JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
merge upstream
[spectrwm.git] / spectrwm.c
index 0ca00bb..dbcd5f6 100644 (file)
@@ -368,7 +368,7 @@ enum {
 /* dialog windows */
 double                 dialog_ratio = 0.6;
 /* status bar */
-#define SWM_BAR_MAX            (256)
+#define SWM_BAR_MAX            (356)
 #define SWM_BAR_JUSTIFY_LEFT   (0)
 #define SWM_BAR_JUSTIFY_CENTER (1)
 #define SWM_BAR_JUSTIFY_RIGHT  (2)
@@ -402,6 +402,9 @@ bool                 stack_enabled = true;
 bool            clock_enabled = true;
 bool            iconic_enabled = false;
 bool            urgent_enabled = false;
+int             composite_enabled = 0;
+double          opacity_focus = 1.0;
+double          opacity_unfocus = 0.6;
 bool            urgent_collapse = false;
 char           *clock_format = NULL;
 bool            window_class_enabled = false;
@@ -519,7 +522,7 @@ struct layout {
 } layouts[] =  {
        /* stack,               configure */
        { vertical_stack,       vertical_config,        0,      plain_stacker },
-       { horizontal_stack,     horizontal_config,      0,      plain_stacker },
+//     { horizontal_stack,     horizontal_config,      0,      plain_stacker },
        { max_stack,            NULL,
          SWM_L_MAPONFOCUS | SWM_L_FOCUSPREV,                   plain_stacker },
        { NULL,                 NULL,                   0,      NULL  },
@@ -528,7 +531,7 @@ struct layout {
 /* position of max_stack mode in the layouts array, index into layouts! */
 #define SWM_V_STACK            (0)
 #define SWM_H_STACK            (1)
-#define SWM_MAX_STACK          (2)
+#define SWM_MAX_STACK          (1)
 
 #define SWM_H_SLICE            (32)
 #define SWM_V_SLICE            (32)
@@ -713,6 +716,7 @@ enum {
        _NET_WM_STATE_MAXIMIZED_HORZ,
        _NET_WM_STATE_SKIP_PAGER,
        _NET_WM_STATE_SKIP_TASKBAR,
+       _NET_WM_WINDOW_OPACITY,
        _NET_WM_WINDOW_TYPE,
        _NET_WM_WINDOW_TYPE_DIALOG,
        _NET_WM_WINDOW_TYPE_DOCK,
@@ -756,6 +760,7 @@ struct ewmh_hint {
     {"_NET_WM_STATE_MAXIMIZED_HORZ", XCB_ATOM_NONE},
     {"_NET_WM_STATE_SKIP_PAGER", XCB_ATOM_NONE},
     {"_NET_WM_STATE_SKIP_TASKBAR", XCB_ATOM_NONE},
+    {"_NET_WM_WINDOW_OPACITY", XCB_ATOM_NONE},
     {"_NET_WM_WINDOW_TYPE", XCB_ATOM_NONE},
     {"_NET_WM_WINDOW_TYPE_DIALOG", XCB_ATOM_NONE},
     {"_NET_WM_WINDOW_TYPE_DOCK", XCB_ATOM_NONE},
@@ -1041,6 +1046,7 @@ char      *get_source_type_label(uint32_t);
 char   *get_stack_mode_name(uint8_t);
 #endif
 int32_t         get_swm_ws(xcb_window_t);
+bool    get_urgent(struct ws_win *);
 char   *get_win_name(xcb_window_t);
 uint8_t         get_win_state(xcb_window_t);
 void    get_wm_protocols(struct ws_win *);
@@ -1133,6 +1139,7 @@ void       setup_quirks(void);
 void    setup_screens(void);
 void    setup_spawn(void);
 void    set_child_transient(struct ws_win *, xcb_window_t *);
+void    set_opacity(struct ws_win *, uint32_t);
 void    set_win_state(struct ws_win *, uint8_t);
 void    shutdown_cleanup(void);
 void    sighdlr(int);
@@ -2168,6 +2175,22 @@ bar_window_name(char *s, size_t sz, struct swm_region *r)
        free(title);
 }
 
+bool
+get_urgent(struct ws_win *win)
+{
+       xcb_icccm_wm_hints_t            hints;
+       xcb_get_property_cookie_t       c;
+       bool                            urgent = false;
+
+       if (win) {
+               c = xcb_icccm_get_wm_hints(conn, win->id);
+               if (xcb_icccm_get_wm_hints_reply(conn, c, &hints, NULL))
+                       urgent = xcb_icccm_wm_hints_get_urgency(&hints);
+       }
+
+       return urgent;
+}
+
 void
 bar_urgent(char *s, size_t sz)
 {
@@ -2175,8 +2198,6 @@ bar_urgent(char *s, size_t sz)
        int                     i, j, num_screens;
        bool                    urgent[SWM_WS_MAX];
        char                    b[8];
-       xcb_get_property_cookie_t       c;
-       xcb_icccm_wm_hints_t    hints;
 
        for (i = 0; i < workspace_limit; i++)
                urgent[i] = false;
@@ -2184,14 +2205,8 @@ bar_urgent(char *s, size_t sz)
        num_screens = get_screen_count();
        for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
-                               c = xcb_icccm_get_wm_hints(conn, win->id);
-                               if (xcb_icccm_get_wm_hints_reply(conn, c,
-                                   &hints, NULL) == 0)
-                                       continue;
-                               if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)
-                                       urgent[j] = true;
-                       }
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               urgent[j] = get_urgent(win);
 
        for (i = 0; i < workspace_limit; i++) {
                if (urgent[i]) {
@@ -3220,6 +3235,9 @@ center_pointer(struct swm_region *r)
                return;
 
        win = r->ws->focus;
+
+       DNPRINTF(SWM_D_EVENT, "center_pointer: win %#x.\n", WINID(win));
+
        if (win && win->mapped)
                xcb_warp_pointer(conn, XCB_NONE, win->id, 0, 0, 0, 0,
                    WIDTH(win) / 2, HEIGHT(win) / 2);
@@ -3458,6 +3476,19 @@ validate_ws(struct workspace *testws)
        return (1);
 }
 
+#define OPAQUE         0xffffffff
+void
+set_opacity(struct ws_win *win, uint32_t opacity)
+{
+       if (opacity != OPAQUE)
+               xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
+                   ewmh[_NET_WM_WINDOW_OPACITY].atom, XCB_ATOM_CARDINAL, 32, 1,
+                   &opacity);
+       else
+               xcb_delete_property(conn, win->id,
+                   ewmh[_NET_WM_WINDOW_OPACITY].atom);
+}
+
 void
 unfocus_win(struct ws_win *win)
 {
@@ -3545,6 +3576,10 @@ focus_win(struct ws_win *win)
                                    &cfw->s->c[(MAXIMIZED(cfw) ?
                                    SWM_S_COLOR_UNFOCUS_MAXIMIZED :
                                    SWM_S_COLOR_UNFOCUS)].pixel);
+
+                               if (composite_enabled)
+                                       set_opacity(cfw,
+                                           opacity_unfocus * OPAQUE);
                        } else {
                                unfocus_win(cfw);
                        }
@@ -4113,6 +4148,7 @@ swapwin(struct swm_region *r, union arg *args)
        ewmh_update_client_list();
 
        stack();
+       center_pointer(r);
        focus_flush();
 out:
        DNPRINTF(SWM_D_MOVE, "swapwin: done\n");
@@ -4266,7 +4302,6 @@ focus(struct swm_region *r, union arg *args)
        struct workspace        *ws = NULL;
        union arg               a;
        int                     i;
-       xcb_icccm_wm_hints_t    hints;
 
        if (!(r && r->ws))
                goto out;
@@ -4327,7 +4362,7 @@ focus(struct swm_region *r, union arg *args)
 
                winfocus = TAILQ_FIRST(wl);
                if (winfocus == cur_focus)
-                       winfocus = cur_focus->ws->focus_prev;
+                       return;
                break;
        case SWM_ARG_ID_FOCUSURGENT:
                /* Search forward for the next urgent window. */
@@ -4339,27 +4374,26 @@ focus(struct swm_region *r, union arg *args)
                                head = TAILQ_FIRST(&r->s->ws[(ws->idx + i) %
                                    workspace_limit].winlist);
 
-                       while (head != NULL &&
-                           (head = TAILQ_NEXT(head, entry)) != NULL) {
+                       while (head) {
                                if (head == cur_focus) {
-                                       winfocus = cur_focus;
-                                       break;
-                               }
-                               if (xcb_icccm_get_wm_hints_reply(conn,
-                                   xcb_icccm_get_wm_hints(conn, head->id),
-                                   &hints, NULL) != 0 &&
-                                   xcb_icccm_wm_hints_get_urgency(&hints)) {
+                                       if (i > 0) {
+                                               winfocus = cur_focus;
+                                               break;
+                                       }
+                               } else if (get_urgent(head)) {
                                        winfocus = head;
                                        break;
                                }
+
+                               head = TAILQ_NEXT(head, entry);
                        }
 
-                       if (winfocus != NULL)
+                       if (winfocus)
                                break;
                }
 
                /* Switch ws if new focus is on a different ws. */
-               if (winfocus != NULL && winfocus->ws != ws) {
+               if (winfocus && winfocus->ws != ws) {
                        a.id = winfocus->ws->idx;
                        switchws(r, &a);
                }
@@ -4400,6 +4434,7 @@ cycle_layout(struct swm_region *r, union arg *args)
 
        focus_win(get_region_focus(r));
 
+       center_pointer(r);
        focus_flush();
 }
 
@@ -4421,6 +4456,7 @@ stack_config(struct swm_region *r, union arg *args)
                stack();
        bar_draw();
 
+       center_pointer(r);
        focus_flush();
 }
 
@@ -4784,7 +4820,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, bool flip)
                        win_g.y += last_h + 2 * border_width + tile_gap;
 
                if (disable_border && !(bar_enabled && ws->bar_enabled) &&
-                   winno == 1){
+                   winno == 1) {
                        bordered = false;
                        win_g.w += 2 * border_width;
                        win_g.h += 2 * border_width;
@@ -4997,12 +5033,13 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                if (X(w) != gg.x || Y(w) != gg.y || WIDTH(w) != gg.w ||
                    HEIGHT(w) != gg.h) {
                        w->g = gg;
-                       if (bar_enabled && ws->bar_enabled){
-                               w->bordered = true;
-                       } else {
+
+                       if (disable_border && !(bar_enabled && ws->bar_enabled)) {
                                w->bordered = false;
                                WIDTH(w) += 2 * border_width;
                                HEIGHT(w) += 2 * border_width;
+                       } else {
+                               w->bordered = true;
                        }
 
                        update_window(w);
@@ -5948,6 +5985,7 @@ maximize_toggle(struct swm_region *r, union arg *args)
        if (w == w->ws->focus)
                focus_win(w);
 
+       center_pointer(r);
        focus_flush();
        DNPRINTF(SWM_D_MISC, "maximize_toggle: done\n");
 }
@@ -6076,15 +6114,22 @@ update_window_color(struct ws_win *win)
 {
        uint32_t        *pixel;
 
-       if (WS_FOCUSED(win->ws) && win->ws->focus == win)
+       if (WS_FOCUSED(win->ws) && win->ws->focus == win) {
                pixel = MAXIMIZED(win) ?
                    &win->s->c[SWM_S_COLOR_FOCUS_MAXIMIZED].pixel :
                    &win->s->c[SWM_S_COLOR_FOCUS].pixel;
-       else
+
+               if (composite_enabled)
+                       set_opacity(win, opacity_focus * OPAQUE);
+       } else {
                pixel = MAXIMIZED(win) ?
                    &win->s->c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].pixel :
                    &win->s->c[SWM_S_COLOR_UNFOCUS].pixel;
 
+               if (composite_enabled)
+                       set_opacity(win, opacity_unfocus * OPAQUE);
+       }
+
        xcb_change_window_attributes(conn, win->id,
            XCB_CW_BORDER_PIXEL, pixel);
 }
@@ -6328,6 +6373,7 @@ resize_step(struct swm_region *r, union arg *args)
                return;
 
        resize(win, args);
+       center_pointer(r);
        focus_flush();
 }
 
@@ -6527,6 +6573,7 @@ move_step(struct swm_region *r, union arg *args)
                return;
 
        move(win, args);
+       center_pointer(r);
        focus_flush();
 }
 
@@ -7890,6 +7937,7 @@ enum {
        SWM_S_BOUNDARY_WIDTH,
        SWM_S_CLOCK_ENABLED,
        SWM_S_CLOCK_FORMAT,
+       SWM_S_COMPOSITE_ENABLED,
        SWM_S_CYCLE_EMPTY,
        SWM_S_CYCLE_VISIBLE,
        SWM_S_DIALOG_RATIO,
@@ -7900,6 +7948,8 @@ enum {
        SWM_S_FOCUS_MODE,
        SWM_S_ICONIC_ENABLED,
        SWM_S_JAVA_WORKAROUND,
+       SWM_S_OPACITY_FOCUS,
+       SWM_S_OPACITY_UNFOCUS,
        SWM_S_REGION_PADDING,
        SWM_S_SPAWN_ORDER,
        SWM_S_SPAWN_TERM,
@@ -8117,6 +8167,23 @@ setconfvalue(const char *selector, const char *value, int flags)
        case SWM_S_URGENT_ENABLED:
                urgent_enabled = (atoi(value) != 0);
                break;
+       case SWM_S_COMPOSITE_ENABLED:
+               composite_enabled = atoi(value);
+               break;
+       case SWM_S_OPACITY_FOCUS:
+               opacity_focus = atof(value);
+               if (opacity_focus > 1.0)
+                       opacity_focus = 1.0;
+               else if (opacity_focus < 0.0)
+                       opacity_focus = 0.0;
+               break;
+       case SWM_S_OPACITY_UNFOCUS:
+               opacity_unfocus = atof(value);
+               if (opacity_unfocus > 1.0)
+                       opacity_unfocus = 1.0;
+               else if (opacity_unfocus < 0.0)
+                       opacity_unfocus = 0.0;
+               break;
        case SWM_S_VERBOSE_LAYOUT:
                verbose_layout = (atoi(value) != 0);
                for (i = 0; layouts[i].l_stack != NULL; i++) {
@@ -8434,6 +8501,7 @@ struct config_option configopt[] = {
        { "color_focus_maximized",      setconfcolor,   SWM_S_COLOR_FOCUS_MAXIMIZED },
        { "color_unfocus",              setconfcolor,   SWM_S_COLOR_UNFOCUS },
        { "color_unfocus_maximized",    setconfcolor,   SWM_S_COLOR_UNFOCUS_MAXIMIZED },
+       { "composite_enabled",          setconfvalue,   SWM_S_COMPOSITE_ENABLED },
        { "cycle_empty",                setconfvalue,   SWM_S_CYCLE_EMPTY },
        { "cycle_visible",              setconfvalue,   SWM_S_CYCLE_VISIBLE },
        { "dialog_ratio",               setconfvalue,   SWM_S_DIALOG_RATIO },
@@ -8447,6 +8515,8 @@ struct config_option configopt[] = {
        { "keyboard_mapping",           setkeymapping,  0 },
        { "layout",                     setlayout,      0 },
        { "modkey",                     setconfmodkey,  0 },
+       { "opacity_focus",              setconfvalue,   SWM_S_OPACITY_FOCUS },
+       { "opacity_unfocus",            setconfvalue,   SWM_S_OPACITY_UNFOCUS },
        { "program",                    setconfspawn,   0 },
        { "quirk",                      setconfquirk,   0 },
        { "region",                     setconfregion,  0 },
@@ -8847,6 +8917,9 @@ manage_window(xcb_window_t id, int spawn_pos, bool mapped)
        xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL |
            XCB_CW_EVENT_MASK, wa);
 
+       if (composite_enabled)
+               set_opacity(win, opacity_unfocus * OPAQUE);
+
        /* Get WM_SIZE_HINTS. */
        xcb_icccm_get_wm_normal_hints_reply(conn,
            xcb_icccm_get_wm_normal_hints(conn, win->id),