X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2FWindow.cc;h=427cc955d8500695bfcf2c1e652e911869472f7d;hb=6954842d84539c1b345d575a39c5dbd5ab0a1227;hp=17f2e8b3ac94e8f4f1d12a4c76be11b67dc78c9b;hpb=ffa4c7f3414944869016497a4f560c24b9d8b3e9;p=chaz%2Fopenbox diff --git a/src/Window.cc b/src/Window.cc index 17f2e8b3..427cc955 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; @@ -136,13 +134,14 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { frame.fgrip_pixel = 0; frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None; frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None; - frame.pbutton = frame.ugrip = frame.fgrip = decorations; + 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; client.wm_hint_flags = client.normal_hint_flags = 0; + client.window_group = None; client.transient_for = 0; /* @@ -190,9 +189,6 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { blackbox->saveWindowSearch(frame.plate, this); blackbox->saveWindowSearch(client.window, this); - screen->addStrut(&client.strut); - updateStrut(); - // determine if this is a transient window getTransientInfo(); @@ -261,6 +257,10 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { place_window = False; } + // add the window's strut. note this is done *after* placing the window. + screen->addStrut(&client.strut); + updateStrut(); + if (decorations & Decor_Titlebar) createTitlebar(); @@ -275,13 +275,6 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { grabButtons(); - positionWindows(); - decorate(); - - if (decorations & Decor_Titlebar) - XMapSubwindows(blackbox->getXDisplay(), frame.title); - XMapSubwindows(blackbox->getXDisplay(), frame.window); - windowmenu = new Windowmenu(this); if (blackbox_attrib.workspace >= screen->getWorkspaceCount()) @@ -313,16 +306,15 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { if (flags.shaded) { flags.shaded = False; + unsigned long orig_state = current_state; 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 - get shown on the first workspace. At this point in the life of a window, current_state should only be set to IconicState if the window was an *icon*, not if it was shaded. */ - current_state = NormalState; + if (orig_state != IconicState) + current_state = NormalState; } if (flags.stuck) { @@ -343,6 +335,11 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { fact never set to Iconic since there is no way for us to tell if a sticky window was iconified previously. */ + + positionWindows(); + decorate(); + + XMapSubwindows(blackbox->getXDisplay(), frame.window); redrawWindowFrame(); } @@ -822,17 +819,11 @@ void BlackboxWindow::positionButtons(bool redecorate_label) { void BlackboxWindow::reconfigure(void) { upsize(); - client.rect.setPos(frame.rect.left() + frame.margin.left, - frame.rect.top() + frame.margin.top); - positionWindows(); decorate(); redrawWindowFrame(); - configure(frame.rect.x(), frame.rect.y(), - frame.rect.width(), frame.rect.height()); - if (windowmenu) { windowmenu->move(windowmenu->getX(), frame.rect.y() + frame.title_h); windowmenu->reconfigure(); @@ -840,6 +831,34 @@ void BlackboxWindow::reconfigure(void) { } +void BlackboxWindow::grabButtons(void) { + if ((! screen->isSloppyFocus()) || screen->doClickRaise()) + // grab button 1 for changing focus/raising + blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask, + GrabModeSync, GrabModeSync, frame.plate, None); + + if (functions & Func_Move) + blackbox->grabButton(Button1, Mod1Mask, frame.window, True, + ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, + GrabModeAsync, frame.window, + blackbox->getMoveCursor()); + if (functions & Func_Resize) + blackbox->grabButton(Button3, Mod1Mask, frame.window, True, + ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, + GrabModeAsync, frame.window, + blackbox->getLowerRightAngleCursor()); +} + + +void BlackboxWindow::ungrabButtons(void) { + if ((! screen->isSloppyFocus()) || screen->doClickRaise()) + blackbox->ungrabButton(Button1, 0, frame.plate); + + blackbox->ungrabButton(Button1, Mod1Mask, frame.window); + blackbox->ungrabButton(Button3, Mod1Mask, frame.window); +} + + void BlackboxWindow::positionWindows(void) { XMoveResizeWindow(blackbox->getXDisplay(), frame.window, frame.rect.x(), frame.rect.y(), frame.inside_w, @@ -854,6 +873,11 @@ void BlackboxWindow::positionWindows(void) { client.rect.width(), client.rect.height()); 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); if (decorations & Decor_Titlebar) { if (frame.title == None) createTitlebar(); @@ -1199,9 +1223,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) { @@ -1242,7 +1269,7 @@ void BlackboxWindow::getMWMHints(void) { functions |= Func_Close; } } - delete mwm_hint; + delete [] mwm_hint; } @@ -1260,9 +1287,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); @@ -1324,7 +1354,7 @@ bool BlackboxWindow::getBlackboxHints(void) { reconfigure(); } - delete blackbox_hint; + delete [] blackbox_hint; return True; } @@ -1402,9 +1432,15 @@ BlackboxWindow *BlackboxWindow::getTransientFor(void) const { } +/* + * This function is responsible for updating both the client and the frame + * rectangles. + * According to the ICCCM a client message is not sent for a resize, only a + * move. + */ void BlackboxWindow::configure(int dx, int dy, unsigned int dw, unsigned int dh) { - bool send_event = False; + bool send_event = (frame.rect.x() != dx || frame.rect.y() != dy); if (dw != frame.rect.width() || dh != frame.rect.height()) { frame.rect.setRect(dx, dy, dw, dh); @@ -1428,9 +1464,7 @@ void BlackboxWindow::configure(int dx, int dy, positionWindows(); decorate(); redrawWindowFrame(); - } else if (frame.rect.x() != dx || frame.rect.y() != dy) { - send_event = True; - + } else { frame.rect.setPos(dx, dy); XMoveWindow(blackbox->getXDisplay(), frame.window, @@ -1438,6 +1472,7 @@ void BlackboxWindow::configure(int dx, int dy, } if (send_event && ! flags.moving) { + // 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); @@ -1457,7 +1492,6 @@ void BlackboxWindow::configure(int dx, int dy, XSendEvent(blackbox->getXDisplay(), client.window, False, StructureNotifyMask, &event); - screen->updateNetizenConfigNotify(&event); } } @@ -1499,8 +1533,10 @@ void BlackboxWindow::configureShape(void) { bool BlackboxWindow::setInputFocus(void) { if (flags.focused) return True; - assert(! flags.iconic); - + assert(! flags.iconic && + (flags.stuck || // window must be on the current workspace or sticky + blackbox_attrib.workspace == screen->getCurrentWorkspaceID())); +#if 0 // if the window is not visible, mark the window as wanting focus rather // than give it focus. if (! flags.visible) { @@ -1508,7 +1544,7 @@ bool BlackboxWindow::setInputFocus(void) { wkspc->setLastFocusedWindow(this); return True; } - +#endif if (! frame.rect.intersects(screen->getRect())) { // client is outside the screen, move it to the center configure((screen->getWidth() - frame.rect.width()) / 2, @@ -1620,13 +1656,24 @@ void BlackboxWindow::show(void) { XMapWindow(blackbox->getXDisplay(), client.window); XMapSubwindows(blackbox->getXDisplay(), frame.window); XMapWindow(blackbox->getXDisplay(), frame.window); + +#ifdef DEBUG + int real_x, real_y; + Window child; + XTranslateCoordinates(blackbox->getXDisplay(), client.window, + screen->getRootWindow(), + 0, 0, &real_x, &real_y, &child); + fprintf(stderr, "%s -- assumed: (%d, %d), real: (%d, %d)\n", getTitle(), + client.rect.left(), client.rect.top(), real_x, real_y); + assert(client.rect.left() == real_x && client.rect.top() == real_y); +#endif } -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()) + else if (blackbox_attrib.workspace != screen->getCurrentWorkspaceID()) return; show(); @@ -1639,18 +1686,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); } @@ -1774,7 +1811,7 @@ void BlackboxWindow::maximize(unsigned int button) { configure(frame.changing.x(), frame.changing.y(), frame.changing.width(), frame.changing.height()); if (flags.focused) - raise(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); redrawAllButtons(); // in case it is not called in configure() setState(current_state); } @@ -2087,26 +2124,25 @@ void BlackboxWindow::restoreAttributes(void) { (unsigned long **)&net)) return; if (num < PropBlackboxAttributesElements) { - delete net; + delete [] net; return; } if (net->flags & AttribShaded && net->attrib & AttribShaded) { flags.shaded = False; + unsigned long orig_state = current_state; 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 - get shown on the first workspace. At this point in the life of a window, current_state should only be set to IconicState if the window was an *icon*, not if it was shaded. */ - current_state = NormalState; + if (orig_state != IconicState) + current_state = WithdrawnState; } - if ((net->workspace != screen->getCurrentWorkspaceID()) && - (net->workspace < screen->getWorkspaceCount())) + if (net->workspace != screen->getCurrentWorkspaceID() && + net->workspace < screen->getWorkspaceCount()) screen->reassociateWindow(this, net->workspace, True); if ((blackbox_attrib.workspace != screen->getCurrentWorkspaceID()) && @@ -2153,7 +2189,7 @@ void BlackboxWindow::restoreAttributes(void) { // 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; } @@ -2301,20 +2337,12 @@ void BlackboxWindow::redrawLabel(void) const { 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); } @@ -2454,7 +2482,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(); @@ -2506,8 +2534,16 @@ void BlackboxWindow::reparentNotifyEvent(const XReparentEvent *re) { } -void BlackboxWindow::propertyNotifyEvent(Atom atom) { - switch(atom) { +void BlackboxWindow::propertyNotifyEvent(const XPropertyEvent *pe) { + if (pe->state == PropertyDelete) + return; + +#ifdef DEBUG + fprintf(stderr, "BlackboxWindow::propertyNotifyEvent(): for 0x%lx\n", + client.window); +#endif + + switch(pe->atom) { case XA_WM_CLASS: case XA_WM_CLIENT_MACHINE: case XA_WM_COMMAND: @@ -2552,6 +2588,9 @@ void BlackboxWindow::propertyNotifyEvent(Atom atom) { if ((client.normal_hint_flags & PMinSize) && (client.normal_hint_flags & PMaxSize)) { + // the window now can/can't resize itself, so the buttons need to be + // regrabbed. + ungrabButtons(); if (client.max_width <= client.min_width && client.max_height <= client.min_height) { decorations &= ~(Decor_Maximize | Decor_Handle); @@ -2560,6 +2599,7 @@ void BlackboxWindow::propertyNotifyEvent(Atom atom) { decorations |= Decor_Maximize | Decor_Handle; functions |= Func_Resize | Func_Maximize; } + grabButtons(); setAllowedActions(); } @@ -2574,7 +2614,7 @@ void BlackboxWindow::propertyNotifyEvent(Atom atom) { } default: - if (atom == xatom->getAtom(XAtom::wm_protocols)) { + if (pe->atom == xatom->getAtom(XAtom::wm_protocols)) { getWMProtocols(); if ((decorations & Decor_Close) && (! frame.close_button)) { @@ -2585,7 +2625,7 @@ void BlackboxWindow::propertyNotifyEvent(Atom atom) { } if (windowmenu) windowmenu->reconfigure(); } - } else if (atom == xatom->getAtom(XAtom::net_wm_strut)) { + } else if (pe->atom == xatom->getAtom(XAtom::net_wm_strut)) { updateStrut(); } @@ -2595,6 +2635,10 @@ void BlackboxWindow::propertyNotifyEvent(Atom atom) { void BlackboxWindow::exposeEvent(const XExposeEvent *ee) { +#ifdef DEBUG + fprintf(stderr, "BlackboxWindow::exposeEvent() for 0x%lx\n", client.window); +#endif + if (frame.label == ee->window && (decorations & Decor_Titlebar)) redrawLabel(); else if (frame.close_button == ee->window) @@ -2638,58 +2682,13 @@ void BlackboxWindow::configureRequestEvent(const XConfigureRequestEvent *cr) { 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; } } @@ -2697,120 +2696,127 @@ void BlackboxWindow::ungrabButtons(void) { void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { - if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); - +#ifdef DEBUG + fprintf(stderr, "BlackboxWindow::buttonPressEvent() for 0x%lx\n", + client.window); +#endif + 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; - - // 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 (root_y > bottom_edge) - root_y = bottom_edge; - if (root_y < top_edge) - root_y = top_edge; + 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; + } + } + if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); - windowmenu->move(root_x, root_y); - windowmenu->show(); - XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID()); - XRaiseWindow(blackbox->getXDisplay(), - windowmenu->getSendToMenu()->getWindowID()); + 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)) { + if (windowmenu->isVisible()) { + windowmenu->hide(); + } else { + int mx = be->x_root - windowmenu->getWidth() / 2, + my = be->y_root - windowmenu->getHeight() / 2; + + // snap the window menu into a corner/side if necessary + int left_edge, right_edge, top_edge, bottom_edge; + + /* + the " + (frame.border_w * 2) - 1" bits are to get the proper width + and height of the menu, as the sizes returned by it do not include + the borders. + */ + left_edge = frame.rect.x(); + right_edge = frame.rect.right() - + (windowmenu->getWidth() + (frame.border_w * 2) - 1); + top_edge = client.rect.top() - (frame.border_w + frame.mwm_border_w); + bottom_edge = client.rect.bottom() - + (windowmenu->getHeight() + (frame.border_w * 2) - 1) + + (frame.border_w + frame.mwm_border_w); + + if (mx < left_edge) + mx = left_edge; + if (mx > right_edge) + mx = right_edge; + if (my < top_edge) + my = top_edge; + if (my > bottom_edge) + my = bottom_edge; + + windowmenu->move(mx, my); + windowmenu->show(); + XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID()); + XRaiseWindow(blackbox->getXDisplay(), + windowmenu->getSendToMenu()->getWindowID()); + } + // 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 - } +#ifdef DEBUG + fprintf(stderr, "BlackboxWindow::buttonReleaseEvent() for 0x%lx\n", + client.window); +#endif - 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) { @@ -2819,48 +2825,6 @@ void BlackboxWindow::buttonReleaseEvent(const XButtonEvent *re) { } -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)); @@ -3252,6 +3216,35 @@ void BlackboxWindow::endResize(void) { } +void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) { +#ifdef DEBUG + fprintf(stderr, "BlackboxWindow::motionNotifyEvent() for 0x%lx\n", + client.window); +#endif + + 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) { @@ -3283,6 +3276,9 @@ void BlackboxWindow::restore(bool remap) { XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); XSelectInput(blackbox->getXDisplay(), frame.plate, NoEventMask); + // do not leave a shaded window as an icon unless it was an icon + if (flags.shaded && ! flags.iconic) setState(NormalState); + restoreGravity(client.rect); XUnmapWindow(blackbox->getXDisplay(), frame.window); @@ -3308,7 +3304,7 @@ void BlackboxWindow::restore(bool remap) { // timer for autoraise void BlackboxWindow::timeout(void) { - raise(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } @@ -3351,7 +3347,7 @@ void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) { withdraw(); } else { show(); - raise(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } } @@ -3438,12 +3434,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); @@ -3586,21 +3577,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); +void 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) { @@ -3616,8 +3600,6 @@ int WindowStyle::doJustify(const char *text, int &start_pos, default: break; } - - return text_len; }