├── LICENCE_DWM ├── Makefile ├── README.md ├── catwm.c └── config.h /LICENCE_DWM: -------------------------------------------------------------------------------- 1 | MIT/X Consortium License 2 | 3 | © 2006-2011 Anselm R Garbe 4 | © 2007-2011 Peter Hartlich 5 | © 2010-2011 Connor Lane Smith 6 | © 2006-2009 Jukka Salmi 7 | © 2007-2009 Premysl Hruby 8 | © 2007-2009 Szabolcs Nagy 9 | © 2007-2009 Christof Musik 10 | © 2009 Mate Nagy 11 | © 2007-2008 Enno Gottox Boland 12 | © 2008 Martin Hurton 13 | © 2008 Neale Pickett 14 | © 2006-2007 Sander van Dijk 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a 17 | copy of this software and associated documentation files (the "Software"), 18 | to deal in the Software without restriction, including without limitation 19 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 | and/or sell copies of the Software, and to permit persons to whom the 21 | Software is furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in 24 | all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 29 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 | DEALINGS IN THE SOFTWARE. 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS+= -Wall 2 | LDADD+= -lX11 3 | LDFLAGS= 4 | EXEC=catwm 5 | 6 | PREFIX?= /usr 7 | BINDIR?= $(PREFIX)/bin 8 | 9 | CC=gcc 10 | 11 | all: $(EXEC) 12 | 13 | catwm: catwm.o 14 | $(CC) $(LDFLAGS) -Os -o $@ $+ $(LDADD) 15 | 16 | install: all 17 | install -Dm 755 catwm $(DESTDIR)$(BINDIR)/catwm 18 | 19 | clean: 20 | rm -f catwm *.o 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CATWM 2 | ===== 3 | 4 | /\___/\ 5 | ( o o ) Made by cat... 6 | ( =^= ) 7 | ( ) ... for cat! 8 | ( ) 9 | ( ))))))________________ Cute And Tiny Window Manager 10 | 11 | Summary 12 | ------- 13 | 14 | catwm is a very simple and lightweight tiling window manager. 15 | I will try to stay under 1000 SLOC. 16 | 17 | Status 18 | ------ 19 | 20 | * 05.07.19 -> v0.3. Multiple desktops and correct some bugs 21 | * 30.06.10 -> v0.2. Back again \o/ 22 | * 15.03.10 -> v0.2. The wm is functional -> I only use this wm! 23 | * 24.02.10 -> First release, v0.1. In this release 0.1, the wm is almost functional 24 | 25 | Modes 26 | ----- 27 | 28 | It allow the "normal" modes of tiling window managers: 29 | 30 | -------------- 31 | | |___| 32 | | |___| 33 | | Master |___| 34 | | |___| 35 | | |___| 36 | -------------- 37 | 38 | and fullscreen mode 39 | 40 | There is no horizontal stack because I never use it. But if someone is interested in, it's very easy to add. 41 | 42 | Installation 43 | ------------ 44 | 45 | Need Xlib, then: 46 | $ vim config.h 47 | $ make 48 | # make install 49 | $ make clean 50 | 51 | Bugs 52 | ---- 53 | * No bugs for the moment ;) (I mean, no importants bugs ;) 54 | 55 | Todo 56 | ---- 57 | * Add multiple view ("desktop") 58 | * Switch to XCB 59 | 60 | If you have some particular request, just send me an e-mail, and I will see for it! 61 | 62 | -------------------------------------------------------------------------------- /catwm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * /\___/\ 3 | * ( o o ) Made by cat... 4 | * ( =^= ) 5 | * ( ) ... for cat! 6 | * ( ) 7 | * ( ))))))________________ Cute And Tiny Window Manager 8 | * ______________________________________________________________________________ 9 | * 10 | * Copyright (c) 2010, Rinaldini Julien, julien.rinaldini@heig-vd.ch 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a 13 | * copy of this software and associated documentation files (the "Software"), 14 | * to deal in the Software without restriction, including without limitation 15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 | * and/or sell copies of the Software, and to permit persons to whom the 17 | * Software is furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | * DEALINGS IN THE SOFTWARE. 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #define TABLENGTH(X) (sizeof(X)/sizeof(*X)) 42 | 43 | typedef union { 44 | const char** com; 45 | const int i; 46 | } Arg; 47 | 48 | // Structs 49 | struct key { 50 | unsigned int mod; 51 | KeySym keysym; 52 | void (*function)(const Arg arg); 53 | const Arg arg; 54 | }; 55 | 56 | typedef struct client client; 57 | struct client{ 58 | // Prev and next client 59 | client *next; 60 | client *prev; 61 | 62 | // The window 63 | Window win; 64 | }; 65 | 66 | typedef struct desktop desktop; 67 | struct desktop{ 68 | int master_size; 69 | int mode; 70 | client *head; 71 | client *current; 72 | }; 73 | 74 | // Functions 75 | static void add_window(Window w); 76 | static void change_desktop(const Arg arg); 77 | static void client_to_desktop(const Arg arg); 78 | static void configurenotify(XEvent *e); 79 | static void configurerequest(XEvent *e); 80 | static void decrease(); 81 | static void destroynotify(XEvent *e); 82 | static void die(const char* e); 83 | static unsigned long getcolor(const char* color); 84 | static void grabkeys(); 85 | static void increase(); 86 | static void keypress(XEvent *e); 87 | static void kill_client(); 88 | static void maprequest(XEvent *e); 89 | static void move_down(); 90 | static void move_up(); 91 | static void next_desktop(); 92 | static void next_win(); 93 | static void prev_desktop(); 94 | static void prev_win(); 95 | static void quit(); 96 | static void remove_window(Window w); 97 | static void save_desktop(int i); 98 | static void select_desktop(int i); 99 | static void send_kill_signal(Window w); 100 | static void setup(); 101 | static void sigchld(int unused); 102 | static void spawn(const Arg arg); 103 | static void start(); 104 | //static void swap(); 105 | static void swap_master(); 106 | static void switch_mode(); 107 | static void tile(); 108 | static void update_current(); 109 | 110 | // Include configuration file (need struct key) 111 | #include "config.h" 112 | 113 | // Variable 114 | static Display *dis; 115 | static int bool_quit; 116 | static int current_desktop; 117 | static int master_size; 118 | static int mode; 119 | static int sh; 120 | static int sw; 121 | static int screen; 122 | static unsigned int win_focus; 123 | static unsigned int win_unfocus; 124 | static Window root; 125 | static client *head; 126 | static client *current; 127 | 128 | // Events array 129 | static void (*events[LASTEvent])(XEvent *e) = { 130 | [KeyPress] = keypress, 131 | [MapRequest] = maprequest, 132 | [DestroyNotify] = destroynotify, 133 | [ConfigureNotify] = configurenotify, 134 | [ConfigureRequest] = configurerequest 135 | }; 136 | 137 | // Desktop array 138 | static desktop desktops[10]; 139 | 140 | void add_window(Window w) { 141 | client *c,*t; 142 | 143 | if(!(c = (client *)calloc(1,sizeof(client)))) 144 | die("Error calloc!"); 145 | 146 | if(head == NULL) { 147 | c->next = NULL; 148 | c->prev = NULL; 149 | c->win = w; 150 | head = c; 151 | } 152 | else { 153 | for(t=head;t->next;t=t->next); 154 | 155 | c->next = NULL; 156 | c->prev = t; 157 | c->win = w; 158 | 159 | t->next = c; 160 | } 161 | 162 | current = c; 163 | } 164 | 165 | void change_desktop(const Arg arg) { 166 | client *c; 167 | 168 | if(arg.i == current_desktop) 169 | return; 170 | 171 | // Unmap all window 172 | if(head != NULL) 173 | for(c=head;c;c=c->next) 174 | XUnmapWindow(dis,c->win); 175 | 176 | // Save current "properties" 177 | save_desktop(current_desktop); 178 | 179 | // Take "properties" from the new desktop 180 | select_desktop(arg.i); 181 | 182 | // Map all windows 183 | if(head != NULL) 184 | for(c=head;c;c=c->next) 185 | XMapWindow(dis,c->win); 186 | 187 | tile(); 188 | update_current(); 189 | } 190 | 191 | void client_to_desktop(const Arg arg) { 192 | client *tmp = current; 193 | int tmp2 = current_desktop; 194 | 195 | if(arg.i == current_desktop || current == NULL) 196 | return; 197 | 198 | // Add client to desktop 199 | select_desktop(arg.i); 200 | add_window(tmp->win); 201 | save_desktop(arg.i); 202 | 203 | // Remove client from current desktop 204 | select_desktop(tmp2); 205 | remove_window(current->win); 206 | 207 | tile(); 208 | update_current(); 209 | } 210 | 211 | void configurenotify(XEvent *e) { 212 | // Do nothing for the moment 213 | } 214 | 215 | void configurerequest(XEvent *e) { 216 | // Paste from DWM, thx again \o/ 217 | XConfigureRequestEvent *ev = &e->xconfigurerequest; 218 | XWindowChanges wc; 219 | wc.x = ev->x; 220 | wc.y = ev->y; 221 | wc.width = ev->width; 222 | wc.height = ev->height; 223 | wc.border_width = ev->border_width; 224 | wc.sibling = ev->above; 225 | wc.stack_mode = ev->detail; 226 | XConfigureWindow(dis, ev->window, ev->value_mask, &wc); 227 | } 228 | 229 | void decrease() { 230 | if(master_size > 50) { 231 | master_size -= 10; 232 | tile(); 233 | } 234 | } 235 | 236 | void destroynotify(XEvent *e) { 237 | int i=0; 238 | client *c; 239 | XDestroyWindowEvent *ev = &e->xdestroywindow; 240 | 241 | // Uber (and ugly) hack ;) 242 | for(c=head;c;c=c->next) 243 | if(ev->window == c->win) 244 | i++; 245 | 246 | // End of the hack 247 | if(i == 0) 248 | return; 249 | 250 | remove_window(ev->window); 251 | tile(); 252 | update_current(); 253 | } 254 | 255 | void die(const char* e) { 256 | fprintf(stdout,"catwm: %s\n",e); 257 | exit(1); 258 | } 259 | 260 | unsigned long getcolor(const char* color) { 261 | XColor c; 262 | Colormap map = DefaultColormap(dis,screen); 263 | 264 | if(!XAllocNamedColor(dis,map,color,&c,&c)) 265 | die("Error parsing color!"); 266 | 267 | return c.pixel; 268 | } 269 | 270 | void grabkeys() { 271 | int i; 272 | KeyCode code; 273 | 274 | // For each shortcuts 275 | for(i=0;ixkey; 292 | int keysym_return; 293 | KeySym *keysym = XGetKeyboardMapping(dis, ke.keycode, 1, &keysym_return); 294 | 295 | for(i=0;iwin; 308 | ke.xclient.message_type = XInternAtom(dis, "WM_PROTOCOLS", True); 309 | ke.xclient.format = 32; 310 | ke.xclient.data.l[0] = XInternAtom(dis, "WM_DELETE_WINDOW", True); 311 | ke.xclient.data.l[1] = CurrentTime; 312 | XSendEvent(dis, current->win, False, NoEventMask, &ke); 313 | send_kill_signal(current->win); 314 | } 315 | } 316 | 317 | void maprequest(XEvent *e) { 318 | XMapRequestEvent *ev = &e->xmaprequest; 319 | 320 | // For fullscreen mplayer (and maybe some other program) 321 | client *c; 322 | for(c=head;c;c=c->next) 323 | if(ev->window == c->win) { 324 | XMapWindow(dis,ev->window); 325 | return; 326 | } 327 | 328 | add_window(ev->window); 329 | XMapWindow(dis,ev->window); 330 | tile(); 331 | update_current(); 332 | } 333 | 334 | void move_down() { 335 | Window tmp; 336 | if(current == NULL || current->next == NULL || current->win == head->win || current->prev == NULL) { 337 | return; 338 | } 339 | tmp = current->win; 340 | current->win = current->next->win; 341 | current->next->win = tmp; 342 | //keep the moved window activated 343 | next_win(); 344 | tile(); 345 | update_current(); 346 | } 347 | 348 | void move_up() { 349 | Window tmp; 350 | if(current == NULL || current->prev == head || current->win == head->win) { 351 | return; 352 | } 353 | tmp = current->win; 354 | current->win = current->prev->win; 355 | current->prev->win = tmp; 356 | prev_win(); 357 | tile(); 358 | update_current(); 359 | } 360 | 361 | void next_desktop() { 362 | int tmp = current_desktop; 363 | if(tmp== 9) 364 | tmp = 0; 365 | else 366 | tmp++; 367 | 368 | Arg a = {.i = tmp}; 369 | change_desktop(a); 370 | } 371 | 372 | void next_win() { 373 | client *c; 374 | 375 | if(current != NULL && head != NULL) { 376 | if(current->next == NULL) { 377 | c = head; 378 | } 379 | else { 380 | c = current->next; 381 | } 382 | 383 | current = c; 384 | update_current(); 385 | } 386 | } 387 | 388 | void prev_desktop() { 389 | int tmp = current_desktop; 390 | if(tmp == 0) 391 | tmp = 9; 392 | else 393 | tmp--; 394 | 395 | Arg a = {.i = tmp}; 396 | change_desktop(a); 397 | } 398 | 399 | void prev_win() { 400 | client *c; 401 | 402 | if(current != NULL && head != NULL) { 403 | if(current->prev == NULL) 404 | for(c=head;c->next;c=c->next); 405 | else 406 | c = current->prev; 407 | 408 | current = c; 409 | update_current(); 410 | } 411 | } 412 | 413 | void quit() { 414 | Window root_return, parent; 415 | Window *children; 416 | int i; 417 | unsigned int nchildren; 418 | XEvent ev; 419 | 420 | /* 421 | * if a client refuses to terminate itself, 422 | * we kill every window remaining the brutal way. 423 | * Since we're stuck in the while(nchildren > 0) { ... } loop 424 | * we can't exit through the main method. 425 | * This all happens if MOD+q is pushed a second time. 426 | */ 427 | if(bool_quit == 1) { 428 | XUngrabKey(dis, AnyKey, AnyModifier, root); 429 | XDestroySubwindows(dis, root); 430 | fprintf(stdout, "catwm: Thanks for using!\n"); 431 | XCloseDisplay(dis); 432 | die("forced shutdown"); 433 | } 434 | 435 | bool_quit = 1; 436 | XQueryTree(dis, root, &root_return, &parent, &children, &nchildren); 437 | for(i = 0; i < nchildren; i++) { 438 | send_kill_signal(children[i]); 439 | } 440 | //keep alive until all windows are killed 441 | while(nchildren > 0) { 442 | XQueryTree(dis, root, &root_return, &parent, &children, &nchildren); 443 | XNextEvent(dis,&ev); 444 | if(events[ev.type]) 445 | events[ev.type](&ev); 446 | } 447 | 448 | XUngrabKey(dis,AnyKey,AnyModifier,root); 449 | fprintf(stdout,"catwm: Thanks for using!\n"); 450 | } 451 | 452 | void remove_window(Window w) { 453 | client *c; 454 | 455 | // CHANGE THIS UGLY CODE 456 | for(c=head;c;c=c->next) { 457 | 458 | if(c->win == w) { 459 | if(c->prev == NULL && c->next == NULL) { 460 | free(head); 461 | head = NULL; 462 | current = NULL; 463 | return; 464 | } 465 | 466 | if(c->prev == NULL) { 467 | head = c->next; 468 | c->next->prev = NULL; 469 | current = c->next; 470 | } 471 | else if(c->next == NULL) { 472 | c->prev->next = NULL; 473 | current = c->prev; 474 | } 475 | else { 476 | c->prev->next = c->next; 477 | c->next->prev = c->prev; 478 | current = c->prev; 479 | } 480 | 481 | free(c); 482 | return; 483 | } 484 | } 485 | } 486 | 487 | void save_desktop(int i) { 488 | desktops[i].master_size = master_size; 489 | desktops[i].mode = mode; 490 | desktops[i].head = head; 491 | desktops[i].current = current; 492 | } 493 | 494 | void select_desktop(int i) { 495 | head = desktops[i].head; 496 | current = desktops[i].current; 497 | master_size = desktops[i].master_size; 498 | mode = desktops[i].mode; 499 | current_desktop = i; 500 | } 501 | 502 | void send_kill_signal(Window w) { 503 | XEvent ke; 504 | ke.type = ClientMessage; 505 | ke.xclient.window = w; 506 | ke.xclient.message_type = XInternAtom(dis, "WM_PROTOCOLS", True); 507 | ke.xclient.format = 32; 508 | ke.xclient.data.l[0] = XInternAtom(dis, "WM_DELETE_WINDOW", True); 509 | ke.xclient.data.l[1] = CurrentTime; 510 | XSendEvent(dis, w, False, NoEventMask, &ke); 511 | } 512 | 513 | void setup() { 514 | // Install a signal 515 | sigchld(0); 516 | 517 | // Screen and root window 518 | screen = DefaultScreen(dis); 519 | root = RootWindow(dis,screen); 520 | 521 | // Screen width and height 522 | sw = XDisplayWidth(dis,screen); 523 | sh = XDisplayHeight(dis,screen); 524 | 525 | // Colors 526 | win_focus = getcolor(FOCUS); 527 | win_unfocus = getcolor(UNFOCUS); 528 | 529 | // Shortcuts 530 | grabkeys(); 531 | 532 | // Vertical stack 533 | mode = 0; 534 | 535 | // For exiting 536 | bool_quit = 0; 537 | 538 | // List of client 539 | head = NULL; 540 | current = NULL; 541 | 542 | // Master size 543 | master_size = sw*MASTER_SIZE; 544 | 545 | // Set up all desktop 546 | int i; 547 | for(i=0;iwin; 598 | head->win = current->win; 599 | current->win = tmp; 600 | current = head; 601 | 602 | tile(); 603 | update_current(); 604 | } 605 | } 606 | 607 | void switch_mode() { 608 | mode = (mode == 0) ? 1:0; 609 | tile(); 610 | update_current(); 611 | } 612 | 613 | void tile() { 614 | client *c; 615 | 616 | int border_space = BORDER_SIZE + GAP_SIZE; 617 | 618 | // If only one window 619 | if(head != NULL && head->next == NULL) { 620 | XMoveResizeWindow(dis,head->win,border_space,border_space,sw-3*border_space, sh-3*border_space); 621 | } 622 | else if(head != NULL) { 623 | switch(mode) { 624 | case 0: 625 | // Master window 626 | XMoveResizeWindow(dis,head->win,border_space,border_space,master_size,sh-2*border_space); 627 | 628 | // Stack 629 | int x = master_size + 3*border_space; 630 | int y = border_space; 631 | int tile_height = sw - master_size - 5*border_space; 632 | int num_windows = 0; 633 | 634 | for(c=head->next;c;c=c->next) ++num_windows; 635 | for(c=head->next;c;c=c->next) { 636 | XMoveResizeWindow(dis,c->win,x,y,tile_height,(sh/num_windows)-2*border_space); 637 | y += sh/num_windows; 638 | } 639 | break; 640 | case 1: 641 | for(c=head;c;c=c->next) { 642 | XMoveResizeWindow(dis,c->win,border_space,border_space,sw-2*border_space,sh-2*border_space); 643 | } 644 | break; 645 | default: 646 | break; 647 | } 648 | } 649 | } 650 | 651 | void update_current() { 652 | client *c; 653 | 654 | for(c=head;c;c=c->next) 655 | if(current == c) { 656 | // "Enable" current window 657 | XSetWindowBorderWidth(dis,c->win,BORDER_SIZE); 658 | XSetWindowBorder(dis,c->win,win_focus); 659 | XSetInputFocus(dis,c->win,RevertToParent,CurrentTime); 660 | XRaiseWindow(dis,c->win); 661 | } 662 | else 663 | XSetWindowBorder(dis,c->win,win_unfocus); 664 | } 665 | 666 | int main(int argc, char **argv) { 667 | // Open display 668 | if(!(dis = XOpenDisplay(NULL))) 669 | die("Cannot open display!"); 670 | 671 | // Setup env 672 | setup(); 673 | 674 | // Start wm 675 | start(); 676 | 677 | // Close display 678 | XCloseDisplay(dis); 679 | 680 | return 0; 681 | } 682 | 683 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * /\___/\ 3 | * ( o o ) Made by cat... 4 | * ( =^= ) 5 | * ( ) ... for cat! 6 | * ( ) 7 | * ( ))))))________________ Cute And Tiny Window Manager 8 | * ______________________________________________________________________________ 9 | * 10 | * Copyright (c) 2010, Rinaldini Julien, julien.rinaldini@heig-vd.ch 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a 13 | * copy of this software and associated documentation files (the "Software"), 14 | * to deal in the Software without restriction, including without limitation 15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 | * and/or sell copies of the Software, and to permit persons to whom the 17 | * Software is furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | * DEALINGS IN THE SOFTWARE. 29 | * 30 | */ 31 | 32 | #ifndef CONFIG_H 33 | #define CONFIG_H 34 | 35 | // Mod (Mod1 == alt) and master size 36 | #define MOD Mod1Mask 37 | #define MASTER_SIZE 0.6 38 | 39 | // Colors 40 | #define FOCUS "rgb:bc/57/66" 41 | #define UNFOCUS "rgb:88/88/88" 42 | 43 | // Borders and gap 44 | #define BORDER_SIZE 5 45 | #define GAP_SIZE 5 46 | 47 | const char* dmenucmd[] = {"dmenu_run",NULL}; 48 | const char* urxvtcmd[] = {"urxvt",NULL}; 49 | const char* lockcmd[] = {"slock",NULL}; 50 | const char* next[] = {"ncmpcpp","next",NULL}; 51 | const char* prev[] = {"ncmpcpp","prev",NULL}; 52 | const char* toggle[] = {"ncmpcpp","toggle",NULL }; 53 | const char* voldown[] = {"amixer","set","PCM","5\%-",NULL}; 54 | const char* volup[] = {"amixer","set","PCM","5\%+",NULL}; 55 | 56 | // Avoid multiple paste 57 | #define DESKTOPCHANGE(K,N) \ 58 | { MOD, K, change_desktop, {.i = N}}, \ 59 | { MOD|ShiftMask, K, client_to_desktop, {.i = N}}, 60 | 61 | // Shortcuts 62 | static struct key keys[] = { 63 | // MOD KEY FUNCTION ARGS 64 | { MOD, XK_h, decrease, {NULL}}, 65 | { MOD, XK_l, increase, {NULL}}, 66 | { MOD, XK_x, kill_client, {NULL}}, 67 | { MOD, XK_j, next_win, {NULL}}, 68 | { MOD, XK_Tab, next_win, {NULL}}, 69 | { MOD, XK_k, prev_win, {NULL}}, 70 | { MOD|ShiftMask, XK_j, move_up, {NULL}}, 71 | { MOD|ShiftMask, XK_k, move_down, {NULL}}, 72 | { MOD, XK_Return, swap_master, {NULL}}, 73 | { MOD, XK_space, switch_mode, {NULL}}, 74 | { MOD, XK_c, spawn, {.com = lockcmd}}, 75 | { 0, XF86XK_AudioNext, spawn, {.com = next}}, 76 | { 0, XF86XK_AudioPrev, spawn, {.com = prev}}, 77 | { 0, XF86XK_AudioPlay, spawn, {.com = toggle}}, 78 | { 0, XF86XK_AudioLowerVolume, spawn, {.com = voldown}}, 79 | { 0, XF86XK_AudioRaiseVolume, spawn, {.com = volup}}, 80 | { MOD, XK_p, spawn, {.com = dmenucmd}}, 81 | { MOD|ShiftMask, XK_Return, spawn, {.com = urxvtcmd}}, 82 | { MOD, XK_Right, next_desktop, {NULL}}, 83 | { MOD, XK_Left, prev_desktop, {NULL}}, 84 | DESKTOPCHANGE( XK_0, 0) 85 | DESKTOPCHANGE( XK_1, 1) 86 | DESKTOPCHANGE( XK_2, 2) 87 | DESKTOPCHANGE( XK_3, 3) 88 | DESKTOPCHANGE( XK_4, 4) 89 | DESKTOPCHANGE( XK_5, 5) 90 | DESKTOPCHANGE( XK_6, 6) 91 | DESKTOPCHANGE( XK_7, 7) 92 | DESKTOPCHANGE( XK_8, 8) 93 | DESKTOPCHANGE( XK_9, 9) 94 | { MOD, XK_q, quit, {NULL}} 95 | }; 96 | 97 | #endif 98 | 99 | --------------------------------------------------------------------------------