]> Dogcows Code - chaz/tint2/blob - src/taskbar/taskbar.c
cleanup
[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, 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.redraw = 1;
117 panel->g_taskbar.area.on_screen = 1;
118 if (panel_horizontal) {
119 panel->g_taskbar.area.posy = panel->area.bg->border.width + panel->area.paddingy;
120 panel->g_taskbar.area.height = panel->area.height - (2 * panel->g_taskbar.area.posy);
121 }
122 else {
123 panel->g_taskbar.area.posx = panel->area.bg->border.width + panel->area.paddingy;
124 panel->g_taskbar.area.width = panel->area.width - (2 * panel->g_taskbar.area.posx);
125 }
126
127 // task
128 panel->g_task.area.size_mode = SIZE_BY_LAYOUT;
129 panel->g_task.area._draw_foreground = draw_task;
130 panel->g_task.area._on_change_layout = on_change_task;
131 panel->g_task.area.redraw = 1;
132 panel->g_task.area.on_screen = 1;
133 if ((panel->g_task.config_asb_mask & (1<<TASK_NORMAL)) == 0) {
134 panel->g_task.alpha[TASK_NORMAL] = 100;
135 panel->g_task.saturation[TASK_NORMAL] = 0;
136 panel->g_task.brightness[TASK_NORMAL] = 0;
137 }
138 if ((panel->g_task.config_asb_mask & (1<<TASK_ACTIVE)) == 0) {
139 panel->g_task.alpha[TASK_ACTIVE] = panel->g_task.alpha[TASK_NORMAL];
140 panel->g_task.saturation[TASK_ACTIVE] = panel->g_task.saturation[TASK_NORMAL];
141 panel->g_task.brightness[TASK_ACTIVE] = panel->g_task.brightness[TASK_NORMAL];
142 }
143 if ((panel->g_task.config_asb_mask & (1<<TASK_ICONIFIED)) == 0) {
144 panel->g_task.alpha[TASK_ICONIFIED] = panel->g_task.alpha[TASK_NORMAL];
145 panel->g_task.saturation[TASK_ICONIFIED] = panel->g_task.saturation[TASK_NORMAL];
146 panel->g_task.brightness[TASK_ICONIFIED] = panel->g_task.brightness[TASK_NORMAL];
147 }
148 if ((panel->g_task.config_asb_mask & (1<<TASK_URGENT)) == 0) {
149 panel->g_task.alpha[TASK_URGENT] = panel->g_task.alpha[TASK_ACTIVE];
150 panel->g_task.saturation[TASK_URGENT] = panel->g_task.saturation[TASK_ACTIVE];
151 panel->g_task.brightness[TASK_URGENT] = panel->g_task.brightness[TASK_ACTIVE];
152 }
153 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.font[TASK_NORMAL] = (Color){{0, 0, 0}, 0};
154 if ((panel->g_task.config_font_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.font[TASK_ACTIVE] = panel->g_task.font[TASK_NORMAL];
155 if ((panel->g_task.config_font_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.font[TASK_ICONIFIED] = panel->g_task.font[TASK_NORMAL];
156 if ((panel->g_task.config_font_mask & (1<<TASK_URGENT)) == 0) panel->g_task.font[TASK_URGENT] = panel->g_task.font[TASK_ACTIVE];
157 if ((panel->g_task.config_font_mask & (1<<TASK_NORMAL)) == 0) panel->g_task.background[TASK_NORMAL] = &g_array_index(backgrounds, Background, 0);
158 if ((panel->g_task.config_background_mask & (1<<TASK_ACTIVE)) == 0) panel->g_task.background[TASK_ACTIVE] = panel->g_task.background[TASK_NORMAL];
159 if ((panel->g_task.config_background_mask & (1<<TASK_ICONIFIED)) == 0) panel->g_task.background[TASK_ICONIFIED] = panel->g_task.background[TASK_NORMAL];
160 if ((panel->g_task.config_background_mask & (1<<TASK_URGENT)) == 0) panel->g_task.background[TASK_URGENT] = panel->g_task.background[TASK_ACTIVE];
161
162 if (panel_horizontal) {
163 panel->g_task.area.posy = panel->g_taskbar.area.posy + panel->g_taskbar.background[TASKBAR_NORMAL]->border.width + panel->g_taskbar.area.paddingy;
164 panel->g_task.area.height = panel->area.height - (2 * panel->g_task.area.posy);
165 }
166 else {
167 panel->g_task.area.posx = panel->g_taskbar.area.posx + panel->g_taskbar.background[TASKBAR_NORMAL]->border.width + panel->g_taskbar.area.paddingy;
168 panel->g_task.area.width = panel->area.width - (2 * panel->g_task.area.posx);
169 panel->g_task.area.height = panel->g_task.maximum_height;
170 }
171
172 for (j=0; j<TASK_STATE_COUNT; ++j) {
173 if (panel->g_task.background[j]->border.rounded > panel->g_task.area.height/2) {
174 printf("task%sbackground_id has a too large rounded value. Please fix your tint2rc\n", j==0 ? "_" : j==1 ? "_active_" : j==2 ? "_iconified_" : "_urgent_");
175 g_array_append_val(backgrounds, *panel->g_task.background[j]);
176 panel->g_task.background[j] = &g_array_index(backgrounds, Background, backgrounds->len-1);
177 panel->g_task.background[j]->border.rounded = panel->g_task.area.height/2;
178 }
179 }
180
181 // compute vertical position : text and icon
182 int height_ink, height;
183 get_text_size(panel->g_task.font_desc, &height_ink, &height, panel->area.height, "TAjpg", 5);
184
185 if (!panel->g_task.maximum_width && panel_horizontal)
186 panel->g_task.maximum_width = server.monitor[panel->monitor].width;
187
188 panel->g_task.text_posx = panel->g_task.background[0]->border.width + panel->g_task.area.paddingxlr;
189 panel->g_task.text_height = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
190 if (panel->g_task.icon) {
191 panel->g_task.icon_size1 = panel->g_task.area.height - (2 * panel->g_task.area.paddingy);
192 panel->g_task.text_posx += panel->g_task.icon_size1;
193 panel->g_task.icon_posy = (panel->g_task.area.height - panel->g_task.icon_size1) / 2;
194 }
195 //printf("monitor %d, task_maximum_width %d\n", panel->monitor, panel->g_task.maximum_width);
196
197 Taskbar *tskbar;
198 panel->nb_desktop = server.nb_desktop;
199 panel->taskbar = calloc(server.nb_desktop, sizeof(Taskbar));
200 for (j=0 ; j < panel->nb_desktop ; j++) {
201 tskbar = &panel->taskbar[j];
202 memcpy(&tskbar->area, &panel->g_taskbar, sizeof(Area));
203 tskbar->desktop = j;
204 if (j == server.desktop)
205 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_ACTIVE];
206 else
207 tskbar->area.bg = panel->g_taskbar.background[TASKBAR_NORMAL];
208 }
209 }
210
211
212 void taskbar_remove_task(gpointer key, gpointer value, gpointer user_data)
213 {
214 remove_task(task_get_task(*(Window*)key));
215 }
216
217
218 Task *task_get_task (Window win)
219 {
220 GPtrArray* task_group = task_get_tasks(win);
221 if (task_group)
222 return g_ptr_array_index(task_group, 0);
223 else
224 return 0;
225 }
226
227
228 GPtrArray* task_get_tasks(Window win)
229 {
230 if (win_to_task_table && taskbar_enabled)
231 return g_hash_table_lookup(win_to_task_table, &win);
232 else
233 return 0;
234 }
235
236
237 void task_refresh_tasklist ()
238 {
239 Window *win;
240 int num_results, i;
241
242 if (!taskbar_enabled) return;
243 win = server_get_property (server.root_win, server.atom._NET_CLIENT_LIST, XA_WINDOW, &num_results);
244 if (!win) return;
245
246 GList* win_list = g_hash_table_get_keys(win_to_task_table);
247 GList* it;
248 for (it=win_list; it; it=it->next) {
249 for (i = 0; i < num_results; i++)
250 if (*((Window*)it->data) == win[i])
251 break;
252 if (i == num_results)
253 taskbar_remove_task(it->data, 0, 0);
254 }
255 g_list_free(win_list);
256
257 // Add any new
258 for (i = 0; i < num_results; i++)
259 if (!task_get_task (win[i]))
260 add_task (win[i]);
261
262 XFree (win);
263 }
264
265
266 void draw_taskbar (void *obj, cairo_t *c)
267 {
268 Taskbar *taskbar = obj;
269 int state = (taskbar->desktop == server.desktop) ? TASKBAR_ACTIVE : TASKBAR_NORMAL;
270
271 taskbar->state_pix[state] = taskbar->area.pix;
272 }
273
274
275 int resize_taskbar(void *obj)
276 {
277 Taskbar *taskbar = (Taskbar*)obj;
278 Panel *panel = (Panel*)taskbar->area.panel;
279 int text_width;
280 Task *tsk;
281
282 //printf("resize_taskbar %d %d\n", taskbar->area.posx, taskbar->area.posy);
283 if (panel_horizontal) {
284 resize_by_layout(obj, panel->g_task.maximum_width);
285
286 text_width = panel->g_task.maximum_width;
287 if (taskbar->area.list != NULL) {
288 tsk = taskbar->area.list->data;
289 text_width = tsk->area.width;
290 }
291 taskbar->text_width = text_width - panel->g_task.text_posx - panel->g_task.area.bg->border.width - panel->g_task.area.paddingx;
292 }
293 else {
294 resize_by_layout(obj, panel->g_task.maximum_height);
295
296 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;
297 }
298 return 0;
299 }
300
301
302 void set_taskbar_state(Taskbar *tskbar, int state)
303 {
304 tskbar->area.bg = panel1[0].g_taskbar.background[state];
305 tskbar->area.pix = tskbar->state_pix[state];
306 if (tskbar->state_pix[state] == 0) {
307 tskbar->area.redraw = 1;
308 GSList *l;
309 for (l = tskbar->area.list ; l ; l = l->next)
310 ((Area*)l->data)->redraw = 1;
311 }
312 panel_refresh = 1;
313 }
314
315
316 void visible_taskbar(void *p)
317 {
318 Panel *panel =(Panel*)p;
319 int j;
320
321 Taskbar *taskbar;
322 for (j=0 ; j < panel->nb_desktop ; j++) {
323 taskbar = &panel->taskbar[j];
324 if (panel_mode != MULTI_DESKTOP && taskbar->desktop != server.desktop) {
325 // SINGLE_DESKTOP and not current desktop
326 taskbar->area.on_screen = 0;
327 }
328 else {
329 taskbar->area.on_screen = 1;
330 }
331 }
332 panel_refresh = 1;
333 }
334
This page took 0.045851 seconds and 4 git commands to generate.