Compare commits
15 Commits
citadel
...
wip/deskto
Author | SHA1 | Date | |
---|---|---|---|
|
45797a977b | ||
|
884b94233e | ||
|
74d3e3139f | ||
|
77b5385cc3 | ||
|
d749d646be | ||
|
fa8224d7b5 | ||
|
f687197ccc | ||
|
28a6aefb6c | ||
|
96c2a90e11 | ||
|
63cf46e49b | ||
|
200a9ef1af | ||
|
6050ca6e0c | ||
|
8bd7db9227 | ||
|
982feb85c1 | ||
|
f165cc23c0 |
@ -70,7 +70,6 @@ POLKIT_MIN_VERSION=0.100
|
|||||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
||||||
GCR_MIN_VERSION=3.7.5
|
GCR_MIN_VERSION=3.7.5
|
||||||
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
|
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
|
||||||
GNOME_MENUS_REQUIRED_VERSION=3.5.3
|
|
||||||
NETWORKMANAGER_MIN_VERSION=0.9.8
|
NETWORKMANAGER_MIN_VERSION=0.9.8
|
||||||
PULSE_MIN_VERS=2.0
|
PULSE_MIN_VERS=2.0
|
||||||
|
|
||||||
@ -80,7 +79,6 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
|
|||||||
gtk+-3.0 >= $GTK_MIN_VERSION
|
gtk+-3.0 >= $GTK_MIN_VERSION
|
||||||
atk-bridge-2.0
|
atk-bridge-2.0
|
||||||
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
||||||
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
|
|
||||||
$recorder_modules
|
$recorder_modules
|
||||||
gdk-x11-3.0 libsoup-2.4
|
gdk-x11-3.0 libsoup-2.4
|
||||||
xtst
|
xtst
|
||||||
|
@ -55,13 +55,13 @@ function _loadCategory(dir, view) {
|
|||||||
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
||||||
if (nextType == GMenu.TreeItemType.ENTRY) {
|
if (nextType == GMenu.TreeItemType.ENTRY) {
|
||||||
let entry = iter.get_entry();
|
let entry = iter.get_entry();
|
||||||
let app = appSystem.lookup_app_by_tree_entry(entry);
|
let appInfo = entry.get_app_info();
|
||||||
if (!entry.get_app_info().get_nodisplay())
|
let app = appSystem.lookup_app(entry.get_desktop_file_id());
|
||||||
|
if (appInfo.should_show())
|
||||||
view.addApp(app);
|
view.addApp(app);
|
||||||
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||||
let itemDir = iter.get_directory();
|
let itemDir = iter.get_directory();
|
||||||
if (!itemDir.get_is_nodisplay())
|
_loadCategory(itemDir, view);
|
||||||
_loadCategory(itemDir, view);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -691,8 +691,7 @@ const AppDisplay = new Lang.Class({
|
|||||||
Name: 'AppDisplay',
|
Name: 'AppDisplay',
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
|
||||||
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
|
|
||||||
Main.queueDeferredWork(this._allAppsWorkId);
|
Main.queueDeferredWork(this._allAppsWorkId);
|
||||||
}));
|
}));
|
||||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||||
@ -808,7 +807,8 @@ const AppDisplay = new Lang.Class({
|
|||||||
|
|
||||||
view.removeAll();
|
view.removeAll();
|
||||||
|
|
||||||
let tree = this._appSystem.get_tree();
|
let tree = new GMenu.Tree({ menu_basename: "applications.menu" });
|
||||||
|
tree.load_sync();
|
||||||
let root = tree.get_root_directory();
|
let root = tree.get_root_directory();
|
||||||
|
|
||||||
let iter = root.iter();
|
let iter = root.iter();
|
||||||
@ -817,8 +817,6 @@ const AppDisplay = new Lang.Class({
|
|||||||
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
||||||
if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||||
let dir = iter.get_directory();
|
let dir = iter.get_directory();
|
||||||
if (dir.get_is_nodisplay())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (folderCategories.indexOf(dir.get_menu_id()) != -1)
|
if (folderCategories.indexOf(dir.get_menu_id()) != -1)
|
||||||
view.addFolder(dir);
|
view.addFolder(dir);
|
||||||
@ -866,8 +864,8 @@ const AppSearchProvider = new Lang.Class({
|
|||||||
getResultMetas: function(apps, callback) {
|
getResultMetas: function(apps, callback) {
|
||||||
let metas = [];
|
let metas = [];
|
||||||
for (let i = 0; i < apps.length; i++) {
|
for (let i = 0; i < apps.length; i++) {
|
||||||
let app = apps[i];
|
let app = this._appSys.lookup_app(apps[i]);
|
||||||
metas.push({ 'id': app,
|
metas.push({ 'id': app.get_id(),
|
||||||
'name': app.get_name(),
|
'name': app.get_name(),
|
||||||
'createIcon': function(size) {
|
'createIcon': function(size) {
|
||||||
return app.create_icon_texture(size);
|
return app.create_icon_texture(size);
|
||||||
@ -877,15 +875,23 @@ const AppSearchProvider = new Lang.Class({
|
|||||||
callback(metas);
|
callback(metas);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_compareResults: function(a, b) {
|
||||||
|
let usage = Shell.AppUsage.get_default();
|
||||||
|
return usage.compare('', a, b);
|
||||||
|
},
|
||||||
|
|
||||||
getInitialResultSet: function(terms) {
|
getInitialResultSet: function(terms) {
|
||||||
this.searchSystem.setResults(this, this._appSys.initial_search(terms));
|
let query = terms.join(' ');
|
||||||
|
let results = Gio.DesktopAppInfo.search(query, Lang.bind(this, this._compareResults), MAX_COLUMNS);
|
||||||
|
this.searchSystem.setResults(this, results);
|
||||||
},
|
},
|
||||||
|
|
||||||
getSubsearchResultSet: function(previousResults, terms) {
|
getSubsearchResultSet: function(previousResults, terms) {
|
||||||
this.searchSystem.setResults(this, this._appSys.subsearch(previousResults, terms));
|
this.getInitialResultSet(terms);
|
||||||
},
|
},
|
||||||
|
|
||||||
activateResult: function(app) {
|
activateResult: function(result) {
|
||||||
|
let app = this._appSys.lookup_app(result);
|
||||||
let event = Clutter.get_current_event();
|
let event = Clutter.get_current_event();
|
||||||
let modifiers = event ? event.get_state() : 0;
|
let modifiers = event ? event.get_state() : 0;
|
||||||
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
||||||
@ -905,7 +911,7 @@ const AppSearchProvider = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
createResultObject: function (resultMeta, terms) {
|
createResultObject: function (resultMeta, terms) {
|
||||||
let app = resultMeta['id'];
|
let app = this._appSys.lookup_app(resultMeta['id']);
|
||||||
return new AppIcon(app);
|
return new AppIcon(app);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -12,9 +12,9 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
ShellApp* _shell_app_new_for_window (MetaWindow *window);
|
ShellApp* _shell_app_new_for_window (MetaWindow *window);
|
||||||
|
|
||||||
ShellApp* _shell_app_new (GMenuTreeEntry *entry);
|
ShellApp* _shell_app_new (GDesktopAppInfo *info);
|
||||||
|
|
||||||
void _shell_app_set_entry (ShellApp *app, GMenuTreeEntry *entry);
|
void _shell_app_set_app_info (ShellApp *app, GDesktopAppInfo *info);
|
||||||
|
|
||||||
void _shell_app_handle_startup_sequence (ShellApp *app, SnStartupSequence *sequence);
|
void _shell_app_handle_startup_sequence (ShellApp *app, SnStartupSequence *sequence);
|
||||||
|
|
||||||
|
@ -38,18 +38,12 @@ enum {
|
|||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
struct _ShellAppSystemPrivate {
|
struct _ShellAppSystemPrivate {
|
||||||
GMenuTree *apps_tree;
|
|
||||||
|
|
||||||
GHashTable *running_apps;
|
GHashTable *running_apps;
|
||||||
GHashTable *visible_id_to_app;
|
|
||||||
GHashTable *id_to_app;
|
GHashTable *id_to_app;
|
||||||
GHashTable *startup_wm_class_to_app;
|
GHashTable *startup_wm_class_to_id;
|
||||||
|
|
||||||
GSList *known_vendor_prefixes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shell_app_system_finalize (GObject *object);
|
static void shell_app_system_finalize (GObject *object);
|
||||||
static void on_apps_tree_changed_cb (GMenuTree *tree, gpointer user_data);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
|
||||||
|
|
||||||
@ -77,10 +71,45 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
|
|||||||
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
|
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
scan_startup_wm_class_to_id (ShellAppSystem *self)
|
||||||
|
{
|
||||||
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
GList *apps, *l;
|
||||||
|
|
||||||
|
g_hash_table_remove_all (priv->startup_wm_class_to_id);
|
||||||
|
|
||||||
|
apps = g_app_info_get_all ();
|
||||||
|
for (l = apps; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
GAppInfo *info = l->data;
|
||||||
|
const char *startup_wm_class, *id;
|
||||||
|
|
||||||
|
id = g_app_info_get_id (info);
|
||||||
|
startup_wm_class = g_desktop_app_info_get_startup_wm_class (G_DESKTOP_APP_INFO (info));
|
||||||
|
if (startup_wm_class != NULL)
|
||||||
|
g_hash_table_insert (priv->startup_wm_class_to_id, (char *) startup_wm_class, (char *) id);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free_full (apps, g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
installed_changed (GAppInfoMonitor *monitor,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppSystem *self = user_data;
|
||||||
|
|
||||||
|
scan_startup_wm_class_to_id (self);
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[INSTALLED_CHANGED], 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_app_system_init (ShellAppSystem *self)
|
shell_app_system_init (ShellAppSystem *self)
|
||||||
{
|
{
|
||||||
ShellAppSystemPrivate *priv;
|
ShellAppSystemPrivate *priv;
|
||||||
|
GAppInfoMonitor *monitor;
|
||||||
|
|
||||||
self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
SHELL_TYPE_APP_SYSTEM,
|
SHELL_TYPE_APP_SYSTEM,
|
||||||
@ -91,19 +120,11 @@ shell_app_system_init (ShellAppSystem *self)
|
|||||||
NULL,
|
NULL,
|
||||||
(GDestroyNotify)g_object_unref);
|
(GDestroyNotify)g_object_unref);
|
||||||
|
|
||||||
/* All the objects in this hash table are owned by id_to_app */
|
priv->startup_wm_class_to_id = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
priv->visible_id_to_app = g_hash_table_new (g_str_hash, g_str_equal);
|
|
||||||
|
|
||||||
priv->startup_wm_class_to_app = g_hash_table_new_full (g_str_hash, g_str_equal,
|
monitor = g_app_info_monitor_get ();
|
||||||
NULL,
|
g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
|
||||||
(GDestroyNotify)g_object_unref);
|
installed_changed (monitor, self);
|
||||||
|
|
||||||
/* We want to track NoDisplay apps, so we add INCLUDE_NODISPLAY. We'll
|
|
||||||
* filter NoDisplay apps out when showing them to the user. */
|
|
||||||
priv->apps_tree = gmenu_tree_new ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
|
|
||||||
g_signal_connect (priv->apps_tree, "changed", G_CALLBACK (on_apps_tree_changed_cb), self);
|
|
||||||
|
|
||||||
on_apps_tree_changed_cb (priv->apps_tree, self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -112,313 +133,13 @@ shell_app_system_finalize (GObject *object)
|
|||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
||||||
ShellAppSystemPrivate *priv = self->priv;
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
|
||||||
g_object_unref (priv->apps_tree);
|
|
||||||
|
|
||||||
g_hash_table_destroy (priv->running_apps);
|
g_hash_table_destroy (priv->running_apps);
|
||||||
g_hash_table_destroy (priv->id_to_app);
|
g_hash_table_destroy (priv->id_to_app);
|
||||||
g_hash_table_destroy (priv->visible_id_to_app);
|
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
||||||
g_hash_table_destroy (priv->startup_wm_class_to_app);
|
|
||||||
|
|
||||||
g_slist_free_full (priv->known_vendor_prefixes, g_free);
|
|
||||||
priv->known_vendor_prefixes = NULL;
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
get_prefix_for_entry (GMenuTreeEntry *entry)
|
|
||||||
{
|
|
||||||
char *prefix = NULL, *file_prefix = NULL;
|
|
||||||
const char *id;
|
|
||||||
GFile *file;
|
|
||||||
char *name;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
id = gmenu_tree_entry_get_desktop_file_id (entry);
|
|
||||||
file = g_file_new_for_path (gmenu_tree_entry_get_desktop_file_path (entry));
|
|
||||||
name = g_file_get_basename (file);
|
|
||||||
|
|
||||||
if (!name)
|
|
||||||
{
|
|
||||||
g_object_unref (file);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (i = 0; vendor_prefixes[i]; i++)
|
|
||||||
{
|
|
||||||
if (g_str_has_prefix (name, vendor_prefixes[i]))
|
|
||||||
{
|
|
||||||
file_prefix = g_strdup (vendor_prefixes[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (strcmp (name, id) != 0)
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
char *pname;
|
|
||||||
GFile *parent = g_file_get_parent (file);
|
|
||||||
|
|
||||||
if (!parent)
|
|
||||||
{
|
|
||||||
g_warn_if_reached ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pname = g_file_get_basename (parent);
|
|
||||||
if (!pname)
|
|
||||||
{
|
|
||||||
g_object_unref (parent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!g_strstr_len (id, -1, pname))
|
|
||||||
{
|
|
||||||
/* handle <LegacyDir prefix="..."> */
|
|
||||||
char *t;
|
|
||||||
size_t name_len = strlen (name);
|
|
||||||
size_t id_len = strlen (id);
|
|
||||||
char *t_id = g_strdup (id);
|
|
||||||
|
|
||||||
t_id[id_len - name_len] = '\0';
|
|
||||||
t = g_strdup(t_id);
|
|
||||||
g_free (prefix);
|
|
||||||
g_free (t_id);
|
|
||||||
g_free (name);
|
|
||||||
name = g_strdup (id);
|
|
||||||
prefix = t;
|
|
||||||
|
|
||||||
g_object_unref (file);
|
|
||||||
file = parent;
|
|
||||||
g_free (pname);
|
|
||||||
g_free (file_prefix);
|
|
||||||
file_prefix = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = g_strconcat (pname, "-", name, NULL);
|
|
||||||
g_free (name);
|
|
||||||
name = t;
|
|
||||||
|
|
||||||
t = g_strconcat (pname, "-", prefix, NULL);
|
|
||||||
g_free (prefix);
|
|
||||||
prefix = t;
|
|
||||||
|
|
||||||
g_object_unref (file);
|
|
||||||
file = parent;
|
|
||||||
g_free (pname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file)
|
|
||||||
g_object_unref (file);
|
|
||||||
|
|
||||||
if (strcmp (name, id) == 0)
|
|
||||||
{
|
|
||||||
g_free (name);
|
|
||||||
if (file_prefix && !prefix)
|
|
||||||
return file_prefix;
|
|
||||||
if (file_prefix)
|
|
||||||
{
|
|
||||||
char *t = g_strconcat (prefix, "-", file_prefix, NULL);
|
|
||||||
g_free (prefix);
|
|
||||||
g_free (file_prefix);
|
|
||||||
prefix = t;
|
|
||||||
}
|
|
||||||
return prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (name);
|
|
||||||
g_free (prefix);
|
|
||||||
g_free (file_prefix);
|
|
||||||
g_return_val_if_reached (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_flattened_entries_recurse (GMenuTreeDirectory *dir,
|
|
||||||
GHashTable *entry_set)
|
|
||||||
{
|
|
||||||
GMenuTreeIter *iter = gmenu_tree_directory_iter (dir);
|
|
||||||
GMenuTreeItemType next_type;
|
|
||||||
|
|
||||||
while ((next_type = gmenu_tree_iter_next (iter)) != GMENU_TREE_ITEM_INVALID)
|
|
||||||
{
|
|
||||||
gpointer item = NULL;
|
|
||||||
|
|
||||||
switch (next_type)
|
|
||||||
{
|
|
||||||
case GMENU_TREE_ITEM_ENTRY:
|
|
||||||
{
|
|
||||||
GMenuTreeEntry *entry;
|
|
||||||
item = entry = gmenu_tree_iter_get_entry (iter);
|
|
||||||
/* Key is owned by entry */
|
|
||||||
g_hash_table_replace (entry_set,
|
|
||||||
(char*)gmenu_tree_entry_get_desktop_file_id (entry),
|
|
||||||
gmenu_tree_item_ref (entry));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GMENU_TREE_ITEM_DIRECTORY:
|
|
||||||
{
|
|
||||||
item = gmenu_tree_iter_get_directory (iter);
|
|
||||||
get_flattened_entries_recurse ((GMenuTreeDirectory*)item, entry_set);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (item != NULL)
|
|
||||||
gmenu_tree_item_unref (item);
|
|
||||||
}
|
|
||||||
|
|
||||||
gmenu_tree_iter_unref (iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GHashTable *
|
|
||||||
get_flattened_entries_from_tree (GMenuTree *tree)
|
|
||||||
{
|
|
||||||
GHashTable *table;
|
|
||||||
GMenuTreeDirectory *root;
|
|
||||||
|
|
||||||
table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
||||||
(GDestroyNotify) NULL,
|
|
||||||
(GDestroyNotify) gmenu_tree_item_unref);
|
|
||||||
|
|
||||||
root = gmenu_tree_get_root_directory (tree);
|
|
||||||
|
|
||||||
if (root != NULL)
|
|
||||||
get_flattened_entries_recurse (root, table);
|
|
||||||
|
|
||||||
gmenu_tree_item_unref (root);
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_apps_tree_changed_cb (GMenuTree *tree,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
|
||||||
GError *error = NULL;
|
|
||||||
GHashTable *new_apps;
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key, value;
|
|
||||||
|
|
||||||
g_assert (tree == self->priv->apps_tree);
|
|
||||||
|
|
||||||
g_hash_table_remove_all (self->priv->visible_id_to_app);
|
|
||||||
g_slist_free_full (self->priv->known_vendor_prefixes, g_free);
|
|
||||||
self->priv->known_vendor_prefixes = NULL;
|
|
||||||
|
|
||||||
if (!gmenu_tree_load_sync (self->priv->apps_tree, &error))
|
|
||||||
{
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
g_warning ("Failed to load apps: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("Failed to load apps");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
|
|
||||||
g_hash_table_iter_init (&iter, new_apps);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
||||||
{
|
|
||||||
const char *id = key;
|
|
||||||
GMenuTreeEntry *entry = value;
|
|
||||||
GMenuTreeEntry *old_entry;
|
|
||||||
char *prefix;
|
|
||||||
ShellApp *app;
|
|
||||||
GDesktopAppInfo *info;
|
|
||||||
const char *startup_wm_class;
|
|
||||||
|
|
||||||
prefix = get_prefix_for_entry (entry);
|
|
||||||
|
|
||||||
if (prefix != NULL
|
|
||||||
&& !g_slist_find_custom (self->priv->known_vendor_prefixes, prefix,
|
|
||||||
(GCompareFunc)g_strcmp0))
|
|
||||||
self->priv->known_vendor_prefixes = g_slist_append (self->priv->known_vendor_prefixes,
|
|
||||||
prefix);
|
|
||||||
else
|
|
||||||
g_free (prefix);
|
|
||||||
|
|
||||||
app = g_hash_table_lookup (self->priv->id_to_app, id);
|
|
||||||
if (app != NULL)
|
|
||||||
{
|
|
||||||
/* We hold a reference to the original entry temporarily,
|
|
||||||
* because otherwise the hash table would be referencing
|
|
||||||
* potentially free'd memory until we replace it below with
|
|
||||||
* the new data.
|
|
||||||
*/
|
|
||||||
old_entry = shell_app_get_tree_entry (app);
|
|
||||||
gmenu_tree_item_ref (old_entry);
|
|
||||||
_shell_app_set_entry (app, entry);
|
|
||||||
g_object_ref (app); /* Extra ref, removed in _replace below */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
old_entry = NULL;
|
|
||||||
app = _shell_app_new (entry);
|
|
||||||
}
|
|
||||||
/* Note that "id" is owned by app->entry. Since we're always
|
|
||||||
* setting a new entry, even if the app already exists in the
|
|
||||||
* hash table we need to replace the key so that the new id
|
|
||||||
* string is pointed to.
|
|
||||||
*/
|
|
||||||
g_hash_table_replace (self->priv->id_to_app, (char*)id, app);
|
|
||||||
if (!gmenu_tree_entry_get_is_nodisplay_recurse (entry))
|
|
||||||
g_hash_table_replace (self->priv->visible_id_to_app, (char*)id, app);
|
|
||||||
|
|
||||||
if (old_entry)
|
|
||||||
{
|
|
||||||
GDesktopAppInfo *old_info;
|
|
||||||
const gchar *old_startup_wm_class;
|
|
||||||
|
|
||||||
old_info = gmenu_tree_entry_get_app_info (old_entry);
|
|
||||||
old_startup_wm_class = g_desktop_app_info_get_startup_wm_class (old_info);
|
|
||||||
|
|
||||||
if (old_startup_wm_class)
|
|
||||||
g_hash_table_remove (self->priv->startup_wm_class_to_app, old_startup_wm_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
info = gmenu_tree_entry_get_app_info (entry);
|
|
||||||
startup_wm_class = g_desktop_app_info_get_startup_wm_class (info);
|
|
||||||
if (startup_wm_class)
|
|
||||||
g_hash_table_replace (self->priv->startup_wm_class_to_app,
|
|
||||||
(char*)startup_wm_class, g_object_ref (app));
|
|
||||||
|
|
||||||
if (old_entry)
|
|
||||||
gmenu_tree_item_unref (old_entry);
|
|
||||||
}
|
|
||||||
/* Now iterate over the apps again; we need to unreference any apps
|
|
||||||
* which have been removed. The JS code may still be holding a
|
|
||||||
* reference; that's fine.
|
|
||||||
*/
|
|
||||||
g_hash_table_iter_init (&iter, self->priv->id_to_app);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
||||||
{
|
|
||||||
const char *id = key;
|
|
||||||
|
|
||||||
if (!g_hash_table_lookup (new_apps, id))
|
|
||||||
g_hash_table_iter_remove (&iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_hash_table_destroy (new_apps);
|
|
||||||
|
|
||||||
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_app_system_get_tree:
|
|
||||||
*
|
|
||||||
* Return Value: (transfer none): The #GMenuTree for apps
|
|
||||||
*/
|
|
||||||
GMenuTree *
|
|
||||||
shell_app_system_get_tree (ShellAppSystem *self)
|
|
||||||
{
|
|
||||||
return self->priv->apps_tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_app_system_get_default:
|
* shell_app_system_get_default:
|
||||||
*
|
*
|
||||||
@ -446,61 +167,20 @@ ShellApp *
|
|||||||
shell_app_system_lookup_app (ShellAppSystem *self,
|
shell_app_system_lookup_app (ShellAppSystem *self,
|
||||||
const char *id)
|
const char *id)
|
||||||
{
|
{
|
||||||
return g_hash_table_lookup (self->priv->id_to_app, id);
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_app_system_lookup_app_by_tree_entry:
|
|
||||||
* @system: a #ShellAppSystem
|
|
||||||
* @entry: a #GMenuTreeEntry
|
|
||||||
*
|
|
||||||
* Find a #ShellApp corresponding to a #GMenuTreeEntry.
|
|
||||||
*
|
|
||||||
* Return value: (transfer none): The #ShellApp for @entry, or %NULL if none
|
|
||||||
*/
|
|
||||||
ShellApp *
|
|
||||||
shell_app_system_lookup_app_by_tree_entry (ShellAppSystem *self,
|
|
||||||
GMenuTreeEntry *entry)
|
|
||||||
{
|
|
||||||
/* If we looked up directly in ->entry_to_app, we'd lose the
|
|
||||||
* override of running apps. Thus, indirect through the id.
|
|
||||||
*/
|
|
||||||
return shell_app_system_lookup_app (self, gmenu_tree_entry_get_desktop_file_id (entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_app_system_lookup_app_for_path:
|
|
||||||
* @system: a #ShellAppSystem
|
|
||||||
* @desktop_path: (type utf8): UTF-8 encoded absolute file name
|
|
||||||
*
|
|
||||||
* Find or create a #ShellApp corresponding to a given absolute file
|
|
||||||
* name which must be in the standard paths (XDG_DATA_DIRS). For
|
|
||||||
* files outside the datadirs, this function returns %NULL.
|
|
||||||
*
|
|
||||||
* Return value: (transfer none): The #ShellApp for id, or %NULL if none
|
|
||||||
*/
|
|
||||||
ShellApp *
|
|
||||||
shell_app_system_lookup_app_for_path (ShellAppSystem *system,
|
|
||||||
const char *desktop_path)
|
|
||||||
{
|
|
||||||
const char *basename;
|
|
||||||
const char *app_path;
|
|
||||||
ShellApp *app;
|
ShellApp *app;
|
||||||
|
GDesktopAppInfo *info;
|
||||||
|
|
||||||
basename = g_strrstr (desktop_path, "/");
|
app = g_hash_table_lookup (priv->id_to_app, id);
|
||||||
if (basename)
|
if (app)
|
||||||
basename += 1;
|
return app;
|
||||||
else
|
|
||||||
basename = desktop_path;
|
|
||||||
|
|
||||||
app = shell_app_system_lookup_app (system, basename);
|
info = g_desktop_app_info_new (id);
|
||||||
if (!app)
|
if (!info)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
app_path = g_desktop_app_info_get_filename (shell_app_get_app_info (app));
|
|
||||||
if (strcmp (desktop_path, app_path) != 0)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
app = _shell_app_new (info);
|
||||||
|
g_hash_table_insert (priv->id_to_app, (char *) id, app);
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,15 +200,15 @@ shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
|
|||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
ShellApp *result;
|
ShellApp *result;
|
||||||
GSList *prefix;
|
const char *const *prefix;
|
||||||
|
|
||||||
result = shell_app_system_lookup_app (system, name);
|
result = shell_app_system_lookup_app (system, name);
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
for (prefix = system->priv->known_vendor_prefixes; prefix; prefix = g_slist_next (prefix))
|
for (prefix = vendor_prefixes; *prefix != NULL; prefix++)
|
||||||
{
|
{
|
||||||
char *tmpid = g_strconcat ((char*)prefix->data, name, NULL);
|
char *tmpid = g_strconcat (*prefix, name, NULL);
|
||||||
result = shell_app_system_lookup_app (system, tmpid);
|
result = shell_app_system_lookup_app (system, tmpid);
|
||||||
g_free (tmpid);
|
g_free (tmpid);
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
@ -603,10 +283,16 @@ ShellApp *
|
|||||||
shell_app_system_lookup_startup_wmclass (ShellAppSystem *system,
|
shell_app_system_lookup_startup_wmclass (ShellAppSystem *system,
|
||||||
const char *wmclass)
|
const char *wmclass)
|
||||||
{
|
{
|
||||||
|
const char *id;
|
||||||
|
|
||||||
if (wmclass == NULL)
|
if (wmclass == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return g_hash_table_lookup (system->priv->startup_wm_class_to_app, wmclass);
|
id = g_hash_table_lookup (system->priv->startup_wm_class_to_id, wmclass);
|
||||||
|
if (id == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return shell_app_system_lookup_app (system, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -661,136 +347,3 @@ shell_app_system_get_running (ShellAppSystem *self)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gint
|
|
||||||
compare_apps_by_usage (gconstpointer a,
|
|
||||||
gconstpointer b,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
ShellAppUsage *usage = shell_app_usage_get_default ();
|
|
||||||
|
|
||||||
ShellApp *app_a = (ShellApp*)a;
|
|
||||||
ShellApp *app_b = (ShellApp*)b;
|
|
||||||
|
|
||||||
return shell_app_usage_compare (usage, "", app_a, app_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSList *
|
|
||||||
sort_and_concat_results (ShellAppSystem *system,
|
|
||||||
GSList *prefix_matches,
|
|
||||||
GSList *substring_matches)
|
|
||||||
{
|
|
||||||
prefix_matches = g_slist_sort_with_data (prefix_matches,
|
|
||||||
compare_apps_by_usage,
|
|
||||||
system);
|
|
||||||
substring_matches = g_slist_sort_with_data (substring_matches,
|
|
||||||
compare_apps_by_usage,
|
|
||||||
system);
|
|
||||||
return g_slist_concat (prefix_matches, substring_matches);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* normalize_terms:
|
|
||||||
* @terms: (element-type utf8): Input search terms
|
|
||||||
*
|
|
||||||
* Returns: (element-type utf8) (transfer full): Unicode-normalized and lowercased terms
|
|
||||||
*/
|
|
||||||
static GSList *
|
|
||||||
normalize_terms (GSList *terms)
|
|
||||||
{
|
|
||||||
GSList *normalized_terms = NULL;
|
|
||||||
GSList *iter;
|
|
||||||
for (iter = terms; iter; iter = iter->next)
|
|
||||||
{
|
|
||||||
const char *term = iter->data;
|
|
||||||
normalized_terms = g_slist_prepend (normalized_terms,
|
|
||||||
shell_util_normalize_casefold_and_unaccent (term));
|
|
||||||
}
|
|
||||||
return normalized_terms;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSList *
|
|
||||||
search_tree (ShellAppSystem *self,
|
|
||||||
GSList *terms,
|
|
||||||
GHashTable *apps)
|
|
||||||
{
|
|
||||||
GSList *prefix_results = NULL;
|
|
||||||
GSList *substring_results = NULL;
|
|
||||||
GSList *normalized_terms;
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key, value;
|
|
||||||
|
|
||||||
normalized_terms = normalize_terms (terms);
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, apps);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
||||||
{
|
|
||||||
ShellApp *app = value;
|
|
||||||
_shell_app_do_match (app, normalized_terms,
|
|
||||||
&prefix_results,
|
|
||||||
&substring_results);
|
|
||||||
}
|
|
||||||
g_slist_free_full (normalized_terms, g_free);
|
|
||||||
|
|
||||||
return sort_and_concat_results (self, prefix_results, substring_results);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_app_system_initial_search:
|
|
||||||
* @system: A #ShellAppSystem
|
|
||||||
* @terms: (element-type utf8): List of terms, logical AND
|
|
||||||
*
|
|
||||||
* Search through applications for the given search terms.
|
|
||||||
*
|
|
||||||
* Returns: (transfer container) (element-type ShellApp): List of applications
|
|
||||||
*/
|
|
||||||
GSList *
|
|
||||||
shell_app_system_initial_search (ShellAppSystem *self,
|
|
||||||
GSList *terms)
|
|
||||||
{
|
|
||||||
return search_tree (self, terms, self->priv->visible_id_to_app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_app_system_subsearch:
|
|
||||||
* @system: A #ShellAppSystem
|
|
||||||
* @previous_results: (element-type ShellApp): List of previous results
|
|
||||||
* @terms: (element-type utf8): List of terms, logical AND
|
|
||||||
*
|
|
||||||
* Search through a previous result set; for more information, see
|
|
||||||
* js/ui/search.js. Note the value of @prefs must be
|
|
||||||
* the same as passed to shell_app_system_initial_search(). Note that returned
|
|
||||||
* strings are only valid until a return to the main loop.
|
|
||||||
*
|
|
||||||
* Returns: (transfer container) (element-type ShellApp): List of application identifiers
|
|
||||||
*/
|
|
||||||
GSList *
|
|
||||||
shell_app_system_subsearch (ShellAppSystem *system,
|
|
||||||
GSList *previous_results,
|
|
||||||
GSList *terms)
|
|
||||||
{
|
|
||||||
GSList *iter;
|
|
||||||
GSList *prefix_results = NULL;
|
|
||||||
GSList *substring_results = NULL;
|
|
||||||
GSList *normalized_terms = normalize_terms (terms);
|
|
||||||
|
|
||||||
previous_results = g_slist_reverse (previous_results);
|
|
||||||
|
|
||||||
for (iter = previous_results; iter; iter = iter->next)
|
|
||||||
{
|
|
||||||
ShellApp *app = iter->data;
|
|
||||||
|
|
||||||
_shell_app_do_match (app, normalized_terms,
|
|
||||||
&prefix_results,
|
|
||||||
&substring_results);
|
|
||||||
}
|
|
||||||
g_slist_free_full (normalized_terms, g_free);
|
|
||||||
|
|
||||||
/* Note that a shorter term might have matched as a prefix, but
|
|
||||||
when extended only as a substring, so we have to redo the
|
|
||||||
sort rather than reusing the existing ordering */
|
|
||||||
return sort_and_concat_results (system, prefix_results, substring_results);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
|
|
||||||
#include <gmenu-tree.h>
|
|
||||||
|
|
||||||
#include "shell-app.h"
|
#include "shell-app.h"
|
||||||
|
|
||||||
@ -39,14 +37,8 @@ struct _ShellAppSystemClass
|
|||||||
GType shell_app_system_get_type (void) G_GNUC_CONST;
|
GType shell_app_system_get_type (void) G_GNUC_CONST;
|
||||||
ShellAppSystem *shell_app_system_get_default (void);
|
ShellAppSystem *shell_app_system_get_default (void);
|
||||||
|
|
||||||
GMenuTree *shell_app_system_get_tree (ShellAppSystem *system);
|
|
||||||
|
|
||||||
ShellApp *shell_app_system_lookup_app (ShellAppSystem *system,
|
ShellApp *shell_app_system_lookup_app (ShellAppSystem *system,
|
||||||
const char *id);
|
const char *id);
|
||||||
ShellApp *shell_app_system_lookup_app_by_tree_entry (ShellAppSystem *system,
|
|
||||||
GMenuTreeEntry *entry);
|
|
||||||
ShellApp *shell_app_system_lookup_app_for_path (ShellAppSystem *system,
|
|
||||||
const char *desktop_path);
|
|
||||||
ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
|
ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
|
||||||
const char *id);
|
const char *id);
|
||||||
|
|
||||||
@ -57,10 +49,4 @@ ShellApp *shell_app_system_lookup_desktop_wmclass (ShellAppSystem *s
|
|||||||
|
|
||||||
GSList *shell_app_system_get_running (ShellAppSystem *self);
|
GSList *shell_app_system_get_running (ShellAppSystem *self);
|
||||||
|
|
||||||
GSList *shell_app_system_initial_search (ShellAppSystem *system,
|
|
||||||
GSList *terms);
|
|
||||||
GSList *shell_app_system_subsearch (ShellAppSystem *system,
|
|
||||||
GSList *previous_results,
|
|
||||||
GSList *terms);
|
|
||||||
|
|
||||||
#endif /* __SHELL_APP_SYSTEM_H__ */
|
#endif /* __SHELL_APP_SYSTEM_H__ */
|
||||||
|
@ -527,19 +527,19 @@ shell_app_usage_get_most_used (ShellAppUsage *self,
|
|||||||
* shell_app_usage_compare:
|
* shell_app_usage_compare:
|
||||||
* @self: the usage instance to request
|
* @self: the usage instance to request
|
||||||
* @context: Activity identifier
|
* @context: Activity identifier
|
||||||
* @app_a: First app
|
* @id_a: ID of first app
|
||||||
* @app_b: Second app
|
* @id_b: ID of second app
|
||||||
*
|
*
|
||||||
* Compare @app_a and @app_b based on frequency of use.
|
* Compare @id_a and @id_b based on frequency of use.
|
||||||
*
|
*
|
||||||
* Returns: -1 if @app_a ranks higher than @app_b, 1 if @app_b ranks higher
|
* Returns: -1 if @id_a ranks higher than @id_b, 1 if @id_b ranks higher
|
||||||
* than @app_a, and 0 if both rank equally.
|
* than @id_a, and 0 if both rank equally.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
shell_app_usage_compare (ShellAppUsage *self,
|
shell_app_usage_compare (ShellAppUsage *self,
|
||||||
const char *context,
|
const char *context,
|
||||||
ShellApp *app_a,
|
const char *id_a,
|
||||||
ShellApp *app_b)
|
const char *id_b)
|
||||||
{
|
{
|
||||||
GHashTable *usages;
|
GHashTable *usages;
|
||||||
UsageData *usage_a, *usage_b;
|
UsageData *usage_a, *usage_b;
|
||||||
@ -548,8 +548,8 @@ shell_app_usage_compare (ShellAppUsage *self,
|
|||||||
if (usages == NULL)
|
if (usages == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
usage_a = g_hash_table_lookup (usages, shell_app_get_id (app_a));
|
usage_a = g_hash_table_lookup (usages, id_a);
|
||||||
usage_b = g_hash_table_lookup (usages, shell_app_get_id (app_b));
|
usage_b = g_hash_table_lookup (usages, id_b);
|
||||||
|
|
||||||
if (usage_a == NULL && usage_b == NULL)
|
if (usage_a == NULL && usage_b == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -31,8 +31,8 @@ GSList *shell_app_usage_get_most_used (ShellAppUsage *usage,
|
|||||||
const char *context);
|
const char *context);
|
||||||
int shell_app_usage_compare (ShellAppUsage *self,
|
int shell_app_usage_compare (ShellAppUsage *self,
|
||||||
const char *context,
|
const char *context,
|
||||||
ShellApp *app_a,
|
const char *id_a,
|
||||||
ShellApp *app_b);
|
const char *id_b);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ typedef struct {
|
|||||||
* SECTION:shell-app
|
* SECTION:shell-app
|
||||||
* @short_description: Object representing an application
|
* @short_description: Object representing an application
|
||||||
*
|
*
|
||||||
* This object wraps a #GMenuTreeEntry, providing methods and signals
|
* This object wraps a #GDesktopAppInfo, providing methods and signals
|
||||||
* primarily useful for running applications.
|
* primarily useful for running applications.
|
||||||
*/
|
*/
|
||||||
struct _ShellApp
|
struct _ShellApp
|
||||||
@ -64,7 +64,7 @@ struct _ShellApp
|
|||||||
|
|
||||||
ShellAppState state;
|
ShellAppState state;
|
||||||
|
|
||||||
GMenuTreeEntry *entry; /* If NULL, this app is backed by one or more
|
GDesktopAppInfo *info; /* If NULL, this app is backed by one or more
|
||||||
* MetaWindow. For purposes of app title
|
* MetaWindow. For purposes of app title
|
||||||
* etc., we use the first window added,
|
* etc., we use the first window added,
|
||||||
* because it's most likely to be what we
|
* because it's most likely to be what we
|
||||||
@ -137,15 +137,15 @@ shell_app_get_property (GObject *gobject,
|
|||||||
const char *
|
const char *
|
||||||
shell_app_get_id (ShellApp *app)
|
shell_app_get_id (ShellApp *app)
|
||||||
{
|
{
|
||||||
if (app->entry)
|
if (app->info)
|
||||||
return gmenu_tree_entry_get_desktop_file_id (app->entry);
|
return g_app_info_get_id (G_APP_INFO (app->info));
|
||||||
return app->window_id_string;
|
return app->window_id_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaWindow *
|
static MetaWindow *
|
||||||
window_backed_app_get_window (ShellApp *app)
|
window_backed_app_get_window (ShellApp *app)
|
||||||
{
|
{
|
||||||
g_assert (app->entry == NULL);
|
g_assert (app->info == NULL);
|
||||||
g_assert (app->running_state);
|
g_assert (app->running_state);
|
||||||
g_assert (app->running_state->windows);
|
g_assert (app->running_state->windows);
|
||||||
return app->running_state->windows->data;
|
return app->running_state->windows->data;
|
||||||
@ -194,10 +194,10 @@ shell_app_create_icon_texture (ShellApp *app,
|
|||||||
|
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
|
|
||||||
if (app->entry == NULL)
|
if (app->info == NULL)
|
||||||
return window_backed_app_get_icon (app, size);
|
return window_backed_app_get_icon (app, size);
|
||||||
|
|
||||||
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
icon = g_app_info_get_icon (G_APP_INFO (app->info));
|
||||||
if (icon != NULL)
|
if (icon != NULL)
|
||||||
ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, size);
|
ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, size);
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
|
|||||||
|
|
||||||
info = NULL;
|
info = NULL;
|
||||||
|
|
||||||
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
icon = g_app_info_get_icon (G_APP_INFO (app->info));
|
||||||
if (icon != NULL)
|
if (icon != NULL)
|
||||||
{
|
{
|
||||||
info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
|
info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
|
||||||
@ -347,7 +347,7 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
|
|||||||
* property tracking bits, and this helps us visually distinguish
|
* property tracking bits, and this helps us visually distinguish
|
||||||
* app-tracked from not.
|
* app-tracked from not.
|
||||||
*/
|
*/
|
||||||
if (!app->entry)
|
if (!app->info)
|
||||||
return window_backed_app_get_icon (app, size);
|
return window_backed_app_get_icon (app, size);
|
||||||
|
|
||||||
/* Use icon: prefix so that we get evicted from the cache on
|
/* Use icon: prefix so that we get evicted from the cache on
|
||||||
@ -384,8 +384,8 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
|
|||||||
const char *
|
const char *
|
||||||
shell_app_get_name (ShellApp *app)
|
shell_app_get_name (ShellApp *app)
|
||||||
{
|
{
|
||||||
if (app->entry)
|
if (app->info)
|
||||||
return g_app_info_get_name (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
return g_app_info_get_name (G_APP_INFO (app->info));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MetaWindow *window = window_backed_app_get_window (app);
|
MetaWindow *window = window_backed_app_get_window (app);
|
||||||
@ -401,8 +401,8 @@ shell_app_get_name (ShellApp *app)
|
|||||||
const char *
|
const char *
|
||||||
shell_app_get_description (ShellApp *app)
|
shell_app_get_description (ShellApp *app)
|
||||||
{
|
{
|
||||||
if (app->entry)
|
if (app->info)
|
||||||
return g_app_info_get_description (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry)));
|
return g_app_info_get_description (G_APP_INFO (app->info));
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -417,7 +417,7 @@ shell_app_get_description (ShellApp *app)
|
|||||||
gboolean
|
gboolean
|
||||||
shell_app_is_window_backed (ShellApp *app)
|
shell_app_is_window_backed (ShellApp *app)
|
||||||
{
|
{
|
||||||
return app->entry == NULL;
|
return app->info == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -670,7 +670,7 @@ void
|
|||||||
shell_app_open_new_window (ShellApp *app,
|
shell_app_open_new_window (ShellApp *app,
|
||||||
int workspace)
|
int workspace)
|
||||||
{
|
{
|
||||||
g_return_if_fail (app->entry != NULL);
|
g_return_if_fail (app->info != NULL);
|
||||||
|
|
||||||
/* Here we just always launch the application again, even if we know
|
/* Here we just always launch the application again, even if we know
|
||||||
* it was already running. For most applications this
|
* it was already running. For most applications this
|
||||||
@ -865,24 +865,23 @@ _shell_app_new_for_window (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShellApp *
|
ShellApp *
|
||||||
_shell_app_new (GMenuTreeEntry *info)
|
_shell_app_new (GDesktopAppInfo *info)
|
||||||
{
|
{
|
||||||
ShellApp *app;
|
ShellApp *app;
|
||||||
|
|
||||||
app = g_object_new (SHELL_TYPE_APP, NULL);
|
app = g_object_new (SHELL_TYPE_APP, NULL);
|
||||||
|
|
||||||
_shell_app_set_entry (app, info);
|
_shell_app_set_app_info (app, info);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_shell_app_set_entry (ShellApp *app,
|
_shell_app_set_app_info (ShellApp *app,
|
||||||
GMenuTreeEntry *entry)
|
GDesktopAppInfo *info)
|
||||||
{
|
{
|
||||||
if (app->entry != NULL)
|
g_clear_object (&app->info);
|
||||||
gmenu_tree_item_unref (app->entry);
|
app->info = g_object_ref (info);
|
||||||
app->entry = gmenu_tree_item_ref (entry);
|
|
||||||
|
|
||||||
if (app->name_collation_key != NULL)
|
if (app->name_collation_key != NULL)
|
||||||
g_free (app->name_collation_key);
|
g_free (app->name_collation_key);
|
||||||
@ -1188,7 +1187,6 @@ shell_app_launch (ShellApp *app,
|
|||||||
char **startup_id,
|
char **startup_id,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GDesktopAppInfo *gapp;
|
|
||||||
GdkAppLaunchContext *context;
|
GdkAppLaunchContext *context;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
ShellGlobal *global;
|
ShellGlobal *global;
|
||||||
@ -1198,7 +1196,7 @@ shell_app_launch (ShellApp *app,
|
|||||||
if (startup_id)
|
if (startup_id)
|
||||||
*startup_id = NULL;
|
*startup_id = NULL;
|
||||||
|
|
||||||
if (app->entry == NULL)
|
if (app->info == NULL)
|
||||||
{
|
{
|
||||||
MetaWindow *window = window_backed_app_get_window (app);
|
MetaWindow *window = window_backed_app_get_window (app);
|
||||||
/* We can't pass URIs into a window; shouldn't hit this
|
/* We can't pass URIs into a window; shouldn't hit this
|
||||||
@ -1224,8 +1222,7 @@ shell_app_launch (ShellApp *app,
|
|||||||
gdk_app_launch_context_set_timestamp (context, timestamp);
|
gdk_app_launch_context_set_timestamp (context, timestamp);
|
||||||
gdk_app_launch_context_set_desktop (context, workspace);
|
gdk_app_launch_context_set_desktop (context, workspace);
|
||||||
|
|
||||||
gapp = gmenu_tree_entry_get_app_info (app->entry);
|
ret = g_desktop_app_info_launch_uris_as_manager (app->info, uris,
|
||||||
ret = g_desktop_app_info_launch_uris_as_manager (gapp, uris,
|
|
||||||
G_APP_LAUNCH_CONTEXT (context),
|
G_APP_LAUNCH_CONTEXT (context),
|
||||||
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
|
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
@ -1245,21 +1242,7 @@ shell_app_launch (ShellApp *app,
|
|||||||
GDesktopAppInfo *
|
GDesktopAppInfo *
|
||||||
shell_app_get_app_info (ShellApp *app)
|
shell_app_get_app_info (ShellApp *app)
|
||||||
{
|
{
|
||||||
if (app->entry)
|
return app->info;
|
||||||
return gmenu_tree_entry_get_app_info (app->entry);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_app_get_tree_entry:
|
|
||||||
* @app: a #ShellApp
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): The #GMenuTreeEntry for this app, or %NULL if backed by a window
|
|
||||||
*/
|
|
||||||
GMenuTreeEntry *
|
|
||||||
shell_app_get_tree_entry (ShellApp *app)
|
|
||||||
{
|
|
||||||
return app->entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1374,24 +1357,22 @@ shell_app_init_search_data (ShellApp *app)
|
|||||||
const char *exec;
|
const char *exec;
|
||||||
const char * const *keywords;
|
const char * const *keywords;
|
||||||
char *normalized_exec;
|
char *normalized_exec;
|
||||||
GDesktopAppInfo *appinfo;
|
|
||||||
|
|
||||||
appinfo = gmenu_tree_entry_get_app_info (app->entry);
|
name = g_app_info_get_name (G_APP_INFO (app->info));
|
||||||
name = g_app_info_get_name (G_APP_INFO (appinfo));
|
|
||||||
app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name);
|
app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name);
|
||||||
|
|
||||||
generic_name = g_desktop_app_info_get_generic_name (appinfo);
|
generic_name = g_desktop_app_info_get_generic_name (app->info);
|
||||||
if (generic_name)
|
if (generic_name)
|
||||||
app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name);
|
app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name);
|
||||||
else
|
else
|
||||||
app->casefolded_generic_name = NULL;
|
app->casefolded_generic_name = NULL;
|
||||||
|
|
||||||
exec = g_app_info_get_executable (G_APP_INFO (appinfo));
|
exec = g_app_info_get_executable (G_APP_INFO (app->info));
|
||||||
normalized_exec = shell_util_normalize_casefold_and_unaccent (exec);
|
normalized_exec = shell_util_normalize_casefold_and_unaccent (exec);
|
||||||
app->casefolded_exec = trim_exec_line (normalized_exec);
|
app->casefolded_exec = trim_exec_line (normalized_exec);
|
||||||
g_free (normalized_exec);
|
g_free (normalized_exec);
|
||||||
|
|
||||||
keywords = g_desktop_app_info_get_keywords (appinfo);
|
keywords = g_desktop_app_info_get_keywords (app->info);
|
||||||
|
|
||||||
if (keywords)
|
if (keywords)
|
||||||
{
|
{
|
||||||
@ -1512,16 +1493,14 @@ _shell_app_do_match (ShellApp *app,
|
|||||||
GSList **substring_results)
|
GSList **substring_results)
|
||||||
{
|
{
|
||||||
ShellAppSearchMatch match;
|
ShellAppSearchMatch match;
|
||||||
GAppInfo *appinfo;
|
|
||||||
|
|
||||||
g_assert (app != NULL);
|
g_assert (app != NULL);
|
||||||
|
|
||||||
/* Skip window-backed apps */
|
/* Skip window-backed apps */
|
||||||
appinfo = (GAppInfo*)shell_app_get_app_info (app);
|
if (app->info == NULL)
|
||||||
if (appinfo == NULL)
|
|
||||||
return;
|
return;
|
||||||
/* Skip not-visible apps */
|
/* Skip not-visible apps */
|
||||||
if (!g_app_info_should_show (appinfo))
|
if (!g_app_info_should_show (G_APP_INFO (app->info)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
match = _shell_app_match_search_terms (app, terms);
|
match = _shell_app_match_search_terms (app, terms);
|
||||||
@ -1550,11 +1529,7 @@ shell_app_dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
ShellApp *app = SHELL_APP (object);
|
ShellApp *app = SHELL_APP (object);
|
||||||
|
|
||||||
if (app->entry)
|
g_clear_object (&app->info);
|
||||||
{
|
|
||||||
gmenu_tree_item_unref (app->entry);
|
|
||||||
app->entry = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app->running_state)
|
if (app->running_state)
|
||||||
{
|
{
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
#include <gio/gdesktopappinfo.h>
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
|
|
||||||
#include <gmenu-tree.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -39,7 +38,6 @@ GType shell_app_get_type (void) G_GNUC_CONST;
|
|||||||
|
|
||||||
const char *shell_app_get_id (ShellApp *app);
|
const char *shell_app_get_id (ShellApp *app);
|
||||||
|
|
||||||
GMenuTreeEntry *shell_app_get_tree_entry (ShellApp *app);
|
|
||||||
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
|
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
|
||||||
|
|
||||||
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
|
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
|
||||||
|
@ -844,6 +844,7 @@ ShellApp *
|
|||||||
shell_startup_sequence_get_app (ShellStartupSequence *sequence)
|
shell_startup_sequence_get_app (ShellStartupSequence *sequence)
|
||||||
{
|
{
|
||||||
const char *appid;
|
const char *appid;
|
||||||
|
char *basename;
|
||||||
ShellAppSystem *appsys;
|
ShellAppSystem *appsys;
|
||||||
ShellApp *app;
|
ShellApp *app;
|
||||||
|
|
||||||
@ -851,8 +852,10 @@ shell_startup_sequence_get_app (ShellStartupSequence *sequence)
|
|||||||
if (!appid)
|
if (!appid)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
basename = g_path_get_basename (appid);
|
||||||
appsys = shell_app_system_get_default ();
|
appsys = shell_app_system_get_default ();
|
||||||
app = shell_app_system_lookup_app_for_path (appsys, appid);
|
app = shell_app_system_lookup_app (appsys, basename);
|
||||||
|
g_free (basename);
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user