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
This commit is contained in:
o9000 2015-03-28 22:38:57 +00:00 committed by mrovi9000@gmail.com
parent 67d5bfcfce
commit e539c6536f
8 changed files with 293 additions and 38 deletions

View file

@ -68,6 +68,7 @@ set( SOURCES src/config.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 )

View file

@ -503,6 +503,15 @@ void add_entry (char *key, char *value)
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)

View file

@ -184,7 +184,10 @@ int get_title(Task *tsk)
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)) {

View file

@ -31,6 +31,7 @@
#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 @@ void default_taskbar()
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 @@ void visible_taskbar(void *p)
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 @@ gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
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 @@ gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
}
}
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);
}
}
}

View file

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

View file

@ -462,7 +462,7 @@ void event_button_motion_notify (XEvent *e)
// 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 @@ void event_button_motion_notify (XEvent *e)
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 @@ void event_property_notify (XEvent *e)
tooltip_copy_text((Area*)tsk);
tooltip_update();
}
if (taskbar_sort_method == TASKBAR_SORT_TITLE)
sort_taskbar_for_win(win);
panel_refresh = 1;
}
}

178
src/util/strnatcmp.c Normal file
View file

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

31
src/util/strnatcmp.h Normal file
View file

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