summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandros Theodotou <alex@zrythm.org>2021-08-27 09:59:34 +0100
committerDavid Robillard <d@drobilla.net>2024-12-01 22:40:20 -0500
commitc8dc495b10e2b761624505f25397aa19e0c88dbf (patch)
treed50b19f7cef44decc1f1fe11062de7b45a1af3bf
parent038c7bb05ad514bc69c43ec877d2e7b4dee90433 (diff)
downloadsuil-c8dc495b10e2b761624505f25397aa19e0c88dbf.tar.gz
suil-c8dc495b10e2b761624505f25397aa19e0c88dbf.tar.bz2
suil-c8dc495b10e2b761624505f25397aa19e0c88dbf.zip
Monitor size hints for X11 in Gtk3 like in Gtk2
The hints are accessed and cached like in Gtk2, but with the Gtk3 size model, we can explicitly use the minimum size, and figure out the "natural" size from the other hints or current size.
-rw-r--r--AUTHORS2
-rw-r--r--NEWS3
-rw-r--r--src/x11_in_gtk3.c130
3 files changed, 96 insertions, 39 deletions
diff --git a/AUTHORS b/AUTHORS
index 8617acd..7e9e59e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -19,3 +19,5 @@ Contributors:
* Stefan Westerfeld
* Qt5 in Gtk2 support
* Initialization API
+ * Alexandros Theodotou
+ * X11 in Gtk3 improvements
diff --git a/NEWS b/NEWS
index e19ae3d..f608a94 100644
--- a/NEWS
+++ b/NEWS
@@ -2,8 +2,9 @@ suil (0.10.21) unstable; urgency=medium
* Add support for X11 in Qt6
* Fix library current_version on MacOS
+ * Monitor size hints for X11 in Gtk3
- -- David Robillard <d@drobilla.net> Thu, 11 Jul 2024 23:40:43 +0000
+ -- David Robillard <d@drobilla.net> Mon, 02 Dec 2024 03:05:37 +0000
suil (0.10.20) stable; urgency=medium
diff --git a/src/x11_in_gtk3.c b/src/x11_in_gtk3.c
index 0a1aaf9..138fdcb 100644
--- a/src/x11_in_gtk3.c
+++ b/src/x11_in_gtk3.c
@@ -39,10 +39,8 @@ typedef struct {
guint idle_id;
guint idle_ms;
guint idle_size_request_id;
- int initial_width;
- int initial_height;
- int req_width;
- int req_height;
+ XSizeHints size_hints;
+ gboolean size_hints_dirty;
} SuilX11Wrapper;
typedef struct {
@@ -197,6 +195,32 @@ idle_size_request(gpointer user_data)
}
static void
+update_wm_hints(SuilX11Wrapper* wrap, gboolean force)
+{
+ const XSizeHints old_hints = wrap->size_hints;
+ if (!wrap->size_hints_dirty && !force) {
+ return;
+ }
+
+ // Fetch hints from X
+ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug));
+ long supplied = 0;
+ XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window),
+ (Window)wrap->instance->ui_widget,
+ &wrap->size_hints,
+ &supplied);
+
+ // Preserve old "custom" size if necessary
+ if ((old_hints.flags & USSize) && old_hints.x && old_hints.y) {
+ wrap->size_hints.flags |= USSize;
+ wrap->size_hints.x = old_hints.x;
+ wrap->size_hints.y = old_hints.y;
+ }
+
+ wrap->size_hints_dirty = FALSE;
+}
+
+static void
forward_size_request(SuilX11Wrapper* socket, GtkAllocation* allocation)
{
GdkWindow* gwindow = gtk_widget_get_window(GTK_WIDGET(socket->plug));
@@ -266,16 +290,24 @@ suil_x11_wrapper_get_preferred_width(GtkWidget* widget,
Window ui_window = (Window)self->instance->ui_widget;
if (suil_x11_is_valid_child(xdisplay, GDK_WINDOW_XID(gwindow), ui_window)) {
- XSizeHints hints;
- memset(&hints, 0, sizeof(hints));
- long supplied = 0;
- XGetWMNormalHints(xdisplay, ui_window, &hints, &supplied);
- *natural_width =
- ((hints.flags & PBaseSize) ? hints.base_width : self->initial_width);
- *minimum_width =
- ((hints.flags & PMinSize) ? hints.min_width : self->req_width);
- } else {
- *natural_width = *minimum_width = self->req_width;
+ update_wm_hints(self, FALSE);
+
+ if (self->size_hints.flags & USSize) {
+ *natural_width = self->size_hints.width;
+ } else if (self->size_hints.flags & PBaseSize) {
+ *natural_width = self->size_hints.base_width;
+ } else if (self->size_hints.flags & PMinSize) {
+ *natural_width = self->size_hints.min_width;
+ } else {
+ g_warning("UI size hints have no base or minimum size");
+ XWindowAttributes attrs;
+ XGetWindowAttributes(xdisplay, ui_window, &attrs);
+ *natural_width = attrs.width;
+ }
+
+ *minimum_width = (self->size_hints.flags & PMinSize)
+ ? self->size_hints.min_width
+ : *natural_width;
}
}
@@ -290,16 +322,24 @@ suil_x11_wrapper_get_preferred_height(GtkWidget* widget,
Window ui_window = (Window)self->instance->ui_widget;
if (suil_x11_is_valid_child(xdisplay, GDK_WINDOW_XID(gwindow), ui_window)) {
- XSizeHints hints;
- memset(&hints, 0, sizeof(hints));
- long supplied = 0;
- XGetWMNormalHints(xdisplay, ui_window, &hints, &supplied);
- *natural_height =
- ((hints.flags & PBaseSize) ? hints.base_height : self->initial_height);
- *minimum_height =
- ((hints.flags & PMinSize) ? hints.min_height : self->req_height);
- } else {
- *natural_height = *minimum_height = self->req_height;
+ update_wm_hints(self, FALSE);
+
+ if (self->size_hints.flags & USSize) {
+ *natural_height = self->size_hints.height;
+ } else if (self->size_hints.flags & PBaseSize) {
+ *natural_height = self->size_hints.base_height;
+ } else if (self->size_hints.flags & PMinSize) {
+ *natural_height = self->size_hints.min_height;
+ } else {
+ g_warning("UI size hints have no base or minimum size");
+ XWindowAttributes attrs;
+ XGetWindowAttributes(xdisplay, ui_window, &attrs);
+ *natural_height = attrs.height;
+ }
+
+ *minimum_height = (self->size_hints.flags & PMinSize)
+ ? self->size_hints.min_height
+ : *natural_height;
}
}
@@ -332,13 +372,14 @@ suil_x11_wrapper_class_init(SuilX11WrapperClass* klass)
static void
suil_x11_wrapper_init(SuilX11Wrapper* self)
{
- self->plug = GTK_PLUG(gtk_plug_new(0));
- self->wrapper = NULL;
- self->instance = NULL;
- self->idle_iface = NULL;
- self->idle_ms = 1000 / 30; // 30 Hz default
- self->req_width = 0;
- self->req_height = 0;
+ self->plug = GTK_PLUG(gtk_plug_new(0));
+ self->wrapper = NULL;
+ self->instance = NULL;
+ self->idle_iface = NULL;
+ self->idle_ms = 1000 / 30; // 30 Hz default
+ self->size_hints_dirty = TRUE;
+
+ memset(&self->size_hints, 0, sizeof(self->size_hints));
}
static int
@@ -346,8 +387,14 @@ wrapper_resize(LV2UI_Feature_Handle handle, int width, int height)
{
SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle);
- wrap->req_width = width;
- wrap->req_height = height;
+ wrap->size_hints.width = width;
+ wrap->size_hints.height = height;
+ if (width > 0 && height > 0) {
+ wrap->size_hints.flags |= USSize;
+ }
+
+ // Fetch hints to get size constraints (probably) updated by plugin
+ wrap->size_hints_dirty = TRUE;
gtk_widget_queue_resize(GTK_WIDGET(handle));
return 0;
@@ -378,11 +425,18 @@ wrapper_wrap(SuilWrapper* wrapper, SuilInstance* instance)
Window ui_window = (Window)instance->ui_widget;
gdk_display_sync(display);
-
- XWindowAttributes attrs;
- XGetWindowAttributes(xdisplay, ui_window, &attrs);
- wrap->initial_width = attrs.width;
- wrap->initial_height = attrs.height;
+ if (suil_x11_is_valid_child(xdisplay, GDK_WINDOW_XID(gwindow), ui_window)) {
+ XWindowAttributes attrs;
+ XGetWindowAttributes(xdisplay, ui_window, &attrs);
+
+ update_wm_hints(wrap, TRUE);
+ if (!(wrap->size_hints.flags & PBaseSize)) {
+ // Fall back to using initial size as base size
+ wrap->size_hints.flags |= PBaseSize;
+ wrap->size_hints.base_width = attrs.width;
+ wrap->size_hints.base_height = attrs.height;
+ }
+ }
const LV2UI_Idle_Interface* idle_iface = NULL;
if (instance->descriptor->extension_data) {