[mutter/wip/carlosg/frames-client: 996/1005] x11: Integrate frames client into Mutter




commit 7a20ea97b509e5f64d68b020cbf54d4d7949a8e8
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Sep 8 10:35:47 2022 +0200

    x11: Integrate frames client into Mutter

 src/core/display.c                |   6 +-
 src/core/events.c                 |  23 +--
 src/core/frame.c                  | 332 +++++++++++++++++++++++++++-----------
 src/core/frame.h                  |  15 +-
 src/core/window-private.h         |   6 +-
 src/core/window.c                 |  30 +---
 src/x11/atomnames.h               |   3 +
 src/x11/events.c                  |  46 ++++--
 src/x11/meta-x11-display.c        |   9 +-
 src/x11/meta-x11-window-control.c |   3 -
 src/x11/window-props.c            |   3 -
 src/x11/window-x11-private.h      |   2 +
 src/x11/window-x11.c              |  37 ++++-
 13 files changed, 332 insertions(+), 183 deletions(-)
---
diff --git a/src/core/display.c b/src/core/display.c
index fb92244164..9d9f936e28 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -974,6 +974,8 @@ meta_display_new (MetaContext  *context,
       return NULL;
     }
 
+  meta_frame_initialize (display);
+
   if (display->x11_display)
     {
       g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
@@ -2105,10 +2107,6 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display)
 
       meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
       meta_window_frame_size_changed (window);
-      if (window->frame)
-        {
-          meta_frame_queue_draw (window->frame);
-        }
 
       tmp = tmp->next;
     }
diff --git a/src/core/events.c b/src/core/events.c
index eca21f52e5..8298620741 100644
--- a/src/core/events.c
+++ b/src/core/events.c
@@ -463,27 +463,8 @@ meta_display_handle_event (MetaDisplay        *display,
        *   trigger ::captured-event handlers along the way.
        */
       bypass_clutter = !IS_GESTURE_EVENT (event);
-
-      /* When double clicking to un-maximize an X11 window under Wayland,
-       * there is a race between X11 and Wayland protocols and the X11
-       * XConfigureWindow may be processed by Xwayland before the button
-       * press event is forwarded via the Wayland protocol.
-       * As a result, the second click may reach another X11 window placed
-       * immediately underneath in the X11 stack.
-       * The following is to make sure we do not forward the button press
-       * event to Wayland if it was handled by the frame UI.
-       * See: https://gitlab.gnome.org/GNOME/mutter/issues/88
-       */
-      if (meta_window_handle_ui_frame_event (window, event))
-        {
-          bypass_wayland = (event->type == CLUTTER_BUTTON_PRESS ||
-                            event->type == CLUTTER_TOUCH_BEGIN);
-        }
-      else
-        {
-          bypass_wayland = meta_window_has_modals (window);
-          meta_window_handle_ungrabbed_event (window, event);
-        }
+      bypass_wayland = meta_window_has_modals (window);
+      meta_window_handle_ungrabbed_event (window, event);
 
       /* This might start a grab op. If it does, then filter out the
        * event, and if it doesn't, replay the event to release our
diff --git a/src/core/frame.c b/src/core/frame.c
index 9c8cbb9464..f7981af75e 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -31,24 +31,46 @@
 #include "meta/meta-x11-errors.h"
 #include "x11/meta-x11-display-private.h"
 
+#include <X11/Xatom.h>
+
 #define EVENT_MASK (SubstructureRedirectMask |                     \
                     StructureNotifyMask | SubstructureNotifyMask | \
-                    ExposureMask | FocusChangeMask)
+                    PropertyChangeMask | FocusChangeMask)
+
+static void on_frames_died (GObject      *source,
+                            GAsyncResult *result,
+                            gpointer      user_data);
 
 void
 meta_window_ensure_frame (MetaWindow *window)
 {
-  MetaFrame *frame;
+  MetaX11Display *x11_display = window->display->x11_display;
+  unsigned long data[1] = { 1 };
+
+  meta_x11_error_trap_push (x11_display);
+
+  XChangeProperty (x11_display->xdisplay,
+                   window->xwindow,
+                   x11_display->atom__MUTTER_NEEDS_FRAME,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+
+  meta_x11_error_trap_pop (x11_display);
+}
+
+void
+meta_window_set_frame_xwindow (MetaWindow *window,
+                               Window      xframe)
+{
+  MetaX11Display *x11_display = window->display->x11_display;
   XSetWindowAttributes attrs;
-  gulong create_serial;
-  MetaX11Display *x11_display;
+  gulong create_serial = 0;
+  MetaFrame *frame;
 
   if (window->frame)
     return;
 
-  x11_display = window->display->x11_display;
-
-  frame = g_new (MetaFrame, 1);
+  frame = g_new0 (MetaFrame, 1);
 
   frame->window = window;
   frame->xwindow = None;
@@ -58,24 +80,22 @@ meta_window_ensure_frame (MetaWindow *window)
   frame->child_y = 0;
   frame->bottom_height = 0;
   frame->right_width = 0;
-  frame->current_cursor = 0;
 
   frame->borders_cached = FALSE;
 
+  window->frame = frame;
+
   meta_verbose ("Frame geometry %d,%d  %dx%d",
                 frame->rect.x, frame->rect.y,
                 frame->rect.width, frame->rect.height);
 
-  frame->ui_frame = meta_ui_create_frame (x11_display->ui,
-                                          x11_display->xdisplay,
-                                          frame->window,
-                                          window->xvisual,
-                                          frame->rect.x,
-                                          frame->rect.y,
-                                          frame->rect.width,
-                                          frame->rect.height,
-                                          &create_serial);
-  frame->xwindow = frame->ui_frame->xwindow;
+  meta_verbose ("Setting frame 0x%lx for window %s, "
+                "frame geometry %d,%d  %dx%d",
+                xframe, window->desc,
+                frame->rect.x, frame->rect.y,
+                frame->rect.width, frame->rect.height);
+
+  frame->xwindow = xframe;
 
   meta_stack_tracker_record_add (window->display->stack_tracker,
                                  frame->xwindow,
@@ -120,40 +140,7 @@ meta_window_ensure_frame (MetaWindow *window)
   /* stick frame to the window */
   window->frame = frame;
 
-  /* Now that frame->xwindow is registered with window, we can set its
-   * style and background.
-   */
-  meta_frame_update_style (frame);
-  meta_frame_update_title (frame);
-
-  meta_ui_map_frame (x11_display->ui, frame->xwindow);
-
-  {
-    MetaBackend *backend = meta_get_backend ();
-    if (META_IS_BACKEND_X11 (backend))
-      {
-        Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
-
-        /* Since the backend selects for events on another connection,
-         * make sure to sync the GTK+ connection to ensure that the
-         * frame window has been created on the server at this point. */
-        XSync (x11_display->xdisplay, False);
-
-        unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
-        XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
-        XISelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
-                        frame->xwindow, &mask, 1);
-
-        XISetMask (mask.mask, XI_ButtonPress);
-        XISetMask (mask.mask, XI_ButtonRelease);
-        XISetMask (mask.mask, XI_Motion);
-        XISetMask (mask.mask, XI_Enter);
-        XISetMask (mask.mask, XI_Leave);
-
-        XISelectEvents (xdisplay, frame->xwindow, &mask, 1);
-      }
-  }
+  XMapWindow (x11_display->xdisplay, frame->xwindow);
 
   /* Move keybindings to frame instead of window */
   meta_window_grab_keys (window);
@@ -212,8 +199,6 @@ meta_window_destroy_frame (MetaWindow *window)
 
   meta_x11_error_trap_pop (x11_display);
 
-  meta_ui_frame_unmanage (frame->ui_frame);
-
   /* Ensure focus is restored after the unmap/map events triggered
    * by XReparentWindow().
    */
@@ -318,6 +303,80 @@ meta_frame_borders_clear (MetaFrameBorders *self)
   self->visible.right  = self->invisible.right  = self->total.right  = 0;
 }
 
+static void
+meta_frame_query_borders (MetaFrame        *frame,
+                          MetaFrameBorders *borders)
+{
+  MetaWindow *window = frame->window;
+  MetaX11Display *x11_display = window->display->x11_display;
+  int format, res;
+  Atom type;
+  unsigned long nitems, bytes_after;
+  unsigned char *data;
+
+  if (!frame->xwindow)
+    return;
+
+  meta_x11_error_trap_push (x11_display);
+
+  res = XGetWindowProperty (x11_display->xdisplay,
+                            frame->xwindow,
+                            x11_display->atom__GTK_FRAME_EXTENTS,
+                            0, 4,
+                            False, XA_CARDINAL,
+                            &type, &format,
+                            &nitems, &bytes_after,
+                            (unsigned char **) &data);
+
+  if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
+    return;
+
+  if (res == Success && nitems == 4)
+    {
+      borders->invisible = (GtkBorder) {
+        ((long *) data)[0],
+        ((long *) data)[1],
+        ((long *) data)[2],
+        ((long *) data)[3],
+      };
+    }
+
+  g_clear_pointer (&data, XFree);
+
+  meta_x11_error_trap_push (x11_display);
+
+  res = XGetWindowProperty (x11_display->xdisplay,
+                            frame->xwindow,
+                            x11_display->atom__MUTTER_FRAME_EXTENTS,
+                            0, 4,
+                            False, XA_CARDINAL,
+                            &type, &format,
+                            &nitems, &bytes_after,
+                            (unsigned char **) &data);
+
+  if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
+    return;
+
+  if (res == Success && nitems == 4)
+    {
+      borders->visible = (GtkBorder) {
+        ((long *) data)[0],
+        ((long *) data)[1],
+        ((long *) data)[2],
+        ((long *) data)[3],
+      };
+    }
+
+  g_clear_pointer (&data, XFree);
+
+  borders->total = (GtkBorder) {
+    borders->invisible.left + frame->cached_borders.visible.left,
+    borders->invisible.right + frame->cached_borders.visible.right,
+    borders->invisible.top + frame->cached_borders.visible.top,
+    borders->invisible.bottom + frame->cached_borders.visible.bottom,
+  };
+}
+
 void
 meta_frame_calc_borders (MetaFrame        *frame,
                          MetaFrameBorders *borders)
@@ -330,7 +389,7 @@ meta_frame_calc_borders (MetaFrame        *frame,
     {
       if (!frame->borders_cached)
         {
-          meta_ui_frame_get_borders (frame->ui_frame, &frame->cached_borders);
+          meta_frame_query_borders (frame, &frame->cached_borders);
           frame->borders_cached = TRUE;
         }
 
@@ -348,6 +407,9 @@ gboolean
 meta_frame_sync_to_window (MetaFrame *frame,
                            gboolean   need_resize)
 {
+  MetaWindow *window = frame->window;
+  MetaX11Display *x11_display = window->display->x11_display;
+
   meta_topic (META_DEBUG_GEOMETRY,
               "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)",
               frame->rect.x, frame->rect.y,
@@ -355,11 +417,16 @@ meta_frame_sync_to_window (MetaFrame *frame,
               frame->rect.x + frame->rect.width,
               frame->rect.y + frame->rect.height);
 
-  meta_ui_frame_move_resize (frame->ui_frame,
-                            frame->rect.x,
-                            frame->rect.y,
-                            frame->rect.width,
-                            frame->rect.height);
+  meta_x11_error_trap_push (x11_display);
+
+  XMoveResizeWindow (x11_display->xdisplay,
+                     frame->xwindow,
+                     frame->rect.x,
+                     frame->rect.y,
+                     frame->rect.width,
+                     frame->rect.height);
+
+  meta_x11_error_trap_pop (x11_display);
 
   return need_resize;
 }
@@ -367,7 +434,21 @@ meta_frame_sync_to_window (MetaFrame *frame,
 cairo_region_t *
 meta_frame_get_frame_bounds (MetaFrame *frame)
 {
-  return meta_ui_frame_get_bounds (frame->ui_frame);
+  MetaFrameBorders borders;
+  cairo_region_t *bounds;
+
+  meta_frame_calc_borders (frame, &borders);
+  /* FIXME: currently just the client area, should shape closer to
+   * frame border, incl. rounded corners.
+   */
+  bounds = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+    borders.total.left,
+    borders.total.top,
+    frame->rect.width - borders.total.left - borders.total.right,
+    frame->rect.height - borders.total.top - borders.total.bottom,
+  });
+
+  return bounds;
 }
 
 void
@@ -375,53 +456,124 @@ meta_frame_get_mask (MetaFrame             *frame,
                      cairo_rectangle_int_t *frame_rect,
                      cairo_t               *cr)
 {
-  meta_ui_frame_get_mask (frame->ui_frame, frame_rect, cr);
+  MetaFrameBorders borders;
+
+  meta_frame_calc_borders (frame, &borders);
+
+  cairo_rectangle (cr,
+                   borders.invisible.left,
+                   borders.invisible.top,
+                   frame_rect->width,
+                   frame_rect->height);
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_fill (cr);
 }
 
-void
-meta_frame_queue_draw (MetaFrame *frame)
+Window
+meta_frame_get_xwindow (MetaFrame *frame)
 {
-  meta_ui_frame_queue_draw (frame->ui_frame);
+  return frame->xwindow;
 }
 
-void
-meta_frame_set_screen_cursor (MetaFrame        *frame,
-                             MetaCursor cursor)
+gboolean
+meta_frame_handle_xevent (MetaFrame *frame,
+                          XEvent    *xevent)
 {
-  MetaX11Display *x11_display;
-  Cursor xcursor;
-  if (cursor == frame->current_cursor)
-    return;
+  MetaWindow *window = frame->window;
+  MetaX11Display *x11_display = window->display->x11_display;
 
-  frame->current_cursor = cursor;
-  x11_display = frame->window->display->x11_display;
+  if (xevent->xany.type == PropertyNotify &&
+      xevent->xproperty.state == PropertyNewValue &&
+      (xevent->xproperty.atom == x11_display->atom__GTK_FRAME_EXTENTS ||
+       xevent->xproperty.atom == x11_display->atom__MUTTER_FRAME_EXTENTS))
+    {
+      meta_window_frame_size_changed (window);
+      meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
+      return TRUE;
+    }
 
-  if (cursor == META_CURSOR_DEFAULT)
-    XUndefineCursor (x11_display->xdisplay, frame->xwindow);
-  else
+  return FALSE;
+}
+
+static void
+on_x11_display_setup (MetaDisplay *display,
+                      gpointer     user_data)
+{
+  g_autoptr(GSubprocessLauncher) launcher = NULL;
+  g_autoptr (GError) error = NULL;
+  GSubprocess *proc;
+  const char *args[2];
+
+  args[0] = MUTTER_LIBEXECDIR "/mutter-x11-frames";
+  args[1] = NULL;
+
+  launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
+  g_subprocess_launcher_setenv (launcher, "DISPLAY",
+                                meta_x11_get_display_name (), TRUE);
+
+  proc = g_subprocess_launcher_spawnv (launcher, args, &error);
+  if (error)
     {
-      xcursor = meta_x11_display_create_x_cursor (x11_display, cursor);
-      XDefineCursor (x11_display->xdisplay, frame->xwindow, xcursor);
-      XFlush (x11_display->xdisplay);
-      XFreeCursor (x11_display->xdisplay, xcursor);
+      g_warning ("Could not launch X11 frames client: %s", error->message);
+      return;
     }
+
+  g_subprocess_wait_async (proc, NULL, on_frames_died, display);
+
+  g_object_set_data_full (G_OBJECT (display), "meta-x11-frames-process",
+                          proc, g_object_unref);
 }
 
-Window
-meta_frame_get_xwindow (MetaFrame *frame)
+static void
+on_x11_display_closing (MetaDisplay *display,
+                        gpointer     user_data)
 {
-  return frame->xwindow;
+  g_autoptr (GSubprocess) proc = NULL;
+
+  proc = g_object_get_data (G_OBJECT (display), "meta-x11-frames-process");
+  if (proc)
+    g_subprocess_send_signal (proc, SIGTERM);
 }
 
-void
-meta_frame_update_style (MetaFrame *frame)
+static void
+on_frames_died (GObject      *source,
+                GAsyncResult *result,
+                gpointer      user_data)
 {
-  meta_ui_frame_update_style (frame->ui_frame);
+  GSubprocess *proc = G_SUBPROCESS (source);
+  g_autoptr (GError) error = NULL;
+
+  if (!g_subprocess_wait_finish (proc, result, &error))
+    g_warning ("Mutter X11 frames client died: %s\n", error->message);
+
+  if (g_subprocess_get_if_signaled (proc))
+    {
+      int signum;
+
+      signum = g_subprocess_get_term_sig (proc);
+
+      /* Bring it up again, unless it was forcibly closed */
+      if (signum != SIGTERM && signum != SIGKILL)
+        on_x11_display_setup (user_data, NULL);
+    }
 }
 
 void
-meta_frame_update_title (MetaFrame *frame)
+meta_frame_initialize (MetaDisplay *display)
 {
-  if (frame->window->title)
-    meta_ui_frame_set_title (frame->ui_frame, frame->window->title);
+  if (meta_is_wayland_compositor ())
+    {
+      g_signal_connect (display, "x11-display-setup",
+                        G_CALLBACK (on_x11_display_setup),
+                        NULL);
+      g_signal_connect (display, "x11-display-closing",
+                        G_CALLBACK (on_x11_display_closing),
+                        NULL);
+    }
+  else
+    {
+      g_signal_connect (display, "x11-display-opened",
+                        G_CALLBACK (on_x11_display_setup),
+                        NULL);
+    }
 }
diff --git a/src/core/frame.h b/src/core/frame.h
index 61a5ca7255..84fb037927 100644
--- a/src/core/frame.h
+++ b/src/core/frame.h
@@ -23,7 +23,6 @@
 #define META_FRAME_PRIVATE_H
 
 #include "core/window-private.h"
-#include "ui/frames.h"
 
 struct _MetaFrame
 {
@@ -33,8 +32,6 @@ struct _MetaFrame
   /* reparent window */
   Window xwindow;
 
-  MetaCursor current_cursor;
-
   /* This rect is trusted info from where we put the
    * frame, not the result of ConfigureNotify
    */
@@ -48,15 +45,11 @@ struct _MetaFrame
   int right_width;
   int bottom_height;
 
-  guint need_reapply_frame_shape : 1;
   guint borders_cached : 1;
-
-  MetaUIFrame *ui_frame;
 };
 
 void     meta_window_ensure_frame           (MetaWindow *window);
 void     meta_window_destroy_frame          (MetaWindow *window);
-void     meta_frame_queue_draw              (MetaFrame  *frame);
 
 MetaFrameFlags meta_frame_get_flags   (MetaFrame *frame);
 Window         meta_frame_get_xwindow (MetaFrame *frame);
@@ -76,10 +69,8 @@ void meta_frame_get_mask (MetaFrame             *frame,
                           cairo_rectangle_int_t *frame_rect,
                           cairo_t               *cr);
 
-void meta_frame_set_screen_cursor (MetaFrame   *frame,
-                                  MetaCursor   cursor);
-
-void meta_frame_update_style (MetaFrame *frame);
-void meta_frame_update_title (MetaFrame *frame);
+gboolean meta_frame_handle_xevent (MetaFrame *frame,
+                                   XEvent    *event);
+void meta_frame_initialize (MetaDisplay *display);
 
 #endif
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 1e559ddc61..c0468bf783 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -817,9 +817,6 @@ void meta_window_handle_enter (MetaWindow  *window,
                                guint        root_y);
 void meta_window_handle_leave (MetaWindow  *window);
 
-gboolean meta_window_handle_ui_frame_event (MetaWindow         *window,
-                                            const ClutterEvent *event);
-
 void meta_window_handle_ungrabbed_event (MetaWindow         *window,
                                          const ClutterEvent *event);
 
@@ -903,4 +900,7 @@ gboolean meta_window_calculate_bounds (MetaWindow *window,
                                        int        *bounds_width,
                                        int        *bounds_height);
 
+void meta_window_set_frame_xwindow (MetaWindow *window,
+                                    Window      xframe);
+
 #endif
diff --git a/src/core/window.c b/src/core/window.c
index 5c09f6e81c..e9a0255350 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -793,6 +793,10 @@ client_window_should_be_mapped (MetaWindow *window)
     return FALSE;
 #endif
 
+  if (window->client_type == META_WINDOW_CLIENT_TYPE_X11 &&
+      window->decorated && !window->frame)
+    return FALSE;
+
   return !window->shaded;
 }
 
@@ -1712,6 +1716,10 @@ meta_window_should_be_showing (MetaWindow  *window)
     return FALSE;
 #endif
 
+  if (window->client_type == META_WINDOW_CLIENT_TYPE_X11 &&
+      window->decorated && !window->frame)
+    return FALSE;
+
   /* Windows should be showing if they're located on the
    * active workspace and they're showing on their own workspace. */
   return (meta_window_located_on_workspace (window, workspace_manager->active_workspace) &&
@@ -2944,9 +2952,6 @@ meta_window_tile (MetaWindow   *window,
                                      META_MOVE_RESIZE_STATE_CHANGED),
                                     META_GRAVITY_NORTH_WEST,
                                     window->unconstrained_rect);
-
-  if (window->frame)
-    meta_frame_queue_draw (window->frame);
 }
 
 MetaTileMode
@@ -5035,9 +5040,6 @@ meta_window_update_appears_focused (MetaWindow *window)
   meta_window_frame_size_changed (window);
 
   g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_APPEARS_FOCUSED]);
-
-  if (window->frame)
-    meta_frame_queue_draw (window->frame);
 }
 
 static gboolean
@@ -5157,9 +5159,6 @@ meta_window_set_focused_internal (MetaWindow *window,
                             window);
         }
 
-      if (window->frame)
-        meta_frame_queue_draw (window->frame);
-
       /* Ungrab click to focus button since the sync grab can interfere
        * with some things you might do inside the focused window, by
        * causing the client to get funky enter/leave events.
@@ -7833,9 +7832,6 @@ meta_window_set_title (MetaWindow *window,
   g_free (window->title);
   window->title = g_strdup (title);
 
-  if (window->frame)
-    meta_frame_update_title (window->frame);
-
   meta_window_update_desc (window);
 
   g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_TITLE]);
@@ -8216,16 +8212,6 @@ meta_window_handle_leave (MetaWindow *window)
     meta_window_lower (window);
 }
 
-gboolean
-meta_window_handle_ui_frame_event (MetaWindow         *window,
-                                   const ClutterEvent *event)
-{
-  if (!window->frame)
-    return FALSE;
-
-  return meta_ui_frame_handle_event (window->frame->ui_frame, event);
-}
-
 void
 meta_window_handle_ungrabbed_event (MetaWindow         *window,
                                     const ClutterEvent *event)
diff --git a/src/x11/atomnames.h b/src/x11/atomnames.h
index b806e6e9dc..4e2939edb0 100644
--- a/src/x11/atomnames.h
+++ b/src/x11/atomnames.h
@@ -71,6 +71,9 @@ item(_MUTTER_TIMESTAMP_PING)
 item(_MUTTER_FOCUS_SET)
 item(_MUTTER_SENTINEL)
 item(_MUTTER_VERSION)
+item(_MUTTER_FRAME_FOR)
+item(_MUTTER_FRAME_EXTENTS)
+item(_MUTTER_NEEDS_FRAME)
 item(WM_CLIENT_MACHINE)
 item(MANAGER)
 item(TARGETS)
diff --git a/src/x11/events.c b/src/x11/events.c
index 8bacd0d2ab..02a86a1a5f 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -48,6 +48,7 @@
 #include "x11/meta-x11-selection-input-stream-private.h"
 #include "x11/meta-x11-selection-output-stream-private.h"
 #include "x11/window-x11.h"
+#include "x11/window-x11-private.h"
 #include "x11/xprops.h"
 
 #ifdef HAVE_WAYLAND
@@ -965,10 +966,6 @@ handle_input_xevent (MetaX11Display *x11_display,
            meta_x11_display_lookup_x_window (x11_display, modified) :
            NULL;
 
-  /* If this is an event for a GTK+ widget, let GTK+ handle it. */
-  if (meta_ui_window_is_widget (x11_display->ui, modified))
-    return FALSE;
-
   switch (input_event->evtype)
     {
     case XI_Enter:
@@ -1039,10 +1036,6 @@ handle_input_xevent (MetaX11Display *x11_display,
       break;
     }
 
-  /* Don't eat events for GTK frames (we need to update the :hover state on buttons) */
-  if (window && window->frame && modified == window->frame->xwindow)
-    return FALSE;
-
   /* Don't pass these events through to Clutter / GTK+ */
   return TRUE;
 }
@@ -1410,8 +1403,6 @@ handle_other_xevent (MetaX11Display *x11_display,
 
           if (frame_was_receiver)
             {
-              meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or 
be considered a bug",
-                            window->frame->xwindow);
               meta_x11_error_trap_push (x11_display);
               meta_window_destroy_frame (window->frame->window);
               meta_x11_error_trap_pop (x11_display);
@@ -1482,6 +1473,37 @@ handle_other_xevent (MetaX11Display *x11_display,
     case MapRequest:
       if (window == NULL)
         {
+          Atom type;
+          int format;
+          unsigned long nitems, bytes_after, *data;
+
+          /* Check whether the new window is a frame for another window */
+          if (XGetWindowProperty (x11_display->xdisplay,
+                                  event->xmaprequest.window,
+                                  x11_display->atom__MUTTER_FRAME_FOR,
+                                  0, 32, False, XA_WINDOW,
+                                  &type, &format, &nitems, &bytes_after,
+                                  (guchar **) &data) == Success &&
+              nitems == 1)
+            {
+              Window client_window;
+
+              client_window = data[0];
+              XFree (data);
+
+              window = meta_x11_display_lookup_x_window (x11_display,
+                                                         client_window);
+
+              if (window != NULL && window->decorated && !window->frame)
+                {
+                  meta_window_set_frame_xwindow (window,
+                                                 event->xmaprequest.window);
+                  meta_window_x11_initialize_state (window);
+                }
+
+              break;
+            }
+
           window = meta_window_x11_new (display, event->xmaprequest.window,
                                         FALSE, META_COMP_EFFECT_CREATE);
           /* The window might have initial iconic state, but this is a
@@ -1491,7 +1513,6 @@ handle_other_xevent (MetaX11Display *x11_display,
         }
       else if (frame_was_receiver)
         {
-          meta_warning ("Map requests on the frame window are unexpected");
           break;
         }
 
@@ -1587,6 +1608,8 @@ handle_other_xevent (MetaX11Display *x11_display,
           meta_window_x11_property_notify (window, event);
         else if (property_for_window && !frame_was_receiver)
           meta_window_x11_property_notify (property_for_window, event);
+        else if (frame_was_receiver)
+          meta_frame_handle_xevent (window->frame, event);
 
         group = meta_x11_display_lookup_group (x11_display,
                                                event->xproperty.window);
@@ -1640,7 +1663,6 @@ handle_other_xevent (MetaX11Display *x11_display,
             }
           else
 #endif
-          if (!frame_was_receiver)
             meta_window_x11_client_message (window, event);
         }
       else
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 76e0b077b0..f353712bc5 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -34,6 +34,7 @@
 #include "x11/meta-x11-display-private.h"
 
 #include <gdk/gdk.h>
+#include <gdk/gdkx.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -140,12 +141,6 @@ meta_x11_display_dispose (GObject *object)
   meta_x11_selection_shutdown (x11_display);
   meta_x11_display_unmanage_windows (x11_display);
 
-  if (x11_display->ui)
-    {
-      meta_ui_free (x11_display->ui);
-      x11_display->ui = NULL;
-    }
-
   if (x11_display->no_focus_window != None)
     {
       XUnmapWindow (x11_display->xdisplay, x11_display->no_focus_window);
@@ -1254,7 +1249,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
                                         meta_unsigned_long_equal);
 
   x11_display->groups_by_leader = NULL;
-  x11_display->ui = NULL;
   x11_display->composite_overlay_window = None;
   x11_display->guard_window = None;
   x11_display->leader_window = None;
@@ -1320,7 +1314,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
   set_desktop_viewport_hint (x11_display);
   set_desktop_geometry_hint (x11_display);
 
-  x11_display->ui = meta_ui_new (x11_display);
   x11_display->x11_stack = meta_x11_stack_new (x11_display);
 
   x11_display->keys_grabbed = FALSE;
diff --git a/src/x11/meta-x11-window-control.c b/src/x11/meta-x11-window-control.c
index 4754be5498..7788550861 100644
--- a/src/x11/meta-x11-window-control.c
+++ b/src/x11/meta-x11-window-control.c
@@ -211,7 +211,4 @@ meta_x11_wm_set_screen_cursor (MetaX11Display *x11_display,
                                Window          frame_on_screen,
                                MetaCursor      cursor)
 {
-  MetaWindow *window = window_from_frame (x11_display, frame_on_screen);
-
-  meta_frame_set_screen_cursor (window->frame, cursor);
 }
diff --git a/src/x11/window-props.c b/src/x11/window-props.c
index a0a30b39a4..1eb3c990a4 100644
--- a/src/x11/window-props.c
+++ b/src/x11/window-props.c
@@ -1815,9 +1815,6 @@ reload_gtk_theme_variant (MetaWindow    *window,
       g_free (current_variant);
 
       window->gtk_theme_variant = g_strdup (requested_variant);
-
-      if (window->frame)
-        meta_frame_update_style (window->frame);
     }
 }
 
diff --git a/src/x11/window-x11-private.h b/src/x11/window-x11-private.h
index 22c198268d..973fc083b8 100644
--- a/src/x11/window-x11-private.h
+++ b/src/x11/window-x11-private.h
@@ -93,6 +93,8 @@ void meta_window_x11_set_bypass_compositor_hint (MetaWindowX11            *windo
 
 void meta_window_x11_queue_update_icon (MetaWindowX11 *window_x11);
 
+void meta_window_x11_initialize_state (MetaWindow *window);
+
 G_END_DECLS
 
 #endif
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 29330d3962..54d5da275d 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -542,6 +542,15 @@ meta_window_x11_manage (MetaWindow *window)
 
   if (window->decorated)
     meta_window_ensure_frame (window);
+  else
+    meta_window_x11_initialize_state (window);
+}
+
+void
+meta_window_x11_initialize_state (MetaWindow *window)
+{
+  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
+  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 
   /* Now try applying saved stuff from the session */
   {
@@ -1203,7 +1212,7 @@ update_gtk_edge_constraints (MetaWindow *window)
 
   meta_x11_error_trap_push (x11_display);
   XChangeProperty (x11_display->xdisplay,
-                   window->xwindow,
+                   window->frame ? window->frame->xwindow : window->xwindow,
                    x11_display->atom__GTK_EDGE_CONSTRAINTS,
                    XA_CARDINAL, 32, PropModeReplace,
                    (guchar*) data, 1);
@@ -1717,9 +1726,6 @@ meta_window_x11_update_icon (MetaWindowX11 *window_x11,
       g_object_notify (G_OBJECT (window), "icon");
       g_object_notify (G_OBJECT (window), "mini-icon");
       g_object_thaw_notify (G_OBJECT (window));
-
-      if (window->frame)
-        meta_frame_queue_draw (window->frame);
     }
 }
 
@@ -2189,6 +2195,16 @@ meta_window_x11_set_net_wm_state (MetaWindow *window)
                    x11_display->atom__NET_WM_STATE,
                    XA_ATOM,
                    32, PropModeReplace, (guchar*) data, i);
+
+  if (window->frame)
+    {
+      XChangeProperty (x11_display->xdisplay,
+                       window->frame->xwindow,
+                       x11_display->atom__NET_WM_STATE,
+                       XA_ATOM,
+                       32, PropModeReplace, (guchar*) data, i);
+    }
+
   meta_x11_error_trap_pop (x11_display);
 
   if (window->fullscreen)
@@ -3927,10 +3943,21 @@ meta_window_x11_set_allowed_actions_hint (MetaWindow *window)
   meta_verbose ("Setting _NET_WM_ALLOWED_ACTIONS with %d atoms", i);
 
   meta_x11_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay, window->xwindow,
+  XChangeProperty (x11_display->xdisplay,
+                   window->xwindow,
                    x11_display->atom__NET_WM_ALLOWED_ACTIONS,
                    XA_ATOM,
                    32, PropModeReplace, (guchar*) data, i);
+
+  if (window->frame)
+    {
+      XChangeProperty (x11_display->xdisplay,
+                       window->frame->xwindow,
+                       x11_display->atom__NET_WM_ALLOWED_ACTIONS,
+                       XA_ATOM,
+                       32, PropModeReplace, (guchar*) data, i);
+    }
+
   meta_x11_error_trap_pop (x11_display);
 #undef MAX_N_ACTIONS
 }


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