all repos — tint2 @ e539c6536f243077302fde0990208dc91ccd6c9b

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Sort tasks on taskbar: config + sort by title or center (disabled, work in progress) - issue 478

git-svn-id: http://tint2.googlecode.com/svn/trunk@743 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
o9000 o9000
commit

e539c6536f243077302fde0990208dc91ccd6c9b

parent

67d5bfcfce1f4d1cca337da411d450e8c8279738

M CMakeLists.txtCMakeLists.txt

@@ -68,6 +68,7 @@ src/taskbar/taskbarname.c

src/tooltip/tooltip.c src/util/area.c src/util/common.c + src/util/strnatcmp.c src/util/timer.c src/util/window.c )
M src/config.csrc/config.c

@@ -503,6 +503,15 @@ }

else if (strcmp (key, "taskbar_hide_different_monitor") == 0) { hide_task_diff_monitor = atoi (value); } + else if (strcmp (key, "taskbar_sort_order") == 0) { + if (strcmp(value, "center") == 0) { + taskbar_sort_method = TASKBAR_SORT_CENTER; + } else if (strcmp(value, "title") == 0) { + taskbar_sort_method = TASKBAR_SORT_TITLE; + } else { + taskbar_sort_method = TASKBAR_NOSORT; + } + } /* Task */ else if (strcmp (key, "task_text") == 0)
M src/taskbar/task.csrc/taskbar/task.c

@@ -184,7 +184,10 @@ {

Panel *panel = tsk->area.panel; char *title, *name; - if (!panel->g_task.text && !panel->g_task.tooltip_enabled) return 0; + if (!panel->g_task.text && + !panel->g_task.tooltip_enabled && + taskbar_sort_method != TASKBAR_SORT_TITLE) + return 0; name = server_get_property (tsk->win, server.atom._NET_WM_VISIBLE_NAME, server.atom.UTF8_STRING, 0); if (!name || !strlen(name)) {
M src/taskbar/taskbar.csrc/taskbar/taskbar.c

@@ -31,6 +31,7 @@ #include "taskbar.h"

#include "server.h" #include "window.h" #include "panel.h" +#include "strnatcmp.h" /* win_to_task_table holds for every Window an array of tasks. Usually the array contains only one

@@ -45,7 +46,7 @@ int taskbar_enabled;

int taskbar_distribute_size; int hide_inactive_tasks; int hide_task_diff_monitor; -int sort_tasks_method; +int taskbar_sort_method; guint win_hash(gconstpointer key) { return (guint)*((Window*)key); } gboolean win_compare(gconstpointer a, gconstpointer b) { return (*((Window*)a) == *((Window*)b)); }

@@ -61,7 +62,7 @@ taskbar_enabled = 0;

taskbar_distribute_size = 0; hide_inactive_tasks = 0; hide_task_diff_monitor = 0; - sort_tasks_method = TASKBAR_NOSORT; + taskbar_sort_method = TASKBAR_NOSORT; default_taskbarname(); }

@@ -410,10 +411,9 @@ }

panel_refresh = 1; } -gint compare_tasks(Task *a, Task *b, Taskbar *taskbar) +#define NONTRIVIAL 2 +gint compare_tasks_trivial(Task *a, Task *b, Taskbar *taskbar) { - int a_horiz_c, a_vert_c, b_horiz_c, b_vert_c; - if (a == b) return 0; if (taskbarname_enabled) {

@@ -422,6 +422,15 @@ return -1;

if (b == taskbar->area.list->data) return 1; } + return NONTRIVIAL; +} + +gint compare_task_centers(Task *a, Task *b, Taskbar *taskbar) +{ + int trivial = compare_tasks_trivial(a, b, taskbar); + if (trivial != NONTRIVIAL) + return trivial; + int a_horiz_c, a_vert_c, b_horiz_c, b_vert_c; a_horiz_c = a->win_x + a->win_w / 2; b_horiz_c = b->win_x + b->win_w / 2; a_vert_c = a->win_y + a->win_h / 2;

@@ -439,17 +448,38 @@ return a_horiz_c - b_horiz_c;

} } +gint compare_task_titles(Task *a, Task *b, Taskbar *taskbar) +{ + int trivial = compare_tasks_trivial(a, b, taskbar); + if (trivial != NONTRIVIAL) + return trivial; + return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : ""); +} + +gint compare_tasks(Task *a, Task *b, Taskbar *taskbar) +{ + int trivial = compare_tasks_trivial(a, b, taskbar); + if (trivial != NONTRIVIAL) + return trivial; + if (taskbar_sort_method == TASKBAR_NOSORT) { + return 0; + } else if (taskbar_sort_method == TASKBAR_SORT_CENTER) { + return compare_task_centers(a, b, taskbar); + } else if (taskbar_sort_method == TASKBAR_SORT_TITLE) { + return compare_task_titles(a, b, taskbar); + } + return 0; +} + int taskbar_needs_sort(Taskbar *taskbar) { - if (sort_tasks_method == TASKBAR_NOSORT) + if (taskbar_sort_method == TASKBAR_NOSORT) return 0; - if (sort_tasks_method == TASKBAR_SORT_POSITION) { - GSList *i, *j; - for (i = taskbar->area.list, j = i ? i->next : NULL; i && j; i = i->next, j = j->next) { - if (compare_tasks(i->data, j->data, taskbar) > 0) { - return 1; - } + GSList *i, *j; + for (i = taskbar->area.list, j = i ? i->next : NULL; i && j; i = i->next, j = j->next) { + if (compare_tasks(i->data, j->data, taskbar) > 0) { + return 1; } }

@@ -460,34 +490,35 @@ void sort_tasks(Taskbar *taskbar)

{ if (!taskbar) return; - if (!taskbar_needs_sort(taskbar)) + if (!taskbar_needs_sort(taskbar)) { return; - if (sort_tasks_method == TASKBAR_SORT_POSITION) { - taskbar->area.list = g_slist_sort_with_data(taskbar->area.list, (GCompareDataFunc)compare_tasks, taskbar); - taskbar->area.resize = 1; - panel_refresh = 1; } + taskbar->area.list = g_slist_sort_with_data(taskbar->area.list, (GCompareDataFunc)compare_tasks, taskbar); + taskbar->area.resize = 1; + panel_refresh = 1; + ((Panel*)taskbar->area.panel)->area.resize = 1; } void sort_taskbar_for_win(Window win) { - if (sort_tasks_method == TASKBAR_SORT_POSITION) { - GPtrArray* task_group = task_get_tasks(win); - if (task_group) { - int i; - Task* tsk0 = g_ptr_array_index(task_group, 0); - if (tsk0) { - window_get_coordinates(win, &tsk0->win_x, &tsk0->win_y, &tsk0->win_w, &tsk0->win_h); - } - for (i = 0; i < task_group->len; ++i) { - Task* tsk = g_ptr_array_index(task_group, i); - tsk->win_x = tsk0->win_x; - tsk->win_y = tsk0->win_y; - tsk->win_w = tsk0->win_w; - tsk->win_h = tsk0->win_h; - sort_tasks(tsk->area.parent); - } + if (taskbar_sort_method == TASKBAR_NOSORT) + return; + + GPtrArray* task_group = task_get_tasks(win); + if (task_group) { + int i; + Task* tsk0 = g_ptr_array_index(task_group, 0); + if (tsk0) { + window_get_coordinates(win, &tsk0->win_x, &tsk0->win_y, &tsk0->win_w, &tsk0->win_h); + } + for (i = 0; i < task_group->len; ++i) { + Task* tsk = g_ptr_array_index(task_group, i); + tsk->win_x = tsk0->win_x; + tsk->win_y = tsk0->win_y; + tsk->win_w = tsk0->win_w; + tsk->win_h = tsk0->win_h; + sort_tasks(tsk->area.parent); } } }
M src/taskbar/taskbar.hsrc/taskbar/taskbar.h

@@ -19,8 +19,8 @@ extern int taskbar_enabled;

extern int taskbar_distribute_size; extern int hide_inactive_tasks; extern int hide_task_diff_monitor; -enum { TASKBAR_NOSORT, TASKBAR_SORT_POSITION }; -extern int sort_tasks_method; +enum { TASKBAR_NOSORT, TASKBAR_SORT_CENTER, TASKBAR_SORT_TITLE }; +extern int taskbar_sort_method; typedef struct { // always start with area
M src/tint.csrc/tint.c

@@ -462,7 +462,7 @@ Task * event_task = click_task(panel, e->xbutton.x, e->xbutton.y);

// If the event takes place on the same taskbar as the task being dragged if(event_taskbar == task_drag->area.parent) { - if (sort_tasks_method == TASKBAR_SORT_POSITION) { + if (taskbar_sort_method != TASKBAR_NOSORT) { sort_tasks(event_taskbar); } else { // Swap the task_drag with the task on the event's location (if they differ)

@@ -500,7 +500,7 @@ task_drag->desktop = event_taskbar->desktop;

windows_set_desktop(task_drag->win, event_taskbar->desktop); - if (sort_tasks_method == TASKBAR_SORT_POSITION) { + if (taskbar_sort_method != TASKBAR_NOSORT) { sort_tasks(event_taskbar); }

@@ -751,6 +751,8 @@ if (g_tooltip.mapped && (g_tooltip.area == (Area*)tsk)) {

tooltip_copy_text((Area*)tsk); tooltip_update(); } + if (taskbar_sort_method == TASKBAR_SORT_TITLE) + sort_taskbar_for_win(win); panel_refresh = 1; } }
A src/util/strnatcmp.c

@@ -0,0 +1,178 @@

+/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +/* partial change history: + * + * 2004-10-10 mbp: Lift out character type dependencies into macros. + * + * Eric Sosman pointed out that ctype functions take a parameter whose + * value must be that of an unsigned int, even on platforms that have + * negative chars in their default char type. + */ + +#include <ctype.h> +#include <string.h> +#include <assert.h> +#include <stdio.h> + +#include "strnatcmp.h" + + +/* These are defined as macros to make it easier to adapt this code to + * different characters types or comparison functions. */ +static inline int +nat_isdigit(nat_char a) +{ + return isdigit((unsigned char) a); +} + + +static inline int +nat_isspace(nat_char a) +{ + return isspace((unsigned char) a); +} + + +static inline nat_char +nat_toupper(nat_char a) +{ + return toupper((unsigned char) a); +} + + + +static int +compare_right(nat_char const *a, nat_char const *b) +{ + int bias = 0; + + /* The longest run of digits wins. That aside, the greatest + value wins, but we can't know that it will until we've scanned + both numbers to know that they have the same magnitude, so we + remember it in BIAS. */ + for (;; a++, b++) { + if (!nat_isdigit(*a) && !nat_isdigit(*b)) + return bias; + else if (!nat_isdigit(*a)) + return -1; + else if (!nat_isdigit(*b)) + return +1; + else if (*a < *b) { + if (!bias) + bias = -1; + } else if (*a > *b) { + if (!bias) + bias = +1; + } else if (!*a && !*b) + return bias; + } + + return 0; +} + + +static int +compare_left(nat_char const *a, nat_char const *b) +{ + /* Compare two left-aligned numbers: the first to have a + different value wins. */ + for (;; a++, b++) { + if (!nat_isdigit(*a) && !nat_isdigit(*b)) + return 0; + else if (!nat_isdigit(*a)) + return -1; + else if (!nat_isdigit(*b)) + return +1; + else if (*a < *b) + return -1; + else if (*a > *b) + return +1; + } + + return 0; +} + + +static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case) +{ + int ai, bi; + nat_char ca, cb; + int fractional, result; + + assert(a && b); + ai = bi = 0; + while (1) { + ca = a[ai]; cb = b[bi]; + + /* skip over leading spaces or zeros */ + while (nat_isspace(ca)) + ca = a[++ai]; + + while (nat_isspace(cb)) + cb = b[++bi]; + + /* process run of digits */ + if (nat_isdigit(ca) && nat_isdigit(cb)) { + fractional = (ca == '0' || cb == '0'); + + if (fractional) { + if ((result = compare_left(a+ai, b+bi)) != 0) + return result; + } else { + if ((result = compare_right(a+ai, b+bi)) != 0) + return result; + } + } + + if (!ca && !cb) { + /* The strings compare the same. Perhaps the caller + will want to call strcmp to break the tie. */ + return 0; + } + + if (fold_case) { + ca = nat_toupper(ca); + cb = nat_toupper(cb); + } + + if (ca < cb) + return -1; + else if (ca > cb) + return +1; + + ++ai; ++bi; + } +} + + + +int strnatcmp(nat_char const *a, nat_char const *b) { + return strnatcmp0(a, b, 0); +} + + +/* Compare, recognizing numeric string and ignoring case. */ +int strnatcasecmp(nat_char const *a, nat_char const *b) { + return strnatcmp0(a, b, 1); +}
A src/util/strnatcmp.h

@@ -0,0 +1,31 @@

+/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +/* CUSTOMIZATION SECTION + * + * You can change this typedef, but must then also change the inline + * functions in strnatcmp.c */ +typedef char nat_char; + +int strnatcmp(nat_char const *a, nat_char const *b); +int strnatcasecmp(nat_char const *a, nat_char const *b);