From d55d7f41c3682614ee8bdb75db2b76849786b9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sat, 7 Apr 2012 13:51:02 +0000 Subject: [PATCH] [GB.GTK] * BUG: Try to handle Leave/Enter events the same way as in gb.qt4. git-svn-id: svn://localhost/gambas/trunk@4606 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- gb.gtk/src/gapplication.cpp | 75 +++++++++++++++++++++++++++++++------ gb.gtk/src/gcontrol.cpp | 19 ++++++++++ gb.gtk/src/gcontrol.h | 37 +++++++++--------- 3 files changed, 102 insertions(+), 29 deletions(-) diff --git a/gb.gtk/src/gapplication.cpp b/gb.gtk/src/gapplication.cpp index 0821d5ed7..d600b5f3a 100644 --- a/gb.gtk/src/gapplication.cpp +++ b/gb.gtk/src/gapplication.cpp @@ -40,6 +40,7 @@ #include "gmainwindow.h" //#define DEBUG_IM 1 +//#define DEBUG_ENTER_LEAVE 1 /************************************************************************* @@ -308,6 +309,20 @@ static bool raise_key_event_to_parent_window(gControl *control, int type) return false; } +static bool check_crossing_event(GdkEvent *event) +{ + #if DEBUG_ENTER_LEAVE + fprintf(stderr, "check_crossing_event: %d / %d\n", event->crossing.detail, event->crossing.mode); + #endif + + if (event->crossing.detail != GDK_NOTIFY_INFERIOR + && (event->crossing.mode == GDK_CROSSING_NORMAL || event->crossing.mode == GDK_CROSSING_STATE_CHANGED)) + // || event->crossing.mode == GDK_CROSSING_UNGRAB || event->crossing.mode == GDK_CROSSING_GTK_UNGRAB)) + return true; + else + return false; +} + static void gambas_handle_event(GdkEvent *event) { GtkWidget *widget; @@ -431,12 +446,20 @@ static void gambas_handle_event(GdkEvent *event) //if (group != gApplication::currentGroup()) // goto __HANDLE_EVENT; - if (event->type != GDK_ENTER_NOTIFY) + if (!gdk_events_pending() && event->type != GDK_ENTER_NOTIFY && event->type != GDK_LEAVE_NOTIFY) { if (gApplication::_leave) { - if (event->type != GDK_LEAVE_NOTIFY || gApplication::_leave != control) - gApplication::_leave->emit(SIGNAL(gApplication::_leave->onEnterLeave), gEvent_Leave); + //if () // || (gApplication::_leave != control && check_crossing_event(event))) + #if DEBUG_ENTER_LEAVE + fprintf(stderr, "post leave: %s\n", gApplication::_leave->name()); + #endif + + if (gApplication::_enter == gApplication::_leave) + gApplication::_enter = NULL; + + gApplication::_leave->emitLeaveEvent(); + gApplication::_leave = NULL; } } @@ -449,25 +472,53 @@ static void gambas_handle_event(GdkEvent *event) { case GDK_ENTER_NOTIFY: - //gApplication::dispatchEnterLeave(control); if (gApplication::_leave == control) + { + #if DEBUG_ENTER_LEAVE + fprintf(stderr, "enter ignored: %s\n", control->name()); + #endif gApplication::_leave = NULL; + } else if (gApplication::_enter != control) { - gApplication::_enter = control; - control->emit(SIGNAL(control->onEnterLeave), gEvent_Enter); + if (check_crossing_event(event)) + { + #if DEBUG_ENTER_LEAVE + fprintf(stderr, "enter: %s\n", control->name()); + #endif + gApplication::_enter = control; + control->emitEnterEvent(); + } } break; case GDK_LEAVE_NOTIFY: - if (gdk_events_pending()) - gApplication::_leave = control; - else + if (gdk_events_pending() && gApplication::_leave == NULL) { - if (gApplication::_enter == control) - gApplication::_enter = NULL; - control->emit(SIGNAL(control->onEnterLeave), gEvent_Leave); + if (check_crossing_event(event)) + { + #if DEBUG_ENTER_LEAVE + fprintf(stderr, "leave later: %s\n", control->name()); + #endif + gApplication::_leave = control; + } + } + else if (gApplication::_leave != control) + { + if (check_crossing_event(event)) + { + if (gApplication::_enter == control) + gApplication::_enter = NULL; + + if (gApplication::_leave == control) + gApplication::_leave = NULL; + + #if DEBUG_ENTER_LEAVE + fprintf(stderr, "leave: %s\n", control->name()); + #endif + control->emitLeaveEvent(); + } } break; diff --git a/gb.gtk/src/gcontrol.cpp b/gb.gtk/src/gcontrol.cpp index 6aa2a586a..72819233e 100644 --- a/gb.gtk/src/gcontrol.cpp +++ b/gb.gtk/src/gcontrol.cpp @@ -237,6 +237,7 @@ void gControl::initAll(gContainer *parent) _no_default_mouse_event = false; _proxy = _proxy_for = NULL; _no_tab_focus = false; + _inside = false; onFinish = NULL; onFocusEvent = NULL; @@ -1859,3 +1860,21 @@ void gControl::setNoTabFocus(bool v) if (pr) pr->updateFocusChain(); } + +void gControl::emitEnterEvent() +{ + if (_inside) + return; + + emit(SIGNAL(onEnterLeave), gEvent_Enter); + _inside = true; +} + +void gControl::emitLeaveEvent() +{ + if (!_inside) + return; + + emit(SIGNAL(onEnterLeave), gEvent_Leave); + _inside = false; +} diff --git a/gb.gtk/src/gcontrol.h b/gb.gtk/src/gcontrol.h index 97b82995c..5bdf283dc 100644 --- a/gb.gtk/src/gcontrol.h +++ b/gb.gtk/src/gcontrol.h @@ -186,36 +186,36 @@ public: unsigned dsg : 1; unsigned expa : 1; unsigned igno : 1; - unsigned _action : 1; // *reserved* - unsigned _accept_drops : 1; // If the control accepts drops - unsigned _drag_get_data : 1; // If we got information on the dragged data - unsigned _drag_enter : 1; // If we have entered the control for drag & drop - unsigned _tracking : 1; // If we are tracking mouse move even if no mouse button is pressed + unsigned _action : 1; // *reserved* + unsigned _accept_drops : 1; // If the control accepts drops + unsigned _drag_get_data : 1; // If we got information on the dragged data + unsigned _drag_enter : 1; // If we have entered the control for drag & drop + unsigned _tracking : 1; // If we are tracking mouse move even if no mouse button is pressed - unsigned _old_tracking : 1; // real value when Tracking is false - unsigned _bg_set : 1; // Have a private background - unsigned _fg_set : 1; // Have a private foreground - unsigned _font_set : 1; // Have a private font - unsigned have_cursor : 1; // If gApplication::setBusy() must update the cursor - unsigned use_base : 1; // Use base and text color for foreground and background - unsigned visible : 1; // A control can be hidden if its width or height is zero - unsigned _destroyed : 1; // If the control has already been added to the destroy list + unsigned _old_tracking : 1; // real value when Tracking is false + unsigned _bg_set : 1; // Have a private background + unsigned _fg_set : 1; // Have a private foreground + unsigned _font_set : 1; // Have a private font + unsigned have_cursor : 1; // If gApplication::setBusy() must update the cursor + unsigned use_base : 1; // Use base and text color for foreground and background + unsigned visible : 1; // A control can be hidden if its width or height is zero + unsigned _destroyed : 1; // If the control has already been added to the destroy list - unsigned _locked : 4; // For locking events + unsigned _locked : 4; // For locking events unsigned frame_border : 4; unsigned frame_padding : 8; unsigned _scrolled_window : 1; - unsigned _dirty_pos : 1; // If the position of the widget has changed - unsigned _dirty_size : 1; // If the size of the widget has changed + unsigned _dirty_pos : 1; // If the position of the widget has changed + unsigned _dirty_size : 1; // If the size of the widget has changed unsigned _no_delete : 1; // Do not delete on destroy signal unsigned no_input_method : 1; // No input method management unsigned _no_default_mouse_event : 1; // No default mouse events unsigned _grab : 1; // control is currently grabbing mouse and keyboard unsigned _has_border : 1; // if the control has a border unsigned _no_tab_focus : 1; // Don't put inside focus chain - + unsigned _inside : 1; // if we got an enter event, but not a leave event yet. void removeParent() { pr = NULL; } void initSignals(); @@ -245,6 +245,9 @@ public: virtual int minimumHeight(); void resolveFont(gFont *new_font); + void emitEnterEvent(); + void emitLeaveEvent(); + /* static gControl* dragWidget(); static void setDragWidget(gControl *ct); static char *dragTextBuffer();