Merge branch 'master' of git://git.openbox.org/dana/openbox
authorMikael Magnusson <mikachu@gmail.com>
Tue, 3 Mar 2015 21:37:21 +0000 (22:37 +0100)
committerMikael Magnusson <mikachu@gmail.com>
Tue, 3 Mar 2015 21:37:21 +0000 (22:37 +0100)
98 files changed:
.gitignore
AUTHORS
CHANGELOG
Makefile.am
configure.ac
data/gnome-session/openbox-gnome-fallback.session
data/gnome-session/openbox-gnome.session
data/rc.xsd
obrender/button.c
obrender/color.c
obrender/font.c
obrender/image.c
obrender/render.h
obrender/theme.c
obrender/theme.h
obt/bsearch.h
obt/bsearch_unittest.c [new file with mode: 0644]
obt/keyboard.c
obt/unittest_base.c [new file with mode: 0644]
obt/unittest_base.h [new file with mode: 0644]
obt/xml.c
openbox/actions/desktop.c
openbox/actions/growtoedge.c
openbox/actions/if.c
openbox/actions/resize.c
openbox/actions/showdesktop.c
openbox/actions/showmenu.c
openbox/client.c
openbox/client.h
openbox/client_menu.c
openbox/config.c
openbox/config.h
openbox/dock.c
openbox/event.c
openbox/frame.c
openbox/frame.h
openbox/framerender.c
openbox/keyboard.c
openbox/menu.c
openbox/menu.h
openbox/menuframe.c
openbox/menuframe.h
openbox/mouse.c
openbox/moveresize.c
openbox/openbox.c
openbox/place.c
openbox/place.h
openbox/place_overlap.c
openbox/screen.c
openbox/screen.h
openbox/stacking.c
openbox/stacking.h
po/LINGUAS
po/af.po
po/ar.po
po/be.po
po/bn_IN.po
po/ca.po
po/cs.po
po/da.po
po/de.po
po/el.po
po/en@boldquot.po
po/en@quot.po
po/es.po
po/et.po
po/eu.po
po/fi.po
po/fr.po
po/gl_ES.po [new file with mode: 0644]
po/he.po
po/hr.po
po/hu.po
po/ia.po
po/it.po
po/ja.po
po/lt.po
po/lv.po
po/nl.po
po/no.po
po/openbox.pot
po/pl.po
po/pt.po
po/pt_BR.po
po/ro.po
po/ru.po
po/sk.po
po/sr.po
po/sr@latin.po
po/sv.po
po/tr.po
po/uk.po
po/vi.po
po/zh_CN.po
po/zh_TW.po
release/email
release/go
tools/obxprop/obxprop.c

index 18e96d0..615af3b 100644 (file)
@@ -5,6 +5,7 @@ Makefile.in
 aclocal.m4
 autom4te.cache
 compile
+config.cache
 config.guess
 config.log
 config.rpath
@@ -107,3 +108,4 @@ obt/tests/bstest
 obt/tests/ddtest
 obt/tests/linktest
 obt/tests/watchtest
+obt/obt_unittests
diff --git a/AUTHORS b/AUTHORS
index b00cb38..1a3e3bf 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,6 +1,6 @@
 Openbox authors/contributors:
 
-Mikael Magnusson (mikachu@comhem.se)
+Mikael Magnusson (mikachu@icculus.org)
  - Developer
 Dana Jansens (danakj@orodu.net)
  - Lead developer
index 65be74d..0549853 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,34 @@
+3.6:
+  * Added various new abilities to If action, including the <query> tag,
+    matching class, name, role and window type.
+  * Added ForEach action.
+  * Restore the <center> option for window placement.
+  * New GrowToFill action.
+  * Updated Portuguese and Polish translations.
+  * New Galician translation.
+  * Added strict option to ToggleShowDesktop action.
+  * Speed optimization in rendering code.
+  * New <position> tag for ShowMenu action allows placing menus other
+    than at the mouse cursor.
+  * Fix some corner cases of relative position to work correctly.
+  * Allow specifying multiple mousebinds in one tag as we already do
+    for keybinds (separated by spaces, as "W-Return M-S-F3" for example).
+  * Added option rebindOnMappingNotify option, on by default, which
+    controls if we update binds when the keyboard layout changes at runtime.
+  * The resize action now only considers the part of the client that is onscreen
+    for purposes of picking an action to perform.
+  * Make desktop actions non-interactive (means you can have more actions bound
+    to a key after them, and the dialog disappears on a timer instead of when
+    releasing the modifier keys).
+  * obxprop is now not pathologically slow when printing very long arrays.
+  * Fix menu accelerator underlines sometimes not showing up.
+  * Fix so you can click menu entries before the menuHideDelay expires if it's
+    a new click.
+  * Don't readd the X event fd to the poll set every time we reconfigure.
+  * Fix some specialized button bitmaps not loading from the correct files.
+    (toggled + pressed or hover would just be the base toggled image).
+  * Various small bugfixes.
+
 3.5.2:
   * Fix crash in theme rendering code, and in theme parsing code.
   * Maximize windows without borders to fill the whole screen, don't leave
index c29e042..b438904 100644 (file)
@@ -36,6 +36,9 @@ bin_PROGRAMS = \
        tools/gnome-panel-control/gnome-panel-control \
        tools/obxprop/obxprop
 
+noinst_PROGRAMS = \
+       obt/obt_unittests
+
 nodist_bin_SCRIPTS = \
        data/xsession/openbox-session \
        data/xsession/openbox-gnome-session \
@@ -308,6 +311,21 @@ openbox_openbox_SOURCES = \
        openbox/window.c \
        openbox/window.h
 
+## obt_unittests ##
+
+obt_obt_unittests_CPPFLAGS = \
+       $(GLIB_CFLAGS) \
+       -DLOCALEDIR=\"$(localedir)\" \
+       -DDATADIR=\"$(datadir)\" \
+       -DCONFIGDIR=\"$(configdir)\" \
+       -DG_LOG_DOMAIN=\"Obt-Unittests\"
+obt_obt_unittests_LDADD = \
+       $(GLIB_LIBS) \
+       obt/libobt.la
+obt_obt_unittests_LDFLAGS = -export-dynamic
+obt_obt_unittests_SOURCES = \
+       obt/unittest_base.c \
+       obt/bsearch_unittest.c
 
 ## gnome-panel-control ##
 
index 33fc6d9..9b95158 100644 (file)
@@ -9,14 +9,24 @@ OB_VERSION=$PACKAGE_VERSION
 AC_SUBST(OB_VERSION)
 
 dnl Making releases:
+dnl RR_ is for obrender, OBT_ is for obt, keep major/minor in sync,
+dnl treat the rest separately.
+dnl
+dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match.
+dnl the other variables aren't related to the user visible versions, but are used
+dnl to version the .so files.
+dnl if no backward compat is broken, it's just a preference if you want to bump
+dnl the AC_INIT micro version or minor version. if the AC_INIT micro version is
+dnl 0, don't write it out.
+dnl
+dnl How to process .so versioning,
 dnl   RR_MICRO_VERSION += 1;
 dnl   RR_INTERFACE_AGE += 1;
-dnl   R_BINARY_AGE += 1;
+dnl   RR_BINARY_AGE += 1;
 dnl if any functions have been added, set RR_INTERFACE_AGE to 0.
 dnl if backwards compatibility has been broken,
 dnl set RR_BINARY_AGE and RR_INTERFACE_AGE to 0.
-dnl
-dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
+dnl if you set anything to 0, you should also bump the MINOR version.
 dnl
 RR_MAJOR_VERSION=3
 RR_MINOR_VERSION=5
index 156f2c3..0909fa7 100644 (file)
@@ -1,6 +1,4 @@
 [GNOME Session]
 Name=GNOME/Openbox fallback (Safe Mode)
-RequiredComponents=gnome-settings-daemon;
-RequiredProviders=windowmanager;
-DefaultProvider-windowmanager=openbox
+RequiredComponents=openbox;gnome-settings-daemon
 DesktopName=GNOME
index 3399c2c..ffeccdb 100644 (file)
@@ -1,9 +1,4 @@
 [GNOME Session]
 Name=GNOME/Openbox
-RequiredComponents=gnome-settings-daemon;
-# Try load with the gnome-panel and use the fallback if we can't load a panel
-RequiredProviders=windowmanager;panel
-DefaultProvider-windowmanager=openbox
-DefaultProvider-panel=gnome-panel
-FallbackSession=openbox-gnome-fallback
+RequiredComponents=openbox;gnome-settings-daemon;gnome-panel;nautilus-classic;gnome-flashback-services
 DesktopName=GNOME
index 75dd660..c8f5638 100644 (file)
             <xsd:element minOccurs="0" name="here" type="ob:bool"/>
             <xsd:element minOccurs="0" name="linear" type="ob:bool"/>
             <xsd:element minOccurs="0" name="group" type="ob:bool"/>
+            <xsd:element minOccurs="0" name="strict" type="ob:bool"/>
         </xsd:all>
         <xsd:attribute name="name" type="ob:actionname" use="required"/>
     </xsd:complexType>
index 35437af..faf83e0 100644 (file)
@@ -29,49 +29,25 @@ RrButton *RrButtonNew (const RrInstance *inst)
 {
     RrButton *out = NULL;
 
-    out = g_new(RrButton, 1);
+    /* no need to alloc colors and masks, set them null (for freeing later) */
+    out = g_new0(RrButton, 1);
     out->inst = inst;
 
-    /* no need to alloc colors, set them null (for freeing later) */
-    out->focused_unpressed_color = NULL;
-    out->unfocused_unpressed_color = NULL;
-    out->focused_pressed_color = NULL;
-    out->unfocused_pressed_color = NULL;
-    out->disabled_focused_color = NULL;
-    out->disabled_unfocused_color = NULL;
-    out->hover_focused_color = NULL;
-    out->hover_unfocused_color = NULL;
-    out->toggled_hover_focused_color = NULL;
-    out->toggled_hover_unfocused_color = NULL;
-    out->toggled_focused_pressed_color = NULL;
-    out->toggled_unfocused_pressed_color = NULL;
-    out->toggled_focused_unpressed_color = NULL;
-    out->toggled_unfocused_unpressed_color = NULL;
-
-    /* same with masks */
-    out->mask = NULL;
-    out->pressed_mask = NULL;
-    out->disabled_mask = NULL;
-    out->hover_mask = NULL;
-    out->toggled_mask = NULL;
-    out->toggled_hover_mask = NULL;
-    out->toggled_pressed_mask = NULL;
-
     /* allocate appearances */
     out->a_focused_unpressed = RrAppearanceNew(inst, 1);
     out->a_unfocused_unpressed = RrAppearanceNew(inst, 1);
     out->a_focused_pressed = RrAppearanceNew(inst, 1);
     out->a_unfocused_pressed = RrAppearanceNew(inst, 1);
-    out->a_disabled_focused = RrAppearanceNew(inst, 1);
-    out->a_disabled_unfocused = RrAppearanceNew(inst, 1);
-    out->a_hover_focused = RrAppearanceNew(inst, 1);
-    out->a_hover_unfocused = RrAppearanceNew(inst, 1);
-    out->a_toggled_focused_unpressed = RrAppearanceNew(inst, 1);
-    out->a_toggled_unfocused_unpressed = RrAppearanceNew(inst, 1);
-    out->a_toggled_focused_pressed = RrAppearanceNew(inst, 1);
-    out->a_toggled_unfocused_pressed = RrAppearanceNew(inst, 1);
-    out->a_toggled_hover_focused = RrAppearanceNew(inst, 1);
-    out->a_toggled_hover_unfocused = RrAppearanceNew(inst, 1);
+    out->a_focused_disabled = RrAppearanceNew(inst, 1);
+    out->a_unfocused_disabled = RrAppearanceNew(inst, 1);
+    out->a_focused_hover = RrAppearanceNew(inst, 1);
+    out->a_unfocused_hover = RrAppearanceNew(inst, 1);
+    out->a_focused_unpressed_toggled = RrAppearanceNew(inst, 1);
+    out->a_unfocused_unpressed_toggled = RrAppearanceNew(inst, 1);
+    out->a_focused_pressed_toggled = RrAppearanceNew(inst, 1);
+    out->a_unfocused_pressed_toggled = RrAppearanceNew(inst, 1);
+    out->a_focused_hover_toggled = RrAppearanceNew(inst, 1);
+    out->a_unfocused_hover_toggled = RrAppearanceNew(inst, 1);
 
     return out;
 }
@@ -79,57 +55,43 @@ RrButton *RrButtonNew (const RrInstance *inst)
 void RrButtonFree(RrButton *b)
 {
     /* colors */
-    if (b->focused_unpressed_color) 
-        RrColorFree(b->focused_unpressed_color);
-    if (b->unfocused_unpressed_color) 
-        RrColorFree(b->unfocused_unpressed_color);
-    if (b->focused_pressed_color) 
-        RrColorFree(b->focused_pressed_color);
-    if (b->unfocused_pressed_color) 
-        RrColorFree(b->unfocused_pressed_color);
-    if (b->disabled_focused_color) 
-        RrColorFree(b->disabled_focused_color);
-    if (b->disabled_unfocused_color) 
-        RrColorFree(b->disabled_unfocused_color);
-    if (b->hover_focused_color) 
-        RrColorFree(b->hover_focused_color);
-    if (b->hover_unfocused_color) 
-        RrColorFree(b->hover_unfocused_color);
-    if (b->toggled_hover_focused_color) 
-        RrColorFree(b->toggled_hover_focused_color);
-    if (b->toggled_hover_unfocused_color) 
-        RrColorFree(b->toggled_hover_unfocused_color);
-    if (b->toggled_focused_pressed_color) 
-        RrColorFree(b->toggled_focused_pressed_color);
-    if (b->toggled_unfocused_pressed_color) 
-        RrColorFree(b->toggled_unfocused_pressed_color);
-    if (b->toggled_focused_unpressed_color) 
-        RrColorFree(b->toggled_focused_unpressed_color);
-    if (b->toggled_unfocused_unpressed_color) 
-        RrColorFree(b->toggled_unfocused_unpressed_color);
+    RrColorFree(b->focused_unpressed_color);
+    RrColorFree(b->unfocused_unpressed_color);
+    RrColorFree(b->focused_pressed_color);
+    RrColorFree(b->unfocused_pressed_color);
+    RrColorFree(b->focused_disabled_color);
+    RrColorFree(b->unfocused_disabled_color);
+    RrColorFree(b->focused_hover_color);
+    RrColorFree(b->unfocused_hover_color);
+    RrColorFree(b->focused_hover_toggled_color);
+    RrColorFree(b->unfocused_hover_toggled_color);
+    RrColorFree(b->focused_pressed_toggled_color);
+    RrColorFree(b->unfocused_pressed_toggled_color);
+    RrColorFree(b->focused_unpressed_toggled_color);
+    RrColorFree(b->unfocused_unpressed_toggled_color);
 
     /* masks */
-    if (b->mask) RrPixmapMaskFree(b->mask);
-    if (b->pressed_mask) RrPixmapMaskFree(b->pressed_mask);
-    if (b->disabled_mask) RrPixmapMaskFree(b->disabled_mask);
-    if (b->hover_mask) RrPixmapMaskFree(b->hover_mask);
-    if (b->toggled_mask) RrPixmapMaskFree(b->toggled_mask);
-    if (b->toggled_hover_mask) RrPixmapMaskFree(b->toggled_hover_mask);
-    if (b->toggled_pressed_mask) RrPixmapMaskFree(b->toggled_pressed_mask);
+    RrPixmapMaskFree(b->unpressed_mask);
+    RrPixmapMaskFree(b->pressed_mask);
+    RrPixmapMaskFree(b->disabled_mask);
+    RrPixmapMaskFree(b->hover_mask);
+    RrPixmapMaskFree(b->unpressed_toggled_mask);
+    RrPixmapMaskFree(b->hover_toggled_mask);
+    RrPixmapMaskFree(b->pressed_toggled_mask);
 
     /* appearances */
     RrAppearanceFree(b->a_focused_unpressed);
     RrAppearanceFree(b->a_unfocused_unpressed);
     RrAppearanceFree(b->a_focused_pressed);
     RrAppearanceFree(b->a_unfocused_pressed);
-    RrAppearanceFree(b->a_disabled_focused);
-    RrAppearanceFree(b->a_disabled_unfocused);
-    RrAppearanceFree(b->a_hover_focused);
-    RrAppearanceFree(b->a_hover_unfocused);
-    RrAppearanceFree(b->a_toggled_focused_unpressed);
-    RrAppearanceFree(b->a_toggled_unfocused_unpressed);
-    RrAppearanceFree(b->a_toggled_focused_pressed);
-    RrAppearanceFree(b->a_toggled_unfocused_pressed);
-    RrAppearanceFree(b->a_toggled_hover_focused);
-    RrAppearanceFree(b->a_toggled_hover_unfocused);
+    RrAppearanceFree(b->a_focused_disabled);
+    RrAppearanceFree(b->a_unfocused_disabled);
+    RrAppearanceFree(b->a_focused_hover);
+    RrAppearanceFree(b->a_unfocused_hover);
+    RrAppearanceFree(b->a_focused_unpressed_toggled);
+    RrAppearanceFree(b->a_unfocused_unpressed_toggled);
+    RrAppearanceFree(b->a_focused_pressed_toggled);
+    RrAppearanceFree(b->a_unfocused_pressed_toggled);
+    RrAppearanceFree(b->a_focused_hover_toggled);
+    RrAppearanceFree(b->a_unfocused_hover_toggled);
 }
index 221ebc4..4295367 100644 (file)
@@ -126,22 +126,26 @@ void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
 {
     gint r, g, b;
     gint x,y;
+    gint ro = RrRedOffset(inst);
+    gint bo = RrBlueOffset(inst);
+    gint go = RrGreenOffset(inst);
+    gint rs = RrRedShift(inst);
+    gint bs = RrBlueShift(inst);
+    gint gs = RrGreenShift(inst);
     RrPixel32 *p32 = (RrPixel32 *) im->data;
     RrPixel16 *p16 = (RrPixel16 *) im->data;
     RrPixel8  *p8  = (RrPixel8 *)  im->data;
     switch (im->bits_per_pixel) {
     case 32:
-        if ((RrRedOffset(inst) != RrDefaultRedOffset) ||
-            (RrBlueOffset(inst) != RrDefaultBlueOffset) ||
-            (RrGreenOffset(inst) != RrDefaultGreenOffset)) {
+        if ((ro != RrDefaultRedOffset) ||
+            (bo != RrDefaultBlueOffset) ||
+            (go != RrDefaultGreenOffset)) {
             for (y = 0; y < im->height; y++) {
                 for (x = 0; x < im->width; x++) {
                     r = (data[x] >> RrDefaultRedOffset) & 0xFF;
                     g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
                     b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
-                    p32[x] = (r << RrRedOffset(inst))
-                           + (g << RrGreenOffset(inst))
-                           + (b << RrBlueOffset(inst));
+                    p32[x] = (r << ro) + (g << go) + (b << bo);
                 }
                 data += im->width;
                 p32 += im->width;
@@ -152,9 +156,9 @@ void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
     {
         /* reverse the ordering, shifting left 16bit should be the first byte
            out of three, etc */
-        const guint roff = (16 - RrRedOffset(inst)) / 8;
-        const guint goff = (16 - RrGreenOffset(inst)) / 8;
-        const guint boff = (16 - RrBlueOffset(inst)) / 8;
+        const guint roff = (16 - ro) / 8;
+        const guint goff = (16 - go) / 8;
+        const guint boff = (16 - bo) / 8;
         gint outx;
         for (y = 0; y < im->height; y++) {
             for (x = 0, outx = 0; x < im->width; x++, outx += 3) {
@@ -174,14 +178,12 @@ void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
         for (y = 0; y < im->height; y++) {
             for (x = 0; x < im->width; x++) {
                 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
-                r = r >> RrRedShift(inst);
+                r = r >> rs;
                 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
-                g = g >> RrGreenShift(inst);
+                g = g >> gs;
                 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
-                b = b >> RrBlueShift(inst);
-                p16[x] = (r << RrRedOffset(inst))
-                       + (g << RrGreenOffset(inst))
-                       + (b << RrBlueOffset(inst));
+                b = b >> bs;
+                p16[x] = (r << ro) + (g << go) + (b << bo);
             }
             data += im->width;
             p16 += im->bytes_per_line/2;
@@ -192,14 +194,12 @@ void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
             for (y = 0; y < im->height; y++) {
                 for (x = 0; x < im->width; x++) {
                     r = (data[x] >> RrDefaultRedOffset) & 0xFF;
-                    r = r >> RrRedShift(inst);
+                    r = r >> rs;
                     g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
-                    g = g >> RrGreenShift(inst);
+                    g = g >> gs;
                     b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
-                    b = b >> RrBlueShift(inst);
-                    p8[x] = (r << RrRedOffset(inst))
-                        + (g << RrGreenOffset(inst))
-                        + (b << RrBlueOffset(inst));
+                    b = b >> bs;
+                    p8[x] = (r << ro) + (g << go) + (b << bo);
                 }
                 data += im->width;
                 p8 += im->bytes_per_line;
@@ -239,7 +239,7 @@ static void swap_byte_order(XImage *im)
 
     di = 0;
     for (y = 0; y < im->height; ++y) {
-        for (x = 0; x < im->height; ++x) {
+        for (x = 0; x < im->width; ++x) {
             gchar *c = &im->data[di + x * im->bits_per_pixel / 8];
             gchar t;
 
index a22e23f..0f56a55 100644 (file)
@@ -73,7 +73,7 @@ RrFont *RrFontOpen(const RrInstance *inst, const gchar *name, gint size,
     out->ref = 1;
     out->font_desc = pango_font_description_new();
     out->layout = pango_layout_new(inst->pango);
-    out->shortcut_underline = pango_attr_underline_new(PANGO_UNDERLINE_LOW);
+    out->shortcut_underline = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
     out->shortcut_underline->start_index = 0;
     out->shortcut_underline->end_index = 0;
 
index 8ff9bf1..fb5f40b 100644 (file)
@@ -243,7 +243,7 @@ RrImageSet* RrImageSetMergeSets(RrImageSet *b, RrImageSet *a)
     gint n_original, n_resized, tmp;
     GSList *it;
 
-    const gint max_resized = a->cache->max_resized_saved;
+    gint max_resized;
 
     if (!a)
         return b;
@@ -251,7 +251,6 @@ RrImageSet* RrImageSetMergeSets(RrImageSet *b, RrImageSet *a)
         return a;
     if (a == b)
         return b;
-
     /* the original and resized picture lists in an RrImageSet are kept ordered
        as newest to oldest.  we don't have timestamps for them, so we cannot
        preserve this in the merged RrImageSet exactly.  a decent approximation,
@@ -264,6 +263,8 @@ RrImageSet* RrImageSetMergeSets(RrImageSet *b, RrImageSet *a)
 
     g_assert(b->cache == a->cache);
 
+    max_resized = a->cache->max_resized_saved;
+
     a_i = b_i = merged_i = 0;
     n_original = a->n_original + b->n_original;
     original = g_new(RrImagePic*, n_original);
index 59e7766..f125847 100644 (file)
@@ -295,41 +295,41 @@ struct _RrButton {
     RrColor *unfocused_unpressed_color;
     RrColor *focused_pressed_color;
     RrColor *unfocused_pressed_color;
-    RrColor *disabled_focused_color;
-    RrColor *disabled_unfocused_color;
-    RrColor *hover_focused_color;
-    RrColor *hover_unfocused_color;
-    RrColor *toggled_hover_focused_color;
-    RrColor *toggled_hover_unfocused_color;
-    RrColor *toggled_focused_pressed_color;
-    RrColor *toggled_unfocused_pressed_color;
-    RrColor *toggled_focused_unpressed_color;
-    RrColor *toggled_unfocused_unpressed_color;
+    RrColor *focused_disabled_color;
+    RrColor *unfocused_disabled_color;
+    RrColor *focused_hover_color;
+    RrColor *unfocused_hover_color;
+    RrColor *focused_hover_toggled_color;
+    RrColor *unfocused_hover_toggled_color;
+    RrColor *focused_pressed_toggled_color;
+    RrColor *unfocused_pressed_toggled_color;
+    RrColor *focused_unpressed_toggled_color;
+    RrColor *unfocused_unpressed_toggled_color;
     
     /* masks */
-    RrPixmapMask *mask;
+    RrPixmapMask *unpressed_mask;
     RrPixmapMask *pressed_mask;
     RrPixmapMask *disabled_mask;
     RrPixmapMask *hover_mask;
-    RrPixmapMask *toggled_mask;
-    RrPixmapMask *toggled_hover_mask;
-    RrPixmapMask *toggled_pressed_mask;
+    RrPixmapMask *unpressed_toggled_mask;
+    RrPixmapMask *hover_toggled_mask;
+    RrPixmapMask *pressed_toggled_mask;
    
     /* textures */
     RrAppearance *a_focused_unpressed;
     RrAppearance *a_unfocused_unpressed;
     RrAppearance *a_focused_pressed;
     RrAppearance *a_unfocused_pressed;
-    RrAppearance *a_disabled_focused;
-    RrAppearance *a_disabled_unfocused;
-    RrAppearance *a_hover_focused;
-    RrAppearance *a_hover_unfocused;
-    RrAppearance *a_toggled_focused_unpressed;
-    RrAppearance *a_toggled_unfocused_unpressed;
-    RrAppearance *a_toggled_focused_pressed;
-    RrAppearance *a_toggled_unfocused_pressed;
-    RrAppearance *a_toggled_hover_focused;
-    RrAppearance *a_toggled_hover_unfocused;
+    RrAppearance *a_focused_disabled;
+    RrAppearance *a_unfocused_disabled;
+    RrAppearance *a_focused_hover;
+    RrAppearance *a_unfocused_hover;
+    RrAppearance *a_focused_unpressed_toggled;
+    RrAppearance *a_unfocused_unpressed_toggled;
+    RrAppearance *a_focused_pressed_toggled;
+    RrAppearance *a_unfocused_pressed_toggled;
+    RrAppearance *a_focused_hover_toggled;
+    RrAppearance *a_unfocused_hover_toggled;
 
 };
 
index 87ca5c8..2a4f6e1 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+struct fallbacks {
+    RrAppearance *focused_disabled;
+    RrAppearance *unfocused_disabled;
+    RrAppearance *focused_hover;
+    RrAppearance *unfocused_hover;
+    RrAppearance *focused_unpressed;
+    RrAppearance *focused_pressed;
+    RrAppearance *unfocused_unpressed;
+    RrAppearance *unfocused_pressed;
+    RrAppearance *focused_hover_toggled;
+    RrAppearance *unfocused_hover_toggled;
+    RrAppearance *focused_unpressed_toggled;
+    RrAppearance *focused_pressed_toggled;
+    RrAppearance *unfocused_unpressed_toggled;
+    RrAppearance *unfocused_pressed_toggled;
+};
+
 static XrmDatabase loaddb(const gchar *name, gchar **path);
 static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
 static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
                            const gchar *rname, RrColor **value);
 static gboolean read_mask(const RrInstance *inst, const gchar *path,
-                          RrTheme *theme, const gchar *maskname,
-                          RrPixmapMask **value);
+                          const gchar *maskname, RrPixmapMask **value);
 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
                                 const gchar *rname, RrAppearance *value,
                                 gboolean allow_trans);
 static int parse_inline_number(const char *p);
 static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
 static void set_default_appearance(RrAppearance *a);
-static void read_button_colors(XrmDatabase db, const RrInstance *inst, 
+static void read_button_styles(XrmDatabase db, const RrInstance *inst, 
+                               gchar *path,
                                const RrTheme *theme, RrButton *btn, 
-                               const gchar *btnname);
+                               const gchar *btnname,
+                               struct fallbacks *fbs,
+                               guchar *normal_mask,
+                               guchar *toggled_mask);
 
 static RrFont *get_font(RrFont *target, RrFont **default_font,
                         const RrInstance *inst)
@@ -81,7 +101,7 @@ static RrFont *get_font(RrFont *target, RrFont **default_font,
         x_var = x_def;
 
 #define READ_MASK_COPY(x_file, x_var, x_copysrc) \
-    if (!read_mask(inst, path, theme, x_file, & x_var)) \
+    if (!read_mask(inst, path, x_file, & x_var)) \
         x_var = RrPixmapMaskCopy(x_copysrc);
 
 #define READ_APPEARANCE(x_resstr, x_var, x_parrel) \
@@ -118,22 +138,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     RrTheme *theme;
     RrFont *default_font = NULL;
     gchar *path;
-    gboolean userdef;
     gint menu_overlap = 0;
-    RrAppearance *a_disabled_focused_tmp;
-    RrAppearance *a_disabled_unfocused_tmp;
-    RrAppearance *a_hover_focused_tmp;
-    RrAppearance *a_hover_unfocused_tmp;
-    RrAppearance *a_focused_unpressed_tmp;
-    RrAppearance *a_focused_pressed_tmp;
-    RrAppearance *a_unfocused_unpressed_tmp;
-    RrAppearance *a_unfocused_pressed_tmp;
-    RrAppearance *a_toggled_hover_focused_tmp;
-    RrAppearance *a_toggled_hover_unfocused_tmp;
-    RrAppearance *a_toggled_focused_unpressed_tmp;
-    RrAppearance *a_toggled_focused_pressed_tmp;
-    RrAppearance *a_toggled_unfocused_unpressed_tmp;
-    RrAppearance *a_toggled_unfocused_pressed_tmp;
+    struct fallbacks fbs;
 
     if (name) {
         db = loaddb(name, &path);
@@ -158,20 +164,20 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     }
 
     /* initialize temp reading textures */
-    a_disabled_focused_tmp = RrAppearanceNew(inst, 1);
-    a_disabled_unfocused_tmp = RrAppearanceNew(inst, 1);
-    a_hover_focused_tmp = RrAppearanceNew(inst, 1);
-    a_hover_unfocused_tmp = RrAppearanceNew(inst, 1);
-    a_toggled_focused_unpressed_tmp = RrAppearanceNew(inst, 1);
-    a_toggled_unfocused_unpressed_tmp = RrAppearanceNew(inst, 1);
-    a_toggled_hover_focused_tmp = RrAppearanceNew(inst, 1);
-    a_toggled_hover_unfocused_tmp = RrAppearanceNew(inst, 1);
-    a_toggled_focused_pressed_tmp = RrAppearanceNew(inst, 1);
-    a_toggled_unfocused_pressed_tmp = RrAppearanceNew(inst, 1);
-    a_focused_unpressed_tmp = RrAppearanceNew(inst, 1);
-    a_focused_pressed_tmp = RrAppearanceNew(inst, 1);
-    a_unfocused_unpressed_tmp = RrAppearanceNew(inst, 1);
-    a_unfocused_pressed_tmp = RrAppearanceNew(inst, 1);
+    fbs.focused_disabled = RrAppearanceNew(inst, 1);
+    fbs.unfocused_disabled = RrAppearanceNew(inst, 1);
+    fbs.focused_hover = RrAppearanceNew(inst, 1);
+    fbs.unfocused_hover = RrAppearanceNew(inst, 1);
+    fbs.focused_unpressed_toggled = RrAppearanceNew(inst, 1);
+    fbs.unfocused_unpressed_toggled = RrAppearanceNew(inst, 1);
+    fbs.focused_hover_toggled = RrAppearanceNew(inst, 1);
+    fbs.unfocused_hover_toggled = RrAppearanceNew(inst, 1);
+    fbs.focused_pressed_toggled = RrAppearanceNew(inst, 1);
+    fbs.unfocused_pressed_toggled = RrAppearanceNew(inst, 1);
+    fbs.focused_unpressed = RrAppearanceNew(inst, 1);
+    fbs.focused_pressed = RrAppearanceNew(inst, 1);
+    fbs.unfocused_unpressed = RrAppearanceNew(inst, 1);
+    fbs.unfocused_pressed = RrAppearanceNew(inst, 1);
 
     /* initialize theme */
     theme = g_slice_new0(RrTheme);
@@ -259,74 +265,70 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     READ_INT("border.width", theme->fbwidth, 0, 100, 1);
     READ_INT("menu.border.width", theme->mbwidth, 0, 100, theme->fbwidth);
     READ_INT("osd.border.width", theme->obwidth, 0, 100, theme->fbwidth);
-    READ_INT("undecorated.border.width", theme->ubwidth, 0, 100,
-             theme->fbwidth);
+    READ_INT("undecorated.border.width", theme->ubwidth, 0, 100, theme->fbwidth);
     READ_INT("menu.separator.width", theme->menu_sep_width, 1, 100, 1);
-    READ_INT("menu.separator.padding.width", theme->menu_sep_paddingx,
-             0, 100, 6);
-    READ_INT("menu.separator.padding.height", theme->menu_sep_paddingy,
-             0, 100, 3);
-    READ_INT("window.client.padding.width", theme->cbwidthx, 0, 100,
-             theme->paddingx);
-    READ_INT("window.client.padding.height", theme->cbwidthy, 0, 100,
-             theme->cbwidthx);
+    READ_INT("menu.separator.padding.width", theme->menu_sep_paddingx, 0, 100, 6);
+    READ_INT("menu.separator.padding.height", theme->menu_sep_paddingy, 0, 100, 3);
+    READ_INT("window.client.padding.width", theme->cbwidthx, 0, 100, theme->paddingx);
+    READ_INT("window.client.padding.height", theme->cbwidthy, 0, 100, theme->cbwidthx);
 
     /* load colors */
-    READ_COLOR_("window.active.border.color", "border.color",
-                theme->frame_focused_border_color, RrColorNew(inst, 0, 0, 0));
-    /* undecorated focused border color inherits from frame focused border
-       color */
+    READ_COLOR_("window.active.border.color",
+                "border.color",
+                theme->frame_focused_border_color,
+                RrColorNew(inst, 0, 0, 0));
     READ_COLOR("window.undecorated.active.border.color",
                theme->frame_undecorated_focused_border_color,
                RrColorCopy(theme->frame_focused_border_color));
-    /* title separator focused color inherits from focused border color */
     READ_COLOR("window.active.title.separator.color",
                theme->title_separator_focused_color,
                RrColorCopy(theme->frame_focused_border_color));
 
-    /* unfocused border color inherits from frame focused border color */
     READ_COLOR("window.inactive.border.color",
                theme->frame_unfocused_border_color,
                RrColorCopy(theme->frame_focused_border_color));
 
-    /* undecorated unfocused border color inherits from frame unfocused border
-       color */
     READ_COLOR("window.undecorated.inactive.border.color",
                theme->frame_undecorated_unfocused_border_color,
                RrColorCopy(theme->frame_unfocused_border_color));
 
-    /* title separator unfocused color inherits from unfocused border color */
     READ_COLOR("window.inactive.title.separator.color",
                theme->title_separator_unfocused_color,
                RrColorCopy(theme->frame_unfocused_border_color));
 
-    /* menu border color inherits from frame focused border color */
-    READ_COLOR("menu.border.color", theme->menu_border_color,
+    READ_COLOR("menu.border.color",
+               theme->menu_border_color,
                RrColorCopy(theme->frame_focused_border_color));
 
-    /* osd border color inherits from frame focused border color */
-    READ_COLOR("osd.border.color", theme->osd_border_color,
+    READ_COLOR("osd.border.color", 
+               theme->osd_border_color,
                RrColorCopy(theme->frame_focused_border_color));
 
-    READ_COLOR("window.active.client.color", theme->cb_focused_color,
+    READ_COLOR("window.active.client.color",
+               theme->cb_focused_color,
                RrColorNew(inst, 0xff, 0xff, 0xff));
 
-    READ_COLOR("window.inactive.client.color", theme->cb_unfocused_color,
+    READ_COLOR("window.inactive.client.color",
+               theme->cb_unfocused_color,
                RrColorNew(inst, 0xff, 0xff, 0xff));
 
-    READ_COLOR("window.active.label.text.color", theme->title_focused_color,
+    READ_COLOR("window.active.label.text.color",
+               theme->title_focused_color,
                RrColorNew(inst, 0x0, 0x0, 0x0));
 
-    READ_COLOR("window.inactive.label.text.color", theme->title_unfocused_color,
+    READ_COLOR("window.inactive.label.text.color",
+               theme->title_unfocused_color,
                RrColorNew(inst, 0xff, 0xff, 0xff));
 
     READ_COLOR_("osd.active.label.text.color",
                 "osd.label.text.color",
-                theme->osd_text_active_color, RrColorCopy(theme->title_focused_color));
+                theme->osd_text_active_color,
+                RrColorCopy(theme->title_focused_color));
 
     READ_COLOR_("osd.inactive.label.text.color",
                 "osd.label.text.color",
-                theme->osd_text_inactive_color, RrColorCopy(theme->title_unfocused_color));
+                theme->osd_text_inactive_color,
+                RrColorCopy(theme->title_unfocused_color));
 
     READ_COLOR("window.active.button.unpressed.image.color",
                theme->titlebut_focused_unpressed_color,
@@ -345,189 +347,181 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
                RrColorCopy(theme->titlebut_unfocused_unpressed_color));
 
     READ_COLOR("window.active.button.disabled.image.color",
-               theme->titlebut_disabled_focused_color,
+               theme->titlebut_focused_disabled_color,
                RrColorNew(inst, 0xff, 0xff, 0xff));
 
     READ_COLOR("window.inactive.button.disabled.image.color",
-               theme->titlebut_disabled_unfocused_color,
+               theme->titlebut_unfocused_disabled_color,
                RrColorNew(inst, 0, 0, 0));
 
     READ_COLOR("window.active.button.hover.image.color",
-               theme->titlebut_hover_focused_color,
+               theme->titlebut_focused_hover_color,
                RrColorCopy(theme->titlebut_focused_unpressed_color));
 
     READ_COLOR("window.inactive.button.hover.image.color",
-               theme->titlebut_hover_unfocused_color,
+               theme->titlebut_unfocused_hover_color,
                RrColorCopy(theme->titlebut_unfocused_unpressed_color));
 
     READ_COLOR_("window.active.button.toggled.unpressed.image.color",
                 "window.active.button.toggled.image.color",
-                theme->titlebut_toggled_focused_unpressed_color,
+                theme->titlebut_focused_unpressed_toggled_color,
                 RrColorCopy(theme->titlebut_focused_pressed_color));
 
     READ_COLOR_("window.inactive.button.toggled.unpressed.image.color",
                 "window.inactive.button.toggled.image.color",
-                theme->titlebut_toggled_unfocused_unpressed_color,
+                theme->titlebut_unfocused_unpressed_toggled_color,
                 RrColorCopy(theme->titlebut_unfocused_pressed_color));
 
     READ_COLOR("window.active.button.toggled.hover.image.color",
-               theme->titlebut_toggled_hover_focused_color,
-               RrColorCopy(theme->titlebut_toggled_focused_unpressed_color));
+               theme->titlebut_focused_hover_toggled_color,
+               RrColorCopy(theme->titlebut_focused_unpressed_toggled_color));
 
     READ_COLOR("window.inactive.button.toggled.hover.image.color",
-               theme->titlebut_toggled_hover_unfocused_color,
-               RrColorCopy(theme->titlebut_toggled_unfocused_unpressed_color));
+               theme->titlebut_unfocused_hover_toggled_color,
+               RrColorCopy(theme->titlebut_unfocused_unpressed_toggled_color));
 
     READ_COLOR("window.active.button.toggled.pressed.image.color",
-               theme->titlebut_toggled_focused_pressed_color,
+               theme->titlebut_focused_pressed_toggled_color,
                RrColorCopy(theme->titlebut_focused_pressed_color));
 
     READ_COLOR("window.inactive.button.toggled.pressed.image.color",
-               theme->titlebut_toggled_unfocused_pressed_color,
+               theme->titlebut_unfocused_pressed_toggled_color,
                RrColorCopy(theme->titlebut_unfocused_pressed_color));
 
-    READ_COLOR("menu.title.text.color", theme->menu_title_color,
+    READ_COLOR("menu.title.text.color",
+               theme->menu_title_color,
                RrColorNew(inst, 0, 0, 0));
 
-    READ_COLOR("menu.items.text.color", theme->menu_color,
+    READ_COLOR("menu.items.text.color",
+               theme->menu_color,
                RrColorNew(inst, 0xff, 0xff, 0xff));
 
-    READ_COLOR("menu.bullet.image.color", theme->menu_bullet_color,
+    READ_COLOR("menu.bullet.image.color",
+               theme->menu_bullet_color,
                RrColorCopy(theme->menu_color));
    
-    READ_COLOR("menu.items.disabled.text.color", theme->menu_disabled_color,
+    READ_COLOR("menu.items.disabled.text.color",
+               theme->menu_disabled_color,
                RrColorNew(inst, 0, 0, 0));
 
     READ_COLOR("menu.items.active.disabled.text.color",
                theme->menu_disabled_selected_color,
                RrColorCopy(theme->menu_disabled_color));
 
-    READ_COLOR("menu.items.active.text.color", theme->menu_selected_color,
+    READ_COLOR("menu.items.active.text.color",
+               theme->menu_selected_color,
                RrColorNew(inst, 0, 0, 0));
 
-    READ_COLOR("menu.separator.color", theme->menu_sep_color,
+    READ_COLOR("menu.separator.color",
+               theme->menu_sep_color,
                RrColorCopy(theme->menu_color));
     
     READ_COLOR("menu.bullet.selected.image.color", 
                theme->menu_bullet_selected_color,
                RrColorCopy(theme->menu_selected_color));
 
-    READ_COLOR("osd.button.unpressed.text.color", theme->osd_unpressed_color,
+    READ_COLOR("osd.button.unpressed.text.color",
+               theme->osd_unpressed_color,
                RrColorCopy(theme->osd_text_active_color));
-    READ_COLOR("osd.button.pressed.text.color", theme->osd_pressed_color,
+    READ_COLOR("osd.button.pressed.text.color",
+               theme->osd_pressed_color,
                RrColorCopy(theme->osd_text_active_color));
-    READ_COLOR("osd.button.focused.text.color", theme->osd_focused_color,
+    READ_COLOR("osd.button.focused.text.color",
+               theme->osd_focused_color,
                RrColorCopy(theme->osd_text_active_color));
-    READ_COLOR("osd.button.pressed.box.color", theme->osd_pressed_lineart,
+    READ_COLOR("osd.button.pressed.box.color",
+               theme->osd_pressed_lineart,
                RrColorCopy(theme->titlebut_focused_pressed_color));
-    READ_COLOR("osd.button.focused.box.color", theme->osd_focused_lineart,
-               RrColorCopy(theme->titlebut_hover_focused_color));
+    READ_COLOR("osd.button.focused.box.color",
+               theme->osd_focused_lineart,
+               RrColorCopy(theme->titlebut_focused_hover_color));
  
-    /* load the image masks */
-
-    /* maximize button masks */
-    userdef = TRUE;
-    if (!read_mask(inst, path, theme, "max.xbm", &theme->btn_max->mask)) {
-            guchar data[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
-            theme->btn_max->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
-            userdef = FALSE;
-    }
-    if (!read_mask(inst, path, theme, "max_toggled.xbm",
-                   &theme->btn_max->toggled_mask))
+    /* load window buttons */
+
+    /* bases: unpressed, pressed, disabled */
+    READ_APPEARANCE("window.active.button.unpressed.bg", fbs.focused_unpressed, TRUE);
+    READ_APPEARANCE("window.inactive.button.unpressed.bg", fbs.unfocused_unpressed, TRUE);
+    READ_APPEARANCE("window.active.button.pressed.bg", fbs.focused_pressed, TRUE);
+    READ_APPEARANCE("window.inactive.button.pressed.bg", fbs.unfocused_pressed, TRUE);
+    READ_APPEARANCE("window.active.button.disabled.bg", fbs.focused_disabled, TRUE);
+    READ_APPEARANCE("window.inactive.button.disabled.bg", fbs.unfocused_disabled, TRUE);
+
+    /* hover */
+    READ_APPEARANCE_COPY("window.active.button.hover.bg",
+                         fbs.focused_hover, TRUE,
+                         fbs.focused_unpressed);
+    READ_APPEARANCE_COPY("window.inactive.button.hover.bg",
+                         fbs.unfocused_hover, TRUE,
+                         fbs.unfocused_unpressed);
+
+    /* toggled unpressed */
+    READ_APPEARANCE_("window.active.button.toggled.unpressed.bg",
+                     "window.active.button.toggled.bg",
+                     fbs.focused_unpressed_toggled, TRUE,
+                     fbs.focused_pressed);
+    READ_APPEARANCE_("window.inactive.button.toggled.unpressed.bg",
+                     "window.inactive.button.toggled.bg",
+                     fbs.unfocused_unpressed_toggled, TRUE,
+                     fbs.unfocused_pressed);
+
+    /* toggled pressed */
+    READ_APPEARANCE_COPY("window.active.button.toggled.pressed.bg",
+                         fbs.focused_pressed_toggled, TRUE,
+                         fbs.focused_pressed);
+    READ_APPEARANCE_COPY("window.inactive.button.toggled.pressed.bg",
+                         fbs.unfocused_pressed_toggled, TRUE,
+                         fbs.unfocused_pressed);
+
+    /* toggled hover */
+    READ_APPEARANCE_COPY("window.active.button.toggled.hover.bg",
+                         fbs.focused_hover_toggled, TRUE,
+                         fbs.focused_unpressed_toggled);
+    READ_APPEARANCE_COPY("window.inactive.button.toggled.hover.bg",
+                         fbs.unfocused_hover_toggled, TRUE,
+                         fbs.unfocused_unpressed_toggled);
+
+
+    /* now do individual buttons, if specified */
+
+    /* max button */
     {
-        if (userdef)
-            theme->btn_max->toggled_mask = RrPixmapMaskCopy(theme->btn_max->mask);
-        else {
-            guchar data[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f };
-            theme->btn_max->toggled_mask = RrPixmapMaskNew(inst, 6, 6,(gchar*)data);
-        }
-    }
-    READ_MASK_COPY("max_pressed.xbm", theme->btn_max->pressed_mask,
-                   theme->btn_max->mask);
-    READ_MASK_COPY("max_disabled.xbm", theme->btn_max->disabled_mask,
-                   theme->btn_max->mask);
-    READ_MASK_COPY("max_hover.xbm", theme->btn_max->hover_mask, 
-                   theme->btn_max->mask);
-    READ_MASK_COPY("max_toggled_pressed.xbm", 
-                   theme->btn_max->toggled_pressed_mask, 
-                   theme->btn_max->toggled_mask);
-    READ_MASK_COPY("max_toggled_hover.xbm", 
-                   theme->btn_max->toggled_hover_mask,
-                   theme->btn_max->toggled_mask);
-
-    /* iconify button masks */
-    if (!read_mask(inst, path, theme, "iconify.xbm", &theme->btn_iconify->mask)) {
-        guchar data[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f };
-        theme->btn_iconify->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+        guchar normal_mask[] =  { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
+        guchar toggled_mask[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f };
+        read_button_styles(db, inst, path, theme, theme->btn_max, "max",
+                           &fbs, normal_mask, toggled_mask);
     }
-    READ_MASK_COPY("iconify_pressed.xbm", theme->btn_iconify->pressed_mask,
-                   theme->btn_iconify->mask);
-    READ_MASK_COPY("iconify_disabled.xbm", theme->btn_iconify->disabled_mask,
-                   theme->btn_iconify->mask);
-    READ_MASK_COPY("iconify_hover.xbm", theme->btn_iconify->hover_mask,
-                   theme->btn_iconify->mask);
-
-    /* all desktops button masks */
-    userdef = TRUE;
-    if (!read_mask(inst, path, theme, "desk.xbm", &theme->btn_desk->mask)) {
-        guchar data[] = { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 };
-        theme->btn_desk->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
-        userdef = FALSE;
+
+    /* close button */
+    {
+        guchar normal_mask[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 };
+        read_button_styles(db, inst, path, theme, theme->btn_close, "close",
+                           &fbs, normal_mask, NULL);
     }
-    if (!read_mask(inst, path, theme, "desk_toggled.xbm",
-                   &theme->btn_desk->toggled_mask)) {
-        if (userdef)
-            theme->btn_desk->toggled_mask = RrPixmapMaskCopy(theme->btn_desk->mask);
-        else {
-            guchar data[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 };
-            theme->btn_desk->toggled_mask =
-                RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
-        }
+
+    /* all desktops button */
+    {
+        guchar normal_mask[] =  { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 };
+        guchar toggled_mask[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 };
+        read_button_styles(db, inst, path, theme, theme->btn_desk, "desk",
+                           &fbs, normal_mask, toggled_mask);
     }
-    READ_MASK_COPY("desk_pressed.xbm", theme->btn_desk->pressed_mask,
-                   theme->btn_desk->mask);
-    READ_MASK_COPY("desk_disabled.xbm", theme->btn_desk->disabled_mask,
-                   theme->btn_desk->mask);
-    READ_MASK_COPY("desk_hover.xbm", theme->btn_desk->hover_mask, theme->btn_desk->mask);
-    READ_MASK_COPY("desk_toggled_pressed.xbm",
-                   theme->btn_desk->toggled_pressed_mask, theme->btn_desk->toggled_mask);
-    READ_MASK_COPY("desk_toggled_hover.xbm", theme->btn_desk->toggled_hover_mask,
-                   theme->btn_desk->toggled_mask);
-
-    /* shade button masks */
-    if (!read_mask(inst, path, theme, "shade.xbm", &theme->btn_shade->mask)) {
-        guchar data[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 };
-        theme->btn_shade->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+
+    /* shade button */
+    {
+        guchar normal_mask[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 };
+        read_button_styles(db, inst, path, theme, theme->btn_shade, "shade",
+                           &fbs, normal_mask, normal_mask);
     }
-    READ_MASK_COPY("shade_toggled.xbm", theme->btn_shade->toggled_mask,
-                   theme->btn_shade->mask);
-    READ_MASK_COPY("shade_pressed.xbm", theme->btn_shade->pressed_mask,
-                   theme->btn_shade->mask);
-    READ_MASK_COPY("shade_disabled.xbm", theme->btn_shade->disabled_mask,
-                   theme->btn_shade->mask);
-    READ_MASK_COPY("shade_hover.xbm", theme->btn_shade->hover_mask,
-                   theme->btn_shade->mask);
-    READ_MASK_COPY("shade_toggled_pressed.xbm",
-                   theme->btn_shade->toggled_pressed_mask,
-                   theme->btn_shade->toggled_mask);
-    READ_MASK_COPY("shade_toggled_hover.xbm",
-                   theme->btn_shade->toggled_hover_mask, 
-                   theme->btn_shade->toggled_mask);
-
-    /* close button masks */
-    if (!read_mask(inst, path, theme, "close.xbm", &theme->btn_close->mask)) {
-        guchar data[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 };
-        theme->btn_close->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+
+    /* iconify button */
+    {
+        guchar normal_mask[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f };
+        read_button_styles(db, inst, path, theme, theme->btn_iconify, "iconify",
+                           &fbs, normal_mask, NULL);
     }
-    READ_MASK_COPY("close_pressed.xbm", theme->btn_close->pressed_mask,
-                   theme->btn_close->mask);
-    READ_MASK_COPY("close_disabled.xbm", theme->btn_close->disabled_mask,
-                   theme->btn_close->mask);
-    READ_MASK_COPY("close_hover.xbm", theme->btn_close->hover_mask,
-                   theme->btn_close->mask);
 
     /* submenu bullet mask */
-    if (!read_mask(inst, path, theme, "bullet.xbm", &theme->menu_bullet_mask))
+    if (!read_mask(inst, path, "bullet.xbm", &theme->menu_bullet_mask))
     {
         guchar data[] = { 0x01, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01 };
         theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data);
@@ -550,31 +544,13 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     theme->def_win_icon_w = OB_DEFAULT_ICON_WIDTH;
     theme->def_win_icon_h = OB_DEFAULT_ICON_HEIGHT;
 
-    /* the toggled hover mask = the toggled unpressed mask (i.e. no change) */
-    theme->btn_max->toggled_hover_mask =
-        RrPixmapMaskCopy(theme->btn_max->toggled_mask);
-    theme->btn_desk->toggled_hover_mask =
-        RrPixmapMaskCopy(theme->btn_desk->toggled_mask);
-    theme->btn_shade->toggled_hover_mask =
-        RrPixmapMaskCopy(theme->btn_shade->toggled_mask);
-    /* the toggled pressed mask = the toggled unpressed mask (i.e. no change)*/
-    theme->btn_max->toggled_pressed_mask =
-        RrPixmapMaskCopy(theme->btn_max->toggled_mask);
-    theme->btn_desk->toggled_pressed_mask =
-        RrPixmapMaskCopy(theme->btn_desk->toggled_mask);
-    theme->btn_shade->toggled_pressed_mask =
-        RrPixmapMaskCopy(theme->btn_shade->toggled_mask);
-
     /* read the decoration textures */
     READ_APPEARANCE("window.active.title.bg", theme->a_focused_title, FALSE);
-    READ_APPEARANCE("window.inactive.title.bg", theme->a_unfocused_title,
-                    FALSE);
+    READ_APPEARANCE("window.inactive.title.bg", theme->a_unfocused_title, FALSE);
     READ_APPEARANCE("window.active.label.bg", theme->a_focused_label, TRUE);
-    READ_APPEARANCE("window.inactive.label.bg", theme->a_unfocused_label,
-                    TRUE);
+    READ_APPEARANCE("window.inactive.label.bg", theme->a_unfocused_label, TRUE);
     READ_APPEARANCE("window.active.handle.bg", theme->a_focused_handle, FALSE);
-    READ_APPEARANCE("window.inactive.handle.bg",theme->a_unfocused_handle,
-                    FALSE);
+    READ_APPEARANCE("window.inactive.handle.bg",theme->a_unfocused_handle, FALSE);
     READ_APPEARANCE("window.active.grip.bg", theme->a_focused_grip, TRUE);
     READ_APPEARANCE("window.inactive.grip.bg", theme->a_unfocused_grip, TRUE);
     READ_APPEARANCE("menu.items.bg", theme->a_menu, FALSE);
@@ -585,25 +561,29 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
         RrAppearanceCopy(theme->a_menu_selected);
 
     /* read appearances for non-decorations (on-screen-display) */
-    if (!read_appearance(db, inst, "osd.bg", theme->osd_bg, FALSE)) {
+    if (!read_appearance(db, inst, "osd.bg", theme->osd_bg, FALSE))
+    {
         RrAppearanceFree(theme->osd_bg);
         theme->osd_bg = RrAppearanceCopy(theme->a_focused_title);
     }
     if (!read_appearance(db, inst, "osd.active.label.bg",
                          theme->osd_hilite_label, TRUE) &&
         !read_appearance(db, inst, "osd.label.bg",
-                         theme->osd_hilite_label, TRUE)) {
+                         theme->osd_hilite_label, TRUE))
+    {
         RrAppearanceFree(theme->osd_hilite_label);
         theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label);
     }
     if (!read_appearance(db, inst, "osd.inactive.label.bg",
-                         theme->osd_unhilite_label, TRUE)) {
+                         theme->osd_unhilite_label, TRUE))
+    {
         RrAppearanceFree(theme->osd_unhilite_label);
         theme->osd_unhilite_label = RrAppearanceCopy(theme->a_unfocused_label);
     }
     /* osd_hilite_fg can't be parentrel */
     if (!read_appearance(db, inst, "osd.hilight.bg",
-                         theme->osd_hilite_bg, FALSE)) {
+                         theme->osd_hilite_bg, FALSE))
+    {
         RrAppearanceFree(theme->osd_hilite_bg);
         if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL)
             theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_label);
@@ -612,7 +592,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     }
     /* osd_unhilite_fg can't be parentrel either */
     if (!read_appearance(db, inst, "osd.unhilight.bg",
-                         theme->osd_unhilite_bg, FALSE)) {
+                         theme->osd_unhilite_bg, FALSE))
+    {
         RrAppearanceFree(theme->osd_unhilite_bg);
         if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL)
             theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_label);
@@ -620,290 +601,10 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_title);
     }
 
-    /* read buttons textures */
-
-    /* bases: unpressed, pressed, disabled */
-    READ_APPEARANCE("window.active.button.unpressed.bg",
-                    a_focused_unpressed_tmp, TRUE);
-    READ_APPEARANCE("window.inactive.button.unpressed.bg",
-                    a_unfocused_unpressed_tmp, TRUE);
-    READ_APPEARANCE("window.active.button.pressed.bg",
-                    a_focused_pressed_tmp, TRUE);
-    READ_APPEARANCE("window.inactive.button.pressed.bg",
-                    a_unfocused_pressed_tmp, TRUE);
-    READ_APPEARANCE("window.active.button.disabled.bg",
-                    a_disabled_focused_tmp, TRUE);
-    READ_APPEARANCE("window.inactive.button.disabled.bg",
-                    a_disabled_unfocused_tmp, TRUE);
-
-    /* hover */
-    READ_APPEARANCE_COPY("window.active.button.hover.bg",
-                         a_hover_focused_tmp, TRUE,
-                         a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.hover.bg",
-                         a_hover_unfocused_tmp, TRUE,
-                         a_unfocused_unpressed_tmp);
-
-    /* toggled unpressed */
-    READ_APPEARANCE_("window.active.button.toggled.unpressed.bg",
-                     "window.active.button.toggled.bg",
-                     a_toggled_focused_unpressed_tmp, TRUE,
-                     a_focused_pressed_tmp);
-    READ_APPEARANCE_("window.inactive.button.toggled.unpressed.bg",
-                     "window.inactive.button.toggled.bg",
-                     a_toggled_unfocused_unpressed_tmp, TRUE,
-                     a_unfocused_pressed_tmp);
-
-    /* toggled pressed */
-    READ_APPEARANCE_COPY("window.active.button.toggled.pressed.bg",
-                         a_toggled_focused_pressed_tmp, TRUE,
-                         a_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.toggled.pressed.bg",
-                         a_toggled_unfocused_pressed_tmp, TRUE,
-                         a_unfocused_pressed_tmp);
-
-    /* toggled hover */
-    READ_APPEARANCE_COPY("window.active.button.toggled.hover.bg",
-                         a_toggled_hover_focused_tmp, TRUE,
-                         a_toggled_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.toggled.hover.bg",
-                         a_toggled_hover_unfocused_tmp, TRUE,
-                         a_toggled_unfocused_unpressed_tmp);
-
-
-    /* now do individual buttons, if specified */
-
-    /* max button */
-    read_button_colors(db, inst, theme, theme->btn_max, "max");
-
-    /* bases:  unpressed, pressed, disabled */
-    READ_APPEARANCE_COPY("window.active.button.max.unpressed.bg",
-                         theme->btn_max->a_focused_unpressed, TRUE,
-                         a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.max.unpressed.bg",
-                         theme->btn_max->a_unfocused_unpressed, TRUE,
-                         a_unfocused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.max.pressed.bg",
-                         theme->btn_max->a_focused_pressed, TRUE,
-                         a_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.max.pressed.bg",
-                         theme->btn_max->a_unfocused_pressed, TRUE,
-                         a_unfocused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.max.disabled.bg",
-                         theme->btn_max->a_disabled_focused, TRUE,
-                         a_disabled_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.max.disabled.bg",
-                         theme->btn_max->a_disabled_unfocused, TRUE,
-                         a_disabled_unfocused_tmp);
-
-    /* hover */
-    READ_APPEARANCE_COPY("window.active.button.max.hover.bg",
-                         theme->btn_max->a_hover_focused, TRUE,
-                         a_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.max.hover.bg",
-                         theme->btn_max->a_hover_unfocused, TRUE,
-                         a_hover_unfocused_tmp);
-
-    /* toggled unpressed */
-    READ_APPEARANCE_("window.active.button.max.toggled.unpressed.bg",
-                     "window.active.button.max.toggled.bg",
-                     theme->btn_max->a_toggled_focused_unpressed, TRUE,
-                     a_toggled_focused_unpressed_tmp);
-    READ_APPEARANCE_("window.inactive.button.max.toggled.unpressed.bg",
-                     "window.inactive.button.max.toggled.bg",
-                     theme->btn_max->a_toggled_unfocused_unpressed, TRUE,
-                     a_toggled_unfocused_unpressed_tmp);
-
-    /* toggled pressed */
-    READ_APPEARANCE_COPY("window.active.button.max.toggled.pressed.bg",
-                         theme->btn_max->a_toggled_focused_pressed, TRUE,
-                         a_toggled_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.max.toggled.pressed.bg",
-                         theme->btn_max->a_toggled_unfocused_pressed, TRUE,
-                         a_toggled_unfocused_pressed_tmp);
-
-    /* toggled hover */
-    READ_APPEARANCE_COPY("window.active.button.max.toggled.hover.bg",
-                         theme->btn_max->a_toggled_hover_focused, TRUE,
-                         a_toggled_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.max.toggled.hover.bg",
-                         theme->btn_max->a_toggled_hover_unfocused, TRUE,
-                         a_toggled_hover_unfocused_tmp);
-
-    /* close button */
-    read_button_colors(db, inst, theme, theme->btn_close, "close");
-
-    READ_APPEARANCE_COPY("window.active.button.close.unpressed.bg",
-                         theme->btn_close->a_focused_unpressed, TRUE,
-                         a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.close.unpressed.bg",
-                         theme->btn_close->a_unfocused_unpressed, TRUE,
-                         a_unfocused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.close.pressed.bg",
-                         theme->btn_close->a_focused_pressed, TRUE,
-                         a_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.close.pressed.bg",
-                         theme->btn_close->a_unfocused_pressed, TRUE,
-                         a_unfocused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.close.disabled.bg",
-                         theme->btn_close->a_disabled_focused, TRUE,
-                         a_disabled_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.close.disabled.bg",
-                         theme->btn_close->a_disabled_unfocused, TRUE,
-                         a_disabled_unfocused_tmp);
-    READ_APPEARANCE_COPY("window.active.button.close.hover.bg",
-                         theme->btn_close->a_hover_focused, TRUE,
-                         a_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.close.hover.bg",
-                         theme->btn_close->a_hover_unfocused, TRUE,
-                         a_hover_unfocused_tmp);
-
-    /* desk button */
-    read_button_colors(db, inst, theme, theme->btn_desk, "desk");
-
-    /* bases:  unpressed, pressed, disabled */
-    READ_APPEARANCE_COPY("window.active.button.desk.unpressed.bg",
-                         theme->btn_desk->a_focused_unpressed, TRUE,
-                         a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.desk.unpressed.bg",
-                         theme->btn_desk->a_unfocused_unpressed, TRUE,
-                         a_unfocused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.desk.pressed.bg",
-                         theme->btn_desk->a_focused_pressed, TRUE,
-                         a_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.desk.pressed.bg",
-                         theme->btn_desk->a_unfocused_pressed, TRUE,
-                         a_unfocused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.desk.disabled.bg",
-                         theme->btn_desk->a_disabled_focused, TRUE,
-                         a_disabled_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.desk.disabled.bg",
-                         theme->btn_desk->a_disabled_unfocused, TRUE,
-                         a_disabled_unfocused_tmp);
-
-    /* hover */
-    READ_APPEARANCE_COPY("window.active.button.desk.hover.bg",
-                         theme->btn_desk->a_hover_focused, TRUE,
-                         a_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.desk.hover.bg",
-                         theme->btn_desk->a_hover_unfocused, TRUE,
-                         a_hover_unfocused_tmp);
-
-    /* toggled unpressed */
-    READ_APPEARANCE_("window.active.button.desk.toggled.unpressed.bg",
-                     "window.active.button.desk.toggled.bg",
-                     theme->btn_desk->a_toggled_focused_unpressed, TRUE,
-                     a_toggled_focused_unpressed_tmp);
-    READ_APPEARANCE_("window.inactive.button.desk.toggled.unpressed.bg",
-                     "window.inactive.button.desk.toggled.bg",
-                     theme->btn_desk->a_toggled_unfocused_unpressed, TRUE,
-                     a_toggled_unfocused_unpressed_tmp);
-
-    /* toggled pressed */
-    READ_APPEARANCE_COPY("window.active.button.desk.toggled.pressed.bg",
-                         theme->btn_desk->a_toggled_focused_pressed, TRUE,
-                         a_toggled_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.desk.toggled.pressed.bg",
-                         theme->btn_desk->a_toggled_unfocused_pressed, TRUE,
-                         a_toggled_unfocused_pressed_tmp);
-
-    /* toggled hover */
-    READ_APPEARANCE_COPY("window.active.button.desk.toggled.hover.bg",
-                         theme->btn_desk->a_toggled_hover_focused, TRUE,
-                         a_toggled_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.desk.toggled.hover.bg",
-                         theme->btn_desk->a_toggled_hover_unfocused, TRUE,
-                         a_toggled_hover_unfocused_tmp);
-
-    /* shade button */
-    read_button_colors(db, inst, theme, theme->btn_shade, "shade");
-
-    /* bases:  unpressed, pressed, disabled */
-    READ_APPEARANCE_COPY("window.active.button.shade.unpressed.bg",
-                         theme->btn_shade->a_focused_unpressed, TRUE,
-                         a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.shade.unpressed.bg",
-                         theme->btn_shade->a_unfocused_unpressed, TRUE,
-                         a_unfocused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.shade.pressed.bg",
-                         theme->btn_shade->a_focused_pressed, TRUE,
-                         a_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.shade.pressed.bg",
-                         theme->btn_shade->a_unfocused_pressed, TRUE,
-                         a_unfocused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.shade.disabled.bg",
-                         theme->btn_shade->a_disabled_focused, TRUE,
-                         a_disabled_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.shade.disabled.bg",
-                         theme->btn_shade->a_disabled_unfocused, TRUE,
-                         a_disabled_unfocused_tmp);
-
-    /* hover */
-    READ_APPEARANCE_COPY("window.active.button.shade.hover.bg",
-                         theme->btn_shade->a_hover_focused, TRUE,
-                         a_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.shade.hover.bg",
-                         theme->btn_shade->a_hover_unfocused, TRUE,
-                         a_hover_unfocused_tmp);
-
-    /* toggled unpressed */
-    READ_APPEARANCE_("window.active.button.shade.toggled.unpressed.bg",
-                     "window.active.button.shade.toggled.bg",
-                     theme->btn_shade->a_toggled_focused_unpressed, TRUE,
-                     a_toggled_focused_unpressed_tmp);
-    READ_APPEARANCE_("window.inactive.button.shade.toggled.unpressed.bg",
-                     "window.inactive.button.shade.toggled.bg",
-                     theme->btn_shade->a_toggled_unfocused_unpressed, TRUE,
-                     a_toggled_unfocused_unpressed_tmp);
-
-    /* toggled pressed */
-    READ_APPEARANCE_COPY("window.active.button.shade.toggled.pressed.bg",
-                         theme->btn_shade->a_toggled_focused_pressed, TRUE,
-                         a_toggled_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.shade.toggled.pressed.bg",
-                         theme->btn_shade->a_toggled_unfocused_pressed, TRUE,
-                         a_toggled_unfocused_pressed_tmp);
-
-    /* toggled hover */
-    READ_APPEARANCE_COPY("window.active.button.shade.toggled.hover.bg",
-                         theme->btn_shade->a_toggled_hover_focused, TRUE,
-                         a_toggled_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.shade.toggled.hover.bg",
-                         theme->btn_shade->a_toggled_hover_unfocused, TRUE,
-                         a_toggled_hover_unfocused_tmp);
-
-    /* iconify button */
-    read_button_colors(db, inst, theme, theme->btn_iconify, "iconify");
-
-    READ_APPEARANCE_COPY("window.active.button.iconify.unpressed.bg",
-                         theme->btn_iconify->a_focused_unpressed, TRUE,
-                         a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.iconify.unpressed.bg",
-                         theme->btn_iconify->a_unfocused_unpressed, TRUE,
-                         a_unfocused_unpressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.iconify.pressed.bg",
-                         theme->btn_iconify->a_focused_pressed, TRUE,
-                         a_focused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.iconify.pressed.bg",
-                         theme->btn_iconify->a_unfocused_pressed, TRUE,
-                         a_unfocused_pressed_tmp);
-    READ_APPEARANCE_COPY("window.active.button.iconify.disabled.bg",
-                         theme->btn_iconify->a_disabled_focused, TRUE,
-                         a_disabled_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.iconify.disabled.bg",
-                         theme->btn_iconify->a_disabled_unfocused, TRUE,
-                         a_disabled_unfocused_tmp);
-    READ_APPEARANCE_COPY("window.active.button.iconify.hover.bg",
-                         theme->btn_iconify->a_hover_focused, TRUE,
-                         a_hover_focused_tmp);
-    READ_APPEARANCE_COPY("window.inactive.button.iconify.hover.bg",
-                         theme->btn_iconify->a_hover_unfocused, TRUE,
-                         a_hover_unfocused_tmp);
-
     /* osd buttons */
-    READ_APPEARANCE_COPY("osd.button.unpressed.bg", theme->osd_unpressed_button, TRUE, a_focused_unpressed_tmp);
-    READ_APPEARANCE_COPY_TEXTURES("osd.button.pressed.bg", theme->osd_pressed_button, TRUE, a_focused_pressed_tmp, 5);
-    READ_APPEARANCE_COPY_TEXTURES("osd.button.focused.bg", theme->osd_focused_button, TRUE, a_focused_unpressed_tmp, 5);
+    READ_APPEARANCE_COPY("osd.button.unpressed.bg", theme->osd_unpressed_button, TRUE, fbs.focused_unpressed);
+    READ_APPEARANCE_COPY_TEXTURES("osd.button.pressed.bg", theme->osd_pressed_button, TRUE, fbs.focused_pressed, 5);
+    READ_APPEARANCE_COPY_TEXTURES("osd.button.focused.bg", theme->osd_focused_button, TRUE, fbs.focused_unpressed, 5);
 
     theme->a_icon->surface.grad =
         theme->a_clear->surface.grad =
@@ -937,8 +638,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
             theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
         }
-        if ((p = strstr(str, "shadowtint=")))
-        {
+        if ((p = strstr(str, "shadowtint="))) {
             i = parse_inline_number(p + strlen("shadowtint="));
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
@@ -951,17 +651,13 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
         }
     }
 
-    theme->a_focused_label->texture[0].data.text.shadow_color =
-        theme->title_focused_shadow_color;
-    theme->a_focused_label->texture[0].data.text.shadow_alpha =
-        theme->title_focused_shadow_alpha;
+    theme->a_focused_label->texture[0].data.text.shadow_color = theme->title_focused_shadow_color;
+    theme->a_focused_label->texture[0].data.text.shadow_alpha = theme->title_focused_shadow_alpha;
 
     theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
     theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
-    theme->osd_hilite_label->texture[0].data.text.font =
-        theme->osd_font_hilite;
-    theme->osd_hilite_label->texture[0].data.text.color =
-        theme->osd_text_active_color;
+    theme->osd_hilite_label->texture[0].data.text.font = theme->osd_font_hilite;
+    theme->osd_hilite_label->texture[0].data.text.color = theme->osd_text_active_color;
 
     if (read_string(db, "osd.active.label.text.font", &str) ||
         read_string(db, "osd.label.text.font", &str))
@@ -977,8 +673,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i;
             theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i;
         }
-        if ((p = strstr(str, "shadowtint=")))
-        {
+        if ((p = strstr(str, "shadowtint="))) {
             i = parse_inline_number(p + strlen("shadowtint="));
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
@@ -1045,10 +740,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
 
     theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT;
     theme->a_unfocused_label->texture[0].data.text.justify = winjust;
-    theme->a_unfocused_label->texture[0].data.text.font =
-        theme->win_font_unfocused;
-    theme->a_unfocused_label->texture[0].data.text.color =
-        theme->title_unfocused_color;
+    theme->a_unfocused_label->texture[0].data.text.font = theme->win_font_unfocused;
+    theme->a_unfocused_label->texture[0].data.text.color = theme->title_unfocused_color;
 
     if (read_string(db, "window.inactive.label.text.font", &str)) {
         char *p;
@@ -1062,8 +755,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i;
             theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i;
         }
-        if ((p = strstr(str, "shadowtint=")))
-        {
+        if ((p = strstr(str, "shadowtint="))) {
             i = parse_inline_number(p + strlen("shadowtint="));
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
@@ -1088,8 +780,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     theme->osd_unhilite_label->texture[0].data.text.color =
         theme->osd_text_inactive_color;
 
-    if (read_string(db, "osd.inactive.label.text.font", &str))
-    {
+    if (read_string(db, "osd.inactive.label.text.font", &str)) {
         char *p;
         gint i = 0;
         gint j;
@@ -1101,8 +792,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x=i;
             theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y=i;
         }
-        if ((p = strstr(str, "shadowtint=")))
-        {
+        if ((p = strstr(str, "shadowtint="))) {
             i = parse_inline_number(p + strlen("shadowtint="));
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
@@ -1135,10 +825,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
 
     theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
     theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
-    theme->a_menu_text_title->texture[0].data.text.font =
-        theme->menu_title_font;
-    theme->a_menu_text_title->texture[0].data.text.color =
-        theme->menu_title_color;
+    theme->a_menu_text_title->texture[0].data.text.font = theme->menu_title_font;
+    theme->a_menu_text_title->texture[0].data.text.color = theme->menu_title_color;
 
     if (read_string(db, "menu.title.text.font", &str)) {
         char *p;
@@ -1152,24 +840,22 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i;
             theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i;
         }
-        if ((p = strstr(str, "shadowtint=")))
-        {
+        if ((p = strstr(str, "shadowtint="))) {
             i = parse_inline_number(p + strlen("shadowtint="));
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
 
             theme->menu_title_shadow_color = RrColorNew(inst, j, j, j);
-            theme->menu_title_shadow_alpha = i;
         } else {
             theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0);
-            theme->menu_title_shadow_alpha = 50;
+            i = 50;
         }
-    }
 
-    theme->a_menu_text_title->texture[0].data.text.shadow_color =
-        theme->menu_title_shadow_color;
-    theme->a_menu_text_title->texture[0].data.text.shadow_alpha =
-        theme->menu_title_shadow_alpha;
+        theme->a_menu_text_title->texture[0].data.text.shadow_color =
+            theme->menu_title_shadow_color;
+        theme->a_menu_text_title->texture[0].data.text.shadow_alpha =
+            i;
+    }
 
     theme->a_menu_text_normal->texture[0].type =
         theme->a_menu_text_selected->texture[0].type =
@@ -1220,313 +906,35 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             theme->a_menu_text_disabled_selected->
                 texture[0].data.text.shadow_offset_y = i;
         }
-        if ((p = strstr(str, "shadowtint=")))
-        {
+        if ((p = strstr(str, "shadowtint="))) {
             i = parse_inline_number(p + strlen("shadowtint="));
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
 
-            theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j);
-            theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j);
-            theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j);
-            theme->menu_text_normal_shadow_alpha = i;
-            theme->menu_text_selected_shadow_alpha = i;
-            theme->menu_text_disabled_shadow_alpha = i;
-            theme->menu_text_disabled_selected_shadow_alpha = i;
+            theme->menu_text_shadow_color = RrColorNew(inst, j, j, j);
         } else {
-            theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0);
-            theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0);
-            theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0);
-            theme->menu_text_normal_shadow_alpha = 50;
-            theme->menu_text_selected_shadow_alpha = 50;
-            theme->menu_text_disabled_selected_shadow_alpha = 50;
+            theme->menu_text_shadow_color = RrColorNew(inst, 0, 0, 0);
+            i = 50;
         }
+
+        theme->a_menu_text_normal->texture[0].data.text.shadow_color =
+            theme->a_menu_text_selected->texture[0].data.text.shadow_color =
+            theme->a_menu_text_disabled->texture[0].data.text.shadow_color =
+            theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color =
+            theme->menu_text_shadow_color;
+
+        theme->a_menu_text_normal->texture[0].data.text.shadow_alpha =
+            theme->a_menu_text_selected->texture[0].data.text.shadow_alpha =
+            theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha =
+            theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha =
+            i;
     }
 
-    theme->a_menu_text_normal->texture[0].data.text.shadow_color =
-        theme->menu_text_normal_shadow_color;
-    theme->a_menu_text_normal->texture[0].data.text.shadow_alpha =
-        theme->menu_text_normal_shadow_alpha;
-    theme->a_menu_text_selected->texture[0].data.text.shadow_color =
-        theme->menu_text_selected_shadow_color;
-    theme->a_menu_text_selected->texture[0].data.text.shadow_alpha =
-        theme->menu_text_selected_shadow_alpha;
-    theme->a_menu_text_disabled->texture[0].data.text.shadow_color =
-        theme->menu_text_disabled_shadow_color;
-    theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha =
-        theme->menu_text_disabled_shadow_alpha;
-    theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color =
-        theme->menu_text_disabled_shadow_color;
-    theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha =
-        theme->menu_text_disabled_shadow_alpha;
-
-    theme->btn_max->a_disabled_focused->texture[0].type =
-        theme->btn_max->a_disabled_unfocused->texture[0].type =
-        theme->btn_max->a_hover_focused->texture[0].type =
-        theme->btn_max->a_hover_unfocused->texture[0].type =
-        theme->btn_max->a_toggled_hover_focused->texture[0].type =
-        theme->btn_max->a_toggled_hover_unfocused->texture[0].type =
-        theme->btn_max->a_toggled_focused_unpressed->texture[0].type =
-        theme->btn_max->a_toggled_unfocused_unpressed->texture[0].type =
-        theme->btn_max->a_toggled_focused_pressed->texture[0].type =
-        theme->btn_max->a_toggled_unfocused_pressed->texture[0].type =
-        theme->btn_max->a_focused_unpressed->texture[0].type =
-        theme->btn_max->a_focused_pressed->texture[0].type =
-        theme->btn_max->a_unfocused_unpressed->texture[0].type =
-        theme->btn_max->a_unfocused_pressed->texture[0].type =
-        theme->btn_close->a_disabled_focused->texture[0].type =
-        theme->btn_close->a_disabled_unfocused->texture[0].type =
-        theme->btn_close->a_hover_focused->texture[0].type =
-        theme->btn_close->a_hover_unfocused->texture[0].type =
-        theme->btn_close->a_focused_unpressed->texture[0].type =
-        theme->btn_close->a_focused_pressed->texture[0].type =
-        theme->btn_close->a_unfocused_unpressed->texture[0].type =
-        theme->btn_close->a_unfocused_pressed->texture[0].type =
-        theme->btn_desk->a_disabled_focused->texture[0].type =
-        theme->btn_desk->a_disabled_unfocused->texture[0].type =
-        theme->btn_desk->a_hover_focused->texture[0].type =
-        theme->btn_desk->a_hover_unfocused->texture[0].type =
-        theme->btn_desk->a_toggled_hover_focused->texture[0].type =
-        theme->btn_desk->a_toggled_hover_unfocused->texture[0].type =
-        theme->btn_desk->a_toggled_focused_unpressed->texture[0].type =
-        theme->btn_desk->a_toggled_unfocused_unpressed->texture[0].type =
-        theme->btn_desk->a_toggled_focused_pressed->texture[0].type =
-        theme->btn_desk->a_toggled_unfocused_pressed->texture[0].type =
-        theme->btn_desk->a_focused_unpressed->texture[0].type =
-        theme->btn_desk->a_focused_pressed->texture[0].type =
-        theme->btn_desk->a_unfocused_unpressed->texture[0].type =
-        theme->btn_desk->a_unfocused_pressed->texture[0].type =
-        theme->btn_shade->a_disabled_focused->texture[0].type =
-        theme->btn_shade->a_disabled_unfocused->texture[0].type =
-        theme->btn_shade->a_hover_focused->texture[0].type =
-        theme->btn_shade->a_hover_unfocused->texture[0].type =
-        theme->btn_shade->a_toggled_hover_focused->texture[0].type =
-        theme->btn_shade->a_toggled_hover_unfocused->texture[0].type =
-        theme->btn_shade->a_toggled_focused_unpressed->texture[0].type =
-        theme->btn_shade->a_toggled_unfocused_unpressed->texture[0].type =
-        theme->btn_shade->a_toggled_focused_pressed->texture[0].type =
-        theme->btn_shade->a_toggled_unfocused_pressed->texture[0].type =
-        theme->btn_shade->a_focused_unpressed->texture[0].type =
-        theme->btn_shade->a_focused_pressed->texture[0].type =
-        theme->btn_shade->a_unfocused_unpressed->texture[0].type =
-        theme->btn_shade->a_unfocused_pressed->texture[0].type =
-        theme->btn_iconify->a_disabled_focused->texture[0].type =
-        theme->btn_iconify->a_disabled_unfocused->texture[0].type =
-        theme->btn_iconify->a_hover_focused->texture[0].type =
-        theme->btn_iconify->a_hover_unfocused->texture[0].type =
-        theme->btn_iconify->a_focused_unpressed->texture[0].type =
-        theme->btn_iconify->a_focused_pressed->texture[0].type =
-        theme->btn_iconify->a_unfocused_unpressed->texture[0].type =
-        theme->btn_iconify->a_unfocused_pressed->texture[0].type =
-        theme->a_menu_bullet_normal->texture[0].type =
+    theme->a_menu_bullet_normal->texture[0].type =
         theme->a_menu_bullet_selected->texture[0].type = RR_TEXTURE_MASK;
-
-    theme->btn_max->a_disabled_focused->texture[0].data.mask.mask =
-        theme->btn_max->a_disabled_unfocused->texture[0].data.mask.mask =
-        theme->btn_max->disabled_mask;
-    theme->btn_max->a_hover_focused->texture[0].data.mask.mask =
-        theme->btn_max->a_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_max->hover_mask;
-    theme->btn_max->a_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_max->a_unfocused_pressed->texture[0].data.mask.mask =
-        theme->btn_max->pressed_mask;
-    theme->btn_max->a_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_max->a_unfocused_unpressed->texture[0].data.mask.mask =
-        theme->btn_max->mask;
-    theme->btn_max->a_toggled_hover_focused->texture[0].data.mask.mask =
-        theme->btn_max->a_toggled_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_max->toggled_hover_mask;
-    theme->btn_max->a_toggled_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_max->a_toggled_unfocused_unpressed->
-        texture[0].data.mask.mask = theme->btn_max->toggled_mask;
-    theme->btn_max->a_toggled_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_max->a_toggled_unfocused_pressed->texture[0].data.mask.mask
-        = theme->btn_max->toggled_pressed_mask;
-    theme->btn_close->a_disabled_focused->texture[0].data.mask.mask =
-        theme->btn_close->a_disabled_unfocused->texture[0].data.mask.mask =
-        theme->btn_close->disabled_mask;
-    theme->btn_close->a_hover_focused->texture[0].data.mask.mask =
-        theme->btn_close->a_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_close->hover_mask;
-    theme->btn_close->a_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_close->a_unfocused_pressed->texture[0].data.mask.mask =
-        theme->btn_close->pressed_mask;
-    theme->btn_close->a_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_close->a_unfocused_unpressed->texture[0].data.mask.mask =
-        theme->btn_close->mask;
-    theme->btn_desk->a_disabled_focused->texture[0].data.mask.mask =
-        theme->btn_desk->a_disabled_unfocused->texture[0].data.mask.mask =
-        theme->btn_desk->disabled_mask;
-    theme->btn_desk->a_hover_focused->texture[0].data.mask.mask =
-        theme->btn_desk->a_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_desk->hover_mask;
-    theme->btn_desk->a_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_desk->a_unfocused_pressed->texture[0].data.mask.mask =
-        theme->btn_desk->pressed_mask;
-    theme->btn_desk->a_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_desk->a_unfocused_unpressed->texture[0].data.mask.mask =
-        theme->btn_desk->mask;
-    theme->btn_desk->a_toggled_hover_focused->texture[0].data.mask.mask =
-        theme->btn_desk->a_toggled_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_desk->toggled_hover_mask;
-    theme->btn_desk->a_toggled_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_desk->a_toggled_unfocused_unpressed->
-        texture[0].data.mask.mask = theme->btn_desk->toggled_mask;
-    theme->btn_desk->a_toggled_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_desk->a_toggled_unfocused_pressed->texture[0].data.mask.mask
-        = theme->btn_desk->toggled_pressed_mask;
-    theme->btn_shade->a_disabled_focused->texture[0].data.mask.mask =
-        theme->btn_shade->a_disabled_unfocused->texture[0].data.mask.mask =
-        theme->btn_shade->disabled_mask;
-    theme->btn_shade->a_hover_focused->texture[0].data.mask.mask =
-        theme->btn_shade->a_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_shade->hover_mask;
-    theme->btn_shade->a_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_shade->a_unfocused_pressed->texture[0].data.mask.mask =
-        theme->btn_shade->pressed_mask;
-    theme->btn_shade->a_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_shade->a_unfocused_unpressed->texture[0].data.mask.mask =
-        theme->btn_shade->mask;
-    theme->btn_shade->a_toggled_hover_focused->texture[0].data.mask.mask =
-        theme->btn_shade->a_toggled_hover_unfocused->texture[0].data.mask.mask
-        = theme->btn_shade->toggled_hover_mask;
-    theme->btn_shade->a_toggled_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_shade->a_toggled_unfocused_unpressed->
-        texture[0].data.mask.mask = theme->btn_shade->toggled_mask;
-    theme->btn_shade->a_toggled_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_shade->a_toggled_unfocused_pressed->
-        texture[0].data.mask.mask = theme->btn_shade->toggled_pressed_mask;
-    theme->btn_iconify->a_disabled_focused->texture[0].data.mask.mask =
-        theme->btn_iconify->a_disabled_unfocused->texture[0].data.mask.mask =
-        theme->btn_iconify->disabled_mask;
-    theme->btn_iconify->a_hover_focused->texture[0].data.mask.mask =
-        theme->btn_iconify->a_hover_unfocused->texture[0].data.mask.mask =
-        theme->btn_iconify->hover_mask;
-    theme->btn_iconify->a_focused_pressed->texture[0].data.mask.mask =
-        theme->btn_iconify->a_unfocused_pressed->texture[0].data.mask.mask =
-        theme->btn_iconify->pressed_mask;
-    theme->btn_iconify->a_focused_unpressed->texture[0].data.mask.mask =
-        theme->btn_iconify->a_unfocused_unpressed->texture[0].data.mask.mask =
-        theme->btn_iconify->mask;
     theme->a_menu_bullet_normal->texture[0].data.mask.mask =
     theme->a_menu_bullet_selected->texture[0].data.mask.mask =
         theme->menu_bullet_mask;
-    theme->btn_max->a_disabled_focused->texture[0].data.mask.color = 
-        theme->btn_max->disabled_focused_color;
-    theme->btn_close->a_disabled_focused->texture[0].data.mask.color = 
-        theme->btn_close->disabled_focused_color;
-    theme->btn_desk->a_disabled_focused->texture[0].data.mask.color = 
-        theme->btn_desk->disabled_focused_color;
-    theme->btn_shade->a_disabled_focused->texture[0].data.mask.color = 
-        theme->btn_shade->disabled_focused_color;
-    theme->btn_iconify->a_disabled_focused->texture[0].data.mask.color = 
-        theme->btn_iconify->disabled_focused_color;
-    theme->btn_max->a_disabled_unfocused->texture[0].data.mask.color = 
-        theme->btn_max->disabled_unfocused_color;
-    theme->btn_close->a_disabled_unfocused->texture[0].data.mask.color = 
-        theme->btn_close->disabled_unfocused_color;
-    theme->btn_desk->a_disabled_unfocused->texture[0].data.mask.color = 
-        theme->btn_desk->disabled_unfocused_color;
-    theme->btn_shade->a_disabled_unfocused->texture[0].data.mask.color = 
-        theme->btn_shade->disabled_unfocused_color;
-    theme->btn_iconify->a_disabled_unfocused->texture[0].data.mask.color = 
-        theme->btn_iconify->disabled_unfocused_color;
-    theme->btn_max->a_hover_focused->texture[0].data.mask.color = 
-        theme->btn_max->hover_focused_color;
-    theme->btn_close->a_hover_focused->texture[0].data.mask.color = 
-        theme->btn_close->hover_focused_color;
-    theme->btn_desk->a_hover_focused->texture[0].data.mask.color = 
-        theme->btn_desk->hover_focused_color;
-    theme->btn_shade->a_hover_focused->texture[0].data.mask.color = 
-        theme->btn_shade->hover_focused_color;
-    theme->btn_iconify->a_hover_focused->texture[0].data.mask.color = 
-        theme->btn_iconify->hover_focused_color;
-    theme->btn_max->a_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_max->hover_unfocused_color;
-    theme->btn_close->a_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_close->hover_unfocused_color;
-    theme->btn_desk->a_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_desk->hover_unfocused_color;
-    theme->btn_shade->a_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_shade->hover_unfocused_color;
-    theme->btn_iconify->a_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_iconify->hover_unfocused_color;
-    theme->btn_max->a_toggled_hover_focused->texture[0].data.mask.color = 
-        theme->btn_max->toggled_hover_focused_color;
-    theme->btn_desk->a_toggled_hover_focused->texture[0].data.mask.color = 
-        theme->btn_desk->toggled_hover_focused_color;
-    theme->btn_shade->a_toggled_hover_focused->texture[0].data.mask.color = 
-        theme->btn_shade->toggled_hover_focused_color;
-    theme->btn_max->a_toggled_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_max->toggled_hover_unfocused_color;
-    theme->btn_desk->a_toggled_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_desk->toggled_hover_unfocused_color;
-    theme->btn_shade->a_toggled_hover_unfocused->texture[0].data.mask.color = 
-        theme->btn_shade->toggled_hover_unfocused_color;
-    theme->btn_max->a_toggled_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_max->toggled_focused_unpressed_color;
-    theme->btn_desk->a_toggled_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_desk->toggled_focused_unpressed_color;
-    theme->btn_shade->a_toggled_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_shade->toggled_focused_unpressed_color;
-    theme->btn_max->a_toggled_unfocused_unpressed->texture[0].data.mask.color = 
-        theme->btn_max->toggled_unfocused_unpressed_color;
-    theme->btn_desk->a_toggled_unfocused_unpressed->texture[0].data.mask.color
-        = theme->btn_desk->toggled_unfocused_unpressed_color;
-    theme->btn_shade->a_toggled_unfocused_unpressed->texture[0].data.mask.color
-        = theme->btn_shade->toggled_unfocused_unpressed_color;
-    theme->btn_max->a_toggled_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_max->toggled_focused_pressed_color;
-    theme->btn_desk->a_toggled_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_desk->toggled_focused_pressed_color;
-    theme->btn_shade->a_toggled_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_shade->toggled_focused_pressed_color;
-    theme->btn_max->a_toggled_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_max->toggled_unfocused_pressed_color;
-    theme->btn_desk->a_toggled_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_desk->toggled_unfocused_pressed_color;
-    theme->btn_shade->a_toggled_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_shade->toggled_unfocused_pressed_color;
-    theme->btn_max->a_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_max->focused_unpressed_color;
-    theme->btn_close->a_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_close->focused_unpressed_color;
-    theme->btn_desk->a_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_desk->focused_unpressed_color;
-    theme->btn_shade->a_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_shade->focused_unpressed_color;
-    theme->btn_iconify->a_focused_unpressed->texture[0].data.mask.color = 
-        theme->btn_iconify->focused_unpressed_color;
-    theme->btn_max->a_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_max->focused_pressed_color;
-    theme->btn_close->a_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_close->focused_pressed_color;
-    theme->btn_desk->a_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_desk->focused_pressed_color;
-    theme->btn_shade->a_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_shade->focused_pressed_color;
-    theme->btn_iconify->a_focused_pressed->texture[0].data.mask.color = 
-        theme->btn_iconify->focused_pressed_color;
-    theme->btn_max->a_unfocused_unpressed->texture[0].data.mask.color = 
-        theme->btn_max->unfocused_unpressed_color;
-    theme->btn_close->a_unfocused_unpressed->texture[0].data.mask.color = 
-        theme->btn_close->unfocused_unpressed_color;
-    theme->btn_desk->a_unfocused_unpressed->texture[0].data.mask.color = 
-        theme->btn_desk->unfocused_unpressed_color;
-    theme->btn_shade->a_unfocused_unpressed->texture[0].data.mask.color = 
-        theme->btn_shade->unfocused_unpressed_color;
-    theme->btn_iconify->a_unfocused_unpressed->texture[0].data.mask.color = 
-        theme->btn_iconify->unfocused_unpressed_color;
-    theme->btn_max->a_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_max->unfocused_pressed_color;
-    theme->btn_close->a_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_close->unfocused_pressed_color;
-    theme->btn_desk->a_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_desk->unfocused_pressed_color;
-    theme->btn_shade->a_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_shade->unfocused_pressed_color;
-    theme->btn_iconify->a_unfocused_pressed->texture[0].data.mask.color = 
-        theme->btn_iconify->unfocused_pressed_color;
     theme->a_menu_bullet_normal->texture[0].data.mask.color =
         theme->menu_bullet_color;
     theme->a_menu_bullet_selected->texture[0].data.mask.color =
@@ -1536,20 +944,16 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     XrmDestroyDatabase(db);
 
     /* set the font heights */
-    theme->win_font_height = RrFontHeight
-        (theme->win_font_focused,
-         theme->a_focused_label->texture[0].data.text.shadow_offset_y);
+    theme->win_font_height = RrFontHeight(theme->win_font_focused,
+        theme->a_focused_label->texture[0].data.text.shadow_offset_y);
     theme->win_font_height =
         MAX(theme->win_font_height,
-            RrFontHeight
-            (theme->win_font_focused,
-             theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
-    theme->menu_title_font_height = RrFontHeight
-        (theme->menu_title_font,
-         theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
-    theme->menu_font_height = RrFontHeight
-        (theme->menu_font,
-         theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
+            RrFontHeight(theme->win_font_focused,
+                theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
+    theme->menu_title_font_height = RrFontHeight(theme->menu_title_font,
+        theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
+    theme->menu_font_height = RrFontHeight(theme->menu_font,
+        theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
 
     /* calculate some last extents */
     {
@@ -1581,20 +985,20 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     theme->button_size = theme->label_height - 2;
     theme->grip_width = 25;
 
-    RrAppearanceFree(a_disabled_focused_tmp);
-    RrAppearanceFree(a_disabled_unfocused_tmp);
-    RrAppearanceFree(a_hover_focused_tmp);
-    RrAppearanceFree(a_hover_unfocused_tmp);
-    RrAppearanceFree(a_focused_unpressed_tmp);
-    RrAppearanceFree(a_focused_pressed_tmp);
-    RrAppearanceFree(a_unfocused_unpressed_tmp);
-    RrAppearanceFree(a_unfocused_pressed_tmp);
-    RrAppearanceFree(a_toggled_hover_focused_tmp);
-    RrAppearanceFree(a_toggled_hover_unfocused_tmp);
-    RrAppearanceFree(a_toggled_focused_unpressed_tmp);
-    RrAppearanceFree(a_toggled_focused_pressed_tmp);
-    RrAppearanceFree(a_toggled_unfocused_unpressed_tmp);
-    RrAppearanceFree(a_toggled_unfocused_pressed_tmp);
+    RrAppearanceFree(fbs.focused_disabled);
+    RrAppearanceFree(fbs.unfocused_disabled);
+    RrAppearanceFree(fbs.focused_hover);
+    RrAppearanceFree(fbs.unfocused_hover);
+    RrAppearanceFree(fbs.focused_unpressed);
+    RrAppearanceFree(fbs.focused_pressed);
+    RrAppearanceFree(fbs.unfocused_unpressed);
+    RrAppearanceFree(fbs.unfocused_pressed);
+    RrAppearanceFree(fbs.focused_hover_toggled);
+    RrAppearanceFree(fbs.unfocused_hover_toggled);
+    RrAppearanceFree(fbs.focused_unpressed_toggled);
+    RrAppearanceFree(fbs.focused_pressed_toggled);
+    RrAppearanceFree(fbs.unfocused_unpressed_toggled);
+    RrAppearanceFree(fbs.unfocused_pressed_toggled);
 
     return theme;
 }
@@ -1622,16 +1026,16 @@ void RrThemeFree(RrTheme *theme)
         RrColorFree(theme->cb_focused_color);
         RrColorFree(theme->title_focused_color);
         RrColorFree(theme->title_unfocused_color);
-        RrColorFree(theme->titlebut_disabled_focused_color);
-        RrColorFree(theme->titlebut_disabled_unfocused_color);
-        RrColorFree(theme->titlebut_hover_focused_color);
-        RrColorFree(theme->titlebut_hover_unfocused_color);
-        RrColorFree(theme->titlebut_toggled_hover_focused_color);
-        RrColorFree(theme->titlebut_toggled_hover_unfocused_color);
-        RrColorFree(theme->titlebut_toggled_focused_pressed_color);
-        RrColorFree(theme->titlebut_toggled_unfocused_pressed_color);
-        RrColorFree(theme->titlebut_toggled_focused_unpressed_color);
-        RrColorFree(theme->titlebut_toggled_unfocused_unpressed_color);
+        RrColorFree(theme->titlebut_focused_disabled_color);
+        RrColorFree(theme->titlebut_unfocused_disabled_color);
+        RrColorFree(theme->titlebut_focused_hover_color);
+        RrColorFree(theme->titlebut_unfocused_hover_color);
+        RrColorFree(theme->titlebut_focused_hover_toggled_color);
+        RrColorFree(theme->titlebut_unfocused_hover_toggled_color);
+        RrColorFree(theme->titlebut_focused_pressed_toggled_color);
+        RrColorFree(theme->titlebut_unfocused_pressed_toggled_color);
+        RrColorFree(theme->titlebut_focused_unpressed_toggled_color);
+        RrColorFree(theme->titlebut_unfocused_unpressed_toggled_color);
         RrColorFree(theme->titlebut_focused_pressed_color);
         RrColorFree(theme->titlebut_unfocused_pressed_color);
         RrColorFree(theme->titlebut_focused_unpressed_color);
@@ -1656,10 +1060,7 @@ void RrThemeFree(RrTheme *theme)
         RrColorFree(theme->osd_pressed_lineart);
         RrColorFree(theme->osd_focused_lineart);
         RrColorFree(theme->menu_title_shadow_color);
-        RrColorFree(theme->menu_text_normal_shadow_color);
-        RrColorFree(theme->menu_text_selected_shadow_color);
-        RrColorFree(theme->menu_text_disabled_shadow_color);
-        RrColorFree(theme->menu_text_disabled_selected_shadow_color);
+        RrColorFree(theme->menu_text_shadow_color);
 
         g_free(theme->def_win_icon);
         
@@ -1834,8 +1235,7 @@ static gboolean read_color(XrmDatabase db, const RrInstance *inst,
 }
 
 static gboolean read_mask(const RrInstance *inst, const gchar *path,
-                          RrTheme *theme, const gchar *maskname,
-                          RrPixmapMask **value)
+                          const gchar *maskname, RrPixmapMask **value)
 {
     gboolean ret = FALSE;
     gchar *s;
@@ -2061,110 +1461,79 @@ static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
     return im;
 }
 
-static void read_button_colors(XrmDatabase db, const RrInstance *inst, 
+static void read_button_styles(XrmDatabase db, const RrInstance *inst, 
+                               gchar *path,
                                const RrTheme *theme, RrButton *btn, 
-                               const gchar *btnname)
+                               const gchar *btnname,
+                               struct fallbacks *fbs,
+                               guchar *normal_mask,
+                               guchar *toggled_mask)
 {
-    gchar *name;
-
-    /* active unpressed */
-    name = g_strdup_printf("window.active.button.%s.unpressed.image.color",
-                           btnname);
-    READ_COLOR(name, btn->focused_unpressed_color,
-               RrColorCopy(theme->titlebut_focused_unpressed_color));
-    g_free(name);
-
-    /* inactive unpressed */
-    name = g_strdup_printf("window.inactive.button.%s.unpressed.image.color",
-                           btnname);
-    READ_COLOR(name, btn->unfocused_unpressed_color,
-               RrColorCopy(theme->titlebut_unfocused_unpressed_color));
-    g_free(name);
+    gchar name[128], name2[128];
+    gboolean userdef = TRUE;
 
-    /* active pressed */
-    name = g_strdup_printf("window.active.button.%s.pressed.image.color",
-                           btnname);
-    READ_COLOR(name, btn->focused_pressed_color,
-               RrColorCopy(theme->titlebut_focused_pressed_color));
-    g_free(name);
+    g_snprintf(name, 128, "%s.xbm", btnname);
+    if (!read_mask(inst, path, name, &btn->unpressed_mask) && normal_mask)
+    {
+        btn->unpressed_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)normal_mask);
+        userdef = FALSE;
+    }
+    g_snprintf(name, 128, "%s_toggled.xbm", btnname);
+    if (toggled_mask && !read_mask(inst, path, name, &btn->unpressed_toggled_mask))
+    {
+        if (userdef)
+            btn->unpressed_toggled_mask = RrPixmapMaskCopy(btn->unpressed_mask);
+        else
+            btn->unpressed_toggled_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)toggled_mask);
+    }
+#define READ_BUTTON_MASK_COPY(type, fallback) \
+    g_snprintf(name, 128, "%s_" #type ".xbm", btnname); \
+    READ_MASK_COPY(name, btn->type##_mask, fallback);
+
+    READ_BUTTON_MASK_COPY(pressed, btn->unpressed_mask);
+    READ_BUTTON_MASK_COPY(disabled, btn->unpressed_mask);
+    READ_BUTTON_MASK_COPY(hover, btn->unpressed_mask);
+    if (toggled_mask) {
+        READ_BUTTON_MASK_COPY(pressed_toggled, btn->unpressed_toggled_mask);
+        READ_BUTTON_MASK_COPY(hover_toggled, btn->unpressed_toggled_mask);
+    }
 
-    /* inactive pressed */
-    name = g_strdup_printf("window.inactive.button.%s.pressed.image.color",
-                          btnname);
-    READ_COLOR(name, btn->unfocused_pressed_color,
-               RrColorCopy(theme->titlebut_unfocused_pressed_color));
-    g_free(name);
-
-    /* active disabled */
-    name = g_strdup_printf("window.active.button.%s.disabled.image.color",
-                           btnname);
-    READ_COLOR(name, btn->disabled_focused_color,
-               RrColorCopy(theme->titlebut_disabled_focused_color));
-    g_free(name);
-
-    /* inactive disabled */
-    name = g_strdup_printf("window.inactive.button.%s.disabled.image.color",
-                           btnname);
-    READ_COLOR(name, btn->disabled_unfocused_color,
-               RrColorCopy(theme->titlebut_disabled_unfocused_color));
-    g_free(name);
-
-    /* active hover */
-    name = g_strdup_printf("window.active.button.%s.hover.image.color",
-                           btnname);
-    READ_COLOR(name, btn->hover_focused_color, 
-               RrColorCopy(theme->titlebut_hover_focused_color));
-    g_free(name);
-
-    /* inactive hover */
-    name = g_strdup_printf("window.inactive.button.%s.hover.image.color",
-                           btnname);
-    READ_COLOR(name, btn->hover_unfocused_color,
-               RrColorCopy(theme->titlebut_hover_unfocused_color));
-    g_free(name);
-
-    /* active toggled unpressed */
-    name = g_strdup_printf("window.active.button.%s.toggled."
-                          "unpressed.image.color", btnname);
-    READ_COLOR(name, btn->toggled_focused_unpressed_color,
-               RrColorCopy(theme->titlebut_toggled_focused_unpressed_color));
-    g_free(name);
-
-    /* inactive toggled unpressed */
-    name = g_strdup_printf("window.inactive.button.%s.toggled."
-                           "unpressed.image.color", btnname);
-    READ_COLOR(name, btn->toggled_unfocused_unpressed_color,
-               RrColorCopy(theme->titlebut_toggled_unfocused_unpressed_color));
-    g_free(name);
-
-    /* active toggled hover */
-    name = g_strdup_printf("window.active.button.%s.toggled.hover.image.color",
-                           btnname);
-    READ_COLOR(name, btn->toggled_hover_focused_color,
-               RrColorCopy(theme->titlebut_toggled_hover_focused_color));
-
-    g_free(name);
-
-    /* inactive toggled hover */
-    name = g_strdup_printf("window.inactive.button.%s.toggled.hover."
-                           "image.color", btnname);
-    READ_COLOR(name, btn->toggled_hover_unfocused_color,
-               RrColorCopy(theme->titlebut_toggled_hover_unfocused_color));
-    g_free(name);
-
-    /* active toggled pressed */
-    name = g_strdup_printf("window.active.button.%s.toggled.pressed."
-                           "image.color", btnname);
-    READ_COLOR(name, btn->toggled_focused_pressed_color, 
-               RrColorCopy(theme->titlebut_toggled_focused_pressed_color));
-    g_free(name);
-   
-    /* inactive toggled pressed */
-    name = g_strdup_printf("window.inactive.button.%s.toggled.pressed."
-                           "image.color", btnname);
-    READ_COLOR(name, btn->toggled_unfocused_pressed_color,
-               RrColorCopy(theme->titlebut_toggled_unfocused_pressed_color));
-    g_free(name);
+#define READ_BUTTON_APPEARANCE(typedots, type, fallback) \
+    g_snprintf(name, 128, "window.active.button.%s." typedots ".image.color", btnname); \
+    READ_COLOR(name, btn->focused_##type##_color, RrColorCopy(theme->titlebut_focused_##type##_color)); \
+    g_snprintf(name, 128, "window.inactive.button.%s." typedots ".image.color", btnname); \
+    READ_COLOR(name, btn->unfocused_##type##_color, RrColorCopy(theme->titlebut_unfocused_##type##_color)); \
+    if (fallback) { \
+        g_snprintf(name, 128, "window.active.button.%s." typedots ".bg", btnname); \
+        g_snprintf(name2, 128, "window.active.button.%s.toggled.bg", btnname); \
+        READ_APPEARANCE_(name, name2, btn->a_focused_##type, TRUE, fbs->focused_##type); \
+        g_snprintf(name, 128, "window.inactive.button.%s." typedots ".bg", btnname); \
+        g_snprintf(name2, 128, "window.inactive.button.%s.toggled.bg", btnname); \
+        READ_APPEARANCE_(name, name2, btn->a_unfocused_##type, TRUE, fbs->unfocused_##type); \
+    } else { \
+        g_snprintf(name, 128, "window.active.button.%s." typedots ".bg", btnname); \
+        READ_APPEARANCE_COPY(name, btn->a_focused_##type, TRUE, fbs->focused_##type); \
+        g_snprintf(name, 128, "window.inactive.button.%s." typedots ".bg", btnname); \
+        READ_APPEARANCE_COPY(name, btn->a_unfocused_##type, TRUE, fbs->unfocused_##type); \
+    } \
+    btn->a_unfocused_##type->texture[0].typ##e = \
+      btn->a_focused_##type->texture[0].typ##e = \
+        RR_TEXTURE_MASK; \
+    btn->a_unfocused_##type->texture[0].data.mask.mask = \
+      btn->a_focused_##type->texture[0].data.mask.mask = \
+        btn->type##_mask; \
+    btn->a_unfocused_##type->texture[0].data.mask.color = \
+        btn->unfocused_##type##_color; \
+    btn->a_focused_##type->texture[0].data.mask.color = \
+        btn->focused_##type##_color;
+
+    READ_BUTTON_APPEARANCE("unpressed", unpressed, 0);
+    READ_BUTTON_APPEARANCE("pressed", pressed, 0);
+    READ_BUTTON_APPEARANCE("disabled", disabled, 0);
+    READ_BUTTON_APPEARANCE("hover", hover, 0);
+    if (toggled_mask) {
+        READ_BUTTON_APPEARANCE("unpressed.toggled", unpressed_toggled, 1);
+        READ_BUTTON_APPEARANCE("pressed.toggled", pressed_toggled, 0);
+        READ_BUTTON_APPEARANCE("hover.toggled", hover_toggled, 0);
+    }
 }
-
-
index eb9ac3f..8797f0b 100644 (file)
@@ -76,16 +76,16 @@ struct _RrTheme {
     RrColor *cb_unfocused_color;
     RrColor *title_focused_color;
     RrColor *title_unfocused_color;
-    RrColor *titlebut_disabled_focused_color;
-    RrColor *titlebut_disabled_unfocused_color;
-    RrColor *titlebut_hover_focused_color;
-    RrColor *titlebut_hover_unfocused_color;
-    RrColor *titlebut_toggled_hover_focused_color;
-    RrColor *titlebut_toggled_hover_unfocused_color;
-    RrColor *titlebut_toggled_focused_pressed_color;
-    RrColor *titlebut_toggled_unfocused_pressed_color;
-    RrColor *titlebut_toggled_focused_unpressed_color;
-    RrColor *titlebut_toggled_unfocused_unpressed_color;
+    RrColor *titlebut_focused_disabled_color;
+    RrColor *titlebut_unfocused_disabled_color;
+    RrColor *titlebut_focused_hover_color;
+    RrColor *titlebut_unfocused_hover_color;
+    RrColor *titlebut_focused_hover_toggled_color;
+    RrColor *titlebut_unfocused_hover_toggled_color;
+    RrColor *titlebut_focused_pressed_toggled_color;
+    RrColor *titlebut_unfocused_pressed_toggled_color;
+    RrColor *titlebut_focused_unpressed_toggled_color;
+    RrColor *titlebut_unfocused_unpressed_toggled_color;
     RrColor *titlebut_focused_pressed_color;
     RrColor *titlebut_unfocused_pressed_color;
     RrColor *titlebut_focused_unpressed_color;
@@ -114,15 +114,7 @@ struct _RrTheme {
     RrColor *osd_pressed_lineart;
     RrColor *osd_focused_lineart;
     RrColor *menu_title_shadow_color;
-    gchar    menu_title_shadow_alpha;
-    RrColor *menu_text_normal_shadow_color;
-    gchar    menu_text_normal_shadow_alpha;
-    RrColor *menu_text_selected_shadow_color;
-    gchar    menu_text_selected_shadow_alpha;
-    RrColor *menu_text_disabled_shadow_color;
-    gchar    menu_text_disabled_shadow_alpha;
-    RrColor *menu_text_disabled_selected_shadow_color;
-    gchar    menu_text_disabled_selected_shadow_alpha;
+    RrColor *menu_text_shadow_color;
 
     /* style settings - pics */
     RrPixel32 *def_win_icon; /* RGBA */
index 60da51d..ceb53ff 100644 (file)
@@ -25,7 +25,8 @@ G_BEGIN_DECLS
 
 /*! Setup to do a binary search on an array. */
 #define BSEARCH_SETUP() \
-    register guint l_BSEARCH, r_BSEARCH, out_BSEARCH;
+    register guint l_BSEARCH, r_BSEARCH, out_BSEARCH; \
+    register gboolean nearest_BSEARCH; (void)nearest_BSEARCH;
 
 /*! Helper macro that just returns the input */
 #define BSEARCH_IS_T(t) (t)
@@ -37,11 +38,21 @@ G_BEGIN_DECLS
 
 /*! Search an array @ar, starting at index @start,
   with @size elements, looking for value @val of type @t,
-  using the macro @to_t to convert values in the arrau @ar to type @t.*/
+  using the macro @to_t to convert values in the arrau @ar to type @t.
+
+  If all elements in @ar are less than @val, then BSEARCH_AT() will be
+  the last element in @ar.
+  If all elements in @ar are greater than @val, then BSEARCH_AT() will be
+  the first element in @ar.
+  Otherwise, if the element @val is not found then BSEARCH_AT() will be set to
+  the position before the first element larger than @val.
+*/
 #define BSEARCH_CMP(t, ar, start, size, val, to_t)  \
-{ \
-    l_BSEARCH = (start);              \
-    r_BSEARCH = (start)+(size)-1;     \
+do { \
+    out_BSEARCH = (start); \
+    l_BSEARCH = (size) > 0 ? (start) : (start + 1); \
+    r_BSEARCH = (size) > 0 ? (start)+(size)-1 : (start); \
+    nearest_BSEARCH = FALSE; \
     while (l_BSEARCH <= r_BSEARCH) { \
         /* m is in the middle, but to the left if there's an even number \
            of elements */ \
@@ -49,21 +60,44 @@ G_BEGIN_DECLS
         if ((val) == to_t((ar)[out_BSEARCH])) {             \
             break; \
         } \
-        else if ((val) < to_t((ar)[out_BSEARCH]) && out_BSEARCH > 0) {   \
-            r_BSEARCH = out_BSEARCH-1; /* search to the left side */ \
+        else if ((val) < to_t((ar)[out_BSEARCH])) { \
+            if (out_BSEARCH > start) { \
+                r_BSEARCH = out_BSEARCH-1; /* search to the left side */ \
+            } else { \
+                /* reached the start of the array */ \
+                r_BSEARCH = out_BSEARCH; \
+                l_BSEARCH = out_BSEARCH + 1; \
+            } \
+        } \
+        else { \
+            l_BSEARCH = out_BSEARCH+1; /* search to the right side */ \
+        } \
+    } \
+    if ((size) > 0 && (val) != to_t((ar)[out_BSEARCH])) { \
+        if ((val) > to_t((ar)[out_BSEARCH])) { \
+            nearest_BSEARCH = TRUE; \
+        } \
+        else if (out_BSEARCH > start) { \
+            --out_BSEARCH; \
+            nearest_BSEARCH = (val) > to_t((ar)[out_BSEARCH]); \
         } \
-        else \
-            l_BSEARCH = out_BSEARCH+1; /* search to the left side */ \
     } \
-}
+} while (0)
 
 /*! Returns true if the element last searched for was found in the array */
 #define BSEARCH_FOUND() (l_BSEARCH <= r_BSEARCH)
+
 /*! Returns the position in the array at which the element last searched for
   was found. */
 #define BSEARCH_AT() (out_BSEARCH)
 
+/*! Returns true if the element at BSEARCH_AT() in the array is the largest
+  value in the array smaller than the search key. Returns false if there was
+  nothing in the array smaller than the search key.
 
+  Should only be used when BSEARCH_FOUND() is false.
+*/
+#define BSEARCH_FOUND_NEAREST_SMALLER() (!BSEARCH_FOUND() && nearest_BSEARCH)
 
 G_END_DECLS
 
diff --git a/obt/bsearch_unittest.c b/obt/bsearch_unittest.c
new file mode 100644 (file)
index 0000000..d5ff325
--- /dev/null
@@ -0,0 +1,316 @@
+#include "obt/unittest_base.h"
+
+#include "obt/bsearch.h"
+
+#include <glib.h>
+
+static void empty() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int* array = NULL;
+    guint array_size = 0;
+
+    /* Search in an empty array. */
+    BSEARCH(int, array, 0, array_size, 10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+
+    /* Search in an empty array with a non-zero starting position. */
+    BSEARCH(int, array, 10, array_size, -10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(10, BSEARCH_AT());
+
+    TEST_END();
+}
+
+static void single_element() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int array[1];
+    guint array_size = 1;
+
+    /* Search for something smaller than the only element. */
+    array[0] = 20;
+    BSEARCH(int, array, 0, array_size, -10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for something bigger than the only element. */
+    array[0] = 20;
+    BSEARCH(int, array, 0, array_size, 30);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for something smaller than the only element. */
+    array[0] = -20;
+    BSEARCH(int, array, 0, array_size, -30);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for something bigger than the only element. */
+    array[0] = -20;
+    BSEARCH(int, array, 0, array_size, 10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for the only element that exists. */
+    array[0] = -20;
+    BSEARCH(int, array, 0, array_size, -20);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    TEST_END();
+}
+
+static void single_element_nonzero_start() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int array[10];
+    guint array_start = 9;
+    guint array_size = 1;
+
+    /* Search for something smaller than the only element. */
+    array[array_start] = 20;
+    BSEARCH(int, array, array_start, array_size, -10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for something bigger than the only element. */
+    array[array_start] = 20;
+    BSEARCH(int, array, array_start, array_size, 30);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for something smaller than the only element. */
+    array[array_start] = -20;
+    BSEARCH(int, array, array_start, array_size, -30);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for something bigger than the only element. */
+    array[array_start] = -20;
+    BSEARCH(int, array, array_start, array_size, 10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    /* Search for the only element that exists. */
+    array[array_start] = -20;
+    BSEARCH(int, array, array_start, array_size, -20);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    TEST_END();
+}
+
+static void present() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int array[5];
+    guint array_start = 0;
+    guint array_size = 5;
+
+    array[0] = 10;
+    array[1] = 12;
+    array[2] = 14;
+    array[3] = 16;
+    array[4] = 18;
+
+    /* Search for something that is in the array. */
+
+    BSEARCH(int, array, array_start, array_size, 10);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 12);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(1, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 14);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(2, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 16);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(3, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 18);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(4, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    TEST_END();
+}
+
+static void present_nonzero_start() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int array[5];
+    guint array_start = 2;
+    guint array_size = 3;
+
+    array[0] = 10;
+    array[1] = 12;
+    array[2] = 14;
+    array[3] = 16;
+    array[4] = 18;
+
+    /* Search for something that is in the array. */
+
+    BSEARCH(int, array, array_start, array_size, 10);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 12);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 14);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(2, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 16);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(3, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 18);
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(4, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    TEST_END();
+}
+
+static void missing() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int array[5];
+    guint array_start = 0;
+    guint array_size = 5;
+
+    array[0] = 10;
+    array[1] = 12;
+    array[2] = 14;
+    array[3] = 16;
+    array[4] = 18;
+
+    /* Search for something that is _not_ in the array. */
+
+    BSEARCH(int, array, array_start, array_size, 9);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 11);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(0, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 13);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(1, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 15);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(2, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 17);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(3, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 19);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(4, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    TEST_END();
+}
+
+static void missing_nonzero_start() {
+    TEST_START();
+
+    BSEARCH_SETUP();
+    int array[5];
+    guint array_start = 2;
+    guint array_size = 3;
+
+    array[0] = 10;
+    array[1] = 12;
+    array[2] = 14;
+    array[3] = 16;
+    array[4] = 18;
+
+    /* Search for something that is _not_ in the array. */
+
+    BSEARCH(int, array, array_start, array_size, 9);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 11);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 13);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(array_start, BSEARCH_AT());
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 15);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(2, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 17);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(3, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    BSEARCH(int, array, array_start, array_size, 19);
+    EXPECT_BOOL_EQ(FALSE, BSEARCH_FOUND());
+    EXPECT_UINT_EQ(4, BSEARCH_AT());
+    EXPECT_BOOL_EQ(TRUE, BSEARCH_FOUND_NEAREST_SMALLER());
+
+    TEST_END();
+}
+
+void run_bsearch_unittest() {
+    unittest_start_suite("bsearch");
+
+    empty();
+    single_element();
+    single_element_nonzero_start();
+    present();
+    present_nonzero_start();
+    missing();
+    missing_nonzero_start();
+
+    unittest_end_suite();
+}
index 4e84f48..60caf0e 100644 (file)
@@ -329,7 +329,7 @@ gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XEvent *ev)
 #ifndef X_HAVE_UTF8_STRING
                 /* convert to utf8 */
                 gchar *buf2 = buf;
-                buf = g_locale_to_utf8(buf2, r, NULL, NULL, NULL);
+                buf = g_locale_to_utf8(buf2, len, NULL, NULL, NULL);
                 g_free(buf2);
 #endif
 
diff --git a/obt/unittest_base.c b/obt/unittest_base.c
new file mode 100644 (file)
index 0000000..d6f91f4
--- /dev/null
@@ -0,0 +1,55 @@
+#include <glib.h>
+
+#include "obt/unittest_base.h"
+
+guint g_test_failures = 0;
+guint g_test_failures_at_test_start = 0;
+const gchar* g_active_test_suite = NULL;
+const gchar* g_active_test_name = NULL;
+
+/* Add all test suites here. Keep them sorted. */
+extern void run_bsearch_unittest();
+
+gint main(gint argc, gchar **argv)
+{
+    /* Add all test suites here. Keep them sorted. */
+    run_bsearch_unittest();
+
+    return g_test_failures == 0 ? 0 : 1;
+}
+
+void unittest_start_suite(const char* suite_name)
+{
+    g_assert(g_active_test_suite == NULL);
+    g_active_test_suite = suite_name;
+    printf("[--------] %s\n", suite_name);
+}
+
+void unittest_end_suite()
+{
+    g_assert(g_active_test_suite);
+    printf("[--------] %s\n", g_active_test_suite);
+    printf("\n");
+    g_active_test_suite = NULL;
+}
+
+void unittest_start(const char* test_name) 
+{
+    g_test_failures_at_test_start = g_test_failures;
+    g_assert(g_active_test_name == NULL);
+    g_active_test_name = test_name;
+    printf("[ RUN    ] %s.%s\n", g_active_test_suite, g_active_test_name);
+}
+
+void unittest_end()
+{
+    g_assert(g_active_test_name);
+    if (g_test_failures_at_test_start == g_test_failures) {
+        printf("[     OK ] %s.%s\n",
+               g_active_test_suite, g_active_test_name);
+    } else {
+        printf("[ FAILED ] %s.%s\n",
+               g_active_test_suite, g_active_test_name);
+    }
+    g_active_test_name = NULL;
+}
diff --git a/obt/unittest_base.h b/obt/unittest_base.h
new file mode 100644 (file)
index 0000000..85106bb
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __obt_unittest_base_h
+#define __obt_unittest_base_h
+
+#include <glib.h>
+#include <stdio.h>
+
+G_BEGIN_DECLS
+
+extern guint g_test_failures;
+extern guint g_test_failures_at_test_start;
+extern const gchar* g_active_test_suite;
+extern const gchar* g_active_test_name;
+
+#define ADD_FAILURE() { ++g_test_failures; }
+
+#define FAILURE_AT() \
+    fprintf(stderr, "Failure at %s:%u\n", __FILE__, __LINE__); \
+    ADD_FAILURE();
+
+#define EXPECT_BOOL_EQ(expected, actual) \
+    if ((expected) != (actual)) { \
+        FAILURE_AT(); \
+        fprintf(stderr, "Expected: %s\nActual: %s\n", \
+               ((expected) ? "true" : "false"), \
+               ((actual) ? "true" : "false"));  \
+    }
+
+#define EXPECT_CHAR_EQ(expected, actual) \
+    if ((expected) != (actual)) { \
+        FAILURE_AT(); \
+        fprintf(stderr, "Expected: %c\nActual: %c\n", (expected), (actual)); \
+    }
+
+#define EXPECT_INT_EQ(expected, actual) \
+    if ((expected) != (actual)) { \
+        FAILURE_AT(); \
+        fprintf(stderr, "Expected: %d\nActual: %d\n", (expected), (actual)); \
+    }
+
+#define EXPECT_UINT_EQ(expected, actual) \
+    if ((expected) != (actual)) { \
+        FAILURE_AT(); \
+        fprintf(stderr, "Expected: %u\nActual: %u\n", (expected), (actual)); \
+    }
+
+#define EXPECT_STRING_EQ(expected, actual) \
+    if ((expected) != (actual)) { \
+        FAILURE_AT(); \
+        fprintf(stderr, "Expected: %s\nActual: %s\n", \
+               ((expected) ? (expected) : "NULL"), \
+               ((actual) ? (actual) : NULL)); \
+    }
+
+void unittest_start_suite(const char* suite_name);
+void unittest_end_suite();
+
+void unittest_start(const char* test_name);
+void unittest_end();
+
+#define TEST_START() unittest_start(__func__);
+#define TEST_END() unittest_end();
+
+G_END_DECLS
+
+#endif
index 223ad02..f200ae7 100644 (file)
--- a/obt/xml.c
+++ b/obt/xml.c
@@ -281,7 +281,7 @@ gboolean obt_xml_load_mem(ObtXmlInst *i,
     xmlResetLastError();
 
     i->doc = xmlParseMemory(data, len);
-    if (i) {
+    if (i->doc) {
         i->root = xmlDocGetRootElement(i->doc);
         if (!i->root) {
             xmlFreeDoc(i->doc);
index 8dadf55..c2f73c6 100644 (file)
@@ -26,131 +26,62 @@ typedef struct {
     } u;
     gboolean send;
     gboolean follow;
-    gboolean interactive;
 } Options;
 
-static gpointer setup_go_func(xmlNodePtr node,
-                              ObActionsIPreFunc *pre,
-                              ObActionsIInputFunc *input,
-                              ObActionsICancelFunc *cancel,
-                              ObActionsIPostFunc *post);
-static gpointer setup_send_func(xmlNodePtr node,
-                                ObActionsIPreFunc *pre,
-                                ObActionsIInputFunc *input,
-                                ObActionsICancelFunc *cancel,
-                                ObActionsIPostFunc *post);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_send_func(xmlNodePtr node);
 static void free_func(gpointer o);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
-static gboolean i_pre_func(guint state, gpointer options);
-static gboolean i_input_func(guint initial_state,
-                             XEvent *e,
-                             ObtIC *ic,
-                             gpointer options,
-                             gboolean *used);
-static void i_post_func(gpointer options);
-
 /* 3.4-compatibility */
 static gpointer setup_go_last_func(xmlNodePtr node);
 static gpointer setup_send_last_func(xmlNodePtr node);
 static gpointer setup_go_abs_func(xmlNodePtr node);
-static gpointer setup_go_next_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post);
-static gpointer setup_send_next_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post);
-static gpointer setup_go_prev_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post);
-static gpointer setup_send_prev_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post);
-static gpointer setup_go_left_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post);
-static gpointer setup_send_left_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post);
-static gpointer setup_go_right_func(xmlNodePtr node,
-                                    ObActionsIPreFunc *pre,
-                                    ObActionsIInputFunc *input,
-                                    ObActionsICancelFunc *cancel,
-                                    ObActionsIPostFunc *post);
-static gpointer setup_send_right_func(xmlNodePtr node,
-                                      ObActionsIPreFunc *pre,
-                                      ObActionsIInputFunc *input,
-                                      ObActionsICancelFunc *cancel,
-                                      ObActionsIPostFunc *post);
-static gpointer setup_go_up_func(xmlNodePtr node,
-                                 ObActionsIPreFunc *pre,
-                                 ObActionsIInputFunc *input,
-                                 ObActionsICancelFunc *cancel,
-                                 ObActionsIPostFunc *post);
-static gpointer setup_send_up_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post);
-static gpointer setup_go_down_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post);
-static gpointer setup_send_down_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post);
+static gpointer setup_go_next_func(xmlNodePtr node);
+static gpointer setup_send_next_func(xmlNodePtr node);
+static gpointer setup_go_prev_func(xmlNodePtr node);
+static gpointer setup_send_prev_func(xmlNodePtr node);
+static gpointer setup_go_left_func(xmlNodePtr node);
+static gpointer setup_send_left_func(xmlNodePtr node);
+static gpointer setup_go_right_func(xmlNodePtr node);
+static gpointer setup_send_right_func(xmlNodePtr node);
+static gpointer setup_go_up_func(xmlNodePtr node);
+static gpointer setup_send_up_func(xmlNodePtr node);
+static gpointer setup_go_down_func(xmlNodePtr node);
+static gpointer setup_send_down_func(xmlNodePtr node);
 
 void action_desktop_startup(void)
 {
-    actions_register_i("GoToDesktop", setup_go_func, free_func, run_func);
-    actions_register_i("SendToDesktop", setup_send_func, free_func, run_func);
+    actions_register("GoToDesktop", setup_func, free_func, run_func);
+    actions_register("SendToDesktop", setup_send_func, free_func, run_func);
     /* 3.4-compatibility */
     actions_register("DesktopLast", setup_go_last_func, free_func, run_func);
     actions_register("SendToDesktopLast", setup_send_last_func,
                      free_func, run_func);
     actions_register("Desktop", setup_go_abs_func, free_func, run_func);
-    actions_register_i("DesktopNext", setup_go_next_func, free_func, run_func);
-    actions_register_i("SendToDesktopNext", setup_send_next_func,
-                       free_func, run_func);
-    actions_register_i("DesktopPrevious", setup_go_prev_func,
-                       free_func, run_func);
-    actions_register_i("SendToDesktopPrevious", setup_send_prev_func,
-                       free_func, run_func);
-    actions_register_i("DesktopLeft", setup_go_left_func, free_func, run_func);
-    actions_register_i("SendToDesktopLeft", setup_send_left_func,
-                       free_func, run_func);
-    actions_register_i("DesktopRight", setup_go_right_func,
-                       free_func, run_func);
-    actions_register_i("SendToDesktopRight", setup_send_right_func,
-                       free_func, run_func);
-    actions_register_i("DesktopUp", setup_go_up_func, free_func, run_func);
-    actions_register_i("SendToDesktopUp", setup_send_up_func,
-                       free_func, run_func);
-    actions_register_i("DesktopDown", setup_go_down_func, free_func, run_func);
-    actions_register_i("SendToDesktopDown", setup_send_down_func,
-                       free_func, run_func);
+    actions_register("DesktopNext", setup_go_next_func, free_func, run_func);
+    actions_register("SendToDesktopNext", setup_send_next_func,
+                     free_func, run_func);
+    actions_register("DesktopPrevious", setup_go_prev_func,
+                     free_func, run_func);
+    actions_register("SendToDesktopPrevious", setup_send_prev_func,
+                     free_func, run_func);
+    actions_register("DesktopLeft", setup_go_left_func, free_func, run_func);
+    actions_register("SendToDesktopLeft", setup_send_left_func,
+                     free_func, run_func);
+    actions_register("DesktopRight", setup_go_right_func,
+                     free_func, run_func);
+    actions_register("SendToDesktopRight", setup_send_right_func,
+                     free_func, run_func);
+    actions_register("DesktopUp", setup_go_up_func, free_func, run_func);
+    actions_register("SendToDesktopUp", setup_send_up_func,
+                     free_func, run_func);
+    actions_register("DesktopDown", setup_go_down_func, free_func, run_func);
+    actions_register("SendToDesktopDown", setup_send_down_func,
+                     free_func, run_func);
 }
 
-static gpointer setup_func(xmlNodePtr node,
-                           ObActionsIPreFunc *pre,
-                           ObActionsIInputFunc *input,
-                           ObActionsICancelFunc *cancel,
-                           ObActionsIPostFunc *post)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -211,36 +142,12 @@ static gpointer setup_func(xmlNodePtr node,
     return o;
 }
 
-
-static gpointer setup_go_func(xmlNodePtr node,
-                              ObActionsIPreFunc *pre,
-                              ObActionsIInputFunc *input,
-                              ObActionsICancelFunc *cancel,
-                              ObActionsIPostFunc *post)
-{
-    Options *o;
-
-    o = setup_func(node, pre, input, cancel, post);
-    if (o->type == RELATIVE) {
-        o->interactive = TRUE;
-        *pre = i_pre_func;
-        *input = i_input_func;
-        *post = i_post_func;
-    }
-
-    return o;
-}
-
-static gpointer setup_send_func(xmlNodePtr node,
-                                ObActionsIPreFunc *pre,
-                                ObActionsIInputFunc *input,
-                                ObActionsICancelFunc *cancel,
-                                ObActionsIPostFunc *post)
+static gpointer setup_send_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
-    o = setup_func(node, pre, input, cancel, post);
+    o = setup_func(node);
     if ((n = obt_xml_find_node(node, "desktop"))) {
         /* 3.4 compatibility */
         o->u.abs.desktop = obt_xml_node_int(n) - 1;
@@ -252,13 +159,6 @@ static gpointer setup_send_func(xmlNodePtr node,
     if ((n = obt_xml_find_node(node, "follow")))
         o->follow = obt_xml_node_bool(n);
 
-    if (o->type == RELATIVE && o->follow) {
-        o->interactive = TRUE;
-        *pre = i_pre_func;
-        *input = i_input_func;
-        *post = i_post_func;
-    }
-
     return o;
 }
 
@@ -310,62 +210,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         actions_client_move(data, FALSE);
     }
 
-    return o->interactive;
-}
-
-static gboolean i_input_func(guint initial_state,
-                             XEvent *e,
-                             ObtIC *ic,
-                             gpointer options,
-                             gboolean *used)
-{
-    guint mods, initial_mods;
-
-    initial_mods = obt_keyboard_only_modmasks(initial_state);
-    mods = obt_keyboard_only_modmasks(e->xkey.state);
-    if (e->type == KeyRelease) {
-        /* remove from the state the mask of the modifier key being
-           released, if it is a modifier key being released that is */
-        mods &= ~obt_keyboard_keyevent_to_modmask(e);
-    }
-
-    if (e->type == KeyPress) {
-        KeySym sym = obt_keyboard_keypress_to_keysym(e);
-
-        /* Escape cancels no matter what */
-        if (sym == XK_Escape)
-            return FALSE;
-
-        /* There were no modifiers and they pressed enter */
-        else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods)
-            return FALSE;
-    }
-    /* They released the modifiers */
-    else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
-    {
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static gboolean i_pre_func(guint initial_state, gpointer options)
-{
-    guint initial_mods = obt_keyboard_only_modmasks(initial_state);
-    if (!initial_mods) {
-        Options *o = options;
-        o->interactive = FALSE;
-        return FALSE;
-    }
-    else {
-        screen_show_desktop_popup(screen_desktop, TRUE);
-        return TRUE;
-    }
-}
-
-static void i_post_func(gpointer options)
-{
-    screen_hide_desktop_popup();
+    return FALSE;
 }
 
 /* 3.4-compatilibity */
@@ -407,10 +252,7 @@ static gpointer setup_go_abs_func(xmlNodePtr node)
 }
 
 static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
-                      ObDirection dir,
-                      ObActionsIPreFunc *pre,
-                      ObActionsIInputFunc *input,
-                      ObActionsIPostFunc *post)
+                      ObDirection dir)
 {
     xmlNodePtr n;
 
@@ -421,149 +263,88 @@ static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
 
     if ((n = obt_xml_find_node(node, "wrap")))
         o->u.rel.wrap = obt_xml_node_bool(n);
-
-    if (input) {
-        o->interactive = TRUE;
-        *pre = i_pre_func;
-        *input = i_input_func;
-        *post = i_post_func;
-    }
 }
 
-static gpointer setup_go_next_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post)
+static gpointer setup_go_next_func(xmlNodePtr node)
 {
     Options *o = g_slice_new0(Options);
-    setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post);
+    setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
     return o;
 }
 
-static gpointer setup_send_next_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post)
+static gpointer setup_send_next_func(xmlNodePtr node)
 {
     Options *o = setup_follow(node);
-    setup_rel(o, node, TRUE, OB_DIRECTION_EAST,
-              pre, (o->follow ? input : NULL), post);
+    setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
     return o;
 }
 
-static gpointer setup_go_prev_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post)
+static gpointer setup_go_prev_func(xmlNodePtr node)
 {
     Options *o = g_slice_new0(Options);
-    setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post);
+    setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
     return o;
 }
 
-static gpointer setup_send_prev_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post)
+static gpointer setup_send_prev_func(xmlNodePtr node)
 {
     Options *o = setup_follow(node);
-    setup_rel(o, node, TRUE, OB_DIRECTION_WEST,
-              pre, (o->follow ? input : NULL), post);
+    setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
     return o;
 }
 
-static gpointer setup_go_left_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post)
+static gpointer setup_go_left_func(xmlNodePtr node)
 {
     Options *o = g_slice_new0(Options);
-    setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
     return o;
 }
 
-static gpointer setup_send_left_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post)
+static gpointer setup_send_left_func(xmlNodePtr node)
 {
     Options *o = setup_follow(node);
-    setup_rel(o, node, FALSE, OB_DIRECTION_WEST,
-              pre, (o->follow ? input : NULL), post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
     return o;
 }
 
-static gpointer setup_go_right_func(xmlNodePtr node,
-                                    ObActionsIPreFunc *pre,
-                                    ObActionsIInputFunc *input,
-                                    ObActionsICancelFunc *cancel,
-                                    ObActionsIPostFunc *post)
+static gpointer setup_go_right_func(xmlNodePtr node)
 {
     Options *o = g_slice_new0(Options);
-    setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
     return o;
 }
 
-static gpointer setup_send_right_func(xmlNodePtr node,
-                                      ObActionsIPreFunc *pre,
-                                      ObActionsIInputFunc *input,
-                                      ObActionsICancelFunc *cancel,
-                                      ObActionsIPostFunc *post)
+static gpointer setup_send_right_func(xmlNodePtr node)
 {
     Options *o = setup_follow(node);
-    setup_rel(o, node, FALSE, OB_DIRECTION_EAST,
-              pre, (o->follow ? input : NULL), post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
     return o;
 }
 
-static gpointer setup_go_up_func(xmlNodePtr node,
-                                 ObActionsIPreFunc *pre,
-                                 ObActionsIInputFunc *input,
-                                 ObActionsICancelFunc *cancel,
-                                 ObActionsIPostFunc *post)
+static gpointer setup_go_up_func(xmlNodePtr node)
 {
     Options *o = g_slice_new0(Options);
-    setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
     return o;
 }
 
-static gpointer setup_send_up_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post)
+static gpointer setup_send_up_func(xmlNodePtr node)
 {
     Options *o = setup_follow(node);
-    setup_rel(o, node, FALSE, OB_DIRECTION_NORTH,
-              pre, (o->follow ? input : NULL), post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
     return o;
 }
 
-static gpointer setup_go_down_func(xmlNodePtr node,
-                                   ObActionsIPreFunc *pre,
-                                   ObActionsIInputFunc *input,
-                                   ObActionsICancelFunc *cancel,
-                                   ObActionsIPostFunc *post)
+static gpointer setup_go_down_func(xmlNodePtr node)
 {
     Options *o = g_slice_new0(Options);
-    setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
     return o;
 }
 
-static gpointer setup_send_down_func(xmlNodePtr node,
-                                     ObActionsIPreFunc *pre,
-                                     ObActionsIInputFunc *input,
-                                     ObActionsICancelFunc *cancel,
-                                     ObActionsIPostFunc *post)
+static gpointer setup_send_down_func(xmlNodePtr node)
 {
     Options *o = setup_follow(node);
-    setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH,
-              pre, (o->follow ? input : NULL), post);
+    setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
     return o;
 }
index d5a7bfd..acfbcfa 100644 (file)
@@ -8,9 +8,11 @@
 typedef struct {
     ObDirection dir;
     gboolean shrink;
+    gboolean fill;
 } Options;
 
-static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_grow_func(xmlNodePtr node);
+static gpointer setup_fill_func(xmlNodePtr node);
 static gpointer setup_shrink_func(xmlNodePtr node);
 static void free_func(gpointer o);
 static gboolean run_func(ObActionsData *data, gpointer options);
@@ -22,7 +24,9 @@ static gpointer setup_west_func(xmlNodePtr node);
 
 void action_growtoedge_startup(void)
 {
-    actions_register("GrowToEdge", setup_func,
+    actions_register("GrowToEdge", setup_grow_func,
+                     free_func, run_func);
+    actions_register("GrowToFill", setup_fill_func,
                      free_func, run_func);
     actions_register("ShrinkToEdge", setup_shrink_func,
                      free_func, run_func);
@@ -40,7 +44,6 @@ static gpointer setup_func(xmlNodePtr node)
 
     o = g_slice_new0(Options);
     o->dir = OB_DIRECTION_NORTH;
-    o->shrink = FALSE;
 
     if ((n = obt_xml_find_node(node, "direction"))) {
         gchar *s = obt_xml_node_string(n);
@@ -62,12 +65,35 @@ static gpointer setup_func(xmlNodePtr node)
     return o;
 }
 
+static gpointer setup_grow_func(xmlNodePtr node)
+{
+    Options *o;
+
+    o = setup_func(node);
+    o->shrink = FALSE;
+    o->fill = FALSE;
+
+    return o;
+}
+
+static gpointer setup_fill_func(xmlNodePtr node)
+{
+    Options *o;
+
+    o = setup_func(node);
+    o->shrink = FALSE;
+    o->fill = TRUE;
+
+    return o;
+}
+
 static gpointer setup_shrink_func(xmlNodePtr node)
 {
     Options *o;
 
     o = setup_func(node);
     o->shrink = TRUE;
+    o->fill = FALSE;
 
     return o;
 }
@@ -97,6 +123,58 @@ static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
     return FALSE;
 }
 
+static gboolean do_grow_all_edges(ObActionsData* data,
+                                  ObClientDirectionalResizeType resize_type)
+{
+    gint x, y, w, h;
+    gint temp_x, temp_y, temp_w, temp_h;
+
+    client_find_resize_directional(data->client,
+                                   OB_DIRECTION_NORTH,
+                                   resize_type,
+                                   &temp_x, &temp_y, &temp_w, &temp_h);
+    y = temp_y;
+    h = temp_h;
+
+    client_find_resize_directional(data->client,
+                                   OB_DIRECTION_SOUTH,
+                                   resize_type,
+                                   &temp_x, &temp_y, &temp_w, &temp_h);
+    h += temp_h - data->client->area.height;
+
+
+    client_find_resize_directional(data->client,
+                                   OB_DIRECTION_WEST,
+                                   resize_type,
+                                   &temp_x, &temp_y, &temp_w, &temp_h);
+    x = temp_x;
+    w = temp_w;
+
+    client_find_resize_directional(data->client,
+                                   OB_DIRECTION_EAST,
+                                   resize_type,
+                                   &temp_x, &temp_y, &temp_w, &temp_h);
+    w += temp_w - data->client->area.width;
+
+    /* When filling, we allow the window to move to an arbitrary x/y
+       position, since we'll be growing the other edge as well. */
+    int lw, lh;
+    client_try_configure(data->client, &x, &y, &w, &h, &lw, &lh, TRUE);
+
+    if (x == data->client->area.x &&
+        y == data->client->area.y &&
+        w == data->client->area.width &&
+        h == data->client->area.height)
+    {
+        return FALSE;
+    }
+
+    actions_client_move(data, TRUE);
+    client_move_resize(data->client, x, y, w, h);
+    actions_client_move(data, FALSE);
+    return TRUE;
+}
+
 static void free_func(gpointer o)
 {
     g_slice_free(Options, o);
@@ -106,34 +184,62 @@ static void free_func(gpointer o)
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
     Options *o = options;
-    gint x, y, w, h;
-    ObDirection opp;
-    gint half;
 
-    if (!data->client ||
-        /* don't allow vertical resize if shaded */
-        ((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) &&
-         data->client->shaded))
-    {
+    if (!data->client)
+        return FALSE;
+
+    gboolean doing_vertical_resize =
+        o->dir == OB_DIRECTION_NORTH ||
+        o->dir == OB_DIRECTION_SOUTH ||
+        o->fill;
+    if (data->client->shaded && doing_vertical_resize)
+            return FALSE;
+
+    if (o->fill) {
+        if (o->shrink) {
+            /* We don't have any implementation of shrinking for the FillToGrow
+               action. */
+            return FALSE;
+        }
+
+        if (do_grow_all_edges(data, CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE))
+            return FALSE;
+
+        /* If all the edges are blocked, then allow them to jump past their
+           current block points. */
+        do_grow_all_edges(data, CLIENT_RESIZE_GROW);
         return FALSE;
     }
 
     if (!o->shrink) {
-        /* try grow */
-        client_find_resize_directional(data->client, o->dir, TRUE,
+        gint x, y, w, h;
+
+        /* Try grow. */
+        client_find_resize_directional(data->client,
+                                       o->dir,
+                                       CLIENT_RESIZE_GROW,
                                        &x, &y, &w, &h);
+
         if (do_grow(data, x, y, w, h))
             return FALSE;
     }
 
-    /* we couldn't grow, so try shrink! */
-    opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
-           (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
-            (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
-             OB_DIRECTION_EAST)));
-    client_find_resize_directional(data->client, opp, FALSE,
+    /* We couldn't grow, so try shrink! */
+    ObDirection opposite =
+        (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
+         (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
+          (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
+           OB_DIRECTION_EAST)));
+
+    gint x, y, w, h;
+    gint half;
+
+    client_find_resize_directional(data->client,
+                                   opposite,
+                                   CLIENT_RESIZE_SHRINK,
                                    &x, &y, &w, &h);
-    switch (opp) {
+
+    switch (opposite) {
     case OB_DIRECTION_NORTH:
         half = data->client->area.y + data->client->area.height / 2;
         if (y > half) {
index a083d48..a9c4094 100644 (file)
@@ -79,10 +79,9 @@ typedef struct {
 } Query;
 
 typedef struct {
-    GArrayqueries;
+    GArray *queries;
     GSList *thenacts;
     GSList *elseacts;
-    gboolean stop;
 } Options;
 
 static gpointer setup_func(xmlNodePtr node);
@@ -91,6 +90,8 @@ static gboolean run_func_if(ObActionsData *data, gpointer options);
 static gboolean run_func_stop(ObActionsData *data, gpointer options);
 static gboolean run_func_foreach(ObActionsData *data, gpointer options);
 
+static gboolean foreach_stop;
+
 void action_if_startup(void)
 {
     actions_register("If", setup_func, free_func, run_func_if);
@@ -313,7 +314,7 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
     gboolean is_true = TRUE;
 
     guint i;
-    for (i = 0; i < o->queries->len; ++i) {
+    for (i = 0; is_true && i < o->queries->len; ++i) {
         Query *q = g_array_index(o->queries, Query*, i);
         ObClient *query_target = NULL;
 
@@ -327,7 +328,10 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
         }
 
         /* If there's no client to query, then false. */
-        is_true &= query_target != NULL;
+        if (!query_target) {
+            is_true = FALSE;
+            break;
+        }
 
         if (q->shaded_on)
             is_true &= query_target->shaded;
@@ -427,14 +431,14 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
 static gboolean run_func_foreach(ObActionsData *data, gpointer options)
 {
     GList *it;
-    Options *o = options;
 
-    o->stop = FALSE;
+    foreach_stop = FALSE;
 
     for (it = client_list; it; it = g_list_next(it)) {
         data->client = it->data;
         run_func_if(data, options);
-        if (o->stop) {
+        if (foreach_stop) {
+            foreach_stop = FALSE;
             break;
         }
     }
@@ -444,11 +448,9 @@ static gboolean run_func_foreach(ObActionsData *data, gpointer options)
 
 static gboolean run_func_stop(ObActionsData *data, gpointer options)
 {
-    Options *o = options;
-
     /* This stops the loop above so we don't invoke actions on any more
        clients */
-    o->stop = TRUE;
+    foreach_stop = TRUE;
 
     /* TRUE causes actions_run_acts to not run further actions on the current
        client */
index f6858d2..fc85c0b 100644 (file)
@@ -2,6 +2,7 @@
 #include "openbox/moveresize.h"
 #include "openbox/client.h"
 #include "openbox/frame.h"
+#include "openbox/screen.h"
 #include "obt/prop.h"
 
 typedef struct {
@@ -95,6 +96,12 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
                            gboolean shaded)
 {
+    const Rect *full = screen_physical_area_all_monitors();
+    if (cx < full->x) { cw = cw + cx - full->x; cx = full->x; }
+    if (cy < full->y) { ch = ch + cy - full->y; cy = full->y; }
+    if (cx + cw > full->x + full->width) cw = full->x + full->width - cx;
+    if (cy + ch > full->y + full->height) ch = full->y + full->height - cy;
+
     /* let's make x and y client relative instead of screen relative */
     x = x - cx;
     y = ch - (y - cy); /* y is inverted, 0 is at the bottom of the window */
index 6dc77d5..3c3b2d1 100644 (file)
@@ -1,17 +1,52 @@
 #include "openbox/actions.h"
 #include "openbox/screen.h"
 
+typedef struct {
+    /* If true, windows are unable to be shown while in the showing-desktop
+       state. */
+    gboolean strict;
+} Options;
+
+static gpointer setup_func(xmlNodePtr node);
+static void free_func(gpointer o);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_showdesktop_startup(void)
 {
-    actions_register("ToggleShowDesktop", NULL, NULL, run_func);
+    actions_register("ToggleShowDesktop", setup_func, free_func, run_func);
+}
+
+static gpointer setup_func(xmlNodePtr node)
+{
+    xmlNodePtr n;
+    Options *o = g_slice_new0(Options);
+    o->strict = FALSE;
+
+    if ((n = obt_xml_find_node(node, "strict")))
+        o->strict = obt_xml_node_bool(n);
+
+    return o;
+}
+
+static void free_func(gpointer o)
+{
+    g_slice_free(Options, o);
 }
 
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
-    screen_show_desktop(!screen_showing_desktop, NULL);
+    Options *o = options;
+
+    ObScreenShowDestopMode show_mode;
+    if (screen_showing_desktop())
+        show_mode = SCREEN_SHOW_DESKTOP_NO;
+    else if (!o->strict)
+        show_mode = SCREEN_SHOW_DESKTOP_UNTIL_WINDOW;
+    else
+        show_mode = SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE;
+
+    screen_show_desktop(show_mode, NULL);
 
     return FALSE;
 }
index 485a31d..7411e98 100644 (file)
@@ -1,9 +1,17 @@
 #include "openbox/actions.h"
 #include "openbox/menu.h"
+#include "openbox/place.h"
+#include "openbox/geom.h"
+#include "openbox/screen.h"
+#include "openbox/config.h"
 #include <glib.h>
 
 typedef struct {
-    gchar   *name;
+    gchar         *name;
+    GravityPoint   position;
+    ObPlaceMonitor monitor_type;
+    gint           monitor;
+    gboolean       use_position;
 } Options;
 
 static gpointer setup_func(xmlNodePtr node);
@@ -17,13 +25,50 @@ void action_showmenu_startup(void)
 
 static gpointer setup_func(xmlNodePtr node)
 {
-    xmlNodePtr n;
+    xmlNodePtr n, c;
     Options *o;
+    gboolean x_pos_given = FALSE;
 
     o = g_slice_new0(Options);
+    o->monitor = -1;
 
     if ((n = obt_xml_find_node(node, "menu")))
         o->name = obt_xml_node_string(n);
+
+    if ((n = obt_xml_find_node(node, "position"))) {
+        if ((c = obt_xml_find_node(n->children, "x"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                config_parse_gravity_coord(c, &o->position.x);
+                x_pos_given = TRUE;
+            }
+        }
+
+        if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                config_parse_gravity_coord(c, &o->position.y);
+                o->use_position = TRUE;
+            }
+        }
+
+        /* unlike client placement, x/y is needed to specify a monitor,
+         * either it's under the mouse or it's in an exact actual position */
+        if (o->use_position && (c = obt_xml_find_node(n->children, "monitor"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                gchar *s = obt_xml_node_string(c);
+                if (!g_ascii_strcasecmp(s, "mouse"))
+                    o->monitor_type = OB_PLACE_MONITOR_MOUSE;
+                else if (!g_ascii_strcasecmp(s, "active"))
+                    o->monitor_type = OB_PLACE_MONITOR_ACTIVE;
+                else if (!g_ascii_strcasecmp(s, "primary"))
+                    o->monitor_type = OB_PLACE_MONITOR_PRIMARY;
+                else if (!g_ascii_strcasecmp(s, "all"))
+                    o->monitor_type = OB_PLACE_MONITOR_ALL;
+                else
+                    o->monitor = obt_xml_node_int(c) - 1;
+                g_free(s);
+            }
+        }
+    }
     return o;
 }
 
@@ -38,10 +83,43 @@ static void free_func(gpointer options)
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
     Options *o = options;
+    GravityPoint position = { { 0, }, };
+    gint monitor = -1;
+
+    if (o->use_position) {
+        if (o->monitor >= 0)
+            monitor = o->monitor;
+        else switch (o->monitor_type) {
+            case OB_PLACE_MONITOR_ANY:
+            case OB_PLACE_MONITOR_PRIMARY:
+                monitor = screen_monitor_primary(FALSE);
+                break;
+            case OB_PLACE_MONITOR_MOUSE:
+                monitor = screen_monitor_pointer();
+                break;
+            case OB_PLACE_MONITOR_ACTIVE:
+                monitor = screen_monitor_active();
+                break;
+            case OB_PLACE_MONITOR_ALL:
+                monitor = screen_num_monitors;
+                break;
+            default:
+                g_assert_not_reached();
+        }
+
+        position = o->position;
+    } else {
+        const Rect *allmon;
+        monitor = screen_num_monitors;
+        allmon = screen_physical_area_monitor(monitor);
+        position.x.pos = data->x - allmon->x;
+        position.y.pos = data->y - allmon->y;
+    }
 
     /* you cannot call ShowMenu from inside a menu */
     if (data->uact != OB_USER_ACTION_MENU_SELECTION && o->name)
-        menu_show(o->name, data->x, data->y, data->button != 0, data->client);
+        menu_show(o->name, &position, monitor,
+                  data->button != 0, o->use_position, data->client);
 
     return FALSE;
 }
index c97abd5..3ff278a 100644 (file)
@@ -2734,7 +2734,7 @@ gboolean client_should_show(ObClient *self)
 {
     if (self->iconic)
         return FALSE;
-    if (client_normal(self) && screen_showing_desktop)
+    if (client_normal(self) && screen_showing_desktop())
         return FALSE;
     if (self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
         return TRUE;
@@ -4080,7 +4080,7 @@ gboolean client_focus(ObClient *self)
 static void client_present(ObClient *self, gboolean here, gboolean raise,
                            gboolean unshade)
 {
-    if (client_normal(self) && screen_showing_desktop)
+    if (client_normal(self) && screen_showing_desktop())
         screen_show_desktop(FALSE, self);
     if (self->iconic)
         client_iconify(self, FALSE, here, FALSE);
@@ -4535,8 +4535,9 @@ void client_find_move_directional(ObClient *self, ObDirection dir,
     frame_frame_gravity(self->frame, x, y);
 }
 
-void client_find_resize_directional(ObClient *self, ObDirection side,
-                                    gboolean grow,
+void client_find_resize_directional(ObClient *self,
+                                    ObDirection side,
+                                    ObClientDirectionalResizeType resize_type,
                                     gint *x, gint *y, gint *w, gint *h)
 {
     gint head;
@@ -4544,31 +4545,84 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
     gboolean near;
     ObDirection dir;
 
+    gboolean grow;
+    switch (resize_type) {
+    case CLIENT_RESIZE_GROW:
+        grow = TRUE;
+        break;
+    case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+        grow = TRUE;
+        break;
+    case CLIENT_RESIZE_SHRINK:
+        grow = FALSE;
+        break;
+    }
+
     switch (side) {
     case OB_DIRECTION_EAST:
-        head = RECT_RIGHT(self->frame->area) +
-            (self->size_inc.width - 1) * (grow ? 1 : 0);
+        head = RECT_RIGHT(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head += self->size_inc.width - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head -= 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_TOP(self->frame->area);
         e_size = self->frame->area.height;
         dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
         break;
     case OB_DIRECTION_WEST:
-        head = RECT_LEFT(self->frame->area) -
-            (self->size_inc.width - 1) * (grow ? 1 : 0);
+        head = RECT_LEFT(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head -= self->size_inc.width - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head += 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_TOP(self->frame->area);
         e_size = self->frame->area.height;
         dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
         break;
     case OB_DIRECTION_NORTH:
-        head = RECT_TOP(self->frame->area) -
-            (self->size_inc.height - 1) * (grow ? 1 : 0);
+        head = RECT_TOP(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head -= self->size_inc.height - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head += 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_LEFT(self->frame->area);
         e_size = self->frame->area.width;
         dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
         break;
     case OB_DIRECTION_SOUTH:
-        head = RECT_BOTTOM(self->frame->area) +
-            (self->size_inc.height - 1) * (grow ? 1 : 0);
+        head = RECT_BOTTOM(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head += self->size_inc.height - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head -= 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_LEFT(self->frame->area);
         e_size = self->frame->area.width;
         dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;
@@ -4607,7 +4661,7 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
         if (grow == near) --e;
         delta = e - RECT_BOTTOM(self->frame->area);
         *h += delta;
-        break;
+       break;
     default:
         g_assert_not_reached();
     }
index 5ae2d3d..11a0140 100644 (file)
@@ -489,8 +489,17 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
                                   gint *dest, gboolean *near_edge);
 void client_find_move_directional(ObClient *self, ObDirection dir,
                                   gint *x, gint *y);
-void client_find_resize_directional(ObClient *self, ObDirection side,
-                                    gboolean grow,
+
+typedef enum {
+    CLIENT_RESIZE_GROW,
+    CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE,
+    CLIENT_RESIZE_SHRINK,
+} ObClientDirectionalResizeType;
+
+/*! Moves the client area passed in to grow/shrink the given edge. */
+void client_find_resize_directional(ObClient *self,
+                                    ObDirection side,
+                                    ObClientDirectionalResizeType resize_type,
                                     gint *x, gint *y, gint *w, gint *h);
 
 /*! Fullscreen's or unfullscreen's the client window
index c6cdd63..4a3b286 100644 (file)
@@ -276,7 +276,7 @@ static gboolean send_to_menu_update(ObMenuFrame *frame, gpointer data)
         if ((desk == DESKTOP_ALL && c->desktop != DESKTOP_ALL) ||
             (c->desktop == DESKTOP_ALL && desk == screen_desktop))
         {
-            e->data.normal.mask = ob_rr_theme->btn_desk->mask;
+            e->data.normal.mask = ob_rr_theme->btn_desk->unpressed_mask;
             set_icon_color(e);
         } else
             e->data.normal.mask = NULL;
@@ -392,7 +392,7 @@ void client_menu_startup(void)
     menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME);
 
     e = menu_add_normal(menu, CLIENT_RESTORE, _("R_estore"), NULL, TRUE);
-    e->data.normal.mask = ob_rr_theme->btn_max->toggled_mask;
+    e->data.normal.mask = ob_rr_theme->btn_max->unpressed_toggled_mask;
     set_icon_color(e);
 
     menu_add_normal(menu, CLIENT_MOVE, _("_Move"), NULL, TRUE);
@@ -400,15 +400,15 @@ void client_menu_startup(void)
     menu_add_normal(menu, CLIENT_RESIZE, _("Resi_ze"), NULL, TRUE);
 
     e = menu_add_normal(menu, CLIENT_ICONIFY, _("Ico_nify"), NULL, TRUE);
-    e->data.normal.mask = ob_rr_theme->btn_iconify->mask;
+    e->data.normal.mask = ob_rr_theme->btn_iconify->unpressed_mask;
     set_icon_color(e);
 
     e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Ma_ximize"), NULL, TRUE);
-    e->data.normal.mask = ob_rr_theme->btn_max->mask;
+    e->data.normal.mask = ob_rr_theme->btn_max->unpressed_mask;
     set_icon_color(e);
 
     e = menu_add_normal(menu, CLIENT_SHADE, _("_Roll up/down"), NULL, TRUE);
-    e->data.normal.mask = ob_rr_theme->btn_shade->mask;
+    e->data.normal.mask = ob_rr_theme->btn_shade->unpressed_mask;
     set_icon_color(e);
 
     menu_add_normal(menu, CLIENT_DECORATE, _("Un/_Decorate"), NULL, TRUE);
@@ -416,6 +416,6 @@ void client_menu_startup(void)
     menu_add_separator(menu, -1, NULL);
 
     e = menu_add_normal(menu, CLIENT_CLOSE, _("_Close"), NULL, TRUE);
-    e->data.normal.mask = ob_rr_theme->btn_close->mask;
+    e->data.normal.mask = ob_rr_theme->btn_close->unpressed_mask;
     set_icon_color(e);
 }
index 76f4856..dad5d1b 100644 (file)
@@ -83,8 +83,9 @@ guint           config_dock_show_delay;
 guint           config_dock_app_move_button;
 guint           config_dock_app_move_modifiers;
 
-guint config_keyboard_reset_keycode;
-guint config_keyboard_reset_state;
+guint    config_keyboard_reset_keycode;
+guint    config_keyboard_reset_state;
+gboolean config_keyboard_rebind_on_mapping_notify;
 
 gint     config_mouse_threshold;
 gint     config_mouse_dclicktime;
@@ -503,6 +504,9 @@ static void parse_keyboard(xmlNodePtr node, gpointer d)
             parse_key(n, NULL);
             n = obt_xml_find_node(n->next, "keybind");
         }
+
+    if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
+        config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
 }
 
 /*
@@ -540,13 +544,15 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
     if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
         config_mouse_screenedgewarp = obt_xml_node_bool(n);
 
-    n = obt_xml_find_node(node, "context");
-    while (n) {
+    for (n = obt_xml_find_node(node, "context");
+         n;
+         n = obt_xml_find_node(n->next, "context"))
+    {
         gchar *modcxstr;
         ObFrameContext cx;
 
         if (!obt_xml_attr_string(n, "name", &cxstr))
-            goto next_n;
+            continue;
 
         modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
         while (frame_next_context_from_string(modcxstr, &cx)) {
@@ -561,10 +567,15 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
                 continue;
             }
 
-            nbut = obt_xml_find_node(n->children, "mousebind");
-            while (nbut) {
+            for (nbut = obt_xml_find_node(n->children, "mousebind");
+                 nbut;
+                 nbut = obt_xml_find_node(nbut->next, "mousebind"))
+            {
+
+                gchar **button, **buttons;
+
                 if (!obt_xml_attr_string(nbut, "button", &buttonstr))
-                    goto next_nbut;
+                    continue;
                 if (obt_xml_attr_contains(nbut, "action", "press"))
                     mact = OB_MOUSE_ACTION_PRESS;
                 else if (obt_xml_attr_contains(nbut, "action", "release"))
@@ -576,25 +587,31 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
                 else if (obt_xml_attr_contains(nbut, "action", "drag"))
                     mact = OB_MOUSE_ACTION_MOTION;
                 else
-                    goto next_nbut;
+                    continue;
 
-                nact = obt_xml_find_node(nbut->children, "action");
-                while (nact) {
+                buttons = g_strsplit(buttonstr, " ", 0);
+                for (nact = obt_xml_find_node(nbut->children, "action");
+                     nact;
+                     nact = obt_xml_find_node(nact->next, "action"))
+                {
                     ObActionsAct *action;
 
-                    if ((action = actions_parse(nact)))
-                        mouse_bind(buttonstr, cx, mact, action);
-                    nact = obt_xml_find_node(nact->next, "action");
+                    /* actions_parse() creates one ref to the action, but we need
+                     * exactly one ref per binding we use it for. */
+                    if ((action = actions_parse(nact))) {
+                        for (button = buttons; *button; ++button) {
+                            actions_act_ref(action);
+                            mouse_bind(*button, cx, mact, action);
+                        }
+                        actions_act_unref(action);
+                    }
                 }
-            g_free(buttonstr);
-            next_nbut:
-            nbut = obt_xml_find_node(nbut->next, "mousebind");
+                g_strfreev(buttons);
+                g_free(buttonstr);
             }
         }
         g_free(modcxstr);
         g_free(cxstr);
-    next_n:
-        n = obt_xml_find_node(n->next, "context");
     }
 }
 
@@ -703,8 +720,10 @@ static void parse_theme(xmlNodePtr node, gpointer d)
             config_theme_window_list_icon_size = 96;
     }
 
-    n = obt_xml_find_node(node, "font");
-    while (n) {
+    for (n = obt_xml_find_node(node, "font");
+         n;
+         n = obt_xml_find_node(n->next, "font"))
+    {
         xmlNodePtr   fnode;
         RrFont     **font;
         gchar       *name = g_strdup(RrDefaultFontFamily);
@@ -727,7 +746,7 @@ static void parse_theme(xmlNodePtr node, gpointer d)
         else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
             font = &config_font_inactiveosd;
         else
-            goto next_font;
+            continue;
 
         if ((fnode = obt_xml_find_node(n->children, "name"))) {
             g_free(name);
@@ -754,8 +773,6 @@ static void parse_theme(xmlNodePtr node, gpointer d)
 
         *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
         g_free(name);
-    next_font:
-        n = obt_xml_find_node(n->next, "font");
     }
 }
 
@@ -784,12 +801,13 @@ static void parse_desktops(xmlNodePtr node, gpointer d)
         g_slist_free(config_desktops_names);
         config_desktops_names = NULL;
 
-        nname = obt_xml_find_node(n->children, "name");
-        while (nname) {
+        for (nname = obt_xml_find_node(n->children, "name");
+             nname;
+             nname = obt_xml_find_node(nname->next, "name"))
+        {
             config_desktops_names =
                 g_slist_append(config_desktops_names,
                                obt_xml_node_string(nname));
-            nname = obt_xml_find_node(nname->next, "name");
         }
     }
     if ((n = obt_xml_find_node(node, "popupTime")))
@@ -905,7 +923,7 @@ static void parse_dock(xmlNodePtr node, gpointer d)
         config_dock_show_delay = obt_xml_node_int(n);
     if ((n = obt_xml_find_node(node, "moveButton"))) {
         gchar *str = obt_xml_node_string(n);
-        guint b, s;
+        guint b = 0, s = 0;
         if (translate_button(str, &s, &b)) {
             config_dock_app_move_button = b;
             config_dock_app_move_modifiers = s;
@@ -939,12 +957,14 @@ static void parse_menu(xmlNodePtr node, gpointer d)
 #endif
     }
 
-    while ((node = obt_xml_find_node(node, "file"))) {
+    for (node = obt_xml_find_node(node, "file");
+         node;
+         node = obt_xml_find_node(node->next, "file"))
+    {
             gchar *c = obt_xml_node_string(node);
             config_menu_files = g_slist_append(config_menu_files,
                                                obt_paths_expand_tilde(c));
             g_free(c);
-            node = node->next;
     }
 }
 
@@ -1120,6 +1140,7 @@ void config_startup(ObtXmlInst *i)
 
     translate_key("C-g", &config_keyboard_reset_state,
                   &config_keyboard_reset_keycode);
+    config_keyboard_rebind_on_mapping_notify = TRUE;
 
     bind_default_keyboard();
 
index fc1d217..96a66cf 100644 (file)
@@ -179,6 +179,8 @@ extern guint config_desktop_popup_time;
 extern guint config_keyboard_reset_keycode;
 /*! The modifiers of the key combo which resets the keybaord chains */
 extern guint config_keyboard_reset_state;
+/*! Reload the keyboard bindings when the mapping changes */
+extern gboolean config_keyboard_rebind_on_mapping_notify;
 
 /*! Number of pixels a drag must go before being considered a drag */
 extern gint config_mouse_threshold;
index f18683d..ea9b7f4 100644 (file)
@@ -632,8 +632,6 @@ static gboolean hide_timeout(gpointer data)
     dock->hidden = TRUE;
     dock_configure();
 
-    hide_timeout_id = 0;
-
     return FALSE; /* don't repeat */
 }
 
@@ -643,30 +641,32 @@ static gboolean show_timeout(gpointer data)
     dock->hidden = FALSE;
     dock_configure();
 
-    show_timeout_id = 0;
-
     return FALSE; /* don't repeat */
 }
 
+static void destroy_timeout(gpointer data)
+{
+    gint *id = data;
+    *id = 0;
+}
+
 void dock_hide(gboolean hide)
 {
     if (!hide) {
         if (dock->hidden && config_dock_hide) {
             show_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
                                                  config_dock_show_delay,
-                                                 show_timeout, NULL, NULL);
+                                                 show_timeout, &show_timeout_id, destroy_timeout);
         } else if (!dock->hidden && config_dock_hide && hide_timeout_id) {
             if (hide_timeout_id) g_source_remove(hide_timeout_id);
-            hide_timeout_id = 0;
         }
     } else {
         if (!dock->hidden && config_dock_hide) {
             hide_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
                                                  config_dock_hide_delay,
-                                                 hide_timeout, NULL, NULL);
+                                                 hide_timeout, &hide_timeout_id, destroy_timeout);
         } else if (dock->hidden && config_dock_hide && show_timeout_id) {
             if (show_timeout_id) g_source_remove(show_timeout_id);
-            show_timeout_id = 0;
         }
     }
 }
index 1b3a0e4..5774f67 100644 (file)
@@ -206,6 +206,7 @@ static Window event_get_window(XEvent *e)
             switch (((XkbAnyEvent*)e)->xkb_type) {
             case XkbBellNotify:
                 window = ((XkbBellNotifyEvent*)e)->window;
+                break;
             default:
                 window = None;
             }
@@ -636,11 +637,13 @@ static void event_process(const XEvent *ec, gpointer data)
     else if (e->type == MappingNotify) {
         /* keyboard layout changes for modifier mapping changes. reload the
            modifier map, and rebind all the key bindings as appropriate */
-        ob_debug("Keyboard map changed. Reloading keyboard bindings.");
-        ob_set_state(OB_STATE_RECONFIGURING);
-        obt_keyboard_reload();
-        keyboard_rebind();
-        ob_set_state(OB_STATE_RUNNING);
+        if (config_keyboard_rebind_on_mapping_notify) {
+            ob_debug("Keyboard map changed. Reloading keyboard bindings.");
+            ob_set_state(OB_STATE_RECONFIGURING);
+            obt_keyboard_reload();
+            keyboard_rebind();
+            ob_set_state(OB_STATE_RUNNING);
+        }
     }
     else if (e->type == ClientMessage) {
         /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
@@ -772,7 +775,12 @@ static void event_handle_root(XEvent *e)
             if (d > 0 && d <= 1000)
                 screen_set_num_desktops(d);
         } else if (msgtype == OBT_PROP_ATOM(NET_SHOWING_DESKTOP)) {
-            screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
+            ObScreenShowDestopMode show_mode;
+            if (e->xclient.data.l[0] != 0)
+                show_mode = SCREEN_SHOW_DESKTOP_UNTIL_WINDOW;
+            else
+                show_mode = SCREEN_SHOW_DESKTOP_NO;
+            screen_show_desktop(show_mode, NULL);
         } else if (msgtype == OBT_PROP_ATOM(OB_CONTROL)) {
             ob_debug("OB_CONTROL: %d", e->xclient.data.l[0]);
             if (e->xclient.data.l[0] == 1)
@@ -1190,7 +1198,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             }
 
         if (e->xconfigurerequest.value_mask & CWStackMode) {
-            ObClient *sibling = NULL;
+            ObWindow *sibling = NULL;
             gulong ignore_start;
             gboolean ok = TRUE;
 
@@ -1201,7 +1209,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 if (win && WINDOW_IS_CLIENT(win) &&
                     WINDOW_AS_CLIENT(win) != client)
                 {
-                    sibling = WINDOW_AS_CLIENT(win);
+                    sibling = win;
+                }
+                else if (win && WINDOW_IS_DOCK(win))
+                {
+                    sibling = win;
                 }
                 else
                     /* an invalid sibling was specified so don't restack at
@@ -1552,13 +1564,17 @@ static void event_handle_client(ObClient *client, XEvent *e)
                               "invalid source indication %ld",
                               client->title, e->xclient.data.l[0]);
             } else {
-                ObClient *sibling = NULL;
+                ObWindow *sibling = NULL;
                 if (e->xclient.data.l[1]) {
                     ObWindow *win = window_find(e->xclient.data.l[1]);
                     if (WINDOW_IS_CLIENT(win) &&
                         WINDOW_AS_CLIENT(win) != client)
                     {
-                        sibling = WINDOW_AS_CLIENT(win);
+                        sibling = win;
+                    }
+                    if (WINDOW_IS_DOCK(win))
+                    {
+                        sibling = win;
                     }
                     if (sibling == NULL)
                         ob_debug_type(OB_DEBUG_APP_BUGS,
@@ -1820,8 +1836,14 @@ static gboolean event_handle_menu_input(XEvent *ev)
             if ((e = menu_entry_frame_under(ev->xbutton.x_root,
                                             ev->xbutton.y_root)))
             {
-                if (ev->type == ButtonPress && e->frame->child)
-                    menu_frame_select(e->frame->child, NULL, TRUE);
+                if (ev->type == ButtonPress) {
+                    /* We know this is a new press, so we don't have to
+                     * block release events anymore */
+                    menu_hide_delay_reset();
+
+                    if (e->frame->child)
+                        menu_frame_select(e->frame->child, NULL, TRUE);
+                }
                 menu_frame_select(e->frame, e, TRUE);
                 if (ev->type == ButtonRelease)
                     menu_entry_frame_execute(e, ev->xbutton.state);
@@ -2106,6 +2128,7 @@ static gboolean focus_delay_func(gpointer data)
     if (client_focus(d->client) && config_focus_raise)
         stacking_raise(CLIENT_AS_WINDOW(d->client));
     event_curtime = old;
+
     return FALSE; /* no repeat */
 }
 
@@ -2118,6 +2141,7 @@ static gboolean unfocus_delay_func(gpointer data)
     event_curserial = d->serial;
     focus_nothing();
     event_curtime = old;
+
     return FALSE; /* no repeat */
 }
 
index 3dbcf12..8966972 100644 (file)
@@ -1664,8 +1664,7 @@ static void flash_done(gpointer data)
 {
     ObFrame *self = data;
 
-    if (self->focused != self->flash_on)
-        frame_adjust_focus(self, self->focused);
+    self->flash_timer = 0;
 }
 
 static gboolean flash_timeout(gpointer data)
@@ -1679,8 +1678,12 @@ static gboolean flash_timeout(gpointer data)
          now.tv_usec >= self->flash_end.tv_usec))
         self->flashing = FALSE;
 
-    if (!self->flashing)
+    if (!self->flashing) {
+        if (self->focused != self->flash_on)
+            frame_adjust_focus(self, self->focused);
+
         return FALSE; /* we are done */
+    }
 
     self->flash_on = !self->flash_on;
     if (!self->focused) {
@@ -1787,14 +1790,12 @@ static gboolean frame_animate_iconify(gpointer p)
     XMoveResizeWindow(obt_display, self->window, x, y, w, h);
     XFlush(obt_display);
 
-    if (time == 0)
-        frame_end_iconify_animation(self);
-
     return time > 0; /* repeat until we're out of time */
 }
 
-void frame_end_iconify_animation(ObFrame *self)
+void frame_end_iconify_animation(gpointer data)
 {
+    ObFrame *self = data;
     /* see if there is an animation going */
     if (self->iconify_animation_going == 0) return;
 
@@ -1811,6 +1812,7 @@ void frame_end_iconify_animation(ObFrame *self)
 
     /* we're not animating any more ! */
     self->iconify_animation_going = 0;
+    self->iconify_animation_timer = 0;
 
     XMoveResizeWindow(obt_display, self->window,
                       self->area.x, self->area.y,
@@ -1861,7 +1863,8 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying)
         self->iconify_animation_timer =
             g_timeout_add_full(G_PRIORITY_DEFAULT,
                                FRAME_ANIMATE_ICONIFY_STEP_TIME,
-                               frame_animate_iconify, self, NULL);
+                               frame_animate_iconify, self,
+                               frame_end_iconify_animation);
                                
 
         /* do the first step */
index 915c08d..ae29c3b 100644 (file)
@@ -265,7 +265,7 @@ void frame_flash_stop(ObFrame *self);
   will be called when the animation finishes. But if another animation is
   started in the meantime, the callback will never get called. */
 void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying);
-void frame_end_iconify_animation(ObFrame *self);
+void frame_end_iconify_animation(gpointer data);
 
 #define frame_iconify_animating(f) (f->iconify_animation_going != 0)
 
index 041e6d1..094d596 100644 (file)
@@ -131,115 +131,115 @@ void framerender_frame(ObFrame *self)
             t = ob_rr_theme->a_focused_title;
             l = ob_rr_theme->a_focused_label;
             m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
-                 ob_rr_theme->btn_max->a_disabled_focused :
+                 ob_rr_theme->btn_max->a_focused_disabled :
                  (self->client->max_vert || self->client->max_horz ?
                   (self->max_press ?
-                   ob_rr_theme->btn_max->a_toggled_focused_pressed :
+                   ob_rr_theme->btn_max->a_focused_pressed_toggled :
                    (self->max_hover ?
-                    ob_rr_theme->btn_max->a_toggled_hover_focused :
-                    ob_rr_theme->btn_max->a_toggled_focused_unpressed)) :
+                    ob_rr_theme->btn_max->a_focused_hover_toggled :
+                    ob_rr_theme->btn_max->a_focused_unpressed_toggled)) :
                   (self->max_press ?
                    ob_rr_theme->btn_max->a_focused_pressed :
                    (self->max_hover ?
-                    ob_rr_theme->btn_max->a_hover_focused :
+                    ob_rr_theme->btn_max->a_focused_hover :
                     ob_rr_theme->btn_max->a_focused_unpressed))));
             n = ob_rr_theme->a_icon;
             i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
-                 ob_rr_theme->btn_iconify->a_disabled_focused :
+                 ob_rr_theme->btn_iconify->a_focused_disabled :
                  (self->iconify_press ?
                   ob_rr_theme->btn_iconify->a_focused_pressed :
                   (self->iconify_hover ?
-                   ob_rr_theme->btn_iconify->a_hover_focused :
+                   ob_rr_theme->btn_iconify->a_focused_hover :
                    ob_rr_theme->btn_iconify->a_focused_unpressed)));
             d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
-                 ob_rr_theme->btn_desk->a_disabled_focused :
+                 ob_rr_theme->btn_desk->a_focused_disabled :
                  (self->client->desktop == DESKTOP_ALL ?
                   (self->desk_press ?
-                   ob_rr_theme->btn_desk->a_toggled_focused_pressed :
+                   ob_rr_theme->btn_desk->a_focused_pressed_toggled :
                    (self->desk_hover ?
-                    ob_rr_theme->btn_desk->a_toggled_hover_focused :
-                    ob_rr_theme->btn_desk->a_toggled_focused_unpressed)) :
+                    ob_rr_theme->btn_desk->a_focused_hover_toggled :
+                    ob_rr_theme->btn_desk->a_focused_unpressed_toggled)) :
                   (self->desk_press ?
                    ob_rr_theme->btn_desk->a_focused_pressed :
                    (self->desk_hover ?
-                    ob_rr_theme->btn_desk->a_hover_focused :
+                    ob_rr_theme->btn_desk->a_focused_hover :
                     ob_rr_theme->btn_desk->a_focused_unpressed))));
             s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
-                 ob_rr_theme->btn_shade->a_disabled_focused :
+                 ob_rr_theme->btn_shade->a_focused_disabled :
                  (self->client->shaded ?
                   (self->shade_press ?
-                   ob_rr_theme->btn_shade->a_toggled_focused_pressed :
+                   ob_rr_theme->btn_shade->a_focused_pressed_toggled :
                    (self->shade_hover ?
-                    ob_rr_theme->btn_shade->a_toggled_hover_focused :
-                    ob_rr_theme->btn_shade->a_toggled_focused_unpressed)) :
+                    ob_rr_theme->btn_shade->a_focused_hover_toggled :
+                    ob_rr_theme->btn_shade->a_focused_unpressed_toggled)) :
                   (self->shade_press ?
                    ob_rr_theme->btn_shade->a_focused_pressed :
                    (self->shade_hover ?
-                    ob_rr_theme->btn_shade->a_hover_focused :
+                    ob_rr_theme->btn_shade->a_focused_hover :
                     ob_rr_theme->btn_shade->a_focused_unpressed))));
             c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
-                 ob_rr_theme->btn_close->a_disabled_focused :
+                 ob_rr_theme->btn_close->a_focused_disabled :
                  (self->close_press ?
                   ob_rr_theme->btn_close->a_focused_pressed :
                   (self->close_hover ?
-                   ob_rr_theme->btn_close->a_hover_focused :
+                   ob_rr_theme->btn_close->a_focused_hover :
                    ob_rr_theme->btn_close->a_focused_unpressed)));
         } else {
             t = ob_rr_theme->a_unfocused_title;
             l = ob_rr_theme->a_unfocused_label;
             m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
-                 ob_rr_theme->btn_max->a_disabled_unfocused :
+                 ob_rr_theme->btn_max->a_unfocused_disabled :
                  (self->client->max_vert || self->client->max_horz ?
                   (self->max_press ?
-                   ob_rr_theme->btn_max->a_toggled_unfocused_pressed :
+                   ob_rr_theme->btn_max->a_unfocused_pressed_toggled :
                    (self->max_hover ?
-                    ob_rr_theme->btn_max->a_toggled_hover_unfocused :
-                    ob_rr_theme->btn_max->a_toggled_unfocused_unpressed)) :
+                    ob_rr_theme->btn_max->a_unfocused_hover_toggled :
+                    ob_rr_theme->btn_max->a_unfocused_unpressed_toggled)) :
                   (self->max_press ?
                    ob_rr_theme->btn_max->a_unfocused_pressed :
                    (self->max_hover ?
-                    ob_rr_theme->btn_max->a_hover_unfocused :
+                    ob_rr_theme->btn_max->a_unfocused_hover :
                     ob_rr_theme->btn_max->a_unfocused_unpressed))));
             n = ob_rr_theme->a_icon;
             i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
-                 ob_rr_theme->btn_iconify->a_disabled_unfocused :
+                 ob_rr_theme->btn_iconify->a_unfocused_disabled :
                  (self->iconify_press ?
                   ob_rr_theme->btn_iconify->a_unfocused_pressed :
                   (self->iconify_hover ?
-                   ob_rr_theme->btn_iconify->a_hover_unfocused :
+                   ob_rr_theme->btn_iconify->a_unfocused_hover :
                    ob_rr_theme->btn_iconify->a_unfocused_unpressed)));
             d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
-                 ob_rr_theme->btn_desk->a_disabled_unfocused :
+                 ob_rr_theme->btn_desk->a_unfocused_disabled :
                  (self->client->desktop == DESKTOP_ALL ?
                   (self->desk_press ?
-                   ob_rr_theme->btn_desk->a_toggled_unfocused_pressed :
+                   ob_rr_theme->btn_desk->a_unfocused_pressed_toggled :
                    (self->desk_hover ?
-                    ob_rr_theme->btn_desk->a_toggled_hover_unfocused :
-                    ob_rr_theme->btn_desk->a_toggled_unfocused_unpressed)) :
+                    ob_rr_theme->btn_desk->a_unfocused_hover_toggled :
+                    ob_rr_theme->btn_desk->a_unfocused_unpressed_toggled)) :
                   (self->desk_press ?
                    ob_rr_theme->btn_desk->a_unfocused_pressed :
                    (self->desk_hover ?
-                    ob_rr_theme->btn_desk->a_hover_unfocused :
+                    ob_rr_theme->btn_desk->a_unfocused_hover :
                     ob_rr_theme->btn_desk->a_unfocused_unpressed))));
             s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
-                 ob_rr_theme->btn_shade->a_disabled_unfocused :
+                 ob_rr_theme->btn_shade->a_unfocused_disabled :
                  (self->client->shaded ?
                   (self->shade_press ?
-                   ob_rr_theme->btn_shade->a_toggled_unfocused_pressed :
+                   ob_rr_theme->btn_shade->a_unfocused_pressed_toggled :
                    (self->shade_hover ?
-                    ob_rr_theme->btn_shade->a_toggled_hover_unfocused :
-                    ob_rr_theme->btn_shade->a_toggled_unfocused_unpressed)) :
+                    ob_rr_theme->btn_shade->a_unfocused_hover_toggled :
+                    ob_rr_theme->btn_shade->a_unfocused_unpressed_toggled)) :
                   (self->shade_press ?
                    ob_rr_theme->btn_shade->a_unfocused_pressed :
                    (self->shade_hover ?
-                    ob_rr_theme->btn_shade->a_hover_unfocused :
+                    ob_rr_theme->btn_shade->a_unfocused_hover :
                     ob_rr_theme->btn_shade->a_unfocused_unpressed))));
             c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
-                 ob_rr_theme->btn_close->a_disabled_unfocused :
+                 ob_rr_theme->btn_close->a_unfocused_disabled :
                  (self->close_press ?
                   ob_rr_theme->btn_close->a_unfocused_pressed :
                   (self->close_hover ?
-                   ob_rr_theme->btn_close->a_hover_unfocused :
+                   ob_rr_theme->btn_close->a_unfocused_hover :
                    ob_rr_theme->btn_close->a_unfocused_unpressed)));
         }
         clear = ob_rr_theme->a_clear;
index 8f4424e..29abca8 100644 (file)
@@ -270,8 +270,8 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
                                  e->xkey.state, e->xkey.x_root, e->xkey.y_root,
                                  0, OB_FRAME_CONTEXT_NONE, client);
             }
-            break;
             used = TRUE;
+            break;
         }
         p = p->next_sibling;
     }
index 7c49ced..8804e12 100644 (file)
@@ -277,7 +277,7 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
     return shortcut;
 }
 
-static void parse_menu_item(xmlNodePtr node,  gpointer data)
+static void parse_menu_item(xmlNodePtr node, gpointer data)
 {
     ObMenuParseState *state = data;
     gchar *label;
@@ -454,10 +454,12 @@ static gboolean menu_hide_delay_func(gpointer data)
 {
     menu_can_hide = TRUE;
     menu_timeout_id = 0;
+
     return FALSE; /* no repeat */
 }
 
-void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
+void menu_show(gchar *name, const GravityPoint *pos, gint monitor,
+               gboolean mouse, gboolean user_positioned, ObClient *client)
 {
     ObMenu *self;
     ObMenuFrame *frame;
@@ -479,7 +481,7 @@ void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
     menu_clear_pipe_caches();
 
     frame = menu_frame_new(self, 0, client);
-    if (!menu_frame_show_topmenu(frame, x, y, mouse))
+    if (!menu_frame_show_topmenu(frame, pos, monitor, mouse, user_positioned))
         menu_frame_free(frame);
     else {
         if (!mouse) {
@@ -517,6 +519,12 @@ gboolean menu_hide_delay_reached(void)
     return menu_can_hide;
 }
 
+void menu_hide_delay_reset(void)
+{
+    if (menu_timeout_id) g_source_remove(menu_timeout_id);
+    menu_hide_delay_func(NULL);
+}
+
 static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
 {
     ObMenuEntry *self;
index 7d71972..8c2ecd7 100644 (file)
@@ -181,9 +181,11 @@ void menu_clear_pipe_caches(void);
 
 void menu_show_all_shortcuts(ObMenu *self, gboolean show);
 
-void menu_show(gchar *name, gint x, gint y, gboolean mouse,
+void menu_show(gchar *name, const GravityPoint *pos, gint monitor,
+               gboolean mouse, gboolean user_positioned,
                struct _ObClient *client);
 gboolean menu_hide_delay_reached(void);
+void menu_hide_delay_reset(void);
 
 /*! The show function is called right after a menu is shown */
 void menu_set_show_func(ObMenu *menu, ObMenuShowFunc func);
index 3252bb3..c37fdcc 100644 (file)
@@ -203,8 +203,6 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
 static void menu_entry_frame_free(ObMenuEntryFrame *self)
 {
     if (self) {
-        menu_entry_unref(self->entry);
-
         window_remove(self->window);
 
         XDestroyWindow(obt_display, self->text);
@@ -221,6 +219,7 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self)
             g_hash_table_remove(menu_frame_map, &self->bullet);
         }
 
+        menu_entry_unref(self->entry);
         g_slice_free(ObMenuEntryFrame, self);
     }
 }
@@ -232,10 +231,18 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y)
     XMoveWindow(obt_display, self->window, self->area.x, self->area.y);
 }
 
-static void menu_frame_place_topmenu(ObMenuFrame *self, gint *x, gint *y)
+static void menu_frame_place_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+                                     gint *x, gint *y, gint monitor,
+                                     gboolean user_positioned)
 {
     gint dx, dy;
 
+    screen_apply_gravity_point(x, y, self->area.width, self->area.height,
+                               pos, screen_physical_area_monitor(monitor));
+
+    if (user_positioned)
+        return;
+
     if (config_menu_middle) {
         gint myx;
 
@@ -989,20 +996,26 @@ static gboolean menu_frame_show(ObMenuFrame *self)
     return TRUE;
 }
 
-gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
-                                 gboolean mouse)
+gboolean menu_frame_show_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+                                 gint monitor, gboolean mouse,
+                                 gboolean user_positioned)
 {
     gint px, py;
+    gint x, y;
 
     if (menu_frame_is_visible(self))
         return TRUE;
     if (!menu_frame_show(self))
         return FALSE;
 
-    if (self->menu->place_func)
+    if (self->menu->place_func) {
+        x = pos->x.pos;
+        y = pos->y.pos;
         self->menu->place_func(self, &x, &y, mouse, self->menu->data);
-    else
-        menu_frame_place_topmenu(self, &x, &y);
+    } else {
+        menu_frame_place_topmenu(self, pos, &x, &y, monitor,
+                                 user_positioned);
+    }
 
     menu_frame_move(self, x, y);
 
@@ -1023,7 +1036,6 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
 static void remove_submenu_hide_timeout(ObMenuFrame *child)
 {
     if (submenu_hide_timer) g_source_remove(submenu_hide_timer);
-    submenu_hide_timer = 0;
 }
 
 gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
@@ -1121,11 +1133,9 @@ void menu_frame_hide_all(void)
 {
     GList *it;
 
-    if (config_submenu_show_delay) {
+    if (config_submenu_show_delay && submenu_show_timer)
         /* remove any submenu open requests */
-        if (submenu_show_timer) g_source_remove(submenu_show_timer);
-        submenu_show_timer = 0;
-    }
+        g_source_remove(submenu_show_timer);
     if ((it = g_list_last(menu_frame_visible)))
         menu_frame_hide(it->data);
 }
@@ -1175,6 +1185,11 @@ static gboolean submenu_show_timeout(gpointer data)
     return FALSE;
 }
 
+static void submenu_show_dest(gpointer data)
+{
+    submenu_show_timer = 0;
+}
+
 static gboolean submenu_hide_timeout(gpointer data)
 {
     g_assert(menu_frame_visible);
@@ -1182,6 +1197,11 @@ static gboolean submenu_hide_timeout(gpointer data)
     return FALSE;
 }
 
+static void submenu_hide_dest(gpointer data)
+{
+    submenu_hide_timer = 0;
+}
+
 void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
                        gboolean immediate)
 {
@@ -1203,11 +1223,9 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
     if (!entry && oldchild_entry)
         entry = oldchild_entry;
 
-    if (config_submenu_show_delay) {
+    if (config_submenu_show_delay && submenu_show_timer)
         /* remove any submenu open requests */
-        if (submenu_show_timer) g_source_remove(submenu_show_timer);
-        submenu_show_timer = 0;
-    }
+        g_source_remove(submenu_show_timer);
 
     self->selected = entry;
 
@@ -1231,7 +1249,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
                 submenu_hide_timer =
                     g_timeout_add_full(G_PRIORITY_DEFAULT,
                                        config_submenu_hide_delay,
-                                       submenu_hide_timeout, oldchild, NULL);
+                                       submenu_hide_timeout, oldchild, submenu_hide_dest);
             }
         }
     }
@@ -1251,7 +1269,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
                         g_timeout_add_full(G_PRIORITY_DEFAULT,
                                            config_submenu_show_delay,
                                            submenu_show_timeout,
-                                           self->selected, NULL);
+                                           self->selected, submenu_show_dest);
                 }
             }
             /* hide the grandchildren of this menu. and move the cursor to
index 2d7a2ae..7b295b6 100644 (file)
@@ -120,8 +120,9 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y);
 void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y,
                                gint *dx, gint *dy);
 
-gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
-                                 gboolean mouse);
+gboolean menu_frame_show_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+                                 gint monitor, gboolean mouse,
+                                 gboolean user_positioned);
 gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
                                  ObMenuEntryFrame *parent_entry);
 
index 2f0c8f5..4da22f3 100644 (file)
@@ -372,7 +372,7 @@ gboolean mouse_event(ObClient *client, XEvent *e)
 gboolean mouse_bind(const gchar *buttonstr, ObFrameContext context,
                     ObMouseAction mact, ObActionsAct *action)
 {
-    guint state, button;
+    guint state = 0, button = 0;
     ObMouseBinding *b;
     GSList *it;
 
index 333a1be..d12a64d 100644 (file)
@@ -795,8 +795,13 @@ static void resize_with_keys(KeySym sym, guint state)
         else /* if (sym == XK_Up)) */
             dir = OB_DIRECTION_NORTH;
 
-        client_find_resize_directional(moveresize_client, key_resize_edge,
-                                       key_resize_edge == dir,
+        ObClientDirectionalResizeType resize_type =
+            key_resize_edge == dir ? CLIENT_RESIZE_GROW
+                                   : CLIENT_RESIZE_SHRINK;
+
+        client_find_resize_directional(moveresize_client,
+                                       key_resize_edge,
+                                       resize_type,
                                        &x, &y, &w, &h);
         dw = w - moveresize_client->area.width;
         dh = h - moveresize_client->area.height;
index cba0499..1671a0d 100644 (file)
@@ -329,11 +329,11 @@ gint main(gint argc, gchar **argv)
             menu_startup(reconfigure);
             prompt_startup(reconfigure);
 
-            /* do this after everything is started so no events will get
-               missed */
-            xqueue_listen();
-
             if (!reconfigure) {
+                /* do this after everything is started so no events will get
+                   missed */
+                xqueue_listen();
+
                 guint32 xid;
                 ObWindow *w;
 
index 7d5c869..de2c7dc 100644 (file)
@@ -257,13 +257,13 @@ static Rect* choose_monitor(ObClient *c, gboolean client_to_be_foregrounded,
 static gboolean place_under_mouse(ObClient *client, gint *x, gint *y,
                                   Size frame_size)
 {
-    if (config_place_policy != OB_PLACE_POLICY_MOUSE)
-        return FALSE;
-
     gint l, r, t, b;
     gint px, py;
     Rect *area;
 
+    if (config_place_policy != OB_PLACE_POLICY_MOUSE)
+        return FALSE;
+
     ob_debug("placing under mouse");
 
     if (!screen_pointer_pos(&px, &py))
@@ -295,25 +295,8 @@ static gboolean place_per_app_setting_position(ObClient *client, Rect *screen,
 
     ob_debug("placing by per-app settings");
 
-    if (settings->position.x.center)
-        *x = screen->x + screen->width / 2 - client->area.width / 2;
-    else if (settings->position.x.opposite)
-        *x = screen->x + screen->width - frame_size.width -
-            settings->position.x.pos;
-    else
-        *x = screen->x + settings->position.x.pos;
-    if (settings->position.x.denom)
-        *x = (*x * screen->width) / settings->position.x.denom;
-
-    if (settings->position.y.center)
-        *y = screen->y + screen->height / 2 - client->area.height / 2;
-    else if (settings->position.y.opposite)
-        *y = screen->y + screen->height - frame_size.height -
-            settings->position.y.pos;
-    else
-        *y = screen->y + settings->position.y.pos;
-    if (settings->position.y.denom)
-        *y = (*y * screen->height) / settings->position.y.denom;
+    screen_apply_gravity_point(x, y, frame_size.width, frame_size.height,
+                               &settings->position, screen);
 
     return TRUE;
 }
@@ -377,11 +360,11 @@ static gboolean place_transient_splash(ObClient *client, Rect *area,
                     b = MAX(b, RECT_BOTTOM(m->frame->area));
                 }
             }
-            if (!first) {
-                *x = ((r + 1 - l) - frame_size.width) / 2 + l;
-                *y = ((b + 1 - t) - frame_size.height) / 2 + t;
-                return TRUE;
-            }
+        }
+        if (!first) {
+            *x = ((r + 1 - l) - frame_size.width) / 2 + l;
+            *y = ((b + 1 - t) - frame_size.height) / 2 + t;
+            return TRUE;
         }
     }
 
@@ -406,8 +389,19 @@ static gboolean place_least_overlap(ObClient *c, Rect *head, int *x, int *y,
     GSList* potential_overlap_clients = NULL;
     gint n_client_rects = config_dock_hide ? 0 : 1;
 
-    /* if we're "showing desktop", ignore all existing windows */
-    if (!screen_showing_desktop) {
+    /* If we're "showing desktop", and going to allow this window to
+       be shown now, then ignore all existing windows */
+    gboolean ignore_windows = FALSE;
+    switch (screen_show_desktop_mode) {
+    case SCREEN_SHOW_DESKTOP_NO:
+    case SCREEN_SHOW_DESKTOP_UNTIL_WINDOW:
+        break;
+    case SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE:
+        ignore_windows = TRUE;
+        break;
+    }
+
+    if (!ignore_windows) {
         GList* it;
         for (it = client_list; it != NULL; it = g_list_next(it)) {
             ObClient* maybe_client = (ObClient*)it->data;
@@ -432,24 +426,27 @@ static gboolean place_least_overlap(ObClient *c, Rect *head, int *x, int *y,
             n_client_rects += 1;
         }
     }
-    Rect client_rects[n_client_rects];
-
-    GSList* it;
-    guint i = 0;
-    if (!config_dock_hide)
-        dock_get_area(&client_rects[i++]);
-    for (it = potential_overlap_clients; it != NULL; it = g_slist_next(it)) {
-        ObClient* potential_overlap_client = (ObClient*)it->data;
-        client_rects[i] = potential_overlap_client->frame->area;
-        i += 1;
-    }
-    g_slist_free(potential_overlap_clients);
 
-    Point result;
-    place_overlap_find_least_placement(client_rects, n_client_rects, head,
-                                       &frame_size, &result);
-    *x = result.x;
-    *y = result.y;
+    if (n_client_rects) {
+        Rect client_rects[n_client_rects];
+        GSList* it;
+        Point result;
+        guint i = 0;
+
+        if (!config_dock_hide)
+            dock_get_area(&client_rects[i++]);
+        for (it = potential_overlap_clients; it != NULL; it = g_slist_next(it)) {
+            ObClient* potential_overlap_client = (ObClient*)it->data;
+            client_rects[i] = potential_overlap_client->frame->area;
+            i += 1;
+        }
+        g_slist_free(potential_overlap_clients);
+
+        place_overlap_find_least_placement(client_rects, n_client_rects, head,
+                                           &frame_size, &result);
+        *x = result.x;
+        *y = result.y;
+    }
 
     return TRUE;
 }
index 3bc679e..792fc38 100644 (file)
@@ -38,7 +38,8 @@ typedef enum
     OB_PLACE_MONITOR_ANY,
     OB_PLACE_MONITOR_ACTIVE,
     OB_PLACE_MONITOR_MOUSE,
-    OB_PLACE_MONITOR_PRIMARY
+    OB_PLACE_MONITOR_PRIMARY,
+    OB_PLACE_MONITOR_ALL
 } ObPlaceMonitor;
 
 /*! Return TRUE if openbox chose the position for the window, and FALSE if
index ac7255b..ed7ff6c 100644 (file)
@@ -19,7 +19,9 @@
 #include "config.h"
 #include "geom.h"
 #include "place_overlap.h"
+#include "obt/bsearch.h"
 
+#include <glib.h>
 #include <stdlib.h>
 
 static void make_grid(const Rect* client_rects,
@@ -170,29 +172,23 @@ static int total_overlap(const Rect* client_rects,
     return overlap;
 }
 
-/* Unfortunately, the libc bsearch() function cannot be used to find the
-   position of a value that is not in the array, and glib doesn't
-   provide a binary search function at all.  So, tricky as it is, if we
-   want to avoid linear scan of the edge array, we have to roll our
-   own. */
-static int grid_position(int value,
-                         const int* edges,
-                         int max_edges)
+static int find_first_grid_position_greater_or_equal(int search_value,
+                                                     const int* edges,
+                                                     int max_edges)
 {
-    int low = 0;
-    int high = max_edges - 1;
-    int mid = low + (high - low) / 2;
-    while (low != mid) {
-        if (value < edges[mid])
-            high = mid;
-        else if (value > edges[mid])
-            low = mid;
-        else                    /* value == edges[mid] */
-            return mid;
-        mid = low + (high - low) / 2;
-    }
-    /* we get here when low == mid.  can have low == high or low == high - 1 */
-    return (value <= edges[low] ? low : high);
+    g_assert(max_edges >= 2);
+    g_assert(search_value >= edges[0]);
+    g_assert(search_value <= edges[max_edges - 1]);
+
+    BSEARCH_SETUP();
+    BSEARCH(int, edges, 0, max_edges, search_value);
+
+    if (BSEARCH_FOUND())
+        return BSEARCH_AT();
+
+    g_assert(BSEARCH_FOUND_NEAREST_SMALLER());
+    /* Get the nearest larger instead. */
+    return BSEARCH_AT() + 1;
 }                         
 
 static void expand_width(Rect* r, int by)
@@ -263,9 +259,11 @@ static void center_in_field(Point* top_left,
 {
     /* Find minimal rectangle. */
     int orig_right_edge_index =
-        grid_position(top_left->x + req_size->width, x_edges, max_edges);
+        find_first_grid_position_greater_or_equal(
+            top_left->x + req_size->width, x_edges, max_edges);
     int orig_bottom_edge_index =
-        grid_position(top_left->y + req_size->height, y_edges, max_edges);
+        find_first_grid_position_greater_or_equal(
+            top_left->y + req_size->height, y_edges, max_edges);
     ExpandInfo i = {
         .top_left = top_left,
         .orig_width = x_edges[orig_right_edge_index] - top_left->x,
index 9295194..e758ada 100644 (file)
@@ -57,15 +57,15 @@ static gboolean replace_wm(void);
 static void     screen_tell_ksplash(void);
 static void     screen_fallback_focus(void);
 
-guint           screen_num_desktops;
-guint           screen_num_monitors;
-guint           screen_desktop;
-guint           screen_last_desktop;
-gboolean        screen_showing_desktop;
-ObDesktopLayout screen_desktop_layout;
-gchar         **screen_desktop_names;
-Window          screen_support_win;
-Time            screen_desktop_user_time = CurrentTime;
+guint                  screen_num_desktops;
+guint                  screen_num_monitors;
+guint                  screen_desktop;
+guint                  screen_last_desktop;
+ObScreenShowDestopMode screen_show_desktop_mode;
+ObDesktopLayout        screen_desktop_layout;
+gchar                **screen_desktop_names;
+Window                 screen_support_win;
+Time                   screen_desktop_user_time = CurrentTime;
 
 static Size     screen_physical_size;
 static guint    screen_old_desktop;
@@ -445,9 +445,9 @@ void screen_startup(gboolean reconfig)
     screen_last_desktop = screen_desktop;
 
     /* don't start in showing-desktop mode */
-    screen_showing_desktop = FALSE;
+    screen_show_desktop_mode = SCREEN_SHOW_DESKTOP_NO;
     OBT_PROP_SET32(obt_root(ob_screen),
-                   NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop);
+                   NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop());
 
     if (session_desktop_layout_present &&
         screen_validate_layout(&session_desktop_layout))
@@ -1218,15 +1218,33 @@ void screen_update_desktop_names(void)
                                       screen_num_desktops);
 }
 
-void screen_show_desktop(gboolean show, ObClient *show_only)
+void screen_show_desktop(ObScreenShowDestopMode show_mode, ObClient *show_only)
 {
     GList *it;
 
-    if (show == screen_showing_desktop) return; /* no change */
+    ObScreenShowDestopMode before_mode = screen_show_desktop_mode;
 
-    screen_showing_desktop = show;
+    gboolean showing_before = screen_showing_desktop();
+    screen_show_desktop_mode = show_mode;
+    gboolean showing_after = screen_showing_desktop();
 
-    if (show) {
+    if (showing_before == showing_after) {
+        /* No change. */
+        screen_show_desktop_mode = before_mode;
+        return;
+    }
+
+    if (screen_show_desktop_mode == SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE &&
+        show_only != NULL)
+    {
+        /* If we're showing the desktop until the show-mode is toggled, we
+           don't allow breaking out of showing-desktop mode unless we're
+           showing all the windows again. */
+        screen_show_desktop_mode = before_mode;
+        return;
+    }
+
+    if (showing_after) {
         /* hide windows bottom to top */
         for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
             if (WINDOW_IS_CLIENT(it->data)) {
@@ -1250,7 +1268,7 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
         }
     }
 
-    if (show) {
+    if (showing_after) {
         /* focus the desktop */
         for (it = focus_order; it; it = g_list_next(it)) {
             ObClient *c = it->data;
@@ -1275,8 +1293,23 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
         }
     }
 
-    show = !!show; /* make it boolean */
-    OBT_PROP_SET32(obt_root(ob_screen), NET_SHOWING_DESKTOP, CARDINAL, show);
+    OBT_PROP_SET32(obt_root(ob_screen),
+                   NET_SHOWING_DESKTOP,
+                   CARDINAL,
+                   !!showing_after);
+}
+
+gboolean screen_showing_desktop()
+{
+    switch (screen_show_desktop_mode) {
+    case SCREEN_SHOW_DESKTOP_NO:
+        return FALSE;
+    case SCREEN_SHOW_DESKTOP_UNTIL_WINDOW:
+    case SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE:
+        return TRUE;
+    }
+    g_assert_not_reached();
+    return FALSE;
 }
 
 void screen_install_colormap(ObClient *client, gboolean install)
@@ -1648,7 +1681,7 @@ guint screen_find_monitor(const Rect *search)
 {
     guint i;
     guint mostpx_index = screen_num_monitors;
-    guint mostpx = 0;
+    glong mostpx = 0;
     guint closest_distance_index = screen_num_monitors;
     guint closest_distance = G_MAXUINT;
     GSList *counted = NULL;
@@ -1895,3 +1928,30 @@ gboolean screen_compare_desktops(guint a, guint b)
         b = screen_desktop;
     return a == b;
 }
+
+void screen_apply_gravity_point(gint *x, gint *y, gint width, gint height,
+                                const GravityPoint *position, const Rect *area)
+{
+    if (position->x.center)
+        *x = area->width / 2 - width / 2;
+    else {
+        *x = position->x.pos;
+        if (position->x.denom)
+            *x = (*x * area->width) / position->x.denom;
+        if (position->x.opposite)
+            *x = area->width - width - *x;
+    }
+
+    if (position->y.center)
+        *y = area->height / 2 - height / 2;
+    else {
+        *y = position->y.pos;
+        if (position->y.denom)
+            *y = (*y * area->height) / position->y.denom;
+        if (position->y.opposite)
+            *y = area->height - height - *y;
+    }
+
+    *x += area->x;
+    *y += area->y;
+}
index a6a3995..6c26ce8 100644 (file)
@@ -26,6 +26,12 @@ struct _ObClient;
 
 #define DESKTOP_ALL (0xffffffff)
 
+typedef enum {
+    SCREEN_SHOW_DESKTOP_NO,
+    SCREEN_SHOW_DESKTOP_UNTIL_WINDOW,
+    SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE
+} ObScreenShowDestopMode;
+
 /*! The number of available desktops */
 extern guint screen_num_desktops;
 /*! The number of virtual "xinerama" screens/heads */
@@ -35,7 +41,7 @@ extern guint screen_desktop;
 /*! The desktop which was last visible */
 extern guint screen_last_desktop;
 /*! Are we in showing-desktop mode? */
-extern gboolean screen_showing_desktop;
+extern ObScreenShowDestopMode screen_show_desktop_mode;
 /*! The support window also used for focus and stacking */
 extern Window screen_support_win;
 /*! The last time at which the user changed desktops */
@@ -90,7 +96,11 @@ void screen_hide_desktop_popup(void);
          show is FALSE (restoring from show-desktop mode), and the rest are
          iconified.
 */
-void screen_show_desktop(gboolean show, struct _ObClient *show_only);
+void screen_show_desktop(ObScreenShowDestopMode show_mode,
+                         struct _ObClient *show_only);
+
+/*! Returns true if showing desktop mode is enabled. */
+gboolean screen_showing_desktop();
 
 /*! Updates the desktop layout from the root property if available */
 void screen_update_layout(void);
@@ -172,4 +182,9 @@ guint screen_monitor_pointer(void);
 */
 gboolean screen_compare_desktops(guint a, guint b);
 
+/*! Resolve a gravity point into absolute coordinates.
+ * width and height are the size of the object being placed, used for
+ * aligning to right/bottom edges of the area. */
+void screen_apply_gravity_point(gint *x, gint *y, gint width, gint height,
+                                const GravityPoint *position, const Rect *area);
 #endif
index 58551b5..0ef900a 100644 (file)
@@ -26,6 +26,8 @@
 #include "window.h"
 #include "event.h"
 #include "debug.h"
+#include "dock.h"
+#include "config.h"
 #include "obt/prop.h"
 
 GList  *stacking_list = NULL;
@@ -567,14 +569,18 @@ void stacking_add_nonintrusive(ObWindow *win)
 /*! Returns TRUE if client is occluded by the sibling. If sibling is NULL it
   tries against all other clients.
 */
-static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
+static gboolean stacking_occluded(ObClient *client, ObWindow *sibling_win)
 {
     GList *it;
     gboolean occluded = FALSE;
+    ObClient *sibling = NULL;
+
+    if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
+        sibling = WINDOW_AS_CLIENT(sibling_win);
 
     /* no need for any looping in this case */
     if (sibling && client->layer != sibling->layer)
-        return occluded;
+        return FALSE;
 
     for (it = g_list_previous(g_list_find(stacking_list, client)); it;
          it = g_list_previous(it))
@@ -601,6 +607,21 @@ static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
                         break; /* we past its layer */
                 }
             }
+        } else if (WINDOW_IS_DOCK(it->data)) {
+            ObDock *dock = it->data;
+            if (RECT_INTERSECTS_RECT(dock->area, client->frame->area))
+            {
+                if (sibling_win != NULL) {
+                    if (DOCK_AS_WINDOW(dock) == sibling_win) {
+                        occluded = TRUE;
+                        break;
+                    }
+                }
+                else if (config_dock_layer == client->layer) {
+                    occluded = TRUE;
+                    break;
+                }
+            }
         }
     return occluded;
 }
@@ -608,14 +629,18 @@ static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
 /*! Returns TRUE if client occludes the sibling. If sibling is NULL it tries
   against all other clients.
 */
-static gboolean stacking_occludes(ObClient *client, ObClient *sibling)
+static gboolean stacking_occludes(ObClient *client, ObWindow *sibling_win)
 {
     GList *it;
     gboolean occludes = FALSE;
+    ObClient *sibling = NULL;
+
+    if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
+        sibling = WINDOW_AS_CLIENT(sibling_win);
 
     /* no need for any looping in this case */
     if (sibling && client->layer != sibling->layer)
-        return occludes;
+        return FALSE;
 
     for (it = g_list_next(g_list_find(stacking_list, client));
          it; it = g_list_next(it))
@@ -643,14 +668,35 @@ static gboolean stacking_occludes(ObClient *client, ObClient *sibling)
                 }
             }
         }
+        else if (WINDOW_IS_DOCK(it->data)) {
+            ObDock *dock = it->data;
+            if (RECT_INTERSECTS_RECT(dock->area, client->frame->area))
+            {
+                if (sibling_win != NULL) {
+                    if (DOCK_AS_WINDOW(dock) == sibling_win) {
+                        occludes = TRUE;
+                        break;
+                    }
+                }
+                else if (config_dock_layer == client->layer) {
+                    occludes = TRUE;
+                    break;
+                }
+            }
+        }
     return occludes;
 }
 
-gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
+gboolean stacking_restack_request(ObClient *client, ObWindow *sibling_win,
                                   gint detail)
 {
     gboolean ret = FALSE;
 
+    ObClient *sibling = NULL;
+
+    if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
+        sibling = WINDOW_AS_CLIENT(sibling_win);
+
     if (sibling && ((client->desktop != sibling->desktop &&
                      client->desktop != DESKTOP_ALL &&
                      sibling->desktop != DESKTOP_ALL) ||
@@ -674,7 +720,7 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
                  client->title, sibling ? sibling->title : "(all)");
         /* if this client occludes sibling (or anything if NULL), then
            lower it to the bottom */
-        if (stacking_occludes(client, sibling)) {
+        if (stacking_occludes(client, sibling_win)) {
             stacking_lower(CLIENT_AS_WINDOW(client));
             ret = TRUE;
         }
@@ -688,7 +734,7 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
     case TopIf:
         ob_debug("Restack request TopIf for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
-        if (stacking_occluded(client, sibling)) {
+        if (stacking_occluded(client, sibling_win)) {
             stacking_raise(CLIENT_AS_WINDOW(client));
             ret = TRUE;
         }
@@ -696,11 +742,11 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
     case Opposite:
         ob_debug("Restack request Opposite for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
-        if (stacking_occluded(client, sibling)) {
+        if (stacking_occluded(client, sibling_win)) {
             stacking_raise(CLIENT_AS_WINDOW(client));
             ret = TRUE;
         }
-        else if (stacking_occludes(client, sibling)) {
+        else if (stacking_occludes(client, sibling_win)) {
             stacking_lower(CLIENT_AS_WINDOW(client));
             ret = TRUE;
         }
index c14aa2e..ebfa175 100644 (file)
@@ -71,7 +71,7 @@ void stacking_below(struct _ObWindow *window, struct _ObWindow *below);
 
 /*! Restack a window based upon a sibling (or all windows) in various ways.
   @param client The client to be restacked
-  @param sibling Another client to compare to, or NULL to compare to all
+  @param sibling A window to compare to, or NULL to compare to all
                  windows
   @param detail One of Above, Below, TopIf, BottomIf, Opposite
   @return TRUE if the client was restacked
@@ -79,7 +79,7 @@ void stacking_below(struct _ObWindow *window, struct _ObWindow *below);
   how each detail works with and without a sibling.
 */
 gboolean stacking_restack_request(struct _ObClient *client,
-                                  struct _ObClient *sibling,
+                                  struct _ObWindow *sibling_win,
                                   gint detail);
 
 #endif
index 1ba991d..789fa2d 100644 (file)
@@ -10,6 +10,7 @@ en@quot en@boldquot
 es
 et
 eu
+gl_ES
 fi
 fr
 he
index c7dc1cf..c61b780 100644 (file)
--- a/po/af.po
+++ b/po/af.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 3.5.0\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2012-02-20 11:26+0700\n"
 "Last-Translator: aspersieman <aspersieman@gmail.com>\n"
 "Language-Team: Afrikaans\n"
@@ -18,7 +18,7 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Ongeldige aksie \"%s\" versoek. Daar is geen sodanige aksie nie."
@@ -40,7 +40,7 @@ msgstr "Voer uit"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Versuim om die pad \"%s\" vanaf utf8 te omskep."
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Kanselleer"
 
@@ -76,7 +76,7 @@ msgstr "Beëindig..."
 msgid "Not Responding"
 msgstr "Reageer Nie"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -85,11 +85,11 @@ msgstr ""
 "Die venster \"%s\" lyk nie asof dit reageer nie. Wil jy dit vorseer om te "
 "eindig deur dit die %s sein te stuur?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Beëindig Proses"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -98,7 +98,7 @@ msgstr ""
 "Die venster \"%s\" lyk nie asof dit reageer nie. Wil jy dit afsluitvan die X-"
 "bediener?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Sluit Af"
 
@@ -186,17 +186,17 @@ msgstr "Ve_rsier/Nie-versier"
 msgid "_Close"
 msgstr "_Sluit"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Ongeldige konteks \"%s\" in die muis binding"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Ongeldige knoppie \"%s\" is gespesifiseer in die konfigurasielêer"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 77cc272..8bfef89 100644 (file)
--- a/po/ar.po
+++ b/po/ar.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.3\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2012-01-18 22:41-0000\n"
 "Last-Translator: كريم اولاد الشلحة <herr.linux88@gmail.com>\n"
 "Language-Team: Arabic <herr.linux88@gmail.com>\n"
@@ -21,7 +21,7 @@ msgstr ""
 "X-Poedit-Language: Arabic\n"
 "X-Poedit-Country: Morocco\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr ""
@@ -43,7 +43,7 @@ msgstr "تنفيذ"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "فشلت في تحويل المسار \"%s\" من utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "إلغاء"
 
@@ -79,25 +79,25 @@ msgstr "إنهاء..."
 msgid "Not Responding"
 msgstr "لا يستجيب"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
 "to exit by sending the %s signal?"
 msgstr ""
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "إنهاء العملية"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
 "it from the X server?"
 msgstr ""
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "قطع الإتصال"
 
@@ -185,17 +185,17 @@ msgstr "ضع/أزل الحواف (_D)"
 msgid "_Close"
 msgstr "أغلق (_C)"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "سياق غير صحيح \"%s\" في ارتباط الفأرة"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "زر غير صحيح \"%s\" محدد في ملف الإعدادات"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index f4b8a1d..739cfd7 100644 (file)
--- a/po/be.po
+++ b/po/be.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: openbox 3.4.11\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2012-07-16 20:55+0300\n"
 "Last-Translator: Mikalai Udodau <crom-a@tut.by>\n"
 "Language-Team: Belarusian <i18n@mova.org>\n"
@@ -19,7 +19,7 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Запытана недапушчальнае дзеянне \"%s\". Няма такога дзеяння."
@@ -41,7 +41,7 @@ msgstr "Выканаць"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Не ўдалося пераўтварыць шлях \"%s\" з utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Скасаваць"
 
@@ -77,7 +77,7 @@ msgstr "Прыбіццё..."
 msgid "Not Responding"
 msgstr "Не адказвае"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -86,11 +86,11 @@ msgstr ""
 "Акно \"%s\" не адказвае, здаецца. Ці хочаце прымусіць яго закрыцца, даслаўшы "
 "яму сігнал %s?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Скончыць працэс"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -98,7 +98,7 @@ msgid ""
 msgstr ""
 "Вакно \"%s\" не адказвае, здаецца.  Вы хочаце адлучыць яго ад X-сервера?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Адлучыць"
 
@@ -186,17 +186,17 @@ msgstr "Раз/Абрамленне (_D)"
 msgid "_Close"
 msgstr "Закрыць (_C)"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Недапушчальны кантэкст \"%s\" у спалучэнні мышы"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Недапушчальная клавіша \"%s\" пазначана ў файле канфігурацыі"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 67712e9..c153324 100644 (file)
@@ -7,18 +7,18 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2007-06-01 19:02+0530\n"
 "Last-Translator: Runa Bhattacharjee <runabh@gmail.com>\n"
 "Language-Team: Bengali (India) <en@li.org>\n"
-"Language: \n"
+"Language: bn_IN\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "X-Generator: KBabel 1.11.4\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr ""
@@ -41,7 +41,7 @@ msgstr ""
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "\"%s\" পাথটি utf8 থেকে রূপান্তর করতে ব্যর্থ"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr ""
 
@@ -77,25 +77,25 @@ msgstr ""
 msgid "Not Responding"
 msgstr ""
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
 "to exit by sending the %s signal?"
 msgstr ""
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr ""
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
 "it from the X server?"
 msgstr ""
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr ""
 
@@ -183,17 +183,17 @@ msgstr "বিন্যাস পরিবর্তন (_D)"
 msgid "_Close"
 msgstr "বন্ধ করুন (_C)"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "মাউস বাইন্ডিং সংক্রান্ত অবৈধ কনটেক্সট \"%s\""
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "কনফিগ ফাইলে অবৈধ বাটন \"%s\" উল্লিখিত হয়েছে"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 22755e9..7f9f40b 100644 (file)
--- a/po/ca.po
+++ b/po/ca.po
@@ -7,17 +7,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2008-05-25 19:23+0200\n"
 "Last-Translator: David Majà Martínez <davidmaja@gmail.com>\n"
 "Language-Team: catalan\n"
-"Language: \n"
+"Language: ca\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "L'acció sollicitada \"%s\" no és vàlida. Aquesta acció no existeix."
@@ -39,7 +39,7 @@ msgstr "Executa"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "No s'ha pogut convertir el camí \"%s\" des de utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Cancel·la"
 
@@ -75,7 +75,7 @@ msgstr "S'està finalitzant..."
 msgid "Not Responding"
 msgstr "No està responent"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -84,11 +84,11 @@ msgstr ""
 "Sembla que la finestra \"%s\" no està responent. Voleu forçar-la a "
 "finalitzar enviant el senyal %s?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Finalitza el procés"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -97,7 +97,7 @@ msgstr ""
 "Sembla que la finestra \"%s\" no està responent.  Voleu desconnectar-la del "
 "servidor d'X?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Desconnecta"
 
@@ -185,17 +185,17 @@ msgstr "Sense/Amb _decoració"
 msgid "_Close"
 msgstr "_Tanca"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "El context \"%s\" no és vàlid en la vinculació del ratolí"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "El botó especificat al fitxer de configuració \"%s\" no és vàlid."
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 91d0e9c..48742d3 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2011-06-03 17:49+0200\n"
 "Last-Translator: David Kolibac <david@kolibac.cz>\n"
 "Language-Team: Czech <cs@li.org>\n"
@@ -19,7 +19,7 @@ msgstr ""
 "X-Generator: Lokalize 1.2\n"
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Požadována neplatná činnost \"%s\". Žádná taková činnost neexistuje."
@@ -41,7 +41,7 @@ msgstr "Spustit"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Nepodařilo se převést cestu \"%s\" z UTF-8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Zrušit"
 
@@ -77,25 +77,25 @@ msgstr "Ukončuje se..."
 msgid "Not Responding"
 msgstr "Neodpovídá"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
 "to exit by sending the %s signal?"
 msgstr "Okno \"%s\" neodpovídá. Chcete jej ukončit signálem %s?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Ukončit proces"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
 "it from the X server?"
 msgstr "Okno \"%s\" neodpovídá. Chcete jej odpojit od X serveru?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Odpojit"
 
@@ -183,17 +183,17 @@ msgstr "O_ddekorovat/Dekorovat"
 msgid "_Close"
 msgstr "_Zavřít"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Neplatný kontext \"%s\" v nastavení myši"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Neplatné tlačítko \"%s\" v konfiguračním souboru"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 4bcbcf0..9f949fe 100644 (file)
--- a/po/da.po
+++ b/po/da.po
@@ -7,17 +7,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2008-08-19 16:50+0100\n"
 "Last-Translator: Jesper Sander <sander.contrib@gmail.com>\n"
 "Language-Team: None\n"
-"Language: \n"
+"Language: da\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Ugyldig operation \"%s\" anmodet. Operationen findes ikke."
@@ -39,7 +39,7 @@ msgstr "Udfør"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Fejl ved konvertering af stien \"%s\" fra utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Afbryd"
 
@@ -75,7 +75,7 @@ msgstr "Dræber..."
 msgid "Not Responding"
 msgstr "Svarer Ikke"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -84,18 +84,18 @@ msgstr ""
 "Vinduet \"%s\" svarer ikke. Vil du udføre tvunget afslutning ved at sende %s "
 "signalet?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Afslut proces"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
 "it from the X server?"
 msgstr "Vinduet \"%s\" svarer ikke. Vil du frakoble vinduet fra X-serveren?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Frakoble"
 
@@ -183,17 +183,17 @@ msgstr "Fjern/tilføj _dekoration"
 msgid "_Close"
 msgstr "_Luk"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Ugyldig indhold \"%s\" i muse-kombination"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Ugyldig tast \"%s\" specificeret i konfigurationsfilen"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index e820cb5..2db570f 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -11,17 +11,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2012-09-18 21:51+0100\n"
 "Last-Translator: Volker Ribbert <volker.nospam@netcologne.de>\n"
 "Language-Team:  <de@li.org>\n"
-"Language: \n"
+"Language: de\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Ungültige Aktion \"%s\" angefordert. Es gibt keine solche."
@@ -43,7 +43,7 @@ msgstr "Ausführen"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Konnte Pfad \"%s\" nicht von UTF-8 konvertieren"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Abbrechen"
 
@@ -79,7 +79,7 @@ msgstr "Wird gelöscht..."
 msgid "Not Responding"
 msgstr "Reagiert nicht"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -88,11 +88,11 @@ msgstr ""
 "Das Fenster \"%s\" reagiert anscheinend nicht. Möchten Sie es durch Senden "
 "des %s-Signals trotzdem beenden?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Prozess beenden"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -101,7 +101,7 @@ msgstr ""
 "Das Fenster \"%s\" reagiert anscheinend nicht. Möchten Sie es vom X-Server "
 "trennen?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Trennen"
 
@@ -189,17 +189,17 @@ msgstr "_Titelleiste ein/aus"
 msgid "_Close"
 msgstr "_Schließen"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Maus-Einbindung mit ungültigem Kontext \"%s\""
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Ungültige Taste \"%s\" in Konfigurationsdatei"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 277f4e0..1e3ffea 100644 (file)
--- a/po/el.po
+++ b/po/el.po
@@ -1,6 +1,6 @@
-# Greek translations for PACKAGE package.
+# Greek translations for openbox
 # Copyright (C) 2012 Dana Jansens
-# This file is distributed under the same license as the PACKAGE package.
+# This file is distributed under the same license as the openbox package.
 # Efstathios Iosifidis <iosifidis@opensuse.org>, 2012.
 #
 msgid ""
@@ -11,11 +11,11 @@ msgstr ""
 "PO-Revision-Date: 2012-04-28 23:21+0300\n"
 "Last-Translator: Efstathios Iosifidis <iosifidis@opensuse.org>\n"
 "Language-Team: Ελληνικά, Σύγχρονα <opensuse-translation-el@opensuse.org>\n"
+"Language: el\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
-"Language: el\n"
 
 #: openbox/actions.c:149
 #, c-format
index 664a9ef..3d0d6fd 100644 (file)
@@ -1,7 +1,7 @@
 # English translations for openbox package.
-# Copyright (C) 2013 Dana Jansens
+# Copyright (C) 2014 Dana Jansens
 # This file is distributed under the same license as the openbox package.
-# Automatically generated, 2013.
+# Automatically generated, 2014.
 #
 # All this catalog "translates" are quotation characters.
 # The msgids must be ASCII and therefore cannot contain real quotation
@@ -32,8 +32,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: openbox 3.5.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
-"PO-Revision-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
+"PO-Revision-Date: 2014-11-05 16:51+0100\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
 "Language: en\n"
@@ -42,7 +42,7 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Invalid action “\e[1m%s\e[0m” requested. No such action exists."
@@ -64,7 +64,7 @@ msgstr "Execute"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Failed to convert the path “\e[1m%s\e[0m” from utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Cancel"
 
@@ -100,7 +100,7 @@ msgstr "Killing..."
 msgid "Not Responding"
 msgstr "Not Responding"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -109,11 +109,11 @@ msgstr ""
 "The window “\e[1m%s\e[0m” does not seem to be responding.  Do you want to force "
 "it to exit by sending the %s signal?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "End Process"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -122,7 +122,7 @@ msgstr ""
 "The window “\e[1m%s\e[0m” does not seem to be responding.  Do you want to "
 "disconnect it from the X server?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Disconnect"
 
@@ -210,17 +210,17 @@ msgstr "Un/_Decorate"
 msgid "_Close"
 msgstr "_Close"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Invalid context “\e[1m%s\e[0m” in mouse binding"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Invalid button “\e[1m%s\e[0m” specified in config file"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 1b5994d..fc614cf 100644 (file)
@@ -1,7 +1,7 @@
 # English translations for openbox package.
-# Copyright (C) 2013 Dana Jansens
+# Copyright (C) 2014 Dana Jansens
 # This file is distributed under the same license as the openbox package.
-# Automatically generated, 2013.
+# Automatically generated, 2014.
 #
 # All this catalog "translates" are quotation characters.
 # The msgids must be ASCII and therefore cannot contain real quotation
@@ -29,8 +29,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: openbox 3.5.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
-"PO-Revision-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
+"PO-Revision-Date: 2014-11-05 16:51+0100\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
 "Language: en\n"
@@ -39,7 +39,7 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Invalid action “%s” requested. No such action exists."
@@ -61,7 +61,7 @@ msgstr "Execute"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Failed to convert the path “%s” from utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Cancel"
 
@@ -97,7 +97,7 @@ msgstr "Killing..."
 msgid "Not Responding"
 msgstr "Not Responding"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -106,11 +106,11 @@ msgstr ""
 "The window “%s” does not seem to be responding.  Do you want to force it to "
 "exit by sending the %s signal?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "End Process"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -119,7 +119,7 @@ msgstr ""
 "The window “%s” does not seem to be responding.  Do you want to disconnect "
 "it from the X server?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Disconnect"
 
@@ -207,17 +207,17 @@ msgstr "Un/_Decorate"
 msgid "_Close"
 msgstr "_Close"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Invalid context “%s” in mouse binding"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Invalid button “%s” specified in config file"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 68aec7e..23bf77e 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -11,17 +11,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2008-05-04 16:39-0300\n"
 "Last-Translator: Nicolás de la Torre <ndelatorre@gmail.com>\n"
 "Language-Team: español <es@li.org>\n"
-"Language: \n"
+"Language: es\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "La acción \"%s\" solicitada es inválida. No existe tal acción."
@@ -43,7 +43,7 @@ msgstr "Ejecutar"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "No se pudo convertir la ruta \"%s\" desde utf8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Cancelar"
 
@@ -79,7 +79,7 @@ msgstr "Terminando..."
 msgid "Not Responding"
 msgstr "No está respondiendo"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -88,11 +88,11 @@ msgstr ""
 "La ventana \"%s\" parce que no responde.  ¿Desea forzar el cierre enviándole "
 "la señal %s?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Finalizar proceso"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -101,7 +101,7 @@ msgstr ""
 "La ventana \"%s\" no parece estar respondiendo. ¿Desea desconectarla del "
 "servidor X?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Desconectar"
 
@@ -189,17 +189,17 @@ msgstr "_Decorar"
 msgid "_Close"
 msgstr "_Cerrar"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Contexto inválido \"%s\" asociado al ratón"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Botón inválido \"%s\" especificado en el archivo de configuración"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index f18fa24..16abe80 100644 (file)
--- a/po/et.po
+++ b/po/et.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.11.1\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2010-04-21 21:40+0300\n"
 "Last-Translator: mihkel <turakas@gmail.com>\n"
 "Language-Team: Estonian <et@li.org>\n"
@@ -19,7 +19,7 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Taotleti kehtetut käsklust \"%s\". Sellist käsklust pole olemas."
@@ -41,7 +41,7 @@ msgstr "Käivita"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Raja \"%s\" ümberkodeerimine UTF8-st ebaõnnestus"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Katkesta"
 
@@ -77,7 +77,7 @@ msgstr "Tapan..."
 msgid "Not Responding"
 msgstr "Ei vasta"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -86,11 +86,11 @@ msgstr ""
 "Paistab, et aken \"%s\" ei vasta enam. Kas soovid teda jõuga väljuma sundida "
 "saates %s signaali?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Lõpeta protsess"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -99,7 +99,7 @@ msgstr ""
 "Paistab, et aken \"%s\" ei vasta enam. Kas soovid ta X serverist lahti "
 "ühendada?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Ühenda lahti"
 
@@ -187,17 +187,17 @@ msgstr "Äär_ed sisse/välja"
 msgid "_Close"
 msgstr "S_ulge"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Vigane kontekst \"%s\" hiire kiirklahvides"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Vigane nupp \"%s\" määratud seadistuste failis"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index e7282d1..17fe980 100644 (file)
--- a/po/eu.po
+++ b/po/eu.po
@@ -7,17 +7,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7.2\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2008-10-22 18:06+0100\n"
 "Last-Translator: Inko I. A. <inkoia@gmail.com>\n"
 "Language-Team: Inko I. A. <inkoia@gmail.com>\n"
-"Language: \n"
+"Language: eu\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Eskatutako \"%s\" ekintza baliogabea. Ez da ekintza hori existitzen."
@@ -39,7 +39,7 @@ msgstr "Exekutatu"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Hutsegitea \"%s\" helbidea utf8-tik bihurtzean"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Ezeztatu"
 
@@ -75,7 +75,7 @@ msgstr "Akabatzen..."
 msgid "Not Responding"
 msgstr "Erantzunik Ez"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -84,11 +84,11 @@ msgstr ""
 "Badirudi \"%s\" leihoak ez duela erantzuten. Nahi al duzu istea behartu %s "
 "seinalea bidaliz?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Prozesua Amaitu"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -97,7 +97,7 @@ msgstr ""
 "Badirudi \"%s\" leihoak ez duela erantzuten. Nahi al duzu leihoa X "
 "zerbitzaritik deskonektatu?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Deskonektatu"
 
@@ -185,17 +185,17 @@ msgstr "Des/_Dekoratu"
 msgid "_Close"
 msgstr "_Itxi"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Baliogabeko \"%s\" testuingurua sagu elkarketan"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Konfigurazio fitxategian zehaztutako \"%s\" botoia baliogabea"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index 1981fd7..b256c77 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
@@ -10,17 +10,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.11\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2010-03-13 21:56+0100\n"
 "Last-Translator: Lauri Hakko <aperculum@gmail.com>\n"
 "Language-Team: None\n"
-"Language: \n"
+"Language: fi\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Pyydettiin virheellinen toiminto \"%s\". Toimintoa ei ole olemassa."
@@ -42,7 +42,7 @@ msgstr "Suorita"
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Polun \"%s\" muuntaminen utf8:sta epäonnistui"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Peruuta"
 
@@ -78,7 +78,7 @@ msgstr "Tapetaan..."
 msgid "Not Responding"
 msgstr "Ei vastaa"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
@@ -87,11 +87,11 @@ msgstr ""
 "Ikkuna \"%s\" ei näytä vastaavan.  Haluatko sulkea sen lähettämällä sille "
 "singaalin %s?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Lopeta prosessi"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
@@ -100,7 +100,7 @@ msgstr ""
 "Ikkuna \"%s\" ei näytä vastaavan.  Haluatko katkaista sen yhteyden X-"
 "palvelimeen?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Katkaise yhteys"
 
@@ -188,17 +188,17 @@ msgstr "(Epä)_reunusta"
 msgid "_Close"
 msgstr "_Sulje"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Virheellinen asiayhteys \"%s\" hiirisidonnoissa"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Asetustiedostossa määritelty painike \"%s\" on virheellinen"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
index de81f5e..13a4c6b 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -11,17 +11,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Openbox 3.4.7\n"
 "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
-"POT-Creation-Date: 2013-08-11 13:47-0400\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
 "PO-Revision-Date: 2008-03-02 02:06+0100\n"
 "Last-Translator: Cyrille Bagard <nocbos@gmail.com>\n"
 "Language-Team: français <fr@li.org>\n"
-"Language: \n"
+"Language: fr\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=ISO-8859-1\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: openbox/actions.c:216
+#: openbox/actions.c:234
 #, c-format
 msgid "Invalid action \"%s\" requested. No such action exists."
 msgstr "Action demandée invalide \"%s\". Une telle action n'existe pas."
@@ -43,7 +43,7 @@ msgstr "Ex
 msgid "Failed to convert the path \"%s\" from utf8"
 msgstr "Échec de la conversion du chemin « %s » depuis l'UTF-8"
 
-#: openbox/actions/exit.c:69 openbox/client.c:3659
+#: openbox/actions/exit.c:69 openbox/client.c:3665
 msgid "Cancel"
 msgstr "Annuler"
 
@@ -53,7 +53,7 @@ msgstr "Quitter"
 
 #: openbox/actions/exit.c:74
 msgid "Are you sure you want to log out?"
-msgstr "Etes vous certain de vouloir vous déconnecter ?"
+msgstr "Êtes-vous certain de vouloir vous déconnecter ?"
 
 #: openbox/actions/exit.c:75
 msgid "Log Out"
@@ -61,7 +61,7 @@ msgstr "D
 
 #: openbox/actions/exit.c:78
 msgid "Are you sure you want to exit Openbox?"
-msgstr "Etes vous certain de vouloir quitter Openbox ?"
+msgstr "Êtes-vous certain de vouloir quitter Openbox ?"
 
 #: openbox/actions/exit.c:79
 msgid "Exit Openbox"
@@ -79,29 +79,29 @@ msgstr "Tue..."
 msgid "Not Responding"
 msgstr "Ne répond pas"
 
-#: openbox/client.c:3648
+#: openbox/client.c:3654
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to force it "
 "to exit by sending the %s signal?"
 msgstr ""
-"La fenêtre \"%s\" semble ne pas répondre. Voulez vous la forcer à se "
+"La fenêtre \"%s\" semble ne pas répondre. Voulez-vous la forcer à se "
 "terminer en envoyant un signal %s ?"
 
-#: openbox/client.c:3650
+#: openbox/client.c:3656
 msgid "End Process"
 msgstr "Fin de processus"
 
-#: openbox/client.c:3654
+#: openbox/client.c:3660
 #, c-format
 msgid ""
 "The window \"%s\" does not seem to be responding.  Do you want to disconnect "
 "it from the X server?"
 msgstr ""
-"La fenêtre \"%s\" semble ne pas répondre. Voulez vous la déconnecter du "
+"La fenêtre \"%s\" semble ne pas répondre. Voulez-vous la déconnecter du "
 "serveur X ?"
 
-#: openbox/client.c:3656
+#: openbox/client.c:3662
 msgid "Disconnect"
 msgstr "Déconnexion"
 
@@ -189,17 +189,17 @@ msgstr "Ne pas/D
 msgid "_Close"
 msgstr "_Fermer"
 
-#: openbox/config.c:556
+#: openbox/config.c:563
 #, c-format
 msgid "Invalid context \"%s\" in mouse binding"
 msgstr "Contexte « %s » invalide dans le paramétrage de la souris"
 
-#: openbox/config.c:908
+#: openbox/config.c:931
 #, c-format
 msgid "Invalid button \"%s\" specified in config file"
 msgstr "Bouton « %s » indiqué dans le fichier de configuration invalide"
 
-#: openbox/config.c:933
+#: openbox/config.c:956
 msgid ""
 "Openbox was compiled without image loading support. Icons in menus will not "
 "be loaded."
diff --git a/po/gl_ES.po b/po/gl_ES.po
new file mode 100644 (file)
index 0000000..003893b
--- /dev/null
@@ -0,0 +1,489 @@
+# Galician messages for openbox
+# Copyright (C) 2013 Dana Jansens
+# This file is distributed under the same license as the openbox package.
+# Javier Mancebo <palleiros@yahoo.es>, 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Openbox 3.5.2\n"
+"Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
+"POT-Creation-Date: 2014-11-05 16:51+0100\n"
+"PO-Revision-Date: 2013-10-29 18:52+0100\n"
+"Last-Translator: Javier Mancebo <palleiros@yahoo.es>\n"
+"Language-Team: Galician\n"
+"Language: gl_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: openbox/actions.c:234
+#, c-format
+msgid "Invalid action \"%s\" requested. No such action exists."
+msgstr "Acción non válida \"%s\" solicitada. A acción non existe."
+
+#: openbox/actions/execute.c:245
+msgid "No"
+msgstr "Non"
+
+#: openbox/actions/execute.c:246
+msgid "Yes"
+msgstr "Si"
+
+#: openbox/actions/execute.c:250
+msgid "Execute"
+msgstr "Executar"
+
+#: openbox/actions/execute.c:259
+#, c-format
+msgid "Failed to convert the path \"%s\" from utf8"
+msgstr "Erro convertendo a ruta \"%s\" dende utf8"
+
+#: openbox/actions/exit.c:69 openbox/client.c:3665
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: openbox/actions/exit.c:70
+msgid "Exit"
+msgstr "Saír"
+
+#: openbox/actions/exit.c:74
+msgid "Are you sure you want to log out?"
+msgstr "Estas seguro de querer saír da sesión?"
+
+#: openbox/actions/exit.c:75
+msgid "Log Out"
+msgstr "Saír da sesión"
+
+#: openbox/actions/exit.c:78
+msgid "Are you sure you want to exit Openbox?"
+msgstr "Estas seguro de querer saír de Openbox?"
+
+#: openbox/actions/exit.c:79
+msgid "Exit Openbox"
+msgstr "Saír do Openbox"
+
+#: openbox/client.c:2115
+msgid "Unnamed Window"
+msgstr "Fiestra sen nome"
+
+#: openbox/client.c:2129 openbox/client.c:2160
+msgid "Killing..."
+msgstr "Abortando..."
+
+#: openbox/client.c:2131 openbox/client.c:2162
+msgid "Not Responding"
+msgstr "Sen resposta"
+