Fix a double free when you have a mousebind without a button attribute
[dana/openbox.git] / openbox / config.c
index 72d0546..025a683 100644 (file)
@@ -86,9 +86,10 @@ guint           config_dock_app_move_modifiers;
 guint config_keyboard_reset_keycode;
 guint config_keyboard_reset_state;
 
-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,7 +107,7 @@ 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;
@@ -153,18 +154,29 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
     }
 }
 
-static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
+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);
+    }
+}
+
+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);
 }
@@ -239,7 +251,7 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
 
         if (class_set || name_set || role_set || title_set || type_set) {
             xmlNodePtr n, c;
-            ObAppSettings *settings = config_create_app_settings();;
+            ObAppSettings *settings = config_create_app_settings();
 
             if (name_set)
                 settings->name = g_pattern_spec_new(name);
@@ -447,7 +459,7 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n, nbut, nact;
     gchar *buttonstr;
-    gchar *contextstr;
+    gchar *cxstr;
     ObMouseAction mact;
 
     mouse_unbind_all();
@@ -465,40 +477,62 @@ 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);
 
     n = obt_xml_find_node(node, "context");
     while (n) {
-        if (!obt_xml_attr_string(n, "name", &contextstr))
+        gchar *modcxstr;
+        ObFrameContext cx;
+
+        if (!obt_xml_attr_string(n, "name", &cxstr))
             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");
+
+        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;
             }
+
+            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, cx, mact, action);
+                    nact = obt_xml_find_node(nact->next, "action");
+                }
             g_free(buttonstr);
-        next_nbut:
+            next_nbut:
             nbut = obt_xml_find_node(nbut->next, "mousebind");
+            }
         }
-        g_free(contextstr);
+        g_free(modcxstr);
+        g_free(cxstr);
     next_n:
         n = obt_xml_find_node(n->next, "context");
     }
@@ -945,8 +979,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)
@@ -985,6 +1019,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);
 
@@ -1028,6 +1064,7 @@ void config_startup(ObtXmlInst *i)
     config_mouse_threshold = 8;
     config_mouse_dclicktime = 200;
     config_mouse_screenedgetime = 400;
+    config_mouse_screenedgewarp = FALSE;
 
     bind_default_mouse();
 
@@ -1040,7 +1077,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;
@@ -1082,7 +1119,7 @@ void config_shutdown(void)
         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);
+        g_slice_free(ObAppSettings, it->data);
     }
     g_slist_free(config_per_app_settings);
 }