return;
case Type_Dock:
- // docks (such as kicker) cannot be moved, and appear on all workspaces
+ case Type_Menu:
+ // docks (such as kicker) and menus (as used by kde for the 'desktop menu'
+ // which mimics apple, cannot be moved, and appear on all workspaces
+ // also, these have no decorations
functions &= ~(Func_Move);
+ decorations &= ~Decor_Titlebar;
flags.stuck = True;
case Type_Toolbar:
- case Type_Menu:
case Type_Utility:
// these windows have minimal decorations, only a titlebar, and cannot
// be resized or iconified
client.normal_hint_flags & (PPosition|USPosition)) {
applyGravity(frame.rect);
- if (blackbox->isStartup() ||
- client.rect.intersects(screen->availableArea()))
+ if (blackbox->isStartup() || client.rect.intersects(screen->getRect()))
place_window = False;
}
}
#endif // SHAPE
- grabButtons();
-
windowmenu = new Windowmenu(this);
if (blackbox_attrib.workspace >= screen->getWorkspaceCount())
positionWindows();
decorate();
+ grabButtons();
XMapSubwindows(blackbox->getXDisplay(), frame.window);
ButtonMotionMask | EnterWindowMask;
return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(),
- -1, -1, 1, 1, frame.border_w, screen->getDepth(),
+ 0, 0, 1, 1, frame.border_w, screen->getDepth(),
InputOutput, screen->getVisual(), create_mask,
&attrib_create);
}
XSelectInput(blackbox->getXDisplay(), frame.plate, SubstructureRedirectMask);
XGrabServer(blackbox->getXDisplay());
- XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
- XReparentWindow(blackbox->getXDisplay(), client.window, frame.plate, 0, 0);
+
+ unsigned long event_mask = PropertyChangeMask | FocusChangeMask |
+ StructureNotifyMask;
XSelectInput(blackbox->getXDisplay(), client.window,
- PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
+ event_mask & ~StructureNotifyMask);
+ XReparentWindow(blackbox->getXDisplay(), client.window, frame.plate, 0, 0);
+ XSelectInput(blackbox->getXDisplay(), client.window, event_mask);
+
XUngrabServer(blackbox->getXDisplay());
XRaiseWindow(blackbox->getXDisplay(), frame.plate);
void BlackboxWindow::reconfigure(void) {
+ restoreGravity(client.rect);
upsize();
-
+ applyGravity(frame.rect);
positionWindows();
decorate();
-
redrawWindowFrame();
+ ungrabButtons();
+ grabButtons();
+
if (windowmenu) {
windowmenu->move(windowmenu->getX(), frame.rect.y() + frame.title_h);
windowmenu->reconfigure();
if (functions & Func_Resize)
blackbox->grabButton(Button3, Mod1Mask, frame.window, True,
ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
- GrabModeAsync, frame.window,
- blackbox->getLowerRightAngleCursor());
+ GrabModeAsync, frame.window, None);
+ // alt+middle lowers the window
+ blackbox->grabButton(Button2, Mod1Mask, frame.window, True,
+ ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
+ frame.window, None);
}
blackbox->ungrabButton(Button1, 0, frame.plate);
blackbox->ungrabButton(Button1, Mod1Mask, frame.window);
+ blackbox->ungrabButton(Button2, Mod1Mask, frame.window);
blackbox->ungrabButton(Button3, Mod1Mask, frame.window);
}
XMoveResizeWindow(blackbox->getXDisplay(), client.window,
0, 0, client.rect.width(), client.rect.height());
// ensure client.rect contains the real location
- client.rect.setCoords(frame.rect.left() + frame.margin.left,
- frame.rect.top() + frame.margin.top,
- frame.rect.right() - frame.margin.right,
- frame.rect.bottom() - frame.margin.bottom);
+ client.rect.setPos(frame.rect.left() + frame.margin.left,
+ frame.rect.top() + frame.margin.top);
if (decorations & Decor_Titlebar) {
if (frame.title == None) createTitlebar();
} else if (frame.handle) {
destroyHandle();
}
+ XSync(blackbox->getXDisplay(), False);
}
// add window to the appropriate group
BWindowGroup *group = blackbox->searchGroup(client.window_group);
- if (! group) // no group found, create it!
- group = new BWindowGroup(blackbox, client.window_group);
- group->addWindow(this);
+ if (! group) { // no group found, create it!
+ new BWindowGroup(blackbox, client.window_group);
+ group = blackbox->searchGroup(client.window_group);
+ }
+ if (group)
+ group->addWindow(this);
}
client.wm_hint_flags = wmhint->flags;
client.min_width = client.min_height =
client.width_inc = client.height_inc = 1;
client.base_width = client.base_height = 0;
+ client.win_gravity = NorthWestGravity;
+#if 0
+ client.min_aspect_x = client.min_aspect_y =
+ client.max_aspect_x = client.max_aspect_y = 1;
+#endif
/*
use the full screen, not the strut modified size. otherwise when the
*/
const Rect& screen_area = screen->getRect();
client.max_width = screen_area.width();
-
client.max_height = screen_area.height();
- client.min_aspect_x = client.min_aspect_y =
- client.max_aspect_x = client.max_aspect_y = 1;
- client.win_gravity = NorthWestGravity;
if (! XGetWMNormalHints(blackbox->getXDisplay(), client.window,
&sizehint, &icccm_mask))
client.normal_hint_flags = sizehint.flags;
if (sizehint.flags & PMinSize) {
- client.min_width = sizehint.min_width;
- client.min_height = sizehint.min_height;
+ if (sizehint.min_width >= 0)
+ client.min_width = sizehint.min_width;
+ if (sizehint.min_height >= 0)
+ client.min_height = sizehint.min_height;
}
if (sizehint.flags & PMaxSize) {
- client.max_width = sizehint.max_width;
- client.max_height = sizehint.max_height;
+ if (sizehint.max_width > static_cast<signed>(client.min_width))
+ client.max_width = sizehint.max_width;
+ else
+ client.max_width = client.min_width;
+
+ if (sizehint.max_height > static_cast<signed>(client.min_height))
+ client.max_height = sizehint.max_height;
+ else
+ client.max_height = client.min_height;
}
if (sizehint.flags & PResizeInc) {
client.height_inc = sizehint.height_inc;
}
+#if 0 // we do not support this at the moment
if (sizehint.flags & PAspect) {
client.min_aspect_x = sizehint.min_aspect.x;
client.min_aspect_y = sizehint.min_aspect.y;
client.max_aspect_x = sizehint.max_aspect.x;
client.max_aspect_y = sizehint.max_aspect.y;
}
+#endif
if (sizehint.flags & PBaseSize) {
client.base_width = sizehint.base_width;
*/
void BlackboxWindow::configure(int dx, int dy,
unsigned int dw, unsigned int dh) {
- bool send_event = (frame.rect.x() != dx || frame.rect.y() != dy);
+ bool send_event = ((frame.rect.x() != dx || frame.rect.y() != dy) &&
+ ! flags.moving);
if (dw != frame.rect.width() || dh != frame.rect.height()) {
frame.rect.setRect(dx, dy, dw, dh);
XMoveWindow(blackbox->getXDisplay(), frame.window,
frame.rect.x(), frame.rect.y());
+ /*
+ we may have been called just after an opaque window move, so even though
+ the old coords match the new ones no ConfigureNotify has been sent yet.
+ There are likely other times when this will be relevant as well.
+ */
+ if (! flags.moving) send_event = True;
}
- if (send_event && ! flags.moving) {
+ if (send_event) {
// if moving, the update and event will occur when the move finishes
client.rect.setPos(frame.rect.left() + frame.margin.left,
frame.rect.top() + frame.margin.top);
XSendEvent(blackbox->getXDisplay(), client.window, False,
StructureNotifyMask, &event);
screen->updateNetizenConfigNotify(&event);
+ XFlush(blackbox->getXDisplay());
}
}
ce.xclient.data.l[4] = 0l;
XSendEvent(blackbox->getXDisplay(), client.window, False,
NoEventMask, &ce);
+ XFlush(blackbox->getXDisplay());
}
return ret;
* split second, leaving us with a ghost window... so, we need to do this
* while the X server is grabbed
*/
+ unsigned long event_mask = PropertyChangeMask | FocusChangeMask |
+ StructureNotifyMask;
XGrabServer(blackbox->getXDisplay());
- XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
- XUnmapWindow(blackbox->getXDisplay(), client.window);
XSelectInput(blackbox->getXDisplay(), client.window,
- PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
+ event_mask & ~StructureNotifyMask);
+ XUnmapWindow(blackbox->getXDisplay(), client.window);
+ XSelectInput(blackbox->getXDisplay(), client.window, event_mask);
XUngrabServer(blackbox->getXDisplay());
XUnmapWindow(blackbox->getXDisplay(), frame.window);
if (! (*it)->flags.iconic) (*it)->iconify();
}
}
+ screen->updateStackingList();
}
ce.xclient.data.l[3] = 0l;
ce.xclient.data.l[4] = 0l;
XSendEvent(blackbox->getXDisplay(), client.window, False, NoEventMask, &ce);
+ XFlush(blackbox->getXDisplay());
}
XGrabServer(blackbox->getXDisplay());
- XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
- XUnmapWindow(blackbox->getXDisplay(), client.window);
+ unsigned long event_mask = PropertyChangeMask | FocusChangeMask |
+ StructureNotifyMask;
XSelectInput(blackbox->getXDisplay(), client.window,
- PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
+ event_mask & ~StructureNotifyMask);
+ XUnmapWindow(blackbox->getXDisplay(), client.window);
+ XSelectInput(blackbox->getXDisplay(), client.window, event_mask);
XUngrabServer(blackbox->getXDisplay());
void BlackboxWindow::setWorkspace(unsigned int n) {
blackbox_attrib.flags |= AttribWorkspace;
blackbox_attrib.workspace = n;
+ if (n == BSENTINEL) { // iconified window
+ /*
+ we set the workspace to 'all workspaces' so that taskbars will show the
+ window. otherwise, it made uniconifying a window imposible without the
+ blackbox workspace menu
+ */
+ n = 0xffffffff;
+ }
xatom->setValue(client.window, XAtom::net_wm_desktop, XAtom::cardinal, n);
}
case NorthEastGravity:
case SouthEastGravity:
case EastGravity:
- r.setX(client.rect.x() - frame.margin.left - frame.margin.right);
+ r.setX(client.rect.x() - frame.margin.left - frame.margin.right + 2);
break;
case ForgetGravity:
case SouthWestGravity:
case SouthEastGravity:
case SouthGravity:
- r.setY(client.rect.y() - frame.margin.top - frame.margin.bottom);
+ r.setY(client.rect.y() - frame.margin.top - frame.margin.bottom + 2);
break;
case ForgetGravity:
case NorthEastGravity:
case SouthEastGravity:
case EastGravity:
- r.setX(frame.rect.x() + frame.margin.left + frame.margin.right);
+ r.setX(frame.rect.x() + frame.margin.left + frame.margin.right - 2);
break;
case ForgetGravity:
case SouthWestGravity:
case SouthEastGravity:
case SouthGravity:
- r.setY(frame.rect.y() + frame.margin.top + frame.margin.bottom);
+ r.setY(frame.rect.y() + frame.margin.top + frame.margin.bottom - 2);
break;
case ForgetGravity:
decorations &= ~(Decor_Maximize | Decor_Handle);
functions &= ~(Func_Resize | Func_Maximize);
} else {
- decorations |= Decor_Maximize | Decor_Handle;
- functions |= Func_Resize | Func_Maximize;
+ if (! isTransient()) {
+ decorations |= Decor_Maximize | Decor_Handle;
+ functions |= Func_Maximize;
+ }
+ functions |= Func_Resize;
}
grabButtons();
setAllowedActions();
client.window);
#endif
- if (frame.maximize_button == be->window) {
+ if (frame.maximize_button == be->window && be->button <= 3) {
redrawMaximizeButton(True);
} else if (be->button == 1 || (be->button == 3 && be->state == Mod1Mask)) {
if (! flags.focused)
if (frame.title == be->window || frame.label == be->window) {
if (((be->time - lastButtonPressTime) <=
blackbox->getDoubleClickInterval()) ||
- (be->state & ControlMask)) {
+ (be->state == ControlMask)) {
lastButtonPressTime = 0;
shade();
} else {
// mouse wheel up
} else if (be->button == 4) {
if ((be->window == frame.label ||
- be->window == frame.title) &&
+ be->window == frame.title ||
+ be->window == frame.maximize_button ||
+ be->window == frame.iconify_button ||
+ be->window == frame.close_button) &&
! flags.shaded)
shade();
// mouse wheel down
} else if (be->button == 5) {
if ((be->window == frame.label ||
- be->window == frame.title) &&
+ be->window == frame.title ||
+ be->window == frame.maximize_button ||
+ be->window == frame.iconify_button ||
+ be->window == frame.close_button) &&
flags.shaded)
shade();
}
client.window);
#endif
- if (re->window == frame.maximize_button) {
+ if (re->window == frame.maximize_button &&
+ re->button >= 1 && re->button <= 3) {
if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
(re->y >= 0 && re->y <= static_cast<signed>(frame.button_w))) {
maximize(re->button);
} else {
redrawMaximizeButton(flags.maximized);
}
- } else if (re->window == frame.iconify_button) {
+ } else if (re->window == frame.iconify_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))) {
iconify();
} else {
redrawIconifyButton(False);
}
- } else if (re->window == frame.close_button) {
+ } 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)))
close();
endMove();
} else if (flags.resizing) {
endResize();
+ } else if (re->window == frame.window) {
+ if (re->button == 2 && re->state == Mod1Mask)
+ XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
}
}
default:
assert(false); // unhandled Corner
+ return; // unreachable, for the compiler
}
XGrabServer(blackbox->getXDisplay());
Corner anchor;
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));
- break;
- case BottomRight:
- anchor = TopLeft;
- frame.changing.setSize(frame.rect.width() + (x_root - frame.grab_x),
- frame.rect.height() + (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));
- break;
- case TopRight:
- anchor = BottomLeft;
- frame.changing.setSize(frame.rect.width() + (x_root - frame.grab_x),
- frame.rect.height() - (y_root - frame.grab_y));
- break;
+ case BottomLeft:
+ anchor = TopRight;
+ frame.changing.setSize(frame.rect.width() - (x_root - frame.grab_x),
+ frame.rect.height() + (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));
+ break;
+ case TopLeft:
+ anchor = BottomRight;
+ frame.changing.setSize(frame.rect.width() - (x_root - frame.grab_x),
+ frame.rect.height() - (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));
+ break;
- default:
- assert(false); // unhandled Corner
+ default:
+ assert(false); // unhandled Corner
+ return; // unreachable, for the compiler
}
constrain(anchor, &gw, &gh);
} else if (flags.resizing) {
doResize(me->x_root, me->y_root);
} else {
- if (! flags.resizing && (me->state & Button1Mask) &&
- (functions & Func_Move) &&
+ if (!flags.resizing && me->state & Button1Mask && (functions & Func_Move) &&
(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 & (Mod1Mask | Button3Mask) &&
- me->window == frame.window))) {
- beginResize(me->x_root, me->y_root,
- (me->window == frame.left_grip) ? BottomLeft : BottomRight);
+ (me->state & Button1Mask && (me->window == frame.right_grip ||
+ me->window == frame.left_grip)) ||
+ (me->state & Button3Mask && me->state & Mod1Mask &&
+ me->window == frame.window)) {
+ unsigned int zones = screen->getResizeZones();
+ Corner corner;
+
+ if (me->window == frame.left_grip) {
+ corner = BottomLeft;
+ } else if (me->window == frame.right_grip || zones == 1) {
+ corner = BottomRight;
+ } else {
+ bool top;
+ bool left = (me->x_root - frame.rect.x() <=
+ static_cast<signed>(frame.rect.width() / 2));
+ if (zones == 2)
+ top = False;
+ else // (zones == 4)
+ top = (me->y_root - frame.rect.y() <=
+ static_cast<signed>(frame.rect.height() / 2));
+ corner = (top ? (left ? TopLeft : TopRight) :
+ (left ? BottomLeft : BottomRight));
+ }
+
+ beginResize(me->x_root, me->y_root, corner);
}
}
}
return;
}
- /*
- watch for destroy notify on the group window (in addition to
- any other events we are looking for)
-
- since some managed windows can also be window group controllers,
- we need to make sure that we don't clobber the event mask for the
- managed window
- */
XSelectInput(blackbox->getXDisplay(), group,
- wattrib.your_event_mask | StructureNotifyMask);
+ PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
blackbox->saveGroupSearch(group, this);
}