diff --git a/app/build.gradle b/app/build.gradle index d5dbf4dcec..f5e0e7fc47 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -130,6 +130,8 @@ android { buildConfigField "String[]", "SPEECH_SERVICES", "{ com.igalia.wolvic.speech.SpeechServices.MEETKAI }" buildConfigField "Boolean", "SUPPORTS_SYSTEM_NOTIFICATIONS", "false" buildConfigField "Float", "DEFAULT_DENSITY", "1.25f" + buildConfigField "Boolean", "ENABLE_PAGE_ZOOM", "false" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" resValue 'string', 'app_name', 'Wolvic' resValue 'string', 'HOMEPAGE_URL', "https://wolvic.com/start" @@ -360,6 +362,7 @@ android { arguments "-DCHROMIUM=ON" } } + buildConfigField "Boolean", "ENABLE_PAGE_ZOOM", "true" } webkit { diff --git a/app/src/common/chromium/com/igalia/wolvic/browser/api/impl/SessionImpl.java b/app/src/common/chromium/com/igalia/wolvic/browser/api/impl/SessionImpl.java index be083c9ac2..25138cf1e4 100644 --- a/app/src/common/chromium/com/igalia/wolvic/browser/api/impl/SessionImpl.java +++ b/app/src/common/chromium/com/igalia/wolvic/browser/api/impl/SessionImpl.java @@ -3,6 +3,7 @@ import android.graphics.Matrix; import android.view.ViewGroup; +import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -240,6 +241,24 @@ public WTextInput getTextInput() { return mTextInput; } + @AnyThread + @Override + public void pageZoomIn() { + mTab.pageZoomIn(); + } + + @AnyThread + @Override + public void pageZoomOut() { + mTab.pageZoomOut(); + } + + @AnyThread + @Override + public int getCurrentZoomLevel() { + return mTab.getCurrentZoomLevel(); + } + @NonNull @Override public WPanZoomController getPanZoomController() { diff --git a/app/src/common/gecko/com/igalia/wolvic/browser/api/impl/SessionImpl.java b/app/src/common/gecko/com/igalia/wolvic/browser/api/impl/SessionImpl.java index 9a0c1a1934..4a20f74b1d 100644 --- a/app/src/common/gecko/com/igalia/wolvic/browser/api/impl/SessionImpl.java +++ b/app/src/common/gecko/com/igalia/wolvic/browser/api/impl/SessionImpl.java @@ -221,6 +221,15 @@ public WTextInput getTextInput() { return mTextInput; } + @Override + public void pageZoomIn() {} + + @Override + public void pageZoomOut() {} + + @Override + public int getCurrentZoomLevel() { return 0; } + @NonNull @Override public WPanZoomController getPanZoomController() { diff --git a/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java b/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java index d841763400..91e68acda0 100644 --- a/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java +++ b/app/src/common/shared/com/igalia/wolvic/VRBrowserActivity.java @@ -1969,6 +1969,11 @@ public boolean isPassthroughSupported() { (DeviceType.isPicoXR() && Build.ID.compareTo(kPicoVersionPassthroughUpdate) >= 0); } + @Override + public boolean isPageZoomEnabled() { + return BuildConfig.ENABLE_PAGE_ZOOM; + } + @Override public void setHeadLockEnabled(boolean isHeadLockEnabled) { queueRunnable(() -> { diff --git a/app/src/common/shared/com/igalia/wolvic/browser/api/WSession.java b/app/src/common/shared/com/igalia/wolvic/browser/api/WSession.java index ec28e2071d..e2356ff618 100644 --- a/app/src/common/shared/com/igalia/wolvic/browser/api/WSession.java +++ b/app/src/common/shared/com/igalia/wolvic/browser/api/WSession.java @@ -2769,6 +2769,15 @@ void dispatchLocation(double latitude, double longitude, double altitude, float WTextInput getTextInput(); + @AnyThread + void pageZoomIn(); + + @AnyThread + void pageZoomOut(); + + @AnyThread + int getCurrentZoomLevel(); + /** * Get the PanZoomController instance for this session. * diff --git a/app/src/common/shared/com/igalia/wolvic/browser/engine/Session.java b/app/src/common/shared/com/igalia/wolvic/browser/engine/Session.java index 619a11315a..c7241c1f97 100644 --- a/app/src/common/shared/com/igalia/wolvic/browser/engine/Session.java +++ b/app/src/common/shared/com/igalia/wolvic/browser/engine/Session.java @@ -1049,6 +1049,25 @@ public void setParentSession(@NonNull Session parentSession) { mState.mParentId = parentSession.getId(); } + public void pageZoomIn() { + if (mState.mSession != null) { + mState.mSession.pageZoomIn(); + } + } + + public void pageZoomOut() { + if (mState.mSession != null) { + mState.mSession.pageZoomOut(); + } + } + + public int getCurrentZoomLevel() { + if (mState.mSession != null) { + return mState.mSession.getCurrentZoomLevel(); + } + return 0; + } + // NavigationDelegate @Override diff --git a/app/src/common/shared/com/igalia/wolvic/ui/adapters/HamburgerMenuAdapter.java b/app/src/common/shared/com/igalia/wolvic/ui/adapters/HamburgerMenuAdapter.java index a1a28ef75d..c31c4f303c 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/adapters/HamburgerMenuAdapter.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/adapters/HamburgerMenuAdapter.java @@ -22,6 +22,7 @@ import com.igalia.wolvic.databinding.HamburgerMenuAddonItemBinding; import com.igalia.wolvic.databinding.HamburgerMenuAddonsSettingsItemBinding; import com.igalia.wolvic.databinding.HamburgerMenuItemBinding; +import com.igalia.wolvic.databinding.HamburgerMenuZoomItemBinding; import com.igalia.wolvic.utils.SystemUtils; import com.igalia.wolvic.utils.ViewUtils; @@ -41,11 +42,12 @@ public class HamburgerMenuAdapter extends RecyclerView.Adapter mCallback; Action mAction; + String mZoomLevel; + Function mZoomCallback; public MenuItem(@NonNull Builder builder) { mItemType = builder.mItemType; @@ -65,6 +69,8 @@ public MenuItem(@NonNull Builder builder) { mIcon = builder.mIcon; mCallback = builder.mCallback; mAction = builder.mAction; + mZoomLevel = builder.mZoomLevel; + mZoomCallback = builder.mZoomCallback;; } public int getItemType() { @@ -107,6 +113,13 @@ public void setIcon(@DrawableRes int icon) { mIcon = icon; } + public void setZoomLevel(String zoomLevel) { + mZoomLevel = zoomLevel; + } + + public String getZoomLevel() { return mZoomLevel; } + + public static class Builder { @MenuItem.MenuItemType @@ -118,6 +131,8 @@ public static class Builder { int mIcon; Function mCallback; Action mAction; + String mZoomLevel; + Function mZoomCallback; public Builder(@MenuItem.MenuItemType int type, @Nullable Function callback) { this.mItemType = type; @@ -149,6 +164,12 @@ public MenuItem.Builder withAction(@Nullable Action action) { return this; } + public MenuItem.Builder withZoom(@NonNull String zoomLevel, Function callback) { + this.mZoomLevel = zoomLevel; + this.mZoomCallback = callback; + return this; + } + public MenuItem build(){ return new MenuItem(this); } @@ -226,6 +247,11 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int parent, false); return new HamburgerMenuItemAddonsSettingsHolder(binding); + } else if (viewType == MenuItem.TYPE_ZOOM) { + HamburgerMenuZoomItemBinding binding = DataBindingUtil + .inflate(LayoutInflater.from(parent.getContext()), R.layout.hamburger_menu_zoom_item, + parent, false); + return new HamburgerMenuZoomItemHolder(binding); } throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly"); @@ -286,6 +312,17 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi viewHolder.binding.container.setOnHoverListener(mHoverListener); ViewUtils.setStickyClickListener(viewHolder.binding.container, callback); setBackground(viewHolder.binding.container, item, position); + } else if (holder instanceof HamburgerMenuZoomItemHolder) { + HamburgerMenuZoomItemHolder viewHolder = (HamburgerMenuZoomItemHolder) holder; + viewHolder.binding.setItem(item); + viewHolder.binding.container.setTag(R.string.position_tag, position); + viewHolder.binding.container.findViewById(R.id.zoomOutImage).setOnClickListener(v -> { + item.mZoomCallback.apply(true); + }); + viewHolder.binding.container.findViewById(R.id.zoomInImage).setOnClickListener(v -> { + item.mZoomCallback.apply(false); + }); + setBackground(viewHolder.binding.container, item, position); } } @@ -401,4 +438,13 @@ static class HamburgerMenuItemAddonsSettingsHolder extends RecyclerView.ViewHold } } + static class HamburgerMenuZoomItemHolder extends RecyclerView.ViewHolder { + + final HamburgerMenuZoomItemBinding binding; + + HamburgerMenuZoomItemHolder(@NonNull HamburgerMenuZoomItemBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + } } diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java index 3b78fd55aa..b5de62c4e2 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/NavigationBarWidget.java @@ -1396,6 +1396,21 @@ public void onSaveWebApp() { showSaveWebAppDialog(); } + + @Override + public void onPageZoomIn() { + mAttachedWindow.getSession().pageZoomIn(); + } + + @Override + public void onPageZoomOut() { + mAttachedWindow.getSession().pageZoomOut(); + } + + @Override + public int getCurrentZoomLevel() { + return mAttachedWindow.getSession().getCurrentZoomLevel(); + } }); boolean isSendTabEnabled = false; if (URLUtil.isHttpUrl(mAttachedWindow.getSession().getCurrentUri()) || diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/WidgetManagerDelegate.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/WidgetManagerDelegate.java index 445c9fa919..9947b7f3af 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/WidgetManagerDelegate.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/WidgetManagerDelegate.java @@ -91,6 +91,7 @@ interface WebXRListener { void togglePassthrough(); boolean isPassthroughEnabled(); boolean isPassthroughSupported(); + boolean isPageZoomEnabled(); void setHeadLockEnabled(boolean isHeadLockEnabled); void recenterUIYaw(@YawTarget int target); void setCylinderDensity(float aDensity); diff --git a/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/HamburgerMenuWidget.java b/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/HamburgerMenuWidget.java index 4bd87ab0bb..1c5dd19b5c 100644 --- a/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/HamburgerMenuWidget.java +++ b/app/src/common/shared/com/igalia/wolvic/ui/widgets/menus/HamburgerMenuWidget.java @@ -51,6 +51,9 @@ public interface MenuDelegate { void onSaveWebApp(); void onPassthrough(); boolean isPassthroughEnabled(); + void onPageZoomIn(); + void onPageZoomOut(); + int getCurrentZoomLevel(); } public static final int SWITCH_ITEM_ID = 0; @@ -313,6 +316,19 @@ private void updateItems() { .build()); } + if (mWidgetManager != null && mWidgetManager.isPageZoomEnabled() && mDelegate != null) { + mItems.add(new HamburgerMenuAdapter.MenuItem.Builder( + HamburgerMenuAdapter.MenuItem.TYPE_ZOOM, null) + .withZoom(Integer.toString(mDelegate.getCurrentZoomLevel()) + "%", + (isZoomOut) -> { + if (isZoomOut) mDelegate.onPageZoomOut(); + else mDelegate.onPageZoomIn(); + updateItems(); + return null; + }) + .build()); + } + mAdapter.setItems(mItems); mAdapter.notifyDataSetChanged(); diff --git a/app/src/main/res/drawable/ic_icon_minus.xml b/app/src/main/res/drawable/ic_icon_minus.xml new file mode 100644 index 0000000000..f53a80e416 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_minus.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_icon_plus.xml b/app/src/main/res/drawable/ic_icon_plus.xml new file mode 100644 index 0000000000..8545554d22 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_plus.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_icon_zoom.xml b/app/src/main/res/drawable/ic_icon_zoom.xml new file mode 100644 index 0000000000..b1cbfd22e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_zoom.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/layout/hamburger_menu_zoom_item.xml b/app/src/main/res/layout/hamburger_menu_zoom_item.xml new file mode 100644 index 0000000000..3f565d2864 --- /dev/null +++ b/app/src/main/res/layout/hamburger_menu_zoom_item.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d8a38427b8..de888d9cff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2061,6 +2061,10 @@ the Select` button. When clicked it closes all the previously selected tabs --> Menu + + Zoom + Move