2009-11-17 11 views
11

Desarrollé una ventana emergente (No decorada) usando GTK + y la herramienta Glade en C. Aparece en su ventana principal cuando se presiona un botón. Quiero destruir u ocultar esta ventana emergente cuando el usuario hace clic en el lado de esta ventana. El usuario puede hacer clic en la ventana principal o en cualquier otra ventana. He intentado capturar el evento GDK_FOCUS_CHANGE pero no puedo capturar este evento. ¿Hay alguna forma de lograr esto? ¿Cómo sé que el clic está en otra ventana y luego aparece la ventana emergente? ¿Cómo está claro que la ventana emergente ha perdido su foco? Para que pueda ocultarlo. El código en cuestión es la siguiente:Cómo ocultar ventana emergente de Gtk cuando el usuario hace clic fuera de la ventana

/* 
* 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; 
} 

Aquí no soy capaz de ocultar este aviso cuando el usuario hace clic en la ventana padre o en otra ventana. ¿Cómo puedo hacer esto?

Tengo que seguir con la versión Gtk + 2.14.

+0

No vuelva a publicar preguntas. Esto parece ser una repetición (mejor presentada) de http://stackoverflow.com/questions/1740947/problem-with-gtk-popup-window-focus-change-event-handling – mlibby

+0

Me ocuparé de esto en el futuro. – kbalar

Respuesta

8

Cambios:

  • cambio de vía desde GTK_WINDOW_POPUP a GTK_WINDOW_TOPLEVEL, contra-intuitivo, pero no pude encontrar la manera de obtener una ventana emergente para aceptar el foco.
  • añadir gtk_window consejos para prevenir emergente de mostrar en la barra de tareas y buscapersonas
  • conjunto intencionadamente el foco en la ventana emergente
  • establecer el GDK_FOCUS_CHANGE_MASK en el GDK_WINDOW con gtk_widget_set_events (necesario para el paso siguiente)
  • conectan a la focus-out-event de la ventana emergente
  • cambiar el manejador de señales para manejar una señal diferente

I woul También sugiero leer la fuente GTK + para ver cómo maneja las ventanas emergentes para la información sobre herramientas y los menús cuando se muestran ... pero normalmente se destruyen en función de que el mouse se mueva fuera de rango, no el foco emergente per se, 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; 
} 
+0

Lo tengo funcionando! Gracias por mirar esto. – kbalar

+0

Buen trato. Si esta respuesta funciona para usted, no dude en hacer clic en la marca grande al lado de la respuesta.:) – mlibby

+0

Gran solución, pero hay un problema: la ventana principal registra visualmente los cambios de enfoque al colorear el borde de forma diferente (Windows 7). Esto no debería ocurrir para una ventana emergente (falsa). Alguna idea para evitar esto? – schlamar

2

No necesita establecer el foco del teclado en su ventana emergente.

sólo tiene que capturar ratón a su popup_window->window usando gdk_pointer_grab(...) con verdaderos owner_events y GDK_BUTTON_PRESS_MASK GdkEventMask argumentos.

A continuación, conecte su ventana emergente a "button-press-event". Dentro de su manejador, oculte/destruya su ventana emergente y suelte la captura usando gdk_pointer_ungrab(...) si * las coordenadas del evento son negativas o más altas que el tamaño de su ventana emergente.

1

Otra alternativa es simplemente agregar un botón presione oyente a la ventana primaria. Esto tiene la ventaja de que la ventana emergente todavía se ve como una ventana emergente (tanto el padre como ella misma pueden estar activos a la vez)

#include <stdio.h> 
#include <gtk/gtk.h> 

static void on_popup_clicked (GtkButton*, GtkWidget*); 

gulong handler_id; 

gboolean 
on_click (GtkWidget *widget, 
       GdkEvent *event, 
       gpointer user_data) 
{ 
    g_signal_handler_disconnect (widget, handler_id); 
    gtk_widget_destroy (user_data); 
    return TRUE; 
} 


gboolean 
on_popup_focus_out (GtkWidget *widget, 
        GdkEventFocus *event, 
        gpointer data) 
{ 
    gtk_widget_destroy (widget); 
    return TRUE; 
} 


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_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_add_events (popup_window, GDK_FOCUS_CHANGE_MASK); 
    gtk_widget_add_events (pWindow, GDK_BUTTON_PRESS_MASK); 

    g_signal_connect (G_OBJECT (popup_window), 
        "focus-out-event", 
        G_CALLBACK (on_popup_focus_out), 
        NULL); 

    handler_id = g_signal_connect (G_OBJECT (pWindow), 
        "button-press-event", 
        G_CALLBACK (on_click), 
        popup_window); 

    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); 
} 
Cuestiones relacionadas