2008-10-02 18:47:02 +00:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Tint2 : taskbar
|
2009-01-17 14:07:56 +00:00
|
|
|
*
|
2010-11-02 11:40:50 +00:00
|
|
|
* Copyright (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) from Omega distribution
|
2009-01-17 14:07:56 +00:00
|
|
|
*
|
2008-10-02 18:47:02 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License version 2
|
|
|
|
* as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <Imlib2.h>
|
|
|
|
|
2009-02-07 23:28:13 +00:00
|
|
|
#include "task.h"
|
2008-10-02 18:47:02 +00:00
|
|
|
#include "taskbar.h"
|
|
|
|
#include "server.h"
|
|
|
|
#include "window.h"
|
|
|
|
#include "panel.h"
|
2015-03-28 22:38:57 +00:00
|
|
|
#include "strnatcmp.h"
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-11-21 03:35:12 +00:00
|
|
|
GHashTable *win_to_task;
|
2010-01-09 18:29:00 +00:00
|
|
|
|
2015-11-21 03:35:12 +00:00
|
|
|
Task *active_task;
|
2010-04-23 14:37:39 +00:00
|
|
|
Task *task_drag;
|
2015-11-20 22:28:37 +00:00
|
|
|
gboolean taskbar_enabled;
|
|
|
|
gboolean taskbar_distribute_size;
|
2017-06-20 03:06:37 +00:00
|
|
|
gboolean hide_task_diff_desktop;
|
2015-11-20 22:28:37 +00:00
|
|
|
gboolean hide_inactive_tasks;
|
|
|
|
gboolean hide_task_diff_monitor;
|
2016-09-04 13:55:51 +00:00
|
|
|
gboolean hide_taskbar_if_empty;
|
2016-01-10 13:40:24 +00:00
|
|
|
gboolean always_show_all_desktop_tasks;
|
2015-11-20 22:28:37 +00:00
|
|
|
TaskbarSortMethod taskbar_sort_method;
|
|
|
|
Alignment taskbar_alignment;
|
|
|
|
|
2015-12-12 14:13:32 +00:00
|
|
|
void taskbar_init_fonts();
|
2016-10-09 13:21:56 +00:00
|
|
|
int taskbar_compute_desired_size(void *obj);
|
2015-12-12 14:13:32 +00:00
|
|
|
|
2016-01-08 22:53:44 +00:00
|
|
|
// Removes the task with &win = key. The other args are ignored.
|
|
|
|
void taskbar_remove_task(Window *win);
|
2016-01-08 22:43:53 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
guint win_hash(gconstpointer key)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
return *((const Window *)key);
|
2015-11-20 22:28:37 +00:00
|
|
|
}
|
2015-11-21 03:35:12 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
gboolean win_compare(gconstpointer a, gconstpointer b)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
return (*((const Window *)a) == *((const Window *)b));
|
2015-11-20 22:28:37 +00:00
|
|
|
}
|
2015-11-21 03:35:12 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void free_ptr_array(gpointer data)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
g_ptr_array_free(data, 1);
|
2015-11-20 22:28:37 +00:00
|
|
|
}
|
2010-04-16 18:50:03 +00:00
|
|
|
|
2010-04-18 12:07:36 +00:00
|
|
|
void default_taskbar()
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
win_to_task = NULL;
|
|
|
|
urgent_timeout = NULL;
|
|
|
|
urgent_list = NULL;
|
|
|
|
taskbar_enabled = FALSE;
|
|
|
|
taskbar_distribute_size = FALSE;
|
2017-06-20 03:06:37 +00:00
|
|
|
hide_task_diff_desktop = FALSE;
|
2017-04-13 12:07:23 +00:00
|
|
|
hide_inactive_tasks = FALSE;
|
|
|
|
hide_task_diff_monitor = FALSE;
|
|
|
|
hide_taskbar_if_empty = FALSE;
|
|
|
|
always_show_all_desktop_tasks = FALSE;
|
|
|
|
taskbar_sort_method = TASKBAR_NOSORT;
|
|
|
|
taskbar_alignment = ALIGN_LEFT;
|
|
|
|
default_taskbarname();
|
2010-04-18 12:07:36 +00:00
|
|
|
}
|
|
|
|
|
2009-02-07 23:28:13 +00:00
|
|
|
void cleanup_taskbar()
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (win_to_task) {
|
|
|
|
while (g_hash_table_size(win_to_task)) {
|
|
|
|
GHashTableIter iter;
|
|
|
|
gpointer key, value;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, win_to_task);
|
|
|
|
if (g_hash_table_iter_next(&iter, &key, &value)) {
|
|
|
|
taskbar_remove_task(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_hash_table_destroy(win_to_task);
|
|
|
|
win_to_task = NULL;
|
|
|
|
}
|
|
|
|
cleanup_taskbarname();
|
|
|
|
for (int i = 0; i < num_panels; i++) {
|
|
|
|
Panel *panel = &panels[i];
|
|
|
|
for (int j = 0; j < panel->num_desktops; j++) {
|
|
|
|
Taskbar *taskbar = &panel->taskbar[j];
|
|
|
|
free_area(&taskbar->area);
|
|
|
|
// remove taskbar from the panel
|
|
|
|
remove_area((Area *)taskbar);
|
|
|
|
}
|
|
|
|
if (panel->taskbar) {
|
|
|
|
free(panel->taskbar);
|
|
|
|
panel->taskbar = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slist_free(urgent_list);
|
|
|
|
urgent_list = NULL;
|
|
|
|
|
|
|
|
stop_timeout(urgent_timeout);
|
|
|
|
|
|
|
|
for (int state = 0; state < TASK_STATE_COUNT; state++) {
|
|
|
|
g_list_free(panel_config.g_task.gradient[state]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int state = 0; state < TASKBAR_STATE_COUNT; state++) {
|
|
|
|
g_list_free(panel_config.g_taskbar.gradient[state]);
|
|
|
|
g_list_free(panel_config.g_taskbar.gradient_name[state]);
|
|
|
|
}
|
2009-02-07 23:28:13 +00:00
|
|
|
}
|
|
|
|
|
2010-09-18 18:06:29 +00:00
|
|
|
void init_taskbar()
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
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;
|
|
|
|
}
|
2015-12-27 14:39:39 +00:00
|
|
|
|
2017-04-13 12:07:23 +00:00
|
|
|
if (!win_to_task)
|
|
|
|
win_to_task = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
|
2010-09-18 18:06:29 +00:00
|
|
|
|
2017-04-13 12:07:23 +00:00
|
|
|
active_task = 0;
|
|
|
|
task_drag = 0;
|
2010-09-18 18:06:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void init_taskbar_panel(void *p)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
Panel *panel = (Panel *)p;
|
|
|
|
|
|
|
|
if (!panel->g_taskbar.background[TASKBAR_NORMAL]) {
|
|
|
|
panel->g_taskbar.background[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
|
|
|
|
panel->g_taskbar.background[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
|
|
|
|
}
|
|
|
|
if (!panel->g_taskbar.background_name[TASKBAR_NORMAL]) {
|
|
|
|
panel->g_taskbar.background_name[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
|
|
|
|
panel->g_taskbar.background_name[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
|
|
|
|
}
|
|
|
|
if (!panel->g_task.area.bg)
|
|
|
|
panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
|
|
|
|
taskbar_init_fonts();
|
|
|
|
|
|
|
|
// taskbar name
|
|
|
|
panel->g_taskbar.area_name.panel = panel;
|
|
|
|
snprintf(panel->g_taskbar.area_name.name, sizeof(panel->g_taskbar.area_name.name), "Taskbarname");
|
|
|
|
panel->g_taskbar.area_name.size_mode = LAYOUT_FIXED;
|
|
|
|
panel->g_taskbar.area_name._resize = resize_taskbarname;
|
|
|
|
panel->g_taskbar.area_name._is_under_mouse = full_width_area_is_under_mouse;
|
|
|
|
panel->g_taskbar.area_name._draw_foreground = draw_taskbarname;
|
|
|
|
panel->g_taskbar.area_name._on_change_layout = 0;
|
|
|
|
panel->g_taskbar.area_name.resize_needed = 1;
|
|
|
|
panel->g_taskbar.area_name.on_screen = TRUE;
|
|
|
|
|
|
|
|
// taskbar
|
|
|
|
panel->g_taskbar.area.parent = panel;
|
|
|
|
panel->g_taskbar.area.panel = panel;
|
|
|
|
snprintf(panel->g_taskbar.area.name, sizeof(panel->g_taskbar.area.name), "Taskbar");
|
|
|
|
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._compute_desired_size = taskbar_compute_desired_size;
|
|
|
|
panel->g_taskbar.area._is_under_mouse = full_width_area_is_under_mouse;
|
|
|
|
panel->g_taskbar.area.resize_needed = 1;
|
|
|
|
panel->g_taskbar.area.on_screen = TRUE;
|
|
|
|
if (panel_horizontal) {
|
|
|
|
panel->g_taskbar.area.posy = top_border_width(&panel->area) + panel->area.paddingy;
|
|
|
|
panel->g_taskbar.area.height =
|
|
|
|
panel->area.height - top_bottom_border_width(&panel->area) - 2 * panel->area.paddingy;
|
|
|
|
panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
|
|
|
|
panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
|
|
|
|
} else {
|
|
|
|
panel->g_taskbar.area.posx = left_border_width(&panel->area) + panel->area.paddingy;
|
|
|
|
panel->g_taskbar.area.width =
|
|
|
|
panel->area.width - left_right_border_width(&panel->area) - 2 * panel->area.paddingy;
|
|
|
|
panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
|
|
|
|
panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
// task
|
|
|
|
panel->g_task.area.panel = panel;
|
|
|
|
snprintf(panel->g_task.area.name, sizeof(panel->g_task.area.name), "Task");
|
|
|
|
panel->g_task.area.size_mode = LAYOUT_DYNAMIC;
|
|
|
|
panel->g_task.area._draw_foreground = draw_task;
|
|
|
|
panel->g_task.area._on_change_layout = on_change_task;
|
|
|
|
panel->g_task.area.resize_needed = 1;
|
|
|
|
panel->g_task.area.on_screen = TRUE;
|
|
|
|
if ((panel->g_task.config_asb_mask & (1 << TASK_NORMAL)) == 0) {
|
|
|
|
panel->g_task.alpha[TASK_NORMAL] = 100;
|
|
|
|
panel->g_task.saturation[TASK_NORMAL] = 0;
|
|
|
|
panel->g_task.brightness[TASK_NORMAL] = 0;
|
|
|
|
}
|
|
|
|
if ((panel->g_task.config_asb_mask & (1 << TASK_ACTIVE)) == 0) {
|
|
|
|
panel->g_task.alpha[TASK_ACTIVE] = panel->g_task.alpha[TASK_NORMAL];
|
|
|
|
panel->g_task.saturation[TASK_ACTIVE] = panel->g_task.saturation[TASK_NORMAL];
|
|
|
|
panel->g_task.brightness[TASK_ACTIVE] = panel->g_task.brightness[TASK_NORMAL];
|
|
|
|
}
|
|
|
|
if ((panel->g_task.config_asb_mask & (1 << TASK_ICONIFIED)) == 0) {
|
|
|
|
panel->g_task.alpha[TASK_ICONIFIED] = panel->g_task.alpha[TASK_NORMAL];
|
|
|
|
panel->g_task.saturation[TASK_ICONIFIED] = panel->g_task.saturation[TASK_NORMAL];
|
|
|
|
panel->g_task.brightness[TASK_ICONIFIED] = panel->g_task.brightness[TASK_NORMAL];
|
|
|
|
}
|
|
|
|
if ((panel->g_task.config_asb_mask & (1 << TASK_URGENT)) == 0) {
|
|
|
|
panel->g_task.alpha[TASK_URGENT] = panel->g_task.alpha[TASK_ACTIVE];
|
|
|
|
panel->g_task.saturation[TASK_URGENT] = panel->g_task.saturation[TASK_ACTIVE];
|
|
|
|
panel->g_task.brightness[TASK_URGENT] = panel->g_task.brightness[TASK_ACTIVE];
|
|
|
|
}
|
|
|
|
if ((panel->g_task.config_font_mask & (1 << TASK_NORMAL)) == 0)
|
|
|
|
panel->g_task.font[TASK_NORMAL] = (Color){{1, 1, 1}, 1};
|
|
|
|
if ((panel->g_task.config_font_mask & (1 << TASK_ACTIVE)) == 0)
|
|
|
|
panel->g_task.font[TASK_ACTIVE] = panel->g_task.font[TASK_NORMAL];
|
|
|
|
if ((panel->g_task.config_font_mask & (1 << TASK_ICONIFIED)) == 0)
|
|
|
|
panel->g_task.font[TASK_ICONIFIED] = panel->g_task.font[TASK_NORMAL];
|
|
|
|
if ((panel->g_task.config_font_mask & (1 << TASK_URGENT)) == 0)
|
|
|
|
panel->g_task.font[TASK_URGENT] = panel->g_task.font[TASK_ACTIVE];
|
|
|
|
if ((panel->g_task.config_background_mask & (1 << TASK_NORMAL)) == 0)
|
|
|
|
panel->g_task.background[TASK_NORMAL] = &g_array_index(backgrounds, Background, 0);
|
|
|
|
if ((panel->g_task.config_background_mask & (1 << TASK_ACTIVE)) == 0)
|
|
|
|
panel->g_task.background[TASK_ACTIVE] = panel->g_task.background[TASK_NORMAL];
|
|
|
|
if ((panel->g_task.config_background_mask & (1 << TASK_ICONIFIED)) == 0)
|
|
|
|
panel->g_task.background[TASK_ICONIFIED] = panel->g_task.background[TASK_NORMAL];
|
|
|
|
if ((panel->g_task.config_background_mask & (1 << TASK_URGENT)) == 0)
|
|
|
|
panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
|
|
|
|
|
2017-05-24 19:07:36 +00:00
|
|
|
if (!panel->g_task.maximum_width || !panel_horizontal)
|
2017-04-13 12:07:23 +00:00
|
|
|
panel->g_task.maximum_width = server.monitors[panel->monitor].width;
|
2017-05-24 19:07:36 +00:00
|
|
|
if (!panel->g_task.maximum_height || panel_horizontal)
|
2017-04-13 12:07:23 +00:00
|
|
|
panel->g_task.maximum_height = server.monitors[panel->monitor].height;
|
|
|
|
|
|
|
|
if (panel_horizontal) {
|
|
|
|
panel->g_task.area.posy = panel->g_taskbar.area.posy +
|
|
|
|
top_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
|
|
|
panel->g_taskbar.area.paddingy;
|
|
|
|
panel->g_task.area.width = panel->g_task.maximum_width;
|
|
|
|
panel->g_task.area.height = panel->g_taskbar.area.height -
|
|
|
|
top_bottom_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
|
|
|
2 * panel->g_taskbar.area.paddingy;
|
|
|
|
} else {
|
|
|
|
panel->g_task.area.posx = panel->g_taskbar.area.posx +
|
|
|
|
left_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) +
|
|
|
|
panel->g_taskbar.area.paddingy;
|
|
|
|
panel->g_task.area.width = panel->g_taskbar.area.width -
|
|
|
|
left_right_bg_border_width(panel->g_taskbar.background[TASKBAR_NORMAL]) -
|
|
|
|
2 * panel->g_taskbar.area.paddingy;
|
|
|
|
panel->g_task.area.height = panel->g_task.maximum_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int j = 0; j < TASK_STATE_COUNT; ++j) {
|
|
|
|
if (!panel->g_task.background[j])
|
|
|
|
panel->g_task.background[j] = &g_array_index(backgrounds, Background, 0);
|
|
|
|
if (panel->g_task.background[j]->border.radius > panel->g_task.area.height / 2) {
|
2017-09-01 16:23:46 +00:00
|
|
|
fprintf(stderr, "tint2: task%sbackground_id has a too large rounded value. Please fix your tint2rc\n",
|
2017-04-13 12:07:23 +00:00
|
|
|
j == 0 ? "_" : j == 1 ? "_active_" : j == 2 ? "_iconified_" : "_urgent_");
|
|
|
|
g_array_append_val(backgrounds, *panel->g_task.background[j]);
|
|
|
|
panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len - 1);
|
|
|
|
panel->g_task.background[j]->border.radius = panel->g_task.area.height / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// compute vertical position : text and icon
|
|
|
|
int height_ink, height, width;
|
|
|
|
get_text_size2(panel->g_task.font_desc,
|
|
|
|
&height_ink,
|
|
|
|
&height,
|
|
|
|
&width,
|
|
|
|
panel->area.height,
|
|
|
|
panel->area.width,
|
|
|
|
"TAjpg",
|
|
|
|
5,
|
|
|
|
PANGO_WRAP_WORD_CHAR,
|
|
|
|
PANGO_ELLIPSIZE_END,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
panel->g_task.text_posx = left_bg_border_width(panel->g_task.background[0]) + panel->g_task.area.paddingxlr;
|
2017-05-28 12:46:50 +00:00
|
|
|
panel->g_task.text_height =
|
|
|
|
panel->g_task.area.height - (2 * panel->g_task.area.paddingy) - top_bottom_border_width(&panel->g_task.area);
|
2017-04-13 12:07:23 +00:00
|
|
|
if (panel->g_task.has_icon) {
|
|
|
|
panel->g_task.icon_size1 = MIN(MIN(panel->g_task.maximum_width, panel->g_task.maximum_height),
|
|
|
|
MIN(panel->g_task.area.width, panel->g_task.area.height)) -
|
|
|
|
2 * panel->g_task.area.paddingy - MAX(left_right_border_width(&panel->g_task.area),
|
|
|
|
top_bottom_border_width(&panel->g_task.area));
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
Taskbar *taskbar;
|
|
|
|
panel->num_desktops = server.num_desktops;
|
|
|
|
panel->taskbar = calloc(server.num_desktops, sizeof(Taskbar));
|
|
|
|
for (int j = 0; j < panel->num_desktops; j++) {
|
|
|
|
taskbar = &panel->taskbar[j];
|
|
|
|
memcpy(&taskbar->area, &panel->g_taskbar.area, sizeof(Area));
|
|
|
|
taskbar->desktop = j;
|
|
|
|
if (j == server.desktop) {
|
|
|
|
taskbar->area.bg = panel->g_taskbar.background[TASKBAR_ACTIVE];
|
|
|
|
free_area_gradient_instances(&taskbar->area);
|
|
|
|
instantiate_area_gradients(&taskbar->area);
|
|
|
|
} else {
|
|
|
|
taskbar->area.bg = panel->g_taskbar.background[TASKBAR_NORMAL];
|
|
|
|
free_area_gradient_instances(&taskbar->area);
|
|
|
|
instantiate_area_gradients(&taskbar->area);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
init_taskbarname_panel(panel);
|
2010-09-18 18:06:29 +00:00
|
|
|
}
|
|
|
|
|
2015-12-12 14:13:32 +00:00
|
|
|
void taskbar_init_fonts()
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
for (int i = 0; i < num_panels; i++) {
|
|
|
|
if (!panels[i].g_task.font_desc) {
|
|
|
|
panels[i].g_task.font_desc = pango_font_description_from_string(get_default_font());
|
|
|
|
pango_font_description_set_size(panels[i].g_task.font_desc,
|
|
|
|
pango_font_description_get_size(panels[i].g_task.font_desc) - PANGO_SCALE);
|
|
|
|
}
|
|
|
|
}
|
2015-12-12 14:13:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void taskbar_default_font_changed()
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (!taskbar_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gboolean needs_update = FALSE;
|
|
|
|
for (int i = 0; i < num_panels; i++) {
|
|
|
|
if (!panels[i].g_task.has_font) {
|
|
|
|
pango_font_description_free(panels[i].g_task.font_desc);
|
|
|
|
panels[i].g_task.font_desc = NULL;
|
|
|
|
needs_update = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!needs_update)
|
|
|
|
return;
|
|
|
|
taskbar_init_fonts();
|
|
|
|
for (int i = 0; i < num_panels; i++) {
|
|
|
|
for (int j = 0; j < panels[i].num_desktops; j++) {
|
|
|
|
Taskbar *taskbar = &panels[i].taskbar[j];
|
|
|
|
for (GList *c = taskbar->area.children; c; c = c->next) {
|
|
|
|
Task *t = c->data;
|
|
|
|
t->area.resize_needed = TRUE;
|
|
|
|
schedule_redraw(&t->area);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
schedule_panel_redraw();
|
2015-12-12 14:13:32 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 22:53:44 +00:00
|
|
|
void taskbar_remove_task(Window *win)
|
2010-09-18 18:06:29 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
remove_task(get_task(*win));
|
2010-09-18 18:06:29 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 22:43:53 +00:00
|
|
|
Task *get_task(Window win)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
GPtrArray *task_buttons = get_task_buttons(win);
|
|
|
|
if (task_buttons)
|
|
|
|
return g_ptr_array_index(task_buttons, 0);
|
|
|
|
return NULL;
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2016-01-09 13:07:44 +00:00
|
|
|
GPtrArray *get_task_buttons(Window win)
|
2009-12-29 19:55:25 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (win_to_task && taskbar_enabled)
|
|
|
|
return g_hash_table_lookup(win_to_task, &win);
|
|
|
|
return NULL;
|
2009-12-29 19:55:25 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 22:43:53 +00:00
|
|
|
void taskbar_refresh_tasklist()
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (!taskbar_enabled)
|
|
|
|
return;
|
2017-09-01 16:23:46 +00:00
|
|
|
// fprintf(stderr, "tint2: %s %d:\n", __FUNCTION__, __LINE__);
|
2017-04-13 12:07:23 +00:00
|
|
|
|
|
|
|
int num_results;
|
|
|
|
Window *win = server_get_property(server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
|
|
|
|
if (!win)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GList *win_list = g_hash_table_get_keys(win_to_task);
|
|
|
|
for (GList *it = win_list; it; it = it->next) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < num_results; i++)
|
|
|
|
if (*((Window *)it->data) == win[i])
|
|
|
|
break;
|
|
|
|
if (i == num_results)
|
|
|
|
taskbar_remove_task(it->data);
|
|
|
|
}
|
|
|
|
g_list_free(win_list);
|
|
|
|
|
|
|
|
// Add any new
|
|
|
|
for (int i = 0; i < num_results; i++)
|
|
|
|
if (!get_task(win[i]))
|
|
|
|
add_task(win[i]);
|
|
|
|
|
|
|
|
XFree(win);
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2016-10-09 13:21:56 +00:00
|
|
|
int taskbar_compute_desired_size(void *obj)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
Taskbar *taskbar = (Taskbar *)obj;
|
|
|
|
Panel *panel = (Panel *)taskbar->area.panel;
|
|
|
|
|
|
|
|
if (taskbar_mode == MULTI_DESKTOP && !taskbar_distribute_size) {
|
|
|
|
int result = 0;
|
|
|
|
for (int i = 0; i < panel->num_desktops; i++) {
|
|
|
|
Taskbar *t = &panel->taskbar[i];
|
|
|
|
result = MAX(result, container_compute_desired_size(&t->area));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return container_compute_desired_size(&taskbar->area);
|
2016-10-09 13:21:56 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
gboolean resize_taskbar(void *obj)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
Taskbar *taskbar = (Taskbar *)obj;
|
|
|
|
Panel *panel = (Panel *)taskbar->area.panel;
|
|
|
|
|
2017-09-01 16:23:46 +00:00
|
|
|
// fprintf(stderr, "tint2: resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
|
2017-04-13 12:07:23 +00:00
|
|
|
if (panel_horizontal) {
|
|
|
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_width);
|
|
|
|
|
|
|
|
int text_width = panel->g_task.maximum_width;
|
|
|
|
GList *l = taskbar->area.children;
|
|
|
|
if (taskbarname_enabled)
|
|
|
|
l = l->next;
|
|
|
|
for (; l != NULL; l = l->next) {
|
|
|
|
if (((Task *)l->data)->area.on_screen) {
|
|
|
|
text_width = ((Task *)l->data)->area.width;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
taskbar->text_width = text_width - panel->g_task.text_posx - right_border_width(&panel->g_task.area) -
|
|
|
|
panel->g_task.area.paddingxlr;
|
|
|
|
} else {
|
|
|
|
relayout_with_constraint(&taskbar->area, panel->g_task.maximum_height);
|
|
|
|
|
|
|
|
taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx -
|
|
|
|
right_border_width(&panel->g_task.area) - panel->g_task.area.paddingxlr;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
2010-09-18 10:41:34 +00:00
|
|
|
|
2016-09-18 10:16:11 +00:00
|
|
|
gboolean taskbar_is_empty(Taskbar *taskbar)
|
2016-08-31 14:55:33 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
GList *l = taskbar->area.children;
|
|
|
|
if (taskbarname_enabled)
|
|
|
|
l = l->next;
|
|
|
|
for (; l != NULL; l = l->next) {
|
|
|
|
if (((Task *)l->data)->area.on_screen) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
2016-09-04 13:33:33 +00:00
|
|
|
}
|
2016-08-31 14:55:33 +00:00
|
|
|
|
2016-09-18 10:16:11 +00:00
|
|
|
void update_taskbar_visibility(Taskbar *taskbar)
|
2016-09-04 13:33:33 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (taskbar->desktop == server.desktop) {
|
|
|
|
// Taskbar for current desktop is always shown
|
|
|
|
show(&taskbar->area);
|
|
|
|
} else if (taskbar_mode == MULTI_DESKTOP) {
|
|
|
|
if (hide_taskbar_if_empty) {
|
|
|
|
if (taskbar_is_empty(taskbar)) {
|
|
|
|
hide(&taskbar->area);
|
|
|
|
} else {
|
|
|
|
show(&taskbar->area);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
show(&taskbar->area);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hide(&taskbar->area);
|
|
|
|
}
|
2016-08-31 14:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void update_all_taskbars_visibility()
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
for (int i = 0; i < num_panels; i++) {
|
|
|
|
Panel *panel = &panels[i];
|
|
|
|
for (int j = 0; j < panel->num_desktops; j++) {
|
|
|
|
update_taskbar_visibility(&panel->taskbar[j]);
|
|
|
|
}
|
|
|
|
}
|
2016-08-31 14:55:33 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void set_taskbar_state(Taskbar *taskbar, TaskbarState state)
|
2010-10-23 11:16:29 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
taskbar->area.bg = panels[0].g_taskbar.background[state];
|
|
|
|
free_area_gradient_instances(&taskbar->area);
|
|
|
|
instantiate_area_gradients(&taskbar->area);
|
|
|
|
|
|
|
|
if (taskbarname_enabled) {
|
|
|
|
taskbar->bar_name.area.bg = panels[0].g_taskbar.background_name[state];
|
|
|
|
free_area_gradient_instances(&taskbar->bar_name.area);
|
|
|
|
instantiate_area_gradients(&taskbar->bar_name.area);
|
|
|
|
}
|
|
|
|
|
|
|
|
update_taskbar_visibility(taskbar);
|
|
|
|
|
|
|
|
if (taskbar->area.on_screen) {
|
|
|
|
schedule_redraw(&taskbar->area);
|
|
|
|
if (taskbarname_enabled) {
|
|
|
|
schedule_redraw(&taskbar->bar_name.area);
|
|
|
|
}
|
|
|
|
if (taskbar_mode == MULTI_DESKTOP &&
|
|
|
|
panels[0].g_taskbar.background[TASKBAR_NORMAL] != panels[0].g_taskbar.background[TASKBAR_ACTIVE]) {
|
|
|
|
GList *l = taskbar->area.children;
|
|
|
|
if (taskbarname_enabled)
|
|
|
|
l = l->next;
|
|
|
|
for (; l; l = l->next)
|
|
|
|
schedule_redraw((Area *)l->data);
|
|
|
|
}
|
2017-06-20 03:06:37 +00:00
|
|
|
if (taskbar_mode == MULTI_DESKTOP && hide_task_diff_desktop) {
|
|
|
|
GList *l = taskbar->area.children;
|
|
|
|
if (taskbarname_enabled)
|
|
|
|
l = l->next;
|
|
|
|
for (; l; l = l->next) {
|
|
|
|
Task *task = (Task *)l->data;
|
|
|
|
set_task_state(task, task->current_state);
|
|
|
|
}
|
|
|
|
}
|
2017-04-13 12:07:23 +00:00
|
|
|
}
|
|
|
|
schedule_panel_redraw();
|
2010-10-23 11:16:29 +00:00
|
|
|
}
|
|
|
|
|
2015-03-28 22:38:57 +00:00
|
|
|
#define NONTRIVIAL 2
|
|
|
|
gint compare_tasks_trivial(Task *a, Task *b, Taskbar *taskbar)
|
2015-03-22 16:07:04 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (a == b)
|
|
|
|
return 0;
|
|
|
|
if (taskbarname_enabled) {
|
|
|
|
if (a == taskbar->area.children->data)
|
|
|
|
return -1;
|
|
|
|
if (b == taskbar->area.children->data)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return NONTRIVIAL;
|
2015-03-28 22:38:57 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 22:53:44 +00:00
|
|
|
gboolean contained_within(Task *a, Task *b)
|
2015-04-12 20:02:58 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if ((a->win_x <= b->win_x) && (a->win_y <= b->win_y) && (a->win_x + a->win_w >= b->win_x + b->win_w) &&
|
|
|
|
(a->win_y + a->win_h >= b->win_y + b->win_h)) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2015-04-12 20:02:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-28 22:38:57 +00:00
|
|
|
gint compare_task_centers(Task *a, Task *b, Taskbar *taskbar)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
|
|
|
if (trivial != NONTRIVIAL)
|
|
|
|
return trivial;
|
|
|
|
|
|
|
|
// If a window has the same coordinates and size as the other,
|
|
|
|
// they are considered to be equal in the comparison.
|
|
|
|
if ((a->win_x == b->win_x) && (a->win_y == b->win_y) && (a->win_w == b->win_w) && (a->win_h == b->win_h)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a window is completely contained in another,
|
|
|
|
// then it is considered to come after (to the right/bottom) of the other.
|
|
|
|
if (contained_within(a, b))
|
|
|
|
return -1;
|
|
|
|
if (contained_within(b, a))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
// Compare centers
|
|
|
|
int a_horiz_c = a->win_x + a->win_w / 2;
|
|
|
|
int b_horiz_c = b->win_x + b->win_w / 2;
|
|
|
|
int a_vert_c = a->win_y + a->win_h / 2;
|
|
|
|
int b_vert_c = b->win_y + b->win_h / 2;
|
|
|
|
if (panel_horizontal) {
|
|
|
|
if (a_horiz_c != b_horiz_c) {
|
|
|
|
return a_horiz_c - b_horiz_c;
|
|
|
|
}
|
|
|
|
return a_vert_c - b_vert_c;
|
|
|
|
} else {
|
|
|
|
if (a_vert_c != b_vert_c) {
|
|
|
|
return a_vert_c - b_vert_c;
|
|
|
|
}
|
|
|
|
return a_horiz_c - b_horiz_c;
|
|
|
|
}
|
2015-03-22 16:07:04 +00:00
|
|
|
}
|
|
|
|
|
2015-03-28 22:38:57 +00:00
|
|
|
gint compare_task_titles(Task *a, Task *b, Taskbar *taskbar)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
int trivial = compare_tasks_trivial(a, b, taskbar);
|
|
|
|
if (trivial != NONTRIVIAL)
|
|
|
|
return trivial;
|
|
|
|
return strnatcasecmp(a->title ? a->title : "", b->title ? b->title : "");
|
2015-03-28 22:38:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gint compare_tasks(Task *a, Task *b, Taskbar *taskbar)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
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);
|
|
|
|
} else if (taskbar_sort_method == TASKBAR_SORT_LRU) {
|
|
|
|
return compare_timespecs(&a->last_activation_time, &b->last_activation_time);
|
|
|
|
} else if (taskbar_sort_method == TASKBAR_SORT_MRU) {
|
|
|
|
return -compare_timespecs(&a->last_activation_time, &b->last_activation_time);
|
|
|
|
}
|
|
|
|
return 0;
|
2015-03-28 22:38:57 +00:00
|
|
|
}
|
|
|
|
|
2015-11-21 03:35:12 +00:00
|
|
|
gboolean taskbar_needs_sort(Taskbar *taskbar)
|
2015-03-22 16:07:04 +00:00
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (taskbar_sort_method == TASKBAR_NOSORT)
|
|
|
|
return FALSE;
|
2015-03-22 16:07:04 +00:00
|
|
|
|
2017-04-13 12:07:23 +00:00
|
|
|
for (GList *i = taskbar->area.children, *j = i ? i->next : NULL; i && j; i = i->next, j = j->next) {
|
|
|
|
if (compare_tasks(i->data, j->data, taskbar) > 0) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2015-03-22 16:07:04 +00:00
|
|
|
|
2017-04-13 12:07:23 +00:00
|
|
|
return FALSE;
|
2015-03-22 16:07:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void sort_tasks(Taskbar *taskbar)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (!taskbar)
|
|
|
|
return;
|
|
|
|
if (!taskbar_needs_sort(taskbar))
|
|
|
|
return;
|
|
|
|
|
|
|
|
taskbar->area.children = g_list_sort_with_data(taskbar->area.children, (GCompareDataFunc)compare_tasks, taskbar);
|
|
|
|
taskbar->area.resize_needed = TRUE;
|
|
|
|
schedule_panel_redraw();
|
|
|
|
((Panel *)taskbar->area.panel)->area.resize_needed = TRUE;
|
2015-03-22 16:07:04 +00:00
|
|
|
}
|
2015-03-28 21:07:33 +00:00
|
|
|
|
|
|
|
void sort_taskbar_for_win(Window win)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
if (taskbar_sort_method == TASKBAR_NOSORT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GPtrArray *task_buttons = get_task_buttons(win);
|
|
|
|
if (task_buttons) {
|
|
|
|
Task *task0 = g_ptr_array_index(task_buttons, 0);
|
|
|
|
if (task0) {
|
|
|
|
get_window_coordinates(win, &task0->win_x, &task0->win_y, &task0->win_w, &task0->win_h);
|
|
|
|
}
|
|
|
|
for (int i = 0; i < task_buttons->len; ++i) {
|
|
|
|
Task *task = g_ptr_array_index(task_buttons, i);
|
|
|
|
task->win_x = task0->win_x;
|
|
|
|
task->win_y = task0->win_y;
|
|
|
|
task->win_w = task0->win_w;
|
|
|
|
task->win_h = task0->win_h;
|
|
|
|
sort_tasks(task->area.parent);
|
|
|
|
}
|
|
|
|
}
|
2015-03-28 21:07:33 +00:00
|
|
|
}
|
2017-04-08 12:10:39 +00:00
|
|
|
|
|
|
|
void update_minimized_icon_positions(void *p)
|
|
|
|
{
|
2017-04-13 12:07:23 +00:00
|
|
|
Panel *panel = (Panel *)p;
|
|
|
|
for (int i = 0; i < panel->num_desktops; i++) {
|
|
|
|
Taskbar *taskbar = &panel->taskbar[i];
|
|
|
|
if (!taskbar->area.on_screen)
|
|
|
|
continue;
|
|
|
|
for (GList *c = taskbar->area.children; c; c = c->next) {
|
|
|
|
Area *area = (Area *)c->data;
|
|
|
|
if (area->_on_change_layout)
|
|
|
|
area->_on_change_layout(area);
|
|
|
|
}
|
|
|
|
}
|
2017-04-08 12:10:39 +00:00
|
|
|
}
|