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