diff --git a/client.cpp b/client.cpp
index ac66746da8..f7ffa31c2d 100644
--- a/client.cpp
+++ b/client.cpp
@@ -262,7 +262,7 @@ void Client::releaseWindow(bool on_shutdown)
emit clientFinishUserMovedResized(this);
emit windowClosed(this, del);
finishCompositing();
- workspace()->discardUsedWindowRules(this, true); // Remove ForceTemporarily rules
+ RuleBook::self()->discardUsed(this, true); // Remove ForceTemporarily rules
StackingUpdatesBlocker blocker(workspace());
if (moveResizeMode)
leaveMoveResize();
@@ -330,7 +330,7 @@ void Client::destroyClient()
emit clientFinishUserMovedResized(this);
emit windowClosed(this, del);
finishCompositing();
- workspace()->discardUsedWindowRules(this, true); // Remove ForceTemporarily rules
+ RuleBook::self()->discardUsed(this, true); // Remove ForceTemporarily rules
StackingUpdatesBlocker blocker(workspace());
if (moveResizeMode)
leaveMoveResize();
diff --git a/manage.cpp b/manage.cpp
index 36d3578d03..93eaa592cf 100644
--- a/manage.cpp
+++ b/manage.cpp
@@ -612,7 +612,7 @@ bool Client::manage(Window w, bool isMapped)
client_rules.discardTemporary();
applyWindowRules(); // Just in case
- workspace()->discardUsedWindowRules(this, false); // Remove ApplyNow rules
+ RuleBook::self()->discardUsed(this, false); // Remove ApplyNow rules
updateWindowRules(Rules::All); // Was blocked while !isManaged()
updateCompositeBlocking(true);
diff --git a/rules.cpp b/rules.cpp
index acb927a964..df5f50908e 100644
--- a/rules.cpp
+++ b/rules.cpp
@@ -22,6 +22,7 @@ along with this program. If not, see .
#include
#include
+#include
#include
#include
#include
@@ -736,7 +737,7 @@ void WindowRules::update(Client* c, int selection)
if ((*it)->update(c, selection)) // no short-circuiting here
updated = true;
if (updated)
- Workspace::self()->rulesUpdated();
+ RuleBook::self()->requestDiskStorage();
}
#define CHECK_RULE( rule, type ) \
@@ -840,7 +841,7 @@ CHECK_FORCE_RULE(DisableGlobalShortcuts, bool)
void Client::setupWindowRules(bool ignore_temporary)
{
- client_rules = workspace()->findWindowRules(this, ignore_temporary);
+ client_rules = RuleBook::self()->find(this, ignore_temporary);
// check only after getting the rules, because there may be a rule forcing window type
}
@@ -901,7 +902,7 @@ void Client::updateWindowRules(Rules::Types selection)
{
if (!isManaged()) // not fully setup yet
return;
- if (workspace()->rulesUpdatesDisabled())
+ if (RuleBook::self()->areUpdatesDisabled())
return;
client_rules.update(this, selection);
}
@@ -913,12 +914,37 @@ void Client::finishWindowRules()
}
// Workspace
+KWIN_SINGLETON_FACTORY(RuleBook)
-WindowRules Workspace::findWindowRules(const Client* c, bool ignore_temporary)
+RuleBook::RuleBook(QObject *parent)
+ : QObject(parent)
+ , m_updateTimer(new QTimer(this))
+ , m_updatesDisabled(false)
+ , m_temporaryRulesMessages(new KXMessages("_KDE_NET_WM_TEMPORARY_RULES", NULL))
+{
+ connect(m_temporaryRulesMessages.data(), SIGNAL(gotMessage(QString)), SLOT(temporaryRulesMessage(QString)));
+ connect(m_updateTimer, SIGNAL(timeout()), SLOT(save()));
+ m_updateTimer->setInterval(1000);
+ m_updateTimer->setSingleShot(true);
+}
+
+RuleBook::~RuleBook()
+{
+ save();
+ deleteAll();
+}
+
+void RuleBook::deleteAll()
+{
+ qDeleteAll(m_rules);
+ m_rules.clear();
+}
+
+WindowRules RuleBook::find(const Client* c, bool ignore_temporary)
{
QVector< Rules* > ret;
- for (QList< Rules* >::Iterator it = rules.begin();
- it != rules.end();
+ for (QList< Rules* >::Iterator it = m_rules.begin();
+ it != m_rules.end();
) {
if (ignore_temporary && (*it)->isTemporary()) {
++it;
@@ -928,7 +954,7 @@ WindowRules Workspace::findWindowRules(const Client* c, bool ignore_temporary)
Rules* rule = *it;
kDebug(1212) << "Rule found:" << rule << ":" << c;
if (rule->isTemporary())
- it = rules.erase(it);
+ it = m_rules.erase(it);
else
++it;
ret.append(rule);
@@ -939,9 +965,9 @@ WindowRules Workspace::findWindowRules(const Client* c, bool ignore_temporary)
return WindowRules(ret);
}
-void Workspace::editWindowRules(Client* c, bool whole_app)
+void RuleBook::edit(Client* c, bool whole_app)
{
- writeWindowRules();
+ save();
QStringList args;
args << "--wid" << QString::number(c->window());
if (whole_app)
@@ -949,12 +975,9 @@ void Workspace::editWindowRules(Client* c, bool whole_app)
KToolInvocation::kdeinitExec("kwin_rules_dialog", args);
}
-void Workspace::loadWindowRules()
+void RuleBook::load()
{
- while (!rules.isEmpty()) {
- delete rules.front();
- rules.pop_front();
- }
+ deleteAll();
KConfig cfg(QLatin1String(KWIN_NAME) + "rulesrc", KConfig::NoGlobals);
int count = cfg.group("General").readEntry("count", 0);
for (int i = 1;
@@ -962,23 +985,23 @@ void Workspace::loadWindowRules()
++i) {
KConfigGroup cg(&cfg, QString::number(i));
Rules* rule = new Rules(cg);
- rules.append(rule);
+ m_rules.append(rule);
}
}
-void Workspace::writeWindowRules()
+void RuleBook::save()
{
- rulesUpdatedTimer.stop();
+ m_updateTimer->stop();
KConfig cfg(QLatin1String(KWIN_NAME) + "rulesrc", KConfig::NoGlobals);
QStringList groups = cfg.groupList();
for (QStringList::ConstIterator it = groups.constBegin();
it != groups.constEnd();
++it)
cfg.deleteGroup(*it);
- cfg.group("General").writeEntry("count", rules.count());
+ cfg.group("General").writeEntry("count", m_rules.count());
int i = 1;
- for (QList< Rules* >::ConstIterator it = rules.constBegin();
- it != rules.constEnd();
+ for (QList< Rules* >::ConstIterator it = m_rules.constBegin();
+ it != m_rules.constEnd();
++it) {
if ((*it)->isTemporary())
continue;
@@ -988,29 +1011,31 @@ void Workspace::writeWindowRules()
}
}
-void Workspace::gotTemporaryRulesMessage(const QString& message)
+void RuleBook::temporaryRulesMessage(const QString& message)
{
bool was_temporary = false;
- for (QList< Rules* >::ConstIterator it = rules.constBegin();
- it != rules.constEnd();
+ for (QList< Rules* >::ConstIterator it = m_rules.constBegin();
+ it != m_rules.constEnd();
++it)
if ((*it)->isTemporary())
was_temporary = true;
Rules* rule = new Rules(message, true);
- rules.prepend(rule); // highest priority first
+ m_rules.prepend(rule); // highest priority first
if (!was_temporary)
QTimer::singleShot(60000, this, SLOT(cleanupTemporaryRules()));
}
-void Workspace::cleanupTemporaryRules()
+void RuleBook::cleanupTemporaryRules()
{
bool has_temporary = false;
- for (QList< Rules* >::Iterator it = rules.begin();
- it != rules.end();
+ for (QList< Rules* >::Iterator it = m_rules.begin();
+ it != m_rules.end();
) {
- if ((*it)->discardTemporary(false))
- it = rules.erase(it);
- else {
+ if ((*it)->discardTemporary(false)) {
+ Rules *rules = (*it);
+ it = m_rules.erase(it);
+ delete rules;
+ } else {
if ((*it)->isTemporary())
has_temporary = true;
++it;
@@ -1020,11 +1045,11 @@ void Workspace::cleanupTemporaryRules()
QTimer::singleShot(60000, this, SLOT(cleanupTemporaryRules()));
}
-void Workspace::discardUsedWindowRules(Client* c, bool withdrawn)
+void RuleBook::discardUsed(Client* c, bool withdrawn)
{
bool updated = false;
- for (QList< Rules* >::Iterator it = rules.begin();
- it != rules.end();
+ for (QList< Rules* >::Iterator it = m_rules.begin();
+ it != m_rules.end();
) {
if (c->rules()->contains(*it)) {
updated = true;
@@ -1032,7 +1057,7 @@ void Workspace::discardUsedWindowRules(Client* c, bool withdrawn)
if ((*it)->isEmpty()) {
c->removeRule(*it);
Rules* r = *it;
- it = rules.erase(it);
+ it = m_rules.erase(it);
delete r;
continue;
}
@@ -1040,20 +1065,19 @@ void Workspace::discardUsedWindowRules(Client* c, bool withdrawn)
++it;
}
if (updated)
- rulesUpdated();
+ requestDiskStorage();
}
-void Workspace::rulesUpdated()
+void RuleBook::requestDiskStorage()
{
- rulesUpdatedTimer.setSingleShot(true);
- rulesUpdatedTimer.start(1000);
+ m_updateTimer->start();
}
-void Workspace::disableRulesUpdates(bool disable)
+void RuleBook::setUpdatesDisabled(bool disable)
{
- rules_updates_disabled = disable;
+ m_updatesDisabled = disable;
if (!disable) {
- foreach (Client * c, clients)
+ foreach (Client * c, Workspace::self()->clientList())
c->updateWindowRules(Rules::All);
}
}
diff --git a/rules.h b/rules.h
index a4893b5fc0..2a635535af 100644
--- a/rules.h
+++ b/rules.h
@@ -33,6 +33,7 @@ along with this program. If not, see .
#include "utils.h"
class KConfig;
+class KXMessages;
namespace KWin
{
@@ -91,6 +92,7 @@ private:
MaximizeMode checkMaximizeHoriz(MaximizeMode mode, bool init) const;
QVector< Rules* > rules;
};
+
#endif
class Rules
@@ -277,6 +279,39 @@ private:
};
#ifndef KCMRULES
+class RuleBook : public QObject
+{
+ Q_OBJECT
+public:
+ virtual ~RuleBook();
+ WindowRules find(const Client*, bool);
+ void discardUsed(Client* c, bool withdraw);
+ void setUpdatesDisabled(bool disable);
+ bool areUpdatesDisabled() const;
+ void load();
+ void edit(Client* c, bool whole_app);
+ void requestDiskStorage();
+private Q_SLOTS:
+ void temporaryRulesMessage(const QString&);
+ void cleanupTemporaryRules();
+ void save();
+
+private:
+ void deleteAll();
+ QTimer *m_updateTimer;
+ bool m_updatesDisabled;
+ QList m_rules;
+ QScopedPointer m_temporaryRulesMessages;
+
+ KWIN_SINGLETON(RuleBook)
+};
+
+inline
+bool RuleBook::areUpdatesDisabled() const
+{
+ return m_updatesDisabled;
+}
+
inline
bool Rules::checkSetRule(SetRule rule, bool init)
{
diff --git a/sm.cpp b/sm.cpp
index 1d6b89aaf6..1e90eb63cf 100644
--- a/sm.cpp
+++ b/sm.cpp
@@ -369,7 +369,7 @@ static void save_yourself(SmcConn conn_P, SmPointer ptr, int, Bool shutdown, int
if (conn_P != session->connection())
return;
if (shutdown)
- Workspace::self()->disableRulesUpdates(true);
+ RuleBook::self()->setUpdatesDisabled(true);
SmcSaveYourselfDone(conn_P, True);
}
@@ -395,7 +395,7 @@ static void shutdown_cancelled(SmcConn conn_P, SmPointer ptr)
SessionSaveDoneHelper* session = reinterpret_cast< SessionSaveDoneHelper* >(ptr);
if (conn_P != session->connection())
return;
- Workspace::self()->disableRulesUpdates(false); // re-enable
+ RuleBook::self()->setUpdatesDisabled(false); // re-enable
// no need to differentiate between successful finish and cancel
session->saveDone();
}
diff --git a/useractions.cpp b/useractions.cpp
index 20d6ad828c..753b8c16cb 100755
--- a/useractions.cpp
+++ b/useractions.cpp
@@ -1111,10 +1111,10 @@ void Workspace::performWindowOperation(Client* c, Options::WindowOperation op)
c->performMouseCommand(Options::MouseShade, cursorPos());
break;
case Options::WindowRulesOp:
- editWindowRules(c, false);
+ RuleBook::self()->edit(c, false);
break;
case Options::ApplicationRulesOp:
- editWindowRules(c, true);
+ RuleBook::self()->edit(c, true);
break;
case Options::SetupWindowShortcutOp:
setupWindowShortcut(c);
diff --git a/workspace.cpp b/workspace.cpp
index 5aee3f8e7f..42dd9c185e 100644
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -86,8 +86,6 @@ Workspace::Workspace(bool restore)
// Unsorted
, active_popup(NULL)
, active_popup_client(NULL)
- , temporaryRulesMessages("_KDE_NET_WM_TEMPORARY_RULES", NULL)
- , rules_updates_disabled(false)
, active_client(0)
, last_active_client(0)
, most_recently_raised(0)
@@ -148,9 +146,6 @@ Workspace::Workspace(bool restore)
default_colormap = DefaultColormap(display(), screen_number);
installed_colormap = default_colormap;
- connect(&temporaryRulesMessages, SIGNAL(gotMessage(QString)),
- this, SLOT(gotTemporaryRulesMessage(QString)));
- connect(&rulesUpdatedTimer, SIGNAL(timeout()), this, SLOT(writeWindowRules()));
updateXTime(); // Needed for proper initialization of user_time in Client ctor
delayFocusTimer = 0;
@@ -158,7 +153,7 @@ Workspace::Workspace(bool restore)
if (restore)
loadSessionInfo();
- loadWindowRules();
+ RuleBook::create(this)->load();
// Call this before XSelectInput() on the root window
startup = new KStartupInfo(
@@ -505,7 +500,7 @@ Workspace::~Workspace()
(*it)->release(true);
XDeleteProperty(display(), rootWindow(), atoms->kwin_running);
- writeWindowRules();
+ delete RuleBook::self();
KGlobal::config()->sync();
delete rootInfo;
@@ -513,10 +508,6 @@ Workspace::~Workspace()
delete startup;
delete Placement::self();
delete client_keys_dialog;
- while (!rules.isEmpty()) {
- delete rules.front();
- rules.pop_front();
- }
foreach (SessionInfo * s, session)
delete s;
XDestroyWindow(display(), null_focus_window);
@@ -907,13 +898,13 @@ void Workspace::slotReconfigure()
c->triggerDecorationRepaint();
}
- loadWindowRules();
+ RuleBook::self()->load();
for (ClientList::Iterator it = clients.begin();
it != clients.end();
++it) {
(*it)->setupWindowRules(true);
(*it)->applyWindowRules();
- discardUsedWindowRules(*it, false);
+ RuleBook::self()->discardUsed(*it, false);
}
if (borderlessMaximizedWindows != options->borderlessMaximizedWindows() &&
diff --git a/workspace.h b/workspace.h
index 3ea9c2e27a..da968c8549 100644
--- a/workspace.h
+++ b/workspace.h
@@ -29,7 +29,6 @@ along with this program. If not, see .
#include "utils.h"
// KDE
#include
-#include
// Qt
#include
#include
@@ -52,10 +51,8 @@ namespace KWin
class Client;
class KillWindow;
class RootInfo;
-class Rules;
class ShortcutDialog;
class UserActionsMenu;
-class WindowRules;
class Compositor;
class Workspace : public QObject, public KDecorationDefines
@@ -246,11 +243,6 @@ public:
void loadSubSessionInfo(const QString &name);
SessionInfo* takeSessionInfo(Client*);
- WindowRules findWindowRules(const Client*, bool);
- void rulesUpdated();
- void discardUsedWindowRules(Client* c, bool withdraw);
- void disableRulesUpdates(bool disable);
- bool rulesUpdatesDisabled() const;
// D-Bus interface
bool waitForCompositingSetup();
@@ -397,9 +389,6 @@ private slots:
void desktopResized();
void slotUpdateToolWindows();
void delayFocus();
- void gotTemporaryRulesMessage(const QString&);
- void cleanupTemporaryRules();
- void writeWindowRules();
void slotBlockShortcuts(int data);
void slotReloadConfig();
void updateCurrentActivity(const QString &new_activity);
@@ -481,14 +470,7 @@ private:
void loadSessionInfo();
void addSessionInfo(KConfigGroup &cg);
- void loadWindowRules();
- void editWindowRules(Client* c, bool whole_app);
-
QList session;
- QList rules;
- KXMessages temporaryRulesMessages;
- QTimer rulesUpdatedTimer;
- bool rules_updates_disabled;
static const char* windowTypeToTxt(NET::WindowType type);
static NET::WindowType txtToWindowType(const char* txt);
static bool sessionInfoWindowTypeMatch(Client* c, SessionInfo* info);
@@ -712,11 +694,6 @@ inline bool Workspace::globalShortcutsDisabled() const
return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
}
-inline bool Workspace::rulesUpdatesDisabled() const
-{
- return rules_updates_disabled;
-}
-
inline void Workspace::forceRestacking()
{
force_restacking = true;