Codebase list i3-wm / cb5fd5d
Update upstream source from tag 'upstream/4.21' Update to upstream version '4.21' with Debian dir cc7789f614727be2ce7bc427728fdcdb3b9d1a73 Jakob Haufe 1 year, 7 months ago
132 changed file(s) with 2290 addition(s) and 544 deletion(s). Raw diff Collapse all Expand all
4040 * Use `clang-format` to format your code.
4141 * Run the [testsuite](https://i3wm.org/docs/testsuite.html)
4242 * If your changes should be reported on the next release's changelog, also
43 update the [RELEASE-notes-next](../RELEASE-notes-next) file in the root
44 folder. Example of changes that should be reported are bug fixes present in
45 the latest stable version of i3 and new enhancements. Example of changes that
46 should not be reported are minor code improvements, documentation, regression
47 and fixes for bugs that were introduced in the `next` branch.
43 add a small single-line file starting with a number (see examples) containing
44 a short explanation of your change either in the
45 [changes](../release-notes/changes) or the
46 [bugfixes](../release-notes/bugfixes/) folder. Example of changes that should
47 be reported are bug fixes present in the latest stable version of i3 and new
48 enhancements. Example of changes that should not be reported are minor code
49 improvements, documentation, regression and fixes for bugs that were
50 introduced in the `next` branch.
4851
4952 ## Finding something to do
5053
4444 echo "::group::Ubuntu i386"
4545 ./travis/skip-pkg.sh || docker pull ${{ env.BASENAME_UBUNTU_386 }} || ./travis/docker-build-and-push.sh ${{ env.BASENAME_UBUNTU_386 }} travis/travis-base-ubuntu-386.Dockerfile
4646 echo "::endgroup::"
47 - name: verify safe wrapper functions are used
48 run: |
49 docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/check-safe-wrappers.sh
50 - name: verify code formatting
51 run: |
52 docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 ${{ env.BASENAME }} ./travis/check-formatting.sh
5347 - name: build i3
5448 run: |
5549 docker run -v $PWD:/usr/src/i3/ -w /usr/src/i3 -e CC ${{ env.BASENAME }} /bin/sh -c 'rm -rf build; mkdir -p build && cd build && CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Wstrict-prototypes -Wmissing-prototypes -Werror -fno-common" meson .. -Ddocs=true -Dmans=true -Db_sanitize=address && ninja -v'
9185 - name: push docs to GitHub pages
9286 run: |
9387 ./travis/skip-pkg.sh || travis/deploy-github-pages.sh
88 formatting:
89 name: Check formatting
90 runs-on: ubuntu-latest
91 steps:
92 - uses: actions/checkout@v2
93 - name: check & print release notes
94 run: ./release-notes/generator.pl
95 - name: Install dependencies
96 run: |
97 sudo apt-get install -y clang-format-10
98 - name: Check formatting
99 run: clang-format-10 --dry-run --Werror $(git ls-files '*.c' '*.h')
100 - name: Verify safe wrapper functions are used
101 run: ./travis/check-safe-wrappers.sh
0 *.o
1 tags
2 include/GENERATED_*.h
3 include/all.h.pch
4 *~
5 *.swp
6 *.gcda
7 *.gcno
8 *.dSYM
9 test.commands_parser
10 test.config_parser
11 testcases/MYMETA.json
12 testcases/MYMETA.yml
13 testcases/blib/
14 testcases/pm_to_blib
15 AnyEvent-I3/Makefile
16 AnyEvent-I3/META.yml
17 AnyEvent-I3/MYMETA.json
18 AnyEvent-I3/MYMETA.yml
19 AnyEvent-I3/blib/
20 AnyEvent-I3/inc/
21 AnyEvent-I3/pm_to_blib
22 *.output
23 *.tab.*
24 *.yy.c
25 man/*.1
26 man/*.xml
27 man/*.html
28 *.tar.bz2*
29 i3
30 i3-input/i3-input
31 i3-nagbar/i3-nagbar
32 i3-msg/i3-msg
33 i3-config-wizard/i3-config-wizard
34 i3-dump-log/i3-dump-log
35 libi3.a
36 docs/*.pdf
37 docs/*.html
38 !/docs/refcard.html
39 i3-command-parser.stamp
40 i3-config-parser.stamp
41 .clang_complete
42 compile_commands.json
43 /.ccls-cache
44 /.clangd
45 LAST_VERSION
46
47 # We recommend building in a subdirectory called build.
48 # If you chose a different directory name,
49 # it is up to you to arrange for it to be ignored by git,
50 # e.g. by listing your directory in .git/info/exclude.
51 /build
52
+0
-27
RELEASE-NOTES-4.20.1 less more
0
1 ┌──────────────────────────────┐
2 │ Release notes for i3 v4.20.1 │
3 └──────────────────────────────┘
4
5 This is i3 v4.20.1. This version is considered stable. All users of i3 are
6 strongly encouraged to upgrade.
7
8 ┌────────────────────────────┐
9 │ Bugfixes │
10 └────────────────────────────┘
11
12 • i3bar: fix crash with multiple monitors
13 • xmlto: fix broken .TH line by extending title length
14 • i3-msg: fix --raw short form (-r) in manpage
15 • libi3: add missing sys/stat.h header
16 • use getcwd(NULL, 0) instead of GNU extension get_current_dir_name()
17
18 ┌────────────────────────────┐
19 │ Thanks! │
20 └────────────────────────────┘
21
22 Thanks for testing, bugfixes, discussions and everything I forgot go out to:
23
24 rvalieris, Jakob Haufe, lycurgus, Baptiste Daroussin
25
26 -- Michael Stapelberg, 2021-11-03
0
1 ┌──────────────────────────────┐
2 │ Release notes for i3 v4.21 │
3 └──────────────────────────────┘
4
5 This is i3 v4.21. This version is considered stable. All users of i3 are
6 strongly encouraged to upgrade.
7
8 The biggest change in this release is that you can now drag tiling windows
9 with your mouse (floating windows could already be dragged). For more details
10 on how to use this feature, please refer to the userguide:
11
12 https://i3wm.org/docs/userguide.html#_moving_tiling_containers_with_the_mouse
13
14 A big thank you goes out to our core i3 developer Orestis Floros who made this
15 feature possible, based on previous work from Michael Forster and Tony Crisci!
16
17 ┌────────────────────────────┐
18 │ Changes in i3 v4.21 │
19 └────────────────────────────┘
20
21 • Allow dragging tiling windows with the mouse
22 • Add client.focused_tab_title color option
23 • Add support for multiple output names in the focus command,
24 allowing users to cycle focus between e.g. VGA1 and LVDS1 but not DVI0.
25 • Add a toggle option to the title_window_icon command
26 • i3 switched from the obsolete PCRE 8.x regular expression matching
27 library to the current PCRE2 10.x version.
28
29 ┌────────────────────────────┐
30 │ Bugfixes │
31 └────────────────────────────┘
32
33 • docs/ipc: document all window_type values
34 • docs/userguide: clarify the difference between the “workspace N” and
35 “workspace number N” commands
36 • i3bar: fix default font not being applied to bars if defined after bar block
37 • i3-dmenu-desktop: add backslashes for the exec command,
38 which fixes opening some .desktop files (e.g. electrum)
39 • i3-sensible-pager: sanitize LESS environment variable to remove -E or -F
40 • testsuite: catch i3 crashes instead of hanging on crash
41 • Fix logging on machines with 256 GB of RAM
42 • Do not replace existing IPC socket on start, to prevent clobbering
43 the IPC socket when running i3 within i3 (e.g. in Xepyhr, for development)
44 • Refuse to start without a valid IPC socket
45 • Fix focus when moving container between outputs with mouse warp and
46 focus_follows_mouse
47 • Fix endless loop with transient_for windows
48 • Fix wrong “failed” IPC reply on move workspace to output
49 • Fix WM registration selection (from WM_S_S<screen> to WM_S<screen>)
50 • avoid graphics artifacts when changing the layout tree by
51 initializing surfaces to all black
52 • update parent split con titles when child container swaps position with
53 another child container
54 • Fix segfault if command in bindsym is empty
55 • Fix segfault with explicit mode "default" key bindings
56 • Fix crash if config contains nested variables.
57 • strip trailing whitespace in bar output names
58 • Fix crash with long commands
59 • Fix changing borders by restoring BS_NORMAL _MOTIF_WM_HINTS correctly
60
61 ┌────────────────────────────┐
62 │ Thanks! │
63 └────────────────────────────┘
64
65 Thanks for testing, bugfixes, discussions and everything I forgot go out to:
66
67 André Silva, Anton Älgmyr, Baptiste Daroussin, bodea, Chris Templin, George
68 Rodrigues, Gergely Risko, Ingo Bürk, Jakob Haufe, Jay Ta'ala, Jeff Smith, Jonta,
69 Josh Soref, Kjetil Torgrim Homme, lycurgus, mariano, Michael Forster, Orestis
70 Floros, paperluigis, Peder Stray, rvalieris, sergio, Tony Crisci, takelley1, Uli
71 Schlachter, viri, zhiv-git, zhrvn
72
73 -- Michael Stapelberg, 2021-10-19
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>Debugging i3: How To</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
956956 <div id="footer">
957957 <div id="footer-text">
958958 Last updated
959 2021-11-03 09:23:08 CET
959 2022-09-21 18:26:43 CEST
960960 </div>
961961 </div>
962962 </body>
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>Hacking i3: How To</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
22822282 <div id="footer">
22832283 <div id="footer-text">
22842284 Last updated
2285 2021-11-03 09:23:08 CET
2285 2022-09-21 18:26:43 CEST
22862286 </div>
22872287 </div>
22882288 </body>
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>i3bar input protocol</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
12201220 <div id="footer">
12211221 <div id="footer-text">
12221222 Last updated
1223 2021-11-03 09:23:08 CET
1223 2022-09-21 18:26:43 CEST
12241224 </div>
12251225 </div>
12261226 </body>
422422 following list: *title*, *instance*, *class*, *window_role*, *machine*
423423 and *transient_for*.
424424 window_type (string)::
425 The window type (_NET_WM_WINDOW_TYPE). Possible values are undefined, normal,
426 dialog, utility, toolbar, splash, menu, dropdown_menu, popup_menu, tooltip and
427 notification.
425 The window type (_NET_WM_WINDOW_TYPE). Possible values are `undefined`,
426 unknown, normal, dialog, utility, toolbar, splash, menu, dropdown_menu,
427 popup_menu, tooltip and notification.
428428 urgent (bool)::
429429 Whether this container (window, split container, floating container or
430430 workspace) has the urgency hint set, directly or indirectly. All parent
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>IPC interface (interprocess communication)</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
14891489 </dt>
14901490 <dd>
14911491 <p>
1492 The window type (_NET_WM_WINDOW_TYPE). Possible values are undefined, normal,
1493 dialog, utility, toolbar, splash, menu, dropdown_menu, popup_menu, tooltip and
1494 notification.
1492 The window type (_NET_WM_WINDOW_TYPE). Possible values are <code>undefined</code>,
1493 unknown, normal, dialog, utility, toolbar, splash, menu, dropdown_menu,
1494 popup_menu, tooltip and notification.
14951495 </p>
14961496 </dd>
14971497 <dt class="hdlist1">
28672867 <div id="footer">
28682868 <div id="footer-text">
28692869 Last updated
2870 2021-11-03 09:23:08 CET
2870 2022-09-21 18:26:43 CEST
28712871 </div>
28722872 </div>
28732873 </body>
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>Layout saving in i3</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
10151015 <div id="footer">
10161016 <div id="footer-text">
10171017 Last updated
1018 2021-11-03 09:23:08 CET
1018 2022-09-21 18:26:43 CEST
10191019 </div>
10201020 </div>
10211021 </body>
3838 <li class='indexItem indexItem2'><a href='#get_dock_clients(%5B_%24dockarea_%5D)'>get_dock_clients([ $dockarea ])</a>
3939 <li class='indexItem indexItem2'><a href='#cmd(%24command)'>cmd($command)</a>
4040 <li class='indexItem indexItem2'><a href='#workspace_exists(%24workspace)'>workspace_exists($workspace)</a>
41 <li class='indexItem indexItem2'><a href='#focused_output'>focused_output</a>
4142 <li class='indexItem indexItem2'><a href='#focused_ws'>focused_ws</a>
4243 <li class='indexItem indexItem2'><a href='#sync_with_i3(%5B_%24args_%5D)'>sync_with_i3([ $args ])</a>
4344 <li class='indexItem indexItem2'><a href='#exit_gracefully(%24pid%2C_%5B_%24socketpath_%5D)'>exit_gracefully($pid, [ $socketpath ])</a>
320321
321322 ok(workspace_exists($old_ws), &#39;old workspace still exists&#39;);</tt></pre>
322323 <h2><a class='u' href='#___top' title='click to go to top of document'
324 name="focused_output"
325 >focused_output</a></h2>
326
327 <p>Returns the name of the currently focused output.</p>
328 <pre><tt> is(focused_output, &#39;fake-0&#39;, &#39;i3 starts on output 0&#39;);</tt></pre>
329 <h2><a class='u' href='#___top' title='click to go to top of document'
323330 name="focused_ws"
324331 >focused_ws</a></h2>
325332
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>The multi-monitor situation</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
815815 <div id="footer">
816816 <div id="footer-text">
817817 Last updated
818 2021-11-03 09:23:08 CET
818 2022-09-21 18:26:43 CEST
819819 </div>
820820 </div>
821821 </body>
33 September 2012
44
55 This document explains how the i3 testsuite works, how to use it and extend it.
6 It is targeted at developers who not necessarily have been doing testing before
7 or have not been testing in Perl before. In general, the testsuite is not of
6 It is targeted at developers who haven't necessarily done testing before,
7 or have not used Perl for testing before. In general, the testsuite is not of
88 interest for end users.
9
109
1110 == Introduction
1211
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>i3 testsuite</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
746746 <div id="preamble">
747747 <div class="sectionbody">
748748 <div class="paragraph"><p>This document explains how the i3 testsuite works, how to use it and extend it.
749 It is targeted at developers who not necessarily have been doing testing before
750 or have not been testing in Perl before. In general, the testsuite is not of
749 It is targeted at developers who haven&#8217;t necessarily done testing before,
750 or have not used Perl for testing before. In general, the testsuite is not of
751751 interest for end users.</p></div>
752752 </div>
753753 </div>
14681468 <div id="footer">
14691469 <div id="footer-text">
14701470 Last updated
1471 2021-11-03 09:23:08 CET
1471 2022-09-21 18:26:43 CEST
14721472 </div>
14731473 </div>
14741474 </body>
195195
196196 Floating windows are always on top of tiling windows.
197197
198 === Moving tiling containers with the mouse
199
200 Since i3 4.21, it's possible to drag tiling containers using the mouse. The
201 drag can be initiated either by dragging the window's titlebar or by pressing
202 the <<floating_modifier>> and dragging the container while holding the
203 left-click button.
204
205 Once the drag is initiated and the cursor has left the original container, drop
206 indicators are created according to the position of the cursor relatively to
207 the target container. These indicators help you understand what the resulting
208 <<tree>> layout is going to be after you release the mouse button.
209
210 The possible drop positions are:
211
212 Drop on container::
213 This happens when the mouse is relatively near the center of a container.
214 If the mouse is released, the result is exactly as if you had run the
215 +move container to mark+ command. See <<move_to_mark>>.
216 Drop as sibling::
217 This happens when the mouse is relatively near the edge of a container. If
218 the mouse is released, the dragged container will become a sibling of the
219 target container, placed left/right/up/down according to the position of
220 the indicator.
221 This might or might not create a new v-split or h-split according to the
222 previous layout of the target container. For example, if the target
223 container is in an h-split and you drop the dragged container below it, the
224 new layout will have to be a v-split.
225 Drop to parent::
226 This happens when the mouse is relatively near the edge of a container (but
227 even closer to the border in comparison to the sibling case above) *and* if
228 that edge is also the parent container's edge. For example, if three
229 containers are in a horizontal layout then edges where this can happen is
230 the left edge of the left container, the right edge of the right container
231 and all bottom and top edges of all three containers.
232 If the mouse is released, the container is first dropped as a sibling to
233 the target container, like in the case above, and then is moved
234 directionally like with the +move left|right|down|up+ command. See
235 <<move_direction>>.
236
237 The color of the indicator matches the +client.focused+ setting. See <<client_colors>>.
238
239 [[tree]]
198240 == Tree
199241
200242 i3 stores all information about the X11 outputs, workspaces and layout of the
537579 # The middle button over a titlebar kills the window
538580 bindsym --release button2 kill
539581
540 # The middle button and a modifer over any part of the window kills the window
582 # The middle button and a modifier over any part of the window kills the window
541583 bindsym --whole-window $mod+button2 kill
542584
543585 # The right button toggles floating
10401082 workspace "2: vim" output VGA1
10411083 ---------------------------
10421084
1085 [[client_colors]]
10431086 === Changing colors
10441087
10451088 You can change all colors which i3 uses to draw the window decorations.
10561099 client.focused_inactive::
10571100 A client which is the focused one of its container, but it does not have
10581101 the focus at the moment.
1102 client.focused_tab_title::
1103 Tab or stack container title that is the parent of the focused container
1104 but not directly focused. Defaults to focused_inactive if not specified and
1105 does not use the indicator and child_border colors.
10591106 client.unfocused::
10601107 A client which is not the focused one of its container.
10611108 client.urgent::
10991146 programs to get information from i3, such as the current workspaces
11001147 (to display a workspace bar), and to control i3.
11011148
1102 The IPC socket is enabled by default and will be created in
1149 By default, an IPC socket will be created in
11031150 +$XDG_RUNTIME_DIR/i3/ipc-socket.%p+ if the directory is available, falling back
11041151 to +/tmp/i3-%u.XXXXXX/ipc-socket.%p+, where +%u+ is your UNIX username, +%p+ is
11051152 the PID of i3 and XXXXXX is a string of random characters from the portable
22072254 focus left|right|down|up
22082255 focus parent|child|floating|tiling|mode_toggle
22092256 focus next|prev [sibling]
2210 focus output left|right|up|down|primary|<output>
2257 focus output left|right|down|up|current|primary|next|<output1> [output2]…
22112258 ----------------------------------------------
22122259
22132260 *Examples*:
22272274 # Focus last floating/tiling container
22282275 bindsym $mod+g focus mode_toggle
22292276
2277 # Focus the next output (effectively toggles when you only have two outputs)
2278 bindsym $mod+x move workspace to output next
2279
22302280 # Focus the output right to the current one
22312281 bindsym $mod+x focus output right
22322282
22352285
22362286 # Focus the primary output
22372287 bindsym $mod+x focus output primary
2288
2289 # Cycle focus between outputs VGA1 and LVDS1 but not DVI0
2290 bindsym $mod+x move workspace to output VGA1 LVDS1
22382291 -------------------------------------------------
22392292
22402293 Note that you might not have a primary output configured yet. To do so, run:
22422295 xrandr --output <output> --primary
22432296 -------------------------
22442297
2298 [[move_direction]]
22452299 === Moving containers
22462300
22472301 Use the +move+ command to move a container.
24762530 If a workspace does not exist, the command +workspace number "1: mail"+ will
24772531 create workspace "1: mail".
24782532
2479 If a workspace with number 1 does already exist, the command will switch to this
2533 If a workspace with number 1 already exists, the command will switch to this
24802534 workspace and ignore the text part. So even when the workspace has been renamed
2481 to "1: web", the above command will still switch to it.
2535 "1: web", the above command will still switch to it. The command +workspace 1+
2536 will however create and move to a new workspace "1" alongside the existing
2537 "1: mail" workspace.
24822538
24832539 === Moving workspaces to a different screen
24842540
25242580 xrandr --output <output> --primary
25252581 -------------------------
25262582
2583 [[move_to_mark]]
25272584 === Moving containers/windows to marks
25282585
25292586 To move a container to another container with a specific mark (see <<vim_like_marks>>),
27172774
27182775 *Syntax*:
27192776 -----------------------------
2720 title_window_icon <yes|no>
2721 title_window_icon padding <px>
2777 title_window_icon <yes|no|toggle>
2778 title_window_icon <padding|toggle> <px>
27222779 ------------------------------
27232780
27242781 *Examples*:
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>i3 User’s Guide</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
969969 provided by the i3 <a href="https://github.com/i3/i3/blob/next/etc/config.keycodes">default config</a>.</p></div>
970970 <div class="paragraph"><p>Floating windows are always on top of tiling windows.</p></div>
971971 </div>
972 <div class="sect2">
973 <h3 id="_moving_tiling_containers_with_the_mouse">2.12. Moving tiling containers with the mouse</h3>
974 <div class="paragraph"><p>Since i3 4.21, it&#8217;s possible to drag tiling containers using the mouse. The
975 drag can be initiated either by dragging the window&#8217;s titlebar or by pressing
976 the <a href="#floating_modifier">[floating_modifier]</a> and dragging the container while holding the
977 left-click button.</p></div>
978 <div class="paragraph"><p>Once the drag is initiated and the cursor has left the original container, drop
979 indicators are created according to the position of the cursor relatively to
980 the target container. These indicators help you understand what the resulting
981 <a href="#tree">[tree]</a> layout is going to be after you release the mouse button.</p></div>
982 <div class="paragraph"><p>The possible drop positions are:</p></div>
983 <div class="dlist"><dl>
984 <dt class="hdlist1">
985 Drop on container
986 </dt>
987 <dd>
988 <p>
989 This happens when the mouse is relatively near the center of a container.
990 If the mouse is released, the result is exactly as if you had run the
991 <code>move container to mark</code> command. See <a href="#move_to_mark">[move_to_mark]</a>.
992 </p>
993 </dd>
994 <dt class="hdlist1">
995 Drop as sibling
996 </dt>
997 <dd>
998 <p>
999 This happens when the mouse is relatively near the edge of a container. If
1000 the mouse is released, the dragged container will become a sibling of the
1001 target container, placed left/right/up/down according to the position of
1002 the indicator.
1003 This might or might not create a new v-split or h-split according to the
1004 previous layout of the target container. For example, if the target
1005 container is in an h-split and you drop the dragged container below it, the
1006 new layout will have to be a v-split.
1007 </p>
1008 </dd>
1009 <dt class="hdlist1">
1010 Drop to parent
1011 </dt>
1012 <dd>
1013 <p>
1014 This happens when the mouse is relatively near the edge of a container (but
1015 even closer to the border in comparison to the sibling case above) <strong>and</strong> if
1016 that edge is also the parent container&#8217;s edge. For example, if three
1017 containers are in a horizontal layout then edges where this can happen is
1018 the left edge of the left container, the right edge of the right container
1019 and all bottom and top edges of all three containers.
1020 If the mouse is released, the container is first dropped as a sibling to
1021 the target container, like in the case above, and then is moved
1022 directionally like with the <code>move left|right|down|up</code> command. See
1023 <a href="#move_direction">[move_direction]</a>.
1024 </p>
1025 </dd>
1026 </dl></div>
1027 <div class="paragraph"><p>The color of the indicator matches the <code>client.focused</code> setting. See <a href="#client_colors">[client_colors]</a>.</p></div>
1028 </div>
9721029 </div>
9731030 </div>
9741031 <div class="sect1">
975 <h2 id="_tree">3. Tree</h2>
1032 <h2 id="tree">3. Tree</h2>
9761033 <div class="sectionbody">
9771034 <div class="paragraph"><p>i3 stores all information about the X11 outputs, workspaces and layout of the
9781035 windows on them in a tree. The root node is the X11 root window, followed by
13481405 <pre><code># The middle button over a titlebar kills the window
13491406 bindsym --release button2 kill
13501407
1351 # The middle button and a modifer over any part of the window kills the window
1408 # The middle button and a modifier over any part of the window kills the window
13521409 bindsym --whole-window $mod+button2 kill
13531410
13541411 # The right button toggles floating
18111868 </div></div>
18121869 </div>
18131870 <div class="sect2">
1814 <h3 id="_changing_colors">4.21. Changing colors</h3>
1871 <h3 id="client_colors">4.21. Changing colors</h3>
18151872 <div class="paragraph"><p>You can change all colors which i3 uses to draw the window decorations.</p></div>
18161873 <div class="paragraph"><p><strong>Syntax</strong>:</p></div>
18171874 <div class="listingblock">
18351892 <p>
18361893 A client which is the focused one of its container, but it does not have
18371894 the focus at the moment.
1895 </p>
1896 </dd>
1897 <dt class="hdlist1">
1898 client.focused_tab_title
1899 </dt>
1900 <dd>
1901 <p>
1902 Tab or stack container title that is the parent of the focused container
1903 but not directly focused. Defaults to focused_inactive if not specified and
1904 does not use the indicator and child_border colors.
18381905 </p>
18391906 </dd>
18401907 <dt class="hdlist1">
19011968 <div class="paragraph"><p>i3 uses Unix sockets to provide an IPC interface. This allows third-party
19021969 programs to get information from i3, such as the current workspaces
19031970 (to display a workspace bar), and to control i3.</p></div>
1904 <div class="paragraph"><p>The IPC socket is enabled by default and will be created in
1971 <div class="paragraph"><p>By default, an IPC socket will be created in
19051972 <code>$XDG_RUNTIME_DIR/i3/ipc-socket.%p</code> if the directory is available, falling back
19061973 to <code>/tmp/i3-%u.XXXXXX/ipc-socket.%p</code>, where <code>%u</code> is your UNIX username, <code>%p</code> is
19071974 the PID of i3 and XXXXXX is a string of random characters from the portable
32653332 focus left|right|down|up
32663333 focus parent|child|floating|tiling|mode_toggle
32673334 focus next|prev [sibling]
3268 focus output left|right|up|down|primary|&lt;output&gt;</code></pre>
3335 focus output left|right|down|up|current|primary|next|&lt;output1&gt; [output2]…</code></pre>
32693336 </div></div>
32703337 <div class="paragraph"><p><strong>Examples</strong>:</p></div>
32713338 <div class="listingblock">
32853352 # Focus last floating/tiling container
32863353 bindsym $mod+g focus mode_toggle
32873354
3355 # Focus the next output (effectively toggles when you only have two outputs)
3356 bindsym $mod+x move workspace to output next
3357
32883358 # Focus the output right to the current one
32893359 bindsym $mod+x focus output right
32903360
32923362 bindsym $mod+x focus output HDMI-2
32933363
32943364 # Focus the primary output
3295 bindsym $mod+x focus output primary</code></pre>
3365 bindsym $mod+x focus output primary
3366
3367 # Cycle focus between outputs VGA1 and LVDS1 but not DVI0
3368 bindsym $mod+x move workspace to output VGA1 LVDS1</code></pre>
32963369 </div></div>
32973370 <div class="paragraph"><p>Note that you might not have a primary output configured yet. To do so, run:</p></div>
32983371 <div class="listingblock">
33013374 </div></div>
33023375 </div>
33033376 <div class="sect2">
3304 <h3 id="_moving_containers">6.5. Moving containers</h3>
3377 <h3 id="move_direction">6.5. Moving containers</h3>
33053378 <div class="paragraph"><p>Use the <code>move</code> command to move a container.</p></div>
33063379 <div class="paragraph"><p><strong>Syntax</strong>:</p></div>
33073380 <div class="listingblock">
35403613 </div></div>
35413614 <div class="paragraph"><p>If a workspace does not exist, the command <code>workspace number "1: mail"</code> will
35423615 create workspace "1: mail".</p></div>
3543 <div class="paragraph"><p>If a workspace with number 1 does already exist, the command will switch to this
3616 <div class="paragraph"><p>If a workspace with number 1 already exists, the command will switch to this
35443617 workspace and ignore the text part. So even when the workspace has been renamed
3545 to "1: web", the above command will still switch to it.</p></div>
3618 "1: web", the above command will still switch to it. The command <code>workspace 1</code>
3619 will however create and move to a new workspace "1" alongside the existing
3620 "1: mail" workspace.</p></div>
35463621 </div>
35473622 </div>
35483623 <div class="sect2">
35883663 </div></div>
35893664 </div>
35903665 <div class="sect2">
3591 <h3 id="_moving_containers_windows_to_marks">6.11. Moving containers/windows to marks</h3>
3666 <h3 id="move_to_mark">6.11. Moving containers/windows to marks</h3>
35923667 <div class="paragraph"><p>To move a container to another container with a specific mark (see <a href="#vim_like_marks">[vim_like_marks]</a>),
35933668 you can use the following command.</p></div>
35943669 <div class="paragraph"><p>The window will be moved right after the marked container in the tree, i.e., it ends up
37893864 <div class="paragraph"><p><strong>Syntax</strong>:</p></div>
37903865 <div class="listingblock">
37913866 <div class="content">
3792 <pre><code>title_window_icon &lt;yes|no&gt;
3793 title_window_icon padding &lt;px&gt;</code></pre>
3867 <pre><code>title_window_icon &lt;yes|no|toggle&gt;
3868 title_window_icon &lt;padding|toggle&gt; &lt;px&gt;</code></pre>
37943869 </div></div>
37953870 <div class="paragraph"><p><strong>Examples</strong>:</p></div>
37963871 <div class="listingblock">
41954270 <div id="footer">
41964271 <div id="footer-text">
41974272 Last updated
4198 2021-11-03 09:23:08 CET
4273 2022-09-21 18:26:43 CEST
41994274 </div>
42004275 </div>
42014276 </body>
33 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44 <head>
55 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 9.1.0" />
6 <meta name="generator" content="AsciiDoc 10.2.0" />
77 <title>External workspace bars</title>
88 <style type="text/css">
99 /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
843843 <div id="footer">
844844 <div id="footer-text">
845845 Last updated
846 2021-11-03 09:23:08 CET
846 2022-09-21 18:26:43 CEST
847847 </div>
848848 </div>
849849 </body>
227227 ($call_identifier) = ($next_state =~ /^call ([0-9]+)$/);
228228 $next_state = '__CALL';
229229 }
230 my $identifier = $token->{identifier};
231 say $tokfh qq| { "$token_name", "$identifier", $next_state, { $call_identifier } },|;
230 my $identifier;
231 # Set $identifier to NULL if there is no identifier
232 if ($token->{identifier} eq ""){
233 $identifier = "NULL"
234 }
235 else{
236 $identifier = qq|"$token->{identifier}"|;
237 }
238 say $tokfh qq| { "$token_name", $identifier, $next_state, { $call_identifier } },|;
232239 }
233240 say $tokfh '};';
234241 }
330330 * separate configuration directives. */
331331 while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
332332 walk++;
333
334 //printf("remaining input: %s\n", walk);
335333
336334 cmdp_token_ptr *ptr = &(tokens[state]);
337335 for (c = 0; c < ptr->n; c++) {
425423 }
426424
427425 if (strcmp(token->name, "end") == 0) {
428 //printf("checking for end: *%s*\n", walk);
429426 if (*walk == '\0' || *walk == '\n' || *walk == '\r') {
430427 if ((result = next_state(token)) != NULL)
431428 return result;
432 /* To make sure we start with an appropriate matching
433 * datastructure for commands which do *not* specify any
429 /* To make sure we start with an appropriate matching data
430 * structure for commands which do *not* specify any
434431 * criteria, we re-initialize the criteria system after
435432 * every command. */
436 // TODO: make this testable
437433 walk++;
438434 break;
439435 }
481481 # double quote which is NOT preceded by a backslash (\).
482482 #
483483 # Therefore, we escape all double quotes (") by replacing them with \"
484 $exec =~ s/"/\\"/g;
484 $exec =~ s/\\"/\\\\\\"/g;
485 $exec =~ s/([^\\])"/$1\\"/g;
485486
486487 if (exists($app->{StartupNotify}) && !$app->{StartupNotify}) {
487488 $nosn = '--no-startup-id';
00 # This list can be used to convert X11 Keysyms to Unicode 2.1 character.
11 # The list is not checked for correctness by Unicode officials. Use it
2 # at your own risk and the creator is not responsable for any damage that
2 # at your own risk and the creator is not responsible for any damage that
33 # occurred due to using this list.
44 #
55 # The list is created by looking at the Keysym names and the Unicode data
77 # Distributions/packagers can enhance this script with a
88 # distribution-specific mechanism to find the preferred pager.
99
10 # The less -E and -F options exit immediately for short files, strip if present.
11 case "$LESS" in
12 *[EF]*) LESS=`echo "$LESS" | tr -d EF`
13 esac
14
1015 # Hopefully one of these is installed (no flamewars about preference please!):
1116 # We don't use 'more' because it will exit if the file is too short.
1217 # Worst case scenario we'll open the file in your editor.
1313 # 2. Distribution-specific mechanisms come next, e.g. x-terminal-emulator
1414 # 3. The terminal emulator with best accessibility comes first.
1515 # 4. No order is guaranteed/desired for the remaining terminal emulators.
16 for terminal in "$TERMINAL" x-terminal-emulator mate-terminal gnome-terminal terminator xfce4-terminal urxvt rxvt termit Eterm aterm uxterm xterm roxterm termite lxterminal terminology st qterminal lilyterm tilix terminix konsole kitty guake tilda alacritty hyper; do
16 for terminal in "$TERMINAL" x-terminal-emulator mate-terminal gnome-terminal terminator xfce4-terminal urxvt rxvt termit Eterm aterm uxterm xterm roxterm termite lxterminal terminology st qterminal lilyterm tilix terminix konsole kitty guake tilda alacritty hyper wezterm; do
1717 if command -v "$terminal" > /dev/null 2>&1; then
1818 exec "$terminal" "$@"
1919 fi
6565 uint32_t border_left;
6666 bool pango_markup;
6767
68 /* The amount of pixels necessary to render a separater after the block. */
68 /* The amount of pixels necessary to render a separator after the block. */
6969 uint32_t sep_block_width;
7070
7171 /* Continuously-updated information on how to render this status block. */
1212 #include <stdlib.h>
1313 #include <string.h>
1414
15 #include <X11/Xlib.h>
1615 #include <yajl/yajl_parse.h>
1716
1817 config_t config;
125124 }
126125
127126 if (len == strlen("shift") && !strncmp((const char *)val, "shift", strlen("shift"))) {
128 config.modifier = ShiftMask;
127 config.modifier = XCB_MOD_MASK_SHIFT;
129128 return 1;
130129 }
131130 if (len == strlen("ctrl") && !strncmp((const char *)val, "ctrl", strlen("ctrl"))) {
132 config.modifier = ControlMask;
131 config.modifier = XCB_MOD_MASK_CONTROL;
133132 return 1;
134133 }
135134 if (len == strlen("Mod") + 1 && !strncmp((const char *)val, "Mod", strlen("Mod"))) {
136135 switch (val[3]) {
137136 case '1':
138 config.modifier = Mod1Mask;
137 config.modifier = XCB_MOD_MASK_1;
139138 return 1;
140139 case '2':
141 config.modifier = Mod2Mask;
140 config.modifier = XCB_MOD_MASK_2;
142141 return 1;
143142 case '3':
144 config.modifier = Mod3Mask;
143 config.modifier = XCB_MOD_MASK_3;
145144 return 1;
146145 case '5':
147 config.modifier = Mod5Mask;
146 config.modifier = XCB_MOD_MASK_5;
148147 return 1;
149148 }
150149 }
151150
152 config.modifier = Mod4Mask;
151 config.modifier = XCB_MOD_MASK_4;
153152 return 1;
154153 }
155154
202202 if (block->border)
203203 render->width += logical_px(block->border_left + block->border_right);
204204
205 /* Compute offset and append for text aligment in min_width. */
205 /* Compute offset and append for text alignment in min_width. */
206206 if (block->min_width <= render->width) {
207207 render->x_offset = 0;
208208 render->x_append = 0;
5757 #include "match.h"
5858 #include "xcursor.h"
5959 #include "resize.h"
60 #include "tiling_drag.h"
6061 #include "sighandler.h"
6162 #include "move.h"
6263 #include "output.h"
332332 void cmd_debuglog(I3_CMD, const char *argument);
333333
334334 /**
335 * Implementation of 'title_window_icon <yes|no>' and 'title_window_icon padding <px>'
335 * Implementation of 'title_window_icon <yes|no|toggle>' and 'title_window_icon <padding|toggle> <px>'
336336 *
337337 */
338338 void cmd_title_window_icon(I3_CMD, const char *enable, int padding);
1313 #include <yajl/yajl_gen.h>
1414
1515 /**
16 * Holds an intermediate represenation of the result of a call to any command.
16 * Holds an intermediate representation of the result of a call to any command.
1717 * When calling parse_command("floating enable, border none"), the parser will
1818 * internally use this struct when calling cmd_floating and cmd_border.
1919 */
206206 *
207207 */
208208 Con *con_by_mark(const char *mark);
209
210 /**
211 * Start from a container and traverse the transient_for linked list. Returns
212 * true if target window is found in the list. Protects againsts potential
213 * cycles.
214 *
215 */
216 bool con_find_transient_for_window(Con *start, xcb_window_t target);
209217
210218 /**
211219 * Returns true if and only if the given containers holds the mark.
362370 */
363371 bool con_move_to_output_name(Con *con, const char *name, bool fix_coordinates);
364372
373 bool con_move_to_target(Con *con, Con *target);
365374 /**
366375 * Moves the given container to the given mark.
367376 *
4040 Match current_match;
4141
4242 /* A list which contains the states that lead to the current state, e.g.
43 * INITIAL, WORKSPACE_LAYOUT.
44 * When jumping back to INITIAL, statelist_idx will simply be set to 1
45 * (likewise for other states, e.g. MODE or BAR).
46 * This list is used to process the nearest error token. */
43 * INITIAL, WORKSPACE_LAYOUT.
44 * When jumping back to INITIAL, statelist_idx will simply be set to 1
45 * (likewise for other states, e.g. MODE or BAR).
46 * This list is used to process the nearest error token. */
4747 int statelist[10];
4848 /* NB: statelist_idx points to where the next entry will be inserted */
4949 int statelist_idx;
5050
5151 /*******************************************************************************
52 * The (small) stack where identified literals are stored during the parsing
53 * of a single config directive (like $workspace).
54 ******************************************************************************/
52 * The (small) stack where identified literals are stored during the parsing
53 * of a single config directive (like $workspace).
54 ******************************************************************************/
5555 struct stack *stack;
5656
5757 struct variables_head variables;
6060 };
6161
6262 /**
63 * An intermediate reprsentation of the result of a parse_config call.
63 * An intermediate representation of the result of a parse_config call.
6464 * Currently unused, but the JSON output will be useful in the future when we
6565 * implement a config parsing IPC command.
6666 *
237237 color_t background;
238238 struct Colortriple focused;
239239 struct Colortriple focused_inactive;
240 struct Colortriple focused_tab_title;
240241 struct Colortriple unfocused;
241242 struct Colortriple urgent;
242243 struct Colortriple placeholder;
244 bool got_focused_tab_title;
243245 } client;
244246 struct config_bar {
245247 struct Colortriple focused;
88 */
99 #pragma once
1010
11 #define PCRE2_CODE_UNIT_WIDTH 8
12
1113 #define SN_API_NOT_YET_FROZEN 1
1214 #include <libsn/sn-launcher.h>
1315
1416 #include <xcb/randr.h>
15 #include <pcre.h>
17 #include <pcre2.h>
1618 #include <sys/time.h>
1719 #include <cairo/cairo.h>
1820
247249 */
248250 struct regex {
249251 char *pattern;
250 pcre *regex;
251 pcre_extra *extra;
252 pcre2_code *regex;
252253 };
253254
254255 /**
661662 char *title_format;
662663
663664 /** Whether the window icon should be displayed, and with what padding. -1
664 * means display no window icon (default behavior), 0 means display without
665 * any padding, 1 means display with 1 pixel of padding and so on. */
665 * means display no window icon (default behavior), 0 means display without
666 * any padding, 1 means display with 1 pixel of padding and so on. */
666667 int window_icon_padding;
667668
668669 /* a sticky-group is an identifier which bundles several containers to a
1313 /**
1414 * Connects to i3 to find out the currently running version. Useful since it
1515 * might be different from the version compiled into this binary (maybe the
16 * user didn’t correctly install i3 or forgot te restart it).
16 * user didn’t correctly install i3 or forgot to restart it).
1717 *
1818 * The output looks like this:
1919 * Running i3 version: 4.2-202-gb8e782c (2012-08-12, branch "next") (pid 14804)
5555 extern SnDisplay *sndisplay;
5656 extern xcb_key_symbols_t *keysyms;
5757 extern char **start_argv;
58 extern Display *xlibdpy, *xkbdpy;
5958 extern int xkb_current_group;
6059 extern TAILQ_HEAD(bindings_head, Binding) *bindings;
6160 extern const char *current_binding_mode;
294294 int ipc_connect(const char *socket_path);
295295
296296 /**
297 * Connects to the socket at the given path with no fallback paths. Returns
298 * -1 if connect() fails and die()s for other errors.
299 */
300 int ipc_connect_impl(const char *socket_path);
301
302 /**
297303 * Formats a message (payload) of the given size and type and sends it to i3 via
298304 * the given socket file descriptor.
299305 *
4848 *
4949 */
5050 void init_ws_for_output(Output *output);
51
52 /**
53 * Initializes the specified output, assigning the specified workspace to it.
54 *
55 */
56 //void initialize_output(xcb_connection_t *conn, Output *output, Workspace *workspace);
5751
5852 /**
5953 * (Re-)queries the outputs via RandR and stores them in the list of outputs.
0 /*
1 * vim:ts=4:sw=4:expandtab
2 *
3 * i3 - an improved dynamic tiling window manager
4 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
5 *
6 * tiling_drag.h: Reposition tiled windows by dragging.
7 *
8 */
9 #pragma once
10
11 /**
12 * Initiates a mouse drag operation on a tiled window.
13 *
14 */
15 void tiling_drag(Con *con, xcb_button_press_event_t *event);
182182 *
183183 */
184184 direction_t direction_from_orientation_position(orientation_t orientation, position_t position);
185
186 /**
187 * Converts direction to a string representation.
188 *
189 */
190 const char *direction_to_string(direction_t direction);
191
192 /**
193 * Converts position to a string representation.
194 *
195 */
196 const char *position_to_string(position_t position);
9393 * it is still in use by popular widget toolkits such as GTK+ and Java AWT.
9494 *
9595 */
96 void window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style);
96 bool window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style);
9797
9898 /**
9999 * Updates the WM_CLIENT_MACHINE
9191
9292 /**
9393 * Returns true if the workspace is currently visible. Especially important for
94 * multi-monitor environments, as they can have multiple currenlty active
94 * multi-monitor environments, as they can have multiple currently active
9595 * workspaces.
9696 *
9797 */
99 #include <unistd.h>
1010 #include <libgen.h>
1111 #include <err.h>
12 #include <errno.h>
1213 #include <fcntl.h>
1314 #include <stdlib.h>
1415 #include <string.h>
3334 }
3435 free(copy);
3536
37 /* Check if the socket is in use by another process (this call does not
38 * succeed if the socket is stale / the owner already exited) */
39 int sockfd = ipc_connect_impl(resolved);
40 if (sockfd != -1) {
41 ELOG("Refusing to create UNIX socket at %s: Socket is already in use\n", resolved);
42 close(sockfd);
43 errno = EEXIST;
44 return -1;
45 }
46
3647 /* Unlink the unix domain socket before */
3748 unlink(resolved);
3849
39 int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
50 sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
4051 if (sockfd < 0) {
4152 perror("socket()");
4253 free(resolved);
159159 font.type = FONT_TYPE_NONE;
160160 font.pattern = NULL;
161161
162 /* No XCB connction, return early because we're just validating the
162 /* No XCB connection, return early because we're just validating the
163163 * configuration file. */
164164 if (conn == NULL) {
165165 return font;
1212 #include <string.h>
1313 #include <sys/socket.h>
1414 #include <sys/un.h>
15 #include <unistd.h>
1516
1617 /*
1718 * Connects to the i3 IPC socket and returns the file descriptor for the
3839 path = sstrdup("/tmp/i3-ipc.sock");
3940 }
4041
42 int sockfd = ipc_connect_impl(path);
43 if (sockfd < 0) {
44 err(EXIT_FAILURE, "Could not connect to i3 on socket %s", path);
45 }
46 free(path);
47 return sockfd;
48 }
49
50 /**
51 * Connects to the socket at the given path with no fallback paths. Returns
52 * -1 if connect() fails and die()s for other errors.
53 *
54 */
55 int ipc_connect_impl(const char *socket_path) {
4156 int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
4257 if (sockfd == -1)
4358 err(EXIT_FAILURE, "Could not create socket");
4762 struct sockaddr_un addr;
4863 memset(&addr, 0, sizeof(struct sockaddr_un));
4964 addr.sun_family = AF_LOCAL;
50 strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
51 if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
52 err(EXIT_FAILURE, "Could not connect to i3 on socket %s", path);
53 free(path);
65 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
66 if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
67 close(sockfd);
68 return -1;
69 }
5470 return sockfd;
5571 }
11 .\" Title: i3-config-wizard
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-CONFIG\-WIZARD" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-CONFIG\-WIZARD" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
0 .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42)
0 .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43)
11 .\"
22 .\" Standard preamble:
33 .\" ========================================================================
7070 .\" ========================================================================
7171 .\"
7272 .IX Title "I3-DMENU-DESKTOP 1"
73 .TH I3-DMENU-DESKTOP 1 "2021-11-03" "perl v5.34.0" "User Contributed Perl Documentation"
73 .TH I3-DMENU-DESKTOP 1 "2022-09-21" "perl v5.36.0" "User Contributed Perl Documentation"
7474 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
7575 .\" way too many mistakes in technical documents.
7676 .if n .ad l
11 .\" Title: i3-dump-log
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-DUMP\-LOG" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-DUMP\-LOG" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3-input
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-INPUT" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-INPUT" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
6262 .RS 4
6363 Use the specified X11 core font (use
6464 xfontsel
65 to chose a font)\&.
65 to choose a font)\&.
6666 .RE
6767 .PP
6868 \-v
3838 The prompt string is not included in the user input/command.
3939
4040 -f <font>::
41 Use the specified X11 core font (use +xfontsel+ to chose a font).
41 Use the specified X11 core font (use +xfontsel+ to choose a font).
4242
4343 -v::
4444 Show version and exit.
11 .\" Title: i3-migrate-config-to-v4
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-MIGRATE\-CONFIG\-TO\-V4" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-MIGRATE\-CONFIG\-TO\-V4" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3-msg
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-MSG" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-MSG" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3-nagbar
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-NAGBAR" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-NAGBAR" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
0 .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42)
0 .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43)
11 .\"
22 .\" Standard preamble:
33 .\" ========================================================================
7070 .\" ========================================================================
7171 .\"
7272 .IX Title "I3-SAVE-TREE 1"
73 .TH I3-SAVE-TREE 1 "2021-11-03" "perl v5.34.0" "User Contributed Perl Documentation"
73 .TH I3-SAVE-TREE 1 "2022-09-21" "perl v5.36.0" "User Contributed Perl Documentation"
7474 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
7575 .\" way too many mistakes in technical documents.
7676 .if n .ad l
11 .\" Title: i3-sensible-editor
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-SENSIBLE\-EDITOR" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-SENSIBLE\-EDITOR" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3-sensible-pager
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-SENSIBLE\-PAGER" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-SENSIBLE\-PAGER" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3-sensible-terminal
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3\-SENSIBLE\-TERMINAL" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3\-SENSIBLE\-TERMINAL" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3
22 .\" Author: [see the "AUTHOR" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
11 .\" Title: i3bar
22 .\" Author: [see the "AUTHORS" section]
33 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
4 .\" Date: 11/03/2021
4 .\" Date: 09/21/2022
55 .\" Manual: i3 Manual
6 .\" Source: i3 4.20.1
6 .\" Source: i3 4.21
77 .\" Language: English
88 .\"
9 .TH "I3BAR" "1" "11/03/2021" "i3 4\&.20\&.1" "i3 Manual"
9 .TH "I3BAR" "1" "09/21/2022" "i3 4\&.21" "i3 Manual"
1010 .\" -----------------------------------------------------------------
1111 .\" * Define some portability stuff
1212 .\" -----------------------------------------------------------------
55 project(
66 'i3',
77 'c',
8 version: '4.20.1',
8 version: '4.21',
99 default_options: [
1010 'c_std=c11',
1111 'warning_level=1', # enable all warnings (-Wall)
6262 sources: vcs_tag(
6363 input: config_h_in,
6464 output: 'config.h',
65 fallback: meson.project_version() + ' (2021-11-03)',
65 fallback: meson.project_version() + ' (2022-09-21)',
6666 )
6767 )
6868
315315 xkbcommon_dep = dependency('xkbcommon', method: 'pkg-config')
316316 xkbcommon_x11_dep = dependency('xkbcommon-x11', method: 'pkg-config')
317317 yajl_dep = dependency('yajl', method: 'pkg-config')
318 libpcre_dep = dependency('libpcre', version: '>=8.10', method: 'pkg-config')
318 libpcre_dep = dependency('libpcre2-8', version: '>=10', method: 'pkg-config')
319319 cairo_dep = dependency('cairo', version: '>=1.14.4', method: 'pkg-config')
320320 pangocairo_dep = dependency('pangocairo', method: 'pkg-config')
321321 glib_dep = dependency('glib-2.0', method: 'pkg-config')
408408 'src/sighandler.c',
409409 'src/startup.c',
410410 'src/sync.c',
411 'src/tiling_drag.c',
411412 'src/tree.c',
412413 'src/util.c',
413414 'src/version.c',
165165 -> call cmd_focus_direction($direction)
166166
167167 state FOCUS_OUTPUT:
168 output = string
169 -> call cmd_focus_output($output)
168 output = word
169 -> call cmd_focus_output($output); FOCUS_OUTPUT
170 end
171 -> call cmd_focus_output(NULL); INITIAL
170172
171173 # kill [window|client]
172174 state KILL:
465467 state TITLE_WINDOW_ICON:
466468 'padding'
467469 -> TITLE_WINDOW_ICON_PADDING
470 enable = 'toggle'
471 -> TITLE_WINDOW_ICON_PADDING
468472 enable = '1', 'yes', 'true', 'on', 'enable', 'active', '0', 'no', 'false', 'off', 'disable', 'inactive'
469473 -> call cmd_title_window_icon($enable, 0)
470474
5555 exectype = 'exec_always', 'exec' -> EXEC
5656 colorclass = 'client.background'
5757 -> COLOR_SINGLE
58 colorclass = 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
58 colorclass = 'client.focused_inactive', 'client.focused_tab_title', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
5959 -> COLOR_BORDER
6060
6161 # We ignore comments and 'set' lines (variables).
398398 exclude_titlebar = '--exclude-titlebar'
399399 ->
400400 command = string
401 -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $exclude_titlebar, $command)
402 end
403401 -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $exclude_titlebar, $command)
404402
405403 ################################################################################
566564 -> call cfg_bar_position($position); BAR
567565
568566 state BAR_OUTPUT:
569 output = string
567 output = word
570568 -> call cfg_bar_output($output); BAR
571569
572570 state BAR_TRAY_OUTPUT:
0 fix crash with "layout default"
0 Do not replace existing IPC socket on start
0 fix focus when moving container between outputs with mouse warp and focus_follows_mouse
0 Fix endless loop with transient_for windows
0 fix wrong failed reply on move workspace to output
0 changed WM registration selection from WM_S_S<screen> to WM_S<screen>
0 avoid graphics artifacts when changing the layout tree by initializing surfaces to all black
0 Fix segfault if command in bindsym is empty
0 update parent split con titles when child con swaps position with another child con
0 fix default font not being applied to bars if defined after bar block
0 strip trailing whitespace in bar output names
0 Fix crash if config contains nested variables.
0 Fix segfault with explicit mode "default" key bindings.
0 Restore BS_NORMAL _MOTIF_WM_HINTS correctly
0 Acquire the WM_Sn selection when starting as required by ICCCM
0 Refuse to start without valid IPC socket
0 Add client.focused_tab_title color option
0 Add support for multiple outputs in focus command
0 Allow moving tiling windows with the mouse
0 #!/usr/bin/env perl
1 use strict;
2 use warnings;
3 use v5.10;
4 use Getopt::Long;
5
6 my @template = (
7 '
8 ┌──────────────────────────────┐
9 │ Release notes for i3 v4.21 │
10 └──────────────────────────────┘
11
12 This is i3 v4.21. This version is considered stable. All users of i3 are
13 strongly encouraged to upgrade.
14
15
16 ┌────────────────────────────┐
17 │ Changes in i3 v4.21 │
18 └────────────────────────────┘
19
20 ',
21 '
22 ┌────────────────────────────┐
23 │ Bugfixes │
24 └────────────────────────────┘
25
26 ');
27
28 my $print_urls = 0;
29 my $result = GetOptions('print-urls' => \$print_urls);
30
31 sub get_number {
32 my $s = shift;
33 return $1 if $s =~ m/^(\d+)/;
34 return -1;
35 }
36
37 sub read_changefiles {
38 my $dirpath = shift;
39 opendir my $dir, $dirpath or die "Cannot open directory $dirpath: $!";
40 my @files = sort { get_number($a) <=> get_number($b) } readdir $dir;
41
42 closedir $dir;
43
44 my $s = '';
45 for my $filename (@files) {
46 next if $filename eq '.';
47 next if $filename eq '..';
48 next if $filename eq '0-example';
49
50 die "Filename $filename should start with a number (e.g. the pull request number)" unless get_number($filename) > 0;
51
52 $filename = $dirpath . '/' . $filename;
53 open my $in, '<', $filename or die "can't open $filename: $!";
54 my @lines = <$in>;
55 close $in or die "can't close $filename: $!";
56
57 my $content = trim(join("\n ", map { trim($_) } @lines));
58 die "$filename can't be empty" unless length($content) > 0;
59
60 my $url = '';
61 if ($print_urls) {
62 my $commit = `git log --diff-filter=A --pretty=format:"%H" $filename`;
63 $commit = trim($commit) if defined($commit);
64 die "$filename: git log failed to find commit" if ($?) || (length($commit) == 0);
65
66 my $pr = find_pr($commit);
67 $url = 'https://github.com/i3/i3/commit/' . $commit;
68 $url = 'https://github.com/i3/i3/pull/' . $pr if defined($pr);
69 $url = $url . "\n";
70 }
71
72 $s = $s . ' • ' . $content . "\n" . $url;
73 }
74 return $s;
75 }
76
77 sub find_pr {
78 my $hash = shift;
79 my $result = `git log --merges --ancestry-path --oneline $hash..next | grep 'Merge pull request' | tail -n1`;
80 return unless defined($result);
81
82 return unless ($result =~ /Merge pull request .([0-9]+)/);
83 return $1;
84 }
85
86 sub trim {
87 (my $s = $_[0]) =~ s/^\s+|\s+$//g;
88 return $s;
89 }
90
91 # Expected to run for i3's git root
92 my $changes = read_changefiles('release-notes/changes');
93 my $bugfixes = read_changefiles('release-notes/bugfixes');
94
95 print $template[0] . $changes . $template[1] . $bugfixes;
7979 */
8080 static bool floating_mod_on_tiled_client(Con *con, xcb_button_press_event_t *event) {
8181 /* The client is in tiling layout. We can still initiate a resize with the
82 * right mouse button, by chosing the border which is the most near one to
82 * right mouse button, by choosing the border which is the most near one to
8383 * the position of the mouse pointer */
8484 int to_right = con->rect.width - event->event_x,
8585 to_left = event->event_x,
186186 if (!ws)
187187 goto done;
188188 }
189
190 if (ws != focused_workspace)
191 workspace_show(ws);
192189
193190 /* get the floating con */
194191 Con *floatingcon = con_inside_floating(con);
217214 goto done;
218215 }
219216
220 /* 2: focus this con or one of its children. */
217 /* 2: floating modifier pressed, initiate a drag */
218 if (mod_pressed && event->detail == XCB_BUTTON_INDEX_1 && !floatingcon) {
219 tiling_drag(con, event);
220 goto done;
221 }
222
223 /* 3: focus this con or one of its children. */
221224 Con *con_to_focus = con;
222225 if (in_stacked && dest == CLICK_DECORATION) {
223226 /* If the container is a tab/stacked container and the click happened
230233 }
231234 }
232235 }
236 if (ws != focused_workspace) {
237 workspace_show(ws);
238 }
233239 con_activate(con_to_focus);
234240
235 /* 3: For floating containers, we also want to raise them on click.
241 /* 4: For floating containers, we also want to raise them on click.
236242 * We will skip handling events on floating cons in fullscreen mode */
237243 Con *fs = con_get_fullscreen_covering_ws(ws);
238244 if (floatingcon != NULL && fs != con) {
239 /* 4: floating_modifier plus left mouse button drags */
245 /* 5: floating_modifier plus left mouse button drags */
240246 if (mod_pressed && is_left_click) {
241247 floating_drag_window(floatingcon, event, false);
242248 return;
243249 }
244250
245 /* 5: resize (floating) if this was a (left or right) click on the
251 /* 6: resize (floating) if this was a (left or right) click on the
246252 * left/right/bottom border, or a right click on the decoration.
247253 * also try resizing (tiling) if possible */
248254 if (mod_pressed && is_right_click) {
271277 return;
272278 }
273279
274 /* 6: dragging, if this was a click on a decoration (which did not lead
280 /* 7: dragging, if this was a click on a decoration (which did not lead
275281 * to a resize) */
276282 if (dest == CLICK_DECORATION && is_left_click) {
277283 floating_drag_window(floatingcon, event, !was_focused);
281287 goto done;
282288 }
283289
284 /* 7: floating modifier pressed, initiate a resize */
290 /* 8: floating modifier pressed, initiate a drag */
291 if ((mod_pressed || dest == CLICK_DECORATION) && event->detail == XCB_BUTTON_INDEX_1) {
292 tiling_drag(con, event);
293 goto done;
294 }
295
296 /* 9: floating modifier pressed, initiate a resize */
285297 if (dest == CLICK_INSIDE && mod_pressed && is_right_click) {
286298 if (floating_mod_on_tiled_client(con, event)) {
287299 return;
292304 xcb_flush(conn);
293305 return;
294306 }
295 /* 8: otherwise, check for border/decoration clicks and resize */
307 /* 10: otherwise, check for border/decoration clicks and resize */
296308 if ((dest == CLICK_BORDER || dest == CLICK_DECORATION) &&
297309 is_left_or_right_click) {
298310 DLOG("Trying to resize (tiling)\n");
10221022 ysuccess(true);
10231023 }
10241024
1025 typedef struct user_output_name {
1026 char *name;
1027 TAILQ_ENTRY(user_output_name) user_output_names;
1028 } user_output_name;
1029 typedef TAILQ_HEAD(user_output_names_head, user_output_name) user_output_names_head;
1030
1031 static void user_output_names_add(user_output_names_head *list, const char *name) {
1032 if (strcmp(name, "next") == 0) {
1033 /* "next" here works like a wildcard: It "expands" to all available
1034 * outputs. */
1035 Output *output;
1036 TAILQ_FOREACH (output, &outputs, outputs) {
1037 user_output_name *co = scalloc(sizeof(user_output_name), 1);
1038 co->name = sstrdup(output_primary_name(output));
1039 TAILQ_INSERT_TAIL(list, co, user_output_names);
1040 }
1041 return;
1042 }
1043
1044 user_output_name *co = scalloc(sizeof(user_output_name), 1);
1045 co->name = sstrdup(name);
1046 TAILQ_INSERT_TAIL(list, co, user_output_names);
1047 return;
1048 }
1049
1050 static Output *user_output_names_find_next(user_output_names_head *names, Output *current_output) {
1051 Output *target_output = NULL;
1052 user_output_name *uo;
1053 TAILQ_FOREACH (uo, names, user_output_names) {
1054 if (!target_output) {
1055 /* The first available output from the list is used in 2 cases:
1056 * 1. When we must wrap around the user list. For example, if user
1057 * specifies outputs A B C and C is `current_output`.
1058 * 2. When the current output is not in the user list. For example,
1059 * user specifies A B C and D is `current_output`. */
1060 target_output = get_output_from_string(current_output, uo->name);
1061 }
1062 if (strcasecmp(output_primary_name(current_output), uo->name) == 0) {
1063 /* The current output is in the user list */
1064 while (true) {
1065 /* This corrupts the outer loop but it is ok since we are going
1066 * to break anyway. */
1067 uo = TAILQ_NEXT(uo, user_output_names);
1068 if (!uo) {
1069 /* We reached the end of the list. We should use the first
1070 * available output that, if it exists, is already saved in
1071 * target_output. */
1072 break;
1073 }
1074 Output *out = get_output_from_string(current_output, uo->name);
1075 if (out) {
1076 return out;
1077 }
1078 }
1079 break;
1080 }
1081 }
1082 return target_output;
1083 }
1084
1085 static void user_output_names_free(user_output_names_head *names) {
1086 user_output_name *uo;
1087 while (!TAILQ_EMPTY(names)) {
1088 uo = TAILQ_FIRST(names);
1089 free(uo->name);
1090 TAILQ_REMOVE(names, uo, user_output_names);
1091 free(uo);
1092 }
1093 }
1094
10251095 /*
10261096 * Implementation of 'move [window|container|workspace] [to] output <strings>'.
10271097 *
10301100 /* Initialize a data structure that is used to save multiple user-specified
10311101 * output names since this function is called multiple types for each
10321102 * command call. */
1033 typedef struct user_output_name {
1034 char *name;
1035 TAILQ_ENTRY(user_output_name) user_output_names;
1036 } user_output_name;
1037 static TAILQ_HEAD(user_output_names_head, user_output_name) user_output_names = TAILQ_HEAD_INITIALIZER(user_output_names);
1103 static user_output_names_head names = TAILQ_HEAD_INITIALIZER(names);
10381104
10391105 if (name) {
1040 if (strcmp(name, "next") == 0) {
1041 /* "next" here works like a wildcard: It "expands" to all available
1042 * outputs. */
1043 Output *output;
1044 TAILQ_FOREACH (output, &outputs, outputs) {
1045 user_output_name *co = scalloc(sizeof(user_output_name), 1);
1046 co->name = sstrdup(output_primary_name(output));
1047 TAILQ_INSERT_TAIL(&user_output_names, co, user_output_names);
1048 }
1049 return;
1050 }
1051
1052 user_output_name *co = scalloc(sizeof(user_output_name), 1);
1053 co->name = sstrdup(name);
1054 TAILQ_INSERT_TAIL(&user_output_names, co, user_output_names);
1055 return;
1056 }
1057
1058 HANDLE_EMPTY_MATCH;
1059
1060 if (TAILQ_EMPTY(&user_output_names)) {
1106 user_output_names_add(&names, name);
1107 return;
1108 }
1109
1110 HANDLE_EMPTY_MATCH;
1111
1112 if (TAILQ_EMPTY(&names)) {
10611113 yerror("At least one output must be specified");
10621114 return;
10631115 }
10641116
10651117 bool success = false;
1066 user_output_name *uo;
10671118 owindow *current;
10681119 TAILQ_FOREACH (current, &owindows, owindows) {
10691120 Con *ws = con_get_workspace(current->con);
10721123 }
10731124
10741125 Output *current_output = get_output_for_con(ws);
1075
1076 Output *target_output = NULL;
1077 TAILQ_FOREACH (uo, &user_output_names, user_output_names) {
1078 if (strcasecmp(output_primary_name(current_output), uo->name) == 0) {
1079 /* The current output is in the user list */
1080 while (true) {
1081 /* This corrupts the outer loop but it is ok since we are
1082 * going to break anyway. */
1083 uo = TAILQ_NEXT(uo, user_output_names);
1084 if (!uo) {
1085 /* We reached the end of the list. We should use the
1086 * first available output that, if it exists, is
1087 * already saved in target_output. */
1088 break;
1089 }
1090 Output *out = get_output_from_string(current_output, uo->name);
1091 if (out) {
1092 DLOG("Found next target for workspace %s from user list: %s\n", ws->name, uo->name);
1093 target_output = out;
1094 break;
1095 }
1096 }
1097 break;
1098 }
1099 if (!target_output) {
1100 /* The first available output from the list is used in 2 cases:
1101 * 1. When we must wrap around the user list. For example, if
1102 * user specifies outputs A B C and C is `current_output`.
1103 * 2. When the current output is not in the user list. For
1104 * example, user specifies A B C and D is `current_output`.
1105 */
1106 DLOG("Found first target for workspace %s from user list: %s\n", ws->name, uo->name);
1107 target_output = get_output_from_string(current_output, uo->name);
1108 }
1109 }
1126 Output *target_output = user_output_names_find_next(&names, current_output);
11101127 if (target_output) {
11111128 if (move_workspace) {
11121129 workspace_move_to_output(ws, target_output);
11161133 success = true;
11171134 }
11181135 }
1119
1120 while (!TAILQ_EMPTY(&user_output_names)) {
1121 uo = TAILQ_FIRST(&user_output_names);
1122 free(uo->name);
1123 TAILQ_REMOVE(&user_output_names, uo, user_output_names);
1124 free(uo);
1125 }
1136 user_output_names_free(&names);
11261137
11271138 cmd_output->needs_tree_render = success;
11281139 if (success) {
17561767 *
17571768 */
17581769 void cmd_focus_output(I3_CMD, const char *name) {
1770 static user_output_names_head names = TAILQ_HEAD_INITIALIZER(names);
1771 if (name) {
1772 user_output_names_add(&names, name);
1773 return;
1774 }
1775
1776 if (TAILQ_EMPTY(&names)) {
1777 yerror("At least one output must be specified");
1778 return;
1779 }
1780
17591781 HANDLE_EMPTY_MATCH;
17601782
17611783 if (TAILQ_EMPTY(&owindows)) {
17641786 }
17651787
17661788 Output *current_output = get_output_for_con(TAILQ_FIRST(&owindows)->con);
1767 Output *output = get_output_from_string(current_output, name);
1768
1769 if (!output) {
1770 yerror("Output %s not found.", name);
1771 return;
1772 }
1773
1774 /* get visible workspace on output */
1775 Con *ws = NULL;
1776 GREP_FIRST(ws, output_get_content(output->con), workspace_is_visible(child));
1777 if (!ws) {
1778 yerror("BUG: No workspace found on output.");
1779 return;
1780 }
1781
1782 workspace_show(ws);
1783
1784 cmd_output->needs_tree_render = true;
1785 ysuccess(true);
1789 Output *target_output = user_output_names_find_next(&names, current_output);
1790 user_output_names_free(&names);
1791 bool success = false;
1792 if (target_output) {
1793 success = true;
1794
1795 /* get visible workspace on output */
1796 Con *ws = NULL;
1797 GREP_FIRST(ws, output_get_content(target_output->con), workspace_is_visible(child));
1798 if (!ws) {
1799 yerror("BUG: No workspace found on output.");
1800 return;
1801 }
1802
1803 workspace_show(ws);
1804 }
1805
1806 cmd_output->needs_tree_render = success;
1807 if (success) {
1808 ysuccess(true);
1809 } else {
1810 yerror("No output matched");
1811 }
17861812 }
17871813
17881814 /*
20372063 }
20382064
20392065 /*
2040 * Implementation of 'title_window_icon <yes|no>' and 'title_window_icon padding <px>'
2066 * Implementation of 'title_window_icon <yes|no|toggle>' and 'title_window_icon padding <px>'
20412067 *
20422068 */
20432069 void cmd_title_window_icon(I3_CMD, const char *enable, int padding) {
2044 if (enable != NULL && !boolstr(enable)) {
2045 padding = -1;
2070 bool is_toggle = false;
2071 if (enable != NULL) {
2072 if (strcmp(enable, "toggle") == 0) {
2073 is_toggle = true;
2074 } else if (!boolstr(enable)) {
2075 padding = -1;
2076 }
20462077 }
20472078 DLOG("setting window_icon=%d\n", padding);
20482079 HANDLE_EMPTY_MATCH;
20492080
20502081 owindow *current;
20512082 TAILQ_FOREACH (current, &owindows, owindows) {
2052 DLOG("setting window_icon for %p / %s\n", current->con, current->con->name);
2053 current->con->window_icon_padding = padding;
2083 if (is_toggle) {
2084 const int current_padding = current->con->window_icon_padding;
2085 if (padding > 0) {
2086 if (current_padding < 0) {
2087 current->con->window_icon_padding = padding;
2088 } else {
2089 /* toggle off, but store padding given */
2090 current->con->window_icon_padding = -(padding + 1);
2091 }
2092 } else {
2093 /* Set to negative of (current value+1) to keep old padding when toggling */
2094 current->con->window_icon_padding = -(current_padding + 1);
2095 }
2096 } else {
2097 current->con->window_icon_padding = padding;
2098 }
2099 DLOG("Set window_icon for %p / %s to %d\n", current->con, current->con->name, current->con->window_icon_padding);
20542100
20552101 if (current->con->window != NULL) {
20562102 /* Make sure the window title is redrawn immediately. */
389389 free(possible_tokens);
390390
391391 /* Contains the same amount of characters as 'input' has, but with
392 * the unparseable part highlighted using ^ characters. */
392 * the unparsable part highlighted using ^ characters. */
393393 char *position = smalloc(len + 1);
394394 for (const char *copywalk = input; *copywalk != '\0'; copywalk++)
395395 position[(copywalk - input)] = (copywalk >= walk ? '^' : ' ');
730730 }
731731
732732 /*
733 * Start from a container and traverse the transient_for linked list. Returns
734 * true if target window is found in the list. Protects againsts potential
735 * cycles.
736 *
737 */
738 bool con_find_transient_for_window(Con *start, xcb_window_t target) {
739 Con *transient_con = start;
740 int count = con_num_windows(croot);
741 while (transient_con != NULL &&
742 transient_con->window != NULL &&
743 transient_con->window->transient_for != XCB_NONE) {
744 DLOG("transient_con = 0x%08x, transient_con->window->transient_for = 0x%08x, target = 0x%08x\n",
745 transient_con->window->id, transient_con->window->transient_for, target);
746 if (transient_con->window->transient_for == target) {
747 return true;
748 }
749 Con *next_transient = con_by_window_id(transient_con->window->transient_for);
750 if (next_transient == NULL) {
751 break;
752 }
753 /* Some clients (e.g. x11-ssh-askpass) actually set WM_TRANSIENT_FOR to
754 * their own window id, so break instead of looping endlessly. */
755 if (transient_con == next_transient) {
756 break;
757 }
758 transient_con = next_transient;
759
760 if (count-- <= 0) { /* Avoid cycles, see #4404 */
761 break;
762 }
763 }
764 return false;
765 }
766
767 /*
733768 * Returns true if and only if the given containers holds the mark.
734769 *
735770 */
851886 Con *con_for_window(Con *con, i3Window *window, Match **store_match) {
852887 Con *child;
853888 Match *match;
854 //DLOG("searching con for window %p starting at con %p\n", window, con);
855 //DLOG("class == %s\n", window->class_class);
856889
857890 TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
858891 TAILQ_FOREACH (match, &(child->swallow_head), matches) {
10111044 Con *child;
10121045 int children = con_num_children(con);
10131046
1014 // calculate how much we have distributed and how many containers
1015 // with a percentage set we have
1047 /* calculate how much we have distributed and how many containers with a
1048 * percentage set we have */
10161049 double total = 0.0;
10171050 int children_with_percent = 0;
10181051 TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
10221055 }
10231056 }
10241057
1025 // if there were children without a percentage set, set to a value that
1026 // will make those children proportional to all others
1058 /* if there were children without a percentage set, set to a value that
1059 * will make those children proportional to all others */
10271060 if (children_with_percent != children) {
10281061 TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
10291062 if (child->percent <= 0.0) {
10361069 }
10371070 }
10381071
1039 // if we got a zero, just distribute the space equally, otherwise
1040 // distribute according to the proportions we got
1072 /* if we got a zero, just distribute the space equally, otherwise
1073 * distribute according to the proportions we got */
10411074 if (total == 0.0) {
10421075 TAILQ_FOREACH (child, &(con->nodes_head), nodes) {
10431076 child->percent = 1.0 / children;
13551388 return true;
13561389 }
13571390
1358 /*
1359 * Moves the given container to the given mark.
1360 *
1361 */
1362 bool con_move_to_mark(Con *con, const char *mark) {
1363 Con *target = con_by_mark(mark);
1364 if (target == NULL) {
1365 DLOG("found no container with mark \"%s\"\n", mark);
1366 return false;
1367 }
1368
1391 bool con_move_to_target(Con *con, Con *target) {
13691392 /* For target containers in the scratchpad, we just send the window to the scratchpad. */
13701393 if (con_get_workspace(target) == workspace_get("__i3_scratch")) {
13711394 DLOG("target container is in the scratchpad, moving container to scratchpad.\n");
14001423 }
14011424
14021425 return _con_move_to_con(con, target, false, true, false, false, true);
1426 }
1427
1428 /*
1429 * Moves the given container to the given mark.
1430 *
1431 */
1432 bool con_move_to_mark(Con *con, const char *mark) {
1433 Con *target = con_by_mark(mark);
1434 if (target == NULL) {
1435 DLOG("found no container with mark \"%s\"\n", mark);
1436 return false;
1437 }
1438
1439 return con_move_to_target(con, target);
14031440 }
14041441
14051442 /*
22012238 } else
22022239 DLOG("Discarding urgency WM_HINT because timer is running\n");
22032240
2204 //CLIENT_LOG(con);
22052241 if (con->window) {
22062242 if (con->urgent) {
22072243 gettimeofday(&con->window->urgent, NULL);
196196 INIT_COLOR(config.client.focused_inactive, "#333333", "#5f676a", "#ffffff", "#484e50");
197197 INIT_COLOR(config.client.unfocused, "#333333", "#222222", "#888888", "#292d2e");
198198 INIT_COLOR(config.client.urgent, "#2f343a", "#900000", "#ffffff", "#900000");
199 config.client.got_focused_tab_title = false;
199200
200201 /* border and indicator color are ignored for placeholder contents */
201202 INIT_COLOR(config.client.placeholder, "#000000", "#0c0c0c", "#ffffff", "#000000");
271272 set_font(&config.font);
272273 }
273274
275 /* Make bar config blocks without a configured font use the i3-wide font. */
276 Barconfig *current;
277 TAILQ_FOREACH (current, &barconfigs, configs) {
278 if (current->font != NULL) {
279 continue;
280 }
281 current->font = sstrdup(config.font.pattern);
282 }
283
274284 if (load_type == C_RELOAD) {
275285 translate_keysyms();
276286 grab_all_keys(conn);
162162 return result;
163163 }
164164
165 static char *font_pattern;
166
167165 CFGFUN(font, const char *font) {
168166 config.font = load_font(font, true);
169167 set_font(&config.font);
170
171 /* Save the font pattern for using it as bar font later on */
172 FREE(font_pattern);
173 font_pattern = sstrdup(font);
174168 }
175169
176170 CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command) {
185179 static bool current_mode_pango_markup;
186180
187181 CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command) {
182 if (current_mode == NULL) {
183 /* When using an invalid mode name, e.g. “default” */
184 return;
185 }
186
188187 configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, current_mode, current_mode_pango_markup);
189188 }
190189
466465 }
467466
468467 CFGFUN(color, const char *colorclass, const char *border, const char *background, const char *text, const char *indicator, const char *child_border) {
469 #define APPLY_COLORS(classname) \
470 do { \
471 if (strcmp(colorclass, "client." #classname) == 0) { \
472 config.client.classname.border = draw_util_hex_to_color(border); \
473 config.client.classname.background = draw_util_hex_to_color(background); \
474 config.client.classname.text = draw_util_hex_to_color(text); \
475 if (indicator != NULL) { \
476 config.client.classname.indicator = draw_util_hex_to_color(indicator); \
477 } \
478 if (child_border != NULL) { \
479 config.client.classname.child_border = draw_util_hex_to_color(child_border); \
480 } else { \
481 config.client.classname.child_border = config.client.classname.background; \
482 } \
483 } \
468 #define APPLY_COLORS(classname) \
469 do { \
470 if (strcmp(colorclass, "client." #classname) == 0) { \
471 if (strcmp("focused_tab_title", #classname) == 0) { \
472 config.client.got_focused_tab_title = true; \
473 if (indicator || child_border) { \
474 ELOG("indicator and child_border colors have no effect for client.focused_tab_title\n"); \
475 } \
476 } \
477 config.client.classname.border = draw_util_hex_to_color(border); \
478 config.client.classname.background = draw_util_hex_to_color(background); \
479 config.client.classname.text = draw_util_hex_to_color(text); \
480 if (indicator != NULL) { \
481 config.client.classname.indicator = draw_util_hex_to_color(indicator); \
482 } \
483 if (child_border != NULL) { \
484 config.client.classname.child_border = draw_util_hex_to_color(child_border); \
485 } else { \
486 config.client.classname.child_border = config.client.classname.background; \
487 } \
488 return; \
489 } \
484490 } while (0)
485491
486492 APPLY_COLORS(focused_inactive);
493 APPLY_COLORS(focused_tab_title);
487494 APPLY_COLORS(focused);
488495 APPLY_COLORS(unfocused);
489496 APPLY_COLORS(urgent);
743750
744751 config.number_barconfigs++;
745752
746 /* If no font was explicitly set, we use the i3 font as default */
747 if (current_bar->font == NULL && font_pattern != NULL)
748 current_bar->font = sstrdup(font_pattern);
749
750753 TAILQ_INSERT_TAIL(&barconfigs, current_bar, configs);
751754 /* Simply reset the pointer, but don't free the resources. */
752755 current_bar = NULL;
164164 static void next_state(const cmdp_token *token, struct parser_ctx *ctx) {
165165 cmdp_state _next_state = token->next_state;
166166
167 //printf("token = name %s identifier %s\n", token->name, token->identifier);
168 //printf("next_state = %d\n", token->next_state);
169167 if (token->next_state == __CALL) {
170168 struct ConfigResultIR subcommand_output = {
171169 .ctx = ctx,
253251 bool token_handled;
254252 linecnt = 1;
255253
256 // TODO: make this testable
257254 #ifndef TEST_PARSER
258255 struct ConfigResultIR subcommand_output = {
259256 .ctx = ctx,
268265 * separate configuration directives. */
269266 while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
270267 walk++;
271
272 //printf("remaining input: %s\n", walk);
273268
274269 cmdp_token_ptr *ptr = &(tokens[ctx->state]);
275270 token_handled = false;
377372 }
378373
379374 if (strcmp(token->name, "end") == 0) {
380 //printf("checking for end: *%s*\n", walk);
381375 if (*walk == '\0' || *walk == '\n' || *walk == '\r') {
382376 next_state(token, ctx);
383377 token_handled = true;
385379 * datastructure for commands which do *not* specify any
386380 * criteria, we re-initialize the criteria system after
387381 * every command. */
388 // TODO: make this testable
389382 #ifndef TEST_PARSER
390383 cfg_criteria_init(&(ctx->current_match), &subcommand_output, INITIAL);
391384 #endif
444437 const char *error_line = start_of_line(walk, input);
445438
446439 /* Contains the same amount of characters as 'input' has, but with
447 * the unparseable part highlighted using ^ characters. */
440 * the unparsable part highlighted using ^ characters. */
448441 char *position = scalloc(strlen(error_line) + 1, 1);
449442 const char *copywalk;
450443 for (copywalk = error_line;
10071000 char *next;
10081001 for (next = bufcopy;
10091002 next < (bufcopy + stbuf.st_size) &&
1010 (next = strcasestr(next, current->key)) != NULL;
1011 next += strlen(current->key)) {
1012 *next = '_';
1003 (next = strcasestr(next, current->key)) != NULL;) {
1004 /* We need to invalidate variables completely (otherwise we may count
1005 * the same variable more than once, thus causing buffer overflow or
1006 * allocation failure) with spaces (variable names cannot contain spaces) */
1007 char *end = next + strlen(current->key);
1008 while (next < end) {
1009 *next++ = ' ';
1010 }
10131011 extra_bytes += extra;
10141012 }
10151013 }
6868 /*
6969 * Connects to i3 to find out the currently running version. Useful since it
7070 * might be different from the version compiled into this binary (maybe the
71 * user didn’t correctly install i3 or forgot te restart it).
71 * user didn’t correctly install i3 or forgot to restart it).
7272 *
7373 * The output looks like this:
7474 * Running i3 version: 4.2-202-gb8e782c (2012-08-12, branch "next") (pid 14804)
252252 }
253253 /* Consider the part of the focus stack of our current workspace:
254254 * [ ... S_{i-1} S_{i} S_{i+1} ... ]
255 * Where S_{x} is a container tree and the container 'con' that is beeing switched to
255 * Where S_{x} is a container tree and the container 'con' that is being switched to
256256 * floating belongs in S_{i}. The new floating container, 'nc', will have the
257257 * workspace as its parent so it needs to be placed in this stack. If C was focused
258258 * we just need to call con_focus(). Otherwise, nc must be placed before or after S_{i}.
6969 event->response_type != response_type)
7070 continue;
7171
72 /* instead of removing a sequence number we better wait until it gets
73 * garbage collected. it may generate multiple events (there are multiple
74 * enter_notifies for one configure_request, for example). */
75 //SLIST_REMOVE(&ignore_events, event, Ignore_Event, ignore_events);
76 //free(event);
72 /* Instead of removing & freeing a sequence number we better wait until
73 * it gets garbage collected. It may generate multiple events (there
74 * are multiple enter_notifies for one configure_request, for example). */
7775 return true;
7876 }
7977
269267 * Configure requests are received when the application wants to resize windows
270268 * on their own.
271269 *
272 * We generate a synthethic configure notify event to signalize the client its
270 * We generate a synthetic configure notify event to signalize the client its
273271 * "new" position.
274272 *
275273 */
800798 } else if (event->type == A_WM_CHANGE_STATE) {
801799 /* http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4 */
802800 if (event->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) {
803 /* For compatiblity reasons, Wine will request iconic state and cannot ensure that the WM has agreed on it;
801 /* For compatibility reasons, Wine will request iconic state and cannot ensure that the WM has agreed on it;
804802 * immediately revert to normal to avoid being stuck in a paused state. */
805803 DLOG("Client has requested iconic state, rejecting. (window = %08x)\n", event->window);
806804 long data[] = {XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE};
11831181 }
11841182
11851183 /*
1186 * Handles the _MOTIF_WM_HINTS property of specifing window deocration settings.
1184 * Handles the _MOTIF_WM_HINTS property of specifying window deocration settings.
11871185 *
11881186 */
11891187 static bool handle_motif_hints_change(Con *con, xcb_get_property_reply_t *prop) {
11901188 border_style_t motif_border_style;
1191 window_update_motif_hints(con->window, prop, &motif_border_style);
1192
1193 if (motif_border_style != con->border_style && motif_border_style != BS_NORMAL) {
1189 bool has_mwm_hints = window_update_motif_hints(con->window, prop, &motif_border_style);
1190
1191 if (has_mwm_hints && motif_border_style != con->border_style) {
11941192 DLOG("Update border style of con %p to %d\n", con, motif_border_style);
11951193 con_set_border_style(con, motif_border_style, con->current_border_width);
11961194
13451343 }
13461344
13471345 if (handler == NULL) {
1348 //DLOG("Unhandled property notify for atom %d (0x%08x)\n", atom, atom);
1346 /* DLOG("Unhandled property notify for atom %d (0x%08x)\n", atom, atom); */
13491347 return;
13501348 }
13511349
15231521 break;
15241522
15251523 default:
1526 //DLOG("Unhandled event of type %d\n", type);
1527 break;
1528 }
1529 }
1524 /* DLOG("Unhandled event of type %d\n", type); */
1525 break;
1526 }
1527 }
136136 * For 512 MiB of RAM this will lead to a 5 MiB log buffer.
137137 * At the moment (2011-12-10), no testcase leads to an i3 log
138138 * of more than ~ 600 KiB. */
139 logbuffer_size = min(physical_mem_bytes * 0.01, shmlog_size);
139 logbuffer_size = shmlog_size;
140 if (physical_mem_bytes * 0.01 < (long long)shmlog_size) {
141 logbuffer_size = physical_mem_bytes * 0.01;
142 }
143
140144 #if defined(__FreeBSD__)
141145 sasprintf(&shmlogname, "/tmp/i3-log-%d", getpid());
142146 #else
682682 else
683683 config.ipc_socket_path = sstrdup(config.ipc_socket_path);
684684 }
685 /* Create the UNIX domain socket for IPC */
686 int ipc_socket = create_socket(config.ipc_socket_path, &current_socketpath);
687 if (ipc_socket == -1) {
688 die("Could not create the IPC socket: %s", config.ipc_socket_path);
689 }
685690
686691 if (config.force_xinerama) {
687692 force_xinerama = true;
690695 /* Acquire the WM_Sn selection. */
691696 {
692697 /* Get the WM_Sn atom */
693 char *atom_name = xcb_atom_name_by_screen("WM_S", conn_screen);
698 char *atom_name = xcb_atom_name_by_screen("WM", conn_screen);
694699 wm_sn_selection_owner = xcb_generate_id(conn);
695700
696701 if (atom_name == NULL) {
697 ELOG("xcb_atom_name_by_screen(\"WM_S\", %d) failed, exiting\n", conn_screen);
702 ELOG("xcb_atom_name_by_screen(\"WM\", %d) failed, exiting\n", conn_screen);
698703 return 1;
699704 }
700705
987992
988993 tree_render();
989994
990 /* Create the UNIX domain socket for IPC */
991 int ipc_socket = create_socket(config.ipc_socket_path, &current_socketpath);
992 if (ipc_socket == -1) {
993 ELOG("Could not create the IPC socket, IPC disabled\n");
994 } else {
995 struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
996 ev_io_init(ipc_io, ipc_new_client, ipc_socket, EV_READ);
997 ev_io_start(main_loop, ipc_io);
998 }
995 /* Listen to the IPC socket for clients */
996 struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
997 ev_io_init(ipc_io, ipc_new_client, ipc_socket, EV_READ);
998 ev_io_start(main_loop, ipc_io);
999999
10001000 /* Chose a file name in /tmp/ based on the PID */
10011001 char *log_stream_socket_path = get_process_filename("log-stream-socket");
122122
123123 geomc = xcb_get_geometry(conn, d);
124124
125 /* Check if the window is mapped (it could be not mapped when intializing and
125 /* Check if the window is mapped (it could be not mapped when initializing and
126126 calling manage_window() for every window) */
127127 if ((attr = xcb_get_window_attributes_reply(conn, cookie, 0)) == NULL) {
128128 DLOG("Could not get attributes\n");
213213 window_update_role(cwindow, xcb_get_property_reply(conn, role_cookie, NULL));
214214 bool urgency_hint;
215215 window_update_hints(cwindow, xcb_get_property_reply(conn, wm_hints_cookie, NULL), &urgency_hint);
216 border_style_t motif_border_style = BS_NORMAL;
217 window_update_motif_hints(cwindow, xcb_get_property_reply(conn, motif_wm_hints_cookie, NULL), &motif_border_style);
216 border_style_t motif_border_style;
217 bool has_mwm_hints = window_update_motif_hints(cwindow, xcb_get_property_reply(conn, motif_wm_hints_cookie, NULL), &motif_border_style);
218218 window_update_normal_hints(cwindow, xcb_get_property_reply(conn, wm_normal_hints_cookie, NULL), geom);
219219 window_update_machine(cwindow, xcb_get_property_reply(conn, wm_machine_cookie, NULL));
220220 xcb_get_property_reply_t *type_reply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
484484 (cwindow->leader != XCB_NONE &&
485485 cwindow->leader != cwindow->id &&
486486 con_by_window_id(cwindow->leader) != NULL)) {
487 LOG("This window is transient for another window, setting floating\n");
487 DLOG("This window is transient for another window, setting floating\n");
488488 want_floating = true;
489489
490490 if (config.popup_during_fullscreen == PDF_LEAVE_FULLSCREEN &&
491491 fs != NULL) {
492 LOG("There is a fullscreen window, leaving fullscreen mode\n");
492 DLOG("There is a fullscreen window, leaving fullscreen mode\n");
493493 con_toggle_fullscreen(fs, CF_OUTPUT);
494494 } else if (config.popup_during_fullscreen == PDF_SMART &&
495495 fs != NULL &&
496496 fs->window != NULL) {
497 i3Window *transient_win = cwindow;
498 while (transient_win != NULL &&
499 transient_win->transient_for != XCB_NONE) {
500 if (transient_win->transient_for == fs->window->id) {
501 LOG("This floating window belongs to the fullscreen window (popup_during_fullscreen == smart)\n");
502 set_focus = true;
503 break;
504 }
505 Con *next_transient = con_by_window_id(transient_win->transient_for);
506 if (next_transient == NULL)
507 break;
508 /* Some clients (e.g. x11-ssh-askpass) actually set
509 * WM_TRANSIENT_FOR to their own window id, so break instead of
510 * looping endlessly. */
511 if (transient_win == next_transient->window)
512 break;
513 transient_win = next_transient->window;
514 }
497 set_focus = con_find_transient_for_window(nc, fs->window->id);
515498 }
516499 }
517500
527510 if (nc->geometry.width == 0)
528511 nc->geometry = (Rect){geom->x, geom->y, geom->width, geom->height};
529512
530 if (motif_border_style != BS_NORMAL) {
513 if (has_mwm_hints) {
531514 DLOG("MOTIF_WM_HINTS specifies decorations (border_style = %d)\n", motif_border_style);
532515 if (want_floating) {
533516 con_set_border_style(nc, motif_border_style, config.default_floating_border_width);
227227 * the focused container, con, is now a child of ws. To work around this
228228 * and still produce the correct workspace focus events (see
229229 * 517-regress-move-direction-ipc.t) we need to temporarily set focused
230 * to the old workspace. */
230 * to the old workspace.
231 *
232 * The following happen:
233 * 1. Focus con to push it on the top of the focus stack in its new
234 * workspace
235 * 2. Set focused to the old workspace to force workspace_show to
236 * execute
237 * 3. workspace_show will descend focus and target our con for
238 * focusing. This also ensures that the mouse warps correctly.
239 * See: #3518. */
240 con_focus(con);
231241 focused = old_ws;
232242 workspace_show(ws);
233 con_focus(con);
234243 }
235244
236245 /* force re-painting the indicators */
319328 } else {
320329 TAILQ_SWAP(con, swap, &(swap->parent->nodes_head), nodes);
321330 }
331
332 /* redraw parents to ensure all parent split container titles are updated correctly */
333 con_force_split_parents_redraw(con);
322334
323335 ipc_send_window_event("move", con);
324336 return;
664664
665665 new->primary = monitor_info->primary;
666666
667 new->changed =
668 update_if_necessary(&(new->rect.x), monitor_info->x) |
669 update_if_necessary(&(new->rect.y), monitor_info->y) |
670 update_if_necessary(&(new->rect.width), monitor_info->width) |
671 update_if_necessary(&(new->rect.height), monitor_info->height);
667 const bool update_x = update_if_necessary(&(new->rect.x), monitor_info->x);
668 const bool update_y = update_if_necessary(&(new->rect.y), monitor_info->y);
669 const bool update_w = update_if_necessary(&(new->rect.width), monitor_info->width);
670 const bool update_h = update_if_necessary(&(new->rect.height), monitor_info->height);
671
672 new->changed = update_x || update_y || update_w || update_h;
672673
673674 DLOG("name %s, x %d, y %d, width %d px, height %d px, width %d mm, height %d mm, primary %d, automatic %d\n",
674675 name,
742743 return;
743744 }
744745
745 bool updated = update_if_necessary(&(new->rect.x), crtc->x) |
746 update_if_necessary(&(new->rect.y), crtc->y) |
747 update_if_necessary(&(new->rect.width), crtc->width) |
748 update_if_necessary(&(new->rect.height), crtc->height);
746 const bool update_x = update_if_necessary(&(new->rect.x), crtc->x);
747 const bool update_y = update_if_necessary(&(new->rect.y), crtc->y);
748 const bool update_w = update_if_necessary(&(new->rect.width), crtc->width);
749 const bool update_h = update_if_necessary(&(new->rect.height), crtc->height);
750 const bool updated = update_x || update_y || update_w || update_h;
749751 free(crtc);
750752 new->active = (new->rect.width != 0 && new->rect.height != 0);
751753 if (!new->active) {
942944 uint32_t width = min(other->rect.width, output->rect.width);
943945 uint32_t height = min(other->rect.height, output->rect.height);
944946
945 if (update_if_necessary(&(output->rect.width), width) |
946 update_if_necessary(&(output->rect.height), height))
947 const bool update_w = update_if_necessary(&(output->rect.width), width);
948 const bool update_h = update_if_necessary(&(output->rect.height), height);
949 if (update_w || update_h) {
947950 output->changed = true;
951 }
948952
949953 update_if_necessary(&(other->rect.width), width);
950954 update_if_necessary(&(other->rect.height), height);
1919 *
2020 */
2121 struct regex *regex_new(const char *pattern) {
22 const char *error;
23 int errorcode, offset;
22 int errorcode;
23 PCRE2_SIZE offset;
2424
2525 struct regex *re = scalloc(1, sizeof(struct regex));
2626 re->pattern = sstrdup(pattern);
27 int options = PCRE_UTF8;
27 uint32_t options = PCRE2_UTF;
2828 /* We use PCRE_UCP so that \B, \b, \D, \d, \S, \s, \W, \w and some POSIX
2929 * character classes play nicely with Unicode */
30 options |= PCRE_UCP;
31 while (!(re->regex = pcre_compile2(pattern, options, &errorcode, &error, &offset, NULL))) {
32 /* If the error is that PCRE was not compiled with UTF-8 support we
33 * disable it and try again */
34 if (errorcode == 32) {
35 options &= ~PCRE_UTF8;
36 continue;
37 }
38 ELOG("PCRE regular expression compilation failed at %d: %s\n",
39 offset, error);
30 options |= PCRE2_UCP;
31 if (!(re->regex = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, options, &errorcode, &offset, NULL))) {
32 PCRE2_UCHAR buffer[256];
33 pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
34 ELOG("PCRE regular expression compilation failed at %lu: %s\n",
35 offset, buffer);
4036 regex_free(re);
4137 return NULL;
42 }
43 re->extra = pcre_study(re->regex, 0, &error);
44 /* If an error happened, we print the error message, but continue.
45 * Studying the regular expression leads to faster matching, but it’s not
46 * absolutely necessary. */
47 if (error) {
48 ELOG("PCRE regular expression studying failed: %s\n", error);
4938 }
5039 return re;
5140 }
5948 return;
6049 FREE(regex->pattern);
6150 FREE(regex->regex);
62 FREE(regex->extra);
6351 FREE(regex);
6452 }
6553
7058 *
7159 */
7260 bool regex_matches(struct regex *regex, const char *input) {
61 pcre2_match_data *match_data;
7362 int rc;
63
64 match_data = pcre2_match_data_create_from_pattern(regex->regex, NULL);
7465
7566 /* We use strlen() because pcre_exec() expects the length of the input
7667 * string in bytes */
77 if ((rc = pcre_exec(regex->regex, regex->extra, input, strlen(input), 0, 0, NULL, 0)) == 0) {
68 rc = pcre2_match(regex->regex, (PCRE2_SPTR)input, strlen(input), 0, 0, match_data, NULL);
69 pcre2_match_data_free(match_data);
70 if (rc > 0) {
7871 LOG("Regular expression \"%s\" matches \"%s\"\n",
7972 regex->pattern, input);
8073 return true;
8174 }
8275
83 if (rc == PCRE_ERROR_NOMATCH) {
76 if (rc == PCRE2_ERROR_NOMATCH) {
8477 LOG("Regular expression \"%s\" does not match \"%s\"\n",
8578 regex->pattern, input);
8679 return false;
225225 }
226226
227227 Con *floating_child = con_descend_focused(child);
228 Con *transient_con = floating_child;
229 bool is_transient_for = false;
230 while (transient_con != NULL &&
231 transient_con->window != NULL &&
232 transient_con->window->transient_for != XCB_NONE) {
233 DLOG("transient_con = 0x%08x, transient_con->window->transient_for = 0x%08x, fullscreen_id = 0x%08x\n",
234 transient_con->window->id, transient_con->window->transient_for, fullscreen->window->id);
235 if (transient_con->window->transient_for == fullscreen->window->id) {
236 is_transient_for = true;
237 break;
238 }
239 Con *next_transient = con_by_window_id(transient_con->window->transient_for);
240 if (next_transient == NULL)
241 break;
242 /* Some clients (e.g. x11-ssh-askpass) actually set
243 * WM_TRANSIENT_FOR to their own window id, so break instead of
244 * looping endlessly. */
245 if (transient_con == next_transient)
246 break;
247 transient_con = next_transient;
248 }
249
250 if (!is_transient_for)
251 continue;
252 else {
228 if (con_find_transient_for_window(floating_child, fullscreen->window->id)) {
253229 DLOG("Rendering floating child even though in fullscreen mode: "
254230 "floating->transient_for (0x%08x) --> fullscreen->id (0x%08x)\n",
255231 floating_child->window->transient_for, fullscreen->window->id);
232 } else {
233 continue;
256234 }
257235 }
258236 DLOG("floating child at (%d,%d) with %d x %d\n",
0 /*
1 * vim:ts=4:sw=4:expandtab
2 *
3 * i3 - an improved dynamic tiling window manager
4 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
5 *
6 * tiling_drag.c: Reposition tiled windows by dragging.
7 *
8 */
9 #include "all.h"
10 static xcb_window_t create_drop_indicator(Rect rect);
11
12 /*
13 * Includes decoration (container title) to the container's rect. This way we
14 * can find the correct drop target if the mouse is on a container's
15 * decoration.
16 *
17 */
18 static Rect con_rect_plus_deco_height(Con *con) {
19 Rect rect = con->rect;
20 rect.height += con->deco_rect.height;
21 if (rect.y < con->deco_rect.height) {
22 rect.y = 0;
23 } else {
24 rect.y -= con->deco_rect.height;
25 }
26 return rect;
27 }
28
29 /*
30 * Return an appropriate target at given coordinates.
31 *
32 */
33 static Con *find_drop_target(uint32_t x, uint32_t y) {
34 Con *con;
35 TAILQ_FOREACH (con, &all_cons, all_cons) {
36 Rect rect = con_rect_plus_deco_height(con);
37
38 if (rect_contains(rect, x, y) &&
39 con_has_managed_window(con) &&
40 !con_is_floating(con) &&
41 !con_is_hidden(con)) {
42 Con *ws = con_get_workspace(con);
43 if (!workspace_is_visible(ws)) {
44 continue;
45 }
46 Con *fs = con_get_fullscreen_covering_ws(ws);
47 return fs ? fs : con;
48 }
49 }
50
51 /* Couldn't find leaf container, get a workspace. */
52 Output *output = get_output_containing(x, y);
53 if (!output) {
54 return NULL;
55 }
56 Con *content = output_get_content(output->con);
57 /* Still descend because you can drag to the bar on an non-empty workspace. */
58 return con_descend_tiling_focused(content);
59 }
60
61 typedef enum { DT_SIBLING,
62 DT_CENTER,
63 DT_PARENT
64 } drop_type_t;
65
66 struct callback_params {
67 xcb_window_t *indicator;
68 Con **target;
69 direction_t *direction;
70 drop_type_t *drop_type;
71 };
72
73 static Rect adjust_rect(Rect rect, direction_t direction, uint32_t threshold) {
74 switch (direction) {
75 case D_LEFT:
76 rect.width = threshold;
77 break;
78 case D_UP:
79 rect.height = threshold;
80 break;
81 case D_RIGHT:
82 rect.x += (rect.width - threshold);
83 rect.width = threshold;
84 break;
85 case D_DOWN:
86 rect.y += (rect.height - threshold);
87 rect.height = threshold;
88 break;
89 }
90 return rect;
91 }
92
93 static bool con_on_side_of_parent(Con *con, direction_t direction) {
94 const orientation_t orientation = orientation_from_direction(direction);
95 direction_t reverse_direction;
96 switch (direction) {
97 case D_LEFT:
98 reverse_direction = D_RIGHT;
99 break;
100 case D_RIGHT:
101 reverse_direction = D_LEFT;
102 break;
103 case D_UP:
104 reverse_direction = D_DOWN;
105 break;
106 case D_DOWN:
107 reverse_direction = D_UP;
108 break;
109 }
110 return (con_orientation(con->parent) != orientation ||
111 con->parent->layout == L_STACKED || con->parent->layout == L_TABBED ||
112 con_descend_direction(con->parent, reverse_direction) == con);
113 }
114
115 /*
116 * The callback that is executed on every mouse move while dragging. On each
117 * invocation we determine the drop target and the direction in which to insert
118 * the dragged container. The indicator window is updated to show the new
119 * position of the dragged container. The target container and direction are
120 * passed out using the callback params.
121 *
122 */
123 DRAGGING_CB(drag_callback) {
124 /* 30% of the container (minus the parent indicator) is used to drop the
125 * dragged container as a sibling to the target */
126 const double sibling_indicator_percent_of_rect = 0.3;
127 /* Use the base decoration height and add a few pixels. This makes the
128 * outer indicator generally thin but at least thick enough to cover
129 * container titles */
130 const double parent_indicator_max_size = render_deco_height() + logical_px(5);
131
132 Con *target = find_drop_target(new_x, new_y);
133 if (target == NULL) {
134 return;
135 }
136
137 Rect rect = con_rect_plus_deco_height(target);
138
139 direction_t direction = 0;
140 drop_type_t drop_type = DT_CENTER;
141 bool draw_window = true;
142 const struct callback_params *params = extra;
143
144 if (target->type == CT_WORKSPACE) {
145 goto create_indicator;
146 }
147
148 /* Define the thresholds in pixels. The drop type depends on the cursor
149 * position. */
150 const uint32_t min_rect_dimension = min(rect.width, rect.height);
151 const uint32_t sibling_indicator_size = max(logical_px(2), (uint32_t)(sibling_indicator_percent_of_rect * min_rect_dimension));
152 const uint32_t parent_indicator_size = min(
153 parent_indicator_max_size,
154 /* For small containers, start where the sibling indicator finishes.
155 * This is always at least 1 pixel. We use min() to not override the
156 * sibling indicator: */
157 sibling_indicator_size - 1);
158
159 /* Find which edge the cursor is closer to. */
160 const uint32_t d_left = new_x - rect.x;
161 const uint32_t d_top = new_y - rect.y;
162 const uint32_t d_right = rect.x + rect.width - new_x;
163 const uint32_t d_bottom = rect.y + rect.height - new_y;
164 const uint32_t d_min = min(min(d_left, d_right), min(d_top, d_bottom));
165 /* And move the container towards that direction. */
166 if (d_left == d_min) {
167 direction = D_LEFT;
168 } else if (d_top == d_min) {
169 direction = D_UP;
170 } else if (d_right == d_min) {
171 direction = D_RIGHT;
172 } else if (d_bottom == d_min) {
173 direction = D_DOWN;
174 } else {
175 /* Keep the compiler happy */
176 ELOG("min() is broken\n");
177 assert(false);
178 }
179 const bool target_parent = (d_min < parent_indicator_size &&
180 con_on_side_of_parent(target, direction));
181 const bool target_sibling = (d_min < sibling_indicator_size);
182 drop_type = target_parent ? DT_PARENT : (target_sibling ? DT_SIBLING : DT_CENTER);
183
184 /* target == con makes sense only when we are moving away from target's parent. */
185 if (drop_type != DT_PARENT && target == con) {
186 draw_window = false;
187 xcb_destroy_window(conn, *(params->indicator));
188 *(params->indicator) = 0;
189 goto create_indicator;
190 }
191
192 switch (drop_type) {
193 case DT_PARENT:
194 while (target->parent->type != CT_WORKSPACE && con_on_side_of_parent(target->parent, direction)) {
195 target = target->parent;
196 }
197 rect = adjust_rect(target->parent->rect, direction, parent_indicator_size);
198 break;
199 case DT_CENTER:
200 rect = target->rect;
201 rect.x += sibling_indicator_size;
202 rect.y += sibling_indicator_size;
203 rect.width -= sibling_indicator_size * 2;
204 rect.height -= sibling_indicator_size * 2;
205 break;
206 case DT_SIBLING:
207 rect = adjust_rect(target->rect, direction, sibling_indicator_size);
208 break;
209 }
210
211 create_indicator:
212 if (draw_window) {
213 if (*(params->indicator) == 0) {
214 *(params->indicator) = create_drop_indicator(rect);
215 } else {
216 const uint32_t values[4] = {rect.x, rect.y, rect.width, rect.height};
217 const uint32_t mask = XCB_CONFIG_WINDOW_X |
218 XCB_CONFIG_WINDOW_Y |
219 XCB_CONFIG_WINDOW_WIDTH |
220 XCB_CONFIG_WINDOW_HEIGHT;
221 xcb_configure_window(conn, *(params->indicator), mask, values);
222 }
223 }
224 x_mask_event_mask(~XCB_EVENT_MASK_ENTER_WINDOW);
225 xcb_flush(conn);
226
227 *(params->target) = target;
228 *(params->direction) = direction;
229 *(params->drop_type) = drop_type;
230 }
231
232 /*
233 * Returns a new drop indicator window with the given initial coordinates.
234 *
235 */
236 static xcb_window_t create_drop_indicator(Rect rect) {
237 uint32_t mask = 0;
238 uint32_t values[2];
239
240 mask = XCB_CW_BACK_PIXEL;
241 values[0] = config.client.focused.indicator.colorpixel;
242
243 mask |= XCB_CW_OVERRIDE_REDIRECT;
244 values[1] = 1;
245
246 xcb_window_t indicator = create_window(conn, rect, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
247 XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_MOVE, false, mask, values);
248 /* Change the window class to "i3-drag", so that it can be matched in a
249 * compositor configuration. Note that the class needs to be changed before
250 * mapping the window. */
251 xcb_change_property(conn,
252 XCB_PROP_MODE_REPLACE,
253 indicator,
254 XCB_ATOM_WM_CLASS,
255 XCB_ATOM_STRING,
256 8,
257 (strlen("i3-drag") + 1) * 2,
258 "i3-drag\0i3-drag\0");
259 xcb_map_window(conn, indicator);
260 xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, indicator);
261
262 return indicator;
263 }
264
265 /*
266 * Initiates a mouse drag operation on a tiled window.
267 *
268 */
269 void tiling_drag(Con *con, xcb_button_press_event_t *event) {
270 DLOG("Start dragging tiled container: con = %p\n", con);
271 bool set_focus = (con == focused);
272 bool set_fs = con->fullscreen_mode != CF_NONE;
273
274 /* Don't change focus while dragging. */
275 x_mask_event_mask(~XCB_EVENT_MASK_ENTER_WINDOW);
276 xcb_flush(conn);
277
278 /* Indicate drop location while dragging. This blocks until the drag is completed. */
279 Con *target = NULL;
280 direction_t direction;
281 drop_type_t drop_type;
282 xcb_window_t indicator = 0;
283 const struct callback_params params = {&indicator, &target, &direction, &drop_type};
284
285 drag_result_t drag_result = drag_pointer(con, event, XCB_NONE, BORDER_TOP, XCURSOR_CURSOR_MOVE, drag_callback, &params);
286
287 /* Dragging is done. We don't need the indicator window any more. */
288 xcb_destroy_window(conn, indicator);
289
290 if (drag_result == DRAG_REVERT ||
291 target == NULL ||
292 (target == con && drop_type != DT_PARENT) ||
293 !con_exists(target)) {
294 DLOG("drop aborted\n");
295 return;
296 }
297
298 const orientation_t orientation = orientation_from_direction(direction);
299 const position_t position = position_from_direction(direction);
300 const layout_t layout = orientation == VERT ? L_SPLITV : L_SPLITH;
301 con_disable_fullscreen(con);
302 switch (drop_type) {
303 case DT_CENTER:
304 /* Also handles workspaces.*/
305 DLOG("drop to center of %p\n", target);
306 con_move_to_target(con, target);
307 break;
308 case DT_SIBLING:
309 DLOG("drop %s %p\n", position_to_string(position), target);
310 if (con_orientation(target->parent) != orientation) {
311 /* If con and target are the only children of the same parent, we can just change
312 * the parent's layout manually and then move con to the correct position.
313 * tree_split checks for a parent with only one child so it would create a new
314 * parent with the new layout. */
315 if (con->parent == target->parent && con_num_children(target->parent) == 2) {
316 target->parent->layout = layout;
317 } else {
318 tree_split(target, orientation);
319 }
320 }
321
322 insert_con_into(con, target, position);
323
324 ipc_send_window_event("move", con);
325 break;
326 case DT_PARENT: {
327 const bool parent_tabbed_or_stacked = (target->parent->layout == L_TABBED || target->parent->layout == L_STACKED);
328 DLOG("drop %s (%s) of %s%p\n",
329 direction_to_string(direction),
330 position_to_string(position),
331 parent_tabbed_or_stacked ? "tabbed/stacked " : "",
332 target);
333 if (parent_tabbed_or_stacked) {
334 /* When dealing with tabbed/stacked the target can be in the
335 * middle of the container. Thus, after a directional move, con
336 * will still be bound to the tabbed/stacked parent. */
337 if (position == BEFORE) {
338 target = TAILQ_FIRST(&(target->parent->nodes_head));
339 } else {
340 target = TAILQ_LAST(&(target->parent->nodes_head), nodes_head);
341 }
342 }
343 if (con != target) {
344 insert_con_into(con, target, position);
345 }
346 /* tree_move can change the focus */
347 Con *old_focus = focused;
348 tree_move(con, direction);
349 if (focused != old_focus) {
350 con_activate(old_focus);
351 }
352 break;
353 }
354 }
355 /* Warning: target might not exist anymore */
356 target = NULL;
357
358 /* Manage fullscreen status. */
359 if (set_focus || set_fs) {
360 Con *fs = con_get_fullscreen_covering_ws(con_get_workspace(con));
361 if (fs == con) {
362 ELOG("dragged container somehow got fullscreen again.\n");
363 assert(false);
364 } else if (fs && set_focus && set_fs) {
365 /* con was focused & fullscreen, disable other fullscreen container. */
366 con_disable_fullscreen(fs);
367 } else if (fs) {
368 /* con was not focused, prefer other fullscreen container. */
369 set_fs = set_focus = false;
370 } else if (!set_focus) {
371 /* con was not focused. If it was fullscreen and we are moving it to the focused
372 * workspace we must focus it. */
373 set_focus = (set_fs && con_get_workspace(focused) == con_get_workspace(con));
374 }
375 }
376 if (set_fs) {
377 con_enable_fullscreen(con, CF_OUTPUT);
378 }
379 if (set_focus) {
380 workspace_show(con_get_workspace(con));
381 con_focus(con);
382 }
383 tree_render();
384 }
475475 return position == BEFORE ? D_UP : D_DOWN;
476476 }
477477 }
478
479 /*
480 * Converts direction to a string representation.
481 *
482 */
483 const char *direction_to_string(direction_t direction) {
484 switch (direction) {
485 case D_LEFT:
486 return "left";
487 case D_RIGHT:
488 return "right";
489 case D_UP:
490 return "up";
491 case D_DOWN:
492 return "down";
493 }
494 return "invalid";
495 }
496
497 /*
498 * Converts position to a string representation.
499 *
500 */
501 const char *position_to_string(position_t position) {
502 switch (position) {
503 case BEFORE:
504 return "before";
505 case AFTER:
506 return "after";
507 }
508 return "invalid";
509 }
414414 * it is still in use by popular widget toolkits such as GTK+ and Java AWT.
415415 *
416416 */
417 void window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style) {
418 /* This implementation simply mirrors Gnome's Metacity. Official
419 * documentation of this hint is nowhere to be found.
420 * For more information see:
421 * https://people.gnome.org/~tthurman/docs/metacity/xprops_8h-source.html
422 * https://stackoverflow.com/questions/13787553/detect-if-a-x11-window-has-decorations
417 bool window_update_motif_hints(i3Window *win, xcb_get_property_reply_t *prop, border_style_t *motif_border_style) {
418 /* See `man VendorShell' for more info, `XmNmwmDecorations' section:
419 * https://linux.die.net/man/3/vendorshell
420 * The following constants are adapted from <Xm/MwmUtil.h>.
423421 */
424422 #define MWM_HINTS_FLAGS_FIELD 0
425423 #define MWM_HINTS_DECORATIONS_FIELD 2
434432
435433 if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
436434 FREE(prop);
437 return;
435 return false;
438436 }
439437
440438 /* The property consists of an array of 5 uint32_t's. The first value is a
460458 }
461459
462460 FREE(prop);
461 return true;
463462
464463 #undef MWM_HINTS_FLAGS_FIELD
465464 #undef MWM_HINTS_DECORATIONS_FIELD
298298
299299 /*
300300 * Returns true if the workspace is currently visible. Especially important for
301 * multi-monitor environments, as they can have multiple currenlty active
301 * multi-monitor environments, as they can have multiple currently active
302302 * workspaces.
303303 *
304304 */
305305 bool workspace_is_visible(Con *ws) {
306306 Con *output = con_get_output(ws);
307 if (output == NULL)
307 if (output == NULL) {
308308 return false;
309 }
309310 Con *fs = con_get_fullscreen_con(output, CF_OUTPUT);
310 LOG("workspace visible? fs = %p, ws = %p\n", fs, ws);
311311 return (fs == ws);
312312 }
313313
489489 struct deco_render_params *p = scalloc(1, sizeof(struct deco_render_params));
490490
491491 /* find out which colors to use */
492 if (con->urgent)
492 if (con->urgent) {
493493 p->color = &config.client.urgent;
494 else if (con == focused || con_inside_focused(con))
494 } else if (con == focused || con_inside_focused(con)) {
495495 p->color = &config.client.focused;
496 else if (con == TAILQ_FIRST(&(parent->focus_head)))
497 p->color = &config.client.focused_inactive;
498 else
496 } else if (con == TAILQ_FIRST(&(parent->focus_head))) {
497 if (config.client.got_focused_tab_title && !leaf && con_descend_focused(con) == focused) {
498 /* Stacked/tabbed parent of focused container */
499 p->color = &config.client.focused_tab_title;
500 } else {
501 p->color = &config.client.focused_inactive;
502 }
503 } else {
499504 p->color = &config.client.unfocused;
505 }
500506
501507 p->border_style = con_border_style(con);
502508
874880 con_state *state;
875881 Rect rect = con->rect;
876882
877 //DLOG("Pushing changes for node %p / %s\n", con, con->name);
878883 state = state_for_frame(con->frame.id);
879884
880885 if (state->name != NULL) {
987992 win_depth = con->window->depth;
988993
989994 /* Ensure we have valid dimensions for our surface. */
990 // TODO This is probably a bug in the condition above as we should never enter this path
991 // for height == 0. Also, we should probably handle width == 0 the same way.
995 /* TODO: This is probably a bug in the condition above as we should
996 * never enter this path for height == 0. Also, we should probably
997 * handle width == 0 the same way. */
992998 int width = MAX((int32_t)rect.width, 1);
993999 int height = MAX((int32_t)rect.height, 1);
9941000
9951001 xcb_create_pixmap(conn, win_depth, con->frame_buffer.id, con->frame.id, width, height);
9961002 draw_util_surface_init(conn, &(con->frame_buffer), con->frame_buffer.id,
9971003 get_visualtype_by_id(get_visualid_by_depth(win_depth)), width, height);
1004 draw_util_clear_surface(&(con->frame_buffer), (color_t){.red = 0.0, .green = 0.0, .blue = 0.0});
9981005
9991006 /* For the graphics context, we disable GraphicsExposure events.
10001007 * Those will be sent when a CopyArea request cannot be fulfilled
10071014 con->pixmap_recreated = true;
10081015
10091016 /* Don’t render the decoration for windows inside a stack which are
1010 * not visible right now */
1011 // TODO Should this work the same way for L_TABBED?
1017 * not visible right now
1018 * TODO: Should this work the same way for L_TABBED? */
10121019 if (!con->parent ||
10131020 con->parent->layout != L_STACKED ||
10141021 TAILQ_FIRST(&(con->parent->focus_head)) == con)
11191126 Con *current;
11201127 con_state *state;
11211128
1122 //DLOG("Pushing changes (with unmaps) for node %p / %s\n", con, con->name);
11231129 state = state_for_frame(con->frame.id);
11241130
11251131 /* map/unmap if map state changed, also ensure that the child window
11951201 }
11961202
11971203 DLOG("-- PUSHING WINDOW STACK --\n");
1198 //DLOG("Disabling EnterNotify\n");
11991204 /* We need to keep SubstructureRedirect around, otherwise clients can send
12001205 * ConfigureWindow requests and get them applied directly instead of having
12011206 * them become ConfigureRequests that i3 handles. */
12041209 if (state->mapped)
12051210 xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
12061211 }
1207 //DLOG("Done, EnterNotify disabled\n");
12081212 bool order_changed = false;
12091213 bool stacking_changed = false;
12101214
12341238 if (con_has_managed_window(state->con))
12351239 memcpy(walk++, &(state->con->window->id), sizeof(xcb_window_t));
12361240
1237 //DLOG("stack: 0x%08x\n", state->id);
12381241 con_state *prev = CIRCLEQ_PREV(state, state);
12391242 con_state *old_prev = CIRCLEQ_PREV(state, old_state);
12401243 if (prev != old_prev)
12411244 order_changed = true;
12421245 if ((state->initial || order_changed) && prev != CIRCLEQ_END(&state_head)) {
12431246 stacking_changed = true;
1244 //DLOG("Stacking 0x%08x above 0x%08x\n", prev->id, state->id);
12451247 uint32_t mask = 0;
12461248 mask |= XCB_CONFIG_WINDOW_SIBLING;
12471249 mask |= XCB_CONFIG_WINDOW_STACK_MODE;
12941296 warp_to = NULL;
12951297 }
12961298
1297 //DLOG("Re-enabling EnterNotify\n");
12981299 values[0] = FRAME_EVENT_MASK;
12991300 CIRCLEQ_FOREACH_REVERSE (state, &state_head, state) {
13001301 if (state->mapped)
13011302 xcb_change_window_attributes(conn, state->id, XCB_CW_EVENT_MASK, values);
13021303 }
1303 //DLOG("Done, EnterNotify re-enabled\n");
13041304
13051305 x_deco_recurse(con);
13061306
13861386 CIRCLEQ_REMOVE(&old_state_head, state, old_state);
13871387 CIRCLEQ_INSERT_TAIL(&old_state_head, state, old_state);
13881388 }
1389 //CIRCLEQ_FOREACH(state, &old_state_head, old_state) {
1390 // DLOG("old stack: 0x%08x\n", state->id);
1391 //}
13921389
13931390 xcb_flush(conn);
13941391 }
14011398 void x_raise_con(Con *con) {
14021399 con_state *state;
14031400 state = state_for_frame(con->frame.id);
1404 //DLOG("raising in new stack: %p / %s / %s / xid %08x\n", con, con->name, con->window ? con->window->name_json : "", state->id);
14051401
14061402 CIRCLEQ_REMOVE(&state_head, state, state);
14071403 CIRCLEQ_INSERT_HEAD(&state_head, state, state);
432432 bound = true;
433433 /* Let the user know bind() was successful, so that they know the
434434 * error messages can be disregarded. */
435 fprintf(stderr, "Successfuly bound to %s\n", addr.sun_path);
435 fprintf(stderr, "Successfully bound to %s\n", addr.sun_path);
436436 sun_path = sstrdup(addr.sun_path);
437437 break;
438438 }
4141 exit_forcefully
4242 workspace_exists
4343 focused_ws
44 focused_output
4445 get_socket_path
4546 launch_with_config
4647 get_i3_log
663664 (scalar grep { $_ eq $name } @{get_workspace_names()}) > 0;
664665 }
665666
666 =head2 focused_ws
667
668 Returns the name of the currently focused workspace.
669
670 my $ws = focused_ws;
671 is($ws, '1', 'i3 starts on workspace 1');
672
673 =cut
674 sub focused_ws {
667 =head2 focused_output
668
669 Returns the name of the currently focused output.
670
671 is(focused_output, 'fake-0', 'i3 starts on output 0');
672
673 =cut
674 sub _focused_output {
675675 my $i3 = i3(get_socket_path());
676676 my $tree = $i3->get_tree->recv;
677677 my $focused = $tree->{focus}->[0];
678678 my $output = first { $_->{id} == $focused } @{$tree->{nodes}};
679 return $output;
680 }
681
682 sub focused_output {
683 return _focused_output->{name}
684 }
685
686 =head2 focused_ws
687
688 Returns the name of the currently focused workspace.
689
690 my $ws = focused_ws;
691 is($ws, '1', 'i3 starts on workspace 1');
692
693 =cut
694
695 sub focused_ws {
696 my $output = _focused_output;
679697 my $content = first { $_->{type} eq 'con' } @{$output->{nodes}};
680698 my $first = first { $_->{fullscreen_mode} == 1 } @{$content->{nodes}};
681699 return $first->{name}
779797 my ($pid, $socketpath) = @_;
780798 $socketpath ||= get_socket_path();
781799
800 $SIG{CHLD} = undef;
801
782802 my $exited = 0;
783803 eval {
784804 say "Exiting i3 cleanly...";
816836 sub exit_forcefully {
817837 my ($pid, $signal) = @_;
818838 $signal ||= 'TERM';
839
840 $SIG{CHLD} = undef;
819841
820842 # Send the given signal to the i3 instance and wait for up to 10s
821843 # for it to terminate.
940962 return ${^CHILD_ERROR_NATIVE};
941963 }
942964
965 $SIG{CHLD} = sub {
966 # don't change $! and $? outside handler
967 local ($!, $?);
968
969 my $child = waitpid -1, POSIX::WNOHANG;
970 warn "SIGCHLD, waitpid() = $child";
971 if ($child == $i3_pid) {
972 warn "i3 died, exiting!";
973 exit 1;
974 }
975 };
976
943977 # force update of the cached socket path in lib/i3test
944978 # as soon as i3 has started
945979 $cv->cb(sub { get_socket_path(0) });
9711005 # Sync in case not all windows are managed by i3 just yet.
9721006 sync_with_i3;
9731007 cmd '[title=".*"] kill';
1008 # Sync to make sure x_window_kill() calls have taken effect.
1009 sync_with_i3;
9741010 }
9751011
9761012 =head2 events_for($subscribecb, [ $rettype ], [ $eventcbs ])
1313 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
1414 # (unless you are already familiar with Perl)
1515 #
16 # Tests whether we can switch to a non-existant workspace
16 # Tests whether we can switch to a non-existent workspace
1717 # (necessary for further tests)
1818 #
1919 use List::Util qw(first);
266266 like($output->[3], qr|^bindsym Mod1\+f resize grow down 23 px$|, 'resize bottom changed');
267267
268268 #####################################################################
269 # also resizing, but with indention this time
269 # also resizing, but with indentation this time
270270 #####################################################################
271271
272272 like($output->[4], qr|^bindsym Mod1\+f resize grow left 10 px$|, 'resize left changed');
475475 ################################################################################
476476
477477 $config = <<'EOT';
478 client.focused #4c7899 #285577 #ffffff #2e9ef4 #b34d4c
479 client.focused_inactive #333333 #5f676a #ffffff #484e50
480 client.unfocused #333333 #222222 #888888 #292d2e
481 client.urgent #2f343a #900000 #ffffff #900000 #c00000
482 client.placeholder #000000 #0c0c0c #ffffff #000000
478 client.focused #4c7899 #285577 #ffffff #2e9ef4 #b34d4c
479 client.focused_inactive #333333 #5f676a #ffffff #484e50
480 client.focused_tab_title #444444 #555555 #ffffff
481 client.unfocused #333333 #222222 #888888 #292d2e
482 client.urgent #2f343a #900000 #ffffff #900000 #c00000
483 client.placeholder #000000 #0c0c0c #ffffff #000000
483484 EOT
484485
485486 $expected = <<'EOT';
486487 cfg_color(client.focused, #4c7899, #285577, #ffffff, #2e9ef4, #b34d4c)
487488 cfg_color(client.focused_inactive, #333333, #5f676a, #ffffff, #484e50, NULL)
489 cfg_color(client.focused_tab_title, #444444, #555555, #ffffff, NULL, NULL)
488490 cfg_color(client.unfocused, #333333, #222222, #888888, #292d2e, NULL)
489491 cfg_color(client.urgent, #2f343a, #900000, #ffffff, #900000, #c00000)
490492 cfg_color(client.placeholder, #000000, #0c0c0c, #ffffff, #000000, NULL)
550552 exec
551553 client.background
552554 client.focused_inactive
555 client.focused_tab_title
553556 client.focused
554557 client.unfocused
555558 client.urgent
7070 cmd 'mark left';
7171
7272 #
73 # get_marks replys an array of marks, whose order is undefined,
73 # get_marks replies an array of marks, whose order is undefined,
7474 # so we use sort to be able to compare the output
7575 #
7676
1717 # i3 config file (v4)
1818 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
1919
20 # fake-1 under fake-0 to not interfere with left/right wraping
20 # fake-1 under fake-0 to not interfere with left/right wrapping
2121 fake-outputs 1024x768+0+0,1024x768+0+1024
2222 workspace X output fake-1
2323 EOT
5555 my $focus = AnyEvent->condvar;
5656
5757 my @events = events_for(
58 sub { cmd $cmd },
58 sub {
59 cmd $cmd;
60 # Sync to make sure x_window_kill() calls have taken effect.
61 sync_with_i3;
62 },
5963 'window');
6064
6165 is(scalar @events, 1, 'Received 1 event');
6161 font \
6262 -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
6363
64 # Use line contiuation with too many lines (>4096 characters).
64 # Use line continuation with too many lines (>4096 characters).
6565 # This config is invalid. Use it to ensure no buffer overflow.
6666 bindsym Mod1+b \
6767 0001-This is a very very very very very very very very very very very very very very very very very long cmd \
2020 #
2121 # Ticket: #2318
2222 # Bug still in: 4.12-46-g2123888
23 use i3test;
23 use i3test i3_autostart => 0;
24
25 my $pid = launch_with_config('-default');
2426
2527 # We cannot use events_for in this test as we cannot send events after
2628 # issuing the restart/shutdown command.
5860 }
5961 })->recv;
6062
61 cmd 'exit';
63 exit_gracefully($pid);
6264
6365 $e = $cv->recv;
6466
1313 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
1414 # (unless you are already familiar with Perl)
1515 #
16 # Verify that the corrent focus stack order is preserved after various
16 # Verify that the current focus stack order is preserved after various
1717 # operations.
1818 use i3test i3_config => <<EOT;
1919 # i3 config file (v4)
4242 * | C |
4343 * +-------+
4444 *
45 * - Zone A is completly opaque.
45 * - Zone A is completely opaque.
4646 * - Zone B is clickable through (input shape).
47 * - Zone C is completly transparent (bounding shape).
47 * - Zone C is completely transparent (bounding shape).
4848 */
4949 void set_shape(long window_id) {
5050 xcb_rectangle_t bounding_rectangle = { 0, 0, 100, 50 };
2121 # i3 config file (v4)
2222 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
2323
24 # fake-1 under fake-0 to not interfere with left/right wraping
24 # fake-1 under fake-0 to not interfere with left/right wrapping
2525 fake-outputs 1024x768+0+0,1024x768+0+1024
2626 workspace X output fake-1
2727 EOT
3737 cmd 'title_window_icon on';
3838 isnt(window_icon_padding($tmp), -1, 'window_icon_padding no longer -1');
3939
40 cmd 'title_window_icon toggle';
41 is(window_icon_padding($tmp), -1, 'window_icon_padding back to -1');
42
43 cmd 'title_window_icon toggle';
44 isnt(window_icon_padding($tmp), -1, 'window_icon_padding no longer -1 again');
45
46 cmd 'title_window_icon off';
47 is(window_icon_padding($tmp), -1, 'window_icon_padding back to -1');
48
49 cmd 'title_window_icon padding 3px';
50 is(window_icon_padding($tmp), 3, 'window_icon_padding set to 3');
51
52 cmd 'title_window_icon toggle';
53 ok(window_icon_padding($tmp) < 0, 'window_icon_padding toggled off');
54
55 cmd 'title_window_icon toggle';
56 is(window_icon_padding($tmp), 3, 'window_icon_padding toggled back to 3');
57
58 cmd 'title_window_icon toggle 5px';
59 ok(window_icon_padding($tmp) < 0, 'window_icon_padding toggled off');
60
61 cmd 'title_window_icon toggle 5px';
62 is(window_icon_padding($tmp), 5, 'window_icon_padding toggled on to 5px');
63
64 cmd 'title_window_icon toggle 5px';
65 ok(window_icon_padding($tmp) < 0, 'window_icon_padding toggled off');
66
67 cmd 'title_window_icon toggle 4px';
68 is(window_icon_padding($tmp), 4, 'window_icon_padding toggled on to 4px');
69
4070 exit_gracefully($pid);
4171
4272 ################################################################################
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test that commands with more than 10 non-identified words doesn't works
17 # 10 is the magic number chosen for the stack size which is why it's used here
18 # Ticket: #2968
19 # Bug still in: 4.19.2-103-gfc65ca36
20 use i3test;
21
22 ######################################################################
23 # 1) run a long command
24 ######################################################################
25
26 my $i3 = i3(get_socket_path());
27 my $tmp = fresh_workspace;
28
29 my $floatwin = open_floating_window;
30
31
32 my ($absolute_before, $top_before) = $floatwin->rect;
33
34 cmd 'move window container to window container to window container to left';
35
36 sync_with_i3;
37
38 my ($absolute, $top) = $floatwin->rect;
39
40 is($absolute->x, ($absolute_before->x - 10), 'moved 10 px to the left');
41 is($absolute->y, $absolute_before->y, 'y not changed');
42 is($absolute->width, $absolute_before->width, 'width not changed');
43 is($absolute->height, $absolute_before->height, 'height not changed');
44
45 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test dragging containers.
17
18 my ($width, $height) = (1000, 500);
19
20 my $config = <<"EOT";
21 # i3 config file (v4)
22 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
23
24 focus_follows_mouse no
25 floating_modifier Mod1
26
27 # 2 side by side outputs
28 fake-outputs ${width}x${height}+0+0P,${width}x${height}+${width}+0
29
30 bar {
31 output primary
32 }
33 EOT
34 use i3test i3_autostart => 0;
35 use i3test::XTEST;
36 my $pid = launch_with_config($config);
37
38 sub start_drag {
39 my ($pos_x, $pos_y) = @_;
40 die "Drag outside of bounds!" unless $pos_x < $width * 2 && $pos_y < $height;
41
42 $x->root->warp_pointer($pos_x, $pos_y);
43 sync_with_i3;
44
45 xtest_key_press(64); # Alt_L
46 xtest_button_press(1, $pos_x, $pos_y);
47 xtest_sync_with_i3;
48 }
49
50 sub end_drag {
51 my ($pos_x, $pos_y) = @_;
52 die "Drag outside of bounds!" unless $pos_x < $width * 2 && $pos_y < $height;
53
54 $x->root->warp_pointer($pos_x, $pos_y);
55 sync_with_i3;
56
57 xtest_button_release(1, $pos_x, $pos_y);
58 xtest_key_release(64); # Alt_L
59 xtest_sync_with_i3;
60 }
61
62 my ($ws1, $ws2);
63 my ($A, $B, $tmp);
64 my ($A_id, $B_id);
65
66 sub move_subtest {
67 my ($cb, $win) = @_;
68
69 my @events = events_for($cb, 'window');
70 my @move = grep { $_->{change} eq 'move' } @events;
71
72 is(scalar @move, 1, 'Received 1 window::move event');
73 is($move[0]->{container}->{window}, $A->{id}, "window id matches");
74 }
75
76 ###############################################################################
77 # Drag floating container onto an empty workspace.
78 ###############################################################################
79
80 $ws2 = fresh_workspace(output => 1);
81 $ws1 = fresh_workspace(output => 0);
82 $A = open_floating_window(rect => [ 30, 30, 50, 50 ]);
83
84 start_drag(40, 40);
85 end_drag(1050, 50);
86
87 is($x->input_focus, $A->id, 'Floating window moved to the right workspace');
88 is($ws2, focused_ws, 'Empty workspace focused after floating window dragged to it');
89
90 ###############################################################################
91 # Drag tiling container onto an empty workspace.
92 ###############################################################################
93
94 subtest "Draging tiling container onto an empty workspace produces move event", \&move_subtest,
95 sub {
96
97 $ws2 = fresh_workspace(output => 1);
98 $ws1 = fresh_workspace(output => 0);
99 $A = open_window;
100
101 start_drag(50, 50);
102 end_drag(1050, 50);
103
104 is($x->input_focus, $A->id, 'Tiling window moved to the right workspace');
105 is($ws2, focused_ws, 'Empty workspace focused after tiling window dragged to it');
106
107 };
108
109 ###############################################################################
110 # Drag tiling container onto a container that closes before the drag is
111 # complete.
112 ###############################################################################
113
114 $ws1 = fresh_workspace(output => 0);
115 $A = open_window;
116 open_window;
117
118 start_drag(600, 300); # Start dragging the second window.
119
120 # Try to place it on the first window.
121 $x->root->warp_pointer(50, 50);
122 sync_with_i3;
123
124 cmd '[id=' . $A->id . '] kill';
125 sync_with_i3;
126 end_drag(50, 50);
127
128 is(@{get_ws_content($ws1)}, 1, 'One container left in ws1');
129
130 ###############################################################################
131 # Drag tiling container onto a tiling container on an other workspace.
132 ###############################################################################
133
134 subtest "Draging tiling container onto a tiling container on an other workspace produces move event", \&move_subtest,
135 sub {
136
137 $ws2 = fresh_workspace(output => 1);
138 open_window;
139 $B_id = get_focused($ws2);
140 $ws1 = fresh_workspace(output => 0);
141 $A = open_window;
142 $A_id = get_focused($ws1);
143
144 start_drag(50, 50);
145 end_drag(1500, 250); # Center of right output, inner region.
146
147 is($ws2, focused_ws, 'Workspace focused after tiling window dragged to it');
148 $ws2 = get_ws($ws2);
149 is($ws2->{focus}[0], $A_id, 'A focused first, dragged container kept focus');
150 is($ws2->{focus}[1], $B_id, 'B focused second');
151
152 };
153
154 ###############################################################################
155 # Drag tiling container onto a floating container on an other workspace.
156 ###############################################################################
157
158 subtest "Draging tiling container onto a floating container on an other workspace produces move event", \&move_subtest,
159 sub {
160
161 $ws2 = fresh_workspace(output => 1);
162 open_floating_window;
163 $B_id = get_focused($ws2);
164 $ws1 = fresh_workspace(output => 0);
165 $A = open_window;
166 $A_id = get_focused($ws1);
167
168 start_drag(50, 50);
169 end_drag(1500, 250);
170
171 is($ws2, focused_ws, 'Workspace with one floating container focused after tiling window dragged to it');
172 $ws2 = get_ws($ws2);
173 is($ws2->{focus}[0], $A_id, 'A focused first, dragged container kept focus');
174 is($ws2->{floating_nodes}[0]->{nodes}[0]->{id}, $B_id, 'B exists & floating');
175
176 };
177
178 ###############################################################################
179 # Drag tiling container onto a bar.
180 ###############################################################################
181
182 subtest "Draging tiling container onto a bar produces move event", \&move_subtest,
183 sub {
184
185 $ws1 = fresh_workspace(output => 0);
186 open_window;
187 $B_id = get_focused($ws1);
188 $ws2 = fresh_workspace(output => 1);
189 $A = open_window;
190 $A_id = get_focused($ws2);
191
192 start_drag(1500, 250);
193 end_drag(1, 498); # Bar on bottom of left output.
194
195 is($ws1, focused_ws, 'Workspace focused after tiling window dragged to its bar');
196 $ws1 = get_ws($ws1);
197 is($ws1->{focus}[0], $A_id, 'B focused first, dragged container kept focus');
198 is($ws1->{focus}[1], $B_id, 'A focused second');
199
200 };
201
202 ###############################################################################
203 # Drag an unfocused tiling container onto it's self.
204 ###############################################################################
205
206 $ws1 = fresh_workspace(output => 0);
207 open_window;
208 $A_id = get_focused($ws1);
209 open_window;
210 $B_id = get_focused($ws1);
211
212 start_drag(50, 50);
213 end_drag(450, 450);
214
215 $ws1 = get_ws($ws1);
216 is($ws1->{focus}[0], $B_id, 'B focused first, kept focus');
217 is($ws1->{focus}[1], $A_id, 'A focused second, unfocused dragged container didn\'t gain focus');
218
219 ###############################################################################
220 # Drag an unfocused tiling container onto an occupied workspace.
221 ###############################################################################
222
223 subtest "Draging unfocused tiling container onto an occupied workspace produces move event", \&move_subtest,
224 sub {
225
226 $ws1 = fresh_workspace(output => 0);
227 $A = open_window;
228 $A_id = get_focused($ws1);
229 $ws2 = fresh_workspace(output => 1);
230 open_window;
231 $B_id = get_focused($ws2);
232
233 start_drag(50, 50);
234 end_drag(1500, 250); # Center of right output, inner region.
235
236 is($ws2, focused_ws, 'Workspace remained focused after dragging unfocused container');
237 $ws2 = get_ws($ws2);
238 is($ws2->{focus}[0], $B_id, 'B focused first, kept focus');
239 is($ws2->{focus}[1], $A_id, 'A focused second, unfocused container didn\'t steal focus');
240
241 };
242
243 ###############################################################################
244 # Drag fullscreen container onto window in same workspace.
245 ###############################################################################
246
247 $ws1 = fresh_workspace(output => 0);
248 open_window;
249 $A = open_window;
250 cmd 'fullscreen enable';
251
252 start_drag(900, 100); # Second window
253 end_drag(50, 50); # To first window
254
255 is($ws1, focused_ws, 'Workspace remained focused after dragging fullscreen container');
256 is_num_fullscreen($ws1, 1, 'Container still fullscreened');
257 is($x->input_focus, $A->id, 'Fullscreen container still focused');
258
259 ###############################################################################
260 # Drag unfocused fullscreen container onto window in other workspace.
261 ###############################################################################
262
263 subtest "Draging unfocused fullscreen container onto window in other workspace produces move event", \&move_subtest,
264 sub {
265
266 $ws1 = fresh_workspace(output => 0);
267 $A = open_window;
268 cmd 'fullscreen enable';
269 $ws2 = fresh_workspace(output => 1);
270 open_window;
271 open_window;
272
273 start_drag(900, 100);
274 end_drag(1000 + 500 * 0.15 + 10, 200); # left of leftmost window
275
276 is($ws2, focused_ws, 'Workspace still focused after dragging fullscreen container to it');
277 is_num_fullscreen($ws1, 0, 'No fullscreen container in first workspace');
278 is_num_fullscreen($ws2, 1, 'Moved container still fullscreened');
279 is($x->input_focus, $A->id, 'Fullscreen container now focused');
280 $ws2 = get_ws($ws2);
281 is($ws2->{nodes}->[0]->{window}, $A->id, 'Fullscreen container now leftmost window in second workspace');
282
283 };
284
285 ###############################################################################
286 # Drag unfocused fullscreen container onto left outter region of window in
287 # other workspace. The container shouldn't end up in $ws2 because it was
288 # dragged onto the outter region of the leftmost window. We must also check
289 # that the focus remains on the other window.
290 ###############################################################################
291
292 subtest "Draging unfocused fullscreen container onto left outter region of window in other workspace produces move event", \&move_subtest,
293 sub {
294
295 $ws1 = fresh_workspace(output => 0);
296 open_window for (1..3);
297 $A = open_window;
298 $tmp = get_focused($ws1);
299 cmd 'fullscreen enable';
300 $ws2 = fresh_workspace(output => 1);
301 $B = open_window;
302
303 start_drag(990, 100); # rightmost of $ws1
304 end_drag(1004, 100); # outter region of window of $ws2
305
306 is($ws2, focused_ws, 'Workspace still focused after dragging fullscreen container to it');
307 is_num_fullscreen($ws1, 1, 'Fullscreen container still in first workspace');
308 is_num_fullscreen($ws2, 0, 'No fullscreen container in second workspace');
309 is($x->input_focus, $B->id, 'Window of second workspace still has focus');
310 is(get_focused($ws1), $tmp, 'Fullscreen container still focused in first workspace');
311 $ws1 = get_ws($ws1);
312 is($ws1->{nodes}->[3]->{window}, $A->id, 'Fullscreen container still rightmost window in first workspace');
313
314 };
315
316 exit_gracefully($pid);
317
318 ###############################################################################
319
320 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test that i3 does not get stuck in an endless loop between two windows that
17 # set transient_for for each other.
18 # Ticket: #4404
19 # Bug still in: 4.20-69-g43e805a00
20 #
21 use i3test i3_config => <<EOT;
22 # i3 config file (v4)
23 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
24
25 popup_during_fullscreen smart;
26 EOT
27
28 my $fs = open_window;
29 cmd 'fullscreen enable';
30
31 my $w1 = open_window({ dont_map => 1 });
32 my $w2 = open_window({ dont_map => 1 });
33
34 $w1->transient_for($w2);
35 $w2->transient_for($w1);
36 $w1->map;
37 $w2->map;
38
39 does_i3_live;
40
41 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Verifies that bar config blocks get the i3-wide font configured,
17 # regardless of where the font is configured in the config file
18 # (before or after the bar config blocks).
19 # Ticket: #5031
20 # Bug still in: 4.20-105-g4db383e4
21 use i3test i3_config => <<'EOT';
22 # i3 config file (v4)
23
24 bar {
25 # no font directive here, no i3-wide font configured (yet)
26 }
27
28 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
29 EOT
30
31 my $i3 = i3(get_socket_path(0));
32 my $bars = $i3->get_bar_config()->recv;
33
34 my $bar_id = shift @$bars;
35 my $bar_config = $i3->get_bar_config($bar_id)->recv;
36 is($bar_config->{font}, 'fixed', 'font ok');
37
38 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Verifies that any trailing whitespace in strings (including in
17 # “bar { output <output> }” in particular) is stripped.
18 # Ticket: #5064
19 # Bug still in: 4.20-105-g4db383e4
20 use i3test i3_autostart => 0;
21
22 # Test with a single output.
23
24 my $config = <<EOT;
25 # i3 config file (v4)
26 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
27
28 bar {
29 output anything
30 }
31 EOT
32
33 my $pid = launch_with_config($config);
34
35 my $i3 = i3(get_socket_path(0));
36 my $bars = $i3->get_bar_config()->recv;
37 is(@$bars, 1, 'one bar configured');
38 my $bar_id = shift @$bars;
39
40 my $bar_config = $i3->get_bar_config($bar_id)->recv;
41 is_deeply($bar_config->{outputs}, [ 'anything' ], 'outputs do not have trailing whitespace');
42
43 exit_gracefully($pid);
44
45 # Test with multiple outputs for a single bar.
46
47 $config = <<EOT;
48 # i3 config file (v4)
49 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
50
51 bar {
52 output nospace
53 output singlespace
54 }
55 EOT
56
57 $pid = launch_with_config($config);
58
59 $i3 = i3(get_socket_path(0));
60 $bars = $i3->get_bar_config()->recv;
61 is(@$bars, 1, 'one bar configured');
62 $bar_id = shift @$bars;
63
64 $bar_config = $i3->get_bar_config($bar_id)->recv;
65 is_deeply($bar_config->{outputs}, [ 'nospace', 'singlespace' ], 'outputs do not have trailing whitespace');
66
67 exit_gracefully($pid);
68
69
70 done_testing;
2929 ################################################################################
3030 # use 'focus output' and verify that focus gets changed appropriately
3131 ################################################################################
32
33 sub focused_output {
34 my $tree = $i3->get_tree->recv;
35 my $focused = $tree->{focus}->[0];
36 my $output = first { $_->{id} == $focused } @{$tree->{nodes}};
37 return $output->{name};
38 }
3932
4033 sync_with_i3;
4134 $x->root->warp_pointer(0, 0);
148148 # Ensure that focusing right/left works in the expected order.
149149 ############################################################################
150150
151 sub get_focused_output {
152 my $tree = i3(get_socket_path())->get_tree->recv;
153 my ($focused_id) = @{$tree->{focus}};
154 my ($output) = grep { $_->{id} == $focused_id } @{$tree->{nodes}};
155 return $output->{name};
156 }
157
158 is(get_focused_output(), 'fake-0', 'focus on fake-0');
151 is(focused_output, 'fake-0', 'focus on fake-0');
159152
160153 cmd 'focus output right';
161 is(get_focused_output(), 'fake-1', 'focus on fake-1');
154 is(focused_output, 'fake-1', 'focus on fake-1');
162155
163156 cmd 'focus output right';
164 is(get_focused_output(), 'fake-2', 'focus on fake-2');
157 is(focused_output, 'fake-2', 'focus on fake-2');
165158
166159 cmd 'focus output left';
167 is(get_focused_output(), 'fake-1', 'focus on fake-1');
160 is(focused_output, 'fake-1', 'focus on fake-1');
168161
169162 cmd 'focus output left';
170 is(get_focused_output(), 'fake-0', 'focus on fake-0');
163 is(focused_output, 'fake-0', 'focus on fake-0');
171164
172165 cmd 'focus output left';
173 is(get_focused_output(), 'fake-2', 'focus on fake-2 (wrapping)');
166 is(focused_output, 'fake-2', 'focus on fake-2 (wrapping)');
174167
175168 cmd 'focus output right';
176 is(get_focused_output(), 'fake-0', 'focus on fake-0 (wrapping)');
169 is(focused_output, 'fake-0', 'focus on fake-0 (wrapping)');
177170
178171 exit_gracefully($pid);
179172
5454
5555 # Check that the windows are on the correct output
5656 is_deeply(scalar $win_on_first_output->rect, $orig_rect1, "first window spans the first output");
57 is_deeply(scalar $win_on_second_output->rect, $orig_rect2, "second window spans the sencond output");
57 is_deeply(scalar $win_on_second_output->rect, $orig_rect2, "second window spans the second output");
5858
5959 # Check that both windows remained fullscreen
6060 my $tree = i3(get_socket_path())->get_tree->recv;
1313 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
1414 # (unless you are already familiar with Perl)
1515 #
16 # Test using multiple workspaces for 'move workspace to output …'
16 # Test using multiple outputs for 'move workspace to output …'
1717 # Ticket: #4337
1818 use i3test i3_config => <<EOT;
1919 # i3 config file (v4)
3939 }
4040
4141 ###############################################################################
42 # Test moving workspace to same output
43 # See issue #4691
44 ###############################################################################
45 is_ws(1, 0, 'sanity check');
46
47 my $reply = cmd '[con_mark=aa] move workspace to output fake-0';
48 is_ws(1, 0, 'workspace did not move');
49 ok($reply->[0]->{success}, 'reply success');
50
51 ###############################################################################
4252 # Test using "next" special keyword
4353 ###############################################################################
4454
5565 }
5666
5767 ###############################################################################
58 # Same as above but explicitely type all the outputs
68 # Same as above but explicitly type all the outputs
5969 ###############################################################################
6070
6171 is_ws(1, 0, 'sanity check');
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test using multiple output for 'focus output …'
17 # Ticket: #4619
18 use i3test i3_config => <<EOT;
19 # i3 config file (v4)
20 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
21
22 fake-outputs 1024x768+0+0,1024x768+1024+0,1024x768+0+768,1024x768+1024+768
23 EOT
24
25 ###############################################################################
26 # Test using "next" special keyword
27 ###############################################################################
28
29 is(focused_output, "fake-0", 'sanity check');
30
31 for (my $i = 1; $i < 9; $i++) {
32 cmd 'focus output next';
33
34 my $out = $i % 4;
35 is(focused_output, "fake-$out", 'focus output next cycle');
36 }
37
38 ###############################################################################
39 # Same as above but explicitly type all the outputs
40 ###############################################################################
41
42 is(focused_output, "fake-0", 'sanity check');
43
44 for (my $i = 1; $i < 10; $i++) {
45 cmd 'focus output fake-0 fake-1 fake-2 fake-3';
46
47 my $out = $i % 4;
48 is(focused_output, "fake-$out", 'focus output next cycle');
49 }
50
51 ###############################################################################
52 # Use a subset of the outputs plus some non-existing outputs
53 ###############################################################################
54
55 cmd 'focus output fake-1';
56 is(focused_output, "fake-1", 'start from fake-1 which is not included in output list');
57
58 my @order = (0, 3, 2);
59 for (my $i = 0; $i < 10; $i++) {
60 cmd 'focus output doesnotexist fake-0 alsodoesnotexist fake-3 fake-2';
61
62 my $out = $order[$i % 3];
63 is(focused_output, "fake-$out", 'focus output next cycle');
64 }
65
66 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Tests whether our WM registration is done with the correct WM_S0 selection.
4
5 use i3test;
6
7 my $x = X11::XCB::Connection->new;
8 my $reply = $x->get_selection_owner($x->atom(name => 'WM_S0')->id);
9 ok($reply, "registration successful");
10 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test that i3 doesn't crash if the binding command is empty.
17 # Ticket: #5000
18
19 use i3test i3_autostart => 0;
20
21 my $config = <<EOT;
22 # i3 config file (v4)
23 bindsym X
24 EOT
25
26 my $pid = launch_with_config($config);
27 does_i3_live;
28
29 exit_gracefully($pid);
30 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test that explicitly defined default mode doesn't cause segfault.
17 # Ticket: #5006
18 # Bug still in: 4.20-96-gce2665ca
19
20 use i3test i3_autostart => 0;
21
22 my $config = <<EOT;
23 # i3 config file (v4)
24 mode "default" {
25 bindsym X resize
26 }
27 EOT
28
29 my $pid = launch_with_config($config);
30 does_i3_live;
31
32 exit_gracefully($pid);
33 done_testing;
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Test that i3 doesn't crash if the config contains nested variables.
17 # Ticket: #5002
18
19 use i3test i3_autostart => 0;
20
21 #######################################################################
22 # Test calloc crash
23 #######################################################################
24
25 my $config = <<'EOT';
26 # i3 config file (v4)
27 set $long_variable_name_with_short_value 1
28 set $$long_variable_name_with_short_value 2
29 set $$$long_variable_name_with_short_value 3
30 EOT
31
32 my $pid = launch_with_config($config);
33
34 # ==2108678==ERROR: AddressSanitizer: requested allocation size 0xffffffffffffffe1 (0x7e8 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)
35 # #0 0x7feaa9cbf411 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
36 # #1 0x560867c0c13d in scalloc ../libi3/safewrappers.c:29
37 # #2 0x560867b7bd63 in parse_file ../src/config_parser.c:1030
38 # #3 0x560867b6b1b8 in load_configuration ../src/config.c:261
39 # #4 0x560867baf9cf in main ../src/main.c:677
40 # #5 0x7feaa95b52cf (/usr/lib/libc.so.6+0x232cf)
41
42 does_i3_live;
43
44 exit_gracefully($pid);
45
46
47 #######################################################################
48 # Test buffer overflow
49 #######################################################################
50
51 $config = <<'EOT';
52 # i3 config file (v4)
53 set $x 1
54 set $$x 2
55 EOT
56
57 $pid = launch_with_config($config);
58
59 # ==2110007==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6070000014f2 at pc 0x558590f680ba bp 0x7ffced72b760 sp 0x7ffced72b750
60 # WRITE of size 1 at 0x6070000014f2 thread T0
61 # #0 0x558590f680b9 in parse_file ../src/config_parser.c:1051
62 # #1 0x558590f571b8 in load_configuration ../src/config.c:261
63 # #2 0x558590f9b9cf in main ../src/main.c:677
64 # #3 0x7f81c61c82cf (/usr/lib/libc.so.6+0x232cf)
65 # #4 0x7f81c61c8389 in __libc_start_main (/usr/lib/libc.so.6+0x23389)
66 # #5 0x558590f0bd54 in _start ../sysdeps/x86_64/start.S:115
67
68 # 0x6070000014f2 is located 0 bytes to the right of 66-byte region [0x6070000014b0,0x6070000014f2)
69 # allocated by thread T0 here:
70 # #0 0x7f81c68bf411 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
71 # #1 0x558590ff813d in scalloc ../libi3/safewrappers.c:29
72 # #2 0x558590f67d63 in parse_file ../src/config_parser.c:1030
73 # #3 0x558590f571b8 in load_configuration ../src/config.c:261
74 # #4 0x558590f9b9cf in main ../src/main.c:677
75 # #5 0x7f81c61c82cf (/usr/lib/libc.so.6+0x232cf)
76
77 does_i3_live;
78
79 exit_gracefully($pid);
80 done_testing;