2008-10-02 18:47:02 +00:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Tint2 : task
|
2009-01-17 14:07:56 +00:00
|
|
|
*
|
2008-10-02 18:47:02 +00:00
|
|
|
* Copyright (C) 2007 Pål Staurland (staura@gmail.com)
|
2010-11-02 11:40:50 +00:00
|
|
|
* Modified (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>
|
2009-10-19 18:27:25 +00:00
|
|
|
#include <unistd.h>
|
2008-10-02 18:47:02 +00:00
|
|
|
|
|
|
|
#include "window.h"
|
|
|
|
#include "task.h"
|
2009-12-29 19:55:25 +00:00
|
|
|
#include "taskbar.h"
|
2008-10-02 18:47:02 +00:00
|
|
|
#include "server.h"
|
|
|
|
#include "panel.h"
|
2009-09-14 21:28:17 +00:00
|
|
|
#include "tooltip.h"
|
2009-11-15 16:55:50 +00:00
|
|
|
#include "timer.h"
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
timeout *urgent_timeout;
|
|
|
|
GSList *urgent_list;
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
char *task_get_tooltip(void *obj)
|
2009-11-16 17:17:53 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *t = (Task *)obj;
|
2015-08-07 00:03:06 +00:00
|
|
|
return strdup(t->title);
|
2009-11-16 17:17:53 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *add_task(Window win)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!win)
|
|
|
|
return 0;
|
|
|
|
if (window_is_hidden(win))
|
|
|
|
return 0;
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
XSelectInput(server.dsp, win, PropertyChangeMask | StructureNotifyMask);
|
2015-05-08 19:49:26 +00:00
|
|
|
XFlush(server.dsp);
|
|
|
|
|
2009-07-26 13:46:50 +00:00
|
|
|
int monitor;
|
2015-11-20 22:28:37 +00:00
|
|
|
if (num_panels > 1) {
|
|
|
|
monitor = get_window_monitor(win);
|
|
|
|
if (monitor >= num_panels)
|
|
|
|
monitor = 0;
|
|
|
|
} else
|
|
|
|
monitor = 0;
|
|
|
|
|
|
|
|
Task new_task;
|
|
|
|
memset(&new_task, 0, sizeof(new_task));
|
|
|
|
new_task.area.has_mouse_over_effect = 1;
|
|
|
|
new_task.area.has_mouse_press_effect = 1;
|
|
|
|
new_task.win = win;
|
|
|
|
new_task.desktop = get_window_desktop(win);
|
|
|
|
new_task.area.panel = &panels[monitor];
|
|
|
|
new_task.current_state = window_is_iconified(win) ? TASK_ICONIFIED : TASK_NORMAL;
|
|
|
|
get_window_coordinates(win, &new_task.win_x, &new_task.win_y, &new_task.win_w, &new_task.win_h);
|
2009-01-20 00:19:05 +00:00
|
|
|
|
2009-02-07 23:28:13 +00:00
|
|
|
// allocate only one title and one icon
|
|
|
|
// even with task_on_all_desktop and with task_on_all_panel
|
2015-11-20 22:28:37 +00:00
|
|
|
new_task.title = 0;
|
2010-01-09 00:11:01 +00:00
|
|
|
int k;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (k = 0; k < TASK_STATE_COUNT; ++k) {
|
|
|
|
new_task.icon[k] = 0;
|
|
|
|
new_task.state_pix[k] = 0;
|
2010-01-10 22:16:27 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
get_title(&new_task);
|
|
|
|
get_icon(&new_task);
|
2009-01-20 21:16:54 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
// printf("new task %s win %u: desktop %d, monitor %d\n", new_task.title, win, new_task.desktop, monitor);
|
2009-02-07 23:28:13 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
GPtrArray *task_group = g_ptr_array_new();
|
|
|
|
Taskbar *taskbar;
|
|
|
|
Task *new_task2 = 0;
|
2010-01-09 18:29:00 +00:00
|
|
|
int j;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (j = 0; j < panels[monitor].num_desktops; j++) {
|
|
|
|
if (new_task.desktop != ALLDESKTOP && new_task.desktop != j)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
taskbar = &panels[monitor].taskbar[j];
|
|
|
|
new_task2 = calloc(1, sizeof(Task));
|
|
|
|
memcpy(&new_task2->area, &panels[monitor].g_task.area, sizeof(Area));
|
|
|
|
new_task2->area.parent = taskbar;
|
|
|
|
new_task2->area.has_mouse_over_effect = 1;
|
|
|
|
new_task2->area.has_mouse_press_effect = 1;
|
|
|
|
new_task2->win = new_task.win;
|
|
|
|
new_task2->desktop = new_task.desktop;
|
|
|
|
new_task2->win_x = new_task.win_x;
|
|
|
|
new_task2->win_y = new_task.win_y;
|
|
|
|
new_task2->win_w = new_task.win_w;
|
|
|
|
new_task2->win_h = new_task.win_h;
|
|
|
|
new_task2->current_state = -1; // to update the current state later in set_task_state...
|
|
|
|
if (new_task2->desktop == ALLDESKTOP && server.desktop != j) {
|
2010-01-09 18:29:00 +00:00
|
|
|
// hide ALLDESKTOP task on non-current desktop
|
2015-11-20 22:28:37 +00:00
|
|
|
new_task2->area.on_screen = FALSE;
|
2009-02-07 23:28:13 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
new_task2->title = new_task.title;
|
|
|
|
if (panels[monitor].g_task.tooltip_enabled)
|
|
|
|
new_task2->area._get_tooltip_text = task_get_tooltip;
|
|
|
|
for (k = 0; k < TASK_STATE_COUNT; ++k) {
|
|
|
|
new_task2->icon[k] = new_task.icon[k];
|
|
|
|
new_task2->icon_hover[k] = new_task.icon_hover[k];
|
|
|
|
new_task2->icon_press[k] = new_task.icon_press[k];
|
|
|
|
new_task2->state_pix[k] = 0;
|
2010-01-09 18:29:00 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
new_task2->icon_width = new_task.icon_width;
|
|
|
|
new_task2->icon_height = new_task.icon_height;
|
|
|
|
taskbar->area.children = g_list_append(taskbar->area.children, new_task2);
|
|
|
|
taskbar->area.resize_needed = 1;
|
|
|
|
g_ptr_array_add(task_group, new_task2);
|
|
|
|
// printf("add_task panel %d, desktop %d, task %s\n", i, j, new_task2->title);
|
2009-02-07 23:28:13 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
Window *key = calloc(1, sizeof(Window));
|
|
|
|
*key = new_task.win;
|
2010-01-09 18:29:00 +00:00
|
|
|
g_hash_table_insert(win_to_task_table, key, task_group);
|
2015-11-20 22:28:37 +00:00
|
|
|
set_task_state(new_task2, new_task.current_state);
|
2010-01-09 18:29:00 +00:00
|
|
|
|
2015-03-28 21:07:33 +00:00
|
|
|
sort_taskbar_for_win(win);
|
2015-03-22 16:07:04 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
if (taskbar_mode == MULTI_DESKTOP) {
|
|
|
|
Panel *panel = new_task2->area.panel;
|
2015-11-18 20:57:10 +00:00
|
|
|
panel->area.resize_needed = 1;
|
2015-01-30 09:53:16 +00:00
|
|
|
}
|
|
|
|
|
2015-03-20 20:54:57 +00:00
|
|
|
if (window_is_urgent(win)) {
|
2015-11-20 22:28:37 +00:00
|
|
|
add_urgent(new_task2);
|
2015-03-20 20:54:57 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
return new_task2;
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void remove_task(Task *task)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!task)
|
|
|
|
return;
|
2009-01-20 21:16:54 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
if (taskbar_mode == MULTI_DESKTOP) {
|
|
|
|
Panel *panel = task->area.panel;
|
2015-11-18 20:57:10 +00:00
|
|
|
panel->area.resize_needed = 1;
|
2015-01-30 09:53:16 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Window win = task->win;
|
2009-02-07 23:28:13 +00:00
|
|
|
|
|
|
|
// free title and icon just for the first task
|
|
|
|
// even with task_on_all_desktop and with task_on_all_panel
|
2015-11-20 22:28:37 +00:00
|
|
|
// printf("remove_task %s %d\n", task->title, task->desktop);
|
|
|
|
if (task->title)
|
|
|
|
free(task->title);
|
2010-01-09 00:11:01 +00:00
|
|
|
int k;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (k = 0; k < TASK_STATE_COUNT; ++k) {
|
|
|
|
if (task->icon[k]) {
|
|
|
|
imlib_context_set_image(task->icon[k]);
|
2010-01-09 00:11:01 +00:00
|
|
|
imlib_free_image();
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon[k] = 0;
|
2010-01-09 00:11:01 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (task->icon_hover[k]) {
|
|
|
|
imlib_context_set_image(task->icon_hover[k]);
|
2015-11-04 12:02:12 +00:00
|
|
|
imlib_free_image();
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon_hover[k] = 0;
|
2015-11-04 12:02:12 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (task->icon_press[k]) {
|
|
|
|
imlib_context_set_image(task->icon_press[k]);
|
2015-11-04 12:02:12 +00:00
|
|
|
imlib_free_image();
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon_press[k] = 0;
|
2015-11-04 12:02:12 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (task->state_pix[k])
|
|
|
|
XFreePixmap(server.dsp, task->state_pix[k]);
|
2009-08-28 12:14:45 +00:00
|
|
|
}
|
2009-02-07 23:28:13 +00:00
|
|
|
|
2010-01-09 18:29:00 +00:00
|
|
|
int i;
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *task2;
|
|
|
|
GPtrArray *task_group = g_hash_table_lookup(win_to_task_table, &win);
|
|
|
|
for (i = 0; i < task_group->len; ++i) {
|
|
|
|
task2 = g_ptr_array_index(task_group, i);
|
|
|
|
if (task2 == task_active)
|
|
|
|
task_active = 0;
|
|
|
|
if (task2 == task_drag)
|
|
|
|
task_drag = 0;
|
|
|
|
if (g_slist_find(urgent_list, task2))
|
|
|
|
del_urgent(task2);
|
|
|
|
remove_area((Area *)task2);
|
|
|
|
free(task2);
|
2009-02-07 23:28:13 +00:00
|
|
|
}
|
2010-01-09 18:29:00 +00:00
|
|
|
g_hash_table_remove(win_to_task_table, &win);
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
gboolean get_title(Task *task)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
Panel *panel = task->area.panel;
|
2009-07-26 13:46:50 +00:00
|
|
|
char *title, *name;
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!panel->g_task.text && !panel->g_task.tooltip_enabled && taskbar_sort_method != TASKBAR_SORT_TITLE)
|
2015-03-28 22:38:57 +00:00
|
|
|
return 0;
|
2009-07-26 13:46:50 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
name = server_get_property(task->win, server.atom._NET_WM_VISIBLE_NAME, server.atom.UTF8_STRING, 0);
|
2009-07-26 13:46:50 +00:00
|
|
|
if (!name || !strlen(name)) {
|
2015-11-20 22:28:37 +00:00
|
|
|
name = server_get_property(task->win, server.atom._NET_WM_NAME, server.atom.UTF8_STRING, 0);
|
2009-07-26 13:46:50 +00:00
|
|
|
if (!name || !strlen(name)) {
|
2015-11-20 22:28:37 +00:00
|
|
|
name = server_get_property(task->win, server.atom.WM_NAME, XA_STRING, 0);
|
2009-07-26 13:46:50 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-04-26 13:16:24 +00:00
|
|
|
if (name && strlen(name)) {
|
|
|
|
title = strdup(name);
|
|
|
|
} else {
|
|
|
|
title = strdup("Untitled");
|
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (name)
|
|
|
|
XFree(name);
|
|
|
|
|
|
|
|
if (task->title) {
|
2010-10-23 13:39:09 +00:00
|
|
|
// check unecessary title change
|
2015-11-20 22:28:37 +00:00
|
|
|
if (strcmp(task->title, title) == 0) {
|
2010-10-23 13:39:09 +00:00
|
|
|
free(title);
|
|
|
|
return 0;
|
2015-11-20 22:28:37 +00:00
|
|
|
} else
|
|
|
|
free(task->title);
|
|
|
|
}
|
2010-01-09 18:29:00 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
task->title = title;
|
|
|
|
GPtrArray *task_group = task_get_tasks(task->win);
|
2010-01-09 18:29:00 +00:00
|
|
|
if (task_group) {
|
|
|
|
int i;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (i = 0; i < task_group->len; ++i) {
|
|
|
|
Task *task2 = g_ptr_array_index(task_group, i);
|
|
|
|
task2->title = task->title;
|
|
|
|
set_task_redraw(task2);
|
2010-01-09 18:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-23 13:39:09 +00:00
|
|
|
return 1;
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void get_icon(Task *task)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
Panel *panel = task->area.panel;
|
|
|
|
if (!panel->g_task.icon)
|
|
|
|
return;
|
2009-09-25 19:11:50 +00:00
|
|
|
int i;
|
|
|
|
Imlib_Image img = NULL;
|
|
|
|
XWMHints *hints = 0;
|
2010-09-12 22:00:00 +00:00
|
|
|
gulong *data = 0;
|
2009-02-07 23:28:13 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
|
|
|
if (task->icon[k]) {
|
|
|
|
imlib_context_set_image(task->icon[k]);
|
2010-01-09 00:11:01 +00:00
|
|
|
imlib_free_image();
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon[k] = 0;
|
2010-01-09 00:11:01 +00:00
|
|
|
}
|
2009-02-07 23:28:13 +00:00
|
|
|
}
|
2009-07-26 13:46:50 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
data = server_get_property(task->win, server.atom._NET_WM_ICON, XA_CARDINAL, &i);
|
2010-08-08 19:23:54 +00:00
|
|
|
if (data) {
|
2009-07-26 13:46:50 +00:00
|
|
|
// get ARGB icon
|
2009-09-19 13:17:44 +00:00
|
|
|
int w, h;
|
2010-09-12 22:00:00 +00:00
|
|
|
gulong *tmp_data;
|
2009-07-26 13:46:50 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
tmp_data = get_best_icon(data, get_icon_count(data, i), i, &w, &h, panel->g_task.icon_size1);
|
2009-07-26 13:46:50 +00:00
|
|
|
#ifdef __x86_64__
|
2009-09-30 17:52:32 +00:00
|
|
|
DATA32 icon_data[w * h];
|
2009-09-19 20:56:15 +00:00
|
|
|
int length = w * h;
|
|
|
|
for (i = 0; i < length; ++i)
|
2015-11-04 22:14:11 +00:00
|
|
|
icon_data[i] = tmp_data[i];
|
2015-11-20 22:28:37 +00:00
|
|
|
img = imlib_create_image_using_copied_data(w, h, icon_data);
|
2009-07-26 13:46:50 +00:00
|
|
|
#else
|
2015-11-20 22:28:37 +00:00
|
|
|
img = imlib_create_image_using_data(w, h, (DATA32 *)tmp_data);
|
2009-07-26 13:46:50 +00:00
|
|
|
#endif
|
2015-11-20 22:28:37 +00:00
|
|
|
} else {
|
2009-09-07 21:41:21 +00:00
|
|
|
// get Pixmap icon
|
2015-11-20 22:28:37 +00:00
|
|
|
hints = XGetWMHints(server.dsp, task->win);
|
2009-09-19 05:30:43 +00:00
|
|
|
if (hints) {
|
|
|
|
if (hints->flags & IconPixmapHint && hints->icon_pixmap != 0) {
|
|
|
|
// get width, height and depth for the pixmap
|
|
|
|
Window root;
|
2015-11-04 22:14:11 +00:00
|
|
|
int icon_x, icon_y;
|
2009-09-19 05:30:43 +00:00
|
|
|
uint border_width, bpp;
|
2009-09-19 13:17:44 +00:00
|
|
|
uint w, h;
|
2009-09-19 05:30:43 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
// printf(" get pixmap\n");
|
2009-09-19 05:30:43 +00:00
|
|
|
XGetGeometry(server.dsp, 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);
|
2009-01-29 22:43:31 +00:00
|
|
|
}
|
2009-02-11 22:25:53 +00:00
|
|
|
}
|
2009-09-07 21:41:21 +00:00
|
|
|
}
|
2009-09-19 20:56:15 +00:00
|
|
|
if (img == NULL) {
|
|
|
|
imlib_context_set_image(default_icon);
|
|
|
|
img = imlib_clone_image();
|
|
|
|
}
|
2009-08-28 12:14:45 +00:00
|
|
|
|
2009-09-19 20:56:15 +00:00
|
|
|
// transform icons
|
|
|
|
imlib_context_set_image(img);
|
2009-09-20 08:02:39 +00:00
|
|
|
imlib_image_set_has_alpha(1);
|
2009-09-25 19:11:50 +00:00
|
|
|
int w, h;
|
|
|
|
w = imlib_image_get_width();
|
|
|
|
h = imlib_image_get_height();
|
2015-11-20 22:28:37 +00:00
|
|
|
Imlib_Image orig_image =
|
|
|
|
imlib_create_cropped_scaled_image(0, 0, w, h, panel->g_task.icon_size1, panel->g_task.icon_size1);
|
2009-09-19 20:56:15 +00:00
|
|
|
imlib_free_image();
|
|
|
|
|
2010-01-09 00:11:01 +00:00
|
|
|
imlib_context_set_image(orig_image);
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon_width = imlib_image_get_width();
|
|
|
|
task->icon_height = imlib_image_get_height();
|
|
|
|
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
2010-01-09 00:11:01 +00:00
|
|
|
imlib_context_set_image(orig_image);
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon[k] = imlib_clone_image();
|
|
|
|
imlib_context_set_image(task->icon[k]);
|
2010-01-09 00:11:01 +00:00
|
|
|
DATA32 *data32;
|
|
|
|
if (panel->g_task.alpha[k] != 100 || panel->g_task.saturation[k] != 0 || panel->g_task.brightness[k] != 0) {
|
|
|
|
data32 = imlib_image_get_data();
|
2015-11-20 22:28:37 +00:00
|
|
|
adjust_asb(data32,
|
|
|
|
task->icon_width,
|
|
|
|
task->icon_height,
|
|
|
|
panel->g_task.alpha[k],
|
|
|
|
(float)panel->g_task.saturation[k] / 100,
|
|
|
|
(float)panel->g_task.brightness[k] / 100);
|
2010-01-09 00:11:01 +00:00
|
|
|
imlib_image_put_back_data(data32);
|
|
|
|
}
|
2015-11-04 12:02:12 +00:00
|
|
|
if (panel_config.mouse_effects) {
|
2015-11-20 22:28:37 +00:00
|
|
|
task->icon_hover[k] = adjust_icon(task->icon[k],
|
|
|
|
panel_config.mouse_over_alpha,
|
|
|
|
panel_config.mouse_over_saturation,
|
|
|
|
panel_config.mouse_over_brightness);
|
|
|
|
task->icon_press[k] = adjust_icon(task->icon[k],
|
|
|
|
panel_config.mouse_pressed_alpha,
|
|
|
|
panel_config.mouse_pressed_saturation,
|
|
|
|
panel_config.mouse_pressed_brightness);
|
2015-11-04 12:02:12 +00:00
|
|
|
}
|
2009-08-29 12:00:11 +00:00
|
|
|
}
|
2010-01-09 00:11:01 +00:00
|
|
|
imlib_context_set_image(orig_image);
|
|
|
|
imlib_free_image();
|
2009-09-25 19:11:50 +00:00
|
|
|
|
|
|
|
if (hints)
|
|
|
|
XFree(hints);
|
|
|
|
if (data)
|
2015-11-20 22:28:37 +00:00
|
|
|
XFree(data);
|
2010-01-09 18:29:00 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
GPtrArray *task_group = task_get_tasks(task->win);
|
2010-01-09 18:29:00 +00:00
|
|
|
if (task_group) {
|
2015-11-20 22:28:37 +00:00
|
|
|
for (i = 0; i < task_group->len; ++i) {
|
|
|
|
Task *task2 = g_ptr_array_index(task_group, i);
|
|
|
|
task2->icon_width = task->icon_width;
|
|
|
|
task2->icon_height = task->icon_height;
|
|
|
|
for (int k = 0; k < TASK_STATE_COUNT; ++k) {
|
|
|
|
task2->icon[k] = task->icon[k];
|
|
|
|
task2->icon_hover[k] = task->icon_hover[k];
|
|
|
|
task2->icon_press[k] = task->icon_press[k];
|
2015-11-04 12:02:12 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
set_task_redraw(task2);
|
2010-01-09 18:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-21 00:12:05 +00:00
|
|
|
// TODO icons look too large when the panel is large
|
2015-11-20 22:28:37 +00:00
|
|
|
void draw_task_icon(Task *task, int text_width)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!task->icon[task->current_state])
|
|
|
|
return;
|
2009-07-26 13:46:50 +00:00
|
|
|
|
2009-08-28 12:14:45 +00:00
|
|
|
// Find pos
|
2009-07-26 13:46:50 +00:00
|
|
|
int pos_x;
|
2015-11-20 22:28:37 +00:00
|
|
|
Panel *panel = (Panel *)task->area.panel;
|
2009-07-26 13:46:50 +00:00
|
|
|
if (panel->g_task.centered) {
|
|
|
|
if (panel->g_task.text)
|
2015-11-20 22:28:37 +00:00
|
|
|
pos_x = (task->area.width - text_width - panel->g_task.icon_size1) / 2;
|
2009-07-26 13:46:50 +00:00
|
|
|
else
|
2015-11-20 22:28:37 +00:00
|
|
|
pos_x = (task->area.width - panel->g_task.icon_size1) / 2;
|
|
|
|
} else
|
|
|
|
pos_x = panel->g_task.area.paddingxlr + task->area.bg->border.width;
|
2009-07-26 13:46:50 +00:00
|
|
|
|
2009-08-28 12:14:45 +00:00
|
|
|
// Render
|
2015-11-04 12:02:12 +00:00
|
|
|
|
|
|
|
Imlib_Image image;
|
|
|
|
// Render
|
|
|
|
if (panel_config.mouse_effects) {
|
2015-11-20 22:28:37 +00:00
|
|
|
if (task->area.mouse_state == MOUSE_OVER)
|
|
|
|
image = task->icon_hover[task->current_state];
|
|
|
|
else if (task->area.mouse_state == MOUSE_DOWN)
|
|
|
|
image = task->icon_press[task->current_state];
|
2015-11-04 12:02:12 +00:00
|
|
|
else
|
2015-11-20 22:28:37 +00:00
|
|
|
image = task->icon[task->current_state];
|
2015-11-04 12:02:12 +00:00
|
|
|
} else {
|
2015-11-20 22:28:37 +00:00
|
|
|
image = task->icon[task->current_state];
|
2015-11-04 12:02:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
imlib_context_set_image(image);
|
2015-11-20 22:28:37 +00:00
|
|
|
render_image(task->area.pix, pos_x, panel->g_task.icon_posy);
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void draw_task(void *obj, cairo_t *c)
|
2008-10-02 18:47:02 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *task = obj;
|
2015-11-04 11:19:23 +00:00
|
|
|
if (!panel_config.mouse_effects)
|
2015-11-20 22:28:37 +00:00
|
|
|
task->state_pix[task->current_state] = task->area.pix;
|
2009-07-26 13:46:50 +00:00
|
|
|
PangoLayout *layout;
|
2010-01-09 00:11:01 +00:00
|
|
|
Color *config_text;
|
2015-11-20 22:28:37 +00:00
|
|
|
int width = 0, height;
|
|
|
|
Panel *panel = (Panel *)task->area.panel;
|
|
|
|
// printf("draw_task %d %d\n", task->area.posx, task->area.posy);
|
2009-01-17 14:07:56 +00:00
|
|
|
|
2009-07-26 13:46:50 +00:00
|
|
|
if (panel->g_task.text) {
|
2009-01-17 14:07:56 +00:00
|
|
|
/* Layout */
|
2015-11-20 22:28:37 +00:00
|
|
|
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);
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2009-01-17 14:07:56 +00:00
|
|
|
/* Drawing width and Cut text */
|
2009-02-25 20:04:43 +00:00
|
|
|
// pango use U+22EF or U+2026
|
2015-11-20 22:28:37 +00:00
|
|
|
pango_layout_set_width(layout, ((Taskbar *)task->area.parent)->text_width * PANGO_SCALE);
|
2010-04-19 21:44:40 +00:00
|
|
|
pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE);
|
2015-04-26 14:33:07 +00:00
|
|
|
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
2015-11-20 22:28:37 +00:00
|
|
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2009-01-17 14:07:56 +00:00
|
|
|
/* Center text */
|
2015-11-20 22:28:37 +00:00
|
|
|
if (panel->g_task.centered)
|
|
|
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
|
|
|
else
|
|
|
|
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
pango_layout_get_pixel_size(layout, &width, &height);
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
config_text = &panel->g_task.font[task->current_state];
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2010-04-19 21:44:40 +00:00
|
|
|
double text_posy = (panel->g_task.area.height - height) / 2.0;
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2015-04-18 13:22:07 +00:00
|
|
|
draw_text(layout, c, panel->g_task.text_posx, text_posy, config_text, panel->font_shadow);
|
2015-01-21 00:27:40 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
g_object_unref(layout);
|
2009-07-26 13:46:50 +00:00
|
|
|
}
|
2008-10-02 18:47:02 +00:00
|
|
|
|
2009-07-26 13:46:50 +00:00
|
|
|
if (panel->g_task.icon) {
|
2015-11-20 22:28:37 +00:00
|
|
|
draw_task_icon(task, width);
|
2009-07-26 13:46:50 +00:00
|
|
|
}
|
2008-10-02 18:47:02 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void on_change_task(void *obj)
|
2010-09-25 21:18:47 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *task = obj;
|
|
|
|
Panel *panel = (Panel *)task->area.panel;
|
|
|
|
|
|
|
|
long value[] = {panel->posx + task->area.posx, panel->posy + task->area.posy, task->area.width, task->area.height};
|
|
|
|
XChangeProperty(server.dsp,
|
|
|
|
task->win,
|
|
|
|
server.atom._NET_WM_ICON_GEOMETRY,
|
|
|
|
XA_CARDINAL,
|
|
|
|
32,
|
|
|
|
PropModeReplace,
|
|
|
|
(unsigned char *)value,
|
|
|
|
4);
|
2010-09-25 21:18:47 +00:00
|
|
|
|
|
|
|
// reset Pixmap when position/size changed
|
2015-11-20 22:28:37 +00:00
|
|
|
set_task_redraw(task);
|
2010-09-25 21:18:47 +00:00
|
|
|
}
|
|
|
|
|
2012-10-14 22:00:48 +00:00
|
|
|
// Given a pointer to the active task (active_task) and a pointer
|
|
|
|
// to the task that is currently under the mouse (current_task),
|
2015-01-21 01:45:09 +00:00
|
|
|
// returns a pointer to the active task.
|
2012-10-14 22:00:48 +00:00
|
|
|
Task *find_active_task(Task *current_task, Task *active_task)
|
|
|
|
{
|
2015-01-21 01:45:09 +00:00
|
|
|
if (active_task == NULL)
|
2012-10-14 22:00:48 +00:00
|
|
|
return current_task;
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Taskbar *taskbar = current_task->area.parent;
|
2012-10-14 22:00:48 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
GList *l0 = taskbar->area.children;
|
2015-01-21 01:45:09 +00:00
|
|
|
if (taskbarname_enabled)
|
|
|
|
l0 = l0->next;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (; l0; l0 = l0->next) {
|
|
|
|
Task *task = l0->data;
|
|
|
|
if (task->win == active_task->win)
|
|
|
|
return task;
|
2012-10-14 22:00:48 +00:00
|
|
|
}
|
2015-01-21 01:45:09 +00:00
|
|
|
|
|
|
|
return current_task;
|
2012-10-14 22:00:48 +00:00
|
|
|
}
|
2010-09-25 21:18:47 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *next_task(Task *task)
|
2009-11-18 05:13:38 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!task)
|
2010-01-09 18:29:00 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Taskbar *taskbar = task->area.parent;
|
2010-01-09 18:29:00 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
GList *l0 = taskbar->area.children;
|
|
|
|
if (taskbarname_enabled)
|
|
|
|
l0 = l0->next;
|
|
|
|
GList *lfirst_task = l0;
|
|
|
|
for (; l0; l0 = l0->next) {
|
|
|
|
Task *task1 = l0->data;
|
|
|
|
if (task1 == task) {
|
|
|
|
l0 = l0->next ? l0->next : lfirst_task;
|
2010-01-09 18:29:00 +00:00
|
|
|
return l0->data;
|
2009-11-18 05:13:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-09 18:29:00 +00:00
|
|
|
return 0;
|
2009-11-18 05:13:38 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *prev_task(Task *task)
|
2009-11-18 05:13:38 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!task)
|
2010-01-09 18:29:00 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Taskbar *taskbar = task->area.parent;
|
|
|
|
|
|
|
|
Task *task2 = NULL;
|
|
|
|
GList *l0 = taskbar->area.children;
|
|
|
|
if (taskbarname_enabled)
|
|
|
|
l0 = l0->next;
|
|
|
|
GList *lfirst_task = l0;
|
|
|
|
for (; l0; l0 = l0->next) {
|
|
|
|
Task *task1 = l0->data;
|
|
|
|
if (task1 == task) {
|
|
|
|
if (l0 == lfirst_task) {
|
|
|
|
l0 = g_list_last(l0);
|
|
|
|
task2 = l0->data;
|
2009-11-18 05:13:38 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
return task2;
|
2009-11-18 05:13:38 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
task2 = task1;
|
2009-11-18 05:13:38 +00:00
|
|
|
}
|
|
|
|
|
2010-01-09 18:29:00 +00:00
|
|
|
return 0;
|
2009-11-18 05:13:38 +00:00
|
|
|
}
|
|
|
|
|
2009-10-23 21:28:44 +00:00
|
|
|
void active_task()
|
|
|
|
{
|
|
|
|
if (task_active) {
|
2010-01-09 18:29:00 +00:00
|
|
|
set_task_state(task_active, window_is_iconified(task_active->win) ? TASK_ICONIFIED : TASK_NORMAL);
|
2009-10-23 21:28:44 +00:00
|
|
|
task_active = 0;
|
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Window w1 = get_active_window();
|
|
|
|
// printf("Change active task %ld\n", w1);
|
2009-10-23 22:20:42 +00:00
|
|
|
|
2010-01-09 18:29:00 +00:00
|
|
|
if (w1) {
|
2010-08-18 12:32:08 +00:00
|
|
|
if (!task_get_tasks(w1)) {
|
|
|
|
Window w2;
|
|
|
|
while (XGetTransientForHint(server.dsp, w1, &w2))
|
|
|
|
w1 = w2;
|
|
|
|
}
|
2010-01-09 18:29:00 +00:00
|
|
|
set_task_state((task_active = task_get_task(w1)), TASK_ACTIVE);
|
2009-10-23 21:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void set_task_state(Task *task, TaskState state)
|
2010-01-09 00:11:01 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!task || state < 0 || state >= TASK_STATE_COUNT)
|
2010-01-09 18:29:00 +00:00
|
|
|
return;
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
if (task->current_state != state || hide_task_diff_monitor) {
|
|
|
|
GPtrArray *task_group = task_get_tasks(task->win);
|
2010-01-10 15:00:40 +00:00
|
|
|
if (task_group) {
|
|
|
|
int i;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (i = 0; i < task_group->len; ++i) {
|
|
|
|
Task *task1 = g_ptr_array_index(task_group, i);
|
|
|
|
task1->current_state = state;
|
|
|
|
task1->area.bg = panels[0].g_task.background[state];
|
2015-11-04 11:19:23 +00:00
|
|
|
if (!panel_config.mouse_effects) {
|
2015-11-20 22:28:37 +00:00
|
|
|
task1->area.pix = task1->state_pix[state];
|
|
|
|
if (!task1->area.pix)
|
|
|
|
task1->area.redraw_needed = TRUE;
|
2015-11-04 11:19:23 +00:00
|
|
|
} else {
|
2015-11-20 22:28:37 +00:00
|
|
|
task1->area.redraw_needed = TRUE;
|
2015-11-04 11:19:23 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (state == TASK_ACTIVE && g_slist_find(urgent_list, task1))
|
|
|
|
del_urgent(task1);
|
2015-03-21 09:49:10 +00:00
|
|
|
int hide = 0;
|
2015-11-20 22:28:37 +00:00
|
|
|
Taskbar *taskbar = (Taskbar *)task1->area.parent;
|
|
|
|
if (task->desktop == ALLDESKTOP && server.desktop != taskbar->desktop) {
|
2015-08-01 06:22:08 +00:00
|
|
|
// Hide ALLDESKTOP task on non-current desktop
|
|
|
|
hide = 1;
|
|
|
|
}
|
2015-03-20 21:19:02 +00:00
|
|
|
if (hide_inactive_tasks) {
|
2015-08-01 06:22:08 +00:00
|
|
|
// Show only the active task
|
2015-03-20 21:19:02 +00:00
|
|
|
if (state != TASK_ACTIVE) {
|
2015-03-21 09:49:10 +00:00
|
|
|
hide = 1;
|
2015-03-20 21:19:02 +00:00
|
|
|
}
|
2015-03-21 09:49:10 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (get_window_monitor(task->win) != ((Panel *)task->area.panel)->monitor &&
|
|
|
|
(hide_task_diff_monitor || num_panels > 1)) {
|
2015-03-21 09:49:10 +00:00
|
|
|
hide = 1;
|
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
if (1 - hide != task1->area.on_screen) {
|
|
|
|
task1->area.on_screen = TRUE - hide;
|
|
|
|
set_task_redraw(task1);
|
|
|
|
Panel *p = (Panel *)task->area.panel;
|
|
|
|
task->area.resize_needed = 1;
|
2015-11-18 20:57:10 +00:00
|
|
|
p->taskbar->area.resize_needed = 1;
|
|
|
|
p->area.resize_needed = 1;
|
2015-03-20 21:19:02 +00:00
|
|
|
}
|
2010-01-10 15:00:40 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
panel_refresh = TRUE;
|
2010-01-09 18:29:00 +00:00
|
|
|
}
|
2010-01-09 09:34:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void set_task_redraw(Task *task)
|
2010-01-09 18:29:00 +00:00
|
|
|
{
|
2010-01-09 09:34:15 +00:00
|
|
|
int k;
|
2015-11-20 22:28:37 +00:00
|
|
|
for (k = 0; k < TASK_STATE_COUNT; ++k) {
|
|
|
|
if (task->state_pix[k])
|
|
|
|
XFreePixmap(server.dsp, task->state_pix[k]);
|
|
|
|
task->state_pix[k] = 0;
|
2010-01-09 09:34:15 +00:00
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
task->area.pix = 0;
|
|
|
|
task->area.redraw_needed = TRUE;
|
2010-01-09 00:11:01 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void blink_urgent(void *arg)
|
2009-11-15 16:55:50 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
GSList *urgent_task = urgent_list;
|
2009-11-15 16:55:50 +00:00
|
|
|
while (urgent_task) {
|
2015-11-20 22:28:37 +00:00
|
|
|
Task *t = urgent_task->data;
|
|
|
|
if (t->urgent_tick < max_tick_urgent) {
|
2010-01-09 00:11:01 +00:00
|
|
|
if (t->urgent_tick++ % 2)
|
|
|
|
set_task_state(t, TASK_URGENT);
|
|
|
|
else
|
|
|
|
set_task_state(t, window_is_iconified(t->win) ? TASK_ICONIFIED : TASK_NORMAL);
|
2009-11-15 16:55:50 +00:00
|
|
|
}
|
|
|
|
urgent_task = urgent_task->next;
|
|
|
|
}
|
2015-11-20 22:28:37 +00:00
|
|
|
panel_refresh = TRUE;
|
2009-11-15 16:55:50 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void add_urgent(Task *task)
|
2009-11-11 20:09:34 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
if (!task)
|
2009-11-26 09:25:38 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// some programs set urgency hint although they are active
|
2015-11-20 22:28:37 +00:00
|
|
|
if (task_active && task_active->win == task->win)
|
2009-11-26 09:25:38 +00:00
|
|
|
return;
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
task = 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))
|
2010-01-09 18:29:00 +00:00
|
|
|
return;
|
2009-11-11 20:09:34 +00:00
|
|
|
|
|
|
|
// not yet in the list, so we have to add it
|
2015-11-20 22:28:37 +00:00
|
|
|
urgent_list = g_slist_prepend(urgent_list, task);
|
2009-11-15 16:55:50 +00:00
|
|
|
|
2015-04-11 09:51:10 +00:00
|
|
|
if (!urgent_timeout)
|
2015-04-17 20:17:25 +00:00
|
|
|
urgent_timeout = add_timeout(10, 1000, blink_urgent, 0, &urgent_timeout);
|
2015-03-20 20:54:57 +00:00
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
Panel *panel = task->area.panel;
|
2015-03-20 20:54:57 +00:00
|
|
|
if (panel->is_hidden)
|
|
|
|
autohide_show(panel);
|
2009-11-11 20:09:34 +00:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:28:37 +00:00
|
|
|
void del_urgent(Task *task)
|
2009-11-11 20:09:34 +00:00
|
|
|
{
|
2015-11-20 22:28:37 +00:00
|
|
|
urgent_list = g_slist_remove(urgent_list, task);
|
2015-04-11 09:51:10 +00:00
|
|
|
if (!urgent_list) {
|
2009-12-29 19:55:25 +00:00
|
|
|
stop_timeout(urgent_timeout);
|
2015-04-11 09:51:10 +00:00
|
|
|
urgent_timeout = NULL;
|
2009-11-11 20:09:34 +00:00
|
|
|
}
|
|
|
|
}
|