GCC warning sweep and correct the C-style casting.
[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 ) {
5a343ad5
JH
490 GtkBox* newbox = GTK_BOX(recreate_box( GTK_BOX(p->box), p->orientation ));
491 if( GTK_WIDGET(newbox) != p->box ) {
492 p->box = GTK_WIDGET(newbox);
493 gtk_container_add( GTK_CONTAINER(p->bbox), GTK_WIDGET(newbox) );
a97d06a6
HJYP
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);
389975e0
HJYP
551 } else if( !g_ascii_strcasecmp(s.t[0], "LogoutCommand") ) {
552 p->logout_command = g_strdup( s.t[1] );
a52c2257
HJYP
553 } else {
554 ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
555 RET(0);
556 }
557 } else if (s.type == LINE_BLOCK_END) {
558 break;
559 } else {
560 ERR( "lxpanel: illegal in this context %s\n", s.str);
561 RET(0);
562 }
563 }
a97d06a6 564 panel_set_orientation( p );
a52c2257
HJYP
565 if (p->width < 0)
566 p->width = 100;
567 if (p->widthtype == WIDTH_PERCENT && p->width > 100)
568 p->width = 100;
569 p->heighttype = HEIGHT_PIXEL;
570 if (p->heighttype == HEIGHT_PIXEL) {
571 if (p->height < PANEL_HEIGHT_MIN)
572 p->height = PANEL_HEIGHT_MIN;
573 else if (p->height > PANEL_HEIGHT_MAX)
574 p->height = PANEL_HEIGHT_MAX;
575 }
576 p->curdesk = get_net_current_desktop();
577 p->desknum = get_net_number_of_desktops();
578 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
579 print_wmdata(p);
580 panel_start_gui(p);
581 RET(1);
582}
583
584static int
db449f6e 585panel_parse_plugin(panel *p, char **fp)
a52c2257
HJYP
586{
587 line s;
588 plugin *plug = NULL;
589 gchar *type = NULL;
a52c2257 590 int expand , padding, border;
db449f6e
HJYP
591 char* pconfig = NULL;
592
a52c2257
HJYP
593 ENTER;
594 s.len = 256;
a52c2257 595 border = expand = padding = 0;
c69ac68e 596 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
a52c2257
HJYP
597 if (s.type == LINE_NONE) {
598 ERR( "lxpanel: bad line %s\n", s.str);
599 goto error;
600 }
601 if (s.type == LINE_VAR) {
602 if (!g_ascii_strcasecmp(s.t[0], "type")) {
603 type = g_strdup(s.t[1]);
604 DBG("plug %s\n", type);
605 } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
606 expand = str2num(bool_pair, s.t[1], 0);
607 else if (!g_ascii_strcasecmp(s.t[0], "padding"))
608 padding = atoi(s.t[1]);
609 else if (!g_ascii_strcasecmp(s.t[0], "border"))
610 border = atoi(s.t[1]);
611 else {
612 ERR( "lxpanel: unknown var %s\n", s.t[0]);
613 goto error;
614 }
615 } else if (s.type == LINE_BLOCK_START) {
616 if (!g_ascii_strcasecmp(s.t[0], "Config")) {
db449f6e 617 pconfig = *fp;
a52c2257
HJYP
618 int pno = 1;
619 while (pno) {
620 get_line_as_is(fp, &s);
621 if (s.type == LINE_NONE) {
622 ERR( "lxpanel: unexpected eof\n");
623 goto error;
624 } else if (s.type == LINE_BLOCK_START) {
625 pno++;
626 } else if (s.type == LINE_BLOCK_END) {
627 pno--;
bee4c26e 628 }
db449f6e 629 }
a52c2257
HJYP
630 } else {
631 ERR( "lxpanel: unknown block %s\n", s.t[0]);
632 goto error;
633 }
634 } else {
635 ERR( "lxpanel: illegal in this context %s\n", s.str);
636 goto error;
637 }
638 }
db449f6e 639
a52c2257
HJYP
640 if (!type || !(plug = plugin_load(type))) {
641 ERR( "lxpanel: can't load %s plugin\n", type);
642 goto error;
643 }
db449f6e 644
a52c2257 645 plug->panel = p;
a52c2257
HJYP
646 plug->expand = expand;
647 plug->padding = padding;
648 plug->border = border;
a52c2257 649 DBG("starting\n");
db449f6e 650 if (!plugin_start(plug, pconfig ? &pconfig : NULL)) {
a52c2257
HJYP
651 ERR( "lxpanel: can't start plugin %s\n", type);
652 goto error;
653 }
654 DBG("plug %s\n", type);
655 p->plugins = g_list_append(p->plugins, plug);
0dcb6bf5
HJYP
656
657 g_free( type );
a52c2257 658 RET(1);
db449f6e 659
a52c2257 660 error:
a52c2257
HJYP
661 g_free(type);
662 if (plug)
663 plugin_put(plug);
664 RET(0);
a52c2257
HJYP
665}
666
667
668int
db449f6e 669panel_start( panel *p, char **fp )
a52c2257
HJYP
670{
671 line s;
db449f6e 672
a52c2257
HJYP
673 /* parse global section */
674 ENTER;
675 s.len = 256;
676 memset(p, 0, sizeof(panel));
677 p->allign = ALLIGN_CENTER;
678 p->edge = EDGE_BOTTOM;
679 p->widthtype = WIDTH_PERCENT;
680 p->width = 100;
681 p->heighttype = HEIGHT_PIXEL;
682 p->height = PANEL_HEIGHT_DEFAULT;
683 p->setdocktype = 1;
684 p->setstrut = 1;
685 p->round_corners = 0;
686 p->transparent = 0;
687 p->alpha = 127;
688 p->tintcolor = 0xFFFFFFFF;
689 p->spacing = 0;
690 fbev = fb_ev_new();
c69ac68e 691 if ((lxpanel_get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
a52c2257
HJYP
692 ERR( "lxpanel: config file must start from Global section\n");
693 RET(0);
694 }
695 if (!panel_parse_global(p, fp))
696 RET(0);
697
c69ac68e 698 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
699 if ((s.type != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
700 ERR( "lxpanel: expecting Plugin section\n");
701 RET(0);
702 }
bee4c26e 703 if (!panel_parse_plugin(p, fp))
a52c2257
HJYP
704 RET(0);
705 }
706 gtk_widget_show_all(p->topgwin);
707 print_wmdata(p);
708 RET(1);
709}
710
711static void
712delete_plugin(gpointer data, gpointer udata)
713{
714 ENTER;
715 plugin_stop((plugin *)data);
716 plugin_put((plugin *)data);
717 RET();
a52c2257
HJYP
718}
719
720void panel_stop(panel *p)
721{
722 ENTER;
723
724 g_list_foreach(p->plugins, delete_plugin, NULL);
725 g_list_free(p->plugins);
726 p->plugins = NULL;
8c44345a
HJYP
727
728 if( p->system_menu ){
729 do{
730 } while ( g_source_remove_by_user_data( p->system_menu ) );
731 }
732
a52c2257
HJYP
733 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), NoEventMask);
734 gdk_window_remove_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
735 gtk_widget_destroy(p->topgwin);
736 g_object_unref(fbev);
737 g_free(p->workarea);
389975e0 738 g_free( p->logout_command );
a52c2257
HJYP
739 gdk_flush();
740 XFlush(GDK_DISPLAY());
741 XSync(GDK_DISPLAY(), True);
742 RET();
743}
744
745
746void
747usage()
748{
749 ENTER;
e7cb732b
HJYP
750 g_print(_("lxpanel %s - lightweight GTK2+ panel for UNIX desktops\n"), version);
751 g_print(_("Command line options:\n"));
752 g_print(_(" --help -- print this help and exit\n"));
753 g_print(_(" --version -- print version and exit\n"));
754 g_print(_(" --log <number> -- set log level 0-5. 0 - none 5 - chatty\n"));
755 g_print(_(" --configure -- launch configuration utility\n"));
756 g_print(_(" --profile name -- use specified profile\n"));
757 g_print("\n");
758 g_print(_(" -h -- same as --help\n"));
759 g_print(_(" -p -- same as --profile\n"));
760 g_print(_(" -v -- same as --version\n"));
761 g_print(_(" -C -- same as --configure\n"));
762 g_print(_("\nVisit http://lxpanel.sourceforge.net/ for detailed documentation,\n\n"));
a52c2257
HJYP
763}
764
db449f6e
HJYP
765char*
766load_profile(gchar *profile)
a52c2257
HJYP
767{
768 gchar *fname;
db449f6e 769 char* ret;
a52c2257
HJYP
770
771 ENTER;
772 LOG(LOG_INFO, "loading %s profile\n", profile);
773 fname = g_strdup_printf("%s/.lxpanel/%s", getenv("HOME"), profile);
db449f6e
HJYP
774 g_file_get_contents( fname, &ret, NULL, NULL );
775 if (ret) {
a52c2257 776 cfgfile = fname;
db449f6e 777 RET(ret);
a52c2257
HJYP
778 }
779 //ERR("Can't load %s\n", fname);
780 g_free(fname);
db449f6e 781
a52c2257
HJYP
782 /* check private configuration directory */
783 fname = g_strdup_printf(PACKAGE_DATA_DIR "/lxpanel/%s", profile);
db449f6e
HJYP
784 g_file_get_contents( fname, &ret, NULL, NULL );
785 if (ret) {
a52c2257 786 cfgfile = fname;
db449f6e 787 RET(ret);
a52c2257
HJYP
788 }
789 //ERR("Can't load %s\n", fname);
790 g_free(fname);
791 LOG(LOG_ERR, "Can't open '%s' profile\n", profile);
792 RET(NULL);
793}
794
795void
796handle_error(Display * d, XErrorEvent * ev)
797{
798 char buf[256];
799
800 ENTER;
801 if (log_level >= LOG_WARN) {
802 XGetErrorText(GDK_DISPLAY(), ev->error_code, buf, 256);
803 LOG(LOG_WARN, "lxpanel : X error: %s\n", buf);
804 }
805 RET();
806}
807
a52c2257
HJYP
808int
809main(int argc, char *argv[], char *env[])
810{
811 int i;
a52c2257 812 void configure();
db449f6e 813 char *fp, *pfp; /* point to current position of profile data in memory */
f277dbb7 814
a52c2257
HJYP
815 ENTER;
816 //printf("sizeof(gulong)=%d\n", sizeof(gulong));
817 setlocale(LC_CTYPE, "");
f277dbb7 818
a52c2257
HJYP
819 gtk_init(&argc, &argv);
820
821#ifdef ENABLE_NLS
822 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
823 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
824 textdomain ( GETTEXT_PACKAGE );
825#endif
826
827 XSetLocaleModifiers("");
828 XSetErrorHandler((XErrorHandler) handle_error);
829 resolve_atoms();
830 for (i = 1; i < argc; i++) {
831 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
832 usage();
833 exit(0);
834 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
835 printf("lxpanel %s\n", version);
836 exit(0);
837 } else if (!strcmp(argv[i], "--log")) {
838 i++;
839 if (i == argc) {
840 ERR( "lxpanel: missing log level\n");
841 usage();
842 exit(1);
843 } else {
844 log_level = atoi(argv[i]);
845 }
846 } else if (!strcmp(argv[i], "--configure") || !strcmp(argv[i], "-C")) {
847 config = 1;
848 } else if (!strcmp(argv[i], "--profile") || !strcmp(argv[i], "-p")) {
849 i++;
850 if (i == argc) {
851 ERR( "lxpanel: missing profile name\n");
852 usage();
853 exit(1);
854 } else {
855 cprofile = g_strdup(argv[i]);
856 }
857 } else {
858 printf("lxpanel: unknown option - %s\n", argv[i]);
859 usage();
860 exit(1);
861 }
862 }
f277dbb7
HJYP
863
864 /* Add our own icons to the search path of icon theme */
865 gtk_icon_theme_append_search_path( gtk_icon_theme_get_default(),
866 PACKAGE_DATA_DIR "/lxpanel/images" );
867
5541b8d2
JH
868 /* Enter main loop */
869 {
db449f6e 870 if (!(fp = pfp = load_profile(cprofile)))
a52c2257
HJYP
871 exit(1);
872 p = g_new0(panel, 1);
873 g_return_val_if_fail (p != NULL, 1);
db449f6e 874 if (!panel_start(p, &pfp)) {
a52c2257
HJYP
875 ERR( "lxpanel: can't start panel\n");
876 exit(1);
877 }
db449f6e 878 g_free( fp );
a52c2257
HJYP
879 if (config)
880 configure();
881 gtk_main();
882 panel_stop(p);
db449f6e 883 g_free( cfgfile );
a52c2257 884 g_free(p);
5541b8d2
JH
885 }
886
887 return 0;
a52c2257
HJYP
888}
889