Openbox doesn't look for hung processes at this time.
+ _NET_FRAME_EXTENTS (1.3)
+ _NET_WM_STATE_DEMANDS_ATTENTION (1.3)
-- _NET_RESTACK_WINDOW (1.3)
- Openbox doesn't support this at this time.
++ _NET_RESTACK_WINDOW (1.3)
+ _NET_WM_SYNC_REQUEST (1.3)
+ _NET_WM_FULL_PLACEMENT (1.4)
+ _NET_WM_MOVERESIZE_CANCEL (1.4)
bin_SCRIPTS = \
data/xsession/openbox-gnome-session \
- data/xsession/openbox-kde-session \
- data/xsession/openbox-gnome \
- data/xsession/openbox-kde
+ data/xsession/openbox-kde-session
## render ##
dist_pixmap_DATA = \
data/openbox.png
-nodist_rc_DATA = \
+dist_rc_DATA = \
data/rc.xml \
data/menu.xml
edit = $(SED) \
-e 's!@version\@!$(VERSION)!' \
- -e 's!@xsddir\@!$(xsddir)!'
+ -e 's!@bindir\@!$(bindir)!'
-data/rc.xml: Makefile $(srcdir)/data/rc.xml.in data
+data/xsession/openbox-gnome-session: Makefile data \
+ $(srcdir)/data/xsession/openbox-gnome-session.in
@echo make: creating $@
@rm -f $@
@mkdir data 2>/dev/null || true
- @$(edit) $(srcdir)/data/rc.xml.in >$@
+ @$(edit) $(srcdir)/data/xsession/openbox-gnome-session.in >$@
+ @chmod +x $@
-data/menu.xml: Makefile $(srcdir)/data/menu.xml.in data
+data/xsession/openbox-kde-session: Makefile data \
+ $(srcdir)/data/xsession/openbox-kde-session.in
@echo make: creating $@
@rm -f $@
@mkdir data 2>/dev/null || true
- @$(edit) $(srcdir)/data/menu.xml.in >$@
+ @$(edit) $(srcdir)/data/xsession/openbox-kde-session.in >$@
+ @chmod +x $@
dist_gnomewmfiles_DATA = \
data/gnome-wm-properties/openbox.desktop \
version.h.in \
data/rc.xsd \
data/menu.xsd \
- data/rc.xml.in \
- data/menu.xml.in \
+ data/xsession/openbox-gnome-session.in \
+ data/xsession/openbox-kde-session.in \
render/obrender-3.0.pc.in \
parser/obparser-3.0.pc.in \
tools/themeupdate/themeupdate.py \
COPYING \
AUTHORS
-CLEANFILES = \
- data/rc.xml \
- data/menu.xml
-
#doc:
# $(MAKE) -$(MAKEFLAGS) -C doc/doxygen doc
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<openbox_menu xmlns="http://openbox.org/"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://openbox.org/
- file://@xsddir@/menu.xsd">
-
-<menu id="games-menu" label="Games">
- <item label="Crack-Attack">
- <action name="Execute"><execute>crack-attack</execute></action>
- </item>
- <item label="XFRisk">
- <action name="Execute"><execute>xfrisk</execute></action>
- </item>
- <item label="Quake III">
- <action name="Execute"><execute>quake3</execute></action>
- </item>
-</menu>
-
-<menu id="apps-menu" label="Applications">
- <item label="Xterm">
- <action name="Execute"><execute>xterm</execute></action>
- </item>
- <item label="Mozilla">
- <action name="Execute"><execute>mozilla</execute></action>
- </item>
- <item label="Gaim">
- <action name="Execute"><execute>gaim</execute></action>
- </item>
- <item label="Quark">
- <action name="Execute"><execute>strange-quark</execute></action>
- </item>
-</menu>
-
-<menu id="root-menu" label="Openbox 3">
- <separator label="Openbox" />
- <menu id="apps-menu" />
- <menu id="games-menu" />
- <separator />
- <menu id="client-list-menu" />
- <separator />
- <item label="ObConf">
- <action name="Execute"><execute>obconf</execute></action>
- </item>
- <item label="Reconfigure">
- <action name="Reconfigure" />
- </item>
- <separator />
- <item label="Exit">
- <action name="Exit" />
- </item>
-</menu>
-
-</openbox_menu>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- Do not edit this file, it will be overwritten on install.
- Copy the file to $HOME/.config/openbox/ instead. -->
-
-<openbox_config xmlns="http://openbox.org/"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://openbox.org/
- file://@xsddir@/rc.xsd">
-
-<resistance>
- <strength>10</strength>
- <screen_edge_strength>20</screen_edge_strength>
- <edges_hit_layers_below>no</edges_hit_layers_below>
-</resistance>
-
-<focus>
- <focusNew>yes</focusNew>
- <focusLast>no</focusLast>
- <followMouse>no</followMouse>
- <focusDelay>0</focusDelay>
- <raiseOnFocus>no</raiseOnFocus>
-</focus>
-
-<placement>
- <policy>Smart</policy>
- <!-- 'Smart' or 'UnderMouse' -->
-</placement>
-
-<theme>
- <name>Clearlooks</name>
- <titleLayout>NLIMC</titleLayout>
- <titleNumber>yes</titleNumber>
- <!--
- avaible characters are NDSLIMC, each can occur at most once.
- N: client menu
- L: window label (AKA title).
- I: iconify
- M: maximize
- C: close
- S: shade
- D: omnipresent (on all desktops).
- -->
- <keepBorder>yes</keepBorder>
- <animateIconify>yes</animateIconify>
- <font place="ActiveWindow">
- <name>sans</name>
- <size>7</size>
- <!-- font size in points -->
- <weight>bold</weight>
- <!-- 'bold' or 'normal' -->
- <slant>normal</slant>
- <!-- 'italic' or 'normal' -->
- </font>
- <font place="InactiveWindow">
- <name>sans</name>
- <size>7</size>
- <!-- font size in points -->
- <weight>bold</weight>
- <!-- 'bold' or 'normal' -->
- <slant>normal</slant>
- <!-- 'italic' or 'normal' -->
- </font>
- <font place="MenuHeader">
- <name>sans</name>
- <size>8</size>
- <!-- font size in points -->
- <weight>bold</weight>
- <!-- 'bold' or 'normal' -->
- <slant>normal</slant>
- <!-- 'italic' or 'normal' -->
- </font>
- <font place="MenuItem">
- <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="OnScreenDisplay">
- <name>sans</name>
- <size>9</size>
- <!-- font size in points -->
- <weight>bold</weight>
- <!-- 'bold' or 'normal' -->
- <slant>normal</slant>
- <!-- 'italic' or 'normal' -->
- </font>
-</theme>
-
-<desktops>
- <!-- this stuff is only used at startup, pagers allow you to change them
- during a session -->
- <number>4</number>
- <firstdesk>1</firstdesk>
- <names>
- <name>desktop one</name>
- <name>desktop two</name>
- <name>desktop three</name>
- <name>desktop four</name>
- </names>
-</desktops>
-
-<resize>
- <drawContents>yes</drawContents>
- <popupShow>Nonpixel</popupShow>
- <!-- 'Always', 'Never', or 'Nonpixel' (xterms and such) -->
- <popupPosition>Center</popupPosition>
- <!-- 'Center' or 'Top' -->
-</resize>
-
-<dock>
- <position>TopLeft</position>
- <!-- (Top|Bottom)(Left|Right|)|Top|Bottom|Left|Right|Floating -->
- <floatingX>0</floatingX>
- <floatingY>0</floatingY>
- <noStrut>no</noStrut>
- <stacking>Above</stacking>
- <!-- 'Above', 'Normal', or 'Below' -->
- <direction>Vertical</direction>
- <!-- 'Vertical' or 'Horizontal' -->
- <autoHide>no</autoHide>
- <hideDelay>300</hideDelay>
- <showDelay>300</showDelay>
- <moveButton>Middle</moveButton>
-</dock>
-
-<keyboard>
- <chainQuitKey>C-g</chainQuitKey>
-
- <keybind key="A-F10">
- <action name="MaximizeFull"/>
- </keybind>
- <keybind key="A-F5">
- <action name="UnmaximizeFull"/>
- </keybind>
- <keybind key="A-F12">
- <action name="ToggleShade"/>
- </keybind>
- <keybind key="C-A-Left">
- <action name="DesktopLeft"><wrap>no</wrap></action>
- </keybind>
- <keybind key="C-A-Right">
- <action name="DesktopRight"><wrap>no</wrap></action>
- </keybind>
- <keybind key="C-A-Up">
- <action name="DesktopUp"><wrap>no</wrap></action>
- </keybind>
- <keybind key="C-A-Down">
- <action name="DesktopDown"><wrap>no</wrap></action>
- </keybind>
- <keybind key="S-A-Left">
- <action name="SendToDesktopLeft"><wrap>no</wrap></action>
- </keybind>
- <keybind key="S-A-Right">
- <action name="SendToDesktopRight"><wrap>no</wrap></action>
- </keybind>
- <keybind key="S-A-Up">
- <action name="SendToDesktopUp"><wrap>no</wrap></action>
- </keybind>
- <keybind key="S-A-Down">
- <action name="SendToDesktopDown"><wrap>no</wrap></action>
- </keybind>
- <keybind key="C-A-d">
- <action name="ToggleShowDesktop"/>
- </keybind>
- <keybind key="A-F4">
- <action name="Close"/>
- </keybind>
- <keybind key="A-Tab">
- <action name="NextWindow"/>
- </keybind>
- <keybind key="A-S-Tab">
- <action name="PreviousWindow"/>
- </keybind>
- <keybind key="C-A-Tab">
- <action name="NextWindow"><panels>yes</panels></action>
- </keybind>
- <keybind key="C-A-S-Tab">
- <action name="PreviousWindow"><panels>yes</panels></action>
- </keybind>
- <keybind key="A-F7">
- <action name="Move"/>
- </keybind>
- <keybind key="A-F8">
- <action name="Resize"/>
- </keybind>
- <keybind key="A-F9">
- <action name="Iconify"/>
- </keybind>
- <keybind key="A-space">
- <action name="ShowMenu"><menu>client-menu</menu></action>
- </keybind>
-</keyboard>
-
-<mouse>
- <dragThreshold>3</dragThreshold>
- <doubleClickTime>200</doubleClickTime>
-
- <context name="Frame">
- <mousebind button="A-Left" action="Drag">
- <action name="Move"/>
- </mousebind>
- <mousebind button="A-Left" action="Click">
- <action name="Raise"/>
- </mousebind>
- <mousebind button="A-Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="A-Middle" action="Drag">
- <action name="Resize"/>
- </mousebind>
- <mousebind button="A-Middle" action="Click">
- <action name="Lower"/>
- </mousebind>
- <mousebind button="A-Right" action="Press">
- <action name="ShowMenu"><menu>client-menu</menu></action>
- </mousebind>
- <mousebind button="A-Up" action="Click">
- <action name="DesktopPrevious"/>
- </mousebind>
- <mousebind button="A-Down" action="Click">
- <action name="DesktopNext"/>
- </mousebind>
- <mousebind button="C-A-Up" action="Click">
- <action name="SendToDesktopPrevious"/>
- </mousebind>
- <mousebind button="C-A-Down" action="Click">
- <action name="SendToDesktopNext"/>
- </mousebind>
- </context>
- <context name="Titlebar">
- <mousebind button="Left" action="Drag">
- <action name="Move"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="Raise"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Left" action="DoubleClick">
- <action name="ToggleShade"/>
- </mousebind>
- <mousebind button="Middle" action="Press">
- <action name="Lower"/>
- </mousebind>
- <mousebind button="Up" action="Click">
- <action name="Shade"/>
- </mousebind>
- <mousebind button="Down" action="Click">
- <action name="Unshade"/>
- </mousebind>
- <mousebind button="Right" action="Press">
- <action name="ShowMenu"><menu>client-menu</menu></action>
- </mousebind>
- </context>
- <context name="Handle">
- <mousebind button="Left" action="Drag">
- <action name="Move"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="Raise"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Middle" action="Press">
- <action name="Lower"/>
- </mousebind>
- </context>
- <context name="BLCorner">
- <mousebind button="Left" action="Drag">
- <action name="Resize"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- </context>
- <context name="BRCorner">
- <mousebind button="Left" action="Drag">
- <action name="Resize"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- </context>
- <context name="TLCorner">
- <mousebind button="Left" action="Drag">
- <action name="Resize"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- </context>
- <context name="TRCorner">
- <mousebind button="Left" action="Drag">
- <action name="Resize"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- </context>
- <context name="Client">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- <action name="Raise"/>
- </mousebind>
- <mousebind button="Middle" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Right" action="Press">
- <action name="Focus"/>
- </mousebind>
- </context>
- <context name="Icon">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Right" action="Press">
- <action name="ShowMenu"><menu>client-menu</menu></action>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="ShowMenu"><menu>client-menu</menu></action>
- </mousebind>
- </context>
- <context name="AllDesktops">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="ToggleOmnipresent"/>
- </mousebind>
- </context>
- <context name="Shade">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="ToggleShade"/>
- </mousebind>
- </context>
- <context name="Iconify">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="Iconify"/>
- </mousebind>
- </context>
- <context name="Maximize">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Middle" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Right" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="ToggleMaximizeFull"/>
- </mousebind>
- <mousebind button="Middle" action="Click">
- <action name="ToggleMaximizeVert"/>
- </mousebind>
- <mousebind button="Right" action="Click">
- <action name="ToggleMaximizeHorz"/>
- </mousebind>
- </context>
- <context name="Close">
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- </mousebind>
- <mousebind button="Left" action="Click">
- <action name="Close"/>
- </mousebind>
- </context>
- <context name="Desktop">
- <mousebind button="Up" action="Press">
- <action name="DesktopPrevious"/>
- </mousebind>
- <mousebind button="Down" action="Press">
- <action name="DesktopNext"/>
- </mousebind>
- <mousebind button="A-Up" action="Press">
- <action name="DesktopPrevious"/>
- </mousebind>
- <mousebind button="A-Down" action="Press">
- <action name="DesktopNext"/>
- </mousebind>
- <mousebind button="Left" action="Press">
- <action name="Focus"/>
- <action name="Raise"/>
- </mousebind>
- <mousebind button="Middle" action="Press">
- <action name="ShowMenu"><menu>client-list-menu</menu></action>
- </mousebind>
- <mousebind button="Right" action="Press">
- <action name="ShowMenu"><menu>root-menu</menu></action>
- </mousebind>
- </context>
- <context name="MoveResize">
- <mousebind button="Up" action="Press">
- <action name="DesktopPrevious"/>
- </mousebind>
- <mousebind button="Down" action="Press">
- <action name="DesktopNext"/>
- </mousebind>
- <mousebind button="A-Up" action="Press">
- <action name="DesktopPrevious"/>
- </mousebind>
- <mousebind button="A-Down" action="Press">
- <action name="DesktopNext"/>
- </mousebind>
- </context>
-</mouse>
-
-<menu>
- <!-- You can specify more than one menu file in here and they are all loaded,
- just don't make menu ids clash or, well, it'll be kind of pointless -->
-
- <!-- default menu file (or custom one in $HOME/.config/openbox/) -->
- <file>menu.xml</file>
- <hideDelay>250</hideDelay>
- <middle>no</middle>
- <submenuShowDelay>0</submenuShowDelay>
- <applicationIcons>yes</applicationIcons>
-</menu>
-
-<!-- this section is commented out.. remove this and the ending comment if you
- want to use it -->
-<applications>
- <!-- the name or the class can be set, or both. this is used to match
- windows when they appear
-
- role can optionally be set, and only as much as you provide will be
- checked to see if it matches, eg. if you set role="abc" and the window's
- role is actually "abcde" it would match.
- -->
- <application name="first element of window's WM_CLASS property (see xprop)"
- class="second element of window's WM_CLASS property (see xprop)"
- role="the window's WM_WINDOW_ROLE property (see xprop)">
-
- <!-- each element can be left out or set to 'default' to specify to not
- change that attribute of the window -->
-
- <decor>yes</decor>
-
- <shade>no</shade>
-
- <position>
- <!-- the position is only used if both an x and y coordinate are provided
- (and not set to 'default') -->
- <x>center</x>
- <!-- a number or 'center' to center on screen -->
- <y>200</y>
- <!-- a number or 'center' to center on screen -->
- <monitor>1</monitor>
- <!-- specifies the monitor in a xinerama setup.
- 1 is the first head, or 'mouse' for wherever the mouse is -->
- </position>
-
- <focus>yes</focus>
- <!-- if the window should try be given focus when it appears -->
-
- <desktop>1</desktop>
- <!-- 1 is the first desktop, 'all' for all desktops -->
-
- <layer>normal</layer>
- <!-- 'above', 'normal', or 'below' -->
-
- <iconic>no</iconic>
-
- <skip_pager>no</skip_pager>
- <!-- asks to not be shown in pagers -->
-
- <skip_taskbar>no</skip_taskbar>
- <!-- asks to not be shown in taskbars. window cycling actions will also
- skip past such windows -->
-
- <fullscreen>yes</fullscreen>
-
- <maximized>true</maximized>
- <!-- 'Horizontal', 'Vertical' or boolean (yes/no/on/off/true/false) -->
- </application>
-</applications>
- -->
-
-</openbox_config>
+++ /dev/null
-#!/bin/sh
-
-# A temporary script to be replaced by a real program..
-exec openbox --restart-binary openbox-gnome "$@"
+++ /dev/null
-#!/bin/sh
-
-# Run GNOME with Openbox as its window manager
-export WINDOW_MANAGER=openbox-gnome
-exec gnome-session "$@"
+++ /dev/null
-#!/bin/sh
-
-# A temporary script to be replaced by a real program..
-exec openbox --restart-binary openbox-kde "$@"
+++ /dev/null
-#!/bin/sh
-
-# Run KDE with Openbox as its window manager
-export KDEWM=openbox-kde
-exec startkde "$@"
raised to the top. Legacy begets legacy I guess?
*/
if (!client_restore_session_stacking(self))
- client_raise(self);
+ stacking_raise(CLIENT_AS_WINDOW(self));
}
/* this has to happen before we try focus the window, but we want it to
for (it = self->transients; it; it = g_slist_next(it))
client_calc_layer_recursive(it->data, orig,
self->layer,
- raised ? raised : self->layer != old);
+ raised ? raised : self->layer > old);
- if (!raised && self->layer != old)
- if (orig->frame) { /* only restack if the original window is managed */
+ /* restack. but only if the original window is managed.
+
+ raised is used so that only the bottom-most window in the stacking
+ order is raised, the others will automatically come with it.
+
+ also only the highest windows in the stacking order (no transients)
+ are lowered, cuz the rest come for free
+ */
+ if (!raised && orig->frame) {
+ if (self->layer > old) {
+ stacking_remove(CLIENT_AS_WINDOW(self));
+ stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
+ } else if (self->layer < old && self->transients == NULL) {
stacking_remove(CLIENT_AS_WINDOW(self));
- stacking_add(CLIENT_AS_WINDOW(self));
+ stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
}
+ }
}
void client_calc_layer(ObClient *self)
client_showhide(self);
/* raise if it was not already on the desktop */
if (old != DESKTOP_ALL)
- client_raise(self);
+ stacking_raise(CLIENT_AS_WINDOW(self));
if (STRUT_EXISTS(self->strut))
screen_update_areas();
}
self->modal = modal;
/* when a window changes modality, then its stacking order with its
transients needs to change */
- client_raise(self);
+ stacking_raise(CLIENT_AS_WINDOW(self));
}
if (iconic != self->iconic)
client_iconify(self, iconic, FALSE);
return;
if (self->shaded)
client_shade(self, FALSE);
+ if (raise)
+ stacking_raise(CLIENT_AS_WINDOW(self));
client_focus(self);
-
- if (raise) {
- /* we do this as an action here. this is rather important. this is
- because we want the results from the focus change to take place
- BEFORE we go about raising the window. when a fullscreen window
- loses focus, we need this or else the raise wont be able to raise
- above the to-lose-focus fullscreen window. */
- client_raise(self);
- }
}
void client_activate(ObClient *self, gboolean here, gboolean user)
client_bring_helper_windows_recursive(self, self->desktop);
}
-void client_raise(ObClient *self)
-{
- action_run_string("Raise", self, CurrentTime);
-}
-
-void client_lower(ObClient *self)
-{
- action_run_string("Lower", self, CurrentTime);
-}
-
gboolean client_focused(ObClient *self)
{
return self == focus_client;
/*! Calculates the stacking layer for the client window */
void client_calc_layer(ObClient *self);
-/*! Raises the client to the top of its stacking layer
- Normally actions call to the client_* functions to make stuff go, but this
- one is an exception. It just fires off an action, which will be queued.
- This is because stacking order rules can be changed by focus state, and so
- any time focus changes you have to wait for it to complete before you can
- properly restart windows. As such, this only queues an action for later
- execution, once the focus change has gone through.
-*/
-void client_raise(ObClient *self);
-
-/*! Lowers the client to the bottom of its stacking layer
- Normally actions call to the client_* functions to make stuff go, but this
- one is an exception. It just fires off an action, which will be queued.
- This is because stacking order rules can be changed by focus state, and so
- any time focus changes you have to wait for it to complete before you can
- properly restart windows. As such, this only queues an action for later
- execution, once the focus change has gone through.
-*/
-void client_lower(ObClient *self);
-
/*! Updates the window's transient status, and any parents of it */
void client_update_transient_for(ObClient *self);
/*! Update the protocols that the window supports and adjusts things if they
}
if (e->xconfigurerequest.value_mask & CWStackMode) {
- switch (e->xconfigurerequest.detail) {
- case Below:
- case BottomIf:
- /* Apps are so rude. And this is totally disconnected from
- activation/focus. Bleh. */
- /*client_lower(client);*/
- break;
-
- case Above:
- case TopIf:
- default:
- /* Apps are so rude. And this is totally disconnected from
- activation/focus. Bleh. */
- /*client_raise(client);*/
- break;
+ ObClient *sibling = NULL;
+
+ /* get the sibling */
+ if (e->xconfigurerequest.value_mask & CWSibling) {
+ ObWindow *win;
+ win = g_hash_table_lookup(window_map,
+ &e->xconfigurerequest.above);
+ if (WINDOW_IS_CLIENT(win) && WINDOW_AS_CLIENT(win) != client)
+ sibling = WINDOW_AS_CLIENT(win);
}
+
+ /* activate it rather than just focus it */
+ stacking_restack_request(client, sibling,
+ e->xconfigurerequest.detail, TRUE);
}
break;
case UnmapNotify:
client_convert_gravity(client, grav, &x, &y, w, h);
client_find_onscreen(client, &x, &y, w, h, FALSE);
client_configure(client, x, y, w, h, FALSE, TRUE);
+ } else if (msgtype == prop_atoms.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",
+ 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]);
+ if (WINDOW_IS_CLIENT(win) &&
+ WINDOW_AS_CLIENT(win) != client)
+ {
+ sibling = WINDOW_AS_CLIENT(win);
+ }
+ if (sibling == NULL)
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "_NET_RESTACK_WINDOW sent for window %s "
+ "with invalid sibling 0x%x\n",
+ client->title, e->xclient.data.l[1]);
+ }
+ if (e->xclient.data.l[2] == Below ||
+ e->xclient.data.l[2] == BottomIf ||
+ e->xclient.data.l[2] == Above ||
+ e->xclient.data.l[2] == TopIf ||
+ e->xclient.data.l[2] == Opposite)
+ {
+ /* just raise, don't activate */
+ stacking_restack_request(client, sibling,
+ e->xclient.data.l[2], FALSE);
+ } else
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "_NET_RESTACK_WINDOW sent for window %s "
+ "with invalid detail %d\n",
+ client->title, e->xclient.data.l[2]);
+ }
}
break;
case PropertyNotify:
event_curtime = d->time;
if (focus_client != d->client) {
if (client_focus(d->client) && config_focus_raise)
- client_raise(d->client);
+ stacking_raise(CLIENT_AS_WINDOW(d->client));
}
event_curtime = old;
return FALSE; /* no repeat */
px = e->xbutton.x_root;
py = e->xbutton.y_root;
- if (pwx == -1) pwx = e->xbutton.x;
- if (pwy == -1) pwy = e->xbutton.y;
+ if (!button) pwx = e->xbutton.x;
+ if (!button) pwy = e->xbutton.y;
button = e->xbutton.button;
state = e->xbutton.state;
context = frame_context(client, e->xbutton.window, pwx, pwy);
context = mouse_button_frame_context(context, e->xbutton.button);
- pwx = pwy = -1;
+ if (e->xbutton.button == button)
+ pwx = pwy = -1;
if (e->xbutton.button == button) {
/* clicks are only valid if its released over the window */
fire_binding(OB_MOUSE_ACTION_RELEASE, context,
client, e->xbutton.state,
e->xbutton.button,
- e->xbutton.x_root, e->xbutton.y_root,
+ e->xbutton.x_root,
+ e->xbutton.y_root,
e->xbutton.time);
if (click)
fire_binding(OB_MOUSE_ACTION_CLICK, context,
context = frame_context(client, e->xmotion.window, pwx, pwy);
context = mouse_button_frame_context(context, button);
- if (ABS(e->xmotion.x_root - px) >=
- config_mouse_threshold ||
- ABS(e->xmotion.y_root - py) >=
- config_mouse_threshold) {
+ if (ABS(e->xmotion.x_root - px) >= config_mouse_threshold ||
+ ABS(e->xmotion.y_root - py) >= config_mouse_threshold) {
/* You can't drag on buttons */
if (context == OB_FRAME_CONTEXT_MAXIMIZE ||
{
gint i;
- for (i = index; i < index + num; ++i)
+ for (i = index; i < *argc - num; ++i)
argv[i] = argv[i+num];
for (; i < *argc; ++i)
argv[i] = NULL;
if (!strcmp(argv[i], "--version")) {
print_version();
exit(0);
- } else if (!strcmp(argv[i], "--help")) {
+ }
+ else if (!strcmp(argv[i], "--help")) {
print_help();
exit(0);
- } else if (!strcmp(argv[i], "--g-fatal-warnings")) {
+ }
+ else if (!strcmp(argv[i], "--g-fatal-warnings")) {
g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
- } else if (!strcmp(argv[i], "--replace")) {
+ }
+ else if (!strcmp(argv[i], "--replace")) {
ob_replace_wm = TRUE;
- } else if (!strcmp(argv[i], "--sync")) {
+ remove_args(argc, argv, i, 1);
+ --i; /* this arg was removed so go back */
+ }
+ else if (!strcmp(argv[i], "--sync")) {
xsync = TRUE;
- } else if (!strcmp(argv[i], "--debug")) {
+ }
+ else if (!strcmp(argv[i], "--debug")) {
ob_debug_show_output(TRUE);
ob_debug_enable(OB_DEBUG_SM, TRUE);
ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
- } else if (!strcmp(argv[i], "--debug-focus")) {
+ }
+ 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], "--reconfigure")) {
+ }
+ else if (!strcmp(argv[i], "--reconfigure")) {
remote_control = 1;
/* don't make this do anything if it's not in --help ..
} else if (!strcmp(argv[i], "--restart")) {
remote_control = 2;
*/
- } else if (!strcmp(argv[i], "--config")) {
+ }
+ else if (!strcmp(argv[i], "--config")) {
if (i == *argc - 1) /* no args left */
g_printerr(_("--config requires an argument\n"));
else {
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_sm_save_file);
}
- } else if (!strcmp(argv[i], "--sm-client-id")) {
+ }
+ else if (!strcmp(argv[i], "--sm-client-id")) {
if (i == *argc - 1) /* no args left */
/* not translated cuz it's sekret */
g_printerr("--sm-client-id requires an argument\n");
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);
}
- } else if (!strcmp(argv[i], "--sm-disable")) {
+ }
+ else if (!strcmp(argv[i], "--sm-disable")) {
ob_sm_use = FALSE;
}
#endif
- else if (!strcmp(argv[i], "--restart-binary")) {
- if (i == *argc - 1) /* no args left */
- /* not translated cuz it's sekret */
- g_printerr("--restart-binary requires an argument\n");
- else {
- argv[0] = g_strdup(argv[i+1]);
- remove_args(argc, argv, i, 2);
- --i; /* this arg was removed so go back */
- }
- } else {
+ else {
/* this is a memleak.. oh well.. heh */
gchar *err = g_strdup_printf
("Invalid command line argument '%s'\n", argv[i]);
CREATE(net_close_window, "_NET_CLOSE_WINDOW");
CREATE(net_wm_moveresize, "_NET_WM_MOVERESIZE");
CREATE(net_moveresize_window, "_NET_MOVERESIZE_WINDOW");
+ CREATE(net_request_frame_extents, "_NET_REQUEST_FRAME_EXTENTS");
+ CREATE(net_restack_window, "_NET_RESTACK_WINDOW");
CREATE(net_startup_id, "_NET_STARTUP_ID");
CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW");
CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT");
CREATE(net_frame_extents, "_NET_FRAME_EXTENTS");
- CREATE(net_request_frame_extents, "_NET_REQUEST_FRAME_EXTENTS");
/* CREATE(net_wm_ping, "_NET_WM_PING"); */
#ifdef SYNC
Atom net_close_window;
Atom net_wm_moveresize;
Atom net_moveresize_window;
+ Atom net_request_frame_extents;
+ Atom net_restack_window;
/* helpful hints to apps that aren't used for anything */
Atom net_wm_full_placement;
Atom net_wm_user_time;
Atom net_wm_user_time_window;
Atom net_frame_extents;
- Atom net_request_frame_extents;
/* application protocols */
/* Atom net_wm_ping; */
if (!resist) return;
+ frame_client_gravity(c->frame, x, y, c->area.width, c->area.height);
+
w = c->frame->area.width;
h = c->frame->area.height;
if (snapx && snapy) break;
}
+
+ frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height);
}
void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
if (!resist) return;
+ frame_client_gravity(c->frame, x, y, c->area.width, c->area.height);
+
w = c->frame->area.width;
h = c->frame->area.height;
else if (cb <= pb && b > pb && b < pb + resist)
*y = pb - h + 1;
}
+
+ frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height);
}
void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h,
#include <glib.h>
+/*! @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
+*/
void resist_move_windows(struct _ObClient *c, gint resist, gint *x, gint *y);
+/*! @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
+*/
void resist_move_monitors(struct _ObClient *c, gint resist, gint *x, gint *y);
void resist_size_windows(struct _ObClient *c, gint resist, gint *w, gint *h,
ObCorner corn);
supported[i++] = prop_atoms.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;
#ifdef SYNC
supported[i++] = prop_atoms.net_wm_sync_request;
if (sm_conn) {
/* if permanent is true then we will change our session state so that
the SM won't run us again */
- session_setup_restart_style(!permanent);
+ if (permanent)
+ session_setup_restart_style(FALSE);
SmcCloseConnection(sm_conn, 0, NULL);
&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);
if (sm_conn == NULL)
ob_debug("Failed to connect to session manager: %s\n", sm_err);
return sm_conn != NULL;
.vals = &vals
};
SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting program: %s\n", sm_argv[0]);
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
.vals = &vals
};
SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting user: %s\n", user);
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
static void session_setup_restart_style(gboolean restart)
{
- char restart_hint = restart ? SmRestartImmediately : SmRestartIfRunning;
+ gchar restart_hint = restart ? SmRestartImmediately : SmRestartIfRunning;
SmPropValue vals = {
.value = &restart_hint,
.vals = &vals
};
SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting restart: %d\n", restart);
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
.vals = &vals
};
SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting pid: %s\n", pid);
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
.vals = &vals
};
SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting priority: %d\n", priority);
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
.num_vals = sm_argc,
.vals = vals
};
+ SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting clone command: (%d)\n", 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);
}
- SmProp *list = ∝
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
.num_vals = sm_argc + 4,
.vals = vals
};
+ SmProp *list = ∝
+ ob_debug_type(OB_DEBUG_SM, "Setting restart command: (%d)\n", 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);
}
- vals[i].value = g_strdup("--sm-save-file");
- vals[i].length = strlen("--sm-save-file") + 1;
- vals[i+1].value = ob_sm_save_file;
- vals[i+1].length = strlen(ob_sm_save_file) + 1;
+ 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);
- vals[i+2].value = g_strdup("--sm-client-id");
- vals[i+2].length = strlen("--sm-client-id") + 1;
- vals[i+3].value = ob_sm_id;
- vals[i+3].length = strlen(ob_sm_id) + 1;
+ 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);
- SmProp *list = ∝
SmcSetProperties(sm_conn, 1, &list);
g_free(prop.name);
g_free(prop.type);
#include "group.h"
#include "frame.h"
#include "window.h"
+#include "debug.h"
GList *stacking_list = NULL;
/* insert above its highest parent (or its highest child !) */
it_below = find_highest_relative(client);
- if (!it_below) {
+ if (!it_below && client != focus_client) {
/* nothing to put it directly above, so try find the focused client to
put it underneath it */
if (focus_client && focus_client->layer == client->layer) {
}
}
if (!it_below) {
- /* there is no window to put this directly above, so put it at the
- bottom */
- stacking_list = g_list_prepend(stacking_list, win);
- stacking_lower(win);
+ if (client == focus_client) {
+ /* it's focused so put it at the top */
+ stacking_list = g_list_append(stacking_list, win);
+ stacking_raise(win);
+ } else {
+ /* there is no window to put this directly above, so put it at the
+ bottom */
+ stacking_list = g_list_prepend(stacking_list, win);
+ stacking_lower(win);
+ }
} else {
/* make sure it's not in the wrong layer though ! */
for (; it_below; it_below = g_list_next(it_below))
g_list_free(wins);
}
}
+
+/*! Returns TRUE if client is occluded by the sibling. If sibling is NULL it
+ tries against all other clients.
+*/
+static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
+{
+ GList *it;
+ gboolean occluded = FALSE;
+ gboolean found = FALSE;
+
+ /* no need for any looping in this case */
+ if (sibling && client->layer != sibling->layer)
+ return occluded;
+
+ for (it = stacking_list; it;
+ it = (found ? g_list_previous(it) :g_list_next(it)))
+ if (WINDOW_IS_CLIENT(it->data)) {
+ ObClient *c = it->data;
+ if (found) {
+ if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area))
+ {
+ if (sibling != NULL) {
+ if (c == sibling) {
+ occluded = TRUE;
+ break;
+ }
+ }
+ else if (c->layer == client->layer) {
+ occluded = TRUE;
+ break;
+ }
+ else if (c->layer > client->layer)
+ break; /* we past its layer */
+ }
+ }
+ else if (c == client)
+ found = TRUE;
+ }
+ return occluded;
+}
+
+/*! Returns TRUE if client is occludes the sibling. If sibling is NULL it tries
+ against all other clients.
+*/
+static gboolean stacking_occludes(ObClient *client, ObClient *sibling)
+{
+ GList *it;
+ gboolean occludes = FALSE;
+ gboolean found = FALSE;
+
+ /* no need for any looping in this case */
+ if (sibling && client->layer != sibling->layer)
+ return occludes;
+
+ for (it = stacking_list; it; it = g_list_next(it))
+ if (WINDOW_IS_CLIENT(it->data)) {
+ ObClient *c = it->data;
+ if (found) {
+ if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area))
+ {
+ if (sibling != NULL) {
+ if (c == sibling) {
+ occludes = TRUE;
+ break;
+ }
+ }
+ else if (c->layer == client->layer) {
+ occludes = TRUE;
+ break;
+ }
+ else if (c->layer > client->layer)
+ break; /* we past its layer */
+ }
+ }
+ else if (c == client)
+ found = TRUE;
+ }
+ return occludes;
+}
+
+void stacking_restack_request(ObClient *client, ObClient *sibling,
+ gint detail, gboolean activate)
+{
+ switch (detail) {
+ case Below:
+ ob_debug("Restack request Below for client %s sibling %s\n",
+ client->title, sibling ? sibling->title : "(all)");
+ /* just lower it */
+ stacking_lower(CLIENT_AS_WINDOW(client));
+ break;
+ case BottomIf:
+ ob_debug("Restack request BottomIf for client %s sibling "
+ "%s\n",
+ client->title, sibling ? sibling->title : "(all)");
+ /* if this client occludes sibling (or anything if NULL), then
+ lower it to the bottom */
+ if (stacking_occludes(client, sibling))
+ stacking_lower(CLIENT_AS_WINDOW(client));
+ break;
+ case Above:
+ ob_debug("Restack request Above for client %s sibling %s\n",
+ client->title, sibling ? sibling->title : "(all)");
+ if (activate)
+ /* use user=TRUE because it is impossible to get a timestamp
+ for this */
+ client_activate(client, FALSE, TRUE);
+ else
+ stacking_raise(CLIENT_AS_WINDOW(client));
+ break;
+ case TopIf:
+ ob_debug("Restack request TopIf for client %s sibling %s\n",
+ client->title, sibling ? sibling->title : "(all)");
+ if (stacking_occluded(client, sibling)) {
+ if (activate)
+ /* use user=TRUE because it is impossible to get a timestamp
+ for this */
+ client_activate(client, FALSE, TRUE);
+ else
+ stacking_raise(CLIENT_AS_WINDOW(client));
+ }
+ break;
+ case Opposite:
+ ob_debug("Restack request Opposite for client %s sibling "
+ "%s\n",
+ client->title, sibling ? sibling->title : "(all)");
+ if (stacking_occluded(client, sibling)) {
+ if (activate)
+ /* use user=TRUE because it is impossible to get a timestamp
+ for this */
+ client_activate(client, FALSE, TRUE);
+ else
+ stacking_raise(CLIENT_AS_WINDOW(client));
+ }
+ else if (stacking_occludes(client, sibling))
+ stacking_lower(CLIENT_AS_WINDOW(client));
+ break;
+ }
+}
*/
void stacking_below(ObWindow *window, ObWindow *below);
+/*! Restack a window based upon a sibling (or all windows) in various ways.
+ @param client The client to be restacked
+ @param sibling Another client to compare to, or NULL to compare to all
+ windows
+ @param detail One of Above, Below, TopIf, BottomIf, Opposite
+ @param activate If TRUE, and if the window is going to be raised, it will
+ be activated instead
+ See http://tronche.com/gui/x/xlib/window/configure.html for details on
+ how each detail works with and without a sibling.
+*/
+void stacking_restack_request(struct _ObClient *client,
+ struct _ObClient *sibling,
+ gint detail, gboolean);
+
#endif