GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Wed Jul 23, 2014 5:46 am

All times are UTC




Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Catching motion notify while LMB is down
PostPosted: Wed Nov 18, 2009 4:18 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
Hi,

I noticed that my custom widget doesn't get any motion notifications when the mouse cursor is outside of my window's bounds. However, I'd need these notifications while the left mouse button is down.

For example, the user presses LMB while the mouse cursor is over my custom widget. Now the user moves the mouse while still holding down LMB. Is it possible for my custom widget to receive *all* these mouse moves now until LMB is up again, even if the user moves the mouse cursor outside of the window?

Andy


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 21, 2009 12:48 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

This is not possible, since application can only detect motion over it's own GdkWindows. Drag and drop will generally work on X11 backend systems (Linux, OSX with X11 backend), but on Windows even this is limited to drags from Explorer (things may have changed since I last looked at Windows specific stuff).

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 21, 2009 1:25 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
But it's technically possible under Windows to get mouse moves from outside of the window's bounds because you can call SetCapture() on the window when LMB goes down over your window and ReleaseCapture() when LMB goes up again. So you can "capture" all mouse moves while the LMB is down. But it seems that this functionality didn't make it into GTK although I find it quite useful.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 21, 2009 2:34 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

Behaviour you describe is possible, because Windows has single windowing system on which it operates, so this functionality can be exposed to programmers in API. You can do the same thing on GNU/Linux, if you code directly using X11 interface.

GTK+ on other hand is designed to work on many different windowing systems and abstracting this kind of functionality would mean a lot of work for minimal gain.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 21, 2009 9:10 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
Ok, but what's really strange is that my custom widget gets motion notifications also if the mouse cursor is over other (!) windows of my application when the LMB is down.

Consider the following test case:

1) I've three windows. Window A has a custom widget that monitors mouse moves. Windows B and C consist of a collection of normal GTK widgets.

2) Now the user presses and holds down LMB on the custom widget in window A.

3) Now the user moves the mouse cursor to window B or window C while he is still holding down LMB. The result is that the custom widget in window A is still getting motion notifications now *although* the cursor is over window B or C.

4) So I thought that I can check GdkEventMotion->window to see if the mouse cursor is over window A. But this doesn't work because GdkEventMotion->window always points to my custom widget in window A even if the mouse cursor is currently over window B or C.

So is there any way that I can find out if the mouse cursor is really over my custom widget? Also, could this be a bug? I'm asking because when the mouse cursor is over windows B or C, the GdkEventMotion->x and GdkEventMotion->y coordinates are pretty weird. I'm getting negative values and stuff... it's really confusing.

Andy


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 23, 2009 3:37 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
@tadeboro:
Are you sure that it's not possible? I've just tried the Win32 version of Gimp and it works very fine in Gimp. E.g. the selection rectangle is still updated even when the mouse cursor has left the Gimp window. It also detects left mouse button release events that happen outside of the Gimp window correctly.

Any ideas how the Gimp does this? Does it access Win32 API directly? If it does not, then it must be possible with GTK.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 24, 2009 5:57 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

I missed the part about mouse button being pressed in your posts. In this case, you can get coordinates of your mouse, but the will be relative to the GdkWindow's origin in which button press occurred. This is why you get negative coordinates when you move your mouse above or to the left of your window.

As for detecting over which window mouse cursor currently is, you may want to use gdk_display_get_window_at_pointer function.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 24, 2009 8:13 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
Quote:
I missed the part about mouse button being pressed in your posts. In this case, you can get coordinates of your mouse


Ok, but how do I do that? As I said, I'm currently not getting them when the mouse is over a window that doesn't belong to my application. Do I need to do something else in my custom widget to tell GTK to notify me? Or is this another weird behaviour of GTK 2.18 on Win32?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 24, 2009 8:18 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.
andy82 wrote:
Ok, but how do I do that? As I said, I'm currently not getting them when the mouse is over a window that doesn't belong to my application. Do I need to do something else in my custom widget to tell GTK to notify me? Or is this another weird behaviour of GTK 2.18 on Win32?
I get the coordinates reported no matter where my mouse is currently placed. This is the sample application I'm using to test this:
Code:
#include <gtk/gtk.h>

static gboolean
cb_press( GtkWidget      *window,
        GdkEventButton *event,
        gpointer        data )
{
   g_message( "Press: %f,%f", event->x, event->y );

   return( TRUE );
}

static gboolean
cb_motion( GtkWidget      *window,
         GdkEventMotion *event,
         gpointer        data )
{
   g_message( "Coords: %f,%f", event->x, event->y );

   return( TRUE );
}

static gboolean
cb_release( GtkWidget      *window,
         GdkEventButton *event,
         gpointer        data )
{
   g_message( "Release: %f,%f", event->x, event->y );

   return( TRUE );
}

int
main( int    argc,
     char **argv )
{
   GtkWidget *window;

   gtk_init( &argc, &argv );

   window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
   gtk_window_set_default_size( GTK_WINDOW( window ), 300, 300 );
   gtk_widget_add_events( window, GDK_POINTER_MOTION_MASK |
                           GDK_BUTTON_PRESS_MASK |
                           GDK_BUTTON_RELEASE_MASK );
   g_signal_connect( G_OBJECT( window ), "button-press-event",
                 G_CALLBACK( cb_press ), NULL );
   g_signal_connect( G_OBJECT( window ), "motion-notify-event",
                 G_CALLBACK( cb_motion ), NULL );
   g_signal_connect( G_OBJECT( window ), "button-release-event",
                 G_CALLBACK( cb_release ), NULL );
   g_signal_connect( G_OBJECT( window ), "destroy",
                 G_CALLBACK( gtk_main_quit ), NULL );

   gtk_widget_show( window );

   gtk_main();

   return( 0 );
}

I'll reboot into Windows now just to see what happens there using GTK+ 2.16 and 2.18. I'll report back ASAP.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 24, 2009 8:24 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
Thanks for all your efforts! I just tried the code you posted under Windows and I don't get notifications when the mouse is outside of the window (button pressed of course). But please try it yourself on Windows, too... maybe there's something wrong my installation.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 24, 2009 10:05 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

I discovered one good and one bad thing while playing in Windows.

Bad one is that client-side GdkWindows in GTK+ 2.18 really broke Windows version badly. I can get exactly the same behavior as you described - no notification is received when mouse is outside the application's window.

On the bright side, GTK+ 2.16 works perfectly. This is why GIMP is working for you, since GIMP's installer, made by Jernej Simončič (BTW, he's from Slovenia like me;), packs GTK+ 2.16.

My advice to you would be to use 2.16 if you don't need new things introduced in 2.18 (as far as I can remember, the only noticeable addition is GtkInfoBar).

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 04, 2009 1:50 pm 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
Quote:
My advice to you would be to use 2.16 if you don't need new things introduced in 2.18 (as far as I can remember, the only noticeable addition is GtkInfoBar).


Actually, I'm needing the following 2.18 features so going back to 2.16 is not really an option.

1) gdk_pixbuf_simple_anim_set_loop()
2) gtk_widget_set_can_focus()
3) gtk_widget_get_sensitive()
4) gtk_widget_get_visible()
5) gtk_widget_set_visible()

I've tried it now with GTK 2.16 (all calls to the functions above uncommented) and the motion notify with LMB down works indeed correctly now. However, the following problems still persist:

1) no blank lines in GtkLabel objects displayed
2) GtkTextView editor behaves *very* strangely
3) weird complete lockup problem when using modal windows (I still have to track this down to see what is really the issue, so this could be also my fault but I doubt it)

As I really need these things to be working, I'm currently considering fixing these GTK bugs myself and then contributing them to the official distro.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 07, 2009 10:09 am 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

Actually, most of the things you need are in fact present in GTK+-2.16, but under different name. The only thing that is not available is gdk_pixbuf_simple_anim_set_loop() function, all others can be replaced with:
  • gtk_widget_set_can_focus() -> GTK_WIDGET_(UN)SET_FLAGS() + GTK_CAN_FOCUS
  • gtk_widget_get_sensitive() -> GTK_WIDGET_SENSITIVE()
  • gtk_widget_get_visible() -> GTK_WIDGET_VISIBLE()
  • gtk_widget_set_visible() -> gtk_widget_hide/show()


andy82 wrote:
I've tried it now with GTK 2.16 (all calls to the functions above uncommented) and the motion notify with LMB down works indeed correctly now. However, the following problems still persist:

1) no blank lines in GtkLabel objects displayed
2) GtkTextView editor behaves *very* strangely
3) weird complete lockup problem when using modal windows (I still have to track this down to see what is really the issue, so this could be also my fault but I doubt it)

As for 1, I'll check this when I get to my Windows XP install.
As for 2, what do you mean by very strangely? I did use text view a bit under windows some time ago and as far as I can remember, it worked just fine.
As for 3, I'm almost sure that the problem is in your application, since those things are generally handled by window manager directly and GTK+ acts here only as messenger that conveys your requests down to WM.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 08, 2009 11:50 am 
Offline
GTK+ Geek

Joined: Thu Nov 12, 2009 1:49 pm
Posts: 51
Quote:
Actually, most of the things you need are in fact present in GTK+-2.16, but under different name. The only thing that is not available is gdk_pixbuf_simple_anim_set_loop() function, all others can be replaced with:

* gtk_widget_set_can_focus() -> GTK_WIDGET_(UN)SET_FLAGS() + GTK_CAN_FOCUS
* gtk_widget_get_sensitive() -> GTK_WIDGET_SENSITIVE()
* gtk_widget_get_visible() -> GTK_WIDGET_VISIBLE()
* gtk_widget_set_visible() -> gtk_widget_hide/show()


Okay, thanks. I'll see if I can get around gdk_pixbuf_simple_anim_set_loop() somehow too.

Quote:
As for 1, I'll check this when I get to my Windows XP install.
As for 2, what do you mean by very strangely? I did use text view a bit under windows some time ago and as far as I can remember, it worked just fine.
As for 3, I'm almost sure that the problem is in your application, since those things are generally handled by window manager directly and GTK+ acts here only as messenger that conveys your requests down to WM.


As for no.s 1 & 2, they're gone as soon as I'm using the MS-Windows theme. If I'm using the default theme, these problems are there. I don't know why this is like it is.

Problem no. 3 is a little bit more tricky. It's unlikely that it is an error of mine because I can easily reproduce it with some very simple code. You can see it for yourself with this code:

Code:

#include <gtk/gtk.h>

static GtkWidget *window2, *window3;

static void buttonclick1(GtkWidget *button_widget, gpointer data)
{
   gtk_widget_show(window3);
}

static void buttonclick2(GtkWidget *button_widget, gpointer data)
{
   gtk_widget_show(window2);
}

static gboolean windowclose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
   gtk_widget_hide(widget);
   
        return TRUE;  // prevent window destroying
}
   
int main (int argc, char *argv[])
{
   GtkWidget *window1;
        GtkWidget *button1, *button2, *button3, *vbox1, *vbox2;
         
        gtk_init(&argc, &argv);

        window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window1), "Window 1");
        gtk_container_set_border_width(GTK_CONTAINER(window1), 10);
        g_signal_connect_swapped(G_OBJECT(window1), "destroy", G_CALLBACK (gtk_main_quit), NULL);
       
   vbox1 = gtk_vbox_new(FALSE, 0);
        button1 = gtk_button_new_with_label("Button 1");
        button2 = gtk_button_new_with_label("Button 2"); 
             
   gtk_box_pack_start(GTK_BOX(vbox1), button1, FALSE, FALSE, 0);
   gtk_box_pack_start(GTK_BOX(vbox1), button2, FALSE, FALSE, 0);
        
        g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(buttonclick1), NULL);
        g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(buttonclick2), NULL);
                 
        gtk_container_add(GTK_CONTAINER(window1), vbox1);

        /***************************************************************************/       
       
        window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window2), "Window 2");
        gtk_window_set_modal(GTK_WINDOW(window2), TRUE);
        gtk_container_set_border_width(GTK_CONTAINER(window2), 10);
   g_signal_connect(G_OBJECT(window2), "delete-event", G_CALLBACK(windowclose), NULL);   
   
   vbox2 = gtk_vbox_new(FALSE, 0);
        button3 = gtk_button_new_with_label("Button 3");
             
   gtk_box_pack_start(GTK_BOX(vbox2), button3, FALSE, FALSE, 0);
        
        g_signal_connect(G_OBJECT(button3), "clicked", G_CALLBACK(buttonclick1), NULL);
     
        gtk_container_add(GTK_CONTAINER(window2), vbox2);

        gtk_widget_show(button3);
        gtk_widget_show(vbox2);   
                  
        /***************************************************************************/       
               
        window3 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window3), "Window 3");
        gtk_window_set_modal(GTK_WINDOW(window3), TRUE);       
        gtk_container_set_border_width(GTK_CONTAINER(window3), 10);       
   g_signal_connect(G_OBJECT(window3), "delete-event", G_CALLBACK(windowclose), NULL);   
   
        gtk_widget_show_all(window1);   

        gtk_main();

        return 0;
}


To get the problem, you have to do the following:

1) Click "Button 1" --> Window 3 opens up
2) close Window 3 again
3) Click "Button 2" --> Window 2 opens up
4) Click "Button 3" --> Window 3 opens up

5) Now the *whole* application locks up completely! It is not possible to click any more buttons or close any window. The application is completely gone, CPU goes to 100% usage and the whole app is simply dead. I don't know whether this happens on Linux or only Windows. But on Windows, it also happens with GTK 2.16 which is considered stable.

The problem is related to the gtk_window_set_modal() call. If I remove this, it works fine. BUT: The problem also sometimes appears with GtkFileChooserButton because that also opens a modal dialog and there's no way I could change that because I cannot get a GtkDialog handle from a GtkFileChooserButton.

So I'm currently stuck with this problem. For my own windows, I could work around the problem by leaving out gtk_window_set_modal() but I can't easily work around the problem when using GtkFileChooserButton.

Can you reproduce this problem under Linux or Windows? It really seems to be a critical bug because it freezes the whole application which is very bad because the user won't be able to save his changes :(( ...

Thanks, Andy


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 08, 2009 8:17 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

I checked your sample application and it works as expected on GNU/Linux. On Windows, I experience the same problem as you do. I checked out what could be the problem and digged out this code: http://git.gnome.org/cgit/gtk+/tree/gdk/win32/gdkwindow-win32.c#n1425. I know nothing about windows specific API, so I stopped investigating here, but you may be able to get something useful out of this.

Tadej


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group