GTK Prevent X close button [Solved]

Linux specific questions.
exagonx
Posts: 314
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

GTK Prevent X close button [Solved]

Post by exagonx »

Hello friends.

Lately I am delighting to improve an application with GTK interface I would like to prevent the use of the X button in the corner since closing with that button destroys its contents preventing me from reopening the window.

I looked on the GTK site if it was possible to disable the button or to manage the event in order to hide instead of closing the window, unfortunately what I found is written in C and I was unable to translate it into FreeBASIC also because I use Glade to draw myself the interface and examples are written to be integrated into the source.

glade source

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkWindow" id="GFAM_preference">
    <property name="name">GFAM_preference</property>
    <property name="can-focus">False</property>
    <signal name="delete-event" handler="on_GFAM_preference_delete_event" swapped="no"/>
    <child>
      <placeholder/>
    </child>
  </object>
  <object class="GtkWindow">
    <property name="can-focus">False</property>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
      </object>
    </child>
  </object>
</interface>

This is my FreeBASIC source

Code: Select all

    #DEFINE __USE_GTK3__ 
    #INCLUDE ONCE "gtk/gtk.bi" 
    gtk_init(@__FB_ARGC__, @__FB_ARGV__) 
    



SCOPE
  VAR er = gtk_check_version_(3, 0, 0)
  IF er THEN
    ?"Error (GTK-Version):"
    ?*er
    END 1
  END IF
END SCOPE

DIM SHARED AS GtkBuilder PTR XML

'Main
DIM SHARED AS GObject PTR _
  GFAM_main
  
'preference
DIM SHARED AS GObject PTR _
  GFAM_preference
  
  
XML = gtk_builder_new()

SCOPE
DIM AS GError PTR meld
IF 0 = gtk_builder_add_from_file(XML, "GFAM.ui", @meld) THEN
  WITH *meld
    ?"Error (GTK-Builder):"
    ?*.message
  END WITH
  g_error_free(meld)
  END 2
END IF
END SCOPE
'main
GFAM_main = gtk_builder_get_object(XML, "GFAM_main")


'preference
GFAM_preference = gtk_builder_get_object(XML, "GFAM_preference")

SUB on_GFAM_preference_delete_event  CDECL ALIAS "on_GFAM_preference_delete_event" ( _
  BYVAL widget AS GtkWidget PTR, _
  BYVAL user_data AS gpointer) EXPORT
  
gtk_widget_hide(GTK_WIDGET(GFAM_preference))

 
END SUB

    gtk_builder_connect_signals(XML, 0)
    g_object_unref(XML) 
    gtk_widget_show_all(GTK_WIDGET(GFAM_main))
    gtk_main() 

Below I have the Code in C

Code: Select all

#include <gtk/gtk.h>

void
on_button_clicked(GtkButton *button, gpointer data)
{
    GtkWidget *widget;
    widget = (GtkWidget *) data;
    if (widget == NULL)
        return;
    gtk_widget_show(widget);
    return;
}

gboolean
on_widget_deleted(GtkWidget *widget, GdkEvent *event, gpointer data)
{
    gtk_widget_hide(widget);
    return TRUE;
}

int
main(int argc, char **argv)
{
    GtkWidget *window1;
    GtkWidget *window2;
    GtkWidget *button;
    gtk_init(&argc, &argv);

    window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    button = gtk_button_new_with_label("Show again...");

    g_signal_connect(G_OBJECT(window1),
        "destroy", gtk_main_quit, NULL);
    g_signal_connect(G_OBJECT(window2), 
        "delete-event", G_CALLBACK(on_widget_deleted), NULL);
    g_signal_connect(G_OBJECT(button), 
        "clicked", G_CALLBACK(on_button_clicked), window2);
    gtk_container_add(GTK_CONTAINER(window1), button);
    gtk_widget_set_size_request(window1, 300, 100);
    gtk_widget_set_size_request(window2, 300, 100);

    gtk_widget_show_all(window1);
    gtk_widget_show(window2);

    gtk_main();
    return 0;
}

Last edited by exagonx on Mar 30, 2022 9:00, edited 1 time in total.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: GTK Prevent X close button

Post by srvaldez »

hello exagonx
try to translate it using fbfrog https://github.com/dkl/fbfrog
here's the output of fbfrog, you may have make changes to get it to work but it's start
note: fbfrog was designed to convert C headers and not to translate C code

Code: Select all

#pragma once

#include once "gtk/gtk.bi"

extern "C"

private sub on_button_clicked(byval button as GtkButton ptr, byval data as gpointer)
	GtkWidget * widget
	widget = cptr(GtkWidget ptr, data)
	if widget = NULL then
		return
	end if
	gtk_widget_show(widget)
	return
end sub

private function on_widget_deleted(byval widget as GtkWidget ptr, byval event as GdkEvent ptr, byval data as gpointer) as gboolean
	gtk_widget_hide(widget)
	return TRUE
end function

private function main(byval argc as long, byval argv as zstring ptr ptr) as long
	GtkWidget * window1
	GtkWidget * window2
	GtkWidget * button
	gtk_init(@argc, @argv)
	window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL)
	window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL)
	button = gtk_button_new_with_label("Show again...")
	g_signal_connect(G_OBJECT(window1), "destroy", gtk_main_quit, NULL)
	g_signal_connect(G_OBJECT(window2), "delete-event", G_CALLBACK(on_widget_deleted), NULL)
	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_button_clicked), window2)
	gtk_container_add(GTK_CONTAINER(window1), button)
	gtk_widget_set_size_request(window1, 300, 100)
	gtk_widget_set_size_request(window2, 300, 100)
	gtk_widget_show_all(window1)
	gtk_widget_show(window2)
	gtk_main()
	return 0
end function

end extern
exagonx
Posts: 314
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: GTK Prevent X close button

Post by exagonx »

srvaldez wrote: Mar 28, 2022 17:05 hello exagonx
try to translate it using fbfrog https://github.com/dkl/fbfrog
hi srvaldez thank you for your answer, its a bit complicate but I will try do study of work.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: GTK Prevent X close button

Post by srvaldez »

hello exagonx
I tweaked the code so that it compiles and runs but it's not disabling the X box, maybe you can make it work

Code: Select all

#pragma once

#include once "gtk/gtk3.bi"

private sub on_button_clicked(byval button as GtkButton ptr, byval data_ as gpointer)
	dim as GtkWidget ptr widget
	widget = cptr(GtkWidget ptr, data_)
	if widget = NULL then
		return
	end if
	gtk_widget_show(widget)
	return
end sub

private function on_widget_deleted(byval widget as GtkWidget ptr, byval event as GdkEvent ptr, byval data_ as gpointer) as gboolean
	gtk_widget_hide(widget)
	return TRUE
end function

private function main(byval argc as long, byval argv as zstring ptr ptr) as long
	dim as GtkWidget ptr window1
	dim as GtkWidget ptr window2
	dim as GtkWidget ptr button
	gtk_init(@argc, @argv)
	window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL)
	window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL)
	button = gtk_button_new_with_label("Show again...")
	g_signal_connect(G_OBJECT(window1), "destroy", @gtk_main_quit, NULL)
	g_signal_connect(G_OBJECT(window2), "delete-event", G_CALLBACK(@on_widget_deleted), NULL)
	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(@on_button_clicked), window2)
	gtk_container_add(GTK_CONTAINER(window1), button)
	gtk_widget_set_size_request(window1, 300, 100)
	gtk_widget_set_size_request(window2, 300, 100)
	gtk_widget_show_all(window1)
	gtk_widget_show(window2)
	gtk_main()
	return 0
end function

main(0,0)
zmymhlej
Posts: 11
Joined: Mar 23, 2022 16:50

Re: GTK Prevent X close button

Post by zmymhlej »

I have no idea why my post was rejected. I didn't put any pirated software link. I will post it again.

srvaldez, you should call your main function with main(__FB_ARGC__,__FB_ARGV__) instead of 0.
exagonx
Posts: 314
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: GTK Prevent X close button

Post by exagonx »

srvaldez wrote: Mar 29, 2022 10:11 hello exagonx
I tweaked the code so that it compiles and runs but it's not disabling the X box, maybe you can make it work
Hi srvaldez I dont want disable the X button I want manage the event when clicked without close the window, actualli I have the event but the window will be close anyway.

For disable the X button the code are below

Code: Select all

gtk_window_set_deletable(gtkwindow, false)
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: GTK Prevent X close button

Post by srvaldez »

thank you zmymhlej :)
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: GTK Prevent X close button

Post by TJF »

The X button is not part of your GUI! Instead it's controlled by the window manager. It's good practice to avoid interference with other systems!

As far as I understand your target, you just want to prevent the widget from getting destroyed. Therefor either
  • add a further reference (in source code by g_object_ref, and unref before gtk_quit), or
  • connect the "delete-event" signal to gtk_widget_hide_on_delete (instead of default gtk_widget_destroy -> can get done in Glade).
ktuee753
Posts: 12
Joined: Mar 23, 2022 17:04

Re: GTK Prevent X close button

Post by ktuee753 »

Asking such question should be on gnome forum: https://discourse.gnome.org/c/platform/5
exagonx
Posts: 314
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: GTK Prevent X close button

Post by exagonx »

TJF wrote: Mar 30, 2022 1:26 The X button is not part of your GUI! Instead it's controlled by the window manager. It's good practice to avoid interference with other systems!

As far as I understand your target, you just want to prevent the widget from getting destroyed. Therefor either
  • add a further reference (in source code by g_object_ref, and unref before gtk_quit), or
  • connect the "delete-event" signal to gtk_widget_hide_on_delete (instead of default gtk_widget_destroy -> can get done in Glade).
Thank you TJF is exactly what i mean

This is the code for handle it and finally work perfectly Thank you .

Code: Select all

SUB on_mysecondwindow_delete_event  CDECL ALIAS "on_mysecondwindow_delete_event" ( _
  BYVAL widget AS GtkWidget PTR, _
  BYVAL user_data AS gpointer) EXPORT
  
gtk_widget_hide(GTK_WIDGET(mysecondwindow))

 
END SUB
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: GTK Prevent X close button [Solved]

Post by TJF »

I'm surprised that this code is working for you. The "delete-event" doesn't require a SUB handler; instead it requires a FUNCTION returning a gboolean (see your C code and srvaldez translation). When your handler does not return TRUE, the default handler should get invoked and destroys the widget.

But this is not what I talked about. You don't need to code that handler, because it's in-build in GTK named gtk_widget_hide_on_delete. Just connect that function to the windows "delete-event" in your Glade file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkWindow" id="GFAM_main">
    <property name="can-focus">False</property>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
      </object>
    </child>
  </object>
  <object class="GtkWindow" id="GFAM_preference">
    <property name="can-focus">False</property>
    <signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/>
    <child>
      <placeholder/>
    </child>
  </object>
</interface>
In order to unhide that window call gtk_widget_show again.

BTW: It's best practise to declare the main window first. And you rarely need to name a widget, the id tag is sufficient for most use-cases.
exagonx
Posts: 314
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: GTK Prevent X close button [Solved]

Post by exagonx »

TJF wrote: Mar 30, 2022 11:34 I'm surprised that this code is working for you.

Thanks for the clarification, but my code is currently working, I hope it is not the fault of a bug, I would not want to have a wrong belief.

Anyway I named thw widget because in the software are more than one window.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: GTK Prevent X close button [Solved]

Post by TJF »

The id tag allows to distinguish between different widget.

Your code works depending on the last value left over on the stack. Since your SUB doesn't return a value, the value from a previous function call get evaluated. In many cases that value is not 0 (FALSE). But this is not sure.

A further hint: when you borrow some code, ie the C code in your first post or the FB code from the GladeToBac code sketcher, then it's best practice to mention where the code comes from. Name the original author!
exagonx
Posts: 314
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: GTK Prevent X close button [Solved]

Post by exagonx »

TJF wrote: Mar 30, 2022 13:42 Your code works depending on the last value left over on the stack. Since your SUB doesn't return a value, the value from a previous function call get evaluated. In many cases that value is not 0 (FALSE). But this is not sure.
Forgive me but I don't understand, the sub written by me is executed by the event specified in the UI file, and the code starts when I click on the X, if it was caused by another event this would be executed regardless of the click on the X or me am I wrong?
TJF wrote: Mar 30, 2022 13:42 A further hint: when you borrow some code, ie the C code in your first post or the FB code from the GladeToBac code sketcher, then it's best practice to mention where the code comes from. Name the original author!
This code was an example quoted on the GTK site I did not see who the author was.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: GTK Prevent X close button [Solved]

Post by TJF »

exagonx wrote: Mar 30, 2022 18:35... or me am I wrong?
Yes, you're wrong.

If you don't trust me, then try to understand the docs for the GtkWidget "delete-event" signal at
https://docs.gtk.org/gtk3/signal.Widget ... event.html
Post Reply