Merge branch 'layer-shell' into 'master'

Hide/show window instead of destroying it

Closes #42

See merge request Librem5/squeekboard!76
This commit is contained in:
David Boddie
2019-07-17 11:34:10 +00:00
3 changed files with 93 additions and 157 deletions

View File

@ -65,9 +65,9 @@ static void layer_surface_configure(void *data,
uint32_t height) uint32_t height)
{ {
PhoshLayerSurface *self = data; PhoshLayerSurface *self = data;
gtk_window_resize (GTK_WINDOW (self), width, height); gtk_window_resize (GTK_WINDOW (self), width, height);
zwlr_layer_surface_v1_ack_configure(surface, serial); zwlr_layer_surface_v1_ack_configure(surface, serial);
gtk_widget_show_all (GTK_WIDGET (self));
g_signal_emit (self, signals[CONFIGURED], 0); g_signal_emit (self, signals[CONFIGURED], 0);
} }
@ -180,22 +180,39 @@ phosh_layer_surface_get_property (GObject *object,
static void 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;
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
GdkWindow *gdk_window; GdkWindow *gdk_window;
G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object); g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
gtk_window_set_decorated (GTK_WINDOW (self), FALSE); priv = phosh_layer_surface_get_instance_private (self);
/* Realize the window so we can get the GDK window */
gtk_widget_realize(GTK_WIDGET (self));
gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
gdk_wayland_window_set_use_custom_surface (gdk_window); gdk_wayland_window_set_use_custom_surface (gdk_window);
priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window); 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->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
priv->wl_surface, priv->wl_surface,
priv->wl_output, priv->wl_output,
@ -209,8 +226,45 @@ phosh_layer_surface_constructed (GObject *object)
&layer_surface_listener, &layer_surface_listener,
self); self);
wl_surface_commit(priv->wl_surface); wl_surface_commit(priv->wl_surface);
/* 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)
{
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);
g_signal_connect (self, "unmap",
G_CALLBACK (on_phosh_layer_surface_unmapped),
NULL);
}
static void static void
phosh_layer_surface_dispose (GObject *object) phosh_layer_surface_dispose (GObject *object)
{ {
@ -352,6 +406,12 @@ phosh_layer_surface_new (gpointer layer_shell,
"wl-output", wl_output); "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 * struct zwlr_layer_surface_v1 *
phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self) phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
{ {
@ -363,6 +423,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 * struct wl_surface *
phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self) phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
{ {

View File

@ -212,12 +212,7 @@ eekboard_context_service_set_property (GObject *object,
context->priv->keyboard = g_value_get_object (value); context->priv->keyboard = g_value_get_object (value);
break; break;
case PROP_VISIBLE: case PROP_VISIBLE:
/*if (context->priv->keyboard) { context->priv->visible = g_value_get_boolean (value);
if (g_value_get_boolean (value))
eekboard_context_service_show_keyboard (context);
else
eekboard_context_service_hide_keyboard (context);
}*/
break; break;
case PROP_FULLSCREEN: case PROP_FULLSCREEN:
context->priv->fullscreen = g_value_get_boolean (value); context->priv->fullscreen = g_value_get_boolean (value);

View File

@ -42,13 +42,9 @@ typedef struct _ServerContextServiceClass ServerContextServiceClass;
struct _ServerContextService { struct _ServerContextService {
EekboardContextService parent; EekboardContextService parent;
gboolean was_visible;
GtkWidget *window; GtkWidget *window;
GtkWidget *widget; GtkWidget *widget;
gulong notify_visible_handler;
gdouble size_constraint_landscape[2]; gdouble size_constraint_landscape[2];
gdouble size_constraint_portrait[2]; gdouble size_constraint_portrait[2];
}; };
@ -61,8 +57,6 @@ G_DEFINE_TYPE (ServerContextService, server_context_service, EEKBOARD_TYPE_CONTE
static void update_widget (ServerContextService *context); static void update_widget (ServerContextService *context);
static void set_geometry (ServerContextService *context); static void set_geometry (ServerContextService *context);
static void set_dock (GtkWidget *widget,
GtkAllocation *allocation);
static void static void
on_monitors_changed (GdkScreen *screen, on_monitors_changed (GdkScreen *screen,
@ -103,24 +97,6 @@ on_notify_keyboard (GObject *object,
// but simpler than adding a check in the window showing procedure // but simpler than adding a check in the window showing procedure
eekboard_context_service_set_keymap(EEKBOARD_CONTEXT_SERVICE(context), eekboard_context_service_set_keymap(EEKBOARD_CONTEXT_SERVICE(context),
keyboard); 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 static void
@ -133,82 +109,21 @@ on_notify_fullscreen (GObject *object,
} }
static void static void
on_notify_visible (GObject *object, on_notify_map (GObject *object,
GParamSpec *spec,
ServerContextService *context) ServerContextService *context)
{ {
gboolean visible; g_object_set (context, "visible", TRUE, NULL);
g_object_get (object, "visible", &visible, NULL);
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 static void
on_realize_set_dock (GtkWidget *widget, on_notify_unmap (GObject *object,
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) ServerContextService *context)
{ {
g_object_set (context, "visible", FALSE, NULL);
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 static void
set_geometry (ServerContextService *context) set_geometry (ServerContextService *context)
{ {
@ -224,13 +139,6 @@ set_geometry (ServerContextService *context)
gdk_monitor_get_geometry (monitor, &rect); gdk_monitor_get_geometry (monitor, &rect);
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds); 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))) { if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
gint width = rect.width; gint width = rect.width;
gint height = rect.height; gint height = rect.height;
@ -256,12 +164,6 @@ set_geometry (ServerContextService *context)
gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE); gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE);
gtk_window_set_resizable (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 { } else {
gtk_window_resize (GTK_WINDOW(context->window), gtk_window_resize (GTK_WINDOW(context->window),
bounds.width, bounds.width,
@ -269,9 +171,6 @@ set_geometry (ServerContextService *context)
gtk_window_move (GTK_WINDOW(context->window), gtk_window_move (GTK_WINDOW(context->window),
MAX(rect.width - 20 - bounds.width, 0), MAX(rect.width - 20 - bounds.width, 0),
MAX(rect.height - 40 - bounds.height, 0)); MAX(rect.height - 40 - bounds.height, 0));
g_signal_connect_after (context->window, "realize",
G_CALLBACK(on_realize_set_non_maximizable),
context);
} }
} }
@ -293,18 +192,15 @@ make_window (ServerContextService *context)
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP, "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
"kbd-interactivity", FALSE, "kbd-interactivity", FALSE,
"exclusive-zone", KEYBOARD_HEIGHT, "exclusive-zone", KEYBOARD_HEIGHT,
//"namespace", "phosh home", "namespace", "osk",
NULL NULL
); );
g_signal_connect (context->window, "destroy", g_object_connect (context->window,
G_CALLBACK(on_destroy), "signal::destroy", G_CALLBACK(on_destroy), context,
context); "signal::map", G_CALLBACK(on_notify_map), context,
"signal::unmap", G_CALLBACK(on_notify_unmap), context,
context->notify_visible_handler = NULL);
g_signal_connect (context->window, "notify::visible",
G_CALLBACK(on_notify_visible),
context);
// The properties below are just to make hacking easier. // The properties below are just to make hacking easier.
// The way we use layer-shell overrides some, // The way we use layer-shell overrides some,
@ -322,6 +218,7 @@ make_window (ServerContextService *context)
static void static void
destroy_window (ServerContextService *context) destroy_window (ServerContextService *context)
{ {
gtk_widget_destroy (GTK_WIDGET (context->window));
context->window = NULL; context->window = NULL;
} }
@ -357,11 +254,13 @@ server_context_service_real_show_keyboard (EekboardContextService *_context)
{ {
ServerContextService *context = SERVER_CONTEXT_SERVICE(_context); ServerContextService *context = SERVER_CONTEXT_SERVICE(_context);
if (!context->window)
make_window (context); make_window (context);
update_widget (context); update_widget (context);
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)-> EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
show_keyboard (_context); show_keyboard (_context);
gtk_widget_show_all (context->window);
} }
static void static void
@ -372,32 +271,10 @@ server_context_service_real_hide_keyboard (EekboardContextService *_context)
gtk_widget_hide (context->window); gtk_widget_hide (context->window);
g_clear_pointer (&context->widget, gtk_widget_destroy); g_clear_pointer (&context->widget, gtk_widget_destroy);
destroy_window (context);
EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)-> EEKBOARD_CONTEXT_SERVICE_CLASS (server_context_service_parent_class)->
hide_keyboard (_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 static void
server_context_service_real_destroyed (EekboardContextService *_context) server_context_service_real_destroyed (EekboardContextService *_context)
{ {
@ -437,7 +314,7 @@ server_context_service_dispose (GObject *object)
{ {
ServerContextService *context = SERVER_CONTEXT_SERVICE(object); ServerContextService *context = SERVER_CONTEXT_SERVICE(object);
g_clear_pointer (&context->window, gtk_widget_destroy); destroy_window (context);
context->widget = NULL; context->widget = NULL;
G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object); G_OBJECT_CLASS (server_context_service_parent_class)->dispose (object);
@ -452,8 +329,6 @@ server_context_service_class_init (ServerContextServiceClass *klass)
context_class->show_keyboard = server_context_service_real_show_keyboard; context_class->show_keyboard = server_context_service_real_show_keyboard;
context_class->hide_keyboard = server_context_service_real_hide_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; context_class->destroyed = server_context_service_real_destroyed;
gobject_class->set_property = server_context_service_set_property; gobject_class->set_property = server_context_service_set_property;