summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2024-12-01 15:05:53 -0500
committerDavid Robillard <d@drobilla.net>2024-12-01 20:12:42 -0500
commit1441f47023151f4e1ae12f1b86ce68fa341c3a14 (patch)
tree966593cc8e8edba1e3498766e078f991c70631e1
parentdb931e680f68aec9756afb2a3542782415163814 (diff)
downloadsuil-1441f47023151f4e1ae12f1b86ce68fa341c3a14.tar.gz
suil-1441f47023151f4e1ae12f1b86ce68fa341c3a14.tar.bz2
suil-1441f47023151f4e1ae12f1b86ce68fa341c3a14.zip
Factor out general X11 utilities
-rw-r--r--meson.build4
-rw-r--r--src/x11_in_gtk2.c66
-rw-r--r--src/x11_in_gtk3.c55
-rw-r--r--src/x11_util.c56
-rw-r--r--src/x11_util.h20
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