Back to index

unity  6.0.0
WindowButtons.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 2010-2012 Canonical Ltd
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  *
00017  * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
00018  *              Marco Trevisan (TreviƱo) <3v1n0@ubuntu.com>
00019  */
00020 
00021 #include "config.h"
00022 
00023 #include <Nux/Nux.h>
00024 
00025 #include <UnityCore/GLibWrapper.h>
00026 #include <UnityCore/Variant.h>
00027 
00028 #include "WindowButtons.h"
00029 
00030 #include "unity-shared/UnitySettings.h"
00031 #include "unity-shared/PanelStyle.h"
00032 #include "unity-shared/UBusMessages.h"
00033 #include "unity-shared/WindowManager.h"
00034 
00035 namespace unity
00036 {
00037 
00038 class WindowButton : public nux::Button, public debug::Introspectable
00039 {
00040   // A single window button
00041 public:
00042   WindowButton(panel::WindowButtonType type)
00043     : nux::Button("", NUX_TRACKER_LOCATION)
00044     , _type(type)
00045     , _focused(true)
00046     , _overlay_is_open(false)
00047     , _opacity(1.0f)
00048   {
00049     SetAcceptKeyNavFocusOnMouseDown(false);
00050     panel::Style::Instance().changed.connect(sigc::mem_fun(this, &WindowButton::LoadImages));
00051     LoadImages();
00052   }
00053 
00054   void SetVisualState(nux::ButtonVisualState new_state)
00055   {
00056     if (new_state != visual_state_)
00057     {
00058       visual_state_ = new_state;
00059       QueueDraw();
00060     }
00061   }
00062 
00063   void Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
00064   {
00065     nux::Geometry const& geo = GetGeometry();
00066     nux::BaseTexture* tex;
00067     nux::TexCoordXForm texxform;
00068 
00069     GfxContext.PushClippingRectangle(geo);
00070 
00071     if (_overlay_is_open)
00072     {
00073       if (!IsEnabled())
00074       {
00075         tex = _disabled_dash_tex.GetPointer();
00076       }
00077       else
00078       {
00079         switch (visual_state_)
00080         {
00081           case nux::VISUAL_STATE_PRESSED:
00082             tex = _pressed_dash_tex.GetPointer();
00083             break;
00084           case nux::VISUAL_STATE_PRELIGHT:
00085             tex = _prelight_dash_tex.GetPointer();
00086             break;
00087           default:
00088             tex = _normal_dash_tex.GetPointer();
00089         }
00090       }
00091     }
00092     else if (!IsEnabled())
00093     {
00094       tex = _disabled_tex.GetPointer();
00095     }
00096     else if (!_focused)
00097     {
00098       switch (visual_state_)
00099       {
00100         case nux::VISUAL_STATE_PRESSED:
00101           tex = _unfocused_pressed_tex.GetPointer();
00102           break;
00103         case nux::VISUAL_STATE_PRELIGHT:
00104           tex = _unfocused_prelight_tex.GetPointer();
00105           break;
00106         default:
00107           tex = _unfocused_tex.GetPointer();
00108       }
00109     }
00110     else
00111     {
00112       switch (visual_state_)
00113       {
00114         case nux::VISUAL_STATE_PRESSED:
00115           tex = _pressed_tex.GetPointer();
00116           break;
00117         case nux::VISUAL_STATE_PRELIGHT:
00118           tex = _prelight_tex.GetPointer();
00119           break;
00120         default:
00121           tex = _normal_tex.GetPointer();
00122       }
00123     }
00124 
00125     if (tex)
00126     {
00127       GfxContext.QRP_1Tex(geo.x, geo.y, geo.width, geo.height,
00128                           tex->GetDeviceTexture(), texxform,
00129                           nux::color::White * _opacity);
00130     }
00131 
00132     GfxContext.PopClippingRectangle();
00133   }
00134 
00135   void UpdateSize()
00136   {
00137     int panel_height = panel::Style::Instance().panel_height;
00138     nux::BaseTexture* tex;
00139     tex = (_overlay_is_open) ? _normal_dash_tex.GetPointer() : _normal_tex.GetPointer();
00140     int width = 0;
00141     int height = 0;
00142 
00143     if (tex)
00144     {
00145       width = std::min(panel_height, tex->GetWidth());
00146       height = std::min(panel_height, tex->GetHeight());
00147     }
00148 
00149     SetMinMaxSize(width, height);
00150   }
00151 
00152   void LoadImages()
00153   {
00154     panel::Style& style = panel::Style::Instance();
00155 
00156     _normal_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::NORMAL));
00157     _prelight_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::PRELIGHT));
00158     _pressed_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::PRESSED));
00159     _unfocused_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::UNFOCUSED));
00160     _disabled_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::DISABLED));
00161     _unfocused_prelight_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::UNFOCUSED_PRELIGHT));
00162     _unfocused_pressed_tex.Adopt(style.GetWindowButton(_type, panel::WindowState::UNFOCUSED_PRESSED));
00163     _normal_dash_tex.Adopt(GetDashWindowButton(_type, panel::WindowState::NORMAL));
00164     _prelight_dash_tex.Adopt(GetDashWindowButton(_type, panel::WindowState::PRELIGHT));
00165     _pressed_dash_tex.Adopt(GetDashWindowButton(_type, panel::WindowState::PRESSED));
00166     _disabled_dash_tex.Adopt(GetDashWindowButton(_type, panel::WindowState::DISABLED));
00167 
00168     UpdateSize();
00169     QueueDraw();
00170   }
00171 
00172   void SetOpacity(double opacity)
00173   {
00174     if (_opacity != opacity)
00175     {
00176       _opacity = opacity;
00177       SetInputEventSensitivity(_opacity != 0.0f);
00178 
00179       QueueDraw();
00180     }
00181   }
00182 
00183   double GetOpacity() const
00184   {
00185     return _opacity;
00186   }
00187 
00188   void SetFocusedState(bool focused)
00189   {
00190     if (_focused != focused)
00191     {
00192       _focused = focused;
00193       QueueDraw();
00194     }
00195   }
00196 
00197   void SetOverlayOpen(bool open)
00198   {
00199     if (_overlay_is_open == open)
00200       return;
00201 
00202     _overlay_is_open = open;
00203 
00204     UpdateSize();
00205     QueueDraw();
00206   }
00207 
00208   bool IsOverlayOpen()
00209   {
00210     return _overlay_is_open;
00211   }
00212 
00213   panel::WindowButtonType GetType() const
00214   {
00215     return _type;
00216   }
00217 
00218   void ChangeType(panel::WindowButtonType new_type)
00219   {
00220     if (_type != new_type)
00221     {
00222       _type = new_type;
00223       LoadImages();
00224     }
00225   }
00226 
00227   void SetEnabled(bool enabled)
00228   {
00229     if (enabled == IsEnabled())
00230       return;
00231 
00232     SetEnableView(enabled);
00233     QueueDraw();
00234   }
00235 
00236   bool IsEnabled()
00237   {
00238     return IsViewEnabled();
00239   }
00240 
00241 protected:
00242   std::string GetName() const
00243   {
00244     return "WindowButton";
00245   }
00246 
00247   void AddProperties(GVariantBuilder* builder)
00248   {
00249     std::string type_name;
00250     std::string state_name;
00251 
00252     switch (_type)
00253     {
00254       case panel::WindowButtonType::CLOSE:
00255         type_name = "Close";
00256         break;
00257       case panel::WindowButtonType::MINIMIZE:
00258         type_name = "Minimize";
00259         break;
00260       case panel::WindowButtonType::MAXIMIZE:
00261         type_name = "Maximize";
00262         break;
00263       case panel::WindowButtonType::UNMAXIMIZE:
00264         type_name = "Unmaximize";
00265         break;
00266     }
00267 
00268     switch (visual_state_)
00269     {
00270       case nux::VISUAL_STATE_PRESSED:
00271         state_name = "pressed";
00272         break;
00273       case nux::VISUAL_STATE_PRELIGHT:
00274         state_name = "prelight";
00275         break;
00276       default:
00277         state_name = "normal";
00278     }
00279 
00280     variant::BuilderWrapper(builder).add(GetAbsoluteGeometry())
00281                                     .add("type", type_name)
00282                                     .add("visible", IsVisible() && _opacity != 0.0f)
00283                                     .add("sensitive", GetInputEventSensitivity())
00284                                     .add("enabled", IsEnabled())
00285                                     .add("visual_state", state_name)
00286                                     .add("opacity", _opacity)
00287                                     .add("focused", _focused)
00288                                     .add("overlay_mode", _overlay_is_open);
00289   }
00290 
00291 
00292 private:
00293   panel::WindowButtonType _type;
00294   bool _focused;
00295   bool _overlay_is_open;
00296   double _opacity;
00297 
00298   nux::ObjectPtr<nux::BaseTexture> _normal_tex;
00299   nux::ObjectPtr<nux::BaseTexture> _prelight_tex;
00300   nux::ObjectPtr<nux::BaseTexture> _pressed_tex;
00301   nux::ObjectPtr<nux::BaseTexture> _unfocused_tex;
00302   nux::ObjectPtr<nux::BaseTexture> _unfocused_prelight_tex;
00303   nux::ObjectPtr<nux::BaseTexture> _unfocused_pressed_tex;
00304   nux::ObjectPtr<nux::BaseTexture> _disabled_tex;
00305   nux::ObjectPtr<nux::BaseTexture> _normal_dash_tex;
00306   nux::ObjectPtr<nux::BaseTexture> _prelight_dash_tex;
00307   nux::ObjectPtr<nux::BaseTexture> _pressed_dash_tex;
00308   nux::ObjectPtr<nux::BaseTexture> _disabled_dash_tex;
00309 
00310   nux::BaseTexture* GetDashWindowButton(panel::WindowButtonType type,
00311                                         panel::WindowState state)
00312   {
00313     nux::BaseTexture* texture = nullptr;
00314     const char* names[] = { "close_dash", "minimize_dash", "unmaximize_dash", "maximize_dash" };
00315     const char* states[] = { "", "_prelight", "_pressed", "_disabled" };
00316 
00317     std::ostringstream subpath;
00318     subpath << names[static_cast<int>(type)]
00319             << states[static_cast<int>(state)] << ".png";
00320 
00321     glib::String filename(g_build_filename(PKGDATADIR, subpath.str().c_str(), NULL));
00322 
00323     glib::Error error;
00324     glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_file(filename, &error));
00325 
00326     if (pixbuf && !error)
00327       texture = nux::CreateTexture2DFromPixbuf(pixbuf, true);
00328 
00329     if (!texture)
00330       texture = panel::Style::Instance().GetFallbackWindowButton(type, state);
00331 
00332     return texture;
00333   }
00334 };
00335 
00336 
00337 WindowButtons::WindowButtons()
00338   : HLayout("", NUX_TRACKER_LOCATION)
00339   , monitor_(0)
00340   , opacity_(1.0f)
00341   , focused_(true)
00342   , window_xid_(0)
00343 {
00344   WindowButton* but;
00345 
00346   auto lambda_enter = [&](int x, int y, unsigned long button_flags, unsigned long key_flags)
00347   {
00348     mouse_enter.emit(x, y, button_flags, key_flags);
00349   };
00350 
00351   auto lambda_leave = [&](int x, int y, unsigned long button_flags, unsigned long key_flags)
00352   {
00353     mouse_leave.emit(x, y, button_flags, key_flags);
00354   };
00355 
00356   auto lambda_moved = [&](int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
00357   {
00358     mouse_move.emit(x, y, dx, dy, button_flags, key_flags);
00359   };
00360 
00361   but = new WindowButton(panel::WindowButtonType::CLOSE);
00362   AddView(but, 0, nux::eCenter, nux::eFix);
00363   AddChild(but);
00364   but->click.connect(sigc::mem_fun(this, &WindowButtons::OnCloseClicked));
00365   but->mouse_enter.connect(lambda_enter);
00366   but->mouse_leave.connect(lambda_leave);
00367   but->mouse_move.connect(lambda_moved);
00368 
00369   but = new WindowButton(panel::WindowButtonType::MINIMIZE);
00370   AddView(but, 0, nux::eCenter, nux::eFix);
00371   AddChild(but);
00372   but->click.connect(sigc::mem_fun(this, &WindowButtons::OnMinimizeClicked));
00373   but->mouse_enter.connect(lambda_enter);
00374   but->mouse_leave.connect(lambda_leave);
00375   but->mouse_move.connect(lambda_moved);
00376 
00377   but = new WindowButton(panel::WindowButtonType::UNMAXIMIZE);
00378   AddView(but, 0, nux::eCenter, nux::eFix);
00379   AddChild(but);
00380   but->click.connect(sigc::mem_fun(this, &WindowButtons::OnRestoreClicked));
00381   but->mouse_enter.connect(lambda_enter);
00382   but->mouse_leave.connect(lambda_leave);
00383   but->mouse_move.connect(lambda_moved);
00384 
00385   but = new WindowButton(panel::WindowButtonType::MAXIMIZE);
00386   AddView(but, 0, nux::eCenter, nux::eFix);
00387   AddChild(but);
00388   but->click.connect(sigc::mem_fun(this, &WindowButtons::OnMaximizeClicked));
00389   but->mouse_enter.connect(lambda_enter);
00390   but->mouse_leave.connect(lambda_leave);
00391   but->mouse_move.connect(lambda_moved);
00392   but->SetVisible(false);
00393 
00394   SetContentDistribution(nux::eStackLeft);
00395 
00396   ubus_manager_.RegisterInterest(UBUS_OVERLAY_SHOWN, sigc::mem_fun(this, &WindowButtons::OnOverlayShown));
00397   ubus_manager_.RegisterInterest(UBUS_OVERLAY_HIDDEN, sigc::mem_fun(this, &WindowButtons::OnOverlayHidden));
00398   Settings::Instance().changed.connect(sigc::mem_fun(this, &WindowButtons::OnDashSettingsUpdated));
00399 }
00400 
00401 nux::Area* WindowButtons::FindAreaUnderMouse(const nux::Point& mouse, nux::NuxEventType event_type)
00402 {
00403   /* The first button should be clickable on the left space too, to
00404    * make Fitts happy. All also on their top side. See bug #839690 */
00405   bool first_found = false;
00406 
00407   for (auto area : GetChildren())
00408   {
00409     if (area->IsVisible() && area->GetInputEventSensitivity())
00410     {
00411       nux::Geometry const& geo = area->GetAbsoluteGeometry();
00412 
00413       if (!first_found)
00414       {
00415         first_found = true;
00416 
00417         if (mouse.x < geo.x && mouse.y < (geo.y + geo.height))
00418           return area;
00419       }
00420 
00421       if (geo.IsPointInside(mouse.x, mouse.y))
00422         return area;
00423 
00424       if (mouse.x >= geo.x && mouse.x <= (geo.x + geo.width) && mouse.y <= geo.y)
00425         return area;
00426     }
00427   }
00428 
00429   return nullptr;
00430 }
00431 
00432 void WindowButtons::OnCloseClicked(nux::Button *button)
00433 {
00434   auto win_button = dynamic_cast<WindowButton*>(button);
00435 
00436   if (!win_button || !win_button->IsEnabled())
00437     return;
00438 
00439   if (win_button->IsOverlayOpen())
00440   {
00441     ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
00442   }
00443   else
00444   {
00445     WindowManager::Default()->Close(window_xid_);
00446   }
00447 
00448   close_clicked.emit();
00449 }
00450 
00451 void WindowButtons::OnMinimizeClicked(nux::Button *button)
00452 {
00453   auto win_button = dynamic_cast<WindowButton*>(button);
00454 
00455   if (!win_button || !win_button->IsEnabled())
00456     return;
00457 
00458   if (!win_button->IsOverlayOpen())
00459     WindowManager::Default()->Minimize(window_xid_);
00460 
00461   minimize_clicked.emit();
00462 }
00463 
00464 void WindowButtons::OnRestoreClicked(nux::Button *button)
00465 {
00466   auto win_button = dynamic_cast<WindowButton*>(button);
00467 
00468   if (!win_button || !win_button->IsEnabled())
00469     return;
00470 
00471   if (win_button->IsOverlayOpen())
00472   {
00473     Settings::Instance().SetFormFactor(FormFactor::DESKTOP);
00474   }
00475   else
00476   {
00477     WindowManager* wm = WindowManager::Default();
00478     Window to_restore = window_xid_;
00479 
00480     wm->Raise(to_restore);
00481     wm->Activate(to_restore);
00482     wm->Restore(to_restore);
00483   }
00484 
00485   restore_clicked.emit();
00486 }
00487 
00488 void WindowButtons::OnMaximizeClicked(nux::Button *button)
00489 {
00490   auto win_button = dynamic_cast<WindowButton*>(button);
00491 
00492   if (!win_button || !win_button->IsEnabled())
00493     return;
00494 
00495   if (win_button->IsOverlayOpen())
00496   {
00497     Settings::Instance().SetFormFactor(FormFactor::NETBOOK);
00498   }
00499 
00500   maximize_clicked.emit();
00501 }
00502 
00503 void WindowButtons::OnOverlayShown(GVariant* data)
00504 {
00505   WindowButton* maximize_button = nullptr;
00506   WindowButton* restore_button = nullptr;
00507   glib::String overlay_identity;
00508   gboolean can_maximise = FALSE;
00509   gint32 overlay_monitor = 0;
00510   g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
00511                 &overlay_identity, &can_maximise, &overlay_monitor);
00512 
00513   if (overlay_monitor != monitor_)
00514   {
00515     for (auto area : GetChildren())
00516     {
00517       auto button = dynamic_cast<WindowButton*>(area);
00518 
00519       if (button)
00520         button->SetEnabled(false);
00521     }
00522 
00523     return;
00524   }
00525 
00526   active_overlay_ = overlay_identity.Str();
00527 
00528   for (auto area : GetChildren())
00529   {
00530     auto button = dynamic_cast<WindowButton*>(area);
00531 
00532     if (button)
00533     {
00534       if (button->GetType() == panel::WindowButtonType::CLOSE)
00535         button->SetEnabled(true);
00536 
00537       if (button->GetType() == panel::WindowButtonType::UNMAXIMIZE)
00538         restore_button = button;
00539 
00540       if (button->GetType() == panel::WindowButtonType::MAXIMIZE)
00541         maximize_button = button;
00542 
00543       if (button->GetType() == panel::WindowButtonType::MINIMIZE)
00544         button->SetEnabled(false);
00545 
00546       button->SetOverlayOpen(true);
00547     }
00548   }
00549 
00550   if (restore_button && maximize_button)
00551   {
00552     Settings &dash_settings = Settings::Instance();
00553     bool maximizable = (dash_settings.GetFormFactor() == FormFactor::DESKTOP);
00554 
00555     restore_button->SetEnabled(can_maximise);
00556     maximize_button->SetEnabled(can_maximise);
00557 
00558     if (maximizable != maximize_button->IsVisible())
00559     {
00560       if (maximize_button->IsVisible())
00561         restore_button->SetVisualState(maximize_button->GetVisualState());
00562       else if (restore_button->IsVisible())
00563         maximize_button->SetVisualState(restore_button->GetVisualState());
00564 
00565       restore_button->SetVisible(!maximizable);
00566       maximize_button->SetVisible(maximizable);
00567 
00568       QueueDraw();
00569     }
00570   }
00571 }
00572 
00573 void WindowButtons::OnOverlayHidden(GVariant* data)
00574 {
00575   WindowButton* maximize_button = nullptr;
00576   WindowButton* restore_button = nullptr;
00577 
00578   glib::String overlay_identity;
00579   gboolean can_maximise = FALSE;
00580   gint32 overlay_monitor = 0;
00581   g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
00582                 &overlay_identity, &can_maximise, &overlay_monitor);
00583 
00584   if (overlay_monitor != monitor_)
00585   {
00586     for (auto area : GetChildren())
00587     {
00588       auto button = dynamic_cast<WindowButton*>(area);
00589 
00590       if (button)
00591         button->SetEnabled(true);
00592     }
00593   }
00594 
00595   if (active_overlay_ != overlay_identity.Str())
00596     return;
00597 
00598   active_overlay_ = "";
00599 
00600   for (auto area : GetChildren())
00601   {
00602     auto button = dynamic_cast<WindowButton*>(area);
00603 
00604     if (button)
00605     {
00606       if (window_xid_)
00607       {
00608         if (button->GetType() == panel::WindowButtonType::CLOSE)
00609         {
00610           bool closable = WindowManager::Default()->IsWindowClosable(window_xid_);
00611           button->SetEnabled(closable);
00612         }
00613 
00614         if (button->GetType() == panel::WindowButtonType::MINIMIZE)
00615         {
00616           bool minimizable = WindowManager::Default()->IsWindowMinimizable(window_xid_);
00617           button->SetEnabled(minimizable);
00618         }
00619       }
00620 
00621       if (button->GetType() == panel::WindowButtonType::UNMAXIMIZE)
00622         restore_button = button;
00623 
00624       if (button->GetType() == panel::WindowButtonType::MAXIMIZE)
00625         maximize_button = button;
00626 
00627       button->SetOverlayOpen(false);
00628     }
00629   }
00630 
00631   if (restore_button && maximize_button)
00632   {
00633     restore_button->SetEnabled(true);
00634     maximize_button->SetEnabled(true);
00635 
00636     if (!restore_button->IsVisible())
00637     {
00638       restore_button->SetVisualState(maximize_button->GetVisualState());
00639 
00640       restore_button->SetVisible(true);
00641       maximize_button->SetVisible(false);
00642 
00643       QueueDraw();
00644     }
00645   }
00646 }
00647 
00648 void WindowButtons::OnDashSettingsUpdated()
00649 {
00650   WindowButton* maximize_button = nullptr;
00651   WindowButton* restore_button = nullptr;
00652 
00653   for (auto area : GetChildren())
00654   {
00655     auto button = dynamic_cast<WindowButton*>(area);
00656 
00657     if (button)
00658     {
00659       if (!button->IsOverlayOpen())
00660         break;
00661 
00662       if (button->GetType() == panel::WindowButtonType::UNMAXIMIZE)
00663         restore_button = button;
00664 
00665       if (button->GetType() == panel::WindowButtonType::MAXIMIZE)
00666         maximize_button = button;
00667 
00668       if (restore_button && maximize_button)
00669         break;
00670     }
00671   }
00672 
00673   if (restore_button && restore_button->IsOverlayOpen() && maximize_button)
00674   {
00675     Settings &dash_settings = Settings::Instance();
00676     bool maximizable = (dash_settings.GetFormFactor() == FormFactor::DESKTOP);
00677 
00678     if (maximizable != maximize_button->IsVisible())
00679     {
00680       if (maximize_button->IsVisible())
00681         restore_button->SetVisualState(maximize_button->GetVisualState());
00682       else if (restore_button->IsVisible())
00683         maximize_button->SetVisualState(restore_button->GetVisualState());
00684 
00685       restore_button->SetVisible(!maximizable);
00686       maximize_button->SetVisible(maximizable);
00687 
00688       QueueRelayout();
00689     }
00690   }
00691 }
00692 
00693 void WindowButtons::SetOpacity(double opacity)
00694 {
00695   opacity = CLAMP(opacity, 0.0f, 1.0f);
00696 
00697   for (auto area : GetChildren())
00698   {
00699     auto button = dynamic_cast<WindowButton*>(area);
00700 
00701     if (button)
00702       button->SetOpacity(opacity);
00703   }
00704 
00705   if (opacity_ != opacity)
00706   {
00707     opacity_ = opacity;
00708     SetInputEventSensitivity(opacity_ != 0.0f);
00709     QueueDraw();
00710   }
00711 }
00712 
00713 double WindowButtons::GetOpacity()
00714 {
00715   return opacity_;
00716 }
00717 
00718 void WindowButtons::SetFocusedState(bool focused)
00719 {
00720   for (auto area : GetChildren())
00721   {
00722     auto button = dynamic_cast<WindowButton*>(area);
00723 
00724     if (button)
00725       button->SetFocusedState(focused);
00726   }
00727 
00728   if (focused_ != focused)
00729   {
00730     focused_ = focused;
00731     QueueDraw();
00732   }
00733 }
00734 
00735 bool WindowButtons::GetFocusedState()
00736 {
00737   return focused_;
00738 }
00739 
00740 void WindowButtons::SetControlledWindow(Window xid)
00741 {
00742   if (xid != window_xid_)
00743   {
00744     window_xid_ = xid;
00745 
00746     if (window_xid_ && active_overlay_.empty())
00747     {
00748       for (auto area : GetChildren())
00749       {
00750         auto button = dynamic_cast<WindowButton*>(area);
00751 
00752         if (!button)
00753           continue;
00754 
00755         if (button->GetType() == panel::WindowButtonType::CLOSE)
00756         {
00757           bool closable = WindowManager::Default()->IsWindowClosable(xid);
00758           button->SetEnabled(closable);
00759         }
00760 
00761         if (button->GetType() == panel::WindowButtonType::MINIMIZE)
00762         {
00763           bool minimizable = WindowManager::Default()->IsWindowMinimizable(xid);
00764           button->SetEnabled(minimizable);
00765         }
00766       }
00767     }
00768   }
00769 }
00770 
00771 Window WindowButtons::GetControlledWindow()
00772 {
00773   return window_xid_;
00774 }
00775 
00776 void WindowButtons::SetMonitor(int monitor)
00777 {
00778   monitor_ = monitor;
00779 }
00780 
00781 int WindowButtons::GetMonitor()
00782 {
00783   return monitor_;
00784 }
00785 
00786 std::string WindowButtons::GetName() const
00787 {
00788   return "WindowButtons";
00789 }
00790 
00791 void WindowButtons::AddProperties(GVariantBuilder* builder)
00792 {
00793   variant::BuilderWrapper(builder).add(GetAbsoluteGeometry())
00794                                   .add("monitor", monitor_)
00795                                   .add("opacity", opacity_)
00796                                   .add("visible", opacity_ != 0.0f)
00797                                   .add("sensitive", GetInputEventSensitivity())
00798                                   .add("focused", focused_)
00799                                   .add("controlled_window", window_xid_);
00800 }
00801 
00802 } // unity namespace