]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
add comment
[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
45 guint win_hash(gconstpointer key) { return (guint)*((Window*)key); }
46 gboolean win_compare(gconstpointer a, gconstpointer b) { return (*((Window*)a) == *((Window*)b)); }
47 void free_ptr_array(gpointer data) { g_ptr_array_free(data, 1); }
48
49 void init_taskbar()
50 {
51 Panel *panel;
52 int i, j;
53
54 if (win_to_task_table == 0)
55 win_to_task_table = g_hash_table_new_full(win_hash, win_compare, free, free_ptr_array);
56
57 task_active = 0;
58 task_drag = 0;
59
60 for (i=0 ; i < nb_panel ; i++) {
61 panel = &panel1[i];
62
63 if (panel->taskbar) {
64 free(panel->taskbar);
65 panel->taskbar = 0;
66 }
67
68 if (panel->g_taskbar.bg == 0) {
69 panel->g_taskbar.bg = &g_array_index(backgrounds, Background, 0);
70 panel->g_taskbar.area.bg = panel->g_taskbar.bg;
71 }
72 if (panel->g_taskbar.bg_active == 0)
73 panel->g_taskbar.bg_active = panel->g_taskbar.bg;
74 if (panel->g_task.area.bg == 0)
75 panel->g_task.area.bg = &g_array_index(backgrounds, Background, 0);
76
77 // taskbar
78 panel->g_taskbar.area.size_mode = SIZE_BY_LAYOUT;
79 panel->g_taskbar.area._resize = resize_taskbar;
80 panel->g_taskbar.area.redraw = 1;
81 panel->g_taskbar.area.on_screen = 1;
82 if (panel_horizontal) {
83 panel->g_taskbar.area.posy = panel->area.bg->border.width + panel->area.paddingy;
84 panel->g_taskbar.area.height = panel->area.height - (2 * panel->g_taskbar.area.posy);
85 }
86 else {
87 panel->g_taskbar.area.posx = panel->area.bg->border.width + panel->area.paddingy;
88 panel->g_taskbar.area.width = panel->area.width - (2 * panel->g_taskbar.area.posx);
89 }
90
91 // task
92 panel->g_task.area.size_mode = SIZE_BY_LAYOUT;
93 panel->g_task.area._draw_foreground = draw_task;
94 panel->g_task.area.redraw = 1;
95 panel->g_task.area.on_screen = 1;
96 if ((panel->g_task.config_asb_mask & (1<<TASK_NORMAL)) == 0) {
97 panel->g_task.alpha[TASK_NORMAL] = 100;
98 panel->g_task.saturation[TASK_NORMAL] = 0;
99 panel->g_task.brightness[TASK_NORMAL] = 0;
100 }
101 if ((panel->g_task.config_asb_mask & (1<<TASK_ACTIVE)) == 0) {
102 panel->g_task.alpha[TASK_ACTIVE] = panel->g_task.alpha[TASK_NORMAL];
103 panel->g_task.saturation[TASK_ACTIVE] = panel->g_task.saturation[TASK_NORMAL];
104 panel->g_task.brightness[TASK_ACTIVE] = panel->g_task.brightness[TASK_NORMAL];
105 }
106 if ((panel->g_task.config_asb_mask & (1<<TASK_ICONIFIED)) == 0) {
107 panel->g_task.alpha[TASK_ICONIFIED] = panel->g_task.alpha[TASK_NORMAL];
108 panel->g_task.saturation[TASK_ICONIFIED] = panel->g_task.saturation[TASK_NORMAL];
109 panel->g_task.brightness[TASK_ICONIFIED] = panel->g_task.brightness[TASK_NORMAL];
110 }
111 if ((panel->g_task.config_asb_mask & (1<<TASK_URGENT)) == 0) {
112 panel->g_task.alpha[TASK_URGENT] = panel->g_task.alpha[TASK_ACTIVE];
113 panel->g_task.saturation[TASK_URGENT] = panel->g_task.saturation[TASK_ACTIVE];
114 panel->g_task.brightness[TASK_URGENT] = panel->g_task.brightness[TASK_ACTIVE];
115 }
116 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.font[TASK_NORMAL] = (Color){{0, 0, 0}, 0};
117 if ((panel->g_task.config_font_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.font[TASK_ACTIVE] = panel->g_task.font[TASK_NORMAL];
118 if ((panel->g_task.config_font_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.font[TASK_ICONIFIED] = panel->g_task.font[TASK_NORMAL];
119 if ((panel->g_task.config_font_mask & (1<<TASK_URGENT)) == 0) panel->g_task.font[TASK_URGENT] = panel->g_task.font[TASK_ACTIVE];
120 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.background[TASK_NORMAL] = &g_array_index(backgrounds, Background, 0);
121 if ((panel->g_task.config_background_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.background[TASK_ACTIVE] = panel->g_task.background[TASK_NORMAL];
122 if ((panel->g_task.config_background_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.background[TASK_ICONIFIED] = panel->g_task.background[TASK_NORMAL];
123 if ((panel->g_task.config_background_mask & (1<<TASK_URGENT)) == 0) panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
124
125 if (panel_horizontal) {
126 panel->g_task.area.posy = panel->g_taskbar.area.posy + panel->g_taskbar.bg->border.width + panel->g_taskbar.area.paddingy;
127 panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
128 }
129 else {
130 panel->g_task.area.posx = panel->g_taskbar.area.posx + panel->g_taskbar.bg->border.width + panel->g_taskbar.area.paddingy;
131 panel->g_task.area.width = panel->area.width - (2 * panel->g_task.area.posx);
132 panel->g_task.area.height = panel->g_task.maximum_height;
133 }
134
135 int k;
136 for (k=0; k<TASK_STATE_COUNT; ++k) {
137 if (panel->g_task.background[k]->border.rounded > panel->g_task.area.height/2) {
138 printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", k==0 ? "_" : k==1 ? "_active_" : k==2 ? "_iconified_" : "_urgent_");
139 g_array_append_val(backgrounds, *panel->g_task.background[k]);
140 panel->g_task.background[k] = &g_array_index(backgrounds, Background, backgrounds->len-1);
141 panel->g_task.background[k]->border.rounded = panel->g_task.area.height/2;
142 }
143 }
144
145 // compute vertical position : text and icon
146 int height_ink, height;
147 get_text_size(panel->g_task.font_desc, &height_ink, &height, panel->area.height, "TAjpg", 5);
148
149 if (!panel->g_task.maximum_width && panel_horizontal)
150 panel->g_task.maximum_width = server.monitor[panel->monitor].width;
151
152 panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
153 panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
154 if (panel->g_task.icon) {
155 panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
156 panel->g_task.text_posx += panel->g_task.icon_size1;
157 panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
158 }
159 //printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
160
161 Taskbar *tskbar;
162 panel->nb_desktop = server.nb_desktop;
163 panel->taskbar = calloc(panel->nb_desktop, sizeof(Taskbar));
164 for (j=0 ; j < panel->nb_desktop ; j++) {
165 tskbar = &panel->taskbar[j];
166 memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area));
167 tskbar->desktop = j;
168 if (j == server.desktop && panel->g_taskbar.use_active)
169 tskbar->area.bg = panel->g_taskbar.bg_active;
170
171 // add taskbar to the panel
172 panel->area.list = g_slist_append(panel->area.list, tskbar);
173 }
174 }
175 }
176
177 void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data)
178 {
179 remove_task(task_get_task(*(Window*)key));
180 }
181
182 void default_taskbar()
183 {
184 win_to_task_table = 0;
185 urgent_timeout = 0;
186 urgent_list = 0;
187 }
188
189 void cleanup_taskbar()
190 {
191 Panel *panel;
192 Taskbar *tskbar;
193 int i, j;
194
195 if (win_to_task_table) g_hash_table_foreach(win_to_task_table, taskbar_remove_task, 0);
196 for (i=0 ; i < nb_panel ; i++) {
197 panel = &panel1[i];
198 for (j=0 ; j < panel->nb_desktop ; j++) {
199 tskbar = &panel->taskbar[j];
200 free_area (&tskbar->area);
201 // remove taskbar from the panel
202 panel->area.list = g_slist_remove(panel->area.list, tskbar);
203 }
204 if (panel->taskbar) {
205 free(panel->taskbar);
206 panel->taskbar = 0;
207 }
208 }
209
210 if (win_to_task_table) {
211 g_hash_table_destroy(win_to_task_table);
212 win_to_task_table = 0;
213 }
214 }
215
216
217 Task *task_get_task (Window win)
218 {
219 GPtrArray* task_group = task_get_tasks(win);
220 if (task_group)
221 return g_ptr_array_index(task_group, 0);
222 else
223 return 0;
224 }
225
226
227 GPtrArray* task_get_tasks(Window win)
228 {
229 if (win_to_task_table)
230 return g_hash_table_lookup(win_to_task_table, &win);
231 else
232 return 0;
233 }
234
235
236 void task_refresh_tasklist ()
237 {
238 Window *win;
239 int num_results, i;
240
241 win = server_get_property (server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
242 if (!win) return;
243
244 GList* win_list = g_hash_table_get_keys(win_to_task_table);
245 GList* it;
246 for (it=win_list; it; it=it->next) {
247 for (i = 0; i < num_results; i++)
248 if (*((Window*)it->data) == win[i])
249 break;
250 if (i == num_results)
251 taskbar_remove_task(it->data, 0, 0);
252 }
253 g_list_free(win_list);
254
255 // Add any new
256 for (i = 0; i < num_results; i++)
257 if (!task_get_task (win[i]))
258 add_task (win[i]);
259
260 XFree (win);
261 }
262
263
264 int resize_taskbar(void *obj)
265 {
266 Taskbar *taskbar = (Taskbar*)obj;
267 Panel *panel = (Panel*)taskbar->area.panel;
268 Task *tsk;
269 GSList *l;
270 int task_count, border_width;
271
272 //printf("resize_taskbar : posx et width des taches\n");
273 taskbar->area.redraw = 1;
274
275 border_width = taskbar->area.bg->border.width;
276
277 if (panel_horizontal) {
278 int pixel_width, modulo_width=0;
279 int x, taskbar_width;
280
281 // new task width for 'desktop'
282 task_count = g_slist_length(taskbar->area.list);
283 if (!task_count) pixel_width = panel->g_task.maximum_width;
284 else {
285 taskbar_width = taskbar->area.width - (2 * border_width) - (2 * panel->g_taskbar.area.paddingxlr);
286 if (task_count>1) taskbar_width -= ((task_count-1) * panel->g_taskbar.area.paddingx);
287
288 pixel_width = taskbar_width / task_count;
289 if (pixel_width > panel->g_task.maximum_width)
290 pixel_width = panel->g_task.maximum_width;
291 else
292 modulo_width = taskbar_width % task_count;
293 }
294
295 taskbar->task_width = pixel_width;
296 taskbar->task_modulo = modulo_width;
297 taskbar->text_width = pixel_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
298
299 // change pos_x and width for all tasks
300 x = taskbar->area.posx + border_width + taskbar->area.paddingxlr;
301 for (l = taskbar->area.list; l ; l = l->next) {
302 tsk = l->data;
303 if (!tsk->area.on_screen) continue;
304 tsk->area.posx = x;
305 set_task_redraw(tsk); // always redraw task, because the background could have changed (taskbar_active_id)
306 tsk->area.width = pixel_width;
307 long value[] = { panel->posx+x, panel->posy, pixel_width, panel->area.height };
308 XChangeProperty (server.dsp, tsk->win, server.atom._NET_WM_ICON_GEOMETRY, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)value, 4);
309
310 if (modulo_width) {
311 tsk->area.width++;
312 modulo_width--;
313 }
314
315 x += tsk->area.width + panel->g_taskbar.area.paddingx;
316 }
317 }
318 else {
319 int pixel_height, modulo_height=0;
320 int y, taskbar_height;
321
322 // new task width for 'desktop'
323 task_count = g_slist_length(taskbar->area.list);
324 if (!task_count) pixel_height = panel->g_task.maximum_height;
325 else {
326 taskbar_height = taskbar->area.height - (2 * border_width) - (2 * panel->g_taskbar.area.paddingxlr);
327 if (task_count>1) taskbar_height -= ((task_count-1) * panel->g_taskbar.area.paddingx);
328
329 pixel_height = taskbar_height / task_count;
330 if (pixel_height > panel->g_task.maximum_height)
331 pixel_height = panel->g_task.maximum_height;
332 else
333 modulo_height = taskbar_height % task_count;
334 }
335
336 taskbar->task_width = pixel_height;
337 taskbar->task_modulo = modulo_height;
338 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;
339
340 // change pos_y and height for all tasks
341 y = taskbar->area.posy + border_width + taskbar->area.paddingxlr;
342 for (l = taskbar->area.list; l ; l = l->next) {
343 tsk = l->data;
344 if (!tsk->area.on_screen) continue;
345 tsk->area.posy = y;
346 set_task_redraw(tsk); // always redraw task, because the background could have changed (taskbar_active_id)
347 tsk->area.height = pixel_height;
348 long value[] = { panel->posx, panel->posy+y, panel->area.width, pixel_height };
349 XChangeProperty (server.dsp, tsk->win, server.atom._NET_WM_ICON_GEOMETRY, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)value, 4);
350
351 if (modulo_height) {
352 tsk->area.height++;
353 modulo_height--;
354 }
355
356 y += tsk->area.height + panel->g_taskbar.area.paddingx;
357 }
358 }
359 return 0;
360 }
This page took 0.046739 seconds and 4 git commands to generate.