X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2FWindow.cc;h=e179824365885361661ea9dee601236a28c5b21b;hb=08d793bb796f608774d6fdefd1950df54477e2c6;hp=09d4ec60e8e78462fea953af915582b537fa9b7b;hpb=18064df19f670589b9387c194b55345c717473db;p=chaz%2Fopenbox diff --git a/src/Window.cc b/src/Window.cc index 09d4ec60..e1798243 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -44,6 +44,7 @@ extern "C" { #include "i18n.hh" #include "blackbox.hh" +#include "Font.hh" #include "GCCache.hh" #include "Iconmenu.hh" #include "Image.hh" @@ -54,8 +55,6 @@ extern "C" { #include "Windowmenu.hh" #include "Workspace.hh" #include "Slit.hh" -#include "XAtom.hh" -#include "Input.hh" using std::string; @@ -80,7 +79,6 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { client.window = w; screen = s; xatom = blackbox->getXAtom(); - input = blackbox->getInput(); if (! validateClient()) { delete this; @@ -254,8 +252,7 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { bool place_window = True; if (blackbox->isStartup() || isTransient() || client.normal_hint_flags & (PPosition|USPosition)) { - setGravityOffsets(); - + applyGravity(frame.rect); if (blackbox->isStartup() || client.rect.intersects(screen->availableArea())) @@ -274,7 +271,25 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { } #endif // SHAPE - grabButtons(); + if ((! screen->isSloppyFocus()) || screen->doClickRaise()) { + // grab button 1 for changing focus/raising + blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask, + GrabModeSync, GrabModeSync, None, None); + } + + if (functions & Func_Move) + blackbox->grabButton(Button1, Mod1Mask, frame.window, True, + ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, + GrabModeAsync, frame.window, + blackbox->getMoveCursor()); + blackbox->grabButton(Button2, Mod1Mask, frame.window, True, + ButtonReleaseMask, GrabModeAsync, GrabModeAsync, + None, None); + if (functions & Func_Resize) + blackbox->grabButton(Button3, Mod1Mask, frame.window, True, + ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, + GrabModeAsync, None, + blackbox->getLowerRightAngleCursor()); positionWindows(); decorate(); @@ -315,7 +330,7 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { if (flags.shaded) { flags.shaded = False; shade(); - + /* Because the iconic'ness of shaded windows is lost, we need to set the state to NormalState so that shaded windows on other workspaces will not @@ -345,7 +360,7 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { window was iconified previously. */ - setFocusFlag(False); + redrawWindowFrame(); } @@ -829,8 +844,7 @@ void BlackboxWindow::reconfigure(void) { positionWindows(); decorate(); - XClearWindow(blackbox->getXDisplay(), frame.window); - setFocusFlag(flags.focused); + redrawWindowFrame(); configure(frame.rect.x(), frame.rect.y(), frame.rect.width(), frame.rect.height()); @@ -842,11 +856,23 @@ void BlackboxWindow::reconfigure(void) { } +void BlackboxWindow::updateFocusModel(void) { + if ((! screen->isSloppyFocus()) || screen->doClickRaise()) { + // grab button 1 for changing focus/raising + blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask, + GrabModeSync, GrabModeSync, None, None); + } else { + blackbox->ungrabButton(Button1, 0, frame.plate); + } +} + + void BlackboxWindow::positionWindows(void) { XMoveResizeWindow(blackbox->getXDisplay(), frame.window, frame.rect.x(), frame.rect.y(), frame.inside_w, (flags.shaded) ? frame.title_h : frame.inside_h); - XSetWindowBorderWidth(blackbox->getXDisplay(), frame.window, frame.border_w); + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.window, + frame.border_w); XSetWindowBorderWidth(blackbox->getXDisplay(), frame.plate, frame.mwm_border_w); XMoveResizeWindow(blackbox->getXDisplay(), frame.plate, @@ -1200,9 +1226,12 @@ void BlackboxWindow::getMWMHints(void) { num = PropMwmHintsElements; if (! xatom->getValue(client.window, XAtom::motif_wm_hints, XAtom::motif_wm_hints, num, - (unsigned long **)&mwm_hint) || - num < PropMwmHintsElements) + (unsigned long **)&mwm_hint)) return; + if (num < PropMwmHintsElements) { + delete [] mwm_hint; + return; + } if (mwm_hint->flags & MwmHintsDecorations) { if (mwm_hint->decorations & MwmDecorAll) { @@ -1243,7 +1272,7 @@ void BlackboxWindow::getMWMHints(void) { functions |= Func_Close; } } - delete mwm_hint; + delete [] mwm_hint; } @@ -1261,9 +1290,12 @@ bool BlackboxWindow::getBlackboxHints(void) { num = PropBlackboxHintsElements; if (! xatom->getValue(client.window, XAtom::blackbox_hints, XAtom::blackbox_hints, num, - (unsigned long **)&blackbox_hint) || - num < PropBlackboxHintsElements) + (unsigned long **)&blackbox_hint)) + return False; + if (num < PropBlackboxHintsElements) { + delete [] blackbox_hint; return False; + } if (blackbox_hint->flags & AttribShaded) flags.shaded = (blackbox_hint->attrib & AttribShaded); @@ -1325,7 +1357,7 @@ bool BlackboxWindow::getBlackboxHints(void) { reconfigure(); } - delete blackbox_hint; + delete [] blackbox_hint; return True; } @@ -1405,9 +1437,9 @@ BlackboxWindow *BlackboxWindow::getTransientFor(void) const { 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 = False; - if ((dw != frame.rect.width()) || (dh != frame.rect.height())) { + if (dw != frame.rect.width() || dh != frame.rect.height()) { frame.rect.setRect(dx, dy, dw, dh); frame.inside_w = frame.rect.width() - (frame.border_w * 2); frame.inside_h = frame.rect.height() - (frame.border_w * 2); @@ -1428,15 +1460,14 @@ void BlackboxWindow::configure(int dx, int dy, positionWindows(); decorate(); - setFocusFlag(flags.focused); - redrawAllButtons(); - } else { + redrawWindowFrame(); + } else if (frame.rect.x() != dx || frame.rect.y() != dy) { + send_event = True; + frame.rect.setPos(dx, dy); XMoveWindow(blackbox->getXDisplay(), frame.window, frame.rect.x(), frame.rect.y()); - - if (! flags.moving) send_event = True; } if (send_event && ! flags.moving) { @@ -1457,8 +1488,8 @@ void BlackboxWindow::configure(int dx, int dy, event.xconfigure.above = frame.window; event.xconfigure.override_redirect = False; - XSendEvent(blackbox->getXDisplay(), client.window, True, - NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), client.window, False, + StructureNotifyMask, &event); screen->updateNetizenConfigNotify(&event); } @@ -1511,7 +1542,7 @@ bool BlackboxWindow::setInputFocus(void) { return True; } - if (! client.rect.intersects(screen->getRect())) { + if (! frame.rect.intersects(screen->getRect())) { // client is outside the screen, move it to the center configure((screen->getWidth() - frame.rect.width()) / 2, (screen->getHeight() - frame.rect.height()) / 2, @@ -1625,7 +1656,7 @@ void BlackboxWindow::show(void) { } -void BlackboxWindow::deiconify(bool reassoc, bool doraise) { +void BlackboxWindow::deiconify(bool reassoc, bool raise) { if (flags.iconic || reassoc) screen->reassociateWindow(this, BSENTINEL, False); else if (blackbox_attrib.workspace != screen->getCurrentWorkspace()->getID()) @@ -1641,18 +1672,8 @@ void BlackboxWindow::deiconify(bool reassoc, bool doraise) { } } - if (doraise) - raise(); -} - - -void BlackboxWindow::raise(void) { - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); -} - - -void BlackboxWindow::lower(void) { - screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); + if (raise) + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } @@ -1725,7 +1746,7 @@ void BlackboxWindow::maximize(unsigned int button) { blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0; blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0; - redrawAllButtons(); + redrawAllButtons(); // in case it is not called in configure() setState(current_state); return; } @@ -1739,7 +1760,6 @@ void BlackboxWindow::maximize(unsigned int button) { const Rect &screen_area = screen->availableArea(); frame.changing = screen_area; - constrain(TopLeft); switch(button) { case 1: @@ -1764,6 +1784,8 @@ void BlackboxWindow::maximize(unsigned int button) { break; } + constrain(TopLeft); + if (flags.shaded) { blackbox_attrib.flags ^= AttribShaded; blackbox_attrib.attrib ^= AttribShaded; @@ -1775,8 +1797,8 @@ void BlackboxWindow::maximize(unsigned int button) { configure(frame.changing.x(), frame.changing.y(), frame.changing.width(), frame.changing.height()); if (flags.focused) - raise(); - redrawAllButtons(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + redrawAllButtons(); // in case it is not called in configure() setState(current_state); } @@ -1823,7 +1845,7 @@ void BlackboxWindow::shade(void) { frame.margin.bottom); } else { if (! (decorations & Decor_Titlebar)) - return; + return; // can't shade it without a titlebar! XResizeWindow(blackbox->getXDisplay(), frame.window, frame.inside_w, frame.title_h); @@ -1884,13 +1906,7 @@ void BlackboxWindow::stick(void) { } -void BlackboxWindow::setFocusFlag(bool focus) { - // only focus a window if it is visible - if (focus && !flags.visible) - return; - - flags.focused = focus; - +void BlackboxWindow::redrawWindowFrame(void) const { if (decorations & Decor_Titlebar) { if (flags.focused) { if (frame.ftitle) @@ -1966,6 +1982,17 @@ void BlackboxWindow::setFocusFlag(bool focus) { XSetWindowBorder(blackbox->getXDisplay(), frame.plate, frame.uborder_pixel); } +} + + +void BlackboxWindow::setFocusFlag(bool focus) { + // only focus a window if it is visible + if (focus && !flags.visible) + return; + + flags.focused = focus; + + redrawWindowFrame(); if (screen->isSloppyFocus() && screen->doAutoRaise()) { if (isFocused()) timer->start(); @@ -1981,8 +2008,8 @@ void BlackboxWindow::installColormap(bool install) { int i = 0, ncmap = 0; Colormap *cmaps = XListInstalledColormaps(blackbox->getXDisplay(), client.window, &ncmap); - XWindowAttributes wattrib; if (cmaps) { + XWindowAttributes wattrib; if (XGetWindowAttributes(blackbox->getXDisplay(), client.window, &wattrib)) { if (install) { @@ -2083,7 +2110,7 @@ void BlackboxWindow::restoreAttributes(void) { (unsigned long **)&net)) return; if (num < PropBlackboxAttributesElements) { - delete net; + delete [] net; return; } @@ -2146,88 +2173,138 @@ void BlackboxWindow::restoreAttributes(void) { blackbox_attrib.premax_h = h; } - // with the state set it will then be the map events job to read the window's - // state and behave accordingly + // with the state set it will then be the map event's job to read the + // window's state and behave accordingly - delete net; + delete [] net; } /* - * Positions the frame according the the client window position and window - * gravity. + * Positions the Rect r according the the client window position and + * window gravity. */ -void BlackboxWindow::setGravityOffsets(void) { - // x coordinates for each gravity type - const int x_west = client.rect.x(); - const int x_east = client.rect.right() - frame.inside_w + 1; - const int x_center = client.rect.left() + - ((client.rect.width() - frame.rect.width()) / 2); - // y coordinates for each gravity type - const int y_north = client.rect.y(); - const int y_south = client.rect.bottom() - frame.inside_h + 1; - const int y_center = client.rect.top() + - ((client.rect.height() - frame.rect.height()) / 2); +void BlackboxWindow::applyGravity(Rect &r) { + // apply horizontal window gravity + switch (client.win_gravity) { + default: + case NorthWestGravity: + case SouthWestGravity: + case WestGravity: + r.setX(client.rect.x()); + break; + + case NorthGravity: + case SouthGravity: + case CenterGravity: + r.setX(client.rect.x() - (frame.margin.left + frame.margin.right) / 2); + break; + + case NorthEastGravity: + case SouthEastGravity: + case EastGravity: + r.setX(client.rect.x() - frame.margin.left - frame.margin.right); + break; + case ForgetGravity: + case StaticGravity: + r.setX(client.rect.x() - frame.margin.left); + break; + } + + // apply vertical window gravity switch (client.win_gravity) { default: - case NorthWestGravity: frame.rect.setPos(x_west, y_north); break; - case NorthGravity: frame.rect.setPos(x_center, y_north); break; - case NorthEastGravity: frame.rect.setPos(x_east, y_north); break; - case SouthWestGravity: frame.rect.setPos(x_west, y_south); break; - case SouthGravity: frame.rect.setPos(x_center, y_south); break; - case SouthEastGravity: frame.rect.setPos(x_east, y_south); break; - case WestGravity: frame.rect.setPos(x_west, y_center); break; - case CenterGravity: frame.rect.setPos(x_center, y_center); break; - case EastGravity: frame.rect.setPos(x_east, y_center); break; + case NorthWestGravity: + case NorthEastGravity: + case NorthGravity: + r.setY(client.rect.y()); + break; + + case CenterGravity: + case EastGravity: + case WestGravity: + r.setY(client.rect.y() - (frame.margin.top + frame.margin.bottom) / 2); + break; + + case SouthWestGravity: + case SouthEastGravity: + case SouthGravity: + r.setY(client.rect.y() - frame.margin.top - frame.margin.bottom); + break; case ForgetGravity: case StaticGravity: - frame.rect.setPos(client.rect.x() - frame.margin.left, - client.rect.y() - frame.margin.top); + r.setY(client.rect.y() - frame.margin.top); break; } } /* - * The reverse of the setGravityOffsets function. Uses the frame window's - * position to find the window's reference point. + * The reverse of the applyGravity function. + * + * Positions the Rect r according to the frame window position and + * window gravity. */ -void BlackboxWindow::restoreGravity(void) { - // x coordinates for each gravity type - const int x_west = frame.rect.x(); - const int x_east = frame.rect.x() + frame.inside_w - client.rect.width(); - const int x_center = frame.rect.x() - - ((client.rect.width() - frame.rect.width()) / 2); - // y coordinates for each gravity type - const int y_north = frame.rect.y(); - const int y_south = frame.rect.y() + frame.inside_h - client.rect.height(); - const int y_center = frame.rect.y() - - ((client.rect.height() - frame.rect.height()) / 2); - - switch(client.win_gravity) { +void BlackboxWindow::restoreGravity(Rect &r) { + // restore horizontal window gravity + switch (client.win_gravity) { default: - case NorthWestGravity: client.rect.setPos(x_west, y_north); break; - case NorthGravity: client.rect.setPos(x_center, y_north); break; - case NorthEastGravity: client.rect.setPos(x_east, y_north); break; - case SouthWestGravity: client.rect.setPos(x_west, y_south); break; - case SouthGravity: client.rect.setPos(x_center, y_south); break; - case SouthEastGravity: client.rect.setPos(x_east, y_south); break; - case WestGravity: client.rect.setPos(x_west, y_center); break; - case CenterGravity: client.rect.setPos(x_center, y_center); break; - case EastGravity: client.rect.setPos(x_east, y_center); break; + case NorthWestGravity: + case SouthWestGravity: + case WestGravity: + r.setX(frame.rect.x()); + break; + + case NorthGravity: + case SouthGravity: + case CenterGravity: + r.setX(frame.rect.x() + (frame.margin.left + frame.margin.right) / 2); + break; + + case NorthEastGravity: + case SouthEastGravity: + case EastGravity: + r.setX(frame.rect.x() + frame.margin.left + frame.margin.right); + break; case ForgetGravity: case StaticGravity: - client.rect.setPos(frame.rect.left() + frame.margin.left, - frame.rect.top() + frame.margin.top); + r.setX(frame.rect.x() + frame.margin.left); + break; + } + + // restore vertical window gravity + switch (client.win_gravity) { + default: + case NorthWestGravity: + case NorthEastGravity: + case NorthGravity: + r.setY(frame.rect.y()); + break; + + case CenterGravity: + case EastGravity: + case WestGravity: + r.setY(frame.rect.y() + (frame.margin.top + frame.margin.bottom) / 2); + break; + + case SouthWestGravity: + case SouthEastGravity: + case SouthGravity: + r.setY(frame.rect.y() + frame.margin.top + frame.margin.bottom); + break; + + case ForgetGravity: + case StaticGravity: + r.setY(frame.rect.y() + frame.margin.top); break; } } -void BlackboxWindow::redrawLabel(void) { +void BlackboxWindow::redrawLabel(void) const { if (flags.focused) { if (frame.flabel) XSetWindowBackgroundPixmap(blackbox->getXDisplay(), @@ -2247,31 +2324,23 @@ void BlackboxWindow::redrawLabel(void) { WindowStyle *style = screen->getWindowStyle(); - int pos = frame.bevel_w * 2, - dlen = style->doJustify(client.title.c_str(), pos, frame.label_w, - frame.bevel_w * 4, i18n.multibyte()); - - BPen pen((flags.focused) ? style->l_text_focus : style->l_text_unfocus, - style->font); - if (i18n.multibyte()) - XmbDrawString(blackbox->getXDisplay(), frame.label, style->fontset, - pen.gc(), pos, - (1 - style->fontset_extents->max_ink_extent.y), - client.title.c_str(), dlen); - else - XDrawString(blackbox->getXDisplay(), frame.label, pen.gc(), pos, - (style->font->ascent + 1), client.title.c_str(), dlen); + int pos = frame.bevel_w * 2; + style->doJustify(client.title.c_str(), pos, frame.label_w, frame.bevel_w * 4); + style->font->drawString(frame.label, pos, 1, + (flags.focused ? style->l_text_focus : + style->l_text_unfocus), + client.title); } -void BlackboxWindow::redrawAllButtons(void) { +void BlackboxWindow::redrawAllButtons(void) const { if (frame.iconify_button) redrawIconifyButton(False); if (frame.maximize_button) redrawMaximizeButton(flags.maximized); if (frame.close_button) redrawCloseButton(False); } -void BlackboxWindow::redrawIconifyButton(bool pressed) { +void BlackboxWindow::redrawIconifyButton(bool pressed) const { if (! pressed) { if (flags.focused) { if (frame.fbutton) @@ -2305,7 +2374,7 @@ void BlackboxWindow::redrawIconifyButton(bool pressed) { } -void BlackboxWindow::redrawMaximizeButton(bool pressed) { +void BlackboxWindow::redrawMaximizeButton(bool pressed) const { if (! pressed) { if (flags.focused) { if (frame.fbutton) @@ -2341,7 +2410,7 @@ void BlackboxWindow::redrawMaximizeButton(bool pressed) { } -void BlackboxWindow::redrawCloseButton(bool pressed) { +void BlackboxWindow::redrawCloseButton(bool pressed) const { if (! pressed) { if (flags.focused) { if (frame.fbutton) @@ -2400,7 +2469,7 @@ void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) { case ZoomState: default: show(); - raise(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); if (! blackbox->isStartup() && (isTransient() || screen->doFocusNew())) { XSync(blackbox->getXDisplay(), False); // make sure the frame is mapped.. setInputFocus(); @@ -2556,83 +2625,41 @@ void BlackboxWindow::configureRequestEvent(const XConfigureRequestEvent *cr) { if (cr->window != client.window || flags.iconic) return; - int cx = frame.rect.x(), cy = frame.rect.y(); - unsigned int cw = frame.rect.width(), ch = frame.rect.height(); - if (cr->value_mask & CWBorderWidth) client.old_bw = cr->border_width; - if (cr->value_mask & CWX) - cx = cr->x - frame.margin.left; + if (cr->value_mask & (CWX | CWY | CWWidth | CWHeight)) { + Rect req = frame.rect; - if (cr->value_mask & CWY) - cy = cr->y - frame.margin.top; + if (cr->value_mask & (CWX | CWY)) { + if (cr->value_mask & CWX) + client.rect.setX(cr->x); + if (cr->value_mask & CWY) + client.rect.setY(cr->y); - if (cr->value_mask & CWWidth) - cw = cr->width + frame.margin.left + frame.margin.right; + applyGravity(req); + } + + if (cr->value_mask & CWWidth) + req.setWidth(cr->width + frame.margin.left + frame.margin.right); - if (cr->value_mask & CWHeight) - ch = cr->height + frame.margin.top + frame.margin.bottom; + if (cr->value_mask & CWHeight) + req.setHeight(cr->height + frame.margin.top + frame.margin.bottom); - if (frame.rect != Rect(cx, cy, cw, ch)) - configure(cx, cy, cw, ch); + configure(req.x(), req.y(), req.width(), req.height()); + } if (cr->value_mask & CWStackMode) { switch (cr->detail) { case Below: case BottomIf: - lower(); + screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); break; case Above: case TopIf: default: - raise(); - break; - } - } -} - - -void BlackboxWindow::grabButtons(void) { - const BInput::MouseBindingList &mbindings = input->getMouseBindings(); - - BInput::MouseBindingList::const_iterator mit = mbindings.begin(); - const BInput::MouseBindingList::const_iterator mend = mbindings.end(); - for (; mit != mend; ++mit) { - // dont grab for an action the window can't perform - //if (! (mit->action == BInput::BeginMove && functions & Func_Move) && - // ! (mit->action == BInput::BeginResize && functions & Func_Resize)) { - switch (mit->event) { - case BInput::WindowClientPress: - blackbox->grabButton(mit->button, mit->state, frame.plate, True, - ButtonPressMask, GrabModeSync, GrabModeSync, - frame.plate, None); - break; - case BInput::WindowDrag: - blackbox->grabButton(mit->button, mit->state, frame.window, True, - ButtonMotionMask, GrabModeAsync, GrabModeAsync, - frame.window, None); - default: - break; - } - } -} - - -void BlackboxWindow::ungrabButtons(void) { - const BInput::MouseBindingList &mbindings = input->getMouseBindings(); - - BInput::MouseBindingList::const_iterator mit = mbindings.begin(); - const BInput::MouseBindingList::const_iterator mend = mbindings.end(); - for (; mit != mend; ++mit) { - switch (mit->event) { - case BInput::WindowClientPress: - blackbox->ungrabButton(mit->button, mit->state, frame.plate); - break; - case BInput::WindowDrag: - blackbox->ungrabButton(mit->button, mit->state, frame.window); - default: + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); break; } } @@ -2640,170 +2667,137 @@ void BlackboxWindow::ungrabButtons(void) { void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { - if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); - if (frame.maximize_button == be->window) { - if (input->hasAction(be->button, be->state, BInput::MaximizeButtonClick)) - redrawMaximizeButton(True); - } else if (frame.iconify_button == be->window) { - if (input->hasAction(be->button, be->state, BInput::IconifyButtonClick)) + redrawMaximizeButton(True); + } else if (be->button == 1 || (be->button == 3 && be->state == Mod1Mask)) { + if (! flags.focused) + setInputFocus(); + + if (frame.iconify_button == be->window) { redrawIconifyButton(True); - } else if (frame.close_button == be->window) { - if (input->hasAction(be->button, be->state, BInput::CloseButtonClick)) + } else if (frame.close_button == be->window) { redrawCloseButton(True); - } else if (frame.title == be->window || frame.label == be->window) { - if (be->time - lastButtonPressTime <= blackbox->getDoubleClickInterval()) { - lastButtonPressTime = 0; - input->doAction(this, be->button, be->state, - BInput::WindowTitleDoublePress); - } else { - lastButtonPressTime = be->time; - input->doAction(this, be->button, be->state, - BInput::WindowTitlePress); - } - } else if (frame.plate == be->window) { - input->doAction(this, be->button, be->state, BInput::WindowClientPress); - // buttons on the client window are grabbed in Sync mode, so we need to let - // events back through again - XAllowEvents(blackbox->getXDisplay(), ReplayPointer, be->time); - } else if (frame.window == be->window || frame.handle == be->window) { - input->doAction(this, be->button, be->state, BInput::WindowFramePress); - } -} + } else if (frame.plate == be->window) { + if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); -void BlackboxWindow::showWindowMenu(int root_x, int root_y) { - if (! windowmenu || windowmenu->isVisible()) - return; - - root_x -= windowmenu->getWidth() / 2; - root_y -= windowmenu->getHeight() / 2; + XAllowEvents(blackbox->getXDisplay(), ReplayPointer, be->time); + } else { + if (frame.title == be->window || frame.label == be->window) { + if (((be->time - lastButtonPressTime) <= + blackbox->getDoubleClickInterval()) || + (be->state & ControlMask)) { + lastButtonPressTime = 0; + shade(); + } else { + lastButtonPressTime = be->time; + } + } - // snap the window menu into a corner/side if necessary - int left_edge, right_edge, top_edge, bottom_edge; - - left_edge = frame.rect.x(); - right_edge = frame.rect.right() - windowmenu->getWidth() - frame.border_w - 1; - if (decorations & Decor_Titlebar) - top_edge = frame.rect.y() + frame.title_h + frame.border_w; - else - top_edge = frame.rect.y() + frame.border_w; - if (decorations & Decor_Handle) - bottom_edge = frame.rect.bottom() - frame.handle_h - (frame.border_w * 3) - - windowmenu->getHeight(); - else - bottom_edge = frame.rect.bottom() - windowmenu->getHeight() - - frame.border_w + 1; - - if (root_x > right_edge) - root_x = right_edge; - if (root_x < left_edge) - root_x = left_edge; + if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); - if (root_y > bottom_edge) - root_y = bottom_edge; - if (root_y < top_edge) - root_y = top_edge; + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + } + } else if (be->button == 2 && (be->window != frame.iconify_button) && + (be->window != frame.close_button)) { + screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); + } else if (windowmenu && be->button == 3 && + (frame.title == be->window || frame.label == be->window || + frame.handle == be->window || frame.window == be->window)) { + int mx = 0, my = 0; + + if (frame.title == be->window || frame.label == be->window) { + mx = be->x_root - (windowmenu->getWidth() / 2); + my = frame.rect.y() + frame.title_h + frame.border_w; + } else if (frame.handle == be->window) { + mx = be->x_root - (windowmenu->getWidth() / 2); + my = frame.rect.bottom() - frame.handle_h - (frame.border_w * 3) - + windowmenu->getHeight(); + } else { + mx = be->x_root - (windowmenu->getWidth() / 2); + if (be->y <= static_cast(frame.bevel_w)) + my = frame.rect.y() + frame.title_h; + else + my = be->y_root - (windowmenu->getHeight() / 2); + } - windowmenu->move(root_x, root_y); - windowmenu->show(); - XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID()); - XRaiseWindow(blackbox->getXDisplay(), - windowmenu->getSendToMenu()->getWindowID()); + // snap the window menu into a corner if necessary - we check the + // position of the menu with the coordinates of the client to + // make the comparisions easier. + // XXX: this needs some work! + if (mx > client.rect.right() - + static_cast(windowmenu->getWidth())) + mx = frame.rect.right() - windowmenu->getWidth() - frame.border_w + 1; + if (mx < client.rect.left()) + mx = frame.rect.x(); + + if (my > client.rect.bottom() - + static_cast(windowmenu->getHeight())) + my = frame.rect.bottom() - windowmenu->getHeight() - frame.border_w + 1; + if (my < client.rect.top()) + my = frame.rect.y() + ((decorations & Decor_Titlebar) ? + frame.title_h : 0); + + if (windowmenu) { + if (! windowmenu->isVisible()) { + windowmenu->move(mx, my); + windowmenu->show(); + XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID()); + XRaiseWindow(blackbox->getXDisplay(), + windowmenu->getSendToMenu()->getWindowID()); + } else { + windowmenu->hide(); + } + } + // mouse wheel up + } else if (be->button == 4) { + if ((be->window == frame.label || + be->window == frame.title) && + ! flags.shaded) + shade(); + // mouse wheel down + } else if (be->button == 5) { + if ((be->window == frame.label || + be->window == frame.title) && + flags.shaded) + shade(); + } } void BlackboxWindow::buttonReleaseEvent(const XButtonEvent *re) { - // get the proper state, without the button that was released - unsigned int state; - switch (re->button) { - case Button1: - state = re->state & ~Button1Mask; - break; - case Button2: - state = re->state & ~Button2Mask; - break; - case Button3: - state = re->state & ~Button3Mask; - break; - case Button4: - state = re->state & ~Button4Mask; - break; - case Button5: - state = re->state & ~Button5Mask; - break; - default: - assert(false); // unhandled button - } - - if (frame.maximize_button == re->window) { - if ((re->x < 0 || re->x >= static_cast(frame.button_w)) || - (re->y < 0 || re->y >= static_cast(frame.button_w)) || - ! input->doAction(this, re->button, state, - BInput::MaximizeButtonClick)) + if (re->window == frame.maximize_button) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(frame.button_w))) { + maximize(re->button); + } else { redrawMaximizeButton(flags.maximized); - } else if (frame.iconify_button == re->window) { - if ((re->x < 0 || re->x >= static_cast(frame.button_w)) || - (re->y < 0 || re->y >= static_cast(frame.button_w)) || - ! input->doAction(this, re->button, state, - BInput::IconifyButtonClick)) + } + } else if (re->window == frame.iconify_button) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(frame.button_w))) { + iconify(); + } else { redrawIconifyButton(False); - } else if (frame.close_button == re->window) { - if (! ((re->x < 0 || re->x >= static_cast(frame.button_w)) || - (re->y < 0 || re->y >= static_cast(frame.button_w)))) - input->doAction(this, re->button, state, BInput::CloseButtonClick); - redrawCloseButton(False); + } + } else if (re->window == frame.close_button) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(frame.button_w))) + close(); + redrawCloseButton(False); } else if (flags.moving) { endMove(); } else if (flags.resizing) { endResize(); + } else if (re->window == frame.window) { + if (re->button == 2 && re->state == Mod1Mask) + XUngrabPointer(blackbox->getXDisplay(), CurrentTime); } } -void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) { - // get the button that is being used - // get the proper state, without the button that is being used - unsigned int button; - unsigned int state; - if (me->state & Button1Mask) { - button = Button1; - state = me->state & ~Button1Mask; - } else if (me->state & Button2Mask) { - button = Button2; - state = me->state & ~Button2Mask; - } else if (me->state & Button3Mask) { - button = Button3; - state = me->state & ~Button3Mask; - } else if (me->state & Button4Mask) { - button = Button4; - state = me->state & ~Button4Mask; - } else if (me->state & Button5Mask) { - button = Button5; - state = me->state & ~Button5Mask; - } else { - return; - } - - if (flags.moving) { - doMove(me->x_root, me->y_root); - } else if (flags.resizing) { - doResize(me->x_root, me->y_root); - } else { - if (frame.title == me->window || frame.label == me->window) - input->doAction(this, button, state, BInput::WindowTitleDrag); - else if (frame.handle == me->window) - input->doAction(this, button, state, BInput::WindowHandleDrag); - else if (frame.left_grip == me->window) - input->doAction(this, button, state, BInput::WindowLeftGripDrag); - else if (frame.right_grip == me->window) - input->doAction(this, button, state, BInput::WindowRightGripDrag); - else if (frame.window == me->window) - input->doAction(this, button, state, BInput::WindowDrag); - } -} - void BlackboxWindow::beginMove(int x_root, int y_root) { assert(! (flags.resizing || flags.moving)); @@ -3195,6 +3189,30 @@ void BlackboxWindow::endResize(void) { } +void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) { + if (flags.moving) { + doMove(me->x_root, me->y_root); + } else if (flags.resizing) { + doResize(me->x_root, me->y_root); + } else { + 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); + } + } +} + + #ifdef SHAPE void BlackboxWindow::shapeEvent(XShapeEvent *) { if (blackbox->hasShapeExtensions() && flags.shaped) { @@ -3226,7 +3244,7 @@ void BlackboxWindow::restore(bool remap) { XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); XSelectInput(blackbox->getXDisplay(), frame.plate, NoEventMask); - restoreGravity(); + restoreGravity(client.rect); XUnmapWindow(blackbox->getXDisplay(), frame.window); XUnmapWindow(blackbox->getXDisplay(), client.window); @@ -3251,7 +3269,7 @@ void BlackboxWindow::restore(bool remap) { // timer for autoraise void BlackboxWindow::timeout(void) { - raise(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } @@ -3294,7 +3312,7 @@ void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) { withdraw(); } else { show(); - raise(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } } @@ -3347,7 +3365,7 @@ void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) { if (flags.shaded && ! (decorations & Decor_Titlebar)) shade(); - if (frame.window) { + if (flags.visible && frame.window) { XMapSubwindows(blackbox->getXDisplay(), frame.window); XMapWindow(blackbox->getXDisplay(), frame.window); } @@ -3381,12 +3399,7 @@ void BlackboxWindow::upsize(void) { // the height of the titlebar is based upon the height of the font being // used to display the window's title WindowStyle *style = screen->getWindowStyle(); - if (i18n.multibyte()) - frame.title_h = (style->fontset_extents->max_ink_extent.height + - (frame.bevel_w * 2) + 2); - else - frame.title_h = (style->font->ascent + style->font->descent + - (frame.bevel_w * 2) + 2); + frame.title_h = style->font->height() + (frame.bevel_w * 2) + 2; frame.label_h = frame.title_h - (frame.bevel_w * 2); frame.button_w = (frame.label_h - 2); @@ -3476,8 +3489,18 @@ void BlackboxWindow::constrain(Corner anchor, int *pw, int *ph) { dh -= base_height; dh /= client.height_inc; - if (pw) *pw = dw; - if (ph) *ph = dh; + if (pw) { + if (client.width_inc == 1) + *pw = dw + base_width; + else + *pw = dw; + } + if (ph) { + if (client.height_inc == 1) + *ph = dh + base_height; + else + *ph = dh; + } dw *= client.width_inc; dw += base_width; @@ -3519,21 +3542,14 @@ void BlackboxWindow::constrain(Corner anchor, int *pw, int *ph) { } -int WindowStyle::doJustify(const char *text, int &start_pos, - unsigned int max_length, unsigned int modifier, - bool multibyte) const { - size_t text_len = strlen(text); +int WindowStyle::doJustify(const std::string &text, int &start_pos, + unsigned int max_length, + unsigned int modifier) const { + size_t text_len = text.size(); unsigned int length; do { - if (multibyte) { - XRectangle ink, logical; - XmbTextExtents(fontset, text, text_len, &ink, &logical); - length = logical.width; - } else { - length = XTextWidth(font, text, text_len); - } - length += modifier; + length = font->measureString(string(text, 0, text_len)) + modifier; } while (length > max_length && text_len-- > 0); switch (justify) {