From 890f538bb5cafafe40aa0c7d8ca1c31561c55761 Mon Sep 17 00:00:00 2001 From: MatthiasWM Date: Wed, 16 Jul 2025 17:39:07 +0200 Subject: Generate better FL_LEAVE coordinates on Windows (#87) Use the current mouse position to estimate the position where the mouse left the window. Not perfect, but much better than repeating the last move coordinates. --- src/Fl_win32.cxx | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index ac3bd1460..d31568778 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -45,6 +45,7 @@ // Some versions of MinGW now require us to explicitly include winerror to get S_OK defined #include #include // for ceil() and round() +#include // for min and max (clamp is C++17) void fl_free_fonts(void); void fl_release_dc(HWND, HDC); @@ -117,6 +118,11 @@ extern void fl_cleanup_pens(void); // Internal functions static void fl_clipboard_notify_target(HWND wnd); static void fl_clipboard_notify_untarget(HWND wnd); +static int clamp(int v, int a, int b) { + if (v < a) return a; + if (v > b) return b; + return v; +} // Internal variables static HWND clipboard_wnd = 0; @@ -1023,6 +1029,12 @@ void fl_get_codepage() { HWND fl_capture; +// \param[in] window The FLTK window that generated the event +// \param[in] what 0 = down, 1 = double down, 2 = up, 3 = move +// \param[in] button 1 = left, 2 = middle, 3 = right, 4 = XBUTTON1, 5 = any other XBUTTON +// \param[in] wParam depends on event, for example MK_LBUTTON, MK_MBUTTON, MK_RBUTTON, MK_XBUTTON1, MK_XBUTTON2 +// \param[in] lParam 32 bit value, top 16 bit are the signed y coordinate, bottom 16 bits is x in window space +// WM_KILLFOCUS calls this with (Fl::grab(), 0, 1, MK_LBUTTON, MAKELPARAM(32767, 0)) static int mouse_event(Fl_Window *window, int what, int button, WPARAM wParam, LPARAM lParam) { static int px, py, pmx, pmy; @@ -1391,6 +1403,16 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar Fl_Window *tw = window; while (tw->parent()) // find top level window tw = tw->window(); + // Get a better mouse position for FL_LEAVE event (#87) + POINT pt; + if (GetCursorPos(&pt)) { + float scale = Fl::screen_driver()->scale(tw->screen_num()); + Fl::e_x_root = int(pt.x / scale); + Fl::e_y_root = int(pt.y / scale); + ScreenToClient(fl_xid(tw), &pt); + Fl::e_x = clamp(int(pt.x / scale), 0, window->w() - 1); + Fl::e_y = clamp(int(pt.y / scale), 0, window->h() - 1); + } Fl::belowmouse(0); Fl::handle(FL_LEAVE, tw); } @@ -1407,8 +1429,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_KILLFOCUS: if (Fl::grab() && (Fl::grab() != window) && Fl::grab()->menu_window()) { - // simulate click at remote location (see issue #1166) - mouse_event(Fl::grab(), 0, 1, MK_LBUTTON, MAKELPARAM(100000, 0)); + // simulate click at remote location (see issue #1166), coordinates are signed 16 bit values + mouse_event(Fl::grab(), 0, 1, MK_LBUTTON, MAKELPARAM(32767, 0)); } Fl::handle(FL_UNFOCUS, window); Fl::flush(); // it never returns to main loop when deactivated... -- cgit v1.2.3