]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
desktop name: first step
[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_font_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]->border.rounded > panel->g_task.area.height/2) {
197 printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", j==0 ? "_" : j==1 ? "_active_" : j==2 ? "_iconified_" : "_urgent_");
198 g_array_append_val(backgrounds, *panel->g_task.background[j]);
199 panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len-1);
200 panel->g_task.background[j]->border.rounded = panel->g_task.area.height/2;
201 }
202 }
203
204 // compute vertical position : text and icon
205 int height_ink, height;
206 get_text_size(panel->g_task.font_desc, &height_ink, &height, panel->area.height, "TAjpg", 5);
207
208 if (!panel->g_task.maximum_width && panel_horizontal)
209 panel->g_task.maximum_width = server.monitor[panel->monitor].width;
210
211 panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
212 panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
213 if (panel->g_task.icon) {
214 panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
215 panel->g_task.text_posx += panel->g_task.icon_size1;
216 panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
217 }
218 //printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
219
220 Taskbar *tskbar;
221 panel->nb_desktop = server.nb_desktop;
222 panel->taskbar = calloc(server.nb_desktop, sizeof(Taskbar));
223 for (j=0 ; j < panel->nb_desktop ; j++) {
224 tskbar = &panel->taskbar[j];
225 memcpy(&tskbar->area, &panel->g_taskbar.area, sizeof(Area));
226 tskbar->desktop = j;
227 if (j == server.desktop)
228 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_ACTIVE];
229 else
230 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_NORMAL];
231
232 if (taskbarname_enabled) {
233 memcpy(&tskbar->bar_name.area, &panel->g_taskbar.area_name, sizeof(Area));
234 tskbar->bar_name.area.parent = tskbar;
235 if (j == server.desktop)
236 tskbar->bar_name.area.bg = panel->g_taskbar.background_name[TASKBAR_ACTIVE];
237 else
238 tskbar->bar_name.area.bg = panel->g_taskbar.background_name[TASKBAR_NORMAL];
239 tskbar->area.list = g_slist_append(tskbar->area.list, &tskbar->bar_name);
240 }
241 }
242 init_taskbarname_panel(panel);
243 }
244
245
246 void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data)
247 {
248 remove_task(task_get_task(*(Window*)key));
249 }
250
251
252 Task *task_get_task (Window win)
253 {
254 GPtrArray* task_group = task_get_tasks(win);
255 if (task_group)
256 return g_ptr_array_index(task_group, 0);
257 else
258 return 0;
259 }
260
261
262 GPtrArray* task_get_tasks(Window win)
263 {
264 if (win_to_task_table && taskbar_enabled)
265 return g_hash_table_lookup(win_to_task_table, &win);
266 else
267 return 0;
268 }
269
270
271 void task_refresh_tasklist ()
272 {
273 Window *win;
274 int num_results, i;
275
276 if (!taskbar_enabled) return;
277 win = server_get_property (server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
278 if (!win) return;
279
280 GList* win_list = g_hash_table_get_keys(win_to_task_table);
281 GList* it;
282 for (it=win_list; it; it=it->next) {
283 for (i = 0; i < num_results; i++)
284 if (*((Window*)it->data) == win[i])
285 break;
286 if (i == num_results)
287 taskbar_remove_task(it->data, 0, 0);
288 }
289 g_list_free(win_list);
290
291 // Add any new
292 for (i = 0; i < num_results; i++)
293 if (!task_get_task (win[i]))
294 add_task (win[i]);
295
296 XFree (win);
297 }
298
299
300 void draw_taskbar (void *obj, cairo_t *c)
301 {
302 Taskbar *taskbar = obj;
303 int state = (taskbar->desktop == server.desktop) ? TASKBAR_ACTIVE : TASKBAR_NORMAL;
304
305 taskbar->state_pix[state] = taskbar->area.pix;
306 }
307
308
309 int resize_taskbar(void *obj)
310 {
311 Taskbar *taskbar = (Taskbar*)obj;
312 Panel *panel = (Panel*)taskbar->area.panel;
313 int text_width;
314
315 //printf("resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
316 if (panel_horizontal) {
317 resize_by_layout(obj, panel->g_task.maximum_width);
318
319 text_width = panel->g_task.maximum_width;
320 GSList *l = taskbar->area.list;
321 if (taskbarname_enabled) l = l->next;
322 if (l != NULL) {
323 text_width = ((Task *)l->data)->area.width;
324 }
325 taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
326 }
327 else {
328 resize_by_layout(obj, panel->g_task.maximum_height);
329
330 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;
331 }
332 return 0;
333 }
334
335
336 void on_change_taskbar (void *obj)
337 {
338 Taskbar *tskbar = obj;
339 int k;
340
341 // reset Pixmap when position/size changed
342 for (k=0; k<TASKBAR_STATE_COUNT; ++k) {
343 if (tskbar->state_pix[k]) XFreePixmap(server.dsp, tskbar->state_pix[k]);
344 tskbar->state_pix[k] = 0;
345 }
346 tskbar->area.pix = 0;
347 tskbar->area.redraw = 1;
348 }
349
350
351 void set_taskbar_state(Taskbar *tskbar, int state)
352 {
353 tskbar->area.bg = panel1[0].g_taskbar.background[state];
354 tskbar->area.pix = tskbar->state_pix[state];
355 if (panel_mode != MULTI_DESKTOP) {
356 if (state == TASKBAR_NORMAL)
357 tskbar->area.on_screen = 0;
358 else
359 tskbar->area.on_screen = 1;
360 }
361 if (tskbar->area.on_screen == 1) {
362 if (tskbar->state_pix[state] == 0)
363 tskbar->area.redraw = 1;
364 if (panel_mode == MULTI_DESKTOP && panel1[0].g_taskbar.background[TASKBAR_NORMAL] != panel1[0].g_taskbar.background[TASKBAR_ACTIVE]) {
365 GSList *l = tskbar->area.list;
366 if (taskbarname_enabled) l = l->next;
367 for ( ; l ; l = l->next)
368 set_task_redraw(l->data);
369 }
370 }
371 panel_refresh = 1;
372 }
373
374
375 void visible_taskbar(void *p)
376 {
377 Panel *panel =(Panel*)p;
378 int j;
379
380 Taskbar *taskbar;
381 for (j=0 ; j < panel->nb_desktop ; j++) {
382 taskbar = &panel->taskbar[j];
383 if (panel_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) {
384 // SINGLE_DESKTOP and not current desktop
385 taskbar->area.on_screen = 0;
386 }
387 else {
388 taskbar->area.on_screen = 1;
389 }
390 }
391 panel_refresh = 1;
392 }
393
This page took 0.055821 seconds and 4 git commands to generate.