// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* * Copyright (C) 2013 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 . * * Authored by: Marco Trevisan (TreviƱo) */ #include "SessionController.h" #include "unity-shared/AnimationUtils.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/UBusWrapper.h" #include "unity-shared/UnitySettings.h" #include "unity-shared/UScreen.h" #include "unity-shared/WindowManager.h" namespace na = nux::animation; namespace unity { namespace session { namespace { const unsigned int FADE_DURATION = 100; } Controller::Controller(session::Manager::Ptr const& manager) : manager_(manager) , fade_animator_(Settings::Instance().low_gfx() ? 0 : FADE_DURATION) { manager_->reboot_requested.connect([this] (bool inhibitors) { Show(View::Mode::SHUTDOWN, inhibitors); }); manager_->shutdown_requested.connect([this] (bool inhibitors) { Show(View::Mode::FULL, inhibitors); }); manager_->logout_requested.connect([this] (bool inhibitors) { Show(View::Mode::LOGOUT, inhibitors); }); manager_->cancel_requested.connect(sigc::mem_fun(this, &Controller::Hide)); WindowManager::Default().average_color.changed.connect(sigc::mem_fun(this, &Controller::OnBackgroundUpdate)); fade_animator_.updated.connect([this] (double opacity) { view_window_->SetOpacity(opacity); }); fade_animator_.finished.connect([this] { if (animation::GetDirection(fade_animator_) == animation::Direction::BACKWARD) CloseWindow(); }); Settings::Instance().low_gfx.changed.connect(sigc::track_obj([this] (bool low_gfx) { fade_animator_.SetDuration(low_gfx ? 0 : FADE_DURATION); }, *this)); } void Controller::OnBackgroundUpdate(nux::Color const& new_color) { if (view_) view_->background_color = new_color; } void Controller::Show(View::Mode mode) { Show(mode, false); } void Controller::LockScreen() const { manager_->LockScreen(); } void Controller::Show(View::Mode mode, bool inhibitors) { EnsureView(); if (Visible() && mode == view_->mode()) return; UBusManager().SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); WindowManager::Default().SaveInputFocus(); if (nux::GetWindowThread()->IsEmbeddedWindow()) { view_window_->EnableInputWindow(true, view_window_->GetWindowName().c_str(), true, false); view_window_->GrabPointer(); view_window_->GrabKeyboard(); } view_->mode = mode; view_->have_inhibitors = inhibitors; view_->live_background = true; view_window_->ShowWindow(true); view_window_->SetInputFocus(); nux::GetWindowCompositor().SetAlwaysOnFrontWindow(view_window_.GetPointer()); nux::GetWindowCompositor().SetKeyFocusArea(view_->key_focus_area()); animation::StartOrReverse(fade_animator_, animation::Direction::FORWARD); } nux::Point Controller::GetOffsetPerMonitor(int monitor) { EnsureView(); auto const& view_geo = view_->GetGeometry(); auto const& monitor_geo = UScreen::GetDefault()->GetMonitorGeometry(monitor); nux::Point offset(adjustment_.x + monitor_geo.x, adjustment_.y + monitor_geo.y); offset.x += (monitor_geo.width - view_geo.width - adjustment_.x) / 2; offset.y += (monitor_geo.height - view_geo.height - adjustment_.y) / 2; return offset; } void Controller::ConstructView() { view_ = View::Ptr(new View(manager_)); view_->background_color = WindowManager::Default().average_color(); debug::Introspectable::AddChild(view_.GetPointer()); auto layout = new nux::HLayout(NUX_TRACKER_LOCATION); layout->SetVerticalExternalMargin(0); layout->SetHorizontalExternalMargin(0); layout->AddView(view_.GetPointer()); view_window_ = new nux::BaseWindow("SessionManager"); view_window_->SetLayout(layout); view_window_->SetBackgroundColor(nux::color::Transparent); view_window_->SetWindowSizeMatchLayout(true); view_window_->ShowWindow(false); view_window_->SetOpacity(0.0f); view_window_->SetEnterFocusInputArea(view_.GetPointer()); view_window_->mouse_down_outside_pointer_grab_area.connect([this] (int, int, unsigned long, unsigned long) { CancelAndHide(); }); view_->request_hide.connect(sigc::mem_fun(this, &Controller::Hide)); view_->request_close.connect(sigc::mem_fun(this, &Controller::CancelAndHide)); if (nux::GetWindowThread()->IsEmbeddedWindow()) { view_->size_changed.connect([this] (nux::Area*, int, int) { int monitor = UScreen::GetDefault()->GetMonitorWithMouse(); view_->monitor = monitor; auto const& offset = GetOffsetPerMonitor(monitor); view_window_->SetXY(offset.x, offset.y); }); } else { view_window_->SetXY(0, 0); } } void Controller::EnsureView() { if (!view_window_) ConstructView(); } void Controller::CancelAndHide() { manager_->CancelAction(); Hide(); } void Controller::Hide() { if (view_window_) { view_window_->UnGrabPointer(); view_window_->UnGrabKeyboard(); animation::StartOrReverse(fade_animator_, animation::Direction::BACKWARD); } } void Controller::CloseWindow() { view_window_->ShowWindow(false); view_window_->EnableInputWindow(false); view_ = nullptr; view_window_ = nullptr; nux::GetWindowCompositor().SetKeyFocusArea(nullptr); WindowManager::Default().RestoreInputFocus(); } bool Controller::Visible() const { return (view_window_ && view_window_->IsVisible()); } // // Introspection // std::string Controller::GetName() const { return "SessionController"; } void Controller::AddProperties(debug::IntrospectionData& introspection) { introspection .add("visible", Visible()); } } // namespace session } // namespace unity