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