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 "Nux/MenuPage.h"
29
#include "NuxCore/Logger.h"
31
#include "NuxGraphics/NuxGraphics.h"
32
#include "NuxGraphics/GpuDevice.h"
33
#include "NuxGraphics/GLTextureResourceManager.h"
35
#include "Nux/BaseWindow.h"
36
#include "Nux/WindowCompositor.h"
38
#include "BamfLauncherIcon.h"
39
#include "FavoriteStore.h"
41
#include "LauncherIcon.h"
42
#include "SpacerLauncherIcon.h"
43
#include "LauncherModel.h"
44
#include "QuicklistManager.h"
45
#include "QuicklistView.h"
46
#include "IconRenderer.h"
48
#include "ubus-server.h"
49
#include "UBusMessages.h"
51
#include <UnityCore/Variant.h>
53
using namespace unity::ui;
55
using namespace unity::ui;
60
nux::logging::Logger logger("unity.launcher");
62
const int URGENT_BLINKS = 3;
63
const int WIGGLE_CYCLES = 6;
65
const int MAX_STARTING_BLINKS = 5;
66
const int STARTING_BLINK_LAMBDA = 3;
68
const int PULSE_BLINK_LAMBDA = 2;
70
const float BACKLIGHT_STRENGTH = 0.9f;
74
#define TRIGGER_SQR_RADIUS 25
76
#define MOUSE_DEADZONE 15
78
#define DRAG_OUT_PIXELS 300.0f
80
#define S_DBUS_NAME "com.canonical.Unity.Launcher"
81
#define S_DBUS_PATH "/com/canonical/Unity/Launcher"
82
#define S_DBUS_IFACE "com.canonical.Unity.Launcher"
84
// FIXME: key-code defines for Up/Down/Left/Right of numeric keypad - needs to
85
// be moved to the correct place in NuxGraphics-headers
86
#define NUX_KP_DOWN 0xFF99
87
#define NUX_KP_UP 0xFF97
88
#define NUX_KP_LEFT 0xFF96
89
#define NUX_KP_RIGHT 0xFF98
91
NUX_IMPLEMENT_OBJECT_TYPE(Launcher);
94
TimeDelta(struct timespec const* x, struct timespec const* y)
96
return ((x->tv_sec - y->tv_sec) * 1000) + ((x->tv_nsec - y->tv_nsec) / 1000000);
99
void SetTimeBack(struct timespec* timeref, int remove)
101
timeref->tv_sec -= remove / 1000;
102
remove = remove % 1000;
104
if (remove > timeref->tv_nsec / 1000000)
107
timeref->tv_nsec += 1000000000;
109
timeref->tv_nsec -= remove * 1000000;
112
const gchar Launcher::introspection_xml[] =
114
" <interface name='com.canonical.Unity.Launcher'>"
116
" <method name='AddLauncherItemFromPosition'>"
117
" <arg type='s' name='icon' direction='in'/>"
118
" <arg type='s' name='title' direction='in'/>"
119
" <arg type='i' name='icon_x' direction='in'/>"
120
" <arg type='i' name='icon_y' direction='in'/>"
121
" <arg type='i' name='icon_size' direction='in'/>"
122
" <arg type='s' name='desktop_file' direction='in'/>"
123
" <arg type='s' name='aptdaemon_task' direction='in'/>"
129
GDBusInterfaceVTable Launcher::interface_vtable =
131
Launcher::handle_dbus_method_call,
136
Launcher::Launcher(nux::BaseWindow* parent,
139
: View(NUX_FILE_LINE_PARAM)
140
, m_ContentOffsetY(0)
141
, m_BackgroundLayer(0)
143
, _background_color (nux::color::DimGray)
144
, _dash_is_open (false)
148
_active_quicklist = 0;
150
_hide_machine = new LauncherHideMachine();
151
_hide_machine->should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden));
152
_hover_machine = new LauncherHoverMachine();
153
_hover_machine->should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover));
155
_launcher_animation_timeout = 0;
157
m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
159
OnMouseDown.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
160
OnMouseUp.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
161
OnMouseDrag.connect(sigc::mem_fun(this, &Launcher::RecvMouseDrag));
162
OnMouseEnter.connect(sigc::mem_fun(this, &Launcher::RecvMouseEnter));
163
OnMouseLeave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave));
164
OnMouseMove.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove));
165
OnMouseWheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel));
166
OnKeyEvent.connect(sigc::mem_fun(this, &Launcher::RecvKeyPressed));
167
OnMouseDownOutsideArea.connect(sigc::mem_fun(this, &Launcher::RecvMouseDownOutsideArea));
168
//OnEndFocus.connect (sigc::mem_fun (this, &Launcher::exitKeyNavMode));
170
CaptureMouseDownAnyWhereElse(true);
172
QuicklistManager& ql_manager = *(QuicklistManager::Default());
173
ql_manager.quicklist_opened.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistOpened));
174
ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
176
PluginAdapter& plugin_adapter = *(PluginAdapter::Default());
177
plugin_adapter.window_maximized.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
178
plugin_adapter.window_restored.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
179
plugin_adapter.window_unminimized.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
180
plugin_adapter.window_mapped.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
181
plugin_adapter.window_unmapped.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
182
plugin_adapter.window_shown.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
183
plugin_adapter.window_hidden.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
184
plugin_adapter.window_resized.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
185
plugin_adapter.window_moved.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihide));
186
plugin_adapter.window_focus_changed.connect(sigc::mem_fun(this, &Launcher::OnWindowMaybeIntellihideDelayed));
187
plugin_adapter.window_mapped.connect(sigc::mem_fun(this, &Launcher::OnWindowMapped));
188
plugin_adapter.window_unmapped.connect(sigc::mem_fun(this, &Launcher::OnWindowUnmapped));
190
plugin_adapter.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
191
plugin_adapter.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
192
plugin_adapter.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
193
plugin_adapter.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
195
GeisAdapter& adapter = *(GeisAdapter::Default(screen));
196
adapter.drag_start.connect(sigc::mem_fun(this, &Launcher::OnDragStart));
197
adapter.drag_update.connect(sigc::mem_fun(this, &Launcher::OnDragUpdate));
198
adapter.drag_finish.connect(sigc::mem_fun(this, &Launcher::OnDragFinish));
200
_current_icon = NULL;
201
_current_icon_index = -1;
202
_last_icon_index = -1;
204
SetCompositionLayout(m_Layout);
206
_folded_angle = 1.0f;
207
_neg_folded_angle = -1.0f;
208
_space_between_icons = 5;
210
_launcher_bottom_y = 0;
211
_folded_z_distance = 10.0f;
212
_launcher_action_state = ACTION_NONE;
213
_launch_animation = LAUNCH_ANIMATION_NONE;
214
_urgent_animation = URGENT_ANIMATION_NONE;
215
_autohide_animation = FADE_AND_SLIDE;
216
_hidemode = LAUNCHER_HIDE_NEVER;
217
_icon_under_mouse = NULL;
218
_icon_mouse_down = NULL;
220
_icon_image_size = 48;
221
_icon_glow_size = 62;
222
_icon_image_size_delta = 6;
223
_icon_size = _icon_image_size + _icon_image_size_delta;
224
_background_alpha = 0.6667; // about 0xAA
227
_launcher_drag_delta = 0;
231
_autoscroll_handle = 0;
232
_super_show_launcher_handle = 0;
233
_super_hide_launcher_handle = 0;
234
_super_show_shortcuts_handle = 0;
235
_start_dragicon_handle = 0;
236
_focus_keynav_handle = 0;
237
_dnd_check_handle = 0;
238
_ignore_repeat_shortcut_handle = 0;
240
_latest_shortcut = 0;
241
_super_pressed = false;
242
_shortcuts_shown = false;
246
_render_drag_window = false;
247
_drag_edge_touching = false;
248
_keynav_activated = false;
249
_backlight_mode = BACKLIGHT_NORMAL;
250
_last_button_press = 0;
253
_drag_out_delta_x = 0.0f;
256
_initial_drag_animation = false;
258
_check_window_over_launcher = true;
259
_postreveal_mousemove_delta_x = 0;
260
_postreveal_mousemove_delta_y = 0;
262
// set them to 1 instead of 0 to avoid :0 in case something is racy
266
// 0 out timers to avoid wonky startups
268
for (i = 0; i < TIME_LAST; ++i)
270
_times[i].tv_sec = 0;
271
_times[i].tv_nsec = 0;
275
_offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(2, 2, 1, nux::BITFMT_R8G8B8A8);
277
for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); ++i)
278
_ubus_handles[i] = 0;
280
UBusServer* ubus = ubus_server_get_default();
281
_ubus_handles[0] = ubus_server_register_interest(ubus,
282
UBUS_PLACE_VIEW_SHOWN,
283
(UBusCallback) &Launcher::OnPlaceViewShown,
286
_ubus_handles[1] = ubus_server_register_interest(ubus,
287
UBUS_PLACE_VIEW_HIDDEN,
288
(UBusCallback)&Launcher::OnPlaceViewHidden,
291
_ubus_handles[2] = ubus_server_register_interest(ubus,
292
UBUS_LAUNCHER_ACTION_DONE,
293
(UBusCallback) &Launcher::OnActionDone,
296
_ubus_handles[3] = ubus_server_register_interest (ubus,
297
UBUS_BACKGROUND_COLOR_CHANGED,
298
(UBusCallback) &Launcher::OnBGColorChanged,
301
_dbus_owner = g_bus_own_name(G_BUS_TYPE_SESSION,
303
(GBusNameOwnerFlags)(G_BUS_NAME_OWNER_FLAGS_REPLACE | G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT),
310
_settings = g_settings_new("com.canonical.Unity.Launcher");
311
_settings_changed_id = g_signal_connect(
312
_settings, "changed", (GCallback)(Launcher::SettingsChanged), this);
313
SettingsChanged(_settings, (gchar*)"shows-on-edge", this);
315
SetDndEnabled(false, true);
317
icon_renderer = AbstractIconRenderer::Ptr(new IconRenderer());
318
icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons);
320
// request the latest colour from bghash
321
ubus_server_send_message (ubus, UBUS_BACKGROUND_REQUEST_COLOUR_EMIT, NULL);
323
SetAcceptMouseWheelEvent(true);
326
Launcher::~Launcher()
328
g_bus_unown_name(_dbus_owner);
330
if (_dnd_check_handle)
331
g_source_remove(_dnd_check_handle);
332
if (_autoscroll_handle)
333
g_source_remove(_autoscroll_handle);
334
if (_focus_keynav_handle)
335
g_source_remove(_focus_keynav_handle);
336
if (_super_show_launcher_handle)
337
g_source_remove(_super_show_launcher_handle);
338
if (_super_show_shortcuts_handle)
339
g_source_remove(_super_show_shortcuts_handle);
340
if (_start_dragicon_handle)
341
g_source_remove(_start_dragicon_handle);
342
if (_ignore_repeat_shortcut_handle)
343
g_source_remove(_ignore_repeat_shortcut_handle);
344
if (_super_hide_launcher_handle)
345
g_source_remove(_super_hide_launcher_handle);
347
if (_settings_changed_id != 0)
348
g_signal_handler_disconnect((gpointer) _settings, _settings_changed_id);
349
g_object_unref(_settings);
351
if (_launcher_animation_timeout > 0)
352
g_source_remove(_launcher_animation_timeout);
354
UBusServer* ubus = ubus_server_get_default();
355
for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); ++i)
357
if (_ubus_handles[i] != 0)
358
ubus_server_unregister_interest(ubus, _ubus_handles[i]);
361
g_idle_remove_by_data(this);
363
delete _hover_machine;
364
delete _hide_machine;
375
Launcher::SettingsChanged(GSettings* settings, char* key, Launcher* self)
377
bool show_on_edge = g_settings_get_boolean(settings, "shows-on-edge") ? true : false;
378
self->_hide_machine->SetShowOnEdge(show_on_edge);
382
Launcher::OnDragStart(GeisAdapter::GeisDragData* data)
384
if (_drag_out_id && _drag_out_id == data->id)
387
if (data->touches == 4)
389
_drag_out_id = data->id;
392
_drag_out_delta_x = 0.0f;
396
_drag_out_delta_x = DRAG_OUT_PIXELS;
397
_hide_machine->SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
403
Launcher::OnDragUpdate(GeisAdapter::GeisDragData* data)
405
if (data->id == _drag_out_id)
407
_drag_out_delta_x = CLAMP(_drag_out_delta_x + data->delta_x, 0.0f, DRAG_OUT_PIXELS);
413
Launcher::OnDragFinish(GeisAdapter::GeisDragData* data)
415
if (data->id == _drag_out_id)
417
if (_drag_out_delta_x >= DRAG_OUT_PIXELS - 90.0f)
418
_hide_machine->SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true);
419
SetTimeStruct(&_times[TIME_DRAG_OUT], &_times[TIME_DRAG_OUT], ANIM_DURATION_SHORT);
426
Launcher::startKeyNavMode()
428
SetStateKeyNav(true);
429
_hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false);
434
// FIXME: long term solution is to rewrite the keynav handle
435
if (_focus_keynav_handle > 0)
436
g_source_remove(_focus_keynav_handle);
437
_focus_keynav_handle = g_timeout_add(ANIM_DURATION_SHORT, &Launcher::MoveFocusToKeyNavModeTimeout, this);
442
Launcher::MoveFocusToKeyNavModeTimeout(gpointer data)
444
Launcher* self = (Launcher*) data;
446
// move focus to key nav mode when activated
447
if (!(self->_keynav_activated))
450
if (self->_last_icon_index == -1)
452
self->_current_icon_index = 0;
455
self->_current_icon_index = self->_last_icon_index;
456
self->EnsureAnimation();
458
ubus_server_send_message(ubus_server_get_default(),
459
UBUS_LAUNCHER_START_KEY_NAV,
462
self->selection_change.emit();
463
self->_focus_keynav_handle = 0;
469
Launcher::leaveKeyNavMode(bool preserve_focus)
471
_last_icon_index = _current_icon_index;
472
_current_icon_index = -1;
475
ubus_server_send_message(ubus_server_get_default(),
476
UBUS_LAUNCHER_END_KEY_NAV,
477
g_variant_new_boolean(preserve_focus));
479
selection_change.emit();
483
Launcher::exitKeyNavMode()
485
if (!_keynav_activated)
490
SetStateKeyNav(false);
492
_current_icon_index = -1;
493
_last_icon_index = _current_icon_index;
495
ubus_server_send_message(ubus_server_get_default(),
496
UBUS_LAUNCHER_END_KEY_NAV,
497
g_variant_new_boolean(true));
498
selection_change.emit();
502
Launcher::AddProperties(GVariantBuilder* builder)
505
clock_gettime(CLOCK_MONOTONIC, ¤t);
507
unity::variant::BuilderWrapper(builder)
508
.add("hover-progress", GetHoverProgress(current))
509
.add("dnd-exit-progress", DnDExitProgress(current))
510
.add("autohide-progress", AutohideProgress(current))
511
.add("dnd-delta", _dnd_delta_y)
512
.add("floating", _floating)
513
.add("hovered", _hovered)
514
.add("hidemode", _hidemode)
515
.add("hidden", _hidden)
516
.add("hide-quirks", _hide_machine->DebugHideQuirks().c_str())
517
.add("hover-quirks", _hover_machine->DebugHoverQuirks().c_str());
520
void Launcher::SetMousePosition(int x, int y)
522
bool beyond_drag_threshold = MouseBeyondDragThreshold();
523
_mouse_position = nux::Point2(x, y);
525
if (beyond_drag_threshold != MouseBeyondDragThreshold())
526
SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT);
531
void Launcher::SetStateMouseOverLauncher(bool over_launcher)
533
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER, over_launcher);
534
_hover_machine->SetQuirk(LauncherHoverMachine::MOUSE_OVER_LAUNCHER, over_launcher);
538
// reset state for some corner case like x=0, show dash (leave event not received)
539
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, false);
543
void Launcher::SetStateKeyNav(bool keynav_activated)
545
_hide_machine->SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, keynav_activated);
546
_hover_machine->SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, keynav_activated);
548
_keynav_activated = keynav_activated;
551
bool Launcher::MouseBeyondDragThreshold()
553
if (GetActionState() == ACTION_DRAG_ICON)
554
return _mouse_position.x > GetGeometry().width + _icon_size / 2;
558
/* Render Layout Logic */
559
float Launcher::GetHoverProgress(struct timespec const& current)
562
return CLAMP((float)(TimeDelta(¤t, &_times[TIME_ENTER])) / (float) ANIM_DURATION, 0.0f, 1.0f);
564
return 1.0f - CLAMP((float)(TimeDelta(¤t, &_times[TIME_LEAVE])) / (float) ANIM_DURATION, 0.0f, 1.0f);
567
float Launcher::DnDExitProgress(struct timespec const& current)
569
return pow(1.0f - CLAMP((float)(TimeDelta(¤t, &_times[TIME_DRAG_END])) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f), 2);
572
float Launcher::DragOutProgress(struct timespec const& current)
574
float timeout = CLAMP((float)(TimeDelta(¤t, &_times[TIME_DRAG_OUT])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
575
float progress = CLAMP(_drag_out_delta_x / DRAG_OUT_PIXELS, 0.0f, 1.0f);
577
if (_drag_out_id || _hide_machine->GetQuirk(LauncherHideMachine::MT_DRAG_OUT))
579
return progress * (1.0f - timeout);
582
float Launcher::AutohideProgress(struct timespec const& current)
584
// time-based progress (full scale or finish the TRIGGER_AUTOHIDE_MIN -> 0.00f on bfb)
585
float animation_progress;
586
animation_progress = CLAMP((float)(TimeDelta(¤t, &_times[TIME_AUTOHIDE])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
588
return animation_progress;
590
return 1.0f - animation_progress;
593
float Launcher::DragHideProgress(struct timespec const& current)
595
if (_drag_edge_touching)
596
return CLAMP((float)(TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f);
598
return 1.0f - CLAMP((float)(TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f);
601
float Launcher::DragThresholdProgress(struct timespec const& current)
603
if (MouseBeyondDragThreshold())
604
return 1.0f - CLAMP((float)(TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
606
return CLAMP((float)(TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
609
gboolean Launcher::AnimationTimeout(gpointer data)
611
Launcher* self = (Launcher*) data;
613
self->_launcher_animation_timeout = 0;
617
void Launcher::EnsureAnimation()
622
bool Launcher::IconNeedsAnimation(LauncherIcon* icon, struct timespec const& current)
624
struct timespec time = icon->GetQuirkTime(LauncherIcon::QUIRK_VISIBLE);
625
if (TimeDelta(¤t, &time) < ANIM_DURATION_SHORT)
628
time = icon->GetQuirkTime(LauncherIcon::QUIRK_RUNNING);
629
if (TimeDelta(¤t, &time) < ANIM_DURATION_SHORT)
632
time = icon->GetQuirkTime(LauncherIcon::QUIRK_STARTING);
633
if (TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2))
636
time = icon->GetQuirkTime(LauncherIcon::QUIRK_URGENT);
637
if (TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2))
640
time = icon->GetQuirkTime(LauncherIcon::QUIRK_PULSE_ONCE);
641
if (TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2))
644
time = icon->GetQuirkTime(LauncherIcon::QUIRK_PRESENTED);
645
if (TimeDelta(¤t, &time) < ANIM_DURATION)
648
time = icon->GetQuirkTime(LauncherIcon::QUIRK_SHIMMER);
649
if (TimeDelta(¤t, &time) < ANIM_DURATION_LONG)
652
time = icon->GetQuirkTime(LauncherIcon::QUIRK_CENTER_SAVED);
653
if (TimeDelta(¤t, &time) < ANIM_DURATION)
656
time = icon->GetQuirkTime(LauncherIcon::QUIRK_PROGRESS);
657
if (TimeDelta(¤t, &time) < ANIM_DURATION)
660
time = icon->GetQuirkTime(LauncherIcon::QUIRK_DROP_DIM);
661
if (TimeDelta(¤t, &time) < ANIM_DURATION)
664
time = icon->GetQuirkTime(LauncherIcon::QUIRK_DESAT);
665
if (TimeDelta(¤t, &time) < ANIM_DURATION_LONG)
668
time = icon->GetQuirkTime(LauncherIcon::QUIRK_DROP_PRELIGHT);
669
if (TimeDelta(¤t, &time) < ANIM_DURATION)
675
bool Launcher::AnimationInProgress()
677
// performance here can be improved by caching the longer remaining animation found and short circuiting to that each time
678
// this way extra checks may be avoided
680
// short circuit to avoid unneeded calculations
681
struct timespec current;
682
clock_gettime(CLOCK_MONOTONIC, ¤t);
684
// hover in animation
685
if (TimeDelta(¤t, &_times[TIME_ENTER]) < ANIM_DURATION)
688
// hover out animation
689
if (TimeDelta(¤t, &_times[TIME_LEAVE]) < ANIM_DURATION)
692
// drag end animation
693
if (TimeDelta(¤t, &_times[TIME_DRAG_END]) < ANIM_DURATION_LONG)
696
// hide animation (time only), position is trigger manually on the bfb
697
if (TimeDelta(¤t, &_times[TIME_AUTOHIDE]) < ANIM_DURATION_SHORT)
700
// collapse animation on DND out of launcher space
701
if (TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD]) < ANIM_DURATION_SHORT)
704
// hide animation for dnd
705
if (TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH]) < ANIM_DURATION * 6)
708
// restore from drag_out animation
709
if (TimeDelta(¤t, &_times[TIME_DRAG_OUT]) < ANIM_DURATION_SHORT)
712
// animations happening on specific icons
713
LauncherModel::iterator it;
714
for (it = _model->begin(); it != _model->end(); it++)
715
if (IconNeedsAnimation(*it, current))
721
void Launcher::SetTimeStruct(struct timespec* timer, struct timespec* sister, int sister_relation)
723
struct timespec current;
724
clock_gettime(CLOCK_MONOTONIC, ¤t);
728
int diff = TimeDelta(¤t, sister);
730
if (diff < sister_relation)
732
int remove = sister_relation - diff;
733
SetTimeBack(¤t, remove);
737
timer->tv_sec = current.tv_sec;
738
timer->tv_nsec = current.tv_nsec;
740
/* Min is when you are on the trigger */
741
float Launcher::GetAutohidePositionMin()
743
if (_autohide_animation == SLIDE_ONLY || _autohide_animation == FADE_AND_SLIDE)
748
/* Max is the initial state over the bfb */
749
float Launcher::GetAutohidePositionMax()
751
if (_autohide_animation == SLIDE_ONLY || _autohide_animation == FADE_AND_SLIDE)
758
float IconVisibleProgress(LauncherIcon* icon, struct timespec const& current)
760
if (icon->GetQuirk(LauncherIcon::QUIRK_VISIBLE))
762
struct timespec icon_visible_time = icon->GetQuirkTime(LauncherIcon::QUIRK_VISIBLE);
763
int enter_ms = TimeDelta(¤t, &icon_visible_time);
764
return CLAMP((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
768
struct timespec icon_hide_time = icon->GetQuirkTime(LauncherIcon::QUIRK_VISIBLE);
769
int hide_ms = TimeDelta(¤t, &icon_hide_time);
770
return 1.0f - CLAMP((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
774
void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current)
776
LauncherIcon* anchor = 0;
777
LauncherModel::iterator it;
778
anchor = MouseIconIntersection(x, _enter_y);
783
for (it = _model->begin(); it != _model->end(); it++)
787
position += _icon_size / 2;
788
_launcher_drag_delta = _enter_y - position;
790
if (position + _icon_size / 2 + _launcher_drag_delta > geo.height)
791
_launcher_drag_delta -= (position + _icon_size / 2 + _launcher_drag_delta) - geo.height;
795
position += (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
800
float Launcher::IconPresentProgress(LauncherIcon* icon, struct timespec const& current)
802
struct timespec icon_present_time = icon->GetQuirkTime(LauncherIcon::QUIRK_PRESENTED);
803
int ms = TimeDelta(¤t, &icon_present_time);
804
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
806
if (icon->GetQuirk(LauncherIcon::QUIRK_PRESENTED))
809
return 1.0f - result;
812
float Launcher::IconUrgentProgress(LauncherIcon* icon, struct timespec const& current)
814
struct timespec urgent_time = icon->GetQuirkTime(LauncherIcon::QUIRK_URGENT);
815
int urgent_ms = TimeDelta(¤t, &urgent_time);
818
if (_urgent_animation == URGENT_ANIMATION_WIGGLE)
819
result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_SHORT * WIGGLE_CYCLES), 0.0f, 1.0f);
821
result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
823
if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT))
826
return 1.0f - result;
829
float Launcher::IconDropDimValue(LauncherIcon* icon, struct timespec const& current)
831
struct timespec dim_time = icon->GetQuirkTime(LauncherIcon::QUIRK_DROP_DIM);
832
int dim_ms = TimeDelta(¤t, &dim_time);
833
float result = CLAMP((float) dim_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
835
if (icon->GetQuirk(LauncherIcon::QUIRK_DROP_DIM))
836
return 1.0f - result;
841
float Launcher::IconDesatValue(LauncherIcon* icon, struct timespec const& current)
843
struct timespec dim_time = icon->GetQuirkTime(LauncherIcon::QUIRK_DESAT);
844
int ms = TimeDelta(¤t, &dim_time);
845
float result = CLAMP((float) ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
847
if (icon->GetQuirk(LauncherIcon::QUIRK_DESAT))
848
return 1.0f - result;
853
float Launcher::IconShimmerProgress(LauncherIcon* icon, struct timespec const& current)
855
struct timespec shimmer_time = icon->GetQuirkTime(LauncherIcon::QUIRK_SHIMMER);
856
int shimmer_ms = TimeDelta(¤t, &shimmer_time);
857
return CLAMP((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
860
float Launcher::IconCenterTransitionProgress(LauncherIcon* icon, struct timespec const& current)
862
struct timespec save_time = icon->GetQuirkTime(LauncherIcon::QUIRK_CENTER_SAVED);
863
int save_ms = TimeDelta(¤t, &save_time);
864
return CLAMP((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
867
float Launcher::IconUrgentPulseValue(LauncherIcon* icon, struct timespec const& current)
869
if (!icon->GetQuirk(LauncherIcon::QUIRK_URGENT))
870
return 1.0f; // we are full on in a normal condition
872
double urgent_progress = (double) IconUrgentProgress(icon, current);
873
return 0.5f + (float)(std::cos(M_PI * (float)(URGENT_BLINKS * 2) * urgent_progress)) * 0.5f;
876
float Launcher::IconPulseOnceValue(LauncherIcon *icon, struct timespec const ¤t)
878
struct timespec pulse_time = icon->GetQuirkTime(LauncherIcon::QUIRK_PULSE_ONCE);
879
int pulse_ms = TimeDelta(¤t, &pulse_time);
880
double pulse_progress = (double) CLAMP((float) pulse_ms / (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), 0.0f, 1.0f);
882
if (pulse_progress == 1.0f)
883
icon->SetQuirk(LauncherIcon::QUIRK_PULSE_ONCE, false);
885
return 0.5f + (float) (std::cos(M_PI * 2.0 * pulse_progress)) * 0.5f;
888
float Launcher::IconUrgentWiggleValue(LauncherIcon* icon, struct timespec const& current)
890
if (!icon->GetQuirk(LauncherIcon::QUIRK_URGENT))
891
return 0.0f; // we are full on in a normal condition
893
double urgent_progress = (double) IconUrgentProgress(icon, current);
894
return 0.3f * (float)(std::sin(M_PI * (float)(WIGGLE_CYCLES * 2) * urgent_progress)) * 0.5f;
897
float Launcher::IconStartingBlinkValue(LauncherIcon* icon, struct timespec const& current)
899
struct timespec starting_time = icon->GetQuirkTime(LauncherIcon::QUIRK_STARTING);
900
int starting_ms = TimeDelta(¤t, &starting_time);
901
double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * STARTING_BLINK_LAMBDA), 0.0f, 1.0f);
902
return 0.5f + (float)(std::cos(M_PI * (_backlight_mode != BACKLIGHT_NORMAL ? 4.0f : 3.0f) * starting_progress)) * 0.5f;
905
float Launcher::IconStartingPulseValue(LauncherIcon* icon, struct timespec const& current)
907
struct timespec starting_time = icon->GetQuirkTime(LauncherIcon::QUIRK_STARTING);
908
int starting_ms = TimeDelta(¤t, &starting_time);
909
double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f);
911
if (starting_progress == 1.0f && !icon->GetQuirk(LauncherIcon::QUIRK_RUNNING))
913
icon->SetQuirk(LauncherIcon::QUIRK_STARTING, false);
914
icon->ResetQuirkTime(LauncherIcon::QUIRK_STARTING);
917
return 0.5f + (float)(std::cos(M_PI * (float)(MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f;
920
float Launcher::IconBackgroundIntensity(LauncherIcon* icon, struct timespec const& current)
924
struct timespec running_time = icon->GetQuirkTime(LauncherIcon::QUIRK_RUNNING);
925
int running_ms = TimeDelta(¤t, &running_time);
926
float running_progress = CLAMP((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
928
if (!icon->GetQuirk(LauncherIcon::QUIRK_RUNNING))
929
running_progress = 1.0f - running_progress;
931
// After we finish a fade in from running, we can reset the quirk
932
if (running_progress == 1.0f && icon->GetQuirk(LauncherIcon::QUIRK_RUNNING))
933
icon->SetQuirk(LauncherIcon::QUIRK_STARTING, false);
935
float backlight_strength;
936
if (_backlight_mode == BACKLIGHT_ALWAYS_ON)
937
backlight_strength = BACKLIGHT_STRENGTH;
938
else if (_backlight_mode == BACKLIGHT_NORMAL)
939
backlight_strength = BACKLIGHT_STRENGTH * running_progress;
941
backlight_strength = 0.0f;
943
switch (_launch_animation)
945
case LAUNCH_ANIMATION_NONE:
946
result = backlight_strength;
948
case LAUNCH_ANIMATION_BLINK:
949
if (_backlight_mode == BACKLIGHT_ALWAYS_ON)
950
result = IconStartingBlinkValue(icon, current);
951
else if (_backlight_mode == BACKLIGHT_ALWAYS_OFF)
952
result = 1.0f - IconStartingBlinkValue(icon, current);
954
result = backlight_strength; // The blink concept is a failure in this case (it just doesn't work right)
956
case LAUNCH_ANIMATION_PULSE:
957
if (running_progress == 1.0f && icon->GetQuirk(LauncherIcon::QUIRK_RUNNING))
958
icon->ResetQuirkTime(LauncherIcon::QUIRK_STARTING);
960
result = backlight_strength;
961
if (_backlight_mode == BACKLIGHT_ALWAYS_ON)
962
result *= CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f);
963
else if (_backlight_mode == BACKLIGHT_NORMAL)
964
result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconStartingPulseValue(icon, current));
966
result = 1.0f - CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f);
970
if (icon->GetQuirk(LauncherIcon::QUIRK_PULSE_ONCE))
972
if (_backlight_mode == BACKLIGHT_ALWAYS_ON)
973
result *= CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f);
974
else if (_backlight_mode == BACKLIGHT_NORMAL)
975
result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconPulseOnceValue(icon, current));
977
result = 1.0f - CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f);
980
// urgent serves to bring the total down only
981
if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT) && _urgent_animation == URGENT_ANIMATION_PULSE)
982
result *= 0.2f + 0.8f * IconUrgentPulseValue(icon, current);
987
float Launcher::IconProgressBias(LauncherIcon* icon, struct timespec const& current)
989
struct timespec icon_progress_time = icon->GetQuirkTime(LauncherIcon::QUIRK_PROGRESS);
990
int ms = TimeDelta(¤t, &icon_progress_time);
991
float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
993
if (icon->GetQuirk(LauncherIcon::QUIRK_PROGRESS))
994
return -1.0f + result;
999
void Launcher::SetupRenderArg(LauncherIcon* icon, struct timespec const& current, RenderArg& arg)
1003
arg.saturation = IconDesatValue(icon, current);
1004
arg.running_arrow = icon->GetQuirk(LauncherIcon::QUIRK_RUNNING);
1005
arg.running_colored = icon->GetQuirk(LauncherIcon::QUIRK_URGENT);
1006
arg.running_on_viewport = icon->HasWindowOnViewport();
1007
arg.active_colored = false;
1008
arg.x_rotation = 0.0f;
1009
arg.y_rotation = 0.0f;
1010
arg.z_rotation = 0.0f;
1012
arg.stick_thingy = false;
1013
arg.keyboard_nav_hl = false;
1014
arg.progress_bias = IconProgressBias(icon, current);
1015
arg.progress = CLAMP(icon->GetProgress(), 0.0f, 1.0f);
1016
arg.draw_shortcut = _shortcuts_shown && !_hide_machine->GetQuirk(LauncherHideMachine::PLACES_VISIBLE);
1019
arg.active_arrow = icon->Type() == LauncherIcon::TYPE_HOME;
1021
arg.active_arrow = icon->GetQuirk(LauncherIcon::QUIRK_ACTIVE);
1023
guint64 shortcut = icon->GetShortcut();
1025
arg.shortcut_label = (char) shortcut;
1027
arg.shortcut_label = 0;
1029
// we dont need to show strays
1030
if (!icon->GetQuirk(LauncherIcon::QUIRK_RUNNING))
1032
if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT))
1034
arg.running_arrow = true;
1035
arg.window_indicators = 1;
1038
arg.window_indicators = 0;
1042
arg.window_indicators = icon->RelatedWindows();
1045
arg.backlight_intensity = IconBackgroundIntensity(icon, current);
1046
arg.shimmer_progress = IconShimmerProgress(icon, current);
1048
float urgent_progress = IconUrgentProgress(icon, current);
1050
if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT))
1051
urgent_progress = CLAMP(urgent_progress * 3.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
1053
urgent_progress = CLAMP(urgent_progress * 3.0f - 2.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
1054
arg.glow_intensity = urgent_progress;
1056
if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT) && _urgent_animation == URGENT_ANIMATION_WIGGLE)
1058
arg.z_rotation = IconUrgentWiggleValue(icon, current);
1061
// we've to walk the list since it is a STL-list and not a STL-vector, thus
1062
// we can't use the random-access operator [] :(
1063
LauncherModel::iterator it;
1065
for (it = _model->begin(), i = 0; it != _model->end(); it++, ++i)
1066
if (i == _current_icon_index && *it == icon)
1068
arg.keyboard_nav_hl = true;
1072
void Launcher::FillRenderArg(LauncherIcon* icon,
1074
nux::Point3& center,
1075
float folding_threshold,
1077
float folded_spacing,
1078
float autohide_offset,
1079
float folded_z_distance,
1080
float animation_neg_rads,
1081
struct timespec const& current)
1083
SetupRenderArg(icon, current, arg);
1088
float size_modifier = IconVisibleProgress(icon, current);
1089
if (size_modifier < 1.0f)
1091
arg.alpha *= size_modifier;
1092
center.z = 300.0f * (1.0f - size_modifier);
1095
float drop_dim_value = 0.2f + 0.8f * IconDropDimValue(icon, current);
1097
if (drop_dim_value < 1.0f)
1098
arg.alpha *= drop_dim_value;
1100
if (icon == _drag_icon)
1102
if (MouseBeyondDragThreshold())
1103
arg.stick_thingy = true;
1105
if (GetActionState() == ACTION_DRAG_ICON ||
1106
(_drag_window && _drag_window->Animating()) ||
1109
size_modifier *= DragThresholdProgress(current);
1112
if (size_modifier <= 0.0f)
1115
// goes for 0.0f when fully unfolded, to 1.0f folded
1116
float folding_progress = CLAMP((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
1117
float present_progress = IconPresentProgress(icon, current);
1119
folding_progress *= 1.0f - present_progress;
1121
float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
1122
float icon_hide_offset = autohide_offset;
1124
icon_hide_offset *= 1.0f - (present_progress * (_hide_machine->GetShowOnEdge() ? icon->PresentUrgency() : 0.0f));
1126
// icon is crossing threshold, start folding
1127
center.z += folded_z_distance * folding_progress;
1128
arg.x_rotation = animation_neg_rads * folding_progress;
1130
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);
1131
float spacing = (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
1133
nux::Point3 centerOffset;
1134
float center_transit_progress = IconCenterTransitionProgress(icon, current);
1135
if (center_transit_progress <= 1.0f)
1137
centerOffset.y = (icon->_saved_center.y - (center.y + (half_size * size_modifier))) * (1.0f - center_transit_progress);
1140
center.y += half_size * size_modifier; // move to center
1142
arg.render_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y + centerOffset.y), roundf(center.z));
1143
arg.logical_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y), roundf(center.z));
1145
icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)));
1147
// FIXME: this is a hack, we should have a look why SetAnimationTarget is necessary in SetAnimationTarget
1148
// we should ideally just need it at start to set the target
1149
if (!_initial_drag_animation && icon == _drag_icon && _drag_window && _drag_window->Animating())
1150
_drag_window->SetAnimationTarget((int) center.x, (int) center.y + _parent->GetGeometry().y);
1152
center.y += (half_size * size_modifier) + spacing; // move to end
1155
float Launcher::DragLimiter(float x)
1157
float result = (1 - std::pow(159.0 / 160, std::abs(x))) * 160;
1164
void Launcher::RenderArgs(std::list<RenderArg> &launcher_args,
1165
nux::Geometry& box_geo, float* launcher_alpha)
1167
nux::Geometry geo = GetGeometry();
1168
LauncherModel::iterator it;
1170
struct timespec current;
1171
clock_gettime(CLOCK_MONOTONIC, ¤t);
1173
float hover_progress = GetHoverProgress(current);
1174
float folded_z_distance = _folded_z_distance * (1.0f - hover_progress);
1175
float animation_neg_rads = _neg_folded_angle * (1.0f - hover_progress);
1177
float folding_constant = 0.25f;
1178
float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress);
1180
float folded_size = _icon_size * folding_not_constant;
1181
float folded_spacing = _space_between_icons * folding_not_constant;
1183
center.x = geo.width / 2;
1184
center.y = _space_between_icons;
1187
int launcher_height = geo.height;
1189
// compute required height of launcher AND folding threshold
1190
float sum = 0.0f + center.y;
1191
float folding_threshold = launcher_height - _icon_size / 2.5f;
1192
for (it = _model->begin(); it != _model->end(); it++)
1194
float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
1197
// magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";
1198
float magic_constant = 1.3f;
1200
float present_progress = IconPresentProgress(*it, current);
1201
folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * present_progress);
1204
if (sum - _space_between_icons <= launcher_height)
1205
folding_threshold = launcher_height;
1207
float autohide_offset = 0.0f;
1208
*launcher_alpha = 1.0f;
1209
if (_hidemode != LAUNCHER_HIDE_NEVER)
1212
float autohide_progress = AutohideProgress(current) * (1.0f - DragOutProgress(current));
1213
if (_autohide_animation == FADE_ONLY)
1214
*launcher_alpha = 1.0f - autohide_progress;
1217
if (autohide_progress > 0.0f)
1219
autohide_offset -= geo.width * autohide_progress;
1220
if (_autohide_animation == FADE_AND_SLIDE)
1221
*launcher_alpha = 1.0f - 0.5f * autohide_progress;
1226
float drag_hide_progress = DragHideProgress(current);
1227
if (_hidemode != LAUNCHER_HIDE_NEVER && drag_hide_progress > 0.0f)
1229
autohide_offset -= geo.width * 0.25f * drag_hide_progress;
1231
if (drag_hide_progress >= 1.0f)
1232
_hide_machine->SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, true);
1235
// Inform the painter where to paint the box
1238
if (_hidemode != LAUNCHER_HIDE_NEVER)
1239
box_geo.x += autohide_offset;
1241
/* Why we need last_geo? It stores the last box_geo (note: as it is a static variable,
1242
* it is initialized only first time). Infact we call SetDndDelta that calls MouseIconIntersection
1243
* that uses values (HitArea) that are computed in UpdateIconXForm.
1244
* The problem is that in DrawContent we calls first RenderArgs, then UpdateIconXForm. Just
1245
* use last_geo to hack this problem.
1247
static nux::Geometry last_geo = box_geo;
1249
// this happens on hover, basically its a flag and a value in one, we translate this into a dnd offset
1250
if (_enter_y != 0 && _enter_y + _icon_size / 2 > folding_threshold)
1251
SetDndDelta(last_geo.x + last_geo.width / 2, center.y, geo, current);
1253
// Update the last_geo value.
1257
if (hover_progress > 0.0f && _launcher_drag_delta != 0)
1259
float delta_y = _launcher_drag_delta;
1261
// logically dnd exit only restores to the clamped ranges
1262
// hover_progress restores to 0
1264
float min = MIN(0.0f, launcher_height - sum);
1266
if (_launcher_drag_delta > max)
1267
delta_y = max + DragLimiter(delta_y - max);
1268
else if (_launcher_drag_delta < min)
1269
delta_y = min + DragLimiter(delta_y - min);
1271
if (GetActionState() != ACTION_DRAG_LAUNCHER)
1273
float dnd_progress = DnDExitProgress(current);
1275
if (_launcher_drag_delta > max)
1276
delta_y = max + (delta_y - max) * dnd_progress;
1277
else if (_launcher_drag_delta < min)
1278
delta_y = min + (delta_y - min) * dnd_progress;
1280
if (dnd_progress == 0.0f)
1281
_launcher_drag_delta = (int) delta_y;
1284
delta_y *= hover_progress;
1285
center.y += delta_y;
1286
folding_threshold += delta_y;
1290
_launcher_drag_delta = 0;
1293
// The functional position we wish to represent for these icons is not smooth. Rather than introducing
1294
// special casing to represent this, we use MIN/MAX functions. This helps ensure that even though our
1295
// function is not smooth it is continuous, which is more important for our visual representation (icons
1296
// wont start jumping around). As a general rule ANY if () statements that modify center.y should be seen
1299
for (it = _model->main_begin(); it != _model->main_end(); it++)
1302
LauncherIcon* icon = *it;
1304
FillRenderArg(icon, arg, center, folding_threshold, folded_size, folded_spacing,
1305
autohide_offset, folded_z_distance, animation_neg_rads, current);
1307
launcher_args.push_back(arg);
1311
// compute maximum height of shelf
1312
float shelf_sum = 0.0f;
1313
for (it = _model->shelf_begin(); it != _model->shelf_end(); it++)
1315
float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current);
1316
shelf_sum += height;
1319
// add bottom padding
1320
if (shelf_sum > 0.0f)
1321
shelf_sum += _space_between_icons;
1323
float shelf_delta = MAX(((launcher_height - shelf_sum) + _space_between_icons) - center.y, 0.0f);
1324
folding_threshold += shelf_delta;
1325
center.y += shelf_delta;
1327
for (it = _model->shelf_begin(); it != _model->shelf_end(); it++)
1330
LauncherIcon* icon = *it;
1332
FillRenderArg(icon, arg, center, folding_threshold, folded_size, folded_spacing,
1333
autohide_offset, folded_z_distance, animation_neg_rads, current);
1335
launcher_args.push_back(arg);
1339
/* End Render Layout Logic */
1341
gboolean Launcher::TapOnSuper()
1343
struct timespec current;
1344
clock_gettime(CLOCK_MONOTONIC, ¤t);
1346
return (TimeDelta(¤t, &_times[TIME_TAP_SUPER]) < SUPER_TAP_DURATION);
1349
/* Launcher Show/Hide logic */
1351
void Launcher::StartKeyShowLauncher()
1353
_super_pressed = true;
1354
_hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false);
1356
SetTimeStruct(&_times[TIME_TAP_SUPER]);
1357
SetTimeStruct(&_times[TIME_SUPER_PRESSED]);
1359
if (_super_show_launcher_handle > 0)
1360
g_source_remove(_super_show_launcher_handle);
1361
_super_show_launcher_handle = g_timeout_add(SUPER_TAP_DURATION, &Launcher::SuperShowLauncherTimeout, this);
1363
if (_super_show_shortcuts_handle > 0)
1364
g_source_remove(_super_show_shortcuts_handle);
1365
_super_show_shortcuts_handle = g_timeout_add(SHORTCUTS_SHOWN_DELAY, &Launcher::SuperShowShortcutsTimeout, this);
1368
void Launcher::EndKeyShowLauncher()
1370
int remaining_time_before_hide;
1371
struct timespec current;
1372
clock_gettime(CLOCK_MONOTONIC, ¤t);
1374
_hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, false);
1375
_super_pressed = false;
1376
_shortcuts_shown = false;
1379
// remove further show launcher (which can happen when we close the dash with super)
1380
if (_super_show_launcher_handle > 0)
1381
g_source_remove(_super_show_launcher_handle);
1382
if (_super_show_shortcuts_handle > 0)
1383
g_source_remove(_super_show_shortcuts_handle);
1384
_super_show_launcher_handle = 0;
1385
_super_show_shortcuts_handle = 0;
1387
// it's a tap on super and we didn't use any shortcuts
1388
if (TapOnSuper() && !_latest_shortcut)
1389
ubus_server_send_message(ubus_server_get_default(), UBUS_DASH_EXTERNAL_ACTIVATION, NULL);
1391
remaining_time_before_hide = BEFORE_HIDE_LAUNCHER_ON_SUPER_DURATION - CLAMP((int)(TimeDelta(¤t, &_times[TIME_SUPER_PRESSED])), 0, BEFORE_HIDE_LAUNCHER_ON_SUPER_DURATION);
1393
if (_super_hide_launcher_handle > 0)
1394
g_source_remove(_super_hide_launcher_handle);
1395
_super_hide_launcher_handle = g_timeout_add(remaining_time_before_hide, &Launcher::SuperHideLauncherTimeout, this);
1398
gboolean Launcher::SuperHideLauncherTimeout(gpointer data)
1400
Launcher* self = (Launcher*) data;
1402
self->_hide_machine->SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, false);
1404
self->_super_hide_launcher_handle = 0;
1408
gboolean Launcher::SuperShowLauncherTimeout(gpointer data)
1410
Launcher* self = (Launcher*) data;
1412
self->_hide_machine->SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, true);
1414
self->_super_show_launcher_handle = 0;
1418
gboolean Launcher::SuperShowShortcutsTimeout(gpointer data)
1420
Launcher* self = (Launcher*) data;
1422
self->_shortcuts_shown = true;
1423
self->_hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, true);
1427
self->_super_show_shortcuts_handle = 0;
1431
void Launcher::OnBGColorChanged(GVariant *data, void *val)
1433
Launcher *self = (Launcher*)val;
1434
double red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f;
1436
g_variant_get(data, "(dddd)", &red, &green, &blue, &alpha);
1437
self->_background_color = nux::Color(red, green, blue, alpha);
1441
void Launcher::OnPlaceViewShown(GVariant* data, void* val)
1443
Launcher* self = (Launcher*)val;
1444
LauncherModel::iterator it;
1446
self->_dash_is_open = true;
1447
self->_hide_machine->SetQuirk(LauncherHideMachine::PLACES_VISIBLE, true);
1448
self->_hover_machine->SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, true);
1450
// TODO: add in a timeout for seeing the animation (and make it smoother)
1451
for (auto icon : *(self->_model))
1453
if (icon->Type () != LauncherIcon::TYPE_HOME)
1454
icon->SetQuirk(LauncherIcon::QUIRK_DESAT, true);
1455
icon->HideTooltip();
1459
void Launcher::OnPlaceViewHidden(GVariant* data, void* val)
1461
Launcher* self = (Launcher*)val;
1462
LauncherModel::iterator it;
1464
self->_dash_is_open = false;
1465
self->_hide_machine->SetQuirk(LauncherHideMachine::PLACES_VISIBLE, false);
1466
self->_hover_machine->SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, false);
1468
// as the leave event is no more received when the place is opened
1469
// FIXME: remove when we change the mouse grab strategy in nux
1470
nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
1472
self->SetStateMouseOverLauncher(self->GetAbsoluteGeometry().IsInside(pt));
1474
// TODO: add in a timeout for seeing the animation (and make it smoother)
1475
for (auto icon : *(self->_model))
1477
icon->SetQuirk(LauncherIcon::QUIRK_DESAT, false);
1481
void Launcher::OnActionDone(GVariant* data, void* val)
1483
Launcher* self = (Launcher*)val;
1484
self->_hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, true);
1487
void Launcher::SetHidden(bool hidden)
1489
if (hidden == _hidden)
1493
_hide_machine->SetQuirk(LauncherHideMachine::LAUNCHER_HIDDEN, hidden);
1494
_hover_machine->SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hidden);
1496
_hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false);
1497
if (_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE))
1498
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
1500
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false);
1504
_hide_machine->SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
1505
SetStateMouseOverLauncher(false);
1508
_postreveal_mousemove_delta_x = 0;
1509
_postreveal_mousemove_delta_y = 0;
1511
SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT);
1513
_parent->EnableInputWindow(!hidden, "launcher", false, false);
1515
if (!hidden && GetActionState() == ACTION_DRAG_EXTERNAL)
1520
hidden_changed.emit();
1524
Launcher::GetMouseX()
1526
return _mouse_position.x;
1530
Launcher::GetMouseY()
1532
return _mouse_position.y;
1536
Launcher::CheckIntersectWindow(CompWindow* window)
1538
nux::Geometry geo = GetAbsoluteGeometry();
1539
int intersect_types = CompWindowTypeNormalMask | CompWindowTypeDialogMask |
1540
CompWindowTypeModalDialogMask | CompWindowTypeUtilMask;
1542
if (!window || !(window->type() & intersect_types) || !window->isMapped() || !window->isViewable())
1545
if (CompRegion(window->borderRect()).intersects(CompRect(geo.x, geo.y, geo.width, geo.height)))
1552
Launcher::EnableCheckWindowOverLauncher(gboolean enabled)
1554
_check_window_over_launcher = enabled;
1558
Launcher::CheckWindowOverLauncher()
1560
CompWindowList window_list = _screen->windows();
1561
CompWindowList::iterator it;
1562
CompWindow* window = NULL;
1563
CompWindow* parent = NULL;
1564
int type_dialogs = CompWindowTypeDialogMask | CompWindowTypeModalDialogMask
1565
| CompWindowTypeUtilMask;
1568
bool active = false;
1570
// state has no mean right now, the check will be done again later
1571
if (!_check_window_over_launcher)
1574
window = _screen->findWindow(_screen->activeWindow());
1576
if (window && (window->type() & type_dialogs))
1577
parent = _screen->findWindow(window->transientFor());
1579
if (CheckIntersectWindow(window) || CheckIntersectWindow(parent))
1586
for (it = window_list.begin(); it != window_list.end(); it++)
1588
if (CheckIntersectWindow(*it))
1595
_hide_machine->SetQuirk(LauncherHideMachine::ANY_WINDOW_UNDER, any);
1596
_hide_machine->SetQuirk(LauncherHideMachine::ACTIVE_WINDOW_UNDER, active);
1600
Launcher::OnUpdateDragManagerTimeout(gpointer data)
1602
Launcher* self = (Launcher*) data;
1604
if (!self->_selection_atom)
1605
self->_selection_atom = XInternAtom(self->_screen->dpy(), "XdndSelection", false);
1607
Window drag_owner = XGetSelectionOwner(self->_screen->dpy(), self->_selection_atom);
1609
// evil hack because Qt does not release the seelction owner on drag finished
1610
Window root_r, child_r;
1611
int root_x_r, root_y_r, win_x_r, win_y_r;
1613
XQueryPointer(self->_screen->dpy(), self->_screen->root(), &root_r, &child_r, &root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask);
1615
if (drag_owner && (mask & (Button1Mask | Button2Mask | Button3Mask)))
1617
self->_hide_machine->SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
1621
self->_hide_machine->SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
1622
self->_hide_machine->SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, false);
1624
self->_dnd_check_handle = 0;
1629
Launcher::OnWindowMapped(guint32 xid)
1631
CompWindow* window = _screen->findWindow(xid);
1632
if (window && window->type() | CompWindowTypeDndMask)
1634
if (!_dnd_check_handle)
1635
_dnd_check_handle = g_timeout_add(200, &Launcher::OnUpdateDragManagerTimeout, this);
1640
Launcher::OnWindowUnmapped(guint32 xid)
1642
CompWindow* window = _screen->findWindow(xid);
1643
if (window && window->type() | CompWindowTypeDndMask)
1645
if (!_dnd_check_handle)
1646
_dnd_check_handle = g_timeout_add(200, &Launcher::OnUpdateDragManagerTimeout, this);
1650
// FIXME: remove those 2 for Oneiric
1652
Launcher::OnWindowMaybeIntellihide(guint32 xid)
1654
if (_hidemode != LAUNCHER_HIDE_NEVER)
1655
CheckWindowOverLauncher();
1659
Launcher::OnWindowMaybeIntellihideDelayed(guint32 xid)
1662
* Delay to let the other window taking the focus first (otherwise focuschanged
1663
* is emmited with the root window focus
1665
if (_hidemode != LAUNCHER_HIDE_NEVER)
1666
g_idle_add((GSourceFunc)CheckWindowOverLauncherSync, this);
1670
Launcher::CheckWindowOverLauncherSync(Launcher* self)
1672
self->CheckWindowOverLauncher();
1677
Launcher::OnPluginStateChanged()
1679
_hide_machine->SetQuirk (LauncherHideMachine::EXPO_ACTIVE, PluginAdapter::Default ()->IsExpoActive ());
1680
_hide_machine->SetQuirk (LauncherHideMachine::SCALE_ACTIVE, PluginAdapter::Default ()->IsScaleActive ());
1682
if (_hidemode == LAUNCHER_HIDE_NEVER)
1685
if (PluginAdapter::Default ()->IsScaleActive ())
1686
_parent->InputWindowEnableStruts (true);
1688
_parent->InputWindowEnableStruts (false);
1691
Launcher::LauncherHideMode Launcher::GetHideMode()
1696
/* End Launcher Show/Hide logic */
1698
// Hacks around compiz failing to see the struts because the window was just mapped.
1699
gboolean Launcher::StrutHack(gpointer data)
1701
Launcher* self = (Launcher*) data;
1702
self->_parent->InputWindowEnableStruts(false);
1704
if (self->_hidemode == LAUNCHER_HIDE_NEVER)
1705
self->_parent->InputWindowEnableStruts(true);
1710
void Launcher::SetHideMode(LauncherHideMode hidemode)
1712
if (_hidemode == hidemode)
1715
if (hidemode != LAUNCHER_HIDE_NEVER)
1717
_parent->InputWindowEnableStruts(false);
1721
_parent->EnableInputWindow(true, "launcher", false, false);
1722
g_timeout_add(1000, &Launcher::StrutHack, this);
1723
_parent->InputWindowEnableStruts(true);
1726
_hidemode = hidemode;
1727
_hide_machine->SetMode((LauncherHideMachine::HideMode) hidemode);
1731
Launcher::AutoHideAnimation Launcher::GetAutoHideAnimation()
1733
return _autohide_animation;
1736
void Launcher::SetAutoHideAnimation(AutoHideAnimation animation)
1738
if (_autohide_animation == animation)
1741
_autohide_animation = animation;
1744
void Launcher::SetFloating(bool floating)
1746
if (_floating == floating)
1749
_floating = floating;
1753
void Launcher::SetBacklightMode(BacklightMode mode)
1755
if (_backlight_mode == mode)
1758
_backlight_mode = mode;
1762
Launcher::BacklightMode Launcher::GetBacklightMode()
1764
return _backlight_mode;
1768
Launcher::SetLaunchAnimation(LaunchAnimation animation)
1770
if (_launch_animation == animation)
1773
_launch_animation = animation;
1776
Launcher::LaunchAnimation
1777
Launcher::GetLaunchAnimation()
1779
return _launch_animation;
1783
Launcher::SetUrgentAnimation(UrgentAnimation animation)
1785
if (_urgent_animation == animation)
1788
_urgent_animation = animation;
1791
Launcher::UrgentAnimation
1792
Launcher::GetUrgentAnimation()
1794
return _urgent_animation;
1798
Launcher::SetActionState(LauncherActionState actionstate)
1800
if (_launcher_action_state == actionstate)
1803
_launcher_action_state = actionstate;
1805
_hover_machine->SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE));
1807
if (_keynav_activated)
1811
Launcher::LauncherActionState
1812
Launcher::GetActionState()
1814
return _launcher_action_state;
1817
void Launcher::SetHover(bool hovered)
1820
if (hovered == _hovered)
1827
_enter_y = (int) _mouse_position.y;
1828
SetTimeStruct(&_times[TIME_ENTER], &_times[TIME_LEAVE], ANIM_DURATION);
1832
SetTimeStruct(&_times[TIME_LEAVE], &_times[TIME_ENTER], ANIM_DURATION);
1838
bool Launcher::MouseOverTopScrollArea()
1840
return _mouse_position.y < 0;
1843
bool Launcher::MouseOverTopScrollExtrema()
1845
// since we are not dragging the bfb will pick up events
1846
if (GetActionState() == ACTION_NONE)
1847
return _bfb_mouse_position.y == 0;
1849
return _mouse_position.y == 0 - _parent->GetGeometry().y;
1852
bool Launcher::MouseOverBottomScrollArea()
1854
return _mouse_position.y > GetGeometry().height - 24;
1857
bool Launcher::MouseOverBottomScrollExtrema()
1859
return _mouse_position.y == GetGeometry().height - 1;
1862
gboolean Launcher::OnScrollTimeout(gpointer data)
1864
Launcher* self = (Launcher*) data;
1865
nux::Geometry geo = self->GetGeometry();
1867
if (!self->_hovered || self->GetActionState() == ACTION_DRAG_LAUNCHER)
1870
if (self->MouseOverTopScrollArea())
1872
if (self->MouseOverTopScrollExtrema())
1873
self->_launcher_drag_delta += 6;
1875
self->_launcher_drag_delta += 3;
1877
else if (self->MouseOverBottomScrollArea())
1879
if (self->MouseOverBottomScrollExtrema())
1880
self->_launcher_drag_delta -= 6;
1882
self->_launcher_drag_delta -= 3;
1885
self->EnsureAnimation();
1889
void Launcher::EnsureScrollTimer()
1891
bool needed = MouseOverTopScrollArea() || MouseOverBottomScrollArea();
1893
if (needed && !_autoscroll_handle)
1895
_autoscroll_handle = g_timeout_add(20, &Launcher::OnScrollTimeout, this);
1897
else if (!needed && _autoscroll_handle)
1899
g_source_remove(_autoscroll_handle);
1900
_autoscroll_handle = 0;
1904
void Launcher::SetIconSize(int tile_size, int icon_size)
1906
nux::Geometry geo = _parent->GetGeometry();
1908
_icon_size = tile_size;
1909
_icon_image_size = icon_size;
1910
_icon_image_size_delta = tile_size - icon_size;
1911
_icon_glow_size = icon_size + 14;
1913
_parent->SetGeometry(nux::Geometry(geo.x, geo.y, tile_size + 12, geo.height));
1915
icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons);
1918
void Launcher::SetBackgroundAlpha(float background_alpha)
1920
if (_background_alpha == background_alpha)
1923
_background_alpha = background_alpha;
1927
void Launcher::OnIconAdded(LauncherIcon* icon)
1931
// needs to be disconnected
1932
icon->needs_redraw_connection = icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
1937
void Launcher::OnIconRemoved(LauncherIcon* icon)
1939
if (icon->needs_redraw_connection.connected())
1940
icon->needs_redraw_connection.disconnect();
1942
if (icon == _current_icon)
1944
if (icon == _icon_under_mouse)
1945
_icon_under_mouse = 0;
1946
if (icon == _icon_mouse_down)
1947
_icon_mouse_down = 0;
1948
if (icon == _drag_icon)
1955
void Launcher::OnOrderChanged()
1960
void Launcher::SetModel(LauncherModel* model)
1964
if (_model->on_icon_added_connection.connected())
1965
_model->on_icon_added_connection.disconnect();
1966
_model->on_icon_added_connection = _model->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded));
1968
if (_model->on_icon_removed_connection.connected())
1969
_model->on_icon_removed_connection.disconnect();
1970
_model->on_icon_removed_connection = _model->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved));
1972
if (_model->on_order_changed_connection.connected())
1973
_model->on_order_changed_connection.disconnect();
1974
_model->on_order_changed_connection = _model->order_changed.connect(sigc::mem_fun(this, &Launcher::OnOrderChanged));
1977
LauncherModel* Launcher::GetModel()
1982
void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon* icon)
1987
long Launcher::ProcessEvent(nux::IEvent& ievent, long TraverseInfo, long ProcessEventInfo)
1989
long ret = TraverseInfo;
1990
ret = PostProcessEvent2(ievent, ret, ProcessEventInfo);
1994
void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
2002
void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
2004
nux::Geometry base = GetGeometry();
2005
nux::Geometry bkg_box;
2006
std::list<RenderArg> args;
2007
std::list<RenderArg>::reverse_iterator rev_it;
2008
float launcher_alpha = 1.0f;
2010
// rely on the compiz event loop to come back to us in a nice throttling
2011
if (AnimationInProgress())
2012
_launcher_animation_timeout = g_timeout_add(0, &Launcher::AnimationTimeout, this);
2016
ROP.SrcBlend = GL_ONE;
2017
ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
2019
RenderArgs(args, bkg_box, &launcher_alpha);
2021
if (_drag_icon && _render_drag_window)
2023
RenderIconToTexture(GfxContext, _drag_icon, _offscreen_drag_texture);
2024
_drag_window->ShowWindow(true);
2026
_render_drag_window = false;
2030
GfxContext.PushClippingRectangle(base);
2031
gPainter.PushDrawColorLayer(GfxContext, base, nux::Color(0x00000000), true, ROP);
2033
// clip vertically but not horizontally
2034
GfxContext.PushClippingRectangle(nux::Geometry(base.x, bkg_box.y, base.width, bkg_box.height));
2038
gPainter.Paint2DQuadColor(GfxContext, bkg_box, _background_color);
2042
gPainter.Paint2DQuadColor(GfxContext, bkg_box, nux::Color(0.0, 0.0, 0.0, _background_alpha));
2045
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
2047
icon_renderer->PreprocessIcons(args, base);
2051
for (rev_it = args.rbegin(); rev_it != args.rend(); rev_it++)
2053
if ((*rev_it).stick_thingy)
2054
gPainter.Paint2DQuadColor(GfxContext,
2055
nux::Geometry(bkg_box.x, (*rev_it).render_center.y - 3, bkg_box.width, 2),
2056
nux::Color(0xAAAAAAAA));
2061
icon_renderer->RenderIcon(GfxContext, *rev_it, bkg_box, base);
2064
gPainter.Paint2DQuadColor(GfxContext,
2065
nux::Geometry(bkg_box.x + bkg_box.width - 1,
2069
nux::Color(0x60606060));
2070
gPainter.Paint2DQuadColor(GfxContext,
2071
nux::Geometry(bkg_box.x,
2075
nux::Color(0x60000000),
2076
nux::Color(0x00000000),
2077
nux::Color(0x00000000),
2078
nux::Color(0x60000000));
2080
// FIXME: can be removed for a bgk_box->SetAlpha once implemented
2081
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::DST_IN);
2082
nux::Color alpha_mask = nux::Color(0xFFAAAAAA) * launcher_alpha;
2083
gPainter.Paint2DQuadColor(GfxContext, bkg_box, alpha_mask);
2085
GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
2086
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
2088
gPainter.PopBackground();
2089
GfxContext.PopClippingRectangle();
2092
void Launcher::PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw)
2096
void Launcher::PreLayoutManagement()
2098
View::PreLayoutManagement();
2099
if (m_CompositionLayout)
2101
m_CompositionLayout->SetGeometry(GetGeometry());
2105
long Launcher::PostLayoutManagement(long LayoutResult)
2107
View::PostLayoutManagement(LayoutResult);
2109
SetMousePosition(0, 0);
2111
return nux::eCompliantHeight | nux::eCompliantWidth;
2114
void Launcher::PositionChildLayout(float offsetX, float offsetY)
2118
void Launcher::OnDragWindowAnimCompleted()
2121
_drag_window->ShowWindow(false);
2127
gboolean Launcher::StartIconDragTimeout(gpointer data)
2129
Launcher* self = (Launcher*) data;
2131
// if we are still waiting…
2132
if (self->GetActionState() == ACTION_NONE)
2134
if (self->_icon_under_mouse)
2136
self->_icon_under_mouse->mouse_leave.emit();
2137
self->_icon_under_mouse = 0;
2139
self->_initial_drag_animation = true;
2140
self->StartIconDragRequest(self->GetMouseX(), self->GetMouseY());
2142
self->_start_dragicon_handle = 0;
2146
void Launcher::StartIconDragRequest(int x, int y)
2148
LauncherIcon* drag_icon = MouseIconIntersection((int)(GetGeometry().x / 2.0f), y);
2149
SetActionState(ACTION_DRAG_ICON);
2151
// FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
2152
// on an internal Launcher property then
2153
if (drag_icon && (_last_button_press == 1) && _model->IconHasSister(drag_icon))
2155
StartIconDrag(drag_icon);
2156
UpdateDragWindowPosition(drag_icon->GetCenter().x, drag_icon->GetCenter().y);
2157
if (_initial_drag_animation)
2159
_drag_window->SetAnimationTarget(x, y + _drag_window->GetGeometry().height / 2);
2160
_drag_window->StartAnimation();
2169
_drag_window->ShowWindow(false);
2170
_drag_window->UnReference();
2171
_drag_window = NULL;
2177
void Launcher::StartIconDrag(LauncherIcon* icon)
2182
_hide_machine->SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
2187
_drag_window->ShowWindow(false);
2188
_drag_window->UnReference();
2189
_drag_window = NULL;
2192
_offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(_icon_size, _icon_size, 1, nux::BITFMT_R8G8B8A8);
2193
_drag_window = new LauncherDragWindow(_offscreen_drag_texture);
2194
_drag_window->SinkReference();
2196
_render_drag_window = true;
2198
UBusServer* ubus = ubus_server_get_default();
2199
ubus_server_send_message(ubus, UBUS_LAUNCHER_ICON_START_DND, NULL);
2202
void Launcher::EndIconDrag()
2206
LauncherIcon* hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2208
if (hovered_icon && hovered_icon->Type() == LauncherIcon::TYPE_TRASH)
2210
hovered_icon->SetQuirk(LauncherIcon::QUIRK_PULSE_ONCE, true);
2212
launcher_removerequest.emit(_drag_icon);
2213
_drag_window->ShowWindow(false);
2219
std::list<BamfLauncherIcon*> launchers;
2220
std::list<BamfLauncherIcon*>::iterator it;
2221
unity::FavoriteList desktop_paths;
2223
// Updates gsettings favorites.
2224
launchers = _model->GetSublist<BamfLauncherIcon> ();
2225
for (it = launchers.begin(); it != launchers.end(); it++)
2227
BamfLauncherIcon* icon = *it;
2229
if (!icon->IsSticky())
2232
const char* desktop_file = icon->DesktopFile();
2234
if (desktop_file && strlen(desktop_file) > 0)
2235
desktop_paths.push_back(desktop_file);
2238
unity::FavoriteStore::GetDefault().SetFavorites(desktop_paths);
2240
_drag_window->SetAnimationTarget((int)(_drag_icon->GetCenter().x), (int)(_drag_icon->GetCenter().y));
2241
_drag_window->StartAnimation();
2243
if (_drag_window->on_anim_completed.connected())
2244
_drag_window->on_anim_completed.disconnect();
2245
_drag_window->on_anim_completed = _drag_window->anim_completed.connect(sigc::mem_fun(this, &Launcher::OnDragWindowAnimCompleted));
2249
if (MouseBeyondDragThreshold())
2250
SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT);
2252
_render_drag_window = false;
2254
_hide_machine->SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, false);
2255
UBusServer* ubus = ubus_server_get_default();
2256
ubus_server_send_message(ubus, UBUS_LAUNCHER_ICON_END_DND, NULL);
2259
void Launcher::UpdateDragWindowPosition(int x, int y)
2263
nux::Geometry geo = _drag_window->GetGeometry();
2264
_drag_window->SetBaseXY(x - geo.width / 2 + _parent->GetGeometry().x, y - geo.height / 2 + _parent->GetGeometry().y);
2266
LauncherIcon* hovered_icon = MouseIconIntersection((int)(GetGeometry().x / 2.0f), y);
2268
struct timespec current;
2269
clock_gettime(CLOCK_MONOTONIC, ¤t);
2270
if (_drag_icon && hovered_icon && _drag_icon != hovered_icon)
2272
float progress = DragThresholdProgress(current);
2274
if (progress >= 1.0f)
2275
_model->ReorderSmart(_drag_icon, hovered_icon, true);
2276
else if (progress == 0.0f)
2277
_model->ReorderBefore(_drag_icon, hovered_icon, false);
2282
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
2284
_last_button_press = nux::GetEventButton(button_flags);
2285
SetMousePosition(x, y);
2287
MouseDownLogic(x, y, button_flags, key_flags);
2291
void Launcher::RecvMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags)
2293
if (_keynav_activated)
2297
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
2299
SetMousePosition(x, y);
2300
nux::Geometry geo = GetGeometry();
2302
MouseUpLogic(x, y, button_flags, key_flags);
2304
if (GetActionState() == ACTION_DRAG_ICON)
2307
if (GetActionState() == ACTION_DRAG_LAUNCHER)
2308
_hide_machine->SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, false);
2309
SetActionState(ACTION_NONE);
2312
_last_button_press = 0;
2316
void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
2318
/* FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
2319
* on an internal Launcher property then
2322
if (_last_button_press != 1)
2325
SetMousePosition(x, y);
2327
// FIXME: hack (see SetupRenderArg)
2328
_initial_drag_animation = false;
2333
if (nux::Abs(_dnd_delta_y) < MOUSE_DEADZONE &&
2334
nux::Abs(_dnd_delta_x) < MOUSE_DEADZONE &&
2335
GetActionState() == ACTION_NONE)
2338
if (_icon_under_mouse)
2340
_icon_under_mouse->mouse_leave.emit();
2341
_icon_under_mouse = 0;
2344
if (GetActionState() == ACTION_NONE)
2346
if (nux::Abs(_dnd_delta_y) >= nux::Abs(_dnd_delta_x))
2348
_launcher_drag_delta += _dnd_delta_y;
2349
SetActionState(ACTION_DRAG_LAUNCHER);
2350
_hide_machine->SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true);
2354
StartIconDragRequest(x, y);
2357
else if (GetActionState() == ACTION_DRAG_LAUNCHER)
2359
_launcher_drag_delta += dy;
2360
ubus_server_send_message(ubus_server_get_default(),
2361
UBUS_LAUNCHER_END_DND,
2364
else if (GetActionState() == ACTION_DRAG_ICON)
2366
UpdateDragWindowPosition(x, y);
2372
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
2374
SetMousePosition(x, y);
2375
SetStateMouseOverLauncher(true);
2377
// make sure we actually get a chance to get events before turning this off
2379
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, false);
2385
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
2387
SetMousePosition(x, y);
2388
SetStateMouseOverLauncher(false);
2389
LauncherIcon::SetSkipTooltipDelay(false);
2395
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
2397
SetMousePosition(x, y);
2399
// make sure we actually get a chance to get events before turning this off
2401
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, false);
2403
_postreveal_mousemove_delta_x += dx;
2404
_postreveal_mousemove_delta_y += dy;
2406
// check the state before changing it to avoid uneeded hide calls
2407
if (!_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) &&
2408
(nux::Abs(_postreveal_mousemove_delta_x) > MOUSE_DEADZONE ||
2409
nux::Abs(_postreveal_mousemove_delta_y) > MOUSE_DEADZONE))
2410
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
2413
// Every time the mouse moves, we check if it is inside an icon...
2417
void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags)
2422
if (wheel_delta < 0)
2425
_launcher_drag_delta += 10;
2430
_launcher_drag_delta -= 10;
2438
Launcher::ResetRepeatShorcutTimeout(gpointer data)
2440
Launcher* self = (Launcher*) data;
2442
self->_latest_shortcut = 0;
2444
self->_ignore_repeat_shortcut_handle = 0;
2449
Launcher::CheckSuperShortcutPressed(unsigned int key_sym,
2450
unsigned long key_code,
2451
unsigned long key_state,
2454
if (!_super_pressed)
2457
LauncherModel::iterator it;
2459
// Shortcut to start launcher icons. Only relies on Keycode, ignore modifier
2460
for (it = _model->begin(); it != _model->end(); it++)
2462
if ((XKeysymToKeycode(screen->dpy(), (*it)->GetShortcut()) == key_code) ||
2463
((gchar)((*it)->GetShortcut()) == key_string[0]))
2466
* start a timeout while repressing the same shortcut will be ignored.
2467
* This is because the keypress repeat is handled by Xorg and we have no
2468
* way to know if a press is an actual press or just an automated repetition
2469
* because the button is hold down. (key release events are sent in both cases)
2471
if (_ignore_repeat_shortcut_handle > 0)
2472
g_source_remove(_ignore_repeat_shortcut_handle);
2473
_ignore_repeat_shortcut_handle = g_timeout_add(IGNORE_REPEAT_SHORTCUT_DURATION, &Launcher::ResetRepeatShorcutTimeout, this);
2475
if (_latest_shortcut == (*it)->GetShortcut())
2478
if (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask))
2479
(*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0));
2481
(*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0));
2483
_latest_shortcut = (*it)->GetShortcut();
2485
// disable the "tap on super" check
2486
_times[TIME_TAP_SUPER].tv_sec = 0;
2487
_times[TIME_TAP_SUPER].tv_nsec = 0;
2496
Launcher::EdgeRevealTriggered()
2498
SetMousePosition(pointerX, pointerY - GetAbsoluteGeometry().y);
2500
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, true);
2501
_hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
2505
Launcher::RecvKeyPressed(unsigned long eventType,
2506
unsigned long key_sym,
2507
unsigned long key_state,
2508
const char* character,
2509
unsigned short keyCount)
2512
LauncherModel::iterator it;
2515
* all key events below are related to keynavigation. Make an additional
2516
* check that we are in a keynav mode when we inadvertadly receive the focus
2518
if (!_keynav_activated)
2523
// up (move selection up or go to global-menu if at top-most icon)
2526
if (_current_icon_index > 0)
2528
int temp_current_icon_index = _current_icon_index;
2531
temp_current_icon_index --;
2532
it = _model->at(temp_current_icon_index);
2534
while (it != (LauncherModel::iterator)NULL && !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE));
2536
if (it != (LauncherModel::iterator)NULL)
2538
_current_icon_index = temp_current_icon_index;
2539
_launcher_drag_delta += (_icon_size + _space_between_icons);
2542
selection_change.emit();
2546
// down (move selection down and unfold launcher if needed)
2549
if (_current_icon_index < _model->Size() - 1)
2551
int temp_current_icon_index = _current_icon_index;
2555
temp_current_icon_index ++;
2556
it = _model->at(temp_current_icon_index);
2558
while (it != (LauncherModel::iterator)NULL && !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE));
2560
if (it != (LauncherModel::iterator)NULL)
2562
_current_icon_index = temp_current_icon_index;
2563
_launcher_drag_delta -= (_icon_size + _space_between_icons);
2567
selection_change.emit();
2571
// esc/left (close quicklist or exit laucher key-focus)
2579
// right/shift-f10 (open quicklist of currently selected icon)
2581
if (!(key_state & NUX_STATE_SHIFT))
2586
// open quicklist of currently selected icon
2587
it = _model->at(_current_icon_index);
2588
if (it != (LauncherModel::iterator)NULL)
2590
if ((*it)->OpenQuicklist(true))
2591
leaveKeyNavMode(false);
2595
// <SPACE> (open a new instance)
2597
// start currently selected icon
2598
it = _model->at(_current_icon_index);
2599
if (it != (LauncherModel::iterator)NULL)
2601
(*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0));
2606
// <RETURN> (start/activate currently selected icon)
2610
// start currently selected icon
2611
it = _model->at(_current_icon_index);
2612
if (it != (LauncherModel::iterator)NULL)
2613
(*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0));
2623
void Launcher::RecvQuicklistOpened(QuicklistView* quicklist)
2625
_hide_machine->SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true);
2626
_hover_machine->SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true);
2631
void Launcher::RecvQuicklistClosed(QuicklistView* quicklist)
2633
nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
2634
if (!GetAbsoluteGeometry().IsInside(pt))
2636
// The Quicklist just closed and the mouse is outside the launcher.
2638
SetStateMouseOverLauncher(false);
2640
// Cancel any prior state that was set before the Quicklist appeared.
2641
SetActionState(ACTION_NONE);
2643
_hide_machine->SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, false);
2644
_hover_machine->SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, false);
2650
void Launcher::EventLogic()
2652
if (GetActionState() == ACTION_DRAG_ICON ||
2653
GetActionState() == ACTION_DRAG_LAUNCHER)
2656
LauncherIcon* launcher_icon = 0;
2658
if (_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER)
2659
&& _hide_machine->GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL))
2661
launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2665
if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
2667
_icon_under_mouse->mouse_leave.emit();
2668
_icon_under_mouse = 0;
2671
if (launcher_icon && (_icon_under_mouse != launcher_icon))
2673
launcher_icon->mouse_enter.emit();
2674
_icon_under_mouse = launcher_icon;
2676
_hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false);
2680
void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
2682
LauncherIcon* launcher_icon = 0;
2683
launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2685
_hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false);
2689
_icon_mouse_down = launcher_icon;
2690
// if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app
2691
if (_start_dragicon_handle > 0)
2692
g_source_remove(_start_dragicon_handle);
2693
_start_dragicon_handle = g_timeout_add(START_DRAGICON_DURATION, &Launcher::StartIconDragTimeout, this);
2695
launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags));
2699
void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
2701
LauncherIcon* launcher_icon = 0;
2703
launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2705
if (_start_dragicon_handle > 0)
2706
g_source_remove(_start_dragicon_handle);
2707
_start_dragicon_handle = 0;
2709
if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
2711
_icon_mouse_down->mouse_up.emit(nux::GetEventButton(button_flags));
2713
if (GetActionState() == ACTION_NONE)
2715
_icon_mouse_down->mouse_click.emit(nux::GetEventButton(button_flags));
2719
if (launcher_icon && (_icon_mouse_down != launcher_icon))
2721
launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags));
2724
if (GetActionState() == ACTION_DRAG_LAUNCHER)
2726
SetTimeStruct(&_times[TIME_DRAG_END]);
2729
_icon_mouse_down = 0;
2732
LauncherIcon* Launcher::MouseIconIntersection(int x, int y)
2734
LauncherModel::iterator it;
2735
// We are looking for the icon at screen coordinates x, y;
2736
nux::Point2 mouse_position(x, y);
2739
for (it = _model->begin(); it != _model->end(); it++)
2741
if (!(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE))
2744
nux::Point2 screen_coord [4];
2745
for (int i = 0; i < 4; ++i)
2747
screen_coord [i].x = (*it)->GetTransform("HitArea") [i].x;
2748
screen_coord [i].y = (*it)->GetTransform("HitArea") [i].y;
2750
inside = PointInside2DPolygon(screen_coord, 4, mouse_position, 1);
2759
Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, LauncherIcon* icon, nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture)
2762
struct timespec current;
2763
clock_gettime(CLOCK_MONOTONIC, ¤t);
2765
SetupRenderArg(icon, current, arg);
2766
arg.render_center = nux::Point3(_icon_size / 2.0f, _icon_size / 2.0f, 0.0f);
2767
arg.logical_center = arg.render_center;
2768
arg.x_rotation = 0.0f;
2769
arg.running_arrow = false;
2770
arg.active_arrow = false;
2772
arg.window_indicators = 0;
2775
std::list<RenderArg> drag_args;
2776
drag_args.push_front(arg);
2777
icon_renderer->PreprocessIcons(drag_args, nux::Geometry(0, 0, _icon_size, _icon_size));
2779
SetOffscreenRenderTarget(texture);
2780
icon_renderer->RenderIcon(nux::GetGraphicsEngine(), arg, nux::Geometry(0, 0, _icon_size, _icon_size), nux::Geometry(0, 0, _icon_size, _icon_size));
2781
RestoreSystemRenderTarget();
2785
Launcher::SetOffscreenRenderTarget(nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture)
2787
int width = texture->GetWidth();
2788
int height = texture->GetHeight();
2790
nux::GetGraphicsDisplay()->GetGpuDevice()->FormatFrameBufferObject(width, height, nux::BITFMT_R8G8B8A8);
2791
nux::GetGraphicsDisplay()->GetGpuDevice()->SetColorRenderTargetSurface(0, texture->GetSurfaceLevel(0));
2792
nux::GetGraphicsDisplay()->GetGpuDevice()->ActivateFrameBuffer();
2794
nux::GetGraphicsDisplay()->GetGraphicsEngine()->SetContext(0, 0, width, height);
2795
nux::GetGraphicsDisplay()->GetGraphicsEngine()->SetViewport(0, 0, width, height);
2796
nux::GetGraphicsDisplay()->GetGraphicsEngine()->Push2DWindow(width, height);
2797
nux::GetGraphicsDisplay()->GetGraphicsEngine()->EmptyClippingRegion();
2801
Launcher::RestoreSystemRenderTarget()
2803
nux::GetWindowCompositor().RestoreRenderingSurface();
2807
Launcher::ProcessDndEnter()
2810
_drag_action = nux::DNDACTION_NONE;
2811
_steal_drag = false;
2812
_data_checked = false;
2813
_drag_edge_touching = false;
2814
_dnd_hovered_icon = 0;
2818
Launcher::ProcessDndLeave()
2820
SetStateMouseOverLauncher(false);
2821
_drag_edge_touching = false;
2823
SetActionState(ACTION_NONE);
2825
if (!_drag_data.empty())
2827
std::list<char*>::iterator it;
2828
for (it = _drag_data.begin(); it != _drag_data.end(); it++)
2835
LauncherModel::iterator it;
2836
for (it = _model->begin(); it != _model->end(); it++)
2838
(*it)->SetQuirk(LauncherIcon::QUIRK_DROP_PRELIGHT, false);
2839
(*it)->SetQuirk(LauncherIcon::QUIRK_DROP_DIM, false);
2842
if (_steal_drag && _dnd_hovered_icon)
2844
_dnd_hovered_icon->SetQuirk(LauncherIcon::QUIRK_VISIBLE, false);
2845
_dnd_hovered_icon->remove.emit(_dnd_hovered_icon);
2849
if (!_steal_drag && _dnd_hovered_icon)
2851
_dnd_hovered_icon->SendDndLeave();
2852
_dnd_hovered_icon = 0;
2855
_steal_drag = false;
2856
_dnd_hovered_icon = 0;
2861
Launcher::StringToUriList(char* input)
2863
std::list<char*> result;
2868
char** imtrappedinastringfactory = g_strsplit(input, "\r\n", -1);
2870
while (imtrappedinastringfactory[i]) // get kinda bored
2872
// empty string check
2873
if (imtrappedinastringfactory[i][0])
2874
result.push_back(g_strdup(imtrappedinastringfactory[i]));
2878
g_strfreev(imtrappedinastringfactory);
2884
Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes)
2886
std::list<char*>::iterator it;
2887
nux::Area* parent = GetToplevel();
2888
char* uri_list_const = g_strdup("text/uri-list");
2892
_data_checked = true;
2896
for (it = mimes.begin(); it != mimes.end(); it++)
2898
if (!g_str_equal(*it, uri_list_const))
2901
_drag_data = StringToUriList(nux::GetWindow().GetDndData(uri_list_const));
2905
// see if the launcher wants this one
2906
for (it = _drag_data.begin(); it != _drag_data.end(); it++)
2908
if (g_str_has_suffix(*it, ".desktop"))
2915
// only set hover once we know our first x/y
2916
SetActionState(ACTION_DRAG_EXTERNAL);
2917
SetStateMouseOverLauncher(true);
2919
LauncherModel::iterator it;
2920
for (it = _model->begin(); it != _model->end() && !_steal_drag; it++)
2922
if ((*it)->QueryAcceptDrop(_drag_data) != nux::DNDACTION_NONE && !_steal_drag)
2923
(*it)->SetQuirk(LauncherIcon::QUIRK_DROP_PRELIGHT, true);
2925
(*it)->SetQuirk(LauncherIcon::QUIRK_DROP_DIM, true);
2930
g_free(uri_list_const);
2932
SetMousePosition(x - parent->GetGeometry().x, y - parent->GetGeometry().y);
2934
if (_mouse_position.x == 0 && _mouse_position.y <= (_parent->GetGeometry().height - _icon_size - 2 * _space_between_icons) && !_drag_edge_touching)
2936
_drag_edge_touching = true;
2937
SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3);
2940
else if (_mouse_position.x != 0 && _drag_edge_touching)
2942
_drag_edge_touching = false;
2943
SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3);
2948
LauncherIcon* hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
2950
bool hovered_icon_is_appropriate = false;
2953
if (hovered_icon->Type() == LauncherIcon::TYPE_TRASH)
2954
_steal_drag = false;
2956
if (hovered_icon->Type() == LauncherIcon::TYPE_APPLICATION || hovered_icon->Type() == LauncherIcon::TYPE_EXPO)
2957
hovered_icon_is_appropriate = true;
2962
_drag_action = nux::DNDACTION_COPY;
2963
if (!_dnd_hovered_icon && hovered_icon_is_appropriate)
2965
_dnd_hovered_icon = new SpacerLauncherIcon(this);
2966
_dnd_hovered_icon->SetSortPriority(G_MAXINT);
2967
_model->AddIcon(_dnd_hovered_icon);
2968
_model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true);
2970
else if (_dnd_hovered_icon)
2974
if (hovered_icon_is_appropriate)
2976
_model->ReorderSmart(_dnd_hovered_icon, hovered_icon, true);
2980
_dnd_hovered_icon->SetQuirk(LauncherIcon::QUIRK_VISIBLE, false);
2981
_dnd_hovered_icon->remove.emit(_dnd_hovered_icon);
2982
_dnd_hovered_icon = 0;
2989
if (hovered_icon != _dnd_hovered_icon)
2993
hovered_icon->SendDndEnter();
2994
_drag_action = hovered_icon->QueryAcceptDrop(_drag_data);
2998
_drag_action = nux::DNDACTION_NONE;
3001
if (_dnd_hovered_icon)
3002
_dnd_hovered_icon->SendDndLeave();
3004
_dnd_hovered_icon = hovered_icon;
3009
if (_drag_action != nux::DNDACTION_NONE)
3014
SendDndStatus(accept, _drag_action, nux::Geometry(x, y, 1, 1));
3018
Launcher::ProcessDndDrop(int x, int y)
3023
std::list<char*>::iterator it;
3025
for (it = _drag_data.begin(); it != _drag_data.end(); it++)
3027
if (g_str_has_suffix(*it, ".desktop"))
3029
if (g_str_has_prefix(*it, "application://"))
3031
const char* tmp = *it + strlen("application://");
3032
char* tmp2 = g_strdup_printf("file:///usr/share/applications/%s", tmp);
3033
path = g_filename_from_uri(tmp2, NULL, NULL);
3037
else if (g_str_has_prefix(*it, "file://"))
3039
path = g_filename_from_uri(*it, NULL, NULL);
3047
launcher_addrequest.emit(path, _dnd_hovered_icon);
3051
else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
3053
_dnd_hovered_icon->AcceptDrop(_drag_data);
3056
if (_drag_action != nux::DNDACTION_NONE)
3057
SendDndFinished(true, _drag_action);
3059
SendDndFinished(false, _drag_action);
3067
* Returns the current selected icon if it is in keynavmode
3068
* It will return NULL if it is not on keynavmode
3071
Launcher::GetSelectedMenuIcon()
3073
LauncherModel::iterator it;
3075
if (_current_icon_index == -1)
3078
it = _model->at(_current_icon_index);
3080
if (it != (LauncherModel::iterator)NULL)
3089
Launcher::handle_dbus_method_call(GDBusConnection* connection,
3090
const gchar* sender,
3091
const gchar* object_path,
3092
const gchar* interface_name,
3093
const gchar* method_name,
3094
GVariant* parameters,
3095
GDBusMethodInvocation* invocation,
3099
if (g_strcmp0(method_name, "AddLauncherItemFromPosition") == 0)
3106
gchar* desktop_file;
3107
gchar* aptdaemon_task;
3109
g_variant_get(parameters, "(ssiiiss)", &icon, &title, &icon_x, &icon_y, &icon_size, &desktop_file, &aptdaemon_task, NULL);
3111
Launcher* self = (Launcher*)user_data;
3112
self->launcher_addrequest.emit(desktop_file, NULL);
3114
g_dbus_method_invocation_return_value(invocation, NULL);
3117
g_free(desktop_file);
3118
g_free(aptdaemon_task);
3124
Launcher::OnBusAcquired(GDBusConnection* connection,
3128
GDBusNodeInfo* introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
3129
guint registration_id;
3131
if (!introspection_data)
3133
LOG_WARNING(logger) << "No introspection data loaded. Won't get dynamic launcher addition.";
3139
registration_id = g_dbus_connection_register_object(connection,
3141
introspection_data->interfaces[0],
3146
if (!registration_id)
3148
LOG_WARNING(logger) << "Object registration failed. Won't get dynamic launcher addition.";
3153
Launcher::OnNameAcquired(GDBusConnection* connection,
3157
LOG_DEBUG(logger) << "Acquired the name " << name << " on the session bus";
3161
Launcher::OnNameLost(GDBusConnection* connection,
3165
LOG_DEBUG(logger) << "Lost the name " << name << " on the session bus";
3172
Launcher::InspectKeyEvent(unsigned int eventType,
3173
unsigned int keysym,
3174
const char* character)
3176
// The Launcher accepts all key inputs.