From 3460d5b551203d3c0d1378b5b5ab031eede0e3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Sat, 25 Aug 2012 18:20:34 +0200 Subject: [PATCH] fix untabbing position the geometry setting needs to happen out of recursion, has to be smarter for unmaximizing and also no real place in TabGroup - the client is no longer tabbed thus it's not the groups task to manage it's geometry. BUG: 226881 REVIEW: 106182 FIXED-IN: 4.9.1 --- client.cpp | 26 +++++++++++++++++++++++++- placement.cpp | 19 ++++++++++++------- tabgroup.cpp | 12 ++---------- tabgroup.h | 2 +- useractions.cpp | 5 ++--- workspace.h | 2 ++ 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/client.cpp b/client.cpp index 48e797d303..0b72051335 100644 --- a/client.cpp +++ b/client.cpp @@ -1940,11 +1940,35 @@ bool Client::tabTo(Client *other, bool behind, bool activate) bool Client::untab(const QRect &toGeometry) { TabGroup *group = tab_group; - if (group && group->remove(this, toGeometry)) { // remove sets the tabgroup to "0", therefore the pointer is cached + if (group && group->remove(this)) { // remove sets the tabgroup to "0", therefore the pointer is cached if (group->isEmpty()) { delete group; } setClientShown(!(isMinimized() || isShade())); + bool keepSize = toGeometry.size() == size(); + bool changedSize = false; + if (quickTileMode() != QuickTileNone) { + changedSize = true; + setQuickTileMode(QuickTileNone); // if we leave a quicktiled group, assume that the user wants to untile + } + if (toGeometry.isValid()) { + if (maximizeMode() != Client::MaximizeRestore) { + changedSize = true; + maximize(Client::MaximizeRestore); // explicitly calling for a geometry -> unmaximize + } + if (keepSize && changedSize) { + geom_restore = geometry(); // checkWorkspacePosition() invokes it + QPoint cpoint = QCursor::pos(); + QPoint point = cpoint; + point.setX((point.x() - toGeometry.x()) * geom_restore.width() / toGeometry.width()); + point.setY((point.y() - toGeometry.y()) * geom_restore.height() / toGeometry.height()); + geom_restore.moveTo(cpoint-point); + } else { + geom_restore = toGeometry; // checkWorkspacePosition() invokes it + } + setGeometry(geom_restore); + checkWorkspacePosition(); + } return true; } return false; diff --git a/placement.cpp b/placement.cpp index f091d9d088..d5ad358016 100644 --- a/placement.cpp +++ b/placement.cpp @@ -319,6 +319,12 @@ void Placement::reinitCascading(int desktop) } } +QPoint Workspace::cascadeOffset(const Client *c) const +{ + QRect area = clientArea(PlacementArea, c->geometry().center(), c->desktop()); + return QPoint(area.width()/48, area.height()/48); +} + /*! Place windows in a cascading order, remembering positions for each desktop */ @@ -330,8 +336,7 @@ void Placement::placeCascaded(Client* c, QRect& area, Policy nextPlacement) int xp, yp; //CT how do I get from the 'Client' class the size that NW squarish "handle" - const int delta_x = 24; - const int delta_y = 24; + const QPoint delta = m_WorkspacePtr->cascadeOffset(c); const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1); @@ -375,16 +380,16 @@ void Placement::placeCascaded(Client* c, QRect& area, Policy nextPlacement) * egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine. * 22-Dec-1999 CS * - * if (xp != X && yp == Y) xp = delta_x * (++(cci[dn].col)); - * if (yp != Y && xp == X) yp = delta_y * (++(cci[dn].row)); + * if (xp != X && yp == Y) xp = delta.x() * (++(cci[dn].col)); + * if (yp != Y && xp == X) yp = delta.y() * (++(cci[dn].row)); */ if (xp != X && yp == Y) { ++(cci[dn].col); - xp = delta_x * cci[dn].col; + xp = delta.x() * cci[dn].col; } if (yp != Y && xp == X) { ++(cci[dn].row); - yp = delta_y * cci[dn].row; + yp = delta.y() * cci[dn].row; } // last resort: if still doesn't fit, smart place it @@ -398,7 +403,7 @@ void Placement::placeCascaded(Client* c, QRect& area, Policy nextPlacement) c->move(QPoint(xp, yp)); // new position - cci[dn].pos = QPoint(xp + delta_x, yp + delta_y); + cci[dn].pos = QPoint(xp + delta.x(), yp + delta.y()); } /*! diff --git a/tabgroup.cpp b/tabgroup.cpp index 771d789954..6109f9fa27 100644 --- a/tabgroup.cpp +++ b/tabgroup.cpp @@ -144,7 +144,7 @@ bool TabGroup::add(Client* c, Client *other, bool after, bool becomeVisible) return true; } -bool TabGroup::remove(Client* c, const QRect& newGeom) +bool TabGroup::remove(Client* c) { if (!c) return false; @@ -159,7 +159,7 @@ bool TabGroup::remove(Client* c, const QRect& newGeom) updateMinMaxSize(); if (m_clients.count() == 1) { // split - remove(m_clients.at(0), m_clients.at(0)->geometry()); + remove(m_clients.at(0)); } if (m_clients.isEmpty()) { // remaining singleton "tab" c->setClientShown(true); @@ -174,14 +174,6 @@ bool TabGroup::remove(Client* c, const QRect& newGeom) static_cast(effects)->slotCurrentTabAboutToChange(c->effectWindow(), m_current->effectWindow()); } - if (c->quickTileMode() != QuickTileNone) - c->setQuickTileMode(QuickTileNone); // if we leave a quicktiled group, assume that the user wants to untile - else if (newGeom.isValid()) { - c->maximize(Client::MaximizeRestore); // explicitly calling for a geometry -> unmaximize - in doubt - c->setGeometry(newGeom); - c->checkWorkspacePosition(); // oxygen has now twice kicked me a window out of the screen - better be safe then sorry - } - // Notify effects of removal if (effects) static_cast(effects)->slotTabRemoved(c->effectWindow(), m_current->effectWindow()); diff --git a/tabgroup.h b/tabgroup.h index 3ad0a08280..96329b1fa9 100644 --- a/tabgroup.h +++ b/tabgroup.h @@ -157,7 +157,7 @@ private: void move(KWin::Client* c, KWin::Client* before, bool behind); // friend bool Client::untab(const QRect&); - bool remove(KWin::Client *c, const QRect &newGeom = QRect()); + bool remove(KWin::Client *c); ClientList m_clients; Client *m_current; diff --git a/useractions.cpp b/useractions.cpp index deb6507675..9a9d159901 100755 --- a/useractions.cpp +++ b/useractions.cpp @@ -766,8 +766,7 @@ void Workspace::performWindowOperation(Client* c, Options::WindowOperation op) case Options::NoOp: break; case Options::RemoveTabFromGroupOp: - if (c->untab()) - if (options->focusPolicyIsReasonable()) + if (c->untab(c->geometry().translated(cascadeOffset(c))) && options->focusPolicyIsReasonable()) takeActivity(c, ActivityFocus | ActivityRaise, true); break; case Options::ActivateNextTabOp: @@ -1424,7 +1423,7 @@ void Workspace::slotActivatePrevTab() void Workspace::slotUntab() { if (active_client) - active_client->untab(); + active_client->untab(active_client->geometry().translated(cascadeOffset(active_client))); } /*! diff --git a/workspace.h b/workspace.h index 1fa0c20f98..fefe9acb8f 100644 --- a/workspace.h +++ b/workspace.h @@ -301,6 +301,8 @@ public: */ int desktopToLeft(int id = 0, bool wrap = true) const; + QPoint cascadeOffset(const Client *c) const; + private: int desktopCount_; QSize desktopGridSize_;