Merge lp:~indicator-applet-developers/hud/support-unity8-window-stack into lp:hud/13.10

Proposed by Pete Woods
Status: Merged
Approved by: Ted Gould
Approved revision: 347
Merged at revision: 329
Proposed branch: lp:~indicator-applet-developers/hud/support-unity8-window-stack
Merge into: lp:hud/13.10
Diff against target: 3307 lines (+1672/-789)
35 files modified
CMakeLists.txt (+18/-12)
data/CMakeLists.txt (+15/-0)
data/com.canonical.Unity.WindowStack.xml (+38/-0)
data/hud.conf.in (+13/-0)
data/org.ayatana.bamf.view.xml (+110/-0)
data/org.ayatana.bamf.xml (+88/-0)
data/window-stack-bridge.conf.in (+15/-0)
debian/control (+1/-1)
debian/rules (+3/-1)
src/CMakeLists.txt (+12/-4)
src/abstract-app.h (+0/-55)
src/application-list.c (+152/-473)
src/application-source-context.c (+36/-16)
src/application-source-context.h (+2/-2)
src/application-source.c (+31/-148)
src/application-source.h (+7/-9)
src/dbusmenu-collector.c (+2/-8)
src/dbusmenu-collector.h (+2/-2)
src/menumodel-collector.c (+11/-40)
src/menumodel-collector.h (+7/-2)
src/service.c (+9/-8)
src/window-info.c (+139/-0)
src/window-info.h (+69/-0)
tests/CMakeLists.txt (+8/-2)
tests/test-application-list.c (+48/-6)
window-stack-bridge/AbstractWindowStack.cpp (+75/-0)
window-stack-bridge/AbstractWindowStack.h (+102/-0)
window-stack-bridge/BamfWindowStack.cpp (+174/-0)
window-stack-bridge/BamfWindowStack.h (+90/-0)
window-stack-bridge/CMakeLists.txt (+89/-0)
window-stack-bridge/Localisation.h (+28/-0)
window-stack-bridge/PlatformApiWindowStack.cpp (+125/-0)
window-stack-bridge/PlatformApiWindowStack.h (+72/-0)
window-stack-bridge/WindowStack.h (+30/-0)
window-stack-bridge/main.cpp (+51/-0)
To merge this branch: bzr merge lp:~indicator-applet-developers/hud/support-unity8-window-stack
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
Indicator Applet Developers Pending
Review via email: mp+189810@code.launchpad.net

Commit message

Support unity8's window stack API

Description of the change

Support unity8's window stack API

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
328. By Pete Woods

The unit tests should pass now

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
329. By Pete Woods

Remove currently un-needed deps

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
330. By Pete Woods

Merge trunk

331. By Pete Woods

Add upstart job for window-stack-bridge

332. By Pete Woods

Activate the BAMF service in BamfWindowStack

333. By Pete Woods

Fix upstart job path

334. By Pete Woods

Fix window stack install path

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
335. By Pete Woods

Fix application IDs in window stack bridge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
336. By Pete Woods

Get rid of commented code

337. By Pete Woods

Attempt to fix ARM build

338. By Pete Woods

Delay DBus registeration attempt til after we check the QPA environment

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
339. By Pete Woods

Revert un-necessary change

340. By Pete Woods

Enable BAMF or PLATFORM_API, not both

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote :

* I think the window-stack-bridge upstart config should be:

   start on starting hud
   stop on stopped hud

  That way it tracks the HUD lifecycle.

* In the window-stack-bridge upstart we should put a pre-start script that will check for the DISPLAY environment variable, if it doesn't exist, stop the job. This way it only run under X11.

* debian/control: You should be able to drop the dep on libubuntu-platform-api1-dev

* debian/rules: I don't think we need any build difference between ARM and other platforms. We should be able to do the same build everywhere.

* We need to reenable the webapp-source

* application-list.c: I think the matching_setup_bamf() should probably be renamed :-)

* Seems like the window needs to be unref'd in this case:

946 + HudWindowInfo *window = hud_window_info_new(list->priv->window_stack, window_id, app_id, stack);
947 +
948 + if (hud_application_list_name_in_ignore_list (window))
949 return;

* window-info.[ch] need copyright headers

* + self->desktop_file = g_strdup_printf("/usr/share/applications/%s.desktop", app_id);, this won't work in many cases. It really needs to be based on the XDG data dirs.

* HudWindowInfo needs a dispose function to handle the unref()s. Drop references in dispose and free memory in finalize.

* HudWindowInfo should really cache window properties. The DBus calls are too expensive to not do it. At this point, this can probably be a comment and a bug, but we should at least do that.

* AbstractWindowStack::registerOnBus(), the object needs to be on the bus before getting the name. That way when other people on the bus see the name they can start grabbing the object.

* The enums for the different stages should have the value specified since they're specified in the interface.

* I don't think we need localization for the window stack utility, we want debug messages translated as we want to be able to read them :-)

* I think if we are going to use the platform API (I vote no) we should do it in a different binary, not trying to link everything together. Eventually we can drop it and BAMF depending on what get seeded.

341. By Pete Woods

Change to getting a vector of properties, and handle the method not existing

342. By Pete Woods

Fix compile error of platform API path

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
343. By Pete Woods

According to the hud-cli, it's working on the phone now

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
344. By Pete Woods

Address review comments

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
345. By Pete Woods

Fix test failure

Need more polymorphism

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
346. By Pete Woods

Just start HUD on login, no watchdog

347. By Pete Woods

Only start HUD when in unity sessions

Revision history for this message
Ted Gould (ted) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2013-09-03 20:21:45 +0000
3+++ CMakeLists.txt 2013-10-09 19:22:59 +0000
4@@ -1,4 +1,4 @@
5-project(hud C)
6+project(hud C CXX)
7 cmake_minimum_required(VERSION 2.8.9)
8
9 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
10@@ -13,6 +13,7 @@
11 option(FULL_WARNINGS "Full compiler warnings." ON)
12 option(DEBUG_MESSAGES "Print debug messages." OFF)
13 option(LOCAL_INSTALL "Support local installation." OFF)
14+option(ENABLE_BAMF "Enable building for BAMF." ON)
15 option(ENABLE_PLATFORM_API "Enable building for platform API." OFF)
16
17 # Trick the H10enable_coverage script into enabling coverage by including the text below:
18@@ -47,6 +48,11 @@
19 set(HUD_SERVICE_XML ${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.hud.xml)
20 set(HUD_APP_XML ${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.hud.Application.xml)
21
22+set(WINDOW_STACK_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.Unity.WindowStack.xml")
23+
24+set(BAMF_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/org.ayatana.bamf.xml")
25+set(BAMF_VIEW_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/org.ayatana.bamf.view.xml")
26+
27 set(HUD_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR})
28 set(HUD_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
29
30@@ -94,6 +100,12 @@
31 pkg_check_modules(DBUS REQUIRED dbus-1)
32 include_directories(${DBUS_INCLUDE_DIRS})
33
34+find_package(Qt5Core REQUIRED)
35+include_directories(${Qt5Core_INCLUDE_DIRS})
36+
37+find_package(Qt5DBus REQUIRED)
38+include_directories(${Qt5DBus_INCLUDE_DIRS})
39+
40 find_package(Vala 0.12)
41
42 find_package(GObjectIntrospection 0.9.12)
43@@ -106,17 +118,6 @@
44
45 pkg_search_module(PANGO REQUIRED pango)
46
47-pkg_search_module(BAMF libbamf3)
48-if(${BAMF_FOUND})
49- add_definitions( -DHAVE_BAMF=1 )
50- include_directories(${BAMF_INCLUDE_DIRS})
51-endif()
52-
53-if(${ENABLE_PLATFORM_API})
54- add_definitions( -DHAVE_PLATFORM_API=1 )
55- set(PHABLET_LIBRARIES "-lubuntu_application_api")
56-endif()
57-
58 if(${LOCAL_INSTALL})
59 set(DBUSSERVICEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/services/")
60 else()
61@@ -134,7 +135,11 @@
62 include_directories(${CMAKE_CURRENT_SOURCE_DIR})
63 include_directories(${CMAKE_CURRENT_BINARY_DIR})
64
65+set(CMAKE_AUTOMOC ON)
66+set(CMAKE_INCLUDE_CURRENT_DIR ON)
67+
68 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC")
69+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
70
71 add_subdirectory(data)
72 add_subdirectory(libhud-client)
73@@ -142,6 +147,7 @@
74 add_subdirectory(libhud-gtk)
75 add_subdirectory(src)
76 add_subdirectory(tools)
77+add_subdirectory(window-stack-bridge)
78
79 if(${ENABLE_TESTS})
80 enable_testing()
81
82=== modified file 'data/CMakeLists.txt'
83--- data/CMakeLists.txt 2013-06-11 17:38:18 +0000
84+++ data/CMakeLists.txt 2013-10-09 19:22:59 +0000
85@@ -64,6 +64,21 @@
86 )
87
88 ###########################
89+# Window Stack Bridge
90+###########################
91+
92+configure_file(
93+ "window-stack-bridge.conf.in"
94+ "window-stack-bridge.conf"
95+ @ONLY
96+)
97+
98+install(
99+ FILES "${CMAKE_CURRENT_BINARY_DIR}/window-stack-bridge.conf"
100+ DESTINATION "/usr/share/upstart/sessions"
101+)
102+
103+###########################
104 # GSettings
105 ###########################
106
107
108=== added file 'data/com.canonical.Unity.WindowStack.xml'
109--- data/com.canonical.Unity.WindowStack.xml 1970-01-01 00:00:00 +0000
110+++ data/com.canonical.Unity.WindowStack.xml 2013-10-09 19:22:59 +0000
111@@ -0,0 +1,38 @@
112+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
113+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
114+<node>
115+ <interface name="com.canonical.Unity.WindowStack">
116+ <signal name="FocusedWindowChanged">
117+ <arg name="window_id" type="u" direction="out"/>
118+ <arg name="app_id" type="s" direction="out"/>
119+ <arg name="stage" type="u" direction="out"/>
120+ <!-- 0, main; 1, side; 2, windowed -->
121+ </signal>
122+ <signal name="WindowCreated">
123+ <arg name="window_id" type="u" direction="out"/>
124+ <arg name="app_id" type="s" direction="out"/>
125+ </signal>
126+ <signal name="WindowDestroyed">
127+ <arg name="window_id" type="u" direction="out"/>
128+ <arg name="app_id" type="s" direction="out"/>
129+ </signal>
130+ <method name="GetWindowProperties">
131+ <arg name="values" type="as" direction="out"/>
132+ <arg name="window_id" type="u" direction="in"/>
133+ <arg name="app_id" type="s" direction="in"/>
134+ <arg name="property_names" type="as" direction="in"/>
135+ </method>
136+ <method name="GetAppIdFromPid">
137+ <arg name="app_id" type="s" direction="out"/>
138+ <arg name="pid" type="u" direction="in"/>
139+ </method>
140+ <method name="GetWindowStack">
141+ <arg type="a(usbu)" direction="out"/>
142+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;WindowInfo&gt;"/>
143+ <!-- a(window_id, app_id, focused, stage) -->
144+ <!-- Order of the array will be in "stacking order" with the first
145+ item being the entry on the top of the stack. Stages will be interleaved
146+ with the entries being in order for that stage. -->
147+ </method>
148+ </interface>
149+</node>
150
151=== modified file 'data/hud.conf.in'
152--- data/hud.conf.in 2013-10-08 14:42:47 +0000
153+++ data/hud.conf.in 2013-10-09 19:22:59 +0000
154@@ -12,5 +12,18 @@
155 # Currently started by the dbus service file
156 # start on dbus-activation com.canonical.hud
157 stop on desktop-end
158+start on started dbus and ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger) or (xsession SESSION=ubuntu))
159+
160+env HUD_SERVICE_TIMEOUT=0
161+export HUD_SERVICE_TIMEOUT
162+
163+pre-start script
164+ if [ -z $DBUS_SESSION_BUS_ADDRESS ]; then
165+ echo "Working around missing DBUS_SESSION_BUS_ADDRESS variable"
166+ printf "DuplicateSignature\0DBusSessionAddressNotSet" | /usr/share/apport/recoverable_problem -p `pidof -s -o 1 init`
167+ . "${HOME}/.cache/upstart/dbus-session"
168+ initctl set-env "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS"
169+ fi
170+end script
171
172 exec @pkglibexecdir@/hud-service
173
174=== added file 'data/org.ayatana.bamf.view.xml'
175--- data/org.ayatana.bamf.view.xml 1970-01-01 00:00:00 +0000
176+++ data/org.ayatana.bamf.view.xml 2013-10-09 19:22:59 +0000
177@@ -0,0 +1,110 @@
178+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
179+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
180+<node>
181+ <interface name="org.ayatana.bamf.view">
182+ <method name="ViewType">
183+ <arg name="view_type" type="s" direction="out"/>
184+ </method>
185+ <method name="Parents">
186+ <arg name="parents_paths" type="as" direction="out"/>
187+ </method>
188+ <method name="Children">
189+ <arg name="children_paths" type="as" direction="out"/>
190+ </method>
191+ <signal name="ChildRemoved">
192+ <arg name="path" type="s"/>
193+ </signal>
194+ <signal name="ChildAdded">
195+ <arg name="path" type="s"/>
196+ </signal>
197+ <signal name="Closed">
198+ </signal>
199+ <property name="Name" type="s" access="read"/>
200+ <property name="Icon" type="s" access="read"/>
201+ <property name="UserVisible" type="b" access="read"/>
202+ <property name="Running" type="b" access="read"/>
203+ <property name="Urgent" type="b" access="read"/>
204+ <property name="Active" type="b" access="read"/>
205+ </interface>
206+
207+ <interface name="org.ayatana.bamf.application">
208+ <method name="ShowStubs">
209+ <arg name="show_stubs" type="b" direction="out"/>
210+ </method>
211+ <method name="Xids">
212+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;uint&gt;"/>
213+ <arg name="xids" type="au" direction="out"/>
214+ </method>
215+ <method name="DesktopFile">
216+ <arg name="desktop_file" type="s" direction="out"/>
217+ </method>
218+ <method name="SupportedMimeTypes">
219+ <arg name="mime_types" type="as" direction="out"/>
220+ </method>
221+ <method name="ApplicationType">
222+ <arg name="type" type="s" direction="out"/>
223+ </method>
224+ <method name="FocusableChild">
225+ <arg name="path" type="s" direction="out"/>
226+ </method>
227+ <signal name="WindowRemoved">
228+ <arg name="path" type="s"/>
229+ </signal>
230+ <signal name="WindowAdded">
231+ <arg name="path" type="s"/>
232+ </signal>
233+ <signal name="SupportedMimeTypesChanged">
234+ <arg name="dnd_mimes" type="as"/>
235+ </signal>
236+ <signal name="DesktopFileUpdated">
237+ <arg name="desktop_file" type="s"/>
238+ </signal>
239+ </interface>
240+
241+ <interface name="org.ayatana.bamf.window">
242+ <method name="GetXid">
243+ <arg name="xid" type="u" direction="out"/>
244+ </method>
245+ <method name="GetPid">
246+ <arg name="pid" type="u" direction="out"/>
247+ </method>
248+ <method name="Transient">
249+ <arg name="path" type="s" direction="out"/>
250+ </method>
251+ <method name="WindowType">
252+ <arg name="type" type="u" direction="out"/>
253+ </method>
254+ <method name="Xprop">
255+ <arg name="xprop" type="s" direction="in"/>
256+ <arg name="name" type="s" direction="out"/>
257+ </method>
258+ <method name="Monitor">
259+ <arg name="monitor_number" type="i" direction="out"/>
260+ </method>
261+ <method name="Maximized">
262+ <arg name="maximized" type="i" direction="out"/>
263+ </method>
264+ <signal name="MonitorChanged">
265+ <arg name="oldValue" type="i" direction="out"/>
266+ <arg name="newValue" type="i" direction="out"/>
267+ </signal>
268+ <signal name="MaximizedChanged">
269+ <arg name="oldValue" type="i" direction="out"/>
270+ <arg name="newValue" type="i" direction="out"/>
271+ </signal>
272+ </interface>
273+
274+ <interface name="org.ayatana.bamf.tab">
275+ <method name="Raise">
276+ </method>
277+ <method name="Close">
278+ </method>
279+ <method name="RequestPreview">
280+ <arg type="s" name="data" direction="out"/>
281+ </method>
282+ <property name="location" type="s" access="read"/>
283+ <property name="xid" type="t" access="read"/>
284+ <property name="desktop-id" type="s" access="read"/>
285+ <property name="is-foreground-tab" type="b" access="read"/>
286+ </interface>
287+</node>
288
289=== added file 'data/org.ayatana.bamf.xml'
290--- data/org.ayatana.bamf.xml 1970-01-01 00:00:00 +0000
291+++ data/org.ayatana.bamf.xml 2013-10-09 19:22:59 +0000
292@@ -0,0 +1,88 @@
293+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
294+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
295+<node>
296+ <interface name="org.ayatana.bamf.control">
297+ <method name="Quit">
298+ </method>
299+ <method name="InsertDesktopFile">
300+ <arg name="desktop_path" type="s" direction="in"/>
301+ </method>
302+ <method name="RegisterApplicationForPid">
303+ <arg name="application" type="s" direction="in"/>
304+ <arg name="pid" type="i" direction="in"/>
305+ </method>
306+ <method name="CreateLocalDesktopFile">
307+ <arg name="application" type="s" direction="in"/>
308+ </method>
309+ </interface>
310+
311+ <interface name="org.ayatana.bamf.matcher">
312+ <method name="XidsForApplication">
313+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;uint&gt;"/>
314+ <arg name="desktop_file" type="s" direction="in"/>
315+ <arg name="xids" type="au" direction="out"/>
316+ </method>
317+ <method name="TabPaths">
318+ <arg name="paths" type="as" direction="out"/>
319+ </method>
320+ <method name="RunningApplications">
321+ <arg name="paths" type="as" direction="out"/>
322+ </method>
323+ <method name="RunningApplicationsDesktopFiles">
324+ <arg name="paths" type="as" direction="out"/>
325+ </method>
326+ <method name="RegisterFavorites">
327+ <arg name="favorites" type="as" direction="in"/>
328+ </method>
329+ <method name="PathForApplication">
330+ <arg name="desktop_file" type="s" direction="in"/>
331+ <arg name="path" type="s" direction="out"/>
332+ </method>
333+ <method name="WindowPaths">
334+ <arg name="paths" type="as" direction="out"/>
335+ </method>
336+ <method name="ApplicationPaths">
337+ <arg name="paths" type="as" direction="out"/>
338+ </method>
339+ <method name="ApplicationIsRunning">
340+ <arg name="desktop_file" type="s" direction="in"/>
341+ <arg name="running" type="b" direction="out"/>
342+ </method>
343+ <method name="ApplicationForXid">
344+ <arg name="xid" type="u" direction="in"/>
345+ <arg name="application" type="s" direction="out"/>
346+ </method>
347+ <method name="ActiveWindow">
348+ <arg name="window" type="s" direction="out"/>
349+ </method>
350+ <method name="ActiveApplication">
351+ <arg name="application" type="s" direction="out"/>
352+ </method>
353+ <method name="WindowStackForMonitor">
354+ <arg name="monitor_id" type="i" direction="in"/>
355+ <arg name="window_list" type="as" direction="out"/>
356+ </method>
357+ <signal name="ActiveApplicationChanged">
358+ <arg name="old_app" type="s"/>
359+ <arg name="new_app" type="s"/>
360+ </signal>
361+ <signal name="ActiveWindowChanged">
362+ <arg name="old_win" type="s"/>
363+ <arg name="new_win" type="s"/>
364+ </signal>
365+ <signal name="ViewClosed">
366+ <arg name="path" type="s"/>
367+ <arg name="type" type="s"/>
368+ </signal>
369+ <signal name="ViewOpened">
370+ <arg name="path" type="s"/>
371+ <arg name="type" type="s"/>
372+ </signal>
373+ <signal name="StackingOrderChanged">
374+ </signal>
375+ <signal name="RunningApplicationsChanged">
376+ <arg name="opened_desktop_files" type="as"/>
377+ <arg name="closed_desktop_files" type="as"/>
378+ </signal>
379+ </interface>
380+</node>
381
382=== added file 'data/window-stack-bridge.conf.in'
383--- data/window-stack-bridge.conf.in 1970-01-01 00:00:00 +0000
384+++ data/window-stack-bridge.conf.in 2013-10-09 19:22:59 +0000
385@@ -0,0 +1,15 @@
386+description "Window Stack Bridge"
387+
388+start on started dbus
389+stop on desktop-end
390+
391+pre-start script
392+ if [ -z $DBUS_SESSION_BUS_ADDRESS ]; then
393+ echo "Working around missing DBUS_SESSION_BUS_ADDRESS variable"
394+ printf "DuplicateSignature\0DBusSessionAddressNotSet" | /usr/share/apport/recoverable_problem -p `pidof -s -o 1 init`
395+ . "${HOME}/.cache/upstart/dbus-session"
396+ initctl set-env "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS"
397+ fi
398+end script
399+
400+exec @pkglibexecdir@/window-stack-bridge
401
402=== modified file 'debian/control'
403--- debian/control 2013-09-03 20:21:45 +0000
404+++ debian/control 2013-10-09 19:22:59 +0000
405@@ -12,7 +12,6 @@
406 gtester2xunit,
407 gtk-doc-tools,
408 intltool,
409- libbamf3-dev (>= 0.2.53) [!armhf],
410 libubuntu-platform-api1-dev [armhf],
411 libdbusmenu-glib-dev (>= 0.5.90),
412 libdbusmenu-gtk3-dev (>= 0.5.90),
413@@ -26,6 +25,7 @@
414 valac,
415 xvfb,
416 python3-dbusmock,
417+ qtbase5-dev,
418 libpocketsphinx-dev (>= 0.8),
419 libsphinxbase-dev (>= 0.8),
420 sphinx-voxforge-hmm-en,
421
422=== modified file 'debian/rules'
423--- debian/rules 2013-05-16 23:02:54 +0000
424+++ debian/rules 2013-10-09 19:22:59 +0000
425@@ -6,15 +6,17 @@
426
427 ifeq ($(DEB_HOST_ARCH),armhf)
428 ENABLE_PLATFORM_API = ON
429+ ENABLE_BAMF = OFF
430 else
431 ENABLE_PLATFORM_API = OFF
432+ ENABLE_BAMF = ON
433 endif
434
435 %:
436 dh $@
437
438 override_dh_auto_configure:
439- dh_auto_configure -- -DDEBIAN_TARGET_DIR="${DEBIAN_TARGET_DIR}" -DENABLE_DOCUMENTATION=ON -DENABLE_VOICE_TESTS=OFF -DENABLE_PLATFORM_API=$(ENABLE_PLATFORM_API)
440+ dh_auto_configure -- -DDEBIAN_TARGET_DIR="${DEBIAN_TARGET_DIR}" -DENABLE_DOCUMENTATION=ON -DENABLE_VOICE_TESTS=OFF -DENABLE_PLATFORM_API=$(ENABLE_PLATFORM_API) -DENABLE_BAMF=$(ENABLE_BAMF)
441
442 override_dh_install:
443 dh_install --fail-missing
444
445=== modified file 'src/CMakeLists.txt'
446--- src/CMakeLists.txt 2013-09-03 20:21:45 +0000
447+++ src/CMakeLists.txt 2013-10-09 19:22:59 +0000
448@@ -53,6 +53,14 @@
449 SERVICE_XML ${HUD_APP_XML}
450 )
451
452+add_gdbus_codegen(
453+OUTFILES HUD_SERVICE_GENERATED_SOURCES
454+NAME window-stack-iface
455+PREFIX com.canonical.Unity.
456+NAMESPACE DBus
457+SERVICE_XML ${WINDOW_STACK_XML}
458+)
459+
460 add_constant_template(HUD_SERVICE_GENERATED_SOURCES
461 create-db
462 create_db
463@@ -71,7 +79,6 @@
464 ###########################
465
466 set(HUD_SERVICE_LIB_HEADERS
467-abstract-app.h
468 action-muxer.h
469 application-list.h
470 application-source-context.h
471@@ -83,7 +90,7 @@
472 dbusmenu-collector.h
473 menumodel-collector.h
474 appindicator-source.h
475-webapp-source.h
476+#webapp-source.h
477 indicator-source.h
478 debug-source.h
479 source-list.h
480@@ -102,6 +109,7 @@
481 query-columns.h
482 usage-tracker.h
483 watchdog.h
484+window-info.h
485 )
486
487 set(HUD_SERVICE_LIB_SOURCES
488@@ -115,7 +123,7 @@
489 dbusmenu-collector.c
490 menumodel-collector.c
491 appindicator-source.c
492-webapp-source.c
493+#webapp-source.c
494 indicator-source.c
495 debug-source.c
496 source-list.c
497@@ -133,6 +141,7 @@
498 pronounce-dict.c
499 usage-tracker.c
500 watchdog.c
501+window-info.c
502 )
503
504 add_glib_enumtypes_t(HUD_SERVICE_LIB_SOURCES
505@@ -155,7 +164,6 @@
506 ${DBUSMENU_GLIB_LIBRARIES}
507 ${SQLITE3_LIBRARIES}
508 ${POCKETSPHINX_LIBRARIES}
509-${PHABLET_LIBRARIES}
510 ${NIH_LIBRARIES}
511 ${NIH_DBUS_LIBRARIES}
512 )
513
514=== removed file 'src/abstract-app.h'
515--- src/abstract-app.h 2013-08-21 18:10:29 +0000
516+++ src/abstract-app.h 1970-01-01 00:00:00 +0000
517@@ -1,55 +0,0 @@
518-/*
519- * Copyright © 2013 Canonical Ltd.
520- *
521- * This program is free software: you can redistribute it and/or modify it
522- * under the terms of the GNU General Public License version 3, as
523- * published by the Free Software Foundation.
524- *
525- * This program is distributed in the hope that it will be useful, but
526- * WITHOUT ANY WARRANTY; without even the implied warranties of
527- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
528- * PURPOSE. See the GNU General Public License for more details.
529- *
530- * You should have received a copy of the GNU General Public License along
531- * with this program. If not, see <http://www.gnu.org/licenses/>.
532- *
533- * Author: Ted Gould <ted@canonical.com>
534- */
535-
536-#ifndef __HUD_ABSTRACT_APP_H__
537-#define __HUD_ABSTRACT_APP_H__
538-
539-#define WINDOW_ID_ALL_WINDOWS (0)
540-
541-#ifdef HAVE_BAMF
542-
543-#include <libbamf/libbamf.h>
544-
545-typedef BamfWindow AbstractWindow;
546-typedef BamfApplication AbstractApplication;
547-
548-#define abstract_window_get_id(win) bamf_window_get_xid(win)
549-
550-#endif /* HAVE_BAMF */
551-
552-#ifdef HAVE_PLATFORM_API
553-
554-#include <glib.h>
555-
556-#define WINDOW_ID_CONSTANT (5)
557-
558-typedef struct {
559- gchar *desktop_file_hint;
560- int stage_hint;
561-} SessionProperties;
562-
563-typedef SessionProperties AbstractWindow;
564-typedef SessionProperties AbstractApplication;
565-
566-#define session_properties_get_window_id(props) WINDOW_ID_CONSTANT
567-
568-#define abstract_window_get_id(win) WINDOW_ID_CONSTANT
569-
570-#endif /* HAVE_PLATFORM_API */
571-
572-#endif /* __HUD_ABSTRACT_APP_H__ */
573
574=== modified file 'src/application-list.c'
575--- src/application-list.c 2013-08-21 18:51:50 +0000
576+++ src/application-list.c 2013-10-09 19:22:59 +0000
577@@ -22,33 +22,22 @@
578 #include "config.h"
579 #endif
580
581-#include "abstract-app.h"
582+#include "window-info.h"
583
584 #include "application-list.h"
585 #include "application-source.h"
586 #include "source.h"
587-
588-#ifdef HAVE_PLATFORM_API
589-#include <ubuntu/ui/ubuntu_ui_session_service.h>
590-#include <ubuntu/application/ui/stage.h>
591-#endif
592+#include "window-stack-iface.h"
593
594 typedef struct _HudApplicationListPrivate HudApplicationListPrivate;
595
596 struct _HudApplicationListPrivate {
597 HudApplicationSource * last_focused_main_stage_source;
598
599-#ifdef HAVE_BAMF
600- BamfMatcher * matcher;
601+ DBusWindowStack * window_stack;
602 gulong matcher_app_sig;
603 gulong matcher_view_open_sig;
604 gulong matcher_view_close_sig;
605-#endif
606-#ifdef HAVE_PLATFORM_API
607- HudApplicationSource * last_focused_side_stage_source;
608- ubuntu_ui_session_lifecycle_observer observer_definition;
609-#endif
610-
611 GHashTable * applications;
612 HudSource * used_source;
613 };
614@@ -59,39 +48,23 @@
615 static void hud_application_list_class_init (HudApplicationListClass * klass);
616 static void hud_application_list_init (HudApplicationList * self);
617 static void hud_application_list_constructed (GObject * object);
618-#ifdef HAVE_BAMF
619-static void matching_setup_bamf (HudApplicationList * self);
620-#endif
621-#ifdef HAVE_PLATFORM_API
622-static void matching_setup_hybris (HudApplicationList * self);
623-#endif
624+static void matching_setup (HudApplicationList * self);
625 static void hud_application_list_dispose (GObject * object);
626 static void hud_application_list_finalize (GObject * object);
627 static void source_iface_init (HudSourceInterface * iface);
628-#ifdef HAVE_BAMF
629-static void window_changed (BamfMatcher * matcher,
630- BamfWindow * old_window,
631- BamfWindow * new_window,
632- gpointer user_data);
633-static void view_opened (BamfMatcher * matcher,
634- BamfView * view,
635- gpointer user_data);
636-static void view_closed (BamfMatcher * matcher,
637- BamfView * view,
638- gpointer user_data);
639-#endif
640-#ifdef HAVE_PLATFORM_API
641-static void session_requested (ubuntu_ui_well_known_application app,
642- void * context);
643-static void session_born (ubuntu_ui_session_properties props,
644- void * context);
645-static void session_focused (ubuntu_ui_session_properties props,
646- void * context);
647-static void session_unfocused (ubuntu_ui_session_properties props,
648- void * context);
649-static void session_died (ubuntu_ui_session_properties props,
650- void * context);
651-#endif
652+static void window_changed (DBusWindowStack * matcher,
653+ guint window_id,
654+ const gchar * app_id,
655+ guint stage,
656+ gpointer user_data);
657+static void view_opened (DBusWindowStack * matcher,
658+ guint window_id,
659+ const gchar * app_id,
660+ gpointer user_data);
661+static void view_closed (DBusWindowStack * matcher,
662+ guint window_id,
663+ const gchar * app_id,
664+ gpointer user_data);
665 static void source_use (HudSource * hud_source);
666 static void source_unuse (HudSource * hud_source);
667 static void source_search (HudSource * hud_source,
668@@ -107,7 +80,7 @@
669 static GList * source_get_items (HudSource * list);
670 static void application_source_changed (HudSource * source,
671 gpointer user_data);
672-static gboolean hud_application_list_name_in_ignore_list (AbstractWindow *window);
673+static gboolean hud_application_list_name_in_ignore_list (HudWindowInfo *window);
674
675 G_DEFINE_TYPE_WITH_CODE (HudApplicationList, hud_application_list, G_TYPE_OBJECT,
676 G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, source_iface_init))
677@@ -124,12 +97,7 @@
678 object_class->dispose = hud_application_list_dispose;
679 object_class->finalize = hud_application_list_finalize;
680
681-#ifdef HAVE_BAMF
682- klass->matching_setup = matching_setup_bamf;
683-#endif
684-#ifdef HAVE_PLATFORM_API
685- klass->matching_setup = matching_setup_hybris;
686-#endif
687+ klass->matching_setup = matching_setup;
688
689 return;
690 }
691@@ -172,94 +140,85 @@
692 return;
693 }
694
695-#ifdef HAVE_BAMF
696 static void
697-matching_setup_bamf (HudApplicationList * self)
698+matching_setup (HudApplicationList * self)
699 {
700- self->priv->matcher = bamf_matcher_get_default();
701- self->priv->matcher_app_sig = g_signal_connect(self->priv->matcher,
702- "active-window-changed",
703+ GError *error = NULL;
704+ self->priv->window_stack = dbus_window_stack_proxy_new_for_bus_sync(
705+ G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE,
706+ "com.canonical.Unity.WindowStack",
707+ "/com/canonical/Unity/WindowStack",
708+ NULL, &error);
709+ if(self->priv->window_stack == NULL) {
710+ g_warning("Could not construct window stack proxy: %s", error->message);
711+ g_error_free(error);
712+ return;
713+ }
714+
715+ g_debug("connecting to window stack signals");
716+ self->priv->matcher_app_sig = g_signal_connect(self->priv->window_stack,
717+ "focused-window-changed",
718 G_CALLBACK(window_changed), self);
719- self->priv->matcher_view_open_sig = g_signal_connect(self->priv->matcher,
720- "view-opened",
721+ self->priv->matcher_view_open_sig = g_signal_connect(self->priv->window_stack,
722+ "window-created",
723 G_CALLBACK(view_opened), self);
724- self->priv->matcher_view_close_sig = g_signal_connect(self->priv->matcher,
725- "view-closed",
726+ self->priv->matcher_view_close_sig = g_signal_connect(self->priv->window_stack,
727+ "window-destroyed",
728 G_CALLBACK(view_closed), self);
729-
730- GList * apps = bamf_matcher_get_applications(self->priv->matcher);
731- GList * app = NULL;
732- for (app = apps; app != NULL; app = g_list_next(app)) {
733- if (!BAMF_IS_APPLICATION(app->data)) {
734- continue;
735- }
736-
737- BamfApplication * bapp = BAMF_APPLICATION(app->data);
738- gchar * app_id = hud_application_source_bamf_app_id(bapp);
739-
740- if (app_id == NULL) {
741- continue;
742- }
743-
744- HudApplicationSource * appsource = hud_application_source_new_for_app(bapp);
745- g_signal_connect(appsource, "changed", G_CALLBACK(application_source_changed), self);
746-
747- if (!hud_application_source_is_empty(appsource)) {
748- g_hash_table_insert(self->priv->applications, app_id, appsource);
749- } else {
750- g_object_unref(appsource);
751- }
752- }
753-
754- GList * windows = bamf_matcher_get_windows(self->priv->matcher);
755- GList * window = NULL;
756- for (window = windows; window != NULL; window = g_list_next(window)) {
757- if (!BAMF_IS_WINDOW(window->data)) {
758- continue;
759- }
760-
761- view_opened(self->priv->matcher, BAMF_VIEW(window->data), self);
762- }
763-
764- BamfWindow * focused = bamf_matcher_get_active_window(self->priv->matcher);
765- if (focused != NULL && !hud_application_list_name_in_ignore_list(focused)) {
766- window_changed(self->priv->matcher, NULL, focused, self);
767- } else {
768- GList * stack = bamf_matcher_get_window_stack_for_monitor(self->priv->matcher, -1);
769-
770- GList * last = g_list_last(stack);
771- while (last != NULL) {
772- if (hud_application_list_name_in_ignore_list(last->data)) {
773- last = g_list_previous(last);
774- continue;
775+ g_debug("connected to window stack signals");
776+
777+ GVariant *stack_variant = NULL;
778+ error = NULL;
779+ if (!dbus_window_stack_call_get_window_stack_sync(self->priv->window_stack,
780+ &stack_variant, NULL, &error)) {
781+ g_warning("Could not get window stack: %s", error->message);
782+ g_error_free(error);
783+ return;
784+ }
785+
786+ GVariantIter iter;
787+ g_variant_iter_init(&iter, stack_variant);
788+
789+ GVariant *window_info = NULL;
790+ while ((window_info = g_variant_iter_next_value(&iter))) {
791+ GVariantIter window_info_iter;
792+ g_variant_iter_init(&window_info_iter, window_info);
793+
794+ GVariant *window_id_variant = g_variant_iter_next_value(&window_info_iter);
795+ GVariant *app_id_variant = g_variant_iter_next_value(&window_info_iter);
796+ GVariant *focused_variant = g_variant_iter_next_value(&window_info_iter);
797+ GVariant *stage_variant = g_variant_iter_next_value(&window_info_iter);
798+
799+ view_opened(self->priv->window_stack,
800+ g_variant_get_uint32(window_id_variant),
801+ g_variant_get_string(app_id_variant, NULL),
802+ /*g_variant_get_uint32(stage_variant),*/self);
803+
804+ if (g_variant_get_boolean(focused_variant)) {
805+ HudApplicationSource *source = g_hash_table_lookup(
806+ self->priv->applications,
807+ g_variant_get_string(app_id_variant, NULL));
808+
809+ if (source
810+ && !hud_application_list_name_in_ignore_list(
811+ hud_application_source_get_application_info(
812+ source))) {
813+ window_changed(self->priv->window_stack,
814+ g_variant_get_uint32(window_id_variant),
815+ g_variant_get_string(app_id_variant, NULL),
816+ g_variant_get_uint32(stage_variant), self);
817 }
818-
819- window_changed(self->priv->matcher, NULL, last->data, self);
820- break;
821 }
822
823- g_list_free(stack);
824+ g_variant_unref (window_id_variant);
825+ g_variant_unref (app_id_variant);
826+ g_variant_unref (focused_variant);
827+ g_variant_unref (stage_variant);
828+ g_variant_unref (window_info);
829 }
830-}
831-#endif
832-
833-#ifdef HAVE_PLATFORM_API
834-static void
835-matching_setup_hybris (HudApplicationList * self)
836-{
837- self->priv->observer_definition.on_session_requested = session_requested;
838- self->priv->observer_definition.on_session_born = session_born;
839- self->priv->observer_definition.on_session_unfocused = session_unfocused;
840- self->priv->observer_definition.on_session_focused = session_focused;
841- self->priv->observer_definition.on_session_died = session_died;
842- self->priv->observer_definition.on_keyboard_geometry_changed = NULL;
843- self->priv->observer_definition.context = self;
844-
845- ubuntu_ui_session_install_session_lifecycle_observer(&self->priv->observer_definition);
846-
847- return;
848-}
849-#endif
850+
851+ g_variant_unref(stack_variant);
852+}
853
854 /* Clean up references */
855 static void
856@@ -275,37 +234,24 @@
857
858 g_clear_object(&self->priv->last_focused_main_stage_source);
859
860-#ifdef HAVE_BAMF
861- if (self->priv->matcher_app_sig != 0 && self->priv->matcher != NULL) {
862- g_signal_handler_disconnect(self->priv->matcher, self->priv->matcher_app_sig);
863+ if (self->priv->matcher_app_sig != 0 && self->priv->window_stack != NULL) {
864+ g_signal_handler_disconnect(self->priv->window_stack, self->priv->matcher_app_sig);
865 }
866 self->priv->matcher_app_sig = 0;
867-#endif
868
869-#ifdef HAVE_BAMF
870- if (self->priv->matcher_view_open_sig != 0 && self->priv->matcher != NULL) {
871- g_signal_handler_disconnect(self->priv->matcher, self->priv->matcher_view_open_sig);
872+ if (self->priv->matcher_view_open_sig != 0 && self->priv->window_stack != NULL) {
873+ g_signal_handler_disconnect(self->priv->window_stack, self->priv->matcher_view_open_sig);
874 }
875 self->priv->matcher_view_open_sig = 0;
876-#endif
877
878-#ifdef HAVE_BAMF
879- if (self->priv->matcher_view_close_sig != 0 && self->priv->matcher != NULL) {
880- g_signal_handler_disconnect(self->priv->matcher, self->priv->matcher_view_close_sig);
881+ if (self->priv->matcher_view_close_sig != 0 && self->priv->window_stack != NULL) {
882+ g_signal_handler_disconnect(self->priv->window_stack, self->priv->matcher_view_close_sig);
883 }
884 self->priv->matcher_view_close_sig = 0;
885-#endif
886-
887-#ifdef HAVE_BAMF
888- g_debug("Unrefing BAMF matcher");
889- g_clear_object(&self->priv->matcher);
890- g_debug("Unref'd BAMF matcher");
891-#endif
892-
893-#ifdef HAVE_PLATFORM_API
894- /* Nothing to do as Hybris has no way to unregister our observer */
895- g_clear_object(&self->priv->last_focused_side_stage_source);
896-#endif
897+
898+ g_debug("Unrefing window stack");
899+ g_clear_object(&self->priv->window_stack);
900+ g_debug("Unref'd window stack");
901
902 g_hash_table_remove_all(self->priv->applications);
903
904@@ -330,40 +276,28 @@
905 return;
906 }
907
908-/* Get a source from a BamfApp */
909 static HudApplicationSource *
910-bamf_app_to_source (HudApplicationList * list, AbstractApplication * bapp)
911+application_info_to_source (HudApplicationList * list, HudApplicationInfo * bapp)
912 {
913- gchar * id = hud_application_source_bamf_app_id(bapp);
914- if (id == NULL) {
915- return NULL;
916- }
917+ const gchar * id = hud_window_info_get_app_id(bapp);
918
919 HudApplicationSource * source = g_hash_table_lookup(list->priv->applications, id);
920 if (source == NULL) {
921 source = hud_application_source_new_for_app(bapp);
922 g_signal_connect(source, "changed", G_CALLBACK(application_source_changed), list);
923
924- g_hash_table_insert(list->priv->applications, id, source);
925+ g_hash_table_insert(list->priv->applications, g_strdup(id), source);
926 id = NULL; /* We used the malloc in the table */
927
928 hud_source_changed(HUD_SOURCE(list));
929 }
930
931- g_free(id);
932-
933 return source;
934 }
935
936 static gboolean
937-hud_application_list_name_in_ignore_list (AbstractWindow *window)
938+hud_application_list_name_in_ignore_list (HudWindowInfo *window)
939 {
940-#ifdef HAVE_PLATFORM_API
941- /* Hybris only supports a very limited set of windows, which
942- doesn't include any debugging tools. So we can just exit. */
943- return FALSE;
944-#endif
945-
946 static const gchar * const ignored_names[] = {
947 "Hud Prototype Test",
948 "Hud",
949@@ -380,17 +314,15 @@
950 "XdndCollectionWindowImp",
951 };
952 gboolean ignored = FALSE;
953- gchar *window_name = NULL;
954 gint i;
955
956-#ifdef HAVE_BAMF
957- window_name = bamf_view_get_name (BAMF_VIEW (window));
958+ gchar *window_name = hud_window_info_get_utf8_prop(window, "WM_NAME");
959 g_debug ("checking window name '%s'", window_name);
960-#endif
961
962- /* sometimes bamf returns NULL here... protect ourselves */
963+ /* it's possible to get NULL here */
964 if (window_name == NULL)
965- return TRUE;
966+ return FALSE;
967+
968
969 for (i = 0; i < G_N_ELEMENTS (ignored_names); i++)
970 if (g_str_equal (ignored_names[i], window_name))
971@@ -400,43 +332,38 @@
972 break;
973 }
974
975- g_free (window_name);
976+ g_free(window_name);
977
978 return ignored;
979 }
980
981-#ifdef HAVE_BAMF
982 /* Called each time the focused application changes */
983 static void
984-window_changed (BamfMatcher * matcher, G_GNUC_UNUSED BamfWindow * old_win, BamfWindow * new_win, gpointer user_data)
985+window_changed (DBusWindowStack *window_stack, guint window_id, const gchar *app_id, guint stack, gpointer user_data)
986 {
987+ g_debug("window_changed(%d, %s, %d)", window_id, app_id, stack);
988+
989 HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
990
991- if (new_win == NULL || hud_application_list_name_in_ignore_list (new_win))
992+ HudWindowInfo *window = hud_window_info_new(list->priv->window_stack, window_id, app_id, stack);
993+
994+ if (hud_application_list_name_in_ignore_list (window)) {
995+ g_object_unref(window);
996 return;
997+ }
998
999 /* Clear the last source, as we've obviously changed */
1000 g_clear_object(&list->priv->last_focused_main_stage_source);
1001
1002- /* Try to use BAMF */
1003- BamfApplication * new_app = bamf_matcher_get_application_for_window(list->priv->matcher, new_win);
1004- if (new_app == NULL || bamf_application_get_desktop_file(new_app) == NULL) {
1005- /* We can't handle things we can't identify */
1006- hud_source_changed(HUD_SOURCE(list));
1007- return;
1008- }
1009-
1010- HudApplicationSource * source = NULL;
1011-
1012- /* If we've got an app, we can find it easily */
1013- if (new_app != NULL) {
1014- source = bamf_app_to_source(list, new_app);
1015- }
1016-
1017- /* If we weren't able to use BAMF, let's try to find a source
1018+ HudApplicationSource *source = application_info_to_source(list, window);
1019+
1020+ g_debug("looking up application source for: %s", app_id);
1021+
1022+ /* If we weren't able to lookup the app, let's try to find a source
1023 for the window. */
1024 if (source == NULL) {
1025- guint32 xid = bamf_window_get_xid(new_win);
1026+ g_debug("no applicationn source was found");
1027+ guint xid = hud_window_info_get_window_id(window);
1028 GList * sources = g_hash_table_get_values(list->priv->applications);
1029 GList * lsource = NULL;
1030
1031@@ -458,207 +385,43 @@
1032
1033 list->priv->last_focused_main_stage_source = g_object_ref(source);
1034
1035- hud_application_source_focus(source, new_app, new_win);
1036-
1037- hud_source_changed(HUD_SOURCE(list));
1038-
1039- return;
1040-}
1041-#endif
1042-
1043-#ifdef HAVE_PLATFORM_API
1044-
1045-typedef struct {
1046- HudApplicationList *list;
1047- SessionProperties *props;
1048-} SessionCallbackData;
1049-
1050-static SessionCallbackData *
1051-create_session_callback_data(ubuntu_ui_session_properties props, void *context)
1052-{
1053- SessionCallbackData *data = g_new(SessionCallbackData, 1);
1054-
1055- data->list = HUD_APPLICATION_LIST(context);
1056-
1057- data->props = g_new(SessionProperties, 1);
1058- data->props->desktop_file_hint
1059- = g_strdup(ubuntu_ui_session_properties_get_desktop_file_hint(props));
1060- data->props->stage_hint = ubuntu_ui_session_properties_get_application_stage_hint(props);
1061-
1062- return data;
1063-}
1064-
1065-static void
1066-destroy_session_callback_data(SessionCallbackData *data)
1067-{
1068- g_free(data->props->desktop_file_hint);
1069- g_free(data->props);
1070- g_free(data);
1071-}
1072-
1073-
1074-/* When a session gets focus */
1075-static gboolean
1076-handle_session_focused (gpointer user_data)
1077-{
1078- SessionCallbackData *data = user_data;
1079- SessionProperties *props = data->props;
1080- HudApplicationList *list = data->list;
1081-
1082- // Do not care about anything not main or side stage
1083- if (props->stage_hint != U_MAIN_STAGE && props->stage_hint != U_SIDE_STAGE)
1084- return G_SOURCE_REMOVE;
1085-
1086-
1087- if (hud_application_list_name_in_ignore_list(props)) {
1088- return G_SOURCE_REMOVE;
1089- }
1090-
1091- HudApplicationSource * source = bamf_app_to_source(list, props);
1092- if (source == NULL) {
1093- return G_SOURCE_REMOVE;
1094- }
1095-
1096- g_debug("Changing focus to: %s", hud_application_source_get_id(source));
1097-
1098- /* NOTE: We don't really have a window to add here, but this
1099- also adjusts focus, which is how we're passing it down. So
1100- what'll happen is that this'll trigger the dummy function since
1101- we can't get window IDs anyway. */
1102- hud_application_source_focus(source, props, props);
1103-
1104- if (props->stage_hint == U_MAIN_STAGE) {
1105- g_clear_object(&list->priv->last_focused_main_stage_source);
1106- list->priv->last_focused_main_stage_source = g_object_ref(source);
1107- } else { /*U_SIDE_STAGE*/
1108- g_clear_object(&list->priv->last_focused_side_stage_source);
1109- list->priv->last_focused_side_stage_source = g_object_ref(source);
1110- }
1111-
1112- hud_source_changed(HUD_SOURCE(list));
1113-
1114- return G_SOURCE_REMOVE;
1115-}
1116-
1117-
1118-static void
1119-session_focused (ubuntu_ui_session_properties props, void * context)
1120-{
1121- SessionCallbackData *data = create_session_callback_data(props, context);
1122- g_idle_add_full(G_PRIORITY_DEFAULT,
1123- handle_session_focused,
1124- data,
1125- (GDestroyNotify)destroy_session_callback_data);
1126-}
1127-
1128-/* When something looses focus, hopefully everything is paired */
1129-static void
1130-session_unfocused (ubuntu_ui_session_properties props, void * context)
1131-{
1132- /* HudApplicationList * list = HUD_APPLICATION_LIST(context); */
1133-
1134- /* NOTE: We don't clear on unfocus because we don't know who
1135- the next focus will be, and it could be blocked. We'll always
1136- just search the last focus. */
1137-
1138- return;
1139-}
1140-
1141-/* This function does nothing, but Hybris isn't smart enough to handle
1142- NULL pointers, so we need to fill in the structure. */
1143-static void
1144-session_requested (ubuntu_ui_well_known_application app, void * context)
1145-{
1146- return;
1147-}
1148-
1149-/* Finds the application object for the session and unref's it so
1150- we'll assume it is gone, gone, gone. */
1151-/* When a session gets focus */
1152-static gboolean
1153-handle_session_died (gpointer user_data)
1154-{
1155- SessionCallbackData *data = user_data;
1156- SessionProperties *props = data->props;
1157- HudApplicationList *list = data->list;
1158-
1159- HudApplicationSource * source = bamf_app_to_source(list, props);
1160- if (source == NULL) {
1161- return G_SOURCE_REMOVE;
1162- }
1163-
1164- gchar * app_id = g_strdup(hud_application_source_get_id(source));
1165- g_debug("Source is getting removed: %s", app_id);
1166-
1167- if ((gpointer)source == (gpointer)list->priv->used_source) {
1168- hud_source_unuse(HUD_SOURCE(source));
1169- g_clear_object(&list->priv->used_source);
1170- }
1171-
1172- if ((gpointer)source == (gpointer)list->priv->last_focused_main_stage_source) {
1173- g_clear_object(&list->priv->last_focused_main_stage_source);
1174- }
1175- if ((gpointer)source == (gpointer)list->priv->last_focused_side_stage_source) {
1176- g_clear_object(&list->priv->last_focused_side_stage_source);
1177- }
1178-
1179- g_hash_table_remove(list->priv->applications, app_id);
1180- g_free(app_id);
1181-
1182- hud_source_changed(HUD_SOURCE(list));
1183-
1184- return G_SOURCE_REMOVE;
1185-}
1186-
1187-static void
1188-session_died (ubuntu_ui_session_properties props, void * context)
1189-{
1190- SessionCallbackData *data = create_session_callback_data(props, context);
1191- g_idle_add_full(G_PRIORITY_DEFAULT,
1192- handle_session_died,
1193- data,
1194- (GDestroyNotify)destroy_session_callback_data);
1195-}
1196-
1197-#endif
1198-
1199-#ifdef HAVE_BAMF
1200-/* A new view has been opened by BAMF */
1201-static void
1202-view_opened (BamfMatcher * matcher, BamfView * view, gpointer user_data)
1203-{
1204- if (!BAMF_IS_WINDOW(view)) {
1205- /* We only want windows. Sorry. */
1206- return;
1207- }
1208-
1209+ hud_application_source_focus(source, window, window);
1210+
1211+ hud_source_changed(HUD_SOURCE(list));
1212+
1213+ g_object_unref(window);
1214+
1215+ return;
1216+}
1217+
1218+
1219+/* A new view has been opened */
1220+static void
1221+view_opened (DBusWindowStack * window_stack, guint window_id, const gchar *app_id, gpointer user_data)
1222+{
1223 HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
1224- BamfApplication * app = bamf_matcher_get_application_for_window(list->priv->matcher, BAMF_WINDOW(view));
1225- if (app == NULL) {
1226- return;
1227- }
1228-
1229- HudApplicationSource * source = bamf_app_to_source(list, app);
1230+
1231+ HudWindowInfo *window = hud_window_info_new(list->priv->window_stack,
1232+ window_id, app_id, HUD_WINDOW_INFO_STAGE_MAIN);
1233+
1234+ HudApplicationSource * source = application_info_to_source(list, window);
1235 if (source == NULL) {
1236+ g_object_unref(window);
1237 return;
1238 }
1239
1240- hud_application_source_add_window(source, BAMF_WINDOW(view));
1241+ hud_application_source_add_window(source, window);
1242+
1243+ g_object_unref(window);
1244
1245 return;
1246 }
1247
1248-/* A view has been closed by BAMF */
1249+/* A view has been closed */
1250 static void
1251-view_closed (BamfMatcher * matcher, BamfView * view, gpointer user_data)
1252+view_closed (DBusWindowStack * window_stack, guint window_id, const gchar *app_id, gpointer user_data)
1253 {
1254- if (!BAMF_IS_WINDOW(view)) {
1255- /* We only want windows. Sorry. */
1256- return;
1257- }
1258-
1259- guint32 xid = abstract_window_get_id(BAMF_WINDOW(view));
1260- g_debug("Closing Window: %d", xid);
1261+ g_debug("Closing Window: %d", window_id);
1262
1263 HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
1264
1265@@ -669,47 +432,13 @@
1266 HudApplicationSource * appsource = HUD_APPLICATION_SOURCE(lsource->data);
1267 if (appsource == NULL) continue;
1268
1269- if (hud_application_source_has_xid(appsource, xid)) {
1270- hud_application_source_window_closed(appsource, BAMF_WINDOW(view));
1271+ if (hud_application_source_has_xid(appsource, window_id)) {
1272+ hud_application_source_window_closed(appsource, window_id);
1273 }
1274 }
1275
1276 return;
1277 }
1278-#endif
1279-
1280-#ifdef HAVE_PLATFORM_API
1281-/* When a new session gets created */
1282-static gboolean
1283-handle_session_born (gpointer user_data)
1284-{
1285- SessionCallbackData *data = user_data;
1286- SessionProperties *props = data->props;
1287- HudApplicationList *list = data->list;
1288-
1289- HudApplicationSource * source = bamf_app_to_source(list, props);
1290- if (source == NULL) {
1291- return G_SOURCE_REMOVE;
1292- }
1293-
1294- /* NOTE: Nothing to do here, since there are no windows and no
1295- information on them, we can't really start getting the menus
1296- from them or anything. But we can makes sure that the appliction
1297- exists in the DBus representation. */
1298-
1299- return G_SOURCE_REMOVE;
1300-}
1301-
1302-static void
1303-session_born (ubuntu_ui_session_properties props, void * context)
1304-{
1305- SessionCallbackData *data = create_session_callback_data(props, context);
1306- g_idle_add_full(G_PRIORITY_DEFAULT,
1307- handle_session_born,
1308- data,
1309- (GDestroyNotify)destroy_session_callback_data);
1310-}
1311-#endif
1312
1313 /* Source interface using this source */
1314 static void
1315@@ -723,52 +452,6 @@
1316 /* First see if we've already got it */
1317 source = list->priv->last_focused_main_stage_source;
1318
1319-#ifdef HAVE_PLATFORM_API
1320- /* Check the side stage */
1321- if (source == NULL) {
1322- source = list->priv->last_focused_side_stage_source;
1323- }
1324-#endif
1325-
1326-#ifdef HAVE_BAMF
1327- if (source == NULL) {
1328- /* Try using the application first */
1329- AbstractApplication * app = NULL;
1330- app = bamf_matcher_get_active_application(list->priv->matcher);
1331-
1332- if (app != NULL) {
1333- source = bamf_app_to_source(list, app);
1334- }
1335- }
1336-#endif
1337-
1338- /* If we weren't able to use BAMF, let's try to find a source
1339- for the window. */
1340- if (source == NULL) {
1341- guint32 xid = 0;
1342-
1343-#ifdef HAVE_BAMF
1344- xid = bamf_window_get_xid(bamf_matcher_get_active_window(list->priv->matcher));
1345-#endif
1346-#ifdef HAVE_PLATFORM_API
1347- /* Hybris has no concept of windows yet, we have to work around it with this */
1348- xid = WINDOW_ID_CONSTANT;
1349-#endif
1350-
1351- GList * sources = g_hash_table_get_values(list->priv->applications);
1352- GList * lsource = NULL;
1353-
1354- for (lsource = sources; lsource != NULL; lsource = g_list_next(lsource)) {
1355- HudApplicationSource * appsource = HUD_APPLICATION_SOURCE(lsource->data);
1356- if (appsource == NULL) continue;
1357-
1358- if (hud_application_source_has_xid(appsource, xid)) {
1359- source = appsource;
1360- break;
1361- }
1362- }
1363- }
1364-
1365 if (source == NULL) {
1366 g_warning("Unable to find source for window");
1367 return;
1368@@ -958,13 +641,9 @@
1369 {
1370 g_return_val_if_fail(HUD_IS_APPLICATION_LIST(list), NULL);
1371
1372-#ifdef HAVE_BAMF
1373 return NULL;
1374-#endif
1375-#ifdef HAVE_PLATFORM_API
1376- return HUD_SOURCE(list->priv->last_focused_side_stage_source);
1377-#endif
1378 }
1379+
1380 /**
1381 * hud_application_list_get_apps:
1382 * @list: A #HudApplicationList object
1383
1384=== modified file 'src/application-source-context.c'
1385--- src/application-source-context.c 2013-09-05 16:15:54 +0000
1386+++ src/application-source-context.c 2013-10-09 19:22:59 +0000
1387@@ -256,7 +256,7 @@
1388 HudApplicationSourceContext *
1389 hud_application_source_context_new (guint32 window_id, const gchar * context_id, const gchar * app_id, const gchar * icon, const gchar * app_path)
1390 {
1391- g_return_val_if_fail(app_id != NULL && app_id[0] != '\0', NULL);
1392+ g_return_val_if_fail(app_id != NULL, NULL); // && app_id[0] != '\0'
1393 g_return_val_if_fail(context_id == NULL || context_id[0] != '\0', NULL);
1394 g_return_val_if_fail(g_variant_is_object_path(app_path), NULL);
1395
1396@@ -389,23 +389,43 @@
1397 * Adds a window to the items indexed by this context.
1398 */
1399 void
1400-hud_application_source_context_add_window (HudApplicationSourceContext * context, AbstractWindow * window)
1401+hud_application_source_context_add_window (HudApplicationSourceContext * context, HudWindowInfo * window)
1402 {
1403 g_return_if_fail(HUD_IS_APPLICATION_SOURCE_CONTEXT(context));
1404 check_for_menu_model(context);
1405
1406- hud_menu_model_collector_add_window(context->priv->model_collector, window);
1407-
1408- if (context->priv->window_menus_dbus == NULL) {
1409- context->priv->window_menus_dbus = hud_dbusmenu_collector_new_for_window(window, context->priv->app_id, context->priv->icon, HUD_SOURCE_ITEM_TYPE_BACKGROUND_APP);
1410- } else {
1411- guint32 oldid = hud_dbusmenu_collector_get_xid(context->priv->window_menus_dbus);
1412- guint32 newid = abstract_window_get_id(window);
1413-
1414- if (oldid != newid) {
1415- g_warning("Adding a second DBus Menu window (%X) to a context. Current window (%X).", newid, oldid);
1416- }
1417- }
1418-
1419- return;
1420+ gchar *unique_bus_name = hud_window_info_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
1421+ /* If this isn't set, we won't get very far... */
1422+ if (unique_bus_name && *unique_bus_name != '\0') {
1423+
1424+ const gchar *property_names[] = { "_GTK_APP_MENU_OBJECT_PATH",
1425+ "_GTK_MENUBAR_OBJECT_PATH", "_GTK_APPLICATION_OBJECT_PATH",
1426+ "_GTK_WINDOW_OBJECT_PATH", "_UNITY_OBJECT_PATH", NULL };
1427+
1428+ gchar** properties = hud_window_info_get_utf8_properties(window,
1429+ ((const gchar * const *) &property_names));
1430+
1431+ if(properties != NULL) {
1432+ hud_menu_model_collector_add_window(context->priv->model_collector,
1433+ unique_bus_name, properties[0], properties[1],
1434+ properties[2], properties[3], properties[4]);
1435+
1436+ g_strfreev(properties);
1437+ }
1438+ }
1439+
1440+ g_free(unique_bus_name);
1441+
1442+ guint xid = hud_window_info_get_window_id(window);
1443+ if(xid != 0) {
1444+ if (context->priv->window_menus_dbus == NULL) {
1445+ context->priv->window_menus_dbus = hud_dbusmenu_collector_new_for_window(xid, context->priv->app_id, context->priv->icon, HUD_SOURCE_ITEM_TYPE_BACKGROUND_APP);
1446+ } else {
1447+ guint32 oldid = hud_dbusmenu_collector_get_xid(context->priv->window_menus_dbus);
1448+
1449+ if (oldid != xid) {
1450+ g_warning("Adding a second DBus Menu window (%X) to a context. Current window (%X).", xid, oldid);
1451+ }
1452+ }
1453+ }
1454 }
1455
1456=== modified file 'src/application-source-context.h'
1457--- src/application-source-context.h 2013-06-13 15:39:24 +0000
1458+++ src/application-source-context.h 2013-10-09 19:22:59 +0000
1459@@ -21,7 +21,7 @@
1460
1461 #include <glib-object.h>
1462 #include <gio/gio.h>
1463-#include "abstract-app.h"
1464+#include "window-info.h"
1465
1466 G_BEGIN_DECLS
1467
1468@@ -66,7 +66,7 @@
1469 GMenuModel * model,
1470 HudApplicationSourceContextModelType type);
1471 void hud_application_source_context_add_window (HudApplicationSourceContext * context,
1472- AbstractWindow * window);
1473+ HudWindowInfo * window);
1474
1475 G_END_DECLS
1476
1477
1478=== modified file 'src/application-source.c'
1479--- src/application-source.c 2013-09-05 16:15:54 +0000
1480+++ src/application-source.c 2013-10-09 19:22:59 +0000
1481@@ -41,12 +41,7 @@
1482 AppIfaceComCanonicalHudApplication * skel;
1483 gboolean used;
1484
1485-#ifdef HAVE_BAMF
1486- AbstractApplication * bamf_app;
1487-#endif
1488-#ifdef HAVE_PLATFORM_API
1489- gchar * desktop_file;
1490-#endif
1491+ HudApplicationInfo * bamf_app;
1492
1493 guint32 focused_window;
1494 GHashTable * window_contexts;
1495@@ -181,9 +176,7 @@
1496 }
1497 g_hash_table_remove_all(self->priv->connections);
1498
1499-#ifdef HAVE_BAMF
1500 g_clear_object(&self->priv->bamf_app);
1501-#endif
1502 g_clear_object(&self->priv->session);
1503
1504 G_OBJECT_CLASS (hud_application_source_parent_class)->dispose (object);
1505@@ -202,9 +195,6 @@
1506 g_clear_pointer(&self->priv->app_id, g_free);
1507 g_clear_pointer(&self->priv->path, g_free);
1508 g_clear_pointer(&self->priv->window_contexts, g_hash_table_unref);
1509-#ifdef HAVE_PLATFORM_API
1510- g_clear_pointer(&self->priv->desktop_file, g_free);
1511-#endif
1512
1513 G_OBJECT_CLASS (hud_application_source_parent_class)->finalize (object);
1514 return;
1515@@ -352,6 +342,12 @@
1516 return hud_application_source_get_app_icon(HUD_APPLICATION_SOURCE(hud_source));
1517 }
1518
1519+HudApplicationInfo *
1520+hud_application_source_get_application_info (HudApplicationSource * app)
1521+{
1522+ return app->priv->bamf_app;
1523+}
1524+
1525 static void
1526 source_get_toolbar_entries (HudSource * hud_source, GArray * toolbar)
1527 {
1528@@ -394,25 +390,15 @@
1529 * Return value: New #HudApplicationSource object
1530 */
1531 HudApplicationSource *
1532-hud_application_source_new_for_app (AbstractApplication * bapp)
1533+hud_application_source_new_for_app (HudApplicationInfo * bapp)
1534 {
1535- gchar * id = hud_application_source_bamf_app_id(bapp);
1536- if (id == NULL) {
1537- return NULL;
1538- }
1539+ const gchar * id = hud_window_info_get_app_id(bapp);
1540
1541 HudApplicationSource * source = hud_application_source_new_for_id(id);
1542- g_free(id);
1543
1544 const gchar * desktop_file = NULL;
1545-#ifdef HAVE_BAMF
1546 source->priv->bamf_app = g_object_ref(bapp);
1547- desktop_file = bamf_application_get_desktop_file(bapp);
1548-#endif
1549-#ifdef HAVE_PLATFORM_API
1550- source->priv->desktop_file = g_strdup(bapp->desktop_file_hint);
1551- desktop_file = source->priv->desktop_file;
1552-#endif
1553+ desktop_file = hud_window_info_get_desktop_file(bapp);
1554
1555 app_iface_com_canonical_hud_application_set_desktop_path(source->priv->skel, desktop_file);
1556
1557@@ -612,11 +598,6 @@
1558 while (g_variant_iter_loop(&action_iter, "(usso)", &idn, &context, &prefix, &object)) {
1559 g_debug("Adding prefix '%s' at path: %s", prefix, object);
1560
1561-#ifdef HAVE_PLATFORM_API
1562- if (idn != WINDOW_ID_ALL_WINDOWS)
1563- idn = WINDOW_ID_CONSTANT;
1564-#endif
1565-
1566 /* Catch the NULL string case */
1567 gchar * refinedcontext = NULL;
1568 if (context != NULL && context[0] != '\0') {
1569@@ -649,11 +630,6 @@
1570 while (g_variant_iter_loop(&desc_iter, "(uso)", &idn, &context, &object)) {
1571 g_debug("Adding descriptions: %s", object);
1572
1573-#ifdef HAVE_PLATFORM_API
1574- if (idn != WINDOW_ID_ALL_WINDOWS)
1575- idn = WINDOW_ID_CONSTANT;
1576-#endif
1577-
1578 /* Catch the NULL string case */
1579 gchar * refinedcontext = NULL;
1580 if (context != NULL && context[0] != '\0') {
1581@@ -725,55 +701,6 @@
1582 }
1583
1584 /**
1585- * hud_application_source_bamf_app_id:
1586- * @bapp: A #BamfApplication object
1587- *
1588- * A little helper function to genereate a constant app ID out of
1589- * BAMF Application objects. Putting this here as it seems to make
1590- * the most sense, but isn't really part of the object.
1591- *
1592- * Return value: (transfer full): ID for the application
1593- */
1594-gchar *
1595-hud_application_source_bamf_app_id (AbstractApplication * bapp)
1596-{
1597-#ifdef HAVE_BAMF
1598- g_return_val_if_fail(BAMF_IS_APPLICATION(bapp), NULL);
1599-#endif
1600-#ifdef HAVE_PLATFORM_API
1601- /* Hybris has no way to check if the pointer is valid */
1602-#endif
1603-
1604- const gchar * desktop_file = NULL;
1605-
1606-#ifdef HAVE_BAMF
1607- desktop_file = bamf_application_get_desktop_file(bapp);
1608-#endif
1609-#ifdef HAVE_PLATFORM_API
1610- desktop_file = bapp->desktop_file_hint;
1611-#endif
1612- if (desktop_file == NULL) {
1613- /* Some apps might not be identifiable. Eh, don't care then */
1614- return NULL;
1615- }
1616-
1617- gchar * basename = g_path_get_basename(desktop_file);
1618- if (basename == NULL || basename[0] == '\0' || !g_str_has_suffix(basename, ".desktop")) {
1619- /* Check to make sure it's not NULL and it returns a desktop file */
1620- g_free(basename);
1621- return NULL;
1622- }
1623-
1624- /* This is probably excessively clever, but I like it. Basically we find
1625- the last instance of .desktop and put the null there. For all practical
1626- purposes this is a NULL terminated string of the first part of the dekstop
1627- file name */
1628- g_strrstr(basename, ".desktop")[0] = '\0';
1629-
1630- return basename;
1631-}
1632-
1633-/**
1634 * hud_application_source_focus:
1635 * @app: A #HudApplicationSource object
1636 * @bapp: The #BamfApplication representing this @app
1637@@ -784,40 +711,29 @@
1638 * and make sure we're all good.
1639 */
1640 void
1641-hud_application_source_focus (HudApplicationSource * app, AbstractApplication * bapp, AbstractWindow * window)
1642+hud_application_source_focus (HudApplicationSource * app, HudApplicationInfo * bapp, HudWindowInfo * window)
1643 {
1644 g_return_if_fail(HUD_IS_APPLICATION_SOURCE(app));
1645-#ifdef HAVE_BAMF
1646- g_return_if_fail(BAMF_IS_APPLICATION(bapp));
1647-#endif
1648-#ifdef HAVE_PLATFORM_API
1649- /* Hybris has no way to check if the pointer is valid */
1650-#endif
1651+ g_return_if_fail(HUD_IS_WINDOW_INFO(bapp));
1652
1653-#ifdef HAVE_BAMF
1654 if (app->priv->bamf_app == NULL) {
1655 app->priv->bamf_app = g_object_ref(bapp);
1656 }
1657
1658+ const gchar *app_id_1 = hud_window_info_get_app_id(bapp);
1659+ const gchar *app_id_2 = hud_window_info_get_app_id(app->priv->bamf_app);
1660+
1661 /* Check to make sure we're getting the right events */
1662- if (G_UNLIKELY(app->priv->bamf_app != bapp)) {
1663- g_critical("App '%s' has been given focus events for '%s'", bamf_application_get_desktop_file(app->priv->bamf_app), bamf_application_get_desktop_file(bapp));
1664+ if (g_strcmp0(app_id_1, app_id_2)) {
1665+ g_critical("App '%s' has been given focus events for '%s'",
1666+ hud_window_info_get_app_id(app->priv->bamf_app),
1667+ hud_window_info_get_app_id(bapp));
1668 return;
1669 }
1670
1671-#endif
1672-#ifdef HAVE_PLATFORM_API
1673- if (app->priv->desktop_file == NULL) {
1674- app->priv->desktop_file = g_strdup(bapp->desktop_file_hint);
1675- app_iface_com_canonical_hud_application_set_desktop_path(app->priv->skel, app->priv->desktop_file);
1676- }
1677-#endif
1678-
1679 hud_application_source_add_window(app, window);
1680
1681- hud_application_source_set_focused_win(app, abstract_window_get_id(window));
1682-
1683- return;
1684+ hud_application_source_set_focused_win(app, hud_window_info_get_window_id(window));
1685 }
1686
1687 /**
1688@@ -867,12 +783,11 @@
1689
1690 const gchar * icon = NULL;
1691 const gchar * desktop_file = NULL;
1692-#ifdef HAVE_BAMF
1693- desktop_file = bamf_application_get_desktop_file(app->priv->bamf_app);
1694-#endif
1695-#ifdef HAVE_PLATFORM_API
1696- desktop_file = app->priv->desktop_file;
1697-#endif
1698+ if(app->priv->bamf_app == NULL) {
1699+ g_warning("Window Info was null for: %s", app->priv->app_id);
1700+ return NULL;
1701+ }
1702+ desktop_file = hud_window_info_get_desktop_file(app->priv->bamf_app);
1703 if (desktop_file != NULL) {
1704 GKeyFile * kfile = g_key_file_new();
1705 g_key_file_load_from_file(kfile, desktop_file, G_KEY_FILE_NONE, NULL);
1706@@ -892,10 +807,8 @@
1707 * up data associated with it.
1708 */
1709 void
1710-hud_application_source_window_closed (HudApplicationSource * app, AbstractWindow * window)
1711+hud_application_source_window_closed (HudApplicationSource * app, guint xid)
1712 {
1713- guint32 xid = abstract_window_get_id(window);
1714-
1715 int i;
1716 for (i = 0; i < app->priv->contexts->len; i++) {
1717 HudApplicationSourceContext * context = g_ptr_array_index(app->priv->contexts, i);
1718@@ -925,56 +838,26 @@
1719 * have one BAMF listener in the application list.
1720 */
1721 void
1722-hud_application_source_add_window (HudApplicationSource * app, AbstractWindow * window)
1723+hud_application_source_add_window (HudApplicationSource * app, HudWindowInfo * window)
1724 {
1725 g_return_if_fail(HUD_IS_APPLICATION_SOURCE(app));
1726-#ifdef HAVE_BAMF
1727- g_return_if_fail(BAMF_IS_WINDOW(window));
1728-#endif
1729-#ifdef HAVE_PLATFORM_API
1730- /* Hybris has no way to check if the pointer is valid */
1731-#endif
1732-
1733- guint32 xid = 0;
1734-#ifdef HAVE_BAMF
1735- xid = bamf_window_get_xid(window);
1736-#endif
1737-#ifdef HAVE_PLATFORM_API
1738- xid = session_properties_get_window_id(window);
1739-#endif
1740-
1741-#ifdef HAVE_BAMF
1742+
1743+ guint32 xid = hud_window_info_get_window_id(window);
1744+
1745 if (app->priv->bamf_app == NULL) {
1746 g_debug("No BAMF application object");
1747 return;
1748 }
1749-#endif
1750
1751 HudApplicationSourceContext * context = find_context(app, xid, NULL);
1752
1753-#ifdef HAVE_BAMF
1754- gchar * app_id = hud_application_source_bamf_app_id(app->priv->bamf_app);
1755-#endif
1756-#ifdef HAVE_PLATFORM_API
1757- gchar * app_id = g_strdup(app->priv->app_id);
1758-#endif
1759- const gchar * icon = NULL;
1760-#ifdef HAVE_BAMF
1761- icon = bamf_view_get_icon(BAMF_VIEW(window));
1762-#endif
1763-#ifdef HAVE_BAMF
1764- /* Hybris can't find window icons, so we want to pull it from the desktop file */
1765-#endif
1766- if (icon == NULL) {
1767- icon = hud_application_source_get_app_icon(app);
1768- }
1769+ const gchar *icon = hud_application_source_get_app_icon(app);
1770
1771 if (icon != NULL) {
1772 app_iface_com_canonical_hud_application_set_icon(app->priv->skel, icon);
1773 }
1774
1775 hud_application_source_context_add_window(context, window);
1776- g_free (app_id);
1777
1778 return;
1779 }
1780
1781=== modified file 'src/application-source.h'
1782--- src/application-source.h 2013-06-13 21:44:17 +0000
1783+++ src/application-source.h 2013-10-09 19:22:59 +0000
1784@@ -20,7 +20,7 @@
1785 #define __HUD_APPLICATION_SOURCE_H__
1786
1787 #include <glib-object.h>
1788-#include "abstract-app.h"
1789+#include "window-info.h"
1790 #include "application-source-context.h"
1791
1792 G_BEGIN_DECLS
1793@@ -48,19 +48,20 @@
1794 };
1795
1796 GType hud_application_source_get_type (void);
1797-HudApplicationSource * hud_application_source_new_for_app (AbstractApplication * bapp);
1798+HudApplicationSource * hud_application_source_new_for_app (HudApplicationInfo * bapp);
1799 HudApplicationSource * hud_application_source_new_for_id (const gchar * id);
1800 gboolean hud_application_source_is_empty (HudApplicationSource * app);
1801 void hud_application_source_focus (HudApplicationSource * app,
1802- AbstractApplication * bapp,
1803- AbstractWindow * window);
1804+ HudApplicationInfo * bapp,
1805+ HudWindowInfo * window);
1806 const gchar * hud_application_source_get_path (HudApplicationSource * app);
1807 const gchar * hud_application_source_get_id (HudApplicationSource * app);
1808 const gchar * hud_application_source_get_app_icon (HudApplicationSource * app);
1809+HudApplicationInfo * hud_application_source_get_application_info (HudApplicationSource * app);
1810 void hud_application_source_add_window (HudApplicationSource * app,
1811- AbstractWindow * window);
1812+ HudWindowInfo * window);
1813 void hud_application_source_window_closed (HudApplicationSource * app,
1814- AbstractWindow * window);
1815+ guint xid);
1816 gboolean hud_application_source_has_xid (HudApplicationSource * app,
1817 guint32 xid);
1818
1819@@ -74,9 +75,6 @@
1820 void hud_application_source_set_focused_win (HudApplicationSource * app,
1821 guint32 xid);
1822
1823-/* Helper functions */
1824-gchar * hud_application_source_bamf_app_id (AbstractApplication * bapp);
1825-
1826 G_END_DECLS
1827
1828 #endif
1829
1830=== modified file 'src/dbusmenu-collector.c'
1831--- src/dbusmenu-collector.c 2013-08-21 18:10:29 +0000
1832+++ src/dbusmenu-collector.c 2013-10-09 19:22:59 +0000
1833@@ -760,7 +760,7 @@
1834 * Returns: a new #HudDbusmenuCollector
1835 **/
1836 HudDbusmenuCollector *
1837-hud_dbusmenu_collector_new_for_window (AbstractWindow *window,
1838+hud_dbusmenu_collector_new_for_window (guint xid,
1839 const gchar *application_id,
1840 const gchar *icon,
1841 HudSourceItemType type)
1842@@ -771,13 +771,7 @@
1843 collector->application_id = g_strdup (application_id);
1844 collector->icon = g_strdup (icon);
1845 collector->type = type;
1846- collector->xid = 0;
1847-#ifdef HAVE_BAMF
1848- collector->xid = bamf_window_get_xid (window);
1849-#endif
1850-#ifdef HAVE_PLATFORM_API
1851- collector->xid = session_properties_get_window_id(window);
1852-#endif
1853+ collector->xid = xid;
1854 collector->keyword_mapping = hud_keyword_mapping_new();
1855 hud_keyword_mapping_load(collector->keyword_mapping, collector->application_id, DATADIR, GNOMELOCALEDIR);
1856
1857
1858=== modified file 'src/dbusmenu-collector.h'
1859--- src/dbusmenu-collector.h 2013-06-14 00:48:33 +0000
1860+++ src/dbusmenu-collector.h 2013-10-09 19:22:59 +0000
1861@@ -20,7 +20,7 @@
1862 #define __HUD_DBUSMENU_COLLECTOR_H__
1863
1864 #include "glib-object.h"
1865-#include "abstract-app.h"
1866+#include "window-info.h"
1867 #include "source.h"
1868
1869 #define HUD_TYPE_DBUSMENU_COLLECTOR (hud_dbusmenu_collector_get_type ())
1870@@ -40,7 +40,7 @@
1871 const gchar *bus_name,
1872 const gchar *object_path,
1873 HudSourceItemType type);
1874-HudDbusmenuCollector * hud_dbusmenu_collector_new_for_window (AbstractWindow *window,
1875+HudDbusmenuCollector * hud_dbusmenu_collector_new_for_window (guint xid,
1876 const gchar *application_id,
1877 const gchar *icon,
1878 HudSourceItemType type);
1879
1880=== modified file 'src/menumodel-collector.c'
1881--- src/menumodel-collector.c 2013-08-21 19:30:18 +0000
1882+++ src/menumodel-collector.c 2013-10-09 19:22:59 +0000
1883@@ -1240,25 +1240,13 @@
1884 * Returns: a #HudMenuModelCollector, or %NULL
1885 **/
1886 void
1887-hud_menu_model_collector_add_window (HudMenuModelCollector * collector,
1888- AbstractWindow *window)
1889+hud_menu_model_collector_add_window(HudMenuModelCollector * collector,
1890+ const gchar *unique_bus_name, const gchar *app_menu_object_path,
1891+ const gchar *menubar_object_path, const gchar *application_object_path,
1892+ const gchar *window_object_path, const gchar *unity_object_path)
1893 {
1894 g_return_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector));
1895
1896-#ifdef HAVE_BAMF
1897- gchar *unique_bus_name;
1898- gchar *application_object_path;
1899- gchar *window_object_path;
1900- gchar *app_menu_object_path;
1901- gchar *menubar_object_path;
1902- gchar *unity_object_path = NULL;
1903-
1904- unique_bus_name = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
1905-
1906- if (!unique_bus_name)
1907- /* If this isn't set, we won't get very far... */
1908- return;
1909-
1910 if (!g_dbus_is_name(unique_bus_name)) {
1911 g_warning("Invalid BUS name '%s'", unique_bus_name);
1912 return;
1913@@ -1270,18 +1258,10 @@
1914
1915 if (g_strcmp0(unique_bus_name, collector->unique_bus_name) != 0) {
1916 g_warning("Bus name '%s' does not match '%s'", unique_bus_name, collector->unique_bus_name);
1917- g_free(unique_bus_name);
1918 return;
1919 }
1920- g_clear_pointer(&unique_bus_name, g_free);
1921-
1922- app_menu_object_path = bamf_window_get_utf8_prop (window, "_GTK_APP_MENU_OBJECT_PATH");
1923- menubar_object_path = bamf_window_get_utf8_prop (window, "_GTK_MENUBAR_OBJECT_PATH");
1924- application_object_path = bamf_window_get_utf8_prop (window, "_GTK_APPLICATION_OBJECT_PATH");
1925- window_object_path = bamf_window_get_utf8_prop (window, "_GTK_WINDOW_OBJECT_PATH");
1926- unity_object_path = bamf_window_get_utf8_prop (window, "_UNITY_OBJECT_PATH");
1927-
1928- if (app_menu_object_path && !g_hash_table_lookup(collector->base_models, app_menu_object_path))
1929+
1930+ if (app_menu_object_path[0] != '\0' && !g_hash_table_lookup(collector->base_models, app_menu_object_path))
1931 {
1932 GDBusMenuModel * app_menu;
1933 app_menu = g_dbus_menu_model_get (collector->session, collector->unique_bus_name, app_menu_object_path);
1934@@ -1292,7 +1272,7 @@
1935 g_hash_table_insert(collector->base_models, g_strdup(app_menu_object_path), GINT_TO_POINTER(TRUE));
1936 }
1937
1938- if (menubar_object_path && !g_hash_table_lookup(collector->base_models, menubar_object_path))
1939+ if (menubar_object_path[0] != '\0' && !g_hash_table_lookup(collector->base_models, menubar_object_path))
1940 {
1941 GDBusMenuModel * menubar;
1942 menubar = g_dbus_menu_model_get (collector->session, collector->unique_bus_name, menubar_object_path);
1943@@ -1303,7 +1283,7 @@
1944 g_hash_table_insert(collector->base_models, g_strdup(menubar_object_path), GINT_TO_POINTER(TRUE));
1945 }
1946
1947- if (unity_object_path && !g_hash_table_lookup(collector->base_models, unity_object_path))
1948+ if (unity_object_path[0] != '\0' && !g_hash_table_lookup(collector->base_models, unity_object_path))
1949 {
1950 GDBusMenuModel * menubar = g_dbus_menu_model_get (collector->session, collector->unique_bus_name, unity_object_path);
1951 hud_menu_model_collector_add_model_internal (collector, G_MENU_MODEL (menubar), unity_object_path, NULL, NULL, NULL, HUD_MENU_MODEL_DEFAULT_DEPTH, collector->type);
1952@@ -1313,21 +1293,21 @@
1953 g_hash_table_insert(collector->base_models, g_strdup(unity_object_path), GINT_TO_POINTER(TRUE));
1954 }
1955
1956- if (application_object_path)
1957+ if (application_object_path[0] != '\0')
1958 {
1959 GDBusActionGroup * ag = g_dbus_action_group_get (collector->session, collector->unique_bus_name, application_object_path);
1960 hud_menu_model_collector_add_actions(collector, G_ACTION_GROUP(ag), "app");
1961 g_object_unref(ag);
1962 }
1963
1964- if (window_object_path)
1965+ if (window_object_path[0] != '\0')
1966 {
1967 GDBusActionGroup * ag = g_dbus_action_group_get (collector->session, collector->unique_bus_name, window_object_path);
1968 hud_menu_model_collector_add_actions(collector, G_ACTION_GROUP(ag), "win");
1969 g_object_unref(ag);
1970 }
1971
1972- if (unity_object_path)
1973+ if (unity_object_path[0] != '\0')
1974 {
1975 GDBusActionGroup * ag = g_dbus_action_group_get (collector->session, collector->unique_bus_name, unity_object_path);
1976 hud_menu_model_collector_add_actions(collector, G_ACTION_GROUP(ag), "unity");
1977@@ -1337,15 +1317,6 @@
1978 /* when the action groups change, we could end up having items
1979 * enabled/disabled. how to deal with that?
1980 */
1981-
1982- g_free (app_menu_object_path);
1983- g_free (menubar_object_path);
1984- g_free (application_object_path);
1985- g_free (window_object_path);
1986- g_free (unity_object_path);
1987-#endif
1988-
1989- return;
1990 }
1991
1992 /**
1993
1994=== modified file 'src/menumodel-collector.h'
1995--- src/menumodel-collector.h 2013-06-14 00:48:33 +0000
1996+++ src/menumodel-collector.h 2013-10-09 19:22:59 +0000
1997@@ -21,7 +21,7 @@
1998
1999 #include <gio/gio.h>
2000
2001-#include "abstract-app.h"
2002+#include "window-info.h"
2003 #include "source.h"
2004
2005 #define HUD_TYPE_MENU_MODEL_COLLECTOR (hud_menu_model_collector_get_type ())
2006@@ -44,7 +44,12 @@
2007 HudSourceItemType type);
2008
2009 void hud_menu_model_collector_add_window (HudMenuModelCollector * collector,
2010- AbstractWindow * window);
2011+ const gchar *unique_bus_name,
2012+ const gchar *app_menu_object_path,
2013+ const gchar *menubar_object_path,
2014+ const gchar *application_object_path,
2015+ const gchar *window_object_path,
2016+ const gchar *unity_object_path);
2017
2018 void hud_menu_model_collector_add_endpoint (HudMenuModelCollector * collector,
2019 const gchar *prefix,
2020
2021=== modified file 'src/service.c'
2022--- src/service.c 2013-09-30 14:37:38 +0000
2023+++ src/service.c 2013-10-09 19:22:59 +0000
2024@@ -697,14 +697,15 @@
2025 g_object_unref (source);
2026 }
2027
2028- {
2029- HudWebappSource *source;
2030-
2031- source = hud_webapp_source_new ();
2032- hud_source_list_add (source_list, HUD_SOURCE (source));
2033-
2034- g_object_unref (G_OBJECT (source));
2035- }
2036+// //FIXME Re-enable webapp source
2037+// {
2038+// HudWebappSource *source;
2039+//
2040+// source = hud_webapp_source_new ();
2041+// hud_source_list_add (source_list, HUD_SOURCE (source));
2042+//
2043+// g_object_unref (G_OBJECT (source));
2044+// }
2045
2046 if (!g_dbus_connection_register_object (connection, DBUS_PATH, hud_iface_com_canonical_hud_interface_info (), &vtable, source_list, NULL, &error))
2047 {
2048
2049=== added file 'src/window-info.c'
2050--- src/window-info.c 1970-01-01 00:00:00 +0000
2051+++ src/window-info.c 2013-10-09 19:22:59 +0000
2052@@ -0,0 +1,139 @@
2053+/*
2054+ * Copyright (C) 2013 Canonical, Ltd.
2055+ *
2056+ * This program is free software: you can redistribute it and/or modify it
2057+ * under the terms of the GNU General Public License version 3, as published
2058+ * by the Free Software Foundation.
2059+ *
2060+ * This program is distributed in the hope that it will be useful, but
2061+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2062+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2063+ * PURPOSE. See the GNU General Public License for more details.
2064+ *
2065+ * You should have received a copy of the GNU General Public License along
2066+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2067+ *
2068+ * Author: Pete Woods <pete.woods@canonical.com>
2069+ */
2070+
2071+#include "window-info.h"
2072+#include <gobject/gobject.h>
2073+
2074+struct _HudWindowInfo
2075+{
2076+ GObject parent_instance;
2077+ guint32 window_id;
2078+ gchar *app_id;
2079+ HudWindowInfoStage stage;
2080+ DBusWindowStack *window_stack;
2081+ gchar *desktop_file;
2082+};
2083+
2084+typedef GObjectClass HudWindowInfoClass;
2085+
2086+static void hud_window_info_finalize (GObject *object);
2087+static void hud_window_info_dispose (GObject *object);
2088+
2089+G_DEFINE_TYPE(HudWindowInfo, hud_window_info, G_TYPE_OBJECT);
2090+
2091+static void
2092+hud_window_info_class_init(GObjectClass *klass) {
2093+ klass->dispose = hud_window_info_dispose;
2094+ klass->finalize = hud_window_info_finalize;
2095+}
2096+
2097+static void
2098+hud_window_info_init (HudWindowInfo *self)
2099+{
2100+}
2101+
2102+HudWindowInfo *
2103+hud_window_info_new(DBusWindowStack *window_stack, guint window_id,
2104+ const gchar *app_id, HudWindowInfoStage stage)
2105+{
2106+ HudWindowInfo *self =
2107+ HUD_WINDOW_INFO(g_object_new(HUD_TYPE_WINDOW_INFO, NULL));
2108+ self->window_id = window_id;
2109+ self->app_id = g_strdup(app_id);
2110+ self->stage = stage;
2111+ self->window_stack = g_object_ref(window_stack);
2112+ const gchar *xdg_data_dirs = g_getenv("XDG_DATA_DIRS");
2113+ if (xdg_data_dirs != NULL && xdg_data_dirs[0] != '\0') {
2114+ gchar** dirs = g_strsplit(xdg_data_dirs, ":", 0);
2115+ gchar **i = dirs;
2116+ while (*i != NULL) {
2117+ gchar *desktop_file = g_strdup_printf("%s/%s.desktop", *i, app_id);
2118+ if (g_file_test(desktop_file, G_FILE_TEST_EXISTS)) {
2119+ self->desktop_file = desktop_file;
2120+ break;
2121+ }
2122+ g_free(desktop_file);
2123+ ++i;
2124+ }
2125+ g_strfreev(dirs);
2126+ }
2127+ if (self->desktop_file == NULL) {
2128+ self->desktop_file = g_strdup_printf(
2129+ "/usr/share/applications/%s.desktop", app_id);
2130+ }
2131+ return self;
2132+}
2133+
2134+static void
2135+hud_window_info_dispose (GObject *object)
2136+{
2137+ HudWindowInfo *self = HUD_WINDOW_INFO(object);
2138+ g_object_unref(self->window_stack);
2139+}
2140+
2141+static void
2142+hud_window_info_finalize (GObject *object)
2143+{
2144+ HudWindowInfo *self = HUD_WINDOW_INFO(object);
2145+ g_free(self->app_id);
2146+ g_free(self->desktop_file);
2147+}
2148+
2149+guint32
2150+hud_window_info_get_window_id(HudWindowInfo *self) {
2151+ return self->window_id;
2152+}
2153+
2154+const gchar *
2155+hud_window_info_get_app_id(HudWindowInfo *self) {
2156+ return self->app_id;
2157+}
2158+
2159+const gchar *
2160+hud_window_info_get_desktop_file(HudWindowInfo *self) {
2161+ return self->desktop_file;
2162+}
2163+
2164+gchar *
2165+hud_window_info_get_utf8_prop(HudWindowInfo *self,
2166+ const gchar *property_name) {
2167+ const gchar *property_names[] = { property_name, NULL };
2168+ gchar** values = hud_window_info_get_utf8_properties(self,
2169+ ((const gchar * const *) &property_names));
2170+ if(values == NULL) {
2171+ return NULL;
2172+ }
2173+ gchar *result = g_strdup(values[0]);
2174+ g_strfreev(values);
2175+ return result;
2176+}
2177+
2178+gchar **
2179+hud_window_info_get_utf8_properties(HudWindowInfo *self,
2180+ const gchar * const *property_names) {
2181+ gchar **result = NULL;
2182+ GError *error = NULL;
2183+ if (!dbus_window_stack_call_get_window_properties_sync(self->window_stack,
2184+ self->window_id, self->app_id, property_names, &result, NULL,
2185+ &error)) {
2186+ g_warning("%s", error->message);
2187+ g_error_free(error);
2188+ return NULL;
2189+ }
2190+ return result;
2191+}
2192
2193=== added file 'src/window-info.h'
2194--- src/window-info.h 1970-01-01 00:00:00 +0000
2195+++ src/window-info.h 2013-10-09 19:22:59 +0000
2196@@ -0,0 +1,69 @@
2197+/*
2198+ * Copyright (C) 2013 Canonical, Ltd.
2199+ *
2200+ * This program is free software: you can redistribute it and/or modify it
2201+ * under the terms of the GNU General Public License version 3, as published
2202+ * by the Free Software Foundation.
2203+ *
2204+ * This program is distributed in the hope that it will be useful, but
2205+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2206+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2207+ * PURPOSE. See the GNU General Public License for more details.
2208+ *
2209+ * You should have received a copy of the GNU General Public License along
2210+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2211+ *
2212+ * Author: Pete Woods <pete.woods@canonical.com>
2213+ */
2214+
2215+
2216+#ifndef __HUD_WINDOW_INFO_H__
2217+#define __HUD_WINDOW_INFO_H__
2218+
2219+#include <glib-object.h>
2220+#include <window-stack-iface.h>
2221+
2222+/*
2223+ * Type macros.
2224+ */
2225+#define HUD_TYPE_WINDOW_INFO (hud_window_info_get_type ())
2226+#define HUD_WINDOW_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HUD_TYPE_WINDOW_INFO, HudWindowInfo))
2227+#define HUD_IS_WINDOW_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HUD_TYPE_WINDOW_INFO))
2228+#define HUD_WINDOW_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HUD_TYPE_WINDOW_INFO, HudWindowInfoClass))
2229+#define HUD_IS_WINDOW_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HUD_TYPE_WINDOW_INFO))
2230+#define HUD_WINDOW_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HUD_TYPE_WINDOW_INFO, HudWindowInfoClass))
2231+
2232+typedef struct _HudWindowInfo HudWindowInfo;
2233+
2234+#define WINDOW_ID_ALL_WINDOWS (0)
2235+
2236+typedef enum {
2237+ HUD_WINDOW_INFO_STAGE_MAIN,
2238+ HUD_WINDOW_INFO_STAGE_SIDE,
2239+ HUD_WINDOW_INFO_STAGE_WINDOWED,
2240+} HudWindowInfoStage;
2241+
2242+typedef HudWindowInfo HudApplicationInfo;
2243+
2244+GType hud_window_info_get_type (void);
2245+
2246+/*
2247+ * Method definitions.
2248+ */
2249+
2250+HudWindowInfo * hud_window_info_new(DBusWindowStack *window_stack,
2251+ guint window_id, const gchar *app_id, guint stack);
2252+
2253+guint32 hud_window_info_get_window_id(HudWindowInfo *self);
2254+
2255+const gchar * hud_window_info_get_app_id(HudWindowInfo *self);
2256+
2257+const gchar * hud_window_info_get_desktop_file(HudWindowInfo *self);
2258+
2259+gchar * hud_window_info_get_utf8_prop(HudWindowInfo *self,
2260+ const gchar *property_name);
2261+
2262+gchar ** hud_window_info_get_utf8_properties(HudWindowInfo *self,
2263+ const gchar * const *property_names);
2264+
2265+#endif /* __HUD_WINDOW_INFO_H__ */
2266
2267=== modified file 'tests/CMakeLists.txt'
2268--- tests/CMakeLists.txt 2013-08-21 17:28:41 +0000
2269+++ tests/CMakeLists.txt 2013-10-09 19:22:59 +0000
2270@@ -7,6 +7,12 @@
2271 endif()
2272
2273 #######################
2274+# BAMF Bridge
2275+#######################
2276+
2277+add_definitions(-DBAMF_BRIDGE="${CMAKE_BINARY_DIR}/window-stack-bridge/window-stack-bridge")
2278+
2279+#######################
2280 # Dbus JSON Loader
2281 #######################
2282
2283@@ -208,12 +214,12 @@
2284 hudtest(test-string-list test-string-list.c test-string-list.xml)
2285 hudtest(test-pronounce-dict test-pronounce-dict.c test-pronounce-dict.xml)
2286 # FIXME: Disabled temporarily on platform-api systems due to some platform-api problems
2287-if(NOT(${ENABLE_PLATFORM_API}))
2288+if(${ENABLE_BAMF})
2289 hudtest(test-source test-source.c test-source.xml)
2290 endif()
2291 hudtest(test-app-indicator-source test-app-indicator-source.c test-app-indicator-source.xml)
2292 hudtest(test-indicator-source test-indicator-source.c test-indicator-source.xml)
2293-if(NOT(${ENABLE_PLATFORM_API}))
2294+if(${ENABLE_BAMF})
2295 hudtest(test-application-list test-application-list.c test-application-list.xml)
2296 endif()
2297 hudtest(test-application-source test-application-source.c test-application-source.xml)
2298
2299=== modified file 'tests/test-application-list.c'
2300--- tests/test-application-list.c 2013-07-01 10:55:05 +0000
2301+++ tests/test-application-list.c 2013-10-09 19:22:59 +0000
2302@@ -16,6 +16,7 @@
2303 */
2304
2305 #define G_LOG_DOMAIN "test-hudappindicatorsource"
2306+#define _POSIX_SOURCE 1
2307
2308 #include "settings.h"
2309 #include "source.h"
2310@@ -26,6 +27,7 @@
2311 #include <glib-object.h>
2312 #include <gio/gio.h>
2313 #include <libdbustest/dbus-test.h>
2314+#include <signal.h>
2315
2316 /* hardcode some parameters for reasons of determinism.
2317 */
2318@@ -48,6 +50,21 @@
2319 static const gchar* REGISTRAR_OBJECT_PATH = "/com/canonical/AppMenu/Registrar";
2320 static const gchar* REGISTRAR_INTERFACE_NAME = "com.canonical.AppMenu.Registrar";
2321
2322+static void name_appeared(GDBusConnection *connection, const gchar *name,
2323+ const gchar *name_owner, gpointer user_data) {
2324+ g_debug("name appeared: %s, %s", name, name_owner);
2325+ g_main_loop_quit((GMainLoop *) user_data);
2326+}
2327+
2328+gboolean
2329+timeout_error_func (gpointer user_data)
2330+{
2331+ GMainLoop * loop = (GMainLoop *)user_data;
2332+ g_main_loop_quit(loop);
2333+ g_error("Failed to get service");
2334+ return FALSE;
2335+}
2336+
2337 static void
2338 test_window_source_add_view_properties (GDBusConnection* connection,
2339 const gchar *object_path)
2340@@ -108,7 +125,8 @@
2341 " '_GTK_MENUBAR_OBJECT_PATH': '',\n"
2342 " '_GTK_APPLICATION_OBJECT_PATH': '/app/dbus/menu/path',\n"
2343 " '_GTK_WINDOW_OBJECT_PATH': '',\n"
2344- " '_UNITY_OBJECT_PATH': ''\n"
2345+ " '_UNITY_OBJECT_PATH': '',\n"
2346+ " 'WM_NAME': 'name'\n"
2347 " }\n"
2348 "ret = dict[args[0]]");
2349 dbus_mock_add_object (connection, BAMF_BUS_NAME, MATCHER_OBJECT_PATH,
2350@@ -118,6 +136,8 @@
2351 "/org/ayatana/bamf/window00000001");
2352 test_window_source_add_view_properties (connection,
2353 "/org/ayatana/bamf/window00000001");
2354+ dbus_mock_add_method (connection, BAMF_BUS_NAME, "/org/ayatana/bamf/window00000001",
2355+ VIEW_INTERFACE_NAME, "Parents", "", "as", "ret = ['/org/ayatana/bamf/application00000001']");
2356 }
2357
2358 /* Define the mock application */
2359@@ -180,6 +200,26 @@
2360
2361 hud_test_utils_process_mainloop (100);
2362
2363+ GPid pid;
2364+ {
2365+ GError *error = NULL;
2366+
2367+ const gchar *argv[] = { BAMF_BRIDGE, NULL };
2368+ g_spawn_async(NULL, (gchar **) argv,
2369+ NULL, G_SPAWN_DEFAULT,
2370+ NULL,
2371+ NULL,
2372+ &pid, &error);
2373+
2374+ GMainLoop *temploop = g_main_loop_new (NULL, FALSE);
2375+ g_timeout_add (1000, timeout_error_func, temploop);
2376+ g_bus_watch_name(G_BUS_TYPE_SESSION, "com.canonical.Unity.WindowStack",
2377+ G_BUS_NAME_WATCHER_FLAGS_NONE, name_appeared, NULL, temploop,
2378+ NULL);
2379+ g_main_loop_run (temploop);
2380+ g_main_loop_unref (temploop);
2381+ }
2382+
2383 HudApplicationList* source = hud_application_list_new();
2384 g_assert(source != NULL);
2385 g_assert(HUD_IS_APPLICATION_LIST(source));
2386@@ -223,19 +263,19 @@
2387 HudApplicationSource * app =
2388 HUD_APPLICATION_SOURCE(g_list_nth_data(apps, 0));
2389 g_assert(HUD_IS_APPLICATION_SOURCE(app));
2390- g_assert_cmpstr(hud_application_source_get_id (app), ==, "name");
2391+ g_assert_cmpstr(hud_application_source_get_id (app), ==, "1");
2392 g_assert_cmpstr(hud_application_source_get_path (app), ==,
2393- "/com/canonical/hud/applications/name");
2394+ "/com/canonical/hud/applications/1");
2395 g_list_free(apps);
2396 }
2397
2398 {
2399 HudApplicationSource * app = hud_application_list_get_source (source,
2400- "name");
2401+ "1");
2402 g_assert(HUD_IS_APPLICATION_SOURCE(app));
2403- g_assert_cmpstr(hud_application_source_get_id (app), ==, "name");
2404+ g_assert_cmpstr(hud_application_source_get_id (app), ==, "1");
2405 g_assert_cmpstr(hud_application_source_get_path (app), ==,
2406- "/com/canonical/hud/applications/name");
2407+ "/com/canonical/hud/applications/1");
2408 }
2409
2410 g_debug("Unusing Source");
2411@@ -251,6 +291,8 @@
2412 g_debug("Waiting for things to settle");
2413 hud_test_utils_process_mainloop (100);
2414
2415+ kill(pid, SIGTERM);
2416+
2417 g_debug("Taking down the connection");
2418 g_object_unref (connection);
2419 g_debug("Taking down the dbus service");
2420
2421=== added directory 'window-stack-bridge'
2422=== added file 'window-stack-bridge/AbstractWindowStack.cpp'
2423--- window-stack-bridge/AbstractWindowStack.cpp 1970-01-01 00:00:00 +0000
2424+++ window-stack-bridge/AbstractWindowStack.cpp 2013-10-09 19:22:59 +0000
2425@@ -0,0 +1,75 @@
2426+/*
2427+ * Copyright (C) 2013 Canonical, Ltd.
2428+ *
2429+ * This program is free software: you can redistribute it and/or modify it
2430+ * under the terms of the GNU General Public License version 3, as published
2431+ * by the Free Software Foundation.
2432+ *
2433+ * This program is distributed in the hope that it will be useful, but
2434+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2435+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2436+ * PURPOSE. See the GNU General Public License for more details.
2437+ *
2438+ * You should have received a copy of the GNU General Public License along
2439+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2440+ *
2441+ * Author: Pete Woods <pete.woods@canonical.com>
2442+ */
2443+
2444+#include <AbstractWindowStack.h>
2445+#include <WindowStackAdaptor.h>
2446+#include <Localisation.h>
2447+
2448+#include <stdexcept>
2449+#include <QDBusMetaType>
2450+#include <QDebug>
2451+
2452+const QString AbstractWindowStack::DBUS_NAME("com.canonical.Unity.WindowStack");
2453+const QString AbstractWindowStack::DBUS_PATH(
2454+ "/com/canonical/Unity/WindowStack");
2455+
2456+QDBusArgument & operator<<(QDBusArgument &a, const WindowInfo &wi) {
2457+ a.beginStructure();
2458+ a << wi.window_id << wi.app_id << wi.focused << wi.stage;
2459+ a.endStructure();
2460+ return a;
2461+}
2462+
2463+const QDBusArgument & operator>>(const QDBusArgument &a, WindowInfo &wi) {
2464+ a.beginStructure();
2465+ uint stage;
2466+ a >> wi.window_id >> wi.app_id >> wi.focused >> stage;
2467+ a.endStructure();
2468+ wi.stage = static_cast<WindowInfo::Stage>(stage);
2469+ return a;
2470+}
2471+
2472+AbstractWindowStack::AbstractWindowStack(const QDBusConnection &connection,
2473+ QObject *parent) :
2474+ QObject(parent), m_adaptor(new WindowStackAdaptor(this)), m_connection(
2475+ connection) {
2476+ registerMetaTypes();
2477+}
2478+
2479+void AbstractWindowStack::registerOnBus() {
2480+ if (!m_connection.registerObject(DBUS_PATH, this)) {
2481+ throw std::logic_error(
2482+ _("Unable to register window stack object on DBus"));
2483+ }
2484+ if (!m_connection.registerService(DBUS_NAME)) {
2485+ throw std::logic_error(
2486+ _("Unable to register window stack service on DBus"));
2487+ }
2488+}
2489+
2490+AbstractWindowStack::~AbstractWindowStack() {
2491+ m_connection.unregisterObject(DBUS_PATH);
2492+}
2493+
2494+void AbstractWindowStack::registerMetaTypes() {
2495+ qRegisterMetaType<WindowInfo>();
2496+ qRegisterMetaType<QList<WindowInfo>>();
2497+ qDBusRegisterMetaType<WindowInfo>();
2498+ qDBusRegisterMetaType<QList<WindowInfo>>();
2499+}
2500+
2501
2502=== added file 'window-stack-bridge/AbstractWindowStack.h'
2503--- window-stack-bridge/AbstractWindowStack.h 1970-01-01 00:00:00 +0000
2504+++ window-stack-bridge/AbstractWindowStack.h 2013-10-09 19:22:59 +0000
2505@@ -0,0 +1,102 @@
2506+/*
2507+ * Copyright (C) 2013 Canonical, Ltd.
2508+ *
2509+ * This program is free software: you can redistribute it and/or modify it
2510+ * under the terms of the GNU General Public License version 3, as published
2511+ * by the Free Software Foundation.
2512+ *
2513+ * This program is distributed in the hope that it will be useful, but
2514+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2515+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2516+ * PURPOSE. See the GNU General Public License for more details.
2517+ *
2518+ * You should have received a copy of the GNU General Public License along
2519+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2520+ *
2521+ * Author: Pete Woods <pete.woods@canonical.com>
2522+ */
2523+
2524+#ifndef ABSTRACTWINDOWSTACK_H_
2525+#define ABSTRACTWINDOWSTACK_H_
2526+
2527+#include <QList>
2528+#include <QString>
2529+#include <QDBusArgument>
2530+#include <QDBusConnection>
2531+#include <QDBusContext>
2532+#include <QScopedPointer>
2533+
2534+class WindowStackAdaptor;
2535+
2536+class WindowInfo {
2537+public:
2538+ enum Stage {
2539+ MAIN, SIDE, WINDOWED,
2540+ };
2541+
2542+ unsigned int window_id;
2543+ QString app_id;
2544+ bool focused;
2545+ unsigned int stage;
2546+
2547+ WindowInfo() :
2548+ window_id(0), focused(false), stage(MAIN) {
2549+ }
2550+
2551+ WindowInfo(unsigned int window_id, const QString &app_id, bool focused,
2552+ Stage stage = MAIN) :
2553+ window_id(window_id), app_id(app_id), focused(focused), stage(stage) {
2554+ }
2555+};
2556+
2557+Q_DECL_EXPORT
2558+QDBusArgument &operator<<(QDBusArgument &a, const WindowInfo &aidf);
2559+
2560+Q_DECL_EXPORT
2561+const QDBusArgument &operator>>(const QDBusArgument &a, WindowInfo &aidf);
2562+
2563+class Q_DECL_EXPORT AbstractWindowStack: public QObject, protected QDBusContext {
2564+Q_OBJECT
2565+
2566+public:
2567+ explicit AbstractWindowStack(const QDBusConnection &connection,
2568+ QObject *parent = 0);
2569+
2570+ virtual ~AbstractWindowStack();
2571+
2572+public:
2573+ Q_DECL_EXPORT
2574+ static const QString DBUS_NAME;
2575+
2576+ Q_DECL_EXPORT
2577+ static const QString DBUS_PATH;
2578+
2579+ Q_DECL_EXPORT
2580+ static void registerMetaTypes();
2581+
2582+public Q_SLOTS:
2583+ virtual QString GetAppIdFromPid(uint pid) = 0;
2584+
2585+ virtual QList<WindowInfo> GetWindowStack() = 0;
2586+
2587+ virtual QStringList GetWindowProperties(uint windowId, const QString &appId,
2588+ const QStringList &names) = 0;
2589+
2590+Q_SIGNALS:
2591+ void FocusedWindowChanged(uint windowId, const QString &appId, uint stage);
2592+
2593+ void WindowCreated(uint windowId, const QString &appId);
2594+
2595+ void WindowDestroyed(uint windowId, const QString &appId);
2596+
2597+protected:
2598+ void registerOnBus();
2599+
2600+ QScopedPointer<WindowStackAdaptor> m_adaptor;
2601+
2602+ QDBusConnection m_connection;
2603+};
2604+
2605+Q_DECLARE_METATYPE(WindowInfo);
2606+
2607+#endif /* ABSTRACTWINDOWSTACK_H_ */
2608
2609=== added file 'window-stack-bridge/BamfWindowStack.cpp'
2610--- window-stack-bridge/BamfWindowStack.cpp 1970-01-01 00:00:00 +0000
2611+++ window-stack-bridge/BamfWindowStack.cpp 2013-10-09 19:22:59 +0000
2612@@ -0,0 +1,174 @@
2613+/*
2614+ * Copyright (C) 2013 Canonical, Ltd.
2615+ *
2616+ * This program is free software: you can redistribute it and/or modify it
2617+ * under the terms of the GNU General Public License version 3, as published
2618+ * by the Free Software Foundation.
2619+ *
2620+ * This program is distributed in the hope that it will be useful, but
2621+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2622+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2623+ * PURPOSE. See the GNU General Public License for more details.
2624+ *
2625+ * You should have received a copy of the GNU General Public License along
2626+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2627+ *
2628+ * Author: Pete Woods <pete.woods@canonical.com>
2629+ */
2630+
2631+#include <BamfWindowStack.h>
2632+#include <Localisation.h>
2633+
2634+#include <QFile>
2635+#include <QFileInfo>
2636+
2637+static const QString BAMF_DBUS_NAME("org.ayatana.bamf");
2638+
2639+BamfWindow::BamfWindow(const QString &path, const QDBusConnection &connection) :
2640+ m_window(BAMF_DBUS_NAME, path, connection), m_view(BAMF_DBUS_NAME, path,
2641+ connection), m_windowId(m_window.GetXid()) {
2642+
2643+ QDBusConnectionInterface* interface = connection.interface();
2644+ if (!interface->isServiceRegistered(BAMF_DBUS_NAME)) {
2645+ QDBusReply<void> reply(interface->startService(BAMF_DBUS_NAME));
2646+ }
2647+
2648+ QStringList parents(m_view.Parents());
2649+
2650+ if (parents.empty()) {
2651+ qWarning() << _("Window: ") << windowId() << m_view.name()
2652+ << _("has no parents");
2653+ } else {
2654+ OrgAyatanaBamfApplicationInterface application(BAMF_DBUS_NAME,
2655+ parents.first(), m_window.connection());
2656+ QFile desktopFile(application.DesktopFile());
2657+ if (desktopFile.exists()) {
2658+ m_applicationId = QFileInfo(desktopFile).baseName();
2659+ }
2660+ }
2661+
2662+ if (m_applicationId.isEmpty()) {
2663+ m_applicationId = QString::number(m_windowId);
2664+ }
2665+}
2666+
2667+BamfWindow::~BamfWindow() {
2668+}
2669+
2670+unsigned int BamfWindow::windowId() {
2671+ return m_windowId;
2672+}
2673+
2674+const QString & BamfWindow::applicationId() {
2675+
2676+ return m_applicationId;
2677+}
2678+
2679+const QString BamfWindow::xProp(const QString &property) {
2680+ return m_window.Xprop(property);
2681+}
2682+
2683+BamfWindowStack::WindowPtr BamfWindowStack::addWindow(const QString& path) {
2684+ WindowPtr window(new BamfWindow(path, m_connection));
2685+ m_windows[path] = window;
2686+ m_windowsById[window->windowId()] = window;
2687+ return window;
2688+}
2689+
2690+BamfWindowStack::WindowPtr BamfWindowStack::removeWindow(const QString& path) {
2691+ WindowPtr window(m_windows.take(path));
2692+ m_windowsById.remove(window->windowId());
2693+ return window;
2694+}
2695+
2696+BamfWindowStack::BamfWindowStack(const QDBusConnection &connection,
2697+ QObject *parent) :
2698+ AbstractWindowStack(connection, parent), m_matcher(BAMF_DBUS_NAME,
2699+ "/org/ayatana/bamf/matcher", connection) {
2700+
2701+ registerOnBus();
2702+
2703+ connect(&m_matcher,
2704+ SIGNAL(ActiveWindowChanged(const QString&, const QString&)), this,
2705+ SLOT(ActiveWindowChanged(const QString&, const QString&)));
2706+
2707+ connect(&m_matcher,
2708+ SIGNAL(ViewClosed(const QString&, const QString&)), this,
2709+ SLOT(ViewClosed(const QString&, const QString&)));
2710+
2711+ connect(&m_matcher,
2712+ SIGNAL(ViewOpened(const QString&, const QString&)), this,
2713+ SLOT(ViewOpened(const QString&, const QString&)));
2714+
2715+ QStringList windowPaths(m_matcher.WindowPaths());
2716+ for (const QString &path : windowPaths) {
2717+ addWindow(path);
2718+ }
2719+}
2720+
2721+BamfWindowStack::~BamfWindowStack() {
2722+}
2723+
2724+QString BamfWindowStack::GetAppIdFromPid(uint pid) {
2725+ // FIXME Not implemented
2726+ sendErrorReply(QDBusError::NotSupported,
2727+ "GetAppIdFromPid method not implemented");
2728+ return QString();
2729+}
2730+
2731+QList<WindowInfo> BamfWindowStack::GetWindowStack() {
2732+ QList<WindowInfo> results;
2733+
2734+ QStringList stack(m_matcher.WindowStackForMonitor(-1));
2735+ for (const QString &path : stack) {
2736+ WindowPtr window(m_windows[path]);
2737+ results
2738+ << WindowInfo(window->windowId(), window->applicationId(),
2739+ false);
2740+ }
2741+
2742+ WindowPtr window(m_windows[m_matcher.ActiveWindow()]);
2743+ if (!window.isNull()) {
2744+ uint windowId(window->windowId());
2745+
2746+ for (WindowInfo &windowInfo : results) {
2747+ if (windowInfo.window_id == windowId) {
2748+ windowInfo.focused = true;
2749+ }
2750+ }
2751+ }
2752+
2753+ return results;
2754+}
2755+
2756+QStringList BamfWindowStack::GetWindowProperties(uint windowId,
2757+ const QString &appId, const QStringList &names) {
2758+ QStringList result;
2759+ for (const QString &name : names) {
2760+ result << m_windowsById[windowId]->xProp(name);
2761+ }
2762+ return result;
2763+}
2764+
2765+void BamfWindowStack::ActiveWindowChanged(const QString &oldWindowPath,
2766+ const QString &newWindowPath) {
2767+ if (!newWindowPath.isEmpty()) {
2768+ WindowPtr window(m_windows[newWindowPath]);
2769+ FocusedWindowChanged(window->windowId(), window->applicationId(),
2770+ WindowInfo::MAIN);
2771+ }
2772+}
2773+
2774+void BamfWindowStack::ViewClosed(const QString &path, const QString &type) {
2775+ if (type == "window") {
2776+ WindowPtr window(removeWindow(path));
2777+ WindowDestroyed(window->windowId(), window->applicationId());
2778+ }
2779+}
2780+
2781+void BamfWindowStack::ViewOpened(const QString &path, const QString &type) {
2782+ if (type == "window") {
2783+ WindowPtr window(addWindow(path));
2784+ WindowCreated(window->windowId(), window->applicationId());
2785+ }
2786+}
2787
2788=== added file 'window-stack-bridge/BamfWindowStack.h'
2789--- window-stack-bridge/BamfWindowStack.h 1970-01-01 00:00:00 +0000
2790+++ window-stack-bridge/BamfWindowStack.h 2013-10-09 19:22:59 +0000
2791@@ -0,0 +1,90 @@
2792+/*
2793+ * Copyright (C) 2013 Canonical, Ltd.
2794+ *
2795+ * This program is free software: you can redistribute it and/or modify it
2796+ * under the terms of the GNU General Public License version 3, as published
2797+ * by the Free Software Foundation.
2798+ *
2799+ * This program is distributed in the hope that it will be useful, but
2800+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2801+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2802+ * PURPOSE. See the GNU General Public License for more details.
2803+ *
2804+ * You should have received a copy of the GNU General Public License along
2805+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2806+ *
2807+ * Author: Pete Woods <pete.woods@canonical.com>
2808+ */
2809+
2810+#ifndef BAMFWINDOWSTACK_H_
2811+#define BAMFWINDOWSTACK_H_
2812+
2813+#include <AbstractWindowStack.h>
2814+#include <BamfInterface.h>
2815+#include <BamfViewInterface.h>
2816+
2817+#include <QMap>
2818+#include <QSharedPointer>
2819+
2820+class Q_DECL_EXPORT BamfWindow {
2821+public:
2822+ explicit BamfWindow(const QString &path, const QDBusConnection &connection);
2823+
2824+ ~BamfWindow();
2825+
2826+ unsigned int windowId();
2827+
2828+ const QString & applicationId();
2829+
2830+ const QString xProp(const QString &property);
2831+
2832+protected:
2833+ OrgAyatanaBamfWindowInterface m_window;
2834+
2835+ OrgAyatanaBamfViewInterface m_view;
2836+
2837+ unsigned int m_windowId;
2838+
2839+ QString m_applicationId;
2840+};
2841+
2842+class Q_DECL_EXPORT BamfWindowStack: public AbstractWindowStack {
2843+Q_OBJECT
2844+
2845+public:
2846+ typedef QSharedPointer<BamfWindow> WindowPtr;
2847+
2848+ explicit BamfWindowStack(const QDBusConnection &connection,
2849+ QObject *parent = 0);
2850+
2851+ virtual ~BamfWindowStack();
2852+
2853+public Q_SLOTS:
2854+ virtual QString GetAppIdFromPid(uint pid);
2855+
2856+ virtual QList<WindowInfo> GetWindowStack();
2857+
2858+ virtual QStringList GetWindowProperties(uint windowId, const QString &appId,
2859+ const QStringList &names);
2860+
2861+protected Q_SLOTS:
2862+ void ActiveWindowChanged(const QString &oldWindow,
2863+ const QString &newWindow);
2864+
2865+ void ViewClosed(const QString &path, const QString &type);
2866+
2867+ void ViewOpened(const QString &path, const QString &type);
2868+
2869+ WindowPtr addWindow(const QString& path);
2870+
2871+ WindowPtr removeWindow(const QString& path);
2872+
2873+protected:
2874+ OrgAyatanaBamfMatcherInterface m_matcher;
2875+
2876+ QMap<QString, WindowPtr> m_windows;
2877+
2878+ QMap<unsigned int, WindowPtr> m_windowsById;
2879+};
2880+
2881+#endif /* BAMFWINDOWSTACK_H_ */
2882
2883=== added file 'window-stack-bridge/CMakeLists.txt'
2884--- window-stack-bridge/CMakeLists.txt 1970-01-01 00:00:00 +0000
2885+++ window-stack-bridge/CMakeLists.txt 2013-10-09 19:22:59 +0000
2886@@ -0,0 +1,89 @@
2887+
2888+if(${ENABLE_BAMF})
2889+ add_definitions( -DENABLE_BAMF=1 )
2890+elseif(${ENABLE_PLATFORM_API})
2891+ add_definitions( -DENABLE_PLATFORM_API=1 )
2892+ set(PLATFORM_API_LIBRARIES "-lubuntu_application_api")
2893+endif()
2894+
2895+if(${ENABLE_BAMF} OR ${ENABLE_PLATFORM_API})
2896+
2897+set(
2898+ WINDOW_STACK_BRIDGE_SOURCES
2899+ AbstractWindowStack.cpp
2900+)
2901+
2902+if(${ENABLE_BAMF})
2903+ list(APPEND WINDOW_STACK_BRIDGE_SOURCES BamfWindowStack.cpp)
2904+
2905+ qt5_add_dbus_interface(
2906+ WINDOW_STACK_BRIDGE_SOURCES
2907+ ${BAMF_XML}
2908+ BamfInterface
2909+ )
2910+
2911+ qt5_add_dbus_interface(
2912+ WINDOW_STACK_BRIDGE_SOURCES
2913+ ${BAMF_VIEW_XML}
2914+ BamfViewInterface
2915+ )
2916+endif()
2917+
2918+if(${ENABLE_PLATFORM_API})
2919+ list(APPEND WINDOW_STACK_BRIDGE_SOURCES PlatformApiWindowStack.cpp)
2920+endif()
2921+
2922+qt5_add_dbus_adaptor(
2923+ WINDOW_STACK_BRIDGE_SOURCES
2924+ ${WINDOW_STACK_XML}
2925+ AbstractWindowStack.h
2926+ AbstractWindowStack
2927+ WindowStackAdaptor
2928+)
2929+
2930+set_source_files_properties(
2931+ "${DATA_DIR}/org.freedesktop.Notifications.xml"
2932+ PROPERTIES
2933+ INCLUDE "DBusTypes.h"
2934+)
2935+
2936+add_library(
2937+ window-stack-bridge
2938+ STATIC
2939+ ${WINDOW_STACK_BRIDGE_SOURCES}
2940+)
2941+
2942+qt5_use_modules(
2943+ window-stack-bridge
2944+ Core
2945+ DBus
2946+)
2947+
2948+add_executable(
2949+ window-stack-bridge-bin
2950+ main.cpp
2951+)
2952+
2953+set_target_properties(
2954+ window-stack-bridge-bin
2955+ PROPERTIES
2956+ OUTPUT_NAME window-stack-bridge
2957+)
2958+
2959+qt5_use_modules(
2960+ window-stack-bridge-bin
2961+ Core
2962+)
2963+
2964+target_link_libraries(
2965+ window-stack-bridge-bin
2966+ window-stack-bridge
2967+ ${PLATFORM_API_LIBRARIES}
2968+)
2969+
2970+install(
2971+ TARGETS window-stack-bridge-bin
2972+ RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud"
2973+)
2974+
2975+endif()
2976\ No newline at end of file
2977
2978=== added file 'window-stack-bridge/Localisation.h'
2979--- window-stack-bridge/Localisation.h 1970-01-01 00:00:00 +0000
2980+++ window-stack-bridge/Localisation.h 2013-10-09 19:22:59 +0000
2981@@ -0,0 +1,28 @@
2982+/*
2983+ * Copyright (C) 2013 Canonical, Ltd.
2984+ *
2985+ * This program is free software: you can redistribute it and/or modify it
2986+ * under the terms of the GNU General Public License version 3, as published
2987+ * by the Free Software Foundation.
2988+ *
2989+ * This program is distributed in the hope that it will be useful, but
2990+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2991+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2992+ * PURPOSE. See the GNU General Public License for more details.
2993+ *
2994+ * You should have received a copy of the GNU General Public License along
2995+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2996+ *
2997+ * Author: Pete Woods <pete.woods@canonical.com>
2998+ */
2999+
3000+#ifndef DAEMON_LOCALISATION_H_
3001+#define DAEMON_LOCALISATION_H_
3002+
3003+#include <libintl.h>
3004+
3005+inline char* _(const char *__msgid) {
3006+ return gettext(__msgid);
3007+}
3008+
3009+#endif // DAEMON_LOCALISATION_H_
3010
3011=== added file 'window-stack-bridge/PlatformApiWindowStack.cpp'
3012--- window-stack-bridge/PlatformApiWindowStack.cpp 1970-01-01 00:00:00 +0000
3013+++ window-stack-bridge/PlatformApiWindowStack.cpp 2013-10-09 19:22:59 +0000
3014@@ -0,0 +1,125 @@
3015+/*
3016+ * Copyright (C) 2013 Canonical, Ltd.
3017+ *
3018+ * This program is free software: you can redistribute it and/or modify it
3019+ * under the terms of the GNU General Public License version 3, as published
3020+ * by the Free Software Foundation.
3021+ *
3022+ * This program is distributed in the hope that it will be useful, but
3023+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3024+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3025+ * PURPOSE. See the GNU General Public License for more details.
3026+ *
3027+ * You should have received a copy of the GNU General Public License along
3028+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3029+ *
3030+ * Author: Pete Woods <pete.woods@canonical.com>
3031+ */
3032+
3033+#include <PlatformApiWindowStack.h>
3034+#include <Localisation.h>
3035+
3036+#include <QDebug>
3037+#include <stdexcept>
3038+#include <ubuntu/application/ui/stage.h>
3039+
3040+PlatformApiWindowStack::PlatformApiWindowStack(
3041+ const QDBusConnection &connection, QObject *parent) :
3042+ AbstractWindowStack(connection, parent) {
3043+
3044+ if (qgetenv("QT_QPA_PLATFORM") != "ubuntu") {
3045+ throw std::logic_error(
3046+ _("Incorrect QPA environment for Ubuntu platform API"));
3047+ }
3048+
3049+ registerOnBus();
3050+
3051+ m_observer_definition.on_session_requested = on_session_requested_cb;
3052+ m_observer_definition.on_session_born = on_session_born_cb;
3053+ m_observer_definition.on_session_unfocused = on_session_unfocused_cb;
3054+ m_observer_definition.on_session_focused = on_session_focused_cb;
3055+ m_observer_definition.on_session_died = on_session_died_cb;
3056+ m_observer_definition.on_keyboard_geometry_changed = 0;
3057+ m_observer_definition.on_session_requested_fullscreen = 0;
3058+ m_observer_definition.context = reinterpret_cast<void *>(this);
3059+
3060+ ubuntu_ui_session_install_session_lifecycle_observer(
3061+ &m_observer_definition);
3062+}
3063+
3064+PlatformApiWindowStack::~PlatformApiWindowStack() {
3065+}
3066+
3067+QString PlatformApiWindowStack::GetAppIdFromPid(uint pid) {
3068+ // FIXME Not implemented
3069+ qDebug() << "GetAppIdFromPid";
3070+ return QString();
3071+}
3072+
3073+QList<WindowInfo> PlatformApiWindowStack::GetWindowStack() {
3074+ // FIXME Not implemented
3075+ qDebug() << "GetWindowStack";
3076+ return QList<WindowInfo>();
3077+}
3078+
3079+QStringList PlatformApiWindowStack::GetWindowProperties(uint windowId,
3080+ const QString &appId, const QStringList &names) {
3081+ // FIXME Not implemented
3082+ qDebug() << "GetWindowProperties:" << windowId << appId << names;
3083+ return QStringList();
3084+}
3085+
3086+void PlatformApiWindowStack::onSessionRequested(
3087+ ubuntu_ui_well_known_application app) {
3088+ // FIXME Not implemented
3089+ qDebug() << "onSessionRequested";
3090+}
3091+
3092+void PlatformApiWindowStack::onSessionBorn(ubuntu_ui_session_properties props) {
3093+ // FIXME Not implemented
3094+ qDebug() << "onSessionBorn";
3095+ //session_properties_get_window_id
3096+}
3097+
3098+void PlatformApiWindowStack::onSessionUnfocused(
3099+ ubuntu_ui_session_properties props) {
3100+ // FIXME Not implemented
3101+ qDebug() << "onSessionUnfocused";
3102+}
3103+
3104+void PlatformApiWindowStack::onSessionFocused(
3105+ ubuntu_ui_session_properties props) {
3106+ // FIXME Not implemented
3107+ qDebug() << "onSessionFocused";
3108+}
3109+
3110+void PlatformApiWindowStack::onSessionDied(ubuntu_ui_session_properties props) {
3111+ // FIXME Not implemented
3112+ qDebug() << "onSessionDied";
3113+}
3114+
3115+void PlatformApiWindowStack::on_session_requested_cb(
3116+ ubuntu_ui_well_known_application app, void* context) {
3117+ reinterpret_cast<PlatformApiWindowStack *>(context)->onSessionRequested(
3118+ app);
3119+}
3120+
3121+void PlatformApiWindowStack::on_session_born_cb(
3122+ ubuntu_ui_session_properties props, void* context) {
3123+ reinterpret_cast<PlatformApiWindowStack *>(context)->onSessionBorn(props);
3124+}
3125+void PlatformApiWindowStack::on_session_unfocused_cb(
3126+ ubuntu_ui_session_properties props, void* context) {
3127+ reinterpret_cast<PlatformApiWindowStack *>(context)->onSessionUnfocused(
3128+ props);
3129+}
3130+void PlatformApiWindowStack::on_session_focused_cb(
3131+ ubuntu_ui_session_properties props, void* context) {
3132+ reinterpret_cast<PlatformApiWindowStack *>(context)->onSessionFocused(
3133+ props);
3134+}
3135+
3136+void PlatformApiWindowStack::on_session_died_cb(
3137+ ubuntu_ui_session_properties props, void* context) {
3138+ reinterpret_cast<PlatformApiWindowStack *>(context)->onSessionDied(props);
3139+}
3140
3141=== added file 'window-stack-bridge/PlatformApiWindowStack.h'
3142--- window-stack-bridge/PlatformApiWindowStack.h 1970-01-01 00:00:00 +0000
3143+++ window-stack-bridge/PlatformApiWindowStack.h 2013-10-09 19:22:59 +0000
3144@@ -0,0 +1,72 @@
3145+/*
3146+ * Copyright (C) 2013 Canonical, Ltd.
3147+ *
3148+ * This program is free software: you can redistribute it and/or modify it
3149+ * under the terms of the GNU General Public License version 3, as published
3150+ * by the Free Software Foundation.
3151+ *
3152+ * This program is distributed in the hope that it will be useful, but
3153+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3154+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3155+ * PURPOSE. See the GNU General Public License for more details.
3156+ *
3157+ * You should have received a copy of the GNU General Public License along
3158+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3159+ *
3160+ * Author: Pete Woods <pete.woods@canonical.com>
3161+ */
3162+
3163+#ifndef PLATFORMAPIWINDOWSTACK_H_
3164+#define PLATFORMAPIWINDOWSTACK_H_
3165+
3166+#include <AbstractWindowStack.h>
3167+
3168+#include <ubuntu/ui/ubuntu_ui_session_service.h>
3169+
3170+class Q_DECL_EXPORT PlatformApiWindowStack: public AbstractWindowStack {
3171+Q_OBJECT
3172+
3173+public:
3174+ explicit PlatformApiWindowStack(const QDBusConnection &connection,
3175+ QObject *parent = 0);
3176+
3177+ virtual ~PlatformApiWindowStack();
3178+
3179+public Q_SLOTS:
3180+ virtual QString GetAppIdFromPid(uint pid);
3181+
3182+ virtual QList<WindowInfo> GetWindowStack();
3183+
3184+ virtual QStringList GetWindowProperties(uint windowId, const QString &appId,
3185+ const QStringList &names);
3186+
3187+protected:
3188+ static void on_session_requested_cb(ubuntu_ui_well_known_application app,
3189+ void* context);
3190+
3191+ void onSessionRequested(ubuntu_ui_well_known_application app);
3192+
3193+ static void on_session_born_cb(ubuntu_ui_session_properties props,
3194+ void* context);
3195+
3196+ void onSessionBorn(ubuntu_ui_session_properties props);
3197+
3198+ static void on_session_unfocused_cb(ubuntu_ui_session_properties props,
3199+ void* context);
3200+
3201+ void onSessionUnfocused(ubuntu_ui_session_properties props);
3202+
3203+ static void on_session_focused_cb(ubuntu_ui_session_properties props,
3204+ void* context);
3205+
3206+ void onSessionFocused(ubuntu_ui_session_properties props);
3207+
3208+ static void on_session_died_cb(ubuntu_ui_session_properties props,
3209+ void* context);
3210+
3211+ void onSessionDied(ubuntu_ui_session_properties props);
3212+
3213+ ubuntu_ui_session_lifecycle_observer m_observer_definition;
3214+};
3215+
3216+#endif /* PLATFORMAPIWINDOWSTACK_H_ */
3217
3218=== added file 'window-stack-bridge/WindowStack.h'
3219--- window-stack-bridge/WindowStack.h 1970-01-01 00:00:00 +0000
3220+++ window-stack-bridge/WindowStack.h 2013-10-09 19:22:59 +0000
3221@@ -0,0 +1,30 @@
3222+/*
3223+ * Copyright (C) 2013 Canonical, Ltd.
3224+ *
3225+ * This program is free software: you can redistribute it and/or modify it
3226+ * under the terms of the GNU General Public License version 3, as published
3227+ * by the Free Software Foundation.
3228+ *
3229+ * This program is distributed in the hope that it will be useful, but
3230+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3231+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3232+ * PURPOSE. See the GNU General Public License for more details.
3233+ *
3234+ * You should have received a copy of the GNU General Public License along
3235+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3236+ *
3237+ * Author: Pete Woods <pete.woods@canonical.com>
3238+ */
3239+
3240+#ifndef WINDOWSTACK_H_
3241+#define WINDOWSTACK_H_
3242+
3243+#ifdef ENABLE_BAMF
3244+#include <BamfWindowStack.h>
3245+typedef BamfWindowStack WindowStack;
3246+#elif ENABLE_PLATFORM_API
3247+#include <PlatformApiWindowStack.h>
3248+typedef PlatformApiWindowStack WindowStack;
3249+#endif
3250+
3251+#endif /* WINDOWSTACK_H_ */
3252
3253=== added file 'window-stack-bridge/main.cpp'
3254--- window-stack-bridge/main.cpp 1970-01-01 00:00:00 +0000
3255+++ window-stack-bridge/main.cpp 2013-10-09 19:22:59 +0000
3256@@ -0,0 +1,51 @@
3257+/*
3258+ * Copyright (C) 2013 Canonical, Ltd.
3259+ *
3260+ * This program is free software: you can redistribute it and/or modify it
3261+ * under the terms of the GNU General Public License version 3, as published
3262+ * by the Free Software Foundation.
3263+ *
3264+ * This program is distributed in the hope that it will be useful, but
3265+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3266+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3267+ * PURPOSE. See the GNU General Public License for more details.
3268+ *
3269+ * You should have received a copy of the GNU General Public License along
3270+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3271+ *
3272+ * Author: Pete Woods <pete.woods@canonical.com>
3273+ */
3274+
3275+#include <Localisation.h>
3276+#include <WindowStack.h>
3277+
3278+#include <QDBusConnection>
3279+#include <QDebug>
3280+#include <QCoreApplication>
3281+#include <csignal>
3282+
3283+using namespace std;
3284+
3285+static void exitQt(int sig) {
3286+ Q_UNUSED(sig);
3287+ QCoreApplication::exit(0);
3288+}
3289+
3290+int main(int argc, char *argv[]) {
3291+ QCoreApplication application(argc, argv);
3292+
3293+ setlocale(LC_ALL, "");
3294+ bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR);
3295+ textdomain(GETTEXT_PACKAGE);
3296+
3297+ signal(SIGINT, &exitQt);
3298+ signal(SIGTERM, &exitQt);
3299+
3300+ try {
3301+ WindowStack windowStack(QDBusConnection::sessionBus());
3302+ return application.exec();
3303+ } catch (std::exception &e) {
3304+ qWarning() << _("Window Stack Bridge:") << e.what();
3305+ return application.exec();
3306+ }
3307+}

Subscribers

People subscribed via source and target branches

to all changes: