Windows: improve moving window across screens having distinct scale factors.
This commit is contained in:
parent
0e570fb672
commit
46e6815612
103
src/Fl_win32.cxx
103
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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user