-#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"
#include "prop.h"
#include "extensions.h"
#include "frame.h"
#include "grab.h"
#include "focus.h"
#include "stacking.h"
-#include "dispatch.h"
#include "openbox.h"
#include "group.h"
#include "config.h"
#define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \
ButtonMotionMask)
-GList *client_list = NULL;
+GList *client_list = NULL;
+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);
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_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(GDestroyNotify func)
+{
+ client_destructors = g_slist_prepend(client_destructors, (gpointer)func);
+}
+
+void client_remove_destructor(GDestroyNotify func)
{
+ client_destructors = g_slist_remove(client_destructors, (gpointer)func);
}
void client_set_list()
}
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)
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) */
frame_grab_client(self->frame, self);
- client_apply_startup_state(self);
-
grab_server(FALSE);
+ client_apply_startup_state(self);
+
/* update the focus lists */
focus_order_add_new(self);
#endif
}
- dispatch_client(Event_Client_New, self, 0, 0);
+ if (ob_state() == OB_STATE_RUNNING) {
+ int x = self->area.x, ox = x;
+ int y = self->area.y, oy = y;
+
+ place_client(self, &x, &y);
+
+ /* make sure the window is visible */
+ client_find_onscreen(self, &x, &y,
+ self->frame->area.width,
+ self->frame->area.height,
+ client_normal(self));
- /* make sure the window is visible */
- if (ob_state() == OB_STATE_RUNNING)
- client_move_onscreen(self, client_normal(self));
+ if (x != ox || y != oy)
+ client_move(self, x, y);
+ }
client_showhide(self);
keyboard_grab_for_client(self, TRUE);
mouse_grab_for_client(self, TRUE);
- dispatch_client(Event_Client_Mapped, self, 0, 0);
-
ob_debug("Managed window 0x%lx (%s)\n", window, self->class);
}
ob_debug("Unmanaging window: %lx (%s)\n", self->window, self->class);
- dispatch_client(Event_Client_Destroy, self, 0, 0);
g_assert(self != NULL);
keyboard_grab_for_client(self, FALSE);
}
}
- if (moveresize_client == self)
- moveresize_end(TRUE);
-
- /* menus can be associated with a client, so close any that are since
- we are disappearing now */
- menu_frame_hide_all_client(self);
-
+ for (it = client_destructors; it; it = g_slist_next(it)) {
+ GDestroyNotify func = (GDestroyNotify) it->data;
+ func(self);
+ }
+
if (focus_client == self) {
XEvent e;
self->group = NULL;
}
- /* dispatch the unmapped event */
- dispatch_client(Event_Client_Unmapped, self, 0, 0);
- g_assert(self != NULL);
-
/* give the client its border back */
client_toggle_border(self, TRUE);
client_set_list();
}
+static void client_urgent_notify(ObClient *self)
+{
+ if (self->urgent)
+ frame_flash_start(self->frame);
+ else
+ frame_flash_stop(self->frame);
+}
+
static void client_restore_session_state(ObClient *self)
{
GList *it;
if (client_find_onscreen(self, &x, &y,
self->frame->area.width,
self->frame->area.height, rude)) {
- client_configure(self, OB_CORNER_TOPLEFT, x, y,
- self->area.width, self->area.height,
- TRUE, TRUE);
+ client_move(self, x, y);
}
}
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);
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;
}
}
}
- 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 */
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
void client_setup_decor_and_functions(ObClient *self)
{
/* start with everything (cept fullscreen) */
- self->decorations = (OB_FRAME_DECOR_TITLEBAR |
- OB_FRAME_DECOR_HANDLE |
- OB_FRAME_DECOR_GRIPS |
- OB_FRAME_DECOR_BORDER |
- OB_FRAME_DECOR_ICON |
- OB_FRAME_DECOR_ALLDESKTOPS |
- OB_FRAME_DECOR_ICONIFY |
- OB_FRAME_DECOR_MAXIMIZE |
- OB_FRAME_DECOR_SHADE);
- self->functions = (OB_CLIENT_FUNC_RESIZE |
- OB_CLIENT_FUNC_MOVE |
- OB_CLIENT_FUNC_ICONIFY |
- OB_CLIENT_FUNC_MAXIMIZE |
- OB_CLIENT_FUNC_SHADE);
+ self->decorations =
+ (OB_FRAME_DECOR_TITLEBAR |
+ (ob_rr_theme->show_handle ? OB_FRAME_DECOR_HANDLE : 0) |
+ OB_FRAME_DECOR_GRIPS |
+ OB_FRAME_DECOR_BORDER |
+ OB_FRAME_DECOR_ICON |
+ OB_FRAME_DECOR_ALLDESKTOPS |
+ OB_FRAME_DECOR_ICONIFY |
+ OB_FRAME_DECOR_MAXIMIZE |
+ OB_FRAME_DECOR_SHADE);
+ self->functions =
+ (OB_CLIENT_FUNC_RESIZE |
+ OB_CLIENT_FUNC_MOVE |
+ OB_CLIENT_FUNC_ICONIFY |
+ OB_CLIENT_FUNC_MAXIMIZE |
+ OB_CLIENT_FUNC_SHADE);
if (self->delete_window) {
self->functions |= OB_CLIENT_FUNC_CLOSE;
self->decorations |= OB_FRAME_DECOR_CLOSE;
/* fire the urgent callback if we're mapped, otherwise, wait until
after we're mapped */
if (self->frame)
- dispatch_client(Event_Client_Urgent, self, self->urgent, 0);
+ client_urgent_notify(self);
}
}
client_shade(self, TRUE);
}
if (self->urgent)
- dispatch_client(Event_Client_Urgent, self, self->urgent, 0);
+ client_urgent_notify(self);
if (self->max_vert && self->max_horz) {
self->max_vert = self->max_horz = FALSE;
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) {
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 */
client_setup_decor_and_functions(self);
- client_configure(self, OB_CORNER_TOPLEFT, x, y, w, h, TRUE, TRUE);
+ client_move_resize(self, x, y, w, h);
/* try focus us when we go into fullscreen mode */
client_focus(self);
client_change_state(self);
client_showhide(self);
screen_update_areas();
-
- dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped,
- self, 0, 0);
}
/* iconify all transients */
/* figure out where the client should be going */
frame_frame_gravity(self->frame, &x, &y);
- client_configure(self, OB_CORNER_TOPLEFT, x, y, w, h, TRUE, TRUE);
+ client_move_resize(self, x, y, w, h);
}
void client_shade(ObClient *self, gboolean shade)
focus_order_to_top(self);
else
focus_order_to_bottom(self);
-
- dispatch_client(Event_Client_Desktop, self, target, old);
}
/* move all transients */