This commit is contained in:
six809 2026-03-14 09:24:45 +07:00 committed by GitHub
commit a12dfd3358
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 117 additions and 4 deletions

View File

@ -114,6 +114,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

@ -58,6 +58,8 @@ private:
protected:
Fl_Window *pWindow;
int screen_num_; // number of screen where window is mapped
int win_gravity_;
public:
Fl_Window_Driver(Fl_Window *);
virtual ~Fl_Window_Driver();
@ -69,6 +71,24 @@ public:
int screen_num();
void screen_num(int n) { screen_num_ = n; }
// Window gravity
enum WIN_GRAVITY {
WIN_GRAVITY_UNMAP = 0,
WIN_GRAVITY_NORTHWEST = 1,
WIN_GRAVITY_NORTH = 2,
WIN_GRAVITY_NORTHEAST = 3,
WIN_GRAVITY_WEST = 4,
WIN_GRAVITY_CENTER = 5,
WIN_GRAVITY_EAST = 6,
WIN_GRAVITY_SOUTHWEST = 7,
WIN_GRAVITY_SOUTH = 8,
WIN_GRAVITY_SOUTHEAST = 9,
WIN_GRAVITY_STATIC = 10,
};
/**
Sets the desired window gravity. Almost certainly only useful in X11.
*/
virtual void win_gravity(int g) { win_gravity_ = g; }
// --- frequently used accessors to public window data
/** returns the x coordinate of the window. */

View File

@ -44,6 +44,7 @@ Fl_Window_Driver::Fl_Window_Driver(Fl_Window *win)
wait_for_expose_value = 0;
other_xid = 0;
screen_num_ = 0;
win_gravity_ = WIN_GRAVITY_STATIC;
}

View File

@ -298,8 +298,38 @@ void Fl_Window::show(int argc, char **argv) {
if (geometry) {
int fl = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h();
fl = Fl::screen_driver()->XParseGeometry(geometry, &gx, &gy, &gw, &gh);
if (fl & Fl_Screen_Driver::fl_XNegative) gx = Fl::w()-w()+gx;
if (fl & Fl_Screen_Driver::fl_YNegative) gy = Fl::h()-h()+gy;
if (fl & Fl_Screen_Driver::fl_XNegative) gx = Fl::w()-gw+gx;
if (fl & Fl_Screen_Driver::fl_YNegative) gy = Fl::h()-gh+gy;
// Determine window gravity from geometry. Note that negative X and Y
// will only end up truly accurate if the screen scale is (or has been
// set to) 1.0. This is because information about the actual screen
// dimensions has been lost scaling integers.
static const Fl_Window_Driver::WIN_GRAVITY gravity_table[16] = {
Fl_Window_Driver::WIN_GRAVITY_STATIC,
Fl_Window_Driver::WIN_GRAVITY_WEST,
Fl_Window_Driver::WIN_GRAVITY_NORTH,
Fl_Window_Driver::WIN_GRAVITY_NORTHWEST,
Fl_Window_Driver::WIN_GRAVITY_STATIC,
Fl_Window_Driver::WIN_GRAVITY_EAST,
Fl_Window_Driver::WIN_GRAVITY_NORTH,
Fl_Window_Driver::WIN_GRAVITY_NORTHEAST,
Fl_Window_Driver::WIN_GRAVITY_STATIC,
Fl_Window_Driver::WIN_GRAVITY_WEST,
Fl_Window_Driver::WIN_GRAVITY_SOUTH,
Fl_Window_Driver::WIN_GRAVITY_SOUTHWEST,
Fl_Window_Driver::WIN_GRAVITY_STATIC,
Fl_Window_Driver::WIN_GRAVITY_EAST,
Fl_Window_Driver::WIN_GRAVITY_SOUTH,
Fl_Window_Driver::WIN_GRAVITY_SOUTHEAST
};
int gravity_index = 0;
gravity_index |= (fl & Fl_Screen_Driver::fl_XValue) ? 1 : 0;
gravity_index |= (fl & Fl_Screen_Driver::fl_YValue) ? 2 : 0;
gravity_index |= (fl & Fl_Screen_Driver::fl_XNegative) ? 4 : 0;
gravity_index |= (fl & Fl_Screen_Driver::fl_YNegative) ? 8 : 0;
pWindowDriver->win_gravity(gravity_table[gravity_index]);
// int mw,mh; minsize(mw,mh);
// if (mw > gw) gw = mw;
// if (mh > gh) gh = mh;

View File

@ -2575,6 +2575,11 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
int scr_x, scr_y, scr_w, scr_h;
Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H);
#if 0
// Munging the coordinates here just makes it impossible to put windows in
// the right place. With win_gravity hints now being set, this should all
// be down to the window manager.
if (win->border()) {
// ensure border is on screen:
// (assume extremely minimal dimensions for this border)
@ -2592,6 +2597,7 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
if (X < scr_x) X = scr_x;
if (Y+H > scr_y+scr_h) Y = scr_y+scr_h-H;
if (Y < scr_y) Y = scr_y;
#endif
}
// if the window is a subwindow and our parent is not mapped yet, we
@ -2681,10 +2687,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,
@ -2849,7 +2879,18 @@ void Fl_X11_Window_Driver::sendxjunk() {
hints->height_inc = 0;
}
hints->win_gravity = StaticGravity;
switch (win_gravity_) {
case WIN_GRAVITY_NORTHWEST: hints->win_gravity = NorthWestGravity; break;
case WIN_GRAVITY_NORTH: hints->win_gravity = NorthGravity; break;
case WIN_GRAVITY_NORTHEAST: hints->win_gravity = NorthEastGravity; break;
case WIN_GRAVITY_WEST: hints->win_gravity = WestGravity; break;
case WIN_GRAVITY_CENTER: hints->win_gravity = CenterGravity; break;
case WIN_GRAVITY_EAST: hints->win_gravity = EastGravity; break;
case WIN_GRAVITY_SOUTHWEST: hints->win_gravity = SouthWestGravity; break;
case WIN_GRAVITY_SOUTH: hints->win_gravity = SouthGravity; break;
case WIN_GRAVITY_SOUTHEAST: hints->win_gravity = SouthEastGravity; break;
default: hints->win_gravity = StaticGravity; break;
}
// see the file /usr/include/X11/Xm/MwmUtil.h:
// fill all fields to avoid bugs in kwm and perhaps other window managers:

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

@ -27,6 +27,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"
@ -273,6 +274,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>