From 570c0cce066d2baab9504aece94a91c3e3a6405c Mon Sep 17 00:00:00 2001 From: Ciaran Anscomb Date: Mon, 14 Aug 2023 11:59:20 +0100 Subject: [PATCH] Set window gravity hint correctly for X11 Removes some window positioning bodges, which mess with coordinates. Window Managers should be responsible for placing windows correctly if they're adding title bars and such to them. 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. Updated patch fixes use of uninitialised variable, with help from Albrecht Schlosser. --- src/Fl_Window_Driver.H | 20 ++++++++++++++++++++ src/Fl_Window_Driver.cxx | 1 + src/Fl_arg.cxx | 30 ++++++++++++++++++++++++++++++ src/Fl_x.cxx | 19 ++++++++++++++++++- 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/Fl_Window_Driver.H b/src/Fl_Window_Driver.H index 9d7588d9d..29c09bea8 100644 --- a/src/Fl_Window_Driver.H +++ b/src/Fl_Window_Driver.H @@ -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. */ diff --git a/src/Fl_Window_Driver.cxx b/src/Fl_Window_Driver.cxx index 25d2554c6..92d1d7343 100644 --- a/src/Fl_Window_Driver.cxx +++ b/src/Fl_Window_Driver.cxx @@ -43,6 +43,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; } diff --git a/src/Fl_arg.cxx b/src/Fl_arg.cxx index 08254c3e9..79777e5cb 100644 --- a/src/Fl_arg.cxx +++ b/src/Fl_arg.cxx @@ -284,6 +284,36 @@ void Fl_Window::show(int argc, char **argv) { 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; + + // 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; diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 1dffa6e1c..1704be57e 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -2375,6 +2375,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) @@ -2392,6 +2397,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 @@ -2647,7 +2653,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: