X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2FWindow.cc;h=3005674b900bdac5cb62585b5a84ccb2d0dec629;hb=c2afc72a41a4093f1fdfdf3245d5d70ef8bf9ad2;hp=c260818c68ba271e97dce45fe7c89ffca0bede36;hpb=f763814b338f9418e705309ddc87f68140d7888a;p=chaz%2Fopenbox diff --git a/src/Window.cc b/src/Window.cc index c260818c..3005674b 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -128,7 +128,8 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { 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 = @@ -474,7 +475,13 @@ Window BlackboxWindow::createToplevelWindow(void) { attrib_create.background_pixmap = None; attrib_create.colormap = screen->getColormap(); attrib_create.override_redirect = True; - attrib_create.event_mask = EnterWindowMask | LeaveWindowMask; + attrib_create.event_mask = EnterWindowMask | LeaveWindowMask | + ButtonPress; + /* + We catch button presses because other wise they get passed down to the + root window, which will then cause root menus to show when you click the + window's frame. + */ return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(), 0, 0, 1, 1, frame.border_w, screen->getDepth(), @@ -719,6 +726,9 @@ void BlackboxWindow::destroyTitlebar(void) { if (frame.maximize_button) destroyMaximizeButton(); + if (frame.stick_button) + destroyStickyButton(); + if (frame.ftitle) screen->getImageControl()->removeImage(frame.ftitle); @@ -802,13 +812,28 @@ void BlackboxWindow::destroyMaximizeButton(void) { 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) { @@ -825,6 +850,12 @@ void BlackboxWindow::positionButtons(bool redecorate_label) { parsed += *it; } break; + case 'S': + if (!hasstick) { + hasstick = true; + parsed += *it; + } + break; case 'M': if (! hasmaximize && (decorations & Decor_Maximize)) { hasmaximize = true; @@ -836,14 +867,18 @@ void BlackboxWindow::positionButtons(bool redecorate_label) { 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 @@ -869,6 +904,12 @@ void BlackboxWindow::positionButtons(bool redecorate_label) { 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, @@ -1090,7 +1131,6 @@ void BlackboxWindow::getWMName(void) { xatom->setValue(client.window, XAtom::net_wm_visible_name, XAtom::utf8, client.title); -#define DEBUG_WITH_ID 1 #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]; @@ -1631,6 +1671,14 @@ void BlackboxWindow::configureShape(void) { 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 @@ -2069,6 +2117,9 @@ void BlackboxWindow::stick(void) { setState(current_state); } + + redrawAllButtons(); + // go up the chain if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul && client.transient_for->isStuck() != flags.stuck) @@ -2534,6 +2585,7 @@ void BlackboxWindow::redrawAllButtons(void) const { 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); } @@ -2562,12 +2614,31 @@ void BlackboxWindow::redrawIconifyButton(bool pressed) const { XSetWindowBackground(blackbox->getXDisplay(), frame.iconify_button, frame.pbutton_pixel); } - XClearWindow(blackbox->getXDisplay(), frame.iconify_button); + XClearWindow(blackbox->getXDisplay(), frame.iconify_button); BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : - screen->getWindowStyle()->b_pic_unfocus); - XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(), - 2, (frame.button_w - 5), (frame.button_w - 5), 2); + screen->getWindowStyle()->b_pic_unfocus); +#ifdef BITMAPBUTTONS + PixmapMask pm = screen->getWindowStyle()->icon_button; + + if (screen->getWindowStyle()->icon_button.mask != None) { + XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask); + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); + + XFillRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, + (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); + + XSetClipMask(blackbox->getXDisplay(), pen.gc(), None); + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0); + } else { +#endif // BITMAPBUTTONS + XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(), + 2, (frame.button_w - 5), (frame.button_w - 5), 2); +#ifdef BITMAPBUTTONS + } +#endif // BITMAPBUTTONS } @@ -2600,10 +2671,30 @@ void BlackboxWindow::redrawMaximizeButton(bool pressed) const { BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : screen->getWindowStyle()->b_pic_unfocus); - XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), - 2, 2, (frame.button_w - 5), (frame.button_w - 5)); - XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), - 2, 3, (frame.button_w - 3), 3); + +#ifdef BITMAPBUTTONS + PixmapMask pm = screen->getWindowStyle()->max_button; + + if (pm.mask != None) { + XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask); + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); + + XFillRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, + (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); + + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 ); + XSetClipMask( blackbox->getXDisplay(), pen.gc(), None ); + } else { +#endif // BITMAPBUTTONS + XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), + 2, 2, (frame.button_w - 5), (frame.button_w - 5)); + XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), + 2, 3, (frame.button_w - 3), 3); +#ifdef BITMAPBUTTONS + } +#endif // BITMAPBUTTONS } @@ -2611,8 +2702,8 @@ void BlackboxWindow::redrawCloseButton(bool pressed) const { if (! pressed) { if (flags.focused) { if (frame.fbutton) - XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button, - frame.fbutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.close_button, frame.fbutton); else XSetWindowBackground(blackbox->getXDisplay(), frame.close_button, frame.fbutton_pixel); @@ -2636,12 +2727,86 @@ void BlackboxWindow::redrawCloseButton(bool pressed) const { BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : screen->getWindowStyle()->b_pic_unfocus); - 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(), - 2, (frame.button_w - 3), (frame.button_w - 3), 2); + +#ifdef BITMAPBUTTONS + PixmapMask pm = screen->getWindowStyle()->close_button; + + if (pm.mask != None) { + XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask); + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); + + XFillRectangle(blackbox->getXDisplay(), frame.close_button, pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, + (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); + + + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 ); + XSetClipMask( blackbox->getXDisplay(), pen.gc(), None ); + } else { +#endif // BITMAPBUTTONS + 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(), + 2, (frame.button_w - 3), (frame.button_w - 3), 2); +#ifdef BITMAPBUTTONS + } +#endif // BITMAPBUTTONS } +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); + +#ifdef BITMAPBUTTONS + PixmapMask pm = screen->getWindowStyle()->stick_button; + + if (pm.mask != None) { + XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask); + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); + + XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(), + (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, + (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); + + + XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 ); + XSetClipMask( blackbox->getXDisplay(), pen.gc(), None ); + } else { +#endif // BITMAPBUTTONS + XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(), + frame.button_w/2 - 1, frame.button_w/2 -1, 2, 2 ); +#ifdef BITMAPBUTTONS + } +#endif +} void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) { if (re->window != client.window) @@ -2656,7 +2821,8 @@ void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) { 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() && + if (! flags.stuck && + blackbox_attrib.workspace != screen->getCurrentWorkspaceID() && blackbox_attrib.workspace < screen->getWorkspaceCount()) if (current_state == NormalState) current_state = WithdrawnState; @@ -2857,6 +3023,8 @@ void BlackboxWindow::exposeEvent(const XExposeEvent *ee) { redrawMaximizeButton(flags.maximized); else if (frame.iconify_button == ee->window) redrawIconifyButton(False); + else if (frame.stick_button == ee->window) + redrawStickyButton(flags.stuck); } @@ -2889,10 +3057,10 @@ void BlackboxWindow::configureRequestEvent(const XConfigureRequestEvent *cr) { frame.margin.top + frame.margin.bottom); /* - if a position change ha been specified, then that position will be used - instead of determining a position based on the window's gravity. + 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)) { + if (! (cr->value_mask & (CWX | CWY))) { Corner corner; switch (client.win_gravity) { case NorthEastGravity: @@ -2950,6 +3118,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { 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(); @@ -2973,7 +3143,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { 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 || @@ -3021,7 +3192,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { 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 @@ -3030,7 +3202,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { 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(); } @@ -3058,6 +3231,13 @@ void BlackboxWindow::buttonReleaseEvent(const XButtonEvent *re) { } else { redrawIconifyButton(False); } + } else if (re->window == frame.stick_button && re->button == 1) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(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(frame.button_w)) && (re->y >= 0 && re->y <= static_cast(frame.button_w))) @@ -3184,7 +3364,7 @@ void BlackboxWindow::doWorkspaceWarping(int x_root, int y_root, int &dx) { bool focus = flags.focused; // had focus while moving? int dest_x = x_root; - if (x_root <= 0) { + if (x_root < 0) { dest_x += screen->getRect().width() - 1; dx += screen->getRect().width() - 1; } else { @@ -3714,11 +3894,14 @@ void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) { 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 & 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))) { + frame.handle == me->window || frame.window == me->window || + frame.right_grip == me->window || + frame.left_grip == me->window))) { unsigned int zones = screen->getResizeZones(); Corner corner; @@ -3765,10 +3948,15 @@ void BlackboxWindow::enterNotifyEvent(const XCrossingEvent* ce) { bool success = setInputFocus(); if (success) // if focus succeeded install the colormap installColormap(True); // XXX: shouldnt we honour no install? - } - if (screen->doAutoRaise()) - timer->start(); + /* + We only auto-raise when the window wasn't focused because otherwise + we run into problems with gtk+ drop-down lists. The window ends up + raising over the list. + */ + if (screen->doAutoRaise()) + timer->start(); + } } } @@ -3785,9 +3973,15 @@ void BlackboxWindow::leaveNotifyEvent(const XCrossingEvent*) { #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 @@ -4019,11 +4213,17 @@ void BlackboxWindow::constrain(Corner anchor, 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);