frame.border_w = 1;
frame.window = frame.plate = frame.title = frame.handle = None;
- frame.close_button = frame.iconify_button = frame.maximize_button = None;
+ frame.close_button = frame.iconify_button = frame.maximize_button =
+ frame.stick_button = None;
frame.right_grip = frame.left_grip = None;
frame.ulabel_pixel = frame.flabel_pixel = frame.utitle_pixel =
windowmenu = 0;
/*
- get the initial size and location of client window (relative to the
+ set the initial size and location of client window (relative to the
_root window_). This position is the reference point used with the
window's gravity to find the window's initial position.
*/
blackbox->saveWindowSearch(frame.window, this);
- frame.plate = createChildWindow(frame.window);
+ frame.plate = createChildWindow(frame.window, ExposureMask);
blackbox->saveWindowSearch(frame.plate, this);
// determine if this is a transient window
break;
case Type_Normal:
- // normal windows retain all of the possible decorations and functionality
+ // normal windows retain all of the possible decorations and
+ // functionality
break;
}
} else {
attrib_create.background_pixmap = None;
attrib_create.colormap = screen->getColormap();
attrib_create.override_redirect = True;
- attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
- ButtonMotionMask |
- EnterWindowMask | LeaveWindowMask;
+ attrib_create.event_mask = EnterWindowMask | LeaveWindowMask;
return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(),
0, 0, 1, 1, frame.border_w, screen->getDepth(),
* Creates a child window, and optionally associates a given cursor with
* the new window.
*/
-Window BlackboxWindow::createChildWindow(Window parent, Cursor cursor) {
+Window BlackboxWindow::createChildWindow(Window parent,
+ unsigned long event_mask,
+ Cursor cursor) {
XSetWindowAttributes attrib_create;
unsigned long create_mask = CWBackPixmap | CWBorderPixel |
CWEventMask;
attrib_create.background_pixmap = None;
- attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
- ButtonMotionMask | ExposureMask;
+ attrib_create.event_mask = event_mask;
if (cursor) {
create_mask |= CWCursor;
}
if (decorations & Decor_Border) {
- frame.fborder_pixel = screen->getWindowStyle()->f_focus.pixel();
- frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.pixel();
+ frame.fborder_pixel = screen->getWindowStyle()->f_focus.color().pixel();
+ frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.color().pixel();
}
if (decorations & Decor_Handle) {
void BlackboxWindow::createHandle(void) {
- frame.handle = createChildWindow(frame.window);
+ frame.handle = createChildWindow(frame.window,
+ ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
blackbox->saveWindowSearch(frame.handle, this);
frame.left_grip =
- createChildWindow(frame.handle, blackbox->getLowerLeftAngleCursor());
+ createChildWindow(frame.handle,
+ ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask,
+ blackbox->getLowerLeftAngleCursor());
blackbox->saveWindowSearch(frame.left_grip, this);
frame.right_grip =
- createChildWindow(frame.handle, blackbox->getLowerRightAngleCursor());
+ createChildWindow(frame.handle,
+ ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask,
+ blackbox->getLowerRightAngleCursor());
blackbox->saveWindowSearch(frame.right_grip, this);
}
void BlackboxWindow::createTitlebar(void) {
- frame.title = createChildWindow(frame.window);
- frame.label = createChildWindow(frame.title);
+ frame.title = createChildWindow(frame.window,
+ ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
+ frame.label = createChildWindow(frame.title,
+ ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
blackbox->saveWindowSearch(frame.title, this);
blackbox->saveWindowSearch(frame.label, this);
if (frame.maximize_button)
destroyMaximizeButton();
+ if (frame.stick_button)
+ destroyStickyButton();
+
if (frame.ftitle)
screen->getImageControl()->removeImage(frame.ftitle);
void BlackboxWindow::createCloseButton(void) {
if (frame.title != None) {
- frame.close_button = createChildWindow(frame.title);
+ frame.close_button = createChildWindow(frame.title,
+ ButtonPressMask |
+ ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
blackbox->saveWindowSearch(frame.close_button, this);
}
}
void BlackboxWindow::createIconifyButton(void) {
if (frame.title != None) {
- frame.iconify_button = createChildWindow(frame.title);
+ frame.iconify_button = createChildWindow(frame.title,
+ ButtonPressMask |
+ ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
blackbox->saveWindowSearch(frame.iconify_button, this);
}
}
void BlackboxWindow::createMaximizeButton(void) {
if (frame.title != None) {
- frame.maximize_button = createChildWindow(frame.title);
+ frame.maximize_button = createChildWindow(frame.title,
+ ButtonPressMask |
+ ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
blackbox->saveWindowSearch(frame.maximize_button, this);
}
}
frame.maximize_button = None;
}
+void BlackboxWindow::createStickyButton(void) {
+ if (frame.title != None) {
+ frame.stick_button = createChildWindow(frame.title,
+ ButtonPressMask |
+ ButtonReleaseMask |
+ ButtonMotionMask | ExposureMask);
+ blackbox->saveWindowSearch(frame.stick_button, this);
+ }
+}
+
+void BlackboxWindow::destroyStickyButton(void) {
+ blackbox->removeWindowSearch(frame.stick_button);
+ XDestroyWindow(blackbox->getXDisplay(), frame.stick_button);
+ frame.stick_button = None;
+}
void BlackboxWindow::positionButtons(bool redecorate_label) {
string layout = blackbox->getTitlebarLayout();
string parsed;
- bool hasclose, hasiconify, hasmaximize, haslabel;
- hasclose = hasiconify = hasmaximize = haslabel = false;
+ bool hasclose, hasiconify, hasmaximize, haslabel, hasstick;
+ hasclose = hasiconify = hasmaximize = haslabel = hasstick = false;
string::const_iterator it, end;
for (it = layout.begin(), end = layout.end(); it != end; ++it) {
parsed += *it;
}
break;
+ case 'S':
+ if (!hasstick) {
+ hasstick = true;
+ parsed += *it;
+ }
+ break;
case 'M':
if (! hasmaximize && (decorations & Decor_Maximize)) {
hasmaximize = true;
haslabel = true;
parsed += *it;
}
+ break;
}
}
+
if (! hasclose && frame.close_button)
destroyCloseButton();
if (! hasiconify && frame.iconify_button)
destroyIconifyButton();
if (! hasmaximize && frame.maximize_button)
destroyMaximizeButton();
+ if (! hasstick && frame.stick_button)
+ destroyStickyButton();
if (! haslabel)
parsed += 'L'; // require that the label be in the layout
frame.button_w, frame.button_w);
x += frame.button_w + bsep;
break;
+ case 'S':
+ if (! frame.stick_button) createStickyButton();
+ XMoveResizeWindow(blackbox->getXDisplay(), frame.stick_button, x, by,
+ frame.button_w, frame.button_w);
+ x += frame.button_w + bsep;
+ break;
case 'M':
if (! frame.maximize_button) createMaximizeButton();
XMoveResizeWindow(blackbox->getXDisplay(), frame.maximize_button, x, by,
// alt+middle lowers the window
blackbox->grabButton(Button2, mod_mask, frame.window, True,
ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
- frame.window, None,
- screen->allowScrollLock());
+ frame.window, None, screen->allowScrollLock());
}
bool BlackboxWindow::getWindowType(void) {
- unsigned long val;
+ window_type = (WindowType) -1;
+
+ unsigned long *val;
+ unsigned long num = (unsigned) -1;
if (xatom->getValue(client.window, XAtom::net_wm_window_type, XAtom::atom,
- val)) {
- if (val == xatom->getAtom(XAtom::net_wm_window_type_desktop))
- window_type = Type_Desktop;
- else if (val == xatom->getAtom(XAtom::net_wm_window_type_dock))
- window_type = Type_Dock;
- else if (val == xatom->getAtom(XAtom::net_wm_window_type_toolbar))
- window_type = Type_Toolbar;
- else if (val == xatom->getAtom(XAtom::net_wm_window_type_menu))
- window_type = Type_Menu;
- else if (val == xatom->getAtom(XAtom::net_wm_window_type_utility))
- window_type = Type_Utility;
- else if (val == xatom->getAtom(XAtom::net_wm_window_type_splash))
- window_type = Type_Splash;
- else if (val == xatom->getAtom(XAtom::net_wm_window_type_dialog))
+ num, &val)) {
+ for (unsigned long i = 0; i < num; ++i) {
+ if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_desktop))
+ window_type = Type_Desktop;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_dock))
+ window_type = Type_Dock;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_toolbar))
+ window_type = Type_Toolbar;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_menu))
+ window_type = Type_Menu;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_utility))
+ window_type = Type_Utility;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_splash))
+ window_type = Type_Splash;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_dialog))
+ window_type = Type_Dialog;
+ else if (val[i] == xatom->getAtom(XAtom::net_wm_window_type_normal))
+ window_type = Type_Normal;
+ else if (val[i] ==
+ xatom->getAtom(XAtom::kde_net_wm_window_type_override))
+ mwm_decorations = 0; // prevent this window from getting any decor
+ }
+ delete val;
+ }
+
+ if (window_type == (WindowType) -1) {
+ /*
+ * the window type hint was not set, which means we either classify ourself
+ * as a normal window or a dialog, depending on if we are a transient.
+ */
+ if (isTransient())
window_type = Type_Dialog;
- else //if (val[0] == xatom->getAtom(XAtom::net_wm_window_type_normal))
+ else
window_type = Type_Normal;
- return True;
+ return False;
}
- /*
- * the window type hint was not set, which means we either classify ourself
- * as a normal window or a dialog, depending on if we are a transient.
- */
- if (isTransient())
- window_type = Type_Dialog;
-
- window_type = Type_Normal;
-
- return False;
+ return True;
}
client.title = i18n(WindowSet, WindowUnnamed, "Unnamed");
xatom->setValue(client.window, XAtom::net_wm_visible_name, XAtom::utf8,
client.title);
+
+#ifdef DEBUG_WITH_ID
+ // the 16 is the 8 chars of the debug text plus the number
+ char *tmp = new char[client.title.length() + 16];
+ sprintf(tmp, "%s; id: 0x%lx", client.title.c_str(), client.window);
+ client.title = tmp;
+ delete tmp;
+#endif
}
client.max_aspect_x = client.max_aspect_y = 1;
#endif
- /*
- use the full screen, not the strut modified size. otherwise when the
- availableArea changes max_width/height will be incorrect and lead to odd
- rendering bugs.
- */
- const Rect& screen_area = screen->getRect();
- client.max_width = screen_area.width();
- client.max_height = screen_area.height();
+ // don't limit the size of a window, the default max width is the biggest
+ // possible
+ client.max_width = (unsigned) -1;
+ client.max_height = (unsigned) -1;
+
if (! XGetWMNormalHints(blackbox->getXDisplay(), client.window,
&sizehint, &icccm_mask))
ShapeBounding, 0, 0, xrect, num,
ShapeUnion, Unsorted);
}
+
+
+void BlackboxWindow::clearShape(void) {
+ XShapeCombineMask(blackbox->getXDisplay(), frame.window, ShapeBounding,
+ frame.margin.left - frame.border_w,
+ frame.margin.top - frame.border_w,
+ None, ShapeSet);
+}
#endif // SHAPE
void BlackboxWindow::iconify(void) {
- if (flags.iconic) return;
+ if (flags.iconic || ! (functions & Func_Iconify)) return;
// We don't need to worry about resizing because resizing always grabs the X
// server. This should only ever happen if using opaque moving.
void BlackboxWindow::close(void) {
+ if (! (functions & Func_Close)) return;
+
XEvent ce;
ce.xclient.type = ClientMessage;
ce.xclient.message_type = xatom->getAtom(XAtom::wm_protocols);
void BlackboxWindow::maximize(unsigned int button) {
+ if (! (functions & Func_Maximize)) return;
+
// We don't need to worry about resizing because resizing always grabs the X
// server. This should only ever happen if using opaque moving.
if (flags.moving)
setState(current_state);
}
+
+ redrawAllButtons();
+
// go up the chain
if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul &&
client.transient_for->isStuck() != flags.stuck)
if (frame.iconify_button) redrawIconifyButton(False);
if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
if (frame.close_button) redrawCloseButton(False);
+ if (frame.stick_button) redrawStickyButton(flags.stuck);
}
XClearWindow(blackbox->getXDisplay(), frame.close_button);
BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
- screen->getWindowStyle()->b_pic_unfocus);
+ screen->getWindowStyle()->b_pic_unfocus, 0, 2);
XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
2, 2, (frame.button_w - 3), (frame.button_w - 3));
XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
}
+void BlackboxWindow::redrawStickyButton(bool pressed) const {
+ if (! pressed) {
+ if (flags.focused) {
+ if (frame.fbutton)
+ XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+ frame.stick_button, frame.fbutton);
+ else
+ XSetWindowBackground(blackbox->getXDisplay(), frame.stick_button,
+ frame.fbutton_pixel);
+ } else {
+ if (frame.ubutton)
+ XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+ frame.stick_button, frame.ubutton);
+ else
+ XSetWindowBackground(blackbox->getXDisplay(), frame.stick_button,
+ frame.ubutton_pixel);
+ }
+ } else {
+ if (frame.pbutton)
+ XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+ frame.stick_button, frame.pbutton);
+ else
+ XSetWindowBackground(blackbox->getXDisplay(), frame.stick_button,
+ frame.pbutton_pixel);
+ }
+ XClearWindow(blackbox->getXDisplay(), frame.stick_button);
+
+ BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+ screen->getWindowStyle()->b_pic_unfocus);
+
+ XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(),
+ frame.button_w/2 - 1, frame.button_w/2 -1, 2, 2 );
+}
+
void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) {
if (re->window != client.window)
return;
void BlackboxWindow::propertyNotifyEvent(const XPropertyEvent *pe) {
- if (pe->state == PropertyDelete)
+ if (pe->state == PropertyDelete || ! validateClient())
return;
#if 0
// determine if this is a transient window
getTransientInfo();
+ if (flags.stuck != s) stick();
+
// adjust the window decorations based on transience
if (isTransient()) {
functions &= ~Func_Maximize;
setAllowedActions();
setupDecor();
- if (flags.stuck != s) stick();
}
reconfigure();
redrawMaximizeButton(flags.maximized);
else if (frame.iconify_button == ee->window)
redrawIconifyButton(False);
+ else if (frame.stick_button == ee->window)
+ redrawStickyButton(flags.stuck);
}
client.old_bw = cr->border_width;
if (cr->value_mask & (CWX | CWY | CWWidth | CWHeight)) {
- Rect req = frame.rect;
+ frame.changing = frame.rect;
if (cr->value_mask & (CWX | CWY)) {
if (cr->value_mask & CWX)
if (cr->value_mask & CWY)
client.rect.setY(cr->y);
- applyGravity(req);
+ applyGravity(frame.changing);
}
- if (cr->value_mask & CWWidth)
- req.setWidth(cr->width + frame.margin.left + frame.margin.right);
+ if (cr->value_mask & (CWWidth | CWHeight)) {
+ if (cr->value_mask & CWWidth)
+ frame.changing.setWidth(cr->width +
+ frame.margin.left + frame.margin.right);
- if (cr->value_mask & CWHeight)
- req.setHeight(cr->height + frame.margin.top + frame.margin.bottom);
+ if (cr->value_mask & CWHeight)
+ frame.changing.setHeight(cr->height +
+ frame.margin.top + frame.margin.bottom);
+
+ /*
+ if a position change has been specified, then that position will be
+ used instead of determining a position based on the window's gravity.
+ */
+ if (! (cr->value_mask & (CWX | CWY))) {
+ Corner corner;
+ switch (client.win_gravity) {
+ case NorthEastGravity:
+ case EastGravity:
+ corner = TopRight;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ corner = BottomLeft;
+ break;
+ case SouthEastGravity:
+ corner = BottomRight;
+ break;
+ default: // NorthWest, Static, etc
+ corner = TopLeft;
+ }
+ constrain(corner);
+ }
+ }
- configure(req.x(), req.y(), req.width(), req.height());
+ configure(frame.changing.x(), frame.changing.y(),
+ frame.changing.width(), frame.changing.height());
}
if (cr->value_mask & CWStackMode && !isDesktop()) {
redrawIconifyButton(True);
} else if (frame.close_button == be->window) {
redrawCloseButton(True);
+ } else if (frame.stick_button == be->window) {
+ redrawStickyButton(True);
} else if (frame.plate == be->window) {
if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
}
} else if (be->button == 2 && (be->window != frame.iconify_button) &&
- (be->window != frame.close_button)) {
+ (be->window != frame.close_button) &&
+ (be->window != frame.stick_button)) {
screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this);
} else if (windowmenu && be->button == 3 &&
(frame.title == be->window || frame.label == be->window ||
be->window == frame.title ||
be->window == frame.maximize_button ||
be->window == frame.iconify_button ||
- be->window == frame.close_button) &&
+ be->window == frame.close_button ||
+ be->window == frame.stick_button) &&
! flags.shaded)
shade();
// mouse wheel down
be->window == frame.title ||
be->window == frame.maximize_button ||
be->window == frame.iconify_button ||
- be->window == frame.close_button) &&
+ be->window == frame.close_button ||
+ be->window == frame.stick_button) &&
flags.shaded)
shade();
}
} else {
redrawIconifyButton(False);
}
+ } else if (re->window == frame.stick_button && re->button == 1) {
+ if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
+ (re->y >= 0 && re->y <= static_cast<signed>(frame.button_w))) {
+ stick();
+ } else {
+ redrawStickyButton(False);
+ }
} else if (re->window == frame.close_button & re->button == 1) {
if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
(re->y >= 0 && re->y <= static_cast<signed>(frame.button_w)))
void BlackboxWindow::beginMove(int x_root, int y_root) {
+ if (! (functions & Func_Move)) return;
+
assert(! (flags.resizing || flags.moving));
/*
dx -= frame.border_w;
dy -= frame.border_w;
- if (screen->doWorkspaceWarping())
- if (doWorkspaceWarping(x_root, y_root, dx, dy))
- return;
-
doWindowSnapping(dx, dy);
if (screen->doOpaqueMove()) {
+ if (screen->doWorkspaceWarping())
+ doWorkspaceWarping(x_root, y_root, dx);
+
configure(dx, dy, frame.rect.width(), frame.rect.height());
} else {
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
frame.changing.width() - 1,
frame.changing.height() - 1);
+ if (screen->doWorkspaceWarping())
+ doWorkspaceWarping(x_root, y_root, dx);
+
frame.changing.setPos(dx, dy);
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
}
-bool BlackboxWindow::doWorkspaceWarping(int x_root, int y_root,
- int dx, int dy) {
+void BlackboxWindow::doWorkspaceWarping(int x_root, int y_root, int &dx) {
// workspace warping
bool warp = False;
unsigned int dest = screen->getCurrentWorkspaceID();
else dest = 0;
}
if (! warp)
- return false;
+ return;
- endMove();
bool focus = flags.focused; // had focus while moving?
- if (! flags.stuck)
- screen->reassociateWindow(this, dest, False);
- screen->changeWorkspaceID(dest);
- if (focus)
- setInputFocus();
- /*
- We grab the X server here because we are moving the window and then the
- mouse cursor. When one moves, it could end up putting the mouse cursor
- over another window for a moment. This can cause the warp to iniate a
- move on another window.
- */
- XGrabServer(blackbox->getXDisplay());
- int dest_x;
+ int dest_x = x_root;
if (x_root <= 0) {
- dest_x = screen->getRect().right() - 1;
- configure(dx + (screen->getRect().width() - 1), dy,
- frame.rect.width(), frame.rect.height());
+ dest_x += screen->getRect().width() - 1;
+ dx += screen->getRect().width() - 1;
} else {
- dest_x = 0;
- configure(dx - (screen->getRect().width() - 1), dy,
- frame.rect.width(), frame.rect.height());
+ dest_x -= screen->getRect().width() - 1;
+ dx -= screen->getRect().width() - 1;
}
+
+ if (! flags.stuck)
+ screen->reassociateWindow(this, dest, False);
+ screen->changeWorkspaceID(dest);
+
+ if (screen->doOpaqueMove())
+ XGrabServer(blackbox->getXDisplay());
+
+ XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
XWarpPointer(blackbox->getXDisplay(), None,
screen->getRootWindow(), 0, 0, 0, 0,
dest_x, y_root);
- XUngrabServer(blackbox->getXDisplay());
+ XGrabPointer(blackbox->getXDisplay(), frame.window, False,
+ PointerMotionMask | ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync,
+ None, blackbox->getMoveCursor(), CurrentTime);
+
+ if (screen->doOpaqueMove())
+ XUngrabServer(blackbox->getXDisplay());
+
+ if (focus)
+ setInputFocus();
- beginMove(dest_x, y_root);
- return true;
}
void BlackboxWindow::beginResize(int x_root, int y_root, Corner dir) {
+ if (! (functions & Func_Resize)) return;
+
assert(! (flags.resizing || flags.moving));
/*
- Only one window can be moved/resized at a time. If another window is already
- being moved or resized, then stop it before whating to work with this one.
+ Only one window can be moved/resized at a time. If another window is
+ already being moved or resized, then stop it before whating to work with
+ this one.
*/
BlackboxWindow *changing = blackbox->getChangingWindow();
if (changing && changing != this) {
unsigned int gw, gh;
Corner anchor;
+ int dx, dy; // the amount of change in the size of the window
switch (resize_dir) {
case BottomLeft:
anchor = TopRight;
- frame.changing.setSize(frame.rect.width() - (x_root - frame.grab_x),
- frame.rect.height() + (y_root - frame.grab_y));
+ dx = - (x_root - frame.grab_x);
+ dy = + (y_root - frame.grab_y);
break;
case BottomRight:
anchor = TopLeft;
- frame.changing.setSize(frame.rect.width() + (x_root - frame.grab_x),
- frame.rect.height() + (y_root - frame.grab_y));
+ dx = + (x_root - frame.grab_x);
+ dy = + (y_root - frame.grab_y);
break;
case TopLeft:
anchor = BottomRight;
- frame.changing.setSize(frame.rect.width() - (x_root - frame.grab_x),
- frame.rect.height() - (y_root - frame.grab_y));
+ dx = - (x_root - frame.grab_x);
+ dy = - (y_root - frame.grab_y);
break;
case TopRight:
anchor = BottomLeft;
- frame.changing.setSize(frame.rect.width() + (x_root - frame.grab_x),
- frame.rect.height() - (y_root - frame.grab_y));
+ dx = + (x_root - frame.grab_x);
+ dy = - (y_root - frame.grab_y);
break;
default:
assert(false); // unhandled Corner
return; // unreachable, for the compiler
}
-
+
+ // make sure the user cant resize the window smaller than 0, which makes it
+ // wrap around and become huge
+ if (dx < -(signed)client.rect.width()) dx = -(signed)client.rect.width();
+ if (dy < -(signed)client.rect.height()) dy = -(signed)client.rect.height();
+
+ frame.changing.setSize(frame.rect.width() + dx, frame.rect.height() + dy);
+
constrain(anchor, &gw, &gh);
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
}
}
- if ((! leave || inferior) && ! isFocused()) {
- bool success = setInputFocus();
- if (success) // if focus succeeded install the colormap
- installColormap(True); // XXX: shouldnt we honour no install?
- }
+ if (! leave || inferior) {
+ if (! isFocused()) {
+ bool success = setInputFocus();
+ if (success) // if focus succeeded install the colormap
+ installColormap(True); // XXX: shouldnt we honour no install?
+ }
- if (screen->doAutoRaise())
- timer->start();
+ if (screen->doAutoRaise())
+ timer->start();
+ }
}
#ifdef SHAPE
-void BlackboxWindow::shapeEvent(XShapeEvent *) {
- if (blackbox->hasShapeExtensions() && flags.shaped) {
- configureShape();
+void BlackboxWindow::shapeEvent(XShapeEvent *e) {
+ if (blackbox->hasShapeExtensions()) {
+ if (! e->shaped && flags.shaped) {
+ clearShape();
+ flags.shaped = False;
+ } else if (e->shaped) {
+ configureShape();
+ flags.shaped = True;
+ }
}
}
#endif // SHAPE
base_height = (client.base_height) ? client.base_height :
client.min_height;
- // constrain
- if (dw < client.min_width) dw = client.min_width;
- if (dh < client.min_height) dh = client.min_height;
- if (dw > client.max_width) dw = client.max_width;
- if (dh > client.max_height) dh = client.max_height;
+ // constrain, but only if the min/max are being used. if they aren't, then
+ // this resize is going to be from a ConfigureRequest because the window
+ // isn't allowed to be resized by the user. And in that case, we don't want
+ // to limit what the app can do
+ if (client.max_width > client.min_width ||
+ client.max_height > client.min_height) {
+ if (dw < client.min_width) dw = client.min_width;
+ if (dh < client.min_height) dh = client.min_height;
+ if (dw > client.max_width) dw = client.max_width;
+ if (dh > client.max_height) dh = client.max_height;
+ }
assert(dw >= base_width && dh >= base_height);