]> source.dussan.org Git - vaadin-framework.git/commitdiff
Centers VOverlays in visual viewport on iOS, Android, fixes #11614
authorMarc Englund <marc@vaadin.com>
Thu, 16 May 2013 13:17:17 +0000 (16:17 +0300)
committerVaadin Code Review <review@vaadin.com>
Fri, 17 May 2013 10:13:23 +0000 (10:13 +0000)
Change-Id: I21fc986b2f4253ad0491a49659db793acf77842d
Ticket: 11614

client/src/com/vaadin/client/ui/VOverlay.java
uitest/src/com/vaadin/tests/components/window/CenteredInVisualViewport.java [new file with mode: 0644]

index d35201460ec6c403b3062c3aec8a1244990a3c62..9e809758cabf562b52cec21c185f5959339d5c95 100644 (file)
@@ -27,6 +27,7 @@ import com.google.gwt.event.logical.shared.CloseEvent;
 import com.google.gwt.event.logical.shared.CloseHandler;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.Widget;
@@ -689,4 +690,68 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
         return container;
     }
 
+    @Override
+    public void center() {
+        super.center();
+
+        // Some devices can be zoomed in, we should center to the visual
+        // viewport for those devices
+        BrowserInfo b = BrowserInfo.get();
+        if (b.isAndroid() || b.isIOS()) {
+            int left = (getVisualViewportWidth() - getOffsetWidth()) >> 1;
+            int top = (getVisualViewportHeight() - getOffsetHeight()) >> 1;
+            setPopupPosition(Math.max(Window.getScrollLeft() + left, 0),
+                    Math.max(Window.getScrollTop() + top, 0));
+        }
+
+    }
+
+    /**
+     * Gets the visual viewport width, which is useful for e.g iOS where the
+     * view can be zoomed in while keeping the layout viewport intact.
+     * 
+     * Falls back to layout viewport; for those browsers/devices the difference
+     * is that the scrollbar with is included (if there is a scrollbar).
+     * 
+     * @since 7.0.7
+     * @return
+     */
+    private int getVisualViewportWidth() {
+        int w = (int) getSubpixelInnerWidth();
+        if (w < 0) {
+            return Window.getClientWidth();
+        } else {
+            return w;
+        }
+    }
+
+    /**
+     * Gets the visual viewport height, which is useful for e.g iOS where the
+     * view can be zoomed in while keeping the layout viewport intact.
+     * 
+     * Falls back to layout viewport; for those browsers/devices the difference
+     * is that the scrollbar with is included (if there is a scrollbar).
+     * 
+     * @since 7.0.7
+     * @return
+     */
+    private int getVisualViewportHeight() {
+        int h = (int) getSubpixelInnerHeight();
+        if (h < 0) {
+            return Window.getClientHeight();
+        } else {
+            return h;
+        }
+    }
+
+    private native double getSubpixelInnerWidth()
+    /*-{
+         return $wnd.innerWidth !== undefined ? $wnd.innerWidth : -1;
+    }-*/;
+
+    private native double getSubpixelInnerHeight()
+    /*-{
+         return $wnd.innerHeight !== undefined ? $wnd.innerHeight :-1;
+    }-*/;
+
 }
diff --git a/uitest/src/com/vaadin/tests/components/window/CenteredInVisualViewport.java b/uitest/src/com/vaadin/tests/components/window/CenteredInVisualViewport.java
new file mode 100644 (file)
index 0000000..428b2ae
--- /dev/null
@@ -0,0 +1,66 @@
+package com.vaadin.tests.components.window;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Window;
+
+public class CenteredInVisualViewport extends TestBase {
+
+    @Override
+    protected String getDescription() {
+        return "Should open centered, even if zoomed in on one button (e.g zoom in iOS)";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 11614;
+    }
+
+    @Override
+    protected void setup() {
+        GridLayout layout = new GridLayout(3, 3);
+        layout.setWidth("1000px");
+        layout.setHeight("1000px");
+        addComponent(layout);
+
+        Button b = new Button("Open", new Button.ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                Window centered = new Window("A window", new Label(
+                        "Centered window"));
+                centered.center();
+                getMainWindow().addWindow(centered);
+            }
+        });
+        layout.addComponent(b, 0, 0);
+
+        b = new Button("Open", new Button.ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                Window centered = new Window("A window", new Label(
+                        "Centered window"));
+                centered.center();
+                getMainWindow().addWindow(centered);
+            }
+        });
+        layout.addComponent(b, 1, 1);
+
+        b = new Button("Open", new Button.ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                Window centered = new Window("A window", new Label(
+                        "Centered window"));
+                centered.center();
+                getMainWindow().addWindow(centered);
+            }
+        });
+        layout.addComponent(b, 2, 2);
+
+    }
+}