~3v1n0/unity/light-shortcuts

« back to all changes in this revision

Viewing changes to launcher/Launcher.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 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: Jason Smith <jason.smith@canonical.com>
18
 
 * Authored by: Jay Taoko <jay.taoko@canonical.com>
19
 
 */
20
 
 
21
 
#include "config.h"
22
 
#include <math.h>
23
 
 
24
 
#include <Nux/Nux.h>
25
 
#include <Nux/VScrollBar.h>
26
 
#include <Nux/HLayout.h>
27
 
#include <Nux/VLayout.h>
28
 
#include <NuxCore/Logger.h>
29
 
 
30
 
#include <NuxGraphics/NuxGraphics.h>
31
 
#include <NuxGraphics/GestureEvent.h>
32
 
#include <NuxGraphics/GpuDevice.h>
33
 
#include <NuxGraphics/GLTextureResourceManager.h>
34
 
 
35
 
#include <Nux/BaseWindow.h>
36
 
#include <Nux/WindowCompositor.h>
37
 
 
38
 
#include "Launcher.h"
39
 
#include "AbstractLauncherIcon.h"
40
 
#include "unity-shared/PanelStyle.h"
41
 
#include "SpacerLauncherIcon.h"
42
 
#include "LauncherModel.h"
43
 
#include "QuicklistManager.h"
44
 
#include "QuicklistView.h"
45
 
#include "unity-shared/IconRenderer.h"
46
 
#include "unity-shared/TimeUtil.h"
47
 
#include "unity-shared/TextureCache.h"
48
 
#include "unity-shared/IconLoader.h"
49
 
#include "unity-shared/UScreen.h"
50
 
#include "unity-shared/UBusMessages.h"
51
 
#include "unity-shared/UnitySettings.h"
52
 
#include "unity-shared/GraphicsUtils.h"
53
 
 
54
 
 
55
 
#include <UnityCore/GLibWrapper.h>
56
 
#include <UnityCore/Variant.h>
57
 
 
58
 
#include <boost/algorithm/string.hpp>
59
 
#include <sigc++/sigc++.h>
60
 
 
61
 
namespace unity
62
 
{
63
 
using ui::RenderArg;
64
 
using ui::Decaymulator;
65
 
 
66
 
namespace launcher
67
 
{
68
 
DECLARE_LOGGER(logger, "unity.launcher");
69
 
 
70
 
const char* window_title = "unity-launcher";
71
 
 
72
 
namespace
73
 
{
74
 
const int URGENT_BLINKS = 3;
75
 
const int WIGGLE_CYCLES = 6;
76
 
 
77
 
const int MAX_STARTING_BLINKS = 5;
78
 
const int STARTING_BLINK_LAMBDA = 3;
79
 
 
80
 
const int PULSE_BLINK_LAMBDA = 2;
81
 
 
82
 
const float BACKLIGHT_STRENGTH = 0.9f;
83
 
const int ICON_PADDING = 6;
84
 
const int RIGHT_LINE_WIDTH = 1;
85
 
 
86
 
const int ANIM_DURATION_SHORT_SHORT = 100;
87
 
const int ANIM_DURATION = 200;
88
 
const int ANIM_DURATION_LONG = 350;
89
 
const int START_DRAGICON_DURATION = 250;
90
 
 
91
 
const int MOUSE_DEADZONE = 15;
92
 
const float DRAG_OUT_PIXELS = 300.0f;
93
 
 
94
 
const int SCROLL_AREA_HEIGHT = 24;
95
 
const int SCROLL_FPS = 30;
96
 
 
97
 
const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";
98
 
const std::string SCROLL_TIMEOUT = "scroll-timeout";
99
 
const std::string ANIMATION_IDLE = "animation-idle";
100
 
}
101
 
 
102
 
 
103
 
NUX_IMPLEMENT_OBJECT_TYPE(Launcher);
104
 
 
105
 
const int Launcher::Launcher::ANIM_DURATION_SHORT = 125;
106
 
 
107
 
Launcher::Launcher(MockableBaseWindow* parent,
108
 
                   NUX_FILE_LINE_DECL)
109
 
  : View(NUX_FILE_LINE_PARAM)
110
 
#ifdef USE_X11
111
 
  , display(nux::GetGraphicsDisplay()->GetX11Display())
112
 
#else
113
 
  , display(0)
114
 
#endif
115
 
  , monitor(0)
116
 
  , _parent(parent)
117
 
  , _active_quicklist(nullptr)
118
 
  , _hovered(false)
119
 
  , _hidden(false)
120
 
  , _shortcuts_shown(false)
121
 
  , _data_checked(false)
122
 
  , _steal_drag(false)
123
 
  , _drag_edge_touching(false)
124
 
  , _initial_drag_animation(false)
125
 
  , _dash_is_open(false)
126
 
  , _hud_is_open(false)
127
 
  , _folded_angle(1.0f)
128
 
  , _neg_folded_angle(-1.0f)
129
 
  , _folded_z_distance(10.0f)
130
 
  , _edge_overcome_pressure(0.0f)
131
 
  , _launcher_action_state(ACTION_NONE)
132
 
  , _space_between_icons(5)
133
 
  , _icon_image_size(48)
134
 
  , _icon_image_size_delta(6)
135
 
  , _icon_glow_size(62)
136
 
  , _icon_size(_icon_image_size + _icon_image_size_delta)
137
 
  , _dnd_delta_y(0)
138
 
  , _dnd_delta_x(0)
139
 
  , _postreveal_mousemove_delta_x(0)
140
 
  , _postreveal_mousemove_delta_y(0)
141
 
  , _launcher_drag_delta(0)
142
 
  , _launcher_drag_delta_max(0)
143
 
  , _launcher_drag_delta_min(0)
144
 
  , _enter_y(0)
145
 
  , _last_button_press(0)
146
 
  , _drag_out_delta_x(0.0f)
147
 
  , _drag_gesture_ongoing(false)
148
 
  , _last_reveal_progress(0.0f)
149
 
  , _selection_atom(0)
150
 
  , icon_renderer(std::make_shared<ui::IconRenderer>())
151
 
{
152
 
  m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
153
 
  icon_renderer->monitor = monitor();
154
 
 
155
 
  bg_effect_helper_.owner = this;
156
 
  bg_effect_helper_.enabled = false;
157
 
 
158
 
  SetCompositionLayout(m_Layout);
159
 
  CaptureMouseDownAnyWhereElse(true);
160
 
  SetAcceptKeyNavFocusOnMouseDown(false);
161
 
  SetAcceptMouseWheelEvent(true);
162
 
  SetDndEnabled(false, true);
163
 
 
164
 
  _hide_machine.should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden));
165
 
  _hide_machine.reveal_progress.changed.connect([&](float value) { EnsureAnimation(); });
166
 
  _hover_machine.should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover));
167
 
 
168
 
  mouse_down.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
169
 
  mouse_up.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
170
 
  mouse_drag.connect(sigc::mem_fun(this, &Launcher::RecvMouseDrag));
171
 
  mouse_enter.connect(sigc::mem_fun(this, &Launcher::RecvMouseEnter));
172
 
  mouse_leave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave));
173
 
  mouse_move.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove));
174
 
  mouse_wheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel));
175
 
  //OnEndFocus.connect   (sigc::mem_fun (this, &Launcher::exitKeyNavMode));
176
 
 
177
 
  QuicklistManager& ql_manager = *(QuicklistManager::Default());
178
 
  ql_manager.quicklist_opened.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistOpened));
179
 
  ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
180
 
 
181
 
  WindowManager& wm = WindowManager::Default();
182
 
  wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
183
 
  wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
184
 
  wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
185
 
  wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
186
 
  wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::EnsureAnimation));
187
 
 
188
 
  // 0 out timers to avoid wonky startups
189
 
  for (int i = 0; i < TIME_LAST; ++i)
190
 
  {
191
 
    _times[i].tv_sec = 0;
192
 
    _times[i].tv_nsec = 0;
193
 
  }
194
 
 
195
 
  ubus_.RegisterInterest(UBUS_OVERLAY_SHOWN, sigc::mem_fun(this, &Launcher::OnOverlayShown));
196
 
  ubus_.RegisterInterest(UBUS_OVERLAY_HIDDEN, sigc::mem_fun(this, &Launcher::OnOverlayHidden));
197
 
  ubus_.RegisterInterest(UBUS_LAUNCHER_LOCK_HIDE, sigc::mem_fun(this, &Launcher::OnLockHideChanged));
198
 
 
199
 
  icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons);
200
 
 
201
 
  TextureCache& cache = TextureCache::GetDefault();
202
 
  launcher_sheen_ = cache.FindTexture("dash_sheen.png");
203
 
  launcher_pressure_effect_ = cache.FindTexture("launcher_pressure_effect.png");
204
 
 
205
 
  options.changed.connect(sigc::mem_fun(this, &Launcher::OnOptionsChanged));
206
 
  monitor.changed.connect(sigc::mem_fun(this, &Launcher::OnMonitorChanged));
207
 
}
208
 
 
209
 
/* Introspection */
210
 
std::string Launcher::GetName() const
211
 
{
212
 
  return "Launcher";
213
 
}
214
 
 
215
 
#ifdef NUX_GESTURES_SUPPORT
216
 
void Launcher::OnDragStart(const nux::GestureEvent &event)
217
 
{
218
 
  _drag_gesture_ongoing = true;
219
 
  if (_hidden)
220
 
  {
221
 
    _drag_out_delta_x = 0.0f;
222
 
  }
223
 
  else
224
 
  {
225
 
    _drag_out_delta_x = DRAG_OUT_PIXELS;
226
 
    _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
227
 
  }
228
 
}
229
 
 
230
 
void Launcher::OnDragUpdate(const nux::GestureEvent &event)
231
 
{
232
 
  _drag_out_delta_x =
233
 
    CLAMP(_drag_out_delta_x + event.GetDelta().x, 0.0f, DRAG_OUT_PIXELS);
234
 
  EnsureAnimation();
235
 
}
236
 
 
237
 
void Launcher::OnDragFinish(const nux::GestureEvent &event)
238
 
{
239
 
  if (_drag_out_delta_x >= DRAG_OUT_PIXELS - 90.0f)
240
 
    _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true);
241
 
  TimeUtil::SetTimeStruct(&_times[TIME_DRAG_OUT],
242
 
                          &_times[TIME_DRAG_OUT],
243
 
                          ANIM_DURATION_SHORT);
244
 
  EnsureAnimation();
245
 
  _drag_gesture_ongoing = false;
246
 
}
247
 
#endif
248
 
 
249
 
void Launcher::AddProperties(GVariantBuilder* builder)
250
 
{
251
 
  timespec current;
252
 
  clock_gettime(CLOCK_MONOTONIC, &current);
253
 
 
254
 
  unity::variant::BuilderWrapper(builder)
255
 
  .add(GetAbsoluteGeometry())
256
 
  .add("hover-progress", GetHoverProgress(current))
257
 
  .add("dnd-exit-progress", DnDExitProgress(current))
258
 
  .add("autohide-progress", AutohideProgress(current))
259
 
  .add("dnd-delta", _dnd_delta_y)
260
 
  .add("hovered", _hovered)
261
 
  .add("hidemode", options()->hide_mode)
262
 
  .add("hidden", _hidden)
263
 
  .add("is_showing", ! _hidden)
264
 
  .add("monitor", monitor())
265
 
  .add("quicklist-open", _hide_machine.GetQuirk(LauncherHideMachine::QUICKLIST_OPEN))
266
 
  .add("hide-quirks", _hide_machine.DebugHideQuirks())
267
 
  .add("hover-quirks", _hover_machine.DebugHoverQuirks())
268
 
  .add("icon-size", _icon_size)
269
 
  .add("shortcuts_shown", _shortcuts_shown)
270
 
  .add("tooltip-shown", _active_tooltip != nullptr);
271
 
}
272
 
 
273
 
void Launcher::SetMousePosition(int x, int y)
274
 
{
275
 
  bool beyond_drag_threshold = MouseBeyondDragThreshold();
276
 
  _mouse_position = nux::Point2(x, y);
277
 
 
278
 
  if (beyond_drag_threshold != MouseBeyondDragThreshold())
279
 
    TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT);
280
 
 
281
 
  EnsureScrollTimer();
282
 
}
283
 
 
284
 
void Launcher::SetStateMouseOverLauncher(bool over_launcher)
285
 
{
286
 
  _hide_machine.SetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER, over_launcher);
287
 
  _hide_machine.SetQuirk(LauncherHideMachine::REVEAL_PRESSURE_PASS, false);
288
 
  _hover_machine.SetQuirk(LauncherHoverMachine::MOUSE_OVER_LAUNCHER, over_launcher);
289
 
  tooltip_manager_.SetHover(over_launcher);
290
 
}
291
 
 
292
 
void Launcher::SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon)
293
 
{
294
 
  if (_icon_under_mouse == icon)
295
 
    return;
296
 
 
297
 
  if (_icon_under_mouse)
298
 
    _icon_under_mouse->mouse_leave.emit(monitor);
299
 
  if (icon)
300
 
    icon->mouse_enter.emit(monitor);
301
 
 
302
 
  _icon_under_mouse = icon;
303
 
}
304
 
 
305
 
bool Launcher::MouseBeyondDragThreshold() const
306
 
{
307
 
  if (GetActionState() == ACTION_DRAG_ICON)
308
 
    return _mouse_position.x > GetGeometry().width + _icon_size / 2;
309
 
  return false;
310
 
}
311
 
 
312
 
/* Render Layout Logic */
313
 
float Launcher::GetHoverProgress(struct timespec const& current) const
314
 
{
315
 
  if (_hovered)
316
 
    return CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_ENTER])) / (float) ANIM_DURATION, 0.0f, 1.0f);
317
 
  else
318
 
    return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_LEAVE])) / (float) ANIM_DURATION, 0.0f, 1.0f);
319
 
}
320
 
 
321
 
float Launcher::DnDExitProgress(struct timespec const& current) const
322
 
{
323
 
  return pow(1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_END])) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f), 2);
324
 
}
325
 
 
326
 
float Launcher::DragOutProgress(struct timespec const& current) const
327
 
{
328
 
  float timeout = CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_OUT])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
329
 
  float progress = CLAMP(_drag_out_delta_x / DRAG_OUT_PIXELS, 0.0f, 1.0f);
330
 
 
331
 
  if (_drag_gesture_ongoing
332
 
      || _hide_machine.GetQuirk(LauncherHideMachine::MT_DRAG_OUT))
333
 
    return progress;
334
 
  else
335
 
    return progress * (1.0f - timeout);
336
 
}
337
 
 
338
 
float Launcher::AutohideProgress(struct timespec const& current) const
339
 
{
340
 
  // time-based progress (full scale or finish the TRIGGER_AUTOHIDE_MIN -> 0.00f on bfb)
341
 
  float animation_progress;
342
 
  animation_progress = CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_AUTOHIDE])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
343
 
  if (_hidden)
344
 
    return animation_progress;
345
 
  else
346
 
    return 1.0f - animation_progress;
347
 
}
348
 
 
349
 
float Launcher::DragHideProgress(struct timespec const& current) const
350
 
{
351
 
  if (_drag_edge_touching)
352
 
    return CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f);
353
 
  else
354
 
    return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f);
355
 
}
356
 
 
357
 
float Launcher::DragThresholdProgress(struct timespec const& current) const
358
 
{
359
 
  if (MouseBeyondDragThreshold())
360
 
    return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
361
 
  else
362
 
    return CLAMP((float)(unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
363
 
}
364
 
 
365
 
void Launcher::EnsureAnimation()
366
 
{
367
 
  QueueDraw();
368
 
}
369
 
 
370
 
bool Launcher::IconNeedsAnimation(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
371
 
{
372
 
  struct timespec time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
373
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION_SHORT)
374
 
    return true;
375
 
 
376
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING);
377
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION_SHORT)
378
 
    return true;
379
 
 
380
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
381
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2))
382
 
    return true;
383
 
 
384
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);
385
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2))
386
 
    return true;
387
 
 
388
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE);
389
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2))
390
 
    return true;
391
 
 
392
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED);
393
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
394
 
    return true;
395
 
 
396
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
397
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
398
 
    return true;
399
 
 
400
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);
401
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION_LONG)
402
 
    return true;
403
 
 
404
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED);
405
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
406
 
    return true;
407
 
 
408
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS);
409
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
410
 
    return true;
411
 
 
412
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM);
413
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
414
 
    return true;
415
 
 
416
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT);
417
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION_SHORT_SHORT)
418
 
    return true;
419
 
 
420
 
  time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_PRELIGHT);
421
 
  if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
422
 
    return true;
423
 
 
424
 
  return false;
425
 
}
426
 
 
427
 
bool Launcher::AnimationInProgress() const
428
 
{
429
 
  // performance here can be improved by caching the longer remaining animation found and short circuiting to that each time
430
 
  // this way extra checks may be avoided
431
 
 
432
 
  if (_last_reveal_progress != _hide_machine.reveal_progress)
433
 
    return true;
434
 
 
435
 
  // short circuit to avoid unneeded calculations
436
 
  struct timespec current;
437
 
  clock_gettime(CLOCK_MONOTONIC, &current);
438
 
 
439
 
  // hover in animation
440
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_ENTER]) < ANIM_DURATION)
441
 
    return true;
442
 
 
443
 
  // hover out animation
444
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_LEAVE]) < ANIM_DURATION)
445
 
    return true;
446
 
 
447
 
  // drag end animation
448
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_END]) < ANIM_DURATION_LONG)
449
 
    return true;
450
 
 
451
 
  // hide animation (time only), position is trigger manually on the bfb
452
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_AUTOHIDE]) < ANIM_DURATION_SHORT)
453
 
    return true;
454
 
 
455
 
  // collapse animation on DND out of launcher space
456
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_THRESHOLD]) < ANIM_DURATION_SHORT)
457
 
    return true;
458
 
 
459
 
  // hide animation for dnd
460
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_EDGE_TOUCH]) < ANIM_DURATION * 6)
461
 
    return true;
462
 
 
463
 
  // restore from drag_out animation
464
 
  if (unity::TimeUtil::TimeDelta(&current, &_times[TIME_DRAG_OUT]) < ANIM_DURATION_SHORT)
465
 
    return true;
466
 
 
467
 
  // animations happening on specific icons
468
 
  for (auto const &icon : *_model)
469
 
    if (IconNeedsAnimation(icon, current))
470
 
      return true;
471
 
 
472
 
  return false;
473
 
}
474
 
 
475
 
/* Min is when you are on the trigger */
476
 
float Launcher::GetAutohidePositionMin() const
477
 
{
478
 
  if (options()->auto_hide_animation() == SLIDE_ONLY || options()->auto_hide_animation() == FADE_AND_SLIDE)
479
 
    return 0.35f;
480
 
  else
481
 
    return 0.25f;
482
 
}
483
 
/* Max is the initial state over the bfb */
484
 
float Launcher::GetAutohidePositionMax() const
485
 
{
486
 
  if (options()->auto_hide_animation() == SLIDE_ONLY || options()->auto_hide_animation() == FADE_AND_SLIDE)
487
 
    return 1.00f;
488
 
  else
489
 
    return 0.75f;
490
 
}
491
 
 
492
 
 
493
 
float Launcher::IconVisibleProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
494
 
{
495
 
  if (!icon->IsVisibleOnMonitor(monitor))
496
 
    return 0.0f;
497
 
 
498
 
  if (icon->GetIconType() == AbstractLauncherIcon::IconType::HUD)
499
 
  {
500
 
    return icon->IsVisible() ? 1.0f : 0.0f;
501
 
  }
502
 
 
503
 
  if (icon->IsVisible())
504
 
  {
505
 
    struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
506
 
    DeltaTime enter_ms = unity::TimeUtil::TimeDelta(&current, &icon_visible_time);
507
 
    return CLAMP((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
508
 
  }
509
 
  else
510
 
  {
511
 
    struct timespec icon_hide_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
512
 
    DeltaTime hide_ms = unity::TimeUtil::TimeDelta(&current, &icon_hide_time);
513
 
    return 1.0f - CLAMP((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
514
 
  }
515
 
}
516
 
 
517
 
void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current)
518
 
{
519
 
  AbstractLauncherIcon::Ptr const& anchor = MouseIconIntersection(x, _enter_y);
520
 
 
521
 
  if (anchor)
522
 
  {
523
 
    float position = y;
524
 
    for (AbstractLauncherIcon::Ptr const& model_icon : *_model)
525
 
    {
526
 
      if (model_icon == anchor)
527
 
      {
528
 
        position += _icon_size / 2;
529
 
        _launcher_drag_delta = _enter_y - position;
530
 
 
531
 
        if (position + _icon_size / 2 + _launcher_drag_delta > geo.height)
532
 
          _launcher_drag_delta -= (position + _icon_size / 2 + _launcher_drag_delta) - geo.height;
533
 
 
534
 
        break;
535
 
      }
536
 
      position += (_icon_size + _space_between_icons) * IconVisibleProgress(model_icon, current);
537
 
    }
538
 
  }
539
 
}
540
 
 
541
 
float Launcher::IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
542
 
{
543
 
  struct timespec icon_present_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED);
544
 
  DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &icon_present_time);
545
 
  float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
546
 
 
547
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PRESENTED))
548
 
    return result;
549
 
  else
550
 
    return 1.0f - result;
551
 
}
552
 
 
553
 
float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
554
 
{
555
 
  struct timespec icon_unfold_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
556
 
  DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &icon_unfold_time);
557
 
  float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
558
 
 
559
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED))
560
 
    return result;
561
 
  else
562
 
    return 1.0f - result;
563
 
}
564
 
 
565
 
float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
566
 
{
567
 
  struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);
568
 
  DeltaTime urgent_ms = unity::TimeUtil::TimeDelta(&current, &urgent_time);
569
 
  float result;
570
 
 
571
 
  if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
572
 
    result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_SHORT * WIGGLE_CYCLES), 0.0f, 1.0f);
573
 
  else
574
 
    result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
575
 
 
576
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
577
 
    return result;
578
 
  else
579
 
    return 1.0f - result;
580
 
}
581
 
 
582
 
float Launcher::IconDropDimValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
583
 
{
584
 
  struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM);
585
 
  DeltaTime dim_ms = unity::TimeUtil::TimeDelta(&current, &dim_time);
586
 
  float result = CLAMP((float) dim_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
587
 
 
588
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DROP_DIM))
589
 
    return 1.0f - result;
590
 
  else
591
 
    return result;
592
 
}
593
 
 
594
 
float Launcher::IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
595
 
{
596
 
  struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT);
597
 
  DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &dim_time);
598
 
  float result = CLAMP((float) ms / (float) ANIM_DURATION_SHORT_SHORT, 0.0f, 1.0f);
599
 
 
600
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT))
601
 
    return 1.0f - result;
602
 
  else
603
 
    return result;
604
 
}
605
 
 
606
 
float Launcher::IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
607
 
{
608
 
  struct timespec shimmer_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);
609
 
  DeltaTime shimmer_ms = unity::TimeUtil::TimeDelta(&current, &shimmer_time);
610
 
  return CLAMP((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
611
 
}
612
 
 
613
 
float Launcher::IconCenterTransitionProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
614
 
{
615
 
  struct timespec save_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED);
616
 
  DeltaTime save_ms = unity::TimeUtil::TimeDelta(&current, &save_time);
617
 
  return CLAMP((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
618
 
}
619
 
 
620
 
float Launcher::IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
621
 
{
622
 
  if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
623
 
    return 1.0f; // we are full on in a normal condition
624
 
 
625
 
  double urgent_progress = (double) IconUrgentProgress(icon, current);
626
 
  return 0.5f + (float)(std::cos(M_PI * (float)(URGENT_BLINKS * 2) * urgent_progress)) * 0.5f;
627
 
}
628
 
 
629
 
float Launcher::IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const &current) const
630
 
{
631
 
  struct timespec pulse_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE);
632
 
  DeltaTime pulse_ms = unity::TimeUtil::TimeDelta(&current, &pulse_time);
633
 
  double pulse_progress = (double) CLAMP((float) pulse_ms / (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), 0.0f, 1.0f);
634
 
 
635
 
  if (pulse_progress == 1.0f)
636
 
    icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, false);
637
 
 
638
 
  return 0.5f + (float) (std::cos(M_PI * 2.0 * pulse_progress)) * 0.5f;
639
 
}
640
 
 
641
 
float Launcher::IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
642
 
{
643
 
  if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
644
 
    return 0.0f; // we are full on in a normal condition
645
 
 
646
 
  double urgent_progress = (double) IconUrgentProgress(icon, current);
647
 
  return 0.3f * (float)(std::sin(M_PI * (float)(WIGGLE_CYCLES * 2) * urgent_progress)) * 0.5f;
648
 
}
649
 
 
650
 
float Launcher::IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
651
 
{
652
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
653
 
    return 1.0f;
654
 
 
655
 
  if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING))
656
 
    return 1.0f;
657
 
 
658
 
  struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
659
 
  DeltaTime starting_ms = unity::TimeUtil::TimeDelta(&current, &starting_time);
660
 
  double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * STARTING_BLINK_LAMBDA), 0.0f, 1.0f);
661
 
  double val = IsBackLightModeToggles() ? 3.0f : 4.0f;
662
 
  return 1.0f-(0.5f + (float)(std::cos(M_PI * val * starting_progress)) * 0.5f);
663
 
}
664
 
 
665
 
float Launcher::IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
666
 
{
667
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
668
 
    return 1.0f;
669
 
 
670
 
  if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING))
671
 
    return 1.0f;
672
 
 
673
 
  struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
674
 
  DeltaTime starting_ms = unity::TimeUtil::TimeDelta(&current, &starting_time);
675
 
  double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f);
676
 
 
677
 
  if (starting_progress == 1.0f && !icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
678
 
  {
679
 
    icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false);
680
 
    icon->ResetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
681
 
  }
682
 
 
683
 
  return 1.0f-(0.5f + (float)(std::cos(M_PI * (float)(MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
684
 
}
685
 
 
686
 
float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
687
 
{
688
 
  float result = 0.0f;
689
 
 
690
 
  struct timespec running_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING);
691
 
  DeltaTime running_ms = unity::TimeUtil::TimeDelta(&current, &running_time);
692
 
  float running_progress = CLAMP((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
693
 
 
694
 
  if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
695
 
    running_progress = 1.0f - running_progress;
696
 
 
697
 
  // After we finish a fade in from running, we can reset the quirk
698
 
  if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
699
 
    icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false);
700
 
 
701
 
  float backlight_strength;
702
 
  if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
703
 
    backlight_strength = BACKLIGHT_STRENGTH;
704
 
  else if (IsBackLightModeToggles())
705
 
    backlight_strength = BACKLIGHT_STRENGTH * running_progress;
706
 
  else
707
 
    backlight_strength = 0.0f;
708
 
 
709
 
  switch (options()->launch_animation())
710
 
  {
711
 
    case LAUNCH_ANIMATION_NONE:
712
 
      result = backlight_strength;
713
 
      break;
714
 
    case LAUNCH_ANIMATION_BLINK:
715
 
      if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
716
 
        result = IconStartingBlinkValue(icon, current);
717
 
      else if (options()->backlight_mode() == BACKLIGHT_ALWAYS_OFF)
718
 
        result = 1.0f - IconStartingBlinkValue(icon, current);
719
 
      else
720
 
        result = backlight_strength; // The blink concept is a failure in this case (it just doesn't work right)
721
 
      break;
722
 
    case LAUNCH_ANIMATION_PULSE:
723
 
      if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
724
 
        icon->ResetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
725
 
 
726
 
      result = backlight_strength;
727
 
      if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
728
 
        result *= CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f);
729
 
      else if (IsBackLightModeToggles())
730
 
        result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconStartingPulseValue(icon, current));
731
 
      else
732
 
        result = 1.0f - CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f);
733
 
      break;
734
 
  }
735
 
 
736
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE))
737
 
  {
738
 
    if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
739
 
      result *= CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f);
740
 
    else if (options()->backlight_mode() == BACKLIGHT_NORMAL)
741
 
      result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconPulseOnceValue(icon, current));
742
 
    else
743
 
      result = 1.0f - CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f);
744
 
  }
745
 
 
746
 
  // urgent serves to bring the total down only
747
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT) && options()->urgent_animation() == URGENT_ANIMATION_PULSE)
748
 
    result *= 0.2f + 0.8f * IconUrgentPulseValue(icon, current);
749
 
 
750
 
  return result;
751
 
}
752
 
 
753
 
float Launcher::IconProgressBias(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
754
 
{
755
 
  struct timespec icon_progress_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS);
756
 
  DeltaTime ms = unity::TimeUtil::TimeDelta(&current, &icon_progress_time);
757
 
  float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
758
 
 
759
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PROGRESS))
760
 
    return -1.0f + result;
761
 
  else
762
 
    return result;
763
 
}
764
 
 
765
 
bool Launcher::IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const
766
 
{
767
 
  if (options()->backlight_mode() == BACKLIGHT_EDGE_TOGGLE)
768
 
    return true;
769
 
 
770
 
  if (options()->backlight_mode() == BACKLIGHT_NORMAL_EDGE_TOGGLE && !icon->WindowVisibleOnMonitor(monitor))
771
 
    return true;
772
 
 
773
 
  return false;
774
 
}
775
 
 
776
 
void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current, RenderArg& arg)
777
 
{
778
 
  float desat_value = IconDesatValue(icon, current);
779
 
  arg.icon                = icon.GetPointer();
780
 
  arg.alpha               = 0.2f + 0.8f * desat_value;
781
 
  arg.saturation          = desat_value;
782
 
  arg.colorify            = nux::color::White;
783
 
  arg.running_arrow       = icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING);
784
 
  arg.running_colored     = icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT);
785
 
  arg.draw_edge_only      = IconDrawEdgeOnly(icon);
786
 
  arg.active_colored      = false;
787
 
  arg.skip                = false;
788
 
  arg.stick_thingy        = false;
789
 
  arg.keyboard_nav_hl     = false;
790
 
  arg.progress_bias       = IconProgressBias(icon, current);
791
 
  arg.progress            = CLAMP(icon->GetProgress(), 0.0f, 1.0f);
792
 
  arg.draw_shortcut       = _shortcuts_shown && !_hide_machine.GetQuirk(LauncherHideMachine::PLACES_VISIBLE);
793
 
  arg.system_item         = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME    ||
794
 
                            icon->GetIconType() == AbstractLauncherIcon::IconType::HUD;
795
 
  arg.colorify_background = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME    ||
796
 
                            icon->GetIconType() == AbstractLauncherIcon::IconType::HUD     ||
797
 
                            icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH   ||
798
 
                            icon->GetIconType() == AbstractLauncherIcon::IconType::DESKTOP ||
799
 
                            icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE  ||
800
 
                            icon->GetIconType() == AbstractLauncherIcon::IconType::EXPO;
801
 
 
802
 
  // trying to protect against flickering when icon is dragged from dash LP: #863230
803
 
  if (arg.alpha < 0.2)
804
 
  {
805
 
    arg.alpha = 0.2;
806
 
    arg.saturation = 0.0;
807
 
  }
808
 
 
809
 
  arg.active_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE);
810
 
 
811
 
  /* BFB or HUD icons don't need the active arrow if the overaly is opened
812
 
   * in another monitor */
813
 
  if (arg.active_arrow && !IsOverlayOpen() &&
814
 
      (icon->GetIconType() == AbstractLauncherIcon::IconType::HOME ||
815
 
       icon->GetIconType() == AbstractLauncherIcon::IconType::HUD))
816
 
  {
817
 
    arg.active_arrow = false;
818
 
  }
819
 
 
820
 
  if (options()->show_for_all)
821
 
    arg.running_on_viewport = icon->WindowVisibleOnViewport();
822
 
  else
823
 
    arg.running_on_viewport = icon->WindowVisibleOnMonitor(monitor);
824
 
 
825
 
  guint64 shortcut = icon->GetShortcut();
826
 
  if (shortcut > 32)
827
 
    arg.shortcut_label = (char) shortcut;
828
 
  else
829
 
    arg.shortcut_label = 0;
830
 
 
831
 
  // we dont need to show strays
832
 
  if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
833
 
  {
834
 
    arg.window_indicators = 0;
835
 
  }
836
 
  else
837
 
  {
838
 
    if (options()->show_for_all)
839
 
      arg.window_indicators = std::max<int> (icon->WindowsOnViewport().size(), 1);
840
 
    else
841
 
      arg.window_indicators = std::max<int> (icon->WindowsForMonitor(monitor).size(), 1);
842
 
 
843
 
    if (icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH ||
844
 
        icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
845
 
    {
846
 
      // TODO: also these icons should respect the actual windows they have
847
 
      arg.window_indicators = 0;
848
 
    }
849
 
  }
850
 
 
851
 
  arg.backlight_intensity = IconBackgroundIntensity(icon, current);
852
 
  arg.shimmer_progress = IconShimmerProgress(icon, current);
853
 
 
854
 
  float urgent_progress = IconUrgentProgress(icon, current);
855
 
 
856
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
857
 
    urgent_progress = CLAMP(urgent_progress * 3.0f, 0.0f, 1.0f);  // we want to go 3x faster than the urgent normal cycle
858
 
  else
859
 
    urgent_progress = CLAMP(urgent_progress * 3.0f - 2.0f, 0.0f, 1.0f);  // we want to go 3x faster than the urgent normal cycle
860
 
  arg.glow_intensity = urgent_progress;
861
 
 
862
 
  if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT) && options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
863
 
  {
864
 
    arg.rotation.z = IconUrgentWiggleValue(icon, current);
865
 
  }
866
 
 
867
 
  if (IsInKeyNavMode())
868
 
  {
869
 
    if (icon == _model->Selection())
870
 
      arg.keyboard_nav_hl = true;
871
 
  }
872
 
}
873
 
 
874
 
void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon,
875
 
                             RenderArg& arg,
876
 
                             nux::Point3& center,
877
 
                             nux::Geometry const& parent_abs_geo,
878
 
                             float folding_threshold,
879
 
                             float folded_size,
880
 
                             float folded_spacing,
881
 
                             float autohide_offset,
882
 
                             float folded_z_distance,
883
 
                             float animation_neg_rads,
884
 
                             struct timespec const& current)
885
 
{
886
 
  SetupRenderArg(icon, current, arg);
887
 
 
888
 
  // reset z
889
 
  center.z = 0;
890
 
 
891
 
  float size_modifier = IconVisibleProgress(icon, current);
892
 
  if (size_modifier < 1.0f)
893
 
  {
894
 
    arg.alpha *= size_modifier;
895
 
    center.z = 300.0f * (1.0f - size_modifier);
896
 
  }
897
 
 
898
 
  float drop_dim_value = 0.2f + 0.8f * IconDropDimValue(icon, current);
899
 
 
900
 
  if (drop_dim_value < 1.0f)
901
 
    arg.alpha *= drop_dim_value;
902
 
 
903
 
  // trying to protect against flickering when icon is dragged from dash LP: #863230
904
 
  if (arg.alpha < 0.2)
905
 
  {
906
 
    arg.alpha = 0.2;
907
 
    arg.saturation = 0.0;
908
 
  }
909
 
 
910
 
  if (icon == _drag_icon)
911
 
  {
912
 
    if (MouseBeyondDragThreshold())
913
 
      arg.stick_thingy = true;
914
 
 
915
 
    if (GetActionState() == ACTION_DRAG_ICON ||
916
 
        (_drag_window && _drag_window->Animating()) ||
917
 
        icon->GetIconType() == AbstractLauncherIcon::IconType::SPACER)
918
 
    {
919
 
      arg.skip = true;
920
 
    }
921
 
 
922
 
    size_modifier *= DragThresholdProgress(current);
923
 
  }
924
 
 
925
 
  if (size_modifier <= 0.0f)
926
 
    arg.skip = true;
927
 
 
928
 
  // goes for 0.0f when fully unfolded, to 1.0f folded
929
 
  float folding_progress = CLAMP((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
930
 
  float unfold_progress = IconUnfoldProgress(icon, current);
931
 
 
932
 
  folding_progress *= 1.0f - unfold_progress;
933
 
 
934
 
  float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
935
 
  float icon_hide_offset = autohide_offset;
936
 
 
937
 
  float present_progress = IconPresentProgress(icon, current);
938
 
  icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency());
939
 
 
940
 
  // icon is crossing threshold, start folding
941
 
  center.z += folded_z_distance * folding_progress;
942
 
  arg.rotation.x = animation_neg_rads * folding_progress;
943
 
 
944
 
  float spacing_overlap = CLAMP((float)(center.y + (2.0f * half_size * size_modifier) + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
945
 
  float spacing = (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
946
 
 
947
 
  nux::Point3 centerOffset;
948
 
  float center_transit_progress = IconCenterTransitionProgress(icon, current);
949
 
  if (center_transit_progress <= 1.0f)
950
 
  {
951
 
    int saved_center = icon->GetSavedCenter(monitor).y - parent_abs_geo.y;
952
 
    centerOffset.y = (saved_center - (center.y + (half_size * size_modifier))) * (1.0f - center_transit_progress);
953
 
  }
954
 
 
955
 
  center.y += half_size * size_modifier;   // move to center
956
 
 
957
 
  arg.render_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y + centerOffset.y), roundf(center.z));
958
 
  arg.logical_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y), roundf(center.z));
959
 
 
960
 
  icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)), monitor, parent_abs_geo);
961
 
 
962
 
  // FIXME: this is a hack, to avoid that we set the target to the end of the icon
963
 
  if (!_initial_drag_animation && icon == _drag_icon && _drag_window && _drag_window->Animating())
964
 
  {
965
 
    auto const& icon_center = _drag_icon->GetCenter(monitor);
966
 
    _drag_window->SetAnimationTarget(icon_center.x, icon_center.y);
967
 
  }
968
 
 
969
 
  center.y += (half_size * size_modifier) + spacing;   // move to end
970
 
}
971
 
 
972
 
float Launcher::DragLimiter(float x)
973
 
{
974
 
  float result = (1 - std::pow(159.0 / 160,  std::abs(x))) * 160;
975
 
 
976
 
  if (x >= 0.0f)
977
 
    return result;
978
 
  return -result;
979
 
}
980
 
 
981
 
nux::Color FullySaturateColor (nux::Color color)
982
 
{
983
 
  float max = std::max<float>(color.red, std::max<float>(color.green, color.blue));
984
 
 
985
 
  if (max > 0.0f)
986
 
    color = color * (1.0f / max);
987
 
 
988
 
  return color;
989
 
}
990
 
 
991
 
void Launcher::RenderArgs(std::list<RenderArg> &launcher_args,
992
 
                          nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo)
993
 
{
994
 
  nux::Geometry const& geo = GetGeometry();
995
 
  LauncherModel::iterator it;
996
 
  nux::Point3 center;
997
 
  struct timespec current;
998
 
  clock_gettime(CLOCK_MONOTONIC, &current);
999
 
 
1000
 
  nux::Color const& colorify = FullySaturateColor(options()->background_color);
1001
 
 
1002
 
  float hover_progress = GetHoverProgress(current);
1003
 
  float folded_z_distance = _folded_z_distance * (1.0f - hover_progress);
1004
 
  float animation_neg_rads = _neg_folded_angle * (1.0f - hover_progress);
1005
 
 
1006
 
  float folding_constant = 0.25f;
1007
 
  float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress);
1008
 
 
1009
 
  float folded_size = _icon_size * folding_not_constant;
1010
 
  float folded_spacing = _space_between_icons * folding_not_constant;
1011
 
 
1012
 
  center.x = geo.width / 2;
1013
 
  center.y = _space_between_icons;
1014
 
  center.z = 0;
1015
 
 
1016
 
  int launcher_height = geo.height;
1017
 
 
1018
 
  // compute required height of launcher AND folding threshold
1019
 
  float sum = 0.0f + center.y;
1020
 
  float folding_threshold = launcher_height - _icon_size / 2.5f;
1021
 
  for (it = _model->begin(); it != _model->end(); ++it)
1022
 
  {
1023
 
    float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
1024
 
    sum += height;
1025
 
 
1026
 
    // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";
1027
 
    float magic_constant = 1.3f;
1028
 
 
1029
 
    float unfold_progress = IconUnfoldProgress(*it, current);
1030
 
    folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * unfold_progress);
1031
 
  }
1032
 
 
1033
 
  if (sum - _space_between_icons <= launcher_height)
1034
 
    folding_threshold = launcher_height;
1035
 
 
1036
 
  float autohide_offset = 0.0f;
1037
 
  *launcher_alpha = 1.0f;
1038
 
  if (options()->hide_mode != LAUNCHER_HIDE_NEVER || _hide_machine.GetQuirk(LauncherHideMachine::LOCK_HIDE))
1039
 
  {
1040
 
 
1041
 
    float autohide_progress = AutohideProgress(current) * (1.0f - DragOutProgress(current));
1042
 
    if (options()->auto_hide_animation() == FADE_ONLY)
1043
 
    {
1044
 
      *launcher_alpha = 1.0f - autohide_progress;
1045
 
    }
1046
 
    else
1047
 
    {
1048
 
      if (autohide_progress > 0.0f)
1049
 
      {
1050
 
        autohide_offset -= geo.width * autohide_progress;
1051
 
        if (options()->auto_hide_animation() == FADE_AND_SLIDE)
1052
 
          *launcher_alpha = 1.0f - 0.5f * autohide_progress;
1053
 
      }
1054
 
    }
1055
 
  }
1056
 
 
1057
 
  float drag_hide_progress = DragHideProgress(current);
1058
 
  if (options()->hide_mode != LAUNCHER_HIDE_NEVER && drag_hide_progress > 0.0f)
1059
 
  {
1060
 
    autohide_offset -= geo.width * 0.25f * drag_hide_progress;
1061
 
 
1062
 
    if (drag_hide_progress >= 1.0f)
1063
 
      _hide_machine.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, true);
1064
 
  }
1065
 
 
1066
 
  // Inform the painter where to paint the box
1067
 
  box_geo = geo;
1068
 
 
1069
 
  if (options()->hide_mode != LAUNCHER_HIDE_NEVER || _hide_machine.GetQuirk(LauncherHideMachine::LOCK_HIDE))
1070
 
    box_geo.x += autohide_offset;
1071
 
 
1072
 
  /* Why we need last_geo? It stores the last box_geo (note: as it is a static variable,
1073
 
   * it is initialized only first time). Infact we call SetDndDelta that calls MouseIconIntersection
1074
 
   * that uses values (HitArea) that are computed in UpdateIconXForm.
1075
 
   * The problem is that in DrawContent we calls first RenderArgs, then UpdateIconXForm. Just
1076
 
   * use last_geo to hack this problem.
1077
 
   */
1078
 
  static nux::Geometry last_geo = box_geo;
1079
 
 
1080
 
  // this happens on hover, basically its a flag and a value in one, we translate this into a dnd offset
1081
 
  if (_enter_y != 0 && _enter_y + _icon_size / 2 > folding_threshold)
1082
 
    SetDndDelta(last_geo.x + last_geo.width / 2, center.y, geo, current);
1083
 
 
1084
 
  // Update the last_geo value.
1085
 
  last_geo = box_geo;
1086
 
  _enter_y = 0;
1087
 
 
1088
 
  
1089
 
  // logically dnd exit only restores to the clamped ranges
1090
 
  // hover_progress restores to 0
1091
 
  _launcher_drag_delta_max = 0.0f;
1092
 
  _launcher_drag_delta_min = MIN(0.0f, launcher_height - sum);
1093
 
 
1094
 
  if (hover_progress > 0.0f && _launcher_drag_delta != 0)
1095
 
  {
1096
 
    float delta_y = _launcher_drag_delta;
1097
 
 
1098
 
    if (_launcher_drag_delta > _launcher_drag_delta_max)
1099
 
      delta_y = _launcher_drag_delta_max + DragLimiter(delta_y - _launcher_drag_delta_max);
1100
 
    else if (_launcher_drag_delta < _launcher_drag_delta_min)
1101
 
      delta_y = _launcher_drag_delta_min + DragLimiter(delta_y - _launcher_drag_delta_min);
1102
 
 
1103
 
    if (GetActionState() != ACTION_DRAG_LAUNCHER)
1104
 
    {
1105
 
      float dnd_progress = DnDExitProgress(current);
1106
 
 
1107
 
      if (_launcher_drag_delta > _launcher_drag_delta_max)
1108
 
        delta_y = _launcher_drag_delta_max + (delta_y - _launcher_drag_delta_max) * dnd_progress;
1109
 
      else if (_launcher_drag_delta < _launcher_drag_delta_min)
1110
 
        delta_y = _launcher_drag_delta_min + (delta_y - _launcher_drag_delta_min) * dnd_progress;
1111
 
 
1112
 
      if (dnd_progress == 0.0f)
1113
 
        _launcher_drag_delta = (int) delta_y;
1114
 
    }
1115
 
 
1116
 
    delta_y *= hover_progress;
1117
 
    center.y += delta_y;
1118
 
    folding_threshold += delta_y;
1119
 
  }
1120
 
  else
1121
 
  {
1122
 
    _launcher_drag_delta = 0;
1123
 
  }
1124
 
 
1125
 
  // The functional position we wish to represent for these icons is not smooth. Rather than introducing
1126
 
  // special casing to represent this, we use MIN/MAX functions. This helps ensure that even though our
1127
 
  // function is not smooth it is continuous, which is more important for our visual representation (icons
1128
 
  // wont start jumping around).  As a general rule ANY if () statements that modify center.y should be seen
1129
 
  // as bugs.
1130
 
  for (it = _model->main_begin(); it != _model->main_end(); ++it)
1131
 
  {
1132
 
    RenderArg arg;
1133
 
    AbstractLauncherIcon::Ptr const& icon = *it;
1134
 
    FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing,
1135
 
                  autohide_offset, folded_z_distance, animation_neg_rads, current);
1136
 
    arg.colorify = colorify;
1137
 
    launcher_args.push_back(arg);
1138
 
  }
1139
 
 
1140
 
  // compute maximum height of shelf
1141
 
  float shelf_sum = 0.0f;
1142
 
  for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it)
1143
 
  {
1144
 
    float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
1145
 
    shelf_sum += height;
1146
 
  }
1147
 
 
1148
 
  // add bottom padding
1149
 
  if (shelf_sum > 0.0f)
1150
 
    shelf_sum += _space_between_icons;
1151
 
 
1152
 
  float shelf_delta = MAX(((launcher_height - shelf_sum) + _space_between_icons) - center.y, 0.0f);
1153
 
  folding_threshold += shelf_delta;
1154
 
  center.y += shelf_delta;
1155
 
 
1156
 
  for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it)
1157
 
  {
1158
 
    RenderArg arg;
1159
 
    AbstractLauncherIcon::Ptr const& icon = *it;
1160
 
 
1161
 
    FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing,
1162
 
                  autohide_offset, folded_z_distance, animation_neg_rads, current);
1163
 
    arg.colorify = colorify;
1164
 
    launcher_args.push_back(arg);
1165
 
  }
1166
 
}
1167
 
 
1168
 
/* End Render Layout Logic */
1169
 
 
1170
 
void Launcher::ForceReveal(bool force_reveal)
1171
 
{
1172
 
  _hide_machine.SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, force_reveal);
1173
 
}
1174
 
 
1175
 
void Launcher::ShowShortcuts(bool show)
1176
 
{
1177
 
  _shortcuts_shown = show;
1178
 
  _hide_machine.SetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE, show);
1179
 
  EnsureAnimation();
1180
 
}
1181
 
 
1182
 
void Launcher::OnLockHideChanged(GVariant *data)
1183
 
{
1184
 
  gboolean enable_lock = FALSE;
1185
 
  g_variant_get(data, "(b)", &enable_lock);
1186
 
 
1187
 
  if (enable_lock)
1188
 
  {
1189
 
    _hide_machine.SetQuirk(LauncherHideMachine::LOCK_HIDE, true);
1190
 
  }
1191
 
  else
1192
 
  {
1193
 
    _hide_machine.SetQuirk(LauncherHideMachine::LOCK_HIDE, false);
1194
 
  }
1195
 
}
1196
 
 
1197
 
void Launcher::DesaturateIcons()
1198
 
{
1199
 
  for (auto icon : *_model)
1200
 
  {
1201
 
    if (icon->GetIconType () != AbstractLauncherIcon::IconType::HOME &&
1202
 
        icon->GetIconType () != AbstractLauncherIcon::IconType::HUD)
1203
 
    {
1204
 
      icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
1205
 
    }
1206
 
 
1207
 
    icon->HideTooltip();
1208
 
  }
1209
 
}
1210
 
 
1211
 
void Launcher::SaturateIcons()
1212
 
{
1213
 
  for (auto icon : *_model)
1214
 
  {
1215
 
    icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
1216
 
  }
1217
 
}
1218
 
 
1219
 
void Launcher::OnOverlayShown(GVariant* data)
1220
 
{
1221
 
  // check the type of overlay
1222
 
  unity::glib::String overlay_identity;
1223
 
  gboolean can_maximise = FALSE;
1224
 
  gint32 overlay_monitor = 0;
1225
 
  int width, height;
1226
 
  g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
1227
 
                &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
1228
 
  std::string identity(overlay_identity.Str());
1229
 
 
1230
 
  LOG_DEBUG(logger) << "Overlay shown: " << identity
1231
 
                    << ", " << (can_maximise ? "can maximise" : "can't maximise")
1232
 
                    << ", on monitor " << overlay_monitor
1233
 
                    << " (for monitor " << monitor() << ")";
1234
 
 
1235
 
  if (overlay_monitor == monitor())
1236
 
  {
1237
 
    if (identity == "dash")
1238
 
    {
1239
 
      _dash_is_open = true;
1240
 
      _hide_machine.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, true);
1241
 
      _hover_machine.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, true);
1242
 
    }
1243
 
    if (identity == "hud")
1244
 
    {
1245
 
      _hud_is_open = true;
1246
 
    }
1247
 
    bg_effect_helper_.enabled = true;
1248
 
    // Don't desaturate icons if the mouse is over the launcher:
1249
 
    if (!_hovered)
1250
 
    {
1251
 
      LOG_DEBUG(logger) << "Desaturate on monitor " << monitor();
1252
 
      DesaturateIcons();
1253
 
    }
1254
 
 
1255
 
    if (_icon_under_mouse)
1256
 
      _icon_under_mouse->HideTooltip();
1257
 
  }
1258
 
  EnsureAnimation();
1259
 
}
1260
 
 
1261
 
void Launcher::OnOverlayHidden(GVariant* data)
1262
 
{
1263
 
  // check the type of overlay
1264
 
  unity::glib::String overlay_identity;
1265
 
  gboolean can_maximise = FALSE;
1266
 
  gint32 overlay_monitor = 0;
1267
 
  int width, height;
1268
 
  g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
1269
 
                &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
1270
 
 
1271
 
  std::string identity = overlay_identity.Str();
1272
 
 
1273
 
  LOG_DEBUG(logger) << "Overlay hidden: " << identity
1274
 
                    << ", " << (can_maximise ? "can maximise" : "can't maximise")
1275
 
                    << ", on monitor " << overlay_monitor
1276
 
                    << " (for monitor" << monitor() << ")";
1277
 
 
1278
 
  if (overlay_monitor == monitor())
1279
 
  {
1280
 
    if (identity == "dash")
1281
 
    {
1282
 
      _hide_machine.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, false);
1283
 
      _hover_machine.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, false);
1284
 
      _dash_is_open = false;
1285
 
    }
1286
 
    else if (identity == "hud")
1287
 
    {
1288
 
      _hud_is_open = false;
1289
 
    }
1290
 
 
1291
 
    // If they are both now shut, then disable the effect helper and saturate the icons.
1292
 
    if (!IsOverlayOpen())
1293
 
    {
1294
 
      bg_effect_helper_.enabled = false;
1295
 
      LOG_DEBUG(logger) << "Saturate on monitor " << monitor();
1296
 
      SaturateIcons();
1297
 
    }
1298
 
  }
1299
 
  EnsureAnimation();
1300
 
 
1301
 
  // as the leave event is no more received when the place is opened
1302
 
  // FIXME: remove when we change the mouse grab strategy in nux
1303
 
  nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
1304
 
  SetStateMouseOverLauncher(GetAbsoluteGeometry().IsInside(pt));
1305
 
}
1306
 
 
1307
 
bool Launcher::IsOverlayOpen() const
1308
 
{
1309
 
  return _dash_is_open || _hud_is_open;
1310
 
}
1311
 
 
1312
 
void Launcher::SetHidden(bool hide_launcher)
1313
 
{
1314
 
  if (hide_launcher == _hidden)
1315
 
    return;
1316
 
 
1317
 
  _hidden = hide_launcher;
1318
 
  _hide_machine.SetQuirk(LauncherHideMachine::LAUNCHER_HIDDEN, hide_launcher);
1319
 
  _hover_machine.SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hide_launcher);
1320
 
 
1321
 
  if (hide_launcher)
1322
 
  {
1323
 
    _hide_machine.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false);
1324
 
    _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
1325
 
    SetStateMouseOverLauncher(false);
1326
 
  }
1327
 
 
1328
 
  _postreveal_mousemove_delta_x = 0;
1329
 
  _postreveal_mousemove_delta_y = 0;
1330
 
 
1331
 
  TimeUtil::SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT);
1332
 
 
1333
 
  if (nux::GetWindowThread()->IsEmbeddedWindow())
1334
 
    _parent->EnableInputWindow(!hide_launcher, launcher::window_title, false, false);
1335
 
 
1336
 
  if (!hide_launcher && GetActionState() == ACTION_DRAG_EXTERNAL)
1337
 
    DndReset();
1338
 
 
1339
 
  EnsureAnimation();
1340
 
 
1341
 
  hidden_changed.emit();
1342
 
}
1343
 
 
1344
 
void Launcher::UpdateChangeInMousePosition(int delta_x, int delta_y)
1345
 
{
1346
 
  _postreveal_mousemove_delta_x += delta_x;
1347
 
  _postreveal_mousemove_delta_y += delta_y;
1348
 
 
1349
 
  // check the state before changing it to avoid uneeded hide calls
1350
 
  if (!_hide_machine.GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) &&
1351
 
     (std::abs(_postreveal_mousemove_delta_x) > MOUSE_DEADZONE ||
1352
 
      std::abs(_postreveal_mousemove_delta_y) > MOUSE_DEADZONE))
1353
 
  {
1354
 
    _hide_machine.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
1355
 
  }
1356
 
}
1357
 
 
1358
 
int Launcher::GetMouseX() const
1359
 
{
1360
 
  return _mouse_position.x;
1361
 
}
1362
 
 
1363
 
int Launcher::GetMouseY() const
1364
 
{
1365
 
  return _mouse_position.y;
1366
 
}
1367
 
 
1368
 
void Launcher::OnPluginStateChanged()
1369
 
{
1370
 
  WindowManager& wm = WindowManager::Default();
1371
 
  _hide_machine.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, wm.IsExpoActive());
1372
 
  _hide_machine.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, wm.IsScaleActive());
1373
 
}
1374
 
 
1375
 
LauncherHideMode Launcher::GetHideMode() const
1376
 
{
1377
 
  return options()->hide_mode;
1378
 
}
1379
 
 
1380
 
/* End Launcher Show/Hide logic */
1381
 
 
1382
 
void Launcher::OnOptionsChanged(Options::Ptr options)
1383
 
{
1384
 
   UpdateOptions(options);
1385
 
   options->option_changed.connect(sigc::mem_fun(this, &Launcher::OnOptionChanged));
1386
 
}
1387
 
 
1388
 
void Launcher::OnOptionChanged()
1389
 
{
1390
 
  UpdateOptions(options());
1391
 
}
1392
 
 
1393
 
void Launcher::OnMonitorChanged(int new_monitor)
1394
 
{
1395
 
  UScreen* uscreen = UScreen::GetDefault();
1396
 
  auto monitor_geo = uscreen->GetMonitorGeometry(new_monitor);
1397
 
  unity::panel::Style &panel_style = panel::Style::Instance();
1398
 
  Resize(nux::Point(monitor_geo.x, monitor_geo.y + panel_style.panel_height),
1399
 
         monitor_geo.height - panel_style.panel_height);
1400
 
  icon_renderer->monitor = new_monitor;
1401
 
}
1402
 
 
1403
 
void Launcher::UpdateOptions(Options::Ptr options)
1404
 
{
1405
 
  SetIconSize(options->tile_size, options->icon_size);
1406
 
  SetHideMode(options->hide_mode);
1407
 
 
1408
 
  ConfigureBarrier();
1409
 
  EnsureAnimation();
1410
 
}
1411
 
 
1412
 
void Launcher::ConfigureBarrier()
1413
 
{
1414
 
  float decay_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .3f) + 1;
1415
 
  float reveal_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .025f) + 1;
1416
 
 
1417
 
  _hide_machine.reveal_pressure = options()->edge_reveal_pressure() * reveal_responsiveness_mult;
1418
 
  _hide_machine.edge_decay_rate = options()->edge_decay_rate() * decay_responsiveness_mult;
1419
 
}
1420
 
 
1421
 
void Launcher::SetHideMode(LauncherHideMode hidemode)
1422
 
{
1423
 
  bool fixed_launcher = (hidemode == LAUNCHER_HIDE_NEVER);
1424
 
  _parent->InputWindowEnableStruts(fixed_launcher);
1425
 
  _hide_machine.SetMode(static_cast<LauncherHideMachine::HideMode>(hidemode));
1426
 
  EnsureAnimation();
1427
 
}
1428
 
 
1429
 
BacklightMode Launcher::GetBacklightMode() const
1430
 
{
1431
 
  return options()->backlight_mode();
1432
 
}
1433
 
 
1434
 
bool Launcher::IsBackLightModeToggles() const
1435
 
{
1436
 
  switch (options()->backlight_mode()) {
1437
 
    case BACKLIGHT_NORMAL:
1438
 
    case BACKLIGHT_EDGE_TOGGLE:
1439
 
    case BACKLIGHT_NORMAL_EDGE_TOGGLE:
1440
 
      return true;
1441
 
    default:
1442
 
      return false;
1443
 
  }
1444
 
}
1445
 
 
1446
 
nux::ObjectPtr<nux::View> const& Launcher::GetActiveTooltip() const
1447
 
{
1448
 
  return _active_tooltip;
1449
 
}
1450
 
 
1451
 
nux::ObjectPtr<LauncherDragWindow> const& Launcher::GetDraggedIcon() const
1452
 
{
1453
 
  return _drag_window;
1454
 
}
1455
 
 
1456
 
void Launcher::SetActionState(LauncherActionState actionstate)
1457
 
{
1458
 
  if (_launcher_action_state == actionstate)
1459
 
    return;
1460
 
 
1461
 
  _launcher_action_state = actionstate;
1462
 
 
1463
 
  _hover_machine.SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE));
1464
 
}
1465
 
 
1466
 
Launcher::LauncherActionState
1467
 
Launcher::GetActionState() const
1468
 
{
1469
 
  return _launcher_action_state;
1470
 
}
1471
 
 
1472
 
void Launcher::SetHover(bool hovered)
1473
 
{
1474
 
  if (hovered == _hovered)
1475
 
    return;
1476
 
 
1477
 
  _hovered = hovered;
1478
 
 
1479
 
  if (_hovered)
1480
 
  {
1481
 
    _enter_y = (int) _mouse_position.y;
1482
 
    TimeUtil::SetTimeStruct(&_times[TIME_ENTER], &_times[TIME_LEAVE], ANIM_DURATION);
1483
 
  }
1484
 
  else
1485
 
  {
1486
 
    TimeUtil::SetTimeStruct(&_times[TIME_LEAVE], &_times[TIME_ENTER], ANIM_DURATION);
1487
 
  }
1488
 
 
1489
 
  if (IsOverlayOpen() && !_hide_machine.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
1490
 
  {
1491
 
    if (hovered && !_hide_machine.GetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE))
1492
 
      SaturateIcons();
1493
 
    else
1494
 
      DesaturateIcons();
1495
 
  }
1496
 
 
1497
 
  EnsureAnimation();
1498
 
}
1499
 
 
1500
 
bool Launcher::MouseOverTopScrollArea()
1501
 
{
1502
 
  return _mouse_position.y < SCROLL_AREA_HEIGHT;
1503
 
}
1504
 
 
1505
 
bool Launcher::MouseOverBottomScrollArea()
1506
 
{
1507
 
  return _mouse_position.y >= GetGeometry().height - SCROLL_AREA_HEIGHT;
1508
 
}
1509
 
 
1510
 
bool Launcher::OnScrollTimeout()
1511
 
{
1512
 
  bool continue_animation = true;
1513
 
  int speed = 0;
1514
 
 
1515
 
  if (IsInKeyNavMode() || !_hovered ||
1516
 
      GetActionState() == ACTION_DRAG_LAUNCHER)
1517
 
  {
1518
 
    continue_animation = false;
1519
 
  }
1520
 
  else if (MouseOverTopScrollArea())
1521
 
  {
1522
 
    if (_launcher_drag_delta >= _launcher_drag_delta_max)
1523
 
      continue_animation = false;
1524
 
    else
1525
 
    {
1526
 
        speed = (SCROLL_AREA_HEIGHT - _mouse_position.y) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
1527
 
        _launcher_drag_delta += speed;
1528
 
    }
1529
 
  }
1530
 
  else if (MouseOverBottomScrollArea())
1531
 
  {
1532
 
    if (_launcher_drag_delta <= _launcher_drag_delta_min)
1533
 
      continue_animation = false;
1534
 
    else
1535
 
    {
1536
 
        speed = ((_mouse_position.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT)) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
1537
 
        _launcher_drag_delta -= speed;
1538
 
    } 
1539
 
  }
1540
 
  else
1541
 
  {
1542
 
    continue_animation = false;
1543
 
  }
1544
 
 
1545
 
  if (continue_animation)
1546
 
  {
1547
 
    EnsureAnimation();
1548
 
  }
1549
 
 
1550
 
  return continue_animation;
1551
 
}
1552
 
 
1553
 
void Launcher::EnsureScrollTimer()
1554
 
{
1555
 
  bool needed = MouseOverTopScrollArea() || MouseOverBottomScrollArea();
1556
 
 
1557
 
  if (needed && !sources_.GetSource(SCROLL_TIMEOUT))
1558
 
  {
1559
 
    sources_.AddTimeout(20, sigc::mem_fun(this, &Launcher::OnScrollTimeout), SCROLL_TIMEOUT);
1560
 
  }
1561
 
  else if (!needed)
1562
 
  {
1563
 
    sources_.Remove(SCROLL_TIMEOUT);
1564
 
  }
1565
 
}
1566
 
 
1567
 
void Launcher::SetIconSize(int tile_size, int icon_size)
1568
 
{
1569
 
  ui::IconRenderer::DestroyShortcutTextures();
1570
 
 
1571
 
  _icon_size = tile_size;
1572
 
  _icon_image_size = icon_size;
1573
 
  _icon_image_size_delta = tile_size - icon_size;
1574
 
  _icon_glow_size = icon_size + 14;
1575
 
 
1576
 
  icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons);
1577
 
 
1578
 
  nux::Geometry const& parent_geo = _parent->GetGeometry();
1579
 
  Resize(nux::Point(parent_geo.x, parent_geo.y), parent_geo.height);
1580
 
}
1581
 
 
1582
 
int Launcher::GetIconSize() const
1583
 
{
1584
 
  return _icon_size;
1585
 
}
1586
 
 
1587
 
void Launcher::Resize(nux::Point const& offset, int height)
1588
 
{
1589
 
  unsigned width = _icon_size + ICON_PADDING * 2 + RIGHT_LINE_WIDTH - 2;
1590
 
  SetMaximumHeight(height);
1591
 
  SetGeometry(nux::Geometry(0, 0, width, height));
1592
 
  _parent->SetGeometry(nux::Geometry(offset.x, offset.y, width, height));
1593
 
 
1594
 
  ConfigureBarrier();
1595
 
}
1596
 
 
1597
 
void Launcher::OnIconAdded(AbstractLauncherIcon::Ptr const& icon)
1598
 
{
1599
 
  EnsureAnimation();
1600
 
 
1601
 
  icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
1602
 
  icon->tooltip_visible.connect(sigc::mem_fun(this, &Launcher::OnTooltipVisible));
1603
 
}
1604
 
 
1605
 
void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr const& icon)
1606
 
{
1607
 
  if (icon->needs_redraw_connection.connected())
1608
 
    icon->needs_redraw_connection.disconnect();
1609
 
 
1610
 
  SetIconUnderMouse(AbstractLauncherIcon::Ptr());
1611
 
  if (icon == _icon_mouse_down)
1612
 
    _icon_mouse_down = nullptr;
1613
 
  if (icon == _drag_icon)
1614
 
    _drag_icon = nullptr;
1615
 
 
1616
 
  EnsureAnimation();
1617
 
}
1618
 
 
1619
 
void Launcher::OnOrderChanged()
1620
 
{
1621
 
  EnsureAnimation();
1622
 
}
1623
 
 
1624
 
void Launcher::SetModel(LauncherModel::Ptr model)
1625
 
{
1626
 
  _model = model;
1627
 
 
1628
 
  for (auto icon : *_model)
1629
 
    icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
1630
 
 
1631
 
  _model->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded));
1632
 
  _model->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved));
1633
 
  _model->order_changed.connect(sigc::mem_fun(this, &Launcher::OnOrderChanged));
1634
 
  _model->selection_changed.connect(sigc::mem_fun(this, &Launcher::OnSelectionChanged));
1635
 
}
1636
 
 
1637
 
LauncherModel::Ptr Launcher::GetModel() const
1638
 
{
1639
 
  return _model;
1640
 
}
1641
 
 
1642
 
void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& selection)
1643
 
{
1644
 
  nux::Geometry const& geo = GetGeometry();
1645
 
 
1646
 
  int natural_y = 0;
1647
 
  for (auto icon : *_model)
1648
 
  {
1649
 
    if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
1650
 
      continue;
1651
 
 
1652
 
    if (icon == selection)
1653
 
      break;
1654
 
 
1655
 
    natural_y += _icon_size + _space_between_icons;
1656
 
  }
1657
 
 
1658
 
  int max_drag_delta = geo.height - (natural_y + _icon_size + (2 * _space_between_icons));
1659
 
  int min_drag_delta = -natural_y;
1660
 
 
1661
 
  _launcher_drag_delta = std::max<int>(min_drag_delta, std::min<int>(max_drag_delta, _launcher_drag_delta));
1662
 
}
1663
 
 
1664
 
void Launcher::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection)
1665
 
{
1666
 
  if (IsInKeyNavMode())
1667
 
  {
1668
 
    EnsureIconOnScreen(selection);
1669
 
    EnsureAnimation();
1670
 
  }
1671
 
}
1672
 
 
1673
 
void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon)
1674
 
{
1675
 
  EnsureAnimation();
1676
 
}
1677
 
 
1678
 
void Launcher::OnTooltipVisible(nux::ObjectPtr<nux::View> view)
1679
 
{
1680
 
  _active_tooltip = view;
1681
 
}
1682
 
 
1683
 
void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
1684
 
{
1685
 
 
1686
 
}
1687
 
 
1688
 
void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
1689
 
{
1690
 
  nux::Geometry const& base = GetGeometry();
1691
 
  nux::Geometry bkg_box;
1692
 
  std::list<RenderArg> args;
1693
 
  std::list<RenderArg>::reverse_iterator rev_it;
1694
 
  float launcher_alpha = 1.0f;
1695
 
 
1696
 
  // rely on the compiz event loop to come back to us in a nice throttling
1697
 
  if (AnimationInProgress())
1698
 
  {
1699
 
    auto idle = std::make_shared<glib::Idle>(glib::Source::Priority::DEFAULT);
1700
 
    sources_.Add(idle, ANIMATION_IDLE);
1701
 
    idle->Run([&]() {
1702
 
      EnsureAnimation();
1703
 
      return false;
1704
 
    });
1705
 
  }
1706
 
 
1707
 
  nux::ROPConfig ROP;
1708
 
  ROP.Blend = false;
1709
 
  ROP.SrcBlend = GL_ONE;
1710
 
  ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
1711
 
 
1712
 
  nux::Geometry const& geo_absolute = GetAbsoluteGeometry();
1713
 
  RenderArgs(args, bkg_box, &launcher_alpha, geo_absolute);
1714
 
  bkg_box.width -= RIGHT_LINE_WIDTH;
1715
 
  
1716
 
  nux::Color clear_colour = nux::Color(0x00000000);
1717
 
  
1718
 
  if (Settings::Instance().GetLowGfxMode())
1719
 
  {
1720
 
    clear_colour = options()->background_color;
1721
 
    clear_colour.alpha = 1.0f;
1722
 
  }
1723
 
 
1724
 
  // clear region
1725
 
  GfxContext.PushClippingRectangle(base);
1726
 
  gPainter.PushDrawColorLayer(GfxContext, base, clear_colour, true, ROP);
1727
 
 
1728
 
  if (Settings::Instance().GetLowGfxMode() == false)
1729
 
  {
1730
 
    GfxContext.GetRenderStates().SetBlend(true);
1731
 
    GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1732
 
    GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
1733
 
  }
1734
 
 
1735
 
  int push_count = 1;
1736
 
 
1737
 
  // clip vertically but not horizontally
1738
 
  GfxContext.PushClippingRectangle(nux::Geometry(base.x, bkg_box.y, base.width, bkg_box.height));
1739
 
 
1740
 
  float reveal_progress = _hide_machine.reveal_progress;
1741
 
  if ((reveal_progress > 0 || _last_reveal_progress > 0) && launcher_pressure_effect_.IsValid())
1742
 
  {
1743
 
    if (std::abs(_last_reveal_progress - reveal_progress) <= .1f)
1744
 
    {
1745
 
      _last_reveal_progress = reveal_progress;
1746
 
    }
1747
 
    else
1748
 
    {
1749
 
      if (_last_reveal_progress > reveal_progress)
1750
 
        _last_reveal_progress -= .1f;
1751
 
      else
1752
 
        _last_reveal_progress += .1f;
1753
 
    }
1754
 
    nux::Color pressure_color = nux::color::White * _last_reveal_progress;
1755
 
    nux::TexCoordXForm texxform_pressure;
1756
 
    GfxContext.QRP_1Tex(base.x, base.y, launcher_pressure_effect_->GetWidth(), base.height,
1757
 
                        launcher_pressure_effect_->GetDeviceTexture(),
1758
 
                        texxform_pressure,
1759
 
                        pressure_color);
1760
 
  }
1761
 
 
1762
 
  if (Settings::Instance().GetLowGfxMode() == false)
1763
 
  {
1764
 
    if (IsOverlayOpen())
1765
 
    {
1766
 
      nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height);
1767
 
      nux::ObjectPtr<nux::IOpenGLBaseTexture> blur_texture;
1768
 
 
1769
 
      if (BackgroundEffectHelper::blur_type != unity::BLUR_NONE && (bkg_box.x + bkg_box.width > 0))
1770
 
      {
1771
 
        blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo);
1772
 
      }
1773
 
      else
1774
 
      {
1775
 
        blur_texture = bg_effect_helper_.GetRegion(blur_geo);
1776
 
      }
1777
 
 
1778
 
      if (blur_texture.IsValid())
1779
 
      {
1780
 
        nux::TexCoordXForm texxform_blur_bg;
1781
 
        texxform_blur_bg.flip_v_coord = true;
1782
 
        texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
1783
 
        texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width;
1784
 
        texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height;
1785
 
 
1786
 
        GfxContext.PushClippingRectangle(bkg_box);
1787
 
 
1788
 
#ifndef NUX_OPENGLES_20
1789
 
        if (GfxContext.UsingGLSLCodePath())
1790
 
          gPainter.PushDrawCompositionLayer(GfxContext, base,
1791
 
                                            blur_texture,
1792
 
                                            texxform_blur_bg,
1793
 
                                            nux::color::White,
1794
 
                                            options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY,
1795
 
                                            true, ROP);
1796
 
        else
1797
 
          gPainter.PushDrawTextureLayer(GfxContext, base,
1798
 
                                        blur_texture,
1799
 
                                        texxform_blur_bg,
1800
 
                                        nux::color::White,
1801
 
                                        true,
1802
 
                                        ROP);
1803
 
#else
1804
 
          gPainter.PushDrawCompositionLayer(GfxContext, base,
1805
 
                                            blur_texture,
1806
 
                                            texxform_blur_bg,
1807
 
                                            nux::color::White,
1808
 
                                            options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY,
1809
 
                                            true, ROP);
1810
 
#endif
1811
 
        GfxContext.PopClippingRectangle();
1812
 
 
1813
 
        push_count++;
1814
 
      }
1815
 
 
1816
 
      unsigned int alpha = 0, src = 0, dest = 0;
1817
 
      GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
1818
 
 
1819
 
      // apply the darkening
1820
 
      GfxContext.GetRenderStates().SetBlend(true, GL_ZERO, GL_SRC_COLOR);
1821
 
      gPainter.Paint2DQuadColor(GfxContext, bkg_box, nux::Color(0.9f, 0.9f, 0.9f, 1.0f));
1822
 
      GfxContext.GetRenderStates().SetBlend (alpha, src, dest);
1823
 
 
1824
 
      // apply the bg colour
1825
 
#ifndef NUX_OPENGLES_20
1826
 
      if (GfxContext.UsingGLSLCodePath() == false)
1827
 
        gPainter.Paint2DQuadColor(GfxContext, bkg_box, options()->background_color);
1828
 
#endif
1829
 
 
1830
 
      // apply the shine
1831
 
      GfxContext.GetRenderStates().SetBlend(true, GL_DST_COLOR, GL_ONE);
1832
 
      nux::TexCoordXForm texxform;
1833
 
      texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
1834
 
      texxform.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP);
1835
 
      texxform.uoffset = (1.0f / launcher_sheen_->GetWidth()); // TODO (gord) don't use absolute values here
1836
 
      texxform.voffset = (1.0f / launcher_sheen_->GetHeight()) * panel::Style::Instance().panel_height;
1837
 
      GfxContext.QRP_1Tex(base.x, base.y, base.width, base.height,
1838
 
                          launcher_sheen_->GetDeviceTexture(),
1839
 
                          texxform,
1840
 
                          nux::color::White);
1841
 
 
1842
 
      //reset the blend state
1843
 
      GfxContext.GetRenderStates().SetBlend (alpha, src, dest);
1844
 
    }
1845
 
    else
1846
 
    {
1847
 
      nux::Color color = options()->background_color;
1848
 
      color.alpha = options()->background_alpha;
1849
 
      gPainter.Paint2DQuadColor(GfxContext, bkg_box, color);
1850
 
    }
1851
 
  }
1852
 
 
1853
 
  GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1854
 
 
1855
 
  icon_renderer->PreprocessIcons(args, base);
1856
 
  EventLogic();
1857
 
 
1858
 
  /* draw launcher */
1859
 
  for (rev_it = args.rbegin(); rev_it != args.rend(); ++rev_it)
1860
 
  {
1861
 
    if ((*rev_it).stick_thingy)
1862
 
      gPainter.Paint2DQuadColor(GfxContext,
1863
 
                                nux::Geometry(bkg_box.x, (*rev_it).render_center.y - 3, bkg_box.width, 2),
1864
 
                                nux::Color(0xAAAAAAAA));
1865
 
 
1866
 
    if ((*rev_it).skip)
1867
 
      continue;
1868
 
 
1869
 
    icon_renderer->RenderIcon(GfxContext, *rev_it, bkg_box, base);
1870
 
  }
1871
 
 
1872
 
  if (!IsOverlayOpen())
1873
 
  {
1874
 
    const double right_line_opacity = 0.15f * launcher_alpha;
1875
 
 
1876
 
    gPainter.Paint2DQuadColor(GfxContext,
1877
 
                              nux::Geometry(bkg_box.x + bkg_box.width,
1878
 
                                            bkg_box.y,
1879
 
                                            RIGHT_LINE_WIDTH,
1880
 
                                            bkg_box.height),
1881
 
                              nux::color::White * right_line_opacity);
1882
 
 
1883
 
    gPainter.Paint2DQuadColor(GfxContext,
1884
 
                              nux::Geometry(bkg_box.x,
1885
 
                                            bkg_box.y,
1886
 
                                            bkg_box.width,
1887
 
                                            8),
1888
 
                              nux::Color(0x70000000),
1889
 
                              nux::Color(0x00000000),
1890
 
                              nux::Color(0x00000000),
1891
 
                              nux::Color(0x70000000));
1892
 
  }
1893
 
 
1894
 
  // FIXME: can be removed for a bgk_box->SetAlpha once implemented
1895
 
  GfxContext.GetRenderStates().SetPremultipliedBlend(nux::DST_IN);
1896
 
  nux::Color alpha_mask = nux::Color(0xFFAAAAAA) * launcher_alpha;
1897
 
  gPainter.Paint2DQuadColor(GfxContext, bkg_box, alpha_mask);
1898
 
 
1899
 
  GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
1900
 
  GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1901
 
 
1902
 
  gPainter.PopBackground(push_count);
1903
 
  GfxContext.PopClippingRectangle();
1904
 
  GfxContext.PopClippingRectangle();
1905
 
}
1906
 
 
1907
 
long Launcher::PostLayoutManagement(long LayoutResult)
1908
 
{
1909
 
  View::PostLayoutManagement(LayoutResult);
1910
 
 
1911
 
  SetMousePosition(0, 0);
1912
 
 
1913
 
  return nux::SIZE_EQUAL_HEIGHT | nux::SIZE_EQUAL_WIDTH;
1914
 
}
1915
 
 
1916
 
void Launcher::OnDragWindowAnimCompleted()
1917
 
{
1918
 
  HideDragWindow();
1919
 
  EnsureAnimation();
1920
 
}
1921
 
 
1922
 
bool Launcher::StartIconDragTimeout(int x, int y)
1923
 
{
1924
 
  // if we are still waiting…
1925
 
  if (GetActionState() == ACTION_NONE)
1926
 
  {
1927
 
    SetIconUnderMouse(AbstractLauncherIcon::Ptr());
1928
 
    _initial_drag_animation = true;
1929
 
    StartIconDragRequest(x, y);
1930
 
  }
1931
 
 
1932
 
  return false;
1933
 
}
1934
 
 
1935
 
void Launcher::StartIconDragRequest(int x, int y)
1936
 
{
1937
 
  nux::Geometry const& abs_geo = GetAbsoluteGeometry();
1938
 
  AbstractLauncherIcon::Ptr const& drag_icon = MouseIconIntersection(abs_geo.width / 2.0f, y);
1939
 
 
1940
 
  // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
1941
 
  // on an internal Launcher property then
1942
 
  if (drag_icon && _last_button_press == 1 && drag_icon->position() == AbstractLauncherIcon::Position::FLOATING)
1943
 
  {
1944
 
    auto const& icon_center = drag_icon->GetCenter(monitor);
1945
 
    x += abs_geo.x;
1946
 
    y += abs_geo.y;
1947
 
 
1948
 
    SetActionState(ACTION_DRAG_ICON);
1949
 
    StartIconDrag(drag_icon);
1950
 
    UpdateDragWindowPosition(icon_center.x, icon_center.y);
1951
 
 
1952
 
    if (_initial_drag_animation)
1953
 
    {
1954
 
      _drag_window->SetAnimationTarget(x, y);
1955
 
      _drag_window->StartQuickAnimation();
1956
 
    }
1957
 
 
1958
 
    EnsureAnimation();
1959
 
  }
1960
 
  else
1961
 
  {
1962
 
    _drag_icon = nullptr;
1963
 
    HideDragWindow();
1964
 
  }
1965
 
}
1966
 
 
1967
 
void Launcher::StartIconDrag(AbstractLauncherIcon::Ptr const& icon)
1968
 
{
1969
 
  if (!icon)
1970
 
    return;
1971
 
 
1972
 
  _hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
1973
 
  _drag_icon = icon;
1974
 
  _drag_icon_position = _model->IconIndex(icon);
1975
 
 
1976
 
  HideDragWindow();
1977
 
  _offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(GetWidth(), GetWidth(), 1, nux::BITFMT_R8G8B8A8);
1978
 
  _drag_window = new LauncherDragWindow(_offscreen_drag_texture);
1979
 
  RenderIconToTexture(nux::GetWindowThread()->GetGraphicsEngine(), _drag_icon, _offscreen_drag_texture);
1980
 
  ShowDragWindow();
1981
 
 
1982
 
  ubus_.SendMessage(UBUS_LAUNCHER_ICON_START_DND);
1983
 
}
1984
 
 
1985
 
void Launcher::EndIconDrag()
1986
 
{
1987
 
  if (_drag_window)
1988
 
  {
1989
 
    AbstractLauncherIcon::Ptr hovered_icon;
1990
 
 
1991
 
    if (!_drag_window->Cancelled())
1992
 
      hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
1993
 
 
1994
 
    if (hovered_icon && hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
1995
 
    {
1996
 
      hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true);
1997
 
 
1998
 
      remove_request.emit(_drag_icon);
1999
 
 
2000
 
      HideDragWindow();
2001
 
      EnsureAnimation();
2002
 
    }
2003
 
    else
2004
 
    {
2005
 
      if (!_drag_window->Cancelled() && _model->IconIndex(_drag_icon) != _drag_icon_position)
2006
 
      {
2007
 
        _drag_icon->Stick(false);
2008
 
        _model->Save();
2009
 
      }
2010
 
 
2011
 
      if (_drag_window->on_anim_completed.connected())
2012
 
        _drag_window->on_anim_completed.disconnect();
2013
 
      _drag_window->on_anim_completed = _drag_window->anim_completed.connect(sigc::mem_fun(this, &Launcher::OnDragWindowAnimCompleted));
2014
 
 
2015
 
      auto const& icon_center = _drag_icon->GetCenter(monitor);
2016
 
      _drag_window->SetAnimationTarget(icon_center.x, icon_center.y),
2017
 
      _drag_window->StartQuickAnimation();
2018
 
    }
2019
 
  }
2020
 
 
2021
 
  if (MouseBeyondDragThreshold())
2022
 
    TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT);
2023
 
 
2024
 
  _hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, false);
2025
 
  ubus_.SendMessage(UBUS_LAUNCHER_ICON_END_DND);
2026
 
}
2027
 
 
2028
 
void Launcher::ShowDragWindow()
2029
 
{
2030
 
  if (!_drag_window || _drag_window->IsVisible())
2031
 
    return;
2032
 
 
2033
 
  _drag_window->GrabKeyboard();
2034
 
  _drag_window->ShowWindow(true);
2035
 
  _drag_window->PushToFront();
2036
 
 
2037
 
  bool is_before;
2038
 
  AbstractLauncherIcon::Ptr const& closer = _model->GetClosestIcon(_drag_icon, is_before);
2039
 
  _drag_window->drag_cancel_request.connect([this, closer, is_before] {
2040
 
    if (is_before)
2041
 
      _model->ReorderAfter(_drag_icon, closer);
2042
 
    else
2043
 
      _model->ReorderBefore(_drag_icon, closer, true);
2044
 
 
2045
 
    ResetMouseDragState();
2046
 
  });
2047
 
}
2048
 
 
2049
 
void Launcher::HideDragWindow()
2050
 
{
2051
 
  nux::Geometry const& abs_geo = GetAbsoluteGeometry();
2052
 
  nux::Point const& mouse = nux::GetWindowCompositor().GetMousePosition();
2053
 
 
2054
 
  if (abs_geo.IsInside(mouse))
2055
 
    mouse_enter.emit(mouse.x - abs_geo.x, mouse.y - abs_geo.y, 0, 0);
2056
 
 
2057
 
  if (!_drag_window)
2058
 
    return;
2059
 
 
2060
 
  _drag_window->UnGrabKeyboard();
2061
 
  _drag_window->ShowWindow(false);
2062
 
  _drag_window = nullptr;
2063
 
}
2064
 
 
2065
 
void Launcher::UpdateDragWindowPosition(int x, int y)
2066
 
{
2067
 
  if (!_drag_window)
2068
 
    return;
2069
 
 
2070
 
  auto const& icon_geo = _drag_window->GetGeometry();
2071
 
  _drag_window->SetBaseXY(x - icon_geo.width / 2, y - icon_geo.height / 2);
2072
 
 
2073
 
  if (!_drag_icon)
2074
 
    return;
2075
 
 
2076
 
  auto const& launcher_geo = GetGeometry();
2077
 
  auto const& hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY());
2078
 
  struct timespec current;
2079
 
  clock_gettime(CLOCK_MONOTONIC, &current);
2080
 
  float progress = DragThresholdProgress(current);
2081
 
 
2082
 
  if (hovered_icon && _drag_icon != hovered_icon)
2083
 
  {
2084
 
    if (progress >= 1.0f)
2085
 
    {
2086
 
      _model->ReorderSmart(_drag_icon, hovered_icon, true);
2087
 
    }
2088
 
    else if (progress == 0.0f)
2089
 
    {
2090
 
      _model->ReorderBefore(_drag_icon, hovered_icon, false);
2091
 
    }
2092
 
  }
2093
 
  else if (!hovered_icon && progress == 0.0f)
2094
 
  {
2095
 
    // If no icon is hovered, then we can add our icon to the bottom
2096
 
    for (auto it = _model->main_rbegin(); it != _model->main_rend(); ++it)
2097
 
    {
2098
 
      auto const& icon = *it;
2099
 
 
2100
 
      if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
2101
 
        continue;
2102
 
 
2103
 
      if (y >= icon->GetCenter(monitor).y)
2104
 
      {
2105
 
        _model->ReorderAfter(_drag_icon, icon);
2106
 
        break;
2107
 
      }
2108
 
    }
2109
 
  }
2110
 
}
2111
 
 
2112
 
void Launcher::ResetMouseDragState()
2113
 
{
2114
 
  if (GetActionState() == ACTION_DRAG_ICON)
2115
 
    EndIconDrag();
2116
 
 
2117
 
  if (GetActionState() == ACTION_DRAG_LAUNCHER)
2118
 
    _hide_machine.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, false);
2119
 
 
2120
 
  SetActionState(ACTION_NONE);
2121
 
  _dnd_delta_x = 0;
2122
 
  _dnd_delta_y = 0;
2123
 
  _last_button_press = 0;
2124
 
  EnsureAnimation();
2125
 
}
2126
 
 
2127
 
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
2128
 
{
2129
 
  _last_button_press = nux::GetEventButton(button_flags);
2130
 
  SetMousePosition(x, y);
2131
 
 
2132
 
  MouseDownLogic(x, y, button_flags, key_flags);
2133
 
  EnsureAnimation();
2134
 
}
2135
 
 
2136
 
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
2137
 
{
2138
 
  SetMousePosition(x, y);
2139
 
 
2140
 
  MouseUpLogic(x, y, button_flags, key_flags);
2141
 
  ResetMouseDragState();
2142
 
}
2143
 
 
2144
 
void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
2145
 
{
2146
 
  /* FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
2147
 
   * on an internal Launcher property then
2148
 
   */
2149
 
 
2150
 
  if (_last_button_press != 1)
2151
 
    return;
2152
 
 
2153
 
  SetMousePosition(x, y);
2154
 
 
2155
 
  // FIXME: hack (see SetupRenderArg)
2156
 
  _initial_drag_animation = false;
2157
 
 
2158
 
  _dnd_delta_y += dy;
2159
 
  _dnd_delta_x += dx;
2160
 
 
2161
 
  if (nux::Abs(_dnd_delta_y) < MOUSE_DEADZONE &&
2162
 
      nux::Abs(_dnd_delta_x) < MOUSE_DEADZONE &&
2163
 
      GetActionState() == ACTION_NONE)
2164
 
    return;
2165
 
 
2166
 
  SetIconUnderMouse(AbstractLauncherIcon::Ptr());
2167
 
 
2168
 
  if (GetActionState() == ACTION_NONE)
2169
 
  {
2170
 
#ifdef USE_X11
2171
 
    if (nux::Abs(_dnd_delta_y) >= nux::Abs(_dnd_delta_x))
2172
 
    {
2173
 
      _launcher_drag_delta += _dnd_delta_y;
2174
 
      SetActionState(ACTION_DRAG_LAUNCHER);
2175
 
      _hide_machine.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true);
2176
 
    }
2177
 
    else
2178
 
    {
2179
 
      // We we can safely start the icon drag, from the original mouse-down position
2180
 
      sources_.Remove(START_DRAGICON_DURATION);
2181
 
      StartIconDragRequest(x - _dnd_delta_x, y - _dnd_delta_y);
2182
 
    }
2183
 
#endif
2184
 
  }
2185
 
  else if (GetActionState() == ACTION_DRAG_LAUNCHER)
2186
 
  {
2187
 
    _launcher_drag_delta += dy;
2188
 
    ubus_.SendMessage(UBUS_LAUNCHER_END_DND);
2189
 
  }
2190
 
  else if (GetActionState() == ACTION_DRAG_ICON)
2191
 
  {
2192
 
    nux::Geometry const& geo = GetAbsoluteGeometry();
2193
 
    UpdateDragWindowPosition(geo.x + x, geo.y + y);
2194
 
  }
2195
 
 
2196
 
  EnsureAnimation();
2197
 
}
2198
 
 
2199
 
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
2200
 
{
2201
 
  SetMousePosition(x, y);
2202
 
  SetStateMouseOverLauncher(true);
2203
 
 
2204
 
  EventLogic();
2205
 
  EnsureAnimation();
2206
 
}
2207
 
 
2208
 
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
2209
 
{
2210
 
  SetStateMouseOverLauncher(false);
2211
 
  EventLogic();
2212
 
  EnsureAnimation();
2213
 
}
2214
 
 
2215
 
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
2216
 
{
2217
 
  SetMousePosition(x, y);
2218
 
  tooltip_manager_.MouseMoved(_icon_under_mouse);
2219
 
 
2220
 
  if (!_hidden)
2221
 
    UpdateChangeInMousePosition(dx, dy);
2222
 
 
2223
 
  // Every time the mouse moves, we check if it is inside an icon...
2224
 
  EventLogic();
2225
 
}
2226
 
 
2227
 
void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned long /*button_flags*/, unsigned long key_flags)
2228
 
{
2229
 
  if (!_hovered)
2230
 
    return;
2231
 
 
2232
 
  bool alt_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_ALT);
2233
 
  if (alt_pressed)
2234
 
  {
2235
 
    ScrollLauncher(wheel_delta);
2236
 
  }
2237
 
  else if (_icon_under_mouse)
2238
 
  {
2239
 
    auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
2240
 
    auto scroll_direction = (wheel_delta < 0) ? AbstractLauncherIcon::ScrollDirection::DOWN : AbstractLauncherIcon::ScrollDirection::UP;
2241
 
    _icon_under_mouse->PerformScroll(scroll_direction, timestamp);
2242
 
  }
2243
 
}
2244
 
 
2245
 
void Launcher::ScrollLauncher(int wheel_delta)
2246
 
{
2247
 
  if (wheel_delta < 0)
2248
 
    // scroll down
2249
 
    _launcher_drag_delta -= 25;
2250
 
  else
2251
 
    // scroll up
2252
 
    _launcher_drag_delta += 25;
2253
 
 
2254
 
  EnsureAnimation();
2255
 
}
2256
 
 
2257
 
#ifdef USE_X11
2258
 
 
2259
 
ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event)
2260
 
{
2261
 
  if (_hide_machine.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
2262
 
  {
2263
 
    return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE;
2264
 
  }
2265
 
 
2266
 
  nux::Geometry const& abs_geo = GetAbsoluteGeometry();
2267
 
 
2268
 
  bool apply_to_reveal = false;
2269
 
  if (event->x >= abs_geo.x && event->x <= abs_geo.x + abs_geo.width)
2270
 
  {
2271
 
    if (!_hidden)
2272
 
      return ui::EdgeBarrierSubscriber::Result::ALREADY_HANDLED;
2273
 
 
2274
 
    if (options()->reveal_trigger == RevealTrigger::EDGE)
2275
 
    {
2276
 
      if (event->y >= abs_geo.y)
2277
 
        apply_to_reveal = true;
2278
 
    }
2279
 
    else if (options()->reveal_trigger == RevealTrigger::CORNER)
2280
 
    {
2281
 
      if (event->y < abs_geo.y)
2282
 
        apply_to_reveal = true;
2283
 
    }
2284
 
  }
2285
 
 
2286
 
  if (apply_to_reveal)
2287
 
  {
2288
 
    int root_x_return, root_y_return, win_x_return, win_y_return;
2289
 
    unsigned int mask_return;
2290
 
    Window root_return, child_return;
2291
 
    Display *dpy = nux::GetGraphicsDisplay()->GetX11Display();
2292
 
 
2293
 
    if (XQueryPointer (dpy, DefaultRootWindow(dpy), &root_return, &child_return, &root_x_return,
2294
 
                       &root_y_return, &win_x_return, &win_y_return, &mask_return))
2295
 
    {
2296
 
      if (mask_return & (Button1Mask | Button3Mask))
2297
 
        return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE;
2298
 
    }
2299
 
  }
2300
 
 
2301
 
  if (!apply_to_reveal)
2302
 
    return ui::EdgeBarrierSubscriber::Result::IGNORED;
2303
 
 
2304
 
  if (!owner->IsFirstEvent())
2305
 
    _hide_machine.AddRevealPressure(event->velocity);
2306
 
 
2307
 
  return ui::EdgeBarrierSubscriber::Result::HANDLED;
2308
 
}
2309
 
 
2310
 
#endif
2311
 
 
2312
 
bool Launcher::IsInKeyNavMode() const
2313
 
{
2314
 
  return _hide_machine.GetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE);
2315
 
}
2316
 
 
2317
 
void Launcher::EnterKeyNavMode()
2318
 
{
2319
 
  _hide_machine.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true);
2320
 
  _hover_machine.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true);
2321
 
  SaturateIcons();
2322
 
}
2323
 
 
2324
 
void Launcher::ExitKeyNavMode()
2325
 
{
2326
 
  _hide_machine.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false);
2327
 
  _hover_machine.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false);
2328
 
}
2329
 
 
2330
 
void Launcher::RecvQuicklistOpened(nux::ObjectPtr<QuicklistView> const& quicklist)
2331
 
{
2332
 
  UScreen* uscreen = UScreen::GetDefault();
2333
 
  if (uscreen->GetMonitorGeometry(monitor).IsInside(nux::Point(quicklist->GetGeometry().x, quicklist->GetGeometry().y)))
2334
 
  {
2335
 
    _hide_machine.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true);
2336
 
    _hover_machine.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true);
2337
 
    EventLogic();
2338
 
    EnsureAnimation();
2339
 
  }
2340
 
}
2341
 
 
2342
 
void Launcher::RecvQuicklistClosed(nux::ObjectPtr<QuicklistView> const& quicklist)
2343
 
{
2344
 
  nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
2345
 
  if (!GetAbsoluteGeometry().IsInside(pt))
2346
 
  {
2347
 
    // The Quicklist just closed and the mouse is outside the launcher.
2348
 
    SetHover(false);
2349
 
    SetStateMouseOverLauncher(false);
2350
 
  }
2351
 
  // Cancel any prior state that was set before the Quicklist appeared.
2352
 
  SetActionState(ACTION_NONE);
2353
 
 
2354
 
  _hide_machine.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, false);
2355
 
  _hover_machine.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, false);
2356
 
 
2357
 
  EventLogic();
2358
 
  EnsureAnimation();
2359
 
}
2360
 
 
2361
 
void Launcher::EventLogic()
2362
 
{
2363
 
  if (GetActionState() == ACTION_DRAG_ICON ||
2364
 
      GetActionState() == ACTION_DRAG_LAUNCHER)
2365
 
    return;
2366
 
 
2367
 
  AbstractLauncherIcon::Ptr launcher_icon;
2368
 
 
2369
 
  if (!_hidden && !IsInKeyNavMode() && _hovered)
2370
 
  {
2371
 
    launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2372
 
  }
2373
 
 
2374
 
  SetIconUnderMouse(launcher_icon);
2375
 
}
2376
 
 
2377
 
void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
2378
 
{
2379
 
  AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2380
 
 
2381
 
  if (launcher_icon)
2382
 
  {
2383
 
    _icon_mouse_down = launcher_icon;
2384
 
    // if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app
2385
 
    auto cb_func = sigc::bind(sigc::mem_fun(this, &Launcher::StartIconDragTimeout), x, y);
2386
 
    sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT);
2387
 
 
2388
 
    launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2389
 
    tooltip_manager_.IconClicked();
2390
 
  }
2391
 
}
2392
 
 
2393
 
void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
2394
 
{
2395
 
  AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2396
 
 
2397
 
  sources_.Remove(START_DRAGICON_TIMEOUT);
2398
 
 
2399
 
  if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
2400
 
  {
2401
 
    _icon_mouse_down->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2402
 
 
2403
 
    if (GetActionState() == ACTION_NONE)
2404
 
    {
2405
 
      _icon_mouse_down->mouse_click.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2406
 
    }
2407
 
  }
2408
 
 
2409
 
  if (launcher_icon && (_icon_mouse_down != launcher_icon))
2410
 
  {
2411
 
    launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2412
 
  }
2413
 
 
2414
 
  if (GetActionState() == ACTION_DRAG_LAUNCHER)
2415
 
  {
2416
 
    TimeUtil::SetTimeStruct(&_times[TIME_DRAG_END]);
2417
 
  }
2418
 
 
2419
 
  _icon_mouse_down = nullptr;
2420
 
}
2421
 
 
2422
 
AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const
2423
 
{
2424
 
  LauncherModel::iterator it;
2425
 
  // We are looking for the icon at screen coordinates x, y;
2426
 
  nux::Point2 mouse_position(x, y);
2427
 
  int inside = 0;
2428
 
 
2429
 
  for (it = _model->begin(); it != _model->end(); ++it)
2430
 
  {
2431
 
    if (!(*it)->IsVisible() || !(*it)->IsVisibleOnMonitor(monitor))
2432
 
      continue;
2433
 
 
2434
 
    nux::Point2 screen_coord [4];
2435
 
    for (int i = 0; i < 4; ++i)
2436
 
    {
2437
 
      auto hit_transform = (*it)->GetTransform(AbstractLauncherIcon::TRANSFORM_HIT_AREA, monitor);
2438
 
      screen_coord [i].x = hit_transform [i].x;
2439
 
      screen_coord [i].y = hit_transform [i].y;
2440
 
    }
2441
 
    inside = PointInside2DPolygon(screen_coord, 4, mouse_position, 1);
2442
 
    if (inside)
2443
 
      return (*it);
2444
 
  }
2445
 
 
2446
 
  return AbstractLauncherIcon::Ptr();
2447
 
}
2448
 
 
2449
 
void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon::Ptr const& icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture)
2450
 
{
2451
 
  RenderArg arg;
2452
 
  struct timespec current;
2453
 
  clock_gettime(CLOCK_MONOTONIC, &current);
2454
 
 
2455
 
  SetupRenderArg(icon, current, arg);
2456
 
  arg.render_center = nux::Point3(roundf(texture->GetWidth() / 2.0f), roundf(texture->GetHeight() / 2.0f), 0.0f);
2457
 
  arg.logical_center = arg.render_center;
2458
 
  arg.rotation.x = 0.0f;
2459
 
  arg.running_arrow = false;
2460
 
  arg.active_arrow = false;
2461
 
  arg.skip = false;
2462
 
  arg.window_indicators = 0;
2463
 
  arg.alpha = 1.0f;
2464
 
 
2465
 
  std::list<RenderArg> drag_args;
2466
 
  drag_args.push_front(arg);
2467
 
 
2468
 
  graphics::PushOffscreenRenderTarget(texture);
2469
 
 
2470
 
  unsigned int alpha = 0, src = 0, dest = 0;
2471
 
  GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
2472
 
  GfxContext.GetRenderStates().SetBlend(false);
2473
 
 
2474
 
  GfxContext.QRP_Color(0,
2475
 
                      0,
2476
 
                      texture->GetWidth(),
2477
 
                      texture->GetHeight(),
2478
 
                      nux::Color(0.0f, 0.0f, 0.0f, 0.0f));
2479
 
 
2480
 
  GfxContext.GetRenderStates().SetBlend(alpha, src, dest);
2481
 
 
2482
 
  nux::Geometry geo(0, 0, texture->GetWidth(), texture->GetWidth());
2483
 
 
2484
 
  icon_renderer->PreprocessIcons(drag_args, geo);
2485
 
  icon_renderer->RenderIcon(GfxContext, arg, geo, geo);
2486
 
  unity::graphics::PopOffscreenRenderTarget();
2487
 
}
2488
 
 
2489
 
#ifdef NUX_GESTURES_SUPPORT
2490
 
nux::GestureDeliveryRequest Launcher::GestureEvent(const nux::GestureEvent &event)
2491
 
{
2492
 
  switch(event.type)
2493
 
  {
2494
 
    case nux::EVENT_GESTURE_BEGIN:
2495
 
      OnDragStart(event);
2496
 
      break;
2497
 
    case nux::EVENT_GESTURE_UPDATE:
2498
 
      OnDragUpdate(event);
2499
 
      break;
2500
 
    default: // EVENT_GESTURE_END
2501
 
      OnDragFinish(event);
2502
 
      break;
2503
 
  }
2504
 
 
2505
 
  return nux::GestureDeliveryRequest::NONE;
2506
 
}
2507
 
#endif
2508
 
 
2509
 
bool Launcher::DndIsSpecialRequest(std::string const& uri) const
2510
 
{
2511
 
  return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);
2512
 
}
2513
 
 
2514
 
void Launcher::ProcessDndEnter()
2515
 
{
2516
 
#ifdef USE_X11
2517
 
  SetStateMouseOverLauncher(true);
2518
 
 
2519
 
  _dnd_data.Reset();
2520
 
  _drag_action = nux::DNDACTION_NONE;
2521
 
  _steal_drag = false;
2522
 
  _data_checked = false;
2523
 
  _drag_edge_touching = false;
2524
 
  _dnd_hovered_icon = nullptr;
2525
 
#endif
2526
 
}
2527
 
 
2528
 
void Launcher::DndReset()
2529
 
{
2530
 
#ifdef USE_X11
2531
 
  _dnd_data.Reset();
2532
 
 
2533
 
  bool is_overlay_open = IsOverlayOpen();
2534
 
 
2535
 
  for (auto it : *_model)
2536
 
  {
2537
 
    auto icon_type = it->GetIconType();
2538
 
 
2539
 
    if (icon_type == AbstractLauncherIcon::IconType::HOME ||
2540
 
        icon_type == AbstractLauncherIcon::IconType::HUD)
2541
 
    {
2542
 
      it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2543
 
    }
2544
 
    else
2545
 
    {
2546
 
      it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered);
2547
 
    }
2548
 
 
2549
 
    it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false);
2550
 
  }
2551
 
 
2552
 
  DndHoveredIconReset();
2553
 
#endif
2554
 
}
2555
 
 
2556
 
void Launcher::DndHoveredIconReset()
2557
 
{
2558
 
#ifdef USE_X11
2559
 
  _drag_edge_touching = false;
2560
 
  SetActionState(ACTION_NONE);
2561
 
 
2562
 
  if (_steal_drag && _dnd_hovered_icon)
2563
 
  {
2564
 
    _dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2565
 
    _dnd_hovered_icon->remove.emit(_dnd_hovered_icon);
2566
 
  }
2567
 
 
2568
 
  if (!_steal_drag && _dnd_hovered_icon)
2569
 
    _dnd_hovered_icon->SendDndLeave();
2570
 
 
2571
 
  _steal_drag = false;
2572
 
  _dnd_hovered_icon = nullptr;
2573
 
#endif
2574
 
}
2575
 
 
2576
 
void Launcher::ProcessDndLeave()
2577
 
{
2578
 
#ifdef USE_X11
2579
 
  SetStateMouseOverLauncher(false);
2580
 
 
2581
 
  DndHoveredIconReset();
2582
 
#endif
2583
 
}
2584
 
 
2585
 
void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes)
2586
 
{
2587
 
#ifdef USE_X11
2588
 
  if (!_data_checked)
2589
 
  {
2590
 
    const std::string uri_list = "text/uri-list";
2591
 
    _data_checked = true;
2592
 
    _dnd_data.Reset();
2593
 
    auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
2594
 
 
2595
 
    // get the data
2596
 
    for (auto const& mime : mimes)
2597
 
    {
2598
 
      if (mime != uri_list)
2599
 
        continue;
2600
 
 
2601
 
      _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
2602
 
      break;
2603
 
    }
2604
 
 
2605
 
    // see if the launcher wants this one
2606
 
    auto const& uris = _dnd_data.Uris();
2607
 
    if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
2608
 
                     {return DndIsSpecialRequest(uri);}) != uris.end())
2609
 
    {
2610
 
      _steal_drag = true;
2611
 
    }
2612
 
 
2613
 
    // only set hover once we know our first x/y
2614
 
    SetActionState(ACTION_DRAG_EXTERNAL);
2615
 
    SetStateMouseOverLauncher(true);
2616
 
 
2617
 
    if (!_steal_drag && !_dnd_data.Uris().empty())
2618
 
    {
2619
 
      for (auto const& it : *_model)
2620
 
      {
2621
 
        if (it->ShouldHighlightOnDrag(_dnd_data))
2622
 
          it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2623
 
        else
2624
 
          it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
2625
 
      }
2626
 
    }
2627
 
  }
2628
 
 
2629
 
  SetMousePosition(x - _parent->GetGeometry().x, y - _parent->GetGeometry().y);
2630
 
 
2631
 
  if (monitor() == 0 && !IsOverlayOpen() && _mouse_position.x == 0 && _mouse_position.y <= (_parent->GetGeometry().height - _icon_size - 2 * _space_between_icons) && !_drag_edge_touching)
2632
 
  {
2633
 
    if (_dnd_hovered_icon)
2634
 
        _dnd_hovered_icon->SendDndLeave();
2635
 
 
2636
 
    _drag_edge_touching = true;
2637
 
    TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3);
2638
 
    EnsureAnimation();
2639
 
  }
2640
 
  else if (_mouse_position.x != 0 && _drag_edge_touching)
2641
 
  {
2642
 
    _drag_edge_touching = false;
2643
 
    TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3);
2644
 
    EnsureAnimation();
2645
 
  }
2646
 
 
2647
 
  EventLogic();
2648
 
  AbstractLauncherIcon::Ptr const& hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2649
 
 
2650
 
  bool hovered_icon_is_appropriate = false;
2651
 
  if (hovered_icon)
2652
 
  {
2653
 
    if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
2654
 
      _steal_drag = false;
2655
 
 
2656
 
    if (hovered_icon->position() == AbstractLauncherIcon::Position::FLOATING)
2657
 
      hovered_icon_is_appropriate = true;
2658
 
  }
2659
 
 
2660
 
  if (_steal_drag)
2661
 
  {
2662
 
    _drag_action = nux::DNDACTION_COPY;
2663
 
    if (!_dnd_hovered_icon && hovered_icon_is_appropriate)
2664
 
    {
2665
 
      _dnd_hovered_icon = new SpacerLauncherIcon(monitor());
2666
 
      _model->AddIcon(_dnd_hovered_icon);
2667
 
      _model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true);
2668
 
    }
2669
 
    else if (_dnd_hovered_icon)
2670
 
    {
2671
 
      if (hovered_icon)
2672
 
      {
2673
 
        if (hovered_icon_is_appropriate)
2674
 
        {
2675
 
          _model->ReorderSmart(_dnd_hovered_icon, hovered_icon, true);
2676
 
        }
2677
 
        else
2678
 
        {
2679
 
          _dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2680
 
          _dnd_hovered_icon->remove.emit(_dnd_hovered_icon);
2681
 
          _dnd_hovered_icon = nullptr;
2682
 
        }
2683
 
      }
2684
 
    }
2685
 
  }
2686
 
  else
2687
 
  {
2688
 
    if (!_drag_edge_touching && hovered_icon != _dnd_hovered_icon)
2689
 
    {
2690
 
      if (hovered_icon)
2691
 
      {
2692
 
        hovered_icon->SendDndEnter();
2693
 
        _drag_action = hovered_icon->QueryAcceptDrop(_dnd_data);
2694
 
      }
2695
 
      else
2696
 
      {
2697
 
        _drag_action = nux::DNDACTION_NONE;
2698
 
      }
2699
 
 
2700
 
      if (_dnd_hovered_icon)
2701
 
        _dnd_hovered_icon->SendDndLeave();
2702
 
 
2703
 
      _dnd_hovered_icon = hovered_icon;
2704
 
    }
2705
 
  }
2706
 
 
2707
 
  bool accept;
2708
 
  if (_drag_action != nux::DNDACTION_NONE)
2709
 
    accept = true;
2710
 
  else
2711
 
    accept = false;
2712
 
 
2713
 
  SendDndStatus(accept, _drag_action, nux::Geometry(x, y, 1, 1));
2714
 
#endif
2715
 
}
2716
 
 
2717
 
void Launcher::ProcessDndDrop(int x, int y)
2718
 
{
2719
 
#ifdef USE_X11
2720
 
  if (_steal_drag)
2721
 
  {
2722
 
    for (auto const& uri : _dnd_data.Uris())
2723
 
    {
2724
 
      if (DndIsSpecialRequest(uri))
2725
 
        add_request.emit(uri, _dnd_hovered_icon);
2726
 
    }
2727
 
  }
2728
 
  else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
2729
 
  {
2730
 
     if (IsOverlayOpen())
2731
 
       ubus_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
2732
 
 
2733
 
    _dnd_hovered_icon->AcceptDrop(_dnd_data);
2734
 
  }
2735
 
 
2736
 
  if (_drag_action != nux::DNDACTION_NONE)
2737
 
    SendDndFinished(true, _drag_action);
2738
 
  else
2739
 
    SendDndFinished(false, _drag_action);
2740
 
 
2741
 
  // reset our shiz
2742
 
  DndReset();
2743
 
#endif
2744
 
}
2745
 
 
2746
 
/*
2747
 
 * Returns the current selected icon if it is in keynavmode
2748
 
 * It will return NULL if it is not on keynavmode
2749
 
 */
2750
 
AbstractLauncherIcon::Ptr Launcher::GetSelectedMenuIcon() const
2751
 
{
2752
 
  if (!IsInKeyNavMode())
2753
 
    return AbstractLauncherIcon::Ptr();
2754
 
 
2755
 
  return _model->Selection();
2756
 
}
2757
 
 
2758
 
//
2759
 
// Key navigation
2760
 
//
2761
 
bool Launcher::InspectKeyEvent(unsigned int eventType,
2762
 
                          unsigned int keysym,
2763
 
                          const char* character)
2764
 
{
2765
 
  // The Launcher accepts all key inputs.
2766
 
  return true;
2767
 
}
2768
 
 
2769
 
int Launcher::GetDragDelta() const
2770
 
{
2771
 
  return _launcher_drag_delta;
2772
 
}
2773
 
 
2774
 
void Launcher::DndStarted(std::string const& data)
2775
 
{
2776
 
#ifdef USE_X11
2777
 
  SetDndQuirk();
2778
 
 
2779
 
  _dnd_data.Fill(data.c_str());
2780
 
 
2781
 
  auto const& uris = _dnd_data.Uris();
2782
 
  if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
2783
 
                   {return DndIsSpecialRequest(uri);}) != uris.end())
2784
 
  {
2785
 
    _steal_drag = true;
2786
 
 
2787
 
    if (IsOverlayOpen())
2788
 
      SaturateIcons();
2789
 
  }
2790
 
  else
2791
 
  {
2792
 
    for (auto const& it : *_model)
2793
 
    {
2794
 
      if (it->ShouldHighlightOnDrag(_dnd_data))
2795
 
      {
2796
 
        it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2797
 
        it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true);
2798
 
      }
2799
 
      else
2800
 
      {
2801
 
        it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
2802
 
        it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false);
2803
 
      }
2804
 
    }
2805
 
  }
2806
 
#endif
2807
 
}
2808
 
 
2809
 
void Launcher::DndFinished()
2810
 
{
2811
 
#ifdef USE_X11
2812
 
  UnsetDndQuirk();
2813
 
 
2814
 
  _data_checked = false;
2815
 
 
2816
 
  if (IsOverlayOpen() && !_hovered)
2817
 
    DesaturateIcons();
2818
 
 
2819
 
  DndReset();
2820
 
#endif
2821
 
}
2822
 
 
2823
 
void Launcher::SetDndQuirk()
2824
 
{
2825
 
#ifdef USE_X11
2826
 
  _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
2827
 
#endif
2828
 
}
2829
 
 
2830
 
void Launcher::UnsetDndQuirk()
2831
 
{
2832
 
#ifdef USE_X11
2833
 
  _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
2834
 
  _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
2835
 
#endif
2836
 
}
2837
 
 
2838
 
} // namespace launcher
2839
 
} // namespace unity