grab_server(TRUE);
- /* check if it has already been unmapped by the time we started mapping
+ /* check if it has already been unmapped by the time we started mapping.
the grab does a sync so we don't have to here */
if (XCheckTypedWindowEvent(ob_display, window, DestroyNotify, &e) ||
XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e))
{
XPutBackEvent(ob_display, &e);
+ ob_debug("Trying to manage unmapped window. Aborting that.\n");
grab_server(FALSE);
return; /* don't manage it */
}
self->window = window;
/* non-zero defaults */
- self->title_count = 1;
self->wmstate = WithdrawnState; /* make sure it gets updated first time */
self->layer = -1;
self->desktop = screen_num_desktops; /* always an invalid value */
- self->user_time = ~0; /* maximum value, always newer than the real time */
+ self->user_time = client_last_user_time;
client_get_all(self);
client_restore_session_state(self);
won't be all wacko!!
also, this moves the window to the position where it has been placed
*/
+ ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
+ self->window, newx, newy, self->area.width, self->area.height);
client_apply_startup_state(self, newx, newy);
keyboard_grab_for_client(self, TRUE);
else
{
/* If time stamp is old, don't steal focus */
- if (self->user_time && self->user_time < client_last_user_time)
+ if (self->user_time &&
+ !event_time_after(self->user_time, client_last_user_time))
+ {
activate = FALSE;
+ }
/* Don't steal focus from globally active clients.
I stole this idea from KWin. It seems nice.
*/
- if (!focus_client->can_focus && focus_client->focus_notify)
+ if (!(focus_client->can_focus || focus_client->focus_notify))
activate = FALSE;
}
/* 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
*/
- client_showhide(self);
+ client_show(self);
/* use client_focus instead of client_activate cuz client_activate does
stuff like switch desktops etc and I'm not interested in all that when
self->group = NULL;
}
- /* give the client its border back */
- client_toggle_border(self, TRUE);
+ /* restore the window's original geometry so it is not lost */
+ {
+ Rect a = self->area;
+
+ if (self->fullscreen)
+ a = self->pre_fullscreen_area;
+ else if (self->max_horz || self->max_vert) {
+ if (self->max_horz) {
+ a.x = self->pre_max_area.x;
+ a.width = self->pre_max_area.width;
+ }
+ if (self->max_vert) {
+ a.y = self->pre_max_area.y;
+ a.height = self->pre_max_area.height;
+ }
+ }
+
+ /* give the client its border back */
+ client_toggle_border(self, TRUE);
+
+ self->fullscreen = self->max_horz = self->max_vert = FALSE;
+ self->decorations = 0; /* unmanaged windows have no decor */
+
+ client_move_resize(self, a.x, a.y, a.width, a.height);
+ }
/* reparent the window out of the frame, and free the frame */
frame_release_client(self->frame, self);
self->frame = NULL;
- /* restore the window's original geometry so it is not lost */
- if (self->fullscreen)
- XMoveResizeWindow(ob_display, self->window,
- self->pre_fullscreen_area.x,
- self->pre_fullscreen_area.y,
- self->pre_fullscreen_area.width,
- self->pre_fullscreen_area.height);
- else if (self->max_horz || self->max_vert) {
- Rect a = self->area;
- if (self->max_horz) {
- a.x = self->pre_max_area.x;
- a.width = self->pre_max_area.width;
- }
- if (self->max_vert) {
- a.y = self->pre_max_area.y;
- a.height = self->pre_max_area.height;
- }
- XMoveResizeWindow(ob_display, self->window,
- a.x, a.y, a.width, a.height);
- }
-
if (ob_state() != OB_STATE_EXITING) {
/* these values should not be persisted across a window
unmapping/mapping */
XMapWindow(ob_display, self->window);
}
-
ob_debug("Unmanaged window 0x%lx\n", self->window);
/* free all data allocated in the client struct */
if (show) {
XSetWindowBorderWidth(ob_display, self->window, self->border_width);
- /* move the client so it is back it the right spot _with_ its
- border! */
- if (x != oldx || y != oldy)
- XMoveWindow(ob_display, self->window, x, y);
+ /* set border_width to 0 because there is no border to add into
+ calculations anymore */
+ self->border_width = 0;
} else
XSetWindowBorderWidth(ob_display, self->window, 0);
}
g_assert(ret != BadWindow);
RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
+ POINT_SET(self->root_pos, wattrib.x, wattrib.y);
self->border_width = wattrib.border_width;
ob_debug("client area: %d %d %d %d\n", wattrib.x, wattrib.y,
void client_update_title(ObClient *self)
{
- GList *it;
- guint32 nums;
- guint i;
gchar *data = NULL;
- gboolean read_title;
- gchar *old_title;
- old_title = self->title;
+ g_free(self->title);
/* try netwm */
if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
/* try old x stuff */
if (!(PROP_GETS(self->window, wm_name, locale, &data)
|| PROP_GETS(self->window, wm_name, utf8, &data))) {
- // http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
if (self->transient) {
+ /*
+ GNOME alert windows are not given titles:
+ http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
+ */
data = g_strdup("");
- goto no_number;
} else
data = g_strdup("Unnamed Window");
}
}
- if (config_title_number) {
-
- /* 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 = g_list_next(it))
- if (it->data != self) {
- ObClient *c = it->data;
-
- if (c->title_count == 1) {
- if (!strcmp(c->title, data))
- nums |= 1 << c->title_count;
- } else {
- size_t len;
- gchar *end;
-
- /* find the beginning of our " - [%u]", this relies on
- that syntax being used */
- end = strrchr(c->title, '-') - 1;
- len = end - c->title;
- if (!strncmp(c->title, data, len))
- nums |= 1 << c->title_count;
- }
- }
- /* find first free number */
- for (i = 1; i <= 32; ++i)
- if (!(nums & (1 << i))) {
- if (self->title_count == 1 || i == 1)
- self->title_count = i;
- break;
- }
- /* dont display the number for the first window */
- if (self->title_count > 1) {
- gchar *ndata;
- ndata = g_strdup_printf("%s - [%u]", data, self->title_count);
- g_free(data);
- data = ndata;
- }
- } else
- self->title_count = 1;
-
-no_number:
PROP_SETS(self->window, net_wm_visible_name, data);
self->title = data;
if (self->frame)
frame_adjust_title(self->frame);
- g_free(old_title);
-
/* update the icon title */
data = NULL;
g_free(self->icon_title);
- read_title = TRUE;
/* try netwm */
if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
/* try old x stuff */
- if (!(PROP_GETS(self->window, wm_icon_name, locale, &data)
- || PROP_GETS(self->window, wm_icon_name, utf8, &data))) {
+ if (!(PROP_GETS(self->window, wm_icon_name, locale, &data) ||
+ PROP_GETS(self->window, wm_icon_name, utf8, &data)))
data = g_strdup(self->title);
- read_title = FALSE;
- }
-
- /* append the title count, dont display the number for the first window.
- * We don't need to check for config_title_number here since title_count
- * is not set above 1 then. */
- if (read_title && self->title_count > 1) {
- gchar *newdata;
- newdata = g_strdup_printf("%s - [%u]", data, self->title_count);
- g_free(data);
- data = newdata;
- }
PROP_SETS(self->window, net_wm_visible_icon_name, data);
-
self->icon_title = data;
}
if (new_event)
client_last_user_time = time;
- /*ob_debug("window 0x%x user time %u\n", self->window, time);*/
+ /*
+ ob_debug("window %s user time %u\n", self->title, time);
+ ob_debug("last user time %u\n", client_last_user_time);
+ */
}
}
return FALSE;
}
+void client_show(ObClient *self)
+{
+
+ if (client_should_show(self)) {
+ frame_show(self->frame);
+ }
+
+ /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+ needs to be in IconicState. This includes when it is on another
+ desktop!
+ */
+ client_change_wm_state(self);
+}
+
+void client_hide(ObClient *self)
+{
+ if (!client_should_show(self)) {
+ frame_hide(self->frame);
+ }
+
+ /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+ needs to be in IconicState. This includes when it is on another
+ desktop!
+ */
+ client_change_wm_state(self);
+}
+
void client_showhide(ObClient *self)
{
}
else {
frame_hide(self->frame);
-
- /* Fall back focus since we're disappearing */
- if (focus_client == self)
- client_unfocus(self);
}
/* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
pos = TRUE;
}
- /* if the client didn't get positioned yet, then do so now */
- if (!pos && (ox != x || oy != y)) {
+ /* if the client didn't get positioned yet, then do so now
+ call client_move even if the window is not being moved anywhere, because
+ when we reparent it and decorate it, it is getting moved and we need to
+ be telling it so with a ConfigureNotify event.
+ */
+ if (!pos) {
/* use the saved position */
self->area.x = ox;
self->area.y = oy;
the updated frame dimensions. */
frame_adjust_area(self->frame, TRUE, TRUE, TRUE);
- /* gets the frame's position */
- frame_client_gravity(self->frame, x, y);
-
- /* these positions are frame positions, not client positions */
-
- /* set the size and position if fullscreen */
- if (self->fullscreen) {
- Rect *a;
- guint i;
-
- i = screen_find_monitor(&desired_area);
- a = screen_physical_area_monitor(i);
-
- *x = a->x;
- *y = a->y;
- *w = a->width;
- *h = a->height;
-
- user = FALSE; /* ignore that increment etc shit when in fullscreen */
- } else {
- Rect *a;
- guint i;
-
- i = screen_find_monitor(&desired_area);
- a = screen_area_monitor(self->desktop, i);
-
- /* set the size and position if maximized */
- if (self->max_horz) {
- *x = a->x;
- *w = a->width - self->frame->size.left - self->frame->size.right;
- }
- if (self->max_vert) {
- *y = a->y;
- *h = a->height - self->frame->size.top - self->frame->size.bottom;
- }
- }
-
- /* gets the client's position */
- frame_frame_gravity(self->frame, x, y);
-
- /* these override the above states! if you cant move you can't move! */
- if (user) {
- if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
- *x = self->area.x;
- *y = self->area.y;
- }
- if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
- *w = self->area.width;
- *h = self->area.height;
- }
- }
-
+ /* work within the prefered sizes given by the window */
if (!(*w == self->area.width && *h == self->area.height)) {
gint basew, baseh, minw, minh;
*h += self->base_size.height;
}
+ /* gets the frame's position */
+ frame_client_gravity(self->frame, x, y);
+
+ /* these positions are frame positions, not client positions */
+
+ /* set the size and position if fullscreen */
+ if (self->fullscreen) {
+ Rect *a;
+ guint i;
+
+ i = screen_find_monitor(&desired_area);
+ a = screen_physical_area_monitor(i);
+
+ *x = a->x;
+ *y = a->y;
+ *w = a->width;
+ *h = a->height;
+
+ user = FALSE; /* ignore if the client can't be moved/resized when it
+ is entering fullscreen */
+ } else if (self->max_horz || self->max_vert) {
+ Rect *a;
+ guint i;
+
+ i = screen_find_monitor(&desired_area);
+ a = screen_area_monitor(self->desktop, i);
+
+ /* set the size and position if maximized */
+ if (self->max_horz) {
+ *x = a->x;
+ *w = a->width - self->frame->size.left - self->frame->size.right;
+ }
+ if (self->max_vert) {
+ *y = a->y;
+ *h = a->height - self->frame->size.top - self->frame->size.bottom;
+ }
+
+ /* maximizing is not allowed if the user can't move+resize the window
+ */
+ }
+
+ /* gets the client's position */
+ frame_frame_gravity(self->frame, x, y);
+
+ /* these override the above states! if you cant move you can't move! */
+ if (user) {
+ if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
+ *x = self->area.x;
+ *y = self->area.y;
+ }
+ if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
+ *w = self->area.width;
+ *h = self->area.height;
+ }
+ }
+
g_assert(*w > 0);
g_assert(*h > 0);
gboolean user, gboolean final,
gboolean force_reply)
{
- gint oldw, oldh;
+ gint oldw, oldh, oldrx, oldry;
gboolean send_resize_client;
- gboolean moved = FALSE, resized = FALSE;
+ gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
guint fdecor = self->frame->decorations;
gboolean fhorz = self->frame->max_horz;
gint logicalw, logicalh;
client_try_configure(self, anchor, &x, &y, &w, &h,
&logicalw, &logicalh, user);
- /* set the logical size */
- SIZE_SET(self->logical_size, logicalw, logicalh);
+ /* set the logical size if things changed */
+ if (!(w == self->area.width && h == self->area.height))
+ SIZE_SET(self->logical_size, logicalw, logicalh);
/* figure out if we moved or resized or what */
moved = x != self->area.x || y != self->area.y;
if (send_resize_client && user && (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) {
- if (self->decorations != fdecor || self->max_horz != fhorz)
- moved = resized = TRUE;
-
- if (moved || resized)
- frame_adjust_area(self->frame, moved, resized, FALSE);
-
- if (!resized && (force_reply || ((!user && moved) || (user && final))))
- {
- XEvent event;
- event.type = ConfigureNotify;
- event.xconfigure.display = ob_display;
- event.xconfigure.event = self->window;
- event.xconfigure.window = self->window;
-
- /* root window real coords */
- event.xconfigure.x = self->frame->area.x + self->frame->size.left -
- self->border_width;
- event.xconfigure.y = self->frame->area.y + self->frame->size.top -
- self->border_width;
- event.xconfigure.width = w;
- event.xconfigure.height = h;
- event.xconfigure.border_width = 0;
- event.xconfigure.above = self->frame->plate;
- event.xconfigure.override_redirect = FALSE;
- XSendEvent(event.xconfigure.display, event.xconfigure.window,
- FALSE, StructureNotifyMask, &event);
- }
+ /* find the frame's dimensions and move/resize it */
+ if (self->decorations != fdecor || self->max_horz != fhorz)
+ moved = resized = TRUE;
+ if (moved || resized)
+ frame_adjust_area(self->frame, moved, resized, FALSE);
+
+ /* find the client's position relative to the root window */
+ oldrx = self->root_pos.x;
+ oldry = self->root_pos.y;
+ rootmoved = (oldrx != (self->frame->area.x + self->frame->size.left -
+ self->border_width) ||
+ oldry != (self->frame->area.y + self->frame->size.top -
+ self->border_width));
+
+ if (force_reply || ((!user || (user && final)) && rootmoved))
+ {
+ XEvent event;
+
+ POINT_SET(self->root_pos,
+ self->frame->area.x + self->frame->size.left -
+ self->border_width,
+ self->frame->area.y + self->frame->size.top -
+ self->border_width);
+
+ event.type = ConfigureNotify;
+ event.xconfigure.display = ob_display;
+ event.xconfigure.event = self->window;
+ event.xconfigure.window = self->window;
+
+ /* root window real coords */
+ event.xconfigure.x = self->root_pos.x;
+ event.xconfigure.y = self->root_pos.y;
+ event.xconfigure.width = w;
+ event.xconfigure.height = h;
+ event.xconfigure.border_width = 0;
+ event.xconfigure.above = self->frame->plate;
+ event.xconfigure.override_redirect = FALSE;
+ XSendEvent(event.xconfigure.display, event.xconfigure.window,
+ FALSE, StructureNotifyMask, &event);
}
/* if the client is shrinking, then resize the frame before the client */
/* choose the correct target */
self = client_focus_target(self);
-#if 0
- if (!client_validate(self))
- return FALSE;
-#endif
-
if (!client_can_focus(self)) {
if (!self->frame->visible) {
/* update the focus lists */
}
}
-void client_activate(ObClient *self, gboolean here, gboolean user, Time time)
+void client_activate(ObClient *self, gboolean here, gboolean user)
{
/* XXX do some stuff here if user is false to determine if we really want
to activate it or not (a parent or group member is currently
*/
ob_debug("Want to activate window 0x%x with time %u (last time %u), "
"source=%s\n",
- self->window, time, client_last_user_time,
+ self->window, event_curtime, client_last_user_time,
(user ? "user" : "application"));
- if (!user && time && time < client_last_user_time)
+ if (!user && event_curtime &&
+ !event_time_after(event_curtime, client_last_user_time))
+ {
client_hilite(self, TRUE);
- else {
+ } else {
if (client_normal(self) && screen_showing_desktop)
screen_show_desktop(FALSE);
if (self->iconic)