~3v1n0/unity/light-shortcuts

« back to all changes in this revision

Viewing changes to dash/DashController.cpp

  • Committer: Marco Trevisan (Treviño)
  • Date: 2013-04-26 12:41:09 UTC
  • Revision ID: mail@3v1n0.net-20130426124109-t3b2shjah2omiqa2
Unity: Remove all the views, but the Shortcuts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2
 
/*
3
 
 * Copyright (C) 2010-2012 Canonical Ltd
4
 
 *
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.
8
 
 *
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.
13
 
 *
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/>.
16
 
 *
17
 
 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
18
 
 */
19
 
 
20
 
#include "DashController.h"
21
 
 
22
 
#include <NuxCore/Logger.h>
23
 
#include <Nux/HLayout.h>
24
 
#include <UnityCore/GLibWrapper.h>
25
 
 
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"
33
 
 
34
 
 
35
 
namespace unity
36
 
{
37
 
namespace dash
38
 
{
39
 
DECLARE_LOGGER(logger, "unity.dash.controller");
40
 
 
41
 
const char* window_title = "unity-dash";
42
 
 
43
 
namespace
44
 
{
45
 
const unsigned int PRELOAD_TIMEOUT_LENGTH = 40;
46
 
 
47
 
namespace dbus
48
 
{
49
 
const std::string PATH = "/com/canonical/Unity/Dash";
50
 
const std::string INTROSPECTION =\
51
 
  "<node>"
52
 
  "  <interface name='com.canonical.Unity.Dash'>"
53
 
  ""
54
 
  "    <method name='HideDash'>"
55
 
  "    </method>"
56
 
  ""
57
 
  "  </interface>"
58
 
  "</node>";
59
 
}
60
 
}
61
 
 
62
 
Controller::Controller(Controller::WindowCreator const& create_window)
63
 
  : launcher_width(64)
64
 
  , use_primary(false)
65
 
  , create_window_(create_window)
66
 
  , monitor_(0)
67
 
  , visible_(false)
68
 
  , need_show_(false)
69
 
  , view_(nullptr)
70
 
  , ensure_timeout_(PRELOAD_TIMEOUT_LENGTH)
71
 
  , timeline_animator_(90)
72
 
{
73
 
  RegisterUBusInterests();
74
 
 
75
 
  ensure_timeout_.Run([&]() { EnsureDash(); return false; });
76
 
  timeline_animator_.updated.connect(sigc::mem_fun(this, &Controller::OnViewShowHideFrame));
77
 
 
78
 
  // As a default. the create_window_ function should just create a base window.
79
 
  if (create_window_ == nullptr)
80
 
  {
81
 
    create_window_ = [&]() {
82
 
      return new ResizingBaseWindow(dash::window_title,
83
 
                                    [this](nux::Geometry const& geo) {
84
 
                                      if (view_)
85
 
                                        return GetInputWindowGeometry();
86
 
                                      return geo;
87
 
                                    });
88
 
    };
89
 
  }
90
 
 
91
 
  SetupWindow();
92
 
  UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(true); });
93
 
 
94
 
  Settings::Instance().form_factor.changed.connect([this](FormFactor)
95
 
  {
96
 
    if (window_ && view_ && visible_)
97
 
    {
98
 
      // Relayout here so the input window size updates.
99
 
      Relayout();
100
 
 
101
 
      window_->PushToFront();
102
 
      window_->SetInputFocus();
103
 
      nux::GetWindowCompositor().SetKeyFocusArea(view_->default_focus());
104
 
    }
105
 
  });
106
 
 
107
 
  auto spread_cb = sigc::bind(sigc::mem_fun(this, &Controller::HideDash), true);
108
 
  WindowManager::Default().initiate_spread.connect(spread_cb);
109
 
 
110
 
  dbus_server_.AddObjects(dbus::INTROSPECTION, dbus::PATH);
111
 
  dbus_server_.GetObjects().front()->SetMethodsCallsHandler([this] (std::string const& method, GVariant*) {
112
 
    if (method == "HideDash")
113
 
      HideDash();
114
 
 
115
 
    return static_cast<GVariant*>(nullptr);
116
 
  });
117
 
}
118
 
 
119
 
void Controller::SetupWindow()
120
 
{
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));
127
 
 
128
 
  if (nux::GetWindowThread()->IsEmbeddedWindow())
129
 
  {
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();
134
 
    wm.SaveInputFocus();
135
 
    window_->EnableInputWindow(true, dash::window_title, true, false);
136
 
    window_->EnableInputWindow(false, dash::window_title, true, false);
137
 
    wm.RestoreInputFocus();
138
 
  }
139
 
}
140
 
 
141
 
void Controller::SetupDashView()
142
 
{
143
 
  view_ = new DashView(std::make_shared<FilesystemLenses>(), std::make_shared<ApplicationStarterImp>());
144
 
  AddChild(view_);
145
 
 
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);
152
 
 
153
 
  window_->UpdateInputWindowGeometry();
154
 
}
155
 
 
156
 
void Controller::RegisterUBusInterests()
157
 
{
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)
165
 
  {
166
 
    unity::glib::String overlay_identity;
167
 
    gboolean can_maximise = FALSE;
168
 
    gint32 overlay_monitor = 0;
169
 
    int width = 0;
170
 
    int height = 0;
171
 
    g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING, &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
172
 
 
173
 
    // hide if something else is coming up
174
 
    if (overlay_identity.Str() != "dash")
175
 
    {
176
 
      HideDash(true);
177
 
    }
178
 
  });
179
 
 
180
 
}
181
 
 
182
 
void Controller::EnsureDash()
183
 
{
184
 
  LOG_DEBUG(logger) << "Initializing Dash";
185
 
  if (!window_)
186
 
    SetupWindow();
187
 
 
188
 
  if (!view_)
189
 
  {
190
 
    SetupDashView();
191
 
    Relayout();
192
 
    ensure_timeout_.Remove();
193
 
 
194
 
    on_realize.emit();
195
 
  }
196
 
}
197
 
 
198
 
nux::BaseWindow* Controller::window() const
199
 
{
200
 
  return window_.GetPointer();
201
 
}
202
 
 
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)
206
 
{
207
 
  Controller* self = static_cast<Controller*>(data);
208
 
  geo = self->GetIdealWindowGeometry();
209
 
}
210
 
 
211
 
int Controller::GetIdealMonitor()
212
 
{
213
 
  UScreen *uscreen = UScreen::GetDefault();
214
 
  int primary_monitor;
215
 
  if (window_->IsVisible())
216
 
    primary_monitor = monitor_;
217
 
  else if (use_primary)
218
 
    primary_monitor = uscreen->GetPrimaryMonitor();
219
 
  else
220
 
    primary_monitor = uscreen->GetMonitorWithMouse();
221
 
 
222
 
  return primary_monitor;
223
 
}
224
 
 
225
 
nux::Geometry Controller::GetIdealWindowGeometry()
226
 
{
227
 
  UScreen *uscreen = UScreen::GetDefault();
228
 
  auto monitor_geo = uscreen->GetMonitorGeometry(GetIdealMonitor());
229
 
 
230
 
  // We want to cover as much of the screen as possible to grab any mouse events outside
231
 
  // of our window
232
 
  return nux::Geometry (monitor_geo.x + launcher_width,
233
 
                        monitor_geo.y,
234
 
                        monitor_geo.width - launcher_width,
235
 
                        monitor_geo.height);
236
 
}
237
 
 
238
 
void Controller::Relayout(bool check_monitor)
239
 
{
240
 
  EnsureDash();
241
 
 
242
 
  if (check_monitor)
243
 
  {
244
 
    monitor_ = CLAMP(GetIdealMonitor(), 0, static_cast<int>(UScreen::GetDefault()->GetMonitors().size()-1));
245
 
  }
246
 
 
247
 
  nux::Geometry geo = GetIdealWindowGeometry();
248
 
  view_->Relayout();
249
 
  window_->SetGeometry(geo);
250
 
  panel::Style &panel_style = panel::Style::Instance();
251
 
  view_->SetMonitorOffset(launcher_width, panel_style.panel_height);
252
 
}
253
 
 
254
 
void Controller::OnMouseDownOutsideWindow(int x, int y,
255
 
                                          unsigned long bflags, unsigned long kflags)
256
 
{
257
 
  HideDash();
258
 
}
259
 
 
260
 
void Controller::OnScreenUngrabbed()
261
 
{
262
 
  LOG_DEBUG(logger) << "On Screen Ungrabbed called";
263
 
  if (need_show_)
264
 
  {
265
 
    EnsureDash();
266
 
    ShowDash();
267
 
  }
268
 
}
269
 
 
270
 
void Controller::OnExternalShowDash(GVariant* variant)
271
 
{
272
 
  EnsureDash();
273
 
  visible_ ? HideDash() : ShowDash();
274
 
}
275
 
 
276
 
void Controller::OnExternalHideDash(GVariant* variant)
277
 
{
278
 
  EnsureDash();
279
 
 
280
 
  if (variant)
281
 
  {
282
 
    HideDash(g_variant_get_boolean(variant));
283
 
  }
284
 
  else
285
 
  {
286
 
    HideDash();
287
 
  }
288
 
}
289
 
 
290
 
void Controller::ShowDash()
291
 
{
292
 
  EnsureDash();
293
 
  WindowManager& wm = WindowManager::Default();
294
 
  // Don't want to show at the wrong time
295
 
  if (visible_ || wm.IsExpoActive() || wm.IsScaleActive())
296
 
    return;
297
 
 
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())
302
 
  {
303
 
    screen_ungrabbed_slot_.disconnect();
304
 
    screen_ungrabbed_slot_ = wm.screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
305
 
    need_show_ = true;
306
 
    return;
307
 
  }
308
 
 
309
 
  monitor_ = GetIdealMonitor();
310
 
 
311
 
  view_->AboutToShow();
312
 
 
313
 
  FocusWindow();
314
 
 
315
 
  need_show_ = false;
316
 
  visible_ = true;
317
 
 
318
 
  StartShowHideTimeline();
319
 
 
320
 
  nux::Geometry const& view_content_geo = view_->GetContentGeometry();
321
 
 
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);
324
 
}
325
 
 
326
 
void Controller::FocusWindow()
327
 
{
328
 
  window_->ShowWindow(true);
329
 
  window_->PushToFront();
330
 
  if (nux::GetWindowThread()->IsEmbeddedWindow())
331
 
  {
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();
336
 
  }
337
 
  window_->SetInputFocus();
338
 
  window_->QueueDraw();
339
 
 
340
 
  nux::GetWindowCompositor().SetKeyFocusArea(view_->default_focus());
341
 
}
342
 
 
343
 
void Controller::QuicklyHideDash(bool restore)
344
 
{
345
 
  HideDash(restore);
346
 
  timeline_animator_.Stop();
347
 
  window_->ShowWindow(false);
348
 
}
349
 
 
350
 
void Controller::HideDash(bool restore)
351
 
{
352
 
  if (!visible_)
353
 
   return;
354
 
 
355
 
  screen_ungrabbed_slot_.disconnect();
356
 
 
357
 
  EnsureDash();
358
 
 
359
 
  view_->AboutToHide();
360
 
 
361
 
  window_->CaptureMouseDownAnyWhereElse(false);
362
 
  window_->EnableInputWindow(false, dash::window_title, true, false);
363
 
  visible_ = false;
364
 
 
365
 
  nux::GetWindowCompositor().SetKeyFocusArea(NULL,nux::KEY_NAV_NONE);
366
 
 
367
 
  if (restore)
368
 
    WindowManager::Default().RestoreInputFocus();
369
 
 
370
 
  StartShowHideTimeline();
371
 
 
372
 
  nux::Geometry const& view_content_geo = view_->GetContentGeometry();
373
 
 
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);
376
 
}
377
 
 
378
 
void Controller::StartShowHideTimeline()
379
 
{
380
 
  EnsureDash();
381
 
 
382
 
  if (timeline_animator_.CurrentState() == nux::animation::Animation::State::Running)
383
 
  {
384
 
    timeline_animator_.Reverse();
385
 
  }
386
 
  else
387
 
  {
388
 
    if (visible_)
389
 
      timeline_animator_.SetStartValue(0.0f).SetFinishValue(1.0f).Start();
390
 
    else
391
 
      timeline_animator_.SetStartValue(1.0f).SetFinishValue(0.0f).Start();
392
 
  }
393
 
}
394
 
 
395
 
void Controller::OnViewShowHideFrame(double opacity)
396
 
{
397
 
  window_->SetOpacity(opacity);
398
 
 
399
 
  if (opacity == 0.0f && !visible_)
400
 
  {
401
 
    window_->ShowWindow(false);
402
 
  }
403
 
}
404
 
 
405
 
void Controller::OnActivateRequest(GVariant* variant)
406
 
{
407
 
  EnsureDash();
408
 
  view_->OnActivateRequest(variant);
409
 
}
410
 
 
411
 
gboolean Controller::CheckShortcutActivation(const char* key_string)
412
 
{
413
 
  EnsureDash();
414
 
  std::string lens_id = view_->GetIdForShortcutActivation(std::string(key_string));
415
 
  if (lens_id != "")
416
 
  {
417
 
    WindowManager& wm = WindowManager::Default();
418
 
    if (wm.IsScaleActive())
419
 
      wm.TerminateScale();
420
 
 
421
 
    GVariant* args = g_variant_new("(sus)", lens_id.c_str(), dash::GOTO_DASH_URI, "");
422
 
    OnActivateRequest(args);
423
 
    g_variant_unref(args);
424
 
    return true;
425
 
  }
426
 
  return false;
427
 
}
428
 
 
429
 
std::vector<char> Controller::GetAllShortcuts()
430
 
{
431
 
  EnsureDash();
432
 
  return view_->GetAllShortcuts();
433
 
}
434
 
 
435
 
// Introspectable
436
 
std::string Controller::GetName() const
437
 
{
438
 
  return "DashController";
439
 
}
440
 
 
441
 
void Controller::AddProperties(GVariantBuilder* builder)
442
 
{
443
 
  variant::BuilderWrapper(builder).add("visible", visible_)
444
 
                                  .add("ideal_monitor", GetIdealMonitor())
445
 
                                  .add("monitor", monitor_);
446
 
}
447
 
 
448
 
void Controller::ReFocusKeyInput()
449
 
{
450
 
  if (visible_)
451
 
  {
452
 
    window_->PushToFront();
453
 
    window_->SetInputFocus();
454
 
  }
455
 
}
456
 
 
457
 
bool Controller::IsVisible() const
458
 
{
459
 
  return visible_;
460
 
}
461
 
 
462
 
bool Controller::IsCommandLensOpen() const
463
 
{
464
 
  return visible_ && view_->IsCommandLensOpen();
465
 
}
466
 
 
467
 
nux::Geometry Controller::GetInputWindowGeometry()
468
 
{
469
 
  EnsureDash();
470
 
  dash::Style& style = dash::Style::Instance();
471
 
  nux::Geometry const& window_geo(window_->GetGeometry());
472
 
  nux::Geometry const& view_content_geo(view_->GetContentGeometry());
473
 
 
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();
477
 
  return geo;
478
 
}
479
 
 
480
 
 
481
 
}
482
 
}