aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am1
-rw-r--r--NEWS0
-rw-r--r--README0
-rw-r--r--applets/Makefile.am21
-rw-r--r--applets/dotdesktop/Makefile.am10
-rw-r--r--applets/dotdesktop/mb-applet-battery.desktop8
-rw-r--r--applets/dotdesktop/mb-applet-clock.desktop7
-rw-r--r--applets/dotdesktop/mb-applet-menu-launcher.desktop7
-rw-r--r--applets/dotdesktop/mb-applet-system-monitor.desktop7
-rw-r--r--applets/dotdesktop/mb-applet-wireless.desktop7
-rw-r--r--applets/dotdesktop/mb-launcher-term.desktop8
-rw-r--r--applets/dotdesktop/mb-show-desktop.desktop8
-rw-r--r--applets/icons/Makefile.am25
-rw-r--r--applets/icons/battery.xpm20
-rw-r--r--applets/icons/broken-0.pngbin0 -> 324 bytes
-rw-r--r--applets/icons/broken-0.xpm63
-rw-r--r--applets/icons/mbmenu.pngbin0 -> 962 bytes
-rw-r--r--applets/icons/mbmenu.xpm72
-rw-r--r--applets/icons/mbterm.pngbin0 -> 1249 bytes
-rw-r--r--applets/icons/minisys.pngbin0 -> 1081 bytes
-rw-r--r--applets/icons/minisys.xpm144
-rw-r--r--applets/icons/minitime.pngbin0 -> 2373 bytes
-rw-r--r--applets/icons/minitimestrip.xpm18
-rw-r--r--applets/icons/miniwave-icon.pngbin0 -> 503 bytes
-rw-r--r--applets/icons/miniwave.xpm21
-rw-r--r--applets/icons/no-link-0.pngbin0 -> 328 bytes
-rw-r--r--applets/icons/no-link-0.xpm62
-rw-r--r--applets/icons/oval_filled.xpm22
-rw-r--r--applets/icons/signal-1-40.pngbin0 -> 816 bytes
-rw-r--r--applets/icons/signal-1-40.xpm127
-rw-r--r--applets/icons/signal-41-60.pngbin0 -> 1261 bytes
-rw-r--r--applets/icons/signal-41-60.xpm169
-rw-r--r--applets/icons/signal-61-80.pngbin0 -> 1255 bytes
-rw-r--r--applets/icons/signal-61-80.xpm169
-rw-r--r--applets/icons/signal-81-100.pngbin0 -> 1838 bytes
-rw-r--r--applets/icons/signal-81-100.xpm219
-rw-r--r--applets/icons/term.pngbin0 -> 798 bytes
-rw-r--r--applets/mb-applet-battery.c482
-rw-r--r--applets/mb-applet-clock.c385
-rw-r--r--applets/mb-applet-launcher.c661
-rw-r--r--applets/mb-applet-menu-launcher.c964
-rw-r--r--applets/mb-applet-system-monitor.c369
-rw-r--r--applets/mb-applet-wireless.c511
-rw-r--r--applets/small-icons/Makefile.am25
-rw-r--r--applets/small-icons/broken-0.pngbin0 -> 1053 bytes
-rw-r--r--applets/small-icons/broken-0.xpm191
-rw-r--r--applets/small-icons/mbdesktop.pngbin0 -> 1175 bytes
-rw-r--r--applets/small-icons/mbdesktop.xpm207
-rw-r--r--applets/small-icons/mbmenu.pngbin0 -> 510 bytes
-rw-r--r--applets/small-icons/mbmenu.xpm68
-rw-r--r--applets/small-icons/miniapm-power.pngbin0 -> 364 bytes
-rw-r--r--applets/small-icons/miniapm-power.xpm43
-rw-r--r--applets/small-icons/miniapm.pngbin0 -> 437 bytes
-rw-r--r--applets/small-icons/miniapm.xpm67
-rw-r--r--applets/small-icons/minisys.pngbin0 -> 206 bytes
-rw-r--r--applets/small-icons/minisys.xpm27
-rw-r--r--applets/small-icons/no-link-0.pngbin0 -> 1056 bytes
-rw-r--r--applets/small-icons/no-link-0.xpm195
-rw-r--r--applets/small-icons/signal-1-40.pngbin0 -> 1063 bytes
-rw-r--r--applets/small-icons/signal-1-40.xpm197
-rw-r--r--applets/small-icons/signal-41-60.pngbin0 -> 1062 bytes
-rw-r--r--applets/small-icons/signal-41-60.xpm199
-rw-r--r--applets/small-icons/signal-61-80.pngbin0 -> 1061 bytes
-rw-r--r--applets/small-icons/signal-61-80.xpm196
-rw-r--r--applets/small-icons/signal-81-100.pngbin0 -> 1051 bytes
-rw-r--r--applets/small-icons/signal-81-100.xpm190
-rwxr-xr-xautogen.sh3
-rw-r--r--configure.ac199
-rw-r--r--po/Makefile.am49
-rw-r--r--po/cs.po140
-rw-r--r--po/de.po141
-rw-r--r--po/en_GB.po142
-rw-r--r--po/es_ES.po142
-rw-r--r--po/fi_FI.po142
-rw-r--r--po/fr_FR.po138
-rw-r--r--src/Makefile.am15
-rw-r--r--src/msg.c670
-rw-r--r--src/msg.h20
-rw-r--r--src/panel.c2030
-rw-r--r--src/panel.h312
-rw-r--r--src/panel_app.c597
-rw-r--r--src/panel_app.h92
-rw-r--r--src/panel_menu.c276
-rw-r--r--src/panel_menu.h27
-rw-r--r--src/panel_util.c233
-rw-r--r--src/panel_util.h33
-rw-r--r--src/session.c311
-rw-r--r--src/session.h37
90 files changed, 11942 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..4346e4b
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Matthew Allum <mallum@handhelds.org>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..25b3e77
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src applets
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/applets/Makefile.am b/applets/Makefile.am
new file mode 100644
index 0000000..2f7692d
--- /dev/null
+++ b/applets/Makefile.am
@@ -0,0 +1,21 @@
+SUBDIRS = dotdesktop icons small-icons
+
+PREFIXDIR = $(prefix)
+PKGDATADIR = $(pkgdatadir)
+DATADIR = $(datadir)
+
+INCLUDES = -DDATADIR=\"$(DATADIR)\" -DPKGDATADIR=\"$(PKGDATADIR)\" -DPREFIX=\"$(PREFIXDIR)\" $(LIBMB_CFLAGS)
+
+bin_PROGRAMS = \
+ mb-applet-clock mb-applet-menu-launcher mb-applet-wireless \
+ mb-applet-launcher mb-applet-system-monitor mb-applet-battery
+
+LDADD = $(LIBMB_LIBS)
+
+mb_applet_clock_SOURCES = mb-applet-clock.c
+mb_applet_menu_launcher_SOURCES = mb-applet-menu-launcher.c
+mb_applet_wireless_SOURCES = mb-applet-wireless.c
+mb_applet_launcher_SOURCES = mb-applet-launcher.c
+mb_applet_system_monitor_SOURCES = mb-applet-system-monitor.c
+mb_applet_battery_SOURCES = mb-applet-battery.c
+mb_applet_battery_LDADD = $(LIBMB_LIBS) -lapm \ No newline at end of file
diff --git a/applets/dotdesktop/Makefile.am b/applets/dotdesktop/Makefile.am
new file mode 100644
index 0000000..4d7dc31
--- /dev/null
+++ b/applets/dotdesktop/Makefile.am
@@ -0,0 +1,10 @@
+files = \
+ mb-applet-battery.desktop mb-applet-wireless.desktop \
+ mb-applet-clock.desktop mb-launcher-term.desktop \
+ mb-applet-menu-launcher.desktop mb-show-desktop.desktop \
+ mb-applet-system-monitor.desktop
+
+EXTRA_DIST = $(desktopfiles)
+
+desktopdir = $(datadir)/applications/
+desktop_DATA = $(files) \ No newline at end of file
diff --git a/applets/dotdesktop/mb-applet-battery.desktop b/applets/dotdesktop/mb-applet-battery.desktop
new file mode 100644
index 0000000..0f8ad74
--- /dev/null
+++ b/applets/dotdesktop/mb-applet-battery.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Battery Monitor
+Comment=Panel based Battery Monitor
+Exec=mb-applet-battery
+Type=PanelApp
+Icon=miniapm.png
+Categories=Panel;Utility;MB
+
diff --git a/applets/dotdesktop/mb-applet-clock.desktop b/applets/dotdesktop/mb-applet-clock.desktop
new file mode 100644
index 0000000..0f34c42
--- /dev/null
+++ b/applets/dotdesktop/mb-applet-clock.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Clock
+Comment=Panel based clock
+Exec=mb-applet-clock
+Type=PanelApp
+Icon=minitime.png
+Categories=Panel;Utility;MB
diff --git a/applets/dotdesktop/mb-applet-menu-launcher.desktop b/applets/dotdesktop/mb-applet-menu-launcher.desktop
new file mode 100644
index 0000000..3129ec4
--- /dev/null
+++ b/applets/dotdesktop/mb-applet-menu-launcher.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=App Launcher
+Comment=Panel based Application Launcher
+Exec=mb-applet-menu-launcher
+Type=PanelApp
+Icon=mbmenu.png
+Categories=Panel;Utility;MB
diff --git a/applets/dotdesktop/mb-applet-system-monitor.desktop b/applets/dotdesktop/mb-applet-system-monitor.desktop
new file mode 100644
index 0000000..a61f731
--- /dev/null
+++ b/applets/dotdesktop/mb-applet-system-monitor.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=CPU/Mem Monitor
+Comment=Panel based CPU/Mem Monitor
+Exec=mb-applet-system-monitor
+Type=PanelApp
+Icon=minisys.png
+Categories=Panel;Utility;MB
diff --git a/applets/dotdesktop/mb-applet-wireless.desktop b/applets/dotdesktop/mb-applet-wireless.desktop
new file mode 100644
index 0000000..7dff9ef
--- /dev/null
+++ b/applets/dotdesktop/mb-applet-wireless.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Wireless Monitor
+Comment=Panel based wireless monitor
+Exec=mb-applet-wireless
+Type=PanelApp
+Icon=signal-81-100.png
+Categories=Panel;Utility;MB
diff --git a/applets/dotdesktop/mb-launcher-term.desktop b/applets/dotdesktop/mb-launcher-term.desktop
new file mode 100644
index 0000000..c68be76
--- /dev/null
+++ b/applets/dotdesktop/mb-launcher-term.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Term Launcher
+Comment=Panel based Terminal launcher
+# the '-o -1' makes monolaunch dock to the left
+Exec=mb-applet-launcher -o -1 -l /usr/local/share/pixmaps/mbterm.png rxvt
+Type=PanelApp
+Icon=mbterm.png
+Categories=Panel;Utility;MB
diff --git a/applets/dotdesktop/mb-show-desktop.desktop b/applets/dotdesktop/mb-show-desktop.desktop
new file mode 100644
index 0000000..eaae088
--- /dev/null
+++ b/applets/dotdesktop/mb-show-desktop.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Desktop
+Comment=Toggle Desktop Visiblity
+Exec=matchbox-remote -desktop
+Type=Application
+Icon=mbdesktop.png
+Categories=Action
+
diff --git a/applets/icons/Makefile.am b/applets/icons/Makefile.am
new file mode 100644
index 0000000..26804ed
--- /dev/null
+++ b/applets/icons/Makefile.am
@@ -0,0 +1,25 @@
+pngs = \
+broken-0.png minisys.png no-link-0.png signal-61-80.png \
+mbmenu.png minitime.png signal-1-40.png signal-81-100.png \
+mbterm.png miniwave-icon.png signal-41-60.png term.png \
+
+xpms = \
+battery.xpm minisys.xpm no-link-0.xpm signal-41-60.xpm \
+broken-0.xpm minitimestrip.xpm oval_filled.xpm signal-61-80.xpm \
+mbmenu.xpm miniwave.xpm signal-1-40.xpm signal-81-100.xpm \
+
+EXTRA_DIST = $(xpms) $(pngs)
+
+if WANT_PNGS
+imgs = $(pngs)
+else
+imgs = $(xpms)
+endif
+
+pixmapsdir = $(datadir)/pixmaps/
+
+if WANT_SMALL_ICONS
+pixmaps_DATA =
+else
+pixmaps_DATA = $(imgs)
+endif \ No newline at end of file
diff --git a/applets/icons/battery.xpm b/applets/icons/battery.xpm
new file mode 100644
index 0000000..289a861
--- /dev/null
+++ b/applets/icons/battery.xpm
@@ -0,0 +1,20 @@
+/* XPM */
+static char * battery_xpm[] = {
+"8 15 2 1",
+" g None",
+". g #000000",
+" ",
+" ... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+"....... ",
+" ... ",
+" "};
diff --git a/applets/icons/broken-0.png b/applets/icons/broken-0.png
new file mode 100644
index 0000000..329e46f
--- /dev/null
+++ b/applets/icons/broken-0.png
Binary files differ
diff --git a/applets/icons/broken-0.xpm b/applets/icons/broken-0.xpm
new file mode 100644
index 0000000..31e3e5b
--- /dev/null
+++ b/applets/icons/broken-0.xpm
@@ -0,0 +1,63 @@
+/* XPM */
+static char *broken-0[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 9 1",
+" c black",
+". c red",
+"X c #FF3F3F",
+"o c #FF7F7F",
+"O c #FFBFBF",
+"+ c #FFCFCF",
+"@ c #FFDFDF",
+"# c gray100",
+"$ c None",
+/* pixels */
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$#######################################$$$$",
+"$$$$#########################################$$$",
+"$$$$#########################################$$$",
+"$$$$###+XXXXXXX+####+XXXXXXX+####+XXXXXXX+###$$$",
+"$$$$###O.......O####O.......O####O.......O###$$$",
+"$$$$###O.......O####O.......O####O.......O###$$$",
+"$$$$###O.......O####O.......O####O.......O###$$$",
+"$$$$###O.......O####O.......O####O.......O###$$$",
+"$$$$###O.......O####O.......O####O.......O###$$$",
+"$$$$###@ooooooo@####@ooooooo@####@ooooooo@###$$$",
+"$$$$#########################################$$$",
+"$$$$#########################################$$$",
+"$$$$$#######################################$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
+};
diff --git a/applets/icons/mbmenu.png b/applets/icons/mbmenu.png
new file mode 100644
index 0000000..2a9e663
--- /dev/null
+++ b/applets/icons/mbmenu.png
Binary files differ
diff --git a/applets/icons/mbmenu.xpm b/applets/icons/mbmenu.xpm
new file mode 100644
index 0000000..4e07b94
--- /dev/null
+++ b/applets/icons/mbmenu.xpm
@@ -0,0 +1,72 @@
+/* XPM */
+static char *mbmenu[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 18 1",
+" c black",
+". c gray6",
+"X c gray12",
+"o c #2F2F2F",
+"O c #3F3F3F",
+"+ c gray31",
+"@ c #5F5F5F",
+"# c #6F6F6F",
+"$ c gray50",
+"% c gray56",
+"& c #9F9F9F",
+"* c #AFAFAF",
+"= c gray75",
+"- c gray81",
+"; c #DFDFDF",
+": c #EFEFEF",
+"> c gray100",
+", c None",
+/* pixels */
+",,,,,,,,,,,,,,,,,,,,>>>>>>>>>,,,,,,,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>,,,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>,,,,,,,,,,,,,",
+",,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>>>>>,,,,,,,,,,,",
+",,,,,,,,,,,>>>>>>>:*#Oo oO$*>>>>>>>>,,,,,,,,,,",
+",,,,,,,,,,>>>>>>-=-. .@->>>>>>,,,,,,,,,",
+",,,,,,,,,>>>>>;+ $>= +;>>>>>,,,,,,,,",
+",,,,,,,,>>>>>%. $>>& .%>>>>>,,,,,,,",
+",,,,,,,>>>>>@ $>>>& @>>>>>,,,,,,",
+",,,,,,>>>>>@ $>>>>& @>>>>>,,,,,",
+",,,,,>>>>>@ $>>>>>& @>>>>>,,,,",
+",,,,,>>>>% $>>>>>>& %>>>>,,,,",
+",,,,>>>>- $>>>>>>>& ;>>>>,,,",
+",,,,>>>>*$$$$$$$$=>>>>>>>>& O>>>>,,,",
+",,,>>>>>>>>>>>>>>>>>>>>>>>>& =>>>>,,",
+",,,>>>>>>>>>>>>>>>>>>>>>>>>>& +>>>>,,",
+",,,>>>>>>>>>>>>>>>>>>>>>>>>>>& :>>>,,",
+",,,>>>>>>>>>>>>>>>>>>>>>>>>>>>& &>>>,,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>>>>>& @>>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>>>>>># o>>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>>>>>:o >>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>>>>:o >>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>>>:o >>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>>:o >>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>>:o >>>>,",
+",,>>>>>>>>>>>>>>>>>>>>>>>>:o X>>>>,",
+",,>>>>O $>>>>>>>:o +>>>>,",
+",,>>>>% $>>>>>>:o %>>>>,",
+",,,>>>- $>>>>>:o ;>>>,,",
+",,,>>>>o $>>>>:o o>>>>,,",
+",,,>>>>& $>>>:o &>>>>,,",
+",,,,>>>>X $>>:o X>>>>,,,",
+",,,,>>>>* $>:o =>>>>,,,",
+",,,,,>>>>@ $:o @>>>>,,,,",
+",,,,,>>>>:o Oo o:>>>>,,,,",
+",,,,,,>>>>:o o:>>>>,,,,,",
+",,,,,,,>>>>:o o:>>>>,,,,,,",
+",,,,,,,>>>>>:+ +:>>>>>,,,,,,",
+",,,,,,,,>>>>>>*X X*>>>>>>,,,,,,,",
+",,,,,,,,,>>>>>>:%X X%:>>>>>>,,,,,,,,",
+",,,,,,,,,,,>>>>>>>=#o O#->>>>>>>,,,,,,,,,,",
+",,,,,,,,,,,,>>>>>>>>>>;===:>>>>>>>>>>,,,,,,,,,,,",
+",,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>>>>>,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,,,>>>>>>>>>>>>>>>>>,,,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,,,,,,>>>>>>>>>>>,,,,,,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,",
+",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
+};
diff --git a/applets/icons/mbterm.png b/applets/icons/mbterm.png
new file mode 100644
index 0000000..d31dff8
--- /dev/null
+++ b/applets/icons/mbterm.png
Binary files differ
diff --git a/applets/icons/minisys.png b/applets/icons/minisys.png
new file mode 100644
index 0000000..893049a
--- /dev/null
+++ b/applets/icons/minisys.png
Binary files differ
diff --git a/applets/icons/minisys.xpm b/applets/icons/minisys.xpm
new file mode 100644
index 0000000..e3427d9
--- /dev/null
+++ b/applets/icons/minisys.xpm
@@ -0,0 +1,144 @@
+/* XPM */
+static char *minisys[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 90 1",
+" c black",
+". c #010101",
+"X c #020202",
+"o c gray1",
+"O c #060606",
+"+ c gray3",
+"@ c #0C0C0C",
+"# c gray5",
+"$ c #0E0E0E",
+"% c gray6",
+"& c #101010",
+"* c #111111",
+"= c gray7",
+"- c gray8",
+"; c #151515",
+": c #161616",
+"> c gray9",
+", c #181818",
+"< c gray11",
+"1 c #1E1E1E",
+"2 c #202020",
+"3 c gray13",
+"4 c #222222",
+"5 c gray15",
+"6 c #282828",
+"7 c gray18",
+"8 c #313131",
+"9 c #323232",
+"0 c gray20",
+"q c #373737",
+"w c #3E3E3E",
+"e c #3F3F3F",
+"r c gray25",
+"t c #434343",
+"y c #464646",
+"u c gray28",
+"i c #494949",
+"p c gray34",
+"a c gray37",
+"s c #646464",
+"d c #686868",
+"f c DimGray",
+"g c #6F6F6F",
+"h c #717171",
+"j c gray47",
+"k c #7C7C7C",
+"l c #808080",
+"z c gray51",
+"x c gray55",
+"c c #909090",
+"v c gray59",
+"b c #9A9A9A",
+"n c gray62",
+"m c #9F9F9F",
+"M c gray63",
+"N c #AAAAAA",
+"B c gray69",
+"V c #B4B4B4",
+"C c #B6B6B6",
+"Z c gray72",
+"A c gray74",
+"S c #C0C0C0",
+"D c #C1C1C1",
+"F c #C3C3C3",
+"G c gray77",
+"H c #C6C6C6",
+"J c #C8C8C8",
+"K c #CBCBCB",
+"L c #D0D0D0",
+"P c #D2D2D2",
+"I c #D7D7D7",
+"U c gray86",
+"Y c gainsboro",
+"T c #DFDFDF",
+"R c gray92",
+"E c #EEEEEE",
+"W c #EFEFEF",
+"Q c gray94",
+"! c #F1F1F1",
+"~ c gray95",
+"^ c #F3F3F3",
+"/ c #F4F4F4",
+"( c gray96",
+") c gray98",
+"_ c #FBFBFB",
+"` c gray99",
+"' c #FDFDFD",
+"] c #FEFEFE",
+"[ c gray100",
+"{ c None",
+/* pixels */
+"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{",
+"{{{{{[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{{{{{",
+"{{{[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{{{",
+"{{[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{{",
+"{[[[[[[[[))))))))))))))))))))))))))))))[[[[[[[[{",
+"{[[[[[Ujw000000q00000000000000000000000qsF[[[[[{",
+"[[[[[Z- x[[[[[",
+"[[[[T< V[[[[",
+"[[[[k *---,-------------,-,---,-,*O i[[[[",
+"[[[[i %vW(!!!!(!(!(!(!!(!!!!!(!!!!!(Z5 -![[[",
+"[[[[r z[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[A %R[[[",
+"[[[[r S[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[!< %R[[[",
+"[[[[w S[[TnMMMMMMMMMMMMMMMMMMMMMMbP[[(3 *R[[[",
+"[[[[w OF[[M k[[(3 %R[[[",
+"[[[[r F[[M z[[(3 %R[[[",
+"[[[[r F[[M z[[(3 %R[[[",
+"[[[[r OS[[M z[[(3 %R[[[",
+"[[[[r F[[M z[[(3 %R[[[",
+"[[[[r F[[M k[[(3 %R[[[",
+"[[[[r OF[[M z[[(3 %R[[[",
+"[[[[r F[[M k[[(3 %R[[[",
+"[[[[r F[[M z[[(3 %R[[[",
+"[[[[r OS[[M z[[(3 %R[[[",
+"[[[)r F[[M k[[(3 %R[[[",
+"[[[[w F[[M z[[(3 %R[[[",
+"[[[[w F[[M k[[(3 %R[[[",
+"[[[[r F[[M z[[(3 %R[[[",
+"[[[[r OS[[M z[[(3 %R[[[",
+"[[[[r F[[M z[[(3 %R[[[",
+"[[[[r F[[M k[[(3 %R[[[",
+"[[[[r OF[[M z[[(3 %R[[[",
+"[[[[r S[[M z[[(3 %R[[[",
+"[[[[r F[[M O k[[(3 %R[[[",
+"[[[[r F[[M +---* z[[(3 %R[[[",
+"[[[[r OF[[M k[[(3 %R[[[",
+"[[[[r F[[JsffffffffffffffffffffffaC[[(3 %R[[[",
+"[[[[w S[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[(3 %R[[[",
+"[[[)w c[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[KO %R[[[",
+"[[[[y ,C))))))))))))))))))))))))))))Iq *W[[[",
+"[[[[h O5007007007070000707007007007+ w[[[[",
+"[[[[P* n[[[[",
+"[[[[[MO g[[[[[",
+"{[[[[[Fp<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-rN[[[[[{",
+"{[[[[[[[(!!W!W!!!W!W!!W!!!!W!!W!!!!W!!!![[[[[[[{",
+"{{[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{{",
+"{{{[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{{{",
+"{{{{[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{{{{",
+"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{"
+};
diff --git a/applets/icons/minitime.png b/applets/icons/minitime.png
new file mode 100644
index 0000000..521b3e4
--- /dev/null
+++ b/applets/icons/minitime.png
Binary files differ
diff --git a/applets/icons/minitimestrip.xpm b/applets/icons/minitimestrip.xpm
new file mode 100644
index 0000000..333207b
--- /dev/null
+++ b/applets/icons/minitimestrip.xpm
@@ -0,0 +1,18 @@
+/* XPM */
+static char * minitimestrip_xpm[] = {
+"122 11 4 1",
+" c None",
+". c #E5EAC9",
+"+ c #686868",
+"@ c #D6D4AD",
+"..........................................................................................................................",
+"..++++...@@@@@.@++++@.@++++@.@@@@@@.@++++@.@++++@.@++++@.@++++@.@++++@................++++....++++.........++++....++++...",
+".+....+.@....+.@....+.@....+.+....+.+....@.+....@.@....+.+....+.+....+..@+...........+....+..+....+...@+..+....+..+....+..",
+".+....+.@....+.@....+.@....+.+....+.+....@.+....@.@....+.+....+.+....+..@+.......+...+....+..+....+...@+..+....+..+....+..",
+".+....+.@....+.@....+.@....+.+....+.+....@.+....@.@....+.+....+.+....+...........+...+....+..+....+.......+....+..+....+..",
+".@@@@@@..@@@@@.@++++@.@++++@.@++++@.@++++@.@++++@..@@@@@.@++++@.@++++@.........+++++.@@@@@@..@@@@@@.......@@@@@@..@@@@@@..",
+".+....+.@....+.+....@.@....+.@....+.@....+.+....+.@....+.+....+.@....+...........+...+....+..+....+.......+....+..+....+..",
+".+....+.@....+.+....@.@....+.@....+.@....+.+....+.@....+.+....+.@....+..@+.......+...+....+..+....+...@+..+....+..+....+..",
+".+....+.@....+.+....@.@....+.@....+.@....+.+....+.@....+.+....+.@....+..@+...........+....+..+....+...@+..+....+..+....+..",
+"..++++...@@@@@.@++++@.@++++@..@@@@@.@++++@.@++++@..@@@@@.@++++@.@++++@................++++....++++.........++++....++++...",
+".........................................................................................................................."};
diff --git a/applets/icons/miniwave-icon.png b/applets/icons/miniwave-icon.png
new file mode 100644
index 0000000..59ffc3d
--- /dev/null
+++ b/applets/icons/miniwave-icon.png
Binary files differ
diff --git a/applets/icons/miniwave.xpm b/applets/icons/miniwave.xpm
new file mode 100644
index 0000000..c096c7c
--- /dev/null
+++ b/applets/icons/miniwave.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static char * miniwave_xpm[] = {
+"16 16 2 1",
+" s None c None",
+". c #000000",
+" ",
+" ",
+" . ",
+" . . ",
+" . . ",
+" . . . . ",
+" . . . . . . ",
+" . . . . . . ",
+".. . . . . . ..",
+" . . . . . ",
+" . . . . ",
+" . . . . ",
+" . . ",
+" ",
+" ",
+" "};
diff --git a/applets/icons/no-link-0.png b/applets/icons/no-link-0.png
new file mode 100644
index 0000000..519b69c
--- /dev/null
+++ b/applets/icons/no-link-0.png
Binary files differ
diff --git a/applets/icons/no-link-0.xpm b/applets/icons/no-link-0.xpm
new file mode 100644
index 0000000..a007019
--- /dev/null
+++ b/applets/icons/no-link-0.xpm
@@ -0,0 +1,62 @@
+/* XPM */
+static char *no-link-0[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 8 1",
+" c black",
+". c #3F3F3F",
+"X c gray50",
+"o c gray75",
+"O c gray81",
+"+ c #DFDFDF",
+"@ c gray100",
+"# c None",
+/* pixels */
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"#####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####",
+"####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###",
+"####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###",
+"####@@@O.......O@@@@O.......O@@@@O.......O@@@###",
+"####@@@o o@@@@o o@@@@o o@@@###",
+"####@@@o o@@@@o o@@@@o o@@@###",
+"####@@@o o@@@@o o@@@@o o@@@###",
+"####@@@o o@@@@o o@@@@o o@@@###",
+"####@@@o o@@@@o o@@@@o o@@@###",
+"####@@@+XXXXXXX+@@@@+XXXXXXX+@@@@+XXXXXXX+@@@###",
+"####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###",
+"####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###",
+"#####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################",
+"################################################"
+};
diff --git a/applets/icons/oval_filled.xpm b/applets/icons/oval_filled.xpm
new file mode 100644
index 0000000..9819898
--- /dev/null
+++ b/applets/icons/oval_filled.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * oval_filled_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #969696",
+"# c #c8c8c8",
+".###############",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+". #",
+"................"}; \ No newline at end of file
diff --git a/applets/icons/signal-1-40.png b/applets/icons/signal-1-40.png
new file mode 100644
index 0000000..5125086
--- /dev/null
+++ b/applets/icons/signal-1-40.png
Binary files differ
diff --git a/applets/icons/signal-1-40.xpm b/applets/icons/signal-1-40.xpm
new file mode 100644
index 0000000..a19b298
--- /dev/null
+++ b/applets/icons/signal-1-40.xpm
@@ -0,0 +1,127 @@
+/* XPM */
+static char *signal-1-40[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 73 1",
+" c black",
+". c #020202",
+"X c gray1",
+"o c gray2",
+"O c #060606",
+"+ c #070707",
+"@ c gray3",
+"# c #111111",
+"$ c #131313",
+"% c gray9",
+"& c gray13",
+"* c gray20",
+"= c gray22",
+"- c gray24",
+"; c #3F3F3F",
+": c gray26",
+"> c #434343",
+", c #494949",
+"< c gray29",
+"1 c #4B4B4B",
+"2 c gray31",
+"3 c #5A5A5A",
+"4 c #646464",
+"5 c gray40",
+"6 c #6A6A6A",
+"7 c gray42",
+"8 c #6D6D6D",
+"9 c #797979",
+"0 c gray49",
+"q c #7E7E7E",
+"w c gray50",
+"e c #FCF000",
+"r c #FDF43F",
+"t c #FDF77F",
+"y c #8D8D8D",
+"u c #929292",
+"i c gray63",
+"p c gray64",
+"a c gray66",
+"s c #A9A9A9",
+"d c #AAAAAA",
+"f c #ACACAC",
+"g c #B7B7B7",
+"h c gray",
+"j c gray75",
+"k c #FEFBBF",
+"l c #C1C1C1",
+"z c #CBCBCB",
+"x c gray80",
+"c c #CDCDCD",
+"v c #CECECE",
+"b c gray81",
+"n c #D5D5D5",
+"m c gray85",
+"M c gray86",
+"N c gray87",
+"B c #DFDFDF",
+"V c #FEFCCF",
+"C c #FFFDDF",
+"Z c #E4E4E4",
+"A c #ECECEC",
+"S c gray93",
+"D c #EEEEEE",
+"F c #EFEFEF",
+"G c gray94",
+"H c #F3F3F3",
+"J c #F4F4F4",
+"K c gray98",
+"L c gray99",
+"P c #FDFDFD",
+"I c #FEFEFE",
+"U c gray100",
+"Y c None",
+/* pixels */
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYUUUUUUUUUUUUUUYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYUUUUUUUUUUUUUUUUUUYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYUUUUUUUKSmvvmGUUUUUUUUYYYYYYYYYYYY",
+"YYYYYYYYYYYYYUUUUUZi5*#OO O#=7aSUUUUUYYYYYYYYYYY",
+"YYYYYYYYYYYYYUUUHq% &uUUUUYYYYYYYYYYY",
+"YYYYYYYYYYYYUUUG, @:qalvvji9-O 5KUUUYYYYYYYYYY",
+"YYYYYYYYYYYYUUUy 8nUUUUUUUUUUz3 aUUUYYYYYYYYYY",
+"YYYYYYYYYYYYUUU2 5UUUUUUUUUUUUUU: 7UUUYYYYYYYYYY",
+"YYYYYUUUUUUUUUUf,vUUUUUSBBGUUUUUg,lUUUUUUUUUYYYY",
+"YYYYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYY",
+"YYYYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYY",
+"YYYYUUUVrrrrrrrVUUUUv:-:----vUUUUn--:--:-vUUUYYY",
+"YYYYUUUkeeeeeeekUUUUj jUUUUj lUUUYYY",
+"YYYYUUUkeeeeeeekUUUUj jUUUUj jUUUYYY",
+"YYYYUUUkeeeeeeekUUUUj jUUUUj jUUUYYY",
+"YYYYUUUkeeeeeeekUUUUj jUUUUj jUUUYYY",
+"YYYYUUUkeeeeeeekUUUUl lUUUUj jUUUYYY",
+"YYYYUUUCtttttttCUUUUBwwqwqwqBUUUUBwqwwwqqBUUUYYY",
+"YYYYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYY",
+"YYYYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYY",
+"YYYYYUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
+"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
+};
diff --git a/applets/icons/signal-41-60.png b/applets/icons/signal-41-60.png
new file mode 100644
index 0000000..5ac580e
--- /dev/null
+++ b/applets/icons/signal-41-60.png
Binary files differ
diff --git a/applets/icons/signal-41-60.xpm b/applets/icons/signal-41-60.xpm
new file mode 100644
index 0000000..3d2956c
--- /dev/null
+++ b/applets/icons/signal-41-60.xpm
@@ -0,0 +1,169 @@
+/* XPM */
+static char *signal-41-60[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 115 2",
+" c black",
+". c #010101",
+"X c #020202",
+"o c gray1",
+"O c #040404",
+"+ c #060606",
+"@ c #070707",
+"# c #0B0B0B",
+"$ c #0C0C0C",
+"% c gray6",
+"& c #111111",
+"* c #131313",
+"= c #151515",
+"- c #1B1B1B",
+"; c #1D1D1D",
+": c #1E1E1E",
+"> c gray12",
+", c #202020",
+"< c gray13",
+"1 c #222222",
+"2 c #252525",
+"3 c #272727",
+"4 c #2A2A2A",
+"5 c gray17",
+"6 c #2D2D2D",
+"7 c #343434",
+"8 c #353535",
+"9 c gray21",
+"0 c gray22",
+"q c #3E3E3E",
+"w c #3F3F3F",
+"e c #444444",
+"r c #515151",
+"t c gray32",
+"y c gray34",
+"u c gray35",
+"i c #5A5A5A",
+"p c #5B5B5B",
+"a c gray36",
+"s c #5D5D5D",
+"d c gray37",
+"f c #626262",
+"g c gray39",
+"h c DimGray",
+"j c #6D6D6D",
+"k c gray44",
+"l c gray46",
+"z c #767676",
+"x c #777777",
+"c c #797979",
+"v c gray48",
+"b c gray49",
+"n c gray50",
+"m c #FCF000",
+"M c #FDF43F",
+"N c #FDF77F",
+"B c #808080",
+"V c #868686",
+"C c gray53",
+"Z c #898989",
+"A c #8B8B8B",
+"S c #8D8D8D",
+"D c #929292",
+"F c #939393",
+"G c gray59",
+"H c #A2A2A2",
+"J c #A4A4A4",
+"K c #A7A7A7",
+"L c gray66",
+"P c #AFAFAF",
+"I c #B9B9B9",
+"U c gray73",
+"Y c #BBBBBB",
+"T c #BCBCBC",
+"R c gray75",
+"E c #FEFBBF",
+"W c #C3C3C3",
+"Q c gray77",
+"! c #C5C5C5",
+"~ c gray78",
+"^ c #C8C8C8",
+"/ c gray79",
+"( c #CECECE",
+") c gray81",
+"_ c gray82",
+"` c LightGray",
+"' c gray83",
+"] c #D5D5D5",
+"[ c gray84",
+"{ c #D7D7D7",
+"} c #DADADA",
+"| c gainsboro",
+" . c #DFDFDF",
+".. c #FEFCCF",
+"X. c #FFFDDF",
+"o. c #E1E1E1",
+"O. c #E2E2E2",
+"+. c gray89",
+"@. c #E7E7E7",
+"#. c #E9E9E9",
+"$. c #EAEAEA",
+"%. c gray92",
+"&. c #F1F1F1",
+"*. c gray95",
+"=. c #F3F3F3",
+"-. c #F4F4F4",
+";. c gray96",
+":. c gray97",
+">. c #F8F8F8",
+",. c gray98",
+"<. c #FBFBFB",
+"1. c gray99",
+"2. c #FEFEFE",
+"3. c gray100",
+"4. c None",
+/* pixels */
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.3.=.@.} ` ` | %.=.3.3.3.3.3.3.3.3.3.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.*.U B y 9 - # O O O # $ : 9 i C W =.3.3.3.3.3.3.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.3.3.3.3.3.~ h 1 4 x } 3.3.3.3.3.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.3.3.3.3.+.s O O 6 f Z L R ~ ( ( ~ U J C s 2 * v =.3.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.3.3.3.` 6 6 Z _ :.3.3.3.3.3.3.3.3.3.3.3.3.=.~ n 1 q +.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.=.9 $ D *.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.@.v r 3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.L $ U 3.3.3.3.3.*.R S j i r r s k D ~ =.3.3.3.3.3.G ~ 3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.n e 3.3.3.3._ h 1 2 x O.3.3.3.:.= L 3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.` s P 3.3.3.H * 1 e i f f y q : 1 U 3.3.3.G g +.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.U : v ~ =.3.3.3.3.3.3.*.W k * * ` 3.3.3.3.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.i 9 O.3.3.3.3.3.3.3.3.3.3.3.3.` : x 3.3.3.3.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.v # L 3.3.3.3.3.3.3.3.3.3.3.3.3.3.C # D 3.3.3.3.3.3.3.3.3.4.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.3.3.3...M M M M M M M ..3.3.3.3...M M M M M M M ..3.3.3.3._ q q q q e q q ( 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R W 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.X.N N N N N N N X.3.3.3.3.X.N N N N N N N X.3.3.3.3.| n n n n n n n | 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4."
+};
diff --git a/applets/icons/signal-61-80.png b/applets/icons/signal-61-80.png
new file mode 100644
index 0000000..254a04a
--- /dev/null
+++ b/applets/icons/signal-61-80.png
Binary files differ
diff --git a/applets/icons/signal-61-80.xpm b/applets/icons/signal-61-80.xpm
new file mode 100644
index 0000000..504dde8
--- /dev/null
+++ b/applets/icons/signal-61-80.xpm
@@ -0,0 +1,169 @@
+/* XPM */
+static char *signal-61-80[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 115 2",
+" c black",
+". c #010101",
+"X c #020202",
+"o c gray1",
+"O c #040404",
+"+ c #060606",
+"@ c #070707",
+"# c #0B0B0B",
+"$ c #0C0C0C",
+"% c gray6",
+"& c #111111",
+"* c #131313",
+"= c #151515",
+"- c #1B1B1B",
+"; c #1D1D1D",
+": c #1E1E1E",
+"> c gray12",
+", c #202020",
+"< c gray13",
+"1 c #222222",
+"2 c #252525",
+"3 c #272727",
+"4 c #2A2A2A",
+"5 c gray17",
+"6 c #2D2D2D",
+"7 c #343434",
+"8 c #353535",
+"9 c gray21",
+"0 c gray22",
+"q c #3E3E3E",
+"w c #3F3F3F",
+"e c #444444",
+"r c #515151",
+"t c gray32",
+"y c gray34",
+"u c gray35",
+"i c #5A5A5A",
+"p c #5B5B5B",
+"a c gray36",
+"s c #5D5D5D",
+"d c gray37",
+"f c #626262",
+"g c gray39",
+"h c DimGray",
+"j c #6D6D6D",
+"k c gray44",
+"l c gray46",
+"z c #767676",
+"x c #777777",
+"c c #797979",
+"v c gray48",
+"b c gray49",
+"n c gray50",
+"m c green",
+"M c #3FFF3F",
+"N c #7FFF7F",
+"B c #808080",
+"V c #868686",
+"C c gray53",
+"Z c #898989",
+"A c #8B8B8B",
+"S c #8D8D8D",
+"D c #929292",
+"F c #939393",
+"G c gray59",
+"H c #A2A2A2",
+"J c #A4A4A4",
+"K c #A7A7A7",
+"L c gray66",
+"P c #AFAFAF",
+"I c #B9B9B9",
+"U c gray73",
+"Y c #BBBBBB",
+"T c #BCBCBC",
+"R c gray75",
+"E c #BFFFBF",
+"W c #C3C3C3",
+"Q c gray77",
+"! c #C5C5C5",
+"~ c gray78",
+"^ c #C8C8C8",
+"/ c gray79",
+"( c #CECECE",
+") c gray81",
+"_ c gray82",
+"` c LightGray",
+"' c gray83",
+"] c #D5D5D5",
+"[ c gray84",
+"{ c #D7D7D7",
+"} c #DADADA",
+"| c gainsboro",
+" . c #DFDFDF",
+".. c #CFFFCF",
+"X. c #DFFFDF",
+"o. c #E1E1E1",
+"O. c #E2E2E2",
+"+. c gray89",
+"@. c #E7E7E7",
+"#. c #E9E9E9",
+"$. c #EAEAEA",
+"%. c gray92",
+"&. c #F1F1F1",
+"*. c gray95",
+"=. c #F3F3F3",
+"-. c #F4F4F4",
+";. c gray96",
+":. c gray97",
+">. c #F8F8F8",
+",. c gray98",
+"<. c #FBFBFB",
+"1. c gray99",
+"2. c #FEFEFE",
+"3. c gray100",
+"4. c None",
+/* pixels */
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.3.=.@.} ` ` | %.=.3.3.3.3.3.3.3.3.3.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.3.3.3.3.3.3.*.U B y 9 - # O O O # $ : 9 i C W =.3.3.3.3.3.3.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.3.3.3.3.3.~ h 1 4 x } 3.3.3.3.3.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.3.3.3.3.+.s O O 6 f Z L R ~ ( ( ~ U J C s 2 * v =.3.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.3.3.3.` 6 6 Z _ :.3.3.3.3.3.3.3.3.3.3.3.3.=.~ n 1 q +.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.=.9 $ D *.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.@.v r 3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.L $ U 3.3.3.3.3.*.R S j i r r s k D ~ =.3.3.3.3.3.G ~ 3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.n e 3.3.3.3._ h 1 2 x O.3.3.3.:.= L 3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.` s P 3.3.3.H * 1 e i f f y q : 1 U 3.3.3.G g +.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.3.3.3.3.3.3.3.U : v ~ =.3.3.3.3.3.3.*.W k * * ` 3.3.3.3.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.3.3.3.3.3.3.3.3.i 9 O.3.3.3.3.3.3.3.3.3.3.3.3.` : x 3.3.3.3.3.3.3.4.4.4.4.4.4.",
+"4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.v # L 3.3.3.3.3.3.3.3.3.3.3.3.3.3.C # D 3.3.3.3.3.3.3.3.3.4.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.3.3.3...M M M M M M M ..3.3.3.3...M M M M M M M ..3.3.3.3._ q q q q e q q ( 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R R 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.E m m m m m m m E 3.3.3.3.E m m m m m m m E 3.3.3.3.R W 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.X.N N N N N N N X.3.3.3.3.X.N N N N N N N X.3.3.3.3.| n n n n n n n | 3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.",
+"4.4.4.4.4.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.",
+"4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4."
+};
diff --git a/applets/icons/signal-81-100.png b/applets/icons/signal-81-100.png
new file mode 100644
index 0000000..2b18778
--- /dev/null
+++ b/applets/icons/signal-81-100.png
Binary files differ
diff --git a/applets/icons/signal-81-100.xpm b/applets/icons/signal-81-100.xpm
new file mode 100644
index 0000000..86f3459
--- /dev/null
+++ b/applets/icons/signal-81-100.xpm
@@ -0,0 +1,219 @@
+/* XPM */
+static char *signal-81-100[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 165 2",
+" c black",
+". c #010101",
+"X c #020202",
+"o c gray1",
+"O c #040404",
+"+ c gray2",
+"@ c #060606",
+"# c #070707",
+"$ c gray3",
+"% c #090909",
+"& c gray4",
+"* c #0B0B0B",
+"= c gray6",
+"- c gray8",
+"; c gray9",
+": c #191919",
+"> c #1B1B1B",
+", c #1D1D1D",
+"< c #1E1E1E",
+"1 c gray12",
+"2 c #202020",
+"3 c gray13",
+"4 c gray14",
+"5 c #282828",
+"6 c gray16",
+"7 c #2A2A2A",
+"8 c #2C2C2C",
+"9 c gray18",
+"0 c #2F2F2F",
+"q c gray19",
+"w c #313131",
+"e c #343434",
+"r c #353535",
+"t c gray21",
+"y c #373737",
+"u c gray22",
+"i c #393939",
+"p c #3A3A3A",
+"a c gray23",
+"s c gray24",
+"d c gray25",
+"f c #414141",
+"g c #434343",
+"h c #484848",
+"j c #494949",
+"k c #4B4B4B",
+"l c #4C4C4C",
+"z c #4E4E4E",
+"x c gray31",
+"c c #505050",
+"v c #515151",
+"b c gray33",
+"n c #555555",
+"m c #585858",
+"M c #5D5D5D",
+"N c gray38",
+"B c #646464",
+"V c #656565",
+"C c #686868",
+"Z c DimGray",
+"A c #6A6A6A",
+"S c #6C6C6C",
+"D c #6D6D6D",
+"F c #6F6F6F",
+"G c gray44",
+"H c #717171",
+"J c gray45",
+"K c #747474",
+"L c #767676",
+"P c #797979",
+"I c #7C7C7C",
+"U c gray49",
+"Y c gray50",
+"T c green",
+"R c #3FFF3F",
+"E c #7FFF7F",
+"W c gray51",
+"Q c #848484",
+"! c gray52",
+"~ c #868686",
+"^ c gray53",
+"/ c #888888",
+"( c gray54",
+") c gray55",
+"_ c #8E8E8E",
+"` c gray56",
+"' c #959595",
+"] c gray59",
+"[ c #979797",
+"{ c gray60",
+"} c #9A9A9A",
+"| c #9D9D9D",
+" . c #9F9F9F",
+".. c #A0A0A0",
+"X. c gray63",
+"o. c gray64",
+"O. c #A7A7A7",
+"+. c gray66",
+"@. c #A9A9A9",
+"#. c #AAAAAA",
+"$. c gray67",
+"%. c #ACACAC",
+"&. c gray68",
+"*. c #AFAFAF",
+"=. c #B2B2B2",
+"-. c gray70",
+";. c gray71",
+":. c #B7B7B7",
+">. c gray72",
+",. c gray73",
+"<. c #BBBBBB",
+"1. c #BCBCBC",
+"2. c gray74",
+"3. c gray75",
+"4. c #BFFFBF",
+"5. c #C0C0C0",
+"6. c #C1C1C1",
+"7. c gray76",
+"8. c #C5C5C5",
+"9. c #C6C6C6",
+"0. c #C8C8C8",
+"q. c gray79",
+"w. c #CACACA",
+"e. c #CBCBCB",
+"r. c gray80",
+"t. c #CDCDCD",
+"y. c #CECECE",
+"u. c gray81",
+"i. c gray82",
+"p. c #D2D2D2",
+"a. c LightGray",
+"s. c #D5D5D5",
+"d. c #D8D8D8",
+"f. c #DADADA",
+"g. c gray86",
+"h. c gainsboro",
+"j. c gray87",
+"k. c #CFFFCF",
+"l. c #DFFFDF",
+"z. c gray88",
+"x. c #E1E1E1",
+"c. c gray89",
+"v. c gray90",
+"b. c #E7E7E7",
+"n. c gray91",
+"m. c #E9E9E9",
+"M. c gray92",
+"N. c #ECECEC",
+"B. c gray93",
+"V. c gray94",
+"C. c #F1F1F1",
+"Z. c gray95",
+"A. c #F3F3F3",
+"S. c #F4F4F4",
+"D. c #F6F6F6",
+"F. c gray97",
+"G. c #F8F8F8",
+"H. c #F9F9F9",
+"J. c gray98",
+"K. c #FBFBFB",
+"L. c gray99",
+"P. c #FDFDFD",
+"I. c #FEFEFE",
+"U. c gray100",
+"Y. c None",
+/* pixels */
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.K.C.z.a.w.7.7.8.r.h.B.F.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.U.K.g.@.Y b w - $ O - 4 z L .r.K.U.U.U.U.U.U.U.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.r.W y $ $ $ $ $ O 6 H ,.K.U.U.U.U.U.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.U.U.U.U.U.;.j O - a V ! o.2.r.h.v.v.h.a.7.@._ F h > y .F.U.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.U.g.b 6 F =.M.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.C.7.Y y y 8.U.U.U.U.Y.Y.",
+"Y.Y.Y.U.U.U.U.8.3 d @.F.U.U.U.U.U.U.U.U.U.U.K.K.U.U.U.U.U.U.U.U.U.U.K.7.b = o.U.U.U.U.Y.",
+"Y.Y.Y.U.U.U.g.> - .U.U.U.U.U.U.K.a.@.! C c d y y a j N Y o.w.C.U.U.U.U.U.U.,.w =.U.U.U.Y.",
+"Y.Y.Y.U.U.U.c < i.U.U.U.U.U.w.P w O 3 C ;.K.U.U.U.U.M.y 0 F.U.U.Y.",
+"Y.Y.Y.U.U.z.$ o.U.U.U.U.8.z O - i b F Y ! ! Y H M d < i =.U.U.U.U.i.$ ,.U.U.Y.",
+"Y.Y.Y.U.U.r. z.U.U.U.[ $ 0 L ,.B.U.U.U.U.U.U.U.U.U.U.C.w.! a F K.U.U.U.0 { U.U.Y.",
+"Y.Y.Y.U.U.F.W _ K.U.U.{ y %.K.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.8.c F U.U.U.%.H M.U.U.Y.",
+"Y.Y.Y.U.U.U.U.U.U.U.C.< c C.U.U.U.U.U.F.g.=.{ _ / [ %.r.C.U.U.U.U.U.U.L O a.U.U.U.U.U.U.U.Y.",
+"Y.Y.Y.U.U.U.U.U.U.U.r. i.U.U.U.U.2.V 6 O < b O.F.U.U.U.K.< [ U.U.U.U.U.U.U.Y.",
+"Y.Y.Y.Y.Y.U.U.U.U.U.M.i z K.U.U.M.n $ < 0 w 3 = i r.U.U.U.Y 0 r.U.U.U.U.U.U.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.U.U.U.U.K.U.U.U.C.i y / 7.M.C.K.K.F.M.w.{ z < h.U.U.U.K.U.U.U.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.@. [ K.U.U.U.U.U.U.U.U.U.U.U.,.< H U.U.U.U.U.U.U.U.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.U. . j U.U.U.U.U.U.U.U.U.U.U.U.U.U.! C U.U.U.U.U.U.U.U.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.K.%.z.U.U.U.U.U.U.U.U.U.U.K.U.U.U.C.%.M.U.U.U.U.U.U.U.U.U.Y.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.k.R R R R R R R k.U.U.U.U.k.R R R R R R R k.U.U.U.U.k.R R R R R R R k.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.U.4.T T T T T T T 4.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.l.E E E E E E E l.U.U.U.U.l.E E E E E E E l.U.U.U.U.l.E E E E E E E l.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.",
+"Y.Y.Y.Y.Y.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.U.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.",
+"Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y.Y."
+};
diff --git a/applets/icons/term.png b/applets/icons/term.png
new file mode 100644
index 0000000..abfe540
--- /dev/null
+++ b/applets/icons/term.png
Binary files differ
diff --git a/applets/mb-applet-battery.c b/applets/mb-applet-battery.c
new file mode 100644
index 0000000..af9970b
--- /dev/null
+++ b/applets/mb-applet-battery.c
@@ -0,0 +1,482 @@
+/* miniapm - A tiny battery monitor
+
+ Copyright 2002 Matthew Allum
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#include <libmb/mb.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(text) gettext(text)
+#else
+# define _(text) (text)
+#endif
+
+#ifdef USE_LIBSN
+#define SN_API_NOT_YET_FROZEN 1
+#include <libsn/sn.h>
+#endif
+
+#ifdef HAVE_APM_H /* Linux */
+#include <apm.h>
+#endif
+
+#ifdef HAVE_APMVAR_H /* *BSD */
+#include <err.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <machine/apmvar.h>
+
+#define APMDEV "/dev/apm"
+
+enum apm_state {
+ NORMAL,
+ SUSPENDING,
+ STANDING_BY
+};
+
+struct apm_reply {
+ int vno;
+ enum apm_state newstate;
+ struct apm_power_info batterystate;
+};
+
+#endif
+
+#define TIME_LEFT 0
+#define PERCENTAGE 1
+#define AC_POWER 2
+
+#define WIN_WIDTH 8
+#define WIN_HEIGHT 14
+
+#define CLOCK_DISP 1
+#define BATT_DISP 0
+
+#ifndef AC_LINE_STATUS_ON
+#define AC_LINE_STATUS_ON 1
+#endif
+
+#ifdef USE_PNG
+#define MINIAPM_IMG "miniapm.png"
+#define MINIAPM_PWR_IMG "miniapm-power.png"
+#else
+#define MINIAPM_IMG "miniapm.xpm"
+#define MINIAPM_PWR_IMG "miniapm-power.xpm"
+#endif
+
+#define CONTEXT_APP "/usr/bin/gpe-info"
+#define CONTEXT_APP_ARGS "battery"
+#define CONTEXT_APP_WANT_SN 1
+
+static int apm_vals[3];
+static MBPixbuf *pb;
+static MBPixbufImage *img_icon = NULL, *img_icon_scaled = NULL,
+ *img_icon_pwr = NULL, *img_icon_pwr_scaled = NULL;
+
+
+static int time_left_alerts[] = { 0, 2, 5, 10, 20 }; /* times to alert on */
+static int time_left_idx = 4;
+
+static Bool ac_power = False;
+
+static char* ThemeName = NULL;
+
+static int last_percentage, last_ac;
+
+#ifdef USE_LIBSN
+
+static SnDisplay *sn_dpy;
+
+static void
+sn_activate(char *name, char *exec_str)
+{
+ SnLauncherContext *context;
+ pid_t child_pid = 0;
+
+ context = sn_launcher_context_new (sn_dpy, 0);
+
+ sn_launcher_context_set_name (context, name);
+ sn_launcher_context_set_binary_name (context, exec_str);
+
+ sn_launcher_context_initiate (context, "monoluanch launch", exec_str,
+ CurrentTime);
+
+ switch ((child_pid = fork ()))
+ {
+ case -1:
+ fprintf (stderr, "Fork failed\n" );
+ break;
+ case 0:
+ sn_launcher_context_setup_child_process (context);
+ mb_exec(exec_str);
+ fprintf (stderr, "Failed to exec %s \n", exec_str);
+ _exit (1);
+ break;
+ }
+}
+
+#endif
+
+
+#ifdef HAVE_APM_H
+
+static int
+read_apm(int *values)
+{
+ /* add stat function here ? */
+
+ apm_info info;
+ apm_read(&info);
+
+ values[TIME_LEFT] = info.battery_time;
+ values[PERCENTAGE] = info.battery_percentage;
+ values[AC_POWER] = info.ac_line_status;
+
+ return 1;
+}
+
+#else /* BSD */
+
+static int
+read_apm(int *values)
+{
+ int fd;
+ struct apm_reply reply;
+ struct apm_power_info *api = &reply.batterystate;
+
+ /* open the device directly and get status */
+ fd = open(APMDEV, O_RDONLY);
+ if (fd == -1)
+ return 0;
+ memset(&reply, 0, sizeof(reply));
+ if (ioctl(fd, APM_IOC_GETPOWER, &reply.batterystate) == -1) {
+ close (fd);
+ return 0;
+ }
+ close (fd);
+
+ values[TIME_LEFT] = api->minutes_left;
+ values[PERCENTAGE] = api->battery_life;
+ values[AC_POWER] = api->ac_state;
+
+ return 1;
+}
+
+#endif
+
+void
+fork_exec(char *cmd)
+{
+ switch (fork())
+ {
+ case 0:
+ setpgid(0, 0); /* Stop us killing child */
+ mb_exec(cmd);
+ fprintf(stderr, "minitime: Failed to Launch '%s'", cmd);
+ exit(1);
+ case -1:
+ fprintf(stderr, "minitime: Failed to Launch '%s'", cmd);
+ break;
+ }
+}
+
+void
+paint_callback (MBTrayApp *app, Drawable drw )
+{
+
+
+ int power_pixels = 0;
+ unsigned char r = 0, g = 0, b = 0;
+ int x, y;
+ int bar_width, bar_height, bar_x, bar_y;
+
+ MBPixbufImage *img_backing = NULL;
+
+
+
+
+ while (!read_apm(apm_vals))
+ usleep(50000L);
+
+ if (last_percentage == apm_vals[PERCENTAGE] && last_ac == apm_vals[AC_POWER])
+ return;
+
+ img_backing = mb_tray_app_get_background (app, pb);
+
+ /* we assume width = height */
+ bar_width = (mb_pixbuf_img_get_width(img_backing)/16) * 10;
+ bar_height = (mb_pixbuf_img_get_width(img_backing)/16) * 2;
+ bar_y = (mb_pixbuf_img_get_width(img_backing)/4)*3;
+ bar_x = (mb_pixbuf_img_get_width(img_backing)/4) - (mb_pixbuf_img_get_width(img_backing)/16);
+
+ /*
+ printf("bar: %ix%i +%i+%i (%i)\n", bar_width, bar_height, bar_x, bar_y, mb_pixbuf_img_get_width(img_backing) );
+ */
+
+ if (apm_vals[PERCENTAGE] <= 0 || apm_vals[PERCENTAGE] > 99)
+ {
+ r = 0x66; g = 0xff; b = 0x33; ac_power = True;
+ apm_vals[PERCENTAGE] = -1;
+ }
+ else if (apm_vals[PERCENTAGE] <= 25)
+ { r = 0xff; g = 0; b = 0; }
+ else if (apm_vals[PERCENTAGE] <= 50)
+ { r = 0xff; g = 0x99; b = 0x33; }
+ else if (apm_vals[PERCENTAGE] <= 100)
+ { r = 0x66; g = 0xff; b = 0x33; }
+
+ if (apm_vals[AC_POWER] == AC_LINE_STATUS_ON)
+ ac_power = True;
+ else
+ ac_power = False;
+
+ if (ac_power)
+ mb_pixbuf_img_composite(pb, img_backing, img_icon_pwr_scaled, 0, 0);
+ else
+ mb_pixbuf_img_composite(pb, img_backing, img_icon_scaled, 0, 0);
+
+ /* Clear out bar first */
+ for ( y = bar_y; y < bar_y + bar_height; y++)
+ for ( x = bar_x; x < bar_x + bar_width; x++)
+ if (ac_power)
+ {
+ mb_pixbuf_img_plot_pixel(pb, img_backing, x, y, 0xff, 0xff, 0);
+ }
+ else
+ {
+ mb_pixbuf_img_plot_pixel(pb, img_backing, x, y, 0, 0, 0);
+ }
+
+ if (apm_vals[PERCENTAGE] > 0)
+ {
+ power_pixels = (apm_vals[PERCENTAGE] * ( bar_width) )/ 100 ;
+
+ for ( y = bar_y; y < bar_y + bar_height; y++)
+ for ( x = bar_x; x < bar_x + power_pixels + 1; x++)
+ mb_pixbuf_img_plot_pixel(pb, img_backing, x, y, r, g, b);
+ }
+
+ /* Bubble alerts */
+ if ((time_left_idx > 0)
+ && !ac_power
+ && apm_vals[PERCENTAGE] > 0
+ && apm_vals[TIME_LEFT] > 0
+ && (apm_vals[TIME_LEFT] < time_left_alerts[time_left_idx]))
+ {
+ char tray_msg[256];
+ sprintf(tray_msg,
+ _("Battery power very low !\n\nTime Left: %.2i minutes"),
+ time_left_alerts[time_left_idx]);
+ mb_tray_app_tray_send_message(app, tray_msg, 0);
+ time_left_idx--;
+ }
+ else if (time_left_idx < 4
+ && apm_vals[TIME_LEFT] > time_left_alerts[time_left_idx+1])
+ {
+ time_left_idx++;
+ }
+
+ mb_pixbuf_img_render_to_drawable(pb, img_backing, drw, 0, 0);
+
+ mb_pixbuf_img_free( pb, img_backing );
+
+ last_percentage = apm_vals[PERCENTAGE];
+ last_ac = apm_vals[AC_POWER];
+
+}
+
+void
+resize_callback (MBTrayApp *app, int w, int h )
+{
+
+ if (img_icon_scaled) mb_pixbuf_img_free(pb, img_icon_scaled);
+ if (img_icon_pwr_scaled) mb_pixbuf_img_free(pb, img_icon_pwr_scaled);
+
+ last_percentage = -1; last_ac = -1;
+
+ img_icon_scaled = mb_pixbuf_img_scale(pb, img_icon, w, h);
+ img_icon_pwr_scaled = mb_pixbuf_img_scale(pb, img_icon_pwr, w, h);
+
+}
+
+void
+load_icon(void)
+{
+ char *icon_path = NULL;
+
+ printf("%s() called", __func__);
+
+ last_percentage = -1; last_ac = -1;
+
+ if (img_icon) mb_pixbuf_img_free(pb, img_icon);
+ if (img_icon_pwr) mb_pixbuf_img_free(pb, img_icon_pwr);
+
+ icon_path = mb_dot_desktop_icon_get_full_path (ThemeName,
+ 32,
+ MINIAPM_IMG );
+
+ if (icon_path == NULL
+ || !(img_icon = mb_pixbuf_img_new_from_file(pb, icon_path)))
+ {
+ fprintf(stderr, "miniapm: failed to load icon %s\n", MINIAPM_IMG);
+ exit(1);
+ }
+
+ free(icon_path);
+
+ icon_path = mb_dot_desktop_icon_get_full_path (ThemeName,
+ 32,
+ MINIAPM_PWR_IMG );
+
+ if (icon_path == NULL
+ || !(img_icon_pwr = mb_pixbuf_img_new_from_file(pb, icon_path)))
+ {
+ fprintf(stderr, "miniapm: failed to load icon %s\n", MINIAPM_PWR_IMG);
+ exit(1);
+ }
+
+ free(icon_path);
+
+ return;
+
+}
+
+void
+theme_callback (MBTrayApp *app, char *theme_name)
+{
+ if (!theme_name) return;
+ if (ThemeName) free(ThemeName);
+ ThemeName = strdup(theme_name);
+ load_icon();
+ resize_callback (app, mb_tray_app_width(app), mb_tray_app_width(app) );
+}
+
+void
+button_callback (MBTrayApp *app, int x, int y, Bool is_released )
+{
+ char tray_msg[256];
+
+ if (!is_released) return;
+
+ if (apm_vals[AC_POWER] == AC_LINE_STATUS_ON)
+ {
+ if (apm_vals[PERCENTAGE] > 0
+ && apm_vals[PERCENTAGE] < 100 )
+ sprintf(tray_msg, _("AC Connected\nCharging: %.2i %%\n")
+ , apm_vals[PERCENTAGE]);
+ else
+ sprintf(tray_msg, _("AC Connected\nFully charged.\n"));
+ } else {
+ if (apm_vals[PERCENTAGE] > 0
+ && apm_vals[PERCENTAGE] < 100
+ && apm_vals[TIME_LEFT] > 0)
+ {
+ sprintf(tray_msg,
+ _("Battery Power\nJuice %.2i %%\nTime left: %.2i mins\n"), apm_vals[PERCENTAGE], apm_vals[TIME_LEFT]);
+ }
+ else sprintf(tray_msg, _("Battery Power\n Device read error.\n"));
+ }
+ mb_tray_app_tray_send_message(app, tray_msg, 5000);
+
+}
+
+void
+timeout_callback ( MBTrayApp *app )
+{
+ mb_tray_app_repaint (app);
+}
+
+void
+context_callback ( MBTrayApp *app )
+{
+#ifdef USE_LIBSN
+ if (CONTEXT_APP_WANT_SN)
+ {
+ sn_activate(CONTEXT_APP, CONTEXT_APP " " CONTEXT_APP_ARGS);
+ return;
+ }
+#endif
+
+ fork_exec(CONTEXT_APP " " CONTEXT_APP_ARGS);
+}
+
+static Bool
+file_exists(char *filename)
+{
+ struct stat st; /* XXX Should probably check if exe too */
+ if (stat(filename, &st)) return False;
+ return True;
+}
+
+int
+main( int argc, char *argv[])
+{
+ MBTrayApp *app = NULL;
+ struct timeval tv;
+
+ printf("%s() called\n", __func__);
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, DATADIR "/locale");
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+ textdomain (PACKAGE);
+#endif
+
+
+ app = mb_tray_app_new ( _("Battery Monitor"),
+ resize_callback,
+ paint_callback,
+ &argc,
+ &argv );
+
+ pb = mb_pixbuf_new(mb_tray_app_xdisplay(app),
+ mb_tray_app_xscreen(app));
+
+ memset(&tv,0,sizeof(struct timeval));
+ tv.tv_sec = 10;
+
+ mb_tray_app_set_timeout_callback (app, timeout_callback, &tv);
+
+ mb_tray_app_set_button_callback (app, button_callback );
+
+ mb_tray_app_set_theme_change_callback (app, theme_callback );
+
+ load_icon();
+
+ mb_tray_app_set_icon(app, pb, img_icon);
+
+ if (file_exists(CONTEXT_APP))
+ {
+ mb_tray_app_set_context_info (app, _("More info"));
+
+ mb_tray_app_set_context_callback (app, context_callback);
+ }
+
+#ifdef USE_LIBSN
+ sn_dpy = sn_display_new (mb_tray_app_xdisplay(app), NULL, NULL);
+#endif
+
+
+
+ mb_tray_app_main (app);
+
+ return 1;
+}
+
+
diff --git a/applets/mb-applet-clock.c b/applets/mb-applet-clock.c
new file mode 100644
index 0000000..0569fb0
--- /dev/null
+++ b/applets/mb-applet-clock.c
@@ -0,0 +1,385 @@
+/*
+
+Minitime - A mini dockable clock.
+
+Copyright (c) 2003 Matthew Allum
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you use
+ this software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and
+ must not be misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <libmb/mb.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(text) gettext(text)
+#else
+# define _(text) (text)
+#endif
+
+#ifdef USE_LIBSN
+#define SN_API_NOT_YET_FROZEN 1
+#include <libsn/sn.h>
+#endif
+
+#define CONTEXT_APP "/usr/bin/gpe-conf"
+#define CONTEXT_APP_ARGS "time"
+#define CONTEXT_APP_WANT_SN 1
+
+MBFont *Fnt = NULL;
+MBDrawable *Drw = NULL;
+MBColor *Col = NULL;
+MBPixbuf *Pixbuf;
+
+void usage()
+{
+ exit(1);
+}
+
+#ifdef USE_LIBSN
+
+static SnDisplay *sn_dpy;
+
+static void
+sn_activate(char *name, char *exec_str)
+{
+ SnLauncherContext *context;
+ pid_t child_pid = 0;
+
+ context = sn_launcher_context_new (sn_dpy, 0);
+
+ sn_launcher_context_set_name (context, name);
+ sn_launcher_context_set_binary_name (context, exec_str);
+
+ sn_launcher_context_initiate (context, "monoluanch launch", exec_str,
+ CurrentTime);
+
+ switch ((child_pid = fork ()))
+ {
+ case -1:
+ fprintf (stderr, "Fork failed\n" );
+ break;
+ case 0:
+ sn_launcher_context_setup_child_process (context);
+ mb_exec(exec_str);
+ fprintf (stderr, "Failed to exec %s \n", exec_str);
+ _exit (1);
+ break;
+ }
+}
+
+#endif
+
+void
+fork_exec(char *cmd)
+{
+ switch (fork())
+ {
+ case 0:
+ setpgid(0, 0); /* Stop us killing child */
+ mb_exec(cmd);
+ fprintf(stderr, "minitime: Failed to Launch '%s'", cmd);
+ exit(1);
+ case -1:
+ fprintf(stderr, "minitime: Failed to Launch '%s'", cmd);
+ break;
+ }
+}
+
+
+static void
+set_fg_col(MBTrayApp *app, char* spec)
+{
+ mb_col_set (Col, spec);
+}
+
+
+void
+paint_callback ( MBTrayApp *app, Drawable pxm )
+{
+ struct timeval tv;
+ struct timezone tz;
+ struct tm *localTime = NULL;
+ time_t actualTime;
+ char timestr[5] = { 0 };
+ MBPixbufImage *img_bg = NULL;
+ MBDrawable *drw;
+
+ /* Figure out the actual time */
+ gettimeofday(&tv, &tz);
+ actualTime = tv.tv_sec;
+ localTime = localtime(&actualTime);
+
+ sprintf(timestr, _("%.2d:%.2d"), localTime->tm_hour, localTime->tm_min);
+
+ img_bg = mb_tray_app_get_background (app, Pixbuf);
+
+ drw = mb_drawable_new_from_pixmap(Pixbuf, pxm);
+
+ if (mb_tray_app_tray_is_vertical(app))
+ {
+ /*
+ - create a new HxW pixmap
+ - rotate background img +90 onto it
+ - render the text to it
+ - call drawable to pixbuf
+ - rotate the new pixbuf -90
+ */
+ MBDrawable *drw_rot;
+ MBPixbufImage *img_bg_rot, *img_txt, *img_txt_rot;
+
+ int font_y = ((mb_tray_app_width(app) - (mb_font_get_height(Fnt)))/2);
+
+ img_bg_rot = mb_pixbuf_img_transform (Pixbuf, img_bg,
+ MBPIXBUF_TRANS_ROTATE_90);
+
+ drw_rot = mb_drawable_new(Pixbuf,
+ mb_pixbuf_img_get_width(img_bg_rot),
+ mb_pixbuf_img_get_height(img_bg_rot));
+
+ mb_pixbuf_img_render_to_drawable (Pixbuf, img_bg_rot,
+ mb_drawable_pixmap(drw_rot), 0, 0);
+
+ mb_font_render_simple (Fnt,
+ drw_rot,
+ 1, font_y,
+ mb_pixbuf_img_get_width(img_bg_rot),
+ (unsigned char *) timestr,
+ MB_ENCODING_UTF8,
+ 0);
+
+ img_txt = mb_pixbuf_img_new_from_drawable (Pixbuf,
+ mb_drawable_pixmap(drw_rot),
+ None,
+ 0, 0,
+ mb_pixbuf_img_get_width(img_bg_rot),
+ mb_pixbuf_img_get_height(img_bg_rot));
+
+ img_txt_rot = mb_pixbuf_img_transform (Pixbuf, img_txt,
+ MBPIXBUF_TRANS_ROTATE_90);
+
+ mb_pixbuf_img_render_to_drawable (Pixbuf, img_txt_rot,
+ mb_drawable_pixmap(drw), 0, 0);
+
+ mb_pixbuf_img_free(Pixbuf, img_bg_rot);
+ mb_pixbuf_img_free(Pixbuf, img_txt);
+ mb_pixbuf_img_free(Pixbuf, img_txt_rot);
+
+ mb_drawable_unref(drw_rot);
+
+ } else {
+ int font_y = ((mb_tray_app_height(app) - (mb_font_get_height(Fnt)))/2);
+
+ mb_pixbuf_img_render_to_drawable (Pixbuf, img_bg,
+ mb_drawable_pixmap(drw), 0, 0);
+
+ mb_font_render_simple (Fnt,
+ drw,
+ 1, font_y,
+ mb_tray_app_width(app),
+ (unsigned char *) timestr,
+ MB_ENCODING_UTF8,
+ 0);
+ }
+
+ mb_pixbuf_img_free(Pixbuf, img_bg);
+ mb_drawable_unref(drw);
+
+}
+
+void
+button_callback (MBTrayApp *app, int x, int y, Bool is_released )
+{
+ if (is_released)
+ {
+ time_t now;
+ struct tm tm;
+ char buf[256];
+
+ now = time (0);
+ localtime_r(&now, &tm);
+ strftime (buf, sizeof (buf), _("%a %b %e %k:%M:%S %Y"), &tm);
+
+ mb_tray_app_tray_send_message(app, buf, 6000);
+ }
+}
+
+void
+resize_callback ( MBTrayApp *app, int w, int h )
+{
+ int req_size = 0;
+
+ mb_font_set_size_to_pixels (Fnt,
+ (mb_tray_app_tray_is_vertical(app) ? w : h),
+ NULL);
+
+ req_size = mb_font_get_txt_width (Fnt,
+ (unsigned char *) "99999", 5,
+ MB_ENCODING_UTF8);
+
+ if (mb_tray_app_tray_is_vertical(app))
+ {
+ mb_tray_app_request_size (app, w, req_size+2);
+ } else {
+ mb_tray_app_request_size (app, req_size+2, h);
+ }
+}
+
+void
+theme_change_callback (MBTrayApp *app, char *theme_name )
+{
+ char *theme_path = mb_util_get_theme_full_path(theme_name);
+
+ if (theme_path)
+ {
+ MBDotDesktop *theme = NULL;
+ char *theme_desktop_path = alloca(strlen(theme_path)+15);
+
+ sprintf(theme_desktop_path, "%s/theme.desktop", theme_path);
+
+ theme = mb_dotdesktop_new_from_file(theme_desktop_path);
+ if (theme)
+ {
+ /* Get the PanelFgColor key value if exists */
+ if (mb_dotdesktop_get(theme, "PanelFgColor"))
+ {
+ /* Set out font foreground color and repaint */
+ set_fg_col(app, mb_dotdesktop_get(theme, "PanelFgColor"));
+ }
+ mb_dotdesktop_free(theme);
+ }
+ free(theme_path);
+ }
+}
+
+void
+timeout_callback ( MBTrayApp *app )
+{
+ mb_tray_app_repaint (app);
+}
+
+void
+context_callback ( MBTrayApp *app )
+{
+#ifdef USE_LIBSN
+ if (CONTEXT_APP_WANT_SN)
+ {
+ sn_activate(CONTEXT_APP, CONTEXT_APP " " CONTEXT_APP_ARGS);
+ return;
+ }
+#endif
+
+ fork_exec(CONTEXT_APP " " CONTEXT_APP_ARGS);
+}
+
+static Bool
+file_exists(char *filename)
+{
+ struct stat st; /* XXX Should probably check if exe too */
+ if (stat(filename, &st)) return False;
+ return True;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ MBTrayApp *app = NULL;
+ MBPixbufImage *img_icon = NULL;
+ struct timeval tv;
+ char *icon_path;
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, DATADIR "/locale");
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+ textdomain (PACKAGE);
+#endif
+
+
+ app = mb_tray_app_new ( _("Clock"),
+ resize_callback,
+ paint_callback,
+ &argc,
+ &argv );
+
+ if (app == NULL) usage();
+
+ Pixbuf = mb_pixbuf_new(mb_tray_app_xdisplay(app),
+ mb_tray_app_xscreen(app));
+
+ Col = mb_col_new_from_spec(Pixbuf, "#000000");
+ Fnt = mb_font_new_from_string(mb_tray_app_xdisplay(app), "Sans bold");
+
+ mb_font_set_color (Fnt, Col);
+
+ memset(&tv,0,sizeof(struct timeval));
+ tv.tv_sec = 30;
+
+ mb_tray_app_set_timeout_callback (app, timeout_callback, &tv);
+
+ mb_tray_app_set_button_callback (app, button_callback );
+
+ mb_tray_app_set_theme_change_callback (app, theme_change_callback );
+
+ if (file_exists(CONTEXT_APP))
+ {
+ mb_tray_app_set_context_info (app, _("Set Time"));
+
+ mb_tray_app_set_context_callback (app, context_callback);
+ }
+
+ if ((icon_path = mb_dot_desktop_icon_get_full_path (NULL,
+ 16,
+ "minitime.png"))
+ != NULL)
+ {
+ if ((img_icon = mb_pixbuf_img_new_from_file(Pixbuf, icon_path)) != NULL)
+ {
+ mb_tray_app_set_icon(app, Pixbuf, img_icon);
+ mb_pixbuf_img_free(Pixbuf, img_icon);
+ }
+ free(icon_path);
+ }
+
+#ifdef USE_LIBSN
+ sn_dpy = sn_display_new (mb_tray_app_xdisplay(app), NULL, NULL);
+#endif
+
+ mb_tray_app_main (app);
+
+ return 1;
+}
diff --git a/applets/mb-applet-launcher.c b/applets/mb-applet-launcher.c
new file mode 100644
index 0000000..e9b64fe
--- /dev/null
+++ b/applets/mb-applet-launcher.c
@@ -0,0 +1,661 @@
+/*
+ * Monolaunch - A docked applicatication launcher
+ *
+ * Originally based on xsingleinstance by Merle F. McClelland for CompanionLink
+ *
+ *
+ * Copyright 2002 Matthew Allum
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ **/
+
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#ifdef USE_LIBSN
+#define SN_API_NOT_YET_FROZEN 1
+#include <libsn/sn.h>
+#endif
+
+#include <libmb/mb.h>
+
+#define BUTTON_UP 0
+#define BUTTON_DOWN 1
+
+#define LAUNCH_TIMEOUT 15 /* 15 seconds to start */
+
+enum {
+ ACTION_KILL,
+ ACTION_TOGGLE_WIN_STATE,
+ ACTION_NONE,
+ ACTION_MESSAGE_DOCK,
+#ifdef USE_LIBSN
+ ACTION_SI, /* Single instance */
+ ACTION_SN, /* Startup notification */
+#endif
+};
+
+static Display *dpy;
+static int screen;
+static MBPixbuf *pb;
+static MBPixbufImage *img_icon = NULL, *img_icon_active = NULL;
+static Atom atom_wm_state, atom_wm_delete, atom_wm_protos;
+
+static MBTrayApp *TrayApp;
+static Bool ButtonIsDown;
+static Bool DoAnimation = True;
+
+#ifdef USE_LIBSN
+
+SnDisplay *sn_dpy;
+
+static void sn_activate(char *name, char *exec_str);
+static void si_activate(char *name, char *exec_str);
+
+static void
+si_activate(char *name, char *exec_str)
+{
+ Window win_found;
+
+ if (mb_single_instance_is_starting(dpy, exec_str))
+ return;
+
+ win_found = mb_single_instance_get_window(dpy, exec_str);
+
+ if (win_found != None)
+ {
+ mb_util_window_activate(dpy, win_found);
+ }
+ else sn_activate(name, exec_str);
+
+}
+
+
+static void
+sn_activate(char *name, char *exec_str)
+{
+
+ SnLauncherContext *context;
+ pid_t child_pid = 0;
+
+ context = sn_launcher_context_new (sn_dpy, screen);
+
+ sn_launcher_context_set_name (context, name);
+ sn_launcher_context_set_binary_name (context, exec_str);
+
+ sn_launcher_context_initiate (context, "monoluanch launch", exec_str,
+ CurrentTime);
+
+ switch ((child_pid = fork ()))
+ {
+ case -1:
+ fprintf (stderr, "Fork failed\n" );
+ break;
+ case 0:
+ sn_launcher_context_setup_child_process (context);
+ mb_exec(exec_str);
+ fprintf (stderr, "Failed to exec %s \n", exec_str);
+ _exit (1);
+ break;
+ }
+}
+#endif
+
+static char*
+arr_to_str(char **args, int argc)
+{
+ int i = 0, n_bytes = 0;
+ char *cmd = NULL;
+
+ while(i < argc)
+ {
+ n_bytes += (strlen(args[i]) + 2);
+ i++;
+ }
+
+ if (n_bytes == 0) return NULL;
+
+ cmd = malloc(sizeof(char)*n_bytes);
+
+ i = 0; *cmd = '\0';
+
+ while(i < argc)
+ {
+ strcat(cmd, args[i]);
+ strcat(cmd, " ");
+ i++;
+ }
+
+ return cmd;
+}
+
+static int
+win_exists(Window win, Window top)
+{
+ Window *children, dummy;
+ unsigned int nchildren;
+ int i, w = 0;
+
+ if (top == win) return 1;
+
+ if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
+ return 0;
+
+ for (i=0; i<nchildren; i++)
+ {
+ w = win_exists(win, children[i]);
+ if (w) break;
+ }
+
+ if (children) XFree ((char *)children);
+ return(w);
+
+}
+
+static void
+send_panel_message(char *args)
+{
+#define MAX_MESSAGE_BYTES 1024
+
+ char buf[256];
+ char msg[MAX_MESSAGE_BYTES] = "";
+ FILE *ptr = NULL;
+ int bytes = 0;
+
+ if ((ptr = popen(args, "r")) != NULL)
+ {
+ while (fgets(buf, 256, ptr) != NULL)
+ {
+ bytes += strlen(buf);
+ if (bytes > MAX_MESSAGE_BYTES) break;
+ strcat(msg, buf);
+ }
+
+ mb_tray_app_tray_send_message(TrayApp, msg, 5000);
+ pclose(ptr);
+ }
+ else
+ {
+ fprintf(stderr, "failed to popen\n");
+ }
+}
+
+int
+get_win_state(Window win)
+{
+ Atom real_type; int real_format;
+ unsigned long items_read, items_left;
+ long *data, state = WithdrawnState;
+
+ if (XGetWindowProperty(dpy, win,
+ atom_wm_state, 0L, 2L, False,
+ atom_wm_state, &real_type, &real_format,
+ &items_read, &items_left,
+ (unsigned char **) &data)
+ == Success && items_read)
+ {
+ state = *data;
+ XFree(data);
+ }
+ return state;
+}
+
+void
+kill_launched_win(Window win)
+{
+ int i, n, found = 0;
+ Atom *protocols;
+ XEvent e;
+
+ if (XGetWMProtocols(dpy, win,
+ &protocols, &n))
+ {
+ for (i=0; i<n; i++)
+ if (protocols[i] == atom_wm_delete) found++;
+ XFree(protocols);
+ }
+
+ if (found)
+ {
+ e.type = ClientMessage;
+ e.xclient.window = win;
+ e.xclient.message_type = atom_wm_protos;
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = atom_wm_delete;
+ e.xclient.data.l[1] = CurrentTime;
+ XSendEvent(dpy, win, False, NoEventMask, &e);
+ }
+ else
+ {
+ XKillClient(dpy, win);
+ }
+}
+
+void
+fork_exec(char *cmd)
+{
+ switch (fork())
+ {
+ case 0:
+ setpgid(0, 0); /* Stop us killing child */
+ mb_exec(cmd);
+ fprintf(stderr, "monolaunch: Failed to Launch '%s'", cmd);
+ exit(1);
+ case -1:
+ fprintf(stderr, "monolaunch: Failed to Launch '%s'", cmd);
+ break;
+ }
+}
+
+Window
+get_launch_window()
+{
+ XEvent xevent;
+ time_t stime = time(NULL);
+
+ while (1)
+ {
+ XNextEvent(dpy, &xevent);
+ switch (xevent.type)
+ {
+ case CreateNotify:
+ if (xevent.xcreatewindow.send_event) {
+ break;
+ }
+ if (xevent.xcreatewindow.override_redirect) {
+ break;
+ }
+ XSelectInput(dpy, xevent.xcreatewindow.window, PropertyChangeMask);
+ break;
+ case PropertyNotify:
+ if (xevent.xproperty.atom != atom_wm_state) break;
+ return xevent.xproperty.window;
+ break;
+ }
+ if ((time(NULL)-stime) > LAUNCH_TIMEOUT) return None;
+ }
+}
+
+
+void
+usage(char *program)
+{
+ fprintf(stderr,
+ "Usage %s [Options..] <%s> <app>\n"
+ "Where options are;\n"
+ "\t-display, -d <display> X11 Display to connect to.\n"
+ "\t--title, -n <title> Set Panels Title.\n"
+ "\t--no-animation,-na Disable Animations, if relevant.\n"
+ "\t--start, -s Starts app instance immediatly\n"
+ "The defualt action is to (un)iconize selected app. Alternate actions;\n"
+ "\t--kill, -k Destroy app\n"
+ "\t--respawn, -l Respawn multiple instances\n"
+ "\t--message, -m Pipe apps stdout to the panel as a message.\n"
+ "Alternatively just a valid .desktop file can be given;\n"
+ "\t%s --desktop <.desktop file>\n\n"
+ "However with this option the -k,-l and -m will have no effect.\n"
+ "The prence of a SingleInstance=True key/pair in the .desktop file\n"
+ "will achieve similar functionality\n"
+ , program,
+#ifdef MB_HAVE_PNG
+ "png|xpm",
+#else
+ "xpm",
+#endif
+ program
+ );
+
+ exit(1);
+
+}
+
+void
+paint_callback ( MBTrayApp *app, Drawable drw )
+{
+ MBPixbufImage *img_bg = NULL, *img_button = NULL;
+
+ img_button = (( ButtonIsDown ) ? img_icon_active : img_icon);
+
+ img_bg = mb_tray_app_get_background (app, pb);
+ mb_pixbuf_img_copy_composite (pb, img_bg, img_button,
+ 0, 0,
+ mb_pixbuf_img_get_width(img_icon),
+ mb_pixbuf_img_get_height(img_icon),
+ 0, 0);
+
+ mb_pixbuf_img_render_to_drawable (pb, img_bg, drw, 0, 0);
+ mb_pixbuf_img_free( pb, img_bg );
+}
+
+void
+xevent_callback (MBTrayApp *app, XEvent *ev)
+{
+ ;
+}
+
+void
+resize_callback ( MBTrayApp *app, int w, int h )
+{
+ if ((w) != mb_pixbuf_img_get_width(img_icon)
+ || (h) != mb_pixbuf_img_get_width(img_icon) )
+ {
+ MBPixbufImage *tmp_img = NULL;
+
+ tmp_img = mb_pixbuf_img_scale(pb, img_icon, w, h);
+ mb_pixbuf_img_free(pb, img_icon);
+ img_icon = tmp_img;
+
+ tmp_img = mb_pixbuf_img_scale(pb, img_icon_active, w, h);
+ mb_pixbuf_img_free(pb, img_icon_active);
+ img_icon_active = tmp_img;
+ }
+}
+
+int action = ACTION_TOGGLE_WIN_STATE;
+Window win_launched = None;
+char *cmd_str = NULL;
+char* win_panel_title = NULL;
+
+void
+button_callback (MBTrayApp *app, int x, int y, Bool is_released )
+{
+ int abs_x, abs_y;
+ Bool do_anim = False;
+
+ ButtonIsDown = True;
+ if (is_released)
+ {
+ ButtonIsDown = False;
+ mb_tray_app_repaint (app);
+ switch (action)
+ {
+ case ACTION_NONE:
+ fork_exec(cmd_str);
+ do_anim = DoAnimation;
+ break;
+ case ACTION_KILL:
+ if (win_launched && win_exists(win_launched, mb_tray_app_xrootwin(app)))
+ {
+ kill_launched_win(win_launched);
+ win_launched = None;
+ } else {
+ fork_exec(cmd_str);
+ win_launched = get_launch_window();
+ }
+ break;
+ case ACTION_TOGGLE_WIN_STATE:
+ if (win_launched && win_exists(win_launched, mb_tray_app_xrootwin(app)))
+ {
+ XWindowAttributes win_attrib;
+ XGetWindowAttributes(dpy, win_launched, &win_attrib);
+
+ if (win_attrib.map_state == IsUnmapped ||
+ get_win_state(win_launched) != NormalState)
+ XMapRaised(dpy, win_launched);
+ else
+ XIconifyWindow(dpy, win_launched, screen);
+ }
+ else
+ {
+ fork_exec(cmd_str);
+ win_launched = get_launch_window();
+ }
+ break;
+ case ACTION_MESSAGE_DOCK:
+ send_panel_message(cmd_str);
+ break;
+#ifdef USE_LIBSN
+ case ACTION_SN:
+ do_anim = DoAnimation;
+ sn_activate(win_panel_title, cmd_str);
+ break;
+ case ACTION_SI:
+ do_anim = DoAnimation;
+ si_activate(win_panel_title, cmd_str);
+ break;
+#endif
+ }
+
+ if (do_anim)
+ {
+ mb_tray_app_get_absolute_coords (app, &abs_x, &abs_y);
+
+ mb_util_animate_startup(mb_tray_app_xdisplay (app),
+ abs_x,
+ abs_y,
+ mb_tray_app_width (app),
+ mb_tray_app_height (app));
+ }
+ } else mb_tray_app_repaint (app);
+
+
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int i, x, y;
+
+ /* Config Parameters */
+ int switch_count = 1;
+ char *img_file = NULL;
+ char *dotdesktop_file = NULL;
+ MBDotDesktop *dd = NULL;
+ Bool start_app = False;
+
+ TrayApp = mb_tray_app_new ( "MonoLaunch",
+ resize_callback,
+ paint_callback,
+ &argc,
+ &argv );
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] == '-')
+ {
+
+ if (!strcmp ("--title", argv[i]) || !strcmp ("-n", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ win_panel_title = argv[i];
+ switch_count += 2;
+ continue;
+ }
+
+ if (!strcmp ("--kill", argv[i]) || !strcmp ("-k", argv[i])) {
+ action = ACTION_KILL;
+ switch_count++;
+ continue;
+ }
+
+ if (!strcmp ("--start", argv[i]) || !strcmp ("-s", argv[i])) {
+ start_app = True;
+ switch_count++;
+ continue;
+ }
+
+ if (!strcmp ("--kill", argv[i]) || !strcmp ("-k", argv[i])) {
+ action = ACTION_KILL;
+ switch_count++;
+ continue;
+ }
+
+ if (!strcmp ("--relaunch", argv[i]) || !strcmp ("-l", argv[i])) {
+ action = ACTION_NONE;
+ switch_count++;
+ continue;
+ }
+
+ if (!strcmp ("--message", argv[i]) || !strcmp ("-m", argv[i])) {
+ action = ACTION_MESSAGE_DOCK;
+ switch_count++;
+ continue;
+ }
+
+ if (!strcmp ("--no-animation", argv[i]) || !strcmp ("-na", argv[i])) {
+ DoAnimation = False;
+ switch_count++;
+ continue;
+ }
+
+ if (!strcmp ("--desktop", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ dotdesktop_file = argv[i];
+ switch_count += 2;
+ continue;
+ }
+ usage(argv[0]);
+ }
+ else break;
+ }
+
+ if (argc-switch_count < 2 && dotdesktop_file == NULL) usage(argv[0]);
+
+ dpy = mb_tray_app_xdisplay(TrayApp);
+ screen = mb_tray_app_xscreen(TrayApp);
+
+ atom_wm_state = XInternAtom(dpy, "WM_STATE", False);
+ atom_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ atom_wm_protos = XInternAtom(dpy, "WM_PROTOCOLS", False);
+
+ pb = mb_pixbuf_new(dpy, mb_tray_app_xscreen(TrayApp));
+
+ if (dotdesktop_file != NULL)
+ {
+ if ((dd = mb_dotdesktop_new_from_file(dotdesktop_file)) != NULL
+ && mb_dotdesktop_get(dd, "Name")
+ && mb_dotdesktop_get(dd, "Icon")
+ && mb_dotdesktop_get(dd, "Exec") )
+ {
+ char png_path[256] = { 0 };
+
+ img_file = mb_dotdesktop_get(dd, "Icon");
+
+ if (img_file[0] != '/')
+ {
+ snprintf(png_path, 256, "%s/share/pixmaps/%s", DATADIR,
+ mb_dotdesktop_get(dd, "Icon") );
+ img_file = strdup(png_path);
+ }
+
+ cmd_str = mb_dotdesktop_get(dd, "Exec");
+ if (!win_panel_title)
+ win_panel_title = mb_dotdesktop_get(dd, "Name");
+#ifdef USE_LIBSN
+
+ if (mb_dotdesktop_get(dd, "SingleInstance")
+ && !strcasecmp(mb_dotdesktop_get(dd, "SingleInstance"),
+ "true"))
+ {
+ action = ACTION_SI;
+ }
+ else if (mb_dotdesktop_get(dd, "StartupNotify")
+ && !strcasecmp(mb_dotdesktop_get(dd, "StartupNotify"),
+ "true"))
+ action = ACTION_SN;
+#endif
+ }
+ else
+ {
+ fprintf(stderr,"%s: failed to parse %s\n",
+ argv[0], dotdesktop_file);
+ exit(1);
+ }
+
+ } else {
+ img_file = argv[switch_count];
+ cmd_str = arr_to_str(&argv[switch_count+1], argc - switch_count - 1);
+ }
+
+ if (!(img_icon = mb_pixbuf_img_new_from_file(pb, img_file)))
+ {
+ fprintf(stderr, "%s: failed to load image %s \n",
+ argv[0], img_file );
+ exit(1);
+ }
+
+ /* make active button image */
+ img_icon_active = mb_pixbuf_img_clone(pb, img_icon);
+
+ for (x=0; x<mb_pixbuf_img_get_width(img_icon); x++)
+ for (y=0; y<mb_pixbuf_img_get_height(img_icon); y++)
+ {
+ int aa;
+ unsigned char r,g,b,a;
+ mb_pixbuf_img_get_pixel (pb, img_icon_active, x, y, &r, &g, &b, &a);
+
+ aa = (int)a;
+ aa -= 0x80; if (aa < 0) aa = 0;
+
+ mb_pixbuf_img_set_pixel_alpha(img_icon_active, x, y, aa);
+ }
+
+
+#ifdef USE_LIBSN
+ if (action == ACTION_SN || action == ACTION_SI)
+ sn_dpy = sn_display_new (dpy, NULL, NULL);
+#endif
+
+ mb_tray_app_set_xevent_callback (TrayApp, xevent_callback );
+
+ mb_tray_app_set_button_callback (TrayApp, button_callback );
+
+
+ if (win_panel_title == NULL) /* XXX UTF8 naming */
+ {
+ win_panel_title = malloc( strlen(argv[1+switch_count]) +
+ strlen(" Launcher") + 1 );
+ strcpy(win_panel_title, argv[1+switch_count]);
+ strcat(win_panel_title, " Launcher");
+ }
+
+ mb_tray_app_set_name (TrayApp, win_panel_title);
+
+ XSelectInput(dpy, mb_tray_app_xrootwin(TrayApp), SubstructureNotifyMask);
+
+ signal(SIGCHLD, SIG_IGN);
+
+ mb_tray_app_set_icon(TrayApp, pb, img_icon);
+
+ if (start_app)
+ {
+ switch(action)
+ {
+#ifdef USE_LIBSN
+ case ACTION_SN:
+ sn_activate(win_panel_title, cmd_str);
+ break;
+ case ACTION_SI:
+ si_activate(win_panel_title, cmd_str);
+ break;
+#endif
+ case ACTION_NONE:
+ fork_exec(cmd_str);
+ break;
+ case ACTION_KILL:
+ case ACTION_TOGGLE_WIN_STATE:
+ fork_exec(cmd_str);
+ win_launched = get_launch_window();
+ break;
+ }
+ }
+
+ mb_tray_app_main (TrayApp);
+
+ XCloseDisplay(dpy);
+ exit(0);
+}
diff --git a/applets/mb-applet-menu-launcher.c b/applets/mb-applet-menu-launcher.c
new file mode 100644
index 0000000..e51921d
--- /dev/null
+++ b/applets/mb-applet-menu-launcher.c
@@ -0,0 +1,964 @@
+/*
+ mbmenu - a small application launcher
+
+ Copyright 2002 Matthew Allum
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+/*
+ TODO
+ o fix crash on menu's bigger than display.
+ o add logout / lock buttons on root menu.
+ - add use_gpe defines for this !
+*/
+
+#ifdef USE_DNOTIFY
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+
+#include <libmb/mb.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef USE_XFT
+#include <X11/Xft/Xft.h>
+#endif
+
+#ifdef USE_LIBSN
+#define SN_API_NOT_YET_FROZEN 1
+#include <libsn/sn.h>
+#endif
+
+#ifndef MB_HAVE_PNG
+#include <setjmp.h>
+#endif
+
+typedef struct _app
+{
+ MBTrayApp *tray_app;
+ MBMenu *mbmenu;
+ MBPixbuf *pb;
+
+ MBPixbufImage *img_tray;
+ MBPixbufImage *img_tray_scaled;
+ MBPixbufImage *img_tray_active;
+ MBPixbufImage *img_tray_active_scaled;
+
+ Atom mbtheme_atom;
+ Atom mbcommand_atom;
+
+ char *theme_name;
+ Bool button_is_down;
+
+#ifdef USE_LIBSN
+ SnDisplay *sn_display;
+#endif
+
+} AppData;
+
+AppData *app_data;
+
+MBMenuMenu *root;
+Bool Update_Pending = False;
+jmp_buf Jbuf;
+MBMenuMenu *active[10];
+int MenuWasActive = False;
+
+Bool WantDebianMenus = False;
+volatile Bool WantReload = False;
+
+
+static void reap_children (int signum);
+static void fork_exec (char *cmd);
+static void usage ();
+static int parse_menu_file (char *data);
+static void build_menu (void);
+static void catch_sigsegv (int sig);
+static void load_icon(void);
+
+#ifdef USE_LIBSN
+static void sn_exec(char* name, char* bin_name, char *desc);
+#endif
+
+#ifdef USE_DNOTIFY
+static void reload_menu(int signum, siginfo_t *siginfo, void *data);
+#endif
+
+#ifdef MB_HAVE_PNG
+#define TRAY_IMG "mbmenu.png"
+#define TRAY_IMG_ACTIVE "mbmenu-active.png"
+#else
+#define TRAY_IMG "mbmenu.xpm"
+#define TRAY_IMG_ACTIVE "mbmenu-active.xpm"
+#endif
+
+#define SINGLE_INSTANCE 1
+#define STARTUP_NOTIFY 2
+
+#define UP 0
+#define DOWN 1
+
+#define MENUDIR "/usr/lib/menu"
+
+#define MBMAX(x,y) ((x>y)?(x):(y))
+
+#define NEW(OBJ) ((OBJ *)(malloc(sizeof(OBJ))))
+
+#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\\' \
+ || (c) == '\t' || (c)=='\n' || (c)=='?')
+
+#ifdef DEBUG
+#define DBG(txt, args... ) fprintf(stderr, "DEBUG: " txt , ##args )
+#else
+#define DBG(txt, args... ) /* nothing */
+#endif
+
+static void usage()
+{
+ printf("usage: mbmenu [options ....]\n"
+ "Where options are\n"
+ " -display <display> Display to connect to\n"
+ "\nAlso set MB_USE_DEB_MENUS env var to enable parsing /usr/lib/menu"
+ "\n"
+
+ );
+ exit(1);
+}
+
+static void catch_sigsegv(int sig)
+{
+ DBG("ouch\n");
+ signal(SIGSEGV, SIG_DFL);
+ longjmp(Jbuf, 1);
+
+}
+
+static void reap_children(int signum)
+{
+ pid_t pid;
+
+ do {
+ pid = waitpid(-1, NULL, WNOHANG);
+ } while (pid > 0);
+}
+
+#ifdef USE_LIBSN
+
+static void
+sn_exec(char* name, char* bin_name, char *desc)
+{
+ SnLauncherContext *context;
+ pid_t child_pid = 0;
+
+ context = sn_launcher_context_new (app_data->sn_display,
+ mb_tray_app_xscreen(app_data->tray_app));
+
+ if (name) sn_launcher_context_set_name (context, name);
+ if (desc) sn_launcher_context_set_description (context, desc);
+ if (bin_name) sn_launcher_context_set_binary_name (context, bin_name);
+
+ sn_launcher_context_initiate (context, "mbmenu launch", bin_name,
+ CurrentTime);
+
+ switch ((child_pid = fork ()))
+ {
+ case -1:
+ fprintf (stderr, "Fork failed\n" );
+ break;
+ case 0:
+ sn_launcher_context_setup_child_process (context);
+ mb_exec(bin_name);
+ fprintf (stderr, "mbmenu: Failed to exec %s \n", bin_name);
+ _exit (1);
+ break;
+ }
+}
+
+#endif
+
+static void fork_exec(char *cmd)
+{
+ pid_t pid;
+
+ switch (pid = fork())
+ {
+ case 0:
+ mb_exec(cmd);
+ /* execlp("/bin/sh", "sh", "-c", cmd, NULL); */
+ fprintf(stderr, "mbmenu: exec failed, cleaning up child\n");
+ exit(1);
+ case -1:
+ fprintf(stderr, "mbmenu: can't fork\n"); break;
+ }
+}
+
+#ifdef USE_LIBSN
+static
+void menu_clicked_sn_cb(MBMenuItem *item)
+{
+ sn_exec(item->title, item->info, item->info);
+}
+
+static
+void menu_clicked_si_cb(MBMenuItem *item)
+{
+ Window win_found;
+
+ win_found = mb_single_instance_get_window(mb_tray_app_xdisplay(app_data->tray_app), item->info);
+
+ if (win_found != None)
+ {
+ mb_util_window_activate(mb_tray_app_xdisplay(app_data->tray_app), win_found);
+ }
+ else menu_clicked_sn_cb(item);
+}
+#endif
+
+static
+void menu_clicked_cb(MBMenuItem *item)
+{
+ fork_exec(item->info);
+}
+
+static int
+parse_menu_file(char *data)
+{
+ char *p, *key, *val;
+
+ char *tmp_title;
+ char *tmp_section;
+ char *tmp_cmd;
+ char *tmp_icon;
+ char *tmp_needs;
+
+ signal(SIGSEGV, catch_sigsegv);
+ if (setjmp(Jbuf)) return 0; /* catch possible parse segfualt */
+
+ tmp_title = NULL;
+ tmp_section = NULL;
+ tmp_cmd = NULL;
+ tmp_icon = NULL;
+ tmp_needs = NULL;
+ p = data;
+
+ if (*p != '?') return 0; /* check is an actual menu entry */
+
+ while(*(++p) != ':'); *p = ' '; /* skip to first entry */
+
+ while(*p != '\0')
+ {
+ if ((!IS_WHITESPACE(*p))
+ || (IS_WHITESPACE(*p) && *(p+1) != '\0'
+ && (!IS_WHITESPACE(*(p+1)))))
+ {
+ /* process key=pair */
+ char *lc = " \t\n\\";
+ char *sc = "\"";
+ char *tc = lc;
+ if (IS_WHITESPACE(*p)) p++;
+ key = p;
+ while(*p != '=') p++; *p = '\0';
+ DBG("\tkey %s ", key);
+ if (*(++p) == '"') { p++; tc = sc; } /* skip "'s */
+ val = p;
+ while(index(tc,*p) == NULL)
+ {
+ if (*p == '\\' && *(p+1) == '"') p++; /* skip \" */
+ p++;
+ } *p = '\0';
+ DBG("value %s \n", val);
+
+ if(!strcmp(key,"title")) { tmp_title = val; }
+ else if(!strcmp(key,"section")) { tmp_section = val; }
+ else if(!strcmp(key,"command")) { tmp_cmd = val; }
+ else if(!strcmp(key,"icon")) { tmp_icon = val; }
+ else if(!strcmp(key,"icon16")) { tmp_icon = val; }
+ else if(!strcmp(key,"icon32")) { tmp_icon = val; }
+ else if(!strcmp(key,"icon48")) { tmp_icon = val; }
+ else if(!strcmp(key,"needs")) { tmp_needs = val; }
+
+ }
+ p++;
+
+ if (tmp_section && (*p == '?' || *p == '\0'))
+ {
+ if ( (!strcmp(tmp_needs,"x11"))
+ || (!strcmp(tmp_needs,"X11"))
+ || (!strcmp(tmp_needs,"text"))
+ || tmp_needs == NULL )
+ {
+ MBMenuMenu *m = NULL;
+
+ char *tmpstr =
+ (char *)malloc(sizeof(char)*(strlen(tmp_section)+
+ strlen(tmp_title)+12));
+ sprintf(tmpstr, "Other/%s", tmp_section);
+
+ m = mb_menu_add_path(app_data->mbmenu, tmpstr, NULL, 0);
+ mb_menu_add_item_to_menu(app_data->mbmenu, m, tmp_title,
+ tmp_icon, tmp_cmd,
+ menu_clicked_cb, NULL, 0);
+ }
+ }
+ }
+ /* reset all */
+ tmp_title = NULL;
+ tmp_section = NULL;
+ tmp_cmd = NULL;
+ tmp_icon = NULL;
+
+ /* new menu entry */
+
+ if ( *p == '?')
+ {
+ DBG("new entry, igonoring package(foo) data\n");
+ while(*(++p) != ':');
+ *p = ' ';
+ }
+
+
+ signal(SIGSEGV, SIG_DFL);
+ return 1;
+}
+
+#ifdef USE_DNOTIFY
+static
+void really_reload_menu(int signum)
+{
+ DBG("Really Reload menu callback\n");
+
+ WantReload = True;
+
+}
+
+
+static
+void reload_menu(int signum, siginfo_t *siginfo, void *data)
+{
+ DBG("Reload menu callback\n");
+
+ /* To avoid the barrage of signals dnotify likes to send when
+ * a file is updated we set an alarm.
+ *
+ */
+ signal (SIGALRM, really_reload_menu);
+ alarm(3);
+
+}
+#endif
+
+static void
+build_menu(void)
+{
+ struct menu_lookup_t {
+ char *match_str;
+ MBMenuMenu *item;
+ };
+
+ int i = 0;
+ DIR *dp;
+ struct dirent *dir_entry;
+ struct stat stat_info;
+ char orig_wd[256];
+
+ char *dd_dir = DATADIR "/applications";
+
+ char dirs[2][256] = { MENUDIR };
+ FILE *fp;
+ char *buf;
+ int len;
+ MBMenuMenu *menu_panel;
+ char *tmp_path = NULL, *tmp_path2 = NULL ;
+
+ char vfolder_path_root[512];
+ char vfolder_path[512];
+ MBDotDesktop *dd;
+ MBDotDesktopFolders *ddfolders;
+ MBDotDesktopFolderEntry *ddentry;
+ char *root_match_str;
+
+ Bool got_root_items = False;
+
+ struct menu_lookup_t *menu_lookup = NULL;
+
+ snprintf( vfolder_path_root, 512, "%s/.matchbox/vfolders/Root.directory", getenv("HOME"));
+ snprintf( vfolder_path, 512, "%s/.matchbox/vfolders", getenv("HOME"));
+
+ if (stat(vfolder_path_root, &stat_info))
+ {
+ snprintf(vfolder_path_root, 512, PKGDATADIR "/vfolders/Root.directory");
+ snprintf(vfolder_path, 512, PKGDATADIR "/vfolders" );
+ }
+
+ dd = mb_dotdesktop_new_from_file(vfolder_path_root);
+
+ if (!dd) /* XXX improve */
+ { fprintf( stderr, "mbdesktop: cant open " PKGDATADIR "/vfolders/Root.desktop\n" ); exit(1); }
+
+ root_match_str = mb_dotdesktop_get(dd, "Match");
+
+ /* Now grab the vfolders */
+ ddfolders = mb_dot_desktop_folders_new(vfolder_path);
+
+ menu_lookup = malloc(sizeof(struct menu_lookup_t)*mb_dot_desktop_folders_get_cnt(ddfolders));
+
+ mb_dot_desktop_folders_enumerate(ddfolders, ddentry)
+ {
+ char *icon_path = NULL;
+
+ if (mb_dot_desktop_folder_entry_get_icon(ddentry))
+ icon_path = mb_dot_desktop_icon_get_full_path (app_data->theme_name,
+ 16,
+ mb_dot_desktop_folder_entry_get_icon(ddentry) );
+
+ menu_lookup[i].item = mb_menu_add_path(app_data->mbmenu,
+ mb_dot_desktop_folder_entry_get_name(ddentry),
+ icon_path, MBMENU_NO_SORT );
+
+ menu_lookup[i].match_str = mb_dot_desktop_folder_entry_get_match(ddentry);
+ i++;
+
+ }
+
+ menu_panel = mb_menu_add_path(app_data->mbmenu, "Utilities/Panel" , NULL, MBMENU_NO_SORT );
+
+ mb_menu_add_seperator_to_menu(app_data->mbmenu, app_data->mbmenu->rootmenu,
+ MBMENU_NO_SORT);
+
+ tmp_path = mb_dot_desktop_icon_get_full_path (app_data->theme_name,
+ 16,
+ "mbfolder.png" );
+
+ tmp_path2 = mb_dot_desktop_icon_get_full_path (app_data->theme_name,
+ 16,
+ "mbnoapp.png" );
+
+ mb_menu_set_default_icons(app_data->mbmenu, tmp_path, tmp_path2);
+
+ if (tmp_path) free(tmp_path);
+ if (tmp_path2) free(tmp_path2);
+
+ if (getcwd(orig_wd, 255) == (char *)NULL)
+ {
+ fprintf(stderr, "mbmenu: cant get current directory\n");
+ exit(0);
+ }
+
+ if ((dp = opendir(dd_dir)) == NULL)
+ {
+ fprintf(stderr, "mbmenu: failed to open %s\n", dd_dir);
+ exit(0);
+ }
+
+ chdir(dd_dir);
+ while((dir_entry = readdir(dp)) != NULL)
+ {
+ if (strcmp(dir_entry->d_name+strlen(dir_entry->d_name)-8,".desktop"))
+ continue;
+
+ lstat(dir_entry->d_name, &stat_info);
+ if (!(S_ISDIR(stat_info.st_mode)))
+ {
+ MBDotDesktop *dd;
+ int flags = 0;
+ dd = mb_dotdesktop_new_from_file(dir_entry->d_name);
+ if (dd)
+ {
+ char *png_path = NULL;
+ MBMenuActivateCB activate_callback = NULL;
+
+ if (mb_dotdesktop_get(dd, "Icon")
+ && mb_dotdesktop_get(dd, "Name")
+ && mb_dotdesktop_get(dd, "Exec"))
+ {
+ MBMenuMenu *m = NULL, *fallback = NULL;
+ char *category;
+
+ png_path = mb_dot_desktop_icon_get_full_path(app_data->theme_name, 16, mb_dotdesktop_get(dd, "Icon"));
+
+ category = mb_dotdesktop_get(dd, "Categories");
+
+ if (category && strstr(category, "Action"))
+ {
+ m = app_data->mbmenu->rootmenu;
+ flags = MBMENU_NO_SORT;
+ }
+ else
+ {
+ if (root_match_str)
+ {
+ if (!strcmp("fallback", root_match_str))
+ {
+ fallback = app_data->mbmenu->rootmenu;
+ }
+ else if (category && strstr(category, root_match_str))
+ {
+ m = app_data->mbmenu->rootmenu;
+ }
+ }
+
+ if (m == NULL
+ && category != NULL)
+ {
+ for (i=0;
+ i<mb_dot_desktop_folders_get_cnt(ddfolders);
+ i++)
+ {
+ if (!strcmp(menu_lookup[i].match_str,"fallback"))
+ {
+ fallback = menu_lookup[i].item;
+ }
+ if (strstr(category, menu_lookup[i].match_str))
+ {
+ m = menu_lookup[i].item;
+ }
+ }
+ }
+
+ if (m == NULL) m = fallback;
+
+ }
+ activate_callback = menu_clicked_cb;
+#ifdef USE_LIBSN
+
+ if (mb_dotdesktop_get(dd, "SingleInstance")
+ && !strcasecmp(mb_dotdesktop_get(dd, "SingleInstance"),
+ "true"))
+ {
+ activate_callback = menu_clicked_si_cb;
+ }
+ else if (mb_dotdesktop_get(dd, "StartupNotify")
+ && !strcasecmp(mb_dotdesktop_get(dd, "StartupNotify"),
+ "true"))
+ {
+ activate_callback = menu_clicked_sn_cb;
+ }
+#endif
+ if (mb_dotdesktop_get(dd, "Type")
+ && !strcmp(mb_dotdesktop_get(dd, "Type"), "PanelApp"))
+ {
+ m = menu_panel;
+ }
+
+ if (png_path && m)
+ {
+
+ if (!flags && m == app_data->mbmenu->rootmenu)
+ {
+ if (got_root_items == False)
+ {
+ mb_menu_add_seperator_to_menu(app_data->mbmenu,
+ app_data->mbmenu->rootmenu,
+ MBMENU_PREPEND);
+ got_root_items = True;
+ }
+
+ flags = MBMENU_PREPEND;
+ }
+
+ mb_menu_add_item_to_menu(app_data->mbmenu, m,
+ mb_dotdesktop_get(dd, "Name"),
+ png_path,
+ mb_dotdesktop_get(dd, "Exec"),
+ activate_callback,
+ (void *)app_data, flags);
+ /* mb_menu_add_seperator_to_menu(app_data-> mbmenu, m); */
+
+ free(png_path);
+ }
+ }
+ else fprintf(stderr,
+ "mbmenu: %s has no icon, png or name\n",
+ dir_entry->d_name);
+ mb_dotdesktop_free(dd);
+ }
+ else
+ fprintf(stderr, "mbmenu: failed to parse %s :( \n", dir_entry->d_name);
+ }
+ }
+
+ closedir(dp);
+
+ /* Now parse old Debian / Familiar Menu entrys */
+ chdir(orig_wd);
+
+ if (WantDebianMenus)
+ {
+ strcpy(dirs[1], (char *)getenv("HOME"));
+ strcat(dirs[1], "/.menu");
+
+ for(i=0; i<2; i++)
+ {
+ if ((dp = opendir(dirs[i])) == NULL)
+ {
+ fprintf(stderr, "mbmenu: failed to open %s\n", dirs[i]);
+ continue;
+ }
+
+ chdir(dirs[i]);
+ while((dir_entry = readdir(dp)) != NULL)
+ {
+ lstat(dir_entry->d_name, &stat_info);
+ if (!(S_ISDIR(stat_info.st_mode)))
+ {
+ DBG("file %s \n", dir_entry->d_name);
+
+ fp = fopen(dir_entry->d_name, "r");
+ buf = malloc(sizeof(char) * (stat_info.st_size + 1));
+ len = fread(buf, 1, stat_info.st_size, fp);
+ if (len >= 0) buf[len] = '\0';
+ if (!(parse_menu_file(buf)))
+ fprintf(stderr, "mbmenu: had problems parsing %s. Ignoring. \n",
+ dir_entry->d_name);
+ DBG("done\n\n");
+ fclose(fp);
+ free(buf);
+ }
+ }
+
+ closedir(dp);
+
+ }
+ chdir(orig_wd);
+ }
+
+}
+
+static void
+menu_get_popup_pos (MBTrayApp *app, int *x, int *y)
+{
+ int abs_x, abs_y, menu_h, menu_w;
+ mb_tray_app_get_absolute_coords (app, &abs_x, &abs_y);
+ mb_menu_get_root_menu_size(app_data->mbmenu, &menu_w, &menu_h);
+
+ if (mb_tray_app_tray_is_vertical (app))
+ {
+ /* XXX need to figure out menu size before its mapped
+ so we can figure out offset for east panel
+ */
+ *y = abs_y + mb_tray_app_height(app);
+
+ if (abs_x > (DisplayWidth(mb_tray_app_xdisplay(app), mb_tray_app_xscreen(app)) /2))
+ *x = abs_x - menu_w - 2;
+ else
+ *x = abs_x + mb_tray_app_width(app) + 2;
+ }
+ else
+ {
+ *x = abs_x;
+ if (abs_y > (DisplayHeight(mb_tray_app_xdisplay(app), mb_tray_app_xscreen(app)) /2))
+ *y = abs_y - 2;
+ else
+ *y = abs_y + mb_tray_app_height(app) + menu_h;
+ }
+}
+
+void
+button_callback (MBTrayApp *app, int x, int y, Bool is_released )
+{
+ int abs_x, abs_y;
+ sigset_t block_sigset;
+ static Bool next_cancels;
+
+ app_data->button_is_down = True;
+ if (is_released) app_data->button_is_down = False;
+
+ sigemptyset(&block_sigset);
+ sigaddset(&block_sigset, SIGRTMIN);
+
+ if (is_released && !next_cancels)
+ {
+ sigaddset(&block_sigset, SIGRTMIN);
+ menu_get_popup_pos (app, &abs_x, &abs_y);
+ mb_menu_activate (app_data->mbmenu, abs_x, abs_y);
+
+ }
+ else
+ if (mb_menu_is_active(app_data->mbmenu))
+ next_cancels = True;
+ else
+ next_cancels = False;
+
+ mb_tray_app_repaint (app);
+}
+
+void
+paint_callback (MBTrayApp *app, Drawable drw )
+{
+ MBPixbufImage *img_bg = NULL;
+ MBPixbufImage *img_button = NULL;
+
+ img_button = ( app_data->button_is_down ? app_data->img_tray_active_scaled : app_data->img_tray_scaled );
+
+ img_bg = mb_tray_app_get_background (app, app_data->pb);
+
+ mb_pixbuf_img_copy_composite (app_data->pb, img_bg,
+ img_button,
+ 0, 0,
+ mb_pixbuf_img_get_width(app_data->img_tray_scaled),
+ mb_pixbuf_img_get_height(app_data->img_tray_scaled),
+ 0, 0 );
+
+ mb_pixbuf_img_render_to_drawable (app_data->pb, img_bg, drw, 0, 0);
+
+ mb_pixbuf_img_free( app_data->pb, img_bg );
+}
+
+void
+resize_callback (MBTrayApp *app, int w, int h)
+{
+ if (app_data->img_tray_scaled)
+ mb_pixbuf_img_free(app_data->pb,
+ app_data->img_tray_scaled);
+
+ app_data->img_tray_scaled = mb_pixbuf_img_scale(app_data->pb,
+ app_data->img_tray,
+ w, h);
+ if (app_data->img_tray_active_scaled)
+ mb_pixbuf_img_free(app_data->pb,
+ app_data->img_tray_active_scaled);
+
+ app_data->img_tray_active_scaled
+ = mb_pixbuf_img_scale(app_data->pb,
+ app_data->img_tray_active,
+ w, h);
+}
+
+void
+theme_callback (MBTrayApp *app, char *theme_name)
+{
+ if (!theme_name) return;
+ if (app_data->theme_name) free(app_data->theme_name);
+ app_data->theme_name = strdup(theme_name);
+
+ if (app_data->mbmenu != NULL)
+ {
+ mb_menu_free(app_data->mbmenu);
+ build_menu();
+ load_icon();
+ resize_callback (app, mb_tray_app_width(app), mb_tray_app_width(app) );
+ mb_tray_app_repaint (app_data->tray_app);
+ }
+}
+
+void
+xevent_callback (MBTrayApp *app, XEvent *ev)
+{
+ sigset_t block_sigset;
+
+ mb_menu_handle_xevent (app_data->mbmenu, ev);
+
+#ifdef USE_DNOTIFY
+ if (!mb_menu_is_active(app_data->mbmenu))
+ { /* Unblock any dnotify signals */
+ sigemptyset(&block_sigset);
+ sigaddset(&block_sigset, SIGRTMIN);
+ sigprocmask(SIG_UNBLOCK, &block_sigset, NULL);
+ }
+#endif
+
+#define MB_CMD_SHOW_EXT_MENU 6
+
+ if (ev->type == ClientMessage)
+ {
+ if (ev->xclient.message_type == app_data->mbcommand_atom
+ && ev->xclient.data.l[0] == MB_CMD_SHOW_EXT_MENU )
+ {
+ sigemptyset(&block_sigset);
+ sigaddset(&block_sigset, SIGRTMIN);
+
+ if (!mb_menu_is_active(app_data->mbmenu))
+ {
+ int abs_x, abs_y;
+ sigprocmask(SIG_BLOCK, &block_sigset, NULL);
+ menu_get_popup_pos (app, &abs_x, &abs_y);
+ mb_menu_activate(app_data->mbmenu, abs_x, abs_y);
+ } else {
+ mb_menu_deactivate(app_data->mbmenu);
+ sigprocmask(SIG_UNBLOCK, &block_sigset, NULL);
+ }
+ }
+ }
+
+ if (WantReload && !mb_menu_is_active(app_data->mbmenu))
+ {
+ DBG("reloading menu\n");
+ mb_menu_free(app_data->mbmenu);
+ build_menu();
+ WantReload = False;
+ }
+}
+
+void
+load_icon(void)
+{
+ char *icon_path = NULL;
+
+ if (app_data->img_tray)
+ mb_pixbuf_img_free(app_data->pb, app_data->img_tray);
+
+ if (app_data->img_tray_active)
+ mb_pixbuf_img_free(app_data->pb, app_data->img_tray_active);
+
+ icon_path = mb_dot_desktop_icon_get_full_path (app_data->theme_name,
+ 16,
+ TRAY_IMG );
+
+ if (icon_path == NULL
+ || !(app_data->img_tray
+ = mb_pixbuf_img_new_from_file(app_data->pb, icon_path)))
+ {
+ fprintf(stderr, "mbmenu: failed to load icon\n");
+ exit(1);
+ }
+
+ free(icon_path);
+
+ icon_path = mb_dot_desktop_icon_get_full_path (app_data->theme_name,
+ 16,
+ TRAY_IMG_ACTIVE );
+
+ if (icon_path == NULL
+ || !(app_data->img_tray_active
+ = mb_pixbuf_img_new_from_file(app_data->pb, icon_path)))
+ {
+ int x, y;
+
+ app_data->img_tray_active
+ = mb_pixbuf_img_clone(app_data->pb, app_data->img_tray);
+
+ for (x=0; x<mb_pixbuf_img_get_width(app_data->img_tray_active); x++)
+ for (y=0; y<mb_pixbuf_img_get_height(app_data->img_tray_active); y++)
+ {
+ int aa;
+ unsigned char r,g,b,a;
+ mb_pixbuf_img_get_pixel(app_data->pb, app_data->img_tray_active,
+ x, y, &r, &g, &b, &a);
+
+ aa = (int)a;
+ aa -= 0x80; if (aa < 0) aa = 0;
+
+ mb_pixbuf_img_set_pixel_alpha(app_data->img_tray_active,
+ x, y, aa);
+ }
+ }
+
+ if (icon_path) free(icon_path);
+}
+
+int
+main( int argc, char *argv[])
+{
+ MBTrayApp *app = NULL;
+ struct sigaction act;
+
+#ifdef USE_DNOTIFY
+ int fd;
+#endif
+
+ app_data = NEW(AppData);
+ memset(app_data, 0, sizeof(AppData));
+
+ app = mb_tray_app_new ( "App Launcher",
+ resize_callback,
+ paint_callback,
+ &argc,
+ &argv );
+
+ if (app == NULL) usage();
+
+ if (argc > 1 && strstr(argv[1], "-h"))
+ usage();
+
+ if (getenv("MB_USE_DEB_MENUS"))
+ WantDebianMenus = True;
+
+ app_data->tray_app = app;
+
+ app_data->mbtheme_atom
+ = XInternAtom(mb_tray_app_xdisplay(app), "_MB_THEME", False);
+ app_data->mbcommand_atom
+ = XInternAtom(mb_tray_app_xdisplay(app), "_MB_COMMAND", False);
+
+ app_data->mbmenu = mb_menu_new(mb_tray_app_xdisplay(app),
+ mb_tray_app_xscreen(app));
+
+#ifdef USE_LIBSN
+
+ app_data->sn_display = sn_display_new (mb_tray_app_xdisplay(app),
+ NULL, NULL);
+
+#endif
+
+ app_data->pb = mb_pixbuf_new(mb_tray_app_xdisplay(app),
+ mb_tray_app_xscreen(app));
+
+ XSelectInput (mb_tray_app_xdisplay(app), mb_tray_app_xrootwin(app),
+ PropertyChangeMask|SubstructureNotifyMask);
+
+ mb_tray_app_set_button_callback (app, button_callback );
+
+ mb_tray_app_set_xevent_callback (app, xevent_callback );
+
+ mb_tray_app_set_theme_change_callback (app, theme_callback );
+
+ /* Make the tray app end up on right of mb panel */
+ mb_tray_app_request_offset (app, -1);
+
+ load_icon();
+
+ build_menu();
+
+ /* Set up signals */
+
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = reap_children;
+ sigaction(SIGCHLD, &act, NULL);
+
+#ifdef USE_DNOTIFY
+
+#define DD_DIR DATADIR "/applications"
+
+ act.sa_sigaction = reload_menu;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ sigaction(SIGRTMIN, &act, NULL);
+
+ fd = open(DD_DIR, O_RDONLY);
+ fcntl(fd, F_SETSIG, SIGRTMIN);
+ fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT);
+
+#endif
+
+ mb_tray_app_set_icon(app, app_data->pb, app_data->img_tray);
+
+ mb_tray_app_main (app);
+
+ return 1;
+}
+
+
diff --git a/applets/mb-applet-system-monitor.c b/applets/mb-applet-system-monitor.c
new file mode 100644
index 0000000..93053f6
--- /dev/null
+++ b/applets/mb-applet-system-monitor.c
@@ -0,0 +1,369 @@
+/*
+ * minisys - tiny sys monitor
+ *
+ * cpu reading code based on wmbubblemon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <libmb/mb.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(text) gettext(text)
+#else
+# define _(text) (text)
+#endif
+
+#ifdef MB_HAVE_PNG
+#define IMG_EXT "png"
+#else
+#define IMG_EXT "xpm"
+#endif
+
+#define MINISYS_IMG "minisys." IMG_EXT
+
+struct {
+
+ /* cpu data */
+ int loadIndex;
+ int samples;
+ u_int64_t *load, *total;
+
+ /* memory data */
+ u_int64_t mem_used;
+ u_int64_t mem_max;
+ u_int64_t swap_used;
+ u_int64_t swap_max;
+ unsigned int swap_percent; /* swap used, in percent */
+ unsigned int mem_percent; /* memory used, in percent */
+
+} msd;
+
+MBPixbuf *pb = NULL;
+MBPixbufImage *ImgIcon = NULL, *ImgIconScaled = NULL, *ImgGraph = NULL;
+
+int GraphHeight = 0, GraphWidth = 0;
+
+char *ThemeName;
+
+/* returns current CPU load in percent, 0 to 100 */
+int system_cpu(void)
+{
+ unsigned int cpuload;
+ u_int64_t load, total, oload, ototal;
+ u_int64_t ab, ac, ad, ae;
+ int i;
+ FILE *stat;
+
+ stat = fopen("/proc/stat", "r");
+ fscanf(stat, "%*s %Ld %Ld %Ld %Ld", &ab, &ac, &ad, &ae);
+ fclose(stat);
+
+ /* Find out the CPU load */
+ /* user + sys = load
+ * total = total */
+ load = ab + ac + ad; /* cpu.user + cpu.sys; */
+ total = ab + ac + ad + ae; /* cpu.total; */
+
+ /* "i" is an index into a load history */
+ i = msd.loadIndex;
+ oload = msd.load[i];
+ ototal = msd.total[i];
+
+ msd.load[i] = load;
+ msd.total[i] = total;
+ msd.loadIndex = (i + 1) % msd.samples;
+
+ if (ototal == 0)
+ cpuload = 0;
+ else
+ cpuload = (100 * (load - oload)) / (total - ototal);
+
+ return cpuload;
+}
+
+int system_memory(void)
+{
+ u_int64_t my_mem_used, my_mem_max;
+ u_int64_t my_swap_max;
+
+ static int mem_delay = 0;
+ FILE *mem;
+ static u_int64_t total, used, mfree, shared, buffers, cached,
+ cache_total, cache_used;
+
+ /* put this in permanent storage instead of stack */
+ static char not_needed[2048];
+
+ if (mem_delay-- <= 0) {
+ mem = fopen("/proc/meminfo", "r");
+ fgets(not_needed, 2048, mem);
+
+ /*
+ total: used: free: shared: buffers: cached:
+ */
+
+ fscanf(mem, "%*s %Ld %Ld %Ld %Ld %Ld %Ld", &total, &used, &mfree,
+ &shared, &buffers, &cached);
+
+ fscanf(mem, "%*s %Ld %Ld", &cache_total, &cache_used);
+
+ fclose(mem);
+ mem_delay = 25;
+
+ /* calculate it */
+ my_mem_max = total;
+ my_swap_max = cache_total;
+
+ my_mem_used = cache_used + used - cached - buffers;
+
+ /* No swap on ipaq
+ if (my_mem_used > my_mem_max) {
+ my_swap_used = my_mem_used - my_mem_max;
+ my_mem_used = my_mem_max;
+ } else {
+ my_swap_used = 0;
+ }
+ */
+
+ msd.mem_used = my_mem_used;
+ msd.mem_max = my_mem_max;
+ //msd.swap_used = my_swap_used;
+ //msd.swap_max = my_swap_max;
+
+ msd.mem_percent = (100 * msd.mem_used) / msd.mem_max;
+ //msd.swap_percent = (100 * msd.swap_used) / msd.swap_max;
+
+ /* memory info changed - update things */
+ return 1;
+ }
+ /* nothing new */
+ return 0;
+}
+
+
+void
+paint_callback (MBTrayApp *app, Drawable drw )
+{
+ static int prev_cpu_pixels, prev_mem_pixels;
+ int cpu_pixels, mem_pixels;
+ int cpusize, memsize;
+ int x, y;
+
+ int membox_x, membox_y, membox_w, membox_h;
+ int cpubox_x, cpubox_y, cpubox_w, cpubox_h;
+
+ MBPixbufImage *img_backing = NULL;
+
+ system_memory(); /* Update reading */
+
+ cpusize = system_cpu();
+ memsize = msd.mem_percent;
+
+ cpubox_h = membox_h = (mb_pixbuf_img_get_width(ImgIconScaled)/16) * 10;
+
+ cpu_pixels = (cpusize * ( cpubox_h) )/ 100 ;
+ mem_pixels = (memsize * ( membox_h) )/ 100 ;
+
+ if (cpu_pixels == prev_cpu_pixels && mem_pixels == prev_mem_pixels)
+ return;
+
+ img_backing = mb_tray_app_get_background (app, pb);
+
+ mb_pixbuf_img_composite(pb, img_backing, ImgIconScaled, 0, 0);
+
+ membox_x = (mb_pixbuf_img_get_width(img_backing)/4) - (mb_pixbuf_img_get_width(img_backing)/16);
+ membox_y = membox_x;
+ membox_w = (mb_pixbuf_img_get_width(img_backing)/16) * 2;
+ cpubox_x = ((mb_pixbuf_img_get_width(img_backing)/4) * 3) - (mb_pixbuf_img_get_width(img_backing)/16);
+ cpubox_y = membox_y;
+ cpubox_w = membox_w;
+
+ /* clear boxes */
+
+ for ( y = membox_y; y < membox_y + membox_h; y++)
+ for ( x = 0; x < membox_w; x++)
+ {
+ mb_pixbuf_img_plot_pixel(pb, img_backing, membox_x + x, y,
+ 0x66, 0x66, 0x66);
+
+ mb_pixbuf_img_plot_pixel(pb, img_backing, cpubox_x + x, y,
+ 0x66, 0x66, 0x66);
+ }
+
+ if (cpusize > 0)
+ {
+ for ( y = cpubox_h; y > cpubox_h - cpu_pixels; y--)
+ for ( x = cpubox_x; x < cpubox_x + cpubox_w; x++)
+ mb_pixbuf_img_plot_pixel(pb, img_backing, x, y + cpubox_y,
+ 0, 0xff, 0);
+ }
+
+ if (memsize > 0)
+ {
+ for ( y = membox_h; y > membox_h - mem_pixels; y--)
+ for ( x = membox_x; x < membox_x + membox_w; x++)
+ mb_pixbuf_img_plot_pixel(pb, img_backing, x, y + membox_y,
+ 0xff, 0, 0);
+ }
+
+ /* XXX Alert here for low memory */
+
+ mb_pixbuf_img_render_to_drawable(pb, img_backing, drw, 0, 0);
+
+ mb_pixbuf_img_free( pb, img_backing );
+
+ prev_cpu_pixels = cpu_pixels;
+ prev_mem_pixels = mem_pixels;
+
+}
+
+void
+button_callback (MBTrayApp *app, int x, int y, Bool is_released )
+{
+ char tray_msg[256];
+ int cpu = system_cpu();
+
+ if (!is_released)
+ return;
+
+ sprintf(tray_msg, _("CPU: %i %%, MEMORY: %i %%\n"),cpu, msd.mem_percent);
+ mb_tray_app_tray_send_message(app, tray_msg, 5000);
+}
+
+void
+resize_callback (MBTrayApp *app, int w, int h )
+{
+
+ if (ImgIconScaled) mb_pixbuf_img_free(pb, ImgIconScaled);
+ if (ImgGraph) mb_pixbuf_img_free(pb, ImgGraph);
+
+ ImgIconScaled = mb_pixbuf_img_scale(pb, ImgIcon, w, h);
+
+}
+
+void
+load_icon(void)
+{
+ char *icon_path = NULL;
+
+ if (ImgIcon) mb_pixbuf_img_free(pb, ImgIcon);
+
+ icon_path = mb_dot_desktop_icon_get_full_path (ThemeName,
+ 32,
+ MINISYS_IMG );
+
+ if (icon_path == NULL
+ || !(ImgIcon = mb_pixbuf_img_new_from_file(pb, icon_path)))
+ {
+ fprintf(stderr, "miniapm: failed to load icon %s\n", MINISYS_IMG);
+ exit(1);
+ }
+
+ free(icon_path);
+
+ return;
+
+}
+
+void
+theme_callback (MBTrayApp *app, char *theme_name)
+{
+ if (!theme_name) return;
+ if (ThemeName) free(ThemeName);
+ ThemeName = strdup(theme_name);
+ load_icon();
+ resize_callback (app, mb_tray_app_width(app), mb_tray_app_width(app) );
+}
+
+void
+timeout_callback ( MBTrayApp *app )
+{
+ mb_tray_app_repaint (app);
+}
+
+int
+main( int argc, char *argv[])
+{
+ MBTrayApp *app = NULL;
+ struct timeval tv;
+
+ int i;
+ u_int64_t load = 0, total = 0;
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, DATADIR "/locale");
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+ textdomain (PACKAGE);
+#endif
+
+ app = mb_tray_app_new ( _("CPU/Mem Monitor"),
+ resize_callback,
+ paint_callback,
+ &argc,
+ &argv );
+
+ msd.samples = 16;
+
+ if (msd.load) {
+ load = msd.load[msd.loadIndex];
+ free(msd.load);
+ }
+
+ if (msd.total) {
+ total = msd.total[msd.loadIndex];
+ free(msd.total);
+ }
+
+ msd.loadIndex = 0;
+ msd.load = malloc(msd.samples * sizeof(u_int64_t));
+ msd.total = malloc(msd.samples * sizeof(u_int64_t));
+ for (i = 0; i < msd.samples; i++) {
+ msd.load[i] = load;
+ msd.total[i] = total;
+ }
+
+ pb = mb_pixbuf_new(mb_tray_app_xdisplay(app),
+ mb_tray_app_xscreen(app));
+
+ memset(&tv,0,sizeof(struct timeval));
+ tv.tv_usec = 400000;
+
+ mb_tray_app_set_theme_change_callback (app, theme_callback );
+
+ mb_tray_app_set_timeout_callback (app, timeout_callback, &tv);
+
+ mb_tray_app_set_button_callback (app, button_callback );
+
+ load_icon();
+
+ mb_tray_app_set_icon(app, pb, ImgIcon);
+
+ mb_tray_app_main (app);
+
+ return 1;
+}
diff --git a/applets/mb-applet-wireless.c b/applets/mb-applet-wireless.c
new file mode 100644
index 0000000..9f62cf6
--- /dev/null
+++ b/applets/mb-applet-wireless.c
@@ -0,0 +1,511 @@
+/*
+ * miniwave - Tiny 820.11 wireless
+ *
+ * Note: you can use themes from http://www.eskil.org/wavelan-applet/
+ *
+ * originally based on wmwave
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <libmb/mb.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(text) gettext(text)
+#else
+# define _(text) (text)
+#endif
+
+#define HAVE_LINUX_WIRELESS_H 1
+
+#ifdef HAVE_LINUX_WIRELESS_H
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <netdb.h> /* gethostbyname, getnetbyname */
+#include <linux/if_arp.h> /* For ARPHRD_ETHER */
+#include <linux/socket.h> /* For AF_INET & struct sockaddr */
+#include <sys/socket.h> /* For struct sockaddr_in */
+#include <linux/wireless.h>
+
+#endif
+
+#ifdef MB_HAVE_PNG
+#define IMG_EXT "png"
+#else
+#define IMG_EXT "xpm"
+#endif
+
+static int LastImg = 0;
+
+enum {
+ MW_BROKE = 1,
+ MW_NO_LINK,
+ MW_SIG_1_40,
+ MW_SIG_41_60,
+ MW_SIG_61_80,
+ MW_SIG_80_100,
+};
+
+#define MW_BROKE_IMG "broken-0." IMG_EXT
+#define MW_NO_LINK_IMG "no-link-0." IMG_EXT
+#define MW_SIG_1_40_IMG "signal-1-40." IMG_EXT
+#define MW_SIG_41_60_IMG "signal-41-60." IMG_EXT
+#define MW_SIG_61_80_IMG "signal-61-80." IMG_EXT
+#define MW_SIG_80_100_IMG "signal-81-100." IMG_EXT
+
+static char *ImgLookup[64] = {
+ MW_BROKE_IMG,
+ MW_NO_LINK_IMG,
+ MW_SIG_1_40_IMG,
+ MW_SIG_41_60_IMG,
+ MW_SIG_61_80_IMG,
+ MW_SIG_80_100_IMG,
+
+};
+
+static char *ThemeName = NULL;
+static MBPixbuf *pb;
+static MBPixbufImage *Imgs[6] = { 0,0,0,0,0,0 },
+ *ImgsScaled[6] = { 0,0,0,0,0,0 };
+static int CurImg = MW_BROKE;
+
+struct {
+
+ char iface[5];
+ char status[3];
+ float link;
+ float level;
+ float noise;
+ int nwid;
+ int crypt;
+ int misc;
+ int mode;
+
+} Mwd;
+
+#define HAVE_LINUX_WIRELESS_H 1
+
+#ifdef HAVE_LINUX_WIRELESS_H
+
+typedef struct iw_range iwrange;
+typedef struct iw_param iwparam;
+typedef struct iw_freq iwfreq;
+typedef struct iw_priv_args iwprivargs;
+typedef struct sockaddr sockaddr;
+
+typedef struct iw_info
+{
+
+ char name[IFNAMSIZ]; /* Wireless/protocol name */
+ int has_nwid;
+ iwparam nwid; /* Network ID */
+ int has_freq;
+ float freq; /* Frequency/channel */
+ int has_sens;
+ iwparam sens; /* sensitivity */
+ int has_key;
+ unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */
+ int key_size; /* Number of bytes */
+ int key_flags; /* Various flags */
+ int has_essid;
+ int essid_on;
+ char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID */
+ int has_nickname;
+ char nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
+ int has_ap_addr;
+ sockaddr ap_addr; /* Access point address */
+ int has_bitrate;
+ iwparam bitrate; /* Bit rate in bps */
+ int has_rts;
+ iwparam rts; /* RTS threshold in bytes */
+ int has_frag;
+ iwparam frag; /* Fragmentation threshold in bytes */
+ int has_mode;
+ int mode; /* Operation mode */
+ int has_power;
+ iwparam power; /* Power management parameters */
+#if 0
+ /* Stats */
+ iwstats stats;
+ int has_stats;
+ iwrange range;
+ int has_range;
+#endif
+} InterfaceInfo;
+
+InterfaceInfo ExtendedIWInfo;
+
+int
+get_extented_iw_info(InterfaceInfo *indata)
+{
+ InterfaceInfo *wdata = indata;
+ struct iwreq request;
+ int netsock_fd = -1;
+
+
+ strcpy( wdata->name, Mwd.iface );
+
+ /* open socket */
+
+ netsock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (netsock_fd == -1) return -1;
+
+ /* network name */
+
+ strcpy ( request.ifr_name, wdata->name);
+ request.u.essid.pointer = (caddr_t) wdata->essid;
+ request.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ request.u.essid.flags = 0;
+
+ if ( ioctl (netsock_fd, SIOCGIWESSID, &request) >= 0)
+ {
+ wdata->has_essid = 1;
+ wdata->essid_on = request.u.data.flags;
+ }
+ else wdata->has_essid = 0;
+
+#if 0 /* Stuff possibly breaks on some cards */
+
+ /* station name */
+
+ strcpy ( request.ifr_name, wdata->name);
+ request.u.essid.pointer = (caddr_t) wdata->nickname;
+ request.u.essid.length=0;
+ request.u.essid.flags=0;
+
+ if ( ioctl (netsock_fd, SIOCGIWNICKN, &request) < 0)
+ {
+ wdata->nickname[0] = '\0';
+ }
+
+ /* mode */
+
+ strcpy ( request.ifr_name, wdata->name);
+
+ if ( ioctl (netsock_fd, SIOCGIWMODE, &request) >= 0)
+ {
+ if ((request.u.mode < 6) && (request.u.mode >= 0))
+ wdata->mode = request.u.mode;
+ }
+
+ /* enc settings (on/off and key) */
+
+ wdata->has_key = 0;
+ strcpy ( request.ifr_name, wdata->name);
+ request.u.data.pointer = (caddr_t) wdata->key;
+ request.u.data.length=0;
+ request.u.data.flags=0;
+
+ if ( ioctl (netsock_fd, SIOCGIWENCODE, &request) >= 0)
+ {
+ wdata->has_key = 1;
+ wdata->key_size = request.u.data.length;
+ wdata->key_flags = request.u.data.flags;
+ }
+
+ /* power savings */
+
+ strcpy(request.ifr_name, wdata->name);
+ request.u.power.flags = 0;
+
+ if(ioctl(netsock_fd, SIOCGIWPOWER, &request) >= 0)
+ {
+ wdata->has_power = 1;
+ memcpy(&(wdata->power), &(request.u.power), sizeof(iwparam));
+ }
+
+ /* access point mac address */
+
+ strcpy(request.ifr_name, wdata->name);
+
+ if(ioctl(netsock_fd, SIOCGIWAP, &request) >= 0)
+ {
+ wdata->has_ap_addr = 1;
+ memcpy(&(wdata->ap_addr), &(request.u.ap_addr), sizeof (sockaddr));
+ }
+
+#endif
+
+ /* pack it up and spit it out */
+
+ close (netsock_fd);
+
+ return 0;
+}
+
+#endif
+
+Bool
+update_wireless(void) {
+ FILE *wireless; // File handle for /proc/net/wireless
+ int count;
+ char line[255];
+
+ Mwd.link = 0;
+ Mwd.level = 0;
+ Mwd.noise = 0;
+ Mwd.nwid = 0;
+ Mwd.crypt = 0;
+ Mwd.misc = 0;
+
+ if ((wireless = fopen ("/proc/net/wireless", "r")) != NULL)
+ {
+ fgets(line,sizeof(line),wireless);
+ fgets(line,sizeof(line),wireless);
+ if (fgets(line,sizeof(line),wireless) == NULL) {
+ Mwd.mode = 0;
+ Mwd.iface[0]=0;
+ } else {
+ sscanf(line,"%s %s %f %f %f %d %d %d",
+ Mwd.iface, Mwd.status, &Mwd.link, &Mwd.level,
+ &Mwd.noise, &Mwd.nwid, &Mwd.crypt, &Mwd.misc);
+ for(count=0;(count<strlen(line)) && (line[count]==0x20);count++);
+ strncpy(Mwd.iface,&line[count],5);
+ Mwd.iface[4]=0;
+ Mwd.mode = 1;
+ }
+ fclose(wireless);
+ }
+ else
+ {
+ fprintf (stderr, "miniwave: Wirless device /proc/net/wireless not found\nEnable radio networking and recompile your kernel\n");
+ return False;
+ }
+ return True;
+}
+
+void
+paint_callback (MBTrayApp *app, Drawable drw )
+{
+
+ MBPixbufImage *img_backing = NULL;
+
+ if (update_wireless())
+ {
+ if (Mwd.mode)
+ {
+ /* res->percent = (int)rint ((log (link) / log (92)) * 100.0); ? */
+ if (Mwd.link > 0 && Mwd.link < 41)
+ CurImg = MW_SIG_1_40;
+ else if (Mwd.link > 40 && Mwd.link < 61)
+ CurImg = MW_SIG_41_60;
+ else if (Mwd.link > 60 && Mwd.link < 81)
+ CurImg = MW_SIG_61_80;
+ else if (Mwd.link > 80)
+ CurImg = MW_SIG_80_100;
+ else
+ CurImg = MW_NO_LINK;
+ }
+ else CurImg = MW_NO_LINK;
+ }
+ else CurImg = MW_BROKE;
+
+ if (LastImg == CurImg) return;
+
+ img_backing = mb_tray_app_get_background (app, pb);
+
+ mb_pixbuf_img_copy_composite(pb, img_backing,
+ ImgsScaled[CurImg], 0, 0,
+ mb_pixbuf_img_get_width(ImgsScaled[0]),
+ mb_pixbuf_img_get_height(ImgsScaled[0]),
+ mb_tray_app_tray_is_vertical(app) ?
+ (mb_pixbuf_img_get_width(img_backing)-mb_pixbuf_img_get_width(ImgsScaled[0]))/2 : 0,
+ mb_tray_app_tray_is_vertical(app) ? 0 :
+ (mb_pixbuf_img_get_height(img_backing)-mb_pixbuf_img_get_height(ImgsScaled[0]))/2 );
+
+ mb_pixbuf_img_render_to_drawable(pb, img_backing, drw, 0, 0);
+
+ mb_pixbuf_img_free( pb, img_backing );
+
+ LastImg = CurImg;
+}
+
+
+void
+load_icons(MBTrayApp *app)
+{
+ int i;
+ char *icon_path;
+
+ for (i=0; i<6; i++)
+ {
+ if (Imgs[i] != NULL) mb_pixbuf_img_free(pb, Imgs[i]);
+ icon_path = mb_dot_desktop_icon_get_full_path (ThemeName,
+ 32,
+ ImgLookup[i]);
+
+ if (icon_path == NULL
+ || !(Imgs[i] = mb_pixbuf_img_new_from_file(pb, icon_path)))
+ {
+ fprintf(stderr, "minivol: failed to load icon\n" );
+ exit(1);
+ }
+
+ free(icon_path);
+ }
+
+}
+
+void
+resize_callback (MBTrayApp *app, int w, int h )
+{
+ int i;
+ int base_width = mb_pixbuf_img_get_width(Imgs[0]);
+ int base_height = mb_pixbuf_img_get_height(Imgs[0]);
+ int scale_width = base_width, scale_height = base_height;
+ Bool want_resize = True;
+
+ if (mb_tray_app_tray_is_vertical(app) && w < base_width)
+ {
+
+ scale_width = w;
+ scale_height = ( base_height * w ) / base_width;
+
+ want_resize = False;
+ }
+ else if (!mb_tray_app_tray_is_vertical(app) && h < base_height)
+ {
+ scale_height = h;
+ scale_width = ( base_width * h ) / base_height;
+ want_resize = False;
+ }
+
+ if (w < base_width && h < base_height
+ && ( scale_height > h || scale_width > w))
+ {
+ /* Something is really wrong to get here */
+ scale_height = h; scale_width = w;
+ want_resize = False;
+ }
+
+ if (want_resize) /* we only request a resize is absolutely needed */
+ {
+ LastImg = 0;
+ mb_tray_app_request_size (app, scale_width, scale_height);
+ }
+
+ for (i=0; i<6; i++)
+ {
+ if (ImgsScaled[i] != NULL) mb_pixbuf_img_free(pb, ImgsScaled[i]);
+ ImgsScaled[i] = mb_pixbuf_img_scale(pb, Imgs[i],
+ scale_width, scale_height);
+ }
+
+}
+
+void
+button_callback (MBTrayApp *app, int x, int y, Bool is_released )
+{
+ char tray_msg[256];
+
+ if (!is_released) return;
+
+ if (Mwd.mode)
+ {
+ if (get_extented_iw_info(&ExtendedIWInfo) == 0)
+ {
+ sprintf(tray_msg,
+ "%s:\n"
+ " Network: %s\n"
+ " Link %.1f\n Level %.1f\n Noise %.1f\n",
+ Mwd.iface,
+ ExtendedIWInfo.has_essid ? ExtendedIWInfo.essid : "Unkown",
+ Mwd.link, Mwd.level, Mwd.noise );
+ }
+ else
+ {
+ sprintf(tray_msg, _("%s:\n Link %.1f\n Level %.1f\n Noise %.1f\n"),
+ Mwd.iface, Mwd.link, Mwd.level, Mwd.noise );
+ }
+ }
+ else
+ sprintf(tray_msg, _("No wireless cards detected\n"));
+
+ mb_tray_app_tray_send_message(app, tray_msg, 5000);
+
+}
+
+void
+theme_callback (MBTrayApp *app, char *theme_name)
+{
+ if (!theme_name) return;
+ if (ThemeName) free(ThemeName);
+
+ LastImg = 0; /* Make sure paint gets updated */
+
+ ThemeName = strdup(theme_name);
+ load_icons(app);
+ resize_callback (app, mb_tray_app_width(app), mb_tray_app_width(app) );
+}
+
+void
+timeout_callback ( MBTrayApp *app )
+{
+ mb_tray_app_repaint (app);
+}
+
+int
+main( int argc, char *argv[])
+{
+ MBTrayApp *app = NULL;
+ struct timeval tv;
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, DATADIR "/locale");
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+ textdomain (PACKAGE);
+#endif
+
+ memset(&ExtendedIWInfo, 0, sizeof(InterfaceInfo));
+
+ app = mb_tray_app_new ( _("Wireless Monitor"),
+ resize_callback,
+ paint_callback,
+ &argc,
+ &argv );
+
+ pb = mb_pixbuf_new(mb_tray_app_xdisplay(app),
+ mb_tray_app_xscreen(app));
+
+ memset(&tv,0,sizeof(struct timeval));
+ tv.tv_sec = 2;
+
+ load_icons(app);
+
+ mb_tray_app_set_timeout_callback (app, timeout_callback, &tv);
+
+ mb_tray_app_set_button_callback (app, button_callback );
+
+ mb_tray_app_set_theme_change_callback (app, theme_callback );
+
+ mb_tray_app_set_icon(app, pb, Imgs[3]);
+
+ mb_tray_app_main (app);
+
+ return 1;
+}
+
+
+
diff --git a/applets/small-icons/Makefile.am b/applets/small-icons/Makefile.am
new file mode 100644
index 0000000..5ec861d
--- /dev/null
+++ b/applets/small-icons/Makefile.am
@@ -0,0 +1,25 @@
+pngs = \
+broken-0.png minisys.png no-link-0.png signal-61-80.png \
+mbmenu.png minitime.png signal-1-40.png signal-81-100.png \
+mbterm.png miniwave-icon.png signal-41-60.png term.png \
+
+xpms = \
+battery.xpm minisys.xpm no-link-0.xpm signal-41-60.xpm \
+broken-0.xpm minitimestrip.xpm oval_filled.xpm signal-61-80.xpm \
+mbmenu.xpm miniwave.xpm signal-1-40.xpm signal-81-100.xpm \
+
+EXTRA_DIST = $(xpms) $(pngs)
+
+if WANT_PNGS
+imgs = $(pngs)
+else
+imgs = $(xpms)
+endif
+
+pixmapsdir = $(datadir)/pixmaps/
+
+if WANT_SMALL_ICONS
+pixmaps_DATA = $(imgs)
+else
+pixmaps_DATA =
+endif \ No newline at end of file
diff --git a/applets/small-icons/broken-0.png b/applets/small-icons/broken-0.png
new file mode 100644
index 0000000..7410b27
--- /dev/null
+++ b/applets/small-icons/broken-0.png
Binary files differ
diff --git a/applets/small-icons/broken-0.xpm b/applets/small-icons/broken-0.xpm
new file mode 100644
index 0000000..1056414
--- /dev/null
+++ b/applets/small-icons/broken-0.xpm
@@ -0,0 +1,191 @@
+/* XPM */
+static char *broken-0[] = {
+/* columns rows colors chars-per-pixel */
+"32 16 169 2",
+" c black",
+". c #070708",
+"X c #323135",
+"o c #36353A",
+"O c #37373A",
+"+ c #3C3B3F",
+"@ c #3E3D42",
+"# c #2C4058",
+"$ c #3D4751",
+"% c #344C61",
+"& c #403F43",
+"* c #404655",
+"= c #424852",
+"- c #494D5A",
+"; c #48535C",
+": c #4C5360",
+"> c #555A61",
+", c #545B64",
+"< c #575B66",
+"1 c #565D6B",
+"2 c #595E62",
+"3 c #595E64",
+"4 c #5A5E64",
+"5 c #5A5F6A",
+"6 c #595F6D",
+"7 c #5D626F",
+"8 c #5C6873",
+"9 c #62666C",
+"0 c #64686E",
+"q c #636674",
+"w c #636876",
+"e c #656B74",
+"r c #616A79",
+"t c #626A78",
+"y c #646C79",
+"u c #6A6E76",
+"i c #6F6E78",
+"p c #65707C",
+"a c #66717C",
+"s c #6D717F",
+"d c #6E717F",
+"f c #706E74",
+"g c #706F7C",
+"h c #72757D",
+"j c #6D7083",
+"k c #707283",
+"l c #727583",
+"z c #717488",
+"x c #757884",
+"c c #777A8D",
+"v c #7B7881",
+"b c #787B84",
+"n c #7C7B86",
+"m c #7A7F8E",
+"M c #7D8189",
+"N c #963E30",
+"B c #983F31",
+"V c #A74535",
+"C c #A74635",
+"Z c #A84535",
+"A c #A94636",
+"S c #AF4938",
+"D c #B84D3B",
+"F c #BB4E3C",
+"G c #D05642",
+"H c #E45F49",
+"J c #808485",
+"K c #82858C",
+"L c #88878E",
+"P c #818397",
+"I c #838490",
+"U c #868593",
+"Y c #868998",
+"T c #86889D",
+"R c #8C8E96",
+"E c #8E8D9C",
+"W c #8F9395",
+"Q c #94929B",
+"! c #96959F",
+"~ c #909A9D",
+"^ c #8A8BA0",
+"/ c #8F91A5",
+"( c #9192A7",
+") c #9597AA",
+"_ c #9796AC",
+"` c #9995A2",
+"' c #9898A4",
+"] c #9999A4",
+"[ c #9C9CB3",
+"{ c #A29EAB",
+"} c #A09FAC",
+"| c #A4A6B9",
+" . c #A7A9BD",
+".. c #A9AAB5",
+"X. c #ACA8B4",
+"o. c #AEAFBE",
+"O. c #AFB2BF",
+"+. c #B0ACB7",
+"@. c #B0AEB9",
+"#. c #A8AAC0",
+"$. c #ADABC2",
+"%. c #ACAEC5",
+"&. c #B6B7CB",
+"*. c #B8B7C4",
+"=. c #BFBEC6",
+"-. c #BEBFD2",
+";. c #BCC2D1",
+":. c #BFC0D6",
+">. c #C4C7CD",
+",. c #C3C3DB",
+"<. c #C7CAD1",
+"1. c #CDCED6",
+"2. c #CACADF",
+"3. c #D5D4DE",
+"4. c #D7D8D7",
+"5. c #D8D8D6",
+"6. c #DBDBDC",
+"7. c #CACCE1",
+"8. c #C7DAE4",
+"9. c #D2D6EB",
+"0. c #D4D5EA",
+"q. c #D1D8EA",
+"w. c #D8DCEF",
+"e. c #DADEF0",
+"r. c #DBE0F5",
+"t. c #E0DEE8",
+"y. c #E3E0EB",
+"u. c #E4E6EE",
+"i. c #E7E5EF",
+"p. c #ECEEEF",
+"a. c #E2E3F5",
+"s. c #E1E4F3",
+"d. c #E3E4F3",
+"f. c #E3E5F2",
+"g. c #E1E4F5",
+"h. c #E7E5F2",
+"j. c #E4E5F6",
+"k. c #E5E7F8",
+"l. c #E5E9F7",
+"z. c #E9E7F3",
+"x. c #E9E9F7",
+"c. c #EBEDF5",
+"v. c #EAECF7",
+"b. c #ECEBF5",
+"n. c #EDECF4",
+"m. c #EEEFF6",
+"M. c #E9ECFB",
+"N. c #F0F1F6",
+"B. c #F1F1F6",
+"V. c #F1F2F6",
+"C. c #F3F2F6",
+"Z. c #F3F4F7",
+"A. c #F6F6F6",
+"S. c #F2F1F9",
+"D. c #F2F3FA",
+"F. c #F3F4F8",
+"G. c #F4F6F9",
+"H. c #F6F7F8",
+"J. c #F7F8F9",
+"K. c #F7F9F9",
+"L. c #F8F6F9",
+"P. c #F8FAF7",
+"I. c #F9FBF7",
+"U. c #FAFAF5",
+"Y. c #FAFAF9",
+"T. c #FAFBFB",
+"R. c #FBFBFB",
+"E. c #FEFEF9",
+"W. c None",
+/* pixels */
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.Y.W , z | O./ s p 8.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.~ = < j %.a.S.i.M.,.T y $ ; W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.a ; k [ 7.s.V.>.e =.l.0.$.P t t W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.J 6 ^ #.9.a.c.<.% # M V.f.w.-.) c 1 W.W.W.W.W.W.W.",
+"W.W.W.W.W.W. 5 ( &.q.d.m.V.p.* - i Y.m.v.e.7._ 8 W.W.W.W.W.W.",
+"W.W.W.W.W. 7 m ;.d.S.F.J.P.Y.J.T.A.Z.m.x.e.Y e W.W.W.W.W.",
+"W.W.W.W.W. n d .j.G.P.E.E.6.4.4.T.U.N.k.-.z q W.W.W.W.W.",
+"W.W.W.W.W. & I x U o.1.t.i.z.b.z.t.3.*.E g x @ W.W.W.W.W.",
+"W.W.W.W.W. O ! ] R h 0 3 > 2 3 0 u K ] ` @ W.W.W.W.W.",
+"W.W.W.W.W. . X f L } ..@.+.X.} Q v O . W.W.W.W.W.",
+"W.W.W.W.W.W. W.W.W.W.W.W.",
+"W.W.W. W.W.W.",
+"W.W.W. F H F S G C A G S F H F W.W.W.",
+"W.W.W. A F B W.W. A D N C D N W.W. A F B W.W.W.",
+"W.W.W. W.W. W.W. W.W. W.W.W."
+};
diff --git a/applets/small-icons/mbdesktop.png b/applets/small-icons/mbdesktop.png
new file mode 100644
index 0000000..f0ccf61
--- /dev/null
+++ b/applets/small-icons/mbdesktop.png
Binary files differ
diff --git a/applets/small-icons/mbdesktop.xpm b/applets/small-icons/mbdesktop.xpm
new file mode 100644
index 0000000..fe0c1ac
--- /dev/null
+++ b/applets/small-icons/mbdesktop.xpm
@@ -0,0 +1,207 @@
+/* XPM */
+static char *mbdesktop[] = {
+/* columns rows colors chars-per-pixel */
+"31 32 169 2",
+" c black",
+". c #161616",
+"X c #1B1B15",
+"o c #2B3444",
+"O c #364155",
+"+ c #4F4115",
+"@ c #5B4F2C",
+"# c #635731",
+"$ c #655930",
+"% c #6C5F34",
+"& c gray25",
+"* c #4D4E41",
+"= c #4B4B49",
+"- c #5D5D5D",
+"; c #44526A",
+": c #4B5564",
+"> c #61624D",
+", c #616252",
+"< c #696A58",
+"1 c #6E705B",
+"2 c #6F725C",
+"3 c #70725A",
+"4 c #70725D",
+"5 c #71725E",
+"6 c #72725E",
+"7 c #7A7D5F",
+"8 c #787963",
+"9 c #7A7C65",
+"0 c #767676",
+"q c #556784",
+"w c #737D8C",
+"e c #7E806B",
+"r c #7F816A",
+"t c #76849C",
+"y c #808266",
+"u c #828565",
+"i c #828665",
+"p c #838666",
+"a c #868969",
+"s c #878A69",
+"d c #878A6A",
+"f c #878B6B",
+"g c #878A6C",
+"h c #888C6C",
+"j c #898C6D",
+"k c #8A8D6D",
+"l c #8B8D72",
+"z c #8F9075",
+"x c #949773",
+"c c #959874",
+"v c #959875",
+"b c #969975",
+"n c #969976",
+"m c #979A76",
+"M c #979A77",
+"N c #989B77",
+"B c #989B78",
+"V c #999C78",
+"C c #999C79",
+"Z c #9A9C79",
+"A c #9A9D79",
+"S c #9A9D7A",
+"D c #9B9E7A",
+"F c #9B9E7B",
+"G c #9C9E7B",
+"H c #9C9F7C",
+"J c #9D9F7D",
+"K c #9DA07D",
+"L c #9EA07E",
+"P c #9EA17E",
+"I c #9EA17F",
+"U c #9FA17F",
+"Y c #9FA27F",
+"T c #D7AE74",
+"R c #F4B244",
+"E c #F7B544",
+"W c #F7B545",
+"Q c #F2B64D",
+"! c #F6D236",
+"~ c #FBE73B",
+"^ c #FCE93B",
+"/ c #FCEB3D",
+"( c gray52",
+") c #848C98",
+"_ c #9298A2",
+"` c #909CAF",
+"' c #A0A280",
+"] c #A0A380",
+"[ c #A0A381",
+"{ c #A1A381",
+"} c #A1A482",
+"| c #A3A583",
+" . c #A3A684",
+".. c #A4A785",
+"X. c #A5A786",
+"o. c #A6A887",
+"O. c #A6A987",
+"+. c #A7AA88",
+"@. c #A8AA89",
+"#. c #A8AB8A",
+"$. c #A9AB8A",
+"%. c #A9AC8A",
+"&. c #AAAC8B",
+"*. c #AAAD8B",
+"=. c #ABAD8C",
+"-. c #ACAE8D",
+";. c #ACAF8E",
+":. c #ADAF8E",
+">. c #AEB08F",
+",. c #AFB191",
+"<. c #B0B292",
+"1. c #B1B493",
+"2. c #B2B494",
+"3. c #B4B696",
+"4. c #B4B797",
+"5. c #B7B999",
+"6. c #B8BA9B",
+"7. c #B9BB9C",
+"8. c #BABC9D",
+"9. c #BBBD9D",
+"0. c #BBBD9E",
+"q. c #BCBE9F",
+"w. c #A0A0A0",
+"e. c gray66",
+"r. c gray68",
+"t. c #A5AFBE",
+"y. c #BBBCAC",
+"u. c #BBBBBB",
+"i. c #BCBCBC",
+"p. c gray74",
+"a. c #B6BECA",
+"s. c #C8C9BC",
+"d. c #CCCDB9",
+"f. c #CDCDB9",
+"g. c #CDCEB9",
+"h. c #CDCFB9",
+"j. c #CDCFBA",
+"k. c #CDD0BB",
+"l. c #CED0BC",
+"z. c #CFD0BC",
+"x. c #D0D1BD",
+"c. c #D1D3BF",
+"v. c #C1C1C1",
+"b. c gray76",
+"n. c #C3C3C3",
+"m. c #D2D3C0",
+"M. c #D3D4C0",
+"N. c #D6D7C6",
+"B. c gray88",
+"V. c #E2E2E2",
+"C. c gray89",
+"Z. c #E4E4E4",
+"A. c gray90",
+"S. c #E6E6E6",
+"D. c #E7E7E7",
+"F. c gray91",
+"G. c #E9E9E9",
+"H. c #EAEAEA",
+"J. c gray92",
+"K. c #ECECEC",
+"L. c gray93",
+"P. c #EEEEEE",
+"I. c #EFEFEF",
+"U. c gray94",
+"Y. c #F1F1F1",
+"T. c #FBFBFB",
+"R. c #FDFDFD",
+"E. c #FEFEFE",
+"W. c None",
+/* pixels */
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W. W.W.W.W.W.W.W.W.W.W.W.W.W.W.W. W.W.",
+"W. W.",
+" a.t.t.w a.` ` w ",
+" ` q ; * s.M.M.M.M.M.c.c.x.x.z.j.j.j.j.j.j.6 t.q ; ",
+" ` ; , q.q.e e 4.1.,.>.=.#.O. .2 ` ; ",
+" w , q.q.q. E.E.E.E.E.V.v. 8 ,.>.=.$.$. .X.[ 1 ` ",
+" y.q.q.q. E.Y.Y.Y.Y.v.T.e. 9 =.#.$.X. .] Y u ",
+" M.q.q.q. E.Y.Y.Y.Y.r.0 - & =.#. 3 ] L u ",
+"W. M.q.q.q. E.Y.Y.Y.Y.V.( = . *. ~ Q L H u W.",
+"W. M.q.q.q. E.Y.K.Y.K.K.Y.K.i. / E # L F u W.",
+"W. M.q.q.q. E.K.K.K.K.J.J.J.i. ~ W % r H Z u W.",
+"W. c.q.q.q. E.J.Z.J.J.Z.J.D. ! R @ f L Z B i W.",
+"W. x.q.q.q. T.J.J.D.Z.J.Z.J. T $ L K Z Z N u W.",
+"W. x.q.q.q. E.Z.Z.J.Z.J.Z. + ] K K Z Z v u W.",
+"W. j.q.q.q. E.J.D.Z.Z.Z.Z. ] Y K K B c v u W.",
+"W. j.q.q.6. T.Z.Z.Z.Z.V.C.V.i. Y L G Z c c x u W.",
+"W. N.q.q.6. v.i.i.i.i.i.i.u.w.X L L Z N c x x u W.",
+" t 6 q.6.6.< > L F Z N c x x 7 _ ",
+" q t 4 6.6.4.4.,.>.>.#.O.X.X.] [ F Z N c c c x a.; ",
+" q q t l x j k k f f f a u u u u u u u u u u t.q ; ",
+" O O O : ) O O o ",
+" ",
+" ",
+"W. W.",
+"W.W. W.W.W.W.W.W.W.W.W.W.W.W.W.W.W. W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.",
+"W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W.W."
+};
diff --git a/applets/small-icons/mbmenu.png b/applets/small-icons/mbmenu.png
new file mode 100644
index 0000000..1ed6cd0
--- /dev/null
+++ b/applets/small-icons/mbmenu.png
Binary files differ
diff --git a/applets/small-icons/mbmenu.xpm b/applets/small-icons/mbmenu.xpm
new file mode 100644
index 0000000..dc115ae
--- /dev/null
+++ b/applets/small-icons/mbmenu.xpm
@@ -0,0 +1,68 @@
+/* XPM */
+static char *mbmenu[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 46 1",
+" c black",
+". c #314E6C",
+"X c #494949",
+"o c #4C4C4C",
+"O c gray30",
+"+ c gray31",
+"@ c #505050",
+"# c #435E7A",
+"$ c #47617C",
+"% c #496582",
+"& c #5A718A",
+"* c #6A7D94",
+"= c #6B7F95",
+"- c #778697",
+"; c #778797",
+": c #7E8C9A",
+"> c #7F8D9B",
+", c #738FAE",
+"< c #7590AF",
+"1 c #7792B1",
+"2 c #7893B0",
+"3 c #7994B2",
+"4 c #86A1BD",
+"5 c #91A4BA",
+"6 c #92A5BB",
+"7 c #97AABF",
+"8 c gray74",
+"9 c #88A3C0",
+"0 c #8AA5C1",
+"q c #8CA7C3",
+"w c #8DA8C5",
+"e c #8FAAC6",
+"r c #91ACC8",
+"t c #93AECA",
+"y c #9BAEC2",
+"u c #95B0CB",
+"i c #A5B6CA",
+"p c #A8B9CD",
+"a c #A9BBCE",
+"s c #AABCCF",
+"d c #ACBDD0",
+"f c #ADBED1",
+"g c #AEC0D3",
+"h c #DADADA",
+"j c gray100",
+"k c None",
+/* pixels */
+"kkkkkkkkkkkkkkkk",
+"kk............kk",
+"k.&7iiaasddfy$.k",
+"k.5,<1*@XXX+;3.k",
+"k.i<13+hjjjh+4.k",
+"k.i*@XXjjjjjX4.k",
+"k.iXjjXjjjjjXe.k",
+"k.iXjjXjjjjjXe.k",
+"k.iXjjXjjjjjXe.k",
+"k.iXjjXjjjjjXe.k",
+"k.iXjj8+XXX+4e.k",
+"k.i+hjjjh+ee5u.k",
+"k.5;@XXXo:ttr4.k",
+"k.#240ewertu4$.k",
+"k.............kk",
+"kkkkkkkkkkkkkkkk"
+};
diff --git a/applets/small-icons/miniapm-power.png b/applets/small-icons/miniapm-power.png
new file mode 100644
index 0000000..d5bd348
--- /dev/null
+++ b/applets/small-icons/miniapm-power.png
Binary files differ
diff --git a/applets/small-icons/miniapm-power.xpm b/applets/small-icons/miniapm-power.xpm
new file mode 100644
index 0000000..8fc8996
--- /dev/null
+++ b/applets/small-icons/miniapm-power.xpm
@@ -0,0 +1,43 @@
+/* XPM */
+static char *miniapm-power[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 21 1",
+" c black",
+". c #181818",
+"X c gray19",
+"o c gray20",
+"O c #3A3A3A",
+"+ c #3F3F3F",
+"@ c gray26",
+"# c gray28",
+"$ c #505050",
+"% c #5A5A5A",
+"& c gray40",
+"* c #717171",
+"= c gray59",
+"- c #9A9A9A",
+"; c gray61",
+": c gray71",
+"> c #BCBCBC",
+", c gray80",
+"< c #E2E2E2",
+"1 c #F9F9F9",
+"2 c None",
+/* pixels */
+"2222 222222",
+"2 <@$& 22",
+" ,:= 1oO$&&&& 22",
+" <XO+&&&& 22",
+"2222 >oO$&&&& ",
+"2 -oo%&&&& ",
+" :;*.-O#&&&&& 22",
+" %O%& 22",
+"2222 222222",
+"2222222222222222",
+"2 2",
+"2 2",
+"2 2",
+"2 2",
+"2 2",
+"2 2"
+};
diff --git a/applets/small-icons/miniapm.png b/applets/small-icons/miniapm.png
new file mode 100644
index 0000000..c4fe874
--- /dev/null
+++ b/applets/small-icons/miniapm.png
Binary files differ
diff --git a/applets/small-icons/miniapm.xpm b/applets/small-icons/miniapm.xpm
new file mode 100644
index 0000000..32cf2fa
--- /dev/null
+++ b/applets/small-icons/miniapm.xpm
@@ -0,0 +1,67 @@
+/* XPM */
+static char *miniapm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 45 1",
+" c black",
+". c #202020",
+"X c gray21",
+"o c #484848",
+"O c #505050",
+"+ c #656565",
+"@ c gray46",
+"# c gray47",
+"$ c #70861F",
+"% c #7F8319",
+"& c #7C831E",
+"* c #818418",
+"= c #85993D",
+"- c #84A523",
+"; c #8EAD23",
+": c #8ABA2B",
+"> c #8FBF2A",
+", c #8EBF2D",
+"< c #95AC22",
+"1 c #9FA827",
+"2 c #96BC2F",
+"3 c #9ABA26",
+"4 c #98BB2A",
+"5 c #A0C32E",
+"6 c #A4C32C",
+"7 c #A9C12C",
+"8 c #A6C131",
+"9 c #C1D471",
+"0 c #868686",
+"q c #8E8E8E",
+"w c #A0A0A0",
+"e c #A2A2A2",
+"r c gray67",
+"t c gray68",
+"y c gray74",
+"u c #CCDE8F",
+"i c #D1DE8D",
+"p c #DADC8C",
+"a c #D2DCBB",
+"s c #DFE3A9",
+"d c #D5D5D5",
+"f c #EFF4DB",
+"g c #F4F8E8",
+"h c #F9FAF2",
+"j c None",
+/* pixels */
+"j jj",
+"j 32>4 jj",
+"j.+etyydyffgh j",
+"j +######ipusa j",
+"j ,5889 j",
+"j O0OO0 :678= j",
+"j rqret -;<1 j",
+"j Xo@Xo $**& jj",
+"j jj",
+"jjjjjjjjjjjjjjjj",
+"j j",
+"j j",
+"j j",
+"j j",
+"j j",
+"j j"
+};
diff --git a/applets/small-icons/minisys.png b/applets/small-icons/minisys.png
new file mode 100644
index 0000000..cb8c9e0
--- /dev/null
+++ b/applets/small-icons/minisys.png
Binary files differ
diff --git a/applets/small-icons/minisys.xpm b/applets/small-icons/minisys.xpm
new file mode 100644
index 0000000..afec042
--- /dev/null
+++ b/applets/small-icons/minisys.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char *minisys[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 5 1",
+" c black",
+". c green",
+"X c red",
+"o c yellow",
+"O c None",
+/* pixels */
+"OOOOOOOOOOOOOOOO",
+"O OO O",
+"O OO O",
+"O oo OO oo O",
+"O oo OO oo O",
+"O oo OO oo O",
+"O oo OO XX O",
+"O oo OO XX O",
+"O .. OO XX O",
+"O .. OO XX O",
+"O .. OO XX O",
+"O .. OO XX O",
+"O .. OO XX O",
+"O OO O",
+"O OO O",
+"OOOOOOOOOOOOOOOO"
+};
diff --git a/applets/small-icons/no-link-0.png b/applets/small-icons/no-link-0.png
new file mode 100644
index 0000000..d62712e
--- /dev/null
+++ b/applets/small-icons/no-link-0.png
Binary files differ
diff --git a/applets/small-icons/no-link-0.xpm b/applets/small-icons/no-link-0.xpm
new file mode 100644
index 0000000..c8de55c
--- /dev/null
+++ b/applets/small-icons/no-link-0.xpm
@@ -0,0 +1,195 @@
+/* XPM */
+static char *no-link-0[] = {
+/* columns rows colors chars-per-pixel */
+"32 16 173 2",
+" c black",
+". c #070708",
+"X c #323135",
+"o c #36353A",
+"O c #37373A",
+"+ c #3C3B3F",
+"@ c #3E3D42",
+"# c #2C4058",
+"$ c #3D4751",
+"% c #344C61",
+"& c #403F43",
+"* c #404655",
+"= c #424852",
+"- c #494D5A",
+"; c #48535C",
+": c #4C5360",
+"> c #555A61",
+", c #545B64",
+"< c #575B66",
+"1 c #565D6B",
+"2 c #595E62",
+"3 c #595E64",
+"4 c #5A5E64",
+"5 c #5A5F6A",
+"6 c #595F6D",
+"7 c #5D626F",
+"8 c #5C6873",
+"9 c #62666C",
+"0 c #64686E",
+"q c #636674",
+"w c #636876",
+"e c #656B74",
+"r c #616A79",
+"t c #626A78",
+"y c #646C79",
+"u c #6A6E76",
+"i c #6F6E78",
+"p c #65707C",
+"a c #66717C",
+"s c #6D717F",
+"d c #6E717F",
+"f c #706E74",
+"g c #706F7C",
+"h c #72757D",
+"j c #6D7083",
+"k c #707283",
+"l c #727583",
+"z c #717488",
+"x c #757884",
+"c c #777A8D",
+"v c #7B7881",
+"b c #787B84",
+"n c #7C7B86",
+"m c #7A7F8E",
+"M c #7D8189",
+"N c #808485",
+"B c #82858C",
+"V c #88878E",
+"C c #818397",
+"Z c #838490",
+"A c #868593",
+"S c #868998",
+"D c #86889D",
+"F c #8C8E96",
+"G c #8E8D9C",
+"H c #8F9395",
+"J c #94929B",
+"K c #96959F",
+"L c #909A9D",
+"P c #8A8BA0",
+"I c #8F91A5",
+"U c #9192A7",
+"Y c #9597AA",
+"T c #9796AC",
+"R c #9995A2",
+"E c #9898A4",
+"W c #9999A4",
+"Q c #9C9CB3",
+"! c #A29EAB",
+"~ c #A09FAC",
+"^ c #A4A6B9",
+"/ c #A7A9BD",
+"( c #A9AAB5",
+") c #ACA8B4",
+"_ c #AEAFBE",
+"` c #AFB2BF",
+"' c #B0ACB7",
+"] c #B0AEB9",
+"[ c #B6B6B6",
+"{ c gray74",
+"} c gray",
+"| c gray75",
+" . c #A8AAC0",
+".. c #ADABC2",
+"X. c #ACAEC5",
+"o. c #B6B7CB",
+"O. c #B8B7C4",
+"+. c #BFBEC6",
+"@. c #BEBFD2",
+"#. c #BCC2D1",
+"$. c #BFC0D6",
+"%. c #C0C0C0",
+"&. c #C1C1C1",
+"*. c #C4C7CD",
+"=. c #C8C8C8",
+"-. c gray79",
+";. c #CACACA",
+":. c #CBCBCB",
+">. c #C3C3DB",
+",. c #C7CAD1",
+"<. c #CDCED6",
+"1. c #CACADF",
+"2. c gray83",
+"3. c gray84",
+"4. c #D7D7D7",
+"5. c #D5D4DE",
+"6. c #D7D8D7",
+"7. c #D8D8D6",
+"8. c #DBDBDC",
+"9. c #CACCE1",
+"0. c #C7DAE4",
+"q. c #D2D6EB",
+"w. c #D4D5EA",
+"e. c #D1D8EA",
+"r. c #D8DCEF",
+"t. c #DADEF0",
+"y. c #DBE0F5",
+"u. c #E0DEE8",
+"i. c #E3E0EB",
+"p. c #E4E6EE",
+"a. c #E7E5EF",
+"s. c #E9E9E9",
+"d. c #ECEEEF",
+"f. c #E2E3F5",
+"g. c #E1E4F3",
+"h. c #E3E4F3",
+"j. c #E3E5F2",
+"k. c #E1E4F5",
+"l. c #E7E5F2",
+"z. c #E4E5F6",
+"x. c #E5E7F8",
+"c. c #E5E9F7",
+"v. c #E9E7F3",
+"b. c #E9E9F7",
+"n. c #EBEDF5",
+"m. c #EAECF7",
+"M. c #ECEBF5",
+"N. c #EDECF4",
+"B. c #EEEFF6",
+"V. c #E9ECFB",
+"C. c #F0F1F6",
+"Z. c #F1F1F6",
+"A. c #F1F2F6",
+"S. c #F3F2F6",
+"D. c #F3F4F7",
+"F. c #F6F6F6",
+"G. c #F2F1F9",
+"H. c #F2F3FA",
+"J. c #F3F4F8",
+"K. c #F4F6F9",
+"L. c #F6F7F8",
+"P. c #F7F8F9",
+"I. c #F7F9F9",
+"U. c #F8F6F9",
+"Y. c #F8FAF7",
+"T. c #F9FBF7",
+"R. c #FAFAF5",
+"E. c #FAFAF9",
+"W. c #FAFBFB",
+"Q. c #FBFBFB",
+"!. c #FEFEF9",
+"~. c gray100",
+"^. c None",
+/* pixels */
+"^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.",
+"^.^.^.^.^.^.^.^.^.^.^.E.H , z ^ ` I s p 0.^.^.^.^.^.^.^.^.^.^.^.",
+"^.^.^.^.^.^.^.^.^.L = < j X.f.G.a.V.>.D y $ ; ^.^.^.^.^.^.^.^.^.",
+"^.^.^.^.^.^.^.^.a ; k Q 9.g.A.*.e +.c.w...C t t ^.^.^.^.^.^.^.^.",
+"^.^.^.^.^.^.^.N 6 P .q.f.n.,.% # M A.j.r.@.Y c 1 ^.^.^.^.^.^.^.",
+"^.^.^.^.^.^. 5 U o.e.h.B.A.d.* - i E.B.m.t.9.T 8 ^.^.^.^.^.^.",
+"^.^.^.^.^. 7 m #.h.G.J.P.Y.E.P.W.F.D.B.b.t.S e ^.^.^.^.^.",
+"^.^.^.^.^. n d / z.K.Y.!.!.8.6.6.W.R.C.x.@.z q ^.^.^.^.^.",
+"^.^.^.^.^. & Z x A _ <.u.a.v.M.v.u.5.O.G g b @ ^.^.^.^.^.",
+"^.^.^.^.^. O K W F h 0 3 > 4 3 9 u B W R + ^.^.^.^.^.",
+"^.^.^.^.^. . X f V ~ ( ] ' ) ! J v O . ^.^.^.^.^.",
+"^.^.^.^.^.^. ^.^.^.^.^.^.",
+"^.^.^. ^.^.^.",
+"^.^.^. 3.~.;. ;.s.[ &.s.| 4.~.:. ^.^.^.",
+"^.^.^. ;.3.| ^.^. ;.3.| ;.2.| ^.^. :.4.&. ^.^.^.",
+"^.^.^. ^.^. ^.^. ^.^. ^.^.^."
+};
diff --git a/applets/small-icons/signal-1-40.png b/applets/small-icons/signal-1-40.png
new file mode 100644
index 0000000..111a2dc
--- /dev/null
+++ b/applets/small-icons/signal-1-40.png
Binary files differ
diff --git a/applets/small-icons/signal-1-40.xpm b/applets/small-icons/signal-1-40.xpm
new file mode 100644
index 0000000..7ba5795
--- /dev/null
+++ b/applets/small-icons/signal-1-40.xpm
@@ -0,0 +1,197 @@
+/* XPM */
+static char *signal-1-40[] = {
+/* columns rows colors chars-per-pixel */
+"32 16 175 2",
+" c black",
+". c #070708",
+"X c #323135",
+"o c #36353A",
+"O c #37373A",
+"+ c #3C3B3F",
+"@ c #3E3D42",
+"# c #2C4058",
+"$ c #3D4751",
+"% c #344C61",
+"& c #403F43",
+"* c #404655",
+"= c #424852",
+"- c #494D5A",
+"; c #48535C",
+": c #4C5360",
+"> c #555A61",
+", c #545B64",
+"< c #575B66",
+"1 c #565D6B",
+"2 c #595E62",
+"3 c #595E64",
+"4 c #5A5E64",
+"5 c #5A5F6A",
+"6 c #595F6D",
+"7 c #5D626F",
+"8 c #5C6873",
+"9 c #62666C",
+"0 c #64686E",
+"q c #636674",
+"w c #636876",
+"e c #656B74",
+"r c #616A79",
+"t c #626A78",
+"y c #646C79",
+"u c #6A6E76",
+"i c #6F6E78",
+"p c #65707C",
+"a c #66717C",
+"s c #6D717F",
+"d c #6E717F",
+"f c #706E74",
+"g c #706F7C",
+"h c #72757D",
+"j c #6D7083",
+"k c #707283",
+"l c #727583",
+"z c #717488",
+"x c #757884",
+"c c #777A8D",
+"v c #7B7881",
+"b c #787B84",
+"n c #7C7B86",
+"m c #7A7F8E",
+"M c #7D8189",
+"N c #A98B20",
+"B c #BC9A23",
+"V c #D0AA27",
+"C c #FED02F",
+"Z c #808485",
+"A c #82858C",
+"S c #88878E",
+"D c #818397",
+"F c #838490",
+"G c #868593",
+"H c #868998",
+"J c #86889D",
+"K c #8C8E96",
+"L c #8E8D9C",
+"P c #8F9395",
+"I c #94929B",
+"U c #96959F",
+"Y c #909A9D",
+"T c #8A8BA0",
+"R c #8F91A5",
+"E c #9192A7",
+"W c #9597AA",
+"Q c #9796AC",
+"! c #9995A2",
+"~ c #9898A4",
+"^ c #9999A4",
+"/ c #9C9CB3",
+"( c #A29EAB",
+") c #A09FAC",
+"_ c #A4A6B9",
+"` c #A7A9BD",
+"' c #A9AAB5",
+"] c #ACA8B4",
+"[ c #AEAFBE",
+"{ c #AFB2BF",
+"} c #B0ACB7",
+"| c #B0AEB9",
+" . c #B6B6B6",
+".. c gray74",
+"X. c gray",
+"o. c #A8AAC0",
+"O. c #ADABC2",
+"+. c #ACAEC5",
+"@. c #B6B7CB",
+"#. c #B8B7C4",
+"$. c #BFBEC6",
+"%. c #BEBFD2",
+"&. c #BCC2D1",
+"*. c #BFC0D6",
+"=. c #C0C0C0",
+"-. c #C1C1C1",
+";. c #C4C7CD",
+":. c #C8C8C8",
+">. c gray79",
+",. c #CACACA",
+"<. c #CBCBCB",
+"1. c #C3C3DB",
+"2. c #C7CAD1",
+"3. c #CDCED6",
+"4. c #CACADF",
+"5. c gray83",
+"6. c #D7D7D7",
+"7. c #D5D4DE",
+"8. c #D7D8D7",
+"9. c #D8D8D6",
+"0. c #DBDBDC",
+"q. c #CACCE1",
+"w. c #C7DAE4",
+"e. c #D2D6EB",
+"r. c #D4D5EA",
+"t. c #D1D8EA",
+"y. c #D8DCEF",
+"u. c #DADEF0",
+"i. c #DBE0F5",
+"p. c #E0DEE8",
+"a. c #E3E0EB",
+"s. c #E4E6EE",
+"d. c #E7E5EF",
+"f. c #E9E9E9",
+"g. c #ECEEEF",
+"h. c #E2E3F5",
+"j. c #E1E4F3",
+"k. c #E3E4F3",
+"l. c #E3E5F2",
+"z. c #E1E4F5",
+"x. c #E7E5F2",
+"c. c #E4E5F6",
+"v. c #E5E7F8",
+"b. c #E5E9F7",
+"n. c #E9E7F3",
+"m. c #E9E9F7",
+"M. c #EBEDF5",
+"N. c #EAECF7",
+"B. c #ECEBF5",
+"V. c #EDECF4",
+"C. c #EEEFF6",
+"Z. c #E9ECFB",
+"A. c #F0F1F6",
+"S. c #F1F1F6",
+"D. c #F1F2F6",
+"F. c #F3F2F6",
+"G. c #F3F4F7",
+"H. c #F6F6F6",
+"J. c #F2F1F9",
+"K. c #F2F3FA",
+"L. c #F3F4F8",
+"P. c #F4F6F9",
+"I. c #F6F7F8",
+"U. c #F7F8F9",
+"Y. c #F7F9F9",
+"T. c #F8F6F9",
+"R. c #F8FAF7",
+"E. c #F9FBF7",
+"W. c #FAFAF5",
+"Q. c #FAFAF9",
+"!. c #FAFBFB",
+"~. c #FBFBFB",
+"^. c #FEFEF9",
+"/. c gray100",
+"(. c None",
+/* pixels */
+"(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.",
+"(.(.(.(.(.(.(.(.(.(.(.Q.P , z _ { R s p w.(.(.(.(.(.(.(.(.(.(.(.",
+"(.(.(.(.(.(.(.(.(.Y = < j +.h.J.d.Z.1.J y $ ; (.(.(.(.(.(.(.(.(.",
+"(.(.(.(.(.(.(.(.a ; k / q.j.D.;.e $.b.r.O.D t t (.(.(.(.(.(.(.(.",
+"(.(.(.(.(.(.(.Z 6 T o.e.h.M.2.% # M D.l.y.%.W c 1 (.(.(.(.(.(.(.",
+"(.(.(.(.(.(. 5 E @.t.k.C.D.g.* - i Q.C.N.u.q.Q 8 (.(.(.(.(.(.",
+"(.(.(.(.(. 7 m &.k.J.L.U.R.Q.U.!.H.G.C.m.u.H e (.(.(.(.(.",
+"(.(.(.(.(. n d ` c.P.R.^.^.0.8.8.!.W.A.v.%.z q (.(.(.(.(.",
+"(.(.(.(.(. & F x G [ 3.p.d.n.B.n.p.7.#.L h x @ (.(.(.(.(.",
+"(.(.(.(.(. O U ^ K h 0 3 > 4 3 9 u A ! ! @ (.(.(.(.(.",
+"(.(.(.(.(. . X f S ) ' | } ] ( I v O . (.(.(.(.(.",
+"(.(.(.(.(.(. (.(.(.(.(.(.",
+"(.(.(. (.(.(.",
+"(.(.(. V C V ,.f. . -.f.X. 6./.<. (.(.(.",
+"(.(.(. B V N (.(. ,.5... ,.5... (.(. <.6.-. (.(.(.",
+"(.(.(. (.(. (.(. (.(. (.(.(."
+};
diff --git a/applets/small-icons/signal-41-60.png b/applets/small-icons/signal-41-60.png
new file mode 100644
index 0000000..cf1fcbc
--- /dev/null
+++ b/applets/small-icons/signal-41-60.png
Binary files differ
diff --git a/applets/small-icons/signal-41-60.xpm b/applets/small-icons/signal-41-60.xpm
new file mode 100644
index 0000000..b74c636
--- /dev/null
+++ b/applets/small-icons/signal-41-60.xpm
@@ -0,0 +1,199 @@
+/* XPM */
+static char *signal-41-60[] = {
+/* columns rows colors chars-per-pixel */
+"32 16 177 2",
+" c black",
+". c #070708",
+"X c #323135",
+"o c #36353A",
+"O c #37373A",
+"+ c #3C3B3F",
+"@ c #3E3D42",
+"# c #2C4058",
+"$ c #3D4751",
+"% c #344C61",
+"& c #403F43",
+"* c #404655",
+"= c #424852",
+"- c #494D5A",
+"; c #48535C",
+": c #4C5360",
+"> c #555A61",
+", c #545B64",
+"< c #575B66",
+"1 c #565D6B",
+"2 c #595E62",
+"3 c #595E64",
+"4 c #5A5E64",
+"5 c #5A5F6A",
+"6 c #595F6D",
+"7 c #5D626F",
+"8 c #5C6873",
+"9 c #62666C",
+"0 c #64686E",
+"q c #636674",
+"w c #636876",
+"e c #656B74",
+"r c #616A79",
+"t c #626A78",
+"y c #646C79",
+"u c #6A6E76",
+"i c #6F6E78",
+"p c #65707C",
+"a c #66717C",
+"s c #6D717F",
+"d c #6E717F",
+"f c #706E74",
+"g c #706F7C",
+"h c #72757D",
+"j c #6D7083",
+"k c #707283",
+"l c #727583",
+"z c #717488",
+"x c #757884",
+"c c #777A8D",
+"v c #7B7881",
+"b c #787B84",
+"n c #7C7B86",
+"m c #7A7F8E",
+"M c #1FA81F",
+"N c #20AB20",
+"B c #23BB23",
+"V c #22BC22",
+"C c #23BD23",
+"Z c #24C324",
+"A c #26CE26",
+"S c #27D127",
+"D c #2BE92B",
+"F c #30FF30",
+"G c #7D8189",
+"H c #808485",
+"J c #82858C",
+"K c #88878E",
+"L c #818397",
+"P c #838490",
+"I c #868593",
+"U c #868998",
+"Y c #86889D",
+"T c #8C8E96",
+"R c #8E8D9C",
+"E c #8F9395",
+"W c #94929B",
+"Q c #96959F",
+"! c #909A9D",
+"~ c #8A8BA0",
+"^ c #8F91A5",
+"/ c #9192A7",
+"( c #9597AA",
+") c #9796AC",
+"_ c #9995A2",
+"` c #9898A4",
+"' c #9999A4",
+"] c #9C9CB3",
+"[ c #A29EAB",
+"{ c #A09FAC",
+"} c #A4A6B9",
+"| c #A7A9BD",
+" . c #A9AAB5",
+".. c #ACA8B4",
+"X. c #AEAFBE",
+"o. c #AFB2BF",
+"O. c #B0ACB7",
+"+. c #B0AEB9",
+"@. c gray",
+"#. c #A8AAC0",
+"$. c #ADABC2",
+"%. c #ACAEC5",
+"&. c #B6B7CB",
+"*. c #B8B7C4",
+"=. c #BFBEC6",
+"-. c #BEBFD2",
+";. c #BCC2D1",
+":. c #BFC0D6",
+">. c #C0C0C0",
+",. c #C1C1C1",
+"<. c #C4C7CD",
+"1. c #C8C8C8",
+"2. c #CBCBCB",
+"3. c #C3C3DB",
+"4. c #C7CAD1",
+"5. c #CDCED6",
+"6. c #CACADF",
+"7. c gray83",
+"8. c #D7D7D7",
+"9. c #D5D4DE",
+"0. c #D7D8D7",
+"q. c #D8D8D6",
+"w. c #DBDBDC",
+"e. c #CACCE1",
+"r. c #C7DAE4",
+"t. c #D2D6EB",
+"y. c #D4D5EA",
+"u. c #D1D8EA",
+"i. c #D8DCEF",
+"p. c #DADEF0",
+"a. c #DBE0F5",
+"s. c #E0DEE8",
+"d. c #E3E0EB",
+"f. c #E4E6EE",
+"g. c #E7E5EF",
+"h. c #E9E9E9",
+"j. c #ECEEEF",
+"k. c #E2E3F5",
+"l. c #E1E4F3",
+"z. c #E3E4F3",
+"x. c #E3E5F2",
+"c. c #E1E4F5",
+"v. c #E7E5F2",
+"b. c #E4E5F6",
+"n. c #E5E7F8",
+"m. c #E5E9F7",
+"M. c #E9E7F3",
+"N. c #E9E9F7",
+"B. c #EBEDF5",
+"V. c #EAECF7",
+"C. c #ECEBF5",
+"Z. c #EDECF4",
+"A. c #EEEFF6",
+"S. c #E9ECFB",
+"D. c #F0F1F6",
+"F. c #F1F1F6",
+"G. c #F1F2F6",
+"H. c #F3F2F6",
+"J. c #F3F4F7",
+"K. c #F6F6F6",
+"L. c #F2F1F9",
+"P. c #F2F3FA",
+"I. c #F3F4F8",
+"U. c #F4F6F9",
+"Y. c #F6F7F8",
+"T. c #F7F8F9",
+"R. c #F7F9F9",
+"E. c #F8F6F9",
+"W. c #F8FAF7",
+"Q. c #F9FBF7",
+"!. c #FAFAF5",
+"~. c #FAFAF9",
+"^. c #FAFBFB",
+"/. c #FBFBFB",
+"(. c #FEFEF9",
+"). c gray100",
+"_. c None",
+/* pixels */
+"_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._.",
+"_._._._._._._._._._._.~.E , z } o.^ s p r._._._._._._._._._._._.",
+"_._._._._._._._._.! = < j %.k.L.g.S.3.Y y $ ; _._._._._._._._._.",
+"_._._._._._._._.a ; k ] e.l.G.<.e =.m.y.$.L t t _._._._._._._._.",
+"_._._._._._._.H 6 ~ #.t.k.B.4.% # G G.x.i.-.( c 1 _._._._._._._.",
+"_._._._._._. 5 / &.u.z.A.G.j.* - i ~.A.V.p.e.) 8 _._._._._._.",
+"_._._._._. 7 m ;.z.L.I.T.W.~.T.^.K.J.A.N.p.U e _._._._._.",
+"_._._._._. n d | b.U.W.(.(.w.0.0.^.!.D.n.-.z q _._._._._.",
+"_._._._._. & P x I X.5.s.g.M.C.M.s.9.*.R g b @ _._._._._.",
+"_._._._._. O Q ' T h 0 3 > 2 3 0 u J ' _ + _._._._._.",
+"_._._._._. . X f K { .+.O...{ W v O . _._._._._.",
+"_._._._._._. _._._._._._.",
+"_._._. _._._.",
+"_._._. S F S Z D B ,.h.@. 8.).2. _._._.",
+"_._._. C S N _._. C A M 1.7.@. _._. 2.8.,. _._._.",
+"_._._. _._. _._. _._. _._._."
+};
diff --git a/applets/small-icons/signal-61-80.png b/applets/small-icons/signal-61-80.png
new file mode 100644
index 0000000..76ec399
--- /dev/null
+++ b/applets/small-icons/signal-61-80.png
Binary files differ
diff --git a/applets/small-icons/signal-61-80.xpm b/applets/small-icons/signal-61-80.xpm
new file mode 100644
index 0000000..ad59b51
--- /dev/null
+++ b/applets/small-icons/signal-61-80.xpm
@@ -0,0 +1,196 @@
+/* XPM */
+static char *signal-61-80[] = {
+/* columns rows colors chars-per-pixel */
+"32 16 174 2",
+" c black",
+". c #070708",
+"X c #323135",
+"o c #36353A",
+"O c #37373A",
+"+ c #3C3B3F",
+"@ c #3E3D42",
+"# c #2C4058",
+"$ c #3D4751",
+"% c #344C61",
+"& c #403F43",
+"* c #404655",
+"= c #424852",
+"- c #494D5A",
+"; c #48535C",
+": c #4C5360",
+"> c #555A61",
+", c #545B64",
+"< c #575B66",
+"1 c #565D6B",
+"2 c #595E62",
+"3 c #595E64",
+"4 c #5A5E64",
+"5 c #5A5F6A",
+"6 c #595F6D",
+"7 c #5D626F",
+"8 c #5C6873",
+"9 c #62666C",
+"0 c #64686E",
+"q c #636674",
+"w c #636876",
+"e c #656B74",
+"r c #616A79",
+"t c #626A78",
+"y c #646C79",
+"u c #6A6E76",
+"i c #6F6E78",
+"p c #65707C",
+"a c #66717C",
+"s c #6D717F",
+"d c #6E717F",
+"f c #706E74",
+"g c #706F7C",
+"h c #72757D",
+"j c #6D7083",
+"k c #707283",
+"l c #727583",
+"z c #717488",
+"x c #757884",
+"c c #777A8D",
+"v c #7B7881",
+"b c #787B84",
+"n c #7C7B86",
+"m c #7A7F8E",
+"M c #1FA81F",
+"N c #1FA91F",
+"B c #20AB20",
+"V c #22BA22",
+"C c #23BB23",
+"Z c #22BC22",
+"A c #23BD23",
+"S c #24C324",
+"D c #26CE26",
+"F c #27D127",
+"G c #2BE92B",
+"H c #30FF30",
+"J c #7D8189",
+"K c #808485",
+"L c #82858C",
+"P c #88878E",
+"I c #818397",
+"U c #838490",
+"Y c #868593",
+"T c #868998",
+"R c #86889D",
+"E c #8C8E96",
+"W c #8E8D9C",
+"Q c #8F9395",
+"! c #94929B",
+"~ c #96959F",
+"^ c #909A9D",
+"/ c #8A8BA0",
+"( c #8F91A5",
+") c #9192A7",
+"_ c #9597AA",
+"` c #9796AC",
+"' c #9995A2",
+"] c #9898A4",
+"[ c #9999A4",
+"{ c #9C9CB3",
+"} c #A29EAB",
+"| c #A09FAC",
+" . c #A4A6B9",
+".. c #A7A9BD",
+"X. c #A9AAB5",
+"o. c #ACA8B4",
+"O. c #AEAFBE",
+"+. c #AFB2BF",
+"@. c #B0ACB7",
+"#. c #B0AEB9",
+"$. c #A8AAC0",
+"%. c #ADABC2",
+"&. c #ACAEC5",
+"*. c #B6B7CB",
+"=. c #B8B7C4",
+"-. c #BFBEC6",
+";. c #BEBFD2",
+":. c #BCC2D1",
+">. c #BFC0D6",
+",. c #C0C0C0",
+"<. c #C4C7CD",
+"1. c #CBCBCB",
+"2. c #C3C3DB",
+"3. c #C7CAD1",
+"4. c #CDCED6",
+"5. c #CACADF",
+"6. c #D7D7D7",
+"7. c #D5D4DE",
+"8. c #D7D8D7",
+"9. c #D8D8D6",
+"0. c #DBDBDC",
+"q. c #CACCE1",
+"w. c #C7DAE4",
+"e. c #D2D6EB",
+"r. c #D4D5EA",
+"t. c #D1D8EA",
+"y. c #D8DCEF",
+"u. c #DADEF0",
+"i. c #DBE0F5",
+"p. c #E0DEE8",
+"a. c #E3E0EB",
+"s. c #E4E6EE",
+"d. c #E7E5EF",
+"f. c #ECEEEF",
+"g. c #E2E3F5",
+"h. c #E1E4F3",
+"j. c #E3E4F3",
+"k. c #E3E5F2",
+"l. c #E1E4F5",
+"z. c #E7E5F2",
+"x. c #E4E5F6",
+"c. c #E5E7F8",
+"v. c #E5E9F7",
+"b. c #E9E7F3",
+"n. c #E9E9F7",
+"m. c #EBEDF5",
+"M. c #EAECF7",
+"N. c #ECEBF5",
+"B. c #EDECF4",
+"V. c #EEEFF6",
+"C. c #E9ECFB",
+"Z. c #F0F1F6",
+"A. c #F1F1F6",
+"S. c #F1F2F6",
+"D. c #F3F2F6",
+"F. c #F3F4F7",
+"G. c #F6F6F6",
+"H. c #F2F1F9",
+"J. c #F2F3FA",
+"K. c #F3F4F8",
+"L. c #F4F6F9",
+"P. c #F6F7F8",
+"I. c #F7F8F9",
+"U. c #F7F9F9",
+"Y. c #F8F6F9",
+"T. c #F8FAF7",
+"R. c #F9FBF7",
+"E. c #FAFAF5",
+"W. c #FAFAF9",
+"Q. c #FAFBFB",
+"!. c #FBFBFB",
+"~. c #FEFEF9",
+"^. c gray100",
+"/. c None",
+/* pixels */
+"/./././././././././././././././././././././././././././././././.",
+"/././././././././././.W.Q , z .+.( s p w./././././././././././.",
+"/././././././././.^ = < j &.g.H.d.C.2.R y $ ; /././././././././.",
+"/./././././././.a ; k { q.h.S.<.e -.v.r.%.I t t /./././././././.",
+"/././././././.K 6 / $.e.g.m.3.% # J S.k.y.;._ c 1 /././././././.",
+"/./././././. 5 ) *.t.j.V.S.f.* - i W.V.M.u.q.` 8 /./././././.",
+"/././././. 7 m :.j.H.K.I.T.W.I.Q.G.F.V.n.u.T e /././././.",
+"/././././. n d ..x.L.T.~.~.0.8.8.Q.E.Z.c.;.z q /././././.",
+"/././././. & U x Y O.4.p.d.b.N.b.p.7.=.W g b @ /././././.",
+"/././././. O ~ [ E h 0 3 > 2 3 0 u L [ ' + /././././.",
+"/././././. . X f P | X.#.@.o.| ! v O . /././././.",
+"/./././././. /./././././.",
+"/././. /././.",
+"/././. F H F S G C C G S 6.^.1. /././.",
+"/././. A F B /./. A D M C D N /./. 1.6.,. /././.",
+"/././. /./. /./. /./. /././."
+};
diff --git a/applets/small-icons/signal-81-100.png b/applets/small-icons/signal-81-100.png
new file mode 100644
index 0000000..97fe8d6
--- /dev/null
+++ b/applets/small-icons/signal-81-100.png
Binary files differ
diff --git a/applets/small-icons/signal-81-100.xpm b/applets/small-icons/signal-81-100.xpm
new file mode 100644
index 0000000..e343a40
--- /dev/null
+++ b/applets/small-icons/signal-81-100.xpm
@@ -0,0 +1,190 @@
+/* XPM */
+static char *signal-81-100[] = {
+/* columns rows colors chars-per-pixel */
+"32 16 168 2",
+" c black",
+". c #070708",
+"X c #323135",
+"o c #36353A",
+"O c #37373A",
+"+ c #3C3B3F",
+"@ c #3E3D42",
+"# c #2C4058",
+"$ c #3D4751",
+"% c #344C61",
+"& c #403F43",
+"* c #404655",
+"= c #424852",
+"- c #494D5A",
+"; c #48535C",
+": c #4C5360",
+"> c #555A61",
+", c #545B64",
+"< c #575B66",
+"1 c #565D6B",
+"2 c #595E62",
+"3 c #595E64",
+"4 c #5A5E64",
+"5 c #5A5F6A",
+"6 c #595F6D",
+"7 c #5D626F",
+"8 c #5C6873",
+"9 c #62666C",
+"0 c #64686E",
+"q c #636674",
+"w c #636876",
+"e c #656B74",
+"r c #616A79",
+"t c #626A78",
+"y c #646C79",
+"u c #6A6E76",
+"i c #6F6E78",
+"p c #65707C",
+"a c #66717C",
+"s c #6D717F",
+"d c #6E717F",
+"f c #706E74",
+"g c #706F7C",
+"h c #72757D",
+"j c #6D7083",
+"k c #707283",
+"l c #727583",
+"z c #717488",
+"x c #757884",
+"c c #777A8D",
+"v c #7B7881",
+"b c #787B84",
+"n c #7C7B86",
+"m c #7A7F8E",
+"M c #2F972F",
+"N c #309930",
+"B c #34A834",
+"V c #34A934",
+"C c #35AA35",
+"Z c #37B037",
+"A c #3AB93A",
+"S c #3BBC3B",
+"D c #41D141",
+"F c #48E548",
+"G c #7D8189",
+"H c #808485",
+"J c #82858C",
+"K c #88878E",
+"L c #818397",
+"P c #838490",
+"I c #868593",
+"U c #868998",
+"Y c #86889D",
+"T c #8C8E96",
+"R c #8E8D9C",
+"E c #8F9395",
+"W c #94929B",
+"Q c #96959F",
+"! c #909A9D",
+"~ c #8A8BA0",
+"^ c #8F91A5",
+"/ c #9192A7",
+"( c #9597AA",
+") c #9796AC",
+"_ c #9995A2",
+"` c #9898A4",
+"' c #9999A4",
+"] c #9C9CB3",
+"[ c #A29EAB",
+"{ c #A09FAC",
+"} c #A4A6B9",
+"| c #A7A9BD",
+" . c #A9AAB5",
+".. c #ACA8B4",
+"X. c #AEAFBE",
+"o. c #AFB2BF",
+"O. c #B0ACB7",
+"+. c #B0AEB9",
+"@. c #A8AAC0",
+"#. c #ADABC2",
+"$. c #ACAEC5",
+"%. c #B6B7CB",
+"&. c #B8B7C4",
+"*. c #BFBEC6",
+"=. c #BEBFD2",
+"-. c #BCC2D1",
+";. c #BFC0D6",
+":. c #C4C7CD",
+">. c #C3C3DB",
+",. c #C7CAD1",
+"<. c #CDCED6",
+"1. c #CACADF",
+"2. c #D5D4DE",
+"3. c #D7D8D7",
+"4. c #D8D8D6",
+"5. c #DBDBDC",
+"6. c #CACCE1",
+"7. c #C7DAE4",
+"8. c #D2D6EB",
+"9. c #D4D5EA",
+"0. c #D1D8EA",
+"q. c #D8DCEF",
+"w. c #DADEF0",
+"e. c #DBE0F5",
+"r. c #E0DEE8",
+"t. c #E3E0EB",
+"y. c #E4E6EE",
+"u. c #E7E5EF",
+"i. c #ECEEEF",
+"p. c #E2E3F5",
+"a. c #E1E4F3",
+"s. c #E3E4F3",
+"d. c #E3E5F2",
+"f. c #E1E4F5",
+"g. c #E7E5F2",
+"h. c #E4E5F6",
+"j. c #E5E7F8",
+"k. c #E5E9F7",
+"l. c #E9E7F3",
+"z. c #E9E9F7",
+"x. c #EBEDF5",
+"c. c #EAECF7",
+"v. c #ECEBF5",
+"b. c #EDECF4",
+"n. c #EEEFF6",
+"m. c #E9ECFB",
+"M. c #F0F1F6",
+"N. c #F1F1F6",
+"B. c #F1F2F6",
+"V. c #F3F2F6",
+"C. c #F3F4F7",
+"Z. c #F6F6F6",
+"A. c #F2F1F9",
+"S. c #F2F3FA",
+"D. c #F3F4F8",
+"F. c #F4F6F9",
+"G. c #F6F7F8",
+"H. c #F7F8F9",
+"J. c #F7F9F9",
+"K. c #F8F6F9",
+"L. c #F8FAF7",
+"P. c #F9FBF7",
+"I. c #FAFAF5",
+"U. c #FAFAF9",
+"Y. c #FAFBFB",
+"T. c #FBFBFB",
+"R. c #FEFEF9",
+"E. c None",
+/* pixels */
+"E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.",
+"E.E.E.E.E.E.E.E.E.E.E.U.E , z } o.^ s p 7.E.E.E.E.E.E.E.E.E.E.E.",
+"E.E.E.E.E.E.E.E.E.! = < j $.p.A.u.m.>.Y y $ ; E.E.E.E.E.E.E.E.E.",
+"E.E.E.E.E.E.E.E.a ; k ] 6.a.B.:.e *.k.9.#.L r r E.E.E.E.E.E.E.E.",
+"E.E.E.E.E.E.E.H 6 ~ @.8.p.x.,.% # G V.s.q.;.) c 1 E.E.E.E.E.E.E.",
+"E.E.E.E.E.E. 5 / %.0.s.n.B.i.* - i F.n.n.q.6.) 8 E.E.E.E.E.E.",
+"E.E.E.E.E. 7 m -.s.A.D.J.L.U.J.Y.Z.Z.n.z.w.U e E.E.E.E.E.",
+"E.E.E.E.E. n d | h.F.L.R.R.5.3.3.Y.L.M.h.=.l q E.E.E.E.E.",
+"E.E.E.E.E. & P x I X.<.r.u.l.v.l.r.2.&.R g x @ E.E.E.E.E.",
+"E.E.E.E.E. O Q ' T h 0 3 > 4 3 9 u J ' _ @ E.E.E.E.E.",
+"E.E.E.E.E. . X f K { .+.O...[ W v O . E.E.E.E.E.",
+"E.E.E.E.E.E. E.E.E.E.E.E.",
+"E.E.E. E.E.E.",
+"E.E.E. S F S C D C C D Z S F S E.E.E.",
+"E.E.E. C S N E.E. C A N B A M E.E. C S N E.E.E.",
+"E.E.E. E.E. E.E. E.E. E.E.E."
+};
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..b1376df
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+autoreconf -v --install || exit 1
+./configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..7378276
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,199 @@
+AC_PREREQ(2.53)
+AC_INIT([matchbox-panel], 0.8, [mallum@handhelds.org])
+AC_CONFIG_SRCDIR([src/panel.c])
+
+AM_INIT_AUTOMAKE()
+AM_MAINTAINER_MODE
+AM_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_CC
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([libintl.h stdlib.h string.h sys/time.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_PID_T
+AC_HEADER_TIME
+
+# Checks for library functions.
+AC_FUNC_ALLOCA
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_FORK
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STAT
+AC_CHECK_FUNCS([alarm getcwd gettimeofday memset mkdir select setenv setlocale strcasecmp strdup strpbrk strstr])
+
+# maybe this should be locale support
+
+#AC_ARG_ENABLE(translations,
+# [ --enable-translations enable debug ( verbose ) build],
+# enable_translations=$enableval, enable_tra=no )
+
+AC_ARG_ENABLE(startup-notification,
+ [ --enable-startup-notification enable startup notification support],
+ enable_sn=$enableval, enable_sn=no )
+
+AC_ARG_ENABLE(nls,
+ [ --enable-nls enable Native Language Support ( gettext/libintl )],
+ enable_nls=$enableval, enable_nls=no)
+
+AC_ARG_ENABLE(sicons,
+ [ --small-icons enable small icons],
+ enable_sicons=$enableval, enable_sicons=no )
+
+
+AC_ARG_ENABLE(debug,
+ [ --enable-debug enable debug ( verbose ) build],
+ enable_debug=$enableval, enable_debug=no )
+
+
+PKG_CHECK_MODULES(LIBMB, libmb >= 1.1,,
+ AC_MSG_ERROR([*** Required Matchbox Library (libmb) not installed ***]))
+
+dnl ------ Debug Build ------------------------------------------------------
+
+if test x$enable_debug = xyes; then
+ LIBMB_CFLAGS="$LIBMB_CFLAGS -DDEBUG"
+fi
+
+dnl ----- Startup Notification ---------------------------------------------
+
+
+if test x$enable_sn != xno; then
+ PKG_CHECK_MODULES(SN, libstartup-notification-1.0, ,
+ AC_MSG_ERROR([*** Required Startup Notification Librays not installed ***]))
+
+ AC_DEFINE(USE_LIBSN, [1], [Has StartupNotification Support])
+fi
+
+dnl ----- NLS Fun -----------------------------------------------------------
+
+INTLIBS=""
+MOFILES=""
+
+if test x$enable_nls = xyes; then
+
+ LINGUAS="en_GB es_ES fi_FI de cs fr_FR"
+
+ AC_CHECK_FUNC(gettext, [HAVEGETTEXT="yes"],
+ AC_CHECK_LIB(intl, gettext, [INTLIBS="-lintl" HAVEGETTEXT="yes"],
+ INTLIBS="" ))
+
+ AC_CHECK_PROG(XGETTEXT, xgettext, xgettext)
+
+ if test "$XGETTEXT" != ""; then
+ if $XGETTEXT --help 2>&1 | grep illegal >/dev/null ; then
+ echo "xgettext isn't GNU version"
+ XGETTEXT=""
+ fi
+ fi
+
+ if test "$LINGUAS" != ""; then
+ if test "$XGETTEXT" != "" -a "$HAVEGETTEXT" != ""; then
+ PO=""
+ if test "$LINGUAS" = ""; then
+ ling=` (cd src/po; /bin/ls *.po) `
+ for l in $ling; do
+ lcode=`basename $l .po`
+ LINGUAS="$LINGUAS $lcode"
+ done
+ fi
+ AC_DEFINE(ENABLE_NLS, [1], [NLS Please])
+ echo "xgettext and gettext() exist; will build i18n support for $LINGUAS"
+ else
+ LINGUAS=""
+ PO=""
+ echo "xgettext and libintl.a don't both exist; will not build i18n support"
+ fi
+ else
+ INTLIBS=""
+ MOFILES=""
+ PO=""
+ fi
+
+ for lang in $LINGUAS; do
+ MOFILES="$MOFILES $lang.mo"
+ done
+
+fi
+
+AC_SUBST(INTLIBS)
+AC_SUBST(MOFILES)
+
+dnl ----- Xsettings ---------------------------------------------------------
+
+AC_MSG_CHECKING([for libmb xsettings support])
+
+if $PKG_CONFIG --libs libmb | grep -i xsettings ; then
+ mb_have_xsettings="yes"
+ AC_DEFINE(USE_XSETTINGS, [1], [Use XSettings])
+ AC_MSG_RESULT([yes])
+else
+ mb_have_xsettings="no"
+ AC_MSG_RESULT([no])
+fi
+
+
+dnl ---- Png Support -------------------------------------------------------
+
+if $PKG_CONFIG --libs libmb | grep png ; then
+ found_png="yes"
+else
+ found_png="no"
+fi
+
+AM_CONDITIONAL(WANT_PNG, test x$found_png = xyes)
+
+
+dnl ---- Icons --------------------------------------------------------------
+
+AM_CONDITIONAL(WANT_SMALL_ICONS, test x$enable_sicons = xyes)
+
+dnl ----- Specific Applet deps ----------------------------------------------
+
+
+AC_CHECK_HEADERS(apm.h, enable_linux_apm=yes, enable_linux_apm=no)
+if test x$enable_linux_apm = xyes; then
+ miniapm_enabled="yes"
+ AC_DEFINE(HAVE_APM_H, [1], [Have Linux APM headers])
+fi
+
+AC_CHECK_HEADERS(apmvar.h, enable_bsd_apm=yes, enable_bsd_apm=no)
+if test x$enable_bsd_apm = xyes; then
+ AC_DEFINE(HAVE_APMVAR_H, [1], [Have BSD APM headers])
+ miniapm_enabled="yes"
+fi
+
+AM_CONDITIONAL(WANT_APM, test x$miniapm_enabled = x"yes")
+
+
+# XXX wireless checks
+
+
+dnl ------ GCC flags --------------------------------------------------------
+
+if test "x$GCC" = "xyes"; then
+ GCC_WARNINGS="-g -Wall -fno-strict-aliasing"
+ LIBMB_CFLAGS="$GCC_WARNINGS $LIBMB_CFLAGS"
+fi
+
+
+dnl ------ Substitute in found libs, clags to Makefiles etc -----------------
+
+AC_SUBST(LIBMB_CFLAGS)
+AC_SUBST(LIBMB_LIBS)
+
+AC_OUTPUT([
+Makefile
+src/Makefile
+applets/Makefile
+applets/dotdesktop/Makefile
+applets/icons/Makefile
+applets/small-icons/Makefile
+po/Makefile
+])
+
diff --git a/po/Makefile.am b/po/Makefile.am
new file mode 100644
index 0000000..db6443e
--- /dev/null
+++ b/po/Makefile.am
@@ -0,0 +1,49 @@
+CATALOGS = @MOFILES@
+
+CLEANFILES = $(CATALOGS) matchbox.pot
+
+# keep this sorted
+EXTRA_DIST = en_GB.po es_ES.po fi_FI.po de.po cs.po fr_FR.po
+
+POTFILES = \
+ $(top_builddir)/src/panel_menu.c \
+ $(top_builddir)/applets/mb-applet-system-monitor.c \
+ $(top_builddir)/applets/mb-applet-wireless.c \
+ $(top_builddir)/applets/mb-applet-clock.c \
+ $(top_builddir)/applets/mb-applet-battery.c
+
+
+SUFFIXES = .po .mo
+
+.po.mo:
+ msgfmt -o $@ $<
+
+matchbox.pot: $(POTFILES)
+ xgettext --default-domain=matchbox \
+ --add-comments --keyword=_ $(POTFILES)
+ if cmp -s matchbox.po matchbox.pot; then \
+ rm -f matchbox.po; \
+ else \
+ mv -f matchbox.po matchbox.pot; \
+ fi
+
+update.po: matchbox.pot
+ for n in $(CATALOGS) __DuMmY ; do \
+ if test "$$n" -a "$$n" != "__DuMmY" ; then \
+ l=`basename $$n .mo`; \
+ msgmerge --update $$l.po matchbox.pot; \
+ fi; \
+ done
+
+install-data-local: $(CATALOGS)
+ $(mkinstalldirs) $(DESTDIR)$(datadir)/locale
+ chmod 755 $(DESTDIR)$(datadir)/locale
+ for n in $(CATALOGS) __DuMmY ; do \
+ if test "$$n" -a "$$n" != "__DuMmY" ; then \
+ l=`basename $$n .mo`; \
+ $(mkinstalldirs) $(DESTDIR)$(datadir)/locale/$$l/LC_MESSAGES; \
+ chmod 755 $(DESTDIR)$(datadir)/locale/$$l; \
+ chmod 755 $(DESTDIR)$(datadir)/locale/$$l/LC_MESSAGES; \
+ $(INSTALL_DATA) -m 644 $$n $(DESTDIR)$(datadir)/locale/$$l/LC_MESSAGES/matchbox.mo; \
+ fi; \
+ done
diff --git a/po/cs.po b/po/cs.po
new file mode 100644
index 0000000..021b03b
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,140 @@
+# translation of matchbox.po to Czech
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# Libor Klepac <elkropac@students.zcu.cz>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: matchbox 0.6.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-02-02 10:37+0000\n"
+"PO-Revision-Date: 2003-10-11 23:36+0100\n"
+"Last-Translator: Libor Klepac <elkropac@students.zcu.cz>\n"
+"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/panel_menu.c:68
+msgid "Remove"
+msgstr "Odebrat"
+
+#: ../src/panel_menu.c:172
+msgid "Add"
+msgstr "Přidat"
+
+#: ../src/panel_menu.c:259
+msgid "Hide"
+msgstr "Schovat"
+
+#: ../applets/mb-applet-system-monitor.c:253
+#, c-format
+msgid "CPU: %i %%, MEMORY: %i %%\n"
+msgstr "CPU: %i %%, PAMĚŤ: %i %%\n"
+
+#: ../applets/mb-applet-system-monitor.c:324
+msgid "CPU/Mem Monitor"
+msgstr "Sledování využití CPU/Paměti"
+
+#: ../applets/mb-applet-wireless.c:438
+#, fuzzy, c-format
+msgid ""
+"%s:\n"
+" Link %.1f\n"
+" Level %.1f\n"
+" Noise %.1f\n"
+msgstr "%s: Link %.1f, Level %.1f, Noise %.1f\n"
+
+#: ../applets/mb-applet-wireless.c:443
+#, c-format
+msgid "No wireless cards detected\n"
+msgstr "Nebyla nalezena karta pro bezdrátové sítě\n"
+
+#: ../applets/mb-applet-wireless.c:483
+msgid "Wireless Monitor"
+msgstr "Sledování bezdrátových síti"
+
+#: ../applets/mb-applet-clock.c:146
+#, c-format
+msgid "%.2d:%.2d"
+msgstr "%.2d:%.2d"
+
+#: ../applets/mb-applet-clock.c:234
+msgid "%a %b %e %k:%M:%S %Y"
+msgstr "%a %b %e %k:%M:%S %Y"
+
+#: ../applets/mb-applet-clock.c:333
+msgid "Clock"
+msgstr "Hodiny"
+
+#: ../applets/mb-applet-clock.c:360
+msgid "Set Time"
+msgstr ""
+
+#: ../applets/mb-applet-battery.c:283
+#, c-format
+msgid ""
+"Battery power very low !\n"
+"\n"
+"Time Left: %.2i minutes"
+msgstr ""
+"Napětí baterie velmi nízké!\n"
+"\n"
+"Zbývá: %.2i minut"
+
+#: ../applets/mb-applet-battery.c:380
+#, c-format
+msgid ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+msgstr ""
+"Připojeno k síti\n"
+"Nabito: %.2i %%\n"
+
+#: ../applets/mb-applet-battery.c:383
+#, c-format
+msgid ""
+"AC Connected\n"
+"Fully charged.\n"
+msgstr ""
+"Připojeno k síti\n"
+"Plně nabito\n"
+
+#: ../applets/mb-applet-battery.c:390
+#, c-format
+msgid ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+msgstr ""
+"Napájeno z baterie\n"
+"Napětí %.2i %%\n"
+"Zbývá: %.2i minut\n"
+
+#: ../applets/mb-applet-battery.c:392
+#, c-format
+msgid ""
+"Battery Power\n"
+" Device read error.\n"
+msgstr ""
+"Napájeno z baterie\n"
+" Chyba při čtení ze zařízení.\n"
+
+#: ../applets/mb-applet-battery.c:442
+msgid "Battery Monitor"
+msgstr "Sledování napájení"
+
+#: ../applets/mb-applet-battery.c:466
+msgid "More info"
+msgstr ""
+
+#~ msgid "Cant open mixer device"
+#~ msgstr "Nemohu otevřít směšovač"
+
+#~ msgid "Cant open mixer device for reading"
+#~ msgstr "Nemohu otevřít směšovač pro čtení"
+
+#~ msgid "Cant open mixer device for writing"
+#~ msgstr "Nemohu otevřít směšovač pro zápis"
+
+#~ msgid "Volume Control"
+#~ msgstr "Nastavení hlasitosti"
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000..01398c2
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,141 @@
+# German translation for matchbox.
+# Copyright (C) 2003 Matthew Allum
+# This file is distributed under the same license as the matchbox package.
+# Colin Marquardt <colin@marquardt-home.de>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: matchbox\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-02-02 10:37+0000\n"
+"PO-Revision-Date: 2003-10-09 22:18+0200\n"
+"Last-Translator: Colin Marquardt <colin@marquardt-home.de>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/panel_menu.c:68
+msgid "Remove"
+msgstr "Entfernen"
+
+#: ../src/panel_menu.c:172
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: ../src/panel_menu.c:259
+msgid "Hide"
+msgstr "Verstecken"
+
+#: ../applets/mb-applet-system-monitor.c:253
+#, c-format
+msgid "CPU: %i %%, MEMORY: %i %%\n"
+msgstr "CPU: %i %%, Speicher: %i %%\n"
+
+#: ../applets/mb-applet-system-monitor.c:324
+msgid "CPU/Mem Monitor"
+msgstr "CPU-/Speicher-Monitor"
+
+#: ../applets/mb-applet-wireless.c:438
+#, fuzzy, c-format
+msgid ""
+"%s:\n"
+" Link %.1f\n"
+" Level %.1f\n"
+" Noise %.1f\n"
+msgstr "%s: Link %.1f, Level %.1f, Stör %.1f\n"
+
+#: ../applets/mb-applet-wireless.c:443
+#, c-format
+msgid "No wireless cards detected\n"
+msgstr "Keine Wireless-Karten erkannt\n"
+
+#: ../applets/mb-applet-wireless.c:483
+msgid "Wireless Monitor"
+msgstr "Wireless-Monitor"
+
+#: ../applets/mb-applet-clock.c:146
+#, c-format
+msgid "%.2d:%.2d"
+msgstr "%.2d:%.2d"
+
+#: ../applets/mb-applet-clock.c:234
+msgid "%a %b %e %k:%M:%S %Y"
+msgstr "%a, %e. %b %Y, %k:%M:%S"
+
+#: ../applets/mb-applet-clock.c:333
+msgid "Clock"
+msgstr "Uhr"
+
+#: ../applets/mb-applet-clock.c:360
+msgid "Set Time"
+msgstr ""
+
+#: ../applets/mb-applet-battery.c:283
+#, c-format
+msgid ""
+"Battery power very low !\n"
+"\n"
+"Time Left: %.2i minutes"
+msgstr ""
+"Batteriestand sehr niedrig!\n"
+"\n"
+"Verbleibend: %.2i min"
+
+#: ../applets/mb-applet-battery.c:380
+#, c-format
+msgid ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+msgstr ""
+"Am Netzteil\n"
+"Ladend: %.2i %%\n"
+
+#: ../applets/mb-applet-battery.c:383
+#, c-format
+msgid ""
+"AC Connected\n"
+"Fully charged.\n"
+msgstr ""
+"Am Netzteil\n"
+"Voll geladen\n"
+
+#: ../applets/mb-applet-battery.c:390
+#, c-format
+msgid ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+msgstr ""
+"Batteriestand\n"
+"Füllung %.2i %%\n"
+"Verbleibend: %.2i min\n"
+
+#: ../applets/mb-applet-battery.c:392
+#, c-format
+msgid ""
+"Battery Power\n"
+" Device read error.\n"
+msgstr ""
+"Batteriestand\n"
+"Fehler beim Auslesen.\n"
+
+#: ../applets/mb-applet-battery.c:442
+msgid "Battery Monitor"
+msgstr "Batteriemonitor"
+
+#: ../applets/mb-applet-battery.c:466
+msgid "More info"
+msgstr ""
+
+#~ msgid "Cant open mixer device"
+#~ msgstr "Kann Mixer-Gerät nicht öffnen"
+
+#~ msgid "Cant open mixer device for reading"
+#~ msgstr "Kann Mixer-Gerät nicht zum Lesen öffnen"
+
+#~ msgid "Cant open mixer device for writing"
+#~ msgstr "Kann Mixer-Gerät nicht zum Schreiben öffnen"
+
+#~ msgid "Volume Control"
+#~ msgstr "Lautstärke"
diff --git a/po/en_GB.po b/po/en_GB.po
new file mode 100644
index 0000000..d32bc05
--- /dev/null
+++ b/po/en_GB.po
@@ -0,0 +1,142 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-02-02 10:37+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/panel_menu.c:68
+msgid "Remove"
+msgstr ""
+
+#: ../src/panel_menu.c:172
+msgid "Add"
+msgstr ""
+
+#: ../src/panel_menu.c:259
+msgid "Hide"
+msgstr ""
+
+#: ../applets/mb-applet-system-monitor.c:253
+#, c-format
+msgid "CPU: %i %%, MEMORY: %i %%\n"
+msgstr "Ye Old CPU: %i %%, MEMORY: %i %%\n"
+
+#: ../applets/mb-applet-system-monitor.c:324
+msgid "CPU/Mem Monitor"
+msgstr "CPU/Mem Monitor"
+
+#: ../applets/mb-applet-wireless.c:438
+#, fuzzy, c-format
+msgid ""
+"%s:\n"
+" Link %.1f\n"
+" Level %.1f\n"
+" Noise %.1f\n"
+msgstr "%s: Link %.1f, Level %.1f, Noise %.1f\n"
+
+#: ../applets/mb-applet-wireless.c:443
+#, c-format
+msgid "No wireless cards detected\n"
+msgstr ""
+
+#: ../applets/mb-applet-wireless.c:483
+msgid "Wireless Monitor"
+msgstr "Wireless Monitor"
+
+#: ../applets/mb-applet-clock.c:146
+#, c-format
+msgid "%.2d:%.2d"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:234
+msgid "%a %b %e %k:%M:%S %Y"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:333
+msgid "Clock"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:360
+msgid "Set Time"
+msgstr ""
+
+#: ../applets/mb-applet-battery.c:283
+#, fuzzy, c-format
+msgid ""
+"Battery power very low !\n"
+"\n"
+"Time Left: %.2i minutes"
+msgstr ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+
+#: ../applets/mb-applet-battery.c:380
+#, c-format
+msgid ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+msgstr ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+
+#: ../applets/mb-applet-battery.c:383
+#, c-format
+msgid ""
+"AC Connected\n"
+"Fully charged.\n"
+msgstr ""
+"AC Connected\n"
+"Fully charged.\n"
+
+#: ../applets/mb-applet-battery.c:390
+#, c-format
+msgid ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+msgstr ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+
+#: ../applets/mb-applet-battery.c:392
+#, c-format
+msgid ""
+"Battery Power\n"
+" Device read error.\n"
+msgstr ""
+"Battery Power\n"
+" Device read error.\n"
+
+#: ../applets/mb-applet-battery.c:442
+msgid "Battery Monitor"
+msgstr "Battery Monitor"
+
+#: ../applets/mb-applet-battery.c:466
+msgid "More info"
+msgstr ""
+
+#~ msgid "Cant open mixer device"
+#~ msgstr "Cant open mixer device"
+
+#~ msgid "Cant open mixer device for reading"
+#~ msgstr "Cant open mixer device for reading"
+
+#~ msgid "Cant open mixer device for writing"
+#~ msgstr "Cant open mixer device for writing"
+
+#~ msgid "Volume Control"
+#~ msgstr "Volume Control"
diff --git a/po/es_ES.po b/po/es_ES.po
new file mode 100644
index 0000000..2bf6c4b
--- /dev/null
+++ b/po/es_ES.po
@@ -0,0 +1,142 @@
+# Spanish localization of MatchBox Dock on-line help
+# Copyright (C) 2003
+# This file is distributed under the same license as the Matchbox package.
+# J.Manrique <jsmanrique@asturlinux.org>, 2003.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.6\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-02-02 10:37+0000\n"
+"PO-Revision-Date: 2003-07-29 09:00+0100\n"
+"Last-Translator: J.Manrique <jsmanrique@asturlinux.org>\n"
+"Language-Team: es@li.org <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/panel_menu.c:68
+msgid "Remove"
+msgstr "Quitar"
+
+#: ../src/panel_menu.c:172
+msgid "Add"
+msgstr "Añadir"
+
+#: ../src/panel_menu.c:259
+msgid "Hide"
+msgstr "Ocultar"
+
+#: ../applets/mb-applet-system-monitor.c:253
+#, c-format
+msgid "CPU: %i %%, MEMORY: %i %%\n"
+msgstr "CPU: %i %%, MEMORIA: %i %%\n"
+
+#: ../applets/mb-applet-system-monitor.c:324
+msgid "CPU/Mem Monitor"
+msgstr "Monitor de CPU/Mem"
+
+#: ../applets/mb-applet-wireless.c:438
+#, fuzzy, c-format
+msgid ""
+"%s:\n"
+" Link %.1f\n"
+" Level %.1f\n"
+" Noise %.1f\n"
+msgstr "%s: Enlace %.1f, Nivel %.1f, Ruido %.1f\n"
+
+#: ../applets/mb-applet-wireless.c:443
+#, c-format
+msgid "No wireless cards detected\n"
+msgstr "No se detectó tarjeta inalámbrica\n"
+
+#: ../applets/mb-applet-wireless.c:483
+msgid "Wireless Monitor"
+msgstr "Monitor de Inalámbrica"
+
+#: ../applets/mb-applet-clock.c:146
+#, c-format
+msgid "%.2d:%.2d"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:234
+msgid "%a %b %e %k:%M:%S %Y"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:333
+msgid "Clock"
+msgstr "Reloj"
+
+#: ../applets/mb-applet-clock.c:360
+msgid "Set Time"
+msgstr ""
+
+#: ../applets/mb-applet-battery.c:283
+#, fuzzy, c-format
+msgid ""
+"Battery power very low !\n"
+"\n"
+"Time Left: %.2i minutes"
+msgstr ""
+"Batería\n"
+"Jugo %.2i %%\n"
+"Tiempo restante: %.2i mins\n"
+
+#: ../applets/mb-applet-battery.c:380
+#, c-format
+msgid ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+msgstr ""
+"AC Conectado\n"
+"Cargando: %.2i %%\n"
+
+#: ../applets/mb-applet-battery.c:383
+#, c-format
+msgid ""
+"AC Connected\n"
+"Fully charged.\n"
+msgstr ""
+"AC Conectado\n"
+"Carga completada.\n"
+
+#: ../applets/mb-applet-battery.c:390
+#, c-format
+msgid ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+msgstr ""
+"Batería\n"
+"Jugo %.2i %%\n"
+"Tiempo restante: %.2i mins\n"
+
+#: ../applets/mb-applet-battery.c:392
+#, c-format
+msgid ""
+"Battery Power\n"
+" Device read error.\n"
+msgstr ""
+"Batería\n"
+" Error leyendo dispositivo.\n"
+
+#: ../applets/mb-applet-battery.c:442
+msgid "Battery Monitor"
+msgstr "Monitor de Batería"
+
+#: ../applets/mb-applet-battery.c:466
+msgid "More info"
+msgstr ""
+
+#~ msgid "Cant open mixer device"
+#~ msgstr "No se pudo abrir dispositivo mezclador"
+
+#~ msgid "Cant open mixer device for reading"
+#~ msgstr "No se pudo abrir dispositivo mezclador para lectura"
+
+#~ msgid "Cant open mixer device for writing"
+#~ msgstr "No se pudo abrir dispositivo mezclador para escritura"
+
+#~ msgid "Volume Control"
+#~ msgstr "Control de Volumen"
diff --git a/po/fi_FI.po b/po/fi_FI.po
new file mode 100644
index 0000000..568ebe8
--- /dev/null
+++ b/po/fi_FI.po
@@ -0,0 +1,142 @@
+# translation of fi_FI.po for Matchbox
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# Eero Tamminen <EMAIL@ADDRESS>, 2003
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-02-02 10:37+0000\n"
+"PO-Revision-Date: 2003-09-23 22:47+0300\n"
+"Last-Translator: Eero Tamminen <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.1\n"
+
+#: ../src/panel_menu.c:68
+msgid "Remove"
+msgstr "Poista"
+
+#: ../src/panel_menu.c:172
+msgid "Add"
+msgstr "Lisää"
+
+#: ../src/panel_menu.c:259
+msgid "Hide"
+msgstr "Piiloon"
+
+#: ../applets/mb-applet-system-monitor.c:253
+#, c-format
+msgid "CPU: %i %%, MEMORY: %i %%\n"
+msgstr "CPU: %i %%, RAM: %i %%\n"
+
+#: ../applets/mb-applet-system-monitor.c:324
+msgid "CPU/Mem Monitor"
+msgstr "CPU/RAM tiedot"
+
+#: ../applets/mb-applet-wireless.c:438
+#, fuzzy, c-format
+msgid ""
+"%s:\n"
+" Link %.1f\n"
+" Level %.1f\n"
+" Noise %.1f\n"
+msgstr "%s: Linkki %.1f, Taso %.1f, Kohina %.1f\n"
+
+#: ../applets/mb-applet-wireless.c:443
+#, c-format
+msgid "No wireless cards detected\n"
+msgstr "Ei havaittuja WLAN-kortteja\n"
+
+#: ../applets/mb-applet-wireless.c:483
+msgid "Wireless Monitor"
+msgstr "WLAN-yhteyden tiedot"
+
+#: ../applets/mb-applet-clock.c:146
+#, c-format
+msgid "%.2d:%.2d"
+msgstr "%.2d:%.2d"
+
+#: ../applets/mb-applet-clock.c:234
+msgid "%a %b %e %k:%M:%S %Y"
+msgstr "%a %b %e %k:%M:%S %Y"
+
+#: ../applets/mb-applet-clock.c:333
+msgid "Clock"
+msgstr "Kello"
+
+#: ../applets/mb-applet-clock.c:360
+msgid "Set Time"
+msgstr ""
+
+#: ../applets/mb-applet-battery.c:283
+#, c-format
+msgid ""
+"Battery power very low !\n"
+"\n"
+"Time Left: %.2i minutes"
+msgstr ""
+"Akkuteho alhaalla!\n"
+"\n"
+"Käyttöaikaa jäljellä: %.2i min."
+
+#: ../applets/mb-applet-battery.c:380
+#, c-format
+msgid ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+msgstr ""
+"Ulkoinen virtalähde kiinni\n"
+"Akun lataus: %.2i %%\n"
+
+#: ../applets/mb-applet-battery.c:383
+#, c-format
+msgid ""
+"AC Connected\n"
+"Fully charged.\n"
+msgstr ""
+"Ulkoinen virtalähde kiinni\n"
+"Akku ladattu täyteen.\n"
+
+#: ../applets/mb-applet-battery.c:390
+#, c-format
+msgid ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+msgstr ""
+"Akkuteho\n"
+"Virtaa %.2i %%\n"
+"Käyttöaikaa jäljellä: %.2i min.\n"
+
+#: ../applets/mb-applet-battery.c:392
+#, c-format
+msgid ""
+"Battery Power\n"
+" Device read error.\n"
+msgstr ""
+"Akkuteho\n"
+" Laitetiedoston lukuvirhe.\n"
+
+#: ../applets/mb-applet-battery.c:442
+msgid "Battery Monitor"
+msgstr "Akun tiedot"
+
+#: ../applets/mb-applet-battery.c:466
+msgid "More info"
+msgstr ""
+
+#~ msgid "Cant open mixer device"
+#~ msgstr "Mixer-laitetiedoston avaus epäonnistui"
+
+#~ msgid "Cant open mixer device for reading"
+#~ msgstr "Mixer-laitetiedoston avaus lukua varten epäonnistui"
+
+#~ msgid "Cant open mixer device for writing"
+#~ msgstr "Mixer-laitetiedoston avaus kirjoitusta varten epäonnistui"
+
+#~ msgid "Volume Control"
+#~ msgstr "Äänenvoimakkuuden säätö"
diff --git a/po/fr_FR.po b/po/fr_FR.po
new file mode 100644
index 0000000..d950026
--- /dev/null
+++ b/po/fr_FR.po
@@ -0,0 +1,138 @@
+# French localization of MatchBox Dock on-line help
+# Copyright (C) 2003
+# This file is distributed under the same license as the Matchbox package.
+# Brice <Brice@substantiel.fr>, 2003.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.7.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-02-02 10:37+0000\n"
+"PO-Revision-Date: 2003-12-06 12:06+0100\n"
+"Last-Translator: Brice <Brice@Substantiel.fr>\n"
+"Language-Team: Substantiel <Info@Substantiel.fr>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/panel_menu.c:68
+msgid "Remove"
+msgstr "Quitter"
+
+#: ../src/panel_menu.c:172
+msgid "Add"
+msgstr "Ajouter"
+
+#: ../src/panel_menu.c:259
+msgid "Hide"
+msgstr "Masquer"
+
+#: ../applets/mb-applet-system-monitor.c:253
+#, c-format
+msgid "CPU: %i %%, MEMORY: %i %%\n"
+msgstr "CPU: %i %%, MEMOIRE: %i %%\n"
+
+#: ../applets/mb-applet-system-monitor.c:324
+msgid "CPU/Mem Monitor"
+msgstr "Moniteur de CPU/Mem"
+
+#: ../applets/mb-applet-wireless.c:438
+#, fuzzy, c-format
+msgid ""
+"%s:\n"
+" Link %.1f\n"
+" Level %.1f\n"
+" Noise %.1f\n"
+msgstr "%s: Lien %.1f, Niveau %.1f, Bruit %.1f\n"
+
+#: ../applets/mb-applet-wireless.c:443
+#, c-format
+msgid "No wireless cards detected\n"
+msgstr "Aucune carte sans-fil détectée\n"
+
+#: ../applets/mb-applet-wireless.c:483
+msgid "Wireless Monitor"
+msgstr "Moniteur sans-fil"
+
+#: ../applets/mb-applet-clock.c:146
+#, c-format
+msgid "%.2d:%.2d"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:234
+msgid "%a %b %e %k:%M:%S %Y"
+msgstr ""
+
+#: ../applets/mb-applet-clock.c:333
+msgid "Clock"
+msgstr "Horloge"
+
+#: ../applets/mb-applet-clock.c:360
+msgid "Set Time"
+msgstr ""
+
+#: ../applets/mb-applet-battery.c:283
+#, fuzzy, c-format
+msgid ""
+"Battery power very low !\n"
+"\n"
+"Time Left: %.2i minutes"
+msgstr ""
+"BatterieJauge %.2i %%\n"
+"Temps restant: %.2i mn\n"
+
+#: ../applets/mb-applet-battery.c:380
+#, c-format
+msgid ""
+"AC Connected\n"
+"Charging: %.2i %%\n"
+msgstr ""
+"AC Conecté\n"
+"En charge: %.2i %%\n"
+
+#: ../applets/mb-applet-battery.c:383
+#, c-format
+msgid ""
+"AC Connected\n"
+"Fully charged.\n"
+msgstr ""
+"AC Conecté\n"
+"Batterie pleine.\n"
+
+#: ../applets/mb-applet-battery.c:390
+#, c-format
+msgid ""
+"Battery Power\n"
+"Juice %.2i %%\n"
+"Time left: %.2i mins\n"
+msgstr ""
+"BatterieJauge %.2i %%\n"
+"Temps restant: %.2i mn\n"
+
+#: ../applets/mb-applet-battery.c:392
+#, c-format
+msgid ""
+"Battery Power\n"
+" Device read error.\n"
+msgstr "BatterieErreur de lecture du composant.\n"
+
+#: ../applets/mb-applet-battery.c:442
+msgid "Battery Monitor"
+msgstr "Moniteur de la batterie"
+
+#: ../applets/mb-applet-battery.c:466
+msgid "More info"
+msgstr ""
+
+#~ msgid "Cant open mixer device"
+#~ msgstr "Ouverture impossible du composant de mixage"
+
+#~ msgid "Cant open mixer device for reading"
+#~ msgstr "Ouverture impossible du composant de mixage pour la lecture"
+
+#~ msgid "Cant open mixer device for writing"
+#~ msgstr "Ouverture impossible du composant de mixage pour l'écriture"
+
+#~ msgid "Volume Control"
+#~ msgstr "Controle du Volume"
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..92f9f65
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,15 @@
+PREFIXDIR = $(prefix)
+PKGDATADIR = $(pkgdatadir)
+DATADIR = $(datadir)
+
+INCLUDES = -DDATADIR=\"$(DATADIR)\" -DPKGDATADIR=\"$(PKGDATADIR)\" -DPREFIX=\"$(PREFIXDIR)\" $(LIBMB_CFLAGS)
+
+bin_PROGRAMS = matchbox-panel
+
+matchbox_panel_LDADD = $(LIBMB_LIBS)
+
+matchbox_panel_SOURCES = \
+ panel.c panel_app.c panel_menu.c panel_util.c session.c msg.c \
+ panel.h panel_app.h panel_menu.h panel_util.h session.h msg.h
+
+
diff --git a/src/msg.c b/src/msg.c
new file mode 100644
index 0000000..f213c95
--- /dev/null
+++ b/src/msg.c
@@ -0,0 +1,670 @@
+#include "msg.h"
+
+static MBLayout*
+msg_calc_win_size(MBPanel *d, MBPanelMessageQueue *m, int *w, int *h);
+
+
+/*
+static int
+_get_text_length(MBPanel *d, char *str, int cnt)
+{
+#ifdef USE_XFT
+ XGlyphInfo extents;
+ XftTextExtents8(d->dpy, d->msg_font, (unsigned char *) str,
+ cnt, &extents);
+ return extents.width;
+#else
+ return XTextWidth(d->msg_font, str, cnt);
+#endif
+}
+*/
+
+static unsigned long
+_get_server_time(MBPanel *d)
+{
+ XEvent xevent;
+ char c = 'a';
+
+ XChangeProperty (d->dpy, d->win_root,
+ d->atoms[ATOM_MB_DOCK_TIMESTAMP],
+ d->atoms[ATOM_MB_DOCK_TIMESTAMP],
+ 8, PropModeReplace, &c, 1);
+
+ for (;;) {
+ XMaskEvent(d->dpy, PropertyChangeMask, &xevent);
+ if (xevent.xproperty.atom == d->atoms[ATOM_MB_DOCK_TIMESTAMP])
+ {
+ return xevent.xproperty.time;
+ }
+ }
+}
+
+static void
+_send_tray_context_message(MBPanel *panel,
+ Window win)
+{
+ XEvent ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = win;
+ ev.xclient.message_type = panel->atoms[ATOM_MB_SYSTEM_TRAY_CONTEXT];
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = _get_server_time(panel);
+
+ XSendEvent(panel->dpy, win, False, NoEventMask, &ev);
+ XSync(panel->dpy, False);
+}
+
+
+MBPanelMessageQueue*
+msg_new(MBPanel *dock, XClientMessageEvent *e)
+{
+ MBPanelMessageQueue *m;
+ MBPanelApp *sender;
+
+ if ((sender = panel_app_get_from_window(dock, e->window )) == NULL)
+ return NULL;
+
+ m = (MBPanelMessageQueue *)malloc(sizeof(MBPanelMessageQueue));
+ m->sender = sender;
+
+ m->starttime = e->data.l[0];
+ m->timeout = e->data.l[2];
+
+ m->total_msg_length = e->data.l[3];
+ m->id = e->data.l[4];
+ m->data = (unsigned char *)malloc(sizeof(unsigned char)
+ *(m->total_msg_length+1));
+ m->current_msg_length = 0;
+ m->pending = False;
+ m->next = NULL;
+
+ if (dock->msg_queue_start == NULL)
+ {
+ DBG("queue is empty\n");
+ dock->msg_queue_start = dock->msg_queue_end = m;
+ } else {
+ DBG("queue is not empty\n");
+ dock->msg_queue_end->next = m;
+ dock->msg_queue_end = m;
+ }
+
+ return m;
+}
+
+void
+msg_destroy(MBPanel *panel, MBPanelMessageQueue *msg)
+{
+ MBPanelMessageQueue *msg_q;
+ if (panel->msg_queue_start == msg)
+ {
+ panel->msg_queue_start = msg->next;
+ } else {
+ for(msg_q=panel->msg_queue_start; msg_q->next != NULL; msg_q=msg_q->next)
+ {
+ if (msg_q->next == msg)
+ {
+ msg_q->next = msg->next;
+ break;
+ }
+ }
+ }
+
+ if (msg->extra_context_data) XFree(msg->extra_context_data);
+ free(msg->data);
+ free(msg);
+}
+
+void
+msg_add_data(MBPanel *d, XClientMessageEvent *e)
+{
+ MBPanelMessageQueue *m;
+
+ for(m=d->msg_queue_start; m != NULL; m=m->next)
+ {
+ if (m->sender->win == e->window)
+ {
+ if ( (m->total_msg_length - m->current_msg_length) > 20)
+ {
+ memcpy(&m->data[m->current_msg_length],e->data.b,sizeof(char)*20);
+ m->current_msg_length += 20;
+ } else {
+ memcpy(&m->data[m->current_msg_length],e->data.b,
+ (m->total_msg_length-m->current_msg_length) );
+ m->current_msg_length = m->total_msg_length;
+ m->data[m->total_msg_length] = '\0';
+
+ m->pending = True;
+ }
+ return;
+ }
+ }
+}
+
+void
+msg_win_create(MBPanel *panel,
+ MBPanelMessageQueue *msg)
+{
+ int msg_win_x = 0, msg_win_y = 0, msg_win_w = 0, msg_win_h = 0,
+ box_x_offset = 0, box_y_offset = 0, arrow_offset = 0, cnt = 0,
+ box_w, box_h;
+
+ int x, y, txt_v_offset;
+ unsigned char r, g, b, fr, fg, fb;
+
+ MBPixbufImage *img_backing = NULL;
+ MBDrawable *tmp_drw;
+
+ Pixmap mask;
+ GC mask_gc;
+ XSetWindowAttributes attr;
+ XWindowAttributes root_attr;
+ XWMHints *wm_hints;
+ long winmask;
+ MBLayout *layout;
+
+ /*
+#ifdef USE_XFT
+ XftDraw *xftdraw;
+ XftColor txt_xftcol;
+ XRenderColor colortmp;
+#endif
+ */
+
+ layout = msg_calc_win_size(panel, msg, &msg_win_w, &msg_win_h);
+
+ msg_win_h += (2*MSG_WIN_Y_PAD);
+
+ box_w = msg_win_w; box_h = msg_win_h;
+
+ XGetWindowAttributes(panel->dpy, panel->win_root, &root_attr);
+
+#define ARROW_SIZE 4
+#define MSG_TEXT_MARGIN 10
+
+ switch (panel->orientation)
+ {
+ case East:
+ msg_win_w += ARROW_SIZE;
+ msg_win_x = panel->x - msg_win_w - 5;
+ break;
+ case West:
+ msg_win_w += ARROW_SIZE;
+ box_x_offset += ARROW_SIZE;
+ msg_win_x = panel->x + panel->w + 5;
+ break;
+ case South:
+ msg_win_h += ARROW_SIZE;
+ msg_win_y = panel->y - msg_win_h - 5;
+ break;
+ case North:
+ msg_win_h += ARROW_SIZE;
+ box_y_offset += ARROW_SIZE;
+ msg_win_y = panel->y + panel->h + 5;
+ break;
+ }
+
+ printf("%s() called()\n", __func__);
+
+ if (PANEL_IS_VERTICAL(panel))
+ {
+ arrow_offset = msg_win_h / 2;
+ msg_win_y = panel->y + msg->sender->y + (msg->sender->h/2) - arrow_offset;
+
+ if (msg_win_y < 0)
+ {
+ msg_win_y = 5; /* a little margin to display top */
+ arrow_offset = msg->sender->y + (msg->sender->h/2);
+ }
+
+ if (msg_win_y + msg_win_h > panel->y + panel->h)
+ {
+ /* reposition with a bit of margin - 5px */
+ msg_win_y = (panel->y + panel->h) - msg_win_h - 5;
+ arrow_offset = panel->y + msg->sender->y - msg_win_y + (msg->sender->h/2);
+ }
+ }
+ else
+ {
+ arrow_offset = msg_win_w / 2;
+ msg_win_x = panel->x + msg->sender->x + (msg->sender->w/2) - arrow_offset;
+
+ if (msg_win_x < 0)
+ {
+ msg_win_x = 5;
+ arrow_offset = msg->sender->x + (msg->sender->w/2);
+ }
+
+ if (msg_win_x + msg_win_w > panel->x + panel->w)
+ {
+ msg_win_x = (panel->x + panel->w) - msg_win_w - 5;
+ arrow_offset = panel->x + msg->sender->x - msg_win_x + (msg->sender->w/2);
+ }
+ }
+
+ attr.event_mask = ButtonPressMask|ButtonReleaseMask|ExposureMask;
+ attr.background_pixel = BlackPixel(panel->dpy, panel->screen);
+ attr.do_not_propagate_mask = ButtonPressMask|ButtonReleaseMask;
+ winmask = CWBackPixel|CWEventMask|CWDontPropagate;
+
+ if (panel->use_overide_wins)
+ {
+ winmask |= CWOverrideRedirect;
+ attr.override_redirect = True;
+ }
+
+ panel->msg_win = XCreateWindow(panel->dpy, panel->win_root,
+ msg_win_x,
+ msg_win_y,
+ msg_win_w,
+ msg_win_h, 0,
+ CopyFromParent,
+ CopyFromParent,
+ CopyFromParent,
+ winmask,
+ &attr);
+
+ XChangeProperty(panel->dpy, panel->msg_win,
+ panel->atoms[ATOM_WM_WINDOW_TYPE],
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)
+ &panel->atoms[ATOM_WM_WINDOW_TYPE_SPLASH], 1);
+
+ wm_hints = XAllocWMHints();
+ wm_hints->input = False;
+ wm_hints->flags = InputHint;
+ XSetWMHints(panel->dpy, panel->msg_win, wm_hints);
+
+ tmp_drw = mb_drawable_new(panel->pb, msg_win_w, msg_win_h);
+
+ img_backing = mb_pixbuf_img_rgba_new(panel->pb, msg_win_w, msg_win_h);
+
+ mask = XCreatePixmap(panel->dpy, panel->win_root, msg_win_w, msg_win_h, 1 );
+ mask_gc = XCreateGC(panel->dpy, mask, 0, 0 );
+
+ XSetForeground(panel->dpy, mask_gc, WhitePixel( panel->dpy, panel->screen ));
+ XFillRectangle(panel->dpy, mask, mask_gc, 0, 0, msg_win_w, msg_win_h );
+ XSetForeground(panel->dpy, mask_gc, BlackPixel( panel->dpy, panel->screen ));
+
+ /*
+ * - fill entire block with forground color
+ * - alpha clear part
+ * - draw arrow part
+ * - curve corners ?
+ */
+
+ r = mb_col_red(panel->msg_col);
+ g = mb_col_green(panel->msg_col);
+ b = mb_col_blue(panel->msg_col);
+
+ fr = mb_col_red(panel->msg_fg_col);
+ fg = mb_col_green(panel->msg_fg_col);
+ fb = mb_col_blue(panel->msg_fg_col);
+
+ mb_pixbuf_img_fill (panel->pb, img_backing, r, g, b, 255);
+
+ /* border */
+
+ /* top/bottom */
+ for (x = box_x_offset; x < box_x_offset + box_w; x++)
+ {
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, box_y_offset,
+ fr, fg, fb);
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x,
+ box_h + box_y_offset - 1,
+ fr, fg, fb);
+ }
+
+ /* sides */
+ for (y = box_y_offset; y < box_y_offset + box_h; y++)
+ {
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, box_x_offset, y,
+ fr, fg, fb);
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing,
+ box_w + box_x_offset - 1, y,
+ fr, fg, fb);
+ }
+
+ /* arrow */
+
+ switch (panel->orientation)
+ {
+ case East:
+
+ for (x= box_w; x < msg_win_w; x++)
+ for (y=0; y < box_h; y++)
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+
+ XSetForeground( panel->dpy, mask_gc,
+ WhitePixel( panel->dpy, panel->screen ));
+
+ for (x= msg_win_w - 1; x > msg_win_w - ARROW_SIZE - 2 ; x--)
+ {
+ for (y = arrow_offset - cnt; y <= arrow_offset + cnt; y++)
+ {
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+ if ( y == (arrow_offset - cnt) || y == (arrow_offset + cnt) )
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y,
+ fr, fg, fb);
+ else
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y, r,g,b);
+ }
+ cnt++;
+ }
+
+ break;
+
+ case West:
+
+ for (x=0; x<ARROW_SIZE; x++)
+ for (y=0; y < msg_win_h; y++)
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+
+ XSetForeground( panel->dpy, mask_gc,
+ WhitePixel( panel->dpy, panel->screen ));
+
+ for (x=0; x<ARROW_SIZE + 1; x++)
+ {
+ for (y = arrow_offset - cnt; y <= arrow_offset + cnt; y++)
+ {
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+ if ( y == (arrow_offset - cnt) || y == (arrow_offset + cnt) )
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y,
+ fr, fg, fb);
+ else
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y, r,g,b);
+ }
+ cnt++;
+ }
+
+ break;
+
+ case South:
+
+ for (y=msg_win_h-ARROW_SIZE; y < msg_win_h; y++)
+ for (x=0; x < msg_win_w; x++)
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+
+ XSetForeground( panel->dpy, mask_gc,
+ WhitePixel( panel->dpy, panel->screen ));
+
+ for (y=msg_win_h; y >= msg_win_h - ARROW_SIZE - 1; y--)
+ {
+ for (x = arrow_offset - cnt; x <= arrow_offset + cnt; x++)
+ {
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+ if ( x == (arrow_offset - cnt) || x == (arrow_offset + cnt) )
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y,
+ fr, fg, fb);
+ else
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y, r,g,b);
+ }
+ cnt++;
+ }
+
+ break;
+
+ case North:
+
+ for (y=0; y < ARROW_SIZE; y++)
+ for (x=0; x < msg_win_w; x++)
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+
+ XSetForeground( panel->dpy, mask_gc,
+ WhitePixel( panel->dpy, panel->screen ));
+
+ for (y=0; y < ARROW_SIZE + 1; y++)
+ {
+ for (x = arrow_offset - cnt; x <= arrow_offset + cnt; x++)
+ {
+ XDrawPoint(panel->dpy, mask, mask_gc, x, y);
+
+ if ( x == (arrow_offset - cnt) || x == (arrow_offset + cnt) )
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y,
+ fr, fg, fb);
+ else
+ mb_pixbuf_img_plot_pixel(panel->pb, img_backing, x, y, r,g,b);
+ }
+
+ cnt++;
+ }
+
+ break;
+
+ }
+
+ /* Render picture to pixmap */
+ mb_pixbuf_img_render_to_drawable(panel->pb, img_backing,
+ mb_drawable_pixmap(tmp_drw),
+ 0, 0);
+
+
+ mb_font_set_color(panel->msg_font, panel->msg_fg_col);
+
+ txt_v_offset = MSG_WIN_Y_PAD + box_y_offset;
+
+ /*
+ i = strlen(msg->sender->name);
+ while (_get_text_length(panel, msg->sender->name, i) > ( box_w + ( 2 * MSG_TEXT_MARGIN ))
+ && i > 0)
+ i--;
+ */
+
+ /* Title */
+
+ XSetForeground(panel->dpy, panel->msg_gc, mb_col_xpixel(panel->msg_fg_col));
+
+ mb_font_render_simple (panel->msg_font,
+ tmp_drw,
+ MSG_TEXT_MARGIN + box_x_offset,
+ txt_v_offset,
+ box_w, /* XXX - TEXT_MARGIN ? */
+ (unsigned char *)msg->sender->name,
+ MB_ENCODING_UTF8,
+ 0);
+
+ /* close box */
+
+ XDrawRectangle(panel->dpy, mb_drawable_pixmap(tmp_drw), panel->msg_gc,
+ box_x_offset + box_w - MSG_TEXT_MARGIN - mb_font_get_height(panel->msg_font),
+ txt_v_offset,
+ mb_font_get_height(panel->msg_font),
+ mb_font_get_height(panel->msg_font) );
+
+ XDrawLine(panel->dpy, mb_drawable_pixmap(tmp_drw), panel->msg_gc,
+ box_x_offset + box_w - MSG_TEXT_MARGIN - mb_font_get_height(panel->msg_font),
+ txt_v_offset ,
+ box_x_offset + box_w - MSG_TEXT_MARGIN,
+ txt_v_offset + mb_font_get_height(panel->msg_font));
+
+ XDrawLine(panel->dpy, mb_drawable_pixmap(tmp_drw), panel->msg_gc,
+ box_x_offset + box_w - MSG_TEXT_MARGIN - mb_font_get_height(panel->msg_font),
+ txt_v_offset + mb_font_get_height(panel->msg_font),
+ box_x_offset + box_w - MSG_TEXT_MARGIN,
+ txt_v_offset );
+
+ /* Title underline */
+
+ XDrawLine(panel->dpy, mb_drawable_pixmap(tmp_drw), panel->msg_gc,
+ box_x_offset + MSG_TEXT_MARGIN / 2 ,
+ txt_v_offset + mb_font_get_height(panel->msg_font) + ( MSG_LINE_SPC / 2 ),
+ box_x_offset + box_w - (MSG_TEXT_MARGIN / 2),
+ txt_v_offset + mb_font_get_height(panel->msg_font) + ( MSG_LINE_SPC / 2 ) );
+
+ /* Forward render postion on */
+ txt_v_offset += mb_font_get_height(panel->msg_font) + MSG_LINE_SPC;
+
+ /* render msg text */
+ mb_layout_render (layout, tmp_drw, MSG_TEXT_MARGIN + box_x_offset, txt_v_offset, 0);
+
+ txt_v_offset += mb_layout_height(layout);
+
+ /* Context button, if applicable */
+ if (msg->extra_context_data)
+ {
+ int context_width = mb_font_get_txt_width ( panel->msg_font,
+ msg->extra_context_data,
+ strlen(msg->extra_context_data),
+ MB_ENCODING_UTF8);
+
+ XSetForeground( panel->dpy, panel->msg_gc, mb_col_xpixel(panel->msg_link_col));
+
+ panel->msg_context_y1 = txt_v_offset;
+ panel->msg_context_y2 = txt_v_offset + mb_font_get_height(panel->msg_font);
+
+ mb_font_set_color(panel->msg_font, panel->msg_link_col);
+
+ mb_font_render_simple (panel->msg_font,
+ tmp_drw,
+ MSG_TEXT_MARGIN + box_x_offset,
+ txt_v_offset,
+ box_w,
+ (unsigned char *)msg->extra_context_data,
+ MB_ENCODING_UTF8,
+ 0);
+
+ /* underline */
+
+ XDrawLine(panel->dpy, mb_drawable_pixmap(tmp_drw), panel->msg_gc,
+ MSG_TEXT_MARGIN + box_x_offset,
+ txt_v_offset + mb_font_get_height(panel->msg_font),
+ MSG_TEXT_MARGIN + box_x_offset + context_width,
+ txt_v_offset + mb_font_get_height(panel->msg_font));
+ }
+
+
+ XSetWindowBackgroundPixmap(panel->dpy, panel->msg_win,
+ mb_drawable_pixmap(tmp_drw));
+
+
+ mb_drawable_unref(tmp_drw);
+
+ XShapeCombineMask( panel->dpy, panel->msg_win, ShapeBounding, 0, 0, mask, ShapeSet);
+
+ XMapWindow(panel->dpy, panel->msg_win);
+ XFree(wm_hints);
+
+ mb_pixbuf_img_free(panel->pb, img_backing);
+ XFreePixmap(panel->dpy, mask);
+}
+
+
+void
+msg_handle_events(MBPanel *panel, XEvent *e)
+{
+ MBPanelMessageQueue *msg = NULL;
+
+ for(msg=panel->msg_queue_start; msg != NULL; msg=msg->next)
+ {
+ if (msg->pending)
+ {
+ if (panel->msg_win)
+ {
+ XDestroyWindow(panel->dpy, panel->msg_win);
+ panel->msg_win = None;
+ }
+
+ panel->msg_starttime = msg->starttime;
+ panel->msg_timeout = msg->timeout;
+ panel->msg_win_sender = msg->sender;
+
+ panel->msg_has_context = False;
+
+ if ((msg->extra_context_data = util_get_utf8_prop(panel, panel->msg_win_sender->win, panel->atoms[ATOM_MB_SYSTEM_TRAY_CONTEXT])) != NULL)
+ panel->msg_has_context = True;
+
+ msg_win_create(panel, msg);
+
+ msg_destroy(panel, msg);
+
+ return;
+ }
+ }
+
+ if (panel->msg_win)
+ {
+ switch (e->type)
+ {
+ case Expose:
+ break;
+ case ButtonRelease:
+ if ( e->xbutton.window == panel->msg_win)
+ {
+ if (panel->msg_has_context
+ && e->xbutton.y >= panel->msg_context_y1
+ && e->xbutton.y <= panel->msg_context_y2)
+ {
+ _send_tray_context_message(panel, panel->msg_win_sender->win);
+ }
+
+ XDestroyWindow(panel->dpy, panel->msg_win);
+ panel->msg_win = None;
+ }
+ break;
+ }
+ }
+}
+
+void
+msg_handle_timeouts(MBPanel *d)
+{
+ if (d->msg_win)
+ {
+ if (d->msg_timeout) /* NON ZERO */
+ {
+ if ((d->msg_starttime+d->msg_timeout) < _get_server_time(d))
+ {
+ XDestroyWindow(d->dpy, d->msg_win);
+ d->msg_win = None;
+ return;
+ }
+ }
+ }
+}
+
+static MBLayout*
+msg_calc_win_size(MBPanel *panel, MBPanelMessageQueue *m, int *w, int *h)
+{
+ MBLayout *layout;
+
+ int title_width = 0, context_width = 0;
+
+ *w = 0;
+ *h = 0;
+
+ layout = mb_layout_new ();
+
+ mb_layout_set_font(layout, panel->msg_font);
+ mb_layout_set_text(layout, m->data, MB_ENCODING_UTF8);
+
+ mb_layout_get_geometry(layout, w, h);
+
+ /* title + line */
+ *h += (mb_font_get_height(panel->msg_font) + MSG_LINE_SPC) ;
+
+ title_width = mb_font_get_txt_width(panel->msg_font,
+ m->sender->name, strlen(m->sender->name),
+ MB_ENCODING_UTF8)
+ + (2 * mb_font_get_height(panel->msg_font));
+
+ if (title_width > *w) *w = title_width;
+
+ if (m->extra_context_data)
+ {
+ context_width = mb_font_get_txt_width(panel->msg_font,
+ m->extra_context_data,
+ strlen(m->extra_context_data),
+ MB_ENCODING_UTF8);
+
+ if (context_width > *w) *w = context_width;
+
+ *h += mb_font_get_height(panel->msg_font);
+ }
+
+ *w += ( 2 * MSG_TEXT_MARGIN );
+
+ return layout;
+}
+
+
diff --git a/src/msg.h b/src/msg.h
new file mode 100644
index 0000000..5fe90ef
--- /dev/null
+++ b/src/msg.h
@@ -0,0 +1,20 @@
+#ifndef _MSG_H_
+#define _MSG_H_
+
+#include <string.h>
+
+#include "panel.h"
+#include "panel_app.h"
+
+#define MSG_WIN_Y_PAD 5
+#define MSG_BUB_POLY 15
+
+#define MSG_LINE_SPC 8
+
+MBPanelMessageQueue* msg_new(MBPanel *dock, XClientMessageEvent *e);
+void msg_destroy(MBPanel *d, MBPanelMessageQueue *m);
+void msg_add_data(MBPanel *d, XClientMessageEvent *e);
+void msg_handle_events(MBPanel *d, XEvent *e);
+void msg_handle_timeouts(MBPanel *d);
+
+#endif
diff --git a/src/panel.c b/src/panel.c
new file mode 100644
index 0000000..1c4d691
--- /dev/null
+++ b/src/panel.c
@@ -0,0 +1,2030 @@
+/*
+ * mbpanel
+ *
+ * A 'system tray' - Matthew Allum <mallum@handhelds.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "panel.h"
+#include "msg.h"
+
+MBPanel *G_panel = NULL;
+
+#define DEFAULT_MSG_FGCOL "black"
+#define DEFAULT_MSG_BGCOL "yellow"
+#define DEFAULT_MSG_BGURGCOL "orange"
+
+#ifdef USE_XSETTINGS
+
+/*
+ XX = system_tray_id;
+
+/MATCHBOX/PANEL/XX/ORIENTATION north|south|east|west
+/MATCHBOX/PANEL/XX/BACKGROUND default|rgb:XXX|pxm:XXX|trans:XXX
+ Gtk/FontName
+*/
+
+#define XSET_UNKNOWN 0
+#define XSET_GTK_FONT 1
+
+static void
+panel_xsettings_notify_cb (const char *name,
+ XSettingsAction action,
+ XSettingsSetting *setting,
+ void *data)
+{
+ MBPanel *panel = (MBPanel *)data;
+ int i = 0;
+ int key = XSET_UNKNOWN;
+
+ struct _mb_xsettings { char *name; int value; } mb_xsettings[] = {
+ { "Gtk/FontName", XSET_GTK_FONT },
+ { NULL, -1 }
+ };
+
+ while( mb_xsettings[i].name != NULL )
+ {
+ if (!strcmp(name, mb_xsettings[i].name)
+ && setting != NULL /* XXX set to NULL when action deleted */
+ && setting->type == XSETTINGS_TYPE_STRING )
+ {
+ key = mb_xsettings[i].value;
+ break;
+ }
+ i++;
+ }
+
+ if (key == XSET_UNKNOWN) return;
+
+ switch (action)
+ {
+ case XSETTINGS_ACTION_NEW:
+ case XSETTINGS_ACTION_CHANGED:
+ switch (key)
+ {
+ case XSET_GTK_FONT:
+ if (setting->data.v_string && strlen(setting->data.v_string))
+ {
+ /* This will be overidden ( hopefully ) by any theme.desktop
+ * setting.
+ */
+ DBG("%s() setting XSET_GTK_FONT: '%s'\n", __func__,
+ setting->data.v_string);
+ /* mb_menu_set_font (panel->mbmenu, setting->data.v_string); */
+ mb_font_set_from_string(panel->msg_font, setting->data.v_string);
+
+ }
+ break;
+
+ }
+ case XSETTINGS_ACTION_DELETED:
+ /* Do nothing for now */
+ break;
+ }
+}
+
+#endif
+
+
+void
+panel_handle_full_panel (MBPanel *panel, MBPanelApp *bad_papp)
+{
+
+ /* For now we just killoff the client */
+
+ DBG("%s() killing winbow id %li\n", __func__, bad_papp->win);
+
+ XKillClient(panel->dpy, bad_papp->win); /* XXX should probably make this
+ kill more effectively */
+ panel_app_destroy (panel, bad_papp);
+}
+
+void /* XXX maybe better to add this to panel_menu_add_remove_item */
+panel_update_client_list_prop (MBPanel *panel)
+{
+ MBPanelApp *papp = NULL;
+ MBPanelApp *papp_heads[] = { panel->apps_start_head,
+ panel->apps_end_head,
+ NULL };
+ int i = 0, app_cnt = 0, cnt = 0;
+ Window *wins = NULL;
+
+ DBG("%s() called\n", __func__);
+
+ /* Count number of applets docked */
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+ while( papp != NULL)
+ {
+ if (!papp->ignore) app_cnt++;
+ papp = papp->next;
+ }
+ i++;
+ }
+
+ if (app_cnt == 0)
+ {
+ /* delete prop ?? */
+ XChangeProperty(panel->dpy, panel->win,
+ panel->atoms[ATOM_NET_CLIENT_LIST] ,
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)NULL, 0);
+ return;
+ }
+
+ i = 0;
+ wins = malloc(sizeof(Window)*app_cnt);
+
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+
+ if (i == 1)
+ papp = panel_app_list_get_last(panel, panel->apps_end_head);
+
+ while( papp != NULL)
+ {
+ if (!papp->ignore)
+ {
+ wins[cnt++] = papp->win;
+ }
+
+ if (i == 1)
+ {
+ papp = panel_app_list_get_prev (panel, papp,
+ &panel->apps_end_head);
+ }
+ else papp = papp->next;
+ }
+ i++;
+ }
+
+
+ XChangeProperty(panel->dpy, panel->win,
+ panel->atoms[ATOM_NET_CLIENT_LIST],
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)wins, app_cnt);
+
+ free(wins);
+
+}
+
+
+void /* show/hiden the panel */
+panel_toggle_visibilty(MBPanel *d)
+{
+
+#define PANEL_HIDDEN_SIZE 6
+
+
+ static int panel_orig_size;
+ MBPanelApp *papp = NULL;
+ MBPanelApp *papp_heads[] = { d->apps_start_head,
+ d->apps_end_head,
+ NULL };
+ int i = 0;
+
+ DBG("%s() called, x: %i, y: %i, w: %i, h: %i\n", __func__,
+ d->x, d->y, d->w, d->h);
+
+ if (d->is_hidden)
+ {
+
+ if (PANEL_IS_VERTICAL(d))
+ {
+ XMoveResizeWindow(d->dpy, d->win, d->x, d->y,
+ panel_orig_size, d->h );
+ d->w = panel_orig_size;
+ } else {
+ XMoveResizeWindow(d->dpy, d->win, d->x, d->y, d->w,
+ panel_orig_size);
+ d->h = panel_orig_size;
+ }
+
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+ while( papp != NULL)
+ {
+ XMapWindow(d->dpy, papp->win);
+ panel_app_move_to (d, papp,
+ panel_app_get_offset (d, papp));
+ papp->ignore_unmap--;
+ papp = papp->next;
+ }
+ i++;
+ }
+
+ d->is_hidden = False;
+
+ } else {
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+ while( papp != NULL)
+ {
+ XUnmapWindow(d->dpy, papp->win);
+ papp->ignore_unmap++;
+ papp = papp->next;
+ }
+ i++;
+ }
+
+ if (PANEL_IS_VERTICAL(d))
+ {
+ XMoveResizeWindow(d->dpy, d->win, d->x, d->y,
+ PANEL_HIDDEN_SIZE, d->h );
+ panel_orig_size = d->w;
+ } else {
+ XMoveResizeWindow(d->dpy, d->win, d->x, d->y,
+ d->w, PANEL_HIDDEN_SIZE);
+ panel_orig_size = d->h;
+ }
+ d->is_hidden = True;
+ }
+}
+
+void
+panel_set_bg(MBPanel *panel, int bg_type, char *bg_spec)
+{
+ MBPixbufImage *img_tmp, *img_bg;
+ int dx, dy, dw, dh;
+
+ Pixmap tmp_pxm;
+ char xprop_def[32] = { 0 };
+ char *tmp_path = NULL;
+
+ if (panel->bg_spec) free(panel->bg_spec);
+ panel->bg_spec = strdup(bg_spec);
+ panel->bg_type = bg_type;
+
+ DBG("%s() bg_spec: %s, type %i\n", __func__, panel->bg_spec, panel->bg_type);
+
+ XGrabServer(panel->dpy);
+
+ switch (bg_type)
+ {
+ case BG_PIXMAP:
+ if (bg_spec[0] != '/' && panel->theme_path != NULL)
+ {
+ tmp_path = alloca( sizeof(char) * (strlen(panel->theme_path) + strlen(bg_spec)));
+ sprintf(tmp_path, "%s/%s", panel->theme_path, bg_spec);
+ }
+ else tmp_path = bg_spec;
+
+ if ((img_tmp = mb_pixbuf_img_new_from_file(panel->pb, tmp_path)) == NULL)
+ {
+ fprintf(stderr, "mbdock: failed to load %s\n", bg_spec);
+ panel_set_bg(panel, BG_SOLID_COLOR, DEFAULT_COLOR_SPEC);
+ return;
+ }
+
+ img_bg = mb_pixbuf_img_new(panel->pb, panel->w, panel->h);
+
+ /* scale for panel height ? */
+ if ( (img_tmp->height != panel->h && !PANEL_IS_VERTICAL(panel))
+ || (img_tmp->width != panel->w && PANEL_IS_VERTICAL(panel)) )
+ {
+ MBPixbufImage *img_scaled;
+ img_scaled = mb_pixbuf_img_scale(panel->pb, img_tmp,
+ img_tmp->width,
+ PANEL_IS_VERTICAL(panel) ?
+ panel->w : panel->h);
+ mb_pixbuf_img_free(panel->pb, img_tmp);
+ img_tmp = img_scaled;
+ }
+
+ /* rotate */
+ if (PANEL_IS_VERTICAL(panel))
+ {
+ MBPixbufImage *img_rot;
+ img_rot = mb_pixbuf_img_transform (panel->pb, img_tmp,
+ MBPIXBUF_TRANS_ROTATE_90);
+
+ mb_pixbuf_img_free(panel->pb, img_tmp);
+ img_tmp = img_rot;
+ }
+
+ for (dy=0; dy < panel->h; dy += img_tmp->height)
+ for (dx=0; dx < panel->w; dx += img_tmp->width)
+ {
+ if ( (dx + img_tmp->width) > panel->w )
+ dw = img_tmp->width - ((dx + img_tmp->width)-panel->w);
+ else
+ dw = img_tmp->width;
+
+ if ( (dy + img_tmp->height) > panel->h )
+ dh = img_tmp->height-((dy + img_tmp->height)-panel->h);
+ else
+ dh = img_tmp->height;
+ mb_pixbuf_img_copy(panel->pb, img_bg, img_tmp,
+ 0, 0, dw, dh, dx, dy);
+ }
+
+ mb_pixbuf_img_free(panel->pb, img_tmp);
+
+ if (panel->bg_pxm != None)
+ XFreePixmap(panel->dpy, panel->bg_pxm);
+
+ panel->bg_pxm = XCreatePixmap(panel->dpy, panel->win_root,
+ panel->w, panel->h,
+ panel->pb->depth );
+
+ mb_pixbuf_img_render_to_drawable(panel->pb, img_bg, panel->bg_pxm, 0, 0);
+
+ mb_pixbuf_img_free(panel->pb, img_bg);
+
+ XSetWindowBackgroundPixmap(panel->dpy, panel->win, panel->bg_pxm);
+ XClearWindow(panel->dpy, panel->win);
+
+ snprintf(xprop_def, 32, "pxm:%li", panel->bg_pxm);
+ panel->root_pixmap_id = 0;
+ break;
+ case BG_SOLID_COLOR:
+ if (XParseColor(panel->dpy,
+ DefaultColormap(panel->dpy, panel->screen),
+ bg_spec,
+ &panel->xcol ))
+ {
+
+ XAllocColor(panel->dpy,
+ DefaultColormap(panel->dpy, panel->screen),
+ &panel->xcol);
+
+ XSetWindowBackground(panel->dpy, panel->win,
+ panel->xcol.pixel);
+ XClearWindow(panel->dpy, panel->win);
+
+ if (panel->bg_pxm != None)
+ XFreePixmap(panel->dpy, panel->bg_pxm);
+ panel->bg_pxm = None;
+
+ snprintf(xprop_def, 32, "rgb:%li", panel->xcol.pixel);
+ }
+ panel->root_pixmap_id = 0;
+ break;
+ case BG_TRANS:
+ tmp_pxm = util_get_root_pixmap(panel);
+ if (tmp_pxm != None)
+ {
+ int trans_level = 0;
+
+ if (bg_spec) trans_level = atoi(bg_spec);
+
+ DBG("%s() Getting root pixmap\n", __func__);
+
+ if (panel->bg_pxm != None) XFreePixmap(panel->dpy, panel->bg_pxm);
+
+ panel->bg_pxm = XCreatePixmap(panel->dpy, panel->win_root,
+ panel->w, panel->h,
+ panel->pb->depth );
+
+ img_tmp = mb_pixbuf_img_new_from_drawable(panel->pb,
+ tmp_pxm, None,
+ panel->x, panel->y,
+ panel->w, panel->h);
+ if (img_tmp == NULL)
+ {
+ XFreePixmap(panel->dpy, panel->bg_pxm);
+ fprintf(stderr, "Failed to get root pixmap id\n");
+ panel_set_bg(panel, BG_SOLID_COLOR, DEFAULT_COLOR_SPEC);
+ return;
+ }
+
+ DBG("%s() First pixel of root looks like %i, %i, %i, %i\n",
+ __func__, img_tmp->rgba[0], img_tmp->rgba[1],
+ img_tmp->rgba[2], img_tmp->rgba[3]);
+
+ if (trans_level > 0)
+ for (dx = 0; dx < panel->w; dx++)
+ for (dy = 0; dy < panel->h; dy++)
+ mb_pixbuf_img_plot_pixel_with_alpha(panel->pb,
+ img_tmp, dx, dy,
+ 255, 255, 255,
+ trans_level);
+
+
+ mb_pixbuf_img_render_to_drawable(panel->pb, img_tmp,
+ panel->bg_pxm, 0, 0);
+
+ mb_pixbuf_img_free(panel->pb, img_tmp);
+
+
+ XSetWindowBackgroundPixmap(panel->dpy, panel->win,
+ panel->bg_pxm);
+ XClearWindow(panel->dpy, panel->win);
+
+ snprintf(xprop_def, 32, "pxm:%li", panel->bg_pxm);
+
+ } else {
+ fprintf(stderr, "Failed to get root pixmap id\n");
+ panel->root_pixmap_id = -1;
+ panel_set_bg(panel, BG_SOLID_COLOR, DEFAULT_COLOR_SPEC);
+ return;
+ }
+
+ break;
+ }
+
+ if (xprop_def)
+ {
+ DBG("setting _MB_PANEL_BG to %s\n", xprop_def);
+
+ XChangeProperty(panel->dpy, panel->win,
+ panel->atoms[ATOM_MB_PANEL_BG],
+ XA_STRING, 8,
+ PropModeReplace, xprop_def,
+ strlen(xprop_def));
+ }
+
+ XUngrabServer(panel->dpy);
+
+ XSync(panel->dpy, False);
+
+}
+
+Bool
+panel_set_theme_from_root_prop(MBPanel *panel)
+{
+ Atom realType;
+ unsigned long n;
+ unsigned long extra;
+ int format;
+ int status;
+ char * value;
+ struct stat stat_info;
+ char panel_cfg[256];
+
+ DBG("%s() called\n", __func__);
+
+ if ( panel->use_themes == False )
+ {
+ DBG("%s() panel themeing disabled by command line options\n", __func__ );
+ return False;
+ }
+
+ status = XGetWindowProperty(panel->dpy, panel->win_root,
+ panel->atoms[ATOM_MB_THEME],
+ 0L, 512L, False,
+ AnyPropertyType, &realType,
+ &format, &n, &extra,
+ (unsigned char **) &value);
+
+ if (status != Success || value == 0
+ || *value == 0 || n == 0)
+ {
+ DBG("%s() no _MB_THEME set on root window\n", __func__ );
+ return False;
+ } else {
+
+ int i = 0;
+ MBPanelApp *papp = NULL;
+ MBPanelApp *papp_heads[] = { panel->apps_start_head,
+ panel->apps_end_head,
+ NULL };
+
+ strcpy(panel_cfg, value);
+ strcat(panel_cfg, "/theme.desktop");
+
+ if (stat(panel_cfg, &stat_info) != -1)
+ {
+ MBDotDesktop *theme = NULL;
+ theme = mb_dotdesktop_new_from_file(panel_cfg);
+ if (theme)
+ {
+ if (panel->theme_path) free(panel->theme_path);
+ panel->theme_path = strdup(value);
+
+ /* Different theme values for panel in titlebar */
+ if (panel->want_titlebar_dest)
+ {
+ if (mb_dotdesktop_get(theme, "TitlebarDockBgColor"))
+ {
+ panel_set_bg(panel, BG_SOLID_COLOR,
+ mb_dotdesktop_get(theme, "TitlebarDockBgColor"));
+ }
+
+ if (mb_dotdesktop_get(theme, "TitlebarDockBgPixmap"))
+ {
+ panel_set_bg(panel, BG_PIXMAP,
+ mb_dotdesktop_get(theme, "TitlebarDockBgPixmap"));
+ }
+
+ /* Newer settings */
+
+ if (mb_dotdesktop_get(theme, "TitlebarPanelBgColor"))
+ {
+ panel_set_bg(panel, BG_SOLID_COLOR,
+ mb_dotdesktop_get(theme, "TitlebarPanelBgColor"));
+ }
+
+ if (mb_dotdesktop_get(theme, "TitlebarPanelBgPixmap"))
+ {
+ panel_set_bg(panel, BG_PIXMAP,
+ mb_dotdesktop_get(theme, "TitlebarPanelBgPixmap"));
+ }
+
+
+ }
+ else
+ {
+
+ /*
+ * FIXME: Need to phase out the Dock prefix to panel
+ */
+
+ if (mb_dotdesktop_get(theme, "DockBgColor"))
+ {
+ panel_set_bg(panel, BG_SOLID_COLOR,
+ mb_dotdesktop_get(theme, "DockBgColor"));
+ }
+ if (mb_dotdesktop_get(theme, "DockBgTrans"))
+ {
+ panel_set_bg(panel, BG_TRANS,
+ mb_dotdesktop_get(theme, "DockBgTrans"));
+ }
+ if (mb_dotdesktop_get(theme, "DockBgPixmap"))
+ {
+ panel_set_bg(panel, BG_PIXMAP,
+ mb_dotdesktop_get(theme, "DockBgPixmap"));
+ }
+
+ /* Newer setting below */
+
+ if (mb_dotdesktop_get(theme, "PanelBgColor"))
+ {
+ panel_set_bg(panel, BG_SOLID_COLOR,
+ mb_dotdesktop_get(theme, "PanelBgColor"));
+ }
+ if (mb_dotdesktop_get(theme, "PanelBgTrans"))
+ {
+ panel_set_bg(panel, BG_TRANS,
+ mb_dotdesktop_get(theme, "PanelBgTrans"));
+ }
+ if (mb_dotdesktop_get(theme, "PanelBgPixmap"))
+ {
+ panel_set_bg(panel, BG_PIXMAP,
+ mb_dotdesktop_get(theme, "PanelBgPixmap"));
+ }
+
+
+ }
+
+ if (mb_dotdesktop_get(theme, "PanelMsgBgCol"))
+ util_xcol_from_spec(panel, panel->msg_col,
+ mb_dotdesktop_get(theme, "PanelMsgBgCol"));
+ else
+ util_xcol_from_spec(panel, panel->msg_col,
+ DEFAULT_MSG_BGCOL);
+
+
+
+
+ if (mb_dotdesktop_get(theme, "PanelMsgBgUrgentCol"))
+ util_xcol_from_spec(panel, panel->msg_urgent_col,
+ mb_dotdesktop_get(theme,
+ "PanelMsgBgUrgentCol"));
+ else
+ util_xcol_from_spec(panel, panel->msg_urgent_col,
+ DEFAULT_MSG_BGURGCOL);
+
+ if (mb_dotdesktop_get(theme, "PanelMsgFgCol"))
+ util_xcol_from_spec(panel, panel->msg_fg_col,
+ mb_dotdesktop_get(theme,
+ "PanelMsgFgCol"));
+ else
+ util_xcol_from_spec(panel, panel->msg_fg_col,
+ DEFAULT_MSG_FGCOL);
+ mb_dotdesktop_free(theme);
+
+ }
+ }
+
+ if (value) XFree(value);
+
+ status = XGetWindowProperty(panel->dpy, panel->win_root,
+ panel->atoms[ATOM_MB_THEME_NAME],
+ 0L, 512L, False,
+ AnyPropertyType, &realType,
+ &format, &n, &extra,
+ (unsigned char **) &value);
+
+ if (status && value)
+ {
+ if (panel->theme_name) free(panel->theme_name);
+ panel->theme_name = strdup(value);
+ }
+
+ if (value) XFree(value);
+
+ /* Now retheme the panel menu */
+ panel_menu_init(panel);
+
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+ while( papp != NULL )
+ {
+ panel_menu_update_remove_items(panel);
+ papp = papp->next;
+ }
+ i++;
+ }
+
+ return True;
+ }
+ return False;
+}
+
+void
+panel_usage(char *bin_name)
+{
+ fprintf(stderr, "%s usage: %s [Options...]\n"
+ "Where options are;\n"
+ "-display, -d <X11 Display name>\n"
+ "-geometry, -g Use --size / --orientation instead.\n"
+ "--id <int> Panel ID\n"
+ "--size, -s <int> width/height of dock in pixels\n"
+ "--orientation <north|east|south|west>\n"
+ "--default-apps, -da <app list> comma seperated list of apps to\n"
+ " add to a tray when no session exists\n"
+ "--margin-start <+int> initial app offset in pixels (panel start)\n"
+ "--margin-end <+int> initial app offset in pixels (panel end)\n"
+ "--titlebar Request panel in titlebar - see docs for limitations\n"
+ "--no-session, -ns No session saving.\n"
+ "--no-menu, -nm No popup menu\n"
+ "--no-flip, -nf On a display rotation, stop the panel from\n"
+ " From rotating itself too\n"
+ "--overide-bubbles, -o\n\n"
+ "Background options:\n"
+ "--bgcolor, -c <color spec>\n"
+ "--bgpixmap, -b <image file>\n"
+ "--bgtrans, -bt <'yes'|transparency percentage>\n"
+ "*NOTE* setting the background here will disable the effect\n"
+ " of any external theme changes. \n"
+ , bin_name, bin_name);
+ exit(1);
+}
+
+/* XEMBED */
+
+int
+panel_get_map_state(MBPanel *d, MBPanelApp *c)
+{
+ Atom realType;
+ unsigned long n;
+ unsigned long extra;
+ int format;
+ int status;
+ CARD32 * value = NULL;
+ int result = -1;
+
+ status = XGetWindowProperty(d->dpy, c->win,
+ d->atoms[ATOM_XEMBED_INFO],
+ 0L, 10L,
+ 0, XA_ATOM, &realType, &format,
+ &n, &extra, (unsigned char **) &value);
+ if (status == Success)
+ {
+ if (realType == XA_CARDINAL && format == 32)
+ {
+ /*
+ printf("VERSION: %i\n", value[0]);
+ printf("MAPPED: %i\n", value[1]);
+ */
+
+ result = (int)value[1];
+
+ }
+ }
+
+ if (value) XFree(value);
+
+ return result;
+}
+
+void panel_send_xembed_message(
+ MBPanel *d,
+ MBPanelApp *c,
+ long message, /* message opcode */
+ long detail, /* message detail */
+ long data1, /* message data 1 */
+ long data2 /* message data 2 */
+ ){
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = c->win;
+ ev.xclient.message_type = d->atoms[ATOM_XEMBED_MESSAGE];
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = CurrentTime;
+ ev.xclient.data.l[1] = message;
+ ev.xclient.data.l[2] = detail;
+ ev.xclient.data.l[3] = data1;
+ ev.xclient.data.l[4] = data2;
+ XSendEvent(d->dpy, c->win, False, NoEventMask, &ev);
+ XSync(d->dpy, False);
+}
+
+void panel_send_manage_message( MBPanel *d )
+{
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = d->win_root;
+ ev.xclient.message_type = d->atoms[ATOM_MANAGER];
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = CurrentTime;
+ ev.xclient.data.l[1] = d->atoms[ATOM_SYSTEM_TRAY];
+ ev.xclient.data.l[2] = d->win;
+
+ XSendEvent(d->dpy, d->win_root, False, StructureNotifyMask, &ev);
+ XSync(d->dpy, False);
+}
+
+
+
+/* Events */
+
+void
+panel_handle_button_event(MBPanel *panel, XButtonEvent *e)
+{
+ XEvent ev;
+ int done = 0;
+ struct timeval then, now;
+
+ DBG("%s() called, subwindow : %li\n", __func__, e->subwindow );
+
+ if (!panel->use_menu) return; /* menu disabled */
+
+ if (e->window != panel->win) return;
+
+ if (panel->is_hidden)
+ {
+ panel_toggle_visibilty(panel);
+ return;
+ }
+
+ gettimeofday(&then, NULL);
+ while (!done) {
+ if (XCheckMaskEvent(panel->dpy,ButtonReleaseMask, &ev))
+ if (ev.type == ButtonRelease) done=1;
+ gettimeofday(&now, NULL);
+ if ( (now.tv_usec-then.tv_usec) > (panel->click_time*1000) )
+ done=2;
+ }
+
+ if (done == 2 && !mb_menu_is_active(panel->mbmenu))
+ {
+ int dpy_h = DisplayHeight(panel->dpy, panel->screen);
+ util_get_mouse_position(panel, &panel->click_x, &panel->click_y);
+ mb_menu_activate(panel->mbmenu,
+ (panel->click_x-5 < 0) ? 2 : panel->click_x-5,
+ (panel->click_y+5 > dpy_h) ? dpy_h-2 : panel->click_y+5);
+ }
+}
+
+void
+panel_handle_expose(MBPanel *panel, XExposeEvent *e)
+{
+ ;
+}
+
+void
+panel_handle_dock_request(MBPanel *panel, Window win)
+{
+ int app_origin_dist = 0;
+ char *cmd_str = NULL;
+ MBPanelApp *new_papp = NULL;
+
+ util_get_command_str_from_win(panel, win, &cmd_str); /* cmd_str freed l8r */
+
+ if (session_preexisting_win_matches_wanted(panel, win, cmd_str))
+ {
+ app_origin_dist = panel->session_init_offset;
+ session_preexisting_clear_current(panel);
+ }
+
+ new_papp = panel_app_new(panel, win, cmd_str);
+
+ if (new_papp)
+ {
+ XSelectInput(panel->dpy, new_papp->win, PropertyChangeMask );
+
+ /* tell app its docked - panel app should now map its self */
+ panel_send_xembed_message(panel, new_papp,
+ XEMBED_EMBEDDED_NOTIFY,
+ 0, panel->win, 0);
+
+ /* sent when it gets focus */
+ panel_send_xembed_message(panel, new_papp,
+ XEMBED_WINDOW_ACTIVATE,
+ 0,0,0);
+
+ XMapWindow(panel->dpy, new_papp->win);
+ new_papp->mapped = True;
+
+ panel_menu_update_remove_items(panel);
+ }
+
+ session_save(panel);
+
+ session_preexisting_start_next(panel);
+}
+
+void
+panel_handle_client_message(MBPanel *panel, XClientMessageEvent *e)
+{
+ DBG("%s() called\n", __func__ );
+ if (e->message_type
+ == panel->atoms[ATOM_SYSTEM_TRAY_OPCODE])
+ {
+ DBG("%s() got system tray message\n", __func__ );
+ switch (e->data.l[1])
+ {
+ case SYSTEM_TRAY_REQUEST_DOCK:
+ DBG("%s() is SYSTEM_TRAY_REQUEST_DOCK\n", __func__ );
+ panel_handle_dock_request(panel, e->data.l[2]);
+ break;
+ case SYSTEM_TRAY_BEGIN_MESSAGE:
+ DBG("%s() is SYSTEM_TRAY_BEGIN_MESSAGE\n", __func__ );
+ msg_new(panel, e);
+ break;
+ case SYSTEM_TRAY_CANCEL_MESSAGE:
+ DBG("%s() is SYSTEM_TRAY_CANCEL_MESSAGE\n", __func__ );
+ break;
+ }
+ return;
+ }
+
+ if (e->message_type
+ == panel->atoms[ATOM_MB_COMMAND])
+ {
+ switch (e->data.l[0])
+ {
+ case MB_CMD_PANEL_TOGGLE_VISIBILITY:
+ panel_toggle_visibilty(panel);
+ break;
+ case MB_CMD_PANEL_SIZE:
+ case MB_CMD_PANEL_ORIENTATION:
+ default:
+ break;
+ }
+
+ }
+
+ if (e->message_type
+ == panel->atoms[ATOM_NET_SYSTEM_TRAY_MESSAGE_DATA])
+ {
+ DBG("%s() got system tray message _data_\n", __func__ );
+ msg_add_data(panel, e);
+ return;
+ }
+
+ if (e->message_type
+ == panel->atoms[ATOM_WM_DELETE_WINDOW])
+ {
+ util_cleanup_children(0);
+ }
+
+ return;
+}
+
+void
+panel_handle_property_notify(MBPanel *panel, XPropertyEvent *e)
+{
+ MBPanelApp *papp;
+
+ if (e->atom == panel->atoms[ATOM_XEMBED_INFO])
+ {
+ int i;
+ papp = panel_app_get_from_window(panel, e->window);
+ DBG("%s() got XEMBED_INFO property notify for %s\n",
+ __func__, papp->name );
+ if (papp != NULL)
+ {
+ i = panel_get_map_state(panel, papp);
+ if (i == 1)
+ {
+ XMapRaised(panel->dpy, papp->win);
+ papp->mapped = True;
+ }
+ if (i == 0)
+ {
+ XUnmapWindow(panel->dpy, papp->win);
+ papp->mapped = False;
+ }
+ }
+ return;
+ }
+
+ if (e->atom == panel->atoms[ATOM_MB_THEME])
+ {
+ panel_set_theme_from_root_prop(panel);
+ return;
+ }
+
+ if (e->atom == panel->atoms[ATOM_XROOTPMAP_ID]
+ && panel->root_pixmap_id != 0)
+ {
+ panel_set_bg(panel, BG_TRANS, panel->bg_trans);
+ return;
+ }
+
+ if (e->atom == panel->atoms[ATOM_MB_REQ_CLIENT_ORDER])
+ {
+ panel_reorder_apps(panel);
+ }
+}
+
+static Bool
+get_xevent_timed(Display* dpy, XEvent* event_return, struct timeval *tv)
+{
+ if (tv == NULL)
+ {
+ XNextEvent(dpy, event_return);
+ return True;
+ }
+
+ XFlush(dpy);
+
+ if (XPending(dpy) == 0)
+ {
+ int fd = ConnectionNumber(dpy);
+ fd_set readset;
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+ if (select(fd+1, &readset, NULL, NULL, tv) == 0)
+ {
+ return False;
+ } else {
+ XNextEvent(dpy, event_return);
+ return True;
+ }
+ } else {
+ XNextEvent(dpy, event_return);
+ return True;
+ }
+}
+
+void
+panel_main(MBPanel *panel)
+{
+ MBPanelApp *papp;
+ XEvent an_event;
+ int xfd;
+ Bool had_rotation = False;
+
+ XSelectInput (panel->dpy, panel->win, StructureNotifyMask|ExposureMask|
+ SubstructureRedirectMask|SubstructureNotifyMask|
+ ButtonPressMask|ButtonReleaseMask|PointerMotionMask|
+ PropertyChangeMask);
+
+ XSelectInput (panel->dpy, panel->win_root,
+ PropertyChangeMask|StructureNotifyMask);
+
+ xfd = ConnectionNumber (panel->dpy);
+
+ XFlush(panel->dpy);
+
+ while(1)
+ {
+ struct timeval tvt;
+ tvt.tv_usec = 500;
+ tvt.tv_sec = 0;
+
+ if (get_xevent_timed(panel->dpy, &an_event, &tvt))
+ {
+#ifdef USE_XSETTINGS
+ if (panel->xsettings_client != NULL)
+ xsettings_client_process_event(panel->xsettings_client, &an_event);
+#endif
+ mb_menu_handle_xevent(panel->mbmenu, &an_event);
+ switch (an_event.type)
+ {
+ case ButtonPress:
+ panel_handle_button_event(panel, &an_event.xbutton);
+ break;
+ case ClientMessage:
+ panel_handle_client_message(panel, &an_event.xclient);
+ break;
+ case PropertyNotify:
+ panel_handle_property_notify(panel, &an_event.xproperty);
+ break;
+ case MapRequest:
+ break;
+ case UnmapNotify:
+ /* window should unmap ... we destroy it */
+ papp = panel_app_get_from_window(panel,
+ an_event.xunmap.window);
+ if (papp && !papp->ignore_unmap)
+ {
+ panel_app_destroy(panel, papp);
+
+ /* remove any connected message windows */
+ if (panel->msg_win && panel->msg_win_sender == papp)
+ {
+ XDestroyWindow(panel->dpy, panel->msg_win);
+ panel->msg_win = None;
+ }
+
+ /*
+ * We set an alarm here, so the session file is only
+ * updated after a couple fo seconds.
+ * This is done so if the xserver is closing and bringing
+ * down all the clients. Its very likely it'll kill
+ * a panelapp before the panel, and we dont really want it
+ * to be refmoved from the session file.
+ */
+ alarm(3);
+ }
+ break;
+ case Expose:
+ panel_handle_expose(panel, &an_event.xexpose);
+ break;
+ case DestroyNotify:
+ break;
+ case ConfigureRequest:
+ panel_app_handle_configure_request(panel,
+ &an_event.xconfigurerequest);
+ break;
+ case ConfigureNotify:
+ if (an_event.xconfigure.window == panel->win_root)
+ {
+ had_rotation = True;
+ DBG("%s() **** HAD ROTATION ***\n", __func__);
+ break;
+ }
+
+ if (an_event.xconfigure.window == panel->win)
+ {
+ DBG("%s(): configureNotify on panel\n", __func__);
+ /* These can be confused by a flip */
+ if (an_event.xconfigure.send_event)
+ break;
+
+ if (panel->w != an_event.xconfigure.width
+ || panel->h != an_event.xconfigure.height)
+ {
+ int diff = 0;
+ MBPanelApp *papp = NULL;
+
+ if (panel->ignore_next_config)
+ {
+ panel->ignore_next_config = False;
+ break;
+ }
+
+ if (panel->use_flip && had_rotation)
+ {
+ /* Flip if are length is changed
+ XXX a little hacky XXXX
+ */
+ int dpy_w, dpy_h;
+ XWindowAttributes root_attr;
+
+ XGetWindowAttributes(panel->dpy,
+ panel->win_root,
+ &root_attr);
+
+ dpy_w = root_attr.width;
+ dpy_h = root_attr.height;
+
+ had_rotation = False;
+
+ if ((PANEL_IS_VERTICAL(panel)
+ && (an_event.xconfigure.width == panel->w)
+ )
+ ||
+ (!PANEL_IS_VERTICAL(panel)
+ && (an_event.xconfigure.height == panel->h)
+ /* && (an_event.xconfigure.width == dpy_w)
+ && dpy_w != panel->w */ )
+ )
+ {
+
+ DBG("%s() flipping ....\n", __func__);
+
+ panel->ignore_next_config = True;
+
+ switch (panel->orientation)
+ {
+ case South:
+ panel_change_orientation(panel, East,
+ dpy_w, dpy_h);
+ break;
+ case North:
+ panel_change_orientation(panel, West,
+ dpy_w, dpy_h);
+ break;
+ case West:
+ panel_change_orientation(panel, North,
+ dpy_w, dpy_h);
+ break;
+ case East:
+ panel_change_orientation(panel, South,
+ dpy_w, dpy_h);
+ break;
+ }
+ break;
+ }
+ }
+
+ if (PANEL_IS_VERTICAL(panel))
+ {
+ diff = an_event.xconfigure.height - panel->h;
+ if (an_event.xconfigure.y > panel->y)
+ papp = panel->apps_start_head;
+ else
+ papp = panel->apps_end_head;
+ } else {
+ diff = an_event.xconfigure.width - panel->w;
+ if (an_event.xconfigure.x > panel->x)
+ papp = panel->apps_start_head;
+ else
+ papp = panel->apps_end_head;
+ }
+
+ panel->w = an_event.xconfigure.width;
+ panel->h = an_event.xconfigure.height;
+
+ panel_apps_nudge (panel, papp, diff);
+
+ /* Nake sure bg gets updated */
+ if (!(panel->use_flip && had_rotation))
+ {
+ char *tmp_str = NULL;
+ if (panel->bg_spec)
+ tmp_str = strdup(panel->bg_spec) ;
+ panel_set_bg(panel, panel->bg_type, tmp_str);
+ if (tmp_str) free(tmp_str);
+ }
+
+ // panel_apps_rescale (panel, panel->apps_start_head);
+ // panel_apps_rescale (panel, panel->apps_end_head);
+ }
+
+ panel->x = an_event.xconfigure.x;
+ panel->y = an_event.xconfigure.y;
+
+ DBG("%s() config notify, got x: %i , y: %i w: %i h: %i \n",
+ __func__,
+ an_event.xconfigure.x,
+ an_event.xconfigure.y,
+ an_event.xconfigure.width,
+ an_event.xconfigure.height);
+
+ DBG("%s() panel is now x: %i , y: %i w: %i h: %i \n",
+ __func__, panel->x, panel->y,
+ panel->w, panel->h );
+ }
+ break;
+ }
+ msg_handle_events(panel, &an_event);
+ }
+ session_preexisting_handle_timeouts(panel);
+ msg_handle_timeouts(panel);
+ }
+}
+
+static void
+panel_orientation_set_hint (MBPanel *panel)
+{
+ int is_vertical[1] = { 0 };
+
+ if (PANEL_IS_VERTICAL(panel)) is_vertical[0] = 1;
+
+ XChangeProperty(panel->dpy, panel->win,
+ panel->atoms[ATOM_NET_SYSTEM_TRAY_ORIENTATION],
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *)is_vertical , 1);
+}
+
+
+void
+panel_change_orientation(MBPanel *panel,
+ MBPanelOrientation new_orientation,
+ int dpy_w, int dpy_h)
+{
+ char *tmp_str = NULL;
+
+ XUnmapWindow(panel->dpy, panel->win);
+
+ if ( ( (panel->orientation == East || panel->orientation == West)
+ && (new_orientation == North || new_orientation == South) )
+ ||
+ ( (panel->orientation == North || panel->orientation == South)
+ && (new_orientation == East || new_orientation == West ) )
+ )
+ {
+ MBPanelApp *papp_heads[] = { panel->apps_start_head,
+ panel->apps_end_head,
+ NULL };
+ MBPanelApp *papp_cur = NULL;
+ int i = 0;
+
+ panel->x = 0;
+ panel->y = 0;
+ panel->h = panel->default_panel_size;
+ panel->w = dpy_w;
+
+ switch (new_orientation)
+ {
+ case South:
+ panel->y = dpy_h - panel->h;
+ break;
+ case North:
+ break;
+ case West:
+ panel->w = panel->default_panel_size;
+ panel->h = dpy_h;
+ break;
+ case East:
+ panel->w = panel->default_panel_size;
+ panel->h = dpy_h;
+ panel->x = dpy_w - panel->w;
+ break;
+ }
+
+ panel->orientation = new_orientation;
+
+ panel_orientation_set_hint(panel);
+
+ DBG("%s() setting panel x: %i , y: %i w: %i h: %i \n",
+ __func__, panel->x, panel->y,
+ panel->w, panel->h );
+
+ XMoveResizeWindow( panel->dpy, panel->win, panel->x, panel->y,
+ panel->w, panel->h );
+
+ /* move_to() will reposition each app */
+ while (i < 2)
+ {
+ papp_cur = papp_heads[i];
+ DBG("%s() moveing to, cur is i: %i ( %p )\n",
+ __func__, i, papp_cur);
+
+ while (papp_cur != NULL)
+ {
+ int tmp;
+ tmp = papp_cur->w;
+ papp_cur->w = papp_cur->h;
+ papp_cur->h = tmp;
+
+ if (panel->orientation == North || panel->orientation == South)
+ {
+ papp_cur->x = papp_cur->offset;
+ papp_cur->y = (panel->h - papp_cur->h) / 2;
+ }
+ else
+ {
+ papp_cur->y = papp_cur->offset;
+ papp_cur->x = (panel->w - papp_cur->w) / 2;
+ }
+
+ XMoveWindow(panel->dpy, papp_cur->win,
+ papp_cur->x, papp_cur->y);
+
+ panel_app_deliver_config_event(panel, papp_cur);
+ papp_cur = papp_cur->next;
+ }
+ i++;
+ }
+ }
+ else
+ {
+ switch (new_orientation)
+ {
+ case South:
+ panel->y = dpy_h - panel->h;
+ break;
+ case North:
+ panel->y = 0;
+ break;
+ case West:
+ panel->x = 0;
+ break;
+ case East:
+ panel->x = dpy_w - panel->w;
+ break;
+ }
+
+ panel->orientation = new_orientation;
+
+ panel_orientation_set_hint(panel);
+
+ XMoveResizeWindow( panel->dpy, panel->win, panel->x, panel->y,
+ panel->w, panel->h );
+ }
+
+ if (panel->bg_spec) tmp_str = strdup(panel->bg_spec) ;
+ panel_set_bg(panel, panel->bg_type, tmp_str);
+ if (tmp_str) free(tmp_str);
+
+ XMapWindow(panel->dpy, panel->win);
+ XMapSubwindows(panel->dpy, panel->win);
+
+}
+
+
+
+void
+panel_reorder_apps(MBPanel *panel)
+{
+ MBPanelApp *papp, *papp_tmp;
+ int i, watermark = 0, offset = 0;
+
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after = 0;
+ unsigned char *prop = NULL;
+ int n_wins;
+ Window *wins;
+
+ if (XGetWindowProperty (panel->dpy, panel->win,
+ panel->atoms[ATOM_MB_REQ_CLIENT_ORDER],
+ 0, 1000L, False, XA_WINDOW,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop) != Success)
+ return;
+
+ wins = (Window *)prop;
+ n_wins = (int)nitems;
+
+ papp = panel->apps_start_head;
+
+ while( papp != NULL)
+ {
+ watermark++;
+ papp = papp->next;
+ }
+
+ DBG("%s() watermark is %i\n", __func__, watermark);
+
+ for (i =0; i<n_wins; i++)
+ {
+ papp = panel_app_get_from_window(panel, wins[i]);
+
+ if (papp)
+ {
+ MBPanelApp *found_head = NULL;
+ /* find where it currently is */
+ papp_tmp = panel->apps_start_head;
+
+ DBG("%s() %i looping for %s\n", __func__, i, papp->name);
+
+ while( papp_tmp != NULL)
+ {
+ if (papp == papp_tmp)
+ {
+ found_head = panel->apps_start_head;
+ break;
+ }
+
+ papp_tmp = papp_tmp->next;
+ }
+
+ if (!found_head)
+ {
+ papp_tmp = panel->apps_end_head;
+
+ while( papp_tmp != NULL)
+ {
+ if (papp == papp_tmp)
+ {
+ found_head = panel->apps_end_head;
+ break;
+ }
+
+ papp_tmp = papp_tmp->next;
+ }
+ }
+
+ if (found_head)
+ {
+ if (found_head == panel->apps_start_head)
+ {
+ DBG("%s() %i found head is start\n", __func__, i );
+ panel_app_list_remove (panel, papp, &panel->apps_start_head);
+ }
+ else
+ {
+ DBG("%s() %i found head is end\n", __func__, i );
+ panel_app_list_remove (panel, papp, &panel->apps_end_head);
+
+ }
+
+ papp->next = NULL;
+
+ if (!watermark || (watermark && i >= watermark))
+ {
+ DBG("%s() %i prepending at end\n", __func__, i );
+
+ /*
+ if (found_head != panel->apps_end_head) switched lists
+ panel_app_list_append(panel, &panel->apps_end_head, papp);
+ else
+ */
+ panel->apps_end_head = panel_app_list_prepend(panel, panel->apps_end_head, papp);
+ papp->gravity = PAPP_GRAVITY_END;
+ //panel_app_add_end(panel, papp);
+ }
+ else
+ {
+ DBG("%s() %i appending at start\n", __func__, i );
+ panel_app_list_append(panel, &panel->apps_start_head, papp);
+ //panel_app_add_start(panel, papp);
+ papp->gravity = PAPP_GRAVITY_START;
+ }
+
+
+ }
+ else DBG("%s() %i not found head !!!!\n", __func__, i );
+ }
+ }
+
+ papp = panel->apps_start_head;
+
+ offset = panel->margin_start;
+
+ DBG("%s() start list:\n", __func__ );
+
+ while( papp != NULL)
+ {
+
+ DBG("%s() %s moving to %i\n", __func__, papp->name, offset );
+
+ if (PANEL_IS_VERTICAL(panel))
+ papp->y = offset;
+ else
+ papp->x = offset;
+
+ papp->offset = offset;
+
+ XMoveWindow(panel->dpy, papp->win, papp->x, papp->y);
+
+ panel_app_deliver_config_event(panel, papp);
+
+ offset += ( panel_app_get_size(panel, papp) + panel->padding );
+
+ papp = papp->next;
+ }
+
+ papp = panel->apps_end_head;
+
+ DBG("%s() end list:\n", __func__ );
+
+ if (papp)
+ {
+ offset = ( PANEL_IS_VERTICAL(panel) ? panel->h : panel->w ) - panel->margin_end;
+
+ while( papp != NULL)
+ {
+ offset -= ( panel_app_get_size(panel, papp) + panel->padding );
+
+ DBG("%s() %s moving to %i\n", __func__, papp->name, offset );
+
+ if (PANEL_IS_VERTICAL(panel))
+ papp->y = offset;
+ else
+ papp->x = offset;
+
+ papp->offset = offset;
+
+ XMoveWindow(panel->dpy, papp->win, papp->x, papp->y);
+
+ panel_app_deliver_config_event(panel, papp);
+
+ papp = papp->next;
+ }
+ }
+
+ session_save(panel);
+ panel_menu_update_remove_items(panel);
+ panel_update_client_list_prop(panel);
+
+}
+
+MBPanel
+*panel_init(int argc, char *argv[])
+{
+ int panel_length;
+ XGCValues gv;
+ XSetWindowAttributes dattr;
+ unsigned long dattr_flags = CWBackPixel;
+ XSizeHints size_hints;
+
+ unsigned long wm_struct_vals[4];
+
+ char *geometry_str = NULL;
+ char *color_def = NULL;
+ char *bg_pixmap_def = NULL;
+ char *display_name = (char *)getenv("DISPLAY");
+
+ char tray_atom_spec[128] = { 0 };
+ char tray_id_env_str[16] = { 0 };
+
+ /* MBPanelApp *papp_menu_button = NULL; */
+ MBPanel *panel;
+
+ int panel_border_sz = 0;
+ char *want_trans = NULL;
+
+ char win_name[64] = { 0 };
+ /*
+#ifdef USE_XFT
+ XRenderColor colortmp;
+#endif
+ */
+
+ int i = 0, j = 0;
+
+ struct {
+ char *name;
+ MBPanelOrientation orientation;
+ } orientation_lookup[] = {
+ { "north", North },
+ { "south", South },
+ { "east", East },
+ { "west", West },
+ { NULL, North }
+ };
+
+ XSetErrorHandler(util_handle_xerror);
+
+ panel = NEW(MBPanel);
+ memset(panel, sizeof(MBPanel), 0);
+
+ /* defualts */
+
+ panel->padding = 2;
+ panel->use_session = True;
+ panel->use_alt_session_defaults = False;
+ panel->use_menu = True;
+ panel->click_time = 400;
+ panel->use_overide_wins = False;
+ panel->orientation = South;
+ panel->system_tray_id = 0;
+ panel->use_flip = True;
+ panel->default_panel_size = 0;
+ panel->session_cur_gravity = PAPP_GRAVITY_START;
+ panel->theme_name = NULL;
+ panel->theme_path = NULL;
+ panel->apps_start_head = NULL;
+ panel->apps_end_head = NULL;
+ panel->ignore_next_config = False;
+ panel->margin_start = 2;
+ panel->margin_end = 2;
+ panel->bg_spec = NULL;
+ panel->want_titlebar_dest = False;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ display_name = argv[i];
+ continue;
+ }
+ if (!strcmp ("--no-session", argv[i]) || !strcmp ("-ns", argv[i])) {
+ panel->use_session = False;
+ continue;
+ }
+ if (!strcmp ("--titlebar", argv[i]) || !strcmp ("-tb", argv[i])) {
+ panel->want_titlebar_dest = True;
+ continue;
+ }
+
+ if (!strcmp ("--default-apps", argv[i]) || !strcmp ("-da", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ if (!strcmp(argv[i], "none"))
+ session_set_defaults(panel, strdup(""));
+ else
+ session_set_defaults(panel, argv[i]);
+ continue;
+ }
+
+ if (!strcmp ("--no-menu", argv[i]) || !strcmp ("-nm", argv[i])) {
+ panel->use_menu = False;
+ continue;
+ }
+ if (!strcmp ("--overide-bubbles", argv[i]) || !strcmp ("-o", argv[i])) {
+ panel->use_overide_wins = True;
+ continue;
+ }
+ if (!strcmp ("--no-flip", argv[i])) {
+ panel->use_flip = False;
+ continue;
+ }
+ if (!strcmp ("--bgcolor", argv[i]) || !strcmp ("-c", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ color_def = argv[i];
+ continue;
+ }
+ if (strstr (argv[i], "-geometry") || !strcmp ("-g", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ fprintf(stderr,"mbdock: -geometry is depreciated, please consider --size and --orientation instead\n");
+ geometry_str = argv[i];
+ continue;
+ }
+ if (strstr (argv[i], "--size") || !strcmp ("-s", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ panel->default_panel_size = atoi(argv[i]);
+ if (panel->default_panel_size < 1) panel_usage (argv[0]);
+ continue;
+ }
+ if (strstr (argv[i], "--margin-start")) {
+ if (++i>=argc) panel_usage (argv[0]);
+ panel->margin_start = atoi(argv[i]);
+ if (panel->margin_start < 1) panel_usage (argv[0]);
+ continue;
+ }
+ if (strstr (argv[i], "--margin-end")) {
+ if (++i>=argc) panel_usage (argv[0]);
+ panel->margin_end = atoi(argv[i]);
+ if (panel->margin_end < 1) panel_usage (argv[0]);
+ continue;
+ }
+ if (!strcmp ("--bgpixmap", argv[i]) || !strcmp ("-b", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ bg_pixmap_def = argv[i];
+ continue;
+ }
+ if (!strcmp ("--bgtrans", argv[i]) || !strcmp ("-bt", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ want_trans = argv[i];
+ continue;
+ }
+ if (!strcmp ("--id", argv[i]) || !strcmp ("-i", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ panel->system_tray_id = atoi(argv[i]);
+ continue;
+
+ }
+ if (!strcmp ("--border", argv[i])) {
+ if (++i>=argc) panel_usage (argv[0]);
+ panel_border_sz = atoi(argv[i]);
+ continue;
+ }
+ if (!strcmp ("--orientation", argv[i])) {
+ Bool found = False;
+ if (++i>=argc) panel_usage (argv[0]);
+ j = 0;
+ while (orientation_lookup[j].name != NULL)
+ {
+ if (!strcasecmp(orientation_lookup[j].name, argv[i]))
+ {
+ panel->orientation = orientation_lookup[j].orientation;
+ found = True;
+ }
+ j++;
+ }
+ if (found) continue;
+ }
+ panel_usage(argv[0]);
+ }
+
+ if ((panel->dpy = XOpenDisplay(display_name)) == NULL)
+ {
+ fprintf(stderr, "%s: failed to open display", argv[0]);
+ exit(1);
+ }
+
+ panel->screen = DefaultScreen(panel->dpy);
+ panel->win_root = RootWindow(panel->dpy, panel->screen);
+
+ if (panel->default_panel_size == 0)
+ panel->default_panel_size
+ = ( DisplayHeight(panel->dpy, panel->screen) > 320 ) ? 36 : 20;
+
+ panel->x = 0;
+ panel->y = 0;
+ panel->h = panel->default_panel_size;
+ panel->w = DisplayWidth(panel->dpy, panel->screen);
+
+ switch (panel->orientation)
+ {
+ case South:
+ panel->y = DisplayHeight(panel->dpy, panel->screen) - panel->h;
+ break;
+ case North:
+ break;
+ case West:
+ panel->w = panel->default_panel_size;
+ panel->h = DisplayHeight(panel->dpy, panel->screen);
+ break;
+ case East:
+ panel->w = panel->default_panel_size;
+ panel->h = DisplayHeight(panel->dpy, panel->screen);
+ panel->x = DisplayWidth(panel->dpy, panel->screen) - panel->w;
+ break;
+ }
+
+ panel->bg_pxm = None;
+
+ if ( PANEL_IS_VERTICAL(panel) )
+ panel_length = panel->h;
+ else
+ panel_length = panel->w;
+
+ /* Clip margin values to 40% */
+ if (panel->margin_start > ( ( panel_length * 40 ) / 100 )
+ || panel->margin_end > ( ( panel_length * 40 ) / 100 ))
+ {
+ fprintf(stderr, "mbdock: Panel margins too large. clipping.\n");
+ panel->margin_start = 2;
+ panel->margin_end = 2;
+ }
+
+ if (geometry_str)
+ XParseGeometry(geometry_str, &panel->x, &panel->y, &panel->w, &panel->h);
+
+ /* XXX
+ * Lots of atoms now, move to xinternatoms call ...
+ */
+ panel->atoms[0] = XInternAtom(panel->dpy, "_NET_WM_WINDOW_TYPE" ,False);
+
+ panel->atoms[1] = XInternAtom(panel->dpy, "_NET_WM_WINDOW_TYPE_DOCK",False);
+
+
+ panel->atoms[3] = XInternAtom(panel->dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
+ panel->atoms[4] = XInternAtom(panel->dpy, "_XEMBED_INFO", False);
+ panel->atoms[5] = XInternAtom(panel->dpy, "_XEMBED", False);
+ panel->atoms[6] = XInternAtom(panel->dpy, "MANAGER", False);
+
+ panel->atoms[7] = XInternAtom(panel->dpy, "_MB_DOCK_ALIGN", False);
+ panel->atoms[8] = XInternAtom(panel->dpy, "_MB_DOCK_ALIGN_EAST", False);
+
+ panel->atoms[9] = XInternAtom(panel->dpy, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+ panel->atoms[10] = XInternAtom(panel->dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
+
+ panel->atoms[11] = XInternAtom(panel->dpy, "WM_PROTOCOLS", False);
+ panel->atoms[12] = XInternAtom(panel->dpy, "WM_DELETE_WINDOW", False);
+
+ panel->atoms[13] = XInternAtom(panel->dpy, "_MB_THEME", False);
+
+ panel->atoms[14] = XInternAtom(panel->dpy, "_MB_PANEL_TIMESTAMP", False);
+
+ panel->atoms[15] = XInternAtom(panel->dpy, "_NET_WM_STRUT", False);
+
+ panel->atoms[16] = XInternAtom(panel->dpy, "_MB_PANEL_BG", False);
+
+ panel->atoms[17] = XInternAtom(panel->dpy, "WM_CLIENT_LEADER", False);
+
+ panel->atoms[18] = XInternAtom(panel->dpy, "_NET_WM_ICON", False);
+
+ panel->atoms[ATOM_NET_WM_PID]
+ = XInternAtom(panel->dpy, "_NET_WM_PID", False);
+
+ panel->atoms[ATOM_XROOTPMAP_ID]
+ = XInternAtom(panel->dpy, "_XROOTPMAP_ID", False);
+
+ panel->atoms[ATOM_NET_SYSTEM_TRAY_ORIENTATION]
+ = XInternAtom(panel->dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
+
+ panel->atoms[ATOM_MB_THEME_NAME]
+ = XInternAtom(panel->dpy, "_MB_THEME_NAME", False);
+
+ panel->atoms[ATOM_MB_COMMAND]
+ = XInternAtom(panel->dpy, "_MB_COMMAND", False);
+
+ panel->atoms[ATOM_NET_WM_NAME]
+ = XInternAtom(panel->dpy, "_NET_WM_NAME", False);
+
+ panel->atoms[ATOM_UTF8_STRING]
+ = XInternAtom(panel->dpy, "UTF8_STRING", False);
+
+ panel->atoms[ATOM_NET_CLIENT_LIST]
+ = XInternAtom(panel->dpy, "_NET_CLIENT_LIST", False);
+
+ panel->atoms[ATOM_NET_WM_STATE]
+ = XInternAtom(panel->dpy, "_NET_WM_STATE", False);
+
+ panel->atoms[ATOM_NET_WM_STATE_TITLEBAR]
+ = XInternAtom(panel->dpy, "_MB_WM_STATE_DOCK_TITLEBAR", False);
+
+ panel->atoms[ATOM_MB_SYSTEM_TRAY_CONTEXT]
+ = XInternAtom(panel->dpy, "_MB_SYSTEM_TRAY_CONTEXT", False);
+
+ panel->atoms[ATOM_MB_REQ_CLIENT_ORDER]
+ = XInternAtom(panel->dpy, "_MB_REQ_CLIENT_ORDER", False);
+
+
+ /* Set selection atom */
+ snprintf(tray_atom_spec, 128,"_NET_SYSTEM_TRAY_S%i", panel->system_tray_id);
+
+ panel->atoms[ATOM_SYSTEM_TRAY]
+ = XInternAtom(panel->dpy, tray_atom_spec, False);
+
+ snprintf(tray_id_env_str, 16, "%i", panel->system_tray_id);
+ setenv("SYSTEM_TRAY_ID", tray_id_env_str, 1);
+
+ snprintf(win_name, 64, "Panel %i", panel->system_tray_id);
+
+ panel->pb = mb_pixbuf_new(panel->dpy, panel->screen);
+
+ gv.graphics_exposures = False;
+ gv.function = GXcopy;
+ gv.foreground = WhitePixel(panel->dpy, panel->screen);
+
+ panel->gc = XCreateGC(panel->dpy, panel->win_root,
+ GCGraphicsExposures|GCFunction|GCForeground, &gv);
+
+ dattr.background_pixel = panel->xcol.pixel;
+
+ if (geometry_str)
+ {
+ /* Make the window overide redirect - kind of evil hack for now */
+ dattr_flags = CWBackPixel|CWOverrideRedirect;
+ dattr.override_redirect = True;
+ }
+
+ panel->win = XCreateWindow(panel->dpy, panel->win_root,
+ panel->x, panel->y,
+ panel->w, panel->h,
+ panel_border_sz,
+ CopyFromParent,
+ CopyFromParent,
+ CopyFromParent,
+ dattr_flags,
+ &dattr);
+
+ size_hints.flags = PPosition | PSize | PMinSize;
+ size_hints.x = panel->x;
+ size_hints.y = panel->y;
+ size_hints.width = panel->w;
+ size_hints.height = panel->h;
+ size_hints.min_width = panel->w;
+ size_hints.min_height = panel->h;
+
+ XSetStandardProperties(panel->dpy, panel->win, win_name,
+ win_name, 0, argv, argc, &size_hints);
+
+ /*
+ XXX For now the menu popup button is removed.
+ If goes down well, need to rip old code out.
+
+ panel_menu_button_create(panel);
+
+ */
+
+ XChangeProperty(panel->dpy, panel->win,
+ panel->atoms[ATOM_WM_WINDOW_TYPE], XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *) &panel->atoms[ATOM_WM_WINDOW_TYPE_DOCK],
+ 1);
+
+ if (panel->want_titlebar_dest)
+ {
+ panel->use_flip = False;
+
+ XChangeProperty(panel->dpy, panel->win,
+ panel->atoms[ATOM_NET_WM_STATE], XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *) &panel->atoms[ATOM_NET_WM_STATE_TITLEBAR], 1);
+
+ panel->orientation = North;
+ }
+
+ /* Set our ewmh reserved space XXX reset this when we hide */
+ wm_struct_vals[0] = ( panel->orientation == West ) ? panel->w : 0;
+ wm_struct_vals[1] = ( panel->orientation == East ) ? panel->w : 0;
+ wm_struct_vals[2] = ( panel->orientation == North ) ? panel->h : 0;
+ wm_struct_vals[3] = ( panel->orientation == South ) ? panel->h : 0;
+
+ XChangeProperty(panel->dpy, panel->win, panel->atoms[ATOM_NET_WM_STRUT],
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *)wm_struct_vals, 4);
+
+ panel->msg_queue_start = NULL;
+ panel->msg_queue_end = NULL;
+ panel->msg_win = None;
+
+ panel->msg_col
+ = mb_col_new_from_spec(panel->pb, DEFAULT_MSG_BGCOL);
+ panel->msg_urgent_col
+ = mb_col_new_from_spec(panel->pb, DEFAULT_MSG_BGURGCOL);
+ panel->msg_fg_col
+ = mb_col_new_from_spec(panel->pb, DEFAULT_MSG_FGCOL);
+ panel->msg_link_col
+ = mb_col_new_from_spec(panel->pb, "blue");
+
+ panel->msg_gc = XCreateGC(panel->dpy, panel->win_root,
+ GCGraphicsExposures|GCFunction|GCForeground, &gv);
+
+ panel->msg_font = mb_font_new_from_string(panel->dpy, MB_MSG_FONT);
+
+ panel->next_click_is_not_double = True;
+ panel->is_hidden = False;
+
+ XSetWMProtocols(panel->dpy, panel->win , &panel->atoms[11], 2);
+
+ panel->mbmenu = NULL;
+ panel_menu_init(panel);
+
+ G_panel = panel; /* global for sig handlers :( */
+ panel->reload_pending = False;
+
+ util_install_signal_handlers();
+
+ /* Set the theme etc */
+
+ panel->use_themes = True;
+
+ if (color_def != NULL)
+ {
+ panel_set_bg(panel, BG_SOLID_COLOR, color_def);
+ mb_menu_set_col(panel->mbmenu, MBMENU_SET_BG_COL, color_def);
+ panel->use_themes = False;
+ }
+ else if (bg_pixmap_def)
+ {
+ panel_set_bg(panel, BG_PIXMAP, bg_pixmap_def);
+ panel->use_themes = False;
+ }
+ else if (want_trans)
+ {
+ panel->bg_trans = strdup(want_trans);
+
+ panel_set_bg(panel, BG_TRANS, want_trans );
+ panel->use_themes = False;
+ }
+ else
+ {
+ if (!panel_set_theme_from_root_prop(panel))
+ {
+ panel_set_bg(panel, BG_SOLID_COLOR, DEFAULT_COLOR_SPEC );
+ mb_menu_set_col(panel->mbmenu, MBMENU_SET_BG_COL, DEFAULT_COLOR_SPEC );
+ }
+ }
+
+ panel->click_x = 0;
+ panel->click_y = 0;
+
+#ifdef USE_XSETTINGS
+
+ /* This will trigger callbacks instantly so called last */
+
+ panel->xsettings_client = xsettings_client_new(panel->dpy, panel->screen,
+ panel_xsettings_notify_cb,
+ NULL,
+ (void *)panel );
+#endif
+
+
+ /* Below line is there to get the menu btton on the right side */
+ panel->session_preexisting_lock = True;
+
+ return panel;
+}
+
+int main(int argc, char *argv[])
+{
+ MBPanel *panel;
+
+#if ENABLE_NLS
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, DATADIR "/locale");
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+ textdomain (PACKAGE);
+#endif
+
+ panel = panel_init(argc, argv);
+
+ /* Attempt to own the system tray selection */
+ if (!XGetSelectionOwner(panel->dpy, panel->atoms[ATOM_SYSTEM_TRAY]))
+ {
+ XSetSelectionOwner(panel->dpy, panel->atoms[ATOM_SYSTEM_TRAY],
+ panel->win, CurrentTime);
+ } else {
+ fprintf(stderr, "Panel already exists. aborting. Try running mbdock with the --id switch.\n");
+ exit(0);
+ }
+
+ /* Announce to any clients that are interested that we have it */
+ panel_send_manage_message( panel );
+
+ panel_orientation_set_hint (panel);
+
+ XMapWindow (panel->dpy, panel->win);
+
+ session_init (panel);
+
+ panel_main(panel);
+
+ return 0;
+}
+
diff --git a/src/panel.h b/src/panel.h
new file mode 100644
index 0000000..79da505
--- /dev/null
+++ b/src/panel.h
@@ -0,0 +1,312 @@
+#ifndef _DOCK_H_
+#define _DOCK_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/xpm.h>
+#include <X11/Xmd.h>
+#include <X11/extensions/shape.h>
+#include <X11/cursorfont.h>
+
+#include <libmb/mb.h>
+
+#ifdef USE_XSETTINGS
+#include <xsettings-client.h>
+#endif
+
+#define NEW(OBJ) ((OBJ *)(malloc(sizeof(OBJ))))
+
+#ifdef DEBUG
+#define DBG(txt, args... ) fprintf(stderr, "MB-PANEL-DEBUG: " txt , ##args )
+#else
+#define DBG(txt, args... ) /* nothing */
+#endif
+
+#define SWAP(a,b) { \
+ (a)^=(b); \
+ (b)^=(a); \
+ (a)^=(b); \
+ }
+
+#define PANEL_IS_VERTICAL(p) ((p)->orientation == East || (p)->orientation == West)
+
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+#define ATOM_WM_WINDOW_TYPE 0
+#define ATOM_WM_WINDOW_TYPE_DOCK 1
+#define ATOM_WM_WINDOW_TYPE_SPLASH 10
+#define ATOM_SYSTEM_TRAY 2
+#define ATOM_SYSTEM_TRAY_OPCODE 3
+#define ATOM_XEMBED_INFO 4
+#define ATOM_XEMBED_MESSAGE 5
+#define ATOM_MANAGER 6
+#define ATOM_MB_DOCK_ALIGN 7
+#define ATOM_MB_DOCK_ALIGN_EAST 8
+
+#define ATOM_NET_SYSTEM_TRAY_MESSAGE_DATA 9
+
+#define ATOM_WM_PROTOCOLS 11
+#define ATOM_WM_DELETE_WINDOW 12
+
+#define ATOM_MB_THEME 13
+#define ATOM_MB_PANEL_BG 16
+#define ATOM_MB_DOCK_TIMESTAMP 14
+#define ATOM_NET_WM_STRUT 15
+#define ATOM_WM_CLIENT_LEADER 17
+#define ATOM_NET_WM_ICON 18
+#define ATOM_NET_WM_PID 19
+#define ATOM_XROOTPMAP_ID 20
+#define ATOM_NET_SYSTEM_TRAY_ORIENTATION 21
+#define ATOM_MB_THEME_NAME 22
+#define ATOM_MB_COMMAND 23
+#define ATOM_NET_WM_NAME 24
+#define ATOM_UTF8_STRING 25
+#define ATOM_NET_CLIENT_LIST 26
+
+#define ATOM_NET_WM_STATE 27
+#define ATOM_NET_WM_STATE_TITLEBAR 28
+
+#define ATOM_MB_SYSTEM_TRAY_CONTEXT 29
+#define ATOM_MB_REQ_CLIENT_ORDER 30
+
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+
+/* ID's for various MB COMMAND X Messages */
+
+#define MB_CMD_PANEL_TOGGLE_VISIBILITY 1
+#define MB_CMD_PANEL_SIZE 2
+#define MB_CMD_PANEL_ORIENTATION 3
+
+#define MB_PANEL_ORIENTATION_NORTH 1
+#define MB_PANEL_ORIENTATION_EAST 2
+#define MB_PANEL_ORIENTATION_SOUTH 3
+#define MB_PANEL_ORIENTATION_WEST 4
+
+
+#define SESSION_TIMEOUT 10 /* 5 second session timeout */
+
+#define DBL_CLICK_TIME 200
+
+
+#define DEFAULT_COLOR_SPEC "#e2e2de" /* Same as gnome ? */
+#define MB_MSG_FONT "Sans-8:bold"
+
+enum {
+ BG_SOLID_COLOR,
+ BG_PIXMAP,
+ BG_TRANS
+};
+
+typedef enum {
+ PAPP_GRAVITY_START,
+ PAPP_GRAVITY_END,
+} PanelAppGravity;
+
+typedef enum {
+ North = 1,
+ East,
+ South,
+ West
+} MBPanelOrientation;
+
+
+typedef struct _panel_app {
+
+ Window win;
+ unsigned char *name;
+ int x;
+ int y;
+ int w;
+ int h;
+
+ int offset;
+
+ Bool mapped;
+
+ struct _panel_app *next;
+
+ char *cmd_str;
+
+ struct _panel *panel;
+
+ Bool ignore; /* set so client cant be removed */
+ int ignore_unmap;
+
+ PanelAppGravity gravity;
+
+ MBPixbufImage *icon;
+
+} MBPanelApp;
+
+typedef struct _message_queue {
+
+ MBPanelApp *sender;
+ unsigned long starttime;
+ int timeout;
+ int total_msg_length;
+ int current_msg_length;
+ int id;
+ unsigned char *data;
+
+ Bool has_extra_context;
+ unsigned char *extra_context_data;
+
+ Bool pending; /* Set to true if all data */
+
+ struct _message_queue *next;
+
+} MBPanelMessageQueue;
+
+
+typedef struct _panel {
+
+ /* General */
+
+ Display *dpy;
+ int screen;
+ MBPixbuf *pb;
+ Window win, win_root;
+ GC gc, band_gc;
+ XColor xcol;
+
+ int x,y,w,h;
+
+ MBPanelApp *apps_start_head;
+ MBPanelApp *apps_end_head;
+
+ Atom atoms[31];
+ int padding;
+ int margin_start;
+ int margin_end;
+
+ /* Message windows */
+
+ struct _message_queue *msg_queue_start;
+ struct _message_queue *msg_queue_end;
+
+ Window msg_win;
+ unsigned long msg_starttime;
+ int msg_timeout;
+ MBPanelApp *msg_win_sender;
+ Bool msg_has_context;
+ int msg_context_y1, msg_context_y2;
+
+ GC msg_gc;
+
+ MBColor *msg_col;
+ MBColor *msg_urgent_col;
+ MBColor *msg_fg_col;
+ MBColor *msg_link_col;
+
+ MBFont *msg_font;
+
+
+ /* Various state bits */
+
+ Bool use_flip;
+ Bool use_session;
+ Bool use_alt_session_defaults;
+
+ Bool use_overide_wins;
+ Bool reload_pending;
+
+ MBPanelOrientation orientation;
+
+ int system_tray_id;
+
+ Bool use_themes;
+ char *theme_name;
+ char *theme_path;
+
+ Bool want_titlebar_dest;
+
+ Bool ignore_next_config;
+
+ int default_panel_size;
+
+ /* Session */
+
+ Bool session_preexisting_lock;
+ int session_init_offset;
+ char session_entry_cur[512];
+ pid_t session_needed_pid;
+ time_t session_start_time;
+ FILE *session_fp;
+ PanelAppGravity session_cur_gravity;
+ Bool session_run_first_time;
+ char *session_defaults_cur_pos;
+
+ Window last_click_window;
+ Time last_click_time;
+ Bool next_click_is_not_double;
+ Bool is_hidden;
+
+ /* Background */
+
+ XColor bg_col;
+ Pixmap bg_tile;
+ Pixmap bg_pxm;
+ char *bg_spec;
+ int bg_type;
+
+ /* Popup menu */
+
+ MBMenu* mbmenu;
+ Bool use_menu;
+ MBMenuMenu *remove_menu;
+
+ /* co-ords of where mouse click happened for menu */
+ int click_x;
+ int click_y;
+ Time click_time;
+
+
+ char *bg_trans;
+ long root_pixmap_id;
+
+#ifdef USE_XSETTINGS
+ XSettingsClient *xsettings_client;
+#endif
+
+} MBPanel;
+
+void
+panel_handle_full_panel (MBPanel *panel, MBPanelApp *bad_papp);
+
+void
+panel_toggle_visibilty(MBPanel *panel);
+
+void
+panel_change_orientation (MBPanel *panel,
+ MBPanelOrientation new_orientation,
+ int dpy_w,
+ int dpy_h);
+
+void
+panel_update_client_list_prop (MBPanel *panel);
+
+void
+panel_reorder_apps(MBPanel *panel);
+
+#include "panel_menu.h"
+#include "panel_util.h"
+#include "panel_app.h"
+#include "session.h"
+
+#endif
diff --git a/src/panel_app.c b/src/panel_app.c
new file mode 100644
index 0000000..a3d020b
--- /dev/null
+++ b/src/panel_app.c
@@ -0,0 +1,597 @@
+#include "panel_app.h"
+
+MBPanelApp*
+panel_app_list_get_prev (MBPanel *panel,
+ MBPanelApp *papp,
+ MBPanelApp **list_head)
+{
+ MBPanelApp *tmp = *list_head;
+
+ if (tmp == NULL || papp == tmp) return NULL;
+
+ while (tmp->next != NULL)
+ {
+ if (tmp->next == papp) return tmp;
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
+
+MBPanelApp*
+panel_app_list_get_last (MBPanel *panel,
+ MBPanelApp *list_head)
+{
+ MBPanelApp *tmp = list_head;
+
+ if (tmp == NULL) return NULL;
+
+ while (tmp->next != NULL) tmp = tmp->next;
+
+ return tmp;
+}
+
+MBPanelApp*
+panel_app_list_prepend(MBPanel *panel,
+ MBPanelApp *list_to_append_to,
+ MBPanelApp *papp_new)
+{
+ papp_new->next = list_to_append_to;
+ return papp_new;
+}
+
+void
+panel_app_list_append (MBPanel *panel,
+ MBPanelApp **list_to_append_to,
+ MBPanelApp *new_client)
+{
+ MBPanelApp *tmp = NULL;
+ if (*list_to_append_to == NULL)
+ {
+ *list_to_append_to = new_client;
+ }
+ else
+ {
+ tmp = *list_to_append_to;
+ while ( tmp->next != NULL ) tmp = tmp->next;
+ tmp->next = new_client;
+ }
+
+ new_client->next = NULL;
+}
+
+void /* XXX Can probably go */
+panel_app_list_insert_after(MBPanel *panel,
+ MBPanelApp *papp,
+ MBPanelApp *new_papp)
+{
+ MBPanelApp *tmp;
+ tmp = papp->next;
+ papp->next = new_papp;
+ new_papp->next = tmp;
+}
+
+void
+panel_app_list_remove (MBPanel *panel,
+ MBPanelApp *papp,
+ MBPanelApp **list_head)
+{
+ MBPanelApp *prev_papp = panel_app_list_get_prev(panel, papp, list_head);
+
+ if (prev_papp == NULL)
+ {
+ *list_head = papp->next;
+ }
+ else
+ {
+ prev_papp->next = papp->next;
+ }
+ return;
+}
+
+void
+panel_app_name_get(MBPanel *panel,
+ MBPanelApp *papp)
+{
+ Atom type;
+ int format;
+ long bytes_after;
+ long n_items;
+ int result;
+
+ result = XGetWindowProperty (panel->dpy, papp->win,
+ panel->atoms[ATOM_NET_WM_NAME],
+ 0, 1024L,
+ False, panel->atoms[ATOM_UTF8_STRING],
+ &type, &format, &n_items,
+ &bytes_after, (unsigned char **)&papp->name);
+
+ if (result != Success
+ || papp->name == NULL
+ || type != panel->atoms[ATOM_UTF8_STRING]
+ || format != 8
+ || n_items == 0)
+ {
+ if (papp->name) XFree (papp->name);
+
+ XFetchName(panel->dpy, papp->win, (char **)&papp->name);
+ if (papp->name == NULL) {
+ XStoreName(panel->dpy, papp->win, "<unnamed>");
+ XFetchName(panel->dpy, papp->win, (char **)&papp->name);
+ if (papp->name == NULL)
+ papp->name = strdup("<unnamed>");
+ }
+ }
+}
+
+Window
+panel_app_get_client_leader_win(MBPanel *panel, MBPanelApp *papp)
+{
+ Atom realType;
+ unsigned long n;
+ unsigned long extra;
+ int format;
+ int status;
+ Window* value = NULL, win_result = None;
+
+ status = XGetWindowProperty(panel->dpy, papp->win,
+ panel->atoms[ATOM_WM_CLIENT_LEADER],
+ 0L, 16L,
+ 0, XA_WINDOW, &realType, &format,
+ &n, &extra, (unsigned char **) &value);
+ if (status == Success && realType == XA_WINDOW
+ && format == 32 && n == 1 && value != NULL)
+ {
+ win_result = (Window) value[0];
+ }
+
+ if (value) XFree(value);
+
+ return win_result;
+}
+
+int*
+panel_app_icon_prop_data_get(MBPanel *d, MBPanelApp *papp)
+{
+ Atom type;
+ int format;
+ long bytes_after;
+ unsigned char *data = NULL;
+ long n_items;
+ int result;
+
+ result = XGetWindowProperty (d->dpy, papp->win,
+ d->atoms[ATOM_NET_WM_ICON],
+ 0, 100000L,
+ False, XA_CARDINAL,
+ &type, &format, &n_items,
+ &bytes_after, (unsigned char **)&data);
+
+ if (result != Success || data == NULL)
+ {
+ if (data) XFree (data);
+ DBG("%s() failed for %s (XID: %li)\n", __func__, papp->name, papp->win);
+ return NULL;
+ }
+
+ return (int *)data;
+}
+
+void
+panel_app_add_start(MBPanel *panel, MBPanelApp *papp_new)
+{
+ MBPanelApp *papp_prev;
+
+ papp_prev = panel_app_list_get_last(panel, panel->apps_start_head);
+
+ panel_app_list_append (panel, &panel->apps_start_head, papp_new);
+
+ if (papp_prev != NULL)
+ {
+ papp_new->offset = panel_app_get_offset(panel, papp_prev)
+ + panel_app_get_size(panel, papp_prev);
+ DBG("%s() got %i = %i + %i\n", __func__, papp_new->offset,
+ panel_app_get_offset(panel, papp_prev) ,
+ panel_app_get_size(panel, papp_prev) );
+ }
+ else
+ papp_new->offset = 0;
+
+ papp_new->gravity = PAPP_GRAVITY_START;
+}
+
+void
+panel_app_add_end(MBPanel *panel, MBPanelApp *papp_new)
+{
+ MBPanelApp *papp_prev;
+
+ papp_prev = panel_app_list_get_last(panel, panel->apps_end_head);
+
+ panel_app_list_append (panel, &panel->apps_end_head, papp_new);
+
+ if (papp_prev != NULL)
+ papp_new->offset = panel_app_get_offset(panel, papp_prev)
+ - panel_app_get_size(panel, papp_new);
+ else
+ papp_new->offset = ( PANEL_IS_VERTICAL(panel) ? panel->h : panel->w )
+ - panel_app_get_size(panel, papp_new);
+
+ papp_new->gravity = PAPP_GRAVITY_END;
+}
+
+Bool
+panel_app_check_for_space (MBPanel *panel, MBPanelApp *papp)
+{
+ MBPanelApp *papp_end = NULL, *papp_start = NULL;
+
+ papp_end = panel_app_list_get_last(panel, panel->apps_end_head);
+ papp_start = panel_app_list_get_last(panel, panel->apps_start_head);
+
+ if (papp_end && papp_start &&
+ panel_app_get_offset(panel, papp_start)
+ + panel_app_get_size(panel, papp_start)
+ > panel_app_get_offset(panel, papp_end))
+ {
+ panel_handle_full_panel(panel, papp);
+ return False;
+ }
+ return True;
+}
+
+MBPanelApp *
+panel_app_new(MBPanel *panel, Window win, char *cmd_str)
+{
+ MBPanelApp *papp;
+ XWindowAttributes attr;
+ int padding = 0;
+ Bool add_at_start = False;
+
+ papp = NEW(MBPanelApp);
+
+ papp->next = NULL;
+ papp->win = win;
+ papp->panel = panel;
+ papp->ignore = False;
+ papp->ignore_unmap = 0;
+ papp->icon = NULL;
+
+ /* XXX should check we actually get this */
+ XGetWindowAttributes(panel->dpy, win, &attr);
+
+ papp->w = attr.width;
+ papp->h = attr.height;
+
+ if (session_preexisting_restarting(panel) && !panel->session_run_first_time)
+ {
+ if (panel->session_cur_gravity == PAPP_GRAVITY_START)
+ add_at_start = True;
+ }
+ else if ( ((attr.x < 0) && !PANEL_IS_VERTICAL(panel))
+ || ((attr.y < 0) && PANEL_IS_VERTICAL(panel)))
+ {
+ add_at_start = True;
+ }
+
+ if (add_at_start)
+ {
+ if (panel->apps_start_head == NULL)
+ padding = panel->margin_start;
+ else
+ padding = panel->padding;
+
+ panel_app_add_start(panel, papp);
+ }
+ else
+ {
+ if (panel->apps_end_head == NULL)
+ padding = -1 * panel->margin_end;
+ else
+ padding = -1 * panel->padding;
+
+ panel_app_add_end(panel, papp);
+ }
+
+ DBG("%s() papp offset at %i\n", __func__, papp->offset );
+
+ panel_app_name_get(panel, papp);
+
+ papp->cmd_str = cmd_str;
+
+ if (panel->orientation == North || panel->orientation == South)
+ {
+ papp->h = panel->h - 4;
+ papp->y = (panel->h - papp->h) / 2;
+ papp->x = papp->offset + padding;
+ }
+ else
+ {
+ papp->w = panel->w - 4;
+ papp->x = (panel->w - papp->w) / 2;
+ papp->y = papp->offset + padding;
+ }
+
+ if (!panel_app_check_for_space(panel, papp))
+ return NULL;
+
+ XResizeWindow(panel->dpy, papp->win, papp->w, papp->h);
+ XReparentWindow(panel->dpy, papp->win, panel->win, papp->x, papp->y);
+ panel_app_deliver_config_event(panel, papp);
+
+ panel_update_client_list_prop (panel);
+
+ return papp;
+}
+
+void
+panel_app_handle_configure_request(MBPanel *panel, XConfigureRequestEvent *ev)
+{
+ XWindowChanges xwc;
+ MBPanelApp *papp = NULL;
+
+ papp = panel_app_get_from_window( panel, ev->window );
+
+ if (panel->is_hidden) return;
+
+ if (papp != NULL)
+ {
+ DBG("%s() config req x: %i , y: %i w: %i h: %i for %s\n",
+ __func__, ev->x, ev->y, ev->width, ev->height, papp->name );
+
+ DBG("%s() panel is w: %i %i h:\n",
+ __func__, panel->w, panel->h );
+
+ if (panel->orientation == North || panel->orientation == South)
+ {
+ xwc.width = ev->width;
+ xwc.height = panel->h - 4;
+
+ papp->y = (panel->h - papp->h) / 2;
+
+ if (xwc.width != papp->w) /* Handle width changes */
+ {
+ if (papp == panel_app_list_get_last(panel, panel->apps_end_head))
+ {
+ panel_app_move_to(panel, papp,
+ papp->x - (xwc.width - papp->w));
+ }
+ else if (papp == panel_app_list_get_last(panel,
+ panel->apps_start_head))
+ {
+ panel_app_move_to(panel, papp,
+ papp->x + (xwc.width - papp->w));
+ }
+ else
+ {
+ panel_apps_nudge (panel, papp->next, xwc.width - papp->w);
+ }
+ papp->w = xwc.width;
+ }
+
+ xwc.x = papp->x; /* NOT allowed to move themselves */
+ xwc.y = papp->y;
+
+ } else { /* East / West orientated dock */
+
+ xwc.width = panel->w - 4;
+ xwc.height = ev->height;
+
+ papp->x = (panel->w - papp->w) / 2;
+ xwc.x = papp->x;
+ xwc.y = papp->y;
+
+ if (xwc.height != papp->h) /* Handle width changes */
+ {
+ if (papp == panel_app_list_get_last(panel, panel->apps_end_head))
+ {
+ panel_app_move_to(panel, papp,
+ papp->y - (xwc.height - papp->h));
+ }
+ else if (papp == panel_app_list_get_last(panel,
+ panel->apps_start_head))
+ {
+ panel_app_move_to(panel, papp,
+ papp->y + (xwc.height - papp->h));
+ }
+ else
+ {
+ panel_apps_nudge (panel, papp->next, xwc.height - papp->h);
+ }
+ papp->h = xwc.height;
+ }
+ }
+
+ xwc.border_width = 0;
+ xwc.sibling = None;
+ xwc.stack_mode = None;
+
+ DBG("%s() setting x: %i , y: %i w: %i h: %i \n",
+ __func__, xwc.x, xwc.y, xwc.width, xwc.height );
+
+ XConfigureWindow(panel->dpy, papp->win, ev->value_mask, &xwc);
+ }
+}
+
+void
+panel_app_deliver_config_event(MBPanel *panel, MBPanelApp *papp)
+{
+ XConfigureEvent ce;
+
+ if (panel->is_hidden) return;
+
+ ce.type = ConfigureNotify;
+ ce.event = papp->win;
+ ce.window = papp->win;
+
+ if (PANEL_IS_VERTICAL(panel))
+ {
+ papp->x = (panel->w - papp->w) / 2;
+ ce.x = papp->x;
+ ce.y = papp->y;
+ ce.width = papp->w;
+ ce.height = papp->h;
+ } else {
+ papp->y = (panel->h - papp->h) / 2;
+ ce.x = papp->x;
+ ce.y = papp->y; // + panel->y;
+ ce.width = papp->w;
+ ce.height = papp->h;
+ }
+
+ ce.border_width = 0;
+ ce.above = panel->win;
+ ce.override_redirect = 0;
+
+ DBG("%s() delivering x: %i , y: %i w: %i h: %i name : %s\n",
+ __func__, ce.x, ce.y, ce.width, ce.height, papp->name );
+
+ XSendEvent(panel->dpy, papp->win, False,
+ StructureNotifyMask, (XEvent *)&ce);
+}
+
+void
+panel_app_move_to (MBPanel *panel,
+ MBPanelApp *papp,
+ int origin_offset)
+{
+ if (panel->orientation == North || panel->orientation == South)
+ {
+ papp->x = origin_offset;
+ papp->y = (panel->h - papp->h) / 2;
+ }
+ else
+ {
+ papp->y = origin_offset;
+ papp->x = (panel->w - papp->w) / 2;
+ }
+
+ papp->offset = origin_offset;
+
+ if (!panel_app_check_for_space(panel, papp))
+ return;
+
+ XMoveWindow(panel->dpy, papp->win, papp->x, papp->y);
+}
+
+void
+panel_apps_nudge (MBPanel *panel,
+ MBPanelApp *papp,
+ int amount)
+{
+ MBPanelApp *papp_cur = papp;
+
+ while (papp_cur != NULL)
+ {
+ panel_app_move_to (panel, papp_cur,
+ panel_app_get_offset(panel, papp_cur) + amount);
+ papp_cur = papp_cur->next;
+ }
+}
+
+void
+panel_apps_rescale (MBPanel *panel,
+ MBPanelApp *papp)
+{
+ MBPanelApp *papp_cur = papp;
+
+ while (papp_cur != NULL)
+ {
+ papp->h = panel->h - 4;
+ XResizeWindow(panel->dpy, papp->win, papp->w, papp->h);
+ panel_app_deliver_config_event(panel, papp);
+ papp_cur = papp_cur->next;
+ }
+}
+
+void
+panel_app_destroy (MBPanel *panel,
+ MBPanelApp *papp)
+{
+ MBMenuItem *tmp = NULL;
+
+ if (!papp) return;
+
+ /* remove popup menu entry XXX this functionaility should be in mbmenu */
+ if (panel->remove_menu)
+ tmp = panel->remove_menu->items;
+
+ while (tmp != NULL)
+ {
+ if ((MBPanelApp *)tmp->cb_data == papp)
+ {
+ mb_menu_item_remove(panel->mbmenu, panel->remove_menu, tmp);
+ break;
+ }
+ tmp = tmp->next_item;
+ }
+
+ if (papp->gravity == PAPP_GRAVITY_START)
+ {
+ panel_apps_nudge(panel, papp->next,
+ -1 * panel_app_get_size(panel, papp));
+ panel_app_list_remove(panel, papp, &panel->apps_start_head);
+ }
+ else
+ {
+ panel_apps_nudge(panel, papp->next, panel_app_get_size(panel, papp));
+ panel_app_list_remove(panel, papp, &panel->apps_end_head);
+ }
+
+ if (papp->name) XFree(papp->name);
+
+ if (papp->cmd_str) free(papp->cmd_str);
+
+ if (papp->icon) mb_pixbuf_img_free(panel->pb, papp->icon);
+
+ free(papp);
+
+ panel_update_client_list_prop (panel);
+}
+
+/* Utilities */
+
+int
+panel_app_get_offset (MBPanel *panel,
+ MBPanelApp *papp)
+{
+ if (panel->orientation == East || panel->orientation == West)
+ return papp->y;
+ else
+ return papp->x;
+}
+
+int
+panel_app_get_size (MBPanel *panel,
+ MBPanelApp *papp)
+{
+ if (panel->orientation == East || panel->orientation == West)
+ return papp->h;
+ else
+ return papp->w;
+}
+
+MBPanelApp*
+panel_app_get_from_window (MBPanel *panel,
+ Window win)
+{
+ MBPanelApp *papp = panel->apps_start_head;
+ DBG("%s() called, looking for win %li\n", __func__, win);
+
+ while( papp != NULL)
+ {
+ DBG("%s() check %s ( %li )\n", __func__, papp->name, papp->win);
+ if (papp->win == win) return papp;
+ papp = papp->next;
+ }
+
+ papp = panel->apps_end_head;
+
+ while( papp != NULL)
+ {
+ // DBG("%s() check %s ( %li )\n", __func__, papp->name, papp->win);
+ if (papp->win == win) return papp;
+ papp = papp->next;
+ }
+
+ return NULL;
+}
+
diff --git a/src/panel_app.h b/src/panel_app.h
new file mode 100644
index 0000000..cb13deb
--- /dev/null
+++ b/src/panel_app.h
@@ -0,0 +1,92 @@
+#ifndef _PANEL_APP_H_
+#define _PANEL_APP_H_
+
+#include "panel.h"
+
+MBPanelApp*
+panel_app_list_get_prev (MBPanel *panel,
+ MBPanelApp *papp,
+ MBPanelApp **list_head);
+MBPanelApp*
+panel_app_list_get_last (MBPanel *panel,
+ MBPanelApp *list_head);
+
+
+MBPanelApp *
+panel_app_list_prepend(MBPanel *panel,
+ MBPanelApp *list_to_append_to,
+ MBPanelApp *papp_new);
+
+/*
+void
+panel_app_list_prepend(MBPanel *panel,
+ MBPanelApp **list_to_append_to,
+ MBPanelApp *papp_new);
+*/
+
+void
+panel_app_list_append (MBPanel *panel,
+ MBPanelApp **list_to_append_to,
+ MBPanelApp *new_client);
+
+
+void panel_app_list_insert_after(MBPanel *panel, MBPanelApp *papp,
+ MBPanelApp *new_papp);
+
+void panel_app_list_remove (MBPanel *panel,
+ MBPanelApp *papp,
+ MBPanelApp **list_head );
+
+void
+panel_app_add_start(MBPanel *panel, MBPanelApp *papp_new);
+
+void
+panel_app_add_end(MBPanel *panel, MBPanelApp *papp_new);
+
+
+void panel_app_list_add(MBPanel *panel, MBPanelApp *papp_new);
+
+void panel_app_name_get(MBPanel *panel, MBPanelApp *papp);
+
+Window panel_app_get_client_leader_win(MBPanel *panel, MBPanelApp *papp);
+
+int* panel_app_icon_prop_data_get(MBPanel *d, MBPanelApp *papp);
+
+void panel_app_command_prop_get(MBPanel *panel, MBPanelApp *papp);
+
+Bool panel_app_get_command_str(MBPanel *panel, MBPanelApp *papp,
+ char **result);
+
+MBPanelApp* panel_app_get_from_window(MBPanel *panel, Window win);
+
+MBPanelApp* panel_app_new(MBPanel *panel,
+ Window win,
+ char *cmd );
+
+void panel_app_handle_configure_request(MBPanel *panel,
+ XConfigureRequestEvent *ev);
+
+void panel_app_deliver_config_event(MBPanel *panel, MBPanelApp *papp);
+
+void
+panel_apps_rescale (MBPanel *panel,
+ MBPanelApp *papp);
+
+void
+panel_apps_nudge (MBPanel *panel,
+ MBPanelApp *papp,
+ int amount);
+
+void
+panel_app_move_to(MBPanel *panel, MBPanelApp *papp, int origin_offset);
+
+void
+panel_app_destroy(MBPanel *panel, MBPanelApp *papp);
+
+int
+panel_app_get_offset(MBPanel *panel, MBPanelApp *papp);
+
+int
+panel_app_get_size(MBPanel *panel, MBPanelApp *papp);
+
+#endif
diff --git a/src/panel_menu.c b/src/panel_menu.c
new file mode 100644
index 0000000..fbb6169
--- /dev/null
+++ b/src/panel_menu.c
@@ -0,0 +1,276 @@
+#include "panel_menu.h"
+
+#ifdef USE_PNG
+#define FOLDER_IMG "mbfolder.png"
+#define ADD_IMG "mbadd.png"
+#define REMOVE_IMG "mbremove.png"
+#define HIDE_IMG "mbdown.png"
+#else
+#define FOLDER_IMG "mbfolder.xpm"
+#define ADD_IMG "mbadd.xpm"
+#define REMOVE_IMG "mbremove.xpm"
+#define HIDE_IMG "mbdown.xpm"
+#endif
+
+void panel_menu_exec_cb(MBMenuItem *item)
+{
+ char *cmd = strdup(item->info);
+
+ util_fork_exec(cmd);
+ free(cmd);
+}
+
+void panel_menu_exit_cb(MBMenuItem *item)
+{
+ /* This should only be called by the menu.
+ As we now delete the session file. So its not used again.
+ */
+ MBPanel *panel = (MBPanel *)item->cb_data;
+ session_destroy(panel);
+
+ util_cleanup_children(0);
+}
+
+void panel_menu_hide_cb(MBMenuItem *item)
+{
+ MBPanel *panel = (MBPanel *)item->cb_data;
+ panel_toggle_visibilty(panel);
+}
+
+void panel_menu_kill_cb(MBMenuItem *item)
+{
+ MBPanelApp *papp = (MBPanelApp *)item->cb_data;
+
+ XGrabServer(papp->panel->dpy);
+ XKillClient(papp->panel->dpy, papp->win);
+ session_save(papp->panel);
+ XUngrabServer(papp->panel->dpy);
+}
+
+void
+panel_menu_update_remove_items(MBPanel *panel)
+{
+ int *icon_data = NULL;
+ MBMenuItem *menu_item;
+ MBPanelApp *papp = NULL;
+ MBPanelApp *papp_heads[] = { panel->apps_start_head,
+ panel->apps_end_head,
+ NULL };
+ int i = 0;
+
+ if (panel->remove_menu == NULL)
+ {
+ char *icon_path = NULL;
+
+ icon_path = mb_dot_desktop_icon_get_full_path (panel->theme_name,
+ 16, REMOVE_IMG );
+
+ panel->remove_menu = mb_menu_add_path(panel->mbmenu, _("Remove"),
+ icon_path,
+ MBMENU_PREPEND);
+ if (icon_path) free(icon_path);
+ }
+
+ /* Remove all items then readd so order matches panel */
+
+ if (panel->remove_menu->items)
+ {
+ MBMenuItem *tmp_item = NULL;
+
+ menu_item = panel->remove_menu->items;
+
+ while (menu_item != NULL)
+ {
+ tmp_item = menu_item->next_item;
+ mb_menu_item_remove(panel->mbmenu, panel->remove_menu, menu_item);
+ menu_item = tmp_item;
+ }
+ }
+
+
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+
+ if (i == 1)
+ papp = panel_app_list_get_last(panel, panel->apps_end_head);
+
+ while( papp != NULL)
+ {
+ if (!papp->ignore)
+ {
+ menu_item = mb_menu_add_item_to_menu(panel->mbmenu,
+ panel->remove_menu,
+ papp->name, NULL,
+ papp->name,
+ panel_menu_kill_cb,
+ (void *)papp,
+ MBMENU_NO_SORT);
+
+ if (!papp->icon)
+ {
+ if ((icon_data = panel_app_icon_prop_data_get(panel, papp))
+ != NULL )
+ {
+ char *p;
+ int j;
+
+ DBG("%s() Got icon data (size: %i x %i)\n", __func__,
+ icon_data[0], icon_data[1] );
+
+ papp->icon = mb_pixbuf_img_new(panel->pb,
+ icon_data[0], icon_data[1] );
+ p = papp->icon->rgba;
+
+ for (j =0 ; j < (icon_data[0]*icon_data[1]); j++)
+ {
+ *p++ = (icon_data[j+2] >> 16) & 0xff;
+ *p++ = (icon_data[j+2] >> 8) & 0xff;
+ *p++ = icon_data[j+2] & 0xff;
+ *p++ = icon_data[j+2] >> 24;
+ }
+
+ XFree(icon_data);
+ }
+ }
+
+ if (papp->icon)
+ mb_menu_item_icon_set(panel->mbmenu, menu_item, papp->icon);
+ }
+
+ if (i == 1)
+ {
+ papp = panel_app_list_get_prev (panel, papp,
+ &panel->apps_end_head);
+ }
+ else papp = papp->next;
+ }
+ i++;
+ }
+
+}
+
+void
+panel_menu_init(MBPanel *panel)
+{
+ MBMenuMenu *m, *menu_launchers;
+ char orig_wd[256] = { 0 };
+ struct dirent *dir_entry;
+ char *icon_path = NULL;
+ DIR *dp;
+
+ if (panel->mbmenu == NULL)
+ {
+ panel->mbmenu = mb_menu_new(panel->dpy, panel->screen );
+ mb_menu_set_icon_size(panel->mbmenu, 16);
+ }
+ else mb_menu_free(panel->mbmenu); /* XXX should be mb_menu_empty */
+
+ icon_path = mb_dot_desktop_icon_get_full_path (panel->theme_name,
+ 16, ADD_IMG );
+
+ m = mb_menu_add_path(panel->mbmenu, _("Add"), icon_path,
+ MBMENU_NO_SORT );
+
+ if (icon_path) free(icon_path);
+
+ icon_path = mb_dot_desktop_icon_get_full_path (panel->theme_name,
+ 16, FOLDER_IMG );
+
+ menu_launchers = mb_menu_add_path(panel->mbmenu, "Add/Launchers",
+ icon_path, MBMENU_NO_SORT );
+
+ if (icon_path) free(icon_path);
+
+ if (getcwd(orig_wd, 255) == (char *)NULL)
+ {
+ printf("Cant get current directory\n");
+ exit(0);
+ }
+
+ if ((dp = opendir(DATADIR "/applications")) != NULL)
+ {
+ chdir(DATADIR "/applications");
+
+ while((dir_entry = readdir(dp)) != NULL)
+ {
+ struct stat stat_info;
+ stat(dir_entry->d_name, &stat_info);
+ if (!(stat_info.st_mode & S_IFDIR))
+ {
+ MBDotDesktop *ddentry = NULL;
+ ddentry = mb_dotdesktop_new_from_file(dir_entry->d_name);
+ if (ddentry
+ && mb_dotdesktop_get(ddentry, "Type")
+ && mb_dotdesktop_get(ddentry, "Name")
+ && mb_dotdesktop_get(ddentry, "Exec")
+ )
+ {
+
+ char *png_path = NULL;
+ unsigned char *icon_str = mb_dotdesktop_get(ddentry, "Icon");
+
+ png_path = mb_dot_desktop_icon_get_full_path (
+ panel->theme_name,
+ 16, icon_str );
+
+ if (!strcmp(mb_dotdesktop_get(ddentry, "Type"), "PanelApp"))
+ {
+ mb_menu_add_item_to_menu(panel->mbmenu,
+ m,
+ mb_dotdesktop_get(ddentry,
+ "Name"),
+ png_path,
+ mb_dotdesktop_get(ddentry,
+ "Exec"),
+ panel_menu_exec_cb,
+ (void *)panel, 0);
+ } else {
+ char launcher_exec_str[256] = { 0 };
+ snprintf(launcher_exec_str, 256,
+ "monolaunch -o -1 --desktop %s/%s",
+ DATADIR "/applications", dir_entry->d_name);
+ mb_menu_add_item_to_menu(panel->mbmenu,
+ menu_launchers,
+ mb_dotdesktop_get(ddentry,
+ "Name"),
+ png_path,
+ launcher_exec_str,
+ panel_menu_exec_cb,
+ (void *)panel, 0);
+
+ }
+ if (png_path) free(png_path);
+ mb_dotdesktop_free(ddentry);
+ }
+ }
+ }
+ closedir(dp);
+ }
+ else fprintf(stderr, "failed to open %s\n", DATADIR "/applications");
+
+ chdir(orig_wd);
+
+ panel->remove_menu = NULL;
+
+ icon_path = mb_dot_desktop_icon_get_full_path (panel->theme_name,
+ 16, HIDE_IMG );
+
+ mb_menu_add_item_to_menu(panel->mbmenu, panel->mbmenu->rootmenu, _("Hide"),
+ icon_path, NULL ,
+ panel_menu_hide_cb, (void *)panel, MBMENU_NO_SORT);
+
+
+ if (panel->system_tray_id > 0)
+ mb_menu_add_item_to_menu(panel->mbmenu, panel->mbmenu->rootmenu,
+ "Exit",
+ NULL, NULL ,
+ panel_menu_exit_cb,
+ (void *)panel, MBMENU_NO_SORT);
+
+
+ if (icon_path) free(icon_path);
+
+ return;
+}
+
diff --git a/src/panel_menu.h b/src/panel_menu.h
new file mode 100644
index 0000000..87839ab
--- /dev/null
+++ b/src/panel_menu.h
@@ -0,0 +1,27 @@
+#ifndef _HAVE_PANEL_MENU_H
+#define _HAVE_PANEL_MENU_H
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(text) gettext(text)
+#else
+# define _(text) (text)
+#endif
+
+#include "panel.h"
+
+void panel_menu_exec_cb(MBMenuItem *item);
+
+void panel_menu_exit_cb(MBMenuItem *item);
+
+void panel_menu_hide_cb(MBMenuItem *item);
+
+void panel_menu_move_app_cb(MBMenuItem *item);
+
+void panel_menu_kill_cb(MBMenuItem *item);
+
+void panel_menu_update_remove_items(MBPanel *panel);
+
+void panel_menu_init(MBPanel *panel);
+
+#endif
diff --git a/src/panel_util.c b/src/panel_util.c
new file mode 100644
index 0000000..593413f
--- /dev/null
+++ b/src/panel_util.c
@@ -0,0 +1,233 @@
+#include "panel_util.h"
+
+extern MBPanel* G_panel;
+
+void
+util_cleanup_children(int s)
+{
+ DBG("DIE DIE\n");
+ kill(-getpid(), 15); /* kill every one in our process group */
+ exit(0);
+}
+
+void
+util_install_signal_handlers(void)
+{
+
+ signal (SIGCHLD, SIG_IGN); /* kernel can deal with zombies */
+ signal (SIGINT, util_cleanup_children);
+ signal (SIGQUIT, util_cleanup_children);
+ signal (SIGTERM, util_cleanup_children);
+ signal (SIGHUP, util_handle_hup);
+ signal (SIGALRM, util_handle_alarm);
+ // signal (SIGSEGV, cleanup_children);
+
+}
+
+int
+util_handle_xerror(Display *dpy, XErrorEvent *e)
+{
+ char msg[255];
+ XGetErrorText(dpy, e->error_code, msg, sizeof msg);
+ fprintf(stderr, "Panel X error (%#lx):\n %s (opcode: %i)\n",
+ e->resourceid, msg, e->request_code);
+ return 0;
+}
+
+pid_t
+util_fork_exec(char *cmd)
+{
+ pid_t pid, mypid;
+ mypid = getpid();
+ pid = fork();
+
+ switch (pid) {
+ case 0:
+ setpgid (0, mypid); /* set pgid to parents pid */
+ mb_exec(cmd);
+ fprintf(stderr, "exec failed, cleaning up child\n");
+ exit(1);
+ case -1:
+ fprintf(stderr, "can't fork\n"); break;
+ }
+ return pid;
+}
+
+
+void
+util_handle_alarm(int s)
+{
+ MBPanel *p = G_panel;
+ DBG("%s() called", __func__);
+ session_save(p);
+}
+
+void
+util_handle_hup(int s)
+{
+ MBPanel *p = G_panel;
+ DBG("%s() called", __func__);
+
+ if (p != NULL)
+ {
+ p->reload_pending = True;
+ }
+}
+
+void
+util_get_mouse_position(MBPanel *panel, int *x, int *y)
+{
+ Window mouse_root, mouse_win;
+ int win_x, win_y;
+ unsigned int mask;
+
+ XQueryPointer(panel->dpy, panel->win_root, &mouse_root, &mouse_win,
+ x, y, &win_x, &win_y, &mask);
+}
+
+pid_t
+util_get_window_pid_from_prop(MBPanel *panel, Window win)
+{
+ Atom type;
+ int format;
+ long bytes_after;
+ unsigned int *data = NULL;
+ long n_items;
+ int result;
+ pid_t pid_result = 0;
+
+ result = XGetWindowProperty (panel->dpy, win,
+ panel->atoms[ATOM_NET_WM_PID],
+ 0, 16L,
+ False, XA_CARDINAL,
+ &type, &format, &n_items,
+ &bytes_after, (unsigned char **)&data);
+
+ if (result == Success && n_items)
+ pid_result = *data;
+
+ if (data) XFree(data);
+
+ return pid_result;
+}
+
+Bool
+util_get_command_str_from_win(MBPanel *panel, Window win, char **result)
+{
+ int i, bytes_needed = 0;
+ char *p = NULL, *cmd = NULL, **argv_win;
+ int argc_win;
+
+ if (!XGetCommand(panel->dpy, win, &argv_win, &argc_win))
+ return False;
+
+ bytes_needed = strlen(argv_win[0])+2;
+
+ for(i=1;i<argc_win;i++)
+ {
+ bytes_needed += strlen(argv_win[i])+2;
+ for (p = argv_win[i]; *p != '\0'; p++)
+ if (*p == ' ' || *p == '\t')
+ bytes_needed++;
+ }
+
+ *result = malloc(sizeof(char)*bytes_needed);
+ cmd = *result;
+
+ strcpy(cmd, argv_win[0]);
+ while(*cmd != '\0') cmd++;
+
+ for(i=1;i<argc_win;i++)
+ {
+ p = argv_win[i];
+ *cmd++ = ' ';
+
+ if (strpbrk(p, " \t") == NULL)
+ {
+ while (*p) *cmd++ = *p++;
+ } else {
+ *cmd++ = '\'';
+ while (*p)
+ {
+ if (*p == '\'')
+ *cmd++ = '\\';
+ *cmd++ = *p++;
+ }
+ *cmd++ = '\'';
+ }
+ }
+
+ *cmd = '\0';
+
+ XFreeStringList(argv_win);
+
+ return True;
+}
+
+Bool
+util_xcol_from_spec(MBPanel *panel, MBColor *col, char *spec)
+{
+ mb_col_set (col, spec);
+ return True;
+}
+
+Pixmap
+util_get_root_pixmap(MBPanel *panel)
+{
+ Pixmap root_pxm = None;
+
+ Atom type;
+ int format;
+ long bytes_after;
+ Pixmap *data = NULL;
+ long n_items;
+ int result;
+
+ result = XGetWindowProperty (panel->dpy, panel->win_root,
+ panel->atoms[ATOM_XROOTPMAP_ID],
+ 0, 16L,
+ False, XA_PIXMAP,
+ &type, &format, &n_items,
+ &bytes_after, (unsigned char **)&data);
+
+ if (result == Success && n_items)
+ root_pxm = *data;
+
+ if (data) XFree(data);
+
+ panel->root_pixmap_id = root_pxm;
+
+ return root_pxm;
+}
+
+unsigned char *
+util_get_utf8_prop(MBPanel *panel, Window win, Atom req_atom)
+{
+ Atom type;
+ int format;
+ long bytes_after;
+ unsigned char *str = NULL;
+ long n_items;
+ int result;
+
+ result = XGetWindowProperty (panel->dpy, win,
+ req_atom,
+ 0, 1024L,
+ False, panel->atoms[ATOM_UTF8_STRING],
+ &type, &format, &n_items,
+ &bytes_after, (unsigned char **)&str);
+
+ if (result != Success || str == NULL)
+ {
+ if (str) XFree (str);
+ return NULL;
+ }
+
+ if (type != panel->atoms[ATOM_UTF8_STRING] || format != 8 || n_items == 0)
+ {
+ XFree (str);
+ return NULL;
+ }
+
+ return str;
+}
diff --git a/src/panel_util.h b/src/panel_util.h
new file mode 100644
index 0000000..01a59b1
--- /dev/null
+++ b/src/panel_util.h
@@ -0,0 +1,33 @@
+#ifndef _HAVE_PANEL_UTIL_H
+#define _HAVE_PANEL_UTIL_H
+
+#include "panel.h"
+
+void util_cleanup_children(int s);
+
+void util_install_signal_handlers(void);
+
+int util_handle_xerror(Display *dpy, XErrorEvent *e);
+
+pid_t util_fork_exec(char *cmd);
+
+void util_handle_alarm(int s);
+
+void util_handle_hup(int s);
+
+void util_get_mouse_position(MBPanel *panel, int *x, int *y);
+
+pid_t util_get_window_pid_from_prop(MBPanel *panel, Window win);
+
+Bool util_get_command_str_from_win(MBPanel *panel, Window win, char **result);
+
+Bool
+util_xcol_from_spec(MBPanel *panel, MBColor *col, char *spec);
+
+Pixmap util_get_root_pixmap(MBPanel *panel);
+
+unsigned char *
+util_get_utf8_prop(MBPanel *panel, Window win, Atom req_atom);
+
+
+#endif
diff --git a/src/session.c b/src/session.c
new file mode 100644
index 0000000..75c29ae
--- /dev/null
+++ b/src/session.c
@@ -0,0 +1,311 @@
+#include "session.h"
+
+#define DEFAULT_SESSIONS "mbmenu,minitime"
+
+void
+session_set_defaults(MBPanel *panel, char *defaults)
+{
+ panel->session_defaults_cur_pos = strdup(defaults);
+ panel->use_alt_session_defaults = True;
+}
+
+void
+session_destroy(MBPanel *panel)
+{
+ char sessionfile[512] = { 0 };
+
+ if (!panel->use_session) return;
+
+ if (panel->system_tray_id)
+ snprintf(sessionfile, 512, "%s/.matchbox/%s.%i", getenv("HOME"),
+ PANELFILE, panel->system_tray_id );
+ else
+ snprintf(sessionfile, 512, "%s/.matchbox/%s",
+ getenv("HOME"), PANELFILE );
+
+ unlink(sessionfile);
+}
+
+void
+session_init(MBPanel *panel)
+{
+ char sessionfile[512] = { 0 };
+ struct stat st;
+
+ DBG("%s() called\n", __func__);
+
+ panel->session_preexisting_lock = False;
+ panel->session_run_first_time = False;
+
+ if (!panel->use_session && !panel->use_alt_session_defaults) return;
+
+ /*
+ if (panel->use_alt_session_defaults)
+ {
+ panel->session_cur_gravity = PAPP_GRAVITY_END;
+ panel->session_run_first_time = True;
+ }
+ */
+
+ if (getenv("HOME") == NULL)
+ {
+ fprintf(stderr, "mbdock: unable to get home directory, is HOME set?\n");
+ panel->session_preexisting_lock = False;
+ return;
+ }
+
+ snprintf(sessionfile, 512, "%s/.matchbox", getenv("HOME"));
+
+ /* Check if ~/.matchbox exists and create if not */
+ if (stat(sessionfile, &st) != 0 /* || !S_ISDIR(st.st_mode) */
+ || !panel->use_session)
+ {
+ if (panel->use_session)
+ {
+ fprintf(stderr, "mbdock: creating %s directory for session files\n",
+ sessionfile);
+ mkdir(sessionfile, 0755);
+ }
+ panel->session_cur_gravity = PAPP_GRAVITY_END;
+ panel->session_run_first_time = True;
+ if (!panel->use_alt_session_defaults)
+ panel->session_defaults_cur_pos = strdup(DEFAULT_SESSIONS);
+ }
+ else
+ {
+ /* We have a ~/.matchbox , see if we have a session file
+ and set defualts if not.
+ */
+ if (panel->system_tray_id)
+ snprintf(sessionfile, 512, "%s/.matchbox/%s.%i", getenv("HOME"),
+ PANELFILE, panel->system_tray_id );
+ else
+ snprintf(sessionfile, 512, "%s/.matchbox/%s",
+ getenv("HOME"), PANELFILE );
+
+ if ((panel->session_fp = fopen(sessionfile, "r")) == NULL)
+ {
+ fprintf(stderr,
+ "mbpanel: Session file does not exist ( tryed %s )\n",
+ sessionfile);
+ if (!panel->use_alt_session_defaults)
+ {
+ panel->session_defaults_cur_pos = strdup(DEFAULT_SESSIONS);
+ }
+ panel->session_cur_gravity = PAPP_GRAVITY_START;
+ panel->session_run_first_time = True;
+ }
+ else
+ {
+ DBG("%s() opened %s\n", __func__, sessionfile);
+ }
+ }
+
+ panel->session_preexisting_lock = True; /* we are loading session data */
+ panel->session_entry_cur[0] = 0;
+
+ session_preexisting_start_next(panel);
+
+}
+
+void session_save(MBPanel *panel)
+{
+ char *sessionfile = alloca(sizeof(char)*255);
+
+ int i = 0;
+ MBPanelApp *papp = NULL;
+ MBPanelApp *papp_heads[] = { panel->apps_start_head,
+ panel->apps_end_head };
+
+ DBG("%s() called\n", __func__);
+
+ if (!panel->use_session
+ || session_preexisting_restarting(panel))
+ return;
+
+ if (getenv("HOME") == NULL)
+ {
+ fprintf(stderr, "mbdock: unable to get home directory, is HOME set?\n");
+ return;
+ }
+
+ if (panel->system_tray_id)
+ snprintf(sessionfile, 255, "%s/.matchbox/%s.%i", getenv("HOME"),
+ PANELFILE, panel->system_tray_id );
+ else
+ snprintf(sessionfile, 255, "%s/.matchbox/%s",
+ getenv("HOME"), PANELFILE );
+
+ if ((panel->session_fp = fopen(sessionfile, "w")) == NULL)
+ {
+ fprintf(stderr,"mbdock: Unable to create Session file ( %s )\n",
+ sessionfile);
+ return;
+ }
+
+ DBG("%s() still called\n", __func__);
+
+ while (i < 2)
+ {
+ papp = papp_heads[i];
+ while( papp != NULL )
+ {
+ DBG("%s() writing %s\n", __func__, papp->cmd_str);
+ if (papp->cmd_str)
+ {
+ DBG("%s() writing %s\n", __func__, papp->cmd_str);
+ fprintf(panel->session_fp, "%s\n", papp->cmd_str);
+ }
+ papp = papp->next;
+ }
+ fprintf(panel->session_fp, "\t\n" );
+ i++;
+ }
+
+ fclose(panel->session_fp);
+}
+
+Bool
+session_preexisting_restarting(MBPanel *panel)
+{
+ return panel->session_preexisting_lock;
+}
+
+Bool
+session_preexisting_start_next(MBPanel *panel)
+{
+ if (!session_preexisting_restarting(panel)) return False;
+
+ if (panel->session_entry_cur[0] == '\0'
+ && session_preexisting_get_next(panel))
+ {
+ DBG("%s() starting %s\n", __func__, panel->session_entry_cur);
+ panel->session_needed_pid = util_fork_exec(panel->session_entry_cur);
+ return True;
+ }
+ return False;
+}
+
+Bool
+session_preexisting_win_matches_wanted(MBPanel *panel, Window win,
+ char *win_cmd)
+{
+ pid_t win_pid = 0;
+ if (!session_preexisting_restarting(panel)) return False;
+
+ DBG("%s() called\n", __func__);
+
+ if (panel->session_entry_cur) /* what were waiting on */
+ {
+ /* Check if its got the pid we expect */
+ win_pid = util_get_window_pid_from_prop(panel, win);
+
+ DBG("%s() win pid is %i\n", __func__, win_pid);
+
+ if (win_pid && win_pid == panel->session_needed_pid)
+ return True;
+
+ DBG("%s() pid failed, comparing '%s' vs '%s'\n", __func__,
+ win_cmd, panel->session_entry_cur );
+
+ /* check cmd str */
+ if (win_cmd && !strncmp(win_cmd, panel->session_entry_cur,
+ strlen(win_cmd)))
+ return True;
+ }
+
+ return False;
+}
+
+void
+session_preexisting_clear_current(MBPanel *panel)
+{
+ panel->session_entry_cur[0] = '\0';
+}
+
+Bool
+session_preexisting_handle_timeouts(MBPanel *panel)
+{
+ if (!session_preexisting_restarting(panel)) return False;
+
+ DBG("%s() called\n", __func__);
+
+ /* catch session timeouts */
+ if (panel->session_entry_cur[0] != '\0')
+ {
+ if ( (time(NULL)-panel->session_start_time) > SESSION_TIMEOUT)
+ {
+ fprintf(stderr, "Session timeout on %s\n", panel->session_entry_cur);
+ session_preexisting_clear_current(panel);
+ session_preexisting_start_next(panel);
+ }
+ }
+ return True;
+}
+
+Bool
+session_preexisting_get_next(MBPanel *panel) /* session_restarting_get_next */
+{
+ char *tmp;
+
+ if (!session_preexisting_restarting(panel)) return False;
+
+ panel->session_init_offset = 10;
+
+ if (panel->session_run_first_time)
+ {
+ if (*panel->session_defaults_cur_pos != '\0')
+ {
+ char *prev_pos = panel->session_defaults_cur_pos;
+ while ( *panel->session_defaults_cur_pos != '\0')
+ {
+ if ( *panel->session_defaults_cur_pos == ',')
+ {
+ *panel->session_defaults_cur_pos = '\0';
+ panel->session_defaults_cur_pos++;
+ break;
+ }
+ panel->session_defaults_cur_pos++;
+ }
+
+ strncpy(panel->session_entry_cur, prev_pos, 512);
+ }
+ else
+ {
+ panel->session_run_first_time = False;
+ panel->session_preexisting_lock = False;
+ session_save(panel);
+ return False;
+ }
+ }
+ else
+ {
+
+ if (fgets(panel->session_entry_cur, 512, panel->session_fp) == NULL)
+ {
+ fclose(panel->session_fp); /* All sessions done */
+ panel->session_preexisting_lock = False;
+ session_save(panel);
+ return False;
+ }
+
+ /* tab + newline -> change the session gravity */
+ if (!strcmp(panel->session_entry_cur, "\t\n"))
+ {
+ panel->session_cur_gravity = PAPP_GRAVITY_END;
+ return session_preexisting_get_next(panel);
+ }
+
+ if ( panel->session_entry_cur[strlen(panel->session_entry_cur)-1] == '\n')
+ panel->session_entry_cur[strlen(panel->session_entry_cur)-1] = '\0';
+
+ if ( (tmp = strstr(panel->session_entry_cur, "\t\t")) != NULL )
+ {
+ panel->session_init_offset = atoi(tmp);
+ *tmp = '\0';
+ }
+ }
+
+ panel->session_start_time = time(NULL);
+ return True;
+}
diff --git a/src/session.h b/src/session.h
new file mode 100644
index 0000000..05b527b
--- /dev/null
+++ b/src/session.h
@@ -0,0 +1,37 @@
+#ifndef _HAVE_PANEL_SESSION_H
+#define _HAVE_PANEL_SESSION_H
+
+#include "panel.h"
+
+#ifdef DEBUG
+#define PANELFILE "mbdock.session.debug"
+#else
+#define PANELFILE "mbdock.session"
+#endif
+
+void
+session_destroy(MBPanel *panel);
+
+void
+session_set_defaults(MBPanel *panel, char *defaults);
+
+void session_init(MBPanel *panel);
+
+void session_save(MBPanel *panel);
+
+Bool session_preexisting_restarting(MBPanel *panel);
+
+Bool session_preexisting_start_next(MBPanel *panel);;
+
+Bool session_preexisting_win_matches_wanted(MBPanel *panel, Window win,
+ char *win_cmd);
+
+void session_preexisting_clear_current(MBPanel *panel);
+
+Bool session_preexisting_handle_timeouts(MBPanel *panel);
+
+Bool session_preexisting_get_next(MBPanel *panel);
+
+
+
+#endif