Merge branch 'backport' into work
authorMikael Magnusson <mikachu@gmail.com>
Sun, 5 Jul 2009 20:27:25 +0000 (22:27 +0200)
committerMikael Magnusson <mikachu@gmail.com>
Sat, 19 Sep 2009 13:03:12 +0000 (15:03 +0200)
Conflicts:
openbox/actions/desktop.c
openbox/client.c
openbox/event.c
openbox/extensions.c
openbox/popup.c
openbox/screen.c
parser/parse.c

12 files changed:
1  2 
configure.ac
obt/paths.c
openbox/actions/desktop.c
openbox/actions/moveresizeto.c
openbox/client.c
openbox/event.c
openbox/frame.c
openbox/menu.c
openbox/popup.c
openbox/screen.c
openbox/startupnotify.c
render/theme.c

diff --cc configure.ac
Simple merge
diff --cc obt/paths.c
index 6100499,0000000..6861543
mode 100644,000000..100644
--- /dev/null
@@@ -1,247 -1,0 +1,249 @@@
-     gchar **spl;
 +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 +
 +   obt/paths.c for the Openbox window manager
 +   Copyright (c) 2003-2007   Dana Jansens
 +
 +   This program is free software; you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by
 +   the Free Software Foundation; either version 2 of the License, or
 +   (at your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +
 +   See the COPYING file for a copy of the GNU General Public License.
 +*/
 +
 +#include "obt/paths.h"
 +#include "obt/util.h"
 +
 +#ifdef HAVE_SYS_STAT_H
 +#  include <sys/stat.h>
 +#endif
 +#ifdef HAVE_SYS_TYPES_H
 +#  include <sys/types.h>
 +#endif
 +#ifdef HAVE_STRING_H
 +#  include <string.h>
 +#endif
 +
 +struct _ObtPaths
 +{
 +    gint   ref;
 +    gchar  *config_home;
 +    gchar  *data_home;
 +    gchar  *cache_home;
 +    GSList *config_dirs;
 +    GSList *data_dirs;
 +};
 +
 +static gint slist_path_cmp(const gchar *a, const gchar *b)
 +{
 +    return strcmp(a, b);
 +}
 +
 +typedef GSList* (*GSListFunc) (gpointer list, gconstpointer data);
 +
 +static GSList* slist_path_add(GSList *list, gpointer data, GSListFunc func)
 +{
 +    g_assert(func);
 +
 +    if (!data)
 +        return list;
 +
 +    if (!g_slist_find_custom(list, data, (GCompareFunc) slist_path_cmp))
 +        list = func(list, data);
 +    else
 +        g_free(data);
 +
 +    return list;
 +}
 +
 +static GSList* split_paths(const gchar *paths)
 +{
 +    GSList *list = NULL;
 +    gchar **spl, **it;
 +
 +    if (!paths)
 +        return NULL;
 +    spl = g_strsplit(paths, ":", -1);
 +    for (it = spl; *it; ++it)
 +        list = slist_path_add(list, *it, (GSListFunc) g_slist_append);
 +    g_free(spl);
 +    return list;
 +}
 +
 +ObtPaths* obt_paths_new(void)
 +{
 +    ObtPaths *p;
 +    const gchar *path;
 +
 +    p = g_new0(ObtPaths, 1);
 +    p->ref = 1;
 +
 +    path = g_getenv("XDG_CONFIG_HOME");
 +    if (path && path[0] != '\0') /* not unset or empty */
 +        p->config_home = g_build_filename(path, NULL);
 +    else
 +        p->config_home = g_build_filename(g_get_home_dir(), ".config", NULL);
 +
 +    path = g_getenv("XDG_DATA_HOME");
 +    if (path && path[0] != '\0') /* not unset or empty */
 +        p->data_home = g_build_filename(path, NULL);
 +    else
 +        p->data_home = g_build_filename(g_get_home_dir(), ".local",
 +                                        "share", NULL);
 +
 +    path = g_getenv("XDG_CACHE_HOME");
 +    if (path && path[0] != '\0') /* not unset or empty */
 +        p->cache_home = g_build_filename(path, NULL);
 +    else
 +        p->cache_home = g_build_filename(g_get_home_dir(), ".cache", NULL);
 +
 +    path = g_getenv("XDG_CONFIG_DIRS");
 +    if (path && path[0] != '\0') /* not unset or empty */
 +        p->config_dirs = split_paths(path);
 +    else {
 +        p->config_dirs = slist_path_add(p->config_dirs,
 +                                        g_strdup(CONFIGDIR),
 +                                        (GSListFunc) g_slist_append);
 +        p->config_dirs = slist_path_add(p->config_dirs,
 +                                        g_build_filename
 +                                        (G_DIR_SEPARATOR_S,
 +                                         "etc", "xdg", NULL),
 +                                        (GSListFunc) g_slist_append);
 +    }
 +    p->config_dirs = slist_path_add(p->config_dirs,
 +                                    g_strdup(p->config_home),
 +                                    (GSListFunc) g_slist_prepend);
 +
 +    path = g_getenv("XDG_DATA_DIRS");
 +    if (path && path[0] != '\0') /* not unset or empty */
 +        p->data_dirs = split_paths(path);
 +    else {
 +        p->data_dirs = slist_path_add(p->data_dirs,
 +                                      g_strdup(DATADIR),
 +                                      (GSListFunc) g_slist_append);
 +        p->data_dirs = slist_path_add(p->data_dirs,
 +                                      g_build_filename
 +                                      (G_DIR_SEPARATOR_S,
 +                                       "usr", "local", "share", NULL),
 +                                      (GSListFunc) g_slist_append);
 +        p->data_dirs = slist_path_add(p->data_dirs,
 +                                      g_build_filename
 +                                      (G_DIR_SEPARATOR_S,
 +                                       "usr", "share", NULL),
 +                                      (GSListFunc) g_slist_append);
 +    }
 +    p->data_dirs = slist_path_add(p->data_dirs,
 +                                  g_strdup(p->data_home),
 +                                  (GSListFunc) g_slist_prepend);
 +    return p;
 +}
 +
 +void obt_paths_ref(ObtPaths *p)
 +{
 +    ++p->ref;
 +}
 +
 +void obt_paths_unref(ObtPaths *p)
 +{
 +    if (p && --p->ref == 0) {
 +        GSList *it;
 +
 +        for (it = p->config_dirs; it; it = g_slist_next(it))
 +            g_free(it->data);
 +        g_slist_free(p->config_dirs);
 +        for (it = p->data_dirs; it; it = g_slist_next(it))
 +            g_free(it->data);
 +        g_slist_free(p->data_dirs);
 +        g_free(p->config_home);
 +        g_free(p->data_home);
 +        g_free(p->cache_home);
 +
 +        obt_free0(p, ObtPaths, 1);
 +    }
 +}
 +
 +gchar *obt_paths_expand_tilde(const gchar *f)
 +{
-     spl = g_strsplit(f, "~", 0);
-     ret = g_strjoinv(g_get_home_dir(), spl);
-     g_strfreev(spl);
 +    gchar *ret;
++    GRegex *regex;
 +
 +    if (!f)
 +        return NULL;
++
++    regex = g_regex_new("(?:^|(?<=[ \\t]))~(?=[/ \\t$])", G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
++    ret = g_regex_replace_literal(regex, f, -1, 0, g_get_home_dir(), 0, NULL);
++    g_regex_unref(regex);
++
 +    return ret;
 +}
 +
 +gboolean obt_paths_mkdir(const gchar *path, gint mode)
 +{
 +    gboolean ret = TRUE;
 +
 +    g_return_val_if_fail(path != NULL, FALSE);
 +    g_return_val_if_fail(path[0] != '\0', FALSE);
 +
 +    if (!g_file_test(path, G_FILE_TEST_IS_DIR))
 +        if (mkdir(path, mode) == -1)
 +            ret = FALSE;
 +
 +    return ret;
 +}
 +
 +gboolean obt_paths_mkdir_path(const gchar *path, gint mode)
 +{
 +    gboolean ret = TRUE;
 +
 +    g_return_val_if_fail(path != NULL, FALSE);
 +    g_return_val_if_fail(path[0] == '/', FALSE);
 +
 +    if (!g_file_test(path, G_FILE_TEST_IS_DIR)) {
 +        gchar *c, *e;
 +
 +        c = g_strdup(path);
 +        e = c;
 +        while ((e = strchr(e + 1, '/'))) {
 +            *e = '\0';
 +            if (!(ret = obt_paths_mkdir(c, mode)))
 +                goto parse_mkdir_path_end;
 +            *e = '/';
 +        }
 +        ret = obt_paths_mkdir(c, mode);
 +
 +    parse_mkdir_path_end:
 +        g_free(c);
 +    }
 +
 +    return ret;
 +}
 +
 +const gchar* obt_paths_config_home(ObtPaths *p)
 +{
 +    return p->config_home;
 +}
 +
 +const gchar* obt_paths_data_home(ObtPaths *p)
 +{
 +    return p->data_home;
 +}
 +
 +const gchar* obt_paths_cache_home(ObtPaths *p)
 +{
 +    return p->cache_home;
 +}
 +
 +GSList* obt_paths_config_dirs(ObtPaths *p)
 +{
 +    return p->config_dirs;
 +}
 +
 +GSList* obt_paths_data_dirs(ObtPaths *p)
 +{
 +    return p->data_dirs;
 +}
@@@ -46,12 -49,12 +46,12 @@@ static gpointer setup_go_func(xmlNodePt
      o = g_new0(Options, 1);
      /* don't go anywhere if theres no options given */
      o->type = ABSOLUTE;
-     o->abs.desktop = screen_desktop;
+     o->u.abs.desktop = screen_desktop;
      /* wrap by default - it's handy! */
-     o->rel.wrap = TRUE;
+     o->u.rel.wrap = TRUE;
  
 -    if ((n = parse_find_node("to", node))) {
 -        gchar *s = parse_string(doc, n);
 +    if ((n = obt_parse_find_node(node, "to"))) {
 +        gchar *s = obt_parse_node_string(n);
          if (!g_ascii_strcasecmp(s, "last"))
              o->type = LAST;
          else if (!g_ascii_strcasecmp(s, "next")) {
@@@ -91,8 -94,8 +91,8 @@@
          g_free(s);
      }
  
 -    if ((n = parse_find_node("wrap", node)))
 -        o->u.rel.wrap = parse_bool(doc, n);
 +    if ((n = obt_parse_find_node(node, "wrap")))
-         o->rel.wrap = obt_parse_node_bool(n);
++        o->u.rel.wrap = obt_parse_node_bool(n);
  
      return o;
  }
@@@ -84,8 -91,12 +86,12 @@@ static gpointer setup_func(xmlNodePtr n
          if (g_ascii_strcasecmp(s, "current") != 0) {
              if (!g_ascii_strcasecmp(s, "all"))
                  o->monitor = ALL_MONITORS;
+             else if(!g_ascii_strcasecmp(s, "next"))
+                 o->monitor = NEXT_MONITOR;
+             else if(!g_ascii_strcasecmp(s, "prev"))
+                 o->monitor = PREV_MONITOR;
              else
 -                o->monitor = parse_int(doc, n) - 1;
 +                o->monitor = obt_parse_node_int(n) - 1;
          }
          g_free(s);
      }
@@@ -231,9 -311,14 +231,14 @@@ void client_manage(Window window, ObPro
      /* get all the stuff off the window */
      client_get_all(self, TRUE);
  
 -    ob_debug("Window type: %d\n", self->type);
 -    ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
 -    ob_debug("Window name: %s class: %s role: %s\n", self->name, self->class, self->role);
 +    ob_debug("Window type: %d", self->type);
 +    ob_debug("Window group: 0x%x", self->group?self->group->leader:0);
-     ob_debug("Window name: %s class: %s", self->name, self->class);
++    ob_debug("Window name: %s class: %s role: %s", self->name, self->class, self->role);
+     /* per-app settings override stuff from client_get_all, and return the
+        settings for other uses too. the returned settings is a shallow copy,
+        that needs to be freed with g_free(). */
+     settings = client_get_settings_state(self);
  
      /* now we have all of the window's information so we can set this up.
         do this before creating the frame, so it can tell that we are still
@@@ -3538,16 -3591,32 +3539,32 @@@ ObClient *client_search_modal_child(ObC
      return NULL;
  }
  
 -    if (XCheckTypedWindowEvent(ob_display, self->window, UnmapNotify, &e)) {
+ static gboolean client_validate_unmap(ObClient *self, int n)
+ {
+     XEvent e;
+     gboolean ret = TRUE;
 -        XPutBackEvent(ob_display, &e);
++    if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) {
+         if (n < self->ignore_unmaps) // ignore this one, but look for more
+             ret = client_validate_unmap(self, n+1);
+         else
+             ret = FALSE; // the window is going to become unmanaged
+         /* put them back on the event stack so they end up in the same order */
++        XPutBackEvent(obt_display, &e);
+     }
+     return ret;
+ }
  gboolean client_validate(ObClient *self)
  {
      XEvent e;
  
 -    XSync(ob_display, FALSE); /* get all events on the server */
 +    XSync(obt_display, FALSE); /* get all events on the server */
  
-     if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e) ||
-         XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e))
-     {
 -    if (XCheckTypedWindowEvent(ob_display, self->window, DestroyNotify, &e)) {
 -        XPutBackEvent(ob_display, &e);
++    if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) {
 +        XPutBackEvent(obt_display, &e);
          return FALSE;
      }
  
diff --cc openbox/event.c
@@@ -656,9 -651,10 +656,9 @@@ static void event_process(const XEvent 
      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("Kepboard map changed. Reloading keyboard bindings.");
 -        ob_debug("Keyboard map changed. Reloading keyboard bindings.\n");
++        ob_debug("Keyboard map changed. Reloading keyboard bindings.");
          ob_set_state(OB_STATE_RECONFIGURING);
 -        modkeys_shutdown(TRUE);
 -        modkeys_startup(TRUE);
 +        obt_keyboard_reload();
          keyboard_rebind();
          ob_set_state(OB_STATE_RUNNING);
      }
diff --cc openbox/frame.c
Simple merge
diff --cc openbox/menu.c
Simple merge
diff --cc openbox/popup.c
@@@ -319,7 -320,7 +319,7 @@@ void popup_hide(ObPopup *self
  
          event_end_ignore_all_enters(ignore_start);
      } else if (self->delay_mapped) {
-         obt_main_loop_timeout_remove(ob_main_loop, popup_show_timeout);
 -        ob_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE);
++        obt_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE);
          self->delay_mapped = FALSE;
      }
  }
@@@ -922,28 -950,36 +939,36 @@@ void screen_show_desktop_popup(guint d
      /* 0 means don't show the popup */
      if (!config_desktop_popup_time) return;
  
-     a = screen_physical_area_active();
-     pager_popup_position(desktop_popup, CenterGravity,
-                          a->x + a->width / 2, a->y + a->height / 2);
-     pager_popup_icon_size_multiplier(desktop_popup,
-                                      (screen_desktop_layout.columns /
-                                       screen_desktop_layout.rows) / 2,
-                                      (screen_desktop_layout.rows/
-                                       screen_desktop_layout.columns) / 2);
-     pager_popup_max_width(desktop_popup,
-                           MAX(a->width/3, POPUP_WIDTH));
-     pager_popup_show(desktop_popup, screen_desktop_names[d], d);
-     obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
-     obt_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000,
-                               hide_desktop_popup_func, NULL, NULL, NULL);
-     g_free(a);
+     for (i = 0; i < screen_num_monitors; i++) {
+         a = screen_physical_area_monitor(i);
+         pager_popup_position(desktop_popup[i], CenterGravity,
+                              a->x + a->width / 2, a->y + a->height / 2);
+         pager_popup_icon_size_multiplier(desktop_popup[i],
+                                          (screen_desktop_layout.columns /
+                                           screen_desktop_layout.rows) / 2,
+                                          (screen_desktop_layout.rows/
+                                           screen_desktop_layout.columns) / 2);
+         pager_popup_max_width(desktop_popup[i],
+                               MAX(a->width/3, POPUP_WIDTH));
+         pager_popup_show(desktop_popup[i], screen_desktop_names[d], d);
 -        ob_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
 -        ob_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000,
 -                                 hide_desktop_popup_func, desktop_popup[i],
 -                                 g_direct_equal, NULL);
++        obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
++        obt_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000,
++                                  hide_desktop_popup_func, desktop_popup[i],
++                                  g_direct_equal, NULL);
+         g_free(a);
+     }
  }
  
  void screen_hide_desktop_popup(void)
  {
-     obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
-     pager_popup_hide(desktop_popup);
+     guint i;
+     for (i = 0; i < screen_num_monitors; i++) {
 -        ob_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func,
 -                                         desktop_popup[i], FALSE);
++        obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func,
++                                          desktop_popup[i], FALSE);
+         pager_popup_hide(desktop_popup[i]);
+     }
  }
  
  guint screen_find_desktop(guint from, ObDirection dir,
@@@ -1299,54 -1338,6 +1326,55 @@@ typedef struct 
      } \
  }
  
-     gint l, r, t, b;
 +static void get_xinerama_screens(Rect **xin_areas, guint *nxin)
 +{
 +    guint i;
-     else if (obt_display_extension_xinerama) {
-         guint i;
-         gint n;
-         XineramaScreenInfo *info = XineramaQueryScreens(obt_display, &n);
++    gint n, l, r, t, b;
++#ifdef XINERAMA
++    XineramaScreenInfo *info;
++#endif
 +
 +    if (ob_debug_xinerama) {
 +        gint w = WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen));
 +        gint h = HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen));
 +        *nxin = 2;
 +        *xin_areas = g_new(Rect, *nxin + 1);
 +        RECT_SET((*xin_areas)[0], 0, 0, w/2, h);
 +        RECT_SET((*xin_areas)[1], w/2, 0, w-(w/2), h);
 +    }
 +#ifdef XINERAMA
++    else if (obt_display_extension_xinerama &&
++             (info = XineramaQueryScreens(obt_display, &n))) {
 +        *nxin = n;
 +        *xin_areas = g_new(Rect, *nxin + 1);
 +        for (i = 0; i < *nxin; ++i)
 +            RECT_SET((*xin_areas)[i], info[i].x_org, info[i].y_org,
 +                     info[i].width, info[i].height);
 +        XFree(info);
 +    }
 +#endif
 +    else {
 +        *nxin = 1;
 +        *xin_areas = g_new(Rect, *nxin + 1);
 +        RECT_SET((*xin_areas)[0], 0, 0,
 +                 WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen)),
 +                 HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen)));
 +    }
 +
 +    /* returns one extra with the total area in it */
 +    l = (*xin_areas)[0].x;
 +    t = (*xin_areas)[0].y;
 +    r = (*xin_areas)[0].x + (*xin_areas)[0].width - 1;
 +    b = (*xin_areas)[0].y + (*xin_areas)[0].height - 1;
 +    for (i = 1; i < *nxin; ++i) {
 +        l = MIN(l, (*xin_areas)[i].x);
 +        t = MIN(l, (*xin_areas)[i].y);
 +        r = MAX(r, (*xin_areas)[i].x + (*xin_areas)[i].width - 1);
 +        b = MAX(b, (*xin_areas)[i].y + (*xin_areas)[i].height - 1);
 +    }
 +    RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1);
 +}
 +
  void screen_update_areas(void)
  {
      guint i, j;
      GSList *sit;
  
      g_free(monitor_area);
 -    extensions_xinerama_screens(&monitor_area, &screen_num_monitors);
 +    get_xinerama_screens(&monitor_area, &screen_num_monitors);
  
+     if (!desktop_popup) {
+         desktop_popup = g_new(ObPagerPopup*, screen_num_monitors);
+         for (i = 0; i < screen_num_monitors; i++) {
+             desktop_popup[i] = pager_popup_new();
+             pager_popup_height(desktop_popup[i], POPUP_HEIGHT);
+             if (screen_desktop_names)
+                 /* update the pager popup's width */
+                 pager_popup_text_width_to_strings(desktop_popup[i],
+                                                   screen_desktop_names,
+                                                   screen_num_desktops);
+         }
+     }
      /* set up the user-specified margins */
      config_margins.top_start = RECT_LEFT(monitor_area[screen_num_monitors]);
      config_margins.top_end = RECT_RIGHT(monitor_area[screen_num_monitors]);
Simple merge
diff --cc render/theme.c
Simple merge