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