Change some while loops to for loops in config.c
[mikachu/openbox.git] / openbox / config.c
index 6904759..1f405e5 100644 (file)
@@ -83,12 +83,14 @@ guint           config_dock_show_delay;
 guint           config_dock_app_move_button;
 guint           config_dock_app_move_modifiers;
 
-guint config_keyboard_reset_keycode;
-guint config_keyboard_reset_state;
+guint    config_keyboard_reset_keycode;
+guint    config_keyboard_reset_state;
+gboolean config_keyboard_rebind_on_mapping_notify;
 
-gint config_mouse_threshold;
-gint config_mouse_dclicktime;
-gint config_mouse_screenedgetime;
+gint     config_mouse_threshold;
+gint     config_mouse_dclicktime;
+gint     config_mouse_screenedgetime;
+gboolean config_mouse_screenedgewarp;
 
 guint    config_menu_hide_delay;
 gboolean config_menu_middle;
@@ -106,10 +108,11 @@ GSList *config_per_app_settings;
 
 ObAppSettings* config_create_app_settings(void)
 {
-    ObAppSettings *settings = g_new0(ObAppSettings, 1);
+    ObAppSettings *settings = g_slice_new0(ObAppSettings);
     settings->type = -1;
     settings->decor = -1;
     settings->shade = -1;
+    settings->monitor_type = OB_PLACE_MONITOR_ANY;
     settings->monitor = -1;
     settings->focus = -1;
     settings->desktop = 0;
@@ -134,6 +137,7 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
     copy_if(type, (ObClientType)-1);
     copy_if(decor, -1);
     copy_if(shade, -1);
+    copy_if(monitor_type, OB_PLACE_MONITOR_ANY);
     copy_if(monitor, -1);
     copy_if(focus, -1);
     copy_if(desktop, 0);
@@ -151,20 +155,36 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
         dst->position = src->position;
         /* monitor is copied above */
     }
+
+    dst->width_num = src->width_num;
+    dst->width_denom = src->width_denom;
+    dst->height_num = src->height_num;
+    dst->height_denom = src->height_denom;
+}
+
+void config_parse_relative_number(gchar *s, gint *num, gint *denom)
+{
+    *num = strtol(s, &s, 10);
+
+    if (*s == '%') {
+        *denom = 100;
+    } else if (*s == '/') {
+        *denom = atoi(s+1);
+    }
 }
 
-static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
+void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
 {
     gchar *s = obt_xml_node_string(node);
     if (!g_ascii_strcasecmp(s, "center"))
         c->center = TRUE;
     else {
+        gchar *ps = s;
         if (s[0] == '-')
             c->opposite = TRUE;
         if (s[0] == '-' || s[0] == '+')
-            c->pos = atoi(s+1);
-        else
-            c->pos = atoi(s);
+            ps++;
+        config_parse_relative_number(ps, &c->pos, &c->denom);
     }
     g_free(s);
 }
@@ -186,10 +206,149 @@ static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
   </applications>
 */
 
+static void parse_single_per_app_settings(xmlNodePtr app,
+                                          ObAppSettings *settings)
+{
+    xmlNodePtr n, c;
+    gboolean x_pos_given = FALSE;
+
+    if ((n = obt_xml_find_node(app->children, "decor")))
+        if (!obt_xml_node_contains(n, "default"))
+            settings->decor = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(app->children, "shade")))
+        if (!obt_xml_node_contains(n, "default"))
+            settings->shade = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(app->children, "position"))) {
+        if ((c = obt_xml_find_node(n->children, "x"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                config_parse_gravity_coord(c, &settings->position.x);
+                x_pos_given = TRUE;
+            }
+        }
+
+        if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                config_parse_gravity_coord(c, &settings->position.y);
+                settings->pos_given = TRUE;
+            }
+        }
+
+        /* monitor can be set without setting x or y */
+        if ((c = obt_xml_find_node(n->children, "monitor"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                gchar *s = obt_xml_node_string(c);
+                if (!g_ascii_strcasecmp(s, "mouse"))
+                    settings->monitor_type = OB_PLACE_MONITOR_MOUSE;
+                else if (!g_ascii_strcasecmp(s, "active"))
+                    settings->monitor_type = OB_PLACE_MONITOR_ACTIVE;
+                else if (!g_ascii_strcasecmp(s, "primary"))
+                    settings->monitor_type = OB_PLACE_MONITOR_PRIMARY;
+                else
+                    settings->monitor = obt_xml_node_int(c);
+                g_free(s);
+            }
+        }
+
+        obt_xml_attr_bool(n, "force", &settings->pos_force);
+    }
+
+    if ((n = obt_xml_find_node(app->children, "size"))) {
+        if ((c = obt_xml_find_node(n->children, "width"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                gchar *s = obt_xml_node_string(c);
+                config_parse_relative_number(s,
+                                             &settings->width_num,
+                                             &settings->width_denom);
+                if (settings->width_num <= 0 || settings->width_denom < 0)
+                    settings->width_num = settings->width_denom = 0;
+                g_free(s);
+            }
+        }
+
+        if ((c = obt_xml_find_node(n->children, "height"))) {
+            if (!obt_xml_node_contains(c, "default")) {
+                gchar *s = obt_xml_node_string(c);
+                config_parse_relative_number(s,
+                                             &settings->height_num,
+                                             &settings->height_denom);
+                if (settings->height_num <= 0 || settings->height_denom < 0)
+                    settings->height_num = settings->height_denom = 0;
+                g_free(s);
+            }
+        }
+    }
+
+    if ((n = obt_xml_find_node(app->children, "focus"))) {
+        if (!obt_xml_node_contains(n, "default"))
+            settings->focus = obt_xml_node_bool(n);
+    }
+
+    if ((n = obt_xml_find_node(app->children, "desktop"))) {
+        if (!obt_xml_node_contains(n, "default")) {
+            gchar *s = obt_xml_node_string(n);
+            if (!g_ascii_strcasecmp(s, "all"))
+                settings->desktop = DESKTOP_ALL;
+            else {
+                gint i = obt_xml_node_int(n);
+                if (i > 0)
+                    settings->desktop = i;
+            }
+            g_free(s);
+        }
+    }
+
+    if ((n = obt_xml_find_node(app->children, "layer"))) {
+        if (!obt_xml_node_contains(n, "default")) {
+            gchar *s = obt_xml_node_string(n);
+            if (!g_ascii_strcasecmp(s, "above"))
+                settings->layer = 1;
+            else if (!g_ascii_strcasecmp(s, "below"))
+                settings->layer = -1;
+            else
+                settings->layer = 0;
+            g_free(s);
+        }
+    }
+
+    if ((n = obt_xml_find_node(app->children, "iconic")))
+        if (!obt_xml_node_contains(n, "default"))
+            settings->iconic = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(app->children, "skip_pager")))
+        if (!obt_xml_node_contains(n, "default"))
+            settings->skip_pager = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
+        if (!obt_xml_node_contains(n, "default"))
+            settings->skip_taskbar = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(app->children, "fullscreen")))
+        if (!obt_xml_node_contains(n, "default"))
+            settings->fullscreen = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(app->children, "maximized"))) {
+        if (!obt_xml_node_contains(n, "default")) {
+            gchar *s = obt_xml_node_string(n);
+            if (!g_ascii_strcasecmp(s, "horizontal")) {
+                settings->max_horz = TRUE;
+                settings->max_vert = FALSE;
+            } else if (!g_ascii_strcasecmp(s, "vertical")) {
+                settings->max_horz = FALSE;
+                settings->max_vert = TRUE;
+            } else
+                settings->max_horz = settings->max_vert =
+                    obt_xml_node_bool(n);
+            g_free(s);
+        }
+    }
+}
+
 /* Manages settings for individual applications.
    Some notes: monitor is the screen number in a multi monitor
-   (Xinerama) setup (starting from 0) or mouse, meaning the
-   monitor the pointer is on. Default: mouse.
+   (Xinerama) setup (starting from 0), or mouse: the monitor the pointer
+   is on, active: the active monitor, primary: the primary monitor.
    Layer can be three values, above (Always on top), below
    (Always on bottom) and everything else (normal behaviour).
    Positions can be an integer value or center, which will
@@ -200,18 +359,22 @@ static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr app = obt_xml_find_node(node->children, "application");
-    gchar *name = NULL, *class = NULL, *role = NULL, *type_str = NULL;
-    gboolean name_set, class_set, type_set, role_set;
-    ObClientType type;
-    gboolean x_pos_given;
+    for (; app; app = obt_xml_find_node(app->next, "application")) {
+        ObAppSettings *settings;
 
-    while (app) {
-        x_pos_given = FALSE;
+        gboolean name_set, class_set, role_set, title_set,
+            type_set, group_name_set, group_class_set;
+        gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
+            *type_str = NULL, *group_name = NULL, *group_class = NULL;
+        ObClientType type;
 
         class_set = obt_xml_attr_string(app, "class", &class);
         name_set = obt_xml_attr_string(app, "name", &name);
+        group_class_set = obt_xml_attr_string(app, "groupclass", &group_class);
+        group_name_set = obt_xml_attr_string(app, "groupname", &group_name);
         type_set = obt_xml_attr_string(app, "type", &type_str);
         role_set = obt_xml_attr_string(app, "role", &role);
+        title_set = obt_xml_attr_string(app, "title", &title);
 
         /* validate the type tho */
         if (type_set) {
@@ -235,127 +398,38 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
                 type_set = FALSE; /* not valid! */
         }
 
-        if (class_set || name_set || role_set || type_set) {
-            xmlNodePtr n, c;
-            ObAppSettings *settings = config_create_app_settings();;
-
-            if (name_set)
-                settings->name = g_pattern_spec_new(name);
-
-            if (class_set)
-                settings->class = g_pattern_spec_new(class);
+        if (!(class_set || name_set || role_set || title_set ||
+              type_set || group_class_set || group_name_set))
+            continue;
+
+        settings = config_create_app_settings();
+
+        if (name_set)
+            settings->name = g_pattern_spec_new(name);
+        if (class_set)
+            settings->class = g_pattern_spec_new(class);
+        if (group_name_set)
+            settings->group_name = g_pattern_spec_new(group_name);
+        if (group_class_set)
+            settings->group_class = g_pattern_spec_new(group_class);
+        if (role_set)
+            settings->role = g_pattern_spec_new(role);
+        if (title_set)
+            settings->title = g_pattern_spec_new(title);
+        if (type_set)
+            settings->type = type;
 
-            if (role_set)
-                settings->role = g_pattern_spec_new(role);
-
-            if (type_set)
-                settings->type = type;
-
-            if ((n = obt_xml_find_node(app->children, "decor")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->decor = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "shade")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->shade = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "position"))) {
-                if ((c = obt_xml_find_node(n->children, "x")))
-                    if (!obt_xml_node_contains(c, "default")) {
-                        config_parse_gravity_coord(c, &settings->position.x);
-                        x_pos_given = TRUE;
-                    }
-
-                if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
-                    if (!obt_xml_node_contains(c, "default")) {
-                        config_parse_gravity_coord(c, &settings->position.y);
-                        settings->pos_given = TRUE;
-                    }
-
-                if (settings->pos_given &&
-                    (c = obt_xml_find_node(n->children, "monitor")))
-                    if (!obt_xml_node_contains(c, "default")) {
-                        gchar *s = obt_xml_node_string(c);
-                        if (!g_ascii_strcasecmp(s, "mouse"))
-                            settings->monitor = 0;
-                        else
-                            settings->monitor = obt_xml_node_int(c);
-                        g_free(s);
-                    }
-
-                obt_xml_attr_bool(n, "force", &settings->pos_force);
-            }
-
-            if ((n = obt_xml_find_node(app->children, "focus")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->focus = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "desktop"))) {
-                if (!obt_xml_node_contains(n, "default")) {
-                    gchar *s = obt_xml_node_string(n);
-                    if (!g_ascii_strcasecmp(s, "all"))
-                        settings->desktop = DESKTOP_ALL;
-                    else {
-                        gint i = obt_xml_node_int(n);
-                        if (i > 0)
-                            settings->desktop = i;
-                    }
-                    g_free(s);
-                }
-            }
-
-            if ((n = obt_xml_find_node(app->children, "layer")))
-                if (!obt_xml_node_contains(n, "default")) {
-                    gchar *s = obt_xml_node_string(n);
-                    if (!g_ascii_strcasecmp(s, "above"))
-                        settings->layer = 1;
-                    else if (!g_ascii_strcasecmp(s, "below"))
-                        settings->layer = -1;
-                    else
-                        settings->layer = 0;
-                    g_free(s);
-                }
-
-            if ((n = obt_xml_find_node(app->children, "iconic")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->iconic = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "skip_pager")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->skip_pager = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->skip_taskbar = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "fullscreen")))
-                if (!obt_xml_node_contains(n, "default"))
-                    settings->fullscreen = obt_xml_node_bool(n);
-
-            if ((n = obt_xml_find_node(app->children, "maximized")))
-                if (!obt_xml_node_contains(n, "default")) {
-                    gchar *s = obt_xml_node_string(n);
-                    if (!g_ascii_strcasecmp(s, "horizontal")) {
-                        settings->max_horz = TRUE;
-                        settings->max_vert = FALSE;
-                    } else if (!g_ascii_strcasecmp(s, "vertical")) {
-                        settings->max_horz = FALSE;
-                        settings->max_vert = TRUE;
-                    } else
-                        settings->max_horz = settings->max_vert =
-                            obt_xml_node_bool(n);
-                    g_free(s);
-                }
-
-            config_per_app_settings = g_slist_append(config_per_app_settings,
-                                                     (gpointer) settings);
-            g_free(name);
-            g_free(class);
-            g_free(role);
-            name = class = role = NULL;
-        }
-
-        app = obt_xml_find_node(app->next, "application");
+        g_free(name);
+        g_free(class);
+        g_free(group_name);
+        g_free(group_class);
+        g_free(role);
+        g_free(title);
+        g_free(type_str);
+
+        parse_single_per_app_settings(app, settings);
+        config_per_app_settings = g_slist_append(config_per_app_settings,
+                                                 (gpointer)settings);
     }
 }
 
@@ -371,39 +445,44 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
 
 static void parse_key(xmlNodePtr node, GList *keylist)
 {
-    gchar *key;
+    gchar *keystring, **keys, **key;
     xmlNodePtr n;
     gboolean is_chroot = FALSE;
 
-    if (!obt_xml_attr_string(node, "key", &key))
+    if (!obt_xml_attr_string(node, "key", &keystring))
         return;
 
     obt_xml_attr_bool(node, "chroot", &is_chroot);
 
-    keylist = g_list_append(keylist, key);
+    keys = g_strsplit(keystring, " ", 0);
+    for (key = keys; *key; ++key) {
+        keylist = g_list_append(keylist, *key);
 
-    if ((n = obt_xml_find_node(node->children, "keybind"))) {
-        while (n) {
-            parse_key(n, keylist);
-            n = obt_xml_find_node(n->next, "keybind");
+        if ((n = obt_xml_find_node(node->children, "keybind"))) {
+            while (n) {
+                parse_key(n, keylist);
+                n = obt_xml_find_node(n->next, "keybind");
+            }
         }
-    }
-    else if ((n = obt_xml_find_node(node->children, "action"))) {
-        while (n) {
-            ObActionsAct *action;
+        else if ((n = obt_xml_find_node(node->children, "action"))) {
+            while (n) {
+                ObActionsAct *action;
 
-            action = actions_parse(n);
-            if (action)
-                keyboard_bind(keylist, action);
-            n = obt_xml_find_node(n->next, "action");
+                action = actions_parse(n);
+                if (action)
+                    keyboard_bind(keylist, action);
+                n = obt_xml_find_node(n->next, "action");
+            }
         }
-    }
 
-    if (is_chroot)
-        keyboard_chroot(keylist);
 
-    g_free(key);
-    keylist = g_list_delete_link(keylist, g_list_last(keylist));
+        if (is_chroot)
+            keyboard_chroot(keylist);
+        keylist = g_list_delete_link(keylist, g_list_last(keylist));
+    }
+
+    g_strfreev(keys);
+    g_free(keystring);
 }
 
 static void parse_keyboard(xmlNodePtr node, gpointer d)
@@ -425,6 +504,9 @@ static void parse_keyboard(xmlNodePtr node, gpointer d)
             parse_key(n, NULL);
             n = obt_xml_find_node(n->next, "keybind");
         }
+
+    if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
+        config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
 }
 
 /*
@@ -441,7 +523,7 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n, nbut, nact;
     gchar *buttonstr;
-    gchar *contextstr;
+    gchar *cxstr;
     ObMouseAction mact;
 
     mouse_unbind_all();
@@ -459,42 +541,77 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
         if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
             config_mouse_screenedgetime = 25;
     }
+    if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
+        config_mouse_screenedgewarp = obt_xml_node_bool(n);
+
+    for (n = obt_xml_find_node(node, "context");
+         n;
+         n = obt_xml_find_node(n->next, "context"))
+    {
+        gchar *modcxstr;
+        ObFrameContext cx;
+
+        if (!obt_xml_attr_string(n, "name", &cxstr))
+            continue;
+
+        modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
+        while (frame_next_context_from_string(modcxstr, &cx)) {
+            if (!cx) {
+                gchar *s = strchr(modcxstr, ' ');
+                if (s) {
+                    *s = '\0';
+                    g_message(_("Invalid context \"%s\" in mouse binding"),
+                              modcxstr);
+                    *s = ' ';
+                }
+                continue;
+            }
 
-    n = obt_xml_find_node(node, "context");
-    while (n) {
-        if (!obt_xml_attr_string(n, "name", &contextstr))
-            goto next_n;
-        nbut = obt_xml_find_node(n->children, "mousebind");
-        while (nbut) {
-            if (!obt_xml_attr_string(nbut, "button", &buttonstr))
-                goto next_nbut;
-            if (obt_xml_attr_contains(nbut, "action", "press")) {
-                mact = OB_MOUSE_ACTION_PRESS;
-            } else if (obt_xml_attr_contains(nbut, "action", "release")) {
-                mact = OB_MOUSE_ACTION_RELEASE;
-            } else if (obt_xml_attr_contains(nbut, "action", "click")) {
-                mact = OB_MOUSE_ACTION_CLICK;
-            } else if (obt_xml_attr_contains(nbut, "action","doubleclick")) {
-                mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
-            } else if (obt_xml_attr_contains(nbut, "action", "drag")) {
-                mact = OB_MOUSE_ACTION_MOTION;
-            } else
-                goto next_nbut;
-            nact = obt_xml_find_node(nbut->children, "action");
-            while (nact) {
-                ObActionsAct *action;
-
-                if ((action = actions_parse(nact)))
-                    mouse_bind(buttonstr, contextstr, mact, action);
-                nact = obt_xml_find_node(nact->next, "action");
+            for (nbut = obt_xml_find_node(n->children, "mousebind");
+                 nbut;
+                 nbut = obt_xml_find_node(nbut->next, "mousebind"))
+            {
+
+                gchar **button, **buttons;
+
+                if (!obt_xml_attr_string(nbut, "button", &buttonstr))
+                    continue;
+                if (obt_xml_attr_contains(nbut, "action", "press"))
+                    mact = OB_MOUSE_ACTION_PRESS;
+                else if (obt_xml_attr_contains(nbut, "action", "release"))
+                    mact = OB_MOUSE_ACTION_RELEASE;
+                else if (obt_xml_attr_contains(nbut, "action", "click"))
+                    mact = OB_MOUSE_ACTION_CLICK;
+                else if (obt_xml_attr_contains(nbut, "action","doubleclick"))
+                    mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
+                else if (obt_xml_attr_contains(nbut, "action", "drag"))
+                    mact = OB_MOUSE_ACTION_MOTION;
+                else
+                    continue;
+
+                buttons = g_strsplit(buttonstr, " ", 0);
+                for (nact = obt_xml_find_node(nbut->children, "action");
+                     nact;
+                     nact = obt_xml_find_node(nact->next, "action"))
+                {
+                    ObActionsAct *action;
+
+                    /* actions_parse() creates one ref to the action, but we need
+                     * exactly one ref per binding we use it for. */
+                    if ((action = actions_parse(nact))) {
+                        for (button = buttons; *button; ++button) {
+                            actions_act_ref(action);
+                            mouse_bind(*button, cx, mact, action);
+                        }
+                        actions_act_unref(action);
+                    }
+                }
+                g_strfreev(buttons);
+                g_free(buttonstr);
             }
-            g_free(buttonstr);
-        next_nbut:
-            nbut = obt_xml_find_node(nbut->next, "mousebind");
         }
-        g_free(contextstr);
-    next_n:
-        n = obt_xml_find_node(n->next, "context");
+        g_free(modcxstr);
+        g_free(cxstr);
     }
 }
 
@@ -526,16 +643,20 @@ static void parse_placement(xmlNodePtr node, gpointer d)
 
     node = node->children;
 
-    if ((n = obt_xml_find_node(node, "policy")))
+    if ((n = obt_xml_find_node(node, "policy"))) {
         if (obt_xml_node_contains(n, "UnderMouse"))
             config_place_policy = OB_PLACE_POLICY_MOUSE;
-    if ((n = obt_xml_find_node(node, "center")))
+    }
+    if ((n = obt_xml_find_node(node, "center"))) {
         config_place_center = obt_xml_node_bool(n);
+    }
     if ((n = obt_xml_find_node(node, "monitor"))) {
         if (obt_xml_node_contains(n, "active"))
             config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
         else if (obt_xml_node_contains(n, "mouse"))
             config_place_monitor = OB_PLACE_MONITOR_MOUSE;
+        else if (obt_xml_node_contains(n, "any"))
+            config_place_monitor = OB_PLACE_MONITOR_ANY;
     }
     if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
         config_primary_monitor_index = obt_xml_node_int(n);
@@ -599,8 +720,10 @@ static void parse_theme(xmlNodePtr node, gpointer d)
             config_theme_window_list_icon_size = 96;
     }
 
-    n = obt_xml_find_node(node, "font");
-    while (n) {
+    for (n = obt_xml_find_node(node, "font");
+         n;
+         n = obt_xml_find_node(n->next, "font"))
+    {
         xmlNodePtr   fnode;
         RrFont     **font;
         gchar       *name = g_strdup(RrDefaultFontFamily);
@@ -623,7 +746,7 @@ static void parse_theme(xmlNodePtr node, gpointer d)
         else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
             font = &config_font_inactiveosd;
         else
-            goto next_font;
+            continue;
 
         if ((fnode = obt_xml_find_node(n->children, "name"))) {
             g_free(name);
@@ -650,8 +773,6 @@ static void parse_theme(xmlNodePtr node, gpointer d)
 
         *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
         g_free(name);
-    next_font:
-        n = obt_xml_find_node(n->next, "font");
     }
 }
 
@@ -680,12 +801,13 @@ static void parse_desktops(xmlNodePtr node, gpointer d)
         g_slist_free(config_desktops_names);
         config_desktops_names = NULL;
 
-        nname = obt_xml_find_node(n->children, "name");
-        while (nname) {
+        for (nname = obt_xml_find_node(n->children, "name");
+             nname;
+             nname = obt_xml_find_node(nname->next, "name"))
+        {
             config_desktops_names =
                 g_slist_append(config_desktops_names,
                                obt_xml_node_string(nname));
-            nname = obt_xml_find_node(nname->next, "name");
         }
     }
     if ((n = obt_xml_find_node(node, "popupTime")))
@@ -829,18 +951,20 @@ static void parse_menu(xmlNodePtr node, gpointer d)
         config_menu_manage_desktops = obt_xml_node_bool(n);
     if ((n = obt_xml_find_node(node, "showIcons"))) {
         config_menu_show_icons = obt_xml_node_bool(n);
-#ifndef USE_IMLIB2
+#if !defined(USE_IMLIB2) && !defined(USE_LIBRSVG)
         if (config_menu_show_icons)
-            g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
+            g_message(_("Openbox was compiled without image loading support. Icons in menus will not be loaded."));
 #endif
     }
 
-    while ((node = obt_xml_find_node(node, "file"))) {
+    for (node = obt_xml_find_node(node, "file");
+         node;
+         node = obt_xml_find_node(node->next, "file"))
+    {
             gchar *c = obt_xml_node_string(node);
             config_menu_files = g_slist_append(config_menu_files,
                                                obt_paths_expand_tilde(c));
             g_free(c);
-            node = node->next;
     }
 }
 
@@ -939,8 +1063,8 @@ static void bind_default_mouse(void)
     };
 
     for (it = binds; it->button; ++it)
-        mouse_bind(it->button, it->context, it->mact,
-                   actions_parse_string(it->actname));
+        mouse_bind(it->button, frame_context_from_string(it->context),
+                   it->mact, actions_parse_string(it->actname));
 }
 
 void config_startup(ObtXmlInst *i)
@@ -957,7 +1081,7 @@ void config_startup(ObtXmlInst *i)
 
     config_place_policy = OB_PLACE_POLICY_SMART;
     config_place_center = TRUE;
-    config_place_monitor = OB_PLACE_MONITOR_ANY;
+    config_place_monitor = OB_PLACE_MONITOR_PRIMARY;
 
     config_primary_monitor_index = 1;
     config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
@@ -979,6 +1103,8 @@ void config_startup(ObtXmlInst *i)
     config_font_inactivewindow = NULL;
     config_font_menuitem = NULL;
     config_font_menutitle = NULL;
+    config_font_activeosd = NULL;
+    config_font_inactiveosd = NULL;
 
     obt_xml_register(i, "theme", parse_theme, NULL);
 
@@ -1014,14 +1140,16 @@ void config_startup(ObtXmlInst *i)
 
     translate_key("C-g", &config_keyboard_reset_state,
                   &config_keyboard_reset_keycode);
+    config_keyboard_rebind_on_mapping_notify = TRUE;
 
     bind_default_keyboard();
 
     obt_xml_register(i, "keyboard", parse_keyboard, NULL);
 
     config_mouse_threshold = 8;
-    config_mouse_dclicktime = 200;
+    config_mouse_dclicktime = 500;
     config_mouse_screenedgetime = 400;
+    config_mouse_screenedgewarp = FALSE;
 
     bind_default_mouse();
 
@@ -1034,7 +1162,7 @@ void config_startup(ObtXmlInst *i)
 
     config_menu_hide_delay = 250;
     config_menu_middle = FALSE;
-    config_submenu_show_delay = 200;
+    config_submenu_show_delay = 100;
     config_submenu_hide_delay = 400;
     config_menu_manage_desktops = TRUE;
     config_menu_files = NULL;
@@ -1072,10 +1200,13 @@ void config_shutdown(void)
 
     for (it = config_per_app_settings; it; it = g_slist_next(it)) {
         ObAppSettings *itd = (ObAppSettings *)it->data;
-        if (itd->name)  g_pattern_spec_free(itd->name);
-        if (itd->role)  g_pattern_spec_free(itd->role);
+        if (itd->name) g_pattern_spec_free(itd->name);
+        if (itd->role) g_pattern_spec_free(itd->role);
+        if (itd->title) g_pattern_spec_free(itd->title);
         if (itd->class) g_pattern_spec_free(itd->class);
-        g_free(it->data);
+        if (itd->group_name) g_pattern_spec_free(itd->group_name);
+        if (itd->group_class) g_pattern_spec_free(itd->group_class);
+        g_slice_free(ObAppSettings, it->data);
     }
     g_slist_free(config_per_app_settings);
 }