+guint config_screen_firstdesk;
+guint config_desktop_popup_time;
+
+gboolean config_resize_redraw;
+gint config_resize_popup_show;
+ObResizePopupPos config_resize_popup_pos;
+GravityPoint config_resize_popup_fixed;
+
+ObStackingLayer config_dock_layer;
+gboolean config_dock_floating;
+gboolean config_dock_nostrut;
+ObDirection config_dock_pos;
+gint config_dock_x;
+gint config_dock_y;
+ObOrientation config_dock_orient;
+gboolean config_dock_hide;
+guint config_dock_hide_delay;
+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;
+
+gint config_mouse_threshold;
+gint config_mouse_dclicktime;
+gint config_mouse_screenedgetime;
+
+guint config_menu_hide_delay;
+gboolean config_menu_middle;
+guint config_submenu_show_delay;
+guint config_submenu_hide_delay;
+gboolean config_menu_manage_desktops;
+gboolean config_menu_show_icons;
+
+GSList *config_menu_files;
+
+gint config_resist_win;
+gint config_resist_edge;
+
+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;
+ settings->focus = -1;
+ settings->desktop = 0;
+ settings->layer = -2;
+ settings->iconic = -1;
+ settings->skip_pager = -1;
+ settings->skip_taskbar = -1;
+ settings->fullscreen = -1;
+ settings->max_horz = -1;
+ settings->max_vert = -1;
+ return settings;
+}
+
+#define copy_if(setting, default) \
+ if (src->setting != default) dst->setting = src->setting
+void config_app_settings_copy_non_defaults(const ObAppSettings *src,
+ ObAppSettings *dst)
+{
+ g_assert(src != NULL);
+ g_assert(dst != NULL);
+
+ copy_if(type, (ObClientType)-1);
+ copy_if(decor, -1);
+ copy_if(shade, -1);
+ copy_if(monitor, -1);
+ copy_if(focus, -1);
+ copy_if(desktop, 0);
+ copy_if(layer, -2);
+ copy_if(iconic, -1);
+ copy_if(skip_pager, -1);
+ copy_if(skip_taskbar, -1);
+ copy_if(fullscreen, -1);
+ copy_if(max_horz, -1);
+ copy_if(max_vert, -1);
+
+ if (src->pos_given) {
+ dst->pos_given = TRUE;
+ dst->pos_force = src->pos_force;
+ dst->position = src->position;
+ /* monitor is copied above */
+ }
+}
+
+static 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 {
+ if (s[0] == '-')
+ c->opposite = TRUE;
+ if (s[0] == '-' || s[0] == '+')
+ c->pos = atoi(s+1);
+ else
+ c->pos = atoi(s);
+ }
+ g_free(s);
+}
+
+/*
+ <applications>
+ <application name="aterm">
+ <decor>false</decor>
+ </application>
+ <application name="Rhythmbox">
+ <layer>above</layer>
+ <position>
+ <x>700</x>
+ <y>0</y>
+ <monitor>1</monitor>
+ </position>
+ .. there is a lot more settings available
+ </application>
+ </applications>
+*/
+
+/* 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.
+ 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
+ center the window in the specified axis. Position is within
+ the monitor, so <position><x>center</x></position><monitor>2</monitor>
+ will center the window on the second monitor.
+*/
+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, *title = NULL,
+ *type_str = NULL;
+ gboolean name_set, class_set, type_set, role_set, title_set;
+ ObClientType type;
+ gboolean x_pos_given;
+
+ while (app) {
+ x_pos_given = FALSE;
+
+ class_set = obt_xml_attr_string(app, "class", &class);
+ name_set = obt_xml_attr_string(app, "name", &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) {
+ if (!g_ascii_strcasecmp(type_str, "normal"))
+ type = OB_CLIENT_TYPE_NORMAL;
+ else if (!g_ascii_strcasecmp(type_str, "dialog"))
+ type = OB_CLIENT_TYPE_DIALOG;
+ else if (!g_ascii_strcasecmp(type_str, "splash"))
+ type = OB_CLIENT_TYPE_SPLASH;
+ else if (!g_ascii_strcasecmp(type_str, "utility"))
+ type = OB_CLIENT_TYPE_UTILITY;
+ else if (!g_ascii_strcasecmp(type_str, "menu"))
+ type = OB_CLIENT_TYPE_MENU;
+ else if (!g_ascii_strcasecmp(type_str, "toolbar"))
+ type = OB_CLIENT_TYPE_TOOLBAR;
+ else if (!g_ascii_strcasecmp(type_str, "dock"))
+ type = OB_CLIENT_TYPE_DOCK;
+ else if (!g_ascii_strcasecmp(type_str, "desktop"))
+ type = OB_CLIENT_TYPE_DESKTOP;
+ else
+ type_set = FALSE; /* not valid! */
+ }
+
+ if (class_set || name_set || role_set || title_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 (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 ((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);
+ g_free(title);
+ name = class = role = title = NULL;
+ }
+
+ app = obt_xml_find_node(app->next, "application");
+ }
+}
+
+/*
+
+<keybind key="C-x">
+ <action name="ChangeDesktop">
+ <desktop>3</desktop>
+ </action>
+</keybind>
+
+*/
+
+static void parse_key(xmlNodePtr node, GList *keylist)
+{
+ gchar *key;
+ xmlNodePtr n;
+ gboolean is_chroot = FALSE;
+
+ if (!obt_xml_attr_string(node, "key", &key))
+ return;
+
+ obt_xml_attr_bool(node, "chroot", &is_chroot);
+
+ 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");
+ }
+ }
+ 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");
+ }
+ }
+
+ if (is_chroot)
+ keyboard_chroot(keylist);
+
+ g_free(key);
+ keylist = g_list_delete_link(keylist, g_list_last(keylist));
+}
+
+static void parse_keyboard(xmlNodePtr node, gpointer d)
+{
+ xmlNodePtr n;
+ gchar *key;
+
+ keyboard_unbind_all();
+
+ if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
+ key = obt_xml_node_string(n);
+ translate_key(key, &config_keyboard_reset_state,
+ &config_keyboard_reset_keycode);
+ g_free(key);
+ }
+
+ if ((n = obt_xml_find_node(node->children, "keybind")))
+ while (n) {
+ parse_key(n, NULL);
+ n = obt_xml_find_node(n->next, "keybind");
+ }
+}
+
+/*
+
+<context name="Titlebar">
+ <mousebind button="Left" action="Press">
+ <action name="Raise"></action>
+ </mousebind>
+</context>
+
+*/
+
+static void parse_mouse(xmlNodePtr node, gpointer d)
+{
+ xmlNodePtr n, nbut, nact;
+ gchar *buttonstr;
+ gchar *contextstr;
+ ObMouseAction mact;
+
+ mouse_unbind_all();
+
+ node = node->children;
+
+ if ((n = obt_xml_find_node(node, "dragThreshold")))
+ config_mouse_threshold = obt_xml_node_int(n);
+ if ((n = obt_xml_find_node(node, "doubleClickTime")))
+ config_mouse_dclicktime = obt_xml_node_int(n);
+ if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
+ config_mouse_screenedgetime = obt_xml_node_int(n);
+ /* minimum value of 25 for this property, when it is 1 and you hit the
+ edge it basically never stops */
+ if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
+ config_mouse_screenedgetime = 25;
+ }