From: Dana Jansens Date: Thu, 24 May 2007 12:48:28 +0000 (+0000) Subject: merge r6768-6807 from trunk X-Git-Tag: openbox-3_3_992-RELEASE~2 X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=aa84dfad5491dffd02234445c24f8e2bc3f0c1d5;p=dana%2Fopenbox.git merge r6768-6807 from trunk --- diff --git a/data/rc.xml b/data/rc.xml index a0d72d3e..2f458937 100644 --- a/data/rc.xml +++ b/data/rc.xml @@ -88,14 +88,20 @@ + during a session + + these are default values to use when other ones are not already set + by other applications, or saved in your session + + use obconf if you want to change these without having to log out + and back in --> 4 1 - desktop one - desktop two - desktop three - desktop four + @@ -502,68 +508,77 @@ yes - - + # the name or the class can be set, or both. this is used to match + # windows when they appear. role can optionally be set as well, to + # further restrict your matches. + + # the name, class, and role use simple wildcard matching such as those + # used by a shell. you can use * to match any characters and ? to match + # any single character. - + # when multiple rules match a window, they will all be applied, in the + # order that they appear in this list + + + # each element can be left out or set to 'default' to specify to not + # change that attribute of the window yes - + # enable or disable window decorations no + # make the window shaded when it appears, or not - + # the position is only used if both an x and y coordinate are provided + # (and not set to 'default') center - + # a number like 50, or 'center' to center on screen 200 - + # a number like 50, or 'center' to center on screen 1 - + # specifies the monitor in a xinerama setup. + # 1 is the first head, or 'mouse' for wherever the mouse is yes - + # if the window should try be given focus when it appears. if this is set + # to yes it doesn't guarantee the window will be given focus. some + # restrictions may apply, but Openbox will try to 1 - + # 1 is the first desktop, 'all' for all desktops normal - + # 'above', 'normal', or 'below' no + # make the window iconified when it appears, or not no - + # asks to not be shown in pagers no - + # asks to not be shown in taskbars. window cycling actions will also + # skip past such windows yes + # make the window in fullscreen mode when it appears true - + # 'Horizontal', 'Vertical' or boolean (yes/no) + + # end of the example +--> - --> diff --git a/data/xsession/openbox-gnome-session.in b/data/xsession/openbox-gnome-session.in index cacfec4d..278ac6a8 100644 --- a/data/xsession/openbox-gnome-session.in +++ b/data/xsession/openbox-gnome-session.in @@ -1,5 +1,12 @@ #!/bin/sh +if test -n "$1"; then + echo "Syntax: openbox-gnome-session" + echo + echo "See the openbox-gnome-session(1) manpage for help." + exit +fi + # Run GNOME with Openbox as its window manager export WINDOW_MANAGER="@bindir@/openbox" exec gnome-session --choose-session=openbox-session "$@" diff --git a/data/xsession/openbox-kde-session.in b/data/xsession/openbox-kde-session.in index 0fe00940..16017260 100644 --- a/data/xsession/openbox-kde-session.in +++ b/data/xsession/openbox-kde-session.in @@ -1,5 +1,12 @@ #!/bin/sh +if test -n "$1"; then + echo "Syntax: openbox-kde-session" + echo + echo "See the openbox-kde-session(1) manpage for help." + exit +fi + # Run KDE with Openbox as its window manager export KDEWM="@bindir@/openbox" exec startkde "$@" diff --git a/data/xsession/openbox-session.in b/data/xsession/openbox-session.in index b3f1c057..cc2169f4 100644 --- a/data/xsession/openbox-session.in +++ b/data/xsession/openbox-session.in @@ -1,5 +1,12 @@ #!/bin/sh +if test -n "$1"; then + echo "Syntax: openbox-session" + echo + echo "See the openbox-session(1) manpage for help." + exit +fi + AUTOSTART="$HOME/.config/openbox/autostart.sh" GLOBALAUTOSTART="@configdir@/openbox/autostart.sh" diff --git a/doc/openbox-gnome-session.1.in b/doc/openbox-gnome-session.1.in index a1e0b471..f38c9bf6 100644 --- a/doc/openbox-gnome-session.1.in +++ b/doc/openbox-gnome-session.1.in @@ -6,6 +6,9 @@ openbox-gnome-session \(em Run a GNOME session with Openbox as the window manage .PP \fBopenbox-gnome-session\fR runs a GNOME session with Openbox as the window manager. +.PP +\fBopenbox-gnome-session\fR does not take any command line +arguments. .SH "SEE ALSO" .PP openbox(1), openbox-kde-session(1), openbox-session(1). @@ -16,4 +19,4 @@ The program's full documentation is available on the website: .PP Please report bugs to: \fBhttp://bugzilla.icculus.org/ \fP -.\" created by instant / docbook-to-man, Tue 22 May 2007, 00:06 +.\" created by instant / docbook-to-man, Wed 23 May 2007, 14:03 diff --git a/doc/openbox-gnome-session.1.sgml b/doc/openbox-gnome-session.1.sgml index 0cf804e1..c72865a7 100644 --- a/doc/openbox-gnome-session.1.sgml +++ b/doc/openbox-gnome-session.1.sgml @@ -38,6 +38,9 @@ manpage.1: manpage.sgml &dhpackage; runs a GNOME session with Openbox as the window manager. + + &dhpackage; does not take any command line + arguments. SEE ALSO diff --git a/doc/openbox-kde-session.1.in b/doc/openbox-kde-session.1.in index 2c21e0b6..d46d14b4 100644 --- a/doc/openbox-kde-session.1.in +++ b/doc/openbox-kde-session.1.in @@ -6,6 +6,9 @@ openbox-kde-session \(em Run a KDE session with Openbox as the window manager .PP \fBopenbox-kde-session\fR runs a KDE session with Openbox as the window manager. +.PP +\fBopenbox-kde-session\fR does not take any command line +arguments. .SH "SEE ALSO" .PP openbox(1), openbox-gnome-session(1), openbox-session(1). @@ -16,4 +19,4 @@ The program's full documentation is available on the website: .PP Please report bugs to: \fBhttp://bugzilla.icculus.org/ \fP -.\" created by instant / docbook-to-man, Tue 22 May 2007, 00:06 +.\" created by instant / docbook-to-man, Wed 23 May 2007, 14:03 diff --git a/doc/openbox-kde-session.1.sgml b/doc/openbox-kde-session.1.sgml index 33cf5d52..e4f049db 100644 --- a/doc/openbox-kde-session.1.sgml +++ b/doc/openbox-kde-session.1.sgml @@ -38,6 +38,9 @@ manpage.1: manpage.sgml &dhpackage; runs a KDE session with Openbox as the window manager. + + &dhpackage; does not take any command line + arguments. SEE ALSO diff --git a/doc/openbox-session.1.in b/doc/openbox-session.1.in index 2d242f93..26232474 100644 --- a/doc/openbox-session.1.in +++ b/doc/openbox-session.1.in @@ -8,6 +8,9 @@ openbox-session \(em Runs an Openbox session without any session manager. any session manager. Without a session manager, you will not be able to save your state from one log in to the next. .PP +\fBopenbox-session\fR does not take any command line +arguments. +.PP On log in, \fBopenbox-session\fR will run the ~/.config/openbox/autostart.sh script if it exists, and will run the system-wide script @configdir@/openbox/autostart.sh otherwise. You may @@ -36,4 +39,4 @@ The program's full documentation is available on the website: .PP Please report bugs to: \fBhttp://bugzilla.icculus.org/ \fP -.\" created by instant / docbook-to-man, Tue 22 May 2007, 00:06 +.\" created by instant / docbook-to-man, Wed 23 May 2007, 14:03 diff --git a/doc/openbox-session.1.sgml b/doc/openbox-session.1.sgml index e4df8a1f..3c31755e 100644 --- a/doc/openbox-session.1.sgml +++ b/doc/openbox-session.1.sgml @@ -40,6 +40,9 @@ manpage.1: manpage.sgml any session manager. Without a session manager, you will not be able to save your state from one log in to the next. + &dhpackage; does not take any command line + arguments. + On log in, &dhpackage; will run the ~/.config/openbox/autostart.sh script if it exists, and will run the system-wide script @configdir@/openbox/autostart.sh otherwise. You may diff --git a/doc/rc-mouse-focus.xml b/doc/rc-mouse-focus.xml index c5afcc26..0685257c 100644 --- a/doc/rc-mouse-focus.xml +++ b/doc/rc-mouse-focus.xml @@ -88,14 +88,20 @@ + during a session + + these are default values to use when other ones are not already set + by other applications, or saved in your session + + use obconf if you want to change these without having to log out + and back in --> 4 1 - desktop one - desktop two - desktop three - desktop four + @@ -528,63 +534,77 @@ yes - - + # the name or the class can be set, or both. this is used to match + # windows when they appear. role can optionally be set as well, to + # further restrict your matches. + + # the name, class, and role use simple wildcard matching such as those + # used by a shell. you can use * to match any characters and ? to match + # any single character. - + # when multiple rules match a window, they will all be applied, in the + # order that they appear in this list + + + # each element can be left out or set to 'default' to specify to not + # change that attribute of the window yes + # enable or disable window decorations no + # make the window shaded when it appears, or not - + # the position is only used if both an x and y coordinate are provided + # (and not set to 'default') center - + # a number like 50, or 'center' to center on screen 200 - + # a number like 50, or 'center' to center on screen 1 - + # specifies the monitor in a xinerama setup. + # 1 is the first head, or 'mouse' for wherever the mouse is yes - + # if the window should try be given focus when it appears. if this is set + # to yes it doesn't guarantee the window will be given focus. some + # restrictions may apply, but Openbox will try to 1 - + # 1 is the first desktop, 'all' for all desktops normal - + # 'above', 'normal', or 'below' no + # make the window iconified when it appears, or not no - + # asks to not be shown in pagers no - + # asks to not be shown in taskbars. window cycling actions will also + # skip past such windows yes + # make the window in fullscreen mode when it appears true - + # 'Horizontal', 'Vertical' or boolean (yes/no) + + # end of the example +--> - --> diff --git a/openbox/action.c b/openbox/action.c index f1066979..85d84798 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -47,18 +47,17 @@ static void client_action_end(union ActionData *data) { if (config_focus_follow) if (data->any.context != OB_FRAME_CONTEXT_CLIENT) { - if (!data->any.button && data->any.c) { + if (!data->any.button && data->any.c) event_ignore_all_queued_enters(); - } else { - ObClient *c; - - /* usually this is sorta redundant, but with a press action - that moves windows our from under the cursor, the enter - event will come as a GrabNotify which is ignored, so this - makes a fake enter event - */ - if ((c = client_under_pointer())) - event_enter_client(c); + else { + /* we USED to create a fake enter event here, so that when you + used a Press context, and the button was still down, + you could still get enter events that weren't + NotifyWhileGrabbed. + + only problem with this is that then the resulting focus + change events can ALSO be NotifyWhileGrabbed. And that is + bad. So, don't create fake enter events anymore. */ } } } diff --git a/openbox/client.c b/openbox/client.c index 68dfedce..2a41ab8d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -735,11 +735,13 @@ static ObAppSettings *client_get_settings_state(ObClient *self) if (app->name && !g_pattern_match(app->name, strlen(self->name), self->name, NULL)) match = FALSE; - if (app->class && - !g_pattern_match(app->class, strlen(self->class),self->class,NULL)) + else if (app->class && + !g_pattern_match(app->class, + strlen(self->class), self->class, NULL)) match = FALSE; - if (app->role && - !g_pattern_match(app->role, strlen(self->role), self->role, NULL)) + else if (app->role && + !g_pattern_match(app->role, + strlen(self->role), self->role, NULL)) match = FALSE; if (match) { @@ -751,46 +753,44 @@ static ObAppSettings *client_get_settings_state(ObClient *self) } } - 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->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_horz = !!settings->max_horz; + if (settings->max_vert != -1) + self->max_vert = !!settings->max_vert; + if (settings->max_horz != -1) + self->max_horz = !!settings->max_horz; - if (settings->fullscreen != -1) - self->fullscreen = !!settings->fullscreen; + if (settings->fullscreen != -1) + self->fullscreen = !!settings->fullscreen; - if (settings->desktop) { - if (settings->desktop == DESKTOP_ALL) - self->desktop = settings->desktop; - else if (settings->desktop > 0 && - settings->desktop <= screen_num_desktops) - self->desktop = settings->desktop - 1; - } + if (settings->desktop) { + if (settings->desktop == DESKTOP_ALL) + self->desktop = settings->desktop; + else if (settings->desktop > 0 && + settings->desktop <= screen_num_desktops) + self->desktop = settings->desktop - 1; + } - 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; - } + 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; } @@ -962,16 +962,13 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, * xterm -geometry resolution-width/2 will work fine. Trying to * place it completely offscreen will be handled in the above code. * Sorry for this confused comment, i am tired. */ - if (fw <= mon_a->width) { - if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x; - if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width) - *x = mon_a->x + mon_a->width - fw; - } - if (fh <= mon_a->height) { - if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y; - if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height) - *y = mon_a->y + mon_a->height - fh; - } + if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x; + if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width) + *x = mon_a->x + MAX(0, mon_a->width - fw); + + if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y; + if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height) + *y = mon_a->y + MAX(0, mon_a->height - fh); /* get where the client should be */ frame_frame_gravity(self->frame, x, y, w, h); @@ -1541,7 +1538,6 @@ void client_update_normal_hints(ObClient *self) { XSizeHints size; glong ret; - gint oldgravity = self->gravity; /* defaults */ self->min_ratio = 0.0f; @@ -1558,19 +1554,8 @@ void client_update_normal_hints(ObClient *self) */ self->positioned = (size.flags & (PPosition|USPosition)); - if (size.flags & PWinGravity) { + if (size.flags & PWinGravity) self->gravity = size.win_gravity; - - /* if the client has a frame, i.e. has already been mapped and - is changing its gravity */ - if (self->frame && self->gravity != oldgravity) { - /* move our idea of the client's position based on its new - gravity */ - client_convert_gravity(self, oldgravity, - &self->area.x, &self->area.y, - self->area.width, self->area.height); - } - } if (size.flags & PAspect) { if (size.min_aspect.y) @@ -1635,14 +1620,16 @@ void client_setup_decor_and_functions(ObClient *self) case OB_CLIENT_TYPE_DIALOG: case OB_CLIENT_TYPE_UTILITY: - /* these windows cannot be maximized */ - self->functions &= ~OB_CLIENT_FUNC_MAXIMIZE; + /* these windows don't have anything added or removed by default */ break; case OB_CLIENT_TYPE_MENU: case OB_CLIENT_TYPE_TOOLBAR: - /* these windows get less functionality */ - self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | OB_CLIENT_FUNC_RESIZE); + /* these windows can't iconify or maximize */ + self->decorations &= ~(OB_FRAME_DECOR_ICONIFY | + OB_FRAME_DECOR_MAXIMIZE); + self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | + OB_CLIENT_FUNC_MAXIMIZE); break; case OB_CLIENT_TYPE_SPLASH: @@ -1717,9 +1704,12 @@ void client_setup_decor_and_functions(ObClient *self) self->decorations &= ~OB_FRAME_DECOR_MAXIMIZE; } - if (self->max_horz && self->max_vert) + if (self->max_horz && self->max_vert) { + /* you can't resize fully maximized windows */ + self->functions &= ~OB_CLIENT_FUNC_RESIZE; /* kill the handle on fully maxed windows */ self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS); + } /* If there are no decorations to remove, don't allow the user to try toggle the state */ @@ -2286,6 +2276,7 @@ static void client_change_wm_state(ObClient *self) state[0] = self->wmstate; state[1] = None; PROP_SETA32(self->window, wm_state, wm_state, state, 2); + ob_debug("setting wm_state %d\n", self->wmstate); } } @@ -2377,10 +2368,10 @@ static ObStackingLayer calc_layer(ObClient *self) } else if ((self->fullscreen || /* No decorations and fills the monitor = oldskool fullscreen. - But not for undecorated windows, because the user can do that + But not for maximized windows. */ (self->decorations == 0 && - !self->undecorated && + !(self->max_horz && self->max_vert) && RECT_EQUAL(self->area, *screen_physical_area_monitor (client_monitor(self))))) && @@ -2446,13 +2437,13 @@ gboolean client_show(ObClient *self) if (client_should_show(self)) { frame_show(self->frame); show = TRUE; - } - /* 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); + /* 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); + } return show; } @@ -2475,13 +2466,13 @@ gboolean client_hide(ObClient *self) frame_hide(self->frame); hide = TRUE; - } - /* 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); + /* 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); + } return hide; } @@ -2489,12 +2480,6 @@ void client_showhide(ObClient *self) { if (!client_show(self)) client_hide(self); - - /* 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); } gboolean client_normal(ObClient *self) { @@ -2574,18 +2559,62 @@ static void client_apply_startup_state(ObClient *self) */ } -void client_convert_gravity(ObClient *self, gint gravity, gint *x, gint *y, - gint w, gint h) +void client_gravity_resize_w(ObClient *self, gint *x, gint oldw, gint neww) { - gint oldg = self->gravity; + /* these should be the current values. this is for when you're not moving, + just resizing */ + g_assert(*x == self->area.x); + g_assert(oldw == self->area.width); - /* get the frame's position from the requested stuff */ - self->gravity = gravity; - frame_client_gravity(self->frame, x, y, w, h); - self->gravity = oldg; + /* horizontal */ + switch (self->gravity) { + default: + case NorthWestGravity: + case WestGravity: + case SouthWestGravity: + case StaticGravity: + case ForgetGravity: + break; + case NorthGravity: + case CenterGravity: + case SouthGravity: + *x -= (neww - oldw) / 2; + break; + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + *x -= neww - oldw; + break; + } +} - /* get the client's position in its true gravity from that */ - frame_frame_gravity(self->frame, x, y, w, h); +void client_gravity_resize_h(ObClient *self, gint *y, gint oldh, gint newh) +{ + /* these should be the current values. this is for when you're not moving, + just resizing */ + g_assert(*y == self->area.y); + g_assert(oldh == self->area.height); + + /* vertical */ + switch (self->gravity) { + default: + case NorthWestGravity: + case NorthGravity: + case NorthEastGravity: + case StaticGravity: + case ForgetGravity: + break; + case WestGravity: + case CenterGravity: + case EastGravity: + *y -= (newh - oldh) / 2; + break; + case SouthWestGravity: + case SouthGravity: + case SouthEastGravity: + *y -= newh - oldh; + break; + } } void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, @@ -2597,7 +2626,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, /* make the frame recalculate its dimentions n shit without changing anything visible for real, this way the constraints below can work with the updated frame dimensions. */ - frame_adjust_area(self->frame, TRUE, TRUE, TRUE); + frame_adjust_area(self->frame, FALSE, TRUE, TRUE); /* work within the prefered sizes given by the window */ if (!(*w == self->area.width && *h == self->area.height)) { @@ -2701,7 +2730,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *h = a->height; user = FALSE; /* ignore if the client can't be moved/resized when it - is entering fullscreen */ + is fullscreening */ } else if (self->max_horz || self->max_vert) { Rect *a; guint i; @@ -2719,8 +2748,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *h = a->height - self->frame->size.top - self->frame->size.bottom; } - /* maximizing is not allowed if the user can't move+resize the window - */ + user = FALSE; /* ignore if the client can't be moved/resized when it + is maximizing */ } /* gets the client's position */ @@ -2788,11 +2817,15 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* find the frame's dimensions and move/resize it */ fmoved = moved; fresized = resized; + + /* if decorations changed, then readjust everything for the frame */ if (self->decorations != fdecor || self->max_horz != fhorz || self->max_vert != fvert) { fmoved = fresized = TRUE; } + + /* adjust the frame */ if (fmoved || fresized) frame_adjust_area(self->frame, fmoved, fresized, FALSE); diff --git a/openbox/client.h b/openbox/client.h index e66cf9e8..82a565f3 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -362,10 +362,24 @@ gboolean client_enter_focusable(ObClient *self); /* Returns if the window is focused */ gboolean client_focused(ObClient *self); -/*! Convery a position/size from a given gravity to the client's true gravity +/*! When the client is resized but not moved, figure out the new position + for it based on its gravity: + http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#id2512541 +*/ +void client_gravity_resize_w(ObClient *self, gint *x, gint oldw, gint neww); + +/*! When the client is resized but not moved, figure out the new position + for it based on its gravity: + http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#id2512541 +*/ +void client_gravity_resize_h(ObClient *self, gint *y, gint oldh, gint newh); + +/*! Convert a position/size from a given gravity to the client's true gravity, + when the client is only resizing (the reference point doesn't move) */ -void client_convert_gravity(ObClient *self, gint gravity, gint *x, gint *y, - gint w, gint h); +void client_convert_gravity_resize(ObClient *self, gint gravity, + gint *x, gint *y, + gint w, gint h); #define client_move(self, x, y) \ client_configure(self, x, y, self->area.width, self->area.height, TRUE, TRUE) diff --git a/openbox/client_list_menu.c b/openbox/client_list_menu.c index 77cfc193..e5ad17a3 100644 --- a/openbox/client_list_menu.c +++ b/openbox/client_list_menu.c @@ -136,33 +136,30 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data) ObMenu *menu = frame->menu; guint i; GSList *it, *next; + + menu_clear_entries(menu); + + while (desktop_menus) { + menu_free(desktop_menus->data); + desktop_menus = g_slist_delete_link(desktop_menus, desktop_menus); + } - it = desktop_menus; for (i = 0; i < screen_num_desktops; ++i) { - if (!it) { - ObMenu *submenu; - gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i); - DesktopData *data = g_new(DesktopData, 1); + ObMenu *submenu; + gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i); + DesktopData *data = g_new(DesktopData, 1); - data->desktop = i; - submenu = menu_new(name, screen_desktop_names[i], FALSE, data); - menu_set_update_func(submenu, desk_menu_update); - menu_set_execute_func(submenu, desk_menu_execute); - menu_set_destroy_func(submenu, desk_menu_destroy); + data->desktop = i; + submenu = menu_new(name, screen_desktop_names[i], FALSE, data); + menu_set_update_func(submenu, desk_menu_update); + menu_set_execute_func(submenu, desk_menu_execute); + menu_set_destroy_func(submenu, desk_menu_destroy); - menu_add_submenu(menu, i, name); + menu_add_submenu(menu, i, name); - g_free(name); + g_free(name); - desktop_menus = g_slist_append(desktop_menus, submenu); - } else - it = g_slist_next(it); - } - for (; it; it = next, ++i) { - next = g_slist_next(it); - menu_free(it->data); - desktop_menus = g_slist_delete_link(desktop_menus, it); - menu_entry_remove(menu_find_entry_id(menu, i)); + desktop_menus = g_slist_append(desktop_menus, submenu); } return TRUE; /* always show */ diff --git a/openbox/event.c b/openbox/event.c index d7c723d1..c19f7017 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -679,7 +679,7 @@ static void event_handle_root(XEvent *e) } } else if (msgtype == prop_atoms.net_number_of_desktops) { guint d = e->xclient.data.l[0]; - if (d > 0) + if (d > 0 && d <= 1000) screen_set_num_desktops(d); } else if (msgtype == prop_atoms.net_showing_desktop) { screen_show_desktop(e->xclient.data.l[0] != 0, NULL); @@ -1035,38 +1035,43 @@ static void event_handle_client(ObClient *client, XEvent *e) move = TRUE; } - /* don't allow clients to move shaded windows (fvwm does this) */ - if (client->shaded && (e->xconfigurerequest.value_mask & CWX || - e->xconfigurerequest.value_mask & CWY)) - { - e->xconfigurerequest.value_mask &= ~CWX; - e->xconfigurerequest.value_mask &= ~CWY; - - /* if the client tried to move and we aren't letting it then a - synthetic event is needed */ - move = TRUE; - } - if (e->xconfigurerequest.value_mask & CWX || e->xconfigurerequest.value_mask & CWY || e->xconfigurerequest.value_mask & CWWidth || e->xconfigurerequest.value_mask & CWHeight) { if (e->xconfigurerequest.value_mask & CWX) { - x = e->xconfigurerequest.x; + /* don't allow clients to move shaded windows (fvwm does this) + */ + if (!client->shaded) + x = e->xconfigurerequest.x; move = TRUE; } if (e->xconfigurerequest.value_mask & CWY) { - y = e->xconfigurerequest.y; + /* don't allow clients to move shaded windows (fvwm does this) + */ + if (!client->shaded) + y = e->xconfigurerequest.y; move = TRUE; } + if (e->xconfigurerequest.value_mask & CWWidth) { w = e->xconfigurerequest.width; resize = TRUE; + + /* if x was not given, then use gravity to figure out the new + x. the reference point should not be moved */ + if (!(e->xconfigurerequest.value_mask & CWX)) + client_gravity_resize_w(client, &x, client->area.width, w); } if (e->xconfigurerequest.value_mask & CWHeight) { h = e->xconfigurerequest.height; resize = TRUE; + + /* if y was not given, then use gravity to figure out the new + y. the reference point should not be moved */ + if (!(e->xconfigurerequest.value_mask & CWY)) + client_gravity_resize_h(client, &y, client->area.height,h); } } @@ -1276,12 +1281,12 @@ static void event_handle_client(ObClient *client, XEvent *e) prop_atoms.net_wm_moveresize_cancel) moveresize_end(TRUE); } else if (msgtype == prop_atoms.net_moveresize_window) { - gint grav, x, y, w, h; + gint ograv, x, y, w, h; + + ograv = client->gravity; if (e->xclient.data.l[0] & 0xff) - grav = e->xclient.data.l[0] & 0xff; - else - grav = client->gravity; + client->gravity = e->xclient.data.l[0] & 0xff; if (e->xclient.data.l[0] & 1 << 8) x = e->xclient.data.l[1]; @@ -1291,23 +1296,40 @@ static void event_handle_client(ObClient *client, XEvent *e) y = e->xclient.data.l[2]; else y = client->area.y; - if (e->xclient.data.l[0] & 1 << 10) + + if (e->xclient.data.l[0] & 1 << 10) { w = e->xclient.data.l[3]; + + /* if x was not given, then use gravity to figure out the new + x. the reference point should not be moved */ + if (!(e->xclient.data.l[0] & 1 << 8)) + client_gravity_resize_w(client, &x, client->area.width, w); + } else w = client->area.width; - if (e->xclient.data.l[0] & 1 << 11) + + if (e->xclient.data.l[0] & 1 << 11) { h = e->xclient.data.l[4]; + + /* if y was not given, then use gravity to figure out the new + y. the reference point should not be moved */ + if (!(e->xclient.data.l[0] & 1 << 9)) + client_gravity_resize_h(client, &y, client->area.height,h); + } else h = client->area.height; - ob_debug("MOVERESIZE x %d %d y %d %d\n", + ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)\n", e->xclient.data.l[0] & 1 << 8, x, - e->xclient.data.l[0] & 1 << 9, y); - client_convert_gravity(client, grav, &x, &y, w, h); + e->xclient.data.l[0] & 1 << 9, y, + client->gravity); + client_find_onscreen(client, &x, &y, w, h, FALSE); client_configure(client, x, y, w, h, FALSE, TRUE); + client->gravity = ograv; + /* ignore enter events caused by these like ob actions do */ event_ignore_all_queued_enters(); } else if (msgtype == prop_atoms.net_restack_window) { diff --git a/openbox/frame.c b/openbox/frame.c index 3aa97215..ba84d474 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -251,6 +251,7 @@ void frame_show(ObFrame *self) if (!self->visible) { self->visible = TRUE; XMapWindow(ob_display, self->client->window); + XMapWindow(ob_display, self->plate); XMapWindow(ob_display, self->window); } } @@ -261,6 +262,10 @@ void frame_hide(ObFrame *self) self->visible = FALSE; if (!frame_iconify_animating(self)) XUnmapWindow(ob_display, self->window); + /* unmap the plate along with the client. some people (libwnck) look + to see if it is unmapped when the client is iconified, for whatever + reason. so let's play along... */ + XUnmapWindow(ob_display, self->plate); /* we unmap the client itself so that we can get MapRequest events, and because the ICCCM tells us to! */ XUnmapWindow(ob_display, self->client->window); @@ -696,7 +701,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->client->area.height + self->size.top + self->size.bottom)); - if (moved || resized) { + if ((moved || resized) && !fake) { /* find the new coordinates, done after setting the frame.size, for frame_client_gravity. */ self->area.x = self->client->area.x; @@ -751,16 +756,24 @@ static void frame_adjust_cursors(ObFrame *self) { if ((self->functions & OB_CLIENT_FUNC_RESIZE) != (self->client->functions & OB_CLIENT_FUNC_RESIZE) || - ((self->max_horz && self->max_vert) != - (self->client->max_horz && self->client->max_vert))) + self->max_horz != self->client->max_horz || + self->max_vert != self->client->max_vert) { gboolean r = (self->client->functions & OB_CLIENT_FUNC_RESIZE) && !(self->client->max_horz && self->client->max_vert); + gboolean topbot = !self->client->max_vert; XSetWindowAttributes a; - a.cursor = ob_cursor(r ? OB_CURSOR_NORTH : OB_CURSOR_NONE); + /* these ones turn off when max vert */ + a.cursor = ob_cursor(r && topbot ? OB_CURSOR_NORTH : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->topresize, CWCursor, &a); XChangeWindowAttributes(ob_display, self->titletop, CWCursor, &a); + a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->handle, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->handletop, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->handlebottom, CWCursor, &a); + + /* these ones don't */ a.cursor = ob_cursor(r ? OB_CURSOR_NORTHWEST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->tltresize, CWCursor, &a); XChangeWindowAttributes(ob_display, self->tllresize, CWCursor, &a); @@ -775,10 +788,6 @@ static void frame_adjust_cursors(ObFrame *self) XChangeWindowAttributes(ob_display, self->left, CWCursor, &a); a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->right, CWCursor, &a); - a.cursor = ob_cursor(r ? OB_CURSOR_SOUTH : OB_CURSOR_NONE); - XChangeWindowAttributes(ob_display, self->handle, CWCursor, &a); - XChangeWindowAttributes(ob_display, self->handletop, CWCursor, &a); - XChangeWindowAttributes(ob_display, self->handlebottom, CWCursor, &a); a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->lgrip, CWCursor, &a); XChangeWindowAttributes(ob_display, self->handleleft, CWCursor, &a); @@ -1259,6 +1268,10 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y) context */ return OB_FRAME_CONTEXT_TITLEBAR; } + else if (self->max_vert && + (win == self->titletop || win == self->topresize)) + /* can't resize vertically when max vert */ + return OB_FRAME_CONTEXT_TITLEBAR; if (win == self->window) return OB_FRAME_CONTEXT_FRAME; if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR; @@ -1311,17 +1324,20 @@ void frame_client_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h) case NorthGravity: case SouthGravity: case CenterGravity: - *x -= (self->size.left + w) / 2; + /* the middle of the client will be the middle of the frame */ + *x -= (self->size.right - self->size.left) / 2; break; case NorthEastGravity: case SouthEastGravity: case EastGravity: - *x -= (self->size.left + self->size.right + w) - 1; + /* the right side of the client will be the right side of the frame */ + *x -= self->size.right + self->size.left; break; case ForgetGravity: case StaticGravity: + /* the client's position won't move */ *x -= self->size.left; break; } @@ -1337,17 +1353,20 @@ void frame_client_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h) case CenterGravity: case EastGravity: case WestGravity: - *y -= (self->size.top + h) / 2; + /* the middle of the client will be the middle of the frame */ + *y -= (self->size.bottom - self->size.top) / 2; break; case SouthWestGravity: case SouthEastGravity: case SouthGravity: - *y -= (self->size.top + self->size.bottom + h) - 1; + /* the bottom of the client will be the bottom of the frame */ + *y -= self->size.bottom + self->size.top; break; case ForgetGravity: case StaticGravity: + /* the client's position won't move */ *y -= self->size.top; break; } @@ -1365,15 +1384,18 @@ void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h) case NorthGravity: case CenterGravity: case SouthGravity: - *x += (self->size.left + w) / 2; + /* the middle of the client will be the middle of the frame */ + *x += (self->size.right - self->size.left) / 2; break; case NorthEastGravity: case EastGravity: case SouthEastGravity: - *x += (self->size.left + self->size.right + w) - 1; + /* the right side of the client will be the right side of the frame */ + *x += self->size.right + self->size.left; break; case StaticGravity: case ForgetGravity: + /* the client's position won't move */ *x += self->size.left; break; } @@ -1388,15 +1410,18 @@ void frame_frame_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h) case WestGravity: case CenterGravity: case EastGravity: - *y += (self->size.top + h) / 2; + /* the middle of the client will be the middle of the frame */ + *y += (self->size.bottom - self->size.top) / 2; break; case SouthWestGravity: case SouthGravity: case SouthEastGravity: - *y += (self->size.top + self->size.bottom + h) - 1; + /* the bottom of the client will be the bottom of the frame */ + *y += self->size.bottom + self->size.top; break; case StaticGravity: case ForgetGravity: + /* the client's position won't move */ *y += self->size.top; break; } diff --git a/openbox/keyboard.c b/openbox/keyboard.c index ab9d05b0..2c60ac3d 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -78,11 +78,11 @@ static gboolean chain_timeout(gpointer data) static void set_curpos(KeyBindingTree *newpos) { - if (curpos != newpos) { - grab_keys(FALSE); - curpos = newpos; - grab_keys(TRUE); - } + if (curpos == newpos) return; + + grab_keys(FALSE); + curpos = newpos; + grab_keys(TRUE); if (curpos != NULL) { gchar *text = NULL; diff --git a/openbox/screen.c b/openbox/screen.c index 4ad46af7..c566a908 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -50,13 +50,16 @@ SubstructureRedirectMask | FocusChangeMask | \ ButtonPressMask | ButtonReleaseMask | ButtonMotionMask) +static gboolean screen_validate_layout(ObDesktopLayout *l); +static gboolean replace_wm(); + guint screen_num_desktops; guint screen_num_monitors; guint screen_desktop; guint screen_last_desktop; Size screen_physical_size; gboolean screen_showing_desktop; -DesktopLayout screen_desktop_layout; +ObDesktopLayout screen_desktop_layout; gchar **screen_desktop_names; Window screen_support_win; Time screen_desktop_user_time = CurrentTime; @@ -304,10 +307,9 @@ gboolean screen_annex() void screen_startup(gboolean reconfig) { - guint i, numnames; - gchar **names; - GSList *it; + gchar **names = NULL; guint32 d; + gboolean namesexist = FALSE; desktop_cycle_popup = pager_popup_new(FALSE); pager_popup_height(desktop_cycle_popup, POPUP_HEIGHT); @@ -323,21 +325,48 @@ void screen_startup(gboolean reconfig) /* get the initial size */ screen_resize(); - /* get the desktop names */ - numnames = g_slist_length(config_desktops_names); - names = g_new(gchar*, numnames + 1); - names[numnames] = NULL; - for (i = 0, it = config_desktops_names; it; ++i, it = g_slist_next(it)) - names[i] = g_strdup(it->data); + /* have names already been set for the desktops? */ + if (PROP_GETSS(RootWindow(ob_display, ob_screen), + net_desktop_names, utf8, &names)) + { + g_strfreev(names); + namesexist = TRUE; + } + + /* if names don't exist and we have session names, set those. + do this stuff BEFORE setting the number of desktops, because that + will create default names for them + */ + if (!namesexist && session_desktop_names != NULL) { + guint i, numnames; + GSList *it; - /* set the root window property */ - PROP_SETSS(RootWindow(ob_display, ob_screen), net_desktop_names,names); + /* get the desktop names */ + numnames = g_slist_length(session_desktop_names); + names = g_new(gchar*, numnames + 1); + names[numnames] = NULL; + for (i = 0, it = session_desktop_names; it; ++i, it = g_slist_next(it)) + names[i] = g_strdup(it->data); - g_strfreev(names); + /* set the root window property */ + PROP_SETSS(RootWindow(ob_display, ob_screen), net_desktop_names,names); - /* set the number of desktops */ + g_strfreev(names); + } + + /* set the number of desktops, if it's not already set. + + this will also set the default names from the config file up for + desktops that don't have names yet */ screen_num_desktops = 0; - screen_set_num_desktops(config_desktops_num); + if (PROP_GET32(RootWindow(ob_display, ob_screen), + net_number_of_desktops, cardinal, &d)) + screen_set_num_desktops(d); + /* restore from session if possible */ + else if (session_num_desktops) + screen_set_num_desktops(session_num_desktops); + else + screen_set_num_desktops(config_desktops_num); /* start on the current desktop when a wm was already running */ if (PROP_GET32(RootWindow(ob_display, ob_screen), @@ -357,7 +386,13 @@ void screen_startup(gboolean reconfig) PROP_SET32(RootWindow(ob_display, ob_screen), net_showing_desktop, cardinal, screen_showing_desktop); - screen_update_layout(); + if (session_desktop_layout_present && + screen_validate_layout(&session_desktop_layout)) + { + screen_desktop_layout = session_desktop_layout; + } + else + screen_update_layout(); } void screen_shutdown(gboolean reconfig) @@ -787,95 +822,90 @@ show_cycle_dialog: return ret; } +static gboolean screen_validate_layout(ObDesktopLayout *l) +{ + if (l->columns == 0 && l->rows == 0) /* both 0's is bad data.. */ + return FALSE; + + /* fill in a zero rows/columns */ + if (l->columns == 0) { + l->columns = screen_num_desktops / l->rows; + if (l->rows * l->columns < screen_num_desktops) + l->columns++; + if (l->rows * l->columns >= screen_num_desktops + l->columns) + l->rows--; + } else if (l->rows == 0) { + l->rows = screen_num_desktops / l->columns; + if (l->columns * l->rows < screen_num_desktops) + l->rows++; + if (l->columns * l->rows >= screen_num_desktops + l->rows) + l->columns--; + } + + /* bounds checking */ + if (l->orientation == OB_ORIENTATION_HORZ) { + l->columns = MIN(screen_num_desktops, l->columns); + l->rows = MIN(l->rows, + (screen_num_desktops + l->columns - 1) / l->columns); + l->columns = screen_num_desktops / l->rows + + !!(screen_num_desktops % l->rows); + } else { + l->rows = MIN(screen_num_desktops, l->rows); + l->columns = MIN(l->columns, + (screen_num_desktops + l->rows - 1) / l->rows); + l->rows = screen_num_desktops / l->columns + + !!(screen_num_desktops % l->columns); + } + return TRUE; +} + void screen_update_layout() + { - ObOrientation orient; - ObCorner corner; - guint rows; - guint cols; + ObDesktopLayout l; guint32 *data; guint num; - gboolean valid = FALSE; + + screen_desktop_layout.orientation = OB_ORIENTATION_HORZ; + screen_desktop_layout.start_corner = OB_CORNER_TOPLEFT; + screen_desktop_layout.rows = 1; + screen_desktop_layout.columns = screen_num_desktops; if (PROP_GETA32(RootWindow(ob_display, ob_screen), net_desktop_layout, cardinal, &data, &num)) { if (num == 3 || num == 4) { - + if (data[0] == prop_atoms.net_wm_orientation_vert) - orient = OB_ORIENTATION_VERT; + l.orientation = OB_ORIENTATION_VERT; else if (data[0] == prop_atoms.net_wm_orientation_horz) - orient = OB_ORIENTATION_HORZ; + l.orientation = OB_ORIENTATION_HORZ; else - goto screen_update_layout_bail; + return; if (num < 4) - corner = OB_CORNER_TOPLEFT; + l.start_corner = OB_CORNER_TOPLEFT; else { if (data[3] == prop_atoms.net_wm_topleft) - corner = OB_CORNER_TOPLEFT; + l.start_corner = OB_CORNER_TOPLEFT; else if (data[3] == prop_atoms.net_wm_topright) - corner = OB_CORNER_TOPRIGHT; + l.start_corner = OB_CORNER_TOPRIGHT; else if (data[3] == prop_atoms.net_wm_bottomright) - corner = OB_CORNER_BOTTOMRIGHT; + l.start_corner = OB_CORNER_BOTTOMRIGHT; else if (data[3] == prop_atoms.net_wm_bottomleft) - corner = OB_CORNER_BOTTOMLEFT; + l.start_corner = OB_CORNER_BOTTOMLEFT; else - goto screen_update_layout_bail; + return; } - cols = data[1]; - rows = data[2]; + l.columns = data[1]; + l.rows = data[2]; - /* fill in a zero rows/columns */ - if ((cols == 0 && rows == 0)) { /* both 0's is bad data.. */ - goto screen_update_layout_bail; - } else { - if (cols == 0) { - cols = screen_num_desktops / rows; - if (rows * cols < screen_num_desktops) - cols++; - if (rows * cols >= screen_num_desktops + cols) - rows--; - } else if (rows == 0) { - rows = screen_num_desktops / cols; - if (cols * rows < screen_num_desktops) - rows++; - if (cols * rows >= screen_num_desktops + rows) - cols--; - } - } + if (screen_validate_layout(&l)) + screen_desktop_layout = l; - /* bounds checking */ - if (orient == OB_ORIENTATION_HORZ) { - cols = MIN(screen_num_desktops, cols); - rows = MIN(rows, (screen_num_desktops + cols - 1) / cols); - cols = screen_num_desktops / rows + - !!(screen_num_desktops % rows); - } else { - rows = MIN(screen_num_desktops, rows); - cols = MIN(cols, (screen_num_desktops + rows - 1) / rows); - rows = screen_num_desktops / cols + - !!(screen_num_desktops % cols); - } - - valid = TRUE; + g_free(data); } - screen_update_layout_bail: - g_free(data); - } - - if (!valid) { - /* defaults */ - orient = OB_ORIENTATION_HORZ; - corner = OB_CORNER_TOPLEFT; - rows = 1; - cols = screen_num_desktops; } - - screen_desktop_layout.orientation = orient; - screen_desktop_layout.start_corner = corner; - screen_desktop_layout.rows = rows; - screen_desktop_layout.columns = cols; } void screen_update_desktop_names() @@ -892,11 +922,29 @@ void screen_update_desktop_names() else i = 0; if (i < screen_num_desktops) { + GSList *it; + screen_desktop_names = g_renew(gchar*, screen_desktop_names, screen_num_desktops + 1); screen_desktop_names[screen_num_desktops] = NULL; - for (; i < screen_num_desktops; ++i) - screen_desktop_names[i] = g_strdup_printf("desktop %i", i + 1); + + it = g_slist_nth(config_desktops_names, i); + + for (; i < screen_num_desktops; ++i) { + if (it) + /* use the names from the config file when possible */ + screen_desktop_names[i] = g_strdup(it->data); + else + /* make up a nice name if it's not though */ + screen_desktop_names[i] = g_strdup_printf(_("desktop %i"), + i + 1); + if (it) it = g_slist_next(it); + } + + /* if we changed any names, then set the root property so we can + all agree on the names */ + PROP_SETSS(RootWindow(ob_display, ob_screen), net_desktop_names, + screen_desktop_names); } /* resize the pager for these names */ diff --git a/openbox/screen.h b/openbox/screen.h index bd96ab20..b40776df 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -41,13 +41,13 @@ extern Window screen_support_win; /*! The last time at which the user changed desktops */ extern Time screen_desktop_user_time; -typedef struct DesktopLayout { +typedef struct ObDesktopLayout { ObOrientation orientation; ObCorner start_corner; guint rows; guint columns; -} DesktopLayout; -extern DesktopLayout screen_desktop_layout; +} ObDesktopLayout; +extern ObDesktopLayout screen_desktop_layout; /*! An array of gchar*'s which are desktop names in UTF-8 format */ extern gchar **screen_desktop_names; diff --git a/openbox/session.c b/openbox/session.c index 969d2f00..5918aa13 100644 --- a/openbox/session.c +++ b/openbox/session.c @@ -24,6 +24,10 @@ struct _ObClient; GList *session_saved_state = NULL; gint session_desktop = -1; +gint session_num_desktops = 0; +gboolean session_desktop_layout_present = FALSE; +ObDesktopLayout session_desktop_layout; +GSList *session_desktop_names = NULL; #ifndef USE_SM void session_startup(gint argc, gchar **argv) {} @@ -36,7 +40,6 @@ GList* session_state_find(struct _ObClient *c) { return NULL; } #include "client.h" #include "prop.h" #include "focus.h" -#include "screen.h" #include "gettext.h" #include "parser/parse.h" @@ -363,6 +366,10 @@ static void session_setup_restart_command() static ObSMSaveData *sm_save_get_data() { ObSMSaveData *savedata = g_new0(ObSMSaveData, 1); + /* save the active desktop and client. + we don't bother to preemptively save the other desktop state like + number and names of desktops, cuz those shouldn't be changing during + the save.. */ savedata->focus_client = focus_client; savedata->desktop = screen_desktop; return savedata; @@ -449,6 +456,28 @@ static gboolean session_save_to_file(const ObSMSaveData *savedata) fprintf(f, "%d\n", savedata->desktop); + fprintf(f, "%d\n", screen_num_desktops); + + fprintf(f, "\n"); + fprintf(f, " %d\n", + screen_desktop_layout.orientation); + fprintf(f, " %d\n", + screen_desktop_layout.start_corner); + fprintf(f, " %d\n", + screen_desktop_layout.columns); + fprintf(f, " %d\n", + screen_desktop_layout.rows); + fprintf(f, "\n"); + + if (screen_desktop_names) { + gint i; + + fprintf(f, "\n"); + for (i = 0; screen_desktop_names[i]; ++i) + fprintf(f, " %s\n", screen_desktop_names[i]); + fprintf(f, "\n"); + } + /* they are ordered top to bottom in stacking order */ for (it = stacking_list; it; it = g_list_next(it)) { gint prex, prey, prew, preh; @@ -580,14 +609,14 @@ static gboolean session_state_cmp(ObSessionState *s, ObClient *c) ob_debug_type(OB_DEBUG_SM, " client name: %s \n", c->name); ob_debug_type(OB_DEBUG_SM, " client class: %s \n", c->class); ob_debug_type(OB_DEBUG_SM, " client role: %s \n", c->role); - ob_debug_type(OB_DEBUG_SM, " client type: %s \n", c->type); + ob_debug_type(OB_DEBUG_SM, " client type: %d \n", c->type); ob_debug_type(OB_DEBUG_SM, " client command: %s \n", c->wm_command ? c->wm_command : "(null)"); ob_debug_type(OB_DEBUG_SM, " state id: %s \n", s->id); ob_debug_type(OB_DEBUG_SM, " state name: %s \n", s->name); ob_debug_type(OB_DEBUG_SM, " state class: %s \n", s->class); ob_debug_type(OB_DEBUG_SM, " state role: %s \n", s->role); - ob_debug_type(OB_DEBUG_SM, " state type: %s \n", s->type); + ob_debug_type(OB_DEBUG_SM, " state type: %d \n", s->type); ob_debug_type(OB_DEBUG_SM, " state command: %s \n", s->command ? s->command : "(null)"); @@ -624,7 +653,7 @@ GList* session_state_find(ObClient *c) static void session_load_file(const gchar *path) { xmlDocPtr doc; - xmlNodePtr node, n; + xmlNodePtr node, n, m; GList *it, *inext; if (!parse_load(path, "openbox_session", &doc, &node)) @@ -633,6 +662,31 @@ static void session_load_file(const gchar *path) if ((n = parse_find_node("desktop", node->children))) session_desktop = parse_int(doc, n); + if ((n = parse_find_node("numdesktops", node->children))) + session_num_desktops = parse_int(doc, n); + + if ((n = parse_find_node("desktoplayout", node->children))) { + /* make sure they are all there for it to be valid */ + if ((m = parse_find_node("orientation", n->children))) + session_desktop_layout.orientation = parse_int(doc, m); + if (m && (m = parse_find_node("startcorner", n->children))) + session_desktop_layout.start_corner = parse_int(doc, m); + if (m && (m = parse_find_node("columns", n->children))) + session_desktop_layout.columns = parse_int(doc, m); + if (m && (m = parse_find_node("rows", n->children))) + session_desktop_layout.rows = parse_int(doc, m); + session_desktop_layout_present = m != NULL; + } + + if ((n = parse_find_node("desktopnames", node->children))) { + for (m = parse_find_node("name", n->children); m; + m = parse_find_node("name", m->next)) + { + session_desktop_names = g_slist_append(session_desktop_names, + parse_string(doc, m)); + } + } + for (node = parse_find_node("window", node->children); node != NULL; node = parse_find_node("window", node->next)) { diff --git a/openbox/session.h b/openbox/session.h index 97e55a3b..b4ce6d91 100644 --- a/openbox/session.h +++ b/openbox/session.h @@ -20,6 +20,7 @@ #define __ob__session_h #include "client.h" +#include "screen.h" #include @@ -40,6 +41,10 @@ struct _ObSessionState { /*! The desktop being viewed when the session was saved. A valud of -1 means it was not saved */ extern gint session_desktop; +extern gint session_num_desktops; +extern gboolean session_desktop_layout_present; +extern ObDesktopLayout session_desktop_layout; +extern GSList *session_desktop_names; extern GList *session_saved_state; diff --git a/render/font.c b/render/font.c index 3755c1ff..48321aec 100644 --- a/render/font.c +++ b/render/font.c @@ -146,7 +146,19 @@ static void font_measure_full(const RrFont *f, const gchar *str, pango_layout_set_text(f->layout, str, -1); pango_layout_set_width(f->layout, -1); - pango_layout_get_pixel_extents(f->layout, NULL, &rect); + + /* pango_layout_get_pixel_extents lies! this is the right way to get the + size of the text's area */ + pango_layout_get_extents(f->layout, NULL, &rect); +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + /* pass the logical rect as the ink rect, this is on purpose so we get the + full area for the text */ + pango_extents_to_pixels(&rect, NULL); +#else + rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE; + rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE; +#endif *x = rect.width + ABS(shadow_x) + 4 /* we put a 2 px edge on each side */; *y = rect.height + ABS(shadow_y); } diff --git a/tests/grav.c b/tests/grav.c index 5aeed8bc..a8dcdc31 100644 --- a/tests/grav.c +++ b/tests/grav.c @@ -49,8 +49,10 @@ int main () { XMapWindow(display, win); XFlush(display); - XMoveResizeWindow(display, win, 960-1, 600-1, 600, 150); - /*XResizeWindow(display, win, 600, 150);*/ + XMoveResizeWindow(display, win, 1172-600, 668-150, 600, 150); + XFlush(display); + sleep(1); + XResizeWindow(display, win, 900, 275); XSelectInput(display, win, ExposureMask | StructureNotifyMask);