]> Pileus Git - ~andy/gtk/commitdiff
[broadway] Add configure event for browser-side geometry changes
authorAlexander Larsson <alexl@redhat.com>
Wed, 6 Apr 2011 14:39:07 +0000 (16:39 +0200)
committerAlexander Larsson <alexl@redhat.com>
Thu, 7 Apr 2011 08:03:17 +0000 (10:03 +0200)
Atm this only works for the useToplevelWindows case, but we can add
a browser wm to make use of it inside the browser too.

gdk/broadway/broadway.js
gdk/broadway/gdkdisplay-broadway.c
gdk/broadway/gdkdisplay-broadway.h
gdk/broadway/gdkeventsource.c
gdk/broadway/gdkprivate-broadway.h
gdk/broadway/gdkwindow-broadway.c

index 8f3e57d69e46dda54cc5b72fed713c1a8ba95f3c..94d9b2e4e9d2354685f9dfd54b9070fad57726b2 100644 (file)
@@ -88,7 +88,27 @@ function resizeBrowserWindow(window, w, h) {
                    h + outerH - innerH);
 }
 
+function resizeCanvas(canvas, w, h)
+{
+    /* Canvas resize clears the data, so we need to save it first */
+    var tmpCanvas = canvas.ownerDocument.createElement("canvas");
+    tmpCanvas.width = canvas.width;
+    tmpCanvas.height = canvas.height;
+    var tmpContext = tmpCanvas.getContext("2d");
+    tmpContext.globalCompositeOperation = "copy";
+    tmpContext.drawImage(canvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
+
+    canvas.width = w;
+    canvas.height = h;
+
+    var context = canvas.getContext("2d");
+
+    context.globalCompositeOperation = "copy";
+    context.drawImage(tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
+}
+
 var useToplevelWindows = false;
+var toplevelWindows = [];
 var grab = new Object();
 grab.window = null;
 grab.ownerEvents = false;
@@ -103,6 +123,9 @@ var windowWithMouse = 0;
 var surfaces = {};
 var outstandingCommands = new Array();
 var inputSocket = null;
+var frameSizeX = -1;
+var frameSizeY = -1;
+
 
 var GDK_CROSSING_NORMAL = 0;
 var GDK_CROSSING_GRAB = 1;
@@ -214,6 +237,67 @@ function ensureSurfaceInDocument(surface, doc)
     }
 }
 
+var windowGeometryTimeout = null;
+
+function updateBrowserWindowGeometry(win) {
+    if (win.closed)
+       return;
+
+    var surface = win.surface;
+
+    var innerW = win.innerWidth;
+    var innerH = win.innerHeight;
+
+    var x = surface.x;
+    var y = surface.y;
+    if (frameSizeX > 0) {
+       x = win.screenX + frameSizeX;
+       y = win.screenY + frameSizeY;
+    }
+
+    if (x != surface.x || y != surface.y ||
+       innerW != surface.width || innerH != surface.height) {
+       var oldX = surface.x;
+       var oldY = surface.y;
+       surface.x = x;
+       surface.y = y;
+       if (surface.width != innerW || surface.height != innerH)
+           resizeCanvas(surface.canvas, innerW, innerH);
+       surface.width = innerW;
+       surface.height = innerH;
+       sendInput ("w", [surface.id, surface.x, surface.y, surface.width, surface.height]);
+       for (id in surfaces) {
+           if (surfaces[id].transientToplevel != null && surfaces[id].transientToplevel == surface) {
+               var childSurface = surfaces[id];
+               childSurface.x += surface.x - oldX;
+               childSurface.y += surface.y - oldY;
+               sendInput ("w", [childSurface.id, childSurface.x, childSurface.y, childSurface.width, childSurface.height]);
+           }
+       }
+    }
+
+}
+
+function registerWindow(win)
+{
+    toplevelWindows.push(win);
+    win.onresize = function(ev) { updateBrowserWindowGeometry(ev.target); };
+    if (!windowGeometryTimeout)
+       windowGeometryTimeout = setInterval(function () { toplevelWindows.forEach(updateBrowserWindowGeometry); }, 2000);
+}
+
+function unregisterWindow(win)
+{
+    var i = toplevelWindows.indexOf(win);
+    if (i >= 0)
+       toplevelWindows.splice(i, 1);
+
+    if (windowGeometryTimeout && toplevelWindows.length == 0) {
+       clearInterval(windowGeometryTimeout);
+       windowGeometryTimeout = null;
+    }
+}
+
 function getTransientToplevel(surface)
 {
     while (surface.transientParent != 0) {
@@ -232,6 +316,7 @@ function cmdCreateSurface(id, x, y, width, height, isTemp)
     surface.visible = false;
     surface.window = null;
     surface.document = document;
+    surface.transientToplevel = null;
 
     var canvas = document.createElement("canvas");
     canvas.width = width;
@@ -269,6 +354,8 @@ function cmdShowSurface(id)
                                  'width='+surface.width+',height='+surface.height+
                                  ',left='+surface.x+',top='+surface.y+',screenX='+surface.x+',screenY='+surface.y+
                                  ',location=no,menubar=no,scrollbars=no,toolbar=no');
+           win.surface = surface;
+           registerWindow(win);
            doc = win.document;
            doc.open();
            doc.write("<body></body>");
@@ -278,11 +365,11 @@ function cmdShowSurface(id)
            xOffset = 0;
            yOffset = 0;
        } else {
-           var transientToplevel = getTransientToplevel(surface);
-           if (transientToplevel) {
-               doc = transientToplevel.window.document;
-               xOffset = surface.x - transientToplevel.x;
-               yOffset = surface.y - transientToplevel.y;
+           surface.transientToplevel = getTransientToplevel(surface);
+           if (surface.transientToplevel) {
+               doc = surface.transientToplevel.window.document;
+               xOffset = surface.x - surface.transientToplevel.x;
+               yOffset = surface.y - surface.transientToplevel.y;
            }
        }
 
@@ -303,12 +390,13 @@ function cmdHideSurface(id)
        return;
     surface.visible = false;
 
-    surfaces[id].canvas.style["display"] = "none";
+    surface.canvas.style["display"] = "none";
 
     // Import the canvas into the main document
     ensureSurfaceInDocument(surface, document);
 
     if (surface.window) {
+       unregisterWindow(surface.window);
        surface.window.close();
        surface.window = null;
     }
@@ -346,7 +434,7 @@ function cmdMoveSurface(id, x, y)
             * However this isn't *strictly* invalid, as any WM could have done whatever it
             * wanted with the positioning of the window.
             */
-           surface.window.moveTo(surface.x, surface.y);
+           //surface.window.moveTo(surface.x, surface.y);
        } else {
            var xOffset = surface.x;
            var yOffset = surface.y;
@@ -373,19 +461,7 @@ function cmdResizeSurface(id, w, h)
     /* Flush any outstanding draw ops before changing size */
     flushSurface(surface);
 
-    /* Canvas resize clears the data, so we need to save it first */
-    var tmpCanvas = surface.document.createElement("canvas");
-    tmpCanvas.width = surface.canvas.width;
-    tmpCanvas.height = surface.canvas.height;
-    var tmpContext = tmpCanvas.getContext("2d");
-    tmpContext.globalCompositeOperation = "copy";
-    tmpContext.drawImage(surface.canvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
-
-    surface.canvas.width = w;
-    surface.canvas.height = h;
-
-    surface.context.globalCompositeOperation = "copy";
-    surface.context.drawImage(tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
+    resizeCanvas(surface.canvas, w, h);
 
     if (surface.window) {
        resizeBrowserWindow(surface.window, w, h);
@@ -649,6 +725,19 @@ function getEffectiveEventTarget (id) {
 
 function updateForEvent(ev) {
     lastTimeStamp = ev.timeStamp;
+    if (ev.target.surface && ev.target.surface.window) {
+       var win = ev.target.surface.window;
+       if (ev.screenX != undefined && ev.clientX != undefined) {
+           var newFrameSizeX = ev.screenX - ev.clientX - win.screenX;
+           var newFrameSizeY = ev.screenY - ev.clientY - win.screenY;
+           if (newFrameSizeX != frameSizeX || newFrameSizeY != frameSizeY) {
+               frameSizeX = newFrameSizeX;
+               frameSizeY = newFrameSizeY;
+               toplevelWindows.forEach(updateBrowserWindowGeometry);
+           }
+       }
+       updateBrowserWindowGeometry(win);
+    }
 }
 
 function onMouseMove (ev) {
@@ -839,4 +928,8 @@ function connect()
        alert("WebSocket not supported, input will not work!");
     }
     setupDocument(document);
+    window.onunload = function (ev) {
+       for (var i = 0; i < toplevelWindows.length; i++)
+           toplevelWindows[i].close();
+    };
 }
index ae2d964aa35da0a44591b4fad93005e2875d9088..3ed9a79a4251c2608669093a964c91119fe3c81b 100644 (file)
@@ -248,6 +248,19 @@ parse_input_message (BroadwayInput *input, const char *message)
     msg.grab_reply.res = strtol(p, &p, 10);
     break;
 
+  case 'w':
+    msg.configure_notify.id = strtol(p, &p, 10);
+    p++; /* Skip , */
+    msg.configure_notify.x = strtol (p, &p, 10);
+    p++; /* Skip , */
+    msg.configure_notify.y = strtol (p, &p, 10);
+    p++; /* Skip , */
+    msg.configure_notify.width = strtol (p, &p, 10);
+    p++; /* Skip , */
+    msg.configure_notify.height = strtol (p, &p, 10);
+    p++; /* Skip , */
+    break;
+
   default:
     g_printerr ("Unknown input command %s\n", message);
     break;
index b791579e50bd31e16eb9823b21294d88403191f3..3e9be851ca22ea759dd651d8af4ffc24c1219fd8 100644 (file)
@@ -87,6 +87,15 @@ typedef struct {
   int res;
 } BroadwayInputGrabReply;
 
+typedef struct {
+  BroadwayInputBaseMsg base;
+  int id;
+  int x;
+  int y;
+  int width;
+  int height;
+} BroadwayInputConfigureNotify;
+
 typedef union {
   BroadwayInputBaseMsg base;
   BroadwayInputPointerMsg pointer;
@@ -95,6 +104,7 @@ typedef union {
   BroadwayInputScrollMsg scroll;
   BroadwayInputKeyMsg key;
   BroadwayInputGrabReply grab_reply;
+  BroadwayInputConfigureNotify configure_notify;
 } BroadwayInputMsg;
 
 struct _GdkBroadwayDisplay
index c94eb090d2b70a16424b79c1dde62928997e1010..a6e47c97ac466b021db4bc2d0692c411b84a7580 100644 (file)
@@ -270,6 +270,30 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
   case 'u':
     _gdk_display_device_grab_update (display, display->core_pointer, NULL, message->base.serial);
     break;
+
+  case 'w':
+    window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->configure_notify.id));
+    if (window)
+      {
+       window->x = message->configure_notify.x;
+       window->y = message->configure_notify.y;
+       window->width = message->configure_notify.width;
+       window->height = message->configure_notify.height;
+       _gdk_window_update_size (window);
+       _gdk_broadway_window_resize_surface (window);
+
+       event = gdk_event_new (GDK_CONFIGURE);
+       event->configure.window = g_object_ref (window);
+       event->configure.x = message->configure_notify.x;
+       event->configure.y = message->configure_notify.y;
+       event->configure.width = message->configure_notify.width;
+       event->configure.height = message->configure_notify.height;
+
+       node = _gdk_event_queue_append (display, event);
+       _gdk_windowing_got_event (display, node, event, message->base.serial);
+      }
+    break;
+
   default:
     g_printerr ("Unknown input command %c\n", message->base.type);
     break;
index b33dd9c3f24de622eaa1a0c2241e349c5947ccd5..517977bd467404ed1bda5f84dd0820c3556062e3 100644 (file)
@@ -207,6 +207,7 @@ gboolean _gdk_broadway_window_simulate_button   (GdkWindow       *window,
                                                 guint            button,
                                                 GdkModifierType  modifiers,
                                                 GdkEventType     button_pressrelease);
+void _gdk_broadway_window_resize_surface        (GdkWindow *window);
 
 void _gdk_broadway_cursor_update_theme (GdkCursor *cursor);
 void _gdk_broadway_cursor_display_finalize (GdkDisplay *display);
index 4fd138fd3efd57330083580177a4c2abecd8bbbc..5b67ea91d0e793a97dcdf594ad32c776e8857cf2 100644 (file)
@@ -368,8 +368,8 @@ _gdk_broadway_display_create_window_impl (GdkDisplay    *display,
                                 window->window_type == GDK_WINDOW_TEMP);
 }
 
-static void
-resize_surface (GdkWindow *window)
+void
+_gdk_broadway_window_resize_surface (GdkWindow *window)
 {
   GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
   cairo_surface_t *old, *last_old;
@@ -396,6 +396,8 @@ resize_surface (GdkWindow *window)
                                   NULL, NULL);
       impl->ref_surface = NULL;
     }
+
+  gdk_window_invalidate_rect (window, NULL, TRUE);
 }
 
 static void
@@ -641,8 +643,7 @@ gdk_window_broadway_move_resize (GdkWindow *window,
 
          window->width = width;
          window->height = height;
-         resize_surface (window);
-         gdk_window_invalidate_rect (window, NULL, TRUE);
+         _gdk_broadway_window_resize_surface (window);
        }
     }