merge r6768-6807 from trunk
authorDana Jansens <danakj@orodu.net>
Thu, 24 May 2007 12:48:28 +0000 (12:48 +0000)
committerDana Jansens <danakj@orodu.net>
Thu, 24 May 2007 12:48:28 +0000 (12:48 +0000)
24 files changed:
data/rc.xml
data/xsession/openbox-gnome-session.in
data/xsession/openbox-kde-session.in
data/xsession/openbox-session.in
doc/openbox-gnome-session.1.in
doc/openbox-gnome-session.1.sgml
doc/openbox-kde-session.1.in
doc/openbox-kde-session.1.sgml
doc/openbox-session.1.in
doc/openbox-session.1.sgml
doc/rc-mouse-focus.xml
openbox/action.c
openbox/client.c
openbox/client.h
openbox/client_list_menu.c
openbox/event.c
openbox/frame.c
openbox/keyboard.c
openbox/screen.c
openbox/screen.h
openbox/session.c
openbox/session.h
render/font.c
tests/grav.c

index a0d72d3efce2759442b1ed69548c1fbbae1c5488..2f45893775843cfa469257b34eb9fc5692c286af 100644 (file)
 
 <desktops>
   <!-- this stuff is only used at startup, pagers allow you to change them
-       during a session -->
+       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 -->
   <number>4</number>
   <firstdesk>1</firstdesk>
   <names>
-    <name>desktop one</name>
-    <name>desktop two</name>
-    <name>desktop three</name>
-    <name>desktop four</name>
+    <!-- set names up here if you want to, like this:
+    <name>desktop 1</name>
+    <name>desktop 2</name>
+    -->
   </names>
 </desktops>
 
   <applicationIcons>yes</applicationIcons>
 </menu>
 
-<!-- this section is commented out.. remove this and the ending comment if you
-     want to use it -->
 <applications>
-  <!-- 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
+<!--
+  # this is an example with comments through out. use these to make your
+  # own rules, but without the comments of course.
 
-       the name, class, and role use simple globbing rules 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
- -->
   <application name="first element of window's WM_CLASS property (see xprop)"
               class="second element of window's WM_CLASS property (see xprop)"
                role="the window's WM_WINDOW_ROLE property (see xprop)">
+  # 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.
 
-    <!-- each element can be left out or set to 'default' to specify to not 
-         change that attribute of the window -->
+  # 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
 
     <decor>yes</decor>
-    <!-- enable or disable window decorations -->
+    # enable or disable window decorations
 
     <shade>no</shade>
+    # make the window shaded when it appears, or not
 
     <position>
-      <!-- the position is only used if both an x and y coordinate are provided
-           (and not set to 'default') -->
+      # the position is only used if both an x and y coordinate are provided
+      # (and not set to 'default')
       <x>center</x>
-      <!-- a number or 'center' to center on screen -->
+      # a number like 50, or 'center' to center on screen
       <y>200</y>
-      <!-- a number or 'center' to center on screen -->
+      # a number like 50, or 'center' to center on screen
       <monitor>1</monitor>
-      <!-- specifies the monitor in a xinerama setup.
-           1 is the first head, or 'mouse' for wherever the mouse is -->
+      # specifies the monitor in a xinerama setup.
+      # 1 is the first head, or 'mouse' for wherever the mouse is
     </position>
 
     <focus>yes</focus>
-    <!-- if the window should try be given focus when it appears -->
+    # 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
 
     <desktop>1</desktop>
-    <!-- 1 is the first desktop, 'all' for all desktops -->
+    # 1 is the first desktop, 'all' for all desktops
 
     <layer>normal</layer>
-    <!-- 'above', 'normal', or 'below' -->
+    # 'above', 'normal', or 'below'
 
     <iconic>no</iconic>
+    # make the window iconified when it appears, or not
 
     <skip_pager>no</skip_pager>
-    <!-- asks to not be shown in pagers -->
+    # asks to not be shown in pagers
 
     <skip_taskbar>no</skip_taskbar>
-    <!-- asks to not be shown in taskbars. window cycling actions will also
-         skip past such windows -->
+    # asks to not be shown in taskbars. window cycling actions will also
+    # skip past such windows
 
     <fullscreen>yes</fullscreen>
+    # make the window in fullscreen mode when it appears
 
     <maximized>true</maximized>
-    <!-- 'Horizontal', 'Vertical' or boolean (yes/no/on/off/true/false) -->
+    # 'Horizontal', 'Vertical' or boolean (yes/no)
   </application>
+
+  # end of the example
+-->
 </applications>
- -->
 
 </openbox_config>
index cacfec4d5b7106c9f78c9ab7cae064f53980631a..278ac6a8ed5a42aa55d1caaa3aef5ab913d40a84 100644 (file)
@@ -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 "$@"
index 0fe009408a6fef68b1f93dac4f803b711cf9fb29..160172605b06e160120fda8133ab59fe52ec4389 100644 (file)
@@ -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 "$@"
index b3f1c0574b8742883b0ce6d1b28714df69538390..cc2169f4b6956a00538c8fc779e9fc2e83249296 100644 (file)
@@ -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"
 
index a1e0b4714425a7ace28941090f2358ce44fb57c7..f38c9bf64c7094dbfb1bf70669cdb0f3a77686cb 100644 (file)
@@ -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 
index 0cf804e1c694c4ac889e2da4769932fa4064729f..c72865a75f72a2f8c4baa0d42ef8d492b622efe9 100644 (file)
@@ -38,6 +38,9 @@ manpage.1: manpage.sgml
 
     <para><command>&dhpackage;</command> runs a GNOME session with
       Openbox as the window manager.</para>
+
+    <para><command>&dhpackage;</command> does not take any command line
+      arguments.</para>
   </refsect1>
   <refsect1>
     <title>SEE ALSO</title>
index 2c21e0b6b02357e09ad0e39d3d00193d8a949549..d46d14b4899324333e1db3e57534b7fed9c13ece 100644 (file)
@@ -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 
index 33cf5d529c5b80598f670f7ebedb0f09180d1c1a..e4f049db4c25c7dd27b5ccb3ff3c336a13660d29 100644 (file)
@@ -38,6 +38,9 @@ manpage.1: manpage.sgml
 
     <para><command>&dhpackage;</command> runs a KDE session with
       Openbox as the window manager.</para>
+
+    <para><command>&dhpackage;</command> does not take any command line
+      arguments.</para>
   </refsect1>
   <refsect1>
     <title>SEE ALSO</title>
index 2d242f937c2a2f714c347db6f35c33e3ca5811bd..262324743584469498f047df4659beb0a868161d 100644 (file)
@@ -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 
index e4df8a1f360a13958d2ab1d7f88168da18fb8e8a..3c31755e7b18f959894b30e51452190a01d6a5d5 100644 (file)
@@ -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.</para>
 
+    <para><command>&dhpackage;</command> does not take any command line
+      arguments.</para>
+
     <para>On log in, <command>&dhpackage;</command> 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
index c5afcc26afbc16f7090b624b11c541ad2d1ebffe..0685257c2051d8ec9a0542603c3f8132c94addb0 100644 (file)
 
 <desktops>
   <!-- this stuff is only used at startup, pagers allow you to change them
-       during a session -->
+       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 -->
   <number>4</number>
   <firstdesk>1</firstdesk>
   <names>
-    <name>desktop one</name>
-    <name>desktop two</name>
-    <name>desktop three</name>
-    <name>desktop four</name>
+    <!-- set names up here if you want to, like this:
+    <name>desktop 1</name>
+    <name>desktop 2</name>
+    -->
   </names>
 </desktops>
 
   <applicationIcons>yes</applicationIcons>
 </menu>
 
-<!-- this section is commented out.. remove this and the ending comment if you
-     want to use it -->
 <applications>
-  <!-- the name or the class can be set, or both. this is used to match
-       windows when they appear
+<!--
+  # this is an example with comments through out. use these to make your
+  # own rules, but without the comments of course.
 
-       role can optionally be set, and only as much as you provide will be 
-       checked to see if it matches, eg. if you set role="abc" and the window's
-       role is actually "abcde" it would match.
- -->
   <application name="first element of window's WM_CLASS property (see xprop)"
               class="second element of window's WM_CLASS property (see xprop)"
                role="the window's WM_WINDOW_ROLE property (see xprop)">
+  # 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.
 
-    <!-- each element can be left out or set to 'default' to specify to not 
-         change that attribute of the window -->
+  # 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
 
     <decor>yes</decor>
+    # enable or disable window decorations
 
     <shade>no</shade>
+    # make the window shaded when it appears, or not
 
     <position>
-      <!-- the position is only used if both an x and y coordinate are provided
-           (and not set to 'default') -->
+      # the position is only used if both an x and y coordinate are provided
+      # (and not set to 'default')
       <x>center</x>
-      <!-- a number or 'center' to center on screen -->
+      # a number like 50, or 'center' to center on screen
       <y>200</y>
-      <!-- a number or 'center' to center on screen -->
+      # a number like 50, or 'center' to center on screen
       <monitor>1</monitor>
-      <!-- specifies the monitor in a xinerama setup.
-           1 is the first head, or 'mouse' for wherever the mouse is -->
+      # specifies the monitor in a xinerama setup.
+      # 1 is the first head, or 'mouse' for wherever the mouse is
     </position>
 
     <focus>yes</focus>
-    <!-- if the window should try be given focus when it appears -->
+    # 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
 
     <desktop>1</desktop>
-    <!-- 1 is the first desktop, 'all' for all desktops -->
+    # 1 is the first desktop, 'all' for all desktops
 
     <layer>normal</layer>
-    <!-- 'above', 'normal', or 'below' -->
+    # 'above', 'normal', or 'below'
 
     <iconic>no</iconic>
+    # make the window iconified when it appears, or not
 
     <skip_pager>no</skip_pager>
-    <!-- asks to not be shown in pagers -->
+    # asks to not be shown in pagers
 
     <skip_taskbar>no</skip_taskbar>
-    <!-- asks to not be shown in taskbars. window cycling actions will also
-         skip past such windows -->
+    # asks to not be shown in taskbars. window cycling actions will also
+    # skip past such windows
 
     <fullscreen>yes</fullscreen>
+    # make the window in fullscreen mode when it appears
 
     <maximized>true</maximized>
-    <!-- 'Horizontal', 'Vertical' or boolean (yes/no/on/off/true/false) -->
+    # 'Horizontal', 'Vertical' or boolean (yes/no)
   </application>
+
+  # end of the example
+-->
 </applications>
- -->
 
 </openbox_config>
index f106697971ee4c3617821e48cecc2f07dd65ec60..85d84798ab991e3eb433afbc01f8887d92671d92 100644 (file)
@@ -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. */
             }
         }
 }
index 68dfedce3468ba67d5874910ec3ef3692627668f..2a41ab8da41be0d15fa1743bc8e789a54c5b7239 100644 (file)
@@ -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);
 
index e66cf9e80215b04cb639c617876eb69ea688e50a..82a565f3fd692f7e64200f8789a5be66081b2ff6 100644 (file)
@@ -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)
index 77cfc1933121a0e31ce744a3434cc09274b715d4..e5ad17a394367b293b1c3b3b20bad26689cccf21 100644 (file)
@@ -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 */
index d7c723d120f1abbc1708f2ddbddf7b84305975b0..c19f70175d1567323b8a28a906cd70e476f3b094 100644 (file)
@@ -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) {
index 3aa97215f78b76c87876cd91e72907816bb1c029..ba84d474d4d2047d148ef8bf29f25b66a0f329cf 100644 (file)
@@ -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;
     }
index ab9d05b09859c631b026bbf31d307adeba1b0c83..2c60ac3d4f632e14c195eb0c1ce0380483b94263 100644 (file)
@@ -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;
index 4ad46af738c79135dd8118b28c633a88ac1b0e2f..c566a908046c5e5a10547ef549a5bdf5ef978905 100644 (file)
                         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 */
index bd96ab200992f998d00ca9d099c0befda1974dd4..b40776df9afa541538c10c802bb150386328fe3e 100644 (file)
@@ -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;
index 969d2f00d8825c6dee58c9ef8e8d153adec9bfd3..5918aa1312778f08f319e8e86295f7a34c097c71 100644 (file)
@@ -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, "<desktop>%d</desktop>\n", savedata->desktop);
 
+        fprintf(f, "<numdesktops>%d</numdesktops>\n", screen_num_desktops);
+
+        fprintf(f, "<desktoplayout>\n");
+        fprintf(f, "  <orientation>%d</orientation>\n",
+                screen_desktop_layout.orientation);
+        fprintf(f, "  <startcorner>%d</startcorner>\n",
+                screen_desktop_layout.start_corner);
+        fprintf(f, "  <columns>%d</columns>\n",
+                screen_desktop_layout.columns);
+        fprintf(f, "  <rows>%d</rows>\n",
+                screen_desktop_layout.rows);
+        fprintf(f, "</desktoplayout>\n");
+
+        if (screen_desktop_names) {
+            gint i;
+
+            fprintf(f, "<desktopnames>\n");
+            for (i = 0; screen_desktop_names[i]; ++i)
+                fprintf(f, "  <name>%s</name>\n", screen_desktop_names[i]);
+            fprintf(f, "</desktopnames>\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))
     {
index 97e55a3b1fe8301b04b8eb709a42c72756c518d0..b4ce6d917a156c775c02ce72f832fcec0cf8a3eb 100644 (file)
@@ -20,6 +20,7 @@
 #define __ob__session_h
 
 #include "client.h"
+#include "screen.h"
 
 #include <glib.h>
 
@@ -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;
 
index 3755c1ff7652c8d0aa013b0c96b41115bdcc4b66..48321aec63a24dd0abd7fef90925850085b2c952 100644 (file)
@@ -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);
 }
index 5aeed8bc4c79722b2532aabc4f7bf692dcf17e6e..a8dcdc31669515a48868e145ab3832c4d9446cfb 100644 (file)
@@ -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);