Taskbar: code cleanup
@@ -782,9 +782,9 @@ }
/* Task */ else if (strcmp(key, "task_text") == 0) - panel_config.g_task.text = atoi(value); + panel_config.g_task.has_text = atoi(value); else if (strcmp(key, "task_icon") == 0) - panel_config.g_task.icon = atoi(value); + panel_config.g_task.has_icon = atoi(value); else if (strcmp(key, "task_centered") == 0) panel_config.g_task.centered = atoi(value); else if (strcmp(key, "task_width") == 0) {
@@ -261,10 +261,10 @@
if (panel_autohide) autohide_trigger_hide(p); - visible_taskbar(p); + update_taskbar_visibility(p); } - task_refresh_tasklist(); + taskbar_refresh_tasklist(); reset_active_task(); }@@ -755,7 +755,7 @@ GList *l = taskbar->area.children;
if (taskbarname_enabled) l = l->next; for (; l; l = l->next) { - set_task_redraw((Task *)l->data); + schedule_redraw((Area *)l->data); } } }
@@ -48,10 +48,8 @@ Task *add_task(Window win)
{ if (!win) return NULL; - if (window_is_hidden(win)) { - // fprintf(stderr, "%s %d: win = %ld not adding task: window hidden\n", __FUNCTION__, __LINE__, win); + if (window_is_hidden(win)) return NULL; - } XSelectInput(server.display, win, PropertyChangeMask | StructureNotifyMask); XFlush(server.display);@@ -81,8 +79,8 @@ task_template.title = NULL;
for (int k = 0; k < TASK_STATE_COUNT; ++k) { task_template.icon[k] = NULL; } - get_title(&task_template); - get_icon(&task_template); + task_update_title(&task_template); + task_update_icon(&task_template); // fprintf(stderr, "%s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, win, task_template.title ? task_template.title : "??"); // fprintf(stderr, "new task %s win %u: desktop %d, monitor %d\n", new_task.title, win, new_task.desktop, monitor);@@ -194,11 +192,11 @@ }
g_hash_table_remove(win_to_task, &win); } -gboolean get_title(Task *task) +gboolean task_update_title(Task *task) { Panel *panel = task->area.panel; - if (!panel->g_task.text && !panel->g_task.tooltip_enabled && taskbar_sort_method != TASKBAR_SORT_TITLE) + if (!panel->g_task.has_text && !panel->g_task.tooltip_enabled && taskbar_sort_method != TASKBAR_SORT_TITLE) return FALSE; char *name = server_get_property(task->win, server.atom._NET_WM_VISIBLE_NAME, server.atom.UTF8_STRING, 0);@@ -229,26 +227,22 @@ }
} task->title = title; - GPtrArray *task_group = task_get_tasks(task->win); + GPtrArray *task_group = get_task_group(task->win); if (task_group) { for (int i = 0; i < task_group->len; ++i) { Task *task2 = g_ptr_array_index(task_group, i); task2->title = task->title; - set_task_redraw(task2); + schedule_redraw(&task2->area); } } return TRUE; } -void get_icon(Task *task) +void task_update_icon(Task *task) { Panel *panel = task->area.panel; - if (!panel->g_task.icon) + if (!panel->g_task.has_icon) return; - - Imlib_Image img = NULL; - XWMHints *hints = 0; - gulong *data = 0; for (int k = 0; k < TASK_STATE_COUNT; ++k) { if (task->icon[k]) {@@ -258,8 +252,10 @@ task->icon[k] = 0;
} } + Imlib_Image img = NULL; + int i; - data = server_get_property(task->win, server.atom._NET_WM_ICON, XA_CARDINAL, &i); + gulong *data = server_get_property(task->win, server.atom._NET_WM_ICON, XA_CARDINAL, &i); if (data) { // get ARGB icon int w, h;@@ -269,15 +265,16 @@ tmp_data = get_best_icon(data, get_icon_count(data, i), i, &w, &h, panel->g_task.icon_size1);
#ifdef __x86_64__ DATA32 icon_data[w * h]; int length = w * h; - for (i = 0; i < length; ++i) - icon_data[i] = tmp_data[i]; + for (int j = 0; j < length; ++j) + icon_data[j] = tmp_data[j]; img = imlib_create_image_using_copied_data(w, h, icon_data); #else img = imlib_create_image_using_data(w, h, (DATA32 *)tmp_data); #endif + XFree(data); } else { // get Pixmap icon - hints = XGetWMHints(server.display, task->win); + XWMHints *hints = XGetWMHints(server.display, task->win); if (hints) { if (hints->flags & IconPixmapHint && hints->icon_pixmap != 0) { // get width, height and depth for the pixmap@@ -291,6 +288,7 @@ XGetGeometry(server.display, hints->icon_pixmap, &root, &icon_x, &icon_y, &w, &h, &border_width, &bpp);
imlib_context_set_drawable(hints->icon_pixmap); img = imlib_create_image_from_drawable(hints->icon_mask, 0, 0, w, h, 0); } + XFree(hints); } } if (img == NULL) {@@ -304,7 +302,7 @@ imlib_image_set_has_alpha(1);
int w = imlib_image_get_width(); int h = imlib_image_get_height(); Imlib_Image orig_image = - imlib_create_cropped_scaled_image(0, 0, w, h, panel->g_task.icon_size1, panel->g_task.icon_size1); + imlib_create_cropped_scaled_image(0, 0, w, h, panel->g_task.icon_size1, panel->g_task.icon_size1); imlib_free_image(); imlib_context_set_image(orig_image);@@ -339,12 +337,7 @@ }
imlib_context_set_image(orig_image); imlib_free_image(); - if (hints) - XFree(hints); - if (data) - XFree(data); - - GPtrArray *task_group = task_get_tasks(task->win); + GPtrArray *task_group = get_task_group(task->win); if (task_group) { for (i = 0; i < task_group->len; ++i) { Task *task2 = g_ptr_array_index(task_group, i);@@ -355,7 +348,7 @@ task2->icon[k] = task->icon[k];
task2->icon_hover[k] = task->icon_hover[k]; task2->icon_press[k] = task->icon_press[k]; } - set_task_redraw(task2); + schedule_redraw(&task2->area); } } }@@ -370,7 +363,7 @@ // Find pos
int pos_x; Panel *panel = (Panel *)task->area.panel; if (panel->g_task.centered) { - if (panel->g_task.text) + if (panel->g_task.has_text) pos_x = (task->area.width - text_width - panel->g_task.icon_size1) / 2; else pos_x = (task->area.width - panel->g_task.icon_size1) / 2;@@ -403,7 +396,7 @@ Task *task = (Task *)obj;
Panel *panel = (Panel *)task->area.panel; int text_width = 0; - if (panel->g_task.text) { + if (panel->g_task.has_text) { PangoLayout *layout = pango_cairo_create_layout(c); pango_layout_set_font_description(layout, panel->g_task.font_desc); pango_layout_set_text(layout, task->title, -1);@@ -428,9 +421,8 @@
g_object_unref(layout); } - if (panel->g_task.icon) { + if (panel->g_task.has_icon) draw_task_icon(task, text_width); - } } void on_change_task(void *obj)@@ -447,9 +439,6 @@ 32,
PropModeReplace, (unsigned char *)value, 4); - - // reset Pixmap when position/size changed - set_task_redraw(task); } Task *find_active_task(Task *current_task)@@ -531,12 +520,12 @@ Window w1 = get_active_window();
// printf("Change active task %ld\n", w1); if (w1) { - if (!task_get_tasks(w1)) { + if (!get_task_group(w1)) { Window w2; while (XGetTransientForHint(server.display, w1, &w2)) w1 = w2; } - set_task_state((active_task = task_get_task(w1)), TASK_ACTIVE); + set_task_state((active_task = get_task(w1)), TASK_ACTIVE); } }@@ -548,7 +537,7 @@
if (state == TASK_ACTIVE && task->current_state != state) { clock_gettime(CLOCK_MONOTONIC, &task->last_activation_time); if (taskbar_sort_method == TASKBAR_SORT_LRU || taskbar_sort_method == TASKBAR_SORT_MRU) { - GPtrArray *task_group = task_get_tasks(task->win); + GPtrArray *task_group = get_task_group(task->win); if (task_group) { for (int i = 0; i < task_group->len; ++i) { Task *task1 = g_ptr_array_index(task_group, i);@@ -560,7 +549,7 @@ }
} if (task->current_state != state || hide_task_diff_monitor) { - GPtrArray *task_group = task_get_tasks(task->win); + GPtrArray *task_group = get_task_group(task->win); if (task_group) { for (int i = 0; i < task_group->len; ++i) { Task *task1 = g_ptr_array_index(task_group, i);@@ -587,7 +576,7 @@ hide = TRUE;
} if ((!hide) != task1->area.on_screen) { task1->area.on_screen = !hide; - set_task_redraw(task1); + schedule_redraw(&task1->area); Panel *p = (Panel *)task->area.panel; task->area.resize_needed = TRUE; p->taskbar->area.resize_needed = TRUE;@@ -597,11 +586,6 @@ }
panel_refresh = TRUE; } } -} - -void set_task_redraw(Task *task) -{ - schedule_redraw(&task->area); } void blink_urgent(void *arg)@@ -629,7 +613,7 @@ // some programs set urgency hint although they are active
if (active_task && active_task->win == task->win) return; - task = task_get_task(task->win); // always add the first task for a task group (omnipresent windows) + task = get_task(task->win); // always add the first task for a task group (omnipresent windows) task->urgent_tick = 0; if (g_slist_find(urgent_list, task)) return;
@@ -22,16 +22,11 @@ TASK_UNDEFINED,
TASK_STATE_COUNT, } TaskState; -extern timeout *urgent_timeout; -extern GSList *urgent_list; - typedef struct GlobalTask { Area area; - - gboolean text; - gboolean icon; + gboolean has_text; + gboolean has_icon; gboolean centered; - int icon_posy; int icon_size1; int maximum_width;@@ -44,7 +39,6 @@ Background *background[TASK_STATE_COUNT];
int config_background_mask; // starting position for text ~ task_padding + task_border + icon_size double text_posx, text_height; - gboolean has_font; PangoFontDescription *font_desc; Color font[TASK_STATE_COUNT];@@ -54,12 +48,9 @@ } GlobalTask;
// Stores information about a task. // Warning: any dynamically allocated members are shared between the Task instances created for the same window -// (for example, if the task appears on all desktops, there will be a different instance on each desktop's taskbar). +// (if the task appears on all desktops, there will be a different instance on each desktop's taskbar). typedef struct Task { - // always start with area Area area; - - // TODO: group task with list of windows here Window win; int desktop; TaskState current_state;@@ -78,17 +69,19 @@ int win_h;
struct timespec last_activation_time; } Task; +extern timeout *urgent_timeout; +extern GSList *urgent_list; + Task *add_task(Window win); void remove_task(Task *task); void draw_task(void *obj, cairo_t *c); void on_change_task(void *obj); -void get_icon(Task *task); -gboolean get_title(Task *task); +void task_update_icon(Task *task); +gboolean task_update_title(Task *task); void reset_active_task(); void set_task_state(Task *task, TaskState state); -void set_task_redraw(Task *task); // Given a pointer to the task that is currently under the mouse (current_task), // returns a pointer to the Task for the active window on the same taskbar.
@@ -33,10 +33,6 @@ #include "window.h"
#include "panel.h" #include "strnatcmp.h" -/* win_to_task holds for every Window an array of tasks. Usually the array contains only one - element. However for omnipresent windows (windows which are visible in every taskbar) the array - contains to every Task* on each panel a pointer (i.e. GPtrArray.len == server.num_desktops) -*/ GHashTable *win_to_task; Task *active_task;@@ -49,6 +45,9 @@ TaskbarSortMethod taskbar_sort_method;
Alignment taskbar_alignment; void taskbar_init_fonts(); + +// Removes the task with &win = key. +void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data); guint win_hash(gconstpointer key) {@@ -117,8 +116,8 @@ }
void init_taskbar() { - if (!panel_config.g_task.text && !panel_config.g_task.icon) { - panel_config.g_task.text = panel_config.g_task.icon = 1; + if (!panel_config.g_task.has_text && !panel_config.g_task.has_icon) { + panel_config.g_task.has_text = panel_config.g_task.has_icon = 1; } if (!win_to_task)@@ -159,7 +158,6 @@ panel->g_taskbar.area.panel = panel;
panel->g_taskbar.area.size_mode = LAYOUT_DYNAMIC; panel->g_taskbar.area.alignment = taskbar_alignment; panel->g_taskbar.area._resize = resize_taskbar; - panel->g_taskbar.area._on_change_layout = on_change_taskbar; panel->g_taskbar.area.resize_needed = 1; panel->g_taskbar.area.on_screen = TRUE; if (panel_horizontal) {@@ -262,7 +260,7 @@ panel->g_task.maximum_width = server.monitors[panel->monitor].width;
panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr; panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy); - if (panel->g_task.icon) { + if (panel->g_task.has_icon) { panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy); panel->g_task.text_posx += panel->g_task.icon_size1 + panel->g_task.area.paddingx; panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;@@ -326,25 +324,25 @@ }
void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data) { - remove_task(task_get_task(*(Window *)key)); + remove_task(get_task(*(Window *)key)); } -Task *task_get_task(Window win) +Task *get_task(Window win) { - GPtrArray *task_group = task_get_tasks(win); + GPtrArray *task_group = get_task_group(win); if (task_group) return g_ptr_array_index(task_group, 0); return NULL; } -GPtrArray *task_get_tasks(Window win) +GPtrArray *get_task_group(Window win) { if (win_to_task && taskbar_enabled) return g_hash_table_lookup(win_to_task, &win); return NULL; } -void task_refresh_tasklist() +void taskbar_refresh_tasklist() { if (!taskbar_enabled) return;@@ -368,7 +366,7 @@ g_list_free(win_list);
// Add any new for (int i = 0; i < num_results; i++) - if (!task_get_task(win[i])) + if (!get_task(win[i])) add_task(win[i]); XFree(win);@@ -404,12 +402,6 @@ }
return FALSE; } -void on_change_taskbar(void *obj) -{ - Taskbar *taskbar = (Taskbar *)obj; - schedule_redraw(&taskbar->area); -} - void set_taskbar_state(Taskbar *taskbar, TaskbarState state) { taskbar->area.bg = panels[0].g_taskbar.background[state];@@ -433,19 +425,18 @@ GList *l = taskbar->area.children;
if (taskbarname_enabled) l = l->next; for (; l; l = l->next) - set_task_redraw((Task *)l->data); + schedule_redraw((Area *)l->data); } } panel_refresh = TRUE; } -void visible_taskbar(void *p) +void update_taskbar_visibility(void *p) { Panel *panel = (Panel *)p; - Taskbar *taskbar; for (int j = 0; j < panel->num_desktops; j++) { - taskbar = &panel->taskbar[j]; + Taskbar *taskbar = &panel->taskbar[j]; if (taskbar_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) { // SINGLE_DESKTOP and not current desktop taskbar->area.on_screen = FALSE;@@ -575,7 +566,7 @@ {
if (taskbar_sort_method == TASKBAR_NOSORT) return; - GPtrArray *task_group = task_get_tasks(win); + GPtrArray *task_group = get_task_group(win); if (task_group) { Task *task0 = g_ptr_array_index(task_group, 0); if (task0) {
@@ -25,61 +25,67 @@ TASKBAR_SORT_LRU,
TASKBAR_SORT_MRU, } TaskbarSortMethod; -extern GHashTable *win_to_task; -extern Task *active_task; -extern Task *task_drag; -extern gboolean taskbar_enabled; -extern gboolean taskbar_distribute_size; -extern gboolean hide_inactive_tasks; -extern gboolean hide_task_diff_monitor; -extern TaskbarSortMethod taskbar_sort_method; -extern Alignment taskbar_alignment; - typedef struct { Area area; gchar *name; int posy; -} Taskbarname; +} TaskbarName; typedef struct { Area area; int desktop; - Taskbarname bar_name; + TaskbarName bar_name; int text_width; } Taskbar; typedef struct GlobalTaskbar { - // always start with area Area area; Area area_name; Background *background[TASKBAR_STATE_COUNT]; Background *background_name[TASKBAR_STATE_COUNT]; } GlobalTaskbar; -// default global data -void default_taskbar(); +extern gboolean taskbar_enabled; +extern gboolean taskbar_distribute_size; +extern gboolean hide_inactive_tasks; +extern gboolean hide_task_diff_monitor; +extern TaskbarSortMethod taskbar_sort_method; +extern Alignment taskbar_alignment; -// freed memory -void cleanup_taskbar(); +// win_to_task holds for every Window an array of tasks. Usually the array contains only one +// element. However for omnipresent windows (windows which are visible in every taskbar) the array +// contains to every Task* on each panel a pointer (i.e. GPtrArray.len == server.num_desktops) +extern GHashTable *win_to_task; +extern Task *active_task; +extern Task *task_drag; + +void default_taskbar(); +void cleanup_taskbar(); void init_taskbar(); void init_taskbar_panel(void *p); -void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data); -Task *task_get_task(Window win); -GPtrArray *task_get_tasks(Window win); -void task_refresh_tasklist(); +gboolean resize_taskbar(void *obj); +void taskbar_default_font_changed(); + +// Reloads the entire list of tasks from the window manager and recreates the task buttons. +void taskbar_refresh_tasklist(); -gboolean resize_taskbar(void *obj); -void on_change_taskbar(void *obj); +// Returns the task button for this window. If there are multiple buttons, returns the first one. +Task *get_task(Window win); + +// Returns the task group, i.e. the set of task buttons for this window, usually having only one element. +// However for windows shown on all desktops, there is one button for each taskbar (usually only one visible). +GPtrArray *get_task_group(Window win); + void set_taskbar_state(Taskbar *taskbar, TaskbarState state); -// show/hide taskbar according to current desktop -void visible_taskbar(void *p); +// Updates the visibility of each taskbar when the current desktop changes. +void update_taskbar_visibility(void *p); +// Sorts the taskbar(s) on which the window is present. void sort_taskbar_for_win(Window win); -void sort_tasks(Taskbar *taskbar); -void taskbar_default_font_changed(); +void sort_tasks(Taskbar *taskbar); #endif
@@ -132,7 +132,7 @@ }
gboolean resize_taskbarname(void *obj) { - Taskbarname *taskbar_name = obj; + TaskbarName *taskbar_name = obj; Panel *panel = taskbar_name->area.panel; int name_height, name_width, name_height_ink; int ret = 0;@@ -170,7 +170,7 @@ }
void draw_taskbarname(void *obj, cairo_t *c) { - Taskbarname *taskbar_name = obj; + TaskbarName *taskbar_name = obj; Taskbar *taskbar = taskbar_name->area.parent; PangoLayout *layout; Color *config_text = (taskbar->desktop == server.desktop) ? &taskbarname_active_font : &taskbarname_font;
@@ -957,10 +957,10 @@ init_taskbar();
for (int i = 0; i < num_panels; i++) { init_taskbar_panel(&panels[i]); set_panel_items_order(&panels[i]); - visible_taskbar(&panels[i]); + update_taskbar_visibility(&panels[i]); panels[i].area.resize_needed = 1; } - task_refresh_tasklist(); + taskbar_refresh_tasklist(); reset_active_task(); panel_refresh = TRUE; } else if (old_desktop != server.desktop) {@@ -1009,7 +1009,7 @@
g_hash_table_iter_init(&iter, win_to_task); while (g_hash_table_iter_next(&iter, &key, &value)) { Window task_win = *(Window *)key; - Task *task = task_get_task(task_win); + Task *task = get_task(task_win); if (task) { int desktop = get_window_desktop(task_win); if (desktop != task->desktop) {@@ -1029,7 +1029,7 @@ // Window list
else if (at == server.atom._NET_CLIENT_LIST) { if (debug) fprintf(stderr, "%s %d: win = root, atom = _NET_CLIENT_LIST\n", __FUNCTION__, __LINE__); - task_refresh_tasklist(); + taskbar_refresh_tasklist(); panel_refresh = TRUE; } // Change active@@ -1054,7 +1054,7 @@ systray_property_notify(traywin, e);
return; } - Task *task = task_get_task(win); + Task *task = get_task(win); if (debug) { char *atom_name = XGetAtomName(server.display, at); fprintf(stderr, "%s %d: win = %ld, task = %s, atom = %s\n", __FUNCTION__, __LINE__, win, task ? (task->title ? task->title : "??") : "null", atom_name);@@ -1079,7 +1079,7 @@ // printf("atom root_win = %s, %s\n", XGetAtomName(server.display, at), task->title);
// Window title changed if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) { - if (get_title(task)) { + if (task_update_title(task)) { if (g_tooltip.mapped && (g_tooltip.area == (Area *)task)) { tooltip_copy_text((Area *)task); tooltip_update();@@ -1118,7 +1118,7 @@ panel_refresh = TRUE;
} // Window icon changed else if (at == server.atom._NET_WM_ICON) { - get_icon(task); + task_update_icon(task); panel_refresh = TRUE; } // Window desktop changed@@ -1157,7 +1157,7 @@ {
Window win = e->xconfigure.window; if (0) { - Task *task = task_get_task(win); + Task *task = get_task(win); fprintf(stderr, "%s %d: win = %ld, task = %s\n", __FUNCTION__, __LINE__, win, task ? (task->title ? task->title : "??") : "null"); }@@ -1175,7 +1175,7 @@ }
// 'win' move in another monitor if (num_panels > 1 || hide_task_diff_monitor) { - Task *task = task_get_task(win); + Task *task = get_task(win); if (task) { Panel *p = task->area.panel; int monitor = get_window_monitor(win);@@ -1194,7 +1194,7 @@ }
} if (server.viewports) { - Task *task = task_get_task(win); + Task *task = get_task(win); if (task) { int desktop = get_window_desktop(win); if (task->desktop != desktop) {
@@ -75,7 +75,7 @@ }
// do not add transient_for windows if the transient window is already in the taskbar window = win; while (XGetTransientForHint(server.display, window, &window)) { - if (task_get_tasks(window)) { + if (get_task_group(window)) { XFree(at); return TRUE; }