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

View file

@ -340,6 +340,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);
@ -399,6 +401,7 @@ public:
virtual Layer layer() const;
Layer belongsToLayer() const;
void invalidateLayer();
void updateLayer();
int sessionStackingOrder() const;
void setModal(bool modal);
@ -717,6 +720,7 @@ Q_SIGNALS:
void activeChanged();
void captionChanged();
void desktopChanged();
void desktopPresenceChanged(KWin::Client*, int); // to be forwarded by Workspace
void fullScreenChanged();
void transientChanged();
void modalChanged();

View file

@ -495,59 +495,75 @@ void LaptopClient::paintEvent( QPaintEvent* )
QPalette g = options()->palette(KDecoration::ColorFrame, isActive());
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());
p.setPen(Qt::black);
p.drawRect(r.adjusted(0, 0, -1, -1));
// fill mid frame...
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.left()+2, r.y()+3, r.left()+2, r.bottom()-layoutMetric(LM_BorderBottom)+1);
p.drawLine(r.right()-2, r.y()+3, r.right()-2, r.bottom()-layoutMetric(LM_BorderBottom)+1);
const int boff = borderBottom ? borderBottom - 1 : 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.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);
// 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.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.x()+1, r.bottom()-1, r.right()-1, r.bottom()-1);
int th = titleHeight;
int bb = handleSize + 2; // 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()) {
bb = 6;
bs = 0;
bb = borderBottom + 2;
bs = 0;
}
if ( isToolWindow() )
th -= 2;
th -= 2;
// 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
if (mustDrawHandle()) {
if (r.width() > 3*handleSize + 20) {
int range = 8 + 3*handleSize/2;
qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range,
if (r.width() > 3*handleSize + 20) {
int range = 8 + 3*handleSize/2;
qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range,
handleSize - 2, g, false, 1, &g.brush(QPalette::Mid));
qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs,
r.width() - 2*range - 2, handleSize - 2, g, false, 1,
isActive() ? &g.brush(QPalette::Background) :
&g.brush(QPalette::Mid));
qDrawShadePanel(&p, r.right() - range, r.bottom() - bs,
range, bs, g, false, 1, &g.brush(QPalette::Mid));
} else {
qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs,
r.width() - 2, bs, g, false, 1,
isActive() ? &g.brush(QPalette::Background) :
&g.brush(QPalette::Mid));
}
qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs,
r.width() - 2*range - 2, handleSize - 2, g, false, 1,
isActive() ? &g.brush(QPalette::Background) : &g.brush(QPalette::Mid));
qDrawShadePanel(&p, r.right() - range, r.bottom() - bs,
range, bs, g, false, 1, &g.brush(QPalette::Mid));
} else {
qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs,
r.width() - 2, bs, g, false, 1,
isActive() ? &g.brush(QPalette::Background) : &g.brush(QPalette::Mid));
}
}
r = titleRect();
@ -621,12 +637,7 @@ QRegion LaptopClient::cornerShape(WindowCorner corner)
bool LaptopClient::mustDrawHandle() const
{
bool drawSmallBorders = !options()->moveResizeMaximizedWindows();
if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
return false;
} else {
return isResizable();
}
return isResizable() && !(maximizeMode() & MaximizeVertical);
}
void LaptopClient::updateActiveBuffer( )
@ -635,7 +646,7 @@ void LaptopClient::updateActiveBuffer( )
if( !bufferDirty && (lastBufferWidth == rTitle.width()))
return;
if ( rTitle.width() <= 0 || rTitle.height() <= 0 )
return;
return;
lastBufferWidth = rTitle.width();
bufferDirty = false;

View file

@ -221,6 +221,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
Workspace *ws = Workspace::self();
VirtualDesktopManager *vds = VirtualDesktopManager::self();
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(unmanagedAdded(KWin::Unmanaged*)), this, SLOT(slotUnmanagedAdded(KWin::Unmanaged*)));
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)
{
if (!t->effectWindow()) {

View file

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

View file

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

View file

@ -239,6 +239,8 @@ var translucencyEffect = {
init: function () {
"use strict";
effect.configChanged.connect(translucencyEffect.loadConfig);
effects.desktopPresenceChanged.connect(translucencyEffect.cancelAnimations);
effects.desktopPresenceChanged.connect(translucencyEffect.startAnimation);
effects.windowAdded.connect(translucencyEffect.startAnimation);
effects.windowUnminimized.connect(translucencyEffect.startAnimation);
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
Placement::self()->place(this, clientArea);
info->setState(0, NET::Max);
quick_tile_mode = QuickTileNone;
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
// visible to allow the user to be able to move it again.
int frameLeft, frameRight, frameTop, frameBottom;
if (decoration)
decoration->borders(frameLeft, frameRight, frameTop, frameBottom);
else
frameTop = 10;
const int frameTop = border_top;
int titlebarArea = qMin(frameTop * 100, moveResizeGeom.width() * moveResizeGeom.height());
bool update = false;
@ -3123,14 +3120,12 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
if (!isResizable() && maximizeMode() != MaximizeFull)
return;
if (mode == QuickTileMaximize)
{
if (mode == QuickTileMaximize) {
TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry|TabGroup::Maximized);
quick_tile_mode = QuickTileNone;
if (maximizeMode() == MaximizeFull)
if (maximizeMode() == MaximizeFull) {
setMaximize(false, false);
else
{
} else {
setMaximize(true, true);
QRect clientArea = workspace()->clientArea(MaximizeArea, this);
if (geometry().top() != clientArea.top()) {
@ -3171,27 +3166,13 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
return;
}
// First, check if the requested tile negates the tile we're in now: move right when left or left when right
// 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 {
if (mode != QuickTileNone) {
TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry);
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
// 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) {
const int numScreens = screens()->count();
const int curScreen = screen();
@ -3200,32 +3181,37 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
for (int i = 0; i < numScreens; ++i) // Cache
screens[i] = Screens::self()->geometry(i);
for (int i = 0; i < numScreens; ++i) {
if (i == curScreen)
continue;
if (((mode == QuickTileLeft &&
screens[i].center().x() < screens[nextScreen].center().x()) ||
(mode == QuickTileRight &&
screens[i].center().x() > screens[nextScreen].center().x())) &&
// Must be in horizontal line
(screens[i].bottom() > screens[nextScreen].top() ||
screens[i].top() < screens[nextScreen].bottom()))
nextScreen = i;
if (screens[i].bottom() <= screens[curScreen].top() || screens[i].top() >= screens[curScreen].bottom())
continue; // not in horizontal line
const int x = screens[i].center().x();
if ((mode & QuickTileHorizontal) == QuickTileLeft) {
if (x >= screens[curScreen].center().x() || (curScreen != nextScreen && x <= screens[nextScreen].center().x()))
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
geom_restore.translate(
screens[nextScreen].x() - screens[curScreen].x(),
screens[nextScreen].y() - screens[curScreen].y());
whichScreen = screens[nextScreen].center();
if (nextScreen == curScreen) {
mode = QuickTileNone; // No other screens, toggle tiling
} else {
// Move to other screen
geom_restore.translate(screens[nextScreen].topLeft() - screens[curScreen].topLeft());
whichScreen = screens[nextScreen].center();
// Swap sides
if (mode == QuickTileLeft)
mode = QuickTileRight;
else
mode = QuickTileLeft;
} else {
// Swap sides
mode = ~mode & QuickTileHorizontal;
}
setElectricBorderMode(mode); // used by ::electricBorderMaximizeGeometry(.)
} else if (quick_tile_mode == QuickTileNone) {
// 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.
geom_restore = geometry();
@ -3243,6 +3229,82 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard)
// Store the mode change
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

View file

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

View file

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