Remove signal handler hack of fbpanel.
[lxde/lxpanel.git] / src / panel.c
CommitLineData
a52c2257
HJYP
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <unistd.h>
10#include <errno.h>
11#include <locale.h>
12#include <string.h>
e7cb732b 13#include <glib/gi18n.h>
a52c2257
HJYP
14
15#include "plugin.h"
16#include "panel.h"
17#include "misc.h"
18#include "bg.h"
19#include "gtkbgbox.h"
20
77886b88
HJYP
21#include "lxpanelctl.h"
22
a52c2257
HJYP
23static gchar *cfgfile = NULL;
24static gchar version[] = VERSION;
25gchar *cprofile = "default";
26
27int config = 0;
28FbEv *fbev;
29
30//#define DEBUG
31#include "dbg.h"
32
33int log_level;
34
35FILE *pconf; // plugin part of profile file
36
37panel *p;
38
39
40/****************************************************
41 * panel's handlers for WM events *
42 ****************************************************/
43/*
44static void
45panel_del_wm_strut(panel *p)
46{
47 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT);
48 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL);
49}
50*/
51
52
53static void
54panel_set_wm_strut(panel *p)
55{
56 gulong data[12] = { 0 };
57 int i = 4;
58
59 ENTER;
60 if (!GTK_WIDGET_MAPPED (p->topgwin))
61 return;
62 switch (p->edge) {
63 case EDGE_LEFT:
64 i = 0;
65 data[i] = p->aw;
66 data[4 + i*2] = p->ay;
67 data[5 + i*2] = p->ay + p->ah;
68 break;
69 case EDGE_RIGHT:
70 i = 1;
71 data[i] = p->aw;
72 data[4 + i*2] = p->ay;
73 data[5 + i*2] = p->ay + p->ah;
74 break;
75 case EDGE_TOP:
76 i = 2;
77 data[i] = p->ah;
78 data[4 + i*2] = p->ax;
79 data[5 + i*2] = p->ax + p->aw;
80 break;
81 case EDGE_BOTTOM:
82 i = 3;
83 data[i] = p->ah;
84 data[4 + i*2] = p->ax;
85 data[5 + i*2] = p->ax + p->aw;
86 break;
87 default:
88 ERR("wrong edge %d. strut won't be set\n", p->edge);
89 RET();
90 }
91 DBG("type %d. width %d. from %d to %d\n", i, data[i], data[4 + i*2], data[5 + i*2]);
92
93 /* if wm supports STRUT_PARTIAL it will ignore STRUT */
94 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL,
95 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 12);
96 /* old spec, for wms that do not support STRUT_PARTIAL */
97 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT,
98 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 4);
99
100 RET();
101}
102
103static void
104print_wmdata(panel *p)
105{
106 int i;
107
108 ENTER;
109 RET();
110 DBG("desktop %d/%d\n", p->curdesk, p->desknum);
111 DBG("workarea\n");
112 for (i = 0; i < p->wa_len/4; i++)
113 DBG("(%d, %d) x (%d, %d)\n",
114 p->workarea[4*i + 0],
115 p->workarea[4*i + 1],
116 p->workarea[4*i + 2],
117 p->workarea[4*i + 3]);
118 RET();
119}
120
121
e996608e 122/* defined in plugins/menu.c */
8c44345a 123gboolean show_system_menu( gpointer system_menu );
e996608e
HJYP
124
125/* built-in commands, defined in configurator.c */
77886b88
HJYP
126void configure(void);
127void restart(void);
128void gtk_run(void);
129
8c44345a 130static void process_client_msg ( panel *p, XClientMessageEvent* ev )
77886b88 131{
8c44345a 132 int cmd = ev->data.b[0];
77886b88
HJYP
133 switch( cmd )
134 {
135 case LXPANEL_CMD_SYS_MENU:
8c44345a
HJYP
136 if( p->system_menu )
137 {
138 show_system_menu( p->system_menu );
139 /* FIXME: I've no idea why this doesn't work without timeout
140 under some WMs, like icewm. */
141 g_timeout_add( 200, show_system_menu, p->system_menu );
142 }
77886b88
HJYP
143 break;
144 case LXPANEL_CMD_RUN:
145 gtk_run();
146 break;
147 case LXPANEL_CMD_CONFIG:
148 configure();
149 break;
150 case LXPANEL_CMD_RESTART:
151 restart();
152 break;
153 case LXPANEL_CMD_EXIT:
154 gtk_main_quit();
155 break;
156 }
157}
158
a52c2257
HJYP
159static GdkFilterReturn
160panel_event_filter(GdkXEvent *xevent, GdkEvent *event, panel *p)
161{
162 Atom at;
163 Window win;
164 XEvent *ev = (XEvent *) xevent;
165
166 ENTER;
167 DBG("win = 0x%x\n", ev->xproperty.window);
77886b88
HJYP
168 if (ev->type != PropertyNotify ) {
169 /* private client message from lxpanelctl */
170 if( ev->type == ClientMessage && ev->xproperty.atom == a_LXPANEL_CMD )
171 {
8c44345a 172 process_client_msg( p, (XClientMessageEvent*)ev );
77886b88 173 }
a52c2257 174 RET(GDK_FILTER_CONTINUE);
77886b88
HJYP
175 }
176
a52c2257
HJYP
177 at = ev->xproperty.atom;
178 win = ev->xproperty.window;
179 DBG("win=%x at=%d\n", win, at);
180 if (win == GDK_ROOT_WINDOW()) {
181 if (at == a_NET_CLIENT_LIST) {
182 DBG("A_NET_CLIENT_LIST\n");
183 fb_ev_trigger(fbev, EV_CLIENT_LIST);
184 } else if (at == a_NET_CURRENT_DESKTOP) {
185 DBG("A_NET_CURRENT_DESKTOP\n");
186 p->curdesk = get_net_current_desktop();
187 fb_ev_trigger(fbev, EV_CURRENT_DESKTOP);
188 } else if (at == a_NET_NUMBER_OF_DESKTOPS) {
189 DBG("A_NET_NUMBER_OF_DESKTOPS\n");
190 p->desknum = get_net_number_of_desktops();
191 fb_ev_trigger(fbev, EV_NUMBER_OF_DESKTOPS);
192 } else if (at == a_NET_DESKTOP_NAMES) {
193 DBG("A_NET_DESKTOP_NAMES\n");
194 fb_ev_trigger(fbev, EV_DESKTOP_NAMES);
195 } else if (at == a_NET_ACTIVE_WINDOW) {
196 DBG("A_NET_ACTIVE_WINDOW\n");
197 fb_ev_trigger(fbev, EV_ACTIVE_WINDOW);
198 }else if (at == a_NET_CLIENT_LIST_STACKING) {
199 DBG("A_NET_CLIENT_LIST_STACKING\n");
200 fb_ev_trigger(fbev, EV_CLIENT_LIST_STACKING);
201 } else if (at == a_XROOTPMAP_ID) {
202 DBG("a_XROOTPMAP_ID\n");
203 if (p->transparent) {
204 fb_bg_notify_changed_bg(p->bg);
205 }
206 } else if (at == a_NET_WORKAREA) {
207 DBG("A_NET_WORKAREA\n");
0dcb6bf5 208 g_free( p->workarea );
a52c2257
HJYP
209 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
210 print_wmdata(p);
211 } else
212 RET(GDK_FILTER_CONTINUE);
213 RET(GDK_FILTER_REMOVE);
214 }
215 DBG("non root %x\n", win);
216 RET(GDK_FILTER_CONTINUE);
217}
218
219/****************************************************
220 * panel's handlers for GTK events *
221 ****************************************************/
222
223
224static gint
225panel_delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
226{
227 ENTER;
228 RET(FALSE);
229}
230
231static gint
232panel_destroy_event(GtkWidget * widget, GdkEvent * event, gpointer data)
233{
234 //panel *p = (panel *) data;
235
236 ENTER;
237 //if (!p->self_destroy)
238 gtk_main_quit();
239 RET(FALSE);
240}
241
242
243static void
244panel_realize(GtkWidget *widget, panel *p)
245{
246 ENTER;
247 RET();
248
249}
250static gint
251panel_size_req(GtkWidget *widget, GtkRequisition *req, panel *p)
252{
253 ENTER;
254 DBG("IN req=(%d, %d)\n", req->width, req->height);
255 if (p->widthtype == WIDTH_REQUEST)
256 p->width = (p->orientation == ORIENT_HORIZ) ? req->width : req->height;
257 if (p->heighttype == HEIGHT_REQUEST)
258 p->height = (p->orientation == ORIENT_HORIZ) ? req->height : req->width;
259 calculate_position(p);
260 req->width = p->aw;
261 req->height = p->ah;
262 DBG("OUT req=(%d, %d)\n", req->width, req->height);
263 RET( TRUE );
264}
265
266static gint
267panel_size_alloc(GtkWidget *widget, GtkAllocation *a, panel *p)
268{
269 ENTER;
270 DBG("installed alloc: size (%d, %d). pos (%d, %d)\n", aa->width, aa->height, aa->x, aa->y);
271 DBG("suggested alloc: size (%d, %d). pos (%d, %d)\n", a->width, a->height, a->x, a->y);
272 DBG("prev pref alloc: size (%d, %d). pos (%d, %d)\n", p->aw, p->ah, p->ax, p->ay);
273 if (p->widthtype == WIDTH_REQUEST)
274 p->width = (p->orientation == ORIENT_HORIZ) ? a->width : a->height;
275 if (p->heighttype == HEIGHT_REQUEST)
276 p->height = (p->orientation == ORIENT_HORIZ) ? a->height : a->width;
277 calculate_position(p);
278 DBG("curr pref alloc: size (%d, %d). pos (%d, %d)\n", p->aw, p->ah, p->ax, p->ay);
279 if (a->width == p->aw && a->height == p->ah && a->x == p->ax && a->y == p ->ay) {
280 DBG("actual coords eq to preffered. just returning\n");
281 RET(TRUE);
282 }
283
284 gtk_window_move(GTK_WINDOW(p->topgwin), p->ax, p->ay);
285 DBG("moving to %d %d\n", p->ax, p->ay);
286 if (p->setstrut)
287 panel_set_wm_strut(p);
288 RET(TRUE);
289}
290
291
292static gboolean
293panel_configure_event (GtkWidget *widget, GdkEventConfigure *e, panel *p)
294{
295 ENTER;
296 if (e->width == p->cw && e->height == p->ch && e->x == p->cx && e->y == p->cy)
297 RET(TRUE);
298 p->cw = e->width;
299 p->ch = e->height;
300 p->cx = e->x;
301 p->cy = e->y;
302 DBG("here\n");
303 if (p->transparent)
304 fb_bg_notify_changed_bg(p->bg);
305 DBG("here\n");
306 DBG("geom: size (%d, %d). pos (%d, %d)\n", e->width, e->height, e->x, e->y);
307 RET(FALSE);
308
309}
310
311
312/****************************************************
313 * panel creation *
314 ****************************************************/
315static void
316make_round_corners(panel *p)
317{
318 GtkWidget *b1, *b2, *img;
319 GtkWidget *(*box_new) (gboolean, gint);
320 void (*box_pack)(GtkBox *, GtkWidget *, gboolean, gboolean, guint);
321 gchar *s1, *s2;
322#define IMGPREFIX PACKAGE_DATA_DIR "/lxpanel/images/"
323
324 ENTER;
325 if (p->edge == EDGE_TOP) {
326 s1 = IMGPREFIX "top-left.xpm";
327 s2 = IMGPREFIX "top-right.xpm";
328 } else if (p->edge == EDGE_BOTTOM) {
329 s1 = IMGPREFIX "bottom-left.xpm";
330 s2 = IMGPREFIX "bottom-right.xpm";
331 } else if (p->edge == EDGE_LEFT) {
332 s1 = IMGPREFIX "top-left.xpm";
333 s2 = IMGPREFIX "bottom-left.xpm";
334 } else if (p->edge == EDGE_RIGHT) {
335 s1 = IMGPREFIX "top-right.xpm";
336 s2 = IMGPREFIX "bottom-right.xpm";
337 } else
338 RET();
339
340 box_new = (p->orientation == ORIENT_HORIZ) ? gtk_vbox_new : gtk_hbox_new;
341 b1 = box_new(0, FALSE);
342 gtk_widget_show(b1);
343 b2 = box_new(0, FALSE);
344 gtk_widget_show(b2);
345
346 box_pack = (p->edge == EDGE_TOP || p->edge == EDGE_LEFT) ?
347 gtk_box_pack_start : gtk_box_pack_end;
348
349 img = gtk_image_new_from_file(s1);
350 gtk_widget_show(img);
351 box_pack(GTK_BOX(b1), img, FALSE, FALSE, 0);
352 img = gtk_image_new_from_file(s2);
353 gtk_widget_show(img);
354 box_pack(GTK_BOX(b2), img, FALSE, FALSE, 0);
355 gtk_box_pack_start(GTK_BOX(p->lbox), b1, FALSE, FALSE, 0);
356 gtk_box_pack_end(GTK_BOX(p->lbox), b2, FALSE, FALSE, 0);
357 RET();
358}
359
360void
361panel_start_gui(panel *p)
362{
363 Atom state[3];
364 XWMHints wmhints;
365 guint32 val;
366
367
368 ENTER;
369
370 // main toplevel window
371 p->topgwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
372 gtk_container_set_border_width(GTK_CONTAINER(p->topgwin), 0);
373 gtk_window_set_resizable(GTK_WINDOW(p->topgwin), FALSE);
374 gtk_window_set_wmclass(GTK_WINDOW(p->topgwin), "panel", "lxpanel");
375 gtk_window_set_title(GTK_WINDOW(p->topgwin), "panel");
376 gtk_window_set_position(GTK_WINDOW(p->topgwin), GTK_WIN_POS_NONE);
377 gtk_window_set_decorated(GTK_WINDOW(p->topgwin), FALSE);
77886b88 378
a52c2257
HJYP
379 g_signal_connect(G_OBJECT(p->topgwin), "delete-event",
380 G_CALLBACK(panel_delete_event), p);
381 g_signal_connect(G_OBJECT(p->topgwin), "destroy-event",
382 G_CALLBACK(panel_destroy_event), p);
383 g_signal_connect (G_OBJECT (p->topgwin), "size-request",
384 (GCallback) panel_size_req, p);
385 g_signal_connect (G_OBJECT (p->topgwin), "size-allocate",
386 (GCallback) panel_size_alloc, p);
387 g_signal_connect (G_OBJECT (p->topgwin), "configure-event",
388 (GCallback) panel_configure_event, p);
389 g_signal_connect (G_OBJECT (p->topgwin), "realize",
390 (GCallback) panel_realize, p);
391
392 gtk_widget_realize(p->topgwin);
393 //gdk_window_set_decorations(p->topgwin->window, 0);
394 gtk_widget_set_app_paintable(p->topgwin, TRUE);
395
396 // background box all over toplevel
397 p->bbox = gtk_bgbox_new();
398 gtk_container_add(GTK_CONTAINER(p->topgwin), p->bbox);
399 gtk_widget_show(p->bbox);
400 gtk_container_set_border_width(GTK_CONTAINER(p->bbox), 0);
401 if (p->transparent) {
402 p->bg = fb_bg_get_for_display();
403 gtk_bgbox_set_background(p->bbox, BG_ROOT, p->tintcolor, p->alpha);
404 }
405
406 // main layout manager as a single child of background widget box
407 p->lbox = p->my_box_new(FALSE, 0);
408 gtk_container_set_border_width(GTK_CONTAINER(p->lbox), 0);
409 gtk_container_add(GTK_CONTAINER(p->bbox), p->lbox);
410 gtk_widget_show(p->lbox);
411 if (p->round_corners)
412 make_round_corners(p);
413
414 p->box = p->my_box_new(FALSE, p->spacing);
415 gtk_container_set_border_width(GTK_CONTAINER(p->box), 0);
416 gtk_box_pack_start(GTK_BOX(p->lbox), p->box, TRUE, TRUE, 0);
417 gtk_widget_show(p->box);
418
419 p->topxwin = GDK_WINDOW_XWINDOW(GTK_WIDGET(p->topgwin)->window);
420 DBG("topxwin = %x\n", p->topxwin);
421
422 /* the settings that should be done before window is mapped */
423 wmhints.flags = InputHint;
424 wmhints.input = 0;
425 XSetWMHints (GDK_DISPLAY(), p->topxwin, &wmhints);
426#define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
427 val = WIN_HINTS_SKIP_FOCUS;
428 XChangeProperty(GDK_DISPLAY(), p->topxwin,
429 XInternAtom(GDK_DISPLAY(), "_WIN_HINTS", False), XA_CARDINAL, 32,
430 PropModeReplace, (unsigned char *) &val, 1);
431
432 if (p->setdocktype) {
433 state[0] = a_NET_WM_WINDOW_TYPE_DOCK;
434 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_WINDOW_TYPE, XA_ATOM,
435 32, PropModeReplace, (unsigned char *) state, 1);
436 }
437
438 /* window mapping point */
439 gtk_widget_show_all(p->topgwin);
440
441 /* the settings that should be done after window is mapped */
442
443 /* send it to running wm */
444 Xclimsg(p->topxwin, a_NET_WM_DESKTOP, 0xFFFFFFFF, 0, 0, 0, 0);
445 /* and assign it ourself just for case when wm is not running */
446 val = 0xFFFFFFFF;
447 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_DESKTOP, XA_CARDINAL, 32,
448 PropModeReplace, (unsigned char *) &val, 1);
449
450 state[0] = a_NET_WM_STATE_SKIP_PAGER;
451 state[1] = a_NET_WM_STATE_SKIP_TASKBAR;
452 state[2] = a_NET_WM_STATE_STICKY;
453 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STATE, XA_ATOM,
454 32, PropModeReplace, (unsigned char *) state, 3);
455
77886b88 456 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), SubstructureNotifyMask|PropertyChangeMask);
a52c2257
HJYP
457 gdk_window_add_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
458
459 calculate_position(p);
460 gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
461 if (p->setstrut)
462 panel_set_wm_strut(p);
77886b88 463
a52c2257
HJYP
464 RET();
465}
466
467static int
468panel_parse_global(panel *p, FILE *fp)
469{
470 line s;
471 s.len = 256;
472
473 ENTER;
474 while (get_line(fp, &s) != LINE_NONE) {
475 if (s.type == LINE_VAR) {
476 if (!g_ascii_strcasecmp(s.t[0], "edge")) {
477 p->edge = str2num(edge_pair, s.t[1], EDGE_NONE);
478 } else if (!g_ascii_strcasecmp(s.t[0], "allign")) {
479 p->allign = str2num(allign_pair, s.t[1], ALLIGN_NONE);
480 } else if (!g_ascii_strcasecmp(s.t[0], "margin")) {
481 p->margin = atoi(s.t[1]);
482 } else if (!g_ascii_strcasecmp(s.t[0], "widthtype")) {
483 p->widthtype = str2num(width_pair, s.t[1], WIDTH_NONE);
484 } else if (!g_ascii_strcasecmp(s.t[0], "width")) {
485 p->width = atoi(s.t[1]);
486 } else if (!g_ascii_strcasecmp(s.t[0], "heighttype")) {
487 p->heighttype = str2num(height_pair, s.t[1], HEIGHT_NONE);
488 } else if (!g_ascii_strcasecmp(s.t[0], "height")) {
489 p->height = atoi(s.t[1]);
490 } else if (!g_ascii_strcasecmp(s.t[0], "spacing")) {
491 p->spacing = atoi(s.t[1]);
492 } else if (!g_ascii_strcasecmp(s.t[0], "SetDockType")) {
493 p->setdocktype = str2num(bool_pair, s.t[1], 0);
494 } else if (!g_ascii_strcasecmp(s.t[0], "SetPartialStrut")) {
495 p->setstrut = str2num(bool_pair, s.t[1], 0);
496 } else if (!g_ascii_strcasecmp(s.t[0], "RoundCorners")) {
497 p->round_corners = str2num(bool_pair, s.t[1], 0);
498 } else if (!g_ascii_strcasecmp(s.t[0], "Transparent")) {
499 p->transparent = str2num(bool_pair, s.t[1], 0);
500 } else if (!g_ascii_strcasecmp(s.t[0], "Alpha")) {
501 p->alpha = atoi(s.t[1]);
502 if (p->alpha > 255)
503 p->alpha = 255;
504 } else if (!g_ascii_strcasecmp(s.t[0], "TintColor")) {
505 if (!gdk_color_parse (s.t[1], &p->gtintcolor))
506 gdk_color_parse ("white", &p->gtintcolor);
507 p->tintcolor = gcolor2rgb24(&p->gtintcolor);
508 DBG("tintcolor=%x\n", p->tintcolor);
509 } else {
510 ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
511 RET(0);
512 }
513 } else if (s.type == LINE_BLOCK_END) {
514 break;
515 } else {
516 ERR( "lxpanel: illegal in this context %s\n", s.str);
517 RET(0);
518 }
519 }
520 p->orientation = (p->edge == EDGE_TOP || p->edge == EDGE_BOTTOM)
521 ? ORIENT_HORIZ : ORIENT_VERT;
522 if (p->orientation == ORIENT_HORIZ) {
523 p->my_box_new = gtk_hbox_new;
524 p->my_separator_new = gtk_vseparator_new;
525 } else {
526 p->my_box_new = gtk_vbox_new;
527 p->my_separator_new = gtk_hseparator_new;
528 }
529 if (p->width < 0)
530 p->width = 100;
531 if (p->widthtype == WIDTH_PERCENT && p->width > 100)
532 p->width = 100;
533 p->heighttype = HEIGHT_PIXEL;
534 if (p->heighttype == HEIGHT_PIXEL) {
535 if (p->height < PANEL_HEIGHT_MIN)
536 p->height = PANEL_HEIGHT_MIN;
537 else if (p->height > PANEL_HEIGHT_MAX)
538 p->height = PANEL_HEIGHT_MAX;
539 }
540 p->curdesk = get_net_current_desktop();
541 p->desknum = get_net_number_of_desktops();
542 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
543 print_wmdata(p);
544 panel_start_gui(p);
545 RET(1);
546}
547
548static int
549panel_parse_plugin(panel *p, FILE *fp)
550{
551 line s;
552 plugin *plug = NULL;
553 gchar *type = NULL;
554 FILE *tmpfp;
555 int expand , padding, border;
556
557 ENTER;
558 s.len = 256;
559 if (!(tmpfp = tmpfile())) {
560 ERR( "can't open temporary file with tmpfile()\n");
561 RET(0);
562 }
563 border = expand = padding = 0;
564 while (get_line(fp, &s) != LINE_BLOCK_END) {
565 if (s.type == LINE_NONE) {
566 ERR( "lxpanel: bad line %s\n", s.str);
567 goto error;
568 }
569 if (s.type == LINE_VAR) {
570 if (!g_ascii_strcasecmp(s.t[0], "type")) {
571 type = g_strdup(s.t[1]);
572 DBG("plug %s\n", type);
573 } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
574 expand = str2num(bool_pair, s.t[1], 0);
575 else if (!g_ascii_strcasecmp(s.t[0], "padding"))
576 padding = atoi(s.t[1]);
577 else if (!g_ascii_strcasecmp(s.t[0], "border"))
578 border = atoi(s.t[1]);
579 else {
580 ERR( "lxpanel: unknown var %s\n", s.t[0]);
581 goto error;
582 }
583 } else if (s.type == LINE_BLOCK_START) {
584 if (!g_ascii_strcasecmp(s.t[0], "Config")) {
585 int pno = 1;
586 while (pno) {
587 get_line_as_is(fp, &s);
588 if (s.type == LINE_NONE) {
589 ERR( "lxpanel: unexpected eof\n");
590 goto error;
591 } else if (s.type == LINE_BLOCK_START) {
592 pno++;
593 } else if (s.type == LINE_BLOCK_END) {
594 pno--;
595 }
596 fprintf(tmpfp, "%s\n", s.str);
597 }
598 } else {
599 ERR( "lxpanel: unknown block %s\n", s.t[0]);
600 goto error;
601 }
602 } else {
603 ERR( "lxpanel: illegal in this context %s\n", s.str);
604 goto error;
605 }
606 }
607
608 if (!type || !(plug = plugin_load(type))) {
609 ERR( "lxpanel: can't load %s plugin\n", type);
610 goto error;
611 }
612 plug->panel = p;
613 plug->fp = tmpfp;
614 plug->expand = expand;
615 plug->padding = padding;
616 plug->border = border;
617 fprintf(tmpfp, "}\n");
618 fseek(tmpfp, 0, SEEK_SET);
619 DBG("starting\n");
620 if (!plugin_start(plug)) {
621 ERR( "lxpanel: can't start plugin %s\n", type);
622 goto error;
623 }
624 DBG("plug %s\n", type);
625 p->plugins = g_list_append(p->plugins, plug);
0dcb6bf5
HJYP
626
627 g_free( type );
a52c2257
HJYP
628 RET(1);
629
630 error:
631 fclose(tmpfp);
632 g_free(type);
633 if (plug)
634 plugin_put(plug);
635 RET(0);
636
637}
638
639
640int
641panel_start(panel *p, FILE *fp)
642{
643 line s;
644 long pos;
645
646 /* parse global section */
647 ENTER;
648 s.len = 256;
649 memset(p, 0, sizeof(panel));
650 p->allign = ALLIGN_CENTER;
651 p->edge = EDGE_BOTTOM;
652 p->widthtype = WIDTH_PERCENT;
653 p->width = 100;
654 p->heighttype = HEIGHT_PIXEL;
655 p->height = PANEL_HEIGHT_DEFAULT;
656 p->setdocktype = 1;
657 p->setstrut = 1;
658 p->round_corners = 0;
659 p->transparent = 0;
660 p->alpha = 127;
661 p->tintcolor = 0xFFFFFFFF;
662 p->spacing = 0;
663 fbev = fb_ev_new();
664 if ((get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
665 ERR( "lxpanel: config file must start from Global section\n");
666 RET(0);
667 }
668 if (!panel_parse_global(p, fp))
669 RET(0);
670
671 if (!(pconf = tmpfile())) {
672 ERR("can't open temporary file\n");
673 RET(0);
674 }
675 pos = ftell(fp);
676 while (get_line_as_is(fp, &s) != LINE_NONE)
677 fprintf(pconf, "%s\n", s.str);
678 fseek(fp, pos, SEEK_SET);
679
680 while (get_line(fp, &s) != LINE_NONE) {
681 if ((s.type != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
682 ERR( "lxpanel: expecting Plugin section\n");
683 RET(0);
684 }
685 if (!panel_parse_plugin(p, fp))
686 RET(0);
687 }
688 gtk_widget_show_all(p->topgwin);
689 print_wmdata(p);
690 RET(1);
691}
692
693static void
694delete_plugin(gpointer data, gpointer udata)
695{
696 ENTER;
697 plugin_stop((plugin *)data);
698 plugin_put((plugin *)data);
699 RET();
700
701}
702
703void panel_stop(panel *p)
704{
705 ENTER;
706
707 g_list_foreach(p->plugins, delete_plugin, NULL);
708 g_list_free(p->plugins);
709 p->plugins = NULL;
8c44345a
HJYP
710
711 if( p->system_menu ){
712 do{
713 } while ( g_source_remove_by_user_data( p->system_menu ) );
714 }
715
a52c2257
HJYP
716 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), NoEventMask);
717 gdk_window_remove_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
718 gtk_widget_destroy(p->topgwin);
719 g_object_unref(fbev);
720 g_free(p->workarea);
721 fclose(pconf);
722 gdk_flush();
723 XFlush(GDK_DISPLAY());
724 XSync(GDK_DISPLAY(), True);
725 RET();
726}
727
728
729void
730usage()
731{
732 ENTER;
e7cb732b
HJYP
733 g_print(_("lxpanel %s - lightweight GTK2+ panel for UNIX desktops\n"), version);
734 g_print(_("Command line options:\n"));
735 g_print(_(" --help -- print this help and exit\n"));
736 g_print(_(" --version -- print version and exit\n"));
737 g_print(_(" --log <number> -- set log level 0-5. 0 - none 5 - chatty\n"));
738 g_print(_(" --configure -- launch configuration utility\n"));
739 g_print(_(" --profile name -- use specified profile\n"));
740 g_print("\n");
741 g_print(_(" -h -- same as --help\n"));
742 g_print(_(" -p -- same as --profile\n"));
743 g_print(_(" -v -- same as --version\n"));
744 g_print(_(" -C -- same as --configure\n"));
745 g_print(_("\nVisit http://lxpanel.sourceforge.net/ for detailed documentation,\n\n"));
a52c2257
HJYP
746}
747
748FILE *
749open_profile(gchar *profile)
750{
751 gchar *fname;
752 FILE *fp;
753
754 ENTER;
755 LOG(LOG_INFO, "loading %s profile\n", profile);
756 fname = g_strdup_printf("%s/.lxpanel/%s", getenv("HOME"), profile);
757 fp = fopen(fname, "r");
758 LOG(LOG_INFO, " %s %s\n", fname, fp ? "ok" : "no");
759 if (fp) {
760 cfgfile = fname;
761 RET(fp);
762 }
763 //ERR("Can't load %s\n", fname);
764 g_free(fname);
765
766 /* check private configuration directory */
767 fname = g_strdup_printf(PACKAGE_DATA_DIR "/lxpanel/%s", profile);
768 fp = fopen(fname, "r");
769 LOG(LOG_INFO, " %s %s\n", fname, fp ? "ok" : "no");
770 if (fp) {
771 cfgfile = fname;
772 RET(fp);
773 }
774 //ERR("Can't load %s\n", fname);
775 g_free(fname);
776 LOG(LOG_ERR, "Can't open '%s' profile\n", profile);
777 RET(NULL);
778}
779
780void
781handle_error(Display * d, XErrorEvent * ev)
782{
783 char buf[256];
784
785 ENTER;
786 if (log_level >= LOG_WARN) {
787 XGetErrorText(GDK_DISPLAY(), ev->error_code, buf, 256);
788 LOG(LOG_WARN, "lxpanel : X error: %s\n", buf);
789 }
790 RET();
791}
792
a52c2257
HJYP
793int
794main(int argc, char *argv[], char *env[])
795{
796 int i;
797 int quit = 0;
798 void configure();
799 FILE *pfp; /* current profile FP */
f277dbb7 800
a52c2257
HJYP
801 ENTER;
802 //printf("sizeof(gulong)=%d\n", sizeof(gulong));
803 setlocale(LC_CTYPE, "");
f277dbb7 804
a52c2257
HJYP
805 gtk_init(&argc, &argv);
806
807#ifdef ENABLE_NLS
808 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
809 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
810 textdomain ( GETTEXT_PACKAGE );
811#endif
812
813 XSetLocaleModifiers("");
814 XSetErrorHandler((XErrorHandler) handle_error);
815 resolve_atoms();
816 for (i = 1; i < argc; i++) {
817 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
818 usage();
819 exit(0);
820 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
821 printf("lxpanel %s\n", version);
822 exit(0);
823 } else if (!strcmp(argv[i], "--log")) {
824 i++;
825 if (i == argc) {
826 ERR( "lxpanel: missing log level\n");
827 usage();
828 exit(1);
829 } else {
830 log_level = atoi(argv[i]);
831 }
832 } else if (!strcmp(argv[i], "--configure") || !strcmp(argv[i], "-C")) {
833 config = 1;
834 } else if (!strcmp(argv[i], "--profile") || !strcmp(argv[i], "-p")) {
835 i++;
836 if (i == argc) {
837 ERR( "lxpanel: missing profile name\n");
838 usage();
839 exit(1);
840 } else {
841 cprofile = g_strdup(argv[i]);
842 }
843 } else {
844 printf("lxpanel: unknown option - %s\n", argv[i]);
845 usage();
846 exit(1);
847 }
848 }
f277dbb7
HJYP
849
850 /* Add our own icons to the search path of icon theme */
851 gtk_icon_theme_append_search_path( gtk_icon_theme_get_default(),
852 PACKAGE_DATA_DIR "/lxpanel/images" );
853
5541b8d2
JH
854 /* Enter main loop */
855 {
a52c2257
HJYP
856 if (!(pfp = open_profile(cprofile)))
857 exit(1);
858 p = g_new0(panel, 1);
859 g_return_val_if_fail (p != NULL, 1);
860 if (!panel_start(p, pfp)) {
861 ERR( "lxpanel: can't start panel\n");
862 exit(1);
863 }
864 fclose(pfp);
0dcb6bf5 865 g_free( cfgfile ); /* FIXME: is it safe to free the string here? */
a52c2257
HJYP
866 if (config)
867 configure();
868 gtk_main();
869 panel_stop(p);
870 g_free(p);
5541b8d2
JH
871 }
872
873 return 0;
a52c2257
HJYP
874}
875