Changed indentation everywhere

This commit is contained in:
o9000
2017-04-13 14:07:23 +02:00
parent c1e5a7b172
commit affac4cfa6
68 changed files with 23280 additions and 22941 deletions

View File

@@ -30,280 +30,280 @@
static gint compare_strings(gconstpointer a, gconstpointer b)
{
return strnatcasecmp((const char *)a, (const char *)b);
return strnatcasecmp((const char *)a, (const char *)b);
}
int parse_dektop_line(char *line, char **key, char **value)
{
char *p;
int found = 0;
*key = line;
for (p = line; *p; p++) {
if (*p == '=') {
*value = p + 1;
*p = 0;
found = 1;
break;
}
}
if (!found)
return 0;
if (found && (strlen(*key) == 0 || strlen(*value) == 0))
return 0;
return 1;
char *p;
int found = 0;
*key = line;
for (p = line; *p; p++) {
if (*p == '=') {
*value = p + 1;
*p = 0;
found = 1;
break;
}
}
if (!found)
return 0;
if (found && (strlen(*key) == 0 || strlen(*value) == 0))
return 0;
return 1;
}
void expand_exec(DesktopEntry *entry, const char *path)
{
// Expand % in exec
// %i -> --icon Icon
// %c -> Name
// %k -> path
if (entry->exec) {
char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
(entry->icon ? strlen(entry->icon) : 1) + 100,
1);
char *p, *q;
// p will never point to an escaped char
for (p = entry->exec, q = exec2; *p; p++, q++) {
*q = *p; // Copy
if (*p == '\\') {
p++, q++;
// Copy the escaped char
if (*p == '%') // For % we delete the backslash, i.e. write % over it
q--;
*q = *p;
if (!*p)
break;
continue;
}
if (*p == '%') {
p++;
if (!*p)
break;
if (*p == 'i' && entry->icon != NULL) {
sprintf(q, "--icon '%s'", entry->icon);
q += strlen("--icon ''");
q += strlen(entry->icon);
q--; // To balance the q++ in the for
} else if (*p == 'c' && entry->name != NULL) {
sprintf(q, "'%s'", entry->name);
q += strlen("''");
q += strlen(entry->name);
q--; // To balance the q++ in the for
} else if (*p == 'c') {
sprintf(q, "'%s'", path);
q += strlen("''");
q += strlen(path);
q--; // To balance the q++ in the for
} else {
// We don't care about other expansions
q--; // Delete the last % from q
}
continue;
}
}
*q = '\0';
free(entry->exec);
entry->exec = exec2;
}
// Expand % in exec
// %i -> --icon Icon
// %c -> Name
// %k -> path
if (entry->exec) {
char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) +
(entry->icon ? strlen(entry->icon) : 1) + 100,
1);
char *p, *q;
// p will never point to an escaped char
for (p = entry->exec, q = exec2; *p; p++, q++) {
*q = *p; // Copy
if (*p == '\\') {
p++, q++;
// Copy the escaped char
if (*p == '%') // For % we delete the backslash, i.e. write % over it
q--;
*q = *p;
if (!*p)
break;
continue;
}
if (*p == '%') {
p++;
if (!*p)
break;
if (*p == 'i' && entry->icon != NULL) {
sprintf(q, "--icon '%s'", entry->icon);
q += strlen("--icon ''");
q += strlen(entry->icon);
q--; // To balance the q++ in the for
} else if (*p == 'c' && entry->name != NULL) {
sprintf(q, "'%s'", entry->name);
q += strlen("''");
q += strlen(entry->name);
q--; // To balance the q++ in the for
} else if (*p == 'c') {
sprintf(q, "'%s'", path);
q += strlen("''");
q += strlen(path);
q--; // To balance the q++ in the for
} else {
// We don't care about other expansions
q--; // Delete the last % from q
}
continue;
}
}
*q = '\0';
free(entry->exec);
entry->exec = exec2;
}
}
gboolean read_desktop_file_full_path(const char *path, DesktopEntry *entry)
{
entry->name = entry->generic_name = entry->icon = entry->exec = entry->cwd = NULL;
entry->hidden_from_menus = FALSE;
entry->name = entry->generic_name = entry->icon = entry->exec = entry->cwd = NULL;
entry->hidden_from_menus = FALSE;
FILE *fp = fopen(path, "rt");
if (fp == NULL) {
fprintf(stderr, "Could not open file %s\n", path);
return FALSE;
}
FILE *fp = fopen(path, "rt");
if (fp == NULL) {
fprintf(stderr, "Could not open file %s\n", path);
return FALSE;
}
const gchar **languages = (const gchar **)g_get_language_names();
// lang_index is the index of the language for the best Name key in the language vector
// lang_index_default is a constant that encodes the Name key without a language
int lang_index_default = 1;
const gchar **languages = (const gchar **)g_get_language_names();
// lang_index is the index of the language for the best Name key in the language vector
// lang_index_default is a constant that encodes the Name key without a language
int lang_index_default = 1;
#define LANG_DBG 0
if (LANG_DBG)
printf("Languages:");
for (int i = 0; languages[i]; i++) {
lang_index_default = i + 1;
if (LANG_DBG)
printf(" %s", languages[i]);
}
if (LANG_DBG)
printf("\n");
// we currently do not know about any Name key at all, so use an invalid index
int lang_index_name = lang_index_default + 1;
int lang_index_generic_name = lang_index_default + 1;
if (LANG_DBG)
printf("Languages:");
for (int i = 0; languages[i]; i++) {
lang_index_default = i + 1;
if (LANG_DBG)
printf(" %s", languages[i]);
}
if (LANG_DBG)
printf("\n");
// we currently do not know about any Name key at all, so use an invalid index
int lang_index_name = lang_index_default + 1;
int lang_index_generic_name = lang_index_default + 1;
gboolean inside_desktop_entry = 0;
char *line = NULL;
size_t line_size;
while (getline(&line, &line_size, fp) >= 0) {
int len = strlen(line);
if (len == 0)
continue;
if (line[len - 1] == '\n')
line[len - 1] = '\0';
if (line[0] == '[') {
inside_desktop_entry = (strcmp(line, "[Desktop Entry]") == 0);
}
char *key, *value;
if (inside_desktop_entry && parse_dektop_line(line, &key, &value)) {
if (strstr(key, "Name") == key) {
if (strcmp(key, "Name") == 0 && lang_index_name > lang_index_default) {
entry->name = strdup(value);
lang_index_name = lang_index_default;
} else {
for (int i = 0; languages[i] && i < lang_index_name; i++) {
gchar *localized_key = g_strdup_printf("Name[%s]", languages[i]);
if (strcmp(key, localized_key) == 0) {
if (entry->name)
free(entry->name);
entry->name = strdup(value);
lang_index_name = i;
}
g_free(localized_key);
}
}
} else if (strstr(key, "GenericName") == key) {
if (strcmp(key, "GenericName") == 0 && lang_index_generic_name > lang_index_default) {
entry->generic_name = strdup(value);
lang_index_generic_name = lang_index_default;
} else {
for (int i = 0; languages[i] && i < lang_index_generic_name; i++) {
gchar *localized_key = g_strdup_printf("GenericName[%s]", languages[i]);
if (strcmp(key, localized_key) == 0) {
if (entry->generic_name)
free(entry->generic_name);
entry->generic_name = strdup(value);
lang_index_generic_name = i;
}
g_free(localized_key);
}
}
} else if (!entry->exec && strcmp(key, "Exec") == 0) {
entry->exec = strdup(value);
} else if (!entry->cwd && strcmp(key, "Path") == 0) {
entry->cwd = strdup(value);
} else if (!entry->icon && strcmp(key, "Icon") == 0) {
entry->icon = strdup(value);
} else if (strcmp(key, "NoDisplay") == 0) {
entry->hidden_from_menus = strcasecmp(value, "true") == 0;
}
}
}
fclose(fp);
// From this point:
// entry->name, entry->generic_name, entry->icon, entry->exec will never be empty strings (can be NULL though)
gboolean inside_desktop_entry = 0;
char *line = NULL;
size_t line_size;
while (getline(&line, &line_size, fp) >= 0) {
int len = strlen(line);
if (len == 0)
continue;
if (line[len - 1] == '\n')
line[len - 1] = '\0';
if (line[0] == '[') {
inside_desktop_entry = (strcmp(line, "[Desktop Entry]") == 0);
}
char *key, *value;
if (inside_desktop_entry && parse_dektop_line(line, &key, &value)) {
if (strstr(key, "Name") == key) {
if (strcmp(key, "Name") == 0 && lang_index_name > lang_index_default) {
entry->name = strdup(value);
lang_index_name = lang_index_default;
} else {
for (int i = 0; languages[i] && i < lang_index_name; i++) {
gchar *localized_key = g_strdup_printf("Name[%s]", languages[i]);
if (strcmp(key, localized_key) == 0) {
if (entry->name)
free(entry->name);
entry->name = strdup(value);
lang_index_name = i;
}
g_free(localized_key);
}
}
} else if (strstr(key, "GenericName") == key) {
if (strcmp(key, "GenericName") == 0 && lang_index_generic_name > lang_index_default) {
entry->generic_name = strdup(value);
lang_index_generic_name = lang_index_default;
} else {
for (int i = 0; languages[i] && i < lang_index_generic_name; i++) {
gchar *localized_key = g_strdup_printf("GenericName[%s]", languages[i]);
if (strcmp(key, localized_key) == 0) {
if (entry->generic_name)
free(entry->generic_name);
entry->generic_name = strdup(value);
lang_index_generic_name = i;
}
g_free(localized_key);
}
}
} else if (!entry->exec && strcmp(key, "Exec") == 0) {
entry->exec = strdup(value);
} else if (!entry->cwd && strcmp(key, "Path") == 0) {
entry->cwd = strdup(value);
} else if (!entry->icon && strcmp(key, "Icon") == 0) {
entry->icon = strdup(value);
} else if (strcmp(key, "NoDisplay") == 0) {
entry->hidden_from_menus = strcasecmp(value, "true") == 0;
}
}
}
fclose(fp);
// From this point:
// entry->name, entry->generic_name, entry->icon, entry->exec will never be empty strings (can be NULL though)
expand_exec(entry, entry->path);
expand_exec(entry, entry->path);
free(line);
return entry->exec != NULL;
free(line);
return entry->exec != NULL;
}
gboolean read_desktop_file_from_dir(const char *path, const char *file_name, DesktopEntry *entry)
{
gchar *full_path = g_build_filename(path, file_name, NULL);
if (read_desktop_file_full_path(full_path, entry)) {
g_free(full_path);
return TRUE;
}
free_and_null(entry->name);
free_and_null(entry->generic_name);
free_and_null(entry->icon);
free_and_null(entry->exec);
free_and_null(entry->cwd);
gchar *full_path = g_build_filename(path, file_name, NULL);
if (read_desktop_file_full_path(full_path, entry)) {
g_free(full_path);
return TRUE;
}
free_and_null(entry->name);
free_and_null(entry->generic_name);
free_and_null(entry->icon);
free_and_null(entry->exec);
free_and_null(entry->cwd);
GList *subdirs = NULL;
GList *subdirs = NULL;
GDir *d = g_dir_open(path, 0, NULL);
if (d) {
const gchar *name;
while ((name = g_dir_read_name(d))) {
gchar *child = g_build_filename(path, name, NULL);
if (g_file_test(child, G_FILE_TEST_IS_DIR)) {
subdirs = g_list_append(subdirs, child);
} else {
g_free(child);
}
}
g_dir_close(d);
}
GDir *d = g_dir_open(path, 0, NULL);
if (d) {
const gchar *name;
while ((name = g_dir_read_name(d))) {
gchar *child = g_build_filename(path, name, NULL);
if (g_file_test(child, G_FILE_TEST_IS_DIR)) {
subdirs = g_list_append(subdirs, child);
} else {
g_free(child);
}
}
g_dir_close(d);
}
subdirs = g_list_sort(subdirs, compare_strings);
gboolean found = FALSE;
for (GList *l = subdirs; l; l = g_list_next(l)) {
if (read_desktop_file_from_dir(l->data, file_name, entry)) {
found = TRUE;
break;
}
}
subdirs = g_list_sort(subdirs, compare_strings);
gboolean found = FALSE;
for (GList *l = subdirs; l; l = g_list_next(l)) {
if (read_desktop_file_from_dir(l->data, file_name, entry)) {
found = TRUE;
break;
}
}
for (GList *l = subdirs; l; l = g_list_next(l)) {
g_free(l->data);
}
g_list_free(subdirs);
g_free(full_path);
for (GList *l = subdirs; l; l = g_list_next(l)) {
g_free(l->data);
}
g_list_free(subdirs);
g_free(full_path);
return found;
return found;
}
gboolean read_desktop_file(const char *path, DesktopEntry *entry)
{
entry->path = strdup(path);
entry->name = entry->generic_name = entry->icon = entry->exec = entry->cwd = NULL;
entry->path = strdup(path);
entry->name = entry->generic_name = entry->icon = entry->exec = entry->cwd = NULL;
if (strchr(path, '/'))
return read_desktop_file_full_path(path, entry);
for (const GSList *location = get_apps_locations(); location; location = g_slist_next(location)) {
if (read_desktop_file_from_dir(location->data, path, entry))
return TRUE;
}
return FALSE;
if (strchr(path, '/'))
return read_desktop_file_full_path(path, entry);
for (const GSList *location = get_apps_locations(); location; location = g_slist_next(location)) {
if (read_desktop_file_from_dir(location->data, path, entry))
return TRUE;
}
return FALSE;
}
void free_desktop_entry(DesktopEntry *entry)
{
free_and_null(entry->name);
free_and_null(entry->generic_name);
free_and_null(entry->icon);
free_and_null(entry->exec);
free_and_null(entry->path);
free_and_null(entry->cwd);
free_and_null(entry->name);
free_and_null(entry->generic_name);
free_and_null(entry->icon);
free_and_null(entry->exec);
free_and_null(entry->path);
free_and_null(entry->cwd);
}
void test_read_desktop_file()
{
fprintf(stdout, "\033[1;33m");
DesktopEntry entry;
read_desktop_file("/usr/share/applications/firefox.desktop", &entry);
printf("Name:%s GenericName:%s Icon:%s Exec:%s\n", entry.name, entry.generic_name, entry.icon, entry.exec);
fprintf(stdout, "\033[0m");
fprintf(stdout, "\033[1;33m");
DesktopEntry entry;
read_desktop_file("/usr/share/applications/firefox.desktop", &entry);
printf("Name:%s GenericName:%s Icon:%s Exec:%s\n", entry.name, entry.generic_name, entry.icon, entry.exec);
fprintf(stdout, "\033[0m");
}
GSList *apps_locations = NULL;
// Do not free the result.
const GSList *get_apps_locations()
{
if (apps_locations)
return apps_locations;
if (apps_locations)
return apps_locations;
apps_locations = load_locations_from_env(apps_locations, "XDG_DATA_HOME", "applications", NULL);
apps_locations = load_locations_from_env(apps_locations, "XDG_DATA_HOME", "applications", NULL);
apps_locations =
g_slist_append(apps_locations, g_build_filename(g_get_home_dir(), ".local/share/applications", NULL));
apps_locations =
g_slist_append(apps_locations, g_build_filename(g_get_home_dir(), ".local/share/applications", NULL));
apps_locations = load_locations_from_env(apps_locations, "XDG_DATA_DIRS", "applications", NULL);
apps_locations = load_locations_from_env(apps_locations, "XDG_DATA_DIRS", "applications", NULL);
apps_locations = g_slist_append(apps_locations, g_strdup("/usr/local/share/applications"));
apps_locations = g_slist_append(apps_locations, g_strdup("/usr/share/applications"));
apps_locations = g_slist_append(apps_locations, g_strdup("/opt/share/applications"));
apps_locations = g_slist_append(apps_locations, g_strdup("/usr/local/share/applications"));
apps_locations = g_slist_append(apps_locations, g_strdup("/usr/share/applications"));
apps_locations = g_slist_append(apps_locations, g_strdup("/opt/share/applications"));
apps_locations = slist_remove_duplicates(apps_locations, g_str_equal, g_free);
apps_locations = slist_remove_duplicates(apps_locations, g_str_equal, g_free);
return apps_locations;
return apps_locations;
}

View File

@@ -10,13 +10,13 @@
#include <glib.h>
typedef struct DesktopEntry {
char *name;
char *generic_name;
char *exec;
char *icon;
char *path;
char *cwd;
gboolean hidden_from_menus;
char *name;
char *generic_name;
char *exec;
char *icon;
char *path;
char *cwd;
gboolean hidden_from_menus;
} DesktopEntry;
// Parses a line of the form "key = value". Modifies the line.

File diff suppressed because it is too large Load Diff

View File

@@ -10,27 +10,27 @@
#include "cache.h"
typedef struct IconThemeWrapper {
// The icon theme name for which this wrapper was created
char *icon_theme_name;
// List of IconTheme*
GSList *themes;
// Themes are loaded lazily when needed.
gboolean _themes_loaded;
// List of IconTheme*
GSList *themes_fallback;
// Fallback themes are loaded lazily when needed.
gboolean _fallback_loaded;
Cache _cache;
// List of icon theme names that have been queued for loading.
// Used to avoid loading the same theme twice, and to avoid cycles.
GSList *_queued;
// The icon theme name for which this wrapper was created
char *icon_theme_name;
// List of IconTheme*
GSList *themes;
// Themes are loaded lazily when needed.
gboolean _themes_loaded;
// List of IconTheme*
GSList *themes_fallback;
// Fallback themes are loaded lazily when needed.
gboolean _fallback_loaded;
Cache _cache;
// List of icon theme names that have been queued for loading.
// Used to avoid loading the same theme twice, and to avoid cycles.
GSList *_queued;
} IconThemeWrapper;
typedef struct IconTheme {
char *name;
char *description;
GSList *list_inherits; // each item is a char* (theme name)
GSList *list_directories; // each item is an IconThemeDir*
char *name;
char *description;
GSList *list_inherits; // each item is a char* (theme name)
GSList *list_directories; // each item is an IconThemeDir*
} IconTheme;
// Parses a line of the form "key = value". Modifies the line.

View File

@@ -67,18 +67,18 @@ int launcher_compute_desired_size(void *obj);
void default_launcher()
{
launcher_enabled = 0;
launcher_max_icon_size = 0;
launcher_tooltip_enabled = 0;
launcher_alpha = 100;
launcher_saturation = 0;
launcher_brightness = 0;
icon_theme_name_config = NULL;
icon_theme_name_xsettings = NULL;
launcher_icon_theme_override = 0;
startup_notifications = 0;
launcher_icon_bg = NULL;
launcher_icon_gradients = NULL;
launcher_enabled = 0;
launcher_max_icon_size = 0;
launcher_tooltip_enabled = 0;
launcher_alpha = 100;
launcher_saturation = 0;
launcher_brightness = 0;
icon_theme_name_config = NULL;
icon_theme_name_xsettings = NULL;
launcher_icon_theme_override = 0;
startup_notifications = 0;
launcher_icon_bg = NULL;
launcher_icon_gradients = NULL;
}
void init_launcher()
@@ -87,97 +87,97 @@ void init_launcher()
void init_launcher_panel(void *p)
{
Panel *panel = (Panel *)p;
Launcher *launcher = &panel->launcher;
Panel *panel = (Panel *)p;
Launcher *launcher = &panel->launcher;
launcher->area.parent = p;
launcher->area.panel = p;
snprintf(launcher->area.name, sizeof(launcher->area.name), "Launcher");
launcher->area._draw_foreground = NULL;
launcher->area.size_mode = LAYOUT_FIXED;
launcher->area._resize = resize_launcher;
launcher->area._compute_desired_size = launcher_compute_desired_size;
launcher->area.resize_needed = 1;
schedule_redraw(&launcher->area);
if (!launcher->area.bg)
launcher->area.bg = &g_array_index(backgrounds, Background, 0);
launcher->area.parent = p;
launcher->area.panel = p;
snprintf(launcher->area.name, sizeof(launcher->area.name), "Launcher");
launcher->area._draw_foreground = NULL;
launcher->area.size_mode = LAYOUT_FIXED;
launcher->area._resize = resize_launcher;
launcher->area._compute_desired_size = launcher_compute_desired_size;
launcher->area.resize_needed = 1;
schedule_redraw(&launcher->area);
if (!launcher->area.bg)
launcher->area.bg = &g_array_index(backgrounds, Background, 0);
if (!launcher_icon_bg)
launcher_icon_bg = &g_array_index(backgrounds, Background, 0);
if (!launcher_icon_bg)
launcher_icon_bg = &g_array_index(backgrounds, Background, 0);
// check consistency
if (launcher->list_apps == NULL)
return;
// check consistency
if (launcher->list_apps == NULL)
return;
// This will be recomputed on resize, we just initialize to a non-zero value
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size : 24;
// This will be recomputed on resize, we just initialize to a non-zero value
launcher->icon_size = launcher_max_icon_size > 0 ? launcher_max_icon_size : 24;
launcher->area.on_screen = TRUE;
schedule_panel_redraw();
instantiate_area_gradients(&launcher->area);
launcher->area.on_screen = TRUE;
schedule_panel_redraw();
instantiate_area_gradients(&launcher->area);
load_icon_themes();
launcher_load_icons(launcher);
load_icon_themes();
launcher_load_icons(launcher);
}
void free_icon_themes()
{
free_themes(icon_theme_wrapper);
icon_theme_wrapper = NULL;
free_themes(icon_theme_wrapper);
icon_theme_wrapper = NULL;
}
void cleanup_launcher()
{
for (int i = 0; i < num_panels; i++) {
Panel *panel = &panels[i];
Launcher *launcher = &panel->launcher;
cleanup_launcher_theme(launcher);
}
for (int i = 0; i < num_panels; i++) {
Panel *panel = &panels[i];
Launcher *launcher = &panel->launcher;
cleanup_launcher_theme(launcher);
}
for (GSList *l = panel_config.launcher.list_apps; l; l = l->next) {
free(l->data);
}
g_slist_free(panel_config.launcher.list_apps);
panel_config.launcher.list_apps = NULL;
for (GSList *l = panel_config.launcher.list_apps; l; l = l->next) {
free(l->data);
}
g_slist_free(panel_config.launcher.list_apps);
panel_config.launcher.list_apps = NULL;
free(icon_theme_name_config);
icon_theme_name_config = NULL;
free(icon_theme_name_config);
icon_theme_name_config = NULL;
free(icon_theme_name_xsettings);
icon_theme_name_xsettings = NULL;
free(icon_theme_name_xsettings);
icon_theme_name_xsettings = NULL;
launcher_enabled = FALSE;
launcher_enabled = FALSE;
}
void cleanup_launcher_theme(Launcher *launcher)
{
free_area(&launcher->area);
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon) {
free_icon(launcherIcon->image);
free_icon(launcherIcon->image_hover);
free_icon(launcherIcon->image_pressed);
free(launcherIcon->icon_name);
free(launcherIcon->icon_path);
free(launcherIcon->cmd);
g_free(launcherIcon->icon_tooltip);
free(launcherIcon->config_path);
}
free(launcherIcon);
}
g_slist_free(launcher->list_icons);
launcher->list_icons = NULL;
free_area(&launcher->area);
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon) {
free_icon(launcherIcon->image);
free_icon(launcherIcon->image_hover);
free_icon(launcherIcon->image_pressed);
free(launcherIcon->icon_name);
free(launcherIcon->icon_path);
free(launcherIcon->cmd);
g_free(launcherIcon->icon_tooltip);
free(launcherIcon->config_path);
}
free(launcherIcon);
}
g_slist_free(launcher->list_icons);
launcher->list_icons = NULL;
}
int launcher_compute_icon_size(Launcher *launcher)
{
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
(2 * launcher->area.paddingy);
if (launcher_max_icon_size > 0 && icon_size > launcher_max_icon_size)
icon_size = launcher_max_icon_size;
return icon_size;
int icon_size = panel_horizontal ? launcher->area.height : launcher->area.width;
icon_size = icon_size - MAX(left_right_border_width(&launcher->area), top_bottom_border_width(&launcher->area)) -
(2 * launcher->area.paddingy);
if (launcher_max_icon_size > 0 && icon_size > launcher_max_icon_size)
icon_size = launcher_max_icon_size;
return icon_size;
}
void launcher_compute_geometry(Launcher *launcher,
@@ -187,438 +187,436 @@ void launcher_compute_geometry(Launcher *launcher,
int *icons_per_row,
int *margin)
{
int count = 0;
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon->area.on_screen)
count++;
}
int count = 0;
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon->area.on_screen)
count++;
}
*icon_size = launcher_compute_icon_size(launcher);
*icons_per_column = 1;
*icons_per_row = 1;
*margin = 0;
if (panel_horizontal) {
if (!count) {
*size = 0;
} else {
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
// here icons_per_column always higher than 0
*icons_per_column = (height + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx);
}
} else {
if (!count) {
*size = 0;
} else {
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
// here icons_per_row always higher than 0
*icons_per_row = (width + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx);
}
}
*icon_size = launcher_compute_icon_size(launcher);
*icons_per_column = 1;
*icons_per_row = 1;
*margin = 0;
if (panel_horizontal) {
if (!count) {
*size = 0;
} else {
int height = launcher->area.height - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
// here icons_per_column always higher than 0
*icons_per_column = (height + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
*margin = height - (*icons_per_column - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
*icons_per_row = count / *icons_per_column + (count % *icons_per_column != 0);
*size = left_right_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
(*icon_size * *icons_per_row) + ((*icons_per_row - 1) * launcher->area.paddingx);
}
} else {
if (!count) {
*size = 0;
} else {
int width = launcher->area.width - top_bottom_border_width(&launcher->area) - 2 * launcher->area.paddingy;
// here icons_per_row always higher than 0
*icons_per_row = (width + launcher->area.paddingx) / (*icon_size + launcher->area.paddingx);
*margin = width - (*icons_per_row - 1) * (*icon_size + launcher->area.paddingx) - *icon_size;
*icons_per_column = count / *icons_per_row + (count % *icons_per_row != 0);
*size = top_bottom_border_width(&launcher->area) + 2 * launcher->area.paddingxlr +
(*icon_size * *icons_per_column) + ((*icons_per_column - 1) * launcher->area.paddingx);
}
}
}
int launcher_compute_desired_size(void *obj)
{
Launcher *launcher = (Launcher *)obj;
Launcher *launcher = (Launcher *)obj;
int size, icon_size, icons_per_column, icons_per_row, margin;
launcher_compute_geometry(launcher, &size, &icon_size, &icons_per_column, &icons_per_row, &margin);
return size;
int size, icon_size, icons_per_column, icons_per_row, margin;
launcher_compute_geometry(launcher, &size, &icon_size, &icons_per_column, &icons_per_row, &margin);
return size;
}
gboolean resize_launcher(void *obj)
{
Launcher *launcher = (Launcher *)obj;
Launcher *launcher = (Launcher *)obj;
int size, icons_per_column, icons_per_row, margin;
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
int size, icons_per_column, icons_per_row, margin;
launcher_compute_geometry(launcher, &size, &launcher->icon_size, &icons_per_column, &icons_per_row, &margin);
// Resize icons if necessary
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon->icon_size != launcher->icon_size || !launcherIcon->image) {
launcherIcon->icon_size = launcher->icon_size;
launcherIcon->area.width = launcherIcon->icon_size;
launcherIcon->area.height = launcherIcon->icon_size;
launcher_reload_icon_image(launcher, launcherIcon);
}
}
save_icon_cache(icon_theme_wrapper);
// Resize icons if necessary
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon->icon_size != launcher->icon_size || !launcherIcon->image) {
launcherIcon->icon_size = launcher->icon_size;
launcherIcon->area.width = launcherIcon->icon_size;
launcherIcon->area.height = launcherIcon->icon_size;
launcher_reload_icon_image(launcher, launcherIcon);
}
}
save_icon_cache(icon_theme_wrapper);
int count = 0;
gboolean needs_repositioning = FALSE;
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon->area.on_screen) {
count++;
if (launcherIcon->area.posx < 0 || launcherIcon->area.posy < 0)
needs_repositioning = TRUE;
}
}
int count = 0;
gboolean needs_repositioning = FALSE;
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (launcherIcon->area.on_screen) {
count++;
if (launcherIcon->area.posx < 0 || launcherIcon->area.posy < 0)
needs_repositioning = TRUE;
}
}
if (!needs_repositioning) {
if (panel_horizontal) {
if (launcher->area.width == size)
return FALSE;
launcher->area.width = size;
} else {
if (launcher->area.height == size)
return FALSE;
launcher->area.height = size;
}
}
if (!needs_repositioning) {
if (panel_horizontal) {
if (launcher->area.width == size)
return FALSE;
launcher->area.width = size;
} else {
if (launcher->area.height == size)
return FALSE;
launcher->area.height = size;
}
}
int posx, posy;
int start;
if (panel_horizontal) {
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr;
} else {
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
}
int posx, posy;
int start;
if (panel_horizontal) {
posy = start = top_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
posx = left_border_width(&launcher->area) + launcher->area.paddingxlr;
} else {
posx = start = left_border_width(&launcher->area) + launcher->area.paddingy + margin / 2;
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
}
int i = 0;
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (!launcherIcon->area.on_screen)
continue;
i++;
launcherIcon->y = posy;
launcherIcon->x = posx;
launcher_icon_on_change_layout(launcherIcon);
// printf("launcher %d : %d,%d\n", i, posx, posy);
if (panel_horizontal) {
if (i % icons_per_column) {
posy += launcher->icon_size + launcher->area.paddingx;
} else {
posy = start;
posx += (launcher->icon_size + launcher->area.paddingx);
}
} else {
if (i % icons_per_row) {
posx += launcher->icon_size + launcher->area.paddingx;
} else {
posx = start;
posy += (launcher->icon_size + launcher->area.paddingx);
}
}
}
int i = 0;
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (!launcherIcon->area.on_screen)
continue;
i++;
launcherIcon->y = posy;
launcherIcon->x = posx;
launcher_icon_on_change_layout(launcherIcon);
// printf("launcher %d : %d,%d\n", i, posx, posy);
if (panel_horizontal) {
if (i % icons_per_column) {
posy += launcher->icon_size + launcher->area.paddingx;
} else {
posy = start;
posx += (launcher->icon_size + launcher->area.paddingx);
}
} else {
if (i % icons_per_row) {
posx += launcher->icon_size + launcher->area.paddingx;
} else {
posx = start;
posy += (launcher->icon_size + launcher->area.paddingx);
}
}
}
if ((panel_horizontal && icons_per_column == 1) || (!panel_horizontal && icons_per_row == 1)) {
launcher->area._is_under_mouse = full_width_area_is_under_mouse;
for (GSList *l = launcher->list_icons; l; l = l->next)
((LauncherIcon *)l->data)->area._is_under_mouse = full_width_area_is_under_mouse;
} else {
launcher->area._is_under_mouse = NULL;
for (GSList *l = launcher->list_icons; l; l = l->next)
((LauncherIcon *)l->data)->area._is_under_mouse = NULL;
}
if ((panel_horizontal && icons_per_column == 1) || (!panel_horizontal && icons_per_row == 1)) {
launcher->area._is_under_mouse = full_width_area_is_under_mouse;
for (GSList *l = launcher->list_icons; l; l = l->next)
((LauncherIcon *)l->data)->area._is_under_mouse = full_width_area_is_under_mouse;
} else {
launcher->area._is_under_mouse = NULL;
for (GSList *l = launcher->list_icons; l; l = l->next)
((LauncherIcon *)l->data)->area._is_under_mouse = NULL;
}
return TRUE;
return TRUE;
}
// Here we override the default layout of the icons; normally Area layouts its children
// in a stack; we need to layout them in a kind of table
void launcher_icon_on_change_layout(void *obj)
{
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
launcherIcon->area.posy = ((Area *)launcherIcon->area.parent)->posy + launcherIcon->y;
launcherIcon->area.posx = ((Area *)launcherIcon->area.parent)->posx + launcherIcon->x;
launcherIcon->area.width = launcherIcon->icon_size;
launcherIcon->area.height = launcherIcon->icon_size;
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
launcherIcon->area.posy = ((Area *)launcherIcon->area.parent)->posy + launcherIcon->y;
launcherIcon->area.posx = ((Area *)launcherIcon->area.parent)->posx + launcherIcon->x;
launcherIcon->area.width = launcherIcon->icon_size;
launcherIcon->area.height = launcherIcon->icon_size;
}
int launcher_icon_compute_desired_size(void *obj)
{
LauncherIcon *icon = (LauncherIcon *)obj;
return icon->icon_size;
LauncherIcon *icon = (LauncherIcon *)obj;
return icon->icon_size;
}
char *launcher_icon_get_tooltip_text(void *obj)
{
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
return strdup(launcherIcon->icon_tooltip);
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
return strdup(launcherIcon->icon_tooltip);
}
void draw_launcher_icon(void *obj, cairo_t *c)
{
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
Imlib_Image image;
// Render
if (panel_config.mouse_effects) {
if (launcherIcon->area.mouse_state == MOUSE_OVER)
image = launcherIcon->image_hover ? launcherIcon->image_hover : launcherIcon->image;
else if (launcherIcon->area.mouse_state == MOUSE_DOWN)
image = launcherIcon->image_pressed ? launcherIcon->image_pressed : launcherIcon->image;
else
image = launcherIcon->image;
} else {
image = launcherIcon->image;
}
imlib_context_set_image(image);
render_image(launcherIcon->area.pix, 0, 0);
Imlib_Image image;
// Render
if (panel_config.mouse_effects) {
if (launcherIcon->area.mouse_state == MOUSE_OVER)
image = launcherIcon->image_hover ? launcherIcon->image_hover : launcherIcon->image;
else if (launcherIcon->area.mouse_state == MOUSE_DOWN)
image = launcherIcon->image_pressed ? launcherIcon->image_pressed : launcherIcon->image;
else
image = launcherIcon->image;
} else {
image = launcherIcon->image;
}
imlib_context_set_image(image);
render_image(launcherIcon->area.pix, 0, 0);
}
void launcher_icon_dump_geometry(void *obj, int indent)
{
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
fprintf(stderr, "%*sIcon: w = h = %d, name = %s\n", indent, "", launcherIcon->icon_size, launcherIcon->icon_name);
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
fprintf(stderr, "%*sIcon: w = h = %d, name = %s\n", indent, "", launcherIcon->icon_size, launcherIcon->icon_name);
}
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
{
Imlib_Image icon_scaled;
if (original) {
imlib_context_set_image(original);
icon_scaled = imlib_create_cropped_scaled_image(0,
0,
imlib_image_get_width(),
imlib_image_get_height(),
icon_size,
icon_size);
Imlib_Image icon_scaled;
if (original) {
imlib_context_set_image(original);
icon_scaled = imlib_create_cropped_scaled_image(0,
0,
imlib_image_get_width(),
imlib_image_get_height(),
icon_size,
icon_size);
imlib_context_set_image(icon_scaled);
imlib_image_set_has_alpha(1);
DATA32 *data = imlib_image_get_data();
adjust_asb(data,
icon_size,
icon_size,
launcher_alpha / 100.0,
launcher_saturation / 100.0,
launcher_brightness / 100.0);
imlib_image_put_back_data(data);
imlib_context_set_image(icon_scaled);
imlib_image_set_has_alpha(1);
DATA32 *data = imlib_image_get_data();
adjust_asb(data,
icon_size,
icon_size,
launcher_alpha / 100.0,
launcher_saturation / 100.0,
launcher_brightness / 100.0);
imlib_image_put_back_data(data);
imlib_context_set_image(icon_scaled);
} else {
icon_scaled = imlib_create_image(icon_size, icon_size);
imlib_context_set_image(icon_scaled);
imlib_context_set_color(255, 255, 255, 255);
imlib_image_fill_rectangle(0, 0, icon_size, icon_size);
}
return icon_scaled;
imlib_context_set_image(icon_scaled);
} else {
icon_scaled = imlib_create_image(icon_size, icon_size);
imlib_context_set_image(icon_scaled);
imlib_context_set_color(255, 255, 255, 255);
imlib_image_fill_rectangle(0, 0, icon_size, icon_size);
}
return icon_scaled;
}
void free_icon(Imlib_Image icon)
{
if (icon) {
imlib_context_set_image(icon);
imlib_free_image();
}
if (icon) {
imlib_context_set_image(icon);
imlib_free_image();
}
}
void launcher_action(LauncherIcon *icon, XEvent *evt)
{
launcher_reload_icon((Launcher *)icon->area.parent, icon);
launcher_reload_hidden_icons((Launcher *)icon->area.parent);
char *cmd = calloc(strlen(icon->cmd) + 10, 1);
sprintf(cmd, "(%s&)", icon->cmd);
launcher_reload_icon((Launcher *)icon->area.parent, icon);
launcher_reload_hidden_icons((Launcher *)icon->area.parent);
char *cmd = calloc(strlen(icon->cmd) + 10, 1);
sprintf(cmd, "(%s&)", icon->cmd);
#if HAVE_SN
SnLauncherContext *ctx = 0;
Time time;
if (startup_notifications) {
ctx = sn_launcher_context_new(server.sn_display, server.screen);
sn_launcher_context_set_name(ctx, icon->icon_tooltip);
sn_launcher_context_set_description(ctx, "Application launched from tint2");
sn_launcher_context_set_binary_name(ctx, icon->cmd);
// Get a timestamp from the X event
if (evt->type == ButtonPress || evt->type == ButtonRelease) {
time = evt->xbutton.time;
} else {
fprintf(stderr, "Unknown X event: %d\n", evt->type);
free(cmd);
return;
}
sn_launcher_context_initiate(ctx, "tint2", icon->cmd, time);
}
SnLauncherContext *ctx = 0;
Time time;
if (startup_notifications) {
ctx = sn_launcher_context_new(server.sn_display, server.screen);
sn_launcher_context_set_name(ctx, icon->icon_tooltip);
sn_launcher_context_set_description(ctx, "Application launched from tint2");
sn_launcher_context_set_binary_name(ctx, icon->cmd);
// Get a timestamp from the X event
if (evt->type == ButtonPress || evt->type == ButtonRelease) {
time = evt->xbutton.time;
} else {
fprintf(stderr, "Unknown X event: %d\n", evt->type);
free(cmd);
return;
}
sn_launcher_context_initiate(ctx, "tint2", icon->cmd, time);
}
#endif /* HAVE_SN */
pid_t pid;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Could not fork\n");
} else if (pid == 0) {
pid_t pid;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Could not fork\n");
} else if (pid == 0) {
// Child process
#if HAVE_SN
if (startup_notifications) {
sn_launcher_context_setup_child_process(ctx);
}
if (startup_notifications) {
sn_launcher_context_setup_child_process(ctx);
}
#endif // HAVE_SN
// Allow children to exist after parent destruction
setsid();
// Run the command
if (icon->cwd)
chdir(icon->cwd);
execl("/bin/sh", "/bin/sh", "-c", icon->cmd, NULL);
fprintf(stderr, "Failed to execlp %s\n", icon->cmd);
// Allow children to exist after parent destruction
setsid();
// Run the command
if (icon->cwd)
chdir(icon->cwd);
execl("/bin/sh", "/bin/sh", "-c", icon->cmd, NULL);
fprintf(stderr, "Failed to execlp %s\n", icon->cmd);
#if HAVE_SN
if (startup_notifications) {
sn_launcher_context_unref(ctx);
}
if (startup_notifications) {
sn_launcher_context_unref(ctx);
}
#endif // HAVE_SN
exit(1);
} else {
exit(1);
} else {
// Parent process
#if HAVE_SN
if (startup_notifications) {
g_tree_insert(server.pids, GINT_TO_POINTER(pid), ctx);
}
if (startup_notifications) {
g_tree_insert(server.pids, GINT_TO_POINTER(pid), ctx);
}
#endif // HAVE_SN
}
free(cmd);
}
free(cmd);
}
// Populates the list_icons list from the list_apps list
void launcher_load_icons(Launcher *launcher)
{
// Load apps (.desktop style launcher items)
GSList *app = launcher->list_apps;
int index = 0;
while (app != NULL) {
index++;
LauncherIcon *launcherIcon = (LauncherIcon *)calloc(1, sizeof(LauncherIcon));
launcherIcon->area.panel = launcher->area.panel;
launcherIcon->area._draw_foreground = draw_launcher_icon;
launcherIcon->area.size_mode = LAYOUT_FIXED;
launcherIcon->area._resize = NULL;
launcherIcon->area._compute_desired_size = launcher_icon_compute_desired_size;
sprintf(launcherIcon->area.name, "LauncherIcon %d", index);
launcherIcon->area.resize_needed = 0;
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
launcherIcon->area.bg = launcher_icon_bg;
launcherIcon->area.on_screen = TRUE;
launcherIcon->area.posx = -1;
launcherIcon->area._on_change_layout = launcher_icon_on_change_layout;
launcherIcon->area._dump_geometry = launcher_icon_dump_geometry;
if (launcher_tooltip_enabled) {
launcherIcon->area._get_tooltip_text = launcher_icon_get_tooltip_text;
} else {
launcherIcon->area._get_tooltip_text = NULL;
}
launcherIcon->config_path = strdup(app->data);
add_area(&launcherIcon->area, (Area *)launcher);
launcher->list_icons = g_slist_append(launcher->list_icons, launcherIcon);
launcherIcon->icon_size = launcher->icon_size;
launcher_reload_icon(launcher, launcherIcon);
instantiate_area_gradients(&launcherIcon->area);
app = g_slist_next(app);
}
// Load apps (.desktop style launcher items)
GSList *app = launcher->list_apps;
int index = 0;
while (app != NULL) {
index++;
LauncherIcon *launcherIcon = (LauncherIcon *)calloc(1, sizeof(LauncherIcon));
launcherIcon->area.panel = launcher->area.panel;
launcherIcon->area._draw_foreground = draw_launcher_icon;
launcherIcon->area.size_mode = LAYOUT_FIXED;
launcherIcon->area._resize = NULL;
launcherIcon->area._compute_desired_size = launcher_icon_compute_desired_size;
sprintf(launcherIcon->area.name, "LauncherIcon %d", index);
launcherIcon->area.resize_needed = 0;
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
launcherIcon->area.bg = launcher_icon_bg;
launcherIcon->area.on_screen = TRUE;
launcherIcon->area.posx = -1;
launcherIcon->area._on_change_layout = launcher_icon_on_change_layout;
launcherIcon->area._dump_geometry = launcher_icon_dump_geometry;
if (launcher_tooltip_enabled) {
launcherIcon->area._get_tooltip_text = launcher_icon_get_tooltip_text;
} else {
launcherIcon->area._get_tooltip_text = NULL;
}
launcherIcon->config_path = strdup(app->data);
add_area(&launcherIcon->area, (Area *)launcher);
launcher->list_icons = g_slist_append(launcher->list_icons, launcherIcon);
launcherIcon->icon_size = launcher->icon_size;
launcher_reload_icon(launcher, launcherIcon);
instantiate_area_gradients(&launcherIcon->area);
app = g_slist_next(app);
}
}
void launcher_reload_icon(Launcher *launcher, LauncherIcon *launcherIcon)
{
DesktopEntry entry;
if (read_desktop_file(launcherIcon->config_path, &entry) && entry.exec) {
schedule_redraw(&launcherIcon->area);
if (launcherIcon->cmd)
free(launcherIcon->cmd);
launcherIcon->cmd = strdup(entry.exec);
if (launcherIcon->cwd)
free(launcherIcon->cwd);
if (entry.cwd)
launcherIcon->cwd = strdup(entry.cwd);
else
launcherIcon->cwd = NULL;
if (launcherIcon->icon_name)
free(launcherIcon->icon_name);
launcherIcon->icon_name = entry.icon ? strdup(entry.icon) : strdup(DEFAULT_ICON);
if (entry.name) {
if (entry.generic_name) {
launcherIcon->icon_tooltip = g_strdup_printf("%s (%s)", entry.name, entry.generic_name);
} else {
launcherIcon->icon_tooltip = g_strdup_printf("%s", entry.name);
}
} else {
if (entry.generic_name) {
launcherIcon->icon_tooltip = g_strdup_printf("%s", entry.generic_name);
} else if (entry.exec) {
launcherIcon->icon_tooltip = g_strdup_printf("%s", entry.exec);
}
}
launcher_reload_icon_image(launcher, launcherIcon);
show(&launcherIcon->area);
} else {
hide(&launcherIcon->area);
}
free_desktop_entry(&entry);
DesktopEntry entry;
if (read_desktop_file(launcherIcon->config_path, &entry) && entry.exec) {
schedule_redraw(&launcherIcon->area);
if (launcherIcon->cmd)
free(launcherIcon->cmd);
launcherIcon->cmd = strdup(entry.exec);
if (launcherIcon->cwd)
free(launcherIcon->cwd);
if (entry.cwd)
launcherIcon->cwd = strdup(entry.cwd);
else
launcherIcon->cwd = NULL;
if (launcherIcon->icon_name)
free(launcherIcon->icon_name);
launcherIcon->icon_name = entry.icon ? strdup(entry.icon) : strdup(DEFAULT_ICON);
if (entry.name) {
if (entry.generic_name) {
launcherIcon->icon_tooltip = g_strdup_printf("%s (%s)", entry.name, entry.generic_name);
} else {
launcherIcon->icon_tooltip = g_strdup_printf("%s", entry.name);
}
} else {
if (entry.generic_name) {
launcherIcon->icon_tooltip = g_strdup_printf("%s", entry.generic_name);
} else if (entry.exec) {
launcherIcon->icon_tooltip = g_strdup_printf("%s", entry.exec);
}
}
launcher_reload_icon_image(launcher, launcherIcon);
show(&launcherIcon->area);
} else {
hide(&launcherIcon->area);
}
free_desktop_entry(&entry);
}
void launcher_reload_hidden_icons(Launcher *launcher)
{
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (!launcherIcon->area.on_screen)
launcher_reload_icon(launcher, launcherIcon);
}
for (GSList *l = launcher->list_icons; l; l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (!launcherIcon->area.on_screen)
launcher_reload_icon(launcher, launcherIcon);
}
}
void launcher_reload_icon_image(Launcher *launcher, LauncherIcon *launcherIcon)
{
free_icon(launcherIcon->image);
free_icon(launcherIcon->image_hover);
free_icon(launcherIcon->image_pressed);
launcherIcon->image = NULL;
free_icon(launcherIcon->image);
free_icon(launcherIcon->image_hover);
free_icon(launcherIcon->image_pressed);
launcherIcon->image = NULL;
char *new_icon_path = get_icon_path(icon_theme_wrapper, launcherIcon->icon_name, launcherIcon->icon_size, TRUE);
if (new_icon_path)
launcherIcon->image = load_image(new_icon_path, TRUE);
// On loading error, fallback to default
if (!launcherIcon->image) {
free(new_icon_path);
new_icon_path = get_icon_path(icon_theme_wrapper, DEFAULT_ICON, launcherIcon->icon_size, TRUE);
if (new_icon_path)
launcherIcon->image = load_image(new_icon_path, TRUE);
}
Imlib_Image original = launcherIcon->image;
launcherIcon->image = scale_icon(launcherIcon->image, launcherIcon->icon_size);
free_icon(original);
free(launcherIcon->icon_path);
launcherIcon->icon_path = new_icon_path;
// fprintf(stderr, "launcher.c %d: Using icon %s\n", __LINE__, launcherIcon->icon_path);
char *new_icon_path = get_icon_path(icon_theme_wrapper, launcherIcon->icon_name, launcherIcon->icon_size, TRUE);
if (new_icon_path)
launcherIcon->image = load_image(new_icon_path, TRUE);
// On loading error, fallback to default
if (!launcherIcon->image) {
free(new_icon_path);
new_icon_path = get_icon_path(icon_theme_wrapper, DEFAULT_ICON, launcherIcon->icon_size, TRUE);
if (new_icon_path)
launcherIcon->image = load_image(new_icon_path, TRUE);
}
Imlib_Image original = launcherIcon->image;
launcherIcon->image = scale_icon(launcherIcon->image, launcherIcon->icon_size);
free_icon(original);
free(launcherIcon->icon_path);
launcherIcon->icon_path = new_icon_path;
// fprintf(stderr, "launcher.c %d: Using icon %s\n", __LINE__, launcherIcon->icon_path);
if (panel_config.mouse_effects) {
launcherIcon->image_hover = adjust_icon(launcherIcon->image,
panel_config.mouse_over_alpha,
panel_config.mouse_over_saturation,
panel_config.mouse_over_brightness);
launcherIcon->image_pressed = adjust_icon(launcherIcon->image,
panel_config.mouse_pressed_alpha,
panel_config.mouse_pressed_saturation,
panel_config.mouse_pressed_brightness);
}
schedule_redraw(&launcherIcon->area);
if (panel_config.mouse_effects) {
launcherIcon->image_hover = adjust_icon(launcherIcon->image,
panel_config.mouse_over_alpha,
panel_config.mouse_over_saturation,
panel_config.mouse_over_brightness);
launcherIcon->image_pressed = adjust_icon(launcherIcon->image,
panel_config.mouse_pressed_alpha,
panel_config.mouse_pressed_saturation,
panel_config.mouse_pressed_brightness);
}
schedule_redraw(&launcherIcon->area);
}
void load_icon_themes()
{
if (icon_theme_wrapper)
return;
icon_theme_wrapper =
load_themes(launcher_icon_theme_override
? (icon_theme_name_config ? icon_theme_name_config
: icon_theme_name_xsettings ? icon_theme_name_xsettings : "hicolor")
: (icon_theme_name_xsettings ? icon_theme_name_xsettings
: icon_theme_name_config ? icon_theme_name_config : "hicolor"));
if (icon_theme_wrapper)
return;
icon_theme_wrapper =
load_themes(launcher_icon_theme_override
? (icon_theme_name_config ? icon_theme_name_config
: icon_theme_name_xsettings ? icon_theme_name_xsettings : "hicolor")
: (icon_theme_name_xsettings ? icon_theme_name_xsettings
: icon_theme_name_config ? icon_theme_name_config : "hicolor"));
}
void launcher_default_icon_theme_changed()
{
for (int i = 0; i < num_panels; i++) {
Launcher *launcher = &panels[i].launcher;
cleanup_launcher_theme(launcher);
launcher_load_icons(launcher);
launcher->area.resize_needed = 1;
}
schedule_panel_redraw();
for (int i = 0; i < num_panels; i++) {
Launcher *launcher = &panels[i].launcher;
cleanup_launcher_theme(launcher);
launcher_load_icons(launcher);
launcher->area.resize_needed = 1;
}
schedule_panel_redraw();
}

View File

@@ -17,27 +17,27 @@ void load_icon_themes();
void free_icon_themes();
typedef struct Launcher {
// always start with area
Area area;
GSList *list_apps; // List of char*, each is a path to a app.desktop file
GSList *list_icons; // List of LauncherIcon*
int icon_size;
// always start with area
Area area;
GSList *list_apps; // List of char*, each is a path to a app.desktop file
GSList *list_icons; // List of LauncherIcon*
int icon_size;
} Launcher;
typedef struct LauncherIcon {
// always start with area
Area area;
char *config_path;
Imlib_Image image;
Imlib_Image image_hover;
Imlib_Image image_pressed;
char *cmd;
char *cwd;
char *icon_name;
char *icon_path;
char *icon_tooltip;
int icon_size;
int x, y;
// always start with area
Area area;
char *config_path;
Imlib_Image image;
Imlib_Image image_hover;
Imlib_Image image_pressed;
char *cmd;
char *cwd;
char *icon_name;
char *icon_path;
char *icon_tooltip;
int icon_size;
int x, y;
} LauncherIcon;
extern gboolean launcher_enabled;

View File

@@ -34,78 +34,78 @@
#include "launcher.h"
struct _XSettingsClient {
Display *display;
int screen;
XSettingsNotifyFunc notify;
XSettingsWatchFunc watch;
void *cb_data;
Display *display;
int screen;
XSettingsNotifyFunc notify;
XSettingsWatchFunc watch;
void *cb_data;
Window manager_window;
XSettingsList *settings;
Window manager_window;
XSettingsList *settings;
};
void xsettings_notify_cb(const char *name, XSettingsAction action, XSettingsSetting *setting, void *data)
{
if ((action == XSETTINGS_ACTION_NEW || action == XSETTINGS_ACTION_CHANGED) && name != NULL && setting != NULL) {
if (strcmp(name, "Net/IconThemeName") == 0 && setting->type == XSETTINGS_TYPE_STRING) {
fprintf(stderr, "xsettings: %s = %s\n", name, setting->data.v_string);
if (icon_theme_name_xsettings) {
if (strcmp(icon_theme_name_xsettings, setting->data.v_string) == 0)
return;
free(icon_theme_name_xsettings);
}
icon_theme_name_xsettings = strdup(setting->data.v_string);
default_icon_theme_changed();
} else if (strcmp(name, "Gtk/FontName") == 0 && setting->type == XSETTINGS_TYPE_STRING) {
fprintf(stderr, "xsettings: %s = %s\n", name, setting->data.v_string);
if (default_font) {
if (strcmp(default_font, setting->data.v_string) == 0)
return;
free(default_font);
}
default_font = strdup(setting->data.v_string);
default_font_changed();
}
}
if ((action == XSETTINGS_ACTION_NEW || action == XSETTINGS_ACTION_CHANGED) && name != NULL && setting != NULL) {
if (strcmp(name, "Net/IconThemeName") == 0 && setting->type == XSETTINGS_TYPE_STRING) {
fprintf(stderr, "xsettings: %s = %s\n", name, setting->data.v_string);
if (icon_theme_name_xsettings) {
if (strcmp(icon_theme_name_xsettings, setting->data.v_string) == 0)
return;
free(icon_theme_name_xsettings);
}
icon_theme_name_xsettings = strdup(setting->data.v_string);
default_icon_theme_changed();
} else if (strcmp(name, "Gtk/FontName") == 0 && setting->type == XSETTINGS_TYPE_STRING) {
fprintf(stderr, "xsettings: %s = %s\n", name, setting->data.v_string);
if (default_font) {
if (strcmp(default_font, setting->data.v_string) == 0)
return;
free(default_font);
}
default_font = strdup(setting->data.v_string);
default_font_changed();
}
}
}
static void notify_changes(XSettingsClient *client, XSettingsList *old_list)
{
XSettingsList *old_iter = old_list;
XSettingsList *new_iter = client->settings;
XSettingsList *old_iter = old_list;
XSettingsList *new_iter = client->settings;
if (!client->notify)
return;
if (!client->notify)
return;
while (old_iter || new_iter) {
int cmp;
while (old_iter || new_iter) {
int cmp;
if (old_iter && new_iter)
cmp = strcmp(old_iter->setting->name, new_iter->setting->name);
else if (old_iter)
cmp = -1;
else
cmp = 1;
if (old_iter && new_iter)
cmp = strcmp(old_iter->setting->name, new_iter->setting->name);
else if (old_iter)
cmp = -1;
else
cmp = 1;
if (cmp < 0) {
client->notify(old_iter->setting->name, XSETTINGS_ACTION_DELETED, NULL, client->cb_data);
} else if (cmp == 0) {
if (!xsettings_setting_equal(old_iter->setting, new_iter->setting))
client->notify(old_iter->setting->name, XSETTINGS_ACTION_CHANGED, new_iter->setting, client->cb_data);
} else {
client->notify(new_iter->setting->name, XSETTINGS_ACTION_NEW, new_iter->setting, client->cb_data);
}
if (cmp < 0) {
client->notify(old_iter->setting->name, XSETTINGS_ACTION_DELETED, NULL, client->cb_data);
} else if (cmp == 0) {
if (!xsettings_setting_equal(old_iter->setting, new_iter->setting))
client->notify(old_iter->setting->name, XSETTINGS_ACTION_CHANGED, new_iter->setting, client->cb_data);
} else {
client->notify(new_iter->setting->name, XSETTINGS_ACTION_NEW, new_iter->setting, client->cb_data);
}
if (old_iter)
old_iter = old_iter->next;
if (new_iter)
new_iter = new_iter->next;
}
if (old_iter)
old_iter = old_iter->next;
if (new_iter)
new_iter = new_iter->next;
}
}
static int ignore_errors(Display *display, XErrorEvent *event)
{
return True;
return True;
}
static char local_byte_order = '\0';
@@ -114,364 +114,364 @@ static char local_byte_order = '\0';
static XSettingsResult fetch_card16(XSettingsBuffer *buffer, CARD16 *result)
{
CARD16 x;
CARD16 x;
if (BYTES_LEFT(buffer) < 2)
return XSETTINGS_ACCESS;
if (BYTES_LEFT(buffer) < 2)
return XSETTINGS_ACCESS;
x = *(CARD16 *)buffer->pos;
buffer->pos += 2;
x = *(CARD16 *)buffer->pos;
buffer->pos += 2;
if (buffer->byte_order == local_byte_order)
*result = x;
else
*result = (x << 8) | (x >> 8);
if (buffer->byte_order == local_byte_order)
*result = x;
else
*result = (x << 8) | (x >> 8);
return XSETTINGS_SUCCESS;
return XSETTINGS_SUCCESS;
}
static XSettingsResult fetch_ushort(XSettingsBuffer *buffer, unsigned short *result)
{
CARD16 x;
XSettingsResult r;
CARD16 x;
XSettingsResult r;
r = fetch_card16(buffer, &x);
if (r == XSETTINGS_SUCCESS)
*result = x;
r = fetch_card16(buffer, &x);
if (r == XSETTINGS_SUCCESS)
*result = x;
return r;
return r;
}
static XSettingsResult fetch_card32(XSettingsBuffer *buffer, CARD32 *result)
{
CARD32 x;
CARD32 x;
if (BYTES_LEFT(buffer) < 4)
return XSETTINGS_ACCESS;
if (BYTES_LEFT(buffer) < 4)
return XSETTINGS_ACCESS;
x = *(CARD32 *)buffer->pos;
buffer->pos += 4;
x = *(CARD32 *)buffer->pos;
buffer->pos += 4;
if (buffer->byte_order == local_byte_order)
*result = x;
else
*result = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
if (buffer->byte_order == local_byte_order)
*result = x;
else
*result = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
return XSETTINGS_SUCCESS;
return XSETTINGS_SUCCESS;
}
static XSettingsResult fetch_card8(XSettingsBuffer *buffer, CARD8 *result)
{
if (BYTES_LEFT(buffer) < 1)
return XSETTINGS_ACCESS;
if (BYTES_LEFT(buffer) < 1)
return XSETTINGS_ACCESS;
*result = *(CARD8 *)buffer->pos;
buffer->pos += 1;
*result = *(CARD8 *)buffer->pos;
buffer->pos += 1;
return XSETTINGS_SUCCESS;
return XSETTINGS_SUCCESS;
}
#define XSETTINGS_PAD(n, m) ((n + m - 1) & (~(m - 1)))
static XSettingsList *parse_settings(unsigned char *data, size_t len)
{
XSettingsBuffer buffer;
XSettingsResult result = XSETTINGS_SUCCESS;
XSettingsList *settings = NULL;
CARD32 serial;
CARD32 n_entries;
CARD32 i;
XSettingsSetting *setting = NULL;
XSettingsBuffer buffer;
XSettingsResult result = XSETTINGS_SUCCESS;
XSettingsList *settings = NULL;
CARD32 serial;
CARD32 n_entries;
CARD32 i;
XSettingsSetting *setting = NULL;
local_byte_order = xsettings_byte_order();
local_byte_order = xsettings_byte_order();
buffer.byte_order = local_byte_order;
buffer.pos = buffer.data = data;
buffer.len = len;
buffer.byte_order = local_byte_order;
buffer.pos = buffer.data = data;
buffer.len = len;
result = fetch_card8(&buffer, (CARD8 *)&buffer.byte_order);
if (buffer.byte_order != MSBFirst && buffer.byte_order != LSBFirst) {
fprintf(stderr, "Invalid byte order %x in XSETTINGS property\n", buffer.byte_order);
result = XSETTINGS_FAILED;
goto out;
}
result = fetch_card8(&buffer, (CARD8 *)&buffer.byte_order);
if (buffer.byte_order != MSBFirst && buffer.byte_order != LSBFirst) {
fprintf(stderr, "Invalid byte order %x in XSETTINGS property\n", buffer.byte_order);
result = XSETTINGS_FAILED;
goto out;
}
buffer.pos += 3;
buffer.pos += 3;
result = fetch_card32(&buffer, &serial);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_card32(&buffer, &serial);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_card32(&buffer, &n_entries);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_card32(&buffer, &n_entries);
if (result != XSETTINGS_SUCCESS)
goto out;
for (i = 0; i < n_entries; i++) {
CARD8 type;
CARD16 name_len;
CARD32 v_int;
size_t pad_len;
for (i = 0; i < n_entries; i++) {
CARD8 type;
CARD16 name_len;
CARD32 v_int;
size_t pad_len;
result = fetch_card8(&buffer, &type);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_card8(&buffer, &type);
if (result != XSETTINGS_SUCCESS)
goto out;
buffer.pos += 1;
buffer.pos += 1;
result = fetch_card16(&buffer, &name_len);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_card16(&buffer, &name_len);
if (result != XSETTINGS_SUCCESS)
goto out;
pad_len = XSETTINGS_PAD(name_len, 4);
if (BYTES_LEFT(&buffer) < pad_len) {
result = XSETTINGS_ACCESS;
goto out;
}
pad_len = XSETTINGS_PAD(name_len, 4);
if (BYTES_LEFT(&buffer) < pad_len) {
result = XSETTINGS_ACCESS;
goto out;
}
setting = calloc(1, sizeof *setting);
if (!setting) {
result = XSETTINGS_NO_MEM;
goto out;
}
setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */
setting = calloc(1, sizeof *setting);
if (!setting) {
result = XSETTINGS_NO_MEM;
goto out;
}
setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */
setting->name = calloc(name_len + 1, 1);
if (!setting->name) {
result = XSETTINGS_NO_MEM;
goto out;
}
setting->name = calloc(name_len + 1, 1);
if (!setting->name) {
result = XSETTINGS_NO_MEM;
goto out;
}
memcpy(setting->name, buffer.pos, name_len);
setting->name[name_len] = '\0';
buffer.pos += pad_len;
memcpy(setting->name, buffer.pos, name_len);
setting->name[name_len] = '\0';
buffer.pos += pad_len;
result = fetch_card32(&buffer, &v_int);
if (result != XSETTINGS_SUCCESS)
goto out;
setting->last_change_serial = v_int;
result = fetch_card32(&buffer, &v_int);
if (result != XSETTINGS_SUCCESS)
goto out;
setting->last_change_serial = v_int;
switch (type) {
case XSETTINGS_TYPE_INT:
result = fetch_card32(&buffer, &v_int);
if (result != XSETTINGS_SUCCESS)
goto out;
setting->data.v_int = (INT32)v_int;
break;
case XSETTINGS_TYPE_STRING:
result = fetch_card32(&buffer, &v_int);
if (result != XSETTINGS_SUCCESS)
goto out;
switch (type) {
case XSETTINGS_TYPE_INT:
result = fetch_card32(&buffer, &v_int);
if (result != XSETTINGS_SUCCESS)
goto out;
setting->data.v_int = (INT32)v_int;
break;
case XSETTINGS_TYPE_STRING:
result = fetch_card32(&buffer, &v_int);
if (result != XSETTINGS_SUCCESS)
goto out;
pad_len = XSETTINGS_PAD(v_int, 4);
if (v_int + 1 == 0 || /* Guard against wrap-around */
BYTES_LEFT(&buffer) < pad_len) {
result = XSETTINGS_ACCESS;
goto out;
}
pad_len = XSETTINGS_PAD(v_int, 4);
if (v_int + 1 == 0 || /* Guard against wrap-around */
BYTES_LEFT(&buffer) < pad_len) {
result = XSETTINGS_ACCESS;
goto out;
}
setting->data.v_string = calloc(v_int + 1, 1);
if (!setting->data.v_string) {
result = XSETTINGS_NO_MEM;
goto out;
}
setting->data.v_string = calloc(v_int + 1, 1);
if (!setting->data.v_string) {
result = XSETTINGS_NO_MEM;
goto out;
}
memcpy(setting->data.v_string, buffer.pos, v_int);
setting->data.v_string[v_int] = '\0';
buffer.pos += pad_len;
break;
case XSETTINGS_TYPE_COLOR:
result = fetch_ushort(&buffer, &setting->data.v_color.red);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_ushort(&buffer, &setting->data.v_color.green);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_ushort(&buffer, &setting->data.v_color.blue);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_ushort(&buffer, &setting->data.v_color.alpha);
if (result != XSETTINGS_SUCCESS)
goto out;
break;
default:
/* Quietly ignore unknown types */
break;
}
memcpy(setting->data.v_string, buffer.pos, v_int);
setting->data.v_string[v_int] = '\0';
buffer.pos += pad_len;
break;
case XSETTINGS_TYPE_COLOR:
result = fetch_ushort(&buffer, &setting->data.v_color.red);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_ushort(&buffer, &setting->data.v_color.green);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_ushort(&buffer, &setting->data.v_color.blue);
if (result != XSETTINGS_SUCCESS)
goto out;
result = fetch_ushort(&buffer, &setting->data.v_color.alpha);
if (result != XSETTINGS_SUCCESS)
goto out;
break;
default:
/* Quietly ignore unknown types */
break;
}
setting->type = type;
setting->type = type;
result = xsettings_list_insert(&settings, setting);
if (result != XSETTINGS_SUCCESS)
goto out;
result = xsettings_list_insert(&settings, setting);
if (result != XSETTINGS_SUCCESS)
goto out;
setting = NULL;
}
setting = NULL;
}
out:
if (result != XSETTINGS_SUCCESS) {
switch (result) {
case XSETTINGS_NO_MEM:
fprintf(stderr, "Out of memory reading XSETTINGS property\n");
break;
case XSETTINGS_ACCESS:
fprintf(stderr, "Invalid XSETTINGS property (read off end)\n");
break;
case XSETTINGS_DUPLICATE_ENTRY:
fprintf(stderr, "Duplicate XSETTINGS entry for '%s'\n", setting->name);
case XSETTINGS_FAILED:
case XSETTINGS_SUCCESS:
case XSETTINGS_NO_ENTRY:
break;
}
if (result != XSETTINGS_SUCCESS) {
switch (result) {
case XSETTINGS_NO_MEM:
fprintf(stderr, "Out of memory reading XSETTINGS property\n");
break;
case XSETTINGS_ACCESS:
fprintf(stderr, "Invalid XSETTINGS property (read off end)\n");
break;
case XSETTINGS_DUPLICATE_ENTRY:
fprintf(stderr, "Duplicate XSETTINGS entry for '%s'\n", setting->name);
case XSETTINGS_FAILED:
case XSETTINGS_SUCCESS:
case XSETTINGS_NO_ENTRY:
break;
}
if (setting)
xsettings_setting_free(setting);
if (setting)
xsettings_setting_free(setting);
xsettings_list_free(settings);
settings = NULL;
}
xsettings_list_free(settings);
settings = NULL;
}
return settings;
return settings;
}
static void read_settings(XSettingsClient *client)
{
Atom type;
int format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *data;
Atom type;
int format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *data;
int (*old_handler)(Display *, XErrorEvent *);
int (*old_handler)(Display *, XErrorEvent *);
XSettingsList *old_list = client->settings;
client->settings = NULL;
XSettingsList *old_list = client->settings;
client->settings = NULL;
old_handler = XSetErrorHandler(ignore_errors);
int result = XGetWindowProperty(client->display,
client->manager_window,
server.atom._XSETTINGS_SETTINGS,
0,
LONG_MAX,
False,
server.atom._XSETTINGS_SETTINGS,
&type,
&format,
&n_items,
&bytes_after,
&data);
XSetErrorHandler(old_handler);
old_handler = XSetErrorHandler(ignore_errors);
int result = XGetWindowProperty(client->display,
client->manager_window,
server.atom._XSETTINGS_SETTINGS,
0,
LONG_MAX,
False,
server.atom._XSETTINGS_SETTINGS,
&type,
&format,
&n_items,
&bytes_after,
&data);
XSetErrorHandler(old_handler);
if (result == Success && type == server.atom._XSETTINGS_SETTINGS) {
if (format != 8) {
fprintf(stderr, "Invalid format for XSETTINGS property %d", format);
} else
client->settings = parse_settings(data, n_items);
XFree(data);
}
if (result == Success && type == server.atom._XSETTINGS_SETTINGS) {
if (format != 8) {
fprintf(stderr, "Invalid format for XSETTINGS property %d", format);
} else
client->settings = parse_settings(data, n_items);
XFree(data);
}
notify_changes(client, old_list);
xsettings_list_free(old_list);
notify_changes(client, old_list);
xsettings_list_free(old_list);
}
static void check_manager_window(XSettingsClient *client)
{
if (client->manager_window && client->watch)
client->watch(client->manager_window, False, 0, client->cb_data);
if (client->manager_window && client->watch)
client->watch(client->manager_window, False, 0, client->cb_data);
XGrabServer(client->display);
XGrabServer(client->display);
client->manager_window = XGetSelectionOwner(server.display, server.atom._XSETTINGS_SCREEN);
if (client->manager_window)
XSelectInput(server.display, client->manager_window, PropertyChangeMask | StructureNotifyMask);
client->manager_window = XGetSelectionOwner(server.display, server.atom._XSETTINGS_SCREEN);
if (client->manager_window)
XSelectInput(server.display, client->manager_window, PropertyChangeMask | StructureNotifyMask);
XUngrabServer(client->display);
XFlush(client->display);
XUngrabServer(client->display);
XFlush(client->display);
if (client->manager_window && client->watch)
client->watch(client->manager_window, True, PropertyChangeMask | StructureNotifyMask, client->cb_data);
if (client->manager_window && client->watch)
client->watch(client->manager_window, True, PropertyChangeMask | StructureNotifyMask, client->cb_data);
read_settings(client);
read_settings(client);
}
XSettingsClient *xsettings_client_new(Display *display,
int screen,
XSettingsNotifyFunc notify,
XSettingsWatchFunc watch,
void *cb_data)
int screen,
XSettingsNotifyFunc notify,
XSettingsWatchFunc watch,
void *cb_data)
{
XSettingsClient *client = calloc(1, sizeof *client);
if (!client)
return NULL;
XSettingsClient *client = calloc(1, sizeof *client);
if (!client)
return NULL;
client->display = display;
client->screen = screen;
client->notify = notify;
client->watch = watch;
client->cb_data = cb_data;
client->display = display;
client->screen = screen;
client->notify = notify;
client->watch = watch;
client->cb_data = cb_data;
client->manager_window = None;
client->settings = NULL;
client->manager_window = None;
client->settings = NULL;
if (client->watch)
client->watch(RootWindow(display, screen), True, StructureNotifyMask, client->cb_data);
if (client->watch)
client->watch(RootWindow(display, screen), True, StructureNotifyMask, client->cb_data);
check_manager_window(client);
check_manager_window(client);
if (client->manager_window == None) {
printf("No XSETTINGS manager, tint2 uses config option 'launcher_icon_theme'.\n");
free(client);
return NULL;
} else {
return client;
}
if (client->manager_window == None) {
printf("No XSETTINGS manager, tint2 uses config option 'launcher_icon_theme'.\n");
free(client);
return NULL;
} else {
return client;
}
}
void xsettings_client_destroy(XSettingsClient *client)
{
if (!client)
return;
if (client->watch)
client->watch(RootWindow(client->display, client->screen), False, 0, client->cb_data);
if (client->manager_window && client->watch)
client->watch(client->manager_window, False, 0, client->cb_data);
if (!client)
return;
if (client->watch)
client->watch(RootWindow(client->display, client->screen), False, 0, client->cb_data);
if (client->manager_window && client->watch)
client->watch(client->manager_window, False, 0, client->cb_data);
xsettings_list_free(client->settings);
free(client);
xsettings_list_free(client->settings);
free(client);
}
XSettingsResult xsettings_client_get_setting(XSettingsClient *client, const char *name, XSettingsSetting **setting)
{
XSettingsSetting *search = xsettings_list_lookup(client->settings, name);
if (search) {
*setting = xsettings_setting_copy(search);
return *setting ? XSETTINGS_SUCCESS : XSETTINGS_NO_MEM;
} else
return XSETTINGS_NO_ENTRY;
XSettingsSetting *search = xsettings_list_lookup(client->settings, name);
if (search) {
*setting = xsettings_setting_copy(search);
return *setting ? XSETTINGS_SUCCESS : XSETTINGS_NO_MEM;
} else
return XSETTINGS_NO_ENTRY;
}
Bool xsettings_client_process_event(XSettingsClient *client, XEvent *xev)
{
/* The checks here will not unlikely cause us to reread
* the properties from the manager window a number of
* times when the manager changes from A->B. But manager changes
* are going to be pretty rare.
*/
if (xev->xany.window == RootWindow(server.display, server.screen)) {
if (xev->xany.type == ClientMessage && xev->xclient.message_type == server.atom.MANAGER) {
check_manager_window(client);
return True;
}
} else if (xev->xany.window == client->manager_window) {
if (xev->xany.type == DestroyNotify) {
check_manager_window(client);
return True;
} else if (xev->xany.type == PropertyNotify) {
read_settings(client);
return True;
}
}
/* The checks here will not unlikely cause us to reread
* the properties from the manager window a number of
* times when the manager changes from A->B. But manager changes
* are going to be pretty rare.
*/
if (xev->xany.window == RootWindow(server.display, server.screen)) {
if (xev->xany.type == ClientMessage && xev->xclient.message_type == server.atom.MANAGER) {
check_manager_window(client);
return True;
}
} else if (xev->xany.window == client->manager_window) {
if (xev->xany.type == DestroyNotify) {
check_manager_window(client);
return True;
} else if (xev->xany.type == PropertyNotify) {
read_settings(client);
return True;
}
}
return False;
return False;
}

View File

@@ -38,10 +38,10 @@ typedef void (*XSettingsNotifyFunc)(const char *name, XSettingsAction action, XS
typedef void (*XSettingsWatchFunc)(Window window, Bool is_start, long mask, void *cb_data);
XSettingsClient *xsettings_client_new(Display *display,
int screen,
XSettingsNotifyFunc notify,
XSettingsWatchFunc watch,
void *cb_data);
int screen,
XSettingsNotifyFunc notify,
XSettingsWatchFunc watch,
void *cb_data);
void xsettings_client_destroy(XSettingsClient *client);
Bool xsettings_client_process_event(XSettingsClient *client, XEvent *xev);

View File

@@ -30,216 +30,216 @@
XSettingsSetting *xsettings_setting_copy(XSettingsSetting *setting)
{
XSettingsSetting *result;
size_t str_len;
XSettingsSetting *result;
size_t str_len;
result = calloc(1, sizeof *result);
if (!result)
return NULL;
result = calloc(1, sizeof *result);
if (!result)
return NULL;
str_len = strlen(setting->name);
result->name = calloc(str_len + 1, 1);
if (!result->name)
goto err;
str_len = strlen(setting->name);
result->name = calloc(str_len + 1, 1);
if (!result->name)
goto err;
memcpy(result->name, setting->name, str_len + 1);
memcpy(result->name, setting->name, str_len + 1);
result->type = setting->type;
result->type = setting->type;
switch (setting->type) {
case XSETTINGS_TYPE_INT:
result->data.v_int = setting->data.v_int;
break;
case XSETTINGS_TYPE_COLOR:
result->data.v_color = setting->data.v_color;
break;
case XSETTINGS_TYPE_STRING:
str_len = strlen(setting->data.v_string);
result->data.v_string = calloc(str_len + 1, 1);
if (!result->data.v_string)
goto err;
switch (setting->type) {
case XSETTINGS_TYPE_INT:
result->data.v_int = setting->data.v_int;
break;
case XSETTINGS_TYPE_COLOR:
result->data.v_color = setting->data.v_color;
break;
case XSETTINGS_TYPE_STRING:
str_len = strlen(setting->data.v_string);
result->data.v_string = calloc(str_len + 1, 1);
if (!result->data.v_string)
goto err;
memcpy(result->data.v_string, setting->data.v_string, str_len + 1);
break;
default:
break;
}
memcpy(result->data.v_string, setting->data.v_string, str_len + 1);
break;
default:
break;
}
result->last_change_serial = setting->last_change_serial;
result->last_change_serial = setting->last_change_serial;
return result;
return result;
err:
if (result->name)
free(result->name);
free(result);
if (result->name)
free(result->name);
free(result);
return NULL;
return NULL;
}
XSettingsList *xsettings_list_copy(XSettingsList *list)
{
XSettingsList *new = NULL;
XSettingsList *old_iter = list;
XSettingsList *new_iter = NULL;
XSettingsList *new = NULL;
XSettingsList *old_iter = list;
XSettingsList *new_iter = NULL;
while (old_iter) {
XSettingsList *new_node;
while (old_iter) {
XSettingsList *new_node;
new_node = calloc(1, sizeof *new_node);
if (!new_node)
goto error;
new_node = calloc(1, sizeof *new_node);
if (!new_node)
goto error;
new_node->setting = xsettings_setting_copy(old_iter->setting);
if (!new_node->setting) {
free(new_node);
goto error;
}
new_node->setting = xsettings_setting_copy(old_iter->setting);
if (!new_node->setting) {
free(new_node);
goto error;
}
if (new_iter)
new_iter->next = new_node;
else
new = new_node;
if (new_iter)
new_iter->next = new_node;
else
new = new_node;
new_iter = new_node;
new_iter = new_node;
old_iter = old_iter->next;
}
old_iter = old_iter->next;
}
return new;
return new;
error:
xsettings_list_free(new);
return NULL;
xsettings_list_free(new);
return NULL;
}
int xsettings_setting_equal(XSettingsSetting *setting_a, XSettingsSetting *setting_b)
{
if (setting_a->type != setting_b->type)
return 0;
if (setting_a->type != setting_b->type)
return 0;
if (strcmp(setting_a->name, setting_b->name) != 0)
return 0;
if (strcmp(setting_a->name, setting_b->name) != 0)
return 0;
switch (setting_a->type) {
case XSETTINGS_TYPE_INT:
return setting_a->data.v_int == setting_b->data.v_int;
case XSETTINGS_TYPE_COLOR:
return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
setting_a->data.v_color.green == setting_b->data.v_color.green &&
setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
case XSETTINGS_TYPE_STRING:
return strcmp(setting_a->data.v_string, setting_b->data.v_string) == 0;
default:
break;
}
switch (setting_a->type) {
case XSETTINGS_TYPE_INT:
return setting_a->data.v_int == setting_b->data.v_int;
case XSETTINGS_TYPE_COLOR:
return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
setting_a->data.v_color.green == setting_b->data.v_color.green &&
setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
case XSETTINGS_TYPE_STRING:
return strcmp(setting_a->data.v_string, setting_b->data.v_string) == 0;
default:
break;
}
return 0;
return 0;
}
void xsettings_setting_free(XSettingsSetting *setting)
{
if (setting->type == XSETTINGS_TYPE_STRING)
free(setting->data.v_string);
if (setting->type == XSETTINGS_TYPE_STRING)
free(setting->data.v_string);
if (setting->name)
free(setting->name);
if (setting->name)
free(setting->name);
free(setting);
free(setting);
}
void xsettings_list_free(XSettingsList *list)
{
while (list) {
XSettingsList *next = list->next;
while (list) {
XSettingsList *next = list->next;
xsettings_setting_free(list->setting);
free(list);
xsettings_setting_free(list->setting);
free(list);
list = next;
}
list = next;
}
}
XSettingsResult xsettings_list_insert(XSettingsList **list, XSettingsSetting *setting)
{
XSettingsList *node;
XSettingsList *iter;
XSettingsList *last = NULL;
XSettingsList *node;
XSettingsList *iter;
XSettingsList *last = NULL;
node = calloc(1, sizeof *node);
if (!node)
return XSETTINGS_NO_MEM;
node->setting = setting;
node = calloc(1, sizeof *node);
if (!node)
return XSETTINGS_NO_MEM;
node->setting = setting;
iter = *list;
while (iter) {
int cmp = strcmp(setting->name, iter->setting->name);
iter = *list;
while (iter) {
int cmp = strcmp(setting->name, iter->setting->name);
if (cmp < 0)
break;
else if (cmp == 0) {
free(node);
return XSETTINGS_DUPLICATE_ENTRY;
}
if (cmp < 0)
break;
else if (cmp == 0) {
free(node);
return XSETTINGS_DUPLICATE_ENTRY;
}
last = iter;
iter = iter->next;
}
last = iter;
iter = iter->next;
}
if (last)
last->next = node;
else
*list = node;
if (last)
last->next = node;
else
*list = node;
node->next = iter;
node->next = iter;
return XSETTINGS_SUCCESS;
return XSETTINGS_SUCCESS;
}
XSettingsResult xsettings_list_delete(XSettingsList **list, const char *name)
{
XSettingsList *iter;
XSettingsList *last = NULL;
XSettingsList *iter;
XSettingsList *last = NULL;
iter = *list;
while (iter) {
if (strcmp(name, iter->setting->name) == 0) {
if (last)
last->next = iter->next;
else
*list = iter->next;
iter = *list;
while (iter) {
if (strcmp(name, iter->setting->name) == 0) {
if (last)
last->next = iter->next;
else
*list = iter->next;
xsettings_setting_free(iter->setting);
free(iter);
xsettings_setting_free(iter->setting);
free(iter);
return XSETTINGS_SUCCESS;
}
return XSETTINGS_SUCCESS;
}
last = iter;
iter = iter->next;
}
last = iter;
iter = iter->next;
}
return XSETTINGS_FAILED;
return XSETTINGS_FAILED;
}
XSettingsSetting *xsettings_list_lookup(XSettingsList *list, const char *name)
{
XSettingsList *iter;
XSettingsList *iter;
iter = list;
while (iter) {
if (strcmp(name, iter->setting->name) == 0)
return iter->setting;
iter = list;
while (iter) {
if (strcmp(name, iter->setting->name) == 0)
return iter->setting;
iter = iter->next;
}
iter = iter->next;
}
return NULL;
return NULL;
}
char xsettings_byte_order(void)
{
CARD32 myint = 0x01020304;
return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
CARD32 myint = 0x01020304;
return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
}

View File

@@ -36,48 +36,48 @@ typedef struct _XSettingsSetting XSettingsSetting;
* protocol values.
*/
typedef enum {
XSETTINGS_TYPE_INT = 0,
XSETTINGS_TYPE_STRING = 1,
XSETTINGS_TYPE_COLOR = 2,
XSETTINGS_TYPE_NONE = 0xff
XSETTINGS_TYPE_INT = 0,
XSETTINGS_TYPE_STRING = 1,
XSETTINGS_TYPE_COLOR = 2,
XSETTINGS_TYPE_NONE = 0xff
} XSettingsType;
typedef enum {
XSETTINGS_SUCCESS,
XSETTINGS_NO_MEM,
XSETTINGS_ACCESS,
XSETTINGS_FAILED,
XSETTINGS_NO_ENTRY,
XSETTINGS_DUPLICATE_ENTRY
XSETTINGS_SUCCESS,
XSETTINGS_NO_MEM,
XSETTINGS_ACCESS,
XSETTINGS_FAILED,
XSETTINGS_NO_ENTRY,
XSETTINGS_DUPLICATE_ENTRY
} XSettingsResult;
struct _XSettingsBuffer {
char byte_order;
size_t len;
unsigned char *data;
unsigned char *pos;
char byte_order;
size_t len;
unsigned char *data;
unsigned char *pos;
};
struct _XSettingsColor {
unsigned short red, green, blue, alpha;
unsigned short red, green, blue, alpha;
};
struct _XSettingsList {
XSettingsSetting *setting;
XSettingsList *next;
XSettingsSetting *setting;
XSettingsList *next;
};
struct _XSettingsSetting {
char *name;
XSettingsType type;
char *name;
XSettingsType type;
union {
int v_int;
char *v_string;
XSettingsColor v_color;
} data;
union {
int v_int;
char *v_string;
XSettingsColor v_color;
} data;
unsigned long last_change_serial;
unsigned long last_change_serial;
};
XSettingsSetting *xsettings_setting_copy(XSettingsSetting *setting);