mirror of
https://github.com/fltk/fltk.git
synced 2026-06-04 15:32:12 +08:00
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
This commit is contained in:
+68
-35
@@ -505,10 +505,8 @@ void Fl_WinAPI_Screen_Driver::open_display_platform() {
|
|||||||
HMODULE hMod = LoadLibrary("Shcore.DLL");
|
HMODULE hMod = LoadLibrary("Shcore.DLL");
|
||||||
if (hMod) {
|
if (hMod) {
|
||||||
SetProcessDpiAwareness_type fl_SetProcessDpiAwareness = (SetProcessDpiAwareness_type)GetProcAddress(hMod, "SetProcessDpiAwareness");
|
SetProcessDpiAwareness_type fl_SetProcessDpiAwareness = (SetProcessDpiAwareness_type)GetProcAddress(hMod, "SetProcessDpiAwareness");
|
||||||
HRESULT r = 0;
|
|
||||||
const int PROCESS_PER_MONITOR_DPI_AWARE = 2;
|
const int PROCESS_PER_MONITOR_DPI_AWARE = 2;
|
||||||
if (fl_SetProcessDpiAwareness) r = fl_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
if (fl_SetProcessDpiAwareness) fl_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
//fprintf(LOG,"SetProcessDpiAwareness=%p result=%d\n",fl_SetProcessDpiAwareness,r);fflush(LOG);
|
|
||||||
}
|
}
|
||||||
#endif // FLTK_HIDPI_SUPPORT
|
#endif // FLTK_HIDPI_SUPPORT
|
||||||
OleInitialize(0L);
|
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;
|
POINT p;
|
||||||
GetCursorPos(&p);
|
GetCursorPos(&p);
|
||||||
x = p.x;
|
mx = p.x; my = p.y;
|
||||||
y = p.y;
|
return screen_num_unscaled(mx, my);
|
||||||
return screen_num(x, y);
|
}
|
||||||
|
|
||||||
|
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);
|
int hdots = GetDeviceCaps(hdc, HORZRES);
|
||||||
ReleaseDC(NULL, hdc);
|
ReleaseDC(NULL, hdc);
|
||||||
float factor = (100.f * hmm) / hdots;
|
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
|
width = int(width * scaling / factor); // convert to screen pixel unit
|
||||||
height = int(height * scaling / factor);
|
height = int(height * scaling / factor);
|
||||||
RECT rect = {0, 0, width, height};
|
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
|
// 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) {
|
if (R2) {
|
||||||
// Also tell WIN32 that we are drawing someplace else as well...
|
// 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
|
// 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));
|
window->clear_damage((uchar)(window->damage()|FL_DAMAGE_EXPOSE));
|
||||||
// These next two statements should not be here, so that all update
|
// 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 ret = bx = by = bt = 0;
|
||||||
|
|
||||||
int fallback = 1;
|
int fallback = 1;
|
||||||
|
float s = Fl::screen_driver()->scale(((Fl_Window*)w)->driver()->screen_num());
|
||||||
if (!w->parent()) {
|
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
|
// The block below calculates the window borders by requesting the
|
||||||
// required decorated window rectangle for a desired client rectangle.
|
// required decorated window rectangle for a desired client rectangle.
|
||||||
// If any part of the function above fails, we will drop to a
|
// 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;
|
RECT r;
|
||||||
r.left = w->x();
|
r.left = w->x() * s;
|
||||||
r.top = w->y();
|
r.top = w->y() * s;
|
||||||
r.right = w->x()+w->w();
|
r.right = (w->x()+w->w())*s;
|
||||||
r.bottom = w->y()+w->h();
|
r.bottom = (w->y()+w->h())*s;
|
||||||
// get the decoration rectangle for the desired client rectangle
|
// get the decoration rectangle for the desired client rectangle
|
||||||
BOOL ok = AdjustWindowRectEx(&r, style, FALSE, styleEx);
|
BOOL ok = AdjustWindowRectEx(&r, style, FALSE, styleEx);
|
||||||
if (ok) {
|
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;
|
Y = r.top;
|
||||||
W = r.right - r.left;
|
W = r.right - r.left;
|
||||||
H = r.bottom - r.top;
|
H = r.bottom - r.top;
|
||||||
bx = w->x() - r.left;
|
bx = w->x() *s - r.left;
|
||||||
by = r.bottom - w->y() - w->h(); // height of the bottom frame
|
by = r.bottom - (w->y() + w->h())*s; // height of the bottom frame
|
||||||
bt = w->y() - r.top - by; // height of top caption bar
|
bt = w->y() * s - r.top - by; // height of top caption bar
|
||||||
xoff = bx;
|
xoff = bx;
|
||||||
yoff = by + bt;
|
yoff = by + bt;
|
||||||
dx = W - w->w();
|
dx = W - w->w() * s;
|
||||||
dy = H - w->h();
|
dy = H - w->h() * s;
|
||||||
if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh))
|
if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh))
|
||||||
ret = 2;
|
ret = 2;
|
||||||
else
|
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
|
//Find screen that contains most of the window
|
||||||
//FIXME: this ought to be the "work area" instead of the entire screen !
|
//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;
|
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
|
//Make border's lower right corner visible
|
||||||
if (scr_x+scr_w < X+W) X = scr_x+scr_w - W;
|
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;
|
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 (X<scr_x) X = scr_x;
|
||||||
if (Y<scr_y) Y = scr_y;
|
if (Y<scr_y) Y = scr_y;
|
||||||
//Make client area's lower right corner visible
|
//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_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() - dy;
|
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
|
//Make client area's upper left corner visible
|
||||||
if (X+xoff < scr_x) X = scr_x-xoff;
|
if (X+xoff < scr_x) X = scr_x-xoff;
|
||||||
if (Y+yoff < scr_y) Y = scr_y-yoff;
|
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());
|
if (!pWindow->resizable()) pWindow->size_range(w(), h(), w(), h());
|
||||||
int dummy_x, dummy_y, bt, bx, by;
|
int dummy_x, dummy_y, bt, bx, by;
|
||||||
//Ignore window managing when resizing, so that windows (and more
|
//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.
|
//specifically menus) can be moved offscreen.
|
||||||
if (fake_X_wm(dummy_x, dummy_y, bt, bx, by)) {
|
if (fake_X_wm(dummy_x, dummy_y, bt, bx, by)) {
|
||||||
X -= bx;
|
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.
|
// will cause continouly new redraw events.
|
||||||
if (W<=0) W = 1;
|
if (W<=0) W = 1;
|
||||||
if (H<=0) H = 1;
|
if (H<=0) H = 1;
|
||||||
float s = Fl::screen_driver()->scale(0);
|
SetWindowPos(fl_xid(pWindow), 0, X, Y, W, H, flags);
|
||||||
SetWindowPos(fl_xid(pWindow), 0, X*s, Y*s, W*s, H*s, 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;
|
DWORD styleEx = WS_EX_LEFT;
|
||||||
|
|
||||||
float s = Fl::screen_driver()->scale(0);
|
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 yp = w->y() * s;
|
||||||
int wp = w->w() * s;
|
int wp = w->w() * s;
|
||||||
int hp = w->h() * s;
|
int hp = w->h() * s;
|
||||||
@@ -1834,7 +1854,7 @@ Fl_X* Fl_WinAPI_Window_Driver::makeWindow() {
|
|||||||
break;
|
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());
|
fake_X_wm_style(w, xwm, ywm, bt, bx, by, style, styleEx, maxw(), minw(), maxh(), minh(), size_range_set());
|
||||||
if (by+bt) {
|
if (by+bt) {
|
||||||
wp += 2*bx;
|
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;
|
top = left = bottom = right = NULL;
|
||||||
if (!shown() || parent() || !border() || !visible()) return;
|
if (!shown() || parent() || !border() || !visible()) return;
|
||||||
int wsides, hbottom, bt;
|
int wsides, hbottom, bt;
|
||||||
float scaling = 1;
|
float scaling = Fl::screen_driver()->scale(screen_num());
|
||||||
RECT r = border_width_title_bar_height(wsides, hbottom, bt, &scaling);
|
RECT r = border_width_title_bar_height(wsides, hbottom, bt);
|
||||||
int htop = bt + hbottom;
|
int htop = bt + hbottom;
|
||||||
Window save_win = fl_window;
|
Window save_win = fl_window;
|
||||||
Fl_Surface_Device::push_current( Fl_Display_Device::display_device() );
|
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();
|
Fl::check();
|
||||||
void* save_gc = fl_graphics_driver->gc();
|
void* save_gc = fl_graphics_driver->gc();
|
||||||
fl_graphics_driver->gc(GetDC(NULL));
|
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
|
// capture the 4 window sides from screen
|
||||||
|
Fl_WinAPI_Screen_Driver *dr = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver();
|
||||||
if (htop) {
|
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);
|
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) {
|
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);
|
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);
|
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);
|
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());
|
ReleaseDC(NULL, (HDC)fl_graphics_driver->gc());
|
||||||
fl_window = save_win;
|
fl_window = save_win;
|
||||||
|
|||||||
@@ -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 factorw = (100.f * hmm) / hdots;
|
||||||
float factorh = (100.f * vmm) / vdots;
|
float factorh = (100.f * vmm) / vdots;
|
||||||
// Global display scaling factor: 1, 1.25, 1.5, 1.75, etc...
|
// 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);
|
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);
|
gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
|
||||||
if (gc != NULL) {
|
if (gc != NULL) {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
void XDestroyRegion(Fl_Region r);
|
void XDestroyRegion(Fl_Region r);
|
||||||
void translate_all(int x, int y);
|
void translate_all(int x, int y);
|
||||||
void untranslate_all(void);
|
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 void scale(float f);
|
||||||
virtual float scale();
|
virtual float scale();
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ void Fl_GDI_Graphics_Driver::translate_all(int x, int y) {
|
|||||||
depth = stack_height - 1;
|
depth = stack_height - 1;
|
||||||
}
|
}
|
||||||
GetWindowOrgEx((HDC)gc(), origins+depth);
|
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++;
|
depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,24 +243,44 @@ float Fl_GDI_Graphics_Driver::scale() {
|
|||||||
|
|
||||||
/* Rescale region r with factor f and returns the scaled region.
|
/* Rescale region r with factor f and returns the scaled region.
|
||||||
The input region is deleted if keep is false.
|
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.
|
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) {
|
if (r && f != 1) {
|
||||||
DWORD size = GetRegionData(r, 0, NULL);
|
DWORD size = GetRegionData(r, 0, NULL);
|
||||||
RGNDATA *pdata = (RGNDATA*)malloc(size);
|
RGNDATA *pdata = (RGNDATA*)malloc(size);
|
||||||
GetRegionData(r, size, pdata);
|
GetRegionData(r, size, pdata);
|
||||||
if (!keep) DeleteObject(r);
|
if (!keep) DeleteObject(r);
|
||||||
if (inflate) {
|
/*if (inflate) { // seems no longer useful
|
||||||
RECT *rects = (RECT*)&(pdata->Buffer);
|
RECT *rects = (RECT*)&(pdata->Buffer);
|
||||||
for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
|
for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
|
||||||
InflateRect(rects+i, 1, 1);
|
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);
|
r = ExtCreateRegion(&xform, size, pdata);
|
||||||
free(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;
|
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) {
|
Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
|
||||||
HRGN r = rstack[rstackptr];
|
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));
|
return (r == r2 ? NULL : (rstack[rstackptr] = r2, r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#ifdef FL_CFG_GFX_GDI
|
#ifdef FL_CFG_GFX_GDI
|
||||||
#include "Fl_GDI_Graphics_Driver.H"
|
#include "Fl_GDI_Graphics_Driver.H"
|
||||||
|
#include "../WinAPI/Fl_WinAPI_Screen_Driver.H"
|
||||||
#include <FL/Fl_Image_Surface.H>
|
#include <FL/Fl_Image_Surface.H>
|
||||||
#include <FL/fl_draw.H>
|
#include <FL/fl_draw.H>
|
||||||
#include <FL/x.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);
|
w = int(w*d);
|
||||||
h = int(h*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);
|
driver(new Fl_GDI_Graphics_Driver);
|
||||||
if (d != 1 && high_res) driver()->scale(d);
|
if (d != 1 && high_res) driver()->scale(d);
|
||||||
_sgc = NULL;
|
_sgc = NULL;
|
||||||
@@ -93,11 +96,8 @@ void Fl_GDI_Image_Surface_Driver::untranslate() {
|
|||||||
|
|
||||||
Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image()
|
Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image()
|
||||||
{
|
{
|
||||||
unsigned char *data;
|
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
|
||||||
data = fl_read_image(NULL, 0, 0, width, height, 0);
|
|
||||||
previous->driver()->gc(_sgc);
|
previous->driver()->gc(_sgc);
|
||||||
Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height);
|
|
||||||
image->alloc_array = 1;
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ protected:
|
|||||||
|
|
||||||
static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM);
|
static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM);
|
||||||
BOOL screen_cb(HMONITOR mon, HDC, LPRECT r);
|
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:
|
public:
|
||||||
Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { scale_ = 1; }
|
Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { scale_ = 1; }
|
||||||
@@ -53,7 +55,7 @@ public:
|
|||||||
virtual int h();
|
virtual int h();
|
||||||
virtual void screen_xywh(int &X, int &Y, int &W, int &H, int n);
|
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);
|
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);
|
virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n);
|
||||||
// --- audible output
|
// --- audible output
|
||||||
virtual void beep(int type);
|
virtual void beep(int type);
|
||||||
@@ -74,6 +76,7 @@ public:
|
|||||||
virtual int dnd(int unused);
|
virtual int dnd(int unused);
|
||||||
virtual int compose(int &del);
|
virtual int compose(int &del);
|
||||||
virtual Fl_RGB_Image *read_win_rectangle(uchar *p, int X, int Y, int w, int h, int alpha);
|
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 int get_mouse(int &x, int &y);
|
||||||
virtual void enable_im();
|
virtual void enable_im();
|
||||||
virtual void disable_im();
|
virtual void disable_im();
|
||||||
|
|||||||
@@ -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 (num_screens < 0) init();
|
||||||
if (n < 0 || n >= num_screens) n = 0;
|
if (n < 0 || n >= num_screens) n = 0;
|
||||||
X = work_area[n].left;
|
X = work_area[n].left/scale_;
|
||||||
Y = work_area[n].top;
|
Y = work_area[n].top/scale_;
|
||||||
W = work_area[n].right - X;
|
W = (work_area[n].right - X)/scale_;
|
||||||
H = work_area[n].bottom - Y;
|
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;
|
n = 0;
|
||||||
|
|
||||||
if (num_screens > 0) {
|
if (num_screens > 0) {
|
||||||
X = screens[n].left;
|
X = screens[n].left/scale_;
|
||||||
Y = screens[n].top;
|
Y = screens[n].top/scale_;
|
||||||
W = screens[n].right - screens[n].left;
|
W = (screens[n].right - screens[n].left)/scale_;
|
||||||
H = screens[n].bottom - screens[n].top;
|
H = (screens[n].bottom - screens[n].top)/scale_;
|
||||||
} else {
|
} else {
|
||||||
/* Fallback if something is broken... */
|
/* Fallback if something is broken... */
|
||||||
X = 0;
|
X = 0;
|
||||||
@@ -519,6 +519,12 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NU
|
|||||||
int w, // I - Width of area to read
|
int w, // I - Width of area to read
|
||||||
int h, // I - Height of area to read
|
int h, // I - Height of area to read
|
||||||
int alpha) // I - Alpha value for image (0 for none)
|
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
|
int d; // Depth of image
|
||||||
|
|
||||||
@@ -614,11 +620,11 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NU
|
|||||||
return rgb;
|
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
|
#ifdef FLTK_HIDPI_SUPPORT
|
||||||
return 1;// this becomes useless if FLTK app are made DPI-aware by calling SetProcessDpiAwareness()
|
return scale(screen_num);
|
||||||
#else
|
#else
|
||||||
// Compute the global desktop scaling factor: 1, 1.25, 1.5, 1.75, etc...
|
// Compute the global desktop scaling factor: 1, 1.25, 1.5, 1.75, etc...
|
||||||
// This factor can be set in Windows 10 by
|
// 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$".
|
// End of "$Id$".
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ class FL_EXPORT Fl_WinAPI_Window_Driver : public Fl_Window_Driver
|
|||||||
HICON small_icon;
|
HICON small_icon;
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
RECT border_width_title_bar_height(int &bx, int &by, int &bt, float *pscaling = NULL);
|
|
||||||
void shape_bitmap_(Fl_Image* b);
|
void shape_bitmap_(Fl_Image* b);
|
||||||
void shape_alpha_(Fl_Image* img, int offset);
|
void shape_alpha_(Fl_Image* img, int offset);
|
||||||
public:
|
public:
|
||||||
@@ -70,6 +69,7 @@ public:
|
|||||||
~Fl_WinAPI_Window_Driver();
|
~Fl_WinAPI_Window_Driver();
|
||||||
static inline Fl_WinAPI_Window_Driver* driver(Fl_Window *w) {return (Fl_WinAPI_Window_Driver*)w->driver();}
|
static inline Fl_WinAPI_Window_Driver* driver(Fl_Window *w) {return (Fl_WinAPI_Window_Driver*)w->driver();}
|
||||||
HDC private_dc; // used for OpenGL
|
HDC private_dc; // used for OpenGL
|
||||||
|
RECT border_width_title_bar_height(int &bx, int &by, int &bt);
|
||||||
|
|
||||||
struct icon_data *icon_;
|
struct icon_data *icon_;
|
||||||
HCURSOR cursor;
|
HCURSOR cursor;
|
||||||
|
|||||||
@@ -59,14 +59,11 @@ Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- private
|
|
||||||
|
|
||||||
RECT // frame of the decorated window in screen coordinates
|
RECT // frame of the decorated window in screen coordinates
|
||||||
Fl_WinAPI_Window_Driver::border_width_title_bar_height(
|
Fl_WinAPI_Window_Driver::border_width_title_bar_height(
|
||||||
int &bx, // left and right border width
|
int &bx, // left and right border width
|
||||||
int &by, // bottom border height (=bx)
|
int &by, // bottom border height (=bx)
|
||||||
int &bt, // height of window title bar
|
int &bt // height of window title bar
|
||||||
float *pscaling // display scaling factor
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Fl_Window *win = pWindow;
|
Fl_Window *win = pWindow;
|
||||||
@@ -83,14 +80,12 @@ RECT // frame of the decorated window in screen coordinates
|
|||||||
const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
|
const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
|
||||||
if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
|
if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
|
||||||
need_r = 0;
|
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) {
|
if (need_r) {
|
||||||
GetWindowRect(fl_xid(win), &r);
|
GetWindowRect(fl_xid(win), &r);
|
||||||
}
|
}
|
||||||
if (pscaling) *pscaling = scaling;
|
|
||||||
|
|
||||||
bx = (r.right - r.left - int(win->w() * scaling))/2;
|
bx = (r.right - r.left - int(win->w() * scaling))/2;
|
||||||
if (bx < 1) bx = 1;
|
if (bx < 1) bx = 1;
|
||||||
by = bx;
|
by = bx;
|
||||||
@@ -105,16 +100,24 @@ RECT // frame of the decorated window in screen coordinates
|
|||||||
int Fl_WinAPI_Window_Driver::decorated_w()
|
int Fl_WinAPI_Window_Driver::decorated_w()
|
||||||
{
|
{
|
||||||
int bt, bx, by;
|
int bt, bx, by;
|
||||||
|
float s = Fl::screen_driver()->scale(screen_num());
|
||||||
border_width_title_bar_height(bx, by, bt);
|
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 Fl_WinAPI_Window_Driver::decorated_h()
|
||||||
{
|
{
|
||||||
int bt, bx, by;
|
int bt, bx, by;
|
||||||
float scaling = 1;
|
border_width_title_bar_height(bx, by, bt);
|
||||||
border_width_title_bar_height(bx, by, bt, &scaling);
|
#ifdef FLTK_HIDPI_SUPPORT
|
||||||
return h() + bt/scaling + 2 * by;
|
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 fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
|
||||||
static char first_time = 1;
|
static char first_time = 1;
|
||||||
// We will have to do some Region magic now, so let's see if the
|
// 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) {
|
if (first_time) {
|
||||||
HMODULE hMod = GetModuleHandle("GDI32.DLL");
|
HMODULE hMod = GetModuleHandle("GDI32.DLL");
|
||||||
if (hMod) {
|
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;
|
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.
|
// Now check if the source scrolling area is fully visible.
|
||||||
// If it is, we will do a quick scroll and just update the
|
// 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
|
// newly exposed area. If it is not, we go the safe route and
|
||||||
|
|||||||
Reference in New Issue
Block a user