=== modified file 'src/IndicatorObjectEntryProxy.h'
--- src/IndicatorObjectEntryProxy.h	2010-11-11 15:07:58 +0000
+++ src/IndicatorObjectEntryProxy.h	2010-12-17 10:43:24 +0000
@@ -36,7 +36,8 @@
   virtual void         ShowMenu (int x, int y, guint32 timestamp, guint32 button) = 0;
 
   // Signals
-  sigc::signal<void> Updated;
+  sigc::signal<void> updated;
+  sigc::signal<void, bool> active_changed;
 
 public:
   bool label_visible;

=== modified file 'src/IndicatorObjectEntryProxyRemote.cpp'
--- src/IndicatorObjectEntryProxyRemote.cpp	2010-11-17 20:12:42 +0000
+++ src/IndicatorObjectEntryProxyRemote.cpp	2010-12-17 10:43:24 +0000
@@ -104,7 +104,8 @@
 
   _active = active;
 
-  Updated.emit ();
+  active_changed.emit (active);
+  updated.emit ();
 }
 
 bool
@@ -141,7 +142,7 @@
   icon_sensitive = __image_sensitive;
   icon_visible = __image_visible;
 
-  Updated.emit ();
+  updated.emit ();
 }
 
 const char *

=== modified file 'src/IndicatorObjectFactory.h'
--- src/IndicatorObjectFactory.h	2010-12-07 13:55:04 +0000
+++ src/IndicatorObjectFactory.h	2010-12-17 10:43:24 +0000
@@ -45,6 +45,7 @@
   sigc::signal<void, IndicatorObjectProxy *> OnObjectRemoved;
   sigc::signal<void, int, int>               OnMenuPointerMoved;
   sigc::signal<void, const char *>           OnEntryActivateRequest;
+  sigc::signal<void, const char *>           OnEntryActivated;
 
 protected:
   std::vector<IndicatorObjectProxy *>_indicators;

=== modified file 'src/IndicatorObjectFactoryRemote.cpp'
--- src/IndicatorObjectFactoryRemote.cpp	2010-12-13 19:53:58 +0000
+++ src/IndicatorObjectFactoryRemote.cpp	2010-12-17 10:43:24 +0000
@@ -239,7 +239,9 @@
 
       entry->SetActive (g_strcmp0 (entry_id, entry->GetId ()) == 0);
     }
-  } 
+  }
+
+  IndicatorObjectFactory::OnEntryActivated.emit (entry_id);
 }
 
 void

=== modified file 'src/PanelIndicatorObjectEntryView.cpp'
--- src/PanelIndicatorObjectEntryView.cpp	2010-12-07 15:01:07 +0000
+++ src/PanelIndicatorObjectEntryView.cpp	2010-12-17 10:43:24 +0000
@@ -31,9 +31,6 @@
 #include <gtk/gtk.h>
 #include <time.h>
 
-#define PANEL_HEIGHT 24
-#define PADDING 6
-#define SPACING 3
 
 static void draw_menu_bg (cairo_t *cr, int width, int height);
 
@@ -43,7 +40,8 @@
   _proxy (proxy),
   _util_cg (CAIRO_FORMAT_ARGB32, 1, 1)
 {
-  _proxy->Updated.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::Refresh));
+  _proxy->active_changed.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::OnActiveChanged));
+  _proxy->updated.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::Refresh));
 
   InputArea::OnMouseDown.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::OnMouseDown));
   
@@ -55,6 +53,12 @@
 }
 
 void
+PanelIndicatorObjectEntryView::OnActiveChanged (bool is_active)
+{
+  active_changed.emit (this, is_active);
+}
+
+void
 PanelIndicatorObjectEntryView::OnMouseDown (int x, int y, long button_flags, long key_flags)
 {
   if (_proxy->GetActive ())

=== modified file 'src/PanelIndicatorObjectEntryView.h'
--- src/PanelIndicatorObjectEntryView.h	2010-12-07 13:55:04 +0000
+++ src/PanelIndicatorObjectEntryView.h	2010-12-17 10:43:24 +0000
@@ -28,6 +28,10 @@
 
 #include "Introspectable.h"
 
+#define PANEL_HEIGHT 24
+#define PADDING 6
+#define SPACING 3
+
 class PanelIndicatorObjectEntryView : public nux::TextureArea, public Introspectable
 {
 public:
@@ -37,10 +41,13 @@
   void Refresh ();
   void OnMouseDown (int x, int y, long button_flags, long key_flags);
   void Activate ();
+  void OnActiveChanged (bool is_active);
 
   const gchar * GetName ();
   void          AddProperties (GVariantBuilder *builder);
 
+  sigc::signal<void, PanelIndicatorObjectEntryView *, bool> active_changed;
+
 public:
   IndicatorObjectEntryProxy *_proxy;
 private:

=== modified file 'src/PanelIndicatorObjectView.cpp'
--- src/PanelIndicatorObjectView.cpp	2010-12-02 11:55:02 +0000
+++ src/PanelIndicatorObjectView.cpp	2010-12-17 10:43:24 +0000
@@ -30,6 +30,13 @@
 
 #include <glib.h>
 
+PanelIndicatorObjectView::PanelIndicatorObjectView ()
+: View (NUX_TRACKER_LOCATION),
+  _proxy (NULL),
+  _entries ()
+{
+}
+
 PanelIndicatorObjectView::PanelIndicatorObjectView (IndicatorObjectProxy *proxy)
 : View (NUX_TRACKER_LOCATION),
   _proxy (proxy),

=== modified file 'src/PanelIndicatorObjectView.h'
--- src/PanelIndicatorObjectView.h	2010-12-02 11:55:02 +0000
+++ src/PanelIndicatorObjectView.h	2010-12-17 10:43:24 +0000
@@ -29,6 +29,7 @@
 class PanelIndicatorObjectView : public nux::View, public Introspectable
 {
 public:
+  PanelIndicatorObjectView ();
   PanelIndicatorObjectView (IndicatorObjectProxy *proxy);
   ~PanelIndicatorObjectView ();
 
@@ -47,7 +48,6 @@
   const gchar * GetChildsName ();
   void          AddProperties (GVariantBuilder *builder);
 
-private:
   IndicatorObjectProxy *_proxy;
   std::vector<PanelIndicatorObjectEntryView *> _entries;
 };

=== added file 'src/PanelMenuView.cpp'
--- src/PanelMenuView.cpp	1970-01-01 00:00:00 +0000
+++ src/PanelMenuView.cpp	2010-12-17 10:43:24 +0000
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+#include <glib.h>
+#include <pango/pangocairo.h>
+#include <gtk/gtk.h>
+
+#include "Nux/Nux.h"
+#include "Nux/HLayout.h"
+#include "Nux/VLayout.h"
+#include <Nux/TextureArea.h>
+
+#include "NuxGraphics/GLThread.h"
+#include "Nux/BaseWindow.h"
+#include "Nux/WindowCompositor.h"
+
+#include "PanelMenuView.h"
+
+#include "WindowManager.h"
+
+#include "IndicatorObjectEntryProxy.h"
+
+#include <gio/gdesktopappinfo.h>
+
+#define BUTTONS_WIDTH 72
+
+static void on_active_window_changed (BamfMatcher   *matcher,
+                                      BamfView      *old_view,
+                                      BamfView      *new_view,
+                                      PanelMenuView *self);
+
+
+PanelMenuView::PanelMenuView ()
+: _matcher (NULL),
+  _title_layer (NULL),
+  _util_cg (CAIRO_FORMAT_ARGB32, 1, 1),
+  _gradient_texture (NULL),
+  _title_tex (NULL),
+  _is_inside (false),
+  _is_maximized (false),
+  _last_active_view (NULL)
+{
+  WindowManager *win_manager;
+
+  _matcher = bamf_matcher_get_default ();
+  g_signal_connect (_matcher, "active-window-changed",
+                    G_CALLBACK (on_active_window_changed), this);
+
+  _menu_layout = new nux::HLayout ("", NUX_TRACKER_LOCATION);
+
+  /* This is for our parent and for PanelView to read indicator entries, we
+   * shouldn't touch this again
+   */
+  _layout = _menu_layout;
+
+  _window_buttons = new WindowButtons ();
+  _window_buttons->NeedRedraw ();
+  _window_buttons->close_clicked.connect (sigc::mem_fun (this, &PanelMenuView::OnCloseClicked));
+  _window_buttons->minimize_clicked.connect (sigc::mem_fun (this, &PanelMenuView::OnMinimizeClicked));
+  _window_buttons->restore_clicked.connect (sigc::mem_fun (this, &PanelMenuView::OnRestoreClicked));
+  _window_buttons->redraw_signal.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowButtonsRedraw));
+
+  win_manager = WindowManager::Default ();
+  win_manager->window_maximized.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowMaximized));
+  win_manager->window_restored.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowRestored));
+  win_manager->window_unmapped.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowUnmapped));
+
+  Refresh ();
+}
+
+PanelMenuView::~PanelMenuView ()
+{
+  if (_title_layer)
+    delete _title_layer;
+  if (_title_tex)
+    _title_tex->UnReference ();
+
+  _menu_layout->UnReference ();
+  _window_buttons->UnReference ();
+}
+
+void
+PanelMenuView::FullRedraw ()
+{
+  _menu_layout->NeedRedraw ();
+  _window_buttons->NeedRedraw ();
+  NeedRedraw ();
+}
+
+void
+PanelMenuView::SetProxy (IndicatorObjectProxy *proxy)
+{
+  _proxy = proxy;
+  printf ("IndicatorAdded: %s\n", _proxy->GetName ().c_str ());
+
+  _proxy->OnEntryAdded.connect (sigc::mem_fun (this, &PanelMenuView::OnEntryAdded));
+  _proxy->OnEntryMoved.connect (sigc::mem_fun (this, &PanelMenuView::OnEntryMoved));
+  _proxy->OnEntryRemoved.connect (sigc::mem_fun (this, &PanelMenuView::OnEntryRemoved));
+}
+
+long
+PanelMenuView::ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
+{
+  long ret = TraverseInfo;
+  nux::Geometry geo = GetGeometry ();
+
+  if (geo.IsPointInside (ievent.e_x, ievent.e_y))
+  {
+    if (_is_inside != true)
+    {
+      _is_inside = true;
+      FullRedraw ();
+    }
+  }
+  else
+  {
+    if (_is_inside != false)
+    {
+      _is_inside = false;
+      FullRedraw ();
+    }
+  }
+
+  if (_is_maximized)
+    ret = _window_buttons->ProcessEvent (ievent, ret, ProcessEventInfo);
+  ret = _menu_layout->ProcessEvent (ievent, ret, ProcessEventInfo);
+
+  return ret;
+}
+
+long PanelMenuView::PostLayoutManagement (long LayoutResult)
+{
+  long res = View::PostLayoutManagement (LayoutResult);
+  int w = _window_buttons->GetContentWidth ();
+  
+  nux::Geometry geo = GetGeometry ();
+
+  _window_buttons->SetGeometry (geo.x + PADDING, geo.y, w, geo.height);
+  _window_buttons->ComputeLayout2 ();
+  
+  /* Explicitly set the size and position of the widgets */
+  geo.x += PADDING + w + PADDING;
+  geo.width -= PADDING + w + PADDING;
+
+  _menu_layout->SetGeometry (geo.x, geo.y, geo.width, geo.height);
+  _menu_layout->ComputeLayout2();
+  
+  Refresh ();
+  
+  return res;
+}
+
+void
+PanelMenuView::Draw (nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+  nux::Geometry geo = GetGeometry ();
+  int button_width = PADDING + _window_buttons->GetContentWidth () + PADDING;
+  float factor = 4;
+  button_width /= factor;
+    
+  GfxContext.PushClippingRectangle (geo);
+
+  /* "Clear" out the background */
+  nux::ROPConfig rop; 
+  rop.Blend = true;
+  rop.SrcBlend = GL_ONE;
+  rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
+ 
+  nux::ColorLayer layer (nux::Color (0x00000000), true, rop);
+  gPainter.PushDrawLayer (GfxContext, GetGeometry (), &layer);
+
+  if (_is_maximized)
+  {
+    if (!_is_inside)
+      gPainter.PushDrawLayer (GfxContext, GetGeometry (), _title_layer);
+  }
+  else
+  {
+    if (_is_inside || _last_active_view)
+    {
+      if (_gradient_texture == NULL)
+      {
+        nux::NTextureData texture_data (nux::BITFMT_R8G8B8A8, geo.width, 1, 1);
+        nux::ImageSurface surface = texture_data.GetSurface (0);
+        nux::SURFACE_LOCKED_RECT lockrect;
+        BYTE *dest;
+        int num_row;
+            
+       _gradient_texture = nux::GetThreadGLDeviceFactory ()->CreateSystemCapableDeviceTexture (texture_data.GetWidth (), texture_data.GetHeight (), 1, texture_data.GetFormat ());
+
+        _gradient_texture->LockRect (0, &lockrect, 0);
+
+        dest = (BYTE *) lockrect.pBits;
+        num_row = surface.GetBlockHeight ();
+
+        for (int y = 0; y < num_row; y++)
+        {
+          for (int x = 0; x < geo.width; x++)
+          {
+            *(dest + y * lockrect.Pitch + 4*x + 0) = 223; //red
+            *(dest + y * lockrect.Pitch + 4*x + 1) = 219; //green
+            *(dest + y * lockrect.Pitch + 4*x + 2) = 210; //blue
+
+            if (x < button_width * (factor - 1))
+            {
+              *(dest + y * lockrect.Pitch + 4*x + 3) = 0xff;
+            }
+            else if (x < button_width * factor)
+            {
+              *(dest + y * lockrect.Pitch + 4*x + 3) = 255 - 255 * (((float)x-(button_width * (factor -1)))/(float)(button_width));
+            }
+            else
+            {
+              *(dest + y * lockrect.Pitch + 4*x + 3) = 0x00;
+            }
+          }
+        }
+        _gradient_texture->UnlockRect (0);
+      }
+      GfxContext.GetRenderStates ().SetBlend(true, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+      nux::TexCoordXForm texxform0;
+      nux::TexCoordXForm texxform1;
+
+      // Modulate the checkboard and the gradient texture
+      GfxContext.QRP_2TexMod(geo.x, geo.y,
+                             geo.width, geo.height,
+                             _gradient_texture, texxform0,
+                             nux::Color::White,
+                             _title_tex->GetDeviceTexture (),
+                             texxform1,
+                             nux::Color::White);
+
+      GfxContext.GetRenderStates ().SetBlend(false);
+
+      // The previous blend is too aggressive on the texture and therefore there
+      // is a slight loss of clarity. This fixes that
+      geo.width = button_width * (factor - 1);
+      gPainter.PushDrawLayer (GfxContext, geo, _title_layer);
+      geo = GetGeometry ();  
+    }
+    else
+    {
+      gPainter.PushDrawLayer (GfxContext,
+                              geo,
+                              _title_layer);
+    }
+  }
+
+  gPainter.PopBackground ();
+ 
+  GfxContext.PopClippingRectangle();
+}
+
+void
+PanelMenuView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
+{
+  nux::Geometry geo = GetGeometry ();
+
+  GfxContext.PushClippingRectangle (geo);
+
+  if (_is_inside || _last_active_view)
+  {
+    _layout->ProcessDraw (GfxContext, force_draw);
+  }
+
+  if (_is_maximized)
+  {
+    _window_buttons->ProcessDraw (GfxContext, true);
+  }
+
+  GfxContext.PopClippingRectangle();
+}
+
+gchar *
+PanelMenuView::GetActiveViewName ()
+{
+  gchar *label = NULL;
+
+  if (_is_maximized)
+  {
+    BamfWindow *window = bamf_matcher_get_active_window (_matcher);
+
+    if (BAMF_IS_WINDOW (window))
+      label = g_strdup (bamf_view_get_name (BAMF_VIEW (window)));
+  }
+
+  if (!label)
+  {
+    BamfApplication *app = bamf_matcher_get_active_application (_matcher);
+    if (BAMF_IS_APPLICATION (app))
+    {
+      const gchar     *filename;
+
+      filename = bamf_application_get_desktop_file (app);
+
+      if (filename && g_strcmp0 (filename, "") != 0)
+      {
+        GDesktopAppInfo *info;
+    
+        info = g_desktop_app_info_new_from_filename (bamf_application_get_desktop_file (app));
+    
+        if (info)
+        {
+          label = g_strdup (g_app_info_get_display_name (G_APP_INFO (info)));
+          g_object_unref (info);
+        }
+        else
+        {
+          g_warning ("Unable to get GDesktopAppInfo for %s",
+                     bamf_application_get_desktop_file (app));
+        }
+      }
+
+      if (label == NULL)
+      {
+        BamfView *active_view;
+
+        active_view = (BamfView *)bamf_matcher_get_active_window (_matcher);
+        if (BAMF_IS_VIEW (active_view))
+          label = g_strdup (bamf_view_get_name (active_view));
+        else
+          label = g_strdup ("");
+      }
+    }
+    else
+    {
+      label = g_strdup (" ");
+    }
+  }
+
+  return label;
+}
+
+void
+PanelMenuView::Refresh ()
+{
+  nux::Geometry         geo = GetGeometry ();
+  char                 *label = GetActiveViewName ();
+  PangoLayout          *layout = NULL;
+  PangoFontDescription *desc = NULL;
+  GtkSettings          *settings = gtk_settings_get_default ();
+  cairo_t              *cr;
+  char                 *font_description = NULL;
+  GdkScreen            *screen = gdk_screen_get_default ();
+  int                   dpi = 0;
+
+  int  x = 0;
+  int  y = 0;
+  int  width = geo.width;
+  int  height = geo.height;
+  int  text_width = 0;
+  int  text_height = 0;
+
+  if (label)
+  {
+    PangoContext *cxt;
+    PangoRectangle log_rect;
+
+    cr = _util_cg.GetContext ();
+
+    g_object_get (settings,
+                  "gtk-font-name", &font_description,
+                  "gtk-xft-dpi", &dpi,
+                  NULL);
+    desc = pango_font_description_from_string (font_description);
+    pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+
+    layout = pango_cairo_create_layout (cr);
+    pango_layout_set_font_description (layout, desc);
+    pango_layout_set_text (layout, label, -1);
+    
+    cxt = pango_layout_get_context (layout);
+    pango_cairo_context_set_font_options (cxt, gdk_screen_get_font_options (screen));
+    pango_cairo_context_set_resolution (cxt, (float)dpi/(float)PANGO_SCALE);
+    pango_layout_context_changed (layout);
+
+    pango_layout_get_extents (layout, NULL, &log_rect);
+    text_width = log_rect.width / PANGO_SCALE;
+    text_height = log_rect.height / PANGO_SCALE;
+
+    pango_font_description_free (desc);
+    g_free (font_description);
+    cairo_destroy (cr);
+  }
+
+  nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, width, height);
+  cr = cairo_graphics.GetContext();
+  cairo_set_line_width (cr, 1);
+
+  x = PADDING;
+  y = 0;
+
+  if (_is_maximized)
+    x += _window_buttons->GetContentWidth () + PADDING + PADDING;
+
+  if (label)
+  {
+    pango_cairo_update_layout (cr, layout);
+
+    // Once for the homies that couldn't be here
+    cairo_set_source_rgb (cr, 50/255.0f, 50/255.0f, 45/255.0f);
+    cairo_move_to (cr, x, ((height - text_height)/2)-1);
+    pango_cairo_show_layout (cr, layout);
+    cairo_stroke (cr);
+
+    // Once again for the homies that could
+    cairo_set_source_rgba (cr, 223/255.0f, 219/255.0f, 210/255.0f, 1.0f);
+    cairo_move_to (cr, x, (height - text_height)/2);
+    pango_cairo_show_layout (cr, layout);
+    cairo_stroke (cr);
+  }
+
+  cairo_destroy (cr);
+  if (layout)
+    g_object_unref (layout);
+
+  nux::NBitmapData* bitmap =  cairo_graphics.GetBitmap();
+
+  // The Texture is created with a reference count of 1. 
+  nux::BaseTexture* texture2D = nux::GetThreadGLDeviceFactory ()->CreateSystemCapableTexture ();
+  texture2D->Update(bitmap);
+  delete bitmap;
+
+  if (_title_layer)
+    delete _title_layer;
+  
+  nux::TexCoordXForm texxform;
+  texxform.SetTexCoordType (nux::TexCoordXForm::OFFSET_COORD);
+  texxform.SetWrap (nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
+  
+  nux::ROPConfig rop; 
+  rop.Blend = true;
+  rop.SrcBlend = GL_ONE;
+  rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
+  _title_layer = new nux::TextureLayer (texture2D->GetDeviceTexture(),
+                                        texxform,
+                                        nux::Color::White,
+                                        false, 
+                                        rop);
+
+  
+  if (_title_tex)
+    _title_tex->UnReference ();
+
+  _title_tex = texture2D;
+
+  g_free (label);
+}
+
+void
+PanelMenuView::OnActiveChanged (PanelIndicatorObjectEntryView *view,
+                                bool                           is_active)
+{
+  if (is_active)
+    _last_active_view = view;
+  else
+  {
+    if (_last_active_view == view)
+    {
+      _last_active_view = NULL;
+    }
+  }
+  FullRedraw ();
+}
+
+void
+PanelMenuView::OnEntryAdded (IndicatorObjectEntryProxy *proxy)
+{
+  PanelIndicatorObjectEntryView *view = new PanelIndicatorObjectEntryView (proxy);
+  view->active_changed.connect (sigc::mem_fun (this, &PanelMenuView::OnActiveChanged));
+  _menu_layout->AddView (view, 0, nux::eCenter, nux::eFull);
+  _menu_layout->SetContentDistribution (nux::eStackLeft);
+
+  _entries.push_back (view);
+
+  AddChild (view);
+
+  this->ComputeChildLayout ();
+  NeedRedraw ();  
+}
+
+void
+PanelMenuView::OnEntryMoved (IndicatorObjectEntryProxy *proxy)
+{
+  printf ("ERROR: Moving IndicatorObjectEntry not supported\n");
+}
+
+void
+PanelMenuView::OnEntryRemoved(IndicatorObjectEntryProxy *proxy)
+{
+  std::vector<PanelIndicatorObjectEntryView *>::iterator it;
+  
+  for (it = _entries.begin(); it != _entries.end(); it++)
+  {
+    PanelIndicatorObjectEntryView *view = static_cast<PanelIndicatorObjectEntryView *> (*it);
+    if (view->_proxy == proxy)
+      {
+        RemoveChild (view);
+        _entries.erase (it);
+        _menu_layout->RemoveChildObject (view);
+
+        break;
+      }
+  }
+
+  this->ComputeChildLayout (); 
+  NeedRedraw ();
+}
+
+void
+PanelMenuView::AllMenusClosed ()
+{
+  _is_inside = false;
+  _last_active_view = false;
+
+  FullRedraw ();
+}
+
+void
+PanelMenuView::OnActiveWindowChanged (BamfView *old_view,
+                                      BamfView *new_view)
+{
+  _is_maximized = false;
+
+  if (BAMF_IS_WINDOW (new_view))
+  {
+    BamfWindow *window = BAMF_WINDOW (new_view);
+    _is_maximized = WindowManager::Default ()->IsWindowMaximized (bamf_window_get_xid (window));
+  }
+
+  Refresh ();
+  FullRedraw ();
+}
+
+void
+PanelMenuView::OnWindowUnmapped (guint32 xid)
+{
+  _decor_map.erase (xid);
+}
+
+void
+PanelMenuView::OnWindowMaximized (guint xid)
+{
+  BamfWindow *window;
+
+  window = bamf_matcher_get_active_window (_matcher);
+  if (BAMF_IS_WINDOW (window) && bamf_window_get_xid (window) == xid)
+  {
+    // We could probably just check if a key is available, but who wants to do that
+    if (_decor_map.find (xid) == _decor_map.end ())
+      _decor_map[xid] = WindowManager::Default ()->IsWindowDecorated (xid);
+  
+    if (_decor_map[xid])
+    {
+      WindowManager::Default ()->Undecorate (xid);
+    }
+
+    _is_maximized = true;
+
+    Refresh ();
+    FullRedraw ();
+  }
+}
+
+void
+PanelMenuView::OnWindowRestored (guint xid)
+{
+  BamfWindow *window;
+  
+  window = bamf_matcher_get_active_window (_matcher);
+  if (BAMF_IS_WINDOW (window) && bamf_window_get_xid (window) == xid)
+  {
+    _is_maximized = false;
+
+    if (_decor_map[xid])
+    {
+      WindowManager::Default ()->Decorate (xid);
+    }
+
+    Refresh ();
+    FullRedraw ();
+  }
+}
+
+void
+PanelMenuView::OnCloseClicked ()
+{
+  BamfWindow *window;
+
+  window = bamf_matcher_get_active_window (_matcher);
+  if (BAMF_IS_WINDOW (window))
+    WindowManager::Default ()->Close (bamf_window_get_xid (window));
+}
+
+void
+PanelMenuView::OnMinimizeClicked ()
+{
+  BamfWindow *window;
+
+  window = bamf_matcher_get_active_window (_matcher);
+  if (BAMF_IS_WINDOW (window))
+    WindowManager::Default ()->Minimize (bamf_window_get_xid (window));
+}
+
+void
+PanelMenuView::OnRestoreClicked ()
+{
+  BamfWindow *window;
+
+  window = bamf_matcher_get_active_window (_matcher);
+  if (BAMF_IS_WINDOW (window))
+    WindowManager::Default ()->Restore (bamf_window_get_xid (window));
+}
+
+void
+PanelMenuView::OnWindowButtonsRedraw ()
+{
+  FullRedraw ();
+}
+
+// Introspectable
+const gchar *
+PanelMenuView::GetName ()
+{
+  return "MenuView";
+}
+
+const gchar *
+PanelMenuView::GetChildsName ()
+{
+  return "entries";
+}
+
+void
+PanelMenuView::AddProperties (GVariantBuilder *builder)
+{
+  nux::Geometry geo = GetGeometry ();
+
+  /* Now some props from ourselves */
+  g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (geo.x));
+  g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (geo.y));
+  g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
+  g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
+}
+
+/*
+ * C code for callbacks
+ */
+static void
+on_active_window_changed (BamfMatcher   *matcher,
+                          BamfView      *old_view,
+                          BamfView      *new_view,
+                          PanelMenuView *self)
+{
+  self->OnActiveWindowChanged (old_view, new_view);
+}

=== added file 'src/PanelMenuView.h'
--- src/PanelMenuView.h	1970-01-01 00:00:00 +0000
+++ src/PanelMenuView.h	2010-12-17 10:43:24 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#ifndef PANEL_MENU_VIEW_H
+#define PANEL_MENU_VIEW_H
+
+#include <Nux/View.h>
+#include <map>
+
+#include "IndicatorObjectProxy.h"
+#include "Introspectable.h"
+#include "PanelIndicatorObjectView.h"
+#include "StaticCairoText.h"
+#include "WindowButtons.h"
+
+#include <libbamf/libbamf.h>
+
+class PanelMenuView : public PanelIndicatorObjectView
+{
+public:
+  // This contains all the menubar logic for the Panel. Mainly it contains
+  // the following states:
+  // 1. Unmaximized window + no mouse hover
+  // 2. Unmaximized window + mouse hover
+  // 3. Unmaximized window + active menu (Alt+F/arrow key nav)
+  // 4. Maximized window + no mouse hover
+  // 5. Maximized window + mouse hover
+  // 6. Maximized window + active menu
+  //
+  // It also deals with undecorating maximized windows (and redecorating them
+  // on unmaximize)
+
+  PanelMenuView ();
+  ~PanelMenuView ();
+
+  void FullRedraw ();
+
+  virtual long ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo);
+  virtual void Draw (nux::GraphicsEngine& GfxContext, bool force_draw);
+  virtual void DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw);
+  virtual long PostLayoutManagement (long LayoutResult);
+  
+  void SetProxy (IndicatorObjectProxy *proxy);
+ 
+  void OnEntryAdded (IndicatorObjectEntryProxy *proxy);
+  void OnEntryMoved (IndicatorObjectEntryProxy *proxy);
+  void OnEntryRemoved (IndicatorObjectEntryProxy *proxy);
+  void OnActiveChanged (PanelIndicatorObjectEntryView *view, bool is_active);
+  void OnActiveWindowChanged (BamfView *old_view, BamfView *new_view);
+  
+  void OnWindowUnmapped (guint xid);
+  void OnWindowMaximized (guint32 xid);
+  void OnWindowRestored  (guint32 xid);
+
+  void Refresh ();
+  void AllMenusClosed ();
+  
+  void OnCloseClicked ();
+  void OnMinimizeClicked ();
+  void OnRestoreClicked ();
+  void OnWindowButtonsRedraw ();
+
+protected:
+  const gchar * GetName ();
+  const gchar * GetChildsName ();
+  void          AddProperties (GVariantBuilder *builder);
+
+private:
+  gchar * GetActiveViewName ();
+  
+private:
+  BamfMatcher* _matcher;
+
+  nux::AbstractPaintLayer *_title_layer;
+  nux::HLayout            *_menu_layout;
+  nux::CairoGraphics       _util_cg;
+  nux::IntrusiveSP<nux::IOpenGLBaseTexture> _gradient_texture;
+  nux::BaseTexture        *_title_tex;
+
+  bool _is_inside;
+  bool _is_maximized; 
+  PanelIndicatorObjectEntryView *_last_active_view;
+
+  WindowButtons *_window_buttons;
+
+  std::map<guint32, bool> _decor_map;
+};
+#endif

=== modified file 'src/PanelView.cpp'
--- src/PanelView.cpp	2010-12-09 17:58:53 +0000
+++ src/PanelView.cpp	2010-12-17 10:43:24 +0000
@@ -46,13 +46,17 @@
    // Home button
    _home_button = new PanelHomeButton ();
    _layout->AddView (_home_button, 0, nux::eCenter, nux::eFull);
-
    AddChild (_home_button);
 
+   _menu_view = new PanelMenuView ();
+   _layout->AddView (_menu_view, 1, nux::eCenter, nux::eFull);
+   AddChild (_menu_view);
+
   _remote = new IndicatorObjectFactoryRemote ();
   _remote->OnObjectAdded.connect (sigc::mem_fun (this, &PanelView::OnObjectAdded));
   _remote->OnMenuPointerMoved.connect (sigc::mem_fun (this, &PanelView::OnMenuPointerMoved));
   _remote->OnEntryActivateRequest.connect (sigc::mem_fun (this, &PanelView::OnEntryActivateRequest));
+  _remote->IndicatorObjectFactory::OnEntryActivated.connect (sigc::mem_fun (this, &PanelView::OnEntryActivated));
 }
 
 PanelView::~PanelView ()
@@ -204,7 +208,11 @@
 
   // Appmenu is treated differently as it needs to expand
   // We could do this in a more special way, but who has the time for special?
-  _layout->AddView (view, (g_strstr_len (proxy->GetName ().c_str (), -1, "appmenu") != NULL), nux::eCenter, nux::eFull);
+  if (g_strstr_len (proxy->GetName ().c_str (), -1, "appmenu") != NULL)
+    _menu_view->SetProxy (proxy);
+  else
+    _layout->AddView (view, 0, nux::eCenter, nux::eFull);
+
   _layout->SetContentDistribution (nux::eStackLeft);
   
   AddChild (view);
@@ -224,40 +232,40 @@
   
   if (x >= geo.x && x <= (geo.x + geo.width)
       && y >= geo.y && y <= (geo.y + geo.height))
+  {
+    std::list<Area *>::iterator it;
+
+    std::list<Area *> my_children = _layout->GetChildren ();
+    for (it = my_children.begin(); it != my_children.end(); it++)
     {
-      std::list<Area *>::iterator it;
+      PanelIndicatorObjectView *view = static_cast<PanelIndicatorObjectView *> (*it);
+      
+      if (view->_layout == NULL)
+        continue;
 
-      std::list<Area *> my_children = _layout->GetChildren ();
-      for (it = my_children.begin(); it != my_children.end(); it++)
+      geo = view->GetGeometry ();
+      if (x >= geo.x && x <= (geo.x + geo.width)
+          && y >= geo.y && y <= (geo.y + geo.height))
       {
-        PanelIndicatorObjectView *view = static_cast<PanelIndicatorObjectView *> (*it);
-        
-        if (view->_layout == NULL)
-          continue;
-
-        geo = view->GetGeometry ();
-        if (x >= geo.x && x <= (geo.x + geo.width)
-            && y >= geo.y && y <= (geo.y + geo.height))
+        std::list<Area *>::iterator it2;
+
+        std::list<Area *> its_children = view->_layout->GetChildren ();
+        for (it2 = its_children.begin(); it2 != its_children.end(); it2++)
+        {
+          PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
+
+          geo = entry->GetGeometry ();
+          if (x >= geo.x && x <= (geo.x + geo.width)
+              && y >= geo.y && y <= (geo.y + geo.height))
           {
-            std::list<Area *>::iterator it2;
-
-            std::list<Area *> its_children = view->_layout->GetChildren ();
-            for (it2 = its_children.begin(); it2 != its_children.end(); it2++)
-            {
-              PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
-
-              geo = entry->GetGeometry ();
-              if (x >= geo.x && x <= (geo.x + geo.width)
-                  && y >= geo.y && y <= (geo.y + geo.height))
-                {
-                  entry->OnMouseDown (x, y, 0, 0);
-                  break;
-                }
-            }
+            entry->OnMouseDown (x, y, 0, 0);
             break;
           }
+        }
+        break;
       }
     }
+  }
 }
 
 void
@@ -281,10 +289,18 @@
       PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
 
       if (g_strcmp0 (entry->GetName (), entry_id) == 0)
-        {
-          entry->Activate ();
-          break;
-        }
+      {
+        g_debug ("%s: Activating: %s", G_STRFUNC, entry_id);
+        entry->Activate ();
+        break;
+      }
     }
   }
 }
+
+void
+PanelView::OnEntryActivated (const char *entry_id)
+{
+  if (g_strcmp0 (entry_id, "") == 0)
+    _menu_view->AllMenusClosed ();
+}

=== modified file 'src/PanelView.h'
--- src/PanelView.h	2010-12-07 13:55:04 +0000
+++ src/PanelView.h	2010-12-17 10:43:24 +0000
@@ -24,6 +24,7 @@
 #include <NuxGraphics/GraphicsEngine.h>
 
 #include "PanelHomeButton.h"
+#include "PanelMenuView.h"
 #include "IndicatorObjectFactoryRemote.h"
 #include "Introspectable.h"
 
@@ -43,6 +44,7 @@
   void OnObjectAdded (IndicatorObjectProxy *proxy);
   void OnMenuPointerMoved (int x, int y);
   void OnEntryActivateRequest (const char *entry_id);
+  void OnEntryActivated (const char *entry_id);
   
   PanelHomeButton * HomeButton ();
 
@@ -59,6 +61,7 @@
   IndicatorObjectFactoryRemote *_remote;
 
   PanelHomeButton         *_home_button;
+  PanelMenuView           *_menu_view;
   nux::AbstractPaintLayer *_bg_layer;
   nux::HLayout            *_layout;
 

=== modified file 'src/PluginAdapter.cpp'
--- src/PluginAdapter.cpp	2010-12-17 10:03:18 +0000
+++ src/PluginAdapter.cpp	2010-12-17 10:43:24 +0000
@@ -65,9 +65,15 @@
 PluginAdapter::NotifyStateChange (CompWindow *window, unsigned int state, unsigned int last_state)
 {
   if (!(last_state & MAXIMIZE_STATE) && (state & MAXIMIZE_STATE))
-    window_maximized.emit (window);
+  {
+    PluginAdapter::window_maximized.emit (window);
+    WindowManager::window_maximized.emit (window->id ());
+  }
   else if ((last_state & MAXIMIZE_STATE) && !(state & MAXIMIZE_STATE))
-    window_restored.emit (window);
+  {
+    PluginAdapter::window_restored.emit (window);
+    WindowManager::window_restored.emit (window->id ());
+  }
 }
 
 void 
@@ -94,10 +100,12 @@
       window_shown.emit (window);
       break;
     case CompWindowNotifyMap:
-      window_mapped.emit (window);
+      PluginAdapter::window_mapped.emit (window);
+      WindowManager::window_mapped.emit (window->id ());
       break;
     case CompWindowNotifyUnmap:
-      window_unmapped.emit (window);
+      PluginAdapter::window_unmapped.emit (window);
+      WindowManager::window_unmapped.emit (window->id ());
       break;
     default:
       break;
@@ -216,3 +224,68 @@
     
     m_ExpoAction->initiate () (m_ExpoAction, 0, argument);
 }
+
+// WindowManager implementation
+bool
+PluginAdapter::IsWindowMaximized (guint xid)
+{
+  Window win = (Window)xid;
+  CompWindow *window;
+
+  window = m_Screen->findWindow (win);
+  if (window)
+  {
+    return window->state () & MAXIMIZE_STATE;
+  }
+
+  return false;
+}
+
+bool
+PluginAdapter::IsWindowDecorated (guint32 xid)
+{
+  Window win = (Window)xid;
+  CompWindow *window;
+
+  window = m_Screen->findWindow (win);
+  if (window)
+  {
+    unsigned int decor = window->mwmDecor ();
+
+    return decor & (MwmDecorAll | MwmDecorTitle);
+  }
+  return true;
+}
+
+void
+PluginAdapter::Restore (guint32 xid)
+{
+  Window win = (Window)xid;
+  CompWindow *window;
+
+  window = m_Screen->findWindow (win);
+  if (window)
+    window->maximize (0);
+}
+
+void
+PluginAdapter::Minimize (guint32 xid)
+{
+  Window win = (Window)xid;
+  CompWindow *window;
+
+  window = m_Screen->findWindow (win);
+  if (window)
+    window->minimize ();
+}
+
+void
+PluginAdapter::Close (guint32 xid)
+{
+  Window win = (Window)xid;
+  CompWindow *window;
+
+  window = m_Screen->findWindow (win);
+  if (window)
+    window->close (CurrentTime);
+}

=== modified file 'src/PluginAdapter.h'
--- src/PluginAdapter.h	2010-12-17 10:03:18 +0000
+++ src/PluginAdapter.h	2010-12-17 10:43:24 +0000
@@ -24,7 +24,9 @@
 
 #include <sigc++/sigc++.h>
 
-class PluginAdapter : public sigc::trackable
+#include "WindowManager.h"
+
+class PluginAdapter : public sigc::trackable, public WindowManager
 {
 public:
     static PluginAdapter * Default ();
@@ -52,6 +54,13 @@
     void NotifyResized (CompWindow *window, int x, int y, int w, int h);
     void NotifyStateChange (CompWindow *window, unsigned int state, unsigned int last_state);
     
+    // WindowManager implementation
+    bool IsWindowMaximized (guint xid);
+    bool IsWindowDecorated (guint xid);
+    void Restore (guint32 xid);
+    void Minimize (guint32 xid);
+    void Close (guint32 xid);
+    
     sigc::signal<void, CompWindow *> window_maximized;
     sigc::signal<void, CompWindow *> window_restored;
     sigc::signal<void, CompWindow *> window_minimized;

=== added file 'src/WindowButtons.cpp'
--- src/WindowButtons.cpp	1970-01-01 00:00:00 +0000
+++ src/WindowButtons.cpp	2010-12-17 10:43:24 +0000
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#include "Nux/Nux.h"
+#include "Nux/HLayout.h"
+#include "Nux/VLayout.h"
+#include "Nux/Button.h"
+
+#include "NuxGraphics/GLThread.h"
+#include "Nux/BaseWindow.h"
+#include "Nux/WindowCompositor.h"
+
+#include "WindowButtons.h"
+
+#include <glib.h>
+
+
+// FIXME: This will be all automatic in the future
+#define AMBIANCE "/usr/share/themes/Ambiance/metacity-1"
+
+enum
+{
+  BUTTON_CLOSE=0,
+  BUTTON_MINIMISE,
+  BUTTON_UNMAXIMISE
+};
+
+class WindowButton : public nux::Button
+{
+  // A single window button
+public:
+  WindowButton (int type)
+  : nux::Button ("X", NUX_TRACKER_LOCATION),
+    _normal_tex (NULL),
+    _prelight_tex (NULL),
+    _pressed_tex (NULL)
+  {
+    if (type == BUTTON_CLOSE)
+      LoadImages ("close");
+    else if (type == BUTTON_MINIMISE)
+      LoadImages ("minimize");
+    else
+      LoadImages ("unmaximize");
+  }
+
+  ~WindowButton ()
+  {
+    _normal_tex->UnReference ();
+    _prelight_tex->UnReference ();
+    _pressed_tex->UnReference ();
+  }
+
+  void Draw (nux::GraphicsEngine &GfxContext, bool force_draw)
+  {
+    nux::Geometry      geo  = GetGeometry ();
+    nux::BaseTexture  *tex;
+    nux::TexCoordXForm texxform;
+ 
+    GfxContext.PushClippingRectangle (geo);
+
+    if (HasMouseFocus ())
+    {
+      tex = _pressed_tex;
+    }
+    else if (IsMouseInside ())
+    {
+      tex = _prelight_tex;
+    }
+    else
+    {
+      tex = _normal_tex;
+    }
+
+    GfxContext.GetRenderStates ().SetSeparateBlend (true,
+                                                    GL_SRC_ALPHA,
+                                                    GL_ONE_MINUS_SRC_ALPHA,
+                                                    GL_ONE_MINUS_DST_ALPHA,
+                                                    GL_ONE);
+    GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
+    if (tex)
+      GfxContext.QRP_GLSL_1Tex (geo.x,
+                                geo.y,
+                                (float)geo.width,
+                                (float)geo.height,
+                                tex->GetDeviceTexture (),
+                                texxform,
+                                nux::Color::White);
+    GfxContext.GetRenderStates ().SetSeparateBlend (false,
+                                                    GL_SRC_ALPHA,
+                                                    GL_ONE_MINUS_SRC_ALPHA,
+                                                    GL_ONE_MINUS_DST_ALPHA,
+                                                    GL_ONE);
+    GfxContext.PopClippingRectangle();
+  }
+
+  void LoadImages (const char *name)
+  {
+    //FIXME: We need to somehow be theme aware. Or, at least support the themes
+    //       we know and have a good default fallback
+    gchar  *filename;
+    GError *error = NULL;
+    GdkPixbuf *_normal;
+    GdkPixbuf *_prelight;
+    GdkPixbuf *_pressed;
+
+    filename = g_strdup_printf ("%s/%s.png", AMBIANCE, name);
+    _normal = gdk_pixbuf_new_from_file (filename, &error);
+    if (error)
+    {
+      g_warning ("Unable to load window button %s: %s", filename, error->message);
+      g_error_free (error);
+      error = NULL;
+    }
+    else
+      _normal_tex = nux::CreateTextureFromPixbuf (_normal);
+    g_free (filename);
+    g_object_unref (_normal);
+
+    filename = g_strdup_printf ("%s/%s_focused_prelight.png", AMBIANCE, name);
+    _prelight = gdk_pixbuf_new_from_file (filename, &error);
+    if (error)
+    {
+      g_warning ("Unable to load window button %s: %s", filename, error->message);
+      g_error_free (error);
+      error = NULL;
+    }
+    else
+      _prelight_tex = nux::CreateTextureFromPixbuf (_prelight);
+    g_free (filename);
+    g_object_unref (_prelight);
+
+    filename = g_strdup_printf ("%s/%s_focused_pressed.png", AMBIANCE, name);
+    _pressed = gdk_pixbuf_new_from_file (filename, &error);
+    if (error)
+    {
+      g_warning ("Unable to load window button %s: %s", name, error->message);
+      g_error_free (error);
+      error = NULL;
+    }
+    else
+      _pressed_tex = nux::CreateTextureFromPixbuf (_pressed);
+    g_free (filename);
+    g_object_unref (_pressed);
+
+    if (_normal_tex)
+      SetMinimumSize (_normal_tex->GetWidth (), _normal_tex->GetHeight ());
+  }
+
+private:
+  nux::BaseTexture *_normal_tex;
+  nux::BaseTexture *_prelight_tex;
+  nux::BaseTexture *_pressed_tex;
+};
+
+
+WindowButtons::WindowButtons ()
+: HLayout ("", NUX_TRACKER_LOCATION)
+{
+  WindowButton *but;
+
+  but = new WindowButton (BUTTON_CLOSE);
+  AddView (but, 0, nux::eCenter, nux::eFix);
+  but->sigClick.connect (sigc::mem_fun (this, &WindowButtons::OnCloseClicked));
+  but->OnMouseEnter.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseEnter));
+  but->OnMouseLeave.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseLeave));
+
+  but = new WindowButton (BUTTON_MINIMISE);
+  AddView (but, 0, nux::eCenter, nux::eFix);
+  but->sigClick.connect (sigc::mem_fun (this, &WindowButtons::OnMinimizeClicked));
+  but->OnMouseEnter.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseEnter));
+  but->OnMouseLeave.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseLeave));
+
+  but = new WindowButton (BUTTON_UNMAXIMISE);
+  AddView (but, 0, nux::eCenter, nux::eFix);
+  but->sigClick.connect (sigc::mem_fun (this, &WindowButtons::OnRestoreClicked));
+  but->OnMouseEnter.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseEnter));
+  but->OnMouseLeave.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseLeave));
+
+  SetContentDistribution (nux::eStackLeft);
+}
+
+
+WindowButtons::~WindowButtons ()
+{
+}
+
+void
+WindowButtons::OnCloseClicked ()
+{
+  close_clicked.emit ();
+}
+
+void
+WindowButtons::OnMinimizeClicked ()
+{
+  minimize_clicked.emit ();
+}
+
+void
+WindowButtons::OnRestoreClicked ()
+{
+  restore_clicked.emit ();
+}
+
+const gchar *
+WindowButtons::GetName ()
+{
+  return "window-buttons";
+}
+
+const gchar *
+WindowButtons::GetChildsName ()
+{
+  return "";
+}
+
+void
+WindowButtons::AddProperties (GVariantBuilder *builder)
+{
+  nux::Geometry geo = GetGeometry ();
+
+  /* Now some props from ourselves */
+  g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (geo.x));
+  g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (geo.y));
+  g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
+  g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
+}
+
+void WindowButtons::RecvMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+  redraw_signal.emit ();
+}
+
+void WindowButtons::RecvMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+  redraw_signal.emit ();
+}
+
+

=== added file 'src/WindowButtons.h'
--- src/WindowButtons.h	1970-01-01 00:00:00 +0000
+++ src/WindowButtons.h	2010-12-17 10:43:24 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#ifndef WINDOW_BUTTONS_H
+#define WINDOW_BUTTONS_H
+
+#include <Nux/View.h>
+
+#include "Introspectable.h"
+
+class WindowButtons : public nux::HLayout, public Introspectable
+{
+  // These are the [close][minimize][restore] buttons on the panel when there
+  // is a maximized window
+
+public:
+  WindowButtons ();
+  ~WindowButtons ();
+
+  sigc::signal<void> close_clicked;
+  sigc::signal<void> minimize_clicked;
+  sigc::signal<void> restore_clicked;
+  sigc::signal<void> redraw_signal;
+
+protected:
+  const gchar * GetName ();
+  const gchar * GetChildsName ();
+  void          AddProperties (GVariantBuilder *builder);
+
+
+  // For testing the buttons
+  void RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags);
+  void RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags);
+  void RecvMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags);
+  void RecvMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags);
+  void RecvMouseClick (int x, int y, unsigned long button_flags, unsigned long key_flags);
+  void RecvMouseMove (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
+
+private:
+  void OnCloseClicked ();
+  void OnMinimizeClicked ();
+  void OnRestoreClicked ();
+
+private:
+  nux::HLayout *_layout;
+};
+
+#endif

=== added file 'src/WindowManager.cpp'
--- src/WindowManager.cpp	1970-01-01 00:00:00 +0000
+++ src/WindowManager.cpp	2010-12-17 10:43:24 +0000
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#include "WindowManager.h"
+
+#include <gdk/gdkx.h>
+
+typedef struct {
+    unsigned long flags;
+    unsigned long functions;
+    unsigned long decorations;
+    long input_mode;
+    unsigned long status;
+} MotifWmHints, MwmHints;
+
+#define MWM_HINTS_FUNCTIONS     (1L << 0)
+#define MWM_HINTS_DECORATIONS   (1L << 1)
+#define _XA_MOTIF_WM_HINTS		"_MOTIF_WM_HINTS"
+
+static void gdk_window_set_mwm_hints (Window        xid,
+                                      MotifWmHints *new_hints);
+
+
+static WindowManager *window_manager = NULL;
+
+class WindowManagerDummy : public WindowManager
+{
+  bool IsWindowMaximized (guint32 xid)
+  {
+    return false;
+  }
+
+  bool IsWindowDecorated (guint32 xid)
+  {
+    return true;
+  }
+
+  void Restore (guint32 xid)
+  {
+    g_debug ("%s", G_STRFUNC);
+  }
+
+  void Minimize (guint32 xid)
+  {
+    g_debug ("%s", G_STRFUNC);
+  }
+
+ void Close (guint32 xid)
+  {
+    g_debug ("%s", G_STRFUNC);
+  }
+};
+
+WindowManager *
+WindowManager::Default ()
+{
+  if (!window_manager)
+    window_manager = new WindowManagerDummy ();
+
+  return window_manager;
+}
+
+void
+WindowManager::SetDefault (WindowManager *manager)
+{
+  window_manager = manager;
+}
+
+void
+WindowManager::Decorate (guint32 xid)
+{
+  MotifWmHints hints = { 0 };
+    
+  hints.flags = MWM_HINTS_DECORATIONS;
+  hints.decorations = GDK_DECOR_ALL;
+ 
+  gdk_window_set_mwm_hints (xid, &hints);
+}
+
+void
+WindowManager::Undecorate (guint32 xid)
+{
+  MotifWmHints hints = { 0 };
+    
+  hints.flags = MWM_HINTS_DECORATIONS;
+  hints.decorations = 0;
+ 
+  gdk_window_set_mwm_hints (xid, &hints);
+}
+
+/*
+ * Copied over C code
+ */
+static void
+gdk_window_set_mwm_hints (Window        xid,
+                          MotifWmHints *new_hints)
+{
+  GdkDisplay *display = gdk_display_get_default();
+  Atom hints_atom = None;
+  guchar *data = NULL;
+  MotifWmHints *hints = NULL;
+  Atom type = None;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+  
+  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, 
+                                                      _XA_MOTIF_WM_HINTS);
+
+  gdk_error_trap_push ();
+  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
+                      xid,
+		                  hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
+		                  False, AnyPropertyType, &type, &format, &nitems,
+		                  &bytes_after, &data);
+  gdk_flush ();
+  if (gdk_error_trap_pop ())
+    {
+      g_debug ("ERROR: Cannot set decorations");
+      return;
+    }
+    
+  if (type != hints_atom || !data)
+    hints = new_hints;
+  else
+  {
+    hints = (MotifWmHints *)data;
+	
+    if (new_hints->flags & MWM_HINTS_FUNCTIONS)
+    {
+      hints->flags |= MWM_HINTS_FUNCTIONS;
+      hints->functions = new_hints->functions;  
+    }
+    if (new_hints->flags & MWM_HINTS_DECORATIONS)
+    {
+      hints->flags |= MWM_HINTS_DECORATIONS;
+      hints->decorations = new_hints->decorations;
+    }
+  }
+  
+  gdk_error_trap_push ();
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), 
+                   xid,
+                   hints_atom, hints_atom, 32, PropModeReplace,
+                   (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
+  gdk_flush ();
+  if (gdk_error_trap_pop ())
+    {
+      g_debug ("ERROR: Setting decorations");
+    }
+  
+  if (data)
+    XFree (data);
+}

=== added file 'src/WindowManager.h'
--- src/WindowManager.h	1970-01-01 00:00:00 +0000
+++ src/WindowManager.h	2010-12-17 10:43:24 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#ifndef WINDOW_MANAGER_H
+#define WINDOW_MANAGER_H
+
+#include <glib.h>
+#include <sigc++/sigc++.h>
+
+class WindowManager
+{
+  // This is a glue interface that breaks the dependancy of Unity with Compiz
+  // Basically it has a default implementation that does nothing useful, but
+  // the idea is that unity.cpp uses SetDefault() early enough in it's
+  // initialization so the things that require it get a usable implementation
+  //
+  // Currently only the Panel uses it but hopefully we'll get more of
+  // PluginAdaptor features moved into here and also get the Launcher to use
+  // it.
+
+public:
+  static WindowManager * Default ();
+  static void            SetDefault (WindowManager *manager);
+
+  virtual bool IsWindowMaximized (guint32 xid) = 0;
+  virtual bool IsWindowDecorated (guint32 xid) = 0;
+
+  virtual void Restore (guint32 xid) = 0;
+  virtual void Minimize (guint32 xid) = 0;
+  virtual void Close (guint32 xid) = 0;
+
+  virtual void Decorate   (guint32 xid);
+  virtual void Undecorate (guint32 xid);
+
+  // Signals
+  sigc::signal<void, guint32> window_mapped;
+  sigc::signal<void, guint32> window_unmapped;
+  sigc::signal<void, guint32> window_maximized;
+  sigc::signal<void, guint32> window_restored;
+};
+
+#endif // WINDOW_MANAGER_H

=== modified file 'src/unity.cpp'
--- src/unity.cpp	2010-12-16 21:07:28 +0000
+++ src/unity.cpp	2010-12-17 10:43:24 +0000
@@ -395,6 +395,8 @@
   GLScreenInterface::setHandler (gScreen);
 
   PluginAdapter::Initialize (screen);
+  WindowManager::SetDefault (PluginAdapter::Default ());
+
   StartupNotifyService::Default ()->SetSnDisplay (screen->snDisplay (), screen->screenNum ());
 
   nux::NuxInitialize (0);
@@ -410,7 +412,6 @@
 
   debugger = new IntrospectionDBusInterface (this);
 
-
   optionSetLauncherAutohideNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
   optionSetLauncherFloatNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
 

=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt	2010-12-13 09:54:54 +0000
+++ tests/CMakeLists.txt	2010-12-17 10:43:24 +0000
@@ -82,6 +82,14 @@
                 ../src/Introspectable.h
                 ../src/PanelHomeButton.cpp
                 ../src/PanelHomeButton.h
+                ../src/PanelMenuView.cpp
+                ../src/PanelMenuView.h
+                ../src/StaticCairoText.cpp
+                ../src/StaticCairoText.h
+                ../src/WindowButtons.cpp
+                ../src/WindowButtons.h
+                ../src/WindowManager.cpp
+                ../src/WindowManager.h
                 ../libunity/ubus-server.c
                 ../libunity/ubus-server.h
                 )

