Merge branch 'KDE/4.11'

This commit is contained in:
Thomas Lübking 2014-01-14 22:51:24 +01:00
commit 4bb88df714
11 changed files with 196 additions and 128 deletions

View file

@ -1447,6 +1447,7 @@ void Client::setDesktop(int desktop)
return; return;
int was_desk = desk; int was_desk = desk;
const bool wasOnCurrentDesktop = isOnCurrentDesktop();
desk = desktop; desk = desktop;
info->setDesktop(desktop); info->setDesktop(desktop);
if ((was_desk == NET::OnAllDesktops) != (desktop == NET::OnAllDesktops)) { if ((was_desk == NET::OnAllDesktops) != (desktop == NET::OnAllDesktops)) {
@ -1476,6 +1477,8 @@ void Client::setDesktop(int desktop)
if (tabGroup()) if (tabGroup())
tabGroup()->updateStates(this, TabGroup::Desktop); tabGroup()->updateStates(this, TabGroup::Desktop);
emit desktopChanged(); emit desktopChanged();
if (wasOnCurrentDesktop != isOnCurrentDesktop())
emit desktopPresenceChanged(this, was_desk);
} }
/** /**

View file

@ -340,6 +340,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);
@ -399,6 +401,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);
@ -717,6 +720,7 @@ Q_SIGNALS:
void activeChanged(); void activeChanged();
void captionChanged(); void captionChanged();
void desktopChanged(); void desktopChanged();
void desktopPresenceChanged(KWin::Client*, int); // to be forwarded by Workspace
void fullScreenChanged(); void fullScreenChanged();
void transientChanged(); void transientChanged();
void modalChanged(); void modalChanged();

View file

@ -495,59 +495,75 @@ void LaptopClient::paintEvent( QPaintEvent* )
QPalette g = options()->palette(KDecoration::ColorFrame, isActive()); QPalette g = options()->palette(KDecoration::ColorFrame, isActive());
g.setCurrentColorGroup( QPalette::Active ); g.setCurrentColorGroup( QPalette::Active );
const int borderBottom = layoutMetric(LM_BorderBottom);
const int borderLeft = layoutMetric(LM_BorderLeft);
const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
QRect r(widget()->rect()); QRect r(widget()->rect());
p.setPen(Qt::black);
p.drawRect(r.adjusted(0, 0, -1, -1));
// fill mid frame... // fill mid frame...
p.setPen(g.background().color()); p.setPen(g.background().color());
p.drawRect(r.adjusted(0,0,-1,-1));
p.drawLine(r.x()+2, r.y()+2, r.right()-2, r.y()+2); p.drawLine(r.x()+2, r.y()+2, r.right()-2, r.y()+2);
p.drawLine(r.left()+2, r.y()+3, r.left()+2, r.bottom()-layoutMetric(LM_BorderBottom)+1); const int boff = borderBottom ? borderBottom - 1 : 1;
p.drawLine(r.right()-2, r.y()+3, r.right()-2, r.bottom()-layoutMetric(LM_BorderBottom)+1); p.drawLine(r.left()+2, r.y()+3, r.left()+2, r.bottom() - boff);
p.drawLine(r.right()-2, r.y()+3, r.right()-2, r.bottom() - boff);
p.drawLine(r.left()+3, r.y()+3, r.left()+3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) ); p.drawLine(r.left()+3, r.y()+3, r.left()+3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) );
p.drawLine(r.right()-3, r.y()+3, r.right()-3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) ); p.drawLine(r.right()-3, r.y()+3, r.right()-3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) );
if (!mustDrawHandle() ) if (borderBottom)
p.drawLine(r.left()+1, r.bottom()-2, r.right()-1, r.bottom()-2); p.drawLine(r.left()+1, r.bottom()-2, r.right()-1, r.bottom()-2);
// outer frame // outer frame
p.setPen(g.color(QPalette::Light)); if (borderBottom)
p.setPen(g.color(QPalette::Light));
p.drawLine(r.x()+1, r.y()+1, r.right()-1, r.y()+1); p.drawLine(r.x()+1, r.y()+1, r.right()-1, r.y()+1);
p.drawLine(r.x()+1, r.y()+1, r.x()+1, r.bottom()-1); p.drawLine(r.x()+1, r.y()+1, r.x()+1, r.bottom()-1);
p.setPen(g.dark().color()); if (borderBottom)
p.setPen(g.dark().color());
p.drawLine(r.right()-1, r.y()+1, r.right()-1, r.bottom()-1); p.drawLine(r.right()-1, r.y()+1, r.right()-1, r.bottom()-1);
p.drawLine(r.x()+1, r.bottom()-1, r.right()-1, r.bottom()-1); p.drawLine(r.x()+1, r.bottom()-1, r.right()-1, r.bottom()-1);
int th = titleHeight; int th = titleHeight;
int bb = handleSize + 2; // Bottom border int bb = handleSize + 2; // Bottom border
int bs = handleSize - 2; // inner size of bottom border int bs = handleSize - 2; // inner size of bottom border
int tb = layoutMetric(LM_TitleEdgeTop, false, NULL); // top border
int sb = layoutMetric(LM_BorderRight, false, NULL) - 1; // side border
if (!mustDrawHandle()) { if (!mustDrawHandle()) {
bb = 6; bb = borderBottom + 2;
bs = 0; bs = 0;
} }
if ( isToolWindow() ) if ( isToolWindow() )
th -= 2; th -= 2;
// inner rect // inner rect
p.drawRect(r.x() + 3, r.y() + th + 3, r.width() - 7, r.height() - th - bb - 1); p.drawRect(r.x() + sb, r.y() + th + tb, r.width() - (2*sb + 1), r.height() - (th + bb + 1));
p.setPen(Qt::black);
if (titleEdgeTop)
p.drawLine(r.topLeft(), r.topRight());
if (borderBottom)
p.drawLine(r.bottomLeft(), r.bottomRight());
if (borderLeft) {
p.drawLine(r.topLeft(), r.bottomLeft());
p.drawLine(r.topRight(), r.bottomRight());
}
// handles // handles
if (mustDrawHandle()) { if (mustDrawHandle()) {
if (r.width() > 3*handleSize + 20) { if (r.width() > 3*handleSize + 20) {
int range = 8 + 3*handleSize/2; int range = 8 + 3*handleSize/2;
qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range, qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range,
handleSize - 2, g, false, 1, &g.brush(QPalette::Mid)); handleSize - 2, g, false, 1, &g.brush(QPalette::Mid));
qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs, qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs,
r.width() - 2*range - 2, handleSize - 2, g, false, 1, r.width() - 2*range - 2, handleSize - 2, g, false, 1,
isActive() ? &g.brush(QPalette::Background) : isActive() ? &g.brush(QPalette::Background) : &g.brush(QPalette::Mid));
&g.brush(QPalette::Mid)); qDrawShadePanel(&p, r.right() - range, r.bottom() - bs,
qDrawShadePanel(&p, r.right() - range, r.bottom() - bs, range, bs, g, false, 1, &g.brush(QPalette::Mid));
range, bs, g, false, 1, &g.brush(QPalette::Mid)); } else {
} else { qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs,
qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, r.width() - 2, bs, g, false, 1,
r.width() - 2, bs, g, false, 1, isActive() ? &g.brush(QPalette::Background) : &g.brush(QPalette::Mid));
isActive() ? &g.brush(QPalette::Background) : }
&g.brush(QPalette::Mid));
}
} }
r = titleRect(); r = titleRect();
@ -621,12 +637,7 @@ QRegion LaptopClient::cornerShape(WindowCorner corner)
bool LaptopClient::mustDrawHandle() const bool LaptopClient::mustDrawHandle() const
{ {
bool drawSmallBorders = !options()->moveResizeMaximizedWindows(); return isResizable() && !(maximizeMode() & MaximizeVertical);
if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
return false;
} else {
return isResizable();
}
} }
void LaptopClient::updateActiveBuffer( ) void LaptopClient::updateActiveBuffer( )
@ -635,7 +646,7 @@ void LaptopClient::updateActiveBuffer( )
if( !bufferDirty && (lastBufferWidth == rTitle.width())) if( !bufferDirty && (lastBufferWidth == rTitle.width()))
return; return;
if ( rTitle.width() <= 0 || rTitle.height() <= 0 ) if ( rTitle.width() <= 0 || rTitle.height() <= 0 )
return; return;
lastBufferWidth = rTitle.width(); lastBufferWidth = rTitle.width();
bufferDirty = false; bufferDirty = false;

View file

@ -221,6 +221,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
Workspace *ws = Workspace::self(); Workspace *ws = Workspace::self();
VirtualDesktopManager *vds = VirtualDesktopManager::self(); VirtualDesktopManager *vds = VirtualDesktopManager::self();
connect(ws, SIGNAL(currentDesktopChanged(int,KWin::Client*)), SLOT(slotDesktopChanged(int,KWin::Client*))); connect(ws, SIGNAL(currentDesktopChanged(int,KWin::Client*)), SLOT(slotDesktopChanged(int,KWin::Client*)));
connect(ws, SIGNAL(desktopPresenceChanged(KWin::Client*,int)), SLOT(slotDesktopPresenceChanged(KWin::Client*,int)));
connect(ws, SIGNAL(clientAdded(KWin::Client*)), this, SLOT(slotClientAdded(KWin::Client*))); connect(ws, SIGNAL(clientAdded(KWin::Client*)), this, SLOT(slotClientAdded(KWin::Client*)));
connect(ws, SIGNAL(unmanagedAdded(KWin::Unmanaged*)), this, SLOT(slotUnmanagedAdded(KWin::Unmanaged*))); connect(ws, SIGNAL(unmanagedAdded(KWin::Unmanaged*)), this, SLOT(slotUnmanagedAdded(KWin::Unmanaged*)));
connect(ws, SIGNAL(clientActivated(KWin::Client*)), this, SLOT(slotClientActivated(KWin::Client*))); connect(ws, SIGNAL(clientActivated(KWin::Client*)), this, SLOT(slotClientActivated(KWin::Client*)));
@ -650,6 +651,11 @@ void EffectsHandlerImpl::slotDesktopChanged(int old, Client *c)
} }
} }
void EffectsHandlerImpl::slotDesktopPresenceChanged(Client *c, int old)
{
emit desktopPresenceChanged(c->effectWindow(), old, c->desktop());
}
void EffectsHandlerImpl::slotWindowDamaged(Toplevel* t, const QRect& r) void EffectsHandlerImpl::slotWindowDamaged(Toplevel* t, const QRect& r)
{ {
if (!t->effectWindow()) { if (!t->effectWindow()) {

View file

@ -223,6 +223,7 @@ public Q_SLOTS:
protected Q_SLOTS: protected Q_SLOTS:
void slotDesktopChanged(int old, KWin::Client *withClient); void slotDesktopChanged(int old, KWin::Client *withClient);
void slotDesktopPresenceChanged(KWin::Client *c, int old);
void slotClientAdded(KWin::Client *c); void slotClientAdded(KWin::Client *c);
void slotClientShown(KWin::Toplevel*); void slotClientShown(KWin::Toplevel*);
void slotUnmanagedAdded(KWin::Unmanaged *u); void slotUnmanagedAdded(KWin::Unmanaged *u);

View file

@ -104,7 +104,7 @@ var dialogParentEffect = {
windows = effects.stackingOrder; windows = effects.stackingOrder;
for (i = 0; i < windows.length; i += 1) { for (i = 0; i < windows.length; i += 1) {
window = windows[i]; window = windows[i];
dialogParentEffect.cancelAnimation(window); dialogParentEffect.cancelAnimation(window);
dialogParentEffect.restartAnimation(window); dialogParentEffect.restartAnimation(window);
} }
}, },
@ -131,6 +131,8 @@ var dialogParentEffect = {
effects.windowUnminimized.connect(dialogParentEffect.restartAnimation); effects.windowUnminimized.connect(dialogParentEffect.restartAnimation);
effects.windowModalityChanged.connect(dialogParentEffect.modalDialogChanged) effects.windowModalityChanged.connect(dialogParentEffect.modalDialogChanged)
effects['desktopChanged(int,int)'].connect(dialogParentEffect.desktopChanged); effects['desktopChanged(int,int)'].connect(dialogParentEffect.desktopChanged);
effects.desktopPresenceChanged.connect(dialogParentEffect.cancelAnimation);
effects.desktopPresenceChanged.connect(dialogParentEffect.restartAnimation);
// start animation // start animation
windows = effects.stackingOrder; windows = effects.stackingOrder;

View file

@ -239,6 +239,8 @@ var translucencyEffect = {
init: function () { init: function () {
"use strict"; "use strict";
effect.configChanged.connect(translucencyEffect.loadConfig); effect.configChanged.connect(translucencyEffect.loadConfig);
effects.desktopPresenceChanged.connect(translucencyEffect.cancelAnimations);
effects.desktopPresenceChanged.connect(translucencyEffect.startAnimation);
effects.windowAdded.connect(translucencyEffect.startAnimation); effects.windowAdded.connect(translucencyEffect.startAnimation);
effects.windowUnminimized.connect(translucencyEffect.startAnimation); effects.windowUnminimized.connect(translucencyEffect.startAnimation);
effects.windowClosed.connect(translucencyEffect.cancelAnimations); effects.windowClosed.connect(translucencyEffect.cancelAnimations);

View file

@ -2331,6 +2331,7 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust)
if (!clientArea.contains(geom_restore.center())) // Not restoring to the same screen if (!clientArea.contains(geom_restore.center())) // Not restoring to the same screen
Placement::self()->place(this, clientArea); Placement::self()->place(this, clientArea);
info->setState(0, NET::Max); info->setState(0, NET::Max);
quick_tile_mode = QuickTileNone;
break; break;
} }
@ -2788,11 +2789,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int y_root)
// When doing a restricted move we must always keep 100px of the titlebar // When doing a restricted move we must always keep 100px of the titlebar
// visible to allow the user to be able to move it again. // visible to allow the user to be able to move it again.
int frameLeft, frameRight, frameTop, frameBottom; const int frameTop = border_top;
if (decoration)
decoration->borders(frameLeft, frameRight, frameTop, frameBottom);
else
frameTop = 10;
int titlebarArea = qMin(frameTop * 100, moveResizeGeom.width() * moveResizeGeom.height()); int titlebarArea = qMin(frameTop * 100, moveResizeGeom.width() * moveResizeGeom.height());
bool update = false; bool update = false;
@ -3123,14 +3120,12 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
if (!isResizable() && maximizeMode() != MaximizeFull) if (!isResizable() && maximizeMode() != MaximizeFull)
return; return;
if (mode == QuickTileMaximize) if (mode == QuickTileMaximize) {
{
TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry|TabGroup::Maximized); TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry|TabGroup::Maximized);
quick_tile_mode = QuickTileNone; quick_tile_mode = QuickTileNone;
if (maximizeMode() == MaximizeFull) if (maximizeMode() == MaximizeFull) {
setMaximize(false, false); setMaximize(false, false);
else } else {
{
setMaximize(true, true); setMaximize(true, true);
QRect clientArea = workspace()->clientArea(MaximizeArea, this); QRect clientArea = workspace()->clientArea(MaximizeArea, this);
if (geometry().top() != clientArea.top()) { if (geometry().top() != clientArea.top()) {
@ -3171,27 +3166,13 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
return; return;
} }
// First, check if the requested tile negates the tile we're in now: move right when left or left when right if (mode != QuickTileNone) {
// is the same as explicitly untiling this window, so allow it.
if (mode == QuickTileNone || ((quick_tile_mode & QuickTileHorizontal) && (mode & QuickTileHorizontal))) {
TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry);
quick_tile_mode = QuickTileNone;
// Untiling, so just restore geometry, and we're done.
if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement
geom_restore = geometry();
// decorations may turn off some borders when tiled
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
setGeometry(geom_restore, geom_mode);
checkWorkspacePosition(); // Just in case it's a different screen
return;
} else {
TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry); TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry);
QPoint whichScreen = keyboard ? geometry().center() : cursorPos(); QPoint whichScreen = keyboard ? geometry().center() : cursorPos();
// If trying to tile to the side that the window is already tiled to move the window to the next // If trying to tile to the side that the window is already tiled to move the window to the next
// screen if it exists, otherwise ignore the request to prevent corrupting geom_restore. // screen if it exists, otherwise toggle the mode (set QuickTileNone)
if (quick_tile_mode == mode) { if (quick_tile_mode == mode) {
const int numScreens = screens()->count(); const int numScreens = screens()->count();
const int curScreen = screen(); const int curScreen = screen();
@ -3200,32 +3181,37 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
for (int i = 0; i < numScreens; ++i) // Cache for (int i = 0; i < numScreens; ++i) // Cache
screens[i] = Screens::self()->geometry(i); screens[i] = Screens::self()->geometry(i);
for (int i = 0; i < numScreens; ++i) { for (int i = 0; i < numScreens; ++i) {
if (i == curScreen) if (i == curScreen)
continue; continue;
if (((mode == QuickTileLeft &&
screens[i].center().x() < screens[nextScreen].center().x()) || if (screens[i].bottom() <= screens[curScreen].top() || screens[i].top() >= screens[curScreen].bottom())
(mode == QuickTileRight && continue; // not in horizontal line
screens[i].center().x() > screens[nextScreen].center().x())) &&
// Must be in horizontal line const int x = screens[i].center().x();
(screens[i].bottom() > screens[nextScreen].top() || if ((mode & QuickTileHorizontal) == QuickTileLeft) {
screens[i].top() < screens[nextScreen].bottom())) if (x >= screens[curScreen].center().x() || (curScreen != nextScreen && x <= screens[nextScreen].center().x()))
nextScreen = i; continue; // not left of current or more left then found next
} else if ((mode & QuickTileHorizontal) == QuickTileRight) {
if (x <= screens[curScreen].center().x() || (curScreen != nextScreen && x >= screens[nextScreen].center().x()))
continue; // not right of current or more right then found next
}
nextScreen = i;
} }
if (nextScreen == curScreen)
return; // No other screens
// Move to other screen if (nextScreen == curScreen) {
geom_restore.translate( mode = QuickTileNone; // No other screens, toggle tiling
screens[nextScreen].x() - screens[curScreen].x(), } else {
screens[nextScreen].y() - screens[curScreen].y()); // Move to other screen
whichScreen = screens[nextScreen].center(); geom_restore.translate(screens[nextScreen].topLeft() - screens[curScreen].topLeft());
whichScreen = screens[nextScreen].center();
// Swap sides // Swap sides
if (mode == QuickTileLeft) mode = ~mode & QuickTileHorizontal;
mode = QuickTileRight; }
else setElectricBorderMode(mode); // used by ::electricBorderMaximizeGeometry(.)
mode = QuickTileLeft; } else if (quick_tile_mode == QuickTileNone) {
} else {
// Not coming out of an existing tile, not shifting monitors, we're setting a brand new tile. // Not coming out of an existing tile, not shifting monitors, we're setting a brand new tile.
// Store geometry first, so we can go out of this tile later. // Store geometry first, so we can go out of this tile later.
geom_restore = geometry(); geom_restore = geometry();
@ -3243,6 +3229,82 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
// Store the mode change // Store the mode change
quick_tile_mode = mode; quick_tile_mode = mode;
} }
if (mode == QuickTileNone) {
TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry);
quick_tile_mode = QuickTileNone;
// Untiling, so just restore geometry, and we're done.
if (!geom_restore.isValid()) // invalid if we started maximized and wait for placement
geom_restore = geometry();
// decorations may turn off some borders when tiled
const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? ForceGeometrySet : NormalGeometrySet;
setGeometry(geom_restore, geom_mode);
checkWorkspacePosition(); // Just in case it's a different screen
}
}
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

View file

@ -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)
@ -848,6 +840,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) {

View file

@ -1030,6 +1030,15 @@ Q_SIGNALS:
* @deprecated * @deprecated
*/ */
void desktopChanged(int oldDesktop, int newDesktop); void desktopChanged(int oldDesktop, int newDesktop);
/**
* Signal emitted when a window moved to another desktop
* NOTICE that this does NOT imply that the desktop has changed
* The @param window which is moved to the new desktop
* @param oldDesktop The previous desktop of the window
* @param newDesktop The new desktop of the window
* @since 4.11.4
*/
void desktopPresenceChanged(KWin::EffectWindow *window, int oldDesktop, int newDesktop);
/** /**
* Signal emitted when the number of currently existing desktops is changed. * Signal emitted when the number of currently existing desktops is changed.
* @param old The previous number of desktops in used. * @param old The previous number of desktops in used.

View file

@ -493,6 +493,7 @@ Client* Workspace::createClient(xcb_window_t w, bool is_mapped)
#ifdef KWIN_BUILD_SCREENEDGES #ifdef KWIN_BUILD_SCREENEDGES
connect(c, SIGNAL(clientFullScreenSet(KWin::Client*,bool,bool)), ScreenEdges::self(), SIGNAL(checkBlocking())); connect(c, SIGNAL(clientFullScreenSet(KWin::Client*,bool,bool)), ScreenEdges::self(), SIGNAL(checkBlocking()));
#endif #endif
connect(c, SIGNAL(desktopPresenceChanged(KWin::Client*,int)), SIGNAL(desktopPresenceChanged(KWin::Client*,int)), Qt::QueuedConnection);
if (!c->manage(w, is_mapped)) { if (!c->manage(w, is_mapped)) {
Client::deleteClient(c); Client::deleteClient(c);
return NULL; return NULL;
@ -1168,8 +1169,6 @@ void Workspace::sendClientToDesktop(Client* c, int desk, bool dont_activate)
return; return;
desk = c->desktop(); // Client did range checking desk = c->desktop(); // Client did range checking
emit desktopPresenceChanged(c, old_desktop);
if (c->isOnDesktop(VirtualDesktopManager::self()->current())) { if (c->isOnDesktop(VirtualDesktopManager::self()->current())) {
if (c->wantsTabFocus() && options->focusPolicyIsReasonable() && if (c->wantsTabFocus() && options->focusPolicyIsReasonable() &&
!was_on_desktop && // for stickyness changes !was_on_desktop && // for stickyness changes
@ -1220,41 +1219,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)