(resend, CONTRIBUTING.md points to http://www.vim.org/maillist.php#vim-dev but mail to vim-...@vim.org apparently does not make it to the list)
Hi, I'm suffering from an annoying issue with ballooneval as used by the taglist plugin. When using gvim built with --enable-gui=gtk3 the balloon sometimes does not hide when the gvim window loses focus, i.e. the ballon shows on top of other windows even when gvim is completely hidden behind other windows, or even when the gvim window is on a different virtual desktop. This is not easy to reproduce at will, the ingredients to reproduce it are awesome wm (awesomewm.org) and multiple gvim and xterm windows on multiple virtual desktops (awesome uses a concept of tags to implement them). Awesome is a tiling wm but I'm using floating window layout, i.e. like a non-tiling wm, i.e. with overlapping windows. Then after some desktop and window switching the issue usually appears. I have not found any deterministic way to reproduce it, though. The issue appears with gvim from Debian unstable's vim-gtk3 package (there is no gtk2 version anymore in Debian unstable). It can be reproduced with current git built with "./configure --prefix=/usr --enable-gui=gtk3 --disable-xim". I debugged it using the attached vim-gdk-event-debug.patch and got this log: Good case: target_event_cb 3 00203f0e pointer_event 27 0 Gdk-Message: 10:39:58.996: leave notify: window 71303175 subwindow:0 device: 2 source device: 9 notify type: 3 crossing mode: 0 target_event_cb 11 00203f0e target_event_cb: GDK_LEAVE_NOTIFY 0 mainwin_event_cb 11 00437310 mainwin_event_cb: GDK_LEAVE_NOTIFY 0 Gdk-Message: 10:39:59.026: focus out: window: 71303175, detail: NotifyNonlinear, mode: NotifyNormal Gdk-Message: 10:39:59.026: focus out: window: 71303175, detail: NotifyNonlinearVirtual, mode: NotifyNormal mainwin_event_cb 12 00437310 mainwin_event_cb: GDK_FOCUS_CHANGE Bad case: target_event_cb 3 00203f0e pointer_event 15 0 Gdk-Message: 10:41:33.068: leave notify: window 56623548 subwindow:0 device: 2 source device: 9 notify type: 3 crossing mode: 0 Gdk-Message: 10:41:33.068: leave notify: window 56623108 subwindow:0 device: 2 source device: 9 notify type: 4 crossing mode: 0 mainwin_event_cb 11 00437310 mainwin_event_cb: GDK_LEAVE_NOTIFY 0 mainwin_event_cb 11 00437310 mainwin_event_cb: GDK_LEAVE_NOTIFY 0 Gdk-Message: 10:41:33.087: focus out: window: 56623108, detail: NotifyNonlinear, mode: NotifyNormal Gdk-Message: 10:41:33.087: focus out: window: 56623108, detail: NotifyNonlinearVirtual, mode: NotifyNormal mainwin_event_cb 12 00437310 mainwin_event_cb: GDK_FOCUS_CHANGE I have no clue about the root cause, I suppose it could be an issue in gtk3 but this is out of scope for me to debug. The attached gvim-beval-fix.patch fixes (or works around) the issue for me. FWIW, the relevant X11 spec for the events is: https://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#events:pointer_window Best Regards, Johannes -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/YMMyjNdBs5rWy1S/%40sig21.net.
diff --git a/src/gui_beval.c b/src/gui_beval.c index 57122ffa9ae2..620ee99b4924 100644 --- a/src/gui_beval.c +++ b/src/gui_beval.c @@ -209,6 +209,7 @@ gui_mch_currently_showing_beval(void) void gui_mch_post_balloon(BalloonEval *beval, char_u *mesg) { + printf("%s: %s\n", __func__, mesg); vim_free(beval->msg); beval->msg = mesg == NULL ? NULL : vim_strsave(mesg); if (beval->msg != NULL) @@ -227,6 +228,7 @@ gui_mch_post_balloon(BalloonEval *beval, char_u *mesg) void gui_mch_unpost_balloon(BalloonEval *beval) { + printf("%s\n", __func__); VIM_CLEAR(beval->msg); undrawBalloon(beval); } @@ -236,6 +238,8 @@ gui_mch_unpost_balloon(BalloonEval *beval) static void addEventHandler(GtkWidget *target, BalloonEval *beval) { + printf("%s %08x\n", __func__, gtk_widget_get_events(target)); + gdk_set_show_events(TRUE); /* * Connect to the generic "event" signal instead of the individual * signals for each event type, because the former is emitted earlier. @@ -253,6 +257,10 @@ addEventHandler(GtkWidget *target, BalloonEval *beval) if (gtk_socket_id == 0 && gui.mainwin != NULL && gtk_widget_is_ancestor(target, gui.mainwin)) { + gtk_widget_add_events(gui.mainwin, + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK | + GDK_FOCUS_CHANGE_MASK); g_signal_connect(G_OBJECT(gui.mainwin), "event", G_CALLBACK(mainwin_event_cb), beval); @@ -280,9 +288,11 @@ target_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) { BalloonEval *beval = (BalloonEval *)data; + printf("%s %d %08x\n", __func__, event->type, gtk_widget_get_events(widget)); switch (event->type) { case GDK_ENTER_NOTIFY: + printf("%s: GDK_ENTER_NOTIFY\n", __func__); pointer_event(beval, (int)event->crossing.x, (int)event->crossing.y, event->crossing.state); @@ -323,6 +333,7 @@ target_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) } break; case GDK_LEAVE_NOTIFY: + printf("%s: GDK_LEAVE_NOTIFY %d\n", __func__, event->crossing.mode); /* * Ignore LeaveNotify events that are not "normal". * Apparently we also get it when somebody else grabs focus. @@ -352,6 +363,7 @@ mainwin_event_cb(GtkWidget *widget UNUSED, GdkEvent *event, gpointer data) { BalloonEval *beval = (BalloonEval *)data; + printf("%s %d %08x\n", __func__, event->type, gtk_widget_get_events(widget)); switch (event->type) { case GDK_KEY_PRESS: @@ -360,6 +372,15 @@ mainwin_event_cb(GtkWidget *widget UNUSED, GdkEvent *event, gpointer data) case GDK_KEY_RELEASE: key_event(beval, event->key.keyval, FALSE); break; + case GDK_FOCUS_CHANGE: + printf("%s: GDK_FOCUS_CHANGE\n", __func__); + break; + case GDK_ENTER_NOTIFY: + printf("%s: GDK_ENTER_NOTIFY\n", __func__); + break; + case GDK_LEAVE_NOTIFY: + printf("%s: GDK_LEAVE_NOTIFY %d\n", __func__, event->crossing.mode); + break; default: break; } @@ -374,6 +395,7 @@ pointer_event(BalloonEval *beval, int x, int y, unsigned state) distance = ABS(x - beval->x) + ABS(y - beval->y); + printf("%s %d %u\n", __func__, distance, state); if (distance > 4) { /*
fix gtk3 GUI balloon failing to hide In some rare cases the GDK_LEAVE_NOTIFY event does not propagate to the target window but instead is sent to the main window twice. This might be a gtk3 issue. diff --git a/src/gui_beval.c b/src/gui_beval.c index 57122ffa9ae2..d2bf8089a357 100644 --- a/src/gui_beval.c +++ b/src/gui_beval.c @@ -253,6 +253,9 @@ addEventHandler(GtkWidget *target, BalloonEval *beval) if (gtk_socket_id == 0 && gui.mainwin != NULL && gtk_widget_is_ancestor(target, gui.mainwin)) { + gtk_widget_add_events(gui.mainwin, + GDK_LEAVE_NOTIFY_MASK); + g_signal_connect(G_OBJECT(gui.mainwin), "event", G_CALLBACK(mainwin_event_cb), beval); @@ -360,6 +363,14 @@ mainwin_event_cb(GtkWidget *widget UNUSED, GdkEvent *event, gpointer data) case GDK_KEY_RELEASE: key_event(beval, event->key.keyval, FALSE); break; + case GDK_LEAVE_NOTIFY: + /* + * Ignore LeaveNotify events that are not "normal". + * Apparently we also get it when somebody else grabs focus. + */ + if (event->crossing.mode == GDK_CROSSING_NORMAL) + cancelBalloon(beval); + break; default: break; }