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
This commit is contained in:
Thomas Lübking 2012-08-25 18:20:34 +02:00
parent a6296dda20
commit 3460d5b551
6 changed files with 44 additions and 22 deletions

View file

@ -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;

View file

@ -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());
}
/*!

View file

@ -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<EffectsHandlerImpl*>(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<EffectsHandlerImpl*>(effects)->slotTabRemoved(c->effectWindow(), m_current->effectWindow());

View file

@ -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;

View file

@ -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)));
}
/*!

View file

@ -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_;