Problem grabbing motion-notify events.



Hello,

I'm having a problem with grabbing motion-notify events when reparenting widgets.  Reparenting appears to 
stop you from receiving all of the events.
I have written the test application below to highlight the problem.

The application reparents a handle box to a window and then reparents it back to the main application window.

Heres how to use it...
1)  Hold the left mouse button down over the handle box and move the cursor outside of the application 
boundary.  You'll notice you'll receive motion-notify events, even if your not over the main application 
window.  This is what I'm expecting.

2) Whilst still holding the left mouse button, click the right mouse button.  This reparents the handle box 
to a newly created GTK_WINDOW_POPUP window.  The newly created window should follow the mouse around.

3) Clicking the right mouse button again reparents the handle box back to the main application window.  Move 
the cursor over the application window and you'll get motion-notify events, move it outside the application 
boundary like before and you'll not get any events?

Can someone please give me a pointer as to why its not receiving events outside the main application boundary 
after its been reparented?  Is it a bug?  Its had me stumped all weekend.  I need it to still pick up events 
even if its outside the windows (like step 1)

Its worth noting that if you change the window style to a GTK_WINDOW_TOPLEVEL then you get similar problems 
for the newly created window (step 2).

Many thanks


#include <gtk/gtk.h>

static gboolean reparented = FALSE;
static GtkWidget* old_window = NULL;
static GtkWidget* new_window;
static GtkWidget* button = NULL;

int 
events(GtkWidget* widget, GdkEvent* event, gpointer object)
{    
    switch(event->type)
    {
        case GDK_BUTTON_PRESS:
        {
            break;
        }
        case GDK_BUTTON_RELEASE:
        {
            GdkEventButton* eventbutton;

            eventbutton = (GdkEventButton*)event;

            if (eventbutton->button == 1 /* Left button. */)
            {
                GdkGrabStatus grabstatus;

                grabstatus = gdk_pointer_grab(widget->window, FALSE, 
GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK, NULL, NULL, GDK_CURRENT_TIME);
                gtk_grab_add(widget);
            }
            else if (eventbutton->button == 3 /* Right button. */)
            {                
                if (!reparented)
                {
                    /* Reparent the handle box to a floating window. */
                    /* If you now Right click it will be reparented back to the main window. */
                    gdk_pointer_ungrab(GDK_CURRENT_TIME);
                    gtk_grab_remove(widget);

                    new_window = gtk_window_new(GTK_WINDOW_POPUP);  // GTK_WINDOW_TOPLEVEL
                    
                    gtk_container_remove(GTK_CONTAINER(old_window), button);
                    gtk_container_add(GTK_CONTAINER(new_window), button);
                    gtk_widget_show_all(new_window);

                    /* Reaquire the grab as the widget->window will have changed. */
                    gdk_pointer_grab(widget->window, FALSE, 
GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK, 0, NULL, GDK_CURRENT_TIME);
                    gtk_grab_add(widget);

                    reparented = TRUE;

                    /* Move the reparented window */
                    gtk_widget_set_uposition(new_window, (gint)eventbutton->x_root, 
(gint)eventbutton->y_root);

                    while (gtk_events_pending())
                        gtk_main_iteration();   /* Process all events currently in the queue. */
                }
                else
                {
                    /* Reparent the handle box back to the maiun window. */
                    /* You only receive mouse events if over the main window */
                    gdk_pointer_ungrab(GDK_CURRENT_TIME);
                    gtk_grab_remove(widget);

                    widget->allocation.width = 50;
                    widget->allocation.height = 50;

                    gtk_container_remove(GTK_CONTAINER(new_window), button);
                    gtk_container_add(GTK_CONTAINER(old_window), button);
                    gtk_widget_show_all(button);
                    
                    gdk_pointer_grab(widget->window, FALSE, 
GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK, 0, NULL, GDK_CURRENT_TIME);
                    gtk_grab_add(widget);

                    gtk_widget_destroy(GTK_WIDGET(new_window));
                    new_window = NULL;

                    reparented = FALSE;

                    while (gtk_events_pending())
                        gtk_main_iteration();   /* Process all events currently in the queue. */              
  
                }
            }

            break;
        }
        case GDK_MOTION_NOTIFY:
        {
            gint x, y;
            GdkModifierType state;
            GdkEventMotion* eventmotion;

            eventmotion = (GdkEventMotion*)event;            

            if (eventmotion->is_hint)
                gdk_window_get_pointer (eventmotion->window, &x, &y, &state);
            else
            {
                x = (gint)eventmotion->x_root;
                y = (gint)eventmotion->y_root;
                state = (GdkModifierType)eventmotion->state;
            }

            g_message("message window %p x %d y %d", eventmotion->window, x, y);

            if (reparented &&
                (new_window != NULL))
                /* Move the reparented window */
                gtk_widget_set_uposition(new_window, x, y);

            break;
        }           
    }

    return FALSE;
}

int main(int argc, char **argv)
{
    gtk_set_locale ();
    gtk_init (&argc, &argv);

    old_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    button = gtk_handle_box_new();
    
    gtk_container_add(GTK_CONTAINER(old_window), button);
    gtk_widget_show_all(old_window);

    g_signal_connect(G_OBJECT(button), "event", G_CALLBACK(events), 0);
        
    gtk_main();

    return 0;
}


-----------------------------------------
Email sent from www.ntlworld.com
Virus-checked using McAfee(R) Software 
Visit www.ntlworld.com/security for more information




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