diff --git a/awesome.c b/awesome.c
index b23261f..ac02f6d 100644
--- a/awesome.c
+++ b/awesome.c
@@ -360,6 +360,8 @@ main(int argc, char *argv[])
             if(handler[ev.type])
                 handler[ev.type](&ev);       /* call handler */
         }
+
+        statusbar_refresh();
     }
 
     if(csfd > 0 && close(csfd))
diff --git a/client.c b/client.c
index a663b13..b5c52d4 100644
--- a/client.c
+++ b/client.c
@@ -29,11 +29,11 @@
 #include "rules.h"
 #include "util.h"
 #include "xutil.h"
-#include "statusbar.h"
 #include "window.h"
 #include "focus.h"
 #include "ewmh.h"
 #include "screen.h"
+#include "widget.h"
 #include "layouts/floating.h"
 
 
@@ -244,6 +244,7 @@ focus(Client *c, Bool selscreen, int screen)
     /* unfocus current selected client */
     if(globalconf.focus->client)
     {
+        widget_invalidate_cache(globalconf.focus->client->screen, WIDGET_CACHE_CLIENTS);
         window_grabbuttons(get_phys_screen(globalconf.focus->client->screen),
                            globalconf.focus->client->win, False, True);
         XSetWindowBorder(globalconf.display, globalconf.focus->client->win,
@@ -274,7 +275,7 @@ focus(Client *c, Bool selscreen, int screen)
     /* save sel in focus history */
     focus_add_client(c);
 
-    statusbar_draw_all(screen);
+    widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS);
 
     if(globalconf.focus->client)
     {
@@ -889,19 +890,21 @@ client_maximize(Client *c, Area geometry)
          * coords */
         c->isfloating = True;
         restack(c->screen);
+        widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
     }
     else if(c->wasfloating)
     {
         c->isfloating = True;
         client_resize(c, c->m_geometry, False);
         restack(c->screen);
+        widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
     }
     else
     {
         c->isfloating = False;
         arrange(c->screen);
+        widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
     }
-    statusbar_draw_all(c->screen);
 }
 
 /** Toggle maximize for client
diff --git a/config.h b/config.h
index 2b065c5..c5db1ae 100644
--- a/config.h
+++ b/config.h
@@ -114,6 +114,12 @@ struct Widget
     Button *buttons;
     /** Font */
     XftFont *font;
+    /** Cache */
+    struct
+    {
+        Bool needs_update;
+        int flags;
+    } cache;
     /** Next widget */
     Widget *next;
 };
diff --git a/event.c b/event.c
index 0057d01..7ad67c7 100644
--- a/event.c
+++ b/event.c
@@ -34,6 +34,7 @@
 #include "mouse.h"
 #include "ewmh.h"
 #include "client.h"
+#include "widget.h"
 #include "layouts/tile.h"
 #include "layouts/floating.h"
 
@@ -166,10 +167,10 @@ handle_event_configurerequest(XEvent * e)
             
             if(old_screen != c->screen)
             {
-                statusbar_draw_all(old_screen);
+                widget_invalidate_cache(old_screen, WIDGET_CACHE_CLIENTS);
                 arrange(old_screen);
             }
-            statusbar_draw_all(c->screen);
+            widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
             arrange(c->screen);
         }
         else
@@ -213,7 +214,7 @@ handle_event_configurenotify(XEvent * e)
                           globalconf.screens[screen].statusbar->width,
                           globalconf.screens[screen].statusbar->height);
 
-            statusbar_draw_all(screen);
+            widget_invalidate_cache(screen, WIDGET_CACHE_ALL);
             arrange(screen);
         }
 }
@@ -375,14 +376,14 @@ handle_event_propertynotify(XEvent * e)
             break;
           case XA_WM_HINTS:
             client_updatewmhints(c);
-            statusbar_draw_all(c->screen);
+            widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
             break;
         }
         if(ev->atom == XA_WM_NAME || ev->atom == XInternAtom(globalconf.display, "_NET_WM_NAME", False))
         {
             client_updatetitle(c);
             if(c == globalconf.focus->client)
-                statusbar_draw_all(c->screen);
+                widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
         }
     }
 }
diff --git a/ewmh.c b/ewmh.c
index 6e86cf0..532f6e6 100644
--- a/ewmh.c
+++ b/ewmh.c
@@ -28,7 +28,7 @@
 #include "focus.h"
 #include "screen.h"
 #include "client.h"
-#include "statusbar.h"
+#include "widget.h"
 
 extern AwesomeConf globalconf;
 
@@ -265,7 +265,7 @@ ewmh_process_state_atom(Client *c, Atom state, int set)
             c->ismax = True;
             c->isfloating = True;
         }
-        statusbar_draw_all(c->screen);
+        widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
         client_resize(c, geometry, False);
         XRaiseWindow(globalconf.display, c->win);
         arrange(c->screen);
diff --git a/layout.c b/layout.c
index abab034..d441d46 100644
--- a/layout.c
+++ b/layout.c
@@ -26,7 +26,7 @@
 #include "util.h"
 #include "xutil.h"
 #include "focus.h"
-#include "statusbar.h"
+#include "widget.h"
 #include "ewmh.h"
 #include "client.h"
 #include "screen.h"
@@ -163,8 +163,6 @@ restack(int screen)
     XWindowChanges wc;
     Tag **curtags;
 
-    statusbar_draw_all(screen);
-
     if(!sel)
         return;
 
@@ -253,7 +251,7 @@ uicb_tag_setlayout(int screen, char *arg)
     if(globalconf.focus->client)
         arrange(screen);
     else
-        statusbar_draw_all(screen);
+        widget_invalidate_cache(screen, WIDGET_CACHE_LAYOUTS);
 
     saveawesomeprops(screen);
 }
@@ -279,6 +277,7 @@ uicb_client_togglefloating(int screen, char *arg)
     else if(sel->ismax)
         client_resize(sel, sel->m_geometry, False);
 
+    widget_invalidate_cache(sel->screen, WIDGET_CACHE_CLIENTS);
     client_saveprops(sel);
     arrange(screen);
 }
diff --git a/mouse.c b/mouse.c
index b1d6247..83eac08 100644
--- a/mouse.c
+++ b/mouse.c
@@ -28,7 +28,6 @@
 #include "util.h"
 #include "event.h"
 #include "window.h"
-#include "statusbar.h"
 #include "client.h"
 #include "layouts/floating.h"
 #include "layouts/tile.h"
@@ -78,7 +77,6 @@ uicb_client_movemouse(int screen, char *arg __attribute__ ((unused)))
                   RootWindow(globalconf.display, phys_screen),
                   &dummy, &dummy, &x1, &y, &di, &di, &dui);
     c->ismax = False;
-    statusbar_draw_all(c->screen);
     for(;;)
     {
         XMaskEvent(globalconf.display, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
diff --git a/screen.c b/screen.c
index 1a9f2ca..09cd9cf 100644
--- a/screen.c
+++ b/screen.c
@@ -25,7 +25,6 @@
 #include "screen.h"
 #include "tag.h"
 #include "focus.h"
-#include "statusbar.h"
 #include "client.h"
 #include "layouts/floating.h"
 
@@ -254,10 +253,6 @@ move_client_to_screen(Client *c, int new_screen, Bool doresize)
     }
 
     focus(c, True, c->screen);
-
-    /* redraw statusbar on all screens */
-    statusbar_draw_all(old_screen);
-    statusbar_draw_all(new_screen);
 }
 
 /** Move mouse pointer to x_org and y_xorg of specified screen
diff --git a/statusbar.c b/statusbar.c
index 2019fc3..345b5bc 100644
--- a/statusbar.c
+++ b/statusbar.c
@@ -30,7 +30,7 @@
 
 extern AwesomeConf globalconf;
 
-static void
+void
 statusbar_draw(Statusbar *statusbar)
 {
     int phys_screen = get_phys_screen(statusbar->screen);
@@ -52,12 +52,16 @@ statusbar_draw(Statusbar *statusbar)
 
     for(widget = statusbar->widgets; widget; widget = widget->next)
         if (widget->alignment == AlignLeft)
+        {
+            widget->cache.needs_update = False;
             left += widget->draw(widget, ctx, left, (left + right));
+        }
 
     /* renders right widget from last to first */
     for(widget = statusbar->widgets; widget; widget = widget->next)
         if (widget->alignment == AlignRight && last_drawn == widget->next)
         {
+            widget->cache.needs_update = False;
             right += widget->draw(widget, ctx, right, (left + right));
             last_drawn = widget;
             widget = statusbar->widgets;
@@ -65,7 +69,10 @@ statusbar_draw(Statusbar *statusbar)
 
     for(widget = statusbar->widgets; widget; widget = widget->next)
         if (widget->alignment == AlignFlex)
+        {
+            widget->cache.needs_update = False;
             left += widget->draw(widget, ctx, left, (left + right));
+        }
 
     if(statusbar->position == Right
        || statusbar->position == Left)
@@ -88,15 +95,6 @@ statusbar_draw(Statusbar *statusbar)
 }
 
 void
-statusbar_draw_all(int screen)
-{
-    Statusbar *statusbar;
-
-    for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
-        statusbar_draw(statusbar);
-}
-
-void
 statusbar_display(Statusbar *statusbar)
 {
     int phys_screen = get_phys_screen(statusbar->screen);
@@ -243,6 +241,26 @@ statusbar_update_position(Statusbar *statusbar)
     while(XCheckMaskEvent(globalconf.display, EnterWindowMask, &ev));
 }
 
+
+void
+statusbar_refresh()
+{
+    int screen;
+    Statusbar *statusbar;
+    Widget *widget;
+
+    for(screen = 0; screen < get_screen_count(); screen++)
+        for(statusbar = globalconf.screens[screen].statusbar;
+            statusbar;
+            statusbar = statusbar->next)
+            for(widget = statusbar->widgets; widget; widget = widget->next)
+                if(widget->cache.needs_update)
+                {
+                    statusbar_draw(statusbar);
+                    break;
+                }
+}
+
 Position
 statusbar_get_position_from_str(const char *pos)
 {
@@ -269,7 +287,6 @@ get_statusbar_byname(int screen, const char *name)
     return NULL;
 }
 
-
 static void
 statusbar_toggle(Statusbar *statusbar)
 {
@@ -283,7 +300,7 @@ statusbar_toggle(Statusbar *statusbar)
 
 /** Toggle statusbar
  * \param screen Screen ID
- * \param arg Unused
+ * \param arg statusbar name
  * \ingroup ui_callback
  */
 void
diff --git a/statusbar.h b/statusbar.h
index 3774e0a..0bab9ba 100644
--- a/statusbar.h
+++ b/statusbar.h
@@ -24,7 +24,8 @@
 
 #include "config.h"
 
-void statusbar_draw_all(int);
+void statusbar_refresh(void);
+void statusbar_draw(Statusbar *);
 void statusbar_init(Statusbar *, int);
 void statusbar_display(Statusbar *);
 Position statusbar_get_position_from_str(const char *);
diff --git a/widget.c b/widget.c
index 9a54d68..7858eff 100644
--- a/widget.c
+++ b/widget.c
@@ -122,6 +122,19 @@ widget_common_new(Widget *widget, Statusbar *statusbar, cfg_t* config)
     widget->user_supplied_y = (widget->area.y != (int) 0xffffffff);
 }
 
+void
+widget_invalidate_cache(int screen, int flags)
+{
+    Statusbar *statusbar;
+    Widget *widget;
+
+    for(statusbar = globalconf.screens[screen].statusbar;
+        statusbar;
+        statusbar = statusbar->next)
+        for(widget = statusbar->widgets; widget; widget = widget->next)
+            widget->cache.needs_update = (widget->cache.flags & flags);
+}
+
 /** Send command to widget
  * \param screen Screen ID
  * \param arg Widget command. Syntax depends on specific widget.
@@ -166,7 +179,8 @@ uicb_widget_tell(int screen, char *arg)
     else
         widget->tell(widget, NULL);
 
-    statusbar_draw_all(screen);
+    widget->cache.needs_update = True;
+
     return;
 }
 
diff --git a/widget.h b/widget.h
index 2e679a4..8ac1b83 100644
--- a/widget.h
+++ b/widget.h
@@ -27,8 +27,14 @@
 
 #include "config.h"
 
+#define WIDGET_CACHE_CLIENTS        1<<0
+#define WIDGET_CACHE_LAYOUTS        1<<1
+#define WIDGET_CACHE_TAGS           1<<2
+#define WIDGET_CACHE_ALL            (WIDGET_CACHE_CLIENTS | WIDGET_CACHE_LAYOUTS | WIDGET_CACHE_TAGS)
+
 typedef Widget *(WidgetConstructor)(Statusbar *, cfg_t *);
 
+void widget_invalidate_cache(int, int);
 int widget_calculate_offset(int, int, int, int);
 void widget_calculate_alignments(Widget *);
 void widget_common_new(Widget*, Statusbar *, cfg_t *);
diff --git a/widgets/focustitle.c b/widgets/focustitle.c
index 4f7bca3..f647da5 100644
--- a/widgets/focustitle.c
+++ b/widgets/focustitle.c
@@ -108,6 +108,9 @@ focustitle_new(Statusbar *statusbar, cfg_t *config)
     if(!w->font)
         w->font = globalconf.screens[statusbar->screen].font;
 
+    /* Set cache property */
+    w->cache.flags = WIDGET_CACHE_CLIENTS | WIDGET_CACHE_TAGS;
+
     return w;
 }
 
diff --git a/widgets/layoutinfo.c b/widgets/layoutinfo.c
index 3b3aaa3..9ed11e9 100644
--- a/widgets/layoutinfo.c
+++ b/widgets/layoutinfo.c
@@ -64,6 +64,10 @@ layoutinfo_new(Statusbar *statusbar, cfg_t* config)
     w = p_new(Widget, 1);
     widget_common_new(w, statusbar, config);
     w->draw = layoutinfo_draw;
+
+    /* Set cache property */
+    w->cache.flags = WIDGET_CACHE_LAYOUTS;
+
     return w;
 }
 
diff --git a/widgets/netwmicon.c b/widgets/netwmicon.c
index 976897b..cbbe7b4 100644
--- a/widgets/netwmicon.c
+++ b/widgets/netwmicon.c
@@ -105,6 +105,9 @@ netwmicon_new(Statusbar *statusbar, cfg_t *config)
     widget_common_new(w, statusbar, config);
     w->draw = netwmicon_draw;
     
+    /* Set cache property */
+    w->cache.flags = WIDGET_CACHE_CLIENTS;
+
     return w;
 }
 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
diff --git a/widgets/taglist.c b/widgets/taglist.c
index f04a085..2cb42ba 100644
--- a/widgets/taglist.c
+++ b/widgets/taglist.c
@@ -182,6 +182,10 @@ taglist_new(Statusbar *statusbar, cfg_t *config)
     widget_common_new(w, statusbar, config);
     w->draw = taglist_draw;
     w->button_press = taglist_button_press;
+
+    /* Set cache property */
+    w->cache.flags = WIDGET_CACHE_TAGS;
+
     return w;
 }
 
diff --git a/widgets/tasklist.c b/widgets/tasklist.c
index f2e3280..7fe5b5a 100644
--- a/widgets/tasklist.c
+++ b/widgets/tasklist.c
@@ -253,6 +253,9 @@ tasklist_new(Statusbar *statusbar, cfg_t *config)
     if(!w->font)
         w->font = globalconf.screens[statusbar->screen].font;
 
+    /* Set cache property */
+    w->cache.flags = WIDGET_CACHE_CLIENTS;
+
     return w;
 }
 
