JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
More focus simplicfication
[spectrwm.git] / scrotwm.c
index 4885e6a..b5e2ffb 100644 (file)
--- a/scrotwm.c
+++ b/scrotwm.c
@@ -132,6 +132,9 @@ int                 ignore_enter = 0;
 unsigned int           numlockmask = 0;
 Display                        *display;
 
+int                    cycle_empty = 0;
+int                    cycle_visible = 0;
+
 /* dialog windows */
 double                 dialog_ratio = .6;
 /* status bar */
@@ -179,7 +182,7 @@ struct ws_win {
        TAILQ_ENTRY(ws_win)     entry;
        Window                  id;
        struct swm_geometry     g;
-       int                     focus;
+       int                     got_focus;
        int                     floating;
        int                     transient;
        struct workspace        *ws;    /* always valid */
@@ -265,6 +268,8 @@ union arg {
 #define SWM_ARG_ID_MASTERDEL   (9)
 #define SWM_ARG_ID_STACKRESET  (10)
 #define SWM_ARG_ID_STACKINIT   (11)
+#define SWM_ARG_ID_CYCLEWS_UP  (12)
+#define SWM_ARG_ID_CYCLEWS_DOWN        (13)
        char                    **argv;
 };
 
@@ -418,6 +423,10 @@ conf_load(char *filename)
                                                    name_to_color(val);
                                else
                                        goto badidx;
+                       else if (!strncmp(var, "cycle_empty", strlen("cycle_empty")))
+                               cycle_visible = atoi(val);
+                       else if (!strncmp(var, "cycle_visible", strlen("cycle_visible")))
+                               cycle_visible = atoi(val);
                        else
                                goto bad;
                        break;
@@ -564,7 +573,8 @@ bar_refresh(void)
                TAILQ_FOREACH(r, &screens[i].rl, entry) {
                        wa.border_pixel = screens[i].bar_border;
                        wa.background_pixel = screens[i].bar_color;
-                       XChangeWindowAttributes(display, r->bar_window, CWBackPixel | CWBorderPixel, &wa);
+                       XChangeWindowAttributes(display, r->bar_window,
+                           CWBackPixel | CWBorderPixel, &wa);
                }
        bar_update();
 }
@@ -702,36 +712,43 @@ spawn(struct swm_region *r, union arg *args)
 }
 
 void
-unfocus_win(struct ws_win *win)
+unfocus_all(void)
 {
-       DNPRINTF(SWM_D_FOCUS, "unfocus_win: id: %lu\n", win->id);
-       if (win->ws->r && win->focus)
-               XSetWindowBorder(display, win->id,
-                   win->ws->r->s->color_unfocus);
-       win->focus = 0;
-       if (win->ws->focus == win)
-               win->ws->focus = NULL;
-       if (cur_focus == win)
-               cur_focus = NULL;
-}
+       struct ws_win           *win;
+       int                     i, j;
+
+       DNPRINTF(SWM_D_FOCUS, "unfocus_all:\n");
 
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
+                               if (win->ws->r == NULL)
+                                       continue;
+                               XSetWindowBorder(display, win->id,
+                                   win->ws->r->s->color_unfocus);
+                               win->got_focus = 0;
+                               win->ws->focus = NULL;
+                               cur_focus = NULL;
+                       }
+}
 
 void
 focus_win(struct ws_win *win)
 {
-       DNPRINTF(SWM_D_FOCUS, "focus_win: id: %lu\n", win->id);
+       DNPRINTF(SWM_D_FOCUS, "focus_win: id: %lu\n", win ? win->id : 0);
 
-       rootclick = 0;
+       if (win == NULL)
+               return;
 
+       rootclick = 0;
+       unfocus_all();
        win->ws->focus = win;
        if (win->ws->r != NULL) {
-               if (cur_focus && cur_focus != win)
-                       unfocus_win(cur_focus);
                cur_focus = win;
-               if (!win->focus)
+               if (!win->got_focus)
                        XSetWindowBorder(display, win->id,
                            win->ws->r->s->color_focus);
-               win->focus = 1;
+               win->got_focus = 1;
                XSetInputFocus(display, win->id,
                    RevertToPointerRoot, CurrentTime);
        }
@@ -784,6 +801,45 @@ switchws(struct swm_region *r, union arg *args)
 }
 
 void
+cyclews(struct swm_region *r, union arg *args)
+{
+       union                   arg a;
+       struct swm_screen       *s = r->s;
+
+       DNPRINTF(SWM_D_WS, "cyclews id %d "
+           "in screen %d region %dx%d+%d+%d ws %d\n", args->id,
+           r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
+
+       a.id = r->ws->idx;
+
+       do {
+               switch (args->id) {
+               case SWM_ARG_ID_CYCLEWS_UP:
+                       if (a.id < SWM_WS_MAX - 1)
+                               a.id++;
+                       else
+                               a.id = 0;
+                       break;
+               case SWM_ARG_ID_CYCLEWS_DOWN:
+                       if (a.id > 0)
+                               a.id--;
+                       else
+                               a.id = SWM_WS_MAX - 1;
+                       break;
+               default:
+                       return;
+               };
+
+               if (cycle_empty == 0 && TAILQ_EMPTY(&s->ws[a.id].winlist))
+                       continue;
+               if (cycle_visible == 0 && s->ws[a.id].r != NULL)
+                       continue;
+
+               switchws(r, &a);
+       } while (a.id != r->ws->idx);
+}
+
+void
 swapwin(struct swm_region *r, union arg *args)
 {
        struct ws_win           *target;
@@ -1280,6 +1336,8 @@ struct key {
        { 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_1,           send_to_ws,     {.id = 0} },
        { MODKEY | ShiftMask,   XK_2,           send_to_ws,     {.id = 1} },
        { MODKEY | ShiftMask,   XK_3,           send_to_ws,     {.id = 2} },
@@ -1295,6 +1353,21 @@ struct key {
        { MODKEY | ShiftMask,   XK_Tab,         focus,          {.id = SWM_ARG_ID_FOCUSPREV} },
 };
 
+#if 0
+/* mouse */
+enum { client_click, root_click };
+struct button {
+       unsigned int            click;
+       unsigned int            mask;
+       unsigned int            button;
+       void                    (*func)(struct swm_region *r, union arg *);
+       union arg               args;
+} buttons[] = {
+         /* action             key             mouse button    func            args */
+       { client_click,         MODKEY,         Button2,        NULL, {0} },
+};
+#endif
+
 void
 updatenumlockmask(void)
 {
@@ -1534,11 +1607,12 @@ destroynotify(XEvent *e)
 {
        struct ws_win           *win;
        XDestroyWindowEvent     *ev = &e->xdestroywindow;
+       struct workspace        *ws;
 
        DNPRINTF(SWM_D_EVENT, "destroynotify: window %lu\n", ev->window);
 
        if ((win = find_window(ev->window)) != NULL) {
-               struct workspace *ws = win->ws;
+               ws = win->ws;
                /* find a window to focus */
                if (ws->focus == win)
                        ws->focus = TAILQ_PREV(win, ws_win_list, entry);
@@ -1546,12 +1620,8 @@ destroynotify(XEvent *e)
                        ws->focus = TAILQ_FIRST(&ws->winlist);
                if (ws->focus == win)
                        ws->focus = NULL;
-               if (cur_focus == win) {
-                       if (ws->focus == NULL) 
-                               unfocus_win(win); /* XXX focus another ws? */
-                       else
-                               focus_win(ws->focus);
-               }
+               if (cur_focus == win)
+                       focus_win(ws->focus);
 
                TAILQ_REMOVE(&ws->winlist, win, entry);
                set_win_state(win, WithdrawnState);
@@ -1565,27 +1635,17 @@ enternotify(XEvent *e)
 {
        XCrossingEvent          *ev = &e->xcrossing;
        struct ws_win           *win;
-       int                     i, j;
 
        DNPRINTF(SWM_D_EVENT, "enternotify: window: %lu\n", ev->window);
 
-       if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) &&
-           ev->window != ev->root)
-               return;
        if (ignore_enter) {
                /* eat event(r) to prevent autofocus */
                ignore_enter--;
                return;
        }
-       /* brute force for now */
-       for (i = 0; i < ScreenCount(display); i++) {
-               for (j = 0; j < SWM_WS_MAX; j++) {
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist , entry) {
-                               if (win->id == ev->window)
-                                       focus_win(win);
-                       }
-               }
-       }
+
+       if ((win = find_window(ev->window)) != NULL)
+               focus_win(win);
 }
 
 void
@@ -1787,7 +1847,7 @@ setup_screens(void)
                screens[i].root = RootWindow(display, i);
                XGetWindowAttributes(display, screens[i].root, &wa);
                XSelectInput(display, screens[i].root,
-                   ButtonPressMask | wa.your_event_mask);
+                   EnterWindowMask | ButtonPressMask | wa.your_event_mask);
 
                /* set default colors */
                screens[i].color_focus = name_to_color("red");