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;