summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2013-05-26 23:16:40 +0000
committerDavid Robillard <d@drobilla.net>2013-05-26 23:16:40 +0000
commit8b2a971c42e5588555488c56966adf1687e38140 (patch)
treeafa43f3bdc4027b0b48aa2bba9ca32596086754c /src
parent2ba8fe75d93a8a1591c53336933bf7f4285e31bc (diff)
downloadsuil-8b2a971c42e5588555488c56966adf1687e38140.tar.gz
suil-8b2a971c42e5588555488c56966adf1687e38140.tar.bz2
suil-8b2a971c42e5588555488c56966adf1687e38140.zip
Support resizing for X11 in Gtk (patch from Robin Gareus, #906).
git-svn-id: http://svn.drobilla.net/lad/trunk/suil@5112 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/x11_in_gtk2.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/x11_in_gtk2.c b/src/x11_in_gtk2.c
index 57a9194..3fd23cf 100644
--- a/src/x11_in_gtk2.c
+++ b/src/x11_in_gtk2.c
@@ -52,6 +52,33 @@ GType 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. -> suil_x11_on_size_allocate()
+ will make the application crash with "BadWinow"
+*/
+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) {
+ return true;
+ }
+ }
+ return false;
+}
+
static gboolean
on_plug_removed(GtkSocket* sock, gpointer data)
{
@@ -136,6 +163,18 @@ forward_key_event(SuilX11Wrapper* socket,
(XEvent*)&xev);
}
+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)) {
+ XResizeWindow(GDK_WINDOW_XDISPLAY(window),
+ (Window) socket->instance->ui_widget,
+ allocation->width, allocation->height);
+ }
+}
+
static gboolean
suil_x11_wrapper_key_event(GtkWidget* widget,
GdkEventKey* event)
@@ -151,6 +190,20 @@ suil_x11_wrapper_key_event(GtkWidget* widget,
}
static void
+suil_x11_on_size_allocate(GtkWidget* widget,
+ GtkAllocation* a)
+{
+ SuilX11Wrapper* const self = SUIL_X11_WRAPPER(widget);
+
+ if (self->plug
+ && GTK_WIDGET_REALIZED(widget)
+ && GTK_WIDGET_MAPPED(widget)
+ && GTK_WIDGET_VISIBLE(widget)) {
+ forward_size_request(self, a);
+ }
+}
+
+static void
suil_x11_wrapper_class_init(SuilX11WrapperClass* klass)
{
GObjectClass* const gobject_class = G_OBJECT_CLASS(klass);
@@ -218,6 +271,11 @@ wrapper_wrap(SuilWrapper* wrapper,
G_CALLBACK(on_plug_removed),
NULL);
+ g_signal_connect(G_OBJECT(wrap),
+ "size-allocate",
+ G_CALLBACK(suil_x11_on_size_allocate),
+ NULL);
+
return 0;
}