diff options
Diffstat (limited to 'src/drivers/X11')
| -rw-r--r-- | src/drivers/X11/Fl_X11_Screen_Driver.H | 16 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Screen_Driver.cxx | 313 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Window_Driver.H | 22 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Window_Driver.cxx | 75 |
4 files changed, 393 insertions, 33 deletions
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.H b/src/drivers/X11/Fl_X11_Screen_Driver.H index 2be26a1ee..8ccf056da 100644 --- a/src/drivers/X11/Fl_X11_Screen_Driver.H +++ b/src/drivers/X11/Fl_X11_Screen_Driver.H @@ -4,7 +4,7 @@ // Definition of X11 Screen interface // for the Fast Light Tool Kit (FLTK). // -// Copyright 2010-2016 by Bill Spitzak and others. +// Copyright 2010-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -39,13 +39,27 @@ protected: short y_org; short width; short height; +#if USE_XFT + float scale; +#endif } FLScreenInfo; FLScreenInfo screens[MAX_SCREENS]; float dpi[MAX_SCREENS][2]; int poll_or_select(); int poll_or_select_with_delay(double time_to_wait); + int get_mouse_unscaled(int &xx, int &yy); public: +#if USE_XFT // scaling does not work without Xft + virtual APP_SCALING_CAPABILITY rescalable() { return PER_SCREEN_APP_SCALING; } + virtual float scale(int n) {return screens[n].scale;} + virtual void scale(int n, float f) { screens[n].scale = f;} + virtual float desktop_scale_factor(); + int screen_num_unscaled(int x, int y); + int screen_num_unscaled(int x, int y, int w, int h); + virtual void screen_xywh(int &X, int &Y, int &W, int &H); +#endif + static int ewmh_supported(); static void copy_image(const unsigned char* data, int W, int H, int destination); // --- display management diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx index 7095ea948..490189673 100644 --- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx @@ -3,7 +3,7 @@ // // Definition of X11 Screen interface // -// Copyright 1998-2016 by Bill Spitzak and others. +// Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -20,9 +20,14 @@ #include "../../config_lib.h" #include "Fl_X11_Screen_Driver.H" #include "../Xlib/Fl_Font.H" +#include "Fl_X11_Window_Driver.H" +#include "../Xlib/Fl_Xlib_Graphics_Driver.H" #include <FL/Fl.H> #include <FL/x.H> #include <FL/fl_ask.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Image_Surface.H> +#include <FL/Fl_Tooltip.H> #include <sys/time.h> @@ -229,10 +234,15 @@ void Fl_X11_Screen_Driver::init_workarea() } else { - fl_workarea_xywh[0] = (int)xywh[0]; - fl_workarea_xywh[1] = (int)xywh[1]; - fl_workarea_xywh[2] = (int)xywh[2]; - fl_workarea_xywh[3] = (int)xywh[3]; +#if USE_XFT + float s = screens[0].scale; +#else + float s = 1; +#endif + fl_workarea_xywh[0] = xywh[0] / s; + fl_workarea_xywh[1] = xywh[1] / s; + fl_workarea_xywh[2] = xywh[2] / s; + fl_workarea_xywh[3] = xywh[3] / s; } if ( xywh ) { XFree(xywh); xywh = 0; } } @@ -316,7 +326,9 @@ void Fl_X11_Screen_Driver::init() { screens[i].y_org = xsi[i].y_org; screens[i].width = xsi[i].width; screens[i].height = xsi[i].height; - +#if USE_XFT + screens[i].scale = 1; +#endif if (dpi_by_randr) { dpi[i][0] = dpih; dpi[i][1] = dpiv; @@ -341,7 +353,9 @@ void Fl_X11_Screen_Driver::init() { screens[i].y_org = 0; screens[i].width = DisplayWidth(fl_display, i); screens[i].height = DisplayHeight(fl_display, i); - +#if USE_XFT + screens[i].scale = 1; +#endif if (dpi_by_randr) { dpi[i][0] = dpih; dpi[i][1] = dpiv; @@ -353,6 +367,17 @@ void Fl_X11_Screen_Driver::init() { } } } +/*#if __APPLE_CC__ && USE_XFT // TMP simulate 2 screens under XQuartz + if (strstr(getenv("DISPLAY"), "xquartz")) { + num_screens = 2; + screens[1].x_org = screens[0].width/2;; + screens[1].y_org = screens[0].y_org; + screens[1].width = screens[0].width = screens[0].width/2; + screens[1].height = screens[0].height; + screens[1].scale = screens[0].scale = 1; + } +#endif*/ + init_workarea(); } @@ -379,10 +404,15 @@ void Fl_X11_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) n = 0; if (num_screens > 0) { - X = screens[n].x_org; - Y = screens[n].y_org; - W = screens[n].width; - H = screens[n].height; +#if USE_XFT + float s = screens[n].scale; +#else + float s = 1; +#endif + X = screens[n].x_org / s; + Y = screens[n].y_org / s; + W = screens[n].width / s; + H = screens[n].height / s; } } @@ -765,26 +795,29 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i image = 0; # endif // __sgi + float s = Fl_Surface_Device::surface()->driver()->scale(); + if (!image) { // fetch absolute coordinates int dx, dy, sx, sy, sw, sh; Window child_win; Fl_Window *win; - if (allow_outside) win = (Fl_Window*)1; + if (allow_outside) win = Fl_Window::current(); else win = fl_find(fl_window); if (win) { XTranslateCoordinates(fl_display, fl_window, - RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win); + RootWindow(fl_display, fl_screen), X*s, Y*s, &dx, &dy, &child_win); + dx /= s; dy /= s; // screen dimensions - Fl::screen_xywh(sx, sy, sw, sh, fl_screen); + Fl::screen_xywh(sx, sy, sw, sh, win->driver()->screen_num()); } if (!win || (dx >= sx && dy >= sy && dx + w <= sx+sw && dy + h <= sy+sh)) { // the image is fully contained, we can use the traditional method // however, if the window is obscured etc. the function will still fail. Make sure we // catch the error and continue, otherwise an exception will be thrown. XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler); - image = XGetImage(fl_display, fl_window, X, Y, w, h, AllPlanes, ZPixmap); + image = XGetImage(fl_display, fl_window, int(X*s), int(Y*s), w*s < 1 ? 1 : int(w*s), h*s < 1 ? 1 : int(h*s), AllPlanes, ZPixmap); XSetErrorHandler(old_handler); } else { // image is crossing borders, determine visible region @@ -795,17 +828,17 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i // allocate the image int bpp = fl_visual->depth + ((fl_visual->depth / 8) % 2) * 8; - char* buf = (char*)malloc(bpp / 8 * w * h); + char* buf = (char*)malloc(bpp / 8 * int(w*s) * int(h*s)); image = XCreateImage(fl_display, fl_visual->visual, - fl_visual->depth, ZPixmap, 0, buf, w, h, bpp, 0); + fl_visual->depth, ZPixmap, 0, buf, w*s, h*s, bpp, 0); if (!image) { if (buf) free(buf); return 0; } XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler); - XImage *subimg = XGetSubImage(fl_display, fl_window, X + noffx, Y + noffy, - nw, nh, AllPlanes, ZPixmap, image, noffx, noffy); + XImage *subimg = XGetSubImage(fl_display, fl_window, (X + noffx)*s, (Y + noffy)*s, + nw*s, nh*s, AllPlanes, ZPixmap, image, noffx*s, noffy*s); XSetErrorHandler(old_handler); if (!subimg) { XDestroyImage(image); @@ -815,6 +848,10 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i } if (!image) return 0; + if (s != 1) { + w = w*s < 1 ? 1 : int(w*s); + h = h*s < 1 ? 1 : int(h*s); + } #ifdef DEBUG printf("width = %d\n", image->width); @@ -1154,6 +1191,244 @@ void Fl_X11_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &hei height = (int)h; } +#if USE_XFT +int Fl_X11_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 ++) { + int sx = screens[i].x_org, sy = screens[i].y_org, sw = screens[i].width, sh = screens[i].height; + if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) { + screen = i; + break; + } + } + return screen; +} + +int Fl_X11_Screen_Driver::screen_num_unscaled(int x, int y, int w, int h) +{ + int best_screen = 0; + float best_intersection = 0.; + if (num_screens < 0) init(); + for (int i = 0; i < num_screens; i++) { + float sintersection = fl_intersection(x, y, w, h, screens[i].x_org, screens[i].y_org, + screens[i].width, screens[i].height); + if (sintersection > best_intersection) { + best_screen = i; + best_intersection = sintersection; + } + } + return best_screen; +} +#endif + +#if USE_XFT +void Fl_X11_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H) +{ + int xx, yy; + int ns = get_mouse_unscaled(xx,yy); + float s = screens[ns].scale; + X = screens[ns].x_org / s; + Y = screens[ns].y_org / s; + W = screens[ns].width / s; + H = screens[ns].height / s; +} + + +#if HAVE_DLSYM && HAVE_DLFCN_H + +// returns true when schema is among the list of available schemas +static bool is_schema_valid(const char *schema, const char **known) { + int i = 0; + while (known[i]) { + if (strcmp(known[i++], schema) == 0) return true; + } + return false; +} + + +/* + returns true under Ubuntu or Debian or FreeBSD and when the gnome scaling value has been found + + Ubuntu: + Change the gnome scaling factor with: + System Settings ==> Displays ==> Scale for menu and title bars + Read the current gnome scaling factor with: + gsettings get com.ubuntu.user-interface scale-factor + Example value: {'VGA-0': 10} + Its type is "a{si}". This value should be divided by 8 to get the correct scaling factor. + + Debian or FreeBSD : + Change the gnome scaling factor with: + Tweak tools ==> Windows ==> Window scaling + Read the current gnome scaling factor with: + gsettings get org.gnome.settings-daemon.plugins.xsettings overrides + Example value: {'Gdk/WindowScalingFactor': <2>} + Its type is "a{sv}" and v itself is of type i + + It's also possible to use 'Tweak tools' under Ubuntu. With the standard Ubuntu desktop, + the modified value goes to "org.gnome.settings-daemon.plugins.xsettings" as above. + + With Gnome session flashback under Ubuntu 'Tweak tools' puts the scaling value (1 or 2) + in "org.gnome.desktop.interface scaling-factor". + Read the current gnome scaling factor with: + gsettings get org.gnome.desktop.interface scaling-factor + Its type is "u" + + Thus, under Ubuntu, we read the 3 possible factor values and + return the first value different from 1 to get the scaling factor. + + ================================================================================================= + Ubuntu | default ubuntu desktop | System Settings => Displays => Scale for menu and title bars + com.ubuntu.user-interface scale-factor + ----------------------- + Tweak tools => Windows => Window scaling + org.gnome.settings-daemon.plugins.xsettings overrides + ----------------------- + Gnome session flashback | System Settings => Displays => Scale for menu and title bars + no effect + ----------------------- + Tweak tools => Windows => Window scaling + org.gnome.desktop.interface scaling-factor + ================================================================================================= + Debian or FreeBSD | gnome | Tweak tools => Windows => Window scaling + org.gnome.settings-daemon.plugins.xsettings overrides + ================================================================================================= + */ +static bool gnome_scale_factor(float& factor) { + // define types needed for dynamic lib functions + typedef const char** (*g_settings_list_schemas_ftype)(void); + typedef void* (*g_settings_new_ftype)(const char *); + typedef void* (*g_settings_get_value_ftype)(void *settings, const char *key); + typedef void (*g_variant_get_ftype)(void *value, const char *format_string, ...); + typedef bool (*g_variant_iter_loop_ftype)(void *iter, const char *format_string, ...); + typedef void (*pter_ftype)(void*); + //typedef void* (*g_variant_get_type_ftype)(void *variant); + + // open dynamic libs + void *glib = dlopen("libglib-2.0.so", RTLD_LAZY); + void *gio = dlopen("libgio-2.0.so", RTLD_LAZY); + void *gobj = dlopen("libgobject-2.0.so", RTLD_LAZY); + //fprintf(stderr,"glib=%p gio=%p gobj=%p\n",glib,gio,gobj); + if (!glib || !gio || !gobj) return false; + + bool ubuntu = false; + // determine whether we run Ubuntu + char line[400] = ""; + FILE *in = fopen("/proc/version", "r"); + if (in) { + fgets(line, sizeof(line), in); + fclose(in); + if (strstr(line, "Ubuntu")) ubuntu = true; + } + + // define pters to used functions + g_settings_list_schemas_ftype g_settings_list_schemas_f = (g_settings_list_schemas_ftype)dlsym(gio, "g_settings_list_schemas"); // 2.26 + g_settings_new_ftype g_settings_new_f = (g_settings_new_ftype)dlsym(gio, "g_settings_new"); // 2.26 + g_settings_get_value_ftype g_settings_get_value_f = + (g_settings_get_value_ftype)dlsym(gio, "g_settings_get_value"); // 2.26 + if (!g_settings_list_schemas_f || !g_settings_new_f || !g_settings_get_value_f) return false; + g_variant_get_ftype g_variant_get_f = (g_variant_get_ftype)dlsym(glib, "g_variant_get"); //2.24 + g_variant_iter_loop_ftype g_variant_iter_loop_f = (g_variant_iter_loop_ftype)dlsym(glib, "g_variant_iter_loop"); // 2.24 + pter_ftype g_variant_iter_free_f = (pter_ftype)dlsym(glib, "g_variant_iter_free"); // 2.24 + pter_ftype g_object_unref_f = (pter_ftype)dlsym(gobj, "g_object_unref"); + pter_ftype g_variant_unref_f = (pter_ftype)dlsym(glib, "g_variant_unref"); // 2.24 + //g_variant_get_type_ftype g_variant_get_type_f = (g_variant_get_type_ftype)dlsym(glib, "g_variant_get_type"); // 2.24 + + // call dynamic lib functions + const char **known = g_settings_list_schemas_f(); // list of available GSettings schemas + const char *schema; + float ubuntu_f = 1, ubuntu_desktop_f = 1, gnome_f = 1; + bool found = false; + + if (ubuntu) { + schema = "com.ubuntu.user-interface"; + if (is_schema_valid(schema, known)) { + found = true; + void *gset = g_settings_new_f(schema); + void *gvar = g_settings_get_value_f(gset, "scale-factor"); + void *iter; + char str[10], *str2; int v=8, v2; + g_variant_get_f(gvar, "a{si}", &iter); + while (g_variant_iter_loop_f(iter, "{si}", &str2, &v2)) { // read the last couple of values + strcpy(str, str2); v = v2; + } + ubuntu_f = v/8.; + printf("com.ubuntu.user-interface scale-factor name=%s value=%d factor=%g\n", str, v, ubuntu_f); + g_variant_iter_free_f(iter); + g_variant_unref_f(gvar); + g_object_unref_f(gset); + if (ubuntu_f != 1) { + factor = ubuntu_f; + return true; + } + } + schema = "org.gnome.desktop.interface"; + if (is_schema_valid(schema, known)) { + found = true; + void *gset = g_settings_new_f(schema); + void *gvar = g_settings_get_value_f(gset, "scaling-factor"); + unsigned v; + g_variant_get_f(gvar, "u", &v); + ubuntu_desktop_f = v; + printf("org.gnome.desktop.interface scaling-factor value=%u factor=%g\n", v, ubuntu_desktop_f); + g_variant_unref_f(gvar); + g_object_unref_f(gset); + if (ubuntu_desktop_f != 1) { + factor = ubuntu_desktop_f; + return true; + } + } + } + schema = "org.gnome.settings-daemon.plugins.xsettings"; + if (is_schema_valid(schema, known)) { + void *gset = g_settings_new_f(schema); + void *gvar = g_settings_get_value_f(gset, "overrides"); + void *iter; + char *str; int v; + //str = (char*)g_variant_get_type_f(gvar); // -> "a{sv}" + g_variant_get_f(gvar, "a{sv}", &iter); + g_variant_unref_f(gvar); + gvar = NULL; + while (g_variant_iter_loop_f(iter, "{sv}", &str, &gvar)) { + if (strstr(str, "WindowScalingFactor") == NULL) continue; + found = true; + //str = (char*)g_variant_get_type_f(gvar); // -> "i" + g_variant_get_f(gvar, "i", &v); + gnome_f = v; + printf("org.gnome.settings-daemon.plugins.xsettings overrides name=%s value=%d factor=%g\n", str, v, gnome_f); + free(str); + break; + } + g_variant_iter_free_f(iter); + if (gvar) g_variant_unref_f(gvar); + g_object_unref_f(gset); + } + if (!found) return false; + //factor = ubuntu_f * ubuntu_desktop_f * gnome_f; + factor = gnome_f; + return true; +} +#endif // HAVE_DLSYM && HAVE_DLFCN_H + + +// return the desktop's default scaling value +float Fl_X11_Screen_Driver::desktop_scale_factor() +{ + float factor = 1; +#if HAVE_DLSYM && HAVE_DLFCN_H + gnome_scale_factor(factor); +#endif + return factor; +} + + + + +#endif // USE_XFT + // // End of "$Id$". // diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H index 4de4e3680..0893d28c0 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.H +++ b/src/drivers/X11/Fl_X11_Window_Driver.H @@ -4,7 +4,7 @@ // Definition of X11 window driver // for the Fast Light Tool Kit (FLTK). // -// Copyright 2010-2016 by Bill Spitzak and others. +// Copyright 2010-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -27,6 +27,7 @@ #include <FL/Fl_Window_Driver.H> #include <config.h> // for USE_XDBE +#include <FL/x.H> // for Cursor class Fl_Bitmap; /* @@ -56,6 +57,8 @@ struct Fl_Window_Driver::shape_data_type { class FL_EXPORT Fl_X11_Window_Driver : public Fl_Window_Driver { friend class Fl_X; + friend class Fl_X11_Screen_Driver; + friend int fl_handle(const XEvent&); private: struct icon_data { @@ -63,6 +66,17 @@ private: Fl_RGB_Image **icons; int count; } *icon_; + Cursor current_cursor_; +#if USE_XFT + // --- support for screen-specific scaling factors + struct type_for_resize_window_between_screens { + int screen; + bool busy; + }; + static type_for_resize_window_between_screens data_for_resize_window_between_screens_; + int screen_num_; + void screen_num(int n) { screen_num_ = n; } +#endif // USE_XFT void decorated_win_size(int &w, int &h); void combine_mask(); void shape_bitmap_(Fl_Image* b); @@ -79,7 +93,11 @@ public: Fl_X11_Window_Driver(Fl_Window*); virtual ~Fl_X11_Window_Driver(); static inline Fl_X11_Window_Driver* driver(Fl_Window *w) {return (Fl_X11_Window_Driver*)w->driver();} - +#if USE_XFT + virtual int screen_num(); + static void resize_after_screen_change(void *data); +#endif // USE_XFT + // --- window data virtual int decorated_w(); virtual int decorated_h(); diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx index f10ed307a..a8952eed3 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx @@ -3,7 +3,7 @@ // // Definition of X11 window driver. // -// Copyright 1998-2016 by Bill Spitzak and others. +// Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -112,11 +112,11 @@ void Fl_X11_Window_Driver::destroy_double_buffer() { #if USE_XDBE if (can_xdbe()) { XdbeDeallocateBackBufferName(fl_display, other_xid); - other_xid = 0; } else #endif // USE_XDBE - Fl_Window_Driver::destroy_double_buffer(); + fl_delete_offscreen(other_xid); + other_xid = 0; } Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) @@ -130,6 +130,10 @@ Fl_X11_Window_Driver::Fl_X11_Window_Driver(Fl_Window *win) { icon_ = new icon_data; memset(icon_, 0, sizeof(icon_data)); + current_cursor_ = None; +#if USE_XFT + screen_num_ = -1; +#endif } @@ -160,8 +164,10 @@ void Fl_X11_Window_Driver::decorated_win_size(int &w, int &h) if (status == 0 || root == parent) return; XWindowAttributes attributes; XGetWindowAttributes(fl_display, parent, &attributes); - w = attributes.width; - h = attributes.height; + int nscreen = screen_num(); + float s = Fl::screen_driver()->scale(nscreen); + w = attributes.width / s; + h = attributes.height / s; } @@ -196,7 +202,9 @@ void Fl_X11_Window_Driver::take_focus() void Fl_X11_Window_Driver::draw_begin() { if (shape_data_) { - if (( shape_data_->lw_ != w() || shape_data_->lh_ != h() ) && shape_data_->shape_) { + int nscreen = screen_num(); + float s = Fl::screen_driver()->scale(nscreen); + if (( shape_data_->lw_ != int(s*w()) || shape_data_->lh_ != int(s*h()) ) && shape_data_->shape_) { // size of window has changed since last time combine_mask(); } @@ -324,8 +332,9 @@ void Fl_X11_Window_Driver::combine_mask() #endif } if (!XShapeCombineMask_f) return; - shape_data_->lw_ = w(); - shape_data_->lh_ = h(); + float s = Fl::screen_driver()->scale(screen_num()); + shape_data_->lw_ = w()*s; + shape_data_->lh_ = h()*s; Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_); Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(pWindow), (const char*)*temp->data(), @@ -400,25 +409,30 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, F if (n) XFree(children); if (!do_it) wsides = htop = 0; int hbottom = wsides; + float s = Fl::screen_driver()->scale(screen_num()); + htop /= s; wsides /= s; fl_window = parent; if (htop) { r_top = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, - (w() + 2 * wsides), htop, 0); top = Fl_Shared_Image::get(r_top); + top->scale(w() + 2 * wsides, htop, 0, 1); } if (wsides) { r_left = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop, -wsides, h(), 0); if (r_left) { left = Fl_Shared_Image::get(r_left); + left->scale(wsides, h(), 0, 1); } r_right = Fl::screen_driver()->read_win_rectangle(NULL, w() + wsides, htop, -wsides, h(), 0); if (r_right) { right = Fl_Shared_Image::get(r_right); + right->scale(wsides, h(), 0, 1); } r_bottom = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop + h(), -(w() + 2*wsides), hbottom, 0); if (r_bottom) { bottom = Fl_Shared_Image::get(r_bottom); - } - } + bottom->scale(w() + 2*wsides, wsides, 0, 1); + } } fl_window = from; Fl_Surface_Device::pop_current(); } @@ -432,6 +446,9 @@ void Fl_X11_Window_Driver::make_current() { } fl_window = fl_xid(pWindow); fl_graphics_driver->clip_region(0); +#if USE_XFT + ((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num())); +#endif #ifdef FLTK_USE_CAIRO // update the cairo_t context @@ -460,6 +477,7 @@ void Fl_X11_Window_Driver::hide() { if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region); # if USE_XFT Fl_Xlib_Graphics_Driver::destroy_xft_draw(ip->xid); + screen_num_ = -1; # endif // this test makes sure ip->xid has not been destroyed already if (ip->xid) XDestroyWindow(fl_display, ip->xid); @@ -650,8 +668,9 @@ void Fl_X11_Window_Driver::erase_menu() { int Fl_X11_Window_Driver::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) { + float s = Fl::screen_driver()->scale(screen_num()); XCopyArea(fl_display, fl_window, fl_window, (GC)fl_graphics_driver->gc(), - src_x, src_y, src_w, src_h, dest_x, dest_y); + int(src_x*s), int(src_y*s), int(src_w*s), int(src_h*s), int(dest_x*s), int(dest_y*s)); // we have to sync the display and get the GraphicsExpose events! (sigh) for (;;) { XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e); @@ -670,6 +689,40 @@ Fl_X *Fl_X11_Window_Driver::makeWindow() return Fl_X::i(pWindow); } + +#if USE_XFT + +Fl_X11_Window_Driver::type_for_resize_window_between_screens Fl_X11_Window_Driver::data_for_resize_window_between_screens_ = {0, false}; + +void Fl_X11_Window_Driver::resize_after_screen_change(void *data) { + Fl_Window *win = (Fl_Window*)data; + int oldx, oldy; + XWindowAttributes actual; + XGetWindowAttributes(fl_display, fl_xid(win), &actual); + Window cr; + XTranslateCoordinates(fl_display, fl_xid(win), actual.root, 0, 0, &oldx, &oldy, &cr); + win->hide(); + float f = Fl::screen_driver()->scale(data_for_resize_window_between_screens_.screen); + Fl_X11_Window_Driver::driver(win)->screen_num(data_for_resize_window_between_screens_.screen); + win->position(oldx/f, oldy/f); + win->driver()->force_position(1); + Fl_Xlib_Graphics_Driver *d = (Fl_Xlib_Graphics_Driver*)Fl_Display_Device::display_device()->driver(); + d->scale(f); + win->show(); + win->wait_for_expose(); + data_for_resize_window_between_screens_.busy = false; +} + + +int Fl_X11_Window_Driver::screen_num() { + if (pWindow->parent()) { + screen_num_ = pWindow->top_window()->driver()->screen_num(); + } + return screen_num_ >= 0 ? screen_num_ : 0; +} +#endif // USE_XFT + + // // End of "$Id$". // |
