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