Back to index

unity  6.0.0
EdgeBarrierController.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 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: Jason Smith <jason.smith@canonical.com>
00018  */
00019 
00020 #include "EdgeBarrierController.h"
00021 #include "Decaymulator.h"
00022 #include "unity-shared/UScreen.h"
00023 
00024 namespace unity {
00025 namespace ui {
00026 
00027 struct EdgeBarrierController::Impl
00028 {
00029   Impl(EdgeBarrierController *parent);
00030   ~Impl();
00031 
00032   void ResizeBarrierList(std::vector<nux::Geometry> const& layout);
00033   void SetupBarriers(std::vector<nux::Geometry> const& layout);
00034 
00035   void OnPointerBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event);
00036 
00037   std::vector<PointerBarrierWrapper::Ptr> barriers_;
00038   Decaymulator::Ptr decaymulator_;
00039   float edge_overcome_pressure_;
00040   EdgeBarrierController* parent_;
00041   std::vector<EdgeBarrierSubscriber*> subscribers_;
00042 };
00043 
00044 EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent)
00045   : decaymulator_(Decaymulator::Ptr(new Decaymulator()))
00046   , edge_overcome_pressure_(0)
00047   , parent_(parent)
00048 {
00049   UScreen *uscreen = UScreen::GetDefault();
00050 
00051   auto monitors = uscreen->GetMonitors();
00052   ResizeBarrierList(monitors);
00053 
00054   uscreen->changed.connect([&](int primary, std::vector<nux::Geometry>& layout) {
00055     ResizeBarrierList(layout);
00056     SetupBarriers(layout);
00057   });
00058 
00059   parent_->sticky_edges.changed.connect([&](bool value) {
00060     SetupBarriers(UScreen::GetDefault()->GetMonitors());
00061   });
00062 
00063   parent_->options.changed.connect([&](launcher::Options::Ptr options) {
00064     options->option_changed.connect([&]() {
00065       SetupBarriers(UScreen::GetDefault()->GetMonitors());
00066     });
00067     SetupBarriers(UScreen::GetDefault()->GetMonitors());
00068   });
00069 }
00070 
00071 EdgeBarrierController::Impl::~Impl()
00072 {
00073 
00074 }
00075 
00076 void EdgeBarrierController::Impl::ResizeBarrierList(std::vector<nux::Geometry> const& layout)
00077 {
00078   size_t num_monitors = layout.size();
00079   if (barriers_.size() > num_monitors)
00080   {
00081     barriers_.resize(num_monitors);
00082   }
00083 
00084   while (barriers_.size() < num_monitors)
00085   {
00086     auto barrier = PointerBarrierWrapper::Ptr(new PointerBarrierWrapper());
00087     barrier->barrier_event.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnPointerBarrierEvent));
00088     barriers_.push_back(barrier);
00089   }
00090 }
00091 
00092 void EdgeBarrierController::Impl::SetupBarriers(std::vector<nux::Geometry> const& layout)
00093 {
00094   bool edge_resist = parent_->options()->edge_resist();
00095 
00096   size_t size = layout.size();
00097   for (size_t i = 0; i < size; i++)
00098   {
00099     auto barrier = barriers_[i];
00100     auto monitor = layout[i];
00101 
00102     barrier->DestroyBarrier();
00103 
00104     if (!edge_resist && (subscribers_[i] == nullptr || parent_->options()->hide_mode() == launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER))
00105       continue;
00106 
00107     barrier->x1 = monitor.x;
00108     barrier->x2 = monitor.x;
00109     barrier->y1 = monitor.y;
00110     barrier->y2 = monitor.y + monitor.height;
00111     barrier->index = i;
00112 
00113     barrier->threshold = parent_->options()->edge_stop_velocity();
00114     barrier->max_velocity_multiplier = parent_->options()->edge_responsiveness();
00115 
00116     if (edge_resist)
00117       barrier->direction = BarrierDirection::BOTH;
00118     else
00119       barrier->direction = BarrierDirection::LEFT;
00120 
00121     barrier->ConstructBarrier();
00122   }
00123 
00124   float decay_responsiveness_mult = ((parent_->options()->edge_responsiveness() - 1) * .3f) + 1;
00125   decaymulator_->rate_of_decay = parent_->options()->edge_decay_rate() * decay_responsiveness_mult;
00126   
00127   float overcome_responsiveness_mult = ((parent_->options()->edge_responsiveness() - 1) * 1.0f) + 1;
00128   edge_overcome_pressure_ = parent_->options()->edge_overcome_pressure() * overcome_responsiveness_mult;
00129 }
00130 
00131 void EdgeBarrierController::Impl::OnPointerBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event)
00132 {
00133   int monitor = owner->index;
00134   bool process = true;
00135 
00136   if ((size_t)monitor <= subscribers_.size())
00137   {
00138     auto subscriber = subscribers_[monitor];
00139     if (subscriber && subscriber->HandleBarrierEvent(owner, event))
00140       process = false;
00141   }
00142 
00143   if (process && owner->x1 > 0)
00144   {
00145     decaymulator_->value = decaymulator_->value + event->velocity;
00146     if (decaymulator_->value > edge_overcome_pressure_ || !parent_->options()->edge_resist())
00147     {
00148       owner->ReleaseBarrier(event->event_id);
00149       decaymulator_->value = 0;
00150     }
00151   }
00152   else
00153   {
00154     decaymulator_->value = 0;
00155   }
00156 }
00157 
00158 EdgeBarrierController::EdgeBarrierController()
00159   : sticky_edges(false)
00160   , pimpl(new Impl(this))
00161 {
00162 }
00163 
00164 EdgeBarrierController::~EdgeBarrierController()
00165 {
00166 
00167 }
00168 
00169 void EdgeBarrierController::Subscribe(EdgeBarrierSubscriber* subscriber, int monitor)
00170 {
00171   if (pimpl->subscribers_.size() <= (size_t)monitor)
00172     pimpl->subscribers_.resize(monitor + 1);
00173   pimpl->subscribers_[monitor] = subscriber;
00174 
00175   pimpl->SetupBarriers(UScreen::GetDefault()->GetMonitors());
00176 }
00177 
00178 void EdgeBarrierController::Unsubscribe(EdgeBarrierSubscriber* subscriber, int monitor)
00179 {
00180   if (pimpl->subscribers_.size() < (size_t)monitor || pimpl->subscribers_[monitor] != subscriber)
00181     return;
00182   pimpl->subscribers_[monitor] = nullptr;
00183 
00184   pimpl->SetupBarriers(UScreen::GetDefault()->GetMonitors());
00185 }
00186 
00187 
00188 }
00189 }