diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index b316f6c78..401a1aabe 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -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) { // 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(); } else if (ns != old_ns) { // 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; SetWindowPos(hWnd, NULL, lParam_rect->left, lParam_rect->top, 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); 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; case WM_MOVING: + //fprintf(stderr,"WM_MOVING\n"); moving_window = true; return 1; 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; return 0; @@ -1779,6 +1803,27 @@ content key keyboard layout if (moving_window) resize_bug_fix = window; POINTS pts = MAKEPOINTS(lParam); 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->y(int(round(pts.y / scale))); }