X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=c54b21fba3e0a135e3b50a1c60ff61913af30273;hb=dc4cfa94c9cd7bd30cdc87a6e4ab8174d8a9703f;hp=35b146eb93415f94f0e7b49d3425b6b202d3c141;hpb=385967b55290105f074080890d55b50d9622b89d;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 35b146eb..c54b21fb 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -112,6 +112,8 @@ static gboolean client_can_steal_focus(ObClient *self, gboolean allow_other_desktop, gboolean request_from_user, Time steal_time, Time launch_time); +static void client_setup_default_decor_and_functions(ObClient *self); +static void client_setup_decor_undecorated(ObClient *self); void client_startup(gboolean reconfig) { @@ -165,6 +167,21 @@ void client_remove_destroy_notify(ObClientCallback func) } } +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; @@ -201,6 +218,7 @@ void client_manage(Window window, ObPrompt *prompt) Time launch_time; guint32 user_time; gboolean obplaced; + gulong ignore_start; ob_debug("Managing window: 0x%lx", window); @@ -238,6 +256,18 @@ void client_manage(Window window, ObPrompt *prompt) that needs to be freed with g_free(). */ settings = client_get_settings_state(self); + /* the session should get the last say though */ + client_restore_session_state(self); + + /* the per-app settings/session may have changed the decorations for + the window, so we setup decorations for that here. this is a special + case because we want to place the window according to these decoration + changes. + we do this before setting up the frame so that it will reflect the + decorations of the window as it will be placed on screen. + */ + client_setup_decor_undecorated(self); + /* specify that if we exit, the window should not be destroyed and should be reparented back to root automatically, unless we are managing an internal ObPrompt window */ @@ -253,8 +283,18 @@ void client_manage(Window window, ObPrompt *prompt) time now */ grab_server(FALSE); - /* the session should get the last say though */ - client_restore_session_state(self); + /* this needs to occur once we have a frame, since it sets a property on + the frame */ + client_update_opacity(self); + + /* don't put helper/modal windows on a different desktop if they are + related to the focused window. */ + if (!screen_compare_desktops(self->desktop, screen_desktop) && + focus_client && client_search_transient(focus_client, self) && + (client_helper(self) || self->modal)) + { + self->desktop = screen_desktop; + } /* tell startup notification that this app started */ launch_time = sn_app_started(self->startup_id, self->class, self->name); @@ -303,9 +343,10 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Going to try activate new window? %s", try_activate ? "yes" : "no"); if (try_activate) - do_activate = client_can_steal_focus(self, settings->focus, - !!launch_time, - event_time(), launch_time); + do_activate = client_can_steal_focus( + self, settings->focus == 1, + (!!launch_time || settings->focus == 1), + event_time(), launch_time); else do_activate = FALSE; @@ -436,22 +477,20 @@ void client_manage(Window window, ObPrompt *prompt) client_apply_startup_state(self, place.x, place.y, place.width, place.height); + /* set the initial value of the desktop hint, when one wasn't requested + on map. */ + OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop); + /* 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) { @@ -479,6 +518,9 @@ void client_manage(Window window, ObPrompt *prompt) 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)); @@ -712,9 +754,13 @@ static gboolean client_can_steal_focus(ObClient *self, /* This is focus stealing prevention */ ob_debug("Want to focus window 0x%x at time %u " "launched at %u (last user interaction time %u) " - "request from %s", + "request from %s, allow other desktop: %s, " + "desktop switch time %u", self->window, steal_time, launch_time, - event_last_user_time, (request_from_user ? "user" : "other")); + event_last_user_time, + (request_from_user ? "user" : "other"), + (allow_other_desktop ? "yes" : "no"), + screen_desktop_user_time); /* if no launch time is provided for an application, make one up. @@ -770,18 +816,24 @@ static gboolean client_can_steal_focus(ObClient *self, } /* if it's on another desktop - then if allow_other_desktop is true, we don't want to let it steal + and if allow_other_desktop is true, we generally let it steal focus. + but if it didn't come from the user, don't let it steal unless it was + launched before the user switched desktops. focus, unless it was launched after we changed desktops and the request came from the user */ - if (!(self->desktop == screen_desktop || - self->desktop == DESKTOP_ALL) && - (!allow_other_desktop || - (request_from_user && screen_desktop_user_time && - !event_time_after(launch_time, screen_desktop_user_time)))) - { - steal = FALSE; - ob_debug("Not focusing the window because its on another desktop\n"); + if (!screen_compare_desktops(screen_desktop, self->desktop)) { + /* must be allowed */ + if (!allow_other_desktop) { + steal = FALSE; + ob_debug("Not focusing the window because its on another desktop"); + } + /* if we don't know when the desktop changed, but request is from an + application, don't let it change desktop on you */ + else if (!request_from_user) { + steal = FALSE; + ob_debug("Not focusing the window because non-user request"); + } } /* If something is focused... */ else if (focus_client) { @@ -826,7 +878,8 @@ static gboolean client_can_steal_focus(ObClient *self, } /* Don't move focus if the window is not visible on the current desktop and none of its relatives are focused */ - else if (!screen_compare_desktops(self->desktop, screen_desktop) && + else if (!allow_other_desktop && + !screen_compare_desktops(self->desktop, screen_desktop) && !relative_focused) { steal = FALSE; @@ -1148,11 +1201,8 @@ static void client_get_all(ObClient *self, gboolean real) client_get_type_and_transientness(self); client_update_normal_hints(self); - /* set up the decor/functions before getting the state. the states may - affect which functions are available, but we want to know the maximum - decor/functions are available to this window, so we can then apply them - in client_apply_startup_state() */ - client_setup_decor_and_functions(self, FALSE); + /* set up the maximum possible decor/functions */ + client_setup_default_decor_and_functions(self); client_get_state(self); @@ -1640,6 +1690,16 @@ void client_update_colormap(ObClient *self, Colormap colormap) self->colormap = colormap; } +void client_update_opacity(ObClient *self) +{ + guint32 o; + + if (OBT_PROP_GET32(self->window, NET_WM_WINDOW_OPACITY, CARDINAL, &o)) + OBT_PROP_SET32(self->frame->window, NET_WM_WINDOW_OPACITY, CARDINAL, o); + else + OBT_PROP_ERASE(self->frame->window, NET_WM_WINDOW_OPACITY); +} + void client_update_normal_hints(ObClient *self) { XSizeHints size; @@ -1696,7 +1756,7 @@ void client_update_normal_hints(ObClient *self) ob_debug("Normal hints: not set"); } -void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) +static void client_setup_default_decor_and_functions(ObClient *self) { /* start with everything (cept fullscreen) */ self->decorations = @@ -1829,6 +1889,23 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) self->functions &= ~OB_CLIENT_FUNC_MAXIMIZE; self->decorations &= ~OB_FRAME_DECOR_MAXIMIZE; } +} + +/*! Set up decor for a client based on its undecorated state. */ +static void client_setup_decor_undecorated(ObClient *self) +{ + /* If the user requested no decorations, then remove all the decorations, + except the border. But don't add a border if there wasn't one. */ + if (self->undecorated) + self->decorations &= (config_theme_keepborder ? + OB_FRAME_DECOR_BORDER : 0); +} + +void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) +{ + client_setup_default_decor_and_functions(self); + + client_setup_decor_undecorated(self); if (self->max_horz && self->max_vert) { /* once upon a time you couldn't resize maximized windows, that is not @@ -1838,12 +1915,6 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS); } - /* finally, the user can have requested no decorations, which overrides - everything (but doesnt give it a border if it doesnt have one) */ - if (self->undecorated) - self->decorations &= (config_theme_keepborder ? - OB_FRAME_DECOR_BORDER : 0); - /* if we don't have a titlebar, then we cannot shade! */ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) self->functions &= ~OB_CLIENT_FUNC_SHADE; @@ -2703,6 +2774,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 || @@ -2775,6 +2852,9 @@ static void client_apply_startup_state(ObClient *self, if (fullscreen) client_fullscreen(self, TRUE); + /* make sure client_setup_decor_and_functions() is called at least once */ + client_setup_decor_and_functions(self, FALSE); + /* 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 @@ -2788,9 +2868,6 @@ static void client_apply_startup_state(ObClient *self, self->area = oldarea; client_configure(self, x, y, w, h, FALSE, TRUE, FALSE); - /* set the desktop hint, to make sure that it always exists */ - OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop); - /* nothing to do for the other states: skip_taskbar skip_pager @@ -2870,6 +2947,14 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, the updated frame dimensions. */ frame_adjust_area(self->frame, FALSE, TRUE, TRUE); + /* cap any X windows at the size of an unsigned short */ + *w = MIN(*w, + (gint)G_MAXUSHORT + - self->frame->size.left - self->frame->size.right); + *h = MIN(*h, + (gint)G_MAXUSHORT + - self->frame->size.top - self->frame->size.bottom); + /* gets the frame's position */ frame_client_gravity(self->frame, x, y); @@ -3908,6 +3993,9 @@ gboolean client_focus(ObClient *self) return FALSE; } + /* if we have helper windows they should be there with the window */ + client_bring_helper_windows(self); + ob_debug_type(OB_DEBUG_FOCUS, "Focusing client \"%s\" (0x%x) at time %u", self->title, self->window, event_time()); @@ -4000,7 +4088,7 @@ static void client_bring_windows_recursive(ObClient *self, if (((helpers && client_helper(self)) || (modals && self->modal)) && - ((self->desktop != desktop && self->desktop != DESKTOP_ALL) || + (!screen_compare_desktops(self->desktop, desktop) || (iconic && self->iconic))) { if (iconic && self->iconic) @@ -4314,32 +4402,26 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, } /* search for edges of clients */ - if (((dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH) && - !self->max_vert) || - ((dir == OB_DIRECTION_EAST || dir == OB_DIRECTION_WEST) && - !self->max_horz)) - { - for (it = client_list; it; it = g_list_next(it)) { - ObClient *cur = it->data; + for (it = client_list; it; it = g_list_next(it)) { + ObClient *cur = it->data; - /* skip windows to not bump into */ - if (cur == self) - continue; - if (cur->iconic) - continue; - if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL && - cur->desktop != screen_desktop) - continue; + /* skip windows to not bump into */ + if (cur == self) + continue; + if (cur->iconic) + continue; + if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL && + cur->desktop != screen_desktop) + continue; - ob_debug("trying window %s", cur->title); + ob_debug("trying window %s", cur->title); - detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start, - my_edge_size, dest, near_edge); - } - dock_get_area(&dock_area); - detect_edge(dock_area, dir, my_head, my_size, my_edge_start, + detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start, my_edge_size, dest, near_edge); } + dock_get_area(&dock_area); + detect_edge(dock_area, dir, my_head, my_size, my_edge_start, + my_edge_size, dest, near_edge); g_slice_free(Rect, a); }