From 7dc496e97d3d9fbc71ffd75b6c4ceb5cfe93ffa5 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Thu, 29 Jun 2017 09:44:35 +0000 Subject: HiDPI support for WIN32 platform: begin to support screen-specific scale factor. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12280 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_win32.cxx | 33 ++++++++++++++++++++++---- src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H | 11 ++++----- src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx | 18 +++++++------- src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H | 3 +++ src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 11 ++++++++- 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 7e99d76c0..2a16a43d3 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -1112,7 +1112,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar #ifdef FLTK_HIDPI_SUPPORT case 0x02E0: { // WM_DPICHANGED: float f = HIWORD(wParam)/96.; - Fl::screen_driver()->scale(0, f); + //for now, same scale factor for each screen + for (int i = 0; i < Fl::screen_count(); i++) Fl::screen_driver()->scale(i, f); Fl_Graphics_Driver::default_driver().scale(f); //fprintf(LOG,"WM_DPICHANGED f=%.2f\n", f);fflush(LOG); if (!window->parent()) { @@ -1445,7 +1446,17 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar 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); - window->position(nx/scale, ny/scale); } + window->position(nx/scale, ny/scale); +// detect when window changes screen + Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); + int news = sd->screen_num_unscaled(nx + window->w()*scale, ny + window->h()*scale); + Fl_WinAPI_Window_Driver *wd = Fl_WinAPI_Window_Driver::driver(window); + int olds = wd->screen_num(); + if (olds != news) { + wd->screen_num(news); +//fprintf(LOG,"olds=%d news=%d\n",olds,news); + } + } break; case WM_SETCURSOR: @@ -1529,7 +1540,7 @@ static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, in int ret = bx = by = bt = 0; int fallback = 1; - float s = Fl::screen_driver()->scale(((Fl_Window*)w)->driver()->screen_num()); + float s = Fl::screen_driver()->scale(w->driver()->screen_num()); if (!w->parent()) { if (fl_xid(w)) { Fl_WinAPI_Window_Driver *dr = (Fl_WinAPI_Window_Driver*)w->driver(); @@ -1801,7 +1812,19 @@ Fl_X* Fl_WinAPI_Window_Driver::makeWindow() { DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; DWORD styleEx = WS_EX_LEFT; - float s = Fl::screen_driver()->scale(0); + //compute adequate screen where to put the window + int nscreen = 0; + if (w->parent()) { + nscreen = w->top_window()->driver()->screen_num(); + } else if (w->driver()->force_position() && Fl_WinAPI_Window_Driver::driver(w)->screen_num_ >= 0) { + nscreen = w->driver()->screen_num(); + } else { + Fl_Window *hint = Fl::first_window(); + if (hint) { + nscreen = hint->top_window()->driver()->screen_num(); + } + } + float s = Fl::screen_driver()->scale(nscreen); int xp = w->x() * s; // these are in graphical units int yp = w->y() * s; int wp = w->w() * s; @@ -1978,7 +2001,7 @@ void Fl_WinAPI_Window_Driver::set_minmax(LPMINMAXINFO minmax) hd *= 2; hd += td; - float s = Fl::screen_driver()->scale(0); + float s = Fl::screen_driver()->scale(screen_num()); minmax->ptMinTrackSize.x = s*minw() + wd; minmax->ptMinTrackSize.y = s*minh() + hd; if (maxw()) { diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H index e81120fea..6dbfa7848 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H @@ -37,14 +37,14 @@ protected: RECT screens[MAX_SCREENS]; RECT work_area[MAX_SCREENS]; float dpi[MAX_SCREENS][2]; + float scale_of_screen[MAX_SCREENS]; static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM); BOOL screen_cb(HMONITOR mon, HDC, LPRECT r); - int screen_num_unscaled(int x, int y); int get_mouse_unscaled(int &mx, int &my); public: - Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { scale_ = 1; } + Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { } // --- display management virtual int visual(int flags); // --- screen configuration @@ -55,6 +55,7 @@ public: virtual int h(); virtual void screen_xywh(int &X, int &Y, int &W, int &H, int n); virtual void screen_dpi(float &h, float &v, int n=0); + int screen_num_unscaled(int x, int y); float DWM_scaling_factor(int screen_num); virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n); // --- audible output @@ -87,11 +88,9 @@ public: return SYSTEMWIDE_APP_SCALING; } #endif - virtual float scale(int n) {return scale_;} - virtual void scale(int n, float f) { scale_ = f;} + virtual float scale(int n) {return scale_of_screen[n];} + virtual void scale(int n, float f) { scale_of_screen[n] = f;} virtual float desktop_scale_factor(); -private: - float scale_; }; diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx index e4a3361f5..236a33288 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx @@ -100,6 +100,7 @@ BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC, LPRECT r) screens[num_screens] = mi.rcMonitor; // If we also want to record the work area, we would also store mi.rcWork at this point work_area[num_screens] = mi.rcWork; + scale_of_screen[num_screens] = 1; /*fl_alert("screen %d %d,%d,%d,%d work %d,%d,%d,%d",num_screens, screens[num_screens].left,screens[num_screens].right,screens[num_screens].top,screens[num_screens].bottom, work_area[num_screens].left,work_area[num_screens].right,work_area[num_screens].top,work_area[num_screens].bottom); @@ -152,6 +153,7 @@ void Fl_WinAPI_Screen_Driver::init() screens[0].right = GetSystemMetrics(SM_CXSCREEN); screens[0].bottom = GetSystemMetrics(SM_CYSCREEN); work_area[0] = screens[0]; + scale_of_screen[0] = 1; } @@ -159,10 +161,10 @@ void Fl_WinAPI_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, i { if (num_screens < 0) init(); if (n < 0 || n >= num_screens) n = 0; - X = work_area[n].left/scale_; - Y = work_area[n].top/scale_; - W = (work_area[n].right - X)/scale_; - H = (work_area[n].bottom - Y)/scale_; + X = work_area[n].left/scale_of_screen[n]; + Y = work_area[n].top/scale_of_screen[n]; + W = (work_area[n].right - X)/scale_of_screen[n]; + H = (work_area[n].bottom - Y)/scale_of_screen[n]; } @@ -174,10 +176,10 @@ void Fl_WinAPI_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) n = 0; if (num_screens > 0) { - X = screens[n].left/scale_; - Y = screens[n].top/scale_; - W = (screens[n].right - screens[n].left)/scale_; - H = (screens[n].bottom - screens[n].top)/scale_; + X = screens[n].left/scale_of_screen[n]; + Y = screens[n].top/scale_of_screen[n]; + W = (screens[n].right - screens[n].left)/scale_of_screen[n]; + H = (screens[n].bottom - screens[n].top)/scale_of_screen[n]; } else { /* Fallback if something is broken... */ X = 0; diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H index 61d456edb..7f548c58b 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H @@ -61,6 +61,7 @@ class FL_EXPORT Fl_WinAPI_Window_Driver : public Fl_Window_Driver HICON big_icon; HICON small_icon; }; + int screen_num_; private: void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset); @@ -70,6 +71,8 @@ public: static inline Fl_WinAPI_Window_Driver* driver(Fl_Window *w) {return (Fl_WinAPI_Window_Driver*)w->driver();} HDC private_dc; // used for OpenGL RECT border_width_title_bar_height(int &bx, int &by, int &bt); + virtual void screen_num(int n) { screen_num_ = n; } + virtual int screen_num(); struct icon_data *icon_; HCURSOR cursor; diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx index 0229f3cce..079ca743d 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx @@ -48,6 +48,7 @@ Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win) icon_ = new icon_data; memset(icon_, 0, sizeof(icon_data)); cursor = NULL; + screen_num_ = -1; } @@ -60,6 +61,13 @@ Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver() delete icon_; } +int Fl_WinAPI_Window_Driver::screen_num() { + if (pWindow->parent()) { + screen_num_ = pWindow->top_window()->driver()->screen_num(); + } + return screen_num_ >= 0 ? screen_num_ : 0; +} + RECT // frame of the decorated window in screen coordinates Fl_WinAPI_Window_Driver::border_width_title_bar_height( @@ -395,7 +403,7 @@ void Fl_WinAPI_Window_Driver::make_current() { #endif // USE_COLORMAP fl_graphics_driver->clip_region(0); - fl_graphics_driver->scale(Fl::screen_driver()->scale(0)); + fl_graphics_driver->scale(Fl::screen_driver()->scale(screen_num())); fl_graphics_driver->line_style(FL_SOLID); // scale also default line width } @@ -489,6 +497,7 @@ void Fl_WinAPI_Window_Driver::hide() { if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown()) Fl::first_window()->show(); delete ip; + screen_num_ = -1; } -- cgit v1.2.3