fix gravity

This commit is contained in:
simonb 2006-07-03 17:18:17 +00:00
parent 7d2f7740d1
commit 12e80f3faf
6 changed files with 130 additions and 111 deletions

View file

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

View file

@ -838,7 +838,7 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce,
// 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

View file

@ -232,39 +232,31 @@ void FbWinFrame::shade() {
}
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 @@ void FbWinFrame::reconfigure() {
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::applyTabContainer() {
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 @@ void FbWinFrame::setBorderWidth(unsigned int border_width) {
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 @@ private:
// 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 @@ void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned i
* 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,60 +1675,54 @@ void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned i
// 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;
y_offset = -y_offset;
@ -1725,6 +1730,7 @@ void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned i
x += x_offset;
y += y_offset;
if (move_frame && (x_offset != 0 || y_offset != 0)) {
move(x, y);
}

View file

@ -96,20 +96,20 @@ public:
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 @@ public:
// 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);
/**
@ -369,6 +368,10 @@ private:
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
unsigned int m_width_before_shade, ///< width before shade, so we can restore it when we unshade

View file

@ -495,15 +495,18 @@ void FluxboxWindow::init() {
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);
grabButtons();
@ -514,10 +517,9 @@ void FluxboxWindow::init() {
m_workspace_number = screen().currentWorkspaceID();
bool place_window = (m_old_pos_x == 0);
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() || m_client->isTransient() ||
m_client->normal_hint_flags & (PPosition|USPosition)) {
if (! fluxbox.isStartup()) {
@ -534,10 +536,12 @@ void FluxboxWindow::init() {
place_window = false;
}
/*
if (wattrib.width <= 0)
wattrib.width = 1;
if (wattrib.height <= 0)
wattrib.height = 1;
*/
@ -1109,17 +1113,18 @@ bool FluxboxWindow::isGroupable() const {
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 @@ void FluxboxWindow::updateBlackboxHintsFromClient(const WinClient &client) {
}
}
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 @@ void FluxboxWindow::resize(unsigned int width, unsigned int height) {
// 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::moveResize(int new_x, int new_y,
}
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 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) {
(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,21 +3164,22 @@ void FluxboxWindow::setDecoration(Decoration decoration, bool apply) {
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
// to external and is meant to be hidden
@ -3202,7 +3207,7 @@ void FluxboxWindow::applyDecorations(bool initial) {
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 @@ void FluxboxWindow::stopMoving(bool interrupted) {
}
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 @@ void FluxboxWindow::restore(WinClient *client, bool remap) {
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.

View file

@ -240,13 +240,13 @@ public:
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 @@ private:
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);