Repost: Get clicks OUTSIDE the window



Sorry to repost, but I'm really getting mad at this :-(

Havoc, please... I know that once you say what I'm doing wrong I'll
realyze I've been a chicken... But it's better to be a chicken and
proceed than just wander around and block the developement...
Tks.

BYtE,
 Diego.

> Havoc Pennington wrote:
> 
> > You have to gdk_grab_pointer() and gtk_grab_add() during the time that
> > the modal window is active.
> I realized that (and the modal window too, or I couldn't gdk_grab
> modalwin->window ... :-) ). The Gtk source was useful. But not
> sufficient.
> The situation is: I have a GtkEntry. When the user right-clicks it, the
> modal window (containing two spinbuttons and two buttons) pops up over
> it.
> In the best case, the "button_press_event" for the entry stays active
> for two clicks (the second when the popup is already displayed!), in the
> worst case "event" handler for the popup window is never called (so I
> have to switch to a terminal and kill the app).
> In the Gtk sources (in gtkcombo.c) I saw a comment regarding not
> explicitly grabbing button presses, but couldn't understand it...
> The other strange thing is that when the cursor is over the spinbutton
> entries, it changes (this means that spinbuttons are getting some
> events, IIUC), but the buttons won't PRELIGHT when it's over them (so
> they don't get some events, apparently).
> I tried grabbing a lot of different events (button presses, mouse
> movements, etc) - at most I got an X error saying "invalid value" when
> using GDK_ALL_EVENTS_MASK .
> 
> The relevant code is:
> 
> static gboolean _popup_event(GtkWidget *widget, GdkEvent *event,
>                              gpointer user_data)
> {
>   gboolean rv=FALSE;
>   switch(event->type) {
>     case GDK_DESTROY:
>       gdk_pointer_ungrab(GDK_CURRENT_TIME);
>       gdk_keyboard_ungrab(GDK_CURRENT_TIME);
>       gtk_grab_remove(widget);
>       break;
>     case GDK_BUTTON_PRESS: {
>       // Close window if click is outside
>       GdkEventButton *e=(GdkEventButton*)event;
>       GtkRequisition req;
>       gtk_widget_size_request(widget, &req);
>       if(0>e->x || 0>e->y || e->x > req.width || e->y > req.height) {
>         gtk_widget_destroy(widget);
>         rv=TRUE;
>       }
>       } break;
>     default:
>       break;
>   }
>   return rv;
> }
> 
> static void gtk_widget_pop_on(GtkWidget *popup, GtkWidget *ref,
>                               gboolean over, gboolean exp_x,
>                               gboolean exp_y)
> {
>   gint x, y, maxx=gdk_screen_width(), maxy=gdk_screen_height(), w, h;
>   GtkRequisition req;
> 
>   g_assert(popup!=NULL);
>   g_assert(ref!=NULL);
>   g_assert(GTK_IS_WINDOW(popup));
> 
>   // avoid NULL==popup->window
>   if(!GTK_WIDGET_REALIZED(popup)) gtk_widget_realize(popup);
>   gdk_window_get_origin(ref->window, &x, &y);
>   if(!over) {
>     // Upper left corner just under 'ref' widget
>     gtk_widget_size_request(ref, &req);
>     y+=req.height;
>   }
>   // Anyway, it must stay on screen
>   gtk_widget_size_request(popup, &req);
>   w=req.width;
>   h=req.height;
>   x=MIN(x, MAX(0, maxx-w));
>   y=MIN(y, MAX(0, maxy-h));
>   gtk_widget_popup(popup, x, y);
> 
>   if(exp_x)
>     w=maxx-x;
>   if(exp_y)
>     h=maxy-y;
> 
>   gtk_widget_set_usize(popup, w, h);
>   gtk_object_set_data(GTK_OBJECT(popup), "master", ref);
>   gdk_pointer_grab(popup->window, FALSE, GDK_BUTTON_PRESS_MASK |
>       GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK |
>       GDK_LEAVE_NOTIFY_MASK| GDK_POINTER_MOTION_MASK, NULL,
>       NULL, GDK_CURRENT_TIME);
>   gdk_keyboard_grab(popup->window, TRUE, GDK_CURRENT_TIME);
>   gtk_grab_add(popup);
> 
>   gtk_signal_connect(GTK_OBJECT(popup), "event", _popup_event, NULL);
> }
> 
> gboolean
> on_search_res_date_button_press_event  (GtkWidget       *widget,
>                                         GdkEventButton  *event,
>                                         gpointer         user_data)
> {
>         gboolean rv=FALSE;
>         if(event->button==3) {
>                 gtk_widget_pop_on(create_date_edit(), widget, TRUE, FALSE, FALSE);
>                 rv=TRUE;
>         }
>         return rv;
> }
> 
> I tried propagating event->time, too, but it didn't work :-(
> I bet it's something obvious, once understood...
> 
> Tks.
> 
> BYtE,
>  Diego.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]