fix gravity
@@ -1,6 +1,11 @@
(Format: Year/Month/Day) Changes for 1.0rc3: *06/07/03: + * fix+improve handling of window gravity, was very broken (Simon) + - caused (among others) windows with gravity set to get relocated + on close. + - gravity is now taken into account on style change + FbWinFrame.hh/cc Window.hh/cc Ewmh.cc * make our default locale, init, menu, and style paths properly expand PREFIX in the make install stage, so that make prefix=elsewhere works properly (Simon)
@@ -838,7 +838,7 @@ // ce.data.l[4] = height
// TODO: flags int win_gravity=ce.data.l[0] & 0xFF; winclient->fbwindow()->moveResizeForClient(ce.data.l[1], ce.data.l[2], - ce.data.l[3], ce.data.l[4], win_gravity); + ce.data.l[3], ce.data.l[4], win_gravity, winclient->old_bw); return true; } else if (ce.message_type == m_net_restack_window) { #ifndef DEBUG
@@ -232,39 +232,31 @@ }
} -void FbWinFrame::move(int x, int y, int win_gravity) { - moveResize(x, y, 0, 0, true, false, win_gravity); +void FbWinFrame::move(int x, int y) { + moveResize(x, y, 0, 0, true, false); } -void FbWinFrame::resize(unsigned int width, unsigned int height, int win_gravity) { - moveResize(0, 0, width, height, false, true, win_gravity); +void FbWinFrame::resize(unsigned int width, unsigned int height) { + moveResize(0, 0, width, height, false, true); } // need an atomic moveresize where possible -void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity) { +void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity, unsigned int client_bw) { // total height for frame - unsigned int total_height = height; + if (resize) // these fns check if the elements are "on" + height += titlebarHeight() + handleHeight(); - if (resize) { - // having a titlebar = 1 extra border + titlebar height - if (m_use_titlebar) - total_height += m_titlebar.height() + m_titlebar.borderWidth(); - // having a handle = 1 extra border + handle height - if (m_use_handle) - total_height += m_handle.height() + m_handle.borderWidth(); - } - moveResize(x, y, width, total_height, move, resize, win_gravity); + gravityTranslate(x, y, win_gravity, client_bw, false); + setActiveGravity(win_gravity, client_bw); + moveResize(x, y, width, height, move, resize); } -void FbWinFrame::resizeForClient(unsigned int width, unsigned int height, int win_gravity) { - moveResizeForClient(0, 0, width, height, false, true, win_gravity); +void FbWinFrame::resizeForClient(unsigned int width, unsigned int height, int win_gravity, unsigned int client_bw) { + moveResizeForClient(0, 0, width, height, false, true, win_gravity, client_bw); } -void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity) { - if(win_gravity!=ForgetGravity) { - gravityTranslate(x, y, width + m_window.borderWidth()*2, height + m_window.borderWidth()*2, win_gravity, false); - } +void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height, bool move, bool resize) { if (move && x == window().x() && y == window().y()) move = false;@@ -946,6 +938,10 @@ void FbWinFrame::reconfigure() {
if (m_tab_container.empty()) return; + int grav_x=0, grav_y=0; + // negate gravity + gravityTranslate(grav_x, grav_y, -m_active_gravity, m_active_orig_client_bw, false); + m_bevel = theme().bevelWidth(); // reconfigure can't set borderwidth, as it doesn't know // if it's meant to be borderless or not@@ -1035,6 +1031,10 @@ m_clientarea.moveResize(0, client_top,
m_window.width(), client_height); } + gravityTranslate(grav_x, grav_y, m_active_gravity, m_active_orig_client_bw, false); + // if the location changes, shift it + if (grav_x != 0 || grav_y != 0) + move(grav_x + x(), grav_y + y()); // render the theme if (isVisible()) {@@ -1532,6 +1532,12 @@ }
void FbWinFrame::setBorderWidth(unsigned int border_width) { int bw_changes = 0; + + int grav_x=0, grav_y=0; + // negate gravity + gravityTranslate(grav_x, grav_y, -m_active_gravity, m_active_orig_client_bw, false); + + // we need to change the size of the window // if the border width changes... if (m_use_titlebar)@@ -1570,6 +1576,12 @@ resize(width(), height() + bw_changes);
if (m_tabmode == EXTERNAL) alignTabs(); + + gravityTranslate(grav_x, grav_y, m_active_gravity, m_active_orig_client_bw, false); + // if the location changes, shift it + if (grav_x != 0 || grav_y != 0) + move(grav_x + x(), grav_y + y()); + } void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {@@ -1635,11 +1647,7 @@
// this function translates its arguments according to win_gravity // if win_gravity is negative, it does an inverse translation // This function should be used when a window is mapped/unmapped/pos configured -void FbWinFrame::gravityTranslate(int &x, int &y, int win_gravity, bool move_frame) { - gravityTranslate(x, y, m_window.width(), m_window.height(), win_gravity, move_frame); -} -//use width and height given instead of the real values, allows figuring out where to place a window before doing a moveResize -void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned int height, int win_gravity, bool move_frame) { +void FbWinFrame::gravityTranslate(int &x, int &y, int win_gravity, unsigned int client_bw, bool move_frame) { bool invert = false; if (win_gravity < 0) { invert = true;@@ -1657,6 +1665,9 @@ * frame is placed where the centre of the rhs of the window would
* have been if there was no frame. * Hope that makes enough sense. * + * NOTE: the gravity calculations are INDEPENDENT of the client + * window width/height. + * * If you get confused with the calculations, draw a picture. * */@@ -1664,59 +1675,53 @@
// We calculate offsets based on the gravity and frame aspects // and at the end apply those offsets +ve or -ve depending on 'invert' + // These will be set to the resulting offsets for adjusting the frame position int x_offset = 0; int y_offset = 0; - /* win_gravity: placed at the reference point - * StaticGravity the left top corner of the client window - * NorthWestGravity the left top corner of the frame window - * NorthGravity the center of the frame window's top side - * NorthEastGravity the right top corner of the frame window - * EastGravity the center of the frame window's right side - * SouthEastGravity the right bottom corner of the frame window - * SouthGravity the center of the frame window's bottom side - * SouthWestGravity the left bottom corner of the frame window - * WestGravity the center of the frame window's left side - * CenterGravity the center of the frame window - */ - + // These are the amount that the frame is larger than the client window + // Note that the client window's x,y is offset by it's borderWidth, which + // is removed by fluxbox, so the gravity needs to account for this change - //vertical offset - //North Gravities don't require a vertical offset - //South Gravities - if (win_gravity==SouthWestGravity || win_gravity==SouthGravity || - win_gravity==SouthEastGravity) { - //We start on the frame so going the full height would take us one pixel past the edge of the frame - y_offset-=height-1; - } +// unsigned int width_offset = 0; // no side decorations - //vertical centering - if (win_gravity==WestGravity || win_gravity==CenterGravity || - win_gravity==EastGravity) { - y_offset-=height/2; - } + // these functions already check if the title/handle is used + int height_offset = - titlebarHeight() - handleHeight(); - //horizontal offset - //West Gravities don't require a horizontal offset - //East Gravities - if (win_gravity==NorthEastGravity || win_gravity==EastGravity || - win_gravity==SouthEastGravity ) { - //Starting on the frame so offset of one width would end up one pixel beyond the border - x_offset-=width-1; - } - //horizontal centering - if (win_gravity==NorthGravity || win_gravity==CenterGravity || - win_gravity==SouthGravity ) { - x_offset-=width/2; - } + int bw_diff = client_bw - m_window.borderWidth(); - if( win_gravity==StaticGravity ) { - if (m_use_titlebar) - y_offset -= m_titlebar.height() + m_titlebar.borderWidth(); - x_offset -= m_window.borderWidth(); - y_offset -= m_window.borderWidth(); + // mostly no X offset, since we don't have extra frame on the sides + switch (win_gravity) { + case NorthEastGravity: + x_offset += bw_diff; + case NorthGravity: + x_offset += bw_diff; + case NorthWestGravity: + // no offset, since the top point is still the same + break; + case SouthEastGravity: + x_offset += bw_diff; + case SouthGravity: + x_offset += bw_diff; + case SouthWestGravity: + // window shifted down by height of titlebar, and the handle + // since that's necessary to get the bottom of the frame + // all the way up + y_offset += 2*bw_diff + height_offset; + break; + case EastGravity: + x_offset += bw_diff; + case CenterGravity: + x_offset += bw_diff; + case WestGravity: + // these centered ones are a little more interesting + y_offset += bw_diff + height_offset/2; + break; + case StaticGravity: + x_offset += bw_diff; + y_offset += -titlebarHeight() + bw_diff; + break; } - if (invert) { x_offset = -x_offset;@@ -1725,6 +1730,7 @@ }
x += x_offset; y += y_offset; + if (move_frame && (x_offset != 0 || y_offset != 0)) { move(x, y); }
@@ -96,20 +96,20 @@ void show();
inline bool isVisible() const { return m_visible; } /// shade frame (ie resize to titlebar size) void shade(); - void move(int x, int y, int win_gravity=ForgetGravity); - void resize(unsigned int width, unsigned int height, int win_gravity=ForgetGravity); + void move(int x, int y); + void resize(unsigned int width, unsigned int height); /// resize client to specified size and resize frame to it - void resizeForClient(unsigned int width, unsigned int height, int win_gravity=ForgetGravity); + void resizeForClient(unsigned int width, unsigned int height, int win_gravity=ForgetGravity, unsigned int client_bw = 0); // for when there needs to be an atomic move+resize operation void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, - bool move = true, bool resize = true, int win_gravity=ForgetGravity); + bool move = true, bool resize = true, int win_gravity=ForgetGravity, unsigned int client_bw = 0); // can elect to ignore move or resize (mainly for use of move/resize individual functions void moveResize(int x, int y, unsigned int width, unsigned int height, - bool move = true, bool resize = true, int win_gravity=ForgetGravity); + bool move = true, bool resize = true); // move without transparency or special effects (generally when dragging) void quietMoveResize(int x, int y,@@ -173,9 +173,8 @@ bool showAllDecorations();
// this function translates its arguments according to win_gravity // if win_gravity is negative, it does an inverse translation - void gravityTranslate(int &x, int &y, int win_gravity, bool move_frame = false); - //use width and height given instead of the real values, allows figuring out where to place a window before doing a moveResize - void gravityTranslate(int &x, int &y, unsigned int width, unsigned int height, int win_gravity, bool move_frame = false); + void gravityTranslate(int &x, int &y, int win_gravity, unsigned int client_bw, bool move_frame = false); + void setActiveGravity(int gravity, unsigned int orig_client_bw) { m_active_gravity = gravity; m_active_orig_client_bw = orig_client_bw; } void setBorderWidth(unsigned int borderW); /**@@ -368,6 +367,10 @@ FbTk::Color m_grip_unfocused_color; ///< unfocused color for grip if no pixmap is given
//@} TabMode m_tabmode; + + // last gravity that this window was *actively* placed with + int m_active_gravity; + unsigned int m_active_orig_client_bw; bool m_need_render; int m_button_size; ///< size for all titlebar buttons
@@ -495,14 +495,17 @@ functions.resize = functions.maximize = false;
decorations.tab = false; //no tab for this window } - associateClientWindow(true, wattrib.x, wattrib.y, wattrib.width, wattrib.height); + + if (m_client->normal_hint_flags & (PPosition|USPosition)) { + frame().gravityTranslate(wattrib.x, wattrib.y, m_client->gravity(), m_client->old_bw, false); + } + associateClientWindow(true, wattrib.x, wattrib.y, wattrib.width, wattrib.height, m_client->gravity(), m_client->old_bw); Fluxbox::instance()->attachSignals(*this); // this window is managed, we are now allowed to modify actual state m_initialized = true; - applyDecorations(true);@@ -514,10 +517,9 @@ if (m_workspace_number < 0 || m_workspace_number >= screen().numberOfWorkspaces())
m_workspace_number = screen().currentWorkspaceID(); bool place_window = (m_old_pos_x == 0); - if (fluxbox.isStartup() || m_client->isTransient() || + + if (fluxbox.isStartup() || m_client->isTransient() || m_client->normal_hint_flags & (PPosition|USPosition)) { - - frame().gravityTranslate(wattrib.x, wattrib.y, m_client->gravity(), false); if (! fluxbox.isStartup()) {@@ -534,10 +536,12 @@ } else
place_window = false; } +/* if (wattrib.width <= 0) wattrib.width = 1; if (wattrib.height <= 0) wattrib.height = 1; +*/@@ -1109,17 +1113,18 @@ }
void FluxboxWindow::associateClientWindow(bool use_attrs, int x, int y, - unsigned int width, unsigned int height) { - m_client->setBorderWidth(0); + unsigned int width, unsigned int height, + int gravity, unsigned int client_bw) { updateTitleFromClient(*m_client); updateIconNameFromClient(*m_client); if (use_attrs) frame().moveResizeForClient(x, y, - width, height); + width, height, gravity, client_bw); else frame().resizeForClient(m_client->width(), m_client->height()); + frame().setActiveGravity(m_client->gravity(), m_client->old_bw); frame().setClientWindow(*m_client); }@@ -1308,8 +1313,8 @@ setDecoration(m_old_decoration, false);
} } -void FluxboxWindow::move(int x, int y, int gravity) { - moveResize(x, y, frame().width(), frame().height(), gravity); +void FluxboxWindow::move(int x, int y) { + moveResize(x, y, frame().width(), frame().height()); } void FluxboxWindow::resize(unsigned int width, unsigned int height) {@@ -1325,16 +1330,12 @@ }
// send_event is just an override void FluxboxWindow::moveResize(int new_x, int new_y, - unsigned int new_width, unsigned int new_height, int gravity, bool send_event) { + unsigned int new_width, unsigned int new_height, bool send_event) { // magic to detect if moved during initialisation if (!isInitialized()) m_old_pos_x = 1; - if (gravity != ForgetGravity) { - frame().gravityTranslate(new_x, new_y, gravity, false); - } - send_event = send_event || (frame().x() != new_x || frame().y() != new_y); if (new_width != frame().width() || new_height != frame().height()) {@@ -1370,12 +1371,12 @@
} void FluxboxWindow::moveResizeForClient(int new_x, int new_y, - unsigned int new_width, unsigned int new_height, int gravity) { + unsigned int new_width, unsigned int new_height, int gravity, unsigned int client_bw) { // magic to detect if moved during initialisation if (!isInitialized()) m_old_pos_x = 1; - frame().moveResizeForClient(new_x, new_y, new_width, new_height, true, true, gravity); + frame().moveResizeForClient(new_x, new_y, new_width, new_height, true, true, gravity, client_bw); setFocusFlag(focused); shaded = false; sendConfigureNotify();@@ -2660,13 +2661,16 @@ if ((cr.value_mask & CWX) &&
(cr.value_mask & CWY)) { cx = cr.x; cy = cr.y; - frame().gravityTranslate(cx, cy, client->gravity(), false); + frame().gravityTranslate(cx, cy, client->gravity(), client->old_bw, false); + frame().setActiveGravity(client->gravity(), client->old_bw); } else if (cr.value_mask & CWX) { cx = cr.x; - frame().gravityTranslate(cx, ignore, client->gravity(), false); + frame().gravityTranslate(cx, ignore, client->gravity(), client->old_bw, false); + frame().setActiveGravity(client->gravity(), client->old_bw); } else if (cr.value_mask & CWY) { cy = cr.y; - frame().gravityTranslate(ignore, cy, client->gravity(), false); + frame().gravityTranslate(ignore, cy, client->gravity(), client->old_bw, false); + frame().setActiveGravity(client->gravity(), client->old_bw); } if (cr.value_mask & CWWidth)@@ -3160,20 +3164,21 @@ // commit current decoration values to actual displayed things
void FluxboxWindow::applyDecorations(bool initial) { frame().clientArea().setBorderWidth(0); // client area bordered by other things - int grav_x=0, grav_y=0; - // negate gravity - frame().gravityTranslate(grav_x, grav_y, -m_client->gravity(), false); - unsigned int border_width = 0; if (decorations.border) border_width = frame().theme().border().width(); bool client_move = false; + // borderWidth setting handles its own gravity if (initial || frame().window().borderWidth() != border_width) { client_move = true; frame().setBorderWidth(border_width); } + + int grav_x=0, grav_y=0; + // negate gravity + frame().gravityTranslate(grav_x, grav_y, -m_client->gravity(), m_client->old_bw, false); // tab deocration only affects if we're external // must do before the setTabMode in case it goes@@ -3202,7 +3207,7 @@ } else
client_move |= frame().hideHandle(); // apply gravity once more - frame().gravityTranslate(grav_x, grav_y, m_client->gravity(), false); + frame().gravityTranslate(grav_x, grav_y, m_client->gravity(), m_client->old_bw, false); // if the location changes, shift it if (grav_x != 0 || grav_y != 0) {@@ -3337,7 +3342,7 @@ }
} fluxbox->ungrab(); } else if (!interrupted) { - moveResize(frame().x(), frame().y(), frame().width(), frame().height(), ForgetGravity, true); + moveResize(frame().x(), frame().y(), frame().width(), frame().height(), true); frame().notifyMoved(true); }@@ -3680,7 +3685,7 @@ XChangeSaveSet(display, client->window(), SetModeDelete);
client->setEventMask(NoEventMask); int wx = frame().x(), wy = frame().y(); // not actually used here - frame().gravityTranslate(wx, wy, -client->gravity(), true); // negative to invert + frame().gravityTranslate(wx, wy, -client->gravity(), client->old_bw, true); // negative to invert // Why was this hide done? It broke vncviewer (and mplayer?), // since it would reparent when going fullscreen.
@@ -240,13 +240,13 @@ void installColormap(bool);
void restore(WinClient *client, bool remap); void restore(bool remap); /// move frame to x, y - void move(int x, int y, int gravity = ForgetGravity); + void move(int x, int y); /// resize frame to width, height void resize(unsigned int width, unsigned int height); /// move and resize frame to pox x,y and size width, height - void moveResize(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity, bool send_event = false); + void moveResize(int x, int y, unsigned int width, unsigned int height, bool send_event = false); /// move to pos x,y and resize client window to size width, height - void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity); + void moveResizeForClient(int x, int y, unsigned int width, unsigned int height, int gravity = ForgetGravity, unsigned int client_bw = 0); void setWorkspace(int n); void changeBlackboxHints(const BlackboxHints &bh); void updateFunctions();@@ -448,7 +448,7 @@ void updateMWMHintsFromClient(WinClient &client);
void updateBlackboxHintsFromClient(const WinClient &client); void updateRememberStateFromClient(WinClient &client); void saveBlackboxAttribs(); - void associateClientWindow(bool use_attrs = false, int x = 0, int y = 0, unsigned int width = 1, unsigned int height = 1); + void associateClientWindow(bool use_attrs = false, int x = 0, int y = 0, unsigned int width = 1, unsigned int height = 1, int gravity = ForgetGravity, unsigned int client_bw = 0); void setState(unsigned long stateval, bool setting_up);