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/execplugin
src/freespace
src/separator
${X11_INCLUDE_DIRS}
${PANGOCAIRO_INCLUDE_DIRS}
${PANGO_INCLUDE_DIRS}
@@ -114,6 +115,7 @@ set( SOURCES src/config.c
src/tooltip/tooltip.c
src/execplugin/execplugin.c
src/freespace/freespace.c
src/separator/separator.c
src/util/area.c
src/util/common.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
- Fixes:
- 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 "tooltip.h"
#include "timer.h"
#include "separator.h"
#include "execplugin.h"
#ifdef ENABLE_BATTERY
@@ -71,6 +72,8 @@ char *snapshot_path;
// detect if it's an old config file (==1)
static gboolean new_config_file;
static gboolean read_bg_color2;
static gboolean read_bg_gradient;
static gboolean read_bg_color_hover;
static gboolean read_border_color_hover;
static gboolean read_bg_color_press;
@@ -202,6 +205,15 @@ void load_launcher_app_dir(const char *path)
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()
{
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
if (backgrounds->len > 0) {
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)
memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color));
if (!read_border_color_hover)
@@ -233,6 +249,8 @@ void add_entry(char *key, char *value)
init_background(&bg);
bg.border.radius = atoi(value);
g_array_append_val(backgrounds, bg);
read_bg_color2 = 0;
read_bg_gradient = 0;
read_bg_color_hover = 0;
read_border_color_hover = 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);
else
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) {
Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1);
extract_values(value, &value1, &value2, &value3);
@@ -527,6 +558,22 @@ void add_entry(char *key, char *value)
#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 */
else if (strcmp(key, "execp") == 0) {
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) {
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)
memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color));
if (!read_border_color_hover)

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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;

View File

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

View File

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

View File

@@ -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();
}
@@ -1641,9 +1636,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 +1659,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();
}
}

View File

@@ -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 "

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -1148,7 +1148,7 @@ msgid "Middle click"
msgstr ""
#: ../properties.c:3506
msgid "sShade"
msgid "Shade"
msgstr ""
#: ../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 *tooltip_background;
// Separators
GArray *separators;
// Executors
GArray *executors;
@@ -141,6 +144,8 @@ GtkWidget *launcher_icon_theme_override;
GtkListStore *backgrounds;
GtkWidget *current_background,
*background_fill_color,
*background_fill_color2,
*background_gradient,
*background_border_color,
*background_fill_color_over,
*background_border_color_over,
@@ -185,6 +190,7 @@ void create_task_status(GtkWidget *notebook,
GtkWidget **task_status_icon_brightness,
GtkWidget **task_status_background,
GtkWidget **task_status_background_set);
void create_separator(GtkWidget *parent, int i);
void create_execp(GtkWidget *parent, int i);
void create_clock(GtkWidget *parent);
void create_systemtray(GtkWidget *parent);
@@ -256,6 +262,7 @@ GtkWidget *create_properties()
tooltips = gtk_tooltips_new();
(void) tooltips;
separators = g_array_new(FALSE, TRUE, sizeof(Separator));
executors = g_array_new(FALSE, TRUE, sizeof(Executor));
// global layer
@@ -497,6 +504,9 @@ void create_background(GtkWidget *parent)
GTK_TYPE_INT,
GDK_TYPE_COLOR,
GTK_TYPE_INT,
GTK_TYPE_BOOL,
GDK_TYPE_COLOR,
GTK_TYPE_INT,
GTK_TYPE_INT,
GTK_TYPE_INT,
GTK_TYPE_STRING,
@@ -571,6 +581,26 @@ void create_background(GtkWidget *parent)
col++;
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;
label = gtk_label_new(_("Border color"));
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(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_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);
@@ -749,6 +781,10 @@ void background_create_new()
GdkColor fillColor;
cairoColor2GdkColor(0, 0, 0, &fillColor);
int fillOpacity = 0;
GdkColor fillColor2;
cairoColor2GdkColor(0, 0, 0, &fillColor2);
int fillOpacity2 = 0;
gboolean gradient = FALSE;
GdkColor borderColor;
cairoColor2GdkColor(0, 0, 0, &borderColor);
int borderOpacity = 0;
@@ -775,6 +811,9 @@ void background_create_new()
bgColPixbuf, NULL,
bgColFillColor, &fillColor,
bgColFillOpacity, fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, fillOpacity2,
bgColGradient, gradient,
bgColBorderColor, &borderColor,
bgColBorderOpacity, borderOpacity,
bgColBorderWidth, b,
@@ -822,6 +861,9 @@ void background_duplicate(GtkWidget *widget, gpointer data)
gboolean sideRight;
GdkColor *fillColor;
int fillOpacity;
GdkColor *fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor *borderColor;
int borderOpacity;
GdkColor *fillColorOver;
@@ -836,6 +878,9 @@ void background_duplicate(GtkWidget *widget, gpointer data)
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity,
bgColFillColorOver, &fillColorOver,
@@ -859,6 +904,9 @@ void background_duplicate(GtkWidget *widget, gpointer data)
bgColPixbuf, NULL,
bgColFillColor, fillColor,
bgColFillOpacity, fillOpacity,
bgColFillColor2, fillColor2,
bgColFillOpacity2, fillOpacity2,
bgColGradient, gradient,
bgColBorderColor, borderColor,
bgColBorderOpacity, borderOpacity,
bgColText, "",
@@ -878,6 +926,7 @@ void background_duplicate(GtkWidget *widget, gpointer data)
bgColBorderSidesRight, sideRight,
-1);
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, fillColorOver);
g_boxed_free(GDK_TYPE_COLOR, borderColorOver);
@@ -926,12 +975,18 @@ void background_update_image(int index)
GdkPixbuf *pixbuf;
GdkColor *fillColor;
int fillOpacity = 50;
GdkColor *fillColor2;
int fillOpacity2 = 50;
gboolean gradient = FALSE;
GdkColor *borderColor;
int borderOpacity = 100;
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity,
bgColBorderWidth, &b,
@@ -941,11 +996,17 @@ void background_update_image(int index)
double bg_r, bg_g, bg_b, bg_a;
gdkColor2CairoColor(*fillColor, &bg_r, &bg_g, &bg_b);
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;
gdkColor2CairoColor(*borderColor, &b_r, &b_g, &b_b);
b_a = borderOpacity / 100.0;
g_boxed_free(GDK_TYPE_COLOR, fillColor);
g_boxed_free(GDK_TYPE_COLOR, fillColor2);
g_boxed_free(GDK_TYPE_COLOR, borderColor);
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_close_path(cr);
cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a);
cairo_fill_preserve(cr);
if (gradient) {
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_line_width(cr, b);
cairo_stroke(cr);
@@ -1019,10 +1091,16 @@ void background_update(GtkWidget *widget, gpointer data)
GdkColor fillColor;
int fillOpacity;
GdkColor fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor borderColor;
int borderOpacity;
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);
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);
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,
bgColFillColor, &fillColor,
bgColFillOpacity, fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, fillOpacity2,
bgColGradient, gradient,
bgColBorderColor, &borderColor,
bgColBorderOpacity, borderOpacity,
bgColFillColorOver, &fillColorOver,
@@ -1093,6 +1174,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
GdkColor *fillColor;
int fillOpacity;
GdkColor *fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor *borderColor;
int borderOpacity;
GdkColor *fillColorOver;
@@ -1108,6 +1192,9 @@ void current_background_changed(GtkWidget *widget, gpointer data)
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity,
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_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_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);
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, fillColorOver);
g_boxed_free(GDK_TYPE_COLOR, borderColorOver);
@@ -1789,6 +1883,11 @@ void create_panel_items(GtkWidget *parent)
itemsColValue, "F",
-1);
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,
itemsColName, _("Executor"),
itemsColValue, "E",
@@ -1951,7 +2050,9 @@ void set_panel_items(const char *items)
{
gtk_list_store_clear(panel_items);
int separator_index = -1;
int execp_index = -1;
for (; items && *items; items++) {
const char *value = NULL;
const char *name = NULL;
@@ -1976,6 +2077,12 @@ void set_panel_items(const char *items)
} else if (v == 'F') {
value = "F";
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') {
execp_index++;
buffer[0] = 0;
@@ -2009,7 +2116,17 @@ void panel_add_item(GtkWidget *widget, gpointer data)
itemsColValue, &value,
-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;
gtk_list_store_append(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();
}
@@ -2038,7 +2156,15 @@ void panel_remove_item(GtkWidget *widget, gpointer data)
itemsColValue, &value,
-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++) {
Executor *executor = &g_array_index(executors, Executor, i);
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);
}
separator_update_indices();
execp_update_indices();
}
@@ -2075,7 +2202,22 @@ void panel_move_item_down(GtkWidget *widget, gpointer data)
itemsColValue, &value2,
-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 *executor2 = NULL;
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);
}
}
separator_update_indices();
execp_update_indices();
}
@@ -2120,7 +2263,22 @@ void panel_move_item_up(GtkWidget *widget, gpointer data)
itemsColValue, &value2,
-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 *executor2 = NULL;
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();
}
@@ -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), _("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"));
@@ -4340,6 +4499,76 @@ void create_clock(GtkWidget *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)
{
GtkWidget *label;
@@ -4716,12 +4945,25 @@ void create_execp(GtkWidget *notebook, int i)
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()
{
g_array_set_size(executors, 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()
{
if (executors->len <= 0)
@@ -4729,6 +4971,21 @@ Executor *execp_get_last()
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)
{
Executor *executor = &g_array_index(executors, Executor, i);
@@ -4744,6 +5001,43 @@ void execp_remove(int 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()
{
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 *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
typedef struct Executor {
char name[256];
@@ -166,6 +179,9 @@ enum {
bgColPixbuf = 0,
bgColFillColor,
bgColFillOpacity,
bgColFillColor2,
bgColFillOpacity2,
bgColGradient,
bgColBorderColor,
bgColBorderOpacity,
bgColBorderWidth,
@@ -189,6 +205,8 @@ enum {
extern GtkListStore *backgrounds;
extern GtkWidget *current_background,
*background_fill_color,
*background_fill_color2,
*background_gradient,
*background_border_color,
*background_fill_color_over,
*background_border_color_over,
@@ -207,6 +225,11 @@ int background_index_safe(int index);
GtkWidget *create_properties();
void separator_create_new();
Separator *separator_get_last();
void separator_remove(int i);
void separator_update_indices();
void execp_create_new();
Executor *execp_get_last();
void execp_remove(int i);

View File

@@ -23,6 +23,7 @@ int no_items_systray_enabled;
int no_items_battery_enabled;
static int num_bg;
static int read_bg_color2;
static int read_bg_color_hover;
static int read_border_color_hover;
static int read_bg_color_press;
@@ -121,6 +122,9 @@ void config_write_backgrounds(FILE *fp)
gboolean sideRight;
GdkColor *fillColor;
int fillOpacity;
GdkColor *fillColor2;
int fillOpacity2;
gboolean gradient;
GdkColor *borderColor;
int borderOpacity;
GdkColor *fillColorOver;
@@ -136,6 +140,9 @@ void config_write_backgrounds(FILE *fp)
gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter,
bgColFillColor, &fillColor,
bgColFillOpacity, &fillOpacity,
bgColFillColor2, &fillColor2,
bgColFillOpacity2, &fillOpacity2,
bgColGradient, &gradient,
bgColBorderColor, &borderColor,
bgColBorderOpacity, &borderOpacity,
bgColFillColorOver, &fillColorOver,
@@ -170,7 +177,12 @@ void config_write_backgrounds(FILE *fp)
strcat(sides, "R");
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_color2", *fillColor2, fillOpacity2);
fprintf(fp, "gradient = %d\n", gradient);
config_write_color(fp, "border_color", *borderColor, borderOpacity);
config_write_color(fp, "background_color_hover", *fillColorOver, fillOpacityOver);
config_write_color(fp, "border_color_hover", *borderColorOver, borderOpacityOver);
@@ -669,6 +681,26 @@ void config_write_battery(FILE *fp)
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)
{
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_clock(fp);
config_write_battery(fp);
config_write_separator(fp);
config_write_execp(fp);
config_write_tooltip(fp);
@@ -829,6 +862,14 @@ gboolean config_is_manual(const char *path)
void finalize_bg()
{
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) {
GdkColor 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();
background_create_new();
num_bg++;
read_bg_color2 = 0;
read_bg_color_hover = 0;
read_border_color_hover = 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);
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) {
extract_values(value, &value1, &value2, &value3);
GdkColor col;
@@ -1671,6 +1726,24 @@ void add_entry(char *key, char *value)
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 */
else if (strcmp(key, "execp") == 0) {
execp_create_new();

View File

@@ -438,9 +438,18 @@ void draw(Area *a)
void draw_background(Area *a, cairo_t *c)
{
if (a->bg->fill_color.alpha > 0.0 ||
(panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect))) {
if (a->mouse_state == MOUSE_OVER)
if ((a->bg->fill_color.alpha > 0.0) ||
(panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect)) ||
(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,
a->bg->fill_color_hover.rgb[0],
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);
cairo_fill(c);
if (area_has_gradient_fill(a))
cairo_pattern_destroy(cairo_gradient_pattern);
}
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);
}
}
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 {
// Normal state
Color fill_color;
Color fill_color2;
gboolean gradient;
Border border;
// On mouse 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_out();
gboolean area_has_gradient_fill(Area *area);
#endif

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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); \

View File

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