Merge branch 'backport' into work
authorDana Jansens <danakj@orodu.net>
Fri, 5 Feb 2010 18:47:58 +0000 (13:47 -0500)
committerDana Jansens <danakj@orodu.net>
Fri, 5 Feb 2010 18:47:58 +0000 (13:47 -0500)
162 files changed:
.gitignore
CHANGELOG
Makefile.am
README.GIT
configure.ac
data/rc.xml
data/rc.xsd
data/xsession/openbox-kde-session.in
m4/openbox.m4
m4/x11.m4
obrender/Makefile [moved from parser/Makefile with 100% similarity]
obrender/color.c [moved from render/color.c with 91% similarity]
obrender/color.h [moved from render/color.h with 100% similarity]
obrender/font.c [moved from render/font.c with 99% similarity]
obrender/font.h [moved from render/font.h with 100% similarity]
obrender/geom.h [moved from render/geom.h with 100% similarity]
obrender/gradient.c [moved from render/gradient.c with 100% similarity]
obrender/gradient.h [moved from render/gradient.h with 100% similarity]
obrender/icon.h [moved from render/icon.h with 100% similarity]
obrender/image.c [moved from render/image.c with 82% similarity]
obrender/image.h [moved from render/image.h with 91% similarity]
obrender/imagecache.c [moved from render/imagecache.c with 84% similarity]
obrender/imagecache.h [moved from render/imagecache.h with 84% similarity]
obrender/instance.c [moved from render/instance.c with 100% similarity]
obrender/instance.h [moved from render/instance.h with 100% similarity]
obrender/mask.c [moved from render/mask.c with 100% similarity]
obrender/mask.h [moved from render/mask.h with 100% similarity]
obrender/obrender-3.5.pc.in [moved from render/obrender-3.0.pc.in with 63% similarity]
obrender/render.c [moved from render/render.c with 100% similarity]
obrender/render.h [moved from render/render.h with 91% similarity]
obrender/test.c [moved from render/test.c with 100% similarity]
obrender/theme.c [moved from render/theme.c with 92% similarity]
obrender/theme.h [moved from render/theme.h with 93% similarity]
obrender/version.h.in [new file with mode: 0644]
obt/Makefile [moved from render/Makefile with 100% similarity]
obt/display.c [new file with mode: 0644]
obt/display.h [new file with mode: 0644]
obt/internal.h [moved from openbox/xerror.h with 70% similarity]
obt/keyboard.c [moved from openbox/modkeys.c with 65% similarity]
obt/keyboard.h [moved from openbox/modkeys.h with 51% similarity]
obt/mainloop.c [moved from openbox/mainloop.c with 75% similarity]
obt/mainloop.h [new file with mode: 0644]
obt/obt-3.5.pc.in [new file with mode: 0644]
obt/paths.c [new file with mode: 0644]
obt/paths.h [new file with mode: 0644]
obt/prop.c [new file with mode: 0644]
obt/prop.h [new file with mode: 0644]
obt/util.h [new file with mode: 0644]
obt/version.h.in [new file with mode: 0644]
obt/xevent.c [new file with mode: 0644]
obt/xevent.h [new file with mode: 0644]
obt/xml.c [new file with mode: 0644]
obt/xml.h [new file with mode: 0644]
openbox/actions.c
openbox/actions.h
openbox/actions/addremovedesktop.c
openbox/actions/all.c
openbox/actions/all.h
openbox/actions/breakchroot.c
openbox/actions/close.c
openbox/actions/cyclewindows.c
openbox/actions/debug.c
openbox/actions/decorations.c
openbox/actions/desktop.c
openbox/actions/directionalwindows.c
openbox/actions/dockautohide.c
openbox/actions/execute.c
openbox/actions/exit.c
openbox/actions/focus.c
openbox/actions/focustobottom.c
openbox/actions/fullscreen.c
openbox/actions/growtoedge.c
openbox/actions/iconify.c
openbox/actions/if.c
openbox/actions/kill.c
openbox/actions/layer.c
openbox/actions/lower.c
openbox/actions/maximize.c
openbox/actions/move.c
openbox/actions/moverelative.c
openbox/actions/moveresizeto.c
openbox/actions/movetoedge.c
openbox/actions/omnipresent.c
openbox/actions/raise.c
openbox/actions/raiselower.c
openbox/actions/reconfigure.c
openbox/actions/resize.c
openbox/actions/resizerelative.c
openbox/actions/restart.c
openbox/actions/shade.c
openbox/actions/shadelowerraise.c [new file with mode: 0644]
openbox/actions/showdesktop.c
openbox/actions/showmenu.c
openbox/actions/unfocus.c
openbox/client.c
openbox/client.h
openbox/client_list_combined_menu.c
openbox/client_list_menu.c
openbox/client_menu.c
openbox/client_menu.h
openbox/config.c
openbox/config.h
openbox/debug.c
openbox/debug.h
openbox/dock.c
openbox/dock.h
openbox/event.c
openbox/event.h
openbox/extensions.c [deleted file]
openbox/extensions.h [deleted file]
openbox/focus.c
openbox/focus.h
openbox/focus_cycle.c
openbox/focus_cycle.h
openbox/focus_cycle_indicator.c
openbox/focus_cycle_popup.c
openbox/focus_cycle_popup.h
openbox/frame.c
openbox/frame.h
openbox/framerender.c
openbox/grab.c
openbox/grab.h
openbox/keyboard.c
openbox/keyboard.h
openbox/mainloop.h [deleted file]
openbox/menu.c
openbox/menu.h
openbox/menuframe.c
openbox/menuframe.h
openbox/mouse.c
openbox/mouse.h
openbox/moveresize.c
openbox/openbox.c
openbox/openbox.h
openbox/ping.c
openbox/place.c
openbox/popup.c
openbox/popup.h
openbox/prompt.c
openbox/prompt.h
openbox/resist.c
openbox/resist.h
openbox/screen.c
openbox/screen.h
openbox/session.c
openbox/stacking.c
openbox/stacking.h
openbox/startupnotify.c
openbox/startupnotify.h
openbox/translate.c
openbox/translate.h
openbox/window.c
openbox/window.h
openbox/xerror.c [deleted file]
parser/obparser-3.0.pc.in [deleted file]
parser/parse.h [deleted file]
po/POTFILES.in
tests/mingrow.c [new file with mode: 0644]
tests/oldfullscreen.c [new file with mode: 0644]
tests/overrideinputonly.c [new file with mode: 0644]
themes/Clearlooks/openbox-3/themerc
version.h.in

index 907abb9..d48a7c3 100644 (file)
@@ -32,7 +32,7 @@ m4/*.m4
 missing
 .dirstamp
 openbox/openbox
-parser/obparser-3.0.pc
+parser/obparser-4.0.pc
 po/Makefile.in.in
 po/Makevars.template
 po/POTFILES
@@ -48,7 +48,8 @@ po/en@boldquot.insert-header
 po/en@quot.insert-header
 po/remove-potcdate.sed
 *.gmo
-render/obrender-3.0.pc
+obrender/obrender-3.5.pc
+obt/obt-3.5.pc
 tools/gnome-panel-control/gnome-panel-control
 tools/gdm-control/gdm-control
 tools/obxprop/obxprop
@@ -75,11 +76,14 @@ tests/grouptrancircular2
 tests/iconifydelay
 tests/icons
 tests/mapiconic
+tests/mingrow
 tests/modal
 tests/modal2
 tests/modal3
 tests/noresize
+tests/oldfullscreen
 tests/override
+tests/overrideinputonly
 tests/positioned
 tests/resize
 tests/restack
index fd68f09..8636efb 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,276 @@
+3.5.0-rc1:
+
+3.4.9:
+  * Allow focus to move while inside an Openbox menu, or during an interactive
+    action such as window cycling.
+  * Fixed bug #3717 (Empty dock interfered with move/grow to edge actions).
+  * Fixed bug #4411 (Crash when switching desktops and window cycling).
+  * Fixed bug #4377 (Window resistance against struts).
+  * Fixed bug #4035 (Prevent focus from moving under the mouse after
+    activating a window with an Openbox menu.
+  * Correct the value provided by the _NET_WORKAREA hint, so desktop icons
+    will place across all monitors.
+  * Don't hide submenus immediately when moving through the parent menu.
+    (Resolves request #3762).
+  * Fix for showing Openbox menus with multiple monitors, don't restrict them
+    to the monitor where the mouse is.
+  * Fixed bug #4023 (Allow the user to have multiple keys which perform the
+    same function in Openbox menus/move/resize.  E.g. two keys which are
+    both bound to Escape.
+  * Add a new obprop tool, which can be used to read the _OB_ROLE, _OB_NAME,
+    and _OB_CLASS (as well as any other UTF-8 window properties) off of a
+    window.
+  * Add _OB_ROLE, _OB_NAME, and _OB_CLASS hints on each window that show the
+    respective values for use in the rc.xml applications section, to modify
+    the window when it appears.
+  * Improve Openbox interoperability with gnome-session >= 2.24.
+  * Fixed bug #4040 (Remove desktop hints set by gdm in the openbox-session
+    scripts, so that Openbox can set the number of desktops (assuming
+    gnome-settings-daemon doesn't first)).
+  * Fix a bug in xdg-autostart preventing some .desktop files from working.
+  * Show the desktop pager popup on the primary monitor instead of on all
+    monitors.
+  * Add a new primaryMonitor config option, which is where Openbox popups
+    will appear.  Defaults to a fixed monitor, but can be made to behave as
+    before with the "active" value for it.
+  * Correct edge detection for move/grow to edge to properly use monitor edges
+    for multi-monitor setups.
+  * Change default window placement policy to stay on the active monitor for
+    multi-monitor setups.
+  * Fixed bug #1149 (Crash with some window icon sizes).
+  * Respond to all strut changes, fixes moving/hiding panels.
+  * Fix internal code to focus windows on other desktops correctly (Fixes
+    bug #4413).
+  * Focus correctness fixups for switching desktops.
+  * Fixed bug #4373 (Decoration bug for shaded maximized windows).
+  * Fixed bug #4350 (Allow a window to be made skip_taskbar but still get
+    focused by the user's rc.xml).
+  * Fixed bug #4307 (Set a minimum time for screenEdgeWarpTime).
+  * Fixed bug #4253 (Support for Solaris in openbox-session scripts).
+  * Fixed bug #3851 (Allow transient windows to be above helper windows).
+
+3.4.8:
+  * Updated translations: Slovak.
+  * Allow windows to change their decorations at any time (Fix for
+    Google Chrome).
+  * Make openbox-session to respect the $XDG_CONFIG_HOME environment variable.
+  * Fixed bug #4344 where borders were given to windows that should not have
+    them.
+  * Merge the SessionLogout and Exit actions.  They now test if connected to a
+    session manager and ask it to exit if so, or simply kill Openbox if not.
+  * Further tweaks to the _NET_ACTIVE_WINDOW message handling.  Use the same
+    logic for focus-stealing as is used when mapping a new window.
+  * Don't go out of our way any more to prevent focus from moving while the
+    keyboard is grabbed.
+  * Fix openbox-gnome-session when using gnome-session > 2.22.
+
+3.4.8-rc2:
+  * Updated translations: Italian, Croatian, Ukrainian.
+  * When resizing a window while focus cycling with bar=no, the bar no longer
+    reappears.
+  * Correctly handle shaped windows using the ShapeInput kind, this is used
+    by many composited apps to pass through clicks in their transparent areas.
+  * Fix the <monitor> per-app setting.
+  * Avoid using anonymous unions.
+  * Windows that had their decorations removed by per-app settings were still
+    placed as if they still had their decorations.
+  * Fix event handling not to ignore events on a window when they have an unmap
+    event in the queue, if that unmap event doesn't cause the window to be
+    unmanaged.
+  * Show the desktop switch on every monitor in xinerama.
+  * Fix interpretation of struts in xinerama where the screens have different
+    sizes.
+  * Add "next" and "prev" as possible <monitor> targets in the moveto and
+    resizeto actions.
+  * Allow escaping the _ used to mark the shortcut character in menu labels.
+    You can now change the (first) _ in a label to __, this will be displayed
+    as a single underscore. The rest of the _ in the string will be unaffected,
+    so only double the first one.
+  * Only replace ~ with the home directory when it is preceded by whitespace or
+    is at the start of the string, and when it is followed by a space, slash, or
+    the end of the string. This is implemented with GRegex, and so the required
+    glib version has been bumped to 2.14.
+  * Some other small fixes.
+
+3.4.8-rc1:
+  * Updated translations: Basque, Catalan, Turkish, Italian, Spanish, Russian.
+  * New translations: Danish, Turkish, Lithuanian.
+  * Set the _MOTIF_WM_INFO atom so urxvt uses motif hints for borderless mode.
+  * Properly escape the xml used in session files.
+  * Correct a 64-bit issue related to comparing timestamps.
+  * There is a sneaky sentence right at the end of a big paragraph in the
+    wm-spec document that says windows mapping with _NET_WM_USER_TIME=0 should
+    not be focused initially, honor this request.
+  * When moving a window to another desktop with following on, bring the
+    window's helper windows (for example gimp image windows with the toolbox
+    set to utility window).
+  * Change the _NET_ACTIVE_WINDOW messages again, if they originate from the
+    app and the window is on another desktop, just set the demands_attention
+    flag. If the event came from the user (ie pager/panel), then the window
+    is still moved to the current desktop.
+
+3.4.7.2:
+  * The system I used to generate the dist tarball didn't have the
+    docbook-to-man command so the manpages were empty.
+
+3.4.7.1:
+  * Not to be outdone by the cairo team, I introduced a bug in the last release
+    which made resizing not give any feedback. This is now fixed.
+
+3.4.7:
+  * Fully updated Czech, Simplified Chinese, Traditional Chinese, German,
+    French, Hungarian, Norwegian, Vietnamese, Dutch, Swedish, Finnish,
+    Brazilian Portuguese, Japanese and Portuguese translations
+  * Partially updated Spanish translation
+  * Add an example of the "force" option for the per-app placement options to
+    the default rc.xml file
+  * Add a new xdg-autostart script.  This will eventually end up in the PyXDG
+    distribution hopefully, but it is included in Openbox for now.  This script
+    runs things based on the freedesktop.org autostart specification.  You can
+    have it run GNOME, KDE, ROX, or XFCE specific things if you want.  The
+    new default system-wide autostart.sh script runs it automatically
+  * Update the default menu.xml to include a lot of common apps
+  * Fix white font shadows (negative shadowtint)
+  * Update the autostart.sh to find gnome-settings-daemon correctly, as the
+    GNOME people have moved it to libexec
+  * Fix focus possibly getting stolen when using the Focus action
+  * Drastically speed up rendering of Vertical and SplitVertical gradients
+  * Speed improvements also for Horizonal and Pyramid gradients
+  * Add new theme options, menu.overlap.x and menu.overlap.y options, that let
+    you independently control the horizontal and vertical position of submenus
+  * Change _NET_ACTIVE_WINDOW messages to not change the current desktop, but
+    to bring the window to the current desktop instead.  This is the industry
+    standard policy
+  * Use the pretty new openbox.png icon as the default window icon
+  * Allow matching per-application rules to windows by their window type
+    (normal, dialog, splash, etc).  The default rc.xml has more details
+  * Add new Openbox-themed prompt windows.  Use these prompt windows to ask
+    before killing off windows that aren't responding.  This also means we
+    don't need to ping every window constantly forever
+  * Add a new <prompt> option to the Execute action.  If this is set to a
+    string, a dialog will be shown with that string in it and "yes"/"no"
+    buttons.  The command to be executed will only be run if the user selects
+    "yes" in the dialog
+  * Add a new <prompt> option to the Exit action, which is a boolean (not a
+    string).  When true, Openbox will show a dialog confirming if you want to
+    exit.  The default is to show the prompt
+  * Reduce Openbox's memory footprint and speed up rendering through the use
+    of a new icon cache, so that Openbox only needs to keep 1 copy of an icon
+    when 100 different windows share it
+  * Make Openbox menus have the "menu type" hint for compositors to see and use
+  * Fix the MoveResizeTo action for negative coords (opposite edges)
+  * Fix key bindings getting lost if multiple bindings at the same level could
+    not be translated (Fixes VMWare causing Openbox keybindings to stop
+    working)
+  * Fix the resize popup box for terminal windows with a base size of 0 (show
+    the right size values for urxvt terminals)
+  * Fix some off-by-one bugs with the edge growing/shrinking code
+  * Add new theme options for menu line separators: menu.separator.color,
+    menu.separator.width, menu.separator.padding.width,
+    menu.separator.padding.height
+  * Add xfce-mcs-manager to the default autostart.sh, and run it automatically
+    when gnome-settings-daemon is not present to have GTK apps inherit settings
+    from the XFCE configuration tools
+  * Make the send-to-desktop menu in the client-menu indicate which is the current
+    desktop for omnipresent windows, and don't close it if just toggling
+    omni-presence when ctrl-clicking
+  * Add a new SessionLogout action that logs out through the session manager,
+    when running Openbox within a session manager such as within an
+    GNOME/Openbox or KDE/Openbox session.  The action includes a <prompt>
+    option which is similar to the Exit action's
+  * Add a new gdm-control command that lets you control gdm from within an X
+    session.  The gdm-control lets you change GDM's behaviour for when you end
+    the current session.  For instance, you can tell GDM to reboot, and
+    then immediately log out of the current session, and the computer will be
+    rebooted
+  * Show an information dialog when an error occurs for Openbox, such as when
+    the Execute action fails or when XML syntax errors are present in the
+    configuration files
+  * When making a window very narrow, don't draw buttons to the right of the title
+    on top of the ones on its left.
+
+3.4.6.1:
+  * Updated Clearlooks theme
+  * Add the force="yes/no" option for the per-app settings' <position> tag
+  * Raise and focus modal children and their direct parents together, improved
+    usability with direct modal transient windows
+  * Fix crash when using <raise> for NextWindow and there are no windows
+    to move focus to
+  * Add the <manageDesktops> option in the rc.xml <menu> section, which toggles
+    the "Manage Desktops" section appearing in the combined-client-list-menu
+  * Fix for menu headers showing the wrong text
+  * Fix for the <focusLast> behavior
+  * Treat modal direct children as one window with their parent consistently
+
+3.4.6:
+  * Added Basque translation
+  * Updated French, Vietnamese German, Simplified Chinese, Russian, Portuguese,
+    Brasilian Portuguese, Norwegian, and Finnish translations
+  * New Clearlooks theme, updated by David Barr
+  * Updated the previous Clearlooks theme, and renamed it to Clearlooks-3.4
+  * Allow dialog type windows to go fullscreen (Fixes Kpdf)
+  * Remove the extraneous top border for undecorated windows while maximized
+  * Fixes for keyboard modifiers (Alt-tab dialog getting stuck on screen for
+    some users)
+  * Automatically catch changes to the keyboard map and reconfigure the key
+    bindings on the fly
+  * Fix focus moving incorrectly sometimes with focus under mouse enabled
+  * Make default configuration focus the desktop when you right click
+  * Add the <bar> and <raise> options for all window cycling actions, allowing
+    you to have your target window temporarily raised above all others, and to
+    turn the focus target indicator bar off
+  * Improve the LastDesktop action to not remember desktops you skipped across
+  * Ignore mouse clicks that are made on override-redirect (unmanaged) windows
+  * When opening a menu with a key binding, don't use the key binding to run
+    something in the menu
+  * Add a <monitor> option for window placement, which gives you the option
+    to place new windows on the active monitor, or the monitor where the mouse
+    is, instead of on any monitor (for xinerama multihead setups)
+  * Add options for placing the window move/resize coordinate popup window in
+    a fixed position on screen, rather than relative to the window being
+    moved or resized
+  * Prevent the dock from auto-hiding completely offscreen if the theme has
+    no borders for it
+  * New icon
+  * Fix race condition when running things that want to grab the keyboard
+    (e.g. gnome-panel-control --main-menu)
+  * When dialog windows ask to not appear in the taskbar, still give them focus
+    in normal ways (fixes new GNOME session logout dialogs)
+  * Fix bug with resizing corners on certain parts of the window frame
+  * Ping applications to tell when they are running or have become frozen.
+    Show a [Not Responding] message in the title bar of windows which are
+    frozen.
+  * When closing a window which is [Not Responding], kill the window's process
+    if it is running on the same machine as Openbox.  Otherwise, just
+    disconnect
+    the window from the X display.  A second attempt to close a [Not
+    Responding]
+    window will kill it forcefully (kill -9).
+  * Fixes for internal timers
+  * Add a <wmclass> option for the execute action's startup-notification.  This
+    lets you tell Openbox that the application will map a window with the
+    specified class - for applications that do not support startup-notification
+    natively.
+  * Fix for empty dock taking up space onscreen after a reconfigure
+  * Reduce Openbox's additional memory footprint per-window and per-menu
+  * Faster horizontal gradient rendering
+  * Don't deiconify windows that aren't allowed to be directly iconified on
+    restart (eg toolbars), as they can be iconified by other means
+  * Improve support for fullscreen windows in xinerama (TwinView) and
+    multiple-screen setups
+  * Add a --config-file command line option, to specify an alternate
+    configuration file path
+
+3.4.5:
+  * Added Hungarian translation
+  * Updated Finnish, Russian, German and French translations
+  * Fixed some very minor memory leaks
+  * Hide the desktop popup when showing the focus popup
+  * Fix a crash when trying to access the More... menu of
+    client-list-combined-menu
+  * Fix the coordinate popup only showing up on the first monitor in xinerama
+  * Add --exit to exit the currently running openbox instance
+
 3.4.4:
   * Updated Traditional Chinese translation
   * Updated Norwegian translation
index 14786f5..91b2303 100644 (file)
@@ -8,7 +8,8 @@ rcdir           = $(configdir)/openbox
 xsessionsdir    = $(datadir)/xsessions
 gnomewmfilesdir = $(datadir)/gnome/wm-properties
 pkgconfigdir    = $(libdir)/pkgconfig
-pubincludedir   = $(includedir)/openbox/@OB_VERSION@/openbox
+obtpubincludedir= $(includedir)/openbox/@OBT_VERSION@/obt
+rrpubincludedir = $(includedir)/openbox/@RR_VERSION@/obrender
 pixmapdir       = $(datadir)/pixmaps
 xsddir          = $(datadir)/openbox
 secretbindir    = $(libdir)/openbox
@@ -23,11 +24,11 @@ ACLOCAL_AMFLAGS = -I m4
 INCLUDES = -I.
 
 check_PROGRAMS = \
-       render/rendertest
+       obrender/rendertest
 
 lib_LTLIBRARIES = \
-       parser/libobparser.la \
-       render/libobrender.la
+       obt/libobt.la \
+       obrender/libobrender.la
 
 bin_PROGRAMS = \
        openbox/openbox \
@@ -43,90 +44,105 @@ nodist_bin_SCRIPTS = \
        data/xsession/openbox-gnome-session \
        data/xsession/openbox-kde-session
 
-## render ##
+## obrender ##
 
-render_rendertest_CPPFLAGS = \
+obrender_rendertest_CPPFLAGS = \
        $(PANGO_CFLAGS) \
-       $(XFT_CFLAGS) \
        $(GLIB_CFLAGS) \
        -DG_LOG_DOMAIN=\"RenderTest\"
-render_rendertest_LDADD = \
-       parser/libobparser.la \
-       render/libobrender.la \
+obrender_rendertest_LDADD = \
+       obt/libobt.la \
+       obrender/libobrender.la \
        $(GLIB_LIBS) \
        $(PANGO_LIBS) \
-       $(XFT_LIBS) \
        $(XML_LIBS) \
        $(X_LIBS)
-render_rendertest_SOURCES = render/test.c
+obrender_rendertest_SOURCES = obrender/test.c
 
-render_libobrender_la_CPPFLAGS = \
+obrender_libobrender_la_CPPFLAGS = \
        $(X_CFLAGS) \
        $(GLIB_CFLAGS) \
        $(XML_CFLAGS) \
        $(PANGO_CFLAGS) \
-       $(XFT_CFLAGS) \
        -DG_LOG_DOMAIN=\"ObRender\" \
        -DDEFAULT_THEME=\"$(theme)\"
-render_libobrender_la_LDFLAGS = \
-       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
-render_libobrender_la_LIBADD = \
-       parser/libobparser.la \
+obrender_libobrender_la_LDFLAGS = \
+       -version-info $(RR_CURRENT):$(RR_REVISION):$(RR_AGE)
+obrender_libobrender_la_LIBADD = \
+       obt/libobt.la \
        $(X_LIBS) \
        $(PANGO_LIBS) \
-       $(XFT_LIBS) \
        $(GLIB_LIBS) \
        $(XML_LIBS)
-render_libobrender_la_SOURCES = \
+obrender_libobrender_la_SOURCES = \
        gettext.h \
-       render/color.h \
-       render/color.c \
-       render/font.h \
-       render/font.c \
-       render/geom.h \
-       render/gradient.h \
-       render/gradient.c \
-       render/icon.h \
-       render/image.h \
-       render/image.c \
-       render/imagecache.h \
-       render/imagecache.c \
-       render/instance.h \
-       render/instance.c \
-       render/mask.h \
-       render/mask.c \
-       render/render.h \
-       render/render.c \
-       render/theme.h \
-       render/theme.c
-
-## parser ##
-
-parser_libobparser_la_CPPFLAGS = \
+       obrender/color.h \
+       obrender/color.c \
+       obrender/font.h \
+       obrender/font.c \
+       obrender/geom.h \
+       obrender/gradient.h \
+       obrender/gradient.c \
+       obrender/icon.h \
+       obrender/image.h \
+       obrender/image.c \
+       obrender/imagecache.h \
+       obrender/imagecache.c \
+       obrender/instance.h \
+       obrender/instance.c \
+       obrender/mask.h \
+       obrender/mask.c \
+       obrender/render.h \
+       obrender/render.c \
+       obrender/theme.h \
+       obrender/theme.c
+
+## obt ##
+
+obt_libobt_la_CPPFLAGS = \
+       $(XINERAMA_CFLAGS) \
+       $(XKB_CFLAGS) \
+       $(XRANDR_CFLAGS) \
+       $(XSHAPE_CFLAGS) \
+       $(XSYNC_CFLAGS) \
        $(GLIB_CFLAGS) \
        $(XML_CFLAGS) \
-       -DG_LOG_DOMAIN=\"ObParser\" \
+       -DG_LOG_DOMAIN=\"Obt\" \
        -DLOCALEDIR=\"$(localedir)\" \
        -DDATADIR=\"$(datadir)\" \
        -DCONFIGDIR=\"$(configdir)\"
-parser_libobparser_la_LDFLAGS = \
-       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
-parser_libobparser_la_LIBADD = \
+obt_libobt_la_LDFLAGS = \
+       -version-info $(OBT_CURRENT):$(OBT_REVISION):$(OBT_AGE)
+obt_libobt_la_LIBADD = \
+       $(XINERAMA_LIBS) \
+       $(XKB_LIBS) \
+       $(XRANDR_LIBS) \
+       $(XSHAPE_LIBS) \
+       $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
-       $(XML_LIBS) 
-parser_libobparser_la_SOURCES = \
-       parser/parse.h \
-       parser/parse.c
+       $(XML_LIBS)
+obt_libobt_la_SOURCES = \
+       obt/display.h \
+       obt/display.c \
+       obt/internal.h \
+       obt/keyboard.h \
+       obt/keyboard.c \
+       obt/mainloop.h \
+       obt/mainloop.c \
+       obt/xml.h \
+       obt/xml.c \
+       obt/paths.h \
+       obt/paths.c \
+       obt/prop.h \
+       obt/prop.c \
+       obt/util.h \
+       obt/xevent.h \
+       obt/xevent.c
 
 ## openbox ##
 
 openbox_openbox_CPPFLAGS = \
        $(SM_CFLAGS) \
-       $(XINERAMA_CFLAGS) \
-       $(XKB_CFLAGS) \
-       $(XRANDR_CFLAGS) \
-       $(XSHAPE_CFLAGS) \
-       $(XSYNC_CFLAGS) \
        $(X_CFLAGS) \
        $(XCURSOR_CFLAGS) \
        $(SM_CFLAGS) \
@@ -134,17 +150,13 @@ openbox_openbox_CPPFLAGS = \
        $(GLIB_CFLAGS) \
        $(LIBSN_CFLAGS) \
        $(XML_CFLAGS) \
+       $(IMLIB2_CFLAGS) \
        -DLOCALEDIR=\"$(localedir)\" \
        -DDATADIR=\"$(datadir)\" \
        -DCONFIGDIR=\"$(configdir)\" \
        -DG_LOG_DOMAIN=\"Openbox\"
 openbox_openbox_LDADD = \
        $(SM_LIBS) \
-       $(XINERAMA_LIBS) \
-       $(XKB_LIBS) \
-       $(XRANDR_LIBS) \
-       $(XSHAPE_LIBS) \
-       $(XSYNC_LIBS) \
        $(GLIB_LIBS) \
        $(X_LIBS) \
        $(XCURSOR_LIBS) \
@@ -152,8 +164,9 @@ openbox_openbox_LDADD = \
        $(XML_LIBS) \
        $(EFENCE_LIBS) \
        $(LIBINTL) \
-       render/libobrender.la \
-       parser/libobparser.la
+       $(IMLIB2_LIBS) \
+       obrender/libobrender.la \
+       obt/libobt.la
 openbox_openbox_LDFLAGS = -export-dynamic
 openbox_openbox_SOURCES = \
        gettext.h \
@@ -192,6 +205,7 @@ openbox_openbox_SOURCES = \
        openbox/actions/resizerelative.c \
        openbox/actions/restart.c \
        openbox/actions/shade.c \
+       openbox/actions/shadelowerraise.c \
        openbox/actions/showdesktop.c \
        openbox/actions/showmenu.c \
        openbox/actions/unfocus.c \
@@ -213,8 +227,6 @@ openbox_openbox_SOURCES = \
        openbox/dock.h \
        openbox/event.c \
        openbox/event.h \
-       openbox/extensions.c \
-       openbox/extensions.h \
        openbox/focus.c \
        openbox/focus.h \
        openbox/focus_cycle.c \
@@ -236,15 +248,11 @@ openbox_openbox_SOURCES = \
        openbox/keyboard.h \
        openbox/keytree.c \
        openbox/keytree.h \
-       openbox/mainloop.c \
-       openbox/mainloop.h \
        openbox/menuframe.c \
        openbox/menuframe.h \
        openbox/menu.c \
        openbox/menu.h \
        openbox/misc.h \
-       openbox/modkeys.c \
-       openbox/modkeys.h \
        openbox/mouse.c \
        openbox/mouse.h \
        openbox/moveresize.c \
@@ -260,8 +268,6 @@ openbox_openbox_SOURCES = \
        openbox/prompt.h \
        openbox/popup.c \
        openbox/popup.h \
-       openbox/prop.c \
-       openbox/prop.h \
        openbox/resist.c \
        openbox/resist.h \
        openbox/screen.c \
@@ -275,9 +281,7 @@ openbox_openbox_SOURCES = \
        openbox/translate.c \
        openbox/translate.h \
        openbox/window.c \
-       openbox/window.h \
-       openbox/xerror.c \
-       openbox/xerror.h
+       openbox/window.h
 
 
 ## gnome-panel-control ##
@@ -406,24 +410,32 @@ dist_syscrash_theme_DATA= \
 
 ## public headers ##
 
-pubinclude_HEADERS = \
-       render/color.h \
-       render/font.h \
-       render/geom.h \
-       render/gradient.h \
-       render/image.h \
-       render/instance.h \
-       render/mask.h \
-       render/render.h \
-       render/theme.h \
-       parser/parse.h
-
-nodist_pubinclude_HEADERS = \
-       version.h
+rrpubinclude_HEADERS = \
+       obrender/color.h \
+       obrender/font.h \
+       obrender/geom.h \
+       obrender/gradient.h \
+       obrender/image.h \
+       obrender/instance.h \
+       obrender/mask.h \
+       obrender/render.h \
+       obrender/theme.h \
+       obrender/version.h
+
+obtpubinclude_HEADERS = \
+       obt/display.h \
+       obt/keyboard.h \
+       obt/mainloop.h \
+       obt/xml.h \
+       obt/paths.h \
+       obt/prop.h \
+       obt/util.h \
+       obt/version.h \
+       obt/xevent.h
 
 nodist_pkgconfig_DATA = \
-       render/obrender-3.0.pc \
-       parser/obparser-3.0.pc
+       obrender/obrender-3.5.pc \
+       obt/obt-3.5.pc
 
 ## data ##
 
@@ -475,7 +487,6 @@ nodist_xsessions_DATA = \
        data/xsession/openbox-kde.desktop
 
 dist_noinst_DATA = \
-       version.h.in \
        data/autostart.sh.in \
        data/rc.xsd \
        data/menu.xsd \
@@ -495,8 +506,10 @@ dist_noinst_DATA = \
        doc/openbox-kde-session.1.in \
        doc/obxprop.1.sgml \
        doc/obxprop.1.in \
-       render/obrender-3.0.pc.in \
-       parser/obparser-3.0.pc.in \
+       obrender/version.h.in \
+       obrender/obrender-3.5.pc.in \
+       obt/obt-3.5.pc.in \
+       obt/version.h.in \
        tools/themeupdate/themeupdate.py \
        tests/hideshow.py \
        tests/Makefile \
@@ -552,7 +565,7 @@ CLEANFILES = \
 #       $(MAKE) -$(MAKEFLAGS) -C doc/doxygen doc
 
 distclean-local:
-       for d in . m4 po render; do \
+       for d in . m4 po obrender parser obt openbox; do \
                for p in core core.* gmon.out *\~ *.orig *.rej .\#*; do \
                        rm -f "$$d/$$p"; \
                done \
index c50118e..b4b0557 100644 (file)
@@ -3,7 +3,7 @@ To build Openbox from git you need:
 A C Compiler (GNU GCC 3.2+ suggested)
 GNU Gettext 0.14.4
 GNU Autoconf 2.50+
-GNU Automake 1.9+
+GNU Automake 1.9 (no more, no less)
 GNU Libtool
 Xlib library/headers (devel package)
 Pkg-Config
index eb11c03..57f126a 100644 (file)
@@ -1,44 +1,71 @@
 AC_PREREQ([2.54])
-AC_INIT([openbox], [3.999.0], [http://bugzilla.icculus.org])
+AC_INIT([openbox], [3.5.0-rc1], [http://bugzilla.icculus.org])
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([openbox/openbox.c])
 
+OB_VERSION=$PACKAGE_VERSION
+AC_SUBST(OB_VERSION)
+
 dnl Making releases:
-dnl   OB_MICRO_VERSION += 1;
-dnl   OB_INTERFACE_AGE += 1;
-dnl   OB_BINARY_AGE += 1;
-dnl if any functions have been added, set OB_INTERFACE_AGE to 0.
+dnl   RR_MICRO_VERSION += 1;
+dnl   RR_INTERFACE_AGE += 1;
+dnl   R_BINARY_AGE += 1;
+dnl if any functions have been added, set RR_INTERFACE_AGE to 0.
 dnl if backwards compatibility has been broken,
-dnl set OB_BINARY_AGE and OB_INTERFACE_AGE to 0.
+dnl set RR_BINARY_AGE and RR_INTERFACE_AGE to 0.
 dnl
 dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
 dnl
-OB_MAJOR_VERSION=3
-OB_MINOR_VERSION=4
-OB_MICRO_VERSION=16
-OB_INTERFACE_AGE=0
-OB_BINARY_AGE=0
-OB_VERSION=$PACKAGE_VERSION
-
-AC_SUBST(OB_MAJOR_VERSION)
-AC_SUBST(OB_MINOR_VERSION)
-AC_SUBST(OB_MICRO_VERSION)
-AC_SUBST(OB_INTERFACE_AGE)
-AC_SUBST(OB_BINARY_AGE)
-AC_SUBST(OB_VERSION)
+RR_MAJOR_VERSION=3
+RR_MINOR_VERSION=5
+RR_MICRO_VERSION=27
+RR_INTERFACE_AGE=0
+RR_BINARY_AGE=0
+RR_VERSION=$RR_MAJOR_VERSION.$RR_MINOR_VERSION
+
+OBT_MAJOR_VERSION=3
+OBT_MINOR_VERSION=5
+OBT_MICRO_VERSION=0
+OBT_INTERFACE_AGE=0
+OBT_BINARY_AGE=0
+OBT_VERSION=$OBT_MAJOR_VERSION.$OBT_MINOR_VERSION
+
+AC_SUBST(RR_MAJOR_VERSION)
+AC_SUBST(RR_MINOR_VERSION)
+AC_SUBST(RR_MICRO_VERSION)
+AC_SUBST(RR_INTERFACE_AGE)
+AC_SUBST(RR_BINARY_AGE)
+AC_SUBST(RR_VERSION)
+AC_SUBST(OBT_MAJOR_VERSION)
+AC_SUBST(OBT_MINOR_VERSION)
+AC_SUBST(OBT_MICRO_VERSION)
+AC_SUBST(OBT_INTERFACE_AGE)
+AC_SUBST(OBT_BINARY_AGE)
+AC_SUBST(OBT_VERSION)
 
 dnl Libtool versioning
-LT_RELEASE=$OB_MAJOR_VERSION.$OB_MINOR_VERSION
-LT_CURRENT=`expr $OB_MICRO_VERSION - $OB_INTERFACE_AGE`
-LT_REVISION=$OB_INTERFACE_AGE
-LT_AGE=`expr $OB_BINARY_AGE - $OB_INTERFACE_AGE`
-LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
-
-AC_SUBST(LT_RELEASE)
-AC_SUBST(LT_CURRENT)
-AC_SUBST(LT_REVISION)
-AC_SUBST(LT_AGE)
-AC_SUBST(LT_CURRENT_MINUS_AGE)
+RR_RELEASE=$RR_MAJOR_VERSION.$RR_MINOR_VERSION
+RR_CURRENT=`expr $RR_MICRO_VERSION - $RR_INTERFACE_AGE`
+RR_REVISION=$RR_INTERFACE_AGE
+RR_AGE=`expr $RR_BINARY_AGE - $RR_INTERFACE_AGE`
+RR_CURRENT_MINUS_AGE=`expr $RR_CURRENT - $RR_AGE`
+
+OBT_RELEASE=$OBT_MAJOR_VERSION.$OBT_MINOR_VERSION
+OBT_CURRENT=`expr $OBT_MICRO_VERSION - $OBT_INTERFACE_AGE`
+OBT_REVISION=$OBT_INTERFACE_AGE
+OBT_AGE=`expr $OBT_BINARY_AGE - $OBT_INTERFACE_AGE`
+OBT_CURRENT_MINUS_AGE=`expr $OBT_CURRENT - $OBT_AGE`
+
+AC_SUBST(RR_RELEASE)
+AC_SUBST(RR_CURRENT)
+AC_SUBST(RR_REVISION)
+AC_SUBST(RR_AGE)
+AC_SUBST(RR_CURRENT_MINUS_AGE)
+AC_SUBST(OBT_RELEASE)
+AC_SUBST(OBT_CURRENT)
+AC_SUBST(OBT_REVISION)
+AC_SUBST(OBT_AGE)
+AC_SUBST(OBT_CURRENT_MINUS_AGE)
 
 AC_PREFIX_DEFAULT([/usr/local])
 test "$prefix" = "NONE" && prefix=$ac_default_prefix
@@ -61,7 +88,8 @@ AM_GNU_GETTEXT_VERSION(0.15)
 AM_GNU_GETTEXT([external])
 
 AC_CHECK_HEADERS(ctype.h fcntl.h locale.h signal.h string.h stdio.h stdlib.h)
-AC_CHECK_HEADERS(unistd.h sys/stat.h sys/select.h sys/time.h sys/wait.h)
+AC_CHECK_HEADERS(unistd.h sys/stat.h sys/select.h sys/socket.h sys/time.h)
+AC_CHECK_HEADERS(sys/wait.h)
 # AC_HEADER_TIME
 # AC_TYPE_SIGNAL
 
@@ -78,10 +106,6 @@ PKG_CHECK_MODULES(PANGO, [pango >= 1.8.0 pangoxft >= 1.8.0])
 AC_SUBST(PANGO_CFLAGS)
 AC_SUBST(PANGO_LIBS)
 
-PKG_CHECK_MODULES(XFT, [xft])
-AC_SUBST(XFT_CFLAGS)
-AC_SUBST(XFT_LIBS)
-
 PKG_CHECK_MODULES(XML, [libxml-2.0 >= 2.6.0])
 AC_SUBST(XML_CFLAGS)
 AC_SUBST(XML_LIBS)
@@ -136,6 +160,33 @@ else
   xcursor_found=no
 fi
 
+AC_ARG_ENABLE(imlib2,
+  AC_HELP_STRING(
+    [--disable-imlib2],
+    [disable use of Imlib2 image library for loading icons. [[default=enabled]]]
+  ),
+  [enable_imlib2=$enableeval],
+  [enable_imlib2=yes]
+)
+
+if test "$enable_imlib2" = yes; then
+PKG_CHECK_MODULES(IMLIB2, [imlib2],
+  [
+    AC_DEFINE(USE_IMLIB2, [1], [Use Imlib2 image library])
+    AC_SUBST(IMLIB2_CFLAGS)
+    AC_SUBST(IMLIB2_LIBS)
+    imlib2_found=yes
+  ],
+  [
+    imlib2_found=no
+  ]
+)
+else
+  imlib2_found=no
+fi
+
+AM_CONDITIONAL(USE_IMLIB2, [test $imlib2_found = yes])
+
 dnl Check for session management
 X11_SM
 
@@ -154,8 +205,10 @@ AC_CONFIG_FILES([
   Makefile
   m4/Makefile
   po/Makefile.in
-  render/obrender-3.0.pc
-  parser/obparser-3.0.pc
+  obrender/obrender-3.5.pc
+  obt/obt-3.5.pc
+  obrender/version.h
+  obt/version.h
   version.h
 ])
 AC_CONFIG_COMMANDS([doc],
@@ -171,5 +224,6 @@ AC_MSG_RESULT([Compiling with these options:
                Startup Notification... $sn_found
                X Cursor Library... $xcursor_found
                Session Management... $SM
+               Imlib2 library... $imlib2_found
                ])
 AC_MSG_RESULT([configure complete, now type "make"])
index a576ca6..6347091 100644 (file)
     <slant>normal</slant>
     <!-- 'italic' or 'normal' -->
   </font>
-  <font place="OnScreenDisplay">
+  <font place="ActiveOnScreenDisplay">
+    <name>sans</name>
+    <size>9</size>
+    <!-- font size in points -->
+    <weight>bold</weight>
+    <!-- 'bold' or 'normal' -->
+    <slant>normal</slant>
+    <!-- 'italic' or 'normal' -->
+  </font>
+  <font place="InactiveOnScreenDisplay">
     <name>sans</name>
     <size>9</size>
     <!-- font size in points -->
     </action>
   </keybind>
 
+  <!-- Keybindings for window switching with the arrow keys -->
+  <keybind key="W-S-Right">
+    <action name="DirectionalCycleWindows">
+      <direction>right</direction>
+    </action>
+  </keybind>
+  <keybind key="W-S-Left">
+    <action name="DirectionalCycleWindows">
+      <direction>left</direction>
+    </action>
+  </keybind>
+  <keybind key="W-S-Up">
+    <action name="DirectionalCycleWindows">
+      <direction>up</direction>
+    </action>
+  </keybind>
+  <keybind key="W-S-Down">
+    <action name="DirectionalCycleWindows">
+      <direction>down</direction>
+    </action>
+  </keybind>
+
   <!-- Keybindings for running applications -->
   <keybind key="W-e">
     <action name="Execute">
     </mousebind>
 
     <mousebind button="Up" action="Click">
-      <action name="Shade"/>
-      <action name="FocusToBottom"/>
-      <action name="Unfocus"/>
-      <action name="Lower"/>
+      <action name="if">
+        <shaded>no</shaded>
+        <then>
+          <action name="Shade"/>
+          <action name="FocusToBottom"/>
+          <action name="Unfocus"/>
+          <action name="Lower"/>
+        </then>
+      </action>
     </mousebind>
     <mousebind button="Down" action="Click">
-      <action name="Unshade"/>
-      <action name="Raise"/>
+      <action name="if">
+        <shaded>yes</shaded>
+        <then>
+          <action name="Unshade"/>
+          <action name="Raise"/>
+        </then>
+      </action>
     </mousebind>
 
     <mousebind button="Right" action="Press">
   </context>
 
   <context name="Desktop">
-    <mousebind button="Up" action="Press">
+    <mousebind button="Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="Down" action="Press">
+    <mousebind button="Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
 
-    <mousebind button="A-Up" action="Press">
+    <mousebind button="A-Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="A-Down" action="Press">
+    <mousebind button="A-Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
-    <mousebind button="C-A-Up" action="Press">
+    <mousebind button="C-A-Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="C-A-Down" action="Press">
+    <mousebind button="C-A-Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
 
   </context>
 
   <context name="MoveResize">
-    <mousebind button="Up" action="Press">
+    <mousebind button="Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="Down" action="Press">
+    <mousebind button="Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
-    <mousebind button="A-Up" action="Press">
+    <mousebind button="A-Up" action="Click">
       <action name="GoToDesktop"><to>previous</to></action>
     </mousebind>
-    <mousebind button="A-Down" action="Press">
+    <mousebind button="A-Down" action="Click">
       <action name="GoToDesktop"><to>next</to></action>
     </mousebind>
   </context>
 <!--
   # this is an example with comments through out. use these to make your
   # own rules, but without the comments of course.
+  # you may use one or more of the name/class/role/title/type rules to specify
+  # windows to match
 
   <application name="the window's _OB_APP_NAME property (see obxprop)"
               class="the window's _OB_APP_CLASS property (see obxprop)"
                role="the window's _OB_APP_ROLE property (see obxprop)"
+              title="the window's _OB_APP_TITLE property (see obxprop)"
                type="the window's _OB_APP_TYPE property (see obxprob)..
                       (if unspecified, then it is 'dialog' for child windows)">
-  # you may set only one of name/class/role/type, or you may use more than one
-  # together to restrict your matches.
+  # you may set only one of name/class/role/title/type, or you may use more
+  # than one together to restrict your matches.
 
-  # the name, class, and role use simple wildcard matching such as those
+  # the name, class, role, and title use simple wildcard matching such as those
   # used by a shell. you can use * to match any characters and ? to match
   # any single character.
 
index 499b81c..2fed1f4 100644 (file)
@@ -61,6 +61,7 @@
             <xsd:element minOccurs="0" name="underMouse" type="ob:bool"/>
             <xsd:element minOccurs="0" name="focusDelay" type="xsd:integer"/>
             <xsd:element minOccurs="0" name="raiseOnFocus" type="ob:bool"/>
+            <xsd:element minOccurs="0" name="unfocusOnLeave" type="ob:bool"/>
         </xsd:all>
     </xsd:complexType>
     <xsd:complexType name="placement">
             <xsd:element minOccurs="0" name="hideDelay" type="xsd:integer"/>
             <xsd:element minOccurs="0" name="middle" type="ob:bool"/>
             <xsd:element minOccurs="0" name="submenuShowDelay" type="xsd:integer"/>
-            <xsd:element minOccurs="0" name="applicationIcons" type="ob:bool"/>
+            <xsd:element minOccurs="0" name="showIcons" type="ob:bool"/>
             <xsd:element minOccurs="0" name="manageDesktops" type="ob:bool"/>
         </xsd:sequence>
     </xsd:complexType>
             <xsd:element minOccurs="0" name="fullscreen" type="ob:bool"/>
             <xsd:element minOccurs="0" name="maximized" type="ob:maximization"/>
         </xsd:all>
+        <!-- at least one of these must be present -->
         <xsd:attribute name="role" type="xsd:string"/>
+        <xsd:attribute name="title" type="xsd:string"/>
         <xsd:attribute name="type" type="ob:clienttype"/>
-        <!-- at least one of these must be present -->
         <xsd:attribute name="name" type="xsd:string"/>
         <xsd:attribute name="class" type="xsd:string"/>
     </xsd:complexType>
index 5299b04..14e3504 100644 (file)
@@ -7,6 +7,9 @@ if test -n "$1"; then
   exit
 fi
 
+# Set the prefix for the menu layout to use
+export XDG_MENU_PREFIX="kde-"
+
 # Clean up after GDM
 xprop -root -remove _NET_NUMBER_OF_DESKTOPS \
       -remove _NET_DESKTOP_NAMES \
index 5c3aeec..5a95e84 100644 (file)
@@ -74,7 +74,7 @@ AC_DEFUN([OB_COMPILER_FLAGS],
     if test "$GCC" = "yes"; then
        AC_MSG_RESULT([yes])
        if test "$DEBUG" = "yes"; then
-           FLAGS="$FLAGS -O0 -g3 -fno-inline -Wwrite-strings"
+           FLAGS="$FLAGS -O0 -ggdb -fno-inline -Wwrite-strings"
            FLAGS="$FLAGS -Wall -Wsign-compare -Waggregate-return"
            FLAGS="$FLAGS -Wcast-qual -Wbad-function-cast -Wpointer-arith"
             # for Python.h
index fc7b36e..d840d34 100644 (file)
--- a/m4/x11.m4
+++ b/m4/x11.m4
@@ -29,155 +29,6 @@ AC_DEFUN([X11_DEVEL],
   CPPFLAGS=$OLDCPPFLAGS
 ])
 
-
-AC_DEFUN([XFT_ERROR],
-[
-  if test "$XFT_MIN"; then
-    AC_MSG_ERROR([$PACKAGE requires the Xft font library >= $XFT_MIN.
-                  See http://www.fontconfig.org/
-])
-  else
-    AC_MSG_ERROR([$PACKAGE requires the Xft font library.
-                  See http://www.fontconfig.org/
-])
-  fi
-])
-
-# XFT_DEVEL([required-version])
-#
-# Check for the XFT development package.
-# You can use the optional argument to check for a library of at least the
-# given version.
-# It provides the $(PYTHON_CFLAGS) $(PYTHON_LIBS) output variables.
-AC_DEFUN([XFT_DEVEL],
-[
-  AC_REQUIRE([X11_DEVEL])
-  
-  if test "$1"; then
-    XFT_MIN="$1"
-    XFT_MIN_MAJOR=${XFT_MIN%.*.*}
-    XFT_MIN_MINOR=${XFT_MIN%.*}
-    XFT_MIN_MINOR=${XFT_MIN_MINOR#*.}
-    XFT_MIN_REVISION=${XFT_MIN#*.*.}
-    XFT_MIN="$XFT_MIN_MAJOR.$XFT_MIN_MINOR.$XFT_MIN_REVISION"
-  else
-    XFT_MIN=""
-  fi
-
-  if test -z "$XFT_MIN"; then
-    AC_MSG_CHECKING([for Xft])
-    if ! pkg-config xft; then
-      AC_MSG_RESULT([no])
-      XFT_ERROR
-    fi
-  else
-    AC_MSG_CHECKING([for Xft version >= $XFT_MIN])
-    if ! pkg-config --atleast-version $XFT_MIN xft; then
-      AC_MSG_RESULT([no])
-      XFT_ERROR
-    fi
-  fi
-  AC_MSG_RESULT([yes])
-
-
-  # Store these
-  OLDLIBS=$LIBS
-  OLDCPPFLAGS=$CPPFLAGS
-
-  XFT_CFLAGS="`pkg-config --cflags xft`"
-  XFT_LIBS="`pkg-config --libs xft`"
-
-  # Set these for checking with the tests below. They'll be restored after
-  LIBS="$LIBS $XFT_LIBS"
-  CPPFLAGS="$XFT_CFLAGS $CPPFLAGS"
-
-  AC_CHECK_LIB([Xft], [XftGetVersion], # this was not defined in < 2.0
-    if test "$XFT_MIN"; then
-      AC_MSG_CHECKING([for X11/Xft/Xft.h for Xft >= $XFT_MIN])
-      AC_TRY_COMPILE(
-      [
-        #include <X11/Xlib.h>
-        #include <X11/Xft/Xft.h>
-      ],
-      [
-        #if !defined(XFT_MAJOR)
-        # error Xft.h is too old
-        #endif
-        #if XFT_MAJOR < $XFT_MIN_MAJOR
-        # error Xft.h is too old
-        #endif
-        #if XFT_MAJOR == $XFT_MIN_MAJOR
-        # if XFT_MINOR < $XFT_MIN_MINOR
-        #  error Xft.h is too old
-        # endif
-        #endif
-        #if XFT_MAJOR == $XFT_MIN_MAJOR
-        # if XFT_MAJOR == $XFT_MIN_MINOR
-        #  if XFT_REVISION < $XFT_MIN_REVISION
-        #   error Xft.h is too old
-        #  endif
-        # endif
-        #endif
-      
-        int i = XFT_MAJOR;
-        XftFont foo;
-      ],
-      [
-        AC_MSG_RESULT([yes])
-      ],
-      [
-        AC_MSG_RESULT([no])
-        XFT_ERROR
-      ])
-    else
-      AC_MSG_CHECKING([for X11/Xft/Xft.h])
-      AC_TRY_COMPILE(
-      [
-        #include <X11/Xlib.h>
-        #include <X11/Xft/Xft.h>
-      ],
-      [
-        int i = XFT_MAJOR; /* make sure were using Xft 2, not 1 */
-        XftFont foo;
-      ],
-      [
-        AC_MSG_RESULT([yes])
-      ],
-      [
-        AC_MSG_RESULT([no])
-        XFT_ERROR
-      ])
-    fi
-
-    AC_MSG_CHECKING([if we can compile with Xft])
-    AC_TRY_LINK(
-    [
-      #include <X11/Xlib.h>
-      #include <X11/Xft/Xft.h>
-    ],
-    [
-      int i = XFT_MAJOR;
-      XftFont foo
-    ],
-    [
-      AC_MSG_RESULT([yes])
-    ],
-    [ 
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([Unable to compile with the Xft font library.
-])
-    ])
-  )
-
-  # Restore the old values. Use XFT_CFLAGS and XFT_LIBS in the Makefiles
-  LIBS=$OLDLIBS
-  CPPFLAGS=$OLDCPPFLAGS
-
-  AC_SUBST([XFT_CFLAGS])
-  AC_SUBST([XFT_LIBS])
-])
-
-
 # X11_EXT_XKB()
 #
 # Check for the presence of the "Xkb" X Window System extension.
similarity index 100%
rename from parser/Makefile
rename to obrender/Makefile
similarity index 91%
rename from render/color.c
rename to obrender/color.c
index 41fcc71..5e3f216 100644 (file)
@@ -143,6 +143,28 @@ void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
             }
         } else im->data = (gchar*) data;
         break;
+    case 24:
+    {
+        /* reverse the ordering, shifting left 16bit should be the first byte
+           out of three, etc */
+        const guint roff = (16 - RrRedOffset(inst)) / 8;
+        const guint goff = (16 - RrGreenOffset(inst)) / 8;
+        const guint boff = (16 - RrBlueOffset(inst)) / 8;
+        gint outx;
+        for (y = 0; y < im->height; y++) {
+            for (x = 0, outx = 0; x < im->width; x++, outx += 3) {
+                r = (data[x] >> RrDefaultRedOffset) & 0xFF;
+                g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
+                b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
+                p8[outx+roff] = r;
+                p8[outx+goff] = g;
+                p8[outx+boff] = b;
+            }
+            data += im->width;
+            p8 += im->bytes_per_line;
+        }
+        break;
+    }
     case 16:
         for (y = 0; y < im->height; y++) {
             for (x = 0; x < im->width; x++) {
@@ -191,7 +213,7 @@ void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
         }
         break;
     default:
-        g_error("Your bit depth is currently unhandled\n");
+        g_error("This image bit depth (%i) is currently unhandled", im->bits_per_pixel);
 
     }
 }
similarity index 100%
rename from render/color.h
rename to obrender/color.h
similarity index 99%
rename from render/font.c
rename to obrender/font.c
index 583c9f7..cde0d03 100644 (file)
@@ -217,7 +217,7 @@ static inline int font_calculate_baseline(RrFont *f, gint height)
 
 void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area)
 {
-    gint x,y,w,h;
+    gint x,y,w;
     XftColor c;
     gint mw;
     PangoRectangle rect;
@@ -240,7 +240,7 @@ void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area)
     w = area->width;
     if (t->flow) w = MAX(w, t->maxwidth);
     w -= 4;
-    h = area->height;
+    /* h = area->height; */
 
     if (t->flow)
         ell = PANGO_ELLIPSIZE_NONE;
@@ -258,6 +258,8 @@ void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area)
         case RR_ELLIPSIZE_END:
             ell = PANGO_ELLIPSIZE_END;
             break;
+        default:
+            g_assert_not_reached();
         }
     }
 
similarity index 100%
rename from render/font.h
rename to obrender/font.h
similarity index 100%
rename from render/geom.h
rename to obrender/geom.h
similarity index 100%
rename from render/gradient.c
rename to obrender/gradient.c
similarity index 100%
rename from render/gradient.h
rename to obrender/gradient.h
similarity index 100%
rename from render/icon.h
rename to obrender/icon.h
similarity index 82%
rename from render/image.c
rename to obrender/image.c
index 3698e81..f86a3ee 100644 (file)
@@ -21,6 +21,9 @@
 #include "image.h"
 #include "color.h"
 #include "imagecache.h"
+#ifdef USE_IMLIB2
+#include <Imlib2.h>
+#endif
 
 #include <glib.h>
 
@@ -28,7 +31,8 @@
 #define FLOOR(i)        ((i) & (~0UL << FRACTION))
 #define AVERAGE(a, b)   (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)))
 
-void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data)
+void RrImagePicInit(RrImagePic *pic, const gchar *name,
+                    gint w, gint h, RrPixel32 *data)
 {
     gint i;
 
@@ -38,12 +42,14 @@ void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data)
     pic->sum = 0;
     for (i = w*h; i > 0; --i)
         pic->sum += *(data++);
+    pic->name = g_strdup(name);
 }
 
 static void RrImagePicFree(RrImagePic *pic)
 {
     if (pic) {
         g_free(pic->data);
+        g_free(pic->name);
         g_free(pic);
     }
 }
@@ -58,7 +64,10 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
 
     g_assert(pic->width > 0 && pic->height > 0);
 
-    g_assert(g_hash_table_lookup(self->cache->table, pic) == NULL);
+    if (pic->name)
+        g_assert(!g_hash_table_lookup(self->cache->name_table, pic->name));
+    else
+        g_assert(!g_hash_table_lookup(self->cache->pic_table, pic));
 
     /* grow the list */
     *list = g_renew(RrImagePic*, *list, ++*len);
@@ -70,15 +79,19 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
     /* set the new picture up at the front of the list */
     (*list)[0] = pic;
 
-    /* add the picture as a key to point to this image in the cache */
-    g_hash_table_insert(self->cache->table, (*list)[0], self);
+    /* add the name or the picture as a key to point to this image in the
+       cache */
+    if (pic->name)
+        g_hash_table_insert(self->cache->name_table, pic->name, self);
+    else
+        g_hash_table_insert(self->cache->pic_table, (*list)[0], self);
 
 /*
 #ifdef DEBUG
-    g_message("Adding %s picture to the cache:\n    "
-              "Image 0x%x, w %d h %d Hash %u",
-              (*list == self->original ? "ORIGINAL" : "RESIZED"),
-              (guint)self, pic->width, pic->height, RrImagePicHash(pic));
+    g_debug("Adding %s picture to the cache:\n    "
+            "Image 0x%lx, w %d h %d Hash %u",
+            (*list == self->original ? "ORIGINAL" : "RESIZED"),
+            (gulong)self, pic->width, pic->height, RrImagePicHash(pic));
 #endif
 */
 }
@@ -92,16 +105,19 @@ static void RemovePicture(RrImage *self, RrImagePic ***list,
 
 /*
 #ifdef DEBUG
-    g_message("Removing %s picture from the cache:\n    "
-              "Image 0x%x, w %d h %d Hash %u",
-              (*list == self->original ? "ORIGINAL" : "RESIZED"),
-              (guint)self, (*list)[i]->width, (*list)[i]->height,
-              RrImagePicHash((*list)[i]));
+    g_debug("Removing %s picture from the cache:\n    "
+            "Image 0x%lx, w %d h %d Hash %u",
+            (*list == self->original ? "ORIGINAL" : "RESIZED"),
+            (gulong)self, (*list)[i]->width, (*list)[i]->height,
+            RrImagePicHash((*list)[i]));
 #endif
 */
 
-    /* remove the picture as a key in the cache */
-    g_hash_table_remove(self->cache->table, (*list)[i]);
+    /* remove the name or picture as a key in the cache */
+    if ((*list)[i]->name)
+        g_hash_table_remove(self->cache->name_table, (*list)[i]->name);
+    else
+        g_hash_table_remove(self->cache->pic_table, (*list)[i]);
 
     /* free the picture */
     RrImagePicFree((*list)[i]);
@@ -220,7 +236,7 @@ static RrImagePic* ResizeImage(RrPixel32 *src,
     }
 
     pic = g_new(RrImagePic, 1);
-    RrImagePicInit(pic, dstW, dstH, dststart);
+    RrImagePicInit(pic, NULL, dstW, dstH, dststart);
 
     return pic;
 }
@@ -325,6 +341,14 @@ RrImage* RrImageNew(RrImageCache *cache)
     return self;
 }
 
+/*! Set function that will be called just before RrImage is destroyed. */
+void RrImageSetDestroyFunc(RrImage *image, RrImageDestroyFunc func,
+                           gpointer data)
+{
+    image->destroy_func = func;
+    image->destroy_data = data;
+}
+
 void RrImageRef(RrImage *self)
 {
     ++self->ref;
@@ -335,10 +359,12 @@ void RrImageUnref(RrImage *self)
     if (self && --self->ref == 0) {
 /*
 #ifdef DEBUG
-        g_message("Refcount to 0, removing ALL pictures from the cache:\n    "
-                  "Image 0x%x", (guint)self);
+        g_debug("Refcount to 0, removing ALL pictures from the cache:\n    "
+                "Image 0x%lx", (gulong)self);
 #endif
 */
+        if (self->destroy_func)
+            self->destroy_func(self, self->destroy_data);
         while (self->n_original > 0)
             RemovePicture(self, &self->original, 0, &self->n_original);
         while (self->n_resized > 0)
@@ -347,10 +373,8 @@ void RrImageUnref(RrImage *self)
     }
 }
 
-/*! Add a new picture with the given RGBA pixel data and dimensions into the
-  RrImage.  This adds an "original" picture to the image.
-*/
-void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
+static void AddPictureFromData(RrImage *self, const char *name,
+                               const RrPixel32 *data, gint w, gint h)
 {
     gint i;
     RrImagePic *pic;
@@ -360,8 +384,8 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
         if (self->original[i]->width == w && self->original[i]->height == h) {
 /*
 #ifdef DEBUG
-            g_message("Found duplicate ORIGINAL image:\n    "
-                      "Image 0x%x, w %d h %d", (guint)self, w, h);
+            g_debug("Found duplicate ORIGINAL image:\n    "
+                    "Image 0x%lx, w %d h %d", (gulong)self, w, h);
 #endif
 */
             return;
@@ -376,10 +400,55 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
 
     /* add the new picture */
     pic = g_new(RrImagePic, 1);
-    RrImagePicInit(pic, w, h, g_memdup(data, w*h*sizeof(RrPixel32)));
+    RrImagePicInit(pic, name, w, h, g_memdup(data, w*h*sizeof(RrPixel32)));
     AddPicture(self, &self->original, &self->n_original, pic);
 }
 
+gboolean RrImageAddPictureName(RrImage *self, const gchar *name)
+{
+#ifdef USE_IMLIB2
+    Imlib_Image img;
+    gint w, h;
+    RrPixel32 *data;
+    gchar *path;
+
+    /* XXX find the path via freedesktop icon spec (use obt) ! */
+    path = g_strdup(name);
+
+    if (!(img = imlib_load_image(path)))
+        g_message("Cannot load image \"%s\" from file \"%s\"", name, path);
+    g_free(path);
+
+    if (!img)
+        return FALSE; /* failed to load it */
+
+    /* Get data and dimensions of the image.
+
+       WARNING: This stuff is NOT threadsafe !!
+    */
+    imlib_context_set_image(img);
+    data = imlib_image_get_data_for_reading_only();
+    w = imlib_image_get_width();
+    h = imlib_image_get_height();
+
+    /* add it to the RrImage, and set its name */
+    AddPictureFromData(self, name, data, w, h);
+
+    imlib_free_image();
+    return TRUE;
+#else
+    return FALSE;
+#endif
+}
+
+/*! Add a new picture with the given RGBA pixel data and dimensions into the
+  RrImage.  This adds an "original" picture to the image.
+*/
+void RrImageAddPicture(RrImage *self, const RrPixel32 *data, gint w, gint h)
+{
+    AddPictureFromData(self, NULL, data, w, h);    
+}
+
 /*! Remove the picture from the RrImage which has the given dimensions. This
  removes an "original" picture from the image.
 */
similarity index 91%
rename from render/image.h
rename to obrender/image.h
index b478daf..6e4a50e 100644 (file)
@@ -23,7 +23,8 @@
 #include "geom.h"
 
 /*! Initialize an RrImagePicture to the specified dimensions and pixel data */
-void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data);
+void RrImagePicInit(RrImagePic *pic, const gchar *path,
+                    gint w, gint h, RrPixel32 *data);
 
 void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img,
                       gint target_w, gint target_h,
similarity index 84%
rename from render/imagecache.c
rename to obrender/imagecache.c
index 9c605f9..036ac12 100644 (file)
@@ -32,8 +32,9 @@ RrImageCache* RrImageCacheNew(gint max_resized_saved)
     self = g_new(RrImageCache, 1);
     self->ref = 1;
     self->max_resized_saved = max_resized_saved;
-    self->table = g_hash_table_new((GHashFunc)RrImagePicHash,
-                                   (GEqualFunc)RrImagePicEqual);
+    self->pic_table = g_hash_table_new((GHashFunc)RrImagePicHash,
+                                       (GEqualFunc)RrImagePicEqual);
+    self->name_table = g_hash_table_new(g_str_hash, g_str_equal);
     return self;
 }
 
@@ -45,21 +46,31 @@ void RrImageCacheRef(RrImageCache *self)
 void RrImageCacheUnref(RrImageCache *self)
 {
     if (self && --self->ref == 0) {
-        g_assert(g_hash_table_size(self->table) == 0);
-        g_hash_table_unref(self->table);
+        g_assert(g_hash_table_size(self->pic_table) == 0);
+        g_hash_table_unref(self->pic_table);
+        self->pic_table = NULL;
+
+        g_assert(g_hash_table_size(self->name_table) == 0);
+        g_hash_table_destroy(self->name_table);
+        self->name_table = NULL;
 
         g_free(self);
     }
 }
 
+RrImage* RrImageCacheFindName(RrImageCache *self, const gchar *name)
+{
+    return g_hash_table_lookup(self->name_table, name);
+}
+
 /*! Finds an image in the cache, if it is already in there */
 RrImage* RrImageCacheFind(RrImageCache *self,
                           RrPixel32 *data, gint w, gint h)
 {
     RrImagePic pic;
 
-    RrImagePicInit(&pic, w, h, data);
-    return g_hash_table_lookup(self->table, &pic);
+    RrImagePicInit(&pic, NULL, w, h, data);
+    return g_hash_table_lookup(self->pic_table, &pic);
 }
 
 #define hashsize(n) ((RrPixel32)1<<(n))
similarity index 84%
rename from render/imagecache.h
rename to obrender/imagecache.h
index 4ad2dea..9baf34b 100644 (file)
@@ -45,7 +45,14 @@ struct _RrImageCache {
     */
     gint max_resized_saved;
 
-    GHashTable *table;
+    /*! A hash table of images in the cache that don't have a file name
+      attached to them, with their key being a hash of the contents of the
+      image. */
+    GHashTable *pic_table;
+
+    /*! Used to find out if an image file has already been loaded.
+      Provides a quick file_name -> RrImage lookup. */
+    GHashTable *name_table;
 };
 
 #endif
similarity index 100%
rename from render/instance.c
rename to obrender/instance.c
similarity index 100%
rename from render/instance.h
rename to obrender/instance.h
similarity index 100%
rename from render/mask.c
rename to obrender/mask.c
similarity index 100%
rename from render/mask.h
rename to obrender/mask.h
similarity index 63%
rename from render/obrender-3.0.pc.in
rename to obrender/obrender-3.5.pc.in
index ebb17ef..78646e3 100644 (file)
@@ -8,7 +8,7 @@ xlibs=@X_LIBS@
 
 Name: ObRender
 Description: Openbox Render Library
-Version: @VERSION@
-Requires: obparser-3.0 glib-2.0 xft pangoxft
+Version: @RR_VERSION@
+Requires: obt-3.5 glib-2.0 xft pangoxft
 Libs: -L${libdir} -lobrender ${xlibs}
-Cflags: -I${includedir}/openbox/@OB_VERSION@ ${xcflags}
+Cflags: -I${includedir}/openbox/@RR_VERSION@ ${xcflags}
similarity index 100%
rename from render/render.c
rename to obrender/render.c
similarity index 91%
rename from render/render.h
rename to obrender/render.h
index f7bc504..64c2f6a 100644 (file)
 #ifndef __render_h
 #define __render_h
 
-#include "geom.h"
-#include "version.h"
-
 #include <X11/Xlib.h> /* some platforms dont include this as needed for Xft */
 #include <pango/pangoxft.h>
 #include <glib.h>
 
 G_BEGIN_DECLS
 
+#include "obrender/geom.h"
+#include "obrender/version.h"
+
 typedef union  _RrTextureData      RrTextureData;
 typedef struct _RrAppearance       RrAppearance;
 typedef struct _RrSurface          RrSurface;
@@ -230,8 +230,14 @@ struct _RrImagePic {
     /* The sum of all the pixels.  This is used to compare pictures if their
        hashes match. */
     gint sum;
+    /* The name of the image.  This is used to determine
+       if the named image already is loaded.  May be NULL if the image
+       was not loaded from disk. */
+    gchar *name;
 };
 
+typedef void (*RrImageDestroyFunc)(RrImage *image, gpointer data);
+
 /*! An RrImage is a sort of meta-image.  It can contain multiple versions of
   an image at different sizes, which may or may not be completely different
   pictures */
@@ -250,6 +256,11 @@ struct _RrImage {
       RrImage. */
     RrImagePic **resized;
     gint n_resized;
+
+    /* This function (if not NULL) will be called just before destroying
+      RrImage. */
+    RrImageDestroyFunc destroy_func;
+    gpointer           destroy_data;
 };
 
 /* these are the same on all endian machines because it seems to be dependant
@@ -337,12 +348,19 @@ void          RrImageCacheUnref(RrImageCache *self);
 /*! Finds an image in the cache, if it is already in there */
 RrImage*      RrImageCacheFind(RrImageCache *self,
                                RrPixel32 *data, gint w, gint h);
+/*! Finds an image in the cache, by searching for the name of the image */
+RrImage*      RrImageCacheFindName(RrImageCache *self,
+                                   const gchar *name);
 
 RrImage* RrImageNew(RrImageCache *cache);
 void     RrImageRef(RrImage *im);
 void     RrImageUnref(RrImage *im);
 
-void     RrImageAddPicture(RrImage *im, RrPixel32 *data, gint w, gint h);
+void     RrImageAddPicture(RrImage *im, const RrPixel32 *data, gint w, gint h);
+/*! Adds a picture by name, from a file on disk. 
+  @name Can be a full path to an image, or it can be a name as per the
+        freedesktop.org icon spec. */
+gboolean RrImageAddPictureName(RrImage *im, const gchar *name);
 void     RrImageRemovePicture(RrImage *im, gint w, gint h);
 
 G_END_DECLS
similarity index 100%
rename from render/test.c
rename to obrender/test.c
similarity index 92%
rename from render/theme.c
rename to obrender/theme.c
index aa9cb3f..43fb0dd 100644 (file)
@@ -23,7 +23,7 @@
 #include "mask.h"
 #include "theme.h"
 #include "icon.h"
-#include "parser/parse.h"
+#include "obt/paths.h"
 
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
@@ -67,7 +67,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
                     gboolean allow_fallback,
                     RrFont *active_window_font, RrFont *inactive_window_font,
                     RrFont *menu_title_font, RrFont *menu_item_font,
-                    RrFont *osd_font)
+                    RrFont *active_osd_font, RrFont *inactive_osd_font)
 {
     XrmDatabase db = NULL;
     RrJustify winjust, mtitlejust;
@@ -142,10 +142,11 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     theme->a_menu_bullet_selected = RrAppearanceNew(inst, 1);
     theme->a_clear = RrAppearanceNew(inst, 0);
     theme->a_clear_tex = RrAppearanceNew(inst, 1);
-    theme->osd_hilite_bg = RrAppearanceNew(inst, 0);
+    theme->osd_bg = RrAppearanceNew(inst, 0);
     theme->osd_hilite_label = RrAppearanceNew(inst, 1);
-    theme->osd_hilite_fg = RrAppearanceNew(inst, 0);
-    theme->osd_unhilite_fg = RrAppearanceNew(inst, 0);
+    theme->osd_hilite_bg = RrAppearanceNew(inst, 0);
+    theme->osd_unhilite_label = RrAppearanceNew(inst, 1);
+    theme->osd_unhilite_bg = RrAppearanceNew(inst, 0);
 
     /* load the font stuff */
     theme->win_font_focused = get_font(active_window_font,
@@ -173,7 +174,8 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
 
     theme->menu_font = get_font(menu_item_font, &default_font, inst);
 
-    theme->osd_font = get_font(osd_font, &default_font, inst);
+    theme->osd_font_hilite = get_font(active_osd_font, &default_font, inst);
+    theme->osd_font_unhilite = get_font(inactive_osd_font, &default_font,inst);
 
     /* load direct dimensions */
     if ((!read_int(db, "menu.overlap.x", &theme->menu_overlap_x) &&
@@ -283,15 +285,26 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
                     "window.active.label.text.color",
                     &theme->title_focused_color))
         theme->title_focused_color = RrColorNew(inst, 0x0, 0x0, 0x0);
-    if (!read_color(db, inst, "osd.label.text.color", &theme->osd_color))
-        theme->osd_color = RrColorNew(inst,
-                                      theme->title_focused_color->r,
-                                      theme->title_focused_color->g,
-                                      theme->title_focused_color->b);
+    if (!read_color(db, inst, "osd.active.label.text.color",
+                    &theme->osd_text_active_color) &&
+        !read_color(db, inst, "osd.label.text.color",
+                    &theme->osd_text_active_color))
+        theme->osd_text_active_color =
+            RrColorNew(inst,
+                       theme->title_focused_color->r,
+                       theme->title_focused_color->g,
+                       theme->title_focused_color->b);
     if (!read_color(db, inst,
                     "window.inactive.label.text.color",
                     &theme->title_unfocused_color))
         theme->title_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+    if (!read_color(db, inst, "osd.inactive.label.text.color",
+                    &theme->osd_text_inactive_color))
+        theme->osd_text_inactive_color =
+            RrColorNew(inst,
+                       theme->title_unfocused_color->r,
+                       theme->title_unfocused_color->g,
+                       theme->title_unfocused_color->b);
     if (!read_color(db, inst,
                     "window.active.button.unpressed.image.color",
                     &theme->titlebut_focused_unpressed_color))
@@ -559,6 +572,16 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
         theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data);
     }
 
+    /* up and down arrows */
+    {
+        guchar data[] = { 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00 };
+        theme->down_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data);
+    }
+    {
+        guchar data[] = { 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00 };
+        theme->up_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data);
+    }
+
     /* setup the default window icon */
     theme->def_win_icon = read_c_image(OB_DEFAULT_ICON_WIDTH,
                                        OB_DEFAULT_ICON_HEIGHT,
@@ -615,32 +638,39 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
         RrAppearanceCopy(theme->a_menu_selected);
 
     /* read appearances for non-decorations (on-screen-display) */
-    if (!read_appearance(db, inst, "osd.bg", theme->osd_hilite_bg, FALSE)) {
-        RrAppearanceFree(theme->osd_hilite_bg);
-        theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title);
+    if (!read_appearance(db, inst, "osd.bg", theme->osd_bg, FALSE)) {
+        RrAppearanceFree(theme->osd_bg);
+        theme->osd_bg = RrAppearanceCopy(theme->a_focused_title);
     }
-    if (!read_appearance(db, inst, "osd.label.bg",
+    if (!read_appearance(db, inst, "osd.active.label.bg",
+                         theme->osd_hilite_label, TRUE) &&
+        !read_appearance(db, inst, "osd.label.bg",
                          theme->osd_hilite_label, TRUE)) {
         RrAppearanceFree(theme->osd_hilite_label);
         theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label);
     }
+    if (!read_appearance(db, inst, "osd.inactive.label.bg",
+                         theme->osd_unhilite_label, TRUE)) {
+        RrAppearanceFree(theme->osd_unhilite_label);
+        theme->osd_unhilite_label = RrAppearanceCopy(theme->a_unfocused_label);
+    }
     /* osd_hilite_fg can't be parentrel */
     if (!read_appearance(db, inst, "osd.hilight.bg",
-                         theme->osd_hilite_fg, FALSE)) {
-        RrAppearanceFree(theme->osd_hilite_fg);
+                         theme->osd_hilite_bg, FALSE)) {
+        RrAppearanceFree(theme->osd_hilite_bg);
         if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL)
-            theme->osd_hilite_fg = RrAppearanceCopy(theme->a_focused_label);
+            theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_label);
         else
-            theme->osd_hilite_fg = RrAppearanceCopy(theme->a_focused_title);
+            theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title);
     }
     /* osd_unhilite_fg can't be parentrel either */
     if (!read_appearance(db, inst, "osd.unhilight.bg",
-                         theme->osd_unhilite_fg, FALSE)) {
-        RrAppearanceFree(theme->osd_unhilite_fg);
+                         theme->osd_unhilite_bg, FALSE)) {
+        RrAppearanceFree(theme->osd_unhilite_bg);
         if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL)
-            theme->osd_unhilite_fg=RrAppearanceCopy(theme->a_unfocused_label);
+            theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_label);
         else
-            theme->osd_unhilite_fg=RrAppearanceCopy(theme->a_unfocused_title);
+            theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_title);
     }
 
     /* read buttons textures */
@@ -897,10 +927,14 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
 
     theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
     theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
-    theme->osd_hilite_label->texture[0].data.text.font = theme->osd_font;
-    theme->osd_hilite_label->texture[0].data.text.color = theme->osd_color;
+    theme->osd_hilite_label->texture[0].data.text.font =
+        theme->osd_font_hilite;
+    theme->osd_hilite_label->texture[0].data.text.color =
+        theme->osd_text_active_color;
 
-    if (read_string(db, "osd.label.text.font", &str)) {
+    if (read_string(db, "osd.active.label.text.font", &str) ||
+        read_string(db, "osd.label.text.font", &str))
+    {
         char *p;
         gint i = 0;
         gint j;
@@ -909,8 +943,6 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
                 i = parse_inline_number(p + strlen("shadowoffset="));
             else
                 i = 1;
-            theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
-            theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
             theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i;
             theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i;
         }
@@ -920,11 +952,11 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
             j = (i > 0 ? 0 : 255);
             i = ABS(i*255/100);
 
-            theme->osd_shadow_color = RrColorNew(inst, j, j, j);
-            theme->osd_shadow_alpha = i;
+            theme->osd_text_active_shadow_color = RrColorNew(inst, j, j, j);
+            theme->osd_text_active_shadow_alpha = i;
         } else {
-            theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
-            theme->osd_shadow_alpha = 50;
+            theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0);
+            theme->osd_text_active_shadow_alpha = 50;
         }
     } else {
         /* inherit the font settings from the focused label */
@@ -933,20 +965,21 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
         theme->osd_hilite_label->texture[0].data.text.shadow_offset_y =
             theme->a_focused_label->texture[0].data.text.shadow_offset_y;
         if (theme->title_focused_shadow_color)
-            theme->osd_shadow_color =
+            theme->osd_text_active_shadow_color =
                 RrColorNew(inst,
                            theme->title_focused_shadow_color->r,
                            theme->title_focused_shadow_color->g,
                            theme->title_focused_shadow_color->b);
         else
-            theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
-        theme->osd_shadow_alpha = theme->title_focused_shadow_alpha;
+            theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0);
+        theme->osd_text_active_shadow_alpha =
+            theme->title_focused_shadow_alpha;
     }
 
     theme->osd_hilite_label->texture[0].data.text.shadow_color =
-        theme->osd_shadow_color;
+        theme->osd_text_active_shadow_color;
     theme->osd_hilite_label->texture[0].data.text.shadow_alpha =
-        theme->osd_shadow_alpha;
+        theme->osd_text_active_shadow_alpha;
 
     theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT;
     theme->a_unfocused_label->texture[0].data.text.justify = winjust;
@@ -986,6 +1019,61 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
     theme->a_unfocused_label->texture[0].data.text.shadow_alpha =
         theme->title_unfocused_shadow_alpha;
 
+    theme->osd_unhilite_label->texture[0].type = RR_TEXTURE_TEXT;
+    theme->osd_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
+    theme->osd_unhilite_label->texture[0].data.text.font =
+        theme->osd_font_unhilite;
+    theme->osd_unhilite_label->texture[0].data.text.color =
+        theme->osd_text_inactive_color;
+
+    if (read_string(db, "osd.inactive.label.text.font", &str))
+    {
+        char *p;
+        gint i = 0;
+        gint j;
+        if (strstr(str, "shadow=y")) {
+            if ((p = strstr(str, "shadowoffset=")))
+                i = parse_inline_number(p + strlen("shadowoffset="));
+            else
+                i = 1;
+            theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x=i;
+            theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y=i;
+        }
+        if ((p = strstr(str, "shadowtint=")))
+        {
+            i = parse_inline_number(p + strlen("shadowtint="));
+            j = (i > 0 ? 0 : 255);
+            i = ABS(i*255/100);
+
+            theme->osd_text_inactive_shadow_color = RrColorNew(inst, j, j, j);
+            theme->osd_text_inactive_shadow_alpha = i;
+        } else {
+            theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0);
+            theme->osd_text_inactive_shadow_alpha = 50;
+        }
+    } else {
+        /* inherit the font settings from the unfocused label */
+        theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x =
+            theme->a_unfocused_label->texture[0].data.text.shadow_offset_x;
+        theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y =
+            theme->a_unfocused_label->texture[0].data.text.shadow_offset_y;
+        if (theme->title_unfocused_shadow_color)
+            theme->osd_text_inactive_shadow_color =
+                RrColorNew(inst,
+                           theme->title_unfocused_shadow_color->r,
+                           theme->title_unfocused_shadow_color->g,
+                           theme->title_unfocused_shadow_color->b);
+        else
+            theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0);
+        theme->osd_text_inactive_shadow_alpha =
+            theme->title_unfocused_shadow_alpha;
+    }
+
+    theme->osd_unhilite_label->texture[0].data.text.shadow_color =
+        theme->osd_text_inactive_shadow_color;
+    theme->osd_unhilite_label->texture[0].data.text.shadow_alpha =
+        theme->osd_text_inactive_shadow_alpha;
+
     theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
     theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
     theme->a_menu_text_title->texture[0].data.text.font =
@@ -1430,8 +1518,10 @@ void RrThemeFree(RrTheme *theme)
         RrColorFree(theme->menu_disabled_selected_color);
         RrColorFree(theme->title_focused_shadow_color);
         RrColorFree(theme->title_unfocused_shadow_color);
-        RrColorFree(theme->osd_color);
-        RrColorFree(theme->osd_shadow_color);
+        RrColorFree(theme->osd_text_active_color);
+        RrColorFree(theme->osd_text_inactive_color);
+        RrColorFree(theme->osd_text_active_shadow_color);
+        RrColorFree(theme->osd_text_inactive_shadow_color);
         RrColorFree(theme->menu_title_shadow_color);
         RrColorFree(theme->menu_text_normal_shadow_color);
         RrColorFree(theme->menu_text_selected_shadow_color);
@@ -1470,12 +1560,15 @@ void RrThemeFree(RrTheme *theme)
         RrPixmapMaskFree(theme->close_hover_mask);
         RrPixmapMaskFree(theme->close_pressed_mask);
         RrPixmapMaskFree(theme->menu_bullet_mask);
+        RrPixmapMaskFree(theme->down_arrow_mask);
+        RrPixmapMaskFree(theme->up_arrow_mask);
 
         RrFontClose(theme->win_font_focused);
         RrFontClose(theme->win_font_unfocused);
         RrFontClose(theme->menu_title_font);
         RrFontClose(theme->menu_font);
-        RrFontClose(theme->osd_font);
+        RrFontClose(theme->osd_font_hilite);
+        RrFontClose(theme->osd_font_unhilite);
 
         RrAppearanceFree(theme->a_disabled_focused_max);
         RrAppearanceFree(theme->a_disabled_unfocused_max);
@@ -1559,10 +1652,11 @@ void RrThemeFree(RrTheme *theme)
         RrAppearanceFree(theme->a_menu_bullet_selected);
         RrAppearanceFree(theme->a_clear);
         RrAppearanceFree(theme->a_clear_tex);
+        RrAppearanceFree(theme->osd_bg);
         RrAppearanceFree(theme->osd_hilite_bg);
-        RrAppearanceFree(theme->osd_hilite_fg);
         RrAppearanceFree(theme->osd_hilite_label);
-        RrAppearanceFree(theme->osd_unhilite_fg);
+        RrAppearanceFree(theme->osd_unhilite_bg);
+        RrAppearanceFree(theme->osd_unhilite_label);
 
         g_free(theme);
     }
@@ -1580,6 +1674,10 @@ static XrmDatabase loaddb(const gchar *name, gchar **path)
             *path = g_path_get_dirname(s);
         g_free(s);
     } else {
+        ObtPaths *p;
+
+        p = obt_paths_new();
+
         /* XXX backwards compatibility, remove me sometime later */
         s = g_build_filename(g_get_home_dir(), ".themes", name,
                              "openbox-3", "themerc", NULL);
@@ -1587,8 +1685,7 @@ static XrmDatabase loaddb(const gchar *name, gchar **path)
             *path = g_path_get_dirname(s);
         g_free(s);
 
-        for (it = parse_xdg_data_dir_paths(); !db && it;
-             it = g_slist_next(it))
+        for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it))
         {
             s = g_build_filename(it->data, "themes", name,
                                  "openbox-3", "themerc", NULL);
@@ -1596,6 +1693,8 @@ static XrmDatabase loaddb(const gchar *name, gchar **path)
                 *path = g_path_get_dirname(s);
             g_free(s);
         }
+
+        obt_paths_unref(p);
     }
 
     if (db == NULL) {
similarity index 93%
rename from render/theme.h
rename to obrender/theme.h
index a14dac2..3f9063e 100644 (file)
@@ -34,7 +34,8 @@ struct _RrTheme {
     RrFont *win_font_unfocused;
     RrFont *menu_title_font;
     RrFont *menu_font;
-    RrFont *osd_font;
+    RrFont *osd_font_hilite;
+    RrFont *osd_font_unhilite;
 
     /* style settings - geometry */
     gint paddingx;
@@ -96,9 +97,12 @@ struct _RrTheme {
     gchar    title_focused_shadow_alpha;
     RrColor *title_unfocused_shadow_color;
     gchar    title_unfocused_shadow_alpha;
-    RrColor *osd_color;
-    RrColor *osd_shadow_color;
-    gchar    osd_shadow_alpha;
+    RrColor *osd_text_active_color;
+    RrColor *osd_text_inactive_color;
+    RrColor *osd_text_active_shadow_color;
+    RrColor *osd_text_inactive_shadow_color;
+    gchar    osd_text_active_shadow_alpha;
+    gchar    osd_text_inactive_shadow_alpha;
     RrColor *menu_title_shadow_color;
     gchar    menu_title_shadow_alpha;
     RrColor *menu_text_normal_shadow_color;
@@ -151,6 +155,9 @@ struct _RrTheme {
     RrPixmapMask *menu_toggle_mask; /* menu boolean */
 #endif
 
+    RrPixmapMask *down_arrow_mask;
+    RrPixmapMask *up_arrow_mask;
+
     /* global appearances */
     RrAppearance *a_disabled_focused_max;
     RrAppearance *a_disabled_unfocused_max;
@@ -236,10 +243,11 @@ struct _RrTheme {
     RrAppearance *a_clear;     /* clear with no texture */
     RrAppearance *a_clear_tex; /* clear with a texture */
 
+    RrAppearance *osd_bg; /* can never be parent relative */
     RrAppearance *osd_hilite_bg; /* can never be parent relative */
-    RrAppearance *osd_hilite_fg; /* can never be parent relative */
     RrAppearance *osd_hilite_label; /* can be parent relative */
-    RrAppearance *osd_unhilite_fg; /* can never be parent relative */
+    RrAppearance *osd_unhilite_bg; /* can never be parent relative */
+    RrAppearance *osd_unhilite_label; /* can be parent relative */
 
     gchar *name;
 };
@@ -250,7 +258,7 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *theme,
                     gboolean allow_fallback,
                     RrFont *active_window_font, RrFont *inactive_window_font,
                     RrFont *menu_title_font, RrFont *menu_item_font,
-                    RrFont *osd_font);
+                    RrFont *active_osd_font, RrFont *inactive_osd_font);
 void RrThemeFree(RrTheme *theme);
 
 G_END_DECLS
diff --git a/obrender/version.h.in b/obrender/version.h.in
new file mode 100644 (file)
index 0000000..0ff30b5
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef rr__version_h
+#define rr__version_h
+
+#define RR_MAJOR_VERSION @RR_MAJOR_VERSION@
+#define RR_MINOR_VERSION @RR_MINOR_VERSION@
+#define RR_MICRO_VERSION @RR_MICRO_VERSION@
+#define RR_VERSION RR_MAJOR_VERSION.RR_MINOR_VERSION.RR_MICRO_VERSION
+
+#define RR_CHECK_VERSION(major,minor,micro) \
+    (RR_MAJOR_VERSION > (major) || \
+     (RR_MAJOR_VERSION == (major) && RR_MINOR_VERSION > (minor)) || \
+     (RR_MAJOR_VERSION == (major) && RR_MINOR_VERSION == (minor) && \
+      RR_MICRO_VERSION >= (micro)))
+
+#endif
similarity index 100%
rename from render/Makefile
rename to obt/Makefile
diff --git a/obt/display.c b/obt/display.c
new file mode 100644 (file)
index 0000000..f34fc57
--- /dev/null
@@ -0,0 +1,152 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/display.c for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/display.h"
+#include "obt/prop.h"
+#include "obt/internal.h"
+#include "obt/keyboard.h"
+
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+Display* obt_display = NULL;
+
+gboolean obt_display_error_occured = FALSE;
+
+gboolean obt_display_extension_xkb       = FALSE;
+gint     obt_display_extension_xkb_basep;
+gboolean obt_display_extension_shape     = FALSE;
+gint     obt_display_extension_shape_basep;
+gboolean obt_display_extension_xinerama  = FALSE;
+gint     obt_display_extension_xinerama_basep;
+gboolean obt_display_extension_randr     = FALSE;
+gint     obt_display_extension_randr_basep;
+gboolean obt_display_extension_sync      = FALSE;
+gint     obt_display_extension_sync_basep;
+
+static gint xerror_handler(Display *d, XErrorEvent *e);
+
+static gboolean xerror_ignore = FALSE;
+
+gboolean obt_display_open(const char *display_name)
+{
+    gchar *n;
+    Display *d = NULL;
+
+    n = display_name ? g_strdup(display_name) : NULL;
+    obt_display = d = XOpenDisplay(n);
+    if (d) {
+        gint junk;
+        (void)junk;
+
+        if (fcntl(ConnectionNumber(d), F_SETFD, 1) == -1)
+            g_message("Failed to set display as close-on-exec");
+        XSetErrorHandler(xerror_handler);
+
+        /* read what extensions are present */
+#ifdef XKB
+        obt_display_extension_xkb =
+            XkbQueryExtension(d, &junk,
+                              &obt_display_extension_xkb_basep, &junk,
+                              NULL, NULL);
+        if (!obt_display_extension_xkb)
+            g_message("XKB extension is not present on the server");
+#endif
+
+#ifdef SHAPE
+        obt_display_extension_shape =
+            XShapeQueryExtension(d, &obt_display_extension_shape_basep,
+                                 &junk);
+        if (!obt_display_extension_shape)
+            g_message("X Shape extension is not present on the server");
+#endif
+
+#ifdef XINERAMA
+        obt_display_extension_xinerama =
+            XineramaQueryExtension(d,
+                                   &obt_display_extension_xinerama_basep,
+                                   &junk) && XineramaIsActive(d);
+        if (!obt_display_extension_xinerama)
+            g_message("Xinerama extension is not present on the server");
+#endif
+
+#ifdef XRANDR
+        obt_display_extension_randr =
+            XRRQueryExtension(d, &obt_display_extension_randr_basep,
+                              &junk);
+        if (!obt_display_extension_randr)
+            g_message("XRandR extension is not present on the server");
+#endif
+
+#ifdef SYNC
+        obt_display_extension_sync =
+            XSyncQueryExtension(d, &obt_display_extension_sync_basep,
+                                &junk) && XSyncInitialize(d, &junk, &junk);
+        if (!obt_display_extension_sync)
+            g_message("X Sync extension is not present on the server or is an "
+                      "incompatible version");
+#endif
+
+        obt_prop_startup();
+        obt_keyboard_reload();
+    }
+    g_free(n);
+
+    return obt_display != NULL;
+}
+
+void obt_display_close(void)
+{
+    obt_keyboard_shutdown();
+    if (obt_display) XCloseDisplay(obt_display);
+}
+
+static gint xerror_handler(Display *d, XErrorEvent *e)
+{
+#ifdef DEBUG
+    gchar errtxt[128];
+
+    XGetErrorText(d, e->error_code, errtxt, 127);
+    if (!xerror_ignore) {
+        if (e->error_code == BadWindow)
+            /*g_debug(_("X Error: %s\n"), errtxt)*/;
+        else
+            g_error("X Error: %s", errtxt);
+    } else
+        g_debug("Ignoring XError code %d '%s'", e->error_code, errtxt);
+#else
+    (void)d; (void)e;
+#endif
+
+    obt_display_error_occured = TRUE;
+    return 0;
+}
+
+void obt_display_ignore_errors(gboolean ignore)
+{
+    XSync(obt_display, FALSE);
+    xerror_ignore = ignore;
+    if (ignore) obt_display_error_occured = FALSE;
+}
diff --git a/obt/display.h b/obt/display.h
new file mode 100644 (file)
index 0000000..ff20f9c
--- /dev/null
@@ -0,0 +1,68 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/display.h for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_display_h
+#define __obt_display_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+#include <X11/Xutil.h> /* shape.h uses Region which is in here */
+#ifdef    XKB
+#include <X11/XKBlib.h>
+#endif
+#ifdef    SHAPE
+#include <X11/extensions/shape.h>
+#endif
+#ifdef    XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+#ifdef    XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef    SYNC
+#include <X11/extensions/sync.h>
+#endif
+
+G_BEGIN_DECLS
+
+extern gboolean obt_display_error_occured;
+
+extern gboolean obt_display_extension_xkb;
+extern gint     obt_display_extension_xkb_basep;
+extern gboolean obt_display_extension_shape;
+extern gint     obt_display_extension_shape_basep;
+extern gboolean obt_display_extension_xinerama;
+extern gint     obt_display_extension_xinerama_basep;
+extern gboolean obt_display_extension_randr;
+extern gint     obt_display_extension_randr_basep;
+extern gboolean obt_display_extension_sync;
+extern gint     obt_display_extension_sync_basep;
+
+extern Display* obt_display;
+
+gboolean obt_display_open(const char *display_name);
+void     obt_display_close(void);
+
+void     obt_display_ignore_errors(gboolean ignore);
+
+#define  obt_root(screen) (RootWindow(obt_display, screen))
+
+G_END_DECLS
+
+#endif /*__obt_display_h*/
similarity index 70%
rename from openbox/xerror.h
rename to obt/internal.h
index de1aa5a..818107d 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   xerror.h for the Openbox window manager
+   obt/internal.h for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
    Copyright (c) 2003-2007   Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#ifndef __xerror_h
-#define __xerror_h
+#ifndef __obt_internal_h
+#define __obt_internal_h
 
-#include <X11/Xlib.h>
-#include <glib.h>
+void obt_prop_startup(void);
 
-/* can be used to track errors */
-extern gboolean xerror_occured;
+void obt_keyboard_shutdown(void);
 
-gint xerror_handler(Display *, XErrorEvent *);
-
-void xerror_set_ignore(gboolean ignore);
-
-#endif
+#endif /* __obt_internal_h */
similarity index 65%
rename from openbox/modkeys.c
rename to obt/keyboard.c
index e897ccb..264201a 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   modkeys.c for the Openbox window manager
+   obt/keyboard.c for the Openbox window manager
    Copyright (c) 2007        Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
@@ -16,8 +16,8 @@
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#include "modkeys.h"
-#include "openbox.h"
+#include "obt/display.h"
+#include "obt/keyboard.h"
 
 #include <X11/Xlib.h>
 #include <X11/keysym.h>
 #define nth_mask(n) (1 << n)
 
 static void set_modkey_mask(guchar mask, KeySym sym);
+void obt_keyboard_shutdown();
 
 static XModifierKeymap *modmap;
 static KeySym *keymap;
 static gint min_keycode, max_keycode, keysyms_per_keycode;
 /* This is a bitmask of the different masks for each modifier key */
-static guchar modkeys_keys[OB_MODKEY_NUM_KEYS];
+static guchar modkeys_keys[OBT_KEYBOARD_NUM_MODKEYS];
 
 static gboolean alt_l = FALSE;
 static gboolean meta_l = FALSE;
 static gboolean super_l = FALSE;
 static gboolean hyper_l = FALSE;
 
-void modkeys_startup(gboolean reconfigure)
+static gboolean started = FALSE;
+
+void obt_keyboard_reload(void)
 {
     gint i, j, k;
 
+    if (started) obt_keyboard_shutdown(); /* free stuff */
+    started = TRUE;
+
     /* reset the keys to not be bound to any masks */
-    for (i = 0; i < OB_MODKEY_NUM_KEYS; ++i)
+    for (i = 0; i < OBT_KEYBOARD_NUM_MODKEYS; ++i)
         modkeys_keys[i] = 0;
 
-    modmap = XGetModifierMapping(ob_display);
+    modmap = XGetModifierMapping(obt_display);
     g_assert(modmap->max_keypermod > 0);
 
-    XDisplayKeycodes(ob_display, &min_keycode, &max_keycode);
-    keymap = XGetKeyboardMapping(ob_display, min_keycode,
+    XDisplayKeycodes(obt_display, &min_keycode, &max_keycode);
+    keymap = XGetKeyboardMapping(obt_display, min_keycode,
                                  max_keycode - min_keycode + 1,
                                  &keysyms_per_keycode);
 
@@ -86,18 +92,21 @@ void modkeys_startup(gboolean reconfigure)
     }
 
     /* CapsLock, Shift, and Control are special and hard-coded */
-    modkeys_keys[OB_MODKEY_KEY_CAPSLOCK] = LockMask;
-    modkeys_keys[OB_MODKEY_KEY_SHIFT] = ShiftMask;
-    modkeys_keys[OB_MODKEY_KEY_CONTROL] = ControlMask;
+    modkeys_keys[OBT_KEYBOARD_MODKEY_CAPSLOCK] = LockMask;
+    modkeys_keys[OBT_KEYBOARD_MODKEY_SHIFT] = ShiftMask;
+    modkeys_keys[OBT_KEYBOARD_MODKEY_CONTROL] = ControlMask;
 }
 
-void modkeys_shutdown(gboolean reconfigure)
+void obt_keyboard_shutdown(void)
 {
     XFreeModifiermap(modmap);
+    modmap = NULL;
     XFree(keymap);
+    keymap = NULL;
+    started = FALSE;
 }
 
-guint modkeys_keycode_to_mask(guint keycode)
+guint obt_keyboard_keycode_to_modmask(guint keycode)
 {
     gint i, j;
     guint mask = 0;
@@ -116,7 +125,7 @@ guint modkeys_keycode_to_mask(guint keycode)
     return mask;
 }
 
-guint modkeys_only_modifier_masks(guint mask)
+guint obt_keyboard_only_modmasks(guint mask)
 {
     mask &= ALL_MASKS;
     /* strip off these lock keys. they shouldn't affect key bindings */
@@ -124,12 +133,12 @@ guint modkeys_only_modifier_masks(guint mask)
                           because you could bind it to something else and it
                           should work as that modifier then. i think capslock
                           is weird in xkb. */
-    mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_NUMLOCK);
-    mask &= ~modkeys_key_to_mask(OB_MODKEY_KEY_SCROLLLOCK);
+    mask &= ~obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_NUMLOCK);
+    mask &= ~obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SCROLLLOCK);
     return mask;
 }
 
-guint modkeys_key_to_mask(ObModkeysKey key)
+guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key)
 {
     return modkeys_keys[key];
 }
@@ -139,44 +148,44 @@ static void set_modkey_mask(guchar mask, KeySym sym)
     /* find what key this is, and bind it to the mask */
 
     if (sym == XK_Num_Lock)
-        modkeys_keys[OB_MODKEY_KEY_NUMLOCK] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_NUMLOCK] |= mask;
     else if (sym == XK_Scroll_Lock)
-        modkeys_keys[OB_MODKEY_KEY_SCROLLLOCK] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SCROLLLOCK] |= mask;
 
     else if (sym == XK_Super_L && super_l)
-        modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SUPER] |= mask;
     else if (sym == XK_Super_L && !super_l)
         /* left takes precident over right, so erase any masks the right
            key may have set */
-        modkeys_keys[OB_MODKEY_KEY_SUPER] = mask, super_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SUPER] = mask, super_l = TRUE;
     else if (sym == XK_Super_R && !super_l)
-        modkeys_keys[OB_MODKEY_KEY_SUPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_SUPER] |= mask;
 
     else if (sym == XK_Hyper_L && hyper_l)
-        modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_HYPER] |= mask;
     else if (sym == XK_Hyper_L && !hyper_l)
-        modkeys_keys[OB_MODKEY_KEY_HYPER] = mask, hyper_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_HYPER] = mask, hyper_l = TRUE;
     else if (sym == XK_Hyper_R && !hyper_l)
-        modkeys_keys[OB_MODKEY_KEY_HYPER] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_HYPER] |= mask;
 
     else if (sym == XK_Alt_L && alt_l)
-        modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_ALT] |= mask;
     else if (sym == XK_Alt_L && !alt_l)
-        modkeys_keys[OB_MODKEY_KEY_ALT] = mask, alt_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_ALT] = mask, alt_l = TRUE;
     else if (sym == XK_Alt_R && !alt_l)
-        modkeys_keys[OB_MODKEY_KEY_ALT] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_ALT] |= mask;
 
     else if (sym == XK_Meta_L && meta_l)
-        modkeys_keys[OB_MODKEY_KEY_META] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_META] |= mask;
     else if (sym == XK_Meta_L && !meta_l)
-        modkeys_keys[OB_MODKEY_KEY_META] = mask, meta_l = TRUE;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_META] = mask, meta_l = TRUE;
     else if (sym == XK_Meta_R && !meta_l)
-        modkeys_keys[OB_MODKEY_KEY_META] |= mask;
+        modkeys_keys[OBT_KEYBOARD_MODKEY_META] |= mask;
 
     /* CapsLock, Shift, and Control are special and hard-coded */
 }
 
-KeyCode* modkeys_sym_to_code(KeySym sym)
+KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym)
 {
     KeyCode *ret;
     gint i, j, n;
@@ -195,3 +204,29 @@ KeyCode* modkeys_sym_to_code(KeySym sym)
             }
     return ret;
 }
+
+gchar *obt_keyboard_keycode_to_string(guint keycode)
+{
+    KeySym sym;
+
+    if ((sym = XKeycodeToKeysym(obt_display, keycode, 0)) != NoSymbol)
+        return g_locale_to_utf8(XKeysymToString(sym), -1, NULL, NULL, NULL);
+    return NULL;
+}
+
+gunichar obt_keyboard_keycode_to_unichar(guint keycode)
+{
+    gunichar unikey = 0;
+    char *key;
+
+    if ((key = obt_keyboard_keycode_to_string(keycode)) != NULL &&
+        /* don't accept keys that aren't a single letter, like "space" */
+        key[1] == '\0')
+    {
+        unikey = g_utf8_get_char_validated(key, -1);
+        if (unikey == (gunichar)-1 || unikey == (gunichar)-2 || unikey == 0)
+            unikey = 0;
+    }
+    g_free(key);
+    return unikey;
+}
similarity index 51%
rename from openbox/modkeys.h
rename to obt/keyboard.h
index 8e795f7..4fb6018 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   masks.h for the Openbox window manager
+   obt/keyboard.h for the Openbox window manager
    Copyright (c) 2007        Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#ifndef ob__modkeys_h
-#define ob__modkeys_h
+#ifndef __obt_keyboard_h
+#define __obt_keyboard_h
 
 #include <glib.h>
 #include <X11/Xlib.h>
 
+G_BEGIN_DECLS
+
 /*! These keys are bound to the modifier masks in any fashion,
   except for CapsLock, Shift, and Control. */
 typedef enum {
-    OB_MODKEY_KEY_CAPSLOCK,
-    OB_MODKEY_KEY_NUMLOCK,
-    OB_MODKEY_KEY_SCROLLLOCK,
-    OB_MODKEY_KEY_SHIFT,
-    OB_MODKEY_KEY_CONTROL,
-    OB_MODKEY_KEY_SUPER,
-    OB_MODKEY_KEY_HYPER,
-    OB_MODKEY_KEY_META,
-    OB_MODKEY_KEY_ALT,
-
-    OB_MODKEY_NUM_KEYS
-} ObModkeysKey;
-
-void modkeys_startup(gboolean reconfigure);
-void modkeys_shutdown(gboolean reconfigure);
-
-/*! Get the modifier masks for a keycode. (eg. a keycode bound to Alt_L could
+    OBT_KEYBOARD_MODKEY_CAPSLOCK,
+    OBT_KEYBOARD_MODKEY_NUMLOCK,
+    OBT_KEYBOARD_MODKEY_SCROLLLOCK,
+    OBT_KEYBOARD_MODKEY_SHIFT,
+    OBT_KEYBOARD_MODKEY_CONTROL,
+    OBT_KEYBOARD_MODKEY_SUPER,
+    OBT_KEYBOARD_MODKEY_HYPER,
+    OBT_KEYBOARD_MODKEY_META,
+    OBT_KEYBOARD_MODKEY_ALT,
+
+    OBT_KEYBOARD_NUM_MODKEYS
+} ObtModkeysKey;
+
+void obt_keyboard_reload(void);
+
+/*! Get the modifier mask(s) for a KeyCode. (eg. a keycode bound to Alt_L could
   return a mask of (Mod1Mask | Mask3Mask)) */
-guint modkeys_keycode_to_mask(guint keycode);
+guint obt_keyboard_keycode_to_modmask(guint keycode);
 
 /*! Strip off all modifiers except for the modifier keys. This strips stuff
-  like Button1Mask, and also LockMask, NumLockMask, and ScrollLockMask */
-guint modkeys_only_modifier_masks(guint mask);
+  like Button1Mask, and also LockMask, NumlockMask, and ScrolllockMask */
+guint obt_keyboard_only_modmasks(guint mask);
 
 /*! Get the modifier masks for a modifier key. This includes both the left and
   right keys when there are both. */
-guint modkeys_key_to_mask(ObModkeysKey key);
+guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key);
 
 /*! Convert a KeySym to all the KeyCodes which generate it. */
-KeyCode* modkeys_sym_to_code(KeySym sym);
+KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym);
+
+/*! Give the string form of a KeyCode */
+gchar *obt_keyboard_keycode_to_string(guint keycode);
+
+/*! Translate a KeyCode to the unicode character it represents */
+gunichar obt_keyboard_keycode_to_unichar(guint keycode);
+
+
+G_END_DECLS
 
-#endif
+#endif /* __obt_keyboard_h */
similarity index 75%
rename from openbox/mainloop.c
rename to obt/mainloop.c
index b292120..bf866ae 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
-   mainloop.c for the Openbox window manager
+   obt/mainloop.c for the Openbox window manager
    Copyright (c) 2006        Mikael Magnusson
    Copyright (c) 2003-2007   Dana Jansens
 
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#include "mainloop.h"
-#include "event.h"
+#include "obt/mainloop.h"
+#include "obt/display.h"
+#include "obt/util.h"
 
+#ifdef HAVE_STDIO_H
 #include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SIGNAL_H
 #include <signal.h>
+#endif
 
-typedef struct _ObMainLoopTimer             ObMainLoopTimer;
-typedef struct _ObMainLoopSignal            ObMainLoopSignal;
-typedef struct _ObMainLoopSignalHandlerType ObMainLoopSignalHandlerType;
-typedef struct _ObMainLoopXHandlerType      ObMainLoopXHandlerType;
-typedef struct _ObMainLoopFdHandlerType     ObMainLoopFdHandlerType;
+typedef struct _ObtMainLoopTimer             ObtMainLoopTimer;
+typedef struct _ObtMainLoopSignal            ObtMainLoopSignal;
+typedef struct _ObtMainLoopSignalHandlerType ObtMainLoopSignalHandlerType;
+typedef struct _ObtMainLoopXHandlerType      ObtMainLoopXHandlerType;
+typedef struct _ObtMainLoopFdHandlerType     ObtMainLoopFdHandlerType;
 
 /* this should be more than the number of possible signals on any
    architecture... */
 #define NUM_SIGNALS 99
 
-/* all created ObMainLoops. Used by the signal handler to pass along signals */
+/* all created ObtMainLoops. Used by the signal handler to pass along
+   signals */
 static GSList *all_loops;
 
 /* signals are global to all loops */
@@ -64,11 +77,13 @@ static gint core_signals[] =
 #define NUM_CORE_SIGNALS (sizeof(core_signals) / sizeof(core_signals[0]))
 
 static void sighandler(gint sig);
-static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait);
+static void timer_dispatch(ObtMainLoop *loop, GTimeVal **wait);
 static void fd_handler_destroy(gpointer data);
+static void calc_max_fd(ObtMainLoop *loop);
 
-struct _ObMainLoop
+struct _ObtMainLoop
 {
+    gint ref;
     Display *display;
 
     gboolean run;     /* do keep running */
@@ -90,7 +105,7 @@ struct _ObMainLoop
     GSList *signal_handlers[NUM_SIGNALS];
 };
 
-struct _ObMainLoopTimer
+struct _ObtMainLoopTimer
 {
     gulong delay;
     GSourceFunc func;
@@ -110,42 +125,41 @@ struct _ObMainLoopTimer
     gboolean fired;
 };
 
-struct _ObMainLoopSignalHandlerType
+struct _ObtMainLoopSignalHandlerType
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
     gint signal;
     gpointer data;
-    ObMainLoopSignalHandler func;
+    ObtMainLoopSignalHandler func;
     GDestroyNotify destroy;
 };
 
-struct _ObMainLoopXHandlerType
+struct _ObtMainLoopXHandlerType
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
     gpointer data;
-    ObMainLoopXHandler func;
+    ObtMainLoopXHandler func;
     GDestroyNotify destroy;
 };
 
-struct _ObMainLoopFdHandlerType
+struct _ObtMainLoopFdHandlerType
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
     gint fd;
     gpointer data;
-    ObMainLoopFdHandler func;
+    ObtMainLoopFdHandler func;
     GDestroyNotify destroy;
 };
 
-ObMainLoop *ob_main_loop_new(Display *display)
+ObtMainLoop *obt_main_loop_new(void)
 {
-    ObMainLoop *loop;
+    ObtMainLoop *loop;
 
-    loop = g_new0(ObMainLoop, 1);
-    loop->display = display;
-    loop->fd_x = ConnectionNumber(display);
+    loop = g_new0(ObtMainLoop, 1);
+    loop->ref = 1;
     FD_ZERO(&loop->fd_set);
-    FD_SET(loop->fd_x, &loop->fd_set);
-    loop->fd_max = loop->fd_x;
+    loop->fd_x = -1;
+    loop->fd_max = -1;
 
     loop->fd_handlers = g_hash_table_new_full(g_int_hash, g_int_equal,
                                               NULL, fd_handler_destroy);
@@ -185,24 +199,29 @@ ObMainLoop *ob_main_loop_new(Display *display)
     return loop;
 }
 
-void ob_main_loop_destroy(ObMainLoop *loop)
+void obt_main_loop_ref(ObtMainLoop *loop)
+{
+    ++loop->ref;
+}
+
+void obt_main_loop_unref(ObtMainLoop *loop)
 {
     guint i;
     GSList *it, *next;
 
-    if (loop) {
+    if (loop && --loop->ref == 0) {
         g_assert(loop->running == FALSE);
 
         for (it = loop->x_handlers; it; it = next) {
-            ObMainLoopXHandlerType *h = it->data;
+            ObtMainLoopXHandlerType *h = it->data;
             next = g_slist_next(it);
-            ob_main_loop_x_remove(loop, h->func);
+            obt_main_loop_x_remove(loop, h->func);
         }
 
         g_hash_table_destroy(loop->fd_handlers);
 
         for (it = loop->timers; it; it = g_slist_next(it)) {
-            ObMainLoopTimer *t = it->data;
+            ObtMainLoopTimer *t = it->data;
             if (t->destroy) t->destroy(t->data);
             g_free(t);
         }
@@ -211,9 +230,9 @@ void ob_main_loop_destroy(ObMainLoop *loop)
 
         for (i = 0; i < NUM_SIGNALS; ++i)
             for (it = loop->signal_handlers[i]; it; it = next) {
-                ObMainLoopSignalHandlerType *h = it->data;
+                ObtMainLoopSignalHandlerType *h = it->data;
                 next = g_slist_next(it);
-                ob_main_loop_signal_remove(loop, h->func);
+                obt_main_loop_signal_remove(loop, h->func);
             }
 
         all_loops = g_slist_remove(all_loops, loop);
@@ -230,7 +249,7 @@ void ob_main_loop_destroy(ObMainLoop *loop)
             }
         }
 
-        g_free(loop);
+        obt_free0(loop, ObtMainLoop, 1);
     }
 }
 
@@ -238,14 +257,14 @@ static void fd_handle_foreach(gpointer key,
                               gpointer value,
                               gpointer data)
 {
-    ObMainLoopFdHandlerType *h = value;
+    ObtMainLoopFdHandlerType *h = value;
     fd_set *set = data;
 
     if (FD_ISSET(h->fd, set))
         h->func(h->fd, h->data);
 }
 
-void ob_main_loop_run(ObMainLoop *loop)
+void obt_main_loop_run(ObtMainLoop *loop)
 {
     XEvent e;
     struct timeval *wait;
@@ -268,7 +287,7 @@ void ob_main_loop_run(ObMainLoop *loop)
                 while (loop->signals_fired[i]) {
                     for (it = loop->signal_handlers[i];
                             it; it = g_slist_next(it)) {
-                        ObMainLoopSignalHandlerType *h = it->data;
+                        ObtMainLoopSignalHandlerType *h = it->data;
                         h->func(i, h->data);
                     }
                     loop->signals_fired[i]--;
@@ -277,12 +296,12 @@ void ob_main_loop_run(ObMainLoop *loop)
             loop->signal_fired = FALSE;
 
             sigprocmask(SIG_SETMASK, &oldset, NULL);
-        } else if (XPending(loop->display)) {
+        } else if (loop->display && XPending(loop->display)) {
             do {
                 XNextEvent(loop->display, &e);
 
                 for (it = loop->x_handlers; it; it = g_slist_next(it)) {
-                    ObMainLoopXHandlerType *h = it->data;
+                    ObtMainLoopXHandlerType *h = it->data;
                     h->func(&e, h->data);
                 }
             } while (XPending(loop->display) && loop->run);
@@ -312,35 +331,45 @@ void ob_main_loop_run(ObMainLoop *loop)
     loop->running = FALSE;
 }
 
-void ob_main_loop_exit(ObMainLoop *loop)
+void obt_main_loop_exit(ObtMainLoop *loop)
 {
     loop->run = FALSE;
 }
 
 /*** XEVENT WATCHERS ***/
 
-void ob_main_loop_x_add(ObMainLoop *loop,
-                        ObMainLoopXHandler handler,
-                        gpointer data,
-                        GDestroyNotify notify)
+void obt_main_loop_x_add(ObtMainLoop *loop,
+                         ObtMainLoopXHandler handler,
+                         gpointer data,
+                         GDestroyNotify notify)
 {
-    ObMainLoopXHandlerType *h;
+    ObtMainLoopXHandlerType *h;
 
-    h = g_new(ObMainLoopXHandlerType, 1);
+    h = g_new(ObtMainLoopXHandlerType, 1);
     h->loop = loop;
     h->func = handler;
     h->data = data;
     h->destroy = notify;
+
+    if (!loop->x_handlers) {
+        g_assert(obt_display); /* is the display open? */
+
+        loop->display = obt_display;
+        loop->fd_x = ConnectionNumber(loop->display);
+        FD_SET(loop->fd_x, &loop->fd_set);
+        calc_max_fd(loop);
+    }
+
     loop->x_handlers = g_slist_prepend(loop->x_handlers, h);
 }
 
-void ob_main_loop_x_remove(ObMainLoop *loop,
-                           ObMainLoopXHandler handler)
+void obt_main_loop_x_remove(ObtMainLoop *loop,
+                            ObtMainLoopXHandler handler)
 {
     GSList *it, *next;
 
     for (it = loop->x_handlers; it; it = next) {
-        ObMainLoopXHandlerType *h = it->data;
+        ObtMainLoopXHandlerType *h = it->data;
         next = g_slist_next(it);
         if (h->func == handler) {
             loop->x_handlers = g_slist_delete_link(loop->x_handlers, it);
@@ -348,6 +377,11 @@ void ob_main_loop_x_remove(ObMainLoop *loop,
             g_free(h);
         }
     }
+
+    if (!loop->x_handlers) {
+        FD_CLR(loop->fd_x, &loop->fd_set);
+        calc_max_fd(loop);
+    }
 }
 
 /*** SIGNAL WATCHERS ***/
@@ -372,23 +406,23 @@ static void sighandler(gint sig)
         }
 
     for (it = all_loops; it; it = g_slist_next(it)) {
-        ObMainLoop *loop = it->data;
+        ObtMainLoop *loop = it->data;
         loop->signal_fired = TRUE;
         loop->signals_fired[sig]++;
     }
 }
 
-void ob_main_loop_signal_add(ObMainLoop *loop,
-                             gint signal,
-                             ObMainLoopSignalHandler handler,
-                             gpointer data,
-                             GDestroyNotify notify)
+void obt_main_loop_signal_add(ObtMainLoop *loop,
+                              gint signal,
+                              ObtMainLoopSignalHandler handler,
+                              gpointer data,
+                              GDestroyNotify notify)
 {
-    ObMainLoopSignalHandlerType *h;
+    ObtMainLoopSignalHandlerType *h;
 
     g_return_if_fail(signal < NUM_SIGNALS);
 
-    h = g_new(ObMainLoopSignalHandlerType, 1);
+    h = g_new(ObtMainLoopSignalHandlerType, 1);
     h->loop = loop;
     h->signal = signal;
     h->func = handler;
@@ -412,15 +446,15 @@ void ob_main_loop_signal_add(ObMainLoop *loop,
     all_signals[signal].installed++;
 }
 
-void ob_main_loop_signal_remove(ObMainLoop *loop,
-                                ObMainLoopSignalHandler handler)
+void obt_main_loop_signal_remove(ObtMainLoop *loop,
+                                 ObtMainLoopSignalHandler handler)
 {
     guint i;
     GSList *it, *next;
 
     for (i = 0; i < NUM_SIGNALS; ++i) {
         for (it = loop->signal_handlers[i]; it; it = next) {
-            ObMainLoopSignalHandlerType *h = it->data;
+            ObtMainLoopSignalHandlerType *h = it->data;
 
             next = g_slist_next(it);
 
@@ -447,28 +481,28 @@ void ob_main_loop_signal_remove(ObMainLoop *loop,
 
 static void max_fd_func(gpointer key, gpointer value, gpointer data)
 {
-    ObMainLoop *loop = data;
+    ObtMainLoop *loop = data;
 
     /* key is the fd */
     loop->fd_max = MAX(loop->fd_max, *(gint*)key);
 }
 
-static void calc_max_fd(ObMainLoop *loop)
+static void calc_max_fd(ObtMainLoop *loop)
 {
     loop->fd_max = loop->fd_x;
 
     g_hash_table_foreach(loop->fd_handlers, max_fd_func, loop);
 }
 
-void ob_main_loop_fd_add(ObMainLoop *loop,
-                         gint fd,
-                         ObMainLoopFdHandler handler,
-                         gpointer data,
-                         GDestroyNotify notify)
+void obt_main_loop_fd_add(ObtMainLoop *loop,
+                          gint fd,
+                          ObtMainLoopFdHandler handler,
+                          gpointer data,
+                          GDestroyNotify notify)
 {
-    ObMainLoopFdHandlerType *h;
+    ObtMainLoopFdHandlerType *h;
 
-    h = g_new(ObMainLoopFdHandlerType, 1);
+    h = g_new(ObtMainLoopFdHandlerType, 1);
     h->loop = loop;
     h->fd = fd;
     h->func = handler;
@@ -482,7 +516,7 @@ void ob_main_loop_fd_add(ObMainLoop *loop,
 
 static void fd_handler_destroy(gpointer data)
 {
-    ObMainLoopFdHandlerType *h = data;
+    ObtMainLoopFdHandlerType *h = data;
 
     FD_CLR(h->fd, &h->loop->fd_set);
 
@@ -490,16 +524,17 @@ static void fd_handler_destroy(gpointer data)
         h->destroy(h->data);
 }
 
-void ob_main_loop_fd_remove(ObMainLoop *loop,
-                            gint fd)
+void obt_main_loop_fd_remove(ObtMainLoop *loop,
+                             gint fd)
 {
     g_hash_table_remove(loop->fd_handlers, &fd);
+    calc_max_fd(loop);
 }
 
 /*** TIMEOUTS ***/
 
 #define NEAREST_TIMEOUT(loop) \
-    (((ObMainLoopTimer*)(loop)->timers->data)->timeout)
+    (((ObtMainLoopTimer*)(loop)->timers->data)->timeout)
 
 static glong timecompare(GTimeVal *a, GTimeVal *b)
 {
@@ -508,11 +543,11 @@ static glong timecompare(GTimeVal *a, GTimeVal *b)
     return a->tv_usec - b->tv_usec;
 }
 
-static void insert_timer(ObMainLoop *loop, ObMainLoopTimer *ins)
+static void insert_timer(ObtMainLoop *loop, ObtMainLoopTimer *ins)
 {
     GSList *it;
     for (it = loop->timers; it; it = g_slist_next(it)) {
-        ObMainLoopTimer *t = it->data;
+        ObtMainLoopTimer *t = it->data;
         if (timecompare(&ins->timeout, &t->timeout) <= 0) {
             loop->timers = g_slist_insert_before(loop->timers, it, ins);
             break;
@@ -522,14 +557,14 @@ static void insert_timer(ObMainLoop *loop, ObMainLoopTimer *ins)
         loop->timers = g_slist_append(loop->timers, ins);
 }
 
-void ob_main_loop_timeout_add(ObMainLoop *loop,
-                              gulong microseconds,
-                              GSourceFunc handler,
-                              gpointer data,
-                              GEqualFunc cmp,
-                              GDestroyNotify notify)
+void obt_main_loop_timeout_add(ObtMainLoop *loop,
+                               gulong microseconds,
+                               GSourceFunc handler,
+                               gpointer data,
+                               GEqualFunc cmp,
+                               GDestroyNotify notify)
 {
-    ObMainLoopTimer *t = g_new(ObMainLoopTimer, 1);
+    ObtMainLoopTimer *t = g_new(ObtMainLoopTimer, 1);
 
     g_assert(microseconds > 0); /* if it's 0 it'll cause an infinite loop */
 
@@ -546,25 +581,25 @@ void ob_main_loop_timeout_add(ObMainLoop *loop,
     insert_timer(loop, t);
 }
 
-void ob_main_loop_timeout_remove(ObMainLoop *loop,
-                                 GSourceFunc handler)
+void obt_main_loop_timeout_remove(ObtMainLoop *loop,
+                                  GSourceFunc handler)
 {
     GSList *it;
 
     for (it = loop->timers; it; it = g_slist_next(it)) {
-        ObMainLoopTimer *t = it->data;
+        ObtMainLoopTimer *t = it->data;
         if (t->func == handler)
             t->del_me = TRUE;
     }
 }
 
-void ob_main_loop_timeout_remove_data(ObMainLoop *loop, GSourceFunc handler,
-                                      gpointer data, gboolean cancel_dest)
+void obt_main_loop_timeout_remove_data(ObtMainLoop *loop, GSourceFunc handler,
+                                       gpointer data, gboolean cancel_dest)
 {
     GSList *it;
 
     for (it = loop->timers; it; it = g_slist_next(it)) {
-        ObMainLoopTimer *t = it->data;
+        ObtMainLoopTimer *t = it->data;
         if (t->func == handler && t->equal(t->data, data)) {
             t->del_me = TRUE;
             if (cancel_dest)
@@ -574,7 +609,7 @@ void ob_main_loop_timeout_remove_data(ObMainLoop *loop, GSourceFunc handler,
 }
 
 /* find the time to wait for the nearest timeout */
-static gboolean nearest_timeout_wait(ObMainLoop *loop, GTimeVal *tm)
+static gboolean nearest_timeout_wait(ObtMainLoop *loop, GTimeVal *tm)
 {
   if (loop->timers == NULL)
     return FALSE;
@@ -594,7 +629,7 @@ static gboolean nearest_timeout_wait(ObMainLoop *loop, GTimeVal *tm)
   return TRUE;
 }
 
-static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
+static void timer_dispatch(ObtMainLoop *loop, GTimeVal **wait)
 {
     GSList *it, *next;
 
@@ -603,7 +638,7 @@ static void timer_dispatch(ObMainLoop *loop, GTimeVal **wait)
     g_get_current_time(&loop->now);
 
     for (it = loop->timers; it; it = next) {
-        ObMainLoopTimer *curr;
+        ObtMainLoopTimer *curr;
 
         next = g_slist_next(it);
 
diff --git a/obt/mainloop.h b/obt/mainloop.h
new file mode 100644 (file)
index 0000000..f455d62
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/mainloop.h for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_mainloop_h
+#define __obt_mainloop_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtMainLoop ObtMainLoop;
+
+ObtMainLoop *obt_main_loop_new(void);
+void        obt_main_loop_ref(ObtMainLoop *loop);
+void        obt_main_loop_unref(ObtMainLoop *loop);
+
+typedef void (*ObtMainLoopXHandler) (const XEvent *e, gpointer data);
+
+void obt_main_loop_x_add(ObtMainLoop *loop,
+                         ObtMainLoopXHandler handler,
+                         gpointer data,
+                         GDestroyNotify notify);
+void obt_main_loop_x_remove(ObtMainLoop *loop,
+                            ObtMainLoopXHandler handler);
+
+typedef void (*ObtMainLoopFdHandler) (gint fd, gpointer data);
+
+void obt_main_loop_fd_add(ObtMainLoop *loop,
+                          gint fd,
+                          ObtMainLoopFdHandler handler,
+                          gpointer data,
+                          GDestroyNotify notify);
+void obt_main_loop_fd_remove(ObtMainLoop *loop,
+                             gint fd);
+
+typedef void (*ObtMainLoopSignalHandler) (gint signal, gpointer data);
+
+void obt_main_loop_signal_add(ObtMainLoop *loop,
+                              gint signal,
+                              ObtMainLoopSignalHandler handler,
+                              gpointer data,
+                              GDestroyNotify notify);
+void obt_main_loop_signal_remove(ObtMainLoop *loop,
+                                 ObtMainLoopSignalHandler handler);
+
+void obt_main_loop_timeout_add(ObtMainLoop *loop,
+                               gulong microseconds,
+                               GSourceFunc handler,
+                               gpointer data,
+                               GEqualFunc cmp,
+                               GDestroyNotify notify);
+void obt_main_loop_timeout_remove(ObtMainLoop *loop,
+                                  GSourceFunc handler);
+void obt_main_loop_timeout_remove_data(ObtMainLoop *loop,
+                                       GSourceFunc handler,
+                                       gpointer data,
+                                       gboolean cancel_dest);
+
+void obt_main_loop_run(ObtMainLoop *loop);
+void obt_main_loop_exit(ObtMainLoop *loop);
+
+G_END_DECLS
+
+#endif
diff --git a/obt/obt-3.5.pc.in b/obt/obt-3.5.pc.in
new file mode 100644 (file)
index 0000000..840de16
--- /dev/null
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+xcflags=@X_CFLAGS@
+xlibs=@X_LIBS@
+
+Name: Obt
+Description: Openbox Toolkit Library
+Version: @OBT_VERSION@
+Requires: glib-2.0
+Libs: -L${libdir} -lobrender ${xlibs}
+Cflags: -I${includedir}/openbox/@OBT_VERSION@ ${xcflags}
diff --git a/obt/paths.c b/obt/paths.c
new file mode 100644 (file)
index 0000000..6861543
--- /dev/null
@@ -0,0 +1,249 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/paths.c for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/paths.h"
+#include "obt/util.h"
+
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+
+struct _ObtPaths
+{
+    gint   ref;
+    gchar  *config_home;
+    gchar  *data_home;
+    gchar  *cache_home;
+    GSList *config_dirs;
+    GSList *data_dirs;
+};
+
+static gint slist_path_cmp(const gchar *a, const gchar *b)
+{
+    return strcmp(a, b);
+}
+
+typedef GSList* (*GSListFunc) (gpointer list, gconstpointer data);
+
+static GSList* slist_path_add(GSList *list, gpointer data, GSListFunc func)
+{
+    g_assert(func);
+
+    if (!data)
+        return list;
+
+    if (!g_slist_find_custom(list, data, (GCompareFunc) slist_path_cmp))
+        list = func(list, data);
+    else
+        g_free(data);
+
+    return list;
+}
+
+static GSList* split_paths(const gchar *paths)
+{
+    GSList *list = NULL;
+    gchar **spl, **it;
+
+    if (!paths)
+        return NULL;
+    spl = g_strsplit(paths, ":", -1);
+    for (it = spl; *it; ++it)
+        list = slist_path_add(list, *it, (GSListFunc) g_slist_append);
+    g_free(spl);
+    return list;
+}
+
+ObtPaths* obt_paths_new(void)
+{
+    ObtPaths *p;
+    const gchar *path;
+
+    p = g_new0(ObtPaths, 1);
+    p->ref = 1;
+
+    path = g_getenv("XDG_CONFIG_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->config_home = g_build_filename(path, NULL);
+    else
+        p->config_home = g_build_filename(g_get_home_dir(), ".config", NULL);
+
+    path = g_getenv("XDG_DATA_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->data_home = g_build_filename(path, NULL);
+    else
+        p->data_home = g_build_filename(g_get_home_dir(), ".local",
+                                        "share", NULL);
+
+    path = g_getenv("XDG_CACHE_HOME");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->cache_home = g_build_filename(path, NULL);
+    else
+        p->cache_home = g_build_filename(g_get_home_dir(), ".cache", NULL);
+
+    path = g_getenv("XDG_CONFIG_DIRS");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->config_dirs = split_paths(path);
+    else {
+        p->config_dirs = slist_path_add(p->config_dirs,
+                                        g_strdup(CONFIGDIR),
+                                        (GSListFunc) g_slist_append);
+        p->config_dirs = slist_path_add(p->config_dirs,
+                                        g_build_filename
+                                        (G_DIR_SEPARATOR_S,
+                                         "etc", "xdg", NULL),
+                                        (GSListFunc) g_slist_append);
+    }
+    p->config_dirs = slist_path_add(p->config_dirs,
+                                    g_strdup(p->config_home),
+                                    (GSListFunc) g_slist_prepend);
+
+    path = g_getenv("XDG_DATA_DIRS");
+    if (path && path[0] != '\0') /* not unset or empty */
+        p->data_dirs = split_paths(path);
+    else {
+        p->data_dirs = slist_path_add(p->data_dirs,
+                                      g_strdup(DATADIR),
+                                      (GSListFunc) g_slist_append);
+        p->data_dirs = slist_path_add(p->data_dirs,
+                                      g_build_filename
+                                      (G_DIR_SEPARATOR_S,
+                                       "usr", "local", "share", NULL),
+                                      (GSListFunc) g_slist_append);
+        p->data_dirs = slist_path_add(p->data_dirs,
+                                      g_build_filename
+                                      (G_DIR_SEPARATOR_S,
+                                       "usr", "share", NULL),
+                                      (GSListFunc) g_slist_append);
+    }
+    p->data_dirs = slist_path_add(p->data_dirs,
+                                  g_strdup(p->data_home),
+                                  (GSListFunc) g_slist_prepend);
+    return p;
+}
+
+void obt_paths_ref(ObtPaths *p)
+{
+    ++p->ref;
+}
+
+void obt_paths_unref(ObtPaths *p)
+{
+    if (p && --p->ref == 0) {
+        GSList *it;
+
+        for (it = p->config_dirs; it; it = g_slist_next(it))
+            g_free(it->data);
+        g_slist_free(p->config_dirs);
+        for (it = p->data_dirs; it; it = g_slist_next(it))
+            g_free(it->data);
+        g_slist_free(p->data_dirs);
+        g_free(p->config_home);
+        g_free(p->data_home);
+        g_free(p->cache_home);
+
+        obt_free0(p, ObtPaths, 1);
+    }
+}
+
+gchar *obt_paths_expand_tilde(const gchar *f)
+{
+    gchar *ret;
+    GRegex *regex;
+
+    if (!f)
+        return NULL;
+
+    regex = g_regex_new("(?:^|(?<=[ \\t]))~(?=[/ \\t$])", G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
+    ret = g_regex_replace_literal(regex, f, -1, 0, g_get_home_dir(), 0, NULL);
+    g_regex_unref(regex);
+
+    return ret;
+}
+
+gboolean obt_paths_mkdir(const gchar *path, gint mode)
+{
+    gboolean ret = TRUE;
+
+    g_return_val_if_fail(path != NULL, FALSE);
+    g_return_val_if_fail(path[0] != '\0', FALSE);
+
+    if (!g_file_test(path, G_FILE_TEST_IS_DIR))
+        if (mkdir(path, mode) == -1)
+            ret = FALSE;
+
+    return ret;
+}
+
+gboolean obt_paths_mkdir_path(const gchar *path, gint mode)
+{
+    gboolean ret = TRUE;
+
+    g_return_val_if_fail(path != NULL, FALSE);
+    g_return_val_if_fail(path[0] == '/', FALSE);
+
+    if (!g_file_test(path, G_FILE_TEST_IS_DIR)) {
+        gchar *c, *e;
+
+        c = g_strdup(path);
+        e = c;
+        while ((e = strchr(e + 1, '/'))) {
+            *e = '\0';
+            if (!(ret = obt_paths_mkdir(c, mode)))
+                goto parse_mkdir_path_end;
+            *e = '/';
+        }
+        ret = obt_paths_mkdir(c, mode);
+
+    parse_mkdir_path_end:
+        g_free(c);
+    }
+
+    return ret;
+}
+
+const gchar* obt_paths_config_home(ObtPaths *p)
+{
+    return p->config_home;
+}
+
+const gchar* obt_paths_data_home(ObtPaths *p)
+{
+    return p->data_home;
+}
+
+const gchar* obt_paths_cache_home(ObtPaths *p)
+{
+    return p->cache_home;
+}
+
+GSList* obt_paths_config_dirs(ObtPaths *p)
+{
+    return p->config_dirs;
+}
+
+GSList* obt_paths_data_dirs(ObtPaths *p)
+{
+    return p->data_dirs;
+}
diff --git a/obt/paths.h b/obt/paths.h
new file mode 100644 (file)
index 0000000..8753d4f
--- /dev/null
@@ -0,0 +1,44 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/paths.h for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_paths_h
+#define __obt_paths_h
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtPaths ObtPaths;
+
+ObtPaths* obt_paths_new(void);
+void obt_paths_ref(ObtPaths *p);
+void obt_paths_unref(ObtPaths *p);
+
+const gchar* obt_paths_config_home(ObtPaths *p);
+const gchar* obt_paths_data_home(ObtPaths *p);
+const gchar* obt_paths_cache_home(ObtPaths *p);
+GSList* obt_paths_config_dirs(ObtPaths *p);
+GSList* obt_paths_data_dirs(ObtPaths *p);
+
+gchar *obt_paths_expand_tilde(const gchar *f);
+gboolean obt_paths_mkdir(const gchar *path, gint mode);
+gboolean obt_paths_mkdir_path(const gchar *path, gint mode);
+
+G_END_DECLS
+
+#endif
diff --git a/obt/prop.c b/obt/prop.c
new file mode 100644 (file)
index 0000000..ae229e4
--- /dev/null
@@ -0,0 +1,504 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/prop.c for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/prop.h"
+#include "obt/display.h"
+
+#include <X11/Xatom.h>
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
+
+Atom prop_atoms[OBT_PROP_NUM_ATOMS];
+gboolean prop_started = FALSE;
+
+#define CREATE_NAME(var, name) (prop_atoms[OBT_PROP_##var] = \
+                                XInternAtom((obt_display), (name), FALSE))
+#define CREATE(var) CREATE_NAME(var, #var)
+#define CREATE_(var) CREATE_NAME(var, "_" #var)
+
+void obt_prop_startup(void)
+{
+    if (prop_started) return;
+    prop_started = TRUE;
+
+    g_assert(obt_display);
+
+    CREATE(CARDINAL);
+    CREATE(WINDOW);
+    CREATE(PIXMAP);
+    CREATE(ATOM);
+    CREATE(STRING);
+    CREATE_NAME(UTF8, "UTF8_STRING");
+
+    CREATE(MANAGER);
+
+    CREATE(WM_COLORMAP_WINDOWS);
+    CREATE(WM_PROTOCOLS);
+    CREATE(WM_STATE);
+    CREATE(WM_CHANGE_STATE);
+    CREATE(WM_DELETE_WINDOW);
+    CREATE(WM_TAKE_FOCUS);
+    CREATE(WM_NAME);
+    CREATE(WM_ICON_NAME);
+    CREATE(WM_CLASS);
+    CREATE(WM_WINDOW_ROLE);
+    CREATE(WM_CLIENT_MACHINE);
+    CREATE(WM_COMMAND);
+    CREATE(WM_CLIENT_LEADER);
+    CREATE(WM_TRANSIENT_FOR);
+    CREATE_(MOTIF_WM_HINTS);
+    CREATE_(MOTIF_WM_INFO);
+
+    CREATE(SM_CLIENT_ID);
+
+    CREATE_(NET_WM_FULL_PLACEMENT);
+
+    CREATE_(NET_SUPPORTED);
+    CREATE_(NET_CLIENT_LIST);
+    CREATE_(NET_CLIENT_LIST_STACKING);
+    CREATE_(NET_NUMBER_OF_DESKTOPS);
+    CREATE_(NET_DESKTOP_GEOMETRY);
+    CREATE_(NET_DESKTOP_VIEWPORT);
+    CREATE_(NET_CURRENT_DESKTOP);
+    CREATE_(NET_DESKTOP_NAMES);
+    CREATE_(NET_ACTIVE_WINDOW);
+/*    CREATE_(NET_RESTACK_WINDOW);*/
+    CREATE_(NET_WORKAREA);
+    CREATE_(NET_SUPPORTING_WM_CHECK);
+    CREATE_(NET_DESKTOP_LAYOUT);
+    CREATE_(NET_SHOWING_DESKTOP);
+
+    CREATE_(NET_CLOSE_WINDOW);
+    CREATE_(NET_WM_MOVERESIZE);
+    CREATE_(NET_MOVERESIZE_WINDOW);
+    CREATE_(NET_REQUEST_FRAME_EXTENTS);
+    CREATE_(NET_RESTACK_WINDOW);
+
+    CREATE_(NET_STARTUP_ID);
+
+    CREATE_(NET_WM_NAME);
+    CREATE_(NET_WM_VISIBLE_NAME);
+    CREATE_(NET_WM_ICON_NAME);
+    CREATE_(NET_WM_VISIBLE_ICON_NAME);
+    CREATE_(NET_WM_DESKTOP);
+    CREATE_(NET_WM_WINDOW_TYPE);
+    CREATE_(NET_WM_STATE);
+    CREATE_(NET_WM_STRUT);
+    CREATE_(NET_WM_STRUT_PARTIAL);
+    CREATE_(NET_WM_ICON);
+    CREATE_(NET_WM_ICON_GEOMETRY);
+    CREATE_(NET_WM_PID);
+    CREATE_(NET_WM_ALLOWED_ACTIONS);
+    CREATE_(NET_WM_USER_TIME);
+/*  CREATE_(NET_WM_USER_TIME_WINDOW); */
+    CREATE_(KDE_NET_WM_FRAME_STRUT);
+    CREATE_(NET_FRAME_EXTENTS);
+
+    CREATE_(NET_WM_PING);
+#ifdef SYNC
+    CREATE_(NET_WM_SYNC_REQUEST);
+    CREATE_(NET_WM_SYNC_REQUEST_COUNTER);
+#endif
+
+    CREATE_(NET_WM_WINDOW_TYPE_DESKTOP);
+    CREATE_(NET_WM_WINDOW_TYPE_DOCK);
+    CREATE_(NET_WM_WINDOW_TYPE_TOOLBAR);
+    CREATE_(NET_WM_WINDOW_TYPE_MENU);
+    CREATE_(NET_WM_WINDOW_TYPE_UTILITY);
+    CREATE_(NET_WM_WINDOW_TYPE_SPLASH);
+    CREATE_(NET_WM_WINDOW_TYPE_DIALOG);
+    CREATE_(NET_WM_WINDOW_TYPE_NORMAL);
+    CREATE_(NET_WM_WINDOW_TYPE_POPUP_MENU);
+
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPLEFT] = 0;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOP] = 1;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPRIGHT] = 2;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_RIGHT] = 3;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT] = 4;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOM] = 5;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT] = 6;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_LEFT] = 7;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_MOVE] = 8;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_KEYBOARD] = 9;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_MOVE_KEYBOARD] = 10;
+    prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_CANCEL] = 11;
+
+    CREATE_(NET_WM_ACTION_MOVE);
+    CREATE_(NET_WM_ACTION_RESIZE);
+    CREATE_(NET_WM_ACTION_MINIMIZE);
+    CREATE_(NET_WM_ACTION_SHADE);
+    CREATE_(NET_WM_ACTION_MAXIMIZE_HORZ);
+    CREATE_(NET_WM_ACTION_MAXIMIZE_VERT);
+    CREATE_(NET_WM_ACTION_FULLSCREEN);
+    CREATE_(NET_WM_ACTION_CHANGE_DESKTOP);
+    CREATE_(NET_WM_ACTION_CLOSE);
+    CREATE_(NET_WM_ACTION_ABOVE);
+    CREATE_(NET_WM_ACTION_BELOW);
+
+    CREATE_(NET_WM_STATE_MODAL);
+/*    CREATE_(NET_WM_STATE_STICKY);*/
+    CREATE_(NET_WM_STATE_MAXIMIZED_VERT);
+    CREATE_(NET_WM_STATE_MAXIMIZED_HORZ);
+    CREATE_(NET_WM_STATE_SHADED);
+    CREATE_(NET_WM_STATE_SKIP_TASKBAR);
+    CREATE_(NET_WM_STATE_SKIP_PAGER);
+    CREATE_(NET_WM_STATE_HIDDEN);
+    CREATE_(NET_WM_STATE_FULLSCREEN);
+    CREATE_(NET_WM_STATE_ABOVE);
+    CREATE_(NET_WM_STATE_BELOW);
+    CREATE_(NET_WM_STATE_DEMANDS_ATTENTION);
+
+    prop_atoms[OBT_PROP_NET_WM_STATE_ADD] = 1;
+    prop_atoms[OBT_PROP_NET_WM_STATE_REMOVE] = 0;
+    prop_atoms[OBT_PROP_NET_WM_STATE_TOGGLE] = 2;
+
+    prop_atoms[OBT_PROP_NET_WM_ORIENTATION_HORZ] = 0;
+    prop_atoms[OBT_PROP_NET_WM_ORIENTATION_VERT] = 1;
+    prop_atoms[OBT_PROP_NET_WM_TOPLEFT] = 0;
+    prop_atoms[OBT_PROP_NET_WM_TOPRIGHT] = 1;
+    prop_atoms[OBT_PROP_NET_WM_BOTTOMRIGHT] = 2;
+    prop_atoms[OBT_PROP_NET_WM_BOTTOMLEFT] = 3;
+
+    CREATE_(KDE_WM_CHANGE_STATE);
+    CREATE_(KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
+
+/*
+    CREATE_NAME(ROOTPMAPId, "_XROOTPMAP_ID");
+    CREATE_NAME(ESETROOTId, "ESETROOT_PMAP_ID");
+*/
+
+    CREATE_(OPENBOX_PID);
+    CREATE_(OB_THEME);
+    CREATE_(OB_CONFIG_FILE);
+    CREATE_(OB_WM_ACTION_UNDECORATE);
+    CREATE_(OB_WM_STATE_UNDECORATED);
+    CREATE_(OB_CONTROL);
+    CREATE_(OB_VERSION);
+    CREATE_(OB_APP_ROLE);
+    CREATE_(OB_APP_TITLE);
+    CREATE_(OB_APP_NAME);
+    CREATE_(OB_APP_CLASS);
+    CREATE_(OB_APP_TYPE);
+}
+
+Atom obt_prop_atom(ObtPropAtom a)
+{
+    g_assert(prop_started);
+    g_assert(a < OBT_PROP_NUM_ATOMS);
+    return prop_atoms[a];
+}
+
+static gboolean get_prealloc(Window win, Atom prop, Atom type, gint size,
+                             guchar *data, gulong num)
+{
+    gboolean ret = FALSE;
+    gint res;
+    guchar *xdata = NULL;
+    Atom ret_type;
+    gint ret_size;
+    gulong ret_items, bytes_left;
+    glong num32 = 32 / size * num; /* num in 32-bit elements */
+
+    res = XGetWindowProperty(obt_display, win, prop, 0l, num32,
+                             FALSE, type, &ret_type, &ret_size,
+                             &ret_items, &bytes_left, &xdata);
+    if (res == Success && ret_items && xdata) {
+        if (ret_size == size && ret_items >= num) {
+            guint i;
+            for (i = 0; i < num; ++i)
+                switch (size) {
+                case 8:
+                    data[i] = xdata[i];
+                    break;
+                case 16:
+                    ((guint16*)data)[i] = ((gushort*)xdata)[i];
+                    break;
+                case 32:
+                    ((guint32*)data)[i] = ((gulong*)xdata)[i];
+                    break;
+                default:
+                    g_assert_not_reached(); /* unhandled size */
+                }
+            ret = TRUE;
+        }
+        XFree(xdata);
+    }
+    return ret;
+}
+
+static gboolean get_all(Window win, Atom prop, Atom type, gint size,
+                        guchar **data, guint *num)
+{
+    gboolean ret = FALSE;
+    gint res;
+    guchar *xdata = NULL;
+    Atom ret_type;
+    gint ret_size;
+    gulong ret_items, bytes_left;
+
+    res = XGetWindowProperty(obt_display, win, prop, 0l, G_MAXLONG,
+                             FALSE, type, &ret_type, &ret_size,
+                             &ret_items, &bytes_left, &xdata);
+    if (res == Success) {
+        if (ret_size == size && ret_items > 0) {
+            guint i;
+
+            *data = g_malloc(ret_items * (size / 8));
+            for (i = 0; i < ret_items; ++i)
+                switch (size) {
+                case 8:
+                    (*data)[i] = xdata[i];
+                    break;
+                case 16:
+                    ((guint16*)*data)[i] = ((gushort*)xdata)[i];
+                    break;
+                case 32:
+                    ((guint32*)*data)[i] = ((gulong*)xdata)[i];
+                    break;
+                default:
+                    g_assert_not_reached(); /* unhandled size */
+                }
+            *num = ret_items;
+            ret = TRUE;
+        }
+        XFree(xdata);
+    }
+    return ret;
+}
+
+static gboolean get_stringlist(Window win, Atom prop, gchar ***list, gint *nstr)
+{
+    XTextProperty tprop;
+    gboolean ret = FALSE;
+
+    if (XGetTextProperty(obt_display, win, &tprop, prop) && tprop.nitems) {
+        if (XTextPropertyToStringList(&tprop, list, nstr))
+            ret = TRUE;
+        XFree(tprop.value);
+    }
+    return ret;
+}
+
+gboolean obt_prop_get32(Window win, Atom prop, Atom type, guint32 *ret)
+{
+    return get_prealloc(win, prop, type, 32, (guchar*)ret, 1);
+}
+
+gboolean obt_prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret,
+                              guint *nret)
+{
+    return get_all(win, prop, type, 32, (guchar**)ret, nret);
+}
+
+gboolean obt_prop_get_string_locale(Window win, Atom prop, gchar **ret)
+{
+    gchar **list;
+    gint nstr;
+    gchar *s;
+
+    if (get_stringlist(win, prop, &list, &nstr) && nstr) {
+        s = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL);
+        XFreeStringList(list);
+        if (s) {
+            *ret = s;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+gboolean obt_prop_get_strings_locale(Window win, Atom prop, gchar ***ret)
+{
+    GSList *strs = NULL, *it;
+    gchar *raw, *p;
+    guint num, i, count = 0;
+
+    if (get_all(win, prop, OBT_PROP_ATOM(STRING), 8,
+                (guchar**)&raw, &num))
+    {
+        p = raw;
+        while (p < raw + num) {
+            ++count;
+            strs = g_slist_append(strs, p);
+            p += strlen(p) + 1; /* next string */
+        }
+
+        *ret = g_new0(gchar*, count + 1);
+        (*ret)[count] = NULL; /* null terminated list */
+
+        for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) {
+            (*ret)[i] = g_locale_to_utf8(it->data, -1, NULL, NULL, NULL);
+            /* make sure translation did not fail */
+            if (!(*ret)[i])
+                (*ret)[i] = g_strdup("");
+        }
+        g_free(raw);
+        g_slist_free(strs);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+gboolean obt_prop_get_string_utf8(Window win, Atom prop, gchar **ret)
+{
+    gchar *raw;
+    gchar *str;
+    guint num;
+
+    if (get_all(win, prop, OBT_PROP_ATOM(UTF8), 8,
+                (guchar**)&raw, &num))
+    {
+        str = g_strndup(raw, num); /* grab the first string from the list */
+        g_free(raw);
+        if (g_utf8_validate(str, -1, NULL)) {
+            *ret = str;
+            return TRUE;
+        }
+        g_free(str);
+    }
+    return FALSE;
+}
+
+gboolean obt_prop_get_strings_utf8(Window win, Atom prop, gchar ***ret)
+{
+    GSList *strs = NULL, *it;
+    gchar *raw, *p;
+    guint num, i, count = 0;
+
+    if (get_all(win, prop, OBT_PROP_ATOM(UTF8), 8,
+                (guchar**)&raw, &num))
+    {
+        p = raw;
+        while (p < raw + num) {
+            ++count;
+            strs = g_slist_append(strs, p);
+            p += strlen(p) + 1; /* next string */
+        }
+
+        *ret = g_new0(gchar*, count + 1);
+
+        for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) {
+            if (g_utf8_validate(it->data, -1, NULL))
+                (*ret)[i] = g_strdup(it->data);
+            else
+                (*ret)[i] = g_strdup("");
+        }
+        g_free(raw);
+        g_slist_free(strs);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void obt_prop_set32(Window win, Atom prop, Atom type, gulong val)
+{
+    XChangeProperty(obt_display, win, prop, type, 32, PropModeReplace,
+                    (guchar*)&val, 1);
+}
+
+void obt_prop_set_array32(Window win, Atom prop, Atom type, gulong *val,
+                      guint num)
+{
+    XChangeProperty(obt_display, win, prop, type, 32, PropModeReplace,
+                    (guchar*)val, num);
+}
+
+void obt_prop_set_string_locale(Window win, Atom prop, const gchar *val)
+{
+    gchar const *s[2] = { val, NULL };
+    obt_prop_set_strings_locale(win, prop, s);
+}
+
+void obt_prop_set_strings_locale(Window win, Atom prop, const gchar **strs)
+{
+    gint i, count;
+    gchar **lstrs;
+    XTextProperty tprop;
+
+    /* count the strings in strs, and convert them to the locale format */
+    for (count = 0; strs[count]; ++count);
+    lstrs = g_new0(char*, count);
+    for (i = 0; i < count; ++i) {
+        lstrs[i] = g_locale_from_utf8(strs[i], -1, NULL, NULL, NULL);
+        if (!lstrs[i]) {
+            lstrs[i] = g_strdup(""); /* make it an empty string */
+            g_warning("Unable to translate string '%s' from UTF8 to locale "
+                      "format", strs[i]);
+        }
+    }
+
+
+    XStringListToTextProperty(lstrs, count, &tprop);
+    XSetTextProperty(obt_display, win, &tprop, prop);
+    XFree(tprop.value);
+}
+
+void obt_prop_set_string_utf8(Window win, Atom prop, const gchar *val)
+{
+    XChangeProperty(obt_display, win, prop, OBT_PROP_ATOM(UTF8), 8,
+                    PropModeReplace, (const guchar*)val, strlen(val));
+}
+
+void obt_prop_set_strings_utf8(Window win, Atom prop, const gchar **strs)
+{
+    GString *str;
+    gchar const **s;
+
+    str = g_string_sized_new(0);
+    for (s = strs; *s; ++s) {
+        str = g_string_append(str, *s);
+        str = g_string_append_c(str, '\0');
+    }
+    XChangeProperty(obt_display, win, prop, obt_prop_atom(OBT_PROP_UTF8), 8,
+                    PropModeReplace, (guchar*)str->str, str->len);
+    g_string_free(str, TRUE);
+}
+
+void obt_prop_erase(Window win, Atom prop)
+{
+    XDeleteProperty(obt_display, win, prop);
+}
+
+void obt_prop_message(gint screen, Window about, Atom messagetype,
+                      glong data0, glong data1, glong data2, glong data3,
+                      glong data4, glong mask)
+{
+    obt_prop_message_to(obt_root(screen), about, messagetype,
+                        data0, data1, data2, data3, data4, mask);
+}
+
+void obt_prop_message_to(Window to, Window about,
+                         Atom messagetype,
+                         glong data0, glong data1, glong data2, glong data3,
+                         glong data4, glong mask)
+{
+    XEvent ce;
+    ce.xclient.type = ClientMessage;
+    ce.xclient.message_type = messagetype;
+    ce.xclient.display = obt_display;
+    ce.xclient.window = about;
+    ce.xclient.format = 32;
+    ce.xclient.data.l[0] = data0;
+    ce.xclient.data.l[1] = data1;
+    ce.xclient.data.l[2] = data2;
+    ce.xclient.data.l[3] = data3;
+    ce.xclient.data.l[4] = data4;
+    XSendEvent(obt_display, to, FALSE, mask, &ce);
+}
diff --git a/obt/prop.h b/obt/prop.h
new file mode 100644 (file)
index 0000000..cc1fe73
--- /dev/null
@@ -0,0 +1,288 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/prop.h for the Openbox window manager
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_prop_h
+#define __obt_prop_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+    /* types */
+    OBT_PROP_CARDINAL, /*!< The atom which represents the Cardinal data type */
+    OBT_PROP_WINDOW,   /*!< The atom which represents window ids */
+    OBT_PROP_PIXMAP,   /*!< The atom which represents pixmap ids */
+    OBT_PROP_ATOM,     /*!< The atom which represents atom values */
+    OBT_PROP_STRING,   /*!< The atom which represents ascii strings */
+    OBT_PROP_UTF8,     /*!< The atom which represents utf8-encoded strings */
+
+    /* selection stuff */
+    OBT_PROP_MANAGER,
+
+    /* window hints */
+    OBT_PROP_WM_COLORMAP_WINDOWS,
+    OBT_PROP_WM_PROTOCOLS,
+    OBT_PROP_WM_STATE,
+    OBT_PROP_WM_DELETE_WINDOW,
+    OBT_PROP_WM_TAKE_FOCUS,
+    OBT_PROP_WM_CHANGE_STATE,
+    OBT_PROP_WM_NAME,
+    OBT_PROP_WM_ICON_NAME,
+    OBT_PROP_WM_CLASS,
+    OBT_PROP_WM_WINDOW_ROLE,
+    OBT_PROP_WM_CLIENT_MACHINE,
+    OBT_PROP_WM_COMMAND,
+    OBT_PROP_WM_CLIENT_LEADER,
+    OBT_PROP_WM_TRANSIENT_FOR,
+    OBT_PROP_MOTIF_WM_HINTS,
+    OBT_PROP_MOTIF_WM_INFO,
+
+    /* SM atoms */
+    OBT_PROP_SM_CLIENT_ID,
+
+    /* NETWM atoms */
+
+    /* Atoms that are used inside messages - these don't go in net_supported */
+
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPLEFT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOP,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPRIGHT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_RIGHT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOM,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_LEFT,
+    OBT_PROP_NET_WM_MOVERESIZE_MOVE,
+    OBT_PROP_NET_WM_MOVERESIZE_SIZE_KEYBOARD,
+    OBT_PROP_NET_WM_MOVERESIZE_MOVE_KEYBOARD,
+    OBT_PROP_NET_WM_MOVERESIZE_CANCEL,
+
+    OBT_PROP_NET_WM_STATE_ADD,
+    OBT_PROP_NET_WM_STATE_REMOVE,
+    OBT_PROP_NET_WM_STATE_TOGGLE,
+
+    OBT_PROP_NET_WM_ORIENTATION_HORZ,
+    OBT_PROP_NET_WM_ORIENTATION_VERT,
+    OBT_PROP_NET_WM_TOPLEFT,
+    OBT_PROP_NET_WM_TOPRIGHT,
+    OBT_PROP_NET_WM_BOTTOMRIGHT,
+    OBT_PROP_NET_WM_BOTTOMLEFT,
+
+    OBT_PROP_NET_WM_WINDOW_TYPE_POPUP_MENU,
+
+    OBT_PROP_PRIVATE_PADDING1,
+    OBT_PROP_PRIVATE_PADDING2,
+    OBT_PROP_PRIVATE_PADDING3,
+    OBT_PROP_PRIVATE_PADDING4,
+    OBT_PROP_PRIVATE_PADDING5,
+    OBT_PROP_PRIVATE_PADDING6,
+    OBT_PROP_PRIVATE_PADDING7,
+    OBT_PROP_PRIVATE_PADDING8,
+    OBT_PROP_PRIVATE_PADDING9,
+    OBT_PROP_PRIVATE_PADDING10,
+    OBT_PROP_PRIVATE_PADDING11,
+    OBT_PROP_PRIVATE_PADDING12,
+
+    /* Everything below here must go in net_supported on the root window */
+
+    /* root window properties */
+    OBT_PROP_NET_SUPPORTED,
+    OBT_PROP_NET_CLIENT_LIST,
+    OBT_PROP_NET_CLIENT_LIST_STACKING,
+    OBT_PROP_NET_NUMBER_OF_DESKTOPS,
+    OBT_PROP_NET_DESKTOP_GEOMETRY,
+    OBT_PROP_NET_DESKTOP_VIEWPORT,
+    OBT_PROP_NET_CURRENT_DESKTOP,
+    OBT_PROP_NET_DESKTOP_NAMES,
+    OBT_PROP_NET_ACTIVE_WINDOW,
+/*    Atom net_restack_window;*/
+    OBT_PROP_NET_WORKAREA,
+    OBT_PROP_NET_SUPPORTING_WM_CHECK,
+    OBT_PROP_NET_DESKTOP_LAYOUT,
+    OBT_PROP_NET_SHOWING_DESKTOP,
+
+    /* root window messages */
+    OBT_PROP_NET_CLOSE_WINDOW,
+    OBT_PROP_NET_WM_MOVERESIZE,
+    OBT_PROP_NET_MOVERESIZE_WINDOW,
+    OBT_PROP_NET_REQUEST_FRAME_EXTENTS,
+    OBT_PROP_NET_RESTACK_WINDOW,
+
+    /* helpful hints to apps that aren't used for anything */
+    OBT_PROP_NET_WM_FULL_PLACEMENT,
+
+    /* startup-notification extension */
+    OBT_PROP_NET_STARTUP_ID,
+
+    /* application window properties */
+    OBT_PROP_NET_WM_NAME,
+    OBT_PROP_NET_WM_VISIBLE_NAME,
+    OBT_PROP_NET_WM_ICON_NAME,
+    OBT_PROP_NET_WM_VISIBLE_ICON_NAME,
+    OBT_PROP_NET_WM_DESKTOP,
+    OBT_PROP_NET_WM_WINDOW_TYPE,
+    OBT_PROP_NET_WM_STATE,
+    OBT_PROP_NET_WM_STRUT,
+    OBT_PROP_NET_WM_STRUT_PARTIAL,
+    OBT_PROP_NET_WM_ICON,
+    OBT_PROP_NET_WM_ICON_GEOMETRY,
+    OBT_PROP_NET_WM_PID,
+    OBT_PROP_NET_WM_ALLOWED_ACTIONS,
+    OBT_PROP_NET_WM_USER_TIME,
+/*  OBT_PROP_NET_WM_USER_TIME_WINDOW, */
+    OBT_PROP_NET_FRAME_EXTENTS,
+
+    /* application protocols */
+    OBT_PROP_NET_WM_PING,
+#ifdef SYNC
+    OBT_PROP_NET_WM_SYNC_REQUEST,
+    OBT_PROP_NET_WM_SYNC_REQUEST_COUNTER,
+#endif
+
+    OBT_PROP_NET_WM_WINDOW_TYPE_DESKTOP,
+    OBT_PROP_NET_WM_WINDOW_TYPE_DOCK,
+    OBT_PROP_NET_WM_WINDOW_TYPE_TOOLBAR,
+    OBT_PROP_NET_WM_WINDOW_TYPE_MENU,
+    OBT_PROP_NET_WM_WINDOW_TYPE_UTILITY,
+    OBT_PROP_NET_WM_WINDOW_TYPE_SPLASH,
+    OBT_PROP_NET_WM_WINDOW_TYPE_DIALOG,
+    OBT_PROP_NET_WM_WINDOW_TYPE_NORMAL,
+
+    OBT_PROP_NET_WM_ACTION_MOVE,
+    OBT_PROP_NET_WM_ACTION_RESIZE,
+    OBT_PROP_NET_WM_ACTION_MINIMIZE,
+    OBT_PROP_NET_WM_ACTION_SHADE,
+/*    OBT_PROP_NET_WM_ACTION_STICK,*/
+    OBT_PROP_NET_WM_ACTION_MAXIMIZE_HORZ,
+    OBT_PROP_NET_WM_ACTION_MAXIMIZE_VERT,
+    OBT_PROP_NET_WM_ACTION_FULLSCREEN,
+    OBT_PROP_NET_WM_ACTION_CHANGE_DESKTOP,
+    OBT_PROP_NET_WM_ACTION_CLOSE,
+    OBT_PROP_NET_WM_ACTION_ABOVE,
+    OBT_PROP_NET_WM_ACTION_BELOW,
+
+    OBT_PROP_NET_WM_STATE_MODAL,
+/*    OBT_PROP_NET_WM_STATE_STICKY,*/
+    OBT_PROP_NET_WM_STATE_MAXIMIZED_VERT,
+    OBT_PROP_NET_WM_STATE_MAXIMIZED_HORZ,
+    OBT_PROP_NET_WM_STATE_SHADED,
+    OBT_PROP_NET_WM_STATE_SKIP_TASKBAR,
+    OBT_PROP_NET_WM_STATE_SKIP_PAGER,
+    OBT_PROP_NET_WM_STATE_HIDDEN,
+    OBT_PROP_NET_WM_STATE_FULLSCREEN,
+    OBT_PROP_NET_WM_STATE_ABOVE,
+    OBT_PROP_NET_WM_STATE_BELOW,
+    OBT_PROP_NET_WM_STATE_DEMANDS_ATTENTION,
+
+    /* KDE atoms */
+
+    OBT_PROP_KDE_WM_CHANGE_STATE,
+    OBT_PROP_KDE_NET_WM_FRAME_STRUT,
+    OBT_PROP_KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
+
+/*
+    OBT_PROP_ROOTPMAPID,
+    OBT_PROP_ESETROOTID,
+*/
+
+    /* Openbox specific atoms */
+
+    OBT_PROP_OB_WM_ACTION_UNDECORATE,
+    OBT_PROP_OB_WM_STATE_UNDECORATED,
+    OBT_PROP_OPENBOX_PID, /* this is depreecated in favour of ob_control */
+    OBT_PROP_OB_THEME,
+    OBT_PROP_OB_CONFIG_FILE,
+    OBT_PROP_OB_CONTROL,
+    OBT_PROP_OB_VERSION,
+    OBT_PROP_OB_APP_ROLE,
+    OBT_PROP_OB_APP_TITLE,
+    OBT_PROP_OB_APP_NAME,
+    OBT_PROP_OB_APP_CLASS,
+    OBT_PROP_OB_APP_TYPE,
+
+    OBT_PROP_NUM_ATOMS
+} ObtPropAtom;
+
+Atom obt_prop_atom(ObtPropAtom a);
+
+gboolean obt_prop_get32(Window win, Atom prop, Atom type, guint32 *ret);
+gboolean obt_prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret,
+                              guint *nret);
+gboolean obt_prop_get_string_locale(Window win, Atom prop, gchar **ret);
+gboolean obt_prop_get_string_utf8(Window win, Atom prop, gchar **ret);
+gboolean obt_prop_get_strings_locale(Window win, Atom prop, gchar ***ret);
+gboolean obt_prop_get_strings_utf8(Window win, Atom prop, gchar ***ret);
+
+void obt_prop_set32(Window win, Atom prop, Atom type, gulong val);
+void obt_prop_set_array32(Window win, Atom prop, Atom type, gulong *val,
+                          guint num);
+void obt_prop_set_string_locale(Window win, Atom prop, const gchar *val);
+void obt_prop_set_string_utf8(Window win, Atom prop, const gchar *val);
+void obt_prop_set_strings_locale(Window win, Atom prop, const gchar **strs);
+void obt_prop_set_strings_utf8(Window win, Atom prop, const gchar **strs);
+
+void obt_prop_erase(Window win, Atom prop);
+
+void obt_prop_message(gint screen, Window about, Atom messagetype,
+                      glong data0, glong data1, glong data2, glong data3,
+                      glong data4, glong mask);
+void obt_prop_message_to(Window to, Window about, Atom messagetype,
+                         glong data0, glong data1, glong data2, glong data3,
+                         glong data4, glong mask);
+
+#define OBT_PROP_ATOM(prop) obt_prop_atom(OBT_PROP_##prop)
+
+#define OBT_PROP_GET32(win, prop, type, ret) \
+    (obt_prop_get32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), ret))
+#define OBT_PROP_GETA32(win, prop, type, ret, nret) \
+    (obt_prop_get_array32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), \
+                          ret, nret))
+#define OBT_PROP_GETS(win, prop, type, ret) \
+    (obt_prop_get_string_##type(win, OBT_PROP_ATOM(prop), ret))
+#define OBT_PROP_GETSS(win, prop, type, ret) \
+    (obt_prop_get_strings_##type(win, OBT_PROP_ATOM(prop), ret))
+
+#define OBT_PROP_SET32(win, prop, type, val) \
+    (obt_prop_set32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), val))
+#define OBT_PROP_SETA32(win, prop, type, val, num) \
+    (obt_prop_set_array32(win, OBT_PROP_ATOM(prop), OBT_PROP_ATOM(type), \
+                          val, num))
+#define OBT_PROP_SETS(win, prop, type, val) \
+    (obt_prop_set_string_##type(win, OBT_PROP_ATOM(prop), val))
+#define OBT_PROP_SETSS(win, prop, type, strs) \
+    (obt_prop_set_strings_##type(win, OBT_PROP_ATOM(prop), strs))
+
+#define OBT_PROP_ERASE(win, prop) (obt_prop_erase(win, OBT_PROP_ATOM(prop)))
+
+#define OBT_PROP_MSG(screen, about, msgtype, data0, data1, data2, data3, \
+                     data4) \
+    (obt_prop_message(screen, about, OBT_PROP_ATOM(msgtype), \
+                      data0, data1, data2, data3, data4, \
+                      SubstructureNotifyMask | SubstructureRedirectMask))
+
+#define OBT_PROP_MSG_TO(to, about, msgtype, data0, data1, data2, data3, \
+                        data4, mask) \
+    (obt_prop_message_to(to, about, OBT_PROP_ATOM(msgtype), \
+                         data0, data1, data2, data3, data4, mask))
+
+G_END_DECLS
+
+#endif /* __obt_prop_h */
diff --git a/obt/util.h b/obt/util.h
new file mode 100644 (file)
index 0000000..ff44d36
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/util.h for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_util_h
+#define __obt_util_h
+
+#include <glib.h>
+
+#ifdef HAVE_STRING_H
+#  include <string.h> /* for memset() */
+#endif
+
+G_BEGIN_DECLS
+
+/* Util funcs */
+#define obt_free g_free
+#define obt_free0(p, type, num) memset((p), 0, sizeof(type) * (num)), g_free(p)
+
+G_END_DECLS
+
+
+#endif /*__obt_util_h*/
diff --git a/obt/version.h.in b/obt/version.h.in
new file mode 100644 (file)
index 0000000..8adfcf8
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef obt__version_h
+#define obt__version_h
+
+#define OBT_MAJOR_VERSION @OBT_MAJOR_VERSION@
+#define OBT_MINOR_VERSION @OBT_MINOR_VERSION@
+#define OBT_MICRO_VERSION @OBT_MICRO_VERSION@
+#define OBT_VERSION OBT_MAJOR_VERSION.OBT_MINOR_VERSION.OBT_MICRO_VERSION
+
+#define OBT_CHECK_VERSION(major,minor,micro) \
+    (OBT_MAJOR_VERSION > (major) || \
+     (OBT_MAJOR_VERSION == (major) && OBT_MINOR_VERSION > (minor)) || \
+     (OBT_MAJOR_VERSION == (major) && OBT_MINOR_VERSION == (minor) && \
+      OBT_MICRO_VERSION >= (micro)))
+
+#endif
diff --git a/obt/xevent.c b/obt/xevent.c
new file mode 100644 (file)
index 0000000..1cc32a9
--- /dev/null
@@ -0,0 +1,134 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/xevent.c for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/xevent.h"
+#include "obt/mainloop.h"
+#include "obt/util.h"
+
+typedef struct _ObtXEventBinding ObtXEventBinding;
+
+struct _ObtXEventHandler
+{
+    gint ref;
+    ObtMainLoop *loop;
+
+    /* An array of hash tables where the key is the window, and the value is
+       the ObtXEventBinding */
+    GHashTable **bindings;
+    gint num_event_types; /* the length of the bindings array */
+};
+
+struct _ObtXEventBinding
+{
+    Window win;
+    ObtXEventCallback func;
+    gpointer data;
+};
+
+static void xevent_handler(const XEvent *e, gpointer data);
+static guint window_hash(Window *w) { return *w; }
+static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+
+ObtXEventHandler* xevent_new(void)
+{
+    ObtXEventHandler *h;
+
+    h = g_new0(ObtXEventHandler, 1);
+    h->ref = 1;
+
+    return h;
+}
+
+void xevent_ref(ObtXEventHandler *h)
+{
+    ++h->ref;
+}
+
+void xevent_unref(ObtXEventHandler *h)
+{
+    if (h && --h->ref == 0) {
+        gint i;
+
+        if (h->loop)
+            obt_main_loop_x_remove(h->loop, xevent_handler);
+        for (i = 0; i < h->num_event_types; ++i)
+            g_hash_table_destroy(h->bindings[i]);
+        g_free(h->bindings);
+
+        obt_free0(h, ObtXEventHandler, 1);
+    }
+}
+
+void xevent_register(ObtXEventHandler *h, ObtMainLoop *loop)
+{
+    h->loop = loop;
+    obt_main_loop_x_add(loop, xevent_handler, h, NULL);
+}
+
+void xevent_set_handler(ObtXEventHandler *h, gint type, Window win,
+                        ObtXEventCallback func, gpointer data)
+{
+    ObtXEventBinding *b;
+
+    g_assert(func);
+
+    /* make sure we have a spot for the event */
+    if (type + 1 < h->num_event_types) {
+        gint i;
+        h->bindings = g_renew(GHashTable*, h->bindings, type + 1);
+        for (i = h->num_event_types; i < type + 1; ++i)
+            h->bindings[i] = g_hash_table_new_full((GHashFunc)window_hash,
+                                                   (GEqualFunc)window_comp,
+                                                   NULL, g_free);
+        h->num_event_types = type + 1;
+    }
+
+    b = g_new(ObtXEventBinding, 1);
+    b->win = win;
+    b->func = func;
+    b->data = data;
+    g_hash_table_replace(h->bindings[type], &b->win, b);
+}
+
+void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win)
+{
+    g_assert(type < h->num_event_types);
+    g_assert(win);
+
+    g_hash_table_remove(h->bindings[type], &win);
+}
+
+static void xevent_handler(const XEvent *e, gpointer data)
+{
+    ObtXEventHandler *h;
+    ObtXEventBinding *b;
+
+    h = data;
+
+    if (e->type < h->num_event_types) {
+        const gint all = OBT_XEVENT_ALL_WINDOWS;
+        /* run the all_windows handler first */
+        b = g_hash_table_lookup(h->bindings[e->xany.type], &all);
+        if (b) b->func(e, b->data);
+        /* then run the per-window handler */
+        b = g_hash_table_lookup(h->bindings[e->xany.type], &e->xany.window);
+        if (b) b->func(e, b->data);
+    }
+    else
+        g_message("Unhandled X Event type %d", e->xany.type);
+}
diff --git a/obt/xevent.h b/obt/xevent.h
new file mode 100644 (file)
index 0000000..ec0b66e
--- /dev/null
@@ -0,0 +1,48 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/xevent.h for the Openbox window manager
+   Copyright (c) 2007        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_xevent_h
+#define __obt_xevent_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+struct _ObtMainLoop;
+
+typedef struct _ObtXEventHandler ObtXEventHandler;
+
+typedef void (*ObtXEventCallback) (const XEvent *e, gpointer data);
+
+ObtXEventHandler* xevent_new(void);
+void              xevent_ref(ObtXEventHandler *h);
+void              xevent_unref(ObtXEventHandler *h);
+
+void              xevent_register(ObtXEventHandler *h,
+                                  struct _ObtMainLoop *loop);
+
+#define OBT_XEVENT_ALL_WINDOWS None
+
+void xevent_set_handler(ObtXEventHandler *h, gint type, Window win,
+                        ObtXEventCallback func, gpointer data);
+void xevent_remove_handler(ObtXEventHandler *h, gint type, Window win);
+
+G_END_DECLS
+
+#endif /*__obt_xevent_h*/
diff --git a/obt/xml.c b/obt/xml.c
new file mode 100644 (file)
index 0000000..92e2343
--- /dev/null
+++ b/obt/xml.c
@@ -0,0 +1,431 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/xml.c for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "obt/xml.h"
+#include "obt/paths.h"
+
+#include <glib.h>
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+struct Callback {
+    gchar *tag;
+    ObtXmlCallback func;
+    gpointer data;
+};
+
+struct _ObtXmlInst {
+    gint ref;
+    ObtPaths *xdg_paths;
+    GHashTable *callbacks;
+    xmlDocPtr doc;
+    xmlNodePtr root;
+    gchar *path;
+};
+
+static void destfunc(struct Callback *c)
+{
+    g_free(c->tag);
+    g_free(c);
+}
+
+ObtXmlInst* obt_xml_instance_new(void)
+{
+    ObtXmlInst *i = g_new(ObtXmlInst, 1);
+    i->ref = 1;
+    i->xdg_paths = obt_paths_new();
+    i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                                         (GDestroyNotify)destfunc);
+    i->doc = NULL;
+    i->root = NULL;
+    i->path = NULL;
+    return i;
+}
+
+void obt_xml_instance_ref(ObtXmlInst *i)
+{
+    ++i->ref;
+}
+
+void obt_xml_instance_unref(ObtXmlInst *i)
+{
+    if (i && --i->ref == 0) {
+        obt_paths_unref(i->xdg_paths);
+        g_hash_table_destroy(i->callbacks);
+        g_free(i);
+    }
+}
+
+xmlDocPtr obt_xml_doc(ObtXmlInst *i)
+{
+    g_assert(i->doc); /* a doc is open? */
+    return i->doc;
+}
+
+xmlNodePtr obt_xml_root(ObtXmlInst *i)
+{
+    g_assert(i->doc); /* a doc is open? */
+    return i->root;
+}
+
+void obt_xml_register(ObtXmlInst *i, const gchar *tag,
+                      ObtXmlCallback func, gpointer data)
+{
+    struct Callback *c;
+
+    if (g_hash_table_lookup(i->callbacks, tag)) {
+        g_error("Tag '%s' already registered", tag);
+        return;
+    }
+
+    c = g_new(struct Callback, 1);
+    c->tag = g_strdup(tag);
+    c->func = func;
+    c->data = data;
+    g_hash_table_insert(i->callbacks, c->tag, c);
+}
+
+static gboolean load_file(ObtXmlInst *i,
+                          const gchar *domain,
+                          const gchar *filename,
+                          const gchar *root_node,
+                          GSList *paths)
+{
+    GSList *it;
+    gboolean r = FALSE;
+
+    g_assert(i->doc == NULL); /* another doc isn't open already? */
+
+    for (it = paths; !r && it; it = g_slist_next(it)) {
+        gchar *path;
+        struct stat s;
+
+        if (!domain && !filename) /* given a full path to the file */
+            path = g_strdup(it->data);
+        else
+            path = g_build_filename(it->data, domain, filename, NULL);
+
+        if (stat(path, &s) >= 0) {
+            /* XML_PARSE_BLANKS is needed apparently, or the tree can end up
+               with extra nodes in it. */
+            i->doc = xmlReadFile(path, NULL, (XML_PARSE_NOBLANKS |
+                                              XML_PARSE_RECOVER));
+            if (i->doc) {
+                i->root = xmlDocGetRootElement(i->doc);
+                if (!i->root) {
+                    xmlFreeDoc(i->doc);
+                    i->doc = NULL;
+                    g_message("%s is an empty XML document", path);
+                }
+                else if (xmlStrcmp(i->root->name,
+                                   (const xmlChar*)root_node)) {
+                    xmlFreeDoc(i->doc);
+                    i->doc = NULL;
+                    i->root = NULL;
+                    g_message("XML document %s is of wrong type. Root "
+                              "node is not '%s'", path, root_node);
+                }
+                else {
+                    i->path = g_strdup(path);
+                    r = TRUE; /* ok! */
+                }
+            }
+        }
+
+        g_free(path);
+    }
+
+    return r;
+}
+
+gboolean obt_xml_load_file(ObtXmlInst *i,
+                           const gchar *path,
+                           const gchar *root_node)
+{
+    GSList *paths;
+    gboolean r;
+
+    paths = g_slist_append(NULL, g_strdup(path));
+
+    r = load_file(i, NULL, NULL, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+gboolean obt_xml_load_config_file(ObtXmlInst *i,
+                                  const gchar *domain,
+                                  const gchar *filename,
+                                  const gchar *root_node)
+{
+    GSList *it, *paths = NULL;
+    gboolean r;
+
+    for (it = obt_paths_config_dirs(i->xdg_paths); it; it = g_slist_next(it))
+        paths = g_slist_append(paths, g_strdup(it->data));
+
+    r = load_file(i, domain, filename, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+gboolean obt_xml_load_data_file(ObtXmlInst *i,
+                                const gchar *domain,
+                                const gchar *filename,
+                                const gchar *root_node)
+{
+    GSList *it, *paths = NULL;
+    gboolean r;
+
+    for (it = obt_paths_data_dirs(i->xdg_paths); it; it = g_slist_next(it))
+        paths = g_slist_append(paths, g_strdup(it->data));
+
+    r = load_file(i, domain, filename, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+gboolean obt_xml_load_theme_file(ObtXmlInst *i,
+                                 const gchar *theme,
+                                 const gchar *domain,
+                                 const gchar *filename,
+                                 const gchar *root_node)
+{
+    GSList *it, *paths = NULL;
+    gboolean r;
+
+    /* use ~/.themes for backwards compatibility */
+    paths = g_slist_append
+        (paths, g_build_filename(g_get_home_dir(), ".themes", theme, NULL));
+
+    for (it = obt_paths_data_dirs(i->xdg_paths); it; it = g_slist_next(it))
+        paths = g_slist_append
+            (paths, g_build_filename(it->data, "themes", theme, NULL));
+
+    r = load_file(i, domain, filename, root_node, paths);
+
+    while (paths) {
+        g_free(paths->data);
+        paths = g_slist_delete_link(paths, paths);
+    }
+    return r;
+}
+
+
+gboolean obt_xml_load_mem(ObtXmlInst *i,
+                          gpointer data, guint len, const gchar *root_node)
+{
+    gboolean r = FALSE;
+
+    g_assert(i->doc == NULL); /* another doc isn't open already? */
+
+    i->doc = xmlParseMemory(data, len);
+    if (i) {
+        i->root = xmlDocGetRootElement(i->doc);
+        if (!i->root) {
+            xmlFreeDoc(i->doc);
+            i->doc = NULL;
+            g_message("Given memory is an empty document");
+        }
+        else if (xmlStrcmp(i->root->name, (const xmlChar*)root_node)) {
+            xmlFreeDoc(i->doc);
+            i->doc = NULL;
+            i->root = NULL;
+            g_message("XML Document in given memory is of wrong "
+                      "type. Root node is not '%s'\n", root_node);
+        }
+        else
+            r = TRUE; /* ok ! */
+    }
+    return r;
+}
+
+gboolean obt_xml_save_file(ObtXmlInst *inst,
+                           const gchar *path,
+                           gboolean pretty)
+{
+    return xmlSaveFormatFile(path, inst->doc, pretty) != -1;
+}
+
+void obt_xml_close(ObtXmlInst *i)
+{
+    if (i && i->doc) {
+        xmlFreeDoc(i->doc);
+        g_free(i->path);
+        i->doc = NULL;
+        i->root = NULL;
+        i->path = NULL;
+    }
+}
+
+void obt_xml_tree(ObtXmlInst *i, xmlNodePtr node)
+{
+    g_assert(i->doc); /* a doc is open? */
+
+    while (node) {
+        struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
+        if (c) c->func(node, c->data);
+        node = node->next;
+    }
+}
+
+void obt_xml_tree_from_root(ObtXmlInst *i)
+{
+    obt_xml_tree(i, i->root->children);
+}
+
+gchar *obt_xml_node_string(xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gchar *s;
+    if (c) g_strstrip((char*)c); /* strip leading/trailing whitespace */
+    s = g_strdup(c ? (gchar*)c : "");
+    xmlFree(c);
+    return s;
+}
+
+gint obt_xml_node_int(xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gint i;
+    if (c) g_strstrip((char*)c); /* strip leading/trailing whitespace */
+    i = c ? atoi((gchar*)c) : 0;
+    xmlFree(c);
+    return i;
+}
+
+gboolean obt_xml_node_bool(xmlNodePtr node)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gboolean b = FALSE;
+    if (c) g_strstrip((char*)c); /* strip leading/trailing whitespace */
+    if (c && !xmlStrcasecmp(c, (const xmlChar*) "true"))
+        b = TRUE;
+    else if (c && !xmlStrcasecmp(c, (const xmlChar*) "yes"))
+        b = TRUE;
+    else if (c && !xmlStrcasecmp(c, (const xmlChar*) "on"))
+        b = TRUE;
+    xmlFree(c);
+    return b;
+}
+
+gboolean obt_xml_node_contains(xmlNodePtr node, const gchar *val)
+{
+    xmlChar *c = xmlNodeGetContent(node);
+    gboolean r;
+    if (c) g_strstrip((char*)c); /* strip leading/trailing whitespace */
+    r = !xmlStrcasecmp(c, (const xmlChar*) val);
+    xmlFree(c);
+    return r;
+}
+
+xmlNodePtr obt_xml_find_node(xmlNodePtr node, const gchar *tag)
+{
+    while (node) {
+        if (!xmlStrcmp(node->name, (const xmlChar*) tag))
+            return node;
+        node = node->next;
+    }
+    return NULL;
+}
+
+gboolean obt_xml_attr_bool(xmlNodePtr node, const gchar *name,
+                           gboolean *value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        g_strstrip((char*)c); /* strip leading/trailing whitespace */
+        if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
+            *value = TRUE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
+            *value = TRUE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
+            *value = TRUE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "false"))
+            *value = FALSE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "no"))
+            *value = FALSE, r = TRUE;
+        else if (!xmlStrcasecmp(c, (const xmlChar*) "off"))
+            *value = FALSE, r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean obt_xml_attr_int(xmlNodePtr node, const gchar *name, gint *value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        g_strstrip((char*)c); /* strip leading/trailing whitespace */
+        *value = atoi((gchar*)c);
+        r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean obt_xml_attr_string(xmlNodePtr node, const gchar *name,
+                             gchar **value)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        g_strstrip((char*)c); /* strip leading/trailing whitespace */
+        *value = g_strdup((gchar*)c);
+        r = TRUE;
+    }
+    xmlFree(c);
+    return r;
+}
+
+gboolean obt_xml_attr_contains(xmlNodePtr node, const gchar *name,
+                               const gchar *val)
+{
+    xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+    gboolean r = FALSE;
+    if (c) {
+        g_strstrip((char*)c); /* strip leading/trailing whitespace */
+        r = !xmlStrcasecmp(c, (const xmlChar*) val);
+    }
+    xmlFree(c);
+    return r;
+}
diff --git a/obt/xml.h b/obt/xml.h
new file mode 100644 (file)
index 0000000..ac2dc57
--- /dev/null
+++ b/obt/xml.h
@@ -0,0 +1,89 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   obt/xml.h for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __obt_xml_h
+#define __obt_xml_h
+
+#include <libxml/parser.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ObtXmlInst ObtXmlInst;
+
+typedef void (*ObtXmlCallback)(xmlNodePtr node, gpointer data);
+
+ObtXmlInst* obt_xml_instance_new(void);
+void obt_xml_instance_ref(ObtXmlInst *inst);
+void obt_xml_instance_unref(ObtXmlInst *inst);
+
+gboolean obt_xml_load_file(ObtXmlInst *inst,
+                           const gchar *path,
+                           const gchar *root_node);
+gboolean obt_xml_load_config_file(ObtXmlInst *inst,
+                                  const gchar *domain,
+                                  const gchar *filename,
+                                  const gchar *root_node);
+gboolean obt_xml_load_data_file(ObtXmlInst *inst,
+                                const gchar *domain,
+                                const gchar *filename,
+                                const gchar *root_node);
+gboolean obt_xml_load_theme_file(ObtXmlInst *inst,
+                                 const gchar *theme,
+                                 const gchar *domain,
+                                 const gchar *filename,
+                                 const gchar *root_node);
+gboolean obt_xml_load_mem(ObtXmlInst *inst,
+                          gpointer data, guint len, const gchar *root_node);
+
+gboolean obt_xml_save_file(ObtXmlInst *inst,
+                           const gchar *path,
+                           gboolean pretty);
+
+xmlDocPtr obt_xml_doc(ObtXmlInst *inst);
+xmlNodePtr obt_xml_root(ObtXmlInst *inst);
+
+void obt_xml_close(ObtXmlInst *inst);
+
+void obt_xml_register(ObtXmlInst *inst, const gchar *tag,
+                      ObtXmlCallback func, gpointer data);
+void obt_xml_tree(ObtXmlInst *i, xmlNodePtr node);
+void obt_xml_tree_from_root(ObtXmlInst *i);
+
+
+/* helpers */
+
+xmlNodePtr obt_xml_find_node   (xmlNodePtr node, const gchar *name);
+
+gboolean obt_xml_node_contains (xmlNodePtr node, const gchar *val);
+gchar   *obt_xml_node_string   (xmlNodePtr node);
+gint     obt_xml_node_int      (xmlNodePtr node);
+gboolean obt_xml_node_bool     (xmlNodePtr node);
+
+gboolean obt_xml_attr_contains (xmlNodePtr node, const gchar *name,
+                                const gchar *val);
+gboolean obt_xml_attr_string   (xmlNodePtr node, const gchar *name,
+                                gchar **value);
+gboolean obt_xml_attr_int      (xmlNodePtr node, const gchar *name,
+                                gint *value);
+gboolean obt_xml_attr_bool     (xmlNodePtr node, const gchar *name,
+                                gboolean *value);
+
+G_END_DECLS
+
+#endif
index 948ac2c..023fab3 100644 (file)
@@ -42,17 +42,23 @@ struct _ObActionsDefinition {
 
     gchar *name;
 
-    ObActionsDataSetupFunc setup;
+    gboolean canbeinteractive;
+    union {
+        ObActionsIDataSetupFunc i;
+        ObActionsDataSetupFunc n;
+    } setup;
     ObActionsDataFreeFunc free;
     ObActionsRunFunc run;
-    ObActionsInteractiveInputFunc i_input;
-    ObActionsInteractiveCancelFunc i_cancel;
 };
 
 struct _ObActionsAct {
     guint ref;
 
     ObActionsDefinition *def;
+    ObActionsIPreFunc i_pre;
+    ObActionsIInputFunc i_input;
+    ObActionsICancelFunc i_cancel;
+    ObActionsIPostFunc i_post;
     gpointer options;
 };
 
@@ -78,37 +84,55 @@ void actions_shutdown(gboolean reconfig)
     }
 }
 
-gboolean actions_register(const gchar *name,
-                          ObActionsDataSetupFunc setup,
-                          ObActionsDataFreeFunc free,
-                          ObActionsRunFunc run,
-                          ObActionsInteractiveInputFunc i_input,
-                          ObActionsInteractiveCancelFunc i_cancel)
+ObActionsDefinition* do_register(const gchar *name,
+                                 ObActionsDataFreeFunc free,
+                                 ObActionsRunFunc run)
 {
     GSList *it;
     ObActionsDefinition *def;
 
     g_assert(run != NULL);
-    g_assert((i_input == NULL) == (i_cancel == NULL));
 
     for (it = registered; it; it = g_slist_next(it)) {
         def = it->data;
         if (!g_ascii_strcasecmp(name, def->name)) /* already registered */
-            return FALSE;
+            return NULL;
     }
 
     def = g_new(ObActionsDefinition, 1);
     def->ref = 1;
     def->name = g_strdup(name);
-    def->setup = setup;
     def->free = free;
     def->run = run;
-    def->i_input = i_input;
-    def->i_cancel = i_cancel;
 
     registered = g_slist_prepend(registered, def);
+    return def;
+}
 
-    return TRUE;
+gboolean actions_register_i(const gchar *name,
+                            ObActionsIDataSetupFunc setup,
+                            ObActionsDataFreeFunc free,
+                            ObActionsRunFunc run)
+{
+    ObActionsDefinition *def = do_register(name, free, run);
+    if (def) {
+        def->canbeinteractive = TRUE;
+        def->setup.i = setup;
+    }
+    return def != NULL;
+}
+
+gboolean actions_register(const gchar *name,
+                          ObActionsDataSetupFunc setup,
+                          ObActionsDataFreeFunc free,
+                          ObActionsRunFunc run)
+{
+    ObActionsDefinition *def = do_register(name, free, run);
+    if (def) {
+        def->canbeinteractive = FALSE;
+        def->setup.n = setup;
+    }
+    return def != NULL;
 }
 
 static void actions_definition_ref(ObActionsDefinition *def)
@@ -144,6 +168,10 @@ static ObActionsAct* actions_build_act_from_string(const gchar *name)
         act->ref = 1;
         act->def = def;
         actions_definition_ref(act->def);
+        act->i_pre = NULL;
+        act->i_input = NULL;
+        act->i_cancel = NULL;
+        act->i_post = NULL;
         act->options = NULL;
     } else
         g_message(_("Invalid action \"%s\" requested. No such action exists."),
@@ -156,26 +184,46 @@ ObActionsAct* actions_parse_string(const gchar *name)
 {
     ObActionsAct *act = NULL;
 
-    if ((act = actions_build_act_from_string(name)))
-        if (act->def->setup)
-            act->options = act->def->setup(NULL, NULL, NULL);
+    if ((act = actions_build_act_from_string(name))) {
+        if (act->def->canbeinteractive) {
+            if (act->def->setup.i)
+                act->options = act->def->setup.i(NULL,
+                                                 &act->i_pre,
+                                                 &act->i_input,
+                                                 &act->i_cancel,
+                                                 &act->i_post);
+        }
+        else {
+            if (act->def->setup.n)
+                act->options = act->def->setup.n(NULL);
+        }
+    }
+                
 
     return act;
 }
 
-ObActionsAct* actions_parse(ObParseInst *i,
-                            xmlDocPtr doc,
-                            xmlNodePtr node)
+ObActionsAct* actions_parse(xmlNodePtr node)
 {
     gchar *name;
     ObActionsAct *act = NULL;
 
-    if (parse_attr_string("name", node, &name)) {
-        if ((act = actions_build_act_from_string(name)))
+    if (obt_xml_attr_string(node, "name", &name)) {
+        if ((act = actions_build_act_from_string(name))) {
             /* there is more stuff to parse here */
-            if (act->def->setup)
-                act->options = act->def->setup(i, doc, node->xmlChildrenNode);
-
+            if (act->def->canbeinteractive) {
+                if (act->def->setup.i)
+                    act->options = act->def->setup.i(node->children,
+                                                     &act->i_pre,
+                                                     &act->i_input,
+                                                     &act->i_cancel,
+                                                     &act->i_post);
+            }
+            else {
+                if (act->def->setup.n)
+                    act->options = act->def->setup.n(node->children);
+            }
+        }
         g_free(name);
     }
 
@@ -184,7 +232,7 @@ ObActionsAct* actions_parse(ObParseInst *i,
 
 gboolean actions_act_is_interactive(ObActionsAct *act)
 {
-    return act->def->i_cancel != NULL;
+    return act->i_input != NULL;
 }
 
 void actions_act_ref(ObActionsAct *act)
@@ -255,8 +303,13 @@ void actions_run_acts(GSList *acts,
                 /* cancel the old one */
                 if (interactive_act)
                     actions_interactive_cancel_act();
-                ok = actions_interactive_begin_act(act, state);
+                if (act->i_pre)
+                    if (!act->i_pre(state, act->options))
+                        act->i_input = NULL; /* remove the interactivity */
             }
+            /* check again cuz it might have been cancelled */
+            if (actions_act_is_interactive(act))
+                ok = actions_interactive_begin_act(act, state);
         }
 
         /* fire the action's run function with this data */
@@ -266,7 +319,7 @@ void actions_run_acts(GSList *acts,
                     actions_interactive_end_act();
             } else {
                 /* make sure its interactive if it returned TRUE */
-                g_assert(act->def->i_cancel && act->def->i_input);
+                g_assert(act->i_input);
 
                 /* no actions are run after the interactive one */
                 break;
@@ -283,7 +336,8 @@ gboolean actions_interactive_act_running(void)
 void actions_interactive_cancel_act(void)
 {
     if (interactive_act) {
-        interactive_act->def->i_cancel(interactive_act->options);
+        if (interactive_act->i_cancel)
+            interactive_act->i_cancel(interactive_act->options);
         actions_interactive_end_act();
     }
 }
@@ -311,6 +365,9 @@ static void actions_interactive_end_act(void)
     if (interactive_act) {
         ungrab_keyboard();
 
+        if (interactive_act->i_post)
+            interactive_act->i_post(interactive_act->options);
+
         actions_act_unref(interactive_act);
         interactive_act = NULL;
     }
@@ -320,8 +377,8 @@ gboolean actions_interactive_input_event(XEvent *e)
 {
     gboolean used = FALSE;
     if (interactive_act) {
-        if (!interactive_act->def->i_input(interactive_initial_state, e,
-                                           interactive_act->options, &used))
+        if (!interactive_act->i_input(interactive_initial_state, e,
+                                      interactive_act->options, &used))
         {
             used = TRUE; /* if it cancelled the action then it has to of
                             been used */
@@ -351,13 +408,19 @@ void actions_client_move(ObActionsData *data, gboolean start)
                are ignored during a grab, so don't force fake ones when they
                should be ignored
             */
-            if ((c = client_under_pointer()) && c != data->client &&
-                !grab_on_pointer())
-            {
-                ob_debug_type(OB_DEBUG_FOCUS,
-                              "Generating fake enter because we did a "
-                              "mouse-event action");
-                event_enter_client(c);
+            if (!grab_on_pointer()) {
+                if ((c = client_under_pointer()) && c != data->client) {
+                    ob_debug_type(OB_DEBUG_FOCUS,
+                                  "Generating fake enter because we did a "
+                                  "mouse-event action");
+                    event_enter_client(c);
+                }
+                else if (!c && c != data->client) {
+                    ob_debug_type(OB_DEBUG_FOCUS,
+                                  "Generating fake leave because we did a "
+                                  "mouse-event action");
+                    event_enter_client(data->client);
+                }
             }
         }
         else if (!data->button && !config_focus_under_mouse)
index 6db6f8d..afcc96b 100644 (file)
@@ -18,7 +18,8 @@
 
 #include "misc.h"
 #include "frame.h"
-#include "parser/parse.h"
+#include "obt/xml.h"
+
 #include <glib.h>
 #include <X11/Xlib.h>
 
@@ -30,16 +31,26 @@ typedef struct _ObActionsGlobalData   ObActionsGlobalData;
 typedef struct _ObActionsClientData   ObActionsClientData;
 typedef struct _ObActionsSelectorData ObActionsSelectorData;
 
-typedef gpointer (*ObActionsDataSetupFunc)(ObParseInst *i,
-                                           xmlDocPtr doc, xmlNodePtr node);
 typedef void     (*ObActionsDataFreeFunc)(gpointer options);
 typedef gboolean (*ObActionsRunFunc)(ObActionsData *data,
                                      gpointer options);
-typedef gboolean (*ObActionsInteractiveInputFunc)(guint initial_state,
+typedef gpointer (*ObActionsDataSetupFunc)(xmlNodePtr node);
+
+/* functions for interactive actions */
+/* return TRUE if the action is going to be interactive, or false to change
+   your mind and make it not */
+typedef gboolean (*ObActionsIPreFunc)(guint initial_state, gpointer options);
+typedef void     (*ObActionsIPostFunc)(gpointer options);
+typedef gboolean (*ObActionsIInputFunc)(guint initial_state,
                                                   XEvent *e,
                                                   gpointer options,
                                                   gboolean *used);
-typedef void     (*ObActionsInteractiveCancelFunc)(gpointer options);
+typedef void     (*ObActionsICancelFunc)(gpointer options);
+typedef gpointer (*ObActionsIDataSetupFunc)(xmlNodePtr node,
+                                            ObActionsIPreFunc *pre,
+                                            ObActionsIInputFunc *input,
+                                            ObActionsICancelFunc *cancel,
+                                            ObActionsIPostFunc *post);
 
 struct _ObActionsData {
     ObUserAction uact;
@@ -55,18 +66,18 @@ struct _ObActionsData {
 void actions_startup(gboolean reconfigure);
 void actions_shutdown(gboolean reconfigure);
 
-/*! If the action is interactive, then i_input and i_cancel are not NULL.
-  Otherwise, they should both be NULL. */
+/*! Use this if the actions created from this name may be interactive */
+gboolean actions_register_i(const gchar *name,
+                            ObActionsIDataSetupFunc setup,
+                            ObActionsDataFreeFunc free,
+                            ObActionsRunFunc run);
+
 gboolean actions_register(const gchar *name,
                           ObActionsDataSetupFunc setup,
                           ObActionsDataFreeFunc free,
-                          ObActionsRunFunc run,
-                          ObActionsInteractiveInputFunc i_input,
-                          ObActionsInteractiveCancelFunc i_cancel);
+                          ObActionsRunFunc run);
 
-ObActionsAct* actions_parse(ObParseInst *i,
-                            xmlDocPtr doc,
-                            xmlNodePtr node);
+ObActionsAct* actions_parse(xmlNodePtr node);
 ObActionsAct* actions_parse_string(const gchar *name);
 
 gboolean actions_act_is_interactive(ObActionsAct *act);
@@ -81,7 +92,7 @@ void actions_act_unref(ObActionsAct *act);
 void actions_set_need_pointer_replay_before_move(gboolean replay);
 /*! Returns if a ReplayPointer is still needed.  If it was called while running
   actions then this will be false */
-gboolean actions_get_need_pointer_replay_before_move();
+gboolean actions_get_need_pointer_replay_before_move(void);
 
 /*! Pass in a GSList of ObActionsAct's to be run. */
 void actions_run_acts(GSList *acts,
@@ -93,8 +104,8 @@ void actions_run_acts(GSList *acts,
                       ObFrameContext con,
                       struct _ObClient *client);
 
-gboolean actions_interactive_act_running();
-void actions_interactive_cancel_act();
+gboolean actions_interactive_act_running(void);
+void actions_interactive_cancel_act(void);
 
 gboolean actions_interactive_input_event(XEvent *e);
 
index 8125b9b..e21e9e6 100644 (file)
@@ -7,36 +7,40 @@ typedef struct {
     gboolean add;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_add_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_remove_func(ObParseInst *i,
-                                  xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_add_func(xmlNodePtr node);
+static gpointer setup_remove_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
+/* 3.4-compatibility */
+static gpointer setup_addcurrent_func(xmlNodePtr node);
+static gpointer setup_addlast_func(xmlNodePtr node);
+static gpointer setup_removecurrent_func(xmlNodePtr node);
+static gpointer setup_removelast_func(xmlNodePtr node);
 
 void action_addremovedesktop_startup(void)
 {
-    actions_register("AddDesktop",
-                     setup_add_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
-    actions_register("RemoveDesktop",
-                     setup_remove_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("AddDesktop", setup_add_func, g_free, run_func);
+    actions_register("RemoveDesktop", setup_remove_func, g_free, run_func);
+
+    /* 3.4-compatibility */
+    actions_register("AddDesktopLast", setup_addlast_func, g_free, run_func);
+    actions_register("RemoveDesktopLast", setup_removelast_func,
+                     g_free, run_func);
+    actions_register("AddDesktopCurrent", setup_addcurrent_func,
+                     g_free, run_func);
+    actions_register("RemoveDesktopCurrent", setup_removecurrent_func,
+                     g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("where", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "where"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "last"))
             o->current = FALSE;
         else if (!g_ascii_strcasecmp(s, "current"))
@@ -47,28 +51,20 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_add_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_add_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->add = TRUE;
     return o;
 }
 
-static gpointer setup_remove_func(ObParseInst *i,
-                                  xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_remove_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->add = FALSE;
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
@@ -85,3 +81,32 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     return FALSE;
 }
+
+/* 3.4-compatibility */
+static gpointer setup_addcurrent_func(xmlNodePtr node)
+{
+    Options *o = setup_add_func(node);
+    o->current = TRUE;
+    return o;
+}
+
+static gpointer setup_addlast_func(xmlNodePtr node)
+{
+    Options *o = setup_add_func(node);
+    o->current = FALSE;
+    return o;
+}
+
+static gpointer setup_removecurrent_func(xmlNodePtr node)
+{
+    Options *o = setup_remove_func(node);
+    o->current = TRUE;
+    return o;
+}
+
+static gpointer setup_removelast_func(xmlNodePtr node)
+{
+    Options *o = setup_remove_func(node);
+    o->current = FALSE;
+    return o;
+}
index 47141ac..4563e65 100644 (file)
@@ -38,4 +38,6 @@ void action_all_startup(void)
     action_growtoedge_startup();
     action_if_startup();
     action_focustobottom_startup();
+    /* 3.4-compatibility */
+    action_shadelowerraise_startup();
 }
index 5f3f573..6acbc9c 100644 (file)
@@ -1,43 +1,45 @@
 #ifndef __actions_all_h
 #define __actions_all_h
 
-void action_all_startup();
+void action_all_startup(void);
 
-void action_execute_startup();
-void action_debug_startup();
-void action_showmenu_startup();
-void action_showdesktop_startup();
-void action_reconfigure_startup();
-void action_exit_startup();
-void action_restart_startup();
-void action_cyclewindows_startup();
-void action_breakchroot_startup();
-void action_close_startup();
-void action_move_startup();
-void action_focus_startup();
-void action_raise_startup();
-void action_lower_startup();
-void action_raiselower_startup();
-void action_unfocus_startup();
-void action_iconify_startup();
-void action_fullscreen_startup();
-void action_maximize_startup();
-void action_moveresizeto_startup();
-void action_moverelative_startup();
-void action_shade_startup();
-void action_kill_startup();
-void action_omnipresent_startup();
-void action_directionalwindows_startup();
-void action_resize_startup();
-void action_decorations_startup();
-void action_desktop_startup();
-void action_resizerelative_startup();
-void action_addremovedesktop_startup();
-void action_dockautohide_startup();
-void action_layer_startup();
-void action_movetoedge_startup();
-void action_growtoedge_startup();
-void action_if_startup();
-void action_focustobottom_startup();
+void action_execute_startup(void);
+void action_debug_startup(void);
+void action_showmenu_startup(void);
+void action_showdesktop_startup(void);
+void action_reconfigure_startup(void);
+void action_exit_startup(void);
+void action_restart_startup(void);
+void action_cyclewindows_startup(void);
+void action_breakchroot_startup(void);
+void action_close_startup(void);
+void action_move_startup(void);
+void action_focus_startup(void);
+void action_raise_startup(void);
+void action_lower_startup(void);
+void action_raiselower_startup(void);
+void action_unfocus_startup(void);
+void action_iconify_startup(void);
+void action_fullscreen_startup(void);
+void action_maximize_startup(void);
+void action_moveresizeto_startup(void);
+void action_moverelative_startup(void);
+void action_shade_startup(void);
+void action_kill_startup(void);
+void action_omnipresent_startup(void);
+void action_directionalwindows_startup(void);
+void action_resize_startup(void);
+void action_decorations_startup(void);
+void action_desktop_startup(void);
+void action_resizerelative_startup(void);
+void action_addremovedesktop_startup(void);
+void action_dockautohide_startup(void);
+void action_layer_startup(void);
+void action_movetoedge_startup(void);
+void action_growtoedge_startup(void);
+void action_if_startup(void);
+void action_focustobottom_startup(void);
+/* 3.4-compatibility */
+void action_shadelowerraise_startup(void);
 
 #endif
index 9804091..8c00458 100644 (file)
@@ -7,8 +7,7 @@ void action_breakchroot_startup(void)
 {
     actions_register("BreakChroot",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
index ab75e05..d2bc96c 100644 (file)
@@ -7,8 +7,7 @@ void action_close_startup(void)
 {
     actions_register("Close",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
index 32d6a45..d111224 100644 (file)
@@ -8,23 +8,36 @@
 
 typedef struct {
     gboolean linear;
-    gboolean dialog;
     gboolean dock_windows;
     gboolean desktop_windows;
     gboolean all_desktops;
     gboolean forward;
     gboolean bar;
     gboolean raise;
+    ObFocusCyclePopupMode dialog_mode;
     GSList *actions;
-} Options;
 
-static gboolean cycling = FALSE;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_forward_func(ObParseInst *i, xmlDocPtr doc,
-                                   xmlNodePtr node);
-static gpointer setup_backward_func(ObParseInst *i, xmlDocPtr doc,
-                                    xmlNodePtr node);
+    /* options for after we're done */
+    gboolean cancel; /* did the user cancel or not */
+    guint state;     /* keyboard state when finished */
+} Options;
+
+static gpointer setup_func(xmlNodePtr node,
+                           ObActionsIPreFunc *pre,
+                           ObActionsIInputFunc *in,
+                           ObActionsICancelFunc *c,
+                           ObActionsIPostFunc *post);
+static gpointer setup_forward_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *in,
+                                   ObActionsICancelFunc *c,
+                                   ObActionsIPostFunc *post);
+static gpointer setup_backward_func(xmlNodePtr node,
+                                    ObActionsIPreFunc *pre,
+                                    ObActionsIInputFunc *in,
+                                    ObActionsICancelFunc *c,
+                                    ObActionsIPostFunc *post);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 static gboolean i_input_func(guint initial_state,
@@ -32,49 +45,55 @@ static gboolean i_input_func(guint initial_state,
                              gpointer options,
                              gboolean *used);
 static void     i_cancel_func(gpointer options);
-
-static void     end_cycle(gboolean cancel, guint state, Options *o);
+static void     i_post_func(gpointer options);
 
 void action_cyclewindows_startup(void)
 {
-    actions_register("NextWindow", setup_forward_func, free_func,
-                     run_func, i_input_func, i_cancel_func);
-    actions_register("PreviousWindow", setup_backward_func, free_func,
-                     run_func, i_input_func, i_cancel_func);
+    actions_register_i("NextWindow", setup_forward_func, free_func, run_func);
+    actions_register_i("PreviousWindow", setup_backward_func, free_func,
+                       run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node,
+                           ObActionsIPreFunc *pre,
+                           ObActionsIInputFunc *input,
+                           ObActionsICancelFunc *cancel,
+                           ObActionsIPostFunc *post)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
-    o->dialog = TRUE;
     o->bar = TRUE;
-
-    if ((n = parse_find_node("linear", node)))
-        o->linear = parse_bool(doc, n);
-    if ((n = parse_find_node("dialog", node)))
-        o->dialog = parse_bool(doc, n);
-    if ((n = parse_find_node("bar", node)))
-        o->bar = parse_bool(doc, n);
-    if ((n = parse_find_node("raise", node)))
-        o->raise = parse_bool(doc, n);
-    if ((n = parse_find_node("panels", node)))
-        o->dock_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("desktop", node)))
-        o->desktop_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("allDesktops", node)))
-        o->all_desktops = parse_bool(doc, n);
-
-    if ((n = parse_find_node("finalactions", node))) {
+    o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST;
+
+    if ((n = obt_xml_find_node(node, "linear")))
+        o->linear = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "dialog"))) {
+        if (obt_xml_node_contains(n, "none"))
+            o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE;
+        else if (obt_xml_node_contains(n, "icons"))
+            o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_ICONS;
+    }
+    if ((n = obt_xml_find_node(node, "bar")))
+        o->bar = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "raise")))
+        o->raise = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "panels")))
+        o->dock_windows = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "desktop")))
+        o->desktop_windows = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "allDesktops")))
+        o->all_desktops = obt_xml_node_bool(n);
+
+    if ((n = obt_xml_find_node(node, "finalactions"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_xml_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->actions = g_slist_append(o->actions, action);
-            m = parse_find_node("action", m->next);
+            m = obt_xml_find_node(m->next, "action");
         }
     }
     else {
@@ -86,21 +105,30 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
                                      actions_parse_string("Unshade"));
     }
 
+    *input = i_input_func;
+    *cancel = i_cancel_func;
+    *post = i_post_func;
     return o;
 }
 
-static gpointer setup_forward_func(ObParseInst *i, xmlDocPtr doc,
-                                   xmlNodePtr node)
+static gpointer setup_forward_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node, pre, input, cancel, post);
     o->forward = TRUE;
     return o;
 }
 
-static gpointer setup_backward_func(ObParseInst *i, xmlDocPtr doc,
-                                    xmlNodePtr node)
+static gpointer setup_backward_func(xmlNodePtr node,
+                                    ObActionsIPreFunc *pre,
+                                    ObActionsIInputFunc *input,
+                                    ObActionsICancelFunc *cancel,
+                                    ObActionsIPostFunc *post)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node, pre, input, cancel, post);
     o->forward = FALSE;
     return o;
 }
@@ -129,9 +157,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
                      o->linear,
                      TRUE,
                      o->bar,
-                     o->dialog,
+                     o->dialog_mode,
                      FALSE, FALSE);
-    cycling = TRUE;
 
     stacking_restore();
     if (o->raise && ft) stacking_temp_raise(CLIENT_AS_WINDOW(ft));
@@ -144,10 +171,13 @@ static gboolean i_input_func(guint initial_state,
                              gpointer options,
                              gboolean *used)
 {
+    Options *o = options;
+
     if (e->type == KeyPress) {
         /* Escape cancels no matter what */
         if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
-            end_cycle(TRUE, e->xkey.state, options);
+            o->cancel = TRUE;
+            o->state = e->xkey.state;
             return FALSE;
         }
 
@@ -155,7 +185,8 @@ static gboolean i_input_func(guint initial_state,
         else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
                  !initial_state)
         {
-            end_cycle(FALSE, e->xkey.state, options);
+            o->cancel = FALSE;
+            o->state = e->xkey.state;
             return FALSE;
         }
     }
@@ -163,7 +194,8 @@ static gboolean i_input_func(guint initial_state,
     else if (e->type == KeyRelease && initial_state &&
              (e->xkey.state & initial_state) == 0)
     {
-        end_cycle(FALSE, e->xkey.state, options);
+        o->cancel = FALSE;
+        o->state = e->xkey.state;
         return FALSE;
     }
 
@@ -172,14 +204,14 @@ static gboolean i_input_func(guint initial_state,
 
 static void i_cancel_func(gpointer options)
 {
-    /* we get cancelled when we move focus, but we're not cycling anymore, so
-       just ignore that */
-    if (cycling)
-        end_cycle(TRUE, 0, options);
+    Options *o = options;
+    o->cancel = TRUE;
+    o->state = 0;
 }
 
-static void end_cycle(gboolean cancel, guint state, Options *o)
+static void i_post_func(gpointer options)
 {
+    Options *o = options;
     struct _ObClient *ft;
 
     ft = focus_cycle(o->forward,
@@ -189,13 +221,12 @@ static void end_cycle(gboolean cancel, guint state, Options *o)
                      o->linear,
                      TRUE,
                      o->bar,
-                     o->dialog,
-                     TRUE, cancel);
-    cycling = FALSE;
+                     o->dialog_mode,
+                     TRUE, o->cancel);
 
     if (ft)
         actions_run_acts(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
-                         state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);
+                         o->state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);
 
     stacking_restore();
 }
index f71b685..9ba7b1b 100644 (file)
@@ -5,39 +5,32 @@ typedef struct {
     gchar   *str;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_debug_startup(void)
 {
-    actions_register("Debug",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Debug", setup_func, free_func, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("string", node)))
-        o->str = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "string")))
+        o->str = obt_xml_node_string(n);
     return o;
 }
 
 static void free_func(gpointer options)
 {
     Options *o = options;
-
-    if (o) {
-        g_free(o->str);
-        g_free(o);
-    }
+    g_free(o->str);
+    g_free(o);
 }
 
 /* Always return FALSE because its not interactive */
index e85fb8e..f6fd2cb 100644 (file)
@@ -7,10 +7,9 @@ static gboolean run_func_toggle(ObActionsData *data, gpointer options);
 
 void action_decorations_startup(void)
 {
-    actions_register("Decorate", NULL, NULL, run_func_on, NULL, NULL);
-    actions_register("Undecorate", NULL, NULL, run_func_off, NULL, NULL);
-    actions_register("ToggleDecorations", NULL, NULL, run_func_toggle,
-                     NULL, NULL);
+    actions_register("Decorate", NULL, NULL, run_func_on);
+    actions_register("Undecorate", NULL, NULL, run_func_off);
+    actions_register("ToggleDecorations", NULL, NULL, run_func_toggle);
 }
 
 /* Always return FALSE because its not interactive */
index 0741615..5b0282c 100644 (file)
@@ -1,6 +1,7 @@
 #include "openbox/actions.h"
 #include "openbox/screen.h"
 #include "openbox/client.h"
+#include "openbox/openbox.h"
 #include <glib.h>
 
 typedef enum {
@@ -24,37 +25,143 @@ typedef struct {
     } u;
     gboolean send;
     gboolean follow;
+    gboolean interactive;
 } Options;
 
-static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node);
-static gpointer setup_send_func(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node);
+static gpointer setup_go_func(xmlNodePtr node,
+                              ObActionsIPreFunc *pre,
+                              ObActionsIInputFunc *input,
+                              ObActionsICancelFunc *cancel,
+                              ObActionsIPostFunc *post);
+static gpointer setup_send_func(xmlNodePtr node,
+                                ObActionsIPreFunc *pre,
+                                ObActionsIInputFunc *input,
+                                ObActionsICancelFunc *cancel,
+                                ObActionsIPostFunc *post);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
+static gboolean i_pre_func(guint state, gpointer options);
+static gboolean i_input_func(guint initial_state,
+                             XEvent *e,
+                             gpointer options,
+                             gboolean *used);
+static void i_post_func(gpointer options);
+
+/* 3.4-compatibility */
+static gpointer setup_go_last_func(xmlNodePtr node);
+static gpointer setup_send_last_func(xmlNodePtr node);
+static gpointer setup_go_abs_func(xmlNodePtr node);
+static gpointer setup_send_abs_func(xmlNodePtr node);
+static gpointer setup_go_next_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post);
+static gpointer setup_send_next_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post);
+static gpointer setup_go_prev_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post);
+static gpointer setup_send_prev_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post);
+static gpointer setup_go_left_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post);
+static gpointer setup_send_left_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post);
+static gpointer setup_go_right_func(xmlNodePtr node,
+                                    ObActionsIPreFunc *pre,
+                                    ObActionsIInputFunc *input,
+                                    ObActionsICancelFunc *cancel,
+                                    ObActionsIPostFunc *post);
+static gpointer setup_send_right_func(xmlNodePtr node,
+                                      ObActionsIPreFunc *pre,
+                                      ObActionsIInputFunc *input,
+                                      ObActionsICancelFunc *cancel,
+                                      ObActionsIPostFunc *post);
+static gpointer setup_go_up_func(xmlNodePtr node,
+                                 ObActionsIPreFunc *pre,
+                                 ObActionsIInputFunc *input,
+                                 ObActionsICancelFunc *cancel,
+                                 ObActionsIPostFunc *post);
+static gpointer setup_send_up_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post);
+static gpointer setup_go_down_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post);
+static gpointer setup_send_down_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post);
 void action_desktop_startup(void)
 {
-    actions_register("GoToDesktop", setup_go_func, g_free, run_func,
-                     NULL, NULL);
-    actions_register("SendToDesktop", setup_send_func, g_free, run_func,
-                     NULL, NULL);
+    actions_register_i("GoToDesktop", setup_go_func, g_free, run_func);
+    actions_register_i("SendToDesktop", setup_send_func, g_free, run_func);
+    /* 3.4-compatibility */
+    actions_register("DesktopLast", setup_go_last_func, g_free, run_func);
+    actions_register("SendToDesktopLast", setup_send_last_func,
+                     g_free, run_func);
+    actions_register("Desktop", setup_go_abs_func, g_free, run_func);
+    actions_register("SendToDesktop", setup_send_abs_func, g_free, run_func);
+    actions_register_i("DesktopNext", setup_go_next_func, g_free, run_func);
+    actions_register_i("SendToDesktopNext", setup_send_next_func,
+                       g_free, run_func);
+    actions_register_i("DesktopPrevious", setup_go_prev_func,
+                       g_free, run_func);
+    actions_register_i("SendToDesktopPrevious", setup_send_prev_func,
+                       g_free, run_func);
+    actions_register_i("DesktopLeft", setup_go_left_func, g_free, run_func);
+    actions_register_i("SendToDesktopLeft", setup_send_left_func,
+                       g_free, run_func);
+    actions_register_i("DesktopRight", setup_go_right_func, g_free, run_func);
+    actions_register_i("SendToDesktopRight", setup_send_right_func,
+                       g_free, run_func);
+    actions_register_i("DesktopUp", setup_go_up_func, g_free, run_func);
+    actions_register_i("SendToDesktopUp", setup_send_up_func,
+                       g_free, run_func);
+    actions_register_i("DesktopDown", setup_go_down_func, g_free, run_func);
+    actions_register_i("SendToDesktopDown", setup_send_down_func,
+                       g_free, run_func);
 }
 
-static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node,
+                           ObActionsIPreFunc *pre,
+                           ObActionsIInputFunc *input,
+                           ObActionsICancelFunc *cancel,
+                           ObActionsIPostFunc *post)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
-    /* don't go anywhere if theres no options given */
+    /* don't go anywhere if there are no options given */
     o->type = ABSOLUTE;
     o->u.abs.desktop = screen_desktop;
     /* wrap by default - it's handy! */
     o->u.rel.wrap = TRUE;
 
-    if ((n = parse_find_node("to", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "to"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "last"))
             o->type = LAST;
         else if (!g_ascii_strcasecmp(s, "next")) {
@@ -94,24 +201,54 @@ static gpointer setup_go_func(ObParseInst *i, xmlDocPtr doc,
         g_free(s);
     }
 
-    if ((n = parse_find_node("wrap", node)))
-        o->u.rel.wrap = parse_bool(doc, n);
+    if ((n = obt_xml_find_node(node, "wrap")))
+        o->u.rel.wrap = obt_xml_node_bool(n);
 
     return o;
 }
 
-static gpointer setup_send_func(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node)
+
+static gpointer setup_go_func(xmlNodePtr node,
+                              ObActionsIPreFunc *pre,
+                              ObActionsIInputFunc *input,
+                              ObActionsICancelFunc *cancel,
+                              ObActionsIPostFunc *post)
+{
+    Options *o;
+
+    o = setup_func(node, pre, input, cancel, post);
+    if (o->type == RELATIVE) {
+        o->interactive = TRUE;
+        *pre = i_pre_func;
+        *input = i_input_func;
+        *post = i_post_func;
+    }
+
+    return o;
+}
+
+static gpointer setup_send_func(xmlNodePtr node,
+                                ObActionsIPreFunc *pre,
+                                ObActionsIInputFunc *input,
+                                ObActionsICancelFunc *cancel,
+                                ObActionsIPostFunc *post)
 {
     xmlNodePtr n;
     Options *o;
 
-    o = setup_go_func(i, doc, node);
+    o = setup_func(node, pre, input, cancel, post);
     o->send = TRUE;
     o->follow = TRUE;
 
-    if ((n = parse_find_node("follow", node)))
-        o->follow = parse_bool(doc, n);
+    if ((n = obt_xml_find_node(node, "follow")))
+        o->follow = obt_xml_node_bool(n);
+
+    if (o->type == RELATIVE && o->follow) {
+        o->interactive = TRUE;
+        *pre = i_pre_func;
+        *input = i_input_func;
+        *post = i_post_func;
+    }
 
     return o;
 }
@@ -133,6 +270,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         d = screen_find_desktop(screen_desktop,
                                 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
         break;
+    default:
+        g_assert_not_reached();
     }
 
     if (d < screen_num_desktops && d != screen_desktop) {
@@ -152,5 +291,264 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
         actions_client_move(data, FALSE);
     }
-    return FALSE;
+
+    return o->interactive;
+}
+
+static gboolean i_input_func(guint initial_state,
+                             XEvent *e,
+                             gpointer options,
+                             gboolean *used)
+{
+    if (e->type == KeyPress) {
+        /* Escape cancels no matter what */
+        if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
+            return FALSE;
+        }
+
+        /* There were no modifiers and they pressed enter */
+        else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
+                 !initial_state)
+        {
+            return FALSE;
+        }
+    }
+    /* They released the modifiers */
+    else if (e->type == KeyRelease && initial_state &&
+             (e->xkey.state & initial_state) == 0)
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static gboolean i_pre_func(guint initial_state, gpointer options)
+{
+    if (!initial_state) {
+        Options *o = options;
+        o->interactive = FALSE;
+        return FALSE;
+    }
+    else {
+        screen_show_desktop_popup(screen_desktop, TRUE);
+        return TRUE;
+    }
+}
+
+static void i_post_func(gpointer options)
+{
+    screen_hide_desktop_popup();
+}
+
+/* 3.4-compatilibity */
+static gpointer setup_follow(xmlNodePtr node)
+{
+    xmlNodePtr n;
+    Options *o = g_new0(Options, 1);
+    o->send = TRUE;
+    o->follow = TRUE;
+    if ((n = obt_xml_find_node(node, "follow")))
+        o->follow = obt_xml_node_bool(n);
+    return o;
+}
+
+static gpointer setup_go_last_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->type = LAST;
+    return o;
+}
+
+static gpointer setup_send_last_func(xmlNodePtr node)
+{
+    Options *o = setup_follow(node);
+    o->type = LAST;
+    return o;
+}
+
+static gpointer setup_go_abs_func(xmlNodePtr node)
+{
+    xmlNodePtr n;
+    Options *o = g_new0(Options, 1);
+    o->type = ABSOLUTE;
+    if ((n = obt_xml_find_node(node, "desktop")))
+        o->u.abs.desktop = obt_xml_node_int(n) - 1;
+    else
+        o->u.abs.desktop = screen_desktop;
+    return o;
+}
+
+static gpointer setup_send_abs_func(xmlNodePtr node)
+{
+    xmlNodePtr n;
+    Options *o = setup_follow(node);
+    o->type = ABSOLUTE;
+    if ((n = obt_xml_find_node(node, "desktop")))
+        o->u.abs.desktop = obt_xml_node_int(n) - 1;
+    else
+        o->u.abs.desktop = screen_desktop;
+    return o;
+}
+
+static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
+                      ObDirection dir,
+                      ObActionsIPreFunc *pre,
+                      ObActionsIInputFunc *input,
+                      ObActionsIPostFunc *post)
+{
+    xmlNodePtr n;
+
+    o->type = RELATIVE;
+    o->u.rel.linear = lin;
+    o->u.rel.dir = dir;
+    o->u.rel.wrap = TRUE;
+
+    if ((n = obt_xml_find_node(node, "wrap")))
+        o->u.rel.wrap = obt_xml_node_bool(n);
+
+    if (input) {
+        o->interactive = TRUE;
+        *pre = i_pre_func;
+        *input = i_input_func;
+        *post = i_post_func;
+    }
+}
+
+static gpointer setup_go_next_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post)
+{
+    Options *o = g_new0(Options, 1);
+    setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post);
+    return o;
+}
+
+static gpointer setup_send_next_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post)
+{
+    Options *o = setup_follow(node);
+    setup_rel(o, node, TRUE, OB_DIRECTION_EAST,
+              pre, (o->follow ? input : NULL), post);
+    return o;
+}
+
+static gpointer setup_go_prev_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post)
+{
+    Options *o = g_new0(Options, 1);
+    setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post);
+    return o;
+}
+
+static gpointer setup_send_prev_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post)
+{
+    Options *o = setup_follow(node);
+    setup_rel(o, node, TRUE, OB_DIRECTION_WEST,
+              pre, (o->follow ? input : NULL), post);
+    return o;
+}
+
+static gpointer setup_go_left_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post)
+{
+    Options *o = g_new0(Options, 1);
+    setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post);
+    return o;
+}
+
+static gpointer setup_send_left_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post)
+{
+    Options *o = setup_follow(node);
+    setup_rel(o, node, FALSE, OB_DIRECTION_WEST,
+              pre, (o->follow ? input : NULL), post);
+    return o;
+}
+
+static gpointer setup_go_right_func(xmlNodePtr node,
+                                    ObActionsIPreFunc *pre,
+                                    ObActionsIInputFunc *input,
+                                    ObActionsICancelFunc *cancel,
+                                    ObActionsIPostFunc *post)
+{
+    Options *o = g_new0(Options, 1);
+    setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post);
+    return o;
+}
+
+static gpointer setup_send_right_func(xmlNodePtr node,
+                                      ObActionsIPreFunc *pre,
+                                      ObActionsIInputFunc *input,
+                                      ObActionsICancelFunc *cancel,
+                                      ObActionsIPostFunc *post)
+{
+    Options *o = setup_follow(node);
+    setup_rel(o, node, FALSE, OB_DIRECTION_EAST,
+              pre, (o->follow ? input : NULL), post);
+    return o;
+}
+
+static gpointer setup_go_up_func(xmlNodePtr node,
+                                 ObActionsIPreFunc *pre,
+                                 ObActionsIInputFunc *input,
+                                 ObActionsICancelFunc *cancel,
+                                 ObActionsIPostFunc *post)
+{
+    Options *o = g_new0(Options, 1);
+    setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post);
+    return o;
+}
+
+static gpointer setup_send_up_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post)
+{
+    Options *o = setup_follow(node);
+    setup_rel(o, node, FALSE, OB_DIRECTION_NORTH,
+              pre, (o->follow ? input : NULL), post);
+    return o;
+}
+
+static gpointer setup_go_down_func(xmlNodePtr node,
+                                   ObActionsIPreFunc *pre,
+                                   ObActionsIInputFunc *input,
+                                   ObActionsICancelFunc *cancel,
+                                   ObActionsIPostFunc *post)
+{
+    Options *o = g_new0(Options, 1);
+    setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post);
+    return o;
+}
+
+static gpointer setup_send_down_func(xmlNodePtr node,
+                                     ObActionsIPreFunc *pre,
+                                     ObActionsIInputFunc *input,
+                                     ObActionsICancelFunc *cancel,
+                                     ObActionsIPostFunc *post)
+{
+    Options *o = setup_follow(node);
+    setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH,
+              pre, (o->follow ? input : NULL), post);
+    return o;
 }
index 6559e44..2cca450 100644 (file)
@@ -20,11 +20,13 @@ typedef struct {
 
 static gboolean cycling = FALSE;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_cycle_func(ObParseInst *i, xmlDocPtr doc,
-                                 xmlNodePtr node);
-static gpointer setup_target_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_cycle_func(xmlNodePtr node,
+                                 ObActionsIPreFunc *pre,
+                                 ObActionsIInputFunc *input,
+                                 ObActionsICancelFunc *cancel,
+                                 ObActionsIPostFunc *post);
+static gpointer setup_target_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 static gboolean i_input_func(guint initial_state,
@@ -35,15 +37,98 @@ static void     i_cancel_func(gpointer options);
 
 static void     end_cycle(gboolean cancel, guint state, Options *o);
 
+/* 3.4-compatibility */
+static gpointer setup_north_cycle_func(xmlNodePtr node,
+                                       ObActionsIPreFunc *pre,
+                                       ObActionsIInputFunc *in,
+                                       ObActionsICancelFunc *c,
+                                       ObActionsIPostFunc *post);
+static gpointer setup_south_cycle_func(xmlNodePtr node,
+                                       ObActionsIPreFunc *pre,
+                                       ObActionsIInputFunc *in,
+                                       ObActionsICancelFunc *c,
+                                       ObActionsIPostFunc *post);
+static gpointer setup_east_cycle_func(xmlNodePtr node,
+                                      ObActionsIPreFunc *pre,
+                                      ObActionsIInputFunc *in,
+                                      ObActionsICancelFunc *c,
+                                      ObActionsIPostFunc *post);
+static gpointer setup_west_cycle_func(xmlNodePtr node,
+                                      ObActionsIPreFunc *pre,
+                                      ObActionsIInputFunc *in,
+                                      ObActionsICancelFunc *c,
+                                      ObActionsIPostFunc *post);
+static gpointer setup_northwest_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *in,
+                                           ObActionsICancelFunc *c,
+                                           ObActionsIPostFunc *post);
+static gpointer setup_northeast_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *in,
+                                           ObActionsICancelFunc *c,
+                                           ObActionsIPostFunc *post);
+static gpointer setup_southwest_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *in,
+                                           ObActionsICancelFunc *c,
+                                           ObActionsIPostFunc *post);
+static gpointer setup_southeast_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *in,
+                                           ObActionsICancelFunc *c,
+                                           ObActionsIPostFunc *post);
+static gpointer setup_north_target_func(xmlNodePtr node);
+static gpointer setup_south_target_func(xmlNodePtr node);
+static gpointer setup_east_target_func(xmlNodePtr node);
+static gpointer setup_west_target_func(xmlNodePtr node);
+static gpointer setup_northwest_target_func(xmlNodePtr node);
+static gpointer setup_northeast_target_func(xmlNodePtr node);
+static gpointer setup_southwest_target_func(xmlNodePtr node);
+static gpointer setup_southeast_target_func(xmlNodePtr node);
+
 void action_directionalwindows_startup(void)
 {
-    actions_register("DirectionalCycleWindows", setup_cycle_func, free_func,
-                     run_func, i_input_func, i_cancel_func);
+    actions_register_i("DirectionalCycleWindows", setup_cycle_func, free_func,
+                       run_func);
     actions_register("DirectionalTargetWindow", setup_target_func, free_func,
-                     run_func, NULL, NULL);
+                     run_func);
+    /* 3.4-compatibility */
+    actions_register_i("DirectionalFocusNorth", setup_north_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusSouth", setup_south_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusWest", setup_west_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusEast", setup_east_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusNorthWest", setup_northwest_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusNorthEast", setup_northeast_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusSouthWest", setup_southwest_cycle_func,
+                       free_func, run_func);
+    actions_register_i("DirectionalFocusSouthEast", setup_southeast_cycle_func,
+                       free_func, run_func);
+    actions_register("DirectionalTargetNorth", setup_north_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetSouth", setup_south_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetWest", setup_west_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetEast", setup_east_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetNorthWest", setup_northwest_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetNorthEast", setup_northeast_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetSouthWest", setup_southwest_target_func,
+                     free_func, run_func);
+    actions_register("DirectionalTargetSouthEast", setup_southeast_target_func,
+                     free_func, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -52,18 +137,18 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o->dialog = TRUE;
     o->bar = TRUE;
 
-    if ((n = parse_find_node("dialog", node)))
-        o->dialog = parse_bool(doc, n);
-    if ((n = parse_find_node("bar", node)))
-        o->bar = parse_bool(doc, n);
-    if ((n = parse_find_node("raise", node)))
-        o->raise = parse_bool(doc, n);
-    if ((n = parse_find_node("panels", node)))
-        o->dock_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("desktop", node)))
-        o->desktop_windows = parse_bool(doc, n);
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "dialog")))
+        o->dialog = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "bar")))
+        o->bar = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "raise")))
+        o->raise = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "panels")))
+        o->dock_windows = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "desktop")))
+        o->desktop_windows = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "direction"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "north") ||
             !g_ascii_strcasecmp(s, "up"))
             o->direction = OB_DIRECTION_NORTH;
@@ -87,14 +172,14 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
         g_free(s);
     }
 
-    if ((n = parse_find_node("finalactions", node))) {
+    if ((n = obt_xml_find_node(node, "finalactions"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_xml_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->actions = g_slist_append(o->actions, action);
-            m = parse_find_node("action", m->next);
+            m = obt_xml_find_node(m->next, "action");
         }
     }
     else {
@@ -109,18 +194,22 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_cycle_func(ObParseInst *i, xmlDocPtr doc,
-                                 xmlNodePtr node)
+static gpointer setup_cycle_func(xmlNodePtr node,
+                                 ObActionsIPreFunc *pre,
+                                 ObActionsIInputFunc *input,
+                                 ObActionsICancelFunc *cancel,
+                                 ObActionsIPostFunc *post)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->interactive = TRUE;
+    *input = i_input_func;
+    *cancel = i_cancel_func;
     return o;
 }
 
-static gpointer setup_target_func(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node)
+static gpointer setup_target_func(xmlNodePtr node)
 {
-    Options *o = setup_func(i, doc, node);
+    Options *o = setup_func(node);
     o->interactive = FALSE;
     return o;
 }
@@ -220,3 +309,149 @@ static void end_cycle(gboolean cancel, guint state, Options *o)
 
     stacking_restore();
 }
+
+/* 3.4-compatibility */
+static gpointer setup_north_cycle_func(xmlNodePtr node,
+                                       ObActionsIPreFunc *pre,
+                                       ObActionsIInputFunc *input,
+                                       ObActionsICancelFunc *cancel,
+                                       ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_NORTH;
+    return o;
+}
+
+static gpointer setup_south_cycle_func(xmlNodePtr node,
+                                       ObActionsIPreFunc *pre,
+                                       ObActionsIInputFunc *input,
+                                       ObActionsICancelFunc *cancel,
+                                       ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_SOUTH;
+    return o;
+}
+
+static gpointer setup_east_cycle_func(xmlNodePtr node,
+                                      ObActionsIPreFunc *pre,
+                                      ObActionsIInputFunc *input,
+                                      ObActionsICancelFunc *cancel,
+                                      ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_EAST;
+    return o;
+}
+
+static gpointer setup_west_cycle_func(xmlNodePtr node,
+                                      ObActionsIPreFunc *pre,
+                                      ObActionsIInputFunc *input,
+                                      ObActionsICancelFunc *cancel,
+                                      ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_WEST;
+    return o;
+}
+
+static gpointer setup_northwest_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *input,
+                                           ObActionsICancelFunc *cancel,
+                                           ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_NORTHWEST;
+    return o;
+}
+
+static gpointer setup_northeast_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *input,
+                                           ObActionsICancelFunc *cancel,
+                                           ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_EAST;
+    return o;
+}
+
+static gpointer setup_southwest_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *input,
+                                           ObActionsICancelFunc *cancel,
+                                           ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_SOUTHWEST;
+    return o;
+}
+
+static gpointer setup_southeast_cycle_func(xmlNodePtr node,
+                                           ObActionsIPreFunc *pre,
+                                           ObActionsIInputFunc *input,
+                                           ObActionsICancelFunc *cancel,
+                                           ObActionsIPostFunc *post)
+{
+    Options *o = setup_cycle_func(node, pre, input, cancel, post);
+    o->direction = OB_DIRECTION_SOUTHEAST;
+    return o;
+}
+
+static gpointer setup_north_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_NORTH;
+    return o;
+}
+
+static gpointer setup_south_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_SOUTH;
+    return o;
+}
+
+static gpointer setup_east_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_EAST;
+    return o;
+}
+
+static gpointer setup_west_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_WEST;
+    return o;
+}
+
+static gpointer setup_northwest_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_NORTHWEST;
+    return o;
+}
+
+static gpointer setup_northeast_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_NORTHEAST;
+    return o;
+}
+
+static gpointer setup_southwest_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_SOUTHWEST;
+    return o;
+}
+
+static gpointer setup_southeast_target_func(xmlNodePtr node)
+{
+    Options *o = setup_target_func(node);
+    o->direction = OB_DIRECTION_SOUTHEAST;
+    return o;
+}
+
index 5e5382d..4a750b2 100644 (file)
@@ -8,8 +8,7 @@ void action_dockautohide_startup(void)
 {
     actions_register("ToggleDockAutoHide",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
index cb3ab24..0e9e738 100644 (file)
@@ -1,8 +1,10 @@
 #include "openbox/actions.h"
 #include "openbox/event.h"
 #include "openbox/startupnotify.h"
+#include "openbox/client.h"
 #include "openbox/prompt.h"
 #include "openbox/screen.h"
+#include "obt/paths.h"
 #include "gettext.h"
 
 #ifdef HAVE_STDLIB_H
@@ -18,7 +20,7 @@ typedef struct {
     gchar   *prompt;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 /*
@@ -31,41 +33,37 @@ static void     i_cancel_func(gpointer options);
 
 void action_execute_startup(void)
 {
-    actions_register("Execute",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Execute", setup_func, free_func, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("command", node)) ||
-        (n = parse_find_node("execute", node)))
+    if ((n = obt_xml_find_node(node, "command")) ||
+        (n = obt_xml_find_node(node, "execute")))
     {
-        gchar *s = parse_string(doc, n);
-        o->cmd = parse_expand_tilde(s);
+        gchar *s = obt_xml_node_string(n);
+        o->cmd = obt_paths_expand_tilde(s);
         g_free(s);
     }
 
-    if ((n = parse_find_node("prompt", node)))
-        o->prompt = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "prompt")))
+        o->prompt = obt_xml_node_string(n);
 
-    if ((n = parse_find_node("startupnotify", node))) {
+    if ((n = obt_xml_find_node(node, "startupnotify"))) {
         xmlNodePtr m;
-        if ((m = parse_find_node("enabled", n->xmlChildrenNode)))
-            o->sn = parse_bool(doc, m);
-        if ((m = parse_find_node("name", n->xmlChildrenNode)))
-            o->sn_name = parse_string(doc, m);
-        if ((m = parse_find_node("icon", n->xmlChildrenNode)))
-            o->sn_icon = parse_string(doc, m);
-        if ((m = parse_find_node("wmclass", n->xmlChildrenNode)))
-            o->sn_wmclass = parse_string(doc, m);
+        if ((m = obt_xml_find_node(n->children, "enabled")))
+            o->sn = obt_xml_node_bool(m);
+        if ((m = obt_xml_find_node(n->children, "name")))
+            o->sn_name = obt_xml_node_string(m);
+        if ((m = obt_xml_find_node(n->children, "icon")))
+            o->sn_icon = obt_xml_node_string(m);
+        if ((m = obt_xml_find_node(n->children, "wmclass")))
+            o->sn_wmclass = obt_xml_node_string(m);
     }
     return o;
 }
@@ -114,7 +112,7 @@ static void prompt_cleanup(ObPrompt *p, gpointer options)
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
-    GError *e = NULL;
+    GError *e;
     gchar **argv = NULL;
     gchar *cmd;
     Options *o = options;
@@ -143,16 +141,82 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         return FALSE;
     }
 
+    if (data->client) {
+        gchar *c, *before, *expand;
+
+        /* replace occurrences of $pid and $wid */
+
+        expand = NULL;
+        before = cmd;
+
+        while ((c = strchr(before, '$'))) {
+            if ((c[1] == 'p' || c[1] == 'P') &&
+                (c[2] == 'i' || c[2] == 'I') &&
+                (c[3] == 'd' || c[3] == 'D') &&
+                !g_ascii_isalnum(c[4]))
+            {
+                /* found $pid */
+                gchar *tmp;
+
+                *c = '\0';
+                tmp = expand;
+                expand = g_strdup_printf("%s%s%u",
+                                         (expand ? expand : ""),
+                                         before,
+                                         data->client->pid);
+                g_free(tmp);
+
+                before = c + 4; /* 4 = strlen("$pid") */
+            }
+            else if ((c[1] == 'w' || c[1] == 'W') &&
+                     (c[2] == 'i' || c[2] == 'I') &&
+                     (c[3] == 'd' || c[3] == 'D') &&
+                     !g_ascii_isalnum(c[4]))
+            {
+                /* found $wid */
+                gchar *tmp;
+
+                *c = '\0';
+                tmp = expand;
+                expand = g_strdup_printf("%s%s%lu",
+                                         (expand ? expand : ""),
+                                         before,
+                                         data->client->window);
+                g_free(tmp);
+
+                before = c + 4; /* 4 = strlen("$wid") */
+            }
+            else
+                before = c + 1; /* no infinite loops plz */
+        }
+
+        if (expand) {
+            gchar *tmp;
+
+            /* add on the end of the string after the last replacement */
+            tmp = expand;
+            expand = g_strconcat(expand, before, NULL);
+            g_free(tmp);
+
+            /* replace the command with the expanded one */
+            g_free(cmd);
+            cmd = expand;
+        }
+    }
+
     /* If there is a keyboard grab going on then we need to cancel
        it so the application can grab things */
-    event_cancel_all_key_grabs();
+    if (data->uact != OB_USER_ACTION_MENU_SELECTION)
+        event_cancel_all_key_grabs();
 
+    e = NULL;
     if (!g_shell_parse_argv(cmd, NULL, &argv, &e)) {
         g_message(e->message, o->cmd);
         g_error_free(e);
     }
     else {
         gchar *program = NULL;
+        gboolean ok;
 
         if (o->sn) {
             program = g_path_get_basename(argv[0]);
@@ -163,18 +227,20 @@ static gboolean run_func(ObActionsData *data, gpointer options)
                                        screen_desktop);
         }
 
-        if (!g_spawn_async(NULL, argv, NULL,
-                           G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
-                           NULL, NULL, NULL, &e))
-        {
+        e = NULL;
+        ok = g_spawn_async(NULL, argv, NULL,
+                           G_SPAWN_SEARCH_PATH |
+                           G_SPAWN_DO_NOT_REAP_CHILD,
+                           NULL, NULL, NULL, &e);
+        if (!ok) {
             g_message(e->message, o->cmd);
             g_error_free(e);
-
-            if (o->sn)
-                sn_spawn_cancel();
         }
-        if (o->sn)
+
+        if (o->sn) {
+            if (!ok) sn_spawn_cancel();
             unsetenv("DESKTOP_STARTUP_ID");
+        }
 
         g_free(program);
         g_strfreev(argv);
index 567926e..f2b0caf 100644 (file)
@@ -8,16 +8,16 @@ typedef struct {
     gboolean prompt;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_exit_startup(void)
 {
-    actions_register("Exit", setup_func, NULL, run_func, NULL, NULL);
-    actions_register("SessionLogout", setup_func, NULL, run_func, NULL, NULL);
+    actions_register("Exit", setup_func, NULL, run_func);
+    actions_register("SessionLogout", setup_func, NULL, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -25,8 +25,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o = g_new0(Options, 1);
     o->prompt = TRUE;
 
-    if ((n = parse_find_node("prompt", node)))
-        o->prompt = parse_bool(doc, n);
+    if ((n = obt_xml_find_node(node, "prompt")))
+        o->prompt = obt_xml_node_bool(n);
 
     return o;
 }
index 1b54491..8bae49c 100644 (file)
@@ -9,20 +9,15 @@ typedef struct {
     gboolean stop_int;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_focus_startup(void)
 {
-    actions_register("Focus",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Focus", setup_func, g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -30,20 +25,13 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o = g_new0(Options, 1);
     o->stop_int = TRUE;
 
-    if ((n = parse_find_node("here", node)))
-        o->here = parse_bool(doc, n);
-    if ((n = parse_find_node("stopInteractive", node)))
-        o->stop_int = parse_bool(doc, n);
+    if ((n = obt_xml_find_node(node, "here")))
+        o->here = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "stopInteractive")))
+        o->stop_int = obt_xml_node_bool(n);
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 49c945b..a3e5b5a 100644 (file)
@@ -5,7 +5,7 @@ static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_focustobottom_startup(void)
 {
-    actions_register("FocusToBottom", NULL, NULL, run_func, NULL, NULL);
+    actions_register("FocusToBottom", NULL, NULL, run_func);
 }
 
 /* Always return FALSE because its not interactive */
index 7579b95..e1fdf23 100644 (file)
@@ -5,8 +5,7 @@ static gboolean run_func_toggle(ObActionsData *data, gpointer options);
 
 void action_fullscreen_startup(void)
 {
-    actions_register("ToggleFullscreen", NULL, NULL, run_func_toggle,
-                     NULL, NULL);
+    actions_register("ToggleFullscreen", NULL, NULL, run_func_toggle);
 }
 
 /* Always return FALSE because its not interactive */
index 69b8ef7..9589d3f 100644 (file)
@@ -7,31 +7,42 @@
 
 typedef struct {
     ObDirection dir;
+    gboolean shrink;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_shrink_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
+/* 3.4-compatibility */
+static gpointer setup_north_func(xmlNodePtr node);
+static gpointer setup_south_func(xmlNodePtr node);
+static gpointer setup_east_func(xmlNodePtr node);
+static gpointer setup_west_func(xmlNodePtr node);
 
 void action_growtoedge_startup(void)
 {
-    actions_register("GrowToEdge",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("GrowToEdge", setup_func,
+                     g_free, run_func);
+    actions_register("ShrinkToEdge", setup_shrink_func,
+                     g_free, run_func);
+    /* 3.4-compatibility */
+    actions_register("GrowToEdgeNorth", setup_north_func, g_free, run_func);
+    actions_register("GrowToEdgeSouth", setup_south_func, g_free, run_func);
+    actions_register("GrowToEdgeEast", setup_east_func, g_free, run_func);
+    actions_register("GrowToEdgeWest", setup_west_func, g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
     o->dir = OB_DIRECTION_NORTH;
+    o->shrink = FALSE;
 
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "direction"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "north") ||
             !g_ascii_strcasecmp(s, "up"))
             o->dir = OB_DIRECTION_NORTH;
@@ -50,11 +61,14 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
+static gpointer setup_shrink_func(xmlNodePtr node)
 {
-    Options *o = options;
+    Options *o;
 
-    g_free(o);
+    o = setup_func(node);
+    o->shrink = TRUE;
+
+    return o;
 }
 
 static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
@@ -98,11 +112,13 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         return FALSE;
     }
 
-    /* try grow */
-    client_find_resize_directional(data->client, o->dir, TRUE,
-                                   &x, &y, &w, &h);
-    if (do_grow(data, x, y, w, h))
-        return FALSE;
+    if (!o->shrink) {
+        /* try grow */
+        client_find_resize_directional(data->client, o->dir, TRUE,
+                                       &x, &y, &w, &h);
+        if (do_grow(data, x, y, w, h))
+            return FALSE;
+    }
 
     /* we couldn't grow, so try shrink! */
     opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
@@ -143,3 +159,36 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     return FALSE;
 }
+
+/* 3.4-compatibility */
+static gpointer setup_north_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->shrink = FALSE;
+    o->dir = OB_DIRECTION_NORTH;
+    return o;
+}
+
+static gpointer setup_south_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->shrink = FALSE;
+    o->dir = OB_DIRECTION_SOUTH;
+    return o;
+}
+
+static gpointer setup_east_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->shrink = FALSE;
+    o->dir = OB_DIRECTION_EAST;
+    return o;
+}
+
+static gpointer setup_west_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->shrink = FALSE;
+    o->dir = OB_DIRECTION_WEST;
+    return o;
+}
index 6f14a2e..e6bdbb7 100644 (file)
@@ -7,8 +7,7 @@ void action_iconify_startup(void)
 {
     actions_register("Iconify",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
index 4c98966..dd86086 100644 (file)
@@ -23,81 +23,77 @@ typedef struct {
     GSList *elseacts;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_if_startup(void)
 {
-    actions_register("If",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("If", setup_func, free_func, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("shaded", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_xml_find_node(node, "shaded"))) {
+        if (obt_xml_node_bool(n))
             o->shaded_on = TRUE;
         else
             o->shaded_off = TRUE;
     }
-    if ((n = parse_find_node("maximized", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_xml_find_node(node, "maximized"))) {
+        if (obt_xml_node_bool(n))
             o->maxfull_on = TRUE;
         else
             o->maxfull_off = TRUE;
     }
-    if ((n = parse_find_node("maximizedhorizontal", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_xml_find_node(node, "maximizedhorizontal"))) {
+        if (obt_xml_node_bool(n))
             o->maxhorz_on = TRUE;
         else
             o->maxhorz_off = TRUE;
     }
-    if ((n = parse_find_node("maximizedvertical", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_xml_find_node(node, "maximizedvertical"))) {
+        if (obt_xml_node_bool(n))
             o->maxvert_on = TRUE;
         else
             o->maxvert_off = TRUE;
     }
-    if ((n = parse_find_node("iconified", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_xml_find_node(node, "iconified"))) {
+        if (obt_xml_node_bool(n))
             o->iconic_on = TRUE;
         else
             o->iconic_off = TRUE;
     }
-    if ((n = parse_find_node("focused", node))) {
-        if (parse_bool(doc, n))
+    if ((n = obt_xml_find_node(node, "focused"))) {
+        if (obt_xml_node_bool(n))
             o->focused = TRUE;
         else
             o->unfocused = TRUE;
     }
 
-    if ((n = parse_find_node("then", node))) {
+    if ((n = obt_xml_find_node(node, "then"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_xml_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->thenacts = g_slist_append(o->thenacts, action);
-            m = parse_find_node("action", m->next);
+            m = obt_xml_find_node(m->next, "action");
         }
     }
-    if ((n = parse_find_node("else", node))) {
+    if ((n = obt_xml_find_node(node, "else"))) {
         xmlNodePtr m;
 
-        m = parse_find_node("action", n->xmlChildrenNode);
+        m = obt_xml_find_node(n->children, "action");
         while (m) {
-            ObActionsAct *action = actions_parse(i, doc, m);
+            ObActionsAct *action = actions_parse(m);
             if (action) o->elseacts = g_slist_append(o->elseacts, action);
-            m = parse_find_node("action", m->next);
+            m = obt_xml_find_node(m->next, "action");
         }
     }
 
@@ -108,6 +104,15 @@ static void free_func(gpointer options)
 {
     Options *o = options;
 
+    while (o->thenacts) {
+        actions_act_unref(o->thenacts->data);
+        o->thenacts = g_slist_delete_link(o->thenacts, o->thenacts);
+    }
+    while (o->elseacts) {
+        actions_act_unref(o->elseacts->data);
+        o->elseacts = g_slist_delete_link(o->elseacts, o->elseacts);
+    }
+
     g_free(o);
 }
 
index 6824440..b7d547b 100644 (file)
@@ -7,8 +7,7 @@ void action_kill_startup(void)
 {
     actions_register("Kill",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
index 92fa480..2b4d325 100644 (file)
@@ -6,24 +6,33 @@ typedef struct {
     gboolean toggle;
 } Options;
 
-static gpointer setup_func_top(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static gpointer setup_func_bottom(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node);
-static gpointer setup_func_send(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node);
+static gpointer setup_func_top(xmlNodePtr node);
+static gpointer setup_func_bottom(xmlNodePtr node);
+static gpointer setup_func_send(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
+/* 3.4-compatibility */
+static gpointer setup_sendtop_func(xmlNodePtr node);
+static gpointer setup_sendbottom_func(xmlNodePtr node);
+static gpointer setup_sendnormal_func(xmlNodePtr node);
 
 void action_layer_startup(void)
 {
     actions_register("ToggleAlwaysOnTop", setup_func_top, g_free,
-                     run_func, NULL, NULL);
+                     run_func);
     actions_register("ToggleAlwaysOnBottom", setup_func_bottom, g_free,
-                     run_func, NULL, NULL);
+                     run_func);
     actions_register("SendToLayer", setup_func_send, g_free,
-                     run_func, NULL, NULL);
+                     run_func);
+    /* 3.4-compatibility */
+    actions_register("SendToTopLayer", setup_sendtop_func, g_free,
+                     run_func);
+    actions_register("SendToBottomLayer", setup_sendbottom_func, g_free,
+                     run_func);
+    actions_register("SendToNormalLayer", setup_sendnormal_func, g_free,
+                     run_func);
 }
 
-static gpointer setup_func_top(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func_top(xmlNodePtr node)
 {
     Options *o = g_new0(Options, 1);
     o->layer = 1;
@@ -31,8 +40,7 @@ static gpointer setup_func_top(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static gpointer setup_func_bottom(ObParseInst *i, xmlDocPtr doc,
-                                  xmlNodePtr node)
+static gpointer setup_func_bottom(xmlNodePtr node)
 {
     Options *o = g_new0(Options, 1);
     o->layer = -1;
@@ -40,16 +48,15 @@ static gpointer setup_func_bottom(ObParseInst *i, xmlDocPtr doc,
     return o;
 }
 
-static gpointer setup_func_send(ObParseInst *i, xmlDocPtr doc,
-                                xmlNodePtr node)
+static gpointer setup_func_send(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("layer", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "layer"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "above") ||
             !g_ascii_strcasecmp(s, "top"))
             o->layer = 1;
@@ -91,3 +98,29 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     return FALSE;
 }
+
+/* 3.4-compatibility */
+static gpointer setup_sendtop_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->layer = 1;
+    o->toggle = FALSE;
+    return o;
+}
+
+static gpointer setup_sendbottom_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->layer = -1;
+    o->toggle = FALSE;
+    return o;
+}
+
+static gpointer setup_sendnormal_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->layer = 0;
+    o->toggle = FALSE;
+    return o;
+}
+
index d34e933..80ca6b8 100644 (file)
@@ -8,8 +8,7 @@ void action_lower_startup(void)
 {
     actions_register("Lower",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
index bb6f470..4c61507 100644 (file)
@@ -12,22 +12,42 @@ typedef struct {
     MaxDirection dir;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func_on(ObActionsData *data, gpointer options);
 static gboolean run_func_off(ObActionsData *data, gpointer options);
 static gboolean run_func_toggle(ObActionsData *data, gpointer options);
+/* 3.4-compatibility */
+static gpointer setup_both_func(xmlNodePtr node);
+static gpointer setup_horz_func(xmlNodePtr node);
+static gpointer setup_vert_func(xmlNodePtr node);
 
 void action_maximize_startup(void)
 {
-    actions_register("Maximize", setup_func, g_free, run_func_on,
-                     NULL, NULL);
-    actions_register("Unmaximize", setup_func, g_free, run_func_off,
-                     NULL, NULL);
-    actions_register("ToggleMaximize", setup_func, g_free, run_func_toggle,
-                     NULL, NULL);
+    actions_register("Maximize", setup_func, g_free, run_func_on);
+    actions_register("Unmaximize", setup_func, g_free, run_func_off);
+    actions_register("ToggleMaximize", setup_func, g_free, run_func_toggle);
+    /* 3.4-compatibility */
+    actions_register("MaximizeFull", setup_both_func, g_free,
+                     run_func_on);
+    actions_register("UnmaximizeFull", setup_both_func, g_free,
+                     run_func_off);
+    actions_register("ToggleMaximizeFull", setup_both_func, g_free,
+                     run_func_toggle);
+    actions_register("MaximizeHorz", setup_horz_func, g_free,
+                     run_func_on);
+    actions_register("UnmaximizeHorz", setup_horz_func, g_free,
+                     run_func_off);
+    actions_register("ToggleMaximizeHorz", setup_horz_func, g_free,
+                     run_func_toggle);
+    actions_register("MaximizeVert", setup_vert_func, g_free,
+                     run_func_on);
+    actions_register("UnmaximizeVert", setup_vert_func, g_free,
+                     run_func_off);
+    actions_register("ToggleMaximizeVert", setup_vert_func, g_free,
+                     run_func_toggle);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -35,8 +55,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o = g_new0(Options, 1);
     o->dir = BOTH;
 
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "direction"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "vertical") ||
             !g_ascii_strcasecmp(s, "vert"))
             o->dir = VERT;
@@ -89,3 +109,26 @@ static gboolean run_func_toggle(ObActionsData *data, gpointer options)
     }
     return FALSE;
 }
+
+/* 3.4-compatibility */
+static gpointer setup_both_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = BOTH;
+    return o;
+}
+
+static gpointer setup_horz_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = HORZ;
+    return o;
+}
+
+static gpointer setup_vert_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = VERT;
+    return o;
+}
+
index 1a8ea20..ba8372a 100644 (file)
@@ -1,6 +1,6 @@
 #include "openbox/actions.h"
-#include "openbox/prop.h"
 #include "openbox/moveresize.h"
+#include "obt/prop.h"
 
 static gboolean run_func(ObActionsData *data, gpointer options);
 
@@ -8,8 +8,7 @@ void action_move_startup(void)
 {
     actions_register("Move",
                      NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+                     run_func);
 }
 
 /* Always return FALSE because its not interactive */
@@ -19,8 +18,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         guint32 corner;
 
         corner = data->button != 0 ?
-            prop_atoms.net_wm_moveresize_move :
-            prop_atoms.net_wm_moveresize_move_keyboard;
+            OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) :
+            OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD);
 
         moveresize_start(data->client, data->x, data->y, data->button, corner);
     }
index 1d1189c..ff9f719 100644 (file)
@@ -9,41 +9,29 @@ typedef struct {
     gint y;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_moverelative_startup(void)
 {
-    actions_register("MoveRelative",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("MoveRelative", setup_func, g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("x", node)))
-        o->x = parse_int(doc, n);
-    if ((n = parse_find_node("y", node)))
-        o->y = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "x")))
+        o->x = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "y")))
+        o->y = obt_xml_node_int(n);
 
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
@@ -54,15 +42,15 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         gint x, y, lw, lh, w, h;
 
         c = data->client;
-        x = data->client->area.x + o->x;
-        y = data->client->area.y + o->y;
-        w = data->client->area.width;
-        h = data->client->area.height;
-        client_try_configure(data->client, &x, &y, &w, &h, &lw, &lh, TRUE);
-        client_find_onscreen(data->client, &x, &y, w, h, FALSE);
+        x = c->area.x + o->x;
+        y = c->area.y + o->y;
+        w = c->area.width;
+        h = c->area.height;
+        client_try_configure(c, &x, &y, &w, &h, &lw, &lh, TRUE);
+        client_find_onscreen(c, &x, &y, w, h, FALSE);
 
         actions_client_move(data, TRUE);
-        client_configure(data->client, x, y, w, h, TRUE, TRUE, FALSE);
+        client_configure(c, x, y, w, h, TRUE, TRUE, FALSE);
         actions_client_move(data, FALSE);
     }
 
index 29780c4..f047279 100644 (file)
@@ -23,23 +23,22 @@ typedef struct {
     gint monitor;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
+/* 3.4-compatibility */
+static gpointer setup_center_func(xmlNodePtr node);
 
 void action_moveresizeto_startup(void)
 {
-    actions_register("MoveResizeTo",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("MoveResizeTo", setup_func, g_free, run_func);
+    /* 3.4-compatibility */
+    actions_register("MoveToCenter", setup_center_func, g_free, run_func);
 }
 
-static void parse_coord(xmlDocPtr doc, xmlNodePtr n, gint *pos,
+static void parse_coord(xmlNodePtr n, gint *pos,
                         gboolean *opposite, gboolean *center)
 {
-    gchar *s = parse_string(doc, n);
+    gchar *s = obt_xml_node_string(n);
     if (g_ascii_strcasecmp(s, "current") != 0) {
         if (!g_ascii_strcasecmp(s, "center"))
             *center = TRUE;
@@ -55,7 +54,7 @@ static void parse_coord(xmlDocPtr doc, xmlNodePtr n, gint *pos,
     g_free(s);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -67,27 +66,27 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o->h = G_MININT;
     o->monitor = CURRENT_MONITOR;
 
-    if ((n = parse_find_node("x", node)))
-        parse_coord(doc, n, &o->x, &o->xopposite, &o->xcenter);
+    if ((n = obt_xml_find_node(node, "x")))
+        parse_coord(n, &o->x, &o->xopposite, &o->xcenter);
 
-    if ((n = parse_find_node("y", node)))
-        parse_coord(doc, n, &o->y, &o->yopposite, &o->ycenter);
+    if ((n = obt_xml_find_node(node, "y")))
+        parse_coord(n, &o->y, &o->yopposite, &o->ycenter);
 
-    if ((n = parse_find_node("width", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "width"))) {
+        gchar *s = obt_xml_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0)
-            o->w = parse_int(doc, n);
+            o->w = obt_xml_node_int(n);
         g_free(s);
     }
-    if ((n = parse_find_node("height", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "height"))) {
+        gchar *s = obt_xml_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0)
-            o->h = parse_int(doc, n);
+            o->h = obt_xml_node_int(n);
         g_free(s);
     }
 
-    if ((n = parse_find_node("monitor", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "monitor"))) {
+        gchar *s = obt_xml_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0) {
             if (!g_ascii_strcasecmp(s, "all"))
                 o->monitor = ALL_MONITORS;
@@ -96,7 +95,7 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
             else if(!g_ascii_strcasecmp(s, "prev"))
                 o->monitor = PREV_MONITOR;
             else
-                o->monitor = parse_int(doc, n) - 1;
+                o->monitor = obt_xml_node_int(n) - 1;
         }
         g_free(s);
     }
@@ -104,13 +103,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
@@ -188,3 +180,19 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     return FALSE;
 }
+
+/* 3.4-compatibility */
+static gpointer setup_center_func(xmlNodePtr node)
+{
+    Options *o;
+
+    o = g_new0(Options, 1);
+    o->x = G_MININT;
+    o->y = G_MININT;
+    o->w = G_MININT;
+    o->h = G_MININT;
+    o->monitor = -1;
+    o->xcenter = TRUE;
+    o->ycenter = TRUE;
+    return o;
+}
index 5941bde..f81ded4 100644 (file)
@@ -9,20 +9,25 @@ typedef struct {
     ObDirection dir;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
+/* 3.4-compatibility */
+static gpointer setup_north_func(xmlNodePtr node);
+static gpointer setup_south_func(xmlNodePtr node);
+static gpointer setup_east_func(xmlNodePtr node);
+static gpointer setup_west_func(xmlNodePtr node);
 
 void action_movetoedge_startup(void)
 {
-    actions_register("MoveToEdge",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("MoveToEdge", setup_func, g_free, run_func);
+    /* 3.4-compatibility */
+    actions_register("MoveToEdgeNorth", setup_north_func, g_free, run_func);
+    actions_register("MoveToEdgeSouth", setup_south_func, g_free, run_func);
+    actions_register("MoveToEdgeEast", setup_east_func, g_free, run_func);
+    actions_register("MoveToEdgeWest", setup_west_func, g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
@@ -30,8 +35,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     o = g_new0(Options, 1);
     o->dir = OB_DIRECTION_NORTH;
 
-    if ((n = parse_find_node("direction", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "direction"))) {
+        gchar *s = obt_xml_node_string(n);
         if (!g_ascii_strcasecmp(s, "north") ||
             !g_ascii_strcasecmp(s, "up"))
             o->dir = OB_DIRECTION_NORTH;
@@ -50,13 +55,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
@@ -75,3 +73,33 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     return FALSE;
 }
+
+/* 3.4-compatibility */
+static gpointer setup_north_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = OB_DIRECTION_NORTH;
+    return o;
+}
+
+static gpointer setup_south_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = OB_DIRECTION_SOUTH;
+    return o;
+}
+
+static gpointer setup_east_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = OB_DIRECTION_EAST;
+    return o;
+}
+
+static gpointer setup_west_func(xmlNodePtr node)
+{
+    Options *o = g_new0(Options, 1);
+    o->dir = OB_DIRECTION_WEST;
+    return o;
+}
+
index 030a015..4309acc 100644 (file)
@@ -6,8 +6,7 @@ static gboolean run_func_toggle(ObActionsData *data, gpointer options);
 
 void action_omnipresent_startup(void)
 {
-    actions_register("ToggleOmnipresent", NULL, NULL, run_func_toggle,
-                     NULL, NULL);
+    actions_register("ToggleOmnipresent", NULL, NULL, run_func_toggle);
 }
 
 /* Always return FALSE because its not interactive */
index 6837bce..f6ac145 100644 (file)
@@ -6,10 +6,7 @@ static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_raise_startup(void)
 {
-    actions_register("Raise",
-                     NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Raise", NULL, NULL, run_func);
 }
 
 /* Always return FALSE because its not interactive */
index 80fc917..dbe41d8 100644 (file)
@@ -5,10 +5,7 @@ static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_raiselower_startup(void)
 {
-    actions_register("RaiseLower",
-                     NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+    actions_register("RaiseLower", NULL, NULL, run_func);
 }
 
 /* Always return FALSE because its not interactive */
index cef8141..813a122 100644 (file)
@@ -5,10 +5,7 @@ static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_reconfigure_startup(void)
 {
-    actions_register("Reconfigure",
-                     NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Reconfigure", NULL, NULL, run_func);
 }
 
 /* Always return FALSE because its not interactive */
index 3714e38..fbcdf24 100644 (file)
@@ -1,16 +1,15 @@
 #include "openbox/actions.h"
-#include "openbox/prop.h"
 #include "openbox/moveresize.h"
 #include "openbox/client.h"
 #include "openbox/frame.h"
+#include "obt/prop.h"
 
 typedef struct {
     gboolean corner_specified;
     guint32 corner;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
@@ -18,40 +17,36 @@ static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
 
 void action_resize_startup(void)
 {
-    actions_register("Resize",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Resize", setup_func, g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("edge", node))) {
-        gchar *s = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "edge"))) {
+        gchar *s = obt_xml_node_string(n);
 
         o->corner_specified = TRUE;
         if (!g_ascii_strcasecmp(s, "top"))
-            o->corner = prop_atoms.net_wm_moveresize_size_top;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP);
         else if (!g_ascii_strcasecmp(s, "bottom"))
-            o->corner = prop_atoms.net_wm_moveresize_size_bottom;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM);
         else if (!g_ascii_strcasecmp(s, "left"))
-            o->corner = prop_atoms.net_wm_moveresize_size_left;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
         else if (!g_ascii_strcasecmp(s, "right"))
-            o->corner = prop_atoms.net_wm_moveresize_size_right;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
         else if (!g_ascii_strcasecmp(s, "topleft"))
-            o->corner = prop_atoms.net_wm_moveresize_size_topleft;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT);
         else if (!g_ascii_strcasecmp(s, "topright"))
-            o->corner = prop_atoms.net_wm_moveresize_size_topright;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
         else if (!g_ascii_strcasecmp(s, "bottomleft"))
-            o->corner = prop_atoms.net_wm_moveresize_size_bottomleft;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
         else if (!g_ascii_strcasecmp(s, "bottomright"))
-            o->corner = prop_atoms.net_wm_moveresize_size_bottomright;
+            o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
         else
             o->corner_specified = FALSE;
 
@@ -60,13 +55,6 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
@@ -77,7 +65,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         guint32 corner;
 
         if (!data->button)
-            corner = prop_atoms.net_wm_moveresize_size_keyboard;
+            corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD);
         else if (o->corner_specified)
             corner = o->corner; /* it was specified in the binding */
         else
@@ -163,30 +151,30 @@ static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
     if (shaded) {
         /* for shaded windows, you can only resize west/east and move */
         if (b)
-            return prop_atoms.net_wm_moveresize_size_left;
+            return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
         if (c)
-            return prop_atoms.net_wm_moveresize_size_right;
-        return prop_atoms.net_wm_moveresize_move;
+            return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
     }
 
     if (y < A && y >= C)
-        return prop_atoms.net_wm_moveresize_size_topleft;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT);
     else if (y >= A && y >= B && a)
-        return prop_atoms.net_wm_moveresize_size_top;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP);
     else if (y < B && y >= D)
-        return prop_atoms.net_wm_moveresize_size_topright;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
     else if (y < C && y >= E && b)
-        return prop_atoms.net_wm_moveresize_size_left;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
     else if (y < D && y >= F && c)
-        return prop_atoms.net_wm_moveresize_size_right;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
     else if (y < E && y >= G)
-        return prop_atoms.net_wm_moveresize_size_bottomleft;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
     else if (y < G && y < H && d)
-        return prop_atoms.net_wm_moveresize_size_bottom;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM);
     else if (y >= H && y < F)
-        return prop_atoms.net_wm_moveresize_size_bottomright;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
     else
-        return prop_atoms.net_wm_moveresize_move;
+        return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
 
 #undef X
 #undef A
index f705c29..c5fc1ea 100644 (file)
@@ -11,47 +11,35 @@ typedef struct {
     gint bottom;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
-static void     free_func(gpointer options);
+static gpointer setup_func(xmlNodePtr node);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_resizerelative_startup(void)
 {
-    actions_register("ResizeRelative",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("ResizeRelative", setup_func, g_free, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("left", node)))
-        o->left = parse_int(doc, n);
-    if ((n = parse_find_node("right", node)))
-        o->right = parse_int(doc, n);
-    if ((n = parse_find_node("top", node)) ||
-        (n = parse_find_node("up", node)))
-        o->top = parse_int(doc, n);
-    if ((n = parse_find_node("bottom", node)) ||
-        (n = parse_find_node("down", node)))
-        o->bottom = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "left")))
+        o->left = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "right")))
+        o->right = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "top")) ||
+        (n = obt_xml_find_node(node, "up")))
+        o->top = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "bottom")) ||
+        (n = obt_xml_find_node(node, "down")))
+        o->bottom = obt_xml_node_int(n);
 
     return o;
 }
 
-static void free_func(gpointer options)
-{
-    Options *o = options;
-
-    g_free(o);
-}
-
 /* Always return FALSE because its not interactive */
 static gboolean run_func(ObActionsData *data, gpointer options)
 {
index 4b52f9d..7d1689c 100644 (file)
@@ -1,35 +1,32 @@
 #include "openbox/actions.h"
 #include "openbox/openbox.h"
+#include "obt/paths.h"
 
 typedef struct {
     gchar   *cmd;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_restart_startup(void)
 {
-    actions_register("Restart",
-                     setup_func,
-                     free_func,
-                     run_func,
-                     NULL, NULL);
+    actions_register("Restart", setup_func, free_func, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("command", node)) ||
-        (n = parse_find_node("execute", node)))
+    if ((n = obt_xml_find_node(node, "command")) ||
+        (n = obt_xml_find_node(node, "execute")))
     {
-        gchar *s = parse_string(doc, n);
-        o->cmd = parse_expand_tilde(s);
+        gchar *s = obt_xml_node_string(n);
+        o->cmd = obt_paths_expand_tilde(s);
         g_free(s);
     }
     return o;
@@ -38,11 +35,8 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
 static void free_func(gpointer options)
 {
     Options *o = options;
-
-    if (o) {
-        g_free(o->cmd);
-        g_free(o);
-    }
+    g_free(o->cmd);
+    g_free(o);
 }
 
 /* Always return FALSE because its not interactive */
index 2342067..502781d 100644 (file)
@@ -7,9 +7,9 @@ static gboolean run_func_toggle(ObActionsData *data, gpointer options);
 
 void action_shade_startup(void)
 {
-    actions_register("Shade", NULL, NULL, run_func_on, NULL, NULL);
-    actions_register("Unshade", NULL, NULL, run_func_off, NULL, NULL);
-    actions_register("ToggleShade", NULL, NULL, run_func_toggle, NULL, NULL);
+    actions_register("Shade", NULL, NULL, run_func_on);
+    actions_register("Unshade", NULL, NULL, run_func_off);
+    actions_register("ToggleShade", NULL, NULL, run_func_toggle);
 }
 
 /* Always return FALSE because its not interactive */
diff --git a/openbox/actions/shadelowerraise.c b/openbox/actions/shadelowerraise.c
new file mode 100644 (file)
index 0000000..414e281
--- /dev/null
@@ -0,0 +1,40 @@
+#include "openbox/actions.h"
+#include "openbox/client.h"
+
+static gboolean run_func_sl(ObActionsData *data, gpointer options);
+static gboolean run_func_ur(ObActionsData *data, gpointer options);
+
+void action_shadelowerraise_startup()
+{
+    /* 3.4-compatibility */
+    actions_register("ShadeLower", NULL, NULL, run_func_sl);
+    actions_register("UnshadeRaise", NULL, NULL, run_func_ur);
+}
+
+/* Always return FALSE because its not interactive */
+static gboolean run_func_sl(ObActionsData *data, gpointer options)
+{
+    if (data->client) {
+        actions_client_move(data, TRUE);
+        if (data->client->shaded)
+            stacking_lower(CLIENT_AS_WINDOW(data->client));
+        else
+            client_shade(data->client, TRUE);
+        actions_client_move(data, FALSE);
+    }
+    return FALSE;
+}
+
+/* Always return FALSE because its not interactive */
+static gboolean run_func_ur(ObActionsData *data, gpointer options)
+{
+    if (data->client) {
+        actions_client_move(data, TRUE);
+        if (data->client->shaded)
+            client_shade(data->client, FALSE);
+        else
+            stacking_raise(CLIENT_AS_WINDOW(data->client));
+        actions_client_move(data, FALSE);
+    }
+    return FALSE;
+}
index c9ba86c..6dc77d5 100644 (file)
@@ -5,10 +5,7 @@ static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_showdesktop_startup(void)
 {
-    actions_register("ToggleShowDesktop",
-                     NULL, NULL,
-                     run_func,
-                     NULL, NULL);
+    actions_register("ToggleShowDesktop", NULL, NULL, run_func);
 }
 
 /* Always return FALSE because its not interactive */
index c1d53e4..e60f1c6 100644 (file)
@@ -6,25 +6,24 @@ typedef struct {
     gchar   *name;
 } Options;
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
+static gpointer setup_func(xmlNodePtr node);
 static void     free_func(gpointer options);
 static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_showmenu_startup(void)
 {
-    actions_register("ShowMenu", setup_func, free_func, run_func,
-                     NULL, NULL);
+    actions_register("ShowMenu", setup_func, free_func, run_func);
 }
 
-static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
+static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_new0(Options, 1);
 
-    if ((n = parse_find_node("menu", node)))
-        o->name = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "menu")))
+        o->name = obt_xml_node_string(n);
     return o;
 }
 
index 22a9378..3db00ca 100644 (file)
@@ -5,7 +5,7 @@ static gboolean run_func(ObActionsData *data, gpointer options);
 
 void action_unfocus_startup(void)
 {
-    actions_register("Unfocus", NULL, NULL, run_func, NULL, NULL);
+    actions_register("Unfocus", NULL, NULL, run_func);
 }
 
 /* Always return FALSE because its not interactive */
index afea324..2f9cfb8 100644 (file)
 #include "debug.h"
 #include "startupnotify.h"
 #include "dock.h"
-#include "xerror.h"
 #include "screen.h"
 #include "moveresize.h"
 #include "ping.h"
 #include "place.h"
-#include "prop.h"
-#include "extensions.h"
 #include "frame.h"
 #include "session.h"
 #include "event.h"
 #include "menuframe.h"
 #include "keyboard.h"
 #include "mouse.h"
-#include "render/render.h"
+#include "obrender/render.h"
 #include "gettext.h"
+#include "obt/display.h"
+#include "obt/prop.h"
 
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
@@ -187,8 +186,8 @@ void client_set_list(void)
     } else
         windows = NULL;
 
-    PROP_SETA32(RootWindow(ob_display, ob_screen),
-                net_client_list, window, (gulong*)windows, size);
+    OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST, WINDOW,
+                    (gulong*)windows, size);
 
     if (windows)
         g_free(windows);
@@ -196,98 +195,19 @@ void client_set_list(void)
     stacking_set_list();
 }
 
-void client_manage_all(void)
-{
-    guint i, j, nchild;
-    Window w, *children;
-    XWMHints *wmhints;
-    XWindowAttributes attrib;
-
-    XQueryTree(ob_display, RootWindow(ob_display, ob_screen),
-               &w, &w, &children, &nchild);
-
-    /* remove all icon windows from the list */
-    for (i = 0; i < nchild; i++) {
-        if (children[i] == None) continue;
-        wmhints = XGetWMHints(ob_display, children[i]);
-        if (wmhints) {
-            if ((wmhints->flags & IconWindowHint) &&
-                (wmhints->icon_window != children[i]))
-                for (j = 0; j < nchild; j++)
-                    if (children[j] == wmhints->icon_window) {
-                        children[j] = None;
-                        break;
-                    }
-            XFree(wmhints);
-        }
-    }
-
-    /* manage windows in reverse order from how they were originally mapped.
-       this is an attempt to manage children windows before their parents, so
-       that when the parent is mapped, it can find the child */
-    for (i = 0; i < nchild; ++i) {
-        if (children[i] == None)
-            continue;
-        if (XGetWindowAttributes(ob_display, children[i], &attrib)) {
-            if (attrib.override_redirect) continue;
-
-            if (attrib.map_state != IsUnmapped)
-                client_manage(children[i], NULL);
-        }
-    }
-    XFree(children);
-}
-
 void client_manage(Window window, ObPrompt *prompt)
 {
     ObClient *self;
-    XEvent e;
-    XWindowAttributes attrib;
     XSetWindowAttributes attrib_set;
-    XWMHints *wmhint;
     gboolean activate = FALSE;
     ObAppSettings *settings;
     gboolean transient = FALSE;
-    Rect place, *monitor;
+    Rect place, *monitor, *allmonitors;
     Time launch_time, map_time;
     guint32 user_time;
+    gboolean obplaced;
 
-    grab_server(TRUE);
-
-    /* check if it has already been unmapped by the time we started
-       mapping. the grab does a sync so we don't have to here */
-    if (XCheckTypedWindowEvent(ob_display, window, DestroyNotify, &e) ||
-        XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e))
-    {
-        XPutBackEvent(ob_display, &e);
-
-        ob_debug("Trying to manage unmapped window. Aborting that.\n");
-        grab_server(FALSE);
-        return; /* don't manage it */
-    }
-
-    /* make sure it isn't an override-redirect window */
-    if (!XGetWindowAttributes(ob_display, window, &attrib) ||
-        attrib.override_redirect)
-    {
-        grab_server(FALSE);
-        return; /* don't manage it */
-    }
-
-    /* is the window a docking app */
-    if ((wmhint = XGetWMHints(ob_display, window))) {
-        if ((wmhint->flags & StateHint) &&
-            wmhint->initial_state == WithdrawnState)
-        {
-            dock_add(window, wmhint);
-            grab_server(FALSE);
-            XFree(wmhint);
-            return;
-        }
-        XFree(wmhint);
-    }
-
-    ob_debug("Managing window: 0x%lx\n", window);
+    ob_debug("Managing window: 0x%lx", window);
 
     map_time = event_get_server_time();
 
@@ -296,13 +216,13 @@ void client_manage(Window window, ObPrompt *prompt)
     attrib_set.event_mask = CLIENT_EVENTMASK |
         (prompt ? prompt->event_mask : 0);
     attrib_set.do_not_propagate_mask = CLIENT_NOPROPAGATEMASK;
-    XChangeWindowAttributes(ob_display, window,
+    XChangeWindowAttributes(obt_display, window,
                             CWEventMask|CWDontPropagate, &attrib_set);
 
     /* create the ObClient struct, and populate it from the hints on the
        window */
     self = g_new0(ObClient, 1);
-    self->obwin.type = Window_Client;
+    self->obwin.type = OB_WINDOW_CLASS_CLIENT;
     self->window = window;
     self->prompt = prompt;
     self->managed = TRUE;
@@ -315,9 +235,10 @@ void client_manage(Window window, ObPrompt *prompt)
     /* get all the stuff off the window */
     client_get_all(self, TRUE);
 
-    ob_debug("Window type: %d\n", self->type);
-    ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0);
-    ob_debug("Window name: %s class: %s role: %s\n", self->name, self->class, self->role);
+    ob_debug("Window type: %d", self->type);
+    ob_debug("Window group: 0x%x", self->group?self->group->leader:0);
+    ob_debug("Window name: %s class: %s role: %s title: %s",
+             self->name, self->class, self->role, self->title);
 
     /* per-app settings override stuff from client_get_all, and return the
        settings for other uses too. the returned settings is a shallow copy,
@@ -333,7 +254,7 @@ void client_manage(Window window, ObPrompt *prompt)
        should be reparented back to root automatically, unless we are managing
        an internal ObPrompt window  */
     if (!self->prompt)
-        XChangeSaveSet(ob_display, window, SetModeInsert);
+        XChangeSaveSet(obt_display, window, SetModeInsert);
 
     /* create the decoration frame for the client window */
     self->frame = frame_new(self);
@@ -350,7 +271,7 @@ void client_manage(Window window, ObPrompt *prompt)
     /* tell startup notification that this app started */
     launch_time = sn_app_started(self->startup_id, self->class, self->name);
 
-    if (!PROP_GET32(self->window, net_wm_user_time, cardinal, &user_time))
+    if (!OBT_PROP_GET32(self->window, NET_WM_USER_TIME, CARDINAL, &user_time))
         user_time = map_time;
 
     /* do this after we have a frame.. it uses the frame to help determine the
@@ -373,14 +294,15 @@ void client_manage(Window window, ObPrompt *prompt)
         (user_time != 0) &&
         /* this checks for focus=false for the window */
         (!settings || settings->focus != 0) &&
-        focus_valid_target(self, FALSE, FALSE, TRUE, FALSE, FALSE,
+        focus_valid_target(self, self->desktop,
+                           FALSE, FALSE, TRUE, FALSE, FALSE,
                            settings->focus == 1))
     {
         activate = TRUE;
     }
 
     /* remove the client's border */
-    XSetWindowBorderWidth(ob_display, self->window, 0);
+    XSetWindowBorderWidth(obt_display, self->window, 0);
 
     /* adjust the frame to the client's size before showing or placing
        the window */
@@ -390,10 +312,11 @@ void client_manage(Window window, ObPrompt *prompt)
     /* where the frame was placed is where the window was originally */
     place = self->area;
     monitor = screen_physical_area_monitor(screen_find_monitor(&place));
+    allmonitors = screen_physical_area_all_monitors();
 
     /* figure out placement for the window if the window is new */
     if (ob_state() == OB_STATE_RUNNING) {
-        ob_debug("Positioned: %s @ %d %d\n",
+        ob_debug("Positioned: %s @ %d %d",
                  (!self->positioned ? "no" :
                   (self->positioned == PPosition ? "program specified" :
                    (self->positioned == USPosition ? "user specified" :
@@ -401,7 +324,7 @@ void client_manage(Window window, ObPrompt *prompt)
                      "program + user specified" :
                      "BADNESS !?")))), place.x, place.y);
 
-        ob_debug("Sized: %s @ %d %d\n",
+        ob_debug("Sized: %s @ %d %d",
                  (!self->sized ? "no" :
                   (self->sized == PSize ? "program specified" :
                    (self->sized == USSize ? "user specified" :
@@ -409,9 +332,23 @@ void client_manage(Window window, ObPrompt *prompt)
                      "program + user specified" :
                      "BADNESS !?")))), place.width, place.height);
 
-        /* splash screens are also returned as TRUE for transient,
-           and so will be forced on screen below */
-        transient = place_client(self, &place.x, &place.y, settings);
+        obplaced = place_client(self, &place.x, &place.y, settings);
+
+        /* watch for buggy apps that ask to be placed at (0,0) when there is
+           a strut there */
+        if (!obplaced && place.x == 0 && place.y == 0 &&
+            /* oldschool fullscreen windows are allowed */
+            !(self->decorations == 0 && (RECT_EQUAL(place, *monitor) ||
+                                         RECT_EQUAL(place, *allmonitors))))
+        {
+            Rect *r;
+
+            r = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS, NULL);
+            place.x = r->x;
+            place.y = r->y;
+            ob_debug("Moving buggy app from (0,0) to (%d,%d)", r->x, r->y);
+            g_free(r);
+        }
 
         /* make sure the window is visible. */
         client_find_onscreen(self, &place.x, &place.y,
@@ -427,11 +364,13 @@ void client_manage(Window window, ObPrompt *prompt)
                                 it is up to the placement routines to avoid
                                 the xinerama divides)
 
-                                splash screens get "transient" set to TRUE by
-                                the place_client call
+                                children and splash screens are forced on
+                                screen, but i don't remember why i decided to
+                                do that.
                              */
                              ob_state() == OB_STATE_RUNNING &&
-                             (transient ||
+                             (self->type == OB_CLIENT_TYPE_DIALOG ||
+                              self->type == OB_CLIENT_TYPE_SPLASH ||
                               (!((self->positioned & USPosition) ||
                                  (settings && settings->pos_given)) &&
                                client_normal(self) &&
@@ -441,7 +380,8 @@ void client_manage(Window window, ObPrompt *prompt)
                                   makes its fullscreen window fit the screen
                                   but it is not USSize'd or USPosition'd) */
                                !(self->decorations == 0 &&
-                                 RECT_EQUAL(place, *monitor)))));
+                                 (RECT_EQUAL(place, *monitor) ||
+                                  RECT_EQUAL(place, *allmonitors))))));
     }
 
     /* if the window isn't user-sized, then make it fit inside
@@ -461,7 +401,8 @@ void client_manage(Window window, ObPrompt *prompt)
           /* don't shrink oldschool fullscreen windows to fit inside the
              struts (fixes Acroread, which makes its fullscreen window
              fit the screen but it is not USSize'd or USPosition'd) */
-          !(self->decorations == 0 && RECT_EQUAL(place, *monitor)))))
+          !(self->decorations == 0 && (RECT_EQUAL(place, *monitor) ||
+                                       RECT_EQUAL(place, *allmonitors))))))
     {
         Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &place);
 
@@ -473,7 +414,7 @@ void client_manage(Window window, ObPrompt *prompt)
         place.width = MIN(place.width, a->width);
         place.height = MIN(place.height, a->height);
 
-        ob_debug("setting window size to %dx%d\n", place.width, place.height);
+        ob_debug("setting window size to %dx%d", place.width, place.height);
 
         /* get the size of the client back */
         place.width -= self->frame->size.left + self->frame->size.right;
@@ -483,11 +424,11 @@ void client_manage(Window window, ObPrompt *prompt)
     }
 
     ob_debug("placing window 0x%x at %d, %d with size %d x %d. "
-             "some restrictions may apply\n",
+             "some restrictions may apply",
              self->window, place.x, place.y, place.width, place.height);
     if (self->session)
         ob_debug("  but session requested %d, %d  %d x %d instead, "
-                 "overriding\n",
+                 "overriding",
                  self->session->x, self->session->y,
                  self->session->w, self->session->h);
 
@@ -501,8 +442,10 @@ void client_manage(Window window, ObPrompt *prompt)
 
     g_free(monitor);
     monitor = NULL;
+    g_free(allmonitors);
+    allmonitors = NULL;
 
-    ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s\n",
+    ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s",
                   activate ? "yes" : "no");
     if (activate) {
         activate = client_can_steal_focus(self, map_time, launch_time);
@@ -550,7 +493,7 @@ void client_manage(Window window, ObPrompt *prompt)
 
     /* add to client list/map */
     client_list = g_list_append(client_list, self);
-    g_hash_table_insert(window_map, &self->window, self);
+    window_add(&self->window, CLIENT_AS_WINDOW(self));
 
     /* this has to happen after we're in the client_list */
     if (STRUT_EXISTS(self->strut))
@@ -562,10 +505,8 @@ void client_manage(Window window, ObPrompt *prompt)
     /* free the ObAppSettings shallow copy */
     g_free(settings);
 
-    ob_debug("Managed window 0x%lx plate 0x%x (%s)\n",
+    ob_debug("Managed window 0x%lx plate 0x%x (%s)",
              window, self->frame->window, self->class);
-
-    return;
 }
 
 ObClient *client_fake_manage(Window window)
@@ -573,7 +514,7 @@ ObClient *client_fake_manage(Window window)
     ObClient *self;
     ObAppSettings *settings;
 
-    ob_debug("Pretend-managing window: %lx\n", window);
+    ob_debug("Pretend-managing window: %lx", window);
 
     /* do this minimal stuff to figure out the client's decorations */
 
@@ -591,7 +532,7 @@ ObClient *client_fake_manage(Window window)
     self->frame = frame_new(self);
     frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
 
-    ob_debug("gave extents left %d right %d top %d bottom %d\n",
+    ob_debug("gave extents left %d right %d top %d bottom %d",
              self->frame->size.left, self->frame->size.right,
              self->frame->size.top, self->frame->size.bottom);
 
@@ -612,7 +553,7 @@ void client_unmanage(ObClient *self)
     GSList *it;
     gulong ignore_start;
 
-    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)\n",
+    ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)",
              self->window, self->frame->window,
              self->class, self->title ? self->title : "");
 
@@ -620,7 +561,7 @@ void client_unmanage(ObClient *self)
 
     /* we dont want events no more. do this before hiding the frame so we
        don't generate more events */
-    XSelectInput(ob_display, self->window, NoEventMask);
+    XSelectInput(obt_display, self->window, NoEventMask);
 
     /* ignore enter events from the unmap so it doesnt mess with the focus */
     if (!config_focus_under_mouse)
@@ -628,7 +569,7 @@ void client_unmanage(ObClient *self)
 
     frame_hide(self->frame);
     /* flush to send the hide to the server quickly */
-    XFlush(ob_display);
+    XFlush(obt_display);
 
     if (!config_focus_under_mouse)
         event_end_ignore_all_enters(ignore_start);
@@ -640,7 +581,7 @@ void client_unmanage(ObClient *self)
     /* remove the window from our save set, unless we are managing an internal
        ObPrompt window */
     if (!self->prompt)
-        XChangeSaveSet(ob_display, self->window, SetModeDelete);
+        XChangeSaveSet(obt_display, self->window, SetModeDelete);
 
     /* update the focus lists */
     focus_order_remove(self);
@@ -655,7 +596,7 @@ void client_unmanage(ObClient *self)
 
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
-    g_hash_table_remove(window_map, &self->window);
+    window_remove(self->window);
 
     /* once the client is out of the list, update the struts to remove its
        influence */
@@ -708,7 +649,7 @@ void client_unmanage(ObClient *self)
         self->decorations = 0; /* unmanaged windows have no decor */
 
         /* give the client its border back */
-        XSetWindowBorderWidth(ob_display, self->window, self->border_width);
+        XSetWindowBorderWidth(obt_display, self->window, self->border_width);
 
         client_move_resize(self, a.x, a.y, a.width, a.height);
     }
@@ -721,25 +662,25 @@ void client_unmanage(ObClient *self)
     if (ob_state() != OB_STATE_EXITING) {
         /* these values should not be persisted across a window
            unmapping/mapping */
-        PROP_ERASE(self->window, net_wm_desktop);
-        PROP_ERASE(self->window, net_wm_state);
-        PROP_ERASE(self->window, wm_state);
+        OBT_PROP_ERASE(self->window, NET_WM_DESKTOP);
+        OBT_PROP_ERASE(self->window, NET_WM_STATE);
+        OBT_PROP_ERASE(self->window, WM_STATE);
     } else {
         /* if we're left in an unmapped state, the client wont be mapped.
            this is bad, since we will no longer be managing the window on
            restart */
-        XMapWindow(ob_display, self->window);
+        XMapWindow(obt_display, self->window);
     }
 
     /* these should not be left on the window ever.  other window managers
        don't necessarily use them and it will mess them up (like compiz) */
-    PROP_ERASE(self->window, net_wm_visible_name);
-    PROP_ERASE(self->window, net_wm_visible_icon_name);
+    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_NAME);
+    OBT_PROP_ERASE(self->window, NET_WM_VISIBLE_ICON_NAME);
 
     /* update the list hints */
     client_set_list();
 
-    ob_debug("Unmanaged window 0x%lx\n", self->window);
+    ob_debug("Unmanaged window 0x%lx", self->window);
 
     /* free all data allocated in the client struct */
     RrImageUnref(self->icon_set);
@@ -783,7 +724,7 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time,
     /* This is focus stealing prevention */
     ob_debug_type(OB_DEBUG_FOCUS,
                   "Want to focus new window 0x%x at time %u "
-                  "launched at %u (last user interaction time %u)\n",
+                  "launched at %u (last user interaction time %u)",
                   self->window, steal_time, launch_time,
                   event_last_user_time);
 
@@ -814,7 +755,7 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time,
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Not focusing the window because the user is "
                           "working in another window that is not "
-                          "its parent\n");
+                          "its parent");
         }
         /* If the new window is a transient (and its relatives aren't
            focused) */
@@ -822,7 +763,7 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time,
             steal = FALSE;
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Not focusing the window because it is a "
-                          "transient, and its relatives aren't focused\n");
+                          "transient, and its relatives aren't focused");
         }
         /* Don't steal focus from globally active clients.
            I stole this idea from KWin. It seems nice.
@@ -833,7 +774,7 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time,
             steal = FALSE;
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Not focusing the window because a globally "
-                          "active client has focus\n");
+                          "active client has focus");
         }
         /* Don't move focus if it's not going to go to this window
            anyway */
@@ -841,7 +782,7 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time,
             steal = FALSE;
             ob_debug_type(OB_DEBUG_FOCUS,
                           "Not focusing the window because another window "
-                          "would get the focus anyway\n");
+                          "would get the focus anyway");
         }
         /* Don't move focus if the window is not visible on the current
            desktop and none of its relatives are focused */
@@ -859,7 +800,7 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time,
     if (!steal)
         ob_debug_type(OB_DEBUG_FOCUS,
                       "Focus stealing prevention activated for %s at "
-                      "time %u (last user interaction time %u)\n",
+                      "time %u (last user interaction time %u)",
                       self->title, steal_time, event_last_user_time);
     return steal;
 }
@@ -877,10 +818,10 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
         ObAppSettings *app = it->data;
         gboolean match = TRUE;
 
-        g_assert(app->name != NULL || app->class != NULL);
+        g_assert(app->name != NULL || app->class != NULL ||
+                 app->role != NULL || app->title != NULL ||
+                 (signed)app->type >= 0);
 
-        /* we know that either name or class is not NULL so it will have to
-           match to use the rule */
         if (app->name &&
             !g_pattern_match(app->name, strlen(self->name), self->name, NULL))
             match = FALSE;
@@ -892,11 +833,16 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
                  !g_pattern_match(app->role,
                                   strlen(self->role), self->role, NULL))
             match = FALSE;
-        else if ((signed)app->type >= 0 && app->type != self->type)
+        else if (app->title &&
+                 !g_pattern_match(app->title,
+                                  strlen(self->title), self->title, NULL))
+            match = FALSE;
+        else if ((signed)app->type >= 0 && app->type != self->type) {
             match = FALSE;
+        }
 
         if (match) {
-            ob_debug("Window matching: %s\n", app->name);
+            ob_debug("Window matching: %s", app->name);
 
             /* copy the settings to our struct, overriding the existing
                settings if they are not defaults */
@@ -951,17 +897,17 @@ static void client_restore_session_state(ObClient *self)
     GList *it;
 
     ob_debug_type(OB_DEBUG_SM,
-                  "Restore session for client %s\n", self->title);
+                  "Restore session for client %s", self->title);
 
     if (!(it = session_state_find(self))) {
         ob_debug_type(OB_DEBUG_SM,
-                      "Session data not found for client %s\n", self->title);
+                      "Session data not found for client %s", self->title);
         return;
     }
 
     self->session = it->data;
 
-    ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s\n",
+    ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s",
                   self->title);
 
     RECT_SET_POINT(self->area, self->session->x, self->session->y);
@@ -971,13 +917,13 @@ static void client_restore_session_state(ObClient *self)
         self->area.width = self->session->w;
     if (self->session->h > 0)
         self->area.height = self->session->h;
-    XResizeWindow(ob_display, self->window,
+    XResizeWindow(obt_display, self->window,
                   self->area.width, self->area.height);
 
     self->desktop = (self->session->desktop == DESKTOP_ALL ?
                      self->session->desktop :
                      MIN(screen_num_desktops - 1, self->session->desktop));
-    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
+    OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop);
 
     self->shaded = self->session->shaded;
     self->iconic = self->session->iconic;
@@ -1165,9 +1111,6 @@ static void client_get_all(ObClient *self, gboolean real)
        from per-app settings */
     client_get_session_ids(self);
 
-    /* save the values of the variables used for app rule matching */
-    client_save_app_rule_values(self);
-
     /* now we got everything that can affect the decorations */
     if (!real)
         return;
@@ -1175,6 +1118,9 @@ static void client_get_all(ObClient *self, gboolean real)
     /* get this early so we have it for debugging */
     client_update_title(self);
 
+    /* save the values of the variables used for app rule matching */
+    client_save_app_rule_values(self);
+
     client_update_protocols(self);
 
     client_update_wmhints(self);
@@ -1207,10 +1153,11 @@ static void client_get_all(ObClient *self, gboolean real)
 
 static void client_get_startup_id(ObClient *self)
 {
-    if (!(PROP_GETS(self->window, net_startup_id, utf8, &self->startup_id)))
+    if (!(OBT_PROP_GETS(self->window, NET_STARTUP_ID, utf8,
+                        &self->startup_id)))
         if (self->group)
-            PROP_GETS(self->group->leader,
-                      net_startup_id, utf8, &self->startup_id);
+            OBT_PROP_GETS(self->group->leader,
+                          NET_STARTUP_ID, utf8, &self->startup_id);
 }
 
 static void client_get_area(ObClient *self)
@@ -1218,14 +1165,14 @@ static void client_get_area(ObClient *self)
     XWindowAttributes wattrib;
     Status ret;
 
-    ret = XGetWindowAttributes(ob_display, self->window, &wattrib);
+    ret = XGetWindowAttributes(obt_display, self->window, &wattrib);
     g_assert(ret != BadWindow);
 
     RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
     POINT_SET(self->root_pos, wattrib.x, wattrib.y);
     self->border_width = wattrib.border_width;
 
-    ob_debug("client area: %d %d  %d %d  bw %d\n", wattrib.x, wattrib.y,
+    ob_debug("client area: %d %d  %d %d  bw %d", wattrib.x, wattrib.y,
              wattrib.width, wattrib.height, wattrib.border_width);
 }
 
@@ -1233,12 +1180,12 @@ static void client_get_desktop(ObClient *self)
 {
     guint32 d = screen_num_desktops; /* an always-invalid value */
 
-    if (PROP_GET32(self->window, net_wm_desktop, cardinal, &d)) {
+    if (OBT_PROP_GET32(self->window, NET_WM_DESKTOP, CARDINAL, &d)) {
         if (d >= screen_num_desktops && d != DESKTOP_ALL)
             self->desktop = screen_num_desktops - 1;
         else
             self->desktop = d;
-        ob_debug("client requested desktop 0x%x\n", self->desktop);
+        ob_debug("client requested desktop 0x%x", self->desktop);
     } else {
         GSList *it;
         gboolean first = TRUE;
@@ -1261,7 +1208,7 @@ static void client_get_desktop(ObClient *self)
         if (all != screen_num_desktops) {
             self->desktop = all;
 
-            ob_debug("client desktop set from parents: 0x%x\n",
+            ob_debug("client desktop set from parents: 0x%x",
                      self->desktop);
         }
         /* try get from the startup-notification protocol */
@@ -1269,13 +1216,13 @@ static void client_get_desktop(ObClient *self)
             if (self->desktop >= screen_num_desktops &&
                 self->desktop != DESKTOP_ALL)
                 self->desktop = screen_num_desktops - 1;
-            ob_debug("client desktop set from startup-notification: 0x%x\n",
+            ob_debug("client desktop set from startup-notification: 0x%x",
                      self->desktop);
         }
         /* defaults to the current desktop */
         else {
             self->desktop = screen_desktop;
-            ob_debug("client desktop set to the current desktop: %d\n",
+            ob_debug("client desktop set to the current desktop: %d",
                      self->desktop);
         }
     }
@@ -1286,32 +1233,32 @@ static void client_get_state(ObClient *self)
     guint32 *state;
     guint num;
 
-    if (PROP_GETA32(self->window, net_wm_state, atom, &state, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_STATE, ATOM, &state, &num)) {
         gulong i;
         for (i = 0; i < num; ++i) {
-            if (state[i] == prop_atoms.net_wm_state_modal)
+            if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MODAL))
                 self->modal = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_shaded)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SHADED))
                 self->shaded = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_hidden)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN))
                 self->iconic = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_skip_taskbar)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR))
                 self->skip_taskbar = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_skip_pager)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER))
                 self->skip_pager = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_fullscreen)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN))
                 self->fullscreen = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_maximized_vert)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT))
                 self->max_vert = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_maximized_horz)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ))
                 self->max_horz = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_above)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_ABOVE))
                 self->above = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_below)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_BELOW))
                 self->below = TRUE;
-            else if (state[i] == prop_atoms.net_wm_state_demands_attention)
+            else if (state[i] == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION))
                 self->demands_attention = TRUE;
-            else if (state[i] == prop_atoms.ob_wm_state_undecorated)
+            else if (state[i] == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED))
                 self->undecorated = TRUE;
         }
 
@@ -1323,14 +1270,14 @@ static void client_get_shaped(ObClient *self)
 {
     self->shaped = FALSE;
 #ifdef SHAPE
-    if (extensions_shape) {
+    if (obt_display_extension_shape) {
         gint foo;
         guint ufoo;
         gint s;
 
-        XShapeSelectInput(ob_display, self->window, ShapeNotifyMask);
+        XShapeSelectInput(obt_display, self->window, ShapeNotifyMask);
 
-        XShapeQueryExtents(ob_display, self->window, &s, &foo,
+        XShapeQueryExtents(obt_display, self->window, &s, &foo,
                            &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo,
                            &ufoo);
         self->shaped = !!s;
@@ -1344,22 +1291,22 @@ void client_update_transient_for(ObClient *self)
     ObClient *target = NULL;
     gboolean trangroup = FALSE;
 
-    if (XGetTransientForHint(ob_display, self->window, &t)) {
+    if (XGetTransientForHint(obt_display, self->window, &t)) {
         if (t != self->window) { /* can't be transient to itself! */
-            target = g_hash_table_lookup(window_map, &t);
+            ObWindow *tw = window_find(t);
             /* if this happens then we need to check for it */
-            g_assert(target != self);
-            if (target && !WINDOW_IS_CLIENT(target)) {
+            g_assert(tw != CLIENT_AS_WINDOW(self));
+            if (tw && WINDOW_IS_CLIENT(tw)) {
                 /* watch out for windows with a parent that is something
                    different, like a dockapp for example */
-                target = NULL;
+                target = WINDOW_AS_CLIENT(tw);
             }
         }
 
         /* Setting the transient_for to Root is actually illegal, however
            applications from time have done this to specify transient for
            their group */
-        if (!target && self->group && t == RootWindow(ob_display, ob_screen))
+        if (!target && self->group && t == obt_root(ob_screen))
             trangroup = TRUE;
     } else if (self->group && self->transient)
         trangroup = TRUE;
@@ -1494,8 +1441,8 @@ void client_get_mwm_hints(ObClient *self)
 
     self->mwmhints.flags = 0; /* default to none */
 
-    if (PROP_GETA32(self->window, motif_wm_hints, motif_wm_hints,
-                    &hints, &num)) {
+    if (OBT_PROP_GETA32(self->window, MOTIF_WM_HINTS, MOTIF_WM_HINTS,
+                        &hints, &num)) {
         if (num >= OB_MWM_ELEMENTS) {
             self->mwmhints.flags = hints[0];
             self->mwmhints.functions = hints[1];
@@ -1514,26 +1461,27 @@ void client_get_type_and_transientness(ObClient *self)
     self->type = -1;
     self->transient = FALSE;
 
-    if (PROP_GETA32(self->window, net_wm_window_type, atom, &val, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_WINDOW_TYPE, ATOM, &val, &num)) {
         /* use the first value that we know about in the array */
         for (i = 0; i < num; ++i) {
-            if (val[i] == prop_atoms.net_wm_window_type_desktop)
+            if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
                 self->type = OB_CLIENT_TYPE_DESKTOP;
-            else if (val[i] == prop_atoms.net_wm_window_type_dock)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK))
                 self->type = OB_CLIENT_TYPE_DOCK;
-            else if (val[i] == prop_atoms.net_wm_window_type_toolbar)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_TOOLBAR))
                 self->type = OB_CLIENT_TYPE_TOOLBAR;
-            else if (val[i] == prop_atoms.net_wm_window_type_menu)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
                 self->type = OB_CLIENT_TYPE_MENU;
-            else if (val[i] == prop_atoms.net_wm_window_type_utility)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_UTILITY))
                 self->type = OB_CLIENT_TYPE_UTILITY;
-            else if (val[i] == prop_atoms.net_wm_window_type_splash)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_SPLASH))
                 self->type = OB_CLIENT_TYPE_SPLASH;
-            else if (val[i] == prop_atoms.net_wm_window_type_dialog)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG))
                 self->type = OB_CLIENT_TYPE_DIALOG;
-            else if (val[i] == prop_atoms.net_wm_window_type_normal)
+            else if (val[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_NORMAL))
                 self->type = OB_CLIENT_TYPE_NORMAL;
-            else if (val[i] == prop_atoms.kde_net_wm_window_type_override) {
+            else if (val[i] == OBT_PROP_ATOM(KDE_NET_WM_WINDOW_TYPE_OVERRIDE))
+            {
                 /* prevent this window from getting any decor or
                    functionality */
                 self->mwmhints.flags &= (OB_MWM_FLAG_FUNCTIONS |
@@ -1547,7 +1495,7 @@ void client_get_type_and_transientness(ObClient *self)
         g_free(val);
     }
 
-    if (XGetTransientForHint(ob_display, self->window, &t))
+    if (XGetTransientForHint(obt_display, self->window, &t))
         self->transient = TRUE;
 
     if (self->type == (ObClientType) -1) {
@@ -1573,26 +1521,26 @@ void client_get_type_and_transientness(ObClient *self)
 void client_update_protocols(ObClient *self)
 {
     guint32 *proto;
-    guint num_return, i;
+    guint num_ret, i;
 
     self->focus_notify = FALSE;
     self->delete_window = FALSE;
 
-    if (PROP_GETA32(self->window, wm_protocols, atom, &proto, &num_return)) {
-        for (i = 0; i < num_return; ++i) {
-            if (proto[i] == prop_atoms.wm_delete_window)
+    if (OBT_PROP_GETA32(self->window, WM_PROTOCOLS, ATOM, &proto, &num_ret)) {
+        for (i = 0; i < num_ret; ++i) {
+            if (proto[i] == OBT_PROP_ATOM(WM_DELETE_WINDOW))
                 /* this means we can request the window to close */
                 self->delete_window = TRUE;
-            else if (proto[i] == prop_atoms.wm_take_focus)
+            else if (proto[i] == OBT_PROP_ATOM(WM_TAKE_FOCUS))
                 /* if this protocol is requested, then the window will be
                    notified whenever we want it to receive focus */
                 self->focus_notify = TRUE;
-            else if (proto[i] == prop_atoms.net_wm_ping)
+            else if (proto[i] == OBT_PROP_ATOM(NET_WM_PING))
                 /* if this protocol is requested, then the window will allow
                    pings to determine if it is still alive */
                 self->ping = TRUE;
 #ifdef SYNC
-            else if (proto[i] == prop_atoms.net_wm_sync_request)
+            else if (proto[i] == OBT_PROP_ATOM(NET_WM_SYNC_REQUEST))
                 /* if this protocol is requested, then resizing the
                    window will be synchronized between the frame and the
                    client */
@@ -1608,7 +1556,8 @@ void client_update_sync_request_counter(ObClient *self)
 {
     guint32 i;
 
-    if (PROP_GET32(self->window, net_wm_sync_request_counter, cardinal, &i)) {
+    if (OBT_PROP_GET32(self->window, NET_WM_SYNC_REQUEST_COUNTER, CARDINAL,&i))
+    {
         self->sync_counter = i;
     } else
         self->sync_counter = None;
@@ -1619,7 +1568,7 @@ static void client_get_colormap(ObClient *self)
 {
     XWindowAttributes wa;
 
-    if (XGetWindowAttributes(ob_display, self->window, &wa))
+    if (XGetWindowAttributes(obt_display, self->window, &wa))
         client_update_colormap(self, wa.colormap);
 }
 
@@ -1627,7 +1576,7 @@ void client_update_colormap(ObClient *self, Colormap colormap)
 {
     if (colormap == self->colormap) return;
 
-    ob_debug("Setting client %s colormap: 0x%x\n", self->title, colormap);
+    ob_debug("Setting client %s colormap: 0x%x", self->title, colormap);
 
     if (client_focused(self)) {
         screen_install_colormap(self, FALSE); /* uninstall old one */
@@ -1651,7 +1600,7 @@ void client_update_normal_hints(ObClient *self)
     SIZE_SET(self->max_size, G_MAXINT, G_MAXINT);
 
     /* get the hints from the window */
-    if (XGetWMNormalHints(ob_display, self->window, &size, &ret)) {
+    if (XGetWMNormalHints(obt_display, self->window, &size, &ret)) {
         /* normal windows can't request placement! har har
         if (!client_normal(self))
         */
@@ -1682,15 +1631,15 @@ void client_update_normal_hints(ObClient *self)
         if (size.flags & PResizeInc && size.width_inc && size.height_inc)
             SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
 
-        ob_debug("Normal hints: min size (%d %d) max size (%d %d)\n   "
-                 "size inc (%d %d) base size (%d %d)\n",
+        ob_debug("Normal hints: min size (%d %d) max size (%d %d)",
                  self->min_size.width, self->min_size.height,
-                 self->max_size.width, self->max_size.height,
+                 self->max_size.width, self->max_size.height);
+        ob_debug("size inc (%d %d) base size (%d %d)",
                  self->size_inc.width, self->size_inc.height,
                  self->base_size.width, self->base_size.height);
     }
     else
-        ob_debug("Normal hints: not set\n");
+        ob_debug("Normal hints: not set");
 }
 
 void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
@@ -1864,38 +1813,38 @@ static void client_change_allowed_actions(ObClient *self)
 
     /* desktop windows are kept on all desktops */
     if (self->type != OB_CLIENT_TYPE_DESKTOP)
-        actions[num++] = prop_atoms.net_wm_action_change_desktop;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_CHANGE_DESKTOP);
 
     if (self->functions & OB_CLIENT_FUNC_SHADE)
-        actions[num++] = prop_atoms.net_wm_action_shade;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_SHADE);
     if (self->functions & OB_CLIENT_FUNC_CLOSE)
-        actions[num++] = prop_atoms.net_wm_action_close;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_CLOSE);
     if (self->functions & OB_CLIENT_FUNC_MOVE)
-        actions[num++] = prop_atoms.net_wm_action_move;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MOVE);
     if (self->functions & OB_CLIENT_FUNC_ICONIFY)
-        actions[num++] = prop_atoms.net_wm_action_minimize;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MINIMIZE);
     if (self->functions & OB_CLIENT_FUNC_RESIZE)
-        actions[num++] = prop_atoms.net_wm_action_resize;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_RESIZE);
     if (self->functions & OB_CLIENT_FUNC_FULLSCREEN)
-        actions[num++] = prop_atoms.net_wm_action_fullscreen;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_FULLSCREEN);
     if (self->functions & OB_CLIENT_FUNC_MAXIMIZE) {
-        actions[num++] = prop_atoms.net_wm_action_maximize_horz;
-        actions[num++] = prop_atoms.net_wm_action_maximize_vert;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_HORZ);
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_VERT);
     }
     if (self->functions & OB_CLIENT_FUNC_ABOVE)
-        actions[num++] = prop_atoms.net_wm_action_above;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_ABOVE);
     if (self->functions & OB_CLIENT_FUNC_BELOW)
-        actions[num++] = prop_atoms.net_wm_action_below;
+        actions[num++] = OBT_PROP_ATOM(NET_WM_ACTION_BELOW);
     if (self->functions & OB_CLIENT_FUNC_UNDECORATE)
-        actions[num++] = prop_atoms.ob_wm_action_undecorate;
+        actions[num++] = OBT_PROP_ATOM(OB_WM_ACTION_UNDECORATE);
 
-    PROP_SETA32(self->window, net_wm_allowed_actions, atom, actions, num);
+    OBT_PROP_SETA32(self->window, NET_WM_ALLOWED_ACTIONS, ATOM, actions, num);
 
-   /* make sure the window isn't breaking any rules now
+    /* make sure the window isn't breaking any rules now
 
-   don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
-   it can't be iconified with its parent
-   */
+       don't check ICONIFY here.  just cuz a window can't iconify doesnt mean
+       it can't be iconified with its parent
+    */
 
     if (!(self->functions & OB_CLIENT_FUNC_SHADE) && self->shaded) {
         if (self->frame) client_shade(self, FALSE);
@@ -1919,7 +1868,7 @@ void client_update_wmhints(ObClient *self)
     /* assume a window takes input if it doesn't specify */
     self->can_focus = TRUE;
 
-    if ((hints = XGetWMHints(ob_display, self->window)) != NULL) {
+    if ((hints = XGetWMHints(obt_display, self->window)) != NULL) {
         gboolean ur;
 
         if (hints->flags & InputHint)
@@ -2010,10 +1959,10 @@ void client_update_title(ObClient *self)
     g_free(self->original_title);
 
     /* try netwm */
-    if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
+    if (!OBT_PROP_GETS(self->window, NET_WM_NAME, utf8, &data)) {
         /* try old x stuff */
-        if (!(PROP_GETS(self->window, wm_name, locale, &data)
-              || PROP_GETS(self->window, wm_name, utf8, &data))) {
+        if (!(OBT_PROP_GETS(self->window, WM_NAME, locale, &data)
+              || OBT_PROP_GETS(self->window, WM_NAME, utf8, &data))) {
             if (self->transient) {
     /*
     GNOME alert windows are not given titles:
@@ -2041,7 +1990,7 @@ void client_update_title(ObClient *self)
         g_free(data);
     }
 
-    PROP_SETS(self->window, net_wm_visible_name, visible);
+    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_NAME, utf8, visible);
     self->title = visible;
 
     if (self->frame)
@@ -2052,10 +2001,10 @@ void client_update_title(ObClient *self)
     g_free(self->icon_title);
 
     /* try netwm */
-    if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
+    if (!OBT_PROP_GETS(self->window, NET_WM_ICON_NAME, utf8, &data))
         /* try old x stuff */
-        if (!(PROP_GETS(self->window, wm_icon_name, locale, &data) ||
-              PROP_GETS(self->window, wm_icon_name, utf8, &data)))
+        if (!(OBT_PROP_GETS(self->window, WM_ICON_NAME, locale, &data) ||
+              OBT_PROP_GETS(self->window, WM_ICON_NAME, utf8, &data)))
             data = g_strdup(self->title);
 
     if (self->client_machine) {
@@ -2073,7 +2022,7 @@ void client_update_title(ObClient *self)
         g_free(data);
     }
 
-    PROP_SETS(self->window, net_wm_visible_icon_name, visible);
+    OBT_PROP_SETS(self->window, NET_WM_VISIBLE_ICON_NAME, utf8, visible);
     self->icon_title = visible;
 }
 
@@ -2084,8 +2033,9 @@ void client_update_strut(ObClient *self)
     gboolean got = FALSE;
     StrutPartial strut;
 
-    if (PROP_GETA32(self->window, net_wm_strut_partial, cardinal,
-                    &data, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_STRUT_PARTIAL, CARDINAL,
+                        &data, &num))
+    {
         if (num == 12) {
             got = TRUE;
             STRUT_PARTIAL_SET(strut,
@@ -2097,7 +2047,7 @@ void client_update_strut(ObClient *self)
     }
 
     if (!got &&
-        PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) {
+        OBT_PROP_GETA32(self->window, NET_WM_STRUT, CARDINAL, &data, &num)) {
         if (num == 4) {
             Rect *a;
 
@@ -2146,7 +2096,7 @@ void client_update_icons(ObClient *self)
        icon */
     grab_server(TRUE);
 
-    if (PROP_GETA32(self->window, net_wm_icon, cardinal, &data, &num)) {
+    if (OBT_PROP_GETA32(self->window, NET_WM_ICON, CARDINAL, &data, &num)) {
         /* figure out how many valid icons are in here */
         i = 0;
         num_seen = 0;
@@ -2198,16 +2148,16 @@ void client_update_icons(ObClient *self)
     if (!img) {
         XWMHints *hints;
 
-        if ((hints = XGetWMHints(ob_display, self->window))) {
+        if ((hints = XGetWMHints(obt_display, self->window))) {
             if (hints->flags & IconPixmapHint) {
                 gboolean xicon;
-                xerror_set_ignore(TRUE);
+                obt_display_ignore_errors(TRUE);
                 xicon = RrPixmapToRGBA(ob_rr_inst,
                                        hints->icon_pixmap,
                                        (hints->flags & IconMaskHint ?
                                         hints->icon_mask : None),
                                        (gint*)&w, (gint*)&h, &data);
-                xerror_set_ignore(FALSE);
+                obt_display_ignore_errors(FALSE);
 
                 if (xicon) {
                     if (w > 0 && h > 0) {
@@ -2250,7 +2200,7 @@ void client_update_icons(ObClient *self)
                 (((icon[i] >> RrDefaultRedOffset) & 0xff) << 16) +
                 (((icon[i] >> RrDefaultGreenOffset) & 0xff) << 8) +
                 (((icon[i] >> RrDefaultBlueOffset) & 0xff) << 0);
-        PROP_SETA32(self->window, net_wm_icon, cardinal, ldata, w*h+2);
+        OBT_PROP_SETA32(self->window, NET_WM_ICON, CARDINAL, ldata, w*h+2);
         g_free(ldata);
     } else if (self->frame)
         /* don't draw the icon empty if we're just setting one now anyways,
@@ -2267,7 +2217,8 @@ void client_update_icon_geometry(ObClient *self)
 
     RECT_SET(self->icon_geometry, 0, 0, 0, 0);
 
-    if (PROP_GETA32(self->window, net_wm_icon_geometry, cardinal, &data, &num))
+    if (OBT_PROP_GETA32(self->window, NET_WM_ICON_GEOMETRY, CARDINAL,
+                        &data, &num))
     {
         if (num == 4)
             /* don't let them set it with an area < 0 */
@@ -2284,23 +2235,23 @@ static void client_get_session_ids(ObClient *self)
     gchar *s;
     gchar **ss;
 
-    if (!PROP_GET32(self->window, wm_client_leader, window, &leader))
+    if (!OBT_PROP_GET32(self->window, WM_CLIENT_LEADER, WINDOW, &leader))
         leader = None;
 
     /* get the SM_CLIENT_ID */
     got = FALSE;
     if (leader)
-        got = PROP_GETS(leader, sm_client_id, locale, &self->sm_client_id);
+        got = OBT_PROP_GETS(leader, SM_CLIENT_ID, locale, &self->sm_client_id);
     if (!got)
-        PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id);
+        OBT_PROP_GETS(self->window, SM_CLIENT_ID, locale, &self->sm_client_id);
 
     /* get the WM_CLASS (name and class). make them "" if they are not
        provided */
     got = FALSE;
     if (leader)
-        got = PROP_GETSS(leader, wm_class, locale, &ss);
+        got = OBT_PROP_GETSS(leader, WM_CLASS, locale, &ss);
     if (!got)
-        got = PROP_GETSS(self->window, wm_class, locale, &ss);
+        got = OBT_PROP_GETSS(self->window, WM_CLASS, locale, &ss);
 
     if (got) {
         if (ss[0]) {
@@ -2317,9 +2268,9 @@ static void client_get_session_ids(ObClient *self)
     /* get the WM_WINDOW_ROLE. make it "" if it is not provided */
     got = FALSE;
     if (leader)
-        got = PROP_GETS(leader, wm_window_role, locale, &s);
+        got = OBT_PROP_GETS(leader, WM_WINDOW_ROLE, locale, &s);
     if (!got)
-        got = PROP_GETS(self->window, wm_window_role, locale, &s);
+        got = OBT_PROP_GETS(self->window, WM_WINDOW_ROLE, locale, &s);
 
     if (got)
         self->role = s;
@@ -2330,9 +2281,9 @@ static void client_get_session_ids(ObClient *self)
     got = FALSE;
 
     if (leader)
-        got = PROP_GETSS(leader, wm_command, locale, &ss);
+        got = OBT_PROP_GETSS(leader, WM_COMMAND, locale, &ss);
     if (!got)
-        got = PROP_GETSS(self->window, wm_command, locale, &ss);
+        got = OBT_PROP_GETSS(self->window, WM_COMMAND, locale, &ss);
 
     if (got) {
         /* merge/mash them all together */
@@ -2355,9 +2306,9 @@ static void client_get_session_ids(ObClient *self)
     /* get the WM_CLIENT_MACHINE */
     got = FALSE;
     if (leader)
-        got = PROP_GETS(leader, wm_client_machine, locale, &s);
+        got = OBT_PROP_GETS(leader, WM_CLIENT_MACHINE, locale, &s);
     if (!got)
-        got = PROP_GETS(self->window, wm_client_machine, locale, &s);
+        got = OBT_PROP_GETS(self->window, WM_CLIENT_MACHINE, locale, &s);
 
     if (got) {
         gchar localhost[128];
@@ -2372,7 +2323,7 @@ static void client_get_session_ids(ObClient *self)
 
         /* see if it has the PID set too (the PID requires that the
            WM_CLIENT_MACHINE be set) */
-        if (PROP_GET32(self->window, net_wm_pid, cardinal, &pid))
+        if (OBT_PROP_GET32(self->window, NET_WM_PID, CARDINAL, &pid))
             self->pid = pid;
     }
 }
@@ -2384,9 +2335,10 @@ static void client_save_app_rule_values(ObClient *self)
 {
     const gchar *type;
 
-    PROP_SETS(self->window, ob_app_role, self->role);
-    PROP_SETS(self->window, ob_app_name, self->name);
-    PROP_SETS(self->window, ob_app_class, self->class);
+    OBT_PROP_SETS(self->window, OB_APP_ROLE, utf8, self->role);
+    OBT_PROP_SETS(self->window, OB_APP_NAME, utf8, self->name);
+    OBT_PROP_SETS(self->window, OB_APP_CLASS, utf8, self->class);
+    OBT_PROP_SETS(self->window, OB_APP_TITLE, utf8, self->original_title);
 
     switch (self->type) {
     case OB_CLIENT_TYPE_NORMAL:
@@ -2406,7 +2358,7 @@ static void client_save_app_rule_values(ObClient *self)
     case OB_CLIENT_TYPE_DOCK:
         type = "dock"; break;
     }
-    PROP_SETS(self->window, ob_app_type, type);
+    OBT_PROP_SETS(self->window, OB_APP_TYPE, utf8, type);
 }
 
 static void client_change_wm_state(ObClient *self)
@@ -2424,12 +2376,12 @@ static void client_change_wm_state(ObClient *self)
         self->wmstate = NormalState;
 
     if (old != self->wmstate) {
-        PROP_MSG(self->window, kde_wm_change_state,
-                 self->wmstate, 1, 0, 0);
+        OBT_PROP_MSG(ob_screen, self->window, KDE_WM_CHANGE_STATE,
+                     self->wmstate, 1, 0, 0, 0);
 
         state[0] = self->wmstate;
         state[1] = None;
-        PROP_SETA32(self->window, wm_state, wm_state, state, 2);
+        OBT_PROP_SETA32(self->window, WM_STATE, WM_STATE, state, 2);
     }
 }
 
@@ -2440,30 +2392,30 @@ static void client_change_state(ObClient *self)
 
     num = 0;
     if (self->modal)
-        netstate[num++] = prop_atoms.net_wm_state_modal;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MODAL);
     if (self->shaded)
-        netstate[num++] = prop_atoms.net_wm_state_shaded;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SHADED);
     if (self->iconic)
-        netstate[num++] = prop_atoms.net_wm_state_hidden;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_HIDDEN);
     if (self->skip_taskbar)
-        netstate[num++] = prop_atoms.net_wm_state_skip_taskbar;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR);
     if (self->skip_pager)
-        netstate[num++] = prop_atoms.net_wm_state_skip_pager;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER);
     if (self->fullscreen)
-        netstate[num++] = prop_atoms.net_wm_state_fullscreen;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN);
     if (self->max_vert)
-        netstate[num++] = prop_atoms.net_wm_state_maximized_vert;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT);
     if (self->max_horz)
-        netstate[num++] = prop_atoms.net_wm_state_maximized_horz;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ);
     if (self->above)
-        netstate[num++] = prop_atoms.net_wm_state_above;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_ABOVE);
     if (self->below)
-        netstate[num++] = prop_atoms.net_wm_state_below;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_BELOW);
     if (self->demands_attention)
-        netstate[num++] = prop_atoms.net_wm_state_demands_attention;
+        netstate[num++] = OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION);
     if (self->undecorated)
-        netstate[num++] = prop_atoms.ob_wm_state_undecorated;
-    PROP_SETA32(self->window, net_wm_state, atom, netstate, num);
+        netstate[num++] = OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED);
+    OBT_PROP_SETA32(self->window, NET_WM_STATE, ATOM, netstate, num);
 
     if (self->frame)
         frame_adjust_state(self->frame);
@@ -2488,7 +2440,7 @@ ObClient *client_search_focus_tree_full(ObClient *self)
 
         for (it = self->parents; it; it = g_slist_next(it)) {
             ObClient *c = it->data;
-            if ((c = client_search_focus_tree_full(it->data))) return c;
+            if ((c = client_search_focus_tree_full(c))) return c;
         }
 
         return NULL;
@@ -2526,9 +2478,10 @@ gboolean client_has_parent(ObClient *self)
 static ObStackingLayer calc_layer(ObClient *self)
 {
     ObStackingLayer l;
-    Rect *monitor;
+    Rect *monitor, *allmonitors;
 
     monitor = screen_physical_area_monitor(client_monitor(self));
+    allmonitors = screen_physical_area_all_monitors();
 
     if (self->type == OB_CLIENT_TYPE_DESKTOP)
         l = OB_STACKING_LAYER_DESKTOP;
@@ -2542,7 +2495,8 @@ static ObStackingLayer calc_layer(ObClient *self)
               */
               (self->decorations == 0 &&
                !(self->max_horz && self->max_vert) &&
-               RECT_EQUAL(self->area, *monitor))) &&
+               (RECT_EQUAL(self->area, *monitor) ||
+                RECT_EQUAL(self->area, *allmonitors)))) &&
              /* you are fullscreen while you or your children are focused.. */
              (client_focused(self) || client_search_focus_tree(self) ||
               /* you can be fullscreen if you're on another desktop */
@@ -2558,6 +2512,7 @@ static ObStackingLayer calc_layer(ObClient *self)
     else l = OB_STACKING_LAYER_NORMAL;
 
     g_free(monitor);
+    g_free(allmonitors);
 
     return l;
 }
@@ -2757,7 +2712,7 @@ static void client_apply_startup_state(ObClient *self,
        pre-max/pre-fullscreen values
     */
     client_try_configure(self, &x, &y, &w, &h, &l, &l, FALSE);
-    ob_debug("placed window 0x%x at %d, %d with size %d x %d\n",
+    ob_debug("placed window 0x%x at %d, %d with size %d x %d",
              self->window, x, y, w, h);
     /* save the area, and make it where it should be for the premax stuff */
     oldarea = self->area;
@@ -2797,7 +2752,7 @@ static void client_apply_startup_state(ObClient *self,
     client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
 
     /* set the desktop hint, to make sure that it always exists */
-    PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop);
+    OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, self->desktop);
 
     /* nothing to do for the other states:
        skip_taskbar
@@ -3075,7 +3030,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
 
     /* if the client is enlarging, then resize the client before the frame */
     if (send_resize_client && (w > oldw || h > oldh)) {
-        XMoveResizeWindow(ob_display, self->window,
+        XMoveResizeWindow(obt_display, self->window,
                           self->frame->size.left, self->frame->size.top,
                           MAX(w, oldw), MAX(h, oldh));
         frame_adjust_client_area(self->frame);
@@ -3141,11 +3096,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
         XEvent event;
 
         event.type = ConfigureNotify;
-        event.xconfigure.display = ob_display;
+        event.xconfigure.display = obt_display;
         event.xconfigure.event = self->window;
         event.xconfigure.window = self->window;
 
-        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d\n",
+        ob_debug("Sending ConfigureNotify to %s for %d,%d %dx%d",
                  self->title, self->root_pos.x, self->root_pos.y, w, h);
 
         /* root window real coords */
@@ -3167,11 +3122,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
      */
     if (send_resize_client && (w <= oldw || h <= oldh)) {
         frame_adjust_client_area(self->frame);
-        XMoveResizeWindow(ob_display, self->window,
+        XMoveResizeWindow(obt_display, self->window,
                           self->frame->size.left, self->frame->size.top, w, h);
     }
 
-    XFlush(ob_display);
+    XFlush(obt_display);
 
     /* if it moved between monitors, then this can affect the stacking
        layer of this window or others - for fullscreen windows */
@@ -3194,6 +3149,9 @@ void client_fullscreen(ObClient *self, gboolean fs)
 
     if (fs) {
         self->pre_fullscreen_area = self->area;
+        self->pre_fullscreen_max_horz = self->max_horz;
+        self->pre_fullscreen_max_vert = self->max_vert;
+
         /* if the window is maximized, its area isn't all that meaningful.
            save its premax area instead. */
         if (self->max_horz) {
@@ -3215,6 +3173,17 @@ void client_fullscreen(ObClient *self, gboolean fs)
         g_assert(self->pre_fullscreen_area.width > 0 &&
                  self->pre_fullscreen_area.height > 0);
 
+        self->max_horz = self->pre_fullscreen_max_horz;
+        self->max_vert = self->pre_fullscreen_max_vert;
+        if (self->max_horz) {
+            self->pre_max_area.x = self->pre_fullscreen_area.x;
+            self->pre_max_area.width = self->pre_fullscreen_area.width;
+        }
+        if (self->max_vert) {
+            self->pre_max_area.y = self->pre_fullscreen_area.y;
+            self->pre_max_area.height = self->pre_fullscreen_area.height;
+        }
+
         x = self->pre_fullscreen_area.x;
         y = self->pre_fullscreen_area.y;
         w = self->pre_fullscreen_area.width;
@@ -3222,7 +3191,7 @@ void client_fullscreen(ObClient *self, gboolean fs)
         RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0);
     }
 
-    ob_debug("Window %s going fullscreen (%d)\n",
+    ob_debug("Window %s going fullscreen (%d)",
              self->title, self->fullscreen);
 
     client_setup_decor_and_functions(self, FALSE);
@@ -3247,7 +3216,7 @@ static void client_iconify_recursive(ObClient *self,
     gboolean changed = FALSE;
 
     if (self->iconic != iconic) {
-        ob_debug("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"),
+        ob_debug("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
                  self->window);
 
         if (iconic) {
@@ -3423,12 +3392,12 @@ void client_close(ObClient *self)
     if (!self->delete_window)
         /* don't use client_kill(), we should only kill based on PID in
            response to a lack of PING replies */
-        XKillClient(ob_display, self->window);
+        XKillClient(obt_display, self->window);
     else {
         /* request the client to close with WM_DELETE_WINDOW */
-        PROP_MSG_TO(self->window, self->window, wm_protocols,
-                    prop_atoms.wm_delete_window, event_curtime, 0, 0, 0,
-                    NoEventMask);
+        OBT_PROP_MSG_TO(self->window, self->window, WM_PROTOCOLS,
+                        OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime,
+                        0, 0, 0, NoEventMask);
 
         /* we're trying to close the window, so see if it is responding. if it
            is not, then we will let them kill the window */
@@ -3536,14 +3505,14 @@ void client_kill(ObClient *self)
             client_update_title(self);
         }
         else {
-            ob_debug("killing window 0x%x with pid %lu, with SIGKILL\n",
+            ob_debug("killing window 0x%x with pid %lu, with SIGKILL",
                      self->window, self->pid);
             kill(self->pid, SIGKILL); /* kill -9 */
         }
     }
     else {
         /* running on a remote host */
-        XKillClient(ob_display, self->window);
+        XKillClient(obt_display, self->window);
     }
 }
 
@@ -3583,13 +3552,13 @@ static void client_set_desktop_recursive(ObClient *self,
 
     if (target != self->desktop && self->type != OB_CLIENT_TYPE_DESKTOP) {
 
-        ob_debug("Setting desktop %u\n", target+1);
+        ob_debug("Setting desktop %u", target+1);
 
         g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
 
         old = self->desktop;
         self->desktop = target;
-        PROP_SET32(self->window, net_wm_desktop, cardinal, target);
+        OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, target);
         /* the frame can display the current desktop state */
         frame_adjust_state(self->frame);
         /* 'move' the window to the new desktop */
@@ -3650,14 +3619,14 @@ static gboolean client_validate_unmap(ObClient *self, int n)
     XEvent e;
     gboolean ret = TRUE;
 
-    if (XCheckTypedWindowEvent(ob_display, self->window, UnmapNotify, &e)) {
+    if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) {
         if (n < self->ignore_unmaps) // ignore this one, but look for more
             ret = client_validate_unmap(self, n+1);
         else
             ret = FALSE; // the window is going to become unmanaged
 
         /* put them back on the event stack so they end up in the same order */
-        XPutBackEvent(ob_display, &e);
+        XPutBackEvent(obt_display, &e);
     }
 
     return ret;
@@ -3667,10 +3636,10 @@ gboolean client_validate(ObClient *self)
 {
     XEvent e;
 
-    XSync(ob_display, FALSE); /* get all events on the server */
+    XSync(obt_display, FALSE); /* get all events on the server */
 
-    if (XCheckTypedWindowEvent(ob_display, self->window, DestroyNotify, &e)) {
-        XPutBackEvent(ob_display, &e);
+    if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) {
+        XPutBackEvent(obt_display, &e);
         return FALSE;
     }
 
@@ -3707,10 +3676,11 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
     gboolean above = self->above;
     gboolean below = self->below;
     gint i;
+    gboolean value;
 
-    if (!(action == prop_atoms.net_wm_state_add ||
-          action == prop_atoms.net_wm_state_remove ||
-          action == prop_atoms.net_wm_state_toggle))
+    if (!(action == OBT_PROP_ATOM(NET_WM_STATE_ADD) ||
+          action == OBT_PROP_ATOM(NET_WM_STATE_REMOVE) ||
+          action == OBT_PROP_ATOM(NET_WM_STATE_TOGGLE)))
         /* an invalid action was passed to the client message, ignore it */
         return;
 
@@ -3720,105 +3690,69 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
         if (!state) continue;
 
         /* if toggling, then pick whether we're adding or removing */
-        if (action == prop_atoms.net_wm_state_toggle) {
-            if (state == prop_atoms.net_wm_state_modal)
-                action = modal ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_maximized_vert)
-                action = self->max_vert ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_maximized_horz)
-                action = self->max_horz ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_shaded)
-                action = shaded ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_skip_taskbar)
-                action = self->skip_taskbar ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_skip_pager)
-                action = self->skip_pager ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_hidden)
-                action = self->iconic ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_fullscreen)
-                action = fullscreen ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_above)
-                action = self->above ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_below)
-                action = self->below ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.net_wm_state_demands_attention)
-                action = self->demands_attention ?
-                    prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
-            else if (state == prop_atoms.ob_wm_state_undecorated)
-                action = undecorated ? prop_atoms.net_wm_state_remove :
-                    prop_atoms.net_wm_state_add;
+        if (action == OBT_PROP_ATOM(NET_WM_STATE_TOGGLE)) {
+            if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL))
+                value = modal;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT))
+                value = self->max_vert;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ))
+                value = self->max_horz;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED))
+                value = shaded;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR))
+                value = self->skip_taskbar;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER))
+                value = self->skip_pager;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN))
+                value = self->iconic;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN))
+                value = fullscreen;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE))
+                value = self->above;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW))
+                value = self->below;
+            else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION))
+                value = self->demands_attention;
+            else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED))
+                value = undecorated;
+            else
+                g_assert_not_reached();
+            action = value ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) :
+                             OBT_PROP_ATOM(NET_WM_STATE_ADD);
         }
 
-        if (action == prop_atoms.net_wm_state_add) {
-            if (state == prop_atoms.net_wm_state_modal) {
-                modal = TRUE;
-            } else if (state == prop_atoms.net_wm_state_maximized_vert) {
-                max_vert = TRUE;
-            } else if (state == prop_atoms.net_wm_state_maximized_horz) {
-                max_horz = TRUE;
-            } else if (state == prop_atoms.net_wm_state_shaded) {
-                shaded = TRUE;
-            } else if (state == prop_atoms.net_wm_state_skip_taskbar) {
-                self->skip_taskbar = TRUE;
-            } else if (state == prop_atoms.net_wm_state_skip_pager) {
-                self->skip_pager = TRUE;
-            } else if (state == prop_atoms.net_wm_state_hidden) {
-                iconic = TRUE;
-            } else if (state == prop_atoms.net_wm_state_fullscreen) {
-                fullscreen = TRUE;
-            } else if (state == prop_atoms.net_wm_state_above) {
-                above = TRUE;
+        value = action == OBT_PROP_ATOM(NET_WM_STATE_ADD);
+        if (state == OBT_PROP_ATOM(NET_WM_STATE_MODAL)) {
+            modal = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT)) {
+            max_vert = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ)) {
+            max_horz = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SHADED)) {
+            shaded = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR)) {
+            self->skip_taskbar = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER)) {
+            self->skip_pager = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_HIDDEN)) {
+            iconic = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN)) {
+            fullscreen = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_ABOVE)) {
+            above = value;
+            /* only unset below when setting above, otherwise you can't get to
+               the normal layer */
+            if (value)
                 below = FALSE;
-            } else if (state == prop_atoms.net_wm_state_below) {
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_BELOW)) {
+            /* and vice versa */
+            if (value)
                 above = FALSE;
-                below = TRUE;
-            } else if (state == prop_atoms.net_wm_state_demands_attention) {
-                demands_attention = TRUE;
-            } else if (state == prop_atoms.ob_wm_state_undecorated) {
-                undecorated = TRUE;
-            }
-
-        } else { /* action == prop_atoms.net_wm_state_remove */
-            if (state == prop_atoms.net_wm_state_modal) {
-                modal = FALSE;
-            } else if (state == prop_atoms.net_wm_state_maximized_vert) {
-                max_vert = FALSE;
-            } else if (state == prop_atoms.net_wm_state_maximized_horz) {
-                max_horz = FALSE;
-            } else if (state == prop_atoms.net_wm_state_shaded) {
-                shaded = FALSE;
-            } else if (state == prop_atoms.net_wm_state_skip_taskbar) {
-                self->skip_taskbar = FALSE;
-            } else if (state == prop_atoms.net_wm_state_skip_pager) {
-                self->skip_pager = FALSE;
-            } else if (state == prop_atoms.net_wm_state_hidden) {
-                iconic = FALSE;
-            } else if (state == prop_atoms.net_wm_state_fullscreen) {
-                fullscreen = FALSE;
-            } else if (state == prop_atoms.net_wm_state_above) {
-                above = FALSE;
-            } else if (state == prop_atoms.net_wm_state_below) {
-                below = FALSE;
-            } else if (state == prop_atoms.net_wm_state_demands_attention) {
-                demands_attention = FALSE;
-            } else if (state == prop_atoms.ob_wm_state_undecorated) {
-                undecorated = FALSE;
-            }
+            below = value;
+        } else if (state == OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION)){
+            demands_attention = value;
+        } else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED)) {
+            undecorated = value;
         }
     }
 
@@ -3910,47 +3844,47 @@ gboolean client_focus(ObClient *self)
 
     if (!client_can_focus(self)) {
         ob_debug_type(OB_DEBUG_FOCUS,
-                      "Client %s can't be focused\n", self->title);
+                      "Client %s can't be focused", self->title);
         return FALSE;
     }
 
     ob_debug_type(OB_DEBUG_FOCUS,
-                  "Focusing client \"%s\" (0x%x) at time %u\n",
+                  "Focusing client \"%s\" (0x%x) at time %u",
                   self->title, self->window, event_curtime);
 
     /* if using focus_delay, stop the timer now so that focus doesn't
        go moving on us */
     event_halt_focus_delay();
 
-    xerror_set_ignore(TRUE);
-    xerror_occured = FALSE;
+    obt_display_ignore_errors(TRUE);
 
     if (self->can_focus) {
         /* This can cause a BadMatch error with CurrentTime, or if an app
            passed in a bad time for _NET_WM_ACTIVE_WINDOW. */
-        XSetInputFocus(ob_display, self->window, RevertToPointerRoot,
+        XSetInputFocus(obt_display, self->window, RevertToPointerRoot,
                        event_curtime);
     }
 
     if (self->focus_notify) {
         XEvent ce;
         ce.xclient.type = ClientMessage;
-        ce.xclient.message_type = prop_atoms.wm_protocols;
-        ce.xclient.display = ob_display;
+        ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS);
+        ce.xclient.display = obt_display;
         ce.xclient.window = self->window;
         ce.xclient.format = 32;
-        ce.xclient.data.l[0] = prop_atoms.wm_take_focus;
+        ce.xclient.data.l[0] = OBT_PROP_ATOM(WM_TAKE_FOCUS);
         ce.xclient.data.l[1] = event_curtime;
         ce.xclient.data.l[2] = 0l;
         ce.xclient.data.l[3] = 0l;
         ce.xclient.data.l[4] = 0l;
-        XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
+        XSendEvent(obt_display, self->window, FALSE, NoEventMask, &ce);
     }
 
-    xerror_set_ignore(FALSE);
+    obt_display_ignore_errors(FALSE);
 
-    ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d\n", xerror_occured);
-    return !xerror_occured;
+    ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d",
+                  obt_display_error_occured);
+    return !obt_display_error_occured;
 }
 
 static void client_present(ObClient *self, gboolean here, gboolean raise,
@@ -4266,15 +4200,15 @@ static void detect_edge(Rect area, ObDirection dir,
             g_assert_not_reached();
     }
 
-    ob_debug("my head %d size %d\n", my_head, my_size);
-    ob_debug("head %d tail %d dest %d\n", head, tail, *dest);
+    ob_debug("my head %d size %d", my_head, my_size);
+    ob_debug("head %d tail %d dest %d", head, tail, *dest);
     if (!skip_head) {
-        ob_debug("using near edge %d\n", head);
+        ob_debug("using near edge %d", head);
         *dest = head;
         *near_edge = TRUE;
     }
     else if (!skip_tail) {
-        ob_debug("using far edge %d\n", tail);
+        ob_debug("using far edge %d", tail);
         *dest = tail;
         *near_edge = FALSE;
     }
@@ -4323,26 +4257,33 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
     }
 
     /* search for edges of clients */
-    for (it = client_list; it; it = g_list_next(it)) {
-        ObClient *cur = it->data;
+    if (((dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH) &&
+         !self->max_vert) ||
+        ((dir == OB_DIRECTION_EAST || dir == OB_DIRECTION_WEST) &&
+         !self->max_horz))
+    {
+        for (it = client_list; it; it = g_list_next(it)) {
+            ObClient *cur = it->data;
 
-        /* skip windows to not bump into */
-        if (cur == self)
-            continue;
-        if (cur->iconic)
-            continue;
-        if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&
-            cur->desktop != screen_desktop)
-            continue;
+            /* skip windows to not bump into */
+            if (cur == self)
+                continue;
+            if (cur->iconic)
+                continue;
+            if (self->desktop != cur->desktop && cur->desktop != DESKTOP_ALL &&
+                cur->desktop != screen_desktop)
+                continue;
 
-        ob_debug("trying window %s\n", cur->title);
+            ob_debug("trying window %s", cur->title);
 
-        detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start,
+            detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start,
+                        my_edge_size, dest, near_edge);
+        }
+        dock_get_area(&dock_area);
+        detect_edge(dock_area, dir, my_head, my_size, my_edge_start,
                     my_edge_size, dest, near_edge);
     }
-    dock_get_area(&dock_area);
-    detect_edge(dock_area, dir, my_head, my_size, my_edge_start,
-                my_edge_size, dest, near_edge);
+
     g_free(a);
 }
 
@@ -4455,10 +4396,10 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
         g_assert_not_reached();
     }
 
-    ob_debug("head %d dir %d\n", head, dir);
+    ob_debug("head %d dir %d", head, dir);
     client_find_edge_directional(self, dir, head, 1,
                                  e_start, e_size, &e, &near);
-    ob_debug("edge %d\n", e);
+    ob_debug("edge %d", e);
     *x = self->frame->area.x;
     *y = self->frame->area.y;
     *w = self->frame->area.width;
index e5a61d5..5830066 100644 (file)
@@ -25,7 +25,7 @@
 #include "geom.h"
 #include "stacking.h"
 #include "window.h"
-#include "render/color.h"
+#include "obrender/color.h"
 
 #include <glib.h>
 #include <X11/Xlib.h>
@@ -147,6 +147,9 @@ struct _ObClient
     Rect pre_max_area;
     /*! Position and size of the window prior to being fullscreened */
     Rect pre_fullscreen_area;
+    /*! Remember if the window was maximized before going fullscreen */
+    gboolean pre_fullscreen_max_horz,
+             pre_fullscreen_max_vert;
 
     /*! The window's strut
       The strut defines areas of the screen that are marked off-bounds for
@@ -324,15 +327,13 @@ typedef void (*ObClientCallback)(ObClient *client, gpointer data);
 void client_add_destroy_notify(ObClientCallback func, gpointer data);
 void client_remove_destroy_notify(ObClientCallback func);
 
-/*! Manages all existing windows */
-void client_manage_all();
 /*! Manages a given window
   @param prompt This specifies an ObPrompt which is being managed.  It is
                 possible to manage Openbox-owned windows through this.
 */
 void client_manage(Window win, struct _ObPrompt *prompt);
 /*! Unmanages all managed windows */
-void client_unmanage_all();
+void client_unmanage_all(void);
 /*! Unmanages a given client */
 void client_unmanage(ObClient *client);
 
@@ -345,7 +346,7 @@ ObClient *client_fake_manage(Window win);
 void client_fake_unmanage(ObClient *self);
 
 /*! Sets the client list on the root window from the client_list */
-void client_set_list();
+void client_set_list(void);
 
 /*! Determines if the client should be shown or hidden currently.
   @return TRUE if it should be visible; otherwise, FALSE.
@@ -731,7 +732,7 @@ void client_set_layer(ObClient *self, gint layer);
 
 guint client_monitor(ObClient *self);
 
-ObClient* client_under_pointer();
+ObClient* client_under_pointer(void);
 
 gboolean client_has_group_siblings(ObClient *self);
 
index 593010e..f4aae88 100644 (file)
@@ -53,8 +53,8 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
         menu_add_separator(menu, SEPARATOR, screen_desktop_names[desktop]);
         for (it = focus_order; it; it = g_list_next(it)) {
             ObClient *c = it->data;
-            if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&
-                (c->desktop == desktop || c->desktop == DESKTOP_ALL))
+            if (focus_valid_target(c, desktop,
+                                   TRUE, TRUE, FALSE, FALSE, FALSE, FALSE))
             {
                 empty = FALSE;
 
@@ -67,7 +67,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
                     e = menu_add_normal(menu, desktop, c->title, NULL, FALSE);
                 }
 
-                if (config_menu_client_list_icons) {
+                if (config_menu_show_icons) {
                     e->data.normal.icon = client_icon(c);
                     RrImageRef(e->data.normal.icon);
                     e->data.normal.icon_alpha =
@@ -114,10 +114,12 @@ static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
     else {
         ObClient *t = self->data.normal.data;
         if (t) { /* it's set to NULL if its destroyed */
-            client_activate(t, TRUE, FALSE, TRUE, TRUE, TRUE);
+            gboolean here = state & ShiftMask;
+
+            client_activate(t, TRUE, here, TRUE, TRUE, TRUE);
             /* if the window is omnipresent then we need to go to its
                desktop */
-            if (t->desktop == DESKTOP_ALL)
+            if (!here && t->desktop == DESKTOP_ALL)
                 screen_set_desktop(self->id, FALSE);
         }
         else
index 2e87259..2d62c3e 100644 (file)
@@ -54,9 +54,8 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
 
     for (it = focus_order; it; it = g_list_next(it)) {
         ObClient *c = it->data;
-        if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&
-            (c->desktop == d->desktop || c->desktop == DESKTOP_ALL))
-        {
+        if (focus_valid_target(c, d->desktop,
+                               TRUE, TRUE, FALSE, FALSE, FALSE, FALSE)) {
             ObMenuEntry *e;
 
             empty = FALSE;
@@ -70,7 +69,7 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
                 e = menu_add_normal(menu, d->desktop, c->title, NULL, FALSE);
             }
 
-            if (config_menu_client_list_icons) {
+            if (config_menu_show_icons) {
                 e->data.normal.icon = client_icon(c);
                 RrImageRef(e->data.normal.icon);
                 e->data.normal.icon_alpha = c->iconic ? OB_ICONIC_ALPHA : 0xff;
@@ -101,10 +100,12 @@ static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f,
 {
     ObClient *t = self->data.normal.data;
     if (t) { /* it's set to NULL if its destroyed */
-        client_activate(t, TRUE, FALSE, TRUE, TRUE, TRUE);
+        gboolean here = state & ShiftMask;
+
+        client_activate(t, TRUE, here, TRUE, TRUE, TRUE);
         /* if the window is omnipresent then we need to go to its
            desktop */
-        if (t->desktop == DESKTOP_ALL)
+        if (!here && t->desktop == DESKTOP_ALL)
             screen_set_desktop(self->id, FALSE);
     }
     else
index 6c3147a..e70e6c0 100644 (file)
@@ -27,8 +27,8 @@
 #include "frame.h"
 #include "moveresize.h"
 #include "event.h"
-#include "prop.h"
 #include "gettext.h"
+#include "obt/prop.h"
 
 #include <glib.h>
 
@@ -118,7 +118,8 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
     gint x, y;
     gulong ignore_start;
 
-    g_assert(c);
+    if (!c)
+        return;
 
     if (!config_focus_under_mouse)
         ignore_start = event_start_ignore_all_enters();
@@ -150,7 +151,7 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
 
         screen_pointer_pos(&x, &y);
         moveresize_start(c, x, y, 0,
-                         prop_atoms.net_wm_moveresize_move_keyboard);
+                         OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD));
         break;
     case CLIENT_RESIZE:
         /* this needs to grab the keyboard so hide the menu */
@@ -159,7 +160,7 @@ static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f,
 
         screen_pointer_pos(&x, &y);
         moveresize_start(c, x, y, 0,
-                         prop_atoms.net_wm_moveresize_size_keyboard);
+                         OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD));
         break;
     case CLIENT_CLOSE:
         client_close(c);
index fe14502..5c55516 100644 (file)
@@ -19,6 +19,6 @@
 #ifndef ob__client_menu_h
 #define ob__client_menu_h
 
-void client_menu_startup();
+void client_menu_startup(void);
 
 #endif
index 240606a..e7a2440 100644 (file)
 #include "keyboard.h"
 #include "mouse.h"
 #include "actions.h"
-#include "prop.h"
 #include "translate.h"
 #include "client.h"
 #include "screen.h"
-#include "parser/parse.h"
 #include "openbox.h"
 #include "gettext.h"
+#include "obt/paths.h"
 
 gboolean config_focus_new;
 gboolean config_focus_follow;
@@ -35,6 +34,7 @@ guint    config_focus_delay;
 gboolean config_focus_raise;
 gboolean config_focus_last;
 gboolean config_focus_under_mouse;
+gboolean config_unfocus_leave;
 
 ObPlacePolicy  config_place_policy;
 gboolean       config_place_center;
@@ -47,6 +47,7 @@ StrutPartial config_margins;
 
 gchar   *config_theme;
 gboolean config_theme_keepborder;
+guint    config_theme_window_list_icon_size;
 
 gchar   *config_title_layout;
 
@@ -56,7 +57,8 @@ RrFont *config_font_activewindow;
 RrFont *config_font_inactivewindow;
 RrFont *config_font_menuitem;
 RrFont *config_font_menutitle;
-RrFont *config_font_osd;
+RrFont *config_font_activeosd;
+RrFont *config_font_inactiveosd;
 
 guint   config_desktops_num;
 GSList *config_desktops_names;
@@ -92,8 +94,8 @@ guint    config_menu_hide_delay;
 gboolean config_menu_middle;
 guint    config_submenu_show_delay;
 guint    config_submenu_hide_delay;
-gboolean config_menu_client_list_icons;
 gboolean config_menu_manage_desktops;
+gboolean config_menu_show_icons;
 
 GSList *config_menu_files;
 
@@ -147,14 +149,13 @@ void config_app_settings_copy_non_defaults(const ObAppSettings *src,
         dst->pos_given = TRUE;
         dst->pos_force = src->pos_force;
         dst->position = src->position;
-        dst->monitor = src->monitor;
+        /* monitor is copied above */
     }
 }
 
-static void config_parse_gravity_coord(xmlDocPtr doc, xmlNodePtr node,
-                                       GravityCoord *c)
+static void config_parse_gravity_coord(xmlNodePtr node, GravityCoord *c)
 {
-    gchar *s = parse_string(doc, node);
+    gchar *s = obt_xml_node_string(node);
     if (!g_ascii_strcasecmp(s, "center"))
         c->center = TRUE;
     else {
@@ -196,21 +197,47 @@ static void config_parse_gravity_coord(xmlDocPtr doc, xmlNodePtr node,
    the monitor, so <position><x>center</x></position><monitor>2</monitor>
    will center the window on the second monitor.
 */
-static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
-                                   xmlNodePtr node, gpointer data)
+static void parse_per_app_settings(xmlNodePtr node, gpointer d)
 {
-    xmlNodePtr app = parse_find_node("application", node->children);
-    gchar *name = NULL, *class = NULL, *role = NULL, *type = NULL;
-    gboolean name_set, class_set, type_set;
+    xmlNodePtr app = obt_xml_find_node(node->children, "application");
+    gchar *name = NULL, *class = NULL, *role = NULL, *title = NULL,
+        *type_str = NULL;
+    gboolean name_set, class_set, type_set, role_set, title_set;
+    ObClientType type;
     gboolean x_pos_given;
 
     while (app) {
-        name_set = class_set = type_set = x_pos_given = FALSE;
+        x_pos_given = FALSE;
+
+        class_set = obt_xml_attr_string(app, "class", &class);
+        name_set = obt_xml_attr_string(app, "name", &name);
+        type_set = obt_xml_attr_string(app, "type", &type_str);
+        role_set = obt_xml_attr_string(app, "role", &role);
+        title_set = obt_xml_attr_string(app, "title", &title);
+
+        /* validate the type tho */
+        if (type_set) {
+            if (!g_ascii_strcasecmp(type_str, "normal"))
+                type = OB_CLIENT_TYPE_NORMAL;
+            else if (!g_ascii_strcasecmp(type_str, "dialog"))
+                type = OB_CLIENT_TYPE_DIALOG;
+            else if (!g_ascii_strcasecmp(type_str, "splash"))
+                type = OB_CLIENT_TYPE_SPLASH;
+            else if (!g_ascii_strcasecmp(type_str, "utility"))
+                type = OB_CLIENT_TYPE_UTILITY;
+            else if (!g_ascii_strcasecmp(type_str, "menu"))
+                type = OB_CLIENT_TYPE_MENU;
+            else if (!g_ascii_strcasecmp(type_str, "toolbar"))
+                type = OB_CLIENT_TYPE_TOOLBAR;
+            else if (!g_ascii_strcasecmp(type_str, "dock"))
+                type = OB_CLIENT_TYPE_DOCK;
+            else if (!g_ascii_strcasecmp(type_str, "desktop"))
+                type = OB_CLIENT_TYPE_DESKTOP;
+            else
+                type_set = FALSE; /* not valid! */
+        }
 
-        class_set = parse_attr_string("class", app, &class);
-        name_set = parse_attr_string("name", app, &name);
-        type_set = parse_attr_string("type", app, &type);
-        if (class_set || name_set) {
+        if (class_set || name_set || role_set || title_set || type_set) {
             xmlNodePtr n, c;
             ObAppSettings *settings = config_create_app_settings();;
 
@@ -220,76 +247,61 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
             if (class_set)
                 settings->class = g_pattern_spec_new(class);
 
-            if (type_set) {
-                if (!g_ascii_strcasecmp(type, "normal"))
-                    settings->type = OB_CLIENT_TYPE_NORMAL;
-                else if (!g_ascii_strcasecmp(type, "dialog"))
-                    settings->type = OB_CLIENT_TYPE_DIALOG;
-                else if (!g_ascii_strcasecmp(type, "splash"))
-                    settings->type = OB_CLIENT_TYPE_SPLASH;
-                else if (!g_ascii_strcasecmp(type, "utility"))
-                    settings->type = OB_CLIENT_TYPE_UTILITY;
-                else if (!g_ascii_strcasecmp(type, "menu"))
-                    settings->type = OB_CLIENT_TYPE_MENU;
-                else if (!g_ascii_strcasecmp(type, "toolbar"))
-                    settings->type = OB_CLIENT_TYPE_TOOLBAR;
-                else if (!g_ascii_strcasecmp(type, "dock"))
-                    settings->type = OB_CLIENT_TYPE_DOCK;
-                else if (!g_ascii_strcasecmp(type, "desktop"))
-                    settings->type = OB_CLIENT_TYPE_DESKTOP;
-            }
-
-            if (parse_attr_string("role", app, &role))
+            if (role_set)
                 settings->role = g_pattern_spec_new(role);
 
-            if ((n = parse_find_node("decor", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->decor = parse_bool(doc, n);
+            if (title_set)
+                settings->title = g_pattern_spec_new(title);
+
+            if (type_set)
+                settings->type = type;
+
+            if ((n = obt_xml_find_node(app->children, "decor")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->decor = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("shade", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->shade = parse_bool(doc, n);
+            if ((n = obt_xml_find_node(app->children, "shade")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->shade = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("position", app->children))) {
-                if ((c = parse_find_node("x", n->children)))
-                    if (!parse_contains("default", doc, c)) {
-                        config_parse_gravity_coord(doc, c,
-                                                   &settings->position.x);
+            if ((n = obt_xml_find_node(app->children, "position"))) {
+                if ((c = obt_xml_find_node(n->children, "x")))
+                    if (!obt_xml_node_contains(c, "default")) {
+                        config_parse_gravity_coord(c, &settings->position.x);
                         x_pos_given = TRUE;
                     }
 
-                if (x_pos_given && (c = parse_find_node("y", n->children)))
-                    if (!parse_contains("default", doc, c)) {
-                        config_parse_gravity_coord(doc, c,
-                                                   &settings->position.y);
+                if (x_pos_given && (c = obt_xml_find_node(n->children, "y")))
+                    if (!obt_xml_node_contains(c, "default")) {
+                        config_parse_gravity_coord(c, &settings->position.y);
                         settings->pos_given = TRUE;
                     }
 
                 if (settings->pos_given &&
-                    (c = parse_find_node("monitor", n->children)))
-                    if (!parse_contains("default", doc, c)) {
-                        gchar *s = parse_string(doc, c);
+                    (c = obt_xml_find_node(n->children, "monitor")))
+                    if (!obt_xml_node_contains(c, "default")) {
+                        gchar *s = obt_xml_node_string(c);
                         if (!g_ascii_strcasecmp(s, "mouse"))
                             settings->monitor = 0;
                         else
-                            settings->monitor = parse_int(doc, c);
+                            settings->monitor = obt_xml_node_int(c);
                         g_free(s);
                     }
 
-                parse_attr_bool("force", n, &settings->pos_force);
+                obt_xml_attr_bool(n, "force", &settings->pos_force);
             }
 
-            if ((n = parse_find_node("focus", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->focus = parse_bool(doc, n);
+            if ((n = obt_xml_find_node(app->children, "focus")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->focus = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("desktop", app->children))) {
-                if (!parse_contains("default", doc, n)) {
-                    gchar *s = parse_string(doc, n);
+            if ((n = obt_xml_find_node(app->children, "desktop"))) {
+                if (!obt_xml_node_contains(n, "default")) {
+                    gchar *s = obt_xml_node_string(n);
                     if (!g_ascii_strcasecmp(s, "all"))
                         settings->desktop = DESKTOP_ALL;
                     else {
-                        gint i = parse_int(doc, n);
+                        gint i = obt_xml_node_int(n);
                         if (i > 0)
                             settings->desktop = i;
                     }
@@ -297,9 +309,9 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                 }
             }
 
-            if ((n = parse_find_node("layer", app->children)))
-                if (!parse_contains("default", doc, n)) {
-                    gchar *s = parse_string(doc, n);
+            if ((n = obt_xml_find_node(app->children, "layer")))
+                if (!obt_xml_node_contains(n, "default")) {
+                    gchar *s = obt_xml_node_string(n);
                     if (!g_ascii_strcasecmp(s, "above"))
                         settings->layer = 1;
                     else if (!g_ascii_strcasecmp(s, "below"))
@@ -309,25 +321,25 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                     g_free(s);
                 }
 
-            if ((n = parse_find_node("iconic", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->iconic = parse_bool(doc, n);
+            if ((n = obt_xml_find_node(app->children, "iconic")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->iconic = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("skip_pager", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->skip_pager = parse_bool(doc, n);
+            if ((n = obt_xml_find_node(app->children, "skip_pager")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->skip_pager = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("skip_taskbar", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->skip_taskbar = parse_bool(doc, n);
+            if ((n = obt_xml_find_node(app->children, "skip_taskbar")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->skip_taskbar = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("fullscreen", app->children)))
-                if (!parse_contains("default", doc, n))
-                    settings->fullscreen = parse_bool(doc, n);
+            if ((n = obt_xml_find_node(app->children, "fullscreen")))
+                if (!obt_xml_node_contains(n, "default"))
+                    settings->fullscreen = obt_xml_node_bool(n);
 
-            if ((n = parse_find_node("maximized", app->children)))
-                if (!parse_contains("default", doc, n)) {
-                    gchar *s = parse_string(doc, n);
+            if ((n = obt_xml_find_node(app->children, "maximized")))
+                if (!obt_xml_node_contains(n, "default")) {
+                    gchar *s = obt_xml_node_string(n);
                     if (!g_ascii_strcasecmp(s, "horizontal")) {
                         settings->max_horz = TRUE;
                         settings->max_vert = FALSE;
@@ -336,19 +348,20 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
                         settings->max_vert = TRUE;
                     } else
                         settings->max_horz = settings->max_vert =
-                            parse_bool(doc, n);
+                            obt_xml_node_bool(n);
                     g_free(s);
                 }
 
             config_per_app_settings = g_slist_append(config_per_app_settings,
-                                              (gpointer) settings);
+                                                     (gpointer) settings);
             g_free(name);
             g_free(class);
             g_free(role);
-            name = class = role = NULL;
+            g_free(title);
+            name = class = role = title = NULL;
         }
 
-        app = parse_find_node("application", app->next);
+        app = obt_xml_find_node(app->next, "application");
     }
 }
 
@@ -362,34 +375,33 @@ static void parse_per_app_settings(ObParseInst *inst, xmlDocPtr doc,
 
 */
 
-static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                      GList *keylist)
+static void parse_key(xmlNodePtr node, GList *keylist)
 {
     gchar *key;
     xmlNodePtr n;
     gboolean is_chroot = FALSE;
 
-    if (!parse_attr_string("key", node, &key))
+    if (!obt_xml_attr_string(node, "key", &key))
         return;
 
-    parse_attr_bool("chroot", node, &is_chroot);
+    obt_xml_attr_bool(node, "chroot", &is_chroot);
 
     keylist = g_list_append(keylist, key);
 
-    if ((n = parse_find_node("keybind", node->children))) {
+    if ((n = obt_xml_find_node(node->children, "keybind"))) {
         while (n) {
-            parse_key(i, doc, n, keylist);
-            n = parse_find_node("keybind", n->next);
+            parse_key(n, keylist);
+            n = obt_xml_find_node(n->next, "keybind");
         }
     }
-    else if ((n = parse_find_node("action", node->children))) {
+    else if ((n = obt_xml_find_node(node->children, "action"))) {
         while (n) {
             ObActionsAct *action;
 
-            action = actions_parse(i, doc, n);
+            action = actions_parse(n);
             if (action)
                 keyboard_bind(keylist, action);
-            n = parse_find_node("action", n->next);
+            n = obt_xml_find_node(n->next, "action");
         }
     }
 
@@ -400,25 +412,24 @@ static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     keylist = g_list_delete_link(keylist, g_list_last(keylist));
 }
 
-static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                           gpointer data)
+static void parse_keyboard(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
     gchar *key;
 
     keyboard_unbind_all();
 
-    if ((n = parse_find_node("chainQuitKey", node->children))) {
-        key = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node->children, "chainQuitKey"))) {
+        key = obt_xml_node_string(n);
         translate_key(key, &config_keyboard_reset_state,
                       &config_keyboard_reset_keycode);
         g_free(key);
     }
 
-    if ((n = parse_find_node("keybind", node->children)))
+    if ((n = obt_xml_find_node(node->children, "keybind")))
         while (n) {
-            parse_key(i, doc, n, NULL);
-            n = parse_find_node("keybind", n->next);
+            parse_key(n, NULL);
+            n = obt_xml_find_node(n->next, "keybind");
         }
 }
 
@@ -432,8 +443,7 @@ static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 
 */
 
-static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                        gpointer data)
+static void parse_mouse(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n, nbut, nact;
     gchar *buttonstr;
@@ -444,153 +454,158 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
 
     node = node->children;
 
-    if ((n = parse_find_node("dragThreshold", node)))
-        config_mouse_threshold = parse_int(doc, n);
-    if ((n = parse_find_node("doubleClickTime", node)))
-        config_mouse_dclicktime = parse_int(doc, n);
-    if ((n = parse_find_node("screenEdgeWarpTime", node))) {
-        config_mouse_screenedgetime = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "dragThreshold")))
+        config_mouse_threshold = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "doubleClickTime")))
+        config_mouse_dclicktime = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "screenEdgeWarpTime"))) {
+        config_mouse_screenedgetime = obt_xml_node_int(n);
         /* minimum value of 25 for this property, when it is 1 and you hit the
            edge it basically never stops */
         if (config_mouse_screenedgetime && config_mouse_screenedgetime < 25)
             config_mouse_screenedgetime = 25;
     }
 
-    n = parse_find_node("context", node);
+    n = obt_xml_find_node(node, "context");
     while (n) {
-        if (!parse_attr_string("name", n, &contextstr))
+        if (!obt_xml_attr_string(n, "name", &contextstr))
             goto next_n;
-        nbut = parse_find_node("mousebind", n->children);
+        nbut = obt_xml_find_node(n->children, "mousebind");
         while (nbut) {
-            if (!parse_attr_string("button", nbut, &buttonstr))
+            if (!obt_xml_attr_string(nbut, "button", &buttonstr))
                 goto next_nbut;
-            if (parse_attr_contains("press", nbut, "action")) {
+            if (obt_xml_attr_contains(nbut, "action", "press")) {
                 mact = OB_MOUSE_ACTION_PRESS;
-            } else if (parse_attr_contains("release", nbut, "action")) {
+            } else if (obt_xml_attr_contains(nbut, "action", "release")) {
                 mact = OB_MOUSE_ACTION_RELEASE;
-            } else if (parse_attr_contains("click", nbut, "action")) {
+            } else if (obt_xml_attr_contains(nbut, "action", "click")) {
                 mact = OB_MOUSE_ACTION_CLICK;
-            } else if (parse_attr_contains("doubleclick", nbut,"action")) {
+            } else if (obt_xml_attr_contains(nbut, "action","doubleclick")) {
                 mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
-            } else if (parse_attr_contains("drag", nbut, "action")) {
+            } else if (obt_xml_attr_contains(nbut, "action", "drag")) {
                 mact = OB_MOUSE_ACTION_MOTION;
             } else
                 goto next_nbut;
-            nact = parse_find_node("action", nbut->children);
+            nact = obt_xml_find_node(nbut->children, "action");
             while (nact) {
                 ObActionsAct *action;
 
-                if ((action = actions_parse(i, doc, nact)))
+                if ((action = actions_parse(nact)))
                     mouse_bind(buttonstr, contextstr, mact, action);
-                nact = parse_find_node("action", nact->next);
+                nact = obt_xml_find_node(nact->next, "action");
             }
             g_free(buttonstr);
         next_nbut:
-            nbut = parse_find_node("mousebind", nbut->next);
+            nbut = obt_xml_find_node(nbut->next, "mousebind");
         }
         g_free(contextstr);
     next_n:
-        n = parse_find_node("context", n->next);
+        n = obt_xml_find_node(n->next, "context");
     }
 }
 
-static void parse_focus(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                        gpointer data)
+static void parse_focus(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("focusNew", node)))
-        config_focus_new = parse_bool(doc, n);
-    if ((n = parse_find_node("followMouse", node)))
-        config_focus_follow = parse_bool(doc, n);
-    if ((n = parse_find_node("focusDelay", node)))
-        config_focus_delay = parse_int(doc, n);
-    if ((n = parse_find_node("raiseOnFocus", node)))
-        config_focus_raise = parse_bool(doc, n);
-    if ((n = parse_find_node("focusLast", node)))
-        config_focus_last = parse_bool(doc, n);
-    if ((n = parse_find_node("underMouse", node)))
-        config_focus_under_mouse = parse_bool(doc, n);
+    if ((n = obt_xml_find_node(node, "focusNew")))
+        config_focus_new = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "followMouse")))
+        config_focus_follow = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "focusDelay")))
+        config_focus_delay = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "raiseOnFocus")))
+        config_focus_raise = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "focusLast")))
+        config_focus_last = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "underMouse")))
+        config_focus_under_mouse = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "unfocusOnLeave")))
+        config_unfocus_leave = obt_xml_node_bool(n);
 }
 
-static void parse_placement(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                            gpointer data)
+static void parse_placement(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("policy", node)))
-        if (parse_contains("UnderMouse", doc, n))
+    if ((n = obt_xml_find_node(node, "policy")))
+        if (obt_xml_node_contains(n, "UnderMouse"))
             config_place_policy = OB_PLACE_POLICY_MOUSE;
-    if ((n = parse_find_node("center", node)))
-        config_place_center = parse_bool(doc, n);
-    if ((n = parse_find_node("monitor", node))) {
-        if (parse_contains("active", doc, n))
+    if ((n = obt_xml_find_node(node, "center")))
+        config_place_center = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "monitor"))) {
+        if (obt_xml_node_contains(n, "active"))
             config_place_monitor = OB_PLACE_MONITOR_ACTIVE;
-        else if (parse_contains("mouse", doc, n))
+        else if (obt_xml_node_contains(n, "mouse"))
             config_place_monitor = OB_PLACE_MONITOR_MOUSE;
     }
-    if ((n = parse_find_node("primaryMonitor", node))) {
-        config_primary_monitor_index = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "primaryMonitor"))) {
+        config_primary_monitor_index = obt_xml_node_int(n);
         if (!config_primary_monitor_index) {
-            if (parse_contains("mouse", doc, n))
+            if (obt_xml_node_contains(n, "mouse"))
                 config_primary_monitor = OB_PLACE_MONITOR_MOUSE;
         }
     }
 }
 
-static void parse_margins(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                          gpointer data)
+static void parse_margins(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("top", node)))
-        config_margins.top = MAX(0, parse_int(doc, n));
-    if ((n = parse_find_node("left", node)))
-        config_margins.left = MAX(0, parse_int(doc, n));
-    if ((n = parse_find_node("right", node)))
-        config_margins.right = MAX(0, parse_int(doc, n));
-    if ((n = parse_find_node("bottom", node)))
-        config_margins.bottom = MAX(0, parse_int(doc, n));
+    if ((n = obt_xml_find_node(node, "top")))
+        config_margins.top = MAX(0, obt_xml_node_int(n));
+    if ((n = obt_xml_find_node(node, "left")))
+        config_margins.left = MAX(0, obt_xml_node_int(n));
+    if ((n = obt_xml_find_node(node, "right")))
+        config_margins.right = MAX(0, obt_xml_node_int(n));
+    if ((n = obt_xml_find_node(node, "bottom")))
+        config_margins.bottom = MAX(0, obt_xml_node_int(n));
 }
 
-static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                        gpointer data)
+static void parse_theme(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("name", node))) {
+    if ((n = obt_xml_find_node(node, "name"))) {
         gchar *c;
 
         g_free(config_theme);
-        c = parse_string(doc, n);
-        config_theme = parse_expand_tilde(c);
+        c = obt_xml_node_string(n);
+        config_theme = obt_paths_expand_tilde(c);
         g_free(c);
     }
-    if ((n = parse_find_node("titleLayout", node))) {
+    if ((n = obt_xml_find_node(node, "titleLayout"))) {
         gchar *c, *d;
 
         g_free(config_title_layout);
-        config_title_layout = parse_string(doc, n);
+        config_title_layout = obt_xml_node_string(n);
 
         /* replace duplicates with spaces */
         for (c = config_title_layout; *c != '\0'; ++c)
             for (d = c+1; *d != '\0'; ++d)
                 if (*c == *d) *d = ' ';
     }
-    if ((n = parse_find_node("keepBorder", node)))
-        config_theme_keepborder = parse_bool(doc, n);
-    if ((n = parse_find_node("animateIconify", node)))
-        config_animate_iconify = parse_bool(doc, n);
+    if ((n = obt_xml_find_node(node, "keepBorder")))
+        config_theme_keepborder = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "animateIconify")))
+        config_animate_iconify = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "windowListIconSize"))) {
+        config_theme_window_list_icon_size = obt_xml_node_int(n);
+        if (config_theme_window_list_icon_size < 16)
+            config_theme_window_list_icon_size = 16;
+        else if (config_theme_window_list_icon_size > 96)
+            config_theme_window_list_icon_size = 96;
+    }
 
-    n = parse_find_node("font", node);
+    n = obt_xml_find_node(node, "font");
     while (n) {
         xmlNodePtr   fnode;
         RrFont     **font;
@@ -599,35 +614,39 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         RrFontWeight weight = RrDefaultFontWeight;
         RrFontSlant  slant = RrDefaultFontSlant;
 
-        if (parse_attr_contains("ActiveWindow", n, "place"))
+        if (obt_xml_attr_contains(n, "place", "ActiveWindow"))
             font = &config_font_activewindow;
-        else if (parse_attr_contains("InactiveWindow", n, "place"))
+        else if (obt_xml_attr_contains(n, "place", "InactiveWindow"))
             font = &config_font_inactivewindow;
-        else if (parse_attr_contains("MenuHeader", n, "place"))
+        else if (obt_xml_attr_contains(n, "place", "MenuHeader"))
             font = &config_font_menutitle;
-        else if (parse_attr_contains("MenuItem", n, "place"))
+        else if (obt_xml_attr_contains(n, "place", "MenuItem"))
             font = &config_font_menuitem;
-        else if (parse_attr_contains("OnScreenDisplay", n, "place"))
-            font = &config_font_osd;
+        else if (obt_xml_attr_contains(n, "place", "ActiveOnScreenDisplay"))
+            font = &config_font_activeosd;
+        else if (obt_xml_attr_contains(n, "place", "OnScreenDisplay"))
+            font = &config_font_activeosd;
+        else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
+            font = &config_font_inactiveosd;
         else
             goto next_font;
 
-        if ((fnode = parse_find_node("name", n->children))) {
+        if ((fnode = obt_xml_find_node(n->children, "name"))) {
             g_free(name);
-            name = parse_string(doc, fnode);
+            name = obt_xml_node_string(fnode);
         }
-        if ((fnode = parse_find_node("size", n->children))) {
-            int s = parse_int(doc, fnode);
+        if ((fnode = obt_xml_find_node(n->children, "size"))) {
+            int s = obt_xml_node_int(fnode);
             if (s > 0) size = s;
         }
-        if ((fnode = parse_find_node("weight", n->children))) {
-            gchar *w = parse_string(doc, fnode);
+        if ((fnode = obt_xml_find_node(n->children, "weight"))) {
+            gchar *w = obt_xml_node_string(fnode);
             if (!g_ascii_strcasecmp(w, "Bold"))
                 weight = RR_FONTWEIGHT_BOLD;
             g_free(w);
         }
-        if ((fnode = parse_find_node("slant", n->children))) {
-            gchar *s = parse_string(doc, fnode);
+        if ((fnode = obt_xml_find_node(n->children, "slant"))) {
+            gchar *s = obt_xml_node_string(fnode);
             if (!g_ascii_strcasecmp(s, "Italic"))
                 slant = RR_FONTSLANT_ITALIC;
             if (!g_ascii_strcasecmp(s, "Oblique"))
@@ -638,28 +657,27 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         *font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
         g_free(name);
     next_font:
-        n = parse_find_node("font", n->next);
+        n = obt_xml_find_node(n->next, "font");
     }
 }
 
-static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                           gpointer data)
+static void parse_desktops(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("number", node))) {
-        gint d = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "number"))) {
+        gint d = obt_xml_node_int(n);
         if (d > 0)
             config_desktops_num = (unsigned) d;
     }
-    if ((n = parse_find_node("firstdesk", node))) {
-        gint d = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "firstdesk"))) {
+        gint d = obt_xml_node_int(n);
         if (d > 0)
             config_screen_firstdesk = (unsigned) d;
     }
-    if ((n = parse_find_node("names", node))) {
+    if ((n = obt_xml_find_node(node, "names"))) {
         GSList *it;
         xmlNodePtr nname;
 
@@ -668,51 +686,51 @@ static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
         g_slist_free(config_desktops_names);
         config_desktops_names = NULL;
 
-        nname = parse_find_node("name", n->children);
+        nname = obt_xml_find_node(n->children, "name");
         while (nname) {
-            config_desktops_names = g_slist_append(config_desktops_names,
-                                                   parse_string(doc, nname));
-            nname = parse_find_node("name", nname->next);
+            config_desktops_names =
+                g_slist_append(config_desktops_names,
+                               obt_xml_node_string(nname));
+            nname = obt_xml_find_node(nname->next, "name");
         }
     }
-    if ((n = parse_find_node("popupTime", node)))
-        config_desktop_popup_time = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "popupTime")))
+        config_desktop_popup_time = obt_xml_node_int(n);
 }
 
-static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                         gpointer data)
+static void parse_resize(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("drawContents", node)))
-        config_resize_redraw = parse_bool(doc, n);
-    if ((n = parse_find_node("popupShow", node))) {
-        config_resize_popup_show = parse_int(doc, n);
-        if (parse_contains("Always", doc, n))
+    if ((n = obt_xml_find_node(node, "drawContents")))
+        config_resize_redraw = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "popupShow"))) {
+        config_resize_popup_show = obt_xml_node_int(n);
+        if (obt_xml_node_contains(n, "Always"))
             config_resize_popup_show = 2;
-        else if (parse_contains("Never", doc, n))
+        else if (obt_xml_node_contains(n, "Never"))
             config_resize_popup_show = 0;
-        else if (parse_contains("Nonpixel", doc, n))
+        else if (obt_xml_node_contains(n, "Nonpixel"))
             config_resize_popup_show = 1;
     }
-    if ((n = parse_find_node("popupPosition", node))) {
-        if (parse_contains("Top", doc, n))
+    if ((n = obt_xml_find_node(node, "popupPosition"))) {
+        if (obt_xml_node_contains(n, "Top"))
             config_resize_popup_pos = OB_RESIZE_POS_TOP;
-        else if (parse_contains("Center", doc, n))
+        else if (obt_xml_node_contains(n, "Center"))
             config_resize_popup_pos = OB_RESIZE_POS_CENTER;
-        else if (parse_contains("Fixed", doc, n)) {
+        else if (obt_xml_node_contains(n, "Fixed")) {
             config_resize_popup_pos = OB_RESIZE_POS_FIXED;
 
-            if ((n = parse_find_node("popupFixedPosition", node))) {
+            if ((n = obt_xml_find_node(node, "popupFixedPosition"))) {
                 xmlNodePtr n2;
 
-                if ((n2 = parse_find_node("x", n->children)))
-                    config_parse_gravity_coord(doc, n2,
+                if ((n2 = obt_xml_find_node(n->children, "x")))
+                    config_parse_gravity_coord(n2,
                                                &config_resize_popup_fixed.x);
-                if ((n2 = parse_find_node("y", n->children)))
-                    config_parse_gravity_coord(doc, n2,
+                if ((n2 = obt_xml_find_node(n->children, "y")))
+                    config_parse_gravity_coord(n2,
                                                &config_resize_popup_fixed.y);
 
                 config_resize_popup_fixed.x.pos =
@@ -724,72 +742,71 @@ static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     }
 }
 
-static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                       gpointer data)
+static void parse_dock(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
 
-    if ((n = parse_find_node("position", node))) {
-        if (parse_contains("TopLeft", doc, n))
+    if ((n = obt_xml_find_node(node, "position"))) {
+        if (obt_xml_node_contains(n, "TopLeft"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_NORTHWEST;
-        else if (parse_contains("Top", doc, n))
+        else if (obt_xml_node_contains(n, "Top"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_NORTH;
-        else if (parse_contains("TopRight", doc, n))
+        else if (obt_xml_node_contains(n, "TopRight"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_NORTHEAST;
-        else if (parse_contains("Right", doc, n))
+        else if (obt_xml_node_contains(n, "Right"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_EAST;
-        else if (parse_contains("BottomRight", doc, n))
+        else if (obt_xml_node_contains(n, "BottomRight"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_SOUTHEAST;
-        else if (parse_contains("Bottom", doc, n))
+        else if (obt_xml_node_contains(n, "Bottom"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_SOUTH;
-        else if (parse_contains("BottomLeft", doc, n))
+        else if (obt_xml_node_contains(n, "BottomLeft"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_SOUTHWEST;
-        else if (parse_contains("Left", doc, n))
+        else if (obt_xml_node_contains(n, "Left"))
             config_dock_floating = FALSE,
             config_dock_pos = OB_DIRECTION_WEST;
-        else if (parse_contains("Floating", doc, n))
+        else if (obt_xml_node_contains(n, "Floating"))
             config_dock_floating = TRUE;
     }
     if (config_dock_floating) {
-        if ((n = parse_find_node("floatingX", node)))
-            config_dock_x = parse_int(doc, n);
-        if ((n = parse_find_node("floatingY", node)))
-            config_dock_y = parse_int(doc, n);
+        if ((n = obt_xml_find_node(node, "floatingX")))
+            config_dock_x = obt_xml_node_int(n);
+        if ((n = obt_xml_find_node(node, "floatingY")))
+            config_dock_y = obt_xml_node_int(n);
     } else {
-        if ((n = parse_find_node("noStrut", node)))
-            config_dock_nostrut = parse_bool(doc, n);
+        if ((n = obt_xml_find_node(node, "noStrut")))
+            config_dock_nostrut = obt_xml_node_bool(n);
     }
-    if ((n = parse_find_node("stacking", node))) {
-        if (parse_contains("above", doc, n))
-            config_dock_layer = OB_STACKING_LAYER_ABOVE;
-        else if (parse_contains("normal", doc, n))
+    if ((n = obt_xml_find_node(node, "stacking"))) {
+        if (obt_xml_node_contains(n, "normal"))
             config_dock_layer = OB_STACKING_LAYER_NORMAL;
-        else if (parse_contains("below", doc, n))
+        else if (obt_xml_node_contains(n, "below"))
             config_dock_layer = OB_STACKING_LAYER_BELOW;
+        else if (obt_xml_node_contains(n, "above"))
+            config_dock_layer = OB_STACKING_LAYER_ABOVE;
     }
-    if ((n = parse_find_node("direction", node))) {
-        if (parse_contains("horizontal", doc, n))
+    if ((n = obt_xml_find_node(node, "direction"))) {
+        if (obt_xml_node_contains(n, "horizontal"))
             config_dock_orient = OB_ORIENTATION_HORZ;
-        else if (parse_contains("vertical", doc, n))
+        else if (obt_xml_node_contains(n, "vertical"))
             config_dock_orient = OB_ORIENTATION_VERT;
     }
-    if ((n = parse_find_node("autoHide", node)))
-        config_dock_hide = parse_bool(doc, n);
-    if ((n = parse_find_node("hideDelay", node)))
-        config_dock_hide_delay = parse_int(doc, n);
-    if ((n = parse_find_node("showDelay", node)))
-        config_dock_show_delay = parse_int(doc, n);
-    if ((n = parse_find_node("moveButton", node))) {
-        gchar *str = parse_string(doc, n);
+    if ((n = obt_xml_find_node(node, "autoHide")))
+        config_dock_hide = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "hideDelay")))
+        config_dock_hide_delay = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "showDelay")))
+        config_dock_show_delay = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "moveButton"))) {
+        gchar *str = obt_xml_node_string(n);
         guint b, s;
         if (translate_button(str, &s, &b)) {
             config_dock_app_move_button = b;
@@ -801,44 +818,47 @@ static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
     }
 }
 
-static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                       gpointer data)
+static void parse_menu(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
     node = node->children;
 
-    if ((n = parse_find_node("hideDelay", node)))
-        config_menu_hide_delay = parse_int(doc, n);
-    if ((n = parse_find_node("middle", node)))
-        config_menu_middle = parse_bool(doc, n);
-    if ((n = parse_find_node("submenuShowDelay", node)))
-        config_submenu_show_delay = parse_int(doc, n);
-    if ((n = parse_find_node("submenuHideDelay", node)))
-        config_submenu_hide_delay = parse_int(doc, n);
-    if ((n = parse_find_node("applicationIcons", node)))
-        config_menu_client_list_icons = parse_bool(doc, n);
-    if ((n = parse_find_node("manageDesktops", node)))
-        config_menu_manage_desktops = parse_bool(doc, n);
-
-    while ((node = parse_find_node("file", node))) {
-            gchar *c = parse_string(doc, node);
+    if ((n = obt_xml_find_node(node, "hideDelay")))
+        config_menu_hide_delay = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "middle")))
+        config_menu_middle = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "submenuShowDelay")))
+        config_submenu_show_delay = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "submenuHideDelay")))
+        config_submenu_hide_delay = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "manageDesktops")))
+        config_menu_manage_desktops = obt_xml_node_bool(n);
+    if ((n = obt_xml_find_node(node, "showIcons"))) {
+        config_menu_show_icons = obt_xml_node_bool(n);
+#ifndef USE_IMLIB2
+        if (config_menu_show_icons)
+            g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded."));
+#endif
+    }
+
+    while ((node = obt_xml_find_node(node, "file"))) {
+            gchar *c = obt_xml_node_string(node);
             config_menu_files = g_slist_append(config_menu_files,
-                                               parse_expand_tilde(c));
+                                               obt_paths_expand_tilde(c));
             g_free(c);
             node = node->next;
     }
 }
 
-static void parse_resistance(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                             gpointer data)
+static void parse_resistance(xmlNodePtr node, gpointer d)
 {
     xmlNodePtr n;
 
     node = node->children;
-    if ((n = parse_find_node("strength", node)))
-        config_resist_win = parse_int(doc, n);
-    if ((n = parse_find_node("screen_edge_strength", node)))
-        config_resist_edge = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node, "strength")))
+        config_resist_win = obt_xml_node_int(n);
+    if ((n = obt_xml_find_node(node, "screen_edge_strength")))
+        config_resist_edge = obt_xml_node_int(n);
 }
 
 typedef struct
@@ -929,7 +949,7 @@ static void bind_default_mouse(void)
                    actions_parse_string(it->actname));
 }
 
-void config_startup(ObParseInst *i)
+void config_startup(ObtXmlInst *i)
 {
     config_focus_new = TRUE;
     config_focus_follow = FALSE;
@@ -937,8 +957,9 @@ void config_startup(ObParseInst *i)
     config_focus_raise = FALSE;
     config_focus_last = TRUE;
     config_focus_under_mouse = FALSE;
+    config_unfocus_leave = FALSE;
 
-    parse_register(i, "focus", parse_focus, NULL);
+    obt_xml_register(i, "focus", parse_focus, NULL);
 
     config_place_policy = OB_PLACE_POLICY_SMART;
     config_place_center = TRUE;
@@ -947,31 +968,34 @@ void config_startup(ObParseInst *i)
     config_primary_monitor_index = 1;
     config_primary_monitor = OB_PLACE_MONITOR_ACTIVE;
 
-    parse_register(i, "placement", parse_placement, NULL);
+    obt_xml_register(i, "placement", parse_placement, NULL);
 
     STRUT_PARTIAL_SET(config_margins, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
-    parse_register(i, "margins", parse_margins, NULL);
+    obt_xml_register(i, "margins", parse_margins, NULL);
 
     config_theme = NULL;
 
     config_animate_iconify = TRUE;
     config_title_layout = g_strdup("NLIMC");
     config_theme_keepborder = TRUE;
+    config_theme_window_list_icon_size = 36;
 
     config_font_activewindow = NULL;
     config_font_inactivewindow = NULL;
     config_font_menuitem = NULL;
     config_font_menutitle = NULL;
+    config_font_activeosd = NULL;
+    config_font_inactiveosd = NULL;
 
-    parse_register(i, "theme", parse_theme, NULL);
+    obt_xml_register(i, "theme", parse_theme, NULL);
 
     config_desktops_num = 4;
     config_screen_firstdesk = 1;
     config_desktops_names = NULL;
     config_desktop_popup_time = 875;
 
-    parse_register(i, "desktops", parse_desktops, NULL);
+    obt_xml_register(i, "desktops", parse_desktops, NULL);
 
     config_resize_redraw = TRUE;
     config_resize_popup_show = 1; /* nonpixel increments */
@@ -979,7 +1003,7 @@ void config_startup(ObParseInst *i)
     GRAVITY_COORD_SET(config_resize_popup_fixed.x, 0, FALSE, FALSE);
     GRAVITY_COORD_SET(config_resize_popup_fixed.y, 0, FALSE, FALSE);
 
-    parse_register(i, "resize", parse_resize, NULL);
+    obt_xml_register(i, "resize", parse_resize, NULL);
 
     config_dock_layer = OB_STACKING_LAYER_ABOVE;
     config_dock_pos = OB_DIRECTION_NORTHEAST;
@@ -994,14 +1018,14 @@ void config_startup(ObParseInst *i)
     config_dock_app_move_button = 2; /* middle */
     config_dock_app_move_modifiers = 0;
 
-    parse_register(i, "dock", parse_dock, NULL);
+    obt_xml_register(i, "dock", parse_dock, NULL);
 
     translate_key("C-g", &config_keyboard_reset_state,
                   &config_keyboard_reset_keycode);
 
     bind_default_keyboard();
 
-    parse_register(i, "keyboard", parse_keyboard, NULL);
+    obt_xml_register(i, "keyboard", parse_keyboard, NULL);
 
     config_mouse_threshold = 8;
     config_mouse_dclicktime = 200;
@@ -1009,26 +1033,26 @@ void config_startup(ObParseInst *i)
 
     bind_default_mouse();
 
-    parse_register(i, "mouse", parse_mouse, NULL);
+    obt_xml_register(i, "mouse", parse_mouse, NULL);
 
     config_resist_win = 10;
     config_resist_edge = 20;
 
-    parse_register(i, "resistance", parse_resistance, NULL);
+    obt_xml_register(i, "resistance", parse_resistance, NULL);
 
     config_menu_hide_delay = 250;
     config_menu_middle = FALSE;
     config_submenu_show_delay = 200;
     config_submenu_hide_delay = 400;
-    config_menu_client_list_icons = TRUE;
     config_menu_manage_desktops = TRUE;
     config_menu_files = NULL;
+    config_menu_show_icons = TRUE;
 
-    parse_register(i, "menu", parse_menu, NULL);
+    obt_xml_register(i, "menu", parse_menu, NULL);
 
     config_per_app_settings = NULL;
 
-    parse_register(i, "applications", parse_per_app_settings, NULL);
+    obt_xml_register(i, "applications", parse_per_app_settings, NULL);
 }
 
 void config_shutdown(void)
@@ -1043,7 +1067,8 @@ void config_shutdown(void)
     RrFontClose(config_font_inactivewindow);
     RrFontClose(config_font_menuitem);
     RrFontClose(config_font_menutitle);
-    RrFontClose(config_font_osd);
+    RrFontClose(config_font_activeosd);
+    RrFontClose(config_font_inactiveosd);
 
     for (it = config_desktops_names; it; it = g_slist_next(it))
         g_free(it->data);
@@ -1057,6 +1082,7 @@ void config_shutdown(void)
         ObAppSettings *itd = (ObAppSettings *)it->data;
         if (itd->name)  g_pattern_spec_free(itd->name);
         if (itd->role)  g_pattern_spec_free(itd->role);
+        if (itd->title) g_pattern_spec_free(itd->title);
         if (itd->class) g_pattern_spec_free(itd->class);
         g_free(it->data);
     }
index 7713936..818dcc7 100644 (file)
 #include "client.h"
 #include "geom.h"
 #include "moveresize.h"
-#include "render/render.h"
+#include "obrender/render.h"
+#include "obt/xml.h"
 
 #include <glib.h>
 
-struct _ObParseInst;
-
 typedef struct _ObAppSettings ObAppSettings;
 
 struct _ObAppSettings
@@ -39,6 +38,7 @@ struct _ObAppSettings
     GPatternSpec *class;
     GPatternSpec *name;
     GPatternSpec *role;
+    GPatternSpec *title;
     ObClientType  type;
 
     GravityPoint position;
@@ -74,6 +74,9 @@ extern gboolean config_focus_last;
 /*! Try keep focus on the window under the mouse when the mouse is not moving
  */
 extern gboolean config_focus_under_mouse;
+/*! Remove focus from windows when the mouse leaves them
+ */
+extern gboolean config_unfocus_leave;
 
 /*! The algorithm to use for placing new windows */
 extern ObPlacePolicy config_place_policy;
@@ -139,6 +142,8 @@ extern gboolean config_theme_keepborder;
 extern gchar *config_title_layout;
 /*! Animate windows iconifying and restoring */
 extern gboolean config_animate_iconify;
+/*! Size of icons in focus switching dialogs */
+extern guint config_theme_window_list_icon_size;
 
 /*! The font for the active window's title */
 extern RrFont *config_font_activewindow;
@@ -148,8 +153,10 @@ extern RrFont *config_font_inactivewindow;
 extern RrFont *config_font_menutitle;
 /*! The font for menu items */
 extern RrFont *config_font_menuitem;
-/*! The font for on-screen-displays/popups */
-extern RrFont *config_font_osd;
+/*! The font for on-screen-displays/popups' active text */
+extern RrFont *config_font_activeosd;
+/*! The font for on-screen-displays/popups' inactive text */
+extern RrFont *config_font_inactiveosd;
 
 /*! The number of desktops */
 extern guint config_desktops_num;
@@ -187,20 +194,20 @@ extern gboolean config_menu_middle;
 extern guint    config_submenu_show_delay;
 /*! Delay before closing a submenu in milliseconds */
 extern guint    config_submenu_hide_delay;
-/*! Show icons in client_list_menu */
-extern gboolean config_menu_client_list_icons;
 /*! Show manage desktops in client_list_menu */
 extern gboolean config_menu_manage_desktops;
+/*! Load & show icons in user-defined menus */
+extern gboolean config_menu_show_icons;
 /*! User-specified menu files */
 extern GSList *config_menu_files;
 /*! Per app settings */
 extern GSList *config_per_app_settings;
 
-void config_startup(struct _ObParseInst *i);
-void config_shutdown();
+void config_startup(ObtXmlInst *i);
+void config_shutdown(void);
 
 /*! Create an ObAppSettings structure with the default values */
-ObAppSettings* config_create_app_settings();
+ObAppSettings* config_create_app_settings(void);
 /*! Copies any settings in src to dest, if they are their default value in
   src. */
 void config_app_settings_copy_non_defaults(const ObAppSettings *src,
index 0fceba4..8423e8a 100644 (file)
 */
 
 #include "debug.h"
+#include "prompt.h"
+#include "openbox.h"
+#include "gettext.h"
+#include "obt/paths.h"
 
 #include <glib.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <errno.h>
 
-static gboolean show;
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
 
-void ob_debug_show_output(gboolean enable)
+static gboolean  enabled_types[OB_DEBUG_TYPE_NUM] = {FALSE};
+static FILE     *log_file = NULL;
+static guint     rr_handler_id = 0;
+static guint     obt_handler_id = 0;
+static guint     ob_handler_id = 0;
+static guint     ob_handler_prompt_id = 0;
+
+static void log_handler(const gchar *log_domain, GLogLevelFlags log_level,
+                        const gchar *message, gpointer user_data);
+static void prompt_handler(const gchar *log_domain, GLogLevelFlags log_level,
+                           const gchar *message, gpointer user_data);
+
+void ob_debug_startup(void)
 {
-    show = enable;
+    ObtPaths *p = obt_paths_new();
+    gchar *dir = g_build_filename(obt_paths_cache_home(p),
+                                  "openbox", NULL);
+
+    /* log messages to a log file!  fancy, no? */
+    if (!obt_paths_mkdir_path(dir, 0777))
+        g_message(_("Unable to make directory '%s': %s"),
+                  dir, g_strerror(errno));
+    else {
+        gchar *name = g_build_filename(obt_paths_cache_home(p),
+                                       "openbox", "openbox.log", NULL);
+        /* unlink it before opening to remove competition */
+        unlink(name);
+        log_file = fopen(name, "w");
+        g_free(name);
+    }
+
+    rr_handler_id =
+        g_log_set_handler("ObRender", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL |
+                          G_LOG_FLAG_RECURSION, log_handler, NULL);
+    obt_handler_id =
+        g_log_set_handler("Obt", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL |
+                          G_LOG_FLAG_RECURSION, log_handler, NULL);
+    ob_handler_id =
+        g_log_set_handler("Openbox", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL |
+                          G_LOG_FLAG_RECURSION, log_handler, NULL);
+    ob_handler_prompt_id =
+        g_log_set_handler("Openbox", G_LOG_LEVEL_MASK & ~G_LOG_LEVEL_DEBUG,
+                          prompt_handler, NULL);
+
+    obt_paths_unref(p);
+    g_free(dir);
 }
 
-void ob_debug(const gchar *a, ...)
+void ob_debug_shutdown(void)
 {
-    va_list vl;
-
-    if (show) {
-        fprintf(stderr, "DEBUG: ");
-        va_start(vl, a);
-        vfprintf(stderr, a, vl);
-        va_end(vl);
+    g_log_remove_handler("ObRender", rr_handler_id);
+    g_log_remove_handler("Obt", obt_handler_id);
+    g_log_remove_handler("Openbox", ob_handler_id);
+    g_log_remove_handler("Openbox", ob_handler_prompt_id);
+
+    if (log_file) {
+        fclose(log_file);
+        log_file = NULL;
     }
 }
 
-static gboolean enabled_types[OB_DEBUG_TYPE_NUM] = {FALSE};
-
 void ob_debug_enable(ObDebugType type, gboolean enable)
 {
     g_assert(type < OB_DEBUG_TYPE_NUM);
     enabled_types[type] = enable;
 }
 
-void ob_debug_type(ObDebugType type, const gchar *a, ...)
+static inline void log_print(FILE *out, const gchar* log_domain,
+                             const gchar *level, const gchar *message)
 {
-    va_list vl;
+    fprintf(out, "%s", log_domain);
+    fprintf(out, "-");
+    fprintf(out, "%s", level);
+    fprintf(out, ": ");
+    fprintf(out, "%s", message);
+    fprintf(out, "\n");
+    fflush(out);
+}
+
+static void log_handler(const gchar *log_domain, GLogLevelFlags log_level,
+                        const gchar *message, gpointer data)
+{
+    FILE *out;
+    const gchar *level;
+
+    switch (log_level & G_LOG_LEVEL_MASK) {
+    case G_LOG_LEVEL_DEBUG:    level = "Debug";    out = stdout; break;
+    case G_LOG_LEVEL_INFO:     level = "Info";     out = stdout; break;
+    case G_LOG_LEVEL_MESSAGE:  level = "Message";  out = stdout; break;
+    case G_LOG_LEVEL_WARNING:  level = "Warning";  out = stderr; break;
+    case G_LOG_LEVEL_CRITICAL: level = "Critical"; out = stderr; break;
+    case G_LOG_LEVEL_ERROR:    level = "Error";    out = stderr; break;
+    default:                   g_assert_not_reached(); /* invalid level.. */
+    }
+
+    log_print(out, log_domain, level, message);
+    if (log_file) log_print(log_file, log_domain, level, message);
+}
+
+static void prompt_handler(const gchar *log_domain, GLogLevelFlags log_level,
+                           const gchar *message, gpointer data)
+{
+    if (ob_state() == OB_STATE_RUNNING)
+        prompt_show_message(message, _("Openbox"), _("Close"));
+    else
+        log_handler(log_domain, log_level, message, data);
+}
+
+static inline void log_argv(ObDebugType type,
+                            const gchar *format, va_list args)
+{
+    const gchar *prefix;
+    gchar *message;
 
     g_assert(type < OB_DEBUG_TYPE_NUM);
+    if (!enabled_types[type]) return;
+
+    switch (type) {
+    case OB_DEBUG_FOCUS:    prefix = "(FOCUS) ";           break;
+    case OB_DEBUG_APP_BUGS: prefix = "(APPLICATION BUG) "; break;
+    case OB_DEBUG_SM:       prefix = "(SESSION) ";         break;
+    default:                prefix = NULL;                 break;
+    }
 
-    if (show && enabled_types[type]) {
-        switch (type) {
-        case OB_DEBUG_FOCUS:
-            fprintf(stderr, "FOCUS: ");
-            break;
-        case OB_DEBUG_APP_BUGS:
-            fprintf(stderr, "APPLICATION BUG: ");
-            break;
-        case OB_DEBUG_SM:
-            fprintf(stderr, "SESSION: ");
-            break;
-        default:
-            g_assert_not_reached();
-        }
-
-        va_start(vl, a);
-        vfprintf(stderr, a, vl);
-        va_end(vl);
+    message = g_strdup_vprintf(format, args);
+    if (prefix) {
+        gchar *a = message;
+        message = g_strconcat(prefix, message, NULL);
+        g_free(a);
     }
+
+    g_debug("%s", message);
+    g_free(message);
+}
+
+void ob_debug(const gchar *a, ...)
+{
+    va_list vl;
+
+    va_start(vl, a);
+    log_argv(OB_DEBUG_NORMAL, a, vl);
+    va_end(vl);
+}
+
+void ob_debug_type(ObDebugType type, const gchar *a, ...)
+{
+    va_list vl;
+
+    va_start(vl, a);
+    log_argv(type, a, vl);
+    va_end(vl);
 }
index 3c6bedf..a24e66e 100644 (file)
 
 #include <glib.h>
 
-void ob_debug_show_output(gboolean enable);
+void ob_debug_startup(void);
+void ob_debug_shutdown(void);
 
 void ob_debug(const gchar *a, ...);
 
 typedef enum {
+    OB_DEBUG_NORMAL,
     OB_DEBUG_FOCUS,
     OB_DEBUG_APP_BUGS,
     OB_DEBUG_SM,
index 4c183e2..d1f6b29 100644 (file)
 
 #include "debug.h"
 #include "dock.h"
-#include "mainloop.h"
 #include "screen.h"
-#include "prop.h"
 #include "config.h"
 #include "grab.h"
 #include "openbox.h"
-#include "render/theme.h"
+#include "obrender/theme.h"
+#include "obt/prop.h"
 
 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
                          EnterWindowMask | LeaveWindowMask)
@@ -51,6 +50,9 @@ static void dock_app_grab_button(ObDockApp *app, gboolean grab)
     }
 }
 
+static guint window_hash(Window *w) { return *w; }
+static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+
 void dock_startup(gboolean reconfig)
 {
     XSetWindowAttributes attrib;
@@ -58,12 +60,12 @@ void dock_startup(gboolean reconfig)
     if (reconfig) {
         GList *it;
 
-        XSetWindowBorder(ob_display, dock->frame,
+        XSetWindowBorder(obt_display, dock->frame,
                          RrColorPixel(ob_rr_theme->osd_border_color));
-        XSetWindowBorderWidth(ob_display, dock->frame, ob_rr_theme->obwidth);
+        XSetWindowBorderWidth(obt_display, dock->frame, ob_rr_theme->obwidth);
 
         RrAppearanceFree(dock->a_frame);
-        dock->a_frame = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg);
+        dock->a_frame = RrAppearanceCopy(ob_rr_theme->osd_bg);
 
         stacking_add(DOCK_AS_WINDOW(dock));
 
@@ -79,30 +81,33 @@ void dock_startup(gboolean reconfig)
                       0, 0, 0, 0, 0, 0, 0, 0);
 
     dock = g_new0(ObDock, 1);
-    dock->obwin.type = Window_Dock;
+    dock->obwin.type = OB_WINDOW_CLASS_DOCK;
 
     dock->hidden = TRUE;
 
+    dock->dock_map = g_hash_table_new((GHashFunc)window_hash,
+                                      (GEqualFunc)window_comp);
+
     attrib.event_mask = DOCK_EVENT_MASK;
     attrib.override_redirect = True;
     attrib.do_not_propagate_mask = DOCK_NOPROPAGATEMASK;
-    dock->frame = XCreateWindow(ob_display, RootWindow(ob_display, ob_screen),
+    dock->frame = XCreateWindow(obt_display, obt_root(ob_screen),
                                 0, 0, 1, 1, 0,
                                 RrDepth(ob_rr_inst), InputOutput,
                                 RrVisual(ob_rr_inst),
                                 CWOverrideRedirect | CWEventMask |
                                 CWDontPropagate,
                                 &attrib);
-    dock->a_frame = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg);
-    XSetWindowBorder(ob_display, dock->frame,
+    dock->a_frame = RrAppearanceCopy(ob_rr_theme->osd_bg);
+    XSetWindowBorder(obt_display, dock->frame,
                      RrColorPixel(ob_rr_theme->osd_border_color));
-    XSetWindowBorderWidth(ob_display, dock->frame, ob_rr_theme->obwidth);
+    XSetWindowBorderWidth(obt_display, dock->frame, ob_rr_theme->obwidth);
 
     /* Setting the window type so xcompmgr can tell what it is */
-    PROP_SET32(dock->frame, net_wm_window_type, atom,
-               prop_atoms.net_wm_window_type_dock);
+    OBT_PROP_SET32(dock->frame, NET_WM_WINDOW_TYPE, ATOM,
+                   OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK));
 
-    g_hash_table_insert(window_map, &dock->frame, dock);
+    window_add(&dock->frame, DOCK_AS_WINDOW(dock));
     stacking_add(DOCK_AS_WINDOW(dock));
 }
 
@@ -118,25 +123,25 @@ void dock_shutdown(gboolean reconfig)
         return;
     }
 
-    XDestroyWindow(ob_display, dock->frame);
+    g_hash_table_destroy(dock->dock_map);
+
+    XDestroyWindow(obt_display, dock->frame);
     RrAppearanceFree(dock->a_frame);
-    g_hash_table_remove(window_map, &dock->frame);
+    window_remove(dock->frame);
     stacking_remove(dock);
 }
 
-void dock_add(Window win, XWMHints *wmhints)
+void dock_manage(Window icon_win, Window name_win)
 {
     ObDockApp *app;
     XWindowAttributes attrib;
     gchar **data;
 
     app = g_new0(ObDockApp, 1);
-    app->obwin.type = Window_DockApp;
-    app->win = win;
-    app->icon_win = (wmhints->flags & IconWindowHint) ?
-        wmhints->icon_window : win;
+    app->name_win = name_win;
+    app->icon_win = icon_win;
 
-    if (PROP_GETSS(app->win, wm_class, locale, &data)) {
+    if (OBT_PROP_GETSS(app->name_win, WM_CLASS, locale, &data)) {
         if (data[0]) {
             app->name = g_strdup(data[0]);
             if (data[1])
@@ -148,7 +153,7 @@ void dock_add(Window win, XWMHints *wmhints)
     if (app->name == NULL) app->name = g_strdup("");
     if (app->class == NULL) app->class = g_strdup("");
 
-    if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
+    if (XGetWindowAttributes(obt_display, app->icon_win, &attrib)) {
         app->w = attrib.width;
         app->h = attrib.height;
     } else {
@@ -156,9 +161,10 @@ void dock_add(Window win, XWMHints *wmhints)
     }
 
     dock->dock_apps = g_list_append(dock->dock_apps, app);
+    g_hash_table_insert(dock->dock_map, &app->icon_win, app);
     dock_configure();
 
-    XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
+    XReparentWindow(obt_display, app->icon_win, dock->frame, app->x, app->y);
     /*
       This is the same case as in frame.c for client windows. When Openbox is
       starting, the window is already mapped so we see unmap events occur for
@@ -168,51 +174,53 @@ void dock_add(Window win, XWMHints *wmhints)
     */
     if (ob_state() == OB_STATE_STARTING)
         app->ignore_unmaps += 2;
+    XChangeSaveSet(obt_display, app->icon_win, SetModeInsert);
+    XMapWindow(obt_display, app->icon_win);
 
-    if (app->win != app->icon_win) {
-        /* have to map it so that it can be re-managed on a restart */
-        XMoveWindow(ob_display, app->win, -1000, -1000);
-        XMapWindow(ob_display, app->win);
+    if (app->name_win != app->icon_win) {
+        XReparentWindow(obt_display, app->name_win, dock->frame, -1000, -1000);
+        XChangeSaveSet(obt_display, app->name_win, SetModeInsert);
+        XMapWindow(obt_display, app->name_win);
     }
-    XMapWindow(ob_display, app->icon_win);
-    XSync(ob_display, False);
 
-    /* specify that if we exit, the window should not be destroyed and should
-       be reparented back to root automatically */
-    XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
-    XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK);
+    XSync(obt_display, False);
+
+    XSelectInput(obt_display, app->icon_win, DOCKAPP_EVENT_MASK);
 
     dock_app_grab_button(app, TRUE);
 
-    g_hash_table_insert(window_map, &app->icon_win, app);
+    ob_debug("Managed Dock App: 0x%lx 0x%lx (%s)",
+             app->icon_win, app->name_win, app->class);
 
-    ob_debug("Managed Dock App: 0x%lx (%s)\n", app->icon_win, app->class);
+    grab_server(FALSE);
 }
 
-void dock_remove_all(void)
+void dock_unmanage_all(void)
 {
     while (dock->dock_apps)
-        dock_remove(dock->dock_apps->data, TRUE);
+        dock_unmanage(dock->dock_apps->data, TRUE);
 }
 
-void dock_remove(ObDockApp *app, gboolean reparent)
+void dock_unmanage(ObDockApp *app, gboolean reparent)
 {
     dock_app_grab_button(app, FALSE);
-    XSelectInput(ob_display, app->icon_win, NoEventMask);
+    XSelectInput(obt_display, app->icon_win, NoEventMask);
     /* remove the window from our save set */
-    XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
-    XSync(ob_display, False);
-
-    g_hash_table_remove(window_map, &app->icon_win);
-
-    if (reparent)
-        XReparentWindow(ob_display, app->icon_win,
-                        RootWindow(ob_display, ob_screen), app->x, app->y);
+    XChangeSaveSet(obt_display, app->icon_win, SetModeDelete);
+    XSync(obt_display, False);
+
+    if (reparent) {
+        XReparentWindow(obt_display, app->icon_win, obt_root(ob_screen), 0, 0);
+        if (app->name_win != app->icon_win)
+            XReparentWindow(obt_display, app->name_win,
+                            obt_root(ob_screen), 0, 0);
+    }
 
     dock->dock_apps = g_list_remove(dock->dock_apps, app);
+    g_hash_table_remove(dock->dock_map, &app->icon_win);
     dock_configure();
 
-    ob_debug("Unmanaged Dock App: 0x%lx (%s)\n", app->icon_win, app->class);
+    ob_debug("Unmanaged Dock App: 0x%lx (%s)", app->icon_win, app->class);
 
     g_free(app->name);
     g_free(app->class);
@@ -273,7 +281,7 @@ void dock_configure(void)
             break;
         }
 
-        XMoveWindow(ob_display, app->icon_win, app->x, app->y);
+        XMoveWindow(obt_display, app->icon_win, app->x, app->y);
     }
 
     /* used for calculating offsets */
@@ -523,14 +531,14 @@ void dock_configure(void)
         g_assert(dock->area.width > 0);
         g_assert(dock->area.height > 0);
 
-        XMoveResizeWindow(ob_display, dock->frame, dock->area.x, dock->area.y,
+        XMoveResizeWindow(obt_display, dock->frame, dock->area.x, dock->area.y,
                           dock->area.width, dock->area.height);
 
         RrPaint(dock->a_frame, dock->frame, dock->area.width,
                 dock->area.height);
-        XMapWindow(ob_display, dock->frame);
+        XMapWindow(obt_display, dock->frame);
     } else
-        XUnmapWindow(ob_display, dock->frame);
+        XUnmapWindow(obt_display, dock->frame);
 
     /* but they are useful outside of this function! but don't add it if the
        dock is actually not visible */
@@ -636,19 +644,21 @@ void dock_hide(gboolean hide)
 {
     if (!hide) {
         if (dock->hidden && config_dock_hide) {
-            ob_main_loop_timeout_add(ob_main_loop,
-                                     config_dock_show_delay * 1000,
-                                     show_timeout, NULL, g_direct_equal, NULL);
+            obt_main_loop_timeout_add(ob_main_loop,
+                                      config_dock_show_delay * 1000,
+                                      show_timeout, NULL,
+                                      g_direct_equal, NULL);
         } else if (!dock->hidden && config_dock_hide) {
-            ob_main_loop_timeout_remove(ob_main_loop, hide_timeout);
+            obt_main_loop_timeout_remove(ob_main_loop, hide_timeout);
         }
     } else {
         if (!dock->hidden && config_dock_hide) {
-            ob_main_loop_timeout_add(ob_main_loop,
-                                     config_dock_hide_delay * 1000,
-                                     hide_timeout, NULL, g_direct_equal, NULL);
+            obt_main_loop_timeout_add(ob_main_loop,
+                                      config_dock_hide_delay * 1000,
+                                      hide_timeout, NULL,
+                                      g_direct_equal, NULL);
         } else if (dock->hidden && config_dock_hide) {
-            ob_main_loop_timeout_remove(ob_main_loop, show_timeout);
+            obt_main_loop_timeout_remove(ob_main_loop, show_timeout);
         }
     }
 }
@@ -658,3 +668,8 @@ void dock_get_area(Rect *a)
     RECT_SET(*a, dock->area.x, dock->area.y,
              dock->area.width, dock->area.height);
 }
+
+ObDockApp* dock_find_dockapp(Window xwin)
+{
+    return g_hash_table_lookup(dock->dock_map, &xwin);
+}
index 57c1f39..8bc735e 100644 (file)
@@ -22,7 +22,7 @@
 #include "window.h"
 #include "stacking.h"
 #include "geom.h"
-#include "render/render.h"
+#include "obrender/render.h"
 
 #include <glib.h>
 #include <X11/Xlib.h>
@@ -44,15 +44,14 @@ struct _ObDock
     gboolean hidden;
 
     GList *dock_apps;
+    GHashTable *dock_map;
 };
 
 struct _ObDockApp {
-    ObWindow obwin;
-
     gint ignore_unmaps;
 
     Window icon_win;
-    Window win;
+    Window name_win;
 
     gchar *name;
     gchar *class;
@@ -68,17 +67,19 @@ extern StrutPartial dock_strut;
 void dock_startup(gboolean reconfig);
 void dock_shutdown(gboolean reconfig);
 
-void dock_configure();
+void dock_configure(void);
 void dock_hide(gboolean hide);
 
-void dock_add(Window win, XWMHints *wmhints);
+void dock_manage(Window icon_win, Window name_win);
 
-void dock_remove_all();
-void dock_remove(ObDockApp *app, gboolean reparent);
+void dock_unmanage_all(void);
+void dock_unmanage(ObDockApp *app, gboolean reparent);
 
 void dock_app_drag(ObDockApp *app, XMotionEvent *e);
 void dock_app_configure(ObDockApp *app, gint w, gint h);
 
 void dock_get_area(Rect *a);
 
+ObDockApp* dock_find_dockapp(Window xwin);
+
 #endif
index 2ebea6b..51cfc65 100644 (file)
@@ -24,8 +24,6 @@
 #include "dock.h"
 #include "actions.h"
 #include "client.h"
-#include "xerror.h"
-#include "prop.h"
 #include "config.h"
 #include "screen.h"
 #include "frame.h"
 #include "prompt.h"
 #include "menuframe.h"
 #include "keyboard.h"
-#include "modkeys.h"
 #include "mouse.h"
-#include "mainloop.h"
 #include "focus.h"
 #include "focus_cycle.h"
 #include "moveresize.h"
 #include "group.h"
 #include "stacking.h"
-#include "extensions.h"
-#include "translate.h"
 #include "ping.h"
+#include "obt/display.h"
+#include "obt/prop.h"
+#include "obt/keyboard.h"
 
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
@@ -87,19 +84,20 @@ typedef struct
 
 static void event_process(const XEvent *e, gpointer data);
 static void event_handle_root(XEvent *e);
-static gboolean event_handle_menu_keyboard(XEvent *e);
-static gboolean event_handle_menu(XEvent *e);
+static gboolean event_handle_menu_input(XEvent *e);
+static void event_handle_menu(ObMenuFrame *frame, XEvent *e);
 static gboolean event_handle_prompt(ObPrompt *p, XEvent *e);
 static void event_handle_dock(ObDock *s, XEvent *e);
 static void event_handle_dockapp(ObDockApp *app, XEvent *e);
 static void event_handle_client(ObClient *c, XEvent *e);
-static void event_handle_user_input(ObClient *client, XEvent *e);
+static gboolean event_handle_user_input(ObClient *client, XEvent *e);
 static gboolean is_enter_focus_event_ignored(gulong serial);
 static void event_ignore_enter_range(gulong start, gulong end);
 
 static void focus_delay_dest(gpointer data);
 static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
 static gboolean focus_delay_func(gpointer data);
+static gboolean unfocus_delay_func(gpointer data);
 static void focus_delay_client_dest(ObClient *client, gpointer data);
 
 Time event_curtime = CurrentTime;
@@ -125,9 +123,9 @@ static void ice_watch(IceConn conn, IcePointer data, Bool opening,
 
     if (opening) {
         fd = IceConnectionNumber(conn);
-        ob_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
+        obt_main_loop_fd_add(ob_main_loop, fd, ice_handler, conn, NULL);
     } else {
-        ob_main_loop_fd_remove(ob_main_loop, fd);
+        obt_main_loop_fd_remove(ob_main_loop, fd);
         fd = -1;
     }
 }
@@ -137,7 +135,7 @@ void event_startup(gboolean reconfig)
 {
     if (reconfig) return;
 
-    ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
+    obt_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
 
 #ifdef USE_SM
     IceAddConnectionWatch(ice_watch, NULL);
@@ -164,9 +162,15 @@ static Window event_get_window(XEvent *e)
     /* pick a window */
     switch (e->type) {
     case SelectionClear:
-        window = RootWindow(ob_display, ob_screen);
+        window = obt_root(ob_screen);
+        break;
+    case CreateNotify:
+        window = e->xcreatewindow.window;
         break;
     case MapRequest:
+        window = e->xmaprequest.window;
+        break;
+    case MapNotify:
         window = e->xmap.window;
         break;
     case UnmapNotify:
@@ -183,7 +187,9 @@ static Window event_get_window(XEvent *e)
         break;
     default:
 #ifdef XKB
-        if (extensions_xkb && e->type == extensions_xkb_event_basep) {
+        if (obt_display_extension_xkb &&
+            e->type == obt_display_extension_xkb_basep)
+        {
             switch (((XkbAnyEvent*)e)->xkb_type) {
             case XkbBellNotify:
                 window = ((XkbBellNotifyEvent*)e)->window;
@@ -193,8 +199,8 @@ static Window event_get_window(XEvent *e)
         } else
 #endif
 #ifdef SYNC
-        if (extensions_sync &&
-            e->type == extensions_sync_event_basep + XSyncAlarmNotify)
+        if (obt_display_extension_sync &&
+            e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
         {
             window = None;
         } else
@@ -232,8 +238,8 @@ static void event_set_curtime(XEvent *e)
         break;
     default:
 #ifdef SYNC
-        if (extensions_sync &&
-            e->type == extensions_sync_event_basep + XSyncAlarmNotify)
+        if (obt_display_extension_sync &&
+            e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
         {
             t = ((XSyncAlarmNotifyEvent*)e)->time;
         }
@@ -261,34 +267,34 @@ static void event_hack_mods(XEvent *e)
     switch (e->type) {
     case ButtonPress:
     case ButtonRelease:
-        e->xbutton.state = modkeys_only_modifier_masks(e->xbutton.state);
+        e->xbutton.state = obt_keyboard_only_modmasks(e->xbutton.state);
         break;
     case KeyPress:
-        e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
+        e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state);
         break;
     case KeyRelease:
 #ifdef XKB
         /* If XKB is present, then the modifiers are all strange from its
            magic.  Our X core protocol stuff won't work, so we use this to
            find what the modifier state is instead. */
-        if (XkbGetState(ob_display, XkbUseCoreKbd, &xkb_state) == Success)
+        if (XkbGetState(obt_display, XkbUseCoreKbd, &xkb_state) == Success)
             e->xkey.state =
-                modkeys_only_modifier_masks(xkb_state.compat_state);
+                obt_keyboard_only_modmasks(xkb_state.compat_state);
         else
 #endif
         {
-            e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
+            e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state);
             /* remove from the state the mask of the modifier key being
                released, if it is a modifier key being released that is */
-            e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode);
+            e->xkey.state &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode);
         }
         break;
     case MotionNotify:
-        e->xmotion.state = modkeys_only_modifier_masks(e->xmotion.state);
+        e->xmotion.state = obt_keyboard_only_modmasks(e->xmotion.state);
         /* compress events */
         {
             XEvent ce;
-            while (XCheckTypedWindowEvent(ob_display, e->xmotion.window,
+            while (XCheckTypedWindowEvent(obt_display, e->xmotion.window,
                                           e->type, &ce)) {
                 e->xmotion.x = ce.xmotion.x;
                 e->xmotion.y = ce.xmotion.y;
@@ -318,7 +324,7 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only)
 
         /* These are the ones we want.. */
 
-        if (win == RootWindow(ob_display, ob_screen)) {
+        if (win == obt_root(ob_screen)) {
             /* If looking for a focus in on a client, then always return
                FALSE for focus in's to the root window */
             if (in_client_only)
@@ -339,7 +345,7 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only)
            but has disappeared.
         */
         if (in_client_only) {
-            ObWindow *w = g_hash_table_lookup(window_map, &e->xfocus.window);
+            ObWindow *w = window_find(e->xfocus.window);
             if (!w || !WINDOW_IS_CLIENT(w))
                 return FALSE;
         }
@@ -372,7 +378,7 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only)
             return FALSE;
 
         /* Focus left the root window revertedto state */
-        if (win == RootWindow(ob_display, ob_screen))
+        if (win == obt_root(ob_screen))
             return FALSE;
 
         /* These are the ones we want.. */
@@ -411,6 +417,7 @@ static void print_focusevent(XEvent *e)
     case NotifyGrab:         modestr="NotifyGrab";         break;
     case NotifyUngrab:       modestr="NotifyUngrab";       break;
     case NotifyWhileGrabbed: modestr="NotifyWhileGrabbed"; break;
+    default:                 g_assert_not_reached();
     }
     switch (detail) {
     case NotifyAncestor:    detailstr="NotifyAncestor";    break;
@@ -421,6 +428,7 @@ static void print_focusevent(XEvent *e)
     case NotifyPointer:     detailstr="NotifyPointer";     break;
     case NotifyPointerRoot: detailstr="NotifyPointerRoot"; break;
     case NotifyDetailNone:  detailstr="NotifyDetailNone";  break;
+    default:                g_assert_not_reached();
     }
 
     if (mode == NotifyGrab || mode == NotifyUngrab)
@@ -428,7 +436,7 @@ static void print_focusevent(XEvent *e)
 
     g_assert(modestr);
     g_assert(detailstr);
-    ob_debug_type(OB_DEBUG_FOCUS, "Focus%s 0x%x mode=%s detail=%s\n",
+    ob_debug_type(OB_DEBUG_FOCUS, "Focus%s 0x%x mode=%s detail=%s",
                   (e->xfocus.type == FocusIn ? "In" : "Out"),
                   win,
                   modestr, detailstr);
@@ -454,45 +462,48 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
 
 static void event_process(const XEvent *ec, gpointer data)
 {
+    XEvent ee, *e;
+    ObEventData *ed = data;
+
     Window window;
     ObClient *client = NULL;
     ObDock *dock = NULL;
     ObDockApp *dockapp = NULL;
     ObWindow *obwin = NULL;
-    XEvent ee, *e;
-    ObEventData *ed = data;
+    ObMenuFrame *menu = NULL;
     ObPrompt *prompt = NULL;
+    gboolean used;
 
     /* make a copy we can mangle */
     ee = *ec;
     e = &ee;
 
     window = event_get_window(e);
-    if ((obwin = g_hash_table_lookup(window_map, &window))) {
+    if (window == obt_root(ob_screen))
+        /* don't do any lookups, waste of cpu */;
+    else if ((obwin = window_find(window))) {
         switch (obwin->type) {
-        case Window_Dock:
+        case OB_WINDOW_CLASS_DOCK:
             dock = WINDOW_AS_DOCK(obwin);
             break;
-        case Window_DockApp:
-            dockapp = WINDOW_AS_DOCKAPP(obwin);
-            break;
-        case Window_Client:
+        case OB_WINDOW_CLASS_CLIENT:
             client = WINDOW_AS_CLIENT(obwin);
             /* events on clients can be events on prompt windows too */
             prompt = client->prompt;
             break;
-        case Window_Menu:
-            /* not to be used for events */
-            g_assert_not_reached();
+        case OB_WINDOW_CLASS_MENUFRAME:
+            menu = WINDOW_AS_MENUFRAME(obwin);
             break;
-        case Window_Internal:
+        case OB_WINDOW_CLASS_INTERNAL:
             /* we don't do anything with events directly on these windows */
             break;
-        case Window_Prompt:
+        case OB_WINDOW_CLASS_PROMPT:
             prompt = WINDOW_AS_PROMPT(obwin);
             break;
         }
     }
+    else
+        dockapp = dock_find_dockapp(window);
 
     event_set_curtime(e);
     event_curserial = e->xany.serial;
@@ -506,12 +517,7 @@ static void event_process(const XEvent *ec, gpointer data)
 
     /* deal with it in the kernel */
 
-    if (menu_frame_visible &&
-        (e->type == EnterNotify || e->type == LeaveNotify))
-    {
-        /* crossing events for menu */
-        event_handle_menu(e);
-    } else if (e->type == FocusIn) {
+    if (e->type == FocusIn) {
         if (client &&
             e->xfocus.detail == NotifyInferior)
         {
@@ -536,7 +542,7 @@ static void event_process(const XEvent *ec, gpointer data)
             XEvent ce;
 
             ob_debug_type(OB_DEBUG_FOCUS,
-                          "Focus went to root or pointer root/none\n");
+                          "Focus went to root or pointer root/none");
 
             if (e->xfocus.detail == NotifyInferior ||
                 e->xfocus.detail == NotifyNonlinear)
@@ -557,12 +563,12 @@ static void event_process(const XEvent *ec, gpointer data)
                But if the other focus in is something like PointerRoot then we
                still want to fall back.
             */
-            if (XCheckIfEvent(ob_display, &ce, event_look_for_focusin_client,
+            if (XCheckIfEvent(obt_display, &ce, event_look_for_focusin_client,
                               NULL))
             {
-                XPutBackEvent(ob_display, &ce);
+                XPutBackEvent(obt_display, &ce);
                 ob_debug_type(OB_DEBUG_FOCUS,
-                              "  but another FocusIn is coming\n");
+                              "  but another FocusIn is coming");
             } else {
                 /* Focus has been reverted.
 
@@ -578,7 +584,7 @@ static void event_process(const XEvent *ec, gpointer data)
         else if (!client)
         {
             ob_debug_type(OB_DEBUG_FOCUS,
-                          "Focus went to a window that is already gone\n");
+                          "Focus went to a window that is already gone");
 
             /* If you send focus to a window and then it disappears, you can
                get the FocusIn for it, after it is unmanaged.
@@ -597,25 +603,25 @@ static void event_process(const XEvent *ec, gpointer data)
         XEvent ce;
 
         /* Look for the followup FocusIn */
-        if (!XCheckIfEvent(ob_display, &ce, event_look_for_focusin, NULL)) {
+        if (!XCheckIfEvent(obt_display, &ce, event_look_for_focusin, NULL)) {
             /* There is no FocusIn, this means focus went to a window that
                is not being managed, or a window on another screen. */
             Window win, root;
             gint i;
             guint u;
-            xerror_set_ignore(TRUE);
-            if (XGetInputFocus(ob_display, &win, &i) != 0 &&
-                XGetGeometry(ob_display, win, &root, &i,&i,&u,&u,&u,&u) != 0 &&
-                root != RootWindow(ob_display, ob_screen))
+            obt_display_ignore_errors(TRUE);
+            if (XGetInputFocus(obt_display, &win, &i) &&
+                XGetGeometry(obt_display, win, &root, &i,&i,&u,&u,&u,&u) &&
+                root != obt_root(ob_screen))
             {
                 ob_debug_type(OB_DEBUG_FOCUS,
-                              "Focus went to another screen !\n");
+                              "Focus went to another screen !");
                 focus_left_screen = TRUE;
             }
             else
                 ob_debug_type(OB_DEBUG_FOCUS,
-                              "Focus went to a black hole !\n");
-            xerror_set_ignore(FALSE);
+                              "Focus went to a black hole !");
+            obt_display_ignore_errors(FALSE);
             /* nothing is focused */
             focus_set_client(NULL);
         } else {
@@ -626,7 +632,7 @@ static void event_process(const XEvent *ec, gpointer data)
                 /* The FocusIn was ignored, this means it was on a window
                    that isn't a client. */
                 ob_debug_type(OB_DEBUG_FOCUS,
-                              "Focus went to an unmanaged window 0x%x !\n",
+                              "Focus went to an unmanaged window 0x%x !",
                               ce.xfocus.window);
                 focus_fallback(TRUE, config_focus_under_mouse, TRUE, TRUE);
             }
@@ -644,24 +650,27 @@ static void event_process(const XEvent *ec, gpointer data)
         event_handle_dockapp(dockapp, e);
     else if (dock)
         event_handle_dock(dock, e);
-    else if (window == RootWindow(ob_display, ob_screen))
+    else if (menu)
+        event_handle_menu(menu, e);
+    else if (window == obt_root(ob_screen))
         event_handle_root(e);
     else if (e->type == MapRequest)
-        client_manage(window, NULL);
+        window_manage(window);
     else if (e->type == MappingNotify) {
         /* keyboard layout changes for modifier mapping changes. reload the
            modifier map, and rebind all the key bindings as appropriate */
-        ob_debug("Keyboard map changed. Reloading keyboard bindings.\n");
+        ob_debug("Keyboard map changed. Reloading keyboard bindings.");
         ob_set_state(OB_STATE_RECONFIGURING);
-        modkeys_shutdown(TRUE);
-        modkeys_startup(TRUE);
+        obt_keyboard_reload();
         keyboard_rebind();
         ob_set_state(OB_STATE_RUNNING);
     }
     else if (e->type == ClientMessage) {
         /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
            windows that are not managed yet. */
-        if (e->xclient.message_type == prop_atoms.net_request_frame_extents) {
+        if (e->xclient.message_type ==
+            OBT_PROP_ATOM(NET_REQUEST_FRAME_EXTENTS))
+        {
             /* Pretend to manage the client, getting information used to
                determine its decorations */
             ObClient *c = client_fake_manage(e->xclient.window);
@@ -672,8 +681,8 @@ static void event_process(const XEvent *ec, gpointer data)
             vals[1] = c->frame->size.right;
             vals[2] = c->frame->size.top;
             vals[3] = c->frame->size.bottom;
-            PROP_SETA32(e->xclient.window, net_frame_extents,
-                        cardinal, vals, 4);
+            OBT_PROP_SETA32(e->xclient.window, NET_FRAME_EXTENTS,
+                            CARDINAL, vals, 4);
 
             /* Free the pretend client */
             client_fake_unmanage(c);
@@ -694,14 +703,14 @@ static void event_process(const XEvent *ec, gpointer data)
 
         /* we are not to be held responsible if someone sends us an
            invalid request! */
-        xerror_set_ignore(TRUE);
-        XConfigureWindow(ob_display, window,
+        obt_display_ignore_errors(TRUE);
+        XConfigureWindow(obt_display, window,
                          e->xconfigurerequest.value_mask, &xwc);
-        xerror_set_ignore(FALSE);
+        obt_display_ignore_errors(FALSE);
     }
 #ifdef SYNC
-    else if (extensions_sync &&
-        e->type == extensions_sync_event_basep + XSyncAlarmNotify)
+    else if (obt_display_extension_sync &&
+             e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
     {
         XSyncAlarmNotifyEvent *se = (XSyncAlarmNotifyEvent*)e;
         if (se->alarm == moveresize_alarm && moveresize_in_progress)
@@ -709,31 +718,37 @@ static void event_process(const XEvent *ec, gpointer data)
     }
 #endif
 
-    if (prompt && event_handle_prompt(prompt, e))
-        ;
-    else if (e->type == ButtonPress || e->type == ButtonRelease) {
+    if (e->type == ButtonPress || e->type == ButtonRelease) {
+        ObWindow *w;
+        static guint pressed = 0;
+        static Window pressed_win = None;
+
         /* If the button press was on some non-root window, or was physically
-           on the root window, then process it */
-        if (window != RootWindow(ob_display, ob_screen) ||
-            e->xbutton.subwindow == None)
+           on the root window... */
+        if (window != obt_root(ob_screen) ||
+            e->xbutton.subwindow == None ||
+            /* ...or if it is related to the last button press we handled... */
+            pressed == e->xbutton.button ||
+            /* ...or it if it was physically on an openbox
+               internal window... */
+            ((w = window_find(e->xbutton.subwindow)) &&
+             WINDOW_IS_INTERNAL(w)))
+            /* ...then process the event, otherwise ignore it */
         {
-            event_handle_user_input(client, e);
-        }
-        /* Otherwise only process it if it was physically on an openbox
-           internal window */
-        else {
-            ObWindow *w;
+            used = event_handle_user_input(client, e);
 
-            if ((w = g_hash_table_lookup(window_map, &e->xbutton.subwindow)) &&
-                WINDOW_IS_INTERNAL(w))
-            {
-                event_handle_user_input(client, e);
+            if (e->type == ButtonPress) {
+                pressed = e->xbutton.button;
+                pressed_win = e->xbutton.subwindow;
             }
         }
     }
     else if (e->type == KeyPress || e->type == KeyRelease ||
              e->type == MotionNotify)
-        event_handle_user_input(client, e);
+        used = event_handle_user_input(client, e);
+
+    if (prompt && !used)
+        used = event_handle_prompt(prompt, e);
 
     /* if something happens and it's not from an XEvent, then we don't know
        the time */
@@ -747,7 +762,7 @@ static void event_handle_root(XEvent *e)
 
     switch(e->type) {
     case SelectionClear:
-        ob_debug("Another WM has requested to replace us. Exiting.\n");
+        ob_debug("Another WM has requested to replace us. Exiting.");
         ob_exit_replace();
         break;
 
@@ -755,41 +770,41 @@ static void event_handle_root(XEvent *e)
         if (e->xclient.format != 32) break;
 
         msgtype = e->xclient.message_type;
-        if (msgtype == prop_atoms.net_current_desktop) {
+        if (msgtype == OBT_PROP_ATOM(NET_CURRENT_DESKTOP)) {
             guint d = e->xclient.data.l[0];
             if (d < screen_num_desktops) {
                 event_curtime = e->xclient.data.l[1];
                 if (event_curtime == 0)
                     ob_debug_type(OB_DEBUG_APP_BUGS,
                                   "_NET_CURRENT_DESKTOP message is missing "
-                                  "a timestamp\n");
+                                  "a timestamp");
                 screen_set_desktop(d, TRUE);
             }
-        } else if (msgtype == prop_atoms.net_number_of_desktops) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_NUMBER_OF_DESKTOPS)) {
             guint d = e->xclient.data.l[0];
             if (d > 0 && d <= 1000)
                 screen_set_num_desktops(d);
-        } else if (msgtype == prop_atoms.net_showing_desktop) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_SHOWING_DESKTOP)) {
             screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
-        } else if (msgtype == prop_atoms.ob_control) {
-            ob_debug("OB_CONTROL: %d\n", e->xclient.data.l[0]);
+        } else if (msgtype == OBT_PROP_ATOM(OB_CONTROL)) {
+            ob_debug("OB_CONTROL: %d", e->xclient.data.l[0]);
             if (e->xclient.data.l[0] == 1)
                 ob_reconfigure();
             else if (e->xclient.data.l[0] == 2)
                 ob_restart();
             else if (e->xclient.data.l[0] == 3)
                 ob_exit(0);
-        } else if (msgtype == prop_atoms.wm_protocols) {
-            if ((Atom)e->xclient.data.l[0] == prop_atoms.net_wm_ping)
+        } else if (msgtype == OBT_PROP_ATOM(WM_PROTOCOLS)) {
+            if ((Atom)e->xclient.data.l[0] == OBT_PROP_ATOM(NET_WM_PING))
                 ping_got_pong(e->xclient.data.l[1]);
         }
         break;
     case PropertyNotify:
-        if (e->xproperty.atom == prop_atoms.net_desktop_names) {
-            ob_debug("UPDATE DESKTOP NAMES\n");
+        if (e->xproperty.atom == OBT_PROP_ATOM(NET_DESKTOP_NAMES)) {
+            ob_debug("UPDATE DESKTOP NAMES");
             screen_update_desktop_names();
         }
-        else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
+        else if (e->xproperty.atom == OBT_PROP_ATOM(NET_DESKTOP_LAYOUT))
             screen_update_layout();
         break;
     case ConfigureNotify:
@@ -817,17 +832,17 @@ void event_enter_client(ObClient *client)
         if (config_focus_delay) {
             ObFocusDelayData *data;
 
-            ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
+            obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
 
             data = g_new(ObFocusDelayData, 1);
             data->client = client;
             data->time = event_curtime;
             data->serial = event_curserial;
 
-            ob_main_loop_timeout_add(ob_main_loop,
-                                     config_focus_delay * 1000,
-                                     focus_delay_func,
-                                     data, focus_delay_cmp, focus_delay_dest);
+            obt_main_loop_timeout_add(ob_main_loop,
+                                      config_focus_delay * 1000,
+                                      focus_delay_func,
+                                      data, focus_delay_cmp, focus_delay_dest);
         } else {
             ObFocusDelayData data;
             data.client = client;
@@ -838,6 +853,41 @@ void event_enter_client(ObClient *client)
     }
 }
 
+void event_leave_client(ObClient *client)
+{
+    g_assert(config_focus_follow);
+
+    if (is_enter_focus_event_ignored(event_curserial)) {
+        ob_debug_type(OB_DEBUG_FOCUS, "Ignoring leave event with serial %lu\n"
+                      "on client 0x%x", event_curserial, client->window);
+        return;
+    }
+
+    if (client == focus_client) {
+        if (config_focus_delay) {
+            ObFocusDelayData *data;
+
+            obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func);
+
+            data = g_new(ObFocusDelayData, 1);
+            data->client = client;
+            data->time = event_curtime;
+            data->serial = event_curserial;
+
+            obt_main_loop_timeout_add(ob_main_loop,
+                                      config_focus_delay * 1000,
+                                      unfocus_delay_func,
+                                      data, focus_delay_cmp, focus_delay_dest);
+        } else {
+            ObFocusDelayData data;
+            data.client = client;
+            data.time = event_curtime;
+            data.serial = event_curserial;
+            unfocus_delay_func(&data);
+        }
+    }
+}
+
 static gboolean *context_to_button(ObFrame *f, ObFrameContext con, gboolean press)
 {
     if (press) {
@@ -877,12 +927,12 @@ static void compress_client_message_event(XEvent *e, XEvent *ce, Window window,
                                           Atom msgtype)
 {
     /* compress changes into a single change */
-    while (XCheckTypedWindowEvent(ob_display, window, e->type, ce)) {
+    while (XCheckTypedWindowEvent(obt_display, window, e->type, ce)) {
         /* XXX: it would be nice to compress ALL messages of a
            type, not just messages in a row without other
            message types between. */
         if (ce->xclient.message_type != msgtype) {
-            XPutBackEvent(ob_display, ce);
+            XPutBackEvent(obt_display, ce);
             break;
         }
         e->xclient = ce->xclient;
@@ -1001,21 +1051,24 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 event_end_ignore_all_enters(event_start_ignore_all_enters());
 
             ob_debug_type(OB_DEBUG_FOCUS,
-                          "%sNotify mode %d detail %d on %lx\n",
+                          "%sNotify mode %d detail %d on %lx",
                           (e->type == EnterNotify ? "Enter" : "Leave"),
                           e->xcrossing.mode,
                           e->xcrossing.detail, (client?client->window:0));
             if (grab_on_keyboard())
                 break;
-            if (config_focus_follow && config_focus_delay &&
+            if (config_focus_follow &&
                 /* leave inferior events can happen when the mouse goes onto
                    the window's border and then into the window before the
                    delay is up */
                 e->xcrossing.detail != NotifyInferior)
             {
-                ob_main_loop_timeout_remove_data(ob_main_loop,
-                                                 focus_delay_func,
-                                                 client, FALSE);
+                if (config_focus_delay)
+                    obt_main_loop_timeout_remove_data(ob_main_loop,
+                                                      focus_delay_func,
+                                                      client, FALSE);
+                if (config_unfocus_leave)
+                    event_leave_client(client);
             }
             break;
         default:
@@ -1046,7 +1099,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             {
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "%sNotify mode %d detail %d serial %lu on %lx "
-                              "IGNORED\n",
+                              "IGNORED",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
                               e->xcrossing.detail,
@@ -1056,14 +1109,19 @@ static void event_handle_client(ObClient *client, XEvent *e)
             else {
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "%sNotify mode %d detail %d serial %lu on %lx, "
-                              "focusing window\n",
+                              "focusing window",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
                               e->xcrossing.detail,
                               e->xcrossing.serial,
                               (client?client->window:0));
-                if (config_focus_follow)
+                if (config_focus_follow) {
+                    if (config_focus_delay)
+                        obt_main_loop_timeout_remove_data(ob_main_loop,
+                                                          unfocus_delay_func,
+                                                          client, FALSE);
                     event_enter_client(client);
+                }
             }
             break;
         default:
@@ -1096,10 +1154,10 @@ static void event_handle_client(ObClient *client, XEvent *e)
         RECT_TO_DIMS(client->area, x, y, w, h);
 
         ob_debug("ConfigureRequest for \"%s\" desktop %d wmstate %d "
-                 "visible %d\n"
-                 "                     x %d y %d w %d h %d b %d\n",
+                 "visible %d",
                  client->title,
-                 screen_desktop, client->wmstate, client->frame->visible,
+                 screen_desktop, client->wmstate, client->frame->visible);
+        ob_debug("                     x %d y %d w %d h %d b %d",
                  x, y, w, h, client->border_width);
 
         if (e->xconfigurerequest.value_mask & CWBorderWidth)
@@ -1122,8 +1180,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             /* get the sibling */
             if (e->xconfigurerequest.value_mask & CWSibling) {
                 ObWindow *win;
-                win = g_hash_table_lookup(window_map,
-                                          &e->xconfigurerequest.above);
+                win = window_find(e->xconfigurerequest.above);
                 if (win && WINDOW_IS_CLIENT(win) &&
                     WINDOW_AS_CLIENT(win) != client)
                 {
@@ -1177,7 +1234,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
         }
 
         ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d "
-                 "move %d resize %d\n",
+                 "move %d resize %d",
                  e->xconfigurerequest.value_mask & CWX, x,
                  e->xconfigurerequest.value_mask & CWY, y,
                  e->xconfigurerequest.value_mask & CWWidth, w,
@@ -1203,7 +1260,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             ob_debug_type(OB_DEBUG_APP_BUGS,
                           "Application %s is trying to move via "
                           "ConfigureRequest to it's root window position "
-                          "but it is not using StaticGravity\n",
+                          "but it is not using StaticGravity",
                           client->title);
             /* don't move it */
             x = client->area.x;
@@ -1230,25 +1287,25 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
             client_find_onscreen(client, &x, &y, w, h, FALSE);
 
-            ob_debug("Granting ConfigureRequest x %d y %d w %d h %d\n",
+            ob_debug("Granting ConfigureRequest x %d y %d w %d h %d",
                      x, y, w, h);
             client_configure(client, x, y, w, h, FALSE, TRUE, TRUE);
         }
         break;
     }
     case UnmapNotify:
+        ob_debug("UnmapNotify for window 0x%x eventwin 0x%x sendevent %d "
+                 "ignores left %d",
+                 client->window, e->xunmap.event, e->xunmap.from_configure,
+                 client->ignore_unmaps);
         if (client->ignore_unmaps) {
             client->ignore_unmaps--;
             break;
         }
-        ob_debug("UnmapNotify for window 0x%x eventwin 0x%x sendevent %d "
-                 "ignores left %d\n",
-                 client->window, e->xunmap.event, e->xunmap.from_configure,
-                 client->ignore_unmaps);
         client_unmanage(client);
         break;
     case DestroyNotify:
-        ob_debug("DestroyNotify for window 0x%x\n", client->window);
+        ob_debug("DestroyNotify for window 0x%x", client->window);
         client_unmanage(client);
         break;
     case ReparentNotify:
@@ -1264,13 +1321,13 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
         /* we don't want the reparent event, put it back on the stack for the
            X server to deal with after we unmanage the window */
-        XPutBackEvent(ob_display, e);
+        XPutBackEvent(obt_display, e);
 
-        ob_debug("ReparentNotify for window 0x%x\n", client->window);
+        ob_debug("ReparentNotify for window 0x%x", client->window);
         client_unmanage(client);
         break;
     case MapRequest:
-        ob_debug("MapRequest for 0x%lx\n", client->window);
+        ob_debug("MapRequest for 0x%lx", client->window);
         if (!client->iconic) break; /* this normally doesn't happen, but if it
                                        does, we don't want it!
                                        it can happen now when the window is on
@@ -1285,20 +1342,20 @@ static void event_handle_client(ObClient *client, XEvent *e)
         if (e->xclient.format != 32) return;
 
         msgtype = e->xclient.message_type;
-        if (msgtype == prop_atoms.wm_change_state) {
+        if (msgtype == OBT_PROP_ATOM(WM_CHANGE_STATE)) {
             compress_client_message_event(e, &ce, client->window, msgtype);
             client_set_wm_state(client, e->xclient.data.l[0]);
-        } else if (msgtype == prop_atoms.net_wm_desktop) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_WM_DESKTOP)) {
             compress_client_message_event(e, &ce, client->window, msgtype);
             if ((unsigned)e->xclient.data.l[0] < screen_num_desktops ||
                 (unsigned)e->xclient.data.l[0] == DESKTOP_ALL)
                 client_set_desktop(client, (unsigned)e->xclient.data.l[0],
                                    FALSE, FALSE);
-        } else if (msgtype == prop_atoms.net_wm_state) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_WM_STATE)) {
             gulong ignore_start;
 
             /* can't compress these */
-            ob_debug("net_wm_state %s %ld %ld for 0x%lx\n",
+            ob_debug("net_wm_state %s %ld %ld for 0x%lx",
                      (e->xclient.data.l[0] == 0 ? "Remove" :
                       e->xclient.data.l[0] == 1 ? "Add" :
                       e->xclient.data.l[0] == 2 ? "Toggle" : "INVALID"),
@@ -1312,11 +1369,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
                              e->xclient.data.l[1], e->xclient.data.l[2]);
             if (!config_focus_under_mouse)
                 event_end_ignore_all_enters(ignore_start);
-        } else if (msgtype == prop_atoms.net_close_window) {
-            ob_debug("net_close_window for 0x%lx\n", client->window);
+        } else if (msgtype == OBT_PROP_ATOM(NET_CLOSE_WINDOW)) {
+            ob_debug("net_close_window for 0x%lx", client->window);
             client_close(client);
-        } else if (msgtype == prop_atoms.net_active_window) {
-            ob_debug("net_active_window for 0x%lx source=%s\n",
+        } else if (msgtype == OBT_PROP_ATOM(NET_ACTIVE_WINDOW)) {
+            ob_debug("net_active_window for 0x%lx source=%s",
                      client->window,
                      (e->xclient.data.l[0] == 0 ? "unknown" :
                       (e->xclient.data.l[0] == 1 ? "application" :
@@ -1327,50 +1384,50 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 if (e->xclient.data.l[1] == 0)
                     ob_debug_type(OB_DEBUG_APP_BUGS,
                                   "_NET_ACTIVE_WINDOW message for window %s is"
-                                  " missing a timestamp\n", client->title);
+                                  " missing a timestamp", client->title);
             } else
                 ob_debug_type(OB_DEBUG_APP_BUGS,
                               "_NET_ACTIVE_WINDOW message for window %s is "
-                              "missing source indication\n", client->title);
+                              "missing source indication", client->title);
             client_activate(client, FALSE, FALSE, TRUE, TRUE,
                             (e->xclient.data.l[0] == 0 ||
                              e->xclient.data.l[0] == 2));
-        } else if (msgtype == prop_atoms.net_wm_moveresize) {
-            ob_debug("net_wm_moveresize for 0x%lx direction %d\n",
+        } else if (msgtype == OBT_PROP_ATOM(NET_WM_MOVERESIZE)) {
+            ob_debug("net_wm_moveresize for 0x%lx direction %d",
                      client->window, e->xclient.data.l[2]);
             if ((Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_topleft ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_top ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_topright ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_right ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_right ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_bottomright ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_bottom ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_bottomleft ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_left ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_move ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_size_keyboard ||
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD) ||
                 (Atom)e->xclient.data.l[2] ==
-                prop_atoms.net_wm_moveresize_move_keyboard) {
-
+                OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
+            {
                 moveresize_start(client, e->xclient.data.l[0],
                                  e->xclient.data.l[1], e->xclient.data.l[3],
                                  e->xclient.data.l[2]);
             }
             else if ((Atom)e->xclient.data.l[2] ==
-                     prop_atoms.net_wm_moveresize_cancel)
+                     OBT_PROP_ATOM(NET_WM_MOVERESIZE_CANCEL))
                 moveresize_end(TRUE);
-        } else if (msgtype == prop_atoms.net_moveresize_window) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_MOVERESIZE_WINDOW)) {
             gint ograv, x, y, w, h;
 
             ograv = client->gravity;
@@ -1408,7 +1465,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             else
                 h = client->area.height;
 
-            ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)\n",
+            ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)",
                      e->xclient.data.l[0] & 1 << 8, x,
                      e->xclient.data.l[0] & 1 << 9, y,
                      client->gravity);
@@ -1418,17 +1475,16 @@ static void event_handle_client(ObClient *client, XEvent *e)
             client_configure(client, x, y, w, h, FALSE, TRUE, FALSE);
 
             client->gravity = ograv;
-        } else if (msgtype == prop_atoms.net_restack_window) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_RESTACK_WINDOW)) {
             if (e->xclient.data.l[0] != 2) {
                 ob_debug_type(OB_DEBUG_APP_BUGS,
                               "_NET_RESTACK_WINDOW sent for window %s with "
-                              "invalid source indication %ld\n",
+                              "invalid source indication %ld",
                               client->title, e->xclient.data.l[0]);
             } else {
                 ObClient *sibling = NULL;
                 if (e->xclient.data.l[1]) {
-                    ObWindow *win = g_hash_table_lookup
-                        (window_map, &e->xclient.data.l[1]);
+                    ObWindow *win = window_find(e->xclient.data.l[1]);
                     if (WINDOW_IS_CLIENT(win) &&
                         WINDOW_AS_CLIENT(win) != client)
                     {
@@ -1437,7 +1493,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
                     if (sibling == NULL)
                         ob_debug_type(OB_DEBUG_APP_BUGS,
                                       "_NET_RESTACK_WINDOW sent for window %s "
-                                      "with invalid sibling 0x%x\n",
+                                      "with invalid sibling 0x%x",
                                  client->title, e->xclient.data.l[1]);
                 }
                 if (e->xclient.data.l[2] == Below ||
@@ -1462,7 +1518,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 } else
                     ob_debug_type(OB_DEBUG_APP_BUGS,
                                   "_NET_RESTACK_WINDOW sent for window %s "
-                                  "with invalid detail %d\n",
+                                  "with invalid detail %d",
                                   client->title, e->xclient.data.l[2]);
             }
         }
@@ -1472,7 +1528,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
         if (!client_validate(client)) break;
 
         /* compress changes to a single property into a single change */
-        while (XCheckTypedWindowEvent(ob_display, client->window,
+        while (XCheckTypedWindowEvent(obt_display, client->window,
                                       e->type, &ce)) {
             Atom a, b;
 
@@ -1484,37 +1540,52 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
             if (a == b)
                 continue;
-            if ((a == prop_atoms.net_wm_name ||
-                 a == prop_atoms.wm_name ||
-                 a == prop_atoms.net_wm_icon_name ||
-                 a == prop_atoms.wm_icon_name)
+            if ((a == OBT_PROP_ATOM(NET_WM_NAME) ||
+                 a == OBT_PROP_ATOM(WM_NAME) ||
+                 a == OBT_PROP_ATOM(NET_WM_ICON_NAME) ||
+                 a == OBT_PROP_ATOM(WM_ICON_NAME))
                 &&
-                (b == prop_atoms.net_wm_name ||
-                 b == prop_atoms.wm_name ||
-                 b == prop_atoms.net_wm_icon_name ||
-                 b == prop_atoms.wm_icon_name)) {
+                (b == OBT_PROP_ATOM(NET_WM_NAME) ||
+                 b == OBT_PROP_ATOM(WM_NAME) ||
+                 b == OBT_PROP_ATOM(NET_WM_ICON_NAME) ||
+                 b == OBT_PROP_ATOM(WM_ICON_NAME))) {
                 continue;
             }
-            if (a == prop_atoms.net_wm_icon &&
-                b == prop_atoms.net_wm_icon)
+            if (a == OBT_PROP_ATOM(NET_WM_ICON) &&
+                b == OBT_PROP_ATOM(NET_WM_ICON))
                 continue;
 
-            XPutBackEvent(ob_display, &ce);
+            XPutBackEvent(obt_display, &ce);
             break;
         }
 
         msgtype = e->xproperty.atom;
         if (msgtype == XA_WM_NORMAL_HINTS) {
-            ob_debug("Update NORMAL hints\n");
+            int x, y, w, h, lw, lh;
+
+            ob_debug("Update NORMAL hints");
             client_update_normal_hints(client);
             /* normal hints can make a window non-resizable */
             client_setup_decor_and_functions(client, FALSE);
 
-            /* make sure the client's sizes are within its bounds, but only
-               reconfigure the window if it needs to. emacs will update its
-               normal hints every time it receives a conigurenotify */
-            client_reconfigure(client, FALSE);
-        } else if (msgtype == prop_atoms.motif_wm_hints) {
+            x = client->area.x;
+            y = client->area.y;
+            w = client->area.width;
+            h = client->area.height;
+
+            /* apply the new normal hints */
+            client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
+            /* make sure the window is visible, and if the window is resized
+               off-screen due to the normal hints changing then this will push
+               it back onto the screen. */
+            client_find_onscreen(client, &x, &y, w, h, FALSE);
+
+            /* make sure the client's sizes are within its bounds, but don't
+               make it reply with a configurenotify unless something changed.
+               emacs will update its normal hints every time it receives a
+               configurenotify */
+            client_configure(client, x, y, w, h, FALSE, TRUE, FALSE);
+        } else if (msgtype == OBT_PROP_ATOM(MOTIF_WM_HINTS)) {
             client_get_mwm_hints(client);
             /* This can override some mwm hints */
             client_get_type_and_transientness(client);
@@ -1529,30 +1600,30 @@ static void event_handle_client(ObClient *client, XEvent *e)
             /* type may have changed, so update the layer */
             client_calc_layer(client);
             client_setup_decor_and_functions(client, TRUE);
-        } else if (msgtype == prop_atoms.net_wm_name ||
-                   msgtype == prop_atoms.wm_name ||
-                   msgtype == prop_atoms.net_wm_icon_name ||
-                   msgtype == prop_atoms.wm_icon_name) {
+        } else if (msgtype == OBT_PROP_ATOM(NET_WM_NAME) ||
+                   msgtype == OBT_PROP_ATOM(WM_NAME) ||
+                   msgtype == OBT_PROP_ATOM(NET_WM_ICON_NAME) ||
+                   msgtype == OBT_PROP_ATOM(WM_ICON_NAME)) {
             client_update_title(client);
-        } else if (msgtype == prop_atoms.wm_protocols) {
+        } else if (msgtype == OBT_PROP_ATOM(WM_PROTOCOLS)) {
             client_update_protocols(client);
             client_setup_decor_and_functions(client, TRUE);
         }
-        else if (msgtype == prop_atoms.net_wm_strut ||
-                 msgtype == prop_atoms.net_wm_strut_partial) {
+        else if (msgtype == OBT_PROP_ATOM(NET_WM_STRUT) ||
+                 msgtype == OBT_PROP_ATOM(NET_WM_STRUT_PARTIAL)) {
             client_update_strut(client);
         }
-        else if (msgtype == prop_atoms.net_wm_icon) {
+        else if (msgtype == OBT_PROP_ATOM(NET_WM_ICON)) {
             client_update_icons(client);
         }
-        else if (msgtype == prop_atoms.net_wm_icon_geometry) {
+        else if (msgtype == OBT_PROP_ATOM(NET_WM_ICON_GEOMETRY)) {
             client_update_icon_geometry(client);
         }
-        else if (msgtype == prop_atoms.net_wm_user_time) {
+        else if (msgtype == OBT_PROP_ATOM(NET_WM_USER_TIME)) {
             guint32 t;
             if (client == focus_client &&
-                PROP_GET32(client->window, net_wm_user_time, cardinal, &t) &&
-                t && !event_time_after(t, e->xproperty.time) &&
+                OBT_PROP_GET32(client->window, NET_WM_USER_TIME, CARDINAL, &t)
+                && t && !event_time_after(t, e->xproperty.time) &&
                 (!event_last_user_time ||
                  event_time_after(t, event_last_user_time)))
             {
@@ -1560,7 +1631,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             }
         }
 #ifdef SYNC
-        else if (msgtype == prop_atoms.net_wm_sync_request_counter) {
+        else if (msgtype == OBT_PROP_ATOM(NET_WM_SYNC_REQUEST_COUNTER)) {
             client_update_sync_request_counter(client);
         }
 #endif
@@ -1573,7 +1644,9 @@ static void event_handle_client(ObClient *client, XEvent *e)
 #ifdef SHAPE
         {
             int kind;
-            if (extensions_shape && e->type == extensions_shape_event_basep) {
+            if (obt_display_extension_shape &&
+                e->type == obt_display_extension_shape_basep)
+            {
                 switch (((XShapeEvent*)e)->kind) {
                     case ShapeBounding:
                     case ShapeClip:
@@ -1584,6 +1657,8 @@ static void event_handle_client(ObClient *client, XEvent *e)
                         client->shaped_input = ((XShapeEvent*)e)->shaped;
                         kind = ShapeInput;
                         break;
+                    default:
+                        g_assert_not_reached();
                 }
                 frame_adjust_shape_kind(client->frame, kind);
             }
@@ -1623,11 +1698,11 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e)
             app->ignore_unmaps--;
             break;
         }
-        dock_remove(app, TRUE);
+        dock_unmanage(app, TRUE);
         break;
     case DestroyNotify:
     case ReparentNotify:
-        dock_remove(app, FALSE);
+        dock_unmanage(app, FALSE);
         break;
     case ConfigureNotify:
         dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);
@@ -1674,144 +1749,180 @@ static gboolean event_handle_prompt(ObPrompt *p, XEvent *e)
     return FALSE;
 }
 
-static gboolean event_handle_menu_keyboard(XEvent *ev)
+static gboolean event_handle_menu_input(XEvent *ev)
 {
-    guint keycode, state;
-    gunichar unikey;
-    ObMenuFrame *frame;
     gboolean ret = FALSE;
 
-    keycode = ev->xkey.keycode;
-    state = ev->xkey.state;
-    unikey = translate_unichar(keycode);
+    if (ev->type == ButtonRelease || ev->type == ButtonPress) {
+        ObMenuEntryFrame *e;
 
-    frame = find_active_or_last_menu();
-    if (frame == NULL)
-        g_assert_not_reached(); /* there is no active menu */
+        if (menu_hide_delay_reached() &&
+            (ev->xbutton.button < 4 || ev->xbutton.button > 5))
+        {
+            if ((e = menu_entry_frame_under(ev->xbutton.x_root,
+                                            ev->xbutton.y_root)))
+            {
+                if (ev->type == ButtonPress && e->frame->child)
+                    menu_frame_select(e->frame->child, NULL, TRUE);
+                menu_frame_select(e->frame, e, TRUE);
+                if (ev->type == ButtonRelease)
+                    menu_entry_frame_execute(e, ev->xbutton.state);
+            }
+            else if (ev->type == ButtonRelease)
+                menu_frame_hide_all();
+        }
+        ret = TRUE;
+    }
+    else if (ev->type == MotionNotify) {
+        ObMenuFrame *f;
+        ObMenuEntryFrame *e;
 
-    /* Allow control while going thru the menu */
-    else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
-        frame->got_press = TRUE;
+        if ((e = menu_entry_frame_under(ev->xmotion.x_root,
+                                        ev->xmotion.y_root)))
+            if (!(f = find_active_menu()) ||
+                f == e->frame ||
+                f->parent == e->frame ||
+                f->child == e->frame)
+                menu_frame_select(e->frame, e, FALSE);
+    }
+    else if (ev->type == KeyPress || ev->type == KeyRelease) {
+        guint keycode, state;
+        gunichar unikey;
+        ObMenuFrame *frame;
 
-        if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) {
-            menu_frame_hide_all();
-            ret = TRUE;
-        }
+        keycode = ev->xkey.keycode;
+        state = ev->xkey.state;
+        unikey = obt_keyboard_keycode_to_unichar(keycode);
+
+        frame = find_active_or_last_menu();
+        if (frame == NULL)
+            g_assert_not_reached(); /* there is no active menu */
 
-        else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
-            /* Left goes to the parent menu */
-            if (frame->parent) {
-                /* remove focus from the child */
-                menu_frame_select(frame, NULL, TRUE);
-                /* and put it in the parent */
-                menu_frame_select(frame->parent, frame->parent->selected,
-                                  TRUE);
+        /* Allow control while going thru the menu */
+        else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
+            frame->got_press = TRUE;
+
+            if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) {
+                menu_frame_hide_all();
+                ret = TRUE;
             }
-            ret = TRUE;
-        }
 
-        else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
-            /* Right goes to the selected submenu */
-            if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
-                /* make sure it is visible */
-                menu_frame_select(frame, frame->selected, TRUE);
-                menu_frame_select_next(frame->child);
+            else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
+                /* Left goes to the parent menu */
+                if (frame->parent) {
+                    /* remove focus from the child */
+                    menu_frame_select(frame, NULL, TRUE);
+                    /* and put it in the parent */
+                    menu_frame_select(frame->parent, frame->parent->selected,
+                                      TRUE);
+                }
+                ret = TRUE;
             }
-            ret = TRUE;
-        }
 
-        else if (ob_keycode_match(keycode, OB_KEY_UP)) {
-            menu_frame_select_previous(frame);
-            ret = TRUE;
-        }
+            else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
+                /* Right goes to the selected submenu */
+                if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
+                {
+                    /* make sure it is visible */
+                    menu_frame_select(frame, frame->selected, TRUE);
+                    menu_frame_select_next(frame->child);
+                }
+                ret = TRUE;
+            }
 
-        else if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
-            menu_frame_select_next(frame);
-            ret = TRUE;
-        }
+            else if (ob_keycode_match(keycode, OB_KEY_UP)) {
+                menu_frame_select_previous(frame);
+                ret = TRUE;
+            }
 
-        else if (ob_keycode_match(keycode, OB_KEY_HOME)) {
-            menu_frame_select_first(frame);
-            ret = TRUE;
-        }
+            else if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
+                menu_frame_select_next(frame);
+                ret = TRUE;
+            }
+
+            else if (ob_keycode_match(keycode, OB_KEY_HOME)) {
+                menu_frame_select_first(frame);
+                ret = TRUE;
+            }
 
-        else if (ob_keycode_match(keycode, OB_KEY_END)) {
-            menu_frame_select_last(frame);
-            ret = TRUE;
+            else if (ob_keycode_match(keycode, OB_KEY_END)) {
+                menu_frame_select_last(frame);
+                ret = TRUE;
+            }
         }
-    }
 
-    /* Use KeyRelease events for running things so that the key release doesn't
-       get sent to the focused application.
+        /* Use KeyRelease events for running things so that the key release
+           doesn't get sent to the focused application.
 
-       Allow ControlMask only, and don't bother if the menu is empty */
-    else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
-             frame->entries && frame->got_press)
-    {
-        if (ob_keycode_match(keycode, OB_KEY_RETURN)) {
-            /* Enter runs the active item or goes into the submenu.
-               Control-Enter runs it without closing the menu. */
-            if (frame->child)
-                menu_frame_select_next(frame->child);
-            else if (frame->selected)
-                menu_entry_frame_execute(frame->selected, state);
-
-            ret = TRUE;
-        }
+           Allow ControlMask only, and don't bother if the menu is empty */
+        else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
+                 frame->entries && frame->got_press)
+        {
+            if (ob_keycode_match(keycode, OB_KEY_RETURN)) {
+                /* Enter runs the active item or goes into the submenu.
+                   Control-Enter runs it without closing the menu. */
+                if (frame->child)
+                    menu_frame_select_next(frame->child);
+                else if (frame->selected)
+                    menu_entry_frame_execute(frame->selected, state);
 
-        /* keyboard accelerator shortcuts. (if it was a valid key) */
-        else if (unikey != 0) {
-            GList *start;
-            GList *it;
-            ObMenuEntryFrame *found = NULL;
-            guint num_found = 0;
-
-            /* start after the selected one */
-            start = frame->entries;
-            if (frame->selected) {
-                for (it = start; frame->selected != it->data;
-                     it = g_list_next(it))
-                    g_assert(it != NULL); /* nothing was selected? */
-                /* next with wraparound */
-                start = g_list_next(it);
-                if (start == NULL) start = frame->entries;
+                ret = TRUE;
             }
 
-            it = start;
-            do {
-                ObMenuEntryFrame *e = it->data;
-                gunichar entrykey = 0;
+            /* keyboard accelerator shortcuts. (if it was a valid key) */
+            else if (unikey != 0) {
+                GList *start;
+                GList *it;
+                ObMenuEntryFrame *found = NULL;
+                guint num_found = 0;
+
+                /* start after the selected one */
+                start = frame->entries;
+                if (frame->selected) {
+                    for (it = start; frame->selected != it->data;
+                         it = g_list_next(it))
+                        g_assert(it != NULL); /* nothing was selected? */
+                    /* next with wraparound */
+                    start = g_list_next(it);
+                    if (start == NULL) start = frame->entries;
+                }
 
-                if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
-                    entrykey = e->entry->data.normal.shortcut;
-                else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
-                    entrykey = e->entry->data.submenu.submenu->shortcut;
+                it = start;
+                do {
+                    ObMenuEntryFrame *e = it->data;
+                    gunichar entrykey = 0;
 
-                if (unikey == entrykey) {
-                    if (found == NULL) found = e;
-                    ++num_found;
-                }
+                    if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
+                        entrykey = e->entry->data.normal.shortcut;
+                    else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
+                        entrykey = e->entry->data.submenu.submenu->shortcut;
 
-                /* next with wraparound */
-                it = g_list_next(it);
-                if (it == NULL) it = frame->entries;
-            } while (it != start);
+                    if (unikey == entrykey) {
+                        if (found == NULL) found = e;
+                        ++num_found;
+                    }
 
-            if (found) {
-                if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
-                    num_found == 1)
-                {
-                    menu_frame_select(frame, found, TRUE);
-                    usleep(50000); /* highlight the item for a short bit so the
-                                      user can see what happened */
-                    menu_entry_frame_execute(found, state);
-                } else {
-                    menu_frame_select(frame, found, TRUE);
-                    if (num_found == 1)
-                        menu_frame_select_next(frame->child);
-                }
+                    /* next with wraparound */
+                    it = g_list_next(it);
+                    if (it == NULL) it = frame->entries;
+                } while (it != start);
 
-                ret = TRUE;
+                if (found) {
+                    if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
+                        num_found == 1)
+                    {
+                        menu_frame_select(frame, found, TRUE);
+                        usleep(50000); /* highlight the item for a short bit so
+                                          the user can see what happened */
+                        menu_entry_frame_execute(found, state);
+                    } else {
+                        menu_frame_select(frame, found, TRUE);
+                        if (num_found == 1)
+                            menu_frame_select_next(frame->child);
+                    }
+
+                    ret = TRUE;
+                }
             }
         }
     }
@@ -1828,27 +1939,12 @@ static Bool event_look_for_menu_enter(Display *d, XEvent *ev, XPointer arg)
         !e->ignore_enters && e->frame == f;
 }
 
-static gboolean event_handle_menu(XEvent *ev)
+static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
 {
     ObMenuFrame *f;
     ObMenuEntryFrame *e;
-    gboolean ret = TRUE;
 
     switch (ev->type) {
-    case ButtonRelease:
-        if (menu_hide_delay_reached() &&
-            (ev->xbutton.button < 4 || ev->xbutton.button > 5))
-        {
-            if ((e = menu_entry_frame_under(ev->xbutton.x_root,
-                                            ev->xbutton.y_root)))
-            {
-                menu_frame_select(e->frame, e, TRUE);
-                menu_entry_frame_execute(e, ev->xbutton.state);
-            }
-            else
-                menu_frame_hide_all();
-        }
-        break;
     case EnterNotify:
         if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window))) {
             if (e->ignore_enters)
@@ -1871,64 +1967,53 @@ static gboolean event_handle_menu(XEvent *ev)
 
             /* check if an EnterNotify event is coming, and if not, then select
                nothing in the menu */
-            if (XCheckIfEvent(ob_display, &ce, event_look_for_menu_enter,
+            if (XCheckIfEvent(obt_display, &ce, event_look_for_menu_enter,
                               (XPointer)e->frame))
-                XPutBackEvent(ob_display, &ce);
+                XPutBackEvent(obt_display, &ce);
             else
                 menu_frame_select(e->frame, NULL, FALSE);
         }
         break;
-    case MotionNotify:
-        if ((e = menu_entry_frame_under(ev->xmotion.x_root,
-                                        ev->xmotion.y_root)))
-            if (!(f = find_active_menu()) ||
-                f == e->frame ||
-                f->parent == e->frame ||
-                f->child == e->frame)
-                menu_frame_select(e->frame, e, FALSE);
-        break;
-    case KeyPress:
-    case KeyRelease:
-        ret = event_handle_menu_keyboard(ev);
-        break;
     }
-    return ret;
 }
 
-static void event_handle_user_input(ObClient *client, XEvent *e)
+static gboolean event_handle_user_input(ObClient *client, XEvent *e)
 {
     g_assert(e->type == ButtonPress || e->type == ButtonRelease ||
              e->type == MotionNotify || e->type == KeyPress ||
              e->type == KeyRelease);
 
     if (menu_frame_visible) {
-        if (event_handle_menu(e))
+        if (event_handle_menu_input(e))
             /* don't use the event if the menu used it, but if the menu
                didn't use it and it's a keypress that is bound, it will
                close the menu and be used */
-            return;
+            return TRUE;
     }
 
     /* if the keyboard interactive action uses the event then dont
        use it for bindings. likewise is moveresize uses the event. */
-    if (!actions_interactive_input_event(e) && !moveresize_event(e)) {
-        if (moveresize_in_progress)
-            /* make further actions work on the client being
-               moved/resized */
-            client = moveresize_client;
-
-        if (e->type == ButtonPress ||
-            e->type == ButtonRelease ||
-            e->type == MotionNotify)
-        {
-            /* the frame may not be "visible" but they can still click on it
-               in the case where it is animating before disappearing */
-            if (!client || !frame_iconify_animating(client->frame))
-                mouse_event(client, e);
-        } else
-            keyboard_event((focus_cycle_target ? focus_cycle_target :
-                            (client ? client : focus_client)), e);
-    }
+    if (actions_interactive_input_event(e) || moveresize_event(e))
+        return TRUE;
+
+    if (moveresize_in_progress)
+        /* make further actions work on the client being
+           moved/resized */
+        client = moveresize_client;
+
+    if (e->type == ButtonPress ||
+        e->type == ButtonRelease ||
+        e->type == MotionNotify)
+    {
+        /* the frame may not be "visible" but they can still click on it
+           in the case where it is animating before disappearing */
+        if (!client || !frame_iconify_animating(client->frame))
+            return mouse_event(client, e);
+    } else
+        return keyboard_event((focus_cycle_target ? focus_cycle_target :
+                               (client ? client : focus_client)), e);
+
+    return FALSE;
 }
 
 static void focus_delay_dest(gpointer data)
@@ -1955,22 +2040,37 @@ static gboolean focus_delay_func(gpointer data)
     return FALSE; /* no repeat */
 }
 
+static gboolean unfocus_delay_func(gpointer data)
+{
+    ObFocusDelayData *d = data;
+    Time old = event_curtime;
+
+    event_curtime = d->time;
+    event_curserial = d->serial;
+    focus_nothing();
+    event_curtime = old;
+    return FALSE; /* no repeat */
+}
+
 static void focus_delay_client_dest(ObClient *client, gpointer data)
 {
-    ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func,
-                                     client, FALSE);
+    obt_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func,
+                                      client, FALSE);
+    obt_main_loop_timeout_remove_data(ob_main_loop, unfocus_delay_func,
+                                      client, FALSE);
 }
 
 void event_halt_focus_delay(void)
 {
     /* ignore all enter events up till the event which caused this to occur */
     if (event_curserial) event_ignore_enter_range(1, event_curserial);
-    ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
+    obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
+    obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func);
 }
 
 gulong event_start_ignore_all_enters(void)
 {
-    return NextRequest(ob_display);
+    return NextRequest(obt_display);
 }
 
 static void event_ignore_enter_range(gulong start, gulong end)
@@ -1985,11 +2085,11 @@ static void event_ignore_enter_range(gulong start, gulong end)
     r->end = end;
     ignore_serials = g_slist_prepend(ignore_serials, r);
 
-    ob_debug_type(OB_DEBUG_FOCUS, "ignoring enters from %lu until %lu\n",
+    ob_debug_type(OB_DEBUG_FOCUS, "ignoring enters from %lu until %lu",
                   r->start, r->end);
 
     /* increment the serial so we don't ignore events we weren't meant to */
-    PROP_ERASE(screen_support_win, motif_wm_hints);
+    OBT_PROP_ERASE(screen_support_win, MOTIF_WM_HINTS);
 }
 
 void event_end_ignore_all_enters(gulong start)
@@ -2000,7 +2100,7 @@ void event_end_ignore_all_enters(gulong start)
        movement will be ignored until we create some further network traffic.
        Instead ignore up to NextRequest-1, then when we increment the serial,
        we will be *past* the range of ignored serials */
-    event_ignore_enter_range(start, NextRequest(ob_display)-1);
+    event_ignore_enter_range(start, NextRequest(obt_display)-1);
 }
 
 static gboolean is_enter_focus_event_ignored(gulong serial)
@@ -2027,24 +2127,24 @@ void event_cancel_all_key_grabs(void)
 {
     if (actions_interactive_act_running()) {
         actions_interactive_cancel_act();
-        ob_debug("KILLED interactive action\n");
+        ob_debug("KILLED interactive action");
     }
     else if (menu_frame_visible) {
         menu_frame_hide_all();
-        ob_debug("KILLED open menus\n");
+        ob_debug("KILLED open menus");
     }
     else if (moveresize_in_progress) {
         moveresize_end(TRUE);
-        ob_debug("KILLED interactive moveresize\n");
+        ob_debug("KILLED interactive moveresize");
     }
     else if (grab_on_keyboard()) {
         ungrab_keyboard();
-        ob_debug("KILLED active grab on keyboard\n");
+        ob_debug("KILLED active grab on keyboard");
     }
     else
         ungrab_passive_key();
 
-    XSync(ob_display, FALSE);
+    XSync(obt_display, FALSE);
 }
 
 gboolean event_time_after(guint32 t1, guint32 t2)
@@ -2079,9 +2179,9 @@ Time event_get_server_time(void)
     /* Generate a timestamp */
     XEvent event;
 
-    XChangeProperty(ob_display, screen_support_win,
-                    prop_atoms.wm_class, prop_atoms.string,
+    XChangeProperty(obt_display, screen_support_win,
+                    OBT_PROP_ATOM(WM_CLASS), OBT_PROP_ATOM(STRING),
                     8, PropModeAppend, NULL, 0);
-    XWindowEvent(ob_display, screen_support_win, PropertyChangeMask, &event);
+    XWindowEvent(obt_display, screen_support_win, PropertyChangeMask, &event);
     return event.xproperty.time;
 }
index a4bd886..4a8d790 100644 (file)
@@ -33,11 +33,6 @@ extern Time event_curtime;
 /*! The last user-interaction time, as given by the clients */
 extern Time event_last_user_time;
 
-/*! The value of the mask for the NumLock modifier */
-extern guint NumLockMask;
-/*! The value of the mask for the ScrollLock modifier */
-extern guint ScrollLockMask;
-
 void event_startup(gboolean reconfig);
 void event_shutdown(gboolean reconfig);
 
@@ -45,9 +40,13 @@ void event_shutdown(gboolean reconfig);
     follows mouse */
 void event_enter_client(struct _ObClient *client);
 
+/*! Make as if the mouse just left the client, use only when using focus
+    follows mouse */
+void event_leave_client(struct _ObClient *client);
+
 /*! Make mouse focus not move at all from the stuff that happens between these
     two function calls. */
-gulong event_start_ignore_all_enters();
+gulong event_start_ignore_all_enters(void);
 void event_end_ignore_all_enters(gulong start);
 
 /*! End *all* active and passive grabs on the keyboard
@@ -57,16 +56,16 @@ void event_end_ignore_all_enters(gulong start);
 
     Actions should not rely on being able to move focus during an
     interactive grab. */
-void event_cancel_all_key_grabs();
+void event_cancel_all_key_grabs(void);
 
 /* Halts any focus delay in progress, use this when the user is selecting a
    window for focus */
-void event_halt_focus_delay();
+void event_halt_focus_delay(void);
 
 /*! Compare t1 and t2, taking into account wraparound. True if t1
     comes at the same time or later than t2. */
 gboolean event_time_after(guint32 t1, guint32 t2);
 
-Time event_get_server_time();
+Time event_get_server_time(void);
 
 #endif
diff --git a/openbox/extensions.c b/openbox/extensions.c
deleted file mode 100644 (file)
index 23d3e0c..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   extensions.c for the Openbox window manager
-   Copyright (c) 2006        Mikael Magnusson
-   Copyright (c) 2003-2007   Dana Jansens
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#include "openbox.h"
-#include "geom.h"
-#include "extensions.h"
-#include "screen.h"
-#include "debug.h"
-
-gboolean extensions_xkb       = FALSE;
-gint     extensions_xkb_event_basep;
-gboolean extensions_shape     = FALSE;
-gint     extensions_shape_event_basep;
-gboolean extensions_xinerama  = FALSE;
-gint     extensions_xinerama_event_basep;
-gboolean extensions_randr     = FALSE;
-gint     extensions_randr_event_basep;
-gboolean extensions_sync      = FALSE;
-gint     extensions_sync_event_basep;
-
-void extensions_query_all(void)
-{
-    gint junk;
-    (void)junk;
-
-#ifdef XKB
-    extensions_xkb =
-        XkbQueryExtension(ob_display, &junk, &extensions_xkb_event_basep,
-                          &junk, NULL, NULL);
-    if (!extensions_xkb)
-        ob_debug("XKB extension is not present on the server\n");
-#endif
-
-#ifdef SHAPE
-    extensions_shape =
-        XShapeQueryExtension(ob_display, &extensions_shape_event_basep,
-                             &junk);
-    if (!extensions_shape)
-        ob_debug("X Shape extension is not present on the server\n");
-#endif
-
-#ifdef XINERAMA
-    extensions_xinerama =
-        XineramaQueryExtension(ob_display, &extensions_xinerama_event_basep,
-                               &junk) && XineramaIsActive(ob_display);
-    if (!extensions_xinerama)
-        ob_debug("Xinerama extension is not present on the server\n");
-#endif
-
-#ifdef XRANDR
-    extensions_randr =
-        XRRQueryExtension(ob_display, &extensions_randr_event_basep,
-                          &junk);
-    if (!extensions_randr)
-        ob_debug("XRandR extension is not present on the server\n");
-#endif
-
-#ifdef SYNC
-    extensions_sync =
-        XSyncQueryExtension(ob_display, &extensions_sync_event_basep,
-                            &junk) &&
-        XSyncInitialize(ob_display, &junk, &junk);
-    if (!extensions_sync)
-        ob_debug("X Sync extension is not present on the server or is an "
-                 "incompatible version\n");
-#endif
-}
-
-void extensions_xinerama_screens(Rect **xin_areas, guint *nxin)
-{
-    guint i;
-    gint n, l, r, t, b;
-#ifdef XINERAMA
-    XineramaScreenInfo *info;
-#endif
-
-    if (ob_debug_xinerama) {
-        gint w = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
-        gint h = HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen));
-        *nxin = 2;
-        *xin_areas = g_new(Rect, *nxin + 1);
-        RECT_SET((*xin_areas)[0], 0, 0, w/2, h);
-        RECT_SET((*xin_areas)[1], w/2, 0, w-(w/2), h);
-    }
-#ifdef XINERAMA
-    else if (extensions_xinerama &&
-             (info = XineramaQueryScreens(ob_display, &n))) {
-        *nxin = n;
-        *xin_areas = g_new(Rect, *nxin + 1);
-        for (i = 0; i < *nxin; ++i)
-            RECT_SET((*xin_areas)[i], info[i].x_org, info[i].y_org,
-                     info[i].width, info[i].height);
-        XFree(info);
-    }
-#endif
-    else
-    {
-        *nxin = 1;
-        *xin_areas = g_new(Rect, *nxin + 1);
-        RECT_SET((*xin_areas)[0], 0, 0,
-                 WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen)),
-                 HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen)));
-    }
-
-    /* returns one extra with the total area in it */
-    l = (*xin_areas)[0].x;
-    t = (*xin_areas)[0].y;
-    r = (*xin_areas)[0].x + (*xin_areas)[0].width - 1;
-    b = (*xin_areas)[0].y + (*xin_areas)[0].height - 1;
-    for (i = 1; i < *nxin; ++i) {
-        l = MIN(l, (*xin_areas)[i].x);
-        t = MIN(l, (*xin_areas)[i].y);
-        r = MAX(r, (*xin_areas)[i].x + (*xin_areas)[i].width - 1);
-        b = MAX(b, (*xin_areas)[i].y + (*xin_areas)[i].height - 1);
-    }
-    RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1);
-}
diff --git a/openbox/extensions.h b/openbox/extensions.h
deleted file mode 100644 (file)
index 3155874..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   extensions.h for the Openbox window manager
-   Copyright (c) 2006        Mikael Magnusson
-   Copyright (c) 2003-2007   Dana Jansens
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#ifndef __extensions_h
-#define __extensions_h
-
-#include "geom.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h> /* shape.h uses Region which is in here */
-#ifdef    XKB
-#include <X11/XKBlib.h>
-#endif
-#ifdef    SHAPE
-#include <X11/extensions/shape.h>
-#endif
-#ifdef    XINERAMA
-#include <X11/extensions/Xinerama.h>
-#endif
-#ifdef    XRANDR
-#include <X11/extensions/Xrandr.h>
-#endif
-#ifdef    SYNC
-#include <X11/extensions/sync.h>
-#endif
-
-#include <glib.h>
-
-/*! Does the display have the XKB extension? */
-extern gboolean extensions_xkb;
-/*! Base for events for the XKB extension */
-extern gint extensions_xkb_event_basep;
-
-/*! Does the display have the Shape extension? */
-extern gboolean extensions_shape;
-/*! Base for events for the Shape extension */
-extern gint extensions_shape_event_basep;
-
-/*! Does the display have the Xinerama extension? */
-extern gboolean extensions_xinerama;
-/*! Base for events for the Xinerama extension */
-extern gint extensions_xinerama_event_basep;
-
-/*! Does the display have the RandR extension? */
-extern gboolean extensions_randr;
-/*! Base for events for the Randr extension */
-extern gint extensions_randr_event_basep;
-
-/*! Does the display have the Sync extension? */
-extern gboolean extensions_sync;
-/*! Base for events for the Sync extension */
-extern gint extensions_sync_event_basep;
-
-void extensions_query_all();
-
-void extensions_xinerama_screens(Rect **areas, guint *nxin);
-
-#endif
index 36d754f..0b1d5bc 100644 (file)
 #include "group.h"
 #include "focus_cycle.h"
 #include "screen.h"
-#include "prop.h"
 #include "keyboard.h"
 #include "focus.h"
 #include "stacking.h"
+#include "obt/prop.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
@@ -52,7 +52,7 @@ void focus_shutdown(gboolean reconfig)
     if (reconfig) return;
 
     /* reset focus to root */
-    XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime);
+    XSetInputFocus(obt_display, PointerRoot, RevertToNone, CurrentTime);
 }
 
 static void push_to_top(ObClient *client)
@@ -74,7 +74,7 @@ void focus_set_client(ObClient *client)
     Window active;
 
     ob_debug_type(OB_DEBUG_FOCUS,
-                  "focus_set_client 0x%lx\n", client ? client->window : 0);
+                  "focus_set_client 0x%lx", client ? client->window : 0);
 
     if (focus_client == client)
         return;
@@ -98,8 +98,7 @@ void focus_set_client(ObClient *client)
     /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
     if (ob_state() != OB_STATE_EXITING) {
         active = client ? client->window : None;
-        PROP_SET32(RootWindow(ob_display, ob_screen),
-                   net_active_window, window, active);
+        OBT_PROP_SET32(obt_root(ob_screen), NET_ACTIVE_WINDOW, WINDOW, active);
     }
 }
 
@@ -111,18 +110,18 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
     GList *it;
     ObClient *c;
 
-    ob_debug_type(OB_DEBUG_FOCUS, "trying pointer stuff\n");
+    ob_debug_type(OB_DEBUG_FOCUS, "trying pointer stuff");
     if (allow_pointer && config_focus_follow)
         if ((c = client_under_pointer()) &&
             (allow_refocus || client_focus_target(c) != old) &&
             (client_normal(c) &&
              client_focus(c)))
         {
-            ob_debug_type(OB_DEBUG_FOCUS, "found in pointer stuff\n");
+            ob_debug_type(OB_DEBUG_FOCUS, "found in pointer stuff");
             return c;
         }
 
-    ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order\n");
+    ob_debug_type(OB_DEBUG_FOCUS, "trying the focus order");
     for (it = focus_order; it; it = g_list_next(it)) {
         c = it->data;
         /* fallback focus to a window if:
@@ -133,17 +132,18 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
            3. it is not shaded
         */
         if ((allow_omnipresent || c->desktop == screen_desktop) &&
-            focus_valid_target(c, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) &&
+            focus_valid_target(c, screen_desktop,
+                               TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) &&
             !c->shaded &&
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
-            ob_debug_type(OB_DEBUG_FOCUS, "found in focus order\n");
+            ob_debug_type(OB_DEBUG_FOCUS, "found in focus order");
             return c;
         }
     }
 
-    ob_debug_type(OB_DEBUG_FOCUS, "trying a desktop window\n");
+    ob_debug_type(OB_DEBUG_FOCUS, "trying a desktop window");
     for (it = focus_order; it; it = g_list_next(it)) {
         c = it->data;
         /* fallback focus to a window if:
@@ -153,11 +153,12 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
            a splashscreen or a desktop window (save the desktop as a
            backup fallback though)
         */
-        if (focus_valid_target(c, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE) &&
+        if (focus_valid_target(c, screen_desktop,
+                               TRUE, FALSE, FALSE, FALSE, TRUE, FALSE) &&
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
-            ob_debug_type(OB_DEBUG_FOCUS, "found a desktop window\n");
+            ob_debug_type(OB_DEBUG_FOCUS, "found a desktop window");
             return c;
         }
     }
@@ -191,7 +192,7 @@ void focus_nothing(void)
     focus_set_client(NULL);
 
     /* when nothing will be focused, send focus to the backup target */
-    XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
+    XSetInputFocus(obt_display, screen_support_win, RevertToPointerRoot,
                    event_curtime);
 }
 
@@ -285,7 +286,8 @@ static gboolean focus_target_has_siblings(ObClient *ft,
         ObClient *c = it->data;
         /* check that it's not a helper window to avoid infinite recursion */
         if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
-            focus_valid_target(c, TRUE, iconic_windows, all_desktops,
+            focus_valid_target(c, screen_desktop,
+                               TRUE, iconic_windows, all_desktops,
                                FALSE, FALSE, FALSE))
         {
             return TRUE;
@@ -295,6 +297,7 @@ static gboolean focus_target_has_siblings(ObClient *ft,
 }
 
 gboolean focus_valid_target(ObClient *ft,
+                            guint    desktop,
                             gboolean helper_windows,
                             gboolean iconic_windows,
                             gboolean all_desktops,
@@ -315,7 +318,7 @@ gboolean focus_valid_target(ObClient *ft,
 
        do this check first because it will usually filter out the most
        windows */
-    ok = (all_desktops || ft->desktop == screen_desktop ||
+    ok = (all_desktops || ft->desktop == desktop ||
           ft->desktop == DESKTOP_ALL);
 
     /* the window can receive focus somehow */
@@ -345,13 +348,17 @@ gboolean focus_valid_target(ObClient *ft,
                   that can be focused instead */
                !focus_target_has_siblings(ft, iconic_windows, all_desktops))));
 
-    /* it's not set to skip the taskbar (but this only applies to normal typed
-       windows, and is overridden if the window is modal or if the user asked
-       for this window to be focused) */
-    ok = ok && (ft->type != OB_CLIENT_TYPE_NORMAL ||
-                ft->modal ||
-                user_request ||
-                !ft->skip_taskbar);
+    /* it's not set to skip the taskbar (but this is overridden if the
+       window is modal or if the user asked for this window to be focused,
+       or if the window is iconified (and does not have any parents with
+       which to uniconify it), and it is not used for windows which are
+       hilited, or dialog windows as these need user interaction and should
+       not be long-lasting windows */
+    ok = ok && (!ft->skip_taskbar ||
+                (ft->modal || user_request ||
+                 (ft->iconic && !ft->parents) ||
+                 ft->demands_attention ||
+                 ft->type == OB_CLIENT_TYPE_DIALOG));
 
     /* it's not going to just send focus off somewhere else (modal window),
        unless that modal window is not one of our valid targets, then let
@@ -359,6 +366,7 @@ gboolean focus_valid_target(ObClient *ft,
     {
         ObClient *cft = client_focus_target(ft);
         ok = ok && (ft == cft || !focus_valid_target(cft,
+                                                     screen_desktop,
                                                      TRUE,
                                                      iconic_windows,
                                                      all_desktops,
index c8af110..47d86d8 100644 (file)
@@ -41,7 +41,7 @@ void focus_shutdown(gboolean reconfig);
 void focus_set_client(struct _ObClient *client);
 
 /*! Focus nothing, but let keyboard events be caught. */
-void focus_nothing();
+void focus_nothing(void);
 
 /*! Call this when you need to focus something! */
 struct _ObClient* focus_fallback(gboolean allow_refocus,
@@ -69,6 +69,7 @@ void focus_order_to_bottom(struct _ObClient *c);
 struct _ObClient *focus_order_find_first(guint desktop);
 
 gboolean focus_valid_target(struct _ObClient *ft,
+                            guint    desktop,
                             gboolean helper_windows,
                             gboolean iconic_windows,
                             gboolean all_desktops,
index da9cd4c..e4c370e 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "focus_cycle.h"
 #include "focus_cycle_indicator.h"
-#include "focus_cycle_popup.h"
 #include "client.h"
 #include "frame.h"
 #include "focus.h"
@@ -98,7 +97,7 @@ void focus_cycle_reorder()
 ObClient* focus_cycle(gboolean forward, gboolean all_desktops,
                       gboolean dock_windows, gboolean desktop_windows,
                       gboolean linear, gboolean interactive,
-                      gboolean showbar, gboolean dialog,
+                      gboolean showbar, ObFocusCyclePopupMode mode,
                       gboolean done, gboolean cancel)
 {
     static GList *order = NULL;
@@ -153,13 +152,13 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops,
                     focus_cycle_type = OB_CYCLE_NORMAL;
                     focus_cycle_draw_indicator(showbar ? ft : NULL);
                 }
-                if (dialog)
-                    /* same arguments as focus_target_valid */
-                    focus_cycle_popup_show(ft,
-                                           focus_cycle_iconic_windows,
-                                           focus_cycle_all_desktops,
-                                           focus_cycle_dock_windows,
-                                           focus_cycle_desktop_windows);
+                /* same arguments as focus_target_valid */
+                focus_cycle_popup_show(ft,
+                                       focus_cycle_iconic_windows,
+                                       focus_cycle_all_desktops,
+                                       focus_cycle_dock_windows,
+                                       focus_cycle_desktop_windows,
+                                       mode);
                 return focus_cycle_target;
             } else if (ft != focus_cycle_target) {
                 focus_cycle_target = ft;
@@ -355,7 +354,7 @@ done_cycle:
 
 gboolean focus_cycle_valid(struct _ObClient *client)
 {
-    return focus_valid_target(client, TRUE,
+    return focus_valid_target(client, screen_desktop, TRUE,
                               focus_cycle_iconic_windows,
                               focus_cycle_all_desktops,
                               focus_cycle_dock_windows,
index 4a97c10..ab477d6 100644 (file)
@@ -21,6 +21,7 @@
 #define __focus_cycle_h
 
 #include "misc.h"
+#include "focus_cycle_popup.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
@@ -37,7 +38,7 @@ void focus_cycle_shutdown(gboolean reconfig);
 struct _ObClient* focus_cycle(gboolean forward, gboolean all_desktops,
                               gboolean dock_windows, gboolean desktop_windows,
                               gboolean linear, gboolean interactive,
-                              gboolean showbar, gboolean dialog,
+                              gboolean showbar, ObFocusCyclePopupMode mode,
                               gboolean done, gboolean cancel);
 struct _ObClient* focus_directional_cycle(ObDirection dir,
                                           gboolean dock_windows,
index 670f48e..8952790 100644 (file)
@@ -23,7 +23,7 @@
 #include "openbox.h"
 #include "frame.h"
 #include "event.h"
-#include "render/render.h"
+#include "obrender/render.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
 
 static struct
 {
-    InternalWindow top;
-    InternalWindow left;
-    InternalWindow right;
-    InternalWindow bottom;
+    ObInternalWindow top;
+    ObInternalWindow left;
+    ObInternalWindow right;
+    ObInternalWindow bottom;
 } focus_indicator;
 
 static RrAppearance *a_focus_indicator;
@@ -45,7 +45,7 @@ static gboolean      visible;
 static Window create_window(Window parent, gulong mask,
                             XSetWindowAttributes *attrib)
 {
-    return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
+    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
                          RrDepth(ob_rr_inst), InputOutput,
                          RrVisual(ob_rr_inst), mask, attrib);
 
@@ -59,38 +59,38 @@ void focus_cycle_indicator_startup(gboolean reconfig)
 
     if (reconfig) return;
 
-    focus_indicator.top.type = Window_Internal;
-    focus_indicator.left.type = Window_Internal;
-    focus_indicator.right.type = Window_Internal;
-    focus_indicator.bottom.type = Window_Internal;
+    focus_indicator.top.type = OB_WINDOW_CLASS_INTERNAL;
+    focus_indicator.left.type = OB_WINDOW_CLASS_INTERNAL;
+    focus_indicator.right.type = OB_WINDOW_CLASS_INTERNAL;
+    focus_indicator.bottom.type = OB_WINDOW_CLASS_INTERNAL;
 
     attr.override_redirect = True;
-    attr.background_pixel = BlackPixel(ob_display, ob_screen);
+    attr.background_pixel = BlackPixel(obt_display, ob_screen);
     focus_indicator.top.window =
-        create_window(RootWindow(ob_display, ob_screen),
+        create_window(obt_root(ob_screen),
                       CWOverrideRedirect | CWBackPixel, &attr);
     focus_indicator.left.window =
-        create_window(RootWindow(ob_display, ob_screen),
+        create_window(obt_root(ob_screen),
                       CWOverrideRedirect | CWBackPixel, &attr);
     focus_indicator.right.window =
-        create_window(RootWindow(ob_display, ob_screen),
+        create_window(obt_root(ob_screen),
                       CWOverrideRedirect | CWBackPixel, &attr);
     focus_indicator.bottom.window =
-        create_window(RootWindow(ob_display, ob_screen),
+        create_window(obt_root(ob_screen),
                       CWOverrideRedirect | CWBackPixel, &attr);
 
     stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top));
     stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left));
     stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.right));
     stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.bottom));
-    g_hash_table_insert(window_map, &focus_indicator.top.window,
-                        &focus_indicator.top);
-    g_hash_table_insert(window_map, &focus_indicator.left.window,
-                        &focus_indicator.left);
-    g_hash_table_insert(window_map, &focus_indicator.right.window,
-                        &focus_indicator.right);
-    g_hash_table_insert(window_map, &focus_indicator.bottom.window,
-                        &focus_indicator.bottom);
+    window_add(&focus_indicator.top.window,
+               INTERNAL_AS_WINDOW(&focus_indicator.top));
+    window_add(&focus_indicator.left.window,
+               INTERNAL_AS_WINDOW(&focus_indicator.left));
+    window_add(&focus_indicator.right.window,
+               INTERNAL_AS_WINDOW(&focus_indicator.right));
+    window_add(&focus_indicator.bottom.window,
+               INTERNAL_AS_WINDOW(&focus_indicator.bottom));
 
     color_white = RrColorNew(ob_rr_inst, 0xff, 0xff, 0xff);
 
@@ -117,20 +117,20 @@ void focus_cycle_indicator_shutdown(gboolean reconfig)
 
     RrAppearanceFree(a_focus_indicator);
 
-    g_hash_table_remove(window_map, &focus_indicator.top.window);
-    g_hash_table_remove(window_map, &focus_indicator.left.window);
-    g_hash_table_remove(window_map, &focus_indicator.right.window);
-    g_hash_table_remove(window_map, &focus_indicator.bottom.window);
+    window_remove(focus_indicator.top.window);
+    window_remove(focus_indicator.left.window);
+    window_remove(focus_indicator.right.window);
+    window_remove(focus_indicator.bottom.window);
 
     stacking_remove(INTERNAL_AS_WINDOW(&focus_indicator.top));
     stacking_remove(INTERNAL_AS_WINDOW(&focus_indicator.left));
     stacking_remove(INTERNAL_AS_WINDOW(&focus_indicator.right));
     stacking_remove(INTERNAL_AS_WINDOW(&focus_indicator.bottom));
 
-    XDestroyWindow(ob_display, focus_indicator.top.window);
-    XDestroyWindow(ob_display, focus_indicator.left.window);
-    XDestroyWindow(ob_display, focus_indicator.right.window);
-    XDestroyWindow(ob_display, focus_indicator.bottom.window);
+    XDestroyWindow(obt_display, focus_indicator.top.window);
+    XDestroyWindow(obt_display, focus_indicator.left.window);
+    XDestroyWindow(obt_display, focus_indicator.right.window);
+    XDestroyWindow(obt_display, focus_indicator.bottom.window);
 }
 
 void focus_cycle_update_indicator(ObClient *c)
@@ -147,10 +147,10 @@ void focus_cycle_draw_indicator(ObClient *c)
         /* kill enter events cause by this unmapping */
         ignore_start = event_start_ignore_all_enters();
 
-        XUnmapWindow(ob_display, focus_indicator.top.window);
-        XUnmapWindow(ob_display, focus_indicator.left.window);
-        XUnmapWindow(ob_display, focus_indicator.right.window);
-        XUnmapWindow(ob_display, focus_indicator.bottom.window);
+        XUnmapWindow(obt_display, focus_indicator.top.window);
+        XUnmapWindow(obt_display, focus_indicator.left.window);
+        XUnmapWindow(obt_display, focus_indicator.right.window);
+        XUnmapWindow(obt_display, focus_indicator.bottom.window);
 
         event_end_ignore_all_enters(ignore_start);
 
@@ -176,7 +176,7 @@ void focus_cycle_draw_indicator(ObClient *c)
         /* kill enter events cause by this moving */
         ignore_start = event_start_ignore_all_enters();
 
-        XMoveResizeWindow(ob_display, focus_indicator.top.window,
+        XMoveResizeWindow(obt_display, focus_indicator.top.window,
                           x, y, w, h);
         a_focus_indicator->texture[0].data.lineart.x1 = 0;
         a_focus_indicator->texture[0].data.lineart.y1 = h-1;
@@ -202,7 +202,7 @@ void focus_cycle_draw_indicator(ObClient *c)
         w = wl;
         h = c->frame->area.height;
 
-        XMoveResizeWindow(ob_display, focus_indicator.left.window,
+        XMoveResizeWindow(obt_display, focus_indicator.left.window,
                           x, y, w, h);
         a_focus_indicator->texture[0].data.lineart.x1 = w-1;
         a_focus_indicator->texture[0].data.lineart.y1 = 0;
@@ -228,7 +228,7 @@ void focus_cycle_draw_indicator(ObClient *c)
         w = wr;
         h = c->frame->area.height ;
 
-        XMoveResizeWindow(ob_display, focus_indicator.right.window,
+        XMoveResizeWindow(obt_display, focus_indicator.right.window,
                           x, y, w, h);
         a_focus_indicator->texture[0].data.lineart.x1 = 0;
         a_focus_indicator->texture[0].data.lineart.y1 = 0;
@@ -254,7 +254,7 @@ void focus_cycle_draw_indicator(ObClient *c)
         w = c->frame->area.width;
         h = wb;
 
-        XMoveResizeWindow(ob_display, focus_indicator.bottom.window,
+        XMoveResizeWindow(obt_display, focus_indicator.bottom.window,
                           x, y, w, h);
         a_focus_indicator->texture[0].data.lineart.x1 = 0;
         a_focus_indicator->texture[0].data.lineart.y1 = 0;
@@ -275,10 +275,10 @@ void focus_cycle_draw_indicator(ObClient *c)
         RrPaint(a_focus_indicator, focus_indicator.bottom.window,
                 w, h);
 
-        XMapWindow(ob_display, focus_indicator.top.window);
-        XMapWindow(ob_display, focus_indicator.left.window);
-        XMapWindow(ob_display, focus_indicator.right.window);
-        XMapWindow(ob_display, focus_indicator.bottom.window);
+        XMapWindow(obt_display, focus_indicator.top.window);
+        XMapWindow(obt_display, focus_indicator.left.window);
+        XMapWindow(obt_display, focus_indicator.right.window);
+        XMapWindow(obt_display, focus_indicator.bottom.window);
 
         event_end_ignore_all_enters(ignore_start);
 
index d7ac9f5..08016fe 100644 (file)
 #include "screen.h"
 #include "focus.h"
 #include "openbox.h"
+#include "config.h"
 #include "window.h"
 #include "event.h"
-#include "render/render.h"
+#include "obrender/render.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
 
-#define ICON_SIZE 40
-#define ICON_HILITE_WIDTH 2
-#define ICON_HILITE_MARGIN 1
+/* Size of the icons, which can appear inside or outside of a hilite box */
+#define ICON_SIZE (gint)config_theme_window_list_icon_size
+/* Size of the hilite box around a window's icon */
+#define HILITE_SIZE (ICON_SIZE + 2*HILITE_OFFSET)
+/* Width of the outer ring around the hilite box */
+#define HILITE_WIDTH 2
+/* Space between the outer ring around the hilite box and the icon inside it */
+#define HILITE_MARGIN 1
+/* Total distance from the edge of the hilite box to the icon inside it */
+#define HILITE_OFFSET (HILITE_WIDTH + HILITE_MARGIN)
+/* Margin area around the outside of the dialog */
 #define OUTSIDE_BORDER 3
+/* Margin area around the text */
 #define TEXT_BORDER 2
+/* Scroll the list-mode list when the cursor gets within this many rows of the
+   top or bottom */
+#define SCROLL_MARGIN 4
 
 typedef struct _ObFocusCyclePopup       ObFocusCyclePopup;
 typedef struct _ObFocusCyclePopupTarget ObFocusCyclePopupTarget;
@@ -45,7 +58,9 @@ struct _ObFocusCyclePopupTarget
     ObClient *client;
     RrImage *icon;
     gchar *text;
-    Window win;
+    Window iconwin;
+    /* This is used when the popup is in list mode */
+    Window textwin;
 };
 
 struct _ObFocusCyclePopup
@@ -53,7 +68,11 @@ struct _ObFocusCyclePopup
     ObWindow obwin;
     Window bg;
 
-    Window text;
+    /* This is used when the popup is in icon mode */
+    Window icon_mode_text;
+
+    Window list_mode_up;
+    Window list_mode_down;
 
     GList *targets;
     gint n_targets;
@@ -62,13 +81,17 @@ struct _ObFocusCyclePopup
 
     gint maxtextw;
 
+    /* How are the list is scrolled, in scroll mode */
+    gint scroll;
+
     RrAppearance *a_bg;
     RrAppearance *a_text;
+    RrAppearance *a_hilite_text;
     RrAppearance *a_icon;
-
-    RrPixel32 *hilite_rgba;
+    RrAppearance *a_arrow;
 
     gboolean mapped;
+    ObFocusCyclePopupMode mode;
 };
 
 /*! This popup shows all possible windows */
@@ -86,7 +109,7 @@ static void     popup_render   (ObFocusCyclePopup *p,
 static Window create_window(Window parent, guint bwidth, gulong mask,
                             XSetWindowAttributes *attr)
 {
-    return XCreateWindow(ob_display, parent, 0, 0, 1, 1, bwidth,
+    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, bwidth,
                          RrDepth(ob_rr_inst), InputOutput,
                          RrVisual(ob_rr_inst), mask, attr);
 }
@@ -94,48 +117,100 @@ static Window create_window(Window parent, guint bwidth, gulong mask,
 void focus_cycle_popup_startup(gboolean reconfig)
 {
     XSetWindowAttributes attrib;
+    RrPixel32 *p;
 
     single_popup = icon_popup_new();
 
-    popup.obwin.type = Window_Internal;
-    popup.a_bg = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg);
-    popup.a_text = RrAppearanceCopy(ob_rr_theme->osd_hilite_label);
-    popup.a_icon = RrAppearanceCopy(ob_rr_theme->a_clear_tex);
+    popup.obwin.type = OB_WINDOW_CLASS_INTERNAL;
+    popup.a_bg = RrAppearanceCopy(ob_rr_theme->osd_bg);
+    popup.a_hilite_text = RrAppearanceCopy(ob_rr_theme->osd_hilite_label);
+    popup.a_text = RrAppearanceCopy(ob_rr_theme->osd_unhilite_label);
+    popup.a_icon = RrAppearanceCopy(ob_rr_theme->a_clear);
+    popup.a_arrow = RrAppearanceCopy(ob_rr_theme->a_clear_tex);
 
+    popup.a_hilite_text->surface.parent = popup.a_bg;
     popup.a_text->surface.parent = popup.a_bg;
     popup.a_icon->surface.parent = popup.a_bg;
 
+    popup.a_text->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
+    popup.a_hilite_text->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
+
+    /* 2 textures. texture[0] is the icon.  texture[1] is the hilight, and
+       may or may not be used */
+    RrAppearanceAddTextures(popup.a_icon, 2);
+
     RrAppearanceClearTextures(popup.a_icon);
     popup.a_icon->texture[0].type = RR_TEXTURE_IMAGE;
 
-    RrAppearanceAddTextures(popup.a_bg, 1);
-    popup.a_bg->texture[0].type = RR_TEXTURE_RGBA;
+    RrAppearanceClearTextures(popup.a_arrow);
+    popup.a_arrow->texture[0].type = RR_TEXTURE_MASK;
+    popup.a_arrow->texture[0].data.mask.color =
+        ob_rr_theme->osd_text_active_color;
 
     attrib.override_redirect = True;
     attrib.border_pixel=RrColorPixel(ob_rr_theme->osd_border_color);
-    popup.bg = create_window(RootWindow(ob_display, ob_screen),
-                             ob_rr_theme->obwidth,
+    popup.bg = create_window(obt_root(ob_screen), ob_rr_theme->obwidth,
                              CWOverrideRedirect | CWBorderPixel, &attrib);
 
-    popup.text = create_window(popup.bg, 0, 0, NULL);
+    /* create the text window used for the icon-mode popup */
+    popup.icon_mode_text = create_window(popup.bg, 0, 0, NULL);
+
+    /* create the windows for the up and down arrows */
+    popup.list_mode_up = create_window(popup.bg, 0, 0, NULL);
+    popup.list_mode_down = create_window(popup.bg, 0, 0, NULL);
 
     popup.targets = NULL;
     popup.n_targets = 0;
     popup.last_target = NULL;
 
-    popup.hilite_rgba = NULL;
+    /* set up the hilite texture for the icon */
+    popup.a_icon->texture[1].data.rgba.width = HILITE_SIZE;
+    popup.a_icon->texture[1].data.rgba.height = HILITE_SIZE;
+    popup.a_icon->texture[1].data.rgba.alpha = 0xff;
+    p = g_new(RrPixel32, HILITE_SIZE * HILITE_SIZE);
+    popup.a_icon->texture[1].data.rgba.data = p;
 
-    XMapWindow(ob_display, popup.text);
+    /* create the hilite under the target icon */
+    {
+        RrPixel32 color;
+        RrColor *tc;
+        gint x, y, o;
+
+        tc = ob_rr_theme->osd_text_active_color;
+        color = ((tc->r & 0xff) << RrDefaultRedOffset) +
+            ((tc->g & 0xff) << RrDefaultGreenOffset) +
+            ((tc->b & 0xff) << RrDefaultBlueOffset);
+
+        o = 0;
+        for (x = 0; x < HILITE_SIZE; x++)
+            for (y = 0; y < HILITE_SIZE; y++) {
+                guchar a;
+
+                if (x < HILITE_WIDTH ||
+                    x >= HILITE_SIZE - HILITE_WIDTH ||
+                    y < HILITE_WIDTH ||
+                    y >= HILITE_SIZE - HILITE_WIDTH)
+                {
+                    /* the border of the target */
+                    a = 0x88;
+                } else {
+                    /* the background of the target */
+                    a = 0x22;
+                }
+
+                p[o++] = color + (a << RrDefaultAlphaOffset);
+            }
+    }
 
     stacking_add(INTERNAL_AS_WINDOW(&popup));
-    g_hash_table_insert(window_map, &popup.bg, &popup);
+    window_add(&popup.bg, INTERNAL_AS_WINDOW(&popup));
 }
 
 void focus_cycle_popup_shutdown(gboolean reconfig)
 {
     icon_popup_free(single_popup);
 
-    g_hash_table_remove(window_map, &popup.bg);
+    window_remove(popup.bg);
     stacking_remove(INTERNAL_AS_WINDOW(&popup));
 
     while(popup.targets) {
@@ -143,19 +218,24 @@ void focus_cycle_popup_shutdown(gboolean reconfig)
 
         RrImageUnref(t->icon);
         g_free(t->text);
-        XDestroyWindow(ob_display, t->win);
+        XDestroyWindow(obt_display, t->iconwin);
+        XDestroyWindow(obt_display, t->textwin);
         g_free(t);
 
         popup.targets = g_list_delete_link(popup.targets, popup.targets);
     }
 
-    g_free(popup.hilite_rgba);
-    popup.hilite_rgba = NULL;
+    g_free(popup.a_icon->texture[1].data.rgba.data);
+    popup.a_icon->texture[1].data.rgba.data = NULL;
 
-    XDestroyWindow(ob_display, popup.text);
-    XDestroyWindow(ob_display, popup.bg);
+    XDestroyWindow(obt_display, popup.list_mode_up);
+    XDestroyWindow(obt_display, popup.list_mode_down);
+    XDestroyWindow(obt_display, popup.icon_mode_text);
+    XDestroyWindow(obt_display, popup.bg);
 
+    RrAppearanceFree(popup.a_arrow);
     RrAppearanceFree(popup.a_icon);
+    RrAppearanceFree(popup.a_hilite_text);
     RrAppearanceFree(popup.a_text);
     RrAppearanceFree(popup.a_bg);
 }
@@ -164,7 +244,8 @@ static void popup_target_free(ObFocusCyclePopupTarget *t)
 {
     RrImageUnref(t->icon);
     g_free(t->text);
-    XDestroyWindow(ob_display, t->win);
+    XDestroyWindow(obt_display, t->iconwin);
+    XDestroyWindow(obt_display, t->textwin);
     g_free(t);
 }
 
@@ -228,9 +309,9 @@ static gboolean popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
                 p->a_text->texture[0].data.text.string = text;
                 maxwidth = MAX(maxwidth, RrMinWidth(p->a_text));
 
-                if (!create_targets)
+                if (!create_targets) {
                     g_free(text);
-                else {
+                else {
                     ObFocusCyclePopupTarget *t =
                         g_new(ObFocusCyclePopupTarget, 1);
 
@@ -238,9 +319,8 @@ static gboolean popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
                     t->text = text;
                     t->icon = client_icon(t->client);
                     RrImageRef(t->icon); /* own the icon so it won't go away */
-                    t->win = create_window(p->bg, 0, 0, NULL);
-
-                    XMapWindow(ob_display, t->win);
+                    t->iconwin = create_window(p->bg, 0, 0, NULL);
+                    t->textwin = create_window(p->bg, 0, 0, NULL);
 
                     p->targets = g_list_prepend(p->targets, t);
                     ++n;
@@ -261,7 +341,11 @@ static gboolean popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
     }
 
     p->n_targets = n;
-    p->maxtextw = maxwidth;
+    if (refresh_targets)
+        /* don't shrink when refreshing */
+        p->maxtextw = MAX(p->maxtextw, maxwidth);
+    else
+        p->maxtextw = maxwidth;
 
     return change;
 }
@@ -309,16 +393,29 @@ static void popup_render(ObFocusCyclePopup *p, const ObClient *c)
     gint l, t, r, b;
     gint x, y, w, h;
     Rect *screen_area = NULL;
-    gint icons_per_row;
-    gint icon_rows;
-    gint textx, texty, textw, texth;
-    gint rgbax, rgbay, rgbaw, rgbah;
-    gint icons_center_x;
-    gint innerw, innerh;
     gint i;
     GList *it;
     const ObFocusCyclePopupTarget *newtarget;
-    gint newtargetx, newtargety;
+    ObFocusCyclePopupMode mode = p->mode;
+    gint icons_per_row;
+    gint icon_rows;
+    gint textw, texth;
+    gint selected_pos;
+    gint last_scroll;
+
+    /* vars for icon mode */
+    gint icon_mode_textx;
+    gint icon_mode_texty;
+    gint icons_center_x;
+
+    /* vars for list mode */
+    gint list_mode_icon_column_w = HILITE_SIZE + OUTSIDE_BORDER;
+    gint up_arrow_x, down_arrow_x;
+    gint up_arrow_y, down_arrow_y;
+    gboolean showing_arrows = FALSE;
+
+    g_assert(mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS ||
+             mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST);
 
     screen_area = screen_physical_area_primary(FALSE);
 
@@ -331,194 +428,306 @@ static void popup_render(ObFocusCyclePopup *p, const ObClient *c)
     t = mt + OUTSIDE_BORDER;
     b = mb + OUTSIDE_BORDER;
 
-    /* get the icon pictures' sizes */
-    innerw = ICON_SIZE - (ICON_HILITE_WIDTH + ICON_HILITE_MARGIN) * 2;
-    innerh = ICON_SIZE - (ICON_HILITE_WIDTH + ICON_HILITE_MARGIN) * 2;
-
     /* get the width from the text and keep it within limits */
     w = l + r + p->maxtextw;
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
+        /* when in list mode, there are icons down the side */
+        w += list_mode_icon_column_w;
     w = MIN(w, MAX(screen_area->width/3, POPUP_WIDTH)); /* max width */
     w = MAX(w, POPUP_WIDTH); /* min width */
 
-    /* how many icons will fit in that row? make the width fit that */
-    w -= l + r;
-    icons_per_row = (w + ICON_SIZE - 1) / ICON_SIZE;
-    w = icons_per_row * ICON_SIZE + l + r;
-
-    /* how many rows do we need? */
-    icon_rows = (p->n_targets-1) / icons_per_row + 1;
+    /* get the text height */
+    texth = RrMinHeight(p->a_hilite_text);
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
+        texth = MAX(MAX(texth, RrMinHeight(p->a_text)), HILITE_SIZE);
+    else
+        texth += TEXT_BORDER * 2;
+
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS) {
+        /* how many icons will fit in that row? make the width fit that */
+        w -= l + r;
+        icons_per_row = (w + HILITE_SIZE - 1) / HILITE_SIZE;
+        w = icons_per_row * HILITE_SIZE + l + r;
+
+        /* how many rows do we need? */
+        icon_rows = (p->n_targets-1) / icons_per_row + 1;
+    } else {
+        /* in list mode, there is one column of icons.. */
+        icons_per_row = 1;
+        /* maximum is 80% of the screen height */
+        icon_rows = MIN(p->n_targets,
+                        (4*screen_area->height/5) /* 80% of the screen */
+                        /
+                        MAX(HILITE_SIZE, texth)); /* height of each row */
+        /* but make sure there is always one */
+        icon_rows = MAX(icon_rows, 1);
+    }
 
-    /* get the text dimensions */
+    /* get the text width */
     textw = w - l - r;
-    texth = RrMinHeight(p->a_text) + TEXT_BORDER * 2;
-
-    /* find the height of the dialog */
-    h = t + b + (icon_rows * ICON_SIZE) + (OUTSIDE_BORDER + texth);
-
-    /* get the position of the text */
-    textx = l;
-    texty = h - texth - b;
-
-    /* find the position for the popup (include the outer borders) */
-    x = screen_area->x + (screen_area->width -
-                          (w + ob_rr_theme->obwidth * 2)) / 2;
-    y = screen_area->y + (screen_area->height -
-                          (h + ob_rr_theme->obwidth * 2)) / 2;
-
-    /* get the dimensions of the target hilite texture */
-    rgbax = ml;
-    rgbay = mt;
-    rgbaw = w - ml - mr;
-    rgbah = h - mt - mb;
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
+        /* leave space on the side for the icons */
+        textw -= list_mode_icon_column_w;
 
-    /* center the icons if there is less than one row */
-    if (icon_rows == 1)
-        icons_center_x = (w - p->n_targets * ICON_SIZE) / 2;
-    else
-        icons_center_x = 0;
+    if (!p->mapped)
+        /* reset the scrolling when the dialog is first shown */
+        p->scroll = 0;
 
-    if (!p->mapped) {
-        /* position the background but don't draw it*/
-        XMoveResizeWindow(ob_display, p->bg, x, y, w, h);
-
-        /* set up the hilite texture for the background */
-        p->a_bg->texture[0].data.rgba.width = rgbaw;
-        p->a_bg->texture[0].data.rgba.height = rgbah;
-        p->a_bg->texture[0].data.rgba.alpha = 0xff;
-        p->hilite_rgba = g_new(RrPixel32, rgbaw * rgbah);
-        p->a_bg->texture[0].data.rgba.data = p->hilite_rgba;
-
-        /* position the text, but don't draw it */
-        XMoveResizeWindow(ob_display, p->text, textx, texty, textw, texth);
-        p->a_text->surface.parentx = textx;
-        p->a_text->surface.parenty = texty;
-    }
+    /* find the height of the dialog */
+    h = t + b + (icon_rows * MAX(HILITE_SIZE, texth));
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS)
+        /* in icon mode the text sits below the icons, so make some space */
+        h += OUTSIDE_BORDER + texth;
 
     /* find the focused target */
+    newtarget = NULL;
     for (i = 0, it = p->targets; it; ++i, it = g_list_next(it)) {
         const ObFocusCyclePopupTarget *target = it->data;
-        const gint row = i / icons_per_row; /* starting from 0 */
-        const gint col = i % icons_per_row; /* starting from 0 */
-
         if (target->client == c) {
             /* save the target */
             newtarget = target;
-            newtargetx = icons_center_x + l + (col * ICON_SIZE);
-            newtargety = t + (row * ICON_SIZE);
+            break;
+        }
+    }
+    selected_pos = i;
+    g_assert(newtarget != NULL);
 
-            if (!p->mapped)
-                break; /* if we're not dimensioning, then we're done */
+    /* scroll the list if needed */
+    last_scroll = p->scroll;
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST) {
+        const gint top = p->scroll + SCROLL_MARGIN;
+        const gint bottom = p->scroll + icon_rows - SCROLL_MARGIN;
+        const gint min_scroll = 0;
+        const gint max_scroll = p->n_targets - icon_rows;
+
+        if (top - selected_pos >= 0) {
+            p->scroll -= top - selected_pos + 1;
+            p->scroll = MAX(p->scroll, min_scroll);
+        } else if (selected_pos - bottom >= 0) {
+            p->scroll += selected_pos - bottom + 1;
+            p->scroll = MIN(p->scroll, max_scroll);
         }
     }
 
-    g_assert(newtarget != NULL);
+    /* show the scroll arrows when appropriate */
+    if (p->scroll && mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST) {
+        XMapWindow(obt_display, p->list_mode_up);
+        showing_arrows = TRUE;
+    } else
+        XUnmapWindow(obt_display, p->list_mode_up);
 
-    /* create the hilite under the target icon */
+    if (p->scroll < p->n_targets - icon_rows &&
+        mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
     {
-        RrPixel32 color;
-        gint i, j, o;
+        XMapWindow(obt_display, p->list_mode_down);
+        showing_arrows = TRUE;
+    } else
+        XUnmapWindow(obt_display, p->list_mode_down);
 
-        color = ((ob_rr_theme->osd_color->r & 0xff) << RrDefaultRedOffset) +
-            ((ob_rr_theme->osd_color->g & 0xff) << RrDefaultGreenOffset) +
-            ((ob_rr_theme->osd_color->b & 0xff) << RrDefaultBlueOffset);
+    /* make space for the arrows */
+    if (showing_arrows)
+        h += ob_rr_theme->up_arrow_mask->height + OUTSIDE_BORDER
+            + ob_rr_theme->down_arrow_mask->height + OUTSIDE_BORDER;
 
-        o = 0;
-        for (i = 0; i < rgbah; ++i)
-            for (j = 0; j < rgbaw; ++j) {
-                guchar a;
-                const gint x = j + rgbax - newtargetx;
-                const gint y = i + rgbay - newtargety;
+    /* center the icons if there is less than one row */
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS && icon_rows == 1)
+        icons_center_x = (w - p->n_targets * HILITE_SIZE) / 2;
+    else
+        icons_center_x = 0;
 
-                if (x < 0 || x >= ICON_SIZE ||
-                    y < 0 || y >= ICON_SIZE)
-                {
-                    /* outside the target */
-                    a = 0x00;
-                }
-                else if (x < ICON_HILITE_WIDTH ||
-                         x >= ICON_SIZE - ICON_HILITE_WIDTH ||
-                         y < ICON_HILITE_WIDTH ||
-                         y >= ICON_SIZE - ICON_HILITE_WIDTH)
-                {
-                    /* the border of the target */
-                    a = 0x88;
-                }
-                else {
-                    /* the background of the target */
-                    a = 0x22;
-                }
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS) {
+        /* get the position of the text */
+        icon_mode_textx = l;
+        icon_mode_texty = h - texth - b;
+    }
 
-                p->hilite_rgba[o++] =
-                    color + (a << RrDefaultAlphaOffset);
-            }
+    /* find the position for the popup (include the outer borders) */
+    x = screen_area->x + (screen_area->width -
+                          (w + ob_rr_theme->obwidth * 2)) / 2;
+    y = screen_area->y + (screen_area->height -
+                          (h + ob_rr_theme->obwidth * 2)) / 2;
+
+    if (!p->mapped) {
+        /* position the background but don't draw it */
+        XMoveResizeWindow(obt_display, p->bg, x, y, w, h);
+
+        if (mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS) {
+            /* position the text */
+            XMoveResizeWindow(obt_display, p->icon_mode_text,
+                              icon_mode_textx, icon_mode_texty, textw, texth);
+            XMapWindow(obt_display, popup.icon_mode_text);
+        } else {
+            XUnmapWindow(obt_display, popup.icon_mode_text);
+
+            up_arrow_x = (w - ob_rr_theme->up_arrow_mask->width) / 2;
+            up_arrow_y = t;
+
+            down_arrow_x = (w - ob_rr_theme->down_arrow_mask->width) / 2;
+            down_arrow_y = h - b - ob_rr_theme->down_arrow_mask->height;
+
+            /* position the arrows */
+            XMoveResizeWindow(obt_display, p->list_mode_up,
+                              up_arrow_x, up_arrow_y,
+                              ob_rr_theme->up_arrow_mask->width,
+                              ob_rr_theme->up_arrow_mask->height);
+            XMoveResizeWindow(obt_display, p->list_mode_down,
+                              down_arrow_x, down_arrow_y,
+                              ob_rr_theme->down_arrow_mask->width,
+                              ob_rr_theme->down_arrow_mask->height);
+        }
     }
 
     /* * * draw everything * * */
 
     /* draw the background */
-    RrPaint(p->a_bg, p->bg, w, h);
+    if (!p->mapped)
+        RrPaint(p->a_bg, p->bg, w, h);
+
+    /* draw the scroll arrows */
+    if (!p->mapped && mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST) {
+        p->a_arrow->texture[0].data.mask.mask =
+            ob_rr_theme->up_arrow_mask;
+        p->a_arrow->surface.parent = p->a_bg;
+        p->a_arrow->surface.parentx = up_arrow_x;
+        p->a_arrow->surface.parenty = up_arrow_y;
+        RrPaint(p->a_arrow, p->list_mode_up, 
+                ob_rr_theme->up_arrow_mask->width,
+                ob_rr_theme->up_arrow_mask->height);
+
+        p->a_arrow->texture[0].data.mask.mask =
+            ob_rr_theme->down_arrow_mask;
+        p->a_arrow->surface.parent = p->a_bg;
+        p->a_arrow->surface.parentx = down_arrow_x;
+        p->a_arrow->surface.parenty = down_arrow_y;
+        RrPaint(p->a_arrow, p->list_mode_down, 
+                ob_rr_theme->down_arrow_mask->width,
+                ob_rr_theme->down_arrow_mask->height);
+    }
 
-    /* draw the icons */
+    /* draw the icons and text */
     for (i = 0, it = p->targets; it; ++i, it = g_list_next(it)) {
         const ObFocusCyclePopupTarget *target = it->data;
 
-        /* have to redraw the targetted icon and last targetted icon,
-           they can pick up the hilite changes in the backgroud */
-        if (!p->mapped || newtarget == target || p->last_target == target) {
-            const gint row = i / icons_per_row; /* starting from 0 */
-            const gint col = i % icons_per_row; /* starting from 0 */
-            gint innerx, innery;
-
-            /* find the dimensions of the icon inside it */
-            innerx = icons_center_x + l + (col * ICON_SIZE);
-            innerx += ICON_HILITE_WIDTH + ICON_HILITE_MARGIN;
-            innery = t + (row * ICON_SIZE);
-            innery += ICON_HILITE_WIDTH + ICON_HILITE_MARGIN;
-
-            /* move the icon */
-            XMoveResizeWindow(ob_display, target->win,
-                              innerx, innery, innerw, innerh);
+        /* have to redraw the targetted icon and last targetted icon
+         * to update the hilite */
+        if (!p->mapped || newtarget == target || p->last_target == target ||
+            last_scroll != p->scroll)
+        {
+            /* row and column start from 0 */
+            const gint row = i / icons_per_row - p->scroll;
+            const gint col = i % icons_per_row;
+            gint iconx, icony;
+            gint list_mode_textx, list_mode_texty;
+            RrAppearance *text;
+
+            /* find the coordinates for the icon */
+            iconx = icons_center_x + l + (col * HILITE_SIZE);
+            icony = t + (showing_arrows ? ob_rr_theme->up_arrow_mask->height
+                                          + OUTSIDE_BORDER
+                         : 0)
+                + (row * MAX(texth, HILITE_SIZE))
+                + MAX(texth - HILITE_SIZE, 0) / 2;
+
+            /* find the dimensions of the text box */
+            list_mode_textx = iconx + HILITE_SIZE + TEXT_BORDER;
+            list_mode_texty = icony;
+
+            /* position the icon */
+            XMoveResizeWindow(obt_display, target->iconwin,
+                              iconx, icony, HILITE_SIZE, HILITE_SIZE);
+
+            /* position the text */
+            if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
+                XMoveResizeWindow(obt_display, target->textwin,
+                                  list_mode_textx, list_mode_texty,
+                                  textw, texth);
+
+            /* show/hide the right windows */
+            if (row >= 0 && row < icon_rows) {
+                XMapWindow(obt_display, target->iconwin);
+                if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
+                    XMapWindow(obt_display, target->textwin);
+                else
+                    XUnmapWindow(obt_display, target->textwin);
+            } else {
+                XUnmapWindow(obt_display, target->textwin);
+                if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST)
+                    XUnmapWindow(obt_display, target->iconwin);
+                else
+                    XMapWindow(obt_display, target->iconwin);
+            }
 
             /* get the icon from the client */
+            p->a_icon->texture[0].data.image.twidth = ICON_SIZE;
+            p->a_icon->texture[0].data.image.theight = ICON_SIZE;
+            p->a_icon->texture[0].data.image.tx = HILITE_OFFSET;
+            p->a_icon->texture[0].data.image.ty = HILITE_OFFSET;
             p->a_icon->texture[0].data.image.alpha =
                 target->client->iconic ? OB_ICONIC_ALPHA : 0xff;
             p->a_icon->texture[0].data.image.image = target->icon;
 
+            /* Draw the hilite? */
+            p->a_icon->texture[1].type = (target == newtarget) ?
+                RR_TEXTURE_RGBA : RR_TEXTURE_NONE;
+
             /* draw the icon */
-            p->a_icon->surface.parentx = innerx;
-            p->a_icon->surface.parenty = innery;
-            RrPaint(p->a_icon, target->win, innerw, innerh);
+            p->a_icon->surface.parentx = iconx;
+            p->a_icon->surface.parenty = icony;
+            RrPaint(p->a_icon, target->iconwin, HILITE_SIZE, HILITE_SIZE);
+
+            /* draw the text */
+            if (mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST ||
+                target == newtarget)
+            {
+                text = (target == newtarget) ? p->a_hilite_text : p->a_text;
+                text->texture[0].data.text.string = target->text;
+                text->surface.parentx =
+                    mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS ?
+                    icon_mode_textx : list_mode_textx;
+                text->surface.parenty =
+                    mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS ?
+                    icon_mode_texty : list_mode_texty;
+                RrPaint(text,
+                        (mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS ?
+                         p->icon_mode_text : target->textwin),
+                        textw, texth);
+            }
         }
     }
 
-    /* draw the text */
-    p->a_text->texture[0].data.text.string = newtarget->text;
-    p->a_text->surface.parentx = textx;
-    p->a_text->surface.parenty = texty;
-    RrPaint(p->a_text, p->text, textw, texth);
-
     p->last_target = newtarget;
 
     g_free(screen_area);
+
+    XFlush(obt_display);
 }
 
 void focus_cycle_popup_show(ObClient *c, gboolean iconic_windows,
                             gboolean all_desktops, gboolean dock_windows,
-                            gboolean desktop_windows)
+                            gboolean desktop_windows,
+                            ObFocusCyclePopupMode mode)
 {
     g_assert(c != NULL);
 
+    if (mode == OB_FOCUS_CYCLE_POPUP_MODE_NONE) {
+        focus_cycle_popup_hide();
+        return;
+    }
+
     /* do this stuff only when the dialog is first showing */
-    if (!popup.mapped)
+    if (!popup.mapped) {
         popup_setup(&popup, TRUE, FALSE);
+        /* this is fixed once the dialog is shown */
+        popup.mode = mode;
+    }
     g_assert(popup.targets != NULL);
 
     popup_render(&popup, c);
 
     if (!popup.mapped) {
         /* show the dialog */
-        XMapWindow(ob_display, popup.bg);
-        XFlush(ob_display);
+        XMapWindow(obt_display, popup.bg);
+        XFlush(obt_display);
         popup.mapped = TRUE;
         screen_hide_desktop_popup();
     }
@@ -530,17 +739,14 @@ void focus_cycle_popup_hide(void)
 
     ignore_start = event_start_ignore_all_enters();
 
-    XUnmapWindow(ob_display, popup.bg);
-    XFlush(ob_display);
+    XUnmapWindow(obt_display, popup.bg);
+    XFlush(obt_display);
 
     event_end_ignore_all_enters(ignore_start);
 
     popup.mapped = FALSE;
 
     popup_cleanup();
-
-    g_free(popup.hilite_rgba);
-    popup.hilite_rgba = NULL;
 }
 
 void focus_cycle_popup_single_show(struct _ObClient *c,
@@ -640,7 +846,7 @@ ObClient* focus_cycle_popup_refresh(ObClient *target,
     if (target && redraw) {
         popup.mapped = FALSE;
         popup_render(&popup, target);
-        XFlush(ob_display);
+        XFlush(obt_display);
         popup.mapped = TRUE;
     }
 
index 934d9a6..b085f9a 100644 (file)
@@ -24,20 +24,27 @@ struct _ObClient;
 
 #include <glib.h>
 
+typedef enum {
+    OB_FOCUS_CYCLE_POPUP_MODE_NONE,
+    OB_FOCUS_CYCLE_POPUP_MODE_ICONS,
+    OB_FOCUS_CYCLE_POPUP_MODE_LIST
+} ObFocusCyclePopupMode;
+
 void focus_cycle_popup_startup(gboolean reconfig);
 void focus_cycle_popup_shutdown(gboolean reconfig);
 
 void focus_cycle_popup_show(struct _ObClient *c, gboolean iconic_windows,
                             gboolean all_desktops, gboolean dock_windows,
-                            gboolean desktop_windows);
-void focus_cycle_popup_hide();
+                            gboolean desktop_windows,
+                            ObFocusCyclePopupMode mode);
+void focus_cycle_popup_hide(void);
 
 void focus_cycle_popup_single_show(struct _ObClient *c,
                                    gboolean iconic_windows,
                                    gboolean all_desktops,
                                    gboolean dock_windows,
                                    gboolean desktop_windows);
-void focus_cycle_popup_single_hide();
+void focus_cycle_popup_single_hide(void);
 
 gboolean focus_cycle_popup_is_showing(struct _ObClient *c);
 
index 67adb40..8835c63 100644 (file)
 #include "frame.h"
 #include "client.h"
 #include "openbox.h"
-#include "extensions.h"
-#include "prop.h"
 #include "grab.h"
 #include "debug.h"
 #include "config.h"
 #include "framerender.h"
-#include "mainloop.h"
 #include "focus_cycle.h"
 #include "focus_cycle_indicator.h"
 #include "moveresize.h"
 #include "screen.h"
-#include "render/theme.h"
+#include "obrender/theme.h"
+#include "obt/display.h"
+#include "obt/prop.h"
 
 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
                          ButtonPressMask | ButtonReleaseMask | \
@@ -57,7 +56,7 @@ static void frame_adjust_cursors(ObFrame *self);
 static Window createWindow(Window parent, Visual *visual,
                            gulong mask, XSetWindowAttributes *attrib)
 {
-    return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
+    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
                          (visual ? 32 : RrDepth(ob_rr_inst)), InputOutput,
                          (visual ? visual : RrVisual(ob_rr_inst)),
                          mask, attrib);
@@ -74,7 +73,7 @@ static Visual *check_32bit_client(ObClient *c)
     if (RrDepth(ob_rr_inst) == 32)
         return NULL;
 
-    ret = XGetWindowAttributes(ob_display, c->window, &wattrib);
+    ret = XGetWindowAttributes(obt_display, c->window, &wattrib);
     g_assert(ret != BadDrawable);
     g_assert(ret != BadWindow);
 
@@ -103,13 +102,12 @@ ObFrame *frame_new(ObClient *client)
         mask = CWColormap | CWBackPixel | CWBorderPixel;
         /* create a colormap with the visual */
         self->colormap = attrib.colormap =
-            XCreateColormap(ob_display,
-                            RootWindow(ob_display, ob_screen),
+            XCreateColormap(obt_display, obt_root(ob_screen),
                             visual, AllocNone);
-        attrib.background_pixel = BlackPixel(ob_display, ob_screen);
-        attrib.border_pixel = BlackPixel(ob_display, ob_screen);
+        attrib.background_pixel = BlackPixel(obt_display, ob_screen);
+        attrib.border_pixel = BlackPixel(obt_display, ob_screen);
     }
-    self->window = createWindow(RootWindow(ob_display, ob_screen), visual,
+    self->window = createWindow(obt_root(ob_screen), visual,
                                 mask, &attrib);
 
     /* create the visible decor windows */
@@ -180,9 +178,9 @@ ObFrame *frame_new(ObClient *client)
     self->focused = FALSE;
 
     /* the other stuff is shown based on decor settings */
-    XMapWindow(ob_display, self->label);
-    XMapWindow(ob_display, self->backback);
-    XMapWindow(ob_display, self->backfront);
+    XMapWindow(obt_display, self->label);
+    XMapWindow(obt_display, self->backback);
+    XMapWindow(obt_display, self->backfront);
 
     self->max_press = self->close_press = self->desk_press =
         self->iconify_press = self->shade_press = FALSE;
@@ -197,25 +195,25 @@ ObFrame *frame_new(ObClient *client)
 static void set_theme_statics(ObFrame *self)
 {
     /* set colors/appearance/sizes for stuff that doesn't change */
-    XResizeWindow(ob_display, self->max,
+    XResizeWindow(obt_display, self->max,
                   ob_rr_theme->button_size, ob_rr_theme->button_size);
-    XResizeWindow(ob_display, self->iconify,
+    XResizeWindow(obt_display, self->iconify,
                   ob_rr_theme->button_size, ob_rr_theme->button_size);
-    XResizeWindow(ob_display, self->icon,
+    XResizeWindow(obt_display, self->icon,
                   ob_rr_theme->button_size + 2, ob_rr_theme->button_size + 2);
-    XResizeWindow(ob_display, self->close,
+    XResizeWindow(obt_display, self->close,
                   ob_rr_theme->button_size, ob_rr_theme->button_size);
-    XResizeWindow(ob_display, self->desk,
+    XResizeWindow(obt_display, self->desk,
                   ob_rr_theme->button_size, ob_rr_theme->button_size);
-    XResizeWindow(ob_display, self->shade,
+    XResizeWindow(obt_display, self->shade,
                   ob_rr_theme->button_size, ob_rr_theme->button_size);
-    XResizeWindow(ob_display, self->tltresize,
+    XResizeWindow(obt_display, self->tltresize,
                   ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
-    XResizeWindow(ob_display, self->trtresize,
+    XResizeWindow(obt_display, self->trtresize,
                   ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
-    XResizeWindow(ob_display, self->tllresize,
+    XResizeWindow(obt_display, self->tllresize,
                   ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
-    XResizeWindow(ob_display, self->trrresize,
+    XResizeWindow(obt_display, self->trrresize,
                   ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
 }
 
@@ -227,9 +225,9 @@ void frame_free(ObFrame *self)
 {
     free_theme_statics(self);
 
-    XDestroyWindow(ob_display, self->window);
+    XDestroyWindow(obt_display, self->window);
     if (self->colormap)
-        XFreeColormap(ob_display, self->colormap);
+        XFreeColormap(obt_display, self->colormap);
 
     g_free(self);
 }
@@ -243,8 +241,8 @@ void frame_show(ObFrame *self)
            the client gets its MapNotify, i.e. to make sure the client is
            _visible_ when it gets MapNotify. */
         grab_server(TRUE);
-        XMapWindow(ob_display, self->client->window);
-        XMapWindow(ob_display, self->window);
+        XMapWindow(obt_display, self->client->window);
+        XMapWindow(obt_display, self->window);
         grab_server(FALSE);
     }
 }
@@ -254,10 +252,10 @@ void frame_hide(ObFrame *self)
     if (self->visible) {
         self->visible = FALSE;
         if (!frame_iconify_animating(self))
-            XUnmapWindow(ob_display, self->window);
+            XUnmapWindow(obt_display, self->window);
         /* 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);
+        XUnmapWindow(obt_display, self->client->window);
         self->client->ignore_unmaps += 1;
     }
 }
@@ -277,13 +275,13 @@ void frame_adjust_shape_kind(ObFrame *self, int kind)
     if (!((kind == ShapeBounding && self->client->shaped) ||
           (kind == ShapeInput && self->client->shaped_input))) {
         /* clear the shape on the frame window */
-        XShapeCombineMask(ob_display, self->window, kind,
+        XShapeCombineMask(obt_display, self->window, kind,
                           self->size.left,
                           self->size.top,
                           None, ShapeSet);
     } else {
         /* make the frame's shape match the clients */
-        XShapeCombineShape(ob_display, self->window, kind,
+        XShapeCombineShape(obt_display, self->window, kind,
                            self->size.left,
                            self->size.top,
                            self->client->window,
@@ -309,8 +307,8 @@ void frame_adjust_shape_kind(ObFrame *self, int kind)
             ++num;
         }
 
-        XShapeCombineRectangles(ob_display, self->window,
-                                kind, 0, 0, xrect, num,
+        XShapeCombineRectangles(obt_display, self->window,
+                                ShapeBounding, 0, 0, xrect, num,
                                 ShapeUnion, Unsorted);
     }
 }
@@ -391,17 +389,17 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 ob_rr_theme->grip_width - self->size.bottom;
 
             if (self->cbwidth_l) {
-                XMoveResizeWindow(ob_display, self->innerleft,
+                XMoveResizeWindow(obt_display, self->innerleft,
                                   self->size.left - self->cbwidth_l,
                                   self->size.top,
                                   self->cbwidth_l, self->client->area.height);
 
-                XMapWindow(ob_display, self->innerleft);
+                XMapWindow(obt_display, self->innerleft);
             } else
-                XUnmapWindow(ob_display, self->innerleft);
+                XUnmapWindow(obt_display, self->innerleft);
 
             if (self->cbwidth_l && innercornerheight > 0) {
-                XMoveResizeWindow(ob_display, self->innerbll,
+                XMoveResizeWindow(obt_display, self->innerbll,
                                   0,
                                   self->client->area.height - 
                                   (ob_rr_theme->grip_width -
@@ -409,22 +407,22 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->cbwidth_l,
                                   ob_rr_theme->grip_width - self->size.bottom);
 
-                XMapWindow(ob_display, self->innerbll);
+                XMapWindow(obt_display, self->innerbll);
             } else
-                XUnmapWindow(ob_display, self->innerbll);
+                XUnmapWindow(obt_display, self->innerbll);
 
             if (self->cbwidth_r) {
-                XMoveResizeWindow(ob_display, self->innerright,
+                XMoveResizeWindow(obt_display, self->innerright,
                                   self->size.left + self->client->area.width,
                                   self->size.top,
                                   self->cbwidth_r, self->client->area.height);
 
-                XMapWindow(ob_display, self->innerright);
+                XMapWindow(obt_display, self->innerright);
             } else
-                XUnmapWindow(ob_display, self->innerright);
+                XUnmapWindow(obt_display, self->innerright);
 
             if (self->cbwidth_r && innercornerheight > 0) {
-                XMoveResizeWindow(ob_display, self->innerbrr,
+                XMoveResizeWindow(obt_display, self->innerbrr,
                                   0,
                                   self->client->area.height - 
                                   (ob_rr_theme->grip_width -
@@ -432,35 +430,35 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->cbwidth_r,
                                   ob_rr_theme->grip_width - self->size.bottom);
 
-                XMapWindow(ob_display, self->innerbrr);
+                XMapWindow(obt_display, self->innerbrr);
             } else
-                XUnmapWindow(ob_display, self->innerbrr);
+                XUnmapWindow(obt_display, self->innerbrr);
 
             if (self->cbwidth_t) {
-                XMoveResizeWindow(ob_display, self->innertop,
+                XMoveResizeWindow(obt_display, self->innertop,
                                   self->size.left - self->cbwidth_l,
                                   self->size.top - self->cbwidth_t,
                                   self->client->area.width +
                                   self->cbwidth_l + self->cbwidth_r,
                                   self->cbwidth_t);
 
-                XMapWindow(ob_display, self->innertop);
+                XMapWindow(obt_display, self->innertop);
             } else
-                XUnmapWindow(ob_display, self->innertop);
+                XUnmapWindow(obt_display, self->innertop);
 
             if (self->cbwidth_b) {
-                XMoveResizeWindow(ob_display, self->innerbottom,
+                XMoveResizeWindow(obt_display, self->innerbottom,
                                   self->size.left - self->cbwidth_l,
                                   self->size.top + self->client->area.height,
                                   self->client->area.width +
                                   self->cbwidth_l + self->cbwidth_r,
                                   self->cbwidth_b);
 
-                XMoveResizeWindow(ob_display, self->innerblb,
+                XMoveResizeWindow(obt_display, self->innerblb,
                                   0, 0,
                                   ob_rr_theme->grip_width + self->bwidth,
                                   self->cbwidth_b);
-                XMoveResizeWindow(ob_display, self->innerbrb,
+                XMoveResizeWindow(obt_display, self->innerbrb,
                                   self->client->area.width +
                                   self->cbwidth_l + self->cbwidth_r -
                                   (ob_rr_theme->grip_width + self->bwidth),
@@ -468,13 +466,13 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   ob_rr_theme->grip_width + self->bwidth,
                                   self->cbwidth_b);
 
-                XMapWindow(ob_display, self->innerbottom);
-                XMapWindow(ob_display, self->innerblb);
-                XMapWindow(ob_display, self->innerbrb);
+                XMapWindow(obt_display, self->innerbottom);
+                XMapWindow(obt_display, self->innerblb);
+                XMapWindow(obt_display, self->innerbrb);
             } else {
-                XUnmapWindow(ob_display, self->innerbottom);
-                XUnmapWindow(ob_display, self->innerblb);
-                XUnmapWindow(ob_display, self->innerbrb);
+                XUnmapWindow(obt_display, self->innerbottom);
+                XUnmapWindow(obt_display, self->innerblb);
+                XUnmapWindow(obt_display, self->innerbrb);
             }
 
             if (self->bwidth) {
@@ -483,16 +481,16 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                 /* height of titleleft and titleright */
                 titlesides = (!self->max_horz ? ob_rr_theme->grip_width : 0);
 
-                XMoveResizeWindow(ob_display, self->titletop,
+                XMoveResizeWindow(obt_display, self->titletop,
                                   ob_rr_theme->grip_width + self->bwidth, 0,
                                   /* width + bwidth*2 - bwidth*2 - grips*2 */
                                   self->width - ob_rr_theme->grip_width * 2,
                                   self->bwidth);
-                XMoveResizeWindow(ob_display, self->titletopleft,
+                XMoveResizeWindow(obt_display, self->titletopleft,
                                   0, 0,
                                   ob_rr_theme->grip_width + self->bwidth,
                                   self->bwidth);
-                XMoveResizeWindow(ob_display, self->titletopright,
+                XMoveResizeWindow(obt_display, self->titletopright,
                                   self->client->area.width +
                                   self->size.left + self->size.right -
                                   ob_rr_theme->grip_width - self->bwidth,
@@ -501,11 +499,11 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->bwidth);
 
                 if (titlesides > 0) {
-                    XMoveResizeWindow(ob_display, self->titleleft,
+                    XMoveResizeWindow(obt_display, self->titleleft,
                                       0, self->bwidth,
                                       self->bwidth,
                                       titlesides);
-                    XMoveResizeWindow(ob_display, self->titleright,
+                    XMoveResizeWindow(obt_display, self->titleright,
                                       self->client->area.width +
                                       self->size.left + self->size.right -
                                       self->bwidth,
@@ -513,73 +511,73 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                       self->bwidth,
                                       titlesides);
 
-                    XMapWindow(ob_display, self->titleleft);
-                    XMapWindow(ob_display, self->titleright);
+                    XMapWindow(obt_display, self->titleleft);
+                    XMapWindow(obt_display, self->titleright);
                 } else {
-                    XUnmapWindow(ob_display, self->titleleft);
-                    XUnmapWindow(ob_display, self->titleright);
+                    XUnmapWindow(obt_display, self->titleleft);
+                    XUnmapWindow(obt_display, self->titleright);
                 }
 
-                XMapWindow(ob_display, self->titletop);
-                XMapWindow(ob_display, self->titletopleft);
-                XMapWindow(ob_display, self->titletopright);
+                XMapWindow(obt_display, self->titletop);
+                XMapWindow(obt_display, self->titletopleft);
+                XMapWindow(obt_display, self->titletopright);
 
                 if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
-                    XMoveResizeWindow(ob_display, self->titlebottom,
+                    XMoveResizeWindow(obt_display, self->titlebottom,
                                       (self->max_horz ? 0 : self->bwidth),
                                       ob_rr_theme->title_height + self->bwidth,
                                       self->width,
                                       self->bwidth);
 
-                    XMapWindow(ob_display, self->titlebottom);
+                    XMapWindow(obt_display, self->titlebottom);
                 } else
-                    XUnmapWindow(ob_display, self->titlebottom);
+                    XUnmapWindow(obt_display, self->titlebottom);
             } else {
-                XUnmapWindow(ob_display, self->titlebottom);
+                XUnmapWindow(obt_display, self->titlebottom);
 
-                XUnmapWindow(ob_display, self->titletop);
-                XUnmapWindow(ob_display, self->titletopleft);
-                XUnmapWindow(ob_display, self->titletopright);
-                XUnmapWindow(ob_display, self->titleleft);
-                XUnmapWindow(ob_display, self->titleright);
+                XUnmapWindow(obt_display, self->titletop);
+                XUnmapWindow(obt_display, self->titletopleft);
+                XUnmapWindow(obt_display, self->titletopright);
+                XUnmapWindow(obt_display, self->titleleft);
+                XUnmapWindow(obt_display, self->titleright);
             }
 
             if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
-                XMoveResizeWindow(ob_display, self->title,
+                XMoveResizeWindow(obt_display, self->title,
                                   (self->max_horz ? 0 : self->bwidth),
                                   self->bwidth,
                                   self->width, ob_rr_theme->title_height);
 
-                XMapWindow(ob_display, self->title);
+                XMapWindow(obt_display, self->title);
 
                 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
-                    XMoveResizeWindow(ob_display, self->topresize,
+                    XMoveResizeWindow(obt_display, self->topresize,
                                       ob_rr_theme->grip_width,
                                       0,
                                       self->width - ob_rr_theme->grip_width *2,
                                       ob_rr_theme->paddingy + 1);
 
-                    XMoveWindow(ob_display, self->tltresize, 0, 0);
-                    XMoveWindow(ob_display, self->tllresize, 0, 0);
-                    XMoveWindow(ob_display, self->trtresize,
+                    XMoveWindow(obt_display, self->tltresize, 0, 0);
+                    XMoveWindow(obt_display, self->tllresize, 0, 0);
+                    XMoveWindow(obt_display, self->trtresize,
                                 self->width - ob_rr_theme->grip_width, 0);
-                    XMoveWindow(ob_display, self->trrresize,
+                    XMoveWindow(obt_display, self->trrresize,
                                 self->width - ob_rr_theme->paddingx - 1, 0);
 
-                    XMapWindow(ob_display, self->topresize);
-                    XMapWindow(ob_display, self->tltresize);
-                    XMapWindow(ob_display, self->tllresize);
-                    XMapWindow(ob_display, self->trtresize);
-                    XMapWindow(ob_display, self->trrresize);
+                    XMapWindow(obt_display, self->topresize);
+                    XMapWindow(obt_display, self->tltresize);
+                    XMapWindow(obt_display, self->tllresize);
+                    XMapWindow(obt_display, self->trtresize);
+                    XMapWindow(obt_display, self->trrresize);
                 } else {
-                    XUnmapWindow(ob_display, self->topresize);
-                    XUnmapWindow(ob_display, self->tltresize);
-                    XUnmapWindow(ob_display, self->tllresize);
-                    XUnmapWindow(ob_display, self->trtresize);
-                    XUnmapWindow(ob_display, self->trrresize);
+                    XUnmapWindow(obt_display, self->topresize);
+                    XUnmapWindow(obt_display, self->tltresize);
+                    XUnmapWindow(obt_display, self->tllresize);
+                    XUnmapWindow(obt_display, self->trtresize);
+                    XUnmapWindow(obt_display, self->trrresize);
                 }
             } else
-                XUnmapWindow(ob_display, self->title);
+                XUnmapWindow(obt_display, self->title);
         }
 
         if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
@@ -590,7 +588,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             gint sidebwidth = self->max_horz ? 0 : self->bwidth;
 
             if (self->bwidth && self->size.bottom) {
-                XMoveResizeWindow(ob_display, self->handlebottom,
+                XMoveResizeWindow(obt_display, self->handlebottom,
                                   ob_rr_theme->grip_width +
                                   self->bwidth + sidebwidth,
                                   self->size.top + self->client->area.height +
@@ -599,8 +597,9 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                                  sidebwidth) * 2,
                                   self->bwidth);
 
+
                 if (sidebwidth) {
-                    XMoveResizeWindow(ob_display, self->lgripleft,
+                    XMoveResizeWindow(obt_display, self->lgripleft,
                                       0,
                                       self->size.top +
                                       self->client->area.height +
@@ -612,7 +611,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                       (!self->max_horz ?
                                        ob_rr_theme->grip_width :
                                        self->size.bottom - self->cbwidth_b));
-                    XMoveResizeWindow(ob_display, self->rgripright,
+                    XMoveResizeWindow(obt_display, self->rgripright,
                                   self->size.left +
                                       self->client->area.width +
                                       self->size.right - self->bwidth,
@@ -627,20 +626,20 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                        ob_rr_theme->grip_width :
                                        self->size.bottom - self->cbwidth_b));
 
-                    XMapWindow(ob_display, self->lgripleft);
-                    XMapWindow(ob_display, self->rgripright);
+                    XMapWindow(obt_display, self->lgripleft);
+                    XMapWindow(obt_display, self->rgripright);
                 } else {
-                    XUnmapWindow(ob_display, self->lgripleft);
-                    XUnmapWindow(ob_display, self->rgripright);
+                    XUnmapWindow(obt_display, self->lgripleft);
+                    XUnmapWindow(obt_display, self->rgripright);
                 }
 
-                XMoveResizeWindow(ob_display, self->lgripbottom,
+                XMoveResizeWindow(obt_display, self->lgripbottom,
                                   sidebwidth,
                                   self->size.top + self->client->area.height +
                                   self->size.bottom - self->bwidth,
                                   ob_rr_theme->grip_width + self->bwidth,
                                   self->bwidth);
-                XMoveResizeWindow(ob_display, self->rgripbottom,
+                XMoveResizeWindow(obt_display, self->rgripbottom,
                                   self->size.left + self->client->area.width +
                                   self->size.right - self->bwidth - sidebwidth-
                                   ob_rr_theme->grip_width,
@@ -649,29 +648,29 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   ob_rr_theme->grip_width + self->bwidth,
                                   self->bwidth);
 
-                XMapWindow(ob_display, self->handlebottom);
-                XMapWindow(ob_display, self->lgripbottom);
-                XMapWindow(ob_display, self->rgripbottom);
+                XMapWindow(obt_display, self->handlebottom);
+                XMapWindow(obt_display, self->lgripbottom);
+                XMapWindow(obt_display, self->rgripbottom);
 
                 if (self->decorations & OB_FRAME_DECOR_HANDLE &&
                     ob_rr_theme->handle_height > 0)
                 {
-                    XMoveResizeWindow(ob_display, self->handletop,
+                    XMoveResizeWindow(obt_display, self->handletop,
                                       ob_rr_theme->grip_width +
                                       self->bwidth + sidebwidth,
                                       FRAME_HANDLE_Y(self),
                                       self->width - (ob_rr_theme->grip_width +
                                                      sidebwidth) * 2,
                                       self->bwidth);
-                    XMapWindow(ob_display, self->handletop);
+                    XMapWindow(obt_display, self->handletop);
 
                     if (self->decorations & OB_FRAME_DECOR_GRIPS) {
-                        XMoveResizeWindow(ob_display, self->handleleft,
+                        XMoveResizeWindow(obt_display, self->handleleft,
                                           ob_rr_theme->grip_width,
                                           0,
                                           self->bwidth,
                                           ob_rr_theme->handle_height);
-                        XMoveResizeWindow(ob_display, self->handleright,
+                        XMoveResizeWindow(obt_display, self->handleright,
                                           self->width -
                                           ob_rr_theme->grip_width -
                                           self->bwidth,
@@ -679,13 +678,13 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                           self->bwidth,
                                           ob_rr_theme->handle_height);
 
-                        XMoveResizeWindow(ob_display, self->lgriptop,
+                        XMoveResizeWindow(obt_display, self->lgriptop,
                                           sidebwidth,
                                           FRAME_HANDLE_Y(self),
                                           ob_rr_theme->grip_width +
                                           self->bwidth,
                                           self->bwidth);
-                        XMoveResizeWindow(ob_display, self->rgriptop,
+                        XMoveResizeWindow(obt_display, self->rgriptop,
                                           self->size.left +
                                           self->client->area.width +
                                           self->size.right - self->bwidth -
@@ -695,77 +694,77 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                           self->bwidth,
                                           self->bwidth);
 
-                        XMapWindow(ob_display, self->handleleft);
-                        XMapWindow(ob_display, self->handleright);
-                        XMapWindow(ob_display, self->lgriptop);
-                        XMapWindow(ob_display, self->rgriptop);
+                        XMapWindow(obt_display, self->handleleft);
+                        XMapWindow(obt_display, self->handleright);
+                        XMapWindow(obt_display, self->lgriptop);
+                        XMapWindow(obt_display, self->rgriptop);
                     } else {
-                        XUnmapWindow(ob_display, self->handleleft);
-                        XUnmapWindow(ob_display, self->handleright);
-                        XUnmapWindow(ob_display, self->lgriptop);
-                        XUnmapWindow(ob_display, self->rgriptop);
+                        XUnmapWindow(obt_display, self->handleleft);
+                        XUnmapWindow(obt_display, self->handleright);
+                        XUnmapWindow(obt_display, self->lgriptop);
+                        XUnmapWindow(obt_display, self->rgriptop);
                     }
                 } else {
-                    XUnmapWindow(ob_display, self->handleleft);
-                    XUnmapWindow(ob_display, self->handleright);
-                    XUnmapWindow(ob_display, self->lgriptop);
-                    XUnmapWindow(ob_display, self->rgriptop);
+                    XUnmapWindow(obt_display, self->handleleft);
+                    XUnmapWindow(obt_display, self->handleright);
+                    XUnmapWindow(obt_display, self->lgriptop);
+                    XUnmapWindow(obt_display, self->rgriptop);
 
-                    XUnmapWindow(ob_display, self->handletop);
+                    XUnmapWindow(obt_display, self->handletop);
                 }
             } else {
-                XUnmapWindow(ob_display, self->handleleft);
-                XUnmapWindow(ob_display, self->handleright);
-                XUnmapWindow(ob_display, self->lgriptop);
-                XUnmapWindow(ob_display, self->rgriptop);
-
-                XUnmapWindow(ob_display, self->handletop);
-
-                XUnmapWindow(ob_display, self->handlebottom);
-                XUnmapWindow(ob_display, self->lgripleft);
-                XUnmapWindow(ob_display, self->rgripright);
-                XUnmapWindow(ob_display, self->lgripbottom);
-                XUnmapWindow(ob_display, self->rgripbottom);
+                XUnmapWindow(obt_display, self->handleleft);
+                XUnmapWindow(obt_display, self->handleright);
+                XUnmapWindow(obt_display, self->lgriptop);
+                XUnmapWindow(obt_display, self->rgriptop);
+
+                XUnmapWindow(obt_display, self->handletop);
+
+                XUnmapWindow(obt_display, self->handlebottom);
+                XUnmapWindow(obt_display, self->lgripleft);
+                XUnmapWindow(obt_display, self->rgripright);
+                XUnmapWindow(obt_display, self->lgripbottom);
+                XUnmapWindow(obt_display, self->rgripbottom);
             }
 
             if (self->decorations & OB_FRAME_DECOR_HANDLE &&
                 ob_rr_theme->handle_height > 0)
             {
-                XMoveResizeWindow(ob_display, self->handle,
+                XMoveResizeWindow(obt_display, self->handle,
                                   sidebwidth,
                                   FRAME_HANDLE_Y(self) + self->bwidth,
                                   self->width, ob_rr_theme->handle_height);
-                XMapWindow(ob_display, self->handle);
+                XMapWindow(obt_display, self->handle);
 
                 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
-                    XMoveResizeWindow(ob_display, self->lgrip,
+                    XMoveResizeWindow(obt_display, self->lgrip,
                                       0, 0,
                                       ob_rr_theme->grip_width,
                                       ob_rr_theme->handle_height);
-                    XMoveResizeWindow(ob_display, self->rgrip,
+                    XMoveResizeWindow(obt_display, self->rgrip,
                                       self->width - ob_rr_theme->grip_width,
                                       0,
                                       ob_rr_theme->grip_width,
                                       ob_rr_theme->handle_height);
 
-                    XMapWindow(ob_display, self->lgrip);
-                    XMapWindow(ob_display, self->rgrip);
+                    XMapWindow(obt_display, self->lgrip);
+                    XMapWindow(obt_display, self->rgrip);
                 } else {
-                    XUnmapWindow(ob_display, self->lgrip);
-                    XUnmapWindow(ob_display, self->rgrip);
+                    XUnmapWindow(obt_display, self->lgrip);
+                    XUnmapWindow(obt_display, self->rgrip);
                 }
             } else {
-                XUnmapWindow(ob_display, self->lgrip);
-                XUnmapWindow(ob_display, self->rgrip);
+                XUnmapWindow(obt_display, self->lgrip);
+                XUnmapWindow(obt_display, self->rgrip);
 
-                XUnmapWindow(ob_display, self->handle);
+                XUnmapWindow(obt_display, self->handle);
             }
 
             if (self->bwidth && !self->max_horz &&
                 (self->client->area.height + self->size.top +
                  self->size.bottom) > ob_rr_theme->grip_width * 2)
             {
-                XMoveResizeWindow(ob_display, self->left,
+                XMoveResizeWindow(obt_display, self->left,
                                   0,
                                   self->bwidth + ob_rr_theme->grip_width,
                                   self->bwidth,
@@ -773,15 +772,15 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->size.top + self->size.bottom -
                                   ob_rr_theme->grip_width * 2);
 
-                XMapWindow(ob_display, self->left);
+                XMapWindow(obt_display, self->left);
             } else
-                XUnmapWindow(ob_display, self->left);
+                XUnmapWindow(obt_display, self->left);
 
             if (self->bwidth && !self->max_horz &&
                 (self->client->area.height + self->size.top +
                  self->size.bottom) > ob_rr_theme->grip_width * 2)
             {
-                XMoveResizeWindow(ob_display, self->right,
+                XMoveResizeWindow(obt_display, self->right,
                                   self->client->area.width + self->cbwidth_l +
                                   self->cbwidth_r + self->bwidth,
                                   self->bwidth + ob_rr_theme->grip_width,
@@ -790,11 +789,11 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                                   self->size.top + self->size.bottom -
                                   ob_rr_theme->grip_width * 2);
 
-                XMapWindow(ob_display, self->right);
+                XMapWindow(obt_display, self->right);
             } else
-                XUnmapWindow(ob_display, self->right);
+                XUnmapWindow(obt_display, self->right);
 
-            XMoveResizeWindow(ob_display, self->backback,
+            XMoveResizeWindow(obt_display, self->backback,
                               self->size.left, self->size.top,
                               self->client->area.width,
                               self->client->area.height);
@@ -826,7 +825,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
                but don't do this during an iconify animation. it will be
                reflected afterwards.
             */
-            XMoveResizeWindow(ob_display, self->window,
+            XMoveResizeWindow(obt_display, self->window,
                               self->area.x,
                               self->area.y,
                               self->area.width,
@@ -836,7 +835,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
            also this correctly positions the client when it maps.
            this also needs to be run when the frame's decorations sizes change!
         */
-        XMoveWindow(ob_display, self->client->window,
+        XMoveWindow(obt_display, self->client->window,
                     self->size.left, self->size.top);
 
         if (resized) {
@@ -851,10 +850,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
             vals[1] = self->size.right;
             vals[2] = self->size.top;
             vals[3] = self->size.bottom;
-            PROP_SETA32(self->client->window, net_frame_extents,
-                        cardinal, vals, 4);
-            PROP_SETA32(self->client->window, kde_net_wm_frame_strut,
-                        cardinal, vals, 4);
+            OBT_PROP_SETA32(self->client->window, NET_FRAME_EXTENTS,
+                            CARDINAL, vals, 4);
+            OBT_PROP_SETA32(self->client->window, KDE_NET_WM_FRAME_STRUT,
+                            CARDINAL, vals, 4);
         }
 
         /* if this occurs while we are focus cycling, the indicator needs to
@@ -865,7 +864,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
     if (resized && (self->decorations & OB_FRAME_DECOR_TITLEBAR) &&
         self->label_width)
     {
-        XResizeWindow(ob_display, self->label, self->label_width,
+        XResizeWindow(obt_display, self->label, self->label_width,
                       ob_rr_theme->label_height);
     }
 }
@@ -887,58 +886,58 @@ static void frame_adjust_cursors(ObFrame *self)
         /* these ones turn off when max vert, and some when shaded */
         a.cursor = ob_cursor(r && topbot && !sh ?
                              OB_CURSOR_NORTH : OB_CURSOR_NONE);
-        XChangeWindowAttributes(ob_display, self->topresize, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->titletop, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->topresize, CWCursor, &a);
+        XChangeWindowAttributes(obt_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);
-        XChangeWindowAttributes(ob_display, self->innerbottom, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->handle, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->handletop, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->handlebottom, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerbottom, CWCursor, &a);
 
         /* these ones change when shaded */
         a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST) :
                              OB_CURSOR_NONE);
-        XChangeWindowAttributes(ob_display, self->titleleft, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->tltresize, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->tllresize, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->titletopleft, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->titleleft, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->tltresize, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->tllresize, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->titletopleft, CWCursor, &a);
         a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST) :
                              OB_CURSOR_NONE);
-        XChangeWindowAttributes(ob_display, self->titleright, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->trtresize, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->trrresize, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->titletopright, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->titleright, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->trtresize, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->trrresize, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->titletopright, CWCursor,&a);
 
         /* these ones are pretty static */
         a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
-        XChangeWindowAttributes(ob_display, self->left, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->innerleft, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->left, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerleft, CWCursor, &a);
         a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE);
-        XChangeWindowAttributes(ob_display, self->right, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->innerright, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->right, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerright, 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);
-        XChangeWindowAttributes(ob_display, self->lgripleft, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->lgriptop, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->lgripbottom, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->innerbll, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->innerblb, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->lgrip, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->handleleft, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->lgripleft, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->lgriptop, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->lgripbottom, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerbll, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerblb, CWCursor, &a);
         a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
-        XChangeWindowAttributes(ob_display, self->rgrip, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->handleright, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->rgripright, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->rgriptop, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->rgripbottom, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->innerbrr, CWCursor, &a);
-        XChangeWindowAttributes(ob_display, self->innerbrb, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->rgrip, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->handleright, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->rgripright, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->rgriptop, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->rgripbottom, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerbrr, CWCursor, &a);
+        XChangeWindowAttributes(obt_display, self->innerbrb, CWCursor, &a);
     }
 }
 
 void frame_adjust_client_area(ObFrame *self)
 {
     /* adjust the window which is there to prevent flashing on unmap */
-    XMoveResizeWindow(ob_display, self->backfront, 0, 0,
+    XMoveResizeWindow(obt_display, self->backfront, 0, 0,
                       self->client->area.width,
                       self->client->area.height);
 }
@@ -957,7 +956,7 @@ void frame_adjust_focus(ObFrame *self, gboolean hilite)
     self->focused = hilite;
     self->need_render = TRUE;
     framerender_frame(self);
-    XFlush(ob_display);
+    XFlush(obt_display);
 }
 
 void frame_adjust_title(ObFrame *self)
@@ -980,7 +979,7 @@ void frame_grab_client(ObFrame *self)
     */
 
     /* reparent the client to the frame */
-    XReparentWindow(ob_display, self->client->window, self->window, 0, 0);
+    XReparentWindow(obt_display, self->client->window, self->window, 0, 0);
 
     /*
       When reparenting the client window, it is usually not mapped yet, since
@@ -993,54 +992,54 @@ void frame_grab_client(ObFrame *self)
 
     /* select the event mask on the client's parent (to receive config/map
        req's) the ButtonPress is to catch clicks on the client border */
-    XSelectInput(ob_display, self->window, FRAME_EVENTMASK);
+    XSelectInput(obt_display, self->window, FRAME_EVENTMASK);
 
     /* set all the windows for the frame in the window_map */
-    g_hash_table_insert(window_map, &self->window, self->client);
-    g_hash_table_insert(window_map, &self->backback, self->client);
-    g_hash_table_insert(window_map, &self->backfront, self->client);
-    g_hash_table_insert(window_map, &self->innerleft, self->client);
-    g_hash_table_insert(window_map, &self->innertop, self->client);
-    g_hash_table_insert(window_map, &self->innerright, self->client);
-    g_hash_table_insert(window_map, &self->innerbottom, self->client);
-    g_hash_table_insert(window_map, &self->innerblb, self->client);
-    g_hash_table_insert(window_map, &self->innerbll, self->client);
-    g_hash_table_insert(window_map, &self->innerbrb, self->client);
-    g_hash_table_insert(window_map, &self->innerbrr, self->client);
-    g_hash_table_insert(window_map, &self->title, self->client);
-    g_hash_table_insert(window_map, &self->label, self->client);
-    g_hash_table_insert(window_map, &self->max, self->client);
-    g_hash_table_insert(window_map, &self->close, self->client);
-    g_hash_table_insert(window_map, &self->desk, self->client);
-    g_hash_table_insert(window_map, &self->shade, self->client);
-    g_hash_table_insert(window_map, &self->icon, self->client);
-    g_hash_table_insert(window_map, &self->iconify, self->client);
-    g_hash_table_insert(window_map, &self->handle, self->client);
-    g_hash_table_insert(window_map, &self->lgrip, self->client);
-    g_hash_table_insert(window_map, &self->rgrip, self->client);
-    g_hash_table_insert(window_map, &self->topresize, self->client);
-    g_hash_table_insert(window_map, &self->tltresize, self->client);
-    g_hash_table_insert(window_map, &self->tllresize, self->client);
-    g_hash_table_insert(window_map, &self->trtresize, self->client);
-    g_hash_table_insert(window_map, &self->trrresize, self->client);
-    g_hash_table_insert(window_map, &self->left, self->client);
-    g_hash_table_insert(window_map, &self->right, self->client);
-    g_hash_table_insert(window_map, &self->titleleft, self->client);
-    g_hash_table_insert(window_map, &self->titletop, self->client);
-    g_hash_table_insert(window_map, &self->titletopleft, self->client);
-    g_hash_table_insert(window_map, &self->titletopright, self->client);
-    g_hash_table_insert(window_map, &self->titleright, self->client);
-    g_hash_table_insert(window_map, &self->titlebottom, self->client);
-    g_hash_table_insert(window_map, &self->handleleft, self->client);
-    g_hash_table_insert(window_map, &self->handletop, self->client);
-    g_hash_table_insert(window_map, &self->handleright, self->client);
-    g_hash_table_insert(window_map, &self->handlebottom, self->client);
-    g_hash_table_insert(window_map, &self->lgripleft, self->client);
-    g_hash_table_insert(window_map, &self->lgriptop, self->client);
-    g_hash_table_insert(window_map, &self->lgripbottom, self->client);
-    g_hash_table_insert(window_map, &self->rgripright, self->client);
-    g_hash_table_insert(window_map, &self->rgriptop, self->client);
-    g_hash_table_insert(window_map, &self->rgripbottom, self->client);
+    window_add(&self->window, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->backback, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->backfront, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerleft, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innertop, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerright, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerbottom, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerblb, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerbll, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerbrb, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->innerbrr, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->title, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->label, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->max, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->close, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->desk, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->shade, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->icon, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->iconify, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->handle, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->lgrip, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->rgrip, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->topresize, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->tltresize, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->tllresize, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->trtresize, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->trrresize, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->left, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->right, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->titleleft, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->titletop, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->titletopleft, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->titletopright, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->titleright, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->titlebottom, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->handleleft, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->handletop, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->handleright, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->handlebottom, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->lgripleft, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->lgriptop, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->lgripbottom, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->rgripright, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->rgriptop, CLIENT_AS_WINDOW(self->client));
+    window_add(&self->rgripbottom, CLIENT_AS_WINDOW(self->client));
 }
 
 void frame_release_client(ObFrame *self)
@@ -1049,11 +1048,11 @@ void frame_release_client(ObFrame *self)
     gboolean reparent = TRUE;
 
     /* if there was any animation going on, kill it */
-    ob_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
-                                     self, FALSE);
+    obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
+                                      self, FALSE);
 
     /* check if the app has already reparented its window away */
-    while (XCheckTypedWindowEvent(ob_display, self->client->window,
+    while (XCheckTypedWindowEvent(obt_display, self->client->window,
                                   ReparentNotify, &ev))
     {
         /* This check makes sure we don't catch our own reparent action to
@@ -1065,7 +1064,7 @@ void frame_release_client(ObFrame *self)
         */
         if (ev.xreparent.parent != self->window) {
             reparent = FALSE;
-            XPutBackEvent(ob_display, &ev);
+            XPutBackEvent(obt_display, &ev);
             break;
         }
     }
@@ -1073,60 +1072,58 @@ void frame_release_client(ObFrame *self)
     if (reparent) {
         /* according to the ICCCM - if the client doesn't reparent itself,
            then we will reparent the window to root for them */
-        XReparentWindow(ob_display, self->client->window,
-                        RootWindow(ob_display, ob_screen),
-                        self->client->area.x,
-                        self->client->area.y);
+        XReparentWindow(obt_display, self->client->window, obt_root(ob_screen),
+                        self->client->area.x, self->client->area.y);
     }
 
     /* remove all the windows for the frame from the window_map */
-    g_hash_table_remove(window_map, &self->window);
-    g_hash_table_remove(window_map, &self->backback);
-    g_hash_table_remove(window_map, &self->backfront);
-    g_hash_table_remove(window_map, &self->innerleft);
-    g_hash_table_remove(window_map, &self->innertop);
-    g_hash_table_remove(window_map, &self->innerright);
-    g_hash_table_remove(window_map, &self->innerbottom);
-    g_hash_table_remove(window_map, &self->innerblb);
-    g_hash_table_remove(window_map, &self->innerbll);
-    g_hash_table_remove(window_map, &self->innerbrb);
-    g_hash_table_remove(window_map, &self->innerbrr);
-    g_hash_table_remove(window_map, &self->title);
-    g_hash_table_remove(window_map, &self->label);
-    g_hash_table_remove(window_map, &self->max);
-    g_hash_table_remove(window_map, &self->close);
-    g_hash_table_remove(window_map, &self->desk);
-    g_hash_table_remove(window_map, &self->shade);
-    g_hash_table_remove(window_map, &self->icon);
-    g_hash_table_remove(window_map, &self->iconify);
-    g_hash_table_remove(window_map, &self->handle);
-    g_hash_table_remove(window_map, &self->lgrip);
-    g_hash_table_remove(window_map, &self->rgrip);
-    g_hash_table_remove(window_map, &self->topresize);
-    g_hash_table_remove(window_map, &self->tltresize);
-    g_hash_table_remove(window_map, &self->tllresize);
-    g_hash_table_remove(window_map, &self->trtresize);
-    g_hash_table_remove(window_map, &self->trrresize);
-    g_hash_table_remove(window_map, &self->left);
-    g_hash_table_remove(window_map, &self->right);
-    g_hash_table_remove(window_map, &self->titleleft);
-    g_hash_table_remove(window_map, &self->titletop);
-    g_hash_table_remove(window_map, &self->titletopleft);
-    g_hash_table_remove(window_map, &self->titletopright);
-    g_hash_table_remove(window_map, &self->titleright);
-    g_hash_table_remove(window_map, &self->titlebottom);
-    g_hash_table_remove(window_map, &self->handleleft);
-    g_hash_table_remove(window_map, &self->handletop);
-    g_hash_table_remove(window_map, &self->handleright);
-    g_hash_table_remove(window_map, &self->handlebottom);
-    g_hash_table_remove(window_map, &self->lgripleft);
-    g_hash_table_remove(window_map, &self->lgriptop);
-    g_hash_table_remove(window_map, &self->lgripbottom);
-    g_hash_table_remove(window_map, &self->rgripright);
-    g_hash_table_remove(window_map, &self->rgriptop);
-    g_hash_table_remove(window_map, &self->rgripbottom);
-
-    ob_main_loop_timeout_remove_data(ob_main_loop, flash_timeout, self, TRUE);
+    window_remove(self->window);
+    window_remove(self->backback);
+    window_remove(self->backfront);
+    window_remove(self->innerleft);
+    window_remove(self->innertop);
+    window_remove(self->innerright);
+    window_remove(self->innerbottom);
+    window_remove(self->innerblb);
+    window_remove(self->innerbll);
+    window_remove(self->innerbrb);
+    window_remove(self->innerbrr);
+    window_remove(self->title);
+    window_remove(self->label);
+    window_remove(self->max);
+    window_remove(self->close);
+    window_remove(self->desk);
+    window_remove(self->shade);
+    window_remove(self->icon);
+    window_remove(self->iconify);
+    window_remove(self->handle);
+    window_remove(self->lgrip);
+    window_remove(self->rgrip);
+    window_remove(self->topresize);
+    window_remove(self->tltresize);
+    window_remove(self->tllresize);
+    window_remove(self->trtresize);
+    window_remove(self->trrresize);
+    window_remove(self->left);
+    window_remove(self->right);
+    window_remove(self->titleleft);
+    window_remove(self->titletop);
+    window_remove(self->titletopleft);
+    window_remove(self->titletopright);
+    window_remove(self->titleright);
+    window_remove(self->titlebottom);
+    window_remove(self->handleleft);
+    window_remove(self->handletop);
+    window_remove(self->handleright);
+    window_remove(self->handlebottom);
+    window_remove(self->lgripleft);
+    window_remove(self->lgriptop);
+    window_remove(self->lgripbottom);
+    window_remove(self->rgripright);
+    window_remove(self->rgriptop);
+    window_remove(self->rgripbottom);
+
+    obt_main_loop_timeout_remove_data(ob_main_loop, flash_timeout, self, TRUE);
 }
 
 /* is there anything present between us and the label? */
@@ -1244,53 +1241,53 @@ static void layout_title(ObFrame *self)
 
     /* position and map the elements */
     if (self->icon_on) {
-        XMapWindow(ob_display, self->icon);
-        XMoveWindow(ob_display, self->icon, self->icon_x,
+        XMapWindow(obt_display, self->icon);
+        XMoveWindow(obt_display, self->icon, self->icon_x,
                     ob_rr_theme->paddingy);
     } else
-        XUnmapWindow(ob_display, self->icon);
+        XUnmapWindow(obt_display, self->icon);
 
     if (self->desk_on) {
-        XMapWindow(ob_display, self->desk);
-        XMoveWindow(ob_display, self->desk, self->desk_x,
+        XMapWindow(obt_display, self->desk);
+        XMoveWindow(obt_display, self->desk, self->desk_x,
                     ob_rr_theme->paddingy + 1);
     } else
-        XUnmapWindow(ob_display, self->desk);
+        XUnmapWindow(obt_display, self->desk);
 
     if (self->shade_on) {
-        XMapWindow(ob_display, self->shade);
-        XMoveWindow(ob_display, self->shade, self->shade_x,
+        XMapWindow(obt_display, self->shade);
+        XMoveWindow(obt_display, self->shade, self->shade_x,
                     ob_rr_theme->paddingy + 1);
     } else
-        XUnmapWindow(ob_display, self->shade);
+        XUnmapWindow(obt_display, self->shade);
 
     if (self->iconify_on) {
-        XMapWindow(ob_display, self->iconify);
-        XMoveWindow(ob_display, self->iconify, self->iconify_x,
+        XMapWindow(obt_display, self->iconify);
+        XMoveWindow(obt_display, self->iconify, self->iconify_x,
                     ob_rr_theme->paddingy + 1);
     } else
-        XUnmapWindow(ob_display, self->iconify);
+        XUnmapWindow(obt_display, self->iconify);
 
     if (self->max_on) {
-        XMapWindow(ob_display, self->max);
-        XMoveWindow(ob_display, self->max, self->max_x,
+        XMapWindow(obt_display, self->max);
+        XMoveWindow(obt_display, self->max, self->max_x,
                     ob_rr_theme->paddingy + 1);
     } else
-        XUnmapWindow(ob_display, self->max);
+        XUnmapWindow(obt_display, self->max);
 
     if (self->close_on) {
-        XMapWindow(ob_display, self->close);
-        XMoveWindow(ob_display, self->close, self->close_x,
+        XMapWindow(obt_display, self->close);
+        XMoveWindow(obt_display, self->close, self->close_x,
                     ob_rr_theme->paddingy + 1);
     } else
-        XUnmapWindow(ob_display, self->close);
+        XUnmapWindow(obt_display, self->close);
 
     if (self->label_on && self->label_width > 0) {
-        XMapWindow(ob_display, self->label);
-        XMoveWindow(ob_display, self->label, self->label_x,
+        XMapWindow(obt_display, self->label);
+        XMoveWindow(obt_display, self->label, self->label_x,
                     ob_rr_theme->paddingy);
     } else
-        XUnmapWindow(ob_display, self->label);
+        XUnmapWindow(obt_display, self->label);
 }
 
 ObFrameContext frame_context_from_string(const gchar *name)
@@ -1345,7 +1342,7 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y)
     if (moveresize_in_progress)
         return OB_FRAME_CONTEXT_MOVE_RESIZE;
 
-    if (win == RootWindow(ob_display, ob_screen))
+    if (win == obt_root(ob_screen))
         return OB_FRAME_CONTEXT_ROOT ;
     if (client == NULL) return OB_FRAME_CONTEXT_NONE;
     if (win == client->window) {
@@ -1638,12 +1635,12 @@ void frame_flash_start(ObFrame *self)
     self->flash_on = self->focused;
 
     if (!self->flashing)
-        ob_main_loop_timeout_add(ob_main_loop,
-                                 G_USEC_PER_SEC * 0.6,
-                                 flash_timeout,
-                                 self,
-                                 g_direct_equal,
-                                 flash_done);
+        obt_main_loop_timeout_add(ob_main_loop,
+                                  G_USEC_PER_SEC * 0.6,
+                                  flash_timeout,
+                                  self,
+                                  g_direct_equal,
+                                  flash_done);
     g_get_current_time(&self->flash_end);
     g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
 
@@ -1729,8 +1726,8 @@ static gboolean frame_animate_iconify(gpointer p)
         h = self->size.top; /* just the titlebar */
     }
 
-    XMoveResizeWindow(ob_display, self->window, x, y, w, h);
-    XFlush(ob_display);
+    XMoveResizeWindow(obt_display, self->window, x, y, w, h);
+    XFlush(obt_display);
 
     if (time == 0)
         frame_end_iconify_animation(self);
@@ -1744,7 +1741,7 @@ void frame_end_iconify_animation(ObFrame *self)
     if (self->iconify_animation_going == 0) return;
 
     if (!self->visible)
-        XUnmapWindow(ob_display, self->window);
+        XUnmapWindow(obt_display, self->window);
     else {
         /* Send a ConfigureNotify when the animation is done, this fixes
            KDE's pager showing the window in the wrong place.  since the
@@ -1757,12 +1754,12 @@ void frame_end_iconify_animation(ObFrame *self)
     /* we're not animating any more ! */
     self->iconify_animation_going = 0;
 
-    XMoveResizeWindow(ob_display, self->window,
+    XMoveResizeWindow(obt_display, self->window,
                       self->area.x, self->area.y,
                       self->area.width, self->area.height);
     /* we delay re-rendering until after we're done animating */
     framerender_frame(self);
-    XFlush(ob_display);
+    XFlush(obt_display);
 }
 
 void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying)
@@ -1801,18 +1798,18 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying)
     }
 
     if (new_anim) {
-        ob_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
-                                         self, FALSE);
-        ob_main_loop_timeout_add(ob_main_loop,
-                                 FRAME_ANIMATE_ICONIFY_STEP_TIME,
-                                 frame_animate_iconify, self,
-                                 g_direct_equal, NULL);
+        obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
+                                          self, FALSE);
+        obt_main_loop_timeout_add(ob_main_loop,
+                                  FRAME_ANIMATE_ICONIFY_STEP_TIME,
+                                  frame_animate_iconify, self,
+                                  g_direct_equal, NULL);
 
         /* do the first step */
         frame_animate_iconify(self);
 
         /* show it during the animation even if it is not "visible" */
         if (!self->visible)
-            XMapWindow(ob_display, self->window);
+            XMapWindow(obt_display, self->window);
     }
 }
index 8687381..1130709 100644 (file)
@@ -21,7 +21,7 @@
 #define __frame_h
 
 #include "geom.h"
-#include "render/render.h"
+#include "obrender/render.h"
 
 typedef struct _ObFrame ObFrame;
 
index 4720d76..28c12ae 100644 (file)
@@ -22,7 +22,7 @@
 #include "screen.h"
 #include "client.h"
 #include "framerender.h"
-#include "render/theme.h"
+#include "obrender/theme.h"
 
 static void framerender_label(ObFrame *self, RrAppearance *a);
 static void framerender_icon(ObFrame *self, RrAppearance *a);
@@ -49,67 +49,67 @@ void framerender_frame(ObFrame *self)
               RrColorPixel(ob_rr_theme->cb_focused_color) :
               RrColorPixel(ob_rr_theme->cb_unfocused_color));
 
-        XSetWindowBackground(ob_display, self->backback, px);
-        XClearWindow(ob_display, self->backback);
-        XSetWindowBackground(ob_display, self->innerleft, px);
-        XClearWindow(ob_display, self->innerleft);
-        XSetWindowBackground(ob_display, self->innertop, px);
-        XClearWindow(ob_display, self->innertop);
-        XSetWindowBackground(ob_display, self->innerright, px);
-        XClearWindow(ob_display, self->innerright);
-        XSetWindowBackground(ob_display, self->innerbottom, px);
-        XClearWindow(ob_display, self->innerbottom);
-        XSetWindowBackground(ob_display, self->innerbll, px);
-        XClearWindow(ob_display, self->innerbll);
-        XSetWindowBackground(ob_display, self->innerbrr, px);
-        XClearWindow(ob_display, self->innerbrr);
-        XSetWindowBackground(ob_display, self->innerblb, px);
-        XClearWindow(ob_display, self->innerblb);
-        XSetWindowBackground(ob_display, self->innerbrb, px);
-        XClearWindow(ob_display, self->innerbrb);
+        XSetWindowBackground(obt_display, self->backback, px);
+        XClearWindow(obt_display, self->backback);
+        XSetWindowBackground(obt_display, self->innerleft, px);
+        XClearWindow(obt_display, self->innerleft);
+        XSetWindowBackground(obt_display, self->innertop, px);
+        XClearWindow(obt_display, self->innertop);
+        XSetWindowBackground(obt_display, self->innerright, px);
+        XClearWindow(obt_display, self->innerright);
+        XSetWindowBackground(obt_display, self->innerbottom, px);
+        XClearWindow(obt_display, self->innerbottom);
+        XSetWindowBackground(obt_display, self->innerbll, px);
+        XClearWindow(obt_display, self->innerbll);
+        XSetWindowBackground(obt_display, self->innerbrr, px);
+        XClearWindow(obt_display, self->innerbrr);
+        XSetWindowBackground(obt_display, self->innerblb, px);
+        XClearWindow(obt_display, self->innerblb);
+        XSetWindowBackground(obt_display, self->innerbrb, px);
+        XClearWindow(obt_display, self->innerbrb);
 
         px = (self->focused ?
               RrColorPixel(ob_rr_theme->frame_focused_border_color) :
               RrColorPixel(ob_rr_theme->frame_unfocused_border_color));
 
-        XSetWindowBackground(ob_display, self->left, px);
-        XClearWindow(ob_display, self->left);
-        XSetWindowBackground(ob_display, self->right, px);
-        XClearWindow(ob_display, self->right);
-
-        XSetWindowBackground(ob_display, self->titleleft, px);
-        XClearWindow(ob_display, self->titleleft);
-        XSetWindowBackground(ob_display, self->titletop, px);
-        XClearWindow(ob_display, self->titletop);
-        XSetWindowBackground(ob_display, self->titletopleft, px);
-        XClearWindow(ob_display, self->titletopleft);
-        XSetWindowBackground(ob_display, self->titletopright, px);
-        XClearWindow(ob_display, self->titletopright);
-        XSetWindowBackground(ob_display, self->titleright, px);
-        XClearWindow(ob_display, self->titleright);
-
-        XSetWindowBackground(ob_display, self->handleleft, px);
-        XClearWindow(ob_display, self->handleleft);
-        XSetWindowBackground(ob_display, self->handletop, px);
-        XClearWindow(ob_display, self->handletop);
-        XSetWindowBackground(ob_display, self->handleright, px);
-        XClearWindow(ob_display, self->handleright);
-        XSetWindowBackground(ob_display, self->handlebottom, px);
-        XClearWindow(ob_display, self->handlebottom);
-
-        XSetWindowBackground(ob_display, self->lgripleft, px);
-        XClearWindow(ob_display, self->lgripleft);
-        XSetWindowBackground(ob_display, self->lgriptop, px);
-        XClearWindow(ob_display, self->lgriptop);
-        XSetWindowBackground(ob_display, self->lgripbottom, px);
-        XClearWindow(ob_display, self->lgripbottom);
-
-        XSetWindowBackground(ob_display, self->rgripright, px);
-        XClearWindow(ob_display, self->rgripright);
-        XSetWindowBackground(ob_display, self->rgriptop, px);
-        XClearWindow(ob_display, self->rgriptop);
-        XSetWindowBackground(ob_display, self->rgripbottom, px);
-        XClearWindow(ob_display, self->rgripbottom);
+        XSetWindowBackground(obt_display, self->left, px);
+        XClearWindow(obt_display, self->left);
+        XSetWindowBackground(obt_display, self->right, px);
+        XClearWindow(obt_display, self->right);
+
+        XSetWindowBackground(obt_display, self->titleleft, px);
+        XClearWindow(obt_display, self->titleleft);
+        XSetWindowBackground(obt_display, self->titletop, px);
+        XClearWindow(obt_display, self->titletop);
+        XSetWindowBackground(obt_display, self->titletopleft, px);
+        XClearWindow(obt_display, self->titletopleft);
+        XSetWindowBackground(obt_display, self->titletopright, px);
+        XClearWindow(obt_display, self->titletopright);
+        XSetWindowBackground(obt_display, self->titleright, px);
+        XClearWindow(obt_display, self->titleright);
+
+        XSetWindowBackground(obt_display, self->handleleft, px);
+        XClearWindow(obt_display, self->handleleft);
+        XSetWindowBackground(obt_display, self->handletop, px);
+        XClearWindow(obt_display, self->handletop);
+        XSetWindowBackground(obt_display, self->handleright, px);
+        XClearWindow(obt_display, self->handleright);
+        XSetWindowBackground(obt_display, self->handlebottom, px);
+        XClearWindow(obt_display, self->handlebottom);
+
+        XSetWindowBackground(obt_display, self->lgripleft, px);
+        XClearWindow(obt_display, self->lgripleft);
+        XSetWindowBackground(obt_display, self->lgriptop, px);
+        XClearWindow(obt_display, self->lgriptop);
+        XSetWindowBackground(obt_display, self->lgripbottom, px);
+        XClearWindow(obt_display, self->lgripbottom);
+
+        XSetWindowBackground(obt_display, self->rgripright, px);
+        XClearWindow(obt_display, self->rgripright);
+        XSetWindowBackground(obt_display, self->rgriptop, px);
+        XClearWindow(obt_display, self->rgriptop);
+        XSetWindowBackground(obt_display, self->rgripbottom, px);
+        XClearWindow(obt_display, self->rgripbottom);
 
         /* don't use the separator color for shaded windows */
         if (!self->client->shaded)
@@ -117,8 +117,8 @@ void framerender_frame(ObFrame *self)
                   RrColorPixel(ob_rr_theme->title_separator_focused_color) :
                   RrColorPixel(ob_rr_theme->title_separator_unfocused_color));
 
-        XSetWindowBackground(ob_display, self->titlebottom, px);
-        XClearWindow(ob_display, self->titlebottom);
+        XSetWindowBackground(obt_display, self->titlebottom, px);
+        XClearWindow(obt_display, self->titlebottom);
     }
 
     if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
@@ -341,7 +341,7 @@ void framerender_frame(ObFrame *self)
         }
     }
 
-    XFlush(ob_display);
+    XFlush(obt_display);
 }
 
 static void framerender_label(ObFrame *self, RrAppearance *a)
index 03e21bd..e797e44 100644 (file)
 */
 
 #include "grab.h"
-#include "modkeys.h"
 #include "openbox.h"
 #include "event.h"
-#include "xerror.h"
 #include "screen.h"
 #include "debug.h"
+#include "obt/display.h"
+#include "obt/keyboard.h"
 
 #include <glib.h>
 #include <X11/Xlib.h>
@@ -74,7 +74,7 @@ gboolean grab_keyboard_full(gboolean grab)
 
     if (grab) {
         if (kgrabs++ == 0) {
-            ret = XGrabKeyboard(ob_display, RootWindow(ob_display, ob_screen),
+            ret = XGrabKeyboard(obt_display, obt_root(ob_screen),
                                 False, GrabModeAsync, GrabModeAsync,
                                 event_curtime) == Success;
             if (!ret)
@@ -87,7 +87,7 @@ gboolean grab_keyboard_full(gboolean grab)
             ret = TRUE;
     } else if (kgrabs > 0) {
         if (--kgrabs == 0) {
-            XUngrabKeyboard(ob_display, ungrab_time());
+            XUngrabKeyboard(obt_display, ungrab_time());
         }
         ret = TRUE;
     }
@@ -102,11 +102,10 @@ gboolean grab_pointer_full(gboolean grab, gboolean owner_events,
 
     if (grab) {
         if (pgrabs++ == 0) {
-            ret = XGrabPointer(ob_display, screen_support_win, owner_events,
+            ret = XGrabPointer(obt_display, screen_support_win, owner_events,
                                GRAB_PTR_MASK,
                                GrabModeAsync, GrabModeAsync,
-                               (confine ? RootWindow(ob_display, ob_screen) :
-                                None),
+                               (confine ? obt_root(ob_screen) : None),
                                ob_cursor(cur), event_curtime) == Success;
             if (!ret)
                 --pgrabs;
@@ -116,7 +115,7 @@ gboolean grab_pointer_full(gboolean grab, gboolean owner_events,
             ret = TRUE;
     } else if (pgrabs > 0) {
         if (--pgrabs == 0) {
-            XUngrabPointer(ob_display, ungrab_time());
+            XUngrabPointer(obt_display, ungrab_time());
         }
         ret = TRUE;
     }
@@ -128,13 +127,13 @@ gint grab_server(gboolean grab)
     static guint sgrabs = 0;
     if (grab) {
         if (sgrabs++ == 0) {
-            XGrabServer(ob_display);
-            XSync(ob_display, FALSE);
+            XGrabServer(obt_display);
+            XSync(obt_display, FALSE);
         }
     } else if (sgrabs > 0) {
         if (--sgrabs == 0) {
-            XUngrabServer(ob_display);
-            XFlush(ob_display);
+            XUngrabServer(obt_display);
+            XFlush(obt_display);
         }
     }
     return sgrabs;
@@ -145,9 +144,9 @@ void grab_startup(gboolean reconfig)
     guint i = 0;
     guint num, caps, scroll;
 
-    num = modkeys_key_to_mask(OB_MODKEY_KEY_NUMLOCK);
-    caps = modkeys_key_to_mask(OB_MODKEY_KEY_CAPSLOCK);
-    scroll = modkeys_key_to_mask(OB_MODKEY_KEY_SCROLLLOCK);
+    num = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_NUMLOCK);
+    caps = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CAPSLOCK);
+    scroll = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SCROLLLOCK);
 
     mask_list[i++] = 0;
     mask_list[i++] = num;
@@ -174,14 +173,14 @@ void grab_button_full(guint button, guint state, Window win, guint mask,
 {
     guint i;
 
-    xerror_set_ignore(TRUE); /* can get BadAccess from these */
-    xerror_occured = FALSE;
+    /* can get BadAccess from these */
+    obt_display_ignore_errors(TRUE);
     for (i = 0; i < MASK_LIST_SIZE; ++i)
-        XGrabButton(ob_display, button, state | mask_list[i], win, False, mask,
-                    pointer_mode, GrabModeAsync, None, ob_cursor(cur));
-    xerror_set_ignore(FALSE);
-    if (xerror_occured)
-        ob_debug("Failed to grab button %d modifiers %d\n", button, state);
+        XGrabButton(obt_display, button, state | mask_list[i], win, False,
+                    mask, pointer_mode, GrabModeAsync, None, ob_cursor(cur));
+    obt_display_ignore_errors(FALSE);
+    if (obt_display_error_occured)
+        ob_debug("Failed to grab button %d modifiers %d", button, state);
 }
 
 void ungrab_button(guint button, guint state, Window win)
@@ -189,26 +188,26 @@ void ungrab_button(guint button, guint state, Window win)
     guint i;
 
     for (i = 0; i < MASK_LIST_SIZE; ++i)
-        XUngrabButton(ob_display, button, state | mask_list[i], win);
+        XUngrabButton(obt_display, button, state | mask_list[i], win);
 }
 
 void grab_key(guint keycode, guint state, Window win, gint keyboard_mode)
 {
     guint i;
 
-    xerror_set_ignore(TRUE); /* can get BadAccess' from these */
-    xerror_occured = FALSE;
+    /* can get BadAccess' from these */
+    obt_display_ignore_errors(TRUE);
     for (i = 0; i < MASK_LIST_SIZE; ++i)
-        XGrabKey(ob_display, keycode, state | mask_list[i], win, FALSE,
+        XGrabKey(obt_display, keycode, state | mask_list[i], win, FALSE,
                  GrabModeAsync, keyboard_mode);
-    xerror_set_ignore(FALSE);
-    if (xerror_occured)
-        ob_debug("Failed to grab keycode %d modifiers %d\n", keycode, state);
+    obt_display_ignore_errors(FALSE);
+    if (obt_display_error_occured)
+        ob_debug("Failed to grab keycode %d modifiers %d", keycode, state);
 }
 
 void ungrab_all_keys(Window win)
 {
-    XUngrabKey(ob_display, AnyKey, AnyModifier, win);
+    XUngrabKey(obt_display, AnyKey, AnyModifier, win);
 }
 
 void grab_key_passive_count(int change)
@@ -223,7 +222,7 @@ void ungrab_passive_key(void)
     /*ob_debug("ungrabbing %d passive grabs\n", passive_count);*/
     if (passive_count) {
         /* kill our passive grab */
-        XUngrabKeyboard(ob_display, event_curtime);
+        XUngrabKeyboard(obt_display, event_curtime);
         passive_count = 0;
     }
 }
index 30c4b70..8253637 100644 (file)
@@ -38,8 +38,8 @@ gint grab_server(gboolean grab);
 #define grab_pointer(o,c,u) grab_pointer_full(TRUE, (o), (c), (u))
 #define ungrab_pointer() grab_pointer_full(FALSE, FALSE, FALSE, OB_CURSOR_NONE)
 
-gboolean grab_on_keyboard();
-gboolean grab_on_pointer();
+gboolean grab_on_keyboard(void);
+gboolean grab_on_pointer(void);
 
 void grab_button_full(guint button, guint state, Window win, guint mask,
                       gint pointer_mode, ObCursor cursor);
@@ -50,6 +50,6 @@ void grab_key(guint keycode, guint state, Window win, gint keyboard_mode);
 void ungrab_all_keys(Window win);
 
 void grab_key_passive_count(int change);
-void ungrab_passive_key();
+void ungrab_passive_key(void);
 
 #endif
index 0d23485..5f7531e 100644 (file)
@@ -17,7 +17,6 @@
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#include "mainloop.h"
 #include "focus.h"
 #include "screen.h"
 #include "frame.h"
@@ -26,7 +25,6 @@
 #include "grab.h"
 #include "client.h"
 #include "actions.h"
-#include "prop.h"
 #include "menuframe.h"
 #include "config.h"
 #include "keytree.h"
@@ -46,20 +44,20 @@ static void grab_keys(gboolean grab)
 {
     KeyBindingTree *p;
 
-    ungrab_all_keys(RootWindow(ob_display, ob_screen));
+    ungrab_all_keys(obt_root(ob_screen));
 
     if (grab) {
         p = curpos ? curpos->first_child : keyboard_firstnode;
         while (p) {
             if (p->key)
-                grab_key(p->key, p->state, RootWindow(ob_display, ob_screen),
+                grab_key(p->key, p->state, obt_root(ob_screen),
                          GrabModeAsync);
             p = p->next_sibling;
         }
         if (curpos)
             grab_key(config_keyboard_reset_keycode,
                      config_keyboard_reset_state,
-                     RootWindow(ob_display, ob_screen), GrabModeAsync);
+                     obt_root(ob_screen), GrabModeAsync);
     }
 }
 
@@ -206,13 +204,14 @@ gboolean keyboard_process_interactive_grab(const XEvent *e, ObClient **client)
 }
 #endif
 
-void keyboard_event(ObClient *client, const XEvent *e)
+gboolean keyboard_event(ObClient *client, const XEvent *e)
 {
     KeyBindingTree *p;
+    gboolean used;
 
     if (e->type == KeyRelease) {
         grab_key_passive_count(-1);
-        return;
+        return FALSE;
     }
 
     g_assert(e->type == KeyPress);
@@ -221,11 +220,12 @@ void keyboard_event(ObClient *client, const XEvent *e)
     if (e->xkey.keycode == config_keyboard_reset_keycode &&
         e->xkey.state == config_keyboard_reset_state)
     {
-        ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
+        obt_main_loop_timeout_remove(ob_main_loop, chain_timeout);
         keyboard_reset_chains(-1);
-        return;
+        return TRUE;
     }
 
+    used = FALSE;
     if (curpos == NULL)
         p = keyboard_firstnode;
     else
@@ -239,11 +239,11 @@ void keyboard_event(ObClient *client, const XEvent *e)
                 menu_frame_hide_all();
 
             if (p->first_child != NULL) { /* part of a chain */
-                ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
+                obt_main_loop_timeout_remove(ob_main_loop, chain_timeout);
                 /* 3 second timeout for chains */
-                ob_main_loop_timeout_add(ob_main_loop, 3 * G_USEC_PER_SEC,
-                                         chain_timeout, NULL,
-                                         g_direct_equal, NULL);
+                obt_main_loop_timeout_add(ob_main_loop, 3 * G_USEC_PER_SEC,
+                                          chain_timeout, NULL,
+                                          g_direct_equal, NULL);
                 set_curpos(p);
             } else if (p->chroot)         /* an empty chroot */
                 set_curpos(p);
@@ -260,9 +260,11 @@ void keyboard_event(ObClient *client, const XEvent *e)
                                  0, OB_FRAME_CONTEXT_NONE, client);
             }
             break;
+            used = TRUE;
         }
         p = p->next_sibling;
     }
+    return used;
 }
 
 static void node_rebind(KeyBindingTree *node)
@@ -316,7 +318,7 @@ void keyboard_startup(gboolean reconfig)
 
 void keyboard_shutdown(gboolean reconfig)
 {
-    ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
+    obt_main_loop_timeout_remove(ob_main_loop, chain_timeout);
 
     keyboard_unbind_all();
     set_curpos(NULL);
index 995cdbc..c89f67e 100644 (file)
@@ -34,13 +34,13 @@ extern KeyBindingTree *keyboard_firstnode;
 void keyboard_startup(gboolean reconfig);
 void keyboard_shutdown(gboolean reconfig);
 
-void keyboard_rebind();
+void keyboard_rebind(void);
 
 void keyboard_chroot(GList *keylist);
 gboolean keyboard_bind(GList *keylist, struct _ObActionsAct *action);
-void keyboard_unbind_all();
+void keyboard_unbind_all(void);
 
-void keyboard_event(struct _ObClient *client, const XEvent *e);
+gboolean keyboard_event(struct _ObClient *client, const XEvent *e);
 /*! @param break_chroots how many chroots to break. -1 means to break them ALL!
  */
 void keyboard_reset_chains(gint break_chroots);
diff --git a/openbox/mainloop.h b/openbox/mainloop.h
deleted file mode 100644 (file)
index 373528e..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   mainloop.h for the Openbox window manager
-   Copyright (c) 2006        Mikael Magnusson
-   Copyright (c) 2003-2007   Dana Jansens
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#ifndef __ob__mainloop_h
-#define __ob__mainloop_h
-
-#include <X11/Xlib.h>
-#include <glib.h>
-
-typedef struct _ObMainLoop ObMainLoop;
-
-ObMainLoop *ob_main_loop_new(Display *display);
-void        ob_main_loop_destroy(ObMainLoop *loop);
-
-typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data);
-
-void ob_main_loop_x_add(ObMainLoop *loop,
-                        ObMainLoopXHandler handler,
-                        gpointer data,
-                        GDestroyNotify notify);
-void ob_main_loop_x_remove(ObMainLoop *loop,
-                           ObMainLoopXHandler handler);
-
-typedef void (*ObMainLoopFdHandler) (gint fd, gpointer data);
-
-void ob_main_loop_fd_add(ObMainLoop *loop,
-                         gint fd,
-                         ObMainLoopFdHandler handler,
-                         gpointer data,
-                         GDestroyNotify notify);
-void ob_main_loop_fd_remove(ObMainLoop *loop,
-                            gint fd);
-
-typedef void (*ObMainLoopSignalHandler) (gint signal, gpointer data);
-
-void ob_main_loop_signal_add(ObMainLoop *loop,
-                             gint signal,
-                             ObMainLoopSignalHandler handler,
-                             gpointer data,
-                             GDestroyNotify notify);
-void ob_main_loop_signal_remove(ObMainLoop *loop,
-                                ObMainLoopSignalHandler handler);
-
-void ob_main_loop_timeout_add(ObMainLoop *loop,
-                              gulong microseconds,
-                              GSourceFunc handler,
-                              gpointer data,
-                              GEqualFunc cmp,
-                              GDestroyNotify notify);
-void ob_main_loop_timeout_remove(ObMainLoop *loop,
-                                 GSourceFunc handler);
-void ob_main_loop_timeout_remove_data(ObMainLoop *loop,
-                                      GSourceFunc handler,
-                                      gpointer data,
-                                      gboolean cancel_dest);
-
-void ob_main_loop_run(ObMainLoop *loop);
-void ob_main_loop_exit(ObMainLoop *loop);
-
-#endif
index 58b6280..ac28ade 100644 (file)
@@ -20,7 +20,6 @@
 #include "debug.h"
 #include "menu.h"
 #include "openbox.h"
-#include "mainloop.h"
 #include "stacking.h"
 #include "grab.h"
 #include "client.h"
@@ -35,7 +34,8 @@
 #include "client_list_menu.h"
 #include "client_list_combined_menu.h"
 #include "gettext.h"
-#include "parser/parse.h"
+#include "obt/xml.h"
+#include "obt/paths.h"
 
 typedef struct _ObMenuParseState ObMenuParseState;
 
@@ -46,33 +46,20 @@ struct _ObMenuParseState
 };
 
 static GHashTable *menu_hash = NULL;
-static ObParseInst *menu_parse_inst;
+static ObtXmlInst *menu_parse_inst;
 static ObMenuParseState menu_parse_state;
 static gboolean menu_can_hide = FALSE;
 
 static void menu_destroy_hash_value(ObMenu *self);
-static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                            gpointer data);
-static void parse_menu_separator(ObParseInst *i,
-                                 xmlDocPtr doc, xmlNodePtr node,
-                                 gpointer data);
-static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                       gpointer data);
+static void parse_menu_item(xmlNodePtr node, gpointer data);
+static void parse_menu_separator(xmlNodePtr node, gpointer data);
+static void parse_menu(xmlNodePtr node, gpointer data);
 static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
                                gchar **strippedlabel, guint *position,
                                gboolean *always_show);
 
-static void client_dest(ObClient *client, gpointer data)
-{
-    /* menus can be associated with a client, so close any that are since
-       we are disappearing now */
-    menu_frame_hide_all_client(client);
-}
-
 void menu_startup(gboolean reconfig)
 {
-    xmlDocPtr doc;
-    xmlNodePtr node;
     gboolean loaded = FALSE;
     GSList *it;
 
@@ -83,46 +70,48 @@ void menu_startup(gboolean reconfig)
     client_list_combined_menu_startup(reconfig);
     client_menu_startup();
 
-    menu_parse_inst = parse_startup();
+    menu_parse_inst = obt_xml_instance_new();
 
     menu_parse_state.parent = NULL;
     menu_parse_state.pipe_creator = NULL;
-    parse_register(menu_parse_inst, "menu", parse_menu, &menu_parse_state);
-    parse_register(menu_parse_inst, "item", parse_menu_item,
-                   &menu_parse_state);
-    parse_register(menu_parse_inst, "separator",
-                   parse_menu_separator, &menu_parse_state);
+    obt_xml_register(menu_parse_inst, "menu", parse_menu, &menu_parse_state);
+    obt_xml_register(menu_parse_inst, "item", parse_menu_item,
+                     &menu_parse_state);
+    obt_xml_register(menu_parse_inst, "separator",
+                       parse_menu_separator, &menu_parse_state);
 
     for (it = config_menu_files; it; it = g_slist_next(it)) {
-        if (parse_load_menu(it->data, &doc, &node)) {
+        if (obt_xml_load_config_file(menu_parse_inst,
+                                     "openbox",
+                                     it->data,
+                                     "openbox_menu"))
+        {
             loaded = TRUE;
-            parse_tree(menu_parse_inst, doc, node->children);
-            xmlFreeDoc(doc);
+            obt_xml_tree_from_root(menu_parse_inst);
+            obt_xml_close(menu_parse_inst);
         } else
             g_message(_("Unable to find a valid menu file \"%s\""),
                       (const gchar*)it->data);
     }
     if (!loaded) {
-        if (parse_load_menu("menu.xml", &doc, &node)) {
-            parse_tree(menu_parse_inst, doc, node->children);
-            xmlFreeDoc(doc);
+        if (obt_xml_load_config_file(menu_parse_inst,
+                                     "openbox",
+                                     "menu.xml",
+                                     "openbox_menu"))
+        {
+            obt_xml_tree_from_root(menu_parse_inst);
+            obt_xml_close(menu_parse_inst);
         } else
             g_message(_("Unable to find a valid menu file \"%s\""),
                       "menu.xml");
     }
 
     g_assert(menu_parse_state.parent == NULL);
-
-    if (!reconfig)
-        client_add_destroy_notify(client_dest, NULL);
 }
 
 void menu_shutdown(gboolean reconfig)
 {
-    if (!reconfig)
-        client_remove_destroy_notify(client_dest);
-
-    parse_shutdown(menu_parse_inst);
+    obt_xml_instance_unref(menu_parse_inst);
     menu_parse_inst = NULL;
 
     client_list_menu_shutdown(reconfig);
@@ -156,8 +145,6 @@ void menu_clear_pipe_caches(void)
 
 void menu_pipe_execute(ObMenu *self)
 {
-    xmlDocPtr doc;
-    xmlNodePtr node;
     gchar *output;
     GError *err = NULL;
 
@@ -173,13 +160,13 @@ void menu_pipe_execute(ObMenu *self)
         return;
     }
 
-    if (parse_load_mem(output, strlen(output),
-                       "openbox_pipe_menu", &doc, &node))
+    if (obt_xml_load_mem(menu_parse_inst, output, strlen(output),
+                         "openbox_pipe_menu"))
     {
         menu_parse_state.pipe_creator = self;
         menu_parse_state.parent = self;
-        parse_tree(menu_parse_inst, doc, node->children);
-        xmlFreeDoc(doc);
+        obt_xml_tree_from_root(menu_parse_inst);
+        obt_xml_close(menu_parse_inst);
     } else {
         g_message(_("Invalid output from pipe-menu \"%s\""), self->execute);
     }
@@ -218,6 +205,7 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
         *strippedlabel = NULL;
     } else {
         gchar *i;
+        gboolean escape;
 
         *strippedlabel = g_strdup(label);
 
@@ -225,20 +213,33 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
            have to just use the first valid character
         */
 
-        i = strchr(*strippedlabel, '_');
+        /* allow __ to escape an underscore */
+        i = *strippedlabel;
+        do {
+            escape = FALSE;
+            i = strchr(i, '_');
+            if (i && *(i+1) == '_') {
+                gchar *j;
+
+                /* remove the escape '_' from the string */
+                for (j = i; *j != '\0'; ++j)
+                    *j = *(j+1);
+
+                ++i;
+                escape = TRUE;
+            }
+        } while (escape);
+
         if (allow_shortcut && i != NULL) {
             /* there is an underscore in the string */
 
             /* you have to use a printable ascii character for shortcuts
                don't allow space either, so you can have like "a _ b"
             */
-            if (VALID_SHORTCUT(*(i+1)) || *(i+1) == '_') {
-                /* Allow you to escape the first _ by putting __ */
-                if (*(i+1) != '_') {
-                    shortcut = g_unichar_tolower(g_utf8_get_char(i+1));
-                    *position = i - *strippedlabel;
-                    *always_show = TRUE;
-                }
+            if (VALID_SHORTCUT(*(i+1))) {
+                shortcut = g_unichar_tolower(g_utf8_get_char(i+1));
+                *position = i - *strippedlabel;
+                *always_show = TRUE;
 
                 /* remove the '_' from the string */
                 for (; *i != '\0'; ++i)
@@ -265,38 +266,65 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
     return shortcut;
 }
 
-static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                            gpointer data)
+static void parse_menu_item(xmlNodePtr node,  gpointer data)
 {
     ObMenuParseState *state = data;
     gchar *label;
+    gchar *icon;
+    ObMenuEntry *e;
 
     if (state->parent) {
-        if (parse_attr_string("label", node, &label)) {
+        /* Don't try to extract "icon" attribute if icons in user-defined
+           menus are not enabled. */
+
+        if (obt_xml_attr_string(node, "label", &label)) {
+            xmlNodePtr c;
             GSList *acts = NULL;
 
-            for (node = node->children; node; node = node->next)
-                if (!xmlStrcasecmp(node->name, (const xmlChar*) "action")) {
-                    ObActionsAct *a = actions_parse(i, doc, node);
-                    if (a)
-                        acts = g_slist_append(acts, a);
+            c = obt_xml_find_node(node->children, "action");
+            while (c) {
+                ObActionsAct *action = actions_parse(c);
+                if (action)
+                    acts = g_slist_append(acts, action);
+                c = obt_xml_find_node(node->next, "action");
+            }
+            e = menu_add_normal(state->parent, -1, label, acts, TRUE);
+            
+            if (config_menu_show_icons &&
+                obt_xml_attr_string(node, "icon", &icon))
+            {
+                RrImage *ic;
+
+                ic = RrImageCacheFindName(ob_rr_icons, icon);
+                if (ic)
+                    RrImageRef(ic);
+                else {
+                    ic = RrImageNew(ob_rr_icons);
+                    if (!RrImageAddPictureName(ic, icon)) {
+                        RrImageUnref(ic); /* no need to keep it around */
+                        ic = NULL;
+                    }
                 }
-            menu_add_normal(state->parent, -1, label, acts, TRUE);
+                e->data.normal.icon = ic;
+
+                if (e->data.normal.icon)
+                    e->data.normal.icon_alpha = 0xff;
+
+                g_free(icon);
+            }
             g_free(label);
         }
     }
 }
 
-static void parse_menu_separator(ObParseInst *i,
-                                 xmlDocPtr doc, xmlNodePtr node,
-                                 gpointer data)
+static void parse_menu_separator(xmlNodePtr node, gpointer data)
 {
     ObMenuParseState *state = data;
 
     if (state->parent) {
         gchar *label;
 
-        if (!parse_attr_string("label", node, &label))
+        if (!obt_xml_attr_string(node, "label", &label))
             label = NULL;
 
         menu_add_separator(state->parent, -1, label);
@@ -304,30 +332,29 @@ static void parse_menu_separator(ObParseInst *i,
     }
 }
 
-static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                       gpointer data)
+static void parse_menu(xmlNodePtr node, gpointer data)
 {
     ObMenuParseState *state = data;
     gchar *name = NULL, *title = NULL, *script = NULL;
     ObMenu *menu;
 
-    if (!parse_attr_string("id", node, &name))
+    if (!obt_xml_attr_string(node, "id", &name))
         goto parse_menu_fail;
 
     if (!g_hash_table_lookup(menu_hash, name)) {
-        if (!parse_attr_string("label", node, &title))
+        if (!obt_xml_attr_string(node, "label", &title))
             goto parse_menu_fail;
 
         if ((menu = menu_new(name, title, TRUE, NULL))) {
             menu->pipe_creator = state->pipe_creator;
-            if (parse_attr_string("execute", node, &script)) {
-                menu->execute = parse_expand_tilde(script);
+            if (obt_xml_attr_string(node, "execute", &script)) {
+                menu->execute = obt_paths_expand_tilde(script);
             } else {
                 ObMenu *old;
 
                 old = state->parent;
                 state->parent = menu;
-                parse_tree(i, doc, node->children);
+                obt_xml_tree(menu_parse_inst, node->children);
                 state->parent = old;
             }
         }
@@ -459,10 +486,10 @@ void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
             menu_can_hide = TRUE;
         else {
             menu_can_hide = FALSE;
-            ob_main_loop_timeout_add(ob_main_loop,
-                                     config_menu_hide_delay * 1000,
-                                     menu_hide_delay_func,
-                                     NULL, g_direct_equal, NULL);
+            obt_main_loop_timeout_add(ob_main_loop,
+                                      config_menu_hide_delay * 1000,
+                                      menu_hide_delay_func,
+                                      NULL, g_direct_equal, NULL);
         }
     }
 }
index 7e11545..16cf429 100644 (file)
@@ -21,8 +21,7 @@
 
 #include "window.h"
 #include "geom.h"
-#include "render/render.h"
-#include "parser/parse.h"
+#include "obrender/render.h"
 
 #include <glib.h>
 
@@ -169,13 +168,13 @@ void menu_free(ObMenu *menu);
 /*! Repopulate a pipe-menu by running its command */
 void menu_pipe_execute(ObMenu *self);
 /*! Clear a pipe-menu's entries */
-void menu_clear_pipe_caches();
+void menu_clear_pipe_caches(void);
 
 void menu_show_all_shortcuts(ObMenu *self, gboolean show);
 
 void menu_show(gchar *name, gint x, gint y, gboolean mouse,
                struct _ObClient *client);
-gboolean menu_hide_delay_reached();
+gboolean menu_hide_delay_reached(void);
 
 void menu_set_show_func(ObMenu *menu, ObMenuShowFunc func);
 void menu_set_hide_func(ObMenu *menu, ObMenuHideFunc func);
index f013bde..4ee5d31 100644 (file)
 #include "client.h"
 #include "menu.h"
 #include "screen.h"
-#include "prop.h"
 #include "actions.h"
 #include "event.h"
 #include "grab.h"
 #include "openbox.h"
-#include "mainloop.h"
 #include "config.h"
-#include "render/theme.h"
+#include "obt/prop.h"
+#include "obrender/theme.h"
 
 #define PADDING 2
 #define MAX_MENU_WIDTH 400
@@ -57,11 +56,24 @@ static gboolean submenu_hide_timeout(gpointer data);
 static Window createWindow(Window parent, gulong mask,
                            XSetWindowAttributes *attrib)
 {
-    return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
+    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
                          RrDepth(ob_rr_inst), InputOutput,
                          RrVisual(ob_rr_inst), mask, attrib);
 }
 
+static void client_dest(ObClient *client, gpointer data)
+{
+    GList *it;
+
+    /* menus can be associated with a client, so null those refs since
+       we are disappearing now */
+    for (it = menu_frame_visible; it; it = g_list_next(it)) {
+        ObMenuFrame *f = it->data;
+        if (f->client == client)
+            f->client = NULL;
+    }
+}
+
 void menu_frame_startup(gboolean reconfig)
 {
     gint i;
@@ -76,6 +88,7 @@ void menu_frame_startup(gboolean reconfig)
 
     if (reconfig) return;
 
+    client_add_destroy_notify(client_dest, NULL);
     menu_frame_map = g_hash_table_new(g_int_hash, g_int_equal);
 }
 
@@ -85,6 +98,7 @@ void menu_frame_shutdown(gboolean reconfig)
 
     if (reconfig) return;
 
+    client_remove_destroy_notify(client_dest);
     g_hash_table_destroy(menu_frame_map);
 }
 
@@ -94,7 +108,7 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
     XSetWindowAttributes attr;
 
     self = g_new0(ObMenuFrame, 1);
-    self->type = Window_Menu;
+    self->obwin.type = OB_WINDOW_CLASS_MENUFRAME;
     self->menu = menu;
     self->selected = NULL;
     self->client = client;
@@ -102,20 +116,21 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
     self->show_from = show_from;
 
     attr.event_mask = FRAME_EVENTMASK;
-    self->window = createWindow(RootWindow(ob_display, ob_screen),
+    self->window = createWindow(obt_root(ob_screen),
                                 CWEventMask, &attr);
 
     /* make it a popup menu type window */
-    PROP_SET32(self->window, net_wm_window_type, atom,
-               prop_atoms.net_wm_window_type_popup_menu);
+    OBT_PROP_SET32(self->window, NET_WM_WINDOW_TYPE, ATOM,
+                   OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_POPUP_MENU));
 
-    XSetWindowBorderWidth(ob_display, self->window, ob_rr_theme->mbwidth);
-    XSetWindowBorder(ob_display, self->window,
+    XSetWindowBorderWidth(obt_display, self->window, ob_rr_theme->mbwidth);
+    XSetWindowBorder(obt_display, self->window,
                      RrColorPixel(ob_rr_theme->menu_border_color));
 
     self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu);
 
-    stacking_add(MENU_AS_WINDOW(self));
+    window_add(&self->window, MENUFRAME_AS_WINDOW(self));
+    stacking_add(MENUFRAME_AS_WINDOW(self));
 
     return self;
 }
@@ -128,11 +143,12 @@ void menu_frame_free(ObMenuFrame *self)
             self->entries = g_list_delete_link(self->entries, self->entries);
         }
 
-        stacking_remove(MENU_AS_WINDOW(self));
+        stacking_remove(MENUFRAME_AS_WINDOW(self));
+        window_remove(self->window);
 
         RrAppearanceFree(self->a_items);
 
-        XDestroyWindow(ob_display, self->window);
+        XDestroyWindow(obt_display, self->window);
 
         g_free(self);
     }
@@ -164,8 +180,10 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
         g_hash_table_insert(menu_frame_map, &self->bullet, self);
     }
 
-    XMapWindow(ob_display, self->window);
-    XMapWindow(ob_display, self->text);
+    XMapWindow(obt_display, self->window);
+    XMapWindow(obt_display, self->text);
+
+    window_add(&self->window, MENUFRAME_AS_WINDOW(self->frame));
 
     return self;
 }
@@ -175,16 +193,18 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self)
     if (self) {
         menu_entry_unref(self->entry);
 
-        XDestroyWindow(ob_display, self->text);
-        XDestroyWindow(ob_display, self->window);
+        window_remove(self->window);
+
+        XDestroyWindow(obt_display, self->text);
+        XDestroyWindow(obt_display, self->window);
         g_hash_table_remove(menu_frame_map, &self->text);
         g_hash_table_remove(menu_frame_map, &self->window);
         if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
-            XDestroyWindow(ob_display, self->icon);
+            XDestroyWindow(obt_display, self->icon);
             g_hash_table_remove(menu_frame_map, &self->icon);
         }
         if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
-            XDestroyWindow(ob_display, self->bullet);
+            XDestroyWindow(obt_display, self->bullet);
             g_hash_table_remove(menu_frame_map, &self->bullet);
         }
 
@@ -196,7 +216,7 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y)
 {
     RECT_SET_POINT(self->area, x, y);
     self->monitor = screen_find_monitor_point(x, y);
-    XMoveWindow(ob_display, self->window, self->area.x, self->area.y);
+    XMoveWindow(obt_display, self->window, self->area.x, self->area.y);
 }
 
 static void menu_frame_place_topmenu(ObMenuFrame *self, gint *x, gint *y)
@@ -358,7 +378,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
     }
 
     RECT_SET_SIZE(self->area, self->frame->inner_w, th);
-    XResizeWindow(ob_display, self->window,
+    XResizeWindow(obt_display, self->window,
                   self->area.width, self->area.height);
     item_a->surface.parent = self->frame->a_items;
     item_a->surface.parentx = self->area.x;
@@ -395,7 +415,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
                   ob_rr_theme->a_menu_text_normal);
         sub = self->entry->data.submenu.submenu;
         text_a->texture[0].data.text.string = sub ? sub->title : "";
-        if (sub->shortcut && (self->frame->menu->show_all_shortcuts ||
+        if (sub && sub->shortcut && (self->frame->menu->show_all_shortcuts ||
                               sub->shortcut_always_show ||
                               sub->shortcut_position > 0))
         {
@@ -413,11 +433,13 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
         else
             text_a = ob_rr_theme->a_menu_text_normal;
         break;
+    default:
+        g_assert_not_reached();
     }
 
     switch (self->entry->type) {
     case OB_MENU_ENTRY_TYPE_NORMAL:
-        XMoveResizeWindow(ob_display, self->text,
+        XMoveResizeWindow(obt_display, self->text,
                           self->frame->text_x, PADDING,
                           self->frame->text_w,
                           ITEM_HEIGHT - 2*PADDING);
@@ -428,7 +450,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
                 ITEM_HEIGHT - 2*PADDING);
         break;
     case OB_MENU_ENTRY_TYPE_SUBMENU:
-        XMoveResizeWindow(ob_display, self->text,
+        XMoveResizeWindow(obt_display, self->text,
                           self->frame->text_x, PADDING,
                           self->frame->text_w - ITEM_HEIGHT,
                           ITEM_HEIGHT - 2*PADDING);
@@ -441,7 +463,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
     case OB_MENU_ENTRY_TYPE_SEPARATOR:
         if (self->entry->data.separator.label != NULL) {
             /* labeled separator */
-            XMoveResizeWindow(ob_display, self->text,
+            XMoveResizeWindow(obt_display, self->text,
                               ob_rr_theme->paddingx, ob_rr_theme->paddingy,
                               self->area.width - 2*ob_rr_theme->paddingx,
                               ob_rr_theme->menu_title_height -
@@ -457,7 +479,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
             gint i;
 
             /* unlabeled separator */
-            XMoveResizeWindow(ob_display, self->text, 0, 0,
+            XMoveResizeWindow(obt_display, self->text, 0, 0,
                               self->area.width,
                               ob_rr_theme->menu_sep_width +
                               2*ob_rr_theme->menu_sep_paddingy);
@@ -481,6 +503,8 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
                     2*ob_rr_theme->menu_sep_paddingy);
         }
         break;
+    default:
+        g_assert_not_reached();
     }
 
     if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
@@ -488,7 +512,7 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
     {
         RrAppearance *clear;
 
-        XMoveResizeWindow(ob_display, self->icon,
+        XMoveResizeWindow(obt_display, self->icon,
                           PADDING, frame->item_margin.top,
                           ITEM_HEIGHT - frame->item_margin.top
                           - frame->item_margin.bottom,
@@ -510,14 +534,14 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
                 - frame->item_margin.bottom,
                 ITEM_HEIGHT - frame->item_margin.top
                 - frame->item_margin.bottom);
-        XMapWindow(ob_display, self->icon);
+        XMapWindow(obt_display, self->icon);
     } else if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
                self->entry->data.normal.mask)
     {
         RrColor *c;
         RrAppearance *clear;
 
-        XMoveResizeWindow(ob_display, self->icon,
+        XMoveResizeWindow(obt_display, self->icon,
                           PADDING, frame->item_margin.top,
                           ITEM_HEIGHT - frame->item_margin.top
                           - frame->item_margin.bottom,
@@ -550,13 +574,13 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
                 - frame->item_margin.bottom,
                 ITEM_HEIGHT - frame->item_margin.top
                 - frame->item_margin.bottom);
-        XMapWindow(ob_display, self->icon);
+        XMapWindow(obt_display, self->icon);
     } else
-        XUnmapWindow(ob_display, self->icon);
+        XUnmapWindow(obt_display, self->icon);
 
     if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
         RrAppearance *bullet_a;
-        XMoveResizeWindow(ob_display, self->bullet,
+        XMoveResizeWindow(obt_display, self->bullet,
                           self->frame->text_x + self->frame->text_w -
                           ITEM_HEIGHT + PADDING, PADDING,
                           ITEM_HEIGHT - 2*PADDING,
@@ -571,11 +595,11 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
         RrPaint(bullet_a, self->bullet,
                 ITEM_HEIGHT - 2*PADDING,
                 ITEM_HEIGHT - 2*PADDING);
-        XMapWindow(ob_display, self->bullet);
+        XMapWindow(obt_display, self->bullet);
     } else
-        XUnmapWindow(ob_display, self->bullet);
+        XUnmapWindow(obt_display, self->bullet);
 
-    XFlush(ob_display);
+    XFlush(obt_display);
 }
 
 /*! this code is taken from the menu_frame_render. if that changes, this won't
@@ -694,10 +718,10 @@ void menu_frame_render(ObMenuFrame *self)
         }
 
         RECT_SET_POINT(e->area, 0, h+e->border);
-        XMoveWindow(ob_display, e->window,
+        XMoveWindow(obt_display, e->window,
                     e->area.x-e->border, e->area.y-e->border);
-        XSetWindowBorderWidth(ob_display, e->window, e->border);
-        XSetWindowBorder(ob_display, e->window,
+        XSetWindowBorderWidth(obt_display, e->window, e->border);
+        XSetWindowBorder(obt_display, e->window,
                          RrColorPixel(ob_rr_theme->menu_border_color));
 
         text_a = (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
@@ -749,6 +773,8 @@ void menu_frame_render(ObMenuFrame *self)
                     2*ob_rr_theme->menu_sep_paddingy - 2*PADDING;
             }
             break;
+        default:
+            g_assert_not_reached();
         }
         tw += 2*PADDING;
         th += 2*PADDING;
@@ -779,7 +805,7 @@ void menu_frame_render(ObMenuFrame *self)
     if (!w) w = 10;
     if (!h) h = 3;
 
-    XResizeWindow(ob_display, self->window, w, h);
+    XResizeWindow(obt_display, self->window, w, h);
 
     self->inner_w = w;
 
@@ -793,7 +819,7 @@ void menu_frame_render(ObMenuFrame *self)
 
     RECT_SET_SIZE(self->area, w, h);
 
-    XFlush(ob_display);
+    XFlush(obt_display);
 }
 
 static void menu_frame_update(ObMenuFrame *self)
@@ -963,7 +989,7 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
 
     menu_frame_move(self, x, y);
 
-    XMapWindow(ob_display, self->window);
+    XMapWindow(obt_display, self->window);
 
     if (screen_pointer_pos(&px, &py)) {
         ObMenuEntryFrame *e = menu_entry_frame_under(px, py);
@@ -979,8 +1005,8 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
 */
 static void remove_submenu_hide_timeout(ObMenuFrame *child)
 {
-    ob_main_loop_timeout_remove_data(ob_main_loop, submenu_hide_timeout,
-                                     child, FALSE);
+    obt_main_loop_timeout_remove_data(ob_main_loop, submenu_hide_timeout,
+                                      child, FALSE);
 }
 
 gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
@@ -1018,7 +1044,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
     }
     menu_frame_move(self, x + dx, y + dy);
 
-    XMapWindow(ob_display, self->window);
+    XMapWindow(obt_display, self->window);
 
     if (screen_pointer_pos(&px, &py)) {
         ObMenuEntryFrame *e = menu_entry_frame_under(px, py);
@@ -1061,7 +1087,7 @@ static void menu_frame_hide(ObMenuFrame *self)
     }
 
     ignore_start = event_start_ignore_all_enters();
-    XUnmapWindow(ob_display, self->window);
+    XUnmapWindow(obt_display, self->window);
     event_end_ignore_all_enters(ignore_start);
 
     menu_frame_free(self);
@@ -1073,28 +1099,12 @@ void menu_frame_hide_all(void)
 
     if (config_submenu_show_delay) {
         /* remove any submenu open requests */
-        ob_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
+        obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
     }
     if ((it = g_list_last(menu_frame_visible)))
         menu_frame_hide(it->data);
 }
 
-void menu_frame_hide_all_client(ObClient *client)
-{
-    GList *it = g_list_last(menu_frame_visible);
-    if (it) {
-        ObMenuFrame *f = it->data;
-        if (f->client == client) {
-            if (config_submenu_show_delay) {
-                /* remove any submenu open requests */
-                ob_main_loop_timeout_remove(ob_main_loop,
-                                            submenu_show_timeout);
-            }
-            menu_frame_hide(f);
-        }
-    }
-}
-
 ObMenuFrame* menu_frame_under(gint x, gint y)
 {
     ObMenuFrame *ret = NULL;
@@ -1170,7 +1180,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
 
     if (config_submenu_show_delay) {
         /* remove any submenu open requests */
-        ob_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
+        obt_main_loop_timeout_remove(ob_main_loop, submenu_show_timeout);
     }
 
     self->selected = entry;
@@ -1191,11 +1201,11 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
             if (immediate || config_submenu_hide_delay == 0)
                 menu_frame_hide(oldchild);
             else if (config_submenu_hide_delay > 0)
-                ob_main_loop_timeout_add(ob_main_loop,
-                                         config_submenu_hide_delay * 1000,
-                                         submenu_hide_timeout,
-                                         oldchild, g_direct_equal,
-                                         NULL);
+                obt_main_loop_timeout_add(ob_main_loop,
+                                          config_submenu_hide_delay * 1000,
+                                          submenu_hide_timeout,
+                                          oldchild, g_direct_equal,
+                                          NULL);
         }
     }
 
@@ -1208,11 +1218,11 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
                 if (immediate || config_submenu_hide_delay == 0)
                     menu_entry_frame_show_submenu(self->selected);
                 else if (config_submenu_hide_delay > 0)
-                    ob_main_loop_timeout_add(ob_main_loop,
-                                             config_submenu_show_delay * 1000,
-                                             submenu_show_timeout,
-                                             self->selected, g_direct_equal,
-                                             NULL);
+                    obt_main_loop_timeout_add(ob_main_loop,
+                                              config_submenu_show_delay * 1000,
+                                              submenu_show_timeout,
+                                              self->selected, g_direct_equal,
+                                              NULL);
             }
             /* hide the grandchildren of this menu. and move the cursor to
                the current menu */
@@ -1255,7 +1265,7 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state)
 
         /* release grabs before executing the shit */
         if (!(state & ControlMask)) {
-            menu_frame_hide_all();
+            event_cancel_all_key_grabs();
             frame = NULL;
         }
 
index da796d5..aa32b21 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "geom.h"
 #include "window.h"
-#include "render/render.h"
+#include "obrender/render.h"
 
 #include <glib.h>
 
@@ -38,7 +38,7 @@ extern GList *menu_frame_visible;
 struct _ObMenuFrame
 {
     /* stuff to be an ObWindow */
-    Window_InternalType type;
+    ObWindow obwin;
     Window window;
 
     struct _ObMenu *menu;
@@ -118,7 +118,7 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
 gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
                                  ObMenuEntryFrame *parent_entry);
 
-void menu_frame_hide_all();
+void menu_frame_hide_all(void);
 void menu_frame_hide_all_client(struct _ObClient *client);
 
 void menu_frame_render(ObMenuFrame *self);
index f63d266..ee14935 100644 (file)
 
 #include "openbox.h"
 #include "config.h"
-#include "xerror.h"
 #include "actions.h"
 #include "event.h"
 #include "client.h"
-#include "prop.h"
 #include "grab.h"
 #include "frame.h"
 #include "translate.h"
 #include "mouse.h"
 #include "gettext.h"
+#include "obt/display.h"
 
 #include <glib.h>
 
@@ -197,21 +196,22 @@ static gboolean fire_binding(ObMouseAction a, ObFrameContext context,
     return TRUE;
 }
 
-void mouse_replay_pointer()
+void mouse_replay_pointer(void)
 {
     if (replay_pointer_needed) {
         /* replay the pointer event before any windows move */
-        XAllowEvents(ob_display, ReplayPointer, event_curtime);
+        XAllowEvents(obt_display, ReplayPointer, event_curtime);
         replay_pointer_needed = FALSE;
     }
 }
 
-void mouse_event(ObClient *client, XEvent *e)
+gboolean mouse_event(ObClient *client, XEvent *e)
 {
     static Time ltime;
     static guint button = 0, state = 0, lbutton = 0;
     static Window lwindow = None;
     static gint px, py, pwx = -1, pwy = -1;
+    gboolean used = FALSE;
 
     ObFrameContext context;
     gboolean click = FALSE;
@@ -247,10 +247,10 @@ void mouse_event(ObClient *client, XEvent *e)
         if (CLIENT_CONTEXT(context, client))
             replay_pointer_needed = TRUE;
 
-        fire_binding(OB_MOUSE_ACTION_PRESS, context,
-                     client, e->xbutton.state,
-                     e->xbutton.button,
-                     e->xbutton.x_root, e->xbutton.y_root);
+        used = fire_binding(OB_MOUSE_ACTION_PRESS, context,
+                            client, e->xbutton.state,
+                            e->xbutton.button,
+                            e->xbutton.x_root, e->xbutton.y_root) || used;
 
         /* if the bindings grab the pointer, there won't be a ButtonRelease
            event for us */
@@ -281,10 +281,10 @@ void mouse_event(ObClient *client, XEvent *e)
             Window wjunk;
             guint ujunk, b, w, h;
             /* this can cause errors to occur when the window closes */
-            xerror_set_ignore(TRUE);
-            junk1 = XGetGeometry(ob_display, e->xbutton.window,
+            obt_display_ignore_errors(TRUE);
+            junk1 = XGetGeometry(obt_display, e->xbutton.window,
                                  &wjunk, &junk1, &junk2, &w, &h, &b, &ujunk);
-            xerror_set_ignore(FALSE);
+            obt_display_ignore_errors(FALSE);
             if (junk1) {
                 if (e->xbutton.x >= (signed)-b &&
                     e->xbutton.y >= (signed)-b &&
@@ -312,23 +312,23 @@ void mouse_event(ObClient *client, XEvent *e)
             state = 0;
             ltime = e->xbutton.time;
         }
-        fire_binding(OB_MOUSE_ACTION_RELEASE, context,
-                     client, e->xbutton.state,
-                     e->xbutton.button,
-                     e->xbutton.x_root,
-                     e->xbutton.y_root);
+        used = fire_binding(OB_MOUSE_ACTION_RELEASE, context,
+                            client, e->xbutton.state,
+                            e->xbutton.button,
+                            e->xbutton.x_root,
+                            e->xbutton.y_root) || used;
         if (click)
-            fire_binding(OB_MOUSE_ACTION_CLICK, context,
-                         client, e->xbutton.state,
-                         e->xbutton.button,
-                         e->xbutton.x_root,
-                         e->xbutton.y_root);
+            used = fire_binding(OB_MOUSE_ACTION_CLICK, context,
+                                client, e->xbutton.state,
+                                e->xbutton.button,
+                                e->xbutton.x_root,
+                                e->xbutton.y_root) || used;
         if (dclick)
-            fire_binding(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
-                         client, e->xbutton.state,
-                         e->xbutton.button,
-                         e->xbutton.x_root,
-                         e->xbutton.y_root);
+            used = fire_binding(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
+                                client, e->xbutton.state,
+                                e->xbutton.button,
+                                e->xbutton.x_root,
+                                e->xbutton.y_root) || used;
         break;
 
     case MotionNotify:
@@ -348,8 +348,8 @@ void mouse_event(ObClient *client, XEvent *e)
                     context == OB_FRAME_CONTEXT_CLOSE)
                     break;
 
-                fire_binding(OB_MOUSE_ACTION_MOTION, context,
-                             client, state, button, px, py);
+                used = fire_binding(OB_MOUSE_ACTION_MOTION, context,
+                                    client, state, button, px, py);
                 button = 0;
                 state = 0;
             }
@@ -359,6 +359,7 @@ void mouse_event(ObClient *client, XEvent *e)
     default:
         g_assert_not_reached();
     }
+    return used;
 }
 
 gboolean mouse_bind(const gchar *buttonstr, const gchar *contextstr,
index a862fe5..3effcc4 100644 (file)
@@ -31,9 +31,9 @@ void mouse_shutdown(gboolean reconfig);
 
 gboolean mouse_bind(const gchar *buttonstr, const gchar *contextstr,
                     ObMouseAction mact, struct _ObActionsAct *action);
-void mouse_unbind_all();
+void mouse_unbind_all(void);
 
-void mouse_event(struct _ObClient *client, XEvent *e);
+gboolean mouse_event(struct _ObClient *client, XEvent *e);
 
 void mouse_grab_for_client(struct _ObClient *client, gboolean grab);
 
@@ -43,6 +43,6 @@ ObFrameContext mouse_button_frame_context(ObFrameContext context,
 /*! If a replay pointer is needed, then do it.  Call this when windows are
   going to be moving/appearing/disappearing, so that you know the mouse click
   will go to the right window */
-void mouse_replay_pointer();
+void mouse_replay_pointer(void);
 
 #endif
index 95d6473..ec9cb10 100644 (file)
 #include "grab.h"
 #include "framerender.h"
 #include "screen.h"
-#include "prop.h"
 #include "client.h"
 #include "frame.h"
 #include "openbox.h"
 #include "resist.h"
-#include "mainloop.h"
-#include "modkeys.h"
 #include "popup.h"
 #include "moveresize.h"
 #include "config.h"
 #include "event.h"
 #include "debug.h"
-#include "extensions.h"
-#include "render/render.h"
-#include "render/theme.h"
+#include "obrender/render.h"
+#include "obrender/theme.h"
+#include "obt/display.h"
+#include "obt/prop.h"
+#include "obt/keyboard.h"
 
 #include <X11/Xlib.h>
 #include <glib.h>
@@ -168,8 +167,8 @@ static void popup_coords(ObClient *c, const gchar *format, gint a, gint b)
 void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
 {
     ObCursor cur;
-    gboolean mv = (cnr == prop_atoms.net_wm_moveresize_move ||
-                   cnr == prop_atoms.net_wm_moveresize_move_keyboard);
+    gboolean mv = (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) ||
+                   cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD));
     gint up = 1;
     gint left = 1;
 
@@ -179,32 +178,37 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
           (c->functions & OB_CLIENT_FUNC_RESIZE)))
         return;
 
-    if (cnr == prop_atoms.net_wm_moveresize_size_topleft) {
+    if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) {
         cur = OB_CURSOR_NORTHWEST;
         up = left = -1;
-    } else if (cnr == prop_atoms.net_wm_moveresize_size_top) {
+    }
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) {
         cur = OB_CURSOR_NORTH;
         up = -1;
-    } else if (cnr == prop_atoms.net_wm_moveresize_size_topright) {
+    }
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) {
         cur = OB_CURSOR_NORTHEAST;
         up = -1;
-    } else if (cnr == prop_atoms.net_wm_moveresize_size_right)
+    }
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT))
         cur = OB_CURSOR_EAST;
-    else if (cnr == prop_atoms.net_wm_moveresize_size_bottomright)
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT))
         cur = OB_CURSOR_SOUTHEAST;
-    else if (cnr == prop_atoms.net_wm_moveresize_size_bottom)
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM))
         cur = OB_CURSOR_SOUTH;
-    else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft) {
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) {
         cur = OB_CURSOR_SOUTHWEST;
         left = -1;
-    } else if (cnr == prop_atoms.net_wm_moveresize_size_left) {
+    }
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) {
         cur = OB_CURSOR_WEST;
         left = -1;
-    } else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard)
+    }
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD))
         cur = OB_CURSOR_SOUTHEAST;
-    else if (cnr == prop_atoms.net_wm_moveresize_move)
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE))
         cur = OB_CURSOR_MOVE;
-    else if (cnr == prop_atoms.net_wm_moveresize_move_keyboard)
+    else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
         cur = OB_CURSOR_MOVE;
     else
         g_assert_not_reached();
@@ -251,7 +255,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
     moveresize_in_progress = TRUE;
 
 #ifdef SYNC
-    if (config_resize_redraw && !moving && extensions_sync &&
+    if (config_resize_redraw && !moving && obt_display_extension_sync &&
         moveresize_client->sync_request && moveresize_client->sync_counter &&
         !moveresize_client->not_responding)
     {
@@ -263,7 +267,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
 
         /* set the counter to an initial value */
         XSyncIntToValue(&val, 0);
-        XSyncSetCounter(ob_display, moveresize_client->sync_counter, val);
+        XSyncSetCounter(obt_display, moveresize_client->sync_counter, val);
 
         /* this will be incremented when we tell the client what we're
            looking for */
@@ -279,7 +283,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
         aa.trigger.test_type = XSyncPositiveTransition;
         aa.events = True;
         XSyncIntToValue(&aa.delta, 1);
-        moveresize_alarm = XSyncCreateAlarm(ob_display,
+        moveresize_alarm = XSyncCreateAlarm(obt_display,
                                             XSyncCACounter |
                                             XSyncCAValue |
                                             XSyncCAValueType |
@@ -300,29 +304,29 @@ void moveresize_end(gboolean cancel)
 
     popup_hide(popup);
 
-    if (moving) {
-        client_move(moveresize_client,
-                    (cancel ? start_cx : cur_x),
-                    (cancel ? start_cy : cur_y));
-    } else {
+    if (!moving) {
 #ifdef SYNC
         /* turn off the alarm */
         if (moveresize_alarm != None) {
-            XSyncDestroyAlarm(ob_display, moveresize_alarm);
+            XSyncDestroyAlarm(obt_display, moveresize_alarm);
             moveresize_alarm = None;
         }
 
-        ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
+        obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
 #endif
-
-        client_configure(moveresize_client,
-                         (cancel ? start_cx : cur_x),
-                         (cancel ? start_cy : cur_y),
-                         (cancel ? start_cw : cur_w),
-                         (cancel ? start_ch : cur_h),
-                         TRUE, TRUE, FALSE);
     }
 
+    /* don't use client_move() here, use the same width/height as
+       we've been using during the move, otherwise we get different results
+       when moving maximized windows between monitors of different sizes !
+    */
+    client_configure(moveresize_client,
+                     (cancel ? start_cx : cur_x),
+                     (cancel ? start_cy : cur_y),
+                     (cancel ? start_cw : cur_w),
+                     (cancel ? start_ch : cur_h),
+                     TRUE, TRUE, FALSE);
+
     /* dont edge warp after its ended */
     cancel_edge_warp();
 
@@ -364,9 +368,8 @@ static void do_resize(void)
     {
 
 #ifdef SYNC
-        if (config_resize_redraw && extensions_sync &&
-            moveresize_client->sync_request &&
-            moveresize_client->sync_counter &&
+        if (config_resize_redraw && obt_display_extension_sync &&
+            moveresize_client->sync_request && moveresize_client->sync_counter &&
             !moveresize_client->not_responding)
         {
             XEvent ce;
@@ -382,28 +385,29 @@ static void do_resize(void)
 
             /* tell the client what we're waiting for */
             ce.xclient.type = ClientMessage;
-            ce.xclient.message_type = prop_atoms.wm_protocols;
-            ce.xclient.display = ob_display;
+            ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS);
+            ce.xclient.display = obt_display;
             ce.xclient.window = moveresize_client->window;
             ce.xclient.format = 32;
-            ce.xclient.data.l[0] = prop_atoms.net_wm_sync_request;
+            ce.xclient.data.l[0] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST);
             ce.xclient.data.l[1] = event_curtime;
             ce.xclient.data.l[2] = XSyncValueLow32(val);
             ce.xclient.data.l[3] = XSyncValueHigh32(val);
             ce.xclient.data.l[4] = 0l;
-            XSendEvent(ob_display, moveresize_client->window, FALSE,
+            XSendEvent(obt_display, moveresize_client->window, FALSE,
                        NoEventMask, &ce);
 
             waiting_for_sync = TRUE;
 
-            ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
-            ob_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
-                                     sync_timeout_func, NULL, NULL, NULL);
+            obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
+            obt_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
+                                      sync_timeout_func,
+                                      NULL, NULL, NULL);
         }
 #endif
 
         client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
-                TRUE, FALSE, FALSE);
+                         TRUE, FALSE, FALSE);
     }
 
     /* this would be better with a fixed width font ... XXX can do it better
@@ -576,10 +580,10 @@ static void do_edge_warp(gint x, gint y)
         cancel_edge_warp();
         if (dir != (ObDirection)-1) {
             edge_warp_odd = TRUE; /* switch on the first timeout */
-            ob_main_loop_timeout_add(ob_main_loop,
-                                     config_mouse_screenedgetime * 1000,
-                                     edge_warp_delay_func,
-                                     NULL, NULL, NULL);
+            obt_main_loop_timeout_add(ob_main_loop,
+                                      config_mouse_screenedgetime * 1000,
+                                      edge_warp_delay_func,
+                                      NULL, NULL, NULL);
         }
         edge_warp_dir = dir;
     }
@@ -587,7 +591,7 @@ static void do_edge_warp(gint x, gint y)
 
 static void cancel_edge_warp(void)
 {
-    ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
+    obt_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
 }
 
 static void move_with_keys(gint keycode, gint state)
@@ -597,7 +601,7 @@ static void move_with_keys(gint keycode, gint state)
     gint dist = 0;
 
     /* shift means jump to edge */
-    if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
+    if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
         gint x, y;
         ObDirection dir;
 
@@ -615,8 +619,11 @@ static void move_with_keys(gint keycode, gint state)
         dy = y - moveresize_client->area.y;
     } else {
         /* control means fine grained */
-        if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
+        if (state &
+            obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
+        {
             dist = 1;
+        }
         else
             dist = KEY_DIST;
 
@@ -631,12 +638,12 @@ static void move_with_keys(gint keycode, gint state)
     }
 
     screen_pointer_pos(&opx, &opy);
-    XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
+    XWarpPointer(obt_display, None, None, 0, 0, 0, 0, dx, dy);
     /* steal the motion events this causes */
-    XSync(ob_display, FALSE);
+    XSync(obt_display, FALSE);
     {
         XEvent ce;
-        while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
+        while (XCheckTypedEvent(obt_display, MotionNotify, &ce));
     }
     screen_pointer_pos(&px, &py);
 
@@ -655,7 +662,7 @@ static void move_with_keys(gint keycode, gint state)
 static void resize_with_keys(gint keycode, gint state)
 {
     gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
-    gint dist = 0, resist = 0;
+    gint resist = 0;
     ObDirection dir;
 
     /* pick the edge if it needs to move */
@@ -667,8 +674,7 @@ static void resize_with_keys(gint keycode, gint state)
             key_resize_edge = OB_DIRECTION_EAST;
             return;
         }
-    }
-    if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
+    } else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
         dir = OB_DIRECTION_WEST;
         if (key_resize_edge != OB_DIRECTION_WEST &&
             key_resize_edge != OB_DIRECTION_EAST)
@@ -676,8 +682,7 @@ static void resize_with_keys(gint keycode, gint state)
             key_resize_edge = OB_DIRECTION_WEST;
             return;
         }
-    }
-    if (ob_keycode_match(keycode, OB_KEY_UP)) {
+    } else if (ob_keycode_match(keycode, OB_KEY_UP)) {
         dir = OB_DIRECTION_NORTH;
         if (key_resize_edge != OB_DIRECTION_NORTH &&
             key_resize_edge != OB_DIRECTION_SOUTH)
@@ -685,8 +690,7 @@ static void resize_with_keys(gint keycode, gint state)
             key_resize_edge = OB_DIRECTION_NORTH;
             return;
         }
-    }
-    if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
+    } else /* if (ob_keycode_match(keycode, OB_KEY_DOWN)) */ {
         dir = OB_DIRECTION_SOUTH;
         if (key_resize_edge != OB_DIRECTION_NORTH &&
             key_resize_edge != OB_DIRECTION_SOUTH)
@@ -697,7 +701,7 @@ static void resize_with_keys(gint keycode, gint state)
     }
 
     /* shift means jump to edge */
-    if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
+    if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
         gint x, y, w, h;
 
         if (ob_keycode_match(keycode, OB_KEY_RIGHT))
@@ -722,7 +726,9 @@ static void resize_with_keys(gint keycode, gint state)
             distw = moveresize_client->size_inc.width;
             resist = 1;
         }
-        else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL)) {
+        else if (state &
+                 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
+        {
             distw = 1;
             resist = 1;
         }
@@ -734,7 +740,9 @@ static void resize_with_keys(gint keycode, gint state)
             disth = moveresize_client->size_inc.height;
             resist = 1;
         }
-        else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL)) {
+        else if (state &
+                 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
+        {
             disth = 1;
             resist = 1;
         }
@@ -745,27 +753,27 @@ static void resize_with_keys(gint keycode, gint state)
 
         if (key_resize_edge == OB_DIRECTION_WEST) {
             if (dir == OB_DIRECTION_WEST)
-                dw = (dist = distw);
+                dw = distw;
             else
-                dw = -(dist = distw);
+                dw = -distw;
         }
         else if (key_resize_edge == OB_DIRECTION_EAST) {
             if (dir == OB_DIRECTION_EAST)
-                dw = (dist = distw);
+                dw = distw;
             else
-                dw = -(dist = distw);
+                dw = -distw;
         }
         else if (key_resize_edge == OB_DIRECTION_NORTH) {
             if (dir == OB_DIRECTION_NORTH)
-                dh = (dist = disth);
+                dh = disth;
             else
-                dh = -(dist = disth);
+                dh = -disth;
         }
         else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
             if (dir == OB_DIRECTION_SOUTH)
-                dh = (dist = disth);
+                dh = disth;
             else
-                dh = -(dist = disth);
+                dh = -disth;
         }
     }
 
@@ -788,12 +796,12 @@ static void resize_with_keys(gint keycode, gint state)
         pdy = dh;
 
     screen_pointer_pos(&opx, &opy);
-    XWarpPointer(ob_display, None, None, 0, 0, 0, 0, pdx, pdy);
+    XWarpPointer(obt_display, None, None, 0, 0, 0, 0, pdx, pdy);
     /* steal the motion events this causes */
-    XSync(ob_display, FALSE);
+    XSync(obt_display, FALSE);
     {
         XEvent ce;
-        while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
+        while (XCheckTypedEvent(obt_display, MotionNotify, &ce));
     }
     screen_pointer_pos(&px, &py);
 
@@ -836,41 +844,44 @@ gboolean moveresize_event(XEvent *e)
             gint dw, dh;
             ObDirection dir;
 
-            if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
+            if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) {
                 dw = -(e->xmotion.x_root - start_x);
                 dh = -(e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_NORTHWEST;
-            } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
+            } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) {
                 dw = 0;
                 dh = -(e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_NORTH;
-            } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
+            } else if (corner ==
+                       OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) {
                 dw = (e->xmotion.x_root - start_x);
                 dh = -(e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_NORTHEAST;
-            } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
+            } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT)) {
                 dw = (e->xmotion.x_root - start_x);
                 dh = 0;
                 dir = OB_DIRECTION_EAST;
             } else if (corner ==
-                       prop_atoms.net_wm_moveresize_size_bottomright) {
+                       OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)) {
                 dw = (e->xmotion.x_root - start_x);
                 dh = (e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_SOUTHEAST;
-            } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
+            } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM))
+            {
                 dw = 0;
                 dh = (e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_SOUTH;
             } else if (corner ==
-                       prop_atoms.net_wm_moveresize_size_bottomleft) {
+                       OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) {
                 dw = -(e->xmotion.x_root - start_x);
                 dh = (e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_SOUTHWEST;
-            } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
+            } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) {
                 dw = -(e->xmotion.x_root - start_x);
                 dh = 0;
                 dir = OB_DIRECTION_WEST;
-            } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
+            } else if (corner ==
+                       OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
                 dw = (e->xmotion.x_root - start_x);
                 dh = (e->xmotion.y_root - start_y);
                 dir = OB_DIRECTION_SOUTHEAST;
@@ -884,15 +895,15 @@ gboolean moveresize_event(XEvent *e)
             cur_w += dw;
             cur_h += dh;
 
-            if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
-                corner == prop_atoms.net_wm_moveresize_size_left ||
-                corner == prop_atoms.net_wm_moveresize_size_bottomleft)
+            if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
+                corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT) ||
+                corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT))
             {
                 cur_x -= dw;
             }
-            if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
-                corner == prop_atoms.net_wm_moveresize_size_top ||
-                corner == prop_atoms.net_wm_moveresize_size_topright)
+            if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
+                corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP) ||
+                corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT))
             {
                 cur_y -= dh;
             }
@@ -912,17 +923,19 @@ gboolean moveresize_event(XEvent *e)
                    ob_keycode_match(e->xkey.keycode, OB_KEY_DOWN) ||
                    ob_keycode_match(e->xkey.keycode, OB_KEY_UP))
         {
-            if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
+            if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
                 resize_with_keys(e->xkey.keycode, e->xkey.state);
                 used = TRUE;
-            } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
+            } else if (corner ==
+                       OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
+            {
                 move_with_keys(e->xkey.keycode, e->xkey.state);
                 used = TRUE;
             }
         }
     }
 #ifdef SYNC
-    else if (e->type == extensions_sync_event_basep + XSyncAlarmNotify)
+    else if (e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
     {
         waiting_for_sync = FALSE; /* we got our sync... */
         do_resize(); /* ...so try resize if there is more change pending */
index 415c160..d2b66b5 100644 (file)
 #include "openbox.h"
 #include "session.h"
 #include "dock.h"
-#include "modkeys.h"
 #include "event.h"
 #include "menu.h"
 #include "client.h"
-#include "xerror.h"
-#include "prop.h"
 #include "screen.h"
 #include "actions.h"
 #include "startupnotify.h"
 #include "framerender.h"
 #include "keyboard.h"
 #include "mouse.h"
-#include "extensions.h"
 #include "menuframe.h"
 #include "grab.h"
 #include "group.h"
 #include "config.h"
 #include "ping.h"
-#include "mainloop.h"
 #include "prompt.h"
 #include "gettext.h"
-#include "parser/parse.h"
-#include "render/render.h"
-#include "render/theme.h"
+#include "obrender/render.h"
+#include "obrender/theme.h"
+#include "obt/display.h"
+#include "obt/prop.h"
+#include "obt/keyboard.h"
+#include "obt/xml.h"
 
 #ifdef HAVE_FCNTL_H
 #  include <fcntl.h>
@@ -88,8 +86,7 @@
 RrInstance   *ob_rr_inst;
 RrImageCache *ob_rr_icons;
 RrTheme      *ob_rr_theme;
-ObMainLoop   *ob_main_loop;
-Display      *ob_display;
+ObtMainLoop  *ob_main_loop;
 gint          ob_screen;
 gboolean      ob_replace_wm = FALSE;
 gboolean      ob_sm_use = TRUE;
@@ -122,6 +119,8 @@ gint main(gint argc, gchar **argv)
 
     ob_set_state(OB_STATE_STARTING);
 
+    ob_debug_startup();
+
     /* initialize the locale */
     if (!setlocale(LC_ALL, ""))
         g_message("Couldn't set locale from environment.");
@@ -141,44 +140,38 @@ gint main(gint argc, gchar **argv)
     program_name = g_path_get_basename(argv[0]);
     g_set_prgname(program_name);
 
-    if (!remote_control) {
-        parse_paths_startup();
-
+    if (!remote_control)
         session_startup(argc, argv);
-    }
 
-    ob_display = XOpenDisplay(NULL);
-    if (ob_display == NULL)
+    if (!obt_display_open(NULL))
         ob_exit_with_error(_("Failed to open the display from the DISPLAY environment variable."));
-    if (fcntl(ConnectionNumber(ob_display), F_SETFD, 1) == -1)
-        ob_exit_with_error("Failed to set display as close-on-exec");
 
     if (remote_control) {
-        prop_startup();
-
         /* Send client message telling the OB process to:
          * remote_control = 1 -> reconfigure
          * remote_control = 2 -> restart */
-        PROP_MSG(RootWindow(ob_display, ob_screen),
-                 ob_control, remote_control, 0, 0, 0);
-        XCloseDisplay(ob_display);
+        OBT_PROP_MSG(ob_screen, obt_root(ob_screen),
+                     OB_CONTROL, remote_control, 0, 0, 0, 0);
+        obt_display_close();
         exit(EXIT_SUCCESS);
     }
 
-    ob_main_loop = ob_main_loop_new(ob_display);
+    ob_main_loop = obt_main_loop_new();
 
     /* set up signal handler */
-    ob_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL, NULL);
-    ob_main_loop_signal_add(ob_main_loop, SIGUSR2, signal_handler, NULL, NULL);
-    ob_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL, NULL);
-    ob_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler, NULL, NULL);
-    ob_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler, NULL, NULL);
-    ob_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL, NULL);
-    ob_main_loop_signal_add(ob_main_loop, SIGCHLD, signal_handler, NULL, NULL);
-
-    ob_screen = DefaultScreen(ob_display);
-
-    ob_rr_inst = RrInstanceNew(ob_display, ob_screen);
+    obt_main_loop_signal_add(ob_main_loop, SIGUSR1, signal_handler, NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGUSR2, signal_handler, NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGTERM, signal_handler, NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGINT, signal_handler,  NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGHUP, signal_handler,  NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGPIPE, signal_handler, NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGCHLD, signal_handler, NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGTTIN, signal_handler, NULL,NULL);
+    obt_main_loop_signal_add(ob_main_loop, SIGTTOU, signal_handler, NULL,NULL);
+
+    ob_screen = DefaultScreen(obt_display);
+
+    ob_rr_inst = RrInstanceNew(obt_display, ob_screen);
     if (ob_rr_inst == NULL)
         ob_exit_with_error(_("Failed to initialize the obrender library."));
     /* Saving 3 resizes of an RrImage makes a lot of sense for icons, as there
@@ -187,7 +180,7 @@ gint main(gint argc, gchar **argv)
     */
     ob_rr_icons = RrImageCacheNew(3);
 
-    XSynchronize(ob_display, xsync);
+    XSynchronize(obt_display, xsync);
 
     /* check for locale support */
     if (!XSupportsLocale())
@@ -195,12 +188,9 @@ gint main(gint argc, gchar **argv)
     if (!XSetLocaleModifiers(""))
         g_message(_("Cannot set locale modifiers for the X server."));
 
-    /* set our error handler */
-    XSetErrorHandler(xerror_handler);
-
     /* set the DISPLAY environment variable for any lauched children, to the
        display we're using, so they open in the right place. */
-    setenv("DISPLAY", DisplayString(ob_display), TRUE);
+    setenv("DISPLAY", DisplayString(obt_display), TRUE);
 
     /* create available cursors */
     cursors[OB_CURSOR_NONE] = None;
@@ -221,35 +211,30 @@ gint main(gint argc, gchar **argv)
     cursors[OB_CURSOR_NORTHWEST] = load_cursor("top_left_corner",
                                                XC_top_left_corner);
 
-    prop_startup(); /* get atoms values for the display */
-    extensions_query_all(); /* find which extensions are present */
-
     if (screen_annex()) { /* it will be ours! */
         do {
             ObPrompt *xmlprompt = NULL;
 
-            modkeys_startup(reconfigure);
+            if (reconfigure) obt_keyboard_reload();
 
             /* get the keycodes for keys we use */
-            keys[OB_KEY_RETURN] = modkeys_sym_to_code(XK_Return);
-            keys[OB_KEY_ESCAPE] = modkeys_sym_to_code(XK_Escape);
-            keys[OB_KEY_LEFT] = modkeys_sym_to_code(XK_Left);
-            keys[OB_KEY_RIGHT] = modkeys_sym_to_code(XK_Right);
-            keys[OB_KEY_UP] = modkeys_sym_to_code(XK_Up);
-            keys[OB_KEY_DOWN] = modkeys_sym_to_code(XK_Down);
-            keys[OB_KEY_TAB] = modkeys_sym_to_code(XK_Tab);
-            keys[OB_KEY_SPACE] = modkeys_sym_to_code(XK_space);
-            keys[OB_KEY_HOME] = modkeys_sym_to_code(XK_Home);
-            keys[OB_KEY_END] = modkeys_sym_to_code(XK_End);
+            keys[OB_KEY_RETURN] = obt_keyboard_keysym_to_keycode(XK_Return);
+            keys[OB_KEY_ESCAPE] = obt_keyboard_keysym_to_keycode(XK_Escape);
+            keys[OB_KEY_LEFT] = obt_keyboard_keysym_to_keycode(XK_Left);
+            keys[OB_KEY_RIGHT] = obt_keyboard_keysym_to_keycode(XK_Right);
+            keys[OB_KEY_UP] = obt_keyboard_keysym_to_keycode(XK_Up);
+            keys[OB_KEY_DOWN] = obt_keyboard_keysym_to_keycode(XK_Down);
+            keys[OB_KEY_TAB] = obt_keyboard_keysym_to_keycode(XK_Tab);
+            keys[OB_KEY_SPACE] = obt_keyboard_keysym_to_keycode(XK_space);
+            keys[OB_KEY_HOME] = obt_keyboard_keysym_to_keycode(XK_Home);
+            keys[OB_KEY_END] = obt_keyboard_keysym_to_keycode(XK_End);
 
             {
-                ObParseInst *i;
-                xmlDocPtr doc;
-                xmlNodePtr node;
+                ObtXmlInst *i;
 
                 /* startup the parsing so everything can register sections
                    of the rc */
-                i = parse_startup();
+                i = obt_xml_instance_new();
 
                 /* register all the available actions */
                 actions_startup(reconfigure);
@@ -257,9 +242,13 @@ gint main(gint argc, gchar **argv)
                 config_startup(i);
 
                 /* parse/load user options */
-                if (parse_load_rc(config_file, &doc, &node)) {
-                    parse_tree(i, doc, node->xmlChildrenNode);
-                    parse_close(doc);
+                if ((config_file &&
+                     obt_xml_load_file(i, config_file, "openbox_config")) ||
+                    obt_xml_load_config_file(i, "openbox", "rc.xml",
+                                             "openbox_config"))
+                {
+                    obt_xml_tree_from_root(i);
+                    obt_xml_close(i);
                 }
                 else {
                     g_message(_("Unable to find a valid config file, using some simple defaults"));
@@ -270,16 +259,15 @@ gint main(gint argc, gchar **argv)
                     gchar *p = g_filename_to_utf8(config_file, -1,
                                                   NULL, NULL, NULL);
                     if (p)
-                        PROP_SETS(RootWindow(ob_display, ob_screen),
-                                  ob_config_file, p);
+                        OBT_PROP_SETS(obt_root(ob_screen), OB_CONFIG_FILE,
+                                      utf8, p);
                     g_free(p);
                 }
                 else
-                    PROP_ERASE(RootWindow(ob_display, ob_screen),
-                               ob_config_file);
+                    OBT_PROP_ERASE(obt_root(ob_screen), OB_CONFIG_FILE);
 
                 /* we're done with parsing now, kill it */
-                parse_shutdown(i);
+                obt_xml_instance_unref(i);
             }
 
             /* load the theme specified in the rc file */
@@ -290,7 +278,8 @@ gint main(gint argc, gchar **argv)
                                         config_font_inactivewindow,
                                         config_font_menutitle,
                                         config_font_menuitem,
-                                        config_font_osd)))
+                                        config_font_activeosd,
+                                        config_font_inactiveosd)))
                 {
                     RrThemeFree(ob_rr_theme);
                     ob_rr_theme = theme;
@@ -298,8 +287,8 @@ gint main(gint argc, gchar **argv)
                 if (ob_rr_theme == NULL)
                     ob_exit_with_error(_("Unable to load a theme."));
 
-                PROP_SETS(RootWindow(ob_display, ob_screen),
-                          ob_theme, ob_rr_theme->name);
+                OBT_PROP_SETS(obt_root(ob_screen),
+                              OB_THEME, utf8, ob_rr_theme->name);
             }
 
             if (reconfigure) {
@@ -338,14 +327,13 @@ gint main(gint argc, gchar **argv)
                 ObWindow *w;
 
                 /* get all the existing windows */
-                client_manage_all();
+                window_manage_all();
                 focus_nothing();
 
                 /* focus what was focused if a wm was already running */
-                if (PROP_GET32(RootWindow(ob_display, ob_screen),
-                               net_active_window, window, &xid) &&
-                    (w = g_hash_table_lookup(window_map, &xid)) &&
-                    WINDOW_IS_CLIENT(w))
+                if (OBT_PROP_GET32(obt_root(ob_screen),
+                                   NET_ACTIVE_WINDOW, WINDOW, &xid) &&
+                    (w = window_find(xid)) && WINDOW_IS_CLIENT(w))
                 {
                     client_focus(WINDOW_AS_CLIENT(w));
                 }
@@ -384,7 +372,7 @@ gint main(gint argc, gchar **argv)
                 }
             }
 
-            ob_main_loop_run(ob_main_loop);
+            obt_main_loop_run(ob_main_loop);
             ob_set_state(reconfigure ?
                          OB_STATE_RECONFIGURING : OB_STATE_EXITING);
 
@@ -393,10 +381,8 @@ gint main(gint argc, gchar **argv)
                 xmlprompt = NULL;
             }
 
-            if (!reconfigure) {
-                dock_remove_all();
-                client_unmanage_all();
-            }
+            if (!reconfigure)
+                window_unmanage_all();
 
             prompt_shutdown(reconfigure);
             menu_shutdown(reconfigure);
@@ -431,12 +417,10 @@ gint main(gint argc, gchar **argv)
             g_free(keys[OB_KEY_SPACE]);
             g_free(keys[OB_KEY_HOME]);
             g_free(keys[OB_KEY_END]);
-
-            modkeys_shutdown(reconfigure);
         } while (reconfigure);
     }
 
-    XSync(ob_display, FALSE);
+    XSync(obt_display, FALSE);
 
     RrThemeFree(ob_rr_theme);
     RrImageCacheUnref(ob_rr_icons);
@@ -444,11 +428,10 @@ gint main(gint argc, gchar **argv)
 
     session_shutdown(being_replaced);
 
-    XCloseDisplay(ob_display);
-
-    parse_paths_shutdown();
+    obt_display_close();
 
     if (restart) {
+        ob_debug_shutdown();
         if (restart_path != NULL) {
             gint argcp;
             gchar **argvp;
@@ -502,6 +485,9 @@ gint main(gint argc, gchar **argv)
     g_free(ob_sm_id);
     g_free(program_name);
 
+    if (!restart)
+        ob_debug_shutdown();
+
     return exitcode;
 }
 
@@ -509,25 +495,29 @@ static void signal_handler(gint signal, gpointer data)
 {
     switch (signal) {
     case SIGUSR1:
-        ob_debug("Caught signal %d. Restarting.\n", signal);
+        ob_debug("Caught signal %d. Restarting.", signal);
         ob_restart();
         break;
     case SIGUSR2:
-        ob_debug("Caught signal %d. Reconfiguring.\n", signal);
+        ob_debug("Caught signal %d. Reconfiguring.", signal);
         ob_reconfigure();
         break;
     case SIGCHLD:
         /* reap children */
         while (waitpid(-1, NULL, WNOHANG) > 0);
         break;
+    case SIGTTIN:
+    case SIGTTOU:
+        ob_debug("Caught signal %d. Ignoring.", signal);
+        break;
     default:
-        ob_debug("Caught signal %d. Exiting.\n", signal);
+        ob_debug("Caught signal %d. Exiting.", signal);
         /* TERM and INT return a 0 code */
         ob_exit(!(signal == SIGTERM || signal == SIGINT));
     }
 }
 
-static void print_version()
+static void print_version(void)
 {
     g_print("Openbox %s\n", PACKAGE_VERSION);
     g_print(_("Copyright (c)"));
@@ -539,7 +529,7 @@ static void print_version()
     g_print("under certain conditions. See the file COPYING for details.\n\n");
 }
 
-static void print_help()
+static void print_help(void)
 {
     g_print(_("Syntax: openbox [options]\n"));
     g_print(_("\nOptions:\n"));
@@ -559,6 +549,7 @@ static void print_help()
     g_print(_("  --sync              Run in synchronous mode\n"));
     g_print(_("  --debug             Display debugging output\n"));
     g_print(_("  --debug-focus       Display debugging output for focus handling\n"));
+    g_print(_("  --debug-session     Display debugging output for session management\n"));
     g_print(_("  --debug-xinerama    Split the display into fake xinerama screens\n"));
     g_print(_("\nPlease report bugs at %s\n"), PACKAGE_BUGREPORT);
 }
@@ -574,7 +565,7 @@ static void remove_args(gint *argc, gchar **argv, gint index, gint num)
     *argc -= num;
 }
 
-static void parse_env()
+static void parse_env(void)
 {
     const gchar *id;
 
@@ -618,16 +609,15 @@ static void parse_args(gint *argc, gchar **argv)
             xsync = TRUE;
         }
         else if (!strcmp(argv[i], "--debug")) {
-            ob_debug_show_output(TRUE);
-            ob_debug_enable(OB_DEBUG_SM, TRUE);
+            ob_debug_enable(OB_DEBUG_NORMAL, TRUE);
             ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
         }
         else if (!strcmp(argv[i], "--debug-focus")) {
-            ob_debug_show_output(TRUE);
-            ob_debug_enable(OB_DEBUG_SM, TRUE);
-            ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
             ob_debug_enable(OB_DEBUG_FOCUS, TRUE);
         }
+        else if (!strcmp(argv[i], "--debug-session")) {
+            ob_debug_enable(OB_DEBUG_SM, TRUE);
+        }
         else if (!strcmp(argv[i], "--debug-xinerama")) {
             ob_debug_xinerama = TRUE;
         }
@@ -648,7 +638,7 @@ static void parse_args(gint *argc, gchar **argv)
                    what we want */
                 config_file = argv[i+1];
                 ++i; /* skip the argument */
-                ob_debug("--config-file %s\n", config_file);
+                ob_debug("--config-file %s", config_file);
             }
         }
         else if (!strcmp(argv[i], "--sm-save-file")) {
@@ -659,7 +649,7 @@ static void parse_args(gint *argc, gchar **argv)
                 ob_sm_save_file = g_strdup(argv[i+1]);
                 remove_args(argc, argv, i, 2);
                 --i; /* this arg was removed so go back */
-                ob_debug_type(OB_DEBUG_SM, "--sm-save-file %s\n",
+                ob_debug_type(OB_DEBUG_SM, "--sm-save-file %s",
                               ob_sm_save_file);
             }
         }
@@ -671,7 +661,7 @@ static void parse_args(gint *argc, gchar **argv)
                 ob_sm_id = g_strdup(argv[i+1]);
                 remove_args(argc, argv, i, 2);
                 --i; /* this arg was removed so go back */
-                ob_debug_type(OB_DEBUG_SM, "--sm-client-id %s\n", ob_sm_id);
+                ob_debug_type(OB_DEBUG_SM, "--sm-client-id %s", ob_sm_id);
             }
         }
         else if (!strcmp(argv[i], "--sm-disable")) {
@@ -696,16 +686,16 @@ static Cursor load_cursor(const gchar *name, guint fontval)
     Cursor c = None;
 
 #if USE_XCURSOR
-    c = XcursorLibraryLoadCursor(ob_display, name);
+    c = XcursorLibraryLoadCursor(obt_display, name);
 #endif
     if (c == None)
-        c = XCreateFontCursor(ob_display, fontval);
+        c = XCreateFontCursor(obt_display, fontval);
     return c;
 }
 
 void ob_exit_with_error(const gchar *msg)
 {
-    g_message(msg);
+    g_message("%s", msg);
     session_shutdown(TRUE);
     exit(EXIT_FAILURE);
 }
@@ -716,13 +706,13 @@ void ob_restart_other(const gchar *path)
     ob_restart();
 }
 
-void ob_restart()
+void ob_restart(void)
 {
     restart = TRUE;
     ob_exit(0);
 }
 
-void ob_reconfigure()
+void ob_reconfigure(void)
 {
     reconfigure = TRUE;
     ob_exit(0);
@@ -731,14 +721,14 @@ void ob_reconfigure()
 void ob_exit(gint code)
 {
     exitcode = code;
-    ob_main_loop_exit(ob_main_loop);
+    obt_main_loop_exit(ob_main_loop);
 }
 
-void ob_exit_replace()
+void ob_exit_replace(void)
 {
     exitcode = 0;
     being_replaced = TRUE;
-    ob_main_loop_exit(ob_main_loop);
+    obt_main_loop_exit(ob_main_loop);
 }
 
 Cursor ob_cursor(ObCursor cursor)
@@ -757,7 +747,7 @@ gboolean ob_keycode_match(KeyCode code, ObKey key)
     return FALSE;
 }
 
-ObState ob_state()
+ObState ob_state(void)
 {
     return state;
 }
index 76b04ea..c43f0a6 100644 (file)
 
 #include "misc.h"
 
-#include "render/render.h"
-#include "render/theme.h"
+#include "obrender/render.h"
+#include "obrender/theme.h"
+#include "obt/mainloop.h"
+#include "obt/display.h"
 
 #include <glib.h>
 #include <X11/Xlib.h>
 
-struct _ObMainLoop;
-
 extern RrInstance *ob_rr_inst;
 extern RrImageCache *ob_rr_icons;
 extern RrTheme    *ob_rr_theme;
 
-extern struct _ObMainLoop *ob_main_loop;
-
-/*! The X display */
-extern Display *ob_display;
+extern ObtMainLoop *ob_main_loop;
 
 /*! The number of the screen on which we're running */
 extern gint     ob_screen;
@@ -51,17 +48,17 @@ extern gboolean ob_replace_wm;
 extern gboolean ob_debug_xinerama;
 
 /* The state of execution of the window manager */
-ObState ob_state();
+ObState ob_state(void);
 void ob_set_state(ObState state);
 
 void ob_restart_other(const gchar *path);
-void ob_restart();
+void ob_restart(void);
 void ob_exit(gint code);
-void ob_exit_replace();
+void ob_exit_replace(void);
 
-void ob_reconfigure();
+void ob_reconfigure(void);
 
-void ob_exit_with_error(const gchar *msg);
+void ob_exit_with_error(const gchar *msg) G_GNUC_NORETURN;
 
 Cursor ob_cursor(ObCursor cursor);
 
index 46952f7..b847929 100644 (file)
 
 #include "ping.h"
 #include "client.h"
-#include "prop.h"
 #include "event.h"
 #include "debug.h"
-#include "mainloop.h"
 #include "openbox.h"
+#include "obt/mainloop.h"
+#include "obt/prop.h"
 
 typedef struct _ObPingTarget
 {
@@ -79,8 +79,8 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h)
     t->client = client;
     t->h = h;
 
-    ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout,
-                             t, g_direct_equal, NULL);
+    obt_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout,
+                              t, g_direct_equal, NULL);
     /* act like we just timed out immediately, to start the pinging process
        now instead of after the first delay.  this makes sure the client
        ends up in the ping_ids hash table now. */
@@ -95,7 +95,7 @@ void ping_got_pong(guint32 id)
     ObPingTarget *t;
 
     if ((t = g_hash_table_lookup(ping_ids, &id))) {
-        /*ob_debug("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/
+        /*ob_debug("-PONG: '%s' (id %u)", t->client->title, t->id);*/
         if (t->waiting > PING_TIMEOUT_WARN) {
             /* we had notified that they weren't responding, so now we
                need to notify that they are again */
@@ -107,7 +107,7 @@ void ping_got_pong(guint32 id)
         ping_end(t->client, NULL);
     }
     else
-        ob_debug("Got PONG with id %u but not waiting for one\n", id);
+        ob_debug("Got PONG with id %u but not waiting for one", id);
 }
 
 static gboolean find_client(gpointer key, gpointer value, gpointer client)
@@ -130,10 +130,10 @@ static void ping_send(ObPingTarget *t)
         g_hash_table_insert(ping_ids, &t->id, t);
     }
 
-    /*ob_debug("+PING: '%s' (id %u)\n", t->client->title, t->id);*/
-    PROP_MSG_TO(t->client->window, t->client->window, wm_protocols,
-                prop_atoms.net_wm_ping, t->id, t->client->window, 0, 0,
-                NoEventMask);
+    /*ob_debug("+PING: '%s' (id %u)", t->client->title, t->id);*/
+    OBT_PROP_MSG_TO(t->client->window, t->client->window, WM_PROTOCOLS,
+                    OBT_PROP_ATOM(NET_WM_PING), t->id, t->client->window, 0, 0,
+                    NoEventMask);
 }
 
 static gboolean ping_timeout(gpointer data)
@@ -158,7 +158,8 @@ static void ping_end(ObClient *client, gpointer data)
     if ((t = g_hash_table_find(ping_ids, find_client, client))) {
         g_hash_table_remove(ping_ids, &t->id);
 
-        ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, FALSE);
+        obt_main_loop_timeout_remove_data(ob_main_loop, ping_timeout,
+                                          t, FALSE);
 
         g_free(t);
     }
index d1d0481..c396e8f 100644 (file)
@@ -63,7 +63,7 @@ static Rect **pick_head(ObClient *c)
     /* try direct parent first */
     if ((p = client_direct_parent(c))) {
         add_choice(choice, client_monitor(p));
-        ob_debug("placement adding choice %d for parent\n",
+        ob_debug("placement adding choice %d for parent",
                  client_monitor(p));
     }
 
@@ -79,7 +79,7 @@ static Rect **pick_head(ObClient *c)
                  itc->desktop == DESKTOP_ALL || c->desktop == DESKTOP_ALL))
             {
                 add_choice(choice, client_monitor(it->data));
-                ob_debug("placement adding choice %d for group sibling\n",
+                ob_debug("placement adding choice %d for group sibling",
                          client_monitor(it->data));
             }
         }
@@ -90,7 +90,7 @@ static Rect **pick_head(ObClient *c)
             if (itc != c) {
                 add_choice(choice, client_monitor(it->data));
                 ob_debug("placement adding choice %d for group sibling on "
-                         "another desktop\n", client_monitor(it->data));
+                         "another desktop", client_monitor(it->data));
             }
         }
     }
@@ -100,7 +100,7 @@ static Rect **pick_head(ObClient *c)
         config_place_monitor != OB_PLACE_MONITOR_MOUSE)
     {
         add_choice(choice, client_monitor(focus_client));
-        ob_debug("placement adding choice %d for normal focused window\n",
+        ob_debug("placement adding choice %d for normal focused window",
                  client_monitor(focus_client));
     }
 
@@ -112,7 +112,7 @@ static Rect **pick_head(ObClient *c)
         g_free(monitor);
         if (contain) {
             add_choice(choice, i);
-            ob_debug("placement adding choice %d for mouse pointer\n", i);
+            ob_debug("placement adding choice %d for mouse pointer", i);
             break;
         }
     }
@@ -468,12 +468,12 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y)
     return FALSE;
 }
 
-/* Return TRUE if we want client.c to enforce on-screen-keeping */
+/*! Return TRUE if openbox chose the position for the window, and FALSE if
+  the application chose it */
 gboolean place_client(ObClient *client, gint *x, gint *y,
                       ObAppSettings *settings)
 {
     gboolean ret;
-    gboolean userplaced = FALSE;
 
     /* per-app settings override program specified position
      * but not user specified, unless pos_force is enabled */
@@ -484,8 +484,8 @@ gboolean place_client(ObClient *client, gint *x, gint *y,
         return FALSE;
 
     /* try a number of methods */
-    ret = place_transient_splash(client, x, y) ||
-        (userplaced = place_per_app_setting(client, x, y, settings)) ||
+    ret = place_per_app_setting(client, x, y, settings) ||
+        place_transient_splash(client, x, y) ||
         (config_place_policy == OB_PLACE_POLICY_MOUSE &&
          place_under_mouse(client, x, y)) ||
         place_nooverlap(client, x, y) ||
@@ -494,5 +494,5 @@ gboolean place_client(ObClient *client, gint *x, gint *y,
 
     /* get where the client should be */
     frame_frame_gravity(client->frame, x, y);
-    return !userplaced;
+    return TRUE;
 }
index 5cbe034..90ec32d 100644 (file)
 #include "stacking.h"
 #include "event.h"
 #include "screen.h"
-#include "mainloop.h"
-#include "render/render.h"
-#include "render/theme.h"
+#include "obrender/render.h"
+#include "obrender/theme.h"
 
 ObPopup *popup_new(void)
 {
     XSetWindowAttributes attrib;
     ObPopup *self = g_new0(ObPopup, 1);
 
-    self->obwin.type = Window_Internal;
+    self->obwin.type = OB_WINDOW_CLASS_INTERNAL;
     self->gravity = NorthWestGravity;
     self->x = self->y = self->textw = self->h = 0;
-    self->a_bg = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg);
+    self->a_bg = RrAppearanceCopy(ob_rr_theme->osd_bg);
     self->a_text = RrAppearanceCopy(ob_rr_theme->osd_hilite_label);
     self->iconwm = self->iconhm = 1;
 
     attrib.override_redirect = True;
-    self->bg = XCreateWindow(ob_display, RootWindow(ob_display, ob_screen),
+    self->bg = XCreateWindow(obt_display, obt_root(ob_screen),
                              0, 0, 1, 1, 0, RrDepth(ob_rr_inst),
                              InputOutput, RrVisual(ob_rr_inst),
                              CWOverrideRedirect, &attrib);
 
-    self->text = XCreateWindow(ob_display, self->bg,
+    self->text = XCreateWindow(obt_display, self->bg,
                                0, 0, 1, 1, 0, RrDepth(ob_rr_inst),
                                InputOutput, RrVisual(ob_rr_inst), 0, NULL);
 
-    XSetWindowBorderWidth(ob_display, self->bg, ob_rr_theme->obwidth);
-    XSetWindowBorder(ob_display, self->bg,
+    XSetWindowBorderWidth(obt_display, self->bg, ob_rr_theme->obwidth);
+    XSetWindowBorder(obt_display, self->bg,
                      RrColorPixel(ob_rr_theme->osd_border_color));
 
-    XMapWindow(ob_display, self->text);
+    XMapWindow(obt_display, self->text);
 
     stacking_add(INTERNAL_AS_WINDOW(self));
-    g_hash_table_insert(window_map, &self->bg, self);
+    window_add(&self->bg, INTERNAL_AS_WINDOW(self));
     return self;
 }
 
@@ -67,11 +66,11 @@ void popup_free(ObPopup *self)
     if (self) {
         popup_hide(self); /* make sure it's not showing or is being delayed and
                              will be shown */
-        XDestroyWindow(ob_display, self->bg);
-        XDestroyWindow(ob_display, self->text);
+        XDestroyWindow(obt_display, self->bg);
+        XDestroyWindow(obt_display, self->text);
         RrAppearanceFree(self->a_bg);
         RrAppearanceFree(self->a_text);
-        g_hash_table_remove(window_map, &self->bg);
+        window_remove(self->bg);
         stacking_remove(self);
         g_free(self);
     }
@@ -143,7 +142,7 @@ static gboolean popup_show_timeout(gpointer data)
 {
     ObPopup *self = data;
 
-    XMapWindow(ob_display, self->bg);
+    XMapWindow(obt_display, self->bg);
     stacking_raise(INTERNAL_AS_WINDOW(self));
     self->mapped = TRUE;
     self->delay_mapped = FALSE;
@@ -160,11 +159,12 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
     gint textx, texty, textw, texth;
     gint iconx, icony, iconw, iconh;
     Rect *area, mon;
+    gboolean hasicon = self->hasicon;
 
     /* when there is no icon and the text is not parent relative, then
        fill the whole dialog with the text appearance, don't use the bg at all
     */
-    if (self->hasicon || self->a_text->surface.grad == RR_SURFACE_PARENTREL)
+    if (hasicon || self->a_text->surface.grad == RR_SURFACE_PARENTREL)
         RrMargins(self->a_bg, &l, &t, &r, &b);
     else
         l = t = r = b = 0;
@@ -192,7 +192,7 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
     iconx = textx = l + ob_rr_theme->paddingx;
 
     emptyx = l + r + ob_rr_theme->paddingx * 2;
-    if (self->hasicon) {
+    if (hasicon) {
         iconw = texth * self->iconwm;
         iconh = texth * self->iconhm;
         textx += iconw + ob_rr_theme->paddingx;
@@ -207,7 +207,7 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
     /* when there is no icon, then fill the whole dialog with the text
        appearance
     */
-    if (!self->hasicon)
+    if (!hasicon)
     {
         textx = texty = 0;
         texth += emptyy;
@@ -275,22 +275,22 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
     }
 
     /* set the windows/appearances up */
-    XMoveResizeWindow(ob_display, self->bg, x, y, w, h);
+    XMoveResizeWindow(obt_display, self->bg, x, y, w, h);
     /* when there is no icon and the text is not parent relative, then
        fill the whole dialog with the text appearance, don't use the bg at all
     */
-    if (self->hasicon || self->a_text->surface.grad == RR_SURFACE_PARENTREL)
+    if (hasicon || self->a_text->surface.grad == RR_SURFACE_PARENTREL)
         RrPaint(self->a_bg, self->bg, w, h);
 
     if (textw) {
         self->a_text->surface.parent = self->a_bg;
         self->a_text->surface.parentx = textx;
         self->a_text->surface.parenty = texty;
-        XMoveResizeWindow(ob_display, self->text, textx, texty, textw, texth);
+        XMoveResizeWindow(obt_display, self->text, textx, texty, textw, texth);
         RrPaint(self->a_text, self->text, textw, texth);
     }
 
-    if (self->hasicon)
+    if (hasicon)
         self->draw_icon(iconx, icony, iconw, iconh, self->draw_icon_data);
 
     /* do the actual showing */
@@ -298,9 +298,9 @@ void popup_delay_show(ObPopup *self, gulong usec, gchar *text)
         if (usec) {
             /* don't kill previous show timers */
             if (!self->delay_mapped) {
-                ob_main_loop_timeout_add(ob_main_loop, usec,
-                                         popup_show_timeout, self,
-                                         g_direct_equal, NULL);
+                obt_main_loop_timeout_add(ob_main_loop, usec,
+                                          popup_show_timeout, self,
+                                          g_direct_equal, NULL);
                 self->delay_mapped = TRUE;
             }
         } else {
@@ -317,12 +317,12 @@ void popup_hide(ObPopup *self)
         /* kill enter events cause by this unmapping */
         ignore_start = event_start_ignore_all_enters();
 
-        XUnmapWindow(ob_display, self->bg);
+        XUnmapWindow(obt_display, self->bg);
         self->mapped = FALSE;
 
         event_end_ignore_all_enters(ignore_start);
     } else if (self->delay_mapped) {
-        ob_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE);
+        obt_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE);
         self->delay_mapped = FALSE;
     }
 }
@@ -334,7 +334,7 @@ static void icon_popup_draw_icon(gint x, gint y, gint w, gint h, gpointer data)
     self->a_icon->surface.parent = self->popup->a_bg;
     self->a_icon->surface.parentx = x;
     self->a_icon->surface.parenty = y;
-    XMoveResizeWindow(ob_display, self->icon, x, y, w, h);
+    XMoveResizeWindow(obt_display, self->icon, x, y, w, h);
     RrPaint(self->a_icon, self->icon, w, h);
 }
 
@@ -345,11 +345,11 @@ ObIconPopup *icon_popup_new(void)
     self = g_new0(ObIconPopup, 1);
     self->popup = popup_new();
     self->a_icon = RrAppearanceCopy(ob_rr_theme->a_clear_tex);
-    self->icon = XCreateWindow(ob_display, self->popup->bg,
+    self->icon = XCreateWindow(obt_display, self->popup->bg,
                                0, 0, 1, 1, 0,
                                RrDepth(ob_rr_inst), InputOutput,
                                RrVisual(ob_rr_inst), 0, NULL);
-    XMapWindow(ob_display, self->icon);
+    XMapWindow(obt_display, self->icon);
 
     self->popup->hasicon = TRUE;
     self->popup->draw_icon = icon_popup_draw_icon;
@@ -361,7 +361,7 @@ ObIconPopup *icon_popup_new(void)
 void icon_popup_free(ObIconPopup *self)
 {
     if (self) {
-        XDestroyWindow(ob_display, self->icon);
+        XDestroyWindow(obt_display, self->icon);
         RrAppearanceFree(self->a_icon);
         popup_free(self->popup);
         g_free(self);
@@ -487,7 +487,7 @@ static void pager_popup_draw_icon(gint px, gint py, gint w, gint h,
                 a->surface.parent = self->popup->a_bg;
                 a->surface.parentx = x + px;
                 a->surface.parenty = y + py;
-                XMoveResizeWindow(ob_display, self->wins[n],
+                XMoveResizeWindow(obt_display, self->wins[n],
                                   x + px, y + py, eachw, eachh);
                 RrPaint(a, self->wins[n], eachw, eachh);
             }
@@ -506,8 +506,8 @@ ObPagerPopup *pager_popup_new(void)
 
     self->desks = 0;
     self->wins = g_new(Window, self->desks);
-    self->hilight = RrAppearanceCopy(ob_rr_theme->osd_hilite_fg);
-    self->unhilight = RrAppearanceCopy(ob_rr_theme->osd_unhilite_fg);
+    self->hilight = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg);
+    self->unhilight = RrAppearanceCopy(ob_rr_theme->osd_unhilite_bg);
 
     self->popup->hasicon = TRUE;
     self->popup->draw_icon = pager_popup_draw_icon;
@@ -522,7 +522,7 @@ void pager_popup_free(ObPagerPopup *self)
         guint i;
 
         for (i = 0; i < self->desks; ++i)
-            XDestroyWindow(ob_display, self->wins[i]);
+            XDestroyWindow(obt_display, self->wins[i]);
         g_free(self->wins);
         RrAppearanceFree(self->hilight);
         RrAppearanceFree(self->unhilight);
@@ -538,7 +538,7 @@ void pager_popup_delay_show(ObPagerPopup *self, gulong usec,
 
     if (screen_num_desktops < self->desks)
         for (i = screen_num_desktops; i < self->desks; ++i)
-            XDestroyWindow(ob_display, self->wins[i]);
+            XDestroyWindow(obt_display, self->wins[i]);
 
     if (screen_num_desktops != self->desks)
         self->wins = g_renew(Window, self->wins, screen_num_desktops);
@@ -549,12 +549,12 @@ void pager_popup_delay_show(ObPagerPopup *self, gulong usec,
 
             attr.border_pixel =
                 RrColorPixel(ob_rr_theme->osd_border_color);
-            self->wins[i] = XCreateWindow(ob_display, self->popup->bg,
+            self->wins[i] = XCreateWindow(obt_display, self->popup->bg,
                                           0, 0, 1, 1, ob_rr_theme->obwidth,
                                           RrDepth(ob_rr_inst), InputOutput,
                                           RrVisual(ob_rr_inst), CWBorderPixel,
                                           &attr);
-            XMapWindow(ob_display, self->wins[i]);
+            XMapWindow(obt_display, self->wins[i]);
         }
 
     self->desks = screen_num_desktops;
index 2b01ce2..f876e3c 100644 (file)
@@ -20,7 +20,7 @@
 #define __popup_h
 
 #include "window.h"
-#include "render/render.h"
+#include "obrender/render.h"
 #include <glib.h>
 
 struct _ObClientIcon;
@@ -77,7 +77,7 @@ struct _ObPagerPopup
     RrAppearance *unhilight;
 };
 
-ObPopup *popup_new();
+ObPopup *popup_new(void);
 void popup_free(ObPopup *self);
 
 /*! Position the popup. The gravity rules are not the same X uses for windows,
@@ -105,7 +105,7 @@ void popup_hide(ObPopup *self);
 RrAppearance *popup_icon_appearance(ObPopup *self);
 
 
-ObIconPopup *icon_popup_new();
+ObIconPopup *icon_popup_new(void);
 void icon_popup_free(ObIconPopup *self);
 
 #define icon_popup_show(s, t, i) icon_popup_delay_show((s),0,(t),(i))
@@ -124,7 +124,7 @@ void icon_popup_delay_show(ObIconPopup *self, gulong usec,
 #define icon_popup_set_text_align(p, j) popup_set_text_align((p)->popup,(j))
 void icon_popup_icon_size_multiplier(ObIconPopup *self, guint wm, guint hm);
 
-ObPagerPopup *pager_popup_new();
+ObPagerPopup *pager_popup_new(void);
 void pager_popup_free(ObPagerPopup *self);
 
 #define pager_popup_show(s, t, d) pager_popup_delay_show((s),0,(t),(d))
index bef06a7..4f8930d 100644 (file)
 #include "prompt.h"
 #include "openbox.h"
 #include "screen.h"
-#include "openbox.h"
 #include "client.h"
 #include "group.h"
-#include "prop.h"
-#include "modkeys.h"
 #include "event.h"
+#include "obt/display.h"
+#include "obt/keyboard.h"
+#include "obt/prop.h"
 #include "gettext.h"
 
 static GList *prompt_list = NULL;
@@ -57,7 +57,7 @@ void prompt_startup(gboolean reconfig)
     RrColor *c_button, *c_focus, *c_press, *c_pfocus;
 
     /* note: this is not a copy, don't free it */
-    prompt_a_bg = ob_rr_theme->osd_hilite_bg;
+    prompt_a_bg = ob_rr_theme->osd_bg;
 
     prompt_a_button = RrAppearanceCopy(ob_rr_theme->a_focused_unpressed_close);
     prompt_a_focus = RrAppearanceCopy(ob_rr_theme->a_hover_focused_close);
@@ -95,7 +95,7 @@ void prompt_startup(gboolean reconfig)
     prompt_a_button->texture[0].data.text.color = c_button;
     prompt_a_focus->texture[0].data.text.color = c_focus;
     prompt_a_press->texture[0].data.text.color = c_press;
-    prompt_a_pfocus->texture[0].data.text.color = c_press;
+    prompt_a_pfocus->texture[0].data.text.color = c_pfocus;
 
     prompt_a_focus->texture[1].data.lineart.color = c_focus;
     prompt_a_focus->texture[2].data.lineart.color = c_focus;
@@ -159,9 +159,8 @@ ObPrompt* prompt_new(const gchar *msg, const gchar *title,
     self->data = data;
     self->default_result = default_result;
     self->cancel_result = cancel_result;
-    self->super.type = Window_Prompt;
-    self->super.window = XCreateWindow(ob_display,
-                                       RootWindow(ob_display, ob_screen),
+    self->super.type = OB_WINDOW_CLASS_PROMPT;
+    self->super.window = XCreateWindow(obt_display, obt_root(ob_screen),
                                        0, 0, 1, 1, 0,
                                        CopyFromParent, InputOutput,
                                        CopyFromParent,
@@ -169,23 +168,23 @@ ObPrompt* prompt_new(const gchar *msg, const gchar *title,
                                        &attrib);
 
     /* make it a dialog type window */
-    PROP_SET32(self->super.window, net_wm_window_type, atom,
-               prop_atoms.net_wm_window_type_dialog);
+    OBT_PROP_SET32(self->super.window, NET_WM_WINDOW_TYPE, ATOM,
+                   OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG));
 
     /* set the window's title */
     if (title)
-        PROP_SETS(self->super.window, net_wm_name, title);
+        OBT_PROP_SETS(self->super.window, NET_WM_NAME, utf8, title);
 
     /* listen for key presses on the window */
     self->event_mask = KeyPressMask;
 
     /* set up the text message widow */
     self->msg.text = g_strdup(msg);
-    self->msg.window = XCreateWindow(ob_display, self->super.window,
+    self->msg.window = XCreateWindow(obt_display, self->super.window,
                                      0, 0, 1, 1, 0,
                                      CopyFromParent, InputOutput,
                                      CopyFromParent, 0, NULL);
-    XMapWindow(ob_display, self->msg.window);
+    XMapWindow(obt_display, self->msg.window);
 
     /* set up the buttons from the answers */
 
@@ -208,16 +207,15 @@ ObPrompt* prompt_new(const gchar *msg, const gchar *title,
     }
 
     for (i = 0; i < self->n_buttons; ++i) {
-        self->button[i].window = XCreateWindow(ob_display, self->super.window,
+        self->button[i].window = XCreateWindow(obt_display, self->super.window,
                                                0, 0, 1, 1, 0,
                                                CopyFromParent, InputOutput,
                                                CopyFromParent, 0, NULL);
-        XMapWindow(ob_display, self->button[i].window);
-        g_hash_table_insert(window_map, &self->button[i].window,
-                            PROMPT_AS_WINDOW(self));
+        XMapWindow(obt_display, self->button[i].window);
+        window_add(&self->button[i].window, PROMPT_AS_WINDOW(self));
 
         /* listen for button presses on the buttons */
-        XSelectInput(ob_display, self->button[i].window,
+        XSelectInput(obt_display, self->button[i].window,
                      ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
     }
 
@@ -242,12 +240,12 @@ void prompt_unref(ObPrompt *self)
         prompt_list = g_list_remove(prompt_list, self);
 
         for (i = 0; i < self->n_buttons; ++i) {
-            g_hash_table_remove(window_map, &self->button[i].window);
-            XDestroyWindow(ob_display, self->button[i].window);
+            window_remove(self->button[i].window);
+            XDestroyWindow(obt_display, self->button[i].window);
         }
 
-        XDestroyWindow(ob_display, self->msg.window);
-        XDestroyWindow(ob_display, self->super.window);
+        XDestroyWindow(obt_display, self->msg.window);
+        XDestroyWindow(obt_display, self->super.window);
         g_free(self);
     }
 }
@@ -329,11 +327,11 @@ static void prompt_layout(ObPrompt *self)
     prompt_resize(self, w + l + r, h + t + b);
 
     /* move and resize the internal windows */
-    XMoveResizeWindow(ob_display, self->msg.window,
+    XMoveResizeWindow(obt_display, self->msg.window,
                       self->msg.x, self->msg.y,
                       self->msg.width, self->msg.height);
     for (i = 0; i < self->n_buttons; ++i)
-        XMoveResizeWindow(ob_display, self->button[i].window,
+        XMoveResizeWindow(obt_display, self->button[i].window,
                           self->button[i].x, self->button[i].y,
                           self->button[i].width, self->button[i].height);
 }
@@ -350,13 +348,13 @@ static void prompt_resize(ObPrompt *self, gint w, gint h)
     hints.flags = PMinSize | PMaxSize;
     hints.min_width = hints.max_width = w;
     hints.min_height = hints.max_height = h;
-    XSetWMNormalHints(ob_display, self->super.window, &hints);
+    XSetWMNormalHints(obt_display, self->super.window, &hints);
 
     if (self->mapped) {
         /* send a configure request like a normal client would */
         req.type = ConfigureRequest;
-        req.display = ob_display;
-        req.parent = RootWindow(ob_display, ob_screen);
+        req.display = obt_display;
+        req.parent = obt_root(ob_screen);
         req.window = self->super.window;
         req.width = w;
         req.height = h;
@@ -365,7 +363,7 @@ static void prompt_resize(ObPrompt *self, gint w, gint h)
                    (XEvent*)&req);
     }
     else
-        XResizeWindow(ob_display, self->super.window, w, h);
+        XResizeWindow(obt_display, self->super.window, w, h);
 }
 
 static void setup_button_focus_tex(ObPromptElement *e, RrAppearance *a,
@@ -413,10 +411,10 @@ static void render_button(ObPrompt *self, ObPromptElement *e)
 {
     RrAppearance *a;
 
-    if (e->pressed && self->focus == e) a = prompt_a_pfocus;
-    else if (self->focus == e)          a = prompt_a_focus;
-    else if (e->pressed)                a = prompt_a_press;
-    else                                a = prompt_a_button;
+    if (e->hover && self->focus == e) a = prompt_a_pfocus;
+    else if (self->focus == e)        a = prompt_a_focus;
+    else if (e->pressed)              a = prompt_a_press;
+    else                              a = prompt_a_button;
 
     a->surface.parent = prompt_a_bg;
     a->surface.parentx = e->x;
@@ -459,11 +457,11 @@ void prompt_show(ObPrompt *self, ObClient *parent, gboolean modal)
 
     if (self->mapped) {
         /* activate the prompt */
-        PROP_MSG(self->super.window, net_active_window,
-                 1, /* from an application.. */
-                 event_curtime,
-                 0,
-                 0);
+        OBT_PROP_MSG(ob_screen, self->super.window, NET_ACTIVE_WINDOW,
+                     1, /* from an application.. */
+                     event_curtime,
+                     0,
+                     0, 0);
         return;
     }
 
@@ -485,7 +483,7 @@ void prompt_show(ObPrompt *self, ObClient *parent, gboolean modal)
             /* make it transient for the window's group */
             h.flags = WindowGroupHint;
             h.window_group = parent->group->leader;
-            p = RootWindow(ob_display, ob_screen);
+            p = obt_root(ob_screen);
         }
         else {
             /* make it transient for the window directly */
@@ -493,15 +491,16 @@ void prompt_show(ObPrompt *self, ObClient *parent, gboolean modal)
             p = parent->window;
         }
 
-        XSetWMHints(ob_display, self->super.window, &h);
-        PROP_SET32(self->super.window, wm_transient_for, window, p);
+        XSetWMHints(obt_display, self->super.window, &h);
+        OBT_PROP_SET32(self->super.window, WM_TRANSIENT_FOR, WINDOW, p);
 
-        states[0] = prop_atoms.net_wm_state_modal;
+        states[0] = OBT_PROP_ATOM(NET_WM_STATE_MODAL);
         nstates = (modal ? 1 : 0);
-        PROP_SETA32(self->super.window, net_wm_state, atom, states, nstates);
+        OBT_PROP_SETA32(self->super.window, NET_WM_STATE, ATOM,
+                        states, nstates);
     }
     else
-        PROP_ERASE(self->super.window, wm_transient_for);
+        OBT_PROP_ERASE(self->super.window, WM_TRANSIENT_FOR);
 
     /* set up the dialog and render it */
     prompt_layout(self);
@@ -514,7 +513,7 @@ void prompt_show(ObPrompt *self, ObClient *parent, gboolean modal)
 
 void prompt_hide(ObPrompt *self)
 {
-    XUnmapWindow(ob_display, self->super.window);
+    XUnmapWindow(obt_display, self->super.window);
     self->mapped = FALSE;
 }
 
@@ -525,7 +524,7 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e)
 
     if (e->type != KeyPress) return FALSE;
 
-    shift_mask = modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT);
+    shift_mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT);
     shift = !!(e->xkey.state & shift_mask);
 
     /* only accept shift */
@@ -588,25 +587,28 @@ gboolean prompt_mouse_event(ObPrompt *self, XEvent *e)
 
         oldfocus = self->focus;
 
-        but->pressed = TRUE;
+        but->pressed = but->hover = TRUE;
         self->focus = but;
 
         if (oldfocus != but) render_button(self, oldfocus);
         render_button(self, but);
     }
     else if (e->type == ButtonRelease) {
-        if (but->pressed)
+        if (but->hover)
             prompt_run_callback(self, but->result);
+        but->pressed = FALSE;
     }
     else if (e->type == MotionNotify) {
-        gboolean press;
+        if (but->pressed) {
+            gboolean hover;
 
-        press = (e->xmotion.x >= 0 && e->xmotion.y >= 0 &&
-                 e->xmotion.x < but->width && e->xmotion.y < but->height);
+            hover = (e->xmotion.x >= 0 && e->xmotion.y >= 0 &&
+                     e->xmotion.x < but->width && e->xmotion.y < but->height);
 
-        if (press != but->pressed) {
-            but->pressed = press;
-            render_button(self, but);
+            if (hover != but->hover) {
+                but->hover = hover;
+                render_button(self, but);
+            }
         }
     }
     return TRUE;
index ef19990..3c46c30 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "window.h"
 #include "geom.h"
-#include "render/render.h"
+#include "obrender/render.h"
 #include <glib.h>
 #include <X11/Xlib.h>
 
@@ -38,12 +38,13 @@ struct _ObPromptElement {
 
     gint x, y, width, height;
     gboolean pressed;
+    gboolean hover;
     gint result;
 };
 
 struct _ObPrompt
 {
-    InternalWindow super;
+    ObInternalWindow super;
     gint ref;
 
     guint event_mask;
index 91eabcb..dc4e2d7 100644 (file)
    See the COPYING file for a copy of the GNU General Public License.
 */
 
+#include "resist.h"
 #include "client.h"
 #include "frame.h"
 #include "stacking.h"
 #include "screen.h"
 #include "dock.h"
 #include "config.h"
-#include "resist.h"
-#include "parser/parse.h"
 
 #include <glib.h>
 
@@ -330,7 +329,6 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
     Rect *area, *parea;
     gint al, at, ar, ab; /* screen boundaries */
     gint pl, pt, pr, pb; /* physical screen boundaries */
-    gint incw, inch;
     guint i;
     Rect desired_area;
 
@@ -341,9 +339,6 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
     t = RECT_TOP(c->frame->area);
     b = RECT_BOTTOM(c->frame->area);
 
-    incw = c->size_inc.width;
-    inch = c->size_inc.height;
-
     RECT_SET(desired_area, c->area.x, c->area.y, *w, *h);
 
     for (i = 0; i < screen_num_monitors; ++i) {
index a2b3f16..31cc717 100644 (file)
 #ifndef ob__resist_h
 #define ob__resist_h
 
-struct _ObClient;
+#include "misc.h"
 
 #include <glib.h>
 
+struct _ObClient;
+
 /*! @x The client's x destination (in the client's coordinates, not the frame's
     @y The client's y destination (in the client's coordinates, not the frame's
 */
index 55fd58d..cbcaad7 100644 (file)
 #include "debug.h"
 #include "openbox.h"
 #include "dock.h"
-#include "xerror.h"
-#include "prop.h"
 #include "grab.h"
 #include "startupnotify.h"
 #include "moveresize.h"
 #include "config.h"
-#include "mainloop.h"
 #include "screen.h"
 #include "client.h"
 #include "session.h"
 #include "focus.h"
 #include "focus_cycle.h"
 #include "popup.h"
-#include "extensions.h"
-#include "render/render.h"
+#include "version.h"
+#include "obrender/render.h"
 #include "gettext.h"
+#include "obt/display.h"
+#include "obt/prop.h"
+#include "obt/mainloop.h"
 
 #include <X11/Xlib.h>
 #ifdef HAVE_UNISTD_H
@@ -79,6 +79,7 @@ static GSList *struts_right = NULL;
 static GSList *struts_bottom = NULL;
 
 static ObPagerPopup *desktop_popup;
+static gboolean      desktop_popup_perm;
 
 /*! The number of microseconds that you need to be on a desktop before it will
   replace the remembered "last desktop" */
@@ -92,10 +93,10 @@ static gboolean replace_wm(void)
     Time timestamp;
 
     wm_sn = g_strdup_printf("WM_S%d", ob_screen);
-    wm_sn_atom = XInternAtom(ob_display, wm_sn, FALSE);
+    wm_sn_atom = XInternAtom(obt_display, wm_sn, FALSE);
     g_free(wm_sn);
 
-    current_wm_sn_owner = XGetSelectionOwner(ob_display, wm_sn_atom);
+    current_wm_sn_owner = XGetSelectionOwner(obt_display, wm_sn_atom);
     if (current_wm_sn_owner == screen_support_win)
         current_wm_sn_owner = None;
     if (current_wm_sn_owner) {
@@ -104,24 +105,23 @@ static gboolean replace_wm(void)
                       ob_screen);
             return FALSE;
         }
-        xerror_set_ignore(TRUE);
-        xerror_occured = FALSE;
+        obt_display_ignore_errors(TRUE);
 
         /* We want to find out when the current selection owner dies */
-        XSelectInput(ob_display, current_wm_sn_owner, StructureNotifyMask);
-        XSync(ob_display, FALSE);
+        XSelectInput(obt_display, current_wm_sn_owner, StructureNotifyMask);
+        XSync(obt_display, FALSE);
 
-        xerror_set_ignore(FALSE);
-        if (xerror_occured)
+        obt_display_ignore_errors(FALSE);
+        if (obt_display_error_occured)
             current_wm_sn_owner = None;
     }
 
     timestamp = event_get_server_time();
 
-    XSetSelectionOwner(ob_display, wm_sn_atom, screen_support_win,
+    XSetSelectionOwner(obt_display, wm_sn_atom, screen_support_win,
                        timestamp);
 
-    if (XGetSelectionOwner(ob_display, wm_sn_atom) != screen_support_win) {
+    if (XGetSelectionOwner(obt_display, wm_sn_atom) != screen_support_win) {
         g_message(_("Could not acquire window manager selection on screen %d"),
                   ob_screen);
         return FALSE;
@@ -134,7 +134,7 @@ static gboolean replace_wm(void)
       const gulong timeout = G_USEC_PER_SEC * 15; /* wait for 15s max */
 
       while (wait < timeout) {
-          if (XCheckWindowEvent(ob_display, current_wm_sn_owner,
+          if (XCheckWindowEvent(obt_display, current_wm_sn_owner,
                                 StructureNotifyMask, &event) &&
               event.type == DestroyNotify)
               break;
@@ -149,9 +149,9 @@ static gboolean replace_wm(void)
     }
 
     /* Send client message indicating that we are now the WM */
-    prop_message(RootWindow(ob_display, ob_screen), prop_atoms.manager,
-                 timestamp, wm_sn_atom, screen_support_win, 0,
-                 SubstructureNotifyMask);
+    obt_prop_message(ob_screen, obt_root(ob_screen), OBT_PROP_ATOM(MANAGER),
+                     timestamp, wm_sn_atom, screen_support_win, 0, 0,
+                     SubstructureNotifyMask);
 
     return TRUE;
 }
@@ -161,37 +161,33 @@ gboolean screen_annex(void)
     XSetWindowAttributes attrib;
     pid_t pid;
     gint i, num_support;
-    Atom *prop_atoms_start, *wm_supported_pos;
     gulong *supported;
 
     /* create the netwm support window */
     attrib.override_redirect = TRUE;
     attrib.event_mask = PropertyChangeMask;
-    screen_support_win = XCreateWindow(ob_display,
-                                       RootWindow(ob_display, ob_screen),
+    screen_support_win = XCreateWindow(obt_display, obt_root(ob_screen),
                                        -100, -100, 1, 1, 0,
                                        CopyFromParent, InputOutput,
                                        CopyFromParent,
                                        CWEventMask | CWOverrideRedirect,
                                        &attrib);
-    XMapWindow(ob_display, screen_support_win);
-    XLowerWindow(ob_display, screen_support_win);
+    XMapWindow(obt_display, screen_support_win);
+    XLowerWindow(obt_display, screen_support_win);
 
     if (!replace_wm()) {
-        XDestroyWindow(ob_display, screen_support_win);
+        XDestroyWindow(obt_display, screen_support_win);
         return FALSE;
     }
 
-    xerror_set_ignore(TRUE);
-    xerror_occured = FALSE;
-    XSelectInput(ob_display, RootWindow(ob_display, ob_screen),
-                 ROOT_EVENTMASK);
-    xerror_set_ignore(FALSE);
-    if (xerror_occured) {
+    obt_display_ignore_errors(TRUE);
+    XSelectInput(obt_display, obt_root(ob_screen), ROOT_EVENTMASK);
+    obt_display_ignore_errors(FALSE);
+    if (obt_display_error_occured) {
         g_message(_("A window manager is already running on screen %d"),
                   ob_screen);
 
-        XDestroyWindow(ob_display, screen_support_win);
+        XDestroyWindow(obt_display, screen_support_win);
         return FALSE;
     }
 
@@ -199,123 +195,120 @@ gboolean screen_annex(void)
 
     /* set the OPENBOX_PID hint */
     pid = getpid();
-    PROP_SET32(RootWindow(ob_display, ob_screen),
-               openbox_pid, cardinal, pid);
+    OBT_PROP_SET32(obt_root(ob_screen), OPENBOX_PID, CARDINAL, pid);
 
     /* set supporting window */
-    PROP_SET32(RootWindow(ob_display, ob_screen),
-               net_supporting_wm_check, window, screen_support_win);
+    OBT_PROP_SET32(obt_root(ob_screen),
+                   NET_SUPPORTING_WM_CHECK, WINDOW, screen_support_win);
 
     /* set properties on the supporting window */
-    PROP_SETS(screen_support_win, net_wm_name, "Openbox");
-    PROP_SET32(screen_support_win, net_supporting_wm_check,
-               window, screen_support_win);
+    OBT_PROP_SETS(screen_support_win, NET_WM_NAME, utf8, "Openbox");
+    OBT_PROP_SET32(screen_support_win, NET_SUPPORTING_WM_CHECK,
+                   WINDOW, screen_support_win);
 
     /* set the _NET_SUPPORTED_ATOMS hint */
 
-    /* this is all the atoms after net_supported in the prop_atoms struct */
-    prop_atoms_start = (Atom*)&prop_atoms;
-    wm_supported_pos = (Atom*)&(prop_atoms.net_supported);
-    num_support = sizeof(prop_atoms) / sizeof(Atom) -
-        (wm_supported_pos - prop_atoms_start) - 1;
+    /* this is all the atoms after NET_SUPPORTED in the ObtPropAtoms enum */
+    num_support = OBT_PROP_NUM_ATOMS - OBT_PROP_NET_SUPPORTED - 1;
     i = 0;
     supported = g_new(gulong, num_support);
-    supported[i++] = prop_atoms.net_supporting_wm_check;
-    supported[i++] = prop_atoms.net_wm_full_placement;
-    supported[i++] = prop_atoms.net_current_desktop;
-    supported[i++] = prop_atoms.net_number_of_desktops;
-    supported[i++] = prop_atoms.net_desktop_geometry;
-    supported[i++] = prop_atoms.net_desktop_viewport;
-    supported[i++] = prop_atoms.net_active_window;
-    supported[i++] = prop_atoms.net_workarea;
-    supported[i++] = prop_atoms.net_client_list;
-    supported[i++] = prop_atoms.net_client_list_stacking;
-    supported[i++] = prop_atoms.net_desktop_names;
-    supported[i++] = prop_atoms.net_close_window;
-    supported[i++] = prop_atoms.net_desktop_layout;
-    supported[i++] = prop_atoms.net_showing_desktop;
-    supported[i++] = prop_atoms.net_wm_name;
-    supported[i++] = prop_atoms.net_wm_visible_name;
-    supported[i++] = prop_atoms.net_wm_icon_name;
-    supported[i++] = prop_atoms.net_wm_visible_icon_name;
-    supported[i++] = prop_atoms.net_wm_desktop;
-    supported[i++] = prop_atoms.net_wm_strut;
-    supported[i++] = prop_atoms.net_wm_strut_partial;
-    supported[i++] = prop_atoms.net_wm_icon;
-    supported[i++] = prop_atoms.net_wm_icon_geometry;
-    supported[i++] = prop_atoms.net_wm_window_type;
-    supported[i++] = prop_atoms.net_wm_window_type_desktop;
-    supported[i++] = prop_atoms.net_wm_window_type_dock;
-    supported[i++] = prop_atoms.net_wm_window_type_toolbar;
-    supported[i++] = prop_atoms.net_wm_window_type_menu;
-    supported[i++] = prop_atoms.net_wm_window_type_utility;
-    supported[i++] = prop_atoms.net_wm_window_type_splash;
-    supported[i++] = prop_atoms.net_wm_window_type_dialog;
-    supported[i++] = prop_atoms.net_wm_window_type_normal;
-    supported[i++] = prop_atoms.net_wm_allowed_actions;
-    supported[i++] = prop_atoms.net_wm_action_move;
-    supported[i++] = prop_atoms.net_wm_action_resize;
-    supported[i++] = prop_atoms.net_wm_action_minimize;
-    supported[i++] = prop_atoms.net_wm_action_shade;
-    supported[i++] = prop_atoms.net_wm_action_maximize_horz;
-    supported[i++] = prop_atoms.net_wm_action_maximize_vert;
-    supported[i++] = prop_atoms.net_wm_action_fullscreen;
-    supported[i++] = prop_atoms.net_wm_action_change_desktop;
-    supported[i++] = prop_atoms.net_wm_action_close;
-    supported[i++] = prop_atoms.net_wm_action_above;
-    supported[i++] = prop_atoms.net_wm_action_below;
-    supported[i++] = prop_atoms.net_wm_state;
-    supported[i++] = prop_atoms.net_wm_state_modal;
-    supported[i++] = prop_atoms.net_wm_state_maximized_vert;
-    supported[i++] = prop_atoms.net_wm_state_maximized_horz;
-    supported[i++] = prop_atoms.net_wm_state_shaded;
-    supported[i++] = prop_atoms.net_wm_state_skip_taskbar;
-    supported[i++] = prop_atoms.net_wm_state_skip_pager;
-    supported[i++] = prop_atoms.net_wm_state_hidden;
-    supported[i++] = prop_atoms.net_wm_state_fullscreen;
-    supported[i++] = prop_atoms.net_wm_state_above;
-    supported[i++] = prop_atoms.net_wm_state_below;
-    supported[i++] = prop_atoms.net_wm_state_demands_attention;
-    supported[i++] = prop_atoms.net_moveresize_window;
-    supported[i++] = prop_atoms.net_wm_moveresize;
-    supported[i++] = prop_atoms.net_wm_user_time;
+    supported[i++] = OBT_PROP_ATOM(NET_SUPPORTING_WM_CHECK);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_FULL_PLACEMENT);
+    supported[i++] = OBT_PROP_ATOM(NET_CURRENT_DESKTOP);
+    supported[i++] = OBT_PROP_ATOM(NET_NUMBER_OF_DESKTOPS);
+    supported[i++] = OBT_PROP_ATOM(NET_DESKTOP_GEOMETRY);
+    supported[i++] = OBT_PROP_ATOM(NET_DESKTOP_VIEWPORT);
+    supported[i++] = OBT_PROP_ATOM(NET_ACTIVE_WINDOW);
+    supported[i++] = OBT_PROP_ATOM(NET_WORKAREA);
+    supported[i++] = OBT_PROP_ATOM(NET_CLIENT_LIST);
+    supported[i++] = OBT_PROP_ATOM(NET_CLIENT_LIST_STACKING);
+    supported[i++] = OBT_PROP_ATOM(NET_DESKTOP_NAMES);
+    supported[i++] = OBT_PROP_ATOM(NET_CLOSE_WINDOW);
+    supported[i++] = OBT_PROP_ATOM(NET_DESKTOP_LAYOUT);
+    supported[i++] = OBT_PROP_ATOM(NET_SHOWING_DESKTOP);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_NAME);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_VISIBLE_NAME);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ICON_NAME);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_VISIBLE_ICON_NAME);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_DESKTOP);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STRUT);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STRUT_PARTIAL);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ICON);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ICON_GEOMETRY);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_TOOLBAR);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_UTILITY);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_SPLASH);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_NORMAL);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ALLOWED_ACTIONS);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_MOVE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_RESIZE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_MINIMIZE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_SHADE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_HORZ);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_MAXIMIZE_VERT);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_FULLSCREEN);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_CHANGE_DESKTOP);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_CLOSE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_ABOVE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_ACTION_BELOW);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_MODAL);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_VERT);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_MAXIMIZED_HORZ);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_SHADED);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_TASKBAR);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_SKIP_PAGER);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_HIDDEN);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_FULLSCREEN);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_ABOVE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_BELOW);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_STATE_DEMANDS_ATTENTION);
+    supported[i++] = OBT_PROP_ATOM(NET_MOVERESIZE_WINDOW);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_MOVERESIZE);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_USER_TIME);
 /*
-    supported[i++] = prop_atoms.net_wm_user_time_window;
+    supported[i++] = OBT_PROP_ATOM(NET_WM_USER_TIME_WINDOW);
 */
-    supported[i++] = prop_atoms.net_frame_extents;
-    supported[i++] = prop_atoms.net_request_frame_extents;
-    supported[i++] = prop_atoms.net_restack_window;
-    supported[i++] = prop_atoms.net_startup_id;
+    supported[i++] = OBT_PROP_ATOM(NET_FRAME_EXTENTS);
+    supported[i++] = OBT_PROP_ATOM(NET_REQUEST_FRAME_EXTENTS);
+    supported[i++] = OBT_PROP_ATOM(NET_RESTACK_WINDOW);
+    supported[i++] = OBT_PROP_ATOM(NET_STARTUP_ID);
 #ifdef SYNC
-    supported[i++] = prop_atoms.net_wm_sync_request;
-    supported[i++] = prop_atoms.net_wm_sync_request_counter;
+    supported[i++] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST_COUNTER);
 #endif
-    supported[i++] = prop_atoms.net_wm_pid;
-    supported[i++] = prop_atoms.net_wm_ping;
-
-    supported[i++] = prop_atoms.kde_wm_change_state;
-    supported[i++] = prop_atoms.kde_net_wm_frame_strut;
-    supported[i++] = prop_atoms.kde_net_wm_window_type_override;
-
-    supported[i++] = prop_atoms.ob_wm_action_undecorate;
-    supported[i++] = prop_atoms.ob_wm_state_undecorated;
-    supported[i++] = prop_atoms.openbox_pid;
-    supported[i++] = prop_atoms.ob_theme;
-    supported[i++] = prop_atoms.ob_config_file;
-    supported[i++] = prop_atoms.ob_control;
-    supported[i++] = prop_atoms.ob_version;
-    supported[i++] = prop_atoms.ob_app_role;
-    supported[i++] = prop_atoms.ob_app_name;
-    supported[i++] = prop_atoms.ob_app_class;
-    supported[i++] = prop_atoms.ob_app_type;
+    supported[i++] = OBT_PROP_ATOM(NET_WM_PID);
+    supported[i++] = OBT_PROP_ATOM(NET_WM_PING);
+
+    supported[i++] = OBT_PROP_ATOM(KDE_WM_CHANGE_STATE);
+    supported[i++] = OBT_PROP_ATOM(KDE_NET_WM_FRAME_STRUT);
+    supported[i++] = OBT_PROP_ATOM(KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
+
+    supported[i++] = OBT_PROP_ATOM(OB_WM_ACTION_UNDECORATE);
+    supported[i++] = OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED);
+    supported[i++] = OBT_PROP_ATOM(OPENBOX_PID);
+    supported[i++] = OBT_PROP_ATOM(OB_THEME);
+    supported[i++] = OBT_PROP_ATOM(OB_CONFIG_FILE);
+    supported[i++] = OBT_PROP_ATOM(OB_CONTROL);
+    supported[i++] = OBT_PROP_ATOM(OB_VERSION);
+    supported[i++] = OBT_PROP_ATOM(OB_APP_ROLE);
+    supported[i++] = OBT_PROP_ATOM(OB_APP_TITLE);
+    supported[i++] = OBT_PROP_ATOM(OB_APP_NAME);
+    supported[i++] = OBT_PROP_ATOM(OB_APP_CLASS);
+    supported[i++] = OBT_PROP_ATOM(OB_APP_TYPE);
     g_assert(i == num_support);
 
-    PROP_SETA32(RootWindow(ob_display, ob_screen),
-                net_supported, atom, supported, num_support);
+    OBT_PROP_SETA32(obt_root(ob_screen),
+                    NET_SUPPORTED, ATOM, supported, num_support);
     g_free(supported);
 
-    PROP_SETS(RootWindow(ob_display, ob_screen), ob_version,
-              OB_VERSION);
+    OBT_PROP_SETS(RootWindow(obt_display, ob_screen), OB_VERSION, utf8,
+                  OPENBOX_VERSION);
 
     screen_tell_ksplash();
 
@@ -346,14 +339,14 @@ static void screen_tell_ksplash(void)
        hear it anyways. perhaps it is for old ksplash. or new ksplash. or
        something. oh well. */
     e.xclient.type = ClientMessage;
-    e.xclient.display = ob_display;
-    e.xclient.window = RootWindow(ob_display, ob_screen);
+    e.xclient.display = obt_display;
+    e.xclient.window = obt_root(ob_screen);
     e.xclient.message_type =
-        XInternAtom(ob_display, "_KDE_SPLASH_PROGRESS", False);
+        XInternAtom(obt_display, "_KDE_SPLASH_PROGRESS", False);
     e.xclient.format = 8;
     strcpy(e.xclient.data.b, "wm started");
-    XSendEvent(ob_display, RootWindow(ob_display, ob_screen),
-               False, SubstructureNotifyMask, &e );
+    XSendEvent(obt_display, obt_root(ob_screen),
+               False, SubstructureNotifyMask, &e);
 }
 
 void screen_startup(gboolean reconfig)
@@ -363,6 +356,7 @@ void screen_startup(gboolean reconfig)
     gboolean namesexist = FALSE;
 
     desktop_popup = pager_popup_new();
+    desktop_popup_perm = FALSE;
     pager_popup_height(desktop_popup, POPUP_HEIGHT);
 
     if (reconfig) {
@@ -377,9 +371,7 @@ void screen_startup(gboolean reconfig)
     screen_resize();
 
     /* have names already been set for the desktops? */
-    if (PROP_GETSS(RootWindow(ob_display, ob_screen),
-                   net_desktop_names, utf8, &names))
-    {
+    if (OBT_PROP_GETSS(obt_root(ob_screen), NET_DESKTOP_NAMES, utf8, &names)) {
         g_strfreev(names);
         namesexist = TRUE;
     }
@@ -400,7 +392,8 @@ void screen_startup(gboolean reconfig)
             names[i] = g_strdup(it->data);
 
         /* set the root window property */
-        PROP_SETSS(RootWindow(ob_display, ob_screen), net_desktop_names,names);
+        OBT_PROP_SETSS(obt_root(ob_screen),
+                       NET_DESKTOP_NAMES, utf8, (const gchar**)names);
 
         g_strfreev(names);
     }
@@ -410,8 +403,8 @@ void screen_startup(gboolean reconfig)
        this will also set the default names from the config file up for
        desktops that don't have names yet */
     screen_num_desktops = 0;
-    if (PROP_GET32(RootWindow(ob_display, ob_screen),
-                   net_number_of_desktops, cardinal, &d))
+    if (OBT_PROP_GET32(obt_root(ob_screen),
+                       NET_NUMBER_OF_DESKTOPS, CARDINAL, &d))
     {
         if (d != config_desktops_num) {
             /* TRANSLATORS: If you need to specify a different order of the
@@ -431,8 +424,8 @@ void screen_startup(gboolean reconfig)
 
     screen_desktop = screen_num_desktops;  /* something invalid */
     /* start on the current desktop when a wm was already running */
-    if (PROP_GET32(RootWindow(ob_display, ob_screen),
-                   net_current_desktop, cardinal, &d) &&
+    if (OBT_PROP_GET32(obt_root(ob_screen),
+                       NET_CURRENT_DESKTOP, CARDINAL, &d) &&
         d < screen_num_desktops)
     {
         screen_set_desktop(d, FALSE);
@@ -446,8 +439,8 @@ void screen_startup(gboolean reconfig)
 
     /* don't start in showing-desktop mode */
     screen_showing_desktop = FALSE;
-    PROP_SET32(RootWindow(ob_display, ob_screen),
-               net_showing_desktop, cardinal, screen_showing_desktop);
+    OBT_PROP_SET32(obt_root(ob_screen),
+                   NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop);
 
     if (session_desktop_layout_present &&
         screen_validate_layout(&session_desktop_layout))
@@ -465,17 +458,16 @@ void screen_shutdown(gboolean reconfig)
     if (reconfig)
         return;
 
-    XSelectInput(ob_display, RootWindow(ob_display, ob_screen),
-                 NoEventMask);
+    XSelectInput(obt_display, obt_root(ob_screen), NoEventMask);
 
     /* we're not running here no more! */
-    PROP_ERASE(RootWindow(ob_display, ob_screen), openbox_pid);
+    OBT_PROP_ERASE(obt_root(ob_screen), OPENBOX_PID);
     /* not without us */
-    PROP_ERASE(RootWindow(ob_display, ob_screen), net_supported);
+    OBT_PROP_ERASE(obt_root(ob_screen), NET_SUPPORTED);
     /* don't keep this mode */
-    PROP_ERASE(RootWindow(ob_display, ob_screen), net_showing_desktop);
+    OBT_PROP_ERASE(obt_root(ob_screen), NET_SHOWING_DESKTOP);
 
-    XDestroyWindow(ob_display, screen_support_win);
+    XDestroyWindow(obt_display, screen_support_win);
 
     g_strfreev(screen_desktop_names);
     screen_desktop_names = NULL;
@@ -488,8 +480,8 @@ void screen_resize(void)
     GList *it;
     gulong geometry[2];
 
-    w = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
-    h = HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen));
+    w = WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen));
+    h = HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen));
 
     if (w == oldw && h == oldh) return;
 
@@ -498,8 +490,8 @@ void screen_resize(void)
     /* Set the _NET_DESKTOP_GEOMETRY hint */
     screen_physical_size.width = geometry[0] = w;
     screen_physical_size.height = geometry[1] = h;
-    PROP_SETA32(RootWindow(ob_display, ob_screen),
-                net_desktop_geometry, cardinal, geometry, 2);
+    OBT_PROP_SETA32(obt_root(ob_screen),
+                    NET_DESKTOP_GEOMETRY, CARDINAL, geometry, 2);
 
     if (ob_state() != OB_STATE_RUNNING)
         return;
@@ -513,7 +505,6 @@ void screen_resize(void)
 
 void screen_set_num_desktops(guint num)
 {
-    guint old;
     gulong *viewport;
     GList *it, *stacking_copy;
 
@@ -521,15 +512,13 @@ void screen_set_num_desktops(guint num)
 
     if (screen_num_desktops == num) return;
 
-    old = screen_num_desktops;
     screen_num_desktops = num;
-    PROP_SET32(RootWindow(ob_display, ob_screen),
-               net_number_of_desktops, cardinal, num);
+    OBT_PROP_SET32(obt_root(ob_screen), NET_NUMBER_OF_DESKTOPS, CARDINAL, num);
 
     /* set the viewport hint */
     viewport = g_new0(gulong, num * 2);
-    PROP_SETA32(RootWindow(ob_display, ob_screen),
-                net_desktop_viewport, cardinal, viewport, num * 2);
+    OBT_PROP_SETA32(obt_root(ob_screen),
+                    NET_DESKTOP_VIEWPORT, CARDINAL, viewport, num * 2);
     g_free(viewport);
 
     /* the number of rows/columns will differ */
@@ -625,8 +614,7 @@ void screen_set_desktop(guint num, gboolean dofocus)
 
     if (previous == num) return;
 
-    PROP_SET32(RootWindow(ob_display, ob_screen),
-               net_current_desktop, cardinal, num);
+    OBT_PROP_SET32(obt_root(ob_screen), NET_CURRENT_DESKTOP, CARDINAL, num);
 
     /* This whole thing decides when/how to save the screen_last_desktop so
        that it can be restored later if you want */
@@ -692,14 +680,14 @@ void screen_set_desktop(guint num, gboolean dofocus)
         }
     }
     screen_desktop_timeout = FALSE;
-    ob_main_loop_timeout_remove(ob_main_loop, last_desktop_func);
-    ob_main_loop_timeout_add(ob_main_loop, REMEMBER_LAST_DESKTOP_TIME,
-                             last_desktop_func, NULL, NULL, NULL);
+    obt_main_loop_timeout_remove(ob_main_loop, last_desktop_func);
+    obt_main_loop_timeout_add(ob_main_loop, REMEMBER_LAST_DESKTOP_TIME,
+                              last_desktop_func, NULL, NULL, NULL);
 
-    ob_debug("Moving to desktop %d\n", num+1);
+    ob_debug("Moving to desktop %d", num+1);
 
     if (ob_state() == OB_STATE_RUNNING)
-        screen_show_desktop_popup(screen_desktop);
+        screen_show_desktop_popup(screen_desktop, FALSE);
 
     /* ignore enter events caused by the move */
     ignore_start = event_start_ignore_all_enters();
@@ -767,7 +755,7 @@ void screen_add_desktop(gboolean current)
                    parent - which will have to be on the same desktop */
                 !client_direct_parent(c))
             {
-                ob_debug("moving window %s\n", c->title);
+                ob_debug("moving window %s", c->title);
                 client_set_desktop(c, c->desktop+1, FALSE, TRUE);
             }
         }
@@ -808,7 +796,7 @@ void screen_remove_desktop(gboolean current)
                    parent - which will have to be on the same desktop */
                 !client_direct_parent(c))
             {
-                ob_debug("moving window %s\n", c->title);
+                ob_debug("moving window %s", c->title);
                 client_set_desktop(c, c->desktop - 1, TRUE, TRUE);
             }
             /* raise all the windows that are on the current desktop which
@@ -818,7 +806,7 @@ void screen_remove_desktop(gboolean current)
                 (d == DESKTOP_ALL || d == screen_desktop))
             {
                 stacking_raise(CLIENT_AS_WINDOW(c));
-                ob_debug("raising window %s\n", c->title);
+                ob_debug("raising window %s", c->title);
             }
         }
     }
@@ -827,7 +815,7 @@ void screen_remove_desktop(gboolean current)
     /* fallback focus like we're changing desktops */
     if (screen_desktop < screen_num_desktops - 1) {
         screen_fallback_focus();
-        ob_debug("fake desktop change\n");
+        ob_debug("fake desktop change");
     }
 
     screen_set_num_desktops(screen_num_desktops-1);
@@ -949,7 +937,7 @@ static gboolean hide_desktop_popup_func(gpointer data)
     return FALSE; /* don't repeat */
 }
 
-void screen_show_desktop_popup(guint d)
+void screen_show_desktop_popup(guint d, gboolean perm)
 {
     Rect *a;
 
@@ -968,16 +956,25 @@ void screen_show_desktop_popup(guint d)
                           MAX(a->width/3, POPUP_WIDTH));
     pager_popup_show(desktop_popup, screen_desktop_names[d], d);
 
-    ob_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
-    ob_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000,
-                             hide_desktop_popup_func, NULL, NULL, NULL);
+    obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
+    if (!perm && !desktop_popup_perm)
+        /* only hide if its not already being show permanently */
+        obt_main_loop_timeout_add(ob_main_loop,
+                                  config_desktop_popup_time * 1000,
+                                  hide_desktop_popup_func, desktop_popup,
+                                  g_direct_equal, NULL);
+    if (perm)
+        desktop_popup_perm = TRUE;
+
     g_free(a);
 }
 
 void screen_hide_desktop_popup(void)
 {
-    ob_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
+    obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func,
+                                      desktop_popup, FALSE);
     pager_popup_hide(desktop_popup);
+    desktop_popup_perm = FALSE;
 }
 
 guint screen_find_desktop(guint from, ObDirection dir,
@@ -1135,13 +1132,13 @@ void screen_update_layout(void)
     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 (OBT_PROP_GETA32(obt_root(ob_screen),
+                        NET_DESKTOP_LAYOUT, CARDINAL, &data, &num)) {
         if (num == 3 || num == 4) {
 
-            if (data[0] == prop_atoms.net_wm_orientation_vert)
+            if (data[0] == OBT_PROP_ATOM(NET_WM_ORIENTATION_VERT))
                 l.orientation = OB_ORIENTATION_VERT;
-            else if (data[0] == prop_atoms.net_wm_orientation_horz)
+            else if (data[0] == OBT_PROP_ATOM(NET_WM_ORIENTATION_HORZ))
                 l.orientation = OB_ORIENTATION_HORZ;
             else
                 return;
@@ -1149,13 +1146,13 @@ void screen_update_layout(void)
             if (num < 4)
                 l.start_corner = OB_CORNER_TOPLEFT;
             else {
-                if (data[3] == prop_atoms.net_wm_topleft)
+                if (data[3] == OBT_PROP_ATOM(NET_WM_TOPLEFT))
                     l.start_corner = OB_CORNER_TOPLEFT;
-                else if (data[3] == prop_atoms.net_wm_topright)
+                else if (data[3] == OBT_PROP_ATOM(NET_WM_TOPRIGHT))
                     l.start_corner = OB_CORNER_TOPRIGHT;
-                else if (data[3] == prop_atoms.net_wm_bottomright)
+                else if (data[3] == OBT_PROP_ATOM(NET_WM_BOTTOMRIGHT))
                     l.start_corner = OB_CORNER_BOTTOMRIGHT;
-                else if (data[3] == prop_atoms.net_wm_bottomleft)
+                else if (data[3] == OBT_PROP_ATOM(NET_WM_BOTTOMLEFT))
                     l.start_corner = OB_CORNER_BOTTOMLEFT;
                 else
                     return;
@@ -1180,8 +1177,8 @@ void screen_update_desktop_names(void)
     g_strfreev(screen_desktop_names);
     screen_desktop_names = NULL;
 
-    if (PROP_GETSS(RootWindow(ob_display, ob_screen),
-                   net_desktop_names, utf8, &screen_desktop_names))
+    if (OBT_PROP_GETSS(obt_root(ob_screen),
+                       NET_DESKTOP_NAMES, utf8, &screen_desktop_names))
         for (i = 0; screen_desktop_names[i] && i < screen_num_desktops; ++i);
     else
         i = 0;
@@ -1207,8 +1204,8 @@ void screen_update_desktop_names(void)
 
         /* 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);
+        OBT_PROP_SETSS(obt_root(ob_screen), NET_DESKTOP_NAMES,
+                       utf8, (const gchar**)screen_desktop_names);
     }
 
     /* resize the pager for these names */
@@ -1275,24 +1272,23 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
     }
 
     show = !!show; /* make it boolean */
-    PROP_SET32(RootWindow(ob_display, ob_screen),
-               net_showing_desktop, cardinal, show);
+    OBT_PROP_SET32(obt_root(ob_screen), NET_SHOWING_DESKTOP, CARDINAL, show);
 }
 
 void screen_install_colormap(ObClient *client, gboolean install)
 {
     if (client == NULL || client->colormap == None) {
         if (install)
-            XInstallColormap(RrDisplay(ob_rr_inst), RrColormap(ob_rr_inst));
+            XInstallColormap(obt_display, RrColormap(ob_rr_inst));
         else
-            XUninstallColormap(RrDisplay(ob_rr_inst), RrColormap(ob_rr_inst));
+            XUninstallColormap(obt_display, RrColormap(ob_rr_inst));
     } else {
-        xerror_set_ignore(TRUE);
+        obt_display_ignore_errors(TRUE);
         if (install)
-            XInstallColormap(RrDisplay(ob_rr_inst), client->colormap);
+            XInstallColormap(obt_display, client->colormap);
         else
-            XUninstallColormap(RrDisplay(ob_rr_inst), client->colormap);
-        xerror_set_ignore(FALSE);
+            XUninstallColormap(obt_display, client->colormap);
+        obt_display_ignore_errors(FALSE);
     }
 }
 
@@ -1321,6 +1317,55 @@ typedef struct {
     } \
 }
 
+static void get_xinerama_screens(Rect **xin_areas, guint *nxin)
+{
+    guint i;
+    gint n, l, r, t, b;
+#ifdef XINERAMA
+    XineramaScreenInfo *info;
+#endif
+
+    if (ob_debug_xinerama) {
+        gint w = WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen));
+        gint h = HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen));
+        *nxin = 2;
+        *xin_areas = g_new(Rect, *nxin + 1);
+        RECT_SET((*xin_areas)[0], 0, 0, w/2, h);
+        RECT_SET((*xin_areas)[1], w/2, 0, w-(w/2), h);
+    }
+#ifdef XINERAMA
+    else if (obt_display_extension_xinerama &&
+             (info = XineramaQueryScreens(obt_display, &n))) {
+        *nxin = n;
+        *xin_areas = g_new(Rect, *nxin + 1);
+        for (i = 0; i < *nxin; ++i)
+            RECT_SET((*xin_areas)[i], info[i].x_org, info[i].y_org,
+                     info[i].width, info[i].height);
+        XFree(info);
+    }
+#endif
+    else {
+        *nxin = 1;
+        *xin_areas = g_new(Rect, *nxin + 1);
+        RECT_SET((*xin_areas)[0], 0, 0,
+                 WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen)),
+                 HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen)));
+    }
+
+    /* returns one extra with the total area in it */
+    l = (*xin_areas)[0].x;
+    t = (*xin_areas)[0].y;
+    r = (*xin_areas)[0].x + (*xin_areas)[0].width - 1;
+    b = (*xin_areas)[0].y + (*xin_areas)[0].height - 1;
+    for (i = 1; i < *nxin; ++i) {
+        l = MIN(l, (*xin_areas)[i].x);
+        t = MIN(l, (*xin_areas)[i].y);
+        r = MAX(r, (*xin_areas)[i].x + (*xin_areas)[i].width - 1);
+        b = MAX(b, (*xin_areas)[i].y + (*xin_areas)[i].height - 1);
+    }
+    RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1);
+}
+
 void screen_update_areas(void)
 {
     guint i;
@@ -1328,7 +1373,7 @@ void screen_update_areas(void)
     GList *it;
 
     g_free(monitor_area);
-    extensions_xinerama_screens(&monitor_area, &screen_num_monitors);
+    get_xinerama_screens(&monitor_area, &screen_num_monitors);
 
     /* set up the user-specified margins */
     config_margins.top_start = RECT_LEFT(monitor_area[screen_num_monitors]);
@@ -1395,8 +1440,8 @@ void screen_update_areas(void)
     }
 
     /* set the legacy workarea hint to the union of all the monitors */
-    PROP_SETA32(RootWindow(ob_display, ob_screen), net_workarea, cardinal,
-                dims, 4 * screen_num_desktops);
+    OBT_PROP_SETA32(obt_root(ob_screen), NET_WORKAREA, CARDINAL,
+                    dims, 4 * screen_num_desktops);
 
     /* the area has changed, adjust all the windows if they need it */
     for (it = client_list; it; it = g_list_next(it))
@@ -1462,7 +1507,7 @@ Rect* screen_area(guint desktop, guint head, Rect *search)
 {
     Rect *a;
     GSList *it;
-    gint l, r, t, b, al, ar, at, ab;
+    gint l, r, t, b;
     guint i, d;
     gboolean us = search != NULL; /* user provided search */
 
@@ -1488,30 +1533,30 @@ Rect* screen_area(guint desktop, guint head, Rect *search)
 
     /* only include monitors which the search area lines up with */
     if (RECT_INTERSECTS_RECT(monitor_area[screen_num_monitors], *search)) {
-        al = l = RECT_RIGHT(monitor_area[screen_num_monitors]);
-        at = t = RECT_BOTTOM(monitor_area[screen_num_monitors]);
-        ar = r = RECT_LEFT(monitor_area[screen_num_monitors]);
-        ab = b = RECT_TOP(monitor_area[screen_num_monitors]);
+        l = RECT_RIGHT(monitor_area[screen_num_monitors]);
+        t = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+        r = RECT_LEFT(monitor_area[screen_num_monitors]);
+        b = RECT_TOP(monitor_area[screen_num_monitors]);
         for (i = 0; i < screen_num_monitors; ++i) {
             /* add the monitor if applicable */
             if (RANGES_INTERSECT(search->x, search->width,
                                  monitor_area[i].x, monitor_area[i].width))
             {
-                at = t = MIN(t, RECT_TOP(monitor_area[i]));
-                ab = b = MAX(b, RECT_BOTTOM(monitor_area[i]));
+                t = MIN(t, RECT_TOP(monitor_area[i]));
+                b = MAX(b, RECT_BOTTOM(monitor_area[i]));
             }
             if (RANGES_INTERSECT(search->y, search->height,
                                  monitor_area[i].y, monitor_area[i].height))
             {
-                al = l = MIN(l, RECT_LEFT(monitor_area[i]));
-                ar = r = MAX(r, RECT_RIGHT(monitor_area[i]));
+                l = MIN(l, RECT_LEFT(monitor_area[i]));
+                r = MAX(r, RECT_RIGHT(monitor_area[i]));
             }
         }
     } else {
-        al = l = RECT_LEFT(monitor_area[screen_num_monitors]);
-        at = t = RECT_TOP(monitor_area[screen_num_monitors]);
-        ar = r = RECT_RIGHT(monitor_area[screen_num_monitors]);
-        ab = b = RECT_BOTTOM(monitor_area[screen_num_monitors]);
+        l = RECT_LEFT(monitor_area[screen_num_monitors]);
+        t = RECT_TOP(monitor_area[screen_num_monitors]);
+        r = RECT_RIGHT(monitor_area[screen_num_monitors]);
+        b = RECT_BOTTOM(monitor_area[screen_num_monitors]);
     }
 
     for (d = 0; d < screen_num_desktops; ++d) {
@@ -1657,10 +1702,10 @@ Rect *screen_physical_area_primary(gboolean fixed)
 void screen_set_root_cursor(void)
 {
     if (sn_app_starting())
-        XDefineCursor(ob_display, RootWindow(ob_display, ob_screen),
+        XDefineCursor(obt_display, obt_root(ob_screen),
                       ob_cursor(OB_CURSOR_BUSYPOINTER));
     else
-        XDefineCursor(ob_display, RootWindow(ob_display, ob_screen),
+        XDefineCursor(obt_display, obt_root(ob_screen),
                       ob_cursor(OB_CURSOR_POINTER));
 }
 
@@ -1686,12 +1731,12 @@ gboolean screen_pointer_pos(gint *x, gint *y)
     guint u;
     gboolean ret;
 
-    ret = !!XQueryPointer(ob_display, RootWindow(ob_display, ob_screen),
+    ret = !!XQueryPointer(obt_display, obt_root(ob_screen),
                           &w, &w, x, y, &i, &i, &u);
     if (!ret) {
-        for (i = 0; i < ScreenCount(ob_display); ++i)
+        for (i = 0; i < ScreenCount(obt_display); ++i)
             if (i != ob_screen)
-                if (XQueryPointer(ob_display, RootWindow(ob_display, i),
+                if (XQueryPointer(obt_display, obt_root(i),
                                   &w, &w, x, y, &i, &i, &u))
                     break;
     }
index 1690330..9408539 100644 (file)
@@ -53,7 +53,7 @@ extern ObDesktopLayout screen_desktop_layout;
 extern gchar **screen_desktop_names;
 
 /*! Take over the screen, set the basic hints on it claming it as ours */
-gboolean screen_annex();
+gboolean screen_annex(void);
 
 /*! Once the screen is ours, set up its initial state */
 void screen_startup(gboolean reconfig);
@@ -61,7 +61,7 @@ void screen_startup(gboolean reconfig);
 void screen_shutdown(gboolean reconfig);
 
 /*! Figure out the new size of the screen and adjust stuff for it */
-void screen_resize();
+void screen_resize(void);
 
 /*! Change the number of available desktops */
 void screen_set_num_desktops(guint num);
@@ -75,10 +75,14 @@ void screen_remove_desktop(gboolean current);
 guint screen_find_desktop(guint from, ObDirection dir,
                           gboolean wrap, gboolean linear);
 
-/*! Show the desktop popup/notification */
-void screen_show_desktop_popup(guint d);
+/*! Show the desktop popup/notification
+  @permanent If TRUE, the popup will stay on the screen until you call
+             screen_hide_desktop_popup().  Otherwise it will hide after a
+             delay.
+ */
+void screen_show_desktop_popup(guint d, gboolean permanent);
 /*! Hide it */
-void screen_hide_desktop_popup();
+void screen_hide_desktop_popup(void);
 
 /*! Shows and focuses the desktop and hides all the client windows, or
   returns to the normal state, showing client windows.
@@ -89,18 +93,18 @@ void screen_hide_desktop_popup();
 void screen_show_desktop(gboolean show, struct _ObClient *show_only);
 
 /*! Updates the desktop layout from the root property if available */
-void screen_update_layout();
+void screen_update_layout(void);
 
 /*! Get desktop names from the root window property */
-void screen_update_desktop_names();
+void screen_update_desktop_names(void);
 
 /*! Installs or uninstalls a colormap for a client. If client is NULL, then
   it handles the root colormap. */
 void screen_install_colormap(struct _ObClient *client, gboolean install);
 
-void screen_update_areas();
+void screen_update_areas(void);
 
-Rect *screen_physical_area_all_monitors();
+Rect *screen_physical_area_all_monitors(void);
 
 Rect *screen_physical_area_monitor(guint head);
 
@@ -147,7 +151,7 @@ guint screen_find_monitor_point(guint x, guint y);
 
 /*! Sets the root cursor. This function decides which cursor to use, but you
   gotta call it to let it know it should change. */
-void screen_set_root_cursor();
+void screen_set_root_cursor(void);
 
 /*! Gives back the pointer's position in x and y. Returns TRUE if the pointer
   is on this screen and FALSE if it is on another screen. */
index 1401847..ba51ed3 100644 (file)
@@ -40,10 +40,10 @@ gboolean session_connected(void) { return FALSE; }
 #include "debug.h"
 #include "openbox.h"
 #include "client.h"
-#include "prop.h"
 #include "focus.h"
 #include "gettext.h"
-#include "parser/parse.h"
+#include "obt/xml.h"
+#include "obt/paths.h"
 
 #include <time.h>
 #include <errno.h>
@@ -93,22 +93,26 @@ static void session_state_free(ObSessionState *state);
 void session_startup(gint argc, gchar **argv)
 {
     gchar *dir;
+    ObtPaths *p;
 
     if (!ob_sm_use) return;
 
     sm_argc = argc;
     sm_argv = argv;
 
-    dir = g_build_filename(parse_xdg_data_home_path(),
+    p = obt_paths_new();
+    dir = g_build_filename(obt_paths_cache_home(p),
                            "openbox", "sessions", NULL);
-    if (!parse_mkdir_path(dir, 0700)) {
+    obt_paths_unref(p), p = NULL;
+
+    if (!obt_paths_mkdir_path(dir, 0700)) {
         g_message(_("Unable to make directory \"%s\": %s"),
                   dir, g_strerror(errno));
     }
 
     if (ob_sm_save_file != NULL) {
         if (ob_sm_restore) {
-            ob_debug_type(OB_DEBUG_SM, "Loading from session file %s\n",
+            ob_debug_type(OB_DEBUG_SM, "Loading from session file %s",
                           ob_sm_save_file);
             session_load_file(ob_sm_save_file);
         }
@@ -162,7 +166,7 @@ gboolean session_connected(void)
 }
 
 /*! Connect to the session manager and set up our callback functions */
-static gboolean session_connect()
+static gboolean session_connect(void)
 {
     SmcCallbacks cb;
     gchar *oldid;
@@ -180,7 +184,7 @@ static gboolean session_connect()
 
     /* connect to the server */
     oldid = ob_sm_id;
-    ob_debug_type(OB_DEBUG_SM, "Connecting to SM with id: %s\n",
+    ob_debug_type(OB_DEBUG_SM, "Connecting to SM with id: %s",
                   oldid ? oldid : "(null)");
     sm_conn = SmcOpenConnection(NULL, NULL, 1, 0,
                                 SmcSaveYourselfProcMask |
@@ -190,13 +194,13 @@ static gboolean session_connect()
                                 &cb, oldid, &ob_sm_id,
                                 SM_ERR_LEN-1, sm_err);
     g_free(oldid);
-    ob_debug_type(OB_DEBUG_SM, "Connected to SM with id: %s\n", ob_sm_id);
+    ob_debug_type(OB_DEBUG_SM, "Connected to SM with id: %s", ob_sm_id);
     if (sm_conn == NULL)
-        ob_debug("Failed to connect to session manager: %s\n", sm_err);
+        ob_debug("Failed to connect to session manager: %s", sm_err);
     return sm_conn != NULL;
 }
 
-static void session_setup_program()
+static void session_setup_program(void)
 {
     SmPropValue vals = {
         .value = sm_argv[0],
@@ -209,13 +213,13 @@ static void session_setup_program()
         .vals = &vals
     };
     SmProp *list = &prop;
-    ob_debug_type(OB_DEBUG_SM, "Setting program: %s\n", sm_argv[0]);
+    ob_debug_type(OB_DEBUG_SM, "Setting program: %s", sm_argv[0]);
     SmcSetProperties(sm_conn, 1, &list);
     g_free(prop.name);
     g_free(prop.type);
 }
 
-static void session_setup_user()
+static void session_setup_user(void)
 {
     char *user = g_strdup(g_get_user_name());
 
@@ -230,7 +234,7 @@ static void session_setup_user()
         .vals = &vals
     };
     SmProp *list = &prop;
-    ob_debug_type(OB_DEBUG_SM, "Setting user: %s\n", user);
+    ob_debug_type(OB_DEBUG_SM, "Setting user: %s", user);
     SmcSetProperties(sm_conn, 1, &list);
     g_free(prop.name);
     g_free(prop.type);
@@ -252,13 +256,13 @@ static void session_setup_restart_style(gboolean restart)
         .vals = &vals
     };
     SmProp *list = &prop;
-    ob_debug_type(OB_DEBUG_SM, "Setting restart: %d\n", restart);
+    ob_debug_type(OB_DEBUG_SM, "Setting restart: %d", restart);
     SmcSetProperties(sm_conn, 1, &list);
     g_free(prop.name);
     g_free(prop.type);
 }
 
-static void session_setup_pid()
+static void session_setup_pid(void)
 {
     gchar *pid = g_strdup_printf("%ld", (glong) getpid());
 
@@ -273,7 +277,7 @@ static void session_setup_pid()
         .vals = &vals
     };
     SmProp *list = &prop;
-    ob_debug_type(OB_DEBUG_SM, "Setting pid: %s\n", pid);
+    ob_debug_type(OB_DEBUG_SM, "Setting pid: %s", pid);
     SmcSetProperties(sm_conn, 1, &list);
     g_free(prop.name);
     g_free(prop.type);
@@ -281,7 +285,7 @@ static void session_setup_pid()
 }
 
 /*! This is a gnome-session-manager extension */
-static void session_setup_priority()
+static void session_setup_priority(void)
 {
     gchar priority = 20; /* 20 is a lower prioity to run before other apps */
 
@@ -296,13 +300,13 @@ static void session_setup_priority()
         .vals = &vals
     };
     SmProp *list = &prop;
-    ob_debug_type(OB_DEBUG_SM, "Setting priority: %d\n", priority);
+    ob_debug_type(OB_DEBUG_SM, "Setting priority: %d", priority);
     SmcSetProperties(sm_conn, 1, &list);
     g_free(prop.name);
     g_free(prop.type);
 }
 
-static void session_setup_clone_command()
+static void session_setup_clone_command(void)
 {
     gint i;
 
@@ -315,11 +319,11 @@ static void session_setup_clone_command()
     };
     SmProp *list = &prop;
 
-    ob_debug_type(OB_DEBUG_SM, "Setting clone command: (%d)\n", sm_argc);
+    ob_debug_type(OB_DEBUG_SM, "Setting clone command: (%d)", sm_argc);
     for (i = 0; i < sm_argc; ++i) {
         vals[i].value = sm_argv[i];
         vals[i].length = strlen(sm_argv[i]) + 1;
-        ob_debug_type(OB_DEBUG_SM, "    %s\n", vals[i].value);
+        ob_debug_type(OB_DEBUG_SM, "    %s", vals[i].value);
     }
 
     SmcSetProperties(sm_conn, 1, &list);
@@ -328,7 +332,7 @@ static void session_setup_clone_command()
     g_free(vals);
 }
 
-static void session_setup_restart_command()
+static void session_setup_restart_command(void)
 {
     gint i;
 
@@ -341,26 +345,26 @@ static void session_setup_restart_command()
     };
     SmProp *list = &prop;
 
-    ob_debug_type(OB_DEBUG_SM, "Setting restart command: (%d)\n", sm_argc+4);
+    ob_debug_type(OB_DEBUG_SM, "Setting restart command: (%d)", sm_argc+4);
     for (i = 0; i < sm_argc; ++i) {
         vals[i].value = sm_argv[i];
         vals[i].length = strlen(sm_argv[i]) + 1;
-        ob_debug_type(OB_DEBUG_SM, "    %s\n", vals[i].value);
+        ob_debug_type(OB_DEBUG_SM, "    %s", vals[i].value);
     }
 
     vals[i].value = g_strdup("--sm-client-id");
     vals[i].length = strlen("--sm-client-id") + 1;
     vals[i+1].value = ob_sm_id;
     vals[i+1].length = strlen(ob_sm_id) + 1;
-    ob_debug_type(OB_DEBUG_SM, "    %s\n", vals[i].value);
-    ob_debug_type(OB_DEBUG_SM, "    %s\n", vals[i+1].value);
+    ob_debug_type(OB_DEBUG_SM, "    %s", vals[i].value);
+    ob_debug_type(OB_DEBUG_SM, "    %s", vals[i+1].value);
 
     vals[i+2].value = g_strdup("--sm-save-file");
     vals[i+2].length = strlen("--sm-save-file") + 1;
     vals[i+3].value = ob_sm_save_file;
     vals[i+3].length = strlen(ob_sm_save_file) + 1;
-    ob_debug_type(OB_DEBUG_SM, "    %s\n", vals[i+2].value);
-    ob_debug_type(OB_DEBUG_SM, "    %s\n", vals[i+3].value);
+    ob_debug_type(OB_DEBUG_SM, "    %s", vals[i+2].value);
+    ob_debug_type(OB_DEBUG_SM, "    %s", vals[i+3].value);
 
     SmcSetProperties(sm_conn, 1, &list);
     g_free(prop.name);
@@ -370,7 +374,7 @@ static void session_setup_restart_command()
     g_free(vals);
 }
 
-static ObSMSaveData *sm_save_get_data()
+static ObSMSaveData *sm_save_get_data(void)
 {
     ObSMSaveData *savedata = g_new0(ObSMSaveData, 1);
     /* save the active desktop and client.
@@ -388,9 +392,9 @@ static void sm_save_yourself_2(SmcConn conn, SmPointer data)
     ObSMSaveData *savedata = data;
 
     /* save the current state */
-    ob_debug_type(OB_DEBUG_SM, "Session save phase 2 requested\n");
+    ob_debug_type(OB_DEBUG_SM, "Session save phase 2 requested");
     ob_debug_type(OB_DEBUG_SM,
-                  "  Saving session to file '%s'\n", ob_sm_save_file);
+                  "  Saving session to file '%s'", ob_sm_save_file);
     if (savedata == NULL)
         savedata = sm_save_get_data();
     success = session_save_to_file(savedata);
@@ -399,7 +403,7 @@ static void sm_save_yourself_2(SmcConn conn, SmPointer data)
     /* tell the session manager how to restore this state */
     if (success) session_setup_restart_command();
 
-    ob_debug_type(OB_DEBUG_SM, "Saving is done (success = %d)\n", success);
+    ob_debug_type(OB_DEBUG_SM, "Saving is done (success = %d)", success);
     SmcSaveYourselfDone(conn, success);
 }
 
@@ -415,7 +419,7 @@ static void sm_save_yourself(SmcConn conn, SmPointer data, gint save_type,
             (save_type == SmSaveLocal ? "SmSaveLocal" :
              (save_type == SmSaveGlobal ? "SmSaveGlobal" :
               (save_type == SmSaveBoth ? "SmSaveBoth" : "INVALID!!")));
-        ob_debug_type(OB_DEBUG_SM, "Session save requested, type %s\n", sname);
+        ob_debug_type(OB_DEBUG_SM, "Session save requested, type %s", sname);
     }
 #endif
 
@@ -427,7 +431,7 @@ static void sm_save_yourself(SmcConn conn, SmPointer data, gint save_type,
     }
 
     vendor = SmcVendor(sm_conn);
-    ob_debug_type(OB_DEBUG_SM, "Session manager's vendor: %s\n", vendor);
+    ob_debug_type(OB_DEBUG_SM, "Session manager's vendor: %s", vendor);
 
     if (!strcmp(vendor, "KDE")) {
         /* ksmserver guarantees that phase 1 will complete before allowing any
@@ -438,7 +442,7 @@ static void sm_save_yourself(SmcConn conn, SmPointer data, gint save_type,
     free(vendor);
 
     if (!SmcRequestSaveYourselfPhase2(conn, sm_save_yourself_2, savedata)) {
-        ob_debug_type(OB_DEBUG_SM, "Requst for phase 2 failed\n");
+        ob_debug_type(OB_DEBUG_SM, "Requst for phase 2 failed");
         g_free(savedata);
         SmcSaveYourselfDone(conn, FALSE);
     }
@@ -446,18 +450,18 @@ static void sm_save_yourself(SmcConn conn, SmPointer data, gint save_type,
 
 static void sm_die(SmcConn conn, SmPointer data)
 {
-    ob_debug_type(OB_DEBUG_SM, "Die requested\n");
+    ob_debug_type(OB_DEBUG_SM, "Die requested");
     ob_exit(0);
 }
 
 static void sm_save_complete(SmcConn conn, SmPointer data)
 {
-    ob_debug_type(OB_DEBUG_SM, "Save complete\n");
+    ob_debug_type(OB_DEBUG_SM, "Save complete");
 }
 
 static void sm_shutdown_cancelled(SmcConn conn, SmPointer data)
 {
-    ob_debug_type(OB_DEBUG_SM, "Shutdown cancelled\n");
+    ob_debug_type(OB_DEBUG_SM, "Shutdown cancelled");
 }
 
 static gboolean session_save_to_file(const ObSMSaveData *savedata)
@@ -519,18 +523,18 @@ static gboolean session_save_to_file(const ObSMSaveData *savedata)
 
             if (!c->sm_client_id) {
                 ob_debug_type(OB_DEBUG_SM, "Client %s does not have a "
-                              "session id set\n",
+                              "session id set",
                               c->title);
                 if (!c->wm_command) {
                     ob_debug_type(OB_DEBUG_SM, "Client %s does not have an "
                                   "oldskool wm_command set either. We won't "
-                                  "be saving its data\n",
+                                  "be saving its data",
                                   c->title);
                     continue;
                 }
             }
 
-            ob_debug_type(OB_DEBUG_SM, "Saving state for client %s\n",
+            ob_debug_type(OB_DEBUG_SM, "Saving state for client %s",
                           c->title);
 
             prex = c->area.x;
@@ -632,20 +636,20 @@ static void session_state_free(ObSessionState *state)
 
 static gboolean session_state_cmp(ObSessionState *s, ObClient *c)
 {
-    ob_debug_type(OB_DEBUG_SM, "Comparing client against saved state: \n");
-    ob_debug_type(OB_DEBUG_SM, "  client id: %s \n", c->sm_client_id);
-    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: %d \n", c->type);
-    ob_debug_type(OB_DEBUG_SM, "  client command: %s \n",
+    ob_debug_type(OB_DEBUG_SM, "Comparing client against saved state: ");
+    ob_debug_type(OB_DEBUG_SM, "  client id: %s ", c->sm_client_id);
+    ob_debug_type(OB_DEBUG_SM, "  client name: %s ", c->name);
+    ob_debug_type(OB_DEBUG_SM, "  client class: %s ", c->class);
+    ob_debug_type(OB_DEBUG_SM, "  client role: %s ", c->role);
+    ob_debug_type(OB_DEBUG_SM, "  client type: %d ", c->type);
+    ob_debug_type(OB_DEBUG_SM, "  client command: %s ",
                   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: %d \n", s->type);
-    ob_debug_type(OB_DEBUG_SM, "  state command: %s \n",
+    ob_debug_type(OB_DEBUG_SM, "  state id: %s ", s->id);
+    ob_debug_type(OB_DEBUG_SM, "  state name: %s ", s->name);
+    ob_debug_type(OB_DEBUG_SM, "  state class: %s ", s->class);
+    ob_debug_type(OB_DEBUG_SM, "  state role: %s ", s->role);
+    ob_debug_type(OB_DEBUG_SM, "  state type: %d ", s->type);
+    ob_debug_type(OB_DEBUG_SM, "  state command: %s ",
                   s->command ? s->command : "(null)");
 
     if ((c->sm_client_id && s->id && !strcmp(c->sm_client_id, s->id)) ||
@@ -680,108 +684,117 @@ GList* session_state_find(ObClient *c)
 
 static void session_load_file(const gchar *path)
 {
-    xmlDocPtr doc;
+    ObtXmlInst *i;
     xmlNodePtr node, n, m;
     GList *it, *inext;
 
-    if (!parse_load(path, "openbox_session", &doc, &node))
+    i = obt_xml_instance_new();
+
+    if (!obt_xml_load_file(i, path, "openbox_session")) {
+        ob_debug_type(OB_DEBUG_SM, "ERROR: session file is missing root node");
+        obt_xml_instance_unref(i);
         return;
+    }
+    node = obt_xml_root(i);
 
-    if ((n = parse_find_node("desktop", node->children)))
-        session_desktop = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node->children, "desktop")))
+        session_desktop = obt_xml_node_int(n);
 
-    if ((n = parse_find_node("numdesktops", node->children)))
-        session_num_desktops = parse_int(doc, n);
+    if ((n = obt_xml_find_node(node->children, "numdesktops")))
+        session_num_desktops = obt_xml_node_int(n);
 
-    if ((n = parse_find_node("desktoplayout", node->children))) {
+    if ((n = obt_xml_find_node(node->children, "desktoplayout"))) {
         /* 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);
+        if ((m = obt_xml_find_node(n->children, "orientation")))
+            session_desktop_layout.orientation = obt_xml_node_int(m);
+        if (m && (m = obt_xml_find_node(n->children, "startcorner")))
+            session_desktop_layout.start_corner = obt_xml_node_int(m);
+        if (m && (m = obt_xml_find_node(n->children, "columns")))
+            session_desktop_layout.columns = obt_xml_node_int(m);
+        if (m && (m = obt_xml_find_node(n->children, "rows")))
+            session_desktop_layout.rows = obt_xml_node_int(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))
+    if ((n = obt_xml_find_node(node->children, "desktopnames"))) {
+        for (m = obt_xml_find_node(n->children, "name"); m;
+             m = obt_xml_find_node(m->next, "name"))
         {
             session_desktop_names = g_slist_append(session_desktop_names,
-                                                   parse_string(doc, m));
+                                                   obt_xml_node_string(m));
         }
     }
 
-    for (node = parse_find_node("window", node->children); node != NULL;
-         node = parse_find_node("window", node->next))
+    ob_debug_type(OB_DEBUG_SM, "loading windows");
+    for (node = obt_xml_find_node(node->children, "window"); node != NULL;
+         node = obt_xml_find_node(node->next, "window"))
     {
         ObSessionState *state;
 
         state = g_new0(ObSessionState, 1);
 
-        if (!parse_attr_string("id", node, &state->id))
-            if (!parse_attr_string("command", node, &state->command))
+        if (!obt_xml_attr_string(node, "id", &state->id))
+            if (!obt_xml_attr_string(node, "command", &state->command))
             goto session_load_bail;
-        if (!(n = parse_find_node("name", node->children)))
+        if (!(n = obt_xml_find_node(node->children, "name")))
             goto session_load_bail;
-        state->name = parse_string(doc, n);
-        if (!(n = parse_find_node("class", node->children)))
+        state->name = obt_xml_node_string(n);
+        if (!(n = obt_xml_find_node(node->children, "class")))
             goto session_load_bail;
-        state->class = parse_string(doc, n);
-        if (!(n = parse_find_node("role", node->children)))
+        state->class = obt_xml_node_string(n);
+        if (!(n = obt_xml_find_node(node->children, "role")))
             goto session_load_bail;
-        state->role = parse_string(doc, n);
-        if (!(n = parse_find_node("windowtype", node->children)))
+        state->role = obt_xml_node_string(n);
+        if (!(n = obt_xml_find_node(node->children, "windowtype")))
             goto session_load_bail;
-        state->type = parse_int(doc, n);
-        if (!(n = parse_find_node("desktop", node->children)))
+        state->type = obt_xml_node_int(n);
+        if (!(n = obt_xml_find_node(node->children, "desktop")))
             goto session_load_bail;
-        state->desktop = parse_int(doc, n);
-        if (!(n = parse_find_node("x", node->children)))
+        state->desktop = obt_xml_node_int(n);
+        if (!(n = obt_xml_find_node(node->children, "x")))
             goto session_load_bail;
-        state->x = parse_int(doc, n);
-        if (!(n = parse_find_node("y", node->children)))
+        state->x = obt_xml_node_int(n);
+        if (!(n = obt_xml_find_node(node->children, "y")))
             goto session_load_bail;
-        state->y = parse_int(doc, n);
-        if (!(n = parse_find_node("width", node->children)))
+        state->y = obt_xml_node_int(n);
+        if (!(n = obt_xml_find_node(node->children, "width")))
             goto session_load_bail;
-        state->w = parse_int(doc, n);
-        if (!(n = parse_find_node("height", node->children)))
+        state->w = obt_xml_node_int(n);
+        if (!(n = obt_xml_find_node(node->children, "height")))
             goto session_load_bail;
-        state->h = parse_int(doc, n);
+        state->h = obt_xml_node_int(n);
 
         state->shaded =
-            parse_find_node("shaded", node->children) != NULL;
+            obt_xml_find_node(node->children, "shaded") != NULL;
         state->iconic =
-            parse_find_node("iconic", node->children) != NULL;
+            obt_xml_find_node(node->children, "iconic") != NULL;
         state->skip_pager =
-            parse_find_node("skip_pager", node->children) != NULL;
+            obt_xml_find_node(node->children, "skip_pager") != NULL;
         state->skip_taskbar =
-            parse_find_node("skip_taskbar", node->children) != NULL;
+            obt_xml_find_node(node->children, "skip_taskbar") != NULL;
         state->fullscreen =
-            parse_find_node("fullscreen", node->children) != NULL;
+            obt_xml_find_node(node->children, "fullscreen") != NULL;
         state->above =
-            parse_find_node("above", node->children) != NULL;
+            obt_xml_find_node(node->children, "above") != NULL;
         state->below =
-            parse_find_node("below", node->children) != NULL;
+            obt_xml_find_node(node->children, "below") != NULL;
         state->max_horz =
-            parse_find_node("max_horz", node->children) != NULL;
+            obt_xml_find_node(node->children, "max_horz") != NULL;
         state->max_vert =
-            parse_find_node("max_vert", node->children) != NULL;
+            obt_xml_find_node(node->children, "max_vert") != NULL;
         state->undecorated =
-            parse_find_node("undecorated", node->children) != NULL;
+            obt_xml_find_node(node->children, "undecorated") != NULL;
         state->focused =
-            parse_find_node("focused", node->children) != NULL;
+            obt_xml_find_node(node->children, "focused") != NULL;
 
         /* save this. they are in the file in stacking order, so preserve
            that order here */
         session_saved_state = g_list_append(session_saved_state, state);
+        ob_debug_type(OB_DEBUG_SM, "loaded %s", state->name);
         continue;
 
     session_load_bail:
+        ob_debug_type(OB_DEBUG_SM, "loading FAILED");
         session_state_free(state);
     }
 
@@ -816,6 +829,7 @@ static void session_load_file(const gchar *path)
                 !strcmp(s1->class, s2->class) &&
                 !strcmp(s1->role, s2->role))
             {
+                ob_debug_type(OB_DEBUG_SM, "removing duplicate %s", s2->name);
                 session_state_free(s2);
                 session_saved_state =
                     g_list_delete_link(session_saved_state, jt);
@@ -824,12 +838,13 @@ static void session_load_file(const gchar *path)
         }
 
         if (founddup) {
+            ob_debug_type(OB_DEBUG_SM, "removing duplicate %s", s1->name);
             session_state_free(s1);
             session_saved_state = g_list_delete_link(session_saved_state, it);
         }
     }
 
-    xmlFreeDoc(doc);
+    obt_xml_instance_unref(i);
 }
 
 void session_request_logout(gboolean silent)
index 1638908..cb710e5 100644 (file)
@@ -18,7 +18,6 @@
 */
 
 #include "openbox.h"
-#include "prop.h"
 #include "screen.h"
 #include "focus.h"
 #include "client.h"
@@ -27,6 +26,7 @@
 #include "window.h"
 #include "event.h"
 #include "debug.h"
+#include "obt/prop.h"
 
 GList  *stacking_list = NULL;
 /*! When true, stacking changes will not be reflected on the screen.  This is
@@ -55,8 +55,8 @@ void stacking_set_list(void)
         }
     }
 
-    PROP_SETA32(RootWindow(ob_display, ob_screen),
-                net_client_list_stacking, window, (gulong*)windows, i);
+    OBT_PROP_SETA32(obt_root(ob_screen), NET_CLIENT_LIST_STACKING, WINDOW,
+                    (gulong*)windows, i);
 
     g_free(windows);
 }
@@ -69,6 +69,8 @@ static void do_restack(GList *wins, GList *before)
 
 #ifdef DEBUG
     GList *next;
+
+    g_assert(wins);
     /* pls only restack stuff in the same layer at a time */
     for (it = wins; it; it = next) {
         next = g_list_next(it);
@@ -105,7 +107,7 @@ static void do_restack(GList *wins, GList *before)
 #endif
 
     if (!pause_changes)
-        XRestackWindows(ob_display, win, i);
+        XRestackWindows(obt_display, win, i);
     g_free(win);
 
     stacking_set_list();
@@ -132,7 +134,7 @@ void stacking_temp_raise(ObWindow *window)
 
     win[1] = window_top(window);
     start = event_start_ignore_all_enters();
-    XRestackWindows(ob_display, win, 2);
+    XRestackWindows(obt_display, win, 2);
     event_end_ignore_all_enters(start);
 
     pause_changes = TRUE;
@@ -150,7 +152,7 @@ void stacking_restore(void)
     for (i = 1, it = stacking_list; it; ++i, it = g_list_next(it))
         win[i] = window_top(it->data);
     start = event_start_ignore_all_enters();
-    XRestackWindows(ob_display, win, i);
+    XRestackWindows(obt_display, win, i);
     event_end_ignore_all_enters(start);
     g_free(win);
 
@@ -648,21 +650,20 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
                     sibling->iconic))
     {
         ob_debug("Setting restack sibling to NULL, they are not on the same "
-                 "desktop or it is iconified\n");
+                 "desktop or it is iconified");
         sibling = NULL;
     }
 
     switch (detail) {
     case Below:
-        ob_debug("Restack request Below for client %s sibling %s\n",
+        ob_debug("Restack request Below for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
         /* just lower it */
         stacking_lower(CLIENT_AS_WINDOW(client));
         ret = TRUE;
         break;
     case BottomIf:
-        ob_debug("Restack request BottomIf for client %s sibling "
-                 "%s\n",
+        ob_debug("Restack request BottomIf for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
         /* if this client occludes sibling (or anything if NULL), then
            lower it to the bottom */
@@ -672,13 +673,13 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
         }
         break;
     case Above:
-        ob_debug("Restack request Above for client %s sibling %s\n",
+        ob_debug("Restack request Above for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
         stacking_raise(CLIENT_AS_WINDOW(client));
         ret = TRUE;
         break;
     case TopIf:
-        ob_debug("Restack request TopIf for client %s sibling %s\n",
+        ob_debug("Restack request TopIf for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
         if (stacking_occluded(client, sibling)) {
             stacking_raise(CLIENT_AS_WINDOW(client));
@@ -686,8 +687,7 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
         }
         break;
     case Opposite:
-        ob_debug("Restack request Opposite for client %s sibling "
-                 "%s\n",
+        ob_debug("Restack request Opposite for client %s sibling %s",
                  client->title, sibling ? sibling->title : "(all)");
         if (stacking_occluded(client, sibling)) {
             stacking_raise(CLIENT_AS_WINDOW(client));
index e226f36..773f658 100644 (file)
@@ -43,7 +43,7 @@ extern GList *stacking_list;
 
 /*! Sets the window stacking list on the root window from the
   stacking_list */
-void stacking_set_list();
+void stacking_set_list(void);
 
 void stacking_add(struct _ObWindow *win);
 void stacking_add_nonintrusive(struct _ObWindow *win);
@@ -56,7 +56,7 @@ void stacking_raise(struct _ObWindow *window);
 void stacking_temp_raise(struct _ObWindow *window);
 
 /*! Restores any temporarily raised windows to their correct place */
-void stacking_restore();
+void stacking_restore(void);
 
 /*! Lowers a window below all others in its stacking layer */
 void stacking_lower(struct _ObWindow *window);
index 47c95da..aa6db7e 100644 (file)
@@ -43,7 +43,6 @@ void sn_spawn_cancel() {}
 #else
 
 #include "openbox.h"
-#include "mainloop.h"
 #include "screen.h"
 
 #define SN_API_NOT_YET_FROZEN
@@ -63,12 +62,12 @@ void sn_startup(gboolean reconfig)
 {
     if (reconfig) return;
 
-    sn_display = sn_display_new(ob_display, NULL, NULL);
+    sn_display = sn_display_new(obt_display, NULL, NULL);
     sn_context = sn_monitor_context_new(sn_display, ob_screen,
                                         sn_event_func, NULL, NULL);
     sn_launcher = sn_launcher_context_new(sn_display, ob_screen);
 
-    ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL);
+    obt_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL);
 }
 
 void sn_shutdown(gboolean reconfig)
@@ -77,7 +76,7 @@ void sn_shutdown(gboolean reconfig)
 
     if (reconfig) return;
 
-    ob_main_loop_x_remove(ob_main_loop, sn_handler);
+    obt_main_loop_x_remove(ob_main_loop, sn_handler);
 
     for (it = sn_waits; it; it = g_slist_next(it))
         sn_startup_sequence_unref((SnStartupSequence*)it->data);
@@ -140,10 +139,10 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data)
         sn_waits = g_slist_prepend(sn_waits, seq);
         /* 20 second timeout for apps to start if the launcher doesn't
            have a timeout */
-        ob_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC,
-                                 sn_wait_timeout, seq,
-                                 g_direct_equal,
-                                 (GDestroyNotify)sn_startup_sequence_unref);
+        obt_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC,
+                                  sn_wait_timeout, seq,
+                                  g_direct_equal,
+                                  (GDestroyNotify)sn_startup_sequence_unref);
         change = TRUE;
         break;
     case SN_MONITOR_EVENT_CHANGED:
@@ -154,8 +153,8 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data)
     case SN_MONITOR_EVENT_CANCELED:
         if ((seq = sequence_find(sn_startup_sequence_get_id(seq)))) {
             sn_waits = g_slist_remove(sn_waits, seq);
-            ob_main_loop_timeout_remove_data(ob_main_loop, sn_wait_timeout,
-                                             seq, FALSE);
+            obt_main_loop_timeout_remove_data(ob_main_loop, sn_wait_timeout,
+                                              seq, FALSE);
             change = TRUE;
         }
         break;
@@ -261,10 +260,10 @@ void sn_setup_spawn_environment(const gchar *program, const gchar *name,
 
     /* 20 second timeout for apps to start */
     sn_launcher_context_ref(sn_launcher);
-    ob_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC,
-                             sn_launch_wait_timeout, sn_launcher,
-                             g_direct_equal,
-                             (GDestroyNotify)sn_launcher_context_unref);
+    obt_main_loop_timeout_add(ob_main_loop, 20 * G_USEC_PER_SEC,
+                              sn_launch_wait_timeout, sn_launcher,
+                              g_direct_equal,
+                              (GDestroyNotify)sn_launcher_context_unref);
 
     setenv("DESKTOP_STARTUP_ID", id, TRUE);
 
index 758beee..d524bca 100644 (file)
@@ -25,7 +25,7 @@
 void sn_startup(gboolean reconfig);
 void sn_shutdown(gboolean reconfig);
 
-gboolean sn_app_starting();
+gboolean sn_app_starting(void);
 
 /*! Notify that an app has started
   @param wmclass the WM_CLASS[1] hint
@@ -45,6 +45,6 @@ void sn_setup_spawn_environment(const gchar *program, const gchar *name,
 /* Tell startup notification we're not actually running the program we
    told it we were
 */
-void sn_spawn_cancel();
+void sn_spawn_cancel(void);
 
 #endif
index bd8b88f..50d5000 100644 (file)
@@ -19,9 +19,9 @@
 
 #include "openbox.h"
 #include "mouse.h"
-#include "modkeys.h"
-#include "translate.h"
 #include "gettext.h"
+#include "obt/keyboard.h"
+
 #include <glib.h>
 #include <string.h>
 #include <stdlib.h>
@@ -38,23 +38,23 @@ static guint translate_modifier(gchar *str)
 
     else if (!g_ascii_strcasecmp("Control", str) ||
              !g_ascii_strcasecmp("C", str))
-        mask = modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL);
+        mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL);
     else if (!g_ascii_strcasecmp("Alt", str) ||
              !g_ascii_strcasecmp("A", str))
-        mask = modkeys_key_to_mask(OB_MODKEY_KEY_ALT);
+        mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_ALT);
     else if (!g_ascii_strcasecmp("Meta", str) ||
              !g_ascii_strcasecmp("M", str))
-        mask = modkeys_key_to_mask(OB_MODKEY_KEY_META);
+        mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_META);
     /* W = windows key, is linked to the Super_L/R buttons */
     else if (!g_ascii_strcasecmp("Super", str) ||
              !g_ascii_strcasecmp("W", str))
-        mask = modkeys_key_to_mask(OB_MODKEY_KEY_SUPER);
+        mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SUPER);
     else if (!g_ascii_strcasecmp("Shift", str) ||
              !g_ascii_strcasecmp("S", str))
-        mask = modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT);
+        mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT);
     else if (!g_ascii_strcasecmp("Hyper", str) ||
              !g_ascii_strcasecmp("H", str))
-        mask = modkeys_key_to_mask(OB_MODKEY_KEY_HYPER);
+        mask = obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_HYPER);
     else
         g_message(_("Invalid modifier key \"%s\" in key/mouse binding"), str);
 
@@ -145,7 +145,7 @@ gboolean translate_key(const gchar *str, guint *state, guint *keycode)
             g_message(_("Invalid key name \"%s\" in key binding"), l);
             goto translation_fail;
         }
-        *keycode = XKeysymToKeycode(ob_display, sym);
+        *keycode = XKeysymToKeycode(obt_display, sym);
     }
     if (!*keycode) {
         g_message(_("Requested key \"%s\" does not exist on the display"), l);
@@ -158,30 +158,3 @@ translation_fail:
     g_strfreev(parsed);
     return ret;
 }
-
-gchar *translate_keycode(guint keycode)
-{
-    KeySym sym;
-    const gchar *ret = NULL;
-
-    if ((sym = XKeycodeToKeysym(ob_display, keycode, 0)) != NoSymbol)
-        ret = XKeysymToString(sym);
-    return g_locale_to_utf8(ret, -1, NULL, NULL, NULL);
-}
-
-gunichar translate_unichar(guint keycode)
-{
-    gunichar unikey = 0;
-
-    char *key;
-    if ((key = translate_keycode(keycode)) != NULL &&
-        /* don't accept keys that aren't a single letter, like "space" */
-        key[1] == '\0')
-    {
-        unikey = g_utf8_get_char_validated(key, -1);
-        if (unikey == (gunichar)-1 || unikey == (gunichar)-2 || unikey == 0)
-            unikey = 0;
-    }
-    g_free(key);
-    return unikey;
-}
index 6d9e23b..bffdc9b 100644 (file)
 gboolean translate_button(const gchar *str, guint *state, guint *keycode);
 gboolean translate_key(const gchar *str, guint *state, guint *keycode);
 
-/*! Give the string form of a keycode */
-gchar *translate_keycode(guint keycode);
-
-/*! Translate a keycode to the unicode character it represents */
-gunichar translate_unichar(guint keycode);
+void RrImageSetDestroyFunc(RrImage *image, RrImageDestroyFunc func);
 
 #endif
index d312fc3..19b362e 100644 (file)
 #include "dock.h"
 #include "client.h"
 #include "frame.h"
+#include "openbox.h"
 #include "prompt.h"
+#include "debug.h"
+#include "grab.h"
 
-GHashTable *window_map;
+static GHashTable *window_map;
 
 static guint window_hash(Window *w) { return *w; }
 static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
@@ -47,20 +50,16 @@ void window_shutdown(gboolean reconfig)
 Window window_top(ObWindow *self)
 {
     switch (self->type) {
-    case Window_Menu:
-        return ((ObMenuFrame*)self)->window;
-    case Window_Dock:
-        return ((ObDock*)self)->frame;
-    case Window_DockApp:
-        /* not to be used for stacking */
-        g_assert_not_reached();
-        break;
-    case Window_Client:
-        return ((ObClient*)self)->frame->window;
-    case Window_Internal:
-        return ((InternalWindow*)self)->window;
-    case Window_Prompt:
-        return ((ObPrompt*)self)->super.window;
+    case OB_WINDOW_CLASS_MENUFRAME:
+        return WINDOW_AS_MENUFRAME(self)->window;
+    case OB_WINDOW_CLASS_DOCK:
+        return WINDOW_AS_DOCK(self)->frame;
+    case OB_WINDOW_CLASS_CLIENT:
+        return WINDOW_AS_CLIENT(self)->frame->window;
+    case OB_WINDOW_CLASS_INTERNAL:
+        return WINDOW_AS_INTERNAL(self)->window;
+    case OB_WINDOW_CLASS_PROMPT:
+        return WINDOW_AS_PROMPT(self)->super.window;
     }
     g_assert_not_reached();
     return None;
@@ -69,19 +68,14 @@ Window window_top(ObWindow *self)
 ObStackingLayer window_layer(ObWindow *self)
 {
     switch (self->type) {
-    case Window_Menu:
-        return OB_STACKING_LAYER_INTERNAL;
-    case Window_Dock:
+    case OB_WINDOW_CLASS_DOCK:
         return config_dock_layer;
-    case Window_DockApp:
-        /* not to be used for stacking */
-        g_assert_not_reached();
-        break;
-    case Window_Client:
+    case OB_WINDOW_CLASS_CLIENT:
         return ((ObClient*)self)->layer;
-    case Window_Internal:
+    case OB_WINDOW_CLASS_MENUFRAME:
+    case OB_WINDOW_CLASS_INTERNAL:
         return OB_STACKING_LAYER_INTERNAL;
-    case Window_Prompt:
+    case OB_WINDOW_CLASS_PROMPT:
         /* not used directly for stacking, prompts are managed as clients */
         g_assert_not_reached();
         break;
@@ -89,3 +83,129 @@ ObStackingLayer window_layer(ObWindow *self)
     g_assert_not_reached();
     return None;
 }
+
+ObWindow* window_find(Window xwin)
+{
+    return g_hash_table_lookup(window_map, &xwin);
+}
+
+void window_add(Window *xwin, ObWindow *win)
+{
+    g_assert(xwin != NULL);
+    g_assert(win != NULL);
+    g_hash_table_insert(window_map, xwin, win);
+}
+
+void window_remove(Window xwin)
+{
+    g_assert(xwin != None);
+    g_hash_table_remove(window_map, &xwin);
+}
+
+void window_manage_all(void)
+{
+    guint i, j, nchild;
+    Window w, *children;
+    XWMHints *wmhints;
+    XWindowAttributes attrib;
+
+    if (!XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
+                    &w, &w, &children, &nchild)) {
+        ob_debug("XQueryTree failed in window_manage_all");
+        nchild = 0;
+    }
+
+    /* remove all icon windows from the list */
+    for (i = 0; i < nchild; i++) {
+        if (children[i] == None) continue;
+        wmhints = XGetWMHints(obt_display, children[i]);
+        if (wmhints) {
+            if ((wmhints->flags & IconWindowHint) &&
+                (wmhints->icon_window != children[i]))
+                for (j = 0; j < nchild; j++)
+                    if (children[j] == wmhints->icon_window) {
+                        /* XXX watch the window though */
+                        children[j] = None;
+                        break;
+                    }
+            XFree(wmhints);
+        }
+    }
+
+    for (i = 0; i < nchild; ++i) {
+        if (children[i] == None) continue;
+        if (window_find(children[i])) continue; /* skip our own windows */
+        if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
+            if (attrib.map_state == IsUnmapped)
+                ;
+            else
+                window_manage(children[i]);
+        }
+    }
+
+    if (children) XFree(children);
+}
+
+void window_manage(Window win)
+{
+    XEvent e;
+    XWindowAttributes attrib;
+    gboolean no_manage = FALSE;
+    gboolean is_dockapp = FALSE;
+    Window icon_win = None;
+
+    grab_server(TRUE);
+
+    /* check if it has already been unmapped by the time we started
+       mapping. the grab does a sync so we don't have to here */
+    if (XCheckTypedWindowEvent(obt_display, win, DestroyNotify, &e) ||
+        XCheckTypedWindowEvent(obt_display, win, UnmapNotify, &e))
+    {
+        XPutBackEvent(obt_display, &e);
+        ob_debug("Trying to manage unmapped window. Aborting that.");
+        no_manage = TRUE;
+    }
+
+    if (!XGetWindowAttributes(obt_display, win, &attrib))
+        no_manage = TRUE;
+    else {
+        XWMHints *wmhints;
+
+        /* is the window a docking app */
+        is_dockapp = FALSE;
+        if ((wmhints = XGetWMHints(obt_display, win))) {
+            if ((wmhints->flags & StateHint) &&
+                wmhints->initial_state == WithdrawnState)
+            {
+                if (wmhints->flags & IconWindowHint)
+                    icon_win = wmhints->icon_window;
+                is_dockapp = TRUE;
+            }
+            XFree(wmhints);
+        }
+    }
+
+    if (!no_manage) {
+        if (attrib.override_redirect) {
+            ob_debug("not managing override redirect window 0x%x", win);
+            grab_server(FALSE);
+        }
+        else if (is_dockapp) {
+            if (!icon_win)
+                icon_win = win;
+            dock_manage(icon_win, win);
+        }
+        else
+            client_manage(win, NULL);
+    }
+    else {
+        grab_server(FALSE);
+        ob_debug("FAILED to manage window 0x%x", win);
+    }
+}
+
+void window_unmanage_all(void)
+{
+    dock_unmanage_all();
+    client_unmanage_all();
+}
index 76615c0..24a7d07 100644 (file)
@@ -28,33 +28,29 @@ typedef struct _ObWindow         ObWindow;
 typedef struct _ObInternalWindow ObInternalWindow;
 
 typedef enum {
-    Window_Menu,
-    Window_Dock,
-    Window_DockApp, /* used for events but not stacking */
-    Window_Client,
-    Window_Internal,/* used for stacking but not events (except to filter
-                       events on the root window) */
-    Window_Prompt,
-} Window_InternalType;
-
-struct _ObWindow
-{
-    Window_InternalType type;
+    OB_WINDOW_CLASS_MENUFRAME,
+    OB_WINDOW_CLASS_DOCK,
+    OB_WINDOW_CLASS_CLIENT,
+    OB_WINDOW_CLASS_INTERNAL,
+    OB_WINDOW_CLASS_PROMPT
+} ObWindowClass;
+
+/* In order to be an ObWindow, you need to make this struct the top of your
+   struct */
+struct _ObWindow {
+    ObWindowClass type;
 };
 
-/* Wrapper for internal stuff. If its struct matches this then it can be used
-   as an ObWindow */
-typedef struct InternalWindow {
-    Window_InternalType type;
-    Window window;
-} InternalWindow;
-
-#define WINDOW_IS_MENU(win) (((ObWindow*)win)->type == Window_Menu)
-#define WINDOW_IS_DOCK(win) (((ObWindow*)win)->type == Window_Dock)
-#define WINDOW_IS_DOCKAPP(win) (((ObWindow*)win)->type == Window_DockApp)
-#define WINDOW_IS_CLIENT(win) (((ObWindow*)win)->type == Window_Client)
-#define WINDOW_IS_INTERNAL(win) (((ObWindow*)win)->type == Window_Internal)
-#define WINDOW_IS_PROMPT(win) (((ObWindow*)win)->type == Window_Prompt)
+#define WINDOW_IS_MENUFRAME(win) \
+    (((ObWindow*)win)->type == OB_WINDOW_CLASS_MENUFRAME)
+#define WINDOW_IS_DOCK(win) \
+    (((ObWindow*)win)->type == OB_WINDOW_CLASS_DOCK)
+#define WINDOW_IS_CLIENT(win) \
+    (((ObWindow*)win)->type == OB_WINDOW_CLASS_CLIENT)
+#define WINDOW_IS_INTERNAL(win) \
+    (((ObWindow*)win)->type == OB_WINDOW_CLASS_INTERNAL)
+#define WINDOW_IS_PROMPT(win) \
+    (((ObWindow*)win)->type == OB_WINDOW_CLASS_PROMPT)
 
 struct _ObMenu;
 struct _ObDock;
@@ -62,26 +58,36 @@ struct _ObDockApp;
 struct _ObClient;
 struct _ObPrompt;
 
-#define WINDOW_AS_MENU(win) ((struct _ObMenuFrame*)win)
+#define WINDOW_AS_MENUFRAME(win) ((struct _ObMenuFrame*)win)
 #define WINDOW_AS_DOCK(win) ((struct _ObDock*)win)
-#define WINDOW_AS_DOCKAPP(win) ((struct _ObDockApp*)win)
 #define WINDOW_AS_CLIENT(win) ((struct _ObClient*)win)
-#define WINDOW_AS_INTERNAL(win) ((struct InternalWindow*)win)
+#define WINDOW_AS_INTERNAL(win) ((struct _ObInternalWindow*)win)
 #define WINDOW_AS_PROMPT(win) ((struct _ObPrompt*)win)
 
-#define MENU_AS_WINDOW(menu) ((ObWindow*)menu)
+#define MENUFRAME_AS_WINDOW(menu) ((ObWindow*)menu)
 #define DOCK_AS_WINDOW(dock) ((ObWindow*)dock)
-#define DOCKAPP_AS_WINDOW(dockapp) ((ObWindow*)dockapp)
 #define CLIENT_AS_WINDOW(client) ((ObWindow*)client)
 #define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern)
 #define PROMPT_AS_WINDOW(prompt) ((ObWindow*)prompt)
 
-extern GHashTable *window_map;
-
-void window_startup(gboolean reconfig);
+void window_startup (gboolean reconfig);
 void window_shutdown(gboolean reconfig);
 
-Window window_top(ObWindow *self);
+Window          window_top  (ObWindow *self);
 ObStackingLayer window_layer(ObWindow *self);
 
+ObWindow* window_find  (Window xwin);
+void      window_add   (Window *xwin, ObWindow *win);
+void      window_remove(Window xwin);
+
+/* Internal openbox-owned windows like the alt-tab popup */
+struct _ObInternalWindow {
+    ObWindowClass type;
+    Window window;
+};
+
+void window_manage_all(void);
+void window_manage(Window win);
+void window_unmanage_all(void);
+
 #endif
diff --git a/openbox/xerror.c b/openbox/xerror.c
deleted file mode 100644 (file)
index 2657b8e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   xerror.c for the Openbox window manager
-   Copyright (c) 2006        Mikael Magnusson
-   Copyright (c) 2003-2007   Dana Jansens
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#include "openbox.h"
-#include "gettext.h"
-#include "debug.h"
-#include "xerror.h"
-#include <glib.h>
-#include <X11/Xlib.h>
-
-static gboolean xerror_ignore = FALSE;
-gboolean xerror_occured = FALSE;
-
-gint xerror_handler(Display *d, XErrorEvent *e)
-{
-#ifdef DEBUG
-    gchar errtxt[128];
-
-    XGetErrorText(d, e->error_code, errtxt, 127);
-    if (!xerror_ignore) {
-        if (e->error_code == BadWindow)
-            /*g_message(_("X Error: %s\n"), errtxt)*/;
-        else
-            g_error(_("X Error: %s"), errtxt);
-    } else
-        ob_debug("XError code %d '%s'\n", e->error_code, errtxt);
-#else
-    (void)d; (void)e;
-#endif
-
-    xerror_occured = TRUE;
-    return 0;
-}
-
-void xerror_set_ignore(gboolean ignore)
-{
-    XSync(ob_display, FALSE);
-    xerror_ignore = ignore;
-}
diff --git a/parser/obparser-3.0.pc.in b/parser/obparser-3.0.pc.in
deleted file mode 100644 (file)
index 75d04c9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: ObParser
-Description: Openbox config file parsing library
-Version: @VERSION@
-Requires: libxml-2.0 glib-2.0
-Libs: -L${libdir} -lobparser
-Cflags: -I${includedir}/openbox/@OB_VERSION@
diff --git a/parser/parse.h b/parser/parse.h
deleted file mode 100644 (file)
index 28af64b..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-   parse.h for the Openbox window manager
-   Copyright (c) 2003-2007   Dana Jansens
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#ifndef __parse_h
-#define __parse_h
-
-#include "version.h"
-
-#include <libxml/parser.h>
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef struct _ObParseInst ObParseInst;
-
-typedef void (*ParseCallback)(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
-                              gpointer data);
-
-ObParseInst* parse_startup();
-void parse_shutdown(ObParseInst *inst);
-
-/*! Loads Openbox's rc, from the normal paths
-  @param file The path of the config to try load.  NULL to load from the
-         default path
- */
-gboolean parse_load_rc(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root);
-/* Loads an Openbox menu, from the normal paths */
-gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root);
-/* Loads an Openbox theme, from the normal paths */
-gboolean parse_load_theme(const gchar *name, xmlDocPtr *doc, xmlNodePtr *root,
-                          gchar **path);
-
-void parse_register(ObParseInst *inst, const gchar *tag,
-                    ParseCallback func, gpointer data);
-void parse_tree(ObParseInst *inst, xmlDocPtr doc, xmlNodePtr node);
-
-
-/* open/close */
-
-gboolean parse_load(const gchar *path, const gchar *rootname,
-                    xmlDocPtr *doc, xmlNodePtr *root);
-gboolean parse_load_mem(gpointer data, guint len, const gchar *rootname,
-                        xmlDocPtr *doc, xmlNodePtr *root);
-void parse_close(xmlDocPtr doc);
-
-
-/* helpers */
-
-xmlNodePtr parse_find_node(const gchar *tag, xmlNodePtr node);
-
-gchar *parse_string(xmlDocPtr doc, xmlNodePtr node);
-gint parse_int(xmlDocPtr doc, xmlNodePtr node);
-gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node);
-
-gboolean parse_contains(const gchar *val, xmlDocPtr doc, xmlNodePtr node);
-gboolean parse_attr_contains(const gchar *val, xmlNodePtr node,
-                             const gchar *name);
-
-gboolean parse_attr_string(const gchar *name, xmlNodePtr node, gchar **value);
-gboolean parse_attr_int(const gchar *name, xmlNodePtr node, gint *value);
-gboolean parse_attr_bool(const gchar *name, xmlNodePtr node, gboolean *value);
-
-/* paths */
-
-void parse_paths_startup();
-void parse_paths_shutdown();
-
-const gchar* parse_xdg_config_home_path();
-const gchar* parse_xdg_data_home_path();
-GSList* parse_xdg_config_dir_paths();
-GSList* parse_xdg_data_dir_paths();
-
-/*! Expands the ~ character to the home directory throughout the given
-  string */
-gchar *parse_expand_tilde(const gchar *f);
-/*! Makes a directory */
-gboolean parse_mkdir(const gchar *path, gint mode);
-/*! Makes a directory and all its parents */
-gboolean parse_mkdir_path(const gchar *path, gint mode);
-
-G_END_DECLS
-
-#endif
index 85938de..4509714 100644 (file)
@@ -7,13 +7,12 @@ openbox/client_list_combined_menu.c
 openbox/client_list_menu.c
 openbox/client_menu.c
 openbox/config.c
+openbox/debug.c
 openbox/keyboard.c
 openbox/menu.c
 openbox/mouse.c
 openbox/openbox.c
 openbox/screen.c
-openbox/session.c
 openbox/startupnotify.c
 openbox/translate.c
-openbox/xerror.c
 openbox/prompt.c
diff --git a/tests/mingrow.c b/tests/mingrow.c
new file mode 100644 (file)
index 0000000..b132fa1
--- /dev/null
@@ -0,0 +1,100 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   noresize.c for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+int main () {
+  XSetWindowAttributes xswa;
+  unsigned long        xswamask;
+  Display   *display;
+  Window     win;
+  XEvent     report;
+  int        x=10,y=10,h=100,w=100;
+  XSizeHints size;
+
+  display = XOpenDisplay(NULL);
+
+  if (display == NULL) {
+    fprintf(stderr, "couldn't connect to X server :0\n");
+    return 0;
+  }
+
+  xswa.win_gravity = StaticGravity;
+  xswamask = CWWinGravity;
+
+  win = XCreateWindow(display, RootWindow(display, 0),
+                     x, y, w, h, 0, CopyFromParent, CopyFromParent,
+                     CopyFromParent, xswamask, &xswa);
+
+  XSetWindowBackground(display,win,WhitePixel(display,0));
+
+  size.flags = PMinSize | PMaxSize;
+  size.max_width = 0;
+  size.min_width = w;
+  size.max_height = 0;
+  size.min_height = h;
+  XSetWMNormalHints(display, win, &size);
+
+  XSelectInput(display, win, ExposureMask | StructureNotifyMask);
+
+  XMapWindow(display, win);
+  XFlush(display);
+
+  printf("sleeping 4..");
+  fflush(stdout);
+  sleep(1);
+  printf("3..");
+  fflush(stdout);
+  sleep(1);
+  printf("2..");
+  fflush(stdout);
+  sleep(1);
+  printf("1..");
+  fflush(stdout);
+  sleep(1);
+  printf("\n");
+
+  size.flags = PMinSize | PMaxSize;
+  size.max_width = 0;
+  size.min_width = w*2;
+  size.max_height = 0;
+  size.min_height = h*2;
+  XSetWMNormalHints(display, win, &size);
+
+  while (1) {
+    XNextEvent(display, &report);
+
+    switch (report.type) {
+    case Expose:
+      printf("exposed\n");
+      break;
+    case ConfigureNotify:
+      x = report.xconfigure.x;
+      y = report.xconfigure.y;
+      w = report.xconfigure.width;
+      h = report.xconfigure.height;
+      printf("confignotify %i,%i-%ix%i\n",x,y,w,h);
+      break;
+    }
+
+  }
+
+  return 1;
+}
diff --git a/tests/oldfullscreen.c b/tests/oldfullscreen.c
new file mode 100644 (file)
index 0000000..543e960
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   oldfullscreen.c for the Openbox window manager
+   Copyright (c) 2010        Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef struct
+{
+    unsigned long   flags;
+    unsigned long   functions;
+    unsigned long   decorations;
+    long            inputMode;
+    unsigned long   status;
+} Hints;
+
+int main (int argc, char **argv) {
+    Display    *display;
+    Window      win;
+    Window      r;
+    XEvent      report;
+    int         x=200,y=200,h=100,w=400,s;
+    XSizeHints *size;
+    Hints       hints;
+    Atom        prop;
+
+    display = XOpenDisplay(NULL);
+
+    if (display == NULL) {
+        fprintf(stderr, "couldn't connect to X server :0\n");
+        return 0;
+    }
+
+    XGetGeometry(display, RootWindow(display, DefaultScreen(display)), &r,
+                 &x, &y, &w, &h, &s, &s);
+
+    win = XCreateWindow(display, RootWindow(display, 0),
+                        x, y, w, h, 0, CopyFromParent, CopyFromParent,
+                        CopyFromParent, 0, NULL);
+    XSetWindowBackground(display,win,WhitePixel(display,0));
+
+    size = XAllocSizeHints();
+    size->flags = PPosition;
+    XSetWMNormalHints(display,win,size);
+    XFree(size);
+
+    hints.flags = 2;
+    hints.decorations = 0;
+    prop = XInternAtom(display, "_MOTIF_WM_HINTS", False);
+    XChangeProperty(display, win, prop, prop, 32, PropModeReplace,
+                    (unsigned char *)&hints, 5);
+
+    XFlush(display);
+    XMapWindow(display, win);
+
+    XSelectInput(display, win, StructureNotifyMask | ButtonPressMask);
+
+    while (1) {
+        XNextEvent(display, &report);
+
+        switch (report.type) {
+        case ButtonPress:
+            XUnmapWindow(display, win);
+            break;
+        case ConfigureNotify:
+            x = report.xconfigure.x;
+            y = report.xconfigure.y;
+            w = report.xconfigure.width;
+            h = report.xconfigure.height;
+            s = report.xconfigure.send_event;
+            printf("confignotify %i,%i-%ix%i (send: %d)\n",x,y,w,h,s);
+            break;
+        }
+
+    }
+
+    return 1;
+}
diff --git a/tests/overrideinputonly.c b/tests/overrideinputonly.c
new file mode 100644 (file)
index 0000000..0c13ac3
--- /dev/null
@@ -0,0 +1,58 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   override.c for the Openbox window manager
+   Copyright (c) 2003-2007   Dana Jansens
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+
+int main (int argc, char *argv[]) {
+  XSetWindowAttributes xswa;
+  unsigned long        xswamask;
+  Display   *display;
+  Window     win;
+  XEvent     report;
+  int        i,x=0,y=0,h=1,w=1;
+
+  for (i=0; i < argc; i++) {
+    if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "-geometry")) {
+      XParseGeometry(argv[++i], &x, &y, &w, &h);
+    }
+  }
+
+  display = XOpenDisplay(NULL);
+
+  if (display == NULL) {
+    fprintf(stderr, "couldn't connect to X server :0\n");
+    return 0;
+  }
+
+  xswa.override_redirect = True;
+  xswamask = CWOverrideRedirect;
+
+  win = XCreateWindow(display, RootWindow(display, 0),
+                     x, y, w, h, 0, 0, InputOnly,
+                     CopyFromParent, xswamask, &xswa);
+
+  XMapWindow(display, win);
+  XFlush(display);
+
+  while (1) {
+    XNextEvent(display, &report);
+  }
+
+  return 1;
+}
index 1dde5fb..67d5f26 100644 (file)
@@ -145,11 +145,14 @@ osd.bg.colorTo.splitto: #E7E5E4
 
 osd.bg.border.color: #ffffff
 
-osd.label.bg: parentrelative
-osd.label.bg.color: #efefef
-osd.label.bg.border.color: #9c9e9c
+osd.active.label.bg: parentrelative
+osd.active.label.bg.color: #efefef
+osd.active.label.bg.border.color: #9c9e9c
+osd.active.label.text.color: #444
+
+osd.inactive.label.bg: parentrelative
+osd.inactive.label.text.color: #70747d
 
-osd.label.text.color: #444
 !# yeah whatever, this is fine anyhoo?
 osd.hilight.bg: flat vertical gradient 
 osd.hilight.bg.color: #9ebde5
index 70cfcec..1cfeb5c 100644 (file)
@@ -1,15 +1,6 @@
 #ifndef ob__version_h
 #define ob__version_h
 
-#define OB_MAJOR_VERSION @OB_MAJOR_VERSION@
-#define OB_MINOR_VERSION @OB_MINOR_VERSION@
-#define OB_MICRO_VERSION @OB_MICRO_VERSION@
-#define OB_VERSION "@OB_VERSION@"
-
-#define OB_CHECK_VERSION(major,minor,micro) \
-    (OB_MAJOR_VERSION > (major) || \
-     (OB_MAJOR_VERSION == (major) && OB_MINOR_VERSION > (minor)) || \
-     (OB_MAJOR_VERSION == (major) && OB_MINOR_VERSION == (minor) && \
-      OB_MICRO_VERSION >= (micro)))
+#define OPENBOX_VERSION "@OPENBOX_VERSION@"
 
 #endif