]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
rendering engine : _on_change_layout() called when pos/size changed
[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._on_change_layout = on_change_task;
129 panel->g_task.area.redraw = 1;
130 panel->g_task.area.on_screen = 1;
131 if ((panel->g_task.config_asb_mask & (1<<TASK_NORMAL)) == 0) {
132 panel->g_task.alpha[TASK_NORMAL] = 100;
133 panel->g_task.saturation[TASK_NORMAL] = 0;
134 panel->g_task.brightness[TASK_NORMAL] = 0;
135 }
136 if ((panel->g_task.config_asb_mask & (1<<TASK_ACTIVE)) == 0) {
137 panel->g_task.alpha[TASK_ACTIVE] = panel->g_task.alpha[TASK_NORMAL];
138 panel->g_task.saturation[TASK_ACTIVE] = panel->g_task.saturation[TASK_NORMAL];
139 panel->g_task.brightness[TASK_ACTIVE] = panel->g_task.brightness[TASK_NORMAL];
140 }
141 if ((panel->g_task.config_asb_mask & (1<<TASK_ICONIFIED)) == 0) {
142 panel->g_task.alpha[TASK_ICONIFIED] = panel->g_task.alpha[TASK_NORMAL];
143 panel->g_task.saturation[TASK_ICONIFIED] = panel->g_task.saturation[TASK_NORMAL];
144 panel->g_task.brightness[TASK_ICONIFIED] = panel->g_task.brightness[TASK_NORMAL];
145 }
146 if ((panel->g_task.config_asb_mask & (1<<TASK_URGENT)) == 0) {
147 panel->g_task.alpha[TASK_URGENT] = panel->g_task.alpha[TASK_ACTIVE];
148 panel->g_task.saturation[TASK_URGENT] = panel->g_task.saturation[TASK_ACTIVE];
149 panel->g_task.brightness[TASK_URGENT] = panel->g_task.brightness[TASK_ACTIVE];
150 }
151 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.font[TASK_NORMAL] = (Color){{0, 0, 0}, 0};
152 if ((panel->g_task.config_font_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.font[TASK_ACTIVE] = panel->g_task.font[TASK_NORMAL];
153 if ((panel->g_task.config_font_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.font[TASK_ICONIFIED] = panel->g_task.font[TASK_NORMAL];
154 if ((panel->g_task.config_font_mask & (1<<TASK_URGENT)) == 0) panel->g_task.font[TASK_URGENT] = panel->g_task.font[TASK_ACTIVE];
155 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.background[TASK_NORMAL] = &g_array_index(backgrounds, Background, 0);
156 if ((panel->g_task.config_background_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.background[TASK_ACTIVE] = panel->g_task.background[TASK_NORMAL];
157 if ((panel->g_task.config_background_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.background[TASK_ICONIFIED] = panel->g_task.background[TASK_NORMAL];
158 if ((panel->g_task.config_background_mask & (1<<TASK_URGENT)) == 0) panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
159
160 if (panel_horizontal) {
161 panel->g_task.area.posy = panel->g_taskbar.area.posy + panel->g_taskbar.bg->border.width + panel->g_taskbar.area.paddingy;
162 panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
163 }
164 else {
165 panel->g_task.area.posx = panel->g_taskbar.area.posx + panel->g_taskbar.bg->border.width + panel->g_taskbar.area.paddingy;
166 panel->g_task.area.width = panel->area.width - (2 * panel->g_task.area.posx);
167 panel->g_task.area.height = panel->g_task.maximum_height;
168 }
169
170 for (j=0; j<TASK_STATE_COUNT; ++j) {
171 if (panel->g_task.background[j]->border.rounded > panel->g_task.area.height/2) {
172 printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", j==0 ? "_" : j==1 ? "_active_" : j==2 ? "_iconified_" : "_urgent_");
173 g_array_append_val(backgrounds, *panel->g_task.background[j]);
174 panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len-1);
175 panel->g_task.background[j]->border.rounded = panel->g_task.area.height/2;
176 }
177 }
178
179 // compute vertical position : text and icon
180 int height_ink, height;
181 get_text_size(panel->g_task.font_desc, &height_ink, &height, panel->area.height, "TAjpg", 5);
182
183 if (!panel->g_task.maximum_width && panel_horizontal)
184 panel->g_task.maximum_width = server.monitor[panel->monitor].width;
185
186 panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
187 panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
188 if (panel->g_task.icon) {
189 panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
190 panel->g_task.text_posx += panel->g_task.icon_size1;
191 panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
192 }
193 //printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
194
195 Taskbar *tskbar;
196 panel->nb_desktop = server.nb_desktop;
197 panel->taskbar = calloc(server.nb_desktop, sizeof(Taskbar));
198 for (j=0 ; j < panel->nb_desktop ; j++) {
199 tskbar = &panel->taskbar[j];
200 memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area));
201 tskbar->desktop = j;
202 if (j == server.desktop)
203 tskbar->area.bg = panel->g_taskbar.bg_active;
204 }
205 }
206
207
208 void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data)
209 {
210 remove_task(task_get_task(*(Window*)key));
211 }
212
213
214 Task *task_get_task (Window win)
215 {
216 GPtrArray* task_group = task_get_tasks(win);
217 if (task_group)
218 return g_ptr_array_index(task_group, 0);
219 else
220 return 0;
221 }
222
223
224 GPtrArray* task_get_tasks(Window win)
225 {
226 if (win_to_task_table && taskbar_enabled)
227 return g_hash_table_lookup(win_to_task_table, &win);
228 else
229 return 0;
230 }
231
232
233 void task_refresh_tasklist ()
234 {
235 Window *win;
236 int num_results, i;
237
238 if (!taskbar_enabled) return;
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 int 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 %d %d\n", taskbar->area.posx, taskbar->area.posy);
271 // taskbar->area.redraw = 1;
272 border_width = taskbar->area.bg->border.width;
273
274 if (panel_horizontal) {
275 int pixel_width, modulo_width=0;
276 int taskbar_width;
277
278 // new task width for 'desktop'
279 task_count = g_slist_length(taskbar->area.list);
280 if (!task_count) pixel_width = panel->g_task.maximum_width;
281 else {
282 taskbar_width = taskbar->area.width - (2 * border_width) - (2 * panel->g_taskbar.area.paddingxlr);
283 if (task_count>1) taskbar_width -= ((task_count-1) * panel->g_taskbar.area.paddingx);
284
285 pixel_width = taskbar_width / task_count;
286 if (pixel_width > panel->g_task.maximum_width)
287 pixel_width = panel->g_task.maximum_width;
288 else
289 modulo_width = taskbar_width % task_count;
290 }
291
292 taskbar->task_width = pixel_width;
293 taskbar->task_modulo = modulo_width;
294 taskbar->text_width = pixel_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
295
296 // change pos_x and width for all tasks
297 for (l = taskbar->area.list; l ; l = l->next) {
298 tsk = l->data;
299 if (!tsk->area.on_screen) continue;
300 tsk->area.width = pixel_width;
301
302 if (modulo_width) {
303 tsk->area.width++;
304 modulo_width--;
305 }
306 }
307 }
308 else {
309 int pixel_height, modulo_height=0;
310 int taskbar_height;
311
312 // new task width for 'desktop'
313 task_count = g_slist_length(taskbar->area.list);
314 if (!task_count) pixel_height = panel->g_task.maximum_height;
315 else {
316 taskbar_height = taskbar->area.height - (2 * border_width) - (2 * panel->g_taskbar.area.paddingxlr);
317 if (task_count>1) taskbar_height -= ((task_count-1) * panel->g_taskbar.area.paddingx);
318
319 pixel_height = taskbar_height / task_count;
320 if (pixel_height > panel->g_task.maximum_height)
321 pixel_height = panel->g_task.maximum_height;
322 else
323 modulo_height = taskbar_height % task_count;
324 }
325
326 taskbar->task_width = pixel_height;
327 taskbar->task_modulo = modulo_height;
328 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;
329
330 // change pos_y and height for all tasks
331 for (l = taskbar->area.list; l ; l = l->next) {
332 tsk = l->data;
333 if (!tsk->area.on_screen) continue;
334 tsk->area.height = pixel_height;
335
336 if (modulo_height) {
337 tsk->area.height++;
338 modulo_height--;
339 }
340 }
341 }
342
343 return 0;
344 }
345
346
347 void visible_taskbar(void *p)
348 {
349 Panel *panel =(Panel*)p;
350 int j;
351
352 Taskbar *taskbar;
353 for (j=0 ; j < panel->nb_desktop ; j++) {
354 taskbar = &panel->taskbar[j];
355 if (panel_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) {
356 // SINGLE_DESKTOP and not current desktop
357 taskbar->area.on_screen = 0;
358 }
359 else {
360 taskbar->area.on_screen = 1;
361 }
362 }
363 panel_refresh = 1;
364 }
365
This page took 0.050887 seconds and 4 git commands to generate.