Enable removing panel plugin and remove the panel via popup menu.
[lxde/lxpanel.git] / src / panel.c
CommitLineData
16fb8c2e 1/**
e68b47dc
JH
2 * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
a52c2257 19#ifdef HAVE_CONFIG_H
cf701cb7 20#include <config.h>
a52c2257
HJYP
21#endif
22
cf701cb7 23#include <glib/gi18n.h>
a52c2257
HJYP
24#include <stdlib.h>
25#include <stdio.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29#include <errno.h>
30#include <locale.h>
31#include <string.h>
e68b47dc 32#include <gdk/gdkx.h>
a52c2257
HJYP
33
34#include "plugin.h"
35#include "panel.h"
36#include "misc.h"
37#include "bg.h"
a52c2257 38
8110399f 39#include "glib-mem.h"
77886b88 40#include "lxpanelctl.h"
cf701cb7 41#include "dbg.h"
77886b88 42
a52c2257
HJYP
43static gchar *cfgfile = NULL;
44static gchar version[] = VERSION;
45gchar *cprofile = "default";
46
e68b47dc 47static int config = 0;
22242ed4 48FbEv *fbev = NULL;
a52c2257 49
a52c2257 50int log_level;
8110399f 51
cf701cb7 52GSList* all_panels = NULL; /* a single-linked list storing all panels */
a52c2257 53
f7cb330e
HJYP
54gboolean is_restarting = FALSE;
55
a52c2257
HJYP
56/****************************************************
57 * panel's handlers for WM events *
58 ****************************************************/
59/*
60static void
22242ed4 61panel_del_wm_strut(Panel *p)
a52c2257
HJYP
62{
63 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT);
64 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL);
65}
66*/
67
68
22242ed4 69void panel_set_wm_strut(Panel *p)
a52c2257
HJYP
70{
71 gulong data[12] = { 0 };
72 int i = 4;
73
a52c2257
HJYP
74 if (!GTK_WIDGET_MAPPED (p->topgwin))
75 return;
bee4c26e
HJYP
76 if ( ! p->setstrut )
77 {
78 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL);
79 /* old spec, for wms that do not support STRUT_PARTIAL */
80 XDeleteProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT);
81 return;
82 }
83
a52c2257
HJYP
84 switch (p->edge) {
85 case EDGE_LEFT:
86 i = 0;
87 data[i] = p->aw;
88 data[4 + i*2] = p->ay;
89 data[5 + i*2] = p->ay + p->ah;
90 break;
91 case EDGE_RIGHT:
92 i = 1;
93 data[i] = p->aw;
94 data[4 + i*2] = p->ay;
95 data[5 + i*2] = p->ay + p->ah;
96 break;
97 case EDGE_TOP:
98 i = 2;
99 data[i] = p->ah;
100 data[4 + i*2] = p->ax;
101 data[5 + i*2] = p->ax + p->aw;
102 break;
103 case EDGE_BOTTOM:
104 i = 3;
105 data[i] = p->ah;
106 data[4 + i*2] = p->ax;
107 data[5 + i*2] = p->ax + p->aw;
108 break;
109 default:
110 ERR("wrong edge %d. strut won't be set\n", p->edge);
111 RET();
bee4c26e 112 }
a52c2257 113 DBG("type %d. width %d. from %d to %d\n", i, data[i], data[4 + i*2], data[5 + i*2]);
bee4c26e 114
a52c2257 115 /* if wm supports STRUT_PARTIAL it will ignore STRUT */
bee4c26e 116 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT_PARTIAL,
a52c2257
HJYP
117 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 12);
118 /* old spec, for wms that do not support STRUT_PARTIAL */
bee4c26e
HJYP
119 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STRUT,
120 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, 4);
a52c2257
HJYP
121
122 RET();
123}
124
125static void
22242ed4 126print_wmdata(Panel *p)
a52c2257
HJYP
127{
128 int i;
129
a52c2257
HJYP
130 RET();
131 DBG("desktop %d/%d\n", p->curdesk, p->desknum);
132 DBG("workarea\n");
133 for (i = 0; i < p->wa_len/4; i++)
134 DBG("(%d, %d) x (%d, %d)\n",
135 p->workarea[4*i + 0],
136 p->workarea[4*i + 1],
137 p->workarea[4*i + 2],
138 p->workarea[4*i + 3]);
139 RET();
140}
141
142
e996608e 143/* defined in plugins/menu.c */
8c44345a 144gboolean show_system_menu( gpointer system_menu );
e996608e
HJYP
145
146/* built-in commands, defined in configurator.c */
8110399f 147void configure(Panel* p);
77886b88
HJYP
148void restart(void);
149void gtk_run(void);
150
22242ed4 151static void process_client_msg ( Panel *p, XClientMessageEvent* ev )
77886b88 152{
8c44345a 153 int cmd = ev->data.b[0];
77886b88
HJYP
154 switch( cmd )
155 {
156 case LXPANEL_CMD_SYS_MENU:
5297da29 157 if( p->system_menus )
8c44345a 158 {
5297da29 159 /* show_system_menu( p->system_menus->data ); */
8c44345a
HJYP
160 /* FIXME: I've no idea why this doesn't work without timeout
161 under some WMs, like icewm. */
5297da29
HJYP
162 g_timeout_add( 200, (GSourceFunc)show_system_menu,
163 p->system_menus->data );
8c44345a 164 }
77886b88
HJYP
165 break;
166 case LXPANEL_CMD_RUN:
167 gtk_run();
168 break;
169 case LXPANEL_CMD_CONFIG:
8110399f 170 //FIXME: configure();
77886b88
HJYP
171 break;
172 case LXPANEL_CMD_RESTART:
173 restart();
174 break;
175 case LXPANEL_CMD_EXIT:
176 gtk_main_quit();
177 break;
178 }
179}
180
a52c2257 181static GdkFilterReturn
cf701cb7 182panel_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer not_used)
a52c2257
HJYP
183{
184 Atom at;
185 Window win;
186 XEvent *ev = (XEvent *) xevent;
187
188 ENTER;
189 DBG("win = 0x%x\n", ev->xproperty.window);
77886b88
HJYP
190 if (ev->type != PropertyNotify ) {
191 /* private client message from lxpanelctl */
192 if( ev->type == ClientMessage && ev->xproperty.atom == a_LXPANEL_CMD )
193 {
cf701cb7 194 g_slist_foreach( all_panels, (GFunc)process_client_msg, (XClientMessageEvent*)ev );
77886b88 195 }
22242ed4
HJYP
196 else if( ev->type == DestroyNotify )
197 {
cf701cb7 198 fb_ev_emit_destroy( fbev, ((XDestroyWindowEvent*)ev)->window );
22242ed4 199 }
a52c2257 200 RET(GDK_FILTER_CONTINUE);
24053345 201 }
77886b88 202
a52c2257
HJYP
203 at = ev->xproperty.atom;
204 win = ev->xproperty.window;
a52c2257 205 if (win == GDK_ROOT_WINDOW()) {
cf701cb7
HJYP
206 if (at == a_NET_CLIENT_LIST) {
207 fb_ev_emit(fbev, EV_CLIENT_LIST);
208 } else if (at == a_NET_CURRENT_DESKTOP) {
209 GSList* l;
210 for( l = all_panels; l; l = l->next )
211 ((Panel*)l->data)->curdesk = get_net_current_desktop();
22242ed4 212 fb_ev_emit(fbev, EV_CURRENT_DESKTOP);
cf701cb7
HJYP
213 } else if (at == a_NET_NUMBER_OF_DESKTOPS) {
214 GSList* l;
215 for( l = all_panels; l; l = l->next )
216 ((Panel*)l->data)->desknum = get_net_number_of_desktops();
22242ed4 217 fb_ev_emit(fbev, EV_NUMBER_OF_DESKTOPS);
cf701cb7 218 } else if (at == a_NET_DESKTOP_NAMES) {
22242ed4 219 fb_ev_emit(fbev, EV_DESKTOP_NAMES);
a52c2257 220 } else if (at == a_NET_ACTIVE_WINDOW) {
22242ed4 221 fb_ev_emit(fbev, EV_ACTIVE_WINDOW );
cf701cb7 222 } else if (at == a_NET_CLIENT_LIST_STACKING) {
22242ed4 223 fb_ev_emit(fbev, EV_CLIENT_LIST_STACKING);
a52c2257 224 } else if (at == a_XROOTPMAP_ID) {
cf701cb7
HJYP
225 GSList* l;
226 for( l = all_panels; l; l = l->next )
227 {
228 Panel* p = (Panel*)l->data;
229 if (p->transparent) {
230 fb_bg_notify_changed_bg(p->bg);
231 }
232 }
233 } else if (at == a_NET_WORKAREA) {
234 GSList* l;
235 for( l = all_panels; l; l = l->next )
236 {
237 Panel* p = (Panel*)l->data;
238 g_free( p->workarea );
239 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
240 print_wmdata(p);
a52c2257 241 }
a52c2257 242 } else
cf701cb7
HJYP
243 return GDK_FILTER_CONTINUE;
244
245 return GDK_FILTER_REMOVE;
a52c2257 246 }
cf701cb7 247 return GDK_FILTER_CONTINUE;
a52c2257
HJYP
248}
249
250/****************************************************
251 * panel's handlers for GTK events *
252 ****************************************************/
253
bee4c26e 254
a52c2257
HJYP
255static gint
256panel_delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
257{
258 ENTER;
259 RET(FALSE);
260}
261
262static gint
263panel_destroy_event(GtkWidget * widget, GdkEvent * event, gpointer data)
264{
22242ed4 265 //Panel *p = (Panel *) data;
a52c2257
HJYP
266 //if (!p->self_destroy)
267 gtk_main_quit();
268 RET(FALSE);
269}
270
4542c20d 271static void
22242ed4 272on_root_bg_changed(FbBg *bg, Panel* p)
4542c20d
HJYP
273{
274 panel_update_background( p );
275}
276
277/* This function should only be called after the panel has been realized */
22242ed4 278void panel_update_background( Panel* p )
4542c20d
HJYP
279{
280 GList* l;
281 GdkPixmap* pixmap = NULL;
282
283 /* handle background image of panel */
284 gtk_widget_set_app_paintable(p->topgwin, TRUE);
285
286 if (p->background) {
287 pixmap = fb_bg_get_pix_from_file(p->topgwin, p->background_file);
288 if( p->bg )
289 {
290 g_object_unref( p->bg );
291 p->bg = NULL;
292 }
293 } else if (p->transparent) {
294 if( ! p->bg )
295 {
296 p->bg = fb_bg_get_for_display();
297 g_signal_connect(G_OBJECT(p->bg), "changed", G_CALLBACK(on_root_bg_changed), p);
298 }
299 pixmap = fb_bg_get_xroot_pix_for_win( p->bg, p->topgwin );
300
301 if (pixmap && pixmap != GDK_NO_BG) {
302 if (p->alpha)
303 fb_bg_composite( pixmap, p->topgwin->style->black_gc, p->tintcolor, p->alpha );
304 }
305 }
306 else
307 {
308 if( p->bg )
309 {
310 g_object_unref( p->bg );
311 p->bg = NULL;
312 }
313 }
314
315 if( pixmap )
316 {
317 gtk_widget_set_app_paintable( p->topgwin, TRUE );
318 gdk_window_set_back_pixmap( p->topgwin->window, pixmap, FALSE );
319 g_object_unref( pixmap );
320 }
321 else
322 {
323// gdk_window_set_back_pixmap( p->topgwin->window, p->topgwin->style->bg_pixmap[0], FALSE );
324 gtk_widget_set_app_paintable( p->topgwin, FALSE );
325// gdk_window_set_background( p->topgwin->window, &p->topgwin->style->bg[0] );
326 }
327
328 for( l = p->plugins; l; l = l->next )
329 {
22242ed4 330 Plugin* pl = (Plugin*)l->data;
4542c20d
HJYP
331 plugin_set_background( pl, p );
332 }
333
334 gdk_window_clear( p->topgwin->window );
335 gtk_widget_queue_draw( p->topgwin );
336}
a52c2257 337
84fc1d55 338/*
a52c2257 339static void
22242ed4 340panel_realize(GtkWidget *widget, Panel *p)
a52c2257 341{
a52c2257
HJYP
342
343}
84fc1d55
HJYP
344*/
345
346static gboolean delay_update_background( Panel* p )
347{
cf701cb7
HJYP
348 panel_update_background( p );
349 return FALSE;
84fc1d55
HJYP
350}
351
352static void
353panel_style_set(GtkWidget *widget, GtkStyle* prev, Panel *p)
354{
cf701cb7
HJYP
355 if( GTK_WIDGET_REALIZED( widget ) )
356 g_idle_add( delay_update_background, p );
84fc1d55 357}
4542c20d 358
a52c2257 359static gint
22242ed4 360panel_size_req(GtkWidget *widget, GtkRequisition *req, Panel *p)
a52c2257
HJYP
361{
362 ENTER;
4542c20d 363
a52c2257
HJYP
364 if (p->widthtype == WIDTH_REQUEST)
365 p->width = (p->orientation == ORIENT_HORIZ) ? req->width : req->height;
366 if (p->heighttype == HEIGHT_REQUEST)
367 p->height = (p->orientation == ORIENT_HORIZ) ? req->height : req->width;
368 calculate_position(p);
369 req->width = p->aw;
370 req->height = p->ah;
4542c20d 371
a52c2257
HJYP
372 RET( TRUE );
373}
374
375static gint
22242ed4 376panel_size_alloc(GtkWidget *widget, GtkAllocation *a, Panel *p)
a52c2257
HJYP
377{
378 ENTER;
a52c2257
HJYP
379 if (p->widthtype == WIDTH_REQUEST)
380 p->width = (p->orientation == ORIENT_HORIZ) ? a->width : a->height;
381 if (p->heighttype == HEIGHT_REQUEST)
382 p->height = (p->orientation == ORIENT_HORIZ) ? a->height : a->width;
383 calculate_position(p);
4542c20d 384
a52c2257 385 if (a->width == p->aw && a->height == p->ah && a->x == p->ax && a->y == p ->ay) {
a52c2257
HJYP
386 RET(TRUE);
387 }
388
389 gtk_window_move(GTK_WINDOW(p->topgwin), p->ax, p->ay);
bee4c26e 390 panel_set_wm_strut(p);
a52c2257
HJYP
391 RET(TRUE);
392}
393
a52c2257 394static gboolean
22242ed4 395panel_configure_event (GtkWidget *widget, GdkEventConfigure *e, Panel *p)
a52c2257
HJYP
396{
397 ENTER;
398 if (e->width == p->cw && e->height == p->ch && e->x == p->cx && e->y == p->cy)
399 RET(TRUE);
400 p->cw = e->width;
401 p->ch = e->height;
402 p->cx = e->x;
403 p->cy = e->y;
4542c20d 404
a52c2257
HJYP
405 if (p->transparent)
406 fb_bg_notify_changed_bg(p->bg);
bee4c26e 407
4542c20d 408 RET(FALSE);
a52c2257
HJYP
409}
410
fddae119
FC
411static gint
412panel_popupmenu_configure(GtkWidget *widget, gpointer user_data)
413{
414 ENTER;
8110399f 415 configure( (Panel*)user_data );
fddae119
FC
416 RET(TRUE);
417}
418
419static gint
420panel_press_button_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
421{
422 GdkEventButton *event_button;
cf701cb7 423 GtkWidget* img;
fddae119
FC
424
425 g_return_val_if_fail (event != NULL, FALSE);
426 event_button = (GdkEventButton *)event;
427 if (event_button->button == 3) {
428 GtkWidget *menu;
cf701cb7 429 Panel* panel = (Panel*)user_data;
fddae119 430 /* create menu */
cf701cb7 431 menu = lxpanel_get_panel_menu( panel, panel->plugins->next->next->data, TRUE );
fddae119
FC
432 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time);
433 return TRUE;
434 }
435
436 return FALSE;
437}
438
cf701cb7
HJYP
439static void panel_popupmenu_config_plugin( GtkMenuItem* item, Plugin* plugin )
440{
441 plugin->class->config( plugin, plugin->panel->topgwin );
442}
443
444static void panel_popupmenu_add_item( GtkMenuItem* item, Panel* panel )
445{
446
447}
448
449static void panel_popupmenu_remove_item( GtkMenuItem* item, Plugin* plugin )
450{
451 Panel* panel = plugin->panel;
452 panel->plugins = g_list_remove( panel->plugins, plugin );
453 plugin_stop( plugin ); /* free the plugin widget & its data */
454 plugin_put( plugin ); /* free the lib if necessary */
455}
456
457static void panel_popupmenu_create_panel( GtkMenuItem* item, Panel* panel )
458{
459
460}
461
462static void panel_popupmenu_delete_panel( GtkMenuItem* item, Panel* panel )
463{
464 GtkWidget* dlg;
465 gboolean ok;
466 dlg = gtk_message_dialog_new_with_markup( panel->topgwin,
467 GTK_DIALOG_MODAL,
468 GTK_MESSAGE_QUESTION,
469 GTK_BUTTONS_OK_CANCEL,
470 _("Really delete this panel?\n<b>Warning: This can not be recovered.</b>") );
471 gtk_window_set_title( (GtkWindow*)dlg, _("Confirm") );
472 ok = ( gtk_dialog_run( (GtkDialog*)dlg ) == GTK_RESPONSE_OK );
473 gtk_widget_destroy( dlg );
474 if( ok )
475 {
476 all_panels = g_slist_remove( all_panels, panel );
477 panel_destroy( panel );
478 }
479}
480
481extern GtkWidget* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_menu )
482{
483 GtkWidget *ret,*menu, *menu_item, *img;
484 char* tmp;
485 ret = menu = gtk_menu_new();
486
487 if( plugin )
488 {
489 img = gtk_image_new_from_stock( GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU );
490 tmp = g_strdup_printf( _("\"%s\" Settings"), _(plugin->class->name) );
491 menu_item = gtk_image_menu_item_new_with_label( tmp );
492 g_free( tmp );
493 gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
494 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
495 if( plugin->class->config )
496 g_signal_connect( menu_item, "activate", G_CALLBACK(panel_popupmenu_config_plugin), plugin );
497 else
498 gtk_widget_set_sensitive( menu_item, FALSE );
499
500 menu_item = gtk_separator_menu_item_new();
501 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
502 }
503
504 img = gtk_image_new_from_stock( GTK_STOCK_ADD, GTK_ICON_SIZE_MENU );
505 menu_item = gtk_image_menu_item_new_with_label(_("Add Item To Panel"));
506 gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
507 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
508 g_signal_connect( menu_item, "activate", G_CALLBACK(panel_popupmenu_add_item), panel );
509
510 if( plugin )
511 {
512 img = gtk_image_new_from_stock( GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU );
513 tmp = g_strdup_printf( _("Remove \"%s\" From Panel"), _(plugin->class->name) );
514 menu_item = gtk_image_menu_item_new_with_label( tmp );
515 g_free( tmp );
516 gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
517 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
518 g_signal_connect( menu_item, "activate", G_CALLBACK(panel_popupmenu_remove_item), plugin );
519 }
520
521 menu_item = gtk_separator_menu_item_new();
522 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
523
524 img = gtk_image_new_from_stock( GTK_STOCK_NEW, GTK_ICON_SIZE_MENU );
525 menu_item = gtk_image_menu_item_new_with_label(_("Create New Panel"));
526 gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
527 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
528 g_signal_connect( menu_item, "activate", G_CALLBACK(panel_popupmenu_create_panel), panel );
529
530 img = gtk_image_new_from_stock( GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU );
531 menu_item = gtk_image_menu_item_new_with_label(_("Delete This Panel"));
532 gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
533 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
534 g_signal_connect( menu_item, "activate", G_CALLBACK(panel_popupmenu_delete_panel), panel );
535 if( ! all_panels->next ) /* if this is the only panel */
536 gtk_widget_set_sensitive( menu_item, FALSE );
537
538 menu_item = gtk_separator_menu_item_new();
539 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
540
541 img = gtk_image_new_from_stock( GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU );
542 menu_item = gtk_image_menu_item_new_with_label(_("Panel Settings"));
543 gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
544 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
545 g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(panel_popupmenu_configure), panel );
546
547 gtk_widget_show_all(menu);
548
549 if( use_sub_menu )
550 {
551 ret = gtk_menu_new();
552 menu_item = gtk_image_menu_item_new_with_label(_("Panel"));
553 gtk_menu_shell_append(GTK_MENU_SHELL(ret), menu_item);
554 gtk_menu_item_set_submenu( menu_item, menu );
555
556 gtk_widget_show_all(ret);
557 }
558
559 g_signal_connect( ret, "selection-done", G_CALLBACK(gtk_widget_destroy), NULL );
560 return ret;
561}
562
fddae119 563
a52c2257
HJYP
564
565/****************************************************
566 * panel creation *
567 ****************************************************/
568static void
22242ed4 569make_round_corners(Panel *p)
a52c2257 570{
a97d06a6 571 /* FIXME: This should be re-written with shape extension of X11 */
4542c20d 572 /* gdk_window_shape_combine_mask() can be used */
bee4c26e
HJYP
573}
574
22242ed4 575void panel_set_dock_type(Panel *p)
bee4c26e
HJYP
576{
577 if (p->setdocktype) {
578 Atom state = a_NET_WM_WINDOW_TYPE_DOCK;
579 XChangeProperty(GDK_DISPLAY(), p->topxwin,
580 a_NET_WM_WINDOW_TYPE, XA_ATOM, 32,
581 PropModeReplace, (unsigned char *) &state, 1);
582 }
583 else {
584 XDeleteProperty( GDK_DISPLAY(), p->topxwin, a_NET_WM_WINDOW_TYPE );
585 }
a52c2257
HJYP
586}
587
0defe4b9 588static void
22242ed4 589panel_start_gui(Panel *p)
a52c2257
HJYP
590{
591 Atom state[3];
592 XWMHints wmhints;
593 guint32 val;
6db11841 594
a52c2257
HJYP
595 ENTER;
596
597 // main toplevel window
598 p->topgwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
599 gtk_container_set_border_width(GTK_CONTAINER(p->topgwin), 0);
600 gtk_window_set_resizable(GTK_WINDOW(p->topgwin), FALSE);
601 gtk_window_set_wmclass(GTK_WINDOW(p->topgwin), "panel", "lxpanel");
602 gtk_window_set_title(GTK_WINDOW(p->topgwin), "panel");
603 gtk_window_set_position(GTK_WINDOW(p->topgwin), GTK_WIN_POS_NONE);
604 gtk_window_set_decorated(GTK_WINDOW(p->topgwin), FALSE);
77886b88 605
a52c2257
HJYP
606 g_signal_connect(G_OBJECT(p->topgwin), "delete-event",
607 G_CALLBACK(panel_delete_event), p);
608 g_signal_connect(G_OBJECT(p->topgwin), "destroy-event",
609 G_CALLBACK(panel_destroy_event), p);
610 g_signal_connect (G_OBJECT (p->topgwin), "size-request",
611 (GCallback) panel_size_req, p);
612 g_signal_connect (G_OBJECT (p->topgwin), "size-allocate",
613 (GCallback) panel_size_alloc, p);
614 g_signal_connect (G_OBJECT (p->topgwin), "configure-event",
615 (GCallback) panel_configure_event, p);
fddae119 616 g_signal_connect(G_OBJECT (p->topgwin), "button_press_event",
8110399f 617 (GCallback) panel_press_button_event, p);
84fc1d55 618/*
a52c2257
HJYP
619 g_signal_connect (G_OBJECT (p->topgwin), "realize",
620 (GCallback) panel_realize, p);
84fc1d55
HJYP
621*/
622 g_signal_connect (G_OBJECT (p->topgwin), "style-set",
623 (GCallback)panel_style_set, p);
a52c2257
HJYP
624 gtk_widget_realize(p->topgwin);
625 //gdk_window_set_decorations(p->topgwin->window, 0);
2de71c90 626
4542c20d 627 // main layout manager as a single child of panel
a97d06a6 628 p->box = p->my_box_new(FALSE, 0);
a52c2257 629 gtk_container_set_border_width(GTK_CONTAINER(p->box), 0);
4542c20d
HJYP
630// gtk_container_add(GTK_CONTAINER(p->bbox), p->box);
631 gtk_container_add(GTK_CONTAINER(p->topgwin), p->box);
a52c2257 632 gtk_widget_show(p->box);
a97d06a6
HJYP
633 if (p->round_corners)
634 make_round_corners(p);
6db11841 635
a52c2257
HJYP
636 p->topxwin = GDK_WINDOW_XWINDOW(GTK_WIDGET(p->topgwin)->window);
637 DBG("topxwin = %x\n", p->topxwin);
638
639 /* the settings that should be done before window is mapped */
640 wmhints.flags = InputHint;
641 wmhints.input = 0;
bee4c26e 642 XSetWMHints (GDK_DISPLAY(), p->topxwin, &wmhints);
24053345 643#define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
a52c2257
HJYP
644 val = WIN_HINTS_SKIP_FOCUS;
645 XChangeProperty(GDK_DISPLAY(), p->topxwin,
646 XInternAtom(GDK_DISPLAY(), "_WIN_HINTS", False), XA_CARDINAL, 32,
647 PropModeReplace, (unsigned char *) &val, 1);
648
bee4c26e 649 panel_set_dock_type(p);
a52c2257
HJYP
650
651 /* window mapping point */
652 gtk_widget_show_all(p->topgwin);
653
654 /* the settings that should be done after window is mapped */
655
656 /* send it to running wm */
657 Xclimsg(p->topxwin, a_NET_WM_DESKTOP, 0xFFFFFFFF, 0, 0, 0, 0);
658 /* and assign it ourself just for case when wm is not running */
659 val = 0xFFFFFFFF;
660 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_DESKTOP, XA_CARDINAL, 32,
661 PropModeReplace, (unsigned char *) &val, 1);
662
663 state[0] = a_NET_WM_STATE_SKIP_PAGER;
664 state[1] = a_NET_WM_STATE_SKIP_TASKBAR;
665 state[2] = a_NET_WM_STATE_STICKY;
666 XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STATE, XA_ATOM,
667 32, PropModeReplace, (unsigned char *) state, 3);
668
a52c2257
HJYP
669 calculate_position(p);
670 gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
bee4c26e 671 panel_set_wm_strut(p);
77886b88 672
239cb032
HJYP
673 p->tooltips = gtk_tooltips_new();
674#if GLIB_CHECK_VERSION( 2, 10, 0 )
675 g_object_ref_sink( p->tooltips );
676#else
677 g_object_ref( p->tooltips );
678 gtk_object_sink( p->tooltips );
679#endif
680
a52c2257
HJYP
681 RET();
682}
683
22242ed4 684void panel_set_orientation(Panel *p)
a97d06a6
HJYP
685{
686 GList* l;
687 p->orientation = (p->edge == EDGE_TOP || p->edge == EDGE_BOTTOM)
688 ? ORIENT_HORIZ : ORIENT_VERT;
689 if (p->orientation == ORIENT_HORIZ) {
690 p->my_box_new = gtk_hbox_new;
691 p->my_separator_new = gtk_vseparator_new;
692 } else {
693 p->my_box_new = gtk_vbox_new;
694 p->my_separator_new = gtk_hseparator_new;
695 }
696
697 /* recreate the main layout box */
698 if( p->box ) {
5a343ad5
JH
699 GtkBox* newbox = GTK_BOX(recreate_box( GTK_BOX(p->box), p->orientation ));
700 if( GTK_WIDGET(newbox) != p->box ) {
701 p->box = GTK_WIDGET(newbox);
4542c20d 702 gtk_container_add( GTK_CONTAINER(p->topgwin), GTK_WIDGET(newbox) );
a97d06a6
HJYP
703 }
704 }
705 /* NOTE: This loop won't be executed when panel started since
706 plugins are not loaded at that time.
707 This is used when the orientation of the panel is changed
708 from the config dialog, and plugins should be re-layout.
709 */
710 for( l = p->plugins; l; l = l->next ) {
22242ed4 711 Plugin* pl = (Plugin*)l->data;
a97d06a6
HJYP
712 if( pl->class->orientation ) {
713 pl->class->orientation( pl );
714 }
715 }
716}
717
a52c2257 718static int
22242ed4 719panel_parse_global(Panel *p, char **fp)
a52c2257
HJYP
720{
721 line s;
722 s.len = 256;
6db11841 723
a52c2257 724 ENTER;
c69ac68e 725 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
726 if (s.type == LINE_VAR) {
727 if (!g_ascii_strcasecmp(s.t[0], "edge")) {
728 p->edge = str2num(edge_pair, s.t[1], EDGE_NONE);
729 } else if (!g_ascii_strcasecmp(s.t[0], "allign")) {
730 p->allign = str2num(allign_pair, s.t[1], ALLIGN_NONE);
731 } else if (!g_ascii_strcasecmp(s.t[0], "margin")) {
732 p->margin = atoi(s.t[1]);
733 } else if (!g_ascii_strcasecmp(s.t[0], "widthtype")) {
734 p->widthtype = str2num(width_pair, s.t[1], WIDTH_NONE);
735 } else if (!g_ascii_strcasecmp(s.t[0], "width")) {
736 p->width = atoi(s.t[1]);
737 } else if (!g_ascii_strcasecmp(s.t[0], "heighttype")) {
738 p->heighttype = str2num(height_pair, s.t[1], HEIGHT_NONE);
739 } else if (!g_ascii_strcasecmp(s.t[0], "height")) {
740 p->height = atoi(s.t[1]);
741 } else if (!g_ascii_strcasecmp(s.t[0], "spacing")) {
742 p->spacing = atoi(s.t[1]);
743 } else if (!g_ascii_strcasecmp(s.t[0], "SetDockType")) {
744 p->setdocktype = str2num(bool_pair, s.t[1], 0);
745 } else if (!g_ascii_strcasecmp(s.t[0], "SetPartialStrut")) {
746 p->setstrut = str2num(bool_pair, s.t[1], 0);
747 } else if (!g_ascii_strcasecmp(s.t[0], "RoundCorners")) {
748 p->round_corners = str2num(bool_pair, s.t[1], 0);
749 } else if (!g_ascii_strcasecmp(s.t[0], "Transparent")) {
750 p->transparent = str2num(bool_pair, s.t[1], 0);
751 } else if (!g_ascii_strcasecmp(s.t[0], "Alpha")) {
752 p->alpha = atoi(s.t[1]);
753 if (p->alpha > 255)
754 p->alpha = 255;
755 } else if (!g_ascii_strcasecmp(s.t[0], "TintColor")) {
756 if (!gdk_color_parse (s.t[1], &p->gtintcolor))
757 gdk_color_parse ("white", &p->gtintcolor);
758 p->tintcolor = gcolor2rgb24(&p->gtintcolor);
759 DBG("tintcolor=%x\n", p->tintcolor);
2de71c90
FC
760 } else if (!g_ascii_strcasecmp(s.t[0], "useFontColor")) {
761 p->usefontcolor = str2num(bool_pair, s.t[1], 0);
762 } else if (!g_ascii_strcasecmp(s.t[0], "FontColor")) {
763 if (!gdk_color_parse (s.t[1], &p->gfontcolor))
764 gdk_color_parse ("black", &p->gfontcolor);
e7ce315d 765 p->fontcolor = gcolor2rgb24(&p->gfontcolor);
2de71c90
FC
766 DBG("fontcolor=%x\n", p->fontcolor);
767 } else if (!g_ascii_strcasecmp(s.t[0], "Background")) {
768 p->background = str2num(bool_pair, s.t[1], 0);
769 } else if( !g_ascii_strcasecmp(s.t[0], "BackgroundFile") ) {
770 p->background_file = g_strdup( s.t[1] );
a52c2257
HJYP
771 } else {
772 ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
773 RET(0);
774 }
775 } else if (s.type == LINE_BLOCK_END) {
776 break;
777 } else {
778 ERR( "lxpanel: illegal in this context %s\n", s.str);
779 RET(0);
780 }
781 }
a97d06a6 782 panel_set_orientation( p );
4542c20d 783
a52c2257
HJYP
784 if (p->width < 0)
785 p->width = 100;
786 if (p->widthtype == WIDTH_PERCENT && p->width > 100)
787 p->width = 100;
788 p->heighttype = HEIGHT_PIXEL;
789 if (p->heighttype == HEIGHT_PIXEL) {
790 if (p->height < PANEL_HEIGHT_MIN)
791 p->height = PANEL_HEIGHT_MIN;
792 else if (p->height > PANEL_HEIGHT_MAX)
793 p->height = PANEL_HEIGHT_MAX;
794 }
2de71c90
FC
795
796 if (p->background)
797 p->transparent = 0;
798
a52c2257
HJYP
799 p->curdesk = get_net_current_desktop();
800 p->desknum = get_net_number_of_desktops();
801 p->workarea = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_WORKAREA, XA_CARDINAL, &p->wa_len);
802 print_wmdata(p);
239cb032 803
a52c2257
HJYP
804 panel_start_gui(p);
805 RET(1);
806}
807
808static int
22242ed4 809panel_parse_plugin(Panel *p, char **fp)
a52c2257
HJYP
810{
811 line s;
22242ed4 812 Plugin *plug = NULL;
a52c2257 813 gchar *type = NULL;
a52c2257 814 int expand , padding, border;
db449f6e
HJYP
815 char* pconfig = NULL;
816
a52c2257
HJYP
817 ENTER;
818 s.len = 256;
a52c2257 819 border = expand = padding = 0;
c69ac68e 820 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
a52c2257
HJYP
821 if (s.type == LINE_NONE) {
822 ERR( "lxpanel: bad line %s\n", s.str);
823 goto error;
824 }
825 if (s.type == LINE_VAR) {
826 if (!g_ascii_strcasecmp(s.t[0], "type")) {
827 type = g_strdup(s.t[1]);
828 DBG("plug %s\n", type);
829 } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
830 expand = str2num(bool_pair, s.t[1], 0);
831 else if (!g_ascii_strcasecmp(s.t[0], "padding"))
832 padding = atoi(s.t[1]);
833 else if (!g_ascii_strcasecmp(s.t[0], "border"))
834 border = atoi(s.t[1]);
835 else {
836 ERR( "lxpanel: unknown var %s\n", s.t[0]);
837 goto error;
838 }
839 } else if (s.type == LINE_BLOCK_START) {
840 if (!g_ascii_strcasecmp(s.t[0], "Config")) {
db449f6e 841 pconfig = *fp;
a52c2257
HJYP
842 int pno = 1;
843 while (pno) {
844 get_line_as_is(fp, &s);
845 if (s.type == LINE_NONE) {
846 ERR( "lxpanel: unexpected eof\n");
847 goto error;
848 } else if (s.type == LINE_BLOCK_START) {
849 pno++;
850 } else if (s.type == LINE_BLOCK_END) {
851 pno--;
bee4c26e 852 }
db449f6e 853 }
a52c2257
HJYP
854 } else {
855 ERR( "lxpanel: unknown block %s\n", s.t[0]);
856 goto error;
857 }
858 } else {
859 ERR( "lxpanel: illegal in this context %s\n", s.str);
860 goto error;
861 }
862 }
db449f6e 863
a52c2257
HJYP
864 if (!type || !(plug = plugin_load(type))) {
865 ERR( "lxpanel: can't load %s plugin\n", type);
866 goto error;
867 }
db449f6e 868
a52c2257 869 plug->panel = p;
a52c2257
HJYP
870 plug->expand = expand;
871 plug->padding = padding;
872 plug->border = border;
a52c2257 873 DBG("starting\n");
db449f6e 874 if (!plugin_start(plug, pconfig ? &pconfig : NULL)) {
a52c2257
HJYP
875 ERR( "lxpanel: can't start plugin %s\n", type);
876 goto error;
877 }
878 DBG("plug %s\n", type);
879 p->plugins = g_list_append(p->plugins, plug);
0dcb6bf5
HJYP
880
881 g_free( type );
a52c2257 882 RET(1);
db449f6e 883
a52c2257 884 error:
a52c2257
HJYP
885 g_free(type);
886 if (plug)
887 plugin_put(plug);
888 RET(0);
a52c2257
HJYP
889}
890
891
0defe4b9 892static int
22242ed4 893panel_start( Panel *p, char **fp )
a52c2257
HJYP
894{
895 line s;
db449f6e 896
a52c2257
HJYP
897 /* parse global section */
898 ENTER;
899 s.len = 256;
8110399f 900
a52c2257
HJYP
901 p->allign = ALLIGN_CENTER;
902 p->edge = EDGE_BOTTOM;
903 p->widthtype = WIDTH_PERCENT;
904 p->width = 100;
905 p->heighttype = HEIGHT_PIXEL;
906 p->height = PANEL_HEIGHT_DEFAULT;
907 p->setdocktype = 1;
908 p->setstrut = 1;
909 p->round_corners = 0;
910 p->transparent = 0;
911 p->alpha = 127;
912 p->tintcolor = 0xFFFFFFFF;
2de71c90
FC
913 p->usefontcolor = 0;
914 p->fontcolor = 0x00000000;
a52c2257 915 p->spacing = 0;
22242ed4 916
c69ac68e 917 if ((lxpanel_get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
a52c2257
HJYP
918 ERR( "lxpanel: config file must start from Global section\n");
919 RET(0);
920 }
921 if (!panel_parse_global(p, fp))
922 RET(0);
923
c69ac68e 924 while (lxpanel_get_line(fp, &s) != LINE_NONE) {
a52c2257
HJYP
925 if ((s.type != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
926 ERR( "lxpanel: expecting Plugin section\n");
927 RET(0);
928 }
9939506e 929 panel_parse_plugin(p, fp);
a52c2257
HJYP
930 }
931 gtk_widget_show_all(p->topgwin);
4542c20d
HJYP
932
933 /* update backgrond of panel and all plugins */
934 panel_update_background( p );
935
a52c2257
HJYP
936 print_wmdata(p);
937 RET(1);
938}
939
940static void
941delete_plugin(gpointer data, gpointer udata)
942{
943 ENTER;
22242ed4
HJYP
944 plugin_stop((Plugin *)data);
945 plugin_put((Plugin *)data);
a52c2257 946 RET();
a52c2257
HJYP
947}
948
8110399f 949void panel_destroy(Panel *p)
a52c2257
HJYP
950{
951 ENTER;
952
953 g_list_foreach(p->plugins, delete_plugin, NULL);
954 g_list_free(p->plugins);
955 p->plugins = NULL;
8c44345a 956
5297da29 957 if( p->system_menus ){
8c44345a 958 do{
5297da29 959 } while ( g_source_remove_by_user_data( p->system_menus ) );
8c44345a
HJYP
960 }
961
239cb032
HJYP
962 g_object_unref( p->tooltips );
963
a52c2257 964 gtk_widget_destroy(p->topgwin);
a52c2257 965 g_free(p->workarea);
2de71c90 966 g_free( p->background_file );
5297da29 967 g_slist_free( p->system_menus );
a52c2257
HJYP
968 gdk_flush();
969 XFlush(GDK_DISPLAY());
970 XSync(GDK_DISPLAY(), True);
8110399f
HJYP
971
972 g_free( p->name );
cf701cb7 973 g_slice_free( Panel, p );
a52c2257
HJYP
974 RET();
975}
976
8110399f
HJYP
977Panel* panel_new( const char* config_file, const char* config_name )
978{
979 char *fp, *pfp; /* point to current position of profile data in memory */
cf701cb7 980 Panel* panel = NULL;
8110399f
HJYP
981 char* ret;
982
983 g_file_get_contents( config_file, &fp, NULL, NULL );
984 if( fp )
cf701cb7
HJYP
985 {
986 panel = g_slice_new0( Panel );
987 panel->name = g_strdup( config_name );
988 pfp = fp;
989
990 if (! panel_start( panel, &pfp )) {
991 ERR( "lxpanel: can't start panel\n");
992 panel_destroy( panel );
993 panel = NULL;
994 }
995
996 g_free( fp );
997 }
998 return panel;
8110399f 999}
a52c2257 1000
0defe4b9 1001static void
a52c2257
HJYP
1002usage()
1003{
e7cb732b
HJYP
1004 g_print(_("lxpanel %s - lightweight GTK2+ panel for UNIX desktops\n"), version);
1005 g_print(_("Command line options:\n"));
1006 g_print(_(" --help -- print this help and exit\n"));
1007 g_print(_(" --version -- print version and exit\n"));
1008 g_print(_(" --log <number> -- set log level 0-5. 0 - none 5 - chatty\n"));
1009 g_print(_(" --configure -- launch configuration utility\n"));
1010 g_print(_(" --profile name -- use specified profile\n"));
1011 g_print("\n");
1012 g_print(_(" -h -- same as --help\n"));
1013 g_print(_(" -p -- same as --profile\n"));
1014 g_print(_(" -v -- same as --version\n"));
1015 g_print(_(" -C -- same as --configure\n"));
8110399f 1016 g_print(_("\nVisit http://lxde.sourceforge.net/ for detail.\n\n"));
a52c2257
HJYP
1017}
1018
e68b47dc 1019static void
a52c2257
HJYP
1020handle_error(Display * d, XErrorEvent * ev)
1021{
1022 char buf[256];
1023
1024 ENTER;
1025 if (log_level >= LOG_WARN) {
1026 XGetErrorText(GDK_DISPLAY(), ev->error_code, buf, 256);
1027 LOG(LOG_WARN, "lxpanel : X error: %s\n", buf);
1028 }
1029 RET();
1030}
1031
e68b47dc
JH
1032/* Lightweight lock related functions - X clipboard hacks */
1033
1034#define CLIPBOARD_NAME "LXPANEL_SELECTION"
1035
1036/*
1037 * clipboard_get_func - dummy get_func for gtk_clipboard_set_with_data ()
1038 */
1039static void
1040clipboard_get_func(
1041 GtkClipboard *clipboard G_GNUC_UNUSED,
1042 GtkSelectionData *selection_data G_GNUC_UNUSED,
1043 guint info G_GNUC_UNUSED,
1044 gpointer user_data_or_owner G_GNUC_UNUSED)
1045{
1046}
1047
1048/*
1049 * clipboard_clear_func - dummy clear_func for gtk_clipboard_set_with_data ()
1050 */
1051static void clipboard_clear_func(
1052 GtkClipboard *clipboard G_GNUC_UNUSED,
1053 gpointer user_data_or_owner G_GNUC_UNUSED)
1054{
1055}
1056
1057/*
1058 * Lightweight version for checking single instance.
1059 * Try and get the CLIPBOARD_NAME clipboard instead of using file manipulation.
1060 *
1061 * Returns TRUE if successfully retrieved and FALSE otherwise.
1062 */
16fb8c2e 1063static gboolean check_main_lock()
e68b47dc
JH
1064{
1065 static const GtkTargetEntry targets[] = { { CLIPBOARD_NAME, 0, 0 } };
1066 gboolean retval = FALSE;
1067 GtkClipboard *clipboard;
1068 Atom atom;
1069
1070 atom = gdk_x11_get_xatom_by_name(CLIPBOARD_NAME);
1071
1072 XGrabServer(GDK_DISPLAY());
1073
1074 if (XGetSelectionOwner(GDK_DISPLAY(), atom) != None)
1075 goto out;
1076
1077 clipboard = gtk_clipboard_get(gdk_atom_intern(CLIPBOARD_NAME, FALSE));
1078
1079 if (gtk_clipboard_set_with_data(clipboard, targets,
1080 G_N_ELEMENTS (targets),
1081 clipboard_get_func,
1082 clipboard_clear_func, NULL))
1083 retval = TRUE;
1084
1085out:
1086 XUngrabServer (GDK_DISPLAY ());
1087 gdk_flush ();
1088
1089 return retval;
1090}
1091#undef CLIPBOARD_NAME
1092
8110399f
HJYP
1093static gboolean start_all_panels( )
1094{
cf701cb7
HJYP
1095 gboolean is_global;
1096 for( is_global = 0; is_global < 2; ++is_global )
1097 {
1098 char* panel_dir = get_config_file( cprofile, "panels", is_global );
1099 GDir* dir = g_dir_open( panel_dir, 0, NULL );
1100 char* name;
1101
1102 if( ! dir )
1103 {
1104 g_free( panel_dir );
1105 continue;
1106 }
1107
1108 while( name = g_dir_read_name( dir ) )
1109 {
1110 char* panel_config = g_build_filename( panel_dir, name, NULL );
1111 Panel* panel = panel_new( panel_config, name );
1112 if( panel )
1113 all_panels = g_slist_prepend( all_panels, panel );
1114 g_free( panel_config );
1115 }
1116 g_dir_close( dir );
1117 g_free( panel_dir );
1118 }
1119 return all_panels != NULL;
8110399f
HJYP
1120}
1121
cf701cb7
HJYP
1122void load_global_config();
1123void free_global_config();
1124
8110399f 1125int main(int argc, char *argv[], char *env[])
a52c2257
HJYP
1126{
1127 int i;
f277dbb7 1128
a52c2257 1129 setlocale(LC_CTYPE, "");
f277dbb7 1130
a52c2257
HJYP
1131 gtk_init(&argc, &argv);
1132
1133#ifdef ENABLE_NLS
1134 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
1135 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
1136 textdomain ( GETTEXT_PACKAGE );
1137#endif
1138
1139 XSetLocaleModifiers("");
1140 XSetErrorHandler((XErrorHandler) handle_error);
8110399f 1141
a52c2257 1142 resolve_atoms();
8110399f 1143
a52c2257
HJYP
1144 for (i = 1; i < argc; i++) {
1145 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
1146 usage();
1147 exit(0);
1148 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
1149 printf("lxpanel %s\n", version);
1150 exit(0);
1151 } else if (!strcmp(argv[i], "--log")) {
1152 i++;
1153 if (i == argc) {
1154 ERR( "lxpanel: missing log level\n");
1155 usage();
1156 exit(1);
1157 } else {
1158 log_level = atoi(argv[i]);
1159 }
1160 } else if (!strcmp(argv[i], "--configure") || !strcmp(argv[i], "-C")) {
1161 config = 1;
1162 } else if (!strcmp(argv[i], "--profile") || !strcmp(argv[i], "-p")) {
1163 i++;
1164 if (i == argc) {
1165 ERR( "lxpanel: missing profile name\n");
1166 usage();
1167 exit(1);
1168 } else {
1169 cprofile = g_strdup(argv[i]);
1170 }
1171 } else {
1172 printf("lxpanel: unknown option - %s\n", argv[i]);
1173 usage();
1174 exit(1);
1175 }
1176 }
f277dbb7 1177
8110399f 1178 /* Check for duplicated lxpanel instances */
e68b47dc
JH
1179 if (!check_main_lock() && !config) {
1180 printf("There is alreay an instance of LXPanel. Now to exit\n");
1181 exit(1);
1182 }
1183
f277dbb7
HJYP
1184 /* Add our own icons to the search path of icon theme */
1185 gtk_icon_theme_append_search_path( gtk_icon_theme_get_default(),
1186 PACKAGE_DATA_DIR "/lxpanel/images" );
1187
cf701cb7 1188 fbev = fb_ev_new();
22242ed4 1189
f7cb330e
HJYP
1190restart:
1191 is_restarting = FALSE;
1192
cf701cb7
HJYP
1193 load_global_config();
1194
1195 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), SubstructureNotifyMask|PropertyChangeMask);
1196 gdk_window_add_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, NULL);
8110399f 1197
cf701cb7
HJYP
1198 if( G_UNLIKELY( ! start_all_panels() ) )
1199 g_warning( "Config files are not found.\n" );
8110399f
HJYP
1200/*
1201 * FIXME: configure??
6a6ad54e
HJYP
1202 if (config)
1203 configure();
8110399f 1204*/
6a6ad54e 1205 gtk_main();
8110399f 1206
cf701cb7
HJYP
1207 XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), NoEventMask);
1208 gdk_window_remove_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, NULL);
1209
8110399f
HJYP
1210 /* destroy all panels */
1211 g_slist_foreach( all_panels, (GFunc) panel_destroy, NULL );
6a6ad54e 1212 g_free( cfgfile );
5541b8d2 1213
cf701cb7
HJYP
1214 free_global_config();
1215
f7cb330e
HJYP
1216 if( is_restarting )
1217 goto restart;
1218
22242ed4
HJYP
1219 g_object_unref(fbev);
1220
5541b8d2 1221 return 0;
a52c2257 1222}