Merge lp:~azzar1/hud/hud-wnck-actions-menu into lp:hud

Proposed by Andrea Azzarone
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: 411
Merged at revision: 405
Proposed branch: lp:~azzar1/hud/hud-wnck-actions-menu
Merge into: lp:hud
Diff against target: 801 lines (+335/-116)
16 files modified
data/com.canonical.Unity.WindowStack.xml (+4/-0)
service/CMakeLists.txt (+1/-0)
service/DBusMenuCollector.cpp (+14/-56)
service/DBusMenuCollector.h (+9/-29)
service/DBusMenuWindowCollector.cpp (+141/-0)
service/DBusMenuWindowCollector.h (+72/-0)
service/Factory.cpp (+9/-4)
service/Factory.h (+5/-2)
service/ItemStore.cpp (+22/-0)
service/ItemStore.h (+2/-0)
service/WindowImpl.cpp (+1/-1)
tests/unit/service/Mocks.h (+1/-1)
tests/unit/service/TestWindow.cpp (+25/-23)
window-stack-bridge/AbstractWindowStack.h (+2/-0)
window-stack-bridge/BamfWindowStack.cpp (+21/-0)
window-stack-bridge/BamfWindowStack.h (+6/-0)
To merge this branch: bzr merge lp:~azzar1/hud/hud-wnck-actions-menu
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+291101@code.launchpad.net

Commit message

Introduce DBusMenuWindowCollector to make it possible to expose the window actions menu through dbusmenu.

Description of the change

Introduce DBusMenuWindowCollector to make it possible to expose the window actions menu through dbus.

To post a comment you must log in.
lp:~azzar1/hud/hud-wnck-actions-menu updated
406. By Andrea Azzarone

Fix indent.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~azzar1/hud/hud-wnck-actions-menu updated
407. By Andrea Azzarone

Add missing files.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~azzar1/hud/hud-wnck-actions-menu updated
408. By Andrea Azzarone

Allow to search using the mnemonic key.

409. By Andrea Azzarone

Fix DBusMenuWindowCollector::isValid.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Nice!

However, since Hud already relies on BAMF and it knows the paths we're handling, there's really no reason to export _WNCK_ACTION_MENU_OBJECT_PATH on windows in BAMF side and then reading it here.

We can just use the window stack to get that.
So, please merge this with my branch, where I've implemented this: lp:~3v1n0/hud/stack-get-bus-address

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Ah, about the searchByMnemonic thing... Maybe it should be enabled for all the menus?
Including the ones provided by GMenuModel (thus probably just keeping it as default, without adding a property)?

lp:~azzar1/hud/hud-wnck-actions-menu updated
410. By Andrea Azzarone

Merge with lp:~3v1n0/hud/stack-get-bus-address.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Ouch, forgot http://pastebin.ubuntu.com/15784656/ please apply it.

(or just bzr pull lp:~3v1n0/hud/stack-get-bus-address)

lp:~azzar1/hud/hud-wnck-actions-menu updated
411. By Andrea Azzarone

Merge with lp:~3v1n0/hud/stack-get-bus-address)

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> Ouch, forgot http://pastebin.ubuntu.com/15784656/ please apply it.
>
> (or just bzr pull lp:~3v1n0/hud/stack-get-bus-address)

Done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

CI failures are pretty random. Not nice, but nothing caused by this change.

Let's go with this.

review: Approve
Revision history for this message
Pete Woods (pete-woods) wrote :

If you had exported the menu as a GMenu on your end, you probably wouldn't have had to touch HUD at all, as it already supports collecting multiple GMenus.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> If you had exported the menu as a GMenu on your end, you probably wouldn't
> have had to touch HUD at all, as it already supports collecting multiple
> GMenus.

It was not possible to do so without an API break for libwnck.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/com.canonical.Unity.WindowStack.xml'
2--- data/com.canonical.Unity.WindowStack.xml 2013-12-18 10:12:17 +0000
3+++ data/com.canonical.Unity.WindowStack.xml 2016-04-12 11:12:57 +0000
4@@ -22,6 +22,10 @@
5 <arg name="app_id" type="s" direction="in"/>
6 <arg name="property_names" type="as" direction="in"/>
7 </method>
8+ <method name="GetWindowBusAddress">
9+ <arg name="address_path" type="as" direction="out"/>
10+ <arg name="window_id" type="u" direction="in"/>
11+ </method>
12 <method name="GetAppIdFromPid">
13 <arg name="app_id" type="s" direction="out"/>
14 <arg name="pid" type="u" direction="in"/>
15
16=== modified file 'service/CMakeLists.txt'
17--- service/CMakeLists.txt 2015-08-20 13:44:43 +0000
18+++ service/CMakeLists.txt 2016-04-12 11:12:57 +0000
19@@ -16,6 +16,7 @@
20 ApplicationListImpl.cpp
21 Collector.cpp
22 DBusMenuCollector.cpp
23+ DBusMenuWindowCollector.cpp
24 Factory.cpp
25 GMenuCollector.cpp
26 GMenuWindowCollector.cpp
27
28=== modified file 'service/DBusMenuCollector.cpp'
29--- service/DBusMenuCollector.cpp 2014-05-13 10:23:56 +0000
30+++ service/DBusMenuCollector.cpp 2016-04-12 11:12:57 +0000
31@@ -1,5 +1,5 @@
32 /*
33- * Copyright (C) 2013 Canonical, Ltd.
34+ * Copyright (C) 2013-2016 Canonical, Ltd.
35 *
36 * This program is free software: you can redistribute it and/or modify it
37 * under the terms of the GNU General Public License version 3, as published
38@@ -14,63 +14,28 @@
39 * with this program. If not, see <http://www.gnu.org/licenses/>.
40 *
41 * Author: Pete Woods <pete.woods@canonical.com>
42+ * Andrea Azzarone <andrea.azzarone@canonical.com>
43 */
44
45-#include <common/DBusTypes.h>
46-#include <common/Localisation.h>
47 #include <service/DBusMenuCollector.h>
48-#include <service/AppmenuRegistrarInterface.h>
49
50 #include <dbusmenuimporter.h>
51+#include <QDebug>
52 #include <QMenu>
53 #include <stdexcept>
54
55-using namespace hud::common;
56 using namespace hud::service;
57
58-DBusMenuCollector::DBusMenuCollector(unsigned int windowId,
59- QSharedPointer<ComCanonicalAppMenuRegistrarInterface> registrar) :
60- m_windowId(windowId), m_registrar(registrar) {
61-
62- connect(registrar.data(),
63- SIGNAL(WindowRegistered(uint, const QString &, const QDBusObjectPath &)),
64- this,
65- SLOT( WindowRegistered(uint, const QString &, const QDBusObjectPath &)));
66-
67- QDBusPendingReply<QString, QDBusObjectPath> windowReply =
68- registrar->GetMenuForWindow(m_windowId);
69-
70- windowReply.waitForFinished();
71- if (windowReply.isError()) {
72- return;
73- }
74-
75- windowRegistered(windowReply.argumentAt<0>(), windowReply.argumentAt<1>());
76-}
77-
78-DBusMenuCollector::~DBusMenuCollector() {
79-}
80-
81-void DBusMenuCollector::windowRegistered(const QString &service,
82- const QDBusObjectPath &menuObjectPath) {
83-
84- if (service.isEmpty()) {
85- return;
86- }
87-
88- m_service = service;
89- m_path = menuObjectPath;
90-
91- disconnect(m_registrar.data(),
92- SIGNAL(
93- WindowRegistered(uint, const QString &, const QDBusObjectPath &)),
94- this,
95- SLOT(
96- WindowRegistered(uint, const QString &, const QDBusObjectPath &)));
97+DBusMenuCollector::DBusMenuCollector(const QString &service,
98+ const QDBusObjectPath &menuObjectPath) :
99+ m_service(service), m_path(menuObjectPath) {
100+
101+ if (m_service.isEmpty()) {
102+ return;
103+ }
104
105 m_menuImporter.reset(
106- new DBusMenuImporter(m_service, m_path.path(),
107- DBusMenuImporterType::SYNCHRONOUS));
108+ new DBusMenuImporter(m_service, m_path.path(), DBusMenuImporterType::SYNCHRONOUS));
109
110 CollectorToken::Ptr collectorToken(m_collectorToken);
111 if(collectorToken) {
112@@ -78,6 +43,9 @@
113 }
114 }
115
116+DBusMenuCollector::~DBusMenuCollector() {
117+}
118+
119 bool DBusMenuCollector::isValid() const {
120 return !m_menuImporter.isNull();
121 }
122@@ -173,13 +141,3 @@
123 qDebug() << e.what();
124 }
125 }
126-
127-void DBusMenuCollector::WindowRegistered(uint windowId, const QString &service,
128- const QDBusObjectPath &menuObjectPath) {
129- // Simply ignore updates for other windows
130- if (windowId != m_windowId) {
131- return;
132- }
133-
134- windowRegistered(service, menuObjectPath);
135-}
136
137=== modified file 'service/DBusMenuCollector.h'
138--- service/DBusMenuCollector.h 2014-03-26 09:00:05 +0000
139+++ service/DBusMenuCollector.h 2016-04-12 11:12:57 +0000
140@@ -1,5 +1,5 @@
141 /*
142- * Copyright (C) 2013 Canonical, Ltd.
143+ * Copyright (C) 2013-2016 Canonical, Ltd.
144 *
145 * This program is free software: you can redistribute it and/or modify it
146 * under the terms of the GNU General Public License version 3, as published
147@@ -14,6 +14,7 @@
148 * with this program. If not, see <http://www.gnu.org/licenses/>.
149 *
150 * Author: Pete Woods <pete.woods@canonical.com>
151+ * Andrea Azzarone <andrea.azzarone@canonical.com>
152 */
153
154 #ifndef HUD_SERVICE_DBUSMENUCOLLECTOR_H_
155@@ -21,10 +22,8 @@
156
157 #include <service/Collector.h>
158
159-#include <QDBusConnection>
160-#include <memory>
161+#include <QDBusObjectPath>
162
163-class ComCanonicalAppMenuRegistrarInterface;
164 class DBusMenuImporter;
165
166 QT_BEGIN_NAMESPACE
167@@ -34,46 +33,27 @@
168 namespace hud {
169 namespace service {
170
171-class DBusMenuCollector: public Collector, public std::enable_shared_from_this<
172- DBusMenuCollector> {
173-Q_OBJECT
174+class DBusMenuCollector: public Collector,
175+ public std::enable_shared_from_this<DBusMenuCollector> {
176 public:
177 typedef std::shared_ptr<DBusMenuCollector> Ptr;
178
179- DBusMenuCollector(unsigned int windowId,
180- QSharedPointer<ComCanonicalAppMenuRegistrarInterface> appmenu);
181-
182+ DBusMenuCollector(const QString &service, const QDBusObjectPath &menuObjectPath);
183 virtual ~DBusMenuCollector();
184
185 virtual bool isValid() const override;
186-
187 virtual QList<CollectorToken::Ptr> activate() override;
188
189-protected Q_SLOTS:
190- void WindowRegistered(uint windowId, const QString &service,
191- const QDBusObjectPath &menuObjectPath);
192-
193-protected:
194- virtual void deactivate();
195-
196- void windowRegistered(const QString &service,
197- const QDBusObjectPath &menuObjectPath);
198-
199-protected:
200+protected:
201+ virtual void deactivate() override;
202+
203 void openMenu(QMenu *menu, unsigned int &limit);
204-
205 void hideMenu(QMenu *menu, unsigned int &limit);
206
207- unsigned int m_windowId;
208-
209- QSharedPointer<ComCanonicalAppMenuRegistrarInterface> m_registrar;
210-
211 QWeakPointer<CollectorToken> m_collectorToken;
212-
213 QSharedPointer<DBusMenuImporter> m_menuImporter;
214
215 QString m_service;
216-
217 QDBusObjectPath m_path;
218 };
219
220
221=== added file 'service/DBusMenuWindowCollector.cpp'
222--- service/DBusMenuWindowCollector.cpp 1970-01-01 00:00:00 +0000
223+++ service/DBusMenuWindowCollector.cpp 2016-04-12 11:12:57 +0000
224@@ -0,0 +1,141 @@
225+/*
226+ * Copyright (C) 2016 Canonical, Ltd.
227+ *
228+ * This program is free software: you can redistribute it and/or modify it
229+ * under the terms of the GNU General Public License version 3, as published
230+ * by the Free Software Foundation.
231+ *
232+ * This program is distributed in the hope that it will be useful, but
233+ * WITHOUT ANY WARRANTY; without even the implied warranties of
234+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
235+ * PURPOSE. See the GNU General Public License for more details.
236+ *
237+ * You should have received a copy of the GNU General Public License along
238+ * with this program. If not, see <http://www.gnu.org/licenses/>.
239+ *
240+ * Author: Andrea Azzarone <andrea.azzarone@canonical.com>
241+ */
242+
243+#include <common/DBusTypes.h>
244+#include <common/WindowStackInterface.h>
245+#include <service/AppmenuRegistrarInterface.h>
246+#include <service/DBusMenuWindowCollector.h>
247+#include <service/Factory.h>
248+
249+#include <QStringList>
250+
251+using namespace hud::common;
252+using namespace hud::service;
253+
254+DBusMenuWindowCollector::DBusMenuWindowCollector(unsigned int windowId,
255+ QSharedPointer<ComCanonicalUnityWindowStackInterface> windowStack,
256+ QSharedPointer<ComCanonicalAppMenuRegistrarInterface> registrar,
257+ Factory &factory) :
258+ m_windowId(windowId), m_registrar(registrar), m_factory(factory) {
259+
260+ connect(registrar.data(),
261+ SIGNAL(WindowRegistered(uint, const QString &, const QDBusObjectPath &)),
262+ this,
263+ SLOT(WindowRegistered(uint, const QString &, const QDBusObjectPath &)));
264+
265+ QDBusPendingReply<QStringList> windowDBusAddressReply(
266+ windowStack->GetWindowBusAddress(windowId));
267+
268+ // Window action menu
269+ windowDBusAddressReply.waitForFinished();
270+ if (!windowDBusAddressReply.isError()) {
271+ QStringList windowDBusAddress(windowDBusAddressReply);
272+
273+ if (windowDBusAddress.size() == 2) {
274+ const QString &name = windowDBusAddress.at(0);
275+ const QString &path = windowDBusAddress.at(1);
276+
277+ if (!name.isEmpty() && !path.isEmpty())
278+ m_am_collector = factory.newDBusMenuCollector(name, QDBusObjectPath(path));
279+ }
280+ }
281+
282+ // AppMenu
283+ QDBusPendingReply<QString, QDBusObjectPath> windowReply =
284+ registrar->GetMenuForWindow(m_windowId);
285+
286+ windowReply.waitForFinished();
287+ if (windowReply.isError()) {
288+ return;
289+ }
290+
291+ windowRegistered(windowReply.argumentAt<0>(), windowReply.argumentAt<1>());
292+}
293+
294+DBusMenuWindowCollector::~DBusMenuWindowCollector() {
295+}
296+
297+bool DBusMenuWindowCollector::isValid() const {
298+ return m_collector || m_am_collector;
299+}
300+
301+static void setPropertyForAllActions(QMenu *menu) {
302+ if (!menu)
303+ return;
304+
305+ for (QAction *action : menu->actions()) {
306+ if (!action->isEnabled()) {
307+ continue;
308+ }
309+
310+ if (action->isSeparator()) {
311+ continue;
312+ }
313+
314+ action->setProperty("searchByMnemonic", true);
315+ setPropertyForAllActions(action->menu());
316+ }
317+}
318+
319+QList<CollectorToken::Ptr> DBusMenuWindowCollector::activate() {
320+ QList<CollectorToken::Ptr> ret;
321+
322+ if (m_am_collector) {
323+ QList<CollectorToken::Ptr> tokens = m_am_collector->activate();
324+
325+ for (CollectorToken::Ptr token : tokens) {
326+ setPropertyForAllActions(token->menu());
327+ }
328+
329+ ret.append(tokens);
330+ }
331+
332+ if (m_collector) {
333+ ret.append(m_collector->activate());
334+ }
335+
336+ return ret;
337+}
338+
339+void DBusMenuWindowCollector::deactivate() {
340+}
341+
342+void DBusMenuWindowCollector::WindowRegistered(uint windowId, const QString &service,
343+ const QDBusObjectPath &menuObjectPath) {
344+ // Simply ignore updates for other windows
345+ if (windowId != m_windowId) {
346+ return;
347+ }
348+
349+ windowRegistered(service, menuObjectPath);
350+}
351+
352+void DBusMenuWindowCollector::windowRegistered(const QString &service,
353+ const QDBusObjectPath &menuObjectPath) {
354+
355+ if (service.isEmpty()) {
356+ return;
357+ }
358+
359+ disconnect(m_registrar.data(),
360+ SIGNAL(WindowRegistered(uint, const QString &, const QDBusObjectPath &)),
361+ this,
362+ SLOT(WindowRegistered(uint, const QString &, const QDBusObjectPath &)));
363+
364+ m_collector = m_factory.newDBusMenuCollector(service, menuObjectPath);
365+}
366
367=== added file 'service/DBusMenuWindowCollector.h'
368--- service/DBusMenuWindowCollector.h 1970-01-01 00:00:00 +0000
369+++ service/DBusMenuWindowCollector.h 2016-04-12 11:12:57 +0000
370@@ -0,0 +1,72 @@
371+/*
372+ * Copyright (C) 2016 Canonical, Ltd.
373+ *
374+ * This program is free software: you can redistribute it and/or modify it
375+ * under the terms of the GNU General Public License version 3, as published
376+ * by the Free Software Foundation.
377+ *
378+ * This program is distributed in the hope that it will be useful, but
379+ * WITHOUT ANY WARRANTY; without even the implied warranties of
380+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
381+ * PURPOSE. See the GNU General Public License for more details.
382+ *
383+ * You should have received a copy of the GNU General Public License along
384+ * with this program. If not, see <http://www.gnu.org/licenses/>.
385+ *
386+ * Author: Andrea Azzarone <andrea.azzarone@canonical.com>
387+ */
388+
389+#ifndef HUD_SERVICE_DBUSMENUWINDOWCOLLECTOR_H_
390+#define HUD_SERVICE_DBUSMENUWINDOWCOLLECTOR_H_
391+
392+#include <service/Collector.h>
393+
394+class ComCanonicalAppMenuRegistrarInterface;
395+class ComCanonicalUnityWindowStackInterface;
396+
397+namespace qtgmenu {
398+class QtGMenuImporter;
399+}
400+
401+namespace hud {
402+namespace service {
403+
404+class Factory;
405+
406+class DBusMenuWindowCollector: public Collector,
407+ public std::enable_shared_from_this<DBusMenuWindowCollector> {
408+Q_OBJECT
409+public:
410+ typedef std::shared_ptr<DBusMenuWindowCollector> Ptr;
411+
412+ DBusMenuWindowCollector(unsigned int windowId,
413+ QSharedPointer<ComCanonicalUnityWindowStackInterface> windowStack,
414+ QSharedPointer<ComCanonicalAppMenuRegistrarInterface> registrar,
415+ Factory &factory);
416+ virtual ~DBusMenuWindowCollector();
417+
418+ virtual bool isValid() const override;
419+ virtual QList<CollectorToken::Ptr> activate() override;
420+
421+protected Q_SLOTS:
422+ void WindowRegistered(uint windowId, const QString &service,
423+ const QDBusObjectPath &menuObjectPath);
424+
425+protected:
426+ virtual void deactivate() override;
427+
428+private:
429+ void windowRegistered(const QString &service,
430+ const QDBusObjectPath &menuObjectPath);
431+
432+ Collector::Ptr m_am_collector;
433+ Collector::Ptr m_collector;
434+ unsigned int m_windowId;
435+ QSharedPointer<ComCanonicalAppMenuRegistrarInterface> m_registrar;
436+ Factory &m_factory;
437+};
438+
439+}
440+}
441+
442+#endif /* HUD_SERVICE_DBUSMENUWINDOWCOLLECTOR_H_ */
443
444=== modified file 'service/Factory.cpp'
445--- service/Factory.cpp 2015-08-20 13:44:43 +0000
446+++ service/Factory.cpp 2016-04-12 11:12:57 +0000
447@@ -161,10 +161,9 @@
448 return WindowContext::Ptr(new WindowContextImpl(*this));
449 }
450
451-Collector::Ptr Factory::newDBusMenuCollector(unsigned int windowId,
452- const QString &applicationId) {
453- Q_UNUSED(applicationId);
454- return Collector::Ptr(new DBusMenuCollector(windowId, singletonAppmenu()));
455+Collector::Ptr Factory::newDBusMenuCollector(const QString &service,
456+ const QDBusObjectPath &menuObjectPath) {
457+ return Collector::Ptr(new DBusMenuCollector(service, menuObjectPath));
458 }
459
460 Collector::Ptr Factory::newGMenuCollector(const QString &name,
461@@ -187,3 +186,9 @@
462 new GMenuWindowCollector(windowId, applicationId,
463 singletonWindowStack(), *this));
464 }
465+
466+Collector::Ptr Factory::newDBusMenuWindowCollector(unsigned int windowId) {
467+ return Collector::Ptr(
468+ new DBusMenuWindowCollector(windowId,
469+ singletonWindowStack(), singletonAppmenu(), *this));
470+}
471
472=== modified file 'service/Factory.h'
473--- service/Factory.h 2015-08-20 11:12:22 +0000
474+++ service/Factory.h 2016-04-12 11:12:57 +0000
475@@ -23,6 +23,7 @@
476 #include <service/Application.h>
477 #include <service/ApplicationList.h>
478 #include <service/DBusMenuCollector.h>
479+#include <service/DBusMenuWindowCollector.h>
480 #include <service/GMenuWindowCollector.h>
481 #include <service/GMenuCollector.h>
482 #include <service/ItemStore.h>
483@@ -87,8 +88,8 @@
484 virtual WindowToken::Ptr newWindowToken(const QString &applicationId,
485 QList<CollectorToken::Ptr> tokens);
486
487- virtual Collector::Ptr newDBusMenuCollector(unsigned int windowId,
488- const QString &applicationId);
489+ virtual Collector::Ptr newDBusMenuCollector(const QString &service,
490+ const QDBusObjectPath &menuObjectPath);
491
492 virtual Collector::Ptr newGMenuCollector(const QString &name,
493 const QMap<QString, QDBusObjectPath> &actions,
494@@ -101,6 +102,8 @@
495 virtual Collector::Ptr newGMenuWindowCollector(unsigned int windowId,
496 const QString &applicationId);
497
498+ virtual Collector::Ptr newDBusMenuWindowCollector(unsigned int windowId);
499+
500 protected:
501 QDBusConnection m_sessionBus;
502
503
504=== modified file 'service/ItemStore.cpp'
505--- service/ItemStore.cpp 2014-03-24 17:19:58 +0000
506+++ service/ItemStore.cpp 2016-04-12 11:12:57 +0000
507@@ -61,6 +61,16 @@
508 return action->text().remove(SINGLE_AMPERSAND).replace("&&", "&");
509 }
510
511+static QChar getMnemonic(const QAction *action) {
512+ int ampersandIndex = action->text().indexOf(SINGLE_AMPERSAND);
513+
514+ if (ampersandIndex < 0 || ampersandIndex >= action->text().length() - 1) {
515+ return 0;
516+ }
517+
518+ return action->text()[ampersandIndex+1].toLower();
519+}
520+
521 void ItemStore::indexMenu(const QMenu *menu, const QMenu *root,
522 const QStringList &stack, const QList<int> &index) {
523 int i(-1);
524@@ -74,6 +84,8 @@
525 continue;
526 }
527
528+ bool searchByMnemonic(action->property("searchByMnemonic").toBool());
529+
530 QStringList text(
531 convertActionText(action).remove(BAD_CHARACTERS).split(
532 WHITESPACE));
533@@ -91,6 +103,11 @@
534 } else {
535 Document document(m_nextId);
536
537+ if (searchByMnemonic) {
538+ QChar mnemonic = getMnemonic(action);
539+ m_mnemonic2DocumentId[mnemonic] = m_nextId;
540+ }
541+
542 WordList command;
543 for (const QString &word : text) {
544 command.addWord(Word(word.toUtf8().constData()));
545@@ -199,6 +216,11 @@
546
547 int queryLength(query.length());
548
549+ if (queryLength == 1 && m_mnemonic2DocumentId.contains(query[0])) {
550+ int docId = m_mnemonic2DocumentId[query[0]];
551+ addResult(docId, stringMatcher, queryLength, 1.0, results);
552+ }
553+
554 size_t maxResults = std::min(matchResults.size(), size_t(20));
555
556 for (size_t i(0); i < maxResults; ++i) {
557
558=== modified file 'service/ItemStore.h'
559--- service/ItemStore.h 2014-03-19 23:26:48 +0000
560+++ service/ItemStore.h 2016-04-12 11:12:57 +0000
561@@ -94,6 +94,8 @@
562 QMap<DocumentID, Item::Ptr> m_items;
563
564 QMap<QString, Item::Ptr> m_toolbarItems;
565+
566+ QMap<QChar, int> m_mnemonic2DocumentId;
567 };
568
569 }
570
571=== modified file 'service/WindowImpl.cpp'
572--- service/WindowImpl.cpp 2014-03-19 23:26:48 +0000
573+++ service/WindowImpl.cpp 2016-04-12 11:12:57 +0000
574@@ -78,7 +78,7 @@
575 WindowContextImpl(factory), m_applicationId(applicationId), m_allWindowsContext(
576 allWindowsContext) {
577
578- m_dbusMenuCollector = factory.newDBusMenuCollector(windowId, applicationId);
579+ m_dbusMenuCollector = factory.newDBusMenuWindowCollector(windowId);
580 m_gMenuCollector = factory.newGMenuWindowCollector(windowId, applicationId);
581 }
582
583
584=== modified file 'tests/unit/service/Mocks.h'
585--- tests/unit/service/Mocks.h 2014-03-19 23:26:48 +0000
586+++ tests/unit/service/Mocks.h 2016-04-12 11:12:57 +0000
587@@ -44,7 +44,7 @@
588
589 MOCK_METHOD0(singletonUsageTracker, UsageTracker::Ptr());
590
591- MOCK_METHOD2(newDBusMenuCollector, Collector::Ptr(unsigned int, const QString &));
592+ MOCK_METHOD1(newDBusMenuWindowCollector, Collector::Ptr(unsigned int));
593
594 MOCK_METHOD2(newGMenuWindowCollector, Collector::Ptr(unsigned int, const QString &));
595
596
597=== modified file 'tests/unit/service/TestWindow.cpp'
598--- tests/unit/service/TestWindow.cpp 2014-03-05 12:59:07 +0000
599+++ tests/unit/service/TestWindow.cpp 2016-04-12 11:12:57 +0000
600@@ -52,8 +52,8 @@
601 allWindowsCollector.reset(new NiceMock<MockCollector>());
602 ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(true));
603
604- dbusMenuCollector.reset(new NiceMock<MockCollector>());
605- ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(true));
606+ dbusmenuWindowCollector.reset(new NiceMock<MockCollector>());
607+ ON_CALL(*dbusmenuWindowCollector, isValid()).WillByDefault(Return(true));
608
609 gmenuWindowCollector.reset(new NiceMock<MockCollector>());
610 ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(true));
611@@ -66,8 +66,8 @@
612 }
613
614 Window::Ptr createWindow() {
615- EXPECT_CALL(factory, newDBusMenuCollector(1234, QString("application-id"))).Times(
616- 1).WillOnce(Return(dbusMenuCollector));
617+ EXPECT_CALL(factory, newDBusMenuWindowCollector(1234)).Times(
618+ 1).WillOnce(Return(dbusmenuWindowCollector));
619 EXPECT_CALL(factory, newGMenuWindowCollector(1234, QString("application-id"))).Times(
620 1).WillOnce(Return(gmenuWindowCollector));
621
622@@ -88,7 +88,7 @@
623
624 shared_ptr<MockCollector> allWindowsCollector;
625
626- shared_ptr<MockCollector> dbusMenuCollector;
627+ shared_ptr<MockCollector> dbusmenuWindowCollector;
628
629 shared_ptr<MockCollector> gmenuWindowCollector;
630
631@@ -106,21 +106,22 @@
632 ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(false));
633 ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false));
634
635- QMenu dbusMenuCollectorMenu;
636- CollectorToken::Ptr dbusMenuCollectorToken(
637- new CollectorToken(dbusMenuCollector, &dbusMenuCollectorMenu));
638- EXPECT_CALL(*dbusMenuCollector, activate()).Times(1).WillOnce(
639- Return(QList<CollectorToken::Ptr>() << dbusMenuCollectorToken));
640+ QMenu dbusmenuWindowCollectorMenu;
641+ CollectorToken::Ptr dbusmenuWindowCollectorToken(
642+ new CollectorToken(dbusmenuWindowCollector,
643+ &dbusmenuWindowCollectorMenu));
644+ EXPECT_CALL(*dbusmenuWindowCollector, activate()).Times(1).WillOnce(
645+ Return(QList<CollectorToken::Ptr>() << dbusmenuWindowCollectorToken));
646
647 WindowToken::Ptr token(window->activate());
648- EXPECT_EQ(QList<CollectorToken::Ptr>() << dbusMenuCollectorToken,
649+ EXPECT_EQ(QList<CollectorToken::Ptr>() << dbusmenuWindowCollectorToken,
650 token->tokens());
651 }
652
653 TEST_F(TestWindow, ActivateOnlyWithGMenu) {
654 Window::Ptr window(createWindow());
655
656- ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(false));
657+ ON_CALL(*dbusmenuWindowCollector, isValid()).WillByDefault(Return(false));
658 ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(false));
659 ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false));
660
661@@ -139,7 +140,7 @@
662 TEST_F(TestWindow, ActivateOnlyWithValidAllWindowsContext) {
663 Window::Ptr window(createWindow());
664
665- ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(false));
666+ ON_CALL(*dbusmenuWindowCollector, isValid()).WillByDefault(Return(false));
667 ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(false));
668 ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false));
669
670@@ -160,7 +161,7 @@
671 TEST_F(TestWindow, ActivateOnlyWithValidWindowContext) {
672 Window::Ptr window(createWindow());
673
674- ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(false));
675+ ON_CALL(*dbusmenuWindowCollector, isValid()).WillByDefault(Return(false));
676 ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(false));
677 ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(false));
678
679@@ -201,11 +202,12 @@
680 EXPECT_CALL(*gmenuWindowCollector, activate()).Times(1).WillOnce(
681 Return(QList<CollectorToken::Ptr>() << gmenuWindowCollectorToken));
682
683- QMenu dbusMenuCollectorMenu;
684- CollectorToken::Ptr dbusMenuCollectorToken(
685- new CollectorToken(dbusMenuCollector, &dbusMenuCollectorMenu));
686- EXPECT_CALL(*dbusMenuCollector, activate()).Times(1).WillOnce(
687- Return(QList<CollectorToken::Ptr>() << dbusMenuCollectorToken));
688+ QMenu dbusmenuWindowCollectorMenu;
689+ CollectorToken::Ptr dbusmenuWindowCollectorToken(
690+ new CollectorToken(dbusmenuWindowCollector,
691+ &dbusmenuWindowCollectorMenu));
692+ EXPECT_CALL(*dbusmenuWindowCollector, activate()).Times(1).WillOnce(
693+ Return(QList<CollectorToken::Ptr>() << dbusmenuWindowCollectorToken));
694
695 QMenu allWindowsCollectorMenu;
696 CollectorToken::Ptr allWindowsCollectorToken(
697@@ -217,7 +219,7 @@
698
699 WindowToken::Ptr token(window->activate());
700 EXPECT_EQ(
701- QList<CollectorToken::Ptr>() << dbusMenuCollectorToken
702+ QList<CollectorToken::Ptr>() << dbusmenuWindowCollectorToken
703 << gmenuWindowCollectorToken << allWindowsCollectorToken,
704 token->tokens());
705
706@@ -230,8 +232,8 @@
707 Return(QList<CollectorToken::Ptr>() << gmenuWindowCollectorTokenChanged));
708
709 // Re-prime the other collectors
710- EXPECT_CALL(*dbusMenuCollector, activate()).Times(1).WillOnce(
711- Return(QList<CollectorToken::Ptr>() << dbusMenuCollectorToken));
712+ EXPECT_CALL(*dbusmenuWindowCollector, activate()).Times(1).WillOnce(
713+ Return(QList<CollectorToken::Ptr>() << dbusmenuWindowCollectorToken));
714 EXPECT_CALL(*allWindowsCollector, activate()).Times(1).WillOnce(
715 Return(QList<CollectorToken::Ptr>() << allWindowsCollectorToken));
716
717@@ -239,7 +241,7 @@
718 EXPECT_NE(token, tokenChanged);
719
720 EXPECT_EQ(
721- QList<CollectorToken::Ptr>() << dbusMenuCollectorToken
722+ QList<CollectorToken::Ptr>() << dbusmenuWindowCollectorToken
723 << gmenuWindowCollectorTokenChanged
724 << allWindowsCollectorToken, tokenChanged->tokens());
725 }
726
727=== modified file 'window-stack-bridge/AbstractWindowStack.h'
728--- window-stack-bridge/AbstractWindowStack.h 2013-12-18 15:19:38 +0000
729+++ window-stack-bridge/AbstractWindowStack.h 2016-04-12 11:12:57 +0000
730@@ -52,6 +52,8 @@
731 virtual QStringList GetWindowProperties(uint windowId, const QString &appId,
732 const QStringList &names) = 0;
733
734+ virtual QStringList GetWindowBusAddress(uint windowId) = 0;
735+
736 Q_SIGNALS:
737 void FocusedWindowChanged(uint windowId, const QString &appId, uint stage);
738
739
740=== modified file 'window-stack-bridge/BamfWindowStack.cpp'
741--- window-stack-bridge/BamfWindowStack.cpp 2013-12-18 15:19:38 +0000
742+++ window-stack-bridge/BamfWindowStack.cpp 2016-04-12 11:12:57 +0000
743@@ -84,6 +84,16 @@
744 return m_windowId;
745 }
746
747+QString BamfWindow::service() const
748+{
749+ return m_window.service();
750+}
751+
752+QString BamfWindow::path() const
753+{
754+ return m_window.path();
755+}
756+
757 const QString & BamfWindow::applicationId() {
758 return m_applicationId;
759 }
760@@ -237,6 +247,17 @@
761 return result;
762 }
763
764+QStringList BamfWindowStack::GetWindowBusAddress(uint windowId) {
765+ const auto window = m_windowsById[windowId];
766+
767+ if (window == nullptr) {
768+ sendErrorReply(QDBusError::InvalidArgs, "Unable to find windowId");
769+ return {};
770+ }
771+
772+ return {window->service(), window->path()};
773+}
774+
775 void BamfWindowStack::ActiveWindowChanged(const QString &oldWindowPath,
776 const QString &newWindowPath) {
777 Q_UNUSED(oldWindowPath);
778
779=== modified file 'window-stack-bridge/BamfWindowStack.h'
780--- window-stack-bridge/BamfWindowStack.h 2013-12-18 15:19:38 +0000
781+++ window-stack-bridge/BamfWindowStack.h 2016-04-12 11:12:57 +0000
782@@ -34,6 +34,10 @@
783
784 unsigned int windowId();
785
786+ QString service() const;
787+
788+ QString path() const;
789+
790 const QString & applicationId();
791
792 const QString xProp(const QString &property);
793@@ -70,6 +74,8 @@
794 QStringList GetWindowProperties(uint windowId, const QString &appId,
795 const QStringList &names) override;
796
797+ QStringList GetWindowBusAddress(uint windowId) override;
798+
799 protected Q_SLOTS:
800 void ActiveWindowChanged(const QString &oldWindow,
801 const QString &newWindow);

Subscribers

People subscribed via source and target branches