Add temporary hack for config saving of menu, launchbar, and image.
[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;
6db11841 363
a52c2257
HJYP
364 ENTER;
365
366 // main toplevel window
367 p->topgwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
368 gtk_container_set_border_width(GTK_CONTAINER(p->topgwin), 0);
369 gtk_window_set_resizable(GTK_WINDOW(p->topgwin), FALSE);
370 gtk_window_set_wmclass(GTK_WINDOW(p->topgwin), "panel", "lxpanel");
371 gtk_window_set_title(GTK_WINDOW(p->topgwin), "panel");
372 gtk_window_set_position(GTK_WINDOW(p->topgwin), GTK_WIN_POS_NONE);
373 gtk_window_set_decorated(GTK_WINDOW(p->topgwin), FALSE);
77886b88 374
a52c2257
HJYP
375 g_signal_connect(G_OBJECT(p->topgwin), "delete-event",
376 G_CALLBACK(panel_delete_event), p);
377 g_signal_connect(G_OBJECT(p->topgwin), "destroy-event",
378 G_CALLBACK(panel_destroy_event), p);
379 g_signal_connect (G_OBJECT (p->topgwin), "size-request",
380 (GCallback) panel_size_req, p);
381 g_signal_connect (G_OBJECT (p->topgwin), "size-allocate",
382 (GCallback) panel_size_alloc, p);
383 g_signal_connect (G_OBJECT (p->topgwin), "configure-event",
384 (GCallback) panel_configure_event, p);
385 g_signal_connect (G_OBJECT (p->topgwin), "realize",
386 (GCallback) panel_realize, p);
6db11841 387
a52c2257
HJYP
388 gtk_widget_realize(p->topgwin);
389 //gdk_window_set_decorations(p->topgwin->window, 0);
390 gtk_widget_set_app_paintable(p->topgwin, TRUE);
6db11841 391
a52c2257
HJYP
392 // background box all over toplevel
393 p->bbox = gtk_bgbox_new();
394 gtk_container_add(GTK_CONTAINER(p->topgwin), p->bbox);
395 gtk_widget_show(p->bbox);
396 gtk_container_set_border_width(GTK_CONTAINER(p->bbox), 0);
397 if (p->transparent) {
398 p->bg = fb_bg_get_for_display();
399 gtk_bgbox_set_background(p->bbox, BG_ROOT, p->tintcolor, p->alpha);
400 }
401
402 // main layout manager as a single child of background widget box
403 p->lbox = p->my_box_new(FALSE, 0);
404 gtk_container_set_border_width(GTK_CONTAINER(p->lbox), 0);
405 gtk_container_add(GTK_CONTAINER(p->bbox), p->lbox);
406 gtk_widget_show(p->lbox);
407 if (p->round_corners)
408 make_round_corners(p);
409
410 p->box = p->my_box_new(FALSE, p->spacing);
411 gtk_container_set_border_width(GTK_CONTAINER(p->box), 0);
412 gtk_box_pack_start(GTK_BOX(p->lbox), p->box, TRUE, TRUE, 0);
413 gtk_widget_show(p->box);
6db11841 414
a52c2257
HJYP
415 p->topxwin = GDK_WINDOW_XWINDOW(GTK_WIDGET(p->topgwin)->window);
416 DBG("topxwin = %x\n", p->topxwin);
417
418 /* the settings that should be done before window is mapped */
419 wmhints.flags = InputHint;
420 wmhints.input = 0;
421 XSetWMHints (GDK_DISPLAY(), p->topxwin, &wmhints);
422#define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
423 val = WIN_HINTS_SKIP_FOCUS;
424 XChangeProperty(GDK_DISPLAY(), p->topxwin,
425 XInternAtom(GDK_DISPLAY(), "_WIN_HINTS", False), XA_CARDINAL, 32,
426 PropModeReplace, (unsigned char *) &val, 1);
427
428 if (p->setdocktype) {
429 state[0] = a_NET_WM_WINDOW_TYPE_DOCK;
430 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_WINDOW_TYPE, XA_ATOM,
431 32, PropModeReplace, (unsigned char *) state, 1);
432 }
433
434 /* window mapping point */
435 gtk_widget_show_all(p->topgwin);
436
437 /* the settings that should be done after window is mapped */
438
439 /* send it to running wm */
440 Xclimsg(p->topxwin, a_NET_WM_DESKTOP, 0xFFFFFFFF, 0, 0, 0, 0);
441 /* and assign it ourself just for case when wm is not running */
442 val = 0xFFFFFFFF;
443 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_DESKTOP, XA_CARDINAL, 32,
444 PropModeReplace, (unsigned char *) &val, 1);
445
446 state[0] = a_NET_WM_STATE_SKIP_PAGER;
447 state[1] = a_NET_WM_STATE_SKIP_TASKBAR;
448 state[2] = a_NET_WM_STATE_STICKY;
449 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STATE, XA_ATOM,
450 32, PropModeReplace, (unsigned char *) state, 3);
451
77886b88 452 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), SubstructureNotifyMask|PropertyChangeMask);
a52c2257
HJYP
453 gdk_window_add_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
454
455 calculate_position(p);
456 gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
457 if (p->setstrut)
458 panel_set_wm_strut(p);
77886b88 459
a52c2257
HJYP
460 RET();
461}
462
463static int
db449f6e 464panel_parse_global(panel *p, char **fp)
a52c2257
HJYP
465{
466 line s;
467 s.len = 256;
6db11841 468
a52c2257 469 ENTER;
c69ac68e 470 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
471 if (s.type == LINE_VAR) {
472 if (!g_ascii_strcasecmp(s.t[0], "edge")) {
473 p->edge = str2num(edge_pair, s.t[1], EDGE_NONE);
474 } else if (!g_ascii_strcasecmp(s.t[0], "allign")) {
475 p->allign = str2num(allign_pair, s.t[1], ALLIGN_NONE);
476 } else if (!g_ascii_strcasecmp(s.t[0], "margin")) {
477 p->margin = atoi(s.t[1]);
478 } else if (!g_ascii_strcasecmp(s.t[0], "widthtype")) {
479 p->widthtype = str2num(width_pair, s.t[1], WIDTH_NONE);
480 } else if (!g_ascii_strcasecmp(s.t[0], "width")) {
481 p->width = atoi(s.t[1]);
482 } else if (!g_ascii_strcasecmp(s.t[0], "heighttype")) {
483 p->heighttype = str2num(height_pair, s.t[1], HEIGHT_NONE);
484 } else if (!g_ascii_strcasecmp(s.t[0], "height")) {
485 p->height = atoi(s.t[1]);
486 } else if (!g_ascii_strcasecmp(s.t[0], "spacing")) {
487 p->spacing = atoi(s.t[1]);
488 } else if (!g_ascii_strcasecmp(s.t[0], "SetDockType")) {
489 p->setdocktype = str2num(bool_pair, s.t[1], 0);
490 } else if (!g_ascii_strcasecmp(s.t[0], "SetPartialStrut")) {
491 p->setstrut = str2num(bool_pair, s.t[1], 0);
492 } else if (!g_ascii_strcasecmp(s.t[0], "RoundCorners")) {
493 p->round_corners = str2num(bool_pair, s.t[1], 0);
494 } else if (!g_ascii_strcasecmp(s.t[0], "Transparent")) {
495 p->transparent = str2num(bool_pair, s.t[1], 0);
496 } else if (!g_ascii_strcasecmp(s.t[0], "Alpha")) {
497 p->alpha = atoi(s.t[1]);
498 if (p->alpha > 255)
499 p->alpha = 255;
500 } else if (!g_ascii_strcasecmp(s.t[0], "TintColor")) {
501 if (!gdk_color_parse (s.t[1], &p->gtintcolor))
502 gdk_color_parse ("white", &p->gtintcolor);
503 p->tintcolor = gcolor2rgb24(&p->gtintcolor);
504 DBG("tintcolor=%x\n", p->tintcolor);
505 } else {
506 ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
507 RET(0);
508 }
509 } else if (s.type == LINE_BLOCK_END) {
510 break;
511 } else {
512 ERR( "lxpanel: illegal in this context %s\n", s.str);
513 RET(0);
514 }
515 }
516 p->orientation = (p->edge == EDGE_TOP || p->edge == EDGE_BOTTOM)
517 ? ORIENT_HORIZ : ORIENT_VERT;
518 if (p->orientation == ORIENT_HORIZ) {
519 p->my_box_new = gtk_hbox_new;
520 p->my_separator_new = gtk_vseparator_new;
521 } else {
522 p->my_box_new = gtk_vbox_new;
523 p->my_separator_new = gtk_hseparator_new;
524 }
525 if (p->width < 0)
526 p->width = 100;
527 if (p->widthtype == WIDTH_PERCENT && p->width > 100)
528 p->width = 100;
529 p->heighttype = HEIGHT_PIXEL;
530 if (p->heighttype == HEIGHT_PIXEL) {
531 if (p->height < PANEL_HEIGHT_MIN)
532 p->height = PANEL_HEIGHT_MIN;
533 else if (p->height > PANEL_HEIGHT_MAX)
534 p->height = PANEL_HEIGHT_MAX;
535 }
536 p->curdesk = get_net_current_desktop();
537 p->desknum = get_net_number_of_desktops();
538 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
539 print_wmdata(p);
540 panel_start_gui(p);
541 RET(1);
542}
543
544static int
db449f6e 545panel_parse_plugin(panel *p, char **fp)
a52c2257
HJYP
546{
547 line s;
548 plugin *plug = NULL;
549 gchar *type = NULL;
a52c2257 550 int expand , padding, border;
db449f6e
HJYP
551 char* pconfig = NULL;
552
a52c2257
HJYP
553 ENTER;
554 s.len = 256;
a52c2257 555 border = expand = padding = 0;
c69ac68e 556 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
a52c2257
HJYP
557 if (s.type == LINE_NONE) {
558 ERR( "lxpanel: bad line %s\n", s.str);
559 goto error;
560 }
561 if (s.type == LINE_VAR) {
562 if (!g_ascii_strcasecmp(s.t[0], "type")) {
563 type = g_strdup(s.t[1]);
564 DBG("plug %s\n", type);
565 } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
566 expand = str2num(bool_pair, s.t[1], 0);
567 else if (!g_ascii_strcasecmp(s.t[0], "padding"))
568 padding = atoi(s.t[1]);
569 else if (!g_ascii_strcasecmp(s.t[0], "border"))
570 border = atoi(s.t[1]);
571 else {
572 ERR( "lxpanel: unknown var %s\n", s.t[0]);
573 goto error;
574 }
575 } else if (s.type == LINE_BLOCK_START) {
576 if (!g_ascii_strcasecmp(s.t[0], "Config")) {
db449f6e 577 pconfig = *fp;
a52c2257
HJYP
578 int pno = 1;
579 while (pno) {
580 get_line_as_is(fp, &s);
581 if (s.type == LINE_NONE) {
582 ERR( "lxpanel: unexpected eof\n");
583 goto error;
584 } else if (s.type == LINE_BLOCK_START) {
585 pno++;
586 } else if (s.type == LINE_BLOCK_END) {
587 pno--;
588 }
db449f6e 589 }
a52c2257
HJYP
590 } else {
591 ERR( "lxpanel: unknown block %s\n", s.t[0]);
592 goto error;
593 }
594 } else {
595 ERR( "lxpanel: illegal in this context %s\n", s.str);
596 goto error;
597 }
598 }
db449f6e 599
a52c2257
HJYP
600 if (!type || !(plug = plugin_load(type))) {
601 ERR( "lxpanel: can't load %s plugin\n", type);
602 goto error;
603 }
db449f6e 604
a52c2257 605 plug->panel = p;
a52c2257
HJYP
606 plug->expand = expand;
607 plug->padding = padding;
608 plug->border = border;
a52c2257 609 DBG("starting\n");
db449f6e 610 if (!plugin_start(plug, pconfig ? &pconfig : NULL)) {
a52c2257
HJYP
611 ERR( "lxpanel: can't start plugin %s\n", type);
612 goto error;
613 }
614 DBG("plug %s\n", type);
615 p->plugins = g_list_append(p->plugins, plug);
0dcb6bf5
HJYP
616
617 g_free( type );
a52c2257 618 RET(1);
db449f6e 619
a52c2257 620 error:
a52c2257
HJYP
621 g_free(type);
622 if (plug)
623 plugin_put(plug);
624 RET(0);
a52c2257
HJYP
625}
626
627
628int
db449f6e 629panel_start( panel *p, char **fp )
a52c2257
HJYP
630{
631 line s;
632 long pos;
db449f6e 633
a52c2257
HJYP
634 /* parse global section */
635 ENTER;
636 s.len = 256;
637 memset(p, 0, sizeof(panel));
638 p->allign = ALLIGN_CENTER;
639 p->edge = EDGE_BOTTOM;
640 p->widthtype = WIDTH_PERCENT;
641 p->width = 100;
642 p->heighttype = HEIGHT_PIXEL;
643 p->height = PANEL_HEIGHT_DEFAULT;
644 p->setdocktype = 1;
645 p->setstrut = 1;
646 p->round_corners = 0;
647 p->transparent = 0;
648 p->alpha = 127;
649 p->tintcolor = 0xFFFFFFFF;
650 p->spacing = 0;
651 fbev = fb_ev_new();
c69ac68e 652 if ((lxpanel_get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
a52c2257
HJYP
653 ERR( "lxpanel: config file must start from Global section\n");
654 RET(0);
655 }
656 if (!panel_parse_global(p, fp))
657 RET(0);
658
c69ac68e 659 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
660 if ((s.type != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
661 ERR( "lxpanel: expecting Plugin section\n");
662 RET(0);
663 }
664 if (!panel_parse_plugin(p, fp))
665 RET(0);
666 }
667 gtk_widget_show_all(p->topgwin);
668 print_wmdata(p);
669 RET(1);
670}
671
672static void
673delete_plugin(gpointer data, gpointer udata)
674{
675 ENTER;
676 plugin_stop((plugin *)data);
677 plugin_put((plugin *)data);
678 RET();
a52c2257
HJYP
679}
680
681void panel_stop(panel *p)
682{
683 ENTER;
684
685 g_list_foreach(p->plugins, delete_plugin, NULL);
686 g_list_free(p->plugins);
687 p->plugins = NULL;
8c44345a
HJYP
688
689 if( p->system_menu ){
690 do{
691 } while ( g_source_remove_by_user_data( p->system_menu ) );
692 }
693
a52c2257
HJYP
694 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), NoEventMask);
695 gdk_window_remove_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
696 gtk_widget_destroy(p->topgwin);
697 g_object_unref(fbev);
698 g_free(p->workarea);
a52c2257
HJYP
699 gdk_flush();
700 XFlush(GDK_DISPLAY());
701 XSync(GDK_DISPLAY(), True);
702 RET();
703}
704
705
706void
707usage()
708{
709 ENTER;
e7cb732b
HJYP
710 g_print(_("lxpanel %s - lightweight GTK2+ panel for UNIX desktops\n"), version);
711 g_print(_("Command line options:\n"));
712 g_print(_(" --help -- print this help and exit\n"));
713 g_print(_(" --version -- print version and exit\n"));
714 g_print(_(" --log <number> -- set log level 0-5. 0 - none 5 - chatty\n"));
715 g_print(_(" --configure -- launch configuration utility\n"));
716 g_print(_(" --profile name -- use specified profile\n"));
717 g_print("\n");
718 g_print(_(" -h -- same as --help\n"));
719 g_print(_(" -p -- same as --profile\n"));
720 g_print(_(" -v -- same as --version\n"));
721 g_print(_(" -C -- same as --configure\n"));
722 g_print(_("\nVisit http://lxpanel.sourceforge.net/ for detailed documentation,\n\n"));
a52c2257
HJYP
723}
724
db449f6e
HJYP
725char*
726load_profile(gchar *profile)
a52c2257
HJYP
727{
728 gchar *fname;
db449f6e 729 char* ret;
a52c2257
HJYP
730
731 ENTER;
732 LOG(LOG_INFO, "loading %s profile\n", profile);
733 fname = g_strdup_printf("%s/.lxpanel/%s", getenv("HOME"), profile);
db449f6e
HJYP
734 g_file_get_contents( fname, &ret, NULL, NULL );
735 if (ret) {
a52c2257 736 cfgfile = fname;
db449f6e 737 RET(ret);
a52c2257
HJYP
738 }
739 //ERR("Can't load %s\n", fname);
740 g_free(fname);
db449f6e 741
a52c2257
HJYP
742 /* check private configuration directory */
743 fname = g_strdup_printf(PACKAGE_DATA_DIR "/lxpanel/%s", profile);
db449f6e
HJYP
744 g_file_get_contents( fname, &ret, NULL, NULL );
745 if (ret) {
a52c2257 746 cfgfile = fname;
db449f6e 747 RET(ret);
a52c2257
HJYP
748 }
749 //ERR("Can't load %s\n", fname);
750 g_free(fname);
751 LOG(LOG_ERR, "Can't open '%s' profile\n", profile);
752 RET(NULL);
753}
754
755void
756handle_error(Display * d, XErrorEvent * ev)
757{
758 char buf[256];
759
760 ENTER;
761 if (log_level >= LOG_WARN) {
762 XGetErrorText(GDK_DISPLAY(), ev->error_code, buf, 256);
763 LOG(LOG_WARN, "lxpanel : X error: %s\n", buf);
764 }
765 RET();
766}
767
a52c2257
HJYP
768int
769main(int argc, char *argv[], char *env[])
770{
771 int i;
772 int quit = 0;
773 void configure();
db449f6e 774 char *fp, *pfp; /* point to current position of profile data in memory */
f277dbb7 775
a52c2257
HJYP
776 ENTER;
777 //printf("sizeof(gulong)=%d\n", sizeof(gulong));
778 setlocale(LC_CTYPE, "");
f277dbb7 779
a52c2257
HJYP
780 gtk_init(&argc, &argv);
781
782#ifdef ENABLE_NLS
783 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
784 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
785 textdomain ( GETTEXT_PACKAGE );
786#endif
787
788 XSetLocaleModifiers("");
789 XSetErrorHandler((XErrorHandler) handle_error);
790 resolve_atoms();
791 for (i = 1; i < argc; i++) {
792 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
793 usage();
794 exit(0);
795 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
796 printf("lxpanel %s\n", version);
797 exit(0);
798 } else if (!strcmp(argv[i], "--log")) {
799 i++;
800 if (i == argc) {
801 ERR( "lxpanel: missing log level\n");
802 usage();
803 exit(1);
804 } else {
805 log_level = atoi(argv[i]);
806 }
807 } else if (!strcmp(argv[i], "--configure") || !strcmp(argv[i], "-C")) {
808 config = 1;
809 } else if (!strcmp(argv[i], "--profile") || !strcmp(argv[i], "-p")) {
810 i++;
811 if (i == argc) {
812 ERR( "lxpanel: missing profile name\n");
813 usage();
814 exit(1);
815 } else {
816 cprofile = g_strdup(argv[i]);
817 }
818 } else {
819 printf("lxpanel: unknown option - %s\n", argv[i]);
820 usage();
821 exit(1);
822 }
823 }
f277dbb7
HJYP
824
825 /* Add our own icons to the search path of icon theme */
826 gtk_icon_theme_append_search_path( gtk_icon_theme_get_default(),
827 PACKAGE_DATA_DIR "/lxpanel/images" );
828
5541b8d2
JH
829 /* Enter main loop */
830 {
db449f6e 831 if (!(fp = pfp = load_profile(cprofile)))
a52c2257
HJYP
832 exit(1);
833 p = g_new0(panel, 1);
834 g_return_val_if_fail (p != NULL, 1);
db449f6e 835 if (!panel_start(p, &pfp)) {
a52c2257
HJYP
836 ERR( "lxpanel: can't start panel\n");
837 exit(1);
838 }
db449f6e 839 g_free( fp );
a52c2257
HJYP
840 if (config)
841 configure();
842 gtk_main();
843 panel_stop(p);
db449f6e 844 g_free( cfgfile );
a52c2257 845 g_free(p);
5541b8d2
JH
846 }
847
848 return 0;
a52c2257
HJYP
849}
850