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(gboolean reconfig)
{
/* 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)) {
+ XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e))
+ {
XPutBackEvent(ob_display, &e);
grab_server(FALSE);
/* make sure it isn't an override-redirect window */
if (!XGetWindowAttributes(ob_display, window, &attrib) ||
- attrib.override_redirect) {
+ attrib.override_redirect)
+ {
grab_server(FALSE);
return; /* don't manage it */
}
/* is the window a docking app */
if ((wmhint = XGetWMHints(ob_display, window))) {
if ((wmhint->flags & StateHint) &&
- wmhint->initial_state == WithdrawnState) {
+ wmhint->initial_state == WithdrawnState)
+ {
dock_add(window, wmhint);
grab_server(FALSE);
XFree(wmhint);
client_get_all(self);
client_restore_session_state(self);
- sn_app_started(self->class);
+ sn_app_started(self->startup_id, self->class);
/* update the focus lists, do this before the call to change_state or
it can end up in the list twice! */
/* Don't worry, we won't actually both shade and undecorate the
* window when push comes to shove. */
if (settings->shade != -1)
- client_shade(self, settings->shade);
+ client_shade(self, !!settings->shade);
if (settings->decor != -1)
client_set_undecorated(self, !settings->decor);
if (settings->iconic != -1)
- client_iconify(self, settings->iconic, FALSE);
+ client_iconify(self, !!settings->iconic, FALSE);
if (settings->skip_pager != -1) {
self->skip_pager = !!settings->skip_pager;
client_change_state(self);
/* focus the new window? */
if (ob_state() != OB_STATE_STARTING &&
- ((settings && settings->focus == TRUE) ||
- (!settings && (config_focus_new ||
- client_search_focus_parent(self)))) &&
+ /* this means focus=true for window is same as config_focus_new=true */
+ ((config_focus_new || (settings && settings->focus == 1)) ||
+ client_search_focus_parent(self)) &&
+ /* this checks for focus=false for the window */
+ (!settings || settings->focus != 0) &&
/* note the check against Type_Normal/Dialog, not client_normal(self),
which would also include other types. in this case we want more
strict rules for focus */
(self->type == OB_CLIENT_TYPE_NORMAL ||
self->type == OB_CLIENT_TYPE_DIALOG))
- {
+ {
activate = TRUE;
#if 0
if (self->desktop != screen_desktop) {
grab_pointer(FALSE, OB_CURSOR_NONE);
}
-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;
/* XXX watch for xinerama dead areas */
/* This makes sure windows aren't entirely outside of the screen so you
- * can't see them at all */
+ can't see them at all.
+ It makes sure 10% of the window is on the screen at least. At don't let
+ it move itself off the top of the screen, which would hide the titlebar
+ on you. (The user can still do this if they want too, it's only limiting
+ the application.
+ */
if (client_normal(self)) {
a = screen_area(self->desktop);
- if (!self->strut.right && *x >= a->x + a->width - 1)
- *x = a->x + a->width - self->frame->area.width;
- if (!self->strut.bottom && *y >= a->y + a->height - 1)
- *y = a->y + a->height - self->frame->area.height;
- if (!self->strut.left && *x + self->frame->area.width - 1 < a->x)
- *x = a->x;
- if (!self->strut.top && *y + self->frame->area.height - 1 < a->y)
- *y = a->y;
+ if (!self->strut.right &&
+ *x + self->frame->area.width/10 >= a->x + a->width - 1)
+ *x = a->x + a->width - self->frame->area.width/10;
+ if (!self->strut.bottom &&
+ *y + self->frame->area.height/10 >= a->y + a->height - 1)
+ *y = a->y + a->height - self->frame->area.height/10;
+ if (!self->strut.left && *x + self->frame->area.width*9/10 - 1 < a->x)
+ *x = a->x - self->frame->area.width*9/10;
+ if (!self->strut.top && *y + self->frame->area.height*9/10 - 1 < a->y)
+ *y = a->y - self->frame->area.width*9/10;
}
/* This here doesn't let windows even a pixel outside the screen,
/* avoid the xinerama monitor divide while we're at it,
* remember to fix the placement stuff to avoid it also and
* then remove this XXX */
- a = screen_physical_area_monitor(client_monitor(self));
- /* dont let windows map/move into the strut unless they
+ a = screen_area_monitor(self->desktop, client_monitor(self));
+ /* dont let windows map into the strut unless they
are bigger than the available area */
if (w <= a->width) {
if (!self->strut.left && *x < a->x) *x = a->x;
self->above = TRUE;
else if (state[i] == prop_atoms.net_wm_state_below)
self->below = TRUE;
+ else if (state[i] == prop_atoms.net_wm_state_demands_attention)
+ self->demands_attention = TRUE;
else if (state[i] == prop_atoms.ob_wm_state_undecorated)
self->undecorated = TRUE;
}
a dockapp, for example */
target = NULL;
}
-
+
+#if 0
+/* we used to do this, but it violates the ICCCM and causes problems because
+ toolkits seem to set transient_for = root rather arbitrarily (eg kicker's
+ config dialogs), so it is being removed. the ewmh provides other ways to
+ make things transient for their group. -dana
+*/
if (!target && self->group) {
/* not transient to a client, see if it is transient for a
group */
target = OB_TRAN_GROUP;
}
}
+#endif
+
}
} else if (self->type == OB_CLIENT_TYPE_DIALOG && self->group) {
self->transient = TRUE;
void client_update_wmhints(ObClient *self)
{
XWMHints *hints;
- gboolean ur = FALSE;
GSList *it;
/* assume a window takes input if it doesnt specify */
if (hints->flags & StateHint)
self->iconic = hints->initial_state == IconicState;
- if (hints->flags & XUrgencyHint)
- ur = TRUE;
-
if (!(hints->flags & WindowGroupHint))
hints->window_group = None;
XFree(hints);
}
-
- if (ur != self->urgent) {
- self->urgent = ur;
- /* fire the urgent callback if we're mapped, otherwise, wait until
- after we're mapped */
- if (self->frame)
- client_urgent_notify(self);
- }
}
void client_update_title(ObClient *self)
for (it = client_list; it; it = g_list_next(it))
if (it->data != self) {
ObClient *c = it->data;
- if (0 == strncmp(c->title, data, strlen(data)))
- nums |= 1 << c->title_count;
+
+ 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)
* 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 *vdata, *ndata;
- ndata = g_strdup_printf(" - [%u]", self->title_count);
- vdata = g_strconcat(data, ndata, NULL);
- g_free(ndata);
+ gchar *newdata;
+ newdata = g_strdup_printf("%s - [%u]", data, self->title_count);
g_free(data);
- data = vdata;
+ data = newdata;
}
PROP_SETS(self->window, net_wm_visible_icon_name, data);
netstate[num++] = prop_atoms.net_wm_state_above;
if (self->below)
netstate[num++] = prop_atoms.net_wm_state_below;
+ if (self->demands_attention)
+ netstate[num++] = prop_atoms.net_wm_state_demands_attention;
if (self->undecorated)
netstate[num++] = prop_atoms.ob_wm_state_undecorated;
PROP_SETA32(self->window, net_wm_state, atom, netstate, num);
self->shaded = FALSE;
client_shade(self, TRUE);
}
- if (self->urgent)
- client_urgent_notify(self);
+ if (self->demands_attention) {
+ self->demands_attention = FALSE;
+ client_hilite(self, TRUE);
+ }
if (self->max_vert && self->max_horz) {
self->max_vert = self->max_horz = FALSE;
XKillClient(ob_display, self->window);
}
+void client_hilite(ObClient *self, gboolean hilite)
+{
+ /* don't allow focused windows to hilite */
+ self->demands_attention = hilite && !client_focused(self);
+ if (self->demands_attention)
+ frame_flash_start(self->frame);
+ else
+ frame_flash_stop(self->frame);
+ client_change_state(self);
+}
+
void client_set_desktop_recursive(ObClient *self,
guint target, gboolean donthide)
{
gboolean max_vert = self->max_vert;
gboolean modal = self->modal;
gboolean iconic = self->iconic;
+ gboolean demands_attention = self->demands_attention;
gint i;
if (!(action == prop_atoms.net_wm_state_add ||
else if (state == prop_atoms.net_wm_state_below)
action = self->below ? prop_atoms.net_wm_state_remove :
prop_atoms.net_wm_state_add;
+ else if (state == prop_atoms.net_wm_state_demands_attention)
+ action = self->demands_attention ?
+ prop_atoms.net_wm_state_remove :
+ prop_atoms.net_wm_state_add;
else if (state == prop_atoms.ob_wm_state_undecorated)
action = undecorated ? prop_atoms.net_wm_state_remove :
prop_atoms.net_wm_state_add;
} else if (state == prop_atoms.net_wm_state_below) {
self->above = FALSE;
self->below = TRUE;
+ } else if (state == prop_atoms.net_wm_state_demands_attention) {
+ demands_attention = TRUE;
} else if (state == prop_atoms.ob_wm_state_undecorated) {
undecorated = TRUE;
}
self->above = FALSE;
} else if (state == prop_atoms.net_wm_state_below) {
self->below = FALSE;
+ } else if (state == prop_atoms.net_wm_state_demands_attention) {
+ demands_attention = FALSE;
} else if (state == prop_atoms.ob_wm_state_undecorated) {
undecorated = FALSE;
}
if (iconic != self->iconic)
client_iconify(self, iconic, FALSE);
+ if (demands_attention != self->demands_attention)
+ client_hilite(self, demands_attention);
+
client_calc_layer(self);
client_change_state(self); /* change the hint to reflect these changes */
}