├── .clang-format ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── pull_request_template.md └── workflows │ ├── Build Test.yml │ └── codeql-analysis.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG ├── I3LOCK_VERSION ├── LICENSE ├── Makefile.am ├── README.md ├── SECURITY.md ├── _config.yml ├── blur.c ├── blur.h ├── blur_simd.c ├── build.sh ├── configure.ac ├── cursors.h ├── dpi.c ├── dpi.h ├── examples ├── lock.sh ├── lock_bar.sh ├── screenshot.png └── screenshot_2017.png ├── fonts.h ├── i3lock-bash ├── i3lock-zsh ├── i3lock.1 ├── i3lock.c ├── i3lock.h ├── install-i3lock-color.sh ├── jpg.c ├── jpg.h ├── m4 ├── ax_append_flag.m4 ├── ax_cflags_warn_all.m4 ├── ax_check_bash_completion.m4 ├── ax_check_compile_flag.m4 ├── ax_check_enable_debug.m4 ├── ax_check_gnu_make.m4 ├── ax_check_link_flag.m4 ├── ax_check_zsh_completion.m4 ├── ax_code_coverage.m4 ├── ax_configure_args.m4 ├── ax_enable_builddir.m4 ├── ax_extend_srcdir.m4 ├── ax_require_defined.m4 └── ax_sanitizers.m4 ├── pam └── i3lock ├── randr.c ├── randr.h ├── rgba.h ├── tinyexpr.c ├── tinyexpr.h ├── travis └── Dockerfile ├── unlock_indicator.c ├── unlock_indicator.h ├── xcb.c └── xcb.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: google 2 | AllowShortIfStatementsOnASingleLine: false 3 | AllowShortLoopsOnASingleLine: false 4 | AllowShortFunctionsOnASingleLine: None 5 | AllowShortBlocksOnASingleLine: false 6 | AlwaysBreakBeforeMultilineStrings: false 7 | IndentWidth: 4 8 | PointerBindsToType: false 9 | ColumnLimit: 0 10 | SpaceBeforeParens: ControlStatements 11 | SortIncludes: false 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | text eol=lf 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [Raymo111] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## This issue is a.... 6 | 7 |
 8 | [ ] Bug
 9 | [ ] Other kind of issue (Please describe in detail)
10 | 
11 | 12 | ## Current Behavior 13 | 14 | 15 | ## Expected Behavior 16 | 17 | 18 | ## Reproduction Instructions 19 | 23 | 24 | ## Environment 25 | Output of `i3lock --version`: 26 |
27 | i3lock version:
28 | 
29 | 30 | Where'd you get i3lock-color from? 31 | 32 |
33 | [ ] AUR package (which one?)
34 | [ ] Built from source yourself
35 | [ ] Other (Please describe in detail)
36 | 
37 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 4 | Closes #[issue number] 5 | 6 | ## Description 7 | - 8 | 9 | ### Screenshots/screencaps 10 | 13 | 14 | ## Release notes 15 | 19 | Notes: 20 | -------------------------------------------------------------------------------- /.github/workflows/Build Test.yml: -------------------------------------------------------------------------------- 1 | name: Build Test 2 | 3 | on: [push, pull_request] 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - name: Install deps 10 | run: | 11 | sudo apt update 12 | sudo apt install pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev libgif-dev 13 | - name: Build 14 | run: ./build.sh 15 | - name: Check and distcheck 16 | run: | 17 | cd build 18 | make check 19 | make distcheck 20 | - name: Upload binary artifact 21 | uses: actions/upload-artifact@v4 22 | with: 23 | name: i3lock 24 | path: /home/runner/work/i3lock-color/i3lock-color/build/i3lock 25 | - run: ./install-i3lock-color.sh 26 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | name: "CodeQL" 7 | 8 | on: 9 | push: 10 | branches: [master] 11 | pull_request: 12 | # The branches below must be a subset of the branches above 13 | branches: [master] 14 | schedule: 15 | - cron: '0 16 * * 4' 16 | 17 | jobs: 18 | analyze: 19 | name: Analyze 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | fail-fast: false 24 | # matrix: 25 | # Override automatic language detection by changing the below list 26 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 27 | # language: ['cpp'] 28 | # Learn more... 29 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v2 34 | with: 35 | # We must fetch at least the immediate parents so that if this is 36 | # a pull request then we can checkout the head. 37 | fetch-depth: 2 38 | 39 | # If this run was triggered by a pull request event, then checkout 40 | # the head of the pull request instead of the merge commit. 41 | # CodeQL apparently deprecated this feature and now warns on running this command 42 | # - run: git checkout HEAD^2 43 | # if: ${{ github.event_name == 'pull_request' }} 44 | 45 | # Initializes the CodeQL tools for scanning. 46 | - name: Initialize CodeQL 47 | uses: github/codeql-action/init@v1 48 | with: 49 | languages: ${{ matrix.language }} 50 | # If you wish to specify custom queries, you can do so here or in a config file. 51 | # By default, queries listed here will override any specified in a config file. 52 | # Prefix the list here with "+" to use these queries and those in the config file. 53 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 54 | 55 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 56 | # If this step fails, then you should remove it and run the build manually (see below) 57 | #- name: Autobuild 58 | # uses: github/codeql-action/autobuild@v1 59 | 60 | # ℹ️ Command-line programs to run using the OS shell. 61 | # 📚 https://git.io/JvXDl 62 | 63 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 64 | # and modify them (or add more) to build your code if your project 65 | # uses a compiled language 66 | 67 | - run: | 68 | sudo apt-get update 69 | sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev libgif-dev 70 | ./build.sh 71 | 72 | - name: Perform CodeQL Analysis 73 | uses: github/codeql-action/analyze@v1 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | i3lock 2 | *.o 3 | tags 4 | *.swp 5 | *.gz 6 | *~ 7 | x86_64-pc-linux-gnu 8 | 9 | ################################################################################ 10 | # https://raw.githubusercontent.com/github/gitignore/master/Autotools.gitignore 11 | ################################################################################ 12 | 13 | # http://www.gnu.org/software/automake 14 | 15 | Makefile.in 16 | /ar-lib 17 | /test-driver 18 | 19 | # http://www.gnu.org/software/autoconf 20 | 21 | /autom4te.cache 22 | /autoscan.log 23 | /autoscan-*.log 24 | /aclocal.m4 25 | /compile 26 | /config.h.in 27 | /config.guess 28 | /config.sub 29 | /configure 30 | /configure.scan 31 | /depcomp 32 | /install-sh 33 | /missing 34 | /stamp-h1 35 | aminclude_static.am 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Use Ubuntu 14.04 (trusty), as per http://blog.travis-ci.com/2015-10-14-opening-up-ubuntu-trusty-beta/ 2 | sudo: false 3 | dist: trusty 4 | services: 5 | - docker 6 | language: c 7 | compiler: 8 | - gcc 9 | - clang 10 | script: 11 | - docker build --pull --no-cache --rm -t=i3lock -f travis/Dockerfile . 12 | - docker run -e CC=$CC -v $PWD:/usr/src:rw i3lock /bin/sh -c 'clang-format-9 -i *.[ch] && git diff --exit-code || (echo "Code was not formatted using clang-format!"; false)' 13 | - docker run -e CC=$CC -v $PWD:/usr/src:rw i3lock /bin/sh -c 'autoreconf -fi && mkdir -p build && cd build && (../configure || (cat config.log; false)) && make -j V=1 CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror"' 14 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2020-10-27 i3lock 2.13 2 | 3 | • Throw error when trying to start on Wayland 4 | • Use explicit_bzero() where available, not just on OpenBSD 5 | • avoid pixmap allocations in the redraw path 6 | • make --debug output go to stderr 7 | • unlock_indicator.c: fix build failure against gcc-10 8 | • fix: call pam_end in cleanup in main, not in event loop 9 | • set _NET_WM_BYPASS_COMPOSITOR hint to avoid flickering 10 | 11 | 2019-07-21 i3lock 2.12 12 | 13 | • remove stray \n from error messages 14 | • capitalize unlock indicator contents 15 | • set WM_CLASS property 16 | • reference modifier as “Super”, not “Win” 17 | • add --raw option to read image as raw bytes 18 | 19 | 2018-10-18 i3lock 2.11.1 20 | 21 | • Fix dist tarball by including I3LOCK_VERSION 22 | 23 | 2018-10-10 i3lock 2.11 24 | 25 | • Switch to autotools 26 | • Display an error when backspace is pressed without any input 27 | • Print an error when a non-PNG file is opened 28 | (i3lock only supports PNG files) (Thanks eplanet) 29 | • Don’t unnecessarily check the xcb_connect return value, 30 | it is known never to be NULL (Thanks SegFault42) 31 | • Fix memory leak when grabbing fails (Thanks karulont) 32 | • Respect Xft.dpi for determining the unlock indicator’s scale factor 33 | • Discard pending password verification attempts 34 | when a new password is entered (Thanks layus) 35 | 36 | 2017-11-25 i3lock 2.10 37 | 38 | • Only use -lpam when not on OpenBSD (Thanks Kaashif) 39 | • locale: treat empty string same as unset (Thanks Ran) 40 | • Fix overwrite of getopt optind (Thanks jakob) 41 | • Immediately hide the unlock indicator after ESC / C-u (Thanks Orestis) 42 | • Measure wall-clock time instead of CPU time for “locking” indicator. 43 | • SetInputFocus to the i3lock window to force-close context menus 44 | • Use RandR for learning about attached monitors 45 | 46 | 2017-06-21 i3lock 2.9.1 47 | 48 | • Fix version number mechanism (for --version) 49 | • Revert the fix for composited notifications, as it causes more issues than 50 | it solves: 51 | https://github.com/i3/i3lock/issues/130 52 | https://github.com/i3/i3lock/issues/128 53 | 54 | 2017-05-26 i3lock 2.9 55 | 56 | • i3lock.1: use signal names without SIG prefix 57 | • Removed obsolete inactivity timeout 58 | • Added version files for release tarball. 59 | • Set font face 60 | • Automatically unlock (without having to press ) one attempt which was 61 | entered while authenticating 62 | • Stop leaking the image_path dup 63 | • Displaying locking message when grabbing the pointer/keyboard 64 | • Display error message when locking failed 65 | • Add Enter on C-m 66 | • Change input slices to be exactly pi/3 in size instead of slightly more 67 | • Fix covering of composited notifications using the XComposite extension 68 | • Remove last traces of DPMS 69 | • Use bsd_auth(3) instead of PAM on OpenBSD 70 | • Restore intended behaviour and don't use mlock(2) on OpenBSD. 71 | 72 | 2016-06-04 i3lock 2.8 73 | 74 | • Remove DPMS support in favor of a wrapper script and xset(1). 75 | • Indicate that the --inactivity-timeout option takes an argument. (Thanks 76 | Kenneth Lyons) 77 | • fix pam_securetty: set PAM_TTY to getenv("DISPLAY") 78 | • Eat XKB_KEY_Delete and XKB_KEY_KP_Delete (Thanks bebehei) 79 | • Show unlock indicator if password was entered during PAM verification 80 | • Allow CTRL+J as enter and CTRL+H as backspace (Thanks Karl Tarbe) 81 | • Flush xcb connection after opening fullscreen window (Thanks martin) 82 | • Add support for `xss-lock --transfer-sleep-lock' 83 | 84 | 2015-05-20 i3lock 2.7 85 | 86 | • Die when the X11 connection breaks during runtime (Thanks Eduan) 87 | • Implement logging the number of failed attempts (Thanks koebi) 88 | • Ignore password validation is pam is in wrong state (Thanks Neodyblue) 89 | • Get current user with getpwuid() instead of using $ENV{USER} (Thanks Martin) 90 | • Add support for Compose and dead-keys with libxkbcommon. 91 | Requires libxkbcommon ≥ 0.5.0 (Thanks Daniel) 92 | • Format the source using clang-format. 93 | • Refresh pam credentials on successful authentication (for Kerberos and the 94 | like) (Thanks James) 95 | • List pressed modifiers on failed authentication (Thanks Deiz, Alexandre) 96 | • Only redraw the screen if the unlock indicator is actually used 97 | (Thanks Ingo) 98 | • Make pkg-config configurable for cross-compilation (Thanks Nikolay) 99 | 100 | 2014-07-18 i3lock 2.6 101 | 102 | • NEW DEPENDENCY: use libxkbcommon-x11 instead of libX11 103 | This helps us get rid of all code that directly uses libX11 104 | • Use cairo_status_to_string for descriptive errors. 105 | • Add `-e` option to not validate empty password. 106 | • Bugfix: update the initial keyboard modifier state (Thanks lee, Ran) 107 | • Re-raise i3lock when obscured in a separate process 108 | • Turn on the screen on successful authentication 109 | • Delay to turn off the screen after wrong passwd 110 | • Discard half-entered passwd after some inactivity 111 | • Ignore empty passwd after repeated Enter keypress 112 | • Scale the unlock indicator (for retina displays) 113 | 114 | 2013-06-09 i3lock 2.5 115 | 116 | • NEW DEPENDENCY: Use libxkbcommon for input handling 117 | This makes input handling much better for many edge cases. 118 | • Bugfix: fix argument parsing on ARM (s/char/int/) 119 | • Bugfix: free(reply) to avoid memory leak 120 | • Bugfix: Use ev_loop_fork after fork, fixes forking on kqueue based OSes 121 | • Bugfix: Fix centering the indicator in the no-xinerama case 122 | • Only use mlock() on Linux, FreeBSD (for example) requires root 123 | • promote the "could not load image" message from debug to normal 124 | • s/pam_message/pam_response/ (Thanks Tucos) 125 | • remove support for NOLIBCAIRO, cairo-xcb is widespread by now 126 | • Allow XKB_KEY_XF86ScreenSaver as synonym for enter 127 | This keysym is generated on convertible tablets by pressing a hardware 128 | lock/unlock button. 129 | • Allow passwordless PAM conversations (e.g. fingerprint) 130 | • Add ctrl+u password reset 131 | • Set window name to i3lock 132 | 133 | 2012-06-02 i3lock 2.4.1 134 | 135 | • Bugfix: Correctly center unlock indicator after reconfiguring screens 136 | (Thanks xeen) 137 | • Bugfix: Revert shift lock handling (broke uppercase letters) 138 | • Bugfix: Skip shift when getting the modifier mask (Thanks SardemFF7) 139 | 140 | 2012-04-01 i3lock 2.4 141 | 142 | • Bugfix: Fix background color when using cairo (Thanks Pascal) 143 | • Only output text when in debug mode (fixes problems with xautolock) 144 | • fallback when the image cannot be loaded 145 | • Use (void) instead of () for functions without args (Thanks fernandotcl) 146 | 147 | 2012-03-15 i3lock 2.3.1 148 | 149 | • Fix compilation on some systems 150 | 151 | 2012-03-15 i3lock 2.3 152 | 153 | • Implement a visual unlock indicator 154 | • Support ISO_Level5_Shift and Caps Lock 155 | • Lock the password buffer in memory, clear it in RAM after verifying 156 | • Fork after the window is visible, not before 157 | • Bugfix: Copy the color depth from parent (root) window instead of 158 | hardcoding a depth of 24 159 | 160 | 2011-11-06 i3lock 2.2 161 | 162 | • Don’t re-grab pointer/keyboard on MappingNotify. In some rare situations, 163 | this lead to some keypresses "slipping through" to the last focused window. 164 | • Correctly handle Mode_switch/ISO_Level3_Shift 165 | • Render to a pixmap which is used as background for the window instead of 166 | copying contents on every expose event 167 | • Handle screen resolution changes while screen is locked 168 | • Manpage: document arguments for every option 169 | 170 | 2011-05-13 i3lock 2.1 171 | 172 | • Accept return/backspace when the buffer of 512 bytes is full 173 | • Handle numpad keys correctly 174 | • Handle MappingNotify events 175 | • Correctly check for errors when connecting to X11 176 | • Add i3lock.pam to not rely on debian’s /etc/pam.d/other anymore 177 | • don’t display debug output 178 | • add NOLIBCAIRO flag to permit compilation without cairo 179 | 180 | 2010-09-05 i3lock 2.0 181 | 182 | • Complete rewrite of i3lock. Now using xcb instead of Xlib. 183 | • When a window obscures i3lock, it pushes itself back to the top again. 184 | • Display version when starting with -v 185 | 186 | 2009-08-02 i3lock 1.1 187 | 188 | • Implement background pictures (-i) and colors (-c) 189 | 190 | 2009-05-10 i3lock 1.0 191 | 192 | • Implement PAM support 193 | • Implement options for forking, beeping, DPMS 194 | 195 | 2009-05-01 i3lock 0.9 196 | 197 | • First release, forked from slock 0.9 198 | -------------------------------------------------------------------------------- /I3LOCK_VERSION: -------------------------------------------------------------------------------- 1 | 2.13.c.5 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2010-2011, Michael Stapelberg 2 | Copyright © 2015, Cassandra Fox 3 | Copyright © 2021, Raymond Li 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Michael Stapelberg, nor the name of Raymond Li, 17 | nor the names of contributors may be used to endorse or promote 18 | products derived from this software without specific prior written 19 | permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY Michael Stapelberg/Cassandra Fox/Raymond Li 22 | ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 | PURPOSE ARE DISCLAIMED. 25 | IN NO EVENT SHALL Michael Stapelberg/Cassandra Fox/Raymond Li BE LIABLE FOR 26 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | @CODE_COVERAGE_RULES@ 2 | 3 | echo-version: 4 | @echo "@I3LOCK_VERSION@" 5 | 6 | bin_PROGRAMS = i3lock 7 | 8 | dist_man1_MANS = i3lock.1 9 | 10 | DISTCLEANFILES = i3lock-color-*.tar.bz2 11 | 12 | pamddir = $(sysconfdir)/pam.d 13 | pamd_files = pam/i3lock 14 | pamd_DATA = $(pamd_files) 15 | 16 | if ENABLE_BASH_COMPLETION 17 | bashcompletiondir = $(BASH_COMPLETION_DIR) 18 | dist_bashcompletion_DATA = i3lock-bash 19 | endif 20 | 21 | if ENABLE_ZSH_COMPLETION 22 | zshcompletiondir = $(ZSH_COMPLETION_DIR) 23 | dist_zshcompletion_DATA = i3lock-zsh 24 | endif 25 | 26 | install-data-hook: 27 | if ENABLE_BASH_COMPLETION 28 | test -f "${BASH_COMPLETION_DIR}/i3lock-bash" && mv -f "${BASH_COMPLETION_DIR}/i3lock-bash" "${BASH_COMPLETION_DIR}/i3lock" || true 29 | endif 30 | if ENABLE_ZSH_COMPLETION 31 | test -f "${ZSH_COMPLETION_DIR}/i3lock-zsh" && mv -f "${ZSH_COMPLETION_DIR}/i3lock-zsh" "${ZSH_COMPLETION_DIR}/_i3lock" || true 32 | endif 33 | 34 | uninstall-hook: 35 | if ENABLE_BASH_COMPLETION 36 | rm -f ${BASH_COMPLETION_DIR}/i3lock 37 | endif 38 | if ENABLE_ZSH_COMPLETION 39 | rm -f ${ZSH_COMPLETION_DIR}/_i3lock 40 | endif 41 | 42 | 43 | AM_CPPFLAGS = \ 44 | @AX_EXTEND_SRCDIR_CPPFLAGS@ 45 | 46 | i3lock_CFLAGS = \ 47 | $(AM_CFLAGS) \ 48 | $(XCB_CFLAGS) \ 49 | $(XCB_IMAGE_CFLAGS) \ 50 | $(XCB_UTIL_CFLAGS) \ 51 | $(XCB_UTIL_XRM_CFLAGS) \ 52 | $(XKBCOMMON_CFLAGS) \ 53 | $(CAIRO_CFLAGS) \ 54 | $(FONTCONFIG_CFLAGS) \ 55 | $(JPEG_CFLAGS) \ 56 | $(CODE_COVERAGE_CFLAGS) 57 | 58 | i3lock_CPPFLAGS = \ 59 | $(AM_CPPFLAGS) \ 60 | $(CODE_COVERAGE_CPPFLAGS) 61 | 62 | i3lock_LDADD = \ 63 | $(XCB_LIBS) \ 64 | $(XCB_IMAGE_LIBS) \ 65 | $(XCB_UTIL_LIBS) \ 66 | $(XCB_UTIL_XRM_LIBS) \ 67 | $(XKBCOMMON_LIBS) \ 68 | $(CAIRO_LIBS) \ 69 | $(JPEG_LIBS) \ 70 | $(FONTCONFIG_LIBS) \ 71 | $(CODE_COVERAGE_LDFLAGS) 72 | 73 | i3lock_SOURCES = \ 74 | blur.c \ 75 | blur.h \ 76 | blur_simd.c \ 77 | cursors.h \ 78 | dpi.c \ 79 | dpi.h \ 80 | fonts.h \ 81 | jpg.c \ 82 | jpg.h \ 83 | i3lock.c \ 84 | i3lock.h \ 85 | randr.c \ 86 | randr.h \ 87 | rgba.h \ 88 | tinyexpr.c \ 89 | tinyexpr.h \ 90 | unlock_indicator.c \ 91 | unlock_indicator.h \ 92 | xcb.c \ 93 | xcb.h 94 | 95 | EXTRA_DIST = \ 96 | $(pamd_files) \ 97 | CHANGELOG \ 98 | LICENSE \ 99 | README.md \ 100 | I3LOCK_VERSION 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i3lock-color 2 | 3 | ![Language count](https://img.shields.io/github/languages/count/Raymo111/i3lock-color) 4 | [![Top language](https://img.shields.io/github/languages/top/Raymo111/i3lock-color)](https://github.com/Raymo111/i3lock-color/search?l=c) 5 | ![Repo size](https://img.shields.io/github/repo-size/Raymo111/i3lock-color) 6 | [![Open issues](https://img.shields.io/github/issues-raw/Raymo111/i3lock-color)](https://github.com/Raymo111/i3lock-color/issues?q=is%3Aopen+is%3Aissue) 7 | [![Closed issues](https://img.shields.io/github/issues-closed-raw/Raymo111/i3lock-color?color=brightgreen)](https://github.com/Raymo111/i3lock-color/issues?q=is%3Aissue+is%3Aclosed) 8 | [![Open PRs](https://img.shields.io/github/issues-pr-raw/Raymo111/i3lock-color?label=open%20PRs)](https://github.com/Raymo111/i3lock-color/pulls?q=is%3Aopen+is%3Apr) 9 | [![Closed PRs](https://img.shields.io/github/issues-pr-closed-raw/Raymo111/i3lock-color?color=brightgreen&label=closed%20PRs)](https://github.com/Raymo111/i3lock-color/pulls?q=is%3Apr+is%3Aclosed) 10 | [![Contributors](https://img.shields.io/github/contributors/Raymo111/i3lock-color)](https://github.com/Raymo111/i3lock-color/graphs/contributors) 11 | [![Latest release](https://img.shields.io/github/release-date/Raymo111/i3lock-color?label=latest%20release)](https://github.com/Raymo111/i3lock-color/releases/latest) 12 | [![Commits](https://img.shields.io/github/commits-since/Raymo111/i3lock-color/latest?include_prereleases&sort=semver)](https://github.com/Raymo111/i3lock-color/commits/master) 13 | ![Latest commit](https://img.shields.io/github/last-commit/Raymo111/i3lock-color) 14 | [![AUR release ver](https://img.shields.io/aur/version/i3lock-color?label=AUR%20release%20ver&logo=ArchLinux)](https://aur.archlinux.org/packages/i3lock-color/) 15 | [![AUR git ver](https://img.shields.io/aur/version/i3lock-color-git?label=AUR%20git%20ver&logo=ArchLinux)](https://aur.archlinux.org/packages/i3lock-color-git/) 16 | ![AUR votes](https://img.shields.io/aur/votes/i3lock-color-git?logo=ArchLinux) 17 | [![GitHub forks](https://img.shields.io/github/forks/Raymo111/i3lock-color?logo=GitHub)](https://github.com/Raymo111/i3lock-color/network/members) 18 | [![GitHub stars](https://img.shields.io/github/stars/Raymo111/i3lock-color?logo=GitHub)](https://github.com/Raymo111/i3lock-color/stargazers) 19 | [![GitHub watchers](https://img.shields.io/github/watchers/Raymo111/i3lock-color?logo=GitHub)](https://github.com/Raymo111/i3lock-color/watchers) 20 | [![Discord server](https://img.shields.io/discord/878461145197977630?label=Discord&logo=Discord)](https://discord.gg/FzVPghyDt2) 21 | ![Maintained](https://img.shields.io/maintenance/yes/9999) 22 | 23 | 24 | ### The world's most popular non-default computer lockscreen. 25 | **A modern version of i3lock with color functionality and other features.** 26 | 27 | ![i3lock-color in action](examples/screenshot.png "Screenshot sample") 28 | 29 | **NEW: Official Discord server at https://discord.gg/FzVPghyDt2** 30 | 31 | i3lock is a simple screen locker like slock. After starting it, you will see a white screen (you can configure the color/an image). You can return to your screen by entering your password. 32 | 33 | Many little improvements have been made to i3lock over time: 34 | 35 | - i3lock forks, so you can combine it with an alias to suspend to RAM (run "i3lock && echo mem > /sys/power/state" to get a locked screen after waking up your computer from suspend to RAM) 36 | - You can specify either a background color or an image (JPG or PNG), which will be displayed while your screen is locked. Note that i3lock is not an image manipulation software. If you need to resize the image to fill the screen, you can use something like ImageMagick combined with `xdpyinfo`: 37 | ```bash 38 | convert image.jpg -resize $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/') RGB:- | i3lock --raw $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/'):rgb --image /dev/stdin 39 | ``` 40 | - You can specify whether i3lock should bell upon a wrong password. 41 | - i3lock uses PAM and therefore is compatible with LDAP etc. On OpenBSD, i3lock uses the bsd\_auth(3) framework. 42 | 43 | ## Additional features in i3lock-color 44 | You can also specify additional options, as detailed in the manpage. This includes, but is not limited to: 45 | 46 | - Color options for: 47 | - Verification ring 48 | - Interior ring color 49 | - Ring interior line color 50 | - Key highlight color 51 | - Backspace highlight color 52 | - Text colors for most/all strings 53 | - Outline colors 54 | - Changing all of the above depending on PAM's authentication status 55 | - Blurring the current screen and using that as the lock background 56 | - Showing a clock in the indicator 57 | - Refreshing on a timer, instead of on each keypress 58 | - Positioning the various UI elements 59 | - Changing the ring radius and thickness, as well as text size 60 | - Options for passwordless auth, removing modkey indicator 61 | - Passing through media keys 62 | - A new bar indicator, which replaces the ring indicator with its own set of options 63 | - An experimental thread for driving the redraw ticks, so that things like the bar/clock still update when PAM is blocking 64 | - Any other feature you want (add it yourself through a PR or make a feature request issue!) 65 | 66 | ## Dependencies 67 | The following dependencies will need to be installed for a successful build, depending on your OS/distro. 68 | 69 | ### Arch Linux 70 | - autoconf 71 | - cairo 72 | - fontconfig 73 | - gcc 74 | - libev 75 | - libjpeg-turbo 76 | - libxinerama 77 | - libxkbcommon-x11 78 | - libxrandr 79 | - pam 80 | - pkgconf 81 | - xcb-util-image 82 | - xcb-util-xrm 83 | 84 | ### Debian 85 | Run this command to install all dependencies: 86 | ``` 87 | sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util0-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev libgif-dev 88 | ``` 89 | If you still see missing packages during build after installing all of these dependencies, try following the steps [here](https://github.com/Raymo111/i3lock-color/issues/211#issuecomment-809891727). 90 | 91 | ### Fedora 92 | Run this command to install all dependencies: 93 | 94 | ```sh 95 | sudo dnf install -y autoconf automake cairo-devel fontconfig gcc libev-devel libjpeg-turbo-devel libXinerama libxkbcommon-devel libxkbcommon-x11-devel libXrandr pam-devel pkgconf xcb-util-image-devel xcb-util-xrm-devel 96 | ``` 97 | 98 | ### Ubuntu 18/20.04 LTS 99 | Run this command to install all dependencies: 100 | ``` 101 | sudo apt install autoconf gcc make pkg-config libpam0g-dev libcairo2-dev libfontconfig1-dev libxcb-composite0-dev libev-dev libx11-xcb-dev libxcb-xkb-dev libxcb-xinerama0-dev libxcb-randr0-dev libxcb-image0-dev libxcb-util-dev libxcb-xrm-dev libxkbcommon-dev libxkbcommon-x11-dev libjpeg-dev libgif-dev 102 | ``` 103 | 104 | ## Building i3lock-color 105 | Before you build - check and see if there's a packaged version available for your distro (there usually is, either in a community repo/PPA). 106 | 107 | **If you want to build a non-debug version, you should tag your build before configuring.** 108 | 109 | For example: `git tag -f "git-$(git rev-parse --short HEAD)"` will add a tag with the short commit ID, which will be used for the version info. 110 | 111 | i3lock-color uses GNU autotools for building. 112 | 113 | To build/install i3lock-color, first install the dependencies listed above, then clone the repo: 114 | ``` 115 | git clone https://github.com/Raymo111/i3lock-color.git 116 | cd i3lock-color 117 | ``` 118 | To build without installing, run: 119 | ``` 120 | ./build.sh 121 | ``` 122 | To build AND install, run: 123 | ``` 124 | ./install-i3lock-color.sh 125 | ``` 126 | You may choose to modify the script based on your needs/OS/distro. 127 | 128 | ## Alpine Linux Packages 129 | Alpine packages i3lock-color for a variety of architectures. A full list can be found on [pkgs.alpinelinux.org](https://pkgs.alpinelinux.org/packages?name=i3lock-color&branch=edge). 130 | 131 | ## Arch Linux Packages 132 | ~~[Stable version in Community](https://www.archlinux.org/packages/community/x86_64/i3lock-color/)~~ 133 | 134 | Unfortunately the previous maintainer left, and the package got dumped back into the AUR where I'm now maintaining it. You can get it on AUR: 135 | - [Release Version on AUR](https://aur.archlinux.org/packages/i3lock-color/) 136 | - [Git Version on AUR](https://aur.archlinux.org/packages/i3lock-color-git/) 137 | 138 | If you're an Arch TU and you're reading this please consider sponsoring it into Community again! 139 | 140 | ## Gentoo Linux Package 141 | i3lock-color is available on **GURU**, under [`x11-misc/i3lock-color`](https://github.com/gentoo/guru/tree/master/x11-misc/i3lock-color). 142 | 143 | ## Kali Linux Package 144 | A Debian/Kali package is available: https://gitlab.com/kalilinux/packages/i3lock-color. 145 | 146 | ## NixOS Package 147 | A NixOS package is available. To install, run 148 | ``` 149 | nix-env -iA nixos.i3lock-color 150 | ``` 151 | 152 | ## Void Linux Package 153 | A Void Linux package is available at https://github.com/void-linux/void-packages/tree/master/srcpkgs/i3lock-color. 154 | 155 | ## FreeBSD port 156 | A FreeBSD port is available on freshports: [x11/i3lock-color/](https://www.freshports.org/x11/i3lock-color/). 157 | 158 | ## Running i3lock-color 159 | Simply invoke the 'i3lock' command. To get out of it, enter your password and press enter. 160 | 161 | A [sample script](examples/lock.sh) is included in this repository. 162 | 163 | On OpenBSD the `i3lock` binary needs to be setgid `auth` to call the authentication helpers, e.g. `/usr/libexec/auth/login_passwd`. 164 | 165 | ## Contributors 166 | This project was started by [eBrnd](https://github.com/eBrnd/i3lock-color), maintained for a few years by [PandorasFox](https://github.com/PandorasFox) and now maintained and being developed by [Raymo111](https://github.com/Raymo111). The full list of contributors can be found [here](https://github.com/Raymo111/i3lock-color/graphs/contributors). 167 | 168 | ## Upstream 169 | Please submit pull requests for i3lock things to [https://github.com/i3/i3lock](https://github.com/i3/i3lock) and pull requests for additional features on top of regular i3lock at [https://github.com/Raymo111/i3lock-color](https://github.com/Raymo111/i3lock-color). 170 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ---------- | ------------------ | 10 | | 2.12.c.5 | :white_check_mark: | 11 | | < 2.12.c.5 | :x: | 12 | 13 | ## Reporting a Vulnerability 14 | 15 | If there's a severe security vulnerability in the latest version of i3lock-color, don't post a public issue. Either email me directly at [i3lock-color@raymond.li](mailto:i3lock@raymond.li?subject=i3lock-color%20security%20vulnerability), or encrypt the issue text with my PGP public key: 16 | ``` 17 | -----BEGIN PGP PUBLIC KEY BLOCK----- 18 | 19 | mQINBF3PSOoBEADQP/vqo3XMOntXWo/IOy0jDCicWycWbwU1UfsZYt4MNAf1/M6t 20 | yBEKt+U94diDoD4JDDaWPdbHEyQ/6AqRqzUO+dcO19pmFc5p0nj4sPQ+iMJ95I63 21 | FW3ZSq//1vf33sNWA773YBJOD0s02dDtuCriUd+06zHXd92+9Vm+wvsP0yaPUC3g 22 | KVgN9IcdKYS6HsBuncfBFVzE/wf9BL3YHwvGgqS+XcQ2mPizy6Ddc/zXfn43zXLT 23 | Q/nYb7Gt34EdP2J31ypuLFrVE3oSA9hK4SSvV8Z4INRELYhSjLVYt9S/NuhpIo8T 24 | wOirZFKVfeBvtoog0LX1isFmGdje3ML20IH9bOqp7UcmsXbYqmza3xrOUdHQpqe2 25 | Idz5O3XOrlcqcVbeeNNcqeUBr/u5XScYGIyDr9+b4utis/PxnqE6hoiwSrwsLZ6Q 26 | QYHcsR+rwLujfxQf3k1emMLkrS+sd61WFGB4ZAvHpdpNtfym/c5g+CTA2SEjhM7+ 27 | g0qvT9guEhLk/mEgtXvCCkcESAIZMnk1xUkXldqofl5Vr8r2B6oEw2hmwwcTJrHJ 28 | 4x9IfcgrJDlyxcUQJ2UJzmtn/D6L7OdG465cdVZ+8QQRmf4IQV+6SXEqb1s9hFDj 29 | sahJIdgftDDYmgaEzNYz09z/obAgUho5stsW7Ah/D8C1DsfD3DMNs5IS7QARAQAB 30 | tCdSYXltb25kIExpICgoUmF5bW8xMTEpKSA8aGlAcmF5bW9uZC5saT6JAk4EEwEI 31 | ADgWIQRkwvsY4QR1Ip//JdHwWN+YLbQvnQUCXc9I6gIbLwULCQgHAgYVCgkICwIE 32 | FgIDAQIeAQIXgAAKCRDwWN+YLbQvndhCEAC1HRAXV2i6pQ6c6frCwAQSbMLiRiqd 33 | OYyipejmjkF04wm3Zb4MMfzSWLoVXbHcX8NX8+i/VjMBgoPyLd/XutdDD8qq1TVb 34 | paIbN+fIgniMMwW0X/8LRm6jqhlO8Z4igzExHF+GLG2NRMIhTaNdRp51x7Lc5iOu 35 | PgR8p1Ql5+vhIb9WdNUq2L74JW7BSqb1Xit86NtJI723gbg+Xwbv60uuzPHhd0bN 36 | jHHHJ1f9YSlPPZH5iMlBcl3iNoMfIbCp1G179IaK/sN5C4hPhVvy8GmoTlTIQ6If 37 | gs2x1xFwoIMlz8SFX4KJwnIIXZz6JBzpGRNIXV5fhwrzLpvY19iKh+JIHOtxcovy 38 | YjKOFe4+dOgBade29C+RyJ+i21cijTzsn8nE7COt49N3gXl+sXHUv4kSUVkGEmNY 39 | VtMLFJbjTxDxb/V25iWov23Gz9DhWcl/oCmCnLhi+7YZtmNpCbFrZSkGVq0VNfBE 40 | f6Mh96ugGbehg0tbbiLf0hdHMO0qi5DXP3Lfyy7Mw20YlOWiLqyTCs+HgVBXP783 41 | n1SfQrswbObOj7z+Bg8iQvYwKhU2A6sgToROYeZ3mV4kuTEcqpJhfGBXD6xraUm1 42 | kSg3Xc8A/3G1z34uHXGPb5sQx3eu+LbaSfDLTLObfy+ef+Z2fqt8Q8SVzTInnUQq 43 | k8K700ofB9zOw7kCDQRdz0jqARAAqfyjVbId7hc4tL9H0rpGr4A2NFdjvs7ktf9L 44 | 63/GtzyTJ5oFa2jOMtmU4PDbgwOAHXFZJEQ9etzPsIxZOrH0uuOO/5WPxu+n+mEz 45 | M+mnV6YA/wGu/IUKcbpOHMjinH6uaNlJ/PErJkHkGPCb97c/HFYROBoSBPtRW+8q 46 | Qdlaq4cccwE93pindt1aoE7nHFlsxuQG0s8fQ8qX7SgO2okve3OJnstADpcpMX5x 47 | VausXoGc3h6BQexaAnsIJ574ov5vNxFOHG/22RSsyf+Xd8MPqQv5Znk2lQD9EwzS 48 | m15jy008jpkV7kByZHDNuiTjxfrhkCy6gS3RlCgnKZlyTqkjuU1vQ12S/xXZJzwD 49 | IBfbxZQP9dfxYo4Pusd7bMlptkJTUmjr5JeLAcfNWyDTvwZ/ea+2gdrXedUYlYNS 50 | m984ZIwLjDxC/PjwXyURCTNamYibGgnMHwD8Fr2czszBQxwM/ThGkgN6fdwyvGzL 51 | AfeYAjZrZfTtA/OV7fpBR+hUAJcFJCSiHzIOyDlAMYVIaRnAfCGvCnE4ksUWP6so 52 | vBBLQsF+XmCw5GhzDC26UV3Cyu/bJ0AXKVYtoKungixjrhwcZ6icAXiAvF6ZtfnA 53 | xxqkgmm4lDbLJN9wbInhAVK5fiN+phbFDPgEorpyoxdsJtwmN0AAYHO+leBMFMfQ 54 | RsEkPLcAEQEAAYkEbAQYAQgAIBYhBGTC+xjhBHUin/8l0fBY35gttC+dBQJdz0jq 55 | AhsuAkAJEPBY35gttC+dwXQgBBkBCAAdFiEEs9q7pbmssSalH+X5oBTqibYruxsF 56 | Al3PSOoACgkQoBTqibYruxuEmg/8D06MiJ7G9hZpENphSl3YcfGYgmHIfCPdc+D4 57 | mMO50ychMGPMDlsDHtVSpUbTrvPtzNlulYfREAm9LsuFQRvYHOVNQ9rbI7gEo3ga 58 | K4LrcCsYkG27TiMeiljgqN2qWHYJAHDdAPbmAEawCMo9Y3uiMvcs8Gt9lFjIiIa9 59 | jfs+rBCw2yJwP2HlYjK7CyIgNvjiMjDbWNIeQY6ONlR+ojDR52bcPljyT4rQ+XTq 60 | t2/ArCwcFciX25EoQ4ncl5F44GqwWDkdpj8/HCfNQkRPN7nR9LGftyFCWUxZLZUQ 61 | Ux0Is6wubu0KxE3P1Xvz2HDhKZVBiR5P4TiC79CgSpENFyAvmCt4tnsnTu7UGYzj 62 | JWl/Lvi+dirC+THmOj00sbTzyKnMn7896hgSiKlgkl968JfTf4SsDmySftg+894f 63 | PZizZt8v3jjEy8oRvQ4S619Visz+3fxrM2mKbBXW33G+cWIyVkKqzUQgdI+itaO8 64 | iLDP5HjMNSJd2VvvwswnJq0KnyMCRY2QzJ90E2FPTcl9Ltv1zEl16GqCWyQtSrma 65 | tEKZAFTdFVMwdLbggFlWnLx7qOfTs7nBIXGmfi25DmPcufNskmq8RiTSxXyFRBJS 66 | OMYP+xkxNR4JSOA+Clt20zclknX6HA9877vWy9Gnqm+gWu5PIfiDvxitQukc+e5B 67 | N3WQfnEUxQ/8CN1ncUHk4JlP25vjFS9/eK+yTqR8AEEr20DD0cSNvRtpjwiaIZaf 68 | Up9SQTtz2RuqiIl7+Hak8VCAKvYWHXy5BjId73x5SfnT9wuic+/jAaUi+5Ypo/Lh 69 | R/LfsWPsE1EGtmcmRwltNjxL32gpiD4LS7TuY5XVvmVBUh5185Y/t5WkP3kv4FB6 70 | uA2g8kADHQbLtcpVc7c510Ru3MQ8HSmyGKO/3K++itNTST70RV36SOCNfG3WDSBD 71 | yO8t2RKzH6Q+f4a2pWJafuknvvMsTf11YRZBBZUVF1XVTABtEu/fucbTMjVHh2gd 72 | 69iICS0KTL6sf6K3fclPQiqKIbCFgf/CGWUaAyzWBM8bWsxD2kywrdf1qY+UU1AF 73 | vV+RmvVjcr1o3V6fZNDSlXET8w7jHjddTBstiCEK4aQCds6DDJU2+Ucqw5sqzwr3 74 | 9LKbph/uibQxJC/AYNMiCH5OHDknhnyAwNmn+KMXHyJkqGoqB5zXVfsxrHroEBHR 75 | Sl77//DFlSl06lLee97HiSoKckpFrsmjpSbkQ+wFcb0x4lRbN5vRx8oUvagpGJ2D 76 | mLhEcizl8EB9RwneaN6AfJg0BIikKpxl/K/gf7wr8fdsEgK0WIgCb60Ed8VEd9+l 77 | rnKFFKw58bCu0PS5Uk6Lnb/jbbWOaB4ngOeOEGPoeT1vdDI6hkkEma4= 78 | =HNQH 79 | -----END PGP PUBLIC KEY BLOCK----- 80 | ``` 81 | You can also get my key directly from the [GNUPG keyserver](http://keys.gnupg.net/pks/lookup?op=vindex&fingerprint=on&search=0xF058DF982DB42F9D). 82 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /blur.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2008 Kristian Høgsberg 3 | * Copyright © 2009 Chris Wilson 4 | * 5 | * Permission to use, copy, modify, distribute, and sell this software and its 6 | * documentation for any purpose is hereby granted without fee, provided that 7 | * the above copyright notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting documentation, and 9 | * that the name of the copyright holders not be used in advertising or 10 | * publicity pertaining to distribution of the software without specific, 11 | * written prior permission. The copyright holders make no representations 12 | * about the suitability of this software for any purpose. It is provided "as 13 | * is" without express or implied warranty. 14 | * 15 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 21 | * OF THIS SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include "blur.h" 26 | /* Performs a simple 2D Gaussian blur of standard devation @sigma surface @surface. */ 27 | void 28 | blur_image_surface (cairo_surface_t *surface, int sigma) 29 | { 30 | cairo_surface_t *tmp; 31 | int width, height; 32 | uint32_t *src, *dst; 33 | 34 | if (cairo_surface_status (surface)) 35 | return; 36 | 37 | width = cairo_image_surface_get_width (surface); 38 | height = cairo_image_surface_get_height (surface); 39 | 40 | switch (cairo_image_surface_get_format (surface)) { 41 | case CAIRO_FORMAT_A1: 42 | default: 43 | /* Don't even think about it! */ 44 | return; 45 | 46 | case CAIRO_FORMAT_A8: 47 | /* Handle a8 surfaces by effectively unrolling the loops by a 48 | * factor of 4 - this is safe since we know that stride has to be a 49 | * multiple of uint32_t. */ 50 | width /= 4; 51 | break; 52 | 53 | case CAIRO_FORMAT_RGB24: 54 | case CAIRO_FORMAT_ARGB32: 55 | break; 56 | } 57 | 58 | tmp = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); 59 | if (cairo_surface_status (tmp)) 60 | return; 61 | 62 | src = (uint32_t*)cairo_image_surface_get_data (surface); 63 | dst = (uint32_t*)cairo_image_surface_get_data (tmp); 64 | 65 | // according to a paper by Peter Kovesi [1], box filter of width w, equals to Gaussian blur of following sigma: 66 | // σ_av = sqrt((w*w-1)/12) 67 | // for our 7x7 filter we have σ_av = 2.0. 68 | // applying the same Gaussian filter n times results in σ_n = sqrt(n*σ_av*σ_av) [2] 69 | // after some trivial math, we arrive at n = ((σ_d)/(σ_av))^2 70 | // since it's a box blur filter, n >= 3 71 | // 72 | // [1]: http://www.peterkovesi.com/papers/FastGaussianSmoothing.pdf 73 | // [2]: https://en.wikipedia.org/wiki/Gaussian_blur#Mathematics 74 | 75 | int n = lrintf((sigma*sigma)/(SIGMA_AV*SIGMA_AV)); 76 | if (n < 3) n = 3; 77 | 78 | for (int i = 0; i < n; i++) 79 | { 80 | // horizontal pass includes image transposition: 81 | // instead of writing pixel src[x] to dst[x], 82 | // we write it to transposed location. 83 | // (to be exact: dst[height * current_column + current_row]) 84 | #ifdef __SSE2__ 85 | blur_impl_horizontal_pass_sse2(src, dst, width, height); 86 | blur_impl_horizontal_pass_sse2(dst, src, height, width); 87 | #else 88 | blur_impl_horizontal_pass_generic(src, dst, width, height); 89 | blur_impl_horizontal_pass_generic(dst, src, height, width); 90 | #endif 91 | } 92 | 93 | cairo_surface_destroy (tmp); 94 | cairo_surface_flush (surface); 95 | cairo_surface_mark_dirty (surface); 96 | } 97 | 98 | void blur_impl_horizontal_pass_generic(uint32_t *src, uint32_t *dst, int width, int height) { 99 | uint32_t *o_src = src; 100 | for (int row = 0; row < height; row++) { 101 | for (int column = 0; column < width; column++, src++) { 102 | uint32_t rgbaIn[KERNEL_SIZE + 1]; 103 | 104 | // handle borders 105 | int leftBorder = column < HALF_KERNEL; 106 | int rightBorder = column > width - HALF_KERNEL; 107 | int i = 0; 108 | if (leftBorder) { 109 | // for kernel size 7x7 and column == 0, we have: 110 | // x x x P0 P1 P2 P3 111 | // first loop mirrors P{0..3} to fill x's, 112 | // second one loads P{0..3} 113 | for (; i < HALF_KERNEL - column; i++) 114 | rgbaIn[i] = *(src + (HALF_KERNEL - i)); 115 | for (; i < KERNEL_SIZE; i++) 116 | rgbaIn[i] = *(src - (HALF_KERNEL - i)); 117 | } else if (rightBorder) { 118 | for (; i < width - column; i++) 119 | rgbaIn[i] = *(src + i); 120 | for (int k = 0; i < KERNEL_SIZE; i++, k++) 121 | rgbaIn[i] = *(src - k); 122 | } else { 123 | for (; i < KERNEL_SIZE; i++) { 124 | if ((uintptr_t) ((src + 4*i - HALF_KERNEL) + 1) 125 | > (uintptr_t) (o_src + (height * width))) 126 | break; 127 | rgbaIn[i] = *(src + i - HALF_KERNEL); 128 | } 129 | } 130 | 131 | uint32_t acc[4] = {0}; 132 | 133 | for (i = 0; i < KERNEL_SIZE; i++) { 134 | acc[0] += (rgbaIn[i] & 0xFF000000) >> 24; 135 | acc[1] += (rgbaIn[i] & 0x00FF0000) >> 16; 136 | acc[2] += (rgbaIn[i] & 0x0000FF00) >> 8; 137 | acc[3] += (rgbaIn[i] & 0x000000FF) >> 0; 138 | } 139 | 140 | for(i = 0; i < 4; i++) 141 | acc[i] *= 1.0/KERNEL_SIZE; 142 | 143 | *(dst + height * column + row) = (acc[0] << 24) | 144 | (acc[1] << 16) | 145 | (acc[2] << 8 ) | 146 | (acc[3] << 0); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /blur.h: -------------------------------------------------------------------------------- 1 | #ifndef _BLUR_H 2 | #define _BLUR_H 3 | 4 | #include 5 | #include 6 | 7 | #define KERNEL_SIZE 7 8 | #define SIGMA_AV 2 9 | #define HALF_KERNEL KERNEL_SIZE / 2 10 | 11 | void blur_image_surface(cairo_surface_t *surface, int sigma); 12 | #ifdef __SSE2__ 13 | void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int height); 14 | #endif 15 | void blur_impl_horizontal_pass_generic(uint32_t *src, uint32_t *dst, int width, int height); 16 | #endif 17 | -------------------------------------------------------------------------------- /blur_simd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * © 2016 Sebastian Frysztak 5 | * 6 | * See LICENSE for licensing information 7 | * 8 | */ 9 | 10 | 11 | // number of xmm registers needed to store input pixels for given kernel size 12 | #ifdef __SSE2__ 13 | #include "blur.h" 14 | #define REGISTERS_CNT (KERNEL_SIZE + 4/2) / 4 15 | #include 16 | void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int height) { 17 | uint32_t* o_src = src; 18 | for (int row = 0; row < height; row++) { 19 | for (int column = 0; column < width; column++, src++) { 20 | __m128i rgbaIn[REGISTERS_CNT]; 21 | 22 | // handle borders 23 | int leftBorder = column < HALF_KERNEL; 24 | int rightBorder = column > width - HALF_KERNEL; 25 | uint32_t _rgbaIn[KERNEL_SIZE + 1] __attribute__((aligned(16))); 26 | int i = 0; 27 | if (leftBorder) { 28 | // for kernel size 7x7 and column == 0, we have: 29 | // x x x P0 P1 P2 P3 30 | // first loop mirrors P{0..3} to fill x's, 31 | // second one loads P{0..3} 32 | for (; i < HALF_KERNEL - column; i++) 33 | _rgbaIn[i] = *(src + (HALF_KERNEL - i)); 34 | for (; i < KERNEL_SIZE; i++) 35 | _rgbaIn[i] = *(src - (HALF_KERNEL - i)); 36 | 37 | for (int k = 0; k < REGISTERS_CNT; k++) 38 | rgbaIn[k] = _mm_load_si128((__m128i*)(_rgbaIn + 4*k)); 39 | } else if (rightBorder) { 40 | for (; i < width - column; i++) 41 | _rgbaIn[i] = *(src + i); 42 | for (int k = 0; i < KERNEL_SIZE; i++, k++) 43 | _rgbaIn[i] = *(src - k); 44 | 45 | for (int k = 0; k < REGISTERS_CNT; k++) 46 | rgbaIn[k] = _mm_load_si128((__m128i*)(_rgbaIn + 4*k)); 47 | } else { 48 | for (int k = 0; k < REGISTERS_CNT; k++) { 49 | if ((uintptr_t) (((__m128i*) src + 4*k - HALF_KERNEL) + 1) 50 | > (uintptr_t) (o_src + (height * width))) 51 | break; 52 | rgbaIn[k] = _mm_loadu_si128((__m128i*)(src + 4*k - HALF_KERNEL)); 53 | } 54 | } 55 | 56 | __m128i zero = _mm_setzero_si128(); 57 | __m128i acc = _mm_setzero_si128(); 58 | 59 | acc = _mm_add_epi16(acc, _mm_unpacklo_epi8(rgbaIn[0], zero)); 60 | acc = _mm_add_epi16(acc, _mm_unpackhi_epi8(rgbaIn[0], zero)); 61 | acc = _mm_add_epi16(acc, _mm_unpacklo_epi8(rgbaIn[1], zero)); 62 | 63 | // kernel size equals to 7, but we can only load multiples of 4 pixels 64 | // we have to set 8th pixel to zero 65 | acc = _mm_add_epi16(acc, _mm_andnot_si128(_mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0, 0), 66 | _mm_unpackhi_epi8(rgbaIn[1], zero))); 67 | acc = _mm_add_epi32(_mm_unpacklo_epi16(acc, zero), 68 | _mm_unpackhi_epi16(acc, zero)); 69 | 70 | // multiplication is significantly faster than division 71 | acc = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(acc), 72 | _mm_set1_ps(1.0/KERNEL_SIZE))); 73 | 74 | *(dst + height * column + row) = 75 | _mm_cvtsi128_si32(_mm_packus_epi16(_mm_packs_epi32(acc, zero), zero)); 76 | } 77 | } 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | configureOpts="" 4 | 5 | while getopts ":hd" opt; do 6 | case ${opt} in 7 | h ) echo "Use -d to turn on sanitizers (for debugging only)" 8 | exit;; 9 | d ) configureOpts="--enable-debug" 10 | ;; 11 | \? ) echo "Usage: $0 [-h] [-d]" 12 | exit;; 13 | esac 14 | done 15 | 16 | configureOpts="${configureOpts} --prefix=/usr --sysconfdir=/etc" 17 | 18 | autoreconf -fiv 19 | 20 | BUILD_DIR=build/ 21 | rm -rf $BUILD_DIR 22 | mkdir -vp $BUILD_DIR 23 | cd $BUILD_DIR || { echo "cd $BUILD_DIR"; exit 127; } 24 | 25 | ../configure ${configureOpts} 26 | 27 | make 28 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Run autoreconf -fi to generate a configure script from this file. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([i3lock-color],[m4_esyscmd_s([cat I3LOCK_VERSION])],[https://github.com/Raymo11/i3lock-color/issues]) 6 | # For AX_EXTEND_SRCDIR 7 | AX_ENABLE_BUILDDIR 8 | AM_INIT_AUTOMAKE([foreign subdir-objects -Wall no-dist-gzip dist-bzip2]) 9 | # Default to silent rules, use V=1 to get verbose compilation output. 10 | AM_SILENT_RULES([yes]) 11 | # Make it possible to disable maintainer mode to disable re-generation of build 12 | # system files. 13 | AM_MAINTAINER_MODE([enable]) 14 | AC_CONFIG_SRCDIR([i3lock.c]) 15 | AC_CONFIG_HEADERS([config.h]) 16 | AC_CONFIG_MACRO_DIR([m4]) 17 | 18 | dnl Verify macros defined in m4/ such as AX_SANITIZERS are not present in the 19 | dnl output, i.e. are replaced as expected. This line results in a better error 20 | dnl message when using aclocal < 1.13 (which does not understand 21 | dnl AC_CONFIG_MACRO_DIR) without passing the -I m4 parameter. 22 | m4_pattern_forbid([AX_SANITIZERS]) 23 | 24 | # Verify we are using GNU make because we use '%'-style pattern rules in 25 | # Makefile.am, which are a GNU make extension. Pull requests to replace 26 | # '%'-style pattern rules with a more portable alternative are welcome. 27 | AX_CHECK_GNU_MAKE 28 | AS_VAR_IF([_cv_gnu_make_command], [""], [AC_MSG_ERROR([the i3lock Makefile.am requires GNU make])]) 29 | 30 | AX_EXTEND_SRCDIR 31 | 32 | AS_IF([test -d ${srcdir}/.git], 33 | [ 34 | VERSION="$(git -C ${srcdir} describe --tags --abbrev=0)" 35 | I3LOCK_VERSION="$(git -C ${srcdir} describe --tags --always) ($(git -C ${srcdir} rev-list --pretty=format:%cd --date=short -n1 HEAD | tail -n1))" 36 | # Mirrors what libi3/is_debug_build.c does: 37 | is_release=$(test $(echo "${I3LOCK_VERSION}" | cut -d ' ' -f 1 | wc -m) -lt 13 && echo yes || echo no) 38 | ], 39 | [ 40 | VERSION="$(cut -d '-' -f 1 ${srcdir}/I3LOCK_VERSION | cut -d ' ' -f 1)" 41 | I3LOCK_VERSION="$(sed -e 's/@<:@\"?\\@:>@/\\&/g' ${srcdir}/I3LOCK_VERSION)" 42 | is_release="$(grep -q non-git ${srcdir}/I3LOCK_VERSION && echo no || echo yes)" 43 | ]) 44 | AC_SUBST([I3LOCK_VERSION], [$I3LOCK_VERSION]) 45 | AC_DEFINE_UNQUOTED([I3LOCK_VERSION], ["${I3LOCK_VERSION}"], [i3lock version]) 46 | 47 | AX_CODE_COVERAGE 48 | 49 | dnl is_release must be lowercase because AX_CHECK_ENABLE_DEBUG calls m4_tolower 50 | dnl on its fourth argument. 51 | AX_CHECK_ENABLE_DEBUG([no], , , [$is_release]) 52 | 53 | AC_PROG_CC 54 | 55 | # For strnlen() and vasprintf(). 56 | AC_USE_SYSTEM_EXTENSIONS 57 | 58 | # Checks for typedefs, structures, and compiler characteristics. 59 | AC_CHECK_HEADER_STDBOOL 60 | dnl The error message should include the specific type which could not be 61 | dnl found, but I do not see a way to achieve that. 62 | AC_CHECK_TYPES([mode_t, off_t, pid_t, size_t, ssize_t], , [AC_MSG_FAILURE([cannot find required type])]) 63 | 64 | # Checks for library functions. 65 | AC_FUNC_FORK 66 | AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK 67 | AC_FUNC_STRNLEN 68 | AC_CHECK_FUNCS([atexit dup2 ftruncate getcwd gettimeofday localtime_r memchr memset mkdir rmdir setlocale socket strcasecmp strchr strdup strerror strncasecmp strndup strrchr strspn strstr strtol strtoul], , [AC_MSG_FAILURE([cannot find the $ac_func function, which i3lock requires])]) 69 | AC_CHECK_FUNCS([explicit_bzero]) 70 | 71 | # Check for libraries 72 | AC_SEARCH_LIBS([floor], [m], , [AC_MSG_FAILURE([cannot find the required floor() function despite trying to link with -lm])]) 73 | 74 | # libev does not ship with a pkg-config file :(. 75 | AC_SEARCH_LIBS([ev_run], [ev], , [AC_MSG_FAILURE([cannot find the required ev_run() function despite trying to link with -lev])]) 76 | 77 | AC_SEARCH_LIBS([shm_open], [rt]) 78 | 79 | AC_SEARCH_LIBS([DGifOpenFileName], [gif]) 80 | # Use system-local-login instead of login on Arch and Gentoo 81 | if [[ -f /etc/arch-release ]] || [[ -f /etc/gentoo-release ]]; then 82 | echo "Using PAM for Arch/Gentoo" 83 | sed -i "s/^#auth include system-local-login/auth include system-local-login/g" ../pam/i3lock 84 | sed -i "s/^auth include login/#auth include login/g" ../pam/i3lock 85 | fi 86 | 87 | # Only disable PAM on OpenBSD where i3lock uses BSD Auth instead 88 | case "$host" in 89 | *-openbsd*) 90 | # Nothing yet. 91 | ;; 92 | *) 93 | AC_SEARCH_LIBS([pam_authenticate], [pam]) 94 | ;; 95 | esac 96 | 97 | AC_SEARCH_LIBS([iconv_open], [iconv], , [AC_MSG_FAILURE([cannot find the required iconv_open() function despite trying to link with -liconv])]) 98 | 99 | dnl Each prefix corresponds to a source tarball which users might have 100 | dnl downloaded in a newer version and would like to overwrite. 101 | PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-composite]) 102 | PKG_CHECK_MODULES([XCB_IMAGE], [xcb-image]) 103 | PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom]) 104 | PKG_CHECK_MODULES([XCB_UTIL_XRM], [xcb-xrm]) 105 | PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11]) 106 | PKG_CHECK_MODULES([CAIRO], [cairo]) 107 | PKG_CHECK_MODULES([JPEG], [libjpeg]) 108 | PKG_CHECK_MODULES([FONTCONFIG], [fontconfig]) 109 | 110 | 111 | # Checks for programs. 112 | AC_PROG_AWK 113 | AC_PROG_CPP 114 | AC_PROG_INSTALL 115 | AC_PROG_MAKE_SET 116 | AC_PROG_RANLIB 117 | AC_PROG_LN_S 118 | 119 | AM_PROG_AR 120 | 121 | AX_FLAGS_WARN_ALL 122 | AX_APPEND_FLAG([-O2], [AM_CFLAGS]) 123 | AX_APPEND_FLAG([-funroll-loops], [AM_CFLAGS]) 124 | AX_APPEND_FLAG([-pthread], [AM_CFLAGS]) 125 | AX_CHECK_COMPILE_FLAG([-Wunused-value], [AX_APPEND_FLAG([-Wunused-value], [AM_CFLAGS])]) 126 | AC_SUBST(AM_CFLAGS) 127 | 128 | AX_CHECK_BASH_COMPLETION 129 | AX_CHECK_ZSH_COMPLETION 130 | 131 | # Checks for header files. 132 | AC_CHECK_HEADERS([fcntl.h float.h inttypes.h limits.h locale.h netinet/in.h paths.h stddef.h stdint.h stdlib.h string.h sys/param.h sys/socket.h sys/time.h unistd.h gif_lib.h], , [AC_MSG_FAILURE([cannot find the $ac_header header, which i3lock requires])]) 133 | 134 | AC_CONFIG_FILES([Makefile]) 135 | 136 | # Enable address sanitizer for debug builds. The performance hit is a 137 | # 50% increase of wallclock time for the testsuite on my machine. 138 | if test "x$ax_enable_debug" = "xyes"; then 139 | default_sanitizers=address 140 | else 141 | default_sanitizers= 142 | fi 143 | AX_SANITIZERS(, [$default_sanitizers]) 144 | 145 | AC_OUTPUT 146 | 147 | in_git_worktree=`git rev-parse --is-inside-work-tree 2>/dev/null` 148 | if [[ "$in_git_worktree" = "true" ]]; then 149 | git_dir=`git rev-parse --git-dir 2>/dev/null` 150 | srcdir=`dirname "$git_dir"` 151 | exclude_dir=`pwd | sed "s,^$srcdir,,g"` 152 | if ! grep -q "^$exclude_dir" "$git_dir/info/exclude"; then 153 | echo "$exclude_dir" >> "$git_dir/info/exclude" 154 | fi 155 | fi 156 | 157 | echo \ 158 | "-------------------------------------------------------------------------------- 159 | build configured: 160 | 161 | AS_HELP_STRING([i3lock version:], [`echo ${I3LOCK_VERSION} | sed 's,\\\\,,g'`]) 162 | AS_HELP_STRING([is release version:], [${is_release}]) 163 | 164 | AS_HELP_STRING([enable debug flags:], [${ax_enable_debug}]) 165 | AS_HELP_STRING([code coverage:], [${CODE_COVERAGE_ENABLED}]) 166 | AS_HELP_STRING([enabled sanitizers:], [${ax_enabled_sanitizers}])" 167 | 168 | #To compile, run: 169 | # 170 | # cd `pwd` && make 171 | echo \ 172 | "--------------------------------------------------------------------------------" 173 | -------------------------------------------------------------------------------- /cursors.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURSORS_H 2 | #define _CURSORS_H 3 | 4 | #define CURS_NONE 0 5 | #define CURS_WIN 1 6 | #define CURS_DEFAULT 2 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /dpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * i3 - an improved dynamic tiling window manager 5 | * © 2009 Michael Stapelberg and contributors (see also: LICENSE) 6 | * 7 | */ 8 | #include "dpi.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "xcb.h" 15 | #include "i3lock.h" 16 | 17 | extern bool debug_mode; 18 | 19 | static long dpi; 20 | 21 | extern xcb_screen_t *screen; 22 | 23 | static long init_dpi_fallback(void) { 24 | return (double)screen->height_in_pixels * 25.4 / (double)screen->height_in_millimeters; 25 | } 26 | 27 | /* 28 | * Initialize the DPI setting. 29 | * This will use the 'Xft.dpi' X resource if available and fall back to 30 | * guessing the correct value otherwise. 31 | */ 32 | void init_dpi(void) { 33 | xcb_xrm_database_t *database = NULL; 34 | char *resource = NULL; 35 | 36 | if (conn == NULL) { 37 | goto init_dpi_end; 38 | } 39 | 40 | database = xcb_xrm_database_from_default(conn); 41 | if (database == NULL) { 42 | DEBUG("Failed to open the resource database.\n"); 43 | goto init_dpi_end; 44 | } 45 | 46 | xcb_xrm_resource_get_string(database, "Xft.dpi", NULL, &resource); 47 | if (resource == NULL) { 48 | DEBUG("Resource Xft.dpi not specified, skipping.\n"); 49 | goto init_dpi_end; 50 | } 51 | 52 | char *endptr; 53 | double in_dpi = strtod(resource, &endptr); 54 | if (in_dpi == HUGE_VAL || dpi < 0 || *endptr != '\0' || endptr == resource) { 55 | DEBUG("Xft.dpi = %s is an invalid number and couldn't be parsed.\n", resource); 56 | dpi = 0; 57 | goto init_dpi_end; 58 | } 59 | dpi = (long)round(in_dpi); 60 | 61 | DEBUG("Found Xft.dpi = %ld.\n", dpi); 62 | 63 | init_dpi_end: 64 | if (resource != NULL) { 65 | free(resource); 66 | } 67 | 68 | if (database != NULL) { 69 | xcb_xrm_database_free(database); 70 | } 71 | 72 | if (dpi == 0) { 73 | DEBUG("Using fallback for calculating DPI.\n"); 74 | dpi = init_dpi_fallback(); 75 | DEBUG("Using dpi = %ld\n", dpi); 76 | } 77 | } 78 | 79 | /* 80 | * This function returns the value of the DPI setting. 81 | * 82 | */ 83 | long get_dpi_value(void) { 84 | return dpi; 85 | } 86 | 87 | /* 88 | * Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI 89 | * screen) to a corresponding amount of physical pixels on a standard or retina 90 | * screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen. 91 | * 92 | */ 93 | int logical_px(const int logical) { 94 | if (screen == NULL) { 95 | /* Dpi info may not be available when parsing a config without an X 96 | * server, such as for config file validation. */ 97 | return logical; 98 | } 99 | 100 | /* There are many misconfigurations out there, i.e. systems with screens 101 | * whose dpi is in fact higher than 96 dpi, but not significantly higher, 102 | * so software was never adapted. We could tell people to reconfigure their 103 | * systems to 96 dpi in order to get the behavior they expect/are used to, 104 | * but since we can easily detect this case in code, let’s do it for them. 105 | */ 106 | if ((dpi / 96.0) < 1.25) 107 | return logical; 108 | return ceil((dpi / 96.0) * logical); 109 | } 110 | -------------------------------------------------------------------------------- /dpi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Initialize the DPI setting. 5 | * This will use the 'Xft.dpi' X resource if available and fall back to 6 | * guessing the correct value otherwise. 7 | */ 8 | void init_dpi(void); 9 | 10 | /** 11 | * This function returns the value of the DPI setting. 12 | * 13 | */ 14 | long get_dpi_value(void); 15 | 16 | /** 17 | * Convert a logical amount of pixels (e.g. 2 pixels on a “standard” 96 DPI 18 | * screen) to a corresponding amount of physical pixels on a standard or retina 19 | * screen, e.g. 5 pixels on a 227 DPI MacBook Pro 13" Retina screen. 20 | * 21 | */ 22 | int logical_px(const int logical); 23 | -------------------------------------------------------------------------------- /examples/lock.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BLANK='#00000000' 4 | CLEAR='#ffffff22' 5 | DEFAULT='#ff00ffcc' 6 | TEXT='#ee00eeee' 7 | WRONG='#880000bb' 8 | VERIFYING='#bb00bbbb' 9 | 10 | i3lock \ 11 | --insidever-color=$CLEAR \ 12 | --ringver-color=$VERIFYING \ 13 | \ 14 | --insidewrong-color=$CLEAR \ 15 | --ringwrong-color=$WRONG \ 16 | \ 17 | --inside-color=$BLANK \ 18 | --ring-color=$DEFAULT \ 19 | --line-color=$BLANK \ 20 | --separator-color=$DEFAULT \ 21 | \ 22 | --verif-color=$TEXT \ 23 | --wrong-color=$TEXT \ 24 | --time-color=$TEXT \ 25 | --date-color=$TEXT \ 26 | --layout-color=$TEXT \ 27 | --keyhl-color=$WRONG \ 28 | --bshl-color=$WRONG \ 29 | \ 30 | --screen 1 \ 31 | --blur 5 \ 32 | --clock \ 33 | --indicator \ 34 | --time-str="%H:%M:%S" \ 35 | --date-str="%A, %Y-%m-%d" \ 36 | --keylayout 1 \ 37 | -------------------------------------------------------------------------------- /examples/lock_bar.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | i3lock \ 4 | --blur 5 \ 5 | --bar-indicator \ 6 | --bar-pos y+h \ 7 | --bar-direction 1 \ 8 | --bar-max-height 50 \ 9 | --bar-base-width 50 \ 10 | --bar-color 000000cc \ 11 | --keyhl-color 880088cc \ 12 | --bar-periodic-step 50 \ 13 | --bar-step 50 \ 14 | --redraw-thread \ 15 | \ 16 | --clock \ 17 | --force-clock \ 18 | --time-pos x+5:y+h-80 \ 19 | --time-color 880088ff \ 20 | --date-pos tx:ty+15 \ 21 | --date-color 990099ff \ 22 | --date-align 1 \ 23 | --time-align 1 \ 24 | --ringver-color 8800ff88 \ 25 | --ringwrong-color ff008888 \ 26 | --status-pos x+5:y+h-16 \ 27 | --verif-align 1 \ 28 | --wrong-align 1 \ 29 | --verif-color ffffffff \ 30 | --wrong-color ffffffff \ 31 | --modif-pos -50:-50 32 | -------------------------------------------------------------------------------- /examples/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Raymo111/i3lock-color/7d337d9133853109d7443a0150ccd26a6b1c02da/examples/screenshot.png -------------------------------------------------------------------------------- /examples/screenshot_2017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Raymo111/i3lock-color/7d337d9133853109d7443a0150ccd26a6b1c02da/examples/screenshot_2017.png -------------------------------------------------------------------------------- /fonts.h: -------------------------------------------------------------------------------- 1 | #ifndef FONTS_H 2 | #define FONTS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define VERIF_FONT 0 11 | #define WRONG_FONT 1 12 | #define LAYOUT_FONT 2 13 | #define TIME_FONT 3 14 | #define DATE_FONT 4 15 | #define GREETER_FONT 5 16 | 17 | typedef struct text { 18 | bool show; 19 | 20 | char str[512]; 21 | double size; 22 | double outline_width; 23 | 24 | cairo_font_face_t *font; 25 | 26 | rgba_t color; 27 | rgba_t outline_color; 28 | double x, y; 29 | 30 | int align; 31 | } text_t; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /i3lock-bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # bash completion for i3lock-color 3 | 4 | _i3lock() { 5 | local cur="${COMP_WORDS[COMP_CWORD]}" 6 | local last="${COMP_WORDS[COMP_CWORD - 1]}" 7 | local -a options=( 8 | "--version -v" 9 | "--nofork -n" 10 | "--beep -b" 11 | "--no-unlock-indicator -u" 12 | "--image -i" 13 | "--raw" 14 | "--color -c" 15 | "--tiling -t" 16 | "--centered -C" 17 | "--fill -F" 18 | "--max -M" 19 | "--scale -L" 20 | "--pointer -p" 21 | "--ignore-empty-password -e" 22 | "--show-failed-attempts" 23 | "--debug" 24 | 25 | # i3lock-color OPTIONS 26 | "--screen -S" 27 | "--blur -B" 28 | "--clock --force-clocl -k" 29 | "--indicator" 30 | "--radius" 31 | "--ring-width" 32 | # Colors 33 | "--inside-color" 34 | "--ring-color" 35 | "--insidever-color" 36 | "--ringver-color" 37 | "--insidewrong-color" 38 | "--ringwrong-color" 39 | "--line-color" 40 | "--line-uses-inside" 41 | "--line-uses-ring" 42 | "--keyhl-color" 43 | "--bshl-color" 44 | "--separator-color" 45 | "--verif-color" 46 | "--wrong-color" 47 | "--modif-color" 48 | "--layout-color" 49 | "--time-color" 50 | "--date-color" 51 | "--greeter-color" 52 | # Text 53 | "--time-str" 54 | "--date-str" 55 | "--verif-text" 56 | "--wrong-text" 57 | "--keylayout" 58 | "--noinput-text" 59 | "--lock-text" 60 | "--lockfailed-text" 61 | "--greeter-text" 62 | "--no-modkey-text" 63 | # Align 64 | "--time-align --date-align --layout-align --verif-align --wrong-algin --modif-align --greeter-align" 65 | # Outline 66 | "--timeoutlinecolor --dateoutlinecolor --layoutoutlinecolor --verifoutlinecolor --wrongoutlinecolor --modifoutline-color --greeteroutlinecolor" 67 | # Fonts 68 | "--time-font --date-font --layout-font --verif-font --wrong-font --greeter-font" 69 | # Size 70 | "--timesize --datesize --layoutsize --verifsize --wrongsize --greetersize" 71 | # Outline width 72 | "--timeoutlinewidth --dateoutlinewidth --layoutoutlinewidth --verifoutlinewidth --wrongoutlinewidth --modifieroutline-width --greeteroutlinewidth" 73 | # Position 74 | "--ind-pos" 75 | "--time-pos" 76 | "--date-pos" 77 | "--greeter-pos" 78 | # Media keys 79 | "--pass-media-keys" 80 | "--pass-screen-keys" 81 | "--pass-power-keys" 82 | "--pass-volume-keys" 83 | "--custom-key-commands" 84 | "--cmd-brightness-up" 85 | "--cmd-brightness-down" 86 | "--cmd-media-play" 87 | "--cmd-media-pause" 88 | "--cmd-media-stop" 89 | "--cmd-media-next" 90 | "--cmd-media-prev" 91 | "--cmd-audio-mute" 92 | "--cmd-volume-up" 93 | "--cmd-volume-down" 94 | "--cmd-mic-mute" 95 | "--cmd-power-down" 96 | "--cmd-power-off" 97 | "--cmd-power-sleep" 98 | # Bar mode 99 | "--bar-indicator" 100 | "--bar-direction" 101 | "--bar-orientation" 102 | "--bar-step" 103 | "--bar-max-height" 104 | "--bar-base-width" 105 | "--bar-color" 106 | "--bar-periodic-step" 107 | "--bar-pos" 108 | "--bar-count" 109 | "--bar-total-width" 110 | # Extra configs 111 | "--redraw-thread" 112 | "--refresh-rate" 113 | "--composite" 114 | "--no-verify" 115 | "--slideshow-interval" 116 | "--slideshow-random-selection" 117 | ) 118 | local args="" 119 | for i in "${options[@]}"; do 120 | args+="$i " 121 | done 122 | COMPREPLY=( $(compgen -W "${args}" -- ${cur}) ) 123 | 124 | } 125 | 126 | complete -F _i3lock i3lock 127 | -------------------------------------------------------------------------------- /i3lock-zsh: -------------------------------------------------------------------------------- 1 | #compdef i3lock 2 | 3 | _i3lock() { 4 | integer ret=1 5 | local -a args 6 | zstyle ':completion:*:*:i3lock:*:descriptions' format '' 7 | args+=( 8 | "(--version -v)"{--version,-v}"[Display the version of i3lock]" 9 | "(--nofork -n)"{--nofork,-n}"[Don't fork after starting]" 10 | "(--beep -b)"{--beeping,-b}"[Enable beeping]" 11 | "(--no-unlock-indicator -u)"{--no-unlock-indicator,-u}"[Disable the unlock indicator]" 12 | "(--image -i)"{--image,-i}"[Display the given PNG image instead of a blank screen]:filename:_files -g '*.(png|jpg)'" 13 | "--raw[Read the image given by --image as a raw image instead of PNG]:raw:" 14 | "(--color -c)"{--color,-c}"[Turn the screen into the given hex color]:hex:->hex" 15 | "(--tiling -t)"{--tiling,-t}"[Image will be displayed tiled all over the screen]" 16 | "(--centered -C)"{--centered,-C}"[Image will be displayed centered on the screen]" 17 | "(--fill -F)"{--fill,-F}"[Image will fill all over the screen]" 18 | "(--max -M)"{--max,-M}"[Image will fit the screen at width or height]" 19 | "(--scale -L)"{--scale,-L}"[Image will be stretched on the screen]" 20 | "(--pointer -p)"{--pointer,-p}"[Sets mouse pointer type]:pointer:(win default)" 21 | "(--ignore-empty-password -e)"{--ignore-empty-password,-e}"[Do not validate empty password]" 22 | "(--show-failed-attempts -f)"{--show-failed-attempts,-f}"[Show the number of failed attemps]" 23 | "--debug[Enables debug logging.]" 24 | 25 | # i3lock-color OPTIONS 26 | 27 | "(--screen -S)"{--screen,-S}"[Specifies which display to draw the unlock indicator]:int:" 28 | "(--blur -B)"{--blur,-B}"[Captures the screen and blurs it using the given sigma]:sigma:" 29 | "(--clock --force-clock -k)"{--clock,--force-clock,-k}"[Displays the clock]" 30 | "--indicator[Forces the indicator to always be visible]" 31 | "--radius[The radius of the circle]:float:" 32 | "--ring-width[The width of the ring unlock indicator]:float:" 33 | # Colors 34 | "--inside-color[Sets the default \"resting\" color for the interior circle]:hex:->hex" 35 | "--ring-color[Sets the default ring color]:hex:->hex" 36 | "--insidever-color[Sets the interior circle color while the password is being verified]:hex:->hex" 37 | "--ringver-color[Sets the ring color while the password is being verified]:hex:->hex" 38 | "--insidewrong-color[Sets the interior circle color for suring flash for an incorrect password]:hex:->hex" 39 | "--ringwrong-color[Sets the ring color during the flas for an incorrect password]:hex:->hex" 40 | "--line-color[Sets the color for the line separating the inside circle, and the outer ring]:hex:->hex" 41 | "--line-uses-inside[Conflicts with --line-uses-ring. Overrides --linecolor; the line will match the inside color]" 42 | "--line-uses-ring[Conflicts with --line-uses-inside. Overrides --linecolor; The line will match the ring color]" 43 | "--keyhl-color[Sets the color of the ring 'highlight' strokes that appear upon keypress]:hex:->hex" 44 | "--bshl-color[Sets the color of the ring 'highlight' strokes that appear upon backspace]:hex:->hex" 45 | "--separator-color[Sets the color of the 'separator', which is at both ends of the ring highlights]:hex:->hex" 46 | "--verif-color[Sets the color of the status text while verifying]:hex:->hex" 47 | "--wrong-color[Sets the color of the status when \"wrong\"]:hex:->hex" 48 | "--modif-color[Sets the color of the status text while verifying]:hex:->hex" 49 | "--layout-color[Sets the color of the keyboard layout text]:hex:->hex" 50 | "--time-color[Sets te color of the time in the clock]:hex:->hex" 51 | "--date-color[Sets the color of the date in the clock]:hex:->hex" 52 | "--greeter-color[Sets the color of the greeter text]:hex:->hex" 53 | # Text 54 | "--time-str[Sets the format used for generating the time string]:str:" 55 | "--date-str[Sets the format used for generating the date string]:str:" 56 | "--verif-text[Sets the string to be shown while verifying]:str:" 57 | "--wrong-text[Sets the string to be shown upon entering an incorrect password]:str:" 58 | "--keylayout[Displays the keylayout]:mode:((0\:'Displays the full string returned by the query, i.e. English (US)' 1\:'Displays up until the first parenthesis, i.e. English' 2\:'Displays just the contents of the parenthesis, i.e US'))" 59 | "--noinput-text[Sets the string to be shown upon pressing backspace whithout anything to delete]:str:" 60 | "--lock-text[Sets the string to be shown while acquiring pointer and keyboard focus]:str:" 61 | "--lockfailed-text[Sets the string to be shown after failing to acquire pointer and keyboard focus]:str:" 62 | "--greeter-text[Sets the greeter text]:str:" 63 | "--no-modkey-text[Hides the modkey indicator]" 64 | # Align 65 | "(--time-align --date-align --layout-align --verif-align --wrong-align --modif-align --greeter-align)"{--time-align,--date-align,--layout-align,--verif-align,--wrong-align,--modif-align,--greeter-align}"[Sets the text alignment]:alignment:((0\:'default' 1\:'left aligned' 2\:'right aligned'))" 66 | # Outline color 67 | "(--timeoutline-color --dateoutline-color --layoutoutline-color --verifoutline-color --wrongoutline-color --modifoutline-color --greeteroutline-color)"{--timeoutline-color,--dateoutline-color,--layoutoutline-color,--verifoutline-color,--wrongoutline-color,--modifoutline-color,--greeteroutline-color}"[Sets the color of the outline]:hex:->hex" 68 | # Fonts 69 | "(--time-font --date-font --layout-font --verif-font --wrong-font --greeter-font)"{--time-font,--date-font,--layout-font,--verif-font,--wrong-font,--greeter-font}"[Sets the font used to render various strings]:str:" 70 | # Size 71 | "(--time-size --date-size --layout-size --verif-size --wrong-size --greeter-size)"{--time-size,--date-size,--layout-size,--verif-size,--wrong-size,--greeter-size}"[Sets the font size used to render various strings]:int:" 72 | # Outline width 73 | "(--timeoutline-width --dateoutline-width --layoutoutline-width --verifoutline-width --wrongoutline-width --modifieroutline-width --greeteroutline-width)"{--timeoutline-width,--dateoutline-width,--layoutoutline-width,--verifoutline-width,--wrongoutline-width,--modifieroutline-width,--greeteroutline-width}"[Sets the width of the outline]:float:" 74 | # Position 75 | "--ind-pos[Sets the position for the unlock indicator]:pos:->ind_pos" 76 | "--time-pos[Sets the position for the time string]:pos:->time_pos" 77 | "--date-pos[Sets the position for the date string]:pos:->date_pos" 78 | "--greeter-pos[Sets the position for the greeter string]:pos:->greeter_pos" 79 | # Media keys 80 | "--pass-media-keys[Allow media keys to be used while the screen is locked]" 81 | "--pass-screen-keys[Allow screen keys to be used while the screen is locked]" 82 | "--pass-power-keys[Allow power keys to be used while the screen is locked]" 83 | "--pass-volume-keys[Allow volume keys to be used while the screen is locked]" 84 | "--custom-key-commands[Enable shell commands for media keys]" 85 | "--cmd-brightness-up[Command for XF86MonBrightnessUp]" 86 | "--cmd-brightness-down[Command for XF86MonBrightnessDown]" 87 | "--cmd-media-play[Command for XF86AudioPlay]" 88 | "--cmd-media-pause[Command for XF86AudioPause]" 89 | "--cmd-media-stop[Command for XF86AudioStop]" 90 | "--cmd-media-next[Command for XF86AudioNext]" 91 | "--cmd-media-prev[Command for XF86AudioPrev]" 92 | "--cmd-audio-mute[Command for XF86AudioMute]" 93 | "--cmd-volume-up[Command for XF86AudioRaiseVolume]" 94 | "--cmd-volume-down[Command for XF86AudioLowerVolume]" 95 | "--cmd-mic-mute[Command for XF86AudioMicMute]" 96 | "--cmd-power-down[Command for XF86PowerDown]" 97 | "--cmd-power-off[Command for XF86PowerOff]" 98 | "--cmd-power-sleep[Command for XF86Sleep]" 99 | # Bar mode 100 | "--bar-indicator[Replaces the usual ring indicator with a bar indicator]" 101 | "--bar-direction[Sets the direction the bars grow in]:direction:((0\:'default' 1\:'reverse' 2\:'both'))" 102 | "--bar-orientation[Sets whether the bar is vertically or horizontally oriented]:orientation:(vertical horizontal)" 103 | "--bar-step[Sets the step that each bar decreases by when a key is pressed]:int:" 104 | "--bar-max-height[The maximum height a bar can get to]:float:" 105 | "--bar-base-width[The thickness of the \"base\" bar that all the bar originate from]:float:" 106 | "--bar-color[Sets the default color of the bar base]:hex:->hex" 107 | "--bar-periodic-step[The value by which the bars decrease each time the screen is redrawn]:int:" 108 | "--bar-pos[Sets the bar position]:pos:->bar_pos" 109 | "--bar-count[Sets the number of minibars to draw on each screen]:int:" 110 | "--bar-total-width[The total width of the bar]:float:" 111 | # Extra configs 112 | "--redraw-thread[Starts a separate thread for redrawing the screen]" 113 | "--refresh-rate[The refresh rate of the indicator]:double:" 114 | "--composite" 115 | "--no-verify[Do not verify the password provided by the user and unlock inmediately]" 116 | # Slideshow 117 | "--slideshow-interval[The interval to wait until switching to the nex image]:double:" 118 | "--slideshow-random-selection[Randomize the order of the images]" 119 | 120 | 121 | ) 122 | _arguments $args[@] && ret=0 123 | 124 | case "$state" in 125 | hex) 126 | zstyle ':completion:*:*:i3lock:*:descriptions' format '%d' 127 | _message "Color in hexadecimal rrggbbaa, like #ff0000ff or #354F9AFF" 128 | ;; 129 | ind_pos) 130 | zstyle ':completion:*:*:i3lock:*:normal' format '%d' 131 | zstyle ':completion:*:*:i3lock:*:descriptions' format '%B%d%b' 132 | 133 | _message "\"x position:y position\"" 134 | _message -e "normal" "'x' - x position of the current display. Corresponds to the left-most row of pixels" 135 | _message -e "normal" "'y' - y position of the current display. Corresponds to the topmost row of pixels" 136 | _message -e "normal" "'w' - width of the current display" 137 | _message -e "normal" "'w' - height of the current display" 138 | _message -e "normal" "'r' - unlock indicator radius" 139 | ;; 140 | time_pos) 141 | zstyle ':completion:*:*:i3lock:*:normal' format '%d' 142 | zstyle ':completion:*:*:i3lock:*:descriptions' format '%B%d%b' 143 | 144 | _message "\"x position:y position\"" 145 | _message -e "normal" "All the variables from --ind-pos may be used, in addition to:" 146 | _message -e "normal" "'ix' - x position of the indicator on the current display" 147 | _message -e "normal" "'iy' - y position of the indicator on the current display" 148 | _message -e "normal" "If the --bar-indicator option is used, the following may be used" 149 | _message -e "normal" "'bw' - width od the bar indicator" 150 | _message -e "normal" "'bx' - x position of the bar indicator on the current display" 151 | _message -e "normal" "'by' - y position of the bar indicator on the current display" 152 | ;; 153 | date_pos) 154 | zstyle ':completion:*:*:i3lock:*:normal' format '%d' 155 | zstyle ':completion:*:*:i3lock:*:descriptions' format '%B%d%b' 156 | 157 | _message "\"x position:y position\"" 158 | _message -e "normal" "All the variables from --ind-pos and --time-pos may be used, in addition to:" 159 | _message -e "normal" "'tx' - x position of the timestring on the current display" 160 | _message -e "normal" "'ty' - y position of the timestring on the current display" 161 | ;; 162 | greeter_pos) 163 | zstyle ':completion:*:*:i3lock:*:normal' format '%d' 164 | zstyle ':completion:*:*:i3lock:*:descriptions' format '%B%d%b' 165 | 166 | _message "\"x position:y position\"" 167 | _message -e "normal" "All the variables from --ind-pos and --time-pos may be used" 168 | ;; 169 | bar_pos) 170 | zstyle ':completion:*:*:i3lock:*:normal' format '%d' 171 | zstyle ':completion:*:*:i3lock:*:descriptions' format '%B%d%b' 172 | 173 | _message "\"x position:y position\"" 174 | _message -e "normal" "All the variables from --ind-pos and --time-pos may be used" 175 | _message -e "normal" "If only one number is provided, sets the vertical offset from the top or left edge" 176 | _message -e "normal" "If two numbers are provided, sets the starting position of the bar" 177 | ;; 178 | 179 | 180 | esac 181 | 182 | return ret 183 | } 184 | 185 | _i3lock 186 | -------------------------------------------------------------------------------- /i3lock.1: -------------------------------------------------------------------------------- 1 | .de Vb \" Begin verbatim text 2 | .ft CW 3 | .nf 4 | .ne \\$1 5 | .. 6 | .de Ve \" End verbatim text 7 | .ft R 8 | .fi 9 | .. 10 | 11 | .TH i3lock-color 1 "MAR 2025" Linux "User Manuals" 12 | 13 | .SH NAME 14 | i3lock-color \- improved screen locker 15 | 16 | .SH SYNOPSIS 17 | .B i3lock 18 | .RB [\|\-v\|] 19 | .RB [\|\-n\|] 20 | .RB [\|\-b\|] 21 | .RB [\|\-i 22 | .IR image.png \|] 23 | .RB [\|\-c 24 | .IR color \|] 25 | .RB [\|\-t\|] 26 | .RB [\|\-p 27 | .IR pointer\|] 28 | .RB [\|\-u\|] 29 | .RB [\|\-e\|] 30 | .RB [\|\-f\|] 31 | .RB [\|\-m\|] 32 | 33 | .SH DESCRIPTION 34 | .B i3lock\-color 35 | is a simple screen locker like slock. After starting it, you will see a white 36 | screen (you can configure the color/an image). You can return to your screen by 37 | entering your password. 38 | 39 | .SH FEATURES 40 | .IP \[bu] 2 41 | i3lock forks, so you can combine it with an alias to suspend to RAM 42 | (run "i3lock && echo mem > /sys/power/state" to get a locked screen after waking 43 | up your computer from suspend to RAM) 44 | .IP \[bu] 45 | You can specify either a PNG or JPG image, a GIF animation or a background 46 | color which will be displayed while your screen is locked. 47 | .IP \[bu] 48 | You can specify whether i3lock should bell upon a wrong password. 49 | .IP \[bu] 50 | i3lock uses PAM and therefore is compatible with LDAP, etc. 51 | 52 | .SH OPTIONS 53 | .TP 54 | .B \-v, \-\-version 55 | Display the version of your 56 | .B i3lock 57 | 58 | .TP 59 | .B \-n, \-\-nofork 60 | Don't fork after starting. 61 | 62 | .TP 63 | .B \-b, \-\-beep 64 | Enable beeping. Be sure to not do this when you are about to annoy other people, 65 | like when opening your laptop in a boring lecture. 66 | 67 | .TP 68 | .B \-u, \-\-no\-unlock\-indicator 69 | Disable the unlock indicator. i3lock will by default show an unlock indicator 70 | after pressing keys. This will give feedback for every keypress and it will 71 | show you the current PAM state (whether your password is currently being 72 | verified or whether it is wrong). 73 | 74 | .TP 75 | .BI \-i\ path \fR,\ \fB\-\-image= path 76 | Display the given PNG/JPG image or GIF animation instead of a blank screen. 77 | 78 | .TP 79 | .BI \fB\-\-raw= format 80 | Read the image given by \-\-image as a raw image instead of PNG/JPG/GIF. The 81 | argument is the image's format as x:. 82 | The supported pixel formats are: 83 | \'native', 'rgb', 'xrgb', 'rgbx', 'bgr', 'xbgr', and 'bgrx'. 84 | The "native" pixel format expects a pixel as a 32-bit (4-byte) integer in 85 | the machine's native endianness, with the upper 8 bits unused. 86 | Red, green and blue are stored in the remaining bits, in that order. 87 | 88 | .BR Example: 89 | .Vb 6 90 | \& --raw=1920x1080:rgb 91 | .Ve 92 | You can use ImageMagick’s 93 | .IR convert(1) 94 | program to feed raw images into i3lock: 95 | 96 | .Vb 6 97 | \& convert wallpaper.jpg RGB:- | i3lock --raw 3840x2160:rgb --image /dev/stdin 98 | .Ve 99 | This allows you to load a variety of image formats without i3lock having to 100 | support each one explicitly. 101 | You can also use it to resize images to the screen ratio: 102 | 103 | .Vb 6 104 | \& convert wallpaper.jpg -resize $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/') RGB:- | i3lock --raw $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/'):rgb --image /dev/stdin 105 | .Ve 106 | Note that $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/') 107 | gets you the current screen dimensions in the wxh (e.g. 1920x1080) format. 108 | 109 | .TP 110 | .BI \-c\ rrggbbaa \fR,\ \fB\-\-color= rrggbbaa 111 | Turn the screen into the given color instead of white. Color must be given in 112 | 4-byte format: rrggbbaa (i.e. ff0000ff is opaque red). 113 | Use the last byte for alpha. Setting this below FF (i.e. ff000088) will allow 114 | your screen to be shown translucently if you use a compositor (e.g. compton, 115 | xcompmgr). 116 | 117 | .TP 118 | .B \-t, \-\-tiling 119 | If an image is specified (via \-i) it will display the image tiled all over the 120 | screen. 121 | 122 | Note: For all image options, with a multi-monitor setup, the image is visible on 123 | all screens. 124 | 125 | .TP 126 | .B \-C, \-\-centered 127 | If an image is specified (via \-i) it will display the image centered on the 128 | screen. 129 | 130 | .TP 131 | .B \-F, \-\-fill 132 | If an image is specified (via \-i) it will scale the image until it fills the 133 | screen. A portion of the image will be cropped. 134 | 135 | .TP 136 | .B \-M, \-\-max 137 | If an image is specified (via \-i) it will scale the image until either the 138 | width or the height fits the screen without being cropped. The border color 139 | can be set via \-c. 140 | 141 | .TP 142 | .B \-L, \-\-scale 143 | If an image is specified (via \-i) it will stretch the image until both the 144 | width and the height fits the screen. 145 | 146 | .TP 147 | .BI \-p\ win|default \fR,\ \fB\-\-pointer= win|default 148 | If you specify "default", 149 | .B i3lock 150 | does not hide your mouse pointer. If you specify "win", 151 | .B i3lock 152 | displays a hardcoded Windows-Pointer (thus enabling you to mess with your 153 | friends by using a screenshot of a Windows desktop as a locking-screen). 154 | 155 | .TP 156 | .B \-e, \-\-ignore\-empty\-password 157 | When an empty password is provided by the user, do not validate it. Without this 158 | option, the empty password will be provided to PAM and, if invalid, the user 159 | will have to wait a few seconds before another try. This can be useful if the 160 | XF86ScreenSaver key is used to put a laptop to sleep and bounce on resume or if 161 | you happen to wake up your computer with the enter key. 162 | 163 | .TP 164 | .B \-f, \-\-show\-failed\-attempts 165 | Show the number of failed attempts, if any. 166 | 167 | .TP 168 | .B \-\-debug 169 | Enables debug logging. 170 | Note, that this will log the password used for authentication to stdout. 171 | 172 | .SH i3lock-color OPTIONS 173 | .TP 174 | .B \-S number, \-\-screen=number 175 | Specifies which display to draw the unlock indicator and clock on. By default, 176 | they'll be placed on every screen. 177 | Note that this number is zero indexed. The ordering is dependent on libxinerama. 178 | 179 | .TP 180 | .B \-B sigma, \-\-blur=sigma 181 | Captures the screen and blurs it using the given sigma (radius). 182 | Images may still be overlaid over the blurred screenshot. 183 | As an alternative to this option, you could specify a translucent background 184 | color (-c option) with a fully transparent or translucent color, and use a 185 | compositor to perform blurring (e.g. compton, picom). 186 | 187 | .TP 188 | .B \-k, \-\-clock, \-\-force\-clock 189 | Displays the clock. \-\-force\-clock also displays the clock when there's 190 | indicator text (useful for when the clock is not positioned with the indicator). 191 | 192 | .TP 193 | .B \-\-indicator 194 | Forces the indicator to always be visible, instead of only showing on activity. 195 | 196 | .TP 197 | .B \-\-radius 198 | The radius of the circle. Defaults to 90. 199 | 200 | .TP 201 | .B \-\-ring\-width 202 | The width of the ring unlock indicator. Defaults to 7.0. 203 | 204 | .TP 205 | .B \-\-{inside, ring}\-color=rrggbbaa 206 | Sets the idle color for the interior circle and ring. Note: use individual 207 | options per element unless the shell supports brace expansion (in which case 208 | remove the spaces inside the curly braces). 209 | 210 | .TP 211 | .B \-\-{inside, ring}ver\-color=rrggbbaa 212 | Sets the interior circle and ring color while the password is being verified. 213 | 214 | .TP 215 | .B \-\-{inside, ring}wrong\-color=rrggbbaa 216 | Sets the interior circle and ring color for during incorrect password flashes. 217 | 218 | .TP 219 | .B \-\-line\-color=rrggbbaa 220 | Sets the color for the line separating the inside circle and the outer ring. 221 | 222 | .TP 223 | .B \-\-line\-uses\-{inside, ring} 224 | Overrides \-\-line\-color. The line will match the {inside, ring} color. 225 | Note: these two options conflict with each other. 226 | 227 | .TP 228 | .B \-\-{key, bs}hl\-color=rrggbbaa 229 | Sets the color of highlight arcs on the ring upon keypress and backspace. 230 | 231 | .TP 232 | .B \-\-separator\-color=rrggbbaa 233 | Sets the color of the seperators at both ends of the highlight arcs on the ring. 234 | 235 | .TP 236 | .B \-\-{verif, wrong, modif}\-color=rrggbbaa 237 | Sets the color of the status text while verifying and when password is wrong. 238 | 239 | .TP 240 | .B \-\-{layout, time, date, greeter}\-color=rrggbbaa 241 | Sets text colors. 242 | 243 | .TP 244 | .B \-\-keylayout mode 245 | Displays the keylayout. Positionable similar to date, time, and indicator. 246 | Modes are as follows: 247 | .RS 248 | .IP \[bu] 2 249 | 0 - Displays the full string returned by the query, i.e. "English (US)" 250 | .IP \[bu] 251 | 1 - Displays up until the first parenthesis, i.e. "English" 252 | .IP \[bu] 253 | 2 - Displays just the contents of the parenthesis, i.e. "US" 254 | .RE 255 | 256 | .B For all following -str or -text options, some control characters 257 | .B (i.e. \\\\n, \\\\t) are supported. See \fBCONTROL CHARACTERS\fR 258 | .B for more details. 259 | 260 | .TP 261 | .B \-\-time\-str="%H:%M:%S" 262 | Sets the format used for generating the time string. 263 | See strftime(3) for a full list of format specifiers. 264 | 265 | .TP 266 | .B \-\-date\-str="%A, %m %Y" 267 | Sets the format used for generating the date string. 268 | 269 | .TP 270 | .B \-\-verif\-text="verifying…" 271 | Sets the string to be shown while verifying the password/input/key/etc. 272 | 273 | .TP 274 | .B \-\-wrong\-text="wrong!" 275 | Sets the string to be shown upon entering an incorrect password. 276 | 277 | .TP 278 | .B \-\-noinput\-text="no input" 279 | Sets the string to be shown upon pressing backspace without anything to delete. 280 | 281 | .TP 282 | .B \-\-lock\-text="locking…" 283 | Sets the string to be shown while acquiring pointer and keyboard focus. 284 | 285 | .TP 286 | .B \-\-lockfailed\-text="lock failed!" 287 | Sets the string to be shown after failing to acquire pointer and keyboard focus. 288 | 289 | .TP 290 | .B \-\-greeter\-text="" 291 | Sets the greeter text. 292 | 293 | .TP 294 | .B \-\-no\-modkey\-text 295 | Hides the modkey indicator (Num, Caps Lock ...) 296 | 297 | .TP 298 | .B \-\-{time, date, layout, verif, wrong, modif, greeter}\-align 299 | Sets the text alignment of the time, date, keylayout, verification, wrong, 300 | modifier and greeter texts. 301 | .RS 302 | .IP \[bu] 2 303 | 0 - centered (default) 304 | .IP \[bu] 305 | 1 - left aligned 306 | .IP \[bu] 307 | 2 - right aligned 308 | .RE 309 | 310 | .TP 311 | .B \-\-{time, date, layout, verif, wrong, greeter, modif}outline\-color=rrggbbaa 312 | Sets the color of the outlines. 313 | 314 | .TP 315 | .B \-\-{time, date, layout, verif, wrong, greeter}\-font=sans\-serif 316 | Sets the font used to render various strings. 317 | 318 | .TP 319 | .B \-\-{time, date, layout, verif, wrong, greeter}\-size=number 320 | Sets the font size used to render various strings. 321 | 322 | .TP 323 | .B \-\-{time, date, layout, verif, wrong, greeter, modifier}outline\-width=number 324 | Sets the width of the outline. 325 | 326 | .TP 327 | .B \-\-ind\-pos="x\-position:y\-position" 328 | Sets the position for the unlock indicator. Valid variables include: 329 | .RS 330 | .IP \[bu] 2 331 | x - x position of the current display. 332 | Corresponds to the leftmost column of pixels on that display. 333 | .IP \[bu] 334 | y - y position of the current display. 335 | Corresponds to the topmost row of pixels on that display. 336 | .IP \[bu] 337 | w - width of the current display. 338 | .IP \[bu] 339 | h - height of the current display. 340 | .IP \[bu] 341 | r - unlock indicator radius. 342 | .RE 343 | 344 | .TP 345 | .B \-\-time\-pos="x\-position:y\-position" 346 | Sets the position for the time string. All the variables from \-\-ind\-pos may 347 | be used, in addition to: 348 | .RS 349 | .IP \[bu] 2 350 | ix - x position of the indicator on the current display. 351 | .IP \[bu] 352 | iy - y position of the indicator on the current display. 353 | 354 | If the \-\-bar\-indicator option is used, the following variables may be used: 355 | .IP \[bu] 2 356 | bw - width of the bar indicator. 357 | .IP \[bu] 358 | bx - x position of the bar indicator on the current display. 359 | .IP \[bu] 360 | by - y position of the bar indicator on the current display. 361 | .RE 362 | 363 | .TP 364 | .B \-\-date\-pos="x\-position:y\-position" 365 | Sets the position for the date string. All the variables from \-\-ind\-pos and 366 | \-\-time\-pos may be used, in addition to: 367 | .RS 368 | .IP \[bu] 2 369 | tx - x position of the timestring on the current display. 370 | .IP \[bu] 371 | ty - y position of the timestring on the current display. 372 | .RE 373 | 374 | .TP 375 | .B \-\-greeter\-pos="x\-position:y\-position" 376 | Sets the position for the greeter string. All the variables from \-\-ind\-pos and 377 | \-\-time\-pos may be used. 378 | 379 | .TP 380 | .B \-\-pass\-{media, screen, power, volume}\-keys 381 | Allow the following keys to be used normally while the screen is locked by 382 | passing them through: 383 | .RS 384 | .IP \[bu] 2 385 | media - XF86AudioPlay, XF86AudioPause, XF86AudioStop, XF86AudioPrev, 386 | XF86AudioNext, XF86AudioMute, XF86AudioLowerVolume, XF86AudioRaiseVolume, 387 | XF86AudioMicMute 388 | .IP \[bu] 389 | screen - XF86MonBrightnessUp, XF86MonBrightnessDown 390 | .IP \[bu] 391 | power - XF86PowerDown, XF86PowerOff, XF86Sleep 392 | .IP \[bu] 393 | volume - XF86AudioMute, XF86AudioLowerVolume, XF86AudioRaiseVolume 394 | .RE 395 | 396 | 397 | .TP 398 | .B \-\-custom\-key\-commands 399 | Enables custom shell commands for media, screen, power and volume keys. An alternative to \-\-pass\-media\0keys that will work in any environment. 400 | 401 | .TP 402 | .B \-\-cmd\-** 403 | Shell command to run when the corresponding key is pressed. Requires \-\-custom\-key\-commands 404 | .RS 405 | .IP \[bu] 2 406 | brightness\-up - XF86MonBrightnessUp 407 | .IP \[bu] 408 | brightness\-down - XF86MonBrightnessDown 409 | .IP \[bu] 410 | media\-play - XF86AudioPlay 411 | .IP \[bu] 412 | media\-pause - XF86AudioPause 413 | .IP \[bu] 414 | media\-stop - XF86AudioStop 415 | .IP \[bu] 416 | media\-next - XF86AudioNext 417 | .IP \[bu] 418 | media\-prev - XF86AudioPrev 419 | .IP \[bu] 420 | audio\-mute - XF86AudioMute 421 | .IP \[bu] 422 | volume\-up - XF86AudioRaiseVolume 423 | .IP \[bu] 424 | volume\-down - XF86AudioLowerVolume 425 | .IP \[bu] 426 | mic\-mute - XF86AudioMicMute 427 | .IP \[bu] 428 | power\-down - XF86PowerDown 429 | .IP \[bu] 430 | power\-off - XF86PowerOff 431 | .IP \[bu] 432 | power\-sleep - XF86Sleep 433 | .RE 434 | 435 | .TP 436 | .B \-\-bar\-indicator 437 | Replaces the usual ring indicator with a bar indicator. Comes with perks. 438 | 439 | .TP 440 | .B \-\-bar\-direction={0, 1, 2} 441 | Sets the direction the bars grow in. 0 is the default (downwards, or rightwards, 442 | depending on the bar orientation). 1 is the reverse, and 2 is both. 443 | 444 | .TP 445 | .B \-\-bar\-orientation={vertical,horizontal} 446 | Sets whether the bar is vertically or horizontally oriented. 447 | Defaults to horizontal. 448 | 449 | .TP 450 | .B \-\-bar\-step 451 | Sets the step that each bar decreases by when a key is pressed. A random bar is 452 | set to its max height, then each neighbor is set to (height - step*distance). 453 | 454 | .TP 455 | .B \-\-bar\-max\-height 456 | The maximum height a bar can get to. When a key is pressed, a random bar is set 457 | to this value, then its neighbors are set to its height, minus the step value. 458 | 459 | .TP 460 | .B \-\-bar\-base\-width 461 | The thickness of the "base" bar that all the bars originate from. 462 | This bar also takes on the ring verification and wrong colors to give 463 | authentication feedback. 464 | 465 | .TP 466 | .B \-\-bar\-color 467 | Sets the default color of the bar base. 468 | 469 | .TP 470 | .B \-\-bar\-periodic\-step 471 | The value by which the bars decrease each time the screen is redrawn. 472 | 473 | .TP 474 | .B \-\-bar\-pos 475 | Works similarly to the time/date/indicator expressions. If only one number is 476 | provided, this sets the vertical offset from the top or left edge. If two 477 | numbers are provided in the form of x:y, sets the starting position of the bar. 478 | 479 | .TP 480 | .B \-\-bar\-count 481 | Sets the number of minibars to draw on each screen. 482 | 483 | .TP 484 | .B \-\-bar\-total\-width 485 | The total width of the bar. Can be an expression. 486 | 487 | .TP 488 | .B \-\-redraw\-thread 489 | Starts a separate thread for redrawing the screen. Potentially worse from a 490 | security standpoint, but makes the bar indicator still do its usual periodic 491 | redraws when PAM is authenticating. 492 | 493 | .TP 494 | .B \-\-refresh\-rate=seconds\-as\-double 495 | The refresh rate of the indicator, given in seconds. This should automatically 496 | align itself, but is somewhat buggy currently. 497 | Values less than one will work, but may result in poor system performance. 498 | 499 | .TP 500 | .B \-\-composite 501 | Some compositors have problems with i3lock trying to render over them, so this 502 | argument is disabled by default. However, some will work properly with it, so 503 | it's been left enabled. 504 | 505 | .TP 506 | .B \-\-no\-verify 507 | Do not verify the password entered by the user and unlock immediately. 508 | .B Use only for quickly testing new configurations and remember to remove to 509 | .B actually lock your screen! 510 | 511 | .TP 512 | .B \-\-slideshow\-interval 513 | The interval to wait until switching to the next image. 514 | 515 | .TP 516 | .B \-\-slideshow\-random\-selection 517 | Randomize the order of the images. 518 | 519 | .SH CONTROL CHARACTERS 520 | Control characters (\\r \\n \\b \\t) are supported in text OPTIONS. Their behavior 521 | are almost as same as anywhere else. 522 | .TP 523 | .B Carriage Return(\\\\r) 524 | Move to the start of line (left edge). 525 | Notes: The rendered characters would still live there. 526 | .TP 527 | .B Line Feed(\\\\n) 528 | Move to start of next line (left edge). 529 | .TP 530 | .B Backspace(\\\\b) 531 | Overwrite last one char if exists. 532 | Notes: The rendered character would still live there. 533 | .TP 534 | .B Tab(\\\\t) 535 | Move to next tab stop position.The width of one character for moving is as same as character 'a'. 536 | Note: The width may be strange if the font is not mono-spaced. 537 | 538 | .SH SEE ALSO 539 | .IR xautolock(1) 540 | \- use i3lock as your screen saver 541 | 542 | .IR convert(1) 543 | \- feed a wide variety of image formats to i3lock 544 | 545 | .SH HOMEPAGE 546 | https://github.com/Raymo111/i3lock-color 547 | 548 | Please report bugs and submit pull-requests as follows: 549 | For i3lock (upstream): https://github.com/i3/i3lock 550 | For i3lock-color (enhancements on top of i3lock): https://github.com/Raymo111/i3lock-color 551 | 552 | .SH AUTHORS 553 | Michael Stapelberg 554 | 555 | Jan-Erik Rediger 556 | 557 | Pandora 558 | 559 | Raymond Li 560 | -------------------------------------------------------------------------------- /i3lock.h: -------------------------------------------------------------------------------- 1 | #ifndef _I3LOCK_H 2 | #define _I3LOCK_H 3 | 4 | // boy i sure hope this doesnt change in the future 5 | #define NANOSECONDS_IN_SECOND 1000000000 6 | 7 | /* This macro will only print debug output when started with --debug. 8 | * This is important because xautolock (for example) closes stdout/stderr by 9 | * default, so just printing something to stdout will lead to the data ending 10 | * up on the X11 socket (!). */ 11 | #define DEBUG(fmt, ...) \ 12 | do { \ 13 | if (debug_mode) { \ 14 | fprintf(stderr, "[i3lock-debug] " fmt, ##__VA_ARGS__); \ 15 | } \ 16 | } while (0) 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /install-i3lock-color.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LICENSE='/usr/share/licenses/i3lock-color/LICENSE' 4 | 5 | ./build.sh 6 | cd build 7 | sudo make install 8 | sudo install -Dm644 ../LICENSE "$LICENSE" 9 | 10 | echo "i3lock-color installed. The binary and manpage listing are \`i3lock'. 11 | The license can be found at $LICENSE 12 | GitHub repo: https://github.com/Raymo111/i3lock-color 13 | Discord server: https://discord.gg/FzVPghyDt2" 14 | -------------------------------------------------------------------------------- /jpg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "jpg.h" 12 | 13 | /* 14 | * Checks if the file is a JPEG by looking for a valid JPEG header. 15 | */ 16 | bool file_is_jpg(FILE* image_file) { 17 | uint16_t file_header; 18 | size_t read_count; 19 | // TODO: Consider endianess on non-x86 platforms 20 | uint16_t jpg_magick = 0xd8ff; 21 | 22 | fseek(image_file, 0, SEEK_SET); 23 | read_count = fread(&file_header, sizeof(file_header), 1, image_file); 24 | 25 | if (read_count < 1) { 26 | fprintf(stderr, "Error searching for JPEG header\n"); 27 | return false; 28 | } 29 | 30 | return file_header == jpg_magick; 31 | } 32 | 33 | /* 34 | * Reads a JPEG from a file into memory, in a format that Cairo can create a 35 | * surface from. 36 | */ 37 | void* read_JPEG_file(char *file_path, JPEG_INFO *jpg_info) { 38 | int img_err; 39 | struct jpeg_decompress_struct cinfo; 40 | struct jpeg_error_mgr jerr; 41 | FILE *infile; /* source file */ 42 | void *img; /* decompressed image data pointer */ 43 | 44 | if ((infile = fopen(file_path, "rb")) == NULL) { 45 | img_err = errno; 46 | fprintf(stderr, "Could not open image file %s: %s\n", 47 | file_path, strerror(img_err)); 48 | return NULL; 49 | } 50 | 51 | cinfo.err = jpeg_std_error(&jerr); 52 | jpeg_create_decompress(&cinfo); 53 | 54 | jpeg_stdio_src(&cinfo, infile); 55 | 56 | (void) jpeg_read_header(&cinfo, TRUE); 57 | 58 | // BGRA + endianness change = RGBA? 59 | // TODO: Test this code on non-x86_64 platforms 60 | cinfo.out_color_space = JCS_EXT_BGRA; 61 | 62 | (void) jpeg_start_decompress(&cinfo); 63 | 64 | jpg_info->height = cinfo.output_height; 65 | jpg_info->width = cinfo.output_width; 66 | 67 | /* Get the *cairo* stride rather than the stride from the image. This is 68 | * the space needed in memory for each row for optimized Cairo rendering. */ 69 | int cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, 70 | cinfo.output_width); 71 | jpg_info->stride = cairo_stride; 72 | if (cairo_stride < jpg_info->width) { 73 | /* This should never happen, but if it does then the following code 74 | * will potentially write into unallocated memory */ 75 | fprintf( 76 | stderr, 77 | "WARNING: Cairo stride shorter than JPEG width. Aborting JPEG read." 78 | ); 79 | return NULL; 80 | } 81 | 82 | // Allocate storage for the final, decompressed image. 83 | img = calloc(cairo_stride, cinfo.output_height); 84 | if (img == NULL) { 85 | fprintf(stderr, "Could not allocate memory for JPEG decode\n"); 86 | 87 | (void) jpeg_finish_decompress(&cinfo); 88 | jpeg_destroy_decompress(&cinfo); 89 | fclose(infile); 90 | 91 | return NULL; 92 | } 93 | 94 | while (cinfo.output_scanline < cinfo.output_height) { 95 | /* Normally, you would allocate a buffer using libJPEG's memory 96 | * management and write into it, but since we're reading one row at a 97 | * time, we just write it directly into the image memory space */ 98 | unsigned char* pos = img + (cairo_stride * (cinfo.output_scanline)); 99 | (void) jpeg_read_scanlines(&cinfo, &pos, 1); 100 | } 101 | 102 | (void) jpeg_finish_decompress(&cinfo); 103 | 104 | jpeg_destroy_decompress(&cinfo); 105 | fclose(infile); 106 | 107 | return img; 108 | } 109 | -------------------------------------------------------------------------------- /jpg.h: -------------------------------------------------------------------------------- 1 | #ifndef _JPG_H 2 | #define _JPG_H 3 | 4 | #include 5 | 6 | #define _GNU_SOURCE 1 7 | typedef struct { 8 | uint height; 9 | uint width; 10 | uint stride; // The width of each row in memory, in bytes 11 | } JPEG_INFO; 12 | 13 | /* 14 | * Checks if the file is a JPEG by looking for a valid JPEG header. 15 | */ 16 | bool file_is_jpg(FILE* image_file); 17 | 18 | /* 19 | * Reads a JPEG from a file into memory, in a format that Cairo can create a 20 | * surface from. 21 | */ 22 | void* read_JPEG_file(char *filename, JPEG_INFO *jpg_info); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /m4/ax_append_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_append_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # FLAG is appended to the FLAGS-VARIABLE shell variable, with a space 12 | # added in between. 13 | # 14 | # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. 15 | # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains 16 | # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly 17 | # FLAG. 18 | # 19 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. 20 | # 21 | # LICENSE 22 | # 23 | # Copyright (c) 2008 Guido U. Draheim 24 | # Copyright (c) 2011 Maarten Bosmans 25 | # 26 | # This program is free software: you can redistribute it and/or modify it 27 | # under the terms of the GNU General Public License as published by the 28 | # Free Software Foundation, either version 3 of the License, or (at your 29 | # option) any later version. 30 | # 31 | # This program is distributed in the hope that it will be useful, but 32 | # WITHOUT ANY WARRANTY; without even the implied warranty of 33 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 34 | # Public License for more details. 35 | # 36 | # You should have received a copy of the GNU General Public License along 37 | # with this program. If not, see . 38 | # 39 | # As a special exception, the respective Autoconf Macro's copyright owner 40 | # gives unlimited permission to copy, distribute and modify the configure 41 | # scripts that are the output of Autoconf when processing the Macro. You 42 | # need not follow the terms of the GNU General Public License when using 43 | # or distributing such scripts, even though portions of the text of the 44 | # Macro appear in them. The GNU General Public License (GPL) does govern 45 | # all other use of the material that constitutes the Autoconf Macro. 46 | # 47 | # This special exception to the GPL applies to versions of the Autoconf 48 | # Macro released by the Autoconf Archive. When you make and distribute a 49 | # modified version of the Autoconf Macro, you may extend this special 50 | # exception to the GPL to apply to your modified version as well. 51 | 52 | #serial 6 53 | 54 | AC_DEFUN([AX_APPEND_FLAG], 55 | [dnl 56 | AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF 57 | AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) 58 | AS_VAR_SET_IF(FLAGS,[ 59 | AS_CASE([" AS_VAR_GET(FLAGS) "], 60 | [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], 61 | [ 62 | AS_VAR_APPEND(FLAGS,[" $1"]) 63 | AC_RUN_LOG([: FLAGS="$FLAGS"]) 64 | ]) 65 | ], 66 | [ 67 | AS_VAR_SET(FLAGS,[$1]) 68 | AC_RUN_LOG([: FLAGS="$FLAGS"]) 69 | ]) 70 | AS_VAR_POPDEF([FLAGS])dnl 71 | ])dnl AX_APPEND_FLAG 72 | -------------------------------------------------------------------------------- /m4/ax_cflags_warn_all.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] 8 | # AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] 9 | # AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] 10 | # 11 | # DESCRIPTION 12 | # 13 | # Try to find a compiler option that enables most reasonable warnings. 14 | # 15 | # For the GNU compiler it will be -Wall (and -ansi -pedantic) The result 16 | # is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default. 17 | # 18 | # Currently this macro knows about the GCC, Solaris, Digital Unix, AIX, 19 | # HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and 20 | # Intel compilers. For a given compiler, the Fortran flags are much more 21 | # experimental than their C equivalents. 22 | # 23 | # - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS 24 | # - $2 add-value-if-not-found : nothing 25 | # - $3 action-if-found : add value to shellvariable 26 | # - $4 action-if-not-found : nothing 27 | # 28 | # NOTE: These macros depend on AX_APPEND_FLAG. 29 | # 30 | # LICENSE 31 | # 32 | # Copyright (c) 2008 Guido U. Draheim 33 | # Copyright (c) 2010 Rhys Ulerich 34 | # 35 | # This program is free software; you can redistribute it and/or modify it 36 | # under the terms of the GNU General Public License as published by the 37 | # Free Software Foundation; either version 3 of the License, or (at your 38 | # option) any later version. 39 | # 40 | # This program is distributed in the hope that it will be useful, but 41 | # WITHOUT ANY WARRANTY; without even the implied warranty of 42 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 43 | # Public License for more details. 44 | # 45 | # You should have received a copy of the GNU General Public License along 46 | # with this program. If not, see . 47 | # 48 | # As a special exception, the respective Autoconf Macro's copyright owner 49 | # gives unlimited permission to copy, distribute and modify the configure 50 | # scripts that are the output of Autoconf when processing the Macro. You 51 | # need not follow the terms of the GNU General Public License when using 52 | # or distributing such scripts, even though portions of the text of the 53 | # Macro appear in them. The GNU General Public License (GPL) does govern 54 | # all other use of the material that constitutes the Autoconf Macro. 55 | # 56 | # This special exception to the GPL applies to versions of the Autoconf 57 | # Macro released by the Autoconf Archive. When you make and distribute a 58 | # modified version of the Autoconf Macro, you may extend this special 59 | # exception to the GPL to apply to your modified version as well. 60 | 61 | #serial 15 62 | 63 | AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl 64 | AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl 65 | AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl 66 | AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings], 67 | VAR,[VAR="no, unknown" 68 | ac_save_[]FLAGS="$[]FLAGS" 69 | for ac_arg dnl 70 | in "-warn all % -warn all" dnl Intel 71 | "-pedantic % -Wall" dnl GCC 72 | "-xstrconst % -v" dnl Solaris C 73 | "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix 74 | "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX 75 | "-ansi -ansiE % -fullwarn" dnl IRIX 76 | "+ESlit % +w1" dnl HP-UX C 77 | "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10) 78 | "-h conform % -h msglevel 2" dnl Cray C (Unicos) 79 | # 80 | do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` 81 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM], 82 | [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) 83 | done 84 | FLAGS="$ac_save_[]FLAGS" 85 | ]) 86 | AS_VAR_POPDEF([FLAGS])dnl 87 | AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) 88 | case ".$VAR" in 89 | .ok|.ok,*) m4_ifvaln($3,$3) ;; 90 | .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;; 91 | *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;; 92 | esac 93 | AS_VAR_POPDEF([VAR])dnl 94 | ])dnl AX_FLAGS_WARN_ALL 95 | dnl implementation tactics: 96 | dnl the for-argument contains a list of options. The first part of 97 | dnl these does only exist to detect the compiler - usually it is 98 | dnl a global option to enable -ansi or -extrawarnings. All other 99 | dnl compilers will fail about it. That was needed since a lot of 100 | dnl compilers will give false positives for some option-syntax 101 | dnl like -Woption or -Xoption as they think of it is a pass-through 102 | dnl to later compile stages or something. The "%" is used as a 103 | dnl delimiter. A non-option comment can be given after "%%" marks 104 | dnl which will be shown but not added to the respective C/CXXFLAGS. 105 | 106 | AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl 107 | AC_LANG_PUSH([C]) 108 | AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) 109 | AC_LANG_POP([C]) 110 | ]) 111 | 112 | AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl 113 | AC_LANG_PUSH([C++]) 114 | AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) 115 | AC_LANG_POP([C++]) 116 | ]) 117 | 118 | AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl 119 | AC_LANG_PUSH([Fortran]) 120 | AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) 121 | AC_LANG_POP([Fortran]) 122 | ]) 123 | -------------------------------------------------------------------------------- /m4/ax_check_bash_completion.m4: -------------------------------------------------------------------------------- 1 | # SYNOPSIS 2 | # 3 | # AX_CHECK_BASH_COMPLETION() 4 | # 5 | # DESCRIPTION 6 | # 7 | # Checks for the presence of an --with-bash-completion-dir option to set a 8 | # custom path to bash completions. If no specified, it will use the default 9 | # path as long as bash-completion is available. 10 | # 11 | 12 | #serial 1 13 | 14 | AC_DEFUN([AX_CHECK_BASH_COMPLETION], [ 15 | AC_ARG_WITH([bash-completion-dir], 16 | AS_HELP_STRING([--with-bash-completion-dir[=PATH]], 17 | [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), 18 | [], 19 | [with_bash_completion_dir=yes]) 20 | 21 | # Check bash-completion 22 | if test "x$with_bash_completion_dir" = "xyes"; then 23 | PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], [ 24 | BASH_COMPLETION_DIR="$datadir/bash-completion/completions" 25 | ], [ 26 | BASH_COMPLETION_DIR="" 27 | ]) 28 | else 29 | BASH_COMPLETION_DIR="$with_bash_completion_dir" 30 | fi 31 | AC_SUBST([BASH_COMPLETION_DIR]) 32 | AM_CONDITIONAL([ENABLE_BASH_COMPLETION], [test "x$with_bash_completion_dir" != "xno" && test "$BASH_COMPLETION_DIR" != ""]) 33 | ]) 34 | 35 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # This program is free software: you can redistribute it and/or modify it 33 | # under the terms of the GNU General Public License as published by the 34 | # Free Software Foundation, either version 3 of the License, or (at your 35 | # option) any later version. 36 | # 37 | # This program is distributed in the hope that it will be useful, but 38 | # WITHOUT ANY WARRANTY; without even the implied warranty of 39 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 40 | # Public License for more details. 41 | # 42 | # You should have received a copy of the GNU General Public License along 43 | # with this program. If not, see . 44 | # 45 | # As a special exception, the respective Autoconf Macro's copyright owner 46 | # gives unlimited permission to copy, distribute and modify the configure 47 | # scripts that are the output of Autoconf when processing the Macro. You 48 | # need not follow the terms of the GNU General Public License when using 49 | # or distributing such scripts, even though portions of the text of the 50 | # Macro appear in them. The GNU General Public License (GPL) does govern 51 | # all other use of the material that constitutes the Autoconf Macro. 52 | # 53 | # This special exception to the GPL applies to versions of the Autoconf 54 | # Macro released by the Autoconf Archive. When you make and distribute a 55 | # modified version of the Autoconf Macro, you may extend this special 56 | # exception to the GPL to apply to your modified version as well. 57 | 58 | #serial 4 59 | 60 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 61 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 62 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 63 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 64 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 65 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 66 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 67 | [AS_VAR_SET(CACHEVAR,[yes])], 68 | [AS_VAR_SET(CACHEVAR,[no])]) 69 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 70 | AS_VAR_IF(CACHEVAR,yes, 71 | [m4_default([$2], :)], 72 | [m4_default([$3], :)]) 73 | AS_VAR_POPDEF([CACHEVAR])dnl 74 | ])dnl AX_CHECK_COMPILE_FLAGS 75 | -------------------------------------------------------------------------------- /m4/ax_check_enable_debug.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_enable_debug.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_ENABLE_DEBUG([enable by default=yes/info/profile/no], [ENABLE DEBUG VARIABLES ...], [DISABLE DEBUG VARIABLES NDEBUG ...], [IS-RELEASE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for the presence of an --enable-debug option to configure, with 12 | # the specified default value used when the option is not present. Return 13 | # the value in the variable $ax_enable_debug. 14 | # 15 | # Specifying 'yes' adds '-g -O0' to the compilation flags for all 16 | # languages. Specifying 'info' adds '-g' to the compilation flags. 17 | # Specifying 'profile' adds '-g -pg' to the compilation flags and '-pg' to 18 | # the linking flags. Otherwise, nothing is added. 19 | # 20 | # Define the variables listed in the second argument if debug is enabled, 21 | # defaulting to no variables. Defines the variables listed in the third 22 | # argument if debug is disabled, defaulting to NDEBUG. All lists of 23 | # variables should be space-separated. 24 | # 25 | # If debug is not enabled, ensure AC_PROG_* will not add debugging flags. 26 | # Should be invoked prior to any AC_PROG_* compiler checks. 27 | # 28 | # IS-RELEASE can be used to change the default to 'no' when making a 29 | # release. Set IS-RELEASE to 'yes' or 'no' as appropriate. By default, it 30 | # uses the value of $ax_is_release, so if you are using the AX_IS_RELEASE 31 | # macro, there is no need to pass this parameter. 32 | # 33 | # AX_IS_RELEASE([git-directory]) 34 | # AX_CHECK_ENABLE_DEBUG() 35 | # 36 | # LICENSE 37 | # 38 | # Copyright (c) 2011 Rhys Ulerich 39 | # Copyright (c) 2014, 2015 Philip Withnall 40 | # 41 | # Copying and distribution of this file, with or without modification, are 42 | # permitted in any medium without royalty provided the copyright notice 43 | # and this notice are preserved. 44 | 45 | #serial 5 46 | 47 | AC_DEFUN([AX_CHECK_ENABLE_DEBUG],[ 48 | AC_BEFORE([$0],[AC_PROG_CC])dnl 49 | AC_BEFORE([$0],[AC_PROG_CXX])dnl 50 | AC_BEFORE([$0],[AC_PROG_F77])dnl 51 | AC_BEFORE([$0],[AC_PROG_FC])dnl 52 | 53 | AC_MSG_CHECKING(whether to enable debugging) 54 | 55 | ax_enable_debug_default=m4_tolower(m4_normalize(ifelse([$1],,[no],[$1]))) 56 | ax_enable_debug_is_release=m4_tolower(m4_normalize(ifelse([$4],, 57 | [$ax_is_release], 58 | [$4]))) 59 | 60 | # If this is a release, override the default. 61 | AS_IF([test "$ax_enable_debug_is_release" = "yes"], 62 | [ax_enable_debug_default="no"]) 63 | 64 | m4_define(ax_enable_debug_vars,[m4_normalize(ifelse([$2],,,[$2]))]) 65 | m4_define(ax_disable_debug_vars,[m4_normalize(ifelse([$3],,[NDEBUG],[$3]))]) 66 | 67 | AC_ARG_ENABLE(debug, 68 | [AS_HELP_STRING([--enable-debug=]@<:@yes/info/profile/no@:>@,[compile with debugging])], 69 | [],enable_debug=$ax_enable_debug_default) 70 | 71 | # empty mean debug yes 72 | AS_IF([test "x$enable_debug" = "x"], 73 | [enable_debug="yes"]) 74 | 75 | # case of debug 76 | AS_CASE([$enable_debug], 77 | [yes],[ 78 | AC_MSG_RESULT(yes) 79 | CFLAGS="${CFLAGS} -g -O0" 80 | CXXFLAGS="${CXXFLAGS} -g -O0" 81 | FFLAGS="${FFLAGS} -g -O0" 82 | FCFLAGS="${FCFLAGS} -g -O0" 83 | OBJCFLAGS="${OBJCFLAGS} -g -O0" 84 | ], 85 | [info],[ 86 | AC_MSG_RESULT(info) 87 | CFLAGS="${CFLAGS} -g" 88 | CXXFLAGS="${CXXFLAGS} -g" 89 | FFLAGS="${FFLAGS} -g" 90 | FCFLAGS="${FCFLAGS} -g" 91 | OBJCFLAGS="${OBJCFLAGS} -g" 92 | ], 93 | [profile],[ 94 | AC_MSG_RESULT(profile) 95 | CFLAGS="${CFLAGS} -g -pg" 96 | CXXFLAGS="${CXXFLAGS} -g -pg" 97 | FFLAGS="${FFLAGS} -g -pg" 98 | FCFLAGS="${FCFLAGS} -g -pg" 99 | OBJCFLAGS="${OBJCFLAGS} -g -pg" 100 | LDFLAGS="${LDFLAGS} -pg" 101 | ], 102 | [ 103 | AC_MSG_RESULT(no) 104 | dnl Ensure AC_PROG_CC/CXX/F77/FC/OBJC will not enable debug flags 105 | dnl by setting any unset environment flag variables 106 | AS_IF([test "x${CFLAGS+set}" != "xset"], 107 | [CFLAGS=""]) 108 | AS_IF([test "x${CXXFLAGS+set}" != "xset"], 109 | [CXXFLAGS=""]) 110 | AS_IF([test "x${FFLAGS+set}" != "xset"], 111 | [FFLAGS=""]) 112 | AS_IF([test "x${FCFLAGS+set}" != "xset"], 113 | [FCFLAGS=""]) 114 | AS_IF([test "x${OBJCFLAGS+set}" != "xset"], 115 | [OBJCFLAGS=""]) 116 | ]) 117 | 118 | dnl Define various variables if debugging is disabled. 119 | dnl assert.h is a NOP if NDEBUG is defined, so define it by default. 120 | AS_IF([test "x$enable_debug" = "xyes"], 121 | [m4_map_args_w(ax_enable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is enabled])])], 122 | [m4_map_args_w(ax_disable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is disabled])])]) 123 | ax_enable_debug=$enable_debug 124 | ]) 125 | -------------------------------------------------------------------------------- /m4/ax_check_gnu_make.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_gnu_make.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_GNU_MAKE() 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro searches for a GNU version of make. If a match is found: 12 | # 13 | # * The makefile variable `ifGNUmake' is set to the empty string, otherwise 14 | # it is set to "#". This is useful for including a special features in a 15 | # Makefile, which cannot be handled by other versions of make. 16 | # * The variable `_cv_gnu_make_command` is set to the command to invoke 17 | # GNU make if it exists, the empty string otherwise. 18 | # * The variable `ax_cv_gnu_make_command` is set to the command to invoke 19 | # GNU make by copying `_cv_gnu_make_command`, otherwise it is unset. 20 | # * If GNU Make is found, its version is extracted from the output of 21 | # `make --version` as the last field of a record of space-separated 22 | # columns and saved into the variable `ax_check_gnu_make_version`. 23 | # 24 | # Here is an example of its use: 25 | # 26 | # Makefile.in might contain: 27 | # 28 | # # A failsafe way of putting a dependency rule into a makefile 29 | # $(DEPEND): 30 | # $(CC) -MM $(srcdir)/*.c > $(DEPEND) 31 | # 32 | # @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND))) 33 | # @ifGNUmake@ include $(DEPEND) 34 | # @ifGNUmake@ endif 35 | # 36 | # Then configure.in would normally contain: 37 | # 38 | # AX_CHECK_GNU_MAKE() 39 | # AC_OUTPUT(Makefile) 40 | # 41 | # Then perhaps to cause gnu make to override any other make, we could do 42 | # something like this (note that GNU make always looks for GNUmakefile 43 | # first): 44 | # 45 | # if ! test x$_cv_gnu_make_command = x ; then 46 | # mv Makefile GNUmakefile 47 | # echo .DEFAULT: > Makefile ; 48 | # echo \ $_cv_gnu_make_command \$@ >> Makefile; 49 | # fi 50 | # 51 | # Then, if any (well almost any) other make is called, and GNU make also 52 | # exists, then the other make wraps the GNU make. 53 | # 54 | # LICENSE 55 | # 56 | # Copyright (c) 2008 John Darrington 57 | # Copyright (c) 2015 Enrico M. Crisostomo 58 | # 59 | # Copying and distribution of this file, with or without modification, are 60 | # permitted in any medium without royalty provided the copyright notice 61 | # and this notice are preserved. This file is offered as-is, without any 62 | # warranty. 63 | 64 | #serial 8 65 | 66 | AC_DEFUN([AX_CHECK_GNU_MAKE],dnl 67 | [AC_PROG_AWK 68 | AC_CACHE_CHECK([for GNU make],[_cv_gnu_make_command],[dnl 69 | _cv_gnu_make_command="" ; 70 | dnl Search all the common names for GNU make 71 | for a in "$MAKE" make gmake gnumake ; do 72 | if test -z "$a" ; then continue ; fi ; 73 | if "$a" --version 2> /dev/null | grep GNU 2>&1 > /dev/null ; then 74 | _cv_gnu_make_command=$a ; 75 | AX_CHECK_GNU_MAKE_HEADLINE=$("$a" --version 2> /dev/null | grep "GNU Make") 76 | ax_check_gnu_make_version=$(echo ${AX_CHECK_GNU_MAKE_HEADLINE} | ${AWK} -F " " '{ print $(NF); }') 77 | break ; 78 | fi 79 | done ;]) 80 | dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise 81 | AS_VAR_IF([_cv_gnu_make_command], [""], [AS_VAR_SET([ifGNUmake], ["#"])], [AS_VAR_SET([ifGNUmake], [""])]) 82 | AS_VAR_IF([_cv_gnu_make_command], [""], [AS_UNSET(ax_cv_gnu_make_command)], [AS_VAR_SET([ax_cv_gnu_make_command], [${_cv_gnu_make_command}])]) 83 | AC_SUBST([ifGNUmake]) 84 | ]) 85 | -------------------------------------------------------------------------------- /m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_LINK_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # This program is free software: you can redistribute it and/or modify it 33 | # under the terms of the GNU General Public License as published by the 34 | # Free Software Foundation, either version 3 of the License, or (at your 35 | # option) any later version. 36 | # 37 | # This program is distributed in the hope that it will be useful, but 38 | # WITHOUT ANY WARRANTY; without even the implied warranty of 39 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 40 | # Public License for more details. 41 | # 42 | # You should have received a copy of the GNU General Public License along 43 | # with this program. If not, see . 44 | # 45 | # As a special exception, the respective Autoconf Macro's copyright owner 46 | # gives unlimited permission to copy, distribute and modify the configure 47 | # scripts that are the output of Autoconf when processing the Macro. You 48 | # need not follow the terms of the GNU General Public License when using 49 | # or distributing such scripts, even though portions of the text of the 50 | # Macro appear in them. The GNU General Public License (GPL) does govern 51 | # all other use of the material that constitutes the Autoconf Macro. 52 | # 53 | # This special exception to the GPL applies to versions of the Autoconf 54 | # Macro released by the Autoconf Archive. When you make and distribute a 55 | # modified version of the Autoconf Macro, you may extend this special 56 | # exception to the GPL to apply to your modified version as well. 57 | 58 | #serial 4 59 | 60 | AC_DEFUN([AX_CHECK_LINK_FLAG], 61 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 62 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 63 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 64 | ax_check_save_flags=$LDFLAGS 65 | LDFLAGS="$LDFLAGS $4 $1" 66 | AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 67 | [AS_VAR_SET(CACHEVAR,[yes])], 68 | [AS_VAR_SET(CACHEVAR,[no])]) 69 | LDFLAGS=$ax_check_save_flags]) 70 | AS_VAR_IF(CACHEVAR,yes, 71 | [m4_default([$2], :)], 72 | [m4_default([$3], :)]) 73 | AS_VAR_POPDEF([CACHEVAR])dnl 74 | ])dnl AX_CHECK_LINK_FLAGS 75 | -------------------------------------------------------------------------------- /m4/ax_check_zsh_completion.m4: -------------------------------------------------------------------------------- 1 | # SYNOPSIS 2 | # 3 | # AX_CHECK_ZSH_COMPLETION() 4 | # 5 | # DESCRIPTION 6 | # 7 | # Checks for the presence of an --with-zsh-completion-dir option to set a 8 | # custom path to zsh completions. If no specified, it will use the default 9 | # path as long as zsh is available. 10 | # 11 | 12 | #serial 1 13 | 14 | AC_DEFUN([AX_CHECK_ZSH_COMPLETION], [ 15 | AC_ARG_WITH([zsh-completion-dir], 16 | AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], 17 | [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), 18 | [], 19 | [with_zsh_completion_dir=yes]) 20 | 21 | # Check zsh-completion 22 | if test "x$with_zsh_completion_dir" = "xyes"; then 23 | AC_ARG_VAR([ZSH_AVAILABLE], []) 24 | AC_CHECK_PROG([ZSH_AVAILABLE], [zsh], [yes], [no]) 25 | 26 | AS_IF([test "$ZSH_AVAILABLE" = "yes"], [ 27 | ZSH_COMPLETION_DIR="$datadir/zsh/vendor-completions" 28 | ], [ 29 | ZSH_COMPLETION_DIR="" 30 | ]) 31 | else 32 | ZSH_COMPLETION_DIR="$with_zsh_completion_dir" 33 | fi 34 | AC_SUBST([ZSH_COMPLETION_DIR]) 35 | AM_CONDITIONAL([ENABLE_ZSH_COMPLETION], [test "x$with_zsh_completion_dir" != "xno" && test "$ZSH_COMPLETION_DIR" != ""]) 36 | ]) 37 | 38 | -------------------------------------------------------------------------------- /m4/ax_code_coverage.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CODE_COVERAGE() 8 | # 9 | # DESCRIPTION 10 | # 11 | # Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS, 12 | # CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LDFLAGS which should be 13 | # included in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LDFLAGS variables of 14 | # every build target (program or library) which should be built with code 15 | # coverage support. Also defines CODE_COVERAGE_RULES which should be 16 | # substituted in your Makefile; and $enable_code_coverage which can be 17 | # used in subsequent configure output. CODE_COVERAGE_ENABLED is defined 18 | # and substituted, and corresponds to the value of the 19 | # --enable-code-coverage option, which defaults to being disabled. 20 | # 21 | # Test also for gcov program and create GCOV variable that could be 22 | # substituted. 23 | # 24 | # Note that all optimisation flags in CFLAGS must be disabled when code 25 | # coverage is enabled. 26 | # 27 | # Usage example: 28 | # 29 | # configure.ac: 30 | # 31 | # AX_CODE_COVERAGE 32 | # 33 | # Makefile.am: 34 | # 35 | # @CODE_COVERAGE_RULES@ 36 | # my_program_LIBS = ... $(CODE_COVERAGE_LDFLAGS) ... 37 | # my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ... 38 | # my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ... 39 | # my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ... 40 | # 41 | # This results in a "check-code-coverage" rule being added to any 42 | # Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module 43 | # has been configured with --enable-code-coverage). Running `make 44 | # check-code-coverage` in that directory will run the module's test suite 45 | # (`make check`) and build a code coverage report detailing the code which 46 | # was touched, then print the URI for the report. 47 | # 48 | # This code was derived from Makefile.decl in GLib, originally licenced 49 | # under LGPLv2.1+. 50 | # 51 | # LICENSE 52 | # 53 | # Copyright (c) 2012, 2016 Philip Withnall 54 | # Copyright (c) 2012 Xan Lopez 55 | # Copyright (c) 2012 Christian Persch 56 | # Copyright (c) 2012 Paolo Borelli 57 | # Copyright (c) 2012 Dan Winship 58 | # Copyright (c) 2015 Bastien ROUCARIES 59 | # 60 | # This library is free software; you can redistribute it and/or modify it 61 | # under the terms of the GNU Lesser General Public License as published by 62 | # the Free Software Foundation; either version 2.1 of the License, or (at 63 | # your option) any later version. 64 | # 65 | # This library is distributed in the hope that it will be useful, but 66 | # WITHOUT ANY WARRANTY; without even the implied warranty of 67 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 68 | # General Public License for more details. 69 | # 70 | # You should have received a copy of the GNU Lesser General Public License 71 | # along with this program. If not, see . 72 | 73 | #serial 15 74 | 75 | AC_DEFUN([AX_CODE_COVERAGE],[ 76 | dnl Check for --enable-code-coverage 77 | AC_REQUIRE([AC_PROG_SED]) 78 | 79 | # allow to override gcov location 80 | AC_ARG_WITH([gcov], 81 | [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], 82 | [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], 83 | [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) 84 | 85 | AC_MSG_CHECKING([whether to build with code coverage support]) 86 | AC_ARG_ENABLE([code-coverage], 87 | AS_HELP_STRING([--enable-code-coverage], 88 | [Whether to enable code coverage support]),, 89 | enable_code_coverage=no) 90 | 91 | AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes]) 92 | AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) 93 | AC_MSG_RESULT($enable_code_coverage) 94 | 95 | AS_IF([ test "$enable_code_coverage" = "yes" ], [ 96 | # check for gcov 97 | AC_CHECK_TOOL([GCOV], 98 | [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], 99 | [:]) 100 | AS_IF([test "X$GCOV" = "X:"], 101 | [AC_MSG_ERROR([gcov is needed to do coverage])]) 102 | AC_SUBST([GCOV]) 103 | 104 | dnl Check if gcc is being used 105 | AS_IF([ test "$GCC" = "no" ], [ 106 | AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) 107 | ]) 108 | 109 | # List of supported lcov versions. 110 | lcov_version_list="1.6 1.7 1.8 1.9 1.10 1.11 1.12" 111 | 112 | AC_CHECK_PROG([LCOV], [lcov], [lcov]) 113 | AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) 114 | 115 | AS_IF([ test "$LCOV" ], [ 116 | AC_CACHE_CHECK([for lcov version], ax_cv_lcov_version, [ 117 | ax_cv_lcov_version=invalid 118 | lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` 119 | for lcov_check_version in $lcov_version_list; do 120 | if test "$lcov_version" = "$lcov_check_version"; then 121 | ax_cv_lcov_version="$lcov_check_version (ok)" 122 | fi 123 | done 124 | ]) 125 | ], [ 126 | lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" 127 | AC_MSG_ERROR([$lcov_msg]) 128 | ]) 129 | 130 | case $ax_cv_lcov_version in 131 | ""|invalid[)] 132 | lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." 133 | AC_MSG_ERROR([$lcov_msg]) 134 | LCOV="exit 0;" 135 | ;; 136 | esac 137 | 138 | AS_IF([ test -z "$GENHTML" ], [ 139 | AC_MSG_ERROR([Could not find genhtml from the lcov package]) 140 | ]) 141 | 142 | dnl Build the code coverage flags 143 | CODE_COVERAGE_CPPFLAGS="-DNDEBUG" 144 | CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" 145 | CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" 146 | CODE_COVERAGE_LDFLAGS="-lgcov" 147 | 148 | AC_SUBST([CODE_COVERAGE_CPPFLAGS]) 149 | AC_SUBST([CODE_COVERAGE_CFLAGS]) 150 | AC_SUBST([CODE_COVERAGE_CXXFLAGS]) 151 | AC_SUBST([CODE_COVERAGE_LDFLAGS]) 152 | ]) 153 | 154 | [CODE_COVERAGE_RULES=' 155 | # Code coverage 156 | # 157 | # Optional: 158 | # - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. 159 | # Multiple directories may be specified, separated by whitespace. 160 | # (Default: $(top_builddir)) 161 | # - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated 162 | # by lcov for code coverage. (Default: 163 | # $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) 164 | # - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage 165 | # reports to be created. (Default: 166 | # $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) 167 | # - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, 168 | # set to 0 to disable it and leave empty to stay with the default. 169 | # (Default: empty) 170 | # - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov 171 | # instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) 172 | # - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov 173 | # instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) 174 | # - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov 175 | # - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the 176 | # collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) 177 | # - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov 178 | # instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) 179 | # - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering 180 | # lcov instance. (Default: empty) 181 | # - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov 182 | # instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) 183 | # - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the 184 | # genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) 185 | # - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml 186 | # instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) 187 | # - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore 188 | # 189 | # The generated report will be titled using the $(PACKAGE_NAME) and 190 | # $(PACKAGE_VERSION). In order to add the current git hash to the title, 191 | # use the git-version-gen script, available online. 192 | 193 | # Optional variables 194 | CODE_COVERAGE_DIRECTORY ?= $(top_builddir) 195 | CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info 196 | CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage 197 | CODE_COVERAGE_BRANCH_COVERAGE ?= 198 | CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ 199 | --rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) 200 | CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) 201 | CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" 202 | CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) 203 | CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) 204 | CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= 205 | CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) 206 | CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ 207 | $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\ 208 | --rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) 209 | CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS) 210 | CODE_COVERAGE_IGNORE_PATTERN ?= 211 | 212 | code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) 213 | code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) 214 | code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\ 215 | $(CODE_COVERAGE_OUTPUT_FILE); 216 | code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) 217 | code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) 218 | code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\ 219 | $(CODE_COVERAGE_IGNORE_PATTERN); 220 | code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) 221 | code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) 222 | code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY); 223 | code_coverage_quiet = $(code_coverage_quiet_$(V)) 224 | code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) 225 | code_coverage_quiet_0 = --quiet 226 | 227 | # sanitizes the test-name: replaces with underscores: dashes and dots 228 | code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) 229 | 230 | # Use recursive makes in order to ignore errors during check 231 | check-code-coverage: 232 | ifeq ($(CODE_COVERAGE_ENABLED),yes) 233 | -$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check 234 | $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture 235 | else 236 | @echo "Need to reconfigure with --enable-code-coverage" 237 | endif 238 | 239 | # Capture code coverage data 240 | code-coverage-capture: code-coverage-capture-hook 241 | ifeq ($(CODE_COVERAGE_ENABLED),yes) 242 | $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) 243 | $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) 244 | -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp 245 | $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) 246 | @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" 247 | else 248 | @echo "Need to reconfigure with --enable-code-coverage" 249 | endif 250 | 251 | # Hook rule executed before code-coverage-capture, overridable by the user 252 | code-coverage-capture-hook: 253 | 254 | ifeq ($(CODE_COVERAGE_ENABLED),yes) 255 | clean: code-coverage-clean 256 | code-coverage-clean: 257 | -$(LCOV) --directory $(top_builddir) -z 258 | -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY) 259 | -find . -name "*.gcda" -o -name "*.gcov" -delete 260 | endif 261 | 262 | GITIGNOREFILES ?= 263 | GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) 264 | 265 | A''M_DISTCHECK_CONFIGURE_FLAGS ?= 266 | A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage 267 | 268 | .PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean 269 | '] 270 | 271 | AC_SUBST([CODE_COVERAGE_RULES]) 272 | m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])]) 273 | ]) 274 | -------------------------------------------------------------------------------- /m4/ax_configure_args.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_configure_args.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CONFIGURE_ARGS 8 | # 9 | # DESCRIPTION 10 | # 11 | # Helper macro for AX_ENABLE_BUILDDIR. 12 | # 13 | # The traditional way of starting a subdir-configure is running the script 14 | # with ${1+"$@"} but since autoconf 2.60 this is broken. Instead we have 15 | # to rely on eval'ing $ac_configure_args however some old autoconf 16 | # versions do not provide that. To ensure maximum portability of autoconf 17 | # extension macros this helper can be AC_REQUIRE'd so that 18 | # $ac_configure_args will alsways be present. 19 | # 20 | # Sadly, the traditional "exec $SHELL" of the enable_builddir macros is 21 | # spoiled now and must be replaced by "eval + exit $?". 22 | # 23 | # Example: 24 | # 25 | # AC_DEFUN([AX_ENABLE_SUBDIR],[dnl 26 | # AC_REQUIRE([AX_CONFIGURE_ARGS])dnl 27 | # eval $SHELL $ac_configure_args || exit $? 28 | # ...]) 29 | # 30 | # LICENSE 31 | # 32 | # Copyright (c) 2008 Guido U. Draheim 33 | # 34 | # This program is free software; you can redistribute it and/or modify it 35 | # under the terms of the GNU General Public License as published by the 36 | # Free Software Foundation; either version 3 of the License, or (at your 37 | # option) any later version. 38 | # 39 | # This program is distributed in the hope that it will be useful, but 40 | # WITHOUT ANY WARRANTY; without even the implied warranty of 41 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 42 | # Public License for more details. 43 | # 44 | # You should have received a copy of the GNU General Public License along 45 | # with this program. If not, see . 46 | # 47 | # As a special exception, the respective Autoconf Macro's copyright owner 48 | # gives unlimited permission to copy, distribute and modify the configure 49 | # scripts that are the output of Autoconf when processing the Macro. You 50 | # need not follow the terms of the GNU General Public License when using 51 | # or distributing such scripts, even though portions of the text of the 52 | # Macro appear in them. The GNU General Public License (GPL) does govern 53 | # all other use of the material that constitutes the Autoconf Macro. 54 | # 55 | # This special exception to the GPL applies to versions of the Autoconf 56 | # Macro released by the Autoconf Archive. When you make and distribute a 57 | # modified version of the Autoconf Macro, you may extend this special 58 | # exception to the GPL to apply to your modified version as well. 59 | 60 | #serial 9 61 | 62 | AC_DEFUN([AX_CONFIGURE_ARGS],[ 63 | # [$]@ is unsable in 2.60+ but earlier autoconf had no ac_configure_args 64 | if test "${ac_configure_args+set}" != "set" ; then 65 | ac_configure_args= 66 | for ac_arg in ${1+"[$]@"}; do 67 | ac_configure_args="$ac_configure_args '$ac_arg'" 68 | done 69 | fi 70 | ]) 71 | -------------------------------------------------------------------------------- /m4/ax_enable_builddir.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_enable_builddir.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_ENABLE_BUILDDIR [(dirstring-or-command [,Makefile.mk [,-all]])] 8 | # 9 | # DESCRIPTION 10 | # 11 | # If the current configure was run within the srcdir then we move all 12 | # configure-files into a subdir and let the configure steps continue 13 | # there. We provide an option --disable-builddir to suppress the move into 14 | # a separate builddir. 15 | # 16 | # Defaults: 17 | # 18 | # $1 = $host (overridden with $HOST) 19 | # $2 = Makefile.mk 20 | # $3 = -all 21 | # 22 | # This macro must be called before AM_INIT_AUTOMAKE. It creates a default 23 | # toplevel srcdir Makefile from the information found in the created 24 | # toplevel builddir Makefile. It just copies the variables and 25 | # rule-targets, each extended with a default rule-execution that recurses 26 | # into the build directory of the current "HOST". You can override the 27 | # auto-dection through `config.guess` and build-time of course, as in 28 | # 29 | # make HOST=i386-mingw-cross 30 | # 31 | # which can of course set at configure time as well using 32 | # 33 | # configure --host=i386-mingw-cross 34 | # 35 | # After the default has been created, additional rules can be appended 36 | # that will not just recurse into the subdirectories and only ever exist 37 | # in the srcdir toplevel makefile - these parts are read from the $2 = 38 | # Makefile.mk file 39 | # 40 | # The automatic rules are usually scanning the toplevel Makefile for lines 41 | # like '#### $host |$builddir' to recognize the place where to recurse 42 | # into. Usually, the last one is the only one used. However, almost all 43 | # targets have an additional "*-all" rule which makes the script to 44 | # recurse into _all_ variants of the current HOST (!!) setting. The "-all" 45 | # suffix can be overriden for the macro as well. 46 | # 47 | # a special rule is only given for things like "dist" that will copy the 48 | # tarball from the builddir to the sourcedir (or $(PUB)) for reason of 49 | # convenience. 50 | # 51 | # LICENSE 52 | # 53 | # Copyright (c) 2009 Guido U. Draheim 54 | # Copyright (c) 2009 Alan Jenkins 55 | # 56 | # This program is free software; you can redistribute it and/or modify it 57 | # under the terms of the GNU General Public License as published by the 58 | # Free Software Foundation; either version 3 of the License, or (at your 59 | # option) any later version. 60 | # 61 | # This program is distributed in the hope that it will be useful, but 62 | # WITHOUT ANY WARRANTY; without even the implied warranty of 63 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 64 | # Public License for more details. 65 | # 66 | # You should have received a copy of the GNU General Public License along 67 | # with this program. If not, see . 68 | # 69 | # As a special exception, the respective Autoconf Macro's copyright owner 70 | # gives unlimited permission to copy, distribute and modify the configure 71 | # scripts that are the output of Autoconf when processing the Macro. You 72 | # need not follow the terms of the GNU General Public License when using 73 | # or distributing such scripts, even though portions of the text of the 74 | # Macro appear in them. The GNU General Public License (GPL) does govern 75 | # all other use of the material that constitutes the Autoconf Macro. 76 | # 77 | # This special exception to the GPL applies to versions of the Autoconf 78 | # Macro released by the Autoconf Archive. When you make and distribute a 79 | # modified version of the Autoconf Macro, you may extend this special 80 | # exception to the GPL to apply to your modified version as well. 81 | 82 | #serial 25 83 | 84 | AC_DEFUN([AX_ENABLE_BUILDDIR],[ 85 | AC_REQUIRE([AC_CANONICAL_HOST])[]dnl 86 | AC_REQUIRE([AC_CANONICAL_TARGET])[]dnl 87 | AC_REQUIRE([AX_CONFIGURE_ARGS])[]dnl 88 | AC_REQUIRE([AM_AUX_DIR_EXPAND])[]dnl 89 | AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl 90 | AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl 91 | AS_VAR_PUSHDEF([AUX],[ax_enable_builddir_auxdir])dnl 92 | AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl 93 | SUB="." 94 | AC_ARG_ENABLE([builddir], AS_HELP_STRING( 95 | [--disable-builddir],[disable automatic build in subdir of sources]) 96 | ,[SUB="$enableval"], [SUB="auto"]) 97 | if test ".$ac_srcdir_defaulted" != ".no" ; then 98 | if test ".$srcdir" = ".." ; then 99 | if test -f config.status ; then 100 | AC_MSG_NOTICE(toplevel srcdir already configured... skipping subdir build) 101 | else 102 | test ".$SUB" = "." && SUB="." 103 | test ".$SUB" = ".no" && SUB="." 104 | test ".$TARGET" = "." && TARGET="$target" 105 | test ".$SUB" = ".auto" && SUB="m4_ifval([$1], [$1],[$TARGET])" 106 | if test ".$SUB" != ".." ; then # we know where to go and 107 | AS_MKDIR_P([$SUB]) 108 | echo __.$SUB.__ > $SUB/conftest.tmp 109 | cd $SUB 110 | if grep __.$SUB.__ conftest.tmp >/dev/null 2>/dev/null ; then 111 | rm conftest.tmp 112 | AC_MSG_RESULT([continue configure in default builddir "./$SUB"]) 113 | else 114 | AC_MSG_ERROR([could not change to default builddir "./$SUB"]) 115 | fi 116 | srcdir=`echo "$SUB" | 117 | sed -e 's,^\./,,;s,[[^/]]$,&/,;s,[[^/]]*/,../,g;s,[[/]]$,,;'` 118 | # going to restart from subdirectory location 119 | test -f $srcdir/config.log && mv $srcdir/config.log . 120 | test -f $srcdir/confdefs.h && mv $srcdir/confdefs.h . 121 | test -f $srcdir/conftest.log && mv $srcdir/conftest.log . 122 | test -f $srcdir/$cache_file && mv $srcdir/$cache_file . 123 | AC_MSG_RESULT(....exec $SHELL $srcdir/[$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"}) 124 | case "[$]0" in # restart 125 | [[\\/]]* | ?:[[\\/]]*) # Asbolute name 126 | eval $SHELL "'[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;; 127 | *) eval $SHELL "'$srcdir/[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;; 128 | esac ; exit $? 129 | fi 130 | fi 131 | fi fi 132 | test ".$SUB" = ".auto" && SUB="." 133 | dnl ac_path_prog uses "set dummy" to override $@ which would defeat the "exec" 134 | AC_PATH_PROG(SED,gsed sed, sed) 135 | AUX="$am_aux_dir" 136 | AS_VAR_POPDEF([SED])dnl 137 | AS_VAR_POPDEF([AUX])dnl 138 | AS_VAR_POPDEF([SUB])dnl 139 | AC_CONFIG_COMMANDS([buildir],[dnl .............. config.status .............. 140 | AS_VAR_PUSHDEF([SUB],[ax_enable_builddir])dnl 141 | AS_VAR_PUSHDEF([TOP],[top_srcdir])dnl 142 | AS_VAR_PUSHDEF([SRC],[ac_top_srcdir])dnl 143 | AS_VAR_PUSHDEF([AUX],[ax_enable_builddir_auxdir])dnl 144 | AS_VAR_PUSHDEF([SED],[ax_enable_builddir_sed])dnl 145 | pushdef([END],[Makefile.mk])dnl 146 | pushdef([_ALL],[ifelse([$3],,[-all],[$3])])dnl 147 | SRC="$ax_enable_builddir_srcdir" 148 | if test ".$SUB" = ".." ; then 149 | if test -f "$TOP/Makefile" ; then 150 | AC_MSG_NOTICE([skipping TOP/Makefile - left untouched]) 151 | else 152 | AC_MSG_NOTICE([skipping TOP/Makefile - not created]) 153 | fi 154 | else 155 | if test -f "$SRC/Makefile" ; then 156 | a=`grep "^VERSION " "$SRC/Makefile"` ; b=`grep "^VERSION " Makefile` 157 | test "$a" != "$b" && rm "$SRC/Makefile" 158 | fi 159 | if test -f "$SRC/Makefile" ; then 160 | echo "$SRC/Makefile : $SRC/Makefile.in" > $tmp/conftemp.mk 161 | echo " []@ echo 'REMOVED,,,' >\$[]@" >> $tmp/conftemp.mk 162 | eval "${MAKE-make} -f $tmp/conftemp.mk 2>/dev/null >/dev/null" 163 | if grep '^REMOVED,,,' "$SRC/Makefile" >/dev/null 164 | then rm $SRC/Makefile ; fi 165 | cp $tmp/conftemp.mk $SRC/makefiles.mk~ ## DEBUGGING 166 | fi 167 | if test ! -f "$SRC/Makefile" ; then 168 | AC_MSG_NOTICE([create TOP/Makefile guessed from local Makefile]) 169 | x='`' ; cat >$tmp/conftemp.sed <<_EOF 170 | /^\$/n 171 | x 172 | /^\$/bS 173 | x 174 | /\\\\\$/{H;d;} 175 | {H;s/.*//;x;} 176 | bM 177 | :S 178 | x 179 | /\\\\\$/{h;d;} 180 | {h;s/.*//;x;} 181 | :M 182 | s/\\(\\n\\) /\\1 /g 183 | /^ /d 184 | /^[[ ]]*[[\\#]]/d 185 | /^VPATH *=/d 186 | s/^srcdir *=.*/srcdir = ./ 187 | s/^top_srcdir *=.*/top_srcdir = ./ 188 | /[[:=]]/!d 189 | /^\\./d 190 | dnl Now handle rules (i.e. lines containing ":" but not " = "). 191 | / = /b 192 | / .= /b 193 | /:/!b 194 | s/:.*/:/ 195 | s/ / /g 196 | s/ \\([[a-z]][[a-z-]]*[[a-zA-Z0-9]]\\)\\([[ :]]\\)/ \\1 \\1[]_ALL\\2/g 197 | s/^\\([[a-z]][[a-z-]]*[[a-zA-Z0-9]]\\)\\([[ :]]\\)/\\1 \\1[]_ALL\\2/ 198 | s/ / /g 199 | /^all all[]_ALL[[ :]]/i\\ 200 | all-configured : all[]_ALL 201 | dnl dist-all exists... and would make for dist-all-all 202 | s/ [[a-zA-Z0-9-]]*[]_ALL [[a-zA-Z0-9-]]*[]_ALL[]_ALL//g 203 | /[]_ALL[]_ALL/d 204 | a\\ 205 | @ HOST="\$(HOST)\" \\\\\\ 206 | ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\ 207 | ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ 208 | ; use=$x basename "\$\@" _ALL $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\ 209 | ; echo "MAKE \$\$HOST : \$\$n * \$\@"; if test "\$\$n" -eq "0" ; then : \\\\\\ 210 | ; BUILD=$x grep "^####.*|" Makefile |tail -1| sed -e 's/.*|//' $x ; fi \\\\\\ 211 | ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\ 212 | ; test "\$\$use" = "\$\@" && BUILD=$x echo "\$\$BUILD" | tail -1 $x \\\\\\ 213 | ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ 214 | ; (cd "\$\$i" && test ! -f configure && \$(MAKE) \$\$use) || exit; done 215 | dnl special rule add-on: "dist" copies the tarball to $(PUB). (source tree) 216 | /dist[]_ALL *:/a\\ 217 | @ HOST="\$(HOST)\" \\\\\\ 218 | ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\ 219 | ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ 220 | ; found=$x echo \$\$BUILD | wc -w $x \\\\\\ 221 | ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).tar.*" \\\\\\ 222 | ; if test "\$\$found" -eq "0" ; then : \\\\\\ 223 | ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\ 224 | ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ 225 | ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).tar.* \\\\\\ 226 | ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done 227 | dnl special rule add-on: "dist-foo" copies all the archives to $(PUB). (source tree) 228 | /dist-[[a-zA-Z0-9]]*[]_ALL *:/a\\ 229 | @ HOST="\$(HOST)\" \\\\\\ 230 | ; test ".\$\$HOST" = "." && HOST=$x sh ./config.guess $x \\\\\\ 231 | ; BUILD=$x grep "^#### \$\$HOST " Makefile | sed -e 's/.*|//' $x \\\\\\ 232 | ; found=$x echo \$\$BUILD | wc -w $x \\\\\\ 233 | ; echo "MAKE \$\$HOST : \$\$found \$(PACKAGE)-\$(VERSION).*" \\\\\\ 234 | ; if test "\$\$found" -eq "0" ; then : \\\\\\ 235 | ; BUILD=$x grep "^#### .*|" Makefile |tail -1| sed -e 's/.*|//' $x \\\\\\ 236 | ; fi ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ 237 | ; for f in \$\$i/\$(PACKAGE)-\$(VERSION).* \\\\\\ 238 | ; do test -f "\$\$f" && mv "\$\$f" \$(PUB). ; done ; break ; done 239 | dnl special rule add-on: "distclean" removes all local builddirs completely 240 | /distclean[]_ALL *:/a\\ 241 | @ HOST="\$(HOST)\" \\\\\\ 242 | ; test ".\$\$HOST" = "." && HOST=$x sh $AUX/config.guess $x \\\\\\ 243 | ; BUILD=$x grep "^#### .*|" Makefile | sed -e 's/.*|//' $x \\\\\\ 244 | ; use=$x basename "\$\@" _ALL $x; n=$x echo \$\$BUILD | wc -w $x \\\\\\ 245 | ; echo "MAKE \$\$HOST : \$\$n * \$\@ (all local builds)" \\\\\\ 246 | ; test ".\$\$BUILD" = "." && BUILD="." \\\\\\ 247 | ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ 248 | ; echo "# rm -r \$\$i"; done ; echo "# (sleep 3)" ; sleep 3 \\\\\\ 249 | ; for i in \$\$BUILD ; do test ".\$\$i" = "." && continue \\\\\\ 250 | ; echo "\$\$i" | grep "^/" > /dev/null && continue \\\\\\ 251 | ; echo "\$\$i" | grep "^../" > /dev/null && continue \\\\\\ 252 | ; echo "rm -r \$\$i"; (rm -r "\$\$i") ; done ; rm Makefile 253 | _EOF 254 | cp "$tmp/conftemp.sed" "$SRC/makefile.sed~" ## DEBUGGING 255 | $SED -f $tmp/conftemp.sed Makefile >$SRC/Makefile 256 | if test -f "$SRC/m4_ifval([$2],[$2],[END])" ; then 257 | AC_MSG_NOTICE([extend TOP/Makefile with TOP/m4_ifval([$2],[$2],[END])]) 258 | cat $SRC/END >>$SRC/Makefile 259 | fi ; xxxx="####" 260 | echo "$xxxx CONFIGURATIONS FOR TOPLEVEL MAKEFILE: " >>$SRC/Makefile 261 | # sanity check 262 | if grep '^; echo "MAKE ' $SRC/Makefile >/dev/null ; then 263 | AC_MSG_NOTICE([buggy sed found - it deletes tab in "a" text parts]) 264 | $SED -e '/^@ HOST=/s/^/ /' -e '/^; /s/^/ /' $SRC/Makefile \ 265 | >$SRC/Makefile~ 266 | (test -s $SRC/Makefile~ && mv $SRC/Makefile~ $SRC/Makefile) 2>/dev/null 267 | fi 268 | else 269 | xxxx="\\#\\#\\#\\#" 270 | # echo "/^$xxxx *$ax_enable_builddir_host /d" >$tmp/conftemp.sed 271 | echo "s!^$xxxx [[^|]]* | *$SUB *\$!$xxxx ...... $SUB!" >$tmp/conftemp.sed 272 | $SED -f "$tmp/conftemp.sed" "$SRC/Makefile" >$tmp/mkfile.tmp 273 | cp "$tmp/conftemp.sed" "$SRC/makefiles.sed~" ## DEBUGGING 274 | cp "$tmp/mkfile.tmp" "$SRC/makefiles.out~" ## DEBUGGING 275 | if cmp -s "$SRC/Makefile" "$tmp/mkfile.tmp" 2>/dev/null ; then 276 | AC_MSG_NOTICE([keeping TOP/Makefile from earlier configure]) 277 | rm "$tmp/mkfile.tmp" 278 | else 279 | AC_MSG_NOTICE([reusing TOP/Makefile from earlier configure]) 280 | mv "$tmp/mkfile.tmp" "$SRC/Makefile" 281 | fi 282 | fi 283 | AC_MSG_NOTICE([build in $SUB (HOST=$ax_enable_builddir_host)]) 284 | xxxx="####" 285 | echo "$xxxx" "$ax_enable_builddir_host" "|$SUB" >>$SRC/Makefile 286 | fi 287 | popdef([END])dnl 288 | AS_VAR_POPDEF([SED])dnl 289 | AS_VAR_POPDEF([AUX])dnl 290 | AS_VAR_POPDEF([SRC])dnl 291 | AS_VAR_POPDEF([TOP])dnl 292 | AS_VAR_POPDEF([SUB])dnl 293 | ],[dnl 294 | ax_enable_builddir_srcdir="$srcdir" # $srcdir 295 | ax_enable_builddir_host="$HOST" # $HOST / $host 296 | ax_enable_builddir_version="$VERSION" # $VERSION 297 | ax_enable_builddir_package="$PACKAGE" # $PACKAGE 298 | ax_enable_builddir_auxdir="$ax_enable_builddir_auxdir" # $AUX 299 | ax_enable_builddir_sed="$ax_enable_builddir_sed" # $SED 300 | ax_enable_builddir="$ax_enable_builddir" # $SUB 301 | ])dnl 302 | ]) 303 | -------------------------------------------------------------------------------- /m4/ax_extend_srcdir.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_extend_srcdir.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_EXTEND_SRCDIR 8 | # 9 | # DESCRIPTION 10 | # 11 | # The AX_EXTEND_SRCDIR macro extends $srcdir by one path component. 12 | # 13 | # As an example, when working in /home/michael/i3-4.12/build and calling 14 | # ../configure, your $srcdir is "..". After calling AX_EXTEND_SRCDIR, 15 | # $srcdir will be set to "../../i3-4.12". 16 | # 17 | # The result of extending $srcdir is that filenames (e.g. in the output of 18 | # the "backtrace" gdb command) will include one more path component of the 19 | # absolute source path. The additional path component makes it easy for 20 | # users to recognize which files belong to the PACKAGE, and -- provided a 21 | # dist tarball was unpacked -- which version of PACKAGE was used. 22 | # 23 | # As an example, in "backtrace", you will see: 24 | # 25 | # #0 main (argc=1, argv=0x7fffffff1fc8) at ../../i3-4.12/src/main.c:187 26 | # 27 | # instead of: 28 | # 29 | # #0 main (argc=1, argv=0x7fffffff1fc8) at ../src/main.c:187 30 | # 31 | # In case your code uses the __FILE__ preprocessor directive to refer to 32 | # the filename of the current source file (e.g. in debug messages), using 33 | # the extended path might be undesirable. For this purpose, 34 | # AX_EXTEND_SRCDIR defines the output variable AX_EXTEND_SRCDIR_CPPFLAGS, 35 | # which can be added to AM_CPPFLAGS in Makefile.am in order to define the 36 | # preprocessor directive STRIPPED__FILE__. As an example, when compiling 37 | # the file "../../i3-4.12/src/main.c", STRIPPED__FILE__ evaluates to 38 | # "main.c". 39 | # 40 | # There are some caveats: When $srcdir is "." (i.e. when ./configure was 41 | # called instead of ../configure in a separate build directory), 42 | # AX_EXTEND_SRCDIR will still extend $srcdir, but the intended effect will 43 | # not be achieved because of the way automake specifies file paths: 44 | # automake defines COMPILE to use "`test -f '$source' || echo 45 | # '\$(srcdir)/'`$source" in order to prefer files in the current directory 46 | # over specifying $srcdir explicitly. 47 | # 48 | # The AX_EXTEND_SRCDIR author is not aware of any way to influence this 49 | # automake behavior. Patches very welcome. 50 | # 51 | # To work around this issue, you can use AX_ENABLE_BUILDDIR i.e. by adding 52 | # the following code to configure.ac: 53 | # 54 | # AX_ENABLE_BUILDDIR 55 | # dnl ... 56 | # AX_EXTEND_SRCDIR 57 | # 58 | # Then also add this bit to Makefile.am (if you wish to use 59 | # STRIPPED__FILE__ in your code): 60 | # 61 | # AM_CPPFLAGS = @AX_EXTEND_SRCDIR_CPPFLAGS@ 62 | # 63 | # LICENSE 64 | # 65 | # Copyright (c) 2016 Michael Stapelberg 66 | # Copyright (c) 2021 Raymond Li 67 | # 68 | # Copying and distribution of this file, with or without modification, are 69 | # permitted in any medium without royalty provided the copyright notice 70 | # and this notice are preserved. This file is offered as-is, without any 71 | # warranty. 72 | 73 | #serial 3 74 | 75 | AC_DEFUN([AX_EXTEND_SRCDIR], 76 | [dnl 77 | AS_CASE([$srcdir], 78 | [.|.*|/*], 79 | [ 80 | # pwd -P is specified in IEEE 1003.1 from 2004 81 | as_dir=`cd "$srcdir" && pwd -P` 82 | as_base=`AS_BASENAME([$as_dir])` 83 | srcdir=${srcdir}/../${as_base} 84 | 85 | AC_SUBST([AX_EXTEND_SRCDIR_CPPFLAGS], ["-DSTRIPPED__FILE__=AS_ESCAPE([\"$$(basename $<)\"])"]) 86 | ]) 87 | ])dnl AX_EXTEND_SRCDIR 88 | -------------------------------------------------------------------------------- /m4/ax_require_defined.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_require_defined.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_REQUIRE_DEFINED(MACRO) 8 | # 9 | # DESCRIPTION 10 | # 11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have 12 | # been defined and thus are available for use. This avoids random issues 13 | # where a macro isn't expanded. Instead the configure script emits a 14 | # non-fatal: 15 | # 16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found 17 | # 18 | # It's like AC_REQUIRE except it doesn't expand the required macro. 19 | # 20 | # Here's an example: 21 | # 22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2014 Mike Frysinger 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 1 34 | 35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl 36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) 37 | ])dnl AX_REQUIRE_DEFINED 38 | -------------------------------------------------------------------------------- /m4/ax_sanitizers.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_sanitizers.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_SANITIZERS([SANITIZERS], [ENABLED-BY-DEFAULT], [ACTION-SUCCESS]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Offers users to enable one or more sanitizers (see 12 | # https://github.com/google/sanitizers) with the corresponding 13 | # --enable--sanitizer option. 14 | # 15 | # SANITIZERS is a whitespace-separated list of sanitizers to offer via 16 | # --enable--sanitizer options, e.g. "address memory" for the 17 | # address sanitizer and the memory sanitizer. If SANITIZERS is not specified, 18 | # all known sanitizers to AX_SANITIZERS will be offered, which at the time of 19 | # writing are "address memory undefined". 20 | # NOTE that SANITIZERS is expanded at autoconf time, not at configure time, 21 | # i.e. you cannot use shell variables in SANITIZERS. 22 | # 23 | # ENABLED-BY-DEFAULT is a whitespace-separated list of sanitizers which 24 | # should be enabled by default, e.g. "memory undefined". Note that not all 25 | # sanitizers can be combined, e.g. memory sanitizer cannot be enabled when 26 | # address sanitizer is already enabled. 27 | # Set ENABLED-BY-DEFAULT to a single whitespace in order to disable all 28 | # sanitizers by default. 29 | # ENABLED-BY-DEFAULT is expanded at configure time, so you can use shell 30 | # variables. 31 | # 32 | # ACTION-SUCCESS allows to specify shell commands to execute on success, i.e. 33 | # when one of the sanitizers was successfully enabled. This is a good place 34 | # to call AC_DEFINE for any precompiler constants you might need to make your 35 | # code play nice with sanitizers. 36 | # 37 | # The variable ax_enabled_sanitizers contains a whitespace-separated list of 38 | # all enabled sanitizers, so that you can print them at the end of configure, 39 | # if you wish. 40 | # 41 | # The additional --enable-sanitizers option allows users to enable/disable 42 | # all sanitizers, effectively overriding ENABLED-BY-DEFAULT. 43 | # 44 | # EXAMPLES 45 | # 46 | # AX_SANITIZERS([address]) 47 | # dnl offer users to enable address sanitizer via --enable-address-sanitizer 48 | # 49 | # is_debug_build=… 50 | # if test "x$is_debug_build" = "xyes"; then 51 | # default_sanitizers="address memory" 52 | # else 53 | # default_sanitizers= 54 | # fi 55 | # AX_SANITIZERS([address memory], [$default_sanitizers]) 56 | # dnl enable address sanitizer and memory sanitizer by default for debug 57 | # dnl builds, e.g. when building from git instead of a dist tarball. 58 | # 59 | # AX_SANITIZERS(, , [ 60 | # AC_DEFINE([SANITIZERS_ENABLED], 61 | # [], 62 | # [At least one sanitizer was enabled])]) 63 | # dnl enable all sanitizers known to AX_SANITIZERS by default and set the 64 | # dnl SANITIZERS_ENABLED precompiler constant. 65 | # 66 | # AX_SANITIZERS(, [ ]) 67 | # dnl provide all sanitizers, but enable none by default. 68 | # 69 | # LICENSE 70 | # 71 | # Copyright (c) 2016 Michael Stapelberg 72 | # Copyright (c) 2021 Raymond Li 73 | # 74 | # Copying and distribution of this file, with or without modification, 75 | # are permitted in any medium without royalty provided the copyright 76 | # notice and this notice are preserved. This file is offered as-is, 77 | # without any warranty. 78 | 79 | AC_DEFUN([AX_SANITIZERS], 80 | [AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) 81 | AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 82 | AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) 83 | AC_ARG_ENABLE(sanitizers, 84 | AS_HELP_STRING( 85 | [--enable-sanitizers], 86 | [enable all known sanitizers]), 87 | [ax_sanitizers_default=$enableval], 88 | [ax_sanitizers_default=]) 89 | ax_enabled_sanitizers= 90 | m4_foreach_w([mysan], m4_default($1, [address memory undefined]), [ 91 | dnl If ax_sanitizers_default is unset, i.e. the user neither explicitly 92 | dnl enabled nor explicitly disabled all sanitizers, we get the default value 93 | dnl for this sanitizer based on whether it is listed in ENABLED-BY-DEFAULT. 94 | AS_IF([test "x$ax_sanitizers_default" = "x"], [dnl 95 | ax_sanitizer_default= 96 | for mycheck in m4_default([$2], [address memory undefined]); do 97 | AS_IF([test "x$mycheck" = "x[]mysan"], [ax_sanitizer_default=yes]) 98 | done 99 | AS_IF([test "x$ax_sanitizer_default" = "x"], [ax_sanitizer_default=no]) 100 | ], 101 | [ax_sanitizer_default=$ax_sanitizers_default]) 102 | AC_ARG_ENABLE(mysan[]-sanitizer, 103 | AS_HELP_STRING( 104 | [--enable-[]mysan[]-sanitizer], 105 | [enable -fsanitize=mysan]), 106 | [ax_sanitizer_enabled=$enableval], 107 | [ax_sanitizer_enabled=$ax_sanitizer_default]) 108 | 109 | AS_IF([test "x$ax_sanitizer_enabled" = "xyes"], [ 110 | dnl Not using AX_APPEND_COMPILE_FLAGS and AX_APPEND_LINK_FLAGS because they 111 | dnl lack the ability to specify ACTION-SUCCESS. 112 | AX_CHECK_COMPILE_FLAG([-fsanitize=[]mysan], [ 113 | AX_CHECK_LINK_FLAG([-fsanitize=[]mysan], [ 114 | AX_APPEND_FLAG([-fsanitize=[]mysan], []) 115 | dnl If and only if libtool is being used, LDFLAGS needs to contain -Wc,-fsanitize=…. 116 | dnl See e.g. https://sources.debian.net/src/systemd/231-7/configure.ac/?hl=128#L135 117 | dnl TODO: how can recognize that situation and add -Wc,? 118 | AX_APPEND_FLAG([-fsanitize=[]mysan], [LDFLAGS]) 119 | dnl TODO: add -fPIE -pie for memory 120 | # -fno-omit-frame-pointer results in nicer stack traces in error 121 | # messages, see http://clang.llvm.org/docs/AddressSanitizer.html#usage 122 | AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [ 123 | AX_APPEND_FLAG([-fno-omit-frame-pointer], [])]) 124 | dnl TODO: at least for clang, we should specify exactly -O1, not -O2 or -O0, so that performance is reasonable but stacktraces are not tampered with (due to inlining), see http://clang.llvm.org/docs/AddressSanitizer.html#usage 125 | m4_default([$3], :) 126 | ax_enabled_sanitizers="[]mysan $ax_enabled_sanitizers" 127 | ]) 128 | ]) 129 | ]) 130 | ])dnl 131 | ])dnl AX_SANITIZERS 132 | -------------------------------------------------------------------------------- /pam/i3lock: -------------------------------------------------------------------------------- 1 | # 2 | # PAM configuration file for the i3lock-color screen locker. By default, it includes 3 | # the 'system-local-login' configuration file (see /etc/pam.d/system-local-login) 4 | # for Arch and Gentoo and 'login' for Debian. Note that upstream uses only 'login', 5 | # which doesn't work on Arch and Gentoo. 6 | # 7 | 8 | #auth include system-local-login # For Arch/Gentoo 9 | auth include login # For Debian 10 | -------------------------------------------------------------------------------- /randr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * © 2010 Michael Stapelberg 5 | * © 2021 Raymond Li 6 | * 7 | * See LICENSE for licensing information 8 | * 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "i3lock.h" 19 | #include "xcb.h" 20 | #include "randr.h" 21 | 22 | /* Number of Xinerama screens which are currently present. */ 23 | int xr_screens = 0; 24 | 25 | /* The resolutions of the currently present Xinerama screens. */ 26 | Rect *xr_resolutions = NULL; 27 | 28 | static bool xinerama_active; 29 | static bool has_randr = false; 30 | static bool has_randr_1_5 = false; 31 | extern bool debug_mode; 32 | 33 | void _xinerama_init(void); 34 | 35 | void randr_init(int *event_base, xcb_window_t root) { 36 | const xcb_query_extension_reply_t *extreply; 37 | 38 | extreply = xcb_get_extension_data(conn, &xcb_randr_id); 39 | if (!extreply->present) { 40 | DEBUG("RandR is not present, falling back to Xinerama.\n"); 41 | _xinerama_init(); 42 | return; 43 | } 44 | 45 | xcb_generic_error_t *err; 46 | xcb_randr_query_version_reply_t *randr_version = 47 | xcb_randr_query_version_reply( 48 | conn, xcb_randr_query_version(conn, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION), &err); 49 | if (err != NULL) { 50 | DEBUG("Could not query RandR version: X11 error code %d\n", err->error_code); 51 | _xinerama_init(); 52 | return; 53 | } 54 | 55 | has_randr = true; 56 | 57 | has_randr_1_5 = (randr_version->major_version >= 1) && 58 | (randr_version->minor_version >= 5); 59 | 60 | free(randr_version); 61 | 62 | if (event_base != NULL) 63 | *event_base = extreply->first_event; 64 | 65 | xcb_randr_select_input(conn, root, 66 | XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | 67 | XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | 68 | XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | 69 | XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY); 70 | 71 | xcb_flush(conn); 72 | } 73 | 74 | void _xinerama_init(void) { 75 | if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) { 76 | DEBUG("Xinerama extension not found, disabling.\n"); 77 | return; 78 | } 79 | 80 | xcb_xinerama_is_active_cookie_t cookie; 81 | xcb_xinerama_is_active_reply_t *reply; 82 | 83 | cookie = xcb_xinerama_is_active(conn); 84 | reply = xcb_xinerama_is_active_reply(conn, cookie, NULL); 85 | if (!reply) 86 | return; 87 | 88 | if (!reply->state) { 89 | free(reply); 90 | return; 91 | } 92 | 93 | xinerama_active = true; 94 | free(reply); 95 | } 96 | 97 | /* 98 | * randr_query_outputs_15 uses RandR ≥ 1.5 to update outputs. 99 | * 100 | */ 101 | static bool _randr_query_monitors_15(xcb_window_t root) { 102 | #if XCB_RANDR_MINOR_VERSION < 5 103 | return false; 104 | #else 105 | /* RandR 1.5 available at compile-time, i.e. libxcb is new enough */ 106 | if (!has_randr_1_5) { 107 | return false; 108 | } 109 | /* RandR 1.5 available at run-time (supported by the server) */ 110 | DEBUG("Querying monitors using RandR 1.5\n"); 111 | xcb_generic_error_t *err; 112 | xcb_randr_get_monitors_reply_t *monitors = 113 | xcb_randr_get_monitors_reply( 114 | conn, xcb_randr_get_monitors(conn, root, true), &err); 115 | if (err != NULL) { 116 | DEBUG("Could not get RandR monitors: X11 error code %d\n", err->error_code); 117 | free(err); 118 | /* Fall back to RandR ≤ 1.4 */ 119 | return false; 120 | } 121 | 122 | int screens = xcb_randr_get_monitors_monitors_length(monitors); 123 | DEBUG("%d RandR monitors found (timestamp %d)\n", 124 | screens, monitors->timestamp); 125 | 126 | Rect *resolutions = malloc(screens * sizeof(Rect)); 127 | /* No memory? Just keep on using the old information. */ 128 | if (!resolutions) { 129 | free(monitors); 130 | return true; 131 | } 132 | 133 | xcb_randr_monitor_info_iterator_t iter; 134 | int screen; 135 | for (iter = xcb_randr_get_monitors_monitors_iterator(monitors), screen = 0; 136 | iter.rem; 137 | xcb_randr_monitor_info_next(&iter), screen++) { 138 | const xcb_randr_monitor_info_t *monitor_info = iter.data; 139 | 140 | resolutions[screen].x = monitor_info->x; 141 | resolutions[screen].y = monitor_info->y; 142 | resolutions[screen].width = monitor_info->width; 143 | resolutions[screen].height = monitor_info->height; 144 | DEBUG("found RandR monitor: %d x %d at %d x %d\n", 145 | monitor_info->width, monitor_info->height, 146 | monitor_info->x, monitor_info->y); 147 | } 148 | free(xr_resolutions); 149 | xr_resolutions = resolutions; 150 | xr_screens = screens; 151 | 152 | free(monitors); 153 | return true; 154 | #endif 155 | } 156 | 157 | /* 158 | * randr_query_outputs_14 uses RandR ≤ 1.4 to update outputs. 159 | * 160 | */ 161 | static bool _randr_query_outputs_14(xcb_window_t root) { 162 | if (!has_randr) { 163 | return false; 164 | } 165 | DEBUG("Querying outputs using RandR ≤ 1.4\n"); 166 | 167 | /* Get screen resources (primary output, crtcs, outputs, modes) */ 168 | xcb_randr_get_screen_resources_current_cookie_t rcookie; 169 | rcookie = xcb_randr_get_screen_resources_current(conn, root); 170 | 171 | xcb_randr_get_screen_resources_current_reply_t *res = 172 | xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL); 173 | if (res == NULL) { 174 | DEBUG("Could not query screen resources.\n"); 175 | return false; 176 | } 177 | 178 | /* timestamp of the configuration so that we get consistent replies to all 179 | * requests (if the configuration changes between our different calls) */ 180 | const xcb_timestamp_t cts = res->config_timestamp; 181 | 182 | const int len = xcb_randr_get_screen_resources_current_outputs_length(res); 183 | 184 | /* an output is VGA-1, LVDS-1, etc. (usually physical video outputs) */ 185 | xcb_randr_output_t *randr_outputs = xcb_randr_get_screen_resources_current_outputs(res); 186 | 187 | /* Request information for each output */ 188 | xcb_randr_get_output_info_cookie_t ocookie[len]; 189 | for (int i = 0; i < len; i++) { 190 | ocookie[i] = xcb_randr_get_output_info(conn, randr_outputs[i], cts); 191 | } 192 | Rect *resolutions = malloc(len * sizeof(Rect)); 193 | /* No memory? Just keep on using the old information. */ 194 | if (!resolutions) { 195 | free(res); 196 | return true; 197 | } 198 | 199 | /* Loop through all outputs available for this X11 screen */ 200 | int screen = 0; 201 | 202 | for (int i = 0; i < len; i++) { 203 | xcb_randr_get_output_info_reply_t *output; 204 | 205 | if ((output = xcb_randr_get_output_info_reply(conn, ocookie[i], NULL)) == NULL) { 206 | continue; 207 | } 208 | 209 | if (output->crtc == XCB_NONE) { 210 | free(output); 211 | continue; 212 | } 213 | 214 | xcb_randr_get_crtc_info_cookie_t icookie; 215 | xcb_randr_get_crtc_info_reply_t *crtc; 216 | icookie = xcb_randr_get_crtc_info(conn, output->crtc, cts); 217 | if ((crtc = xcb_randr_get_crtc_info_reply(conn, icookie, NULL)) == NULL) { 218 | DEBUG("Skipping output: could not get CRTC (0x%08x)\n", output->crtc); 219 | free(output); 220 | continue; 221 | } 222 | 223 | resolutions[screen].x = crtc->x; 224 | resolutions[screen].y = crtc->y; 225 | resolutions[screen].width = crtc->width; 226 | resolutions[screen].height = crtc->height; 227 | 228 | DEBUG("found RandR output: %d x %d at %d x %d\n", 229 | crtc->width, crtc->height, 230 | crtc->x, crtc->y); 231 | 232 | screen++; 233 | 234 | free(crtc); 235 | 236 | free(output); 237 | } 238 | free(xr_resolutions); 239 | xr_resolutions = resolutions; 240 | xr_screens = screen; 241 | free(res); 242 | return true; 243 | } 244 | 245 | void _xinerama_query_screens(void) { 246 | if (!xinerama_active) { 247 | return; 248 | } 249 | 250 | xcb_xinerama_query_screens_cookie_t cookie; 251 | xcb_xinerama_query_screens_reply_t *reply; 252 | xcb_xinerama_screen_info_t *screen_info; 253 | xcb_generic_error_t *err; 254 | cookie = xcb_xinerama_query_screens_unchecked(conn); 255 | reply = xcb_xinerama_query_screens_reply(conn, cookie, &err); 256 | if (!reply) { 257 | DEBUG("Couldn't get Xinerama screens: X11 error code %d\n", err->error_code); 258 | free(err); 259 | return; 260 | } 261 | screen_info = xcb_xinerama_query_screens_screen_info(reply); 262 | int screens = xcb_xinerama_query_screens_screen_info_length(reply); 263 | 264 | Rect *resolutions = malloc(screens * sizeof(Rect)); 265 | /* No memory? Just keep on using the old information. */ 266 | if (!resolutions) { 267 | free(reply); 268 | return; 269 | } 270 | 271 | for (int screen = 0; screen < xr_screens; screen++) { 272 | resolutions[screen].x = screen_info[screen].x_org; 273 | resolutions[screen].y = screen_info[screen].y_org; 274 | resolutions[screen].width = screen_info[screen].width; 275 | resolutions[screen].height = screen_info[screen].height; 276 | DEBUG("found Xinerama screen: %d x %d at %d x %d\n", 277 | screen_info[screen].width, screen_info[screen].height, 278 | screen_info[screen].x_org, screen_info[screen].y_org); 279 | } 280 | 281 | free(xr_resolutions); 282 | xr_resolutions = resolutions; 283 | xr_screens = screens; 284 | 285 | free(reply); 286 | } 287 | 288 | void randr_query(xcb_window_t root) { 289 | if (_randr_query_monitors_15(root)) { 290 | return; 291 | } 292 | 293 | if (_randr_query_outputs_14(root)) { 294 | return; 295 | } 296 | 297 | _xinerama_query_screens(); 298 | } 299 | -------------------------------------------------------------------------------- /randr.h: -------------------------------------------------------------------------------- 1 | #ifndef _XINERAMA_H 2 | #define _XINERAMA_H 3 | 4 | typedef struct Rect { 5 | int16_t x; 6 | int16_t y; 7 | uint16_t width; 8 | uint16_t height; 9 | } Rect; 10 | 11 | extern int xr_screens; 12 | extern Rect *xr_resolutions; 13 | 14 | void randr_init(int *event_base, xcb_window_t root); 15 | void randr_query(xcb_window_t root); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /rgba.h: -------------------------------------------------------------------------------- 1 | #ifndef RGBA_H 2 | #define RGBA_H 3 | 4 | typedef struct rgb { 5 | double red; 6 | double green; 7 | double blue; 8 | } rgb_t; 9 | 10 | typedef struct rgb_str { 11 | char red[3]; 12 | char green[3]; 13 | char blue[3]; 14 | } rgb_str_t; 15 | 16 | typedef struct rgba { 17 | double red; 18 | double green; 19 | double blue; 20 | double alpha; 21 | } rgba_t; 22 | 23 | typedef struct rgba_str { 24 | char red[3]; 25 | char green[3]; 26 | char blue[3]; 27 | char alpha[3]; 28 | } rgba_str_t; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tinyexpr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TINYEXPR - Tiny recursive descent parser and evaluation engine in C 3 | * 4 | * Copyright (c) 2015, 2016 Lewis Van Winkle 5 | * 6 | * http://CodePlea.com 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | #ifndef __TINYEXPR_H__ 26 | #define __TINYEXPR_H__ 27 | 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | 35 | typedef struct te_expr { 36 | int type; 37 | union {double value; const double *bound; const void *function;}; 38 | void *parameters[1]; 39 | } te_expr; 40 | 41 | 42 | enum { 43 | TE_VARIABLE = 0, 44 | 45 | TE_FUNCTION0 = 8, TE_FUNCTION1, TE_FUNCTION2, TE_FUNCTION3, 46 | TE_FUNCTION4, TE_FUNCTION5, TE_FUNCTION6, TE_FUNCTION7, 47 | 48 | TE_CLOSURE0 = 16, TE_CLOSURE1, TE_CLOSURE2, TE_CLOSURE3, 49 | TE_CLOSURE4, TE_CLOSURE5, TE_CLOSURE6, TE_CLOSURE7, 50 | 51 | TE_FLAG_PURE = 32 52 | }; 53 | 54 | typedef struct te_variable { 55 | const char *name; 56 | const void *address; 57 | int type; 58 | void *context; 59 | } te_variable; 60 | 61 | 62 | 63 | /* Parses the input expression, evaluates it, and frees it. */ 64 | /* Returns NaN on error. */ 65 | double te_interp(const char *expression, int *error); 66 | 67 | /* Parses the input expression and binds variables. */ 68 | /* Returns NULL on error. */ 69 | te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error); 70 | 71 | /* Evaluates the expression. */ 72 | double te_eval(const te_expr *n); 73 | 74 | /* Prints debugging information on the syntax tree. */ 75 | void te_print(const te_expr *n); 76 | 77 | /* Frees the expression. */ 78 | /* This is safe to call on NULL pointers. */ 79 | void te_free(te_expr *n); 80 | 81 | 82 | #ifdef __cplusplus 83 | } 84 | #endif 85 | 86 | #endif /*__TINYEXPR_H__*/ 87 | -------------------------------------------------------------------------------- /travis/Dockerfile: -------------------------------------------------------------------------------- 1 | # vim:ft=Dockerfile 2 | FROM debian:sid 3 | 4 | RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup 5 | # Paper over occasional network flakiness of some mirrors. 6 | RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry 7 | 8 | # NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com 9 | # instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357 10 | # kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s 11 | # (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now. 12 | 13 | # Install mk-build-deps (for installing the i3 build dependencies), 14 | # clang and clang-format-9 (for checking formatting and building with clang), 15 | # lintian (for checking spelling errors), 16 | # test suite dependencies (for running tests) 17 | RUN apt-get update && \ 18 | DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ 19 | build-essential clang git autoconf automake libxcb-randr0-dev pkg-config libpam0g-dev \ 20 | libcairo2-dev libxcb1-dev libxcb-dpms0-dev libxcb-image0-dev libxcb-util0-dev \ 21 | libxcb-xrm-dev libev-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev \ 22 | libxkbcommon-x11-dev clang-format-9 libgif-dev && \ 23 | rm -rf /var/lib/apt/lists/* 24 | 25 | WORKDIR /usr/src 26 | -------------------------------------------------------------------------------- /unlock_indicator.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNLOCK_INDICATOR_H 2 | #define _UNLOCK_INDICATOR_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | typedef enum { 10 | STATE_STARTED = 0, /* default state */ 11 | STATE_KEY_PRESSED = 1, /* key was pressed, show unlock indicator */ 12 | STATE_KEY_ACTIVE = 2, /* a key was pressed recently, highlight part 13 | of the unlock indicator. */ 14 | STATE_BACKSPACE_ACTIVE = 3, /* backspace was pressed recently, highlight 15 | part of the unlock indicator in red. */ 16 | STATE_NOTHING_TO_DELETE = 4, /* backspace was pressed, but there is nothing to delete. */ 17 | } unlock_state_t; 18 | 19 | typedef enum { 20 | STATE_AUTH_IDLE = 0, /* no authenticator interaction at the moment */ 21 | STATE_AUTH_VERIFY = 1, /* currently verifying the password via authenticator */ 22 | STATE_AUTH_LOCK = 2, /* currently locking the screen */ 23 | STATE_AUTH_WRONG = 3, /* the password was wrong */ 24 | STATE_I3LOCK_LOCK_FAILED = 4, /* i3lock failed to load */ 25 | } auth_state_t; 26 | 27 | typedef struct { 28 | text_t status_text; 29 | text_t mod_text; 30 | text_t keylayout_text; 31 | text_t time_text; 32 | text_t date_text; 33 | text_t greeter_text; 34 | 35 | double indicator_x, indicator_y; 36 | 37 | double screen_x, screen_y; 38 | double bar_x, bar_y, bar_width; 39 | } DrawData; 40 | 41 | typedef enum { 42 | NONE, 43 | TILE, 44 | CENTER, 45 | FILL, 46 | SCALE, 47 | MAX, 48 | } background_type_t; 49 | 50 | 51 | typedef enum { 52 | CC_POS_RESET, 53 | CC_POS_CHANGE, 54 | CC_POS_KEEP, 55 | CC_POS_TAB 56 | } control_char_pos_t; 57 | 58 | typedef struct { 59 | char character; 60 | control_char_pos_t x_behavior; 61 | int x_behavior_arg; 62 | control_char_pos_t y_behavior; 63 | int y_behavior_arg; 64 | } control_char_config_t; 65 | 66 | void render_lock(uint32_t* resolution, xcb_drawable_t drawable); 67 | void draw_image(uint32_t* resolution, cairo_surface_t* img, cairo_t* xcb_ctx); 68 | void init_colors_once(void); 69 | void redraw_screen(void); 70 | void clear_indicator(void); 71 | void start_time_redraw_timeout(void); 72 | void* start_time_redraw_tick_pthread(void* arg); 73 | void start_time_redraw_tick(struct ev_loop* main_loop); 74 | #endif 75 | -------------------------------------------------------------------------------- /xcb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vim:ts=4:sw=4:expandtab 3 | * 4 | * © 2010 Michael Stapelberg 5 | * © 2021 Raymond Li 6 | * 7 | * xcb.c: contains all functions which use XCB to talk to X11. Mostly wrappers 8 | * around the rather complicated/ugly parts of the XCB API. 9 | * 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "cursors.h" 30 | #include "i3lock.h" 31 | #include "xcb.h" 32 | #include "unlock_indicator.h" 33 | 34 | extern auth_state_t auth_state; 35 | extern bool composite; 36 | extern bool debug_mode; 37 | 38 | xcb_connection_t *conn; 39 | xcb_screen_t *screen; 40 | 41 | static xcb_atom_t _NET_WM_BYPASS_COMPOSITOR = XCB_NONE; 42 | void _init_net_wm_bypass_compositor(xcb_connection_t *conn) { 43 | if (_NET_WM_BYPASS_COMPOSITOR != XCB_NONE) { 44 | /* already initialized */ 45 | return; 46 | } 47 | xcb_generic_error_t *err; 48 | xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply( 49 | conn, 50 | xcb_intern_atom(conn, 0, strlen("_NET_WM_BYPASS_COMPOSITOR"), "_NET_WM_BYPASS_COMPOSITOR"), 51 | &err); 52 | if (atom_reply == NULL) { 53 | fprintf(stderr, "X11 Error %d\n", err->error_code); 54 | free(err); 55 | return; 56 | } 57 | _NET_WM_BYPASS_COMPOSITOR = atom_reply->atom; 58 | free(atom_reply); 59 | } 60 | 61 | #define curs_invisible_width 8 62 | #define curs_invisible_height 8 63 | 64 | static unsigned char curs_invisible_bits[] = { 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 66 | 67 | #define curs_windows_width 11 68 | #define curs_windows_height 19 69 | 70 | static unsigned char curs_windows_bits[] = { 71 | 0xfe, 0x07, 0xfc, 0x07, 0xfa, 0x07, 0xf6, 0x07, 0xee, 0x07, 0xde, 0x07, 72 | 0xbe, 0x07, 0x7e, 0x07, 0xfe, 0x06, 0xfe, 0x05, 0x3e, 0x00, 0xb6, 0x07, 73 | 0x6a, 0x07, 0x6c, 0x07, 0xde, 0x06, 0xdf, 0x06, 0xbf, 0x05, 0xbf, 0x05, 74 | 0x7f, 0x06}; 75 | 76 | #define mask_windows_width 11 77 | #define mask_windows_height 19 78 | 79 | static unsigned char mask_windows_bits[] = { 80 | 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 81 | 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0x7f, 0x00, 82 | 0xf7, 0x00, 0xf3, 0x00, 0xe1, 0x01, 0xe0, 0x01, 0xc0, 0x03, 0xc0, 0x03, 83 | 0x80, 0x01}; 84 | 85 | static uint32_t get_colorpixel(char *hex) { 86 | char strgroups[4][3] = {{hex[0], hex[1], '\0'}, 87 | {hex[2], hex[3], '\0'}, 88 | {hex[4], hex[5], '\0'}, 89 | {hex[6], hex[4], '\0'}}; 90 | uint32_t rgb16[4] = {(strtol(strgroups[0], NULL, 16)), 91 | (strtol(strgroups[1], NULL, 16)), 92 | (strtol(strgroups[2], NULL, 16)), 93 | (strtol(strgroups[3], NULL, 16))}; 94 | 95 | return (rgb16[3] << 24) + (rgb16[0] << 16) + (rgb16[1] << 8) + rgb16[2]; 96 | } 97 | 98 | xcb_visualtype_t *get_visualtype_by_depth(uint16_t depth, xcb_screen_t *root_screen) { 99 | xcb_depth_iterator_t depth_iter; 100 | 101 | depth_iter = xcb_screen_allowed_depths_iterator(root_screen); 102 | for (; depth_iter.rem; xcb_depth_next(&depth_iter)) { 103 | if (depth_iter.data->depth != depth) 104 | continue; 105 | 106 | xcb_visualtype_iterator_t visual_iter; 107 | 108 | visual_iter = xcb_depth_visuals_iterator(depth_iter.data); 109 | if (!visual_iter.rem) 110 | continue; 111 | return visual_iter.data; 112 | } 113 | return NULL; 114 | } 115 | 116 | 117 | xcb_visualtype_t *get_root_visual_type(xcb_screen_t *screen) { 118 | xcb_visualtype_t *visual_type = NULL; 119 | xcb_depth_iterator_t depth_iter; 120 | xcb_visualtype_iterator_t visual_iter; 121 | 122 | for (depth_iter = xcb_screen_allowed_depths_iterator(screen); 123 | depth_iter.rem; 124 | xcb_depth_next(&depth_iter)) { 125 | for (visual_iter = xcb_depth_visuals_iterator(depth_iter.data); 126 | visual_iter.rem; 127 | xcb_visualtype_next(&visual_iter)) { 128 | if (screen->root_visual != visual_iter.data->visual_id) 129 | continue; 130 | 131 | visual_type = visual_iter.data; 132 | return visual_type; 133 | } 134 | } 135 | 136 | return NULL; 137 | } 138 | 139 | xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_drawable_t win, u_int32_t *resolution, char *color) { 140 | xcb_pixmap_t bg_pixmap = xcb_generate_id(conn); 141 | xcb_create_pixmap(conn, 32, bg_pixmap, win, resolution[0], resolution[1]); 142 | 143 | /* Generate a Graphics Context and fill the pixmap with background color 144 | * (for images that are smaller than your screen) */ 145 | xcb_gcontext_t gc = xcb_generate_id(conn); 146 | uint32_t values[] = {get_colorpixel(color)}; 147 | xcb_create_gc(conn, gc, bg_pixmap, XCB_GC_FOREGROUND, values); 148 | xcb_rectangle_t rect = {0, 0, resolution[0], resolution[1]}; 149 | xcb_poly_fill_rectangle(conn, bg_pixmap, gc, 1, &rect); 150 | xcb_free_gc(conn, gc); 151 | 152 | return bg_pixmap; 153 | } 154 | 155 | xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color) { 156 | uint32_t mask = 0; 157 | uint32_t values[5]; 158 | xcb_window_t win = xcb_generate_id(conn); 159 | xcb_window_t parent_win = scr->root; 160 | 161 | if (composite) { 162 | /* Check whether the composite extension is available */ 163 | const xcb_query_extension_reply_t *extension_query = NULL; 164 | xcb_generic_error_t *error = NULL; 165 | xcb_composite_get_overlay_window_cookie_t cookie; 166 | xcb_composite_get_overlay_window_reply_t *composite_reply = NULL; 167 | 168 | extension_query = xcb_get_extension_data(conn, &xcb_composite_id); 169 | if (extension_query && extension_query->present) { 170 | /* When composition is used, we need to use the composite overlay 171 | * window instead of the normal root window to be able to cover 172 | * composited windows */ 173 | cookie = xcb_composite_get_overlay_window(conn, scr->root); 174 | composite_reply = xcb_composite_get_overlay_window_reply(conn, cookie, &error); 175 | 176 | if (!error && composite_reply) { 177 | parent_win = composite_reply->overlay_win; 178 | } 179 | 180 | free(composite_reply); 181 | free(error); 182 | } 183 | } 184 | 185 | 186 | xcb_visualid_t visual = get_visualtype_by_depth(32, scr)->visual_id; 187 | xcb_colormap_t win_colormap = xcb_generate_id(conn); 188 | xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, scr->root, visual); 189 | 190 | mask |= XCB_CW_BACK_PIXEL; 191 | values[0] = get_colorpixel(color); 192 | 193 | mask |= XCB_CW_BORDER_PIXEL; 194 | values[1] = 0x00000000; 195 | 196 | mask |= XCB_CW_OVERRIDE_REDIRECT; 197 | values[2] = 1; 198 | 199 | mask |= XCB_CW_EVENT_MASK; 200 | values[3] = XCB_EVENT_MASK_EXPOSURE | 201 | XCB_EVENT_MASK_KEY_PRESS | 202 | XCB_EVENT_MASK_KEY_RELEASE | 203 | XCB_EVENT_MASK_VISIBILITY_CHANGE | 204 | XCB_EVENT_MASK_STRUCTURE_NOTIFY; 205 | 206 | mask |= XCB_CW_COLORMAP; 207 | values[4] = win_colormap; 208 | 209 | xcb_create_window(conn, 210 | 32, 211 | win, /* the window id */ 212 | parent_win, 213 | 0, 0, 214 | scr->width_in_pixels, 215 | scr->height_in_pixels, /* dimensions */ 216 | 0, /* border = 0, we draw our own */ 217 | XCB_WINDOW_CLASS_INPUT_OUTPUT, 218 | visual, /* copy visual from parent */ 219 | mask, 220 | values); 221 | 222 | char *name = "i3lock"; 223 | xcb_change_property(conn, 224 | XCB_PROP_MODE_REPLACE, 225 | win, 226 | XCB_ATOM_WM_NAME, 227 | XCB_ATOM_STRING, 228 | 8, 229 | strlen(name), 230 | name); 231 | 232 | xcb_change_property(conn, 233 | XCB_PROP_MODE_REPLACE, 234 | win, 235 | XCB_ATOM_WM_CLASS, 236 | XCB_ATOM_STRING, 237 | 8, 238 | 2 * (strlen("i3lock") + 1), 239 | "i3lock\0i3lock\0"); 240 | 241 | const uint32_t bypass_compositor = 1; /* disable compositing */ 242 | _init_net_wm_bypass_compositor(conn); 243 | xcb_change_property(conn, 244 | XCB_PROP_MODE_REPLACE, 245 | win, 246 | _NET_WM_BYPASS_COMPOSITOR, 247 | XCB_ATOM_CARDINAL, 248 | 32, 249 | 1, 250 | &bypass_compositor); 251 | 252 | /* Map the window (= make it visible) */ 253 | xcb_map_window(conn, win); 254 | 255 | /* Raise window (put it on top) */ 256 | values[0] = XCB_STACK_MODE_ABOVE; 257 | xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values); 258 | 259 | /* Ensure that the window is created and set up before returning */ 260 | xcb_aux_sync(conn); 261 | 262 | return win; 263 | } 264 | 265 | /* 266 | * Repeatedly tries to grab pointer and keyboard (up to the specified number of 267 | * tries). 268 | * 269 | * Returns true if the grab succeeded, false if not. 270 | * 271 | */ 272 | bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor, int tries) { 273 | xcb_grab_pointer_cookie_t pcookie; 274 | xcb_grab_pointer_reply_t *preply; 275 | 276 | xcb_grab_keyboard_cookie_t kcookie; 277 | xcb_grab_keyboard_reply_t *kreply; 278 | 279 | const suseconds_t screen_redraw_timeout = 100000; /* 100ms */ 280 | 281 | /* Using few variables to trigger a redraw_screen() if too many tries */ 282 | bool redrawn = false; 283 | struct timeval start; 284 | if (gettimeofday(&start, NULL) == -1) { 285 | err(EXIT_FAILURE, "gettimeofday"); 286 | } 287 | 288 | while (tries-- > 0) { 289 | pcookie = xcb_grab_pointer( 290 | conn, 291 | false, /* get all pointer events specified by the following mask */ 292 | screen->root, /* grab the root window */ 293 | XCB_NONE, /* which events to let through */ 294 | XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */ 295 | XCB_GRAB_MODE_ASYNC, /* keyboard mode */ 296 | XCB_NONE, /* confine_to = in which window should the cursor stay */ 297 | cursor, /* we change the cursor to whatever the user wanted */ 298 | XCB_CURRENT_TIME); 299 | 300 | if ((preply = xcb_grab_pointer_reply(conn, pcookie, NULL)) && 301 | preply->status == XCB_GRAB_STATUS_SUCCESS) { 302 | free(preply); 303 | break; 304 | } 305 | 306 | /* In case the grab failed, we still need to free the reply */ 307 | free(preply); 308 | 309 | /* Make this quite a bit slower */ 310 | usleep(50); 311 | 312 | struct timeval now; 313 | if (gettimeofday(&now, NULL) == -1) { 314 | err(EXIT_FAILURE, "gettimeofday"); 315 | } 316 | 317 | struct timeval elapsed; 318 | timersub(&now, &start, &elapsed); 319 | 320 | if (!redrawn && 321 | (tries % 100) == 0 && 322 | elapsed.tv_usec >= screen_redraw_timeout) { 323 | redraw_screen(); 324 | redrawn = true; 325 | } 326 | } 327 | 328 | while (tries-- > 0) { 329 | kcookie = xcb_grab_keyboard( 330 | conn, 331 | true, /* report events */ 332 | screen->root, /* grab the root window */ 333 | XCB_CURRENT_TIME, 334 | XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ 335 | XCB_GRAB_MODE_ASYNC); 336 | 337 | if ((kreply = xcb_grab_keyboard_reply(conn, kcookie, NULL)) && 338 | kreply->status == XCB_GRAB_STATUS_SUCCESS) { 339 | free(kreply); 340 | break; 341 | } 342 | 343 | /* In case the grab failed, we still need to free the reply */ 344 | free(kreply); 345 | 346 | /* Make this quite a bit slower */ 347 | usleep(50); 348 | 349 | struct timeval now; 350 | if (gettimeofday(&now, NULL) == -1) { 351 | err(EXIT_FAILURE, "gettimeofday"); 352 | } 353 | 354 | struct timeval elapsed; 355 | timersub(&now, &start, &elapsed); 356 | 357 | /* Trigger a screen redraw if 100ms elapsed */ 358 | if (!redrawn && 359 | (tries % 100) == 0 && 360 | elapsed.tv_usec >= screen_redraw_timeout) { 361 | redraw_screen(); 362 | redrawn = true; 363 | } 364 | } 365 | 366 | return (tries > 0); 367 | } 368 | 369 | xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) { 370 | xcb_pixmap_t bitmap; 371 | xcb_pixmap_t mask; 372 | xcb_cursor_t cursor; 373 | 374 | unsigned char *curs_bits; 375 | unsigned char *mask_bits; 376 | int curs_w, curs_h; 377 | 378 | switch (choice) { 379 | case CURS_NONE: 380 | curs_bits = curs_invisible_bits; 381 | mask_bits = curs_invisible_bits; 382 | curs_w = curs_invisible_width; 383 | curs_h = curs_invisible_height; 384 | break; 385 | case CURS_WIN: 386 | curs_bits = curs_windows_bits; 387 | mask_bits = mask_windows_bits; 388 | curs_w = curs_windows_width; 389 | curs_h = curs_windows_height; 390 | break; 391 | case CURS_DEFAULT: 392 | default: 393 | return XCB_NONE; /* XCB_NONE is xcb's way of saying "don't change the cursor" */ 394 | } 395 | 396 | bitmap = xcb_create_pixmap_from_bitmap_data(conn, 397 | win, 398 | curs_bits, 399 | curs_w, 400 | curs_h, 401 | 1, 402 | screen->white_pixel, 403 | screen->black_pixel, 404 | NULL); 405 | 406 | mask = xcb_create_pixmap_from_bitmap_data(conn, 407 | win, 408 | mask_bits, 409 | curs_w, 410 | curs_h, 411 | 1, 412 | screen->white_pixel, 413 | screen->black_pixel, 414 | NULL); 415 | 416 | cursor = xcb_generate_id(conn); 417 | 418 | xcb_create_cursor(conn, 419 | cursor, 420 | bitmap, 421 | mask, 422 | 65535, 65535, 65535, 423 | 0, 0, 0, 424 | 0, 0); 425 | 426 | xcb_free_pixmap(conn, bitmap); 427 | xcb_free_pixmap(conn, mask); 428 | 429 | return cursor; 430 | } 431 | 432 | static xcb_atom_t _NET_ACTIVE_WINDOW = XCB_NONE; 433 | void _init_net_active_window(xcb_connection_t *conn) { 434 | if (_NET_ACTIVE_WINDOW != XCB_NONE) { 435 | /* already initialized */ 436 | return; 437 | } 438 | xcb_generic_error_t *err; 439 | xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply( 440 | conn, 441 | xcb_intern_atom(conn, 0, strlen("_NET_ACTIVE_WINDOW"), "_NET_ACTIVE_WINDOW"), 442 | &err); 443 | if (atom_reply == NULL) { 444 | fprintf(stderr, "X11 Error %d\n", err->error_code); 445 | free(err); 446 | return; 447 | } 448 | _NET_ACTIVE_WINDOW = atom_reply->atom; 449 | free(atom_reply); 450 | } 451 | 452 | xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root) { 453 | xcb_window_t result = XCB_NONE; 454 | 455 | _init_net_active_window(conn); 456 | 457 | xcb_get_property_reply_t *prop_reply = xcb_get_property_reply( 458 | conn, 459 | xcb_get_property_unchecked( 460 | conn, false, root, _NET_ACTIVE_WINDOW, XCB_GET_PROPERTY_TYPE_ANY, 0, 1 /* word */), 461 | NULL); 462 | if (prop_reply == NULL) { 463 | goto out; 464 | } 465 | if (xcb_get_property_value_length(prop_reply) == 0) { 466 | goto out_prop; 467 | } 468 | if (prop_reply->type != XCB_ATOM_WINDOW) { 469 | goto out_prop; 470 | } 471 | 472 | result = *((xcb_window_t *)xcb_get_property_value(prop_reply)); 473 | 474 | out_prop: 475 | free(prop_reply); 476 | out: 477 | return result; 478 | } 479 | 480 | void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const xcb_window_t window) { 481 | xcb_client_message_event_t ev; 482 | memset(&ev, '\0', sizeof(xcb_client_message_event_t)); 483 | 484 | _init_net_active_window(conn); 485 | 486 | ev.response_type = XCB_CLIENT_MESSAGE; 487 | ev.window = window; 488 | ev.type = _NET_ACTIVE_WINDOW; 489 | ev.format = 32; 490 | ev.data.data32[0] = 2; /* 2 = pager */ 491 | 492 | xcb_send_event(conn, false, root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)&ev); 493 | xcb_flush(conn); 494 | } 495 | 496 | xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t * resolution) { 497 | xcb_pixmap_t bg_pixmap = xcb_generate_id(conn); 498 | xcb_create_pixmap(conn, scr->root_depth, bg_pixmap, scr->root, resolution[0], resolution[1]); 499 | xcb_gcontext_t gc = xcb_generate_id(conn); 500 | uint32_t values[] = { scr->black_pixel, 1}; 501 | xcb_create_gc(conn, gc, bg_pixmap, XCB_GC_FOREGROUND | XCB_GC_SUBWINDOW_MODE, values); 502 | xcb_rectangle_t rect = { 0, 0, resolution[0], resolution[1] }; 503 | xcb_poly_fill_rectangle(conn, bg_pixmap, gc, 1, &rect); 504 | xcb_copy_area(conn, scr->root, bg_pixmap, gc, 0, 0, 0, 0, resolution[0], resolution[1]); 505 | xcb_flush(conn); 506 | xcb_free_gc(conn, gc); 507 | return bg_pixmap; 508 | } 509 | 510 | static char * get_atom_name(xcb_connection_t* conn, xcb_atom_t atom) { 511 | xcb_get_atom_name_reply_t *reply = NULL; 512 | char *name; 513 | int length; 514 | char* answer = NULL; 515 | 516 | if (atom == 0) 517 | return ""; 518 | 519 | xcb_get_atom_name_cookie_t cookie; 520 | xcb_generic_error_t *error = NULL; 521 | 522 | cookie = xcb_get_atom_name(conn, atom); 523 | 524 | reply = xcb_get_atom_name_reply(conn, cookie, &error); 525 | if (!reply || error) 526 | return ""; 527 | 528 | length = xcb_get_atom_name_name_length(reply); 529 | name = xcb_get_atom_name_name(reply); 530 | 531 | answer = malloc(sizeof(char) * (length + 1)); 532 | strncpy(answer, name, length); 533 | answer[length] = '\0'; 534 | free(error); 535 | free(reply); 536 | return answer; 537 | } 538 | 539 | 540 | uint8_t xcb_get_key_group_index(xcb_connection_t *conn) { 541 | xcb_xkb_get_state_cookie_t cookie; 542 | xcb_xkb_get_state_reply_t* reply = NULL; 543 | cookie = xcb_xkb_get_state(conn, XCB_XKB_ID_USE_CORE_KBD); 544 | reply = xcb_xkb_get_state_reply(conn, cookie, NULL); 545 | uint8_t ans = reply->group; 546 | free(reply); 547 | return ans; 548 | } 549 | 550 | 551 | char* xcb_get_key_group_names(xcb_connection_t *conn) { 552 | uint8_t xkb_base_event; 553 | uint8_t xkb_base_error; 554 | if (xkb_x11_setup_xkb_extension(conn, 555 | XKB_X11_MIN_MAJOR_XKB_VERSION, 556 | XKB_X11_MIN_MINOR_XKB_VERSION, 557 | 0, 558 | NULL, 559 | NULL, 560 | &xkb_base_event, 561 | &xkb_base_error) != 1) 562 | errx(EXIT_FAILURE, "Could not setup XKB extension."); 563 | 564 | 565 | xcb_xkb_get_names_reply_t *reply = NULL; 566 | 567 | 568 | xcb_generic_error_t *error = NULL; 569 | xcb_xkb_get_names_cookie_t cookie; 570 | 571 | cookie = xcb_xkb_get_names(conn, 572 | XCB_XKB_ID_USE_CORE_KBD, 573 | all_name_details); 574 | 575 | reply = xcb_xkb_get_names_reply(conn, cookie, &error); 576 | if (!reply || error) 577 | errx(1, "couldn't get reply for get_names"); 578 | 579 | xcb_xkb_get_names_value_list_t list; 580 | 581 | void *buffer; 582 | 583 | buffer = xcb_xkb_get_names_value_list(reply); 584 | xcb_xkb_get_names_value_list_unpack(buffer, 585 | reply->nTypes, 586 | reply->indicators, 587 | reply->virtualMods, 588 | reply->groupNames, 589 | reply->nKeys, 590 | reply->nKeyAliases, 591 | reply->nRadioGroups, 592 | reply->which, 593 | &list); 594 | 595 | /* dump group names. */ 596 | 597 | int length; 598 | xcb_atom_t *iter; 599 | uint8_t index; 600 | char* answer = NULL; 601 | length = xcb_xkb_get_names_value_list_groups_length(reply, &list); 602 | iter = xcb_xkb_get_names_value_list_groups(&list); 603 | index = xcb_get_key_group_index(conn); 604 | 605 | for (int i = 0; i < length; i++) { 606 | xcb_atom_t group_name = *iter; 607 | char* name = get_atom_name(conn, group_name); 608 | DEBUG("group_name %d: %s\n", i, name); 609 | if (i == index) { 610 | answer = name; 611 | } else { 612 | free(name); 613 | } 614 | iter++; 615 | } 616 | free(reply); 617 | free(error); 618 | return answer; 619 | } 620 | -------------------------------------------------------------------------------- /xcb.h: -------------------------------------------------------------------------------- 1 | #ifndef _XCB_H 2 | #define _XCB_H 3 | 4 | #include 5 | 6 | #define all_name_details \ 7 | (XCB_XKB_NAME_DETAIL_KEYCODES | \ 8 | XCB_XKB_NAME_DETAIL_GEOMETRY | \ 9 | XCB_XKB_NAME_DETAIL_SYMBOLS | \ 10 | XCB_XKB_NAME_DETAIL_PHYS_SYMBOLS | \ 11 | XCB_XKB_NAME_DETAIL_TYPES | \ 12 | XCB_XKB_NAME_DETAIL_COMPAT | \ 13 | XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | \ 14 | XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | \ 15 | XCB_XKB_NAME_DETAIL_INDICATOR_NAMES | \ 16 | XCB_XKB_NAME_DETAIL_KEY_NAMES | \ 17 | XCB_XKB_NAME_DETAIL_KEY_ALIASES | \ 18 | XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES | \ 19 | XCB_XKB_NAME_DETAIL_GROUP_NAMES | \ 20 | XCB_XKB_NAME_DETAIL_RG_NAMES) 21 | 22 | 23 | extern xcb_connection_t *conn; 24 | extern xcb_screen_t *screen; 25 | 26 | xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s); 27 | xcb_visualtype_t* get_visualtype_by_depth(uint16_t depth, xcb_screen_t* root_screen); 28 | xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_drawable_t drawable, u_int32_t *resolution, char *color); 29 | xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color); 30 | bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor, int tries); 31 | xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice); 32 | xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root); 33 | void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const xcb_window_t window); 34 | xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t* resolution); 35 | char* xcb_get_key_group_names(xcb_connection_t *conn); 36 | 37 | #endif 38 | --------------------------------------------------------------------------------