]> Dogcows Code - chaz/tint2/blob - src/tint.c
fixed bug with active task
[chaz/tint2] / src / tint.c
1 /**************************************************************************
2 *
3 * Tint2 panel
4 *
5 * Copyright (C) 2007 Pål Staurland (staura@gmail.com)
6 * Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 **************************************************************************/
20
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
29 #include <X11/Xlocale.h>
30 #include <Imlib2.h>
31 #include <signal.h>
32
33 #include "server.h"
34 #include "window.h"
35 #include "config.h"
36 #include "task.h"
37 #include "taskbar.h"
38 #include "panel.h"
39 #include "docker.h"
40 #include "net.h"
41 #include "kde.h"
42
43
44 void signal_handler(int sig)
45 {
46 // signal handler is light as it should be
47 panel.signal_pending = sig;
48 }
49
50
51 void init ()
52 {
53 // Set signal handler
54 signal(SIGUSR1, signal_handler);
55 signal(SIGINT, signal_handler);
56 signal(SIGTERM, signal_handler);
57
58 // set global data
59 memset(&panel, 0, sizeof(Panel));
60 memset(&server, 0, sizeof(Server_global));
61 memset(&g_task, 0, sizeof(Global_task));
62 memset(&g_taskbar, 0, sizeof(Area));
63 panel.clock.area.draw_foreground = draw_foreground_clock;
64 g_task.area.draw_foreground = draw_foreground_task;
65 window.main_win = 0;
66
67 server.dsp = XOpenDisplay (NULL);
68 if (!server.dsp) {
69 fprintf(stderr, "Could not open display.\n");
70 exit(0);
71 }
72 server_init_atoms ();
73 server.screen = DefaultScreen (server.dsp);
74 server.root_win = RootWindow(server.dsp, server.screen);
75 server.depth = DefaultDepth (server.dsp, server.screen);
76 server.visual = DefaultVisual (server.dsp, server.screen);
77 server.desktop = server_get_current_desktop ();
78
79 XSetErrorHandler ((XErrorHandler) server_catch_error);
80
81 // init systray
82 display = server.dsp;
83 root = RootWindow(display, DefaultScreen(display));
84 //create_main_window();
85 //kde_init();
86 //net_init();
87 //printf("ici 4\n");
88
89 imlib_context_set_display (server.dsp);
90 imlib_context_set_visual (server.visual);
91 imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen));
92
93 /* Catch events */
94 XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
95
96 setlocale (LC_ALL, "");
97 }
98
99
100 void window_action (Task *tsk, int action)
101 {
102 switch (action) {
103 case CLOSE:
104 set_close (tsk->win);
105 break;
106 case TOGGLE:
107 set_active(tsk->win);
108 break;
109 case ICONIFY:
110 XIconifyWindow (server.dsp, tsk->win, server.screen);
111 break;
112 case TOGGLE_ICONIFY:
113 if (tsk == panel.task_active) XIconifyWindow (server.dsp, tsk->win, server.screen);
114 else set_active (tsk->win);
115 break;
116 case SHADE:
117 window_toggle_shade (tsk->win);
118 break;
119 }
120 }
121
122
123 void event_button_press (int x, int y)
124 {
125 if (panel.mode == SINGLE_DESKTOP) {
126 // drag and drop disabled
127 XLowerWindow (server.dsp, window.main_win);
128 return;
129 }
130
131 Taskbar *tskbar;
132 GSList *l0;
133 for (l0 = panel.area.list; l0 ; l0 = l0->next) {
134 tskbar = l0->data;
135 if (x >= tskbar->area.posx && x <= (tskbar->area.posx + tskbar->area.width))
136 break;
137 }
138
139 if (l0) {
140 Task *tsk;
141 for (l0 = tskbar->area.list; l0 ; l0 = l0->next) {
142 tsk = l0->data;
143 if (x >= tsk->area.posx && x <= (tsk->area.posx + tsk->area.width)) {
144 panel.task_drag = tsk;
145 break;
146 }
147 }
148 }
149
150 XLowerWindow (server.dsp, window.main_win);
151 }
152
153
154 void event_button_release (int button, int x, int y)
155 {
156 int action = TOGGLE_ICONIFY;
157 // TODO: convert event_button_press(int x, int y) to area->event_button_press()
158 // if systray is ok
159
160 switch (button) {
161 case 2:
162 action = panel.mouse_middle;
163 break;
164 case 3:
165 action = panel.mouse_right;
166 break;
167 case 4:
168 action = panel.mouse_scroll_up;
169 break;
170 case 5:
171 action = panel.mouse_scroll_down;
172 break;
173 }
174
175 // search taskbar
176 Taskbar *tskbar;
177 GSList *l0;
178 for (l0 = panel.area.list; l0 ; l0 = l0->next) {
179 tskbar = l0->data;
180 if (x >= tskbar->area.posx && x <= (tskbar->area.posx + tskbar->area.width))
181 goto suite;
182 }
183
184 // TODO: check better solution to keep window below
185 XLowerWindow (server.dsp, window.main_win);
186 panel.task_drag = 0;
187 return;
188
189 suite:
190 // drag and drop task
191 if (panel.task_drag) {
192 if (tskbar != panel.task_drag->area.parent && action == TOGGLE_ICONIFY) {
193 windows_set_desktop(panel.task_drag->win, tskbar->desktop);
194 if (tskbar->desktop == server.desktop)
195 set_active(panel.task_drag->win);
196 panel.task_drag = 0;
197 return;
198 }
199 else panel.task_drag = 0;
200 }
201
202 // switch desktop
203 if (panel.mode == MULTI_DESKTOP)
204 if (tskbar->desktop != server.desktop && action != CLOSE)
205 set_desktop (tskbar->desktop);
206
207 // action on task
208 Task *tsk;
209 GSList *l;
210 for (l = tskbar->area.list ; l ; l = l->next) {
211 tsk = l->data;
212 if (x >= tsk->area.posx && x <= (tsk->area.posx + tsk->area.width)) {
213 window_action (tsk, action);
214 break;
215 }
216 }
217
218 // to keep window below
219 XLowerWindow (server.dsp, window.main_win);
220 }
221
222
223 void event_property_notify (Window win, Atom at)
224 {
225
226 if (win == server.root_win) {
227 if (!server.got_root_win) {
228 XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
229 server.got_root_win = 1;
230 }
231
232 /* Change number of desktops */
233 else if (at == server.atom._NET_NUMBER_OF_DESKTOPS) {
234 config_taskbar();
235 visible_object();
236 }
237 /* Change desktop */
238 else if (at == server.atom._NET_CURRENT_DESKTOP) {
239 server.desktop = server_get_current_desktop ();
240 if (panel.mode != MULTI_DESKTOP) {
241 visible_object();
242 }
243 }
244 /* Window list */
245 else if (at == server.atom._NET_CLIENT_LIST) {
246 task_refresh_tasklist ();
247 panel.refresh = 1;
248 }
249 /* Change active */
250 else if (at == server.atom._NET_ACTIVE_WINDOW) {
251 if (panel.task_active) {
252 panel.task_active->area.is_active = 0;
253 panel.task_active = 0;
254 }
255 Window w1 = window_get_active ();
256 Task *t = task_get_task(w1);
257 if (!t) {
258 Window w2;
259 if (XGetTransientForHint(server.dsp, w1, &w2) != 0)
260 if (w2) t = task_get_task(w2);
261 }
262 if (t) {
263 t->area.is_active = 1;
264 panel.task_active = t;
265 }
266 panel.refresh = 1;
267 }
268 /* Wallpaper changed */
269 else if (at == server.atom._XROOTPMAP_ID) {
270 XFreePixmap (server.dsp, panel.area.pix.pmap);
271 panel.area.pix.pmap = 0;
272 panel.refresh = 1;
273 }
274 }
275 else {
276 Task *tsk;
277 tsk = task_get_task (win);
278 if (!tsk) return;
279 //printf("atom root_win = %s, %s\n", XGetAtomName(server.dsp, at), tsk->title);
280
281 /* Window title changed */
282 if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) {
283 get_title(tsk);
284 tsk->area.redraw = 1;
285 panel.refresh = 1;
286 }
287 /* Iconic state */
288 else if (at == server.atom.WM_STATE) {
289 if (window_is_iconified (win))
290 if (panel.task_active == tsk) {
291 tsk->area.is_active = 0;
292 panel.task_active = 0;
293 }
294 }
295 /* Window icon changed */
296 else if (at == server.atom._NET_WM_ICON) {
297 if (tsk->icon_data) {
298 free (tsk->icon_data);
299 tsk->icon_data = 0;
300 }
301 tsk->area.redraw = 1;
302 panel.refresh = 1;
303 }
304 /* Window desktop changed */
305 else if (at == server.atom._NET_WM_DESKTOP) {
306 add_task (tsk->win);
307 remove_task (tsk);
308 panel.refresh = 1;
309 }
310
311 if (!server.got_root_win) server.root_win = RootWindow (server.dsp, server.screen);
312 }
313 }
314
315
316 void event_configure_notify (Window win)
317 {
318 Task *tsk;
319
320 tsk = task_get_task (win);
321 if (!tsk) return;
322
323 Taskbar *tskbar = tsk->area.parent;
324 if (tskbar->monitor != window_get_monitor (win)) {
325 // task on another monitor
326 add_task (tsk->win);
327 remove_task (tsk);
328 panel.refresh = 1;
329 }
330 }
331
332
333 void event_timer()
334 {
335 struct timeval stv;
336
337 if (!panel.clock.time1_format) return;
338
339 if (gettimeofday(&stv, 0)) return;
340
341 if (abs(stv.tv_sec - panel.clock.clock.tv_sec) < panel.clock.time_precision) return;
342
343 // update clock
344 panel.clock.clock.tv_sec = stv.tv_sec;
345 panel.clock.clock.tv_sec -= panel.clock.clock.tv_sec % panel.clock.time_precision;
346 panel.clock.area.redraw = 1;
347 panel.refresh = 1;
348 }
349
350
351 int main (int argc, char *argv[])
352 {
353 XEvent e;
354 fd_set fd;
355 int x11_fd, i, c;
356 struct timeval tv;
357
358 c = getopt (argc, argv, "c:");
359 init ();
360
361 load_config:
362 if (panel.area.pix.pmap) XFreePixmap (server.dsp, panel.area.pix.pmap);
363 panel.area.pix.pmap = 0;
364 // append full transparency background
365 list_back = g_slist_append(0, calloc(1, sizeof(Area)));
366
367 // read tint2rc config
368 i = 0;
369 if (c != -1)
370 i = config_read_file (optarg);
371 if (!i)
372 i = config_read ();
373 if (!i) {
374 fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
375 cleanup();
376 exit(1);
377 }
378 config_finish ();
379
380 window_draw_panel ();
381
382 // BUG: refresh(clock) is needed here, but 'on the paper' it's not necessary.
383 refresh(&panel.clock.area);
384
385 x11_fd = ConnectionNumber (server.dsp);
386 XSync (server.dsp, False);
387
388 while (1) {
389 // thanks to AngryLlama for the timer
390 // Create a File Description Set containing x11_fd
391 FD_ZERO (&fd);
392 FD_SET (x11_fd, &fd);
393
394 tv.tv_usec = 500000;
395 tv.tv_sec = 0;
396
397 // Wait for X Event or a Timer
398 if (select(x11_fd+1, &fd, 0, 0, &tv)) {
399 while (XPending (server.dsp)) {
400 XNextEvent(server.dsp, &e);
401
402 switch (e.type) {
403 case ButtonPress:
404 if (e.xbutton.button == 1) event_button_press (e.xbutton.x, e.xbutton.y);
405 break;
406
407 case ButtonRelease:
408 event_button_release (e.xbutton.button, e.xbutton.x, e.xbutton.y);
409 break;
410
411 case Expose:
412 XCopyArea (server.dsp, panel.area.pix.pmap, server.root_win, server.gc_root, 0, 0, panel.area.width, panel.area.height, server.posx, server.posy);
413 XCopyArea (server.dsp, server.pmap, window.main_win, server.gc, panel.area.paddingx, 0, panel.area.width-(2*panel.area.paddingx), panel.area.height, 0, 0);
414 break;
415
416 case PropertyNotify:
417 //printf("PropertyNotify\n");
418 event_property_notify (e.xproperty.window, e.xproperty.atom);
419 break;
420
421 case ConfigureNotify:
422 if (e.xconfigure.window == server.root_win)
423 goto load_config;
424 else
425 if (panel.mode == MULTI_MONITOR)
426 event_configure_notify (e.xconfigure.window);
427 break;
428 }
429 }
430 }
431 else event_timer();
432
433 switch (panel.signal_pending) {
434 case SIGUSR1:
435 goto load_config;
436 case SIGINT:
437 case SIGTERM:
438 cleanup ();
439 return 0;
440 }
441
442 if (panel.refresh && !panel.sleep_mode) {
443 visual_refresh ();
444 //printf(" *** visual_refresh\n");
445 }
446 }
447 }
448
449
This page took 0.051818 seconds and 4 git commands to generate.