Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions lib/AppSystem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,64 @@ public class Gala.AppSystem : GLib.Object {
private GLib.HashTable<unowned string, Gala.App> id_to_app;
private GLib.HashTable<string, string> startup_wm_class_to_id;
private Gala.AppCache app_cache;
private string[] all_desktop_files = {};
private GLib.FileMonitor[]? directory_monitors;

construct {
id_to_app = new GLib.HashTable<unowned string, Gala.App> (str_hash, str_equal);
startup_wm_class_to_id = new GLib.HashTable<string, string> (str_hash, str_equal);
running_apps = new GLib.HashTable<Gala.App, unowned Gala.App> (null, null);
app_cache = new AppCache ();

update_desktop_files ();
}

private void update_desktop_files () {
var data_dirs = Environment.get_system_data_dirs ();
data_dirs += Environment.get_user_data_dir ();

var create_monitors = directory_monitors == null;
if (create_monitors) {
directory_monitors = {};
}

foreach (unowned string data_dir in data_dirs) {
var app_dir = Path.build_filename (data_dir, "applications");
if (FileUtils.test (app_dir, FileTest.EXISTS)) {
try {
foreach (var name in enumerate_children (app_dir)) {
if (!name.contains ("~") && name.has_suffix (".desktop")) {
all_desktop_files += name;
}
}

if (!create_monitors) {
continue;
}

var monitor = File.new_for_path (app_dir).monitor (GLib.FileMonitorFlags.NONE, null);
monitor.changed.connect ((file, other_file, event_type) => {
if (event_type == GLib.FileMonitorEvent.CHANGES_DONE_HINT) {
update_desktop_files ();
}
});
directory_monitors += monitor;
} catch (Error e) {
debug ("Error inside %s: %s", app_dir, e.message);
}
}
}
}

private string[] enumerate_children (string dir) throws Error {
string[] result = {};
FileInfo? file_info;
var enumerator = File.new_for_path (dir).enumerate_children (FileAttribute.STANDARD_NAME, 0);
while ((file_info = enumerator.next_file ()) != null) {
result += file_info.get_name ();
}

return result;
}

public unowned Gala.App? lookup_app (string id) {
Expand Down Expand Up @@ -105,6 +157,20 @@ public class Gala.AppSystem : GLib.Object {
return lookup_heuristic_basename (desktop_file);
}

public unowned Gala.App? guess_app_by_id (string _id) {
var id = _id.ascii_down ();
unowned Gala.App? result = null;

foreach (var name in all_desktop_files) {
// Try to find desktop file based on the application name
if (name.contains (id) && (result = lookup_app (name)) != null) {
return result;
}
}

return null;
}

public void notify_app_state_changed (Gala.App app) {
if (app.state == Gala.AppState.RUNNING) {
running_apps.insert (app, app);
Expand Down
36 changes: 35 additions & 1 deletion src/WindowTracker.vala
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,34 @@ public class Gala.WindowTracker : GLib.Object {
return null;
}

private unowned Gala.App? get_app_by_guessing (Meta.Window window) {
unowned var app_system = Gala.AppSystem.get_default ();
unowned Gala.App? result = null;

unowned string? id = window.get_gtk_application_id ();
// if id contains '.' it's probably a valid app id but it doesn't provide the desktop file
if (id != null && !id.contains (".") && (result = app_system.guess_app_by_id (id)) != null) {
return result;
}

id = window.get_sandboxed_app_id ();
if (id != null && !id.contains (".") && (result = app_system.guess_app_by_id (id)) != null) {
return result;
}

id = window.get_wm_class ();
if (id != null && !id.contains (".") && (result = app_system.guess_app_by_id (id)) != null) {
return result;
}

id = window.get_wm_class_instance ();
if (id != null && !id.contains (".") && (result = app_system.guess_app_by_id (id)) != null) {
return result;
}

return null;
}

public Gala.App get_app_for_window (Meta.Window window) {
unowned Meta.Window? transient_for = window.get_transient_for ();
if (transient_for != null) {
Expand Down Expand Up @@ -279,9 +307,15 @@ public class Gala.WindowTracker : GLib.Object {
return result;
}

/* Try to carefully guess .desktop file name based on application ids and wm class
*/
result = get_app_by_guessing (window);
if (result != null) {
return result;
}

/* Our last resort - we create a fake app from the window */
return new Gala.App.for_window (window);

}

private void tracked_window_changed (Meta.Window window) {
Expand Down