From: Charles McGarvey Date: Fri, 26 Oct 2012 19:03:24 +0000 (-0600) Subject: Merge branch 'master' into chaz X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fopenbox;a=commitdiff_plain;h=9325c92056ff4268db2263cdf8c07bb529e158aa;hp=-c Merge branch 'master' into chaz Conflicts: openbox/config.c --- 9325c92056ff4268db2263cdf8c07bb529e158aa diff --combined data/rc.xml index 70ad9bf9,932521b7..ce1e8fc1 --- a/data/rc.xml +++ b/data/rc.xml @@@ -33,9 -33,6 +33,6 @@@ Smart -
yes
- Primary yes yes + 600 + 5000 sans 8 @@@ -636,10 -631,10 +633,10 @@@ submenu will not be shown until it is clicked on --> 400 + entry in parent menu if this is a negative value, then the delay is infinite and the submenu will not be hidden until a different submenu is opened --> - yes + yes yes @@@ -654,6 -649,8 +651,8 @@@ - - + @@@ -92,8 -91,6 +91,8 @@@ + + @@@ -236,11 -233,18 +235,18 @@@ + + + + + + + @@@ -249,7 -253,6 +255,7 @@@ + @@@ -396,7 -399,8 +402,8 @@@ - + + @@@ -421,7 -425,12 +428,12 @@@ - + + + + + + @@@ -528,7 -537,7 +540,7 @@@ - + diff --combined openbox/client.c index 46162c31,b6cc4a87..1478d840 --- a/openbox/client.c +++ b/openbox/client.c @@@ -167,6 -167,21 +167,21 @@@ void client_remove_destroy_notify(ObCli } } + void client_remove_destroy_notify_data(ObClientCallback func, gpointer data) + { + GSList *it; + + for (it = client_destroy_notifies; it; it = g_slist_next(it)) { + ClientCallback *d = it->data; + if (d->func == func && d->data == data) { + g_slice_free(ClientCallback, d); + client_destroy_notifies = + g_slist_delete_link(client_destroy_notifies, it); + break; + } + } + } + void client_set_list(void) { Window *windows, *win_it; @@@ -203,6 -218,7 +218,7 @@@ void client_manage(Window window, ObPro Time launch_time; guint32 user_time; gboolean obplaced; + gulong ignore_start; ob_debug("Managing window: 0x%lx", window); @@@ -234,6 -250,8 +250,8 @@@ ob_debug("Window group: 0x%x", self->group?self->group->leader:0); ob_debug("Window name: %s class: %s role: %s title: %s", self->name, self->class, self->role, self->title); + ob_debug("Window group name: %s group class: %s", + self->group_name, self->group_class); /* per-app settings override stuff from client_get_all, and return the settings for other uses too. the returned settings is a shallow copy, @@@ -352,8 -370,7 +370,7 @@@ "program + user specified" : "BADNESS !?")))), place.width, place.height); - obplaced = place_client(self, do_activate, &place.x, &place.y, - settings); + obplaced = place_client(self, do_activate, &place, settings); /* watch for buggy apps that ask to be placed at (0,0) when there is a strut there */ @@@ -468,19 -485,13 +485,13 @@@ /* grab mouse bindings before showing the window */ mouse_grab_for_client(self, TRUE); + if (!config_focus_under_mouse) + ignore_start = event_start_ignore_all_enters(); + /* this has to happen before we try focus the window, but we want it to happen after the client's stacking has been determined or it looks bad */ - { - gulong ignore_start; - if (!config_focus_under_mouse) - ignore_start = event_start_ignore_all_enters(); - - client_show(self); - - if (!config_focus_under_mouse) - event_end_ignore_all_enters(ignore_start); - } + client_show(self); /* activate/hilight/raise the window */ if (try_activate) { @@@ -508,6 -519,9 +519,9 @@@ stacking_raise(CLIENT_AS_WINDOW(self)); } + if (!config_focus_under_mouse) + event_end_ignore_all_enters(ignore_start); + /* add to client list/map */ client_list = g_list_append(client_list, self); window_add(&self->window, CLIENT_AS_WINDOW(self)); @@@ -710,6 -724,8 +724,8 @@@ void client_unmanage(ObClient *self g_free(self->name); g_free(self->class); g_free(self->role); + g_free(self->group_name); + g_free(self->group_class); g_free(self->client_machine); g_free(self->sm_client_id); g_slice_free(ObClient, self); @@@ -902,15 -918,25 +918,25 @@@ static ObAppSettings *client_get_settin g_assert(app->name != NULL || app->class != NULL || app->role != NULL || app->title != NULL || + app->group_name != NULL || app->group_class != NULL || (signed)app->type >= 0); if (app->name && !g_pattern_match(app->name, strlen(self->name), self->name, NULL)) match = FALSE; + else if (app->group_name && + !g_pattern_match(app->group_name, + strlen(self->group_name), self->group_name, NULL)) + match = FALSE; else if (app->class && !g_pattern_match(app->class, strlen(self->class), self->class, NULL)) match = FALSE; + else if (app->group_class && + !g_pattern_match(app->group_class, + strlen(self->group_class), self->group_class, + NULL)) + match = FALSE; else if (app->role && !g_pattern_match(app->role, strlen(self->role), self->role, NULL)) @@@ -959,9 -985,6 +985,9 @@@ self->desktop = settings->desktop - 1; } + if (settings->opacity != -1) + self->opacity = settings->opacity; + if (settings->layer == -1) { self->below = TRUE; self->above = FALSE; @@@ -1020,8 -1043,6 +1046,8 @@@ static void client_restore_session_stat self->max_horz = self->session->max_horz; self->max_vert = self->session->max_vert; self->undecorated = self->session->undecorated; + + self->opacity = self->session->opacity; } static gboolean client_restore_session_stacking(ObClient *self) @@@ -1202,13 -1223,15 +1228,15 @@@ static void client_get_all(ObClient *se from per-app settings */ client_get_session_ids(self); - /* now we got everything that can affect the decorations */ + /* get this early so we have it for debugging, also this can be used + by app rule matching */ + client_update_title(self); + + /* now we got everything that can affect the decorations or app rule + matching */ if (!real) return; - /* get this early so we have it for debugging */ - client_update_title(self); - /* save the values of the variables used for app rule matching */ client_save_app_rule_values(self); @@@ -2357,6 -2380,25 +2385,25 @@@ static void client_get_session_ids(ObCl if (self->name == NULL) self->name = g_strdup(""); if (self->class == NULL) self->class = g_strdup(""); + /* get the WM_CLASS (name and class) from the group leader. make them "" if + they are not provided */ + if (leader) + got = OBT_PROP_GETSS_TYPE(leader, WM_CLASS, STRING_NO_CC, &ss); + else + got = FALSE; + + if (got) { + if (ss[0]) { + self->group_name = g_strdup(ss[0]); + if (ss[1]) + self->group_class = g_strdup(ss[1]); + } + g_strfreev(ss); + } + + if (self->group_name == NULL) self->group_name = g_strdup(""); + if (self->group_class == NULL) self->group_class = g_strdup(""); + /* get the WM_WINDOW_ROLE. make it "" if it is not provided */ got = OBT_PROP_GETS_XPCS(self->window, WM_WINDOW_ROLE, &s); @@@ -2426,6 -2468,8 +2473,8 @@@ static void client_save_app_rule_values OBT_PROP_SETS(self->window, OB_APP_ROLE, self->role); OBT_PROP_SETS(self->window, OB_APP_NAME, self->name); OBT_PROP_SETS(self->window, OB_APP_CLASS, self->class); + OBT_PROP_SETS(self->window, OB_APP_GROUP_NAME, self->group_name); + OBT_PROP_SETS(self->window, OB_APP_GROUP_CLASS, self->group_class); OBT_PROP_SETS(self->window, OB_APP_TITLE, self->original_title); switch (self->type) { @@@ -2766,6 -2810,12 +2815,12 @@@ gboolean client_helper(ObClient *self self->type == OB_CLIENT_TYPE_TOOLBAR); } + gboolean client_occupies_space(ObClient *self) + { + return !(self->type == OB_CLIENT_TYPE_DESKTOP || + self->type == OB_CLIENT_TYPE_SPLASH); + } + gboolean client_mouse_focusable(ObClient *self) { return !(self->type == OB_CLIENT_TYPE_MENU || @@@ -2792,7 -2842,6 +2847,7 @@@ static void client_apply_startup_state( gboolean demands_attention = self->demands_attention; gboolean max_horz = self->max_horz; gboolean max_vert = self->max_vert; + guint8 opacity = self->opacity; Rect oldarea; gint l; @@@ -2842,9 -2891,6 +2897,9 @@@ /* make sure client_setup_decor_and_functions() is called at least once */ client_setup_decor_and_functions(self, FALSE); + /* make the client semi-transparent */ + client_set_opacity(self, opacity); + /* if the window hasn't been configured yet, then do so now, in fact the x,y,w,h may _not_ be the same as the area rect, which can end up meaning that the client isn't properly moved/resized by the fullscreen @@@ -3733,12 -3779,6 +3788,12 @@@ void client_set_desktop(ObClient *self focus_cycle_addremove(NULL, TRUE); } +void client_set_opacity(ObClient *self, guint8 opacity) +{ + OBT_PROP_SET32(self->window, NET_WM_WINDOW_OPACITY, CARDINAL, + opacity * 16777216); +} + gboolean client_is_direct_child(ObClient *parent, ObClient *child) { while (child != parent && (child = client_direct_parent(child))); diff --combined openbox/client.h index 99fdfd05,d68d3035..a946f274 --- a/openbox/client.h +++ b/openbox/client.h @@@ -127,6 -127,10 +127,10 @@@ struct _ObClien gchar *class; /*! The specified role of the window, used for identification */ gchar *role; + /*! The application that created the window's group. */ + gchar *group_name; + /*! The class of the window's group, can used for grouping */ + gchar *group_class; /*! The session client id for the window. *This can be NULL!* */ gchar *sm_client_id; @@@ -264,8 -268,6 +268,8 @@@ gboolean max_vert; /*! The window is maximized to fill the screen horizontally */ gboolean max_horz; + /*! The window is semi-transparent */ + guint8 opacity; /*! The window should not be displayed by pagers */ gboolean skip_pager; /*! The window should not be displayed by taskbars */ @@@ -328,6 -330,7 +332,7 @@@ typedef void (*ObClientCallback)(ObClie /*! Get notified when the client is unmanaged */ void client_add_destroy_notify(ObClientCallback func, gpointer data); void client_remove_destroy_notify(ObClientCallback func); + void client_remove_destroy_notify_data(ObClientCallback func, gpointer data); /*! Manages a given window @param prompt This specifies an ObPrompt which is being managed. It is @@@ -364,6 -367,10 +369,10 @@@ gboolean client_normal(ObClient *self) (utilty, menu, etc) */ gboolean client_helper(ObClient *self); + /*! Returns true if the window occupies space in the monitor conceptually, or + false if it does not and its presence should be ignored when possible. */ + gboolean client_occupies_space(ObClient *self); + /*! Return if the client is a type which should be given focus from mouse presses on the *client* window. This doesn't affect clicking on the decorations. This doesn't count for focus cycling, different rules apply to @@@ -495,7 -502,7 +504,7 @@@ void client_fullscreen(ObClient *self, /*! Determine if the window, using the given client-area, would be considered as an "oldschool fullscreen" window, that is, if it is filling a whole monitor. */ - gboolean client_is_oldfullscreen(const ObClient const *self, const Rect *area); + gboolean client_is_oldfullscreen(const ObClient *self, const Rect *area); /*! Iconifies or uniconifies the client window @param iconic true if the window should be iconified; false if it should be @@@ -541,9 -548,6 +550,9 @@@ void client_kill(ObClient *self) void client_set_desktop(ObClient *self, guint target, gboolean donthide, gboolean dontraise); +/*! Adjust the client opacity */ +void client_set_opacity(ObClient *self, guint8 opacity); + /*! Show the client if it should be shown. Returns if the window is shown. */ gboolean client_show(ObClient *self); diff --combined openbox/config.c index f0f6c7b3,03fc96b3..c21b47d8 --- a/openbox/config.c +++ b/openbox/config.c @@@ -37,7 -37,6 +37,6 @@@ gboolean config_focus_under_mouse gboolean config_unfocus_leave; ObPlacePolicy config_place_policy; - gboolean config_place_center; ObPlaceMonitor config_place_monitor; guint config_primary_monitor_index; @@@ -48,8 -47,6 +47,8 @@@ StrutPartial config_margins gchar *config_theme; gboolean config_theme_keepborder; guint config_theme_window_list_icon_size; +guint config_frame_flash_delay; +guint config_frame_flash_duration; gchar *config_title_layout; @@@ -124,7 -121,6 +123,7 @@@ ObAppSettings* config_create_app_settin settings->fullscreen = -1; settings->max_horz = -1; settings->max_vert = -1; + settings->opacity = -1; return settings; } @@@ -150,7 -146,6 +149,7 @@@ void config_app_settings_copy_non_defau copy_if(fullscreen, -1); copy_if(max_horz, -1); copy_if(max_vert, -1); + copy_if(opacity, -1); if (src->pos_given) { dst->pos_given = TRUE; @@@ -158,6 -153,14 +157,14 @@@ dst->position = src->position; /* monitor is copied above */ } + + if (src->size_given) { + dst->size_given = TRUE; + 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) @@@ -204,6 -207,144 +211,148 @@@ void config_parse_gravity_coord(xmlNode */ + static void parse_single_per_app_settings(xmlNodePtr app, + ObAppSettings *settings) + { + xmlNodePtr n, c; + gboolean x_pos_given = FALSE; + gboolean width_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) + width_given = TRUE; + g_free(s); + } + } + + if (width_given && (c = obt_xml_find_node(n->children, "height"))) { + 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->size_given = TRUE; + 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); + } + } ++ ++ if ((n = obt_xml_find_node(app->children, "opacity"))) ++ if (!obt_xml_node_contains(n, "default")) ++ settings->opacity = obt_xml_node_int(n); + } + /* Manages settings for individual applications. Some notes: monitor is the screen number in a multi monitor (Xinerama) setup (starting from 0), or mouse: the monitor the pointer @@@ -218,17 -359,19 +367,19 @@@ 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; + 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); @@@ -255,143 -398,38 +406,38 @@@ 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; - } - - /* 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, "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 (!(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 ((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); - } - - if ((n = obt_xml_find_node(app->children, "opacity"))) - if (!obt_xml_node_contains(n, "default")) - settings->opacity = obt_xml_node_int(n); - - 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); - g_free(type_str); - name = class = role = title = type_str = 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); } } @@@ -592,8 -630,6 +638,6 @@@ static void parse_placement(xmlNodePtr 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"))) - 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; @@@ -663,10 -699,6 +707,10 @@@ static void parse_theme(xmlNodePtr node else if (config_theme_window_list_icon_size > 96) config_theme_window_list_icon_size = 96; } + if ((n = obt_xml_find_node(node, "flashFrameDelay"))) + config_frame_flash_delay = obt_xml_node_int(n); + if ((n = obt_xml_find_node(node, "flashFrameDuration"))) + config_frame_flash_duration = obt_xml_node_int(n); n = obt_xml_find_node(node, "font"); while (n) { @@@ -1025,7 -1057,6 +1069,6 @@@ void config_startup(ObtXmlInst *i obt_xml_register(i, "focus", parse_focus, NULL); config_place_policy = OB_PLACE_POLICY_SMART; - config_place_center = TRUE; config_place_monitor = OB_PLACE_MONITOR_PRIMARY; config_primary_monitor_index = 1; @@@ -1043,8 -1074,6 +1086,8 @@@ config_title_layout = g_strdup("NLIMC"); config_theme_keepborder = TRUE; config_theme_window_list_icon_size = 36; + config_frame_flash_delay = 600; + config_frame_flash_duration = 5000; config_font_activewindow = NULL; config_font_inactivewindow = NULL; @@@ -1146,10 -1175,12 +1189,12 @@@ 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); + 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); diff --combined openbox/config.h index beb54be4,87662ab9..c09a1f4f --- a/openbox/config.h +++ b/openbox/config.h @@@ -38,6 -38,8 +38,8 @@@ struct _ObAppSetting GPatternSpec *class; GPatternSpec *name; GPatternSpec *role; + GPatternSpec *group_class; + GPatternSpec *group_name; GPatternSpec *title; ObClientType type; @@@ -45,6 -47,12 +47,12 @@@ gboolean pos_given; gboolean pos_force; + gint width_num; + gint width_denom; + gint height_num; + gint height_denom; + gboolean size_given; + guint desktop; gint shade; gint decor; @@@ -57,9 -65,8 +65,9 @@@ gint max_horz; gint max_vert; gint fullscreen; - gint layer; + + guint8 opacity; }; /*! Should new windows be focused */ @@@ -82,8 -89,6 +90,6 @@@ extern gboolean config_unfocus_leave /*! The algorithm to use for placing new windows */ extern ObPlacePolicy config_place_policy; - /*! Place windows in the center of the free area */ - extern gboolean config_place_center; /*! Place windows on the active monitor (unless they are part of an application already on another monitor) */ extern ObPlaceMonitor config_place_monitor; @@@ -146,10 -151,6 +152,10 @@@ extern gchar *config_title_layout extern gboolean config_animate_iconify; /*! Size of icons in focus switching dialogs */ extern guint config_theme_window_list_icon_size; +/*! Amount of time between flashes (0 to disable flashing) */ +extern guint config_frame_flash_delay; +/*! How long (ms) to flash the window's frame (0 to flash forever) */ +extern guint config_frame_flash_duration; /*! The font for the active window's title */ extern RrFont *config_font_activewindow; diff --combined openbox/frame.c index 4468e191,24d3eb53..0f2d56eb --- a/openbox/frame.c +++ b/openbox/frame.c @@@ -378,13 -378,22 +378,22 @@@ void frame_adjust_area(ObFrame *self, g STRUT_SET(self->size, self->cbwidth_l + (!self->max_horz ? self->bwidth : 0), - self->cbwidth_t + self->bwidth, + self->cbwidth_t + + (!self->max_horz || !self->max_vert ? self->bwidth : 0), self->cbwidth_r + (!self->max_horz ? self->bwidth : 0), self->cbwidth_b + (!self->max_horz || !self->max_vert ? self->bwidth : 0)); if (self->decorations & OB_FRAME_DECOR_TITLEBAR) self->size.top += ob_rr_theme->title_height + self->bwidth; + else if (self->max_horz && self->max_vert) { + /* A maximized and undecorated window needs a small border on the + top of the window to let the user still undecorate/unmaximize the + window via the client menu. */ + /* XXX This size should probably be a theme option. */ + self->size.top += 1; + } + if (self->decorations & OB_FRAME_DECOR_HANDLE && ob_rr_theme->handle_height > 0) { @@@ -1665,13 -1674,11 +1674,13 @@@ static gboolean flash_timeout(gpointer ObFrame *self = data; GTimeVal now; - g_get_current_time(&now); - if (now.tv_sec > self->flash_end.tv_sec || - (now.tv_sec == self->flash_end.tv_sec && - now.tv_usec >= self->flash_end.tv_usec)) - self->flashing = FALSE; + if (config_frame_flash_duration != 0) { + g_get_current_time(&now); + if (now.tv_sec > self->flash_end.tv_sec || + (now.tv_sec == self->flash_end.tv_sec && + now.tv_usec >= self->flash_end.tv_usec)) + self->flashing = FALSE; + } if (!self->flashing) return FALSE; /* we are done */ @@@ -1687,19 -1694,14 +1696,19 @@@ void frame_flash_start(ObFrame *self) { + if (config_frame_flash_delay == 0) return; + self->flash_on = self->focused; if (!self->flashing) self->flash_timer = g_timeout_add_full(G_PRIORITY_DEFAULT, - 600, flash_timeout, self, + config_frame_flash_delay, flash_timeout, self, flash_done); - g_get_current_time(&self->flash_end); - g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5); + + if (config_frame_flash_duration != 0) { + g_get_current_time(&self->flash_end); + g_time_val_add(&self->flash_end, 1000 * config_frame_flash_duration); + } self->flashing = TRUE; } diff --combined openbox/moveresize.c index d700da9e,1625ccf0..ffed9093 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@@ -583,16 -583,16 +583,16 @@@ static void edge_warp_move_ptr(void switch (edge_warp_dir) { case OB_DIRECTION_NORTH: - y = a->height - 1; + y = a->height - 2; break; case OB_DIRECTION_EAST: - x = a->x; + x = a->x + 1; break; case OB_DIRECTION_SOUTH: - y = a->y; + y = a->y + 1; break; case OB_DIRECTION_WEST: - x = a->width - 1; + x = a->width - 2; break; default: g_assert_not_reached(); @@@ -630,6 -630,10 +630,10 @@@ static void do_edge_warp(gint x, gint y for (i = 0; i < screen_num_monitors; ++i) { const Rect *a = screen_physical_area_monitor(i); + + if (!RECT_CONTAINS(*a, x, y)) + continue; + if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST; if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST; if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;