summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Fl_win32.cxx68
1 files changed, 53 insertions, 15 deletions
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index aef124d65..1aa82c175 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -143,21 +143,46 @@ static HMODULE get_imm_module() {
return s_imm_module;
}
+// USE_TRACK_MOUSE - define NO_TRACK_MOUSE if you don't have
+// TrackMouseEvent()...
//
-// USE_TRACK_MOUSE - define it if you have TrackMouseEvent()...
+// Now (Dec. 2008) we can assume that current Cygwin/MinGW versions
+// support the TrackMouseEvent() function, but WinCE obviously doesn't
+// support it (STR 2095). Therefore, USE_TRACK_MOUSE is enabled by
+// default, but you can disable it by defining NO_TRACK_MOUSE.
//
-// Apparently, at least some versions of Cygwin/MingW don't provide
-// the TrackMouseEvent() function. You can define this by hand
-// if you have it - this is only needed to support subwindow
-// enter/leave notification under Windows.
+// TrackMouseEvent is only used to support window leave notifications
+// under Windows. It can be used to get FL_LEAVE events, when the
+// mouse leaves the _main_ application window (FLTK detects subwindow
+// leave events by using normal move events).
//
+// Implementation note: If the mouse cursor leaves one subwindow and
+// enters another window, then Windows sends a WM_MOUSEMOVE message to
+// the new window before it sends a WM_MOUSELEAVE message to the old
+// (just left) window. We save the current mouse window in a static variable,
+// and if we get a WM_MOUSELEAVE event for the current mouse window, this
+// means that the top level window has been left (otherwise we would have
+// got another WM_MOUSEMOVE message before).
+
+// #define NO_TRACK_MOUSE
+
+#if !defined(NO_TRACK_MOUSE)
+# define USE_TRACK_MOUSE
+#endif // NO_TRACK_MOUSE
+
+static Fl_Window *track_mouse_win=0; // current TrackMouseEvent() window
+
+// USE_CAPTURE_MOUSE_WIN - this must be defined for TrackMouseEvent to work
+// correctly with subwindows - otherwise a single mouse click and release
+// (without a move) would generate phantom leave events.
+// This defines, if the current mouse window (maybe a subwindow) or the
+// main window should get mouse events after pushing (and holding) a mouse
+// button, i.e. when dragging the mouse. This is done by calling SetCapture
+// (see below).
-//#define USE_TRACK_MOUSE
-
-#if !defined(__GNUC__)
-# define USE_TRACK_MOUSE
-#endif // !__GNUC__
-
+#ifdef USE_TRACK_MOUSE
+#define USE_CAPTURE_MOUSE_WIN
+#endif // USE_TRACK_MOUSE
//
// WM_SYNCPAINT is an "undocumented" message, which is finally defined in
@@ -618,6 +643,9 @@ static int mouse_event(Fl_Window *window, int what, int button,
ClientToScreen(fl_xid(window), &pt);
Fl::e_x_root = pt.x;
Fl::e_y_root = pt.y;
+#ifdef USE_CAPTURE_MOUSE_WIN
+ Fl_Window *mouse_window = window; // save "mouse window"
+#endif
while (window->parent()) {
Fl::e_x += window->x();
Fl::e_y += window->y();
@@ -641,7 +669,11 @@ static int mouse_event(Fl_Window *window, int what, int button,
case 0: // single-click
Fl::e_clicks = 0;
J1:
- if (!fl_capture) SetCapture(fl_xid(window));
+#ifdef USE_CAPTURE_MOUSE_WIN
+ if (!fl_capture) SetCapture(fl_xid(mouse_window)); // use mouse window
+#else
+ if (!fl_capture) SetCapture(fl_xid(window)); // use main window
+#endif
Fl::e_keysym = FL_Button + button;
Fl::e_is_click = 1;
px = pmx = Fl::e_x_root; py = pmy = Fl::e_y_root;
@@ -861,20 +893,26 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
case WM_MOUSEMOVE:
#ifdef USE_TRACK_MOUSE
- if (Fl::belowmouse() != window) {
+ if (track_mouse_win != window) {
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
_TrackMouseEvent(&tme);
+ track_mouse_win = window;
}
#endif // USE_TRACK_MOUSE
mouse_event(window, 3, 0, wParam, lParam);
return 0;
case WM_MOUSELEAVE:
- Fl::belowmouse(0);
- if (!window->parent()) Fl::handle(FL_LEAVE, window);
+ if (track_mouse_win == window) { // we left the top level window !
+ Fl_Window *tw = window;
+ while (tw->parent()) tw = tw->window(); // find top level window
+ Fl::belowmouse(0);
+ Fl::handle(FL_LEAVE, tw);
+ }
+ track_mouse_win = 0; // force TrackMouseEvent() restart
break;
case WM_SETFOCUS: