]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
back to ELLIPSIZE_END and multi-line task name. multi-line depend on task vertical_pa...
[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_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
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 if (win_to_task_table) g_hash_table_foreach(win_to_task_table, taskbar_remove_task, 0);
188 for (i=0 ; i < nb_panel ; i++) {
189 panel = &panel1[i];
190 for (j=0 ; j < panel->nb_desktop ; j++) {
191 tskbar = &panel->taskbar[j];
192 free_area (&tskbar->area);
193 // remove taskbar from the panel
194 panel->area.list = g_slist_remove(panel->area.list, tskbar);
195 }
196 if (panel->taskbar) {
197 free(panel->taskbar);
198 panel->taskbar = 0;
199 }
200 }
201
202 if (win_to_task_table) {
203 g_hash_table_destroy(win_to_task_table);
204 win_to_task_table = 0;
205 }
206 }
207
208
209 Task *task_get_task (Window win)
210 {
211 GPtrArray* task_group = task_get_tasks(win);
212 if (task_group)
213 return g_ptr_array_index(task_group, 0);
214 else
215 return 0;
216 }
217
218
219 GPtrArray* task_get_tasks(Window win)
220 {
221 return g_hash_table_lookup(win_to_task_table, &win);
222 }
223
224
225 void task_refresh_tasklist ()
226 {
227 Window *win;
228 int num_results, i;
229
230 win = server_get_property (server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
231 if (!win) return;
232
233 // Remove any old and set active win
234 // remark from Andreas: This seems unneccessary...
235 // active_task();
236
237 GList* win_list = g_hash_table_get_keys(win_to_task_table);
238 GList* it;
239 for (it=win_list; it; it=it->next) {
240 for (i = 0; i < num_results; i++)
241 if (*((Window*)it->data) == win[i])
242 break;
243 if (i == num_results)
244 taskbar_remove_task(it->data, 0, 0);
245 }
246 g_list_free(win_list);
247
248 // Add any new
249 for (i = 0; i < num_results; i++)
250 if (!task_get_task (win[i]))
251 add_task (win[i]);
252
253 XFree (win);
254 }
255
256
257 void resize_taskbar(void *obj)
258 {
259 Taskbar *taskbar = (Taskbar*)obj;
260 Panel *panel = (Panel*)taskbar->area.panel;
261 Task *tsk;
262 GSList *l;
263 int task_count, border_width;
264
265 //printf("resize_taskbar : posx et width des taches\n");
266 taskbar->area.redraw = 1;
267
268 border_width = taskbar->area.bg->border.width;
269
270 if (panel_horizontal) {
271 int pixel_width, modulo_width=0;
272 int x, taskbar_width;
273
274 // new task width for 'desktop'
275 task_count = g_slist_length(taskbar->area.list);
276 if (!task_count) pixel_width = panel->g_task.maximum_width;
277 else {
278 taskbar_width = taskbar->area.width - (2 * border_width) - (2 * panel->g_taskbar.area.paddingxlr);
279 if (task_count>1) taskbar_width -= ((task_count-1) * panel->g_taskbar.area.paddingx);
280
281 pixel_width = taskbar_width / task_count;
282 if (pixel_width > panel->g_task.maximum_width)
283 pixel_width = panel->g_task.maximum_width;
284 else
285 modulo_width = taskbar_width % task_count;
286 }
287
288 taskbar->task_width = pixel_width;
289 taskbar->task_modulo = modulo_width;
290 taskbar->text_width = pixel_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
291
292 // change pos_x and width for all tasks
293 x = taskbar->area.posx + border_width + taskbar->area.paddingxlr;
294 for (l = taskbar->area.list; l ; l = l->next) {
295 tsk = l->data;
296 if (!tsk->area.on_screen) continue;
297 tsk->area.posx = x;
298 set_task_redraw(tsk); // always redraw task, because the background could have changed (taskbar_active_id)
299 tsk->area.width = pixel_width;
300 if (modulo_width) {
301 tsk->area.width++;
302 modulo_width--;
303 }
304
305 x += tsk->area.width + panel->g_taskbar.area.paddingx;
306 }
307 }
308 else {
309 int pixel_height, modulo_height=0;
310 int y, 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 y = taskbar->area.posy + border_width + taskbar->area.paddingxlr;
332 for (l = taskbar->area.list; l ; l = l->next) {
333 tsk = l->data;
334 if (!tsk->area.on_screen) continue;
335 tsk->area.posy = y;
336 set_task_redraw(tsk); // always redraw task, because the background could have changed (taskbar_active_id)
337 tsk->area.height = pixel_height;
338 if (modulo_height) {
339 tsk->area.height++;
340 modulo_height--;
341 }
342
343 y += tsk->area.height + panel->g_taskbar.area.paddingx;
344 }
345 }
346 }
This page took 0.047175 seconds and 5 git commands to generate.