diff options
author | Marco Trevisan (TreviƱo) <mail@3v1n0.net> | 2013-04-05 14:43:22 +0000 |
---|---|---|
committer | Tarmac <Unknown> | 2013-04-05 14:43:22 +0000 |
commit | d774ac38dd84f52394bfcbb557b0e3475f999f34 (patch) | |
tree | ecfa17ebc292904664ce58e5ecb5905744518bbb | |
parent | a83c4b7d257344bff272c169e36736a2205fda31 (diff) | |
parent | 0762482ba33dc83ce4675481895bf0cd6568e53d (diff) | |
download | ayatana-indicator-sound-d774ac38dd84f52394bfcbb557b0e3475f999f34.tar.gz ayatana-indicator-sound-d774ac38dd84f52394bfcbb557b0e3475f999f34.tar.bz2 ayatana-indicator-sound-d774ac38dd84f52394bfcbb557b0e3475f999f34.zip |
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. Fixes: https://bugs.launchpad.net/bugs/627195.
Approved by PS Jenkins bot, Lars Uebernickel.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | debian/control | 1 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/metadata-menu-item.vala | 2 | ||||
-rw-r--r-- | src/player-activator.vala (renamed from src/gtk-application-player.vala) | 102 | ||||
-rw-r--r-- | src/player-controller.vala | 4 |
6 files changed, 98 insertions, 17 deletions
diff --git a/configure.ac b/configure.ac index 7d8c008..3a72c5c 100644 --- a/configure.ac +++ b/configure.ac @@ -52,7 +52,9 @@ PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK_REQUIRED_VERSION PKG_CHECK_MODULES(SOUNDSERVICE, dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION indicator3-0.4 gee-1.0 + gdk-x11-3.0 gio-unix-2.0 + libbamf3 libxml-2.0) AC_SUBST(APPLET_CFLAGS) diff --git a/debian/control b/debian/control index 320f8b7..abd1f75 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 9.0), gnome-common, autotools-dev, valac-0.18, + libbamf3-dev, libglib2.0-dev (>= 2.22.3), libgtk-3-dev, libdbusmenu-glib-dev (>= 0.5.90), diff --git a/src/Makefile.am b/src/Makefile.am index 381da56..55df0f6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -68,7 +68,7 @@ music_bridge_VALASOURCES = \ playlists-menu-item.vala \ freedesktop-interfaces.vala \ fetch-file.vala \ - gtk-application-player.vala + player-activator.vala music_bridge_VALAFLAGS = \ --ccode \ @@ -83,7 +83,9 @@ music_bridge_VALAFLAGS = \ --pkg gio-2.0 \ --pkg gio-unix-2.0 \ --pkg gdk-3.0 \ + --pkg gdk-x11-3.0 \ --pkg gdk-pixbuf-2.0 \ + --pkg libbamf3 \ --pkg libxml-2.0 $(MAINTAINER_VALAFLAGS) diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala index a81c143..f4a7e68 100644 --- a/src/metadata-menu-item.vala +++ b/src/metadata-menu-item.vala @@ -177,7 +177,7 @@ public class MetadataMenuitem : PlayerItem this.owner.instantiate(timestamp); } else if (this.owner.current_state == PlayerController.state.CONNECTED) { - this.owner.gtk_app_player.activate(timestamp); + this.owner.player_activator.activate(timestamp); this.owner.mpris_bridge.expose(timestamp); } } diff --git a/src/gtk-application-player.vala b/src/player-activator.vala index 8422ca5..7437a35 100644 --- a/src/gtk-application-player.vala +++ b/src/player-activator.vala @@ -4,16 +4,16 @@ Copyright 2013 Canonical Ltd. Authors: Marco Trevisan <marco.trevisan@canonical.com> -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -22,24 +22,44 @@ public interface DBusGtkApplication : Object { public abstract void Activate(GLib.HashTable<string, Variant?> platform_data) throws IOError; } -public class GtkApplicationPlayer : GLib.Object +public class PlayerActivator : GLib.Object { public PlayerController owner {get; construct;} private bool gtk_application_searched = false; private DBusGtkApplication gtk_application; + private Bamf.Application bamf_application; - public GtkApplicationPlayer(PlayerController ctrl) + private const uint MAX_BAMF_APPLICATION_WAIT_MS = 1000; + private int64 last_check_time; + + public PlayerActivator(PlayerController ctrl) { GLib.Object(owner: ctrl); } public void activate(uint timestamp) { + if (!activate_gtk_appplication(timestamp)) { + if (!activate_bamf_appplication(timestamp)) { + // Let's wait BAMF to update its windows list + this.last_check_time = get_monotonic_time(); + + Idle.add(() => { + bool activated = activate_bamf_appplication(timestamp); + int64 waited = (get_monotonic_time() - this.last_check_time) / 1000; + return !activated && waited < MAX_BAMF_APPLICATION_WAIT_MS; + }); + } + } + } + + private bool activate_gtk_appplication(uint timestamp) + { this.setup_gtk_application(); if (this.gtk_application == null) { - return; + return false; } var context = Gdk.Display.get_default().get_app_launch_context(); @@ -49,9 +69,13 @@ public class GtkApplicationPlayer : GLib.Object data["desktop-startup-id"] = context.get_startup_notify_id(this.owner.app_info, new GLib.List<GLib.File>()); try { - this.gtk_application.Activate(data); + this.gtk_application.Activate(data); } - catch (IOError e) {} + catch (IOError e) { + return false; + } + + return true; } private void setup_gtk_application() @@ -79,7 +103,7 @@ public class GtkApplicationPlayer : GLib.Object private void find_iface_path(DBusConnection connection, string name, string path, string target_iface, out string found_path) { - found_path = null; + found_path = null; DBusNodeInfo node = null; try { @@ -120,4 +144,56 @@ public class GtkApplicationPlayer : GLib.Object } } } -}
\ No newline at end of file + + private void setup_bamf_application() + { + this.bamf_application = null; + var desktop_app = this.owner.app_info as DesktopAppInfo; + + if (desktop_app == null) + return; + + foreach (var app in Bamf.Matcher.get_default().get_applications()) { + if (app.get_desktop_file() == desktop_app.get_filename()) { + this.bamf_application = app; + break; + } + } + } + + private bool activate_bamf_appplication(uint timestamp) + { + this.setup_bamf_application(); + + if (this.bamf_application == null) + return false; + + bool focused = false; + var dpy = Gdk.Display.get_default(); + + foreach (var win in this.bamf_application.get_windows()) { + X.Window xid = 0; + + if (win is Bamf.Window) { + if (win.get_window_type() != Bamf.WindowType.NORMAL) + continue; + + xid = win.get_xid(); + } + else if (win is Bamf.Tab) { + xid = (X.Window) (win as Bamf.Tab).get_xid(); + } + + if (xid > 0) { + var xwin = Gdk.X11Window.foreign_new_for_display(dpy, xid); + + if (xwin != null) { + xwin.focus(timestamp); + focused = true; + } + } + } + + return focused; + } +} diff --git a/src/player-controller.vala b/src/player-controller.vala index dbe7c3c..8c3339e 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -45,7 +45,7 @@ public class PlayerController : GLib.Object public string dbus_name { get; set;} public ArrayList<PlayerItem> custom_items; public Mpris2Controller mpris_bridge; - public GtkApplicationPlayer gtk_app_player; + public PlayerActivator player_activator; public AppInfo? app_info { get; set;} public int menu_offset { get; set;} public string icon_name { get; set; } @@ -150,7 +150,7 @@ public class PlayerController : GLib.Object debug ( " establish mpris connection - use playlists value = %s ", this.use_playlists.to_string() ); this.mpris_bridge = new Mpris2Controller (this); - this.gtk_app_player = new GtkApplicationPlayer (this); + this.player_activator = new PlayerActivator (this); this.determine_state (); } |