Add external controller lxpanelctl for lxpanel.
authorHong Jen Yee (PCMan) <pcman.tw@gmail.com>
Fri, 6 Oct 2006 13:46:08 +0000 (13:46 +0000)
committerHong Jen Yee (PCMan) <pcman.tw@gmail.com>
Fri, 6 Oct 2006 13:46:08 +0000 (13:46 +0000)
src/Makefile.am
src/Makefile.in
src/lxpanelctl.c [new file with mode: 0644]
src/lxpanelctl.h [new file with mode: 0644]
src/misc.c
src/panel.c
src/panel.h

index 2698a7c..3a92b6f 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-bin_PROGRAMS = lxpanel
+bin_PROGRAMS = lxpanel lxpanelctl
 
 INCLUDES = \
        -I$(top_srcdir) \
@@ -47,5 +47,8 @@ lxpanel_SOURCES = \
 
 lxpanel_LDADD = $(PACKAGE_LIBS) $(INTLLIBS)
 
+lxpanelctl_SOURCES = lxpanelctl.c
+lxpanelctl_LDADD = -lX11 $(INTLLIBS)
+
 EXTRA_DIST = \
        plugins/icon.xpm
index 047c66d..eb5daff 100644 (file)
@@ -36,7 +36,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-bin_PROGRAMS = lxpanel$(EXEEXT)
+bin_PROGRAMS = lxpanel$(EXEEXT) lxpanelctl$(EXEEXT)
 subdir = src
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -63,6 +63,9 @@ am_lxpanel_OBJECTS = misc.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
 lxpanel_OBJECTS = $(am_lxpanel_OBJECTS)
 am__DEPENDENCIES_1 =
 lxpanel_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_lxpanelctl_OBJECTS = lxpanelctl.$(OBJEXT)
+lxpanelctl_OBJECTS = $(am_lxpanelctl_OBJECTS)
+lxpanelctl_DEPENDENCIES = $(am__DEPENDENCIES_1)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -70,8 +73,8 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(lxpanel_SOURCES)
-DIST_SOURCES = $(lxpanel_SOURCES)
+SOURCES = $(lxpanel_SOURCES) $(lxpanelctl_SOURCES)
+DIST_SOURCES = $(lxpanel_SOURCES) $(lxpanelctl_SOURCES)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -259,6 +262,8 @@ lxpanel_SOURCES = \
        gtk-run.c
 
 lxpanel_LDADD = $(PACKAGE_LIBS) $(INTLLIBS)
+lxpanelctl_SOURCES = lxpanelctl.c
+lxpanelctl_LDADD = -lX11 $(INTLLIBS)
 EXTRA_DIST = \
        plugins/icon.xpm
 
@@ -321,6 +326,9 @@ clean-binPROGRAMS:
 lxpanel$(EXEEXT): $(lxpanel_OBJECTS) $(lxpanel_DEPENDENCIES) 
        @rm -f lxpanel$(EXEEXT)
        $(LINK) $(lxpanel_LDFLAGS) $(lxpanel_OBJECTS) $(lxpanel_LDADD) $(LIBS)
+lxpanelctl$(EXEEXT): $(lxpanelctl_OBJECTS) $(lxpanelctl_DEPENDENCIES) 
+       @rm -f lxpanelctl$(EXEEXT)
+       $(LINK) $(lxpanelctl_LDFLAGS) $(lxpanelctl_OBJECTS) $(lxpanelctl_LDADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
@@ -345,6 +353,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icons.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/image.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/launchbar.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxpanelctl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menu.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pager.Po@am__quote@
diff --git a/src/lxpanelctl.c b/src/lxpanelctl.c
new file mode 100644 (file)
index 0000000..39de2ed
--- /dev/null
@@ -0,0 +1,71 @@
+/* Remote controller of lxpanel */
+
+#include "lxpanelctl.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+static Display* dpy;
+
+const char usage[] = "\nlxpanelctl - LXPanel Controller\n"
+        "Usage: lxpanelctl <command>\n\n"
+        "Available commands:\n"
+        "menu\tshow system menu\n"
+        "run\tshow run dialog\n"
+        "config\tshow config dialog\n"
+        "restart\trestart lxpanel\n"
+        "exit\texit lxpanel\n\n";
+
+int get_cmd( const char* cmd )
+{
+    if( ! strcmp( cmd, "menu") )
+        return LXPANEL_CMD_SYS_MENU;
+    else if( ! strcmp( cmd, "run") )
+        return LXPANEL_CMD_RUN;
+    else if( ! strcmp( cmd, "config") )
+        return LXPANEL_CMD_CONFIG;
+    else if( ! strcmp( cmd, "restart") )
+        return LXPANEL_CMD_RESTART;
+    else if( ! strcmp( cmd, "exit") )
+        return LXPANEL_CMD_EXIT;
+    return -1;
+}
+
+int main( int argc, char** argv )
+{
+    char *display_name = (char *)getenv("DISPLAY");
+    XEvent ev;
+    Window root;
+    Atom cmd_atom;
+    int cmd;
+
+    if( argc < 2 )
+    {
+        printf( usage );
+        return 1;
+    }
+    if( ( cmd = get_cmd( argv[1] ) ) == -1 )
+        return 1;
+
+    dpy = XOpenDisplay(display_name);
+    if (dpy == NULL) {
+        printf("Cant connect to display: %s\n", display_name);
+        exit(1);
+    }
+    root = DefaultRootWindow(dpy);
+    cmd_atom = XInternAtom(dpy, "_LXPANEL_CMD", False);
+    memset(&ev, '\0', sizeof ev);
+    ev.xclient.type = ClientMessage;
+    ev.xclient.window = root;
+    ev.xclient.message_type = cmd_atom;
+    ev.xclient.format = 8;
+
+    ev.xclient.data.l[0] = cmd;
+
+    XSendEvent(dpy, root, False,
+               SubstructureRedirectMask|SubstructureNotifyMask, &ev);
+    XSync(dpy, False);
+    XCloseDisplay(dpy);
+    return 0;
+}
+
diff --git a/src/lxpanelctl.h b/src/lxpanelctl.h
new file mode 100644 (file)
index 0000000..3470649
--- /dev/null
@@ -0,0 +1,10 @@
+/* Commands controlling lxpanel */
+
+enum {
+    LXPANEL_CMD_NONE,
+    LXPANEL_CMD_SYS_MENU,
+    LXPANEL_CMD_RUN,
+    LXPANEL_CMD_CONFIG,
+    LXPANEL_CMD_RESTART,
+    LXPANEL_CMD_EXIT
+};
index 2053ba2..07ba0d0 100644 (file)
@@ -63,6 +63,8 @@ Atom a_NET_WM_STRUT_PARTIAL;
 Atom a_NET_WM_ICON;
 Atom a_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR;
 
+Atom a_LXPANEL_CMD; /* for private client message */
+
 pair allign_pair[] = {
     { ALLIGN_NONE, "none" },
     { ALLIGN_LEFT, "left" },
@@ -209,7 +211,7 @@ get_line_as_is(FILE *fp, line *s)
 void resolve_atoms()
 {
     ENTER;
-    
+
     a_UTF8_STRING                = XInternAtom(GDK_DISPLAY(), "UTF8_STRING", False);
     a_XROOTPMAP_ID               = XInternAtom(GDK_DISPLAY(), "_XROOTPMAP_ID", False);
     a_WM_STATE                   = XInternAtom(GDK_DISPLAY(), "WM_STATE", False);
@@ -249,7 +251,9 @@ void resolve_atoms()
     a_NET_WM_ICON                = XInternAtom(GDK_DISPLAY(), "_NET_WM_ICON", False);
     a_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
                                  = XInternAtom(GDK_DISPLAY(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
-                                
+
+    a_LXPANEL_CMD = XInternAtom(GDK_DISPLAY(), "_LXPANEL_CMD", False);
+
     RET();
 }
 
index 0671aa6..a733791 100644 (file)
@@ -19,6 +19,8 @@
 #include "bg.h"
 #include "gtkbgbox.h"
 
+#include "lxpanelctl.h"
+
 static gchar *cfgfile = NULL;
 static gchar version[] = VERSION;
 gchar *cprofile = "default";
@@ -118,6 +120,33 @@ print_wmdata(panel *p)
 }
 
 
+/* built-in commands */
+void configure(void);
+void restart(void);
+void gtk_run(void);
+
+static void process_client_msg ( panel *p, int cmd )
+{
+    switch( cmd )
+    {
+        case LXPANEL_CMD_SYS_MENU:
+            /* FIXME: should popup system menu */
+            break;
+        case LXPANEL_CMD_RUN:
+            gtk_run();
+            break;
+        case LXPANEL_CMD_CONFIG:
+            configure();
+            break;
+        case LXPANEL_CMD_RESTART:
+            restart();
+            break;
+        case LXPANEL_CMD_EXIT:
+            gtk_main_quit();
+            break;
+    }
+}
+
 static GdkFilterReturn
 panel_event_filter(GdkXEvent *xevent, GdkEvent *event, panel *p)
 {
@@ -127,9 +156,15 @@ panel_event_filter(GdkXEvent *xevent, GdkEvent *event, panel *p)
 
     ENTER;
     DBG("win = 0x%x\n", ev->xproperty.window);
-    if (ev->type != PropertyNotify )
+    if (ev->type != PropertyNotify ) {
+        /* private client message from lxpanelctl */
+        if( ev->type == ClientMessage && ev->xproperty.atom == a_LXPANEL_CMD )
+        {
+            process_client_msg( p, ((XClientMessageEvent*)ev)->data.b[0] );
+        }
         RET(GDK_FILTER_CONTINUE);
-    
+       }
+
     at = ev->xproperty.atom;
     win = ev->xproperty.window;
     DBG("win=%x at=%d\n", win, at);
@@ -330,7 +365,7 @@ panel_start_gui(panel *p)
     gtk_window_set_title(GTK_WINDOW(p->topgwin), "panel");
     gtk_window_set_position(GTK_WINDOW(p->topgwin), GTK_WIN_POS_NONE);
     gtk_window_set_decorated(GTK_WINDOW(p->topgwin), FALSE);
-    
+
     g_signal_connect(G_OBJECT(p->topgwin), "delete-event",
           G_CALLBACK(panel_delete_event), p);
     g_signal_connect(G_OBJECT(p->topgwin), "destroy-event",
@@ -408,14 +443,14 @@ panel_start_gui(panel *p)
     XChangeProperty(GDK_DISPLAY(), p->topxwin, a_NET_WM_STATE, XA_ATOM,
           32, PropModeReplace, (unsigned char *) state, 3);
 
-    XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), PropertyChangeMask);
+    XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(), SubstructureNotifyMask|PropertyChangeMask);
     gdk_window_add_filter(gdk_get_default_root_window (), (GdkFilterFunc)panel_event_filter, p);
 
     calculate_position(p);
     gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
     if (p->setstrut)
         panel_set_wm_strut(p);
-  
+
     RET();
 }
 
index a1853e4..f664c9b 100644 (file)
@@ -144,6 +144,7 @@ extern Atom a_NET_WM_STRUT_PARTIAL;
 extern Atom a_NET_WM_ICON;
 extern Atom a_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR;
 
+extern Atom a_LXPANEL_CMD; /* for private client message */
 
 extern int verbose;