<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -45,17 +45,17 @@ chains = [
     (if_key(&quot;v&quot;, M4), mpd(&quot;pause&quot;)),
     (if_key(&quot;b&quot;, M4), mpd(&quot;next&quot;)),
 
-    (if_key('w', C+A), if_client, delete_client()),
-    (if_button(1,  A), if_client, flipping_move()),
-    (if_button(3,  A), if_client, flipping_resize()),
-    (if_button(4,  A), if_client, client_method('stack_bottom')),
-    (if_button(5,  A), if_client, client_method('stack_top')),
+    (if_key('w', C+A), if_manipulable, delete_client()),
+    (if_button(1,  A), if_manipulable, flipping_move()),
+    (if_button(3,  A), if_manipulable, flipping_resize()),
+    (if_button(4,  A), if_manipulable, client_method('stack_bottom')),
+    (if_button(5,  A), if_manipulable, client_method('stack_top')),
 
     # maximizations: full screen, left half, right half
 
-    (if_key(&quot;f&quot;, M4), if_client, client_method('moveresize', x=0,   y=0, width=W,   height=H)),
-    (if_key(&quot;h&quot;, M4), if_client, client_method('moveresize', x=0,   y=0, width=W/2, height=H)),
-    (if_key(&quot;l&quot;, M4), if_client, client_method('moveresize', x=W/2, y=0, width=W/2, height=H)),
+    (if_key(&quot;f&quot;, M4), if_manipulable, client_method('moveresize', x=0,   y=0, width=W,   height=H)),
+    (if_key(&quot;h&quot;, M4), if_manipulable, client_method('moveresize', x=0,   y=0, width=W/2, height=H)),
+    (if_key(&quot;l&quot;, M4), if_manipulable, client_method('moveresize', x=W/2, y=0, width=W/2, height=H)),
 ]
 
 # the recursiveness of grabbing on root is also causing global keybindings to</diff>
      <filename>config.py</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@
 import os, subprocess, logging
 
 from whimsy.x11 import props
+from whimsy.filters import if_sticky
 
 class delete_client(object):
     &quot;&quot;&quot;this is when we tell the client to go away&quot;&quot;&quot;
@@ -91,8 +92,9 @@ class viewport_absolute_move(object):
         wins = props.get_prop(wm.dpy, wm.root, '_NET_CLIENT_LIST_STACKING')
         for win in wins:
             c = wm.find_client(win)
-            c.geom.move_ip(xdelta, ydelta)
-            c.moveresize()
+            if not if_sticky(wm=wm, win=c.win):
+                c.geom.move_ip(xdelta, ydelta)
+                c.moveresize()
             #c.dpy.sync() # necessary?  maybe not
             #wish list: discard enternotifies
 </diff>
      <filename>whimsy/actions/builtins.py</filename>
    </modified>
    <modified>
      <diff>@@ -262,14 +262,20 @@ class net_wm_strut_partial(ewmh_prop):
         hub.emit('workarea_changed',
             **dict(zip(('x', 'y', 'width', 'height'), workarea)))
 
-def confine_to_workarea(hub, wm, x, y, width, height, **kw):
+def confine_to_workarea(hub, wm, **kw):
     # this should go somewhere else
-
-    # need to differentiate between encroaching and retreating/disappearing
+    try:
+        x, y, width, height = props.get_prop(wm.dpy, wm.root, '_NET_WORKAREA')
+    except Exception, e:
+        print &quot;net workarea value invalid?&quot;
+        print e
+        print repr(e)
+        try: print vars(e)
+        except: pass
+        return
 
     clients = [ c for c in wm.clients if not c.out_of_viewport(wm) ]
 
-    #left edge
     for c in clients:
         if c.props.get('_NET_WM_STRUT') or c.props.get('_NET_WM_STRUT_PARTIAL'):
             continue
@@ -292,10 +298,13 @@ def confine_to_workarea(hub, wm, x, y, width, height, **kw):
                         c.geom[begin] += near_overlap
                         c.geom[size] -= near_overlap
 
-        fix_axis(0, 2, wm.root_geometry.width, x, width)
-        fix_axis(1, 3, wm.root_geometry.height, y, height)
+            return near_needs_move or far_needs_move
+
+        moved =  fix_axis(0, 2, wm.root_geometry.width, x, width)
+        moved |= fix_axis(1, 3, wm.root_geometry.height, y, height)
 
-        c.moveresize()
+        if moved:
+            c.moveresize()
 
 
 # 'send_event': True,</diff>
      <filename>whimsy/actions/ewmh.py</filename>
    </modified>
    <modified>
      <diff>@@ -86,7 +86,9 @@ chains = [
     ('client_init_after', client_method('configure', border_width=0)),
     ('client_init_after', client_method('map_normal')),
 
-    ('workarea_changed', ewmh.confine_to_workarea),
+    ('workarea_changed',    ewmh.confine_to_workarea),
+    ('after_viewport_move', ewmh.confine_to_workarea),
+
     ('client_message', ewmh.handle_client_message),
 ]
 </diff>
      <filename>whimsy/base_config.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,7 @@ from Xlib import X, Xutil
 from Xlib import error as Xerror
 
 from whimsy import util
+from whimsy.x11 import props
 from whimsy.models.client import existing_unmanaged_window, newly_mapped_window
 
 class if_event_type(object):
@@ -16,9 +17,55 @@ class if_event_type(object):
 def _if_win_type(wtype, wm, **kw):
     return 'win' in kw and util.window_type(wm, kw['win']) == wtype
 
-def if_client   (wm, **kw): return _if_win_type('client',    wm, **kw)
-def if_root     (wm, **kw): return _if_win_type('root',      wm, **kw)
-def if_unmanaged(wm, **kw): return _if_win_type('unmanaged', wm, **kw)
+def if_client   (**kw): return _if_win_type('client',    **kw)
+def if_root     (**kw): return _if_win_type('root',      **kw)
+def if_unmanaged(**kw): return _if_win_type('unmanaged', **kw)
+
+def _if_hinted_win_type(wtypes, wm, **kw):
+    if 'win' not in kw:
+        return False
+    types = set(props.get_prop(wm.dpy, kw['win'], '_NET_WM_WINDOW_TYPE'))
+    ours = set([
+        wm.dpy.get_atom('_NET_WM_WINDOW_TYPE_'+wtype.upper())
+        for wtype in wtypes
+    ])
+    return bool(ours &amp; types)
+
+def if_desktop_type(**kw): return _if_hinted_win_type(['desktop'], **kw)
+def if_dock_type   (**kw): return _if_hinted_win_type(['dock'   ], **kw)
+def if_toolbar_type(**kw): return _if_hinted_win_type(['toolbar'], **kw)
+def if_menu_type   (**kw): return _if_hinted_win_type(['menu'   ], **kw)
+def if_utility_type(**kw): return _if_hinted_win_type(['utility'], **kw)
+def if_splash_type (**kw): return _if_hinted_win_type(['splash' ], **kw)
+def if_dialog_type (**kw): return _if_hinted_win_type(['dialog' ], **kw)
+def if_normal_type (**kw): return _if_hinted_win_type(['normal' ], **kw)
+
+def _if_hinted_win_state(wstates, wm, **kw):
+    if 'win' not in kw:
+        return False
+    states = set(props.get_prop(wm.dpy, kw['win'], '_NET_WM_STATE'))
+    ours = set([
+        wm.dpy.get_atom('_NET_WM_STATE_'+wstate.upper())
+        for wstate in wstates
+    ])
+    return bool(ours &amp; states)
+
+def if_modal            (**kw): return _if_hinted_win_state(['modal'            ], **kw)
+def if_sticky           (**kw): return _if_hinted_win_state(['sticky'           ], **kw)
+def if_maximized_vert   (**kw): return _if_hinted_win_state(['maximized_vert'   ], **kw)
+def if_maximized_horz   (**kw): return _if_hinted_win_state(['maximized_horz'   ], **kw)
+def if_shaded           (**kw): return _if_hinted_win_state(['shaded'           ], **kw)
+def if_skip_taskbar     (**kw): return _if_hinted_win_state(['skip_taskbar'     ], **kw)
+def if_skip_pager       (**kw): return _if_hinted_win_state(['skip_pager'       ], **kw)
+def if_hidden           (**kw): return _if_hinted_win_state(['hidden'           ], **kw)
+def if_fullscreen       (**kw): return _if_hinted_win_state(['fullscreen'       ], **kw)
+def if_above            (**kw): return _if_hinted_win_state(['above'            ], **kw)
+def if_below            (**kw): return _if_hinted_win_state(['below'            ], **kw)
+def if_demands_attention(**kw): return _if_hinted_win_state(['demands_attention'], **kw)
+
+def if_manipulable(**kw):
+    return _if_win_type('client', **kw) and \
+       not _if_hinted_win_type(['desktop', 'dock', 'splash'], **kw)
 
 class if_state(object):
     'true if modifier (shift/control/etc) keys currently match mods'</diff>
      <filename>whimsy/filters/__init__.py</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>94c6fb394fa891f0cb49f6710a7b81cff886a008</id>
    </parent>
  </parents>
  <author>
    <name>Nick Welch</name>
    <email>mack@incise.org</email>
  </author>
  <url>http://github.com/mackstann/whimsy/commit/bf4fb75c039495db317ea304674585cf94c35e96</url>
  <id>bf4fb75c039495db317ea304674585cf94c35e96</id>
  <committed-date>2008-11-24T14:38:36-08:00</committed-date>
  <authored-date>2008-11-24T14:38:36-08:00</authored-date>
  <message>support for _NET_WM_STATE, _NET_WM_WINDOW_TYPE, better workarea behavior</message>
  <tree>78c56482654ae8545d39b1e8e759dadf9aacef3f</tree>
  <committer>
    <name>Nick Welch</name>
    <email>mack@incise.org</email>
  </committer>
</commit>
