JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Add version stuff
[spectrwm.git] / scrotwm.c
index 520f156..d6f4d23 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -126,6 +126,7 @@ u_int32_t           swm_debug = 0
 #define MODKEY                 Mod1Mask
 #define CLEANMASK(mask)                (mask & ~(numlockmask | LockMask))
 #define BUTTONMASK             (ButtonPressMask|ButtonReleaseMask)
+#define MOUSEMASK              (BUTTONMASK|PointerMotionMask)
 #define SWM_PROPLEN            (16)
 #define X(r)                   (r)->g.x        
 #define Y(r)                   (r)->g.y
@@ -157,6 +158,8 @@ double                      dialog_ratio = .6;
 char                   *bar_argv[] = { NULL, NULL };
 int                    bar_pipe[2];
 char                   bar_ext[SWM_BAR_MAX];
+char                   bar_vertext[SWM_BAR_MAX];
+int                    bar_version = 0;
 sig_atomic_t           bar_alarm = 0;
 int                    bar_delay = 30;
 int                    bar_enabled = 1;
@@ -312,6 +315,7 @@ union arg {
        char                    **argv;
 };
 
+/* quirks */
 struct quirk {
        char                    *class;
        char                    *name;
@@ -323,6 +327,37 @@ struct quirk {
        { NULL,         NULL,           0},
 };
 
+/* events */
+void                   expose(XEvent *);
+void                   keypress(XEvent *);
+void                   buttonpress(XEvent *);
+void                   configurerequest(XEvent *);
+void                   configurenotify(XEvent *);
+void                   destroynotify(XEvent *);
+void                   enternotify(XEvent *);
+void                   focusin(XEvent *);
+void                   mappingnotify(XEvent *);
+void                   maprequest(XEvent *);
+void                   propertynotify(XEvent *);
+void                   unmapnotify(XEvent *);
+void                   visibilitynotify(XEvent *);
+
+void                   (*handler[LASTEvent])(XEvent *) = {
+                               [Expose] = expose,
+                               [KeyPress] = keypress,
+                               [ButtonPress] = buttonpress,
+                               [ConfigureRequest] = configurerequest,
+                               [ConfigureNotify] = configurenotify,
+                               [DestroyNotify] = destroynotify,
+                               [EnterNotify] = enternotify,
+                               [FocusIn] = focusin,
+                               [MappingNotify] = mappingnotify,
+                               [MapRequest] = maprequest,
+                               [PropertyNotify] = propertynotify,
+                               [UnmapNotify] = unmapnotify,
+                               [VisibilityNotify] = visibilitynotify,
+};
+
 unsigned long
 name_to_color(char *colorname)
 {
@@ -566,8 +601,8 @@ bar_update(void)
        for (i = 0; i < ScreenCount(display); i++) {
                x = 1;
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
-                       snprintf(loc, sizeof loc, "%s     %d:%d    %s",
-                           s, x++, r->ws->idx + 1, bar_ext);
+                       snprintf(loc, sizeof loc, "%s     %d:%d    %s    %s",
+                           s, x++, r->ws->idx + 1, bar_ext, bar_vertext);
                        bar_print(r, loc);
                }
        }
@@ -693,6 +728,17 @@ bar_setup(struct swm_region *r)
 }
 
 void
+version(struct swm_region *r, union arg *args)
+{
+       bar_version = !bar_version;
+       if (bar_version)
+               strlcpy(bar_vertext, cvstag, sizeof bar_vertext);
+       else
+               strlcpy(bar_vertext, "", sizeof bar_vertext);
+       bar_update();
+}
+
+void
 config_win(struct ws_win *win)
 {
        XConfigureEvent         ce;
@@ -1482,6 +1528,9 @@ send_to_ws(struct swm_region *r, union arg *args)
        Atom                    ws_idx_atom = 0;
        unsigned char           ws_idx_str[SWM_PROPLEN];
 
+       if (win == NULL)
+               return;
+
        DNPRINTF(SWM_D_MOVE, "send_to_ws: win: %lu\n", win->id);
 
        ws = win->ws;
@@ -1605,23 +1654,133 @@ struct key {
        { MODKEY | ShiftMask,   XK_x,           wkill,          {0} },
        { MODKEY,               XK_s,           screenshot,     {.id = SWM_ARG_ID_SS_ALL} },
        { MODKEY | ShiftMask,   XK_s,           screenshot,     {.id = SWM_ARG_ID_SS_WINDOW} },
+       { MODKEY | ShiftMask,   XK_v,           version,        {0} },
 };
 
 void
-click(struct swm_region *r, union arg *args)
+resize_window(struct ws_win *win)
 {
-       DNPRINTF(SWM_D_MOUSE, "click: button: %d\n", args->id);
+       unsigned int            mask;
+       XWindowChanges          wc;
+       struct swm_region       *r;
 
-       switch (args->id) {
-       case Button1:
-               break;
-       case Button2:
-               break;
-       case Button3:
-               break;
-       default:
+       r = root_to_region(win->wa.root);
+       bzero(&wc, sizeof wc);
+       mask = CWX | CWY | CWBorderWidth | CWWidth | CWHeight;
+       wc.border_width = 1;
+       wc.width = win->g.w;
+       wc.height = win->g.h;
+       wc.x = (WIDTH(r) - win->g.w) / 2;
+       wc.y = (HEIGHT(r) - win->g.h) / 2;
+
+       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;
+
+       DNPRINTF(SWM_D_MOUSE, "resize: win %d 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:
+                       XSync(display, False);
+                       if (ev.xmotion.x < 0)
+                               ev.xmotion.x = 0;
+                       if (ev.xmotion.y < 0)
+                               ev.xmotion.y = 0;
+                       win->g.w = ev.xmotion.x;
+                       win->g.h = ev.xmotion.y;
+                       resize_window(win);
+                       break;
+               }
+       } while (ev.type != ButtonRelease);
+       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;
+
+       DNPRINTF(SWM_D_MOUSE, "move: win %d 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, 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:
+                       XSync(display, False);
+                       win->g.x = ev.xmotion.x_root;
+                       win->g.y = ev.xmotion.y_root;
+                       move_window(win);
+                       break;
+               }
+       } while (ev.type != ButtonRelease);
+       XWarpPointer(display, None, win->id, 0, 0, 0, 0, 0, 0);
+       XUngrabPointer(display, CurrentTime);
+
+       /* drain events */
+       while (XCheckMaskEvent(display, EnterWindowMask, &ev));
 }
 
 /* mouse */
@@ -1630,11 +1789,12 @@ struct button {
        unsigned int            action;
        unsigned int            mask;
        unsigned int            button;
-       void                    (*func)(struct swm_region *r, union arg *);
+       void                    (*func)(struct ws_win *, union arg *);
        union arg               args;
 } buttons[] = {
          /* action             key             mouse button    func            args */
-       { client_click,         MODKEY,         Button1,        click, {.id=Button1} },
+       { client_click,         MODKEY,         Button3,        resize,         {0} },
+       { client_click,         MODKEY,         Button1,        move,           {0} },
 };
 
 void
@@ -1750,8 +1910,7 @@ buttonpress(XEvent *e)
                if (action == buttons[i].action && buttons[i].func &&
                    buttons[i].button == ev->button &&
                    CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
-                       buttons[i].func(root_to_region(ev->root),
-                       &buttons[i].args);
+                       buttons[i].func(win, &buttons[i].args);
 }
 
 void
@@ -2075,22 +2234,6 @@ visibilitynotify(XEvent *e)
                                        bar_update();
 }
 
-void                   (*handler[LASTEvent])(XEvent *) = {
-                               [Expose] = expose,
-                               [KeyPress] = keypress,
-                               [ButtonPress] = buttonpress,
-                               [ConfigureRequest] = configurerequest,
-                               [ConfigureNotify] = configurenotify,
-                               [DestroyNotify] = destroynotify,
-                               [EnterNotify] = enternotify,
-                               [FocusIn] = focusin,
-                               [MappingNotify] = mappingnotify,
-                               [MapRequest] = maprequest,
-                               [PropertyNotify] = propertynotify,
-                               [UnmapNotify] = unmapnotify,
-                               [VisibilityNotify] = visibilitynotify,
-};
-
 int
 xerror_start(Display *d, XErrorEvent *ee)
 {