<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <!--Converted with LaTeX2HTML 2002-2-1 (1.71) original version by: Nikos Drakos, CBLU, University of Leeds * revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan * with significant contributions from: Jens Lippmann, Marek Rouchal, Martin Wilck and others --> <HTML> <HEAD> <TITLE>3. Basic configuration</TITLE> <META NAME="description" CONTENT="3. Basic configuration"> <META NAME="keywords" CONTENT="ionconf"> <META NAME="resource-type" CONTENT="document"> <META NAME="distribution" CONTENT="global"> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> <META NAME="Generator" CONTENT="LaTeX2HTML v2002-2-1"> <META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> <LINK REL="STYLESHEET" HREF="ionconf.css"> <LINK REL="next" HREF="node5.html"> <LINK REL="previous" HREF="node3.html"> <LINK REL="up" HREF="ionconf.html"> <LINK REL="next" HREF="node5.html"> </HEAD> <BODY > <!--Navigation Panel--> <A NAME="tex2html273" HREF="node5.html"> <IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" SRC="next.png"></A> <A NAME="tex2html267" HREF="ionconf.html"> <IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" SRC="up.png"></A> <A NAME="tex2html261" HREF="node3.html"> <IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" SRC="prev.png"></A> <A NAME="tex2html269" HREF="node1.html"> <IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" SRC="contents.png"></A> <A NAME="tex2html271" HREF="node11.html"> <IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index" SRC="index.png"></A> <BR> <B> Next:</B> <A NAME="tex2html274" HREF="node5.html">4. Graphical styles</A> <B> Up:</B> <A NAME="tex2html268" HREF="ionconf.html">Configuring and extending Ion3</A> <B> Previous:</B> <A NAME="tex2html262" HREF="node3.html">2. Preliminaries: Key concepts</A> <B> <A NAME="tex2html270" HREF="node1.html">Contents</A></B> <B> <A NAME="tex2html272" HREF="node11.html">Index</A></B> <BR> <BR> <!--End of Navigation Panel--> <!--Table of Child-Links--> <A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></A> <UL> <LI><A NAME="tex2html275" HREF="node4.html#SECTION00410000000000000000">3.1 The configuration files</A> <LI><A NAME="tex2html276" HREF="node4.html#SECTION00420000000000000000">3.2 A walk through <I>cfg_ion.lua</I></A> <LI><A NAME="tex2html277" HREF="node4.html#SECTION00430000000000000000">3.3 Keys and rodents</A> <UL> <LI><A NAME="tex2html278" HREF="node4.html#SECTION00431000000000000000">3.3.1 Binding handlers and special variables</A> <LI><A NAME="tex2html279" HREF="node4.html#SECTION00432000000000000000">3.3.2 Guards</A> <LI><A NAME="tex2html280" HREF="node4.html#SECTION00433000000000000000">3.3.3 Defining the bindings</A> <LI><A NAME="tex2html281" HREF="node4.html#SECTION00434000000000000000">3.3.4 Examples</A> <LI><A NAME="tex2html282" HREF="node4.html#SECTION00435000000000000000">3.3.5 Key specifications</A> <LI><A NAME="tex2html283" HREF="node4.html#SECTION00436000000000000000">3.3.6 Button specifications</A> <LI><A NAME="tex2html284" HREF="node4.html#SECTION00437000000000000000">3.3.7 A further note on the default binding configuration</A> <LI><A NAME="tex2html285" HREF="node4.html#SECTION00438000000000000000">3.3.8 Client window bindings</A> </UL> <BR> <LI><A NAME="tex2html286" HREF="node4.html#SECTION00440000000000000000">3.4 Menus</A> <UL> <LI><A NAME="tex2html287" HREF="node4.html#SECTION00441000000000000000">3.4.1 Defining menus</A> <LI><A NAME="tex2html288" HREF="node4.html#SECTION00442000000000000000">3.4.2 Special menus</A> <LI><A NAME="tex2html289" HREF="node4.html#SECTION00443000000000000000">3.4.3 Defining context menus</A> <LI><A NAME="tex2html290" HREF="node4.html#SECTION00444000000000000000">3.4.4 Displaying menus</A> </UL> <BR> <LI><A NAME="tex2html291" HREF="node4.html#SECTION00450000000000000000">3.5 Winprops</A> <UL> <LI><A NAME="tex2html292" HREF="node4.html#SECTION00451000000000000000">3.5.1 Classes, roles and instances</A> <LI><A NAME="tex2html293" HREF="node4.html#SECTION00452000000000000000">3.5.2 Finding window identification</A> <LI><A NAME="tex2html294" HREF="node4.html#SECTION00453000000000000000">3.5.3 Some common examples</A> <UL> <LI><A NAME="tex2html295" HREF="node4.html#SECTION00453100000000000000">3.5.3.1 Acrobat Reader</A> <LI><A NAME="tex2html296" HREF="node4.html#SECTION00453200000000000000">3.5.3.2 Fixing a Mozilla Firebird transient</A> <LI><A NAME="tex2html297" HREF="node4.html#SECTION00453300000000000000">3.5.3.3 Forcing newly created windows in named frames</A> </UL></UL></UL> <!--End of Table of Child-Links--> <HR> <H1><A NAME="SECTION00400000000000000000"></A> <A NAME="chap:config"></A> <BR> 3. Basic configuration </H1> <P> This chapter should help your configure Ion to your liking. As the your probably already know, Ion uses Lua as a configuration and extension language. If you're new to it, you might first want to read some Lua documentation as already suggested and pointed to in the Introduction before continuing with this chapter. <P> Section <A HREF="#sec:conffiles">3.1</A> is an overview of the multiple configuration files Ion uses and as a perhaps more understandable introduction to the general layout of the configuration files, a walk-through of the main configuration file <I>ion.lua</I> is provided in section <A HREF="#sec:walkthrough">3.2</A>. How keys and mouse action are bound to functions is described in detail in <A HREF="#sec:bindings">3.3</A> and in section <A HREF="#sec:winprops">3.5</A> winprops are explained. For a reference on exported functions, see section <A HREF="node7.html#sec:exports">6</A>. <P> <H2><A NAME="SECTION00410000000000000000"></A> <A NAME="sec:conffiles"></A> <BR> 3.1 The configuration files </H2> <P> Ion3, to which document applies, stores its stock configuration files in <I>/usr/local/etc/ion3/</I> unless you, the OS package maintainer or whoever installed the package on the system has modified the variables <TT>PREFIX</TT><A NAME="595"></A> or <TT>ETCDIR</TT><A NAME="596"></A> in <I>system.mk</I><A NAME="597"></A> before compiling Ion. In the first case you probably know where to find the files and in the other case the system administrator or the OS package maintainer should have provided documentation to point to the correct location. If these instructions are no help in locating the correct directory, the command <TT>locate cfg_ion.lua</TT> might help provided <TT>updatedb</TT> has been run recently. <P> User configuration files go in <I>~/.ion3/</I>. Ion always searches the user configuration file directory before the stock configuration file directory for files. Therefore, if you want to change some setting, it is advised against that you modify the stock configuration files in-place as subsequent installs of Ion will restore the stock configuration files. Instead you should always make a copy of the stock file in <I>~/.ion3/</I> and modify this file. When searching for a file, if no extension or path component is given, compiled <I>.lc</I> files are attempted before <I>.lua</I> files. <P> All the configuration files are named <I>cfg_*.lua</I> with the ''<I>*</I>'' part varying. The configuration file for each module <I>mod_modname</I> is <I>cfg_modname.lua</I>, with <I>modname</I> varying by the module in question. The following table summarises these and other configuration files: <P> <TABLE CELLPADDING=3 BORDER="1" WIDTH="100%"> <TR><TD ALIGN="LEFT" VALIGN="TOP" WIDTH=1>File</TD> <TD ALIGN="LEFT">Description</TD> </TR> <TR><TD ALIGN="LEFT" VALIGN="TOP" WIDTH=1><I>cfg_ion.lua</I></TD> <TD ALIGN="LEFT">The main configuration file</TD> </TR> <TR><TD ALIGN="LEFT" VALIGN="TOP" WIDTH=1><I>cfg_bindings.lua</I></TD> <TD ALIGN="LEFT">Most of Ion's bindings are configured here. Bindings that are specific to some module are configured in the module's configuration file. For details, see section <A HREF="#sec:bindings">3.3</A>.</TD> </TR> <TR><TD ALIGN="LEFT" VALIGN="TOP" WIDTH=1><I>cfg_menus.lua</I></TD> <TD ALIGN="LEFT">Menu definitions; see section <A HREF="#sec:menus">3.4</A>.</TD> </TR> <TR><TD ALIGN="LEFT" VALIGN="TOP" WIDTH=1><I>cfg_kludges.lua</I></TD> <TD ALIGN="LEFT">Settings to get some applications behave more nicely have been collected here. See section <A HREF="#sec:winprops">3.5</A>.</TD> </TR> <TR><TD ALIGN="LEFT" VALIGN="TOP" WIDTH=1><I>cfg_ionws.lua</I> <I>cfg_floatws.lua</I> <I>cfg_panews.lua</I> <I>cfg_query.lua</I> <I>cfg_menu.lua</I> <I>cfg_dock.lua</I> <I>cfg_statusbar.lua</I> ...</TD> <TD ALIGN="LEFT">Configuration files for different modules.</TD> </TR> </TABLE> <P> Additionally, there's <I>look.lua</I> that configures the drawing engine, but it is covered in chapter <A HREF="node5.html#chap:gr">4</A>. <P> <H2><A NAME="SECTION00420000000000000000"></A> <A NAME="sec:walkthrough"></A> <BR> 3.2 A walk through <I>cfg_ion.lua</I> </H2> <P> As already mentioned <I>cfg_ion.lua</I> is Ion's main configuration file. Some basic 'feel' settings are usually configured there and the necessary modules and other configuration files configuring some more specific aspects of Ion are loaded there. In this section we take a walk through the stock <I>cfg_ion.lua</I>. <P> The first thing that is done in that file is set <P> <PRE> MOD1="Mod1+" MOD2="" </PRE> This causes most of Ion's key bindings to use <B>Mod1</B> as the modifier key. If <TT>MOD2</TT> is set, it is used as modifier for the keys that don't normally use a modifier. for details on modifiers and key binding setup in general see section <A HREF="#sec:bindings">3.3</A>. <P> Next we do some basic feel configuration: <P> <PRE> ioncore.set{ dblclick_delay=250, kbresize_delay=1500, } </PRE> <P> These two will set the delay between button presses in a double click, and the timeout to quit resize mode in milliseconds. <P> <PRE> ioncore.set{ opaque_resize=true, warp=true, } </PRE> <P> The first of these two settings enables opaque resize mode: in move/resize move frames and other objects mirror you actions immediately. If opaque resize is disabled, a XOR rubber band is shown during the mode instead. This will, unfortunately, cause Ion to also grab the X server and has some side effects. <P> <PRE> ioncore.set{ default_ws_type="WIonWS", } </PRE> <P> This will set the default workspace type to WIonWS - tiled workspaces. <P> To actually be able to do something besides display windows in full screen mode, we must next load some modules: <P> <PRE> dopath("mod_query") dopath("mod_menu") dopath("mod_ionws") dopath("mod_floatws") dopath("mod_panews") dopath("mod_statusbar") --dopath("mod_dock") --dopath("mod_sp") </PRE> <P> As already mentioned, each of these modules have their own configuration files. Finally, additional configuration files are loaded: <P> <PRE> dopath("cfg_kludges") dopath("cfg_bindings") dopath("cfg_menus") </PRE> <P> Bindings and menus are defined in <I>cfg_bindings.lua</I> and <I>cfg_menus.lua</I>. Details on making such definitions follow in sections <A HREF="#sec:bindings">3.3</A> and <A HREF="#sec:menus">3.4</A>, respectively. some kludges or ''winprops'' to make some applications behave better under Ion are colledted in <I>cfg_kludges.lua</I>; see section <A HREF="#sec:winprops">3.5</A> for details. In addition to these, this file lists quite a few statements of the form <PRE> ioncore.defshortening("[^:]+: (.*)(<[0-9]+>)", "$1$2$|$1$<...$2") </PRE> These are used to configure how Ion attempts to shorten window titles when they do not fit in a Tab. The first argument is a POSIX regular expression that is used to match against the title and the next is a rule to construct a new title of a match occurs. This particular rule is used to shorten e.g. 'Foo: barbaz<3>' to 'barba...<3>'; for details see the function reference entry for <A HREF="node7.html#fn:ioncore.defshortening"><TT>ioncore.defshortening</TT></A>. <P> <H2><A NAME="SECTION00430000000000000000"></A> <A NAME="sec:bindings"></A> <BR> 3.3 Keys and rodents </H2> <P> In the stock configuration file setup, most key and mouse bindings are set from the file <I>cfg_bindings.lua</I> while module-specific bindings are set from the modules' main configuration files (<I>cfg_modname.lua</I>). This, however, does not have to be so as long as the module has been loaded prior to defining any module-specific bindings. <P> Bindings are defined by calling the function <A HREF="node7.html#fn:ioncore.defbindings"><TT>defbindings</TT></A> with the ''context'' of the bindings and the a table of new bindings to make. The context is simply string indicating one of the classes of regions (or modes such as WMoveresMode) introduced in section <A HREF="node3.html#sec:objects">2.2</A>, and fully listed in appendix <A HREF="node9.html#app:fullhierarchy">B</A>, although not all define a binding map. For example, the following skeleton would be used to define new bindings for all frames: <P> <PRE> defbindings("WFrame", { -- List of bindings to make goes here. }) </PRE> <P> There has been some confusion among users about the need to define the ''context'' for each binding, so let me try to explain this design decision here. The thing is that if there was a just a simple 'bind this key to this action' method without knowledge of the context, some limitations would have to be made on the available actions and writing custom handlers would be more complicated. In addition one may want to bind the same function to different key for different types of objects. Indeed, the workspace and frame tab switching functions are the same both classes being based on WMPlex, and in the stock configuration the switch to :th workspaces is bound to <B>Mod1+n</B> while the switch to :th tab is bound to the sequence <B>Mod1+k n</B>. <P> The following subsections describe how to construct elements of the binding table. Note that <A HREF="node7.html#fn:ioncore.defbindings"><TT>defbindings</TT></A> adds the the newly defined bindings to the previous bindings of the context, overriding duplicates. To unbind an event, set the handler parameter to <TT>nil</TT> for each of the functions to be described in the following subsections. <P> Also note that when multiple objects want to handle a binding, the innermost (when the root window is considered the outermost) active object in the parent-child hierarchy (see Figure <A HREF="node3.html#fig:parentship">2.2</A>) of objects gets to handle the action. <P> <H3><A NAME="SECTION00431000000000000000"> 3.3.1 Binding handlers and special variables</A> </H3> <P> Unlike in Ion2, in Ion3 binding handlers are not normally passed as ''anonymous functions'', although this is still possible. The preferred method now is to pass the code of the handler as a string. Two special variables are available in this code. These are <P> <TABLE CELLPADDING=3 BORDER="1" WIDTH="100%"> <TR><TD ALIGN="LEFT">Variable</TD> <TD ALIGN="LEFT">Description</TD> </TR> <TR><TD ALIGN="LEFT"><TT>_</TT> (underscore)</TD> <TD ALIGN="LEFT">Reference to the object on which the binding was triggered. The object is of the same class as the the context of the <A HREF="node7.html#fn:ioncore.defbindings"><TT>defbindings</TT></A> call defining the binding.</TD> </TR> <TR><TD ALIGN="LEFT"><TT>_sub</TT></TD> <TD ALIGN="LEFT">Usually, the currently active child of the object referred to by <TT>_</TT>, but sometimes (e.g. mouse actions on tabs of frames) something else relevant to the action triggering the binding.</TD> </TR> </TABLE> <P> For example, supposing '<TT>_</TT>' is a WFrame, the following handler should move the active window to the right, if possible: <P> <PRE> "_:inc_index(_sub)" </PRE> <P> <H3><A NAME="SECTION00432000000000000000"> 3.3.2 Guards</A> </H3> <P> To suppress error messages, each binding handler may also be accompanied by a ''guard'' expression that blocks the handler from being called when the guard condition is not met. Currently the following guard expressions are supported: <P> <TABLE CELLPADDING=3 BORDER="1" WIDTH="100%"> <TR><TD ALIGN="LEFT">Guard</TD> <TD ALIGN="LEFT">Description</TD> </TR> <TR><TD ALIGN="LEFT"><TT>"_sub:non-nil"</TT></TD> <TD ALIGN="LEFT">The <TT>_sub</TT> parameter must be set.</TD> </TR> <TR><TD ALIGN="LEFT"><TT>"_sub:SomeClass"</TT></TD> <TD ALIGN="LEFT">The <TT>_sub</TT> parameter must be member of class SomeClass.</TD> </TR> </TABLE> <P> <H3><A NAME="SECTION00433000000000000000"></A> <A NAME="sec:binddef"></A> <BR> 3.3.3 Defining the bindings </H3> <P> The descriptions of the individual bindings in the binding table argument to <A HREF="node7.html#fn:ioncore.defbindings"><TT>defbindings</TT></A> should be constructed with the following functions. <P> Key presses: <UL> <LI><A HREF="#fn:kpress"><TT>kpress</TT></A><TT>(keyspec, handler [, guard])</TT>, </LI> <LI><A HREF="#fn:kpress_wait"><TT>kpress_wait</TT></A><TT>(keyspec, handler [, guard])</TT> and </LI> <LI><A HREF="#fn:submap"><TT>submap</TT></A><TT>(keyspec, { ... more key bindings ... })</TT>. </LI> </UL> Mouse actions: <UL> <LI><A HREF="#fn:mclick"><TT>mclick</TT></A><TT>(buttonspec, handler [, guard])</TT>, </LI> <LI><A HREF="#fn:mdblclick"><TT>mdblclick</TT></A><TT>(buttonspec, handler [, guard])</TT>, </LI> <LI><A HREF="#fn:mpress"><TT>mpress</TT></A><TT>(buttonspec, handler [, guard])</TT> and </LI> <LI><A HREF="#fn:mdrag"><TT>mdrag</TT></A><TT>(buttonspec, handler [, guard])</TT>. </LI> </UL> <P> The actions that most of these functions correspond to should be clear and as explained in the reference, <A HREF="#fn:kpress_wait"><TT>kpress_wait</TT></A> is simply <A HREF="#fn:kpress"><TT>kpress</TT></A> with a flag set instructing Ioncore wait for all modifiers to be released before processing any further actions. This is to stop one from accidentally calling e.g. <A HREF="node7.html#fn:WRegion.rqclose"><TT>WRegion.rqclose</TT></A> multiple times in a row. The <A HREF="#fn:submap"><TT>submap</TT></A> function is used to define submaps or ''prefix maps''. The second argument to this function is table listing the key press actions (<A HREF="#fn:kpress"><TT>kpress</TT></A>) in the submap <P> The parameters <TT>keyspec</TT> and <TT>buttonspec</TT> are explained below in detail. The parameter <TT>handler</TT> is the handler for the binding, and the optional parameter <TT>guard</TT> its guard. These should normally be strings as explained above. <P> <H3><A NAME="SECTION00434000000000000000"> 3.3.4 Examples</A> </H3> <P> For example, to just bind the key <B>Mod1+1</B> to switch to the first workspace and <B>Mod1+Right</B> to the next workspace, you would make the following call <PRE> defbindings("WScreen", { kpress("Mod1+Right", "_:switch_next()"), kpress("Mod1+1", "_:switch_nth(1)"), }) </PRE> <P> Note that <TT>_:switch_nth(1)</TT> is the same as calling <A HREF="node7.html#fn:WMPlex.switch_next"><TT>WMPlex.switch_next</TT></A><TT>(_, 1)</TT> as WScreen inherits WMPlex and this is where the function is actually defined. <P> Similarly to the above example, to bind the key sequence <B>Mod1+k n</B> switch to the next managed object within a frame, and <B>Mod1+k 1</B> to the first, you would issue the following call: <PRE> defbindings("WFrame", { submap("Mod1+K", { kpress("Right", "_:switch_next()"), kpress("1", "_:switch_nth(1)"), }), }) </PRE> <P> <H3><A NAME="SECTION00435000000000000000"> 3.3.5 Key specifications</A> </H3> <P> As seen above, the functions that create key binding specifications require a <TT>keyspec</TT> argument. This argument should be a string containing the name of a key as listed in the X header file <I>keysymdef.h</I><A NAME="tex2html7" HREF="#foot856"><SUP>3.1</SUP></A> without the <TT>XK_</TT> prefix. <A NAME="857"></A> Most of the key names are quite intuitive while some are not. For example, the <B>Enter</B> key on the main part of the keyboard has the less common name <B>Return</B> while the one the numpad is called <B>KP_Enter</B>. <P> The <TT>keyspec</TT> string may optionally have multiple ''modifier'' names followed by a plus sign (<TT>+</TT>) as a prefix. X defines the following modifiers: <BLOCKQUOTE> <B>Shift</B>, <B>Control</B>, <B>Mod1</B> to <B>Mod5</B>, <B>AnyModifier</B> and <B>Lock</B>. <A NAME="858"></A> <A NAME="859"></A> <A NAME="860"></A> <A NAME="861"></A> <A NAME="862"></A> </BLOCKQUOTE> <P> X allows binding all of these modifiers to almost any key and while this list of modifiers does not explicitly list keys such as <B>Alt</B><A NAME="863"></A> that are common on modern keyboards, such keys are bound to one of the <B>ModN</B>. On systems running XFree86 <B>Alt</B> is usually <B>Mod1</B>. On Suns <B>Mod1</B> is the diamond key and <B>Alt</B> something else. One of the ''flying window'' keys on so called Windows-keyboards is probably mapped to <B>Mod3</B> if you have such a key. Use the program <I>xmodmap</I><A NAME="864"></A> to find out what exactly is bound where. <P> Ion defaults to <B>AnyModifier</B> in submaps. This can sometimes lead to unwanted effects when the same key is used with and without explicitly specified modifiers in nested regions. For this reason, Ion recognises <B>NoModifier</B> as a special modifier that can be used to reset this default. <P> Ion ignores the <B>Lock</B> modifier and any <B>ModN</B> () bound to <B>NumLock</B><A NAME="865"></A> or <B>ScrollLock</B><A NAME="866"></A> by default because such<A NAME="tex2html8" HREF="#foot829"><SUP>3.2</SUP></A> locking keys may otherwise cause confusion. <P> <H3><A NAME="SECTION00436000000000000000"> 3.3.6 Button specifications</A> </H3> <P> Button specifications are similar to key definitions but now instead of specifying modifiers and a key, you specify modifiers and one of the button names <B>Button1</B> to <B>Button5</B><A NAME="867"></A>. Additionally the specification may end with an optional area name following an @-sign. Only frames currently support areas, and the supported values in this case are <TT>"border"</TT>, <TT>"tab"</TT>, <TT>"empty_tab"</TT>, <TT>"client"</TT> and <TT>nil</TT> (for the whole frame). <P> For example, the following code binds dragging a tab with the first button pressed to initiate tab drag&drop handling: <P> <PRE> defbindings("WFrame", { mdrag("Button1@tab", "_:p_tabdrag()"), }) </PRE> <P> <H3><A NAME="SECTION00437000000000000000"> 3.3.7 A further note on the default binding configuration</A> </H3> <P> The default binding configuration contains references to the variables <TT>MOD1</TT> and <TT>MOD2</TT> instead of directly using the default values of <TT>"Mod1+"</TT> and <TT>""</TT> (nothing). As explained in section <A HREF="#sec:walkthrough">3.2</A>, the definitions of these variables appear in <I>cfg_ion.lua</I>. This way you can easily change the the modifiers used by all bindings in the default configuration without changing the whole binding configuration. Quite a few people prefer to use the Windows keys as modifiers because many applications already use <B>Alt</B>. Nevertheless, <B>Mod1</B> is the default as a key bound to it is available virtually everywhere. <P> <H3><A NAME="SECTION00438000000000000000"> 3.3.8 Client window bindings</A> </H3> <P> As client windows do not have a binding map of their own due to technical reasons, it is necessary to call client window functions by specifying the bindings somewhere else. In the stock configuration file setup this is done among WMPlex bindings, setting the guard to <TT>_sub:WClientWin</TT> and using <TT>_sub</TT> to refer to the client window. <P> For example, the full screen toggle key is bound like this: <P> <PRE> defbindings("WMPlex", { kpress_wait("Mod1+Return", "_:toggle_fullscreen()", "_sub:WClientWin"), }) </PRE> <P> <P> <H2><A NAME="SECTION00440000000000000000"></A> <A NAME="sec:menus"></A> <BR> 3.4 Menus </H2> <P> <H3><A NAME="SECTION00441000000000000000"> 3.4.1 Defining menus</A> </H3> <P> <A NAME="1100"></A> <A NAME="1152"></A> <A NAME="1153"></A> <A NAME="1154"></A> In the stock configuration file setup, menus are defined in the file <I>cfg_menus.lua</I> as previously mentioned. The <I>mod_menu</I> module must be loaded for one to be able to define menus, and this is done with the function <A HREF="#fn:mod_menu.defmenu"><TT>defmenu</TT></A> provided by it. <P> Here's an example of the definition of a rather simple menu with a submenu: <P> <PRE> defmenu("exitmenu", { menuentry("Restart", "ioncore.restart()"), menuentry("Exit", "ioncore.shutdown()"), }) defmenu("mainmenu", { menuentry("Lock screen", "ioncore.exec('xlock')"), menuentry("Help", "mod_query.query_man(_)"), submenu("Exit", "exitmenu"), }) </PRE> <P> The <A HREF="#fn:mod_menu.menuentry"><TT>menuentry</TT></A> function is used to create an entry in the menu with a title and an entry handler to be called when the menu entry is activated. The parameters to the handler are similar to those of binding handlers, and usually the same as those of the binding that opened the menu. <P> The <A HREF="#fn:mod_menu.submenu"><TT>submenu</TT></A> function is used to insert a submenu at that point in the menu. (One could as well just pass a table with the menu entries, but it is not encouraged.) <P> <H3><A NAME="SECTION00442000000000000000"> 3.4.2 Special menus</A> </H3> <P> The menu module predefines the following special menus. These can be used just like the menus defined as above. <P> <TABLE CELLPADDING=3 BORDER="1" WIDTH="100%"> <TR><TD ALIGN="LEFT">Menu name</TD> <TD ALIGN="LEFT">Description</TD> </TR> <TR><TD ALIGN="LEFT"><TT>windowlist</TT></TD> <TD ALIGN="LEFT">List of all client windows. Activating an entry jumps to that window.</TD> </TR> <TR><TD ALIGN="LEFT"><TT>workspacelist</TT></TD> <TD ALIGN="LEFT">List of all workspaces. Activating an entry jumps to that workspaces.</TD> </TR> <TR><TD ALIGN="LEFT"><TT>stylemenu</TT></TD> <TD ALIGN="LEFT">List of available <I>look_*.lua</I> style files. Activating an entry loads that style and ask to save the selection.</TD> </TR> <TR><TD ALIGN="LEFT"><TT>ctxmenu</TT></TD> <TD ALIGN="LEFT">Context menu for given object.</TD> </TR> </TABLE> <P> <H3><A NAME="SECTION00443000000000000000"> 3.4.3 Defining context menus</A> </H3> <P> The ''ctxmenu'' is a special menu that is assembled from a defined context menu for the object for which the menu was opened for, but also includes the context menus for the manager objects as submenus. <P> Context menus for a given region class are defined with the <A HREF="#fn:mod_menu.defctxmenu"><TT>defctxmenu</TT></A> function. This is other ways similar to <A HREF="#fn:mod_menu.defmenu"><TT>defmenu</TT></A>, but the first argument instead being the name of the menu, the name of the region class to define context menu for. For example, here's part of the stock WFrame context menu definition: <P> <PRE> defctxmenu("WFrame", { menuentry("Close", "WRegion.rqclose_propagate(_, _sub)"), menuentry("Kill", "WClientWin.kill(_sub)", "_sub:WClientWin"), }) </PRE> <P> <H3><A NAME="SECTION00444000000000000000"></A> <A NAME="sec:menudisp"></A> <BR> 3.4.4 Displaying menus </H3> <P> The following functions may be used to display menus from binding handlers (and elsewhere): <P> <TABLE CELLPADDING=3 BORDER="1" WIDTH="100%"> <TR><TD ALIGN="LEFT">Function</TD> <TD ALIGN="LEFT">Description</TD> </TR> <TR><TD ALIGN="LEFT"><A HREF="node7.html#fn:mod_menu.menu"><TT>mod_menu.menu</TT></A></TD> <TD ALIGN="LEFT">Keyboard (or mouse) operated menus that open in the bottom-left corner of a screen or frame.</TD> </TR> <TR><TD ALIGN="LEFT"><A HREF="#fn:mod_menu.bigmenu"><TT>mod_menu.bigmenu</TT></A></TD> <TD ALIGN="LEFT">Same as previous, but uses another graphical style.</TD> </TR> <TR><TD ALIGN="LEFT"><A HREF="node7.html#fn:mod_menu.pmenu"><TT>mod_menu.pmenu</TT></A></TD> <TD ALIGN="LEFT">Mouse-operated drop-down menus. This function can only be called from a mouse press or drag handler.</TD> </TR> <TR><TD ALIGN="LEFT"><A HREF="node7.html#fn:mod_menu.grabmenu"><TT>mod_menu.grabmenu</TT></A></TD> <TD ALIGN="LEFT">A special version of <A HREF="node7.html#fn:mod_menu.menu"><TT>mod_menu.menu</TT></A> that grabs the keyboard and is scrolled with a given key until all modifiers have been released, after which the selected entry is activated. This function is meant to be used for implementing, for example, Win***s-style <B>Alt-Tab</B> handling.<A NAME="tex2html9" HREF="#foot1155"><SUP>3.3</SUP></A></TD> </TR> </TABLE> <P> The <A HREF="node7.html#fn:mod_menu.grabmenu"><TT>grabmenu</TT></A> function takes the extra key parameter, but aside from that each of these functions takes three arguments, which when called from a binding handler, should be the parameters to the handler, and the name of the menu. For example, the following snippet of of code binds the both ways to open a context menu for a frame: <P> <PRE> defbindings("WFrame", { kpress(MOD1.."M", "mod_menu.menu(_, _sub, 'ctxmenu')"), mpress("Button3", "mod_menu.pmenu(_, _sub, 'ctxmenu')"), }) </PRE> <P> <H2><A NAME="SECTION00450000000000000000"></A> <A NAME="sec:winprops"></A> <BR> 3.5 Winprops </H2> <P> The so-called ''winprops''<A NAME="1243"></A> can be used to change how specific windows are handled and to set up some kludges to deal with badly behaving applications. They are defined by calling the function <TT>defwinprop</TT> with a table containing the properties to set and the necessary information to identify a window. The currently supported winprops are listed below, and the subsequent subsections explain the usual method of identifying windows, and how to obtain this information. <P> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>acrobatic</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1382"></A> Set this to <TT>true</TT> for Acrobat Reader. It has an annoying habit of trying to manage its dialogs instead of setting them as transients and letting the window manager do its job, causing Ion and acrobat go a window-switching loop when a dialog is opened. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>aspect</TT> (table) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1383"></A> The table should contain the entries <TT>w</TT> and <TT>h</TT> that override application-supplied aspect ratio hint. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>fullscreen</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1384"></A> Should the window be initially in full screen mode? </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>ignore_cfgrq</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1385"></A> Should configure requests on the window be ignored? Only has effect on windows on floatws:s. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>ignore_net_active_window</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1386"></A> Ignore extended WM hints <TT>_NET_ACTIVE_WINDOW</TT> request. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>ignore_resizeinc</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1387"></A> Should application supplied size increments be ignored? </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>jumpto</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1388"></A> Should a newly created client window always be made active, even if the allocated frame isn't. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>max_size</TT> (table) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1389"></A> The table should contain the entries <TT>w</TT> and <TT>h</TT> that override application-supplied maximum size hint. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>min_size</TT> (table) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1390"></A> Similar to <TT>max_size</TT> but for the minimum size hint. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>oneshot</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1391"></A> Discard this winprop after first use. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>switchto</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1392"></A> Should a newly mapped client window be switched to within its frame. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>target</TT> (string) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1393"></A> The name of an object (workspace, frame) that should manage windows of this type. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>transient_mode</TT> (string) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1394"></A> "normal": No change in behaviour. "current": The window should be thought of as a transient for the current active client window (if any) even if it is not marked as a transient by the application. "off": The window should be handled as a normal window even if it is marked as a transient by the application. </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>transients_at_top</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1395"></A> When transients are managed by the client window itself (as it is the case on tiled workspaces), should the transients be placed at the top of the window instead of bottom? </DD> </DL> <P> <DL> <DT><STRONG>Winprop:</STRONG></DT> <DD><TT>transparent</TT> (boolean) </DD> <DT><STRONG>Description:</STRONG></DT> <DD><A NAME="1396"></A> Should frames be made transparent when this window is selected? <BR> </DD> </DL> <P> <H3><A NAME="SECTION00451000000000000000"></A> <A NAME="sec:classesrolesinstances"></A> <BR> 3.5.1 Classes, roles and instances </H3> <P> The identification information in the winprop specification is usually the <TT>class</TT><A NAME="1397"></A>, <TT>role</TT><A NAME="1398"></A>, <TT>instance</TT><A NAME="1399"></A> and <TT>name</TT> of the window. The <TT>name</TT> field is a Lua-style regular expression matched against the window's title and the rest are strings that must exactly much the corresponding window information. It is not necessary to specify all of these fields. <P> Ion looks for a matching winprop in the order listed by the following table. An 'E' indicates that the field must be set in the winprop and it must match the window's corresponding property exactly or, in case of <TT>name</TT>, the regular expression must match the window title. An asterisk '*' indicates that a winprop where the field is not specified (or is itself an asterisk in case of the first three fields) is tried. <P> <DIV ALIGN="CENTER"> <TABLE CELLPADDING=3 BORDER="1"> <TR><TD ALIGN="LEFT"><TT>class</TT></TD> <TD ALIGN="LEFT"><TT>role</TT></TD> <TD ALIGN="LEFT"><TT>instance</TT></TD> <TD ALIGN="LEFT"><TT>name</TT></TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> <TD ALIGN="LEFT">E</TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> <TD ALIGN="LEFT">*</TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">E</TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> <TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> </TR> <TR><TD ALIGN="LEFT">E</TD> <TD ALIGN="LEFT">*</TD> <TD ALIGN="LEFT">*</TD> <TD ALIGN="LEFT">E</TD> </TR> <TR><TD ALIGN="LEFT"> </TD> <TD ALIGN="LEFT"> </TD> <TD ALIGN="LEFT"> </TD> <TD ALIGN="LEFT">etc.</TD> </TR> </TABLE> </DIV> <P> If there are multiple winprops with other identification information the same but different <TT>name</TT>, the longest match is chosen. <P> <H3><A NAME="SECTION00452000000000000000"> 3.5.2 Finding window identification</A> </H3> <P> The 'Window info' context menu entry (<B>Mod1+M</B> or <B>Button3</B> on a tab) can be used to list the identification information required to set winprops for a window and all the transient windows managed within it. <P> <A NAME="1355"></A> Another way to get the identification information is to use <TT>xprop</TT>. Simply run To get class and instance, simply run <TT>xprop WM_CLASS</TT> and click on the particular window of interest. The class is the latter of the strings while the instance is the former. To get the role - few windows have this property - use the command <TT>xprop WM_ROLE</TT>. This method, however, will not work on transients. <P> <A NAME="1359"></A> So-called ''transient windows'' are usually short-lived dialogs (although some programs abuse this property) that have a parent window that they are ''transient for''. On tiled workspaces Ion displays these windows simulatenously with the parent window at the bottom of the same frame. Unfortunately <TT>xprop</TT> is stupid and can't cope with this situation, returning the parent window's properties when the transient is clicked on. For this reason you'll have to do a little extra work to get the properties for that window.<A NAME="tex2html11" HREF="#foot1401"><SUP>3.4</SUP></A> <P> Finally, it should be mentioned that too many authors these days ''forget'' to set this vital identification to anything meaningful: everything except name is the same for all of the programs's windows, for example. <P> <H3><A NAME="SECTION00453000000000000000"> 3.5.3 Some common examples</A> </H3> <P> <H4><A NAME="SECTION00453100000000000000"> 3.5.3.1 Acrobat Reader</A> </H4> <P> The following is absolutely necessary for Acrobat reader: <P> <PRE> defwinprop{ class = "AcroRead", instance = "documentShell", acrobatic = true, } </PRE> <P> <H4><A NAME="SECTION00453200000000000000"> 3.5.3.2 Fixing a Mozilla Firebird transient</A> </H4> <P> Mozilla Firebird (0.7) incorrectly does not set the <TT>WM_TRANSIENT_FOR</TT> property for the dialog that is used to ask the action to take for a file. It, however, sets the the property point to the main window for the save dialog. This can be annoying and confusing, as the first dialog is not closed before the second is displayed. <P> We'd like the first dialog to be transient to the main window. The closest we can get to that is to consider it transient to the current window (if there's one). Unfortunately Firebird does not set any meaningful classes, instances or roles for the windows, so we'll have to rely on an ugly title match. <P> <PRE> defwinprop{ class = "MozillaFirebird-bin", name = "Opening .*", transient_mode = "current", } </PRE> <P> <H4><A NAME="SECTION00453300000000000000"> 3.5.3.3 Forcing newly created windows in named frames</A> </H4> <P> The following winprop should place xterm started with command-line parameter <TT>-name sysmon</TT> and running a system monitoring program in a particular frame: <PRE> defwinprop{ class = "XTerm", instance = "sysmon", target = "sysmonframe", } </PRE> <P> For this example to work, we have to somehow create a frame named <TT>sysmonframe</TT>. One way to do this is to make the following call in the <B>Mod1+F3</B> Lua code query: <P> <PRE> mod_query.query_renameframe(_) </PRE> <P> Recall that <TT>_</TT> points to the multiplexer (frame or screen) in which the query was opened. Running this code should open a new query prefilled with the current name of the frame. In our example we would change the name to <TT>sysmonframe</TT>, but we could just as well have used the default name formed from the frame's class name and an instance number. <P> <P> <BR><HR><H4>Footnotes</H4> <DL> <DT><A NAME="foot856">...keysymdef.h</A><A HREF="node4.html#tex2html7"><SUP>3.1</SUP></A></DT> <DD>This file can usually be found in the directory <I>/usr/X11R6/include/X11/</I>. </DD> <DT><A NAME="foot829">... such</A><A HREF="node4.html#tex2html8"><SUP>3.2</SUP></A></DT> <DD>Completely useless keys that should be gotten rid of in the author's opinion. </DD> <DT><A NAME="foot1155">... handling.</A><A HREF="node4.html#tex2html9"><SUP>3.3</SUP></A></DT> <DD>See the <I>wcirculate.lua</I> script in the Ion scripts repository <TT><A NAME="tex2html10" HREF="http://iki.fi/tuomov/repos/ion-scripts-3/">http://iki.fi/tuomov/repos/ion-scripts-3/</A></TT>. </DD> <DT><A NAME="foot1401">... window.</A><A HREF="node4.html#tex2html11"><SUP>3.4</SUP></A></DT> <DD>There's a patch to <TT>xprop</TT> to fix this, but nothing seems to be happening with respect to including it in XFree86. </DD> </DL><HR> <!--Navigation Panel--> <A NAME="tex2html273" HREF="node5.html"> <IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" SRC="next.png"></A> <A NAME="tex2html267" HREF="ionconf.html"> <IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" SRC="up.png"></A> <A NAME="tex2html261" HREF="node3.html"> <IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" SRC="prev.png"></A> <A NAME="tex2html269" HREF="node1.html"> <IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" SRC="contents.png"></A> <A NAME="tex2html271" HREF="node11.html"> <IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index" SRC="index.png"></A> <BR> <B> Next:</B> <A NAME="tex2html274" HREF="node5.html">4. Graphical styles</A> <B> Up:</B> <A NAME="tex2html268" HREF="ionconf.html">Configuring and extending Ion3</A> <B> Previous:</B> <A NAME="tex2html262" HREF="node3.html">2. Preliminaries: Key concepts</A> <B> <A NAME="tex2html270" HREF="node1.html">Contents</A></B> <B> <A NAME="tex2html272" HREF="node11.html">Index</A></B> <!--End of Navigation Panel--> </BODY> </HTML>