├── .clang-format ├── .clangd ├── .gitignore ├── .vscode ├── c_cpp_properties.json └── settings.json ├── LICENSE ├── Makefile ├── README.md ├── build.sh ├── config.def.h ├── config.mk ├── drw.c ├── drw.h ├── instantwm.1 ├── instantwm.c ├── instantwm.desktop ├── instantwm.h ├── instantwmctrl.sh ├── layouts.c ├── layouts.h ├── push.c ├── push.h ├── startinstantos ├── themes ├── arc.theme ├── dracula.theme ├── mac.theme └── manjaro.theme ├── util.c └── util.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | # We'll use defaults from the LLVM style, but with 4 columns indentation. 3 | BasedOnStyle: LLVM 4 | IndentWidth: 4 5 | -------------------------------------------------------------------------------- /.clangd: -------------------------------------------------------------------------------- 1 | CompileFlags: # Tweak the parse settings 2 | Add: [-xc, -std=c11, -I/usr/include/freetype2] # treat all files as C, enable more warnings, add FreeType2 include path 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | config.h 3 | instantwm 4 | tags 5 | .envrc 6 | shell.nix 7 | .nvimlog 8 | cscope.out 9 | .ccls-cache 10 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "/usr/include/**" 8 | ], 9 | "defines": [], 10 | "compilerPath": "/usr/bin/clang", 11 | "cStandard": "c11", 12 | "cppStandard": "c++17", 13 | "intelliSenseMode": "gcc-x86", 14 | "configurationProvider": "ms-vscode.makefile-tools" 15 | } 16 | ], 17 | "version": 4 18 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "layouts.c": "c", 4 | "functional": "c", 5 | "exception": "c", 6 | "stack": "c", 7 | "variant": "c", 8 | "stdarg.h": "c", 9 | "push.c": "c", 10 | "cmath": "c", 11 | "bit": "c", 12 | "*.tcc": "c", 13 | "complex": "c", 14 | "random": "c", 15 | "config.h": "c", 16 | "hash_map": "c", 17 | "deque": "c", 18 | "list": "c", 19 | "string": "c", 20 | "vector": "c", 21 | "valarray": "c", 22 | "typeinfo": "cpp", 23 | "*.rh": "cpp", 24 | "memory_resource": "cpp", 25 | "*.inc": "c", 26 | "iterator": "c", 27 | "new": "c" 28 | } 29 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT/X Consortium License 2 | 3 | © 2006-2019 Anselm R Garbe 4 | © 2006-2009 Jukka Salmi 5 | © 2006-2007 Sander van Dijk 6 | © 2007-2011 Peter Hartlich 7 | © 2007-2009 Szabolcs Nagy 8 | © 2007-2009 Christof Musik 9 | © 2007-2009 Premysl Hruby 10 | © 2007-2008 Enno Gottox Boland 11 | © 2008 Martin Hurton 12 | © 2008 Neale Pickett 13 | © 2009 Mate Nagy 14 | © 2010-2016 Hiltjo Posthuma 15 | © 2010-2012 Connor Lane Smith 16 | © 2011 Christoph Lohmann <20h@r-36.net> 17 | © 2015-2016 Quentin Rameau 18 | © 2015-2016 Eric Pruitt 19 | © 2016-2017 Markus Teich 20 | © 2019-2022 paperbenni 21 | 22 | Permission is hereby granted, free of charge, to any person obtaining a 23 | copy of this software and associated documentation files (the "Software"), 24 | to deal in the Software without restriction, including without limitation 25 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 26 | and/or sell copies of the Software, and to permit persons to whom the 27 | Software is furnished to do so, subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in 30 | all copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 35 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 37 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 38 | DEALINGS IN THE SOFTWARE. 39 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # instantWM - window manager for instantOS 2 | # See LICENSE file for copyright and license details. 3 | 4 | include config.mk 5 | 6 | SRC = drw.c instantwm.c layouts.c util.c 7 | OBJ = ${SRC:.c=.o} 8 | 9 | .PHONY: all 10 | all: instantwm 11 | 12 | .c.o: 13 | ${CC} -c ${CFLAGS} $< 14 | 15 | ${OBJ}: config.h config.mk 16 | 17 | config.h: 18 | cp config.def.h $@ 19 | 20 | instantwm: ${OBJ} 21 | ${CC} -o $@ ${OBJ} ${LDFLAGS} 22 | 23 | .PHONY: clean 24 | clean: 25 | rm -f instantwm ${OBJ} instantwm-${CMS_VERSION}.tar.gz 26 | 27 | .PHONY: dist 28 | dist: clean 29 | tar --transform 's|^|instantwm-${CMS_VERSION}/|' \ 30 | -czf instantwm-${CMS_VERSION}.tar.gz \ 31 | LICENSE Makefile README.md config.def.h config.mk\ 32 | instantwm.1 drw.h util.h ${SRC} 33 | 34 | .PHONY: install 35 | install: all 36 | install -d ${DESTDIR}{${PREFIX}/bin,/usr/share/xsessions,${MANPREFIX}/man1} 37 | install -m 755 -s instantwm ${DESTDIR}${PREFIX}/bin/ 38 | install -Dm 755 instantwmctrl.sh ${DESTDIR}${PREFIX}/bin/instantwmctrl 39 | ln -sf ${DESTDIR}${PREFIX}/bin/instantwmctrl ${DESTDIR}${PREFIX}/bin/instantwmctl 40 | install -m 644 instantwm.1 ${DESTDIR}${MANPREFIX}/man1/ 41 | sed -i 's/VERSION/${VERSION}/g' ${DESTDIR}${MANPREFIX}/man1/instantwm.1 42 | install -m 644 instantwm.desktop ${DESTDIR}/usr/share/xsessions 43 | install -Dm 644 instantwm.desktop ${DESTDIR}/usr/share/xsessions/default.desktop 44 | install -m 755 startinstantos ${DESTDIR}${PREFIX}/bin/ 45 | 46 | .PHONY: uninstall 47 | uninstall: 48 | rm -f ${DESTDIR}${PREFIX}/bin/instantwm\ 49 | ${DESTDIR}${PREFIX}/bin/instantwmctrl\ 50 | ${DESTDIR}${PREFIX}/bin/instantwmctl\ 51 | ${DESTDIR}${MANPREFIX}/man1/instantwm.1\ 52 | ${DESTDIR}${PREFIX}/bin/startinstantos\ 53 | ${DESTDIR}/usr/share/xsessions/instantwm.desktop\ 54 | ${DESTDIR}/usr/share/xsessions/default.desktop 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

instantWM

3 |

Window manager for instantOS

4 | 5 |
6 | 7 | instantWM the window manager of instantOS. 8 | 9 | ![img](https://github.com/instantOS/instantLOGO/blob/main/screeenshots/screenshot1.png) 10 | 11 | ## Installation 12 | 13 | It is preinstalled on instantOS. 14 | You can manually install the git build at your own risk by cloning the repo and then running build.sh, 15 | however you'll likely be missing a lot of other tools if you're not on instantOS. 16 | It is not recommended to use instantWM with other distributions. 17 | 18 | ```sh 19 | git clone --depth=1 https://github.com/instantOS/instantWM.git 20 | cd instantWM 21 | ./build.sh 22 | ``` 23 | 24 | [Download latest release](https://github.com/instantOS/instantWM/releases/download/beta2/instantwm.pkg.tar.xz) 25 | 26 | ## [Documentation](https://instantos.io/documentation) 27 | 28 | Documentation for instantWM can be found in the general documentation for 29 | instantOS and the instructional screencasts. It is not described in this 30 | README 31 | 32 | ## Features 33 | 34 | This is just a quick list of some features. For a full list and explanation, 35 | please refer to the documentation. 36 | 37 | - General 38 | * hybrid-wm: tiling and floating mode 39 | * Keyboard and Mouse based workflows 40 | * start menu 41 | * desktop bindings 42 | * full multi monitor support 43 | * tag system 44 | * overview mode 45 | * overlays 46 | - Graphical Features 47 | * Animations 48 | * Hover indicators 49 | * Status markup 50 | * color indicators for sticky windows, tag status etc. 51 | - Mouse support 52 | * Drag windows by grabbing the title 53 | * Drag windows onto other tags 54 | * Rio-like drawing feature 55 | 56 | ## TODO 57 | 58 | - [ ] look at if hack to fix rendering locking up on unknown characters is still needed 59 | 60 | 61 | ## Background information 62 | 63 | instantWM is a dwm fork, but contains less than 40% original dwm code. Most of 64 | the changed and added code is completely original which means there are no 65 | patches replicating the behaviour for dwm. It also makes instantWM incompatible 66 | with dwm patches. Why go this route? Why not just use dwm patches? The 67 | features patches introduce are by nature completely isolated. They have no way 68 | of knowing what else is applied to the WM and therefore are limited in their 69 | usage of other parts of the WM. Not relying on patches enables huge amounts of 70 | freedom. Take for instance sticky windows. They are a simple concept, but need 71 | a few checks in some places that adjust behaviour based on wether a window is 72 | sticky or not. A patch can only apply this to code present in the barren 73 | vanilla version. Other examples of this include animations and overlays or 74 | scratchpads. Most features weren't available as patches anyway. instantWM has 75 | different goals than dwm. It prioritizes stability, speed and features over 76 | lines of code. It aims to have excellent mouse and touch screen support. It 77 | contains graphical features like animations and hover indicators that make it 78 | look more appealing. It is meant to be used as is. instantOS has every feature 79 | that a desktop enviroment has or offers a replacement and instantWM closely 80 | follows this "just works" approach and in many ways goes beyond the 81 | capabilities of a desktop environment. This makes it a possible choice for new 82 | or casual users that cannot be bothered to learn C, vim, git, bash and loads of 83 | other stuff just to do their email. 84 | 85 | ### instantOS is still in early beta, contributions always welcome 86 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # compile and install instantWM 4 | 5 | SUPERTOOL="sudo" 6 | if [[ -x /usr/bin/doas ]] && [[ -s /etc/doas.conf ]] ; then 7 | SUPERTOOL="doas" 8 | fi 9 | 10 | make clean &>/dev/null 11 | 12 | if [ -z "$2" ]; then 13 | mv config.h "$(mktemp --tmpdir instantwmcfg_XXXX.h)" &>/dev/null && 14 | echo "Existing config.h moved to /tmp/" 1>&2 15 | $SUPERTOOL make install 16 | fi 17 | -------------------------------------------------------------------------------- /config.def.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include "instantwm.h" 4 | 5 | /* appearance */ 6 | static const unsigned int borderpx = 3; /* border pixel of windows */ 7 | static const unsigned int snap = 32; /* snap pixel */ 8 | static const unsigned int startmenusize = 30; /* snap pixel */ 9 | static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ 10 | static const unsigned int systrayspacing = 0; /* systray spacing */ 11 | static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ 12 | static const int showsystray = 1; /* 0 means no systray */ 13 | static const int showbar = 1; /* 0 means no bar */ 14 | static const int topbar = 1; /* 0 means bottom bar */ 15 | static const char *fonts[] = {"Inter-Regular:size=12", "Fira Code Nerd Font:size=12"}; 16 | 17 | static int barheight; 18 | static char xresourcesfont[30]; 19 | 20 | 21 | static char col_bg[] = "#121212"; 22 | static char col_text[] = "#DFDFDF"; 23 | static char col_black[] = "#000000"; 24 | 25 | static char col_bg_accent[] = "#384252"; 26 | static char col_bg_accent_hover[] = "#4C5564"; 27 | static char col_bg_hover[] = "#1C1C1C"; 28 | 29 | static char col_light_blue[] = "#89B3F7"; 30 | static char col_light_blue_hover[] = "#a1c2f9"; 31 | static char col_blue[] = "#536DFE"; 32 | static char col_blue_hover[] = "#758afe"; 33 | 34 | 35 | static char col_light_green[] = "#81c995"; 36 | static char col_light_green_hover[] = "#99d3aa"; 37 | static char col_green[] = "#1e8e3e"; 38 | static char col_green_hover[] = "#4ba465"; 39 | 40 | static char col_light_yellow[] = "#fdd663"; 41 | static char col_light_yellow_hover[] = "#fddd82"; 42 | static char col_yellow[] = "#f9ab00"; 43 | static char col_yellow_hover[] = "#f9bb33"; 44 | 45 | static char col_light_red[] = "#f28b82"; 46 | static char col_light_red_hover[] = "#f4a19a"; 47 | static char col_red[] = "#d93025"; 48 | static char col_red_hover[] = "#e05951"; 49 | 50 | static const char *tagcolors[2][5][3] = { 51 | [SchemeNoHover] = { 52 | [SchemeTagInactive] = { 53 | [ColFg] = col_text, 54 | [ColBg] = col_bg, 55 | [ColDetail] = col_bg, 56 | }, 57 | [SchemeTagFilled] = { 58 | [ColFg] = col_text, 59 | [ColBg] = col_bg_accent, 60 | [ColDetail] = col_light_blue, 61 | }, 62 | [SchemeTagFocus] = { 63 | [ColFg] = col_black, 64 | [ColBg] = col_light_green, 65 | [ColDetail] = col_green, 66 | }, 67 | [SchemeTagNoFocus] = { 68 | [ColFg] = col_black, 69 | [ColBg] = col_light_yellow, 70 | [ColDetail] = col_yellow, 71 | }, 72 | [SchemeTagEmpty] = { 73 | [ColFg] = col_black, 74 | [ColBg] = col_light_red, 75 | [ColDetail] = col_red, 76 | } 77 | }, 78 | [SchemeHover] = { 79 | [SchemeTagInactive] = { 80 | [ColFg] = col_text, 81 | [ColBg] = col_bg_hover, 82 | [ColDetail] = col_bg, 83 | }, 84 | [SchemeTagFilled] = { 85 | [ColFg] = col_text, 86 | [ColBg] = col_bg_accent_hover, 87 | [ColDetail] = col_light_blue_hover, 88 | }, 89 | [SchemeTagFocus] = { 90 | [ColFg] = col_black, 91 | [ColBg] = col_light_green_hover, 92 | [ColDetail] = col_green_hover, 93 | }, 94 | [SchemeTagNoFocus] = { 95 | [ColFg] = col_black, 96 | [ColBg] = col_light_yellow_hover, 97 | [ColDetail] = col_yellow_hover, 98 | }, 99 | [SchemeTagEmpty] = { 100 | [ColFg] = col_black, 101 | [ColBg] = col_light_red_hover, 102 | [ColDetail] = col_red_hover, 103 | } 104 | } 105 | }; 106 | 107 | static const char *windowcolors[2][7][3] = { 108 | [SchemeNoHover] = { 109 | [SchemeWinFocus] = { 110 | [ColFg] = col_text, 111 | [ColBg] = col_bg_accent, 112 | [ColDetail] = col_light_blue, 113 | }, 114 | [SchemeWinNormal] = { 115 | [ColFg] = col_text, 116 | [ColBg] = col_bg, 117 | [ColDetail] = col_bg, 118 | }, 119 | [SchemeWinMinimized] = { 120 | [ ColFg ] = col_bg_accent, 121 | [ ColBg ] = col_bg, 122 | [ ColDetail ] = col_bg, 123 | }, 124 | [SchemeWinSticky] = { 125 | [ ColFg ] = col_black, 126 | [ ColBg ] = col_light_yellow, 127 | [ ColDetail ] = col_yellow, 128 | }, 129 | [ SchemeWinStickyFocus ] = { 130 | [ ColFg ] = col_black, 131 | [ ColBg ] = col_light_green, 132 | [ ColDetail ] = col_green 133 | }, 134 | [SchemeWinOverlay] = { 135 | [ ColFg ] = col_black, 136 | [ ColBg ] = col_light_yellow, 137 | [ ColDetail ] = col_yellow, 138 | }, 139 | [SchemeWinOverlayFocus] = { 140 | [ ColFg ] = col_black, 141 | [ ColBg ] = col_light_green, 142 | [ ColDetail ] = col_green, 143 | }, 144 | }, 145 | //TODO: different hover colors 146 | [SchemeHover] = { 147 | [SchemeWinFocus] = { 148 | [ColFg] = col_text, 149 | [ColBg] = col_bg_accent_hover, 150 | [ColDetail] = col_light_blue_hover, 151 | }, 152 | [SchemeWinNormal] = { 153 | [ColFg] = col_text, 154 | [ColBg] = col_bg_hover, 155 | [ColDetail] = col_bg_hover, 156 | }, 157 | [SchemeWinMinimized] = { 158 | [ ColFg ] = col_bg_accent_hover, 159 | [ ColBg ] = col_bg, 160 | [ ColDetail ] = col_bg, 161 | }, 162 | [SchemeWinSticky] = { 163 | [ ColFg ] = col_black, 164 | [ ColBg ] = col_light_yellow_hover, 165 | [ ColDetail ] = col_yellow_hover, 166 | }, 167 | [ SchemeWinStickyFocus ] = { 168 | [ ColFg ] = col_black, 169 | [ ColBg ] = col_light_green_hover, 170 | [ ColDetail ] = col_green_hover 171 | }, 172 | [SchemeWinOverlay] = { 173 | [ ColFg ] = col_black, 174 | [ ColBg ] = col_light_yellow_hover, 175 | [ ColDetail ] = col_yellow_hover, 176 | }, 177 | [SchemeWinOverlayFocus] = { 178 | [ ColFg ] = col_black, 179 | [ ColBg ] = col_light_green_hover, 180 | [ ColDetail ] = col_green_hover, 181 | }, 182 | } 183 | }; 184 | 185 | static const char *closebuttoncolors[2][3][3] = { 186 | [SchemeNoHover] = { 187 | [ SchemeCloseNormal ] = { 188 | [ColFg] = col_text, 189 | [ColBg] = col_light_red, 190 | [ColDetail] = col_red, 191 | }, 192 | [ SchemeCloseLocked ] = { 193 | [ ColFg ] = col_text, 194 | [ ColBg ] = col_light_yellow, 195 | [ ColDetail ] = col_yellow 196 | }, 197 | [ SchemeCloseFullscreen ] = { 198 | [ColFg] = col_text, 199 | [ColBg] = col_light_red, 200 | [ColDetail] = col_red, 201 | }, 202 | }, 203 | [ SchemeHover ] = { 204 | [ SchemeCloseNormal ] = { 205 | [ColFg] = col_text, 206 | [ColBg] = col_light_red_hover, 207 | [ColDetail] = col_red_hover, 208 | }, 209 | [ SchemeCloseLocked ] = { 210 | [ ColFg ] = col_text, 211 | [ ColBg ] = col_light_yellow_hover, 212 | [ ColDetail ] = col_yellow_hover 213 | }, 214 | [ SchemeCloseFullscreen ] = { 215 | [ColFg] = col_text, 216 | [ColBg] = col_light_red_hover, 217 | [ColDetail] = col_red_hover, 218 | }, 219 | } 220 | }; 221 | 222 | static const char *bordercolors[] = { 223 | [ SchemeBorderNormal ] = col_bg_accent, 224 | [ SchemeBorderTileFocus ] = col_light_blue, 225 | [ SchemeBorderFloatFocus ] = col_light_green, 226 | [ SchemeBorderSnap ] = col_light_yellow 227 | }; 228 | 229 | static const char *statusbarcolors[] = { 230 | [ ColFg ] = col_text, 231 | [ ColBg ] = col_bg, 232 | [ ColDetail ] = col_bg 233 | }; 234 | 235 | SchemePref schemehovertypes[] = { 236 | { "hover", SchemeHover }, 237 | { "nohover", SchemeNoHover } 238 | }; 239 | 240 | SchemePref schemewindowtypes[] = { 241 | {"normal", SchemeWinNormal}, 242 | {"minimized", SchemeWinMinimized}, 243 | {"sticky", SchemeWinSticky}, 244 | {"focus", SchemeWinFocus}, 245 | {"stickyfocus", SchemeWinStickyFocus}, 246 | {"overlay", SchemeWinOverlay}, 247 | {"overlayfocus", SchemeWinOverlayFocus}, 248 | }; 249 | 250 | SchemePref schemetagtypes[] = { 251 | {"inactive", SchemeTagInactive}, 252 | {"filled", SchemeTagFilled}, 253 | {"focus", SchemeTagFocus}, 254 | {"nofocus", SchemeTagNoFocus}, 255 | {"empty", SchemeTagEmpty}, 256 | }; 257 | 258 | SchemePref schemeclosetypes[] = { 259 | {"normal", SchemeCloseNormal}, 260 | {"locked", SchemeCloseLocked}, 261 | {"fullscreen", SchemeCloseFullscreen}, 262 | }; 263 | 264 | SchemePref schemecolortypes[] = { 265 | {"fg", ColFg}, 266 | {"bg", ColBg}, 267 | {"detail", ColDetail}, 268 | }; 269 | 270 | 271 | /* tagging */ 272 | #define MAX_TAGLEN 16 273 | static const char *tags_default[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "s"}; 274 | static char tags[][MAX_TAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "s" }; 275 | /* ffox, programming1, term, music, steam, folder, play icon, document, message */ 276 | static const char *tagsalt[] = { "", "{}", "$", "", "", "", "", "", "" }; 277 | 278 | static const char scratchpadname[] = "instantscratchpad"; 279 | 280 | static const char *upvol[] = {"/usr/share/instantassist/utils/p.sh", "+", NULL}; 281 | static const char *downvol[] = {"/usr/share/instantassist/utils/p.sh", "-", NULL}; 282 | static const char *mutevol[] = {"/usr/share/instantassist/utils/p.sh", "m", NULL}; 283 | 284 | static const char *upbright[] = {"/usr/share/instantassist/utils/b.sh", "+", NULL}; 285 | static const char *downbright[] = {"/usr/share/instantassist/utils/b.sh", "-", NULL}; 286 | 287 | static const Rule rules[] = { 288 | /* xprop(1): 289 | * WM_CLASS(STRING) = instance, class 290 | * WM_NAME(STRING) = title 291 | */ 292 | /* class instance title tags mask isfloating monitor */ 293 | {"Pavucontrol", NULL, NULL, 0, 1, -1}, 294 | {"Onboard", NULL, NULL, 0, 1, -1}, 295 | {"floatmenu", NULL, NULL, 0, 1, -1}, 296 | {"Welcome.py", NULL, NULL, 0, 1, -1}, 297 | {"Pamac-installer", NULL, NULL, 0, 1, -1}, 298 | {"xpad", NULL, NULL, 0, 1, -1}, 299 | {"Guake", NULL, NULL, 0, 1, -1}, 300 | {"instantfloat", NULL, NULL, 0, 2, -1}, 301 | {scratchpadname, NULL, NULL, 0, 4, -1}, 302 | {"kdeconnect.daemon", NULL, NULL, 0, 3, -1}, 303 | {"Panther", NULL, NULL, 0, 3, -1}, 304 | {"org-wellkord-globonote-Main", NULL, NULL, 0, 1, -1}, 305 | {"Peek", NULL, NULL, 0, 1, -1}, 306 | {"ROX-Filer", NULL, NULL, 0, 0, -1}, 307 | }; 308 | 309 | /* layout(s) */ 310 | static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ 311 | static const int nmaster = 1; /* number of clients in master area */ 312 | static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ 313 | static const int decorhints = 1; /* 1 means respect decoration hints */ 314 | 315 | static const Layout layouts[] = { 316 | /* symbol arrange function */ 317 | { "+", tile }, /* first entry is default */ 318 | { "#", grid }, 319 | { "-", NULL }, /* no layout function means floating behavior */ 320 | { "[M]", monocle }, 321 | { "|||", tcl }, 322 | { "H[]", deck }, 323 | { "O", overviewlayout }, 324 | { "TTT", bstack }, 325 | { "===", bstackhoriz }, 326 | { NULL, NULL }, 327 | }; 328 | 329 | /* key definitions */ 330 | #define MODKEY Mod4Mask 331 | #define TAGKEYS(KEY, TAG) \ 332 | {MODKEY, KEY, view, {.ui = 1 << TAG}}, \ 333 | {MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ 334 | {MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \ 335 | {MODKEY|Mod1Mask, KEY, followtag, {.ui = 1 << TAG}}, \ 336 | {MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, \ 337 | {MODKEY|Mod1Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG}}, 338 | 339 | 340 | #define SHCMD(cmd) \ 341 | { \ 342 | .v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } \ 343 | } 344 | 345 | /* commands */ 346 | static char instantmenumon[2] = "0"; /* component of instantmenucmd, manipulated in spawn() */ 347 | static const char *instantmenucmd[] = {"instantmenu_run", NULL}; 348 | static const char *clipmenucmd[] = {"instantclipmenu", NULL}; 349 | static const char *smartcmd[] = {"instantmenu_smartrun", NULL}; 350 | static const char *instantmenustcmd[] = {"instantmenu_run_st", NULL}; 351 | static const char *termcmd[] = {".config/instantos/default/terminal", NULL}; 352 | static const char *termscratchcmd[] = {".config/instantos/default/terminal", "-c", scratchpadname, NULL}; 353 | static const char *quickmenucmd[] = {"quickmenu", NULL}; 354 | static const char *instantassistcmd[] = {"instantassist", NULL}; 355 | static const char *instantrepeatcmd[] = {"instantrepeat", NULL}; 356 | static const char *instantpacmancmd[] = {"instantpacman", NULL}; 357 | static const char *instantsharecmd[] = {"instantshare", "snap", NULL}; 358 | static const char *nautiluscmd[] = {".config/instantos/default/filemanager", NULL}; 359 | static const char *slockcmd[] = {".config/instantos/default/lockscreen", NULL}; 360 | static const char *onekeylock[] = {"ilock", "-o", NULL}; 361 | static const char *langswitchcmd[] = {"ilayout", NULL}; 362 | static const char *oslockcmd[] = {"instantlock", "-o", NULL}; 363 | static const char *helpcmd[] = {"instanthotkeys", "gui", NULL}; 364 | static const char *searchcmd[] = {"instantsearch", NULL}; 365 | static const char *keylayoutswitchcmd[] = {"instantkeyswitch", NULL}; 366 | static const char *iswitchcmd[] = {"iswitch", NULL}; 367 | static const char *instantswitchcmd[] = {"rofi", "-show", "window", "-kb-row-down", "Alt+Tab,Down", "-kb-row-up", "Alt+Ctrl+Tab,Up", "-kb-accept-entry", "!Alt_L,!Alt+Tab,Return", "-me-select-entry", "", "-me-accept-entry", "MousePrimary", NULL}; 368 | static const char *caretinstantswitchcmd[] = {"rofi", "-show", "window", "-kb-row-down", "Alt+Tab,Down", "-kb-row-up", "Alt+Ctrl+Tab,Up", "-kb-accept-entry", "!Alt_L,!Alt+Tab,Return", "-me-select-entry", "", "-me-accept-entry", "MousePrimary", "-theme", "/usr/share/instantdotfiles/rootconfig/rofi/appmenu.rasi", NULL}; 369 | static const char *instantskippycmd[] = {"instantskippy", NULL}; 370 | static const char *onboardcmd[] = {"onboard", NULL}; 371 | static const char *instantshutdowncmd[] = {"instantshutdown", NULL}; 372 | static const char *systemmonitorcmd[] = {".config/instantos/default/systemmonitor", NULL}; 373 | static const char *notifycmd[] = {"instantnotify", NULL}; 374 | static const char *rangercmd[] = { ".config/instantos/default/termfilemanager", NULL }; 375 | static const char *panther[] = { ".config/instantos/default/appmenu", NULL}; 376 | static const char *controlcentercmd[] = { "instantsettings", NULL}; 377 | static const char *displaycmd[] = { "instantdisper", NULL}; 378 | static const char *pavucontrol[] = { "pavucontrol", NULL}; 379 | static const char *instantsettings[] = { "instantsettings", NULL}; 380 | // static const char *clickcmd[] = { "autoclicker", NULL }; 381 | static const char *codecmd[] = { "instantutils open graphicaleditor", NULL }; 382 | static const char *startmenucmd[] = { "instantstartmenu", NULL }; 383 | 384 | static const char *scrotcmd[] = { "/usr/share/instantassist/assists/s/s.sh", NULL }; 385 | static const char *fscrotcmd[] = { "/usr/share/instantassist/assists/s/m.sh", NULL }; 386 | static const char *clipscrotcmd[] = { "/usr/share/instantassist/assists/s/c.sh", NULL }; 387 | static const char *fclipscrotcmd[] = { "/usr/share/instantassist/assists/s/f.sh", NULL }; 388 | 389 | static const char *firefoxcmd[] = { ".config/instantos/default/browser", NULL }; 390 | static const char *editorcmd[] = { ".config/instantos/default/editor", NULL }; 391 | 392 | static const char *playernext[] = { "playerctl", "next", NULL}; 393 | static const char *playerprevious[] = { "playerctl", "previous", NULL}; 394 | static const char *playerpause[] = { "playerctl", "play-pause", NULL}; 395 | static const char *spoticli[] = { "spoticli", "m", NULL}; 396 | 397 | #include "push.c" 398 | 399 | ResourcePref resources[] = { 400 | { "barheight", INTEGER, &barheight }, 401 | { "font", STRING, &xresourcesfont }, 402 | 403 | // set tag labels 404 | { "tag1", STRING, &tags[0] }, 405 | { "tag2", STRING, &tags[1] }, 406 | { "tag3", STRING, &tags[2] }, 407 | { "tag4", STRING, &tags[3] }, 408 | { "tag5", STRING, &tags[4] }, 409 | { "tag6", STRING, &tags[5] }, 410 | { "tag7", STRING, &tags[6] }, 411 | { "tag8", STRING, &tags[7] }, 412 | { "tag9", STRING, &tags[8] }, 413 | 414 | }; 415 | 416 | // instantwmctrl commands 417 | static Xcommand commands[] = { 418 | /* signum function default argument arg handler*/ 419 | // 0 means off, 1 means toggle, 2 means on 420 | // arg handlers: 421 | // 0 no argument 422 | // 1 binary toggle 423 | // 3 tag number (bitmask) 424 | // 4 string 425 | // 5 integer 426 | { "overlay", setoverlay, {0}, 0 }, 427 | { "warpfocus", warpfocus, {0}, 0 }, 428 | { "tag", view, { .ui = 2 }, 3 }, 429 | { "animated", toggleanimated, { .ui = 2 }, 1 }, 430 | { "border", setborderwidth, { .i = borderpx }, 5 }, 431 | { "focusfollowsmouse", togglefocusfollowsmouse, { .ui = 2 }, 1 }, 432 | { "focusfollowsfloatmouse", togglefocusfollowsfloatmouse, { .ui = 2 }, 1 }, 433 | { "alttab", alttabfree, { .ui = 2 }, 1 }, 434 | { "layout", commandlayout, { .ui = 0 }, 1 }, 435 | { "prefix", commandprefix, { .ui = 1 }, 1 }, 436 | { "alttag", togglealttag, { .ui = 0 }, 1 }, 437 | { "hidetags", toggleshowtags, { .ui = 0 }, 1 }, 438 | { "specialnext", setspecialnext, { .ui = 0 }, 3 }, 439 | { "tagmon", tagmon, { .i = +1 }, 0 }, 440 | { "followmon", followmon, { .i = +1 }, 0 }, 441 | { "focusmon", focusmon, { .i = +1 }, 0 }, 442 | { "focusnmon", focusnmon, { .i = 0 }, 5 }, 443 | { "nametag", nametag, { .v = "tag" }, 4 }, 444 | { "resetnametag", resetnametag, {0}, 0 }, 445 | }; 446 | 447 | static const Key dkeys[] = { 448 | /* modifier key function argument */ 449 | {0, XK_r, spawn, {.v = rangercmd } }, 450 | {0, XK_e, spawn, {.v = editorcmd } }, 451 | {0, XK_n, spawn, {.v = nautiluscmd } }, 452 | {0, XK_space, spawn, {.v = panther} }, 453 | {0, XK_f, spawn, {.v = firefoxcmd} }, 454 | {0, XK_a, spawn, {.v = instantassistcmd} }, 455 | {0, XK_F1, spawn, {.v = helpcmd} }, 456 | {0, XK_m, spawn, {.v = spoticli} }, 457 | {0, XK_Return, spawn, {.v = termcmd} }, 458 | {0, XK_plus, spawn, {.v = upvol} }, 459 | {0, XK_minus, spawn, {.v = downvol} }, 460 | {0, XK_Tab, spawn, {.v = caretinstantswitchcmd} }, 461 | {0, XK_c, spawn, {.v = codecmd} }, 462 | {0, XK_y, spawn, {.v = smartcmd} }, 463 | {0, XK_v, spawn, {.v = quickmenucmd} }, 464 | 465 | {0, XK_h, viewtoleft, {0}}, 466 | {0, XK_l, viewtoright, {0}}, 467 | {0, XK_k, shiftview, {.i = +1 } }, 468 | {0, XK_j, shiftview, {.i = -1 } }, 469 | 470 | {0, XK_Left, viewtoleft, {0}}, 471 | {0, XK_Right, viewtoright, {0}}, 472 | {0, XK_Up, shiftview, {.i = +1 } }, 473 | {0, XK_Down, shiftview, {.i = -1 } }, 474 | 475 | {0, XK_1, view, {.ui = 1 << 0}}, 476 | {0, XK_2, view, {.ui = 1 << 1}}, 477 | {0, XK_3, view, {.ui = 1 << 2}}, 478 | {0, XK_4, view, {.ui = 1 << 3}}, 479 | {0, XK_5, view, {.ui = 1 << 4}}, 480 | {0, XK_6, view, {.ui = 1 << 5}}, 481 | {0, XK_7, view, {.ui = 1 << 6}}, 482 | {0, XK_8, view, {.ui = 1 << 7}}, 483 | {0, XK_9, view, {.ui = 1 << 8}}, 484 | 485 | }; 486 | 487 | static Key keys[] = { 488 | /* modifier key function argument */ 489 | 490 | {MODKEY|Mod1Mask, XK_j, keyresize, {.i = 0}}, 491 | {MODKEY|Mod1Mask, XK_k, keyresize, {.i = 1}}, 492 | {MODKEY|Mod1Mask, XK_l, keyresize, {.i = 2}}, 493 | {MODKEY|Mod1Mask, XK_h, keyresize, {.i = 3}}, 494 | {MODKEY|ControlMask, XK_d, distributeclients, {0}}, 495 | {MODKEY|ShiftMask, XK_d, drawwindow, {0}}, 496 | {MODKEY|ShiftMask, XK_Escape, spawn, {.v = systemmonitorcmd}}, 497 | 498 | {MODKEY, XK_r, spawn, {.v = rangercmd } }, 499 | {MODKEY|ControlMask|Mod1Mask, XK_r, redrawwin, {0} }, 500 | {MODKEY, XK_n, spawn, {.v = nautiluscmd } }, 501 | {MODKEY|ControlMask, XK_q, spawn, {.v = instantshutdowncmd } }, 502 | {MODKEY, XK_y, spawn, {.v = panther} }, 503 | {MODKEY, XK_a, spawn, {.v = instantassistcmd} }, 504 | {MODKEY|ShiftMask, XK_a, spawn, {.v = instantrepeatcmd} }, 505 | {MODKEY|ControlMask, XK_i, spawn, {.v = instantpacmancmd} }, 506 | {MODKEY|ShiftMask, XK_i, spawn, {.v = instantsharecmd} }, 507 | {MODKEY, XK_w, setoverlay, {0} }, 508 | {MODKEY|ControlMask, XK_w, createoverlay, {0} }, 509 | {MODKEY, XK_g, spawn, {.v = notifycmd} }, 510 | {MODKEY|ControlMask, XK_space, spawn, {.v = instantmenucmd}}, 511 | {MODKEY|ShiftMask, XK_v, spawn, {.v = clipmenucmd}}, 512 | {MODKEY, XK_space, spawn, {.v = smartcmd}}, 513 | {MODKEY, XK_minus, spawn, {.v = instantmenustcmd}}, 514 | {MODKEY, XK_x, spawn, {.v = instantswitchcmd}}, 515 | {Mod1Mask, XK_Tab, spawn, {.v = iswitchcmd}}, 516 | {MODKEY|Mod1Mask|ControlMask|ShiftMask, XK_Tab, alttabfree, {0}}, 517 | {MODKEY, XK_dead_circumflex, spawn, {.v = caretinstantswitchcmd}}, 518 | {MODKEY|ControlMask, XK_l, spawn, {.v = slockcmd}}, 519 | {MODKEY|ControlMask|ShiftMask, XK_l, spawn, {.v = onekeylock}}, 520 | {MODKEY|ControlMask, XK_h, hidewin, {0}}, 521 | {MODKEY|Mod1Mask|ControlMask, XK_h, unhideall, {0}}, 522 | {MODKEY|Mod1Mask|ControlMask, XK_l, spawn, {.v = langswitchcmd}}, 523 | {MODKEY, XK_Return, spawn, {.v = termcmd}}, 524 | {MODKEY, XK_v, spawn, {.v = quickmenucmd}}, 525 | {MODKEY, XK_b, togglebar, {0}}, 526 | {MODKEY, XK_j, focusstack, {.i = +1}}, 527 | {MODKEY, XK_Down, downkey, {.i = +1}}, 528 | {MODKEY|ShiftMask, XK_Down, downpress, {0}}, 529 | {MODKEY, XK_k, focusstack, {.i = -1}}, 530 | {MODKEY, XK_Up, upkey, {.i = -1}}, 531 | {MODKEY|ShiftMask, XK_Up, uppress, {0}}, 532 | {MODKEY|ControlMask, XK_j, pushdown, {0} }, 533 | {MODKEY|ControlMask, XK_k, pushup, {0} }, 534 | {MODKEY|Mod1Mask, XK_s, togglealttag, { .ui = 2 } }, 535 | {MODKEY|ShiftMask|Mod1Mask, XK_s, toggleanimated, { .ui = 2 } }, 536 | {MODKEY|ControlMask, XK_s, togglesticky, {0} }, 537 | {MODKEY|ShiftMask, XK_s, createscratchpad, {0}}, 538 | {MODKEY, XK_s, togglescratchpad, {0}}, 539 | {MODKEY|ShiftMask, XK_f, togglefakefullscreen, {0} }, 540 | {MODKEY|ControlMask, XK_f, tempfullscreen, {0} }, 541 | {MODKEY|Mod1Mask, XK_f, spawn, { .v = searchcmd } }, 542 | {MODKEY|Mod1Mask, XK_space, spawn, { .v = keylayoutswitchcmd } }, 543 | {MODKEY|ShiftMask|Mod1Mask, XK_d, toggledoubledraw, {0} }, 544 | {MODKEY|ShiftMask, XK_w, warpfocus, {0} }, 545 | {MODKEY|Mod1Mask, XK_w, centerwindow, {0} }, 546 | {MODKEY|ShiftMask|ControlMask, XK_s, toggleshowtags, { .ui = 2 } }, 547 | {MODKEY, XK_i, incnmaster, {.i = +1}}, 548 | {MODKEY, XK_d, incnmaster, {.i = -1}}, 549 | {MODKEY, XK_h, setmfact, {.f = -0.05}}, 550 | {MODKEY, XK_l, setmfact, {.f = +0.05}}, 551 | {MODKEY|ShiftMask, XK_Return, zoom, {0}}, 552 | {MODKEY, XK_Tab, lastview, {0}}, 553 | {MODKEY|ShiftMask, XK_Tab, focuslastclient, {0}}, 554 | {MODKEY|Mod1Mask, XK_Tab, followview, {0}}, 555 | {MODKEY, XK_q, shutkill, {0}}, 556 | {Mod1Mask, XK_F4, killclient, {0}}, 557 | {MODKEY, XK_F1, spawn, {.v = helpcmd}}, 558 | {MODKEY, XK_F2, toggleprefix, {0}}, 559 | {MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, 560 | {MODKEY, XK_f, setlayout, {.v = &layouts[2]}}, 561 | {MODKEY, XK_m, setlayout, {.v = &layouts[3]}}, 562 | {MODKEY|ShiftMask, XK_m, movemouse, {0}}, 563 | {MODKEY|Mod1Mask, XK_m, resizemouse, {0}}, 564 | {MODKEY, XK_c, setlayout, {.v = &layouts[1]}}, 565 | {MODKEY|ControlMask, XK_c, spawn, {.v = controlcentercmd}}, 566 | 567 | {MODKEY, XK_Left, animleft, {0}}, 568 | {MODKEY, XK_Right, animright, {0}}, 569 | 570 | {MODKEY, XK_e, overtoggle, {.ui = ~0}}, 571 | {MODKEY|ShiftMask, XK_e, fullovertoggle, {.ui = ~0}}, 572 | {MODKEY|ControlMask, XK_e, spawn, {.v = instantskippycmd} }, 573 | 574 | {MODKEY|ControlMask, XK_Left, directionfocus, {.ui = 3 }}, 575 | {MODKEY|ControlMask, XK_Right, directionfocus, {.ui = 1 }}, 576 | {MODKEY|ControlMask, XK_Up, directionfocus, {.ui = 0 }}, 577 | {MODKEY|ControlMask, XK_Down, directionfocus, {.ui = 2 }}, 578 | 579 | {MODKEY|ShiftMask|ControlMask, XK_Right, shiftview, {.i = +1 }}, 580 | {MODKEY|ShiftMask|ControlMask, XK_Left, shiftview, {.i = -1 }}, 581 | 582 | {MODKEY|Mod1Mask, XK_Left, moveleft, {0}}, 583 | {MODKEY|Mod1Mask, XK_Right, moveright, {0}}, 584 | 585 | {MODKEY|ShiftMask, XK_Left, tagtoleft, {0}}, 586 | {MODKEY|ShiftMask, XK_Right, tagtoright, {0}}, 587 | 588 | {MODKEY|ShiftMask, XK_j, moveresize, {.i = 0}}, 589 | {MODKEY|ShiftMask, XK_k, moveresize, {.i = 1}}, 590 | {MODKEY|ShiftMask, XK_l, moveresize, {.i = 2}}, 591 | {MODKEY|ShiftMask, XK_h, moveresize, {.i = 3}}, 592 | 593 | 594 | {MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, 595 | {MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, 596 | {MODKEY, XK_p, setlayout, {0}}, 597 | {MODKEY|ShiftMask, XK_p, spawn, {.v = displaycmd }}, 598 | {MODKEY|ShiftMask, XK_space, spacetoggle, {0}}, 599 | {MODKEY, XK_0, view, {.ui = ~0}}, 600 | {MODKEY|ShiftMask, XK_0, tag, {.ui = ~0}}, 601 | {MODKEY, XK_comma, focusmon, {.i = -1}}, 602 | {MODKEY, XK_period, focusmon, {.i = +1}}, 603 | {MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1}}, 604 | {MODKEY|ShiftMask, XK_period, tagmon, {.i = +1}}, 605 | {MODKEY|Mod1Mask, XK_comma, followmon, {.i = -1}}, 606 | {MODKEY|Mod1Mask, XK_period, followmon, {.i = +1}}, 607 | 608 | {MODKEY|ShiftMask|ControlMask|Mod1Mask, XK_period, desktopset, {0}}, 609 | TAGKEYS(XK_1, 0) 610 | TAGKEYS(XK_2, 1) 611 | TAGKEYS(XK_3, 2) 612 | TAGKEYS(XK_4, 3) 613 | TAGKEYS(XK_5, 4) 614 | TAGKEYS(XK_6, 5) 615 | TAGKEYS(XK_7, 6) 616 | TAGKEYS(XK_8, 7) 617 | TAGKEYS(XK_9, 8) 618 | {MODKEY|ShiftMask|ControlMask, XK_q, quit, {0}}, 619 | {0, XF86XK_MonBrightnessUp, spawn, {.v = upbright}}, 620 | {0, XF86XK_MonBrightnessDown, spawn, {.v = downbright}}, 621 | {0, XF86XK_AudioLowerVolume, spawn, {.v = downvol}}, 622 | {0, XF86XK_AudioMute, spawn, {.v = mutevol}}, 623 | {0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol}}, 624 | {0, XF86XK_AudioPlay, spawn, {.v = playerpause}}, 625 | {0, XF86XK_AudioPause, spawn, {.v = playerpause}}, 626 | {0, XF86XK_AudioNext, spawn, {.v = playernext}}, 627 | {0, XF86XK_AudioPrev, spawn, {.v = playerprevious}}, 628 | 629 | {MODKEY|ShiftMask, XK_Print, spawn, {.v = fscrotcmd}}, 630 | {MODKEY, XK_Print, spawn, {.v = scrotcmd}}, 631 | {MODKEY|ControlMask, XK_Print, spawn, {.v = clipscrotcmd}}, 632 | {MODKEY|Mod1Mask, XK_Print, spawn, {.v = fclipscrotcmd}}, 633 | 634 | { MODKEY, XK_o, winview, {0} }, 635 | 636 | }; 637 | 638 | /* button definitions */ 639 | /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ 640 | static const Button buttons[] = { 641 | /* click event mask button function argument */ 642 | { ClkLtSymbol, 0, Button1, cyclelayout, {.i = -1 } }, 643 | { ClkLtSymbol, 0, Button3, cyclelayout, {.i = +1 } }, 644 | { ClkLtSymbol, MODKEY, Button1, createoverlay, {0} }, 645 | { ClkLtSymbol, 0, Button2, setlayout, {.v = &layouts[0]} }, 646 | { ClkWinTitle, 0, Button1, dragmouse, {0} }, 647 | { ClkWinTitle, MODKEY, Button1, setoverlay, {0} }, 648 | { ClkWinTitle, MODKEY, Button3, spawn, {.v = notifycmd } }, 649 | { ClkStatusText, 0, Button3, spawn, {.v = caretinstantswitchcmd } }, 650 | { ClkWinTitle, 0, Button2, closewin, {0} }, 651 | { ClkCloseButton, 0, Button1, killclient, {0} }, 652 | { ClkCloseButton, 0, Button3, togglelocked, {0} }, 653 | { ClkWinTitle, 0, Button3, dragrightmouse, {0} }, 654 | { ClkWinTitle, 0, Button5, focusstack, {.i = +1} }, 655 | { ClkWinTitle, 0, Button4, focusstack, {.i = -1} }, 656 | { ClkWinTitle, ShiftMask, Button5, pushdown, {0} }, 657 | { ClkWinTitle, ShiftMask, Button4, pushup, {0} }, 658 | { ClkWinTitle, ControlMask, Button5, downscaleclient, {0} }, 659 | { ClkWinTitle, ControlMask, Button4, upscaleclient, {0} }, 660 | { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, 661 | { ClkStatusText, 0, Button4, spawn, {.v = upvol } }, 662 | { ClkStatusText, 0, Button5, spawn, {.v = downvol } }, 663 | { ClkStatusText, MODKEY, Button2, spawn, {.v = mutevol } }, 664 | { ClkStatusText, 0, Button1, spawn, {.v = panther } }, 665 | { ClkStatusText, MODKEY|ShiftMask, Button1, spawn, {.v = pavucontrol } }, 666 | { ClkStatusText, MODKEY|ControlMask, Button1, spawn, {.v = notifycmd } }, 667 | { ClkStatusText, MODKEY, Button1, spawn, {.v = instantsettings } }, 668 | { ClkStatusText, MODKEY, Button3, spawn, {.v = spoticli } }, 669 | { ClkStatusText, MODKEY, Button4, spawn, {.v = upbright } }, 670 | { ClkStatusText, MODKEY, Button5, spawn, {.v = downbright } }, 671 | { ClkRootWin, MODKEY, Button3, spawn, {.v = notifycmd } }, 672 | { ClkRootWin, 0, Button1, spawn, {.v = panther } }, 673 | { ClkRootWin, MODKEY, Button1, setoverlay, {0} }, 674 | { ClkRootWin, 0, Button3, spawn, {.v = smartcmd } }, 675 | { ClkRootWin, 0, Button5, showoverlay, {0} }, 676 | { ClkRootWin, 0, Button4, hideoverlay, {0} }, 677 | { ClkRootWin, 0, Button2, spawn, {.v = instantmenucmd } }, 678 | { ClkClientWin, MODKEY, Button1, movemouse, {0} }, 679 | { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, 680 | { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, 681 | { ClkClientWin, MODKEY|Mod1Mask, Button3, forceresizemouse, {0} }, 682 | { ClkClientWin, MODKEY|ShiftMask, Button3, resizeaspectmouse, {0} }, 683 | { ClkTagBar, 0, Button1, dragtag, {0} }, 684 | { ClkTagBar, 0, Button5, viewtoright, {0} }, 685 | { ClkTagBar, MODKEY, Button4, shiftview, {.i = -1 } }, 686 | { ClkTagBar, MODKEY, Button5, shiftview, {.i = +1 } }, 687 | { ClkTagBar, 0, Button4, viewtoleft, {0} }, 688 | { ClkTagBar, 0, Button3, toggleview, {0} }, 689 | { ClkTagBar, MODKEY, Button1, tag, {0} }, 690 | { ClkTagBar, Mod1Mask, Button1, followtag, {0} }, 691 | { ClkTagBar, MODKEY, Button3, toggletag, {0} }, 692 | { ClkShutDown, 0, Button1, spawn, {.v = instantshutdowncmd } }, 693 | { ClkShutDown, 0, Button3, spawn, {.v = slockcmd } }, 694 | { ClkShutDown, 0, Button2, spawn, {.v = oslockcmd } }, 695 | { ClkSideBar, 0, Button1, gesturemouse, {0} }, 696 | { ClkStartMenu, 0, Button1, spawn, {.v = startmenucmd}}, 697 | { ClkStartMenu, ShiftMask, Button1, toggleprefix, {0}}, 698 | { ClkStartMenu, 0, Button3, spawn, {.v = quickmenucmd}}, 699 | }; 700 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | # instantWM version 2 | CMS_VERSION := $(shell git describe --abbrev=5 --dirty=-dev --always --tags 2>/dev/null || echo "unknown") 3 | VERSION := "instantOS $(CMS_VERSION) - Build $(shell LANG=en_us_8859_1 date '+%a, %b %e %Y, %R:%S %z') on $(shell hostname 2>/dev/null || echo "unknown host")" 4 | 5 | # Customize below to fit your system 6 | 7 | # paths 8 | PREFIX = /usr/local 9 | MANPREFIX = ${PREFIX}/share/man 10 | 11 | X11INC = /usr/X11R6/include 12 | X11LIB = /usr/X11R6/lib 13 | 14 | # Xinerama, comment if you don't want it 15 | XINERAMALIBS = -lXinerama 16 | XINERAMAFLAGS = -DXINERAMA 17 | 18 | # freetype 19 | FREETYPELIBS = -lfontconfig -lXft 20 | FREETYPEINC = /usr/include/freetype2 21 | # OpenBSD (uncomment) 22 | #FREETYPEINC = ${X11INC}/freetype2 23 | #MANPREFIX = ${PREFIX}/man 24 | 25 | # includes and libs 26 | INCS = -I${X11INC} -I${FREETYPEINC} 27 | LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lm 28 | 29 | # flags 30 | CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 31 | #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} 32 | CFLAGS = -std=c99 -pedantic -Wall -Wunused -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} 33 | LDFLAGS = ${LIBS} 34 | 35 | # Solaris 36 | #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" 37 | #LDFLAGS = ${LIBS} 38 | 39 | # compiler and linker 40 | CC = cc 41 | -------------------------------------------------------------------------------- /drw.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "drw.h" 10 | #include "util.h" 11 | 12 | #define UTF_INVALID 0xFFFD 13 | #define UTF_SIZ 4 14 | 15 | static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 16 | static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 17 | static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; 18 | static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 19 | 20 | static long 21 | utf8decodebyte(const char c, size_t *i) 22 | { 23 | for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) 24 | if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) 25 | return (unsigned char)c & ~utfmask[*i]; 26 | return 0; 27 | } 28 | 29 | static size_t 30 | utf8validate(long *u, size_t i) 31 | { 32 | if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) 33 | *u = UTF_INVALID; 34 | for (i = 1; *u > utfmax[i]; ++i) 35 | ; 36 | return i; 37 | } 38 | 39 | static size_t 40 | utf8decode(const char *c, long *u, size_t clen) 41 | { 42 | size_t i, j, len, type; 43 | long udecoded; 44 | 45 | *u = UTF_INVALID; 46 | if (!clen) 47 | return 0; 48 | udecoded = utf8decodebyte(c[0], &len); 49 | if (!BETWEEN(len, 1, UTF_SIZ)) 50 | return 1; 51 | for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 52 | udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); 53 | if (type) 54 | return j; 55 | } 56 | if (j < len) 57 | return 0; 58 | *u = udecoded; 59 | utf8validate(u, len); 60 | 61 | return len; 62 | } 63 | 64 | Drw * 65 | drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) 66 | { 67 | Drw *drw = ecalloc(1, sizeof(Drw)); 68 | 69 | drw->dpy = dpy; 70 | drw->screen = screen; 71 | drw->root = root; 72 | drw->w = w; 73 | drw->h = h; 74 | drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); 75 | drw->gc = XCreateGC(dpy, root, 0, NULL); 76 | XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); 77 | 78 | return drw; 79 | } 80 | 81 | void 82 | drw_resize(Drw *drw, unsigned int w, unsigned int h) 83 | { 84 | if (!drw) 85 | return; 86 | 87 | drw->w = w; 88 | drw->h = h; 89 | if (drw->drawable) 90 | XFreePixmap(drw->dpy, drw->drawable); 91 | drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); 92 | } 93 | 94 | void 95 | drw_free(Drw *drw) 96 | { 97 | XFreePixmap(drw->dpy, drw->drawable); 98 | XFreeGC(drw->dpy, drw->gc); 99 | drw_fontset_free(drw->fonts); 100 | free(drw); 101 | } 102 | 103 | /* This function is an implementation detail. Library users should use 104 | * drw_fontset_create instead. 105 | */ 106 | static Fnt * 107 | xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) 108 | { 109 | Fnt *font; 110 | XftFont *xfont = NULL; 111 | FcPattern *pattern = NULL; 112 | 113 | if (fontname) { 114 | /* Using the pattern found at font->xfont->pattern does not yield the 115 | * same substitution results as using the pattern returned by 116 | * FcNameParse; using the latter results in the desired fallback 117 | * behaviour whereas the former just results in missing-character 118 | * rectangles being drawn, at least with some fonts. */ 119 | if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { 120 | fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); 121 | return NULL; 122 | } 123 | if (!(pattern = FcNameParse((FcChar8 *) fontname))) { 124 | fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); 125 | XftFontClose(drw->dpy, xfont); 126 | return NULL; 127 | } 128 | } else if (fontpattern) { 129 | if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { 130 | fprintf(stderr, "error, cannot load font from pattern.\n"); 131 | return NULL; 132 | } 133 | } else { 134 | die("no font specified."); 135 | } 136 | 137 | 138 | font = ecalloc(1, sizeof(Fnt)); 139 | font->xfont = xfont; 140 | font->pattern = pattern; 141 | font->h = xfont->ascent + xfont->descent; 142 | font->dpy = drw->dpy; 143 | 144 | return font; 145 | } 146 | 147 | static void 148 | xfont_free(Fnt *font) 149 | { 150 | if (!font) 151 | return; 152 | if (font->pattern) 153 | FcPatternDestroy(font->pattern); 154 | XftFontClose(font->dpy, font->xfont); 155 | free(font); 156 | } 157 | 158 | Fnt* 159 | drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) 160 | { 161 | Fnt *cur, *ret = NULL; 162 | size_t i; 163 | 164 | if (!drw || !fonts) 165 | return NULL; 166 | 167 | for (i = 1; i <= fontcount; i++) { 168 | if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { 169 | cur->next = ret; 170 | ret = cur; 171 | } 172 | } 173 | return (drw->fonts = ret); 174 | } 175 | 176 | void 177 | drw_fontset_free(Fnt *font) 178 | { 179 | if (font) { 180 | drw_fontset_free(font->next); 181 | xfont_free(font); 182 | } 183 | } 184 | 185 | void 186 | drw_clr_create(Drw *drw, Clr *dest, const char *clrname) 187 | { 188 | if (!drw || !dest || !clrname) 189 | return; 190 | 191 | if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), 192 | DefaultColormap(drw->dpy, drw->screen), 193 | clrname, dest)) 194 | die("error, cannot allocate color '%s'", clrname); 195 | 196 | dest->pixel |= 0xff << 24; 197 | } 198 | 199 | /* Wrapper to create color schemes. The caller has to call free(3) on the 200 | * returned color scheme when done using it. */ 201 | Clr * 202 | drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) 203 | { 204 | size_t i; 205 | Clr *ret; 206 | 207 | /* need at least two colors for a scheme */ 208 | if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) 209 | return NULL; 210 | 211 | for (i = 0; i < clrcount; i++) 212 | drw_clr_create(drw, &ret[i], clrnames[i]); 213 | return ret; 214 | } 215 | 216 | void 217 | drw_setfontset(Drw *drw, Fnt *set) 218 | { 219 | if (drw) 220 | drw->fonts = set; 221 | } 222 | 223 | void 224 | drw_setscheme(Drw *drw, Clr *scm) 225 | { 226 | if (drw) 227 | drw->scheme = scm; 228 | } 229 | 230 | void 231 | drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) 232 | { 233 | if (!drw || !drw->scheme) 234 | return; 235 | XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); 236 | if (filled) 237 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); 238 | else 239 | XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); 240 | } 241 | 242 | void 243 | drw_circ(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) 244 | { 245 | if (!drw || !drw->scheme) 246 | return; 247 | XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); 248 | if (filled) 249 | XFillArc(drw->dpy, drw->drawable, drw->gc, x, y, w, h, 0, 360*64); 250 | else 251 | XDrawArc(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1, 0, 360*64); 252 | } 253 | 254 | int 255 | drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, int rounded) 256 | { 257 | 258 | int i, ty, ellipsis_x = 0; 259 | unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; 260 | 261 | XftDraw *d = NULL; 262 | Fnt *usedfont, *curfont, *nextfont; 263 | int utf8strlen, utf8charlen, render = x || y || w || h; 264 | long utf8codepoint = 0; 265 | const char *utf8str; 266 | FcCharSet *fccharset; 267 | FcPattern *fcpattern; 268 | FcPattern *match; 269 | XftResult result; 270 | int charexists = 0, overflow = 0; 271 | /* keep track of a couple codepoints for which we have no match. */ 272 | enum { nomatches_len = 64 }; 273 | static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; 274 | static unsigned int ellipsis_width = 0; 275 | 276 | if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) 277 | return 0; 278 | 279 | if (!render) { 280 | w = invert ? invert : ~invert; 281 | } else { 282 | XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); 283 | 284 | if (rounded) { 285 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h - rounded); 286 | XSetForeground(drw->dpy, drw->gc, drw->scheme[ColDetail].pixel); 287 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y + h - rounded, w, rounded); 288 | 289 | } else { 290 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); 291 | } 292 | 293 | d = XftDrawCreate(drw->dpy, drw->drawable, 294 | DefaultVisual(drw->dpy, drw->screen), 295 | DefaultColormap(drw->dpy, drw->screen)); 296 | x += lpad; 297 | w -= lpad; 298 | } 299 | 300 | usedfont = drw->fonts; 301 | if (!ellipsis_width && render) 302 | ellipsis_width = drw_fontset_getwidth(drw, "..."); 303 | 304 | while (1) { 305 | ew = ellipsis_len = utf8strlen = 0; 306 | utf8str = text; 307 | nextfont = NULL; 308 | while (*text) { 309 | utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); 310 | while (!charexists) { 311 | for (curfont = drw->fonts; curfont; curfont = curfont->next) { 312 | charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); 313 | if (charexists) { 314 | 315 | drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); 316 | if (ew + ellipsis_width <= w) { 317 | /* keep track where the ellipsis still fits */ 318 | ellipsis_x = x + ew; 319 | ellipsis_w = w - ew; 320 | ellipsis_len = utf8strlen; 321 | } 322 | 323 | if (ew + tmpw > w) { 324 | overflow = 1; 325 | /* called from drw_fontset_getwidth_clamp(): 326 | * it wants the width AFTER the overflow 327 | */ 328 | if (!render) 329 | x += tmpw; 330 | else 331 | utf8strlen = ellipsis_len; 332 | } else if (curfont == usedfont) { 333 | 334 | utf8strlen += utf8charlen; 335 | text += utf8charlen; 336 | ew += tmpw; 337 | 338 | } else { 339 | nextfont = curfont; 340 | } 341 | break; 342 | } 343 | } 344 | if (!charexists) 345 | utf8charlen = utf8decode("a", &utf8codepoint, UTF_SIZ); 346 | } 347 | 348 | if (overflow || !charexists || nextfont) 349 | break; 350 | else 351 | charexists = 0; 352 | } 353 | 354 | if (utf8strlen) { 355 | if (render) { 356 | ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; 357 | XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], 358 | usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); 359 | } 360 | x += ew; 361 | w -= ew; 362 | } 363 | if (render && overflow) 364 | drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert, rounded); 365 | 366 | 367 | if (!*text || overflow) { 368 | break; 369 | } else if (nextfont) { 370 | charexists = 0; 371 | usedfont = nextfont; 372 | } else { 373 | //utf8codepoint = utf8decode('s', &utf8codepoint, UTF_SIZ); 374 | /* Regardless of whether or not a fallback font is found, the 375 | * character must be drawn. */ 376 | charexists = 1; 377 | 378 | for (i = 0; i < nomatches_len; ++i) { 379 | /* avoid calling XftFontMatch if we know we won't find a match */ 380 | if (utf8codepoint == nomatches.codepoint[i]) 381 | goto no_match; 382 | } 383 | 384 | 385 | fccharset = FcCharSetCreate(); 386 | FcCharSetAddChar(fccharset, utf8codepoint); 387 | 388 | if (!drw->fonts->pattern) { 389 | /* Refer to the comment in xfont_create for more information. */ 390 | die("the first font in the cache must be loaded from a font string."); 391 | } 392 | 393 | fcpattern = FcPatternDuplicate(drw->fonts->pattern); 394 | FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); 395 | FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); 396 | 397 | FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); 398 | FcDefaultSubstitute(fcpattern); 399 | match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); 400 | 401 | FcCharSetDestroy(fccharset); 402 | FcPatternDestroy(fcpattern); 403 | 404 | if (match) { 405 | usedfont = xfont_create(drw, NULL, match); 406 | if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { 407 | for (curfont = drw->fonts; curfont->next; curfont = curfont->next) 408 | ; /* NOP */ 409 | curfont->next = usedfont; 410 | } else { 411 | xfont_free(usedfont); 412 | nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; 413 | no_match: 414 | usedfont = drw->fonts; 415 | } 416 | } 417 | } 418 | } 419 | if (d) 420 | XftDrawDestroy(d); 421 | 422 | return x + (render ? w : 0); 423 | } 424 | 425 | void 426 | drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash) 427 | { 428 | if (!drw) 429 | return; 430 | 431 | /* direction=1 draws right arrow */ 432 | x = direction ? x : x + w; 433 | w = direction ? w : -w; 434 | /* slash=1 draws slash instead of arrow */ 435 | unsigned int hh = slash ? (direction ? 0 : h) : h/2; 436 | 437 | XPoint points[] = { 438 | {x , y }, 439 | {x + w, y + hh }, 440 | {x , y + h }, 441 | }; 442 | 443 | XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); 444 | XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin); 445 | } 446 | 447 | void 448 | drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) 449 | { 450 | if (!drw) 451 | return; 452 | 453 | XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); 454 | XSync(drw->dpy, False); 455 | } 456 | 457 | unsigned int 458 | drw_fontset_getwidth(Drw *drw, const char *text) 459 | { 460 | if (!drw || !drw->fonts || !text) 461 | return 0; 462 | return drw_text(drw, 0, 0, 0, 0, 0, text, 0, 0); 463 | } 464 | 465 | unsigned int 466 | drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) 467 | { 468 | unsigned int tmp = 0; 469 | if (drw && drw->fonts && text && n) 470 | tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n, 0); 471 | return MIN(n, tmp); 472 | } 473 | 474 | void 475 | drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) 476 | { 477 | XGlyphInfo ext; 478 | 479 | if (!font || !text) 480 | return; 481 | 482 | XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); 483 | if (w) 484 | *w = ext.xOff; 485 | if (h) 486 | *h = font->h; 487 | } 488 | 489 | Cur * 490 | drw_cur_create(Drw *drw, int shape) 491 | { 492 | Cur *cur; 493 | 494 | if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) 495 | return NULL; 496 | 497 | cur->cursor = XCreateFontCursor(drw->dpy, shape); 498 | 499 | return cur; 500 | } 501 | 502 | void 503 | drw_cur_free(Drw *drw, Cur *cursor) 504 | { 505 | if (!cursor) 506 | return; 507 | 508 | XFreeCursor(drw->dpy, cursor->cursor); 509 | free(cursor); 510 | } 511 | -------------------------------------------------------------------------------- /drw.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | typedef struct { 6 | Cursor cursor; 7 | } Cur; 8 | 9 | typedef struct { 10 | char *text; 11 | char *bg; 12 | char *detail; 13 | } ColorScheme; 14 | 15 | typedef struct Fnt { 16 | Display *dpy; 17 | unsigned int h; 18 | XftFont *xfont; 19 | FcPattern *pattern; 20 | struct Fnt *next; 21 | } Fnt; 22 | 23 | enum { ColFg, ColBg, ColDetail, ColLast }; /* Clr scheme index */ 24 | typedef XftColor Clr; 25 | 26 | typedef struct { 27 | unsigned int w, h; 28 | Display *dpy; 29 | int screen; 30 | Window root; 31 | Drawable drawable; 32 | GC gc; 33 | Clr *scheme; 34 | Fnt *fonts; 35 | } Drw; 36 | 37 | /* Drawable abstraction */ 38 | Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); 39 | void drw_resize(Drw *drw, unsigned int w, unsigned int h); 40 | void drw_free(Drw *drw); 41 | 42 | /* Fnt abstraction */ 43 | Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); 44 | void drw_fontset_free(Fnt* set); 45 | unsigned int drw_fontset_getwidth(Drw *drw, const char *text); 46 | unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); 47 | void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); 48 | 49 | /* Colorscheme abstraction */ 50 | void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); 51 | Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); 52 | 53 | /* Cursor abstraction */ 54 | Cur *drw_cur_create(Drw *drw, int shape); 55 | void drw_cur_free(Drw *drw, Cur *cursor); 56 | 57 | /* Drawing context manipulation */ 58 | void drw_setfontset(Drw *drw, Fnt *set); 59 | void drw_setscheme(Drw *drw, Clr *scm); 60 | 61 | /* Drawing functions */ 62 | void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); 63 | void drw_circ(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); 64 | int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, int rounded); 65 | void drw_arrow(Drw* drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash); 66 | 67 | /* Map functions */ 68 | void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); 69 | -------------------------------------------------------------------------------- /instantwm.1: -------------------------------------------------------------------------------- 1 | .TH IWM 1 IWM\-VERSION 2 | .SH NAME 3 | instantWM \- Window manager for instantOS 4 | .SH SYNOPSIS 5 | .B instantwm 6 | .RB [ \-v ] 7 | .SH DESCRIPTION 8 | instantWM is the window manager in use on the Linux Distribution instantOS. It 9 | is a hybrid WM meaning it has an equal focus on tiling and floating and can 10 | freely mix between the two. Tiling works in a similar way to dwm. Windows are 11 | arranged by selecting from a set of rules called layouts. The floating 12 | functionality is somewhat similar to conventional desktop enviroments but 13 | brings a couple of own ideas to the table. instantWM started out as a dwm fork 14 | and while some parts of the dwm code remain, it has changed drastically and 15 | does a lot of things different. 16 | .P 17 | In tiled layouts windows are managed in a master and stacking area. The master 18 | area on the left contains one window by default, and the stacking area on the 19 | right contains all other windows. The number of master area windows can be 20 | adjusted from zero to an arbitrary number. In monocle layout all windows are 21 | maximised to the screen size. In floating layout windows can be resized and 22 | moved freely. Dialog windows are always managed floating, regardless of the 23 | layout applied. 24 | .P 25 | Windows are grouped by tags. Each window can be tagged with one or multiple 26 | tags. Selecting certain tags displays all windows with these tags. 27 | .P 28 | Each screen contains a small status bar which displays all available tags, the 29 | layout, the title of the focused window, and the text read from the root window 30 | name property, if the screen is focused. A floating window is indicated with an 31 | empty square and a maximised floating window is indicated with a filled square 32 | before the windows title. The selected tags are indicated with a different 33 | color. The tags of the focused window are indicated with a filled square in the 34 | top left corner. The tags which are applied to one or more windows are 35 | indicated with an empty square in the top left corner. 36 | .P 37 | instantWM draws a small border around windows to indicate the focus state. 38 | .SH OPTIONS 39 | .TP 40 | .B \-v 41 | prints version information to stderr, then exits. 42 | .SH USAGE 43 | .SS Status bar 44 | .TP 45 | .B X root window name 46 | is read and displayed in the status text area. It can be set with the 47 | .BR xsetroot (1) 48 | command. 49 | .TP 50 | .B Button1 51 | click on a tag label to display all windows with that tag, click on the layout 52 | label toggles between tiled and floating layout. 53 | .TP 54 | .B Button3 55 | click on a tag label adds/removes all windows with that tag to/from the view. 56 | .TP 57 | .B Mod1\-Button1 58 | click on a tag label applies that tag to the focused window. 59 | .TP 60 | .B Mod1\-Button3 61 | click on a tag label adds/removes that tag to/from the focused window. 62 | .SS Keyboard commands 63 | .TP 64 | .B Mod1\-Shift\-Return 65 | Start 66 | .BR st(1). 67 | .TP 68 | .B Mod1\-p 69 | Spawn 70 | .BR instantmenu(1) 71 | for launching other programs. 72 | .TP 73 | .B Mod1\-, 74 | Focus previous screen, if any. 75 | .TP 76 | .B Mod1\-. 77 | Focus next screen, if any. 78 | .TP 79 | .B Mod1\-Shift\-, 80 | Send focused window to previous screen, if any. 81 | .TP 82 | .B Mod1\-Shift\-. 83 | Send focused window to next screen, if any. 84 | .TP 85 | .B Mod1\-b 86 | Toggles bar on and off. 87 | .TP 88 | .B Mod1\-t 89 | Sets tiled layout. 90 | .TP 91 | .B Mod1\-f 92 | Sets floating layout. 93 | .TP 94 | .B Mod1\-m 95 | Sets monocle layout. 96 | .TP 97 | .B Mod1\-space 98 | Toggles between current and previous layout. 99 | .TP 100 | .B Mod1\-Control\-, 101 | Cycles backwards in layout list. 102 | .TP 103 | .B Mod1\-Control\-. 104 | Cycles forwards in layout list. 105 | .TP 106 | .B Mod1\-j 107 | Focus next window. 108 | .TP 109 | .B Mod1\-k 110 | Focus previous window. 111 | .TP 112 | .B Mod1\-i 113 | Increase number of windows in master area. 114 | .TP 115 | .B Mod1\-d 116 | Decrease number of windows in master area. 117 | .TP 118 | .B Mod1\-l 119 | Increase master area size. 120 | .TP 121 | .B Mod1\-h 122 | Decrease master area size. 123 | .TP 124 | .B Mod1\-o 125 | Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. 126 | .TP 127 | .B Mod1\-Return 128 | Zooms/cycles focused window to/from master area (tiled layouts only). 129 | .TP 130 | .B Mod1\-Shift\-c 131 | Close focused window. 132 | .TP 133 | .B Mod1\-Shift\-space 134 | Toggle focused window between tiled and floating state. 135 | .TP 136 | .B Mod1\-Tab 137 | Toggles to the previously selected tags. 138 | .TP 139 | .B Mod1\-Shift\-[1..n] 140 | Apply nth tag to focused window. 141 | .TP 142 | .B Mod1\-Shift\-0 143 | Apply all tags to focused window. 144 | .TP 145 | .B Mod1\-Control\-Shift\-[1..n] 146 | Add/remove nth tag to/from focused window. 147 | .TP 148 | .B Mod1\-[1..n] 149 | View all windows with nth tag. 150 | .TP 151 | .B Mod1\-0 152 | View all windows with any tag. 153 | .TP 154 | .B Mod1\-Control\-[1..n] 155 | Add/remove all windows with nth tag to/from the view. 156 | .TP 157 | .B Mod1\-Shift\-q 158 | Quit instantWM. 159 | .SS Mouse commands 160 | .TP 161 | .B Mod1\-Button1 162 | Move focused window while dragging. Tiled windows will be toggled to the floating state. 163 | .TP 164 | .B Mod1\-Button2 165 | Toggles focused window between floating and tiled state. 166 | .TP 167 | .B Mod1\-Button3 168 | Resize focused window while dragging. Tiled windows will be toggled to the floating state. 169 | .SH CUSTOMIZATION 170 | instantWM is customized by creating a custom config.h and (re)compiling the source 171 | code. This keeps it fast, secure and simple. 172 | .SH SEE ALSO 173 | .BR instantmenu (1), 174 | .BR st (1) 175 | .SH ISSUES 176 | Java applications which use the XToolkit/XAWT backend may draw grey windows 177 | only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early 178 | JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds 179 | are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the 180 | environment variable 181 | .BR AWT_TOOLKIT=MToolkit 182 | (to use the older Motif backend instead) or running 183 | .B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D 184 | or 185 | .B wmname LG3D 186 | (to pretend that a non-reparenting window manager is running that the 187 | XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable 188 | .BR _JAVA_AWT_WM_NONREPARENTING=1 . 189 | .SH BUGS 190 | Report bugs at https://github.com/instantOS/instantWM or at any of the places listed on https://instantos.io/support 191 | -------------------------------------------------------------------------------- /instantwm.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Name=instantWM 4 | Comment=instantOS window manager 5 | Exec=startinstantos 6 | Icon=instantwm 7 | Type=XSession 8 | -------------------------------------------------------------------------------- /instantwm.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTANTWM_H 2 | #define INSTANTWM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef XINERAMA 14 | #include 15 | #endif /* XINERAMA */ 16 | 17 | #include "drw.h" 18 | 19 | 20 | /* macros */ 21 | #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) 22 | #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) 23 | #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ 24 | * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) 25 | #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) 26 | #define HIDDEN(C) ((getstate(C->win) == IconicState)) 27 | #define LENGTH(X) (sizeof X / sizeof X[0]) 28 | #define MOUSEMASK (BUTTONMASK|PointerMotionMask) 29 | #define WIDTH(X) ((X)->w + 2 * (X)->bw) 30 | #define HEIGHT(X) ((X)->h + 2 * (X)->bw) 31 | #define TAGMASK ((1 << LENGTH(tags)) - 1) 32 | #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) 33 | 34 | #define MWM_HINTS_FLAGS_FIELD 0 35 | #define MWM_HINTS_DECORATIONS_FIELD 2 36 | #define MWM_HINTS_DECORATIONS (1 << 1) 37 | #define MWM_DECOR_ALL (1 << 0) 38 | #define MWM_DECOR_BORDER (1 << 1) 39 | #define MWM_DECOR_TITLE (1 << 3) 40 | 41 | /* XEMBED messages */ 42 | #define XEMBED_EMBEDDED_NOTIFY 0 43 | #define XEMBED_WINDOW_ACTIVATE 1 44 | #define XEMBED_FOCUS_IN 4 45 | #define XEMBED_MODALITY_ON 10 46 | 47 | #define XEMBED_MAPPED (1 << 0) 48 | #define XEMBED_WINDOW_ACTIVATE 1 49 | #define XEMBED_WINDOW_DEACTIVATE 2 50 | 51 | #define VERSION_MAJOR 0 52 | #define VERSION_MINOR 0 53 | #define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR 54 | #define SYSTEM_TRAY_REQUEST_DOCK 0 55 | 56 | /* enums */ 57 | enum { CurNormal, CurResize, CurMove, CurClick, CurHor, CurVert, CurTL, CurTR, CurBL, CurBR, CurLast }; /* cursor */ 58 | /* enum { SchemeNorm, SchemeSel, SchemeHid, SchemeTags, SchemeActive, SchemeAddActive, SchemeEmpty, SchemeHover, SchemeClose, SchemeHoverTags }; /1* color schemes *1/ */ 59 | enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 60 | NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, 61 | NetWMFullscreen, NetActiveWindow, NetWMWindowType, 62 | NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetLast }; /* EWMH atoms */ 63 | enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ 64 | enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 65 | enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 66 | ClkClientWin, ClkRootWin, ClkCloseButton, ClkShutDown, ClkSideBar, ClkStartMenu, ClkLast }; /* clicks */ 67 | 68 | 69 | 70 | ////// Colorscheme enums ////// 71 | // each element has the possibility of a hover over 72 | enum { SchemeHover, SchemeNoHover, SchemeHoverLast }; 73 | // tag states 74 | enum { SchemeTagInactive, SchemeTagFilled, SchemeTagFocus, SchemeTagNoFocus, SchemeTagEmpty, SchemeTagLast }; 75 | // window states 76 | enum { SchemeWinFocus, SchemeWinMinimized, SchemeWinNormal, 77 | SchemeWinStickyFocus, SchemeWinSticky, SchemeWinOverlay, SchemeWinOverlayFocus }; 78 | // close button 79 | enum { SchemeCloseNormal, SchemeCloseLocked, SchemeCloseFullscreen, SchemeCloseLast }; 80 | // window border states 81 | enum { SchemeBorderNormal, SchemeBorderFloatFocus, SchemeBorderTileFocus, SchemeBorderSnap, SchemeBorderLast }; 82 | 83 | typedef union { 84 | int i; 85 | unsigned int ui; 86 | float f; 87 | const void *v; 88 | } Arg; 89 | 90 | typedef struct { 91 | unsigned int click; 92 | unsigned int mask; 93 | unsigned int button; 94 | void (*func)(const Arg *arg); 95 | const Arg arg; 96 | } Button; 97 | 98 | typedef struct Monitor Monitor; 99 | typedef struct Client Client; 100 | struct Client { 101 | char name[256]; 102 | float mina, maxa; 103 | int x, y, w, h; 104 | int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ 105 | int oldx, oldy, oldw, oldh; 106 | int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; 107 | int bw, oldbw; 108 | unsigned int tags; 109 | int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isfakefullscreen, islocked, issticky, snapstatus; 110 | Client *next; 111 | Client *snext; 112 | Monitor *mon; 113 | Window win; 114 | }; 115 | 116 | typedef struct { 117 | unsigned int mod; 118 | KeySym keysym; 119 | void (*func)(const Arg *); 120 | const Arg arg; 121 | } Key; 122 | 123 | 124 | typedef struct { 125 | char *cmd; 126 | void (*func)(const Arg *); 127 | const Arg arg; 128 | unsigned int type; 129 | } Xcommand; 130 | 131 | typedef struct { 132 | const char *symbol; 133 | void (*arrange)(Monitor *); 134 | } Layout; 135 | 136 | typedef struct Pertag Pertag; 137 | struct Monitor { 138 | char ltsymbol[16]; 139 | float mfact; 140 | int nmaster; 141 | int num; 142 | int by; /* bar geometry */ 143 | int btw; /* width of tasks portion of bar */ 144 | int bt; /* number of tasks */ 145 | int mx, my, mw, mh; /* screen size */ 146 | int wx, wy, ww, wh; /* window area */ 147 | unsigned int seltags; 148 | unsigned int sellt; 149 | unsigned int tagset[2]; 150 | unsigned int activeoffset; 151 | unsigned int titleoffset; 152 | unsigned int clientcount; 153 | int showbar; 154 | int topbar; 155 | Client *clients; 156 | Client *sel; 157 | Client *overlay; 158 | Client *activescratchpad; 159 | Client *fullscreen; 160 | int overlaystatus; 161 | int overlaymode; 162 | int scratchvisible; 163 | int gesture; 164 | Client *stack; 165 | Client *hoverclient; 166 | Monitor *next; 167 | Window barwin; 168 | const Layout *lt[2]; 169 | unsigned int showtags; 170 | Pertag *pertag; 171 | }; 172 | 173 | typedef struct { 174 | const char *class; 175 | const char *instance; 176 | const char *title; 177 | unsigned int tags; 178 | int isfloating; 179 | int monitor; 180 | } Rule; 181 | 182 | /* Xresources preferences */ 183 | enum resource_type { 184 | STRING = 0, 185 | INTEGER = 1, 186 | FLOAT = 2 187 | }; 188 | 189 | typedef struct { 190 | char *name; 191 | enum resource_type type; 192 | void *dst; 193 | } ResourcePref; 194 | 195 | typedef struct { 196 | char *name; 197 | int type; 198 | } SchemePref; 199 | 200 | typedef struct Systray Systray; 201 | struct Systray { 202 | Window win; 203 | Client *icons; 204 | }; 205 | 206 | /* function declarations */ 207 | void applyrules(Client *c); 208 | int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); 209 | void arrange(Monitor *m); 210 | void arrangemon(Monitor *m); 211 | void resetcursor(); 212 | void attach(Client *c); 213 | void attachstack(Client *c); 214 | void buttonpress(XEvent *e); 215 | void checkotherwm(void); 216 | void cleanup(void); 217 | void cleanupmon(Monitor *mon); 218 | void clientmessage(XEvent *e); 219 | void configure(Client *c); 220 | void configurenotify(XEvent *e); 221 | void configurerequest(XEvent *e); 222 | Monitor *createmon(void); 223 | void cyclelayout(const Arg *arg); 224 | void destroynotify(XEvent *e); 225 | void detach(Client *c); 226 | void detachstack(Client *c); 227 | Monitor *dirtomon(int dir); 228 | void drawbar(Monitor *m); 229 | void drawbars(void); 230 | int drawstatusbar(Monitor *m, int bh, char* text); 231 | void enternotify(XEvent *e); 232 | void expose(XEvent *e); 233 | void focus(Client *c); 234 | void focusin(XEvent *e); 235 | void focusmon(const Arg *arg); 236 | void focusnmon(const Arg *arg); 237 | void followmon(const Arg *arg); 238 | void focusstack(const Arg *arg); 239 | void upkey(const Arg *arg); 240 | void downkey(const Arg *arg); 241 | void spacetoggle(const Arg *arg); 242 | Atom getatomprop(Client *c, Atom prop); 243 | int getrootptr(int *x, int *y); 244 | long getstate(Window w); 245 | unsigned int getsystraywidth(); 246 | int gettextprop(Window w, Atom atom, char *text, unsigned int size); 247 | void grabbuttons(Client *c, int focused); 248 | void grabkeys(void); 249 | void hide(Client *c); 250 | void incnmaster(const Arg *arg); 251 | void keypress(XEvent *e); 252 | int xcommand(void); 253 | void killclient(const Arg *arg); 254 | void manage(Window w, XWindowAttributes *wa); 255 | void mappingnotify(XEvent *e); 256 | void maprequest(XEvent *e); 257 | void motionnotify(XEvent *e); 258 | void movemouse(const Arg *arg); 259 | void dragmouse(const Arg *arg); 260 | void gesturemouse(const Arg *arg); 261 | int resizeborder(const Arg *arg); 262 | void dragrightmouse(const Arg *arg); 263 | void drawwindow(const Arg *arg); 264 | void dragtag(const Arg *arg); 265 | void moveresize(const Arg *arg); 266 | void distributeclients(const Arg *arg); 267 | void keyresize(const Arg *arg); 268 | void centerwindow(); 269 | void resetnametag(const Arg *arg); 270 | void nametag(const Arg *arg); 271 | Client *nexttiled(Client *c); 272 | void pop(Client *c); 273 | void shutkill(const Arg *arg); 274 | void propertynotify(XEvent *e); 275 | void quit(const Arg *arg); 276 | Monitor *recttomon(int x, int y, int w, int h); 277 | void removesystrayicon(Client *i); 278 | void resize(Client *c, int x, int y, int w, int h, int interact); 279 | void applysize(Client *c); 280 | void resetsticky(Client *c); 281 | void applysnap(Client *c, Monitor *m); 282 | int unhideone(); 283 | int allclientcount(); 284 | int clientcountmon(Monitor *m); 285 | void resizebarwin(Monitor *m); 286 | void resizeclient(Client *c, int x, int y, int w, int h); 287 | void resizemouse(const Arg *arg); 288 | void forceresizemouse(const Arg *arg); 289 | void resizeaspectmouse(const Arg *arg); 290 | void resizerequest(XEvent *e); 291 | void restack(Monitor *m); 292 | void animateclient(Client *c, int x, int y, int w, int h, int frames, int resetpos); 293 | void checkanimate(Client *c, int x, int y, int w, int h, int frames, int resetpos); 294 | void run(void); 295 | void runAutostart(void); 296 | void scan(void); 297 | int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); 298 | void sendmon(Client *c, Monitor *m); 299 | int gettagwidth(); 300 | int getxtag(int ix); 301 | void setclientstate(Client *c, long state); 302 | void setclienttagprop(Client *c); 303 | void setfocus(Client *c); 304 | void setfullscreen(Client *c, int fullscreen); 305 | void setlayout(const Arg *arg); 306 | void commandlayout(const Arg *arg); 307 | void commandprefix(const Arg *arg); 308 | void setmfact(const Arg *arg); 309 | void setup(void); 310 | void seturgent(Client *c, int urg); 311 | void show(Client *c); 312 | void showhide(Client *c); 313 | void spawn(const Arg *arg); 314 | void clickstatus(const Arg *arg); 315 | Monitor *systraytomon(Monitor *m); 316 | Client *getcursorclient(); 317 | void tag(const Arg *arg); 318 | void tagall(const Arg *arg); 319 | void followtag(const Arg *arg); 320 | void swaptags(const Arg *arg); 321 | void followview(const Arg *arg); 322 | void tagmon(const Arg *arg); 323 | void tagtoleft(const Arg *arg); 324 | void tagtoright(const Arg *arg); 325 | void uppress(const Arg *arg); 326 | void downpress(const Arg *arg); 327 | void togglealttag(const Arg *arg); 328 | void alttabfree(const Arg *arg); 329 | void toggleanimated(const Arg *arg); 330 | void setborderwidth(const Arg *arg); 331 | void togglefocusfollowsmouse(const Arg *arg); 332 | void togglefocusfollowsfloatmouse(const Arg *arg); 333 | void toggledoubledraw(const Arg *arg); 334 | void togglefakefullscreen(const Arg *arg); 335 | void togglelocked(const Arg *arg); 336 | void toggleshowtags(const Arg *arg); 337 | void togglebar(const Arg *arg); 338 | void togglefloating(const Arg *arg); 339 | void togglesticky(const Arg *arg); 340 | void toggleprefix(const Arg *arg); 341 | void toggletag(const Arg *arg); 342 | void togglescratchpad(const Arg *arg); 343 | void createscratchpad(const Arg *arg); 344 | void toggleview(const Arg *arg); 345 | void hidewin(const Arg *arg); 346 | void redrawwin(const Arg *arg); 347 | void unhideall(const Arg *arg); 348 | void closewin(const Arg *arg); 349 | void unfocus(Client *c, int setfocus); 350 | void unmanage(Client *c, int destroyed); 351 | void unmapnotify(XEvent *e); 352 | void updatebarpos(Monitor *m); 353 | void verifytagsxres(void); 354 | void updatebars(void); 355 | void updateclientlist(void); 356 | int updategeom(void); 357 | void updatemotifhints(Client *c); 358 | void updatenumlockmask(void); 359 | void updatesizehints(Client *c); 360 | void updatestatus(void); 361 | void updatesystray(void); 362 | void updatesystrayicongeom(Client *i, int w, int h); 363 | void updatesystrayiconstate(Client *i, XPropertyEvent *ev); 364 | void updatetitle(Client *c); 365 | void updatewindowtype(Client *c); 366 | void updatewmhints(Client *c); 367 | void view(const Arg *arg); 368 | void warp(const Client *c); 369 | void forcewarp(const Client *c); 370 | void warpinto(const Client *c); 371 | void warpfocus(); 372 | void viewtoleft(const Arg *arg); 373 | void animleft(const Arg *arg); 374 | void animright(const Arg *arg); 375 | void moveleft(const Arg *arg); 376 | void viewtoright(const Arg *arg); 377 | void moveright(const Arg *arg); 378 | 379 | void scaleclient(Client *c, int scale); 380 | void upscaleclient(const Arg *arg); 381 | void downscaleclient(const Arg *arg); 382 | 383 | void overtoggle(const Arg *arg); 384 | void lastview(const Arg *arg); 385 | void fullovertoggle(const Arg *arg); 386 | 387 | void setspecialnext(const Arg *arg); 388 | 389 | void directionfocus(const Arg *arg); 390 | 391 | Client *wintoclient(Window w); 392 | Monitor *wintomon(Window w); 393 | Client *wintosystrayicon(Window w); 394 | void winview(const Arg* arg); 395 | 396 | int xerror(Display *dpy, XErrorEvent *ee); 397 | int xerrordummy(Display *dpy, XErrorEvent *ee); 398 | int xerrorstart(Display *dpy, XErrorEvent *ee); 399 | void zoom(const Arg *arg); 400 | void load_xresources(void); 401 | void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); 402 | 403 | void keyrelease(XEvent *e); 404 | void setoverlay(); 405 | void desktopset(); 406 | void createdesktop(); 407 | void createoverlay(); 408 | void tempfullscreen(); 409 | 410 | void savefloating(Client *c); 411 | void restorefloating(Client *c); 412 | 413 | void savebw(Client *c); 414 | void restorebw(Client *c); 415 | 416 | void shiftview(const Arg *arg); 417 | void focuslastclient(const Arg *arg); 418 | 419 | void resetoverlay(); 420 | void showoverlay(); 421 | void hideoverlay(); 422 | void changefloating(Client *c); 423 | void resetbar(); 424 | 425 | extern Monitor *selmon; 426 | extern int bh; 427 | extern int animated; 428 | extern Display *dpy; 429 | 430 | #endif 431 | -------------------------------------------------------------------------------- /instantwmctrl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | description="$0 ... 3 | 4 | Really basic tool to send commands to instantWM. 5 | 6 | Commands: 7 | help Display this help text 8 | overlay Toggle overlay (Super + Ctrl + W to define a widnow as overlay) 9 | warpfocus Warp mouse to currently focussed window 10 | tag Switch to tag described by 11 | animated Toggle animations 12 | alttab 13 | layout | Change window layout to given argument, e.g. $0 layout monocle 14 | prefix Set action prefix 15 | focusfollowsmouse Toggle window focus will change with mouse movement 16 | focusfollowsfloatmouse As above but only for flowting windows 17 | focusmon Switch focus to other monitor 18 | focusnmon Focus monitor with index n 19 | tagmon Move window to other monitor 20 | followmon Two above combined 21 | border Set window border width to 22 | alttag Display tag symbols instead of numbers 23 | hidetags 0|1 Hide tags that have no windows on current monitor (0 means hide) 24 | nametag change the name/icon of the current tag 25 | resetnametag reset all tag names to default" 26 | # See config.def.c and look for "Xcommand commands" 27 | 28 | main() { 29 | case $1 in 30 | help) usage -h ;; 31 | layout) layout "$2"; exit ;; 32 | esac 33 | xsetroot -name "c;:;$1;$2" 34 | } 35 | 36 | layout() { 37 | if [[ $1 =~ ^[0-8]$ ]]; then # between zero and eight 38 | layout=$1 39 | else 40 | declare -A layouts=( 41 | ["tile"]=0 ['grid']=1 ['float']=2 42 | ['monocle']=3 ['tcl']=4 ['deck']=5 43 | ['overview']=6 ['bstack']=7 ['bstackhoriz']=8 44 | ) 45 | layout=${layouts[$1]} 46 | [ -z "$layout" ] && 47 | { echo "Error: Unknown layout '$1'"; exit 1; } 48 | fi 49 | xsetroot -name "c;:;layout;$layout" 50 | } 51 | 52 | usage() { 53 | for itm in "$@"; do 54 | if [[ "$itm" =~ ^(-h|--help|-help|-\?)$ ]]; then 55 | 1>&2 echo "Usage: $description"; exit 0; 56 | fi 57 | done 58 | } 59 | 60 | if [ "$0" = "$BASH_SOURCE" ]; then 61 | usage "$@" 62 | main "$@" 63 | fi 64 | 65 | -------------------------------------------------------------------------------- /layouts.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | #include "layouts.h" 4 | #include "push.h" 5 | #include "util.h" 6 | 7 | void 8 | bstack(Monitor *m) { 9 | int w, h, mh, mx, tx, ty, tw, framecount; 10 | unsigned int i, n; 11 | Client *c; 12 | 13 | if (animated && clientcount() > 4) 14 | framecount = 4; 15 | else 16 | framecount = 7; 17 | 18 | for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 19 | if (n == 0) 20 | return; 21 | if (n > m->nmaster) { 22 | mh = m->nmaster ? m->mfact * m->wh : 0; 23 | tw = m->ww / (n - m->nmaster); 24 | ty = m->wy + mh; 25 | } else { 26 | mh = m->wh; 27 | tw = m->ww; 28 | ty = m->wy; 29 | } 30 | for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { 31 | if (i < m->nmaster) { 32 | w = (m->ww - mx) / (MIN(n, m->nmaster) - i); 33 | animateclient(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), framecount, 0); 34 | mx += WIDTH(c); 35 | } else { 36 | h = m->wh - mh; 37 | animateclient(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), framecount, 0); 38 | if (tw != m->ww) 39 | tx += WIDTH(c); 40 | } 41 | } 42 | } 43 | 44 | 45 | /* 46 | * Different ids for snapping positions 47 | * 48 | * ################################## 49 | * # 8 1 2 # 50 | * # # 51 | * # # 52 | * # # 53 | * # 7 9 3 # 54 | * # # 55 | * # # 56 | * # 6 5 4 # 57 | * ################################## 58 | * 59 | * */ 60 | 61 | void floatl(Monitor *m) { 62 | Client *c; 63 | int animatestore; 64 | animatestore = animated; 65 | animated = 0; 66 | for(c = m->clients; c; c = c->next) { 67 | if (!(ISVISIBLE(c))) 68 | continue; 69 | if (c->snapstatus) 70 | applysnap(c, m); 71 | } 72 | restack(selmon); 73 | if (selmon->sel) 74 | XRaiseWindow(dpy, selmon->sel->win); 75 | if (animatestore) 76 | animated = 1; 77 | } 78 | 79 | 80 | 81 | void 82 | bstackhoriz(Monitor *m) { 83 | int w, mh, mx, tx, ty, th, framecount; 84 | unsigned int i, n; 85 | Client *c; 86 | 87 | if (animated && clientcount() > 4) 88 | framecount = 4; 89 | else 90 | framecount = 7; 91 | 92 | for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 93 | if (n == 0) 94 | return; 95 | if (n > m->nmaster) { 96 | mh = m->nmaster ? m->mfact * m->wh : 0; 97 | th = (m->wh - mh) / (n - m->nmaster); 98 | ty = m->wy + mh; 99 | } else { 100 | th = mh = m->wh; 101 | ty = m->wy; 102 | } 103 | for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { 104 | if (i < m->nmaster) { 105 | w = (m->ww - mx) / (MIN(n, m->nmaster) - i); 106 | animateclient(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), framecount, 0); 107 | mx += WIDTH(c); 108 | } else { 109 | animateclient(c, tx, ty, m->ww - (2 * c->bw), th - (2 * c->bw), framecount, 0); 110 | if (th != m->wh) 111 | ty += HEIGHT(c); 112 | } 113 | } 114 | } 115 | 116 | void 117 | deck(Monitor *m) 118 | { 119 | int dn; 120 | unsigned int i, n, h, mw, my; 121 | Client *c; 122 | 123 | for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 124 | if(n == 0) 125 | return; 126 | 127 | dn = n - m->nmaster; 128 | if(dn > 0) /* override layout symbol */ 129 | snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", dn); 130 | 131 | if(n > m->nmaster) 132 | mw = m->nmaster ? m->ww * m->mfact : 0; 133 | else 134 | mw = m->ww; 135 | for(i = my = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 136 | if(i < m->nmaster) { 137 | h = (m->wh - my) / (MIN(n, m->nmaster) - i); 138 | resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); 139 | my += HEIGHT(c); 140 | } 141 | else 142 | resize(c, m->wx + mw, m->wy, m->ww - mw - (2*c->bw), m->wh - (2*c->bw), False); 143 | } 144 | 145 | void 146 | grid(Monitor *m) { 147 | int i, n, rows, framecount; 148 | unsigned int cols; 149 | Client *c; 150 | 151 | if (m->clientcount <= 2 && m->mw > m->mh) 152 | { 153 | tile(m); 154 | return; 155 | } 156 | 157 | if (animated && clientcount() > 5) 158 | framecount = 3; 159 | else 160 | framecount = 6; 161 | for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) 162 | n++; 163 | 164 | /* grid dimensions */ 165 | for(rows = 0; rows <= n/2; rows++) 166 | if(rows*rows >= n) 167 | break; 168 | cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; 169 | 170 | /* window geoms (cell height/width) */ 171 | int ch = m->wh / (rows ? rows : 1); 172 | int cw = m->ww / (cols ? cols : 1); 173 | for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { 174 | unsigned int cx = m->wx + (i / rows) * cw; 175 | unsigned int cy = m->wy + (i % rows) * ch; 176 | /* adjust height/width of last row/column's windows */ 177 | int ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0; 178 | unsigned int aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0; 179 | animateclient(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, framecount, 0); 180 | i++; 181 | } 182 | } 183 | 184 | // overlay all clients on top of each other 185 | void 186 | monocle(Monitor *m) 187 | { 188 | unsigned int n = 0; 189 | Client *c; 190 | 191 | if (animated && selmon->sel) 192 | XRaiseWindow(dpy, selmon->sel->win); 193 | 194 | for (c = m->clients; c; c = c->next) 195 | if (ISVISIBLE(c)) 196 | n++; 197 | if (n > 0) /* override layout symbol */ 198 | snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%1u]", n); 199 | for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) { 200 | animateclient(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 7 * (animated && c == selmon->sel), 0); 201 | } 202 | 203 | } 204 | 205 | void 206 | focusstack2(const Arg *arg) 207 | { 208 | Client *nextVisibleClient = findVisibleClient(selmon->sel->next) ?: findVisibleClient(selmon->clients); 209 | 210 | if (nextVisibleClient) { 211 | if (nextVisibleClient->mon != selmon) 212 | selmon = nextVisibleClient->mon; 213 | detachstack(nextVisibleClient); 214 | attachstack(nextVisibleClient); 215 | selmon->sel = nextVisibleClient; 216 | } 217 | } 218 | 219 | void 220 | overviewlayout(Monitor *m) 221 | { 222 | int n; 223 | int gridwidth; 224 | unsigned int colwidth; 225 | unsigned int lineheight; 226 | int tmpx; 227 | int tmpy; 228 | Client *c; 229 | XWindowChanges wc; 230 | n = allclientcount(); 231 | 232 | if (n == 0) 233 | return; 234 | 235 | gridwidth = 1; 236 | 237 | while ((gridwidth * gridwidth) < n) { 238 | gridwidth++; 239 | } 240 | 241 | tmpx = selmon->mx; 242 | tmpy = selmon->my + (selmon->showbar ? bh : 0); 243 | lineheight = selmon->wh / gridwidth; 244 | colwidth = selmon->ww / gridwidth; 245 | wc.stack_mode = Above; 246 | wc.sibling = m->barwin; 247 | 248 | for(c = m->clients; c; c = c->next) { 249 | if (HIDDEN(c)) 250 | continue; 251 | if (c == selmon->overlay) 252 | continue; 253 | if (c->isfloating) 254 | savefloating(c); 255 | resize(c,tmpx, tmpy, c->w, c->h, 0); 256 | 257 | XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); 258 | wc.sibling = c->win; 259 | if (tmpx + colwidth < selmon->mx + selmon->ww) { 260 | tmpx += colwidth; 261 | } else { 262 | tmpx = selmon->mx; 263 | tmpy += lineheight; 264 | } 265 | } 266 | XSync(dpy, False); 267 | } 268 | 269 | void 270 | tcl(Monitor * m) 271 | { 272 | int x, y, h, w, mw, sw, bdw; 273 | unsigned int i, n; 274 | Client * c; 275 | 276 | for (n = 0, c = nexttiled(m->clients); c; 277 | c = nexttiled(c->next), n++); 278 | 279 | if (n == 0) 280 | return; 281 | 282 | c = nexttiled(m->clients); 283 | 284 | mw = m->mfact * m->ww; 285 | sw = (m->ww - mw) / 2; 286 | bdw = (2 * c->bw); 287 | resize(c, 288 | n < 3 ? m->wx : m->wx + sw, 289 | m->wy, 290 | n == 1 ? m->ww - bdw : mw - bdw, 291 | m->wh - bdw, 292 | False); 293 | 294 | if (--n == 0) 295 | return; 296 | 297 | w = (m->ww - mw) / ((n > 1) + 1); 298 | c = nexttiled(c->next); 299 | 300 | if (n > 1) 301 | { 302 | x = m->wx + mw + sw; 303 | y = m->wy; 304 | h = m->wh / (n / 2); 305 | 306 | if (h < bh) 307 | h = m->wh; 308 | 309 | for (i = 0; c && i < n / 2; c = nexttiled(c->next), i++) 310 | { 311 | resize(c, 312 | x, 313 | y, 314 | w - bdw, 315 | (i + 1 == n / 2) ? m->wy + m->wh - y - bdw : h - bdw, 316 | False); 317 | 318 | if (h != m->wh) 319 | y = c->y + HEIGHT(c); 320 | } 321 | } 322 | 323 | x = (n + 1 / 2) == 1 ? mw + m->wx : m->wx; 324 | y = m->wy; 325 | h = m->wh / ((n + 1) / 2); 326 | 327 | if (h < bh) 328 | h = m->wh; 329 | 330 | int rw = w - bdw; 331 | 332 | for (i = 0; c; c = nexttiled(c->next), i++) 333 | { 334 | int rh = (i + 1 == (n + 1) / 2) ? m->wy + m->wh - y - bdw : h - bdw; 335 | resize(c, x, y, rw, rh, 0); 336 | 337 | if (h != m->wh) 338 | y = c->y + HEIGHT(c); 339 | } 340 | } 341 | 342 | void 343 | tile(Monitor *m) 344 | { 345 | unsigned int i, n, h, mw, my, ty, framecount; 346 | Client *c; 347 | 348 | if (animated && clientcount() > 5) 349 | framecount = 4; 350 | else 351 | framecount = 7; 352 | 353 | for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 354 | if (n == 0) 355 | return; 356 | 357 | if (n > m->nmaster) 358 | mw = m->nmaster ? m->ww * m->mfact : 0; 359 | else { 360 | mw = m->ww; 361 | if (n > 1 && n < m->nmaster) { 362 | m->nmaster = n; 363 | tile(m); 364 | return; 365 | } 366 | } 367 | for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 368 | if (i < m->nmaster) { 369 | // client is in the master 370 | h = (m->wh - my) / (MIN(n, m->nmaster) - i); 371 | 372 | if (n == 2) { 373 | animateclient(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0, 0); 374 | } else { 375 | animateclient(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), framecount, 0); 376 | if (m->nmaster == 1 && n > 1) { 377 | mw = c->w + c->bw * 2; 378 | } 379 | } 380 | if (my + HEIGHT(c) < m->wh) 381 | my += HEIGHT(c); 382 | } else { 383 | // client is in the stack 384 | h = (m->wh - ty) / (n - i); 385 | animateclient(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), framecount, 0); 386 | if (ty + HEIGHT(c) < m->wh) 387 | ty += HEIGHT(c); 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /layouts.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYOUTS_H 2 | #define LAYOUTS_H 3 | 4 | #include "instantwm.h" 5 | 6 | void bstack(Monitor *m); 7 | void bstackhoriz(Monitor *m); 8 | void deck(Monitor *m); 9 | void grid(Monitor *m); 10 | void monocle(Monitor *m); 11 | void overviewlayout(Monitor *m); 12 | void tcl(Monitor * m); 13 | void tile(Monitor *m); 14 | void floatl(Monitor *m); 15 | static inline Client* findVisibleClient(Client *c){ 16 | Client* client = NULL; 17 | for (client = c; client ; client = client->next){ 18 | if(ISVISIBLE(client)) 19 | return client; 20 | } 21 | return NULL; 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /push.c: -------------------------------------------------------------------------------- 1 | Client * 2 | nextc(Client *c, float f) { 3 | if(!f) 4 | return nexttiled(c); 5 | 6 | for(; c && !ISVISIBLE(c); c = c->next); 7 | return c; 8 | } 9 | 10 | static Client * 11 | prevc(Client *c, float f) { 12 | Client *p, *r; 13 | 14 | for(p = selmon->clients, r = NULL; c && p && p != c; p = p->next) 15 | if((f || !p->isfloating) && ISVISIBLE(p)) 16 | r = p; 17 | return r; 18 | } 19 | 20 | int clientcountmon(Monitor *m) 21 | { 22 | int n; 23 | Client *c; 24 | for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 25 | return n; 26 | } 27 | 28 | // get amount of tiled clients 29 | int clientcount() 30 | { 31 | return clientcountmon(selmon); 32 | } 33 | 34 | int allclientcount() 35 | { 36 | int n; 37 | Client *c; 38 | n = 0; 39 | for (c = selmon->clients; c; c = c->next) { 40 | if (c == selmon->overlay) 41 | continue; 42 | n++; 43 | } 44 | return n; 45 | } 46 | 47 | int clientdistance(Client *c, Client *c2) { 48 | int x, y, distance; 49 | x = abs(((c->x + c->w) / 2) - ((c2->x + c->w) / 2)); 50 | y = abs(((c->y + c->h) / 2) - ((c2->y + c->h) / 2)); 51 | 52 | distance = (sqrt(y*y+x*x)); 53 | return distance; 54 | 55 | } 56 | 57 | static void 58 | pushup(const Arg *arg) { 59 | Client *sel = selmon->sel; 60 | Client *c; 61 | if (clientcount() < 2) { 62 | return; 63 | } 64 | 65 | if(!sel || (sel->isfloating && !arg->f)) 66 | return; 67 | if((c = prevc(sel, arg->f))) { 68 | /* attach before c */ 69 | detach(sel); 70 | sel->next = c; 71 | if(selmon->clients == c) 72 | selmon->clients = sel; 73 | else { 74 | for(c = selmon->clients; c->next != sel->next; c = c->next); 75 | c->next = sel; 76 | } 77 | } else { 78 | /* move to the end */ 79 | for(c = sel; c->next; c = c->next); 80 | detach(sel); 81 | sel->next = NULL; 82 | c->next = sel; 83 | } 84 | focus(sel); 85 | arrange(selmon); 86 | } 87 | 88 | static void 89 | pushdown(const Arg *arg) { 90 | Client *sel = selmon->sel; 91 | Client *c; 92 | 93 | if (clientcount() < 2) { 94 | return; 95 | } 96 | 97 | if(!sel || (sel->isfloating && !arg->f)) 98 | return; 99 | if((c = nextc(sel->next, arg->f))) { 100 | /* attach after c */ 101 | detach(sel); 102 | sel->next = c->next; 103 | c->next = sel; 104 | } else { 105 | /* move to the front */ 106 | detach(sel); 107 | attach(sel); 108 | } 109 | focus(sel); 110 | arrange(selmon); 111 | } 112 | -------------------------------------------------------------------------------- /push.h: -------------------------------------------------------------------------------- 1 | #ifndef PUSH_H 2 | #define PUSH_H 3 | 4 | int clientcount(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /startinstantos: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ############################################### 4 | ## x session for instantOS, use with lightdm ## 5 | ############################################### 6 | 7 | # used for shutdown 8 | 9 | # try to obtain a temp dir unique to the user, to enable 10 | # instantOS xsessions for concurrent users on the same machine 11 | RTD="$(instantruntimedir)" 12 | 13 | if [ -z "$RTD" ]; then 14 | mkdir -p /tmp/instantos 15 | RTD="/tmp/instantos" 16 | fi 17 | 18 | echo $$ >"${RTD}"/instantosrunning 19 | 20 | # just in case, some systems might not do this 21 | cd || echo "failed to access home directory" 22 | 23 | # execute autostart even if instantautostart doesn't work 24 | if ! command -v instantautostart &>/dev/null; then 25 | sleep 4 26 | bash ~/.instantautostart 27 | fi & 28 | 29 | # needed to fix some misbehaving applications 30 | if iconf wmname; then 31 | wmname "$(iconf wmname)" 32 | fi 33 | 34 | [ -e ~/.instantsession ] && source ~/.instantsession 35 | 36 | ILOGFILE="$HOME/.local/share/instantos.log" 37 | 38 | if iconf -i debug; then 39 | export INSTANTDEBUG="true" 40 | fi 41 | 42 | if [ -z "$INSTANTDEBUG" ]; then 43 | if [ -e "$ILOGFILE" ] && [ "$(du -sm "$ILOGFILE" | grep -o '^[0-9]*')" -gt 20 ]; then 44 | echo "log file has gotten out of hand, clearing logs" 45 | echo "start of log file" >"$ILOGFILE" 46 | fi 47 | fi 48 | 49 | # loop so crashing instantwm doesn't end the x session 50 | while [ -e "${RTD}"/instantosrunning ]; do 51 | # allow changing wm on the fly 52 | if [ -e "${RTD}"/wmoverride ]; then 53 | if command -v "$(cat "${RTD}"/wmoverride)" &>/dev/null; then 54 | "$(cat ${RTD}/wmoverride)" 2>~/.instantos.log & 55 | WMPID="$!" 56 | echo "$WMPID" >"${RTD}"/wmpid 57 | while kill -0 "$WMPID"; do 58 | sleep 1 59 | done 60 | fi 61 | rm "${RTD}"/wmoverride 62 | else 63 | # Log stderror or stdout to a file 64 | if ! [ -e .local/share ]; then 65 | mkdir -p ~/.local/share 66 | fi 67 | 68 | export XDG_CURRENT_DESKTOP="instantwm" 69 | 70 | if [ -n "$INSTANTDEBUG" ]; then 71 | instantwm &>>~/.local/share/instantos.log 72 | export WMEXITCODE="$?" 73 | else 74 | instantwm 2>>~/.local/share/instantos.log 75 | export WMEXITCODE="$?" 76 | fi 77 | fi 78 | echo "$(date): window manager was restarted or crashed" >>"$ILOGFILE" 79 | echo "window manager exit code: $WMEXITCODE" >>"$ILOGFILE" 80 | done 81 | -------------------------------------------------------------------------------- /themes/arc.theme: -------------------------------------------------------------------------------- 1 | static const char *fonts[] = {"Cantarell-Regular:size=12", "Fira Code Nerd Font:size=12"}; 2 | static const char col_gray1[] = "#292f3a"; /* top bar d */ 3 | static const char col_gray2[] = "#ffffff";/*unfocused fonts d */ 4 | static const char col_gray3[] = "#747c90";/*unfocused border d */ 5 | static const char col_gray4[] = "#ffffff";/*focused fonts d */ 6 | static const char col_gray5[] = "#4dadd4";/*focused windows d */ 7 | static const char col_cyan[] = "#5294E2";/*focused instantmenu or topbar d */ -------------------------------------------------------------------------------- /themes/dracula.theme: -------------------------------------------------------------------------------- 1 | static const char *fonts[] = {"Monaco-Nerd-Font-Complete-Mono:size=12"}; 2 | static const char col_gray1[] = "#282a36"; /* top bar d */ 3 | static const char col_gray2[] = "#bd93f9";/*unfocused fonts d */ 4 | static const char col_gray3[] = "#6272a4";/*unfocused border d */ 5 | static const char col_gray4[] = "#8be9fd";/*focused fonts d */ 6 | static const char col_gray5[] = "#50fa7b";/*focused windows d */ 7 | static const char col_cyan[] = "#44475a";/*focused instantmenu or topbar d */ -------------------------------------------------------------------------------- /themes/mac.theme: -------------------------------------------------------------------------------- 1 | static const char *fonts[] = {"SF-Mono-Bold:size=12"}; 2 | static const char col_gray1[] = "#fafafa"; /* top bar d */ 3 | static const char col_gray2[] = "#4c4c4c";/*unfocused fonts d */ 4 | static const char col_gray3[] = "#8e8e93";/*unfocused border d */ 5 | static const char col_gray4[] = "#fafafa";/*focused fonts d */ 6 | static const char col_gray5[] = "#28CD41";/*focused windows d */ 7 | static const char col_cyan[] = "#007aff";/*focused instantmenu or topbar d */ -------------------------------------------------------------------------------- /themes/manjaro.theme: -------------------------------------------------------------------------------- 1 | static const char *fonts[] = {"Cantarell-Regular:size=12"}; 2 | static const char col_gray1[] = "#1B2224"; /* top bar d */ 3 | static const char col_gray2[] = "#A4ABAA";/*unfocused fonts d */ 4 | static const char col_gray3[] = "#686868";/*unfocused border d */ 5 | static const char col_gray4[] = "#FFFFFF";/*focused fonts d */ 6 | static const char col_gray5[] = "#2EB398";/*focused windows d */ 7 | static const char col_cyan[] = "#2EB398";/*focused instantmenu or topbar d */ -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | 9 | void * 10 | ecalloc(size_t nmemb, size_t size) 11 | { 12 | void *p; 13 | 14 | if (!(p = calloc(nmemb, size))) 15 | die("calloc:"); 16 | return p; 17 | } 18 | 19 | void 20 | die(const char *fmt, ...) { 21 | va_list ap; 22 | 23 | va_start(ap, fmt); 24 | vfprintf(stderr, fmt, ap); 25 | va_end(ap); 26 | 27 | if (fmt[0] && fmt[strlen(fmt)-1] == ':') { 28 | fputc(' ', stderr); 29 | perror(NULL); 30 | } else { 31 | fputc('\n', stderr); 32 | } 33 | 34 | exit(1); 35 | } 36 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | #define MAX(A, B) ((A) > (B) ? (A) : (B)) 4 | #define MIN(A, B) ((A) < (B) ? (A) : (B)) 5 | #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) 6 | 7 | void die(const char *fmt, ...); 8 | void *ecalloc(size_t nmemb, size_t size); 9 | --------------------------------------------------------------------------------