From 7d7a6f6719ddf99a4afefe6ae44f7cba48707d45 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 5 Jun 2022 13:02:58 +0800 Subject: [PATCH] Better respect window manager stacking order * src/xfns.c (x_frame_list_z_order, Fx_frame_list_z_order): Use _NET_CLIENT_LIST_STACKING if supported. * src/xterm.c (x_wm_supports_1): New function. Accept dpyinfo instead of frame. (x_wm_supports): Use that function instead. * src/xterm.h: Update prototypes. --- src/xfns.c | 62 ++++++++++++++++++++++++++++++++++++++++++++--------- src/xterm.c | 12 ++++++++--- src/xterm.h | 1 + 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index e3763a55893..cfc6d4c212e 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6600,17 +6600,61 @@ menu bar or tool bar of FRAME. */) * WINDOW to FRAMES and return FRAMES. */ static Lisp_Object -x_frame_list_z_order (Display* dpy, Window window) +x_frame_list_z_order (struct x_display_info *dpyinfo, Window window) { + Display *dpy; Window root, parent, *children; unsigned int nchildren; - int i; - Lisp_Object frames = Qnil; + unsigned long i; + Lisp_Object frames, val; + Atom type; + Window *toplevels; + int format, rc; + unsigned long nitems, bytes_after; + unsigned char *data; + struct frame *f; + + dpy = dpyinfo->display; + data = NULL; + frames = Qnil; + + if (window == dpyinfo->root_window + && x_wm_supports_1 (dpyinfo, + dpyinfo->Xatom_net_client_list_stacking)) + { + rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_net_client_list_stacking, + 0, LONG_MAX, False, XA_WINDOW, &type, + &format, &nitems, &bytes_after, &data); + + if (rc != Success) + return Qnil; + + if (format != 32 || type != XA_WINDOW) + { + XFree (data); + return Qnil; + } + + toplevels = (Window *) data; + + for (i = 0; i < nitems; ++i) + { + f = x_top_window_to_frame (dpyinfo, toplevels[i]); + + if (f) + { + XSETFRAME (val, f); + frames = Fcons (val, frames); + } + } + + XFree (data); + return frames; + } - block_input (); if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren)) { - unblock_input (); for (i = 0; i < nchildren; i++) { Lisp_Object frame, tail; @@ -6628,10 +6672,9 @@ x_frame_list_z_order (Display* dpy, Window window) } } - if (children) XFree ((char *)children); + if (children) + XFree (children); } - else - unblock_input (); return frames; } @@ -6652,7 +6695,6 @@ Frames are listed from topmost (first) to bottommost (last). */) (Lisp_Object terminal) { struct x_display_info *dpyinfo = check_x_display_info (terminal); - Display *dpy = dpyinfo->display; Window window; if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) @@ -6660,7 +6702,7 @@ Frames are listed from topmost (first) to bottommost (last). */) else window = dpyinfo->root_window; - return x_frame_list_z_order (dpy, window); + return x_frame_list_z_order (dpyinfo, window); } /** diff --git a/src/xterm.c b/src/xterm.c index 2bf37e94d6b..3b60dba69bd 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -22591,17 +22591,16 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) https://freedesktop.org/wiki/Specifications/wm-spec/. */ bool -x_wm_supports (struct frame *f, Atom want_atom) +x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom) { Atom actual_type; unsigned long actual_size, bytes_remaining; int i, rc, actual_format; bool ret; Window wmcheck_window; - struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Window target_window = dpyinfo->root_window; int max_len = 65536; - Display *dpy = FRAME_X_DISPLAY (f); + Display *dpy = dpyinfo->display; unsigned char *tmp_data = NULL; Atom target_type = XA_WINDOW; @@ -22675,6 +22674,13 @@ x_wm_supports (struct frame *f, Atom want_atom) return ret; } +bool +x_wm_supports (struct frame *f, Atom want_atom) +{ + return x_wm_supports_1 (FRAME_DISPLAY_INFO (f), + want_atom); +} + static void set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value) { diff --git a/src/xterm.h b/src/xterm.h index d7e184ed9f1..878cb5fd87b 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1497,6 +1497,7 @@ extern void x_set_shaded (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object); extern bool x_wm_supports (struct frame *, Atom); +extern bool x_wm_supports_1 (struct x_display_info *, Atom); extern void x_wait_for_event (struct frame *, int); extern void x_clear_under_internal_border (struct frame *f); -- 2.39.2