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 setDesktop(int);
|
||||||
void setOnAllDesktops(bool set);
|
void setOnAllDesktops(bool set);
|
||||||
|
|
||||||
|
void sendToScreen(int screen);
|
||||||
|
|
||||||
virtual QStringList activities() const;
|
virtual QStringList activities() const;
|
||||||
void setOnActivity(const QString &activity, bool enable);
|
void setOnActivity(const QString &activity, bool enable);
|
||||||
void setOnAllActivities(bool set);
|
void setOnAllActivities(bool set);
|
||||||
|
@ -405,6 +407,7 @@ public:
|
||||||
virtual Layer layer() const;
|
virtual Layer layer() const;
|
||||||
Layer belongsToLayer() const;
|
Layer belongsToLayer() const;
|
||||||
void invalidateLayer();
|
void invalidateLayer();
|
||||||
|
void updateLayer();
|
||||||
int sessionStackingOrder() const;
|
int sessionStackingOrder() const;
|
||||||
|
|
||||||
void setModal(bool modal);
|
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
|
} // namespace
|
||||||
|
|
23
layers.cpp
23
layers.cpp
|
@ -103,16 +103,8 @@ namespace KWin
|
||||||
|
|
||||||
void Workspace::updateClientLayer(Client* c)
|
void Workspace::updateClientLayer(Client* c)
|
||||||
{
|
{
|
||||||
if (c == NULL)
|
if (c)
|
||||||
return;
|
c->updateLayer();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::updateStackingOrder(bool propagate_new_clients)
|
void Workspace::updateStackingOrder(bool propagate_new_clients)
|
||||||
|
@ -851,6 +843,17 @@ Layer Client::belongsToLayer() const
|
||||||
return NormalLayer;
|
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)
|
bool rec_checkTransientOnTop(const ClientList &transients, const Client *topmost)
|
||||||
{
|
{
|
||||||
foreach (const Client *transient, transients) {
|
foreach (const Client *transient, transients) {
|
||||||
|
|
|
@ -1217,41 +1217,7 @@ bool Workspace::isOnCurrentHead()
|
||||||
|
|
||||||
void Workspace::sendClientToScreen(Client* c, int screen)
|
void Workspace::sendClientToScreen(Client* c, int screen)
|
||||||
{
|
{
|
||||||
screen = c->rules()->checkScreen(screen);
|
c->sendToScreen(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::sendPingToWindow(xcb_window_t window, xcb_timestamp_t timestamp)
|
void Workspace::sendPingToWindow(xcb_window_t window, xcb_timestamp_t timestamp)
|
||||||
|
|
Loading…
Reference in a new issue