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