diff --git a/atoms.cpp b/atoms.cpp
index 5e93b2ad91..5ba1930bd4 100644
--- a/atoms.cpp
+++ b/atoms.cpp
@@ -114,6 +114,9 @@ Atoms::Atoms()
atoms[n] = &net_wm_sync_request;
names[n++] = (char*) "_NET_WM_SYNC_REQUEST";
+ atoms[n] = &kde_net_wm_block_compositing;
+ names[n++] = (char*) "_KDE_NET_WM_BLOCK_COMPOSITING";
+
assert(n <= max);
XInternAtoms(display(), names, n, false, atoms_return);
diff --git a/atoms.h b/atoms.h
index 7d5752c2ae..aa6cfed110 100644
--- a/atoms.h
+++ b/atoms.h
@@ -60,6 +60,7 @@ public:
Atom kde_net_wm_frame_strut;
Atom net_wm_sync_request_counter;
Atom net_wm_sync_request;
+ Atom kde_net_wm_block_compositing;
};
diff --git a/client.cpp b/client.cpp
index ec60bde9c7..57e324b631 100644
--- a/client.cpp
+++ b/client.cpp
@@ -95,6 +95,7 @@ Client::Client(Workspace* ws)
, transient_for (NULL)
, transient_for_id(None)
, original_transient_for_id(None)
+ , blocks_compositing(false)
, autoRaiseTimer(NULL)
, shadeHoverTimer(NULL)
, delayedMoveResizeTimer(NULL)
@@ -2110,6 +2111,20 @@ void Client::updateCursor()
cursor.handle(), xTime());
}
+void Client::updateCompositeBlocking(bool readProperty)
+{
+ const bool usedToBlock = blocks_compositing;
+ if (readProperty) {
+ const unsigned long properties[2] = {0, NET::WM2BlockCompositing};
+ NETWinInfo2 i(QX11Info::display(), window(), rootWindow(), properties, 2);
+ blocks_compositing = rules()->checkBlockCompositing(i.isBlockingCompositing());
+ }
+ else
+ blocks_compositing = rules()->checkBlockCompositing(blocks_compositing);
+ if (usedToBlock != blocks_compositing)
+ workspace()->updateCompositeBlocking(blocks_compositing ? this : 0);
+}
+
Client::Position Client::mousePosition(const QPoint& p) const
{
if (decoration != NULL)
diff --git a/client.h b/client.h
index 0d479a0f93..5dd47027fd 100644
--- a/client.h
+++ b/client.h
@@ -295,6 +295,8 @@ public:
virtual void setupCompositing();
virtual void finishCompositing();
+ inline bool isBlockingCompositing() { return blocks_compositing; }
+ void updateCompositeBlocking(bool readProperty = false);
QString caption(bool full = true) const;
void updateCaption();
@@ -647,6 +649,7 @@ private:
uint urgency : 1; ///< XWMHints, UrgencyHint
uint ignore_focus_stealing : 1; ///< Don't apply focus stealing prevention to this client
uint demands_attention : 1;
+ bool blocks_compositing;
WindowRules client_rules;
void getWMHints();
void readIcons();
diff --git a/composite.cpp b/composite.cpp
index 6783d3240b..79a8b3c449 100644
--- a/composite.cpp
+++ b/composite.cpp
@@ -281,6 +281,32 @@ void Workspace::toggleCompositing()
}
}
+void Workspace::updateCompositeBlocking(Client *c)
+{
+ if (c) { // if c == 0 we just check if we can resume
+ if (c->isBlockingCompositing()) {
+ compositingBlocked = true;
+ suspendCompositing(true);
+ }
+ }
+ else if (compositingBlocked) { // lost a client and we're blocked - can we resume?
+ // NOTICE do NOT check for "compositingSuspended" or "!compositing()"
+ // only "resume" if it was really disabled for a block
+ bool resume = true;
+ for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it) {
+ if ((*it)->isBlockingCompositing()) {
+ resume = false;
+ break;
+ }
+ }
+ if (resume) { // do NOT attempt to call suspendCompositing(false); from within the eventchain!
+ compositingBlocked = false;
+ if (compositingSuspended)
+ QMetaObject::invokeMethod(this, "slotToggleCompositing", Qt::QueuedConnection);
+ }
+ }
+}
+
void Workspace::suspendCompositing()
{
suspendCompositing(true);
diff --git a/events.cpp b/events.cpp
index 05cf864c65..0d5dc7c1a9 100644
--- a/events.cpp
+++ b/events.cpp
@@ -870,6 +870,8 @@ void Client::propertyNotifyEvent(XPropertyEvent* e)
getSyncCounter();
else if (e->atom == atoms->activities)
checkActivities();
+ else if (e->atom == atoms->kde_net_wm_block_compositing)
+ updateCompositeBlocking(true);
break;
}
}
diff --git a/kcmkwin/kwinrules/ruleswidget.cpp b/kcmkwin/kwinrules/ruleswidget.cpp
index f9fc4076e8..b9fe8497e5 100644
--- a/kcmkwin/kwinrules/ruleswidget.cpp
+++ b/kcmkwin/kwinrules/ruleswidget.cpp
@@ -115,6 +115,7 @@ RulesWidget::RulesWidget(QWidget* parent)
SETUP(maxsize, force);
SETUP(strictgeometry, force);
SETUP(disableglobalshortcuts, force);
+ SETUP(blockcompositing, force);
int i;
for (i = 1;
i <= KWindowSystem::numberOfDesktops();
@@ -171,6 +172,7 @@ UPDATE_ENABLE_SLOT(minsize)
UPDATE_ENABLE_SLOT(maxsize)
UPDATE_ENABLE_SLOT(strictgeometry)
UPDATE_ENABLE_SLOT(disableglobalshortcuts)
+UPDATE_ENABLE_SLOT(blockcompositing)
#undef UPDATE_ENABLE_SLOT
@@ -450,6 +452,7 @@ void RulesWidget::setRules(Rules* rules)
LINEEDIT_FORCE_RULE(maxsize, sizeToStr);
CHECKBOX_FORCE_RULE(strictgeometry,);
CHECKBOX_FORCE_RULE(disableglobalshortcuts,);
+ CHECKBOX_FORCE_RULE(blockcompositing,);
}
#undef GENERIC_RULE
@@ -544,6 +547,7 @@ Rules* RulesWidget::rules() const
LINEEDIT_FORCE_RULE(maxsize, strToSize);
CHECKBOX_FORCE_RULE(strictgeometry,);
CHECKBOX_FORCE_RULE(disableglobalshortcuts,);
+ CHECKBOX_FORCE_RULE(blockcompositing,);
return rules;
}
@@ -662,6 +666,7 @@ void RulesWidget::prefillUnusedValues(const KWindowInfo& info)
LINEEDIT_PREFILL(maxsize, sizeToStr, info.frameGeometry().size());
//CHECKBOX_PREFILL( strictgeometry, );
//CHECKBOX_PREFILL( disableglobalshortcuts, );
+ //CHECKBOX_PREFILL( blockcompositing, );
}
#undef GENERIC_PREFILL
diff --git a/kcmkwin/kwinrules/ruleswidget.h b/kcmkwin/kwinrules/ruleswidget.h
index ca44bf2c7b..6972e523d6 100644
--- a/kcmkwin/kwinrules/ruleswidget.h
+++ b/kcmkwin/kwinrules/ruleswidget.h
@@ -89,6 +89,7 @@ private slots:
void updateEnablestrictgeometry();
void updateEnableshortcut();
void updateEnabledisableglobalshortcuts();
+ void updateEnableblockcompositing();
// internal
void detected(bool);
private:
diff --git a/kcmkwin/kwinrules/ruleswidgetbase.ui b/kcmkwin/kwinrules/ruleswidgetbase.ui
index 74ac56b6f2..84e05c08dc 100644
--- a/kcmkwin/kwinrules/ruleswidgetbase.ui
+++ b/kcmkwin/kwinrules/ruleswidgetbase.ui
@@ -1792,7 +1792,7 @@
W&orkarounds
-
+
-
@@ -1800,6 +1800,113 @@
+ -
+
+
+ false
+
+
-
+
+ Do Not Affect
+
+
+ -
+
+ Force
+
+
+ -
+
+ Force Temporarily
+
+
+
+
+ -
+
+
+ false
+
+
-
+
+ None
+
+
+ -
+
+ Low
+
+
+ -
+
+ Normal
+
+
+ -
+
+ High
+
+
+ -
+
+ Extreme
+
+
+
+
+ -
+
+
+ &Moving/resizing
+
+
+
+ -
+
+
+ false
+
+
-
+
+ Do Not Affect
+
+
+ -
+
+ Force
+
+
+ -
+
+ Force Temporarily
+
+
+
+
+ -
+
+
+ false
+
+
-
+
+ Opaque
+
+
+ -
+
+ Transparent
+
+
+
+
+ -
+
+
+ Window &type
+
+
+
-
@@ -1879,191 +1986,6 @@
- -
-
-
- false
-
-
-
-
- Opaque
-
-
- -
-
- Transparent
-
-
-
-
- -
-
-
- Window &type
-
-
-
- -
-
-
- &Moving/resizing
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- None
-
-
- -
-
- Low
-
-
- -
-
- Normal
-
-
- -
-
- High
-
-
- -
-
- Extreme
-
-
-
-
- -
-
-
- false
-
-
- 0123456789-+,xX:
-
-
-
- -
-
-
- M&inimum size
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- M&aximum size
-
-
-
- -
-
-
- false
-
-
- 0123456789-+,xX:
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
-
@@ -2103,21 +2025,83 @@
- -
-
-
- Qt::Vertical
+
-
+
+
+ M&inimum size
-
- QSizePolicy::Expanding
+
+
+ -
+
+
+ false
-
-
- 20
- 160
-
+
-
+
+ Do Not Affect
+
+
+ -
+
+ Force
+
+
+ -
+
+ Force Temporarily
+
+
+
+
+ -
+
+
+ false
-
+
+ 0123456789-+,xX:
+
+
+
+ -
+
+
+ M&aximum size
+
+
+
+ -
+
+
+ false
+
+
-
+
+ Do Not Affect
+
+
+ -
+
+ Force
+
+
+ -
+
+ Force Temporarily
+
+
+
+
+ -
+
+
+ false
+
+
+ 0123456789-+,xX:
+
+
-
@@ -2161,16 +2145,6 @@
- -
-
-
- false
-
-
-
-
-
-
-
@@ -2203,6 +2177,68 @@
+ -
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Block compositing
+
+
+
+ -
+
+
+ false
+
+
-
+
+ Do Not Affect
+
+
+ -
+
+ Force
+
+
+ -
+
+ Force Temporarily
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Expanding
+
+
+
+ 20
+ 160
+
+
+
+
diff --git a/manage.cpp b/manage.cpp
index 135a0166fa..a802623818 100644
--- a/manage.cpp
+++ b/manage.cpp
@@ -591,6 +591,8 @@ bool Client::manage(Window w, bool isMapped)
workspace()->discardUsedWindowRules(this, false); // Remove ApplyNow rules
updateWindowRules(); // Was blocked while !isManaged()
+ updateCompositeBlocking(true);
+
// TODO: there's a small problem here - isManaged() depends on the mapping state,
// but this client is not yet in Workspace's client list at this point, will
// be only done in addClient()
diff --git a/rules.cpp b/rules.cpp
index 9e4136a241..1587064d2b 100644
--- a/rules.cpp
+++ b/rules.cpp
@@ -66,6 +66,7 @@ Rules::Rules()
, belowrule(UnusedSetRule)
, fullscreenrule(UnusedSetRule)
, noborderrule(UnusedSetRule)
+ , blockcompositingrule(UnusedForceRule)
, fsplevelrule(UnusedForceRule)
, acceptfocusrule(UnusedForceRule)
, moveresizemoderule(UnusedForceRule)
@@ -173,6 +174,7 @@ void Rules::readFromCfg(const KConfigGroup& cfg)
READ_SET_RULE(below, , false);
READ_SET_RULE(fullscreen, , false);
READ_SET_RULE(noborder, , false);
+ READ_FORCE_RULE(blockcompositing, , false);
READ_FORCE_RULE(fsplevel, limit0to4, 0); // fsp is 0-4
READ_FORCE_RULE(acceptfocus, , false);
READ_FORCE_RULE(moveresizemode, Options::stringToMoveResizeMode, QString());
@@ -262,6 +264,7 @@ void Rules::write(KConfigGroup& cfg) const
WRITE_SET_RULE(below,);
WRITE_SET_RULE(fullscreen,);
WRITE_SET_RULE(noborder,);
+ WRITE_FORCE_RULE(blockcompositing,);
WRITE_FORCE_RULE(fsplevel,);
WRITE_FORCE_RULE(acceptfocus,);
WRITE_FORCE_RULE(moveresizemode, Options::moveResizeModeToString);
@@ -303,6 +306,7 @@ bool Rules::isEmpty() const
&& belowrule == UnusedSetRule
&& fullscreenrule == UnusedSetRule
&& noborderrule == UnusedSetRule
+ && blockcompositingrule == UnusedForceRule
&& fsplevelrule == UnusedForceRule
&& acceptfocusrule == UnusedForceRule
&& moveresizemoderule == UnusedForceRule
@@ -612,6 +616,7 @@ APPLY_RULE(above, KeepAbove, bool)
APPLY_RULE(below, KeepBelow, bool)
APPLY_RULE(fullscreen, FullScreen, bool)
APPLY_RULE(noborder, NoBorder, bool)
+APPLY_FORCE_RULE(blockcompositing, BlockCompositing, bool)
APPLY_FORCE_RULE(fsplevel, FSP, int)
APPLY_FORCE_RULE(acceptfocus, AcceptFocus, bool)
APPLY_FORCE_RULE(moveresizemode, MoveResizeMode, Options::MoveResizeMode)
@@ -678,6 +683,7 @@ void Rules::discardUsed(bool withdrawn)
DISCARD_USED_SET_RULE(below);
DISCARD_USED_SET_RULE(fullscreen);
DISCARD_USED_SET_RULE(noborder);
+ DISCARD_USED_FORCE_RULE(blockcompositing);
DISCARD_USED_FORCE_RULE(fsplevel);
DISCARD_USED_FORCE_RULE(acceptfocus);
DISCARD_USED_FORCE_RULE(moveresizemode);
@@ -801,6 +807,7 @@ CHECK_RULE(KeepAbove, bool)
CHECK_RULE(KeepBelow, bool)
CHECK_RULE(FullScreen, bool)
CHECK_RULE(NoBorder, bool)
+CHECK_FORCE_RULE(BlockCompositing, bool)
CHECK_FORCE_RULE(FSP, int)
CHECK_FORCE_RULE(AcceptFocus, bool)
CHECK_FORCE_RULE(MoveResizeMode, Options::MoveResizeMode)
diff --git a/rules.h b/rules.h
index 87b205574a..84a8df16be 100644
--- a/rules.h
+++ b/rules.h
@@ -75,6 +75,7 @@ public:
bool checkKeepBelow(bool below, bool init = false) const;
bool checkFullScreen(bool fs, bool init = false) const;
bool checkNoBorder(bool noborder, bool init = false) const;
+ bool checkBlockCompositing(bool block) const;
int checkFSP(int fsp) const;
bool checkAcceptFocus(bool focus) const;
Options::MoveResizeMode checkMoveResizeMode(Options::MoveResizeMode mode) const;
@@ -132,6 +133,7 @@ public:
bool applyKeepBelow(bool& below, bool init) const;
bool applyFullScreen(bool& fs, bool init) const;
bool applyNoBorder(bool& noborder, bool init) const;
+ bool applyBlockCompositing(bool& block) const;
bool applyFSP(int& fsp) const;
bool applyAcceptFocus(bool& focus) const;
bool applyMoveResizeMode(Options::MoveResizeMode& mode) const;
@@ -244,6 +246,8 @@ private:
SetRule fullscreenrule;
bool noborder;
SetRule noborderrule;
+ bool blockcompositing;
+ ForceRule blockcompositingrule;
int fsplevel;
ForceRule fsplevelrule;
bool acceptfocus;
diff --git a/workspace.cpp b/workspace.cpp
index e534018418..9dc9012b39 100644
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -151,6 +151,7 @@ Workspace::Workspace(bool restore)
, forced_global_mouse_grab(false)
, cm_selection(NULL)
, compositingSuspended(false)
+ , compositingBlocked(false)
, xrrRefreshRate(0)
, overlay(None)
, overlay_visible(true)
@@ -701,6 +702,8 @@ void Workspace::removeClient(Client* c, allowed_t)
updateStackingOrder(true);
+ updateCompositeBlocking();
+
if (tab_grab)
tab_box->reset(true);
diff --git a/workspace.h b/workspace.h
index e6aa196f48..6284487429 100644
--- a/workspace.h
+++ b/workspace.h
@@ -404,6 +404,7 @@ public:
void toggleEffect(const QString& name);
void reconfigureEffect(const QString& name);
void unloadEffect(const QString& name);
+ void updateCompositeBlocking(Client* c = NULL);
QStringList loadedEffects() const;
QStringList listOfEffects() const;
@@ -1016,7 +1017,7 @@ private:
friend class StackingUpdatesBlocker;
KSelectionOwner* cm_selection;
- bool compositingSuspended;
+ bool compositingSuspended, compositingBlocked;
QBasicTimer compositeTimer;
qint64 nextPaintReference;
QTimer mousePollingTimer;