[gtk+] [broadway] Add configure event for browser-side geometry changes



commit adc05ae6b7e369d31a052e373b1f08a1928a86bc
Author: Alexander Larsson <alexl redhat com>
Date:   Wed Apr 6 16:39:07 2011 +0200

    [broadway] Add configure event for browser-side geometry changes
    
    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           |  133 ++++++++++++++++++++++++++++++------
 gdk/broadway/gdkdisplay-broadway.c |   13 ++++
 gdk/broadway/gdkdisplay-broadway.h |   10 +++
 gdk/broadway/gdkeventsource.c      |   24 +++++++
 gdk/broadway/gdkprivate-broadway.h |    1 +
 gdk/broadway/gdkwindow-broadway.c  |    9 ++-
 6 files changed, 166 insertions(+), 24 deletions(-)
---
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 8f3e57d..94d9b2e 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -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();
+    };
 }
diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c
index ae2d964..3ed9a79 100644
--- a/gdk/broadway/gdkdisplay-broadway.c
+++ b/gdk/broadway/gdkdisplay-broadway.c
@@ -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;
diff --git a/gdk/broadway/gdkdisplay-broadway.h b/gdk/broadway/gdkdisplay-broadway.h
index b791579..3e9be85 100644
--- a/gdk/broadway/gdkdisplay-broadway.h
+++ b/gdk/broadway/gdkdisplay-broadway.h
@@ -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
diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c
index c94eb09..a6e47c9 100644
--- a/gdk/broadway/gdkeventsource.c
+++ b/gdk/broadway/gdkeventsource.c
@@ -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;
diff --git a/gdk/broadway/gdkprivate-broadway.h b/gdk/broadway/gdkprivate-broadway.h
index b33dd9c..517977b 100644
--- a/gdk/broadway/gdkprivate-broadway.h
+++ b/gdk/broadway/gdkprivate-broadway.h
@@ -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);
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
index 4fd138f..5b67ea9 100644
--- a/gdk/broadway/gdkwindow-broadway.c
+++ b/gdk/broadway/gdkwindow-broadway.c
@@ -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);
 	}
     }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]