preserve offsets when sending client to screen
for that purpose, move sendToScreen and updateLayer functions from Workspace to Client, keep wrappers BUG: 327361 FIXED-IN: 4.11.6 REVIEW: 114078
This commit is contained in:
parent
c4d014eb8c
commit
3d389961ff
4 changed files with 80 additions and 45 deletions
3
client.h
3
client.h
|
@ -346,6 +346,8 @@ public:
|
|||
void setDesktop(int);
|
||||
void setOnAllDesktops(bool set);
|
||||
|
||||
void sendToScreen(int screen);
|
||||
|
||||
virtual QStringList activities() const;
|
||||
void setOnActivity(const QString &activity, bool enable);
|
||||
void setOnAllActivities(bool set);
|
||||
|
@ -405,6 +407,7 @@ public:
|
|||
virtual Layer layer() const;
|
||||
Layer belongsToLayer() const;
|
||||
void invalidateLayer();
|
||||
void updateLayer();
|
||||
int sessionStackingOrder() const;
|
||||
|
||||
void setModal(bool modal);
|
||||
|
|
63
geometry.cpp
63
geometry.cpp
|
@ -3266,4 +3266,67 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
|||
}
|
||||
}
|
||||
|
||||
void Client::sendToScreen(int newScreen)
|
||||
{
|
||||
newScreen = rules()->checkScreen(newScreen);
|
||||
if (isActive()) {
|
||||
screens()->setCurrent(newScreen);
|
||||
// might impact the layer of a fullscreen window
|
||||
foreach (Client *cc, workspace()->clientList()) {
|
||||
if (cc->isFullScreen() && cc->screen() == newScreen) {
|
||||
cc->updateLayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (screen() == newScreen) // Don't use isOnScreen(), that's true even when only partially
|
||||
return;
|
||||
|
||||
GeometryUpdatesBlocker blocker(this);
|
||||
|
||||
// operating on the maximized / quicktiled window would leave the old geom_restore behind,
|
||||
// so we clear the state first
|
||||
MaximizeMode maxMode = maximizeMode();
|
||||
QuickTileMode qtMode = (QuickTileMode)quick_tile_mode;
|
||||
maximize(MaximizeRestore);
|
||||
setQuickTileMode(QuickTileNone);
|
||||
|
||||
QRect oldScreenArea = workspace()->clientArea(MaximizeArea, this);
|
||||
QRect screenArea = workspace()->clientArea(MaximizeArea, newScreen, desktop());
|
||||
QRect oldGeom = geometry();
|
||||
QRect newGeom = oldGeom;
|
||||
// move the window to have the same relative position to the center of the screen
|
||||
// (i.e. one near the middle of the right edge will also end up near the middle of the right edge)
|
||||
QPoint center = newGeom.center() - oldScreenArea.center();
|
||||
center.setX(center.x() * screenArea.width() / oldScreenArea.width());
|
||||
center.setY(center.y() * screenArea.height() / oldScreenArea.height());
|
||||
center += screenArea.center();
|
||||
newGeom.moveCenter(center);
|
||||
setGeometry(newGeom);
|
||||
// align geom_restore - checkWorkspacePosition operates on it
|
||||
geom_restore = newGeom;
|
||||
|
||||
// If the window was inside the old screen area, explicitly make sure its inside also the new screen area.
|
||||
// Calling checkWorkspacePosition() should ensure that, but when moving to a small screen the window could
|
||||
// be big enough to overlap outside of the new screen area, making struts from other screens come into effect,
|
||||
// which could alter the resulting geometry.
|
||||
if (oldScreenArea.contains(oldGeom))
|
||||
keepInArea(screenArea);
|
||||
checkWorkspacePosition(oldGeom);
|
||||
|
||||
// re-align geom_restore to contrained geometry
|
||||
geom_restore = geometry();
|
||||
|
||||
// finally reset special states
|
||||
// NOTICE that MaximizeRestore/QuickTileNone checks are required.
|
||||
// eg. setting QuickTileNone would break maximization
|
||||
if (maxMode != MaximizeRestore)
|
||||
maximize(maxMode);
|
||||
if (qtMode != QuickTileNone)
|
||||
setQuickTileMode(qtMode);
|
||||
|
||||
ClientList tso = workspace()->ensureStackingOrder(transients());
|
||||
for (ClientList::ConstIterator it = tso.constBegin(), end = tso.constEnd(); it != end; ++it)
|
||||
(*it)->sendToScreen(newScreen);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
23
layers.cpp
23
layers.cpp
|
@ -103,16 +103,8 @@ namespace KWin
|
|||
|
||||
void Workspace::updateClientLayer(Client* c)
|
||||
{
|
||||
if (c == NULL)
|
||||
return;
|
||||
if (c->layer() == c->belongsToLayer())
|
||||
return;
|
||||
StackingUpdatesBlocker blocker(this);
|
||||
c->invalidateLayer(); // invalidate, will be updated when doing restacking
|
||||
for (ClientList::ConstIterator it = c->transients().constBegin();
|
||||
it != c->transients().constEnd();
|
||||
++it)
|
||||
updateClientLayer(*it);
|
||||
if (c)
|
||||
c->updateLayer();
|
||||
}
|
||||
|
||||
void Workspace::updateStackingOrder(bool propagate_new_clients)
|
||||
|
@ -851,6 +843,17 @@ Layer Client::belongsToLayer() const
|
|||
return NormalLayer;
|
||||
}
|
||||
|
||||
void Client::updateLayer()
|
||||
{
|
||||
if (layer() == belongsToLayer())
|
||||
return;
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
invalidateLayer(); // invalidate, will be updated when doing restacking
|
||||
for (ClientList::ConstIterator it = transients().constBegin(),
|
||||
end = transients().constEnd(); it != end; ++it)
|
||||
(*it)->updateLayer();
|
||||
}
|
||||
|
||||
bool rec_checkTransientOnTop(const ClientList &transients, const Client *topmost)
|
||||
{
|
||||
foreach (const Client *transient, transients) {
|
||||
|
|
|
@ -1217,41 +1217,7 @@ bool Workspace::isOnCurrentHead()
|
|||
|
||||
void Workspace::sendClientToScreen(Client* c, int screen)
|
||||
{
|
||||
screen = c->rules()->checkScreen(screen);
|
||||
if (c->isActive()) {
|
||||
screens()->setCurrent(screen);
|
||||
// might impact the layer of a fullscreen window
|
||||
foreach (Client *cc, clientList()) {
|
||||
if (cc->isFullScreen() && cc->screen() == screen) {
|
||||
updateClientLayer(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c->screen() == screen) // Don't use isOnScreen(), that's true even when only partially
|
||||
return;
|
||||
GeometryUpdatesBlocker blocker(c);
|
||||
QRect old_sarea = clientArea(MaximizeArea, c);
|
||||
QRect sarea = clientArea(MaximizeArea, screen, c->desktop());
|
||||
QRect oldgeom = c->geometry();
|
||||
QRect geom = c->geometry();
|
||||
// move the window to have the same relative position to the center of the screen
|
||||
// (i.e. one near the middle of the right edge will also end up near the middle of the right edge)
|
||||
geom.moveCenter(
|
||||
QPoint(( geom.center().x() - old_sarea.center().x()) * sarea.width() / old_sarea.width() + sarea.center().x(),
|
||||
( geom.center().y() - old_sarea.center().y()) * sarea.height() / old_sarea.height() + sarea.center().y()));
|
||||
c->setGeometry( geom );
|
||||
// If the window was inside the old screen area, explicitly make sure its inside also the new screen area.
|
||||
// Calling checkWorkspacePosition() should ensure that, but when moving to a small screen the window could
|
||||
// be big enough to overlap outside of the new screen area, making struts from other screens come into effect,
|
||||
// which could alter the resulting geometry.
|
||||
if( old_sarea.contains( oldgeom ))
|
||||
c->keepInArea( sarea );
|
||||
c->checkWorkspacePosition( oldgeom );
|
||||
ClientList transients_stacking_order = ensureStackingOrder(c->transients());
|
||||
for (ClientList::ConstIterator it = transients_stacking_order.constBegin();
|
||||
it != transients_stacking_order.constEnd();
|
||||
++it)
|
||||
sendClientToScreen(*it, screen);
|
||||
c->sendToScreen(screen);
|
||||
}
|
||||
|
||||
void Workspace::sendPingToWindow(xcb_window_t window, xcb_timestamp_t timestamp)
|
||||
|
|
Loading…
Reference in a new issue