Split out Rules related code from Workspace into class RuleBook

Workspace is hardly interacting with Rules and all the Rules related code
is already in rules.cpp. This highly qualifies to move all the code out
of Workspace and improve the names.

REVIEW: 110207
This commit is contained in:
Martin Gräßlin 2013-04-26 14:40:35 +02:00
parent 4ec0f64ea3
commit 65ec86113a
8 changed files with 111 additions and 84 deletions

View file

@ -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();

View file

@ -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);

106
rules.cpp
View file

@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <fixx11h.h>
#include <kconfig.h>
#include <KDE/KXMessages>
#include <QRegExp>
#include <ktemporaryfile.h>
#include <QFile>
@ -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);
}
}

35
rules.h
View file

@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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<Rules*> m_rules;
QScopedPointer<KXMessages> m_temporaryRulesMessages;
KWIN_SINGLETON(RuleBook)
};
inline
bool RuleBook::areUpdatesDisabled() const
{
return m_updatesDisabled;
}
inline
bool Rules::checkSetRule(SetRule rule, bool init)
{

4
sm.cpp
View file

@ -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();
}

View file

@ -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);

View file

@ -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() &&

View file

@ -29,7 +29,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "utils.h"
// KDE
#include <KDE/NETRootInfo>
#include <KDE/KXMessages>
// Qt
#include <QTimer>
#include <QVector>
@ -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<SessionInfo*> session;
QList<Rules*> 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;