diff --git a/activation.cpp b/activation.cpp index d9540593ce..42a264dc41 100644 --- a/activation.cpp +++ b/activation.cpp @@ -403,6 +403,25 @@ static inline bool isUsableFocusCandidate(Client *c, Client *prev, bool respectS (!respectScreen || c->isOnScreen(prev ? prev->screen() : Workspace::self()->activeScreen())); } +Client *Workspace::clientUnderMouse(int screen) const +{ + QList::const_iterator it = stackingOrder().constEnd(); + while (it != stackingOrder().constBegin()) { + Client *client = *(--it); + + // rule out clients which are not really visible. + // the screen test is rather superflous for xrandr & twinview since the geometry would differ -> TODO: might be dropped + if (!(client->isShown(false) && client->isOnCurrentDesktop() && + client->isOnCurrentActivity() && client->isOnScreen(screen))) + continue; + + if (client->geometry().contains(QCursor::pos())) { + return client; + } + } + return 0; +} + // deactivates 'c' and activates next client bool Workspace::activateNextClient(Client* c) { @@ -431,22 +450,10 @@ bool Workspace::activateNextClient(Client* c) Client* get_focus = NULL; if (options->nextFocusPrefersMouse) { - QList::const_iterator it = stackingOrder().constEnd(); - while (it != stackingOrder().constBegin()) { - Client *client = *(--it); - - // rule out clients which are not really visible. - // the screen test is rather superfluous for xrandr & twinview since the geometry would differ -> TODO: might be dropped - if (!(client->isShown(false) && client->isOnCurrentDesktop() && - client->isOnCurrentActivity() && client->isOnScreen(c ? c->screen() : activeScreen()))) - continue; - - if (client->geometry().contains(QCursor::pos())) { - if (client != c && !client->isDesktop()) // should rather not happen, but it cannot get the focus. rest of usability is tested above - get_focus = client; - break; // unconditional break - we do not pass the focus to some client below an unusable one - } - + get_focus = clientUnderMouse(c ? c->screen() : activeScreen()); + if (get_focus && (get_focus == c || get_focus->isDesktop())) { + // should rather not happen, but it cannot get the focus. rest of usability is tested above + get_focus = 0; } } diff --git a/client.cpp b/client.cpp index 34e9006d4a..726b2c97c1 100644 --- a/client.cpp +++ b/client.cpp @@ -818,10 +818,15 @@ void Client::updateShape() noborder = true; updateDecoration(true); } - } - if (shape() && noBorder()) - XShapeCombineShape(display(), frameId(), ShapeBounding, + if (noBorder()) + XShapeCombineShape(display(), frameId(), ShapeBounding, clientPos().x(), clientPos().y(), window(), ShapeBounding, ShapeSet); + } else if (app_noborder) { + XShapeCombineMask(display(), frameId(), ShapeBounding, 0, 0, None, ShapeSet); + detectNoBorder(); + app_noborder = noborder; + updateDecoration(true); + } // Decoration mask (i.e. 'else' here) setting is done in setMask() // when the decoration calls it or when the decoration is created/destroyed diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index 86ab0f5077..db1e86a7a8 100755 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -453,7 +453,7 @@ void PresentWindowsEffect::slotWindowAdded(EffectWindow *w) m_motionManager.manage(w); rearrangeWindows(); } - if (w == effects->findWindow(m_closeView->winId())) { + if (m_closeView && w == effects->findWindow(m_closeView->winId())) { winData->visible = true; winData->highlight = 1.0; m_closeWindow = w; @@ -527,7 +527,7 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e) Q_UNUSED(w); QMouseEvent* me = static_cast< QMouseEvent* >(e); - if (m_closeView->geometry().contains(me->pos())) { + if (m_closeView && m_closeView->geometry().contains(me->pos())) { if (!m_closeView->isVisible()) { updateCloseWindow(); } @@ -557,7 +557,7 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e) } if (m_highlightedWindow && m_motionManager.transformedGeometry(m_highlightedWindow).contains(me->pos())) updateCloseWindow(); - else + else if (m_closeView) m_closeView->hide(); if (e->type() == QEvent::MouseButtonRelease) { @@ -966,7 +966,8 @@ void PresentWindowsEffect::rearrangeWindows() return; effects->addRepaintFull(); // Trigger the first repaint - m_closeView->hide(); + if (m_closeView) + m_closeView->hide(); // Work out which windows are on which screens EffectWindowList windowlist; @@ -1600,8 +1601,10 @@ void PresentWindowsEffect::setActive(bool active, bool closingTab) m_highlightedWindow = NULL; m_windowFilter.clear(); - m_closeView = new CloseWindowView(); - connect(m_closeView, SIGNAL(close()), SLOT(closeWindow())); + if (!m_doNotCloseWindows) { + m_closeView = new CloseWindowView(); + connect(m_closeView, SIGNAL(close()), SLOT(closeWindow())); + } // Add every single window to m_windowData (Just calling [w] creates it) foreach (EffectWindow * w, effects->stackingOrder()) { @@ -1770,7 +1773,7 @@ bool PresentWindowsEffect::isSelectableWindow(EffectWindow *w) return false; if (w->isSkipSwitcher()) return false; - if (w == effects->findWindow(m_closeView->winId())) + if (m_closeView && w == effects->findWindow(m_closeView->winId())) return false; if (m_tabBoxEnabled) return true; diff --git a/geometry.cpp b/geometry.cpp index b4478384ca..fd70beb689 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1591,10 +1591,12 @@ void Client::configureRequest(int value_mask, int rx, int ry, int rw, int rh, in kDebug(1212) << this << bool(value_mask & (CWX|CWWidth|CWY|CWHeight)) << bool(maximizeMode() & MaximizeVertical) << bool(maximizeMode() & MaximizeHorizontal); - if (maximizeMode() & MaximizeVertical) - value_mask &= ~(CWY|CWHeight); // do not allow clients to drop out of vertical ... - if (maximizeMode() & MaximizeHorizontal) - value_mask &= ~(CWX|CWWidth); // .. or horizontal maximization (MaximizeFull == MaximizeVertical|MaximizeHorizontal) + if (!app_noborder) { // + if (maximizeMode() & MaximizeVertical) + value_mask &= ~(CWY|CWHeight); // do not allow clients to drop out of vertical ... + if (maximizeMode() & MaximizeHorizontal) + value_mask &= ~(CWX|CWWidth); // .. or horizontal maximization (MaximizeFull == MaximizeVertical|MaximizeHorizontal) + } if (!(value_mask & (CWX|CWWidth|CWY|CWHeight))) { kDebug(1212) << "DENIED"; return; // nothing to (left) to do for use - bugs #158974, #252314 diff --git a/scene.cpp b/scene.cpp index a2dd25cf18..2af2262cd1 100644 --- a/scene.cpp +++ b/scene.cpp @@ -257,6 +257,7 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region) // This has to be done here because many effects schedule a repaint for // the next frame within Effects::prePaintWindow. topw->resetRepaints(); + // Clip out the decoration for opaque windows; the decoration is drawn in the second pass if (w->isOpaque()) { // the window is fully opaque diff --git a/toplevel.cpp b/toplevel.cpp index f3902ea097..2c91c9c420 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -381,6 +381,7 @@ void Toplevel::getShadow() if (hasShadow()) dirtyRect |= shadow()->shadowRegion().boundingRect(); if (dirtyRect.isValid()) { + resetRepaints(dirtyRect); dirtyRect.translate(pos()); workspace()->addRepaint(dirtyRect); } diff --git a/useractions.cpp b/useractions.cpp index 1eaf3e217f..b5af670e23 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -410,10 +410,8 @@ void Workspace::initDesktopPopup() desk_popup = new QMenu(popup); desk_popup->setFont(KGlobalSettings::menuFont()); - connect(desk_popup, SIGNAL(triggered(QAction*)), - this, SLOT(slotSendToDesktop(QAction*))); - connect(desk_popup, SIGNAL(aboutToShow()), - this, SLOT(desktopPopupAboutToShow())); + connect(desk_popup, SIGNAL(triggered(QAction*)), SLOT(slotSendToDesktop(QAction*))); + connect(desk_popup, SIGNAL(aboutToShow()), SLOT(desktopPopupAboutToShow())); QAction *action = desk_popup->menuAction(); // set it as the first item @@ -618,6 +616,8 @@ void Workspace::clientPopupActivated(QAction *action) WindowOperation op = static_cast< WindowOperation >(action->data().toInt()); Client* c = active_popup_client ? active_popup_client : active_client; + if (!c) + return; QString type; switch(op) { case FullScreenOp: @@ -795,13 +795,17 @@ bool Client::performMouseCommand(Options::MouseCommand command, const QPoint &gl case Options::MouseRaise: workspace()->raiseClient(this); break; - case Options::MouseLower: + case Options::MouseLower: { workspace()->lowerClient(this); - // As this most likely makes the window no longer visible change the - // keyboard focus to the next available window. - //workspace()->activateNextClient( this ); // Doesn't work when we lower a child window - workspace()->activateClient(workspace()->topClientOnDesktop(workspace()->currentDesktop(), -1)); + // used to be activateNextClient(this), then topClientOnDesktop + // since this is a mouseOp it's however safe to use the client under the mouse instead + if (isActive()) { + Client *next = workspace()->clientUnderMouse(screen()); + if (next && next != this) + workspace()->requestFocus(next, false); + } break; + } case Options::MouseShade : toggleShade(); cancelShadeHoverTimer(); @@ -1095,17 +1099,18 @@ void Workspace::slotSwitchToDesktop() setCurrentDesktop(i); } +#define USABLE_ACTIVE_CLIENT (active_client && !(active_client->isDesktop() || active_client->isDock())) void Workspace::slotWindowToDesktop() { - const int i = senderValue(sender()); - if (i < 1) - return; - Client* c = active_popup_client ? active_popup_client : active_client; - if (i >= 1 && i <= numberOfDesktops() && c - && !c->isDesktop() - && !c->isDock()) - sendClientToDesktop(c, i, true); + if (USABLE_ACTIVE_CLIENT) { + const int i = senderValue(sender()); + if (i < 1) + return; + + if (i >= 1 && i <= numberOfDesktops()) + sendClientToDesktop(active_client, i, true); + } } void Workspace::slotSwitchToScreen() @@ -1122,25 +1127,20 @@ void Workspace::slotSwitchToNextScreen() void Workspace::slotWindowToScreen() { - const int i = senderValue(sender()); - if (i < 0) - return; - Client* c = active_popup_client ? active_popup_client : active_client; - if (i >= 0 && i <= numScreens() && c - && !c->isDesktop() - && !c->isDock()) { - sendClientToScreen(c, i); + if (USABLE_ACTIVE_CLIENT) { + const int i = senderValue(sender()); + if (i < 0) + return; + if (i >= 0 && i <= numScreens()) { + sendClientToScreen(active_client, i); + } } } void Workspace::slotWindowToNextScreen() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c - && !c->isDesktop() - && !c->isDock()) { - sendClientToScreen(c, (c->screen() + 1) % numScreens()); - } + if (USABLE_ACTIVE_CLIENT) + sendClientToScreen(active_client, (active_client->screen() + 1) % numScreens()); } /*! @@ -1148,9 +1148,8 @@ void Workspace::slotWindowToNextScreen() */ void Workspace::slotWindowMaximize() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::MaximizeOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::MaximizeOp); } /*! @@ -1158,9 +1157,8 @@ void Workspace::slotWindowMaximize() */ void Workspace::slotWindowMaximizeVertical() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::VMaximizeOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::VMaximizeOp); } /*! @@ -1168,9 +1166,8 @@ void Workspace::slotWindowMaximizeVertical() */ void Workspace::slotWindowMaximizeHorizontal() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::HMaximizeOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::HMaximizeOp); } @@ -1179,8 +1176,8 @@ void Workspace::slotWindowMaximizeHorizontal() */ void Workspace::slotWindowMinimize() { - Client* c = active_popup_client ? active_popup_client : active_client; - performWindowOperation(c, Options::MinimizeOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::MinimizeOp); } /*! @@ -1188,8 +1185,8 @@ void Workspace::slotWindowMinimize() */ void Workspace::slotWindowShade() { - Client* c = active_popup_client ? active_popup_client : active_client; - performWindowOperation(c, Options::ShadeOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::ShadeOp); } /*! @@ -1197,9 +1194,8 @@ void Workspace::slotWindowShade() */ void Workspace::slotWindowRaise() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - raiseClient(c); + if (USABLE_ACTIVE_CLIENT) + raiseClient(active_client); } /*! @@ -1207,13 +1203,13 @@ void Workspace::slotWindowRaise() */ void Workspace::slotWindowLower() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) { - lowerClient(c); + if (USABLE_ACTIVE_CLIENT) { + lowerClient(active_client); // As this most likely makes the window no longer visible change the // keyboard focus to the next available window. //activateNextClient( c ); // Doesn't work when we lower a child window - activateClient(topClientOnDesktop(currentDesktop(), -1)); + if (active_client->isActive()) + activateClient(topClientOnDesktop(currentDesktop(), -1)); } } @@ -1222,50 +1218,43 @@ void Workspace::slotWindowLower() */ void Workspace::slotWindowRaiseOrLower() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - raiseOrLowerClient(c); + if (USABLE_ACTIVE_CLIENT) + raiseOrLowerClient(active_client); } void Workspace::slotWindowOnAllDesktops() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - c->setOnAllDesktops(!c->isOnAllDesktops()); + if (USABLE_ACTIVE_CLIENT) + active_client->setOnAllDesktops(!active_client->isOnAllDesktops()); } void Workspace::slotWindowFullScreen() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::FullScreenOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::FullScreenOp); } void Workspace::slotWindowNoBorder() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::NoBorderOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::NoBorderOp); } void Workspace::slotWindowAbove() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::KeepAboveOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::KeepAboveOp); } void Workspace::slotWindowBelow() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::KeepBelowOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::KeepBelowOp); } void Workspace::slotSetupWindowShortcut() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) - performWindowOperation(c, Options::SetupWindowShortcutOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::SetupWindowShortcutOp); } /*! @@ -1281,7 +1270,8 @@ void Workspace::slotToggleShowDesktop() */ void Workspace::slotWindowToNextDesktop() { - windowToNextDesktop(active_popup_client ? active_popup_client : active_client); + if (USABLE_ACTIVE_CLIENT) + windowToNextDesktop(active_client); } void Workspace::windowToNextDesktop(Client* c) @@ -1302,7 +1292,8 @@ void Workspace::windowToNextDesktop(Client* c) */ void Workspace::slotWindowToPreviousDesktop() { - windowToPreviousDesktop(active_popup_client ? active_popup_client : active_client); + if (USABLE_ACTIVE_CLIENT) + windowToPreviousDesktop(active_client); } void Workspace::windowToPreviousDesktop(Client* c) @@ -1320,13 +1311,12 @@ void Workspace::windowToPreviousDesktop(Client* c) void Workspace::slotWindowToDesktopRight() { - int d = desktopToRight(currentDesktop(), options->rollOverDesktops); - if (d == currentDesktop()) - return; - Client* c = active_popup_client ? active_popup_client : active_client; - if (c && !c->isDesktop() - && !c->isDock()) { - setClientIsMoving(c); + if (USABLE_ACTIVE_CLIENT) { + int d = desktopToRight(currentDesktop(), options->rollOverDesktops); + if (d == currentDesktop()) + return; + + setClientIsMoving(active_client); setCurrentDesktop(d); setClientIsMoving(NULL); } @@ -1334,13 +1324,12 @@ void Workspace::slotWindowToDesktopRight() void Workspace::slotWindowToDesktopLeft() { - int d = desktopToLeft(currentDesktop(), options->rollOverDesktops); - if (d == currentDesktop()) - return; - Client* c = active_popup_client ? active_popup_client : active_client; - if (c && !c->isDesktop() - && !c->isDock()) { - setClientIsMoving(c); + if (USABLE_ACTIVE_CLIENT) { + int d = desktopToLeft(currentDesktop(), options->rollOverDesktops); + if (d == currentDesktop()) + return; + + setClientIsMoving(active_client); setCurrentDesktop(d); setClientIsMoving(NULL); } @@ -1348,13 +1337,12 @@ void Workspace::slotWindowToDesktopLeft() void Workspace::slotWindowToDesktopUp() { - int d = desktopAbove(currentDesktop(), options->rollOverDesktops); - if (d == currentDesktop()) - return; - Client* c = active_popup_client ? active_popup_client : active_client; - if (c && !c->isDesktop() - && !c->isDock()) { - setClientIsMoving(c); + if (USABLE_ACTIVE_CLIENT) { + int d = desktopAbove(currentDesktop(), options->rollOverDesktops); + if (d == currentDesktop()) + return; + + setClientIsMoving(active_client); setCurrentDesktop(d); setClientIsMoving(NULL); } @@ -1362,13 +1350,12 @@ void Workspace::slotWindowToDesktopUp() void Workspace::slotWindowToDesktopDown() { - int d = desktopBelow(currentDesktop(), options->rollOverDesktops); - if (d == currentDesktop()) - return; - Client* c = active_popup_client ? active_popup_client : active_client; - if (c && !c->isDesktop() - && !c->isDock()) { - setClientIsMoving(c); + if (USABLE_ACTIVE_CLIENT) { + int d = desktopBelow(currentDesktop(), options->rollOverDesktops); + if (d == currentDesktop()) + return; + + setClientIsMoving(active_client); setCurrentDesktop(d); setClientIsMoving(NULL); } @@ -1586,8 +1573,8 @@ void Workspace::slotWindowClose() // TODO: why? // if ( tab_box->isVisible()) // return; - Client* c = active_popup_client ? active_popup_client : active_client; - performWindowOperation(c, Options::CloseOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::CloseOp); } /*! @@ -1595,8 +1582,8 @@ void Workspace::slotWindowClose() */ void Workspace::slotWindowMove() { - Client* c = active_popup_client ? active_popup_client : active_client; - performWindowOperation(c, Options::UnrestrictedMoveOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::UnrestrictedMoveOp); } /*! @@ -1604,10 +1591,12 @@ void Workspace::slotWindowMove() */ void Workspace::slotWindowResize() { - Client* c = active_popup_client ? active_popup_client : active_client; - performWindowOperation(c, Options::UnrestrictedResizeOp); + if (USABLE_ACTIVE_CLIENT) + performWindowOperation(active_client, Options::UnrestrictedResizeOp); } +#undef USABLE_ACTIVE_CLIENT + void Client::setShortcut(const QString& _cut) { QString cut = rules()->checkShortcut(_cut); diff --git a/workspace.h b/workspace.h index d9a4ee37fa..cb1c139c42 100644 --- a/workspace.h +++ b/workspace.h @@ -143,6 +143,8 @@ public: */ Client* mostRecentlyActivatedClient() const; + Client* clientUnderMouse(int screen) const; + void activateClient(Client*, bool force = false); void requestFocus(Client* c, bool force = false); void takeActivity(Client* c, int flags, bool handled); // Flags are ActivityFlags