]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
memorized taskbar pixmap. So we don t redraw taskbar/task when switching desktop.
[chaz/tint2] / src / taskbar / taskbar.c
1 /**************************************************************************
2 *
3 * Tint2 : taskbar
4 *
5 * Copyright (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **************************************************************************/
19
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include <X11/Xatom.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <Imlib2.h>
28
29 #include "task.h"
30 #include "taskbar.h"
31 #include "server.h"
32 #include "window.h"
33 #include "panel.h"
34
35
36 /* win_to_task_table holds for every Window an array of tasks. Usually the array contains only one
37 element. However for omnipresent windows (windows which are visible in every taskbar) the array
38 contains to every Task* on each panel a pointer (i.e. GPtrArray.len == server.nb_desktop)
39 */
40 GHashTable* win_to_task_table;
41
42 Task *task_active;
43 Task *task_drag;
44 int taskbar_enabled;
45
46 guint win_hash(gconstpointer key) { return (guint)*((Window*)key); }
47 gboolean win_compare(gconstpointer a, gconstpointer b) { return (*((Window*)a) == *((Window*)b)); }
48 void free_ptr_array(gpointer data) { g_ptr_array_free(data, 1); }
49
50
51 void default_taskbar()
52 {
53 win_to_task_table = 0;
54 urgent_timeout = 0;
55 urgent_list = 0;
56 taskbar_enabled = 0;
57 }
58
59 void cleanup_taskbar()
60 {
61 Panel *panel;
62 Taskbar *tskbar;
63 int i, j;
64
65 if (win_to_task_table) g_hash_table_foreach(win_to_task_table, taskbar_remove_task, 0);
66 for (i=0 ; i < nb_panel ; i++) {
67 panel = &panel1[i];
68 for (j=0 ; j < panel->nb_desktop ; j++) {
69 tskbar = &panel->taskbar[j];
70 free_area (&tskbar->area);
71 // remove taskbar from the panel
72 panel->area.list = g_slist_remove(panel->area.list, tskbar);
73 }
74 if (panel->taskbar) {
75 free(panel->taskbar);
76 panel->taskbar = 0;
77 }
78 }
79
80 if (win_to_task_table) {
81 g_hash_table_destroy(win_to_task_table);
82 win_to_task_table = 0;
83 }
84 }
85
86
87 void init_taskbar()
88 {
89 if (win_to_task_table == 0)
90 win_to_task_table = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
91
92 task_active = 0;
93 task_drag = 0;
94 }
95
96
97 void init_taskbar_panel(void *p)
98 {
99 Panel *panel =(Panel*)p;
100 int j;
101
102 if (panel->g_taskbar.background[TASKBAR_NORMAL] == 0) {
103 panel->g_taskbar.background[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
104 panel->g_taskbar.background[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
105 }
106 if (panel->g_task.area.bg == 0)
107 panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
108
109 // taskbar
110 panel->g_taskbar.area.size_mode = SIZE_BY_LAYOUT;
111 panel->g_taskbar.area._resize = resize_taskbar;
112 panel->g_taskbar.area._draw_foreground = draw_taskbar;
113 panel->g_taskbar.area.redraw = 1;
114 panel->g_taskbar.area.on_screen = 1;
115 if (panel_horizontal) {
116 panel->g_taskbar.area.posy = panel->area.bg->border.width + panel->area.paddingy;
117 panel->g_taskbar.area.height = panel->area.height - (2 * panel->g_taskbar.area.posy);
118 }
119 else {
120 panel->g_taskbar.area.posx = panel->area.bg->border.width + panel->area.paddingy;
121 panel->g_taskbar.area.width = panel->area.width - (2 * panel->g_taskbar.area.posx);
122 }
123
124 // task
125 panel->g_task.area.size_mode = SIZE_BY_LAYOUT;
126 panel->g_task.area._draw_foreground = draw_task;
127 panel->g_task.area._on_change_layout = on_change_task;
128 panel->g_task.area.redraw = 1;
129 panel->g_task.area.on_screen = 1;
130 if ((panel->g_task.config_asb_mask & (1<<TASK_NORMAL)) == 0) {
131 panel->g_task.alpha[TASK_NORMAL] = 100;
132 panel->g_task.saturation[TASK_NORMAL] = 0;
133 panel->g_task.brightness[TASK_NORMAL] = 0;
134 }
135 if ((panel->g_task.config_asb_mask & (1<<TASK_ACTIVE)) == 0) {
136 panel->g_task.alpha[TASK_ACTIVE] = panel->g_task.alpha[TASK_NORMAL];
137 panel->g_task.saturation[TASK_ACTIVE] = panel->g_task.saturation[TASK_NORMAL];
138 panel->g_task.brightness[TASK_ACTIVE] = panel->g_task.brightness[TASK_NORMAL];
139 }
140 if ((panel->g_task.config_asb_mask & (1<<TASK_ICONIFIED)) == 0) {
141 panel->g_task.alpha[TASK_ICONIFIED] = panel->g_task.alpha[TASK_NORMAL];
142 panel->g_task.saturation[TASK_ICONIFIED] = panel->g_task.saturation[TASK_NORMAL];
143 panel->g_task.brightness[TASK_ICONIFIED] = panel->g_task.brightness[TASK_NORMAL];
144 }
145 if ((panel->g_task.config_asb_mask & (1<<TASK_URGENT)) == 0) {
146 panel->g_task.alpha[TASK_URGENT] = panel->g_task.alpha[TASK_ACTIVE];
147 panel->g_task.saturation[TASK_URGENT] = panel->g_task.saturation[TASK_ACTIVE];
148 panel->g_task.brightness[TASK_URGENT] = panel->g_task.brightness[TASK_ACTIVE];
149 }
150 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.font[TASK_NORMAL] = (Color){{0, 0, 0}, 0};
151 if ((panel->g_task.config_font_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.font[TASK_ACTIVE] = panel->g_task.font[TASK_NORMAL];
152 if ((panel->g_task.config_font_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.font[TASK_ICONIFIED] = panel->g_task.font[TASK_NORMAL];
153 if ((panel->g_task.config_font_mask & (1<<TASK_URGENT)) == 0) panel->g_task.font[TASK_URGENT] = panel->g_task.font[TASK_ACTIVE];
154 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.background[TASK_NORMAL] = &g_array_index(backgrounds, Background, 0);
155 if ((panel->g_task.config_background_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.background[TASK_ACTIVE] = panel->g_task.background[TASK_NORMAL];
156 if ((panel->g_task.config_background_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.background[TASK_ICONIFIED] = panel->g_task.background[TASK_NORMAL];
157 if ((panel->g_task.config_background_mask & (1<<TASK_URGENT)) == 0) panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
158
159 if (panel_horizontal) {
160 panel->g_task.area.posy = panel->g_taskbar.area.posy + panel->g_taskbar.background[TASKBAR_NORMAL]->border.width + panel->g_taskbar.area.paddingy;
161 panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
162 }
163 else {
164 panel->g_task.area.posx = panel->g_taskbar.area.posx + panel->g_taskbar.background[TASKBAR_NORMAL]->border.width + panel->g_taskbar.area.paddingy;
165 panel->g_task.area.width = panel->area.width - (2 * panel->g_task.area.posx);
166 panel->g_task.area.height = panel->g_task.maximum_height;
167 }
168
169 for (j=0; j<TASK_STATE_COUNT; ++j) {
170 if (panel->g_task.background[j]->border.rounded > panel->g_task.area.height/2) {
171 printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", j==0 ? "_" : j==1 ? "_active_" : j==2 ? "_iconified_" : "_urgent_");
172 g_array_append_val(backgrounds, *panel->g_task.background[j]);
173 panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len-1);
174 panel->g_task.background[j]->border.rounded = panel->g_task.area.height/2;
175 }
176 }
177
178 // compute vertical position : text and icon
179 int height_ink, height;
180 get_text_size(panel->g_task.font_desc, &height_ink, &height, panel->area.height, "TAjpg", 5);
181
182 if (!panel->g_task.maximum_width && panel_horizontal)
183 panel->g_task.maximum_width = server.monitor[panel->monitor].width;
184
185 panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
186 panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
187 if (panel->g_task.icon) {
188 panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
189 panel->g_task.text_posx += panel->g_task.icon_size1;
190 panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
191 }
192 //printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
193
194 Taskbar *tskbar;
195 panel->nb_desktop = server.nb_desktop;
196 panel->taskbar = calloc(server.nb_desktop, sizeof(Taskbar));
197 for (j=0 ; j < panel->nb_desktop ; j++) {
198 tskbar = &panel->taskbar[j];
199 memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area));
200 tskbar->desktop = j;
201 if (j == server.desktop)
202 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_ACTIVE];
203 else
204 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_NORMAL];
205 }
206 }
207
208
209 void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data)
210 {
211 remove_task(task_get_task(*(Window*)key));
212 }
213
214
215 Task *task_get_task (Window win)
216 {
217 GPtrArray* task_group = task_get_tasks(win);
218 if (task_group)
219 return g_ptr_array_index(task_group, 0);
220 else
221 return 0;
222 }
223
224
225 GPtrArray* task_get_tasks(Window win)
226 {
227 if (win_to_task_table && taskbar_enabled)
228 return g_hash_table_lookup(win_to_task_table, &win);
229 else
230 return 0;
231 }
232
233
234 void task_refresh_tasklist ()
235 {
236 Window *win;
237 int num_results, i;
238
239 if (!taskbar_enabled) return;
240 win = server_get_property (server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
241 if (!win) return;
242
243 GList* win_list = g_hash_table_get_keys(win_to_task_table);
244 GList* it;
245 for (it=win_list; it; it=it->next) {
246 for (i = 0; i < num_results; i++)
247 if (*((Window*)it->data) == win[i])
248 break;
249 if (i == num_results)
250 taskbar_remove_task(it->data, 0, 0);
251 }
252 g_list_free(win_list);
253
254 // Add any new
255 for (i = 0; i < num_results; i++)
256 if (!task_get_task (win[i]))
257 add_task (win[i]);
258
259 XFree (win);
260 }
261
262
263 void draw_taskbar (void *obj, cairo_t *c)
264 {
265 Taskbar *taskbar = obj;
266 int state = (taskbar->desktop == server.desktop) ? TASKBAR_ACTIVE : TASKBAR_NORMAL;
267
268 taskbar->state_pix[state] = taskbar->area.pix;
269 }
270
271
272 int resize_taskbar(void *obj)
273 {
274 Taskbar *taskbar = (Taskbar*)obj;
275 Panel *panel = (Panel*)taskbar->area.panel;
276 int text_width;
277 Task *tsk;
278
279 //printf("resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
280 if (panel_horizontal) {
281 resize_by_layout(obj, panel->g_task.maximum_width);
282
283 text_width = panel->g_task.maximum_width;
284 if (taskbar->area.list != NULL) {
285 tsk = taskbar->area.list->data;
286 text_width = tsk->area.width;
287 }
288 taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
289 }
290 else {
291 resize_by_layout(obj, panel->g_task.maximum_height);
292
293 taskbar->text_width = taskbar->area.width - (2 * panel->g_taskbar.area.paddingy) - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
294 }
295 return 0;
296 }
297
298
299 void set_taskbar_state(Taskbar *tskbar, int state)
300 {
301 tskbar->area.bg = panel1[0].g_taskbar.background[state];
302 tskbar->area.pix = tskbar->state_pix[state];
303 if (tskbar->state_pix[state] == 0) {
304 tskbar->area.redraw = 1;
305 GSList *l;
306 for (l = tskbar->area.list ; l ; l = l->next)
307 ((Area*)l->data)->redraw = 1;
308 }
309 panel_refresh = 1;
310 }
311
312
313 void visible_taskbar(void *p)
314 {
315 Panel *panel =(Panel*)p;
316 int j;
317
318 Taskbar *taskbar;
319 for (j=0 ; j < panel->nb_desktop ; j++) {
320 taskbar = &panel->taskbar[j];
321 if (panel_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) {
322 // SINGLE_DESKTOP and not current desktop
323 taskbar->area.on_screen = 0;
324 }
325 else {
326 taskbar->area.on_screen = 1;
327 }
328 }
329 panel_refresh = 1;
330 }
331
This page took 0.053376 seconds and 4 git commands to generate.