From 209f348ca406416a66cf02567d4af0bcc9435a12 Mon Sep 17 00:00:00 2001 From: Ciaran Anscomb Date: Mon, 14 Aug 2023 14:18:10 +0100 Subject: [PATCH] Offset position in X11 for east and south gravity Adds new virtual functions x_from_right() and y_from_bottom() to Fl_Screen_Driver. These are overridden in Fl_X11_Screen_Driver to return the offset between the actual screen edge (right or bottom) and the scaled up screen edge. The calculation is: scaled delta = scaled limit - scaled coordinate real coordinate = real limit - (scaled delta * screen scale) These offsets then applied when creating a window with east or south gravity to adjust for the loss of precision in the screen dimensions when they were scaled. --- src/Fl_Screen_Driver.H | 2 ++ src/Fl_x.cxx | 26 +++++++++++++++++++++++- src/drivers/X11/Fl_X11_Screen_Driver.H | 2 ++ src/drivers/X11/Fl_X11_Screen_Driver.cxx | 17 ++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/Fl_Screen_Driver.H b/src/Fl_Screen_Driver.H index 1b6e057ed..89a0e1c48 100644 --- a/src/Fl_Screen_Driver.H +++ b/src/Fl_Screen_Driver.H @@ -111,6 +111,8 @@ public: virtual int y() { return 0; } virtual int w() { return 800; } // default, FL_OVERRIDE in driver! virtual int h() { return 600; } // default, FL_OVERRIDE in driver! + virtual int x_from_right(int x) { return x * scale(0); } + virtual int y_from_bottom(int y) { return y * scale(0); } virtual int screen_count(); void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my); virtual void screen_xywh(int &X, int &Y, int &W, int &H, int /*n*/) { diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 1704be57e..800c27e90 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -2487,10 +2487,34 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) s = Fl::screen_driver()->scale(nscreen); // if (!win->parent()) printf("win creation on screen #%d\n", nscreen); #endif + + int win_x = rint(X*s); + int win_y = rint(Y*s); + + switch (Fl_X11_Window_Driver::driver(win)->win_gravity_) { + case Fl_X11_Window_Driver::WIN_GRAVITY_NORTHEAST: + case Fl_X11_Window_Driver::WIN_GRAVITY_EAST: + case Fl_X11_Window_Driver::WIN_GRAVITY_SOUTHEAST: + win_x = Fl::screen_driver()->x_from_right(X); + break; + default: + break; + } + + switch (Fl_X11_Window_Driver::driver(win)->win_gravity_) { + case Fl_X11_Window_Driver::WIN_GRAVITY_SOUTHWEST: + case Fl_X11_Window_Driver::WIN_GRAVITY_SOUTH: + case Fl_X11_Window_Driver::WIN_GRAVITY_SOUTHEAST: + win_y = Fl::screen_driver()->y_from_bottom(Y); + break; + default: + break; + } + Fl_X* xp = set_xid(win, XCreateWindow(fl_display, root, - rint(X*s), rint(Y*s), W*s, H*s, + win_x, win_y, W*s, H*s, 0, // borderwidth visual->depth, InputOutput, diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.H b/src/drivers/X11/Fl_X11_Screen_Driver.H index 17826a94d..89bbca2dd 100644 --- a/src/drivers/X11/Fl_X11_Screen_Driver.H +++ b/src/drivers/X11/Fl_X11_Screen_Driver.H @@ -81,6 +81,8 @@ public: int y() FL_OVERRIDE; int w() FL_OVERRIDE; int h() FL_OVERRIDE; + int x_from_right(int x) FL_OVERRIDE; + int y_from_bottom(int y) FL_OVERRIDE; void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE; void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx index 9e3465f13..4debda429 100644 --- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "../../Fl_Timeout.h" @@ -252,6 +253,22 @@ int Fl_X11_Screen_Driver::h() { ; } +// Returns a real (unscaled) X coordinate calculated relative to the right of +// of the screen. Used when positioning window with "east" gravity. + +int Fl_X11_Screen_Driver::x_from_right(int x) { + int dx = w() - x; + return (fl_workarea_xywh[0] + fl_workarea_xywh[2]) - rint(dx * screens[0].scale); +} + +// Returns a real (unscaled) Y coordinate calculated relative to the bottom of +// the screen. Used when positioning window with "south" gravity. + +int Fl_X11_Screen_Driver::y_from_bottom(int y) { + int dy = h() - y; + return (fl_workarea_xywh[1] + fl_workarea_xywh[3]) - rint(dy * screens[0].scale); +} + #define USE_XRANDR (HAVE_DLSYM && HAVE_DLFCN_H) // means attempt to dynamically load libXrandr.so #if USE_XRANDR #include