summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2017-07-03 17:31:57 +0000
committerManolo Gouy <Manolo>2017-07-03 17:31:57 +0000
commit8dccfc88386561782d9b78900b283cedad2e59bb (patch)
treee241ec766008d154f32f1b3a313fd7233984606a
parentba10af9edb594f69e58e6f2ccb251e3bdff3e9c6 (diff)
HiDPI support under WIN32 platform: completed.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12285 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--FL/Fl_Screen_Driver.H2
-rw-r--r--FL/Fl_Window_Driver.H2
-rw-r--r--src/Fl_Screen_Driver.cxx36
-rw-r--r--src/Fl_Window_Driver.cxx17
-rw-r--r--src/Fl_win32.cxx57
-rw-r--r--src/Fl_x.cxx2
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H19
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx10
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H8
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx20
10 files changed, 121 insertions, 52 deletions
diff --git a/FL/Fl_Screen_Driver.H b/FL/Fl_Screen_Driver.H
index 9d016043d..7f229e22b 100644
--- a/FL/Fl_Screen_Driver.H
+++ b/FL/Fl_Screen_Driver.H
@@ -167,7 +167,7 @@ public:
static int scale_handler(int event);
virtual void init_workarea() {}
virtual float desktop_scale_factor() {return 1;}
- float default_scale_factor();
+ void use_startup_scale_factor();
enum APP_SCALING_CAPABILITY {
NO_APP_SCALING = 0, ///< The platform does not support rescaling.
SYSTEMWIDE_APP_SCALING, ///< The platform supports rescaling with the same factor for all screens.
diff --git a/FL/Fl_Window_Driver.H b/FL/Fl_Window_Driver.H
index 20e3503fc..9a588a46e 100644
--- a/FL/Fl_Window_Driver.H
+++ b/FL/Fl_Window_Driver.H
@@ -108,6 +108,8 @@ public:
void overlay(Fl_Window *o) {
if (pWindow->as_overlay_window()) pWindow->as_overlay_window()->overlay_ = o;
}
+
+ void resize_after_scale_change(int ns, float old_f, float new_f);
// --- window data
virtual int decorated_w() = 0;
diff --git a/src/Fl_Screen_Driver.cxx b/src/Fl_Screen_Driver.cxx
index 0332f59b3..41cffff03 100644
--- a/src/Fl_Screen_Driver.cxx
+++ b/src/Fl_Screen_Driver.cxx
@@ -364,18 +364,7 @@ void Fl_Screen_Driver::rescale_all_windows_from_screen(int screen, float f)
}
for (i = count - 1; i >= 0; i--) { // rescale all top-level windows, finishing with front one
win = win_array[i];
- int oldx = win->x(), oldy = win->y();
- fl_uintptr_t current = win->driver()->current_cursor();
- win->hide();
- win->driver()->screen_num(screen);
- win->position(oldx*old_f/f, oldy*old_f/f);
- win->driver()->force_position(1);
- if (win->fullscreen_active()) {
- win->size(win->w() * old_f/f, win->h() * old_f/f);
- }
- win->show();
- win->driver()->reuse_cursor(current);
- win->driver()->reuse_icons();
+ win->driver()->resize_after_scale_change(screen, old_f, f);
win->wait_for_expose();
}
delete[] win_array;
@@ -469,21 +458,23 @@ int Fl_Screen_Driver::scale_handler(int event)
}
-// determine the scaling value used at startup time (helps supporting HiDPI displays)
-float Fl_Screen_Driver::default_scale_factor()
+// use the startup time scaling value
+void Fl_Screen_Driver::use_startup_scale_factor()
{
- float factor = 1;
+ float factor;
char *p = 0;
if ((p = fl_getenv("FLTK_SCALING_FACTOR"))) {
sscanf(p, "%f", &factor);
+ // checks to prevent potential crash (factor <= 0) or very large factors
+ if (factor < 0.25) factor = 0.25;
+ else if (factor > 10.0) factor = 10.0;
}
else {
factor = desktop_scale_factor();
}
- // checks to prevent potential crash (factor <= 0) or very large factors
- if (factor < 0.25) factor = 0.25;
- else if (factor > 10.0) factor = 10.0;
- return factor;
+ if (factor) {
+ for (int i = 0; i < screen_count(); i++) scale(i, factor);
+ }
}
@@ -495,10 +486,11 @@ void Fl_Screen_Driver::open_display()
been_here = true;
int ns = screen_count();
if (rescalable()) {
- float factor = default_scale_factor();
- for (int i = 0; i < ns; i++) scale(i, factor);
+ use_startup_scale_factor();
Fl::add_handler(Fl_Screen_Driver::scale_handler);
- Fl_Graphics_Driver::default_driver().scale(factor);
+ int mx, my;
+ int ns = Fl::screen_driver()->get_mouse(mx, my);
+ Fl_Graphics_Driver::default_driver().scale(scale(ns));
}
}
}
diff --git a/src/Fl_Window_Driver.cxx b/src/Fl_Window_Driver.cxx
index b750b1ff7..2ec0cfaff 100644
--- a/src/Fl_Window_Driver.cxx
+++ b/src/Fl_Window_Driver.cxx
@@ -260,6 +260,23 @@ int Fl_Window_Driver::screen_num() {
return Fl::screen_num(x(), y(), w(), h());
}
+void Fl_Window_Driver::resize_after_scale_change(int ns, float old_f, float new_f) {
+ int oldx = pWindow->x(), oldy = pWindow->y();
+ fl_uintptr_t current = current_cursor();
+ pWindow->hide();
+ screen_num(ns);
+ pWindow->position(oldx*old_f/new_f, oldy*old_f/new_f);
+ force_position(1);
+ if (pWindow->fullscreen_active()) {
+ pWindow->size(pWindow->w() * old_f/new_f, pWindow->h() * old_f/new_f);
+ }
+ Fl_Graphics_Driver::default_driver().scale(new_f);
+ pWindow->show();
+ reuse_cursor(current);
+ reuse_icons();
+//extern FILE*LOG;fprintf(LOG,"ns=%d old_f%.2f new_f=%.2f\n",ns,old_f,new_f);fflush(LOG);
+}
+
//
// End of "$Id$".
//
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 0366178bc..92a02dd3f 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -515,24 +515,24 @@ void Fl_WinAPI_Screen_Driver::open_display_platform() {
}
-float Fl_WinAPI_Screen_Driver::desktop_scale_factor() {
- float f = 1;
#ifdef FLTK_HIDPI_SUPPORT
+void Fl_WinAPI_Screen_Driver::init_screen_scale_factors() {
typedef HRESULT (WINAPI* GetDpiForMonitor_type)(HMONITOR, int, UINT*, UINT*);
HMODULE hMod = LoadLibrary("Shcore.DLL");
GetDpiForMonitor_type fl_GetDpiForMonitor = NULL;
if (hMod) fl_GetDpiForMonitor = (GetDpiForMonitor_type)GetProcAddress(hMod, "GetDpiForMonitor");
if (fl_GetDpiForMonitor) {
- RECT rect = {0, 0, 0, 0};
- HMONITOR hm = MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY);
- UINT dpiX, dpiY;
- HRESULT r = fl_GetDpiForMonitor(hm, 0, &dpiX, &dpiY);
- if (r == S_OK) f = dpiX/96.;
-//fprintf(LOG, "result=%d dpiX=%d dpiY=%d factor=%.2f\n", r, dpiX, dpiY, f);fflush(LOG);
+ for (int ns = 0; ns < screen_count(); ns++) {
+ HMONITOR hm = MonitorFromRect(&screens[ns], MONITOR_DEFAULTTONEAREST);
+ UINT dpiX, dpiY;
+ HRESULT r = fl_GetDpiForMonitor(hm, 0, &dpiX, &dpiY);
+ float f = (r == S_OK ? dpiX/96. : 1);
+ scale(ns, f);
+//fprintf(LOG, "desktop_scale_factor ns=%d factor=%.2f\n", ns, f);fflush(LOG);
+ }
}
-#endif // FLTK_HIDPI_SUPPORT
- return f;
}
+#endif // FLTK_HIDPI_SUPPORT
class Fl_Win32_At_Exit {
@@ -1111,14 +1111,14 @@ 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.;
- //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()) {
- window->hide();
- window->show();
+ if (!Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) {
+ RECT r;
+ float f = HIWORD(wParam)/96.;
+ GetClientRect(hWnd, &r);
+ float old_f = float(r.right)/window->w();
+ int ns = window->driver()->screen_num();
+ Fl::screen_driver()->scale(ns, f);
+ window->driver()->resize_after_scale_change(ns, old_f, f);
}
}
return 0;
@@ -1446,16 +1446,24 @@ 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);
// 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);
+ int news = sd->screen_num_unscaled(nx + window->w()*scale/2, ny + window->h()*scale/2);
Fl_WinAPI_Window_Driver *wd = Fl_WinAPI_Window_Driver::driver(window);
int olds = wd->screen_num();
+ 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 (olds != news) {
- wd->screen_num(news);
-//fprintf(LOG,"olds=%d news=%d\n",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);
}
+ window->position(nx/scale, ny/scale);
}
break;
@@ -1822,8 +1830,12 @@ Fl_X* Fl_WinAPI_Window_Driver::makeWindow() {
Fl_Window *hint = Fl::first_window();
if (hint) {
nscreen = hint->top_window()->driver()->screen_num();
+ } else {
+ int mx, my;
+ nscreen = Fl::screen_driver()->get_mouse(mx, my);
}
}
+ w->driver()->screen_num(nscreen);
float s = Fl::screen_driver()->scale(nscreen);
int xp = w->x() * s; // these are in graphical units
int yp = w->y() * s;
@@ -2340,6 +2352,7 @@ int Fl_WinAPI_Window_Driver::set_cursor(const Fl_RGB_Image *image, int hotx, int
}
void Fl_WinAPI_Window_Driver::reuse_cursor(fl_uintptr_t c) {
+ cursor = (HCURSOR)c;
SetCursor((HCURSOR)c);
}
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 71d9d95a6..f81ceff9f 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -1252,7 +1252,7 @@ int fl_handle(const XEvent& thisevent)
XRRUpdateConfiguration_f(&xevent);
Fl::call_screen_init();
#if USE_XFT
- float factor = Fl::screen_driver()->default_scale_factor();
+ float factor = Fl::screen_driver()->desktop_scale_factor();
for (int screen = 0; screen <= Fl::screen_count(); screen++)
Fl::screen_driver()->rescale_all_windows_from_screen(screen, factor);
#endif // USE_XFT
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
index 6dbfa7848..682afca25 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
@@ -42,9 +42,14 @@ protected:
static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM);
BOOL screen_cb(HMONITOR mon, HDC, LPRECT r);
int get_mouse_unscaled(int &mx, int &my);
+#ifdef FLTK_HIDPI_SUPPORT
+ void init_screen_scale_factors();
+#endif
public:
- Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { }
+ Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
+ for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1;
+ }
// --- display management
virtual int visual(int flags);
// --- screen configuration
@@ -85,11 +90,17 @@ public:
virtual void offscreen_size(Fl_Offscreen off, int &width, int &height);
#if defined(FLTK_HIDPI_SUPPORT)
virtual APP_SCALING_CAPABILITY rescalable() {
- return SYSTEMWIDE_APP_SCALING;
+ return PER_SCREEN_APP_SCALING;
+ }
+#endif
+#if defined(FLTK_HIDPI_SUPPORT)
+ virtual float scale(int n) {
+ return scale_of_screen[n];
+ }
+ virtual void scale(int n, float f) {
+ scale_of_screen[n] = f;
}
#endif
- 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();
};
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
index 236a33288..5951ba193 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
@@ -100,7 +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;
+//extern FILE*LOG;fprintf(LOG,"screen_cb ns=%d\n",num_screens);fflush(LOG);
/*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);
@@ -141,6 +141,9 @@ void Fl_WinAPI_Screen_Driver::init()
// NOTE: num_screens is incremented in screen_cb so we must first reset it here...
num_screens = 0;
fl_edm(0, 0, screen_cb, (LPARAM)this);
+#ifdef FLTK_HIDPI_SUPPORT
+ init_screen_scale_factors();
+#endif
return;
}
}
@@ -157,6 +160,11 @@ void Fl_WinAPI_Screen_Driver::init()
}
+float Fl_WinAPI_Screen_Driver::desktop_scale_factor() {
+ return 0; //indicates each screen has already been assigned its scale factor value
+}
+
+
void Fl_WinAPI_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n)
{
if (num_screens < 0) init();
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
index 7f548c58b..29b20aefc 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
@@ -71,12 +71,17 @@ 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 void screen_num(int n);
virtual int screen_num();
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);
void make_fullscreen(int X, int Y, int W, int H);
@@ -117,6 +122,7 @@ public:
virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
virtual 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);
+ static void resize_after_screen_change(void *data);
};
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
index 079ca743d..a5621de6a 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
@@ -68,6 +68,13 @@ int Fl_WinAPI_Window_Driver::screen_num() {
return screen_num_ >= 0 ? screen_num_ : 0;
}
+//FILE*LOG=fopen("log.log","w");
+
+void Fl_WinAPI_Window_Driver::screen_num(int n) {
+//fprintf(LOG, "screen_num setter old=%d new=%d\n",screen_num_, n);fflush(LOG);
+ screen_num_ = n;
+}
+
RECT // frame of the decorated window in screen coordinates
Fl_WinAPI_Window_Driver::border_width_title_bar_height(
@@ -669,6 +676,19 @@ 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;
+ win->driver()->resize_after_scale_change(ns, old_f, Fl::screen_driver()->scale(ns));
+ win->wait_for_expose();
+ data_for_resize_window_between_screens_.busy = false;
+}
+
//
// End of "$Id$".
//