summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2017-08-18 20:09:15 -0300
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2017-09-19 22:08:39 -0300
commita1fa001e8c0f97ed6fd1a7a87d1cbf5f497ed09c (patch)
treeed6173c983c8bf10f63ca95f26e05f83458a9323
parentaac6d044dbabbaac63c2b9f0b59efb69671de446 (diff)
downloadgtk+-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.c205
-rw-r--r--gdk/x11/gdkwindow-x11.h3
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;