+ switch (args->id) {
+ case SWM_ARG_ID_SS_ALL:
+ spawn_screenshot[1] = "full";
+ break;
+ case SWM_ARG_ID_SS_WINDOW:
+ spawn_screenshot[1] = "window";
+ break;
+ default:
+ return;
+ }
+ a.argv = spawn_screenshot;
+ spawn(r, &a);
+}
+
+void
+floating_toggle(struct swm_region *r, union arg *args)
+{
+ struct ws_win *win = cur_focus;
+
+ if (win == NULL)
+ return;
+
+ win->floating = !win->floating;
+ win->manual = 0;
+ stack();
+ focus_win(win);
+}
+
+/* key definitions */
+struct key {
+ unsigned int mod;
+ KeySym keysym;
+ void (*func)(struct swm_region *r, union arg *);
+ union arg args;
+} keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_space, cycle_layout, {0} },
+ { MODKEY | ShiftMask, XK_space, stack_config, {.id = SWM_ARG_ID_STACKRESET} },
+ { MODKEY, XK_h, stack_config, {.id = SWM_ARG_ID_MASTERSHRINK} },
+ { MODKEY, XK_l, stack_config, {.id = SWM_ARG_ID_MASTERGROW} },
+ { MODKEY, XK_comma, stack_config, {.id = SWM_ARG_ID_MASTERADD} },
+ { MODKEY, XK_period, stack_config, {.id = SWM_ARG_ID_MASTERDEL} },
+ { MODKEY | ShiftMask, XK_comma, stack_config, {.id = SWM_ARG_ID_STACKINC} },
+ { MODKEY | ShiftMask, XK_period, stack_config, {.id = SWM_ARG_ID_STACKDEC} },
+ { MODKEY, XK_Return, swapwin, {.id = SWM_ARG_ID_SWAPMAIN} },
+ { MODKEY, XK_j, focus, {.id = SWM_ARG_ID_FOCUSNEXT} },
+ { MODKEY, XK_k, focus, {.id = SWM_ARG_ID_FOCUSPREV} },
+ { MODKEY | ShiftMask, XK_j, swapwin, {.id = SWM_ARG_ID_SWAPNEXT} },
+ { MODKEY | ShiftMask, XK_k, swapwin, {.id = SWM_ARG_ID_SWAPPREV} },
+ { MODKEY | ShiftMask, XK_Return, spawnterm, {.argv = spawn_term} },
+ { MODKEY, XK_p, spawnmenu, {.argv = spawn_menu} },
+ { MODKEY | ShiftMask, XK_q, quit, {0} },
+ { MODKEY, XK_q, restart, {0} },
+ { MODKEY, XK_m, focus, {.id = SWM_ARG_ID_FOCUSMAIN} },
+ { MODKEY, XK_1, switchws, {.id = 0} },
+ { MODKEY, XK_2, switchws, {.id = 1} },
+ { MODKEY, XK_3, switchws, {.id = 2} },
+ { MODKEY, XK_4, switchws, {.id = 3} },
+ { MODKEY, XK_5, switchws, {.id = 4} },
+ { MODKEY, XK_6, switchws, {.id = 5} },
+ { MODKEY, XK_7, switchws, {.id = 6} },
+ { MODKEY, XK_8, switchws, {.id = 7} },
+ { MODKEY, XK_9, switchws, {.id = 8} },
+ { MODKEY, XK_0, switchws, {.id = 9} },
+ { MODKEY, XK_Right, cyclews, {.id = SWM_ARG_ID_CYCLEWS_UP} },
+ { MODKEY, XK_Left, cyclews, {.id = SWM_ARG_ID_CYCLEWS_DOWN} },
+ { MODKEY | ShiftMask, XK_Right, cyclescr, {.id = SWM_ARG_ID_CYCLESC_UP} },
+ { MODKEY | ShiftMask, XK_Left, cyclescr, {.id = SWM_ARG_ID_CYCLESC_DOWN} },
+ { MODKEY | ShiftMask, XK_1, send_to_ws, {.id = 0} },
+ { MODKEY | ShiftMask, XK_2, send_to_ws, {.id = 1} },
+ { MODKEY | ShiftMask, XK_3, send_to_ws, {.id = 2} },
+ { MODKEY | ShiftMask, XK_4, send_to_ws, {.id = 3} },
+ { MODKEY | ShiftMask, XK_5, send_to_ws, {.id = 4} },
+ { MODKEY | ShiftMask, XK_6, send_to_ws, {.id = 5} },
+ { MODKEY | ShiftMask, XK_7, send_to_ws, {.id = 6} },
+ { MODKEY | ShiftMask, XK_8, send_to_ws, {.id = 7} },
+ { MODKEY | ShiftMask, XK_9, send_to_ws, {.id = 8} },
+ { MODKEY | ShiftMask, XK_0, send_to_ws, {.id = 9} },
+ { MODKEY, XK_b, bar_toggle, {0} },
+ { MODKEY, XK_Tab, focus, {.id = SWM_ARG_ID_FOCUSNEXT} },
+ { MODKEY | ShiftMask, XK_Tab, focus, {.id = SWM_ARG_ID_FOCUSPREV} },
+ { MODKEY | ShiftMask, XK_x, wkill, {.id = SWM_ARG_ID_KILLWINDOW} },
+ { MODKEY, XK_x, wkill, {.id = SWM_ARG_ID_DELETEWINDOW} },
+ { MODKEY, XK_s, screenshot, {.id = SWM_ARG_ID_SS_ALL} },
+ { MODKEY | ShiftMask, XK_s, screenshot, {.id = SWM_ARG_ID_SS_WINDOW} },
+ { MODKEY, XK_t, floating_toggle,{0} },
+ { MODKEY | ShiftMask, XK_v, version, {0} },
+ { MODKEY | ShiftMask, XK_Delete, spawn, {.argv = spawn_lock} },
+ { MODKEY | ShiftMask, XK_i, spawn, {.argv = spawn_initscr} },
+};
+
+void
+resize_window(struct ws_win *win, int center)
+{
+ unsigned int mask;
+ XWindowChanges wc;
+ struct swm_region *r;
+
+ r = root_to_region(win->wa.root);
+ bzero(&wc, sizeof wc);
+ mask = CWBorderWidth | CWWidth | CWHeight;
+ wc.border_width = 1;
+ wc.width = win->g.w;
+ wc.height = win->g.h;
+ if (center == SWM_ARG_ID_CENTER) {
+ wc.x = (WIDTH(r) - win->g.w) / 2;
+ wc.y = (HEIGHT(r) - win->g.h) / 2;
+ mask |= CWX | CWY;
+ }
+
+ DNPRINTF(SWM_D_STACK, "resize_window: win %lu x %d y %d w %d h %d\n",
+ win->id, wc.x, wc.y, wc.width, wc.height);
+
+ XConfigureWindow(display, win->id, mask, &wc);
+ config_win(win);
+}
+
+void
+resize(struct ws_win *win, union arg *args)
+{
+ XEvent ev;
+ Time time = 0;
+
+ DNPRINTF(SWM_D_MOUSE, "resize: win %lu floating %d trans %d\n",
+ win->id, win->floating, win->transient);
+
+ if (!(win->transient != 0 || win->floating != 0))
+ return;
+
+ if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
+ GrabModeAsync, None, None /* cursor */, CurrentTime) != GrabSuccess)
+ return;
+ XWarpPointer(display, None, win->id, 0, 0, 0, 0, win->g.w, win->g.h);
+ do {
+ XMaskEvent(display, MOUSEMASK | ExposureMask |
+ SubstructureRedirectMask, &ev);
+ switch(ev.type) {
+ case ConfigureRequest:
+ case Expose:
+ case MapRequest:
+ handler[ev.type](&ev);
+ break;
+ case MotionNotify:
+ if (ev.xmotion.x <= 1)
+ ev.xmotion.x = 1;
+ if (ev.xmotion.y <= 1)
+ ev.xmotion.y = 1;
+ win->g.w = ev.xmotion.x;
+ win->g.h = ev.xmotion.y;
+
+ /* not free, don't sync more than 60 times / second */
+ if ((ev.xmotion.time - time) > (1000 / 60) ) {
+ time = ev.xmotion.time;
+ XSync(display, False);
+ resize_window(win, args->id);
+ }
+ break;
+ }
+ } while (ev.type != ButtonRelease);
+ if (time) {
+ XSync(display, False);
+ resize_window(win, args->id);
+ }
+ XWarpPointer(display, None, win->id, 0, 0, 0, 0, win->g.w - 1,
+ win->g.h - 1);
+ XUngrabPointer(display, CurrentTime);
+
+ /* drain events */
+ while (XCheckMaskEvent(display, EnterWindowMask, &ev));
+}
+
+void
+move_window(struct ws_win *win)
+{
+ unsigned int mask;
+ XWindowChanges wc;
+ struct swm_region *r;
+
+ r = root_to_region(win->wa.root);
+ bzero(&wc, sizeof wc);
+ mask = CWX | CWY;
+ wc.x = win->g.x;
+ wc.y = win->g.y;
+
+ DNPRINTF(SWM_D_STACK, "move_window: win %lu x %d y %d w %d h %d\n",
+ win->id, wc.x, wc.y, wc.width, wc.height);
+
+ XConfigureWindow(display, win->id, mask, &wc);
+ config_win(win);
+}
+
+void
+move(struct ws_win *win, union arg *args)
+{
+ XEvent ev;
+ Time time = 0;
+ int restack = 0;
+
+ DNPRINTF(SWM_D_MOUSE, "move: win %lu floating %d trans %d\n",
+ win->id, win->floating, win->transient);
+
+ if (win->floating == 0) {
+ win->floating = 1;
+ win->manual = 1;
+ restack = 1;
+ }
+
+ if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
+ GrabModeAsync, None, None /* cursor */, CurrentTime) != GrabSuccess)
+ return;
+ XWarpPointer(display, None, win->id, 0, 0, 0, 0, 0, 0);
+ do {
+ XMaskEvent(display, MOUSEMASK | ExposureMask |
+ SubstructureRedirectMask, &ev);
+ switch(ev.type) {
+ case ConfigureRequest:
+ case Expose:
+ case MapRequest:
+ handler[ev.type](&ev);
+ break;
+ case MotionNotify:
+ win->g.x = ev.xmotion.x_root;
+ win->g.y = ev.xmotion.y_root;
+
+ /* not free, don't sync more than 60 times / second */
+ if ((ev.xmotion.time - time) > (1000 / 60) ) {
+ time = ev.xmotion.time;
+ XSync(display, False);
+ move_window(win);
+ }
+ break;
+ }
+ } while (ev.type != ButtonRelease);
+ if (time) {
+ XSync(display, False);
+ move_window(win);
+ }
+ XWarpPointer(display, None, win->id, 0, 0, 0, 0, 0, 0);
+ XUngrabPointer(display, CurrentTime);
+ if (restack)
+ stack();