Browse Source

! NEW SYSTRAY ! systray element as 'y', element dynamic size

Martin Duquesnoy 12 years ago
parent
commit
2eba3ccc64
16 changed files with 295 additions and 115 deletions
  1. 1 0
      Makefile.in
  2. 6 1
      src/barwin.h
  3. 1 0
      src/config.h
  4. 30 22
      src/event.c
  5. 9 5
      src/ewmh.c
  6. 5 4
      src/ewmh.h
  7. 136 39
      src/infobar.c
  8. 5 8
      src/infobar.h
  9. 1 1
      src/screen.c
  10. 3 0
      src/status.c
  11. 84 29
      src/systray.c
  12. 3 1
      src/systray.h
  13. 3 0
      src/tag.c
  14. 1 1
      src/wmfs.c
  15. 3 1
      src/wmfs.h
  16. 4 3
      wmfsrc

+ 1 - 0
Makefile.in

@@ -18,6 +18,7 @@ SRCS=                 \
       src/util.c      \
       src/fifo.c      \
       src/status.c    \
+      src/systray.c   \
       src/mouse.c     \
       src/log.c       \
       src/wmfs.c

+ 6 - 1
src/barwin.h

@@ -22,9 +22,14 @@
 #define barwin_refresh(b)       XCopyArea(W->dpy, b->dr, b->win, W->gc, 0, 0, b->geo.w, b->geo.h, 0, 0)
 #define barwin_map(b)           XMapWindow(W->dpy, b->win);
 #define barwin_unmap(b)         XUnmapWindow(W->dpy, b->win);
-#define barwin_move(b, x, y)    XMoveWindow(W->dpy, b->win, x, y);
 #define barwin_reparent(b, w)   XReparentWindow(W->dpy, b->win, w, 0, 0);
 
+static inline void
+barwin_move(struct barwin *b, int x, int y)
+{
+     XMoveWindow(W->dpy, b->win, (b->geo.x = x), (b->geo.y = y));
+}
+
 struct barwin* barwin_new(Window parent, int x, int y, int w, int h, Color fg, Color bg, bool entermask);
 void barwin_remove(struct barwin *b);
 void barwin_resize(struct barwin *b, int w, int h);

+ 1 - 0
src/config.h

@@ -17,6 +17,7 @@
 #include "status.h"
 #include "mouse.h"
 #include "screen.h"
+#include "infobar.h"
 
 #define THEME_DEFAULT (SLIST_FIRST(&W->h.theme))
 

+ 30 - 22
src/event.c

@@ -54,7 +54,7 @@ event_enternotify(XEvent *e)
                && ev->window != W->root)
           return;
 
-     if(ev->window == W->systray.win /* || systray_find(ev->window) */)
+     if(ev->window == W->systray.win || systray_find(ev->window))
           return;
 
      if((c = client_gb_win(ev->window))
@@ -82,21 +82,27 @@ event_clientmessageevent(XEvent *e)
       * Systray message
       * _NET_WM_SYSTRAY_TRAY_OPCODE
       */
-     if(ev->window == W->systray.win && type == net_wm_system_tray_opcode)
+     if(ev->window == W->systray.win && type == net_system_tray_opcode)
      {
           if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY)
           {
-               /* systray_add(ev->data.l[2]); */
-               /* systray_update() */
+               systray_add(ev->data.l[2]);
+               systray_update();
           }
           else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS)
           {
-               /* if((sy = systray_find(ev->data.l[2])))
+               if((sy = systray_find(ev->data.l[2])))
                     ewmh_send_message(sy->win, sy->win, "_XEMBED", XEMBED_FOCUS_IN,
-                    XEMBED_FOCUS_CURRENT, 0, 0, 0);*/
+                                      XEMBED_FOCUS_CURRENT, 0, 0, 0);
 
           }
      }
+     else if(ev->window == W->root)
+     {
+          if(type == net_active_window)
+               if((sy = systray_find(ev->data.l[0])))
+                    XSetInputFocus(W->dpy, sy->win, RevertToNone, CurrentTime);
+     }
 
      switch(type)
      {
@@ -155,12 +161,12 @@ event_destroynotify(XEvent *e)
 
      if((c = client_gb_win(ev->window)))
           client_remove(c);
-     /*else if((s = systray_find(ev->window)))
+     else if((s = systray_find(ev->window)))
      {
           ewmh_set_wm_state(s->win, WithdrawnState);
           systray_del(s);
           systray_update();
-          }*/
+     }
 }
 
 static void
@@ -186,11 +192,12 @@ event_maprequest(XEvent *e)
 
      if(!client_gb_win(ev->window))
           client_new(ev->window, &at, false);
-     /*else if((s = systray_find(ev->window)))
+     else if((s = systray_find(ev->window)))
      {
-          ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
+          ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
+                            XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
           systray_update();
-          }*/
+     }
 }
 
 static void
@@ -239,11 +246,11 @@ event_propertynotify(XEvent *e)
                     break;
           }
      }
-     /*else if((s = systray_find(ev->window)))
+     else if((s = systray_find(ev->window)))
      {
           systray_state(s);
           systray_update();
-          }*/
+     }
 }
 
 static void
@@ -251,15 +258,15 @@ event_unmapnotify(XEvent *e)
 {
      XUnmapEvent *ev = &e->xunmap;
      struct client *c;
-     struct systray *s;
+     struct _systray *s;
 
      if((c = client_gb_win(ev->window)) && ev->send_event)
           client_remove(c);
-     /*else if((s = systray_find(ev->window)))
+     else if((s = systray_find(ev->window)))
      {
           systray_del(s);
-          systray_update(s);
-          }*/
+          systray_update();
+     }
 }
 
 static void
@@ -303,21 +310,22 @@ event_mapnotify(XEvent *e)
 
      if((c = client_gb_win(ev->window)))
           ewmh_set_wm_state(c->win, NormalState);
-     /*else if((s = systray_find(ev->window)))
+     else if((s = systray_find(ev->window)))
      {
           ewmh_set_wm_state(s->win, NormalState);
-          ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
-          }*/
+          ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
+                            XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
+     }
 }
 
 static void
 event_selectionclearevent(XEvent *ev)
 {
      /* Getting selection if lost it */
-/*     if(ev->xselectionclear.window == W->systray.win)
+     if(ev->xselectionclear.window == W->systray.win)
           systray_acquire();
 
-          systray_update();*/
+     systray_update();
 }
 
 static void

+ 9 - 5
src/ewmh.c

@@ -22,6 +22,7 @@ ewmh_init(void)
 
      /* EWMH hints */
      W->net_atom[wm_state]                       = ATOM("WM_STATE");
+     W->net_atom[wm_class]                       = ATOM("WM_CLASS");
      W->net_atom[net_supported]                  = ATOM("_NET_SUPPORTED");
      W->net_atom[net_client_list]                = ATOM("_NET_CLIENT_LIST");
      W->net_atom[net_frame_extents]              = ATOM("_NET_FRAME_EXTENTS");
@@ -48,7 +49,8 @@ ewmh_init(void)
      W->net_atom[net_wm_state_fullscreen]        = ATOM("_NET_WM_STATE_FULLSCREEN");
      W->net_atom[net_wm_state_sticky]            = ATOM("_NET_WM_STATE_STICKY");
      W->net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
-     W->net_atom[net_wm_system_tray_opcode]      = ATOM("_NET_SYSTEM_TRAY_OPCODE");
+     W->net_atom[net_system_tray_s]              = ATOM("_NET_SYSTEM_TRAY_S0");
+     W->net_atom[net_system_tray_opcode]         = ATOM("_NET_SYSTEM_TRAY_OPCODE");
      W->net_atom[net_system_tray_message_data]   = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
      W->net_atom[net_system_tray_visual]         = ATOM("_NET_SYSTEM_TRAY_VISUAL");
      W->net_atom[net_system_tray_orientation]    = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
@@ -79,12 +81,14 @@ ewmh_init(void)
      /* Set _NET_SUPPORTING_WM_CHECK */
      XChangeProperty(W->dpy, W->root, W->net_atom[net_supporting_wm_check], XA_WINDOW, 32,
                      PropModeReplace, (unsigned char*)&W->root, 1);
-     /*
-     XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
-                     PropModeReplace, (unsigned char*)&rootn, strlen(rootn));
 
      XChangeProperty(W->dpy, W->root, ATOM("WM_CLASS"), XA_STRING, 8,
-                     PropModeReplace, (unsigned char*)&class, strlen(class));
+                     PropModeReplace, (unsigned char*)&"wmfs", 4);
+
+     XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
+                     PropModeReplace, (unsigned char*)&"wmfs2", 5);
+
+         /*
 
       * Set _NET_WM_PID
      XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_pid], XA_CARDINAL, 32,

+ 5 - 4
src/ewmh.h

@@ -31,15 +31,16 @@
 #define XEMBED_ACTIVATE_ACCELERATOR   14
 
 /* Details for  XEMBED_FOCUS_IN: */
-#define XEMBED_FOCUS_CURRENT0
-#define XEMBED_FOCUS_FIRST 1
-#define XEMBED_FOCUS_LAST2
+#define XEMBED_FOCUS_CURRENT 0
+#define XEMBED_FOCUS_FIRST   1
+#define XEMBED_FOCUS_LAST    2
 
 /* Ewmh hints list */
 enum
 {
      /* ICCCM */
      wm_state,
+     wm_class,
      /* EWMH */
      net_supported,
      net_wm_name,
@@ -67,7 +68,7 @@ enum
      net_wm_state_fullscreen,
      net_wm_state_sticky,
      net_wm_state_demands_attention,
-     net_wm_system_tray_opcode,
+     net_system_tray_opcode,
      net_system_tray_message_data,
      net_system_tray_s,
      net_system_tray_visual,

+ 136 - 39
src/infobar.c

@@ -10,11 +10,14 @@
 #include "util.h"
 #include "tag.h"
 #include "status.h"
+#include "systray.h"
 
 static void infobar_elem_tag_init(struct element *e);
 static void infobar_elem_tag_update(struct element *e);
 static void infobar_elem_status_init(struct element *e);
 static void infobar_elem_status_update(struct element *e);
+static void infobar_elem_systray_init(struct element *e);
+static void infobar_elem_systray_update(struct element *e);
 
 const struct elem_funcs
 {
@@ -23,12 +26,9 @@ const struct elem_funcs
      void (*func_update)(struct element *e);
 } elem_funcs[] =
 {
-     { 't', infobar_elem_tag_init,    infobar_elem_tag_update },
-     { 's', infobar_elem_status_init, infobar_elem_status_update },
-
-     /* { 'l',  infobar_elem_layout_init, infobar_elem_layout_update },
-        { 'S',  infobar_elem_selbar_init, infobar_elem_selbar_update },
-     */
+     { 't', infobar_elem_tag_init,     infobar_elem_tag_update },
+     { 's', infobar_elem_status_init,  infobar_elem_status_update },
+     { 'y', infobar_elem_systray_init, infobar_elem_systray_update },
      { '\0', NULL, NULL }
 };
 
@@ -51,32 +51,41 @@ infobar_elem_tag_init(struct element *e)
 
      e->statusctx = &e->infobar->theme->tags_n_sl;
 
-     TAILQ_FOREACH(t, &e->infobar->screen->tags, next)
+     if(SLIST_EMPTY(&e->bars))
      {
-          s = draw_textw(e->infobar->theme, t->name) + PAD;
+          TAILQ_FOREACH(t, &e->infobar->screen->tags, next)
+          {
+               s = draw_textw(e->infobar->theme, t->name) + PAD;
 
-          /* Init barwin */
-          b = barwin_new(e->infobar->bar->win, j, 0, s, e->geo.h, 0, 0, false);
+               /* Init barwin */
+               b = barwin_new(e->infobar->bar->win, j, 0, s, e->geo.h, 0, 0, false);
 
-          /* Set border */
-          if(e->infobar->theme->tags_border_width)
-          {
-               XSetWindowBorder(W->dpy, b->win, e->infobar->theme->tags_border_col);
-               XSetWindowBorderWidth(W->dpy, b->win, e->infobar->theme->tags_border_width);
-          }
+               /* Set border */
+               if(e->infobar->theme->tags_border_width)
+               {
+                    XSetWindowBorder(W->dpy, b->win, e->infobar->theme->tags_border_col);
+                    XSetWindowBorderWidth(W->dpy, b->win, e->infobar->theme->tags_border_width);
+               }
 
-          b->ptr = (void*)t;
-          barwin_map(b);
+               b->ptr = (void*)t;
+               barwin_map(b);
 
-          b->mousebinds = W->tmp_head.tag;
+               b->mousebinds = W->tmp_head.tag;
 
-          SLIST_INSERT_TAIL(&e->bars, b, enext, prev);
+               SLIST_INSERT_TAIL(&e->bars, b, enext, prev);
 
-          prev = b;
-          j += s;
+               prev = b;
+               j += s;
+          }
+     }
+     else
+     {
+          SLIST_FOREACH(b, &e->bars, enext)
+          {
+               barwin_move(b, j, 0);
+               j += b->geo.w;
+          }
      }
-
-     e->infobar->screen->elemupdate |= FLAGINT(ElemTag);
 }
 
 static void
@@ -137,25 +146,77 @@ infobar_elem_status_init(struct element *e)
 
      e->geo.w = e->infobar->geo.w - e->geo.x - (en ? e->infobar->geo.w - en->geo.x : 0);
 
-     b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
+     if(!(b = SLIST_FIRST(&e->bars)))
+     {
+          b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
+          barwin_refresh_color(b);
+          SLIST_INSERT_HEAD(&e->bars, b, enext);
+
+          e->infobar->statusctx = status_new_ctx(b, e->infobar->theme);
+          e->infobar->statusctx.status = strdup("wmfs2");
+          e->infobar->statusctx.update = true;
+     }
+     else
+     {
+          barwin_move(b, e->geo.x, e->geo.y);
+          barwin_resize(b, e->geo.w, e->geo.h);
+     }
 
      b->fg = e->infobar->theme->bars.fg;
      b->bg = e->infobar->theme->bars.bg;
 
      barwin_map(b);
+}
+
+static void
+infobar_elem_status_update(struct element *e)
+{
+     if(e->infobar->statusctx.update)
+          status_manage(&e->infobar->statusctx);
+     else
+     {
+          status_render(&e->infobar->statusctx);
+          status_copy_mousebind(&e->infobar->statusctx);
+     }
+     puts("status");
+}
+
+static void
+infobar_elem_systray_init(struct element *e)
+{
+     struct barwin *b;
 
-     SLIST_INSERT_HEAD(&e->bars, b, enext);
+     /* Activate systray mask; no more systray element allowed now */
+     W->flags |= WMFS_SYSTRAY;
 
-     e->infobar->statusctx = status_new_ctx(b, e->infobar->theme);
+     W->systray.infobar = e->infobar;
 
-     e->infobar->screen->elemupdate |= FLAGINT(ElemStatus);
-     e->infobar->statusctx.status = strdup("wmfs2");
+     e->geo.w = systray_get_width();
+     infobar_elem_placement(e);
+
+     if(!(b = SLIST_FIRST(&e->bars)))
+     {
+          b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
+          XFreePixmap(W->dpy, b->dr);
+          SLIST_INSERT_HEAD(&e->bars, b, enext);
+          W->systray.barwin = b;
+          systray_acquire();
+     }
+     else
+     {
+          barwin_move(b, e->geo.x, e->geo.y);
+          barwin_resize(b, e->geo.w, e->geo.h);
+     }
+
+     XMoveResizeWindow(W->dpy, W->systray.win, 0, 0, e->geo.w, e->geo.h);
 }
 
 static void
-infobar_elem_status_update(struct element *e)
+infobar_elem_systray_update(struct element *e)
 {
-     status_manage(&e->infobar->statusctx);
+     (void)e;
+
+     systray_update();
 }
 
 #define ELEM_INIT(a)                                  \
@@ -187,15 +248,16 @@ infobar_elem_init(struct infobar *i)
                break;
           }
 
+          /* Only one systray element in a wmfs session */
+          if(i->elemorder[n] == 'y' && W->flags & WMFS_SYSTRAY)
+               continue;
+
           for(j = 0; j < (int)LEN(elem_funcs); ++j)
                if(elem_funcs[j].c == i->elemorder[n])
                {
                     ELEM_INIT(Left);
 
-                    if(TAILQ_EMPTY(&i->elements))
-                         TAILQ_INSERT_HEAD(&i->elements, e, next);
-                    else
-                         TAILQ_INSERT_TAIL(&i->elements, e, next);
+                    TAILQ_INSERT_TAIL(&i->elements, e, next);
 
                     e->func_init(e);
                     es = e;
@@ -211,7 +273,7 @@ infobar_elem_init(struct infobar *i)
           for(k = l - 1; k >= n; --k)
           {
                /* Only one status */
-               if(i->elemorder[k] == 's')
+               if(i->elemorder[k] == 's' || (i->elemorder[n] == 'y' && W->flags & WMFS_SYSTRAY))
                     continue;
 
                for(j = 0; j < (int)LEN(elem_funcs); ++j)
@@ -244,12 +306,12 @@ infobar_elem_init(struct infobar *i)
 }
 
 void
-infobar_elem_update(struct infobar *i)
+infobar_elem_update(struct infobar *i, int type)
 {
      struct element *e;
 
      TAILQ_FOREACH(e, &i->elements, next)
-          if(i->screen->elemupdate & FLAGINT(e->type))
+          if(type == e->type || type == -1)
                e->func_update(e);
 }
 
@@ -270,6 +332,38 @@ infobar_elem_remove(struct element *e)
      free(e);
 }
 
+void
+infobar_elem_reinit(struct infobar *i)
+{
+     struct element *e;
+
+     TAILQ_FOREACH(e, &i->elements, next)
+     {
+          /* Status element found, scan from the tail now */
+          if(e->type == ElemStatus)
+          {
+               struct element *ee;
+
+               TAILQ_FOREACH_REVERSE(ee, &i->elements, esub, next)
+               {
+                    if(e == ee)
+                         break;
+
+                    ee->func_init(ee);
+                    ee->func_update(ee);
+               }
+
+               e->func_init(e);
+               e->func_update(e);
+
+               return;
+          }
+
+          e->func_init(e);
+          e->func_update(e);
+     }
+}
+
 struct infobar*
 infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos, const char *elem)
 {
@@ -307,7 +401,7 @@ infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos,
 void
 infobar_refresh(struct infobar *i)
 {
-     infobar_elem_update(i);
+     infobar_elem_update(i, -1);
 
      barwin_refresh(i->bar);
 }
@@ -321,6 +415,9 @@ infobar_remove(struct infobar *i)
      free(i->name);
      free(i->status);
 
+     if(i == W->systray.infobar)
+          systray_freeicons();
+
      TAILQ_FOREACH(e, &i->elements, next)
           infobar_elem_remove(e);
 

+ 5 - 8
src/infobar.h

@@ -8,16 +8,16 @@
 
 #include "wmfs.h"
 #include "util.h"
-#include "draw.h"
 #include "tag.h"
 
-enum { ElemTag = 0, ElemStatus, ElemCustom, ElemLast };
+enum { ElemTag = 0, ElemStatus, ElemSystray, ElemCustom, ElemLast };
 
 struct infobar *infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos, const char *elem);
-void infobar_elem_update(struct infobar *i);
+void infobar_elem_update(struct infobar *i, int type);
 void infobar_refresh(struct infobar *i);
 void infobar_remove(struct infobar *i);
 void infobar_free(struct screen *s);
+void infobar_elem_reinit(struct infobar *i);
 
 /* Basic placement of elements */
 static inline void
@@ -63,16 +63,13 @@ infobar_placement(struct infobar *i, enum barpos p)
 }
 
 static inline void
-infobar_elem_screen_update(struct screen *s, int addf)
+infobar_elem_screen_update(struct screen *s, int type)
 {
      struct infobar *i;
 
-     s->elemupdate |= FLAGINT(addf);
-
      SLIST_FOREACH(i, &s->infobars, next)
-          infobar_elem_update(i);
+          infobar_elem_update(i, type);
 
-     s->elemupdate &= ~FLAGINT(addf);
 }
 
 static inline struct infobar*

+ 1 - 1
src/screen.c

@@ -129,7 +129,7 @@ uicb_screen_prev(Uicb cmd)
 static void
 screen_move_client(struct client *c, struct screen *s)
 {
-          tag_client(s->seltag, c);
+     tag_client(s->seltag, c);
 }
 
 void

+ 3 - 0
src/status.c

@@ -327,6 +327,8 @@ status_manage(struct status_ctx *ctx)
      if(!ctx->status)
           return;
 
+     ctx->update = false;
+
      status_flush_list(ctx);
      status_parse(ctx);
      status_render(ctx);
@@ -355,6 +357,7 @@ uicb_status(Uicb cmd)
                {
                     free(ib->statusctx.status);
                     ib->statusctx.status = xstrdup(p);
+                    ib->statusctx.update = true;
                     infobar_elem_screen_update(s, ElemStatus);
                }
      }

+ 84 - 29
src/systray.c

@@ -5,47 +5,57 @@
 
 #include "wmfs.h"
 #include "systray.h"
+#include "ewmh.h"
+#include "infobar.h"
 
-bool
+#define SYSTRAY_SPACING (2)
+
+void
 systray_acquire(void)
 {
+     Window w = 0;
      XSetWindowAttributes wattr =
-          {
-               .event_mask = ButtonPressMask | ExposureMask,
-               .override_redirect = true,
-               .background_pixmap = ParentRelative,
-               .background_pixel  = 0
-          };
+     {
+          .event_mask = ButtonPressMask | ExposureMask,
+          .override_redirect = true,
+          .background_pixmap = ParentRelative,
+          .background_pixel  = W->systray.infobar->theme->bars.bg,
+     };
 
      if(!(W->flags & WMFS_SYSTRAY) || W->systray.win)
-          return false;
+          return;
 
      if(XGetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s]) != None)
      {
           warnx("Can't initialize system tray: owned by another process.");
-          return False;
+          return;
      }
 
-     /* Init traywin window */
-     XChangeWindowAttributes(W->dpy, W->systray.win, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
-     XSelectInput(W->dpy, W->systray.win, KeyPressMask | ButtonPressMask);
-     XMapRaised(W->dpy, W->systray.win);
-     XSetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s], W->systray.win, CurrentTime);
+     SLIST_INIT(&W->systray.head);
 
-     if(XGetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s]) != W->systray.win)
+     /* Init systray window */
+     w = XCreateSimpleWindow(W->dpy, W->systray.barwin->win, 0, 0,
+                             W->systray.barwin->geo.h, W->systray.barwin->geo.h, 0, 0, 0);
+
+     XChangeWindowAttributes(W->dpy, w, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
+     XSelectInput(W->dpy, w, KeyPressMask | ButtonPressMask);
+     XMapRaised(W->dpy, w);
+
+     XSetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s], w, CurrentTime);
+
+     if(XGetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s]) != w)
      {
+          warnl("System tray: can't get systray manager");
           systray_freeicons();
-          warnx("System tray: can't get systray manager");
-
-          return false;
+          return;
      }
 
      ewmh_send_message(W->root, W->root, "MANAGER", CurrentTime,
-                       W->net_atom[net_system_tray_s], W->systray.win, 0, 0);
+                       W->net_atom[net_system_tray_s], w, 0, 0);
 
-     XSync(dpy, false);
+     XSync(W->dpy, false);
 
-     return true;
+     W->systray.win = w;
 }
 
 void
@@ -60,16 +70,18 @@ systray_add(Window win)
      s->win = win;
 
      s->geo.h = W->systray.barwin->geo.h;
-     s->geo.w = W->systray.barwin->geo.w + 2;
+     s->geo.w = W->systray.barwin->geo.h + SYSTRAY_SPACING;
 
-     ewmh_set_win_state(s->win, WithdrawnState);
+     ewmh_set_wm_state(s->win, WithdrawnState);
      XSelectInput(W->dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask);
      XReparentWindow(W->dpy, s->win, W->systray.win, 0, 0);
 
      ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
-                       XEMBED_EMBEDDED_NOTIFY, 0, W->systray,win, 0);
+                       XEMBED_EMBEDDED_NOTIFY, 0, W->systray.win, 0);
 
      SLIST_INSERT_HEAD(&W->systray.head, s, next);
+
+     W->systray.redim = true;
 }
 
 void
@@ -80,6 +92,8 @@ systray_del(struct _systray *s)
 
      SLIST_REMOVE(&W->systray.head, s, _systray, next);
      free(s);
+
+     W->systray.redim = true;
 }
 
 void
@@ -95,13 +109,13 @@ systray_state(struct _systray *s)
      {
           code = XEMBED_WINDOW_ACTIVATE;
           XMapRaised(W->dpy, s->win);
-          ewmh_set_win_state(s->win, NormalState);
+          ewmh_set_wm_state(s->win, NormalState);
      }
      else
      {
           code = XEMBED_WINDOW_DEACTIVATE;
           XUnmapWindow(W->dpy, s->win);
-          ewmh_set_win_state(s->win, WithdrawnState);
+          ewmh_set_wm_state(s->win, WithdrawnState);
      }
 
      ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, code, 0, 0, 0);
@@ -120,13 +134,14 @@ systray_freeicons(void)
           i = SLIST_FIRST(&W->systray.head);
           SLIST_REMOVE_HEAD(&W->systray.head, next);
 
-          XUnmapWindow(dpy, i->win);
-          XReparentWindow(dpy, i->win, W->root, 0, 0);
+          XUnmapWindow(W->dpy, i->win);
+          XReparentWindow(W->dpy, i->win, W->root, 0, 0);
           free(i);
      }
 
      XSetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s], None, CurrentTime);
-     XDestroyWindow(W->dpy, W->systray.win);
+     W->systray.barwin->geo.w = 0;
+     infobar_elem_reinit(W->systray.infobar);
      XSync(W->dpy, false);
 }
 
@@ -144,3 +159,43 @@ systray_find(Window win)
 
      return NULL;
 }
+
+int
+systray_get_width(void)
+{
+     int w = 1;
+     struct _systray *i;
+
+     SLIST_FOREACH(i, &W->systray.head, next)
+          w += i->geo.w + SYSTRAY_SPACING;
+
+     return w;
+}
+
+void
+systray_update(void)
+{
+     int x = 1;
+     struct _systray *i;
+
+     if(!(W->flags & WMFS_SYSTRAY))
+          return;
+
+     if(W->systray.redim)
+     {
+          W->systray.redim = false;
+          infobar_elem_reinit(W->systray.infobar);
+          puts("update");
+     }
+
+     SLIST_FOREACH(i, &W->systray.head, next)
+     {
+          XMapWindow(W->dpy, i->win);
+          XMoveResizeWindow(W->dpy, i->win, (i->geo.x = x), 0, i->geo.w, i->geo.h);
+
+          x += i->geo.w + SYSTRAY_SPACING;
+     }
+}
+
+
+

+ 3 - 1
src/systray.h

@@ -8,11 +8,13 @@
 
 #include "wmfs.h"
 
-bool systray_acquire(void);
+void systray_acquire(void);
 void systray_add(Window win);
 void systray_del(struct _systray *s);
 void systray_state(struct _systray *s);
 void systray_freeicons(void);
 struct _systray *systray_find(Window win);
+int systray_get_width(void);
+void systray_update(void);
 
 #endif /* SYSTRAY_H */

+ 3 - 0
src/tag.c

@@ -101,6 +101,8 @@ tag_client(struct tag *t, struct client *c)
       */
      SLIST_INSERT_HEAD(&t->clients, c, tnext);
 
+     infobar_elem_screen_update(t->screen, ElemTag);
+
      if(c->flags & CLIENT_IGNORE_LAYOUT)
           c->flags ^= CLIENT_IGNORE_LAYOUT;
      else if(!(c->flags & CLIENT_TABBED))
@@ -117,6 +119,7 @@ tag_client(struct tag *t, struct client *c)
 
      if(t != c->screen->seltag || c->flags & CLIENT_TABBED)
           client_unmap(c);
+
 }
 
 void

+ 1 - 1
src/wmfs.c

@@ -202,7 +202,7 @@ wmfs_scan(void)
      int i, n, rf, nscreen = 0;
      int tag = -1, screen = -1, flags = -1;
      unsigned long ir, il;
-     long *ret, *tret;
+     long *ret = NULL, *tret;
      bool getg = false;
      XWindowAttributes wa;
      Window usl, usl2, *w = NULL, tm, focus;

+ 3 - 1
src/wmfs.h

@@ -113,6 +113,7 @@ struct status_ctx
      struct barwin *barwin;
      struct theme *theme;
      char *status;
+     bool update;
      SLIST_HEAD(, status_seq) statushead;
 };
 
@@ -149,7 +150,6 @@ struct screen
      struct geo geo, ugeo;
      struct tag *seltag;
      int id;
-     Flags elemupdate;
      TAILQ_HEAD(tsub, tag) tags;
      SLIST_HEAD(, infobar) infobars;
      SLIST_ENTRY(screen) next;
@@ -346,6 +346,8 @@ struct wmfs
      struct
      {
           struct barwin *barwin;
+          struct infobar *infobar;
+          bool redim;
           Window win;
           SLIST_HEAD(, _systray) head;
      } systray;

+ 4 - 3
wmfsrc

@@ -38,11 +38,11 @@
      # Frame / Client
      client_normal_fg = "#AABBAA"
      client_normal_bg = "#223322"
-     client_normal_statusline = "\s[left;#ff0000; x](1;client_close)"
+     client_normal_statusline = "\s[3;9;#121212;x] \s[2;8;#ff0000;x](1;client_close)"
 
      client_sel_fg = "#223322"
      client_sel_bg = "#AABBAA"
-     client_sel_statusline = "\s[left;#ff0000; x](1;client_close)"
+     client_sel_statusline = "\s[3;9;#121212;x] \s[2;8;#ff0000;x](1;client_close)"
 
      frame_bg = "#555555"
      client_titlebar_width = 12
@@ -64,11 +64,12 @@
   #
   # t  Tags
   # s  Statustext (will take available space)
+  # y  Systray (can be set only ONE time among all element)
 
   [bar]
      position = 0
      screen = 0
-     elements = "ts"    # element order in bar
+     elements = "tsy"   # element order in bar
      theme = "default"
   [/bar]