From bc0a9cb53a98c181fe62e1f99cc6bba039b05605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 20 Mar 2014 09:19:53 +0100 Subject: [PATCH] [kwin] Use std::find_if and lambda functions for Workspace::findClient Instead of passing the macro based Predicate to findClient it now expects a function which can be passed to std::find_if. Existing code like: xcb_window_t window; // our test window Client *c = findClient(WindowMatchPredicated(window)); becomes: Client *c = findClient([window](const Client *c) { return c->window() == window; }); The advantage is that it is way more flexible and has the logic what to check for directly with the code and not hidden in the macro definition. In addition there is a simplified overload for the very common case of matching a window id against one of Client's windows. This overloaded method takes a Predicate and the window id. Above example becomes: Client *c = findClient(Predicate::WindowMatch, w); Existing code is migrated to use the simplified method taking MatchPredicate and window id. The very few cases where a more complex condition is tested the lambda function is used. As these are very local tests only used in one function it's not worthwhile to add further overloads to the findClient method in Workspace. With this change all the Predicate macro definitions are removed from utils.h as they are now completely unused. REVIEW: 116916 --- activation.cpp | 17 +++++----- appmenu.cpp | 6 ++-- client.cpp | 10 +++--- client.h | 17 +++++++--- effects.cpp | 2 +- events.cpp | 12 +++---- group.cpp | 12 +++---- killwindow.cpp | 2 +- layers.cpp | 8 ++--- netinfo.cpp | 14 ++++---- scripting/workspace_wrapper.cpp | 2 +- thumbnailitem.cpp | 4 +-- toplevel.h | 3 -- utils.h | 34 -------------------- workspace.cpp | 36 ++++++++++++++++++++- workspace.h | 57 ++++++++++++++++++++++++--------- 16 files changed, 135 insertions(+), 101 deletions(-) diff --git a/activation.cpp b/activation.cpp index cde06b4c37..4824645911 100644 --- a/activation.cpp +++ b/activation.cpp @@ -695,13 +695,6 @@ void Client::demandAttention(bool set) emit demandsAttentionChanged(); } -// TODO I probably shouldn't be lazy here and do it without the macro, so that people can read it -KWIN_COMPARE_PREDICATE(SameApplicationActiveHackPredicate, Client, const Client*, - // ignore already existing splashes, toolbars, utilities and menus, - // as the app may show those before the main window - !cl->isSplash() && !cl->isToolbar() && !cl->isUtility() && !cl->isMenu() - && Client::belongToSameApplication(cl, value, true) && cl != value); - xcb_timestamp_t Client::readUserTimeMapTimestamp(const KStartupInfoId *asn_id, const KStartupInfoData *asn_data, bool session) const { @@ -733,17 +726,23 @@ xcb_timestamp_t Client::readUserTimeMapTimestamp(const KStartupInfoId *asn_id, c Client* act = workspace()->mostRecentlyActivatedClient(); if (act != NULL && !belongToSameApplication(act, this, true)) { bool first_window = true; + auto sameApplicationActiveHackPredicate = [this](const Client *cl) { + // ignore already existing splashes, toolbars, utilities and menus, + // as the app may show those before the main window + return !cl->isSplash() && !cl->isToolbar() && !cl->isUtility() && !cl->isMenu() + && cl != this && Client::belongToSameApplication(cl, this, true); + }; if (isTransient()) { if (act->hasTransient(this, true)) ; // is transient for currently active window, even though it's not // the same app (e.g. kcookiejar dialog) -> allow activation else if (groupTransient() && - findClientInList(mainClients(), SameApplicationActiveHackPredicate(this)) == NULL) + findInList(mainClients(), sameApplicationActiveHackPredicate) == NULL) ; // standalone transient else first_window = false; } else { - if (workspace()->findClient(SameApplicationActiveHackPredicate(this))) + if (workspace()->findClient(sameApplicationActiveHackPredicate)) first_window = false; } // don't refuse if focus stealing prevention is turned off diff --git a/appmenu.cpp b/appmenu.cpp index 2937a46ea1..d8266449c7 100644 --- a/appmenu.cpp +++ b/appmenu.cpp @@ -50,13 +50,13 @@ bool ApplicationMenu::hasMenu(xcb_window_t window) void ApplicationMenu::slotShowRequest(qulonglong wid) { - if (Client *c = Workspace::self()->findClient(WindowMatchPredicate(wid))) + if (Client *c = Workspace::self()->findClient(Predicate::WindowMatch, wid)) c->emitShowRequest(); } void ApplicationMenu::slotMenuAvailable(qulonglong wid) { - if (Client *c = Workspace::self()->findClient(WindowMatchPredicate(wid))) + if (Client *c = Workspace::self()->findClient(Predicate::WindowMatch, wid)) c->setAppMenuAvailable(); else m_windowsMenu.append(wid); @@ -64,7 +64,7 @@ void ApplicationMenu::slotMenuAvailable(qulonglong wid) void ApplicationMenu::slotMenuHidden(qulonglong wid) { - if (Client *c = Workspace::self()->findClient(WindowMatchPredicate(wid))) + if (Client *c = Workspace::self()->findClient(Predicate::WindowMatch, wid)) c->emitMenuHidden(); } diff --git a/client.cpp b/client.cpp index 7d4ef33d8b..4a9de4a438 100644 --- a/client.cpp +++ b/client.cpp @@ -1800,8 +1800,6 @@ QString Client::readName() const return KWindowSystem::readNameProperty(window(), XCB_ATOM_WM_NAME); } -KWIN_COMPARE_PREDICATE(FetchNameInternalPredicate, Client, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); - // The list is taken from http://www.unicode.org/reports/tr9/ (#154840) QChar LRM(0x200E); QChar RLM(0x200F); @@ -1856,12 +1854,16 @@ void Client::setCaption(const QString& _s, bool force) } QString shortcut_suffix = !shortcut().isEmpty() ? (QStringLiteral(" {") + shortcut().toString() + QStringLiteral("}")) : QString(); cap_suffix = machine_suffix + shortcut_suffix; - if ((!isSpecialWindow() || isToolbar()) && workspace()->findClient(FetchNameInternalPredicate(this))) { + auto fetchNameInternalPredicate = [this](const Client *cl) { + return (!cl->isSpecialWindow() || cl->isToolbar()) && + cl != this && cl->caption() == caption(); + }; + if ((!isSpecialWindow() || isToolbar()) && workspace()->findClient(fetchNameInternalPredicate)) { int i = 2; do { cap_suffix = machine_suffix + QStringLiteral(" <") + QString::number(i) + QStringLiteral(">") + LRM; i++; - } while (workspace()->findClient(FetchNameInternalPredicate(this))); + } while (workspace()->findClient(fetchNameInternalPredicate)); info->setVisibleName(caption().toUtf8().constData()); reset_name = false; } diff --git a/client.h b/client.h index 5f5ac91583..8737ff5bf5 100644 --- a/client.h +++ b/client.h @@ -55,6 +55,19 @@ class TabBoxClientImpl; class Bridge; class PaintRedirector; + +/** + * @brief Defines Predicates on how to search for a Client. + * + * Used by Workspace::findClient. + */ +enum class Predicate { + WindowMatch, + WrapperIdMatch, + FrameIdMatch, + InputIdMatch +}; + class Client : public Toplevel { @@ -978,7 +991,6 @@ private: static bool check_active_modal; ///< \see Client::checkActiveModal() QKeySequence _shortcut; int sm_stacking_order; - friend struct FetchNameInternalPredicate; friend struct ResetupRulesProcedure; friend class GeometryUpdatesBlocker; PaintRedirector* paintRedirector; @@ -1269,9 +1281,6 @@ inline void Client::print(T &stream) const << resourceName() << ";Caption:" << caption() << "\'"; } -KWIN_COMPARE_PREDICATE(WrapperIdMatchPredicate, Client, Window, cl->wrapperId() == value); -KWIN_COMPARE_PREDICATE(InputIdMatchPredicate, Client, Window, cl->inputId() == value); - } // namespace Q_DECLARE_METATYPE(KWin::Client*) Q_DECLARE_METATYPE(QList) diff --git a/effects.cpp b/effects.cpp index 1d6f913449..b847a03911 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1112,7 +1112,7 @@ WindowQuadType EffectsHandlerImpl::newWindowQuadType() EffectWindow* EffectsHandlerImpl::findWindow(WId id) const { - if (Client* w = Workspace::self()->findClient(WindowMatchPredicate(id))) + if (Client* w = Workspace::self()->findClient(Predicate::WindowMatch, id)) return w->effectWindow(); if (Unmanaged* w = Workspace::self()->findUnmanaged(id)) return w->effectWindow(); diff --git a/events.cpp b/events.cpp index 0005151401..07eae014a5 100644 --- a/events.cpp +++ b/events.cpp @@ -234,16 +234,16 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e) const xcb_window_t eventWindow = findEventWindow(e); if (eventWindow != XCB_WINDOW_NONE) { - if (Client* c = findClient(WindowMatchPredicate(eventWindow))) { + if (Client* c = findClient(Predicate::WindowMatch, eventWindow)) { if (c->windowEvent(e)) return true; - } else if (Client* c = findClient(WrapperIdMatchPredicate(eventWindow))) { + } else if (Client* c = findClient(Predicate::WrapperIdMatch, eventWindow)) { if (c->windowEvent(e)) return true; - } else if (Client* c = findClient(FrameIdMatchPredicate(eventWindow))) { + } else if (Client* c = findClient(Predicate::FrameIdMatch, eventWindow)) { if (c->windowEvent(e)) return true; - } else if (Client *c = findClient(InputIdMatchPredicate(eventWindow))) { + } else if (Client *c = findClient(Predicate::InputIdMatch, eventWindow)) { if (c->windowEvent(e)) return true; } else if (Unmanaged* c = findUnmanaged(eventWindow)) { @@ -300,7 +300,7 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e) updateXTime(); const auto *event = reinterpret_cast(e); - if (Client* c = findClient(WindowMatchPredicate(event->window))) { + if (Client* c = findClient(Predicate::WindowMatch, event->window)) { // e->xmaprequest.window is different from e->xany.window // TODO this shouldn't be necessary now c->windowEvent(e); @@ -350,7 +350,7 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e) break; // TODO is this cliente ever found, given that client events are searched above? const auto *event = reinterpret_cast(e); - Client* c = findClient(FrameIdMatchPredicate(event->event)); + Client* c = findClient(Predicate::FrameIdMatch, event->event); if (c && event->detail != XCB_NOTIFY_DETAIL_INFERIOR) QWhatsThis::leaveWhatsThisMode(); break; diff --git a/group.cpp b/group.cpp index 296da16844..1819f928d1 100644 --- a/group.cpp +++ b/group.cpp @@ -203,7 +203,7 @@ Group::Group(Window leader_P) refcount(0) { if (leader_P != None) { - leader_client = workspace()->findClient(WindowMatchPredicate(leader_P)); + leader_client = workspace()->findClient(Predicate::WindowMatch, leader_P); leader_info = new NETWinInfo(connection(), leader_P, rootWindow(), 0, NET::WM2StartupId); } @@ -583,7 +583,7 @@ void Client::setTransient(xcb_window_t new_transient_for_id) transient_for = NULL; m_transientForId = new_transient_for_id; if (m_transientForId != XCB_WINDOW_NONE && !groupTransient()) { - transient_for = workspace()->findClient(WindowMatchPredicate(m_transientForId)); + transient_for = workspace()->findClient(Predicate::WindowMatch, m_transientForId); assert(transient_for != NULL); // verifyTransient() had to check this transient_for->addTransient(this); } // checkGroup() will check 'check_active_modal' @@ -755,14 +755,14 @@ xcb_window_t Client::verifyTransientFor(xcb_window_t new_transient_for, bool set xcb_window_t before_search = new_transient_for; while (new_transient_for != XCB_WINDOW_NONE && new_transient_for != rootWindow() - && !workspace()->findClient(WindowMatchPredicate(new_transient_for))) { + && !workspace()->findClient(Predicate::WindowMatch, new_transient_for)) { Xcb::Tree tree(new_transient_for); if (tree.isNull()) { break; } new_transient_for = tree->parent; } - if (Client* new_transient_for_client = workspace()->findClient(WindowMatchPredicate(new_transient_for))) { + if (Client* new_transient_for_client = workspace()->findClient(Predicate::WindowMatch, new_transient_for)) { if (new_transient_for != before_search) { qDebug() << "Client " << this << " has WM_TRANSIENT_FOR poiting to non-toplevel window " << before_search << ", child of " << new_transient_for_client << ", adjusting." << endl; @@ -776,7 +776,7 @@ xcb_window_t Client::verifyTransientFor(xcb_window_t new_transient_for, bool set int count = 20; xcb_window_t loop_pos = new_transient_for; while (loop_pos != XCB_WINDOW_NONE && loop_pos != rootWindow()) { - Client* pos = workspace()->findClient(WindowMatchPredicate(loop_pos)); + Client* pos = workspace()->findClient(Predicate::WindowMatch, loop_pos); if (pos == NULL) break; loop_pos = pos->m_transientForId; @@ -786,7 +786,7 @@ xcb_window_t Client::verifyTransientFor(xcb_window_t new_transient_for, bool set } } if (new_transient_for != rootWindow() - && workspace()->findClient(WindowMatchPredicate(new_transient_for)) == NULL) { + && workspace()->findClient(Predicate::WindowMatch, new_transient_for) == NULL) { // it's transient for a specific window, but that window is not mapped new_transient_for = rootWindow(); } diff --git a/killwindow.cpp b/killwindow.cpp index f12cab9c92..d3d951c3bc 100644 --- a/killwindow.cpp +++ b/killwindow.cpp @@ -203,7 +203,7 @@ void KillWindow::killWindowId(xcb_window_t window_to_kill) xcb_window_t window = window_to_kill; Client* client = NULL; while (true) { - client = Workspace::self()->findClient(FrameIdMatchPredicate(window)); + client = Workspace::self()->findClient(Predicate::FrameIdMatch, window); if (client) { break; // Found the client } diff --git a/layers.cpp b/layers.cpp index 5dd8a4a5c8..362839a239 100644 --- a/layers.cpp +++ b/layers.cpp @@ -694,7 +694,7 @@ void Client::restackWindow(xcb_window_t above, int detail, NET::RequestSource sr { Client *other = 0; if (detail == XCB_STACK_MODE_OPPOSITE) { - other = workspace()->findClient(WindowMatchPredicate(above)); + other = workspace()->findClient(Predicate::WindowMatch, above); if (!other) { workspace()->raiseOrLowerClient(this); return; @@ -713,20 +713,20 @@ void Client::restackWindow(xcb_window_t above, int detail, NET::RequestSource sr } } else if (detail == XCB_STACK_MODE_TOP_IF) { - other = workspace()->findClient(WindowMatchPredicate(above)); + other = workspace()->findClient(Predicate::WindowMatch, above); if (other && other->geometry().intersects(geometry())) workspace()->raiseClientRequest(this, src, timestamp); return; } else if (detail == XCB_STACK_MODE_BOTTOM_IF) { - other = workspace()->findClient(WindowMatchPredicate(above)); + other = workspace()->findClient(Predicate::WindowMatch, above); if (other && other->geometry().intersects(geometry())) workspace()->lowerClientRequest(this, src, timestamp); return; } if (!other) - other = workspace()->findClient(WindowMatchPredicate(above)); + other = workspace()->findClient(Predicate::WindowMatch, above); if (other && detail == XCB_STACK_MODE_ABOVE) { ToplevelList::const_iterator it = workspace()->stackingOrder().constEnd(), diff --git a/netinfo.cpp b/netinfo.cpp index 391ffb3956..85983b478b 100644 --- a/netinfo.cpp +++ b/netinfo.cpp @@ -157,7 +157,7 @@ void RootInfo::changeCurrentDesktop(int d) void RootInfo::changeActiveWindow(xcb_window_t w, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window) { Workspace *workspace = Workspace::self(); - if (Client* c = workspace->findClient(WindowMatchPredicate(w))) { + if (Client* c = workspace->findClient(Predicate::WindowMatch, w)) { if (timestamp == CurrentTime) timestamp = c->userTime(); if (src != NET::FromApplication && src != FromTool) @@ -172,7 +172,7 @@ void RootInfo::changeActiveWindow(xcb_window_t w, NET::RequestSource src, xcb_ti workspace->activateClient(c); // if activation of the requestor's window would be allowed, allow activation too else if (active_window != None - && (c2 = workspace->findClient(WindowMatchPredicate(active_window))) != NULL + && (c2 = workspace->findClient(Predicate::WindowMatch, active_window)) != NULL && workspace->allowClientActivation(c2, timestampCompare(timestamp, c2->userTime() > 0 ? timestamp : c2->userTime()), false, true)) { workspace->activateClient(c); @@ -184,7 +184,7 @@ void RootInfo::changeActiveWindow(xcb_window_t w, NET::RequestSource src, xcb_ti void RootInfo::restackWindow(xcb_window_t w, RequestSource src, xcb_window_t above, int detail, xcb_timestamp_t timestamp) { - if (Client* c = Workspace::self()->findClient(WindowMatchPredicate(w))) { + if (Client* c = Workspace::self()->findClient(Predicate::WindowMatch, w)) { if (timestamp == CurrentTime) timestamp = c->userTime(); if (src != NET::FromApplication && src != FromTool) @@ -195,14 +195,14 @@ void RootInfo::restackWindow(xcb_window_t w, RequestSource src, xcb_window_t abo void RootInfo::closeWindow(xcb_window_t w) { - Client* c = Workspace::self()->findClient(WindowMatchPredicate(w)); + Client* c = Workspace::self()->findClient(Predicate::WindowMatch, w); if (c) c->closeWindow(); } void RootInfo::moveResize(xcb_window_t w, int x_root, int y_root, unsigned long direction) { - Client* c = Workspace::self()->findClient(WindowMatchPredicate(w)); + Client* c = Workspace::self()->findClient(Predicate::WindowMatch, w); if (c) { updateXTime(); // otherwise grabbing may have old timestamp - this message should include timestamp c->NETMoveResize(x_root, y_root, (Direction)direction); @@ -211,14 +211,14 @@ void RootInfo::moveResize(xcb_window_t w, int x_root, int y_root, unsigned long void RootInfo::moveResizeWindow(xcb_window_t w, int flags, int x, int y, int width, int height) { - Client* c = Workspace::self()->findClient(WindowMatchPredicate(w)); + Client* c = Workspace::self()->findClient(Predicate::WindowMatch, w); if (c) c->NETMoveResizeWindow(flags, x, y, width, height); } void RootInfo::gotPing(xcb_window_t w, xcb_timestamp_t timestamp) { - if (Client* c = Workspace::self()->findClient(WindowMatchPredicate(w))) + if (Client* c = Workspace::self()->findClient(Predicate::WindowMatch, w)) c->gotPing(timestamp); } diff --git a/scripting/workspace_wrapper.cpp b/scripting/workspace_wrapper.cpp index d42222543f..cb52a828bd 100644 --- a/scripting/workspace_wrapper.cpp +++ b/scripting/workspace_wrapper.cpp @@ -261,7 +261,7 @@ void WorkspaceWrapper::hideOutline() Client *WorkspaceWrapper::getClient(qulonglong windowId) { - return Workspace::self()->findClient(WindowMatchPredicate(windowId)); + return Workspace::self()->findClient(Predicate::WindowMatch, windowId); } QSize WorkspaceWrapper::desktopGridSize() const diff --git a/thumbnailitem.cpp b/thumbnailitem.cpp index 531dfe8802..d4124ae14b 100644 --- a/thumbnailitem.cpp +++ b/thumbnailitem.cpp @@ -138,7 +138,7 @@ void WindowThumbnailItem::setWId(qulonglong wId) } m_wId = wId; if (m_wId != 0) { - setClient(Workspace::self()->findClient(WindowMatchPredicate(m_wId))); + setClient(Workspace::self()->findClient(Predicate::WindowMatch, m_wId)); } else if (m_client) { m_client = NULL; emit clientChanged(); @@ -165,7 +165,7 @@ void WindowThumbnailItem::paint(QPainter *painter) if (effects) { return; } - Client *client = Workspace::self()->findClient(WindowMatchPredicate(m_wId)); + Client *client = Workspace::self()->findClient(Predicate::WindowMatch, m_wId); if (!client) { return; } diff --git a/toplevel.h b/toplevel.h index 70775e538b..f8a05bead8 100644 --- a/toplevel.h +++ b/toplevel.h @@ -685,9 +685,6 @@ inline T *Toplevel::findInList(const QList &list, std::functionwindow() == value); -KWIN_COMPARE_PREDICATE(FrameIdMatchPredicate, Toplevel, Window, cl->frameId() == value); - } // namespace Q_DECLARE_METATYPE(KWin::Toplevel*) diff --git a/utils.h b/utils.h index 9deae736c3..99291d64ff 100644 --- a/utils.h +++ b/utils.h @@ -156,40 +156,6 @@ public: #define UrgencyHint XUrgencyHint #endif -// for STL-like algo's -#define KWIN_CHECK_PREDICATE( name, cls, check ) \ - struct name \ - { \ - inline bool operator()( const cls* cl ) { return check; } \ - } - -#define KWIN_COMPARE_PREDICATE( name, cls, type, check ) \ - struct name \ - { \ - typedef type type_helper; /* in order to work also with type being 'const Client*' etc. */ \ - inline name( const type_helper& compare_value ) : value( compare_value ) {} \ - inline bool operator()( const cls* cl ) { return check; } \ - const type_helper& value; \ - } - -#define KWIN_PROCEDURE( name, cls, action ) \ - struct name \ - { \ - inline void operator()( cls* cl ) { action; } \ - } - -KWIN_CHECK_PREDICATE(TruePredicate, Client, cl == cl /*true, avoid warning about 'cl' */); - -template< typename T > -Client* findClientInList(const ClientList& list, T predicate) -{ - for (ClientList::ConstIterator it = list.begin(); it != list.end(); ++it) { - if (predicate(const_cast< const Client* >(*it))) - return *it; - } - return NULL; -} - QPoint cursorPos(); // converting between X11 mouse/keyboard state mask and Qt button/keyboard states diff --git a/workspace.cpp b/workspace.cpp index 50df1d6cd2..3d2c672752 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -381,7 +381,7 @@ void Workspace::init() Client* new_active_client = NULL; if (!qApp->isSessionRestored()) { --block_focus; - new_active_client = findClient(WindowMatchPredicate(client_info.activeWindow())); + new_active_client = findClient(Predicate::WindowMatch, client_info.activeWindow()); } if (new_active_client == NULL && activeClient() == NULL && should_get_focus.count() == 0) { @@ -1527,6 +1527,17 @@ void Workspace::slotToggleCompositing() } } +Client *Workspace::findClient(std::function func) const +{ + if (Client *ret = Toplevel::findInList(clients, func)) { + return ret; + } + if (Client *ret = Toplevel::findInList(desktops, func)) { + return ret; + } + return nullptr; +} + Unmanaged *Workspace::findUnmanaged(std::function func) const { return Toplevel::findInList(unmanaged, func); @@ -1539,6 +1550,29 @@ Unmanaged *Workspace::findUnmanaged(xcb_window_t w) const }); } +Client *Workspace::findClient(Predicate predicate, xcb_window_t w) const +{ + switch (predicate) { + case Predicate::WindowMatch: + return findClient([w](const Client *c) { + return c->window() == w; + }); + case Predicate::WrapperIdMatch: + return findClient([w](const Client *c) { + return c->wrapperId() == w; + }); + case Predicate::FrameIdMatch: + return findClient([w](const Client *c) { + return c->frameId() == w; + }); + case Predicate::InputIdMatch: + return findClient([w](const Client *c) { + return c->inputId() == w; + }); + } + return nullptr; +} + } // namespace #include "workspace.moc" diff --git a/workspace.h b/workspace.h index f3ef7b9e73..71c328e4f4 100644 --- a/workspace.h +++ b/workspace.h @@ -55,6 +55,7 @@ class KillWindow; class ShortcutDialog; class UserActionsMenu; class Compositor; +enum class Predicate; class Workspace : public QObject, public KDecorationDefines { @@ -72,7 +73,44 @@ public: bool hasClient(const Client*); - template Client* findClient(T predicate) const; + /** + * @brief Finds the first Client matching the condition expressed by passed in @p func. + * + * Internally findClient uses the std::find_if algorithm and that determines how the function + * needs to be implemented. An example usage for finding a Client with a matching windowId + * @code + * xcb_window_t w; // our test window + * Client *client = findClient([w](const Client *c) -> bool { + * return c->window() == w; + * }); + * @endcode + * + * For the standard cases of matching the window id with one of the Client's windows use + * the simplified overload method findClient(Predicate, xcb_window_t). Above example + * can be simplified to: + * @code + * xcb_window_t w; // our test window + * Client *client = findClient(Predicate::WindowMatch, w); + * @endcode + * + * @param func Unary function that accepts a Client* as argument and + * returns a value convertible to bool. The value returned indicates whether the + * Client* is considered a match in the context of this function. + * The function shall not modify its argument. + * This can either be a function pointer or a function object. + * @return KWin::Client* The found Client or @c null + * @see findClient(Predicate, xcb_window_t) + */ + Client *findClient(std::function func) const; + /** + * @brief Finds the Client matching the given match @p predicate for the given window. + * + * @param predicate Which window should be compared + * @param w The window id to test against + * @return KWin::Client* The found Client or @c null + * @see findClient(std::function) + */ + Client *findClient(Predicate predicate, xcb_window_t w) const; void forEachClient(std::function func); Unmanaged *findUnmanaged(std::function func) const; /** @@ -659,17 +697,6 @@ inline QPoint Workspace::focusMousePosition() const return focusMousePos; } -template< typename T > -inline Client* Workspace::findClient(T predicate) const -{ - if (Client* ret = findClientInList(clients, predicate)) - return ret; - if (Client* ret = findClientInList(desktops, predicate)) - return ret; - return NULL; -} - - inline void Workspace::forEachClient(std::function< void (Client*) > func) { @@ -683,11 +710,11 @@ void Workspace::forEachUnmanaged(std::function< void (Unmanaged*) > func) std::for_each(unmanaged.constBegin(), unmanaged.constEnd(), func); } -KWIN_COMPARE_PREDICATE(ClientMatchPredicate, Client, const Client*, cl == value); - inline bool Workspace::hasClient(const Client* c) { - return findClient(ClientMatchPredicate(c)); + return findClient([c](const Client *test) { + return test == c; + }); } inline Workspace *workspace()