<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> <title>i3: src/mainx.c Source File</title> <link href="tabs.css" rel="stylesheet" type="text/css"/> <link href="doxygen.css" rel="stylesheet" type="text/css"/> </head> <body> <!-- Generated by Doxygen 1.6.2-20100208 --> <div class="navigation" id="top"> <div class="tabs"> <ul> <li><a href="index.html"><span>Main Page</span></a></li> <li><a href="annotated.html"><span>Data Structures</span></a></li> <li class="current"><a href="files.html"><span>Files</span></a></li> </ul> </div> <div class="tabs"> <ul> <li><a href="files.html"><span>File List</span></a></li> <li><a href="globals.html"><span>Globals</span></a></li> </ul> </div> <h1>src/mainx.c</h1><a href="a00071.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span> <a name="l00002"></a>00002 <span class="comment"> * vim:ts=8:expandtab</span> <a name="l00003"></a>00003 <span class="comment"> *</span> <a name="l00004"></a>00004 <span class="comment"> * i3 - an improved dynamic tiling window manager</span> <a name="l00005"></a>00005 <span class="comment"> *</span> <a name="l00006"></a>00006 <span class="comment"> * © 2009-2010 Michael Stapelberg and contributors</span> <a name="l00007"></a>00007 <span class="comment"> *</span> <a name="l00008"></a>00008 <span class="comment"> * See file LICENSE for license information.</span> <a name="l00009"></a>00009 <span class="comment"> *</span> <a name="l00010"></a>00010 <span class="comment"> */</span> <a name="l00011"></a>00011 <span class="preprocessor">#include <stdio.h></span> <a name="l00012"></a>00012 <span class="preprocessor">#include <stdlib.h></span> <a name="l00013"></a>00013 <span class="preprocessor">#include <string.h></span> <a name="l00014"></a>00014 <span class="preprocessor">#include <sys/types.h></span> <a name="l00015"></a>00015 <span class="preprocessor">#include <unistd.h></span> <a name="l00016"></a>00016 <span class="preprocessor">#include <stdbool.h></span> <a name="l00017"></a>00017 <span class="preprocessor">#include <assert.h></span> <a name="l00018"></a>00018 <span class="preprocessor">#include <limits.h></span> <a name="l00019"></a>00019 <span class="preprocessor">#include <locale.h></span> <a name="l00020"></a>00020 <span class="preprocessor">#include <fcntl.h></span> <a name="l00021"></a>00021 <span class="preprocessor">#include <getopt.h></span> <a name="l00022"></a>00022 <a name="l00023"></a>00023 <span class="preprocessor">#include <X11/XKBlib.h></span> <a name="l00024"></a>00024 <span class="preprocessor">#include <X11/extensions/XKB.h></span> <a name="l00025"></a>00025 <a name="l00026"></a>00026 <span class="preprocessor">#include <xcb/xcb.h></span> <a name="l00027"></a>00027 <span class="preprocessor">#include <xcb/xcb_atom.h></span> <a name="l00028"></a>00028 <span class="preprocessor">#include <xcb/xcb_aux.h></span> <a name="l00029"></a>00029 <span class="preprocessor">#include <xcb/xcb_event.h></span> <a name="l00030"></a>00030 <span class="preprocessor">#include <xcb/xcb_property.h></span> <a name="l00031"></a>00031 <span class="preprocessor">#include <xcb/xcb_keysyms.h></span> <a name="l00032"></a>00032 <span class="preprocessor">#include <xcb/xcb_icccm.h></span> <a name="l00033"></a>00033 <a name="l00034"></a>00034 <span class="preprocessor">#include <ev.h></span> <a name="l00035"></a>00035 <a name="l00036"></a>00036 <span class="preprocessor">#include "<a class="code" href="a00034.html">config.h</a>"</span> <a name="l00037"></a>00037 <span class="preprocessor">#include "<a class="code" href="a00036.html">data.h</a>"</span> <a name="l00038"></a>00038 <span class="preprocessor">#include "<a class="code" href="a00037.html">debug.h</a>"</span> <a name="l00039"></a>00039 <span class="preprocessor">#include "<a class="code" href="a00040.html">handlers.h</a>"</span> <a name="l00040"></a>00040 <span class="preprocessor">#include "<a class="code" href="a00031.html">click.h</a>"</span> <a name="l00041"></a>00041 <span class="preprocessor">#include "<a class="code" href="a00041.html">i3.h</a>"</span> <a name="l00042"></a>00042 <span class="preprocessor">#include "<a class="code" href="a00043.html">layout.h</a>"</span> <a name="l00043"></a>00043 <span class="preprocessor">#include "<a class="code" href="a00047.html">queue.h</a>"</span> <a name="l00044"></a>00044 <span class="preprocessor">#include "<a class="code" href="a00051.html">table.h</a>"</span> <a name="l00045"></a>00045 <span class="preprocessor">#include "<a class="code" href="a00052.html">util.h</a>"</span> <a name="l00046"></a>00046 <span class="preprocessor">#include "<a class="code" href="a00054.html">xcb.h</a>"</span> <a name="l00047"></a>00047 <span class="preprocessor">#include "<a class="code" href="a00048.html">randr.h</a>"</span> <a name="l00048"></a>00048 <span class="preprocessor">#include "<a class="code" href="a00055.html">xinerama.h</a>"</span> <a name="l00049"></a>00049 <span class="preprocessor">#include "<a class="code" href="a00046.html">manage.h</a>"</span> <a name="l00050"></a>00050 <span class="preprocessor">#include "<a class="code" href="a00042.html">ipc.h</a>"</span> <a name="l00051"></a>00051 <span class="preprocessor">#include "<a class="code" href="a00044.html">log.h</a>"</span> <a name="l00052"></a>00052 <span class="preprocessor">#include "<a class="code" href="a00050.html">sighandler.h</a>"</span> <a name="l00053"></a>00053 <a name="l00054"></a><a class="code" href="a00071.html#ab7a200a5f990dc2deaae492aa7b57711">00054</a> <span class="keyword">static</span> <span class="keywordtype">int</span> <a class="code" href="a00071.html#ab7a200a5f990dc2deaae492aa7b57711">xkb_event_base</a>; <a name="l00055"></a>00055 <a name="l00056"></a><a class="code" href="a00041.html#a2590f55d5727c7d1cd01ebe7fd94a05d">00056</a> <span class="keywordtype">int</span> <a class="code" href="a00071.html#a2590f55d5727c7d1cd01ebe7fd94a05d">xkb_current_group</a>; <a name="l00057"></a>00057 <a name="l00058"></a><a class="code" href="a00041.html#ada13c42121d64521629e06e7a5e1db16">00058</a> xcb_connection_t *<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>; <a name="l00059"></a>00059 <a name="l00060"></a>00060 <span class="comment">/* This is the path to i3, copied from argv[0] when starting up */</span> <a name="l00061"></a><a class="code" href="a00041.html#adff3468c46bf36c35842552ad6cd220d">00061</a> <span class="keywordtype">char</span> **<a class="code" href="a00071.html#adff3468c46bf36c35842552ad6cd220d">start_argv</a>; <a name="l00062"></a>00062 <a name="l00063"></a>00063 <span class="comment">/* This is our connection to X11 for use with XKB */</span> <a name="l00064"></a><a class="code" href="a00041.html#a3401bcd302be580b0500474e75726538">00064</a> Display *<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>; <a name="l00065"></a>00065 <a name="l00066"></a><a class="code" href="a00041.html#a5cc0138ae2cf3bbb63a7cae907620797">00066</a> xcb_key_symbols_t *<a class="code" href="a00071.html#a5cc0138ae2cf3bbb63a7cae907620797">keysyms</a>; <a name="l00067"></a>00067 <a name="l00068"></a>00068 <span class="comment">/* The list of key bindings */</span> <a name="l00069"></a><a class="code" href="a00071.html#afe67646b6ee7ae51b130a59354fe7f49">00069</a> <span class="keyword">struct </span>bindings_head *<a class="code" href="a00071.html#afe67646b6ee7ae51b130a59354fe7f49">bindings</a>; <a name="l00070"></a>00070 <a name="l00071"></a>00071 <span class="comment">/* The list of exec-lines */</span> <a name="l00072"></a><a class="code" href="a00071.html#adc8cf28482f0bbe29f8bdcba0e32d16f">00072</a> <span class="keyword">struct </span>autostarts_head <a class="code" href="a00071.html#adc8cf28482f0bbe29f8bdcba0e32d16f">autostarts</a> = <a class="code" href="a00047.html#ac269df7d4126ed9885156cbad2cbf8af">TAILQ_HEAD_INITIALIZER</a>(<a class="code" href="a00071.html#adc8cf28482f0bbe29f8bdcba0e32d16f">autostarts</a>); <a name="l00073"></a>00073 <a name="l00074"></a>00074 <span class="comment">/* The list of assignments */</span> <a name="l00075"></a><a class="code" href="a00071.html#af36d2f2cbc5487cf0e9e2d60165b3e89">00075</a> <span class="keyword">struct </span>assignments_head <a class="code" href="a00071.html#af36d2f2cbc5487cf0e9e2d60165b3e89">assignments</a> = <a class="code" href="a00047.html#ac269df7d4126ed9885156cbad2cbf8af">TAILQ_HEAD_INITIALIZER</a>(<a class="code" href="a00071.html#af36d2f2cbc5487cf0e9e2d60165b3e89">assignments</a>); <a name="l00076"></a>00076 <a name="l00077"></a>00077 <span class="comment">/* This is a list of Stack_Windows, global, for easier/faster access on expose events */</span> <a name="l00078"></a><a class="code" href="a00071.html#ac38e5cddf6395c52d3755d7b368e4a2b">00078</a> <span class="keyword">struct </span>stack_wins_head <a class="code" href="a00071.html#ac38e5cddf6395c52d3755d7b368e4a2b">stack_wins</a> = <a class="code" href="a00047.html#a9ae2aca3d46e62be4cb1408bd946ef15">SLIST_HEAD_INITIALIZER</a>(<a class="code" href="a00071.html#ac38e5cddf6395c52d3755d7b368e4a2b">stack_wins</a>); <a name="l00079"></a>00079 <a name="l00080"></a>00080 <span class="comment">/* The event handlers need to be global because they are accessed by our custom event handler</span> <a name="l00081"></a>00081 <span class="comment"> in handle_button_press(), needed for graphical resizing */</span> <a name="l00082"></a><a class="code" href="a00041.html#a123feed3140395e51010f45a3268464c">00082</a> xcb_event_handlers_t <a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>; <a name="l00083"></a><a class="code" href="a00041.html#a327a6e1e08087496e9cb60b9e6f2a499">00083</a> xcb_atom_t <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00041.html#afe7f1cb6978a57f18167c0c7c7db4b12">NUM_ATOMS</a>]; <a name="l00084"></a>00084 <a name="l00085"></a><a class="code" href="a00041.html#a768f07da9e11ab88732a5c550ff49257">00085</a> xcb_window_t <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>; <a name="l00086"></a><a class="code" href="a00071.html#a59ff745efdee354cf2bc3dd370fec282">00086</a> <span class="keywordtype">int</span> <a class="code" href="a00071.html#a59ff745efdee354cf2bc3dd370fec282">num_screens</a> = 0; <a name="l00087"></a>00087 <a name="l00088"></a>00088 <span class="comment">/* The depth of the root screen (used e.g. for creating new pixmaps later) */</span> <a name="l00089"></a><a class="code" href="a00041.html#a5cc2471a026cd3d2a8800e8ab2c9dcb7">00089</a> uint8_t <a class="code" href="a00071.html#a5cc2471a026cd3d2a8800e8ab2c9dcb7">root_depth</a>; <a name="l00090"></a>00090 <a name="l00091"></a>00091 <span class="comment">/* We hope that XKB is supported and set this to false */</span> <a name="l00092"></a><a class="code" href="a00041.html#a213753c490c48df1df94aba1d4840eee">00092</a> <span class="keywordtype">bool</span> <a class="code" href="a00071.html#a213753c490c48df1df94aba1d4840eee">xkb_supported</a> = <span class="keyword">true</span>; <a name="l00093"></a>00093 <a name="l00094"></a>00094 <span class="comment">/*</span> <a name="l00095"></a>00095 <span class="comment"> * This callback is only a dummy, see xcb_prepare_cb and xcb_check_cb.</span> <a name="l00096"></a>00096 <span class="comment"> * See also man libev(3): "ev_prepare" and "ev_check" - customise your event loop</span> <a name="l00097"></a>00097 <span class="comment"> *</span> <a name="l00098"></a>00098 <span class="comment"> */</span> <a name="l00099"></a><a class="code" href="a00071.html#a3afd076b2b7a6629dbdd5ca39bc97e14">00099</a> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="a00071.html#a3afd076b2b7a6629dbdd5ca39bc97e14">xcb_got_event</a>(EV_P_ <span class="keyword">struct</span> ev_io *w, <span class="keywordtype">int</span> revents) { <a name="l00100"></a>00100 <span class="comment">/* empty, because xcb_prepare_cb and xcb_check_cb are used */</span> <a name="l00101"></a>00101 } <a name="l00102"></a>00102 <a name="l00103"></a>00103 <span class="comment">/*</span> <a name="l00104"></a>00104 <span class="comment"> * Flush before blocking (and waiting for new events)</span> <a name="l00105"></a>00105 <span class="comment"> *</span> <a name="l00106"></a>00106 <span class="comment"> */</span> <a name="l00107"></a><a class="code" href="a00071.html#af056ab78448062575ad541c74acf424f">00107</a> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="a00071.html#af056ab78448062575ad541c74acf424f">xcb_prepare_cb</a>(EV_P_ ev_prepare *w, <span class="keywordtype">int</span> revents) { <a name="l00108"></a>00108 xcb_flush(<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>.c); <a name="l00109"></a>00109 } <a name="l00110"></a>00110 <a name="l00111"></a>00111 <span class="comment">/*</span> <a name="l00112"></a>00112 <span class="comment"> * Instead of polling the X connection socket we leave this to</span> <a name="l00113"></a>00113 <span class="comment"> * xcb_poll_for_event() which knows better than we can ever know.</span> <a name="l00114"></a>00114 <span class="comment"> *</span> <a name="l00115"></a>00115 <span class="comment"> */</span> <a name="l00116"></a><a class="code" href="a00071.html#ae803eb28e01465a23d3106d041d20a35">00116</a> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="a00071.html#ae803eb28e01465a23d3106d041d20a35">xcb_check_cb</a>(EV_P_ ev_check *w, <span class="keywordtype">int</span> revents) { <a name="l00117"></a>00117 xcb_generic_event_t *event; <a name="l00118"></a>00118 <a name="l00119"></a>00119 <span class="keywordflow">while</span> ((event = xcb_poll_for_event(<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>.c)) != NULL) { <a name="l00120"></a>00120 xcb_event_handle(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, event); <a name="l00121"></a>00121 free(event); <a name="l00122"></a>00122 } <a name="l00123"></a>00123 } <a name="l00124"></a>00124 <a name="l00125"></a>00125 <span class="comment">/*</span> <a name="l00126"></a>00126 <span class="comment"> * When using xmodmap to change the keyboard mapping, this event</span> <a name="l00127"></a>00127 <span class="comment"> * is only sent via XKB. Therefore, we need this special handler.</span> <a name="l00128"></a>00128 <span class="comment"> *</span> <a name="l00129"></a>00129 <span class="comment"> */</span> <a name="l00130"></a><a class="code" href="a00071.html#a9dee8ad840a7178248adce10de9f168a">00130</a> <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="a00071.html#a9dee8ad840a7178248adce10de9f168a">xkb_got_event</a>(EV_P_ <span class="keyword">struct</span> ev_io *w, <span class="keywordtype">int</span> revents) { <a name="l00131"></a>00131 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Handling XKB event\n"</span>); <a name="l00132"></a>00132 XkbEvent ev; <a name="l00133"></a>00133 <a name="l00134"></a>00134 <span class="comment">/* When using xmodmap, every change (!) gets an own event.</span> <a name="l00135"></a>00135 <span class="comment"> * Therefore, we just read all events and only handle the</span> <a name="l00136"></a>00136 <span class="comment"> * mapping_notify once. */</span> <a name="l00137"></a>00137 <span class="keywordtype">bool</span> mapping_changed = <span class="keyword">false</span>; <a name="l00138"></a>00138 <span class="keywordflow">while</span> (XPending(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>)) { <a name="l00139"></a>00139 XNextEvent(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>, (XEvent*)&ev); <a name="l00140"></a>00140 <span class="comment">/* While we should never receive a non-XKB event,</span> <a name="l00141"></a>00141 <span class="comment"> * better do sanity checking */</span> <a name="l00142"></a>00142 <span class="keywordflow">if</span> (ev.type != <a class="code" href="a00071.html#ab7a200a5f990dc2deaae492aa7b57711">xkb_event_base</a>) <a name="l00143"></a>00143 <span class="keywordflow">continue</span>; <a name="l00144"></a>00144 <a name="l00145"></a>00145 <span class="keywordflow">if</span> (ev.any.xkb_type == XkbMapNotify) { <a name="l00146"></a>00146 mapping_changed = <span class="keyword">true</span>; <a name="l00147"></a>00147 <span class="keywordflow">continue</span>; <a name="l00148"></a>00148 } <a name="l00149"></a>00149 <a name="l00150"></a>00150 <span class="keywordflow">if</span> (ev.any.xkb_type != XkbStateNotify) { <a name="l00151"></a>00151 <a class="code" href="a00044.html#a6828c68e0feb4b7fdfe0fc3ba9f3038b">ELOG</a>(<span class="stringliteral">"Unknown XKB event received (type %d)\n"</span>, ev.any.xkb_type); <a name="l00152"></a>00152 <span class="keywordflow">continue</span>; <a name="l00153"></a>00153 } <a name="l00154"></a>00154 <a name="l00155"></a>00155 <span class="comment">/* See The XKB Extension: Library Specification, section 14.1 */</span> <a name="l00156"></a>00156 <span class="comment">/* We check if the current group (each group contains</span> <a name="l00157"></a>00157 <span class="comment"> * two levels) has been changed. Mode_switch activates</span> <a name="l00158"></a>00158 <span class="comment"> * group XkbGroup2Index */</span> <a name="l00159"></a>00159 <span class="keywordflow">if</span> (<a class="code" href="a00071.html#a2590f55d5727c7d1cd01ebe7fd94a05d">xkb_current_group</a> == ev.state.group) <a name="l00160"></a>00160 <span class="keywordflow">continue</span>; <a name="l00161"></a>00161 <a name="l00162"></a>00162 <a class="code" href="a00071.html#a2590f55d5727c7d1cd01ebe7fd94a05d">xkb_current_group</a> = ev.state.group; <a name="l00163"></a>00163 <a name="l00164"></a>00164 <span class="keywordflow">if</span> (ev.state.group == XkbGroup2Index) { <a name="l00165"></a>00165 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Mode_switch enabled\n"</span>); <a name="l00166"></a>00166 <a class="code" href="a00062.html#a1741cf749eb2243cca453355d3f6879b" title="Grab the bound keys (tell X to send us keypress events for those keycodes).">grab_all_keys</a>(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>, <span class="keyword">true</span>); <a name="l00167"></a>00167 } <a name="l00168"></a>00168 <a name="l00169"></a>00169 <span class="keywordflow">if</span> (ev.state.group == XkbGroup1Index) { <a name="l00170"></a>00170 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Mode_switch disabled\n"</span>); <a name="l00171"></a>00171 <a class="code" href="a00062.html#afa95dc10a37decc54e9a376d0d462048" title="Ungrabs all keys, to be called before re-grabbing the keys because of a mapping_notify...">ungrab_all_keys</a>(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>); <a name="l00172"></a>00172 <a class="code" href="a00062.html#a1741cf749eb2243cca453355d3f6879b" title="Grab the bound keys (tell X to send us keypress events for those keycodes).">grab_all_keys</a>(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>, <span class="keyword">false</span>); <a name="l00173"></a>00173 } <a name="l00174"></a>00174 } <a name="l00175"></a>00175 <a name="l00176"></a>00176 <span class="keywordflow">if</span> (!mapping_changed) <a name="l00177"></a>00177 <span class="keywordflow">return</span>; <a name="l00178"></a>00178 <a name="l00179"></a>00179 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Keyboard mapping changed, updating keybindings\n"</span>); <a name="l00180"></a>00180 xcb_key_symbols_free(<a class="code" href="a00071.html#a5cc0138ae2cf3bbb63a7cae907620797">keysyms</a>); <a name="l00181"></a>00181 <a class="code" href="a00071.html#a5cc0138ae2cf3bbb63a7cae907620797">keysyms</a> = xcb_key_symbols_alloc(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>); <a name="l00182"></a>00182 <a name="l00183"></a>00183 <a class="code" href="a00079.html#aeae86e9fc76e08fd43f142de4d11bba0" title="Finds out which modifier mask is the one for numlock, as the user may change this...">xcb_get_numlock_mask</a>(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>); <a name="l00184"></a>00184 <a name="l00185"></a>00185 <a class="code" href="a00062.html#afa95dc10a37decc54e9a376d0d462048" title="Ungrabs all keys, to be called before re-grabbing the keys because of a mapping_notify...">ungrab_all_keys</a>(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>); <a name="l00186"></a>00186 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Re-grabbing...\n"</span>); <a name="l00187"></a>00187 <a class="code" href="a00062.html#a0ee8ffa5c11aeb96126b36171da84adc" title="Translates keysymbols to keycodes for all bindings which use keysyms.">translate_keysyms</a>(); <a name="l00188"></a>00188 <a class="code" href="a00062.html#a1741cf749eb2243cca453355d3f6879b" title="Grab the bound keys (tell X to send us keypress events for those keycodes).">grab_all_keys</a>(<a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a>, (<a class="code" href="a00071.html#a2590f55d5727c7d1cd01ebe7fd94a05d">xkb_current_group</a> == XkbGroup2Index)); <a name="l00189"></a>00189 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Done\n"</span>); <a name="l00190"></a>00190 } <a name="l00191"></a>00191 <a name="l00192"></a>00192 <a name="l00193"></a><a class="code" href="a00071.html#a7f567e72b4713406998c6192bb2a10e7">00193</a> <span class="keywordtype">int</span> <a class="code" href="a00071.html#a7f567e72b4713406998c6192bb2a10e7">main</a>(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> *argv[], <span class="keywordtype">char</span> *env[]) { <a name="l00194"></a>00194 <span class="keywordtype">int</span> i, screens, opt; <a name="l00195"></a>00195 <span class="keywordtype">char</span> *override_configpath = NULL; <a name="l00196"></a>00196 <span class="keywordtype">bool</span> autostart = <span class="keyword">true</span>; <a name="l00197"></a>00197 <span class="keywordtype">bool</span> only_check_config = <span class="keyword">false</span>; <a name="l00198"></a>00198 <span class="keywordtype">bool</span> force_xinerama = <span class="keyword">false</span>; <a name="l00199"></a>00199 xcb_connection_t *conn; <a name="l00200"></a>00200 xcb_property_handlers_t prophs; <a name="l00201"></a>00201 xcb_intern_atom_cookie_t atom_cookies[<a class="code" href="a00041.html#afe7f1cb6978a57f18167c0c7c7db4b12">NUM_ATOMS</a>]; <a name="l00202"></a>00202 <span class="keyword">static</span> <span class="keyword">struct </span>option long_options[] = { <a name="l00203"></a>00203 {<span class="stringliteral">"no-autostart"</span>, no_argument, 0, <span class="charliteral">'a'</span>}, <a name="l00204"></a>00204 {<span class="stringliteral">"config"</span>, required_argument, 0, <span class="charliteral">'c'</span>}, <a name="l00205"></a>00205 {<span class="stringliteral">"version"</span>, no_argument, 0, <span class="charliteral">'v'</span>}, <a name="l00206"></a>00206 {<span class="stringliteral">"help"</span>, no_argument, 0, <span class="charliteral">'h'</span>}, <a name="l00207"></a>00207 {<span class="stringliteral">"force-xinerama"</span>, no_argument, 0, 0}, <a name="l00208"></a>00208 {0, 0, 0, 0} <a name="l00209"></a>00209 }; <a name="l00210"></a>00210 <span class="keywordtype">int</span> option_index = 0; <a name="l00211"></a>00211 <a name="l00212"></a>00212 setlocale(LC_ALL, <span class="stringliteral">""</span>); <a name="l00213"></a>00213 <a name="l00214"></a>00214 <span class="comment">/* Disable output buffering to make redirects in .xsession actually useful for debugging */</span> <a name="l00215"></a>00215 <span class="keywordflow">if</span> (!isatty(fileno(stdout))) <a name="l00216"></a>00216 setbuf(stdout, NULL); <a name="l00217"></a>00217 <a name="l00218"></a>00218 <a class="code" href="a00071.html#adff3468c46bf36c35842552ad6cd220d">start_argv</a> = argv; <a name="l00219"></a>00219 <a name="l00220"></a>00220 <span class="keywordflow">while</span> ((opt = getopt_long(argc, argv, <span class="stringliteral">"c:Cvahld:V"</span>, long_options, &option_index)) != -1) { <a name="l00221"></a>00221 <span class="keywordflow">switch</span> (opt) { <a name="l00222"></a>00222 <span class="keywordflow">case</span> <span class="charliteral">'a'</span>: <a name="l00223"></a>00223 <a class="code" href="a00044.html#a388edf12256bf73c3a8ee9734c3bd841" title="#__VA_ARGS__ means: leave out __VA_ARGS__ completely if it is empty, that is, delete...">LOG</a>(<span class="stringliteral">"Autostart disabled using -a\n"</span>); <a name="l00224"></a>00224 autostart = <span class="keyword">false</span>; <a name="l00225"></a>00225 <span class="keywordflow">break</span>; <a name="l00226"></a>00226 <span class="keywordflow">case</span> <span class="charliteral">'c'</span>: <a name="l00227"></a>00227 override_configpath = <a class="code" href="a00077.html#a11822d1f4b182be3fa03d2a5af536e1a" title="Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there...">sstrdup</a>(optarg); <a name="l00228"></a>00228 <span class="keywordflow">break</span>; <a name="l00229"></a>00229 <span class="keywordflow">case</span> <span class="charliteral">'C'</span>: <a name="l00230"></a>00230 <a class="code" href="a00044.html#a388edf12256bf73c3a8ee9734c3bd841" title="#__VA_ARGS__ means: leave out __VA_ARGS__ completely if it is empty, that is, delete...">LOG</a>(<span class="stringliteral">"Checking configuration file only (-C)\n"</span>); <a name="l00231"></a>00231 only_check_config = <span class="keyword">true</span>; <a name="l00232"></a>00232 <span class="keywordflow">break</span>; <a name="l00233"></a>00233 <span class="keywordflow">case</span> <span class="charliteral">'v'</span>: <a name="l00234"></a>00234 printf(<span class="stringliteral">"i3 version "</span> I3_VERSION <span class="stringliteral">" © 2009-2010 Michael Stapelberg and contributors\n"</span>); <a name="l00235"></a>00235 exit(EXIT_SUCCESS); <a name="l00236"></a>00236 <span class="keywordflow">case</span> <span class="charliteral">'V'</span>: <a name="l00237"></a>00237 <a class="code" href="a00070.html#a9aeb8f383a036722d9213b750e90703d" title="Set verbosity of i3.">set_verbosity</a>(<span class="keyword">true</span>); <a name="l00238"></a>00238 <span class="keywordflow">break</span>; <a name="l00239"></a>00239 <span class="keywordflow">case</span> <span class="charliteral">'d'</span>: <a name="l00240"></a>00240 <a class="code" href="a00044.html#a388edf12256bf73c3a8ee9734c3bd841" title="#__VA_ARGS__ means: leave out __VA_ARGS__ completely if it is empty, that is, delete...">LOG</a>(<span class="stringliteral">"Enabling debug loglevel %s\n"</span>, optarg); <a name="l00241"></a>00241 <a class="code" href="a00070.html#a71ad89f7f5c5c75b215dfa26a9c1bc43" title="Enables the given loglevel.">add_loglevel</a>(optarg); <a name="l00242"></a>00242 <span class="keywordflow">break</span>; <a name="l00243"></a>00243 <span class="keywordflow">case</span> <span class="charliteral">'l'</span>: <a name="l00244"></a>00244 <span class="comment">/* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */</span> <a name="l00245"></a>00245 <span class="keywordflow">break</span>; <a name="l00246"></a>00246 <span class="keywordflow">case</span> 0: <a name="l00247"></a>00247 <span class="keywordflow">if</span> (strcmp(long_options[option_index].name, <span class="stringliteral">"force-xinerama"</span>) == 0) { <a name="l00248"></a>00248 force_xinerama = <span class="keyword">true</span>; <a name="l00249"></a>00249 <a class="code" href="a00044.html#a6828c68e0feb4b7fdfe0fc3ba9f3038b">ELOG</a>(<span class="stringliteral">"Using Xinerama instead of RandR. This option should be "</span> <a name="l00250"></a>00250 <span class="stringliteral">"avoided at all cost because it does not refresh the list "</span> <a name="l00251"></a>00251 <span class="stringliteral">"of screens, so you cannot configure displays at runtime. "</span> <a name="l00252"></a>00252 <span class="stringliteral">"Please check if your driver really does not support RandR "</span> <a name="l00253"></a>00253 <span class="stringliteral">"and disable this option as soon as you can.\n"</span>); <a name="l00254"></a>00254 <span class="keywordflow">break</span>; <a name="l00255"></a>00255 } <a name="l00256"></a>00256 <span class="comment">/* fall-through */</span> <a name="l00257"></a>00257 <span class="keywordflow">default</span>: <a name="l00258"></a>00258 fprintf(stderr, <span class="stringliteral">"Usage: %s [-c configfile] [-d loglevel] [-a] [-v] [-V] [-C]\n"</span>, argv[0]); <a name="l00259"></a>00259 fprintf(stderr, <span class="stringliteral">"\n"</span>); <a name="l00260"></a>00260 fprintf(stderr, <span class="stringliteral">"-a: disable autostart\n"</span>); <a name="l00261"></a>00261 fprintf(stderr, <span class="stringliteral">"-v: display version and exit\n"</span>); <a name="l00262"></a>00262 fprintf(stderr, <span class="stringliteral">"-V: enable verbose mode\n"</span>); <a name="l00263"></a>00263 fprintf(stderr, <span class="stringliteral">"-d <loglevel>: enable debug loglevel <loglevel>\n"</span>); <a name="l00264"></a>00264 fprintf(stderr, <span class="stringliteral">"-c <configfile>: use the provided configfile instead\n"</span>); <a name="l00265"></a>00265 fprintf(stderr, <span class="stringliteral">"-C: check configuration file and exit\n"</span>); <a name="l00266"></a>00266 fprintf(stderr, <span class="stringliteral">"--force-xinerama: Use Xinerama instead of RandR. This "</span> <a name="l00267"></a>00267 <span class="stringliteral">"option should only be used if you are stuck with the "</span> <a name="l00268"></a>00268 <span class="stringliteral">"nvidia closed source driver which does not support RandR.\n"</span>); <a name="l00269"></a>00269 exit(EXIT_FAILURE); <a name="l00270"></a>00270 } <a name="l00271"></a>00271 } <a name="l00272"></a>00272 <a name="l00273"></a>00273 <a class="code" href="a00044.html#a388edf12256bf73c3a8ee9734c3bd841" title="#__VA_ARGS__ means: leave out __VA_ARGS__ completely if it is empty, that is, delete...">LOG</a>(<span class="stringliteral">"i3 version "</span> I3_VERSION <span class="stringliteral">" starting\n"</span>); <a name="l00274"></a>00274 <a name="l00275"></a>00275 <span class="comment">/* Initialize the table data structures for each workspace */</span> <a name="l00276"></a>00276 <a class="code" href="a00076.html#af025cd3b8bcee08bf8f89ae8c17d5f69" title="Initialize table.">init_table</a>(); <a name="l00277"></a>00277 <a name="l00278"></a>00278 memset(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, 0, <span class="keyword">sizeof</span>(xcb_event_handlers_t)); <a name="l00279"></a>00279 memset(&prophs, 0, <span class="keyword">sizeof</span>(xcb_property_handlers_t)); <a name="l00280"></a>00280 <a name="l00281"></a>00281 conn = <a class="code" href="a00071.html#ada13c42121d64521629e06e7a5e1db16">global_conn</a> = xcb_connect(NULL, &screens); <a name="l00282"></a>00282 <a name="l00283"></a>00283 <span class="keywordflow">if</span> (xcb_connection_has_error(conn)) <a name="l00284"></a>00284 <a class="code" href="a00052.html#a0b2164ee75646f16a7388a36e6800c35">die</a>(<span class="stringliteral">"Cannot open display\n"</span>); <a name="l00285"></a>00285 <a name="l00286"></a>00286 <a class="code" href="a00062.html#a19bff8205cd2bd9492b5f95076dfa3a0" title="Reads the configuration from ~/.i3/config or /etc/i3/config if not found.">load_configuration</a>(conn, override_configpath, <span class="keyword">false</span>); <a name="l00287"></a>00287 <span class="keywordflow">if</span> (only_check_config) { <a name="l00288"></a>00288 <a class="code" href="a00044.html#a388edf12256bf73c3a8ee9734c3bd841" title="#__VA_ARGS__ means: leave out __VA_ARGS__ completely if it is empty, that is, delete...">LOG</a>(<span class="stringliteral">"Done checking configuration file. Exiting.\n"</span>); <a name="l00289"></a>00289 exit(0); <a name="l00290"></a>00290 } <a name="l00291"></a>00291 <a name="l00292"></a>00292 <span class="comment">/* Create the initial container on the first workspace. This used to</span> <a name="l00293"></a>00293 <span class="comment"> * be part of init_table, but since it possibly requires an X</span> <a name="l00294"></a>00294 <span class="comment"> * connection and a loaded configuration (default mode for new</span> <a name="l00295"></a>00295 <span class="comment"> * containers may be stacking, which requires a new window to be</span> <a name="l00296"></a>00296 <span class="comment"> * created), it had to be delayed. */</span> <a name="l00297"></a>00297 <a class="code" href="a00076.html#ac58314a435fd187ce2ed416b9dc8019f" title="Add one column to the table.">expand_table_cols</a>(<a class="code" href="a00047.html#a7d6894360bd1c41e0e6f6d84998c1362">TAILQ_FIRST</a>(<a class="code" href="a00076.html#afb45f3a3a9c66c3e3a5e4d372ae24da7">workspaces</a>)); <a name="l00298"></a>00298 <a class="code" href="a00076.html#a8fb9ac616cc935e2fd54c6bcb6563df1" title="Add one row to the table.">expand_table_rows</a>(<a class="code" href="a00047.html#a7d6894360bd1c41e0e6f6d84998c1362">TAILQ_FIRST</a>(<a class="code" href="a00076.html#afb45f3a3a9c66c3e3a5e4d372ae24da7">workspaces</a>)); <a name="l00299"></a>00299 <a name="l00300"></a>00300 <span class="comment">/* Place requests for the atoms we need as soon as possible */</span> <a name="l00301"></a>00301 <span class="preprocessor"> #define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name);</span> <a name="l00302"></a>00302 <span class="preprocessor"></span> <a name="l00303"></a>00303 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a02709e70342f55474db97400e435c636">_NET_SUPPORTED</a>); <a name="l00304"></a>00304 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635accdb5c5ee0d74dfffda6f4324a9abff5">_NET_WM_STATE_FULLSCREEN</a>); <a name="l00305"></a>00305 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635aabc07cc4cd1aea6087dc5763d82576cf">_NET_SUPPORTING_WM_CHECK</a>); <a name="l00306"></a>00306 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a1dedae1b3288478b95e08984bac0e951">_NET_WM_NAME</a>); <a name="l00307"></a>00307 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a555588bf6061a168cd7526a49dc4b0fa">_NET_WM_STATE</a>); <a name="l00308"></a>00308 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635ad2b0847e09761bd2ad2b6482c51b07ca">_NET_WM_WINDOW_TYPE</a>); <a name="l00309"></a>00309 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a92d29c09b7c0af698c72325a0372126f">_NET_WM_DESKTOP</a>); <a name="l00310"></a>00310 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a2d1c4f653feb0746c9d55bddfa1f8946">_NET_WM_WINDOW_TYPE_DOCK</a>); <a name="l00311"></a>00311 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635afc6c49b0d04427d54227a147e230fa6c">_NET_WM_WINDOW_TYPE_DIALOG</a>); <a name="l00312"></a>00312 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a2e553ea4ae93c2324801a40f52d7a70a">_NET_WM_WINDOW_TYPE_UTILITY</a>); <a name="l00313"></a>00313 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635adc360a29b4d20ba8cd1c999f6077a843">_NET_WM_WINDOW_TYPE_TOOLBAR</a>); <a name="l00314"></a>00314 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a49555c0ebb81f76501d672c92857704a">_NET_WM_WINDOW_TYPE_SPLASH</a>); <a name="l00315"></a>00315 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5171f3918252a26530d02d6a1716ca45">_NET_WM_STRUT_PARTIAL</a>); <a name="l00316"></a>00316 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5d7366da3deea67253099a5c730d4297">WM_PROTOCOLS</a>); <a name="l00317"></a>00317 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a72e98f8036033fc3b9db52933dd749d0">WM_DELETE_WINDOW</a>); <a name="l00318"></a>00318 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635aef8323bb1a48d3826fa5269e578b4a6a">UTF8_STRING</a>); <a name="l00319"></a>00319 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5ce0f911fd3494577cce5417d7b7eea4">WM_STATE</a>); <a name="l00320"></a>00320 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a13d4dbc6987347bcc7c535570b4e6c2b">WM_CLIENT_LEADER</a>); <a name="l00321"></a>00321 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a7b3651a6efcb0970efc89dc301c91e5e">_NET_CURRENT_DESKTOP</a>); <a name="l00322"></a>00322 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635ac34e05dfa966932f57aad3f572ed01f2">_NET_ACTIVE_WINDOW</a>); <a name="l00323"></a>00323 <a class="code" href="a00071.html#a868013b069440d8dff4c0554efbd10c6">REQUEST_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5258a6a20735e2ae242453ddaf60d157">_NET_WORKAREA</a>); <a name="l00324"></a>00324 <a name="l00325"></a>00325 <span class="comment">/* TODO: this has to be more beautiful somewhen */</span> <a name="l00326"></a>00326 <span class="keywordtype">int</span> major, minor, error; <a name="l00327"></a>00327 <a name="l00328"></a>00328 major = XkbMajorVersion; <a name="l00329"></a>00329 minor = XkbMinorVersion; <a name="l00330"></a>00330 <a name="l00331"></a>00331 <span class="keywordtype">int</span> errBase; <a name="l00332"></a>00332 <a name="l00333"></a>00333 <span class="keywordflow">if</span> ((<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a> = XkbOpenDisplay(getenv(<span class="stringliteral">"DISPLAY"</span>), &<a class="code" href="a00071.html#ab7a200a5f990dc2deaae492aa7b57711">xkb_event_base</a>, &errBase, &major, &minor, &error)) == NULL) { <a name="l00334"></a>00334 <a class="code" href="a00044.html#a6828c68e0feb4b7fdfe0fc3ba9f3038b">ELOG</a>(<span class="stringliteral">"ERROR: XkbOpenDisplay() failed, disabling XKB support\n"</span>); <a name="l00335"></a>00335 <a class="code" href="a00071.html#a213753c490c48df1df94aba1d4840eee">xkb_supported</a> = <span class="keyword">false</span>; <a name="l00336"></a>00336 } <a name="l00337"></a>00337 <a name="l00338"></a>00338 <span class="keywordflow">if</span> (<a class="code" href="a00071.html#a213753c490c48df1df94aba1d4840eee">xkb_supported</a>) { <a name="l00339"></a>00339 <span class="keywordflow">if</span> (fcntl(ConnectionNumber(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>), F_SETFD, FD_CLOEXEC) == -1) { <a name="l00340"></a>00340 fprintf(stderr, <span class="stringliteral">"Could not set FD_CLOEXEC on xkbdpy\n"</span>); <a name="l00341"></a>00341 <span class="keywordflow">return</span> 1; <a name="l00342"></a>00342 } <a name="l00343"></a>00343 <a name="l00344"></a>00344 <span class="keywordtype">int</span> i1; <a name="l00345"></a>00345 <span class="keywordflow">if</span> (!XkbQueryExtension(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>,&i1,&<a class="code" href="a00071.html#ab7a200a5f990dc2deaae492aa7b57711">xkb_event_base</a>,&errBase,&major,&minor)) { <a name="l00346"></a>00346 fprintf(stderr, <span class="stringliteral">"XKB not supported by X-server\n"</span>); <a name="l00347"></a>00347 <span class="keywordflow">return</span> 1; <a name="l00348"></a>00348 } <a name="l00349"></a>00349 <span class="comment">/* end of ugliness */</span> <a name="l00350"></a>00350 <a name="l00351"></a>00351 <span class="keywordflow">if</span> (!XkbSelectEvents(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>, XkbUseCoreKbd, <a name="l00352"></a>00352 XkbMapNotifyMask | XkbStateNotifyMask, <a name="l00353"></a>00353 XkbMapNotifyMask | XkbStateNotifyMask)) { <a name="l00354"></a>00354 fprintf(stderr, <span class="stringliteral">"Could not set XKB event mask\n"</span>); <a name="l00355"></a>00355 <span class="keywordflow">return</span> 1; <a name="l00356"></a>00356 } <a name="l00357"></a>00357 } <a name="l00358"></a>00358 <a name="l00359"></a>00359 <span class="comment">/* Initialize event loop using libev */</span> <a name="l00360"></a>00360 <span class="keyword">struct </span>ev_loop *loop = ev_loop_new(0); <a name="l00361"></a>00361 <span class="keywordflow">if</span> (loop == NULL) <a name="l00362"></a>00362 <a class="code" href="a00052.html#a0b2164ee75646f16a7388a36e6800c35">die</a>(<span class="stringliteral">"Could not initialize libev. Bad LIBEV_FLAGS?\n"</span>); <a name="l00363"></a>00363 <a name="l00364"></a>00364 <span class="keyword">struct </span>ev_io *xcb_watcher = <a class="code" href="a00077.html#ad475e1b898d9da9b2a8b92e3da51b3dd" title="Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there...">scalloc</a>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> ev_io)); <a name="l00365"></a>00365 <span class="keyword">struct </span>ev_io *xkb = <a class="code" href="a00077.html#ad475e1b898d9da9b2a8b92e3da51b3dd" title="Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there...">scalloc</a>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> ev_io)); <a name="l00366"></a>00366 <span class="keyword">struct </span>ev_check *xcb_check = <a class="code" href="a00077.html#ad475e1b898d9da9b2a8b92e3da51b3dd" title="Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there...">scalloc</a>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> ev_check)); <a name="l00367"></a>00367 <span class="keyword">struct </span>ev_prepare *xcb_prepare = <a class="code" href="a00077.html#ad475e1b898d9da9b2a8b92e3da51b3dd" title="Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there...">scalloc</a>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> ev_prepare)); <a name="l00368"></a>00368 <a name="l00369"></a>00369 ev_io_init(xcb_watcher, <a class="code" href="a00071.html#a3afd076b2b7a6629dbdd5ca39bc97e14">xcb_got_event</a>, xcb_get_file_descriptor(conn), EV_READ); <a name="l00370"></a>00370 ev_io_start(loop, xcb_watcher); <a name="l00371"></a>00371 <a name="l00372"></a>00372 <span class="keywordflow">if</span> (<a class="code" href="a00071.html#a213753c490c48df1df94aba1d4840eee">xkb_supported</a>) { <a name="l00373"></a>00373 ev_io_init(xkb, <a class="code" href="a00071.html#a9dee8ad840a7178248adce10de9f168a">xkb_got_event</a>, ConnectionNumber(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>), EV_READ); <a name="l00374"></a>00374 ev_io_start(loop, xkb); <a name="l00375"></a>00375 <a name="l00376"></a>00376 <span class="comment">/* Flush the buffer so that libev can properly get new events */</span> <a name="l00377"></a>00377 XFlush(<a class="code" href="a00071.html#a3401bcd302be580b0500474e75726538">xkbdpy</a>); <a name="l00378"></a>00378 } <a name="l00379"></a>00379 <a name="l00380"></a>00380 ev_check_init(xcb_check, <a class="code" href="a00071.html#ae803eb28e01465a23d3106d041d20a35">xcb_check_cb</a>); <a name="l00381"></a>00381 ev_check_start(loop, xcb_check); <a name="l00382"></a>00382 <a name="l00383"></a>00383 ev_prepare_init(xcb_prepare, <a class="code" href="a00071.html#af056ab78448062575ad541c74acf424f">xcb_prepare_cb</a>); <a name="l00384"></a>00384 ev_prepare_start(loop, xcb_prepare); <a name="l00385"></a>00385 <a name="l00386"></a>00386 <span class="comment">/* Grab the server to delay any events until we enter the eventloop */</span> <a name="l00387"></a>00387 xcb_grab_server(conn); <a name="l00388"></a>00388 <a name="l00389"></a>00389 xcb_event_handlers_init(conn, &<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>); <a name="l00390"></a>00390 <a name="l00391"></a>00391 <span class="comment">/* DEBUG: Trap all events and print them */</span> <a name="l00392"></a>00392 <span class="keywordflow">for</span> (i = 2; i < 128; ++i) <a name="l00393"></a>00393 xcb_event_set_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, i, <a class="code" href="a00064.html#a5f13dbbbc2fe5c143d138bba3b873b53">handle_event</a>, 0); <a name="l00394"></a>00394 <a name="l00395"></a>00395 <span class="keywordflow">for</span> (i = 0; i < 256; ++i) <a name="l00396"></a>00396 xcb_event_set_error_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, i, (xcb_generic_error_handler_t)<a class="code" href="a00064.html#a5f13dbbbc2fe5c143d138bba3b873b53">handle_event</a>, 0); <a name="l00397"></a>00397 <a name="l00398"></a>00398 <span class="comment">/* Expose = an Application should redraw itself, in this case it’s our titlebars. */</span> <a name="l00399"></a>00399 xcb_event_set_expose_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#aef74cebc820b8224d196fa6eb9c13ac4" title="Expose event means we should redraw our windows (= title bar).">handle_expose_event</a>, NULL); <a name="l00400"></a>00400 <a name="l00401"></a>00401 <span class="comment">/* Key presses are pretty obvious, I think */</span> <a name="l00402"></a>00402 xcb_event_set_key_press_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#abcdedd21ed4dd7e762b2fb2ac49b6527" title="There was a key press.">handle_key_press</a>, NULL); <a name="l00403"></a>00403 <a name="l00404"></a>00404 <span class="comment">/* Enter window = user moved his mouse over the window */</span> <a name="l00405"></a>00405 xcb_event_set_enter_notify_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#ade0bc204de173bdbeacb7b10b5631aec" title="When the user moves the mouse pointer onto a window, this callback gets called.">handle_enter_notify</a>, NULL); <a name="l00406"></a>00406 <a name="l00407"></a>00407 <span class="comment">/* Button press = user pushed a mouse button over one of our windows */</span> <a name="l00408"></a>00408 xcb_event_set_button_press_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00059.html#ac97f2eddd5082f584d9370459628f503" title="Checks if the button press was on a stack window, handles focus setting and returns...">handle_button_press</a>, NULL); <a name="l00409"></a>00409 <a name="l00410"></a>00410 <span class="comment">/* Map notify = there is a new window */</span> <a name="l00411"></a>00411 xcb_event_set_map_request_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#ae301f3f0db441a1c22a39e88989a96c3" title="A new window appeared on the screen (=was mapped), so let’s manage it.">handle_map_request</a>, &prophs); <a name="l00412"></a>00412 <a name="l00413"></a>00413 <span class="comment">/* Unmap notify = window disappeared. When sent from a client, we don’t manage</span> <a name="l00414"></a>00414 <span class="comment"> it any longer. Usually, the client destroys the window shortly afterwards. */</span> <a name="l00415"></a>00415 xcb_event_set_unmap_notify_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#af9fc851cafbabe50fa229f4bfb5f0d22" title="Our window decorations were unmapped.">handle_unmap_notify_event</a>, NULL); <a name="l00416"></a>00416 <a name="l00417"></a>00417 <span class="comment">/* Destroy notify is handled the same as unmap notify */</span> <a name="l00418"></a>00418 xcb_event_set_destroy_notify_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#a8c3b4a8b74d993af20e5078e4a20efed" title="A destroy notify event is sent when the window is not unmapped, but immediately destroyed...">handle_destroy_notify_event</a>, NULL); <a name="l00419"></a>00419 <a name="l00420"></a>00420 <span class="comment">/* Configure notify = window’s configuration (geometry, stacking, …). We only need</span> <a name="l00421"></a>00421 <span class="comment"> it to set up ignore the following enter_notify events */</span> <a name="l00422"></a>00422 xcb_event_set_configure_notify_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#aa17e023a1acbf56eb18628e82c8ed55e" title="Configuration notifies are only handled because we need to set up ignore for the...">handle_configure_event</a>, NULL); <a name="l00423"></a>00423 <a name="l00424"></a>00424 <span class="comment">/* Configure request = window tried to change size on its own */</span> <a name="l00425"></a>00425 xcb_event_set_configure_request_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#abef279a14e8384ccf48371d6a3f6f962" title="Configure requests are received when the application wants to resize windows on their...">handle_configure_request</a>, NULL); <a name="l00426"></a>00426 <a name="l00427"></a>00427 <span class="comment">/* Motion notify = user moved his cursor (over the root window and may</span> <a name="l00428"></a>00428 <span class="comment"> * cross virtual screen boundaries doing that) */</span> <a name="l00429"></a>00429 xcb_event_set_motion_notify_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#a23c1d18838f1993a18c1bd891a0fcd3e" title="When the user moves the mouse but does not change the active window (e.g.">handle_motion_notify</a>, NULL); <a name="l00430"></a>00430 <a name="l00431"></a>00431 <span class="comment">/* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */</span> <a name="l00432"></a>00432 xcb_event_set_mapping_notify_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#a2ca89397c76485894e1de2fcb65ec697" title="Called when the keyboard mapping changes (for example by using Xmodmap), we need...">handle_mapping_notify</a>, NULL); <a name="l00433"></a>00433 <a name="l00434"></a>00434 <span class="comment">/* Client message are sent to the root window. The only interesting client message</span> <a name="l00435"></a>00435 <span class="comment"> for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */</span> <a name="l00436"></a>00436 xcb_event_set_client_message_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a class="code" href="a00067.html#aa3ab831816987a97999392d7b54e4aee" title="Handle client messages (EWMH).">handle_client_message</a>, NULL); <a name="l00437"></a>00437 <a name="l00438"></a>00438 <span class="comment">/* Initialize the property handlers */</span> <a name="l00439"></a>00439 xcb_property_handlers_init(&prophs, &<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>); <a name="l00440"></a>00440 <a name="l00441"></a>00441 <span class="comment">/* Watch size hints (to obey correct aspect ratio) */</span> <a name="l00442"></a>00442 xcb_property_set_handler(&prophs, WM_NORMAL_HINTS, UINT_MAX, <a class="code" href="a00067.html#a37b6d4793feaffd6a4a25db3416c0d3f" title="Handles the size hints set by a window, but currently only the part necessary for...">handle_normal_hints</a>, NULL); <a name="l00443"></a>00443 <a name="l00444"></a>00444 <span class="comment">/* Get the root window and set the event mask */</span> <a name="l00445"></a>00445 xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens); <a name="l00446"></a>00446 <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a> = root_screen->root; <a name="l00447"></a>00447 <a class="code" href="a00071.html#a5cc2471a026cd3d2a8800e8ab2c9dcb7">root_depth</a> = root_screen->root_depth; <a name="l00448"></a>00448 <a name="l00449"></a>00449 uint32_t mask = XCB_CW_EVENT_MASK; <a name="l00450"></a>00450 uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | <a name="l00451"></a>00451 XCB_EVENT_MASK_STRUCTURE_NOTIFY | <span class="comment">/* when the user adds a screen (e.g. video</span> <a name="l00452"></a>00452 <span class="comment"> projector), the root window gets a</span> <a name="l00453"></a>00453 <span class="comment"> ConfigureNotify */</span> <a name="l00454"></a>00454 XCB_EVENT_MASK_POINTER_MOTION | <a name="l00455"></a>00455 XCB_EVENT_MASK_PROPERTY_CHANGE | <a name="l00456"></a>00456 XCB_EVENT_MASK_ENTER_WINDOW }; <a name="l00457"></a>00457 xcb_void_cookie_t cookie; <a name="l00458"></a>00458 cookie = xcb_change_window_attributes_checked(conn, <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>, mask, values); <a name="l00459"></a>00459 <a class="code" href="a00077.html#ae8ee4cede01d9a00cbeaffbc5f096f8d" title="Checks a generic cookie for errors and quits with the given message if there was...">check_error</a>(conn, cookie, <span class="stringliteral">"Another window manager seems to be running"</span>); <a name="l00460"></a>00460 <a name="l00461"></a>00461 <span class="comment">/* Setup NetWM atoms */</span> <a name="l00462"></a>00462 <span class="preprocessor"> #define GET_ATOM(name) { \</span> <a name="l00463"></a>00463 <span class="preprocessor"> xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, atom_cookies[name], NULL); \</span> <a name="l00464"></a>00464 <span class="preprocessor"> if (!reply) { \</span> <a name="l00465"></a>00465 <span class="preprocessor"> ELOG("Could not get atom " #name "\n"); \</span> <a name="l00466"></a>00466 <span class="preprocessor"> exit(-1); \</span> <a name="l00467"></a>00467 <span class="preprocessor"> } \</span> <a name="l00468"></a>00468 <span class="preprocessor"> atoms[name] = reply->atom; \</span> <a name="l00469"></a>00469 <span class="preprocessor"> free(reply); \</span> <a name="l00470"></a>00470 <span class="preprocessor"> }</span> <a name="l00471"></a>00471 <span class="preprocessor"></span> <a name="l00472"></a>00472 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a02709e70342f55474db97400e435c636">_NET_SUPPORTED</a>); <a name="l00473"></a>00473 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635accdb5c5ee0d74dfffda6f4324a9abff5">_NET_WM_STATE_FULLSCREEN</a>); <a name="l00474"></a>00474 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635aabc07cc4cd1aea6087dc5763d82576cf">_NET_SUPPORTING_WM_CHECK</a>); <a name="l00475"></a>00475 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a1dedae1b3288478b95e08984bac0e951">_NET_WM_NAME</a>); <a name="l00476"></a>00476 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a555588bf6061a168cd7526a49dc4b0fa">_NET_WM_STATE</a>); <a name="l00477"></a>00477 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635ad2b0847e09761bd2ad2b6482c51b07ca">_NET_WM_WINDOW_TYPE</a>); <a name="l00478"></a>00478 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a92d29c09b7c0af698c72325a0372126f">_NET_WM_DESKTOP</a>); <a name="l00479"></a>00479 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a2d1c4f653feb0746c9d55bddfa1f8946">_NET_WM_WINDOW_TYPE_DOCK</a>); <a name="l00480"></a>00480 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635afc6c49b0d04427d54227a147e230fa6c">_NET_WM_WINDOW_TYPE_DIALOG</a>); <a name="l00481"></a>00481 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a2e553ea4ae93c2324801a40f52d7a70a">_NET_WM_WINDOW_TYPE_UTILITY</a>); <a name="l00482"></a>00482 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635adc360a29b4d20ba8cd1c999f6077a843">_NET_WM_WINDOW_TYPE_TOOLBAR</a>); <a name="l00483"></a>00483 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a49555c0ebb81f76501d672c92857704a">_NET_WM_WINDOW_TYPE_SPLASH</a>); <a name="l00484"></a>00484 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5171f3918252a26530d02d6a1716ca45">_NET_WM_STRUT_PARTIAL</a>); <a name="l00485"></a>00485 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5d7366da3deea67253099a5c730d4297">WM_PROTOCOLS</a>); <a name="l00486"></a>00486 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a72e98f8036033fc3b9db52933dd749d0">WM_DELETE_WINDOW</a>); <a name="l00487"></a>00487 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635aef8323bb1a48d3826fa5269e578b4a6a">UTF8_STRING</a>); <a name="l00488"></a>00488 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5ce0f911fd3494577cce5417d7b7eea4">WM_STATE</a>); <a name="l00489"></a>00489 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a13d4dbc6987347bcc7c535570b4e6c2b">WM_CLIENT_LEADER</a>); <a name="l00490"></a>00490 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a7b3651a6efcb0970efc89dc301c91e5e">_NET_CURRENT_DESKTOP</a>); <a name="l00491"></a>00491 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635ac34e05dfa966932f57aad3f572ed01f2">_NET_ACTIVE_WINDOW</a>); <a name="l00492"></a>00492 <a class="code" href="a00071.html#a8b894f92a3b1fcc9d1332bcadd9be933">GET_ATOM</a>(<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a5258a6a20735e2ae242453ddaf60d157">_NET_WORKAREA</a>); <a name="l00493"></a>00493 <a name="l00494"></a>00494 xcb_property_set_handler(&prophs, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635ad2b0847e09761bd2ad2b6482c51b07ca">_NET_WM_WINDOW_TYPE</a>], UINT_MAX, <a class="code" href="a00067.html#a9f7d547fc847e3dc11747b7d04077c46" title="Handles _NET_WM_WINDOW_TYPE changes.">handle_window_type</a>, NULL); <a name="l00495"></a>00495 <span class="comment">/* TODO: In order to comply with EWMH, we have to watch _NET_WM_STRUT_PARTIAL */</span> <a name="l00496"></a>00496 <a name="l00497"></a>00497 <span class="comment">/* Watch _NET_WM_NAME (= title of the window in UTF-8) property */</span> <a name="l00498"></a>00498 xcb_property_set_handler(&prophs, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a1dedae1b3288478b95e08984bac0e951">_NET_WM_NAME</a>], 128, <a class="code" href="a00067.html#a763f921cc825269f3034ac3237f911f2" title="Called when a window changes its title.">handle_windowname_change</a>, NULL); <a name="l00499"></a>00499 <a name="l00500"></a>00500 <span class="comment">/* Watch WM_TRANSIENT_FOR property (to which client this popup window belongs) */</span> <a name="l00501"></a>00501 xcb_property_set_handler(&prophs, WM_TRANSIENT_FOR, UINT_MAX, <a class="code" href="a00067.html#a770ba9d5b30d95d843fe637e2b3910eb" title="Handles the transient for hints set by a window, signalizing that this window is...">handle_transient_for</a>, NULL); <a name="l00502"></a>00502 <a name="l00503"></a>00503 <span class="comment">/* Watch WM_NAME (= title of the window in compound text) property for legacy applications */</span> <a name="l00504"></a>00504 xcb_watch_wm_name(&prophs, 128, <a class="code" href="a00067.html#ac3e59ebb6684722fada02f66582a1787" title="We handle legacy window names (titles) which are in COMPOUND_TEXT encoding.">handle_windowname_change_legacy</a>, NULL); <a name="l00505"></a>00505 <a name="l00506"></a>00506 <span class="comment">/* Watch WM_CLASS (= class of the window) */</span> <a name="l00507"></a>00507 xcb_property_set_handler(&prophs, WM_CLASS, 128, <a class="code" href="a00067.html#a3fdeb5f8c0fbef80784d1d62e4653ed9" title="Store the window classes for jumping to them later.">handle_windowclass_change</a>, NULL); <a name="l00508"></a>00508 <a name="l00509"></a>00509 <span class="comment">/* Watch WM_CLIENT_LEADER (= logical parent window for toolbars etc.) */</span> <a name="l00510"></a>00510 xcb_property_set_handler(&prophs, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a13d4dbc6987347bcc7c535570b4e6c2b">WM_CLIENT_LEADER</a>], UINT_MAX, <a class="code" href="a00067.html#a3651e94bba743f088fd461a90892ff2f" title="Handles changes of the WM_CLIENT_LEADER atom which specifies if this is a toolwindow...">handle_clientleader_change</a>, NULL); <a name="l00511"></a>00511 <a name="l00512"></a>00512 <span class="comment">/* Watch WM_HINTS (contains the urgent property) */</span> <a name="l00513"></a>00513 xcb_property_set_handler(&prophs, WM_HINTS, UINT_MAX, <a class="code" href="a00067.html#a875fb3362eee6f327b57a6033ed29a51" title="Handles the WM_HINTS property for extracting the urgency state of the window.">handle_hints</a>, NULL); <a name="l00514"></a>00514 <a name="l00515"></a>00515 <span class="comment">/* Set up the atoms we support */</span> <a name="l00516"></a>00516 <a class="code" href="a00077.html#ae8ee4cede01d9a00cbeaffbc5f096f8d" title="Checks a generic cookie for errors and quits with the given message if there was...">check_error</a>(conn, xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE, <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635a02709e70342f55474db97400e435c636">_NET_SUPPORTED</a>], <a name="l00517"></a>00517 ATOM, 32, 7, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>), <span class="stringliteral">"Could not set _NET_SUPPORTED"</span>); <a name="l00518"></a>00518 <span class="comment">/* Set up the window manager’s name */</span> <a name="l00519"></a>00519 xcb_change_property(conn, XCB_PROP_MODE_REPLACE, <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635aabc07cc4cd1aea6087dc5763d82576cf">_NET_SUPPORTING_WM_CHECK</a>], WINDOW, 32, 1, &<a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>); <a name="l00520"></a>00520 xcb_change_property(conn, XCB_PROP_MODE_REPLACE, <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>, <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[_NET_WM_NAME], <a class="code" href="a00071.html#a327a6e1e08087496e9cb60b9e6f2a499">atoms</a>[<a class="code" href="a00054.html#a726ca809ffd3d67ab4b8476646f26635aef8323bb1a48d3826fa5269e578b4a6a">UTF8_STRING</a>], 8, strlen(<span class="stringliteral">"i3"</span>), <span class="stringliteral">"i3"</span>); <a name="l00521"></a>00521 <a name="l00522"></a>00522 <a class="code" href="a00071.html#a5cc0138ae2cf3bbb63a7cae907620797">keysyms</a> = xcb_key_symbols_alloc(conn); <a name="l00523"></a>00523 <a name="l00524"></a>00524 <a class="code" href="a00079.html#aeae86e9fc76e08fd43f142de4d11bba0" title="Finds out which modifier mask is the one for numlock, as the user may change this...">xcb_get_numlock_mask</a>(conn); <a name="l00525"></a>00525 <a name="l00526"></a>00526 <a class="code" href="a00062.html#a0ee8ffa5c11aeb96126b36171da84adc" title="Translates keysymbols to keycodes for all bindings which use keysyms.">translate_keysyms</a>(); <a name="l00527"></a>00527 <a class="code" href="a00062.html#a1741cf749eb2243cca453355d3f6879b" title="Grab the bound keys (tell X to send us keypress events for those keycodes).">grab_all_keys</a>(conn, <span class="keyword">false</span>); <a name="l00528"></a>00528 <a name="l00529"></a>00529 <span class="keywordtype">int</span> randr_base; <a name="l00530"></a>00530 <span class="keywordflow">if</span> (force_xinerama) { <a name="l00531"></a>00531 <a class="code" href="a00080.html#a93044db4172ab2447725a2bee3065931" title="We have just established a connection to the X server and need the initial Xinerama...">initialize_xinerama</a>(conn); <a name="l00532"></a>00532 } <span class="keywordflow">else</span> { <a name="l00533"></a>00533 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Checking for XRandR...\n"</span>); <a name="l00534"></a>00534 <a class="code" href="a00073.html#a6a7a017cf0668c2b9aba5011bdd7e9f3" title="We have just established a connection to the X server and need the initial XRandR...">initialize_randr</a>(conn, &randr_base); <a name="l00535"></a>00535 <a name="l00536"></a>00536 xcb_event_set_handler(&<a class="code" href="a00071.html#a123feed3140395e51010f45a3268464c">evenths</a>, <a name="l00537"></a>00537 randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY, <a name="l00538"></a>00538 <a class="code" href="a00067.html#a38db143e8cde0e72a7fe1aa1a9412c0e" title="Gets triggered upon a RandR screen change event, that is when the user changes the...">handle_screen_change</a>, <a name="l00539"></a>00539 NULL); <a name="l00540"></a>00540 } <a name="l00541"></a>00541 <a name="l00542"></a>00542 xcb_flush(conn); <a name="l00543"></a>00543 <a name="l00544"></a>00544 <span class="comment">/* Get pointer position to see on which screen we’re starting */</span> <a name="l00545"></a>00545 xcb_query_pointer_reply_t *reply; <a name="l00546"></a>00546 <span class="keywordflow">if</span> ((reply = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>), NULL)) == NULL) { <a name="l00547"></a>00547 <a class="code" href="a00044.html#a6828c68e0feb4b7fdfe0fc3ba9f3038b">ELOG</a>(<span class="stringliteral">"Could not get pointer position\n"</span>); <a name="l00548"></a>00548 <span class="keywordflow">return</span> 1; <a name="l00549"></a>00549 } <a name="l00550"></a>00550 <a name="l00551"></a>00551 <a class="code" href="a00026.html" title="An Output is a physical output on your graphics driver.">Output</a> *screen = <a class="code" href="a00073.html#abb7e75366265212195afd09ab85235f6" title="Returns the active (!) output which contains the coordinates x, y or NULL if there...">get_output_containing</a>(reply->root_x, reply->root_y); <a name="l00552"></a>00552 <span class="keywordflow">if</span> (screen == NULL) { <a name="l00553"></a>00553 <a class="code" href="a00044.html#a6828c68e0feb4b7fdfe0fc3ba9f3038b">ELOG</a>(<span class="stringliteral">"ERROR: No screen at %d x %d, starting on the first screen\n"</span>, <a name="l00554"></a>00554 reply->root_x, reply->root_y); <a name="l00555"></a>00555 screen = <a class="code" href="a00073.html#a514adc4dcfc06b1e9329e41633c65fb0" title="Returns the first output which is active.">get_first_output</a>(); <a name="l00556"></a>00556 } <a name="l00557"></a>00557 <a name="l00558"></a>00558 <a class="code" href="a00044.html#a287e239c800086178591f5e53f5bb82c">DLOG</a>(<span class="stringliteral">"Starting on %p\n"</span>, screen-><a class="code" href="a00026.html#a9bcf702b65d8f47f98eafbefff529ffe" title="Current workspace selected on this virtual screen.">current_workspace</a>); <a name="l00559"></a>00559 <a class="code" href="a00076.html#a6dc99dff7063221c1096561951c0386b">c_ws</a> = screen-><a class="code" href="a00026.html#a9bcf702b65d8f47f98eafbefff529ffe" title="Current workspace selected on this virtual screen.">current_workspace</a>; <a name="l00560"></a>00560 <a name="l00561"></a>00561 <a class="code" href="a00072.html#a525375308e06d233e560f4e739e02ca6" title="Go through all existing windows (if the window manager is restarted) and manage them...">manage_existing_windows</a>(conn, &prophs, <a class="code" href="a00071.html#a768f07da9e11ab88732a5c550ff49257">root</a>); <a name="l00562"></a>00562 <a name="l00563"></a>00563 <span class="comment">/* Create the UNIX domain socket for IPC */</span> <a name="l00564"></a>00564 <span class="keywordflow">if</span> (<a class="code" href="a00062.html#a4a8dd3a2de125b72d4fe6251a0a271b5">config</a>.<a class="code" href="a00010.html#a79aa7dde4fb7016d2e71a6433ec467b1">ipc_socket_path</a> != NULL) { <a name="l00565"></a>00565 <span class="keywordtype">int</span> ipc_socket = <a class="code" href="a00068.html#a173c2426068f80edfacc45e1fca642d4" title="Creates the UNIX domain socket at the given path, sets it to non-blocking mode, bind()s...">ipc_create_socket</a>(<a class="code" href="a00062.html#a4a8dd3a2de125b72d4fe6251a0a271b5">config</a>.<a class="code" href="a00010.html#a79aa7dde4fb7016d2e71a6433ec467b1">ipc_socket_path</a>); <a name="l00566"></a>00566 <span class="keywordflow">if</span> (ipc_socket == -1) { <a name="l00567"></a>00567 <a class="code" href="a00044.html#a6828c68e0feb4b7fdfe0fc3ba9f3038b">ELOG</a>(<span class="stringliteral">"Could not create the IPC socket, IPC disabled\n"</span>); <a name="l00568"></a>00568 } <span class="keywordflow">else</span> { <a name="l00569"></a>00569 <span class="keyword">struct </span>ev_io *ipc_io = <a class="code" href="a00077.html#ad475e1b898d9da9b2a8b92e3da51b3dd" title="Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there...">scalloc</a>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> ev_io)); <a name="l00570"></a>00570 ev_io_init(ipc_io, <a class="code" href="a00068.html#ab60981ffa93c190e40d52e05f6c8a4d8" title="Handler for activity on the listening socket, meaning that a new client has just...">ipc_new_client</a>, ipc_socket, EV_READ); <a name="l00571"></a>00571 ev_io_start(loop, ipc_io); <a name="l00572"></a>00572 } <a name="l00573"></a>00573 } <a name="l00574"></a>00574 <a name="l00575"></a>00575 <span class="comment">/* Handle the events which arrived until now */</span> <a name="l00576"></a>00576 <a class="code" href="a00071.html#ae803eb28e01465a23d3106d041d20a35">xcb_check_cb</a>(NULL, NULL, 0); <a name="l00577"></a>00577 <a name="l00578"></a>00578 <a class="code" href="a00075.html#ae057b3065391c2db8120a38fe9d805b4" title="Setup signal handlers to safely handle SIGSEGV and SIGFPE.">setup_signal_handler</a>(); <a name="l00579"></a>00579 <a name="l00580"></a>00580 <span class="comment">/* Ignore SIGPIPE to survive errors when an IPC client disconnects</span> <a name="l00581"></a>00581 <span class="comment"> * while we are sending him a message */</span> <a name="l00582"></a>00582 signal(SIGPIPE, SIG_IGN); <a name="l00583"></a>00583 <a name="l00584"></a>00584 <span class="comment">/* Ungrab the server to receive events and enter libev’s eventloop */</span> <a name="l00585"></a>00585 xcb_ungrab_server(conn); <a name="l00586"></a>00586 <a name="l00587"></a>00587 <span class="comment">/* Autostarting exec-lines */</span> <a name="l00588"></a>00588 <span class="keyword">struct </span><a class="code" href="a00002.html" title="Holds a command specified by an exec-line in the config (see src/config.c).">Autostart</a> *exec; <a name="l00589"></a>00589 <span class="keywordflow">if</span> (autostart) { <a name="l00590"></a>00590 <a class="code" href="a00047.html#a16e5fc168e7f3494d4b1df54447d871e">TAILQ_FOREACH</a>(exec, &<a class="code" href="a00071.html#adc8cf28482f0bbe29f8bdcba0e32d16f">autostarts</a>, <a class="code" href="a00071.html#adc8cf28482f0bbe29f8bdcba0e32d16f">autostarts</a>) { <a name="l00591"></a>00591 <a class="code" href="a00044.html#a388edf12256bf73c3a8ee9734c3bd841" title="#__VA_ARGS__ means: leave out __VA_ARGS__ completely if it is empty, that is, delete...">LOG</a>(<span class="stringliteral">"auto-starting %s\n"</span>, exec-><a class="code" href="a00002.html#a6286090e69f758678cafeb975607ff97" title="Command, like in command mode.">command</a>); <a name="l00592"></a>00592 <a class="code" href="a00077.html#a4a1b0dbf1f2e37a0ad5a0f6cc786225c" title="Starts the given application by passing it through a shell.">start_application</a>(exec-><a class="code" href="a00002.html#a6286090e69f758678cafeb975607ff97" title="Command, like in command mode.">command</a>); <a name="l00593"></a>00593 } <a name="l00594"></a>00594 } <a name="l00595"></a>00595 <a name="l00596"></a>00596 ev_loop(loop, 0); <a name="l00597"></a>00597 <a name="l00598"></a>00598 <span class="comment">/* not reached */</span> <a name="l00599"></a>00599 <span class="keywordflow">return</span> 0; <a name="l00600"></a>00600 } </pre></div></div> <hr class="footer"/><address style="text-align: right;"><small>Generated by <a href="http://www.doxygen.org/index.html"> <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.2-20100208 </small></address> </body> </html>