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.
This commit is contained in:
Ciaran Anscomb 2023-08-14 14:18:10 +01:00
parent 570c0cce06
commit 209f348ca4
4 changed files with 46 additions and 1 deletions

View File

@ -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*/) {

View File

@ -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,

View File

@ -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;

View File

@ -26,6 +26,7 @@
#include <FL/Fl_Image_Surface.H>
#include <FL/Fl_Tooltip.H>
#include <FL/filename.H>
#include <math.h>
#include <sys/time.h>
#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 <dlfcn.h>