diff options
author | David Robillard <d@drobilla.net> | 2024-12-01 15:05:53 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2024-12-01 20:12:42 -0500 |
commit | 1441f47023151f4e1ae12f1b86ce68fa341c3a14 (patch) | |
tree | 966593cc8e8edba1e3498766e078f991c70631e1 | |
parent | db931e680f68aec9756afb2a3542782415163814 (diff) | |
download | suil-1441f47023151f4e1ae12f1b86ce68fa341c3a14.tar.gz suil-1441f47023151f4e1ae12f1b86ce68fa341c3a14.tar.bz2 suil-1441f47023151f4e1ae12f1b86ce68fa341c3a14.zip |
Factor out general X11 utilities
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | src/x11_in_gtk2.c | 66 | ||||
-rw-r--r-- | src/x11_in_gtk3.c | 55 | ||||
-rw-r--r-- | src/x11_util.c | 56 | ||||
-rw-r--r-- | src/x11_util.h | 20 |
5 files changed, 98 insertions, 103 deletions
diff --git a/meson.build b/meson.build index 8feb798..6793bb0 100644 --- a/meson.build +++ b/meson.build @@ -367,7 +367,7 @@ gtk_cpp_args = cpp.get_supported_arguments(gtk_args) if gtk2_dep.found() and gtk2_x11_dep.found() and x11_dep.found() shared_module( 'suil_x11_in_gtk2', - files('src/x11_in_gtk2.c'), + files('src/x11_in_gtk2.c', 'src/x11_util.c'), c_args: c_suppressions + gtk_c_args + platform_defines, dependencies: [gtk2_dep, gtk2_x11_dep, lv2_dep, x11_dep], gnu_symbol_visibility: 'hidden', @@ -381,7 +381,7 @@ endif if gtk3_dep.found() and gtk3_x11_dep.found() and x11_dep.found() shared_module( 'suil_x11_in_gtk3', - files('src/x11_in_gtk3.c'), + files('src/x11_in_gtk3.c', 'src/x11_util.c'), c_args: c_suppressions + gtk_c_args + platform_defines, dependencies: [gtk3_dep, gtk3_x11_dep, lv2_dep, x11_dep], gnu_symbol_visibility: 'hidden', diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c index dafeaea..2828b84 100644 --- a/src/x11_in_gtk2.c +++ b/src/x11_in_gtk2.c @@ -3,6 +3,7 @@ #include "suil_internal.h" #include "warnings.h" +#include "x11_util.h" #include <lv2/core/lv2.h> #include <lv2/options/options.h> @@ -24,7 +25,6 @@ SUIL_DISABLE_GTK_WARNINGS #include <gtk/gtk.h> SUIL_RESTORE_WARNINGS -#include <stdbool.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -54,62 +54,6 @@ suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) -/** - Check if 'swallowed' subwindow is known to the X server. - - Gdk/GTK can mark the window as realized, mapped and visible even though - there is no window-ID on the X server for it yet. Then, - suil_x11_on_size_allocate() will cause a "BadWinow" X error. -*/ -static bool -x_window_is_valid(SuilX11Wrapper* socket) -{ - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - Window root = 0; - Window parent = 0; - Window* children = NULL; - unsigned childcount = 0; - - XQueryTree(GDK_WINDOW_XDISPLAY(window), - GDK_WINDOW_XID(window), - &root, - &parent, - &children, - &childcount); - - for (unsigned i = 0; i < childcount; ++i) { - if (children[i] == (Window)socket->instance->ui_widget) { - XFree(children); - return true; - } - } - - if (children) { - XFree(children); - } - - return false; -} - -static Window -get_parent_window(Display* display, Window child) -{ - Window root = 0; - Window parent = 0; - Window* children = NULL; - unsigned count = 0; - - if (child) { - if (XQueryTree(display, child, &root, &parent, &children, &count)) { - if (children) { - XFree(children); - } - } - } - - return (parent == root) ? 0 : parent; -} - static gboolean on_plug_removed(GtkSocket* sock, gpointer data) { @@ -173,7 +117,7 @@ suil_x11_wrapper_realize(GtkWidget* w) (unsigned char*)&plugin, 1); - xwindow = get_parent_window(GDK_WINDOW_XDISPLAY(gwindow), xwindow); + xwindow = suil_x11_get_parent(GDK_WINDOW_XDISPLAY(gwindow), xwindow); } } @@ -257,7 +201,9 @@ static void forward_size_request(SuilX11Wrapper* socket, GtkAllocation* allocation) { GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - if (x_window_is_valid(socket)) { + if (suil_x11_is_valid_child(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + (Window)socket->instance->ui_widget)) { // Calculate allocation size constrained to X11 limits for widget int width = allocation->width; int height = allocation->height; @@ -448,7 +394,7 @@ wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance) Window xwindow = (Window)instance->ui_widget; gdk_display_sync(display); - if (x_window_is_valid(wrap)) { + if (suil_x11_is_valid_child(xdisplay, GDK_WINDOW_XID(window), xwindow)) { XWindowAttributes attrs; XGetWindowAttributes(xdisplay, xwindow, &attrs); diff --git a/src/x11_in_gtk3.c b/src/x11_in_gtk3.c index 5ac5306..4addc03 100644 --- a/src/x11_in_gtk3.c +++ b/src/x11_in_gtk3.c @@ -3,6 +3,7 @@ #include "suil_internal.h" #include "warnings.h" +#include "x11_util.h" #include <lv2/core/lv2.h> #include <lv2/options/options.h> @@ -24,7 +25,6 @@ SUIL_DISABLE_GTK_WARNINGS #include <gtk/gtkx.h> SUIL_RESTORE_WARNINGS -#include <stdbool.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -57,39 +57,6 @@ suil_x11_wrapper_get_type(void); // Accessor for SUIL_TYPE_X11_WRAPPER G_DEFINE_TYPE(SuilX11Wrapper, suil_x11_wrapper, GTK_TYPE_SOCKET) -/** - Check if 'swallowed' subwindow is known to the X server. - - Gdk/GTK can mark the window as realized, mapped and visible even though - there is no window-ID on the X server for it yet. Then, - suil_x11_on_size_allocate() will cause a "BadWinow" X error. -*/ -static bool -x_window_is_valid(SuilX11Wrapper* socket) -{ - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - Window root = 0; - Window parent = 0; - Window* children = NULL; - unsigned childcount = 0; - - XQueryTree(GDK_WINDOW_XDISPLAY(window), - GDK_WINDOW_XID(window), - &root, - &parent, - &children, - &childcount); - for (unsigned i = 0; i < childcount; ++i) { - if (children[i] == (Window)socket->instance->ui_widget) { - XFree(children); - return true; - } - } - - XFree(children); - return false; -} - static gboolean on_plug_removed(GtkSocket* sock, gpointer data) { @@ -212,7 +179,9 @@ static void forward_size_request(SuilX11Wrapper* socket, GtkAllocation* allocation) { GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(socket->plug)); - if (x_window_is_valid(socket)) { + if (suil_x11_is_valid_child(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + (Window)socket->instance->ui_widget)) { // Calculate allocation size constrained to X11 limits for widget int width = allocation->width; int height = allocation->height; @@ -281,9 +250,11 @@ suil_x11_wrapper_get_preferred_width(GtkWidget* widget, gint* minimum_width, gint* natural_width) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - if (x_window_is_valid(self)) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self->plug)); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + GdkWindow* const window = gtk_widget_get_window(GTK_WIDGET(self->plug)); + if (suil_x11_is_valid_child(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + (Window)self->instance->ui_widget)) { XSizeHints hints; memset(&hints, 0, sizeof(hints)); long supplied = 0; @@ -305,9 +276,11 @@ suil_x11_wrapper_get_preferred_height(GtkWidget* widget, gint* minimum_height, gint* natural_height) { - SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); - if (x_window_is_valid(self)) { - GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self->plug)); + SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget); + GdkWindow* const window = gtk_widget_get_window(GTK_WIDGET(self->plug)); + if (suil_x11_is_valid_child(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + (Window)self->instance->ui_widget)) { XSizeHints hints; memset(&hints, 0, sizeof(hints)); long supplied = 0; diff --git a/src/x11_util.c b/src/x11_util.c new file mode 100644 index 0000000..f5f1c87 --- /dev/null +++ b/src/x11_util.c @@ -0,0 +1,56 @@ +// Copyright 2020-2024 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include "x11_util.h" + +#include <X11/X.h> +#include <X11/Xlib.h> + +#include <stddef.h> + +bool +suil_x11_is_valid_child(Display* const display, + const Window parent, + const Window child) +{ + Window root = 0U; + Window grandparent = 0U; + Window* children = NULL; + unsigned n_children = 0U; + + XQueryTree(display, parent, &root, &grandparent, &children, &n_children); + + for (unsigned i = 0U; i < n_children; ++i) { + if (children[i] == child) { + if (children) { + XFree(children); + } + return true; + } + } + + if (children) { + XFree(children); + } + + return false; +} + +Window +suil_x11_get_parent(Display* display, Window child) +{ + Window root = 0U; + Window parent = 0U; + Window* children = NULL; + unsigned count = 0U; + + if (child) { + if (XQueryTree(display, child, &root, &parent, &children, &count)) { + if (children) { + XFree(children); + } + } + } + + return (parent == root) ? 0 : parent; +} diff --git a/src/x11_util.h b/src/x11_util.h new file mode 100644 index 0000000..7ca2e7c --- /dev/null +++ b/src/x11_util.h @@ -0,0 +1,20 @@ +// Copyright 2020-2024 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#ifndef SUIL_X11_UTIL +#define SUIL_X11_UTIL + +#include <X11/X.h> +#include <X11/Xlib.h> + +#include <stdbool.h> + +/// Return whether `child` can be found in the subtree under `parent` +bool +suil_x11_is_valid_child(Display* display, Window parent, Window child); + +/// Return the non-root parent window of `child` if it has one, or zero +Window +suil_x11_get_parent(Display* display, Window child); + +#endif // SUIL_X11_UTIL |