Fix "Windows rapidly changing scales near edge between screens" - cont'd (#1439)
Build and Test / build-linux (push) Has been cancelled
Build and Test / build-wayland (push) Has been cancelled
Build and Test / build-macos (push) Has been cancelled
Build and Test / build-windows (push) Has been cancelled

This commit is contained in:
ManoloFLTK
2026-05-20 16:51:42 +02:00
parent b2fd08f2e1
commit faf210a1d0
+47 -2
View File
@@ -1238,6 +1238,16 @@ static BOOL CALLBACK child_window_cb(HWND child_xid, LPARAM data) {
} }
static struct win_w_h {
Fl_Window *win;
int W, H;
} moved_win_data; // FLTK size of window at start of the window move operation
static void delayed_size(void *) { // performed after end of win move operation or change of screen
moved_win_data.win->size(moved_win_data.W, moved_win_data.H);
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 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. // Copy the message to fl_msg so add_handler code can see it.
@@ -1276,7 +1286,11 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
sd->update_scaling_capability(); sd->update_scaling_capability();
} else if (ns != old_ns) { } else if (ns != old_ns) {
// jump window with Windows+Shift+L|R-arrow to other screen with other DPI // jump window with Windows+Shift+L|R-arrow to other screen with other DPI
if (ns >= 0) Fl_Window_Driver::driver(window)->screen_num(ns); if (ns >= 0) {
//fprintf(stderr,"WM_DPICHANGED ns %d --> %d moving_window=%d\n",old_ns,ns,moving_window);
Fl_Window_Driver::driver(window)->screen_num(ns);
if (!moving_window) moved_win_data = {window, window->w(), window->h()};
}
UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOCOPYBITS; UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOCOPYBITS;
SetWindowPos(hWnd, NULL, lParam_rect->left, lParam_rect->top, SetWindowPos(hWnd, NULL, lParam_rect->left, lParam_rect->top,
lParam_rect->right - lParam_rect->left, lParam_rect->right - lParam_rect->left,
@@ -1288,6 +1302,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
} }
scale = Fl::screen_driver()->scale(ns); scale = Fl::screen_driver()->scale(ns);
EnumChildWindows(hWnd, child_window_cb, (LPARAM)&scale); EnumChildWindows(hWnd, child_window_cb, (LPARAM)&scale);
if (!moving_window) Fl::add_timeout(0, (Fl_Timeout_Handler)delayed_size, NULL);
} }
} }
} }
@@ -1764,11 +1779,20 @@ content key keyboard layout
return 0; return 0;
case WM_MOVING: case WM_MOVING:
//fprintf(stderr,"WM_MOVING\n");
moving_window = true; moving_window = true;
return 1; return 1;
case WM_CAPTURECHANGED: case WM_CAPTURECHANGED:
moving_window = false; //fprintf(stderr,"WM_CAPTURECHANGED moving_window=%d\n",moving_window);
if (!moving_window) {
moved_win_data.win = window;
moved_win_data.W = window->w();
moved_win_data.H = window->h();
} else {
moving_window = false;
Fl::add_timeout(0, (Fl_Timeout_Handler)delayed_size, NULL);
}
resize_bug_fix = 0; resize_bug_fix = 0;
return 0; return 0;
@@ -1779,6 +1803,27 @@ content key keyboard layout
if (moving_window) resize_bug_fix = window; if (moving_window) resize_bug_fix = window;
POINTS pts = MAKEPOINTS(lParam); POINTS pts = MAKEPOINTS(lParam);
Fl_Window_Driver *wd = Fl_Window_Driver::driver(window); Fl_Window_Driver *wd = Fl_Window_Driver::driver(window);
Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver *)Fl::screen_driver();
// detect when window centre changes screen
int olds = wd->screen_num();
// Issue #1097: when a fullscreen window is restored to its size, it receives first a WM_MOVE
// and then a WM_SIZE, so it still has its fullscreen size at the WM_MOVE event, which defeats
// using window->w()|h() to compute the center of the (small) window. We detect this situation
// with condition: !window->fullscreen_active() && *wd->no_fullscreen_w()
// and use *wd->no_fullscreen_w()|h() instead of window->w()|h().
int trueW = window->w(), trueH = window->h();
if (!window->fullscreen_active() && *wd->no_fullscreen_w()) {
trueW = *wd->no_fullscreen_w(); trueH = *wd->no_fullscreen_h();
}
int news = sd->screen_num_unscaled(pts.x + int(trueW * scale / 2), pts.y + int(trueH * scale / 2));
//fprintf(stderr,"WM_MOVE to %dx%d ns %d--> %d scale=%g\n",pts.x,pts.y,olds,news,sd->scale(news>=0?news:olds));
if (news == -1)
news = olds;
else if (news != olds) {
wd->screen_num(news);
scale = sd->scale(news);
window->redraw();
}
wd->x(int(round(pts.x / scale))); wd->x(int(round(pts.x / scale)));
wd->y(int(round(pts.y / scale))); wd->y(int(round(pts.y / scale)));
} }