]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
*fix* test with config_background_mask rather than config_font_mask, since we check...
[chaz/tint2] / src / taskbar / taskbar.c
1 /**************************************************************************
2 *
3 * Tint2 : taskbar
4 *
5 * Copyright (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) from Omega distribution
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 default_taskbarname();
58 }
59
60 void cleanup_taskbar()
61 {
62 Panel *panel;
63 Taskbar *tskbar;
64 int i, j, k;
65
66 cleanup_taskbarname();
67 if (win_to_task_table) g_hash_table_foreach(win_to_task_table, taskbar_remove_task, 0);
68 for (i=0 ; i < nb_panel ; i++) {
69 panel = &panel1[i];
70 for (j=0 ; j < panel->nb_desktop ; j++) {
71 tskbar = &panel->taskbar[j];
72 for (k=0; k<TASKBAR_STATE_COUNT; ++k) {
73 if (tskbar->state_pix[k]) XFreePixmap(server.dsp, tskbar->state_pix[k]);
74 }
75 free_area (&tskbar->area);
76 // remove taskbar from the panel
77 panel->area.list = g_slist_remove(panel->area.list, tskbar);
78 }
79 if (panel->taskbar) {
80 free(panel->taskbar);
81 panel->taskbar = 0;
82 }
83 }
84
85 if (win_to_task_table) {
86 g_hash_table_destroy(win_to_task_table);
87 win_to_task_table = 0;
88 }
89 }
90
91
92 void init_taskbar()
93 {
94 if (win_to_task_table == 0)
95 win_to_task_table = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
96
97 task_active = 0;
98 task_drag = 0;
99 }
100
101
102 void init_taskbar_panel(void *p)
103 {
104 Panel *panel =(Panel*)p;
105 int j;
106
107 if (panel->g_taskbar.background[TASKBAR_NORMAL] == 0) {
108 panel->g_taskbar.background[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
109 panel->g_taskbar.background[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
110 }
111 if (panel->g_taskbar.background_name[TASKBAR_NORMAL] == 0) {
112 panel->g_taskbar.background_name[TASKBAR_NORMAL] = &g_array_index(backgrounds, Background, 0);
113 panel->g_taskbar.background_name[TASKBAR_ACTIVE] = &g_array_index(backgrounds, Background, 0);
114 }
115 if (panel->g_task.area.bg == 0)
116 panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
117
118 // taskbar name
119 panel->g_taskbar.area_name.panel = panel;
120 panel->g_taskbar.area_name.size_mode = SIZE_BY_CONTENT;
121 panel->g_taskbar.area_name._resize = resize_taskbarname;
122 panel->g_taskbar.area_name._draw_foreground = draw_taskbarname;
123 panel->g_taskbar.area_name._on_change_layout = 0;
124 panel->g_taskbar.area_name.resize = 1;
125 panel->g_taskbar.area_name.on_screen = 1;
126
127 // taskbar
128 panel->g_taskbar.area.parent = panel;
129 panel->g_taskbar.area.panel = panel;
130 panel->g_taskbar.area.size_mode = SIZE_BY_LAYOUT;
131 panel->g_taskbar.area._resize = resize_taskbar;
132 panel->g_taskbar.area._draw_foreground = draw_taskbar;
133 panel->g_taskbar.area._on_change_layout = on_change_taskbar;
134 panel->g_taskbar.area.resize = 1;
135 panel->g_taskbar.area.on_screen = 1;
136 if (panel_horizontal) {
137 panel->g_taskbar.area.posy = panel->area.bg->border.width + panel->area.paddingy;
138 panel->g_taskbar.area.height = panel->area.height - (2 * panel->g_taskbar.area.posy);
139 panel->g_taskbar.area_name.posy = panel->g_taskbar.area.posy;
140 panel->g_taskbar.area_name.height = panel->g_taskbar.area.height;
141 }
142 else {
143 panel->g_taskbar.area.posx = panel->area.bg->border.width + panel->area.paddingy;
144 panel->g_taskbar.area.width = panel->area.width - (2 * panel->g_taskbar.area.posx);
145 panel->g_taskbar.area_name.posx = panel->g_taskbar.area.posx;
146 panel->g_taskbar.area_name.width = panel->g_taskbar.area.width;
147 }
148
149 // task
150 panel->g_task.area.panel = panel;
151 panel->g_task.area.size_mode = SIZE_BY_LAYOUT;
152 panel->g_task.area._draw_foreground = draw_task;
153 panel->g_task.area._on_change_layout = on_change_task;
154 panel->g_task.area.resize = 1;
155 panel->g_task.area.on_screen = 1;
156 if ((panel->g_task.config_asb_mask & (1<<TASK_NORMAL)) == 0) {
157 panel->g_task.alpha[TASK_NORMAL] = 100;
158 panel->g_task.saturation[TASK_NORMAL] = 0;
159 panel->g_task.brightness[TASK_NORMAL] = 0;
160 }
161 if ((panel->g_task.config_asb_mask & (1<<TASK_ACTIVE)) == 0) {
162 panel->g_task.alpha[TASK_ACTIVE] = panel->g_task.alpha[TASK_NORMAL];
163 panel->g_task.saturation[TASK_ACTIVE] = panel->g_task.saturation[TASK_NORMAL];
164 panel->g_task.brightness[TASK_ACTIVE] = panel->g_task.brightness[TASK_NORMAL];
165 }
166 if ((panel->g_task.config_asb_mask & (1<<TASK_ICONIFIED)) == 0) {
167 panel->g_task.alpha[TASK_ICONIFIED] = panel->g_task.alpha[TASK_NORMAL];
168 panel->g_task.saturation[TASK_ICONIFIED] = panel->g_task.saturation[TASK_NORMAL];
169 panel->g_task.brightness[TASK_ICONIFIED] = panel->g_task.brightness[TASK_NORMAL];
170 }
171 if ((panel->g_task.config_asb_mask & (1<<TASK_URGENT)) == 0) {
172 panel->g_task.alpha[TASK_URGENT] = panel->g_task.alpha[TASK_ACTIVE];
173 panel->g_task.saturation[TASK_URGENT] = panel->g_task.saturation[TASK_ACTIVE];
174 panel->g_task.brightness[TASK_URGENT] = panel->g_task.brightness[TASK_ACTIVE];
175 }
176 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.font[TASK_NORMAL] = (Color){{0, 0, 0}, 0};
177 if ((panel->g_task.config_font_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.font[TASK_ACTIVE] = panel->g_task.font[TASK_NORMAL];
178 if ((panel->g_task.config_font_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.font[TASK_ICONIFIED] = panel->g_task.font[TASK_NORMAL];
179 if ((panel->g_task.config_font_mask & (1<<TASK_URGENT)) == 0) panel->g_task.font[TASK_URGENT] = panel->g_task.font[TASK_ACTIVE];
180 if ((panel->g_task.config_background_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.background[TASK_NORMAL] = &g_array_index(backgrounds, Background, 0);
181 if ((panel->g_task.config_background_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.background[TASK_ACTIVE] = panel->g_task.background[TASK_NORMAL];
182 if ((panel->g_task.config_background_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.background[TASK_ICONIFIED] = panel->g_task.background[TASK_NORMAL];
183 if ((panel->g_task.config_background_mask & (1<<TASK_URGENT)) == 0) panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
184
185 if (panel_horizontal) {
186 panel->g_task.area.posy = panel->g_taskbar.area.posy + panel->g_taskbar.background[TASKBAR_NORMAL]->border.width + panel->g_taskbar.area.paddingy;
187 panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
188 }
189 else {
190 panel->g_task.area.posx = panel->g_taskbar.area.posx + panel->g_taskbar.background[TASKBAR_NORMAL]->border.width + panel->g_taskbar.area.paddingy;
191 panel->g_task.area.width = panel->area.width - (2 * panel->g_task.area.posx);
192 panel->g_task.area.height = panel->g_task.maximum_height;
193 }
194
195 for (j=0; j<TASK_STATE_COUNT; ++j) {
196 if (panel->g_task.background[j] == 0)
197 panel->g_task.background[j] = &g_array_index(backgrounds, Background, 0);
198 if (panel->g_task.background[j]->border.rounded > panel->g_task.area.height/2) {
199 printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", j==0 ? "_" : j==1 ? "_active_" : j==2 ? "_iconified_" : "_urgent_");
200 g_array_append_val(backgrounds, *panel->g_task.background[j]);
201 panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len-1);
202 panel->g_task.background[j]->border.rounded = panel->g_task.area.height/2;
203 }
204 }
205
206 // compute vertical position : text and icon
207 int height_ink, height;
208 get_text_size(panel->g_task.font_desc, &height_ink, &height, panel->area.height, "TAjpg", 5);
209
210 if (!panel->g_task.maximum_width && panel_horizontal)
211 panel->g_task.maximum_width = server.monitor[panel->monitor].width;
212
213 panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
214 panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
215 if (panel->g_task.icon) {
216 panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
217 panel->g_task.text_posx += panel->g_task.icon_size1;
218 panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
219 }
220 //printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
221
222 Taskbar *tskbar;
223 panel->nb_desktop = server.nb_desktop;
224 panel->taskbar = calloc(server.nb_desktop, sizeof(Taskbar));
225 for (j=0 ; j < panel->nb_desktop ; j++) {
226 tskbar = &panel->taskbar[j];
227 memcpy(&tskbar->area, &panel->g_taskbar.area, sizeof(Area));
228 tskbar->desktop = j;
229 if (j == server.desktop)
230 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_ACTIVE];
231 else
232 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_NORMAL];
233 }
234 init_taskbarname_panel(panel);
235 }
236
237
238 void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data)
239 {
240 remove_task(task_get_task(*(Window*)key));
241 }
242
243
244 Task *task_get_task (Window win)
245 {
246 GPtrArray* task_group = task_get_tasks(win);
247 if (task_group)
248 return g_ptr_array_index(task_group, 0);
249 else
250 return 0;
251 }
252
253
254 GPtrArray* task_get_tasks(Window win)
255 {
256 if (win_to_task_table && taskbar_enabled)
257 return g_hash_table_lookup(win_to_task_table, &win);
258 else
259 return 0;
260 }
261
262
263 void task_refresh_tasklist ()
264 {
265 Window *win;
266 int num_results, i;
267
268 if (!taskbar_enabled) return;
269 win = server_get_property (server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
270 if (!win) return;
271
272 GList* win_list = g_hash_table_get_keys(win_to_task_table);
273 GList* it;
274 for (it=win_list; it; it=it->next) {
275 for (i = 0; i < num_results; i++)
276 if (*((Window*)it->data) == win[i])
277 break;
278 if (i == num_results)
279 taskbar_remove_task(it->data, 0, 0);
280 }
281 g_list_free(win_list);
282
283 // Add any new
284 for (i = 0; i < num_results; i++)
285 if (!task_get_task (win[i]))
286 add_task (win[i]);
287
288 XFree (win);
289 }
290
291
292 void draw_taskbar (void *obj, cairo_t *c)
293 {
294 Taskbar *taskbar = obj;
295 int state = (taskbar->desktop == server.desktop) ? TASKBAR_ACTIVE : TASKBAR_NORMAL;
296
297 taskbar->state_pix[state] = taskbar->area.pix;
298 }
299
300
301 int resize_taskbar(void *obj)
302 {
303 Taskbar *taskbar = (Taskbar*)obj;
304 Panel *panel = (Panel*)taskbar->area.panel;
305 int text_width;
306
307 //printf("resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
308 if (panel_horizontal) {
309 resize_by_layout(obj, panel->g_task.maximum_width);
310
311 text_width = panel->g_task.maximum_width;
312 GSList *l = taskbar->area.list;
313 if (taskbarname_enabled) l = l->next;
314 if (l != NULL) {
315 text_width = ((Task *)l->data)->area.width;
316 }
317 taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
318 }
319 else {
320 resize_by_layout(obj, panel->g_task.maximum_height);
321
322 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;
323 }
324 return 0;
325 }
326
327
328 void on_change_taskbar (void *obj)
329 {
330 Taskbar *tskbar = obj;
331 int k;
332
333 // reset Pixmap when position/size changed
334 for (k=0; k<TASKBAR_STATE_COUNT; ++k) {
335 if (tskbar->state_pix[k]) XFreePixmap(server.dsp, tskbar->state_pix[k]);
336 tskbar->state_pix[k] = 0;
337 }
338 tskbar->area.pix = 0;
339 tskbar->area.redraw = 1;
340 }
341
342
343 void set_taskbar_state(Taskbar *tskbar, int state)
344 {
345 tskbar->area.bg = panel1[0].g_taskbar.background[state];
346 tskbar->area.pix = tskbar->state_pix[state];
347 if (taskbarname_enabled) {
348 tskbar->bar_name.area.bg = panel1[0].g_taskbar.background_name[state];
349 tskbar->bar_name.area.pix = tskbar->bar_name.state_pix[state];
350 }
351 if (panel_mode != MULTI_DESKTOP) {
352 if (state == TASKBAR_NORMAL)
353 tskbar->area.on_screen = 0;
354 else
355 tskbar->area.on_screen = 1;
356 }
357 if (tskbar->area.on_screen == 1) {
358 if (tskbar->state_pix[state] == 0)
359 tskbar->area.redraw = 1;
360 if (taskbarname_enabled && tskbar->bar_name.state_pix[state] == 0)
361 tskbar->bar_name.area.redraw = 1;
362 if (panel_mode == MULTI_DESKTOP && panel1[0].g_taskbar.background[TASKBAR_NORMAL] != panel1[0].g_taskbar.background[TASKBAR_ACTIVE]) {
363 GSList *l = tskbar->area.list;
364 if (taskbarname_enabled) l = l->next;
365 for ( ; l ; l = l->next)
366 set_task_redraw(l->data);
367 }
368 }
369 panel_refresh = 1;
370 }
371
372
373 void visible_taskbar(void *p)
374 {
375 Panel *panel =(Panel*)p;
376 int j;
377
378 Taskbar *taskbar;
379 for (j=0 ; j < panel->nb_desktop ; j++) {
380 taskbar = &panel->taskbar[j];
381 if (panel_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) {
382 // SINGLE_DESKTOP and not current desktop
383 taskbar->area.on_screen = 0;
384 }
385 else {
386 taskbar->area.on_screen = 1;
387 }
388 }
389 panel_refresh = 1;
390 }
391
This page took 0.049535 seconds and 4 git commands to generate.