1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
3
* Copyright (C) 2010-2012 Canonical Ltd
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 3 as
7
* published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
20
#include "DashController.h"
22
#include <NuxCore/Logger.h>
23
#include <Nux/HLayout.h>
24
#include <UnityCore/GLibWrapper.h>
26
#include "ApplicationStarterImp.h"
27
#include "unity-shared/DashStyle.h"
28
#include "unity-shared/PanelStyle.h"
29
#include "unity-shared/UBusMessages.h"
30
#include "unity-shared/UnitySettings.h"
31
#include "unity-shared/UScreen.h"
32
#include "unity-shared/WindowManager.h"
39
DECLARE_LOGGER(logger, "unity.dash.controller");
41
const char* window_title = "unity-dash";
45
const unsigned int PRELOAD_TIMEOUT_LENGTH = 40;
49
const std::string PATH = "/com/canonical/Unity/Dash";
50
const std::string INTROSPECTION =\
52
" <interface name='com.canonical.Unity.Dash'>"
54
" <method name='HideDash'>"
62
Controller::Controller(Controller::WindowCreator const& create_window)
65
, create_window_(create_window)
70
, ensure_timeout_(PRELOAD_TIMEOUT_LENGTH)
71
, timeline_animator_(90)
73
RegisterUBusInterests();
75
ensure_timeout_.Run([&]() { EnsureDash(); return false; });
76
timeline_animator_.updated.connect(sigc::mem_fun(this, &Controller::OnViewShowHideFrame));
78
// As a default. the create_window_ function should just create a base window.
79
if (create_window_ == nullptr)
81
create_window_ = [&]() {
82
return new ResizingBaseWindow(dash::window_title,
83
[this](nux::Geometry const& geo) {
85
return GetInputWindowGeometry();
92
UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(true); });
94
Settings::Instance().form_factor.changed.connect([this](FormFactor)
96
if (window_ && view_ && visible_)
98
// Relayout here so the input window size updates.
101
window_->PushToFront();
102
window_->SetInputFocus();
103
nux::GetWindowCompositor().SetKeyFocusArea(view_->default_focus());
107
auto spread_cb = sigc::bind(sigc::mem_fun(this, &Controller::HideDash), true);
108
WindowManager::Default().initiate_spread.connect(spread_cb);
110
dbus_server_.AddObjects(dbus::INTROSPECTION, dbus::PATH);
111
dbus_server_.GetObjects().front()->SetMethodsCallsHandler([this] (std::string const& method, GVariant*) {
112
if (method == "HideDash")
115
return static_cast<GVariant*>(nullptr);
119
void Controller::SetupWindow()
121
window_ = create_window_();
122
window_->SetBackgroundColor(nux::Color(0.0f, 0.0f, 0.0f, 0.0f));
123
window_->SetConfigureNotifyCallback(&Controller::OnWindowConfigure, this);
124
window_->ShowWindow(false);
125
window_->SetOpacity(0.0f);
126
window_->mouse_down_outside_pointer_grab_area.connect(sigc::mem_fun(this, &Controller::OnMouseDownOutsideWindow));
128
if (nux::GetWindowThread()->IsEmbeddedWindow())
130
/* FIXME - first time we load our windows there is a race that causes the input
131
* window not to actually get input, this side steps that by causing an input window
132
* show and hide before we really need it. */
133
WindowManager& wm = WindowManager::Default();
135
window_->EnableInputWindow(true, dash::window_title, true, false);
136
window_->EnableInputWindow(false, dash::window_title, true, false);
137
wm.RestoreInputFocus();
141
void Controller::SetupDashView()
143
view_ = new DashView(std::make_shared<FilesystemLenses>(), std::make_shared<ApplicationStarterImp>());
146
nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
147
layout->AddView(view_, 1);
148
layout->SetContentDistribution(nux::MAJOR_POSITION_START);
149
layout->SetVerticalExternalMargin(0);
150
layout->SetHorizontalExternalMargin(0);
151
window_->SetLayout(layout);
153
window_->UpdateInputWindowGeometry();
156
void Controller::RegisterUBusInterests()
158
ubus_manager_.RegisterInterest(UBUS_DASH_EXTERNAL_ACTIVATION,
159
sigc::mem_fun(this, &Controller::OnExternalShowDash));
160
ubus_manager_.RegisterInterest(UBUS_OVERLAY_CLOSE_REQUEST,
161
sigc::mem_fun(this, &Controller::OnExternalHideDash));
162
ubus_manager_.RegisterInterest(UBUS_DASH_ABOUT_TO_SHOW,
163
[&] (GVariant*) { EnsureDash(); });
164
ubus_manager_.RegisterInterest(UBUS_OVERLAY_SHOWN, [&] (GVariant *data)
166
unity::glib::String overlay_identity;
167
gboolean can_maximise = FALSE;
168
gint32 overlay_monitor = 0;
171
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING, &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
173
// hide if something else is coming up
174
if (overlay_identity.Str() != "dash")
182
void Controller::EnsureDash()
184
LOG_DEBUG(logger) << "Initializing Dash";
192
ensure_timeout_.Remove();
198
nux::BaseWindow* Controller::window() const
200
return window_.GetPointer();
203
// We update the @geo that's sent in with our desired width and height
204
void Controller::OnWindowConfigure(int window_width, int window_height,
205
nux::Geometry& geo, void* data)
207
Controller* self = static_cast<Controller*>(data);
208
geo = self->GetIdealWindowGeometry();
211
int Controller::GetIdealMonitor()
213
UScreen *uscreen = UScreen::GetDefault();
215
if (window_->IsVisible())
216
primary_monitor = monitor_;
217
else if (use_primary)
218
primary_monitor = uscreen->GetPrimaryMonitor();
220
primary_monitor = uscreen->GetMonitorWithMouse();
222
return primary_monitor;
225
nux::Geometry Controller::GetIdealWindowGeometry()
227
UScreen *uscreen = UScreen::GetDefault();
228
auto monitor_geo = uscreen->GetMonitorGeometry(GetIdealMonitor());
230
// We want to cover as much of the screen as possible to grab any mouse events outside
232
return nux::Geometry (monitor_geo.x + launcher_width,
234
monitor_geo.width - launcher_width,
238
void Controller::Relayout(bool check_monitor)
244
monitor_ = CLAMP(GetIdealMonitor(), 0, static_cast<int>(UScreen::GetDefault()->GetMonitors().size()-1));
247
nux::Geometry geo = GetIdealWindowGeometry();
249
window_->SetGeometry(geo);
250
panel::Style &panel_style = panel::Style::Instance();
251
view_->SetMonitorOffset(launcher_width, panel_style.panel_height);
254
void Controller::OnMouseDownOutsideWindow(int x, int y,
255
unsigned long bflags, unsigned long kflags)
260
void Controller::OnScreenUngrabbed()
262
LOG_DEBUG(logger) << "On Screen Ungrabbed called";
270
void Controller::OnExternalShowDash(GVariant* variant)
273
visible_ ? HideDash() : ShowDash();
276
void Controller::OnExternalHideDash(GVariant* variant)
282
HideDash(g_variant_get_boolean(variant));
290
void Controller::ShowDash()
293
WindowManager& wm = WindowManager::Default();
294
// Don't want to show at the wrong time
295
if (visible_ || wm.IsExpoActive() || wm.IsScaleActive())
298
// We often need to wait for the mouse/keyboard to be available while a plugin
299
// is finishing it's animations/cleaning up. In these cases, we patiently wait
300
// for the screen to be available again before honouring the request.
301
if (wm.IsScreenGrabbed())
303
screen_ungrabbed_slot_.disconnect();
304
screen_ungrabbed_slot_ = wm.screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
309
monitor_ = GetIdealMonitor();
311
view_->AboutToShow();
318
StartShowHideTimeline();
320
nux::Geometry const& view_content_geo = view_->GetContentGeometry();
322
GVariant* info = g_variant_new(UBUS_OVERLAY_FORMAT_STRING, "dash", TRUE, monitor_, view_content_geo.width, view_content_geo.height);
323
ubus_manager_.SendMessage(UBUS_OVERLAY_SHOWN, info);
326
void Controller::FocusWindow()
328
window_->ShowWindow(true);
329
window_->PushToFront();
330
if (nux::GetWindowThread()->IsEmbeddedWindow())
332
// in standalone (i.e. not embedded) mode, we do not need an input window. we are one.
333
window_->EnableInputWindow(true, dash::window_title, true, false);
334
// update the input window geometry. This causes the input window to match the actual size of the dash.
335
window_->UpdateInputWindowGeometry();
337
window_->SetInputFocus();
338
window_->QueueDraw();
340
nux::GetWindowCompositor().SetKeyFocusArea(view_->default_focus());
343
void Controller::QuicklyHideDash(bool restore)
346
timeline_animator_.Stop();
347
window_->ShowWindow(false);
350
void Controller::HideDash(bool restore)
355
screen_ungrabbed_slot_.disconnect();
359
view_->AboutToHide();
361
window_->CaptureMouseDownAnyWhereElse(false);
362
window_->EnableInputWindow(false, dash::window_title, true, false);
365
nux::GetWindowCompositor().SetKeyFocusArea(NULL,nux::KEY_NAV_NONE);
368
WindowManager::Default().RestoreInputFocus();
370
StartShowHideTimeline();
372
nux::Geometry const& view_content_geo = view_->GetContentGeometry();
374
GVariant* info = g_variant_new(UBUS_OVERLAY_FORMAT_STRING, "dash", TRUE, monitor_, view_content_geo.width, view_content_geo.height);
375
ubus_manager_.SendMessage(UBUS_OVERLAY_HIDDEN, info);
378
void Controller::StartShowHideTimeline()
382
if (timeline_animator_.CurrentState() == nux::animation::Animation::State::Running)
384
timeline_animator_.Reverse();
389
timeline_animator_.SetStartValue(0.0f).SetFinishValue(1.0f).Start();
391
timeline_animator_.SetStartValue(1.0f).SetFinishValue(0.0f).Start();
395
void Controller::OnViewShowHideFrame(double opacity)
397
window_->SetOpacity(opacity);
399
if (opacity == 0.0f && !visible_)
401
window_->ShowWindow(false);
405
void Controller::OnActivateRequest(GVariant* variant)
408
view_->OnActivateRequest(variant);
411
gboolean Controller::CheckShortcutActivation(const char* key_string)
414
std::string lens_id = view_->GetIdForShortcutActivation(std::string(key_string));
417
WindowManager& wm = WindowManager::Default();
418
if (wm.IsScaleActive())
421
GVariant* args = g_variant_new("(sus)", lens_id.c_str(), dash::GOTO_DASH_URI, "");
422
OnActivateRequest(args);
423
g_variant_unref(args);
429
std::vector<char> Controller::GetAllShortcuts()
432
return view_->GetAllShortcuts();
436
std::string Controller::GetName() const
438
return "DashController";
441
void Controller::AddProperties(GVariantBuilder* builder)
443
variant::BuilderWrapper(builder).add("visible", visible_)
444
.add("ideal_monitor", GetIdealMonitor())
445
.add("monitor", monitor_);
448
void Controller::ReFocusKeyInput()
452
window_->PushToFront();
453
window_->SetInputFocus();
457
bool Controller::IsVisible() const
462
bool Controller::IsCommandLensOpen() const
464
return visible_ && view_->IsCommandLensOpen();
467
nux::Geometry Controller::GetInputWindowGeometry()
470
dash::Style& style = dash::Style::Instance();
471
nux::Geometry const& window_geo(window_->GetGeometry());
472
nux::Geometry const& view_content_geo(view_->GetContentGeometry());
474
nux::Geometry geo(window_geo.x, window_geo.y, view_content_geo.width, view_content_geo.height);
475
geo.width += style.GetDashRightTileWidth();
476
geo.height += style.GetDashBottomTileHeight();