save and restore pre-maximized/fullscreen sizes properly

much cleanup on how per-app settings are applied to new mapping windows. maybe i broke it? but it'll be much quicker now, and it's consistant with the rest of the code, so hooray for that. pls let me know if i broke any of it :( hee..
This commit is contained in:
Dana Jansens 2007-03-13 02:29:08 +00:00
parent b2e08c0ad5
commit 7f58bd9eaa
3 changed files with 178 additions and 132 deletions

View file

@ -1359,14 +1359,14 @@ void action_resize_relative(union ActionData *data)
void action_maximize_full(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c, TRUE, 0, TRUE);
client_maximize(data->client.any.c, TRUE, 0);
client_action_end(data);
}
void action_unmaximize_full(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c, FALSE, 0, TRUE);
client_maximize(data->client.any.c, FALSE, 0);
client_action_end(data);
}
@ -1376,21 +1376,21 @@ void action_toggle_maximize_full(union ActionData *data)
client_maximize(data->client.any.c,
!(data->client.any.c->max_horz ||
data->client.any.c->max_vert),
0, TRUE);
0);
client_action_end(data);
}
void action_maximize_horz(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c, TRUE, 1, TRUE);
client_maximize(data->client.any.c, TRUE, 1);
client_action_end(data);
}
void action_unmaximize_horz(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c, FALSE, 1, TRUE);
client_maximize(data->client.any.c, FALSE, 1);
client_action_end(data);
}
@ -1398,21 +1398,21 @@ void action_toggle_maximize_horz(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c,
!data->client.any.c->max_horz, 1, TRUE);
!data->client.any.c->max_horz, 1);
client_action_end(data);
}
void action_maximize_vert(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c, TRUE, 2, TRUE);
client_maximize(data->client.any.c, TRUE, 2);
client_action_end(data);
}
void action_unmaximize_vert(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c, FALSE, 2, TRUE);
client_maximize(data->client.any.c, FALSE, 2);
client_action_end(data);
}
@ -1420,15 +1420,14 @@ void action_toggle_maximize_vert(union ActionData *data)
{
client_action_start(data);
client_maximize(data->client.any.c,
!data->client.any.c->max_vert, 2, TRUE);
!data->client.any.c->max_vert, 2);
client_action_end(data);
}
void action_toggle_fullscreen(union ActionData *data)
{
client_action_start(data);
client_fullscreen(data->client.any.c,
!(data->client.any.c->fullscreen), TRUE);
client_fullscreen(data->client.any.c, !(data->client.any.c->fullscreen));
client_action_end(data);
}

View file

@ -74,9 +74,10 @@ static void client_get_gravity(ObClient *self);
static void client_showhide(ObClient *self);
static void client_change_allowed_actions(ObClient *self);
static void client_change_state(ObClient *self);
static void client_apply_startup_state(ObClient *self);
static void client_apply_startup_state(ObClient *self, gint x, gint y);
static void client_restore_session_state(ObClient *self);
static void client_restore_session_stacking(ObClient *self);
static ObAppSettings *client_get_settings_state(ObClient *self);
void client_startup(gboolean reconfig)
{
@ -205,33 +206,6 @@ void client_manage_all()
XFree(children);
}
static ObAppSettings *get_settings(ObClient *client)
{
GSList *a = config_per_app_settings;
while (a) {
ObAppSettings *app = (ObAppSettings *) a->data;
if (
(app->name && !app->class && !strcmp(app->name, client->name))
|| (app->class && !app->name && !strcmp(app->class, client->class))
|| (app->class && app->name && !strcmp(app->class, client->class)
&& !strcmp(app->name, client->name))
) {
ob_debug("Window matching: %s\n", app->name);
/* Match if no role was specified in the per app setting, or if the
* string matches the beginning of the role, since apps like to set
* the role to things like browser-window-23c4b2f */
if (!app->role
|| !strncmp(app->role, client->role, strlen(app->role)))
return app;
}
a = a->next;
}
return NULL;
}
void client_manage(Window window)
{
ObClient *self;
@ -241,6 +215,7 @@ void client_manage(Window window)
XWMHints *wmhint;
gboolean activate = FALSE;
ObAppSettings *settings;
gint newx, newy;
grab_server(TRUE);
@ -300,6 +275,9 @@ void client_manage(Window window)
client_get_all(self);
client_restore_session_state(self);
/* per-app settings override stuff, and return the settings for other
uses too */
settings = client_get_settings_state(self);
client_calc_layer(self);
@ -328,57 +306,9 @@ void client_manage(Window window)
grab_server(FALSE);
client_apply_startup_state(self);
/* get and set application level settings */
settings = get_settings(self);
stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
client_restore_session_stacking(self);
if (settings) {
/* 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);
if (settings->decor != -1)
client_set_undecorated(self, !settings->decor);
if (settings->iconic != -1)
client_iconify(self, !!settings->iconic, FALSE);
if (settings->skip_pager != -1) {
self->skip_pager = !!settings->skip_pager;
client_change_state(self);
}
if (settings->skip_taskbar != -1) {
self->skip_taskbar = !!settings->skip_taskbar;
client_change_state(self);
}
/* 1 && -1 shouldn't be possible by the code in config.c */
if (settings->max_vert == 1 && settings->max_horz == 1)
client_maximize(self, TRUE, 0, TRUE);
else if (settings->max_vert == 0 && settings->max_horz == 0)
client_maximize(self, FALSE, 0, TRUE);
else if (settings->max_vert == 1 && settings->max_horz == 0) {
client_maximize(self, TRUE, 2, TRUE);
client_maximize(self, FALSE, 1, TRUE);
} else if (settings->max_vert == 0 && settings->max_horz == 1) {
client_maximize(self, TRUE, 1, TRUE);
client_maximize(self, FALSE, 2, TRUE);
}
if (settings->fullscreen != -1)
client_fullscreen(self, !!settings->fullscreen, TRUE);
if (settings->desktop < screen_num_desktops
|| settings->desktop == DESKTOP_ALL)
client_set_desktop(self, settings->desktop, TRUE);
if (settings->layer > -2 && settings->layer < 2)
client_set_layer(self, settings->layer);
}
/* focus the new window? */
if (ob_state() != OB_STATE_STARTING &&
/* this means focus=true for window is same as config_focus_new=true */
@ -426,15 +356,18 @@ void client_manage(Window window)
#endif
}
/* get the current position */
newx = self->area.x;
newy = self->area.y;
/* figure out placement for the window */
if (ob_state() == OB_STATE_RUNNING) {
gint x = self->area.x, ox = x;
gint y = self->area.y, oy = y;
gboolean transient;
transient = place_client(self, &x, &y, settings);
transient = place_client(self, &newx, &newy, settings);
/* make sure the window is visible. */
client_find_onscreen(self, &x, &y,
client_find_onscreen(self, &newx, &newy,
self->frame->area.width,
self->frame->area.height,
/* non-normal clients has less rules, and
@ -452,10 +385,14 @@ void client_manage(Window window)
!(self->positioned & USPosition)) &&
client_normal(self) &&
!self->session));
if (x != ox || y != oy)
client_move(self, x, y);
}
/* do this after the window is placed, so the premax/prefullscreen numbers
won't be all wacko!!
also, this moves the window to the position where it has been placed
*/
client_apply_startup_state(self, newx, newy);
keyboard_grab_for_client(self, TRUE);
mouse_grab_for_client(self, TRUE);
@ -636,6 +573,27 @@ void client_unmanage(ObClient *self)
/* 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
@ -673,6 +631,73 @@ void client_unmanage(ObClient *self)
grab_pointer(FALSE, OB_CURSOR_NONE);
}
static ObAppSettings *client_get_settings_state(ObClient *self)
{
ObAppSettings *settings = NULL;
GSList *it;
for (it = config_per_app_settings; it; it = g_slist_next(it)) {
ObAppSettings *app;
if ((app->name && !app->class && !strcmp(app->name, self->name))
|| (app->class && !app->name && !strcmp(app->class, self->class))
|| (app->class && app->name && !strcmp(app->class, self->class)
&& !strcmp(app->name, self->name)))
{
ob_debug("Window matching: %s\n", app->name);
/* Match if no role was specified in the per app setting, or if the
* string matches the beginning of the role, since apps like to set
* the role to things like browser-window-23c4b2f */
if (!app->role
|| !strncmp(app->role, self->role, strlen(app->role)))
{
/* use this one */
settings = app;
break;
}
}
}
if (settings) {
if (settings->shade != -1)
self->shaded = !!settings->shade;
if (settings->decor != -1)
self->undecorated = !settings->decor;
if (settings->iconic != -1)
self->iconic = !!settings->iconic;
if (settings->skip_pager != -1)
self->skip_pager = !!settings->skip_pager;
if (settings->skip_taskbar != -1)
self->skip_taskbar = !!settings->skip_taskbar;
if (settings->max_vert != -1)
self->max_vert = !!settings->max_vert;
if (settings->max_horz != -1)
self->max_vert = !!settings->max_horz;
if (settings->fullscreen != -1)
self->fullscreen = !!settings->fullscreen;
if (settings->desktop < screen_num_desktops
|| settings->desktop == DESKTOP_ALL)
client_set_desktop(self, settings->desktop, TRUE);
if (settings->layer == -1) {
self->below = TRUE;
self->above = FALSE;
}
else if (settings->layer == 0) {
self->below = FALSE;
self->above = FALSE;
}
else if (settings->layer == 1) {
self->below = FALSE;
self->above = TRUE;
}
}
return settings;
}
static void client_restore_session_state(ObClient *self)
{
GList *it;
@ -935,6 +960,9 @@ static void client_get_area(ObClient *self)
RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
self->border_width = wattrib.border_width;
ob_debug("client area: %d %d %d %d\n", wattrib.x, wattrib.y,
wattrib.width, wattrib.height);
}
static void client_get_desktop(ObClient *self)
@ -1511,12 +1539,12 @@ static void client_change_allowed_actions(ObClient *self)
else self->iconic = FALSE;
}
if (!(self->functions & OB_CLIENT_FUNC_FULLSCREEN) && self->fullscreen) {
if (self->frame) client_fullscreen(self, FALSE, TRUE);
if (self->frame) client_fullscreen(self, FALSE);
else self->fullscreen = FALSE;
}
if (!(self->functions & OB_CLIENT_FUNC_MAXIMIZE) && (self->max_horz ||
self->max_vert)) {
if (self->frame) client_maximize(self, FALSE, 0, TRUE);
if (self->frame) client_maximize(self, FALSE, 0);
else self->max_vert = self->max_horz = FALSE;
}
}
@ -2080,8 +2108,17 @@ gboolean client_normal(ObClient *self) {
self->type == OB_CLIENT_TYPE_SPLASH);
}
static void client_apply_startup_state(ObClient *self)
static void client_apply_startup_state(ObClient *self, gint x, gint y)
{
gboolean pos = FALSE; /* has the window's position been configured? */
gint ox, oy;
/* save the position, and set self->area for these to use */
ox = self->area.x;
oy = self->area.y;
self->area.x = x;
self->area.y = y;
/* these are in a carefully crafted order.. */
if (self->iconic) {
@ -2090,7 +2127,8 @@ static void client_apply_startup_state(ObClient *self)
}
if (self->fullscreen) {
self->fullscreen = FALSE;
client_fullscreen(self, TRUE, FALSE);
client_fullscreen(self, TRUE);
pos = TRUE;
}
if (self->undecorated) {
self->undecorated = FALSE;
@ -2107,13 +2145,24 @@ static void client_apply_startup_state(ObClient *self)
if (self->max_vert && self->max_horz) {
self->max_vert = self->max_horz = FALSE;
client_maximize(self, TRUE, 0, FALSE);
client_maximize(self, TRUE, 0);
pos = TRUE;
} else if (self->max_vert) {
self->max_vert = FALSE;
client_maximize(self, TRUE, 2, FALSE);
client_maximize(self, TRUE, 2);
pos = TRUE;
} else if (self->max_horz) {
self->max_horz = FALSE;
client_maximize(self, TRUE, 1, FALSE);
client_maximize(self, TRUE, 1);
pos = TRUE;
}
/* if the client didn't get positioned yet, then do so now */
if (!pos && (ox != x || oy != y)) {
/* use the saved position */
self->area.x = ox;
self->area.y = oy;
client_move(self, x, y);
}
/* nothing to do for the other states:
@ -2351,7 +2400,7 @@ void client_configure_full(ObClient *self, ObCorner anchor,
XFlush(ob_display);
}
void client_fullscreen(ObClient *self, gboolean fs, gboolean savearea)
void client_fullscreen(ObClient *self, gboolean fs)
{
gint x, y, w, h;
@ -2363,8 +2412,17 @@ void client_fullscreen(ObClient *self, gboolean fs, gboolean savearea)
client_calc_layer(self); /* and adjust out layer/stacking */
if (fs) {
if (savearea)
self->pre_fullscreen_area = self->area;
self->pre_fullscreen_area = self->area;
/* if the window is maximized, its area isn't all that meaningful.
save it's premax area instead. */
if (self->max_horz) {
self->pre_fullscreen_area.x = self->pre_max_area.x;
self->pre_fullscreen_area.width = self->pre_max_area.width;
}
if (self->max_vert) {
self->pre_fullscreen_area.y = self->pre_max_area.y;
self->pre_fullscreen_area.height = self->pre_max_area.height;
}
/* these are not actually used cuz client_configure will set them
as appropriate when the window is fullscreened */
@ -2473,7 +2531,7 @@ void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
client_iconify_recursive(self, iconic, curdesk);
}
void client_maximize(ObClient *self, gboolean max, gint dir, gboolean savearea)
void client_maximize(ObClient *self, gboolean max, gint dir)
{
gint x, y, w, h;
@ -2499,17 +2557,15 @@ void client_maximize(ObClient *self, gboolean max, gint dir, gboolean savearea)
h = self->area.height;
if (max) {
if (savearea) {
if ((dir == 0 || dir == 1) && !self->max_horz) { /* horz */
RECT_SET(self->pre_max_area,
self->area.x, self->pre_max_area.y,
self->area.width, self->pre_max_area.height);
}
if ((dir == 0 || dir == 2) && !self->max_vert) { /* vert */
RECT_SET(self->pre_max_area,
self->pre_max_area.x, self->area.y,
self->pre_max_area.width, self->area.height);
}
if ((dir == 0 || dir == 1) && !self->max_horz) { /* horz */
RECT_SET(self->pre_max_area,
self->area.x, self->pre_max_area.y,
self->area.width, self->pre_max_area.height);
}
if ((dir == 0 || dir == 2) && !self->max_vert) { /* vert */
RECT_SET(self->pre_max_area,
self->pre_max_area.x, self->area.y,
self->pre_max_area.width, self->area.height);
}
} else {
Rect *a;
@ -2857,23 +2913,23 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
if (max_horz != self->max_horz && max_vert != self->max_vert) {
/* toggling both */
if (max_horz == max_vert) { /* both going the same way */
client_maximize(self, max_horz, 0, TRUE);
client_maximize(self, max_horz, 0);
} else {
client_maximize(self, max_horz, 1, TRUE);
client_maximize(self, max_vert, 2, TRUE);
client_maximize(self, max_horz, 1);
client_maximize(self, max_vert, 2);
}
} else {
/* toggling one */
if (max_horz != self->max_horz)
client_maximize(self, max_horz, 1, TRUE);
client_maximize(self, max_horz, 1);
else
client_maximize(self, max_vert, 2, TRUE);
client_maximize(self, max_vert, 2);
}
}
/* change fullscreen state before shading, as it will affect if the window
can shade or not */
if (fullscreen != self->fullscreen)
client_fullscreen(self, fullscreen, TRUE);
client_fullscreen(self, fullscreen);
if (shaded != self->shaded)
client_shade(self, shaded);
if (undecorated != self->undecorated)

View file

@ -397,12 +397,8 @@ void client_move_onscreen(ObClient *self, gboolean rude);
/*! Fullscreen's or unfullscreen's the client window
@param fs true if the window should be made fullscreen; false if it should
be returned to normal state.
@param savearea true to have the client's current size and position saved;
otherwise, they are not. You should not save when mapping a
new window that is set to fullscreen. This has no effect
when restoring a window from fullscreen.
*/
void client_fullscreen(ObClient *self, gboolean fs, gboolean savearea);
void client_fullscreen(ObClient *self, gboolean fs);
/*! Iconifies or uniconifies the client window
@param iconic true if the window should be iconified; false if it should be
@ -417,13 +413,8 @@ void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk);
@param max true if the window should be maximized; false if it should be
returned to normal size.
@param dir 0 to set both horz and vert, 1 to set horz, 2 to set vert.
@param savearea true to have the client's current size and position saved;
otherwise, they are not. You should not save when mapping a
new window that is set to fullscreen. This has no effect
when unmaximizing a window.
*/
void client_maximize(ObClient *self, gboolean max, gint dir,
gboolean savearea);
void client_maximize(ObClient *self, gboolean max, gint dir);
/*! Shades or unshades the client window
@param shade true if the window should be shaded; false if it should be