]> Dogcows Code - chaz/tint2/blob - src/tint.c
fixed issue 13, removed Window magager s menu for stability reason
[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 XGCValues gcv;
79 server.gc = XCreateGC (server.dsp, server.root_win, (unsigned long)0, &gcv) ;
80
81 XSetErrorHandler ((XErrorHandler) server_catch_error);
82
83 // init systray
84 //display = server.dsp;
85 //root = RootWindow(display, DefaultScreen(display));
86 //create_main_window();
87 //kde_init();
88 //net_init();
89 //printf("ici 4\n");
90
91 imlib_context_set_display (server.dsp);
92 imlib_context_set_visual (server.visual);
93 imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen));
94
95 /* Catch events */
96 XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
97
98 setlocale (LC_ALL, "");
99 }
100
101
102 void window_action (Task *tsk, int action)
103 {
104 switch (action) {
105 case CLOSE:
106 set_close (tsk->win);
107 break;
108 case TOGGLE:
109 set_active(tsk->win);
110 break;
111 case ICONIFY:
112 XIconifyWindow (server.dsp, tsk->win, server.screen);
113 break;
114 case TOGGLE_ICONIFY:
115 if (tsk == panel.task_active) XIconifyWindow (server.dsp, tsk->win, server.screen);
116 else set_active (tsk->win);
117 break;
118 case SHADE:
119 window_toggle_shade (tsk->win);
120 break;
121 }
122 }
123
124
125 void event_button_press (int x, int y)
126 {
127 if (panel.mode == SINGLE_DESKTOP) {
128 // drag and drop disabled
129 XLowerWindow (server.dsp, window.main_win);
130 return;
131 }
132
133 Taskbar *tskbar;
134 GSList *l0;
135 for (l0 = panel.area.list; l0 ; l0 = l0->next) {
136 tskbar = l0->data;
137 if (x >= tskbar->area.posx && x <= (tskbar->area.posx + tskbar->area.width))
138 break;
139 }
140
141 if (l0) {
142 Task *tsk;
143 for (l0 = tskbar->area.list; l0 ; l0 = l0->next) {
144 tsk = l0->data;
145 if (x >= tsk->area.posx && x <= (tsk->area.posx + tsk->area.width)) {
146 panel.task_drag = tsk;
147 break;
148 }
149 }
150 }
151
152 XLowerWindow (server.dsp, window.main_win);
153 }
154
155
156 void event_button_release (int button, int x, int y)
157 {
158 int action = TOGGLE_ICONIFY;
159 // TODO: convert event_button_press(int x, int y) to area->event_button_press()
160 // if systray is ok
161
162 switch (button) {
163 case 2:
164 action = panel.mouse_middle;
165 break;
166 case 3:
167 action = panel.mouse_right;
168 break;
169 case 4:
170 action = panel.mouse_scroll_up;
171 break;
172 case 5:
173 action = panel.mouse_scroll_down;
174 break;
175 }
176
177 // search taskbar
178 Taskbar *tskbar;
179 GSList *l0;
180 for (l0 = panel.area.list; l0 ; l0 = l0->next) {
181 tskbar = l0->data;
182 if (x >= tskbar->area.posx && x <= (tskbar->area.posx + tskbar->area.width))
183 goto suite;
184 }
185
186 // TODO: check better solution to keep window below
187 XLowerWindow (server.dsp, window.main_win);
188 panel.task_drag = 0;
189 return;
190
191 suite:
192 // drag and drop task
193 if (panel.task_drag) {
194 if (tskbar != panel.task_drag->area.parent && action == TOGGLE_ICONIFY) {
195 if (!panel.task_drag->all_desktop && panel.mode == MULTI_DESKTOP) {
196 windows_set_desktop(panel.task_drag->win, tskbar->desktop);
197 if (tskbar->desktop == server.desktop)
198 set_active(panel.task_drag->win);
199 panel.task_drag = 0;
200 }
201 return;
202 }
203 else panel.task_drag = 0;
204 }
205
206 // switch desktop
207 if (panel.mode == MULTI_DESKTOP)
208 if (tskbar->desktop != server.desktop && action != CLOSE)
209 set_desktop (tskbar->desktop);
210
211 // action on task
212 Task *tsk;
213 GSList *l;
214 for (l = tskbar->area.list ; l ; l = l->next) {
215 tsk = l->data;
216 if (x >= tsk->area.posx && x <= (tsk->area.posx + tsk->area.width)) {
217 window_action (tsk, action);
218 break;
219 }
220 }
221
222 // to keep window below
223 XLowerWindow (server.dsp, window.main_win);
224 }
225
226
227 void event_property_notify (Window win, Atom at)
228 {
229
230 if (win == server.root_win) {
231 if (!server.got_root_win) {
232 XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
233 server.got_root_win = 1;
234 }
235
236 /* Change number of desktops */
237 else if (at == server.atom._NET_NUMBER_OF_DESKTOPS) {
238 config_taskbar();
239 visible_object();
240 }
241 /* Change desktop */
242 else if (at == server.atom._NET_CURRENT_DESKTOP) {
243 server.desktop = server_get_current_desktop ();
244 if (panel.mode != MULTI_DESKTOP) {
245 visible_object();
246 }
247 }
248 /* Window list */
249 else if (at == server.atom._NET_CLIENT_LIST) {
250 task_refresh_tasklist ();
251 panel.refresh = 1;
252 }
253 /* Change active */
254 else if (at == server.atom._NET_ACTIVE_WINDOW) {
255 if (panel.task_active) {
256 if (panel.task_active->all_desktop) {
257 Task *tsk;
258 GSList *l0;
259 int i, nb;
260 nb = server.nb_desktop * server.nb_monitor;
261 for (i=0 ; i < nb ; i++) {
262 for (l0 = panel.taskbar[i].area.list; l0 ; l0 = l0->next) {
263 tsk = l0->data;
264 tsk->area.is_active = 0;
265 }
266 }
267 }
268 else
269 panel.task_active->area.is_active = 0;
270 panel.task_active = 0;
271 }
272 Window w1 = window_get_active ();
273 Task *t = task_get_task(w1);
274 if (!t) {
275 Window w2;
276 if (XGetTransientForHint(server.dsp, w1, &w2) != 0)
277 if (w2) t = task_get_task(w2);
278 }
279 if (t) {
280 if (t->all_desktop) {
281 Task *tsk;
282 GSList *l0;
283 int i, nb;
284 nb = server.nb_desktop * server.nb_monitor;
285 for (i=0 ; i < nb ; i++) {
286 for (l0 = panel.taskbar[i].area.list; l0 ; l0 = l0->next) {
287 tsk = l0->data;
288 if (tsk->win == t->win)
289 tsk->area.is_active = 1;
290 }
291 }
292 }
293 else
294 t->area.is_active = 1;
295 panel.task_active = t;
296 }
297 panel.refresh = 1;
298 }
299 /* Wallpaper changed */
300 else if (at == server.atom._XROOTPMAP_ID) {
301 set_panel_background();
302 panel.refresh = 1;
303 }
304 }
305 else {
306 Task *tsk;
307 tsk = task_get_task (win);
308 if (!tsk) return;
309 //printf("atom root_win = %s, %s\n", XGetAtomName(server.dsp, at), tsk->title);
310
311 /* Window title changed */
312 if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) {
313 if (tsk->all_desktop) {
314 Task *tsk2;
315 GSList *l0;
316 int i, nb;
317 nb = server.nb_desktop * server.nb_monitor;
318 for (i=0 ; i < nb ; i++) {
319 for (l0 = panel.taskbar[i].area.list; l0 ; l0 = l0->next) {
320 tsk2 = l0->data;
321 if (tsk->win == tsk2->win) {
322 get_title(tsk2);
323 tsk2->area.redraw = 1;
324 }
325 }
326 }
327 }
328 else {
329 get_title(tsk);
330 tsk->area.redraw = 1;
331 }
332 panel.refresh = 1;
333 }
334 /* Iconic state */
335 else if (at == server.atom.WM_STATE) {
336 if (window_is_iconified (win))
337 if (panel.task_active) {
338 if (panel.task_active->win == tsk->win) {
339 if (tsk->all_desktop) {
340 Task *tsk2;
341 GSList *l0;
342 int i, nb;
343 nb = server.nb_desktop * server.nb_monitor;
344 for (i=0 ; i < nb ; i++) {
345 for (l0 = panel.taskbar[i].area.list; l0 ; l0 = l0->next) {
346 tsk2 = l0->data;
347 tsk2->area.is_active = 0;
348 }
349 }
350 }
351 else
352 panel.task_active->area.is_active = 0;
353 panel.task_active = 0;
354 }
355 }
356 }
357 /* Window icon changed */
358 else if (at == server.atom._NET_WM_ICON) {
359 if (tsk->icon_data) {
360 free (tsk->icon_data);
361 tsk->icon_data = 0;
362 }
363 tsk->area.redraw = 1;
364 panel.refresh = 1;
365 }
366 /* Window desktop changed */
367 else if (at == server.atom._NET_WM_DESKTOP) {
368 remove_task (tsk);
369 add_task (win);
370 panel.refresh = 1;
371 }
372
373 if (!server.got_root_win) server.root_win = RootWindow (server.dsp, server.screen);
374 }
375 }
376
377
378 void event_configure_notify (Window win)
379 {
380 if (panel.mode != MULTI_MONITOR) return;
381
382 Task *tsk = task_get_task (win);
383 if (!tsk) return;
384
385 Taskbar *tskbar = tsk->area.parent;
386 if (tskbar->monitor != window_get_monitor (win)) {
387 // task on another monitor
388 remove_task (tsk);
389 add_task (win);
390 panel.refresh = 1;
391 }
392 }
393
394
395 void event_timer()
396 {
397 struct timeval stv;
398
399 if (!time1_format) return;
400
401 if (gettimeofday(&stv, 0)) return;
402
403 if (abs(stv.tv_sec - time_clock.tv_sec) < time_precision) return;
404
405 // update clock
406 time_clock.tv_sec = stv.tv_sec;
407 time_clock.tv_sec -= time_clock.tv_sec % time_precision;
408 panel.clock.area.redraw = 1;
409 panel.refresh = 1;
410 }
411
412
413 int main (int argc, char *argv[])
414 {
415 XEvent e;
416 fd_set fd;
417 int x11_fd, i, c;
418 struct timeval tv;
419
420 c = getopt (argc, argv, "c:");
421 init ();
422
423 load_config:
424 // append full transparency background
425 list_back = g_slist_append(0, calloc(1, sizeof(Area)));
426
427 // read tint2rc config
428 i = 0;
429 if (c != -1)
430 i = config_read_file (optarg);
431 if (!i)
432 i = config_read ();
433 if (!i) {
434 fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
435 cleanup();
436 exit(1);
437 }
438 config_finish ();
439
440 window_draw_panel ();
441
442 // BUG: refresh(clock) is needed here, but 'on the paper' it's not necessary.
443 refresh(&panel.clock.area);
444
445 x11_fd = ConnectionNumber (server.dsp);
446 XSync (server.dsp, False);
447
448 while (1) {
449 // thanks to AngryLlama for the timer
450 // Create a File Description Set containing x11_fd
451 FD_ZERO (&fd);
452 FD_SET (x11_fd, &fd);
453
454 tv.tv_usec = 500000;
455 tv.tv_sec = 0;
456
457 // Wait for X Event or a Timer
458 if (select(x11_fd+1, &fd, 0, 0, &tv)) {
459 while (XPending (server.dsp)) {
460 XNextEvent(server.dsp, &e);
461
462 switch (e.type) {
463 case ButtonPress:
464 if (e.xbutton.button == 1) event_button_press (e.xbutton.x, e.xbutton.y);
465 break;
466
467 case ButtonRelease:
468 event_button_release (e.xbutton.button, e.xbutton.x, e.xbutton.y);
469 break;
470
471 case Expose:
472 //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);
473 //XCopyArea (server.dsp, server.pmap, window.main_win, server.gc, panel.area.paddingxlr, 0, panel.area.width-(2*panel.area.paddingxlr), panel.area.height, 0, 0);
474 XCopyArea (server.dsp, server.pmap, window.main_win, server.gc, 0, 0, panel.area.width, panel.area.height, 0, 0);
475 break;
476
477 case PropertyNotify:
478 //printf("PropertyNotify\n");
479 event_property_notify (e.xproperty.window, e.xproperty.atom);
480 break;
481
482 case ConfigureNotify:
483 if (e.xconfigure.window == server.root_win)
484 goto load_config;
485 else
486 event_configure_notify (e.xconfigure.window);
487 break;
488 }
489 }
490 }
491 else event_timer();
492
493 switch (panel.signal_pending) {
494 case SIGUSR1:
495 goto load_config;
496 case SIGINT:
497 case SIGTERM:
498 cleanup ();
499 return 0;
500 }
501
502 if (panel.refresh && !panel.sleep_mode) {
503 visual_refresh ();
504 //printf(" *** visual_refresh\n");
505 }
506 }
507 }
508
509
This page took 0.05723 seconds and 4 git commands to generate.