diff options
| author | Manolo Gouy <Manolo> | 2017-06-18 16:01:53 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2017-06-18 16:01:53 +0000 |
| commit | 701fa00c7c54a1260f05ef41ee11592059d9f652 (patch) | |
| tree | e256811b8842ac1376e8b3730c42478162849eb0 | |
| parent | 2cda5a4fa682372f294a7a8e9e2b90a9fdb15610 (diff) | |
Advancing HiDPI support for the WIN32 platform - still incomplete.
It's still necessary to compile with -DFLTK_HIDPI_SUPPORT
to activate the new HiDPI support.
Default builds get the same HiDPI support as in FLTK 1.3
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12265 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | src/Fl_win32.cxx | 103 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx | 9 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.H | 2 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx | 32 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx | 10 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H | 5 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx | 44 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H | 2 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx | 29 |
9 files changed, 161 insertions, 75 deletions
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 371a760b9..30e01c0ea 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -505,10 +505,8 @@ void Fl_WinAPI_Screen_Driver::open_display_platform() { HMODULE hMod = LoadLibrary("Shcore.DLL"); if (hMod) { SetProcessDpiAwareness_type fl_SetProcessDpiAwareness = (SetProcessDpiAwareness_type)GetProcAddress(hMod, "SetProcessDpiAwareness"); - HRESULT r = 0; const int PROCESS_PER_MONITOR_DPI_AWARE = 2; - if (fl_SetProcessDpiAwareness) r = fl_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); -//fprintf(LOG,"SetProcessDpiAwareness=%p result=%d\n",fl_SetProcessDpiAwareness,r);fflush(LOG); + if (fl_SetProcessDpiAwareness) fl_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); } #endif // FLTK_HIDPI_SUPPORT OleInitialize(0L); @@ -583,12 +581,19 @@ void Fl_WinAPI_Screen_Driver::disable_im() { //////////////////////////////////////////////////////////////// -int Fl_WinAPI_Screen_Driver::get_mouse(int &x, int &y) { +int Fl_WinAPI_Screen_Driver::get_mouse_unscaled(int &mx, int &my) { POINT p; GetCursorPos(&p); - x = p.x; - y = p.y; - return screen_num(x, y); + mx = p.x; my = p.y; + return screen_num_unscaled(mx, my); +} + +int Fl_WinAPI_Screen_Driver::get_mouse(int &x, int &y) { + int n = get_mouse_unscaled(x, y); + float s = scale(n); + x = x/s; + y = y/s; + return n; } //////////////////////////////////////////////////////////////// @@ -801,7 +806,7 @@ void Fl_WinAPI_System_Driver::paste(Fl_Widget &receiver, int clipboard, const ch int hdots = GetDeviceCaps(hdc, HORZRES); ReleaseDC(NULL, hdc); float factor = (100.f * hmm) / hdots; - float scaling = Fl_WinAPI_Screen_Driver::desktop_scaling_factor(); + float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor(receiver.top_window()->driver()->screen_num()); width = int(width * scaling / factor); // convert to screen pixel unit height = int(height * scaling / factor); RECT rect = {0, 0, width, height}; @@ -1153,7 +1158,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar } // convert i->region in FLTK units to R2 in drawing units - R2 = Fl_GDI_Graphics_Driver::scale_region(i->region, scale, false); + R2 = Fl_GDI_Graphics_Driver::scale_region(i->region, scale, NULL, false); if (R2) { // Also tell WIN32 that we are drawing someplace else as well... @@ -1168,7 +1173,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar } // convert R2 in drawing units to i->region in FLTK units - i->region = Fl_GDI_Graphics_Driver::scale_region(R2, 1/scale, false, true); + i->region = Fl_GDI_Graphics_Driver::scale_region(R2, 1/scale, NULL, false /*, true*/); window->clear_damage((uchar)(window->damage()|FL_DAMAGE_EXPOSE)); // These next two statements should not be here, so that all update @@ -1524,8 +1529,20 @@ 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()); if (!w->parent()) { - if (fl_xid(w) || style) { + if (fl_xid(w)) { + Fl_WinAPI_Window_Driver *dr = (Fl_WinAPI_Window_Driver*)w->driver(); + dr->border_width_title_bar_height(bx, by, bt); + xoff = bx; + yoff = by + bt; + dx = 2*bx; + dy = 2*by + bt; + X = w->x()*s - bx; + Y = w->y()*s - bt - by; + W = w->w()*s + dx; + H = w->h()*s + dy; + } else if (fl_xid(w) || style) { // The block below calculates the window borders by requesting the // required decorated window rectangle for a desired client rectangle. // If any part of the function above fails, we will drop to a @@ -1539,10 +1556,10 @@ static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, in } RECT r; - r.left = w->x(); - r.top = w->y(); - r.right = w->x()+w->w(); - r.bottom = w->y()+w->h(); + r.left = w->x() * s; + r.top = w->y() * s; + r.right = (w->x()+w->w())*s; + r.bottom = (w->y()+w->h())*s; // get the decoration rectangle for the desired client rectangle BOOL ok = AdjustWindowRectEx(&r, style, FALSE, styleEx); if (ok) { @@ -1550,13 +1567,13 @@ static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, in Y = r.top; W = r.right - r.left; H = r.bottom - r.top; - bx = w->x() - r.left; - by = r.bottom - w->y() - w->h(); // height of the bottom frame - bt = w->y() - r.top - by; // height of top caption bar + bx = w->x() *s - r.left; + by = r.bottom - (w->y() + w->h())*s; // height of the bottom frame + bt = w->y() * s - r.top - by; // height of top caption bar xoff = bx; yoff = by + bt; - dx = W - w->w(); - dy = H - w->h(); + dx = W - w->w() * s; + dy = H - w->h() * s; if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh)) ret = 2; else @@ -1598,7 +1615,8 @@ static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, in //Find screen that contains most of the window //FIXME: this ought to be the "work area" instead of the entire screen ! int scr_x = 0, scr_y = 0, scr_w = 0, scr_h = 0; - Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H); + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X/s, Y/s, W/s, H/s); + scr_x *= s; scr_y *= s; scr_w *= s; scr_h *= s; //Make border's lower right corner visible if (scr_x+scr_w < X+W) X = scr_x+scr_w - W; if (scr_y+scr_h < Y+H) Y = scr_y+scr_h - H; @@ -1606,8 +1624,8 @@ static int fake_X_wm_style(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, in if (X<scr_x) X = scr_x; if (Y<scr_y) Y = scr_y; //Make client area's lower right corner visible - if (scr_x+scr_w < X+dx+ w->w()) X = scr_x+scr_w - w->w() - dx; - if (scr_y+scr_h < Y+dy+ w->h()) Y = scr_y+scr_h - w->h() - dy; + if (scr_x+scr_w < X+dx+ w->w()) X = scr_x+scr_w - w->w()*s - dx; + if (scr_y+scr_h < Y+dy+ w->h()) Y = scr_y+scr_h - w->h()*s - dy; //Make client area's upper left corner visible if (X+xoff < scr_x) X = scr_x-xoff; if (Y+yoff < scr_y) Y = scr_y-yoff; @@ -1659,6 +1677,8 @@ void Fl_WinAPI_Window_Driver::resize(int X,int Y,int W,int H) { if (!pWindow->resizable()) pWindow->size_range(w(), h(), w(), h()); int dummy_x, dummy_y, bt, bx, by; //Ignore window managing when resizing, so that windows (and more + float s = Fl::screen_driver()->scale(screen_num()); + X *= s; Y *= s; W *= s; H *= s; //specifically menus) can be moved offscreen. if (fake_X_wm(dummy_x, dummy_y, bt, bx, by)) { X -= bx; @@ -1670,8 +1690,8 @@ void Fl_WinAPI_Window_Driver::resize(int X,int Y,int W,int H) { // will cause continouly new redraw events. if (W<=0) W = 1; if (H<=0) H = 1; - float s = Fl::screen_driver()->scale(0); - SetWindowPos(fl_xid(pWindow), 0, X*s, Y*s, W*s, H*s, flags); + SetWindowPos(fl_xid(pWindow), 0, X, Y, W, H, flags); +//fprintf(LOG,"parent=%p bt=%d X=%d W=%d H=%d s=%f\n",pWindow->parent(),bt,int(X),int(W),int(H),s);fflush(LOG); } } @@ -1782,7 +1802,7 @@ Fl_X* Fl_WinAPI_Window_Driver::makeWindow() { DWORD styleEx = WS_EX_LEFT; float s = Fl::screen_driver()->scale(0); - int xp = w->x() * s; + int xp = w->x() * s; // these are in graphical units int yp = w->y() * s; int wp = w->w() * s; int hp = w->h() * s; @@ -1834,7 +1854,7 @@ Fl_X* Fl_WinAPI_Window_Driver::makeWindow() { break; } - int xwm = xp , ywm = yp , bt, bx, by; + int xwm = xp , ywm = yp , bt, bx, by; // these are in graphical units fake_X_wm_style(w, xwm, ywm, bt, bx, by, style, styleEx, maxw(), minw(), maxh(), minh(), size_range_set()); if (by+bt) { wp += 2*bx; @@ -2456,8 +2476,8 @@ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top top = left = bottom = right = NULL; if (!shown() || parent() || !border() || !visible()) return; int wsides, hbottom, bt; - float scaling = 1; - RECT r = border_width_title_bar_height(wsides, hbottom, bt, &scaling); + float scaling = Fl::screen_driver()->scale(screen_num()); + RECT r = border_width_title_bar_height(wsides, hbottom, bt); int htop = bt + hbottom; Window save_win = fl_window; Fl_Surface_Device::push_current( Fl_Display_Device::display_device() ); @@ -2465,20 +2485,33 @@ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top Fl::check(); void* save_gc = fl_graphics_driver->gc(); fl_graphics_driver->gc(GetDC(NULL)); - int ww = w() + 2 * wsides; + int ww = w()*scaling + 2 * wsides; + wsides /= scaling; if (wsides < 1) wsides = 1; + ww /= scaling; if (wsides <= 1) ww = w() + 2*wsides; +#ifdef FLTK_HIDPI_SUPPORT + float DWMscaling = scaling; +#else + float DWMscaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor(0); +#endif // capture the 4 window sides from screen + Fl_WinAPI_Screen_Driver *dr = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); if (htop) { - r_top = Fl::screen_driver()->read_win_rectangle(NULL, r.left, r.top, r.right - r.left + 1, htop, 0); + r_top = dr->read_win_rectangle_unscaled(NULL, r.left, r.top, r.right - r.left, htop, 0); top = Fl_Shared_Image::get(r_top); - if (scaling >= 1.1) top->scale(ww, htop/scaling, 0); + if (DWMscaling >= 1.1) top->scale(ww, htop/DWMscaling, 0, 1); } if (wsides) { - r_left = Fl::screen_driver()->read_win_rectangle(NULL, r.left, r.top + htop, wsides, h(), 0); + r_left = dr->read_win_rectangle_unscaled(NULL, r.left, r.top + htop, wsides, h()*scaling, 0); left = Fl_Shared_Image::get(r_left); - r_right = Fl::screen_driver()->read_win_rectangle(NULL, r.right - wsides, r.top + htop, wsides, h(), 0); + r_right = dr->read_win_rectangle_unscaled(NULL, r.right - wsides, r.top + htop, wsides, h()*scaling, 0); right = Fl_Shared_Image::get(r_right); - r_bottom = Fl::screen_driver()->read_win_rectangle(NULL, r.left, r.bottom-hbottom, ww, hbottom, 0); + r_bottom = dr->read_win_rectangle_unscaled(NULL, r.left, r.bottom-hbottom, ww, hbottom, 0); bottom = Fl_Shared_Image::get(r_bottom); + if (scaling >= 1.1) { + left->scale(wsides, h(), 0, 1); + right->scale(wsides, h(), 0, 1); + bottom->scale(ww, hbottom, 0, 1); + } } ReleaseDC(NULL, (HDC)fl_graphics_driver->gc()); fl_window = save_win; diff --git a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx index 1e7584fa8..e3d43664c 100644 --- a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx @@ -60,8 +60,13 @@ Fl_GDI_Copy_Surface_Driver::Fl_GDI_Copy_Surface_Driver(int w, int h) : Fl_Copy_S float factorw = (100.f * hmm) / hdots; float factorh = (100.f * vmm) / vdots; // Global display scaling factor: 1, 1.25, 1.5, 1.75, etc... - float scaling = Fl_WinAPI_Screen_Driver::desktop_scaling_factor(); - +#ifdef FLTK_HIDPI_SUPPORT + float scaling = Fl_Graphics_Driver::default_driver().scale(); + factorw *= scaling; + factorh *= scaling; +#else + float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor(0); +#endif RECT rect; rect.left = 0; rect.top = 0; rect.right = (LONG)((w/scaling) * factorw); rect.bottom = (LONG)((h/scaling) * factorh); gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL); if (gc != NULL) { diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H index a641e4c89..0ab48418b 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H @@ -89,7 +89,7 @@ public: void XDestroyRegion(Fl_Region r); void translate_all(int x, int y); void untranslate_all(void); - static HRGN scale_region(HRGN r, float f, bool keep, bool inflate=false); + static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr, bool keep/*, bool inflate=false*/); virtual void scale(float f); virtual float scale(); protected: diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx index 00bade1b1..41948b83a 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx @@ -146,7 +146,7 @@ void Fl_GDI_Graphics_Driver::translate_all(int x, int y) { depth = stack_height - 1; } GetWindowOrgEx((HDC)gc(), origins+depth); - SetWindowOrgEx((HDC)gc(), origins[depth].x - x, origins[depth].y - y, NULL); + SetWindowOrgEx((HDC)gc(), origins[depth].x - x*scale_, origins[depth].y - y*scale_, NULL); depth++; } @@ -243,24 +243,44 @@ float Fl_GDI_Graphics_Driver::scale() { /* Rescale region r with factor f and returns the scaled region. The input region is deleted if keep is false. - The input region is inflated by 1 unit before rescaling if inflate is true. + //The input region is inflated by 1 unit before rescaling if inflate is true. Region r is returned unchanged if r is null or f is 1. */ -HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, bool keep, bool inflate) { +HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr, bool keep/*, bool inflate*/) { if (r && f != 1) { DWORD size = GetRegionData(r, 0, NULL); RGNDATA *pdata = (RGNDATA*)malloc(size); GetRegionData(r, size, pdata); if (!keep) DeleteObject(r); - if (inflate) { + /*if (inflate) { // seems no longer useful RECT *rects = (RECT*)&(pdata->Buffer); for (DWORD i = 0; i < pdata->rdh.nCount; i++) { InflateRect(rects+i, 1, 1); } + }*/ + POINT pt = {0, 0}; + if (dr && dr->depth >= 1) { // account for both scaling and translation + GetWindowOrgEx((HDC)dr->gc(), &pt); + pt.x *= (f - 1); + pt.y *= (f - 1); } - XFORM xform = {f, 0, 0, f, 0, 0}; + XFORM xform = {f, 0, 0, f, (FLOAT)pt.x , (FLOAT)pt.y}; r = ExtCreateRegion(&xform, size, pdata); free(pdata); + + if (dr && int(f) != f && f > 1) { // needed for clean checkers demo + DWORD size = GetRegionData(r, 0, NULL); + RGNDATA *pdata = (RGNDATA*)malloc(size); + GetRegionData(r, size, pdata); + DeleteObject(r); + RECT *rects = (RECT*)&(pdata->Buffer); + for (DWORD i = 0; i < pdata->rdh.nCount; i++) { + InflateRect(rects+i, 1, 1); + } + r = ExtCreateRegion(NULL, size, pdata); + free(pdata); + } + } return r; } @@ -268,7 +288,7 @@ HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, bool keep, bool infla Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) { HRGN r = rstack[rstackptr]; - HRGN r2 = scale_region(r, f, true); + HRGN r2 = scale_region(r, f, this, true); return (r == r2 ? NULL : (rstack[rstackptr] = r2, r)); } diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx index e55e69583..904511fe0 100644 --- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx @@ -21,6 +21,7 @@ #ifdef FL_CFG_GFX_GDI #include "Fl_GDI_Graphics_Driver.H" +#include "../WinAPI/Fl_WinAPI_Screen_Driver.H" #include <FL/Fl_Image_Surface.H> #include <FL/fl_draw.H> #include <FL/x.H> @@ -55,7 +56,9 @@ Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_ w = int(w*d); h = int(h*d); } - offscreen = off ? off : CreateCompatibleBitmap( (fl_graphics_driver->gc() ? (HDC)fl_graphics_driver->gc() : fl_GetDC(0) ) , w, h); + HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); + offscreen = off ? off : CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h); + if (!offscreen) offscreen = CreateCompatibleBitmap(fl_GetDC(0), w, h); driver(new Fl_GDI_Graphics_Driver); if (d != 1 && high_res) driver()->scale(d); _sgc = NULL; @@ -93,11 +96,8 @@ void Fl_GDI_Image_Surface_Driver::untranslate() { Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image() { - unsigned char *data; - data = fl_read_image(NULL, 0, 0, width, height, 0); + Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0); previous->driver()->gc(_sgc); - Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height); - image->alloc_array = 1; return image; } diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H index 503eb308d..e81120fea 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H @@ -40,6 +40,8 @@ protected: 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; } @@ -53,7 +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); - static float desktop_scaling_factor(); + float DWM_scaling_factor(int screen_num); virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n); // --- audible output virtual void beep(int type); @@ -74,6 +76,7 @@ public: virtual int dnd(int unused); virtual int compose(int &del); virtual Fl_RGB_Image *read_win_rectangle(uchar *p, int X, int Y, int w, int h, int alpha); + Fl_RGB_Image *read_win_rectangle_unscaled(uchar *p, int X, int Y, int w, int h, int alpha); virtual int get_mouse(int &x, int &y); virtual void enable_im(); virtual void disable_im(); diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx index e9ca9d2fb..e4a3361f5 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx @@ -159,10 +159,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; - Y = work_area[n].top; - W = work_area[n].right - X; - H = work_area[n].bottom - Y; + 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_; } @@ -174,10 +174,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; - Y = screens[n].top; - W = screens[n].right - screens[n].left; - H = screens[n].bottom - screens[n].top; + 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_; } else { /* Fallback if something is broken... */ X = 0; @@ -512,7 +512,7 @@ int Fl_WinAPI_Screen_Driver::compose(int &del) { } -Fl_RGB_Image * // O - image or NULL if failed +Fl_RGB_Image * // O - image or NULL if failed Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NULL to allocate int X, // I - Left position int Y, // I - Top position @@ -520,6 +520,12 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NU int h, // I - Height of area to read int alpha) // I - Alpha value for image (0 for none) { + float s = Fl_Surface_Device::surface()->driver()->scale(); + return read_win_rectangle_unscaled(p, X*s, Y*s, w*s, h*s, alpha); +} + +Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(uchar *p, int X, int Y, int w, int h, int alpha) +{ int d; // Depth of image // Allocate the image data array as needed... @@ -614,11 +620,11 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NU return rgb; } -/** Returns the current desktop scaling factor (1.75 for example) +/* Returns the current desktop scaling factor for screen_num (1.75 for example) */ -float Fl_WinAPI_Screen_Driver::desktop_scaling_factor() { +float Fl_WinAPI_Screen_Driver::DWM_scaling_factor(int screen_num) { #ifdef FLTK_HIDPI_SUPPORT - return 1;// this becomes useless if FLTK app are made DPI-aware by calling SetProcessDpiAwareness() + return scale(screen_num); #else // Compute the global desktop scaling factor: 1, 1.25, 1.5, 1.75, etc... // This factor can be set in Windows 10 by @@ -651,6 +657,20 @@ void Fl_WinAPI_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int & } } +int Fl_WinAPI_Screen_Driver::screen_num_unscaled(int x, int y) +{ + int screen = 0; + if (num_screens < 0) init(); + for (int i = 0; i < num_screens; i ++) { + if (x >= screens[i].left && x < screens[i].right && + y >= screens[i].top && y < screens[i].bottom) { + screen = i; + break; + } + } + return screen; +} + // // End of "$Id$". // diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H index 59ced3e37..acd8f7603 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H @@ -62,7 +62,6 @@ class FL_EXPORT Fl_WinAPI_Window_Driver : public Fl_Window_Driver HICON small_icon; }; private: - RECT border_width_title_bar_height(int &bx, int &by, int &bt, float *pscaling = NULL); void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset); public: @@ -70,6 +69,7 @@ public: ~Fl_WinAPI_Window_Driver(); 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); 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 1d496edff..e39a2ed5a 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx @@ -59,14 +59,11 @@ Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver() } -// --- private - RECT // frame of the decorated window in screen coordinates Fl_WinAPI_Window_Driver::border_width_title_bar_height( int &bx, // left and right border width int &by, // bottom border height (=bx) - int &bt, // height of window title bar - float *pscaling // display scaling factor + int &bt // height of window title bar ) { Fl_Window *win = pWindow; @@ -83,14 +80,12 @@ RECT // frame of the decorated window in screen coordinates const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9; if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) { need_r = 0; - scaling = Fl_WinAPI_Screen_Driver::desktop_scaling_factor(); + scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor(screen_num()); } } if (need_r) { GetWindowRect(fl_xid(win), &r); } - if (pscaling) *pscaling = scaling; - bx = (r.right - r.left - int(win->w() * scaling))/2; if (bx < 1) bx = 1; by = bx; @@ -105,16 +100,24 @@ RECT // frame of the decorated window in screen coordinates int Fl_WinAPI_Window_Driver::decorated_w() { int bt, bx, by; + float s = Fl::screen_driver()->scale(screen_num()); border_width_title_bar_height(bx, by, bt); - return w() + 2 * bx; + int mini_bx = bx/s; if (mini_bx < 1) mini_bx = 1; + return w() + 2 * mini_bx; } int Fl_WinAPI_Window_Driver::decorated_h() { int bt, bx, by; - float scaling = 1; - border_width_title_bar_height(bx, by, bt, &scaling); - return h() + bt/scaling + 2 * by; + border_width_title_bar_height(bx, by, bt); +#ifdef FLTK_HIDPI_SUPPORT + float s = Fl::screen_driver()->scale(screen_num()); + int mini_by = by/s; if (mini_by < 1) mini_by = 1; + return h() + (bt + by)/s + mini_by; +#else + float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor(0); + return h() + bt/scaling + 2 * by +1; +#endif } @@ -596,7 +599,7 @@ int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, static fl_GetRandomRgn_func fl_GetRandomRgn = 0L; static char first_time = 1; // We will have to do some Region magic now, so let's see if the - // required function is available (and it should be staring w/Win95) + // required function is available (and it should be starting w/Win95) if (first_time) { HMODULE hMod = GetModuleHandle("GDI32.DLL"); if (hMod) { @@ -604,6 +607,8 @@ int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, } first_time = 0; } + float s = Fl::screen_driver()->scale(screen_num()); + src_x *= s; src_y *= s; src_w *= s; src_h *= s; dest_x *= s; dest_y *= s; // Now check if the source scrolling area is fully visible. // If it is, we will do a quick scroll and just update the // newly exposed area. If it is not, we go the safe route and |
