Merge branch 'backport' into work
[mikachu/openbox.git] / openbox / config.c
index 70e44d7..790b03b 100644 (file)
 #include "mouse.h"
 #include "actions.h"
 #include "translate.h"
+#include "hooks.h"
 #include "client.h"
 #include "screen.h"
 #include "openbox.h"
 #include "gettext.h"
+#include "obt/paths.h"
 
 gboolean config_focus_new;
 gboolean config_focus_follow;
@@ -34,14 +36,15 @@ gboolean config_focus_raise;
 gboolean config_focus_last;
 gboolean config_focus_under_mouse;
 
-ObPlacePolicy config_place_policy;
-gboolean      config_place_center;
-gboolean      config_place_active;
+ObPlacePolicy  config_place_policy;
+gboolean       config_place_center;
+ObPlaceMonitor config_place_monitor;
 
 StrutPartial config_margins;
 
 gchar   *config_theme;
 gboolean config_theme_keepborder;
+guint    config_theme_window_list_icon_size;
 
 gchar   *config_title_layout;
 
@@ -53,7 +56,7 @@ RrFont *config_font_menuitem;
 RrFont *config_font_menutitle;
 RrFont *config_font_osd;
 
-gint    config_desktops_num;
+guint   config_desktops_num;
 GSList *config_desktops_names;
 guint   config_screen_firstdesk;
 guint   config_desktop_popup_time;
@@ -87,6 +90,7 @@ guint    config_menu_hide_delay;
 gboolean config_menu_middle;
 guint    config_submenu_show_delay;
 gboolean config_menu_client_list_icons;
+gboolean config_menu_manage_desktops;
 
 GSList *config_menu_files;
 
@@ -98,6 +102,7 @@ GSList *config_per_app_settings;
 ObAppSettings* config_create_app_settings(void)
 {
     ObAppSettings *settings = g_new0(ObAppSettings, 1);
+    settings->type = -1;
     settings->decor = -1;
     settings->shade = -1;
     settings->monitor = -1;
@@ -121,6 +126,7 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
     g_assert(src != NULL);
     g_assert(dst != NULL);
 
+    copy_if(type, (ObClientType)-1);
     copy_if(decor, -1);
     copy_if(shade, -1);
     copy_if(focus, -1);
@@ -135,6 +141,7 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
 
     if (src->pos_given) {
         dst->pos_given = TRUE;
+        dst->pos_force = src->pos_force;
         dst->position = src->position;
         dst->monitor = src->monitor;
     }
@@ -187,15 +194,16 @@ static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
 static void parse_per_app_settings(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr app = obt_parse_find_node(node->children, "application");
-    gchar *name = NULL, *class = NULL, *role = NULL;
-    gboolean name_set, class_set;
+    gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
+    gboolean name_set, class_set, type_set;
     gboolean x_pos_given;
 
     while (app) {
-        name_set = class_set = x_pos_given = FALSE;
+        name_set = class_set = type_set = x_pos_given = FALSE;
 
         class_set = obt_parse_attr_string(app, "class", &class);
         name_set = obt_parse_attr_string(app, "name", &name);
+        type_set = obt_parse_attr_string(app, "type", &type);
         if (class_set || name_set) {
             xmlNodePtr n, c;
             ObAppSettings *settings = config_create_app_settings();;
@@ -206,6 +214,25 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
             if (class_set)
                 settings->class = g_pattern_spec_new(class);
 
+            if (type_set) {
+                if (!g_ascii_strcasecmp(type, "normal"))
+                    settings->type = OB_CLIENT_TYPE_NORMAL;
+                else if (!g_ascii_strcasecmp(type, "dialog"))
+                    settings->type = OB_CLIENT_TYPE_DIALOG;
+                else if (!g_ascii_strcasecmp(type, "splash"))
+                    settings->type = OB_CLIENT_TYPE_SPLASH;
+                else if (!g_ascii_strcasecmp(type, "utility"))
+                    settings->type = OB_CLIENT_TYPE_UTILITY;
+                else if (!g_ascii_strcasecmp(type, "menu"))
+                    settings->type = OB_CLIENT_TYPE_MENU;
+                else if (!g_ascii_strcasecmp(type, "toolbar"))
+                    settings->type = OB_CLIENT_TYPE_TOOLBAR;
+                else if (!g_ascii_strcasecmp(type, "dock"))
+                    settings->type = OB_CLIENT_TYPE_DOCK;
+                else if (!g_ascii_strcasecmp(type, "desktop"))
+                    settings->type = OB_CLIENT_TYPE_DESKTOP;
+            }
+
             if (obt_parse_attr_string(app, "role", &role))
                 settings->role = g_pattern_spec_new(role);
 
@@ -225,7 +252,7 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
                     }
 
                 if (x_pos_given && (c = obt_parse_find_node(n->children, "y")))
-                    if (!obt_parse_node_contains("default", doc, c)) {
+                    if (!obt_parse_node_contains(c, "default")) {
                         config_parse_gravity_coord(c, &settings->position.y);
                         settings->pos_given = TRUE;
                     }
@@ -240,6 +267,8 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
                             settings->monitor = obt_parse_node_int(c) + 1;
                         g_free(s);
                     }
+
+                obt_parse_attr_bool(n, "force", &settings->pos_force);
             }
 
             if ((n = obt_parse_find_node(app->children, "focus")))
@@ -315,6 +344,47 @@ static void parse_per_app_settings(xmlNodePtr node, gpointer d)
     }
 }
 
+static void parse_hook(xmlNodePtr node, gpointer d)
+{
+    gchar *name;
+    ObHook hook;
+    xmlNodePtr n;
+
+
+    if (!obt_parse_attr_string(node, "name", &name)) {
+        g_message(_("Hook in config file is missing a name"));
+        return;
+    }
+
+    hook = hooks_hook_from_name(name);
+    if (!hook)
+        g_message(_("Unknown hook \"%s\" in config file"), name);
+    else {
+        if ((n = obt_parse_find_node(node->children, "action")))
+            while (n) {
+                ObActionsAct *action;
+
+                action = actions_parse(n);
+                if (action)
+                    hooks_add(hook, action);
+                n = obt_parse_find_node(n->next, "action");
+            }
+    }
+
+    g_free(name);
+}
+
+static void parse_hooks(xmlNodePtr node, gpointer d)
+{
+    xmlNodePtr n;
+
+    if ((n = obt_parse_find_node(node->children, "hook")))
+        while (n) {
+            parse_hook(n, NULL);
+            n = obt_parse_find_node(n->next, "hook");
+        }
+}
+
 /*
 
 <keybind key="C-x">
@@ -480,8 +550,12 @@ static void parse_placement(xmlNodePtr node, gpointer d)
             config_place_policy = OB_PLACE_POLICY_MOUSE;
     if ((n = obt_parse_find_node(node, "center")))
         config_place_center = obt_parse_node_bool(n);
-    if ((n = obt_parse_find_node(node, "active")))
-        config_place_active = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "monitor"))) {
+        if (obt_parse_node_contains(n, "active"))
+            config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
+        else if (obt_parse_node_contains(n, "mouse"))
+            config_place_monitor = OB_PLACE_MONITOR_MOUSE;
+    }
 }
 
 static void parse_margins(xmlNodePtr node, gpointer d)
@@ -511,7 +585,7 @@ static void parse_theme(xmlNodePtr node, gpointer d)
 
         g_free(config_theme);
         c = obt_parse_node_string(n);
-        config_theme = parse_expand_tilde(c);
+        config_theme = obt_paths_expand_tilde(c);
         g_free(c);
     }
     if ((n = obt_parse_find_node(node, "titleLayout"))) {
@@ -529,6 +603,13 @@ static void parse_theme(xmlNodePtr node, gpointer d)
         config_theme_keepborder = obt_parse_node_bool(n);
     if ((n = obt_parse_find_node(node, "animateIconify")))
         config_animate_iconify = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "windowListIconSize"))) {
+        config_theme_window_list_icon_size = obt_parse_node_int(n);
+        if (config_theme_window_list_icon_size < 16)
+            config_theme_window_list_icon_size = 16;
+        else if (config_theme_window_list_icon_size > 96)
+            config_theme_window_list_icon_size = 96;
+    }
 
     n = obt_parse_find_node(node, "font");
     while (n) {
@@ -591,7 +672,7 @@ static void parse_desktops(xmlNodePtr node, gpointer d)
     if ((n = obt_parse_find_node(node, "number"))) {
         gint d = obt_parse_node_int(n);
         if (d > 0)
-            config_desktops_num = d;
+            config_desktops_num = (unsigned) d;
     }
     if ((n = obt_parse_find_node(node, "firstdesk"))) {
         gint d = obt_parse_node_int(n);
@@ -653,6 +734,11 @@ static void parse_resize(xmlNodePtr node, gpointer d)
                 if ((n2 = obt_parse_find_node(n->children, "y")))
                     config_parse_gravity_coord(n2,
                                                &config_resize_popup_fixed.y);
+
+                config_resize_popup_fixed.x.pos =
+                    MAX(config_resize_popup_fixed.x.pos, 0);
+                config_resize_popup_fixed.y.pos =
+                    MAX(config_resize_popup_fixed.y.pos, 0);
             }
         }
     }
@@ -728,7 +814,7 @@ static void parse_dock(xmlNodePtr node, gpointer d)
             config_dock_app_move_button = b;
             config_dock_app_move_modifiers = s;
         } else {
-            g_message(_("Invalid button '%s' specified in config file"), str);
+            g_message(_("Invalid button \"%s\" specified in config file"), str);
         }
         g_free(str);
     }
@@ -737,23 +823,25 @@ static void parse_dock(xmlNodePtr node, gpointer d)
 static void parse_menu(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
-    for (node = node->children; node; node = node->next) {
-        if (!xmlStrcasecmp(node->name, (const xmlChar*) "file")) {
-            gchar *c;
+    node = node->children;
 
-            c = obt_parse_node_string(node);
+    if ((n = obt_parse_find_node(node, "hideDelay")))
+        config_menu_hide_delay = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "middle")))
+        config_menu_middle = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "submenuShowDelay")))
+        config_submenu_show_delay = obt_parse_node_int(n);
+    if ((n = obt_parse_find_node(node, "applicationIcons")))
+        config_menu_client_list_icons = obt_parse_node_bool(n);
+    if ((n = obt_parse_find_node(node, "manageDesktops")))
+        config_menu_manage_desktops = obt_parse_node_bool(n);
+
+    while ((node = obt_parse_find_node(node, "file"))) {
+            gchar *c = obt_parse_node_string(node);
             config_menu_files = g_slist_append(config_menu_files,
-                                               parse_expand_tilde(c));
+                                               obt_paths_expand_tilde(c));
             g_free(c);
-        }
-        if ((n = obt_parse_find_node(node, "hideDelay")))
-            config_menu_hide_delay = obt_parse_node_int(n);
-        if ((n = obt_parse_find_node(node, "middle")))
-            config_menu_middle = obt_parse_node_bool(n);
-        if ((n = obt_parse_find_node(node, "submenuShowDelay")))
-            config_submenu_show_delay = obt_parse_node_int(n);
-        if ((n = obt_parse_find_node(node, "applicationIcons")))
-            config_menu_client_list_icons = obt_parse_node_bool(n);
+            node = node->next;
     }
 }
 
@@ -869,7 +957,7 @@ void config_startup(ObtParseInst *i)
 
     config_place_policy = OB_PLACE_POLICY_SMART;
     config_place_center = TRUE;
-    config_place_active = FALSE;
+    config_place_monitor = OB_PLACE_MONITOR_ANY;
 
     obt_parse_register(i, "placement", parse_placement, NULL);
 
@@ -882,6 +970,7 @@ void config_startup(ObtParseInst *i)
     config_animate_iconify = TRUE;
     config_title_layout = g_strdup("NLIMC");
     config_theme_keepborder = TRUE;
+    config_theme_window_list_icon_size = 36;
 
     config_font_activewindow = NULL;
     config_font_inactivewindow = NULL;
@@ -944,10 +1033,13 @@ void config_startup(ObtParseInst *i)
     config_menu_middle = FALSE;
     config_submenu_show_delay = 0;
     config_menu_client_list_icons = TRUE;
+    config_menu_manage_desktops = TRUE;
     config_menu_files = NULL;
 
     obt_parse_register(i, "menu", parse_menu, NULL);
 
+    obt_parse_register(i, "hooks", parse_hooks, NULL);
+
     config_per_app_settings = NULL;
 
     obt_parse_register(i, "applications", parse_per_app_settings, NULL);
@@ -965,6 +1057,7 @@ void config_shutdown(void)
     RrFontClose(config_font_inactivewindow);
     RrFontClose(config_font_menuitem);
     RrFontClose(config_font_menutitle);
+    RrFontClose(config_font_osd);
 
     for (it = config_desktops_names; it; it = g_slist_next(it))
         g_free(it->data);