From adc05ae6b7e369d31a052e373b1f08a1928a86bc Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 6 Apr 2011 16:39:07 +0200 Subject: [PATCH] [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 8f3e57d69e..94d9b2e4e9 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(""); @@ -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 ae2d964aa3..3ed9a79a42 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 b791579e50..3e9be851ca 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 c94eb090d2..a6e47c97ac 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 b33dd9c3f2..517977bd46 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 4fd138fd3e..5b67ea91d0 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); } }