1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 apps_menu.c for the Openbox window manager
4 Copyright (c) 2011 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
21 #include "menuframe.h"
23 #include "apps_menu.h"
26 #include "obt/linkbase.h"
28 #include "obt/paths.h"
32 #define MENU_NAME "apps-menu"
34 typedef struct _ObAppsMenuCategory ObAppsMenuCategory;
36 struct _ObAppsMenuCategory {
42 static ObMenu *apps_menu;
43 static ObtLinkBase *linkbase;
44 static gboolean dirty;
46 static ObAppsMenuCategory *categories;
47 /*! An array of pointers to the categories array, sorted by their friendly
49 static ObAppsMenuCategory **sorted_categories;
50 static guint n_categories;
52 static void self_destroy(ObMenu *menu, gpointer data)
54 menu_clear_entries(menu);
57 static gboolean self_update(ObMenuFrame *frame, gpointer data)
59 ObMenu *menu = frame->menu;
63 g_print("UPDATE DIRTY %d\n", dirty);
65 if (!dirty) return TRUE; /* nothing has changed to be updated */
67 menu_clear_entries(menu);
69 for (i = 0; i < n_categories; ++i) {
70 menu_free(categories[i].m);
71 categories[i].m = NULL;
75 for (i = 0; i < n_categories; ++i) {
77 ObAppsMenuCategory *cat = sorted_categories[i];
78 const gchar *label = g_quark_to_string(cat->q);
80 cat->m = menu_new(label, cat->friendly, FALSE, NULL);
81 e = menu_add_submenu(menu, i, label);
84 menu_add_separator(menu, SEPARATOR, screen_desktop_names[desktop]);
86 gchar *title = g_strdup_printf("(%s)", c->icon_title);
87 e = menu_add_normal(menu, desktop, title, NULL, FALSE);
90 if (config_menu_show_icons) {
91 e->data.normal.icon = client_icon(c);
92 RrImageRef(e->data.normal.icon);
93 e->data.normal.icon_alpha =
94 c->iconic ? OB_ICONIC_ALPHA : 0xff;
97 e->data.normal.data = link;
102 return TRUE; /* always show the menu */
105 static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
106 ObClient *c, guint state, gpointer data)
109 ObClient *t = self->data.normal.data;
110 if (t) { /* it's set to NULL if its destroyed */
111 gboolean here = state & ShiftMask;
113 client_activate(t, TRUE, here, TRUE, TRUE, TRUE);
114 /* if the window is omnipresent then we need to go to its
116 if (!here && t->desktop == DESKTOP_ALL)
117 screen_set_desktop(self->id, FALSE);
122 static void linkbase_update(ObtLinkBase *lb, gpointer data)
127 static int cat_cmp(const void *a, const void *b)
129 const ObAppsMenuCategory *ca = a, *cb = b;
130 return ca->q - cb->q;
133 static int cat_friendly_cmp(const void *a, const void *b)
135 ObAppsMenuCategory *const *ca = a, *const *cb = b;
136 return strcmp((*ca)->friendly, (*cb)->friendly);
139 void apps_menu_startup(gboolean reconfig)
145 paths = obt_paths_new();
146 /* XXX allow more environments, like GNOME or KDE, to be included */
147 linkbase = obt_linkbase_new(paths, ob_locale_msg,
148 OBT_LINK_ENV_OPENBOX);
149 obt_paths_unref(paths);
150 obt_linkbase_set_update_func(linkbase, linkbase_update, NULL);
154 /* From http://standards.freedesktop.org/menu-spec/latest/apa.html */
156 categories = g_new0(ObAppsMenuCategory, n_categories);
157 sorted_categories = g_new(ObAppsMenuCategory*, n_categories);
159 categories[0].q = g_quark_from_static_string("AudioVideo");
160 categories[0].friendly = _("Sound & Video");
161 categories[1].q = g_quark_from_static_string("Development");
162 categories[1].friendly = _("Programming");
163 categories[2].q = g_quark_from_static_string("Education");
164 categories[2].friendly = _("Education");
165 categories[3].q = g_quark_from_static_string("Game");
166 categories[3].friendly = _("Games");
167 categories[4].q = g_quark_from_static_string("Graphics");
168 categories[4].friendly = _("Graphics");
169 categories[5].q = g_quark_from_static_string("Network");
170 categories[5].friendly = _("Internet");
171 categories[6].q = g_quark_from_static_string("Office");
172 categories[6].friendly = _("Office");
173 categories[7].q = g_quark_from_static_string("Settings");
174 categories[7].friendly = _("Settings");
175 categories[8].q = g_quark_from_static_string("System");
176 categories[8].friendly = _("System");
177 categories[9].q = g_quark_from_static_string("Utility");
178 categories[9].friendly = _("Utility");
179 /* Sort them by their quark values */
180 qsort(categories, n_categories, sizeof(ObAppsMenuCategory), cat_cmp);
182 for (i = 0; i < n_categories; ++i)
183 sorted_categories[i] = &categories[i];
184 qsort(sorted_categories, n_categories, sizeof(void*),
188 apps_menu = menu_new(MENU_NAME, _("Applications"), TRUE, NULL);
189 menu_set_update_func(apps_menu, self_update);
190 menu_set_destroy_func(apps_menu, self_destroy);
191 menu_set_execute_func(apps_menu, menu_execute);
194 void apps_menu_shutdown(gboolean reconfig)
199 obt_linkbase_unref(linkbase);
202 for (i = 0; i < n_categories; ++i)
204 menu_free(categories[i].m);
207 g_free(sorted_categories);
208 sorted_categories = NULL;
211 /* freed by the hash table */