all my changes while i was offline.
authorDana Jansens <danakj@orodu.net>
Fri, 9 May 2003 16:57:17 +0000 (16:57 +0000)
committerDana Jansens <danakj@orodu.net>
Fri, 9 May 2003 16:57:17 +0000 (16:57 +0000)
better alt-tabbing. better transient handling. i dont even know. lots of fucking cool shit so WATCH the FUCK OUT.

37 files changed:
HACKING
Makefile.am
configure.ac
data/rc3
m4/x11.m4
openbox/Makefile.am
openbox/client.c
openbox/client.h
openbox/config.c
openbox/config.h
openbox/event.c
openbox/extensions.c
openbox/extensions.h
openbox/focus.c
openbox/framerender.c
openbox/framerender.h
openbox/menu.c
openbox/moveresize.c
openbox/moveresize.h
openbox/openbox.c
openbox/parse.h
openbox/parse.l
openbox/parse.y
openbox/screen.c
openbox/screen.h
openbox/stacking.c
plugins/keyboard/keyboard.c
plugins/keyboard/tree.c
plugins/keyboard/tree.h
plugins/mouse/mouse.c
plugins/mouse/mouse.h
render/font.c
render/image.c
render/render.c
render/render.h
render/theme.c
render/theme.h

diff --git a/HACKING b/HACKING
index afd8486..4510420 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -13,6 +13,10 @@ which is not a valid pointer. You must ALWAYS check for TRAN_GROUP before
 following transient_for. When TRAN_GROUP is found, Client.group will always
 be !NULL. Some smart action should be taken using all members of the group in
 this case.
+    Smart action idea:
+        Skip over members of the group that are also transients of the group
+        (have Client.transient_for set to TRAN_GROUP). These windows are not
+        ancestors and using them will also end up causing infinite loops!
 
 When using coordinates/sizes of windows, make sure you use the right area. The
 Client.area rect is the reference point and size of the *CLIENT* window. This
index 060cf7d..8e701c9 100644 (file)
@@ -1,5 +1,5 @@
 #SUBDIRS = po themes doc render cwmcc obcl kernel plugins
-SUBDIRS = po themes data render kernel plugins
+SUBDIRS = po themes data render kernel plugins tools
 MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in stamp-h.in
 
 doc:
index e8ba1b3..9b914ef 100644 (file)
@@ -57,6 +57,8 @@ AC_SUBST(XFT_LIBS)
 
 # Check for X11 extensions
 X11_EXT_XKB
+X11_EXT_XRANDR
+X11_EXT_VIDMODE
 X11_EXT_SHAPE
 X11_EXT_XINERAMA
 
@@ -69,7 +71,9 @@ AC_CONFIG_FILES([Makefile
                 plugins/Makefile
                 plugins/placement/Makefile
                 plugins/mouse/Makefile
-                plugins/keyboard/Makefile])
+                plugins/keyboard/Makefile
+                tools/Makefile
+                tools/slit/Makefile])
 AC_OUTPUT
 
 AC_MSG_RESULT
index 67c87da..fd16dc9 100644 (file)
--- a/data/rc3
+++ b/data/rc3
@@ -27,6 +27,9 @@
 # set, the previously focused window on the desktop is focused when switching
 #focusLastOnDesktop = yes
 
+# shows a helpful dialog while cycling focus
+#cyclingDialog = yes
+
 [desktops]
 
 # The number of virtual desktops to use
index 5a4a35d..65e2ab7 100644 (file)
--- a/m4/x11.m4
+++ b/m4/x11.m4
@@ -211,6 +211,11 @@ AC_DEFUN([X11_EXT_XKB],
       AC_MSG_RESULT([yes])
       XKB="yes"
       AC_DEFINE([XKB], [1], [Found the XKB extension])
+
+      XKB_CFLAGS=""
+      XKB_LIBS=""
+      AC_SUBST(XKB_CFLAGS)
+      AC_SUBST(XKB_LIBS)
     ],
     [ 
       AC_MSG_RESULT([no])
@@ -229,6 +234,63 @@ AC_DEFUN([X11_EXT_XKB],
   fi
 ])
 
+# X11_EXT_XRANDR()
+#
+# Check for the presence of the "XRandR" X Window System extension.
+# Defines "XRANDR" and sets the $(XRANDR) variable to "yes" if the extension is
+# present.
+AC_DEFUN([X11_EXT_XRANDR],
+[
+  AC_REQUIRE([X11_DEVEL])
+
+  # Store these
+  OLDLIBS=$LIBS
+  OLDCPPFLAGS=$CPPFLAGS
+     
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+  LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS -lXext -lXrender -lXrandr"
+
+  AC_CHECK_LIB([Xrandr], [XRRSelectInput],
+    AC_MSG_CHECKING([for X11/extensions/Xrandr.h])
+    AC_TRY_LINK(
+    [
+      #include <X11/Xlib.h>
+      #include <X11/extensions/Xrandr.h>
+    ],
+    [
+      Display *d;
+      Drawable r;
+      int i;
+      XRRQueryExtension(d, &i, &i);
+      XRRGetScreenInfo(d, r);
+    ],
+    [
+      AC_MSG_RESULT([yes])
+      XRANDR="yes"
+      AC_DEFINE([XRANDR], [1], [Found the XRandR extension])
+
+      XRANDR_CFLAGS=""
+      XRANDR_LIBS="-lXext -lXrender -lXrandr"
+      AC_SUBST(XRANDR_CFLAGS)
+      AC_SUBST(XRANDR_LIBS)
+    ],
+    [ 
+      AC_MSG_RESULT([no])
+      XRANDR="no"
+    ])
+  )
+
+  LIBS=$OLDLIBS
+  CPPFLAGS=$OLDCPPFLAGS
+
+  AC_MSG_CHECKING([for the XRandR extension])
+  if test "$XRANDR" = "yes"; then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+])
+
 # X11_EXT_SHAPE()
 #
 # Check for the presence of the "Shape" X Window System extension.
@@ -260,7 +322,11 @@ AC_DEFUN([X11_EXT_SHAPE],
       AC_MSG_RESULT([yes])
       SHAPE="yes"
       AC_DEFINE([SHAPE], [1], [Found the XShape extension])
-      LIBS="$LIBS -lXext"
+
+      XSHAPE_CFLAGS=""
+      XSHAPE_LIBS="-lXext"
+      AC_SUBST(XSHAPE_CFLAGS)
+      AC_SUBST(XSHAPE_LIBS)
     ],
     [ 
       AC_MSG_RESULT([no])
@@ -271,7 +337,7 @@ AC_DEFUN([X11_EXT_SHAPE],
   LIBS=$OLDLIBS
   CPPFLAGS=$OLDCPPFLAGS
  
- AC_MSG_CHECKING([for the Shape extension])
 AC_MSG_CHECKING([for the Shape extension])
   if test "$SHAPE" = "yes"; then
     AC_MSG_RESULT([yes])
   else
@@ -330,3 +396,59 @@ AC_DEFUN([X11_EXT_XINERAMA],
     AC_MSG_RESULT([no])
   fi
 ])
+
+# VIDMODE()
+#
+# Check for the presence of the "VidMode" X Window System extension.
+# Defines "VIDMODE" and sets the $(VIDMODE) variable to "yes" if the extension
+# is present.
+AC_DEFUN([X11_EXT_VIDMODE],
+[
+  AC_REQUIRE([X11_DEVEL])
+
+  # Store these
+  OLDLIBS=$LIBS
+  OLDCPPFLAGS=$CPPFLAGS
+     
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+  LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS -lXext -lXxf86vm"
+
+  AC_CHECK_LIB([Xxf86vm], [XF86VidModeGetViewPort],
+    AC_MSG_CHECKING([for X11/extensions/xf86vmode.h])
+    AC_TRY_LINK(
+    [
+      #include <X11/Xlib.h>
+      #include <X11/extensions/xf86vmode.h>
+    ],
+    [
+      Display *d;
+      int i;
+      XF86VidModeQueryExtension(d, &i, &i);
+      XF86VidModeGetViewPort(d, i, &i, &i);
+    ],
+    [
+      AC_MSG_RESULT([yes])
+      VIDMODE="yes"
+      AC_DEFINE([VIDMODE], [1], [Found the VidMode extension])
+
+      VIDMODE_CFLAGS=""
+      VIDMODE_LIBS="-lXext -lXxf86vm"
+      AC_SUBST(VIDMODE_CFLAGS)
+      AC_SUBST(VIDMODE_LIBS)
+    ],
+    [ 
+      AC_MSG_RESULT([no])
+      VIDMODE="no"
+    ])
+  )
+
+  LIBS=$OLDLIBS
+  CPPFLAGS=$OLDCPPFLAGS
+
+  AC_MSG_CHECKING([for the VidMode extension])
+  if test "$VIDMODE" = "yes"; then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+])
index a82473b..8e027dd 100644 (file)
@@ -14,22 +14,24 @@ CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
          -DBINARY=\"$(binary)\"
 
 INCLUDES=-I..
-LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) @LIBS@
+LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(XKB_LIBS) $(XRANDR_LIBS) \
+       $(VIDMODE_LIBS) $(XSHAPE_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) @LIBS@ \
+       @LIBINTL@
 
 bin_PROGRAMS=$(binary)
 
-openbox3_LDADD=@LIBINTL@ -lobrender -L../render
+openbox3_LDADD=-lobrender -L../render
 openbox3_LDFLAGS=-export-dynamic
 openbox3_SOURCES=parse.tab.c parse.lex.c action.c client.c config.c \
                  extensions.c focus.c frame.c grab.c menu.c menu_render.c \
                  openbox.c framerender.c parse.c plugin.c prop.c screen.c \
                  stacking.c dispatch.c event.c group.c timer.c xerror.c \
-                 moveresize.c startup.c
+                 moveresize.c startup.c popup.c
 
 noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \
                focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \
                menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \
-               stacking.h timer.h xerror.h moveresize.h startup.h
+               stacking.h timer.h xerror.h moveresize.h startup.h popup.h
 
 # kill the implicit .c.y rule
 %.c: %.y
index 47be1bd..2cd9212 100644 (file)
@@ -38,10 +38,7 @@ static void client_get_gravity(Client *self);
 static void client_showhide(Client *self);
 static void client_change_allowed_actions(Client *self);
 static void client_change_state(Client *self);
-static void client_move_onscreen(Client *self);
-static Client *search_focus_tree(Client *node, Client *skip);
 static void client_apply_startup_state(Client *self);
-static Client *search_modal_tree(Client *node, Client *skip);
 
 static guint map_hash(Window *w) { return *w; }
 static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; }
@@ -82,6 +79,37 @@ void client_set_list()
     stacking_set_list();
 }
 
+/*
+void client_foreach_transient(Client *self, ClientForeachFunc func, void *data)
+{
+    GSList *it;
+
+    for (it = self->transients; it; it = it->next) {
+        if (!func(it->data, data)) return;
+        client_foreach_transient(it->data, func, data);
+    }
+}
+
+void client_foreach_ancestor(Client *self, ClientForeachFunc func, void *data)
+{
+    if (self->transient_for) {
+        if (self->transient_for != TRAN_GROUP) {
+            if (!func(self->transient_for, data)) return;
+            client_foreach_ancestor(self->transient_for, func, data);
+        } else {
+            GSList *it;
+
+            for (it = self->group->members; it; it = it->next)
+                if (it->data != self &&
+                    ((Client*)it->data)->transient_for != TRAN_GROUP) {
+                    if (!func(it->data, data)) return;
+                    client_foreach_ancestor(it->data, func, data);
+                }
+        }
+    }
+}
+*/
+
 void client_manage_all()
 {
     unsigned int i, j, nchild;
@@ -137,7 +165,7 @@ void client_manage_all()
 
     if (config_focus_new) {
         active = g_hash_table_lookup(client_map, &startup_active);
-        if (!active || !client_focus(active))
+        if (!(active && client_focus(active)))
             focus_fallback(Fallback_NoFocus);
     }
 }
@@ -266,7 +294,7 @@ void client_manage(Window window)
                 (!parent && (!self->group ||
                              !self->group->members->next)))))) ||
             (parent && (client_focused(parent) ||
-                        search_focus_tree(parent, parent)))) {
+                        client_search_focus_tree(parent)))) {
             client_focus(self);
         }
     }
@@ -399,7 +427,7 @@ void client_unmanage(Client *self)
     client_set_list();
 }
 
-static void client_move_onscreen(Client *self)
+void client_move_onscreen(Client *self)
 {
     Rect *a;
     int x = self->frame->area.x, y = self->frame->area.y;
@@ -415,7 +443,7 @@ static void client_move_onscreen(Client *self)
         y = a->y;
 
     frame_frame_gravity(self->frame, &x, &y); /* get where the client
-                                              should be */
+                                                 should be */
     client_configure(self , Corner_TopLeft, x, y,
                      self->area.width, self->area.height,
                      TRUE, TRUE);
@@ -496,6 +524,7 @@ static void client_get_all(Client *self)
     /* defaults */
     self->frame = NULL;
     self->title = self->icon_title = NULL;
+    self->title_count = 1;
     self->name = self->class = self->role = NULL;
     self->wmstate = NormalState;
     self->transient = FALSE;
@@ -529,7 +558,6 @@ static void client_get_all(Client *self)
     client_setup_decor_and_functions(self);
   
     client_update_title(self);
-    client_update_icon_title(self);
     client_update_class(self);
     client_update_strut(self);
     client_update_icons(self);
@@ -782,10 +810,6 @@ void client_get_type(Client *self)
        else
            self->type = Type_Normal;
     }
-
-    /* this makes sure that these windows appear on all desktops */
-    if (self->type == Type_Desktop)
-       self->desktop = DESKTOP_ALL;
 }
 
 void client_update_protocols(Client *self)
@@ -991,11 +1015,19 @@ void client_setup_decor_and_functions(Client *self)
     client_change_allowed_actions(self);
 
     if (self->frame) {
+        /* this makes sure that these windows appear on all desktops */
+        if (self->type == Type_Desktop && self->desktop != DESKTOP_ALL)
+            client_set_desktop(self, DESKTOP_ALL, FALSE);
+
        /* change the decors on the frame, and with more/less decorations,
            we may also need to be repositioned */
        frame_adjust_area(self->frame, TRUE, TRUE);
        /* with new decor, the window's maximized size may change */
        client_remaximize(self);
+    } else {
+        /* this makes sure that these windows appear on all desktops */
+        if (self->type == Type_Desktop && self->desktop != DESKTOP_ALL)
+            self->desktop = DESKTOP_ALL;
     }
 }
 
@@ -1004,7 +1036,9 @@ static void client_change_allowed_actions(Client *self)
     guint32 actions[9];
     int num = 0;
 
-    actions[num++] = prop_atoms.net_wm_action_change_desktop;
+    /* desktop windows are kept on all desktops */
+    if (self->type != Type_Desktop)
+        actions[num++] = prop_atoms.net_wm_action_change_desktop;
 
     if (self->functions & Func_Shade)
        actions[num++] = prop_atoms.net_wm_action_shade;
@@ -1154,6 +1188,9 @@ void client_update_wmhints(Client *self)
 
 void client_update_title(Client *self)
 {
+    GList *it;
+    guint32 nums;
+    guint i;
     char *data = NULL;
 
     g_free(self->title);
@@ -1165,6 +1202,29 @@ void client_update_title(Client *self)
            data = g_strdup("Unnamed Window");
 
     /* look for duplicates and append a number */
+    nums = 0;
+    for (it = client_list; it; it = it->next)
+        if (it->data != self) {
+            Client *c = it->data;
+            if (0 == strncmp(c->title, data, strlen(data)))
+                nums |= 1 << c->title_count;
+        }
+    /* find first free number */
+    for (i = 1; i <= 32; ++i)
+        if (!(nums & (1 << i))) {
+            if (self->title_count == 1 || i == 1)
+                self->title_count = i;
+            break;
+        }
+    /* dont display the number for the first window */
+    if (self->title_count > 1) {
+        char *vdata, *ndata;
+        ndata = g_strdup_printf(" - [%u]", self->title_count);
+        vdata = g_strconcat(data, ndata, NULL);
+        g_free(ndata);
+        g_free(data);
+        data = vdata;
+    }
 
     PROP_SETS(self->window, net_wm_visible_name, data);
 
@@ -1172,12 +1232,9 @@ void client_update_title(Client *self)
 
     if (self->frame)
        frame_adjust_title(self->frame);
-}
-
-void client_update_icon_title(Client *self)
-{
-    char *data = NULL;
 
+    /* update the icon title */
+    data = NULL;
     g_free(self->icon_title);
      
     /* try netwm */
@@ -1186,6 +1243,16 @@ void client_update_icon_title(Client *self)
        if (!PROP_GETS(self->window, wm_icon_name, locale, &data))
             data = g_strdup("Unnamed Window");
 
+    /* append the title count, dont display the number for the first window */
+    if (self->title_count > 1) {
+        char *vdata, *ndata;
+        ndata = g_strdup_printf(" - [%u]", self->title_count);
+        vdata = g_strconcat(data, ndata, NULL);
+        g_free(ndata);
+        g_free(data);
+        data = vdata;
+    }
+
     PROP_SETS(self->window, net_wm_visible_icon_name, data);
 
     self->icon_title = data;
@@ -1342,28 +1409,70 @@ static void client_change_state(Client *self)
        frame_adjust_state(self->frame);
 }
 
-static Client *search_focus_tree(Client *node, Client *skip)
+Client *client_search_focus_tree(Client *self)
 {
     GSList *it;
     Client *ret;
 
-    for (it = node->transients; it != NULL; it = it->next) {
-       Client *c = it->data;
-       if (c == skip) continue; /* circular? */
-       if ((ret = search_focus_tree(c, skip))) return ret;
-       if (client_focused(c)) return c;
+    for (it = self->transients; it != NULL; it = it->next) {
+       if (client_focused(it->data)) return it->data;
+       if ((ret = client_search_focus_tree(it->data))) return ret;
     }
     return NULL;
 }
 
+Client *client_search_focus_tree_full(Client *self)
+{
+    if (self->transient_for) {
+        if (self->transient_for != TRAN_GROUP) {
+            return client_search_focus_tree_full(self->transient_for);
+        } else {
+            GSList *it;
+        
+            for (it = self->group->members; it; it = it->next)
+                if (((Client*)it->data)->transient_for != TRAN_GROUP) {
+                    Client *c;
+                    if ((c = client_search_focus_tree_full(it->data)))
+                        return c;
+                }
+            return NULL;
+        }
+    } else {
+        /* this function checks the whole tree, the client_search_focus_tree
+           does not, so we need to check this window */
+        if (client_focused(self))
+            return self;
+        return client_search_focus_tree(self);
+    }
+}
+
+static StackLayer calc_layer(Client *self)
+{
+    StackLayer l;
+
+    if (self->iconic) l = Layer_Icon;
+    else if (self->fullscreen) l = Layer_Fullscreen;
+    else if (self->type == Type_Desktop) l = Layer_Desktop;
+    else if (self->type == Type_Dock) {
+        if (!self->below) l = Layer_Top;
+        else l = Layer_Normal;
+    }
+    else if (self->above) l = Layer_Above;
+    else if (self->below) l = Layer_Below;
+    else l = Layer_Normal;
+
+    return l;
+}
+
 static void calc_recursive(Client *self, Client *orig, StackLayer l,
                            gboolean raised)
 {
-    StackLayer old;
+    StackLayer old, own;
     GSList *it;
 
     old = self->layer;
-    self->layer = l;
+    own = calc_layer(self);
+    self->layer = l > own ? l : own;
 
     for (it = self->transients; it; it = it->next)
         calc_recursive(it->data, orig, l, raised ? raised : l != old);
@@ -1376,7 +1485,6 @@ static void calc_recursive(Client *self, Client *orig, StackLayer l,
 void client_calc_layer(Client *self)
 {
     StackLayer l;
-    gboolean f;
     Client *orig;
 
     orig = self;
@@ -1397,25 +1505,7 @@ void client_calc_layer(Client *self)
         }
     }
 
-    /* is us or one of our transients focused? */
-    if (client_focused(self))
-        f = TRUE;
-    else if (search_focus_tree(self, self))
-        f = TRUE;
-    else
-        f = FALSE;
-
-    if (self->iconic) l = Layer_Icon;
-    /* fullscreen windows are only in the fullscreen layer while focused */
-    else if (self->fullscreen && f) l = Layer_Fullscreen;
-    else if (self->type == Type_Desktop) l = Layer_Desktop;
-    else if (self->type == Type_Dock) {
-        if (!self->below) l = Layer_Top;
-        else l = Layer_Normal;
-    }
-    else if (self->above) l = Layer_Above;
-    else if (self->below) l = Layer_Below;
-    else l = Layer_Normal;
+    l = calc_layer(self);
 
     calc_recursive(self, orig, l, FALSE);
 }
@@ -1698,31 +1788,30 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
 {
     GSList *it;
 
-    /* move up the transient chain as far as possible first if deiconifying */
-    if (!iconic)
-        while (self->transient_for) {
-            if (self->transient_for != TRAN_GROUP) {
-                if (self->transient_for->iconic == iconic)
-                    break;
-                self = self->transient_for;
-            } else {
-                GSList *it;
-
-                /* the check for TRAN_GROUP is to prevent an infinate loop with
-                   2 transients of the same group at the head of the group's
-                   members list */
-                for (it = self->group->members; it; it = it->next) {
-                    Client *c = it->data;
+    /* move up the transient chain as far as possible first */
+    if (self->transient_for) {
+        if (self->transient_for != TRAN_GROUP) {
+            if (self->transient_for->iconic != iconic) {
+                client_iconify(self->transient_for, iconic, curdesk);
+                return;
+            }
+        } else {
+            GSList *it;
 
-                    if (c != self && c->transient_for->iconic != iconic &&
-                        c->transient_for != TRAN_GROUP) {
-                        self = it->data;
-                        break;
-                    }
+            /* the check for TRAN_GROUP is to prevent an infinate loop with
+               2 transients of the same group at the head of the group's
+               members list */
+            for (it = self->group->members; it; it = it->next) {
+                Client *c = it->data;
+                if (c != self && c->iconic != iconic &&
+                    c->transient_for != TRAN_GROUP) {
+                    client_iconify(it->data, iconic, curdesk);
+                    break;
                 }
-                if (it == NULL) break;
             }
+            if (it != NULL) return;
         }
+    }
 
     if (self->iconic == iconic) return; /* nothing to do */
 
@@ -1738,13 +1827,18 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
           and because the ICCCM tells us to! */
        XUnmapWindow(ob_display, self->window);
 
-        /* update the focus lists.. iconic windows go to the bottom */
-        focus_order_to_bottom(self);
+        /* update the focus lists.. iconic windows go to the bottom of the
+         list, put the new iconic window at the 'top of the bottom'. */
+        focus_order_to_top(self);
     } else {
        if (curdesk)
            client_set_desktop(self, screen_desktop, FALSE);
        self->wmstate = self->shaded ? IconicState : NormalState;
        XMapWindow(ob_display, self->window);
+
+        /* this puts it after the current focused window */
+        focus_order_remove(self);
+        focus_order_add_new(self);
     }
     client_change_state(self);
     client_showhide(self);
@@ -1941,25 +2035,19 @@ void client_set_desktop(Client *self, guint target, gboolean donthide)
     dispatch_client(Event_Client_Desktop, self, target, old);
 }
 
-static Client *search_modal_tree(Client *node, Client *skip)
+Client *client_search_modal_child(Client *self)
 {
     GSList *it;
     Client *ret;
   
-    for (it = node->transients; it != NULL; it = it->next) {
+    for (it = self->transients; it != NULL; it = it->next) {
        Client *c = it->data;
-       if (c == skip) continue; /* circular? */
-       if ((ret = search_modal_tree(c, skip))) return ret;
+       if ((ret = client_search_modal_child(c))) return ret;
        if (c->modal) return c;
     }
     return NULL;
 }
 
-Client *client_find_modal_child(Client *self)
-{
-    return search_modal_tree(self, self);
-}
-
 gboolean client_validate(Client *self)
 {
     XEvent e; 
@@ -2118,7 +2206,7 @@ Client *client_focus_target(Client *self)
     Client *child;
      
     /* if we have a modal child, then focus it, not us */
-    child = client_find_modal_child(self);
+    child = client_search_modal_child(self);
     if (child) return child;
     return self;
 }
index e7ee308..faa04e6 100644 (file)
@@ -112,6 +112,7 @@ typedef enum {
 typedef struct Client {
     Window  window;
 
+    /*! The window's decorations. NULL while the window is being managed! */
     struct Frame *frame;
 
     /*! The number of unmap events to ignore on the window */
@@ -133,10 +134,13 @@ typedef struct Client {
     GSList *transients;
     /*! The desktop on which the window resides (0xffffffff for all
       desktops) */
-    unsigned int desktop;
+    guint desktop;
 
     /*! Normal window title */
     gchar *title;
+    /*! The count for the title. When another window with the same title
+      exists, a count will be appended to it. */
+    guint title_count;
     /*! Window title when iconified */
     gchar *icon_title;
 
@@ -341,6 +345,11 @@ gboolean client_focused(Client *self);
 void client_configure(Client *self, Corner anchor, int x, int y, int w, int h,
                      gboolean user, gboolean final);
 
+/*! Moves a client so that it is on screen if it is entirely out of the
+  viewable screen.
+*/
+void client_move_onscreen(Client *self);
+
 /*! Fullscreen's or unfullscreen's the client window
   @param fs true if the window should be made fullscreen; false if it should
             be returned to normal state.
@@ -389,11 +398,6 @@ void client_kill(Client *self);
          desktop has been changed. Generally this should be FALSE. */
 void client_set_desktop(Client *self, guint target, gboolean donthide);
 
-/*! Return a modal child of the client window
-    @return A modal child of the client window, or 0 if none was found.
-*/
-Client *client_find_modal_child(Client *self);
-
 /*! Validate client, by making sure no Destroy or Unmap events exist in
   the event queue for the window.
   @return true if the client is valid; false if the client has already
@@ -440,10 +444,8 @@ void client_update_normal_hints(Client *self);
                   process.
 */
 void client_update_wmhints(Client *self);
-/*! Updates the window's title */
+/*! Updates the window's title and icon title */
 void client_update_title(Client *self);
-/*! Updates the window's icon title */
-void client_update_icon_title(Client *self);
 /*! Updates the window's application name and class */
 void client_update_class(Client *self);
 /*! Updates the strut for the client */
@@ -464,4 +466,21 @@ void client_get_type(Client *self);
 
 Icon *client_icon(Client *self, int w, int h);
 
+/*! Searches a client's transients for a focused window. The function does not
+  check for the passed client, only for its transients.
+  If no focused transient is found, NULL is returned.
+*/
+Client *client_search_focus_tree(Client *self);
+
+/*! Searches a client's transient tree for a focused window. The function
+  searches up the tree and down other branches as well as the passed client's.
+  If no focused client is found, NULL is returned.
+*/
+Client *client_search_focus_tree_full(Client *self);
+
+/*! Return a modal child of the client window
+    @return A modal child of the client window, or 0 if none was found.
+*/
+Client *client_search_modal_child(Client *self);
+
 #endif
index db8856e..959f6c2 100644 (file)
@@ -5,6 +5,7 @@ gboolean config_focus_new;
 gboolean config_focus_follow;
 gboolean config_focus_last;
 gboolean config_focus_last_on_desktop;
+gboolean config_focus_popup;
 
 char *config_theme;
 
@@ -37,6 +38,12 @@ static void parse_focus(char *name, ParseToken *value)
         else {
             config_focus_last_on_desktop = value->data.bool;
         }
+    } else if (!g_ascii_strcasecmp(name, "cyclingdialog")) {
+        if (value->type != TOKEN_BOOL)
+            yyerror("invalid value");
+        else {
+            config_focus_popup = value->data.bool;
+        }
     } else
         yyerror("invalid option");
     parse_free_token(value);
@@ -95,6 +102,7 @@ void config_startup()
     config_focus_follow = FALSE;
     config_focus_last = TRUE;
     config_focus_last_on_desktop = TRUE;
+    config_focus_popup = TRUE;
 
     parse_reg_section("focus", NULL, parse_focus);
 
index 27b00dd..081561c 100644 (file)
@@ -11,6 +11,8 @@ extern gboolean config_focus_follow;
 extern gboolean config_focus_last;
 /*! Focus the last focused window as a fallback when switching desktops */
 extern gboolean config_focus_last_on_desktop;
+/*! Show a popup dialog while cycling focus */
+extern gboolean config_focus_popup;
 
 /* The name of the theme */
 char *config_theme;
index eea6583..39dfca5 100644 (file)
@@ -144,6 +144,9 @@ static Window event_get_window(XEvent *e)
     case ConfigureRequest:
        window = e->xconfigurerequest.window;
        break;
+    case ConfigureNotify:
+        window = e->xconfigure.window;
+        break;
     default:
 #ifdef XKB
        if (extensions_xkb && e->type == extensions_xkb_event_basep) {
@@ -308,6 +311,16 @@ static gboolean event_ignore(XEvent *e, Client *client)
 #ifdef DEBUG_FOCUS
                     g_message("found pending FocusIn");
 #endif
+                    /* is the focused window getting a FocusOut/In back to
+                       itself? */
+                    if (fe.xfocus.window == e->xfocus.window) {
+#ifdef DEBUG_FOCUS
+                        g_message("focused window got an Out/In back to "
+                                  "itself IGNORED both");
+#endif
+                        return TRUE;
+                    }
+
                     /* once all the FocusOut's have been dealt with, if there
                        is a FocusIn still left and it is valid, then use it */
                     event_process(&fe);
@@ -451,6 +464,21 @@ static void event_handle_root(XEvent *e)
        else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
            screen_update_layout();
        break;
+    case ConfigureNotify:
+#ifdef XRANDR
+        XRRUpdateConfiguration(e);
+#endif
+        if (e->xconfigure.width != screen_physical_size.width ||
+            e->xconfigure.height != screen_physical_size.height)
+            screen_resize(e->xconfigure.width, e->xconfigure.height);
+        break;
+    default:
+        ;
+#ifdef VIDMODE
+        if (extensions_vidmode && e->type == extensions_vidmode_event_basep) {
+            g_message("VIDMODE EVENT");
+        }
+#endif
     }
 }
 
@@ -490,15 +518,25 @@ static void event_handle_client(Client *client, XEvent *e)
         }
         break;
     case FocusIn:
+#ifdef DEBUG_FOCUS
+        g_message("FocusIn on client for %lx", client->window);
+#endif
         focus_set_client(client);
+        frame_adjust_focus(client->frame, TRUE);
+        break;
     case FocusOut:
 #ifdef DEBUG_FOCUS
-        g_message("Focus%s on client for %lx", (e->type==FocusIn?"In":"Out"),
-                  client->window);
+        g_message("FocusOut on client for %lx", client->window);
 #endif
-        /* focus state can affect the stacking layer */
-        client_calc_layer(client);
-        frame_adjust_focus(client->frame, e->type == FocusIn);
+        /* are we a fullscreen window or a transient of one? (checks layer)
+           if we are then we need to be iconified since we are losing focus
+         */
+        if (client->layer == Layer_Fullscreen && !client->iconic &&
+            !client_search_focus_tree_full(client))
+            /* iconify fullscreen windows when they and their transients
+               aren't focused */
+            client_iconify(client, TRUE, TRUE);
+        frame_adjust_focus(client->frame, FALSE);
        break;
     case EnterNotify:
         if (client_normal(client)) {
@@ -797,11 +835,10 @@ static void event_handle_client(Client *client, XEvent *e)
            client_setup_decor_and_functions(client);
        }
        else if (msgtype == prop_atoms.net_wm_name ||
-                msgtype == prop_atoms.wm_name)
-           client_update_title(client);
-       else if (msgtype == prop_atoms.net_wm_icon_name ||
+                msgtype == prop_atoms.wm_name ||
+                 msgtype == prop_atoms.net_wm_icon_name ||
                 msgtype == prop_atoms.wm_icon_name)
-           client_update_icon_title(client);
+           client_update_title(client);
        else if (msgtype == prop_atoms.wm_class)
            client_update_class(client);
        else if (msgtype == prop_atoms.wm_protocols) {
index 3fe4319..be1ac54 100644 (file)
@@ -7,7 +7,10 @@ gboolean extensions_shape     = FALSE;
 int      extensions_shape_event_basep;
 gboolean extensions_xinerama  = FALSE;
 int      extensions_xinerama_event_basep;
-
+gboolean extensions_randr     = FALSE;
+int      extensions_randr_event_basep;
+gboolean extensions_vidmode   = FALSE;
+int      extensions_vidmode_event_basep;
 
 void extensions_query_all()
 {
@@ -31,4 +34,16 @@ void extensions_query_all()
        XineramaQueryExtension(ob_display, &extensions_xinerama_event_basep,
                               &junk);
 #endif
+
+#ifdef XRANDR
+    extensions_randr =
+       XRRQueryExtension(ob_display, &extensions_randr_event_basep,
+                          &junk);
+#endif
+
+#ifdef VIDMODE
+    extensions_vidmode =
+       XF86VidModeQueryExtension(ob_display, &extensions_vidmode_event_basep,
+                                  &junk);
+#endif
 }
index 3c11076..cda1bf7 100644 (file)
 #ifdef    XINERAMA
 #include <X11/extensions/Xinerama.h>
 #endif
+#ifdef    XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef    VIDMODE
+#include <X11/extensions/xf86vmode.h>
+#endif
 #include <glib.h>
 
 /*! Does the display have the XKB extension? */
@@ -28,6 +34,16 @@ extern gboolean extensions_xinerama;
 /*! Base for events for the Xinerama extension */
 extern int extensions_xinerama_event_basep;
 
+/*! Does the display have the RandR extension? */
+extern gboolean extensions_randr;
+/*! Base for events for the Randr extension */
+extern int extensions_randr_event_basep;
+
+/*! Does the display have the VidMode extension? */
+extern gboolean extensions_vidmode;
+/*! Base for events for the VidMode extension */
+extern int extensions_vidmode_event_basep;
+
 void extensions_query_all();
   
 #endif
index 5e47dd2..7a2d079 100644 (file)
@@ -1,6 +1,5 @@
 #include "event.h"
 #include "openbox.h"
-#include "grab.h"
 #include "framerender.h"
 #include "client.h"
 #include "config.h"
@@ -12,6 +11,7 @@
 #include "focus.h"
 #include "parse.h"
 #include "stacking.h"
+#include "popup.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
@@ -23,6 +23,7 @@ GList **focus_order = NULL; /* these lists are created when screen_startup
 Window focus_backup = None;
 
 static Client *focus_cycle_target = NULL;
+static Popup *focus_cycle_popup = NULL;
 
 void focus_startup()
 {
@@ -32,6 +33,7 @@ void focus_startup()
     XSetWindowAttributes attrib;
 
     focus_client = NULL;
+    focus_cycle_popup = popup_new(TRUE);
 
     attrib.override_redirect = TRUE;
     focus_backup = XCreateWindow(ob_display, ob_root,
@@ -54,6 +56,9 @@ void focus_shutdown()
     g_free(focus_order);
     focus_order = NULL;
 
+    popup_free(focus_cycle_popup);
+    focus_cycle_popup = NULL;
+
     XDestroyWindow(ob_display, focus_backup);
 
     /* reset focus to root */
@@ -98,9 +103,11 @@ void focus_set_client(Client *client)
     if (client != NULL)
         push_to_top(client);
 
-    /* set the NET_ACTIVE_WINDOW hint */
-    active = client ? client->window : None;
-    PROP_SET32(ob_root, net_active_window, window, active);
+    /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
+    if (ob_state != State_Exiting) {
+        active = client ? client->window : None;
+        PROP_SET32(ob_root, net_active_window, window, active);
+    }
 
     if (focus_client != NULL)
         dispatch_client(Event_Client_Focus, focus_client, 0, 0);
@@ -206,7 +213,11 @@ void focus_fallback(FallbackType type)
 
     for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
         if (type != Fallback_Unfocusing || it->data != old)
-            if (client_normal(it->data) && client_focus(it->data))
+            if (client_normal(it->data) &&
+                /* dont fall back to 'anonymous' fullscreen windows. theres no
+                   checks for this is in transient/group fallbacks. */
+                !((Client*)it->data)->fullscreen &&
+                client_focus(it->data))
                 return;
 
     /* nothing to focus */
@@ -215,38 +226,28 @@ void focus_fallback(FallbackType type)
 
 static void popup_cycle(Client *c, gboolean show)
 {
-    XSetWindowAttributes attrib;
-    static Window coords = None;
-
-    if (coords == None) {
-        attrib.override_redirect = TRUE;
-        coords = XCreateWindow(ob_display, ob_root,
-                               0, 0, 1, 1, 0, render_depth, InputOutput,
-                               render_visual, CWOverrideRedirect, &attrib);
-        g_assert(coords != None);
-
-        grab_pointer(TRUE, None);
-
-        XMapWindow(ob_display, coords);
-    }
-
     if (!show) {
-        XDestroyWindow(ob_display, coords);
-        coords = None;
-
-        grab_pointer(FALSE, None);
+        popup_hide(focus_cycle_popup);
     } else {
         Rect *a;
-        Size s;
 
         a = screen_area(c->desktop);
-
-        framerender_size_popup_label(c->title, &s);
-        XMoveResizeWindow(ob_display, coords,
-                          a->x + (a->width - s.width) / 2,
-                          a->y + (a->height - s.height) / 2,
-                          s.width, s.height);
-        framerender_popup_label(coords, &s, c->title);
+        popup_position(focus_cycle_popup, CenterGravity,
+                       a->x + a->width / 2, a->y + a->height / 2);
+/*        popup_size(focus_cycle_popup, a->height/2, a->height/16);
+        popup_show(focus_cycle_popup, c->title,
+                   client_icon(c, a->height/16, a->height/16));
+*/
+        /* XXX the size and the font extents need to be related on some level
+         */
+        popup_size(focus_cycle_popup, 320, 48);
+
+        /* use the transient's parent's title/icon */
+        while (c->transient_for && c->transient_for != TRAN_GROUP)
+            c = c->transient_for;
+
+        popup_show(focus_cycle_popup, (c->iconic ? c->icon_title : c->title),
+                   client_icon(c, 48, 48));
     }
 }
 
@@ -294,15 +295,18 @@ Client *focus_cycle(gboolean forward, gboolean linear, gboolean done,
             it = it->prev;
             if (it == NULL) it = g_list_last(list);
         }
-        ft = client_focus_target(it->data);
-        if (ft == it->data && client_normal(ft) &&
+        /*ft = client_focus_target(it->data);*/
+        ft = it->data;
+        if (ft->transients == NULL && /*ft == it->data &&*/client_normal(ft) &&
             (ft->can_focus || ft->focus_notify) &&
             (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) {
-            if (focus_cycle_target)
-                frame_adjust_focus(focus_cycle_target->frame, FALSE);
-            focus_cycle_target = ft;
-            frame_adjust_focus(focus_cycle_target->frame, TRUE);
-            popup_cycle(ft, TRUE);
+            if (ft != focus_cycle_target) { /* prevents flicker */
+                if (focus_cycle_target)
+                    frame_adjust_focus(focus_cycle_target->frame, FALSE);
+                focus_cycle_target = ft;
+                frame_adjust_focus(focus_cycle_target->frame, TRUE);
+            }
+            popup_cycle(ft, config_focus_popup);
             return ft;
         }
     } while (it != start);
index 0f4c665..737dfe9 100644 (file)
@@ -218,34 +218,3 @@ static void framerender_close(Frame *self, Appearance *a)
              theme_button_size, theme_button_size);
     paint(self->close, a);
 }
-
-void framerender_popup_label(Window win, Size *sz, char *text)
-{
-    Appearance *a;
-
-    a = theme_app_hilite_label;
-    a->texture[0].data.text.string = text;
-    RECT_SET(a->area, 0, 0, sz->width, sz->height);
-    a->texture[0].position = a->area;
-    a->texture[0].position.x += theme_bevel;
-    a->texture[0].position.y += theme_bevel;
-    a->texture[0].position.width -= theme_bevel * 2;
-    a->texture[0].position.height -= theme_bevel * 2;
-
-    XSetWindowBorderWidth(ob_display, win, theme_bwidth);
-    XSetWindowBorder(ob_display, win, theme_b_color->pixel);
-
-    paint(win, a);
-}
-
-void framerender_size_popup_label(char *text, Size *sz)
-{
-    Appearance *a;
-
-    a = theme_app_hilite_label;
-    a->texture[0].data.text.string = text;
-
-    appearance_minsize(a, &sz->width, &sz->height);
-    sz->width += theme_bevel * 2;
-    sz->height += theme_bevel * 2;
-}
index c02c9e7..9655a93 100644 (file)
@@ -5,7 +5,4 @@
 
 void framerender_frame(Frame *self);
 
-void framerender_popup_label(Window win, Size *sz, char *text);
-void framerender_size_popup_label(char *text, Size *sz);
-
 #endif
index 42a183a..88eef9c 100644 (file)
@@ -76,6 +76,16 @@ void menu_startup()
     menu_add_entry(m, menu_entry_new("--", NULL));
     a = action_from_string("exit");
     menu_add_entry(m, menu_entry_new("exit", a));
+
+    m = menu_new("client menu", "client", NULL);
+    a = action_from_string("iconify");
+    menu_add_entry(m, menu_entry_new("iconify", a));
+    a = action_from_string("toggleshade");
+    menu_add_entry(m, menu_entry_new("(un)shade", a));
+    a = action_from_string("togglemaximizefull");
+    menu_add_entry(m, menu_entry_new("(un)maximize", a));
+    a = action_from_string("close");
+    menu_add_entry(m, menu_entry_new("close", a));
 }
 
 void menu_shutdown()
index 08d96ad..7878b9f 100644 (file)
@@ -4,6 +4,7 @@
 #include "client.h"
 #include "dispatch.h"
 #include "openbox.h"
+#include "popup.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
@@ -13,7 +14,6 @@ Client *moveresize_client = NULL;
 
 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
 
-static Window coords = None;
 static int start_x, start_y, start_cx, start_cy, start_cw, start_ch;
 static int cur_x, cur_y;
 static guint button;
@@ -23,6 +23,8 @@ static Corner lockcorner;
 static guint button_return, button_escape, button_left, button_right,
     button_up, button_down;
 
+static Popup *popup = NULL;
+
 #define POPUP_X (10)
 #define POPUP_Y (10)
 
@@ -34,29 +36,24 @@ void moveresize_startup()
     button_right = XKeysymToKeycode(ob_display, XStringToKeysym("Right"));
     button_up = XKeysymToKeycode(ob_display, XStringToKeysym("Up"));
     button_down = XKeysymToKeycode(ob_display, XStringToKeysym("Down"));
+
+    popup = popup_new(FALSE);
+    popup_size_to_string(popup, "W:  0000  W:  0000");
+    popup_position(popup, NorthWestGravity, POPUP_X, POPUP_Y);
+}
+
+void moveresize_shutdown()
+{
+    popup_free(popup);
+    popup = NULL;
 }
 
 static void popup_coords(char *format, int a, int b)
 {
-    XSetWindowAttributes attrib;
-    Size s;
     char *text;
 
-    if (coords == None) {
-        attrib.override_redirect = TRUE;
-        coords = XCreateWindow(ob_display, ob_root,
-                               0, 0, 1, 1, 0, render_depth, InputOutput,
-                               render_visual, CWOverrideRedirect, &attrib);
-        g_assert(coords != None);
-
-        XMapWindow(ob_display, coords);
-    }
-
     text = g_strdup_printf(format, a, b);
-    framerender_size_popup_label(text, &s);
-    XMoveResizeWindow(ob_display, coords,
-                      POPUP_X, POPUP_Y, s.width, s.height);
-    framerender_popup_label(coords, &s, text);
+    popup_show(popup, text, NULL);
     g_free(text);
 }
 
@@ -127,8 +124,7 @@ void moveresize_end(gboolean cancel)
     grab_keyboard(FALSE);
     grab_pointer(FALSE, None);
 
-    XDestroyWindow(ob_display, coords);
-    coords = None;
+    popup_hide(popup);
 
     if (moving) {
         client_configure(moveresize_client, Corner_TopLeft,
@@ -156,7 +152,9 @@ static void do_move()
     client_configure(moveresize_client, Corner_TopLeft, cur_x, cur_y,
                      start_cw, start_ch, TRUE, FALSE);
 
-    popup_coords("X:  %d  Y:  %d", moveresize_client->frame->area.x,
+    /* this would be better with a fixed width font ... XXX can do it better
+       if there are 2 text boxes */
+    popup_coords("X:  %4d  Y:  %4d", moveresize_client->frame->area.x,
                  moveresize_client->frame->area.y);
 }
 
@@ -178,7 +176,9 @@ static void do_resize()
     client_configure(moveresize_client, lockcorner, moveresize_client->area.x,
                      moveresize_client->area.y, cur_x, cur_y, TRUE, FALSE);
 
-    popup_coords("W:  %d  H:  %d", moveresize_client->logical_size.width,
+    /* this would be better with a fixed width font ... XXX can do it better
+       if there are 2 text boxes */
+    popup_coords("W:  %4d  H:  %4d", moveresize_client->logical_size.width,
                  moveresize_client->logical_size.height);
 }
 
index ba717cd..4b9cdac 100644 (file)
@@ -9,6 +9,7 @@ extern gboolean moveresize_in_progress;
 extern Client *moveresize_client;
 
 void moveresize_startup();
+void moveresize_shutdown();
 
 void moveresize_start(Client *c, int x, int y, guint button, guint32 corner);
 void moveresize_end(gboolean cancel);
index ea9b895..304d52c 100644 (file)
@@ -166,7 +166,6 @@ int main(int argc, char **argv)
        font_startup();
         theme_startup();
        event_startup();
-        moveresize_startup();
         grab_startup();
         plugin_startup();
         /* load the plugins specified in the pluginrc */
@@ -187,6 +186,7 @@ int main(int argc, char **argv)
         menu_startup();
         frame_startup();
         stacking_startup();
+        moveresize_startup();
        focus_startup();
        screen_startup();
         group_startup();
@@ -210,6 +210,7 @@ int main(int argc, char **argv)
         group_shutdown();
        screen_shutdown();
        focus_shutdown();
+        moveresize_shutdown();
         stacking_shutdown();
         frame_shutdown();
         menu_shutdown();
index 3ce5ebb..abd5bb2 100644 (file)
@@ -11,7 +11,7 @@ typedef enum {
     TOKEN_INTEGER    = INTEGER,
     TOKEN_STRING     = STRING,
     TOKEN_IDENTIFIER = IDENTIFIER,
-    TOKEN_BOOL       = BOOL,
+    TOKEN_BOOL       = BOOLEAN,
     TOKEN_LIST,
     TOKEN_LBRACE     = '{',
     TOKEN_RBRACE     = '}',
index 3762f33..a7cd6c6 100644 (file)
@@ -31,7 +31,7 @@ bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][
 {bool}       { yylval.bool = (!g_ascii_strcasecmp("true", yytext) ||
                               !g_ascii_strcasecmp("yes", yytext) ||
                               !g_ascii_strcasecmp("on", yytext));
-               return BOOL;
+               return BOOLEAN;
              }
 {identifier} { yylval.identifier = g_strdup(yytext); return IDENTIFIER; }
 [{}()\[\]=,] { yylval.character = *yytext; return *yytext; }
index aa59fe4..7e92efd 100644 (file)
@@ -41,7 +41,7 @@ void parse_set_section(char *section);
 %token <integer> INTEGER
 %token <string> STRING
 %token <identifier> IDENTIFIER
-%token <bool> BOOL
+%token <bool> BOOLEAN
 %token <character> '('
 %token <character> ')'
 %token <character> '{'
@@ -78,7 +78,7 @@ token:
   | INTEGER    { t.type = TOKEN_INTEGER; t.data.integer = $1; }
   | STRING     { t.type = TOKEN_STRING; t.data.string = $1; }
   | IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
-  | BOOL       { t.type = TOKEN_BOOL; t.data.bool = $1; }
+  | BOOLEAN    { t.type = TOKEN_BOOL; t.data.bool = $1; }
   | list       { t.type = TOKEN_LIST; t.data.list = $1; }
   | '{'        { t.type = $1; t.data.character = $1; }
   | '}'        { t.type = $1; t.data.character = $1; }
@@ -107,7 +107,7 @@ listtoken:
   | INTEGER    { t.type = TOKEN_INTEGER; t.data.integer = $1; }
   | STRING     { t.type = TOKEN_STRING; t.data.string = $1; }
   | IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
-  | BOOL       { t.type = TOKEN_BOOL; t.data.bool = $1; }
+  | BOOLEAN    { t.type = TOKEN_BOOL; t.data.bool = $1; }
   | list       { t.type = TOKEN_LIST; t.data.list = $1; }
   | '{'        { t.type = $1; t.data.character = $1; }
   | '}'        { t.type = $1; t.data.character = $1; }
index 7f9b439..04bc21c 100644 (file)
@@ -7,6 +7,7 @@
 #include "frame.h"
 #include "focus.h"
 #include "dispatch.h"
+#include "extensions.h"
 #include "../render/render.h"
 
 #include <X11/Xlib.h>
@@ -16,7 +17,7 @@
 #endif
 
 /*! The event mask to grab on the root window */
-#define ROOT_EVENTMASK (/*ColormapChangeMask |*/ PropertyChangeMask | \
+#define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
                        EnterWindowMask | LeaveWindowMask | \
                        SubstructureNotifyMask | SubstructureRedirectMask | \
                        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
@@ -160,7 +161,8 @@ void screen_startup()
     guint i;
 
     /* get the initial size */
-    screen_resize();
+    screen_resize(WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen)),
+                  HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen)));
 
     /* set the names */
     screen_desktop_names = g_new(char*,
@@ -201,14 +203,14 @@ void screen_shutdown()
     g_free(area);
 }
 
-void screen_resize()
+void screen_resize(int w, int h)
 {
-    /* XXX RandR support here? */
+    GList *it;
     guint32 geometry[2];
 
     /* Set the _NET_DESKTOP_GEOMETRY hint */
-    geometry[0] = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
-    geometry[1] = HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen));
+    geometry[0] = w;
+    geometry[1] = h;
     PROP_SETA32(ob_root, net_desktop_geometry, cardinal, geometry, 2);
     screen_physical_size.width = geometry[0];
     screen_physical_size.height = geometry[1];
@@ -218,7 +220,8 @@ void screen_resize()
 
     screen_update_struts();
 
-    /* XXX adjust more stuff ? */
+    for (it = client_list; it; it = it->next)
+        client_move_onscreen(it->data);
 }
 
 void screen_set_num_desktops(guint num)
index f68b3be..f493bd8 100644 (file)
@@ -43,7 +43,7 @@ void screen_startup();
 void screen_shutdown();
 
 /*! Figure out the new size of the screen and adjust stuff for it */
-void screen_resize();
+void screen_resize(int w, int h);
 
 /*! Change the number of available desktops */
 void screen_set_num_desktops(guint num);
index 6ff0172..ab1e195 100644 (file)
@@ -70,7 +70,7 @@ static GList *find_lowest_transient(Client *c)
 static void raise_recursive(Client *client)
 {
     Window wins[2];  /* only ever restack 2 windows. */
-    GList *it;
+    GList *it, *low;
     GSList *sit;
 
     g_assert(stacking_list != NULL); /* this would be bad */
@@ -86,15 +86,15 @@ static void raise_recursive(Client *client)
     /* find 'it' where it is the positiion in the stacking order where
        'client' will be inserted *before* */
 
-    it = find_lowest_transient(client);
-    if (it)
-        it = it->next;
-    else {
-        /* the stacking list is from highest to lowest */
-        for (it = stacking_list; it; it = it->next) {
-            if (client->layer >= ((Client*)it->data)->layer)
-                break;
+    low = find_lowest_transient(client);
+    /* the stacking list is from highest to lowest */
+    for (it = g_list_last(stacking_list); it; it = it->prev) {
+        if (it == low || client->layer < ((Client*)it->data)->layer) {
+            it = it->next;
+            break;
         }
+        if (it == stacking_list)
+            break;
     }
 
     /*
index bf670c4..acda951 100644 (file)
@@ -56,12 +56,15 @@ gboolean kbind(GList *keylist, Action *action)
 
     if (!(tree = tree_build(keylist)))
         return FALSE;
+
     if ((t = tree_find(tree, &conflict)) != NULL) {
-       /* already bound to something */
-       g_message("keychain is already bound");
+       /* already bound to something, use the existing tree */
         tree_destroy(tree);
-        return FALSE;
-    }
+        tree = NULL;
+    } else
+        t = tree;
+    while (t->first_child) t = t->first_child;
+
     if (conflict) {
         g_message("conflict with binding");
         tree_destroy(tree);
@@ -73,12 +76,10 @@ gboolean kbind(GList *keylist, Action *action)
     grab_keys(FALSE);
 
     /* set the action */
-    t = tree;
-    while (t->first_child) t = t->first_child;
-    t->action = action;
+    t->actions = g_slist_append(t->actions, action);
     /* assimilate this built tree into the main tree. assimilation
        destroys/uses the tree */
-    tree_assimilate(tree);
+    if (tree) tree_assimilate(tree);
 
     grab_keys(TRUE); 
     grab_server(FALSE);
@@ -100,17 +101,25 @@ static void event(ObEvent *e, void *foo)
             if (e->data.x.e->xkey.keycode == button_return)
                 done = TRUE;
             else if (e->data.x.e->xkey.keycode == button_escape) {
-                grabbed_key->action->data.cycle.cancel = TRUE;
+                GSList *it;
+                for (it = grabbed_key->actions; it; it = it->next) {
+                    Action *act = it->data;
+                    act->data.cycle.cancel = TRUE;
+                }
                 done = TRUE;
             }
         }
-        if (done) {
-            grabbed_key->action->data.cycle.final = TRUE;
-            grabbed_key->action->func(&grabbed_key->action->data);
-            grab_keyboard(FALSE);
-            grabbed_key = NULL;
-            reset_chains();
-            return; 
+        if (done) { 
+            GSList *it;
+            for (it = grabbed_key->actions; it; it = it->next) {
+                Action *act = it->data;
+                act->data.cycle.final = TRUE;
+                act->func(&act->data);
+                grab_keyboard(FALSE);
+                grabbed_key = NULL;
+                reset_chains();
+                return;
+            }
         }
     }
     if (e->type == Event_X_KeyRelease)
@@ -140,20 +149,24 @@ static void event(ObEvent *e, void *foo)
                     }
                     curpos = p;
                 } else {
-                    if (p->action->func != NULL) {
-                        p->action->data.any.c = focus_client;
-
-                        if (p->action->func == action_cycle_windows) {
-                            p->action->data.cycle.final = FALSE;
-                            p->action->data.cycle.cancel = FALSE;
-                        }
-
-                        p->action->func(&p->action->data);
-
-                        if (p->action->func == action_cycle_windows &&
-                            !grabbed_key) {
-                            grab_keyboard(TRUE);
-                            grabbed_key = p;
+                    GSList *it;
+                    for (it = p->actions; it; it = it->next) {
+                        Action *act = it->data;
+                        if (act->func != NULL) {
+                            act->data.any.c = focus_client;
+
+                            if (act->func == action_cycle_windows) {
+                                act->data.cycle.final = FALSE;
+                                act->data.cycle.cancel = FALSE;
+                            }
+
+                            act->func(&act->data);
+
+                            if (act->func == action_cycle_windows &&
+                                !grabbed_key) {
+                                grab_keyboard(TRUE);
+                                grabbed_key = p;
+                            }
                         }
                     }
 
index c0ea2f4..896f77b 100644 (file)
@@ -11,10 +11,13 @@ void tree_destroy(KeyBindingTree *tree)
        c = tree->first_child;
        if (c == NULL) {
            GList *it;
+            GSList *sit;
            for (it = tree->keylist; it != NULL; it = it->next)
                g_free(it->data);
            g_list_free(tree->keylist);
-            action_free(tree->action);
+           for (it = tree->actions; it != NULL; it = it->next)
+                action_free(it->data);
+           g_slist_free(tree->actions);
        }
        g_free(tree);
        tree = c;
index 8750c94..aefb256 100644 (file)
@@ -8,7 +8,7 @@ typedef struct KeyBindingTree {
     guint state;
     guint key;
     GList *keylist;
-    Action *action;
+    GSList *actions; /* list of Action pointers */
 
     /* the next binding in the tree at the same level */
     struct KeyBindingTree *next_sibling; 
index caf4e55..8df8e2a 100644 (file)
@@ -96,9 +96,13 @@ static void clearall()
             int j;
 
             MouseBinding *b = it->data;
-            for (j = 0; j < NUM_MOUSEACTION; ++j)
-                if (b->action[j] != NULL)
-                    action_free(b->action[j]);
+            for (j = 0; j < NUM_MOUSEACTION; ++j) {
+                GSList *it;
+                for (it = b->actions[j]; it; it = it->next) {
+                    action_free(it->data);
+                }
+                g_slist_free(b->actions[j]);
+            }
             g_free(b);
         }
         g_slist_free(bound_contexts[i]);
@@ -119,17 +123,20 @@ static void fire_button(MouseAction a, Context context, Client *c, guint state,
     /* if not bound, then nothing to do! */
     if (it == NULL) return;
 
-    if (b->action[a] != NULL && b->action[a]->func != NULL) {
-        b->action[a]->data.any.c = c;
+    for (it = b->actions[a]; it; it = it->next) {
+        Action *act = it->data;
+        if (act->func != NULL) {
+            act->data.any.c = c;
 
-        g_assert(b->action[a]->func != action_moveresize);
+            g_assert(act->func != action_moveresize);
 
-        if (b->action[a]->func == action_showmenu) {
-            b->action[a]->data.showmenu.x = x;
-            b->action[a]->data.showmenu.y = y;
-        }
+            if (act->func == action_showmenu) {
+                act->data.showmenu.x = x;
+                act->data.showmenu.y = y;
+            }
 
-        b->action[a]->func(&b->action[a]->data);
+            act->func(&act->data);
+        }
     }
 }
 
@@ -148,24 +155,27 @@ static void fire_motion(MouseAction a, Context context, Client *c,
     /* if not bound, then nothing to do! */
     if (it == NULL) return;
 
-    if (b->action[a] != NULL && b->action[a]->func != NULL) {
-        b->action[a]->data.any.c = c;
-
-        if (b->action[a]->func == action_moveresize) {
-            b->action[a]->data.moveresize.x = x_root;
-            b->action[a]->data.moveresize.y = y_root;
-            b->action[a]->data.moveresize.button = button;
-            if (!(b->action[a]->data.moveresize.corner ==
-                  prop_atoms.net_wm_moveresize_move ||
-                  b->action[a]->data.moveresize.corner ==
-                  prop_atoms.net_wm_moveresize_move_keyboard ||
-                  b->action[a]->data.moveresize.corner ==
-                  prop_atoms.net_wm_moveresize_size_keyboard))
-                b->action[a]->data.moveresize.corner = corner;
-        } else
-            g_assert_not_reached();
+    for (it = b->actions[a]; it; it = it->next) {
+        Action *act = it->data;
+        if (act->func != NULL) {
+            act->data.any.c = c;
+
+            if (act->func == action_moveresize) {
+                act->data.moveresize.x = x_root;
+                act->data.moveresize.y = y_root;
+                act->data.moveresize.button = button;
+                if (!(act->data.moveresize.corner ==
+                      prop_atoms.net_wm_moveresize_move ||
+                      act->data.moveresize.corner ==
+                      prop_atoms.net_wm_moveresize_move_keyboard ||
+                      act->data.moveresize.corner ==
+                      prop_atoms.net_wm_moveresize_size_keyboard))
+                    act->data.moveresize.corner = corner;
+            } else
+                g_assert_not_reached();
 
-        b->action[a]->func(&b->action[a]->data);
+            act->func(&act->data);
+        }
     }
 }
 
@@ -338,12 +348,7 @@ gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
     for (it = bound_contexts[context]; it != NULL; it = it->next){
        b = it->data;
        if (b->state == state && b->button == button) {
-           /* already bound */
-            if (b->action[mact] != NULL) {
-                g_warning("duplicate binding");
-                return FALSE;
-            }
-            b->action[mact] = action;
+            b->actions[mact] = g_slist_append(b->actions[mact], action);
             return TRUE;
        }
     }
@@ -354,7 +359,7 @@ gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
     b = g_new0(MouseBinding, 1);
     b->state = state;
     b->button = button;
-    b->action[mact] = action;
+    b->actions[mact] = g_slist_append(NULL, action);
     bound_contexts[context] = g_slist_append(bound_contexts[context], b);
 
     grab_all_clients(TRUE);
index 832ada1..408ae96 100644 (file)
@@ -15,7 +15,7 @@ typedef enum {
 typedef struct {
     guint state;
     guint button;
-    Action *action[NUM_MOUSEACTION];
+    GSList *actions[NUM_MOUSEACTION]; /* lists of Action pointers */
 } MouseBinding;
 
 gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
index 7ffcb53..504063b 100644 (file)
@@ -8,6 +8,10 @@
 #include <glib.h>
 #include "../kernel/geom.h"
 
+#define ELIPSES "..."
+#define ELIPSES_LENGTH(font, shadow, offset) \
+    (font->elipses_length + (shadow ? offset : 0))
+
 void font_startup(void)
 {
 #ifdef DEBUG
@@ -38,6 +42,11 @@ static void measure_height(ObFont *f)
     XftTextExtentsUtf8(ob_display, f->xftfont,
                        (FcChar8*)str, strlen(str), &info);
     f->height = (signed) info.height;
+
+    /* measure an elipses */
+    XftTextExtentsUtf8(ob_display, f->xftfont,
+                       (FcChar8*)ELIPSES, strlen(ELIPSES), &info);
+    f->elipses_length = (signed) info.xOff;
 }
 
 ObFont *font_open(char *fontstring)
@@ -98,9 +107,10 @@ void font_draw(XftDraw *d, TextureText *t, Rect *position)
 {
     int x,y,w,h;
     XftColor c;
-    char *text;
-    int m;
+    GString *text;
+    int m, em;
     size_t l;
+    gboolean shortened = FALSE;
 
     y = position->y;
     w = position->width;
@@ -110,12 +120,22 @@ void font_draw(XftDraw *d, TextureText *t, Rect *position)
     y -= (2 * (t->font->xftfont->ascent + t->font->xftfont->descent) -
           (t->font->height + h) - 1) / 2;
 
-    text = g_strdup(t->string);
-    l = strlen(text);
-    m = font_measure_string(t->font, text, t->shadow, t->offset);
+    text = g_string_new(t->string);
+    l = g_utf8_strlen(text->str, -1);
+    m = font_measure_string(t->font, text->str, t->shadow, t->offset);
     while (l && m > position->width) {
-        text[--l] = '\0';
-        m = font_measure_string(t->font, text, t->shadow, t->offset);
+        shortened = TRUE;
+        /* remove a character from the middle */
+        text = g_string_erase(text, l-- / 2, 1);
+        em = ELIPSES_LENGTH(t->font, t->shadow, t->offset);
+        /* if the elipses are too large, don't show them at all */
+        if (em > position->width)
+            shortened = FALSE;
+        m = font_measure_string(t->font, text->str, t->shadow, t->offset) + em;
+    }
+    if (shortened) {
+        text = g_string_insert(text, (l + 1) / 2, ELIPSES);
+        l += 3;
     }
     if (!l) return;
 
@@ -147,7 +167,7 @@ void font_draw(XftDraw *d, TextureText *t, Rect *position)
         }  
         XftDrawStringUtf8(d, &c, t->font->xftfont, x + t->offset,
                           t->font->xftfont->ascent + y + t->offset,
-                          (FcChar8*)text, l);
+                          (FcChar8*)text->str, l);
     }  
     c.color.red = t->color->r | t->color->r << 8;
     c.color.green = t->color->g | t->color->g << 8;
@@ -157,6 +177,6 @@ void font_draw(XftDraw *d, TextureText *t, Rect *position)
                      
     XftDrawStringUtf8(d, &c, t->font->xftfont, x,
                       t->font->xftfont->ascent + y,
-                      (FcChar8*)text, l);
+                      (FcChar8*)text->str, l);
     return;
 }
index bdc51ee..e0c5540 100644 (file)
@@ -5,66 +5,72 @@
 void image_draw(pixel32 *target, TextureRGBA *rgba, Rect *position,
                 Rect *surarea)
 {
-  unsigned long *draw = rgba->data;
-  int c, sfw, sfh;
-  unsigned int i, e;
-  sfw = position->width;
-  sfh = position->height;
+    gulong *draw = rgba->data;
+    guint c, i, e, t, sfw, sfh;
+    sfw = position->width;
+    sfh = position->height;
 
-  /* it would be nice if this worked, but this function is well broken in these
-     cercumstances. */
-  g_assert(position->width == surarea->width &&
-           position->height == surarea->height);
+    /* it would be nice if this worked, but this function is well broken in
+       these circumstances. */
+    g_assert(position->width == surarea->width &&
+             position->height == surarea->height);
 
-  g_assert(rgba->data != NULL);
+    g_assert(rgba->data != NULL);
 
-  if ((rgba->width != sfw || rgba->height != sfh) &&
-      (rgba->width != rgba->cwidth || rgba->height != rgba->cheight)) {
-    double dx = rgba->width / (double)sfw;
-    double dy = rgba->height / (double)sfh;
-    double px = 0.0;
-    double py = 0.0;
-    int iy = 0;
+    if ((rgba->width != sfw || rgba->height != sfh) &&
+        (rgba->width != rgba->cwidth || rgba->height != rgba->cheight)) {
+        double dx = rgba->width / (double)sfw;
+        double dy = rgba->height / (double)sfh;
+        double px = 0.0;
+        double py = 0.0;
+        int iy = 0;
 
-    /* scale it and cache it */
-    if (rgba->cache != NULL)
-        g_free(rgba->cache);
-    rgba->cache = g_new(unsigned long, sfw * sfh);
-    rgba->cwidth = sfw;
-    rgba->cheight = sfh;
-    for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) {
-      rgba->cache[i] = rgba->data[(int)px + iy];
-      if (++c >= sfw) {
-        c = 0;
-        px = 0;
-        py += dy;
-        iy = (int)py * rgba->width;
-      } else
-        px += dx;
-    }
+        /* scale it and cache it */
+        if (rgba->cache != NULL)
+            g_free(rgba->cache);
+        rgba->cache = g_new(unsigned long, sfw * sfh);
+        rgba->cwidth = sfw;
+        rgba->cheight = sfh;
+        for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) {
+            rgba->cache[i] = rgba->data[(int)px + iy];
+            if (++c >= sfw) {
+                c = 0;
+                px = 0;
+                py += dy;
+                iy = (int)py * rgba->width;
+            } else
+                px += dx;
+        }
+
+        /* do we use the cache we may have just created, or the original? */
+        if (rgba->width != sfw || rgba->height != sfh)
+            draw = rgba->cache;
+
+        /* apply the alpha channel */
+        for (i = 0, c = 0, t = position->x, e = sfw*sfh; i < e; ++i, ++t) {
+            guchar alpha, r, g, b, bgr, bgg, bgb;
 
-/* do we use the cache we may have just created, or the original? */
-    if (rgba->width != sfw || rgba->height != sfh)
-        draw = rgba->cache;
+            alpha = draw[i] >> 24;
+            r = draw[i] >> 16;
+            g = draw[i] >> 8;
+            b = draw[i];
 
-    /* apply the alpha channel */
-    for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) {
-      unsigned char alpha = draw[i] >> 24;
-      unsigned char r = draw[i] >> 16;
-      unsigned char g = draw[i] >> 8;
-      unsigned char b = draw[i];
+            if (c >= sfw) {
+                c = 0;
+                t += surarea->width - sfw;
+            }
 
-      /* background color */
-      unsigned char bgr = target[i] >> default_red_shift;
-      unsigned char bgg = target[i] >> default_green_shift;
-      unsigned char bgb = target[i] >> default_blue_shift;
+            /* background color */
+            bgr = target[t] >> default_red_shift;
+            bgg = target[t] >> default_green_shift;
+            bgb = target[t] >> default_blue_shift;
 
-      r = bgr + (((r - bgr) * alpha) >> 8);
-      g = bgg + (((g - bgg) * alpha) >> 8);
-      b = bgb + (((b - bgb) * alpha) >> 8);
+            r = bgr + (((r - bgr) * alpha) >> 8);
+            g = bgg + (((g - bgg) * alpha) >> 8);
+            b = bgb + (((b - bgb) * alpha) >> 8);
 
-      target[i] = (r << default_red_shift) | (g << default_green_shift) |
-        (b << default_blue_shift);
+            target[t] = (r << default_red_shift) | (g << default_green_shift) |
+                (b << default_blue_shift);
+        }
     }
-  }
 }
index a141274..804e6c3 100644 (file)
@@ -7,6 +7,7 @@
 #include "mask.h"
 #include "color.h"
 #include "image.h"
+#include "theme.h"
 #include "kernel/openbox.h"
 
 #ifdef HAVE_STDLIB_H
@@ -421,6 +422,7 @@ void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h)
 void appearance_minsize(Appearance *l, int *w, int *h)
 {
     int i;
+    int m;
     *w = *h = 1;
 
     switch (l->surface.type) {
@@ -437,20 +439,22 @@ void appearance_minsize(Appearance *l, int *w, int *h)
         } else if (l->surface.data.planar.border)
             *w = *h = 2;
 
-        for (i = 0; i < l->textures; ++i)
+        for (i = 0; i < l->textures; ++i) {
             switch (l->texture[i].type) {
             case Bitmask:
                 *w += l->texture[i].data.mask.mask->w;
                 *h += l->texture[i].data.mask.mask->h;
                 break;
             case Text:
-                *w +=font_measure_string(l->texture[i].data.text.font,
-                                         l->texture[i].data.text.string,
-                                         l->texture[i].data.text.shadow,
-                                         l->texture[i].data.text.offset);
-                *h +=  font_height(l->texture[i].data.text.font,
-                                   l->texture[i].data.text.shadow,
-                                   l->texture[i].data.text.offset);
+                m = font_measure_string(l->texture[i].data.text.font,
+                                        l->texture[i].data.text.string,
+                                        l->texture[i].data.text.shadow,
+                                        l->texture[i].data.text.offset);
+                *w += m;
+                m = font_height(l->texture[i].data.text.font,
+                                l->texture[i].data.text.shadow,
+                                l->texture[i].data.text.offset);
+                *h += m;
                 break;
             case RGBA:
                 *w += l->texture[i].data.rgba.width;
@@ -458,7 +462,8 @@ void appearance_minsize(Appearance *l, int *w, int *h)
                 break;
             case NoTexture:
                 break;
-            }            
+            }
+        }
         break;
     }
 }
index d98cebd..006eaf4 100644 (file)
@@ -79,6 +79,7 @@ typedef struct Surface {
 typedef struct {
     XftFont *xftfont;
     int height;
+    int elipses_length;
 } ObFont;
 
 typedef enum {
@@ -109,12 +110,12 @@ typedef struct TextureMask {
 } TextureMask;
 
 typedef struct TextureRGBA {
-    int width;
-    int height;
+    guint width;
+    guint height;
     unsigned long *data;
 /* cached scaled so we don't have to scale often */
-    int cwidth;
-    int cheight;
+    guint cwidth;
+    guint cheight;
     unsigned long *cache;
 } TextureRGBA;
 
index eccc2c8..39079bd 100644 (file)
@@ -93,8 +93,11 @@ Appearance *theme_a_menu_item;
 Appearance *theme_a_menu_disabled;
 Appearance *theme_a_menu_hilite;
 
+Appearance *theme_app_hilite_bg;
+Appearance *theme_app_unhilite_bg;
 Appearance *theme_app_hilite_label;
 Appearance *theme_app_unhilite_label;
+Appearance *theme_app_icon;
 
 void theme_startup()
 {
@@ -151,8 +154,11 @@ void theme_startup()
     theme_a_menu_disabled = appearance_new(Surface_Planar, 1);
     theme_a_menu_hilite = appearance_new(Surface_Planar, 1);
 
+    theme_app_hilite_bg = appearance_new(Surface_Planar, 0);
+    theme_app_unhilite_bg = appearance_new(Surface_Planar, 0);
     theme_app_hilite_label = appearance_new(Surface_Planar, 1);
     theme_app_unhilite_label = appearance_new(Surface_Planar, 1);
+    theme_app_icon = appearance_new(Surface_Planar, 1);
 
 }
 
@@ -221,8 +227,11 @@ void theme_shutdown()
     appearance_free(theme_a_menu_item);
     appearance_free(theme_a_menu_disabled);
     appearance_free(theme_a_menu_hilite);
+    appearance_free(theme_app_hilite_bg);
+    appearance_free(theme_app_unhilite_bg);
     appearance_free(theme_app_hilite_label);
     appearance_free(theme_app_unhilite_label);
+    appearance_free(theme_app_icon);
 }
 
 static XrmDatabase loaddb(char *theme)
@@ -330,7 +339,7 @@ static gboolean read_mask(XrmDatabase db, char *rname, char *theme,
     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
         retvalue.addr != NULL) {
 
-       button_dir = g_strdup_printf("%s_buttons", theme);
+       button_dir = g_strdup_printf("%s_data", theme);
 
         s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
                              button_dir, retvalue.addr, NULL);
@@ -348,7 +357,7 @@ static gboolean read_mask(XrmDatabase db, char *rname, char *theme,
 
                 g_free(s);
                 themename = g_path_get_basename(theme);
-                s = g_strdup_printf("%s/%s_buttons/%s", theme,
+                s = g_strdup_printf("%s/%s_data/%s", theme,
                                     themename, retvalue.addr);
                 g_free(themename);
                 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) ==
@@ -728,26 +737,15 @@ char *theme_load(char *theme)
     if (!read_appearance(db, "menu.hilite", theme_a_menu_hilite))
        set_default_appearance(theme_a_menu_hilite);
 
-    /* read the appearances for rendering non-decorations. these cannot be
-       parent-relative */
-    if (theme_a_focused_label->surface.data.planar.grad !=
-        Background_ParentRelative) {
-        if (!read_appearance(db, "window.label.focus", theme_app_hilite_label))
-            set_default_appearance(theme_app_hilite_label);
-    } else {
-        if (!read_appearance(db, "window.title.focus", theme_app_hilite_label))
-            set_default_appearance(theme_app_hilite_label);
-    }
-    if (theme_a_unfocused_label->surface.data.planar.grad !=
-        Background_ParentRelative) {
-        if (!read_appearance(db, "window.label.unfocus",
-                             theme_app_unhilite_label))
-            set_default_appearance(theme_app_unhilite_label);
-    } else {
-        if (!read_appearance(db, "window.title.unfocus",
-                             theme_app_unhilite_label))
-            set_default_appearance(theme_app_unhilite_label);
-    }
+    /* read the appearances for rendering non-decorations */
+    if (!read_appearance(db, "window.title.focus", theme_app_hilite_bg))
+        set_default_appearance(theme_app_hilite_bg);
+    if (!read_appearance(db, "window.label.focus", theme_app_hilite_label))
+        set_default_appearance(theme_app_hilite_label);
+    if (!read_appearance(db, "window.title.unfocus", theme_app_unhilite_bg))
+        set_default_appearance(theme_app_unhilite_bg);
+    if (!read_appearance(db, "window.label.unfocus", theme_app_unhilite_label))
+        set_default_appearance(theme_app_unhilite_label);
 
     /* read buttons textures */
     if (!read_appearance(db, "window.button.pressed.focus",
@@ -817,8 +815,8 @@ char *theme_load(char *theme)
     /* set up the textures */
     theme_a_focused_label->texture[0].type = 
         theme_app_hilite_label->texture[0].type = Text;
-    theme_a_focused_label->texture[0].data.text.justify =
-        theme_app_hilite_label->texture[0].data.text.justify = winjust;
+    theme_a_focused_label->texture[0].data.text.justify = winjust;
+    theme_app_hilite_label->texture[0].data.text.justify = Justify_Left;
     theme_a_focused_label->texture[0].data.text.font =
         theme_app_hilite_label->texture[0].data.text.font = theme_winfont;
     theme_a_focused_label->texture[0].data.text.shadow =
@@ -836,8 +834,8 @@ char *theme_load(char *theme)
 
     theme_a_unfocused_label->texture[0].type =
         theme_app_unhilite_label->texture[0].type = Text;
-    theme_a_unfocused_label->texture[0].data.text.justify =
-        theme_app_unhilite_label->texture[0].data.text.justify = winjust;
+    theme_a_unfocused_label->texture[0].data.text.justify = winjust;
+    theme_app_unhilite_label->texture[0].data.text.justify = Justify_Left;
     theme_a_unfocused_label->texture[0].data.text.font =
         theme_app_unhilite_label->texture[0].data.text.font = theme_winfont;
     theme_a_unfocused_label->texture[0].data.text.shadow =
@@ -865,6 +863,7 @@ char *theme_load(char *theme)
 
     theme_a_menu_item->surface.data.planar.grad = 
         theme_a_menu_disabled->surface.data.planar.grad =
+        theme_app_icon->surface.data.planar.grad =
         Background_ParentRelative;
 
     theme_a_menu_item->texture[0].type =
index 97a58f9..2a93c8d 100644 (file)
@@ -78,8 +78,11 @@ extern Appearance *theme_a_menu_item;
 extern Appearance *theme_a_menu_disabled;
 extern Appearance *theme_a_menu_hilite;
 
+extern Appearance *theme_app_hilite_bg;
+extern Appearance *theme_app_unhilite_bg;
 extern Appearance *theme_app_hilite_label;
 extern Appearance *theme_app_unhilite_label;
+extern Appearance *theme_app_icon;
 
 void theme_startup();
 void theme_shutdown();