} else
windows = NULL;
- OBT_PROP_SETA32(RootWindow(obt_display, ob_screen),
- NET_CLIENT_LIST, WINDOW, (gulong*)windows, size);
+ OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST, WINDOW,
+ (gulong*)windows, size);
if (windows)
g_free(windows);
}
}
+ /* manage windows in reverse order from how they were originally mapped.
+ this is an attempt to manage children windows before their parents, so
+ that when the parent is mapped, it can find the child */
for (i = 0; i < nchild; ++i) {
if (children[i] == None)
continue;
/* create the ObClient struct, and populate it from the hints on the
window */
self = g_new0(ObClient, 1);
- self->obwin.type = Window_Client;
+ self->obwin.type = OB_WINDOW_CLASS_CLIENT;
self->window = window;
/* non-zero defaults */
ob_debug("Window type: %d\n", self->type);
ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
+ /* now we have all of the window's information so we can set this up.
+ do this before creating the frame, so it can tell that we are still
+ mapping and doesn't go applying things right away */
+ client_setup_decor_and_functions(self, FALSE);
+
/* specify that if we exit, the window should not be destroyed and
should be reparented back to root automatically */
XChangeSaveSet(obt_display, window, SetModeInsert);
/* the session should get the last say though */
client_restore_session_state(self);
- /* now we have all of the window's information so we can set this up */
- client_setup_decor_and_functions(self, FALSE);
-
/* tell startup notification that this app started */
- launch_time = sn_app_started(self->startup_id, self->class);
+ launch_time = sn_app_started(self->startup_id, self->class, self->name);
/* do this after we have a frame.. it uses the frame to help determine the
WM_STATE to apply. */
/* add to client list/map */
client_list = g_list_append(client_list, self);
- g_hash_table_insert(window_map, &self->window, self);
+ window_add(&self->window, CLIENT_AS_WINDOW(self));
/* this has to happen after we're in the client_list */
if (STRUT_EXISTS(self->strut))
client_list = g_list_remove(client_list, self);
stacking_remove(self);
- g_hash_table_remove(window_map, &self->window);
+ window_remove(self->window);
/* once the client is out of the list, update the struts to remove its
influence */
g_free(self->icons[j].data);
if (self->nicons > 0)
g_free(self->icons);
+ g_free(self->startup_id);
g_free(self->wm_command);
g_free(self->title);
g_free(self->icon_title);
if (XGetTransientForHint(obt_display, self->window, &t)) {
if (t != self->window) { /* cant be transient to itself! */
- target = g_hash_table_lookup(window_map, &t);
+ ObWindow *tw = window_find(t);
/* if this happens then we need to check for it*/
- g_assert(target != self);
- if (target && !WINDOW_IS_CLIENT(target)) {
- /* this can happen when a dialog is a child of
- a dockapp, for example */
- target = NULL;
+ g_assert(tw != CLIENT_AS_WINDOW(self));
+ if (tw && WINDOW_IS_CLIENT(tw)) {
+ /* watch out for windows with a parent that is something
+ different, like a dockapp for example */
+ target = WINDOW_AS_CLIENT(tw);
}
}
/* Setting the transient_for to Root is actually illegal, however
applications from time have done this to specify transient for
their group */
- if (!target && self->group && t == RootWindow(obt_display, ob_screen))
+ if (!target && self->group && t == obt_root(ob_screen))
trangroup = TRUE;
} else if (self->group && self->transient)
trangroup = TRUE;
OBT_PROP_SETA32(self->window, NET_WM_ALLOWED_ACTIONS, ATOM, actions, num);
- /* make sure the window isn't breaking any rules now */
+ /* make sure the window isn't breaking any rules now
+
+ don't check ICONIFY here. just cuz a window can't iconify doesnt mean
+ it can't be iconified with its parent
+ */
if (!(self->functions & OB_CLIENT_FUNC_SHADE) && self->shaded) {
if (self->frame) client_shade(self, FALSE);
else self->shaded = FALSE;
}
- if (!(self->functions & OB_CLIENT_FUNC_ICONIFY) && self->iconic) {
- if (self->frame) client_iconify(self, FALSE, TRUE, FALSE);
- else self->iconic = FALSE;
- }
if (!(self->functions & OB_CLIENT_FUNC_FULLSCREEN) && self->fullscreen) {
if (self->frame) client_fullscreen(self, FALSE);
else self->fullscreen = FALSE;
}
}
+/* Avoid storing icons above this size if possible */
+#define AVOID_ABOVE 64
+
void client_update_icons(ObClient *self)
{
guint num;
guint32 *data;
guint w, h, i, j;
+ guint num_seen; /* number of icons present */
+ guint num_small_seen; /* number of icons small enough present */
+ guint smallest, smallest_area;
for (i = 0; i < self->nicons; ++i)
g_free(self->icons[i].data);
if (OBT_PROP_GETA32(self->window, NET_WM_ICON, CARDINAL, &data, &num)) {
/* figure out how many valid icons are in here */
i = 0;
- while (num - i > 2) {
- w = data[i++];
- h = data[i++];
- i += w * h;
- if (i > num || w*h == 0) break;
- ++self->nicons;
- }
+ num_seen = num_small_seen = 0;
+ smallest = smallest_area = 0;
+ if (num > 2)
+ while (i < num) {
+ w = data[i++];
+ h = data[i++];
+ i += w * h;
+ /* watch for it being too small for the specified size, or for
+ zero sized icons. */
+ if (i > num || w == 0 || h == 0) break;
+
+ if (!smallest_area || w*h < smallest_area) {
+ smallest = num_seen;
+ smallest_area = w*h;
+ }
+ ++num_seen;
+ if (w <= AVOID_ABOVE && h <= AVOID_ABOVE)
+ ++num_small_seen;
+ }
+ if (num_small_seen > 0)
+ self->nicons = num_small_seen;
+ else if (num_seen)
+ self->nicons = 1;
self->icons = g_new(ObClientIcon, self->nicons);
/* store the icons */
i = 0;
- for (j = 0; j < self->nicons; ++j) {
+ for (j = 0; j < self->nicons;) {
guint x, y, t;
w = self->icons[j].width = data[i++];
h = self->icons[j].height = data[i++];
- if (w*h == 0) continue;
+ /* if there are some icons smaller than the threshold, we're
+ skipping all the ones above */
+ if (num_small_seen > 0) {
+ if (w > AVOID_ABOVE || h > AVOID_ABOVE) {
+ i += w*h;
+ continue;
+ }
+ }
+ /* if there were no icons smaller than the threshold, then we are
+ only taking the smallest available one we saw */
+ else if (j != smallest) {
+ i += w*h;
+ continue;
+ }
self->icons[j].data = g_new(RrPixel32, w * h);
for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) {
(((data[i] >> 0) & 0xff) << RrDefaultBlueOffset);
}
g_assert(i <= num);
+
+ ++j;
}
g_free(data);
RECT_SET(self->icon_geometry, 0, 0, 0, 0);
if (OBT_PROP_GETA32(self->window, NET_WM_ICON_GEOMETRY, CARDINAL,
- &data, &num) && num == 4)
+ &data, &num))
{
- /* don't let them set it with an area < 0 */
- RECT_SET(self->icon_geometry, data[0], data[1],
- MAX(data[2],0), MAX(data[3],0));
+ if (num == 4)
+ /* don't let them set it with an area < 0 */
+ RECT_SET(self->icon_geometry, data[0], data[1],
+ MAX(data[2],0), MAX(data[3],0));
+ g_free(data);
}
}