diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-04 16:45:11 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-04 16:45:11 +0100 |
| commit | 46e681561241d0a123dfc08c234745c40c4a262a (patch) | |
| tree | 96e7f272127d5ba050222832f0fb5cc950c2f3a3 /src | |
| parent | 0e570fb6729ff6b97249256c2c9d5f3aa58c7bb4 (diff) | |
Windows: improve moving window across screens having distinct scale factors.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_win32.cxx | 103 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx | 13 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H | 16 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 12 |
4 files changed, 82 insertions, 62 deletions
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 728e25557..abb875be7 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -1208,11 +1208,35 @@ extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx static Fl_Window *resize_bug_fix; +static bool moving_window = false; // true when dragging a window with the mouse on the titlebar extern void fl_save_pen(void); extern void fl_restore_pen(void); extern LRESULT fl_win32_tablet_handler(MSG& msg); + +static void invalidate_gl_win(Fl_Window *glwin) { + static Fl_WinAPI_Plugin *plugin = NULL; + if (!plugin) { + Fl_Plugin_Manager pm("winapi.fltk.org"); + plugin = (Fl_WinAPI_Plugin*)pm.plugin("gl.winapi.fltk.org"); + } + plugin->invalidate(glwin); +} + + +static BOOL CALLBACK child_window_cb(HWND child_xid, LPARAM data) { + Fl_Window *child = fl_find(child_xid); + if (data) { + float s = *(float*)data; + SetWindowPos(child_xid, 0, int(round(child->x() * s)), int(round(child->y() * s)), + int(round(child->w() * s)), int(round(child->h() * s)), 0); + } + if (child->as_gl_window()) invalidate_gl_win(child); + return TRUE; +} + + static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Copy the message to fl_msg so add_handler code can see it. @@ -1234,7 +1258,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar switch (uMsg) { case WM_DPICHANGED: { // 0x02E0, after display re-scaling and followed by WM_DISPLAYCHANGE - if (is_dpi_aware && !Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) { + if (is_dpi_aware) { RECT r, *lParam_rect = (RECT*)lParam; Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); int centerX = (lParam_rect->left + lParam_rect->right)/2; @@ -1251,13 +1275,11 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar sd->update_scaling_capability(); } else if (ns != old_ns) { // jump window with Windows+Shift+L|R-arrow to other screen with other DPI - float scale = Fl::screen_driver()->scale(ns); - int bt, bx, by; - Fl_WinAPI_Window_Driver *wdr = (Fl_WinAPI_Window_Driver*)Fl_Window_Driver::driver(window); - wdr->border_width_title_bar_height(bx, by, bt); - window->position(int(round(lParam_rect->left/scale)), - int(round((lParam_rect->top + bt)/scale))); - wdr->resize_after_scale_change(ns, scale, scale); + if (ns >= 0) window->screen_num(ns); + UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOCOPYBITS; + SetWindowPos(hWnd, NULL, lParam_rect->left, lParam_rect->top, + lParam_rect->right - lParam_rect->left, + lParam_rect->bottom - lParam_rect->top, flags); } } return 0; @@ -1704,26 +1726,34 @@ content key keyboard layout if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) { Fl::handle(FL_HIDE, window); } else { - Fl::handle(FL_SHOW, window); - resize_bug_fix = window; - window->size(int(ceil(LOWORD(lParam) / scale)), int(ceil(HIWORD(lParam) / scale))); - // fprintf(LOG,"WM_SIZE size(%.0f,%.0f) graph(%d,%d) s=%.2f\n", - // ceil(LOWORD(lParam)/scale),ceil(HIWORD(lParam)/scale), - // LOWORD(lParam),HIWORD(lParam),scale); + if (!moving_window) { + Fl::handle(FL_SHOW, window); + resize_bug_fix = window; + window->size(int(ceil(LOWORD(lParam) / scale)), int(ceil(HIWORD(lParam) / scale))); + } else { + window->size(int(ceil(LOWORD(lParam) / scale)), int(ceil(HIWORD(lParam) / scale))); + EnumChildWindows(hWnd, child_window_cb, (LPARAM)&scale); + window->redraw(); + } } } - break; + return 0; + + case WM_MOVING: + moving_window = true; + return 1; + + case WM_CAPTURECHANGED: + moving_window = false; + return 0; case WM_MOVE: { - if (IsIconic(hWnd)) { + if (IsIconic(hWnd) || window->parent()) { break; } resize_bug_fix = window; - int nx = LOWORD(lParam); - int ny = HIWORD(lParam); - if (nx & 0x8000) nx -= 65536; - if (ny & 0x8000) ny -= 65536; - // fprintf(LOG,"WM_MOVE position(%d,%d) s=%.2f\n",int(nx/scale),int(ny/scale),scale); + POINTS pts = MAKEPOINTS(lParam); + int nx = pts.x, ny = pts.y; // detect when window centre changes screen Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver *)Fl::screen_driver(); Fl_WinAPI_Window_Driver *wd = Fl_WinAPI_Window_Driver::driver(window); @@ -1740,30 +1770,15 @@ content key keyboard layout int news = sd->screen_num_unscaled(nx + int(trueW * scale / 2), ny + int(trueH * scale / 2)); if (news == -1) news = olds; - float s = sd->scale(news); - // fprintf(LOG,"WM_MOVE olds=%d(%.2f) news=%d(%.2f) busy=%d\n",olds, - // sd->scale(olds),news, s, - // Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy); - // fflush(LOG); - if (!window->parent()) { - if (olds != news) { - if (s != sd->scale(olds) && - !Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy && - window->user_data() != &Fl_WinAPI_Screen_Driver::transient_scale_display) { - Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy = true; - Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.screen = news; - Fl::add_timeout(1, Fl_WinAPI_Window_Driver::resize_after_screen_change, window); - } - else if (!Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) - wd->screen_num(news); - } else if (Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) { - Fl::remove_timeout(Fl_WinAPI_Window_Driver::resize_after_screen_change, window); - Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy = false; - } + scale = sd->scale(news); + if (olds != news) { + wd->screen_num(news); + if (window->as_gl_window()) invalidate_gl_win(window); } - window->position(int(round(nx/scale)), int(round(ny/scale))); - break; - } // case WM_MOVE + wd->x(int(round(nx/scale))); + wd->y(int(round(ny/scale))); + } + return 0; case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { diff --git a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx index 375408496..8e199b09c 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx @@ -454,6 +454,19 @@ void Fl_WinAPI_Gl_Window_Driver::switch_back() { } +class Fl_WinAPI_Gl_Plugin : public Fl_WinAPI_Plugin { +public: + Fl_WinAPI_Gl_Plugin() : Fl_WinAPI_Plugin(name()) { } + const char *name() override { return "gl.winapi.fltk.org"; } + void invalidate(Fl_Window *w) override { + w->as_gl_window()->valid(0); + } +}; + + +static Fl_WinAPI_Gl_Plugin Gl_Invalidate_Plugin; + + FL_EXPORT HGLRC fl_win32_glcontext(GLContext rc) { return (HGLRC)rc; } #endif // HAVE_GL diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H index 7d208e429..3cf26b67c 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H @@ -23,6 +23,7 @@ #ifndef FL_WINAPI_WINDOW_DRIVER_H #define FL_WINAPI_WINDOW_DRIVER_H +#include <FL/Fl_Plugin.H> #include "../../Fl_Window_Driver.H" #include <windows.h> @@ -71,11 +72,6 @@ public: struct icon_data *icon_; HCURSOR cursor; int custom_cursor; - struct type_for_resize_window_between_screens { - int screen; - bool busy; - }; - static type_for_resize_window_between_screens data_for_resize_window_between_screens_; void set_minmax(LPMINMAXINFO minmax); int fake_X_wm(int &X, int &Y, int &bt, int &bx, int &by, DWORD style = 0, DWORD styleEx = 0); void make_fullscreen(int X, int Y, int W, int H); @@ -120,7 +116,15 @@ public: void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE; int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE; - static void resize_after_screen_change(void *data); +}; + + +class Fl_WinAPI_Plugin : public Fl_Plugin { +public: + Fl_WinAPI_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { } + virtual const char *klass() { return "winapi.fltk.org"; } + virtual const char *name() = 0; + virtual void invalidate(Fl_Window*) = 0; }; diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx index b2735b711..4b27753bf 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx @@ -50,7 +50,6 @@ Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win) Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver() { - Fl::remove_timeout(resize_after_screen_change, pWindow); if (shape_data_) { delete shape_data_->effective_bitmap_; delete shape_data_; @@ -716,17 +715,6 @@ int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, return 0; } -Fl_WinAPI_Window_Driver::type_for_resize_window_between_screens Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_ = {0, false}; - -void Fl_WinAPI_Window_Driver::resize_after_screen_change(void *data) { - Fl_Window *win = (Fl_Window*)data; - RECT r; - GetClientRect(fl_xid(win), &r); - float old_f = float(r.right)/win->w(); - int ns = data_for_resize_window_between_screens_.screen; - Fl_Window_Driver::driver(win)->resize_after_scale_change(ns, old_f, Fl::screen_driver()->scale(ns)); - data_for_resize_window_between_screens_.busy = false; -} const Fl_Image* Fl_WinAPI_Window_Driver::shape() { return shape_data_ ? shape_data_->shape_ : NULL; |
