From 5827827008ada0b56ab94c559eb03a45ecf30ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 15 Jul 2019 17:49:56 +0200 Subject: [PATCH 01/11] Update layer surface code from phosh As of commit 77bba4fcb2d836a58ccf8913d9a514aac6cc49a2. This allows us to split the widget creation from making it visible. --- eek/layersurface.c | 55 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/eek/layersurface.c b/eek/layersurface.c index 63f88eaf..05a14ad9 100644 --- a/eek/layersurface.c +++ b/eek/layersurface.c @@ -65,9 +65,9 @@ static void layer_surface_configure(void *data, uint32_t height) { PhoshLayerSurface *self = data; + gtk_window_resize (GTK_WINDOW (self), width, height); zwlr_layer_surface_v1_ack_configure(surface, serial); - gtk_widget_show_all (GTK_WIDGET (self)); g_signal_emit (self, signals[CONFIGURED], 0); } @@ -180,20 +180,21 @@ phosh_layer_surface_get_property (GObject *object, static void -phosh_layer_surface_constructed (GObject *object) +on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused) { - PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object); - PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self); + PhoshLayerSurfacePrivate *priv; GdkWindow *gdk_window; - G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object); - gtk_window_set_decorated (GTK_WINDOW (self), FALSE); - /* Realize the window so we can get the GDK window */ - gtk_widget_realize(GTK_WIDGET (self)); + g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); + + priv = phosh_layer_surface_get_instance_private (self); gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); gdk_wayland_window_set_use_custom_surface (gdk_window); + + wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ())); + priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window); priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell, @@ -209,8 +210,34 @@ phosh_layer_surface_constructed (GObject *object) &layer_surface_listener, self); wl_surface_commit(priv->wl_surface); + + gtk_window_set_decorated (GTK_WINDOW (self), FALSE); } + +static void +on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused) +{ + /* Process all pending events, otherwise we end up sending ack configure + * to a not yet configured surface */ + wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ())); +} + + +static void +phosh_layer_surface_constructed (GObject *object) +{ + PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object); + + g_signal_connect (self, "realize", + G_CALLBACK (on_phosh_layer_surface_realized), + NULL); + g_signal_connect (self, "map", + G_CALLBACK (on_phosh_layer_surface_mapped), + NULL); +} + + static void phosh_layer_surface_dispose (GObject *object) { @@ -352,6 +379,12 @@ phosh_layer_surface_new (gpointer layer_shell, "wl-output", wl_output); } +/** + * phosh_layer_surface_get_surface: + * + * Get the layer layer surface or #NULL if the window + * is not yet realized. + */ struct zwlr_layer_surface_v1 * phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self) { @@ -363,6 +396,12 @@ phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self) } +/** + * phosh_layer_surface_get_wl_surface: + * + * Get the layer wayland surface or #NULL if the window + * is not yet realized. + */ struct wl_surface * phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self) { From 078efa2a6e8fe8c4f5aedc585d06edffde1e5d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 15 Jul 2019 18:11:13 +0200 Subject: [PATCH 02/11] LayerShell: Set a proper namespace --- src/server-context-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index 967aca7c..6455a27b 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -293,7 +293,7 @@ make_window (ServerContextService *context) "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP, "kbd-interactivity", FALSE, "exclusive-zone", KEYBOARD_HEIGHT, - //"namespace", "phosh home", + "namespace", "osk", NULL ); From 0a112be956ba741e32c320266cbc40dc903c9b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 15 Jul 2019 18:33:13 +0200 Subject: [PATCH 03/11] ServerContextService: Show keyboard when everything else is set up This avoids some flickering. --- src/server-context-service.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server-context-service.c b/src/server-context-service.c index 6455a27b..d230e40e 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -362,6 +362,7 @@ server_context_service_real_show_keyboard (EekboardContextService *_context) EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)-> show_keyboard (_context); + gtk_widget_show_all (context->window); } static void From d807e4392956fdbdd5ded4f53ffcb075a5b0760b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 15 Jul 2019 20:36:57 +0200 Subject: [PATCH 04/11] ServerContextService: Drop unneeded code The layer shell code handles parts of this and others are just not needed on wayland. --- src/server-context-service.c | 84 ------------------------------------ 1 file changed, 84 deletions(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index d230e40e..681073d5 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -61,8 +61,6 @@ G_DEFINE_TYPE (ServerContextService, server_context_service, EEKBOARD_TYPE_CONTE static void update_widget (ServerContextService *context); static void set_geometry (ServerContextService *context); -static void set_dock (GtkWidget *widget, - GtkAllocation *allocation); static void on_monitors_changed (GdkScreen *screen, @@ -143,72 +141,6 @@ on_notify_visible (GObject *object, g_object_set (context, "visible", visible, NULL); } -static void -set_dock (GtkWidget *widget, GtkAllocation *allocation) -{ -#ifdef HAVE_XDOCK - GdkWindow *window = gtk_widget_get_window (widget); - long vals[12]; - - /* set window type to dock */ - gdk_window_set_type_hint (window, GDK_WINDOW_TYPE_HINT_DOCK); - - vals[0] = 0; - vals[1] = 0; - vals[2] = 0; - vals[3] = allocation->height; - vals[4] = 0; - vals[5] = 0; - vals[6] = 0; - vals[7] = 0; - vals[8] = 0; - vals[9] = 0; - vals[10] = allocation->x; - vals[11] = allocation->x + allocation->width; - - XChangeProperty (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - XInternAtom (GDK_WINDOW_XDISPLAY (window), - "_NET_WM_STRUT_PARTIAL", False), - XA_CARDINAL, 32, PropModeReplace, - (guchar *)vals, 12); -#endif /* HAVE_XDOCK */ -} - -static void -on_realize_set_dock (GtkWidget *widget, - gpointer user_data) -{ - GtkAllocation allocation; - - gtk_widget_get_allocation (widget, &allocation); - set_dock (widget, &allocation); -} - -static void -on_size_allocate_set_dock (GtkWidget *widget, - GdkRectangle *allocation, - gpointer user_data) -{ - if (gtk_widget_get_realized (widget)) - set_dock (widget, allocation); -} - -static void -on_realize_set_non_maximizable (GtkWidget *widget, - ServerContextService *context) -{ - - g_assert (context && context->window == widget); - - /* make the window not maximizable */ - gdk_window_set_functions (gtk_widget_get_window (widget), - GDK_FUNC_RESIZE | - GDK_FUNC_MOVE | - GDK_FUNC_MINIMIZE | - GDK_FUNC_CLOSE); -} - static void set_geometry (ServerContextService *context) { @@ -224,13 +156,6 @@ set_geometry (ServerContextService *context) gdk_monitor_get_geometry (monitor, &rect); eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds); - g_signal_handlers_disconnect_by_func (context->window, - on_realize_set_dock, - context); - g_signal_handlers_disconnect_by_func (context->window, - on_realize_set_non_maximizable, - context); - if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) { gint width = rect.width; gint height = rect.height; @@ -256,12 +181,6 @@ set_geometry (ServerContextService *context) gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE); gtk_window_set_resizable (GTK_WINDOW(context->window), FALSE); - g_signal_connect_after (context->window, "realize", - G_CALLBACK(on_realize_set_dock), - context); - g_signal_connect_after (context->window, "size-allocate", - G_CALLBACK(on_size_allocate_set_dock), - context); } else { gtk_window_resize (GTK_WINDOW(context->window), bounds.width, @@ -269,9 +188,6 @@ set_geometry (ServerContextService *context) gtk_window_move (GTK_WINDOW(context->window), MAX(rect.width - 20 - bounds.width, 0), MAX(rect.height - 40 - bounds.height, 0)); - g_signal_connect_after (context->window, "realize", - G_CALLBACK(on_realize_set_non_maximizable), - context); } } From 83d48d24ce0f15ec114fc4c7ebfa321faad27c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 15 Jul 2019 23:38:04 +0200 Subject: [PATCH 05/11] ServerContextService: Really destroy the main window Otherwise layer surfaces keep piling up --- src/server-context-service.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server-context-service.c b/src/server-context-service.c index 681073d5..cdf959c0 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -238,6 +238,7 @@ make_window (ServerContextService *context) static void destroy_window (ServerContextService *context) { + gtk_widget_destroy (GTK_WIDGET (context->window)); context->window = NULL; } From c638c40a09ac0a3a343db27b218049fb859bdfea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 16 Jul 2019 09:45:41 +0200 Subject: [PATCH 06/11] ServerContextService: Drop everything depending on self->was_visible This was never used so everything depending on it was dead code. --- src/server-context-service.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index cdf959c0..aa067682 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -42,8 +42,6 @@ typedef struct _ServerContextServiceClass ServerContextServiceClass; struct _ServerContextService { EekboardContextService parent; - gboolean was_visible; - GtkWidget *window; GtkWidget *widget; @@ -296,26 +294,6 @@ server_context_service_real_hide_keyboard (EekboardContextService *_context) hide_keyboard (_context); } -static void -server_context_service_real_enabled (EekboardContextService *_context) -{ - ServerContextService *context = SERVER_CONTEXT_SERVICE(_context); - - if (context->was_visible && context->window) - gtk_widget_show_all (context->window); -} - -static void -server_context_service_real_disabled (EekboardContextService *_context) -{ - ServerContextService *context = SERVER_CONTEXT_SERVICE(_context); - - if (context->window) { - context->was_visible = gtk_widget_get_visible (context->window); - gtk_widget_hide (context->window); - } -} - static void server_context_service_real_destroyed (EekboardContextService *_context) { @@ -370,8 +348,6 @@ server_context_service_class_init (ServerContextServiceClass *klass) context_class->show_keyboard = server_context_service_real_show_keyboard; context_class->hide_keyboard = server_context_service_real_hide_keyboard; - context_class->enabled = server_context_service_real_enabled; - context_class->disabled = server_context_service_real_disabled; context_class->destroyed = server_context_service_real_destroyed; gobject_class->set_property = server_context_service_set_property; From 95ef52fe4225ac407c61f7be932dea86f44d4575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 16 Jul 2019 09:49:44 +0200 Subject: [PATCH 07/11] ServerContextService: Remove more unused code The whole visible/enable logic was disfunctional all the time. What works is show_keyboard and hide_keyboard. --- src/server-context-service.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index aa067682..dd986da6 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -99,24 +99,6 @@ on_notify_keyboard (GObject *object, // but simpler than adding a check in the window showing procedure eekboard_context_service_set_keymap(EEKBOARD_CONTEXT_SERVICE(context), keyboard); - - if (context->window) { - if (keyboard == NULL) { - gtk_widget_hide (context->window); - g_clear_pointer (&context->widget, gtk_widget_destroy); - } else { - gboolean was_visible = gtk_widget_get_visible (context->window); - /* avoid to send KeyboardVisibilityChanged */ - g_signal_handler_block (context->window, - context->notify_visible_handler); - update_widget (context); - if (was_visible) { - gtk_widget_show_all (context->window); - } - g_signal_handler_unblock (context->window, - context->notify_visible_handler); - } - } } static void From c3a54595ea72638fbc7b65ffc3c26966de772e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 16 Jul 2019 13:31:21 +0200 Subject: [PATCH 08/11] layersurface: Refresh layersurface on map If the surface gets unmapped and mapped again we have another GDK window so we have to reconfigure the layers surface on map and destroy it on unmap. This will be merged back into phosh if it works out. --- eek/layersurface.c | 49 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/eek/layersurface.c b/eek/layersurface.c index 05a14ad9..c9e93a83 100644 --- a/eek/layersurface.c +++ b/eek/layersurface.c @@ -185,18 +185,34 @@ on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused) PhoshLayerSurfacePrivate *priv; GdkWindow *gdk_window; - g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); gdk_wayland_window_set_use_custom_surface (gdk_window); - - wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ())); - priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window); + gtk_window_set_decorated (GTK_WINDOW (self), FALSE); +} + + +static void +on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused) +{ + PhoshLayerSurfacePrivate *priv; + GdkWindow *gdk_window; + + g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); + priv = phosh_layer_surface_get_instance_private (self); + + if (!priv->wl_surface) { + gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); + gdk_wayland_window_set_use_custom_surface (gdk_window); + priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window); + } + g_debug ("Mapped %p", priv->wl_surface); + priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell, priv->wl_surface, priv->wl_output, @@ -211,18 +227,26 @@ on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused) self); wl_surface_commit(priv->wl_surface); - gtk_window_set_decorated (GTK_WINDOW (self), FALSE); -} - - -static void -on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused) -{ /* Process all pending events, otherwise we end up sending ack configure * to a not yet configured surface */ wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ())); } +static void +on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused) +{ + PhoshLayerSurfacePrivate *priv; + + g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); + priv = phosh_layer_surface_get_instance_private (self); + + priv = phosh_layer_surface_get_instance_private (self); + if (priv->layer_surface) { + zwlr_layer_surface_v1_destroy(priv->layer_surface); + priv->layer_surface = NULL; + } + priv->wl_surface = NULL; +} static void phosh_layer_surface_constructed (GObject *object) @@ -235,6 +259,9 @@ phosh_layer_surface_constructed (GObject *object) g_signal_connect (self, "map", G_CALLBACK (on_phosh_layer_surface_mapped), NULL); + g_signal_connect (self, "unmap", + G_CALLBACK (on_phosh_layer_surface_unmapped), + NULL); } From 93e9b2dde96ba2587b1ba836e6c7fde144aa9461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 16 Jul 2019 13:32:58 +0200 Subject: [PATCH 09/11] ServerContextService: Hide the widget instead of destroying it This is quicker and makes sure we don't stack up surfaces. --- src/server-context-service.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index dd986da6..c0dfaff5 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -254,7 +254,8 @@ server_context_service_real_show_keyboard (EekboardContextService *_context) { ServerContextService *context = SERVER_CONTEXT_SERVICE(_context); - make_window (context); + if (!context->window) + make_window (context); update_widget (context); EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)-> @@ -270,8 +271,6 @@ server_context_service_real_hide_keyboard (EekboardContextService *_context) gtk_widget_hide (context->window); g_clear_pointer (&context->widget, gtk_widget_destroy); - destroy_window (context); - EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)-> hide_keyboard (_context); } @@ -315,7 +314,7 @@ server_context_service_dispose (GObject *object) { ServerContextService *context = SERVER_CONTEXT_SERVICE(object); - g_clear_pointer (&context->window, gtk_widget_destroy); + destroy_window (context); context->widget = NULL; G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object); From 8dafad80b199c7f5e9e5481b37928ae560f32f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 17 Jul 2019 00:11:20 +0200 Subject: [PATCH 10/11] ServerContextService: Check for mapped/unmapped Visible does not tell us if the widget is actually visible on the screen. --- src/server-context-service.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/server-context-service.c b/src/server-context-service.c index c0dfaff5..189b8791 100644 --- a/src/server-context-service.c +++ b/src/server-context-service.c @@ -45,8 +45,6 @@ struct _ServerContextService { GtkWidget *window; GtkWidget *widget; - gulong notify_visible_handler; - gdouble size_constraint_landscape[2]; gdouble size_constraint_portrait[2]; }; @@ -111,16 +109,21 @@ on_notify_fullscreen (GObject *object, } static void -on_notify_visible (GObject *object, - GParamSpec *spec, - ServerContextService *context) +on_notify_map (GObject *object, + ServerContextService *context) { - gboolean visible; - - g_object_get (object, "visible", &visible, NULL); - g_object_set (context, "visible", visible, NULL); + g_object_set (context, "visible", TRUE, NULL); } + +static void +on_notify_unmap (GObject *object, + ServerContextService *context) +{ + g_object_set (context, "visible", FALSE, NULL); +} + + static void set_geometry (ServerContextService *context) { @@ -193,14 +196,11 @@ make_window (ServerContextService *context) NULL ); - g_signal_connect (context->window, "destroy", - G_CALLBACK(on_destroy), - context); - - context->notify_visible_handler = - g_signal_connect (context->window, "notify::visible", - G_CALLBACK(on_notify_visible), - context); + g_object_connect (context->window, + "signal::destroy", G_CALLBACK(on_destroy), context, + "signal::map", G_CALLBACK(on_notify_map), context, + "signal::unmap", G_CALLBACK(on_notify_unmap), context, + NULL); // The properties below are just to make hacking easier. // The way we use layer-shell overrides some, From 9974c385e524ed695f1fc3b64e762de5efc95f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 17 Jul 2019 00:44:09 +0200 Subject: [PATCH 11/11] EekboardContextService: Don't comment out property setters This lets us keep the visible property up to date. --- eekboard/eekboard-context-service.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/eekboard/eekboard-context-service.c b/eekboard/eekboard-context-service.c index 1b298223..00a60cd7 100644 --- a/eekboard/eekboard-context-service.c +++ b/eekboard/eekboard-context-service.c @@ -212,12 +212,7 @@ eekboard_context_service_set_property (GObject *object, context->priv->keyboard = g_value_get_object (value); break; case PROP_VISIBLE: - /*if (context->priv->keyboard) { - if (g_value_get_boolean (value)) - eekboard_context_service_show_keyboard (context); - else - eekboard_context_service_hide_keyboard (context); - }*/ + context->priv->visible = g_value_get_boolean (value); break; case PROP_FULLSCREEN: context->priv->fullscreen = g_value_get_boolean (value);