X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=4ac234d73315a9d3137078f70c0643e3a99f4249;hb=8fe0cb8989c1fe12b30b9030b446345f25340d35;hp=c7c9a548de6a3f666c92c474961d08cef34334af;hpb=9d42df6ab4099c9365d3631ea86348a8f21752a0;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index c7c9a548..4ac234d7 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1,8 +1,8 @@ -#include "debug.h" #include "client.h" +#include "debug.h" +#include "startupnotify.h" #include "dock.h" #include "xerror.h" -#include "startup.h" #include "screen.h" #include "moveresize.h" #include "place.h" @@ -37,6 +37,7 @@ GSList *client_destructors = NULL; static void client_get_all(ObClient *self); static void client_toggle_border(ObClient *self, gboolean show); +static void client_get_startup_id(ObClient *self); static void client_get_area(ObClient *self); static void client_get_desktop(ObClient *self); static void client_get_state(ObClient *self); @@ -49,23 +50,25 @@ static void client_change_state(ObClient *self); static void client_apply_startup_state(ObClient *self); static void client_restore_session_state(ObClient *self); static void client_restore_session_stacking(ObClient *self); -static void client_act_urgent(ObClient *self); +static void client_urgent_notify(ObClient *self); -void client_startup() +void client_startup(gboolean reconfig) { + if (reconfig) return; + client_set_list(); } -void client_shutdown() +void client_shutdown(gboolean reconfig) { } -void client_add_destructor(ObClientDestructorFunc func) +void client_add_destructor(GDestroyNotify func) { client_destructors = g_slist_prepend(client_destructors, (gpointer)func); } -void client_remove_destructor(ObClientDestructorFunc func) +void client_remove_destructor(GDestroyNotify func) { client_destructors = g_slist_remove(client_destructors, (gpointer)func); } @@ -163,35 +166,8 @@ void client_manage_all() } XFree(children); - /* stack them as they were on startup! - why with stacking_lower? Why, because then windows who aren't in the - stacking list are on the top where you can see them instead of buried - at the bottom! */ - for (i = startup_stack_size; i > 0; --i) { - ObWindow *obw; - - w = startup_stack_order[i-1]; - obw = g_hash_table_lookup(window_map, &w); - if (obw) { - g_assert(WINDOW_IS_CLIENT(obw)); - stacking_lower(CLIENT_AS_WINDOW(obw)); - } - } - g_free(startup_stack_order); - startup_stack_order = NULL; - startup_stack_size = 0; - - if (config_focus_new) { - ObWindow *active; - - active = g_hash_table_lookup(window_map, &startup_active); - if (active) { - g_assert(WINDOW_IS_CLIENT(active)); - if (!client_focus(WINDOW_AS_CLIENT(active))) - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); - } else - focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); - } + if (config_focus_new) + focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS); } void client_manage(Window window) @@ -249,9 +225,18 @@ void client_manage(Window window) self->obwin.type = Window_Client; self->window = window; + /* non-zero defaults */ + self->title_count = 1; + self->wmstate = NormalState; + self->layer = -1; + self->decorate = TRUE; + self->desktop = screen_num_desktops; /* always an invalid value */ + client_get_all(self); client_restore_session_state(self); + sn_app_started(self->class); + client_change_state(self); /* remove the client's border (and adjust re gravity) */ @@ -423,7 +408,7 @@ void client_unmanage(ObClient *self) } for (it = client_destructors; it; it = g_slist_next(it)) { - ObClientDestructorFunc func = (ObClientDestructorFunc) it->data; + GDestroyNotify func = (GDestroyNotify) it->data; func(self); } @@ -482,16 +467,12 @@ void client_unmanage(ObClient *self) client_set_list(); } -static void client_act_urgent(ObClient *self) +static void client_urgent_notify(ObClient *self) { - GSList *it; - - for (it = config_urgent_actions; it; it = g_slist_next(it)) { - ObAction *a = it->data; - - a->data.any.c = self; - a->func(&a->data); - } + if (self->urgent) + frame_flash_start(self->frame); + else + frame_flash_stop(self->frame); } static void client_restore_session_state(ObClient *self) @@ -671,15 +652,10 @@ static void client_toggle_border(ObClient *self, gboolean show) static void client_get_all(ObClient *self) { - /* non-zero defaults */ - self->title_count = 1; - self->wmstate = NormalState; - self->layer = -1; - self->decorate = TRUE; - client_get_area(self); client_update_transient_for(self); client_update_wmhints(self); + client_get_startup_id(self); client_get_desktop(self); client_get_state(self); client_get_shaped(self); @@ -703,6 +679,14 @@ static void client_get_all(ObClient *self) client_update_icons(self); } +static void client_get_startup_id(ObClient *self) +{ + if (!(PROP_GETS(self->window, net_startup_id, utf8, &self->startup_id))) + if (self->group) + PROP_GETS(self->group->leader, + net_startup_id, utf8, &self->startup_id); +} + static void client_get_area(ObClient *self) { XWindowAttributes wattrib; @@ -743,9 +727,16 @@ static void client_get_desktop(ObClient *self) } } } - if (!trdesk) - /* defaults to the current desktop */ - self->desktop = screen_desktop; + if (!trdesk) { + /* try get from the startup-notification protocol */ + if (sn_get_desktop(self->startup_id, &self->desktop)) { + if (self->desktop >= screen_num_desktops && + self->desktop != DESKTOP_ALL) + self->desktop = screen_num_desktops - 1; + } else + /* defaults to the current desktop */ + self->desktop = screen_desktop; + } } if (self->desktop != d) { /* set the desktop hint, to make sure that it always exists */ @@ -758,10 +749,6 @@ static void client_get_state(ObClient *self) guint32 *state; guint num; - self->modal = self->shaded = self->max_horz = self->max_vert = - self->fullscreen = self->above = self->below = self->iconic = - self->skip_taskbar = self->skip_pager = FALSE; - if (PROP_GETA32(self->window, net_wm_state, atom, &state, &num)) { gulong i; for (i = 0; i < num; ++i) { @@ -821,7 +808,11 @@ void client_update_transient_for(ObClient *self) target = g_hash_table_lookup(window_map, &t); /* if this happens then we need to check for it*/ g_assert(target != self); - g_assert(!target || WINDOW_IS_CLIENT(target)); + if (target && !WINDOW_IS_CLIENT(target)) { + /* this can happen when a dialog is a child of + a dockapp, for example */ + target = NULL; + } if (!target && self->group) { /* not transient to a client, see if it is transient for a @@ -1305,8 +1296,8 @@ void client_update_wmhints(ObClient *self) ur ? "ON" : "OFF"); /* fire the urgent callback if we're mapped, otherwise, wait until after we're mapped */ - if (self->frame && self->urgent) - client_act_urgent(self); + if (self->frame) + client_urgent_notify(self); } } @@ -1315,10 +1306,11 @@ void client_update_title(ObClient *self) GList *it; guint32 nums; guint i; - char *data = NULL; + gchar *data = NULL; gboolean read_title; + gchar *old_title; - g_free(self->title); + old_title = self->title; /* try netwm */ if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) @@ -1326,6 +1318,10 @@ void client_update_title(ObClient *self) if (!PROP_GETS(self->window, wm_name, locale, &data)) data = g_strdup("Unnamed Window"); + /* did the title change? then reset the title_count */ + if (old_title && 0 != strncmp(old_title, data, strlen(data))) + self->title_count = 1; + /* look for duplicates and append a number */ nums = 0; for (it = client_list; it; it = it->next) @@ -1343,12 +1339,10 @@ void client_update_title(ObClient *self) } /* dont display the number for the first window */ if (self->title_count > 1) { - char *vdata, *ndata; - ndata = g_strdup_printf(" - [%u]", self->title_count); - vdata = g_strconcat(data, ndata, NULL); - g_free(ndata); + char *ndata; + ndata = g_strdup_printf("%s - [%u]", data, self->title_count); g_free(data); - data = vdata; + data = ndata; } PROP_SETS(self->window, net_wm_visible_name, data); @@ -1358,6 +1352,8 @@ void client_update_title(ObClient *self) if (self->frame) frame_adjust_title(self->frame); + g_free(old_title); + /* update the icon title */ data = NULL; g_free(self->icon_title); @@ -1730,7 +1726,7 @@ static void client_apply_startup_state(ObClient *self) client_shade(self, TRUE); } if (self->urgent) - client_act_urgent(self); + client_urgent_notify(self); if (self->max_vert && self->max_horz) { self->max_vert = self->max_horz = FALSE; @@ -1757,6 +1753,8 @@ void client_configure_full(ObClient *self, ObCorner anchor, gboolean user, gboolean final, gboolean force_reply) { + gint oldw, oldh; + gboolean send_resize_client; gboolean moved = FALSE, resized = FALSE; guint fdecor = self->frame->decorations; gboolean fhorz = self->frame->max_horz; @@ -1837,7 +1835,6 @@ void client_configure_full(ObClient *self, ObCorner anchor, if (!(w == self->area.width && h == self->area.height)) { int basew, baseh, minw, minh; - int mw, mh, aw, ah; /* base size is substituted with min size if not specified */ if (self->base_size.width || self->base_size.height) { @@ -1856,23 +1853,6 @@ void client_configure_full(ObClient *self, ObCorner anchor, minh = self->base_size.height; } - /* for interactive resizing. have to move half an increment in each - direction. */ - - /* how far we are towards the next size inc */ - mw = (w - basew) % self->size_inc.width; - mh = (h - baseh) % self->size_inc.height; - /* amount to add */ - aw = self->size_inc.width / 2; - ah = self->size_inc.height / 2; - /* don't let us move into a new size increment */ - if (mw + aw >= self->size_inc.width) - aw = self->size_inc.width - mw - 1; - if (mh + ah >= self->size_inc.height) - ah = self->size_inc.height - mh - 1; - w += aw; - h += ah; - /* if this is a user-requested resize, then check against min/max sizes */ @@ -1936,14 +1916,20 @@ void client_configure_full(ObClient *self, ObCorner anchor, moved = x != self->area.x || y != self->area.y; resized = w != self->area.width || h != self->area.height; + oldw = self->area.width; + oldh = self->area.height; RECT_SET(self->area, x, y, w, h); /* for app-requested resizes, always resize if 'resized' is true. for user-requested ones, only resize if final is true, or when resizing in redraw mode */ - if ((!user && resized) || - (user && (final || (resized && config_redraw_resize)))) - XResizeWindow(ob_display, self->window, w, h); + send_resize_client = ((!user && resized) || + (user && (final || + (resized && config_redraw_resize)))); + + /* if the client is enlarging, the resize the client before the frame */ + if (send_resize_client && (w > oldw || h > oldh)) + XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh)); /* move/resize the frame to match the request */ if (self->frame) { @@ -1975,6 +1961,12 @@ void client_configure_full(ObClient *self, ObCorner anchor, FALSE, StructureNotifyMask, &event); } } + + /* if the client is shrinking, then resize the frame before the client */ + if (send_resize_client && (w <= oldw || h <= oldh)) + XResizeWindow(ob_display, self->window, w, h); + + XFlush(ob_display); } void client_fullscreen(ObClient *self, gboolean fs, gboolean savearea) @@ -2528,12 +2520,17 @@ gboolean client_focus(ObClient *self) return FALSE; } - if (self->can_focus) + if (self->can_focus) { /* RevertToPointerRoot causes much more headache than RevertToNone, so I choose to use it always, hopefully to find errors quicker, if any - are left. (I hate X. I hate focus events.) */ - XSetInputFocus(ob_display, self->window, RevertToPointerRoot, + are left. (I hate X. I hate focus events.) + + Update: Changing this to RevertToNone fixed a bug with mozilla (bug + #799. So now it is RevertToNone again. + */ + XSetInputFocus(ob_display, self->window, RevertToNone, event_lasttime); + } if (self->focus_notify) { XEvent ce;