Compare commits
12 Commits
0.12.12
...
BenoitAver
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
187e7f294e | ||
|
|
8976f35c5f | ||
|
|
008eebe4b1 | ||
|
|
cbb76849ea | ||
|
|
cf930fa42e | ||
|
|
da51d37322 | ||
|
|
a09e1a0e45 | ||
|
|
1d4f64d745 | ||
|
|
2857b96c4d | ||
|
|
8b08930268 | ||
|
|
2922708c18 | ||
|
|
5c6385b4c3 |
@@ -1,3 +1,7 @@
|
||||
2016-08-07 master
|
||||
- Enhancements:
|
||||
- Desktop files (shortcuts) used in launcher are reloaded on click, in case the file has changed
|
||||
|
||||
2016-08-02 0.12.12
|
||||
- Fixes:
|
||||
- Set task maximum height equal to width if not specified, instead of hardcoding 30 (issue #583; thanks @VastOne)
|
||||
|
||||
@@ -32,12 +32,11 @@ Execp *create_execp()
|
||||
Execp *execp = calloc(1, sizeof(Execp));
|
||||
execp->backend = calloc(1, sizeof(ExecpBackend));
|
||||
execp->backend->child_pipe = -1;
|
||||
|
||||
execp->backend->cmd_pids = g_tree_new(cmp_ptr);
|
||||
execp->backend->interval = 30;
|
||||
execp->backend->cache_icon = TRUE;
|
||||
execp->backend->centered = TRUE;
|
||||
execp->backend->font_color.alpha = 0.5;
|
||||
|
||||
return execp;
|
||||
}
|
||||
|
||||
@@ -59,6 +58,9 @@ void destroy_execp(void *obj)
|
||||
// This is a frontend element
|
||||
execp->backend->instances = g_list_remove_all(execp->backend->instances, execp);
|
||||
free_and_null(execp->frontend);
|
||||
remove_area(&execp->area);
|
||||
free_area(&execp->area);
|
||||
free_and_null(execp);
|
||||
} else {
|
||||
// This is a backend element
|
||||
stop_timeout(execp->backend->timer);
|
||||
@@ -80,6 +82,10 @@ void destroy_execp(void *obj)
|
||||
close(execp->backend->child_pipe);
|
||||
execp->backend->child_pipe = -1;
|
||||
}
|
||||
if (execp->backend->cmd_pids) {
|
||||
g_tree_destroy(execp->backend->cmd_pids);
|
||||
execp->backend->cmd_pids = NULL;
|
||||
}
|
||||
|
||||
execp->backend->bg = NULL;
|
||||
pango_font_description_free(execp->backend->font_desc);
|
||||
@@ -464,6 +470,18 @@ void execp_dump_geometry(void *obj, int indent)
|
||||
execp->backend->text);
|
||||
}
|
||||
|
||||
void execp_force_update(Execp *execp)
|
||||
{
|
||||
if (execp->backend->child_pipe > 0) {
|
||||
// Command currently running, nothing to do
|
||||
} else {
|
||||
if (execp->backend->timer)
|
||||
stop_timeout(execp->backend->timer);
|
||||
// Run command right away
|
||||
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
||||
}
|
||||
}
|
||||
|
||||
void execp_action(void *obj, int button, int x, int y)
|
||||
{
|
||||
Execp *execp = obj;
|
||||
@@ -495,20 +513,32 @@ void execp_action(void *obj, int button, int x, int y)
|
||||
execp->area.width,
|
||||
execp->area.height,
|
||||
command);
|
||||
tint_exec(full_cmd);
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "Could not fork\n");
|
||||
} else if (pid == 0) {
|
||||
// Child process
|
||||
// Allow children to exist after parent destruction
|
||||
setsid();
|
||||
// Run the command
|
||||
execl("/bin/sh", "/bin/sh", "-c", full_cmd, NULL);
|
||||
fprintf(stderr, "Failed to execlp %s\n", full_cmd);
|
||||
exit(1);
|
||||
}
|
||||
// Parent process
|
||||
g_tree_insert(execp->backend->cmd_pids, GINT_TO_POINTER(pid), GINT_TO_POINTER(1));
|
||||
g_free(full_cmd);
|
||||
} else {
|
||||
if (execp->backend->child_pipe > 0) {
|
||||
// Command currently running, nothing to do
|
||||
} else {
|
||||
if (execp->backend->timer)
|
||||
stop_timeout(execp->backend->timer);
|
||||
// Run command right away
|
||||
execp->backend->timer = add_timeout(10, 0, execp_timer_callback, execp, &execp->backend->timer);
|
||||
}
|
||||
execp_force_update(execp);
|
||||
}
|
||||
}
|
||||
|
||||
void execp_cmd_completed(Execp *execp, pid_t pid)
|
||||
{
|
||||
g_tree_remove(execp->backend->cmd_pids, GINT_TO_POINTER(pid));
|
||||
execp_force_update(execp);
|
||||
}
|
||||
|
||||
void execp_timer_callback(void *arg)
|
||||
{
|
||||
Execp *execp = arg;
|
||||
|
||||
@@ -70,6 +70,7 @@ typedef struct ExecpBackend {
|
||||
|
||||
// List of Execp which are frontends for this backend, one for each panel
|
||||
GList *instances;
|
||||
GTree *cmd_pids;
|
||||
} ExecpBackend;
|
||||
|
||||
typedef struct ExecpFrontend {
|
||||
@@ -130,6 +131,8 @@ gboolean resize_execp(void *obj);
|
||||
// Called on mouse click event.
|
||||
void execp_action(void *obj, int button, int x, int y);
|
||||
|
||||
void execp_cmd_completed(Execp *obj, pid_t pid);
|
||||
|
||||
// Called to check if new output from the command can be read.
|
||||
// No command might be running.
|
||||
// Returns 1 if the output has been updated and a redraw is needed.
|
||||
|
||||
@@ -305,6 +305,7 @@ void free_themes(IconThemeWrapper *wrapper)
|
||||
{
|
||||
if (!wrapper)
|
||||
return;
|
||||
free(wrapper->icon_theme_name);
|
||||
for (GSList *l = wrapper->themes; l; l = l->next) {
|
||||
IconTheme *theme = (IconTheme *)l->data;
|
||||
free_icon_theme(theme);
|
||||
|
||||
@@ -57,6 +57,10 @@ Background *launcher_icon_bg;
|
||||
Imlib_Image scale_icon(Imlib_Image original, int icon_size);
|
||||
void free_icon(Imlib_Image icon);
|
||||
void launcher_icon_dump_geometry(void *obj, int indent);
|
||||
void launcher_reload_icon(Launcher *launcher, LauncherIcon *launcherIcon);
|
||||
void launcher_reload_icon_image(Launcher *launcher, LauncherIcon *launcherIcon);
|
||||
void launcher_reload_hidden_icons(Launcher *launcher);
|
||||
void launcher_icon_on_change_layout(void *obj);
|
||||
|
||||
void default_launcher()
|
||||
{
|
||||
@@ -143,6 +147,7 @@ void cleanup_launcher_theme(Launcher *launcher)
|
||||
free(launcherIcon->icon_path);
|
||||
free(launcherIcon->cmd);
|
||||
g_free(launcherIcon->icon_tooltip);
|
||||
free(launcherIcon->config_path);
|
||||
}
|
||||
free(launcherIcon);
|
||||
}
|
||||
@@ -176,61 +181,17 @@ gboolean resize_launcher(void *obj)
|
||||
launcherIcon->icon_size = icon_size;
|
||||
launcherIcon->area.width = launcherIcon->icon_size;
|
||||
launcherIcon->area.height = launcherIcon->icon_size;
|
||||
|
||||
// Get the path for an icon file with the new size
|
||||
char *new_icon_path =
|
||||
get_icon_path(launcher->icon_theme_wrapper, launcherIcon->icon_name, launcherIcon->icon_size);
|
||||
if (!new_icon_path) {
|
||||
// Draw a blank icon
|
||||
free_icon(launcherIcon->image);
|
||||
free_icon(launcherIcon->image_hover);
|
||||
free_icon(launcherIcon->image_pressed);
|
||||
launcherIcon->image = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Free the old files
|
||||
free_icon(launcherIcon->image);
|
||||
free_icon(launcherIcon->image_hover);
|
||||
free_icon(launcherIcon->image_pressed);
|
||||
// Load the new file
|
||||
launcherIcon->image = load_image(new_icon_path, 1);
|
||||
// On loading error, fallback to default
|
||||
if (!launcherIcon->image) {
|
||||
free(new_icon_path);
|
||||
new_icon_path = get_icon_path(launcher->icon_theme_wrapper, DEFAULT_ICON, launcherIcon->icon_size);
|
||||
if (new_icon_path)
|
||||
launcherIcon->image = imlib_load_image_immediately(new_icon_path);
|
||||
}
|
||||
|
||||
if (!launcherIcon->image) {
|
||||
// Loading default icon failed, draw a blank icon
|
||||
free(new_icon_path);
|
||||
} else {
|
||||
// Loaded icon successfully, rescale it
|
||||
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);
|
||||
launcher_reload_icon_image(launcher, launcherIcon);
|
||||
}
|
||||
}
|
||||
save_icon_cache(launcher->icon_theme_wrapper);
|
||||
|
||||
int count = g_slist_length(launcher->list_icons);
|
||||
int count = 0;
|
||||
for (GSList *l = launcher->list_icons; l; l = l->next) {
|
||||
LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
|
||||
if (launcherIcon->area.on_screen)
|
||||
count++;
|
||||
}
|
||||
|
||||
if (panel_horizontal) {
|
||||
if (!count) {
|
||||
@@ -268,17 +229,15 @@ gboolean resize_launcher(void *obj)
|
||||
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
|
||||
}
|
||||
|
||||
int i;
|
||||
GSList *l;
|
||||
for (i = 1, l = launcher->list_icons; l; i++, l = l->next) {
|
||||
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;
|
||||
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;
|
||||
launcher_icon_on_change_layout(launcherIcon);
|
||||
// printf("launcher %d : %d,%d\n", i, posx, posy);
|
||||
if (panel_horizontal) {
|
||||
if (i % icons_per_column) {
|
||||
@@ -401,6 +360,8 @@ void free_icon(Imlib_Image icon)
|
||||
|
||||
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);
|
||||
#if HAVE_SN
|
||||
@@ -461,56 +422,109 @@ void launcher_load_icons(Launcher *launcher)
|
||||
// Load apps (.desktop style launcher items)
|
||||
GSList *app = launcher->list_apps;
|
||||
while (app != NULL) {
|
||||
DesktopEntry entry;
|
||||
read_desktop_file(app->data, &entry);
|
||||
if (entry.exec) {
|
||||
LauncherIcon *launcherIcon = calloc(1, sizeof(LauncherIcon));
|
||||
launcherIcon->area.panel = launcher->area.panel;
|
||||
snprintf(launcherIcon->area.name,
|
||||
sizeof(launcherIcon->area.name),
|
||||
"LauncherIcon %s",
|
||||
entry.name ? entry.name : "null");
|
||||
launcherIcon->area._draw_foreground = draw_launcher_icon;
|
||||
launcherIcon->area.size_mode = LAYOUT_FIXED;
|
||||
launcherIcon->area._resize = NULL;
|
||||
launcherIcon->area.resize_needed = 0;
|
||||
schedule_redraw(&launcherIcon->area);
|
||||
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._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->is_app_desktop = 1;
|
||||
launcherIcon->cmd = strdup(entry.exec);
|
||||
launcherIcon->icon_name = entry.icon ? strdup(entry.icon) : strdup(DEFAULT_ICON);
|
||||
launcherIcon->icon_size = 1;
|
||||
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->list_icons = g_slist_append(launcher->list_icons, launcherIcon);
|
||||
add_area(&launcherIcon->area, (Area *)launcher);
|
||||
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.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._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;
|
||||
}
|
||||
free_desktop_entry(&entry);
|
||||
launcherIcon->config_path = strdup(app->data);
|
||||
add_area(&launcherIcon->area, (Area *)launcher);
|
||||
launcher->list_icons = g_slist_append(launcher->list_icons, launcherIcon);
|
||||
launcher_reload_icon(launcher, launcherIcon);
|
||||
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->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);
|
||||
if (!launcherIcon->area.on_screen)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
char *new_icon_path = get_icon_path(launcher->icon_theme_wrapper, launcherIcon->icon_name, launcherIcon->icon_size);
|
||||
if (new_icon_path)
|
||||
launcherIcon->image = load_image(new_icon_path, 1);
|
||||
// On loading error, fallback to default
|
||||
if (!launcherIcon->image) {
|
||||
free(new_icon_path);
|
||||
new_icon_path = get_icon_path(launcher->icon_theme_wrapper, DEFAULT_ICON, launcherIcon->icon_size);
|
||||
if (new_icon_path)
|
||||
launcherIcon->image = imlib_load_image_immediately(new_icon_path);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Populates the icon_theme_wrapper list
|
||||
void launcher_load_themes(Launcher *launcher)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef struct Launcher {
|
||||
typedef struct LauncherIcon {
|
||||
// always start with area
|
||||
Area area;
|
||||
char *config_path;
|
||||
Imlib_Image image;
|
||||
Imlib_Image image_hover;
|
||||
Imlib_Image image_pressed;
|
||||
@@ -31,7 +32,6 @@ typedef struct LauncherIcon {
|
||||
char *icon_path;
|
||||
char *icon_tooltip;
|
||||
int icon_size;
|
||||
int is_app_desktop;
|
||||
int x, y;
|
||||
} LauncherIcon;
|
||||
|
||||
|
||||
13
src/panel.c
13
src/panel.c
@@ -269,12 +269,11 @@ void init_panel()
|
||||
|
||||
if (panel_autohide)
|
||||
autohide_trigger_hide(p);
|
||||
|
||||
update_taskbar_visibility(p);
|
||||
}
|
||||
|
||||
taskbar_refresh_tasklist();
|
||||
reset_active_task();
|
||||
update_all_taskbars_visibility();
|
||||
}
|
||||
|
||||
void init_panel_size_and_position(Panel *panel)
|
||||
@@ -395,7 +394,11 @@ gboolean resize_panel(void *obj)
|
||||
int total_size = 0;
|
||||
int total_name_size = 0;
|
||||
int total_items = 0;
|
||||
int visible_taskbars = 0;
|
||||
for (int i = 0; i < panel->num_desktops; i++) {
|
||||
if (!panel->taskbar[i].area.on_screen)
|
||||
continue;
|
||||
visible_taskbars++;
|
||||
if (panel_horizontal) {
|
||||
total_size += panel->taskbar[i].area.width;
|
||||
} else {
|
||||
@@ -427,14 +430,16 @@ gboolean resize_panel(void *obj)
|
||||
if (total_items) {
|
||||
int actual_name_size;
|
||||
if (total_name_size <= total_size) {
|
||||
actual_name_size = total_name_size / panel->num_desktops;
|
||||
actual_name_size = total_name_size / visible_taskbars;
|
||||
} else {
|
||||
actual_name_size = total_size / panel->num_desktops;
|
||||
actual_name_size = total_size / visible_taskbars;
|
||||
}
|
||||
total_size -= total_name_size;
|
||||
|
||||
for (int i = 0; i < panel->num_desktops; i++) {
|
||||
Taskbar *taskbar = &panel->taskbar[i];
|
||||
if (!taskbar->area.on_screen)
|
||||
continue;
|
||||
|
||||
int requested_size = (panel_horizontal ? left_right_border_width(&taskbar->area)
|
||||
: top_bottom_border_width(&taskbar->area)) +
|
||||
|
||||
@@ -140,6 +140,11 @@ void cleanup_server()
|
||||
XFreeGC(server.display, server.gc);
|
||||
server.gc = NULL;
|
||||
server.disable_transparency = FALSE;
|
||||
#ifdef HAVE_SN
|
||||
if (server.pids)
|
||||
g_tree_destroy(server.pids);
|
||||
server.pids = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void send_event32(Window win, Atom at, long data1, long data2, long data3)
|
||||
|
||||
@@ -268,21 +268,26 @@ void task_update_icon(Task *task)
|
||||
|
||||
Imlib_Image img = NULL;
|
||||
|
||||
int i;
|
||||
gulong *data = server_get_property(task->win, server.atom._NET_WM_ICON, XA_CARDINAL, &i);
|
||||
if (data) {
|
||||
// get ARGB icon
|
||||
int w, h;
|
||||
gulong *tmp_data;
|
||||
if (!img) {
|
||||
int i;
|
||||
gulong *data = server_get_property(task->win, server.atom._NET_WM_ICON, XA_CARDINAL, &i);
|
||||
if (data) {
|
||||
// get ARGB icon
|
||||
int w, h;
|
||||
gulong *tmp_data;
|
||||
|
||||
tmp_data = get_best_icon(data, get_icon_count(data, i), i, &w, &h, panel->g_task.icon_size1);
|
||||
DATA32 icon_data[w * h];
|
||||
for (int j = 0; j < w * h; ++j)
|
||||
icon_data[j] = tmp_data[j];
|
||||
img = imlib_create_image_using_copied_data(w, h, icon_data);
|
||||
XFree(data);
|
||||
} else {
|
||||
// get Pixmap icon
|
||||
tmp_data = get_best_icon(data, get_icon_count(data, i), i, &w, &h, panel->g_task.icon_size1);
|
||||
DATA32 icon_data[w * h];
|
||||
for (int j = 0; j < w * h; ++j)
|
||||
icon_data[j] = tmp_data[j];
|
||||
img = imlib_create_image_using_copied_data(w, h, icon_data);
|
||||
if (img)
|
||||
fprintf(stderr, "%s: Got %dx%d icon via _NET_WM_ICON for %s\n", __FUNCTION__, w, h, task->title ? task->title : "task");
|
||||
XFree(data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!img) {
|
||||
XWMHints *hints = XGetWMHints(server.display, task->win);
|
||||
if (hints) {
|
||||
if (hints->flags & IconPixmapHint && hints->icon_pixmap != 0) {
|
||||
@@ -292,17 +297,20 @@ void task_update_icon(Task *task)
|
||||
uint border_width, bpp;
|
||||
uint w, h;
|
||||
|
||||
// printf(" get pixmap\n");
|
||||
XGetGeometry(server.display, hints->icon_pixmap, &root, &icon_x, &icon_y, &w, &h, &border_width, &bpp);
|
||||
imlib_context_set_drawable(hints->icon_pixmap);
|
||||
img = imlib_create_image_from_drawable(hints->icon_mask, 0, 0, w, h, 0);
|
||||
if (img)
|
||||
fprintf(stderr, "%s: Got %dx%d pixmap icon via WM_HINTS for %s\n", __FUNCTION__, w, h, task->title ? task->title : "task");
|
||||
}
|
||||
XFree(hints);
|
||||
}
|
||||
}
|
||||
|
||||
if (img == NULL) {
|
||||
imlib_context_set_image(default_icon);
|
||||
img = imlib_clone_image();
|
||||
fprintf(stderr, "%s: Using default icon for %s\n", __FUNCTION__, task->title ? task->title : "task");
|
||||
}
|
||||
|
||||
// transform icons
|
||||
@@ -348,7 +356,7 @@ void task_update_icon(Task *task)
|
||||
|
||||
GPtrArray *task_buttons = get_task_buttons(task->win);
|
||||
if (task_buttons) {
|
||||
for (i = 0; i < task_buttons->len; ++i) {
|
||||
for (int i = 0; i < task_buttons->len; ++i) {
|
||||
Task *task2 = g_ptr_array_index(task_buttons, i);
|
||||
task2->icon_width = task->icon_width;
|
||||
task2->icon_height = task->icon_height;
|
||||
|
||||
@@ -169,7 +169,7 @@ void init_taskbar_panel(void *p)
|
||||
if (panel_horizontal) {
|
||||
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy;
|
||||
panel->g_taskbar.area.height =
|
||||
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
||||
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
||||
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
||||
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
||||
} else {
|
||||
@@ -430,18 +430,51 @@ gboolean resize_taskbar(void *obj)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean taskbar_is_empty(Taskbar *taskbar)
|
||||
{
|
||||
GList *l = taskbar->area.children;
|
||||
if (taskbarname_enabled)
|
||||
l = l->next;
|
||||
for (; l != NULL; l = l->next) {
|
||||
if (((Task *)l->data)->area.on_screen) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void update_one_taskbar_visibility(Taskbar *taskbar)
|
||||
{
|
||||
if (taskbar->desktop == server.desktop) {
|
||||
// Taskbar for current desktop is always shown
|
||||
show(&taskbar->area);
|
||||
} else if (taskbar_mode == MULTI_DESKTOP && taskbar_is_empty(taskbar)) {
|
||||
// MULTI_DESKTOP : show non-empty taskbars
|
||||
show(&taskbar->area);
|
||||
} else {
|
||||
hide(&taskbar->area);
|
||||
}
|
||||
}
|
||||
|
||||
void update_all_taskbars_visibility()
|
||||
{
|
||||
for (int i = 0; i < num_panels; i++) {
|
||||
Panel *panel = &panels[i];
|
||||
for (int j = 0; j < panel->num_desktops; j++) {
|
||||
update_one_taskbar_visibility(&panel->taskbar[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_taskbar_state(Taskbar *taskbar, TaskbarState state)
|
||||
{
|
||||
taskbar->area.bg = panels[0].g_taskbar.background[state];
|
||||
if (taskbarname_enabled) {
|
||||
taskbar->bar_name.area.bg = panels[0].g_taskbar.background_name[state];
|
||||
}
|
||||
if (taskbar_mode != MULTI_DESKTOP) {
|
||||
if (state == TASKBAR_NORMAL)
|
||||
taskbar->area.on_screen = FALSE;
|
||||
else
|
||||
taskbar->area.on_screen = TRUE;
|
||||
}
|
||||
|
||||
update_one_taskbar_visibility(taskbar);
|
||||
|
||||
if (taskbar->area.on_screen) {
|
||||
schedule_redraw(&taskbar->area);
|
||||
if (taskbarname_enabled) {
|
||||
@@ -459,22 +492,6 @@ void set_taskbar_state(Taskbar *taskbar, TaskbarState state)
|
||||
panel_refresh = TRUE;
|
||||
}
|
||||
|
||||
void update_taskbar_visibility(void *p)
|
||||
{
|
||||
Panel *panel = (Panel *)p;
|
||||
|
||||
for (int j = 0; j < panel->num_desktops; j++) {
|
||||
Taskbar *taskbar = &panel->taskbar[j];
|
||||
if (taskbar_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) {
|
||||
// SINGLE_DESKTOP and not current desktop
|
||||
taskbar->area.on_screen = FALSE;
|
||||
} else {
|
||||
taskbar->area.on_screen = TRUE;
|
||||
}
|
||||
}
|
||||
panel_refresh = TRUE;
|
||||
}
|
||||
|
||||
#define NONTRIVIAL 2
|
||||
gint compare_tasks_trivial(Task *a, Task *b, Taskbar *taskbar)
|
||||
{
|
||||
|
||||
@@ -79,10 +79,11 @@ Task *get_task(Window win);
|
||||
// However for windows shown on all desktops, there are multiple buttons, one for each taskbar.
|
||||
GPtrArray *get_task_buttons(Window win);
|
||||
|
||||
// Change state of a taskbar (ACTIVE or NORMAL)
|
||||
void set_taskbar_state(Taskbar *taskbar, TaskbarState state);
|
||||
|
||||
// Updates the visibility of each taskbar when the current desktop changes.
|
||||
void update_taskbar_visibility(void *p);
|
||||
// Updates the visibility of all taskbars
|
||||
void update_all_taskbars_visibility();
|
||||
|
||||
// Sorts the taskbar(s) on which the window is present.
|
||||
void sort_taskbar_for_win(Window win);
|
||||
|
||||
98
src/tint.c
98
src/tint.c
@@ -18,6 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -36,10 +37,10 @@
|
||||
#include <pwd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifdef HAVE_SN
|
||||
#include <libsn/sn.h>
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <version.h>
|
||||
@@ -376,8 +377,8 @@ void init(int argc, char *argv[])
|
||||
debug_geometry = getenv("DEBUG_GEOMETRY") != NULL;
|
||||
}
|
||||
|
||||
static int sn_pipe_valid = 0;
|
||||
static int sn_pipe[2];
|
||||
static int sigchild_pipe_valid = FALSE;
|
||||
static int sigchild_pipe[2];
|
||||
|
||||
#ifdef HAVE_SN
|
||||
static int error_trap_depth = 0;
|
||||
@@ -397,50 +398,41 @@ static void error_trap_pop(SnDisplay *display, Display *xdisplay)
|
||||
XSync(xdisplay, False); /* get all errors out of the queue */
|
||||
--error_trap_depth;
|
||||
}
|
||||
#endif // HAVE_SN
|
||||
|
||||
static void sigchld_handler(int sig)
|
||||
{
|
||||
if (!startup_notifications)
|
||||
if (!sigchild_pipe_valid)
|
||||
return;
|
||||
if (!sn_pipe_valid)
|
||||
return;
|
||||
ssize_t wur = write(sn_pipe[1], "x", 1);
|
||||
(void)wur;
|
||||
fsync(sn_pipe[1]);
|
||||
int savedErrno = errno;
|
||||
ssize_t unused = write(sigchild_pipe[1], "x", 1);
|
||||
(void)unused;
|
||||
fsync(sigchild_pipe[1]);
|
||||
errno = savedErrno;
|
||||
}
|
||||
|
||||
static void sigchld_handler_async()
|
||||
{
|
||||
if (!startup_notifications)
|
||||
return;
|
||||
// Wait for all dead processes
|
||||
pid_t pid;
|
||||
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
|
||||
SnLauncherContext *ctx;
|
||||
ctx = (SnLauncherContext *)g_tree_lookup(server.pids, GINT_TO_POINTER(pid));
|
||||
int status;
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) {
|
||||
#ifdef HAVE_SN
|
||||
SnLauncherContext *ctx = (SnLauncherContext *)g_tree_lookup(server.pids, GINT_TO_POINTER(pid));
|
||||
if (ctx) {
|
||||
g_tree_remove(server.pids, GINT_TO_POINTER(pid));
|
||||
sn_launcher_context_complete(ctx);
|
||||
sn_launcher_context_unref(ctx);
|
||||
}
|
||||
#endif
|
||||
for (GList *l = panel_config.execp_list; l; l = l->next) {
|
||||
Execp *execp = (Execp *)l->data;
|
||||
if (g_tree_lookup(execp->backend->cmd_pids, GINT_TO_POINTER(pid)))
|
||||
execp_cmd_completed(execp, pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gint cmp_ptr(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
if (a < b)
|
||||
return -1;
|
||||
else if (a == b)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
static void sigchld_handler_async()
|
||||
{
|
||||
}
|
||||
#endif // HAVE_SN
|
||||
|
||||
void init_X11_pre_config()
|
||||
{
|
||||
server.display = XOpenDisplay(NULL);
|
||||
@@ -475,25 +467,32 @@ void init_X11_post_config()
|
||||
{
|
||||
server_init_visual();
|
||||
|
||||
gboolean need_sigchld = FALSE;
|
||||
#ifdef HAVE_SN
|
||||
// Initialize startup-notification
|
||||
if (startup_notifications) {
|
||||
server.sn_display = sn_display_new(server.display, error_trap_push, error_trap_pop);
|
||||
server.pids = g_tree_new(cmp_ptr);
|
||||
need_sigchld = TRUE;
|
||||
}
|
||||
#endif // HAVE_SN
|
||||
if (panel_config.execp_list)
|
||||
need_sigchld = TRUE;
|
||||
|
||||
if (need_sigchld) {
|
||||
// Setup a handler for child termination
|
||||
if (pipe(sn_pipe) != 0) {
|
||||
if (pipe(sigchild_pipe) != 0) {
|
||||
fprintf(stderr, "Creating pipe failed.\n");
|
||||
} else {
|
||||
fcntl(sn_pipe[0], F_SETFL, O_NONBLOCK | fcntl(sn_pipe[0], F_GETFL));
|
||||
fcntl(sn_pipe[1], F_SETFL, O_NONBLOCK | fcntl(sn_pipe[1], F_GETFL));
|
||||
sn_pipe_valid = 1;
|
||||
struct sigaction act = {.sa_handler = sigchld_handler, .sa_flags = SA_NOCLDWAIT | SA_RESTART};
|
||||
fcntl(sigchild_pipe[0], F_SETFL, O_NONBLOCK | fcntl(sigchild_pipe[0], F_GETFL));
|
||||
fcntl(sigchild_pipe[1], F_SETFL, O_NONBLOCK | fcntl(sigchild_pipe[1], F_GETFL));
|
||||
sigchild_pipe_valid = 1;
|
||||
struct sigaction act = {.sa_handler = sigchld_handler, .sa_flags = SA_RESTART};
|
||||
if (sigaction(SIGCHLD, &act, 0)) {
|
||||
perror("sigaction");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_SN
|
||||
|
||||
imlib_context_set_display(server.display);
|
||||
imlib_context_set_visual(server.visual);
|
||||
@@ -543,15 +542,11 @@ void cleanup()
|
||||
XCloseDisplay(server.display);
|
||||
server.display = NULL;
|
||||
|
||||
#ifdef HAVE_SN
|
||||
if (startup_notifications) {
|
||||
if (sn_pipe_valid) {
|
||||
sn_pipe_valid = 0;
|
||||
close(sn_pipe[1]);
|
||||
close(sn_pipe[0]);
|
||||
}
|
||||
if (sigchild_pipe_valid) {
|
||||
sigchild_pipe_valid = FALSE;
|
||||
close(sigchild_pipe[1]);
|
||||
close(sigchild_pipe[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
uevent_cleanup();
|
||||
}
|
||||
@@ -1015,7 +1010,7 @@ void event_property_notify(XEvent *e)
|
||||
int old_desktop = server.desktop;
|
||||
server_get_number_of_desktops();
|
||||
server.desktop = get_current_desktop();
|
||||
if (old_num_desktops != server.num_desktops) {
|
||||
if (old_num_desktops != server.num_desktops) { // If number of desktop changed
|
||||
if (server.num_desktops <= server.desktop) {
|
||||
server.desktop = server.num_desktops - 1;
|
||||
}
|
||||
@@ -1024,11 +1019,11 @@ void event_property_notify(XEvent *e)
|
||||
for (int i = 0; i < num_panels; i++) {
|
||||
init_taskbar_panel(&panels[i]);
|
||||
set_panel_items_order(&panels[i]);
|
||||
update_taskbar_visibility(&panels[i]);
|
||||
panels[i].area.resize_needed = 1;
|
||||
}
|
||||
taskbar_refresh_tasklist();
|
||||
reset_active_task();
|
||||
update_all_taskbars_visibility();
|
||||
panel_refresh = TRUE;
|
||||
} else if (old_desktop != server.desktop) {
|
||||
for (int i = 0; i < num_panels; i++) {
|
||||
@@ -1097,6 +1092,7 @@ void event_property_notify(XEvent *e)
|
||||
if (debug)
|
||||
fprintf(stderr, "%s %d: win = root, atom = _NET_CLIENT_LIST\n", __FUNCTION__, __LINE__);
|
||||
taskbar_refresh_tasklist();
|
||||
update_all_taskbars_visibility();
|
||||
panel_refresh = TRUE;
|
||||
}
|
||||
// Change active
|
||||
@@ -1208,6 +1204,8 @@ void event_property_notify(XEvent *e)
|
||||
add_urgent(task);
|
||||
}
|
||||
XFree(wmhints);
|
||||
task_update_icon(task);
|
||||
panel_refresh = TRUE;
|
||||
}
|
||||
|
||||
if (!server.got_root_win)
|
||||
@@ -1641,9 +1639,9 @@ start:
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(x11_fd, &fdset);
|
||||
int maxfd = x11_fd;
|
||||
if (sn_pipe_valid) {
|
||||
FD_SET(sn_pipe[0], &fdset);
|
||||
maxfd = maxfd < sn_pipe[0] ? sn_pipe[0] : maxfd;
|
||||
if (sigchild_pipe_valid) {
|
||||
FD_SET(sigchild_pipe[0], &fdset);
|
||||
maxfd = maxfd < sigchild_pipe[0] ? sigchild_pipe[0] : maxfd;
|
||||
}
|
||||
for (GList *l = panel_config.execp_list; l; l = l->next) {
|
||||
Execp *execp = (Execp *)l->data;
|
||||
@@ -1664,9 +1662,9 @@ start:
|
||||
if (XPending(server.display) > 0 || select(maxfd + 1, &fdset, 0, 0, select_timeout) >= 0) {
|
||||
uevent_handler();
|
||||
|
||||
if (sn_pipe_valid) {
|
||||
if (sigchild_pipe_valid) {
|
||||
char buffer[1];
|
||||
while (read(sn_pipe[0], buffer, sizeof(buffer)) > 0) {
|
||||
while (read(sigchild_pipe[0], buffer, sizeof(buffer)) > 0) {
|
||||
sigchld_handler_async();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1133,12 +1133,6 @@ msgstr "Prebaci"
|
||||
msgid "Iconify"
|
||||
msgstr "Umanji"
|
||||
|
||||
#: ../properties.c:3434 ../properties.c:3470 ../properties.c:3542
|
||||
#: ../properties.c:3578
|
||||
#, fuzzy
|
||||
msgid "Shade"
|
||||
msgstr "Zatamni"
|
||||
|
||||
#: ../properties.c:3435 ../properties.c:3471 ../properties.c:3507
|
||||
#: ../properties.c:3543 ../properties.c:3579
|
||||
msgid "Toggle or iconify"
|
||||
@@ -1233,9 +1227,8 @@ msgid "Middle click"
|
||||
msgstr "Srednji klik"
|
||||
|
||||
#: ../properties.c:3506
|
||||
#, fuzzy
|
||||
msgid "sShade"
|
||||
msgstr "zZatamni"
|
||||
msgid "Shade"
|
||||
msgstr "Zatamni"
|
||||
|
||||
#: ../properties.c:3514
|
||||
msgid "Specifies the action performed when task buttons receive a middle "
|
||||
|
||||
@@ -1257,10 +1257,6 @@ msgstr "Spécifie l'action à engager lorsque les boutons de tâches reçoivent
|
||||
msgid "Middle click"
|
||||
msgstr "Clic milieu"
|
||||
|
||||
#: ../properties.c:3506
|
||||
msgid "sShade"
|
||||
msgstr "Réduire"
|
||||
|
||||
#: ../properties.c:3514
|
||||
msgid "Specifies the action performed when task buttons receive a middle "
|
||||
"click event: \n"
|
||||
|
||||
@@ -1232,11 +1232,6 @@ msgstr "Određuje akciju nakon pomijeranja kolutića miša gore na zadatku: \n"
|
||||
msgid "Middle click"
|
||||
msgstr "Srednji klik"
|
||||
|
||||
#: ../properties.c:3506
|
||||
#, fuzzy
|
||||
msgid "sShade"
|
||||
msgstr "zZatamni"
|
||||
|
||||
#: ../properties.c:3514
|
||||
msgid "Specifies the action performed when task buttons receive a middle "
|
||||
"click event: \n"
|
||||
|
||||
@@ -1248,10 +1248,6 @@ msgstr "Określa akcję, która zostanie wykonana po poruszeniu kółka myszy w
|
||||
msgid "Middle click"
|
||||
msgstr "Klik środkowym"
|
||||
|
||||
#: ../properties.c:3506
|
||||
msgid "sShade"
|
||||
msgstr "Zwiń"
|
||||
|
||||
#: ../properties.c:3514
|
||||
msgid "Specifies the action performed when task buttons receive a middle "
|
||||
"click event: \n"
|
||||
|
||||
@@ -1220,10 +1220,6 @@ msgstr "Задает действие, выполняемое когда кно
|
||||
msgid "Middle click"
|
||||
msgstr "Средний щелчок"
|
||||
|
||||
#: ../properties.c:3506
|
||||
msgid "sShade"
|
||||
msgstr "Скрутить"
|
||||
|
||||
#: ../properties.c:3514
|
||||
msgid "Specifies the action performed when task buttons receive a middle "
|
||||
"click event: \n"
|
||||
|
||||
@@ -1133,7 +1133,6 @@ msgstr "Умањи"
|
||||
|
||||
#: ../properties.c:3434 ../properties.c:3470 ../properties.c:3542
|
||||
#: ../properties.c:3578
|
||||
#, fuzzy
|
||||
msgid "Shade"
|
||||
msgstr "Затамни"
|
||||
|
||||
@@ -1230,11 +1229,6 @@ msgstr "Одређује акцију након померања колути
|
||||
msgid "Middle click"
|
||||
msgstr "Средњи клик"
|
||||
|
||||
#: ../properties.c:3506
|
||||
#, fuzzy
|
||||
msgid "sShade"
|
||||
msgstr "зЗатамни"
|
||||
|
||||
#: ../properties.c:3514
|
||||
msgid "Specifies the action performed when task buttons receive a middle "
|
||||
"click event: \n"
|
||||
|
||||
@@ -1148,7 +1148,7 @@ msgid "Middle click"
|
||||
msgstr ""
|
||||
|
||||
#: ../properties.c:3506
|
||||
msgid "sShade"
|
||||
msgid "Shade"
|
||||
msgstr ""
|
||||
|
||||
#: ../properties.c:3514
|
||||
|
||||
@@ -3503,7 +3503,7 @@ void create_task(GtkWidget *parent)
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Close"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Toggle"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Iconify"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("sShade"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Shade"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Toggle or iconify"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Maximize or restore"));
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Desktop left"));
|
||||
|
||||
@@ -86,6 +86,8 @@ void load_cache(Cache *cache, const gchar *cache_path)
|
||||
|
||||
if (parse_line(line, &key, &value)) {
|
||||
g_hash_table_insert(cache->_table, g_strdup(key), g_strdup(value));
|
||||
free(key);
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
|
||||
@@ -73,15 +73,15 @@ void copy_file(const char *path_src, const char *path_dest)
|
||||
fclose(file_src);
|
||||
}
|
||||
|
||||
int parse_line(const char *line, char **key, char **value)
|
||||
gboolean parse_line(const char *line, char **key, char **value)
|
||||
{
|
||||
char *a, *b;
|
||||
|
||||
/* Skip useless lines */
|
||||
if ((line[0] == '#') || (line[0] == '\n'))
|
||||
return 0;
|
||||
return FALSE;
|
||||
if (!(a = strchr(line, '=')))
|
||||
return 0;
|
||||
return FALSE;
|
||||
|
||||
/* overwrite '=' with '\0' */
|
||||
a[0] = '\0';
|
||||
@@ -96,7 +96,7 @@ int parse_line(const char *line, char **key, char **value)
|
||||
|
||||
g_strstrip(*key);
|
||||
g_strstrip(*value);
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void tint_exec(const char *command)
|
||||
@@ -673,3 +673,13 @@ GSList *slist_remove_duplicates(GSList *list, GCompareFunc eq, GDestroyNotify fr
|
||||
|
||||
return new_list;
|
||||
}
|
||||
|
||||
gint cmp_ptr(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
if (a < b)
|
||||
return -1;
|
||||
else if (a == b)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void copy_file(const char *path_src, const char *path_dest);
|
||||
// Strips key and value.
|
||||
// Values may contain spaces and the equal sign.
|
||||
// Returns 1 if both key and value could be read, zero otherwise.
|
||||
int parse_line(const char *line, char **key, char **value);
|
||||
gboolean parse_line(const char *line, char **key, char **value);
|
||||
|
||||
void extract_values(const char *value, char **value1, char **value2, char **value3);
|
||||
|
||||
@@ -120,6 +120,9 @@ GSList *load_locations_from_env(GSList *locations, const char *var, ...);
|
||||
|
||||
GSList *slist_remove_duplicates(GSList *list, GCompareFunc eq, GDestroyNotify fr);
|
||||
|
||||
// A trivial pointer comparator.
|
||||
gint cmp_ptr(gconstpointer a, gconstpointer b);
|
||||
|
||||
#define free_and_null(p) \
|
||||
{ \
|
||||
free(p); \
|
||||
|
||||
Reference in New Issue
Block a user