I have developed one popup window (Non decorated) using GTK+ and glade tool in C.
It popup on its parent window when a button clicked. I want to destroy or hide this popup window when user clicks out side this window. User can click on parent window or any other window.
I have tried to capture GDK_FOCUS_CHANGE
event but I am not able to capture this event. Is there any way to achieve this? How do I know that click is on other window then pop up window? How is it clear that pop up window has lost it's focus?
So that I can hide it.
The relevant code is as follow:
/*
* Compile me with:
gcc -o popup popup.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)
*/
#include <gtk/gtk.h>
static void on_popup_clicked (GtkButton*, GtkWidget*);
static gboolean on_popup_window_event(GtkWidget*, GdkEventExpose*);
int main (int argc, char *argv[])
{
GtkWidget *window, *button, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Parent window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 300);
gtk_window_set_position (GTK_WINDOW (window),GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label("Pop Up");
g_signal_connect (G_OBJECT (button), "clicked",G_CALLBACK (on_popup_clicked),(gpointer) window);
vbox = gtk_vbox_new (FALSE, 3);
gtk_box_pack_end(GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void on_popup_clicked (GtkButton* button, GtkWidget* pWindow)
{
GtkWidget *popup_window;
popup_window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_title (GTK_WINDOW (popup_window), "Pop Up window");
gtk_container_set_border_width (GTK_CONTAINER (popup_window), 10);
gtk_window_set_resizable(GTK_WINDOW (popup_window), FALSE);
gtk_window_set_decorated(GTK_WINDOW (popup_window), FALSE);
gtk_widget_set_size_request (popup_window, 150, 150);
gtk_window_set_transient_for(GTK_WINDOW (popup_window),GTK_WINDOW (pWindow));
gtk_window_set_position (GTK_WINDOW (popup_window),GTK_WIN_POS_CENTER);
g_signal_connect (G_OBJECT (button), "event",
G_CALLBACK (on_popup_window_event),NULL);
GdkColor color;
gdk_color_parse("#3b3131", &color);
gtk_widget_modify_bg(GTK_WIDGET(popup_window), GTK_STATE_NORMAL, &color);
gtk_widget_show_all (popup_window);
}
gboolean on_popup_window_event(GtkWidget *popup_window, GdkEventExpose *event)
{
if(event->type == GDK_FOCUS_CHANGE)
gtk_widget_hide (popup_window);
return FALSE;
}
Here I am not able to hide this pop up window when user clicks on parent window or on other window. How can I do this?
I have to stick with Gtk+2.14 version.
Changes:
GTK_WINDOW_POPUP
to GTK_WINDOW_TOPLEVEL
, counter-intuitive, but I could not figure out how to get a popup to accept focus.gtk_window
hints to prevent popup from showing in taskbar and pagerGDK_FOCUS_CHANGE_MASK
on the GDK_WINDOW
with gtk_widget_set_events
(required for the next step)focus-out-event
of the popup windowI would also suggest reading the GTK+ source to see how it handles popup windows for tooltips and menus when they are shown... but those are usually destroyed based on the mouse moving out of range, not the popup losing focus, per se.
#include
static void on_popup_clicked (GtkButton*, GtkWidget*);
gboolean on_popup_focus_out (GtkWidget*, GdkEventFocus*, gpointer);
int
main (int argc, char *argv[])
{
GtkWidget *window, *button, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Parent window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 300);
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label ("Pop Up");
g_signal_connect (G_OBJECT (button),
"clicked",
G_CALLBACK (on_popup_clicked),
(gpointer) window);
vbox = gtk_vbox_new (FALSE, 3);
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void
on_popup_clicked (GtkButton* button, GtkWidget* pWindow)
{
GtkWidget *popup_window;
popup_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (popup_window), "Pop Up window");
gtk_container_set_border_width (GTK_CONTAINER (popup_window), 10);
gtk_window_set_resizable (GTK_WINDOW (popup_window), FALSE);
gtk_window_set_decorated (GTK_WINDOW (popup_window), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (popup_window), TRUE);
gtk_window_set_skip_pager_hint (GTK_WINDOW (popup_window), TRUE);
gtk_widget_set_size_request (popup_window, 150, 150);
gtk_window_set_transient_for (GTK_WINDOW (popup_window), GTK_WINDOW (pWindow));
gtk_window_set_position (GTK_WINDOW (popup_window), GTK_WIN_POS_CENTER);
gtk_widget_set_events (popup_window, GDK_FOCUS_CHANGE_MASK);
g_signal_connect (G_OBJECT (popup_window),
"focus-out-event",
G_CALLBACK (on_popup_focus_out),
NULL);
GdkColor color;
gdk_color_parse ("#3b3131", &color);
gtk_widget_modify_bg (GTK_WIDGET (popup_window), GTK_STATE_NORMAL, &color);
gtk_widget_show_all (popup_window);
gtk_widget_grab_focus (popup_window);
}
gboolean
on_popup_focus_out (GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
gtk_widget_destroy (widget);
return TRUE;
}
You don't need to set keyboard focus to your popup window.
You just need to capture mouse to your popup_window->window
using gdk_pointer_grab(...)
with True owner_events
and GDK_BUTTON_PRESS_MASK GdkEventMask
arguments.
Then connect your popup_window to "button-press-event"
. Inside it's handler hide/destroy your popup_window and release capture using gdk_pointer_ungrab(...)
if *event coordinates are negative or higher than your popup_window size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With