diff options
author | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2017-08-18 20:09:15 -0300 |
---|---|---|
committer | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2017-09-19 22:08:39 -0300 |
commit | a1fa001e8c0f97ed6fd1a7a87d1cbf5f497ed09c (patch) | |
tree | ed6173c983c8bf10f63ca95f26e05f83458a9323 | |
parent | aac6d044dbabbaac63c2b9f0b59efb69671de446 (diff) | |
download | gtk+-a1fa001e8c0f97ed6fd1a7a87d1cbf5f497ed09c.tar.gz |
x11: Add support for _GTK_EDGE_CONSTRAINTS atom
Following the previous patch, where edge constraints support
was added to the Wayland backend, this patch introduces the
necessary code to handle the _GTK_EDGE_CONSTRAINTS atom from
X11 backend.
https://bugzilla.gnome.org/show_bug.cgi?id=783669
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 205 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.h | 3 |
2 files changed, 193 insertions, 15 deletions
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index ad65e297b1..e9a263f23d 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -190,6 +190,147 @@ gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface) } static void +do_edge_constraint_state_check (GdkWindow *window, + GdkWindowState old_state, + GdkWindowState *set, + GdkWindowState *unset) +{ + GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); + GdkWindowState local_set, local_unset; + GdkScreen *screen = GDK_WINDOW_SCREEN (window); + guint edge_constraints; + + local_set = *set; + local_unset = *unset; + edge_constraints = toplevel->edge_constraints; + + /* If the WM doesn't support _GTK_EDGE_CONSTRAINTS, rely on the fallback + * implementation. If it supports _GTK_EDGE_CONSTRAINTS, however, remove + * the GDK_WINDOW_STATE_TILED flag explicitly. + */ + if (!gdk_x11_screen_supports_net_wm_hint (screen, + gdk_atom_intern_static_string ("_GTK_EDGE_CONSTRAINTS"))) + { + /* FIXME: we rely on implementation details of mutter here: + * mutter only tiles horizontally, and sets maxvert when it does + * and if it tiles, it always affects all edges + */ + if (old_state & GDK_WINDOW_STATE_TILED) + { + if (!toplevel->have_maxvert) + local_unset |= GDK_WINDOW_STATE_TILED; + } + else + { + if (toplevel->have_maxvert && !toplevel->have_maxhorz) + local_set |= GDK_WINDOW_STATE_TILED; + } + } + else + { + if (!(old_state & GDK_WINDOW_STATE_TILED)) + { + local_set |= GDK_WINDOW_STATE_TILED; + } + } + + /* Top edge */ + if (old_state & GDK_WINDOW_STATE_TOP_TILED) + { + if ((edge_constraints & GDK_WINDOW_STATE_TOP_TILED) == 0) + local_unset |= GDK_WINDOW_STATE_TOP_TILED; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_TOP_TILED) + local_set |= GDK_WINDOW_STATE_TOP_TILED; + } + + if (old_state & GDK_WINDOW_STATE_TOP_RESIZABLE) + { + if ((edge_constraints & GDK_WINDOW_STATE_TOP_RESIZABLE) == 0) + local_unset |= GDK_WINDOW_STATE_TOP_RESIZABLE; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_TOP_RESIZABLE) + local_set |= GDK_WINDOW_STATE_TOP_RESIZABLE; + } + + /* Right edge */ + if (old_state & GDK_WINDOW_STATE_RIGHT_TILED) + { + if ((edge_constraints & GDK_WINDOW_STATE_RIGHT_TILED) == 0) + local_unset |= GDK_WINDOW_STATE_RIGHT_TILED; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_RIGHT_TILED) + local_set |= GDK_WINDOW_STATE_RIGHT_TILED; + } + + if (old_state & GDK_WINDOW_STATE_RIGHT_RESIZABLE) + { + if ((edge_constraints & GDK_WINDOW_STATE_RIGHT_RESIZABLE) == 0) + local_unset |= GDK_WINDOW_STATE_RIGHT_RESIZABLE; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_RIGHT_RESIZABLE) + local_set |= GDK_WINDOW_STATE_RIGHT_RESIZABLE; + } + + /* Bottom edge */ + if (old_state & GDK_WINDOW_STATE_BOTTOM_TILED) + { + if ((edge_constraints & GDK_WINDOW_STATE_BOTTOM_TILED) == 0) + local_unset |= GDK_WINDOW_STATE_BOTTOM_TILED; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_BOTTOM_TILED) + local_set |= GDK_WINDOW_STATE_BOTTOM_TILED; + } + + if (old_state & GDK_WINDOW_STATE_BOTTOM_RESIZABLE) + { + if ((edge_constraints & GDK_WINDOW_STATE_BOTTOM_RESIZABLE) == 0) + local_unset |= GDK_WINDOW_STATE_BOTTOM_RESIZABLE; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_BOTTOM_RESIZABLE) + local_set |= GDK_WINDOW_STATE_BOTTOM_RESIZABLE; + } + + /* Left edge */ + if (old_state & GDK_WINDOW_STATE_LEFT_TILED) + { + if ((edge_constraints & GDK_WINDOW_STATE_LEFT_TILED) == 0) + local_unset |= GDK_WINDOW_STATE_LEFT_TILED; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_LEFT_TILED) + local_set |= GDK_WINDOW_STATE_LEFT_TILED; + } + + if (old_state & GDK_WINDOW_STATE_LEFT_RESIZABLE) + { + if ((edge_constraints & GDK_WINDOW_STATE_LEFT_RESIZABLE) == 0) + local_unset |= GDK_WINDOW_STATE_LEFT_RESIZABLE; + } + else + { + if (edge_constraints & GDK_WINDOW_STATE_LEFT_RESIZABLE) + local_set |= GDK_WINDOW_STATE_LEFT_RESIZABLE; + } + + *set = local_set; + *unset = local_unset; +} + +static void do_net_wm_state_changes (GdkWindow *window) { GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); @@ -242,21 +383,6 @@ do_net_wm_state_changes (GdkWindow *window) set |= GDK_WINDOW_STATE_MAXIMIZED; } - /* FIXME: we rely on implementation details of mutter here: - * mutter only tiles horizontally, and sets maxvert when it does - * and if it tiles, it always affects all edges - */ - if (old_state & GDK_WINDOW_STATE_TILED) - { - if (!toplevel->have_maxvert) - unset |= GDK_WINDOW_STATE_TILED; - } - else - { - if (toplevel->have_maxvert && !toplevel->have_maxhorz) - set |= GDK_WINDOW_STATE_TILED; - } - if (old_state & GDK_WINDOW_STATE_FOCUSED) { if (!toplevel->have_focused) @@ -279,6 +405,9 @@ do_net_wm_state_changes (GdkWindow *window) set |= GDK_WINDOW_STATE_ICONIFIED; } + /* Update edge constraints and tiling */ + do_edge_constraint_state_check (window, old_state, &set, &unset); + gdk_synthesize_window_state (window, unset, set); } @@ -395,6 +524,49 @@ gdk_check_wm_state_changed (GdkWindow *window) do_net_wm_state_changes (window); } +static void +gdk_check_edge_constraints_changed (GdkWindow *window) +{ + GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + + Atom type; + gint format; + gulong nitems; + gulong bytes_after; + guchar *data; + gulong *constraints; + + type = None; + gdk_x11_display_error_trap_push (display); + XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + gdk_x11_get_xatom_by_name_for_display (display, "_GTK_EDGE_CONSTRAINTS"), + 0, G_MAXLONG, False, XA_CARDINAL, &type, + &format, &nitems, + &bytes_after, &data); + gdk_x11_display_error_trap_pop_ignored (display); + + if (type != None) + { + constraints = (gulong *)data; + + /* The GDK enum for these states does not begin at zero so, to avoid + * messing around with shifts, just make the passed value and GDK's + * enum values match by shifting to the first tiled state. + */ + toplevel->edge_constraints = constraints[0] << 9; + + XFree (constraints); + } + else + { + toplevel->edge_constraints = 0; + } + + do_net_wm_state_changes (window); +} + static Window get_event_xwindow (XEvent *xevent) { @@ -879,6 +1051,9 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP")) gdk_check_wm_desktop_changed (window); + + if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_GTK_EDGE_CONSTRAINTS")) + gdk_check_edge_constraints_changed (window); } if (window->event_mask & GDK_PROPERTY_CHANGE_MASK) diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index ed0cbb6cf3..2b5749c4bd 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -166,6 +166,9 @@ struct _GdkToplevelX11 GdkWindowHints last_geometry_hints_mask; GdkGeometry last_geometry_hints; + /* Constrained edge information */ + guint edge_constraints; + #ifdef HAVE_XSYNC XID update_counter; XID extended_update_counter; |