gtk: Persist panel state
Creating and destroying the panel as needed causes a resource leak somewhere in the deeper layers of the stack. This is a workaround. See https://gitlab.gnome.org/World/Phosh/squeekboard/-/issues/343
This commit is contained in:
		
							
								
								
									
										73
									
								
								src/panel.c
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								src/panel.c
									
									
									
									
									
								
							@ -9,13 +9,8 @@ void
 | 
				
			|||||||
panel_manager_hide(struct panel_manager *self)
 | 
					panel_manager_hide(struct panel_manager *self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (self->window) {
 | 
					    if (self->window) {
 | 
				
			||||||
        gtk_widget_destroy (GTK_WIDGET (self->window));
 | 
					        gtk_widget_hide (GTK_WIDGET (self->window));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (self->widget) {
 | 
					 | 
				
			||||||
        gtk_widget_destroy (GTK_WIDGET (self->widget));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    self->window = NULL;
 | 
					 | 
				
			||||||
    self->widget = NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
@ -65,42 +60,40 @@ make_widget (struct panel_manager *self)
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
panel_manager_request_widget (struct panel_manager *self, struct wl_output *output, uint32_t height, struct squeek_panel_manager *mgr)
 | 
					panel_manager_request_widget (struct panel_manager *self, struct wl_output *output, uint32_t height, struct squeek_panel_manager *mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (self->window) {
 | 
					    if (!self->window) {
 | 
				
			||||||
        g_error("Window already present");
 | 
					        self->window = g_object_new (
 | 
				
			||||||
 | 
					            PHOSH_TYPE_LAYER_SURFACE,
 | 
				
			||||||
 | 
					            "layer-shell", squeek_wayland->layer_shell,
 | 
				
			||||||
 | 
					            "wl-output", output,
 | 
				
			||||||
 | 
					            "height", height,
 | 
				
			||||||
 | 
					            "anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
 | 
				
			||||||
 | 
					            | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
 | 
				
			||||||
 | 
					            | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
 | 
				
			||||||
 | 
					            "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
 | 
				
			||||||
 | 
					            "kbd-interactivity", FALSE,
 | 
				
			||||||
 | 
					            "exclusive-zone", height,
 | 
				
			||||||
 | 
					            "namespace", "osk",
 | 
				
			||||||
 | 
					            NULL
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        g_object_connect (self->window,
 | 
				
			||||||
 | 
					            "swapped-signal::destroy", G_CALLBACK(on_destroy), self,
 | 
				
			||||||
 | 
					            "swapped-signal::configured", G_CALLBACK(on_surface_configure), mgr,
 | 
				
			||||||
 | 
					            NULL);
 | 
				
			||||||
 | 
					        // The properties below are just to make hacking easier.
 | 
				
			||||||
 | 
					        // The way we use layer-shell overrides some,
 | 
				
			||||||
 | 
					        // and there's no space in the protocol for others.
 | 
				
			||||||
 | 
					        // Those may still be useful in the future,
 | 
				
			||||||
 | 
					        // or for hacks with regular windows.
 | 
				
			||||||
 | 
					        gtk_widget_set_can_focus (GTK_WIDGET(self->window), FALSE);
 | 
				
			||||||
 | 
					        g_object_set (G_OBJECT(self->window), "accept_focus", FALSE, NULL);
 | 
				
			||||||
 | 
					        gtk_window_set_title (GTK_WINDOW(self->window), "Squeekboard");
 | 
				
			||||||
 | 
					        gtk_window_set_icon_name (GTK_WINDOW(self->window), "squeekboard");
 | 
				
			||||||
 | 
					        gtk_window_set_keep_above (GTK_WINDOW(self->window), TRUE);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->window = g_object_new (
 | 
					    if (!self->widget) {
 | 
				
			||||||
        PHOSH_TYPE_LAYER_SURFACE,
 | 
					        make_widget(self);
 | 
				
			||||||
        "layer-shell", squeek_wayland->layer_shell,
 | 
					    }
 | 
				
			||||||
        "wl-output", output,
 | 
					 | 
				
			||||||
        "height", height,
 | 
					 | 
				
			||||||
        "anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
 | 
					 | 
				
			||||||
        | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
 | 
					 | 
				
			||||||
        | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
 | 
					 | 
				
			||||||
        "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
 | 
					 | 
				
			||||||
        "kbd-interactivity", FALSE,
 | 
					 | 
				
			||||||
        "exclusive-zone", height,
 | 
					 | 
				
			||||||
        "namespace", "osk",
 | 
					 | 
				
			||||||
        NULL
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_object_connect (self->window,
 | 
					 | 
				
			||||||
        "swapped-signal::destroy", G_CALLBACK(on_destroy), self,
 | 
					 | 
				
			||||||
        "swapped-signal::configured", G_CALLBACK(on_surface_configure), mgr,
 | 
					 | 
				
			||||||
        NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // The properties below are just to make hacking easier.
 | 
					 | 
				
			||||||
    // The way we use layer-shell overrides some,
 | 
					 | 
				
			||||||
    // and there's no space in the protocol for others.
 | 
					 | 
				
			||||||
    // Those may still be useful in the future,
 | 
					 | 
				
			||||||
    // or for hacks with regular windows.
 | 
					 | 
				
			||||||
    gtk_widget_set_can_focus (GTK_WIDGET(self->window), FALSE);
 | 
					 | 
				
			||||||
    g_object_set (G_OBJECT(self->window), "accept_focus", FALSE, NULL);
 | 
					 | 
				
			||||||
    gtk_window_set_title (GTK_WINDOW(self->window), "Squeekboard");
 | 
					 | 
				
			||||||
    gtk_window_set_icon_name (GTK_WINDOW(self->window), "squeekboard");
 | 
					 | 
				
			||||||
    gtk_window_set_keep_above (GTK_WINDOW(self->window), TRUE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    make_widget(self);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gtk_widget_show (GTK_WIDGET(self->window));
 | 
					    gtk_widget_show (GTK_WIDGET(self->window));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,8 +13,10 @@ struct panel_manager {
 | 
				
			|||||||
    struct squeek_popover *popover; // shared reference
 | 
					    struct squeek_popover *popover; // shared reference
 | 
				
			||||||
    struct submission *submission; // unowned
 | 
					    struct submission *submission; // unowned
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // both memoized - doesn't have to be, but bugs happen:
 | 
				
			||||||
 | 
					    // https://gitlab.gnome.org/World/Phosh/squeekboard/-/issues/343
 | 
				
			||||||
    PhoshLayerSurface *window;
 | 
					    PhoshLayerSurface *window;
 | 
				
			||||||
    GtkWidget *widget; // nullable
 | 
					    GtkWidget *widget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Those should be held in Rust
 | 
					    // Those should be held in Rust
 | 
				
			||||||
    struct wl_output *current_output;
 | 
					    struct wl_output *current_output;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user