Taskbar: code cleanup

This commit is contained in:
o9000 2016-01-08 23:43:53 +01:00
parent d08606dc93
commit 92bd9e9184
9 changed files with 117 additions and 143 deletions

View file

@ -782,9 +782,9 @@ void add_entry(char *key, char *value)
/* 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) {

View file

@ -261,10 +261,10 @@ void init_panel()
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 @@ void set_panel_background(Panel *p)
if (taskbarname_enabled)
l = l->next;
for (; l; l = l->next) {
set_task_redraw((Task *)l->data);
schedule_redraw((Area *)l->data);
}
}
}

View file

@ -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 *add_task(Window win)
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 @@ void remove_task(Task *task)
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,27 +227,23 @@ gboolean get_title(Task *task)
}
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]) {
imlib_context_set_image(task->icon[k]);
@ -258,8 +252,10 @@ void get_icon(Task *task)
}
}
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 @@ void get_icon(Task *task)
#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 @@ void get_icon(Task *task)
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 @@ void get_icon(Task *task)
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 @@ void get_icon(Task *task)
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 @@ void get_icon(Task *task)
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 @@ void draw_task_icon(Task *task, int text_width)
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 @@ void draw_task(void *obj, cairo_t *c)
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 @@ void draw_task(void *obj, cairo_t *c)
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 @@ void on_change_task(void *obj)
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 @@ void reset_active_task()
// 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 @@ void set_task_state(Task *task, TaskState state)
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 @@ void set_task_state(Task *task, TaskState state)
}
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 @@ void set_task_state(Task *task, TaskState state)
}
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;
@ -599,11 +588,6 @@ void set_task_state(Task *task, TaskState state)
}
}
void set_task_redraw(Task *task)
{
schedule_redraw(&task->area);
}
void blink_urgent(void *arg)
{
GSList *urgent_task = urgent_list;
@ -629,7 +613,7 @@ void add_urgent(Task *task)
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;

View file

@ -22,16 +22,11 @@ typedef enum TaskState {
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 @@ typedef struct GlobalTask {
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 @@ typedef struct 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 @@ typedef struct Task {
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.

View file

@ -33,10 +33,6 @@
#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;
@ -50,6 +46,9 @@ 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)
{
return *((const Window *)key);
@ -117,8 +116,8 @@ void cleanup_taskbar()
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 @@ void init_taskbar_panel(void *p)
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 @@ void init_taskbar_panel(void *p)
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_default_font_changed()
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 @@ void task_refresh_tasklist()
// 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 @@ gboolean resize_taskbar(void *obj)
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 @@ void set_taskbar_state(Taskbar *taskbar, TaskbarState state)
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 @@ void sort_taskbar_for_win(Window win)
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) {

View file

@ -25,9 +25,26 @@ typedef enum TaskbarSortMethod {
TASKBAR_SORT_MRU,
} TaskbarSortMethod;
extern GHashTable *win_to_task;
extern Task *active_task;
extern Task *task_drag;
typedef struct {
Area area;
gchar *name;
int posy;
} TaskbarName;
typedef struct {
Area area;
int desktop;
TaskbarName bar_name;
int text_width;
} Taskbar;
typedef struct GlobalTaskbar {
Area area;
Area area_name;
Background *background[TASKBAR_STATE_COUNT];
Background *background_name[TASKBAR_STATE_COUNT];
} GlobalTaskbar;
extern gboolean taskbar_enabled;
extern gboolean taskbar_distribute_size;
extern gboolean hide_inactive_tasks;
@ -35,51 +52,40 @@ extern gboolean hide_task_diff_monitor;
extern TaskbarSortMethod taskbar_sort_method;
extern Alignment taskbar_alignment;
typedef struct {
Area area;
gchar *name;
int posy;
} Taskbarname;
// 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;
typedef struct {
Area area;
int desktop;
Taskbarname bar_name;
int text_width;
} Taskbar;
extern Task *active_task;
extern Task *task_drag;
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();
// freed memory
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 on_change_taskbar(void *obj);
void set_taskbar_state(Taskbar *taskbar, TaskbarState state);
// show/hide taskbar according to current desktop
void visible_taskbar(void *p);
void sort_taskbar_for_win(Window win);
void sort_tasks(Taskbar *taskbar);
void taskbar_default_font_changed();
// Reloads the entire list of tasks from the window manager and recreates the task buttons.
void taskbar_refresh_tasklist();
// 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);
// 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);
#endif

View file

@ -132,7 +132,7 @@ void cleanup_taskbarname()
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 @@ gboolean resize_taskbarname(void *obj)
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;

View file

@ -957,10 +957,10 @@ void event_property_notify(XEvent *e)
for (int i = 0; i < num_panels; i++) {
init_taskbar_panel(&panels[i]);
set_panel_items_order(&panels[i]);
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 @@ void event_property_notify(XEvent *e)
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 @@ void event_property_notify(XEvent *e)
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 @@ void event_property_notify(XEvent *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 @@ void event_property_notify(XEvent *e)
// 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 @@ void event_property_notify(XEvent *e)
}
// 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 @@ void event_configure_notify(XEvent *e)
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 @@ void event_configure_notify(XEvent *e)
// '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 @@ void event_configure_notify(XEvent *e)
}
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) {

View file

@ -75,7 +75,7 @@ gboolean window_is_hidden(Window win)
// 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;
}