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