~3v1n0/unity/overlay-border-scale

« back to all changes in this revision

Viewing changes to plugins/unityshell/src/LauncherController.cpp

  • Committer: Daniel van Vugt
  • Date: 2012-03-14 06:24:18 UTC
  • mfrom: (2108 unity)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: daniel.van.vugt@canonical.com-20120314062418-nprucpbr0m7qky5e
MergedĀ latestĀ lp:unity

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
#include <glib/gi18n-lib.h>
22
22
#include <libbamf/libbamf.h>
23
 
/* Compiz */
24
 
#include <core/core.h>
25
23
 
26
24
#include <Nux/Nux.h>
27
25
#include <Nux/HLayout.h>
28
26
#include <Nux/BaseWindow.h>
29
27
#include <NuxCore/Logger.h>
30
28
 
 
29
#include "LauncherOptions.h"
31
30
#include "BamfLauncherIcon.h"
32
31
#include "DesktopLauncherIcon.h"
33
32
#include "DeviceLauncherIcon.h"
37
36
#include "LauncherController.h"
38
37
#include "LauncherEntryRemote.h"
39
38
#include "LauncherEntryRemoteModel.h"
40
 
#include "LauncherIcon.h"
 
39
#include "AbstractLauncherIcon.h"
41
40
#include "SoftwareCenterLauncherIcon.h"
42
41
#include "LauncherModel.h"
43
42
#include "WindowManager.h"
44
43
#include "TrashLauncherIcon.h"
45
44
#include "BFBLauncherIcon.h"
 
45
#include "UScreen.h"
 
46
#include "UBusWrapper.h"
 
47
#include "UBusMessages.h"
 
48
#include "TimeUtil.h"
46
49
 
47
50
namespace unity
48
51
{
53
56
nux::logging::Logger logger("unity.launcher");
54
57
}
55
58
 
 
59
namespace local
 
60
{
 
61
namespace
 
62
{
 
63
  const int super_tap_duration = 250;
 
64
  const int launcher_minimum_show_duration = 1250;
 
65
  const int shortcuts_show_delay = 750;
 
66
  const int ignore_repeat_shortcut_duration = 250;
 
67
}
 
68
}
 
69
 
56
70
class Controller::Impl
57
71
{
58
72
public:
59
 
  Impl(Display* display);
 
73
  Impl(Display* display, Controller* parent);
60
74
  ~Impl();
61
75
 
62
76
  void UpdateNumWorkspaces(int workspaces);
63
77
 
 
78
  Launcher* CreateLauncher(int monitor);
 
79
 
64
80
  void Save();
65
81
  void SortAndUpdate();
66
82
 
67
 
  void OnIconAdded(LauncherIcon* icon);
68
 
  void OnIconRemoved(LauncherIcon* icon);
69
 
 
70
 
  void OnLauncherAddRequest(char* path, LauncherIcon* before);
71
 
  void OnLauncherAddRequestSpecial(char* path, LauncherIcon* before, char* aptdaemon_trans_id, char* icon_path);
72
 
  void OnLauncherRemoveRequest(LauncherIcon* icon);
 
83
  nux::ObjectPtr<Launcher> CurrentLauncher();
 
84
 
 
85
  void OnIconAdded(AbstractLauncherIcon::Ptr icon);
 
86
  void OnIconRemoved(AbstractLauncherIcon::Ptr icon);
 
87
 
 
88
  void OnLauncherAddRequest(char* path, AbstractLauncherIcon::Ptr before);
 
89
  void OnLauncherAddRequestSpecial(std::string const& path, AbstractLauncherIcon::Ptr before, std::string const& aptdaemon_trans_id, std::string const& icon_path);
 
90
  void OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr icon);
73
91
 
74
92
  void OnLauncherEntryRemoteAdded(LauncherEntryRemote* entry);
75
93
  void OnLauncherEntryRemoteRemoved(LauncherEntryRemote* entry);
76
94
 
 
95
  void OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before);
 
96
  void OnFavoriteStoreFavoriteRemoved(std::string const& entry);
 
97
  void OnFavoriteStoreReordered();
 
98
 
 
99
 
77
100
  void InsertExpoAction();
78
101
  void RemoveExpoAction();
79
102
 
80
103
  void InsertDesktopIcon();
81
104
  void RemoveDesktopIcon();
82
105
 
 
106
  bool TapTimeUnderLimit();
 
107
 
 
108
  void SendHomeActivationRequest();
 
109
 
 
110
  int TimeSinceLauncherKeyPress();
 
111
 
 
112
  int MonitorWithMouse();
 
113
 
83
114
  void InsertTrash();
84
115
 
85
 
  void RegisterIcon(LauncherIcon* icon);
86
 
 
87
 
  LauncherIcon* CreateFavorite(const char* file_path);
88
 
 
89
 
  SoftwareCenterLauncherIcon* CreateSCLauncherIcon(const char* file_path, const char* aptdaemon_trans_id, char* icon_path);
 
116
  void RegisterIcon(AbstractLauncherIcon::Ptr icon);
 
117
 
 
118
  AbstractLauncherIcon::Ptr CreateFavorite(const char* file_path);
 
119
 
 
120
  AbstractLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path);
90
121
 
91
122
  void SetupBamf();
92
123
 
 
124
  void EnsureLaunchers(std::vector<nux::Geometry> const& monitors);
 
125
 
93
126
  void OnExpoActivated();
94
127
 
 
128
  void OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors);
 
129
 
 
130
  void OnWindowFocusChanged (guint32 xid);
 
131
 
 
132
  void ReceiveMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags);
 
133
 
 
134
  void ReceiveLauncherKeyPress(unsigned long eventType,
 
135
                               unsigned long keysym,
 
136
                               unsigned long state,
 
137
                               const char* character,
 
138
                               unsigned short keyCount);
 
139
 
95
140
  /* statics */
96
141
 
97
142
  static void OnViewOpened(BamfMatcher* matcher, BamfView* view, gpointer data);
98
143
 
 
144
  Controller* parent_;
99
145
  glib::Object<BamfMatcher> matcher_;
100
146
  LauncherModel::Ptr     model_;
101
 
  nux::ObjectPtr<nux::BaseWindow> launcher_window_;
102
147
  nux::ObjectPtr<Launcher> launcher_;
 
148
  nux::ObjectPtr<Launcher> keyboard_launcher_;
103
149
  int                    sort_priority_;
104
150
  DeviceLauncherSection* device_section_;
105
151
  LauncherEntryRemoteModel remote_model_;
106
 
  SimpleLauncherIcon*    expo_icon_;
107
 
  DesktopLauncherIcon*   desktop_launcher_icon_;
108
 
  nux::ObjectPtr<AbstractLauncherIcon> desktop_icon_;
 
152
  AbstractLauncherIcon::Ptr expo_icon_;
 
153
  AbstractLauncherIcon::Ptr desktop_launcher_icon_;
 
154
  AbstractLauncherIcon::Ptr desktop_icon_;
109
155
  int                    num_workspaces_;
110
156
  bool                   show_desktop_icon_;
111
 
 
112
 
  guint            bamf_timer_handler_id_;
113
 
 
114
 
  guint32 on_view_opened_id_;
 
157
  Display*               display_;
 
158
 
 
159
  guint                  bamf_timer_handler_id_;
 
160
  guint                  on_view_opened_id_;
 
161
  guint                  launcher_key_press_handler_id_;
 
162
  guint                  launcher_label_show_handler_id_;
 
163
  guint                  launcher_hide_handler_id_;
 
164
 
 
165
  bool                   launcher_open;
 
166
  bool                   launcher_keynav;
 
167
  bool                   launcher_grabbed;
 
168
  bool                   reactivate_keynav;
 
169
  int                    reactivate_index;
 
170
  bool                   keynav_restore_window_;
 
171
 
 
172
  UBusManager            ubus;
 
173
 
 
174
  struct timespec        launcher_key_press_time_;
 
175
 
 
176
  LauncherList launchers;
115
177
 
116
178
  sigc::connection on_expoicon_activate_connection_;
 
179
  sigc::connection launcher_key_press_connection_;
 
180
  sigc::connection launcher_event_outside_connection_;
117
181
};
118
182
 
119
183
 
120
 
Controller::Impl::Impl(Display* display)
121
 
  : matcher_(nullptr)
 
184
Controller::Impl::Impl(Display* display, Controller* parent)
 
185
  : parent_(parent)
 
186
  , matcher_(nullptr)
122
187
  , model_(new LauncherModel())
123
188
  , sort_priority_(0)
124
189
  , show_desktop_icon_(false)
 
190
  , display_(display)
125
191
{
126
 
  // NOTE: should the launcher itself hold the base window?
127
 
  // seems like it probably should...
128
 
  launcher_window_ = new nux::BaseWindow(TEXT("LauncherWindow"));
129
 
 
130
 
  Launcher* raw_launcher = new Launcher(launcher_window_.GetPointer());
131
 
  launcher_ = raw_launcher;
132
 
  launcher_->display = display;
133
 
  launcher_->SetIconSize(54, 48);
134
 
  launcher_->SetBacklightMode(Launcher::BACKLIGHT_ALWAYS_ON);
135
 
  launcher_->SetHideMode(Launcher::LAUNCHER_HIDE_DODGE_WINDOWS);
136
 
  launcher_->SetLaunchAnimation(Launcher::LAUNCH_ANIMATION_PULSE);
137
 
  launcher_->SetUrgentAnimation(Launcher::URGENT_ANIMATION_WIGGLE);
138
 
 
139
 
  nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
140
 
  layout->AddView(raw_launcher, 1);
141
 
  layout->SetContentDistribution(nux::eStackLeft);
142
 
  layout->SetVerticalExternalMargin(0);
143
 
  layout->SetHorizontalExternalMargin(0);
144
 
 
145
 
  launcher_window_->SetLayout(layout);
146
 
  launcher_window_->SetBackgroundColor(nux::color::Transparent);
147
 
  launcher_window_->ShowWindow(true);
148
 
  launcher_window_->EnableInputWindow(true, "launcher", false, false);
149
 
  launcher_window_->InputWindowEnableStruts(false);
150
 
  launcher_window_->SetEnterFocusInputArea(raw_launcher);
151
 
 
152
 
  launcher_->SetModel(model_.get());
153
 
  launcher_->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
154
 
  launcher_->launcher_addrequest_special.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequestSpecial));
155
 
  launcher_->launcher_removerequest.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest));
156
 
 
157
 
  device_section_ = new DeviceLauncherSection(raw_launcher);
 
192
  UScreen* uscreen = UScreen::GetDefault();
 
193
  auto monitors = uscreen->GetMonitors();
 
194
 
 
195
  launcher_open = false;
 
196
  launcher_keynav = false;
 
197
  launcher_grabbed = false;
 
198
  reactivate_keynav = false;
 
199
  keynav_restore_window_ = true;
 
200
 
 
201
  EnsureLaunchers(monitors);
 
202
 
 
203
  launcher_ = launchers[0];
 
204
 
 
205
  device_section_ = new DeviceLauncherSection();
158
206
  device_section_->IconAdded.connect(sigc::mem_fun(this, &Impl::OnIconAdded));
159
207
 
160
208
  num_workspaces_ = WindowManager::Default()->WorkspaceCount();
180
228
  remote_model_.entry_added.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteAdded));
181
229
  remote_model_.entry_removed.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteRemoved));
182
230
 
183
 
  RegisterIcon(new BFBLauncherIcon(raw_launcher));
184
 
  desktop_icon_ = new DesktopLauncherIcon(raw_launcher);
 
231
  FavoriteStore::GetDefault().favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
 
232
  FavoriteStore::GetDefault().favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
 
233
  FavoriteStore::GetDefault().reordered.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreReordered));
 
234
 
 
235
  RegisterIcon(AbstractLauncherIcon::Ptr(new BFBLauncherIcon()));
 
236
  desktop_icon_ = AbstractLauncherIcon::Ptr(new DesktopLauncherIcon());
 
237
 
 
238
  uscreen->changed.connect(sigc::mem_fun(this, &Controller::Impl::OnScreenChanged));
 
239
 
 
240
  WindowManager& plugin_adapter = *(WindowManager::Default()); 
 
241
  plugin_adapter.window_focus_changed.connect (sigc::mem_fun (this, &Controller::Impl::OnWindowFocusChanged));
 
242
 
 
243
  launcher_key_press_time_ = { 0, 0 };
 
244
 
 
245
  ubus.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, [&](GVariant * args) {
 
246
    if (reactivate_keynav)
 
247
      parent_->KeyNavGrab();
 
248
      model_->SetSelection(reactivate_index);
 
249
  });
 
250
 
 
251
  parent_->AddChild(model_.get());
185
252
}
186
253
 
187
254
Controller::Impl::~Impl()
195
262
  delete device_section_;
196
263
}
197
264
 
198
 
 
199
 
void Controller::Impl::OnLauncherAddRequest(char* path, LauncherIcon* before)
 
265
void Controller::Impl::EnsureLaunchers(std::vector<nux::Geometry> const& monitors)
 
266
{
 
267
  unsigned int num_monitors;
 
268
  if (parent_->multiple_launchers)
 
269
  {
 
270
    num_monitors = monitors.size();
 
271
  }
 
272
  else
 
273
  {
 
274
    num_monitors = 1;
 
275
  }
 
276
 
 
277
  unsigned int i;
 
278
  for (i = 0; i < num_monitors; i++)
 
279
  {
 
280
    if (i >= launchers.size())
 
281
      launchers.push_back(nux::ObjectPtr<Launcher> (CreateLauncher(i)));
 
282
 
 
283
    launchers[i]->Resize();
 
284
  }
 
285
 
 
286
  for (; i < launchers.size(); ++i)
 
287
  {
 
288
    auto launcher = launchers[i];
 
289
    if (launcher.IsValid())
 
290
      launcher->GetParent()->UnReference();
 
291
  }
 
292
  launchers.resize(num_monitors);
 
293
}
 
294
 
 
295
void Controller::Impl::OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors)
 
296
{
 
297
  EnsureLaunchers(monitors);
 
298
}
 
299
 
 
300
void Controller::Impl::OnWindowFocusChanged (guint32 xid)
 
301
{
 
302
  static bool keynav_first_focus = false;
 
303
 
 
304
  if (keynav_first_focus)
 
305
  {
 
306
    keynav_first_focus = false;
 
307
    keynav_restore_window_ = false;
 
308
    parent_->KeyNavTerminate(false);
 
309
  }
 
310
  else if (launcher_keynav)
 
311
  {
 
312
    keynav_first_focus = true;
 
313
  } 
 
314
}
 
315
 
 
316
Launcher* Controller::Impl::CreateLauncher(int monitor)
 
317
{
 
318
  nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow"));
 
319
 
 
320
  Launcher* launcher = new Launcher(launcher_window);
 
321
  launcher->display = display_;
 
322
  launcher->monitor = monitor;
 
323
  launcher->options = parent_->options();
 
324
 
 
325
  nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
 
326
  layout->AddView(launcher, 1);
 
327
  layout->SetContentDistribution(nux::eStackLeft);
 
328
  layout->SetVerticalExternalMargin(0);
 
329
  layout->SetHorizontalExternalMargin(0);
 
330
 
 
331
  launcher_window->SetLayout(layout);
 
332
  launcher_window->SetBackgroundColor(nux::color::Transparent);
 
333
  launcher_window->ShowWindow(true);
 
334
  launcher_window->EnableInputWindow(true, "launcher", false, false);
 
335
  launcher_window->InputWindowEnableStruts(false);
 
336
  launcher_window->SetEnterFocusInputArea(launcher);
 
337
 
 
338
  launcher->SetModel(model_.get());
 
339
  launcher->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
 
340
  launcher->launcher_removerequest.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest));
 
341
 
 
342
  parent_->AddChild(launcher);
 
343
 
 
344
  return launcher;
 
345
}
 
346
 
 
347
void Controller::Impl::OnLauncherAddRequest(char* path, AbstractLauncherIcon::Ptr before)
200
348
{
201
349
  for (auto it : model_->GetSublist<BamfLauncherIcon> ())
202
350
  {
203
 
    if (!g_strcmp0(path, it->DesktopFile()))
 
351
    if (path && path == it->DesktopFile())
204
352
    {
205
353
      it->Stick();
206
354
      model_->ReorderBefore(it, before, false);
209
357
    }
210
358
  }
211
359
 
212
 
  LauncherIcon* result = CreateFavorite(path);
 
360
  AbstractLauncherIcon::Ptr result = CreateFavorite(path);
213
361
  if (result)
214
362
  {
215
363
    RegisterIcon(result);
225
373
  unity::FavoriteList desktop_paths;
226
374
 
227
375
  // Updates gsettings favorites.
228
 
  std::list<BamfLauncherIcon*> launchers = model_->GetSublist<BamfLauncherIcon> ();
 
376
  auto launchers = model_->GetSublist<BamfLauncherIcon> ();
229
377
  for (auto icon : launchers)
230
378
  {
231
379
    if (!icon->IsSticky())
232
380
      continue;
233
381
 
234
 
    const char* desktop_file = icon->DesktopFile();
 
382
    std::string const& desktop_file = icon->DesktopFile();
235
383
 
236
 
    if (desktop_file && strlen(desktop_file) > 0)
237
 
      desktop_paths.push_back(desktop_file);
 
384
    if (!desktop_file.empty())
 
385
      desktop_paths.push_back(desktop_file.c_str());
238
386
  }
239
387
 
240
388
  unity::FavoriteStore::GetDefault().SetFavorites(desktop_paths);
241
389
}
242
390
 
243
391
void
244
 
Controller::Impl::OnLauncherAddRequestSpecial(char* path, LauncherIcon* before, char* aptdaemon_trans_id, char* icon_path)
 
392
Controller::Impl::OnLauncherAddRequestSpecial(std::string const& path,
 
393
                                              AbstractLauncherIcon::Ptr before,
 
394
                                              std::string const& aptdaemon_trans_id,
 
395
                                              std::string const& icon_path)
245
396
{
246
 
  std::list<BamfLauncherIcon*> launchers;
247
 
  std::list<BamfLauncherIcon*>::iterator it;
248
 
 
249
 
  launchers = model_->GetSublist<BamfLauncherIcon> ();
250
 
  for (it = launchers.begin(); it != launchers.end(); it++)
 
397
  auto launchers = model_->GetSublist<BamfLauncherIcon>();
 
398
  for (auto icon : launchers)
251
399
  {
252
 
    if (g_strcmp0(path, (*it)->DesktopFile()) == 0)
 
400
    if (icon->DesktopFile() == path)
253
401
      return;
254
402
  }
255
403
 
256
 
  SoftwareCenterLauncherIcon* result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path);
 
404
  AbstractLauncherIcon::Ptr result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path);
257
405
  if (result)
258
406
  {
259
407
    RegisterIcon(result);
267
415
void Controller::Impl::SortAndUpdate()
268
416
{
269
417
  gint   shortcut = 1;
270
 
  gchar* buff;
271
418
 
272
 
  std::list<BamfLauncherIcon*> launchers = model_->GetSublist<BamfLauncherIcon> ();
273
 
  for (auto it : launchers)
 
419
  auto launchers = model_->GetSublist<BamfLauncherIcon> ();
 
420
  for (auto icon : launchers)
274
421
  {
275
 
    if (shortcut < 11 && it->GetQuirk(LauncherIcon::QUIRK_VISIBLE))
 
422
    if (shortcut <= 10 && icon->IsVisible())
276
423
    {
277
 
      buff = g_strdup_printf("%d", shortcut % 10);
278
 
      it->SetShortcut(buff[0]);
279
 
      g_free(buff);
 
424
      std::stringstream shortcut_string;
 
425
      shortcut_string << (shortcut % 10);
 
426
      icon->SetShortcut(shortcut_string.str()[0]);
280
427
      shortcut++;
281
428
    }
282
429
    // reset shortcut
283
430
    else
284
431
    {
285
 
      it->SetShortcut(0);
 
432
      icon->SetShortcut(0);
286
433
    }
287
434
  }
288
435
}
289
436
 
290
 
void Controller::Impl::OnIconAdded(LauncherIcon* icon)
 
437
void Controller::Impl::OnIconAdded(AbstractLauncherIcon::Ptr icon)
291
438
{
292
439
  this->RegisterIcon(icon);
293
440
}
294
441
 
295
 
void Controller::Impl::OnIconRemoved(LauncherIcon* icon)
 
442
void Controller::Impl::OnIconRemoved(AbstractLauncherIcon::Ptr icon)
296
443
{
297
444
  SortAndUpdate();
298
445
}
299
446
 
300
 
void Controller::Impl::OnLauncherRemoveRequest(LauncherIcon* icon)
 
447
void Controller::Impl::OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr icon)
301
448
{
302
 
  switch (icon->Type())
 
449
  switch (icon->GetIconType())
303
450
  {
304
 
    case LauncherIcon::TYPE_APPLICATION:
 
451
    case AbstractLauncherIcon::TYPE_APPLICATION:
305
452
    {
306
 
      BamfLauncherIcon* bamf_icon = dynamic_cast<BamfLauncherIcon*>(icon);
 
453
      BamfLauncherIcon* bamf_icon = dynamic_cast<BamfLauncherIcon*>(icon.GetPointer());
307
454
 
308
455
      if (bamf_icon)
309
456
      {
313
460
 
314
461
      break;
315
462
    }
316
 
    case LauncherIcon::TYPE_DEVICE:
 
463
    case AbstractLauncherIcon::TYPE_DEVICE:
317
464
    {
318
 
      DeviceLauncherIcon* device_icon = dynamic_cast<DeviceLauncherIcon*>(icon);
 
465
      DeviceLauncherIcon* device_icon = dynamic_cast<DeviceLauncherIcon*>(icon.GetPointer());
319
466
 
320
467
      if (device_icon && device_icon->CanEject())
321
468
        device_icon->Eject();
349
496
  }
350
497
}
351
498
 
 
499
void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before)
 
500
{
 
501
  auto bamf_list = model_->GetSublist<BamfLauncherIcon>();
 
502
  AbstractLauncherIcon::Ptr other;
 
503
  if (bamf_list.size() > 0)
 
504
    other = *(bamf_list.begin());
 
505
 
 
506
  if (!pos.empty())
 
507
  {
 
508
    for (auto it : bamf_list)
 
509
    {
 
510
      if (it->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE) && pos == it->DesktopFile())
 
511
        other = it;
 
512
    }
 
513
  }
 
514
 
 
515
  for (auto it : bamf_list)
 
516
  {
 
517
    if (entry == it->DesktopFile())
 
518
    {
 
519
      it->Stick(false);
 
520
      if (!before)
 
521
        model_->ReorderAfter(it, other);
 
522
      else
 
523
        model_->ReorderBefore(it, other, false);
 
524
      return;
 
525
    }
 
526
  }
 
527
 
 
528
  AbstractLauncherIcon::Ptr result = CreateFavorite(entry.c_str());
 
529
  if (result)
 
530
  {
 
531
    RegisterIcon(result);
 
532
    if (!before)
 
533
      model_->ReorderAfter(result, other);
 
534
    else
 
535
      model_->ReorderBefore(result, other, false);
 
536
  }
 
537
}
 
538
 
 
539
void Controller::Impl::OnFavoriteStoreFavoriteRemoved(std::string const& entry)
 
540
{
 
541
  for (auto it : model_->GetSublist<BamfLauncherIcon> ())
 
542
  {
 
543
    if (it->DesktopFile() == entry)
 
544
    {
 
545
      OnLauncherRemoveRequest(it);
 
546
      break;
 
547
     }
 
548
  }
 
549
}
 
550
 
 
551
void Controller::Impl::OnFavoriteStoreReordered()
 
552
{
 
553
  FavoriteList const& favs = FavoriteStore::GetDefault().GetFavorites();
 
554
  auto bamf_list = model_->GetSublist<BamfLauncherIcon>();
 
555
 
 
556
  int i = 0;
 
557
  for (auto it : favs)
 
558
  {
 
559
    auto icon = std::find_if(bamf_list.begin(), bamf_list.end(),
 
560
    [&it](AbstractLauncherIcon::Ptr x) { return (x->DesktopFile() == it); });
 
561
 
 
562
    if (icon != bamf_list.end())
 
563
    {
 
564
      (*icon)->SetSortPriority(i++);
 
565
    }
 
566
  }
 
567
 
 
568
  for (auto it : bamf_list)
 
569
  {
 
570
    if (!it->IsSticky())
 
571
      it->SetSortPriority(i++);
 
572
  }
 
573
 
 
574
  model_->Sort();
 
575
}
 
576
 
352
577
void Controller::Impl::OnExpoActivated()
353
578
{
354
579
  WindowManager::Default()->InitiateExpo();
356
581
 
357
582
void Controller::Impl::InsertTrash()
358
583
{
359
 
  TrashLauncherIcon* icon;
360
 
  icon = new TrashLauncherIcon(launcher_.GetPointer());
 
584
  AbstractLauncherIcon::Ptr icon(new TrashLauncherIcon());
361
585
  RegisterIcon(icon);
362
586
}
363
587
 
377
601
 
378
602
void Controller::Impl::InsertExpoAction()
379
603
{
380
 
  expo_icon_ = new SimpleLauncherIcon(launcher_.GetPointer());
381
 
 
382
 
  expo_icon_->tooltip_text = _("Workspace Switcher");
383
 
  expo_icon_->icon_name = "workspace-switcher";
384
 
  expo_icon_->SetQuirk(LauncherIcon::QUIRK_VISIBLE, true);
385
 
  expo_icon_->SetQuirk(LauncherIcon::QUIRK_RUNNING, false);
386
 
  expo_icon_->SetIconType(LauncherIcon::TYPE_EXPO);
387
 
  expo_icon_->SetShortcut('s');
388
 
 
389
 
  on_expoicon_activate_connection_ = expo_icon_->activate.connect(sigc::mem_fun(this, &Impl::OnExpoActivated));
390
 
 
 
604
  expo_icon_ = AbstractLauncherIcon::Ptr(new SimpleLauncherIcon());
 
605
 
 
606
  SimpleLauncherIcon* icon = static_cast<SimpleLauncherIcon*>(expo_icon_.GetPointer());
 
607
  icon->tooltip_text = _("Workspace Switcher");
 
608
  icon->icon_name = "workspace-switcher";
 
609
  icon->SetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE, true);
 
610
  icon->SetQuirk(AbstractLauncherIcon::QUIRK_RUNNING, false);
 
611
  icon->SetIconType(AbstractLauncherIcon::TYPE_EXPO);
 
612
  icon->SetShortcut('s');
 
613
 
 
614
  on_expoicon_activate_connection_ = icon->activate.connect(sigc::mem_fun(this, &Impl::OnExpoActivated));
 
615
 
 
616
  
391
617
  RegisterIcon(expo_icon_);
392
618
}
393
619
 
400
626
 
401
627
void Controller::Impl::InsertDesktopIcon()
402
628
{
403
 
  desktop_launcher_icon_ = new DesktopLauncherIcon(launcher_.GetPointer());
404
 
  desktop_launcher_icon_->SetIconType(LauncherIcon::TYPE_DESKTOP);
405
 
  desktop_launcher_icon_->SetShowInSwitcher(false);
406
 
 
 
629
  desktop_launcher_icon_ = AbstractLauncherIcon::Ptr(new DesktopLauncherIcon());
407
630
  RegisterIcon(desktop_launcher_icon_);
408
631
}
409
632
 
412
635
  model_->RemoveIcon(desktop_launcher_icon_);
413
636
}
414
637
 
415
 
void Controller::Impl::RegisterIcon(LauncherIcon* icon)
 
638
void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr icon)
416
639
{
417
640
  model_->AddIcon(icon);
418
641
 
419
 
  BamfLauncherIcon* bamf_icon = dynamic_cast<BamfLauncherIcon*>(icon);
420
 
  if (bamf_icon)
421
 
  {
422
 
    LauncherEntryRemote* entry = NULL;
423
 
    const char* path;
424
 
    path = bamf_icon->DesktopFile();
425
 
    if (path)
426
 
      entry = remote_model_.LookupByDesktopFile(path);
427
 
    if (entry)
428
 
      icon->InsertEntryRemote(entry);
429
 
  }
 
642
  LauncherEntryRemote* entry = NULL;
 
643
  std::string const& path = icon->DesktopFile();
 
644
  if (!path.empty())
 
645
    entry = remote_model_.LookupByDesktopFile(path.c_str());
 
646
  if (entry)
 
647
    icon->InsertEntryRemote(entry);
430
648
}
431
649
 
432
650
/* static private */
446
664
    return;
447
665
  }
448
666
 
449
 
  BamfLauncherIcon* icon = new BamfLauncherIcon(self->launcher_.GetPointer(), app);
450
 
  icon->SetIconType(LauncherIcon::TYPE_APPLICATION);
 
667
  AbstractLauncherIcon::Ptr icon (new BamfLauncherIcon(app));
451
668
  icon->SetSortPriority(self->sort_priority_++);
452
669
 
453
670
  self->RegisterIcon(icon);
454
671
}
455
672
 
456
 
LauncherIcon* Controller::Impl::CreateFavorite(const char* file_path)
 
673
AbstractLauncherIcon::Ptr Controller::Impl::CreateFavorite(const char* file_path)
457
674
{
458
675
  BamfApplication* app;
459
 
  BamfLauncherIcon* icon;
 
676
  AbstractLauncherIcon::Ptr result;
460
677
 
461
678
  app = bamf_matcher_get_application_for_desktop_file(matcher_, file_path, true);
462
679
  if (!app)
463
 
    return NULL;
 
680
    return result;
464
681
 
465
682
  if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
466
683
  {
467
684
    bamf_view_set_sticky(BAMF_VIEW(app), true);
468
 
    return 0;
 
685
    return result;
469
686
  }
470
687
 
471
688
  g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1));
472
689
 
473
690
  bamf_view_set_sticky(BAMF_VIEW(app), true);
474
 
  icon = new BamfLauncherIcon(launcher_.GetPointer(), app);
475
 
  icon->SetIconType(LauncherIcon::TYPE_APPLICATION);
 
691
  AbstractLauncherIcon::Ptr icon (new BamfLauncherIcon(app));
476
692
  icon->SetSortPriority(sort_priority_++);
 
693
  result = icon;
477
694
 
478
 
  return icon;
 
695
  return result;
479
696
}
480
697
 
481
 
SoftwareCenterLauncherIcon*
482
 
Controller::Impl::CreateSCLauncherIcon(const char* file_path, const char* aptdaemon_trans_id, char* icon_path)
 
698
AbstractLauncherIcon::Ptr
 
699
Controller::Impl::CreateSCLauncherIcon(std::string const& file_path,
 
700
                                       std::string const& aptdaemon_trans_id,
 
701
                                       std::string const& icon_path)
483
702
{
484
703
  BamfApplication* app;
485
 
  SoftwareCenterLauncherIcon* icon;
 
704
  AbstractLauncherIcon::Ptr result;
486
705
 
487
 
  app = bamf_matcher_get_application_for_desktop_file(matcher_, file_path, true);
 
706
  app = bamf_matcher_get_application_for_desktop_file(matcher_, file_path.c_str(), true);
488
707
  if (!BAMF_IS_APPLICATION(app))
489
 
    return NULL;
 
708
    return result;
490
709
 
491
710
  if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
492
711
  {
493
712
    bamf_view_set_sticky(BAMF_VIEW(app), true);
494
 
    return 0;
 
713
    return result;
495
714
  }
496
715
 
497
716
  g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1));
498
717
 
499
718
  bamf_view_set_sticky(BAMF_VIEW(app), true);
500
 
  icon = new SoftwareCenterLauncherIcon(launcher_.GetPointer(), app, (char*)aptdaemon_trans_id, icon_path);
501
 
  icon->SetIconType(LauncherIcon::TYPE_APPLICATION);
 
719
  AbstractLauncherIcon::Ptr icon(new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path));
502
720
  icon->SetSortPriority(sort_priority_++);
503
721
 
504
 
  return icon;
 
722
  result = icon;
 
723
  return result;
505
724
}
506
725
 
507
726
void Controller::Impl::SetupBamf()
508
727
{
509
728
  GList* apps, *l;
510
729
  BamfApplication* app;
511
 
  BamfLauncherIcon* icon;
512
730
 
513
731
  // Sufficiently large number such that we ensure proper sorting
514
732
  // (avoids case where first item gets tacked onto end rather than start)
521
739
  for (FavoriteList::const_iterator i = favs.begin(), end = favs.end();
522
740
       i != end; ++i)
523
741
  {
524
 
    LauncherIcon* fav = CreateFavorite(i->c_str());
 
742
    AbstractLauncherIcon::Ptr fav = CreateFavorite(i->c_str());
525
743
 
526
744
    if (fav)
527
745
    {
542
760
      continue;
543
761
    g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1));
544
762
 
545
 
    icon = new BamfLauncherIcon(launcher_.GetPointer(), app);
 
763
    AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
546
764
    icon->SetSortPriority(sort_priority_++);
547
765
    RegisterIcon(icon);
548
766
  }
554
772
  bamf_timer_handler_id_ = 0;
555
773
}
556
774
 
 
775
int Controller::Impl::TimeSinceLauncherKeyPress()
 
776
{
 
777
  struct timespec current;
 
778
  unity::TimeUtil::SetTimeStruct(&current);
 
779
  return unity::TimeUtil::TimeDelta(&current, &launcher_key_press_time_);
 
780
}
 
781
 
 
782
bool Controller::Impl::TapTimeUnderLimit()
 
783
{
 
784
  int time_difference = TimeSinceLauncherKeyPress();
 
785
  return time_difference < local::super_tap_duration;
 
786
}
 
787
 
 
788
void Controller::Impl::SendHomeActivationRequest()
 
789
{
 
790
  ubus.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, g_variant_new("(sus)", "home.lens", 0, ""));
 
791
}
557
792
 
558
793
Controller::Controller(Display* display)
559
 
  : pimpl(new Impl(display))
 
794
 : options(Options::Ptr(new Options()))
 
795
 , multiple_launchers(true)
 
796
 , pimpl(new Impl(display, this))
560
797
{
 
798
  multiple_launchers.changed.connect([&](bool value) -> void {
 
799
    UScreen* uscreen = UScreen::GetDefault();
 
800
    auto monitors = uscreen->GetMonitors();
 
801
    pimpl->EnsureLaunchers(monitors);
 
802
    options()->show_for_all = !value;
 
803
  });
561
804
}
562
805
 
563
806
Controller::~Controller()
570
813
  pimpl->UpdateNumWorkspaces(workspaces);
571
814
}
572
815
 
573
 
Launcher& Controller::launcher()
 
816
Launcher& Controller::launcher() const
574
817
{
575
818
  return *(pimpl->launcher_);
576
819
}
577
820
 
578
 
std::vector<char> Controller::GetAllShortcuts()
 
821
Controller::LauncherList& Controller::launchers() const
 
822
{
 
823
  return pimpl->launchers;
 
824
}
 
825
 
 
826
std::vector<char> Controller::GetAllShortcuts() const
579
827
{
580
828
  std::vector<char> shortcuts;
581
829
  for (auto icon : *(pimpl->model_))
588
836
  return shortcuts;
589
837
}
590
838
 
591
 
std::vector<AbstractLauncherIcon*> Controller::GetAltTabIcons()
 
839
std::vector<AbstractLauncherIcon::Ptr> Controller::GetAltTabIcons(bool current) const
592
840
{
593
 
  std::vector<AbstractLauncherIcon*> results;
 
841
  std::vector<AbstractLauncherIcon::Ptr> results;
594
842
 
595
 
  results.push_back(pimpl->desktop_icon_.GetPointer());
 
843
  results.push_back(pimpl->desktop_icon_);
596
844
 
597
845
  for (auto icon : *(pimpl->model_))
598
 
    if (icon->ShowInSwitcher())
 
846
    if (icon->ShowInSwitcher(current))
599
847
      results.push_back(icon);
600
848
 
601
849
  return results;
602
850
}
603
851
 
604
 
void Controller::PrimaryMonitorGeometryChanged(nux::Geometry const& rect)
 
852
Window Controller::LauncherWindowId(int launcher) const
605
853
{
606
 
  const int panel_height = 24;
607
 
 
608
 
  int launcher_width = pimpl->launcher_window_->GetGeometry().width;
609
 
 
610
 
  nux::Geometry new_geometry(rect.x,
611
 
                             rect.y + panel_height,
612
 
                             launcher_width,
613
 
                             rect.height - panel_height);
614
 
 
615
 
  LOG_DEBUG(logger) << "Setting to launcher rect:"
616
 
                    << " x=" << new_geometry.x
617
 
                    << " y=" << new_geometry.y
618
 
                    << " w=" << new_geometry.width
619
 
                    << " h=" << new_geometry.height;
620
 
 
621
 
  pimpl->launcher_->SetMaximumHeight(new_geometry.height);
622
 
 
623
 
  pimpl->launcher_window_->SetGeometry(new_geometry);
624
 
  pimpl->launcher_->SetGeometry(new_geometry);
 
854
  if (launcher >= (int)pimpl->launchers.size())
 
855
    return 0;
 
856
  return pimpl->launchers[launcher]->GetParent()->GetInputWindowId();
625
857
}
626
858
 
627
 
Window Controller::launcher_input_window_id()
 
859
Window Controller::KeyNavLauncherInputWindowId() const
628
860
{
629
 
  return pimpl->launcher_window_->GetInputWindowId();
 
861
  if (KeyNavIsActive())
 
862
    return pimpl->keyboard_launcher_->GetParent()->GetInputWindowId();
 
863
  return 0;
630
864
}
631
865
 
632
866
void Controller::PushToFront()
633
867
{
634
 
  pimpl->launcher_window_->PushToFront();
 
868
  pimpl->launcher_->GetParent()->PushToFront();
635
869
}
636
870
 
637
871
void Controller::SetShowDesktopIcon(bool show_desktop_icon)
647
881
    pimpl->RemoveDesktopIcon();
648
882
}
649
883
 
 
884
int Controller::Impl::MonitorWithMouse()
 
885
{
 
886
  UScreen* uscreen = UScreen::GetDefault();
 
887
  return uscreen->GetMonitorWithMouse();
 
888
}
 
889
 
 
890
nux::ObjectPtr<Launcher> Controller::Impl::CurrentLauncher()
 
891
{
 
892
  nux::ObjectPtr<Launcher> result;
 
893
  int best = std::max<int> (launchers.size() - 1, MonitorWithMouse());
 
894
  if (best >= 0)
 
895
    result = launchers[best];
 
896
  return result;
 
897
}
 
898
 
 
899
void Controller::HandleLauncherKeyPress()
 
900
{
 
901
  unity::TimeUtil::SetTimeStruct(&pimpl->launcher_key_press_time_);
 
902
 
 
903
  auto show_launcher = [](gpointer user_data) -> gboolean
 
904
  {
 
905
    Impl* self = static_cast<Impl*>(user_data);
 
906
    if (self->keyboard_launcher_.IsNull())
 
907
      self->keyboard_launcher_ = self->CurrentLauncher();
 
908
 
 
909
    if (self->launcher_hide_handler_id_ > 0)
 
910
    {
 
911
      g_source_remove(self->launcher_hide_handler_id_);
 
912
      self->launcher_hide_handler_id_ = 0;
 
913
    }
 
914
 
 
915
    self->keyboard_launcher_->ForceReveal(true);
 
916
    self->launcher_open = true;
 
917
    self->launcher_key_press_handler_id_ = 0;
 
918
    return FALSE;
 
919
  };
 
920
  pimpl->launcher_key_press_handler_id_ = g_timeout_add(local::super_tap_duration, show_launcher, pimpl);
 
921
 
 
922
  auto show_shortcuts = [](gpointer user_data) -> gboolean
 
923
  {
 
924
    Impl* self = static_cast<Impl*>(user_data);
 
925
    if (!self->launcher_keynav)
 
926
    {
 
927
      if (self->keyboard_launcher_.IsNull())
 
928
        self->keyboard_launcher_ = self->CurrentLauncher();
 
929
 
 
930
      self->keyboard_launcher_->ShowShortcuts(true);
 
931
      self->launcher_open = true;
 
932
      self->launcher_label_show_handler_id_ = 0;
 
933
    }
 
934
    return FALSE;
 
935
  };
 
936
  pimpl->launcher_label_show_handler_id_ = g_timeout_add(local::shortcuts_show_delay, show_shortcuts, pimpl);
 
937
}
 
938
 
 
939
void Controller::HandleLauncherKeyRelease(bool was_tap)
 
940
{
 
941
  if (pimpl->TapTimeUnderLimit() && was_tap)
 
942
  {
 
943
    pimpl->SendHomeActivationRequest();
 
944
  }
 
945
 
 
946
  if (pimpl->launcher_label_show_handler_id_)
 
947
  {
 
948
    g_source_remove(pimpl->launcher_label_show_handler_id_);
 
949
    pimpl->launcher_label_show_handler_id_ = 0;
 
950
  }
 
951
 
 
952
  if (pimpl->launcher_key_press_handler_id_)
 
953
  {
 
954
    g_source_remove(pimpl->launcher_key_press_handler_id_);
 
955
    pimpl->launcher_key_press_handler_id_ = 0;
 
956
  }
 
957
 
 
958
  if (pimpl->keyboard_launcher_.IsValid())
 
959
  {
 
960
    pimpl->keyboard_launcher_->ShowShortcuts(false);
 
961
 
 
962
    int ms_since_show = pimpl->TimeSinceLauncherKeyPress();
 
963
    if (ms_since_show > local::launcher_minimum_show_duration)
 
964
    {
 
965
      pimpl->keyboard_launcher_->ForceReveal(false);
 
966
      pimpl->launcher_open = false;
 
967
 
 
968
      if (!pimpl->launcher_keynav)
 
969
        pimpl->keyboard_launcher_.Release();
 
970
    }
 
971
    else
 
972
    {
 
973
      int time_left = local::launcher_minimum_show_duration - ms_since_show;
 
974
      auto hide_launcher = [](gpointer user_data) -> gboolean
 
975
      {
 
976
        Impl *self = static_cast<Impl*>(user_data);
 
977
        if (self->keyboard_launcher_.IsValid())
 
978
        {
 
979
          self->keyboard_launcher_->ForceReveal(false);
 
980
          self->launcher_open = false;
 
981
 
 
982
          if (!self->launcher_keynav)
 
983
            self->keyboard_launcher_.Release();
 
984
        }
 
985
 
 
986
        self->launcher_hide_handler_id_ = 0;
 
987
        return FALSE;
 
988
      };
 
989
 
 
990
      pimpl->launcher_hide_handler_id_ = g_timeout_add(time_left, hide_launcher, pimpl);
 
991
    }
 
992
  }
 
993
}
 
994
 
 
995
bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym, unsigned long key_code, unsigned long key_state, char* key_string)
 
996
{
 
997
  LauncherModel::iterator it;
 
998
 
 
999
  // Shortcut to start launcher icons. Only relies on Keycode, ignore modifier
 
1000
  for (it = pimpl->model_->begin(); it != pimpl->model_->end(); it++)
 
1001
  {
 
1002
    if ((XKeysymToKeycode(display, (*it)->GetShortcut()) == key_code) ||
 
1003
        ((gchar)((*it)->GetShortcut()) == key_string[0]))
 
1004
    {
 
1005
      struct timespec last_action_time = (*it)->GetQuirkTime(AbstractLauncherIcon::QUIRK_LAST_ACTION);
 
1006
      struct timespec current;
 
1007
      TimeUtil::SetTimeStruct(&current);
 
1008
      if (TimeUtil::TimeDelta(&current, &last_action_time) > local::ignore_repeat_shortcut_duration)
 
1009
      {
 
1010
        if (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask))
 
1011
          (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0));
 
1012
        else
 
1013
          (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0));
 
1014
      }
 
1015
 
 
1016
      // disable the "tap on super" check
 
1017
      pimpl->launcher_key_press_time_ = { 0, 0 };
 
1018
      return true;
 
1019
    }
 
1020
  }
 
1021
 
 
1022
  return false;
 
1023
}
 
1024
 
 
1025
void Controller::Impl::ReceiveMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags)
 
1026
{
 
1027
  if (launcher_grabbed)
 
1028
    parent_->KeyNavTerminate(false);
 
1029
}
 
1030
 
 
1031
void Controller::KeyNavGrab()
 
1032
{
 
1033
  pimpl->ubus.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
 
1034
  KeyNavActivate();
 
1035
  pimpl->keyboard_launcher_->GrabKeyboard();
 
1036
  pimpl->launcher_grabbed = true;
 
1037
 
 
1038
  pimpl->launcher_key_press_connection_ =
 
1039
    pimpl->keyboard_launcher_->key_down.connect(sigc::mem_fun(pimpl, &Controller::Impl::ReceiveLauncherKeyPress));
 
1040
  pimpl->launcher_event_outside_connection_ =
 
1041
    pimpl->keyboard_launcher_->mouse_down_outside_pointer_grab_area.connect(sigc::mem_fun(pimpl, &Controller::Impl::ReceiveMouseDownOutsideArea));
 
1042
}
 
1043
 
 
1044
void Controller::KeyNavActivate()
 
1045
{
 
1046
  if (pimpl->launcher_keynav)
 
1047
    return;
 
1048
 
 
1049
  pimpl->reactivate_keynav = false;
 
1050
  pimpl->launcher_keynav = true;
 
1051
  pimpl->keynav_restore_window_ = true;
 
1052
  pimpl->keyboard_launcher_ = pimpl->CurrentLauncher();
 
1053
 
 
1054
  pimpl->keyboard_launcher_->EnterKeyNavMode();
 
1055
  pimpl->model_->SetSelection(0);
 
1056
 
 
1057
  pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_SWTICHER, g_variant_new_boolean(true));
 
1058
  pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_NAV, NULL);
 
1059
}
 
1060
 
 
1061
void Controller::KeyNavNext()
 
1062
{
 
1063
  pimpl->model_->SelectNext();
 
1064
}
 
1065
 
 
1066
void Controller::KeyNavPrevious()
 
1067
{
 
1068
  pimpl->model_->SelectPrevious();
 
1069
}
 
1070
 
 
1071
void Controller::KeyNavTerminate(bool activate)
 
1072
{
 
1073
  if (!pimpl->launcher_keynav)
 
1074
    return;
 
1075
 
 
1076
  pimpl->keyboard_launcher_->ExitKeyNavMode();
 
1077
  if (pimpl->launcher_grabbed)
 
1078
  {
 
1079
    pimpl->keyboard_launcher_->UnGrabKeyboard();
 
1080
    pimpl->launcher_key_press_connection_.disconnect();
 
1081
    pimpl->launcher_event_outside_connection_.disconnect();
 
1082
    pimpl->launcher_grabbed = false;
 
1083
  }
 
1084
 
 
1085
  if (activate)
 
1086
    pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0));
 
1087
 
 
1088
  pimpl->launcher_keynav = false;
 
1089
  if (!pimpl->launcher_open)
 
1090
    pimpl->keyboard_launcher_.Release();
 
1091
 
 
1092
  pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_SWTICHER, g_variant_new_boolean(true));
 
1093
  pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_NAV, g_variant_new_boolean(pimpl->keynav_restore_window_));
 
1094
}
 
1095
 
 
1096
bool Controller::KeyNavIsActive() const
 
1097
{
 
1098
  return pimpl->launcher_keynav;
 
1099
}
 
1100
 
 
1101
std::string
 
1102
Controller::GetName() const
 
1103
{
 
1104
  return "LauncherController";
 
1105
}
 
1106
 
 
1107
void
 
1108
Controller::AddProperties(GVariantBuilder* builder)
 
1109
{
 
1110
  timespec current;
 
1111
  clock_gettime(CLOCK_MONOTONIC, &current);
 
1112
 
 
1113
  unity::variant::BuilderWrapper(builder)
 
1114
  .add("key_nav_is_active", KeyNavIsActive())
 
1115
  .add("key_nav_launcher_monitor", pimpl->keyboard_launcher_.IsValid() ?  pimpl->keyboard_launcher_->monitor : -1)
 
1116
  .add("key_nav_selection", pimpl->model_->SelectionIndex())
 
1117
  .add("key_nav_is_grabbed", pimpl->launcher_grabbed)
 
1118
  .add("keyboard_launcher", pimpl->CurrentLauncher()->monitor);
 
1119
}
 
1120
 
 
1121
void Controller::Impl::ReceiveLauncherKeyPress(unsigned long eventType,
 
1122
                                               unsigned long keysym,
 
1123
                                               unsigned long state,
 
1124
                                               const char* character,
 
1125
                                               unsigned short keyCount)
 
1126
{
 
1127
  /*
 
1128
   * all key events below are related to keynavigation. Make an additional
 
1129
   * check that we are in a keynav mode when we inadvertadly receive the focus
 
1130
   */
 
1131
  if (!launcher_grabbed)
 
1132
    return;
 
1133
 
 
1134
  switch (keysym)
 
1135
  {
 
1136
      // up (move selection up or go to global-menu if at top-most icon)
 
1137
    case NUX_VK_UP:
 
1138
    case NUX_KP_UP:
 
1139
      parent_->KeyNavPrevious();
 
1140
      break;
 
1141
 
 
1142
      // down (move selection down and unfold launcher if needed)
 
1143
    case NUX_VK_DOWN:
 
1144
    case NUX_KP_DOWN:
 
1145
      parent_->KeyNavNext();
 
1146
      break;
 
1147
 
 
1148
      // super/control/alt/esc/left (close quicklist or exit laucher key-focus)
 
1149
    case NUX_VK_LWIN:
 
1150
    case NUX_VK_RWIN:
 
1151
    case NUX_VK_CONTROL:
 
1152
    case NUX_VK_MENU:
 
1153
    case NUX_VK_LEFT:
 
1154
    case NUX_KP_LEFT:
 
1155
    case NUX_VK_ESCAPE:
 
1156
      // hide again
 
1157
      parent_->KeyNavTerminate(false);
 
1158
      break;
 
1159
 
 
1160
      // right/shift-f10 (open quicklist of currently selected icon)
 
1161
    case XK_F10:
 
1162
      if (!(state & nux::NUX_STATE_SHIFT))
 
1163
        break;
 
1164
    case NUX_VK_RIGHT:
 
1165
    case NUX_KP_RIGHT:
 
1166
    case XK_Menu:
 
1167
      if (model_->Selection()->OpenQuicklist(true, keyboard_launcher_->monitor()))
 
1168
      {
 
1169
        reactivate_keynav = true;
 
1170
        reactivate_index = model_->SelectionIndex();
 
1171
        parent_->KeyNavTerminate(false);
 
1172
      }
 
1173
      break;
 
1174
 
 
1175
      // <SPACE> (open a new instance)
 
1176
    case NUX_VK_SPACE:
 
1177
      model_->Selection()->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0));
 
1178
      parent_->KeyNavTerminate(false);
 
1179
      break;
 
1180
 
 
1181
      // <RETURN> (start/activate currently selected icon)
 
1182
    case NUX_VK_ENTER:
 
1183
    case NUX_KP_ENTER:
 
1184
    model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0));
 
1185
    parent_->KeyNavTerminate(false);
 
1186
    break;
 
1187
 
 
1188
    default:
 
1189
      break;
 
1190
  }
 
1191
}
 
1192
 
650
1193
 
651
1194
} // namespace launcher
652
1195
} // namespace unity