Merge lp:~3v1n0/indicator-sound/bamf-player-activation into lp:indicator-sound/13.10

Proposed by Marco Trevisan (Treviño) on 2013-04-05
Status: Merged
Approved by: Lars Karlitski on 2013-04-05
Approved revision: 351
Merged at revision: 347
Proposed branch: lp:~3v1n0/indicator-sound/bamf-player-activation
Merge into: lp:indicator-sound/13.10
Prerequisite: lp:~3v1n0/indicator-sound/gtk-application-player-activate
Diff against target: 243 lines (+100/-19)
6 files modified
configure.ac (+2/-0)
debian/control (+1/-0)
src/Makefile.am (+3/-1)
src/metadata-menu-item.vala (+1/-1)
src/player-activator.vala (+91/-15)
src/player-controller.vala (+2/-2)
To merge this branch: bzr merge lp:~3v1n0/indicator-sound/bamf-player-activation
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve on 2013-04-05
Lars Karlitski (community) 2013-04-05 Approve on 2013-04-05
Review via email: mp+157360@code.launchpad.net

Commit Message

PlayerActivator: Use BAMF to find the windows to activate with timestamp

Improved the"old" GtkApplicationPlayer, using BAMF as a fallback method to
activate an application's windows. Basically we try to get the windows of the
selected application and when found we focus them using the activation
timestamp.

Description of the Change

Upstream port of lp:~3v1n0/indicator-sound/bamf-player-activation/+merge/156920

Added a new fallback method to focus the windows of the player that we need to raise using the event timestamp, if we're not using a GtkApplication based player, we try to get the player windows from Bamf.
At that point we can focus them with the activation event timestamp.

This will work well for banshee, Spotify, Youtube and any other local or web-player.

I've added a new dependency to libbamf3. If this is a problem for packaing stuff, I can provide a version that uses bamf directly via DBus, but I'd really prefer to use the library.

To post a comment you must log in.
Lars Karlitski (larsu) wrote :

Approved, same as the one merged in 13.04.

review: Approve
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 'configure.ac'
2--- configure.ac 2012-11-13 20:24:30 +0000
3+++ configure.ac 2013-04-05 13:43:39 +0000
4@@ -52,7 +52,9 @@
5 PKG_CHECK_MODULES(SOUNDSERVICE, dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION
6 indicator3-0.4
7 gee-1.0
8+ gdk-x11-3.0
9 gio-unix-2.0
10+ libbamf3
11 libxml-2.0)
12
13 AC_SUBST(APPLET_CFLAGS)
14
15=== modified file 'debian/control'
16--- debian/control 2012-11-14 21:43:14 +0000
17+++ debian/control 2013-04-05 13:43:39 +0000
18@@ -10,6 +10,7 @@
19 gnome-common,
20 autotools-dev,
21 valac-0.18,
22+ libbamf3-dev,
23 libglib2.0-dev (>= 2.22.3),
24 libgtk-3-dev,
25 libdbusmenu-glib-dev (>= 0.5.90),
26
27=== modified file 'src/Makefile.am'
28--- src/Makefile.am 2013-04-05 13:43:39 +0000
29+++ src/Makefile.am 2013-04-05 13:43:39 +0000
30@@ -68,7 +68,7 @@
31 playlists-menu-item.vala \
32 freedesktop-interfaces.vala \
33 fetch-file.vala \
34- gtk-application-player.vala
35+ player-activator.vala
36
37 music_bridge_VALAFLAGS = \
38 --ccode \
39@@ -83,7 +83,9 @@
40 --pkg gio-2.0 \
41 --pkg gio-unix-2.0 \
42 --pkg gdk-3.0 \
43+ --pkg gdk-x11-3.0 \
44 --pkg gdk-pixbuf-2.0 \
45+ --pkg libbamf3 \
46 --pkg libxml-2.0
47
48 $(MAINTAINER_VALAFLAGS)
49
50=== modified file 'src/metadata-menu-item.vala'
51--- src/metadata-menu-item.vala 2013-04-05 13:43:39 +0000
52+++ src/metadata-menu-item.vala 2013-04-05 13:43:39 +0000
53@@ -177,7 +177,7 @@
54 this.owner.instantiate(timestamp);
55 }
56 else if (this.owner.current_state == PlayerController.state.CONNECTED) {
57- this.owner.gtk_app_player.activate(timestamp);
58+ this.owner.player_activator.activate(timestamp);
59 this.owner.mpris_bridge.expose(timestamp);
60 }
61 }
62
63=== renamed file 'src/gtk-application-player.vala' => 'src/player-activator.vala'
64--- src/gtk-application-player.vala 2013-04-05 13:43:39 +0000
65+++ src/player-activator.vala 2013-04-05 13:43:39 +0000
66@@ -4,16 +4,16 @@
67 Authors:
68 Marco Trevisan <marco.trevisan@canonical.com>
69
70-This program is free software: you can redistribute it and/or modify it
71-under the terms of the GNU General Public License version 3, as published
72+This program is free software: you can redistribute it and/or modify it
73+under the terms of the GNU General Public License version 3, as published
74 by the Free Software Foundation.
75
76-This program is distributed in the hope that it will be useful, but
77-WITHOUT ANY WARRANTY; without even the implied warranties of
78-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
79+This program is distributed in the hope that it will be useful, but
80+WITHOUT ANY WARRANTY; without even the implied warranties of
81+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
82 PURPOSE. See the GNU General Public License for more details.
83
84-You should have received a copy of the GNU General Public License along
85+You should have received a copy of the GNU General Public License along
86 with this program. If not, see <http://www.gnu.org/licenses/>.
87 */
88
89@@ -22,24 +22,44 @@
90 public abstract void Activate(GLib.HashTable<string, Variant?> platform_data) throws IOError;
91 }
92
93-public class GtkApplicationPlayer : GLib.Object
94+public class PlayerActivator : GLib.Object
95 {
96 public PlayerController owner {get; construct;}
97
98 private bool gtk_application_searched = false;
99 private DBusGtkApplication gtk_application;
100-
101- public GtkApplicationPlayer(PlayerController ctrl)
102+ private Bamf.Application bamf_application;
103+
104+ private const uint MAX_BAMF_APPLICATION_WAIT_MS = 1000;
105+ private int64 last_check_time;
106+
107+ public PlayerActivator(PlayerController ctrl)
108 {
109 GLib.Object(owner: ctrl);
110 }
111
112 public void activate(uint timestamp)
113 {
114+ if (!activate_gtk_appplication(timestamp)) {
115+ if (!activate_bamf_appplication(timestamp)) {
116+ // Let's wait BAMF to update its windows list
117+ this.last_check_time = get_monotonic_time();
118+
119+ Idle.add(() => {
120+ bool activated = activate_bamf_appplication(timestamp);
121+ int64 waited = (get_monotonic_time() - this.last_check_time) / 1000;
122+ return !activated && waited < MAX_BAMF_APPLICATION_WAIT_MS;
123+ });
124+ }
125+ }
126+ }
127+
128+ private bool activate_gtk_appplication(uint timestamp)
129+ {
130 this.setup_gtk_application();
131
132 if (this.gtk_application == null) {
133- return;
134+ return false;
135 }
136
137 var context = Gdk.Display.get_default().get_app_launch_context();
138@@ -49,9 +69,13 @@
139 data["desktop-startup-id"] = context.get_startup_notify_id(this.owner.app_info, new GLib.List<GLib.File>());
140
141 try {
142- this.gtk_application.Activate(data);
143- }
144- catch (IOError e) {}
145+ this.gtk_application.Activate(data);
146+ }
147+ catch (IOError e) {
148+ return false;
149+ }
150+
151+ return true;
152 }
153
154 private void setup_gtk_application()
155@@ -79,7 +103,7 @@
156
157 private void find_iface_path(DBusConnection connection, string name, string path, string target_iface, out string found_path)
158 {
159- found_path = null;
160+ found_path = null;
161 DBusNodeInfo node = null;
162
163 try {
164@@ -120,4 +144,56 @@
165 }
166 }
167 }
168-}
169\ No newline at end of file
170+
171+ private void setup_bamf_application()
172+ {
173+ this.bamf_application = null;
174+ var desktop_app = this.owner.app_info as DesktopAppInfo;
175+
176+ if (desktop_app == null)
177+ return;
178+
179+ foreach (var app in Bamf.Matcher.get_default().get_applications()) {
180+ if (app.get_desktop_file() == desktop_app.get_filename()) {
181+ this.bamf_application = app;
182+ break;
183+ }
184+ }
185+ }
186+
187+ private bool activate_bamf_appplication(uint timestamp)
188+ {
189+ this.setup_bamf_application();
190+
191+ if (this.bamf_application == null)
192+ return false;
193+
194+ bool focused = false;
195+ var dpy = Gdk.Display.get_default();
196+
197+ foreach (var win in this.bamf_application.get_windows()) {
198+ X.Window xid = 0;
199+
200+ if (win is Bamf.Window) {
201+ if (win.get_window_type() != Bamf.WindowType.NORMAL)
202+ continue;
203+
204+ xid = win.get_xid();
205+ }
206+ else if (win is Bamf.Tab) {
207+ xid = (X.Window) (win as Bamf.Tab).get_xid();
208+ }
209+
210+ if (xid > 0) {
211+ var xwin = Gdk.X11Window.foreign_new_for_display(dpy, xid);
212+
213+ if (xwin != null) {
214+ xwin.focus(timestamp);
215+ focused = true;
216+ }
217+ }
218+ }
219+
220+ return focused;
221+ }
222+}
223
224=== modified file 'src/player-controller.vala'
225--- src/player-controller.vala 2013-04-05 13:43:39 +0000
226+++ src/player-controller.vala 2013-04-05 13:43:39 +0000
227@@ -45,7 +45,7 @@
228 public string dbus_name { get; set;}
229 public ArrayList<PlayerItem> custom_items;
230 public Mpris2Controller mpris_bridge;
231- public GtkApplicationPlayer gtk_app_player;
232+ public PlayerActivator player_activator;
233 public AppInfo? app_info { get; set;}
234 public int menu_offset { get; set;}
235 public string icon_name { get; set; }
236@@ -150,7 +150,7 @@
237 debug ( " establish mpris connection - use playlists value = %s ",
238 this.use_playlists.to_string() );
239 this.mpris_bridge = new Mpris2Controller (this);
240- this.gtk_app_player = new GtkApplicationPlayer (this);
241+ this.player_activator = new PlayerActivator (this);
242 this.determine_state ();
243 }
244

Subscribers

People subscribed via source and target branches