Merge branch 'next'
This commit is contained in:
commit
34f6f185bf
11
.clang-format
Normal file
11
.clang-format
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
BasedOnStyle: google
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
IndentWidth: 4
|
||||||
|
PointerBindsToType: false
|
||||||
|
ColumnLimit: 0
|
||||||
|
ForEachMacros: [ TAILQ_FOREACH, TAILQ_FOREACH_REVERSE, SLIST_FOREACH, CIRCLEQ_FOREACH, CIRCLEQ_FOREACH_REVERSE, NODES_FOREACH, NODES_FOREACH_REVERSE ]
|
||||||
|
SpaceBeforeParens: ControlStatements
|
10
DEPENDS
10
DEPENDS
@ -12,7 +12,7 @@
|
|||||||
│ xcb-util │ 0.3.3 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │
|
│ xcb-util │ 0.3.3 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │
|
||||||
│ util-cursor³│ 0.0.99 │ 0.0.99 │ http://xcb.freedesktop.org/dist/ │
|
│ util-cursor³│ 0.0.99 │ 0.0.99 │ http://xcb.freedesktop.org/dist/ │
|
||||||
│ libev │ 4.0 │ 4.11 │ http://libev.schmorp.de/ │
|
│ libev │ 4.0 │ 4.11 │ http://libev.schmorp.de/ │
|
||||||
│ yajl │ 1.0.8 │ 2.0.1 │ http://lloyd.github.com/yajl/ │
|
│ yajl │ 2.0.1 │ 2.0.4 │ http://lloyd.github.com/yajl/ │
|
||||||
│ asciidoc │ 8.3.0 │ 8.6.4 │ http://www.methods.co.nz/asciidoc/ │
|
│ asciidoc │ 8.3.0 │ 8.6.4 │ http://www.methods.co.nz/asciidoc/ │
|
||||||
│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │
|
│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │
|
||||||
│ Pod::Simple²│ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/
|
│ Pod::Simple²│ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/
|
||||||
@ -32,5 +32,9 @@
|
|||||||
i3bar, i3-msg, i3-input, i3-nagbar and i3-config-wizard do not introduce any
|
i3bar, i3-msg, i3-input, i3-nagbar and i3-config-wizard do not introduce any
|
||||||
new dependencies.
|
new dependencies.
|
||||||
|
|
||||||
i3-migrate-config-to-v4 is implemented in Perl, but it has no dependencies
|
i3-migrate-config-to-v4 and i3-dmenu-desktop are implemented in Perl, but have
|
||||||
besides Perl 5.10.
|
no dependencies besides Perl 5.10.
|
||||||
|
|
||||||
|
i3-save-tree is also implemented in Perl and needs AnyEvent::I3 and JSON::XS.
|
||||||
|
While i3-save-tree is not required for running i3 itself, it is strongly
|
||||||
|
recommended to provide it in distribution packages.
|
||||||
|
4
Makefile
4
Makefile
@ -30,8 +30,8 @@ dist: distclean
|
|||||||
[ ! -d i3-${VERSION} ] || rm -rf i3-${VERSION}
|
[ ! -d i3-${VERSION} ] || rm -rf i3-${VERSION}
|
||||||
[ ! -e i3-${VERSION}.tar.bz2 ] || rm i3-${VERSION}.tar.bz2
|
[ ! -e i3-${VERSION}.tar.bz2 ] || rm i3-${VERSION}.tar.bz2
|
||||||
mkdir i3-${VERSION}
|
mkdir i3-${VERSION}
|
||||||
cp i3-migrate-config-to-v4 generate-command-parser.pl i3-sensible-* i3-dmenu-desktop i3.config.keycodes DEPENDS LICENSE PACKAGE-MAINTAINER RELEASE-NOTES-${VERSION} i3.config i3.xsession.desktop i3-with-shmlog.xsession.desktop i3.applications.desktop pseudo-doc.doxygen common.mk Makefile i3-${VERSION}
|
cp i3-migrate-config-to-v4 i3-save-tree generate-command-parser.pl i3-sensible-* i3-dmenu-desktop i3.config.keycodes DEPENDS LICENSE PACKAGE-MAINTAINER RELEASE-NOTES-${VERSION} i3.config i3.xsession.desktop i3-with-shmlog.xsession.desktop i3.applications.desktop pseudo-doc.doxygen common.mk Makefile i3-${VERSION}
|
||||||
cp -r src libi3 i3-msg i3-nagbar i3-config-wizard i3bar i3-dump-log yajl-fallback include man parser-specs testcases i3-${VERSION}
|
cp -r src libi3 i3-msg i3-nagbar i3-config-wizard i3bar i3-dump-log include man parser-specs testcases i3-${VERSION}
|
||||||
# Only copy toplevel documentation (important stuff)
|
# Only copy toplevel documentation (important stuff)
|
||||||
mkdir i3-${VERSION}/docs
|
mkdir i3-${VERSION}/docs
|
||||||
# Pre-generate documentation
|
# Pre-generate documentation
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.2 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the second release of the new major version of i3, v4.2. It is
|
|
||||||
considered stable. All users of i3 are strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
A big change with this release is (again) a new parser for commands. You might
|
|
||||||
get the impression that we like rewriting parsers, but check the commit message
|
|
||||||
of commit a532f5a for rationale on this decision.
|
|
||||||
|
|
||||||
A more visible change to users is the introduction of a scratchpad command:
|
|
||||||
This is useful to have a permanent editor session ready whenever you need it.
|
|
||||||
Or your music player. Or email client? Or $programming-language REPL? Give it a
|
|
||||||
try!
|
|
||||||
|
|
||||||
Also, you are finally able to move workspaces between the different outputs if
|
|
||||||
you are using multiple monitors. You can rename workspaces on the fly and
|
|
||||||
identify named workspaces by their number. So you can rename "1: www" to "1:
|
|
||||||
code" with one simple rename command and all your keybindings will still work.
|
|
||||||
|
|
||||||
A subtle indicator of the split state of containers has been introduced: In
|
|
||||||
case you are in a split container with precisely one window (a situation which
|
|
||||||
you could not recognize by looking at your screen previously), i3 will
|
|
||||||
highlight the bottom/right border of the split container in a lighter blue.
|
|
||||||
This should reduce confusion about whether you are dealing with a split
|
|
||||||
container or not.
|
|
||||||
|
|
||||||
And finally, i3bar now supports a JSON input protocol, so that with a
|
|
||||||
subsequent release of i3status, you will be able to use colors in your bar!
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.2 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• i3-sensible-*: don’t call which without parameters
|
|
||||||
• i3-config-wizard: Mark the currently selected modifier with an arrow
|
|
||||||
• i3bar: kick tray clients after output configuration changed
|
|
||||||
• i3bar: kill child processes when exit()ing (they might be stopped)
|
|
||||||
• i3bar now supports a JSON input format to provide colors and more (later)
|
|
||||||
• Support different modifier keys for showing i3bar in hide mode
|
|
||||||
• bar config: add i3bar_command for non-standard setups
|
|
||||||
• Implement scratchpad functionality
|
|
||||||
• Implement 'focus output left|right|up|down'
|
|
||||||
• Implement 'workspace next_on_output|prev_on_output'
|
|
||||||
• Implement 'move workspace to output <output>'
|
|
||||||
• Implement a new parser for commands
|
|
||||||
• Implement 'workspace number <number>' to switch to named workspaces
|
|
||||||
• Implement 'move [container|window] to workspace number <number>'
|
|
||||||
• Implement 'rename workspace <old_name> to <new_name>'
|
|
||||||
• Re-implement borders in the workspace bar
|
|
||||||
• Draw a separator line after each tab in tabbed mode
|
|
||||||
• Ignore aspect ratio during fullscreen mode (fixes MPlayer subtitles)
|
|
||||||
• Correctly restore focus after in-place restarts
|
|
||||||
• Highlight the right/bottom border of split windows ("indicator")
|
|
||||||
• Install /usr/share/applications/i3.desktop so that you can select i3 as a
|
|
||||||
window manager in GNOME
|
|
||||||
• Don’t migrate unfocused empty workspaces when disabling an output
|
|
||||||
• randr: Skip workspaces which are assigned to a different output when
|
|
||||||
creating a new workspace
|
|
||||||
• Implement an urgency flag criterion
|
|
||||||
• Render only once for all matching assignments
|
|
||||||
• Implement support for user configuration of constraints on floating window
|
|
||||||
dimensions
|
|
||||||
• Extend move command for floating windows
|
|
||||||
• Added option to select primary display on tray_output
|
|
||||||
• Implement resize <grow|shrink> <width|height>, use it in the default config
|
|
||||||
• Replace the old fullscreen container when requesting fullscreen
|
|
||||||
• Prevent changing focus outside a container when scrolling on the
|
|
||||||
decorations
|
|
||||||
• Only resize when the left/right mouse button is used, not when scrolling
|
|
||||||
• docs: replace the refcard with an HTML version
|
|
||||||
• cfgparse: accept force-xinerama as a synonym of force_xinerama
|
|
||||||
• Implement support for 32 bit visuals (necessary for transparency)
|
|
||||||
• X11: only copy the requested region from buffer pixmaps in ExposeEvents
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• Bugfix: Don’t leak IPC file descriptors
|
|
||||||
• Bugfix: fix empty tray icon areas in i3bar
|
|
||||||
• Bugfix: properly handle workspace names with double quotes
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
Aaron Small, ablepharus, aksr, alexander, badboy, B-con, beauby, ben, biiter,
|
|
||||||
binzter, cg, cradle, darkraven, dbp, dcoppa, Don, dothebart, D Thompson,
|
|
||||||
eeemsi, f8l, Fandekasp, fernandotcl, gamo, garga, gregkh, Han, helgikrs,
|
|
||||||
Jeremy O'Brien, jjfoerch, joepd, Jose Pereira, Jure Ziberna, MasterofJOKers,
|
|
||||||
Merovius, mhcerri, migueldvb, moemoe, mseed, mxf, nh2, noxxun, Paul, Pavel
|
|
||||||
Löbl, Peter Bui, Phlogistique, phnom, piroko, rami, SardemFF7, xeen, xpt,
|
|
||||||
zeus
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2012-04-25
|
|
@ -1,186 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.3 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.3. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
One rather visible change is that commands which could not be parsed properly
|
|
||||||
will now spawn i3-nagbar. In case you used "bindsym $mod+x firefox" (and
|
|
||||||
forgot the "exec" keyword) or you made a typo in your config, you will now
|
|
||||||
notice that :).
|
|
||||||
|
|
||||||
|
|
||||||
We also made the orientation (horizontal/vertical) part of the layout
|
|
||||||
mechanism: Before, we got the default layout and you could change
|
|
||||||
orientation. Now, there are two new layouts "splitv" and "splith", which
|
|
||||||
replace the default layout. The "split h" and "split v" commands continue to
|
|
||||||
work as before, they split the current container and you will end up in a
|
|
||||||
split container with layout splith (after "split h") or splitv (after
|
|
||||||
"split v").
|
|
||||||
|
|
||||||
To change a splith container into a splitv container, use either "layout
|
|
||||||
splitv" or "layout toggle split". The latter command is used in the
|
|
||||||
default config as mod+e (formerly "layout default"). In case you have
|
|
||||||
"layout default" in your config file, it is recommended to just replace
|
|
||||||
it by "layout toggle split", which will work as "layout default" did
|
|
||||||
before when pressing it once, but toggle between horizontal/vertical
|
|
||||||
when pressing it repeatedly.
|
|
||||||
|
|
||||||
The rationale behind this change is that it’s cleaner to have all
|
|
||||||
parameters that influence how windows are rendered in the layout itself
|
|
||||||
rather than having one special layout in combination with an additional
|
|
||||||
orientation. This enables us to change existing split containers in all
|
|
||||||
cases without breaking existing features (see ticket #464). Also, users
|
|
||||||
should feel more confident about whether they are actually splitting or
|
|
||||||
just changing an existing split container now.
|
|
||||||
|
|
||||||
As a nice side-effect, this commit brings back the "layout toggle"
|
|
||||||
feature we once had in i3 v3 (see the userguide).
|
|
||||||
|
|
||||||
|
|
||||||
Another very important change is that we now support pango for rendering text.
|
|
||||||
The default is still to use misc-fixed (X core fonts), but you can use a font
|
|
||||||
specification starting with "xft:" now, such as "xft:DejaVu Sans Mono 10" and
|
|
||||||
i3 will use pango. The sole motivation for this is NOT to have fancier window
|
|
||||||
decorations, but to support fonts which have more glyphs (think Japanese for
|
|
||||||
example) and to support right-to-left rendering (open http://www.ftpal.net/
|
|
||||||
for an example). Supporting users from all over the planet is important, and
|
|
||||||
as such I would strongly advise distribution packagers to leave pango support
|
|
||||||
enabled. In case you are working on a very low-spec embedded device, it is
|
|
||||||
easy enough to disable pango support, see common.mk.
|
|
||||||
|
|
||||||
|
|
||||||
Also, the 'layout' command now always works on the parent split container. This
|
|
||||||
allows you to do things like this:
|
|
||||||
|
|
||||||
for_window [class="XTerm"] layout tabbed
|
|
||||||
|
|
||||||
When you now open XTerm on an empty workspace, the whole workspace will be
|
|
||||||
set to tabbed. In case you want to open XTerm in its own tabbed split
|
|
||||||
container, you need to split before:
|
|
||||||
|
|
||||||
for_window [class="XTerm"] split v, layout tabbed
|
|
||||||
|
|
||||||
|
|
||||||
Furthermore, we decided to entirely ignore resize increment size hints for
|
|
||||||
tiling windows. These are set by terminal emulators (such as urxvt,
|
|
||||||
gnome-terminal, …) and specify that the window may only be resized in
|
|
||||||
multiples of the specified size. All terminal emulators cope with the window
|
|
||||||
manager ignoring these hints and by doing so, they can decide what to do with
|
|
||||||
the lost space (that is, pseudo-transparency now works without black bars in
|
|
||||||
urxvt).
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.3 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• docs: there now is documentation about lib::i3test and lib::i3test::Test,
|
|
||||||
the main Perl modules used by our testsuite.
|
|
||||||
• docs/refcard: update for v4
|
|
||||||
• docs/userguide: clarify the default for focus_follows_mouse and new_window
|
|
||||||
• docs/userguide: add section about implicit containers
|
|
||||||
• docs/userguide: give 'move <container|workspace> to output' its own section
|
|
||||||
• docs/ipc: document the 'window' field in the GET_TREE reply
|
|
||||||
• docs/ipc: update links to ipc libraries
|
|
||||||
• docs/ipc: make the reply sections consistent
|
|
||||||
• docs/i3bar-protocol: add example (illustration-only!) shell script
|
|
||||||
• man/i3bar.man: reference i3bar-protocol
|
|
||||||
• IPC: Commands now lead to proper error messages in general. If we forgot
|
|
||||||
about a specific one, please open a ticket.
|
|
||||||
• IPC: implement GET_VERSION to find out the i3 version
|
|
||||||
• i3-dump-log now comes with a massively more helpful error message that
|
|
||||||
should cover all the use cases.
|
|
||||||
• 'workspace number <number>' now opens a new workspace
|
|
||||||
• 'workspace number <number>' now works with the back_and_forth option
|
|
||||||
• Allow focus with target (criteria) when in fullscreen mode in some cases
|
|
||||||
• Allow focus child/parent when in fullscreen mode
|
|
||||||
• Restrict directional focus when in fullscreen mode
|
|
||||||
• Prevent moving out of fullscreen containers
|
|
||||||
• Add 'move to workspace current' (useful when used with criteria)
|
|
||||||
• replace loglevels by a global debug logging
|
|
||||||
• make: new makefile layout
|
|
||||||
• make: canonicalize path when compiling. This leads to sth like
|
|
||||||
../i3-4.2/src/main.c in backtraces, clearly identifying i3 code.
|
|
||||||
• automatically hide i3bar when it’s unneeded (after urgency hints)
|
|
||||||
• i3-config-wizard: use the level 0 keysym whenever it’s unambiguous
|
|
||||||
• i3-nagbar: use custom scripts to work around different terminal emulators
|
|
||||||
using different ways of interpreting the arguments to -e
|
|
||||||
• i3-sensible-terminal: add xfce4-terminal
|
|
||||||
• default config: require confirmation when exiting i3
|
|
||||||
• Display i3-nagbar when a command leads to an error.
|
|
||||||
• testcases: complete-run now supports --xtrace
|
|
||||||
• testcases: handle EAGAIN (fixes hangs)
|
|
||||||
• testcases: handle test bailouts
|
|
||||||
• Introduce splith/splitv layouts, remove orientation
|
|
||||||
• Implement hide_edge_borders option
|
|
||||||
• Support _NET_ACTIVE_WINDOW ClientMessages
|
|
||||||
• Set I3_PID atom on the X11 root window
|
|
||||||
• Implement i3 --moreversion, handy for figuring out whether you run the
|
|
||||||
latest binary which is installed.
|
|
||||||
• i3bar: be less strict about the {"version":1} JSON header
|
|
||||||
• shm-logging: implement i3-dump-log -f (follow)
|
|
||||||
• Implement pango support
|
|
||||||
• 'move workspace number n' will now create the workspace if it doesn’t exist
|
|
||||||
• Accept slashes in RandR output names
|
|
||||||
• Keep startup-notification sequences around for 30s after completion
|
|
||||||
• Introduce bindsym --release, which will trigger the binding not on the
|
|
||||||
KeyPress event, but on the KeyRelease event (useful for import(1) or
|
|
||||||
xdotool(1)).
|
|
||||||
• The signalhandler does not offer you to exit i3 anymore. Instead, there is
|
|
||||||
'b' for writing a backtrace to a file in /tmp (if gdb is installed)
|
|
||||||
• Remove support for resize increment hints for tiling windows
|
|
||||||
• Exit fullscreen mode when 'scratchpad show' is executed while in fullscreen
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• Fix floating precision bug when floating windows are moved between outputs.
|
|
||||||
• i3bar won’t crash when full_text is missing or null in the JSON input
|
|
||||||
• When having "workspace number 1" in your config, there will no longer be a
|
|
||||||
stray workspace "number 1".
|
|
||||||
• i3.config.keycodes used bindsym instead of bindcode for the arrow key
|
|
||||||
resizing bindings by mistake
|
|
||||||
• Fix 'move to workspace' when used with criteria
|
|
||||||
• Handle clicks to the very left edge of i3bar
|
|
||||||
• When using i3 -C, don’t send remaining arguments as an IPC command
|
|
||||||
• Fix reload crashes in rare cases
|
|
||||||
• i3bar: inform all clients of new tray selection owner (fixes tray problems
|
|
||||||
with X-Chat and possibly others)
|
|
||||||
• resizing: traverse containers up properly (fixes non-working resizing when
|
|
||||||
having a h-split within a h-split for example)
|
|
||||||
• Fix floating coordinates when moving assigned workspaces
|
|
||||||
• Properly fix floating coordinates when disabling outputs
|
|
||||||
• floating_fix_coordinates: properly deal with negative positions
|
|
||||||
• floating windows: add deco_height only when in normal border mode (fixes
|
|
||||||
initial floating window position/size when using a different default border
|
|
||||||
setting).
|
|
||||||
• Fix moving scratchpad window
|
|
||||||
• Cleanup zero-byte logfile on immediate exit (they are created by i3
|
|
||||||
--get-socketpath for example).
|
|
||||||
• Fix resizing floating windows by height
|
|
||||||
• Fix back_and_forth in 'workspace number' for named workspaces
|
|
||||||
• Grab server and process pending events before managing existing windows
|
|
||||||
(fixes problems with GIMP windows not being managed after an in-place
|
|
||||||
restart)
|
|
||||||
• Don’t allow ConfigureRequests while in fullscreen (fixes a compatibility
|
|
||||||
issue with gnome-terminal and xfce’s terminal)
|
|
||||||
• Fix flickering with 1pixel border tabbed layouts
|
|
||||||
• Use _exit() instead of exit() when i3 utility programs cannot be executed
|
|
||||||
• Don’t focus the wrong workspace when moving to scratchpad
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
aksr, Axel Wagner, darkraven, David Coppa, eeemsi, Felicitus, Fernando Tarlá
|
|
||||||
Cardoso Lemos, Iakov Davydov, jh, Joel Stemmer, Julius Plenz, loblik, Marcel
|
|
||||||
Hellwig, Marcus, mloskot, Moritz Bandemer, oblique, Ondrej Grover, Pavel
|
|
||||||
Löbl, Philipp Middendorf, prg, Quentin Glidic, Sebastian Ullrich, Simon
|
|
||||||
Elsbrock, somelauw, stfn, tucos, TunnelWicht, Valentin Haenel
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2012-09-19
|
|
@ -1,107 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.4 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.4. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
An important under-the-hood change is that we now use the same parser
|
|
||||||
infrastructure for the configuration file as we do for the commands. This
|
|
||||||
makes maintenance and contributions easier and lets us finally escape the
|
|
||||||
insanity that is bison/flex.
|
|
||||||
|
|
||||||
In case there is a bug and your existing config does not work as expected
|
|
||||||
anymore, try using the --force-old-config-parser-v4.4-only flag when starting
|
|
||||||
i3 and please report a bug. This option will only be present in v4.4, so if
|
|
||||||
you don’t report a bug, you are willingly breaking your own config file.
|
|
||||||
|
|
||||||
Apart from that, there have been several little fixes and additions which make
|
|
||||||
i3 pay more attention to detail, particularly in the floating window area of
|
|
||||||
the code. See the changes/bugfixes list for more information.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.4 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• add i3-dmenu-desktop, a dmenu wrapper which parses application .desktop
|
|
||||||
files and executes them.
|
|
||||||
• also use a custom parser for the config file
|
|
||||||
• i3.xsession.desktop is now standards-compliant
|
|
||||||
• ipc: you can now subscribe to an event called 'mode' (for binding modes)
|
|
||||||
• implement "move container to workspace back_and_forth"
|
|
||||||
• implement delayed urgency hint reset
|
|
||||||
• make "move workspace number" accept a default workspace name after the
|
|
||||||
number
|
|
||||||
• i3bar: allow child to specify start/stop signals to use in hide mode
|
|
||||||
• i3bar: add "urgent" to protocol, it unhides i3bar when in hide mode
|
|
||||||
• make parent of urgent containers also urgent
|
|
||||||
• add descriptive title to split containers (no more "another container")
|
|
||||||
• click to focus: clicking the root window focuses the relevant workspace
|
|
||||||
• display appropriate cursors when resizing or moving floating windows
|
|
||||||
• implement variable border widths for pixel/normal
|
|
||||||
• Implement moving workspaces as if they’re regular containers
|
|
||||||
• Maintain relative positioning when moving floating windows between outputs
|
|
||||||
• Focus the relevant workspace when clicking any container
|
|
||||||
• docs/ipc: remove unnecessary newline
|
|
||||||
• docs/ipc: add a warning to use an existing library
|
|
||||||
• shmlog: remove O_TRUNC flag for shm_open, we truncate on our own
|
|
||||||
• un-fullscreen as needed when moving fullscreen containers
|
|
||||||
• improve startup sequence termination conditions
|
|
||||||
• allow floating cons to be reached using 'focus parent'
|
|
||||||
• grab keys with all permutations of lock and numlock
|
|
||||||
• allow workspace contents to be moved if there are only floating children
|
|
||||||
• allow 'focus <direction>' to move out of non-global fullscreen containers
|
|
||||||
• exit with a proper error message when there are no outputs available
|
|
||||||
• skip floating cons in focus <child|parent> and stop them from being split
|
|
||||||
• focus windows when middle-clicking
|
|
||||||
• skip floating windows in the focus stack when moving through the tree
|
|
||||||
• docs/userguide: use $mod consistently
|
|
||||||
• keycode default config: s/bindcode/bindsym/
|
|
||||||
• implement smart popup_during_fullscreen mode
|
|
||||||
• docs/testsuite: add "installing the dependencies" section
|
|
||||||
• introduce new command to rename focused workspace
|
|
||||||
• libi3: use "pango:" prefix instead of "xft:" to avoid confusion
|
|
||||||
• ipc: add "current" and "old" containers to workspace events
|
|
||||||
• i3bar: add current binding mode indicator
|
|
||||||
• resizing floating windows now obeys the minimum/maximum size
|
|
||||||
• docs/userguide: document new_float option
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• Bugfix: get_output_next() now works with non-aligned RandR setups
|
|
||||||
• Bugfix: close empty workspaces after cross-output move
|
|
||||||
• Bugfix: fix bottom line of tabbed decoration not continuous
|
|
||||||
• Bugfix: use correct coordinates for windows which are opened on a newly
|
|
||||||
created workspace due to assignments
|
|
||||||
• Bugfix: properly react to windows being unmapped before we can reparent
|
|
||||||
• Bugfix: send non-floating window with floating parent to scratchpad
|
|
||||||
• docs/userguide: document how to "un-scratchpad" a window
|
|
||||||
• Bugfix: don’t crash when dragged floating window closes
|
|
||||||
• Bugfix: draw h-split indicator at the correct position
|
|
||||||
• make the resize command honor criteria
|
|
||||||
• Bugfix: with one ws per output, don’t crash on cross-output moves
|
|
||||||
• Bugfix: correctly move floating windows to invisible workspaces
|
|
||||||
cross-output
|
|
||||||
• Bugfix: set workspace_layout in create_workspace_on_output
|
|
||||||
• fix fullscreen focus bug and corresponding test flaw
|
|
||||||
• i3bar: bugfix: don’t send workspace command when at beginning/end of workspace
|
|
||||||
• Bugfix: force rendering when the parent’s orientation changed
|
|
||||||
• Bugfix: fix workspace back_and_forth after displaying a scratchpad window
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
Adrien Schildknecht, aksr, bitonic, chrysn, Conley Moorhous, darkraven, Deiz,
|
|
||||||
Emil Mikulic, Feh, flo, Francesco Mazzoli, hax404, joepd, Kacper Kowalik,
|
|
||||||
Markus, meaneye, Merovius, Michael Walle, moju, Moritz, noxxun, Oliver
|
|
||||||
Kiddle, Pauli Ervi, Pavel Löbl, Piotr, pkordy, Quentin Glidic, Sascha Kruse,
|
|
||||||
Sebastian Ullrich, Simon Elsbrock, slowpoke, strcat, Tblue, Tim, whitequark,
|
|
||||||
xeen, Yaroslav Molochko
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2012-12-12
|
|
@ -1,103 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.5 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.5. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
Most of the changes are cleanups and bugfixes. Due to cleanups, i3 no longer
|
|
||||||
depends on flex/bison at all. Furthermore, libev ≥ 4 is now a hard dependency
|
|
||||||
(libev < 4 is not supported anymore).
|
|
||||||
|
|
||||||
One important change to note is that moving windows to a different output will
|
|
||||||
no longer move focus to that output. If you want to have the old behavior,
|
|
||||||
modify the keybindings for moving in your configfile like this:
|
|
||||||
|
|
||||||
bindsym $mod+Shift+1 move workspace 1; workspace 1
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.5 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• docs/hacking-howto: refer people to cr.i3wm.org
|
|
||||||
• docs/ipc: Adds Go IPC lib to the docs.
|
|
||||||
• docs/userguide: remove obsolete sentence about client.background
|
|
||||||
• docs/userguide: be explicit about assignment processing order
|
|
||||||
• docs/userguide: be more clear about the resize command arguments
|
|
||||||
• docs/userguide: fix typo: s/11x/11px/
|
|
||||||
• i3-dmenu-desktop: don’t add “geany” if “Geany” is already present
|
|
||||||
• i3-dmenu-desktop: strip newlines from dmenu ≥ 4.4
|
|
||||||
• i3-dmenu-desktop: skip files with broken utf8 but warn about it
|
|
||||||
• i3-dmenu-desktop: skip broken files (no/empty Exec=) but warn about them
|
|
||||||
• i3-dmenu-desktop: List filenames of .desktop files
|
|
||||||
• i3-dmenu-desktop: remove %i from commandline
|
|
||||||
• i3-nagbar: Work around terminals not supporting -e with quoted arguments
|
|
||||||
• i3-nagbar: use the same font as configured for i3
|
|
||||||
• i3bar: set _NET_SYSTEM_TRAY_COLORS for symbolic icons (gtk3+)
|
|
||||||
• i3bar: don’t use X11 borders to avoid overlapping in hide mode
|
|
||||||
• i3bar: separator color via config; separator width and on/off via ipc
|
|
||||||
• i3bar: Allow min_width of a block in i3bar to be a string
|
|
||||||
• i3-msg: parse command replies and display errors nicely if there were
|
|
||||||
errors
|
|
||||||
• Draw 1px tab separators left/right instead of 2px on the right only
|
|
||||||
• Render tree before destroying X11 containers upon unmap
|
|
||||||
• scratchpad show: move visible scratchpad window from another workspace to
|
|
||||||
focused workspace instead of doing nothing
|
|
||||||
• ignore MotionNotify events generated while warping the pointer
|
|
||||||
• Allow X11 servers which do not support the XKB extension.
|
|
||||||
• remove the urgency indicator when a window is closed
|
|
||||||
• wrap when moving containers to outputs with direction
|
|
||||||
• scratchpad_show: focus unfocused scratchpad window
|
|
||||||
• Split workspace instead of changing orientation
|
|
||||||
• scratchpad: always auto center on 'scratchpad show' if window hasn't been
|
|
||||||
repositioned by the user
|
|
||||||
• Add a new IPC event for changes on windows.
|
|
||||||
• config: accept “smart” as popup_during_fullscreen parameter
|
|
||||||
• Add support for _NET_WM_STATE_DEMANDS_ATTENTION.
|
|
||||||
• Obey WM_SIZE_HINTS's resize increments in floating mode
|
|
||||||
• Do not move focus if a container is moved across outputs
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• Ignore ConfigureRequests for scratchpad windows
|
|
||||||
• Correctly parse `move ... workspace *_on_output`
|
|
||||||
• i3bar: Set separator color properly when drawing
|
|
||||||
• Properly parse commands like “move workspace torrent”
|
|
||||||
• Handle nested transient popups properly
|
|
||||||
• Fix decoration rect size for windows without border
|
|
||||||
• parse outputs as "word", not "string", to ignore trailing whitespace
|
|
||||||
• fix crash when disabling output without any windows
|
|
||||||
• scratchpad: fix crash when moving last window of an invisible workspace
|
|
||||||
• fix coordinates of scratchpad windows on output changes
|
|
||||||
• call scratchpad_show() when focusing scratchpad windows via criteria
|
|
||||||
• fix continuous resize bug in floating mode, e.g. with xbmc
|
|
||||||
• fix “overlapping” --release key bindings
|
|
||||||
• fix IPC messages writes with low buffer sizes
|
|
||||||
• unregister as window manager before restarting (fixes a race condition)
|
|
||||||
• Fix bind[code|sym] --release
|
|
||||||
• remove superfluous #include <xcb/xcb_atom.h>
|
|
||||||
• Makefile: Repect AR environment variable
|
|
||||||
• i3-input: restore input focus on exit()
|
|
||||||
• Also draw right tab border for split containers
|
|
||||||
• Fix scrolling on a tabbed titlebar which contains split cons
|
|
||||||
• Correctly close floating windows
|
|
||||||
• handle MapRequests sent between i3 registering as a wm and handling events
|
|
||||||
• i3bar: fake DestroyNotify and send MANAGER ClientMessages to fix tray restarts
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
Adrien Schildknecht, alex, András Mohari, Artem Shinkarov, badboy, bafain,
|
|
||||||
cradle, dcoppa, Donald, dRbiG, eeemsi, else, emias, f8l, Francesco Mazzoli,
|
|
||||||
jasper, joepd, Kacper Kowalik, Kai, knopwob, Marcos, Marius Muja, Mats,
|
|
||||||
MeanEYE, Merovius, oblique, paolo, phlux, Piotr S. Staszewski, pnutzh4x0r,
|
|
||||||
rasi, saurabhgeek92, Sebastian Rachuj, Sebastian Ullrich, slowpoke, Steven
|
|
||||||
Allen, supplantr, Tai-Lin Chu, Tucos, Vivien Didelot, xeen
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2013-03-12
|
|
@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.5.1 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.5.1, a bugfix release. This version is considered stable. All
|
|
||||||
users of i3 are strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
This release fixes an i3 lockup when dragging floating windows from one monitor
|
|
||||||
to another.
|
|
||||||
|
|
||||||
Furthermore, in the release process for v4.5, there was a human error leading
|
|
||||||
to i3 thinking that v4.5 is a debug version, therefore allocating 25 MB of
|
|
||||||
shared memory logging ringbuffer by default.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.5.1 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• Bugfix: Don’t warp the pointer when dragging floating windows
|
|
||||||
• i3-dmenu-desktop: improve error message when dmenu cannot be found
|
|
||||||
• Add YAJL_CFLAGS to i3-msg.mk
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2013-03-18
|
|
@ -1,99 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.6 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.6. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
The main improvement of this release is increased compatibility. We made a few
|
|
||||||
tiny code changes and hope that Mathematica and Java applications will work
|
|
||||||
better with i3 now. i3-nagbar should work with more terminal emulators than
|
|
||||||
before.
|
|
||||||
|
|
||||||
For debugging, the shmlog and debuglog commands can be sent via IPC to enable
|
|
||||||
shared memory logging while i3 is running. For the large number of users using
|
|
||||||
a release version (i.e. a version without shared memory logging by default),
|
|
||||||
this will make debugging their issues much simpler.
|
|
||||||
|
|
||||||
i3bar now supports click events and can be hidden/shown via an i3 IPC command.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.6 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• docs/userguide: mention forgotten layout splitv/splith
|
|
||||||
• docs/multi-monitor: nVidia ≥ 302.17 works just fine
|
|
||||||
• docs/wsbar: update (we have i3bar now, i3-wsbar is just an example)
|
|
||||||
• docs/testsuite: Document fixes and workarounds for test failures
|
|
||||||
• man/i3-msg.man: updated man page to include all options
|
|
||||||
• lib/i3test: clarify how to identify open_window() windows in i3 commands
|
|
||||||
• Use a saner sanity check for floating_reposition
|
|
||||||
• tabbed: floor(), put extra pixels into the last tab
|
|
||||||
• raise fullscreen windows on top of all other X11 windows
|
|
||||||
• Draw indicator border only for split layouts
|
|
||||||
• re-shuffle struct members to save a bit of memory
|
|
||||||
• Add 'NoDisplay=true' to i3.application.desktop
|
|
||||||
• Store aspect_ratio instead of weird proportional_{width,height}
|
|
||||||
• Implement shmlog command
|
|
||||||
• Implement debuglog command
|
|
||||||
• Implement unmark command
|
|
||||||
• actively delete _NET_WORKAREA on startup
|
|
||||||
• Handle the _NET_REQUEST_FRAME_EXTENTS ClientMessage (java compat)
|
|
||||||
• i3bar: add click events
|
|
||||||
• i3bar: fix -b parameter, fix usage description
|
|
||||||
• i3bar: restore compatibility with libyajl version 1
|
|
||||||
• i3bar: unhide hidden i3bar when mode is active
|
|
||||||
• i3bar: fix font display height in i3bar
|
|
||||||
• i3bar: introduced i3 command for changing the hidden state and mode
|
|
||||||
• i3bar: fix wrong placement of i3bar when connecting/disconnecting outputs
|
|
||||||
• i3bar: draw workspace buttons at x=0 instead of x=1
|
|
||||||
• i3-nagbar: take our terminal execution kludge to the next level
|
|
||||||
• i3-nagbar: Bugfix: -m requires an argument (crashes if none specified)
|
|
||||||
• i3-dmenu-desktop: run commands when they don’t match a .desktop file
|
|
||||||
(e.g. enter “i3 layout stacking”)
|
|
||||||
• i3-dmenu-desktop: honor Path= key
|
|
||||||
• contrib/dump-asy.pl: Fix $ and & in window titles
|
|
||||||
• contrib/dump-asy.pl: Display nicer double-quotes
|
|
||||||
• contrib/gtk-tree-watch.pl: Remove bogus default socket path
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• Bugfix: ipc: use correct workspace in workspace change event
|
|
||||||
• Bugfix: fix floating window size with hide_edge_borders
|
|
||||||
• Bugfix: Fix parsing of comments in the config file
|
|
||||||
• Bugfix: Fix error messages for the debug log
|
|
||||||
• Bugfix: shm_unlink the correct file when handling errors
|
|
||||||
• Bugfix: Fix shm logging on FreeBSD
|
|
||||||
• Bugfix: Fix restarting with 32 bit depth windows
|
|
||||||
• Bugfix: Fix scratchpad_show on non-scratchpad windows
|
|
||||||
• Bugfix: i3bar: mark IPC fd CLOEXEC
|
|
||||||
• Bugfix: fix crash when not having tray_output configured
|
|
||||||
• Bugfix: make sure that resize will take place even if pixel is smaller
|
|
||||||
than size increments.
|
|
||||||
• Bugfix: render_con: fix height rounding in aspect ratio computation
|
|
||||||
• Bugfix: fix problem when moving fullscreen window to scratchpad
|
|
||||||
• Bugfix: Unmap windows before reparenting them to the root window
|
|
||||||
(fixes Mathematica)
|
|
||||||
• Bugfix: update parent urgency hint if a child is removed.
|
|
||||||
• Bugfix: fix bus error on OpenBSD/sparc64
|
|
||||||
• Bugfix: fix focus handling in 'floating disable' on non-visible windows
|
|
||||||
• Bugfix: ignore spaces in front of default workspace name
|
|
||||||
• Bugfix: call i3-nagbar correctly for configfiles without the font directive
|
|
||||||
• Bugfix: resize and center a scratchpad even when a criteria is used.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
Alexander, Alexander Berntsen, Arun Persaud, badboy, Baptiste Daroussin,
|
|
||||||
Clément Bœsch, Diego Ongaro, Eelis van der Weegen, Eika Enge, enkore, Eric S.
|
|
||||||
Raymond, Franck Michea, haptix, HedgeMage, koebi, Layus, Mayhem, Merovius,
|
|
||||||
necoro, oblique, Philippe Virouleau, phillip, psychon, Simon Elsbrock, Simon
|
|
||||||
Wesp, Thomas Adam, tobiasu, vandannen, xeen, Yuxuan Shui
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2013-08-07
|
|
@ -1,82 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.7 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.7. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
This release features a number of documentation improvements, better error
|
|
||||||
messages in various places, better tray compatibility in i3bar, and a number of
|
|
||||||
bugfixes.
|
|
||||||
|
|
||||||
Relevant from a packaging point of view is that we have switched to the new
|
|
||||||
xcb-util-cursor library to get rid of libXcursor. The last remaining big piece
|
|
||||||
of Xlib code now is XKB, which we may be able to tackle in upcoming releases
|
|
||||||
thanks to the just released libxcb 1.10.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.7 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• docs/userguide: clarify variable parsing
|
|
||||||
• docs/userguide: clarify urgent_workspace
|
|
||||||
• docs/userguide: add proper quoting for rename sample command
|
|
||||||
• docs/userguide: clarify multiple criteria
|
|
||||||
• docs/userguide: userguide: explain the difference between comma and semicolon for command chaining
|
|
||||||
• docs/hacking-howto: update to reflect parser changes
|
|
||||||
• man/i3-dump-log: document -f
|
|
||||||
• switch from libXcursor to xcb-util-cursor
|
|
||||||
• Respect workspace numbers when looking for a free workspace name
|
|
||||||
• Revert "raise fullscreen windows on top of all other X11 windows"
|
|
||||||
• i3bar: Create pixmaps using the real bar height, rather than screen height
|
|
||||||
• Add scratchpad bindings to the default config
|
|
||||||
• Close all children when closing a workspace
|
|
||||||
• i3bar: Add new bar.binding_mode_indicator configuration
|
|
||||||
• Improve error message when $XDG_RUNTIME_DIR is not writable
|
|
||||||
• libi3/font: Draw the text at the expected place
|
|
||||||
• libi3/font: Set DPI for the pango context
|
|
||||||
• Add ability to escape out of a mouse-resize operation
|
|
||||||
• Do not resize/reposition floating containers when moving them to scratchpad
|
|
||||||
• i3-nagbar: Set button inner-width to the width of the label
|
|
||||||
• Assigned windows open urgent when not visible
|
|
||||||
• i3bar: Only configure tray on own outputs
|
|
||||||
• Command 'move <direction>' moves across outputs
|
|
||||||
• i3bar: Handle DestroyNotify events
|
|
||||||
• i3bar: Realign tray clients on map/unmap notify
|
|
||||||
• i3bar: Group child processes for signalling
|
|
||||||
• i3bar: Print error message when status_command fails
|
|
||||||
• Remove references to PATH_MAX macro for GNU/Hurd
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• update root geometry on output changes for “fullscreen global”
|
|
||||||
• don’t flatten tabbed/stacked containers
|
|
||||||
• Fix handling of new windows with WM_STATE_FULLSCREEN
|
|
||||||
• correctly recognize assigned windows as urgent
|
|
||||||
• Fix keyboard and mouse resize in nested containers
|
|
||||||
• Reply to _NET_REQUEST_FRAME_EXTENTS correctly
|
|
||||||
• Fix command parser: resizing tiling windows
|
|
||||||
• Fix output retrieval for floating cons
|
|
||||||
• Use _PATH_BSHELL to ensure using a bourne shell
|
|
||||||
• Instead of crashing, return DRAG_ABORT on UnmapNotify from drag_pointer
|
|
||||||
• Remove-child callback skips output content cons
|
|
||||||
• ignore _NET_ACTIVE_WINDOW for scratchpad windows
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
Alexander Neumann, badboy, Baptiste Daroussin, Bas Pape, Deiz, Franck Michea,
|
|
||||||
Jean-Philippe Ouellet, jj, jookia, kaersten, Lancelot SIX, Leo Gaspard,
|
|
||||||
mistnim, Peter Maatman, Quentin Glidic, Sebastian Ullrich, Slava, syl20bnr,
|
|
||||||
Tony Crisci, Trung Ngo, Vivien Didelot, Xarthisius
|
|
||||||
|
|
||||||
I want to specifically thank Tony Crisci for the very valuable help with
|
|
||||||
responding to bugreports in our bugtracker. Thank you!
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2013-12-22
|
|
@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.7.1 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.7.1. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
This is a bugfix release for v4.7.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Changes in v4.7.1 │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• docs/debugging: explain how to enable logging on the fly
|
|
||||||
• docs/debugging: small cleanups (versions, bzip2)
|
|
||||||
• add i3-with-shmlog.xsession.desktop
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• only LOG() the DPI when it changes, DLOG() it otherwise
|
|
||||||
• make “move <direction>” properly send workspace focus event
|
|
||||||
• i3bar: set mapped flag on trayclient creation
|
|
||||||
• i3bar: don’t show EOF status line error in favor of exit code
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
lkraav, TonyC
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2014-01-21
|
|
@ -1,26 +0,0 @@
|
|||||||
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Release notes for i3 v4.7.2 │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
|
|
||||||
This is the i3 v4.7.2. This version is considered stable. All users of i3 are
|
|
||||||
strongly encouraged to upgrade.
|
|
||||||
|
|
||||||
This is a bugfix release for v4.7.
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Bugfixes │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
• install i3-with-shmlog.xsession.desktop to the correct location
|
|
||||||
• OpenBSD currently lacks posix_fallocate()
|
|
||||||
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ Thanks! │
|
|
||||||
└────────────────────────────┘
|
|
||||||
|
|
||||||
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
|
||||||
|
|
||||||
David Coppa
|
|
||||||
|
|
||||||
-- Michael Stapelberg, 2014-01-23
|
|
138
RELEASE-NOTES-4.8
Normal file
138
RELEASE-NOTES-4.8
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
|
||||||
|
┌──────────────────────────────┐
|
||||||
|
│ Release notes for i3 v4.8 │
|
||||||
|
└──────────────────────────────┘
|
||||||
|
|
||||||
|
This is i3 v4.8. This version is considered stable. All users of i3 are
|
||||||
|
strongly encouraged to upgrade.
|
||||||
|
|
||||||
|
The biggest new feature certainly is layout saving/restoring. See
|
||||||
|
http://i3wm.org/docs/layout-saving.html for more details. tl;dr: export your
|
||||||
|
current layout as JSON file, load it into new i3 sessions, get placeholder
|
||||||
|
windows that will be replaced by the actual apps once you start them.
|
||||||
|
|
||||||
|
Also very important for owners of HiDPI/“retina” displays is that i3 will now
|
||||||
|
respect your configured DPI and scale up its UI elements accordingly. Use
|
||||||
|
“xrandr --dpi 184” to set your dpi to 184, in case your setup does not figure
|
||||||
|
it out automatically. To get properly scaling fonts, we also changed the
|
||||||
|
default font from a bitmap font to a pango font (“DejaVu Sans Mono 8”).
|
||||||
|
|
||||||
|
Multiple changes improve the compatibility of i3 with other software, e.g.
|
||||||
|
java-based software (focus handling, once again) or external pagers (we now
|
||||||
|
provide _NET_CLIENT_LIST and let pager applications change workspaces).
|
||||||
|
|
||||||
|
For packagers, another change is that yajl ≥ 2.0 is now required for compiling
|
||||||
|
i3. This should not be a problem for anyone, as that version is pretty old by
|
||||||
|
now.
|
||||||
|
|
||||||
|
For contributors, note that we have starting formatting the source code with
|
||||||
|
clang-format-3.5. This means that there will no longer be a need to argue about
|
||||||
|
coding style when discussing patches :).
|
||||||
|
|
||||||
|
┌────────────────────────────┐
|
||||||
|
│ Changes in v4.8 │
|
||||||
|
└────────────────────────────┘
|
||||||
|
|
||||||
|
• docs/ipc: reformat/update list of ipc libraries
|
||||||
|
• docs/ipc: fix current_workspace outputs reply member
|
||||||
|
• docs/ipc: update ipc COMMAND reply docs
|
||||||
|
• docs/userguide: fix multiple typos
|
||||||
|
• docs/debugging: use bzip2
|
||||||
|
• docs/debugging: explain how to enable logging on the fly
|
||||||
|
• docs/debugging: merge the debug symbols/backtrace section
|
||||||
|
• docs/debugging: recommend i3 --moreversion
|
||||||
|
• man/i3-nagbar.man: update manpage to document all options
|
||||||
|
• i3bar: Amend status line error 127 message
|
||||||
|
• i3bar: don’t kill watcher on EOF, leads to better error messages
|
||||||
|
• i3bar: send mouse wheel events to child too
|
||||||
|
• i3bar: do click handling and tray padding retina-correctly
|
||||||
|
• i3bar: render separators render-correctly
|
||||||
|
• i3bar: reinit colors on barconfig update
|
||||||
|
• i3bar: Don't start child unless status_command
|
||||||
|
• i3bar: implement custom workspace numbers config
|
||||||
|
• resize floating windows when right-clicking the decoration
|
||||||
|
• enable shmlog when invoked as i3-with-shmlog
|
||||||
|
• Disable pointer warps when focus_follows_mouse is disabled
|
||||||
|
• Movement into a branch considers movement direction
|
||||||
|
• set ewmh desktop properties on startup
|
||||||
|
• handle ButtonPress events with child != XCB_NONE
|
||||||
|
• implement layout restoring
|
||||||
|
• only LOG() the DPI when it changes, DLOG() it otherwise
|
||||||
|
• send IPC window events for focus and title changes
|
||||||
|
• these types of windows are now floating by default:
|
||||||
|
dialog, utility, toolbar and splash windows, modal windows, windows with an
|
||||||
|
equal minimum and maximum size
|
||||||
|
• send last event timestamp with WM_TAKE_FOCUS message
|
||||||
|
• maintain the _NET_CLIENT_LIST property
|
||||||
|
• don’t set input focus _and_ send WM_TAKE_FOCUS
|
||||||
|
• respect CFLAGS in linking command
|
||||||
|
• fix parallel make
|
||||||
|
• reset SIGPIPE handler before executing a command
|
||||||
|
• render default window border width retina-correctly
|
||||||
|
• draw workspace buttons and padded text blocks retina-correctly
|
||||||
|
• render resize windows retina-correctly
|
||||||
|
• delegate click handling to dock clients
|
||||||
|
• send complete config on barconfig_update
|
||||||
|
• implement the window::fullscreen_mode ipc event
|
||||||
|
• make all workspaces starting with "__" internal
|
||||||
|
• improve error messages for i3-internal workspace names
|
||||||
|
• allow _NET_ACTIVE_WINDOW requests to switch workspaces if they indicate
|
||||||
|
that they are a pager (following the spec)
|
||||||
|
• workspace assignments by number
|
||||||
|
• add configuration option for disabling mouse warping
|
||||||
|
• set _NET_ACTIVE_WINDOW to None when none has focus
|
||||||
|
• set X-LightDM-DesktopName in i3.xsession.desktop to fix autostart on Ubuntu
|
||||||
|
• don’t ELOG ipc EOF
|
||||||
|
• replace all printf()s with D?LOG
|
||||||
|
• delete ipc socket when exiting, cleanup tmpdir
|
||||||
|
• default config: switch to DejaVu Sans Mono 8 as default font
|
||||||
|
• cleanup tmpdir when restarting and not using XDG_RUNTIME_DIR
|
||||||
|
• Snap pointer to resize bar on drag resize
|
||||||
|
• Size resizebar according to container size
|
||||||
|
• Fix clang -Wextra except -Wunused-parameter
|
||||||
|
• Respect Motif hint for window decorations
|
||||||
|
|
||||||
|
┌────────────────────────────┐
|
||||||
|
│ Bugfixes │
|
||||||
|
└────────────────────────────┘
|
||||||
|
|
||||||
|
• create con pixmaps when not needed
|
||||||
|
• i3bar: fix resource leak: statusline_ctx needs to be freed first
|
||||||
|
• tree_split should not split floating cons
|
||||||
|
• fix memory leak with ipc_receive_message
|
||||||
|
• fix invalid reads by setting con->window to NULL in tree_close
|
||||||
|
• fix memory leak when closing windows
|
||||||
|
• fix memory leak when matching window by criteria
|
||||||
|
• fix memory leak when matching window by con_id
|
||||||
|
• ignore dock clients in the resize command
|
||||||
|
• clear wm_size_hints if they are not set
|
||||||
|
• resize window check should check for NULL
|
||||||
|
• fix window event crash with no window
|
||||||
|
• i3-dmenu-desktop: also quote the %c field code
|
||||||
|
• new_window and new_float can now be used simultaneously with different
|
||||||
|
border widths
|
||||||
|
• fix crash when using multiple for_window statements that move windows
|
||||||
|
• Set input focus with last timestamp
|
||||||
|
• handle windows whose WM_TRANSIENT_FOR points to themselve
|
||||||
|
• don’t overwrite the original size of floating windows when changing border
|
||||||
|
• don’t errnously render floating fullscreen windows during restart
|
||||||
|
• ensure floating windows don’t drop out of fullscreen when restarting
|
||||||
|
• don’t overwrite the window’s geometry after restartingnext
|
||||||
|
• i3bar: Set `mapped` flag on trayclient creation
|
||||||
|
• i3bar: don't show "EOF" status line error
|
||||||
|
|
||||||
|
┌────────────────────────────┐
|
||||||
|
│ Thanks! │
|
||||||
|
└────────────────────────────┘
|
||||||
|
|
||||||
|
Thanks for testing, bugfixes, discussions and everything I forgot go out to:
|
||||||
|
|
||||||
|
Aleksi Blinnikka, Alexander Berntsen, Alexander Kedrik, Antonio, Arun
|
||||||
|
Persaud, Atte Peltomaki, bo, Campbell Barton, chris, David Coppa, eeemsi,
|
||||||
|
Holger Langenau, Jean-Philippe Ouellet, Jens, jeroentbt, Jonas Maaskola,
|
||||||
|
Julian Ospald, Kernc, Koston, lasers, lkraav, Marcin, Marco Hunsicker,
|
||||||
|
Marcus Crestani, Matthias Thubauville, Maxime, Michael Stapelberg, Peter
|
||||||
|
Boström, Petr Písař, Quentin Glidic, Steve Jones, TonyC, Tony Crisci,
|
||||||
|
Vivien Didelot, Wieland Hoffmann, x33a, xeen
|
||||||
|
|
||||||
|
-- Michael Stapelberg, 2014-06-15
|
@ -115,9 +115,6 @@ XCURSOR_LIBS := $(call ldflags_for_lib, xcb-cursor,xcb-cursor)
|
|||||||
|
|
||||||
# yajl
|
# yajl
|
||||||
YAJL_CFLAGS := $(call cflags_for_lib, yajl)
|
YAJL_CFLAGS := $(call cflags_for_lib, yajl)
|
||||||
# Fallback for libyajl 1 which did not include yajl_version.h. We need
|
|
||||||
# YAJL_MAJOR from that file to decide which code path should be used.
|
|
||||||
YAJL_CFLAGS += -idirafter $(TOPDIR)/yajl-fallback
|
|
||||||
YAJL_LIBS := $(call ldflags_for_lib, yajl,yajl)
|
YAJL_LIBS := $(call ldflags_for_lib, yajl,yajl)
|
||||||
|
|
||||||
#libev
|
#libev
|
||||||
@ -171,8 +168,8 @@ endif
|
|||||||
|
|
||||||
ifeq ($(UNAME),Darwin)
|
ifeq ($(UNAME),Darwin)
|
||||||
LIBS += -liconv
|
LIBS += -liconv
|
||||||
else
|
else ifneq ($(UNAME),OpenBSD)
|
||||||
# Darwin (Mac OS X) doesn’t have librt
|
# Darwin (Mac OS X) and OpenBSD do not have librt
|
||||||
LIBS += -lrt
|
LIBS += -lrt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
55
contrib/per-workspace-layout.pl
Normal file
55
contrib/per-workspace-layout.pl
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
# vim:ts=4:sw=4:expandtab
|
||||||
|
# © 2012 Michael Stapelberg
|
||||||
|
# Licensed under BSD license, see http://code.i3wm.org/i3/tree/LICENSE
|
||||||
|
#
|
||||||
|
# Append this line to your i3 config file:
|
||||||
|
# exec_always ~/per-workspace-layout.pl
|
||||||
|
#
|
||||||
|
# Then, change the %layouts hash like you want your workspaces to be set up.
|
||||||
|
# This script requires i3 >= v4.4 for the extended workspace event.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use AnyEvent;
|
||||||
|
use AnyEvent::I3;
|
||||||
|
use v5.10;
|
||||||
|
|
||||||
|
my %layouts = (
|
||||||
|
'4' => 'tabbed',
|
||||||
|
'5' => 'stacked',
|
||||||
|
);
|
||||||
|
|
||||||
|
my $i3 = i3();
|
||||||
|
|
||||||
|
die "Could not connect to i3: $!" unless $i3->connect->recv();
|
||||||
|
|
||||||
|
die "Could not subscribe to the workspace event: $!" unless
|
||||||
|
$i3->subscribe({
|
||||||
|
workspace => sub {
|
||||||
|
my ($msg) = @_;
|
||||||
|
return unless $msg->{change} eq 'focus';
|
||||||
|
die "Your version of i3 is too old. You need >= v4.4"
|
||||||
|
unless exists($msg->{current});
|
||||||
|
my $ws = $msg->{current};
|
||||||
|
|
||||||
|
# If the workspace already has children, don’t change the layout.
|
||||||
|
return unless scalar @{$ws->{nodes}} == 0;
|
||||||
|
|
||||||
|
my $name = $ws->{name};
|
||||||
|
my $con_id = $ws->{id};
|
||||||
|
|
||||||
|
return unless exists $layouts{$name};
|
||||||
|
|
||||||
|
$i3->command(qq|[con_id="$con_id"] layout | . $layouts{$name});
|
||||||
|
},
|
||||||
|
_error => sub {
|
||||||
|
my ($msg) = @_;
|
||||||
|
say "AnyEvent::I3 error: $msg";
|
||||||
|
say "Exiting.";
|
||||||
|
exit 1;
|
||||||
|
},
|
||||||
|
})->recv->{success};
|
||||||
|
|
||||||
|
# Run forever.
|
||||||
|
AnyEvent->condvar->recv
|
BIN
contrib/sticker-7x5cm-stickma.tif.lzma
Normal file
BIN
contrib/sticker-7x5cm-stickma.tif.lzma
Normal file
Binary file not shown.
24
debian/changelog
vendored
24
debian/changelog
vendored
@ -1,8 +1,26 @@
|
|||||||
i3-wm (4.6.1-1) unstable; urgency=low
|
i3-wm (4.7.3-1) unstable; urgency=low
|
||||||
|
|
||||||
* NOT YET RELEASED.
|
* NOT YET RELEASED
|
||||||
|
|
||||||
-- Michael Stapelberg <stapelberg@debian.org> Wed, 07 Aug 2013 20:53:26 +0200
|
-- Michael Stapelberg <stapelberg@debian.org> Thu, 23 Jan 2014 23:11:48 +0100
|
||||||
|
|
||||||
|
i3-wm (4.7.2-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release. (Closes: #736396)
|
||||||
|
|
||||||
|
-- Michael Stapelberg <stapelberg@debian.org> Thu, 23 Jan 2014 23:03:03 +0100
|
||||||
|
|
||||||
|
i3-wm (4.7.1-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Michael Stapelberg <stapelberg@debian.org> Tue, 21 Jan 2014 19:29:34 +0100
|
||||||
|
|
||||||
|
i3-wm (4.7-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream release.
|
||||||
|
|
||||||
|
-- Michael Stapelberg <stapelberg@debian.org> Sun, 22 Dec 2013 21:19:02 +0100
|
||||||
|
|
||||||
i3-wm (4.6-1) unstable; urgency=low
|
i3-wm (4.6-1) unstable; urgency=low
|
||||||
|
|
||||||
|
4
debian/control
vendored
4
debian/control
vendored
@ -15,7 +15,7 @@ Build-Depends: debhelper (>= 7.0.50~),
|
|||||||
docbook-xml,
|
docbook-xml,
|
||||||
pkg-config,
|
pkg-config,
|
||||||
libev-dev (>= 1:4.04),
|
libev-dev (>= 1:4.04),
|
||||||
libyajl-dev,
|
libyajl-dev (>= 2.0.4),
|
||||||
libpcre3-dev,
|
libpcre3-dev,
|
||||||
libstartup-notification0-dev (>= 0.10),
|
libstartup-notification0-dev (>= 0.10),
|
||||||
libcairo2-dev,
|
libcairo2-dev,
|
||||||
@ -38,7 +38,7 @@ Architecture: any
|
|||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, x11-utils
|
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, x11-utils
|
||||||
Provides: x-window-manager
|
Provides: x-window-manager
|
||||||
Suggests: rxvt-unicode | x-terminal-emulator
|
Suggests: rxvt-unicode | x-terminal-emulator
|
||||||
Recommends: xfonts-base
|
Recommends: xfonts-base, fonts-dejavu-core, libanyevent-i3-perl, libjson-xs-perl
|
||||||
Description: improved dynamic tiling window manager
|
Description: improved dynamic tiling window manager
|
||||||
Key features of i3 are good documentation, reasonable defaults (changeable in
|
Key features of i3 are good documentation, reasonable defaults (changeable in
|
||||||
a simple configuration file) and good multi-monitor support. The user
|
a simple configuration file) and good multi-monitor support. The user
|
||||||
|
2
debian/i3-wm.docs
vendored
2
debian/i3-wm.docs
vendored
@ -29,3 +29,5 @@ docs/refcard_style.css
|
|||||||
docs/logo-30.png
|
docs/logo-30.png
|
||||||
docs/lib-i3test.html
|
docs/lib-i3test.html
|
||||||
docs/lib-i3test-test.html
|
docs/lib-i3test-test.html
|
||||||
|
docs/layout-saving.html
|
||||||
|
docs/layout-saving-1.png
|
||||||
|
1
debian/i3-wm.links
vendored
Normal file
1
debian/i3-wm.links
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
usr/share/man/man1/i3.1.gz usr/share/man/man1/i3-with-shmlog.1.gz
|
2
debian/rules
vendored
2
debian/rules
vendored
@ -38,7 +38,7 @@ override_dh_auto_build:
|
|||||||
$(MAKE) -C docs
|
$(MAKE) -C docs
|
||||||
|
|
||||||
override_dh_installchangelogs:
|
override_dh_installchangelogs:
|
||||||
dh_installchangelogs RELEASE-NOTES-4.6
|
dh_installchangelogs RELEASE-NOTES-*
|
||||||
|
|
||||||
override_dh_install:
|
override_dh_install:
|
||||||
$(MAKE) DESTDIR=$(CURDIR)/debian/i3-wm/ install
|
$(MAKE) DESTDIR=$(CURDIR)/debian/i3-wm/ install
|
||||||
|
BIN
docs/NoName-2009-03-12/screenshot.png
Normal file
BIN
docs/NoName-2009-03-12/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
@ -560,7 +560,7 @@ ifdef::linkcss[]
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
# Escape as CDATA to pass validators.
|
# Escape as CDATA to pass validators.
|
||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
window.onload = function()\{asciidoc.footnotes();{toc? asciidoc.toc({toclevels});}\}
|
document.addEventListener("DOMContentLoaded", function()\{asciidoc.footnotes();{toc? asciidoc.toc({toclevels});}\}, false);
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="{scriptsdir=.}/asciidoc-xhtml11.js"></script>
|
<script type="text/javascript" src="{scriptsdir=.}/asciidoc-xhtml11.js"></script>
|
||||||
@ -569,7 +569,7 @@ ifndef::linkcss[]
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
# Escape as CDATA to pass validators.
|
# Escape as CDATA to pass validators.
|
||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
window.onload = function()\{asciidoc.footnotes();{toc? asciidoc.toc({toclevels});}\}
|
document.addEventListener("DOMContentLoaded", function()\{asciidoc.footnotes();{toc? asciidoc.toc({toclevels});}\}, false);
|
||||||
include1::{scriptsdir=./javascripts}/asciidoc-xhtml11.js[]
|
include1::{scriptsdir=./javascripts}/asciidoc-xhtml11.js[]
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
</script>
|
</script>
|
||||||
@ -647,7 +647,7 @@ endif::doctype-manpage[]
|
|||||||
</div>
|
</div>
|
||||||
{disable-javascript%<div id="footnotes"><hr /></div>}
|
{disable-javascript%<div id="footnotes"><hr /></div>}
|
||||||
<div id="footer" lang="de">
|
<div id="footer" lang="de">
|
||||||
© 2009-2012 Michael Stapelberg, <a href="/impress.html">Impressum</a>
|
© 2009-2014 Michael Stapelberg, <a href="http://i3wm.org/impress.html">Impressum</a>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -14,7 +14,8 @@ ASCIIDOC_TOC_TARGETS = \
|
|||||||
docs/multi-monitor.html \
|
docs/multi-monitor.html \
|
||||||
docs/wsbar.html \
|
docs/wsbar.html \
|
||||||
docs/testsuite.html \
|
docs/testsuite.html \
|
||||||
docs/i3bar-protocol.html
|
docs/i3bar-protocol.html \
|
||||||
|
docs/layout-saving.html
|
||||||
|
|
||||||
ASCIIDOC_TARGETS = \
|
ASCIIDOC_TARGETS = \
|
||||||
$(ASCIIDOC_TOC_TARGETS) \
|
$(ASCIIDOC_TOC_TARGETS) \
|
||||||
|
@ -172,6 +172,10 @@ values will later be pushed to X11 in +src/x.c+.
|
|||||||
src/resize.c::
|
src/resize.c::
|
||||||
Contains the functions to resize containers.
|
Contains the functions to resize containers.
|
||||||
|
|
||||||
|
src/restore_layout.c::
|
||||||
|
Everything for restored containers that is not pure state parsing (which can be
|
||||||
|
found in load_layout.c).
|
||||||
|
|
||||||
src/sighandler.c::
|
src/sighandler.c::
|
||||||
Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
|
Handles +SIGSEGV+, +SIGABRT+ and +SIGFPE+ by showing a dialog that i3 crashed.
|
||||||
You can chose to let it dump core, to restart it in-place or to restart it
|
You can chose to let it dump core, to restart it in-place or to restart it
|
||||||
|
@ -225,7 +225,7 @@ instance::
|
|||||||
Instance of the block, if set
|
Instance of the block, if set
|
||||||
x, y::
|
x, y::
|
||||||
X11 root window coordinates where the click occured
|
X11 root window coordinates where the click occured
|
||||||
button:
|
button::
|
||||||
X11 button ID (for example 1 to 3 for left/middle/right mouse button)
|
X11 button ID (for example 1 to 3 for left/middle/right mouse button)
|
||||||
|
|
||||||
*Example*:
|
*Example*:
|
||||||
|
89
docs/ipc
89
docs/ipc
@ -1,7 +1,7 @@
|
|||||||
IPC interface (interprocess communication)
|
IPC interface (interprocess communication)
|
||||||
==========================================
|
==========================================
|
||||||
Michael Stapelberg <michael@i3wm.org>
|
Michael Stapelberg <michael@i3wm.org>
|
||||||
October 2012
|
February 2014
|
||||||
|
|
||||||
This document describes how to interface with i3 from a separate process. This
|
This document describes how to interface with i3 from a separate process. This
|
||||||
is useful for example to remote-control i3 (to write test cases for example) or
|
is useful for example to remote-control i3 (to write test cases for example) or
|
||||||
@ -140,12 +140,13 @@ VERSION (7)::
|
|||||||
|
|
||||||
=== COMMAND reply
|
=== COMMAND reply
|
||||||
|
|
||||||
The reply consists of a single serialized map. At the moment, the only
|
The reply consists of a list of serialized maps for each command that was
|
||||||
property is +success (bool)+, but this will be expanded in future versions.
|
parsed. Each has the property +success (bool)+ and may also include a
|
||||||
|
human-readable error message in the property +error (string)+.
|
||||||
|
|
||||||
*Example:*
|
*Example:*
|
||||||
-------------------
|
-------------------
|
||||||
{ "success": true }
|
[{ "success": true }]
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
=== WORKSPACES reply
|
=== WORKSPACES reply
|
||||||
@ -227,9 +228,9 @@ name (string)::
|
|||||||
The name of this output (as seen in +xrandr(1)+). Encoded in UTF-8.
|
The name of this output (as seen in +xrandr(1)+). Encoded in UTF-8.
|
||||||
active (boolean)::
|
active (boolean)::
|
||||||
Whether this output is currently active (has a valid mode).
|
Whether this output is currently active (has a valid mode).
|
||||||
current_workspace (integer)::
|
current_workspace (string)::
|
||||||
The current workspace which is visible on this output. +null+ if the
|
The name of the current workspace that is visible on this output. +null+ if
|
||||||
output is not active.
|
the output is not active.
|
||||||
rect (map)::
|
rect (map)::
|
||||||
The rectangle of this output (equals the rect of the output it
|
The rectangle of this output (equals the rect of the output it
|
||||||
is on), consists of x, y, width, height.
|
is on), consists of x, y, width, height.
|
||||||
@ -240,7 +241,7 @@ rect (map)::
|
|||||||
{
|
{
|
||||||
"name": "LVDS1",
|
"name": "LVDS1",
|
||||||
"active": true,
|
"active": true,
|
||||||
"current_workspace": 4,
|
"current_workspace": "4",
|
||||||
"rect": {
|
"rect": {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
@ -251,7 +252,7 @@ rect (map)::
|
|||||||
{
|
{
|
||||||
"name": "VGA1",
|
"name": "VGA1",
|
||||||
"active": true,
|
"active": true,
|
||||||
"current_workspace": 1,
|
"current_workspace": "1",
|
||||||
"rect": {
|
"rect": {
|
||||||
"x": 1280,
|
"x": 1280,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
@ -277,7 +278,12 @@ name (string)::
|
|||||||
The internal name of this container. For all containers which are part
|
The internal name of this container. For all containers which are part
|
||||||
of the tree structure down to the workspace contents, this is set to a
|
of the tree structure down to the workspace contents, this is set to a
|
||||||
nice human-readable name of the container.
|
nice human-readable name of the container.
|
||||||
|
For containers that have an X11 window, the content is the title
|
||||||
|
(_NET_WM_NAME property) of that window.
|
||||||
For all other containers, the content is not defined (yet).
|
For all other containers, the content is not defined (yet).
|
||||||
|
type (string)::
|
||||||
|
Type of this container. Can be one of "root", "output", "con",
|
||||||
|
"floating_con", "workspace" or "dockarea".
|
||||||
border (string)::
|
border (string)::
|
||||||
Can be either "normal", "none" or "1pixel", dependending on the
|
Can be either "normal", "none" or "1pixel", dependending on the
|
||||||
container’s border style.
|
container’s border style.
|
||||||
@ -627,10 +633,11 @@ mode (2)::
|
|||||||
Sent whenever i3 changes its binding mode.
|
Sent whenever i3 changes its binding mode.
|
||||||
window (3)::
|
window (3)::
|
||||||
Sent when a client's window is successfully reparented (that is when i3
|
Sent when a client's window is successfully reparented (that is when i3
|
||||||
has finished fitting it into a container).
|
has finished fitting it into a container), when a window received input
|
||||||
|
focus or when certain properties of the window have changed.
|
||||||
barconfig_update (4)::
|
barconfig_update (4)::
|
||||||
Sent when the hidden_state or mode field in the barconfig of any bar
|
Sent when the hidden_state or mode field in the barconfig of any bar
|
||||||
instance was updated.
|
instance was updated and when the config is reloaded.
|
||||||
|
|
||||||
*Example:*
|
*Example:*
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
@ -670,12 +677,12 @@ but will still be present in the "old" property.
|
|||||||
"change": "focus",
|
"change": "focus",
|
||||||
"current": {
|
"current": {
|
||||||
"id": 28489712,
|
"id": 28489712,
|
||||||
"type":4,
|
"type": "workspace",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
"old": {
|
"old": {
|
||||||
"id": 28489715,
|
"id": 28489715,
|
||||||
"type": 4,
|
"type": "workspace",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -707,14 +714,18 @@ mode is simply named default.
|
|||||||
=== window event
|
=== window event
|
||||||
|
|
||||||
This event consists of a single serialized map containing a property
|
This event consists of a single serialized map containing a property
|
||||||
+change (string)+ which currently can indicate only that a new window
|
+change (string)+ which indicates the type of the change
|
||||||
has been successfully reparented (the value will be "new").
|
|
||||||
|
* +new+ - the window has become managed by i3
|
||||||
|
* +focus+ - the window has received input focus
|
||||||
|
* +title+ - the window's title has changed
|
||||||
|
* +fullscreen_mode+ - the window has entered or exited fullscreen mode
|
||||||
|
|
||||||
Additionally a +container (object)+ field will be present, which consists
|
Additionally a +container (object)+ field will be present, which consists
|
||||||
of the window's parent container. Be aware that the container will hold
|
of the window's parent container. Be aware that for the "new" event, the
|
||||||
the initial name of the newly reparented window (e.g. if you run urxvt
|
container will hold the initial name of the newly reparented window (e.g.
|
||||||
with a shell that changes the title, you will still at this point get the
|
if you run urxvt with a shell that changes the title, you will still at
|
||||||
window title as "urxvt").
|
this point get the window title as "urxvt").
|
||||||
|
|
||||||
*Example:*
|
*Example:*
|
||||||
---------------------------
|
---------------------------
|
||||||
@ -722,7 +733,7 @@ window title as "urxvt").
|
|||||||
"change": "new",
|
"change": "new",
|
||||||
"container": {
|
"container": {
|
||||||
"id": 35569536,
|
"id": 35569536,
|
||||||
"type": 2,
|
"type": "con",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -731,20 +742,8 @@ window title as "urxvt").
|
|||||||
=== barconfig_update event
|
=== barconfig_update event
|
||||||
|
|
||||||
This event consists of a single serialized map reporting on options from the
|
This event consists of a single serialized map reporting on options from the
|
||||||
barconfig of the specified bar_id that were updated in i3. The map always
|
barconfig of the specified bar_id that were updated in i3. This event is the
|
||||||
consists of a property +id (string)+, which specifies to which bar instance the
|
same as a +GET_BAR_CONFIG+ reply for the bar with the given id.
|
||||||
sent config update belongs, a property +hidden_state (string)+, which indicates
|
|
||||||
the hidden_state of an i3bar instance, and a property +mode (string)+, which
|
|
||||||
corresponds to the current mode.
|
|
||||||
|
|
||||||
*Example:*
|
|
||||||
---------------------------
|
|
||||||
{
|
|
||||||
"id": "bar-0",
|
|
||||||
"hidden_state": "hide"
|
|
||||||
"mode": "hide"
|
|
||||||
}
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
== See also (existing libraries)
|
== See also (existing libraries)
|
||||||
|
|
||||||
@ -756,13 +755,19 @@ know):
|
|||||||
|
|
||||||
C::
|
C::
|
||||||
i3 includes a headerfile +i3/ipc.h+ which provides you all constants.
|
i3 includes a headerfile +i3/ipc.h+ which provides you all constants.
|
||||||
However, there is no library yet.
|
|
||||||
Ruby::
|
https://github.com/acrisci/i3ipc-glib
|
||||||
http://github.com/badboy/i3-ipc
|
|
||||||
Perl::
|
|
||||||
https://metacpan.org/module/AnyEvent::I3
|
|
||||||
Python::
|
|
||||||
* https://github.com/whitelynx/i3ipc
|
|
||||||
* https://github.com/ziberna/i3-py (includes higher-level features)
|
|
||||||
Go::
|
Go::
|
||||||
* https://github.com/proxypoke/i3ipc
|
* https://github.com/proxypoke/i3ipc
|
||||||
|
JavaScript::
|
||||||
|
* https://github.com/acrisci/i3ipc-gjs
|
||||||
|
Lua::
|
||||||
|
* https:/github.com/acrisci/i3ipc-lua
|
||||||
|
Perl::
|
||||||
|
* https://metacpan.org/module/AnyEvent::I3
|
||||||
|
Python::
|
||||||
|
* https://github.com/acrisci/i3ipc-python
|
||||||
|
* https://github.com/whitelynx/i3ipc (not maintained)
|
||||||
|
* https://github.com/ziberna/i3-py (not maintained)
|
||||||
|
Ruby::
|
||||||
|
http://github.com/badboy/i3-ipc
|
||||||
|
233
docs/layout-saving
Normal file
233
docs/layout-saving
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
Layout saving in i3
|
||||||
|
===================
|
||||||
|
Michael Stapelberg <michael@i3wm.org>
|
||||||
|
April 2014
|
||||||
|
|
||||||
|
Layout saving/restoring is a feature that was introduced in i3 v4.8.
|
||||||
|
|
||||||
|
Layout saving/restoring allows you to load a JSON layout file so that you can
|
||||||
|
have a base layout to start working with after powering on your computer.
|
||||||
|
Dynamic use-cases also come to mind: if you frequently (but not always!) need a
|
||||||
|
grid layout of terminals with ping/traceroute commands to diagnose network
|
||||||
|
issues, you can easily automate opening these windows in just the right layout.
|
||||||
|
|
||||||
|
== Saving the layout
|
||||||
|
|
||||||
|
You can save the layout of either a single workspace or an entire output (e.g.
|
||||||
|
LVDS1). Of course, you can repeat this step multiple times if you want to
|
||||||
|
save/restore multiple workspaces/outputs.
|
||||||
|
|
||||||
|
+i3-save-tree(1)+ is a tool to save the layout. It will print a JSON
|
||||||
|
representation of i3’s internal layout data structures to stdout. Typically,
|
||||||
|
you may want to take a quick look at the output, then save it to a file and
|
||||||
|
tweak it a little bit:
|
||||||
|
|
||||||
|
---------------------------------------------------
|
||||||
|
i3-save-tree --workspace 1 > ~/.i3/workspace-1.json
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
Please note that the output of +i3-save-tree(1)+ is *NOT useful* until you
|
||||||
|
manually modify it — you need to tell i3 how to match/distinguish windows (for
|
||||||
|
example based on their WM_CLASS, title, etc.). By default, all the different
|
||||||
|
window properties are included in the output, but commented out. This is partly
|
||||||
|
to avoid relying on heuristics and partly to make you aware how i3 works so
|
||||||
|
that you can easily solve layout restoring problems.
|
||||||
|
|
||||||
|
How to modify the file manually is described in <<EditingLayoutFiles>>.
|
||||||
|
|
||||||
|
== Restoring the layout
|
||||||
|
|
||||||
|
After restoring the example layout from <<EditingLayoutFiles>>, i3 will open
|
||||||
|
placeholder windows for all the windows that were specified in the layout file.
|
||||||
|
You can recognize the placeholder windows by the watch symbol
|
||||||
|
footnote:[Depending on the font you are using, a placeholder symbol may show up
|
||||||
|
instead of the watch symbol.] in the center of the window, and by the swallow
|
||||||
|
criteria specification at the top of the window:
|
||||||
|
|
||||||
|
image:layout-saving-1.png["Restored layout",width=400,link="layout-saving-1.png"]
|
||||||
|
|
||||||
|
When an application opens a window that matches the specified swallow criteria,
|
||||||
|
it will be placed in the corresponding placeholder window. We say it gets
|
||||||
|
*swallowed* by the placeholder container, hence the term.
|
||||||
|
|
||||||
|
Note: Swallowing windows into unsatisfied placeholder windows takes precedence
|
||||||
|
over
|
||||||
|
link:http://i3wm.org/docs/userguide.html#_automatically_putting_clients_on_specific_workspaces[assignment
|
||||||
|
rules]. For example, if you assign all Emacs windows to workspace 1 in your i3
|
||||||
|
configuration file, but there is a placeholder window on workspace 2 which
|
||||||
|
matches Emacs as well, your newly started Emacs window will end up in the
|
||||||
|
placeholder window on workspace 2.
|
||||||
|
|
||||||
|
The placeholder windows are just regular windows, so feel free to move them
|
||||||
|
around or close them, for example.
|
||||||
|
|
||||||
|
=== append_layout command
|
||||||
|
|
||||||
|
The +append_layout+ command is used to load a layout file into i3. It accepts a
|
||||||
|
path (relative to i3’s current working directory or absolute) to a JSON file.
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
append_layout <path>
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*Examples*:
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
# From a terminal or script:
|
||||||
|
i3-msg "workspace 1; append_layout /home/michael/.i3/workspace-1.json"
|
||||||
|
|
||||||
|
# In your i3 configuration file, you can autostart i3-msg like this:
|
||||||
|
# (Note that those lines will quickly become long, so typically you would store
|
||||||
|
# them in a script with proper indentation.)
|
||||||
|
exec --no-startup-id "i3-msg 'workspace 1; append_layout /home/michael/.i3/workspace-1.json'"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
== Editing layout files
|
||||||
|
|
||||||
|
[[EditingLayoutFiles]]
|
||||||
|
|
||||||
|
=== Anatomy of a layout file
|
||||||
|
|
||||||
|
Here is an example layout file that we’ll discuss:
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
// splitv split container with 2 children
|
||||||
|
"layout": "splitv",
|
||||||
|
"percent": 0.4,
|
||||||
|
"type": "con",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"border": "none",
|
||||||
|
"name": "irssi",
|
||||||
|
"percent": 0.5,
|
||||||
|
"type": "con",
|
||||||
|
"swallows": [
|
||||||
|
{
|
||||||
|
"class": "^URxvt$",
|
||||||
|
"instance": "^irssi$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// stacked split container with 2 children
|
||||||
|
"layout": "stacked",
|
||||||
|
"percent": 0.5,
|
||||||
|
"type": "con",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "notmuch",
|
||||||
|
"percent": 0.5,
|
||||||
|
"type": "con",
|
||||||
|
"swallows": [
|
||||||
|
{
|
||||||
|
"class": "^Emacs$",
|
||||||
|
"instance": "^notmuch$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "midna: ~",
|
||||||
|
"percent": 0.5,
|
||||||
|
"type": "con"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// stacked split container with 1 children
|
||||||
|
"layout": "stacked",
|
||||||
|
"percent": 0.6,
|
||||||
|
"type": "con",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "chrome",
|
||||||
|
"type": "con",
|
||||||
|
"swallows": [
|
||||||
|
{
|
||||||
|
"class": "^Google-chrome$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
In this layout, the screen is divided into two columns. In the left column,
|
||||||
|
which covers 40% of the screen, there is a terminal emulator running irssi on
|
||||||
|
the top, and a stacked split container with an Emacs window and a terminal
|
||||||
|
emulator on the bottom. In the right column, there is a stacked container with
|
||||||
|
a Chrome window:
|
||||||
|
|
||||||
|
image:layout-saving-1.png["Restored layout",width=400,link="layout-saving-1.png"]
|
||||||
|
|
||||||
|
The structure of this JSON file looks a lot like the +TREE+ reply, see
|
||||||
|
http://build.i3wm.org/docs/ipc.html#_tree_reply for documentation on that. Some
|
||||||
|
properties are excluded because they are not relevant when restoring a layout.
|
||||||
|
|
||||||
|
Most importantly, look at the "swallows" section of each window. This is where
|
||||||
|
you need to be more or less specific. As an example, remember the section about
|
||||||
|
the Emacs window:
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
"swallows": [
|
||||||
|
{
|
||||||
|
"class": "^Emacs$",
|
||||||
|
"instance": "^notmuch$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Here you can see that i3 will require both the class and the instance to match.
|
||||||
|
Therefore, if you just start Emacs via dmenu, it will not get swallowed by that
|
||||||
|
container. Only if you start Emacs with the proper instance name (+emacs24
|
||||||
|
--name notmuch+), it will get swallowed.
|
||||||
|
|
||||||
|
You can match on "class", "instance", "window_role" and "title". All values are
|
||||||
|
case-sensitive regular expressions (PCRE). Use +xprop(1)+ and click into a
|
||||||
|
window to see its properties:
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
$ xprop
|
||||||
|
WM_WINDOW_ROLE(STRING) = "gimp-toolbox-color-dialog"
|
||||||
|
WM_CLASS(STRING) = "gimp-2.8", "Gimp-2.8"
|
||||||
|
_NET_WM_NAME(UTF8_STRING) = "Change Foreground Color"
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The first part of +WM_CLASS+ is the "instance" (gimp-2.8 in this case), the
|
||||||
|
second part is the "class" (Gimp-2.8 in this case). "title" matches against
|
||||||
|
+_NET_WM_NAME+ and "window_role" matches against +WM_WINDOW_ROLE+.
|
||||||
|
|
||||||
|
In general, you should try to be as specific as possible in your swallow
|
||||||
|
criteria. Try to use criteria that match one window and only one window, to
|
||||||
|
have a reliable startup procedure.
|
||||||
|
|
||||||
|
If you specify multiple swallow criteria, the placeholder will be replaced by
|
||||||
|
the window which matches any of the criteria. As an example:
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
// Matches either Emacs or Gvim, whichever one is started first.
|
||||||
|
"swallows": [
|
||||||
|
{"class": "^Emacs$"},
|
||||||
|
{"class": "^Gvim$"}
|
||||||
|
]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
=== JSON standard non-compliance
|
||||||
|
|
||||||
|
A layout file as generated by +i3-save-tree(1)+ is not strictly valid JSON:
|
||||||
|
|
||||||
|
1. Layout files contain multiple “JSON documents” on the top level, whereas the
|
||||||
|
JSON standard only allows precisely one “document” (array or hash).
|
||||||
|
|
||||||
|
2. Layout files contain comments which are not standardized, but understood by
|
||||||
|
many parsers.
|
||||||
|
|
||||||
|
Both deviations from the JSON standard are to make manual editing by humans
|
||||||
|
easier. In case you are writing a more elaborate tool for manipulating these
|
||||||
|
layouts, you can either use a JSON parser that supports these deviations (for
|
||||||
|
example libyajl), transform the layout file to a JSON-conforming file, or
|
||||||
|
link:http://cr.i3wm.org/[submit a patch] to make +i3-save-tree(1)+ optionally
|
||||||
|
output standard-conforming JSON.
|
BIN
docs/layout-saving-1.png
Normal file
BIN
docs/layout-saving-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -166,7 +166,8 @@ hint and are opened in floating mode by default.
|
|||||||
You can toggle floating mode for a window by pressing +$mod+Shift+Space+. By
|
You can toggle floating mode for a window by pressing +$mod+Shift+Space+. By
|
||||||
dragging the window’s titlebar with your mouse you can move the window
|
dragging the window’s titlebar with your mouse you can move the window
|
||||||
around. By grabbing the borders and moving them you can resize the window. You
|
around. By grabbing the borders and moving them you can resize the window. You
|
||||||
can also do that by using the <<floating_modifier>>.
|
can also do that by using the <<floating_modifier>>. Another way to resize
|
||||||
|
floating windows using the mouse is to right-click on the titlebar and drag.
|
||||||
|
|
||||||
For resizing floating windows with your keyboard, see <<resizingconfig>>.
|
For resizing floating windows with your keyboard, see <<resizingconfig>>.
|
||||||
|
|
||||||
@ -203,7 +204,7 @@ orientation (horizontal, vertical or unspecified) and the orientation depends
|
|||||||
on the layout the container is in (vertical for splitv and stacking, horizontal
|
on the layout the container is in (vertical for splitv and stacking, horizontal
|
||||||
for splith and tabbed). So, in our example with the workspace, the default
|
for splith and tabbed). So, in our example with the workspace, the default
|
||||||
layout of the workspace +Container+ is splith (most monitors are widescreen
|
layout of the workspace +Container+ is splith (most monitors are widescreen
|
||||||
nowadays). If you change the layout to splitv (+$mod+l+ in the default config)
|
nowadays). If you change the layout to splitv (+$mod+v+ in the default config)
|
||||||
and *then* open two terminals, i3 will configure your windows like this:
|
and *then* open two terminals, i3 will configure your windows like this:
|
||||||
|
|
||||||
image::tree-shot2.png["shot2",title="Vertical Workspace Orientation"]
|
image::tree-shot2.png["shot2",title="Vertical Workspace Orientation"]
|
||||||
@ -249,13 +250,13 @@ single workspace on which you open three terminal windows. All these terminal
|
|||||||
windows are directly attached to one node inside i3’s layout tree, the
|
windows are directly attached to one node inside i3’s layout tree, the
|
||||||
workspace node. By default, the workspace node’s orientation is +horizontal+.
|
workspace node. By default, the workspace node’s orientation is +horizontal+.
|
||||||
|
|
||||||
Now you move one of these terminals down (+$mod+k+ by default). The workspace
|
Now you move one of these terminals down (+$mod+Shift+k+ by default). The
|
||||||
node’s orientation will be changed to +vertical+. The terminal window you moved
|
workspace node’s orientation will be changed to +vertical+. The terminal window
|
||||||
down is directly attached to the workspace and appears on the bottom of the
|
you moved down is directly attached to the workspace and appears on the bottom
|
||||||
screen. A new (horizontal) container was created to accommodate the other two
|
of the screen. A new (horizontal) container was created to accommodate the
|
||||||
terminal windows. You will notice this when switching to tabbed mode (for
|
other two terminal windows. You will notice this when switching to tabbed mode
|
||||||
example). You would end up having one tab called "another container" and the
|
(for example). You would end up having one tab called "another container" and
|
||||||
other one being the terminal window you moved down.
|
the other one being the terminal window you moved down.
|
||||||
|
|
||||||
[[configuring]]
|
[[configuring]]
|
||||||
== Configuring i3
|
== Configuring i3
|
||||||
@ -727,6 +728,9 @@ client.unfocused::
|
|||||||
A client which is not the focused one of its container.
|
A client which is not the focused one of its container.
|
||||||
client.urgent::
|
client.urgent::
|
||||||
A client which has its urgency hint activated.
|
A client which has its urgency hint activated.
|
||||||
|
client.placeholder::
|
||||||
|
Background and text color are used to draw placeholder window contents
|
||||||
|
(when restoring layouts). Border and indicator are ignored.
|
||||||
|
|
||||||
You can also specify the color to be used to paint the background of the client
|
You can also specify the color to be used to paint the background of the client
|
||||||
windows. This color will be used to paint the window on top of which the client
|
windows. This color will be used to paint the window on top of which the client
|
||||||
@ -749,6 +753,7 @@ client.focused #4c7899 #285577 #ffffff #2e9ef4
|
|||||||
client.focused_inactive #333333 #5f676a #ffffff #484e50
|
client.focused_inactive #333333 #5f676a #ffffff #484e50
|
||||||
client.unfocused #333333 #222222 #888888 #292d2e
|
client.unfocused #333333 #222222 #888888 #292d2e
|
||||||
client.urgent #2f343a #900000 #ffffff #900000
|
client.urgent #2f343a #900000 #ffffff #900000
|
||||||
|
client.placeholder #000000 #0c0c0c #ffffff #000000
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Note that for the window decorations, the color around the child window is the
|
Note that for the window decorations, the color around the child window is the
|
||||||
@ -805,6 +810,26 @@ focus_follows_mouse <yes|no>
|
|||||||
focus_follows_mouse no
|
focus_follows_mouse no
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
=== Mouse warping
|
||||||
|
|
||||||
|
By default, when switching focus to a window on a different output (e.g.
|
||||||
|
focusing a window on workspace 3 on output VGA-1, coming from workspace 2 on
|
||||||
|
LVDS-1), the mouse cursor is warped to the center of that window.
|
||||||
|
|
||||||
|
With the +mouse_warping+ option, you can control when the mouse cursor should
|
||||||
|
be warped. +none+ disables warping entirely, whereas +output+ is the default
|
||||||
|
behavior described above.
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
---------------------------
|
||||||
|
mouse_warping <output|none>
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
*Example*:
|
||||||
|
------------------
|
||||||
|
mouse_warping none
|
||||||
|
------------------
|
||||||
|
|
||||||
=== Popups during fullscreen mode
|
=== Popups during fullscreen mode
|
||||||
|
|
||||||
When you are in fullscreen mode, some applications still open popup windows
|
When you are in fullscreen mode, some applications still open popup windows
|
||||||
@ -861,7 +886,7 @@ inferior Xinerama API explicitly and therefore don’t provide support for
|
|||||||
reconfiguring your screens on the fly (they are read only once on startup and
|
reconfiguring your screens on the fly (they are read only once on startup and
|
||||||
that’s it).
|
that’s it).
|
||||||
|
|
||||||
For people who do cannot modify their +~/.xsession+ to add the
|
For people who cannot modify their +~/.xsession+ to add the
|
||||||
+--force-xinerama+ commandline parameter, a configuration option is provided:
|
+--force-xinerama+ commandline parameter, a configuration option is provided:
|
||||||
|
|
||||||
*Syntax*:
|
*Syntax*:
|
||||||
@ -1186,6 +1211,31 @@ bar {
|
|||||||
}
|
}
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
=== Strip workspace numbers
|
||||||
|
|
||||||
|
Specifies whether workspace numbers should be displayed within the workspace
|
||||||
|
buttons. This is useful if you want to have a named workspace that stays in
|
||||||
|
order on the bar according to its number without displaying the number prefix.
|
||||||
|
|
||||||
|
When +strip_workspace_numbers+ is set to +yes+, any workspace that has a name of
|
||||||
|
the form "[n]:[NAME]" will display only the name. You could use this, for
|
||||||
|
instance, to display Roman numerals rather than digits by naming your
|
||||||
|
workspaces to "1:I", "2:II", "3:III", "4:IV", ...
|
||||||
|
|
||||||
|
The default is to display the full name within the workspace button.
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
----------------------------------
|
||||||
|
strip_workspace_numbers <yes|no>
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
*Example*:
|
||||||
|
----------------------------
|
||||||
|
bar {
|
||||||
|
strip_workspace_numbers yes
|
||||||
|
}
|
||||||
|
----------------------------
|
||||||
|
|
||||||
=== Binding Mode indicator
|
=== Binding Mode indicator
|
||||||
|
|
||||||
Specifies whether the current binding mode indicator should be shown or not.
|
Specifies whether the current binding mode indicator should be shown or not.
|
||||||
|
@ -131,7 +131,7 @@ close($enumfh);
|
|||||||
|
|
||||||
# Third step: Generate the call function.
|
# Third step: Generate the call function.
|
||||||
open(my $callfh, '>', "GENERATED_${prefix}_call.h");
|
open(my $callfh, '>', "GENERATED_${prefix}_call.h");
|
||||||
my $resultname = uc(substr($prefix, 0, 1)) . substr($prefix, 1) . 'Result';
|
my $resultname = uc(substr($prefix, 0, 1)) . substr($prefix, 1) . 'ResultIR';
|
||||||
say $callfh "static void GENERATED_call(const int call_identifier, struct $resultname *result) {";
|
say $callfh "static void GENERATED_call(const int call_identifier, struct $resultname *result) {";
|
||||||
say $callfh ' switch (call_identifier) {';
|
say $callfh ' switch (call_identifier) {';
|
||||||
my $call_id = 0;
|
my $call_id = 0;
|
||||||
|
@ -53,19 +53,21 @@
|
|||||||
#error "SYSCONFDIR not defined"
|
#error "SYSCONFDIR not defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FREE(pointer) do { \
|
#define FREE(pointer) \
|
||||||
if (pointer != NULL) { \
|
do { \
|
||||||
free(pointer); \
|
if (pointer != NULL) { \
|
||||||
pointer = NULL; \
|
free(pointer); \
|
||||||
} \
|
pointer = NULL; \
|
||||||
} \
|
} \
|
||||||
while (0)
|
} while (0)
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "libi3.h"
|
#include "libi3.h"
|
||||||
|
|
||||||
enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME;
|
enum { STEP_WELCOME,
|
||||||
enum { MOD_Mod1, MOD_Mod4 } modifier = MOD_Mod4;
|
STEP_GENERATE } current_step = STEP_WELCOME;
|
||||||
|
enum { MOD_Mod1,
|
||||||
|
MOD_Mod4 } modifier = MOD_Mod4;
|
||||||
|
|
||||||
static char *config_path;
|
static char *config_path;
|
||||||
static uint32_t xcb_numlock_mask;
|
static uint32_t xcb_numlock_mask;
|
||||||
@ -102,7 +104,6 @@ typedef struct tokenptr {
|
|||||||
int n;
|
int n;
|
||||||
} cmdp_token_ptr;
|
} cmdp_token_ptr;
|
||||||
|
|
||||||
|
|
||||||
#include "GENERATED_config_tokens.h"
|
#include "GENERATED_config_tokens.h"
|
||||||
|
|
||||||
static cmdp_state state;
|
static cmdp_state state;
|
||||||
@ -111,7 +112,7 @@ static cmdp_state state;
|
|||||||
* When jumping back to INITIAL, statelist_idx will simply be set to 1
|
* When jumping back to INITIAL, statelist_idx will simply be set to 1
|
||||||
* (likewise for other states, e.g. MODE or BAR).
|
* (likewise for other states, e.g. MODE or BAR).
|
||||||
* This list is used to process the nearest error token. */
|
* This list is used to process the nearest error token. */
|
||||||
static cmdp_state statelist[10] = { INITIAL };
|
static cmdp_state statelist[10] = {INITIAL};
|
||||||
/* NB: statelist_idx points to where the next entry will be inserted */
|
/* NB: statelist_idx points to where the next entry will be inserted */
|
||||||
static int statelist_idx = 1;
|
static int statelist_idx = 1;
|
||||||
|
|
||||||
@ -182,7 +183,6 @@ static void push_long(const char *identifier, long num) {
|
|||||||
"in the code, or a new command which contains more than "
|
"in the code, or a new command which contains more than "
|
||||||
"10 identified tokens.\n");
|
"10 identified tokens.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_string(const char *identifier) {
|
static const char *get_string(const char *identifier) {
|
||||||
@ -195,7 +195,6 @@ static const char *get_string(const char *identifier) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void clear_stack(void) {
|
static void clear_stack(void) {
|
||||||
for (int c = 0; c < 10; c++) {
|
for (int c = 0; c < 10; c++) {
|
||||||
if (stack[c].type == STACK_STR && stack[c].val.str != NULL)
|
if (stack[c].type == STACK_STR && stack[c].val.str != NULL)
|
||||||
@ -213,8 +212,8 @@ static void clear_stack(void) {
|
|||||||
*/
|
*/
|
||||||
static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) {
|
static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) {
|
||||||
xcb_keycode_t i,
|
xcb_keycode_t i,
|
||||||
min_keycode = xcb_get_setup(conn)->min_keycode,
|
min_keycode = xcb_get_setup(conn)->min_keycode,
|
||||||
max_keycode = xcb_get_setup(conn)->max_keycode;
|
max_keycode = xcb_get_setup(conn)->max_keycode;
|
||||||
|
|
||||||
for (i = min_keycode; i && i <= max_keycode; i++) {
|
for (i = min_keycode; i && i <= max_keycode; i++) {
|
||||||
if (i == except_keycode)
|
if (i == except_keycode)
|
||||||
@ -228,7 +227,6 @@ static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *next_state(const cmdp_token *token) {
|
static char *next_state(const cmdp_token *token) {
|
||||||
cmdp_state _next_state = token->next_state;
|
cmdp_state _next_state = token->next_state;
|
||||||
|
|
||||||
@ -277,7 +275,7 @@ static char *next_state(const cmdp_token *token) {
|
|||||||
for (int i = 0; i < statelist_idx; i++) {
|
for (int i = 0; i < statelist_idx; i++) {
|
||||||
if (statelist[i] != _next_state)
|
if (statelist[i] != _next_state)
|
||||||
continue;
|
continue;
|
||||||
statelist_idx = i+1;
|
statelist_idx = i + 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +284,6 @@ static char *next_state(const cmdp_token *token) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *rewrite_binding(const char *input) {
|
static char *rewrite_binding(const char *input) {
|
||||||
state = INITIAL;
|
state = INITIAL;
|
||||||
statelist_idx = 1;
|
statelist_idx = 1;
|
||||||
@ -299,13 +296,13 @@ static char *rewrite_binding(const char *input) {
|
|||||||
|
|
||||||
/* The "<=" operator is intentional: We also handle the terminating 0-byte
|
/* The "<=" operator is intentional: We also handle the terminating 0-byte
|
||||||
* explicitly by looking for an 'end' token. */
|
* explicitly by looking for an 'end' token. */
|
||||||
while ((walk - input) <= len) {
|
while ((size_t)(walk - input) <= len) {
|
||||||
/* Skip whitespace before every token, newlines are relevant since they
|
/* Skip whitespace before every token, newlines are relevant since they
|
||||||
* separate configuration directives. */
|
* separate configuration directives. */
|
||||||
while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
|
while ((*walk == ' ' || *walk == '\t') && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
|
|
||||||
//printf("remaining input: %s\n", walk);
|
//printf("remaining input: %s\n", walk);
|
||||||
|
|
||||||
cmdp_token_ptr *ptr = &(tokens[state]);
|
cmdp_token_ptr *ptr = &(tokens[state]);
|
||||||
for (c = 0; c < ptr->n; c++) {
|
for (c = 0; c < ptr->n; c++) {
|
||||||
@ -354,7 +351,7 @@ static char *rewrite_binding(const char *input) {
|
|||||||
if (*walk == '"') {
|
if (*walk == '"') {
|
||||||
beginning++;
|
beginning++;
|
||||||
walk++;
|
walk++;
|
||||||
while (*walk != '\0' && (*walk != '"' || *(walk-1) == '\\'))
|
while (*walk != '\0' && (*walk != '"' || *(walk - 1) == '\\'))
|
||||||
walk++;
|
walk++;
|
||||||
} else {
|
} else {
|
||||||
if (token->name[0] == 's') {
|
if (token->name[0] == 's') {
|
||||||
@ -366,22 +363,22 @@ static char *rewrite_binding(const char *input) {
|
|||||||
* semicolon (;). */
|
* semicolon (;). */
|
||||||
while (*walk != ' ' && *walk != '\t' &&
|
while (*walk != ' ' && *walk != '\t' &&
|
||||||
*walk != ']' && *walk != ',' &&
|
*walk != ']' && *walk != ',' &&
|
||||||
*walk != ';' && *walk != '\r' &&
|
*walk != ';' && *walk != '\r' &&
|
||||||
*walk != '\n' && *walk != '\0')
|
*walk != '\n' && *walk != '\0')
|
||||||
walk++;
|
walk++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (walk != beginning) {
|
if (walk != beginning) {
|
||||||
char *str = scalloc(walk-beginning + 1);
|
char *str = scalloc(walk - beginning + 1);
|
||||||
/* We copy manually to handle escaping of characters. */
|
/* We copy manually to handle escaping of characters. */
|
||||||
int inpos, outpos;
|
int inpos, outpos;
|
||||||
for (inpos = 0, outpos = 0;
|
for (inpos = 0, outpos = 0;
|
||||||
inpos < (walk-beginning);
|
inpos < (walk - beginning);
|
||||||
inpos++, outpos++) {
|
inpos++, outpos++) {
|
||||||
/* We only handle escaped double quotes to not break
|
/* We only handle escaped double quotes to not break
|
||||||
* backwards compatibility with people using \w in
|
* backwards compatibility with people using \w in
|
||||||
* regular expressions etc. */
|
* regular expressions etc. */
|
||||||
if (beginning[inpos] == '\\' && beginning[inpos+1] == '"')
|
if (beginning[inpos] == '\\' && beginning[inpos + 1] == '"')
|
||||||
inpos++;
|
inpos++;
|
||||||
str[outpos] = beginning[inpos];
|
str[outpos] = beginning[inpos];
|
||||||
}
|
}
|
||||||
@ -410,15 +407,14 @@ static char *rewrite_binding(const char *input) {
|
|||||||
// TODO: make this testable
|
// TODO: make this testable
|
||||||
walk++;
|
walk++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Having verboselog(), errorlog() and debuglog() is necessary when using libi3.
|
* Having verboselog(), errorlog() and debuglog() is necessary when using libi3.
|
||||||
*
|
*
|
||||||
@ -453,7 +449,7 @@ static char *resolve_tilde(const char *path) {
|
|||||||
char *head, *tail, *result;
|
char *head, *tail, *result;
|
||||||
|
|
||||||
tail = strchr(path, '/');
|
tail = strchr(path, '/');
|
||||||
head = strndup(path, tail ? tail - path : strlen(path));
|
head = strndup(path, tail ? (size_t)(tail - path) : strlen(path));
|
||||||
|
|
||||||
int res = glob(head, GLOB_TILDE, NULL, &globbuf);
|
int res = glob(head, GLOB_TILDE, NULL, &globbuf);
|
||||||
free(head);
|
free(head);
|
||||||
@ -481,14 +477,14 @@ static char *resolve_tilde(const char *path) {
|
|||||||
static int handle_expose() {
|
static int handle_expose() {
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8};
|
xcb_rectangle_t border = {0, 0, 300, (15 * font.height) + 8};
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#000000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
||||||
|
|
||||||
set_font(&font);
|
set_font(&font);
|
||||||
|
|
||||||
#define txt(x, row, text) \
|
#define txt(x, row, text) \
|
||||||
draw_text_ascii(text, pixmap, pixmap_gc,\
|
draw_text_ascii(text, pixmap, pixmap_gc, \
|
||||||
x, (row - 1) * font.height + 4, 300 - x * 2)
|
x, (row - 1) * font.height + 4, 300 - x * 2)
|
||||||
|
|
||||||
if (current_step == STEP_WELCOME) {
|
if (current_step == STEP_WELCOME) {
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
@ -521,14 +517,16 @@ static int handle_expose() {
|
|||||||
/* the not-selected modifier */
|
/* the not-selected modifier */
|
||||||
if (modifier == MOD_Mod4)
|
if (modifier == MOD_Mod4)
|
||||||
txt(31, 5, "<Alt>");
|
txt(31, 5, "<Alt>");
|
||||||
else txt(31, 4, "<Win>");
|
else
|
||||||
|
txt(31, 4, "<Win>");
|
||||||
|
|
||||||
/* the selected modifier */
|
/* the selected modifier */
|
||||||
set_font(&bold_font);
|
set_font(&bold_font);
|
||||||
set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000"));
|
set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000"));
|
||||||
if (modifier == MOD_Mod4)
|
if (modifier == MOD_Mod4)
|
||||||
txt(10, 4, "-> <Win>");
|
txt(10, 4, "-> <Win>");
|
||||||
else txt(10, 5, "-> <Alt>");
|
else
|
||||||
|
txt(10, 5, "-> <Alt>");
|
||||||
|
|
||||||
/* green */
|
/* green */
|
||||||
set_font(&font);
|
set_font(&font);
|
||||||
@ -565,16 +563,16 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
|||||||
current_step = STEP_GENERATE;
|
current_step = STEP_GENERATE;
|
||||||
/* Set window title */
|
/* Set window title */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_NAME,
|
A__NET_WM_NAME,
|
||||||
A_UTF8_STRING,
|
A_UTF8_STRING,
|
||||||
8,
|
8,
|
||||||
strlen("i3: generate config"),
|
strlen("i3: generate config"),
|
||||||
"i3: generate config");
|
"i3: generate config");
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
}
|
} else
|
||||||
else finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cancel any time */
|
/* cancel any time */
|
||||||
@ -618,7 +616,7 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
|||||||
* Handle button presses to make clicking on "<win>" and "<alt>" work
|
* Handle button presses to make clicking on "<win>" and "<alt>" work
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_button_press(xcb_button_press_event_t* event) {
|
static void handle_button_press(xcb_button_press_event_t *event) {
|
||||||
if (current_step != STEP_GENERATE)
|
if (current_step != STEP_GENERATE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -667,7 +665,7 @@ static void finish() {
|
|||||||
fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config);
|
fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config);
|
||||||
fputs("# It will not be overwritten, so edit it as you like.\n", ks_config);
|
fputs("# It will not be overwritten, so edit it as you like.\n", ks_config);
|
||||||
fputs("#\n", ks_config);
|
fputs("#\n", ks_config);
|
||||||
fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config);
|
fputs("# Should you change your keyboard layout some time, delete\n", ks_config);
|
||||||
fputs("# this file and re-run i3-config-wizard(1).\n", ks_config);
|
fputs("# this file and re-run i3-config-wizard(1).\n", ks_config);
|
||||||
fputs("#\n", ks_config);
|
fputs("#\n", ks_config);
|
||||||
|
|
||||||
@ -701,7 +699,8 @@ static void finish() {
|
|||||||
if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
|
if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
|
||||||
if (modifier == MOD_Mod1)
|
if (modifier == MOD_Mod1)
|
||||||
fputs("set $mod Mod1\n", ks_config);
|
fputs("set $mod Mod1\n", ks_config);
|
||||||
else fputs("set $mod Mod4\n", ks_config);
|
else
|
||||||
|
fputs("set $mod Mod4\n", ks_config);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,7 +728,7 @@ static void finish() {
|
|||||||
|
|
||||||
/* tell i3 to reload the config file */
|
/* tell i3 to reload the config file */
|
||||||
int sockfd = ipc_connect(socket_path);
|
int sockfd = ipc_connect(socket_path);
|
||||||
ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload");
|
ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t *)"reload");
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -750,8 +749,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"prefix", required_argument, 0, 'p'},
|
{"prefix", required_argument, 0, 'p'},
|
||||||
{"font", required_argument, 0, 'f'},
|
{"font", required_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:vh";
|
char *options_string = "s:vh";
|
||||||
|
|
||||||
@ -810,11 +808,11 @@ int main(int argc, char *argv[]) {
|
|||||||
modmap_cookie = xcb_get_modifier_mapping(conn);
|
modmap_cookie = xcb_get_modifier_mapping(conn);
|
||||||
symbols = xcb_key_symbols_alloc(conn);
|
symbols = xcb_key_symbols_alloc(conn);
|
||||||
|
|
||||||
/* Place requests for the atoms we need as soon as possible */
|
/* Place requests for the atoms we need as soon as possible */
|
||||||
#define xmacro(atom) \
|
#define xmacro(atom) \
|
||||||
xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(conn, screen);
|
root_screen = xcb_aux_get_screen(conn, screen);
|
||||||
root = root_screen->root;
|
root = root_screen->root;
|
||||||
@ -832,54 +830,53 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
490, 297, 300, 205, /* dimensions */
|
490, 297, 300, 205, /* dimensions */
|
||||||
0, /* X11 border = 0, we draw our own */
|
0, /* X11 border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
0, /* back pixel: black */
|
0, /* back pixel: black */
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_BUTTON_PRESS
|
XCB_EVENT_MASK_BUTTON_PRESS});
|
||||||
});
|
|
||||||
|
|
||||||
/* Map the window (make it visible) */
|
/* Map the window (make it visible) */
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
|
|
||||||
/* Setup NetWM atoms */
|
/* Setup NetWM atoms */
|
||||||
#define xmacro(name) \
|
#define xmacro(name) \
|
||||||
do { \
|
do { \
|
||||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
|
||||||
if (!reply) \
|
if (!reply) \
|
||||||
errx(EXIT_FAILURE, "Could not get atom " # name "\n"); \
|
errx(EXIT_FAILURE, "Could not get atom " #name "\n"); \
|
||||||
\
|
\
|
||||||
A_ ## name = reply->atom; \
|
A_##name = reply->atom; \
|
||||||
free(reply); \
|
free(reply); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
/* Set dock mode */
|
/* Set dock mode */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_WINDOW_TYPE,
|
A__NET_WM_WINDOW_TYPE,
|
||||||
A_ATOM,
|
A_ATOM,
|
||||||
32,
|
32,
|
||||||
1,
|
1,
|
||||||
(unsigned char*) &A__NET_WM_WINDOW_TYPE_DIALOG);
|
(unsigned char *)&A__NET_WM_WINDOW_TYPE_DIALOG);
|
||||||
|
|
||||||
/* Set window title */
|
/* Set window title */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_NAME,
|
A__NET_WM_NAME,
|
||||||
A_UTF8_STRING,
|
A_UTF8_STRING,
|
||||||
8,
|
8,
|
||||||
strlen("i3: first configuration"),
|
strlen("i3: first configuration"),
|
||||||
"i3: first configuration");
|
"i3: first configuration");
|
||||||
|
|
||||||
/* Create pixmap */
|
/* Create pixmap */
|
||||||
pixmap = xcb_generate_id(conn);
|
pixmap = xcb_generate_id(conn);
|
||||||
@ -922,13 +919,13 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
|
handle_key_press(NULL, conn, (xcb_key_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* TODO: handle mappingnotify */
|
/* TODO: handle mappingnotify */
|
||||||
|
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
handle_button_press((xcb_button_press_event_t*)event);
|
handle_button_press((xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#ifndef I3_XCB_H
|
#pragma once
|
||||||
#define I3_XCB_H
|
|
||||||
|
|
||||||
/* from X11/keysymdef.h */
|
/* from X11/keysymdef.h */
|
||||||
#define XCB_NUM_LOCK 0xff7f
|
#define XCB_NUM_LOCK 0xff7f
|
||||||
@ -7,5 +6,3 @@
|
|||||||
#define xmacro(atom) xcb_atom_t A_ ## atom;
|
#define xmacro(atom) xcb_atom_t A_ ## atom;
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env perl
|
#!/usr/bin/env perl
|
||||||
# vim:ts=4:sw=4:expandtab
|
# vim:ts=4:sw=4:expandtab
|
||||||
#
|
#
|
||||||
# © 2012-2013 Michael Stapelberg
|
# © 2012-2014 Michael Stapelberg
|
||||||
#
|
#
|
||||||
# No dependencies except for perl ≥ v5.10
|
# No dependencies except for perl ≥ v5.10
|
||||||
|
|
||||||
@ -55,8 +55,12 @@ my $result = GetOptions(
|
|||||||
die "Could not parse command line options" unless $result;
|
die "Could not parse command line options" unless $result;
|
||||||
|
|
||||||
# Filter entry types and set default type(s) if none selected
|
# Filter entry types and set default type(s) if none selected
|
||||||
my @valid_types = ('name', 'command', 'filename');
|
my $valid_types = {
|
||||||
@entry_types = grep { $_ ~~ @valid_types } @entry_types;
|
name => 1,
|
||||||
|
command => 1,
|
||||||
|
filename => 1,
|
||||||
|
};
|
||||||
|
@entry_types = grep { exists($valid_types->{$_}) } @entry_types;
|
||||||
@entry_types = ('name', 'command') unless @entry_types;
|
@entry_types = ('name', 'command') unless @entry_types;
|
||||||
|
|
||||||
# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||||
@ -257,7 +261,7 @@ for my $app (keys %apps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('name' ~~ @entry_types) {
|
if ((scalar grep { $_ eq 'name' } @entry_types) > 0) {
|
||||||
if (exists($choices{$name})) {
|
if (exists($choices{$name})) {
|
||||||
# There are two .desktop files which contain the same “Name” value.
|
# There are two .desktop files which contain the same “Name” value.
|
||||||
# I’m not sure if that is allowed to happen, but we disambiguate the
|
# I’m not sure if that is allowed to happen, but we disambiguate the
|
||||||
@ -273,22 +277,22 @@ for my $app (keys %apps) {
|
|||||||
$choices{$name} = $app;
|
$choices{$name} = $app;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('command' ~~ @entry_types) {
|
if ((scalar grep { $_ eq 'command' } @entry_types) > 0) {
|
||||||
my ($command) = split(' ', $apps{$app}->{Exec});
|
my ($command) = split(' ', $apps{$app}->{Exec});
|
||||||
|
|
||||||
# Don’t add “geany” if “Geany” is already present.
|
# Don’t add “geany” if “Geany” is already present.
|
||||||
my @keys = map { lc } keys %choices;
|
my @keys = map { lc } keys %choices;
|
||||||
next if lc(basename($command)) ~~ @keys;
|
next if (scalar grep { $_ eq lc(basename($command)) } @keys) > 0;
|
||||||
|
|
||||||
$choices{basename($command)} = $app;
|
$choices{basename($command)} = $app;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('filename' ~~ @entry_types) {
|
if ((scalar grep { $_ eq 'filename' } @entry_types) > 0) {
|
||||||
my $filename = basename($app, '.desktop');
|
my $filename = basename($app, '.desktop');
|
||||||
|
|
||||||
# Don’t add “geany” if “Geany” is already present.
|
# Don’t add “geany” if “Geany” is already present.
|
||||||
my @keys = map { lc } keys %choices;
|
my @keys = map { lc } keys %choices;
|
||||||
next if lc($filename) ~~ @keys;
|
next if (scalar grep { $_ eq lc($filename) } @keys) > 0;
|
||||||
|
|
||||||
$choices{$filename} = $app;
|
$choices{$filename} = $app;
|
||||||
}
|
}
|
||||||
@ -376,6 +380,7 @@ sub quote {
|
|||||||
|
|
||||||
$choice = quote($choice);
|
$choice = quote($choice);
|
||||||
$location = quote($location);
|
$location = quote($location);
|
||||||
|
$name = quote($name);
|
||||||
|
|
||||||
# Remove deprecated field codes, as the spec dictates.
|
# Remove deprecated field codes, as the spec dictates.
|
||||||
$exec =~ s/%[dDnNvm]//g;
|
$exec =~ s/%[dDnNvm]//g;
|
||||||
|
@ -29,11 +29,11 @@
|
|||||||
#include <i3/ipc.h>
|
#include <i3/ipc.h>
|
||||||
|
|
||||||
static uint32_t offset_next_write,
|
static uint32_t offset_next_write,
|
||||||
wrap_count;
|
wrap_count;
|
||||||
|
|
||||||
static i3_shmlog_header *header;
|
static i3_shmlog_header *header;
|
||||||
static char *logbuffer,
|
static char *logbuffer,
|
||||||
*walk;
|
*walk;
|
||||||
|
|
||||||
static int check_for_wrap(void) {
|
static int check_for_wrap(void) {
|
||||||
if (wrap_count == header->wrap_count)
|
if (wrap_count == header->wrap_count)
|
||||||
@ -70,8 +70,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"verbose", no_argument, 0, 'V'},
|
{"verbose", no_argument, 0, 'V'},
|
||||||
{"follow", no_argument, 0, 'f'},
|
{"follow", no_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:vfVh";
|
char *options_string = "s:vfVh";
|
||||||
|
|
||||||
@ -139,7 +138,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (logbuffer == MAP_FAILED)
|
if (logbuffer == MAP_FAILED)
|
||||||
err(EXIT_FAILURE, "Could not mmap SHM segment for the i3 log");
|
err(EXIT_FAILURE, "Could not mmap SHM segment for the i3 log");
|
||||||
|
|
||||||
header = (i3_shmlog_header*)logbuffer;
|
header = (i3_shmlog_header *)logbuffer;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("next_write = %d, last_wrap = %d, logbuffer_size = %d, shmname = %s\n",
|
printf("next_write = %d, last_wrap = %d, logbuffer_size = %d, shmname = %s\n",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#ifndef I3_INPUT
|
#pragma once
|
||||||
#define I3_INPUT
|
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
|
||||||
@ -13,5 +12,3 @@
|
|||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
extern xcb_window_t root;
|
extern xcb_window_t root;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -103,7 +103,7 @@ static void restore_input_focus(void) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static uint8_t *concat_strings(char **glyphs, int max) {
|
static uint8_t *concat_strings(char **glyphs, int max) {
|
||||||
uint8_t *output = calloc(max+1, 4);
|
uint8_t *output = calloc(max + 1, 4);
|
||||||
uint8_t *walk = output;
|
uint8_t *walk = output;
|
||||||
for (int c = 0; c < max; c++) {
|
for (int c = 0; c < max; c++) {
|
||||||
printf("at %c\n", glyphs[c][0]);
|
printf("at %c\n", glyphs[c][0]);
|
||||||
@ -112,7 +112,7 @@ static uint8_t *concat_strings(char **glyphs, int max) {
|
|||||||
memcpy(walk, glyphs[c], 2);
|
memcpy(walk, glyphs[c], 2);
|
||||||
walk += 2;
|
walk += 2;
|
||||||
} else {
|
} else {
|
||||||
strcpy((char*)walk, glyphs[c]);
|
strcpy((char *)walk, glyphs[c]);
|
||||||
walk += strlen(glyphs[c]);
|
walk += strlen(glyphs[c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,9 +130,9 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t
|
|||||||
|
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4};
|
xcb_rectangle_t border = {0, 0, 500, font.height + 8}, inner = {2, 2, 496, font.height + 8 - 4};
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#FF0000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#FF0000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &border);
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ get_colorpixel("#000000") });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {get_colorpixel("#000000")});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner);
|
||||||
|
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
@ -143,8 +143,7 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t
|
|||||||
draw_text(prompt, pixmap, pixmap_gc, 4, 4, 492);
|
draw_text(prompt, pixmap, pixmap_gc, 4, 4, 492);
|
||||||
}
|
}
|
||||||
/* … and the text */
|
/* … and the text */
|
||||||
if (input_position > 0)
|
if (input_position > 0) {
|
||||||
{
|
|
||||||
i3String *input = i3string_from_ucs2(glyphs_ucs, input_position);
|
i3String *input = i3string_from_ucs2(glyphs_ucs, input_position);
|
||||||
draw_text(input, pixmap, pixmap_gc, prompt_offset + 4, 4, 492);
|
draw_text(input, pixmap, pixmap_gc, prompt_offset + 4, 4, 492);
|
||||||
i3string_free(input);
|
i3string_free(input);
|
||||||
@ -174,14 +173,14 @@ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_rel
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void finish_input() {
|
static void finish_input() {
|
||||||
char *command = (char*)concat_strings(glyphs_utf8, input_position);
|
char *command = (char *)concat_strings(glyphs_utf8, input_position);
|
||||||
|
|
||||||
/* count the occurences of %s in the string */
|
/* count the occurences of %s in the string */
|
||||||
int c;
|
int c;
|
||||||
int len = strlen(format);
|
int len = strlen(format);
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (c = 0; c < (len-1); c++)
|
for (c = 0; c < (len - 1); c++)
|
||||||
if (format[c] == '%' && format[c+1] == 's')
|
if (format[c] == '%' && format[c + 1] == 's')
|
||||||
cnt++;
|
cnt++;
|
||||||
printf("occurences = %d\n", cnt);
|
printf("occurences = %d\n", cnt);
|
||||||
|
|
||||||
@ -189,13 +188,13 @@ static void finish_input() {
|
|||||||
int inputlen = strlen(command);
|
int inputlen = strlen(command);
|
||||||
char *full = calloc(1,
|
char *full = calloc(1,
|
||||||
strlen(format) - (2 * cnt) /* format without all %s */
|
strlen(format) - (2 * cnt) /* format without all %s */
|
||||||
+ (inputlen * cnt) /* replaced %s */
|
+ (inputlen * cnt) /* replaced %s */
|
||||||
+ 1); /* trailing NUL */
|
+ 1); /* trailing NUL */
|
||||||
char *dest = full;
|
char *dest = full;
|
||||||
for (c = 0; c < len; c++) {
|
for (c = 0; c < len; c++) {
|
||||||
/* if this is not % or it is % but without a following 's',
|
/* if this is not % or it is % but without a following 's',
|
||||||
* just copy the character */
|
* just copy the character */
|
||||||
if (format[c] != '%' || (c == (len-1)) || format[c+1] != 's')
|
if (format[c] != '%' || (c == (len - 1)) || format[c + 1] != 's')
|
||||||
*(dest++) = format[c];
|
*(dest++) = format[c];
|
||||||
else {
|
else {
|
||||||
strncat(dest, command, inputlen);
|
strncat(dest, command, inputlen);
|
||||||
@ -212,7 +211,9 @@ static void finish_input() {
|
|||||||
|
|
||||||
xcb_aux_sync(conn);
|
xcb_aux_sync(conn);
|
||||||
|
|
||||||
ipc_send_message(sockfd, strlen(full), 0, (uint8_t*)full);
|
ipc_send_message(sockfd, strlen(full), 0, (uint8_t *)full);
|
||||||
|
|
||||||
|
free(full);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
free(command);
|
free(command);
|
||||||
@ -290,8 +291,8 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
|||||||
}
|
}
|
||||||
|
|
||||||
xcb_char2b_t inp;
|
xcb_char2b_t inp;
|
||||||
inp.byte1 = ( ucs & 0xff00 ) >> 2;
|
inp.byte1 = (ucs & 0xff00) >> 2;
|
||||||
inp.byte2 = ( ucs & 0x00ff ) >> 0;
|
inp.byte2 = (ucs & 0x00ff) >> 0;
|
||||||
|
|
||||||
printf("inp.byte1 = %02x, inp.byte2 = %02x\n", inp.byte1, inp.byte2);
|
printf("inp.byte1 = %02x, inp.byte2 = %02x\n", inp.byte1, inp.byte2);
|
||||||
/* convert it to UTF-8 */
|
/* convert it to UTF-8 */
|
||||||
@ -324,8 +325,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"format", required_argument, 0, 'F'},
|
{"format", required_argument, 0, 'F'},
|
||||||
{"font", required_argument, 0, 'f'},
|
{"font", required_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:p:P:f:l:F:vh";
|
char *options_string = "s:p:P:f:l:F:vh";
|
||||||
|
|
||||||
@ -403,18 +403,17 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
50, 50, 500, font.height + 8, /* dimensions */
|
50, 50, 500, font.height + 8, /* dimensions */
|
||||||
0, /* X11 border = 0, we draw our own */
|
0, /* X11 border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
0, /* back pixel: black */
|
0, /* back pixel: black */
|
||||||
1, /* override redirect: don’t manage this window */
|
1, /* override redirect: don’t manage this window */
|
||||||
XCB_EVENT_MASK_EXPOSURE
|
XCB_EVENT_MASK_EXPOSURE});
|
||||||
});
|
|
||||||
|
|
||||||
/* Map the window (make it visible) */
|
/* Map the window (make it visible) */
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
@ -465,15 +464,15 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
handle_key_press(NULL, conn, (xcb_key_press_event_t*)event);
|
handle_key_press(NULL, conn, (xcb_key_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_KEY_RELEASE:
|
case XCB_KEY_RELEASE:
|
||||||
handle_key_release(NULL, conn, (xcb_key_release_event_t*)event);
|
handle_key_release(NULL, conn, (xcb_key_release_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
handle_expose(NULL, conn, (xcb_expose_event_t*)event);
|
handle_expose(NULL, conn, (xcb_expose_event_t *)event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,20 +76,17 @@ static int reply_boolean_cb(void *params, int val) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int reply_string_cb(void *params, const unsigned char *val, size_t len) {
|
static int reply_string_cb(void *params, const unsigned char *val, size_t len) {
|
||||||
#else
|
|
||||||
static int reply_string_cb(void *params, const unsigned char *val, unsigned int len) {
|
|
||||||
#endif
|
|
||||||
char *str = scalloc(len + 1);
|
char *str = scalloc(len + 1);
|
||||||
strncpy(str, (const char*)val, len);
|
strncpy(str, (const char *)val, len);
|
||||||
if (strcmp(last_key, "error") == 0)
|
if (strcmp(last_key, "error") == 0)
|
||||||
last_reply.error = str;
|
last_reply.error = str;
|
||||||
else if (strcmp(last_key, "input") == 0)
|
else if (strcmp(last_key, "input") == 0)
|
||||||
last_reply.input = str;
|
last_reply.input = str;
|
||||||
else if (strcmp(last_key, "errorposition") == 0)
|
else if (strcmp(last_key, "errorposition") == 0)
|
||||||
last_reply.errorposition = str;
|
last_reply.errorposition = str;
|
||||||
else free(str);
|
else
|
||||||
|
free(str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,36 +103,25 @@ static int reply_end_map_cb(void *params) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int reply_map_key_cb(void *params, const unsigned char *keyVal, size_t keyLen) {
|
static int reply_map_key_cb(void *params, const unsigned char *keyVal, size_t keyLen) {
|
||||||
#else
|
|
||||||
static int reply_map_key_cb(void *params, const unsigned char *keyVal, unsigned keyLen) {
|
|
||||||
#endif
|
|
||||||
free(last_key);
|
free(last_key);
|
||||||
last_key = scalloc(keyLen + 1);
|
last_key = scalloc(keyLen + 1);
|
||||||
strncpy(last_key, (const char*)keyVal, keyLen);
|
strncpy(last_key, (const char *)keyVal, keyLen);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
yajl_callbacks reply_callbacks = {
|
static yajl_callbacks reply_callbacks = {
|
||||||
NULL,
|
.yajl_boolean = reply_boolean_cb,
|
||||||
&reply_boolean_cb,
|
.yajl_string = reply_string_cb,
|
||||||
NULL,
|
.yajl_start_map = reply_start_map_cb,
|
||||||
NULL,
|
.yajl_map_key = reply_map_key_cb,
|
||||||
NULL,
|
.yajl_end_map = reply_end_map_cb,
|
||||||
&reply_string_cb,
|
|
||||||
&reply_start_map_cb,
|
|
||||||
&reply_map_key_cb,
|
|
||||||
&reply_end_map_cb,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
socket_path = getenv("I3SOCK");
|
socket_path = getenv("I3SOCK");
|
||||||
int o, option_index = 0;
|
int o, option_index = 0;
|
||||||
int message_type = I3_IPC_MESSAGE_TYPE_COMMAND;
|
uint32_t message_type = I3_IPC_MESSAGE_TYPE_COMMAND;
|
||||||
char *payload = NULL;
|
char *payload = NULL;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
|
|
||||||
@ -145,8 +131,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
{"quiet", no_argument, 0, 'q'},
|
{"quiet", no_argument, 0, 'q'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "s:t:vhq";
|
char *options_string = "s:t:vhq";
|
||||||
|
|
||||||
@ -221,10 +206,10 @@ int main(int argc, char *argv[]) {
|
|||||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_LOCAL;
|
addr.sun_family = AF_LOCAL;
|
||||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||||
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
|
if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||||
err(EXIT_FAILURE, "Could not connect to i3 on socket \"%s\"", socket_path);
|
err(EXIT_FAILURE, "Could not connect to i3 on socket \"%s\"", socket_path);
|
||||||
|
|
||||||
if (ipc_send_message(sockfd, strlen(payload), message_type, (uint8_t*)payload) == -1)
|
if (ipc_send_message(sockfd, strlen(payload), message_type, (uint8_t *)payload) == -1)
|
||||||
err(EXIT_FAILURE, "IPC: write()");
|
err(EXIT_FAILURE, "IPC: write()");
|
||||||
|
|
||||||
if (quiet)
|
if (quiet)
|
||||||
@ -245,21 +230,12 @@ int main(int argc, char *argv[]) {
|
|||||||
* If not, nicely format the error message. */
|
* If not, nicely format the error message. */
|
||||||
if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND) {
|
if (reply_type == I3_IPC_MESSAGE_TYPE_COMMAND) {
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
handle = yajl_alloc(&reply_callbacks, &parse_conf, NULL, NULL);
|
|
||||||
#else
|
|
||||||
handle = yajl_alloc(&reply_callbacks, NULL, NULL);
|
handle = yajl_alloc(&reply_callbacks, NULL, NULL);
|
||||||
#endif
|
yajl_status state = yajl_parse(handle, (const unsigned char *)reply, reply_length);
|
||||||
yajl_status state = yajl_parse(handle, (const unsigned char*)reply, reply_length);
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case yajl_status_ok:
|
case yajl_status_ok:
|
||||||
break;
|
break;
|
||||||
case yajl_status_client_canceled:
|
case yajl_status_client_canceled:
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
case yajl_status_insufficient_data:
|
|
||||||
#endif
|
|
||||||
case yajl_status_error:
|
case yajl_status_error:
|
||||||
errx(EXIT_FAILURE, "IPC: Could not parse JSON reply.");
|
errx(EXIT_FAILURE, "IPC: Could not parse JSON reply.");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#ifndef I3_NAGBAR
|
#pragma once
|
||||||
#define I3_NAGBAR
|
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
|
||||||
@ -17,5 +16,3 @@ while (0)
|
|||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
extern xcb_window_t root;
|
extern xcb_window_t root;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
159
i3-nagbar/main.c
159
i3-nagbar/main.c
@ -43,7 +43,7 @@ typedef struct {
|
|||||||
static xcb_window_t win;
|
static xcb_window_t win;
|
||||||
static xcb_pixmap_t pixmap;
|
static xcb_pixmap_t pixmap;
|
||||||
static xcb_gcontext_t pixmap_gc;
|
static xcb_gcontext_t pixmap_gc;
|
||||||
static xcb_rectangle_t rect = { 0, 0, 600, 20 };
|
static xcb_rectangle_t rect = {0, 0, 600, 20};
|
||||||
static i3Font font;
|
static i3Font font;
|
||||||
static i3String *prompt;
|
static i3String *prompt;
|
||||||
static button_t *buttons;
|
static button_t *buttons;
|
||||||
@ -100,7 +100,7 @@ static void start_application(const char *command) {
|
|||||||
setsid();
|
setsid();
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
/* This is the child */
|
/* This is the child */
|
||||||
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void*)NULL);
|
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void *)NULL);
|
||||||
/* not reached */
|
/* not reached */
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -118,7 +118,7 @@ static button_t *get_button_at(int16_t x, int16_t y) {
|
|||||||
|
|
||||||
static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t *event) {
|
static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t *event) {
|
||||||
printf("button pressed on x = %d, y = %d\n",
|
printf("button pressed on x = %d, y = %d\n",
|
||||||
event->event_x, event->event_y);
|
event->event_x, event->event_y);
|
||||||
/* TODO: set a flag for the button, re-render */
|
/* TODO: set a flag for the button, re-render */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t
|
|||||||
*/
|
*/
|
||||||
static void handle_button_release(xcb_connection_t *conn, xcb_button_release_event_t *event) {
|
static void handle_button_release(xcb_connection_t *conn, xcb_button_release_event_t *event) {
|
||||||
printf("button released on x = %d, y = %d\n",
|
printf("button released on x = %d, y = %d\n",
|
||||||
event->event_x, event->event_y);
|
event->event_x, event->event_y);
|
||||||
/* If the user hits the close button, we exit(0) */
|
/* If the user hits the close button, we exit(0) */
|
||||||
if (event->event_x >= (rect.width - 32))
|
if (event->event_x >= (rect.width - 32))
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -188,13 +188,13 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve
|
|||||||
*/
|
*/
|
||||||
static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
||||||
/* re-draw the background */
|
/* re-draw the background */
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_background });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_background});
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect);
|
||||||
|
|
||||||
/* restore font color */
|
/* restore font color */
|
||||||
set_font_colors(pixmap_gc, color_text, color_background);
|
set_font_colors(pixmap_gc, color_text, color_background);
|
||||||
draw_text(prompt, pixmap, pixmap_gc,
|
draw_text(prompt, pixmap, pixmap_gc,
|
||||||
4 + 4, 4 + 4, rect.width - 4 - 4);
|
4 + 4, 4 + 4, rect.width - 4 - 4);
|
||||||
|
|
||||||
/* render close button */
|
/* render close button */
|
||||||
const char *close_button_label = "X";
|
const char *close_button_label = "X";
|
||||||
@ -209,24 +209,23 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
values[1] = line_width;
|
values[1] = line_width;
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
||||||
|
|
||||||
xcb_rectangle_t close = { y - w - (2 * line_width), 0, w + (2 * line_width), rect.height };
|
xcb_rectangle_t close = {y - w - (2 * line_width), 0, w + (2 * line_width), rect.height};
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
||||||
|
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_border });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border});
|
||||||
xcb_point_t points[] = {
|
xcb_point_t points[] = {
|
||||||
{ y - w - (2 * line_width), line_width / 2 },
|
{y - w - (2 * line_width), line_width / 2},
|
||||||
{ y - (line_width / 2), line_width / 2 },
|
{y - (line_width / 2), line_width / 2},
|
||||||
{ y - (line_width / 2), (rect.height - (line_width / 2)) - 2 },
|
{y - (line_width / 2), (rect.height - (line_width / 2)) - 2},
|
||||||
{ y - w - (2 * line_width), (rect.height - (line_width / 2)) - 2 },
|
{y - w - (2 * line_width), (rect.height - (line_width / 2)) - 2},
|
||||||
{ y - w - (2 * line_width), line_width / 2 }
|
{y - w - (2 * line_width), line_width / 2}};
|
||||||
};
|
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points);
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points);
|
||||||
|
|
||||||
values[0] = 1;
|
values[0] = 1;
|
||||||
set_font_colors(pixmap_gc, color_text, color_button_background);
|
set_font_colors(pixmap_gc, color_text, color_button_background);
|
||||||
/* the x term here seems to set left/right padding */
|
/* the x term here seems to set left/right padding */
|
||||||
draw_text_ascii(close_button_label, pixmap, pixmap_gc, y - w - line_width + w / 2 - 4,
|
draw_text_ascii(close_button_label, pixmap, pixmap_gc, y - w - line_width + w / 2 - 4,
|
||||||
4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4);
|
4 + 4 - 1, rect.width - y + w + line_width - w / 2 + 4);
|
||||||
y -= w;
|
y -= w;
|
||||||
|
|
||||||
y -= 20;
|
y -= 20;
|
||||||
@ -239,20 +238,19 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
/* account for left/right padding, which seems to be set to 12px (total) below */
|
/* account for left/right padding, which seems to be set to 12px (total) below */
|
||||||
w += 12;
|
w += 12;
|
||||||
y -= 30;
|
y -= 30;
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_button_background });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_button_background});
|
||||||
close = (xcb_rectangle_t){ y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6 };
|
close = (xcb_rectangle_t) {y - w - (2 * line_width), 2, w + (2 * line_width), rect.height - 6};
|
||||||
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close);
|
||||||
|
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){ color_border });
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]) {color_border});
|
||||||
buttons[c].x = y - w - (2 * line_width);
|
buttons[c].x = y - w - (2 * line_width);
|
||||||
buttons[c].width = w;
|
buttons[c].width = w;
|
||||||
xcb_point_t points2[] = {
|
xcb_point_t points2[] = {
|
||||||
{ y - w - (2 * line_width), (line_width / 2) + 2 },
|
{y - w - (2 * line_width), (line_width / 2) + 2},
|
||||||
{ y - (line_width / 2), (line_width / 2) + 2 },
|
{y - (line_width / 2), (line_width / 2) + 2},
|
||||||
{ y - (line_width / 2), (rect.height - 4 - (line_width / 2)) },
|
{y - (line_width / 2), (rect.height - 4 - (line_width / 2))},
|
||||||
{ y - w - (2 * line_width), (rect.height - 4 - (line_width / 2)) },
|
{y - w - (2 * line_width), (rect.height - 4 - (line_width / 2))},
|
||||||
{ y - w - (2 * line_width), (line_width / 2) + 2 }
|
{y - w - (2 * line_width), (line_width / 2) + 2}};
|
||||||
};
|
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2);
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2);
|
||||||
|
|
||||||
values[0] = color_text;
|
values[0] = color_text;
|
||||||
@ -260,7 +258,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
set_font_colors(pixmap_gc, color_text, color_button_background);
|
set_font_colors(pixmap_gc, color_text, color_button_background);
|
||||||
/* the x term seems to set left/right padding */
|
/* the x term seems to set left/right padding */
|
||||||
draw_text(buttons[c].label, pixmap, pixmap_gc,
|
draw_text(buttons[c].label, pixmap, pixmap_gc,
|
||||||
y - w - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6);
|
y - w - line_width + 6, 4 + 3, rect.width - y + w + line_width - 6);
|
||||||
|
|
||||||
y -= w;
|
y -= w;
|
||||||
}
|
}
|
||||||
@ -271,12 +269,10 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) {
|
|||||||
values[1] = line_width;
|
values[1] = line_width;
|
||||||
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values);
|
||||||
xcb_point_t bottom[] = {
|
xcb_point_t bottom[] = {
|
||||||
{ 0, rect.height - 0 },
|
{0, rect.height - 0},
|
||||||
{ rect.width, rect.height - 0 }
|
{rect.width, rect.height - 0}};
|
||||||
};
|
|
||||||
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 2, bottom);
|
xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 2, bottom);
|
||||||
|
|
||||||
|
|
||||||
/* Copy the contents of the pixmap to the real window */
|
/* Copy the contents of the pixmap to the real window */
|
||||||
xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, rect.width, rect.height);
|
xcb_copy_area(conn, pixmap, win, pixmap_gc, 0, 0, 0, 0, rect.width, rect.height);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
@ -322,7 +318,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1");
|
char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1");
|
||||||
int o, option_index = 0;
|
int o, option_index = 0;
|
||||||
enum { TYPE_ERROR = 0, TYPE_WARNING = 1 } bar_type = TYPE_ERROR;
|
enum { TYPE_ERROR = 0,
|
||||||
|
TYPE_WARNING = 1 } bar_type = TYPE_ERROR;
|
||||||
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
@ -331,8 +328,7 @@ int main(int argc, char *argv[]) {
|
|||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"message", required_argument, 0, 'm'},
|
{"message", required_argument, 0, 'm'},
|
||||||
{"type", required_argument, 0, 't'},
|
{"type", required_argument, 0, 't'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
char *options_string = "b:f:m:t:vh";
|
char *options_string = "b:f:m:t:vh";
|
||||||
|
|
||||||
@ -341,7 +337,7 @@ int main(int argc, char *argv[]) {
|
|||||||
while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) {
|
while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'v':
|
case 'v':
|
||||||
printf("i3-nagbar " I3_VERSION);
|
printf("i3-nagbar " I3_VERSION "\n");
|
||||||
return 0;
|
return 0;
|
||||||
case 'f':
|
case 'f':
|
||||||
FREE(pattern);
|
FREE(pattern);
|
||||||
@ -363,8 +359,8 @@ int main(int argc, char *argv[]) {
|
|||||||
buttons[buttoncnt].label = i3string_from_utf8(optarg);
|
buttons[buttoncnt].label = i3string_from_utf8(optarg);
|
||||||
buttons[buttoncnt].action = argv[optind];
|
buttons[buttoncnt].action = argv[optind];
|
||||||
printf("button with label *%s* and action *%s*\n",
|
printf("button with label *%s* and action *%s*\n",
|
||||||
i3string_as_utf8(buttons[buttoncnt].label),
|
i3string_as_utf8(buttons[buttoncnt].label),
|
||||||
buttons[buttoncnt].action);
|
buttons[buttoncnt].action);
|
||||||
buttoncnt++;
|
buttoncnt++;
|
||||||
printf("now %d buttons\n", buttoncnt);
|
printf("now %d buttons\n", buttoncnt);
|
||||||
if (optind < argc)
|
if (optind < argc)
|
||||||
@ -378,11 +374,11 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_connection_has_error(conn))
|
xcb_connection_has_error(conn))
|
||||||
die("Cannot open display\n");
|
die("Cannot open display\n");
|
||||||
|
|
||||||
/* Place requests for the atoms we need as soon as possible */
|
/* Place requests for the atoms we need as soon as possible */
|
||||||
#define xmacro(atom) \
|
#define xmacro(atom) \
|
||||||
xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(conn, screens);
|
root_screen = xcb_aux_get_screen(conn, screens);
|
||||||
root = root_screen->root;
|
root = root_screen->root;
|
||||||
@ -412,46 +408,45 @@ int main(int argc, char *argv[]) {
|
|||||||
xcb_create_window(
|
xcb_create_window(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
win, /* the window id */
|
win, /* the window id */
|
||||||
root, /* parent == root */
|
root, /* parent == root */
|
||||||
50, 50, 500, font.height + 8 + 8 /* 8 px padding */, /* dimensions */
|
50, 50, 500, font.height + 8 + 8 /* 8 px padding */, /* dimensions */
|
||||||
0, /* x11 border = 0, we draw our own */
|
0, /* x11 border = 0, we draw our own */
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
||||||
(uint32_t[]){
|
(uint32_t[]) {
|
||||||
0, /* back pixel: black */
|
0, /* back pixel: black */
|
||||||
XCB_EVENT_MASK_EXPOSURE |
|
XCB_EVENT_MASK_EXPOSURE |
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
||||||
XCB_EVENT_MASK_BUTTON_PRESS |
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
||||||
XCB_EVENT_MASK_BUTTON_RELEASE
|
XCB_EVENT_MASK_BUTTON_RELEASE});
|
||||||
});
|
|
||||||
|
|
||||||
/* Map the window (make it visible) */
|
/* Map the window (make it visible) */
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
|
|
||||||
/* Setup NetWM atoms */
|
/* Setup NetWM atoms */
|
||||||
#define xmacro(name) \
|
#define xmacro(name) \
|
||||||
do { \
|
do { \
|
||||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
|
||||||
if (!reply) \
|
if (!reply) \
|
||||||
die("Could not get atom " # name "\n"); \
|
die("Could not get atom " #name "\n"); \
|
||||||
\
|
\
|
||||||
A_ ## name = reply->atom; \
|
A_##name = reply->atom; \
|
||||||
free(reply); \
|
free(reply); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#include "atoms.xmacro"
|
#include "atoms.xmacro"
|
||||||
#undef xmacro
|
#undef xmacro
|
||||||
|
|
||||||
/* Set dock mode */
|
/* Set dock mode */
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_WINDOW_TYPE,
|
A__NET_WM_WINDOW_TYPE,
|
||||||
A_ATOM,
|
A_ATOM,
|
||||||
32,
|
32,
|
||||||
1,
|
1,
|
||||||
(unsigned char*) &A__NET_WM_WINDOW_TYPE_DOCK);
|
(unsigned char *)&A__NET_WM_WINDOW_TYPE_DOCK);
|
||||||
|
|
||||||
/* Reserve some space at the top of the screen */
|
/* Reserve some space at the top of the screen */
|
||||||
struct {
|
struct {
|
||||||
@ -467,20 +462,21 @@ int main(int argc, char *argv[]) {
|
|||||||
uint32_t top_end_x;
|
uint32_t top_end_x;
|
||||||
uint32_t bottom_start_x;
|
uint32_t bottom_start_x;
|
||||||
uint32_t bottom_end_x;
|
uint32_t bottom_end_x;
|
||||||
} __attribute__((__packed__)) strut_partial = {0,};
|
} __attribute__((__packed__)) strut_partial;
|
||||||
|
memset(&strut_partial, 0, sizeof(strut_partial));
|
||||||
|
|
||||||
strut_partial.top = font.height + 6;
|
strut_partial.top = font.height + 6;
|
||||||
strut_partial.top_start_x = 0;
|
strut_partial.top_start_x = 0;
|
||||||
strut_partial.top_end_x = 800;
|
strut_partial.top_end_x = 800;
|
||||||
|
|
||||||
xcb_change_property(conn,
|
xcb_change_property(conn,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
win,
|
win,
|
||||||
A__NET_WM_STRUT_PARTIAL,
|
A__NET_WM_STRUT_PARTIAL,
|
||||||
A_CARDINAL,
|
A_CARDINAL,
|
||||||
32,
|
32,
|
||||||
12,
|
12,
|
||||||
&strut_partial);
|
&strut_partial);
|
||||||
|
|
||||||
/* Create pixmap */
|
/* Create pixmap */
|
||||||
pixmap = xcb_generate_id(conn);
|
pixmap = xcb_generate_id(conn);
|
||||||
@ -503,25 +499,24 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
handle_expose(conn, (xcb_expose_event_t*)event);
|
handle_expose(conn, (xcb_expose_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
handle_button_press(conn, (xcb_button_press_event_t*)event);
|
handle_button_press(conn, (xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_BUTTON_RELEASE:
|
case XCB_BUTTON_RELEASE:
|
||||||
handle_button_release(conn, (xcb_button_release_event_t*)event);
|
handle_button_release(conn, (xcb_button_release_event_t *)event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCB_CONFIGURE_NOTIFY: {
|
case XCB_CONFIGURE_NOTIFY: {
|
||||||
xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t*)event;
|
xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t *)event;
|
||||||
rect = (xcb_rectangle_t){
|
rect = (xcb_rectangle_t) {
|
||||||
configure_notify->x,
|
configure_notify->x,
|
||||||
configure_notify->y,
|
configure_notify->y,
|
||||||
configure_notify->width,
|
configure_notify->width,
|
||||||
configure_notify->height
|
configure_notify->height};
|
||||||
};
|
|
||||||
|
|
||||||
/* Recreate the pixmap / gc */
|
/* Recreate the pixmap / gc */
|
||||||
xcb_free_pixmap(conn, pixmap);
|
xcb_free_pixmap(conn, pixmap);
|
||||||
|
288
i3-save-tree
Executable file
288
i3-save-tree
Executable file
@ -0,0 +1,288 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
# vim:ts=4:sw=4:expandtab
|
||||||
|
#
|
||||||
|
# © 2013-2014 Michael Stapelberg
|
||||||
|
#
|
||||||
|
# Requires perl ≥ v5.10, AnyEvent::I3 and JSON::XS
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings qw(FATAL utf8);
|
||||||
|
use Data::Dumper;
|
||||||
|
use IPC::Open2;
|
||||||
|
use POSIX qw(locale_h);
|
||||||
|
use File::Find;
|
||||||
|
use File::Basename qw(basename);
|
||||||
|
use File::Temp qw(tempfile);
|
||||||
|
use Getopt::Long;
|
||||||
|
use Pod::Usage;
|
||||||
|
use AnyEvent::I3;
|
||||||
|
use JSON::XS;
|
||||||
|
use List::Util qw(first);
|
||||||
|
use v5.10;
|
||||||
|
use utf8;
|
||||||
|
use open ':encoding(UTF-8)';
|
||||||
|
|
||||||
|
binmode STDOUT, ':utf8';
|
||||||
|
binmode STDERR, ':utf8';
|
||||||
|
|
||||||
|
my $workspace;
|
||||||
|
my $output;
|
||||||
|
my $result = GetOptions(
|
||||||
|
'workspace=s' => \$workspace,
|
||||||
|
'output=s' => \$output,
|
||||||
|
'version' => sub {
|
||||||
|
say "i3-save-tree 0.1 © 2013 Michael Stapelberg";
|
||||||
|
exit 0;
|
||||||
|
},
|
||||||
|
'help' => sub {
|
||||||
|
pod2usage(-exitval => 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
die "Could not parse command line options" unless $result;
|
||||||
|
|
||||||
|
if (!defined($workspace) && !defined($output)) {
|
||||||
|
die "One of --workspace or --output need to be specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (defined($workspace) ^ defined($output)) {
|
||||||
|
die "Only one of --workspace or --output can be specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $i3 = i3();
|
||||||
|
if (!$i3->connect->recv) {
|
||||||
|
die "Could not connect to i3";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub filter_containers {
|
||||||
|
my ($tree, $pred) = @_;
|
||||||
|
|
||||||
|
$_ = $tree;
|
||||||
|
return $tree if $pred->();
|
||||||
|
|
||||||
|
for my $child (@{$tree->{nodes}}, @{$tree->{floating_nodes}}) {
|
||||||
|
my $result = filter_containers($child, $pred);
|
||||||
|
return $result if defined($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub leaf_node {
|
||||||
|
my ($tree) = @_;
|
||||||
|
|
||||||
|
return $tree->{type} eq 'con' &&
|
||||||
|
@{$tree->{nodes}} == 0 &&
|
||||||
|
@{$tree->{floating_nodes}} == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
my %allowed_keys = map { ($_, 1) } qw(
|
||||||
|
type
|
||||||
|
fullscreen_mode
|
||||||
|
layout
|
||||||
|
border
|
||||||
|
current_border_width
|
||||||
|
floating
|
||||||
|
percent
|
||||||
|
nodes
|
||||||
|
floating_nodes
|
||||||
|
name
|
||||||
|
geometry
|
||||||
|
window_properties
|
||||||
|
);
|
||||||
|
|
||||||
|
sub strip_containers {
|
||||||
|
my ($tree) = @_;
|
||||||
|
|
||||||
|
# layout is not relevant for a leaf container
|
||||||
|
delete $tree->{layout} if leaf_node($tree);
|
||||||
|
|
||||||
|
# fullscreen_mode conveys no state at all, it can either be 0 or 1 and the
|
||||||
|
# default is _always_ 0, so skip noop entries.
|
||||||
|
delete $tree->{fullscreen_mode} if $tree->{fullscreen_mode} == 0;
|
||||||
|
|
||||||
|
# names for non-leafs are auto-generated and useful only for i3 debugging
|
||||||
|
delete $tree->{name} unless leaf_node($tree);
|
||||||
|
|
||||||
|
delete $tree->{geometry} if zero_rect($tree->{geometry});
|
||||||
|
|
||||||
|
delete $tree->{current_border_width} if $tree->{current_border_width} == -1;
|
||||||
|
|
||||||
|
for my $key (keys %$tree) {
|
||||||
|
next if exists($allowed_keys{$key});
|
||||||
|
|
||||||
|
delete $tree->{$key};
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $key (qw(nodes floating_nodes)) {
|
||||||
|
$tree->{$key} = [ map { strip_containers($_) } @{$tree->{$key}} ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $json_xs = JSON::XS->new->pretty(1)->allow_nonref->space_before(0)->canonical(1);
|
||||||
|
|
||||||
|
sub zero_rect {
|
||||||
|
my ($rect) = @_;
|
||||||
|
return $rect->{x} == 0 &&
|
||||||
|
$rect->{y} == 0 &&
|
||||||
|
$rect->{width} == 0 &&
|
||||||
|
$rect->{height} == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Dumps the containers in JSON, but with comments to explain the user what she
|
||||||
|
# needs to fix.
|
||||||
|
sub dump_containers {
|
||||||
|
my ($tree, $ws, $last) = @_;
|
||||||
|
|
||||||
|
$ws //= "";
|
||||||
|
|
||||||
|
say $ws . '{';
|
||||||
|
|
||||||
|
$ws .= (' ' x 4);
|
||||||
|
|
||||||
|
if (!leaf_node($tree)) {
|
||||||
|
my $desc = $tree->{layout} . ' split container';
|
||||||
|
if ($tree->{type} ne 'con') {
|
||||||
|
$desc = $tree->{type};
|
||||||
|
}
|
||||||
|
say "$ws// $desc with " . @{$tree->{nodes}} . " children";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Turn “window_properties” into “swallows” expressions, but only for leaf
|
||||||
|
# nodes. It only makes sense for leaf nodes to swallow anything.
|
||||||
|
if (leaf_node($tree)) {
|
||||||
|
my $swallows = {};
|
||||||
|
for my $property (keys %{$tree->{window_properties}}) {
|
||||||
|
$swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$';
|
||||||
|
}
|
||||||
|
$tree->{swallows} = [ $swallows ];
|
||||||
|
}
|
||||||
|
delete $tree->{window_properties};
|
||||||
|
|
||||||
|
my @keys = sort keys %$tree;
|
||||||
|
for (0 .. (@keys-1)) {
|
||||||
|
my $key = $keys[$_];
|
||||||
|
# Those are handled recursively, not printed.
|
||||||
|
next if $key eq 'nodes' || $key eq 'floating_nodes';
|
||||||
|
|
||||||
|
# JSON::XS’s encode appends a newline
|
||||||
|
chomp(my $val = $json_xs->encode($tree->{$key}));
|
||||||
|
|
||||||
|
# Fix indentation. Keep in mind we are producing output to be
|
||||||
|
# read/modified by a human.
|
||||||
|
$val =~ s/^/$ws/mg;
|
||||||
|
$val =~ s/^\s+//;
|
||||||
|
|
||||||
|
# Comment out all swallows criteria, they are just suggestions.
|
||||||
|
if ($key eq 'swallows') {
|
||||||
|
$val =~ s,^(\s*)\s{3}",\1// ",gm;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Append a comma unless this is the last value.
|
||||||
|
# Ugly, but necessary so that we can print all values before recursing.
|
||||||
|
my $comma = ($_ == (@keys-1) &&
|
||||||
|
@{$tree->{nodes}} == 0 &&
|
||||||
|
@{$tree->{floating_nodes}} == 0 ? '' : ',');
|
||||||
|
say qq#$ws"$key": $val$comma#;
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $key (qw(nodes floating_nodes)) {
|
||||||
|
my $num = scalar @{$tree->{$key}};
|
||||||
|
next if !$num;
|
||||||
|
|
||||||
|
say qq#$ws"$key": [#;
|
||||||
|
for (0 .. ($num-1)) {
|
||||||
|
dump_containers(
|
||||||
|
$tree->{$key}->[$_],
|
||||||
|
$ws . (' ' x 4),
|
||||||
|
($_ == ($num-1)));
|
||||||
|
}
|
||||||
|
say qq#$ws]#;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ws =~ s/\s{4}$//;
|
||||||
|
|
||||||
|
say $ws . ($last ? '}' : '},');
|
||||||
|
}
|
||||||
|
|
||||||
|
my $tree = $i3->get_tree->recv;
|
||||||
|
|
||||||
|
my $dump;
|
||||||
|
if (defined($workspace)) {
|
||||||
|
$dump = filter_containers($tree, sub {
|
||||||
|
$_->{type} eq 'workspace' && $_->{name} eq $workspace
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$dump = filter_containers($tree, sub {
|
||||||
|
$_->{type} eq 'output' && $_->{name} eq $output
|
||||||
|
});
|
||||||
|
# Get the output’s content container (living beneath dockarea containers).
|
||||||
|
$dump = first { $_->{type} eq 'con' } @{$dump->{nodes}};
|
||||||
|
}
|
||||||
|
|
||||||
|
$dump = strip_containers($dump);
|
||||||
|
|
||||||
|
say "// vim:ts=4:sw=4:et";
|
||||||
|
for my $key (qw(nodes floating_nodes)) {
|
||||||
|
for (0 .. (@{$dump->{$key}} - 1)) {
|
||||||
|
dump_containers($dump->{$key}->[$_], undef, 1);
|
||||||
|
# Newlines separate containers so that one can use { and } in vim to
|
||||||
|
# jump out of the current container.
|
||||||
|
say '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
=encoding utf-8
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
i3-save-tree - save (parts of) the layout tree for restoring
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
i3-save-tree [--workspace=name] [--output=name]
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Dumps a workspace (or an entire output) to stdout. The data is supposed to be
|
||||||
|
edited a bit by a human, then later fed to i3 via the append_layout command.
|
||||||
|
|
||||||
|
The append_layout command will create placeholder windows, arranged in the
|
||||||
|
layout the input file specifies. Each container should have a swallows
|
||||||
|
specification. When a window is mapped (made visible on the screen) that
|
||||||
|
matches the specification, i3 will put it into that place and kill the
|
||||||
|
placeholder.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item B<--workspace=name>
|
||||||
|
|
||||||
|
Specifies the workspace that should be dumped, e.g. 1. Either this or --output
|
||||||
|
need to be specified.
|
||||||
|
|
||||||
|
=item B<--output=name>
|
||||||
|
|
||||||
|
Specifies the output that should be dumped, e.g. LVDS-1. Either this or
|
||||||
|
--workspace need to be specified.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 VERSION
|
||||||
|
|
||||||
|
Version 0.1
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Michael Stapelberg, C<< <michael at i3wm.org> >>
|
||||||
|
|
||||||
|
=head1 LICENSE AND COPYRIGHT
|
||||||
|
|
||||||
|
Copyright 2013 Michael Stapelberg.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the BSD license.
|
||||||
|
|
||||||
|
=cut
|
46
i3.config
46
i3.config
@ -10,13 +10,23 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Font for window titles. Will also be used by the bar unless a different font
|
# Font for window titles. Will also be used by the bar unless a different font
|
||||||
# is used in the bar {} block below. ISO 10646 = Unicode
|
# is used in the bar {} block below.
|
||||||
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
# This font is widely installed, provides lots of unicode glyphs, right-to-left
|
||||||
|
# text rendering and scalability on retina/hidpi displays (thanks to pango).
|
||||||
|
font pango:DejaVu Sans Mono 8
|
||||||
|
# Before i3 v4.8, we used to recommend this one as the default:
|
||||||
|
# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
# The font above is very space-efficient, that is, it looks good, sharp and
|
# The font above is very space-efficient, that is, it looks good, sharp and
|
||||||
# clear in small sizes. However, if you need a lot of unicode glyphs or
|
# clear in small sizes. However, its unicode glyph coverage is limited, the old
|
||||||
# right-to-left text rendering, you should instead use pango for rendering and
|
# X core fonts rendering does not support right-to-left and this being a bitmap
|
||||||
# chose a FreeType font, such as:
|
# font, it doesn’t scale on retina/hidpi displays.
|
||||||
# font pango:DejaVu Sans Mono 10
|
|
||||||
|
# use these keys for focus, movement, and resize directions when reaching for
|
||||||
|
# the arrows is not convenient
|
||||||
|
set $up l
|
||||||
|
set $down k
|
||||||
|
set $left j
|
||||||
|
set $right semicolon
|
||||||
|
|
||||||
# use Mouse+Mod1 to drag floating windows to their wanted position
|
# use Mouse+Mod1 to drag floating windows to their wanted position
|
||||||
floating_modifier Mod1
|
floating_modifier Mod1
|
||||||
@ -35,10 +45,10 @@ bindsym Mod1+d exec dmenu_run
|
|||||||
# bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop
|
# bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop
|
||||||
|
|
||||||
# change focus
|
# change focus
|
||||||
bindsym Mod1+j focus left
|
bindsym Mod1+$left focus left
|
||||||
bindsym Mod1+k focus down
|
bindsym Mod1+$down focus down
|
||||||
bindsym Mod1+l focus up
|
bindsym Mod1+$up focus up
|
||||||
bindsym Mod1+semicolon focus right
|
bindsym Mod1+$right focus right
|
||||||
|
|
||||||
# alternatively, you can use the cursor keys:
|
# alternatively, you can use the cursor keys:
|
||||||
bindsym Mod1+Left focus left
|
bindsym Mod1+Left focus left
|
||||||
@ -47,10 +57,10 @@ bindsym Mod1+Up focus up
|
|||||||
bindsym Mod1+Right focus right
|
bindsym Mod1+Right focus right
|
||||||
|
|
||||||
# move focused window
|
# move focused window
|
||||||
bindsym Mod1+Shift+j move left
|
bindsym Mod1+Shift+$left move left
|
||||||
bindsym Mod1+Shift+k move down
|
bindsym Mod1+Shift+$down move down
|
||||||
bindsym Mod1+Shift+l move up
|
bindsym Mod1+Shift+$up move up
|
||||||
bindsym Mod1+Shift+semicolon move right
|
bindsym Mod1+Shift+$right move right
|
||||||
|
|
||||||
# alternatively, you can use the cursor keys:
|
# alternatively, you can use the cursor keys:
|
||||||
bindsym Mod1+Shift+Left move left
|
bindsym Mod1+Shift+Left move left
|
||||||
@ -130,10 +140,10 @@ mode "resize" {
|
|||||||
# Pressing right will grow the window’s width.
|
# Pressing right will grow the window’s width.
|
||||||
# Pressing up will shrink the window’s height.
|
# Pressing up will shrink the window’s height.
|
||||||
# Pressing down will grow the window’s height.
|
# Pressing down will grow the window’s height.
|
||||||
bindsym j resize shrink width 10 px or 10 ppt
|
bindsym $left resize shrink width 10 px or 10 ppt
|
||||||
bindsym k resize grow height 10 px or 10 ppt
|
bindsym $down resize grow height 10 px or 10 ppt
|
||||||
bindsym l resize shrink height 10 px or 10 ppt
|
bindsym $up resize shrink height 10 px or 10 ppt
|
||||||
bindsym semicolon resize grow width 10 px or 10 ppt
|
bindsym $right resize grow width 10 px or 10 ppt
|
||||||
|
|
||||||
# same bindings, but for the arrow keys
|
# same bindings, but for the arrow keys
|
||||||
bindsym Left resize shrink width 10 px or 10 ppt
|
bindsym Left resize shrink width 10 px or 10 ppt
|
||||||
|
@ -11,13 +11,16 @@
|
|||||||
set $mod Mod1
|
set $mod Mod1
|
||||||
|
|
||||||
# Font for window titles. Will also be used by the bar unless a different font
|
# Font for window titles. Will also be used by the bar unless a different font
|
||||||
# is used in the bar {} block below. ISO 10646 = Unicode
|
# is used in the bar {} block below.
|
||||||
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
# This font is widely installed, provides lots of unicode glyphs, right-to-left
|
||||||
|
# text rendering and scalability on retina/hidpi displays (thanks to pango).
|
||||||
|
font pango:DejaVu Sans Mono 8
|
||||||
|
# Before i3 v4.8, we used to recommend this one as the default:
|
||||||
|
# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
|
||||||
# The font above is very space-efficient, that is, it looks good, sharp and
|
# The font above is very space-efficient, that is, it looks good, sharp and
|
||||||
# clear in small sizes. However, if you need a lot of unicode glyphs or
|
# clear in small sizes. However, its unicode glyph coverage is limited, the old
|
||||||
# right-to-left text rendering, you should instead use pango for rendering and
|
# X core fonts rendering does not support right-to-left and this being a bitmap
|
||||||
# chose a FreeType font, such as:
|
# font, it doesn’t scale on retina/hidpi displays.
|
||||||
# font pango:DejaVu Sans Mono 10
|
|
||||||
|
|
||||||
# Use Mouse+$mod to drag floating windows to their wanted position
|
# Use Mouse+$mod to drag floating windows to their wanted position
|
||||||
floating_modifier $mod
|
floating_modifier $mod
|
||||||
|
@ -2,4 +2,6 @@
|
|||||||
Name=i3
|
Name=i3
|
||||||
Comment=improved dynamic tiling window manager
|
Comment=improved dynamic tiling window manager
|
||||||
Exec=i3
|
Exec=i3
|
||||||
|
TryExec=i3
|
||||||
Type=Application
|
Type=Application
|
||||||
|
X-LightDM-DesktopName=i3
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* child.c: Getting Input for the statusline
|
* child.c: Getting Input for the statusline
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef CHILD_H_
|
#pragma once
|
||||||
#define CHILD_H_
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@ -74,10 +73,14 @@ void stop_child(void);
|
|||||||
*/
|
*/
|
||||||
void cont_child(void);
|
void cont_child(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether or not the child want click events
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool child_want_click_events(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generates a click event, if enabled.
|
* Generates a click event, if enabled.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void send_block_clicked(int button, const char *name, const char *instance, int x, int y);
|
void send_block_clicked(int button, const char *name, const char *instance, int x, int y);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
* © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
|
* © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef COMMON_H_
|
#pragma once
|
||||||
#define COMMON_H_
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
@ -74,5 +73,3 @@ TAILQ_HEAD(statusline_head, status_block) statusline_head;
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "libi3.h"
|
#include "libi3.h"
|
||||||
#include "parse_json_header.h"
|
#include "parse_json_header.h"
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* config.c: Parses the configuration (received from i3).
|
* config.c: Parses the configuration (received from i3).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef CONFIG_H_
|
#pragma once
|
||||||
#define CONFIG_H_
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
@ -18,6 +17,9 @@ typedef enum {
|
|||||||
POS_BOT
|
POS_BOT
|
||||||
} position_t;
|
} position_t;
|
||||||
|
|
||||||
|
/* Bar display mode (hide unless modifier is pressed or show in dock mode or always hide in invisible mode) */
|
||||||
|
typedef enum { M_DOCK = 0, M_HIDE = 1, M_INVISIBLE = 2 } bar_display_mode_t;
|
||||||
|
|
||||||
typedef struct config_t {
|
typedef struct config_t {
|
||||||
int modifier;
|
int modifier;
|
||||||
position_t position;
|
position_t position;
|
||||||
@ -25,6 +27,7 @@ typedef struct config_t {
|
|||||||
struct xcb_color_strings_t colors;
|
struct xcb_color_strings_t colors;
|
||||||
bool disable_binding_mode_indicator;
|
bool disable_binding_mode_indicator;
|
||||||
bool disable_ws;
|
bool disable_ws;
|
||||||
|
bool strip_ws_numbers;
|
||||||
char *bar_id;
|
char *bar_id;
|
||||||
char *command;
|
char *command;
|
||||||
char *fontname;
|
char *fontname;
|
||||||
@ -32,8 +35,7 @@ typedef struct config_t {
|
|||||||
int num_outputs;
|
int num_outputs;
|
||||||
char **outputs;
|
char **outputs;
|
||||||
|
|
||||||
/* Bar display mode (hide unless modifier is pressed or show in dock mode or always hide in invisible mode) */
|
bar_display_mode_t hide_on_modifier;
|
||||||
enum { M_DOCK = 0, M_HIDE = 1, M_INVISIBLE = 2 } hide_on_modifier;
|
|
||||||
|
|
||||||
/* The current hidden_state of the bar, which indicates whether it is hidden or shown */
|
/* The current hidden_state of the bar, which indicates whether it is hidden or shown */
|
||||||
enum { S_HIDE = 0, S_SHOW = 1 } hidden_state;
|
enum { S_HIDE = 0, S_SHOW = 1 } hidden_state;
|
||||||
@ -52,5 +54,3 @@ void parse_config_json(char *json);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void free_colors(struct xcb_color_strings_t *colors);
|
void free_colors(struct xcb_color_strings_t *colors);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* ipc.c: Communicating with i3
|
* ipc.c: Communicating with i3
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef IPC_H_
|
#pragma once
|
||||||
#define IPC_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -37,5 +36,3 @@ int i3_send_msg(uint32_t type, const char* payload);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void subscribe_events(void);
|
void subscribe_events(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* mode.c: Handle mode-event and show current binding mode in the bar
|
* mode.c: Handle mode-event and show current binding mode in the bar
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef MODE_H_
|
#pragma once
|
||||||
#define MODE_H_
|
|
||||||
|
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@ -27,5 +26,3 @@ typedef struct mode mode;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void parse_mode_json(char *json);
|
void parse_mode_json(char *json);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* outputs.c: Maintaining the output-list
|
* outputs.c: Maintaining the output-list
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef OUTPUTS_H_
|
#pragma once
|
||||||
#define OUTPUTS_H_
|
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
@ -53,5 +52,3 @@ struct i3_output {
|
|||||||
|
|
||||||
SLIST_ENTRY(i3_output) slist; /* Pointer for the SLIST-Macro */
|
SLIST_ENTRY(i3_output) slist; /* Pointer for the SLIST-Macro */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
* protocol version and features.
|
* protocol version and features.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef PARSE_JSON_HEADER_H_
|
#pragma once
|
||||||
#define PARSE_JSON_HEADER_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -22,5 +21,3 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void parse_json_header(i3bar_child *child, const unsigned char *buffer, int length, unsigned int *consumed);
|
void parse_json_header(i3bar_child *child, const unsigned char *buffer, int length, unsigned int *consumed);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
* © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
|
* © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef TRAYCLIENT_H_
|
#pragma once
|
||||||
#define TRAYCLIENT_H_
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
@ -21,5 +20,3 @@ struct trayclient {
|
|||||||
|
|
||||||
TAILQ_ENTRY(trayclient) tailq; /* Pointer for the TAILQ-Macro */
|
TAILQ_ENTRY(trayclient) tailq; /* Pointer for the TAILQ-Macro */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
|
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef UTIL_H_
|
#pragma once
|
||||||
#define UTIL_H_
|
|
||||||
|
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
||||||
@ -36,8 +35,6 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Securely fee tail-queues */
|
/* Securely fee tail-queues */
|
||||||
#define FREE_TAILQ(l, type) do { \
|
#define FREE_TAILQ(l, type) do { \
|
||||||
type *walk = TAILQ_FIRST(l); \
|
type *walk = TAILQ_FIRST(l); \
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* workspaces.c: Maintaining the workspace-lists
|
* workspaces.c: Maintaining the workspace-lists
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef WORKSPACES_H_
|
#pragma once
|
||||||
#define WORKSPACES_H_
|
|
||||||
|
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
@ -32,7 +31,8 @@ void free_workspaces(void);
|
|||||||
|
|
||||||
struct i3_ws {
|
struct i3_ws {
|
||||||
int num; /* The internal number of the ws */
|
int num; /* The internal number of the ws */
|
||||||
i3String *name; /* The name of the ws */
|
char *canonical_name; /* The true name of the ws according to the ipc */
|
||||||
|
i3String *name; /* The name of the ws that is displayed on the bar */
|
||||||
int name_width; /* The rendered width of the name */
|
int name_width; /* The rendered width of the name */
|
||||||
bool visible; /* If the ws is currently visible on an output */
|
bool visible; /* If the ws is currently visible on an output */
|
||||||
bool focused; /* If the ws is currently focused */
|
bool focused; /* If the ws is currently focused */
|
||||||
@ -42,5 +42,3 @@ struct i3_ws {
|
|||||||
|
|
||||||
TAILQ_ENTRY(i3_ws) tailq; /* Pointer for the TAILQ-Macro */
|
TAILQ_ENTRY(i3_ws) tailq; /* Pointer for the TAILQ-Macro */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* xcb.c: Communicating with X
|
* xcb.c: Communicating with X
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef XCB_H_
|
#pragma once
|
||||||
#define XCB_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
//#include "outputs.h"
|
//#include "outputs.h"
|
||||||
@ -133,5 +132,3 @@ void redraw_bars(void);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void set_current_mode(struct mode *mode);
|
void set_current_mode(struct mode *mode);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -28,14 +28,13 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
/* Global variables for child_*() */
|
/* Global variables for child_*() */
|
||||||
i3bar_child child = { 0 };
|
i3bar_child child;
|
||||||
|
|
||||||
/* stdin- and sigchild-watchers */
|
/* stdin- and sigchild-watchers */
|
||||||
ev_io *stdin_io;
|
ev_io *stdin_io;
|
||||||
ev_child *child_sig;
|
ev_child *child_sig;
|
||||||
|
|
||||||
/* JSON parser for stdin */
|
/* JSON parser for stdin */
|
||||||
yajl_callbacks callbacks;
|
|
||||||
yajl_handle parser;
|
yajl_handle parser;
|
||||||
|
|
||||||
/* JSON generator for stdout */
|
/* JSON generator for stdout */
|
||||||
@ -81,12 +80,7 @@ static void clear_status_blocks() {
|
|||||||
* `draw_bars' is called, the error message text will be drawn on the bar in
|
* `draw_bars' is called, the error message text will be drawn on the bar in
|
||||||
* the space allocated for the statusline.
|
* the space allocated for the statusline.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((format(printf, 1, 2))) static void set_statusline_error(const char *format, ...) {
|
||||||
/* forward function declaration is needed to add __attribute__ mechanism which
|
|
||||||
* helps the compiler understand we are defining a printf wrapper */
|
|
||||||
static void set_statusline_error(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
|
||||||
|
|
||||||
static void set_statusline_error(const char *format, ...) {
|
|
||||||
clear_status_blocks();
|
clear_status_blocks();
|
||||||
|
|
||||||
char *message;
|
char *message;
|
||||||
@ -162,16 +156,12 @@ static int stdin_start_map(void *context) {
|
|||||||
memset(&(ctx->block), '\0', sizeof(struct status_block));
|
memset(&(ctx->block), '\0', sizeof(struct status_block));
|
||||||
|
|
||||||
/* Default width of the separator block. */
|
/* Default width of the separator block. */
|
||||||
ctx->block.sep_block_width = 9;
|
ctx->block.sep_block_width = logical_px(9);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int stdin_map_key(void *context, const unsigned char *key, size_t len) {
|
static int stdin_map_key(void *context, const unsigned char *key, size_t len) {
|
||||||
#else
|
|
||||||
static int stdin_map_key(void *context, const unsigned char *key, unsigned int len) {
|
|
||||||
#endif
|
|
||||||
parser_ctx *ctx = context;
|
parser_ctx *ctx = context;
|
||||||
FREE(ctx->last_map_key);
|
FREE(ctx->last_map_key);
|
||||||
sasprintf(&(ctx->last_map_key), "%.*s", len, key);
|
sasprintf(&(ctx->last_map_key), "%.*s", len, key);
|
||||||
@ -189,11 +179,7 @@ static int stdin_boolean(void *context, int val) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int stdin_string(void *context, const unsigned char *val, size_t len) {
|
static int stdin_string(void *context, const unsigned char *val, size_t len) {
|
||||||
#else
|
|
||||||
static int stdin_string(void *context, const unsigned char *val, unsigned int len) {
|
|
||||||
#endif
|
|
||||||
parser_ctx *ctx = context;
|
parser_ctx *ctx = context;
|
||||||
if (strcasecmp(ctx->last_map_key, "full_text") == 0) {
|
if (strcasecmp(ctx->last_map_key, "full_text") == 0) {
|
||||||
ctx->block.full_text = i3string_from_utf8_with_length((const char *)val, len);
|
ctx->block.full_text = i3string_from_utf8_with_length((const char *)val, len);
|
||||||
@ -202,9 +188,9 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le
|
|||||||
sasprintf(&(ctx->block.color), "%.*s", len, val);
|
sasprintf(&(ctx->block.color), "%.*s", len, val);
|
||||||
}
|
}
|
||||||
if (strcasecmp(ctx->last_map_key, "align") == 0) {
|
if (strcasecmp(ctx->last_map_key, "align") == 0) {
|
||||||
if (len == strlen("left") && !strncmp((const char*)val, "left", strlen("left"))) {
|
if (len == strlen("left") && !strncmp((const char *)val, "left", strlen("left"))) {
|
||||||
ctx->block.align = ALIGN_LEFT;
|
ctx->block.align = ALIGN_LEFT;
|
||||||
} else if (len == strlen("right") && !strncmp((const char*)val, "right", strlen("right"))) {
|
} else if (len == strlen("right") && !strncmp((const char *)val, "right", strlen("right"))) {
|
||||||
ctx->block.align = ALIGN_RIGHT;
|
ctx->block.align = ALIGN_RIGHT;
|
||||||
} else {
|
} else {
|
||||||
ctx->block.align = ALIGN_CENTER;
|
ctx->block.align = ALIGN_CENTER;
|
||||||
@ -215,13 +201,13 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le
|
|||||||
i3string_free(text);
|
i3string_free(text);
|
||||||
}
|
}
|
||||||
if (strcasecmp(ctx->last_map_key, "name") == 0) {
|
if (strcasecmp(ctx->last_map_key, "name") == 0) {
|
||||||
char *copy = (char*)malloc(len+1);
|
char *copy = (char *)malloc(len + 1);
|
||||||
strncpy(copy, (const char *)val, len);
|
strncpy(copy, (const char *)val, len);
|
||||||
copy[len] = 0;
|
copy[len] = 0;
|
||||||
ctx->block.name = copy;
|
ctx->block.name = copy;
|
||||||
}
|
}
|
||||||
if (strcasecmp(ctx->last_map_key, "instance") == 0) {
|
if (strcasecmp(ctx->last_map_key, "instance") == 0) {
|
||||||
char *copy = (char*)malloc(len+1);
|
char *copy = (char *)malloc(len + 1);
|
||||||
strncpy(copy, (const char *)val, len);
|
strncpy(copy, (const char *)val, len);
|
||||||
copy[len] = 0;
|
copy[len] = 0;
|
||||||
ctx->block.instance = copy;
|
ctx->block.instance = copy;
|
||||||
@ -229,11 +215,7 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int stdin_integer(void *context, long long val) {
|
static int stdin_integer(void *context, long long val) {
|
||||||
#else
|
|
||||||
static int stdin_integer(void *context, long val) {
|
|
||||||
#endif
|
|
||||||
parser_ctx *ctx = context;
|
parser_ctx *ctx = context;
|
||||||
if (strcasecmp(ctx->last_map_key, "min_width") == 0) {
|
if (strcasecmp(ctx->last_map_key, "min_width") == 0) {
|
||||||
ctx->block.min_width = (uint32_t)val;
|
ctx->block.min_width = (uint32_t)val;
|
||||||
@ -261,7 +243,7 @@ static int stdin_end_map(void *context) {
|
|||||||
static int stdin_end_array(void *context) {
|
static int stdin_end_array(void *context) {
|
||||||
DLOG("dumping statusline:\n");
|
DLOG("dumping statusline:\n");
|
||||||
struct status_block *current;
|
struct status_block *current;
|
||||||
TAILQ_FOREACH(current, &statusline_head, blocks) {
|
TAILQ_FOREACH (current, &statusline_head, blocks) {
|
||||||
DLOG("full_text = %s\n", i3string_as_utf8(current->full_text));
|
DLOG("full_text = %s\n", i3string_as_utf8(current->full_text));
|
||||||
DLOG("color = %s\n", current->color);
|
DLOG("color = %s\n", current->color);
|
||||||
}
|
}
|
||||||
@ -272,15 +254,17 @@ static int stdin_end_array(void *context) {
|
|||||||
/*
|
/*
|
||||||
* Helper function to read stdin
|
* Helper function to read stdin
|
||||||
*
|
*
|
||||||
|
* Returns NULL on EOF.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static unsigned char *get_buffer(ev_io *watcher, int *ret_buffer_len) {
|
static unsigned char *get_buffer(ev_io *watcher, int *ret_buffer_len) {
|
||||||
int fd = watcher->fd;
|
int fd = watcher->fd;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
int rec = 0;
|
int rec = 0;
|
||||||
int buffer_len = STDIN_CHUNK_SIZE;
|
int buffer_len = STDIN_CHUNK_SIZE;
|
||||||
unsigned char *buffer = smalloc(buffer_len+1);
|
unsigned char *buffer = smalloc(buffer_len + 1);
|
||||||
buffer[0] = '\0';
|
buffer[0] = '\0';
|
||||||
while(1) {
|
while (1) {
|
||||||
n = read(fd, buffer + rec, buffer_len - rec);
|
n = read(fd, buffer + rec, buffer_len - rec);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
@ -291,9 +275,7 @@ static unsigned char *get_buffer(ev_io *watcher, int *ret_buffer_len) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
/* end of file, kill the watcher */
|
|
||||||
ELOG("stdin: received EOF\n");
|
ELOG("stdin: received EOF\n");
|
||||||
cleanup();
|
|
||||||
*ret_buffer_len = -1;
|
*ret_buffer_len = -1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -318,20 +300,17 @@ static void read_flat_input(char *buffer, int length) {
|
|||||||
I3STRING_FREE(first->full_text);
|
I3STRING_FREE(first->full_text);
|
||||||
/* Remove the trailing newline and terminate the string at the same
|
/* Remove the trailing newline and terminate the string at the same
|
||||||
* time. */
|
* time. */
|
||||||
if (buffer[length-1] == '\n' || buffer[length-1] == '\r')
|
if (buffer[length - 1] == '\n' || buffer[length - 1] == '\r')
|
||||||
buffer[length-1] = '\0';
|
buffer[length - 1] = '\0';
|
||||||
else buffer[length] = '\0';
|
else
|
||||||
|
buffer[length] = '\0';
|
||||||
first->full_text = i3string_from_utf8(buffer);
|
first->full_text = i3string_from_utf8(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool read_json_input(unsigned char *input, int length) {
|
static bool read_json_input(unsigned char *input, int length) {
|
||||||
yajl_status status = yajl_parse(parser, input, length);
|
yajl_status status = yajl_parse(parser, input, length);
|
||||||
bool has_urgent = false;
|
bool has_urgent = false;
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
if (status != yajl_status_ok) {
|
if (status != yajl_status_ok) {
|
||||||
#else
|
|
||||||
if (status != yajl_status_ok && status != yajl_status_insufficient_data) {
|
|
||||||
#endif
|
|
||||||
char *message = (char *)yajl_get_error(parser, 0, input, length);
|
char *message = (char *)yajl_get_error(parser, 0, input, length);
|
||||||
|
|
||||||
/* strip the newline yajl adds to the error message */
|
/* strip the newline yajl adds to the error message */
|
||||||
@ -342,7 +321,7 @@ static bool read_json_input(unsigned char *input, int length) {
|
|||||||
status, message, length, input);
|
status, message, length, input);
|
||||||
|
|
||||||
set_statusline_error("Could not parse JSON (%s)", message);
|
set_statusline_error("Could not parse JSON (%s)", message);
|
||||||
yajl_free_error(parser, (unsigned char*)message);
|
yajl_free_error(parser, (unsigned char *)message);
|
||||||
draw_bars(false);
|
draw_bars(false);
|
||||||
} else if (parser_context.has_urgent) {
|
} else if (parser_context.has_urgent) {
|
||||||
has_urgent = true;
|
has_urgent = true;
|
||||||
@ -364,7 +343,7 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
if (child.version > 0) {
|
if (child.version > 0) {
|
||||||
has_urgent = read_json_input(buffer, rec);
|
has_urgent = read_json_input(buffer, rec);
|
||||||
} else {
|
} else {
|
||||||
read_flat_input((char*)buffer, rec);
|
read_flat_input((char *)buffer, rec);
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
draw_bars(has_urgent);
|
draw_bars(has_urgent);
|
||||||
@ -398,7 +377,7 @@ void stdin_io_first_line_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
* full_text pointer later. */
|
* full_text pointer later. */
|
||||||
struct status_block *new_block = scalloc(sizeof(struct status_block));
|
struct status_block *new_block = scalloc(sizeof(struct status_block));
|
||||||
TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks);
|
TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks);
|
||||||
read_flat_input((char*)buffer, rec);
|
read_flat_input((char *)buffer, rec);
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
ev_io_stop(main_loop, stdin_io);
|
ev_io_stop(main_loop, stdin_io);
|
||||||
@ -416,15 +395,15 @@ void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
|
|||||||
int exit_status = WEXITSTATUS(watcher->rstatus);
|
int exit_status = WEXITSTATUS(watcher->rstatus);
|
||||||
|
|
||||||
ELOG("Child (pid: %d) unexpectedly exited with status %d\n",
|
ELOG("Child (pid: %d) unexpectedly exited with status %d\n",
|
||||||
child.pid,
|
child.pid,
|
||||||
exit_status);
|
exit_status);
|
||||||
|
|
||||||
/* this error is most likely caused by a user giving a nonexecutable or
|
/* this error is most likely caused by a user giving a nonexecutable or
|
||||||
* nonexistent file, so we will handle those cases separately. */
|
* nonexistent file, so we will handle those cases separately. */
|
||||||
if (exit_status == 126)
|
if (exit_status == 126)
|
||||||
set_statusline_error("status_command is not executable (exit %d)", exit_status);
|
set_statusline_error("status_command is not executable (exit %d)", exit_status);
|
||||||
else if (exit_status == 127)
|
else if (exit_status == 127)
|
||||||
set_statusline_error("status_command not found (exit %d)", exit_status);
|
set_statusline_error("status_command not found or is missing a library dependency (exit %d)", exit_status);
|
||||||
else
|
else
|
||||||
set_statusline_error("status_command process exited unexpectedly (exit %d)", exit_status);
|
set_statusline_error("status_command process exited unexpectedly (exit %d)", exit_status);
|
||||||
|
|
||||||
@ -435,11 +414,8 @@ void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
|
|||||||
void child_write_output(void) {
|
void child_write_output(void) {
|
||||||
if (child.click_events) {
|
if (child.click_events) {
|
||||||
const unsigned char *output;
|
const unsigned char *output;
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
unsigned int size;
|
|
||||||
#else
|
|
||||||
size_t size;
|
size_t size;
|
||||||
#endif
|
|
||||||
yajl_gen_get_buf(gen, &output, &size);
|
yajl_gen_get_buf(gen, &output, &size);
|
||||||
write(child_stdin, output, size);
|
write(child_stdin, output, size);
|
||||||
write(child_stdin, "\n", 1);
|
write(child_stdin, "\n", 1);
|
||||||
@ -450,69 +426,66 @@ void child_write_output(void) {
|
|||||||
/*
|
/*
|
||||||
* Start a child-process with the specified command and reroute stdin.
|
* Start a child-process with the specified command and reroute stdin.
|
||||||
* We actually start a $SHELL to execute the command so we don't have to care
|
* We actually start a $SHELL to execute the command so we don't have to care
|
||||||
* about arguments and such
|
* about arguments and such.
|
||||||
|
*
|
||||||
|
* If `command' is NULL, such as in the case when no `status_command' is given
|
||||||
|
* in the bar config, no child will be started.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void start_child(char *command) {
|
void start_child(char *command) {
|
||||||
|
if (command == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Allocate a yajl parser which will be used to parse stdin. */
|
/* Allocate a yajl parser which will be used to parse stdin. */
|
||||||
memset(&callbacks, '\0', sizeof(yajl_callbacks));
|
static yajl_callbacks callbacks = {
|
||||||
callbacks.yajl_map_key = stdin_map_key;
|
.yajl_boolean = stdin_boolean,
|
||||||
callbacks.yajl_boolean = stdin_boolean;
|
.yajl_integer = stdin_integer,
|
||||||
callbacks.yajl_string = stdin_string;
|
.yajl_string = stdin_string,
|
||||||
callbacks.yajl_integer = stdin_integer;
|
.yajl_start_map = stdin_start_map,
|
||||||
callbacks.yajl_start_array = stdin_start_array;
|
.yajl_map_key = stdin_map_key,
|
||||||
callbacks.yajl_end_array = stdin_end_array;
|
.yajl_end_map = stdin_end_map,
|
||||||
callbacks.yajl_start_map = stdin_start_map;
|
.yajl_start_array = stdin_start_array,
|
||||||
callbacks.yajl_end_map = stdin_end_map;
|
.yajl_end_array = stdin_end_array,
|
||||||
#if YAJL_MAJOR < 2
|
};
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
parser = yajl_alloc(&callbacks, &parse_conf, NULL, (void*)&parser_context);
|
|
||||||
|
|
||||||
gen = yajl_gen_alloc(NULL, NULL);
|
|
||||||
#else
|
|
||||||
parser = yajl_alloc(&callbacks, NULL, &parser_context);
|
parser = yajl_alloc(&callbacks, NULL, &parser_context);
|
||||||
|
|
||||||
gen = yajl_gen_alloc(NULL);
|
gen = yajl_gen_alloc(NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (command != NULL) {
|
int pipe_in[2]; /* pipe we read from */
|
||||||
int pipe_in[2]; /* pipe we read from */
|
int pipe_out[2]; /* pipe we write to */
|
||||||
int pipe_out[2]; /* pipe we write to */
|
|
||||||
|
|
||||||
if (pipe(pipe_in) == -1)
|
if (pipe(pipe_in) == -1)
|
||||||
err(EXIT_FAILURE, "pipe(pipe_in)");
|
err(EXIT_FAILURE, "pipe(pipe_in)");
|
||||||
if (pipe(pipe_out) == -1)
|
if (pipe(pipe_out) == -1)
|
||||||
err(EXIT_FAILURE, "pipe(pipe_out)");
|
err(EXIT_FAILURE, "pipe(pipe_out)");
|
||||||
|
|
||||||
child.pid = fork();
|
child.pid = fork();
|
||||||
switch (child.pid) {
|
switch (child.pid) {
|
||||||
case -1:
|
case -1:
|
||||||
ELOG("Couldn't fork(): %s\n", strerror(errno));
|
ELOG("Couldn't fork(): %s\n", strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
case 0:
|
case 0:
|
||||||
/* Child-process. Reroute streams and start shell */
|
/* Child-process. Reroute streams and start shell */
|
||||||
|
|
||||||
close(pipe_in[0]);
|
close(pipe_in[0]);
|
||||||
close(pipe_out[1]);
|
close(pipe_out[1]);
|
||||||
|
|
||||||
dup2(pipe_in[1], STDOUT_FILENO);
|
dup2(pipe_in[1], STDOUT_FILENO);
|
||||||
dup2(pipe_out[0], STDIN_FILENO);
|
dup2(pipe_out[0], STDIN_FILENO);
|
||||||
|
|
||||||
setpgid(child.pid, 0);
|
setpgid(child.pid, 0);
|
||||||
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (char*) NULL);
|
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (char *)NULL);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
/* Parent-process. Reroute streams */
|
/* Parent-process. Reroute streams */
|
||||||
|
|
||||||
close(pipe_in[1]);
|
close(pipe_in[1]);
|
||||||
close(pipe_out[0]);
|
close(pipe_out[0]);
|
||||||
|
|
||||||
dup2(pipe_in[0], STDIN_FILENO);
|
dup2(pipe_in[0], STDIN_FILENO);
|
||||||
child_stdin = pipe_out[1];
|
child_stdin = pipe_out[1];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We set O_NONBLOCK because blocking is evil in event-driven software */
|
/* We set O_NONBLOCK because blocking is evil in event-driven software */
|
||||||
@ -625,3 +598,11 @@ void cont_child(void) {
|
|||||||
killpg(child.pid, child.cont_signal);
|
killpg(child.pid, child.cont_signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether or not the child want click events
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool child_want_click_events(void) {
|
||||||
|
return child.click_events;
|
||||||
|
}
|
||||||
|
@ -27,15 +27,11 @@ static char *cur_key;
|
|||||||
* Essentially we just save it in cur_key.
|
* Essentially we just save it in cur_key.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
#else
|
|
||||||
static int config_map_key_cb(void *params_, const unsigned char *keyVal, unsigned keyLen) {
|
|
||||||
#endif
|
|
||||||
FREE(cur_key);
|
FREE(cur_key);
|
||||||
|
|
||||||
cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(cur_key, (const char*) keyVal, keyLen);
|
strncpy(cur_key, (const char *)keyVal, keyLen);
|
||||||
cur_key[keyLen] = '\0';
|
cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -61,11 +57,7 @@ static int config_null_cb(void *params_) {
|
|||||||
* Parse a string
|
* Parse a string
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int config_string_cb(void *params_, const unsigned char *val, size_t _len) {
|
static int config_string_cb(void *params_, const unsigned char *val, size_t _len) {
|
||||||
#else
|
|
||||||
static int config_string_cb(void *params_, const unsigned char *val, unsigned int _len) {
|
|
||||||
#endif
|
|
||||||
int len = (int)_len;
|
int len = (int)_len;
|
||||||
/* The id and socket_path are ignored, we already know them. */
|
/* The id and socket_path are ignored, we already know them. */
|
||||||
if (!strcmp(cur_key, "id") || !strcmp(cur_key, "socket_path"))
|
if (!strcmp(cur_key, "id") || !strcmp(cur_key, "socket_path"))
|
||||||
@ -73,29 +65,29 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in
|
|||||||
|
|
||||||
if (!strcmp(cur_key, "mode")) {
|
if (!strcmp(cur_key, "mode")) {
|
||||||
DLOG("mode = %.*s, len = %d\n", len, val, len);
|
DLOG("mode = %.*s, len = %d\n", len, val, len);
|
||||||
config.hide_on_modifier = (len == 4 && !strncmp((const char*)val, "dock", strlen("dock")) ? M_DOCK
|
config.hide_on_modifier = (len == 4 && !strncmp((const char *)val, "dock", strlen("dock")) ? M_DOCK
|
||||||
: (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")) ? M_HIDE
|
: (len == 4 && !strncmp((const char *)val, "hide", strlen("hide")) ? M_HIDE
|
||||||
: M_INVISIBLE));
|
: M_INVISIBLE));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "hidden_state")) {
|
if (!strcmp(cur_key, "hidden_state")) {
|
||||||
DLOG("hidden_state = %.*s, len = %d\n", len, val, len);
|
DLOG("hidden_state = %.*s, len = %d\n", len, val, len);
|
||||||
config.hidden_state = (len == 4 && !strncmp((const char*)val, "hide", strlen("hide")) ? S_HIDE : S_SHOW);
|
config.hidden_state = (len == 4 && !strncmp((const char *)val, "hide", strlen("hide")) ? S_HIDE : S_SHOW);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "modifier")) {
|
if (!strcmp(cur_key, "modifier")) {
|
||||||
DLOG("modifier = %.*s\n", len, val);
|
DLOG("modifier = %.*s\n", len, val);
|
||||||
if (len == 5 && !strncmp((const char*)val, "shift", strlen("shift"))) {
|
if (len == 5 && !strncmp((const char *)val, "shift", strlen("shift"))) {
|
||||||
config.modifier = ShiftMask;
|
config.modifier = ShiftMask;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (len == 4 && !strncmp((const char*)val, "ctrl", strlen("ctrl"))) {
|
if (len == 4 && !strncmp((const char *)val, "ctrl", strlen("ctrl"))) {
|
||||||
config.modifier = ControlMask;
|
config.modifier = ControlMask;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (len == 4 && !strncmp((const char*)val, "Mod", strlen("Mod"))) {
|
if (len == 4 && !strncmp((const char *)val, "Mod", strlen("Mod"))) {
|
||||||
switch (val[3]) {
|
switch (val[3]) {
|
||||||
case '1':
|
case '1':
|
||||||
config.modifier = Mod1Mask;
|
config.modifier = Mod1Mask;
|
||||||
@ -122,15 +114,11 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in
|
|||||||
|
|
||||||
if (!strcmp(cur_key, "position")) {
|
if (!strcmp(cur_key, "position")) {
|
||||||
DLOG("position = %.*s\n", len, val);
|
DLOG("position = %.*s\n", len, val);
|
||||||
config.position = (len == 3 && !strncmp((const char*)val, "top", strlen("top")) ? POS_TOP : POS_BOT);
|
config.position = (len == 3 && !strncmp((const char *)val, "top", strlen("top")) ? POS_TOP : POS_BOT);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "status_command")) {
|
if (!strcmp(cur_key, "status_command")) {
|
||||||
/* We cannot directly start the child here, because start_child() also
|
|
||||||
* needs to be run when no command was specified (to setup stdin).
|
|
||||||
* Therefore we save the command in 'config' and access it later in
|
|
||||||
* got_bar_config() */
|
|
||||||
DLOG("command = %.*s\n", len, val);
|
DLOG("command = %.*s\n", len, val);
|
||||||
sasprintf(&config.command, "%.*s", len, val);
|
sasprintf(&config.command, "%.*s", len, val);
|
||||||
return 1;
|
return 1;
|
||||||
@ -145,7 +133,7 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in
|
|||||||
if (!strcmp(cur_key, "outputs")) {
|
if (!strcmp(cur_key, "outputs")) {
|
||||||
DLOG("+output %.*s\n", len, val);
|
DLOG("+output %.*s\n", len, val);
|
||||||
int new_num_outputs = config.num_outputs + 1;
|
int new_num_outputs = config.num_outputs + 1;
|
||||||
config.outputs = srealloc(config.outputs, sizeof(char*) * new_num_outputs);
|
config.outputs = srealloc(config.outputs, sizeof(char *) * new_num_outputs);
|
||||||
sasprintf(&config.outputs[config.num_outputs], "%.*s", len, val);
|
sasprintf(&config.outputs[config.num_outputs], "%.*s", len, val);
|
||||||
config.num_outputs = new_num_outputs;
|
config.num_outputs = new_num_outputs;
|
||||||
return 1;
|
return 1;
|
||||||
@ -158,13 +146,13 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COLOR(json_name, struct_name) \
|
#define COLOR(json_name, struct_name) \
|
||||||
do { \
|
do { \
|
||||||
if (!strcmp(cur_key, #json_name)) { \
|
if (!strcmp(cur_key, #json_name)) { \
|
||||||
DLOG(#json_name " = " #struct_name " = %.*s\n", len, val); \
|
DLOG(#json_name " = " #struct_name " = %.*s\n", len, val); \
|
||||||
sasprintf(&(config.colors.struct_name), "%.*s", len, val); \
|
sasprintf(&(config.colors.struct_name), "%.*s", len, val); \
|
||||||
return 1; \
|
return 1; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
COLOR(statusline, bar_fg);
|
COLOR(statusline, bar_fg);
|
||||||
@ -205,6 +193,12 @@ static int config_boolean_cb(void *params_, int val) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(cur_key, "strip_workspace_numbers")) {
|
||||||
|
DLOG("strip_workspace_numbers = %d\n", val);
|
||||||
|
config.strip_ws_numbers = val;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(cur_key, "verbose")) {
|
if (!strcmp(cur_key, "verbose")) {
|
||||||
DLOG("verbose = %d\n", val);
|
DLOG("verbose = %d\n", val);
|
||||||
config.verbose = val;
|
config.verbose = val;
|
||||||
@ -216,17 +210,10 @@ static int config_boolean_cb(void *params_, int val) {
|
|||||||
|
|
||||||
/* A datastructure to pass all these callbacks to yajl */
|
/* A datastructure to pass all these callbacks to yajl */
|
||||||
static yajl_callbacks outputs_callbacks = {
|
static yajl_callbacks outputs_callbacks = {
|
||||||
&config_null_cb,
|
.yajl_null = config_null_cb,
|
||||||
&config_boolean_cb,
|
.yajl_boolean = config_boolean_cb,
|
||||||
NULL,
|
.yajl_string = config_string_cb,
|
||||||
NULL,
|
.yajl_map_key = config_map_key_cb,
|
||||||
NULL,
|
|
||||||
&config_string_cb,
|
|
||||||
NULL,
|
|
||||||
&config_map_key_cb,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -236,24 +223,15 @@ static yajl_callbacks outputs_callbacks = {
|
|||||||
void parse_config_json(char *json) {
|
void parse_config_json(char *json) {
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
handle = yajl_alloc(&outputs_callbacks, &parse_conf, NULL, NULL);
|
|
||||||
#else
|
|
||||||
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
handle = yajl_alloc(&outputs_callbacks, NULL, NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
|
|
||||||
/* FIXME: Proper errorhandling for JSON-parsing */
|
/* FIXME: Proper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case yajl_status_ok:
|
case yajl_status_ok:
|
||||||
break;
|
break;
|
||||||
case yajl_status_client_canceled:
|
case yajl_status_client_canceled:
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
case yajl_status_insufficient_data:
|
|
||||||
#endif
|
|
||||||
case yajl_status_error:
|
case yajl_status_error:
|
||||||
ELOG("Could not parse config-reply!\n");
|
ELOG("Could not parse config-reply!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -268,9 +246,9 @@ void parse_config_json(char *json) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void free_colors(struct xcb_color_strings_t *colors) {
|
void free_colors(struct xcb_color_strings_t *colors) {
|
||||||
#define FREE_COLOR(x) \
|
#define FREE_COLOR(x) \
|
||||||
do { \
|
do { \
|
||||||
if (colors->x) \
|
if (colors->x) \
|
||||||
free(colors->x); \
|
free(colors->x); \
|
||||||
} while (0)
|
} while (0)
|
||||||
FREE_COLOR(bar_fg);
|
FREE_COLOR(bar_fg);
|
||||||
@ -290,4 +268,3 @@ void free_colors(struct xcb_color_strings_t *colors) {
|
|||||||
FREE_COLOR(focus_ws_border);
|
FREE_COLOR(focus_ws_border);
|
||||||
#undef FREE_COLOR
|
#undef FREE_COLOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
ev_io *i3_connection;
|
ev_io *i3_connection;
|
||||||
|
|
||||||
const char *sock_path;
|
const char *sock_path;
|
||||||
|
|
||||||
typedef void(*handler_t)(char*);
|
typedef void (*handler_t)(char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called, when we get a reply to a command from i3.
|
* Called, when we get a reply to a command from i3.
|
||||||
@ -67,7 +67,7 @@ void got_output_reply(char *reply) {
|
|||||||
reconfig_windows(false);
|
reconfig_windows(false);
|
||||||
|
|
||||||
i3_output *o_walk;
|
i3_output *o_walk;
|
||||||
SLIST_FOREACH(o_walk, outputs, slist) {
|
SLIST_FOREACH (o_walk, outputs, slist) {
|
||||||
kick_tray_clients(o_walk);
|
kick_tray_clients(o_walk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,9 +100,6 @@ void got_bar_config(char *reply) {
|
|||||||
/* Resolve color strings to colorpixels and save them, then free the strings. */
|
/* Resolve color strings to colorpixels and save them, then free the strings. */
|
||||||
init_colors(&(config.colors));
|
init_colors(&(config.colors));
|
||||||
|
|
||||||
/* The name of this function is actually misleading. Even if no command is
|
|
||||||
* specified, this function initiates the watchers to listen on stdin and
|
|
||||||
* react accordingly */
|
|
||||||
start_child(config.command);
|
start_child(config.command);
|
||||||
FREE(config.command);
|
FREE(config.command);
|
||||||
}
|
}
|
||||||
@ -160,16 +157,21 @@ void got_bar_config_update(char *event) {
|
|||||||
char *found_id = strstr(event, expected_id);
|
char *found_id = strstr(event, expected_id);
|
||||||
FREE(expected_id);
|
FREE(expected_id);
|
||||||
if (found_id == NULL)
|
if (found_id == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
free_colors(&(config.colors));
|
||||||
|
|
||||||
/* update the configuration with the received settings */
|
/* update the configuration with the received settings */
|
||||||
DLOG("Received bar config update \"%s\"\n", event);
|
DLOG("Received bar config update \"%s\"\n", event);
|
||||||
int old_mode = config.hide_on_modifier;
|
bar_display_mode_t old_mode = config.hide_on_modifier;
|
||||||
parse_config_json(event);
|
parse_config_json(event);
|
||||||
if (old_mode != config.hide_on_modifier) {
|
if (old_mode != config.hide_on_modifier) {
|
||||||
reconfig_windows(true);
|
reconfig_windows(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_colors(&(config.colors));
|
||||||
|
realloc_sl_buffer();
|
||||||
|
|
||||||
draw_bars(false);
|
draw_bars(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +193,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
|
|||||||
int fd = watcher->fd;
|
int fd = watcher->fd;
|
||||||
|
|
||||||
/* First we only read the header, because we know its length */
|
/* First we only read the header, because we know its length */
|
||||||
uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t)*2;
|
uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t) * 2;
|
||||||
char *header = smalloc(header_len);
|
char *header = smalloc(header_len);
|
||||||
|
|
||||||
/* We first parse the fixed-length IPC-header, to know, how much data
|
/* We first parse the fixed-length IPC-header, to know, how much data
|
||||||
@ -215,7 +217,7 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
|
|||||||
|
|
||||||
if (strncmp(header, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC))) {
|
if (strncmp(header, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC))) {
|
||||||
ELOG("Wrong magic code: %.*s\n Expected: %s\n",
|
ELOG("Wrong magic code: %.*s\n Expected: %s\n",
|
||||||
(int) strlen(I3_IPC_MAGIC),
|
(int)strlen(I3_IPC_MAGIC),
|
||||||
header,
|
header,
|
||||||
I3_IPC_MAGIC);
|
I3_IPC_MAGIC);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -223,10 +225,10 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
|
|||||||
|
|
||||||
char *walk = header + strlen(I3_IPC_MAGIC);
|
char *walk = header + strlen(I3_IPC_MAGIC);
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
memcpy(&size, (uint32_t*)walk, sizeof(uint32_t));
|
memcpy(&size, (uint32_t *)walk, sizeof(uint32_t));
|
||||||
walk += sizeof(uint32_t);
|
walk += sizeof(uint32_t);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
memcpy(&type, (uint32_t*)walk, sizeof(uint32_t));
|
memcpy(&type, (uint32_t *)walk, sizeof(uint32_t));
|
||||||
|
|
||||||
/* Now that we know, what to expect, we can start read()ing the rest
|
/* Now that we know, what to expect, we can start read()ing the rest
|
||||||
* of the message */
|
* of the message */
|
||||||
@ -272,7 +274,7 @@ int i3_send_msg(uint32_t type, const char *payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We are a wellbehaved client and send a proper header first */
|
/* We are a wellbehaved client and send a proper header first */
|
||||||
uint32_t to_write = strlen (I3_IPC_MAGIC) + sizeof(uint32_t)*2 + len;
|
uint32_t to_write = strlen(I3_IPC_MAGIC) + sizeof(uint32_t) * 2 + len;
|
||||||
/* TODO: I'm not entirely sure if this buffer really has to contain more
|
/* TODO: I'm not entirely sure if this buffer really has to contain more
|
||||||
* than the pure header (why not just write() the payload from *payload?),
|
* than the pure header (why not just write() the payload from *payload?),
|
||||||
* but we leave it for now */
|
* but we leave it for now */
|
||||||
|
@ -99,12 +99,11 @@ int main(int argc, char **argv) {
|
|||||||
memset(&config, '\0', sizeof(config_t));
|
memset(&config, '\0', sizeof(config_t));
|
||||||
|
|
||||||
static struct option long_opt[] = {
|
static struct option long_opt[] = {
|
||||||
{ "socket", required_argument, 0, 's' },
|
{"socket", required_argument, 0, 's'},
|
||||||
{ "bar_id", required_argument, 0, 'b' },
|
{"bar_id", required_argument, 0, 'b'},
|
||||||
{ "help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h'},
|
||||||
{ "version", no_argument, 0, 'v' },
|
{"version", no_argument, 0, 'v'},
|
||||||
{ NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}};
|
||||||
};
|
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "b:s:hv", long_opt, &option_index)) != -1) {
|
while ((opt = getopt_long(argc, argv, "b:s:hv", long_opt, &option_index)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -112,7 +111,7 @@ int main(int argc, char **argv) {
|
|||||||
socket_path = expand_path(optarg);
|
socket_path = expand_path(optarg);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
printf("i3bar version " I3_VERSION " © 2010-2011 Axel Wagner and contributors\n");
|
printf("i3bar version " I3_VERSION " © 2010-2014 Axel Wagner and contributors\n");
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
|
@ -18,36 +18,31 @@
|
|||||||
|
|
||||||
/* A datatype to pass through the callbacks to save the state */
|
/* A datatype to pass through the callbacks to save the state */
|
||||||
struct mode_json_params {
|
struct mode_json_params {
|
||||||
char *json;
|
char *json;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
mode *mode;
|
mode *mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a string (change)
|
* Parse a string (change)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
|
static int mode_string_cb(void *params_, const unsigned char *val, size_t len) {
|
||||||
#else
|
struct mode_json_params *params = (struct mode_json_params *)params_;
|
||||||
static int mode_string_cb(void *params_, const unsigned char *val, unsigned int len) {
|
|
||||||
#endif
|
|
||||||
struct mode_json_params *params = (struct mode_json_params*) params_;
|
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "change")) {
|
if (!strcmp(params->cur_key, "change")) {
|
||||||
|
/* Save the name */
|
||||||
|
params->mode->name = i3string_from_utf8_with_length((const char *)val, len);
|
||||||
|
/* Save its rendered width */
|
||||||
|
params->mode->width = predict_text_width(params->mode->name);
|
||||||
|
|
||||||
/* Save the name */
|
DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
|
||||||
params->mode->name = i3string_from_utf8_with_length((const char *)val, len);
|
FREE(params->cur_key);
|
||||||
/* Save its rendered width */
|
|
||||||
params->mode->width = predict_text_width(params->mode->name);
|
|
||||||
|
|
||||||
DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
|
return 1;
|
||||||
FREE(params->cur_key);
|
}
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -56,34 +51,21 @@ static int mode_string_cb(void *params_, const unsigned char *val, unsigned int
|
|||||||
* Essentially we just save it in the parsing-state
|
* Essentially we just save it in the parsing-state
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int mode_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
#else
|
struct mode_json_params *params = (struct mode_json_params *)params_;
|
||||||
static int mode_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) {
|
|
||||||
#endif
|
|
||||||
struct mode_json_params *params = (struct mode_json_params*) params_;
|
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(params->cur_key, (const char*) keyVal, keyLen);
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
||||||
params->cur_key[keyLen] = '\0';
|
params->cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A datastructure to pass all these callbacks to yajl */
|
/* A datastructure to pass all these callbacks to yajl */
|
||||||
yajl_callbacks mode_callbacks = {
|
static yajl_callbacks mode_callbacks = {
|
||||||
NULL,
|
.yajl_string = mode_string_cb,
|
||||||
NULL,
|
.yajl_map_key = mode_map_key_cb,
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&mode_string_cb,
|
|
||||||
NULL,
|
|
||||||
&mode_map_key_cb,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -104,24 +86,15 @@ void parse_mode_json(char *json) {
|
|||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
|
|
||||||
#if YAJL_MAJOR < 2
|
handle = yajl_alloc(&mode_callbacks, NULL, (void *)¶ms);
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
handle = yajl_alloc(&mode_callbacks, &parse_conf, NULL, (void*) ¶ms);
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
#else
|
|
||||||
handle = yajl_alloc(&mode_callbacks, NULL, (void*) ¶ms);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
|
||||||
|
|
||||||
/* FIXME: Propper errorhandling for JSON-parsing */
|
/* FIXME: Propper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case yajl_status_ok:
|
case yajl_status_ok:
|
||||||
break;
|
break;
|
||||||
case yajl_status_client_canceled:
|
case yajl_status_client_canceled:
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
case yajl_status_insufficient_data:
|
|
||||||
#endif
|
|
||||||
case yajl_status_error:
|
case yajl_status_error:
|
||||||
ELOG("Could not parse mode-event!\n");
|
ELOG("Could not parse mode-event!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
/* A datatype to pass through the callbacks to save the state */
|
/* A datatype to pass through the callbacks to save the state */
|
||||||
struct outputs_json_params {
|
struct outputs_json_params {
|
||||||
struct outputs_head *outputs;
|
struct outputs_head *outputs;
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
char *json;
|
char *json;
|
||||||
bool in_rect;
|
bool in_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -31,7 +31,7 @@ struct outputs_json_params {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_null_cb(void *params_) {
|
static int outputs_null_cb(void *params_) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
|
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ static int outputs_null_cb(void *params_) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_boolean_cb(void *params_, int val) {
|
static int outputs_boolean_cb(void *params_, int val) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "active")) {
|
if (!strcmp(params->cur_key, "active")) {
|
||||||
params->outputs_walk->active = val;
|
params->outputs_walk->active = val;
|
||||||
@ -64,39 +64,35 @@ static int outputs_boolean_cb(void *params_, int val) {
|
|||||||
* Parse an integer (current_workspace or the rect)
|
* Parse an integer (current_workspace or the rect)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int outputs_integer_cb(void *params_, long long val) {
|
static int outputs_integer_cb(void *params_, long long val) {
|
||||||
#else
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
static int outputs_integer_cb(void *params_, long val) {
|
|
||||||
#endif
|
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "current_workspace")) {
|
if (!strcmp(params->cur_key, "current_workspace")) {
|
||||||
params->outputs_walk->ws = (int) val;
|
params->outputs_walk->ws = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "x")) {
|
if (!strcmp(params->cur_key, "x")) {
|
||||||
params->outputs_walk->rect.x = (int) val;
|
params->outputs_walk->rect.x = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "y")) {
|
if (!strcmp(params->cur_key, "y")) {
|
||||||
params->outputs_walk->rect.y = (int) val;
|
params->outputs_walk->rect.y = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "width")) {
|
if (!strcmp(params->cur_key, "width")) {
|
||||||
params->outputs_walk->rect.w = (int) val;
|
params->outputs_walk->rect.w = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "height")) {
|
if (!strcmp(params->cur_key, "height")) {
|
||||||
params->outputs_walk->rect.h = (int) val;
|
params->outputs_walk->rect.h = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -108,16 +104,12 @@ static int outputs_integer_cb(void *params_, long val) {
|
|||||||
* Parse a string (name)
|
* Parse a string (name)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int outputs_string_cb(void *params_, const unsigned char *val, size_t len) {
|
static int outputs_string_cb(void *params_, const unsigned char *val, size_t len) {
|
||||||
#else
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
static int outputs_string_cb(void *params_, const unsigned char *val, unsigned int len) {
|
|
||||||
#endif
|
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "current_workspace")) {
|
if (!strcmp(params->cur_key, "current_workspace")) {
|
||||||
char *copy = smalloc(sizeof(const unsigned char) * (len + 1));
|
char *copy = smalloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(copy, (const char*) val, len);
|
strncpy(copy, (const char *)val, len);
|
||||||
copy[len] = '\0';
|
copy[len] = '\0';
|
||||||
|
|
||||||
char *end;
|
char *end;
|
||||||
@ -136,7 +128,7 @@ static int outputs_string_cb(void *params_, const unsigned char *val, unsigned i
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *name = smalloc(sizeof(const unsigned char) * (len + 1));
|
char *name = smalloc(sizeof(const unsigned char) * (len + 1));
|
||||||
strncpy(name, (const char*) val, len);
|
strncpy(name, (const char *)val, len);
|
||||||
name[len] = '\0';
|
name[len] = '\0';
|
||||||
|
|
||||||
params->outputs_walk->name = name;
|
params->outputs_walk->name = name;
|
||||||
@ -151,7 +143,7 @@ static int outputs_string_cb(void *params_, const unsigned char *val, unsigned i
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_start_map_cb(void *params_) {
|
static int outputs_start_map_cb(void *params_) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
i3_output *new_output = NULL;
|
i3_output *new_output = NULL;
|
||||||
|
|
||||||
if (params->cur_key == NULL) {
|
if (params->cur_key == NULL) {
|
||||||
@ -184,7 +176,7 @@ static int outputs_start_map_cb(void *params_) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int outputs_end_map_cb(void *params_) {
|
static int outputs_end_map_cb(void *params_) {
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
if (params->in_rect) {
|
if (params->in_rect) {
|
||||||
params->in_rect = false;
|
params->in_rect = false;
|
||||||
/* Ignore the end of a rect */
|
/* Ignore the end of a rect */
|
||||||
@ -232,34 +224,26 @@ static int outputs_end_map_cb(void *params_) {
|
|||||||
* Essentially we just save it in the parsing-state
|
* Essentially we just save it in the parsing-state
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
#else
|
struct outputs_json_params *params = (struct outputs_json_params *)params_;
|
||||||
static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, unsigned keyLen) {
|
|
||||||
#endif
|
|
||||||
struct outputs_json_params *params = (struct outputs_json_params*) params_;
|
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(params->cur_key, (const char*) keyVal, keyLen);
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
||||||
params->cur_key[keyLen] = '\0';
|
params->cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A datastructure to pass all these callbacks to yajl */
|
/* A datastructure to pass all these callbacks to yajl */
|
||||||
yajl_callbacks outputs_callbacks = {
|
static yajl_callbacks outputs_callbacks = {
|
||||||
&outputs_null_cb,
|
.yajl_null = outputs_null_cb,
|
||||||
&outputs_boolean_cb,
|
.yajl_boolean = outputs_boolean_cb,
|
||||||
&outputs_integer_cb,
|
.yajl_integer = outputs_integer_cb,
|
||||||
NULL,
|
.yajl_string = outputs_string_cb,
|
||||||
NULL,
|
.yajl_start_map = outputs_start_map_cb,
|
||||||
&outputs_string_cb,
|
.yajl_map_key = outputs_map_key_cb,
|
||||||
&outputs_start_map_cb,
|
.yajl_end_map = outputs_end_map_cb,
|
||||||
&outputs_map_key_cb,
|
|
||||||
&outputs_end_map_cb,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -285,24 +269,15 @@ void parse_outputs_json(char *json) {
|
|||||||
|
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
#if YAJL_MAJOR < 2
|
handle = yajl_alloc(&outputs_callbacks, NULL, (void *)¶ms);
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
handle = yajl_alloc(&outputs_callbacks, &parse_conf, NULL, (void*) ¶ms);
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
#else
|
|
||||||
handle = yajl_alloc(&outputs_callbacks, NULL, (void*) ¶ms);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
|
||||||
|
|
||||||
/* FIXME: Propper errorhandling for JSON-parsing */
|
/* FIXME: Propper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case yajl_status_ok:
|
case yajl_status_ok:
|
||||||
break;
|
break;
|
||||||
case yajl_status_client_canceled:
|
case yajl_status_client_canceled:
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
case yajl_status_insufficient_data:
|
|
||||||
#endif
|
|
||||||
case yajl_status_error:
|
case yajl_status_error:
|
||||||
ELOG("Could not parse outputs-reply!\n");
|
ELOG("Could not parse outputs-reply!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -321,7 +296,7 @@ i3_output *get_output_by_name(char *name) {
|
|||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!strcmp(walk->name, name)) {
|
if (!strcmp(walk->name, name)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,7 @@ static enum {
|
|||||||
NO_KEY
|
NO_KEY
|
||||||
} current_key;
|
} current_key;
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int header_integer(void *ctx, long long val) {
|
static int header_integer(void *ctx, long long val) {
|
||||||
#else
|
|
||||||
static int header_integer(void *ctx, long val) {
|
|
||||||
#endif
|
|
||||||
i3bar_child *child = ctx;
|
i3bar_child *child = ctx;
|
||||||
|
|
||||||
switch (current_key) {
|
switch (current_key) {
|
||||||
@ -74,13 +70,9 @@ static int header_boolean(void *ctx, int val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_KEY(name) (stringlen == strlen(name) && \
|
#define CHECK_KEY(name) (stringlen == strlen(name) && \
|
||||||
STARTS_WITH((const char*)stringval, stringlen, name))
|
STARTS_WITH((const char *)stringval, stringlen, name))
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int header_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
static int header_map_key(void *ctx, const unsigned char *stringval, size_t stringlen) {
|
||||||
#else
|
|
||||||
static int header_map_key(void *ctx, const unsigned char *stringval, unsigned int stringlen) {
|
|
||||||
#endif
|
|
||||||
if (CHECK_KEY("version")) {
|
if (CHECK_KEY("version")) {
|
||||||
current_key = KEY_VERSION;
|
current_key = KEY_VERSION;
|
||||||
} else if (CHECK_KEY("stop_signal")) {
|
} else if (CHECK_KEY("stop_signal")) {
|
||||||
@ -93,20 +85,6 @@ static int header_map_key(void *ctx, const unsigned char *stringval, unsigned in
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static yajl_callbacks version_callbacks = {
|
|
||||||
NULL, /* null */
|
|
||||||
&header_boolean, /* boolean */
|
|
||||||
&header_integer,
|
|
||||||
NULL, /* double */
|
|
||||||
NULL, /* number */
|
|
||||||
NULL, /* string */
|
|
||||||
NULL, /* start_map */
|
|
||||||
&header_map_key,
|
|
||||||
NULL, /* end_map */
|
|
||||||
NULL, /* start_array */
|
|
||||||
NULL /* end_array */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void child_init(i3bar_child *child) {
|
static void child_init(i3bar_child *child) {
|
||||||
child->version = 0;
|
child->version = 0;
|
||||||
child->stop_signal = SIGSTOP;
|
child->stop_signal = SIGSTOP;
|
||||||
@ -122,20 +100,20 @@ static void child_init(i3bar_child *child) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void parse_json_header(i3bar_child *child, const unsigned char *buffer, int length, unsigned int *consumed) {
|
void parse_json_header(i3bar_child *child, const unsigned char *buffer, int length, unsigned int *consumed) {
|
||||||
|
static yajl_callbacks version_callbacks = {
|
||||||
|
.yajl_boolean = header_boolean,
|
||||||
|
.yajl_integer = header_integer,
|
||||||
|
.yajl_map_key = &header_map_key,
|
||||||
|
};
|
||||||
|
|
||||||
child_init(child);
|
child_init(child);
|
||||||
|
|
||||||
current_key = NO_KEY;
|
current_key = NO_KEY;
|
||||||
|
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
yajl_handle handle = yajl_alloc(&version_callbacks, NULL, child);
|
yajl_handle handle = yajl_alloc(&version_callbacks, NULL, child);
|
||||||
/* Allow trailing garbage. yajl 1 always behaves that way anyways, but for
|
/* Allow trailing garbage. yajl 1 always behaves that way anyways, but for
|
||||||
* yajl 2, we need to be explicit. */
|
* yajl 2, we need to be explicit. */
|
||||||
yajl_config(handle, yajl_allow_trailing_garbage, 1);
|
yajl_config(handle, yajl_allow_trailing_garbage, 1);
|
||||||
#else
|
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
yajl_handle handle = yajl_alloc(&version_callbacks, &parse_conf, NULL, child);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
yajl_status state = yajl_parse(handle, buffer, length);
|
yajl_status state = yajl_parse(handle, buffer, length);
|
||||||
if (state != yajl_status_ok) {
|
if (state != yajl_status_ok) {
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
/* A datatype to pass through the callbacks to save the state */
|
/* A datatype to pass through the callbacks to save the state */
|
||||||
struct workspaces_json_params {
|
struct workspaces_json_params {
|
||||||
struct ws_head *workspaces;
|
struct ws_head *workspaces;
|
||||||
i3_ws *workspaces_walk;
|
i3_ws *workspaces_walk;
|
||||||
char *cur_key;
|
char *cur_key;
|
||||||
char *json;
|
char *json;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -29,7 +29,7 @@ struct workspaces_json_params {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_boolean_cb(void *params_, int val) {
|
static int workspaces_boolean_cb(void *params_, int val) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "visible")) {
|
if (!strcmp(params->cur_key, "visible")) {
|
||||||
params->workspaces_walk->visible = val;
|
params->workspaces_walk->visible = val;
|
||||||
@ -58,39 +58,35 @@ static int workspaces_boolean_cb(void *params_, int val) {
|
|||||||
* Parse an integer (num or the rect)
|
* Parse an integer (num or the rect)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int workspaces_integer_cb(void *params_, long long val) {
|
static int workspaces_integer_cb(void *params_, long long val) {
|
||||||
#else
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
static int workspaces_integer_cb(void *params_, long val) {
|
|
||||||
#endif
|
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "num")) {
|
if (!strcmp(params->cur_key, "num")) {
|
||||||
params->workspaces_walk->num = (int) val;
|
params->workspaces_walk->num = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "x")) {
|
if (!strcmp(params->cur_key, "x")) {
|
||||||
params->workspaces_walk->rect.x = (int) val;
|
params->workspaces_walk->rect.x = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "y")) {
|
if (!strcmp(params->cur_key, "y")) {
|
||||||
params->workspaces_walk->rect.y = (int) val;
|
params->workspaces_walk->rect.y = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "width")) {
|
if (!strcmp(params->cur_key, "width")) {
|
||||||
params->workspaces_walk->rect.w = (int) val;
|
params->workspaces_walk->rect.w = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "height")) {
|
if (!strcmp(params->cur_key, "height")) {
|
||||||
params->workspaces_walk->rect.h = (int) val;
|
params->workspaces_walk->rect.h = (int)val;
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -103,51 +99,71 @@ static int workspaces_integer_cb(void *params_, long val) {
|
|||||||
* Parse a string (name, output)
|
* Parse a string (name, output)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int workspaces_string_cb(void *params_, const unsigned char *val, size_t len) {
|
static int workspaces_string_cb(void *params_, const unsigned char *val, size_t len) {
|
||||||
#else
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
static int workspaces_string_cb(void *params_, const unsigned char *val, unsigned int len) {
|
|
||||||
#endif
|
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
|
||||||
|
|
||||||
char *output_name;
|
char *output_name;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "name")) {
|
if (!strcmp(params->cur_key, "name")) {
|
||||||
/* Save the name */
|
const char *ws_name = (const char *)val;
|
||||||
params->workspaces_walk->name = i3string_from_utf8_with_length((const char *)val, len);
|
params->workspaces_walk->canonical_name = strndup(ws_name, len);
|
||||||
|
|
||||||
/* Save its rendered width */
|
if (config.strip_ws_numbers && params->workspaces_walk->num >= 0) {
|
||||||
params->workspaces_walk->name_width =
|
/* Special case: strip off the workspace number */
|
||||||
predict_text_width(params->workspaces_walk->name);
|
static char ws_num[10];
|
||||||
|
|
||||||
DLOG("Got Workspace %s, name_width: %d, glyphs: %zu\n",
|
snprintf(ws_num, sizeof(ws_num), "%d", params->workspaces_walk->num);
|
||||||
i3string_as_utf8(params->workspaces_walk->name),
|
|
||||||
params->workspaces_walk->name_width,
|
|
||||||
i3string_get_num_glyphs(params->workspaces_walk->name));
|
|
||||||
FREE(params->cur_key);
|
|
||||||
|
|
||||||
return 1;
|
/* Calculate the length of the number str in the name */
|
||||||
|
size_t offset = strspn(ws_name, ws_num);
|
||||||
|
|
||||||
|
/* Also strip off the conventional ws name delimiter */
|
||||||
|
if (offset && ws_name[offset] == ':')
|
||||||
|
offset += 1;
|
||||||
|
|
||||||
|
/* Offset may be equal to length, in which case display the number */
|
||||||
|
params->workspaces_walk->name = (offset < len
|
||||||
|
? i3string_from_utf8_with_length(ws_name + offset, len - offset)
|
||||||
|
: i3string_from_utf8(ws_num));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Default case: just save the name */
|
||||||
|
params->workspaces_walk->name = i3string_from_utf8_with_length(ws_name, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "output")) {
|
/* Save its rendered width */
|
||||||
/* We add the ws to the TAILQ of the output, it belongs to */
|
params->workspaces_walk->name_width =
|
||||||
output_name = smalloc(sizeof(const unsigned char) * (len + 1));
|
predict_text_width(params->workspaces_walk->name);
|
||||||
strncpy(output_name, (const char*) val, len);
|
|
||||||
output_name[len] = '\0';
|
|
||||||
i3_output *target = get_output_by_name(output_name);
|
|
||||||
if (target) {
|
|
||||||
params->workspaces_walk->output = target;
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
|
DLOG("Got Workspace canonical: %s, name: '%s', name_width: %d, glyphs: %zu\n",
|
||||||
params->workspaces_walk,
|
params->workspaces_walk->canonical_name,
|
||||||
tailq);
|
i3string_as_utf8(params->workspaces_walk->name),
|
||||||
}
|
params->workspaces_walk->name_width,
|
||||||
|
i3string_get_num_glyphs(params->workspaces_walk->name));
|
||||||
|
FREE(params->cur_key);
|
||||||
|
|
||||||
FREE(output_name);
|
return 1;
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
if (!strcmp(params->cur_key, "output")) {
|
||||||
|
/* We add the ws to the TAILQ of the output, it belongs to */
|
||||||
|
output_name = smalloc(sizeof(const unsigned char) * (len + 1));
|
||||||
|
strncpy(output_name, (const char *)val, len);
|
||||||
|
output_name[len] = '\0';
|
||||||
|
i3_output *target = get_output_by_name(output_name);
|
||||||
|
if (target) {
|
||||||
|
params->workspaces_walk->output = target;
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces,
|
||||||
|
params->workspaces_walk,
|
||||||
|
tailq);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
FREE(output_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -155,7 +171,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, unsigne
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int workspaces_start_map_cb(void *params_) {
|
static int workspaces_start_map_cb(void *params_) {
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
|
|
||||||
i3_ws *new_workspace = NULL;
|
i3_ws *new_workspace = NULL;
|
||||||
|
|
||||||
@ -182,34 +198,24 @@ static int workspaces_start_map_cb(void *params_) {
|
|||||||
* Essentially we just save it in the parsing-state
|
* Essentially we just save it in the parsing-state
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if YAJL_MAJOR >= 2
|
|
||||||
static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) {
|
||||||
#else
|
struct workspaces_json_params *params = (struct workspaces_json_params *)params_;
|
||||||
static int workspaces_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) {
|
|
||||||
#endif
|
|
||||||
struct workspaces_json_params *params = (struct workspaces_json_params*) params_;
|
|
||||||
FREE(params->cur_key);
|
FREE(params->cur_key);
|
||||||
|
|
||||||
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
params->cur_key = smalloc(sizeof(unsigned char) * (keyLen + 1));
|
||||||
strncpy(params->cur_key, (const char*) keyVal, keyLen);
|
strncpy(params->cur_key, (const char *)keyVal, keyLen);
|
||||||
params->cur_key[keyLen] = '\0';
|
params->cur_key[keyLen] = '\0';
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A datastructure to pass all these callbacks to yajl */
|
/* A datastructure to pass all these callbacks to yajl */
|
||||||
yajl_callbacks workspaces_callbacks = {
|
static yajl_callbacks workspaces_callbacks = {
|
||||||
NULL,
|
.yajl_boolean = workspaces_boolean_cb,
|
||||||
&workspaces_boolean_cb,
|
.yajl_integer = workspaces_integer_cb,
|
||||||
&workspaces_integer_cb,
|
.yajl_string = workspaces_string_cb,
|
||||||
NULL,
|
.yajl_start_map = workspaces_start_map_cb,
|
||||||
NULL,
|
.yajl_map_key = workspaces_map_key_cb,
|
||||||
&workspaces_string_cb,
|
|
||||||
&workspaces_start_map_cb,
|
|
||||||
&workspaces_map_key_cb,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -229,24 +235,15 @@ void parse_workspaces_json(char *json) {
|
|||||||
|
|
||||||
yajl_handle handle;
|
yajl_handle handle;
|
||||||
yajl_status state;
|
yajl_status state;
|
||||||
#if YAJL_MAJOR < 2
|
handle = yajl_alloc(&workspaces_callbacks, NULL, (void *)¶ms);
|
||||||
yajl_parser_config parse_conf = { 0, 0 };
|
|
||||||
|
|
||||||
handle = yajl_alloc(&workspaces_callbacks, &parse_conf, NULL, (void*) ¶ms);
|
state = yajl_parse(handle, (const unsigned char *)json, strlen(json));
|
||||||
#else
|
|
||||||
handle = yajl_alloc(&workspaces_callbacks, NULL, (void*) ¶ms);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
state = yajl_parse(handle, (const unsigned char*) json, strlen(json));
|
|
||||||
|
|
||||||
/* FIXME: Propper errorhandling for JSON-parsing */
|
/* FIXME: Propper errorhandling for JSON-parsing */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case yajl_status_ok:
|
case yajl_status_ok:
|
||||||
break;
|
break;
|
||||||
case yajl_status_client_canceled:
|
case yajl_status_client_canceled:
|
||||||
#if YAJL_MAJOR < 2
|
|
||||||
case yajl_status_insufficient_data:
|
|
||||||
#endif
|
|
||||||
case yajl_status_error:
|
case yajl_status_error:
|
||||||
ELOG("Could not parse workspaces-reply!\n");
|
ELOG("Could not parse workspaces-reply!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -267,12 +264,13 @@ void free_workspaces(void) {
|
|||||||
if (outputs == NULL) {
|
if (outputs == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i3_ws *ws_walk;
|
i3_ws *ws_walk;
|
||||||
|
|
||||||
SLIST_FOREACH(outputs_walk, outputs, slist) {
|
SLIST_FOREACH (outputs_walk, outputs, slist) {
|
||||||
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
|
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
|
||||||
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
|
||||||
I3STRING_FREE(ws_walk->name);
|
I3STRING_FREE(ws_walk->name);
|
||||||
|
FREE(ws_walk->canonical_name);
|
||||||
}
|
}
|
||||||
FREE_TAILQ(outputs_walk->workspaces, i3_ws);
|
FREE_TAILQ(outputs_walk->workspaces, i3_ws);
|
||||||
}
|
}
|
||||||
|
406
i3bar/src/xcb.c
406
i3bar/src/xcb.c
@ -35,19 +35,19 @@
|
|||||||
|
|
||||||
/* We save the Atoms in an easy to access array, indexed by an enum */
|
/* We save the Atoms in an easy to access array, indexed by an enum */
|
||||||
enum {
|
enum {
|
||||||
#define ATOM_DO(name) name,
|
#define ATOM_DO(name) name,
|
||||||
#include "xcb_atoms.def"
|
#include "xcb_atoms.def"
|
||||||
NUM_ATOMS
|
NUM_ATOMS
|
||||||
};
|
};
|
||||||
|
|
||||||
xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS];
|
xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS];
|
||||||
xcb_atom_t atoms[NUM_ATOMS];
|
xcb_atom_t atoms[NUM_ATOMS];
|
||||||
|
|
||||||
/* Variables, that are the same for all functions at all times */
|
/* Variables, that are the same for all functions at all times */
|
||||||
xcb_connection_t *xcb_connection;
|
xcb_connection_t *xcb_connection;
|
||||||
int screen;
|
int screen;
|
||||||
xcb_screen_t *root_screen;
|
xcb_screen_t *root_screen;
|
||||||
xcb_window_t xcb_root;
|
xcb_window_t xcb_root;
|
||||||
|
|
||||||
/* selection window for tray support */
|
/* selection window for tray support */
|
||||||
static xcb_window_t selwin = XCB_NONE;
|
static xcb_window_t selwin = XCB_NONE;
|
||||||
@ -63,22 +63,22 @@ static i3Font font;
|
|||||||
int bar_height;
|
int bar_height;
|
||||||
|
|
||||||
/* These are only relevant for XKB, which we only need for grabbing modifiers */
|
/* These are only relevant for XKB, which we only need for grabbing modifiers */
|
||||||
Display *xkb_dpy;
|
Display *xkb_dpy;
|
||||||
int xkb_event_base;
|
int xkb_event_base;
|
||||||
int mod_pressed = 0;
|
int mod_pressed = 0;
|
||||||
|
|
||||||
/* Because the statusline is the same on all outputs, we have
|
/* Because the statusline is the same on all outputs, we have
|
||||||
* global buffer to render it on */
|
* global buffer to render it on */
|
||||||
xcb_gcontext_t statusline_ctx;
|
xcb_gcontext_t statusline_ctx;
|
||||||
xcb_gcontext_t statusline_clear;
|
xcb_gcontext_t statusline_clear;
|
||||||
xcb_pixmap_t statusline_pm;
|
xcb_pixmap_t statusline_pm;
|
||||||
uint32_t statusline_width;
|
uint32_t statusline_width;
|
||||||
|
|
||||||
/* Event-Watchers, to interact with the user */
|
/* Event-Watchers, to interact with the user */
|
||||||
ev_prepare *xcb_prep;
|
ev_prepare *xcb_prep;
|
||||||
ev_check *xcb_chk;
|
ev_check *xcb_chk;
|
||||||
ev_io *xcb_io;
|
ev_io *xcb_io;
|
||||||
ev_io *xkb_io;
|
ev_io *xkb_io;
|
||||||
|
|
||||||
/* The name of current binding mode */
|
/* The name of current binding mode */
|
||||||
static mode binding;
|
static mode binding;
|
||||||
@ -128,7 +128,7 @@ void refresh_statusline(void) {
|
|||||||
statusline_width = 0;
|
statusline_width = 0;
|
||||||
|
|
||||||
/* Predict the text width of all blocks (in pixels). */
|
/* Predict the text width of all blocks (in pixels). */
|
||||||
TAILQ_FOREACH(block, &statusline_head, blocks) {
|
TAILQ_FOREACH (block, &statusline_head, blocks) {
|
||||||
if (i3string_get_num_bytes(block->full_text) == 0)
|
if (i3string_get_num_bytes(block->full_text) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -148,8 +148,8 @@ void refresh_statusline(void) {
|
|||||||
block->x_offset = padding_width;
|
block->x_offset = padding_width;
|
||||||
break;
|
break;
|
||||||
case ALIGN_CENTER:
|
case ALIGN_CENTER:
|
||||||
block->x_offset = padding_width / 2;
|
block->x_offset = padding_width / logical_px(2);
|
||||||
block->x_append = padding_width / 2 + padding_width % 2;
|
block->x_append = padding_width / logical_px(2) + padding_width % logical_px(2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,12 +168,12 @@ void refresh_statusline(void) {
|
|||||||
realloc_sl_buffer();
|
realloc_sl_buffer();
|
||||||
|
|
||||||
/* Clear the statusline pixmap. */
|
/* Clear the statusline pixmap. */
|
||||||
xcb_rectangle_t rect = { 0, 0, root_screen->width_in_pixels, font.height + 2 };
|
xcb_rectangle_t rect = {0, 0, root_screen->width_in_pixels, font.height + logical_px(5)};
|
||||||
xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect);
|
xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect);
|
||||||
|
|
||||||
/* Draw the text of each block. */
|
/* Draw the text of each block. */
|
||||||
uint32_t x = 0;
|
uint32_t x = 0;
|
||||||
TAILQ_FOREACH(block, &statusline_head, blocks) {
|
TAILQ_FOREACH (block, &statusline_head, blocks) {
|
||||||
if (i3string_get_num_bytes(block->full_text) == 0)
|
if (i3string_get_num_bytes(block->full_text) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -184,14 +184,14 @@ void refresh_statusline(void) {
|
|||||||
|
|
||||||
if (TAILQ_NEXT(block, blocks) != NULL && !block->no_separator && block->sep_block_width > 0) {
|
if (TAILQ_NEXT(block, blocks) != NULL && !block->no_separator && block->sep_block_width > 0) {
|
||||||
/* This is not the last block, draw a separator. */
|
/* This is not the last block, draw a separator. */
|
||||||
uint32_t sep_offset = block->sep_block_width/2 + block->sep_block_width % 2;
|
uint32_t sep_offset = block->sep_block_width / 2 + block->sep_block_width % 2;
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_LINE_WIDTH;
|
||||||
uint32_t values[] = { colors.sep_fg, colors.bar_bg };
|
uint32_t values[] = {colors.sep_fg, colors.bar_bg, logical_px(1)};
|
||||||
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
|
xcb_change_gc(xcb_connection, statusline_ctx, mask, values);
|
||||||
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
|
xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
|
||||||
statusline_ctx, 2,
|
statusline_ctx, 2,
|
||||||
(xcb_point_t[]){ { x - sep_offset, 2 },
|
(xcb_point_t[]) {{x - sep_offset, 2},
|
||||||
{ x - sep_offset, font.height - 2 } });
|
{x - sep_offset, font.height - 2}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@ void hide_bars(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active) {
|
if (!walk->active) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -224,14 +224,14 @@ void unhide_bars(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
uint32_t values[5];
|
uint32_t values[5];
|
||||||
|
|
||||||
cont_child();
|
cont_child();
|
||||||
|
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (walk->bar == XCB_NONE) {
|
if (walk->bar == XCB_NONE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -243,7 +243,8 @@ void unhide_bars(void) {
|
|||||||
values[0] = walk->rect.x;
|
values[0] = walk->rect.x;
|
||||||
if (config.position == POS_TOP)
|
if (config.position == POS_TOP)
|
||||||
values[1] = walk->rect.y;
|
values[1] = walk->rect.y;
|
||||||
else values[1] = walk->rect.y + walk->rect.h - bar_height;
|
else
|
||||||
|
values[1] = walk->rect.y + walk->rect.h - bar_height;
|
||||||
values[2] = walk->rect.w;
|
values[2] = walk->rect.w;
|
||||||
values[3] = bar_height;
|
values[3] = bar_height;
|
||||||
values[4] = XCB_STACK_MODE_ABOVE;
|
values[4] = XCB_STACK_MODE_ABOVE;
|
||||||
@ -265,10 +266,10 @@ void unhide_bars(void) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void init_colors(const struct xcb_color_strings_t *new_colors) {
|
void init_colors(const struct xcb_color_strings_t *new_colors) {
|
||||||
#define PARSE_COLOR(name, def) \
|
#define PARSE_COLOR(name, def) \
|
||||||
do { \
|
do { \
|
||||||
colors.name = get_colorpixel(new_colors->name ? new_colors->name : def); \
|
colors.name = get_colorpixel(new_colors->name ? new_colors->name : def); \
|
||||||
} while (0)
|
} while (0)
|
||||||
PARSE_COLOR(bar_fg, "#FFFFFF");
|
PARSE_COLOR(bar_fg, "#FFFFFF");
|
||||||
PARSE_COLOR(bar_bg, "#000000");
|
PARSE_COLOR(bar_bg, "#000000");
|
||||||
PARSE_COLOR(sep_fg, "#666666");
|
PARSE_COLOR(sep_fg, "#666666");
|
||||||
@ -302,7 +303,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
/* Determine, which bar was clicked */
|
/* Determine, which bar was clicked */
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
xcb_window_t bar = event->event;
|
xcb_window_t bar = event->event;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (walk->bar == bar) {
|
if (walk->bar == bar) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -314,7 +315,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Move this to extern get_ws_for_output() */
|
/* TODO: Move this to extern get_ws_for_output() */
|
||||||
TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
|
TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
|
||||||
if (cur_ws->visible) {
|
if (cur_ws->visible) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -330,6 +331,39 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
|
|
||||||
DLOG("Got Button %d\n", event->detail);
|
DLOG("Got Button %d\n", event->detail);
|
||||||
|
|
||||||
|
if (child_want_click_events()) {
|
||||||
|
/* If the child asked for click events,
|
||||||
|
* check if a status block has been clicked. */
|
||||||
|
|
||||||
|
/* First calculate width of tray area */
|
||||||
|
trayclient *trayclient;
|
||||||
|
int tray_width = 0;
|
||||||
|
TAILQ_FOREACH_REVERSE (trayclient, walk->trayclients, tc_head, tailq) {
|
||||||
|
if (!trayclient->mapped)
|
||||||
|
continue;
|
||||||
|
tray_width += (font.height + logical_px(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
int block_x = 0, last_block_x;
|
||||||
|
int offset = (walk->rect.w - (statusline_width + tray_width)) - logical_px(10);
|
||||||
|
|
||||||
|
x = original_x - offset;
|
||||||
|
if (x >= 0) {
|
||||||
|
struct status_block *block;
|
||||||
|
|
||||||
|
TAILQ_FOREACH (block, &statusline_head, blocks) {
|
||||||
|
last_block_x = block_x;
|
||||||
|
block_x += block->width + block->x_offset + block->x_append;
|
||||||
|
|
||||||
|
if (x <= block_x && x >= last_block_x) {
|
||||||
|
send_block_clicked(event->detail, block->name, block->instance, event->root_x, event->root_y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x = original_x;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event->detail) {
|
switch (event->detail) {
|
||||||
case 4:
|
case 4:
|
||||||
/* Mouse wheel up. We select the previous ws, if any.
|
/* Mouse wheel up. We select the previous ws, if any.
|
||||||
@ -351,52 +385,32 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
|
|
||||||
cur_ws = TAILQ_NEXT(cur_ws, tailq);
|
cur_ws = TAILQ_NEXT(cur_ws, tailq);
|
||||||
break;
|
break;
|
||||||
default:
|
case 1:
|
||||||
/* Check if this event regards a workspace button */
|
/* Check if this event regards a workspace button */
|
||||||
TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
|
TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
|
||||||
DLOG("x = %d\n", x);
|
DLOG("x = %d\n", x);
|
||||||
if (x >= 0 && x < cur_ws->name_width + 10) {
|
if (x >= 0 && x < cur_ws->name_width + logical_px(10)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
x -= cur_ws->name_width + 11;
|
x -= cur_ws->name_width + logical_px(11);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise, focus our currently visible workspace if it is not
|
||||||
|
* already focused */
|
||||||
if (cur_ws == NULL) {
|
if (cur_ws == NULL) {
|
||||||
/* No workspace button was pressed.
|
TAILQ_FOREACH (cur_ws, walk->workspaces, tailq) {
|
||||||
* Check if a status block has been clicked.
|
if (cur_ws->visible && !cur_ws->focused)
|
||||||
* This of course only has an effect,
|
break;
|
||||||
* if the child reported bidirectional protocol usage. */
|
|
||||||
|
|
||||||
/* First calculate width of tray area */
|
|
||||||
trayclient *trayclient;
|
|
||||||
int tray_width = 0;
|
|
||||||
TAILQ_FOREACH_REVERSE(trayclient, walk->trayclients, tc_head, tailq) {
|
|
||||||
if (!trayclient->mapped)
|
|
||||||
continue;
|
|
||||||
tray_width += (font.height + 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int block_x = 0, last_block_x;
|
|
||||||
int offset = (walk->rect.w - (statusline_width + tray_width)) - 10;
|
|
||||||
|
|
||||||
x = original_x - offset;
|
|
||||||
if (x < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct status_block *block;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(block, &statusline_head, blocks) {
|
|
||||||
last_block_x = block_x;
|
|
||||||
block_x += block->width + block->x_offset + block->x_append;
|
|
||||||
|
|
||||||
if (x <= block_x && x >= last_block_x) {
|
|
||||||
send_block_clicked(event->detail, block->name, block->instance, event->root_x, event->root_y);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (event->detail != 1)
|
|
||||||
|
/* if there is nothing to focus, we are done */
|
||||||
|
if (cur_ws == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To properly handle workspace names with double quotes in them, we need
|
/* To properly handle workspace names with double quotes in them, we need
|
||||||
@ -405,7 +419,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
* buffer, then we copy character by character. */
|
* buffer, then we copy character by character. */
|
||||||
int num_quotes = 0;
|
int num_quotes = 0;
|
||||||
size_t namelen = 0;
|
size_t namelen = 0;
|
||||||
const char *utf8_name = i3string_as_utf8(cur_ws->name);
|
const char *utf8_name = cur_ws->canonical_name;
|
||||||
for (const char *walk = utf8_name; *walk != '\0'; walk++) {
|
for (const char *walk = utf8_name; *walk != '\0'; walk++) {
|
||||||
if (*walk == '"')
|
if (*walk == '"')
|
||||||
num_quotes++;
|
num_quotes++;
|
||||||
@ -415,9 +429,9 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const size_t len = namelen + strlen("workspace \"\"") + 1;
|
const size_t len = namelen + strlen("workspace \"\"") + 1;
|
||||||
char *buffer = scalloc(len+num_quotes);
|
char *buffer = scalloc(len + num_quotes);
|
||||||
strncpy(buffer, "workspace \"", strlen("workspace \""));
|
strncpy(buffer, "workspace \"", strlen("workspace \""));
|
||||||
int inpos, outpos;
|
size_t inpos, outpos;
|
||||||
for (inpos = 0, outpos = strlen("workspace \"");
|
for (inpos = 0, outpos = strlen("workspace \"");
|
||||||
inpos < namelen;
|
inpos < namelen;
|
||||||
inpos++, outpos++) {
|
inpos++, outpos++) {
|
||||||
@ -441,19 +455,19 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
static void configure_trayclients(void) {
|
static void configure_trayclients(void) {
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH (output, outputs, slist) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int clients = 0;
|
int clients = 0;
|
||||||
TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
|
TAILQ_FOREACH_REVERSE (trayclient, output->trayclients, tc_head, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
clients++;
|
clients++;
|
||||||
|
|
||||||
DLOG("Configuring tray window %08x to x=%d\n",
|
DLOG("Configuring tray window %08x to x=%d\n",
|
||||||
trayclient->win, output->rect.w - (clients * (font.height + 2)));
|
trayclient->win, output->rect.w - (clients * (font.height + logical_px(2))));
|
||||||
uint32_t x = output->rect.w - (clients * (font.height + 2));
|
uint32_t x = output->rect.w - (clients * (font.height + logical_px(2)));
|
||||||
xcb_configure_window(xcb_connection,
|
xcb_configure_window(xcb_connection,
|
||||||
trayclient->win,
|
trayclient->win,
|
||||||
XCB_CONFIG_WINDOW_X,
|
XCB_CONFIG_WINDOW_X,
|
||||||
@ -469,7 +483,7 @@ static void configure_trayclients(void) {
|
|||||||
* supported client messages currently are _NET_SYSTEM_TRAY_OPCODE.
|
* supported client messages currently are _NET_SYSTEM_TRAY_OPCODE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_client_message(xcb_client_message_event_t* event) {
|
static void handle_client_message(xcb_client_message_event_t *event) {
|
||||||
if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] &&
|
if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] &&
|
||||||
event->format == 32) {
|
event->format == 32) {
|
||||||
DLOG("_NET_SYSTEM_TRAY_OPCODE received\n");
|
DLOG("_NET_SYSTEM_TRAY_OPCODE received\n");
|
||||||
@ -530,7 +544,7 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
|
|
||||||
DLOG("X window %08x requested docking\n", client);
|
DLOG("X window %08x requested docking\n", client);
|
||||||
i3_output *walk, *output = NULL;
|
i3_output *walk, *output = NULL;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
if (config.tray_output) {
|
if (config.tray_output) {
|
||||||
@ -548,7 +562,7 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
if (output == NULL &&
|
if (output == NULL &&
|
||||||
config.tray_output &&
|
config.tray_output &&
|
||||||
strcasecmp("primary", config.tray_output) == 0) {
|
strcasecmp("primary", config.tray_output) == 0) {
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("Falling back to output %s because no primary output is configured\n", walk->name);
|
DLOG("Falling back to output %s because no primary output is configured\n", walk->name);
|
||||||
@ -593,7 +607,7 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
0,
|
0,
|
||||||
client,
|
client,
|
||||||
XCB_EVENT_MASK_NO_EVENT,
|
XCB_EVENT_MASK_NO_EVENT,
|
||||||
(char*)ev);
|
(char *)ev);
|
||||||
free(event);
|
free(event);
|
||||||
|
|
||||||
/* Put the client inside the save set. Upon termination (whether
|
/* Put the client inside the save set. Upon termination (whether
|
||||||
@ -632,16 +646,16 @@ static void handle_client_message(xcb_client_message_event_t* event) {
|
|||||||
* See: http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
|
* See: http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_destroy_notify(xcb_destroy_notify_event_t* event) {
|
static void handle_destroy_notify(xcb_destroy_notify_event_t *event) {
|
||||||
DLOG("DestroyNotify for window = %08x, event = %08x\n", event->window, event->event);
|
DLOG("DestroyNotify for window = %08x, event = %08x\n", event->window, event->event);
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("checking output %s\n", walk->name);
|
DLOG("checking output %s\n", walk->name);
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
TAILQ_FOREACH(trayclient, walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, walk->trayclients, tailq) {
|
||||||
if (trayclient->win != event->window)
|
if (trayclient->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -661,16 +675,16 @@ static void handle_destroy_notify(xcb_destroy_notify_event_t* event) {
|
|||||||
* window. We respond by realigning the tray clients.
|
* window. We respond by realigning the tray clients.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_map_notify(xcb_map_notify_event_t* event) {
|
static void handle_map_notify(xcb_map_notify_event_t *event) {
|
||||||
DLOG("MapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
DLOG("MapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("checking output %s\n", walk->name);
|
DLOG("checking output %s\n", walk->name);
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
TAILQ_FOREACH(trayclient, walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, walk->trayclients, tailq) {
|
||||||
if (trayclient->win != event->window)
|
if (trayclient->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -689,16 +703,16 @@ static void handle_map_notify(xcb_map_notify_event_t* event) {
|
|||||||
* window. We respond by realigning the tray clients.
|
* window. We respond by realigning the tray clients.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void handle_unmap_notify(xcb_unmap_notify_event_t* event) {
|
static void handle_unmap_notify(xcb_unmap_notify_event_t *event) {
|
||||||
DLOG("UnmapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
DLOG("UnmapNotify for window = %08x, event = %08x\n", event->window, event->event);
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active)
|
if (!walk->active)
|
||||||
continue;
|
continue;
|
||||||
DLOG("checking output %s\n", walk->name);
|
DLOG("checking output %s\n", walk->name);
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
TAILQ_FOREACH(trayclient, walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, walk->trayclients, tailq) {
|
||||||
if (trayclient->win != event->window)
|
if (trayclient->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -725,11 +739,11 @@ static void handle_property_notify(xcb_property_notify_event_t *event) {
|
|||||||
DLOG("xembed_info updated\n");
|
DLOG("xembed_info updated\n");
|
||||||
trayclient *trayclient = NULL, *walk;
|
trayclient *trayclient = NULL, *walk;
|
||||||
i3_output *o_walk;
|
i3_output *o_walk;
|
||||||
SLIST_FOREACH(o_walk, outputs, slist) {
|
SLIST_FOREACH (o_walk, outputs, slist) {
|
||||||
if (!o_walk->active)
|
if (!o_walk->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TAILQ_FOREACH(walk, o_walk->trayclients, tailq) {
|
TAILQ_FOREACH (walk, o_walk->trayclients, tailq) {
|
||||||
if (walk->win != event->window)
|
if (walk->win != event->window)
|
||||||
continue;
|
continue;
|
||||||
trayclient = walk;
|
trayclient = walk;
|
||||||
@ -788,12 +802,12 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
|
|||||||
|
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH (output, outputs, slist) {
|
||||||
if (!output->active)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int clients = 0;
|
int clients = 0;
|
||||||
TAILQ_FOREACH_REVERSE(trayclient, output->trayclients, tc_head, tailq) {
|
TAILQ_FOREACH_REVERSE (trayclient, output->trayclients, tc_head, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
clients++;
|
clients++;
|
||||||
@ -847,31 +861,31 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
|
|||||||
break;
|
break;
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
/* Button-press-events are mouse-buttons clicked on one of our bars */
|
/* Button-press-events are mouse-buttons clicked on one of our bars */
|
||||||
handle_button((xcb_button_press_event_t*) event);
|
handle_button((xcb_button_press_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
/* Client messages are used for client-to-client communication, for
|
/* Client messages are used for client-to-client communication, for
|
||||||
* example system tray widgets talk to us directly via client messages. */
|
* example system tray widgets talk to us directly via client messages. */
|
||||||
handle_client_message((xcb_client_message_event_t*) event);
|
handle_client_message((xcb_client_message_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_DESTROY_NOTIFY:
|
case XCB_DESTROY_NOTIFY:
|
||||||
/* DestroyNotify signifies the end of the XEmbed protocol */
|
/* DestroyNotify signifies the end of the XEmbed protocol */
|
||||||
handle_destroy_notify((xcb_destroy_notify_event_t*) event);
|
handle_destroy_notify((xcb_destroy_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_UNMAP_NOTIFY:
|
case XCB_UNMAP_NOTIFY:
|
||||||
/* UnmapNotify is received when a tray client hides its window. */
|
/* UnmapNotify is received when a tray client hides its window. */
|
||||||
handle_unmap_notify((xcb_unmap_notify_event_t*) event);
|
handle_unmap_notify((xcb_unmap_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_MAP_NOTIFY:
|
case XCB_MAP_NOTIFY:
|
||||||
handle_map_notify((xcb_map_notify_event_t*) event);
|
handle_map_notify((xcb_map_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_PROPERTY_NOTIFY:
|
case XCB_PROPERTY_NOTIFY:
|
||||||
/* PropertyNotify */
|
/* PropertyNotify */
|
||||||
handle_property_notify((xcb_property_notify_event_t*) event);
|
handle_property_notify((xcb_property_notify_event_t *)event);
|
||||||
break;
|
break;
|
||||||
case XCB_CONFIGURE_REQUEST:
|
case XCB_CONFIGURE_REQUEST:
|
||||||
/* ConfigureRequest, sent by a tray child */
|
/* ConfigureRequest, sent by a tray child */
|
||||||
handle_configure_request((xcb_configure_request_event_t*) event);
|
handle_configure_request((xcb_configure_request_event_t *)event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(event);
|
free(event);
|
||||||
@ -897,7 +911,7 @@ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
DLOG("Got XKB-Event!\n");
|
DLOG("Got XKB-Event!\n");
|
||||||
|
|
||||||
while (XPending(xkb_dpy)) {
|
while (XPending(xkb_dpy)) {
|
||||||
XNextEvent(xkb_dpy, (XEvent*)&ev);
|
XNextEvent(xkb_dpy, (XEvent *)&ev);
|
||||||
|
|
||||||
if (ev.type != xkb_event_base) {
|
if (ev.type != xkb_event_base) {
|
||||||
ELOG("No Xkb-Event!\n");
|
ELOG("No Xkb-Event!\n");
|
||||||
@ -913,31 +927,31 @@ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
|
|||||||
modstate = mods & config.modifier;
|
modstate = mods & config.modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DLOGMOD(modmask, status) \
|
#define DLOGMOD(modmask, status) \
|
||||||
do { \
|
do { \
|
||||||
switch (modmask) { \
|
switch (modmask) { \
|
||||||
case ShiftMask: \
|
case ShiftMask: \
|
||||||
DLOG("ShiftMask got " #status "!\n"); \
|
DLOG("ShiftMask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case ControlMask: \
|
case ControlMask: \
|
||||||
DLOG("ControlMask got " #status "!\n"); \
|
DLOG("ControlMask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod1Mask: \
|
case Mod1Mask: \
|
||||||
DLOG("Mod1Mask got " #status "!\n"); \
|
DLOG("Mod1Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod2Mask: \
|
case Mod2Mask: \
|
||||||
DLOG("Mod2Mask got " #status "!\n"); \
|
DLOG("Mod2Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod3Mask: \
|
case Mod3Mask: \
|
||||||
DLOG("Mod3Mask got " #status "!\n"); \
|
DLOG("Mod3Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod4Mask: \
|
case Mod4Mask: \
|
||||||
DLOG("Mod4Mask got " #status "!\n"); \
|
DLOG("Mod4Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
case Mod5Mask: \
|
case Mod5Mask: \
|
||||||
DLOG("Mod5Mask got " #status "!\n"); \
|
DLOG("Mod5Mask got " #status "!\n"); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
if (modstate != mod_pressed) {
|
if (modstate != mod_pressed) {
|
||||||
@ -971,9 +985,9 @@ char *init_xcb_early() {
|
|||||||
conn = xcb_connection;
|
conn = xcb_connection;
|
||||||
DLOG("Connected to xcb\n");
|
DLOG("Connected to xcb\n");
|
||||||
|
|
||||||
/* We have to request the atoms we need */
|
/* We have to request the atoms we need */
|
||||||
#define ATOM_DO(name) atom_cookies[name] = xcb_intern_atom(xcb_connection, 0, strlen(#name), #name);
|
#define ATOM_DO(name) atom_cookies[name] = xcb_intern_atom(xcb_connection, 0, strlen(#name), #name);
|
||||||
#include "xcb_atoms.def"
|
#include "xcb_atoms.def"
|
||||||
|
|
||||||
root_screen = xcb_aux_get_screen(xcb_connection, screen);
|
root_screen = xcb_aux_get_screen(xcb_connection, screen);
|
||||||
xcb_root = root_screen->root;
|
xcb_root = root_screen->root;
|
||||||
@ -981,7 +995,7 @@ char *init_xcb_early() {
|
|||||||
/* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
|
/* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
|
||||||
* this way, we can choose to crop it */
|
* this way, we can choose to crop it */
|
||||||
uint32_t mask = XCB_GC_FOREGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND;
|
||||||
uint32_t vals[] = { colors.bar_bg, colors.bar_bg };
|
uint32_t vals[] = {colors.bar_bg, colors.bar_bg};
|
||||||
|
|
||||||
statusline_clear = xcb_generate_id(xcb_connection);
|
statusline_clear = xcb_generate_id(xcb_connection);
|
||||||
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
||||||
@ -1005,7 +1019,6 @@ char *init_xcb_early() {
|
|||||||
root_screen->width_in_pixels,
|
root_screen->width_in_pixels,
|
||||||
root_screen->height_in_pixels);
|
root_screen->height_in_pixels);
|
||||||
|
|
||||||
|
|
||||||
/* The various Watchers to communicate with xcb */
|
/* The various Watchers to communicate with xcb */
|
||||||
xcb_io = smalloc(sizeof(ev_io));
|
xcb_io = smalloc(sizeof(ev_io));
|
||||||
xcb_prep = smalloc(sizeof(ev_prepare));
|
xcb_prep = smalloc(sizeof(ev_prepare));
|
||||||
@ -1086,7 +1099,7 @@ void register_xkb_keyevents() {
|
|||||||
*/
|
*/
|
||||||
void deregister_xkb_keyevents() {
|
void deregister_xkb_keyevents() {
|
||||||
if (xkb_dpy != NULL) {
|
if (xkb_dpy != NULL) {
|
||||||
ev_io_stop (main_loop, xkb_io);
|
ev_io_stop(main_loop, xkb_io);
|
||||||
XCloseDisplay(xkb_dpy);
|
XCloseDisplay(xkb_dpy);
|
||||||
close(xkb_io->fd);
|
close(xkb_io->fd);
|
||||||
FREE(xkb_io);
|
FREE(xkb_io);
|
||||||
@ -1107,7 +1120,7 @@ void init_xcb_late(char *fontname) {
|
|||||||
font = load_font(fontname, true);
|
font = load_font(fontname, true);
|
||||||
set_font(&font);
|
set_font(&font);
|
||||||
DLOG("Calculated Font-height: %d\n", font.height);
|
DLOG("Calculated Font-height: %d\n", font.height);
|
||||||
bar_height = font.height + 6;
|
bar_height = font.height + logical_px(6);
|
||||||
|
|
||||||
xcb_flush(xcb_connection);
|
xcb_flush(xcb_connection);
|
||||||
|
|
||||||
@ -1121,8 +1134,8 @@ void init_xcb_late(char *fontname) {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void send_tray_clientmessage(void) {
|
static void send_tray_clientmessage(void) {
|
||||||
uint8_t buffer[32] = { 0 };
|
uint8_t buffer[32] = {0};
|
||||||
xcb_client_message_event_t *ev = (xcb_client_message_event_t*)buffer;
|
xcb_client_message_event_t *ev = (xcb_client_message_event_t *)buffer;
|
||||||
|
|
||||||
ev->response_type = XCB_CLIENT_MESSAGE;
|
ev->response_type = XCB_CLIENT_MESSAGE;
|
||||||
ev->window = xcb_root;
|
ev->window = xcb_root;
|
||||||
@ -1136,10 +1149,9 @@ static void send_tray_clientmessage(void) {
|
|||||||
0,
|
0,
|
||||||
xcb_root,
|
xcb_root,
|
||||||
0xFFFFFF,
|
0xFFFFFF,
|
||||||
(char*)buffer);
|
(char *)buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes tray support by requesting the appropriate _NET_SYSTEM_TRAY atom
|
* Initializes tray support by requesting the appropriate _NET_SYSTEM_TRAY atom
|
||||||
* for the X11 display we are running on, then acquiring the selection for this
|
* for the X11 display we are running on, then acquiring the selection for this
|
||||||
@ -1158,7 +1170,7 @@ void init_tray(void) {
|
|||||||
/* tray support: we need a window to own the selection */
|
/* tray support: we need a window to own the selection */
|
||||||
selwin = xcb_generate_id(xcb_connection);
|
selwin = xcb_generate_id(xcb_connection);
|
||||||
uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT;
|
uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT;
|
||||||
uint32_t selval[] = { 1 };
|
uint32_t selval[] = {1};
|
||||||
xcb_create_window(xcb_connection,
|
xcb_create_window(xcb_connection,
|
||||||
root_screen->root_depth,
|
root_screen->root_depth,
|
||||||
selwin,
|
selwin,
|
||||||
@ -1207,8 +1219,9 @@ void init_tray(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selreply->owner != selwin) {
|
if (selreply->owner != selwin) {
|
||||||
ELOG("Could not set the %s selection. " \
|
ELOG("Could not set the %s selection. "
|
||||||
"Maybe another tray is already running?\n", atomname);
|
"Maybe another tray is already running?\n",
|
||||||
|
atomname);
|
||||||
/* NOTE that this error is not fatal. We just can’t provide tray
|
/* NOTE that this error is not fatal. We just can’t provide tray
|
||||||
* functionality */
|
* functionality */
|
||||||
free(selreply);
|
free(selreply);
|
||||||
@ -1267,7 +1280,7 @@ void init_tray_colors(void) {
|
|||||||
void clean_xcb(void) {
|
void clean_xcb(void) {
|
||||||
i3_output *o_walk;
|
i3_output *o_walk;
|
||||||
free_workspaces();
|
free_workspaces();
|
||||||
SLIST_FOREACH(o_walk, outputs, slist) {
|
SLIST_FOREACH (o_walk, outputs, slist) {
|
||||||
destroy_window(o_walk);
|
destroy_window(o_walk);
|
||||||
FREE(o_walk->trayclients);
|
FREE(o_walk->trayclients);
|
||||||
FREE(o_walk->workspaces);
|
FREE(o_walk->workspaces);
|
||||||
@ -1294,15 +1307,16 @@ void clean_xcb(void) {
|
|||||||
*/
|
*/
|
||||||
void get_atoms(void) {
|
void get_atoms(void) {
|
||||||
xcb_intern_atom_reply_t *reply;
|
xcb_intern_atom_reply_t *reply;
|
||||||
#define ATOM_DO(name) reply = xcb_intern_atom_reply(xcb_connection, atom_cookies[name], NULL); \
|
#define ATOM_DO(name) \
|
||||||
if (reply == NULL) { \
|
reply = xcb_intern_atom_reply(xcb_connection, atom_cookies[name], NULL); \
|
||||||
ELOG("Could not get atom %s\n", #name); \
|
if (reply == NULL) { \
|
||||||
exit(EXIT_FAILURE); \
|
ELOG("Could not get atom %s\n", #name); \
|
||||||
} \
|
exit(EXIT_FAILURE); \
|
||||||
atoms[name] = reply->atom; \
|
} \
|
||||||
free(reply);
|
atoms[name] = reply->atom; \
|
||||||
|
free(reply);
|
||||||
|
|
||||||
#include "xcb_atoms.def"
|
#include "xcb_atoms.def"
|
||||||
DLOG("Got Atoms\n");
|
DLOG("Got Atoms\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1338,14 +1352,14 @@ void kick_tray_clients(i3_output *output) {
|
|||||||
/* Fake a DestroyNotify so that Qt re-adds tray icons.
|
/* Fake a DestroyNotify so that Qt re-adds tray icons.
|
||||||
* We cannot actually destroy the window because then Qt will not restore
|
* We cannot actually destroy the window because then Qt will not restore
|
||||||
* its event mask on the new window. */
|
* its event mask on the new window. */
|
||||||
uint8_t buffer[32] = { 0 };
|
uint8_t buffer[32] = {0};
|
||||||
xcb_destroy_notify_event_t *event = (xcb_destroy_notify_event_t*)buffer;
|
xcb_destroy_notify_event_t *event = (xcb_destroy_notify_event_t *)buffer;
|
||||||
|
|
||||||
event->response_type = XCB_DESTROY_NOTIFY;
|
event->response_type = XCB_DESTROY_NOTIFY;
|
||||||
event->event = selwin;
|
event->event = selwin;
|
||||||
event->window = selwin;
|
event->window = selwin;
|
||||||
|
|
||||||
xcb_send_event(conn, false, selwin, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)event);
|
xcb_send_event(conn, false, selwin, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *)event);
|
||||||
|
|
||||||
send_tray_clientmessage();
|
send_tray_clientmessage();
|
||||||
}
|
}
|
||||||
@ -1384,7 +1398,7 @@ void realloc_sl_buffer(void) {
|
|||||||
bar_height);
|
bar_height);
|
||||||
|
|
||||||
uint32_t mask = XCB_GC_FOREGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND;
|
||||||
uint32_t vals[2] = { colors.bar_bg, colors.bar_bg };
|
uint32_t vals[2] = {colors.bar_bg, colors.bar_bg};
|
||||||
xcb_free_gc(xcb_connection, statusline_clear);
|
xcb_free_gc(xcb_connection, statusline_clear);
|
||||||
statusline_clear = xcb_generate_id(xcb_connection);
|
statusline_clear = xcb_generate_id(xcb_connection);
|
||||||
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
|
||||||
@ -1408,7 +1422,6 @@ void realloc_sl_buffer(void) {
|
|||||||
xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) {
|
xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1421,7 +1434,7 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
static bool tray_configured = false;
|
static bool tray_configured = false;
|
||||||
|
|
||||||
i3_output *walk;
|
i3_output *walk;
|
||||||
SLIST_FOREACH(walk, outputs, slist) {
|
SLIST_FOREACH (walk, outputs, slist) {
|
||||||
if (!walk->active) {
|
if (!walk->active) {
|
||||||
/* If an output is not active, we destroy its bar */
|
/* If an output is not active, we destroy its bar */
|
||||||
/* FIXME: Maybe we rather want to unmap? */
|
/* FIXME: Maybe we rather want to unmap? */
|
||||||
@ -1504,7 +1517,7 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
XCB_ATOM_ATOM,
|
XCB_ATOM_ATOM,
|
||||||
32,
|
32,
|
||||||
1,
|
1,
|
||||||
(unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]);
|
(unsigned char *)&atoms[_NET_WM_WINDOW_TYPE_DOCK]);
|
||||||
|
|
||||||
/* We need to tell i3, where to reserve space for i3bar */
|
/* We need to tell i3, where to reserve space for i3bar */
|
||||||
/* left, right, top, bottom, left_start_y, left_end_y,
|
/* left, right, top, bottom, left_start_y, left_end_y,
|
||||||
@ -1524,7 +1537,9 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
uint32_t top_end_x;
|
uint32_t top_end_x;
|
||||||
uint32_t bottom_start_x;
|
uint32_t bottom_start_x;
|
||||||
uint32_t bottom_end_x;
|
uint32_t bottom_end_x;
|
||||||
} __attribute__((__packed__)) strut_partial = {0,};
|
} __attribute__((__packed__)) strut_partial;
|
||||||
|
memset(&strut_partial, 0, sizeof(strut_partial));
|
||||||
|
|
||||||
switch (config.position) {
|
switch (config.position) {
|
||||||
case POS_NONE:
|
case POS_NONE:
|
||||||
break;
|
break;
|
||||||
@ -1563,13 +1578,13 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
|
map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xcb_request_failed(win_cookie, "Could not create window") ||
|
if (xcb_request_failed(win_cookie, "Could not create window") ||
|
||||||
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
||||||
xcb_request_failed(dock_cookie, "Could not set dock mode") ||
|
xcb_request_failed(dock_cookie, "Could not set dock mode") ||
|
||||||
xcb_request_failed(class_cookie, "Could not set WM_CLASS") ||
|
xcb_request_failed(class_cookie, "Could not set WM_CLASS") ||
|
||||||
xcb_request_failed(name_cookie, "Could not set WM_NAME") ||
|
xcb_request_failed(name_cookie, "Could not set WM_NAME") ||
|
||||||
xcb_request_failed(strut_cookie, "Could not set strut") ||
|
xcb_request_failed(strut_cookie, "Could not set strut") ||
|
||||||
xcb_request_failed(gc_cookie, "Could not create graphical context") ||
|
xcb_request_failed(gc_cookie, "Could not create graphical context") ||
|
||||||
((config.hide_on_modifier == M_DOCK) && xcb_request_failed(map_cookie, "Could not map window"))) {
|
((config.hide_on_modifier == M_DOCK) && xcb_request_failed(map_cookie, "Could not map window"))) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -1581,9 +1596,9 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
* VGA-1 but output == [HDMI-1]).
|
* VGA-1 but output == [HDMI-1]).
|
||||||
*/
|
*/
|
||||||
i3_output *output;
|
i3_output *output;
|
||||||
SLIST_FOREACH(output, outputs, slist) {
|
SLIST_FOREACH (output, outputs, slist) {
|
||||||
if (strcasecmp(output->name, tray_output) == 0 ||
|
if (strcasecmp(output->name, tray_output) == 0 ||
|
||||||
(strcasecmp(tray_output, "primary") == 0 && output->primary)) {
|
(strcasecmp(tray_output, "primary") == 0 && output->primary)) {
|
||||||
init_tray();
|
init_tray();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1650,9 +1665,9 @@ void reconfig_windows(bool redraw_bars) {
|
|||||||
|
|
||||||
if (xcb_request_failed(cfg_cookie, "Could not reconfigure window") ||
|
if (xcb_request_failed(cfg_cookie, "Could not reconfigure window") ||
|
||||||
xcb_request_failed(chg_cookie, "Could not change window") ||
|
xcb_request_failed(chg_cookie, "Could not change window") ||
|
||||||
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
xcb_request_failed(pm_cookie, "Could not create pixmap") ||
|
||||||
(redraw_bars && (xcb_request_failed(umap_cookie, "Could not unmap window") ||
|
(redraw_bars && (xcb_request_failed(umap_cookie, "Could not unmap window") ||
|
||||||
(config.hide_on_modifier == M_DOCK && xcb_request_failed(map_cookie, "Could not map window"))))) {
|
(config.hide_on_modifier == M_DOCK && xcb_request_failed(map_cookie, "Could not map window"))))) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1670,7 +1685,7 @@ void draw_bars(bool unhide) {
|
|||||||
refresh_statusline();
|
refresh_statusline();
|
||||||
|
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
SLIST_FOREACH(outputs_walk, outputs, slist) {
|
SLIST_FOREACH (outputs_walk, outputs, slist) {
|
||||||
if (!outputs_walk->active) {
|
if (!outputs_walk->active) {
|
||||||
DLOG("Output %s inactive, skipping...\n", outputs_walk->name);
|
DLOG("Output %s inactive, skipping...\n", outputs_walk->name);
|
||||||
continue;
|
continue;
|
||||||
@ -1685,7 +1700,7 @@ void draw_bars(bool unhide) {
|
|||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
XCB_GC_FOREGROUND,
|
XCB_GC_FOREGROUND,
|
||||||
&color);
|
&color);
|
||||||
xcb_rectangle_t rect = { 0, 0, outputs_walk->rect.w, bar_height };
|
xcb_rectangle_t rect = {0, 0, outputs_walk->rect.w, bar_height};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
@ -1700,7 +1715,7 @@ void draw_bars(bool unhide) {
|
|||||||
* position */
|
* position */
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
int traypx = 0;
|
int traypx = 0;
|
||||||
TAILQ_FOREACH(trayclient, outputs_walk->trayclients, tailq) {
|
TAILQ_FOREACH (trayclient, outputs_walk->trayclients, tailq) {
|
||||||
if (!trayclient->mapped)
|
if (!trayclient->mapped)
|
||||||
continue;
|
continue;
|
||||||
/* We assume the tray icons are quadratic (we use the font
|
/* We assume the tray icons are quadratic (we use the font
|
||||||
@ -1717,12 +1732,12 @@ void draw_bars(bool unhide) {
|
|||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
MAX(0, (int16_t)(statusline_width - outputs_walk->rect.w + 4)), 0,
|
MAX(0, (int16_t)(statusline_width - outputs_walk->rect.w + 4)), 0,
|
||||||
MAX(0, (int16_t)(outputs_walk->rect.w - statusline_width - traypx - 4)), 3,
|
MAX(0, (int16_t)(outputs_walk->rect.w - statusline_width - traypx - 4)), 3,
|
||||||
MIN(outputs_walk->rect.w - traypx - 4, statusline_width), font.height + 2);
|
MIN(outputs_walk->rect.w - traypx - 4, (int)statusline_width), font.height + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.disable_ws) {
|
if (!config.disable_ws) {
|
||||||
i3_ws *ws_walk;
|
i3_ws *ws_walk;
|
||||||
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
TAILQ_FOREACH (ws_walk, outputs_walk->workspaces, tailq) {
|
||||||
DLOG("Drawing Button for WS %s at x = %d, len = %d\n",
|
DLOG("Drawing Button for WS %s at x = %d, len = %d\n",
|
||||||
i3string_as_utf8(ws_walk->name), i, ws_walk->name_width);
|
i3string_as_utf8(ws_walk->name), i, ws_walk->name_width);
|
||||||
uint32_t fg_color = colors.inactive_ws_fg;
|
uint32_t fg_color = colors.inactive_ws_fg;
|
||||||
@ -1747,23 +1762,29 @@ void draw_bars(bool unhide) {
|
|||||||
unhide = true;
|
unhide = true;
|
||||||
}
|
}
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
||||||
uint32_t vals_border[] = { border_color, border_color };
|
uint32_t vals_border[] = {border_color, border_color};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals_border);
|
vals_border);
|
||||||
xcb_rectangle_t rect_border = { i, 1, ws_walk->name_width + 10, font.height + 4 };
|
xcb_rectangle_t rect_border = {i,
|
||||||
|
logical_px(1),
|
||||||
|
ws_walk->name_width + logical_px(10),
|
||||||
|
font.height + logical_px(4)};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
1,
|
1,
|
||||||
&rect_border);
|
&rect_border);
|
||||||
uint32_t vals[] = { bg_color, bg_color };
|
uint32_t vals[] = {bg_color, bg_color};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals);
|
vals);
|
||||||
xcb_rectangle_t rect = { i + 1, 2, ws_walk->name_width + 8, font.height + 2 };
|
xcb_rectangle_t rect = {i + logical_px(1),
|
||||||
|
2 * logical_px(1),
|
||||||
|
ws_walk->name_width + logical_px(8),
|
||||||
|
font.height + logical_px(2)};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
@ -1771,9 +1792,8 @@ void draw_bars(bool unhide) {
|
|||||||
&rect);
|
&rect);
|
||||||
set_font_colors(outputs_walk->bargc, fg_color, bg_color);
|
set_font_colors(outputs_walk->bargc, fg_color, bg_color);
|
||||||
draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc,
|
draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc,
|
||||||
i + 5, 3, ws_walk->name_width);
|
i + logical_px(5), 3 * logical_px(1), ws_walk->name_width);
|
||||||
i += 10 + ws_walk->name_width + 1;
|
i += logical_px(10) + ws_walk->name_width + logical_px(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1782,24 +1802,24 @@ void draw_bars(bool unhide) {
|
|||||||
uint32_t bg_color = colors.urgent_ws_bg;
|
uint32_t bg_color = colors.urgent_ws_bg;
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
|
||||||
|
|
||||||
uint32_t vals_border[] = { colors.urgent_ws_border, colors.urgent_ws_border };
|
uint32_t vals_border[] = {colors.urgent_ws_border, colors.urgent_ws_border};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals_border);
|
vals_border);
|
||||||
xcb_rectangle_t rect_border = { i, 1, binding.width + 10, font.height + 4 };
|
xcb_rectangle_t rect_border = {i, 1, binding.width + 10, font.height + 4};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
1,
|
1,
|
||||||
&rect_border);
|
&rect_border);
|
||||||
|
|
||||||
uint32_t vals[] = { bg_color, bg_color };
|
uint32_t vals[] = {bg_color, bg_color};
|
||||||
xcb_change_gc(xcb_connection,
|
xcb_change_gc(xcb_connection,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
mask,
|
mask,
|
||||||
vals);
|
vals);
|
||||||
xcb_rectangle_t rect = { i + 1, 2, binding.width + 8, font.height + 2 };
|
xcb_rectangle_t rect = {i + 1, 2, binding.width + 8, font.height + 2};
|
||||||
xcb_poly_fill_rectangle(xcb_connection,
|
xcb_poly_fill_rectangle(xcb_connection,
|
||||||
outputs_walk->buffer,
|
outputs_walk->buffer,
|
||||||
outputs_walk->bargc,
|
outputs_walk->bargc,
|
||||||
@ -1817,8 +1837,8 @@ void draw_bars(bool unhide) {
|
|||||||
|
|
||||||
/* Assure the bar is hidden/unhidden according to the specified hidden_state and mode */
|
/* Assure the bar is hidden/unhidden according to the specified hidden_state and mode */
|
||||||
if (mod_pressed ||
|
if (mod_pressed ||
|
||||||
config.hidden_state == S_SHOW ||
|
config.hidden_state == S_SHOW ||
|
||||||
unhide) {
|
unhide) {
|
||||||
unhide_bars();
|
unhide_bars();
|
||||||
} else if (config.hide_on_modifier == M_HIDE) {
|
} else if (config.hide_on_modifier == M_HIDE) {
|
||||||
hide_bars();
|
hide_bars();
|
||||||
@ -1833,7 +1853,7 @@ void draw_bars(bool unhide) {
|
|||||||
*/
|
*/
|
||||||
void redraw_bars(void) {
|
void redraw_bars(void) {
|
||||||
i3_output *outputs_walk;
|
i3_output *outputs_walk;
|
||||||
SLIST_FOREACH(outputs_walk, outputs, slist) {
|
SLIST_FOREACH (outputs_walk, outputs, slist) {
|
||||||
if (!outputs_walk->active) {
|
if (!outputs_walk->active) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +79,12 @@
|
|||||||
#include "scratchpad.h"
|
#include "scratchpad.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "commands_parser.h"
|
#include "commands_parser.h"
|
||||||
|
#include "bindings.h"
|
||||||
#include "config_directives.h"
|
#include "config_directives.h"
|
||||||
#include "config_parser.h"
|
#include "config_parser.h"
|
||||||
#include "fake_outputs.h"
|
#include "fake_outputs.h"
|
||||||
#include "display_version.h"
|
#include "display_version.h"
|
||||||
|
#include "restore_layout.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* assignments.c: Assignments for specific windows (for_window).
|
* assignments.c: Assignments for specific windows (for_window).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_ASSIGNMENTS_H
|
#pragma once
|
||||||
#define I3_ASSIGNMENTS_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the list of assignments for the given window and runs all matching
|
* Checks the list of assignments for the given window and runs all matching
|
||||||
@ -22,5 +21,3 @@ void run_assignments(i3Window *window);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Assignment *assignment_for(i3Window *window, int type);
|
Assignment *assignment_for(i3Window *window, int type);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -3,6 +3,7 @@ xmacro(_NET_SUPPORTING_WM_CHECK)
|
|||||||
xmacro(_NET_WM_NAME)
|
xmacro(_NET_WM_NAME)
|
||||||
xmacro(_NET_WM_STATE_FULLSCREEN)
|
xmacro(_NET_WM_STATE_FULLSCREEN)
|
||||||
xmacro(_NET_WM_STATE_DEMANDS_ATTENTION)
|
xmacro(_NET_WM_STATE_DEMANDS_ATTENTION)
|
||||||
|
xmacro(_NET_WM_STATE_MODAL)
|
||||||
xmacro(_NET_WM_STATE)
|
xmacro(_NET_WM_STATE)
|
||||||
xmacro(_NET_WM_WINDOW_TYPE)
|
xmacro(_NET_WM_WINDOW_TYPE)
|
||||||
xmacro(_NET_WM_WINDOW_TYPE_DOCK)
|
xmacro(_NET_WM_WINDOW_TYPE_DOCK)
|
||||||
@ -12,6 +13,7 @@ xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR)
|
|||||||
xmacro(_NET_WM_WINDOW_TYPE_SPLASH)
|
xmacro(_NET_WM_WINDOW_TYPE_SPLASH)
|
||||||
xmacro(_NET_WM_DESKTOP)
|
xmacro(_NET_WM_DESKTOP)
|
||||||
xmacro(_NET_WM_STRUT_PARTIAL)
|
xmacro(_NET_WM_STRUT_PARTIAL)
|
||||||
|
xmacro(_NET_CLIENT_LIST)
|
||||||
xmacro(_NET_CLIENT_LIST_STACKING)
|
xmacro(_NET_CLIENT_LIST_STACKING)
|
||||||
xmacro(_NET_CURRENT_DESKTOP)
|
xmacro(_NET_CURRENT_DESKTOP)
|
||||||
xmacro(_NET_ACTIVE_WINDOW)
|
xmacro(_NET_ACTIVE_WINDOW)
|
||||||
@ -31,3 +33,4 @@ xmacro(I3_SHMLOG_PATH)
|
|||||||
xmacro(I3_PID)
|
xmacro(I3_PID)
|
||||||
xmacro(_NET_REQUEST_FRAME_EXTENTS)
|
xmacro(_NET_REQUEST_FRAME_EXTENTS)
|
||||||
xmacro(_NET_FRAME_EXTENTS)
|
xmacro(_NET_FRAME_EXTENTS)
|
||||||
|
xmacro(_MOTIF_WM_HINTS)
|
||||||
|
69
include/bindings.h
Normal file
69
include/bindings.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* vim:ts=4:sw=4:expandtab
|
||||||
|
*
|
||||||
|
* i3 - an improved dynamic tiling window manager
|
||||||
|
* © 2009-2014 Michael Stapelberg and contributors (see also: LICENSE)
|
||||||
|
*
|
||||||
|
* bindings.h: Functions for configuring, finding, and running bindings.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern pid_t command_error_nagbar_pid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the default mode.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const char *DEFAULT_BINDING_MODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a binding from config parameters given as strings and returns a
|
||||||
|
* pointer to the binding structure. Returns NULL if the input code could not
|
||||||
|
* be parsed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
|
||||||
|
const char *release, const char *command, const char *mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab the bound keys (tell X to send us keypress events for those keycodes)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the Binding that matches the given xcb event or NULL if
|
||||||
|
* no such binding exists.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Binding *get_binding_from_xcb_event(xcb_generic_event_t *event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates keysymbols to keycodes for all bindings which use keysyms.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void translate_keysyms(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the key bindings to the given mode, if the mode exists
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void switch_mode(const char *new_mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for duplicate key bindings (the same keycode or keysym is configured
|
||||||
|
* more than once). If a duplicate binding is found, a message is printed to
|
||||||
|
* stderr and the has_errors variable is set to true, which will start
|
||||||
|
* i3-nagbar.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void check_for_duplicate_bindings(struct context *context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given binding and handles parse errors. Returns a CommandResult for
|
||||||
|
* running the binding's command. Caller should render tree if
|
||||||
|
* needs_tree_render is true. Free with command_result_free().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CommandResult *run_binding(Binding *bind);
|
@ -7,8 +7,7 @@
|
|||||||
* click.c: Button press (mouse click) events.
|
* click.c: Button press (mouse click) events.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_CLICK_H
|
#pragma once
|
||||||
#define I3_CLICK_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The button press X callback. This function determines whether the floating
|
* The button press X callback. This function determines whether the floating
|
||||||
@ -19,5 +18,3 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int handle_button_press(xcb_button_press_event_t *event);
|
int handle_button_press(xcb_button_press_event_t *event);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,9 +7,6 @@
|
|||||||
* cmdparse.y: the parser for commands you send to i3 (or bind on keys)
|
* cmdparse.y: the parser for commands you send to i3 (or bind on keys)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_CMDPARSE_H
|
#pragma once
|
||||||
#define I3_CMDPARSE_H
|
|
||||||
|
|
||||||
char *parse_cmd(const char *new);
|
char *parse_cmd(const char *new);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,13 +7,12 @@
|
|||||||
* commands.c: all command functions (see commands_parser.c)
|
* commands.c: all command functions (see commands_parser.c)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_COMMANDS_H
|
#pragma once
|
||||||
#define I3_COMMANDS_H
|
|
||||||
|
|
||||||
#include "commands_parser.h"
|
#include "commands_parser.h"
|
||||||
|
|
||||||
/** The beginning of the prototype for every cmd_ function. */
|
/** The beginning of the prototype for every cmd_ function. */
|
||||||
#define I3_CMD Match *current_match, struct CommandResult *cmd_output
|
#define I3_CMD Match *current_match, struct CommandResultIR *cmd_output
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the specified 'Match' data structure and the initial state of
|
* Initializes the specified 'Match' data structure and the initial state of
|
||||||
@ -288,5 +287,3 @@ void cmd_shmlog(I3_CMD, char *argument);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_debuglog(I3_CMD, char *argument);
|
void cmd_debuglog(I3_CMD, char *argument);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,22 +7,17 @@
|
|||||||
* commands.c: all command functions (see commands_parser.c)
|
* commands.c: all command functions (see commands_parser.c)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_COMMANDS_PARSER_H
|
#pragma once
|
||||||
#define I3_COMMANDS_PARSER_H
|
|
||||||
|
|
||||||
#include <yajl/yajl_gen.h>
|
#include <yajl/yajl_gen.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Holds the result of a call to any command. When calling
|
* Holds an intermediate represenation of the result of a call to any command.
|
||||||
* parse_command("floating enable, border none"), the parser will internally
|
* When calling parse_command("floating enable, border none"), the parser will
|
||||||
* use a struct CommandResult when calling cmd_floating and cmd_border.
|
* internally use this struct when calling cmd_floating and cmd_border.
|
||||||
* parse_command will also return another struct CommandResult, whose
|
|
||||||
* json_output is set to a map of individual json_outputs and whose
|
|
||||||
* needs_tree_trender is true if any individual needs_tree_render was true.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
struct CommandResult {
|
struct CommandResultIR {
|
||||||
/* The JSON generator to append a reply to. */
|
/* The JSON generator to append a reply to (may be NULL). */
|
||||||
yajl_gen json_gen;
|
yajl_gen json_gen;
|
||||||
|
|
||||||
/* The next state to transition to. Passed to the function so that we can
|
/* The next state to transition to. Passed to the function so that we can
|
||||||
@ -34,6 +29,31 @@ struct CommandResult {
|
|||||||
bool needs_tree_render;
|
bool needs_tree_render;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandResult *parse_command(const char *input);
|
typedef struct CommandResult CommandResult;
|
||||||
|
|
||||||
#endif
|
/**
|
||||||
|
* A struct that contains useful information about the result of a command as a
|
||||||
|
* whole (e.g. a compound command like "floating enable, border none").
|
||||||
|
* needs_tree_render is true if needs_tree_render of any individual command was
|
||||||
|
* true.
|
||||||
|
*/
|
||||||
|
struct CommandResult {
|
||||||
|
bool parse_error;
|
||||||
|
/* the error_message is currently only set for parse errors */
|
||||||
|
char *error_message;
|
||||||
|
bool needs_tree_render;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses and executes the given command. If a caller-allocated yajl_gen is
|
||||||
|
* passed, a json reply will be generated in the format specified by the ipc
|
||||||
|
* protocol. Pass NULL if no json reply is required.
|
||||||
|
*
|
||||||
|
* Free the returned CommandResult with command_result_free().
|
||||||
|
*/
|
||||||
|
CommandResult *parse_command(const char *input, yajl_gen gen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a CommandResult
|
||||||
|
*/
|
||||||
|
void command_result_free(CommandResult *result);
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
* …).
|
* …).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_CON_H
|
#pragma once
|
||||||
#define I3_CON_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new container (and attach it to the given parent, if not NULL).
|
* Create a new container (and attach it to the given parent, if not NULL).
|
||||||
@ -38,6 +37,12 @@ void con_focus(Con *con);
|
|||||||
*/
|
*/
|
||||||
bool con_is_leaf(Con *con);
|
bool con_is_leaf(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when this con is a leaf node with a managed X11 window (e.g.,
|
||||||
|
* excluding dock containers)
|
||||||
|
*/
|
||||||
|
bool con_has_managed_window(Con *con);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if a container should be considered split.
|
* Returns true if a container should be considered split.
|
||||||
*
|
*
|
||||||
@ -81,7 +86,7 @@ Con *con_parent_with_orientation(Con *con, orientation_t orientation);
|
|||||||
* Returns the first fullscreen node below this node.
|
* Returns the first fullscreen node below this node.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con *con_get_fullscreen_con(Con *con, int fullscreen_mode);
|
Con *con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the container is internal, such as __i3_scratch
|
* Returns true if the container is internal, such as __i3_scratch
|
||||||
@ -193,7 +198,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
|
|||||||
* container).
|
* container).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int con_orientation(Con *con);
|
orientation_t con_orientation(Con *con);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the container which will be focused next when the given container
|
* Returns the container which will be focused next when the given container
|
||||||
@ -340,5 +345,3 @@ void con_set_urgency(Con *con, bool urgent);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char *con_get_tree_representation(Con *con);
|
char *con_get_tree_representation(Con *con);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
* bindings mode).
|
* bindings mode).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_CONFIG_H
|
#pragma once
|
||||||
#define I3_CONFIG_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
@ -99,6 +98,7 @@ struct Config {
|
|||||||
int container_stack_limit;
|
int container_stack_limit;
|
||||||
int container_stack_limit_value;
|
int container_stack_limit_value;
|
||||||
int default_border_width;
|
int default_border_width;
|
||||||
|
int default_floating_border_width;
|
||||||
|
|
||||||
/** Default orientation for new containers */
|
/** Default orientation for new containers */
|
||||||
int default_orientation;
|
int default_orientation;
|
||||||
@ -109,6 +109,16 @@ struct Config {
|
|||||||
* It is not planned to add any different focus models. */
|
* It is not planned to add any different focus models. */
|
||||||
bool disable_focus_follows_mouse;
|
bool disable_focus_follows_mouse;
|
||||||
|
|
||||||
|
/** By default, when switching focus to a window on a different output
|
||||||
|
* (e.g. focusing a window on workspace 3 on output VGA-1, coming from
|
||||||
|
* workspace 2 on LVDS-1), the mouse cursor is warped to the center of
|
||||||
|
* that window.
|
||||||
|
*
|
||||||
|
* With the mouse_warping option, you can control when the mouse cursor
|
||||||
|
* should be warped. "none" disables warping entirely, whereas "output"
|
||||||
|
* is the default behavior described above. */
|
||||||
|
warping_t mouse_warping;
|
||||||
|
|
||||||
/** Remove borders if they are adjacent to the screen edge.
|
/** Remove borders if they are adjacent to the screen edge.
|
||||||
* This is useful if you are reaching scrollbar on the edge of the
|
* This is useful if you are reaching scrollbar on the edge of the
|
||||||
* screen or do not want to waste a single pixel of displayspace.
|
* screen or do not want to waste a single pixel of displayspace.
|
||||||
@ -180,6 +190,7 @@ struct Config {
|
|||||||
struct Colortriple focused_inactive;
|
struct Colortriple focused_inactive;
|
||||||
struct Colortriple unfocused;
|
struct Colortriple unfocused;
|
||||||
struct Colortriple urgent;
|
struct Colortriple urgent;
|
||||||
|
struct Colortriple placeholder;
|
||||||
} client;
|
} client;
|
||||||
struct config_bar {
|
struct config_bar {
|
||||||
struct Colortriple focused;
|
struct Colortriple focused;
|
||||||
@ -267,6 +278,10 @@ struct Barconfig {
|
|||||||
* zero. */
|
* zero. */
|
||||||
bool hide_workspace_buttons;
|
bool hide_workspace_buttons;
|
||||||
|
|
||||||
|
/** Strip workspace numbers? Configuration option is
|
||||||
|
* 'strip_workspace_numbers yes'. */
|
||||||
|
bool strip_workspace_numbers;
|
||||||
|
|
||||||
/** Hide mode button? Configuration option is 'binding_mode_indicator no'
|
/** Hide mode button? Configuration option is 'binding_mode_indicator no'
|
||||||
* but we invert the bool for the same reason as hide_workspace_buttons.*/
|
* but we invert the bool for the same reason as hide_workspace_buttons.*/
|
||||||
bool hide_binding_mode_indicator;
|
bool hide_binding_mode_indicator;
|
||||||
@ -308,12 +323,6 @@ struct Barconfig {
|
|||||||
*/
|
*/
|
||||||
void load_configuration(xcb_connection_t *conn, const char *override_configfile, bool reload);
|
void load_configuration(xcb_connection_t *conn, const char *override_configfile, bool reload);
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates keysymbols to keycodes for all bindings which use keysyms.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void translate_keysyms(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ungrabs all keys, to be called before re-grabbing the keys because of a
|
* Ungrabs all keys, to be called before re-grabbing the keys because of a
|
||||||
* mapping_notify event or a configuration file reload
|
* mapping_notify event or a configuration file reload
|
||||||
@ -321,30 +330,11 @@ void translate_keysyms(void);
|
|||||||
*/
|
*/
|
||||||
void ungrab_all_keys(xcb_connection_t *conn);
|
void ungrab_all_keys(xcb_connection_t *conn);
|
||||||
|
|
||||||
/**
|
|
||||||
* Grab the bound keys (tell X to send us keypress events for those keycodes)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switches the key bindings to the given mode, if the mode exists
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void switch_mode(const char *new_mode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the current bar configuration as an event to all barconfig_update listeners.
|
* Sends the current bar configuration as an event to all barconfig_update listeners.
|
||||||
* This update mechnism currently only includes the hidden_state and the mode in the config.
|
|
||||||
*
|
|
||||||
*/void update_barconfig();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a pointer to the Binding with the specified modifiers and keycode
|
|
||||||
* or NULL if no such binding exists.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Binding *get_binding(uint16_t modifiers, bool key_release, xcb_keycode_t keycode);
|
void update_barconfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kills the configerror i3-nagbar process, if any.
|
* Kills the configerror i3-nagbar process, if any.
|
||||||
@ -356,5 +346,3 @@ Binding *get_binding(uint16_t modifiers, bool key_release, xcb_keycode_t keycode
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void kill_configerror_nagbar(bool wait_for_it);
|
void kill_configerror_nagbar(bool wait_for_it);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,13 +7,18 @@
|
|||||||
* config_directives.h: all config storing functions (see config_parser.c)
|
* config_directives.h: all config storing functions (see config_parser.c)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_CONFIG_DIRECTIVES_H
|
#pragma once
|
||||||
#define I3_CONFIG_DIRECTIVES_H
|
|
||||||
|
|
||||||
#include "config_parser.h"
|
#include "config_parser.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility function to convert a string of modifiers to the corresponding bit
|
||||||
|
* mask.
|
||||||
|
*/
|
||||||
|
uint32_t modifiers_from_str(const char *str);
|
||||||
|
|
||||||
/** The beginning of the prototype for every cfg_ function. */
|
/** The beginning of the prototype for every cfg_ function. */
|
||||||
#define I3_CFG Match *current_match, struct ConfigResult *result
|
#define I3_CFG Match *current_match, struct ConfigResultIR *result
|
||||||
|
|
||||||
/* Defines a configuration function, that is, anything that can be called by
|
/* Defines a configuration function, that is, anything that can be called by
|
||||||
* using 'call cfg_foo()' in parser-specs/.*.spec. Useful so that we don’t need
|
* using 'call cfg_foo()' in parser-specs/.*.spec. Useful so that we don’t need
|
||||||
@ -41,6 +46,7 @@ CFGFUN(default_orientation, const char *orientation);
|
|||||||
CFGFUN(workspace_layout, const char *layout);
|
CFGFUN(workspace_layout, const char *layout);
|
||||||
CFGFUN(workspace_back_and_forth, const char *value);
|
CFGFUN(workspace_back_and_forth, const char *value);
|
||||||
CFGFUN(focus_follows_mouse, const char *value);
|
CFGFUN(focus_follows_mouse, const char *value);
|
||||||
|
CFGFUN(mouse_warping, const char *value);
|
||||||
CFGFUN(force_focus_wrapping, const char *value);
|
CFGFUN(force_focus_wrapping, const char *value);
|
||||||
CFGFUN(force_xinerama, const char *value);
|
CFGFUN(force_xinerama, const char *value);
|
||||||
CFGFUN(fake_outputs, const char *outputs);
|
CFGFUN(fake_outputs, const char *outputs);
|
||||||
@ -76,6 +82,5 @@ CFGFUN(bar_color_single, const char *colorclass, const char *color);
|
|||||||
CFGFUN(bar_status_command, const char *command);
|
CFGFUN(bar_status_command, const char *command);
|
||||||
CFGFUN(bar_binding_mode_indicator, const char *value);
|
CFGFUN(bar_binding_mode_indicator, const char *value);
|
||||||
CFGFUN(bar_workspace_buttons, const char *value);
|
CFGFUN(bar_workspace_buttons, const char *value);
|
||||||
|
CFGFUN(bar_strip_workspace_numbers, const char *value);
|
||||||
CFGFUN(bar_finish);
|
CFGFUN(bar_finish);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,19 +7,19 @@
|
|||||||
* config_parser.h: config parser-related definitions
|
* config_parser.h: config parser-related definitions
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_CONFIG_PARSER_H
|
#pragma once
|
||||||
#define I3_CONFIG_PARSER_H
|
|
||||||
|
|
||||||
#include <yajl/yajl_gen.h>
|
#include <yajl/yajl_gen.h>
|
||||||
|
|
||||||
extern pid_t config_error_nagbar_pid;
|
extern pid_t config_error_nagbar_pid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The result of a parse_config call. Currently unused, but the JSON output
|
* An intermediate reprsentation of the result of a parse_config call.
|
||||||
* will be useful in the future when we implement a config parsing IPC command.
|
* Currently unused, but the JSON output will be useful in the future when we
|
||||||
|
* implement a config parsing IPC command.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct ConfigResult {
|
struct ConfigResultIR {
|
||||||
/* The JSON generator to append a reply to. */
|
/* The JSON generator to append a reply to. */
|
||||||
yajl_gen json_gen;
|
yajl_gen json_gen;
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ struct ConfigResult {
|
|||||||
int next_state;
|
int next_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConfigResult *parse_config(const char *input, struct context *context);
|
struct ConfigResultIR *parse_config(const char *input, struct context *context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given file by first replacing the variables, then calling
|
* Parses the given file by first replacing the variables, then calling
|
||||||
@ -37,5 +37,3 @@ struct ConfigResult *parse_config(const char *input, struct context *context);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void parse_file(const char *f);
|
void parse_file(const char *f);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* include/data.h: This file defines all data structures used by i3
|
* include/data.h: This file defines all data structures used by i3
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_DATA_H
|
#pragma once
|
||||||
#define I3_DATA_H
|
|
||||||
|
|
||||||
#define SN_API_NOT_YET_FROZEN 1
|
#define SN_API_NOT_YET_FROZEN 1
|
||||||
#include <libsn/sn-launcher.h>
|
#include <libsn/sn-launcher.h>
|
||||||
@ -92,6 +91,22 @@ typedef enum {
|
|||||||
L_SPLITH = 6
|
L_SPLITH = 6
|
||||||
} layout_t;
|
} layout_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binding input types. See Binding::input_type.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
B_KEYBOARD = 0,
|
||||||
|
B_MOUSE = 1
|
||||||
|
} input_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mouse pointer warping modes.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
POINTER_WARPING_OUTPUT = 0,
|
||||||
|
POINTER_WARPING_NONE = 1
|
||||||
|
} warping_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a rectangle, for example the size of a window, the child window etc.
|
* Stores a rectangle, for example the size of a window, the child window etc.
|
||||||
* It needs to be packed so that the compiler will not add any padding bytes.
|
* It needs to be packed so that the compiler will not add any padding bytes.
|
||||||
@ -151,7 +166,7 @@ struct deco_render_params {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores which workspace (by name) goes to which output.
|
* Stores which workspace (by name or number) goes to which output.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Workspace_Assignment {
|
struct Workspace_Assignment {
|
||||||
@ -214,6 +229,10 @@ struct regex {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Binding {
|
struct Binding {
|
||||||
|
/* The type of input this binding is for. (Mouse bindings are not yet
|
||||||
|
* implemented. All bindings are currently assumed to be keyboard bindings.) */
|
||||||
|
input_type_t input_type;
|
||||||
|
|
||||||
/** If true, the binding should be executed upon a KeyRelease event, not a
|
/** If true, the binding should be executed upon a KeyRelease event, not a
|
||||||
* KeyPress (the default). */
|
* KeyPress (the default). */
|
||||||
enum {
|
enum {
|
||||||
@ -374,7 +393,7 @@ struct Match {
|
|||||||
struct regex *class;
|
struct regex *class;
|
||||||
struct regex *instance;
|
struct regex *instance;
|
||||||
struct regex *mark;
|
struct regex *mark;
|
||||||
struct regex *role;
|
struct regex *window_role;
|
||||||
enum {
|
enum {
|
||||||
U_DONTCHECK = -1,
|
U_DONTCHECK = -1,
|
||||||
U_LATEST = 0,
|
U_LATEST = 0,
|
||||||
@ -450,6 +469,9 @@ struct Assignment {
|
|||||||
TAILQ_ENTRY(Assignment) assignments;
|
TAILQ_ENTRY(Assignment) assignments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Fullscreen modes. Used by Con.fullscreen_mode. */
|
||||||
|
typedef enum { CF_NONE = 0, CF_OUTPUT = 1, CF_GLOBAL = 2 } fullscreen_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A 'Con' represents everything from the X11 root window down to a single X11 window.
|
* A 'Con' represents everything from the X11 root window down to a single X11 window.
|
||||||
*
|
*
|
||||||
@ -538,7 +560,7 @@ struct Con {
|
|||||||
|
|
||||||
TAILQ_HEAD(swallow_head, Match) swallow_head;
|
TAILQ_HEAD(swallow_head, Match) swallow_head;
|
||||||
|
|
||||||
enum { CF_NONE = 0, CF_OUTPUT = 1, CF_GLOBAL = 2 } fullscreen_mode;
|
fullscreen_mode_t fullscreen_mode;
|
||||||
/* layout is the layout of this container: one of split[v|h], stacked or
|
/* layout is the layout of this container: one of split[v|h], stacked or
|
||||||
* tabbed. Special containers in the tree (above workspaces) have special
|
* tabbed. Special containers in the tree (above workspaces) have special
|
||||||
* layouts like dockarea or output.
|
* layouts like dockarea or output.
|
||||||
@ -595,5 +617,3 @@ struct Con {
|
|||||||
/* Depth of the container window */
|
/* Depth of the container window */
|
||||||
uint16_t depth;
|
uint16_t depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
* events. This code is from xcb-util.
|
* events. This code is from xcb-util.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_DEBUG_H
|
#pragma once
|
||||||
#define I3_DEBUG_H
|
|
||||||
|
|
||||||
int handle_event(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e);
|
int handle_event(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* display_version.c: displays the running i3 version, runs as part of
|
* display_version.c: displays the running i3 version, runs as part of
|
||||||
* i3 --moreversion.
|
* i3 --moreversion.
|
||||||
*/
|
*/
|
||||||
#ifndef I3_DISPLAY_VERSION_H
|
#pragma once
|
||||||
#define I3_DISPLAY_VERSION_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to i3 to find out the currently running version. Useful since it
|
* Connects to i3 to find out the currently running version. Useful since it
|
||||||
@ -23,5 +22,3 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void display_running_version(void);
|
void display_running_version(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* ewmh.c: Get/set certain EWMH properties easily.
|
* ewmh.c: Get/set certain EWMH properties easily.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_EWMH_C
|
#pragma once
|
||||||
#define I3_EWMH_C
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates _NET_CURRENT_DESKTOP with the current desktop number.
|
* Updates _NET_CURRENT_DESKTOP with the current desktop number.
|
||||||
@ -28,6 +27,11 @@ void ewmh_update_current_desktop(void);
|
|||||||
*/
|
*/
|
||||||
void ewmh_update_active_window(xcb_window_t window);
|
void ewmh_update_active_window(xcb_window_t window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the _NET_CLIENT_LIST hint. Used for window listers.
|
||||||
|
*/
|
||||||
|
void ewmh_update_client_list(xcb_window_t *list, int num_windows);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the _NET_CLIENT_LIST_STACKING hint. Necessary to move tabs in
|
* Updates the _NET_CLIENT_LIST_STACKING hint. Necessary to move tabs in
|
||||||
* Chromium correctly.
|
* Chromium correctly.
|
||||||
@ -62,5 +66,3 @@ void ewmh_setup_hints(void);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ewmh_update_workarea(void);
|
void ewmh_update_workarea(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
* which don’t support multi-monitor in a useful way) and for our testsuite.
|
* which don’t support multi-monitor in a useful way) and for our testsuite.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_FAKE_OUTPUTS_H
|
#pragma once
|
||||||
#define I3_FAKE_OUTPUTS_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates outputs according to the given specification.
|
* Creates outputs according to the given specification.
|
||||||
@ -19,5 +18,3 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void fake_outputs_init(const char *output_spec);
|
void fake_outputs_init(const char *output_spec);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* floating.c: Floating windows.
|
* floating.c: Floating windows.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_FLOATING_H
|
#pragma once
|
||||||
#define I3_FLOATING_H
|
|
||||||
|
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
|
||||||
@ -183,5 +182,3 @@ void floating_reposition(Con *con, Rect newrect);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void floating_fix_coordinates(Con *con, Rect *old_rect, Rect *new_rect);
|
void floating_fix_coordinates(Con *con, Rect *old_rect, Rect *new_rect);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
* …).
|
* …).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_HANDLERS_H
|
#pragma once
|
||||||
#define I3_HANDLERS_H
|
|
||||||
|
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
|
|
||||||
@ -63,5 +62,3 @@ int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state,
|
|||||||
xcb_window_t window, xcb_atom_t atom,
|
xcb_window_t window, xcb_atom_t atom,
|
||||||
xcb_get_property_reply_t *property);
|
xcb_get_property_reply_t *property);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* i3.h: global variables that are used all over i3.
|
* i3.h: global variables that are used all over i3.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_I3_H
|
#pragma once
|
||||||
#define I3_I3_H
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
@ -62,5 +61,3 @@ extern bool xcursor_supported, xkb_supported;
|
|||||||
extern xcb_window_t root;
|
extern xcb_window_t root;
|
||||||
extern struct ev_loop *main_loop;
|
extern struct ev_loop *main_loop;
|
||||||
extern bool only_check_config;
|
extern bool only_check_config;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
* for the IPC interface to i3 (see docs/ipc for more information).
|
* for the IPC interface to i3 (see docs/ipc for more information).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_I3_IPC_H
|
#pragma once
|
||||||
#define I3_I3_IPC_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -101,5 +100,3 @@ typedef struct i3_ipc_header {
|
|||||||
|
|
||||||
/** Bar config update will be triggered to update the bar config */
|
/** Bar config update will be triggered to update the bar config */
|
||||||
#define I3_IPC_EVENT_BARCONFIG_UPDATE (I3_IPC_EVENT_MASK | 4)
|
#define I3_IPC_EVENT_BARCONFIG_UPDATE (I3_IPC_EVENT_MASK | 4)
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* ipc.c: UNIX domain socket IPC (initialization, client handling, protocol).
|
* ipc.c: UNIX domain socket IPC (initialization, client handling, protocol).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_IPC_H
|
#pragma once
|
||||||
#define I3_IPC_H
|
|
||||||
|
|
||||||
#include <ev.h>
|
#include <ev.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -17,6 +16,7 @@
|
|||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include "i3/ipc.h"
|
#include "i3/ipc.h"
|
||||||
|
|
||||||
@ -89,4 +89,13 @@ void dump_node(yajl_gen gen, Con *con, bool inplace_restart);
|
|||||||
*/
|
*/
|
||||||
void ipc_send_workspace_focus_event(Con *current, Con *old);
|
void ipc_send_workspace_focus_event(Con *current, Con *old);
|
||||||
|
|
||||||
#endif
|
/**
|
||||||
|
* For the window events we send, along the usual "change" field,
|
||||||
|
* also the window container, in "container".
|
||||||
|
*/
|
||||||
|
void ipc_send_window_event(const char *property, Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the barconfig update events, we send the serialized barconfig.
|
||||||
|
*/
|
||||||
|
void ipc_send_barconfig_update_event(Barconfig *barconfig);
|
||||||
|
@ -7,10 +7,7 @@
|
|||||||
* key_press.c: key press handler
|
* key_press.c: key press handler
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_KEY_PRESS_H
|
#pragma once
|
||||||
#define I3_KEY_PRESS_H
|
|
||||||
|
|
||||||
extern pid_t command_error_nagbar_pid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There was a key press. We compare this key code with our bindings table and pass
|
* There was a key press. We compare this key code with our bindings table and pass
|
||||||
@ -30,5 +27,3 @@ void handle_key_press(xcb_key_press_event_t *event);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void kill_commanderror_nagbar(bool wait_for_it);
|
void kill_commanderror_nagbar(bool wait_for_it);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
* as i3-msg, i3-config-wizard, …
|
* as i3-msg, i3-config-wizard, …
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_LIBI3_H
|
#pragma once
|
||||||
#define I3_LIBI3_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -383,4 +382,10 @@ char *get_process_filename(const char *prefix);
|
|||||||
*/
|
*/
|
||||||
char *get_exe_path(const char *argv0);
|
char *get_exe_path(const char *argv0);
|
||||||
|
|
||||||
#endif
|
/**
|
||||||
|
* Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI
|
||||||
|
* screen) to a corresponding amount of physical pixels on a standard or retina
|
||||||
|
* screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int logical_px(const int logical);
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
* restart.
|
* restart.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_LOAD_LAYOUT_H
|
#pragma once
|
||||||
#define I3_LOAD_LAYOUT_H
|
|
||||||
|
|
||||||
void tree_append_json(const char *filename);
|
void tree_append_json(Con *con, const char *filename, char **errormsg);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* log.c: Logging functions.
|
* log.c: Logging functions.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_LOG_H
|
#pragma once
|
||||||
#define I3_LOG_H
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -102,5 +101,3 @@ void verboselog(char *fmt, ...)
|
|||||||
* failures. This function is invoked automatically when exiting.
|
* failures. This function is invoked automatically when exiting.
|
||||||
*/
|
*/
|
||||||
void purge_zerobyte_logfile(void);
|
void purge_zerobyte_logfile(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
18
include/main.h
Normal file
18
include/main.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* vim:ts=4:sw=4:expandtab
|
||||||
|
*
|
||||||
|
* i3 - an improved dynamic tiling window manager
|
||||||
|
* © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
|
||||||
|
*
|
||||||
|
* main.c: Initialization, main loop
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable the main X11 event handling function.
|
||||||
|
* This is used by drag_pointer() which has its own, modal event handler, which
|
||||||
|
* takes precedence over the normal event handler.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void main_set_x11_cb(bool enable);
|
@ -7,8 +7,7 @@
|
|||||||
* manage.c: Initially managing new windows (or existing ones on restart).
|
* manage.c: Initially managing new windows (or existing ones on restart).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_MANAGE_H
|
#pragma once
|
||||||
#define I3_MANAGE_H
|
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
|
||||||
@ -52,4 +51,3 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
|||||||
uint32_t border_width);
|
uint32_t border_width);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
* match_matches_window() to find the windows affected by this command.
|
* match_matches_window() to find the windows affected by this command.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_MATCH_H
|
#pragma once
|
||||||
#define I3_MATCH_H
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes the Match data structure. This function is necessary because the
|
* Initializes the Match data structure. This function is necessary because the
|
||||||
@ -46,5 +45,3 @@ bool match_matches_window(Match *match, i3Window *window);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void match_free(Match *match);
|
void match_free(Match *match);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* move.c: Moving containers into some direction.
|
* move.c: Moving containers into some direction.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_MOVE_H
|
#pragma once
|
||||||
#define I3_MOVE_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the current container in the given direction (TOK_LEFT, TOK_RIGHT,
|
* Moves the current container in the given direction (TOK_LEFT, TOK_RIGHT,
|
||||||
@ -16,5 +15,3 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void tree_move(int direction);
|
void tree_move(int direction);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,13 +7,10 @@
|
|||||||
* output.c: Output (monitor) related functions.
|
* output.c: Output (monitor) related functions.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_OUTPUT_H
|
#pragma once
|
||||||
#define I3_OUTPUT_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the output container below the given output container.
|
* Returns the output container below the given output container.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con *output_get_content(Con *output);
|
Con *output_get_content(Con *output);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -32,8 +32,7 @@
|
|||||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_QUEUE_H_
|
#pragma once
|
||||||
#define _SYS_QUEUE_H_
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file defines five types of data structures: singly-linked lists,
|
* This file defines five types of data structures: singly-linked lists,
|
||||||
@ -536,5 +535,3 @@ struct { \
|
|||||||
_Q_INVALIDATE((elm)->field.cqe_prev); \
|
_Q_INVALIDATE((elm)->field.cqe_prev); \
|
||||||
_Q_INVALIDATE((elm)->field.cqe_next); \
|
_Q_INVALIDATE((elm)->field.cqe_next); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* !_SYS_QUEUE_H_ */
|
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
* (take your time to read it completely, it answers all questions).
|
* (take your time to read it completely, it answers all questions).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_RANDR_H
|
#pragma once
|
||||||
#define I3_RANDR_H
|
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
@ -85,7 +84,7 @@ Output *get_output_by_name(const char *name);
|
|||||||
* if there is no output which contains these coordinates.
|
* if there is no output which contains these coordinates.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Output *get_output_containing(int x, int y);
|
Output *get_output_containing(unsigned int x, unsigned int y);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In contained_by_output, we check if any active output contains part of the container.
|
* In contained_by_output, we check if any active output contains part of the container.
|
||||||
@ -121,5 +120,3 @@ Output *get_output_next(direction_t direction, Output *current, output_close_far
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Output *get_output_next_wrap(direction_t direction, Output *current);
|
Output *get_output_next_wrap(direction_t direction, Output *current);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
* regex.c: Interface to libPCRE (perl compatible regular expressions).
|
* regex.c: Interface to libPCRE (perl compatible regular expressions).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_REGEX_H
|
#pragma once
|
||||||
#define I3_REGEX_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new 'regex' struct containing the given pattern and a PCRE
|
* Creates a new 'regex' struct containing the given pattern and a PCRE
|
||||||
@ -35,5 +34,3 @@ void regex_free(struct regex *regex);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool regex_matches(struct regex *regex, const char *input);
|
bool regex_matches(struct regex *regex, const char *input);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
* various rects. Needs to be pushed to X11 (see x.c) to be visible.
|
* various rects. Needs to be pushed to X11 (see x.c) to be visible.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef I3_RENDER_H
|
#pragma once
|
||||||
#define I3_RENDER_H
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Renders" the given container (and its children), meaning that all rects are
|
* "Renders" the given container (and its children), meaning that all rects are
|
||||||
@ -25,5 +24,3 @@ void render_con(Con *con, bool render_fullscreen);
|
|||||||
* Returns the height for the decorations
|
* Returns the height for the decorations
|
||||||
*/
|
*/
|
||||||
int render_deco_height(void);
|
int render_deco_height(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user