]> Dogcows Code - chaz/tint2/blob - src/tint.c
fixed decorated window with compiz
[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 /* Active */
250 else if (at == server.atom._NET_ACTIVE_WINDOW) {
251 Window w1 = window_get_active ();
252 Task *t = task_get_task(w1);
253 if (t) panel.task_active = t;
254 else {
255 Window w2;
256 if (XGetTransientForHint(server.dsp, w1, &w2) != 0)
257 if (w2) panel.task_active = task_get_task(w2);
258 }
259 panel.refresh = 1;
260 }
261 /* Wallpaper changed */
262 else if (at == server.atom._XROOTPMAP_ID) {
263 XFreePixmap (server.dsp, panel.area.pmap);
264 panel.area.pmap = 0;
265 panel.refresh = 1;
266 }
267 }
268 else {
269 Task *tsk;
270 tsk = task_get_task (win);
271 if (!tsk) return;
272 //printf("atom root_win = %s, %s\n", XGetAtomName(server.dsp, at), tsk->title);
273
274 /* Window title changed */
275 if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) {
276 get_title(tsk);
277 tsk->area.redraw = 1;
278 panel.refresh = 1;
279 }
280 /* Iconic state */
281 else if (at == server.atom.WM_STATE) {
282 if (window_is_iconified (win))
283 if (panel.task_active == tsk) panel.task_active = 0;
284 }
285 /* Window icon changed */
286 else if (at == server.atom._NET_WM_ICON) {
287 if (tsk->icon_data) {
288 free (tsk->icon_data);
289 tsk->icon_data = 0;
290 }
291 tsk->area.redraw = 1;
292 panel.refresh = 1;
293 }
294 /* Window desktop changed */
295 else if (at == server.atom._NET_WM_DESKTOP) {
296 add_task (tsk->win);
297 remove_task (tsk);
298 panel.refresh = 1;
299 }
300
301 if (!server.got_root_win) server.root_win = RootWindow (server.dsp, server.screen);
302 }
303 }
304
305
306 void event_configure_notify (Window win)
307 {
308 Task *tsk;
309
310 tsk = task_get_task (win);
311 if (!tsk) return;
312
313 Taskbar *tskbar = tsk->area.parent;
314 if (tskbar->monitor != window_get_monitor (win)) {
315 // task on another monitor
316 add_task (tsk->win);
317 remove_task (tsk);
318 panel.refresh = 1;
319 }
320 }
321
322
323 void event_timer()
324 {
325 struct timeval stv;
326
327 if (!panel.clock.time1_format) return;
328
329 if (gettimeofday(&stv, 0)) return;
330
331 if (abs(stv.tv_sec - panel.clock.clock.tv_sec) < panel.clock.time_precision) return;
332
333 // update clock
334 panel.clock.clock.tv_sec = stv.tv_sec;
335 panel.clock.clock.tv_sec -= panel.clock.clock.tv_sec % panel.clock.time_precision;
336 panel.clock.area.redraw = 1;
337 panel.refresh = 1;
338 }
339
340
341 int main (int argc, char *argv[])
342 {
343 XEvent e;
344 fd_set fd;
345 int x11_fd, i, c;
346 struct timeval tv;
347
348 c = getopt (argc, argv, "c:");
349 init ();
350
351 load_config:
352 if (panel.area.pmap) XFreePixmap (server.dsp, panel.area.pmap);
353 panel.area.pmap = 0;
354 // append full transparency background
355 list_back = g_slist_append(0, calloc(1, sizeof(Area)));
356
357 // read tint2rc config
358 i = 0;
359 if (c != -1)
360 i = config_read_file (optarg);
361 if (!i)
362 i = config_read ();
363 if (!i) {
364 fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
365 cleanup();
366 exit(1);
367 }
368 config_finish ();
369
370 window_draw_panel ();
371
372 // BUG: refresh(clock) is needed here, but 'on the paper' it's not necessary.
373 refresh(&panel.clock.area);
374
375 x11_fd = ConnectionNumber (server.dsp);
376 XSync (server.dsp, False);
377
378 while (1) {
379 // thanks to AngryLlama for the timer
380 // Create a File Description Set containing x11_fd
381 FD_ZERO (&fd);
382 FD_SET (x11_fd, &fd);
383
384 tv.tv_usec = 500000;
385 tv.tv_sec = 0;
386
387 // Wait for X Event or a Timer
388 if (select(x11_fd+1, &fd, 0, 0, &tv)) {
389 while (XPending (server.dsp)) {
390 XNextEvent(server.dsp, &e);
391
392 switch (e.type) {
393 case ButtonPress:
394 if (e.xbutton.button == 1) event_button_press (e.xbutton.x, e.xbutton.y);
395 break;
396
397 case ButtonRelease:
398 event_button_release (e.xbutton.button, e.xbutton.x, e.xbutton.y);
399 break;
400
401 case Expose:
402 XCopyArea (server.dsp, panel.area.pmap, server.root_win, server.gc_root, 0, 0, panel.area.width, panel.area.height, server.posx, server.posy);
403 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);
404 break;
405
406 case PropertyNotify:
407 //printf("PropertyNotify\n");
408 event_property_notify (e.xproperty.window, e.xproperty.atom);
409 break;
410
411 case ConfigureNotify:
412 if (e.xconfigure.window == server.root_win)
413 goto load_config;
414 else
415 if (panel.mode == MULTI_MONITOR)
416 event_configure_notify (e.xconfigure.window);
417 break;
418 }
419 }
420 }
421 else event_timer();
422
423 switch (panel.signal_pending) {
424 case SIGUSR1:
425 goto load_config;
426 case SIGINT:
427 case SIGTERM:
428 cleanup ();
429 return 0;
430 }
431
432 if (panel.refresh && !panel.sleep_mode) {
433 visual_refresh ();
434 //printf(" *** visual_refresh\n");
435 }
436 }
437 }
438
439
This page took 0.051886 seconds and 4 git commands to generate.