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