1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
3
* Copyright (C) 2010 Canonical Ltd
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 3 as
7
* published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Authored by: Jason Smith <jason.smith@canonical.com>
18
* Authored by: Jay Taoko <jay.taoko@canonical.com>
25
#include <Nux/VScrollBar.h>
26
#include <Nux/HLayout.h>
27
#include <Nux/VLayout.h>
28
#include <NuxCore/Logger.h>
30
#include <NuxGraphics/NuxGraphics.h>
31
#include <NuxGraphics/GestureEvent.h>
32
#include <NuxGraphics/GpuDevice.h>
33
#include <NuxGraphics/GLTextureResourceManager.h>
35
#include <Nux/BaseWindow.h>
36
#include <Nux/WindowCompositor.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"
55
#include <UnityCore/GLibWrapper.h>
56
#include <UnityCore/Variant.h>
58
#include <boost/algorithm/string.hpp>
59
#include <sigc++/sigc++.h>
64
using ui::Decaymulator;
68
DECLARE_LOGGER(logger, "unity.launcher");
70
const char* window_title = "unity-launcher";
74
const int URGENT_BLINKS = 3;
75
const int WIGGLE_CYCLES = 6;
77
const int MAX_STARTING_BLINKS = 5;
78
const int STARTING_BLINK_LAMBDA = 3;
80
const int PULSE_BLINK_LAMBDA = 2;
82
const float BACKLIGHT_STRENGTH = 0.9f;
83
const int ICON_PADDING = 6;
84
const int RIGHT_LINE_WIDTH = 1;
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;
91
const int MOUSE_DEADZONE = 15;
92
const float DRAG_OUT_PIXELS = 300.0f;
94
const int SCROLL_AREA_HEIGHT = 24;
95
const int SCROLL_FPS = 30;
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";
103
NUX_IMPLEMENT_OBJECT_TYPE(Launcher);
105
const int Launcher::Launcher::ANIM_DURATION_SHORT = 125;
107
Launcher::Launcher(MockableBaseWindow* parent,
109
: View(NUX_FILE_LINE_PARAM)
111
, display(nux::GetGraphicsDisplay()->GetX11Display())
117
, _active_quicklist(nullptr)
120
, _shortcuts_shown(false)
121
, _data_checked(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)
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)
145
, _last_button_press(0)
146
, _drag_out_delta_x(0.0f)
147
, _drag_gesture_ongoing(false)
148
, _last_reveal_progress(0.0f)
150
, icon_renderer(std::make_shared<ui::IconRenderer>())
152
m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
153
icon_renderer->monitor = monitor();
155
bg_effect_helper_.owner = this;
156
bg_effect_helper_.enabled = false;
158
SetCompositionLayout(m_Layout);
159
CaptureMouseDownAnyWhereElse(true);
160
SetAcceptKeyNavFocusOnMouseDown(false);
161
SetAcceptMouseWheelEvent(true);
162
SetDndEnabled(false, true);
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));
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));
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));
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));
188
// 0 out timers to avoid wonky startups
189
for (int i = 0; i < TIME_LAST; ++i)
191
_times[i].tv_sec = 0;
192
_times[i].tv_nsec = 0;
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));
199
icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons);
201
TextureCache& cache = TextureCache::GetDefault();
202
launcher_sheen_ = cache.FindTexture("dash_sheen.png");
203
launcher_pressure_effect_ = cache.FindTexture("launcher_pressure_effect.png");
205
options.changed.connect(sigc::mem_fun(this, &Launcher::OnOptionsChanged));
206
monitor.changed.connect(sigc::mem_fun(this, &Launcher::OnMonitorChanged));
210
std::string Launcher::GetName() const
215
#ifdef NUX_GESTURES_SUPPORT
216
void Launcher::OnDragStart(const nux::GestureEvent &event)
218
_drag_gesture_ongoing = true;
221
_drag_out_delta_x = 0.0f;
225
_drag_out_delta_x = DRAG_OUT_PIXELS;
226
_hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
230
void Launcher::OnDragUpdate(const nux::GestureEvent &event)
233
CLAMP(_drag_out_delta_x + event.GetDelta().x, 0.0f, DRAG_OUT_PIXELS);
237
void Launcher::OnDragFinish(const nux::GestureEvent &event)
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);
245
_drag_gesture_ongoing = false;
249
void Launcher::AddProperties(GVariantBuilder* builder)
252
clock_gettime(CLOCK_MONOTONIC, ¤t);
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);
273
void Launcher::SetMousePosition(int x, int y)
275
bool beyond_drag_threshold = MouseBeyondDragThreshold();
276
_mouse_position = nux::Point2(x, y);
278
if (beyond_drag_threshold != MouseBeyondDragThreshold())
279
TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT);
284
void Launcher::SetStateMouseOverLauncher(bool over_launcher)
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);
292
void Launcher::SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon)
294
if (_icon_under_mouse == icon)
297
if (_icon_under_mouse)
298
_icon_under_mouse->mouse_leave.emit(monitor);
300
icon->mouse_enter.emit(monitor);
302
_icon_under_mouse = icon;
305
bool Launcher::MouseBeyondDragThreshold() const
307
if (GetActionState() == ACTION_DRAG_ICON)
308
return _mouse_position.x > GetGeometry().width + _icon_size / 2;
312
/* Render Layout Logic */
313
float Launcher::GetHoverProgress(struct timespec const& current) const
316
return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_ENTER])) / (float) ANIM_DURATION, 0.0f, 1.0f);
318
return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_LEAVE])) / (float) ANIM_DURATION, 0.0f, 1.0f);
321
float Launcher::DnDExitProgress(struct timespec const& current) const
323
return pow(1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_END])) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f), 2);
326
float Launcher::DragOutProgress(struct timespec const& current) const
328
float timeout = CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_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);
331
if (_drag_gesture_ongoing
332
|| _hide_machine.GetQuirk(LauncherHideMachine::MT_DRAG_OUT))
335
return progress * (1.0f - timeout);
338
float Launcher::AutohideProgress(struct timespec const& current) const
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(¤t, &_times[TIME_AUTOHIDE])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
344
return animation_progress;
346
return 1.0f - animation_progress;
349
float Launcher::DragHideProgress(struct timespec const& current) const
351
if (_drag_edge_touching)
352
return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f);
354
return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f);
357
float Launcher::DragThresholdProgress(struct timespec const& current) const
359
if (MouseBeyondDragThreshold())
360
return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
362
return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
365
void Launcher::EnsureAnimation()
370
bool Launcher::IconNeedsAnimation(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
372
struct timespec time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
373
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT)
376
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING);
377
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT)
380
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
381
if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2))
384
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);
385
if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2))
388
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE);
389
if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2))
392
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED);
393
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION)
396
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
397
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION)
400
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);
401
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_LONG)
404
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED);
405
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION)
408
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS);
409
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION)
412
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM);
413
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION)
416
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT);
417
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT_SHORT)
420
time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_PRELIGHT);
421
if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION)
427
bool Launcher::AnimationInProgress() const
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
432
if (_last_reveal_progress != _hide_machine.reveal_progress)
435
// short circuit to avoid unneeded calculations
436
struct timespec current;
437
clock_gettime(CLOCK_MONOTONIC, ¤t);
439
// hover in animation
440
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_ENTER]) < ANIM_DURATION)
443
// hover out animation
444
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_LEAVE]) < ANIM_DURATION)
447
// drag end animation
448
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_END]) < ANIM_DURATION_LONG)
451
// hide animation (time only), position is trigger manually on the bfb
452
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_AUTOHIDE]) < ANIM_DURATION_SHORT)
455
// collapse animation on DND out of launcher space
456
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD]) < ANIM_DURATION_SHORT)
459
// hide animation for dnd
460
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH]) < ANIM_DURATION * 6)
463
// restore from drag_out animation
464
if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_OUT]) < ANIM_DURATION_SHORT)
467
// animations happening on specific icons
468
for (auto const &icon : *_model)
469
if (IconNeedsAnimation(icon, current))
475
/* Min is when you are on the trigger */
476
float Launcher::GetAutohidePositionMin() const
478
if (options()->auto_hide_animation() == SLIDE_ONLY || options()->auto_hide_animation() == FADE_AND_SLIDE)
483
/* Max is the initial state over the bfb */
484
float Launcher::GetAutohidePositionMax() const
486
if (options()->auto_hide_animation() == SLIDE_ONLY || options()->auto_hide_animation() == FADE_AND_SLIDE)
493
float Launcher::IconVisibleProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
495
if (!icon->IsVisibleOnMonitor(monitor))
498
if (icon->GetIconType() == AbstractLauncherIcon::IconType::HUD)
500
return icon->IsVisible() ? 1.0f : 0.0f;
503
if (icon->IsVisible())
505
struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
506
DeltaTime enter_ms = unity::TimeUtil::TimeDelta(¤t, &icon_visible_time);
507
return CLAMP((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
511
struct timespec icon_hide_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
512
DeltaTime hide_ms = unity::TimeUtil::TimeDelta(¤t, &icon_hide_time);
513
return 1.0f - CLAMP((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
517
void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current)
519
AbstractLauncherIcon::Ptr const& anchor = MouseIconIntersection(x, _enter_y);
524
for (AbstractLauncherIcon::Ptr const& model_icon : *_model)
526
if (model_icon == anchor)
528
position += _icon_size / 2;
529
_launcher_drag_delta = _enter_y - position;
531
if (position + _icon_size / 2 + _launcher_drag_delta > geo.height)
532
_launcher_drag_delta -= (position + _icon_size / 2 + _launcher_drag_delta) - geo.height;
536
position += (_icon_size + _space_between_icons) * IconVisibleProgress(model_icon, current);
541
float Launcher::IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
543
struct timespec icon_present_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED);
544
DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &icon_present_time);
545
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
547
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PRESENTED))
550
return 1.0f - result;
553
float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
555
struct timespec icon_unfold_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
556
DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &icon_unfold_time);
557
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
559
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED))
562
return 1.0f - result;
565
float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
567
struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);
568
DeltaTime urgent_ms = unity::TimeUtil::TimeDelta(¤t, &urgent_time);
571
if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
572
result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_SHORT * WIGGLE_CYCLES), 0.0f, 1.0f);
574
result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
576
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
579
return 1.0f - result;
582
float Launcher::IconDropDimValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
584
struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM);
585
DeltaTime dim_ms = unity::TimeUtil::TimeDelta(¤t, &dim_time);
586
float result = CLAMP((float) dim_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
588
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DROP_DIM))
589
return 1.0f - result;
594
float Launcher::IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
596
struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT);
597
DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &dim_time);
598
float result = CLAMP((float) ms / (float) ANIM_DURATION_SHORT_SHORT, 0.0f, 1.0f);
600
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT))
601
return 1.0f - result;
606
float Launcher::IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
608
struct timespec shimmer_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);
609
DeltaTime shimmer_ms = unity::TimeUtil::TimeDelta(¤t, &shimmer_time);
610
return CLAMP((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
613
float Launcher::IconCenterTransitionProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
615
struct timespec save_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED);
616
DeltaTime save_ms = unity::TimeUtil::TimeDelta(¤t, &save_time);
617
return CLAMP((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
620
float Launcher::IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
622
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
623
return 1.0f; // we are full on in a normal condition
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;
629
float Launcher::IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const ¤t) const
631
struct timespec pulse_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE);
632
DeltaTime pulse_ms = unity::TimeUtil::TimeDelta(¤t, &pulse_time);
633
double pulse_progress = (double) CLAMP((float) pulse_ms / (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), 0.0f, 1.0f);
635
if (pulse_progress == 1.0f)
636
icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, false);
638
return 0.5f + (float) (std::cos(M_PI * 2.0 * pulse_progress)) * 0.5f;
641
float Launcher::IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
643
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT))
644
return 0.0f; // we are full on in a normal condition
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;
650
float Launcher::IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
652
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
655
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING))
658
struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
659
DeltaTime starting_ms = unity::TimeUtil::TimeDelta(¤t, &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);
665
float Launcher::IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
667
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
670
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING))
673
struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
674
DeltaTime starting_ms = unity::TimeUtil::TimeDelta(¤t, &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);
677
if (starting_progress == 1.0f && !icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
679
icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false);
680
icon->ResetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
683
return 1.0f-(0.5f + (float)(std::cos(M_PI * (float)(MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
686
float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
690
struct timespec running_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING);
691
DeltaTime running_ms = unity::TimeUtil::TimeDelta(¤t, &running_time);
692
float running_progress = CLAMP((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
694
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
695
running_progress = 1.0f - running_progress;
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);
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;
707
backlight_strength = 0.0f;
709
switch (options()->launch_animation())
711
case LAUNCH_ANIMATION_NONE:
712
result = backlight_strength;
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);
720
result = backlight_strength; // The blink concept is a failure in this case (it just doesn't work right)
722
case LAUNCH_ANIMATION_PULSE:
723
if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
724
icon->ResetQuirkTime(AbstractLauncherIcon::Quirk::STARTING);
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));
732
result = 1.0f - CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f);
736
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE))
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));
743
result = 1.0f - CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f);
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);
753
float Launcher::IconProgressBias(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
755
struct timespec icon_progress_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS);
756
DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &icon_progress_time);
757
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
759
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PROGRESS))
760
return -1.0f + result;
765
bool Launcher::IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const
767
if (options()->backlight_mode() == BACKLIGHT_EDGE_TOGGLE)
770
if (options()->backlight_mode() == BACKLIGHT_NORMAL_EDGE_TOGGLE && !icon->WindowVisibleOnMonitor(monitor))
776
void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current, RenderArg& arg)
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;
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;
802
// trying to protect against flickering when icon is dragged from dash LP: #863230
806
arg.saturation = 0.0;
809
arg.active_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE);
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))
817
arg.active_arrow = false;
820
if (options()->show_for_all)
821
arg.running_on_viewport = icon->WindowVisibleOnViewport();
823
arg.running_on_viewport = icon->WindowVisibleOnMonitor(monitor);
825
guint64 shortcut = icon->GetShortcut();
827
arg.shortcut_label = (char) shortcut;
829
arg.shortcut_label = 0;
831
// we dont need to show strays
832
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING))
834
arg.window_indicators = 0;
838
if (options()->show_for_all)
839
arg.window_indicators = std::max<int> (icon->WindowsOnViewport().size(), 1);
841
arg.window_indicators = std::max<int> (icon->WindowsForMonitor(monitor).size(), 1);
843
if (icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH ||
844
icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
846
// TODO: also these icons should respect the actual windows they have
847
arg.window_indicators = 0;
851
arg.backlight_intensity = IconBackgroundIntensity(icon, current);
852
arg.shimmer_progress = IconShimmerProgress(icon, current);
854
float urgent_progress = IconUrgentProgress(icon, current);
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
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;
862
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT) && options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
864
arg.rotation.z = IconUrgentWiggleValue(icon, current);
867
if (IsInKeyNavMode())
869
if (icon == _model->Selection())
870
arg.keyboard_nav_hl = true;
874
void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon,
877
nux::Geometry const& parent_abs_geo,
878
float folding_threshold,
880
float folded_spacing,
881
float autohide_offset,
882
float folded_z_distance,
883
float animation_neg_rads,
884
struct timespec const& current)
886
SetupRenderArg(icon, current, arg);
891
float size_modifier = IconVisibleProgress(icon, current);
892
if (size_modifier < 1.0f)
894
arg.alpha *= size_modifier;
895
center.z = 300.0f * (1.0f - size_modifier);
898
float drop_dim_value = 0.2f + 0.8f * IconDropDimValue(icon, current);
900
if (drop_dim_value < 1.0f)
901
arg.alpha *= drop_dim_value;
903
// trying to protect against flickering when icon is dragged from dash LP: #863230
907
arg.saturation = 0.0;
910
if (icon == _drag_icon)
912
if (MouseBeyondDragThreshold())
913
arg.stick_thingy = true;
915
if (GetActionState() == ACTION_DRAG_ICON ||
916
(_drag_window && _drag_window->Animating()) ||
917
icon->GetIconType() == AbstractLauncherIcon::IconType::SPACER)
922
size_modifier *= DragThresholdProgress(current);
925
if (size_modifier <= 0.0f)
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);
932
folding_progress *= 1.0f - unfold_progress;
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;
937
float present_progress = IconPresentProgress(icon, current);
938
icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency());
940
// icon is crossing threshold, start folding
941
center.z += folded_z_distance * folding_progress;
942
arg.rotation.x = animation_neg_rads * folding_progress;
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;
947
nux::Point3 centerOffset;
948
float center_transit_progress = IconCenterTransitionProgress(icon, current);
949
if (center_transit_progress <= 1.0f)
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);
955
center.y += half_size * size_modifier; // move to center
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));
960
icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)), monitor, parent_abs_geo);
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())
965
auto const& icon_center = _drag_icon->GetCenter(monitor);
966
_drag_window->SetAnimationTarget(icon_center.x, icon_center.y);
969
center.y += (half_size * size_modifier) + spacing; // move to end
972
float Launcher::DragLimiter(float x)
974
float result = (1 - std::pow(159.0 / 160, std::abs(x))) * 160;
981
nux::Color FullySaturateColor (nux::Color color)
983
float max = std::max<float>(color.red, std::max<float>(color.green, color.blue));
986
color = color * (1.0f / max);
991
void Launcher::RenderArgs(std::list<RenderArg> &launcher_args,
992
nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo)
994
nux::Geometry const& geo = GetGeometry();
995
LauncherModel::iterator it;
997
struct timespec current;
998
clock_gettime(CLOCK_MONOTONIC, ¤t);
1000
nux::Color const& colorify = FullySaturateColor(options()->background_color);
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);
1006
float folding_constant = 0.25f;
1007
float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress);
1009
float folded_size = _icon_size * folding_not_constant;
1010
float folded_spacing = _space_between_icons * folding_not_constant;
1012
center.x = geo.width / 2;
1013
center.y = _space_between_icons;
1016
int launcher_height = geo.height;
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)
1023
float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
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;
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);
1033
if (sum - _space_between_icons <= launcher_height)
1034
folding_threshold = launcher_height;
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))
1041
float autohide_progress = AutohideProgress(current) * (1.0f - DragOutProgress(current));
1042
if (options()->auto_hide_animation() == FADE_ONLY)
1044
*launcher_alpha = 1.0f - autohide_progress;
1048
if (autohide_progress > 0.0f)
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;
1057
float drag_hide_progress = DragHideProgress(current);
1058
if (options()->hide_mode != LAUNCHER_HIDE_NEVER && drag_hide_progress > 0.0f)
1060
autohide_offset -= geo.width * 0.25f * drag_hide_progress;
1062
if (drag_hide_progress >= 1.0f)
1063
_hide_machine.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, true);
1066
// Inform the painter where to paint the box
1069
if (options()->hide_mode != LAUNCHER_HIDE_NEVER || _hide_machine.GetQuirk(LauncherHideMachine::LOCK_HIDE))
1070
box_geo.x += autohide_offset;
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.
1078
static nux::Geometry last_geo = box_geo;
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);
1084
// Update the last_geo value.
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);
1094
if (hover_progress > 0.0f && _launcher_drag_delta != 0)
1096
float delta_y = _launcher_drag_delta;
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);
1103
if (GetActionState() != ACTION_DRAG_LAUNCHER)
1105
float dnd_progress = DnDExitProgress(current);
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;
1112
if (dnd_progress == 0.0f)
1113
_launcher_drag_delta = (int) delta_y;
1116
delta_y *= hover_progress;
1117
center.y += delta_y;
1118
folding_threshold += delta_y;
1122
_launcher_drag_delta = 0;
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
1130
for (it = _model->main_begin(); it != _model->main_end(); ++it)
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);
1140
// compute maximum height of shelf
1141
float shelf_sum = 0.0f;
1142
for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it)
1144
float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
1145
shelf_sum += height;
1148
// add bottom padding
1149
if (shelf_sum > 0.0f)
1150
shelf_sum += _space_between_icons;
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;
1156
for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it)
1159
AbstractLauncherIcon::Ptr const& icon = *it;
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);
1168
/* End Render Layout Logic */
1170
void Launcher::ForceReveal(bool force_reveal)
1172
_hide_machine.SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, force_reveal);
1175
void Launcher::ShowShortcuts(bool show)
1177
_shortcuts_shown = show;
1178
_hide_machine.SetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE, show);
1182
void Launcher::OnLockHideChanged(GVariant *data)
1184
gboolean enable_lock = FALSE;
1185
g_variant_get(data, "(b)", &enable_lock);
1189
_hide_machine.SetQuirk(LauncherHideMachine::LOCK_HIDE, true);
1193
_hide_machine.SetQuirk(LauncherHideMachine::LOCK_HIDE, false);
1197
void Launcher::DesaturateIcons()
1199
for (auto icon : *_model)
1201
if (icon->GetIconType () != AbstractLauncherIcon::IconType::HOME &&
1202
icon->GetIconType () != AbstractLauncherIcon::IconType::HUD)
1204
icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
1207
icon->HideTooltip();
1211
void Launcher::SaturateIcons()
1213
for (auto icon : *_model)
1215
icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
1219
void Launcher::OnOverlayShown(GVariant* data)
1221
// check the type of overlay
1222
unity::glib::String overlay_identity;
1223
gboolean can_maximise = FALSE;
1224
gint32 overlay_monitor = 0;
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());
1230
LOG_DEBUG(logger) << "Overlay shown: " << identity
1231
<< ", " << (can_maximise ? "can maximise" : "can't maximise")
1232
<< ", on monitor " << overlay_monitor
1233
<< " (for monitor " << monitor() << ")";
1235
if (overlay_monitor == monitor())
1237
if (identity == "dash")
1239
_dash_is_open = true;
1240
_hide_machine.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, true);
1241
_hover_machine.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, true);
1243
if (identity == "hud")
1245
_hud_is_open = true;
1247
bg_effect_helper_.enabled = true;
1248
// Don't desaturate icons if the mouse is over the launcher:
1251
LOG_DEBUG(logger) << "Desaturate on monitor " << monitor();
1255
if (_icon_under_mouse)
1256
_icon_under_mouse->HideTooltip();
1261
void Launcher::OnOverlayHidden(GVariant* data)
1263
// check the type of overlay
1264
unity::glib::String overlay_identity;
1265
gboolean can_maximise = FALSE;
1266
gint32 overlay_monitor = 0;
1268
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
1269
&overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
1271
std::string identity = overlay_identity.Str();
1273
LOG_DEBUG(logger) << "Overlay hidden: " << identity
1274
<< ", " << (can_maximise ? "can maximise" : "can't maximise")
1275
<< ", on monitor " << overlay_monitor
1276
<< " (for monitor" << monitor() << ")";
1278
if (overlay_monitor == monitor())
1280
if (identity == "dash")
1282
_hide_machine.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, false);
1283
_hover_machine.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, false);
1284
_dash_is_open = false;
1286
else if (identity == "hud")
1288
_hud_is_open = false;
1291
// If they are both now shut, then disable the effect helper and saturate the icons.
1292
if (!IsOverlayOpen())
1294
bg_effect_helper_.enabled = false;
1295
LOG_DEBUG(logger) << "Saturate on monitor " << monitor();
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));
1307
bool Launcher::IsOverlayOpen() const
1309
return _dash_is_open || _hud_is_open;
1312
void Launcher::SetHidden(bool hide_launcher)
1314
if (hide_launcher == _hidden)
1317
_hidden = hide_launcher;
1318
_hide_machine.SetQuirk(LauncherHideMachine::LAUNCHER_HIDDEN, hide_launcher);
1319
_hover_machine.SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hide_launcher);
1323
_hide_machine.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false);
1324
_hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
1325
SetStateMouseOverLauncher(false);
1328
_postreveal_mousemove_delta_x = 0;
1329
_postreveal_mousemove_delta_y = 0;
1331
TimeUtil::SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT);
1333
if (nux::GetWindowThread()->IsEmbeddedWindow())
1334
_parent->EnableInputWindow(!hide_launcher, launcher::window_title, false, false);
1336
if (!hide_launcher && GetActionState() == ACTION_DRAG_EXTERNAL)
1341
hidden_changed.emit();
1344
void Launcher::UpdateChangeInMousePosition(int delta_x, int delta_y)
1346
_postreveal_mousemove_delta_x += delta_x;
1347
_postreveal_mousemove_delta_y += delta_y;
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))
1354
_hide_machine.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
1358
int Launcher::GetMouseX() const
1360
return _mouse_position.x;
1363
int Launcher::GetMouseY() const
1365
return _mouse_position.y;
1368
void Launcher::OnPluginStateChanged()
1370
WindowManager& wm = WindowManager::Default();
1371
_hide_machine.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, wm.IsExpoActive());
1372
_hide_machine.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, wm.IsScaleActive());
1375
LauncherHideMode Launcher::GetHideMode() const
1377
return options()->hide_mode;
1380
/* End Launcher Show/Hide logic */
1382
void Launcher::OnOptionsChanged(Options::Ptr options)
1384
UpdateOptions(options);
1385
options->option_changed.connect(sigc::mem_fun(this, &Launcher::OnOptionChanged));
1388
void Launcher::OnOptionChanged()
1390
UpdateOptions(options());
1393
void Launcher::OnMonitorChanged(int new_monitor)
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;
1403
void Launcher::UpdateOptions(Options::Ptr options)
1405
SetIconSize(options->tile_size, options->icon_size);
1406
SetHideMode(options->hide_mode);
1412
void Launcher::ConfigureBarrier()
1414
float decay_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .3f) + 1;
1415
float reveal_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .025f) + 1;
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;
1421
void Launcher::SetHideMode(LauncherHideMode hidemode)
1423
bool fixed_launcher = (hidemode == LAUNCHER_HIDE_NEVER);
1424
_parent->InputWindowEnableStruts(fixed_launcher);
1425
_hide_machine.SetMode(static_cast<LauncherHideMachine::HideMode>(hidemode));
1429
BacklightMode Launcher::GetBacklightMode() const
1431
return options()->backlight_mode();
1434
bool Launcher::IsBackLightModeToggles() const
1436
switch (options()->backlight_mode()) {
1437
case BACKLIGHT_NORMAL:
1438
case BACKLIGHT_EDGE_TOGGLE:
1439
case BACKLIGHT_NORMAL_EDGE_TOGGLE:
1446
nux::ObjectPtr<nux::View> const& Launcher::GetActiveTooltip() const
1448
return _active_tooltip;
1451
nux::ObjectPtr<LauncherDragWindow> const& Launcher::GetDraggedIcon() const
1453
return _drag_window;
1456
void Launcher::SetActionState(LauncherActionState actionstate)
1458
if (_launcher_action_state == actionstate)
1461
_launcher_action_state = actionstate;
1463
_hover_machine.SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE));
1466
Launcher::LauncherActionState
1467
Launcher::GetActionState() const
1469
return _launcher_action_state;
1472
void Launcher::SetHover(bool hovered)
1474
if (hovered == _hovered)
1481
_enter_y = (int) _mouse_position.y;
1482
TimeUtil::SetTimeStruct(&_times[TIME_ENTER], &_times[TIME_LEAVE], ANIM_DURATION);
1486
TimeUtil::SetTimeStruct(&_times[TIME_LEAVE], &_times[TIME_ENTER], ANIM_DURATION);
1489
if (IsOverlayOpen() && !_hide_machine.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
1491
if (hovered && !_hide_machine.GetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE))
1500
bool Launcher::MouseOverTopScrollArea()
1502
return _mouse_position.y < SCROLL_AREA_HEIGHT;
1505
bool Launcher::MouseOverBottomScrollArea()
1507
return _mouse_position.y >= GetGeometry().height - SCROLL_AREA_HEIGHT;
1510
bool Launcher::OnScrollTimeout()
1512
bool continue_animation = true;
1515
if (IsInKeyNavMode() || !_hovered ||
1516
GetActionState() == ACTION_DRAG_LAUNCHER)
1518
continue_animation = false;
1520
else if (MouseOverTopScrollArea())
1522
if (_launcher_drag_delta >= _launcher_drag_delta_max)
1523
continue_animation = false;
1526
speed = (SCROLL_AREA_HEIGHT - _mouse_position.y) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
1527
_launcher_drag_delta += speed;
1530
else if (MouseOverBottomScrollArea())
1532
if (_launcher_drag_delta <= _launcher_drag_delta_min)
1533
continue_animation = false;
1536
speed = ((_mouse_position.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT)) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
1537
_launcher_drag_delta -= speed;
1542
continue_animation = false;
1545
if (continue_animation)
1550
return continue_animation;
1553
void Launcher::EnsureScrollTimer()
1555
bool needed = MouseOverTopScrollArea() || MouseOverBottomScrollArea();
1557
if (needed && !sources_.GetSource(SCROLL_TIMEOUT))
1559
sources_.AddTimeout(20, sigc::mem_fun(this, &Launcher::OnScrollTimeout), SCROLL_TIMEOUT);
1563
sources_.Remove(SCROLL_TIMEOUT);
1567
void Launcher::SetIconSize(int tile_size, int icon_size)
1569
ui::IconRenderer::DestroyShortcutTextures();
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;
1576
icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons);
1578
nux::Geometry const& parent_geo = _parent->GetGeometry();
1579
Resize(nux::Point(parent_geo.x, parent_geo.y), parent_geo.height);
1582
int Launcher::GetIconSize() const
1587
void Launcher::Resize(nux::Point const& offset, int height)
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));
1597
void Launcher::OnIconAdded(AbstractLauncherIcon::Ptr const& icon)
1601
icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
1602
icon->tooltip_visible.connect(sigc::mem_fun(this, &Launcher::OnTooltipVisible));
1605
void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr const& icon)
1607
if (icon->needs_redraw_connection.connected())
1608
icon->needs_redraw_connection.disconnect();
1610
SetIconUnderMouse(AbstractLauncherIcon::Ptr());
1611
if (icon == _icon_mouse_down)
1612
_icon_mouse_down = nullptr;
1613
if (icon == _drag_icon)
1614
_drag_icon = nullptr;
1619
void Launcher::OnOrderChanged()
1624
void Launcher::SetModel(LauncherModel::Ptr model)
1628
for (auto icon : *_model)
1629
icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
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));
1637
LauncherModel::Ptr Launcher::GetModel() const
1642
void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& selection)
1644
nux::Geometry const& geo = GetGeometry();
1647
for (auto icon : *_model)
1649
if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
1652
if (icon == selection)
1655
natural_y += _icon_size + _space_between_icons;
1658
int max_drag_delta = geo.height - (natural_y + _icon_size + (2 * _space_between_icons));
1659
int min_drag_delta = -natural_y;
1661
_launcher_drag_delta = std::max<int>(min_drag_delta, std::min<int>(max_drag_delta, _launcher_drag_delta));
1664
void Launcher::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection)
1666
if (IsInKeyNavMode())
1668
EnsureIconOnScreen(selection);
1673
void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon)
1678
void Launcher::OnTooltipVisible(nux::ObjectPtr<nux::View> view)
1680
_active_tooltip = view;
1683
void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
1688
void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
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;
1696
// rely on the compiz event loop to come back to us in a nice throttling
1697
if (AnimationInProgress())
1699
auto idle = std::make_shared<glib::Idle>(glib::Source::Priority::DEFAULT);
1700
sources_.Add(idle, ANIMATION_IDLE);
1709
ROP.SrcBlend = GL_ONE;
1710
ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
1712
nux::Geometry const& geo_absolute = GetAbsoluteGeometry();
1713
RenderArgs(args, bkg_box, &launcher_alpha, geo_absolute);
1714
bkg_box.width -= RIGHT_LINE_WIDTH;
1716
nux::Color clear_colour = nux::Color(0x00000000);
1718
if (Settings::Instance().GetLowGfxMode())
1720
clear_colour = options()->background_color;
1721
clear_colour.alpha = 1.0f;
1725
GfxContext.PushClippingRectangle(base);
1726
gPainter.PushDrawColorLayer(GfxContext, base, clear_colour, true, ROP);
1728
if (Settings::Instance().GetLowGfxMode() == false)
1730
GfxContext.GetRenderStates().SetBlend(true);
1731
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1732
GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
1737
// clip vertically but not horizontally
1738
GfxContext.PushClippingRectangle(nux::Geometry(base.x, bkg_box.y, base.width, bkg_box.height));
1740
float reveal_progress = _hide_machine.reveal_progress;
1741
if ((reveal_progress > 0 || _last_reveal_progress > 0) && launcher_pressure_effect_.IsValid())
1743
if (std::abs(_last_reveal_progress - reveal_progress) <= .1f)
1745
_last_reveal_progress = reveal_progress;
1749
if (_last_reveal_progress > reveal_progress)
1750
_last_reveal_progress -= .1f;
1752
_last_reveal_progress += .1f;
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(),
1762
if (Settings::Instance().GetLowGfxMode() == false)
1764
if (IsOverlayOpen())
1766
nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height);
1767
nux::ObjectPtr<nux::IOpenGLBaseTexture> blur_texture;
1769
if (BackgroundEffectHelper::blur_type != unity::BLUR_NONE && (bkg_box.x + bkg_box.width > 0))
1771
blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo);
1775
blur_texture = bg_effect_helper_.GetRegion(blur_geo);
1778
if (blur_texture.IsValid())
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;
1786
GfxContext.PushClippingRectangle(bkg_box);
1788
#ifndef NUX_OPENGLES_20
1789
if (GfxContext.UsingGLSLCodePath())
1790
gPainter.PushDrawCompositionLayer(GfxContext, base,
1794
options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY,
1797
gPainter.PushDrawTextureLayer(GfxContext, base,
1804
gPainter.PushDrawCompositionLayer(GfxContext, base,
1808
options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY,
1811
GfxContext.PopClippingRectangle();
1816
unsigned int alpha = 0, src = 0, dest = 0;
1817
GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
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);
1824
// apply the bg colour
1825
#ifndef NUX_OPENGLES_20
1826
if (GfxContext.UsingGLSLCodePath() == false)
1827
gPainter.Paint2DQuadColor(GfxContext, bkg_box, options()->background_color);
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(),
1842
//reset the blend state
1843
GfxContext.GetRenderStates().SetBlend (alpha, src, dest);
1847
nux::Color color = options()->background_color;
1848
color.alpha = options()->background_alpha;
1849
gPainter.Paint2DQuadColor(GfxContext, bkg_box, color);
1853
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1855
icon_renderer->PreprocessIcons(args, base);
1859
for (rev_it = args.rbegin(); rev_it != args.rend(); ++rev_it)
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));
1869
icon_renderer->RenderIcon(GfxContext, *rev_it, bkg_box, base);
1872
if (!IsOverlayOpen())
1874
const double right_line_opacity = 0.15f * launcher_alpha;
1876
gPainter.Paint2DQuadColor(GfxContext,
1877
nux::Geometry(bkg_box.x + bkg_box.width,
1881
nux::color::White * right_line_opacity);
1883
gPainter.Paint2DQuadColor(GfxContext,
1884
nux::Geometry(bkg_box.x,
1888
nux::Color(0x70000000),
1889
nux::Color(0x00000000),
1890
nux::Color(0x00000000),
1891
nux::Color(0x70000000));
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);
1899
GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
1900
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1902
gPainter.PopBackground(push_count);
1903
GfxContext.PopClippingRectangle();
1904
GfxContext.PopClippingRectangle();
1907
long Launcher::PostLayoutManagement(long LayoutResult)
1909
View::PostLayoutManagement(LayoutResult);
1911
SetMousePosition(0, 0);
1913
return nux::SIZE_EQUAL_HEIGHT | nux::SIZE_EQUAL_WIDTH;
1916
void Launcher::OnDragWindowAnimCompleted()
1922
bool Launcher::StartIconDragTimeout(int x, int y)
1924
// if we are still waiting…
1925
if (GetActionState() == ACTION_NONE)
1927
SetIconUnderMouse(AbstractLauncherIcon::Ptr());
1928
_initial_drag_animation = true;
1929
StartIconDragRequest(x, y);
1935
void Launcher::StartIconDragRequest(int x, int y)
1937
nux::Geometry const& abs_geo = GetAbsoluteGeometry();
1938
AbstractLauncherIcon::Ptr const& drag_icon = MouseIconIntersection(abs_geo.width / 2.0f, y);
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)
1944
auto const& icon_center = drag_icon->GetCenter(monitor);
1948
SetActionState(ACTION_DRAG_ICON);
1949
StartIconDrag(drag_icon);
1950
UpdateDragWindowPosition(icon_center.x, icon_center.y);
1952
if (_initial_drag_animation)
1954
_drag_window->SetAnimationTarget(x, y);
1955
_drag_window->StartQuickAnimation();
1962
_drag_icon = nullptr;
1967
void Launcher::StartIconDrag(AbstractLauncherIcon::Ptr const& icon)
1972
_hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
1974
_drag_icon_position = _model->IconIndex(icon);
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);
1982
ubus_.SendMessage(UBUS_LAUNCHER_ICON_START_DND);
1985
void Launcher::EndIconDrag()
1989
AbstractLauncherIcon::Ptr hovered_icon;
1991
if (!_drag_window->Cancelled())
1992
hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
1994
if (hovered_icon && hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
1996
hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true);
1998
remove_request.emit(_drag_icon);
2005
if (!_drag_window->Cancelled() && _model->IconIndex(_drag_icon) != _drag_icon_position)
2007
_drag_icon->Stick(false);
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));
2015
auto const& icon_center = _drag_icon->GetCenter(monitor);
2016
_drag_window->SetAnimationTarget(icon_center.x, icon_center.y),
2017
_drag_window->StartQuickAnimation();
2021
if (MouseBeyondDragThreshold())
2022
TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT);
2024
_hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, false);
2025
ubus_.SendMessage(UBUS_LAUNCHER_ICON_END_DND);
2028
void Launcher::ShowDragWindow()
2030
if (!_drag_window || _drag_window->IsVisible())
2033
_drag_window->GrabKeyboard();
2034
_drag_window->ShowWindow(true);
2035
_drag_window->PushToFront();
2038
AbstractLauncherIcon::Ptr const& closer = _model->GetClosestIcon(_drag_icon, is_before);
2039
_drag_window->drag_cancel_request.connect([this, closer, is_before] {
2041
_model->ReorderAfter(_drag_icon, closer);
2043
_model->ReorderBefore(_drag_icon, closer, true);
2045
ResetMouseDragState();
2049
void Launcher::HideDragWindow()
2051
nux::Geometry const& abs_geo = GetAbsoluteGeometry();
2052
nux::Point const& mouse = nux::GetWindowCompositor().GetMousePosition();
2054
if (abs_geo.IsInside(mouse))
2055
mouse_enter.emit(mouse.x - abs_geo.x, mouse.y - abs_geo.y, 0, 0);
2060
_drag_window->UnGrabKeyboard();
2061
_drag_window->ShowWindow(false);
2062
_drag_window = nullptr;
2065
void Launcher::UpdateDragWindowPosition(int x, int y)
2070
auto const& icon_geo = _drag_window->GetGeometry();
2071
_drag_window->SetBaseXY(x - icon_geo.width / 2, y - icon_geo.height / 2);
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, ¤t);
2080
float progress = DragThresholdProgress(current);
2082
if (hovered_icon && _drag_icon != hovered_icon)
2084
if (progress >= 1.0f)
2086
_model->ReorderSmart(_drag_icon, hovered_icon, true);
2088
else if (progress == 0.0f)
2090
_model->ReorderBefore(_drag_icon, hovered_icon, false);
2093
else if (!hovered_icon && progress == 0.0f)
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)
2098
auto const& icon = *it;
2100
if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
2103
if (y >= icon->GetCenter(monitor).y)
2105
_model->ReorderAfter(_drag_icon, icon);
2112
void Launcher::ResetMouseDragState()
2114
if (GetActionState() == ACTION_DRAG_ICON)
2117
if (GetActionState() == ACTION_DRAG_LAUNCHER)
2118
_hide_machine.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, false);
2120
SetActionState(ACTION_NONE);
2123
_last_button_press = 0;
2127
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
2129
_last_button_press = nux::GetEventButton(button_flags);
2130
SetMousePosition(x, y);
2132
MouseDownLogic(x, y, button_flags, key_flags);
2136
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
2138
SetMousePosition(x, y);
2140
MouseUpLogic(x, y, button_flags, key_flags);
2141
ResetMouseDragState();
2144
void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
2146
/* FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
2147
* on an internal Launcher property then
2150
if (_last_button_press != 1)
2153
SetMousePosition(x, y);
2155
// FIXME: hack (see SetupRenderArg)
2156
_initial_drag_animation = false;
2161
if (nux::Abs(_dnd_delta_y) < MOUSE_DEADZONE &&
2162
nux::Abs(_dnd_delta_x) < MOUSE_DEADZONE &&
2163
GetActionState() == ACTION_NONE)
2166
SetIconUnderMouse(AbstractLauncherIcon::Ptr());
2168
if (GetActionState() == ACTION_NONE)
2171
if (nux::Abs(_dnd_delta_y) >= nux::Abs(_dnd_delta_x))
2173
_launcher_drag_delta += _dnd_delta_y;
2174
SetActionState(ACTION_DRAG_LAUNCHER);
2175
_hide_machine.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true);
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);
2185
else if (GetActionState() == ACTION_DRAG_LAUNCHER)
2187
_launcher_drag_delta += dy;
2188
ubus_.SendMessage(UBUS_LAUNCHER_END_DND);
2190
else if (GetActionState() == ACTION_DRAG_ICON)
2192
nux::Geometry const& geo = GetAbsoluteGeometry();
2193
UpdateDragWindowPosition(geo.x + x, geo.y + y);
2199
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
2201
SetMousePosition(x, y);
2202
SetStateMouseOverLauncher(true);
2208
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
2210
SetStateMouseOverLauncher(false);
2215
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
2217
SetMousePosition(x, y);
2218
tooltip_manager_.MouseMoved(_icon_under_mouse);
2221
UpdateChangeInMousePosition(dx, dy);
2223
// Every time the mouse moves, we check if it is inside an icon...
2227
void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned long /*button_flags*/, unsigned long key_flags)
2232
bool alt_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_ALT);
2235
ScrollLauncher(wheel_delta);
2237
else if (_icon_under_mouse)
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);
2245
void Launcher::ScrollLauncher(int wheel_delta)
2247
if (wheel_delta < 0)
2249
_launcher_drag_delta -= 25;
2252
_launcher_drag_delta += 25;
2259
ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event)
2261
if (_hide_machine.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
2263
return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE;
2266
nux::Geometry const& abs_geo = GetAbsoluteGeometry();
2268
bool apply_to_reveal = false;
2269
if (event->x >= abs_geo.x && event->x <= abs_geo.x + abs_geo.width)
2272
return ui::EdgeBarrierSubscriber::Result::ALREADY_HANDLED;
2274
if (options()->reveal_trigger == RevealTrigger::EDGE)
2276
if (event->y >= abs_geo.y)
2277
apply_to_reveal = true;
2279
else if (options()->reveal_trigger == RevealTrigger::CORNER)
2281
if (event->y < abs_geo.y)
2282
apply_to_reveal = true;
2286
if (apply_to_reveal)
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();
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))
2296
if (mask_return & (Button1Mask | Button3Mask))
2297
return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE;
2301
if (!apply_to_reveal)
2302
return ui::EdgeBarrierSubscriber::Result::IGNORED;
2304
if (!owner->IsFirstEvent())
2305
_hide_machine.AddRevealPressure(event->velocity);
2307
return ui::EdgeBarrierSubscriber::Result::HANDLED;
2312
bool Launcher::IsInKeyNavMode() const
2314
return _hide_machine.GetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE);
2317
void Launcher::EnterKeyNavMode()
2319
_hide_machine.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true);
2320
_hover_machine.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true);
2324
void Launcher::ExitKeyNavMode()
2326
_hide_machine.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false);
2327
_hover_machine.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false);
2330
void Launcher::RecvQuicklistOpened(nux::ObjectPtr<QuicklistView> const& quicklist)
2332
UScreen* uscreen = UScreen::GetDefault();
2333
if (uscreen->GetMonitorGeometry(monitor).IsInside(nux::Point(quicklist->GetGeometry().x, quicklist->GetGeometry().y)))
2335
_hide_machine.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true);
2336
_hover_machine.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true);
2342
void Launcher::RecvQuicklistClosed(nux::ObjectPtr<QuicklistView> const& quicklist)
2344
nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
2345
if (!GetAbsoluteGeometry().IsInside(pt))
2347
// The Quicklist just closed and the mouse is outside the launcher.
2349
SetStateMouseOverLauncher(false);
2351
// Cancel any prior state that was set before the Quicklist appeared.
2352
SetActionState(ACTION_NONE);
2354
_hide_machine.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, false);
2355
_hover_machine.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, false);
2361
void Launcher::EventLogic()
2363
if (GetActionState() == ACTION_DRAG_ICON ||
2364
GetActionState() == ACTION_DRAG_LAUNCHER)
2367
AbstractLauncherIcon::Ptr launcher_icon;
2369
if (!_hidden && !IsInKeyNavMode() && _hovered)
2371
launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2374
SetIconUnderMouse(launcher_icon);
2377
void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
2379
AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
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);
2388
launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2389
tooltip_manager_.IconClicked();
2393
void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
2395
AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2397
sources_.Remove(START_DRAGICON_TIMEOUT);
2399
if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
2401
_icon_mouse_down->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2403
if (GetActionState() == ACTION_NONE)
2405
_icon_mouse_down->mouse_click.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2409
if (launcher_icon && (_icon_mouse_down != launcher_icon))
2411
launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags);
2414
if (GetActionState() == ACTION_DRAG_LAUNCHER)
2416
TimeUtil::SetTimeStruct(&_times[TIME_DRAG_END]);
2419
_icon_mouse_down = nullptr;
2422
AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const
2424
LauncherModel::iterator it;
2425
// We are looking for the icon at screen coordinates x, y;
2426
nux::Point2 mouse_position(x, y);
2429
for (it = _model->begin(); it != _model->end(); ++it)
2431
if (!(*it)->IsVisible() || !(*it)->IsVisibleOnMonitor(monitor))
2434
nux::Point2 screen_coord [4];
2435
for (int i = 0; i < 4; ++i)
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;
2441
inside = PointInside2DPolygon(screen_coord, 4, mouse_position, 1);
2446
return AbstractLauncherIcon::Ptr();
2449
void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon::Ptr const& icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture)
2452
struct timespec current;
2453
clock_gettime(CLOCK_MONOTONIC, ¤t);
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;
2462
arg.window_indicators = 0;
2465
std::list<RenderArg> drag_args;
2466
drag_args.push_front(arg);
2468
graphics::PushOffscreenRenderTarget(texture);
2470
unsigned int alpha = 0, src = 0, dest = 0;
2471
GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
2472
GfxContext.GetRenderStates().SetBlend(false);
2474
GfxContext.QRP_Color(0,
2476
texture->GetWidth(),
2477
texture->GetHeight(),
2478
nux::Color(0.0f, 0.0f, 0.0f, 0.0f));
2480
GfxContext.GetRenderStates().SetBlend(alpha, src, dest);
2482
nux::Geometry geo(0, 0, texture->GetWidth(), texture->GetWidth());
2484
icon_renderer->PreprocessIcons(drag_args, geo);
2485
icon_renderer->RenderIcon(GfxContext, arg, geo, geo);
2486
unity::graphics::PopOffscreenRenderTarget();
2489
#ifdef NUX_GESTURES_SUPPORT
2490
nux::GestureDeliveryRequest Launcher::GestureEvent(const nux::GestureEvent &event)
2494
case nux::EVENT_GESTURE_BEGIN:
2497
case nux::EVENT_GESTURE_UPDATE:
2498
OnDragUpdate(event);
2500
default: // EVENT_GESTURE_END
2501
OnDragFinish(event);
2505
return nux::GestureDeliveryRequest::NONE;
2509
bool Launcher::DndIsSpecialRequest(std::string const& uri) const
2511
return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);
2514
void Launcher::ProcessDndEnter()
2517
SetStateMouseOverLauncher(true);
2520
_drag_action = nux::DNDACTION_NONE;
2521
_steal_drag = false;
2522
_data_checked = false;
2523
_drag_edge_touching = false;
2524
_dnd_hovered_icon = nullptr;
2528
void Launcher::DndReset()
2533
bool is_overlay_open = IsOverlayOpen();
2535
for (auto it : *_model)
2537
auto icon_type = it->GetIconType();
2539
if (icon_type == AbstractLauncherIcon::IconType::HOME ||
2540
icon_type == AbstractLauncherIcon::IconType::HUD)
2542
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2546
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered);
2549
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false);
2552
DndHoveredIconReset();
2556
void Launcher::DndHoveredIconReset()
2559
_drag_edge_touching = false;
2560
SetActionState(ACTION_NONE);
2562
if (_steal_drag && _dnd_hovered_icon)
2564
_dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2565
_dnd_hovered_icon->remove.emit(_dnd_hovered_icon);
2568
if (!_steal_drag && _dnd_hovered_icon)
2569
_dnd_hovered_icon->SendDndLeave();
2571
_steal_drag = false;
2572
_dnd_hovered_icon = nullptr;
2576
void Launcher::ProcessDndLeave()
2579
SetStateMouseOverLauncher(false);
2581
DndHoveredIconReset();
2585
void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes)
2590
const std::string uri_list = "text/uri-list";
2591
_data_checked = true;
2593
auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
2596
for (auto const& mime : mimes)
2598
if (mime != uri_list)
2601
_dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
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())
2613
// only set hover once we know our first x/y
2614
SetActionState(ACTION_DRAG_EXTERNAL);
2615
SetStateMouseOverLauncher(true);
2617
if (!_steal_drag && !_dnd_data.Uris().empty())
2619
for (auto const& it : *_model)
2621
if (it->ShouldHighlightOnDrag(_dnd_data))
2622
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2624
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
2629
SetMousePosition(x - _parent->GetGeometry().x, y - _parent->GetGeometry().y);
2631
if (monitor() == 0 && !IsOverlayOpen() && _mouse_position.x == 0 && _mouse_position.y <= (_parent->GetGeometry().height - _icon_size - 2 * _space_between_icons) && !_drag_edge_touching)
2633
if (_dnd_hovered_icon)
2634
_dnd_hovered_icon->SendDndLeave();
2636
_drag_edge_touching = true;
2637
TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3);
2640
else if (_mouse_position.x != 0 && _drag_edge_touching)
2642
_drag_edge_touching = false;
2643
TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3);
2648
AbstractLauncherIcon::Ptr const& hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2650
bool hovered_icon_is_appropriate = false;
2653
if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
2654
_steal_drag = false;
2656
if (hovered_icon->position() == AbstractLauncherIcon::Position::FLOATING)
2657
hovered_icon_is_appropriate = true;
2662
_drag_action = nux::DNDACTION_COPY;
2663
if (!_dnd_hovered_icon && hovered_icon_is_appropriate)
2665
_dnd_hovered_icon = new SpacerLauncherIcon(monitor());
2666
_model->AddIcon(_dnd_hovered_icon);
2667
_model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true);
2669
else if (_dnd_hovered_icon)
2673
if (hovered_icon_is_appropriate)
2675
_model->ReorderSmart(_dnd_hovered_icon, hovered_icon, true);
2679
_dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2680
_dnd_hovered_icon->remove.emit(_dnd_hovered_icon);
2681
_dnd_hovered_icon = nullptr;
2688
if (!_drag_edge_touching && hovered_icon != _dnd_hovered_icon)
2692
hovered_icon->SendDndEnter();
2693
_drag_action = hovered_icon->QueryAcceptDrop(_dnd_data);
2697
_drag_action = nux::DNDACTION_NONE;
2700
if (_dnd_hovered_icon)
2701
_dnd_hovered_icon->SendDndLeave();
2703
_dnd_hovered_icon = hovered_icon;
2708
if (_drag_action != nux::DNDACTION_NONE)
2713
SendDndStatus(accept, _drag_action, nux::Geometry(x, y, 1, 1));
2717
void Launcher::ProcessDndDrop(int x, int y)
2722
for (auto const& uri : _dnd_data.Uris())
2724
if (DndIsSpecialRequest(uri))
2725
add_request.emit(uri, _dnd_hovered_icon);
2728
else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
2730
if (IsOverlayOpen())
2731
ubus_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
2733
_dnd_hovered_icon->AcceptDrop(_dnd_data);
2736
if (_drag_action != nux::DNDACTION_NONE)
2737
SendDndFinished(true, _drag_action);
2739
SendDndFinished(false, _drag_action);
2747
* Returns the current selected icon if it is in keynavmode
2748
* It will return NULL if it is not on keynavmode
2750
AbstractLauncherIcon::Ptr Launcher::GetSelectedMenuIcon() const
2752
if (!IsInKeyNavMode())
2753
return AbstractLauncherIcon::Ptr();
2755
return _model->Selection();
2761
bool Launcher::InspectKeyEvent(unsigned int eventType,
2762
unsigned int keysym,
2763
const char* character)
2765
// The Launcher accepts all key inputs.
2769
int Launcher::GetDragDelta() const
2771
return _launcher_drag_delta;
2774
void Launcher::DndStarted(std::string const& data)
2779
_dnd_data.Fill(data.c_str());
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())
2787
if (IsOverlayOpen())
2792
for (auto const& it : *_model)
2794
if (it->ShouldHighlightOnDrag(_dnd_data))
2796
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2797
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true);
2801
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
2802
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false);
2809
void Launcher::DndFinished()
2814
_data_checked = false;
2816
if (IsOverlayOpen() && !_hovered)
2823
void Launcher::SetDndQuirk()
2826
_hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
2830
void Launcher::UnsetDndQuirk()
2833
_hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
2834
_hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
2838
} // namespace launcher
2839
} // namespace unity