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: