Compare commits

..

11 Commits

Author SHA1 Message Date
Oskari Rauta
5e231842fa Add gradient background support 2016-08-15 01:18:11 -04:00
Oskari Rauta
dd3e2a7b91 Add separator plugin 2016-08-15 01:12:33 -04:00
o9000
cbb76849ea Fix missing include (fixes issue #594; thanks @Coacher) 2016-08-08 13:08:29 +02:00
o9000
cf930fa42e Fix hang (issue #586) 2016-08-08 12:17:15 +02:00
o9000
da51d37322 Execp: force update after custom command execution (issue #586) 2016-08-08 12:04:31 +02:00
o9000
a09e1a0e45 Fixed multiple memory leaks 2016-08-08 11:15:59 +02:00
o9000
1d4f64d745 Fixed typo causing missing startup notifications 2016-08-08 10:58:18 +02:00
o9000
2857b96c4d Fixed memory leak in icon loading 2016-08-08 10:56:06 +02:00
o9000
8b08930268 tint2conf: fix typo (issue #592) 2016-08-07 14:23:49 +02:00
o9000
2922708c18 Launcher: reload shortcut on click: updated changelog (issue #569) 2016-08-07 14:18:34 +02:00
o9000
5c6385b4c3 Launcher: reload shortcut on click (issue #569) 2016-08-07 14:15:45 +02:00
30 changed files with 980 additions and 212 deletions

View File

@@ -87,6 +87,7 @@ include_directories( ${PROJECT_BINARY_DIR}
src/util src/util
src/execplugin src/execplugin
src/freespace src/freespace
src/separator
${X11_INCLUDE_DIRS} ${X11_INCLUDE_DIRS}
${PANGOCAIRO_INCLUDE_DIRS} ${PANGOCAIRO_INCLUDE_DIRS}
${PANGO_INCLUDE_DIRS} ${PANGO_INCLUDE_DIRS}
@@ -114,6 +115,7 @@ set( SOURCES src/config.c
src/tooltip/tooltip.c src/tooltip/tooltip.c
src/execplugin/execplugin.c src/execplugin/execplugin.c
src/freespace/freespace.c src/freespace/freespace.c
src/separator/separator.c
src/util/area.c src/util/area.c
src/util/common.c src/util/common.c
src/util/strnatcmp.c src/util/strnatcmp.c

View File

@@ -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 2016-08-02 0.12.12
- Fixes: - Fixes:
- Set task maximum height equal to width if not specified, instead of hardcoding 30 (issue #583; thanks @VastOne) - Set task maximum height equal to width if not specified, instead of hardcoding 30 (issue #583; thanks @VastOne)

View File

@@ -52,6 +52,7 @@
#include "window.h" #include "window.h"
#include "tooltip.h" #include "tooltip.h"
#include "timer.h" #include "timer.h"
#include "separator.h"
#include "execplugin.h" #include "execplugin.h"
#ifdef ENABLE_BATTERY #ifdef ENABLE_BATTERY
@@ -71,6 +72,8 @@ char *snapshot_path;
// detect if it's an old config file (==1) // detect if it's an old config file (==1)
static gboolean new_config_file; static gboolean new_config_file;
static gboolean read_bg_color2;
static gboolean read_bg_gradient;
static gboolean read_bg_color_hover; static gboolean read_bg_color_hover;
static gboolean read_border_color_hover; static gboolean read_border_color_hover;
static gboolean read_bg_color_press; static gboolean read_bg_color_press;
@@ -202,6 +205,15 @@ void load_launcher_app_dir(const char *path)
g_list_free(files); g_list_free(files);
} }
Separator *get_or_create_last_separator()
{
if (!panel_config.separator_list) {
fprintf(stderr, "Warning: separator items should shart with 'separator = new'\n");
panel_config.separator_list = g_list_append(panel_config.separator_list, create_separator());
}
return (Separator *)g_list_last(panel_config.separator_list)->data;
}
Execp *get_or_create_last_execp() Execp *get_or_create_last_execp()
{ {
if (!panel_config.execp_list) { if (!panel_config.execp_list) {
@@ -220,6 +232,10 @@ void add_entry(char *key, char *value)
// 'rounded' is the first parameter => alloc a new background // 'rounded' is the first parameter => alloc a new background
if (backgrounds->len > 0) { if (backgrounds->len > 0) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
if (!read_bg_color2)
memcpy(&bg->fill_color2, &bg->fill_color, sizeof(Color));
if (!read_bg_gradient)
bg->gradient = 0;
if (!read_bg_color_hover) if (!read_bg_color_hover)
memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color)); memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color));
if (!read_border_color_hover) if (!read_border_color_hover)
@@ -233,6 +249,8 @@ void add_entry(char *key, char *value)
init_background(&bg); init_background(&bg);
bg.border.radius = atoi(value); bg.border.radius = atoi(value);
g_array_append_val(backgrounds, bg); g_array_append_val(backgrounds, bg);
read_bg_color2 = 0;
read_bg_gradient = 0;
read_bg_color_hover = 0; read_bg_color_hover = 0;
read_border_color_hover = 0; read_border_color_hover = 0;
read_bg_color_press = 0; read_bg_color_press = 0;
@@ -260,6 +278,19 @@ void add_entry(char *key, char *value)
bg->fill_color.alpha = (atoi(value2) / 100.0); bg->fill_color.alpha = (atoi(value2) / 100.0);
else else
bg->fill_color.alpha = 0.5; bg->fill_color.alpha = 0.5;
} else if (strcmp(key, "background_color2") == 0) {
Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1);
extract_values(value, &value1, &value2, &value3);
get_color (value1, bg->fill_color2.rgb);
if (value2)
bg->fill_color2.alpha = (atoi (value2) / 100.0);
else
bg->fill_color2.alpha = 0.5;
read_bg_color2 = 1;
} else if (strcmp(key, "gradient") == 0) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len-1);
bg->gradient = atoi(value);
read_bg_gradient = 1;
} else if (strcmp(key, "border_color") == 0) { } else if (strcmp(key, "border_color") == 0) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
extract_values(value, &value1, &value2, &value3); extract_values(value, &value1, &value2, &value3);
@@ -527,6 +558,22 @@ void add_entry(char *key, char *value)
#endif #endif
} }
/* Separator */
else if (strcmp(key, "separator") == 0) {
panel_config.separator_list = g_list_append(panel_config.separator_list, create_separator());
} else if (strcmp(key, "separator_color") == 0) {
Separator *separator = get_or_create_last_separator();
extract_values(value, &value1, &value2, &value3);
get_color(value1, separator->color.rgb);
if (value2)
separator->color.alpha = (atoi(value2) / 100.0);
else
separator->color.alpha = 0.5;
} else if (strcmp(key, "separator_style") == 0) {
Separator *separator = get_or_create_last_separator();
separator->style = atoi(value);
}
/* Execp */ /* Execp */
else if (strcmp(key, "execp") == 0) { else if (strcmp(key, "execp") == 0) {
panel_config.execp_list = g_list_append(panel_config.execp_list, create_execp()); panel_config.execp_list = g_list_append(panel_config.execp_list, create_execp());
@@ -1104,6 +1151,10 @@ gboolean config_read_file(const char *path)
if (backgrounds->len > 0) { if (backgrounds->len > 0) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
if (!read_bg_color2)
memcpy(&bg->fill_color2, &bg->fill_color, sizeof(Color));
if (!read_bg_gradient)
bg->gradient = 0;
if (!read_bg_color_hover) if (!read_bg_color_hover)
memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color)); memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color));
if (!read_border_color_hover) if (!read_border_color_hover)

View File

@@ -32,12 +32,11 @@ Execp *create_execp()
Execp *execp = calloc(1, sizeof(Execp)); Execp *execp = calloc(1, sizeof(Execp));
execp->backend = calloc(1, sizeof(ExecpBackend)); execp->backend = calloc(1, sizeof(ExecpBackend));
execp->backend->child_pipe = -1; execp->backend->child_pipe = -1;
execp->backend->cmd_pids = g_tree_new(cmp_ptr);
execp->backend->interval = 30; execp->backend->interval = 30;
execp->backend->cache_icon = TRUE; execp->backend->cache_icon = TRUE;
execp->backend->centered = TRUE; execp->backend->centered = TRUE;
execp->backend->font_color.alpha = 0.5; execp->backend->font_color.alpha = 0.5;
return execp; return execp;
} }
@@ -59,6 +58,9 @@ void destroy_execp(void *obj)
// This is a frontend element // This is a frontend element
execp->backend->instances = g_list_remove_all(execp->backend->instances, execp); execp->backend->instances = g_list_remove_all(execp->backend->instances, execp);
free_and_null(execp->frontend); free_and_null(execp->frontend);
remove_area(&execp->area);
free_area(&execp->area);
free_and_null(execp);
} else { } else {
// This is a backend element // This is a backend element
stop_timeout(execp->backend->timer); stop_timeout(execp->backend->timer);
@@ -80,6 +82,10 @@ void destroy_execp(void *obj)
close(execp->backend->child_pipe); close(execp->backend->child_pipe);
execp->backend->child_pipe = -1; 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; execp->backend->bg = NULL;
pango_font_description_free(execp->backend->font_desc); pango_font_description_free(execp->backend->font_desc);
@@ -464,6 +470,18 @@ void execp_dump_geometry(void *obj, int indent)
execp->backend->text); 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) void execp_action(void *obj, int button, int x, int y)
{ {
Execp *execp = obj; Execp *execp = obj;
@@ -495,20 +513,32 @@ void execp_action(void *obj, int button, int x, int y)
execp->area.width, execp->area.width,
execp->area.height, execp->area.height,
command); 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); g_free(full_cmd);
} else { } else {
if (execp->backend->child_pipe > 0) { execp_force_update(execp);
// 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_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) void execp_timer_callback(void *arg)
{ {
Execp *execp = arg; Execp *execp = arg;

View File

@@ -70,6 +70,7 @@ typedef struct ExecpBackend {
// List of Execp which are frontends for this backend, one for each panel // List of Execp which are frontends for this backend, one for each panel
GList *instances; GList *instances;
GTree *cmd_pids;
} ExecpBackend; } ExecpBackend;
typedef struct ExecpFrontend { typedef struct ExecpFrontend {
@@ -130,6 +131,8 @@ gboolean resize_execp(void *obj);
// Called on mouse click event. // Called on mouse click event.
void execp_action(void *obj, int button, int x, int y); 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. // Called to check if new output from the command can be read.
// No command might be running. // No command might be running.
// Returns 1 if the output has been updated and a redraw is needed. // Returns 1 if the output has been updated and a redraw is needed.

View File

@@ -305,6 +305,7 @@ void free_themes(IconThemeWrapper *wrapper)
{ {
if (!wrapper) if (!wrapper)
return; return;
free(wrapper->icon_theme_name);
for (GSList *l = wrapper->themes; l; l = l->next) { for (GSList *l = wrapper->themes; l; l = l->next) {
IconTheme *theme = (IconTheme *)l->data; IconTheme *theme = (IconTheme *)l->data;
free_icon_theme(theme); free_icon_theme(theme);

View File

@@ -57,6 +57,10 @@ Background *launcher_icon_bg;
Imlib_Image scale_icon(Imlib_Image original, int icon_size); Imlib_Image scale_icon(Imlib_Image original, int icon_size);
void free_icon(Imlib_Image icon); void free_icon(Imlib_Image icon);
void launcher_icon_dump_geometry(void *obj, int indent); 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() void default_launcher()
{ {
@@ -143,6 +147,7 @@ void cleanup_launcher_theme(Launcher *launcher)
free(launcherIcon->icon_path); free(launcherIcon->icon_path);
free(launcherIcon->cmd); free(launcherIcon->cmd);
g_free(launcherIcon->icon_tooltip); g_free(launcherIcon->icon_tooltip);
free(launcherIcon->config_path);
} }
free(launcherIcon); free(launcherIcon);
} }
@@ -176,61 +181,17 @@ gboolean resize_launcher(void *obj)
launcherIcon->icon_size = icon_size; launcherIcon->icon_size = icon_size;
launcherIcon->area.width = launcherIcon->icon_size; launcherIcon->area.width = launcherIcon->icon_size;
launcherIcon->area.height = launcherIcon->icon_size; launcherIcon->area.height = launcherIcon->icon_size;
launcher_reload_icon_image(launcher, launcherIcon);
// 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);
} }
} }
save_icon_cache(launcher->icon_theme_wrapper); 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 (panel_horizontal) {
if (!count) { if (!count) {
@@ -268,17 +229,15 @@ gboolean resize_launcher(void *obj)
posy = top_border_width(&launcher->area) + launcher->area.paddingxlr; posy = top_border_width(&launcher->area) + launcher->area.paddingxlr;
} }
int i; int i = 0;
GSList *l; for (GSList *l = launcher->list_icons; l; l = l->next) {
for (i = 1, l = launcher->list_icons; l; i++, l = l->next) {
LauncherIcon *launcherIcon = (LauncherIcon *)l->data; LauncherIcon *launcherIcon = (LauncherIcon *)l->data;
if (!launcherIcon->area.on_screen)
continue;
i++;
launcherIcon->y = posy; launcherIcon->y = posy;
launcherIcon->x = posx; launcherIcon->x = posx;
launcherIcon->area.posy = ((Area *)launcherIcon->area.parent)->posy + launcherIcon->y; launcher_icon_on_change_layout(launcherIcon);
launcherIcon->area.posx = ((Area *)launcherIcon->area.parent)->posx + launcherIcon->x;
launcherIcon->area.width = launcherIcon->icon_size;
launcherIcon->area.height = launcherIcon->icon_size;
// printf("launcher %d : %d,%d\n", i, posx, posy); // printf("launcher %d : %d,%d\n", i, posx, posy);
if (panel_horizontal) { if (panel_horizontal) {
if (i % icons_per_column) { if (i % icons_per_column) {
@@ -401,6 +360,8 @@ void free_icon(Imlib_Image icon)
void launcher_action(LauncherIcon *icon, XEvent *evt) 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); char *cmd = calloc(strlen(icon->cmd) + 10, 1);
sprintf(cmd, "(%s&)", icon->cmd); sprintf(cmd, "(%s&)", icon->cmd);
#if HAVE_SN #if HAVE_SN
@@ -461,56 +422,109 @@ void launcher_load_icons(Launcher *launcher)
// Load apps (.desktop style launcher items) // Load apps (.desktop style launcher items)
GSList *app = launcher->list_apps; GSList *app = launcher->list_apps;
while (app != NULL) { while (app != NULL) {
DesktopEntry entry; LauncherIcon *launcherIcon = calloc(1, sizeof(LauncherIcon));
read_desktop_file(app->data, &entry); launcherIcon->area.panel = launcher->area.panel;
if (entry.exec) { launcherIcon->area._draw_foreground = draw_launcher_icon;
LauncherIcon *launcherIcon = calloc(1, sizeof(LauncherIcon)); launcherIcon->area.size_mode = LAYOUT_FIXED;
launcherIcon->area.panel = launcher->area.panel; launcherIcon->area._resize = NULL;
snprintf(launcherIcon->area.name, launcherIcon->area.resize_needed = 0;
sizeof(launcherIcon->area.name), launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects;
"LauncherIcon %s", launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect;
entry.name ? entry.name : "null"); launcherIcon->area.bg = launcher_icon_bg;
launcherIcon->area._draw_foreground = draw_launcher_icon; launcherIcon->area.on_screen = TRUE;
launcherIcon->area.size_mode = LAYOUT_FIXED; launcherIcon->area._on_change_layout = launcher_icon_on_change_layout;
launcherIcon->area._resize = NULL; launcherIcon->area._dump_geometry = launcher_icon_dump_geometry;
launcherIcon->area.resize_needed = 0; if (launcher_tooltip_enabled) {
schedule_redraw(&launcherIcon->area); launcherIcon->area._get_tooltip_text = launcher_icon_get_tooltip_text;
launcherIcon->area.has_mouse_over_effect = panel_config.mouse_effects; } else {
launcherIcon->area.has_mouse_press_effect = launcherIcon->area.has_mouse_over_effect; launcherIcon->area._get_tooltip_text = NULL;
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);
} }
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); 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 // Populates the icon_theme_wrapper list
void launcher_load_themes(Launcher *launcher) void launcher_load_themes(Launcher *launcher)
{ {

View File

@@ -23,6 +23,7 @@ typedef struct Launcher {
typedef struct LauncherIcon { typedef struct LauncherIcon {
// always start with area // always start with area
Area area; Area area;
char *config_path;
Imlib_Image image; Imlib_Image image;
Imlib_Image image_hover; Imlib_Image image_hover;
Imlib_Image image_pressed; Imlib_Image image_pressed;
@@ -31,7 +32,6 @@ typedef struct LauncherIcon {
char *icon_path; char *icon_path;
char *icon_tooltip; char *icon_tooltip;
int icon_size; int icon_size;
int is_app_desktop;
int x, y; int x, y;
} LauncherIcon; } LauncherIcon;

View File

@@ -171,6 +171,7 @@ void init_panel()
init_battery(); init_battery();
#endif #endif
init_taskbar(); init_taskbar();
init_separator();
init_execp(); init_execp();
// number of panels (one monitor or 'all' monitors) // number of panels (one monitor or 'all' monitors)
@@ -204,6 +205,7 @@ void init_panel()
p->area.size_mode = LAYOUT_DYNAMIC; p->area.size_mode = LAYOUT_DYNAMIC;
p->area._resize = resize_panel; p->area._resize = resize_panel;
p->area._clear = panel_clear_background; p->area._clear = panel_clear_background;
p->separator_list = NULL;
init_panel_size_and_position(p); init_panel_size_and_position(p);
// add children according to panel_items // add children according to panel_items
for (int k = 0; k < strlen(panel_items_order); k++) { for (int k = 0; k < strlen(panel_items_order); k++) {
@@ -223,6 +225,8 @@ void init_panel()
init_clock_panel(p); init_clock_panel(p);
if (panel_items_order[k] == 'F' && !strstr(panel_items_order, "T")) if (panel_items_order[k] == 'F' && !strstr(panel_items_order, "T"))
init_freespace_panel(p); init_freespace_panel(p);
if (panel_items_order[k] == ':')
init_separator_panel(p);
if (panel_items_order[k] == 'E') if (panel_items_order[k] == 'E')
init_execp_panel(p); init_execp_panel(p);
} }
@@ -547,6 +551,7 @@ void set_panel_items_order(Panel *p)
} }
int i_execp = 0; int i_execp = 0;
int i_separator = 0;
for (int k = 0; k < strlen(panel_items_order); k++) { for (int k = 0; k < strlen(panel_items_order); k++) {
if (panel_items_order[k] == 'L') { if (panel_items_order[k] == 'L') {
p->area.children = g_list_append(p->area.children, &p->launcher); p->area.children = g_list_append(p->area.children, &p->launcher);
@@ -568,6 +573,12 @@ void set_panel_items_order(Panel *p)
p->area.children = g_list_append(p->area.children, &p->clock); p->area.children = g_list_append(p->area.children, &p->clock);
if (panel_items_order[k] == 'F') if (panel_items_order[k] == 'F')
p->area.children = g_list_append(p->area.children, &p->freespace); p->area.children = g_list_append(p->area.children, &p->freespace);
if (panel_items_order[k] == ':') {
GList *item = g_list_nth(p->separator_list, i_separator);
i_separator++;
if (item)
p->area.children = g_list_append(p->area.children, (Area *)item->data);
}
if (panel_items_order[k] == 'E') { if (panel_items_order[k] == 'E') {
GList *item = g_list_nth(p->execp_list, i_execp); GList *item = g_list_nth(p->execp_list, i_execp);
i_execp++; i_execp++;

View File

@@ -22,6 +22,7 @@
#include "launcher.h" #include "launcher.h"
#include "freespace.h" #include "freespace.h"
#include "execplugin.h" #include "execplugin.h"
#include "separator.h"
#ifdef ENABLE_BATTERY #ifdef ENABLE_BATTERY
#include "battery.h" #include "battery.h"
@@ -127,6 +128,7 @@ typedef struct Panel {
Launcher launcher; Launcher launcher;
FreeSpace freespace; FreeSpace freespace;
GList *separator_list;
GList *execp_list; GList *execp_list;
// Autohide // Autohide

217
src/separator/separator.c Normal file
View File

@@ -0,0 +1,217 @@
// Tint2 : Separator plugin
// Author: Oskari Rauta
#include <string.h>
#include <stdio.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <pango/pangocairo.h>
#include <stdlib.h>
#include <math.h>
#include "window.h"
#include "server.h"
#include "panel.h"
#include "common.h"
#include "separator.h"
Separator *create_separator()
{
Separator *separator = calloc(1, sizeof(Separator));
return separator;
}
void destroy_separator(void *obj)
{
Separator *separator = (Separator *)obj;
remove_area(&separator->area);
free_area(&separator->area);
free_and_null(separator);
}
void init_separator()
{
GList *to_remove = panel_config.separator_list;
for (int k = 0; k < strlen(panel_items_order) && to_remove; k++) {
if (panel_items_order[k] == ':') {
to_remove = to_remove->next;
}
}
if (to_remove) {
if (to_remove == panel_config.separator_list) {
g_list_free_full(to_remove, destroy_separator);
panel_config.separator_list = NULL;
} else {
// Cut panel_config.separator_list
if (to_remove->prev)
to_remove->prev->next = NULL;
to_remove->prev = NULL;
// Remove all elements of to_remove and to_remove itself
g_list_free_full(to_remove, destroy_separator);
}
}
}
void init_separator_panel(void *p)
{
Panel *panel = (Panel *)p;
// Make sure this is only done once if there are multiple items
if (panel->separator_list)
return;
// panel->separator_list is now a copy of the pointer panel_config.separator_list
// We make it a deep copy
panel->separator_list = g_list_copy_deep(panel_config.separator_list, NULL, NULL);
for (GList *l = panel->separator_list; l; l = l->next) {
Separator *separator = l->data;
if (!separator->area.bg)
separator->area.bg = &g_array_index(backgrounds, Background, 0);
separator->area.parent = p;
separator->area.panel = p;
snprintf(separator->area.name, sizeof(separator->area.name), "separator");
separator->area.size_mode = LAYOUT_FIXED;
separator->area.resize_needed = 1;
separator->area.on_screen = TRUE;
separator->area._resize = resize_separator;
separator->area._draw_foreground = draw_separator;
}
}
void cleanup_separator()
{
// Cleanup frontends
for (int i = 0; i < num_panels; i++) {
g_list_free_full(panels[i].separator_list, destroy_separator);
panels[i].separator_list = NULL;
}
// Cleanup backends
g_list_free_full(panel_config.separator_list, destroy_separator);
panel_config.separator_list = NULL;
}
gboolean resize_separator(void *obj)
{
Separator *separator = obj;
// Panel *panel = separator->area.panel;
if (!separator->area.on_screen)
return FALSE;
double d_height = panel_horizontal ? separator->area.height : separator->area.width;
double d_thickness = round(d_height / 16) >= 1.0 ? round(d_height / 16) : 1.0;
if (separator->style == 3)
d_thickness = round(d_height / 8) >= 1.0 ? round(d_height / 8) : 1.0;
double d_len = round(d_height / 16) >= 1.0 ? round(d_height / 16) : 1.0;
double d_width = d_thickness * 5;
if (separator->style == 4) {
d_width = d_thickness * 7;
d_thickness = d_thickness * 3;
}
if (separator->style == 2) {
d_width = d_height;
d_thickness = round(d_height / 8) >= 1.0 ? round(d_height / 8) : 1.0;
d_len = d_thickness;
}
double d_empty_thickness = d_thickness;
if (separator->style == 5 || separator->style == 6) {
d_width = (d_thickness * 4) + 2.0;
d_thickness = 1.0;
}
if (panel_horizontal) {
separator->area.width = d_width;
separator->area.height = d_height;
} else {
separator->area.width = d_height;
separator->area.height = d_width;
}
separator->empty_thickness = d_empty_thickness;
separator->thickness = d_thickness;
separator->len = d_len;
schedule_redraw(&separator->area);
panel_refresh = TRUE;
return TRUE;
}
void draw_separator(void *obj, cairo_t *c)
{
Separator *separator = obj;
if (separator->style == 0 )
return;
double start_point = 0 + ( separator->thickness * 2 );
double end_point = separator->area.height - ( separator->thickness * 2 );
if (!panel_horizontal)
end_point = separator->area.width - ( separator->thickness * 2 );
double count = end_point - start_point;
double thickness = separator->thickness;
double len = separator->len;
int alt = 0;
double x_fix = 0;
if (separator->style == 2) {
if (!panel_horizontal)
start_point=start_point + 2;
cairo_set_source_rgba(c, separator->color.rgb[0], separator->color.rgb[1], separator->color.rgb[2], separator->color.alpha);
cairo_set_line_width(c, 1);
cairo_rectangle(c, start_point - 2, start_point - (panel_horizontal ? 0 : 4), end_point - thickness - 3, end_point - thickness - ( panel_horizontal ? 3 : 3));
cairo_stroke_preserve(c);
cairo_fill(c);
return;
}
if (count < thickness)
return;
while (((int) count) % 2) {
if (alt) {
start_point++;
alt = 0;
} else {
end_point--;
alt = 1;
}
count = end_point - start_point;
if (count < thickness)
return;
}
if (separator->style == 3 || separator->style == 4)
x_fix = round(thickness / 2) + (separator->style == 4 ? 1.0 : 0.0);
if (separator->style == 5 || separator->style == 6) {
x_fix = -1.0;
start_point = start_point + 2;
end_point--;
}
double separator_pattern[] = { len, len };
double separator_style6_pattern[] = { 1.0 };
cairo_set_source_rgba(c, separator->color.rgb[0], separator->color.rgb[1], separator->color.rgb[2], separator->color.alpha);
cairo_set_line_width(c, thickness);
if (separator->style == 6)
cairo_set_dash(c, separator_style6_pattern, 1, 0);
else
cairo_set_dash(c, separator_pattern, sizeof(separator_pattern) / sizeof(separator_pattern[0]), 0);
if (panel_horizontal) {
cairo_move_to(c, (separator->area.width / 2) - thickness + x_fix, start_point);
cairo_line_to(c, (separator->area.width / 2) - thickness + x_fix, end_point);
} else {
cairo_move_to(c, start_point, (separator->area.height / 2) - thickness + x_fix);
cairo_line_to(c, end_point, (separator->area.height / 2) - thickness + x_fix);
}
cairo_stroke(c);
}

27
src/separator/separator.h Normal file
View File

@@ -0,0 +1,27 @@
// Tint2 : Separator
// Author: Oskari Rauta <oskari.rauta@gmail.com>
#ifndef SEPARATOR_H
#define SEPARATOR_H
#include "common.h"
#include "area.h"
typedef struct Separator {
Area area;
int style;
Color color;
double empty_thickness;
double thickness;
double len;
} Separator;
Separator *create_separator();
void destroy_separator(void *obj);
void init_separator();
void init_separator_panel(void *p);
void cleanup_separator();
gboolean resize_separator(void *obj);
void draw_separator(void *obj, cairo_t *c);
#endif

View File

@@ -140,6 +140,11 @@ void cleanup_server()
XFreeGC(server.display, server.gc); XFreeGC(server.display, server.gc);
server.gc = NULL; server.gc = NULL;
server.disable_transparency = FALSE; 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) void send_event32(Window win, Atom at, long data1, long data2, long data3)

View File

@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**************************************************************************/ **************************************************************************/
#include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@@ -36,10 +37,10 @@
#include <pwd.h> #include <pwd.h>
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#ifdef HAVE_SN #ifdef HAVE_SN
#include <libsn/sn.h> #include <libsn/sn.h>
#include <sys/wait.h>
#endif #endif
#include <version.h> #include <version.h>
@@ -376,8 +377,8 @@ void init(int argc, char *argv[])
debug_geometry = getenv("DEBUG_GEOMETRY") != NULL; debug_geometry = getenv("DEBUG_GEOMETRY") != NULL;
} }
static int sn_pipe_valid = 0; static int sigchild_pipe_valid = FALSE;
static int sn_pipe[2]; static int sigchild_pipe[2];
#ifdef HAVE_SN #ifdef HAVE_SN
static int error_trap_depth = 0; 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 */ XSync(xdisplay, False); /* get all errors out of the queue */
--error_trap_depth; --error_trap_depth;
} }
#endif // HAVE_SN
static void sigchld_handler(int sig) static void sigchld_handler(int sig)
{ {
if (!startup_notifications) if (!sigchild_pipe_valid)
return; return;
if (!sn_pipe_valid) int savedErrno = errno;
return; ssize_t unused = write(sigchild_pipe[1], "x", 1);
ssize_t wur = write(sn_pipe[1], "x", 1); (void)unused;
(void)wur; fsync(sigchild_pipe[1]);
fsync(sn_pipe[1]); errno = savedErrno;
} }
static void sigchld_handler_async() static void sigchld_handler_async()
{ {
if (!startup_notifications)
return;
// Wait for all dead processes // Wait for all dead processes
pid_t pid; pid_t pid;
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { int status;
SnLauncherContext *ctx; while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) {
ctx = (SnLauncherContext *)g_tree_lookup(server.pids, GINT_TO_POINTER(pid)); #ifdef HAVE_SN
SnLauncherContext *ctx = (SnLauncherContext *)g_tree_lookup(server.pids, GINT_TO_POINTER(pid));
if (ctx) { if (ctx) {
g_tree_remove(server.pids, GINT_TO_POINTER(pid)); g_tree_remove(server.pids, GINT_TO_POINTER(pid));
sn_launcher_context_complete(ctx); sn_launcher_context_complete(ctx);
sn_launcher_context_unref(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() void init_X11_pre_config()
{ {
server.display = XOpenDisplay(NULL); server.display = XOpenDisplay(NULL);
@@ -475,25 +467,32 @@ void init_X11_post_config()
{ {
server_init_visual(); server_init_visual();
gboolean need_sigchld = FALSE;
#ifdef HAVE_SN #ifdef HAVE_SN
// Initialize startup-notification // Initialize startup-notification
if (startup_notifications) { if (startup_notifications) {
server.sn_display = sn_display_new(server.display, error_trap_push, error_trap_pop); server.sn_display = sn_display_new(server.display, error_trap_push, error_trap_pop);
server.pids = g_tree_new(cmp_ptr); 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 // Setup a handler for child termination
if (pipe(sn_pipe) != 0) { if (pipe(sigchild_pipe) != 0) {
fprintf(stderr, "Creating pipe failed.\n"); fprintf(stderr, "Creating pipe failed.\n");
} else { } else {
fcntl(sn_pipe[0], F_SETFL, O_NONBLOCK | fcntl(sn_pipe[0], F_GETFL)); fcntl(sigchild_pipe[0], F_SETFL, O_NONBLOCK | fcntl(sigchild_pipe[0], F_GETFL));
fcntl(sn_pipe[1], F_SETFL, O_NONBLOCK | fcntl(sn_pipe[1], F_GETFL)); fcntl(sigchild_pipe[1], F_SETFL, O_NONBLOCK | fcntl(sigchild_pipe[1], F_GETFL));
sn_pipe_valid = 1; sigchild_pipe_valid = 1;
struct sigaction act = {.sa_handler = sigchld_handler, .sa_flags = SA_NOCLDWAIT | SA_RESTART}; struct sigaction act = {.sa_handler = sigchld_handler, .sa_flags = SA_RESTART};
if (sigaction(SIGCHLD, &act, 0)) { if (sigaction(SIGCHLD, &act, 0)) {
perror("sigaction"); perror("sigaction");
} }
} }
} }
#endif // HAVE_SN
imlib_context_set_display(server.display); imlib_context_set_display(server.display);
imlib_context_set_visual(server.visual); imlib_context_set_visual(server.visual);
@@ -543,15 +542,11 @@ void cleanup()
XCloseDisplay(server.display); XCloseDisplay(server.display);
server.display = NULL; server.display = NULL;
#ifdef HAVE_SN if (sigchild_pipe_valid) {
if (startup_notifications) { sigchild_pipe_valid = FALSE;
if (sn_pipe_valid) { close(sigchild_pipe[1]);
sn_pipe_valid = 0; close(sigchild_pipe[0]);
close(sn_pipe[1]);
close(sn_pipe[0]);
}
} }
#endif
uevent_cleanup(); uevent_cleanup();
} }
@@ -1641,9 +1636,9 @@ start:
FD_ZERO(&fdset); FD_ZERO(&fdset);
FD_SET(x11_fd, &fdset); FD_SET(x11_fd, &fdset);
int maxfd = x11_fd; int maxfd = x11_fd;
if (sn_pipe_valid) { if (sigchild_pipe_valid) {
FD_SET(sn_pipe[0], &fdset); FD_SET(sigchild_pipe[0], &fdset);
maxfd = maxfd < sn_pipe[0] ? sn_pipe[0] : maxfd; maxfd = maxfd < sigchild_pipe[0] ? sigchild_pipe[0] : maxfd;
} }
for (GList *l = panel_config.execp_list; l; l = l->next) { for (GList *l = panel_config.execp_list; l; l = l->next) {
Execp *execp = (Execp *)l->data; Execp *execp = (Execp *)l->data;
@@ -1664,9 +1659,9 @@ start:
if (XPending(server.display) > 0 || select(maxfd + 1, &fdset, 0, 0, select_timeout) >= 0) { if (XPending(server.display) > 0 || select(maxfd + 1, &fdset, 0, 0, select_timeout) >= 0) {
uevent_handler(); uevent_handler();
if (sn_pipe_valid) { if (sigchild_pipe_valid) {
char buffer[1]; char buffer[1];
while (read(sn_pipe[0], buffer, sizeof(buffer)) > 0) { while (read(sigchild_pipe[0], buffer, sizeof(buffer)) > 0) {
sigchld_handler_async(); sigchld_handler_async();
} }
} }

View File

@@ -1133,12 +1133,6 @@ msgstr "Prebaci"
msgid "Iconify" msgid "Iconify"
msgstr "Umanji" 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:3435 ../properties.c:3471 ../properties.c:3507
#: ../properties.c:3543 ../properties.c:3579 #: ../properties.c:3543 ../properties.c:3579
msgid "Toggle or iconify" msgid "Toggle or iconify"
@@ -1233,9 +1227,8 @@ msgid "Middle click"
msgstr "Srednji klik" msgstr "Srednji klik"
#: ../properties.c:3506 #: ../properties.c:3506
#, fuzzy msgid "Shade"
msgid "sShade" msgstr "Zatamni"
msgstr "zZatamni"
#: ../properties.c:3514 #: ../properties.c:3514
msgid "Specifies the action performed when task buttons receive a middle " msgid "Specifies the action performed when task buttons receive a middle "

View File

@@ -1257,10 +1257,6 @@ msgstr "Spécifie l'action à engager lorsque les boutons de tâches reçoivent
msgid "Middle click" msgid "Middle click"
msgstr "Clic milieu" msgstr "Clic milieu"
#: ../properties.c:3506
msgid "sShade"
msgstr "Réduire"
#: ../properties.c:3514 #: ../properties.c:3514
msgid "Specifies the action performed when task buttons receive a middle " msgid "Specifies the action performed when task buttons receive a middle "
"click event: \n" "click event: \n"

View File

@@ -1232,11 +1232,6 @@ msgstr "Određuje akciju nakon pomijeranja kolutića miša gore na zadatku: \n"
msgid "Middle click" msgid "Middle click"
msgstr "Srednji klik" msgstr "Srednji klik"
#: ../properties.c:3506
#, fuzzy
msgid "sShade"
msgstr "zZatamni"
#: ../properties.c:3514 #: ../properties.c:3514
msgid "Specifies the action performed when task buttons receive a middle " msgid "Specifies the action performed when task buttons receive a middle "
"click event: \n" "click event: \n"

View File

@@ -1248,10 +1248,6 @@ msgstr "Określa akcję, która zostanie wykonana po poruszeniu kółka myszy w
msgid "Middle click" msgid "Middle click"
msgstr "Klik środkowym" msgstr "Klik środkowym"
#: ../properties.c:3506
msgid "sShade"
msgstr "Zwiń"
#: ../properties.c:3514 #: ../properties.c:3514
msgid "Specifies the action performed when task buttons receive a middle " msgid "Specifies the action performed when task buttons receive a middle "
"click event: \n" "click event: \n"

View File

@@ -1220,10 +1220,6 @@ msgstr "Задает действие, выполняемое когда кно
msgid "Middle click" msgid "Middle click"
msgstr "Средний щелчок" msgstr "Средний щелчок"
#: ../properties.c:3506
msgid "sShade"
msgstr "Скрутить"
#: ../properties.c:3514 #: ../properties.c:3514
msgid "Specifies the action performed when task buttons receive a middle " msgid "Specifies the action performed when task buttons receive a middle "
"click event: \n" "click event: \n"

View File

@@ -1133,7 +1133,6 @@ msgstr "Умањи"
#: ../properties.c:3434 ../properties.c:3470 ../properties.c:3542 #: ../properties.c:3434 ../properties.c:3470 ../properties.c:3542
#: ../properties.c:3578 #: ../properties.c:3578
#, fuzzy
msgid "Shade" msgid "Shade"
msgstr "Затамни" msgstr "Затамни"
@@ -1230,11 +1229,6 @@ msgstr "Одређује акцију након померања колути
msgid "Middle click" msgid "Middle click"
msgstr "Средњи клик" msgstr "Средњи клик"
#: ../properties.c:3506
#, fuzzy
msgid "sShade"
msgstr "зЗатамни"
#: ../properties.c:3514 #: ../properties.c:3514
msgid "Specifies the action performed when task buttons receive a middle " msgid "Specifies the action performed when task buttons receive a middle "
"click event: \n" "click event: \n"

View File

@@ -1148,7 +1148,7 @@ msgid "Middle click"
msgstr "" msgstr ""
#: ../properties.c:3506 #: ../properties.c:3506
msgid "sShade" msgid "Shade"
msgstr "" msgstr ""
#: ../properties.c:3514 #: ../properties.c:3514

View File

@@ -120,6 +120,9 @@ GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after;
GtkWidget *clock_format_tooltip, *clock_tmz_tooltip; GtkWidget *clock_format_tooltip, *clock_tmz_tooltip;
GtkWidget *tooltip_background; GtkWidget *tooltip_background;
// Separators
GArray *separators;
// Executors // Executors
GArray *executors; GArray *executors;
@@ -141,6 +144,8 @@ GtkWidget *launcher_icon_theme_override;
GtkListStore *backgrounds; GtkListStore *backgrounds;
GtkWidget *current_background, GtkWidget *current_background,
*background_fill_color, *background_fill_color,
*background_fill_color2,
*background_gradient,
*background_border_color, *background_border_color,
*background_fill_color_over, *background_fill_color_over,
*background_border_color_over, *background_border_color_over,
@@ -185,6 +190,7 @@ void create_task_status(GtkWidget *notebook,
GtkWidget **task_status_icon_brightness, GtkWidget **task_status_icon_brightness,
GtkWidget **task_status_background, GtkWidget **task_status_background,
GtkWidget **task_status_background_set); GtkWidget **task_status_background_set);
void create_separator(GtkWidget *parent, int i);
void create_execp(GtkWidget *parent, int i); void create_execp(GtkWidget *parent, int i);
void create_clock(GtkWidget *parent); void create_clock(GtkWidget *parent);
void create_systemtray(GtkWidget *parent); void create_systemtray(GtkWidget *parent);
@@ -256,6 +262,7 @@ GtkWidget *create_properties()
tooltips = gtk_tooltips_new(); tooltips = gtk_tooltips_new();
(void) tooltips; (void) tooltips;
separators = g_array_new(FALSE, TRUE, sizeof(Separator));
executors = g_array_new(FALSE, TRUE, sizeof(Executor)); executors = g_array_new(FALSE, TRUE, sizeof(Executor));
// global layer // global layer
@@ -497,6 +504,9 @@ void create_background(GtkWidget *parent)
GTK_TYPE_INT, GTK_TYPE_INT,
GDK_TYPE_COLOR, GDK_TYPE_COLOR,
GTK_TYPE_INT, GTK_TYPE_INT,
GTK_TYPE_BOOL,
GDK_TYPE_COLOR,
GTK_TYPE_INT,
GTK_TYPE_INT, GTK_TYPE_INT,
GTK_TYPE_INT, GTK_TYPE_INT,
GTK_TYPE_STRING, GTK_TYPE_STRING,
@@ -571,6 +581,26 @@ void create_background(GtkWidget *parent)
col++; col++;
gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL); gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL);
row++, col = 2;
label = gtk_label_new(_("Secondary fill color"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
background_fill_color2 = gtk_color_button_new();
gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(background_fill_color2), TRUE);
gtk_widget_show(background_fill_color2);
gtk_table_attach(GTK_TABLE(table), background_fill_color2, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
background_gradient = gtk_check_button_new_with_label(_("Enable gradient"));
gtk_widget_show(background_gradient);
gtk_table_attach(GTK_TABLE(table), background_gradient, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, background_fill_color2, _("Color to fade into when using gradient background."), NULL);
row++, col = 2; row++, col = 2;
label = gtk_label_new(_("Border color")); label = gtk_label_new(_("Border color"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
@@ -697,6 +727,8 @@ void create_background(GtkWidget *parent)
g_signal_connect(G_OBJECT(current_background), "changed", G_CALLBACK(current_background_changed), NULL); g_signal_connect(G_OBJECT(current_background), "changed", G_CALLBACK(current_background_changed), NULL);
g_signal_connect(G_OBJECT(background_fill_color), "color-set", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_fill_color), "color-set", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_fill_color2), "color-set", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_gradient), "toggled", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_border_color), "color-set", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_border_color), "color-set", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_fill_color_over), "color-set", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_fill_color_over), "color-set", G_CALLBACK(background_update), NULL);
g_signal_connect(G_OBJECT(background_border_color_over), "color-set", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_border_color_over), "color-set", G_CALLBACK(background_update), NULL);
@@ -749,6 +781,10 @@ void background_create_new()
GdkColor fillColor; GdkColor fillColor;
cairoColor2GdkColor(0, 0, 0, &fillColor); cairoColor2GdkColor(0, 0, 0, &fillColor);
int fillOpacity = 0; int fillOpacity = 0;
GdkColor fillColor2;
cairoColor2GdkColor(0, 0, 0, &fillColor2);
int fillOpacity2 = 0;
gboolean gradient = FALSE;
GdkColor borderColor; GdkColor borderColor;
cairoColor2GdkColor(0, 0, 0, &borderColor); cairoColor2GdkColor(0, 0, 0, &borderColor);
int borderOpacity = 0; int borderOpacity = 0;
@@ -775,6 +811,9 @@ void background_create_new()
bgColPixbuf, NULL, bgColPixbuf, NULL,
bgColFillColor, &fillColor, bgColFillColor, &fillColor,
bgColFillOpacity, fillOpacity, bgColFillOpacity, fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, fillOpacity2,
bgColGradient, gradient,
bgColBorderColor, &borderColor, bgColBorderColor, &borderColor,
bgColBorderOpacity, borderOpacity, bgColBorderOpacity, borderOpacity,
bgColBorderWidth, b, bgColBorderWidth, b,
@@ -822,6 +861,9 @@ void background_duplicate(GtkWidget *widget, gpointer data)
gboolean sideRight; gboolean sideRight;
GdkColor *fillColor; GdkColor *fillColor;
int fillOpacity; int fillOpacity;
GdkColor *fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor *borderColor; GdkColor *borderColor;
int borderOpacity; int borderOpacity;
GdkColor *fillColorOver; GdkColor *fillColorOver;
@@ -836,6 +878,9 @@ void background_duplicate(GtkWidget *widget, gpointer data)
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor, bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity, bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor, bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity, bgColBorderOpacity, &borderOpacity,
bgColFillColorOver, &fillColorOver, bgColFillColorOver, &fillColorOver,
@@ -859,6 +904,9 @@ void background_duplicate(GtkWidget *widget, gpointer data)
bgColPixbuf, NULL, bgColPixbuf, NULL,
bgColFillColor, fillColor, bgColFillColor, fillColor,
bgColFillOpacity, fillOpacity, bgColFillOpacity, fillOpacity,
bgColFillColor2, fillColor2,
bgColFillOpacity2, fillOpacity2,
bgColGradient, gradient,
bgColBorderColor, borderColor, bgColBorderColor, borderColor,
bgColBorderOpacity, borderOpacity, bgColBorderOpacity, borderOpacity,
bgColText, "", bgColText, "",
@@ -878,6 +926,7 @@ void background_duplicate(GtkWidget *widget, gpointer data)
bgColBorderSidesRight, sideRight, bgColBorderSidesRight, sideRight,
-1); -1);
g_boxed_free(GDK_TYPE_COLOR, fillColor); g_boxed_free(GDK_TYPE_COLOR, fillColor);
g_boxed_free(GDK_TYPE_COLOR, fillColor2);
g_boxed_free(GDK_TYPE_COLOR, borderColor); g_boxed_free(GDK_TYPE_COLOR, borderColor);
g_boxed_free(GDK_TYPE_COLOR, fillColorOver); g_boxed_free(GDK_TYPE_COLOR, fillColorOver);
g_boxed_free(GDK_TYPE_COLOR, borderColorOver); g_boxed_free(GDK_TYPE_COLOR, borderColorOver);
@@ -926,12 +975,18 @@ void background_update_image(int index)
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
GdkColor *fillColor; GdkColor *fillColor;
int fillOpacity = 50; int fillOpacity = 50;
GdkColor *fillColor2;
int fillOpacity2 = 50;
gboolean gradient = FALSE;
GdkColor *borderColor; GdkColor *borderColor;
int borderOpacity = 100; int borderOpacity = 100;
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor, bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity, bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor, bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity, bgColBorderOpacity, &borderOpacity,
bgColBorderWidth, &b, bgColBorderWidth, &b,
@@ -941,11 +996,17 @@ void background_update_image(int index)
double bg_r, bg_g, bg_b, bg_a; double bg_r, bg_g, bg_b, bg_a;
gdkColor2CairoColor(*fillColor, &bg_r, &bg_g, &bg_b); gdkColor2CairoColor(*fillColor, &bg_r, &bg_g, &bg_b);
bg_a = fillOpacity / 100.0; bg_a = fillOpacity / 100.0;
double bg_r2, bg_g2, bg_b2, bg_a2;
gdkColor2CairoColor(*fillColor2, &bg_r2, &bg_g2, &bg_b2);
bg_a2 = fillOpacity2 / 100.0;
double b_r, b_g, b_b, b_a; double b_r, b_g, b_b, b_a;
gdkColor2CairoColor(*borderColor, &b_r, &b_g, &b_b); gdkColor2CairoColor(*borderColor, &b_r, &b_g, &b_b);
b_a = borderOpacity / 100.0; b_a = borderOpacity / 100.0;
g_boxed_free(GDK_TYPE_COLOR, fillColor); g_boxed_free(GDK_TYPE_COLOR, fillColor);
g_boxed_free(GDK_TYPE_COLOR, fillColor2);
g_boxed_free(GDK_TYPE_COLOR, borderColor); g_boxed_free(GDK_TYPE_COLOR, borderColor);
GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24); GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24);
@@ -966,8 +1027,19 @@ void background_update_image(int index)
cairo_arc(cr, r + b, r + b, r, 180 * degrees, 270 * degrees); cairo_arc(cr, r + b, r + b, r, 180 * degrees, 270 * degrees);
cairo_close_path(cr); cairo_close_path(cr);
cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a); if (gradient) {
cairo_fill_preserve(cr); cairo_pattern_t *gpat;
gpat = cairo_pattern_create_linear(0, 0, 0, h - b);
cairo_pattern_add_color_stop_rgba(gpat, 0.1, bg_r, bg_g, bg_b, bg_a);
cairo_pattern_add_color_stop_rgba(gpat, 0.9, bg_r2, bg_g2, bg_b2, bg_a2);
cairo_set_source(cr, gpat);
cairo_fill_preserve(cr);
cairo_pattern_destroy(gpat);
} else {
cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a);
cairo_fill_preserve(cr);
}
cairo_set_source_rgba(cr, b_r, b_g, b_b, b_a); cairo_set_source_rgba(cr, b_r, b_g, b_b, b_a);
cairo_set_line_width(cr, b); cairo_set_line_width(cr, b);
cairo_stroke(cr); cairo_stroke(cr);
@@ -1019,10 +1091,16 @@ void background_update(GtkWidget *widget, gpointer data)
GdkColor fillColor; GdkColor fillColor;
int fillOpacity; int fillOpacity;
GdkColor fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor borderColor; GdkColor borderColor;
int borderOpacity; int borderOpacity;
gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color), &fillColor); gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color), &fillColor);
fillOpacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color)) * 100.0 / 0xffff); fillOpacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color)) * 100.0 / 0xffff);
gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color2), &fillColor2);
fillOpacity2 = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color2)) * 100.0 / 0xffff);
gradient = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_gradient));
gtk_color_button_get_color(GTK_COLOR_BUTTON(background_border_color), &borderColor); gtk_color_button_get_color(GTK_COLOR_BUTTON(background_border_color), &borderColor);
borderOpacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_border_color)) * 100.0 / 0xffff); borderOpacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_border_color)) * 100.0 / 0xffff);
@@ -1048,6 +1126,9 @@ void background_update(GtkWidget *widget, gpointer data)
bgColPixbuf, NULL, bgColPixbuf, NULL,
bgColFillColor, &fillColor, bgColFillColor, &fillColor,
bgColFillOpacity, fillOpacity, bgColFillOpacity, fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, fillOpacity2,
bgColGradient, gradient,
bgColBorderColor, &borderColor, bgColBorderColor, &borderColor,
bgColBorderOpacity, borderOpacity, bgColBorderOpacity, borderOpacity,
bgColFillColorOver, &fillColorOver, bgColFillColorOver, &fillColorOver,
@@ -1093,6 +1174,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
GdkColor *fillColor; GdkColor *fillColor;
int fillOpacity; int fillOpacity;
GdkColor *fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor *borderColor; GdkColor *borderColor;
int borderOpacity; int borderOpacity;
GdkColor *fillColorOver; GdkColor *fillColorOver;
@@ -1108,6 +1192,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor, bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity, bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor, bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity, bgColBorderOpacity, &borderOpacity,
bgColFillColorOver, &fillColorOver, bgColFillColorOver, &fillColorOver,
@@ -1133,6 +1220,12 @@ void current_background_changed(GtkWidget *widget, gpointer data)
gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color), fillColor); gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color), fillColor);
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color), (fillOpacity*0xffff)/100); gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color), (fillOpacity*0xffff)/100);
gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color2), fillColor2);
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color2), (fillOpacity2*0xffff)/100);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_gradient), gradient);
gtk_color_button_set_color(GTK_COLOR_BUTTON(background_border_color), borderColor); gtk_color_button_set_color(GTK_COLOR_BUTTON(background_border_color), borderColor);
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_border_color), (borderOpacity*0xffff)/100); gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_border_color), (borderOpacity*0xffff)/100);
@@ -1150,6 +1243,7 @@ void current_background_changed(GtkWidget *widget, gpointer data)
gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_corner_radius), r); gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_corner_radius), r);
g_boxed_free(GDK_TYPE_COLOR, fillColor); g_boxed_free(GDK_TYPE_COLOR, fillColor);
g_boxed_free(GDK_TYPE_COLOR, fillColor2);
g_boxed_free(GDK_TYPE_COLOR, borderColor); g_boxed_free(GDK_TYPE_COLOR, borderColor);
g_boxed_free(GDK_TYPE_COLOR, fillColorOver); g_boxed_free(GDK_TYPE_COLOR, fillColorOver);
g_boxed_free(GDK_TYPE_COLOR, borderColorOver); g_boxed_free(GDK_TYPE_COLOR, borderColorOver);
@@ -1789,6 +1883,11 @@ void create_panel_items(GtkWidget *parent)
itemsColValue, "F", itemsColValue, "F",
-1); -1);
gtk_list_store_append(all_items, &iter); gtk_list_store_append(all_items, &iter);
gtk_list_store_set(all_items, &iter,
itemsColName, _("Separator"),
itemsColValue, ":",
-1);
gtk_list_store_append(all_items, &iter);
gtk_list_store_set(all_items, &iter, gtk_list_store_set(all_items, &iter,
itemsColName, _("Executor"), itemsColName, _("Executor"),
itemsColValue, "E", itemsColValue, "E",
@@ -1951,7 +2050,9 @@ void set_panel_items(const char *items)
{ {
gtk_list_store_clear(panel_items); gtk_list_store_clear(panel_items);
int separator_index = -1;
int execp_index = -1; int execp_index = -1;
for (; items && *items; items++) { for (; items && *items; items++) {
const char *value = NULL; const char *value = NULL;
const char *name = NULL; const char *name = NULL;
@@ -1976,6 +2077,12 @@ void set_panel_items(const char *items)
} else if (v == 'F') { } else if (v == 'F') {
value = "F"; value = "F";
name = _("Free space"); name = _("Free space");
} else if (v == ':') {
separator_index++;
buffer[0] = 0;
sprintf(buffer, "%s %d", _("Separator"), separator_index + 1);
name = buffer;
value = ":";
} else if (v == 'E') { } else if (v == 'E') {
execp_index++; execp_index++;
buffer[0] = 0; buffer[0] = 0;
@@ -2009,7 +2116,17 @@ void panel_add_item(GtkWidget *widget, gpointer data)
itemsColValue, &value, itemsColValue, &value,
-1); -1);
if (!panel_contains(value) || g_str_equal(value, "E")) { if (!panel_contains(value) || g_str_equal(value, ":")) {
GtkTreeIter iter;
gtk_list_store_append(panel_items, &iter);
gtk_list_store_set(panel_items, &iter,
itemsColName, g_strdup(name),
itemsColValue, g_strdup(value),
-1);
if (g_str_equal(value, ":")) {
separator_create_new();
}
} else if (!panel_contains(value) || g_str_equal(value, "E")) {
GtkTreeIter iter; GtkTreeIter iter;
gtk_list_store_append(panel_items, &iter); gtk_list_store_append(panel_items, &iter);
gtk_list_store_set(panel_items, &iter, gtk_list_store_set(panel_items, &iter,
@@ -2021,6 +2138,7 @@ void panel_add_item(GtkWidget *widget, gpointer data)
} }
} }
} }
separator_update_indices();
execp_update_indices(); execp_update_indices();
} }
@@ -2038,7 +2156,15 @@ void panel_remove_item(GtkWidget *widget, gpointer data)
itemsColValue, &value, itemsColValue, &value,
-1); -1);
if (g_str_equal(value, "E")) { if (g_str_equal(value, ":")) {
for (int i = 0; i < separators->len; i++) {
Separator *separator = &g_array_index(separators, Separator, i);
if (g_str_equal(name, separator->name)) {
separator_remove(i);
break;
}
}
} else if (g_str_equal(value, "E")) {
for (int i = 0; i < executors->len; i++) { for (int i = 0; i < executors->len; i++) {
Executor *executor = &g_array_index(executors, Executor, i); Executor *executor = &g_array_index(executors, Executor, i);
if (g_str_equal(name, executor->name)) { if (g_str_equal(name, executor->name)) {
@@ -2051,6 +2177,7 @@ void panel_remove_item(GtkWidget *widget, gpointer data)
gtk_list_store_remove(panel_items, &iter); gtk_list_store_remove(panel_items, &iter);
} }
separator_update_indices();
execp_update_indices(); execp_update_indices();
} }
@@ -2075,7 +2202,22 @@ void panel_move_item_down(GtkWidget *widget, gpointer data)
itemsColValue, &value2, itemsColValue, &value2,
-1); -1);
if (g_str_equal(value1, "E") && g_str_equal(value2, "E")) { if (g_str_equal(value1, ":") && g_str_equal(value2, ":")) {
Separator *separator1 = NULL;
Separator *separator2 = NULL;
for (int i = 0; i < separators->len; i++) {
Separator *separator = &g_array_index(separators, Separator, i);
if (g_str_equal(name1, separator->name)) {
separator1 = separator;
}
if (g_str_equal(name2, separator->name)) {
separator2 = separator;
}
}
Separator tmp = *separator1;
*separator1 = *separator2;
*separator2 = tmp;
} else if (g_str_equal(value1, "E") && g_str_equal(value2, "E")) {
Executor *executor1 = NULL; Executor *executor1 = NULL;
Executor *executor2 = NULL; Executor *executor2 = NULL;
for (int i = 0; i < executors->len; i++) { for (int i = 0; i < executors->len; i++) {
@@ -2095,6 +2237,7 @@ void panel_move_item_down(GtkWidget *widget, gpointer data)
gtk_list_store_swap(panel_items, &iter, &next); gtk_list_store_swap(panel_items, &iter, &next);
} }
} }
separator_update_indices();
execp_update_indices(); execp_update_indices();
} }
@@ -2120,7 +2263,22 @@ void panel_move_item_up(GtkWidget *widget, gpointer data)
itemsColValue, &value2, itemsColValue, &value2,
-1); -1);
if (g_str_equal(value1, "E") && g_str_equal(value2, "E")) { if (g_str_equal(value1, ":") && g_str_equal(value2, ":")) {
Separator *separator1 = NULL;
Separator *separator2 = NULL;
for (int i = 0; i < separators->len; i++) {
Separator *separator = &g_array_index(separators, Separator, i);
if (g_str_equal(name1, separator->name)) {
separator1 = separator;
}
if (g_str_equal(name2, separator->name)) {
separator2 = separator;
}
}
Separator tmp = *separator1;
*separator1 = *separator2;
*separator2 = tmp;
} else if (g_str_equal(value1, "E") && g_str_equal(value2, "E")) {
Executor *executor1 = NULL; Executor *executor1 = NULL;
Executor *executor2 = NULL; Executor *executor2 = NULL;
for (int i = 0; i < executors->len; i++) { for (int i = 0; i < executors->len; i++) {
@@ -2141,6 +2299,7 @@ void panel_move_item_up(GtkWidget *widget, gpointer data)
} }
} }
} }
separator_update_indices();
execp_update_indices(); execp_update_indices();
} }
@@ -3503,7 +3662,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), _("Close"));
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Toggle")); 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), _("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), _("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), _("Maximize or restore"));
gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Desktop left")); gtk_combo_box_append_text(GTK_COMBO_BOX(task_mouse_middle), _("Desktop left"));
@@ -4340,6 +4499,76 @@ void create_clock(GtkWidget *parent)
change_paragraph(parent); change_paragraph(parent);
} }
void create_separator(GtkWidget *notebook, int i)
{
GtkWidget *label;
GtkWidget *table;
int row, col;
GtkTooltips *tooltips = gtk_tooltips_new();
Separator *separator = &g_array_index(separators, Separator, i);
separator->name[0] = 0;
sprintf(separator->name, "%s %d", _("Separator"), i + 1);
separator->page_label = gtk_label_new(separator->name);
gtk_widget_show(separator->page_label);
separator->page_separator = gtk_vbox_new(FALSE, DEFAULT_HOR_SPACING);
separator->container = addScrollBarToWidget(separator->page_separator);
gtk_container_set_border_width(GTK_CONTAINER(separator->page_separator), 10);
gtk_widget_show(separator->page_separator);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), separator->container, separator->page_label);
GtkWidget *parent = separator->page_separator;
table = gtk_table_new(1, 2, FALSE);
gtk_widget_show(table);
gtk_box_pack_start(GTK_BOX(parent), table, FALSE, FALSE, 0);
gtk_table_set_row_spacings(GTK_TABLE(table), ROW_SPACING);
gtk_table_set_col_spacings(GTK_TABLE(table), COL_SPACING);
row = 0, col = 2;
label = gtk_label_new(_("<b>Format</b>"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
gtk_widget_show(label);
gtk_box_pack_start(GTK_BOX(parent), label, FALSE, FALSE, 0);
table = gtk_table_new(3, 10, FALSE);
gtk_widget_show(table);
gtk_box_pack_start(GTK_BOX(parent), table, FALSE, FALSE, 0);
gtk_table_set_row_spacings(GTK_TABLE(table), ROW_SPACING);
gtk_table_set_col_spacings(GTK_TABLE(table), COL_SPACING);
row = 0, col = 2;
label = gtk_label_new(_("Foreground color"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
separator->separator_color = gtk_color_button_new();
gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(separator->separator_color), TRUE);
gtk_widget_show(separator->separator_color);
gtk_table_attach(GTK_TABLE(table), separator->separator_color, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, separator->separator_color, _("Specifies separator's color."), NULL);
row++, col = 2;
label = gtk_label_new(_("Separator style"));
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
separator->separator_style = gtk_spin_button_new_with_range(0, 6, 1);
gtk_widget_show(separator->separator_style);
gtk_table_attach(GTK_TABLE(table), separator->separator_style, col, col+1, row, row+1, GTK_FILL, 0, 0, 0);
col++;
gtk_tooltips_set_tip(tooltips, separator->separator_style, _("Specifies separator's appearance. 0 is empty/invisible separator."), NULL);
change_paragraph(parent);
}
void create_execp(GtkWidget *notebook, int i) void create_execp(GtkWidget *notebook, int i)
{ {
GtkWidget *label; GtkWidget *label;
@@ -4716,12 +4945,25 @@ void create_execp(GtkWidget *notebook, int i)
change_paragraph(parent); change_paragraph(parent);
} }
void separator_create_new()
{
g_array_set_size(separators, separators->len + 1);
create_separator(notebook, separators->len - 1);
}
void execp_create_new() void execp_create_new()
{ {
g_array_set_size(executors, executors->len + 1); g_array_set_size(executors, executors->len + 1);
create_execp(notebook, executors->len - 1); create_execp(notebook, executors->len - 1);
} }
Separator *separator_get_last()
{
if (separators->len <= 0)
separator_create_new();
return &g_array_index(separators, Separator, separators->len - 1);
}
Executor *execp_get_last() Executor *execp_get_last()
{ {
if (executors->len <= 0) if (executors->len <= 0)
@@ -4729,6 +4971,21 @@ Executor *execp_get_last()
return &g_array_index(executors, Executor, executors->len - 1); return &g_array_index(executors, Executor, executors->len - 1);
} }
void separator_remove(int i)
{
Separator *separator = &g_array_index(separators, Separator, i);
for (int i_page = 0; i_page < gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); i_page++) {
GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i_page);
if (page == separator->container) {
gtk_widget_hide(page);
gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), i_page);
}
}
separators = g_array_remove_index(separators, i);
}
void execp_remove(int i) void execp_remove(int i)
{ {
Executor *executor = &g_array_index(executors, Executor, i); Executor *executor = &g_array_index(executors, Executor, i);
@@ -4744,6 +5001,43 @@ void execp_remove(int i)
executors = g_array_remove_index(executors, i); executors = g_array_remove_index(executors, i);
} }
void separator_update_indices()
{
for (int i = 0; i < separators->len; i++) {
Separator *separator = &g_array_index(separators, Separator, i);
sprintf(separator->name, "%s %d", _("Separator"), i + 1);
gtk_label_set_text(GTK_LABEL(separator->page_label), separator->name);
}
GtkTreeModel *model = GTK_TREE_MODEL(panel_items);
GtkTreeIter iter;
if (!gtk_tree_model_get_iter_first(model, &iter))
return;
int separator_index = -1;
while (1) {
gchar *name;
gchar *value;
gtk_tree_model_get(model, &iter,
itemsColName, &name,
itemsColValue, &value,
-1);
if (g_str_equal(value, ":")) {
separator_index++;
char buffer[256];
buffer[0] = 0;
sprintf(buffer, "%s %d", _("Separator"), separator_index + 1);
gtk_list_store_set(panel_items, &iter,
itemsColName, buffer,
-1);
}
if (!gtk_tree_model_iter_next(model, &iter))
break;
}
}
void execp_update_indices() void execp_update_indices()
{ {
for (int i = 0; i < executors->len; i++) { for (int i = 0; i < executors->len; i++) {

View File

@@ -118,6 +118,19 @@ extern GtkWidget *tooltip_task_show, *tooltip_show_after, *tooltip_hide_after;
extern GtkWidget *clock_format_tooltip, *clock_tmz_tooltip; extern GtkWidget *clock_format_tooltip, *clock_tmz_tooltip;
extern GtkWidget *tooltip_background; extern GtkWidget *tooltip_background;
// Separator
typedef struct Separator {
char name[256];
GtkWidget *container;
GtkWidget *page_separator;
GtkWidget *page_label;
GtkWidget *separator_background;
GtkWidget *separator_color;
GtkWidget *separator_style;
} Separator;
extern GArray *separators;
// Executor // Executor
typedef struct Executor { typedef struct Executor {
char name[256]; char name[256];
@@ -166,6 +179,9 @@ enum {
bgColPixbuf = 0, bgColPixbuf = 0,
bgColFillColor, bgColFillColor,
bgColFillOpacity, bgColFillOpacity,
bgColFillColor2,
bgColFillOpacity2,
bgColGradient,
bgColBorderColor, bgColBorderColor,
bgColBorderOpacity, bgColBorderOpacity,
bgColBorderWidth, bgColBorderWidth,
@@ -189,6 +205,8 @@ enum {
extern GtkListStore *backgrounds; extern GtkListStore *backgrounds;
extern GtkWidget *current_background, extern GtkWidget *current_background,
*background_fill_color, *background_fill_color,
*background_fill_color2,
*background_gradient,
*background_border_color, *background_border_color,
*background_fill_color_over, *background_fill_color_over,
*background_border_color_over, *background_border_color_over,
@@ -207,6 +225,11 @@ int background_index_safe(int index);
GtkWidget *create_properties(); GtkWidget *create_properties();
void separator_create_new();
Separator *separator_get_last();
void separator_remove(int i);
void separator_update_indices();
void execp_create_new(); void execp_create_new();
Executor *execp_get_last(); Executor *execp_get_last();
void execp_remove(int i); void execp_remove(int i);

View File

@@ -23,6 +23,7 @@ int no_items_systray_enabled;
int no_items_battery_enabled; int no_items_battery_enabled;
static int num_bg; static int num_bg;
static int read_bg_color2;
static int read_bg_color_hover; static int read_bg_color_hover;
static int read_border_color_hover; static int read_border_color_hover;
static int read_bg_color_press; static int read_bg_color_press;
@@ -121,6 +122,9 @@ void config_write_backgrounds(FILE *fp)
gboolean sideRight; gboolean sideRight;
GdkColor *fillColor; GdkColor *fillColor;
int fillOpacity; int fillOpacity;
GdkColor *fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor *borderColor; GdkColor *borderColor;
int borderOpacity; int borderOpacity;
GdkColor *fillColorOver; GdkColor *fillColorOver;
@@ -136,6 +140,9 @@ void config_write_backgrounds(FILE *fp)
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor, bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity, bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor, bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity, bgColBorderOpacity, &borderOpacity,
bgColFillColorOver, &fillColorOver, bgColFillColorOver, &fillColorOver,
@@ -170,7 +177,12 @@ void config_write_backgrounds(FILE *fp)
strcat(sides, "R"); strcat(sides, "R");
fprintf(fp, "border_sides = %s\n", sides); fprintf(fp, "border_sides = %s\n", sides);
// This is a workaround. For some reason, there was a problem while storing fillOpacity2
//fillOpacity2 = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color2)) * 100.0 / 0xffff);
config_write_color(fp, "background_color", *fillColor, fillOpacity); config_write_color(fp, "background_color", *fillColor, fillOpacity);
config_write_color(fp, "background_color2", *fillColor2, fillOpacity2);
fprintf(fp, "gradient = %d\n", gradient);
config_write_color(fp, "border_color", *borderColor, borderOpacity); config_write_color(fp, "border_color", *borderColor, borderOpacity);
config_write_color(fp, "background_color_hover", *fillColorOver, fillOpacityOver); config_write_color(fp, "background_color_hover", *fillColorOver, fillOpacityOver);
config_write_color(fp, "border_color_hover", *borderColorOver, borderOpacityOver); config_write_color(fp, "border_color_hover", *borderColorOver, borderOpacityOver);
@@ -669,6 +681,26 @@ void config_write_battery(FILE *fp)
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
void config_write_separator(FILE *fp)
{
for (int i = 0; i < separators->len; i++) {
fprintf(fp, "#-------------------------------------\n");
fprintf(fp, "# Separator %d\n", i + 1);
Separator *separator = &g_array_index(separators, Separator, i);
fprintf(fp, "separator = new\n");
GdkColor color;
gtk_color_button_get_color(GTK_COLOR_BUTTON(separator->separator_color), &color);
config_write_color(fp,
"separator_color",
color,
gtk_color_button_get_alpha(GTK_COLOR_BUTTON(separator->separator_color)) * 100 / 0xffff);
fprintf(fp, "separator_style = %d\n", (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(separator->separator_style)));
fprintf(fp, "\n");
}
}
void config_write_execp(FILE *fp) void config_write_execp(FILE *fp)
{ {
for (int i = 0; i < executors->len; i++) { for (int i = 0; i < executors->len; i++) {
@@ -788,6 +820,7 @@ void config_save_file(const char *path) {
config_write_launcher(fp); config_write_launcher(fp);
config_write_clock(fp); config_write_clock(fp);
config_write_battery(fp); config_write_battery(fp);
config_write_separator(fp);
config_write_execp(fp); config_write_execp(fp);
config_write_tooltip(fp); config_write_tooltip(fp);
@@ -829,6 +862,14 @@ gboolean config_is_manual(const char *path)
void finalize_bg() void finalize_bg()
{ {
if (num_bg > 0) { if (num_bg > 0) {
if (!read_bg_color2) {
GdkColor fillColor;
gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color),&fillColor);
gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color2), &fillColor);
int fillOpacity = gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color2));
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color2), fillOpacity);
background_force_update();
}
if (!read_bg_color_hover) { if (!read_bg_color_hover) {
GdkColor fillColor; GdkColor fillColor;
gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color), &fillColor); gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color), &fillColor);
@@ -874,6 +915,7 @@ void add_entry(char *key, char *value)
finalize_bg(); finalize_bg();
background_create_new(); background_create_new();
num_bg++; num_bg++;
read_bg_color2 = 0;
read_bg_color_hover = 0; read_bg_color_hover = 0;
read_border_color_hover = 0; read_border_color_hover = 0;
read_bg_color_press = 0; read_bg_color_press = 0;
@@ -894,6 +936,19 @@ void add_entry(char *key, char *value)
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color), (alpha*65535)/100); gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color), (alpha*65535)/100);
background_force_update(); background_force_update();
} }
else if (strcmp(key, "background_color2") == 0) {
extract_values(value, &value1, &value2, &value3);
GdkColor col;
hex2gdk(value1, &col);
gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color2), &col);
int alpha = value2 ? atoi(value2) : 50;
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color2), (alpha*65535)/100);
background_force_update();
read_bg_color2 = 1;
}
else if (strcmp(key, "gradient") == 0 ) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_gradient), atoi(value));
}
else if (strcmp(key, "border_color") == 0) { else if (strcmp(key, "border_color") == 0) {
extract_values(value, &value1, &value2, &value3); extract_values(value, &value1, &value2, &value3);
GdkColor col; GdkColor col;
@@ -1671,6 +1726,24 @@ void add_entry(char *key, char *value)
set_action(value, task_mouse_scroll_down); set_action(value, task_mouse_scroll_down);
} }
/* Separator */
else if (strcmp(key, "separator") == 0) {
separator_create_new();
}
else if (strcmp(key, "separator_color") == 0) {
extract_values(value, &value1, &value2, &value3);
GdkColor col;
hex2gdk(value1, &col);
gtk_color_button_set_color(GTK_COLOR_BUTTON(separator_get_last()->separator_color), &col);
if (value2) {
int alpha = atoi(value2);
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(separator_get_last()->separator_color), (alpha*65535)/100);
}
}
else if (strcmp(key, "separator_style") == 0) {
gtk_spin_button_set_value(GTK_SPIN_BUTTON(separator_get_last()->separator_style), atoi(value));
}
/* Executor */ /* Executor */
else if (strcmp(key, "execp") == 0) { else if (strcmp(key, "execp") == 0) {
execp_create_new(); execp_create_new();

View File

@@ -438,9 +438,18 @@ void draw(Area *a)
void draw_background(Area *a, cairo_t *c) void draw_background(Area *a, cairo_t *c)
{ {
if (a->bg->fill_color.alpha > 0.0 || if ((a->bg->fill_color.alpha > 0.0) ||
(panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect))) { (panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect)) ||
if (a->mouse_state == MOUSE_OVER) (area_has_gradient_fill(a))) {
cairo_pattern_t *cairo_gradient_pattern;
if (area_has_gradient_fill(a)) {
cairo_gradient_pattern = cairo_pattern_create_linear(0.0, 0.0, 0.0, a->height - top_bottom_border_width(a));
cairo_pattern_add_color_stop_rgba(cairo_gradient_pattern, 0.1, a->bg->fill_color.rgb[0], a->bg->fill_color.rgb[1], a->bg->fill_color.rgb[2], a->bg->fill_color.alpha);
cairo_pattern_add_color_stop_rgba(cairo_gradient_pattern, 0.9, a->bg->fill_color2.rgb[0], a->bg->fill_color2.rgb[1], a->bg->fill_color2.rgb[2], a->bg->fill_color2.alpha);
cairo_set_source(c, cairo_gradient_pattern);
} else if (a->mouse_state == MOUSE_OVER)
cairo_set_source_rgba(c, cairo_set_source_rgba(c,
a->bg->fill_color_hover.rgb[0], a->bg->fill_color_hover.rgb[0],
a->bg->fill_color_hover.rgb[1], a->bg->fill_color_hover.rgb[1],
@@ -467,6 +476,8 @@ void draw_background(Area *a, cairo_t *c)
a->bg->border.radius - a->bg->border.width / 1.571); a->bg->border.radius - a->bg->border.width / 1.571);
cairo_fill(c); cairo_fill(c);
if (area_has_gradient_fill(a))
cairo_pattern_destroy(cairo_gradient_pattern);
} }
if (a->bg->border.width > 0) { if (a->bg->border.width > 0) {
@@ -814,3 +825,18 @@ void area_dump_geometry(Area *area, int indent)
area_dump_geometry((Area *)l->data, indent); area_dump_geometry((Area *)l->data, indent);
} }
} }
gboolean area_has_gradient_fill(Area *area)
{
if (!area->bg->gradient)
return FALSE;
else if ((area->bg->fill_color.alpha <= 0.0 ) && (area->bg->fill_color2.alpha <= 0.0))
return FALSE;
else if ((area->bg->fill_color.rgb[0] == area->bg->fill_color2.rgb[0]) &&
(area->bg->fill_color.rgb[1] == area->bg->fill_color2.rgb[1]) &&
(area->bg->fill_color.rgb[2] == area->bg->fill_color2.rgb[2]) &&
(area->bg->fill_color.alpha == area->bg->fill_color2.alpha))
return FALSE;
else return TRUE;
}

View File

@@ -147,6 +147,8 @@ typedef struct Border {
typedef struct Background { typedef struct Background {
// Normal state // Normal state
Color fill_color; Color fill_color;
Color fill_color2;
gboolean gradient;
Border border; Border border;
// On mouse hover // On mouse hover
Color fill_color_hover; Color fill_color_hover;
@@ -314,4 +316,6 @@ void area_dump_geometry(Area *area, int indent);
void mouse_over(Area *area, int pressed); void mouse_over(Area *area, int pressed);
void mouse_out(); void mouse_out();
gboolean area_has_gradient_fill(Area *area);
#endif #endif

View File

@@ -86,6 +86,8 @@ void load_cache(Cache *cache, const gchar *cache_path)
if (parse_line(line, &key, &value)) { if (parse_line(line, &key, &value)) {
g_hash_table_insert(cache->_table, g_strdup(key), g_strdup(value)); g_hash_table_insert(cache->_table, g_strdup(key), g_strdup(value));
free(key);
free(value);
} }
} }
free(line); free(line);

View File

@@ -73,15 +73,15 @@ void copy_file(const char *path_src, const char *path_dest)
fclose(file_src); 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; char *a, *b;
/* Skip useless lines */ /* Skip useless lines */
if ((line[0] == '#') || (line[0] == '\n')) if ((line[0] == '#') || (line[0] == '\n'))
return 0; return FALSE;
if (!(a = strchr(line, '='))) if (!(a = strchr(line, '=')))
return 0; return FALSE;
/* overwrite '=' with '\0' */ /* overwrite '=' with '\0' */
a[0] = '\0'; a[0] = '\0';
@@ -96,7 +96,7 @@ int parse_line(const char *line, char **key, char **value)
g_strstrip(*key); g_strstrip(*key);
g_strstrip(*value); g_strstrip(*value);
return 1; return TRUE;
} }
void tint_exec(const char *command) void tint_exec(const char *command)
@@ -673,3 +673,13 @@ GSList *slist_remove_duplicates(GSList *list, GCompareFunc eq, GDestroyNotify fr
return new_list; return new_list;
} }
gint cmp_ptr(gconstpointer a, gconstpointer b)
{
if (a < b)
return -1;
else if (a == b)
return 0;
else
return 1;
}

View File

@@ -48,7 +48,7 @@ void copy_file(const char *path_src, const char *path_dest);
// Strips key and value. // Strips key and value.
// Values may contain spaces and the equal sign. // Values may contain spaces and the equal sign.
// Returns 1 if both key and value could be read, zero otherwise. // 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); 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); 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) \ #define free_and_null(p) \
{ \ { \
free(p); \ free(p); \

View File

@@ -21,5 +21,6 @@ po
src/tint2conf/po src/tint2conf/po
src/freespace src/freespace
src/execplugin src/execplugin
src/separator
themes themes
doc doc