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