Project

General

Profile

unexist.dev

/

subtle

Assorted tidbits and projects

Hacking » History » Version 95

Anonymous, 03/23/2011 10:23 PM

1 95
h1. Hacking\015\012\015\012The following information is for people who are interested in [[subtle]]'s internals and/or like to play around and extend [[subtle]]. If you have problems with a certain client or discover an odd behaviour, feel free to add to the [[blamelist]].\015\012\015\012{{>toc}}\015\012\015\012h2. RDoc documentation\015\012\015\012The latest "rdoc":http://rdoc.sourceforge.net documention can either be found "here":http://rdoc.subforge.org or be generated from the source tree:\015\012\015\012<pre><code>rake rdoc</code></pre>\015\012\015\012h2. Unit testing\015\012\015\012Testing a window manager is a difficult task, currently the unit tests consist of a bunch of "riot":https://github.com/thumblemonks/riot contexts and a script to run "Xvfb":http://en.wikipedia.org/wiki/Xvfb.\015\012\015\012Requirements:\015\012# "riot":https://github.com/thumblemonks/riot\015\012# "Xvfb":http://en.wikipedia.org/wiki/Xvfb\015\012# "xterm":http://en.wikipedia.org/wiki/Xterm\015\012\015\012Run tests:\015\012\015\012<pre><code>cd test\015\012ruby ./xserver.rb &\015\012ruby ./test.rb\015\012\015\012...\015\012\015\01268 passes, 0 failures, 0 errors in 18.540124 seconds\015\012</code></pre>\015\012\015\012h2. Loglevel\015\012\015\012[[subtle]] uses a loglevel system to distinguish between messages and to be able to turn certain messages off. \015\012\015\012Following levels exist:\015\012\015\012|_. Name     |_. Messages                       |\015\012| warnings   | Warning messages                 |\015\012| sublet     | [[sublets|Sublet]] warnings      |\015\012| error      | Error messages                   |\015\012| deprecated | Deprecation warnings             |\015\012| events     | Information about handled events |\015\012| ruby       | Ruby debugging messages          |\015\012| xerror     | X11 error messages               |\015\012| subtlext   | Debugging messages of subtlext   |\015\012| subtle     | Subsystem messages of subtle     |\015\012| debug      | General debugging messages       |\015\012\015\012The level can be set with the *&#45;l* or *&#45;&#45;level=* options, multiple values are comma separated without any whitespace.\015\012\015\012<pre><code>subtle -l ruby,subtlext\015\012subtle --level=ruby,subtlext\015\012</code></pre>\015\012\015\012h2. EWMH/ICCCM specifications\015\012\015\012Here are all "EWMH/NetWM":http://standards.freedesktop.org/wm-spec properties listed, that are supported by [[subtle]] and [[subtlext]].\015\012\015\012h3. Default\015\012\015\012h4. _NET_NUMBER_OF_DESKTOPS\015\012\015\012Get the number of views.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_DESKTOP_NAMES\015\012\015\012Get a list of all view names.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_CURRENT_DESKTOP\015\012\015\012Change or get current desktop\015\012\015\012h5. Root property\015\012\015\012Get current desktop\015\012\015\012h5. Client message\015\012\015\012Set current desktop\015\012\015\012<pre><code class="ruby">\015\012data.l[0] = <View id>\015\012data.l[1] = <Timestamp>\015\012data.l[2] = <Screen id>[1]\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012fn1. [[subtle]] extension\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_ACTIVE_WINDOW\015\012\015\012h5. Root property\015\012\015\012Get current[1] active window\015\012\015\012fn1. [[subtle]] returns the five recent active windows\015\012\015\012h5. Client message\015\012\015\012Set current active window\015\012\015\012<pre><code class="ruby">\015\012data.l[0] = <Window id>\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_RESTACK_WINDOW\015\012\015\012Change stacking of window\015\012<pre><code class="ruby">\015\012data.l[0] = <Ignored>\015\012data.l[1] = <Client id>\015\012data.l[2] = <Detail>\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012*Detail*: 0 = Above (raise), 1 = Below (lower)\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_MOVERESIZE_WINDOW\015\012\015\012Resize window\015\012<pre><code class="ruby">\015\012data.l[0] = <Ignored>\015\012data.l[1] = <x>\015\012data.l[2] = <y>\015\012data.l[3] = <width>\015\012data.l[4] = <height>\015\012</code></pre>\015\012\015\012Move/resize a window.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_CLOSE_WINDOW\015\012\015\012Close client window\015\012<pre><code class="ruby">\015\012data.l[0] = <Timestamp>\015\012data.l[1] = <Ignored>\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012Ask [[subtle]] to close a window.\015\012\015\012[[Development#1|top]]\015\012\015\012h3. WM State\015\012\015\012Normally there are three types of actions: +remove+ (0), +add+ (1) and +toggle+ (2), but we _always_ toggle the states independent of the supplied action. The second property will be ignored.\015\012\015\012h4. _NET_WM_STATE_FULLSCREEN\015\012\015\012Toggle client fullscreen\015\012<pre><code class="ruby">\015\012data.l[0] = <Action>\015\012data.l[1] = _NET_WM_STATE_FULLSCREEN\015\012data.l[2] = <Ignored>\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012Set fullscreen state of a window.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_WM_STATE_ABOVE\015\012\015\012Toggle client float\015\012<pre><code class="ruby">\015\012data.l[0] = <Action>\015\012data.l[1] = _NET_WM_STATE_ABOVE\015\012data.l[2] = <Ignored>\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012Set floating state of a window.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_WM_STATE_STICKY\015\012\015\012Toggle client urgent\015\012<pre><code class="ruby">\015\012data.l[0] = <Action>\015\012data.l[1] = _NET_WM_STATE_STICKY\015\012data.l[2] = <Ignored>\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012Set sticky mode of a window.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_WM_STATE_DEMANDS_ATTENTION\015\012\015\012Toggle client urgent\015\012<pre><code class="ruby">\015\012data.l[0] = <Action>\015\012data.l[1] = _NET_WM_STATE_DEMANDS_ATTENTION\015\012data.l[2] = <Ignored>\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012Set urgency of a window.\015\012\015\012[[Development#1|top]]\015\012\015\012h3. Tray\015\012\015\012h4. MANAGER\015\012\015\012Inform clients about a new selection manager.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_SYSTEM_TRAY_OPCODE\015\012\015\012Used for communication between embedder and client.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_SYSTEM_TRAY_MESSAGE_DATA\015\012\015\012Used for communication between embedder and client.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. _NET_SYSTEM_TRAY_S\015\012\015\012Screen tray selection.\015\012\015\012[[Development#1|top]]\015\012\015\012h3. _XEMBED\015\012\015\012h4. _XEMBED_INFO\015\012\015\012XEmbed protocol info.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. XEMBED_EMBEDDED_NOTIFY\015\012\015\012Notification to start embedding cycle.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. XEMBED_WINDOW_ACTIVATE\015\012\015\012NormalState for embedded clients.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. XEMBED_WINDOW_DEACTIVATE\015\012\015\012WithdrawnState for embedded clients.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. XEMBED_REQUEST_FOCUS\015\012\015\012Notification of the client for embedder to pass focus.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. XEMBED_FOCUS_IN\015\012\015\012Notification when client can take focus.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. XEMBED_FOCUS_OUT\015\012\015\012Notification when client lost focus.\015\012\015\012[[Development#1|top]]\015\012\015\012h3. Subtle extension\015\012\015\012h4. SUBTLE_CLIENT_TAGS\015\012\015\012Set the tags of a client.\015\012<pre><code class="ruby">\015\012data.l[0] = <Client id>\015\012data.l[1] = <Tag bitmask>\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_CLIENT_GRAVITY\015\012\015\012Set client [[gravity]]\015\012<pre><code class="ruby">\015\012data.l[0] = <Client id>\015\012data.l[1] = <Gravity id>\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_CLIENT_FLAGS\015\012\015\012Set client flags\015\012<pre><code class="ruby">\015\012data.l[0] = <Client id>\015\012data.l[1] = <Flags>\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012The bits in *flags* have the following meaning:\015\012\015\012| Bit | Description |\015\012| 1   | Fullscreen  | \015\012| 2   | Floating    |\015\012| 3   | Sticky      |\015\012| 4   | Resize      |\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_GRAVITY_NEW\015\012\015\012Create a new [[gravity]] mode\015\012<pre><code class="ruby">\015\012data.b[0-20] = <Gravity x>x<Gravity y>+<Gravity width>+<Gravity height>#<Gravity name>\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_GRAVITY_LIST\015\012\015\012Get a [[gravity]] mode list\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_GRAVITY_KILL\015\012\015\012Kill a gravity\015\012<pre><code class="ruby">\015\012data.l[0] = <Gravity id>\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_TAG_NEW\015\012\015\012Create a new [[tags|tag]]\015\012<pre><code class="ruby">\015\012data.b[0-20] = <Tag name>\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_TAG_LIST\015\012\015\012Get a [[tags|tag]] list\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_TAG_KILL\015\012\015\012Kill a [[tags|tag]]\015\012<pre><code class="ruby">\015\012data.l[0] = <Tag id>\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_VIEW_NEW\015\012\015\012Create a new [[views|view]]\015\012<pre><code class="ruby">\015\012data.b[0-20] = <View name>\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_VIEW_TAGS\015\012\015\012h5. Root property\015\012\015\012Get a list of all [[tags]].\015\012\015\012h5. Client message\015\012\015\012Set tags of [[views]].\015\012<pre><code class="ruby">\015\012data.l[0] = <View id>\015\012data.l[1] = <Tag mask>\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012h4. SUBTLE_VIEW_KILL\015\012\015\012Kill a [[views|view]]\015\012<pre><code class="ruby">\015\012data.l[0] = <View id>\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_SUBLET_NEW\015\012\015\012Load a [[sublets|sublet]] from _$XDG_DATA_HOME/subtle/sublets_\015\012<pre><code class="ruby">\015\012data.b[0-20] = <Sublet filename>\015\012</code></pre>\015\012\015\012h4. SUBTLE_SUBLET_UPDATE\015\012\015\012Force update of a [[sublets|sublet]]\015\012<pre><code class="ruby">\015\012data.l[0] = <Sublet id>\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_SUBLET_DATA\015\012\015\012Set data field of [[sublets|sublet]]\015\012<pre><code class="ruby">\015\012data.l[0] = <Sublet id>\015\012</code></pre>\015\012\015\012After receiving of this client message, [[subtle]] checkes the [[Hacking#SUBTLE_DATA|SUBTLE_DATA]] property on the root display and copies the data.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_SUBLET_LIST\015\012\015\012Get [[sublets|sublet]] list\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_SUBLET_KILL\015\012\015\012Kill a [[sublets|sublet]]\015\012<pre><code class="ruby">\015\012data.l[0] = <Sublet id>\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_SCREEN_VIEWS\015\012\015\012List of views in screen order that are visible.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_VISIBLE_TAGS\015\012\015\012Bitfield of all visible tags on all screens.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_VISIBLE_VIEWS\015\012\015\012Bitfield of all visible views on all screens.\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_RELOAD\015\012\015\012Force reload of config and sublets.\015\012<pre><code class="ruby">\015\012data.l[0] = 0\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_RESTART\015\012\015\012Force full restart.\015\012<pre><code class="ruby">\015\012data.l[0] = 0\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_QUIT\015\012\015\012Force quit.\015\012<pre><code class="ruby">\015\012data.l[0] = 0\015\012data.l[1] = 0\015\012data.l[2] = 0\015\012data.l[3] = 0\015\012data.l[4] = 0\015\012</code></pre>\015\012\015\012[[Development#1|top]]\015\012\015\012h4. SUBTLE_COLORS\015\012\015\012Get a color list.\015\012\015\012h4. SUBTLE_DATA\015\012\015\012Property to exchange data.\015\012\015\012[[Development#1|top]]\015\012