using std::string;
using std::abs;
-// change this to change what modifier keys openbox uses for mouse bindings
-// for example: Mod1Mask | ControlMask
-// or: ControlMask| ShiftMask
-const unsigned int ModMask = Mod1Mask;
-
/*
* Initializes the class with default values/the window's set initial values.
*/
blackbox_attrib.workspace = window_number = BSENTINEL;
- blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack
- = blackbox_attrib.decoration = 0l;
+ blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack = 0l;
+ blackbox_attrib.decoration = DecorNormal;
blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0;
blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0;
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 =
frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None;
frame.pbutton = frame.ugrip = frame.fgrip = None;
- decorations = Decor_Titlebar | Decor_Border | Decor_Handle |
- Decor_Iconify | Decor_Maximize;
functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
+ mwm_decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
+ Decor_Iconify | Decor_Maximize;
client.normal_hint_flags = 0;
client.window_group = None;
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.
*/
// get size, aspect, minimum/maximum size and other hints set by the
// client
- if (! getBlackboxHints()) {
- getMWMHints();
+ if (! getBlackboxHints())
getNetWMHints();
- }
getWMProtocols();
getWMHints();
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
// determine the window's type, so we can decide its decorations and
// functionality, or if we should not manage it at all
- getWindowType();
-
- // adjust the window decorations/behavior based on the window type
-
- switch (window_type) {
- case Type_Desktop:
- case Type_Dock:
- case Type_Menu:
- case Type_Toolbar:
- case Type_Utility:
- case Type_Splash:
- // none of these windows are decorated or manipulated by the window manager
- decorations = 0;
- functions = 0;
- blackbox_attrib.workspace = 0; // we do need to belong to a workspace
- flags.stuck = True; // we show up on all workspaces
- break;
+ if (getWindowType()) {
+ // adjust the window decorations/behavior based on the window type
+ switch (window_type) {
+ case Type_Desktop:
+ case Type_Dock:
+ case Type_Menu:
+ blackbox_attrib.workspace = 0; // we do need to belong to a workspace
+ flags.stuck = True; // we show up on all workspaces
+ case Type_Splash:
+ // none of these windows are manipulated by the window manager
+ functions = 0;
+ break;
- case Type_Dialog:
- // dialogs cannot be maximized, and don't display a handle
- decorations &= ~(Decor_Maximize | Decor_Handle);
- functions &= ~Func_Maximize;
- break;
+ case Type_Toolbar:
+ case Type_Utility:
+ // these windows get less functionality
+ functions &= ~(Func_Maximize | Func_Resize | Func_Iconify);
+ break;
- case Type_Normal:
- // normal windows retain all of the possible decorations and functionality
- break;
+ case Type_Dialog:
+ // dialogs cannot be maximized
+ functions &= ~Func_Maximize;
+ break;
+
+ case Type_Normal:
+ // normal windows retain all of the possible decorations and
+ // functionality
+ break;
+ }
+ } else {
+ getMWMHints();
}
- setAllowedActions();
-
// further adjeust the window's decorations/behavior based on window sizes
if ((client.normal_hint_flags & PMinSize) &&
(client.normal_hint_flags & PMaxSize) &&
client.max_width <= client.min_width &&
client.max_height <= client.min_height) {
- decorations &= ~(Decor_Maximize | Decor_Handle);
functions &= ~(Func_Resize | Func_Maximize);
}
+ setAllowedActions();
+
+ setupDecor();
+
if (decorations & Decor_Titlebar)
createTitlebar();
if (! timer) // window not managed...
return;
+ if (flags.moving)
+ endMove();
+
screen->removeStrut(&client.strut);
screen->updateAvailableArea();
}
+void BlackboxWindow::enableDecor(bool enable) {
+ blackbox_attrib.flags |= AttribDecoration;
+ blackbox_attrib.decoration = enable ? DecorNormal : DecorNone;
+ setupDecor();
+
+ // we can not be shaded if we lack a titlebar
+ if (! (decorations & Decor_Titlebar) && flags.shaded)
+ shade();
+
+ if (flags.visible && frame.window) {
+ XMapSubwindows(blackbox->getXDisplay(), frame.window);
+ XMapWindow(blackbox->getXDisplay(), frame.window);
+ }
+
+ reconfigure();
+ setState(current_state);
+}
+
+
+void BlackboxWindow::setupDecor() {
+ if (blackbox_attrib.decoration != DecorNone) {
+ // start with everything on
+ decorations = Decor_Close |
+ (mwm_decorations & Decor_Titlebar ? Decor_Titlebar : 0) |
+ (mwm_decorations & Decor_Border ? Decor_Border : 0) |
+ (mwm_decorations & Decor_Handle ? Decor_Handle : 0) |
+ (mwm_decorations & Decor_Iconify ? Decor_Iconify : 0) |
+ (mwm_decorations & Decor_Maximize ? Decor_Maximize : 0);
+
+ if (! (functions & Func_Close)) decorations &= ~Decor_Close;
+ if (! (functions & Func_Maximize)) decorations &= ~Decor_Maximize;
+ if (! (functions & Func_Iconify)) decorations &= ~Decor_Iconify;
+ if (! (functions & Func_Resize)) decorations &= ~Decor_Handle;
+
+ switch (window_type) {
+ case Type_Desktop:
+ case Type_Dock:
+ case Type_Menu:
+ case Type_Splash:
+ // none of these windows are decorated by the window manager at all
+ decorations = 0;
+ break;
+
+ case Type_Toolbar:
+ case Type_Utility:
+ decorations &= ~(Decor_Border);
+ break;
+
+ case Type_Dialog:
+ decorations &= ~Decor_Handle;
+ break;
+
+ case Type_Normal:
+ break;
+ }
+ } else {
+ decorations = 0;
+ }
+}
+
/*
* Creates a new top level window, with a given location, size, and border
* width.
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();
- blackbox_attrib.flags |= AttribDecoration;
- blackbox_attrib.decoration = DecorNormal;
- } else {
- blackbox_attrib.flags |= AttribDecoration;
- blackbox_attrib.decoration = DecorNone;
+ 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,
void BlackboxWindow::grabButtons(void) {
+ mod_mask = blackbox->getMouseModMask();
+
if (! screen->isSloppyFocus() || screen->doClickRaise())
// grab button 1 for changing focus/raising
blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
screen->allowScrollLock());
if (functions & Func_Move)
- blackbox->grabButton(Button1, ModMask, frame.window, True,
+ blackbox->grabButton(Button1, mod_mask, frame.window, True,
ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
GrabModeAsync, frame.window, None,
screen->allowScrollLock());
if (functions & Func_Resize)
- blackbox->grabButton(Button3, ModMask, frame.window, True,
+ blackbox->grabButton(Button3, mod_mask, frame.window, True,
ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
GrabModeAsync, frame.window, None,
screen->allowScrollLock());
// alt+middle lowers the window
- blackbox->grabButton(Button2, ModMask, frame.window, True,
+ blackbox->grabButton(Button2, mod_mask, frame.window, True,
ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
- frame.window, None,
- screen->allowScrollLock());
+ frame.window, None, screen->allowScrollLock());
}
void BlackboxWindow::ungrabButtons(void) {
blackbox->ungrabButton(Button1, 0, frame.plate);
- blackbox->ungrabButton(Button1, ModMask, frame.window);
- blackbox->ungrabButton(Button2, ModMask, frame.window);
- blackbox->ungrabButton(Button3, ModMask, frame.window);
+ blackbox->ungrabButton(Button1, mod_mask, frame.window);
+ blackbox->ungrabButton(Button2, mod_mask, frame.window);
+ blackbox->ungrabButton(Button3, mod_mask, frame.window);
}
}
-void BlackboxWindow::getWindowType(void) {
- unsigned long val;
+bool BlackboxWindow::getWindowType(void) {
+ 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;
- }
- /*
- * 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;
+ return False;
+ }
- window_type = Type_Normal;
+ 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))
if (mwm_hint->flags & MwmHintsDecorations) {
if (mwm_hint->decorations & MwmDecorAll) {
- decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
- Decor_Iconify | Decor_Maximize | Decor_Close;
+ mwm_decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
+ Decor_Iconify | Decor_Maximize;
} else {
- decorations = 0;
+ mwm_decorations = 0;
if (mwm_hint->decorations & MwmDecorBorder)
- decorations |= Decor_Border;
+ mwm_decorations |= Decor_Border;
if (mwm_hint->decorations & MwmDecorHandle)
- decorations |= Decor_Handle;
+ mwm_decorations |= Decor_Handle;
if (mwm_hint->decorations & MwmDecorTitle)
- decorations |= Decor_Titlebar;
+ mwm_decorations |= Decor_Titlebar;
if (mwm_hint->decorations & MwmDecorIconify)
- decorations |= Decor_Iconify;
+ mwm_decorations |= Decor_Iconify;
if (mwm_hint->decorations & MwmDecorMaximize)
- decorations |= Decor_Maximize;
+ mwm_decorations |= Decor_Maximize;
}
}
if (blackbox_hint->flags & AttribDecoration) {
switch (blackbox_hint->decoration) {
case DecorNone:
- decorations = 0;
+ blackbox_attrib.decoration = DecorNone;
break;
case DecorTiny:
- decorations |= Decor_Titlebar | Decor_Iconify;
- decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
- functions &= ~(Func_Resize | Func_Maximize);
-
- break;
-
case DecorTool:
- decorations |= Decor_Titlebar;
- decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
- functions &= ~(Func_Resize | Func_Maximize | Func_Iconify);
-
- break;
-
case DecorNormal:
default:
- decorations |= Decor_Titlebar | Decor_Border | Decor_Handle |
- Decor_Iconify | Decor_Maximize;
+ // blackbox_attrib.decoration defaults to DecorNormal
break;
}
-
- reconfigure();
}
delete [] blackbox_hint;
}
// we have no transient_for until we find a new one
- client.transient_for = 0;
+ client.transient_for = (BlackboxWindow *) 0;
Window trans_for;
if (! XGetTransientForHint(blackbox->getXDisplay(), client.window,
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 (net->flags & AttribDecoration) {
switch (net->decoration) {
case DecorNone:
- decorations = 0;
-
+ enableDecor(False);
break;
+ /* since tools only let you toggle this anyways, we'll just make that all
+ it supports for now.
+ */
default:
case DecorNormal:
- decorations |= Decor_Titlebar | Decor_Handle | Decor_Border |
- Decor_Iconify | Decor_Maximize;
-
- break;
-
case DecorTiny:
- decorations |= Decor_Titlebar | Decor_Iconify;
- decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
-
- break;
-
case DecorTool:
- decorations |= Decor_Titlebar;
- decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
-
+ enableDecor(True);
break;
}
-
- // sanity check the new decor
- if (! (functions & Func_Resize) || isTransient())
- decorations &= ~(Decor_Maximize | Decor_Handle);
- if (! (functions & Func_Maximize))
- decorations &= ~Decor_Maximize;
-
- if (decorations & Decor_Titlebar) {
- if (functions & Func_Close) // close button is controlled by function
- decorations |= Decor_Close; // not decor type
- } else {
- if (flags.shaded) // we can not be shaded if we lack a titlebar
- shade();
- }
-
- if (flags.visible && frame.window) {
- XMapSubwindows(blackbox->getXDisplay(), frame.window);
- XMapWindow(blackbox->getXDisplay(), frame.window);
- }
-
- reconfigure();
- setState(current_state);
}
// with the state set it will then be the map event's job to read the
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;
client.window);
#endif // DEBUG
+ /*
+ Even though the window wants to be shown, if it is not on the current
+ workspace, then it isn't going to be shown right now.
+ */
+ if (blackbox_attrib.workspace != screen->getCurrentWorkspaceID() &&
+ blackbox_attrib.workspace < screen->getWorkspaceCount())
+ if (current_state == NormalState) current_state = WithdrawnState;
+
switch (current_state) {
case IconicState:
iconify();
if (isNormal()) {
if (! blackbox->isStartup()) {
XSync(blackbox->getXDisplay(), False); // make sure the frame is mapped
- if (screen->doFocusNew()|| (isTransient() && getTransientFor() &&
- getTransientFor()->isFocused())) {
+ if (screen->doFocusNew() || (isTransient() && getTransientFor() &&
+ getTransientFor()->isFocused())) {
setInputFocus();
}
if (screen->getPlacementPolicy() == BScreen::ClickMousePlacement) {
void BlackboxWindow::propertyNotifyEvent(const XPropertyEvent *pe) {
- if (pe->state == PropertyDelete)
+ if (pe->state == PropertyDelete || ! validateClient())
return;
-#ifdef DEBUG
+#if 0
fprintf(stderr, "BlackboxWindow::propertyNotifyEvent(): for 0x%lx\n",
client.window);
#endif
break;
case XA_WM_TRANSIENT_FOR: {
+ bool s = flags.stuck;
+
// determine if this is a transient window
getTransientInfo();
+ if (flags.stuck != s) stick();
+
// adjust the window decorations based on transience
if (isTransient()) {
- decorations &= ~(Decor_Maximize | Decor_Handle);
functions &= ~Func_Maximize;
setAllowedActions();
+ setupDecor();
}
reconfigure();
ungrabButtons();
if (client.max_width <= client.min_width &&
client.max_height <= client.min_height) {
- decorations &= ~(Decor_Maximize | Decor_Handle);
functions &= ~(Func_Resize | Func_Maximize);
} else {
- if (! isTransient()) {
- decorations |= Decor_Maximize | Decor_Handle;
+ if (! isTransient())
functions |= Func_Maximize;
- }
functions |= Func_Resize;
}
grabButtons();
setAllowedActions();
+ setupDecor();
}
Rect old_rect = frame.rect;
void BlackboxWindow::exposeEvent(const XExposeEvent *ee) {
-#ifdef DEBUG
+#if 0
fprintf(stderr, "BlackboxWindow::exposeEvent() for 0x%lx\n", client.window);
#endif
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);
- configure(req.x(), req.y(), req.width(), req.height());
+ /*
+ 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(frame.changing.x(), frame.changing.y(),
+ frame.changing.width(), frame.changing.height());
}
if (cr->value_mask & CWStackMode && !isDesktop()) {
if (frame.maximize_button == be->window && be->button <= 3) {
redrawMaximizeButton(True);
- } else if (be->button == 1 || (be->button == 3 && be->state == ModMask)) {
+ } else if (be->button == 1 || (be->button == 3 && be->state == mod_mask)) {
if (! flags.focused)
setInputFocus();
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)))
} else if (flags.resizing) {
endResize();
} else if (re->window == frame.window) {
- if (re->button == 2 && re->state == ModMask)
+ if (re->button == 2 && re->state == mod_mask)
XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
}
}
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?
+
+ int dest_x = x_root;
+ if (x_root <= 0) {
+ dest_x += screen->getRect().width() - 1;
+ dx += screen->getRect().width() - 1;
+ } else {
+ dest_x -= screen->getRect().width() - 1;
+ dx -= screen->getRect().width() - 1;
+ }
+
if (! flags.stuck)
screen->reassociateWindow(this, dest, False);
screen->changeWorkspaceID(dest);
- if (focus)
- setInputFocus();
- /*
- If the XWarpPointer is done after the configure, we can end up
- grabbing another window, so made sure you do it first.
- */
- int dest_x;
- if (x_root <= 0) {
- dest_x = screen->getRect().right() - 1;
- XWarpPointer(blackbox->getXDisplay(), None,
- screen->getRootWindow(), 0, 0, 0, 0,
- dest_x, y_root);
+ if (screen->doOpaqueMove())
+ XGrabServer(blackbox->getXDisplay());
- configure(dx + (screen->getRect().width() - 1), dy,
- frame.rect.width(), frame.rect.height());
- } else {
- dest_x = 0;
- XWarpPointer(blackbox->getXDisplay(), None,
- screen->getRootWindow(), 0, 0, 0, 0,
- dest_x, y_root);
+ XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
+ XWarpPointer(blackbox->getXDisplay(), None,
+ screen->getRootWindow(), 0, 0, 0, 0,
+ dest_x, y_root);
+ XGrabPointer(blackbox->getXDisplay(), frame.window, False,
+ PointerMotionMask | ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync,
+ None, blackbox->getMoveCursor(), CurrentTime);
- configure(dx - (screen->getRect().width() - 1), dy,
- frame.rect.width(), frame.rect.height());
- }
+ if (screen->doOpaqueMove())
+ XUngrabServer(blackbox->getXDisplay());
+
+ if (focus)
+ setInputFocus();
- beginMove(dest_x, y_root);
- return true;
}
const BlackboxWindowList& stack_list = w->getStackingList();
BlackboxWindowList::const_iterator st_it, st_end = stack_list.end();
for (st_it = stack_list.begin(); st_it != st_end; ++st_it)
- rectlist.push_back( (*st_it)->frameRect() );
+ if (*st_it != this) // don't snap to ourself
+ rectlist.push_back( (*st_it)->frameRect() );
// add the toolbar and the slit to the rect list.
// (only if they are not hidden)
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(),
void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) {
-#ifdef DEBUG
+#if 0
fprintf(stderr, "BlackboxWindow::motionNotifyEvent() for 0x%lx\n",
client.window);
#endif
} else if (flags.resizing) {
doResize(me->x_root, me->y_root);
} else {
- if (!flags.resizing && me->state & Button1Mask && (functions & Func_Move) &&
+ if ((functions & Func_Move) &&
+ (me->state & Button1Mask) &&
(frame.title == me->window || frame.label == me->window ||
frame.handle == me->window || frame.window == me->window)) {
beginMove(me->x_root, me->y_root);
} else if ((functions & Func_Resize) &&
- (me->state & Button1Mask && (me->window == frame.right_grip ||
- me->window == frame.left_grip)) ||
- (me->state & Button3Mask && me->state & ModMask &&
- me->window == frame.window)) {
+ ((me->state & Button1Mask) && (me->window == frame.right_grip ||
+ me->window == frame.left_grip)) ||
+ ((me->state & Button3Mask) && (me->state & mod_mask) &&
+ (frame.title == me->window || frame.label == me->window ||
+ frame.handle == me->window || frame.window == me->window))) {
unsigned int zones = screen->getResizeZones();
Corner corner;
}
}
- 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
if (flags.shaded && ! flags.iconic)
setState(NormalState);
+ // erase the netwm stuff that we read when a window maps, so that it
+ // doesn't persist between mappings.
+ // (these are the ones read in getNetWMFlags().)
+ xatom->eraseValue(client.window, XAtom::net_wm_desktop);
+ xatom->eraseValue(client.window, XAtom::net_wm_state);
+
restoreGravity(client.rect);
XUnmapWindow(blackbox->getXDisplay(), frame.window);
if (net->flags & AttribDecoration) {
switch (net->decoration) {
case DecorNone:
- decorations = 0;
-
+ enableDecor(False);
break;
default:
case DecorNormal:
- decorations |= Decor_Titlebar | Decor_Border | Decor_Iconify;
-
- decorations = ((functions & Func_Resize) && !isTransient() ?
- decorations | Decor_Handle :
- decorations &= ~Decor_Handle);
- decorations = (functions & Func_Maximize ?
- decorations | Decor_Maximize :
- decorations &= ~Decor_Maximize);
-
- break;
-
case DecorTiny:
- decorations |= Decor_Titlebar | Decor_Iconify;
- decorations &= ~(Decor_Border | Decor_Handle);
-
- decorations = (functions & Func_Maximize ?
- decorations | Decor_Maximize :
- decorations &= ~Decor_Maximize);
-
- break;
-
case DecorTool:
- decorations |= Decor_Titlebar;
- decorations &= ~(Decor_Iconify | Decor_Border);
-
- decorations = ((functions & Func_Resize) && !isTransient() ?
- decorations | Decor_Handle :
- decorations &= ~Decor_Handle);
- decorations = (functions & Func_Maximize ?
- decorations | Decor_Maximize :
- decorations &= ~Decor_Maximize);
-
+ enableDecor(True);
break;
}
-
- // we can not be shaded if we lack a titlebar
- if (flags.shaded && ! (decorations & Decor_Titlebar))
- shade();
-
- if (flags.visible && frame.window) {
- XMapSubwindows(blackbox->getXDisplay(), frame.window);
- XMapWindow(blackbox->getXDisplay(), frame.window);
- }
-
- reconfigure();
- setState(current_state);
}
}
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);