summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--src/x11_in_gtk2.c120
-rw-r--r--src/x11_in_gtk3.c72
-rw-r--r--wscript2
4 files changed, 176 insertions, 24 deletions
diff --git a/NEWS b/NEWS
index cfecbe6..af06c39 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+suil (0.10.3) unstable;
+
+ * Add support for min/base size hints for X11 in Gtk (thanks Hermann Meyer)
+
+ -- David Robillard <d@drobilla.net> Tue, 19 Feb 2019 08:34:31 +0100
+
suil (0.10.2) stable;
* Add support for Cocoa in Qt5
diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c
index 7ec9592..13195d9 100644
--- a/src/x11_in_gtk2.c
+++ b/src/x11_in_gtk2.c
@@ -28,6 +28,13 @@
typedef struct _SuilX11Wrapper SuilX11Wrapper;
typedef struct _SuilX11WrapperClass SuilX11WrapperClass;
+typedef struct _SuilX11SizeHints SuilX11SizeHints;
+
+struct _SuilX11SizeHints {
+ bool is_set;
+ int width;
+ int height;
+};
struct _SuilX11Wrapper {
GtkSocket socket;
@@ -37,6 +44,10 @@ struct _SuilX11Wrapper {
const LV2UI_Idle_Interface* idle_iface;
guint idle_id;
guint idle_ms;
+ SuilX11SizeHints max_size;
+ SuilX11SizeHints custom_size;
+ SuilX11SizeHints base_size;
+ SuilX11SizeHints min_size;
};
struct _SuilX11WrapperClass {
@@ -192,18 +203,14 @@ forward_size_request(SuilX11Wrapper* socket,
// Calculate allocation size constrained to X11 limits for widget
int width = allocation->width;
int height = allocation->height;
- XSizeHints hints;
- memset(&hints, 0, sizeof(hints));
- XGetNormalHints(GDK_WINDOW_XDISPLAY(window),
- (Window)socket->instance->ui_widget,
- &hints);
- if (hints.flags & PMaxSize) {
- width = MIN(width, hints.max_width);
- height = MIN(height, hints.max_height);
+
+ if (socket->max_size.is_set) {
+ width = MIN(width, socket->max_size.width);
+ height = MIN(height, socket->max_size.height);
}
- if (hints.flags & PMinSize) {
- width = MAX(width, hints.min_width);
- height = MAX(height, hints.min_height);
+ if (socket->min_size.is_set) {
+ width = MAX(width, socket->min_size.width);
+ height = MAX(height, socket->min_size.height);
}
// Resize widget window
@@ -249,6 +256,24 @@ suil_x11_wrapper_key_event(GtkWidget* widget,
}
static void
+suil_x11_on_size_request(GtkWidget* widget,
+ GtkRequisition* requisition)
+{
+ SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget);
+
+ if (self->custom_size.is_set) {
+ requisition->width = self->custom_size.width;
+ requisition->height = self->custom_size.height;
+ } else if (self->base_size.is_set) {
+ requisition->width = self->base_size.width;
+ requisition->height = self->base_size.height;
+ } else if (self->min_size.is_set) {
+ requisition->width = self->min_size.width;
+ requisition->height = self->min_size.height;
+ }
+}
+
+static void
suil_x11_on_size_allocate(GtkWidget* widget,
GtkAllocation* a)
{
@@ -263,6 +288,20 @@ suil_x11_on_size_allocate(GtkWidget* widget,
}
static void
+suil_x11_on_map_event(GtkWidget* widget, GdkEvent* event)
+{
+ SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget);
+ // Reset size request to min size, if the plug provided different size settings
+ if ((self->custom_size.is_set || self->base_size.is_set) &&
+ self->min_size.is_set) {
+ g_object_set(G_OBJECT(GTK_WIDGET(self)),
+ "width-request", self->min_size.width,
+ "height-request", self->min_size.height,
+ NULL);
+ }
+}
+
+static void
suil_x11_wrapper_class_init(SuilX11WrapperClass* klass)
{
GObjectClass* const gobject_class = G_OBJECT_CLASS(klass);
@@ -278,17 +317,27 @@ 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->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->max_size = (SuilX11SizeHints){false, 0, 0};
+ self->custom_size = (SuilX11SizeHints){false, 0, 0};
+ self->base_size = (SuilX11SizeHints){false, 0, 0};
+ self->min_size = (SuilX11SizeHints){false, 0, 0};
}
static int
wrapper_resize(LV2UI_Feature_Handle handle, int width, int height)
{
- gtk_widget_set_size_request(GTK_WIDGET(handle), width, height);
+ SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle);
+
+ wrap->custom_size.width = width;
+ wrap->custom_size.height = height;
+ wrap->custom_size.is_set = width > 0 && height > 0;
+
+ gtk_widget_queue_resize(GTK_WIDGET(handle));
return 0;
}
@@ -312,6 +361,33 @@ wrapper_wrap(SuilWrapper* wrapper,
wrap->wrapper = wrapper;
wrap->instance = instance;
+ if (x_window_is_valid(wrap)) {
+ // Read XSizeHints and store the values for later use
+ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(wrap->plug));
+ XSizeHints hints;
+ memset(&hints, 0, sizeof(hints));
+ long supplied;
+ XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window),
+ (Window)wrap->instance->ui_widget,
+ &hints,
+ &supplied);
+ if (hints.flags & PMaxSize) {
+ wrap->max_size.width = hints.max_width;
+ wrap->max_size.height = hints.max_height;
+ wrap->max_size.is_set = true;
+ }
+ if (hints.flags & PBaseSize) {
+ wrap->base_size.width = hints.base_width;
+ wrap->base_size.height = hints.base_height;
+ wrap->base_size.is_set = true;
+ }
+ if (hints.flags & PMinSize) {
+ wrap->min_size.width = hints.min_width;
+ wrap->min_size.height = hints.min_height;
+ wrap->min_size.is_set = true;
+ }
+ }
+
const LV2UI_Idle_Interface* idle_iface = NULL;
if (instance->descriptor->extension_data) {
idle_iface = (const LV2UI_Idle_Interface*)
@@ -329,10 +405,20 @@ wrapper_wrap(SuilWrapper* wrapper,
NULL);
g_signal_connect(G_OBJECT(wrap),
+ "size-request",
+ G_CALLBACK(suil_x11_on_size_request),
+ NULL);
+
+ g_signal_connect(G_OBJECT(wrap),
"size-allocate",
G_CALLBACK(suil_x11_on_size_allocate),
NULL);
+ g_signal_connect(G_OBJECT(wrap),
+ "map-event",
+ G_CALLBACK(suil_x11_on_map_event),
+ NULL);
+
return 0;
}
diff --git a/src/x11_in_gtk3.c b/src/x11_in_gtk3.c
index 0c016c9..a55eb4c 100644
--- a/src/x11_in_gtk3.c
+++ b/src/x11_in_gtk3.c
@@ -39,6 +39,8 @@ struct _SuilX11Wrapper {
const LV2UI_Idle_Interface* idle_iface;
guint idle_id;
guint idle_ms;
+ int req_width;
+ int req_height;
};
struct _SuilX11WrapperClass {
@@ -253,6 +255,55 @@ suil_x11_wrapper_key_event(GtkWidget* widget,
}
static void
+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));
+ XSizeHints hints;
+ memset(&hints, 0, sizeof(hints));
+ long supplied;
+ XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window),
+ (Window)self->instance->ui_widget,
+ &hints,
+ &supplied);
+ *natural_width = ((hints.flags & PBaseSize) ? hints.base_width
+ : self->req_width);
+ *minimum_width = ((hints.flags & PMinSize) ? hints.min_width
+ : self->req_width);
+ } else {
+ *natural_width = *minimum_width = self->req_width;
+ }
+}
+
+static void
+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));
+ XSizeHints hints;
+ memset(&hints, 0, sizeof(hints));
+ long supplied;
+ XGetWMNormalHints(GDK_WINDOW_XDISPLAY(window),
+ (Window)self->instance->ui_widget,
+ &hints,
+ &supplied);
+ *natural_height = ((hints.flags & PBaseSize) ? hints.base_height
+ : self->req_height);
+ *minimum_height = ((hints.flags & PMinSize) ? hints.min_height
+ : self->req_height);
+ } else {
+ *natural_height = *minimum_height = self->req_height;
+ }
+}
+
+static void
suil_x11_on_size_allocate(GtkWidget* widget,
GtkAllocation* a)
{
@@ -272,11 +323,13 @@ suil_x11_wrapper_class_init(SuilX11WrapperClass* klass)
GObjectClass* const gobject_class = G_OBJECT_CLASS(klass);
GtkWidgetClass* const widget_class = GTK_WIDGET_CLASS(klass);
- gobject_class->finalize = suil_x11_wrapper_finalize;
- widget_class->realize = suil_x11_wrapper_realize;
- widget_class->show = suil_x11_wrapper_show;
- widget_class->key_press_event = suil_x11_wrapper_key_event;
- widget_class->key_release_event = suil_x11_wrapper_key_event;
+ gobject_class->finalize = suil_x11_wrapper_finalize;
+ widget_class->realize = suil_x11_wrapper_realize;
+ widget_class->show = suil_x11_wrapper_show;
+ widget_class->key_press_event = suil_x11_wrapper_key_event;
+ widget_class->key_release_event = suil_x11_wrapper_key_event;
+ widget_class->get_preferred_width = suil_x11_wrapper_get_preferred_width;
+ widget_class->get_preferred_height = suil_x11_wrapper_get_preferred_height;
}
static void
@@ -287,12 +340,19 @@ suil_x11_wrapper_init(SuilX11Wrapper* self)
self->instance = NULL;
self->idle_iface = NULL;
self->idle_ms = 1000 / 30; // 30 Hz default
+ self->req_width = 0;
+ self->req_height = 0;
}
static int
wrapper_resize(LV2UI_Feature_Handle handle, int width, int height)
{
- gtk_widget_set_size_request(GTK_WIDGET(handle), width, height);
+ SuilX11Wrapper* const wrap = SUIL_X11_WRAPPER(handle);
+
+ wrap->req_width = width;
+ wrap->req_height = height;
+
+ gtk_widget_queue_resize(GTK_WIDGET(handle));
return 0;
}
diff --git a/wscript b/wscript
index 89ab039..4a29215 100644
--- a/wscript
+++ b/wscript
@@ -7,7 +7,7 @@ from waflib import TaskGen
from waflib.extras import autowaf
# Semver package/library version
-SUIL_VERSION = '0.10.2'
+SUIL_VERSION = '0.10.3'
SUIL_MAJOR_VERSION = SUIL_VERSION[0:SUIL_VERSION.find('.')]
# Mandatory waf variables