./ 0000755 0000156 0000165 00000000000 12704076362 011104 5 ustar jenkins jenkins ./launcher/ 0000755 0000156 0000165 00000000000 12704076362 012705 5 ustar jenkins jenkins ./launcher/VolumeMonitorWrapper.cpp 0000644 0000156 0000165 00000004034 12704076362 017572 0 ustar jenkins jenkins /*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#include "VolumeMonitorWrapper.h"
namespace unity
{
namespace launcher
{
VolumeMonitorWrapper::VolumeMonitorWrapper()
: monitor_(g_volume_monitor_get())
{
typedef glib::Signal VolumeSignal;
sig_manager_.Add(new VolumeSignal(monitor_, "volume-added", sigc::mem_fun(this, &VolumeMonitorWrapper::OnVolumeAdded)));
sig_manager_.Add(new VolumeSignal(monitor_, "volume-removed", sigc::mem_fun(this, &VolumeMonitorWrapper::OnVolumeRemoved)));
}
VolumeMonitorWrapper::VolumeList VolumeMonitorWrapper::GetVolumes()
{
VolumeList ret;
auto volumes = std::shared_ptr(g_volume_monitor_get_volumes(monitor_), g_list_free);
for (GList* v = volumes.get(); v; v = v->next)
{
if (!G_IS_VOLUME(v->data))
continue;
// This will unref the volume, since the list entries needs that.
// We'll keep a reference in the list.
glib::Object volume(G_VOLUME(v->data));
ret.push_back(volume);
}
return ret;
}
void VolumeMonitorWrapper::OnVolumeAdded(GVolumeMonitor* monitor, GVolume* volume)
{
glib::Object gvolume(volume, glib::AddRef());
volume_added.emit(gvolume);
}
void VolumeMonitorWrapper::OnVolumeRemoved(GVolumeMonitor* monitor, GVolume* volume)
{
glib::Object gvolume(volume, glib::AddRef());
volume_removed.emit(gvolume);
}
} // namespace launcher
} // namespace unity
./launcher/XdndStartStopNotifier.cpp 0000644 0000156 0000165 00000001515 12704076362 017674 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#include "XdndStartStopNotifier.h"
namespace unity {
XdndStartStopNotifier::~XdndStartStopNotifier()
{}
} ./launcher/TrashLauncherIcon.h 0000644 0000156 0000165 00000003416 12704076362 016436 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
*/
#ifndef TRASHLAUNCHERICON_H
#define TRASHLAUNCHERICON_H
#include
#include
#include
#include
#include "DndData.h"
#include "StorageLauncherIcon.h"
#include "unity-shared/FileManager.h"
namespace unity
{
namespace launcher
{
class TrashLauncherIcon : public StorageLauncherIcon
{
public:
TrashLauncherIcon(FileManager::Ptr const& = nullptr);
protected:
void UpdateTrashIcon();
nux::DndAction OnQueryAcceptDrop(DndData const& dnd_data);
bool OnShouldHighlightOnDrag(DndData const& dnd_data);
void OnAcceptDrop(DndData const& dnd_data);
WindowList GetStorageWindows() const override;
std::string GetName() const;
private:
void OpenInstanceLauncherIcon(Time timestamp) override;
MenuItemsVector GetMenus();
static void UpdateTrashIconCb(GObject* source, GAsyncResult* res, gpointer data);
bool empty_;
glib::Cancellable cancellable_;
glib::Object trash_monitor_;
};
}
} // namespace unity
#endif // TRASHLAUNCHERICON_H
./launcher/CairoBaseWindow.cpp 0000644 0000156 0000165 00000014630 12704076362 016435 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Marco Trevisan <3v1n0@ubuntu.com>
*/
#include
#include
#include "unity-shared/AnimationUtils.h"
#include "unity-shared/CairoTexture.h"
#include "unity-shared/UnitySettings.h"
#include "CairoBaseWindow.h"
namespace unity
{
namespace
{
const int ANCHOR_WIDTH = 14;
const int ANCHOR_HEIGHT = 18;
const int CORNER_RADIUS = 4;
const int PADDING = 15;
const int TEXT_PADDING = 8;
const int MINIMUM_TEXT_WIDTH = 100;
const int TOP_SIZE = 0;
const int FADE_DURATION = 80;
}
NUX_IMPLEMENT_OBJECT_TYPE(CairoBaseWindow);
CairoBaseWindow::CairoBaseWindow(int monitor)
: cv_(Settings::Instance().em(monitor))
, use_blurred_background_(!Settings::Instance().GetLowGfxMode())
, compute_blur_bkg_(use_blurred_background_)
, fade_animator_(FADE_DURATION)
{
SetWindowSizeMatchLayout(true);
sigVisible.connect([this] (BaseWindow*) { compute_blur_bkg_ = true; });
fade_animator_.updated.connect(sigc::mem_fun(this, &BaseWindow::SetOpacity));
fade_animator_.finished.connect([this] {
if (animation::GetDirection(fade_animator_) == animation::Direction::BACKWARD)
{
ShowWindow(false);
hidden.emit();
}
});
}
void CairoBaseWindow::Show()
{
animation::StartOrReverse(fade_animator_, animation::Direction::FORWARD);
ShowWindow(true);
PushToFront();
}
void CairoBaseWindow::Hide()
{
animation::StartOrReverse(fade_animator_, animation::Direction::BACKWARD);
}
void CairoBaseWindow::PromptHide()
{
Hide();
fade_animator_.Stop();
}
void CairoBaseWindow::RedrawBlur()
{
compute_blur_bkg_ = true;
QueueDraw();
}
bool CairoBaseWindow::HasBlurredBackground() const
{
return use_blurred_background_;
}
void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw)
{
nux::Geometry base(GetGeometry());
// Get the background and apply some blur
if (use_blurred_background_ && compute_blur_bkg_)
{
auto current_fbo = nux::GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject();
nux::GetWindowCompositor ().RestoreMainFramebuffer();
gfxContext.SetViewport(0, 0, gfxContext.GetWindowWidth(), gfxContext.GetWindowHeight());
gfxContext.SetScissor(0, 0, gfxContext.GetWindowWidth(), gfxContext.GetWindowHeight());
gfxContext.GetRenderStates().EnableScissor(false);
nux::ObjectPtr bkg_texture = gfxContext.CreateTextureFromBackBuffer(base.x, base.y, base.width, base.height);
nux::TexCoordXForm texxform_bkg;
bg_blur_texture_ = gfxContext.QRP_GetBlurTexture(0, 0, base.width, base.height, bkg_texture, texxform_bkg, nux::color::White, 1.0f, 3);
if (current_fbo.IsValid())
{
current_fbo->Activate(true);
gfxContext.Push2DWindow(current_fbo->GetWidth(), current_fbo->GetHeight());
}
else
{
gfxContext.SetViewport(0, 0, gfxContext.GetWindowWidth(), gfxContext.GetWindowHeight());
gfxContext.Push2DWindow(gfxContext.GetWindowWidth(), gfxContext.GetWindowHeight());
gfxContext.ApplyClippingRectangle();
}
compute_blur_bkg_ = false;
}
// the elements position inside the window are referenced to top-left window
// corner. So bring base to (0, 0).
base.SetX(0);
base.SetY(0);
gfxContext.PushClippingRectangle(base);
/*"Clear" out the background. Blending is disabled if blur is disabled. This might need to change, but for the moment both classes
* which are children of CairoBaseWindow don't have any alpha blending when not using the blurred texture.*/
nux::ROPConfig rop;
rop.Blend = use_blurred_background_;
rop.SrcBlend = GL_ONE;
rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
nux::ColorLayer layer(nux::Color(0x00000000), use_blurred_background_, rop);
nux::GetPainter().PushDrawLayer(gfxContext, base, &layer);
nux::TexCoordXForm texxform_bg;
texxform_bg.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP);
texxform_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
nux::TexCoordXForm texxform_mask;
texxform_mask.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP);
texxform_mask.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
nux::GetWindowThread()->GetGraphicsEngine().GetRenderStates().SetBlend(true);
nux::GetWindowThread()->GetGraphicsEngine().GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
if (bg_blur_texture_.IsValid() && texture_mask_.IsValid())
{
nux::TexCoordXForm texxform_blur_bkg;
gfxContext.QRP_2TexMod(
base.x,
base.y,
base.width,
base.height,
bg_blur_texture_,
texxform_blur_bkg,
nux::color::White,
texture_mask_->GetDeviceTexture(),
texxform_mask,
nux::color::White);
}
if (texture_bg_.IsValid() && texture_mask_.IsValid())
{
gfxContext.QRP_2TexMod(base.x,
base.y,
base.width,
base.height,
texture_bg_->GetDeviceTexture(),
texxform_bg,
nux::color::White,
texture_mask_->GetDeviceTexture(),
texxform_mask,
nux::color::White);
}
if (texture_outline_.IsValid())
{
nux::TexCoordXForm texxform;
texxform.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP);
texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
gfxContext.QRP_1Tex(base.x,
base.y,
base.width,
base.height,
texture_outline_->GetDeviceTexture(),
texxform,
nux::color::White);
}
nux::GetWindowThread()->GetGraphicsDisplay().GetGraphicsEngine()->GetRenderStates().SetBlend(false);
nux::GetPainter().PopBackground();
gfxContext.PopClippingRectangle();
}
} // namespace nux
./launcher/LauncherEntryRemote.cpp 0000644 0000156 0000165 00000023040 12704076362 017347 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2011-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Mikkel Kamstrup Erlandsen
* Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
*/
#include "LauncherEntryRemote.h"
#include
#include
namespace unity
{
DECLARE_LOGGER(logger, "unity.launcher.entry.remote");
/**
* Create a new LauncherEntryRemote parsed from the raw DBus wire format
* of the com.canonical.Unity.LauncherEntry.Update signal '(sa{sv})'. The
* dbus_name argument should be the unique bus name of the process owning
* the launcher entry.
*
* You don't normally need to use this constructor yourself. The
* LauncherEntryRemoteModel will do that for you when needed.
*/
LauncherEntryRemote::LauncherEntryRemote(std::string const& dbus_name, GVariant* val)
: _dbus_name(dbus_name)
, _count(0)
, _progress(0.0f)
, _emblem_visible(false)
, _count_visible(false)
, _progress_visible(false)
, _urgent(false)
{
glib::String app_uri;
GVariantIter* prop_iter;
if (!val || dbus_name.empty())
{
LOG_ERROR(logger) << "Invalid launcher entry remote construction";
return;
}
/* This will make sure that the values are properly ref_sink'ed and unreff'ed */
glib::Variant values(val);
g_variant_get(values, "(sa{sv})", &app_uri, &prop_iter);
_app_uri = app_uri.Str();
Update(prop_iter);
g_variant_iter_free(prop_iter);
}
/**
* The appuri property is on the form application://$desktop_file_id and is
* used within the LauncherEntryRemoteModel to uniquely identify the various
* applications.
*
* Note that a desktop file id is defined to be the base name of the desktop
* file including the extension. Eg. gedit.desktop. Thus a full appuri could be
* application://gedit.desktop.
*/
std::string const& LauncherEntryRemote::AppUri() const
{
return _app_uri;
}
/**
* Return the unique DBus name for the remote party owning this launcher entry.
*/
std::string const& LauncherEntryRemote::DBusName() const
{
return _dbus_name;
}
std::string const& LauncherEntryRemote::Emblem() const
{
return _emblem;
}
int32_t LauncherEntryRemote::Count() const
{
return _count;
}
double LauncherEntryRemote::Progress() const
{
return _progress;
}
/**
* Return a pointer to the current quicklist of the launcher entry; NULL if
* it's unset.
*
* The returned object should not be freed.
*/
glib::Object const& LauncherEntryRemote::Quicklist() const
{
return _quicklist;
}
bool LauncherEntryRemote::EmblemVisible() const
{
return _emblem_visible;
}
bool LauncherEntryRemote::CountVisible() const
{
return _count_visible;
}
bool LauncherEntryRemote::ProgressVisible() const
{
return _progress_visible;
}
bool LauncherEntryRemote::Urgent() const
{
return _urgent;
}
/**
* Set the unique DBus name for the process owning the launcher entry.
*
* If the entry has any exported quicklist it will be removed.
*/
void LauncherEntryRemote::SetDBusName(std::string const& dbus_name)
{
if (_dbus_name == dbus_name)
return;
std::string old_name(_dbus_name);
_dbus_name = dbus_name;
/* Remove the quicklist since we can't know if it it'll be valid on the
* new name, and we certainly don't want the quicklist to operate on a
* different name than the rest of the launcher API */
SetQuicklist(nullptr);
dbus_name_changed.emit(this, old_name);
}
void LauncherEntryRemote::SetEmblem(std::string const& emblem)
{
if (_emblem == emblem)
return;
_emblem = emblem;
emblem_changed.emit(this);
}
void LauncherEntryRemote::SetCount(int32_t count)
{
if (_count == count)
return;
_count = count;
count_changed.emit(this);
}
void LauncherEntryRemote::SetProgress(double progress)
{
if (_progress == progress)
return;
_progress = progress;
progress_changed.emit(this);
}
/**
* Set the quicklist of this entry to be the Dbusmenu on the given path.
* If entry already has a quicklist with the same path this call is a no-op.
*
* To unset the quicklist pass in a NULL path or empty string.
*/
void LauncherEntryRemote::SetQuicklistPath(std::string const& dbus_path)
{
/* Check if existing quicklist have exact same path
* and ignore the change in that case */
if (_quicklist)
{
glib::String ql_path;
g_object_get(_quicklist, DBUSMENU_CLIENT_PROP_DBUS_OBJECT, &ql_path, NULL);
if (ql_path.Str() == dbus_path)
{
return;
}
}
else if (!_quicklist && dbus_path.empty())
return;
if (!dbus_path.empty())
_quicklist = dbusmenu_client_new(_dbus_name.c_str(), dbus_path.c_str());
else
_quicklist = nullptr;
quicklist_changed.emit(this);
}
/**
* Set the quicklist of this entry to a given DbusmenuClient.
* If entry already has a quicklist with the same path this call is a no-op.
*
* To unset the quicklist for this entry pass in NULL as the quicklist to set.
*/
void
LauncherEntryRemote::SetQuicklist(DbusmenuClient* quicklist)
{
/* Check if existing quicklist have exact same path as the new one
* and ignore the change in that case. We also assert that the quicklist
* uses the same name as the connection owning this launcher entry */
if (_quicklist)
{
glib::String ql_path, new_ql_path, new_ql_name;
g_object_get(_quicklist, DBUSMENU_CLIENT_PROP_DBUS_OBJECT, &ql_path, NULL);
if (quicklist)
{
g_object_get(quicklist, DBUSMENU_CLIENT_PROP_DBUS_OBJECT, &new_ql_path, NULL);
g_object_get(quicklist, DBUSMENU_CLIENT_PROP_DBUS_NAME, &new_ql_name, NULL);
}
if (quicklist && new_ql_name.Str() != _dbus_name)
{
LOG_ERROR(logger) << "Mismatch between quicklist- and launcher entry owner:"
<< new_ql_name << " and " << _dbus_name << " respectively";
return;
}
if (new_ql_path.Str() == ql_path.Str())
{
return;
}
}
else if (!_quicklist && !quicklist)
return;
if (!quicklist)
_quicklist = nullptr;
else
_quicklist = glib::Object(quicklist, glib::AddRef());
quicklist_changed.emit(this);
}
void LauncherEntryRemote::SetEmblemVisible(bool visible)
{
if (_emblem_visible == visible)
return;
_emblem_visible = visible;
emblem_visible_changed.emit(this);
}
void LauncherEntryRemote::SetCountVisible(bool visible)
{
if (_count_visible == visible)
return;
_count_visible = visible;
count_visible_changed.emit(this);
}
void LauncherEntryRemote::SetProgressVisible(bool visible)
{
if (_progress_visible == visible)
return;
_progress_visible = visible;
progress_visible_changed.emit(this);
}
void LauncherEntryRemote::SetUrgent(bool urgent)
{
if (_urgent == urgent)
return;
_urgent = urgent;
urgent_changed.emit(this);
}
/**
* Set all properties from 'other' on 'this'.
*/
void LauncherEntryRemote::Update(LauncherEntryRemote::Ptr const& other)
{
/* It's important that we update the DBus name first since it might
* unset the quicklist if it changes */
if (!other)
return;
SetDBusName(other->DBusName());
SetEmblem(other->Emblem());
SetCount(other->Count());
SetProgress(other->Progress());
SetQuicklist(other->Quicklist());
SetUrgent(other->Urgent());
SetEmblemVisible(other->EmblemVisible());
SetCountVisible(other->CountVisible());
SetProgressVisible(other->ProgressVisible());
}
/**
* Iterate over a GVariantIter containing elements of type '{sv}' and apply
* any properties to 'this'.
*/
void LauncherEntryRemote::Update(GVariantIter* prop_iter)
{
gchar* prop_key;
GVariant* prop_value;
g_return_if_fail(prop_iter != NULL);
while (g_variant_iter_loop(prop_iter, "{sv}", &prop_key, &prop_value))
{
if (g_str_equal("emblem", prop_key))
SetEmblem(glib::String(g_variant_dup_string(prop_value, 0)).Str());
else if (g_str_equal("count", prop_key))
SetCount(g_variant_get_int64(prop_value));
else if (g_str_equal("progress", prop_key))
SetProgress(g_variant_get_double(prop_value));
else if (g_str_equal("emblem-visible", prop_key))
SetEmblemVisible(g_variant_get_boolean(prop_value));
else if (g_str_equal("count-visible", prop_key))
SetCountVisible(g_variant_get_boolean(prop_value));
else if (g_str_equal("progress-visible", prop_key))
SetProgressVisible(g_variant_get_boolean(prop_value));
else if (g_str_equal("urgent", prop_key))
SetUrgent(g_variant_get_boolean(prop_value));
else if (g_str_equal("quicklist", prop_key))
{
/* The value is the object path of the dbusmenu */
SetQuicklistPath(glib::String(g_variant_dup_string(prop_value, 0)).Str());
}
}
}
std::string LauncherEntryRemote::GetName() const
{
// This seems a more appropriate name than LauncherEntryRemote
return "LauncherEntry";
}
void LauncherEntryRemote::AddProperties(debug::IntrospectionData& introspection)
{
introspection
.add("count", Count())
.add("progress", Progress())
.add("emblem_visible", EmblemVisible())
.add("count_visible", CountVisible())
.add("progress_visible", ProgressVisible())
.add("urgent", Urgent());
}
} // Namespace
./launcher/WindowedLauncherIcon.cpp 0000644 0000156 0000165 00000040403 12704076362 017465 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2015 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Marco Trevisan
*/
#include
#include "WindowedLauncherIcon.h"
#include "MultiMonitor.h"
#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
#include "unity-shared/UScreen.h"
namespace unity
{
namespace launcher
{
namespace
{
const std::string ICON_DND_OVER_TIMEOUT = "windowed-icon-dnd-over";
const int COMPIZ_SCALE_DND_SPREAD = 1 << 7;
const int MAXIMUM_QUICKLIST_WIDTH = 300;
}
NUX_IMPLEMENT_OBJECT_TYPE(WindowedLauncherIcon);
WindowedLauncherIcon::WindowedLauncherIcon(AbstractLauncherIcon::IconType icon_type)
: SimpleLauncherIcon(icon_type)
, last_scroll_timestamp_(0)
, progressive_scroll_(0)
{
WindowManager& wm = WindowManager::Default();
wm.window_minimized.connect(sigc::mem_fun(this, &WindowedLauncherIcon::OnWindowMinimized));
wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &WindowedLauncherIcon::EnsureWindowState));
wm.terminate_expo.connect(sigc::mem_fun(this, &WindowedLauncherIcon::EnsureWindowState));
UScreen::GetDefault()->changed.connect(sigc::hide(sigc::hide(sigc::mem_fun(this, &WindowedLauncherIcon::EnsureWindowsLocation))));
windows_changed.connect([this] (int) {
if (WindowManager::Default().IsScaleActiveForGroup() && IsActive())
Spread(true, 0, false);
});
}
bool WindowedLauncherIcon::IsActive() const
{
return GetQuirk(Quirk::ACTIVE);
}
bool WindowedLauncherIcon::IsStarting() const
{
return GetQuirk(Quirk::STARTING);
}
bool WindowedLauncherIcon::IsRunning() const
{
return GetQuirk(Quirk::RUNNING);
}
bool WindowedLauncherIcon::IsUrgent() const
{
return GetQuirk(Quirk::URGENT);
}
bool WindowedLauncherIcon::IsUserVisible() const
{
return IsRunning();
}
void WindowedLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
SimpleLauncherIcon::ActivateLauncherIcon(arg);
WindowManager& wm = WindowManager::Default();
// This is a little awkward as the target is only set from the switcher.
if (arg.target)
{
// thumper: should we Raise too? should the WM raise?
wm.Activate(arg.target);
return;
}
bool scale_was_active = wm.IsScaleActive();
bool active = IsActive();
bool user_visible = IsRunning();
/* We should check each child to see if there is
* an unmapped (!= minimized) window around and
* if so force "Focus" behaviour */
if (arg.source != ActionArg::Source::SWITCHER)
{
user_visible = IsUserVisible();
if (active)
{
bool any_visible = false;
bool any_mapped = false;
bool any_on_top = false;
bool any_on_monitor = (arg.monitor < 0);
int active_monitor = arg.monitor;
for (auto const& window : GetManagedWindows())
{
Window xid = window->window_id();
if (!any_visible && wm.IsWindowOnCurrentDesktop(xid))
{
any_visible = true;
}
if (!any_mapped && wm.IsWindowMapped(xid))
{
any_mapped = true;
}
if (!any_on_top && wm.IsWindowOnTop(xid))
{
any_on_top = true;
}
if (!any_on_monitor && window->monitor() == arg.monitor &&
wm.IsWindowMapped(xid) && wm.IsWindowVisible(xid))
{
any_on_monitor = true;
}
if (window->active())
{
active_monitor = window->monitor();
}
}
if (!any_visible || !any_mapped || !any_on_top)
active = false;
if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
active = false;
}
}
/* Behaviour:
* 1) Nothing running, or nothing visible -> launch application
* 2) Running and active -> spread application
* 3) Running and not active -> focus application
* 4) Spread is active and different icon pressed -> change spread
* 5) Spread is active -> Spread de-activated, and fall through
*/
if (!IsRunning() || (IsRunning() && !user_visible)) // #1 above
{
if (GetQuirk(Quirk::STARTING, arg.monitor))
return;
wm.TerminateScale();
SetQuirk(Quirk::STARTING, true, arg.monitor);
OpenInstanceLauncherIcon(arg.timestamp);
}
else // container is running
{
if (active)
{
if (scale_was_active) // #5 above
{
wm.TerminateScale();
if (minimize_window_on_click())
{
for (auto const& win : GetWindows(WindowFilter::ON_CURRENT_DESKTOP))
wm.Minimize(win->window_id());
}
else
{
Focus(arg);
}
}
else // #2 above
{
if (arg.source != ActionArg::Source::SWITCHER)
{
bool minimized = false;
if (minimize_window_on_click())
{
WindowList const& windows = GetWindows(WindowFilter::ON_CURRENT_DESKTOP);
if (windows.size() == 1)
{
wm.Minimize(windows[0]->window_id());
minimized = true;
}
}
if (!minimized)
{
Spread(true, 0, false);
}
}
}
}
else
{
if (scale_was_active) // #4 above
{
if (GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() <= 1)
wm.TerminateScale();
Focus(arg);
if (arg.source != ActionArg::Source::SWITCHER)
Spread(true, 0, false);
}
else // #3 above
{
Focus(arg);
}
}
}
}
WindowList WindowedLauncherIcon::GetWindows(WindowFilterMask filter, int monitor)
{
if ((!filter && monitor < 0) || (filter == WindowFilter::ON_ALL_MONITORS))
return GetManagedWindows();
WindowManager& wm = WindowManager::Default();
WindowList results;
monitor = (filter & WindowFilter::ON_ALL_MONITORS) ? -1 : monitor;
bool mapped = (filter & WindowFilter::MAPPED);
bool user_visible = (filter & WindowFilter::USER_VISIBLE);
bool current_desktop = (filter & WindowFilter::ON_CURRENT_DESKTOP);
for (auto& window : GetManagedWindows())
{
if ((monitor >= 0 && window->monitor() == monitor) || monitor < 0)
{
if ((user_visible && window->visible()) || !user_visible)
{
Window xid = window->window_id();
if ((mapped && wm.IsWindowMapped(xid)) || !mapped)
{
if ((current_desktop && wm.IsWindowOnCurrentDesktop(xid)) || !current_desktop)
{
results.push_back(window);
}
}
}
}
}
return results;
}
WindowList WindowedLauncherIcon::Windows()
{
return GetWindows(WindowFilter::MAPPED|WindowFilter::ON_ALL_MONITORS);
}
WindowList WindowedLauncherIcon::WindowsOnViewport()
{
WindowFilterMask filter = 0;
filter |= WindowFilter::MAPPED;
filter |= WindowFilter::USER_VISIBLE;
filter |= WindowFilter::ON_CURRENT_DESKTOP;
filter |= WindowFilter::ON_ALL_MONITORS;
return GetWindows(filter);
}
WindowList WindowedLauncherIcon::WindowsForMonitor(int monitor)
{
WindowFilterMask filter = 0;
filter |= WindowFilter::MAPPED;
filter |= WindowFilter::USER_VISIBLE;
filter |= WindowFilter::ON_CURRENT_DESKTOP;
return GetWindows(filter, monitor);
}
void WindowedLauncherIcon::OnWindowMinimized(Window xid)
{
for (auto const& window : GetManagedWindows())
{
if (xid == window->window_id())
{
int monitor = GetCenterForMonitor(window->monitor()).first;
if (monitor >= 0)
{
Present(0.5f, 600, monitor);
FullyAnimateQuirkDelayed(300, Quirk::SHIMMER, monitor);
}
break;
}
}
}
void WindowedLauncherIcon::Focus(ActionArg arg)
{
bool show_only_visible = (arg.source == ActionArg::Source::SWITCHER);
ApplicationManager::Default().FocusWindowGroup(GetManagedWindows(), show_only_visible, arg.monitor);
}
bool WindowedLauncherIcon::Spread(bool current_desktop, int state, bool force)
{
std::vector windows;
for (auto& window : GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0))
windows.push_back(window->window_id());
return WindowManager::Default().ScaleWindowGroup(windows, state, force);
}
void WindowedLauncherIcon::EnsureWindowState()
{
std::vector number_of_windows_on_monitor(monitors::MAX);
for (auto const& window : WindowsOnViewport())
{
int monitor = window->monitor();
// If monitor is -1 (or negative), show on all monitors.
if (monitor < 0)
{
for (unsigned j; j < monitors::MAX; ++j)
++number_of_windows_on_monitor[j];
}
else
{
++number_of_windows_on_monitor[monitor];
}
}
for (unsigned i = 0; i < monitors::MAX; ++i)
SetNumberOfWindowsVisibleOnMonitor(number_of_windows_on_monitor[i], i);
}
void WindowedLauncherIcon::EnsureWindowsLocation()
{
EnsureWindowState();
UpdateIconGeometries(GetCenters());
}
void WindowedLauncherIcon::UpdateIconGeometries(std::vector const& centers)
{
nux::Geometry geo(0, 0, icon_size, icon_size);
for (auto& window : GetManagedWindows())
{
Window xid = window->window_id();
int monitor = GetCenterForMonitor(window->monitor()).first;
if (monitor < 0)
{
WindowManager::Default().SetWindowIconGeometry(xid, nux::Geometry());
continue;
}
geo.x = centers[monitor].x - icon_size / 2;
geo.y = centers[monitor].y - icon_size / 2;
WindowManager::Default().SetWindowIconGeometry(xid, geo);
}
}
void WindowedLauncherIcon::OnCenterStabilized(std::vector const& centers)
{
UpdateIconGeometries(centers);
}
void WindowedLauncherIcon::OnDndEnter()
{
auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
_source_manager.AddTimeout(1000, [this, timestamp] {
bool to_spread = GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() > 1;
if (!to_spread)
WindowManager::Default().TerminateScale();
if (!IsRunning())
return false;
UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
Focus(ActionArg(ActionArg::Source::LAUNCHER, 1, timestamp));
if (to_spread)
Spread(true, COMPIZ_SCALE_DND_SPREAD, false);
return false;
}, ICON_DND_OVER_TIMEOUT);
}
void WindowedLauncherIcon::OnDndLeave()
{
_source_manager.Remove(ICON_DND_OVER_TIMEOUT);
}
bool WindowedLauncherIcon::HandlesSpread()
{
return true;
}
bool WindowedLauncherIcon::ShowInSwitcher(bool current)
{
if (!removed() && IsRunning() && IsVisible())
{
// If current is true, we only want to show the current workspace.
if (!current)
{
return true;
}
else
{
for (unsigned i = 0; i < monitors::MAX; ++i)
{
if (WindowVisibleOnMonitor(i))
return true;
}
}
}
return false;
}
bool WindowedLauncherIcon::AllowDetailViewInSwitcher() const
{
return true;
}
uint64_t WindowedLauncherIcon::SwitcherPriority()
{
uint64_t result = 0;
for (auto& window : GetManagedWindows())
{
Window xid = window->window_id();
result = std::max(result, WindowManager::Default().GetWindowActiveNumber(xid));
}
return result;
}
void PerformScrollUp(WindowList const& windows, unsigned int progressive_scroll)
{
if (progressive_scroll == windows.size() - 1)
{
//RestackAbove to preserve Global Stacking Order
WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(1)->window_id());
WindowManager::Default().RestackBelow(windows.at(1)->window_id(), windows.at(0)->window_id());
windows.back()->Focus();
return;
}
WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll + 1)->window_id());
windows.at(progressive_scroll + 1)->Focus();
}
void PerformScrollDown(WindowList const& windows, unsigned int progressive_scroll)
{
if (!progressive_scroll)
{
WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.back()->window_id());
windows.at(1)->Focus();
return;
}
WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll)->window_id());
windows.at(progressive_scroll)->Focus();
}
void WindowedLauncherIcon::PerformScroll(ScrollDirection direction, Time timestamp)
{
if (timestamp - last_scroll_timestamp_ < 150)
return;
else if (timestamp - last_scroll_timestamp_ > 1500)
progressive_scroll_ = 0;
last_scroll_timestamp_ = timestamp;
auto const& windows = GetWindowsOnCurrentDesktopInStackingOrder();
if (windows.empty())
return;
if (scroll_inactive_icons && !IsActive())
{
windows.at(0)->Focus();
return;
}
if (!scroll_inactive_icons && !IsActive())
return;
if (windows.size() <= 1)
return;
if (direction == ScrollDirection::DOWN)
++progressive_scroll_;
else
//--progressive_scroll_; but roll to the top of windows
progressive_scroll_ += windows.size() - 1;
progressive_scroll_ %= windows.size();
switch(direction)
{
case ScrollDirection::UP:
PerformScrollUp(windows, progressive_scroll_);
break;
case ScrollDirection::DOWN:
PerformScrollDown(windows, progressive_scroll_);
break;
}
}
WindowList WindowedLauncherIcon::GetWindowsOnCurrentDesktopInStackingOrder()
{
auto windows = GetWindows(WindowFilter::ON_CURRENT_DESKTOP | WindowFilter::ON_ALL_MONITORS);
auto sorted_windows = WindowManager::Default().GetWindowsInStackingOrder();
// Order the windows
std::sort(windows.begin(), windows.end(), [&sorted_windows] (ApplicationWindowPtr const& win1, ApplicationWindowPtr const& win2) {
for (auto const& window : sorted_windows)
{
if (window == win1->window_id())
return false;
else if (window == win2->window_id())
return true;
}
return true;
});
return windows;
}
void WindowedLauncherIcon::Quit() const
{
for (auto& window : GetManagedWindows())
window->Quit();
}
void WindowedLauncherIcon::AboutToRemove()
{
Quit();
}
AbstractLauncherIcon::MenuItemsVector WindowedLauncherIcon::GetWindowsMenuItems()
{
auto const& windows = Windows();
MenuItemsVector menu_items;
// We only add quicklist menu-items for windows if we have more than one window
if (windows.size() < 2)
return menu_items;
// add menu items for all open windows
for (auto const& w : windows)
{
auto const& title = w->title();
if (title.empty())
continue;
glib::Object menu_item(dbusmenu_menuitem_new());
dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, title.c_str());
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ACCEL_DISABLED_PROPERTY, true);
dbusmenu_menuitem_property_set_int(menu_item, QuicklistMenuItem::MAXIMUM_LABEL_WIDTH_PROPERTY, MAXIMUM_QUICKLIST_WIDTH);
Window xid = w->window_id();
glib_signals_.Add(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[xid] (DbusmenuMenuitem*, unsigned) {
WindowManager& wm = WindowManager::Default();
wm.Activate(xid);
wm.Raise(xid);
});
if (w->active())
{
dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO);
dbusmenu_menuitem_property_set_int(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
}
menu_items.push_back(menu_item);
}
return menu_items;
}
std::string WindowedLauncherIcon::GetName() const
{
return "WindowedLauncherIcon";
}
void WindowedLauncherIcon::AddProperties(debug::IntrospectionData& introspection)
{
SimpleLauncherIcon::AddProperties(introspection);
std::vector xids;
for (auto const& window : GetManagedWindows())
xids.push_back(window->window_id());
introspection.add("xids", glib::Variant::FromVector(xids))
.add("sticky", IsSticky());
}
} // namespace launcher
} // namespace unity
./launcher/CairoBaseWindow.h 0000644 0000156 0000165 00000003257 12704076362 016105 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Marco Trevisan <3v1n0@ubuntu.com>
*/
#ifndef CAIRO_BASEWINDOW_H
#define CAIRO_BASEWINDOW_H
#include
#include
#include
#include "unity-shared/EMConverter.h"
namespace unity
{
class CairoBaseWindow : public nux::BaseWindow
{
NUX_DECLARE_OBJECT_TYPE(CairoBaseWindow, nux::BaseWindow);
public:
CairoBaseWindow(int monitor = 0);
virtual void Show();
virtual void Hide();
void PromptHide();
void RedrawBlur();
bool HasBlurredBackground() const;
sigc::signal hidden;
protected:
void Draw(nux::GraphicsEngine& gfxContext, bool forceDraw);
nux::ObjectPtr texture_bg_;
nux::ObjectPtr texture_mask_;
nux::ObjectPtr texture_outline_;
EMConverter::Ptr cv_;
private:
bool use_blurred_background_;
bool compute_blur_bkg_;
nux::ObjectPtr bg_blur_texture_;
nux::animation::AnimateValue fade_animator_;
};
}
#endif // CAIRO_BASEWINDOW_H
./launcher/EdgeBarrierController.h 0000644 0000156 0000165 00000004070 12704076362 017276 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
*/
#ifndef UNITY_EDGEBARRIERCONTROLLER_H
#define UNITY_EDGEBARRIERCONTROLLER_H
#include "PointerBarrier.h"
#include "LauncherOptions.h"
namespace unity {
namespace ui {
struct EdgeBarrierSubscriber
{
enum class Result
{
IGNORED,
HANDLED,
ALREADY_HANDLED,
NEEDS_RELEASE
};
virtual ~EdgeBarrierSubscriber() {}
virtual Result HandleBarrierEvent(PointerBarrierWrapper::Ptr const& owner, BarrierEvent::Ptr event) = 0;
};
class EdgeBarrierController : public sigc::trackable
{
public:
typedef std::shared_ptr Ptr;
EdgeBarrierController();
~EdgeBarrierController();
nux::RWProperty sticky_edges;
nux::Property force_disable;
nux::Property options;
void AddHorizontalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor);
void RemoveHorizontalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor);
void AddVerticalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor);
void RemoveVerticalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor);
EdgeBarrierSubscriber* GetHorizontalSubscriber(unsigned int monitor);
EdgeBarrierSubscriber* GetVerticalSubscriber(unsigned int monitor);
private:
struct Impl;
std::unique_ptr pimpl;
friend class TestEdgeBarrierController;
};
}
}
#endif
./launcher/Volume.h 0000644 0000156 0000165 00000003663 12704076362 014335 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#ifndef UNITYSHELL_VOLUME_H
#define UNITYSHELL_VOLUME_H
#include
#include
#include
#include
namespace unity
{
namespace launcher
{
class Volume : public sigc::trackable
{
public:
typedef std::shared_ptr Ptr;
Volume() = default;
virtual ~Volume() = default;
virtual bool CanBeEjected() const = 0;
virtual bool CanBeFormatted() const = 0;
virtual bool CanBeRemoved() const = 0;
virtual bool CanBeStopped() const = 0;
virtual std::string GetName() const = 0;
virtual std::string GetIconName() const = 0;
virtual std::string GetIdentifier() const = 0;
virtual std::string GetUnixDevicePath() const = 0;
virtual std::string GetUri() const = 0;
virtual bool HasSiblings() const = 0;
virtual bool IsMounted() const = 0;
virtual void Eject() = 0;
virtual void Mount() = 0;
virtual void StopDrive() = 0;
virtual void Unmount() = 0;
sigc::signal changed;
sigc::signal removed;
sigc::signal mounted;
sigc::signal unmounted;
sigc::signal ejected;
sigc::signal stopped;
private:
Volume(Volume const&) = delete;
Volume& operator=(Volume const&) = delete;
};
}
}
#endif
./launcher/DeviceNotificationDisplay.h 0000644 0000156 0000165 00000002331 12704076362 020151 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#ifndef UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_H
#define UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_H
#include
#include
#include
namespace unity
{
namespace launcher
{
class DeviceNotificationDisplay : private boost::noncopyable
{
public:
typedef std::shared_ptr Ptr;
virtual ~DeviceNotificationDisplay() {}
virtual void Display(std::string const& icon_name, std::string const& volume_name) = 0;
};
}
}
#endif
./launcher/XdndCollectionWindowImp.cpp 0000644 0000156 0000165 00000007540 12704076362 020166 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2011 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#include "XdndCollectionWindowImp.h"
#include "unity-shared/UScreen.h"
#include "unity-shared/WindowManager.h"
namespace unity {
namespace {
class PrivateWindow : public nux::BaseWindow
{
public:
PrivateWindow(XdndCollectionWindowImp* parent)
: nux::BaseWindow("")
, parent_(parent)
{
// Make it invisible...
SetBackgroundColor(nux::color::Transparent);
SetOpacity(0.0f);
// ... and as big as the whole screen.
auto uscreen = UScreen::GetDefault();
SetGeometry(uscreen->GetScreenGeometry());
// We are not calling ShowWindow () as this window
// isn't really visible
PushToBack();
if (nux::GetWindowThread()->IsEmbeddedWindow())
{
// Hack to create the X Window as soon as possible.
EnableInputWindow(true, "XdndCollectionWindowImp");
EnableInputWindow(false, "XdndCollectionWindowImp");
}
SetDndEnabled(false, true);
uscreen->changed.connect(sigc::mem_fun(this, &PrivateWindow::OnScreenChanged));
WindowManager::Default().window_moved.connect(sigc::mem_fun(this, &PrivateWindow::OnWindowMoved));
}
void OnScreenChanged(int /*primary*/, std::vector const& /*monitors*/)
{
auto uscreen = UScreen::GetDefault();
SetGeometry(uscreen->GetScreenGeometry());
}
/**
* EnableInputWindow doesn't show the window immediately.
* Since nux::EnableInputWindow uses XMoveResizeWindow the best way to know if
* the X Window is really on/off screen is receiving WindowManager::window_moved
* signal. Please don't hate me!
**/
void OnWindowMoved(Window window_id)
{
if (G_LIKELY(window_id != GetInputWindowId()))
return;
// Create a fake mouse move because sometimes an extra one is required.
auto display = nux::GetGraphicsDisplay()->GetX11Display();
XWarpPointer(display, None, None, 0, 0, 0, 0, 0, 0);
XFlush(display);
}
void ProcessDndMove(int x, int y, std::list mimes)
{
// Hide the window as soon as possible.
PushToBack();
EnableInputWindow(false, "XdndCollectionWindowImp");
std::vector data;
for (auto mime : mimes)
if (mime) data.push_back(mime);
parent_->collected.emit(data);
}
XdndCollectionWindowImp* parent_;
};
}
XdndCollectionWindowImp::XdndCollectionWindowImp()
: window_(new PrivateWindow(this))
{}
void XdndCollectionWindowImp::Collect()
{
// Using PushToFront we're sure that the window is shown over the panel window,
// the launcher window and the dash window. Don't forget to call PushToBack as
// soon as possible.
window_->ShowWindow(true);
window_->PushToFront();
if (nux::GetWindowThread()->IsEmbeddedWindow())
window_->EnableInputWindow(true, "XdndCollectionWindowImp");
}
void XdndCollectionWindowImp::Deactivate()
{
window_->ShowWindow(false);
window_->PushToBack();
if (nux::GetWindowThread()->IsEmbeddedWindow())
window_->EnableInputWindow(false, "XdndCollectionWindowImp");
}
std::string XdndCollectionWindowImp::GetData(std::string const& type)
{
auto& gp_display = nux::GetWindowThread()->GetGraphicsDisplay();
return glib::String(gp_display.GetDndData(const_cast(type.c_str()))).Str();
}
}
./launcher/pch/ 0000755 0000156 0000165 00000000000 12704076362 013457 5 ustar jenkins jenkins ./launcher/pch/launcher_pch.hh 0000644 0000156 0000165 00000002056 12704076362 016436 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jussi Pakkanen
*/
/*
* These are the precompiled header includes for this module.
* Only system header files can be listed here.
*/
#include
#include
#include
#include
#include
#include
#include
./launcher/QuicklistMenuItemRadio.h 0000644 0000156 0000165 00000002436 12704076362 017456 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Mirco Müller
* Marco Trevisan
*/
#ifndef QUICKLISTMENUITEMRADIO_H
#define QUICKLISTMENUITEMRADIO_H
#include "QuicklistMenuItem.h"
namespace unity
{
class QuicklistMenuItemRadio : public QuicklistMenuItem
{
public:
QuicklistMenuItemRadio(glib::Object const& item, NUX_FILE_LINE_PROTO);
protected:
std::string GetName() const;
virtual std::string GetDefaultText() const;
virtual void UpdateTexture(nux::CairoGraphics&, double width, double height);
};
} //NAMESPACE
#endif // QUICKLISTMENUITEMRADIO_H
./launcher/LauncherOptions.h 0000644 0000156 0000165 00000005245 12704076362 016201 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
* Tim Penhey
*/
#ifndef LAUNCHEROPTIONS_H
#define LAUNCHEROPTIONS_H
#include
#include
#include
#include
#include
namespace unity
{
namespace launcher
{
enum LauncherHideMode
{
LAUNCHER_HIDE_NEVER,
LAUNCHER_HIDE_AUTOHIDE,
};
enum LaunchAnimation
{
LAUNCH_ANIMATION_NONE,
LAUNCH_ANIMATION_PULSE,
LAUNCH_ANIMATION_BLINK,
};
enum UrgentAnimation
{
URGENT_ANIMATION_NONE,
URGENT_ANIMATION_PULSE,
URGENT_ANIMATION_WIGGLE,
};
enum AutoHideAnimation
{
FADE_OR_SLIDE,
SLIDE_ONLY,
FADE_ONLY,
FADE_AND_SLIDE,
};
enum BacklightMode
{
BACKLIGHT_ALWAYS_ON,
BACKLIGHT_NORMAL,
BACKLIGHT_ALWAYS_OFF,
BACKLIGHT_EDGE_TOGGLE,
BACKLIGHT_NORMAL_EDGE_TOGGLE
};
enum RevealTrigger
{
EDGE,
CORNER,
};
class Options : public sigc::trackable
{
public:
typedef std::shared_ptr Ptr;
Options();
nux::Property hide_mode;
nux::Property launch_animation;
nux::Property urgent_animation;
nux::Property auto_hide_animation;
nux::Property backlight_mode;
nux::Property reveal_trigger;
nux::Property background_color;
nux::Property background_alpha;
nux::Property icon_size;
nux::Property tile_size;
nux::Property super_tap_duration;
nux::Property edge_decay_rate;
nux::Property edge_overcome_pressure;
nux::Property edge_stop_velocity;
nux::Property edge_reveal_pressure;
nux::Property edge_responsiveness;
nux::Property edge_passed_disabled_ms;
nux::Property edge_resist;
nux::Property show_for_all;
nux::Property scroll_inactive_icons;
nux::Property minimize_window_on_click;
sigc::signal option_changed;
private:
glib::Source::UniquePtr changed_idle_;
};
}
}
#endif // LAUNCHEROPTIONS_H
./launcher/BFBLauncherIcon.h 0000644 0000156 0000165 00000003451 12704076362 015745 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2011 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
*/
#ifndef UNITYSHELL_BFBLAUNCHERICON_H
#define UNITYSHELL_BFBLAUNCHERICON_H
#include
#include
#include
#include "LauncherOptions.h"
#include "SimpleLauncherIcon.h"
#include "unity-shared/UBusWrapper.h"
namespace unity
{
namespace launcher
{
class BFBLauncherIcon : public SimpleLauncherIcon
{
public:
BFBLauncherIcon();
virtual nux::Color BackgroundColor() const;
virtual nux::Color GlowColor();
void ActivateLauncherIcon(ActionArg arg);
void SetHideMode(LauncherHideMode hide_mode);
protected:
MenuItemsVector GetMenus();
std::string GetName() const;
private:
void OnOverlayShown(GVariant *data, bool visible);
void OnMenuitemActivated(DbusmenuMenuitem* item, int time, std::string const& scope_id);
void UpdateDefaultSearchText();
void UpdateIcon();
nux::Color background_color_;
dash::GSettingsScopesReader::Ptr reader_;
LauncherHideMode launcher_hide_mode_;
UBusManager ubus_manager_;
glib::SignalManager signals_;
};
}
}
#endif // UNITYSHELL_BFBLAUNCHERICON_H
./launcher/LauncherIcon.h 0000644 0000156 0000165 00000021707 12704076362 015437 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
*
*/
#ifndef LAUNCHERICON_H
#define LAUNCHERICON_H
#include
#include
#include
#include
#include
#include
#include
#include "AbstractLauncherIcon.h"
#include "MultiMonitor.h"
#include "Tooltip.h"
#include "QuicklistView.h"
#include "LauncherEntryRemote.h"
#include "unity-shared/TimeUtil.h"
namespace unity
{
namespace launcher
{
class Launcher;
class LauncherIcon : public AbstractLauncherIcon
{
NUX_DECLARE_OBJECT_TYPE(LauncherIcon, AbstractLauncherIcon);
public:
typedef nux::ObjectPtr BaseTexturePtr;
LauncherIcon(IconType type);
void SetShortcut(guint64 shortcut);
guint64 GetShortcut();
void SetSortPriority(int priority);
void RecvMouseEnter(int monitor);
void RecvMouseLeave(int monitor);
void RecvMouseDown(int button, int monitor, unsigned long key_flags = 0);
void RecvMouseUp(int button, int monitor, unsigned long key_flags = 0);
void RecvMouseClick(int button, int monitor, unsigned long key_flags = 0);
void HideTooltip();
void PromptHideTooltip();
void ShowTooltip();
bool OpenQuicklist(bool select_first_item = false, int monitor = -1, bool restore_input_focus = false);
void CloseQuicklist();
void SetCenter(nux::Point3 const& center, int parent_monitor);
void ResetCenters(int monitor = -1);
nux::Point3 GetCenter(int monitor);
void Activate(ActionArg arg);
void OpenInstance(ActionArg arg);
void SaveCenter();
nux::Point3 GetSavedCenter(int monitor);
int SortPriority();
void SetOrder(int order);
WindowList Windows() { return WindowList(); }
WindowList WindowsOnViewport() { return WindowList(); }
WindowList WindowsForMonitor(int monitor) { return WindowList(); }
bool WindowVisibleOnMonitor(int monitor) const;
bool WindowVisibleOnViewport() const;
size_t WindowsVisibleOnMonitor(int monitor) const;
size_t WindowsVisibleOnViewport() const;
float PresentUrgency();
float GetProgress();
void SetEmblemIconName(std::string const& name);
void SetEmblemText(std::string const& text);
void DeleteEmblem();
virtual bool ShowInSwitcher(bool current)
{
return false;
};
virtual bool AllowDetailViewInSwitcher() const override
{
return false;
}
virtual uint64_t SwitcherPriority()
{
return 0;
}
bool GetQuirk(Quirk quirk, int monitor = -1) const;
void SetQuirk(Quirk quirk, bool value, int monitor = -1);
float GetQuirkProgress(Quirk quirk, int monitor) const;
void SetQuirkDuration(Quirk quirk, unsigned duration, int monitor = -1);
void SkipQuirkAnimation(Quirk quirk, int monitor = -1);
IconType GetIconType() const;
virtual nux::Color BackgroundColor() const;
virtual nux::Color GlowColor();
std::string RemoteUri() const
{
return GetRemoteUri();
}
nux::BaseTexture* TextureForSize(int size);
nux::BaseTexture* Emblem() const override;
nux::BaseTexture* CountTexture(double scale) override;
MenuItemsVector Menus();
unsigned Count() const;
void InsertEntryRemote(LauncherEntryRemote::Ptr const&);
void SelectEntryRemote(LauncherEntryRemote::Ptr const&);
void RemoveEntryRemote(LauncherEntryRemote::Ptr const&);
nux::DndAction QueryAcceptDrop(DndData const& dnd_data)
{
return OnQueryAcceptDrop(dnd_data);
}
bool ShouldHighlightOnDrag(DndData const& dnd_data)
{
return OnShouldHighlightOnDrag(dnd_data);
}
void AcceptDrop(DndData const& dnd_data)
{
return OnAcceptDrop(dnd_data);
}
void SendDndEnter()
{
OnDndEnter();
}
void SendDndLeave()
{
OnDndLeave();
}
virtual std::string DesktopFile() const { return std::string(); }
virtual bool IsSticky() const { return _sticky; }
virtual bool IsVisible() const { return GetQuirk(Quirk::VISIBLE); }
virtual bool IsVisibleOnMonitor(int monitor) const;
virtual void SetVisibleOnMonitor(int monitor, bool visible);
virtual void AboutToRemove() {}
virtual void Stick(bool save = true);
virtual void UnStick();
virtual glib::Object GetRemoteMenus() const;
void PerformScroll(ScrollDirection direction, Time timestamp) override;
protected:
std::vector GetCenters();
std::pair GetCenterForMonitor(int monitor) const;
std::string GetName() const;
void AddProperties(debug::IntrospectionData&);
void FullyAnimateQuirkDelayed(guint ms, Quirk quirk, int monitor = -1);
void FullyAnimateQuirk(Quirk quirk, int monitor = -1);
void Remove();
void SetProgress(float progress);
void SetNumberOfWindowsVisibleOnMonitor(int number_of_windows, int monitor);
void Present(float urgency, int length, int monitor = -1);
void Unpresent(int monitor = -1);
void SetEmblem(BaseTexturePtr const& emblem);
virtual MenuItemsVector GetMenus();
virtual nux::BaseTexture* GetTextureForSize(int size) = 0;
virtual void OnCenterStabilized(std::vector const& centers) {}
virtual std::string GetRemoteUri() const
{
return "";
}
virtual nux::DndAction OnQueryAcceptDrop(DndData const& dnd_data)
{
return nux::DNDACTION_NONE;
}
virtual bool OnShouldHighlightOnDrag(DndData const& dnd_data)
{
return false;
}
virtual void OnAcceptDrop(DndData const& dnd_data) {}
virtual void OnDndEnter() {}
virtual void OnDndLeave() {}
virtual void ActivateLauncherIcon(ActionArg arg) {}
virtual void OpenInstanceLauncherIcon(Time timestamp) {}
virtual bool HandlesSpread () { return false; }
BaseTexturePtr TextureFromPixbuf(GdkPixbuf *pixbuf, int size, bool update_glow_colors = true);
BaseTexturePtr TextureFromGtkTheme(std::string name, int size, bool update_glow_colors = true);
BaseTexturePtr TextureFromSpecificGtkTheme(GtkIconTheme* theme, std::string const& name, int size, bool update_glow_colors = true, bool is_default_theme = false);
BaseTexturePtr TextureFromPath(std::string const& name, int size, bool update_glow_colors = true);
void OnRemoteEmblemChanged(LauncherEntryRemote* remote);
void OnRemoteCountChanged(LauncherEntryRemote* remote);
void OnRemoteProgressChanged(LauncherEntryRemote* remote);
void OnRemoteQuicklistChanged(LauncherEntryRemote* remote);
void OnRemoteUrgentChanged(LauncherEntryRemote* remote);
void OnRemoteEmblemVisibleChanged(LauncherEntryRemote* remote);
void OnRemoteCountVisibleChanged(LauncherEntryRemote* remote);
void OnRemoteProgressVisibleChanged(LauncherEntryRemote* remote);
void EmitNeedsRedraw(int monitor = -1);
void EmitRemove();
bool IsActionArgValid(ActionArg const&);
typedef nux::animation::AnimateValue Animation;
inline Animation& GetQuirkAnimation(Quirk quirk, int monitor) const
{
return *_quirk_animations[monitor][unsigned(quirk)];
}
private:
IconType _icon_type;
nux::ObjectPtr _tooltip;
nux::ObjectPtr _quicklist;
static void ChildRealized(DbusmenuMenuitem* newitem, QuicklistView* quicklist);
static void RootChanged(DbusmenuClient* client, DbusmenuMenuitem* newroot, QuicklistView* quicklist);
void ColorForIcon(GdkPixbuf* pixbuf, nux::Color& background, nux::Color& glow);
nux::Point GetTipPosition(int monitor) const;
void LoadTooltip();
void LoadQuicklist();
void OnTooltipEnabledChanged(bool value);
void CleanCountTextures();
BaseTexturePtr DrawCountTexture(unsigned count, double scale);
bool _sticky;
float _present_urgency;
float _progress;
int _sort_priority;
int _order;
int _last_monitor;
nux::Color _background_color;
nux::Color _glow_color;
gint64 _shortcut;
bool _allow_quicklist_to_show;
std::vector _center;
std::bitset _has_visible_window;
std::vector _number_of_visible_windows;
std::vector> _quirks;
std::vector>> _quirk_animations;
std::vector _last_stable;
std::vector _saved_center;
time::Spec _last_action;
BaseTexturePtr _emblem;
std::unordered_map _counts;
std::vector _remote_entries;
connection::Manager _remote_connections;
glib::Object _remote_menus;
protected:
glib::SourceManager _source_manager;
};
}
}
#endif // LAUNCHERICON_H
./launcher/QuicklistMenuItemRadio.cpp 0000644 0000156 0000165 00000006222 12704076362 020006 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Mirco Müller
* Marco Trevisan
*/
#include "unity-shared/CairoTexture.h"
#include "QuicklistMenuItemRadio.h"
namespace unity
{
QuicklistMenuItemRadio::QuicklistMenuItemRadio(glib::Object const& item, NUX_FILE_LINE_DECL)
: QuicklistMenuItem(QuicklistMenuItemType::RADIO, item, NUX_FILE_LINE_PARAM)
{
InitializeText();
}
std::string QuicklistMenuItemRadio::GetDefaultText() const
{
return "Radio Button";
}
std::string QuicklistMenuItemRadio::GetName() const
{
return "QuicklistMenuItemRadio";
}
void QuicklistMenuItemRadio::UpdateTexture(nux::CairoGraphics& cairoGraphics, double width, double height)
{
cairo_t* cr = cairoGraphics.GetInternalContext();
// draw normal, disabled version
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
DrawText(cairoGraphics, width, height, nux::color::White);
_normalTexture[0].Adopt(texture_from_cairo_graphics(cairoGraphics));
// draw normal, enabled version
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_scale(cr, 1.0f, 1.0f);
cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f);
cairo_set_line_width(cr, 1.0f);
double x = Align((ITEM_INDENT_ABS + ITEM_MARGIN) / 2.0f);
double y = Align(static_cast(height) / 2.0f);
double radius = 3.5f;
cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f);
cairo_arc(cr, x, y, radius, 0.0f * (G_PI / 180.0f), 360.0f * (G_PI / 180.0f));
cairo_fill(cr);
DrawText(cairoGraphics, width, height, nux::color::White);
_normalTexture[1].Adopt(texture_from_cairo_graphics(cairoGraphics));
// draw active/prelight, unchecked version
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
DrawPrelight(cairoGraphics, width, height, nux::color::White);
DrawText(cairoGraphics, width, height, nux::color::White * 0.0f);
_prelightTexture[0].Adopt(texture_from_cairo_graphics(cairoGraphics));
// draw active/prelight, unchecked version
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
DrawPrelight(cairoGraphics, width, height, nux::color::White);
cairo_set_source_rgba(cr, 0.0f, 0.0f, 0.0f, 0.0f);
cairo_arc(cr, x, y, radius, 0.0f * (G_PI / 180.0f), 360.0f * (G_PI / 180.0f));
cairo_fill(cr);
DrawText(cairoGraphics, width, height, nux::color::White * 0.0f);
_prelightTexture[1].Adopt(texture_from_cairo_graphics(cairoGraphics));
}
} // NAMESPACE
./launcher/Launcher.cpp 0000644 0000156 0000165 00000300031 12704076362 015147 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
* Authored by: Jay Taoko
*/
#include "config.h"
#include
#include
#include "Launcher.h"
#include "AbstractLauncherIcon.h"
#include "SpacerLauncherIcon.h"
#include "LauncherModel.h"
#include "QuicklistManager.h"
#include "QuicklistView.h"
#include "unity-shared/AnimationUtils.h"
#include "unity-shared/IconRenderer.h"
#include "unity-shared/GraphicsUtils.h"
#include "unity-shared/IconLoader.h"
#include "unity-shared/PanelStyle.h"
#include "unity-shared/TextureCache.h"
#include "unity-shared/TimeUtil.h"
#include "unity-shared/UScreen.h"
#include "unity-shared/UBusMessages.h"
#include "unity-shared/UnitySettings.h"
#include
#include
namespace unity
{
using ui::RenderArg;
namespace launcher
{
DECLARE_LOGGER(logger, "unity.launcher");
const char* window_title = "unity-launcher";
namespace
{
const int URGENT_BLINKS = 3;
const int WIGGLE_CYCLES = 6;
const int MAX_STARTING_BLINKS = 15;
const int STARTING_BLINK_LAMBDA = 3;
const int PULSE_BLINK_LAMBDA = 2;
const float BACKLIGHT_STRENGTH = 0.9f;
const RawPixel ICON_PADDING = 6_em;
const RawPixel SIDE_LINE_WIDTH = 1_em;
const int ANIM_DURATION_SHORT = 125;
const int ANIM_DURATION_SHORT_SHORT = 100;
const int ANIM_DURATION = 200;
const int ANIM_DURATION_LONG = 350;
const int START_DRAGICON_DURATION = 250;
const RawPixel DEFAULT_ICON_SIZE = 48_em;
const RawPixel DEFAULT_ICON_SIZE_DELTA = 6_em;
const RawPixel SPACE_BETWEEN_ICONS = 5_em;
const int MOUSE_DEADZONE = 15;
const float DRAG_OUT_PIXELS = 300.0f;
const float FOLDED_Z_DISTANCE = 10.f;
const float NEG_FOLDED_ANGLE = -1.0f;
const RawPixel SCROLL_AMOUNT = 25_em;
const RawPixel SCROLL_AREA_HEIGHT = 24_em;
const int SCROLL_FPS = 30;
const int BASE_URGENT_ANIMATION_PERIOD = 60; // In seconds
const int MAX_URGENT_ANIMATION_DELTA = 960; // In seconds
const int DOUBLE_TIME = 2;
const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";
const std::string SCROLL_TIMEOUT = "scroll-timeout";
const std::string SCALE_DESATURATE_IDLE = "scale-desaturate-idle";
const std::string URGENT_TIMEOUT = "urgent-timeout";
const std::string LAST_ANIMATION_URGENT_IDLE = "last-animation-urgent-idle";
}
NUX_IMPLEMENT_OBJECT_TYPE(Launcher);
Launcher::Launcher(MockableBaseWindow* parent,
NUX_FILE_LINE_DECL)
: View(NUX_FILE_LINE_PARAM)
, monitor(0)
, parent_(parent)
, icon_renderer_(std::make_shared())
, hovered_(false)
, hidden_(false)
, folded_(true)
, shortcuts_shown_(false)
, data_checked_(false)
, steal_drag_(false)
, drag_edge_touching_(false)
, initial_drag_animation_(false)
, dash_is_open_(false)
, hud_is_open_(false)
, launcher_action_state_(ACTION_NONE)
, icon_size_(DEFAULT_ICON_SIZE + DEFAULT_ICON_SIZE_DELTA)
, dnd_delta_y_(0)
, dnd_delta_x_(0)
, postreveal_mousemove_delta_x_(0)
, postreveal_mousemove_delta_y_(0)
, launcher_drag_delta_(0)
, launcher_drag_delta_max_(0)
, launcher_drag_delta_min_(0)
, enter_x_(0)
, enter_y_(0)
, last_button_press_(0)
, urgent_animation_period_(0)
, urgent_ack_needed_(false)
, drag_out_delta_x_(0.0f)
, drag_gesture_ongoing_(false)
, last_reveal_progress_(0.0f)
, drag_action_(nux::DNDACTION_NONE)
, bg_effect_helper_(this)
, launcher_position_(unity::Settings::Instance().launcher_position())
, auto_hide_animation_(ANIM_DURATION_SHORT)
, hover_animation_(ANIM_DURATION)
, drag_over_animation_(ANIM_DURATION_LONG)
, drag_out_animation_(ANIM_DURATION_SHORT)
, drag_icon_animation_(ANIM_DURATION_SHORT)
, dnd_hide_animation_(ANIM_DURATION * 3)
, dash_showing_animation_(90)
, cv_(unity::Settings::Instance().em(monitor))
{
icon_renderer_->monitor = monitor();
icon_renderer_->scale = cv_->DPIScale();
icon_renderer_->SetTargetSize(icon_size_.CP(cv_), DEFAULT_ICON_SIZE.CP(cv_), SPACE_BETWEEN_ICONS.CP(cv_));
CaptureMouseDownAnyWhereElse(true);
SetAcceptKeyNavFocusOnMouseDown(false);
SetAcceptMouseWheelEvent(true);
SetDndEnabled(false, true);
auto const& redraw_cb = sigc::hide(sigc::mem_fun(this, &Launcher::QueueDraw));
hide_machine_.should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden));
hide_machine_.reveal_progress.changed.connect(redraw_cb);
hover_machine_.should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover));
bg_effect_helper_.enabled.changed.connect(redraw_cb);
mouse_down.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
mouse_up.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
mouse_drag.connect(sigc::mem_fun(this, &Launcher::RecvMouseDrag));
mouse_enter.connect(sigc::mem_fun(this, &Launcher::RecvMouseEnter));
mouse_leave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave));
mouse_move.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove));
mouse_wheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel));
QuicklistManager& ql_manager = *(QuicklistManager::Default());
ql_manager.quicklist_opened.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistOpened));
ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
WindowManager& wm = WindowManager::Default();
wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnSpreadChanged));
wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnSpreadChanged));
wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnExpoChanged));
wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnExpoChanged));
wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::QueueDraw));
ubus_.RegisterInterest(UBUS_OVERLAY_SHOWN, sigc::mem_fun(this, &Launcher::OnOverlayShown));
ubus_.RegisterInterest(UBUS_OVERLAY_HIDDEN, sigc::mem_fun(this, &Launcher::OnOverlayHidden));
ubus_.RegisterInterest(UBUS_LAUNCHER_LOCK_HIDE, sigc::mem_fun(this, &Launcher::OnLockHideChanged));
LoadTextures();
TextureCache::GetDefault().themed_invalidated.connect(sigc::mem_fun(this, &Launcher::LoadTextures));
options.changed.connect(sigc::mem_fun(this, &Launcher::OnOptionsChanged));
monitor.changed.connect(sigc::mem_fun(this, &Launcher::OnMonitorChanged));
launcher_position_changed_ = unity::Settings::Instance().launcher_position.changed.connect([this] (LauncherPosition const& position) {
launcher_position_ = position;
LoadTextures();
OnMonitorChanged(monitor);
QueueDraw();
});
unity::Settings::Instance().dpi_changed.connect(sigc::mem_fun(this, &Launcher::OnDPIChanged));
auto_hide_animation_.updated.connect(redraw_cb);
hover_animation_.updated.connect(redraw_cb);
drag_over_animation_.updated.connect(redraw_cb);
drag_out_animation_.updated.connect(redraw_cb);
drag_icon_animation_.updated.connect(redraw_cb);
dnd_hide_animation_.updated.connect(redraw_cb);
dash_showing_animation_.updated.connect(redraw_cb);
}
/* Introspection */
std::string Launcher::GetName() const
{
return "Launcher";
}
void Launcher::LoadTextures()
{
auto& cache = TextureCache::GetDefault();
auto launcher_pressure_icon = launcher_position_ == LauncherPosition::LEFT ?
"launcher_pressure_effect" :
"launcher_pressure_effect_rotated";
launcher_pressure_effect_ = cache.FindTexture(launcher_pressure_icon);
launcher_sheen_ = cache.FindTexture("dash_sheen");
QueueDraw();
}
#ifdef NUX_GESTURES_SUPPORT
void Launcher::OnDragStart(const nux::GestureEvent &event)
{
drag_gesture_ongoing_ = true;
if (hidden_)
{
drag_out_delta_x_ = 0.0f;
}
else
{
drag_out_delta_x_ = DRAG_OUT_PIXELS;
hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
}
}
void Launcher::OnDragUpdate(const nux::GestureEvent &event)
{
auto& wm = WindowManager::Default();
if (options()->hide_mode == LAUNCHER_HIDE_AUTOHIDE &&
!wm.IsScaleActive() && !wm.IsExpoActive() &&
!dash_is_open_ && !hud_is_open_)
{
drag_out_delta_x_ =
CLAMP(drag_out_delta_x_ + event.GetDelta().x, 0.0f, DRAG_OUT_PIXELS);
QueueDraw();
}
}
void Launcher::OnDragFinish(const nux::GestureEvent &event)
{
if (drag_out_delta_x_ >= DRAG_OUT_PIXELS - 90.0f)
hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true);
animation::StartOrReverse(drag_out_animation_, animation::Direction::BACKWARD);
drag_gesture_ongoing_ = false;
}
#endif
void Launcher::AddProperties(debug::IntrospectionData& introspection)
{
introspection
.add(GetAbsoluteGeometry())
.add("hover-progress", hover_animation_.GetCurrentValue())
.add("dnd-exit-progress", drag_over_animation_.GetCurrentValue())
.add("autohide-progress", auto_hide_animation_.GetCurrentValue())
.add("dnd-delta", dnd_delta_y_)
.add("hovered", hovered_)
.add("hidemode", options()->hide_mode)
.add("hidden", hidden_)
.add("is_showing", ! hidden_)
.add("monitor", monitor())
.add("quicklist-open", hide_machine_.GetQuirk(LauncherHideMachine::QUICKLIST_OPEN))
.add("hide-quirks", hide_machine_.DebugHideQuirks())
.add("hover-quirks", hover_machine_.DebugHoverQuirks())
.add("icon-size", icon_size_.CP(cv_))
.add("shortcuts_shown", shortcuts_shown_)
.add("tooltip-shown", active_tooltip_ != nullptr);
}
void Launcher::SetMousePosition(int x, int y)
{
bool was_beyond_drag_threshold = MouseBeyondDragThreshold();
mouse_position_ = nux::Point(x, y);
bool is_beyond_drag_threshold = MouseBeyondDragThreshold();
if (was_beyond_drag_threshold != is_beyond_drag_threshold)
animation::StartOrReverseIf(drag_icon_animation_, !is_beyond_drag_threshold);
EnsureScrollTimer();
}
void Launcher::SetStateMouseOverLauncher(bool over_launcher)
{
hide_machine_.SetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER, over_launcher);
hide_machine_.SetQuirk(LauncherHideMachine::REVEAL_PRESSURE_PASS, false);
hover_machine_.SetQuirk(LauncherHoverMachine::MOUSE_OVER_LAUNCHER, over_launcher);
tooltip_manager_.SetHover(over_launcher);
}
void Launcher::SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon)
{
if (icon_under_mouse_ == icon)
return;
if (icon_under_mouse_)
icon_under_mouse_->mouse_leave.emit(monitor);
if (icon)
icon->mouse_enter.emit(monitor);
icon_under_mouse_ = icon;
}
bool Launcher::MouseBeyondDragThreshold() const
{
if (GetActionState() == ACTION_DRAG_ICON)
{
if (launcher_position_ == LauncherPosition::LEFT)
return mouse_position_.x > GetGeometry().width + icon_size_.CP(cv_) / 2;
else
return mouse_position_.y < GetGeometry().y - icon_size_.CP(cv_) / 2;
}
return false;
}
/* Render Layout Logic */
float Launcher::DragOutProgress() const
{
float progress = drag_out_delta_x_ / DRAG_OUT_PIXELS;
if (drag_gesture_ongoing_ || hide_machine_.GetQuirk(LauncherHideMachine::MT_DRAG_OUT))
return progress;
else
return progress * drag_out_animation_.GetCurrentValue();
}
/* Min is when you are on the trigger */
float Launcher::GetAutohidePositionMin() const
{
if (options()->auto_hide_animation() == SLIDE_ONLY || options()->auto_hide_animation() == FADE_AND_SLIDE)
return 0.35f;
else
return 0.25f;
}
/* Max is the initial state over the bfb */
float Launcher::GetAutohidePositionMax() const
{
if (options()->auto_hide_animation() == SLIDE_ONLY || options()->auto_hide_animation() == FADE_AND_SLIDE)
return 1.00f;
else
return 0.75f;
}
void Launcher::OnDPIChanged()
{
monitor.changed.emit(monitor());
}
void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo)
{
auto const& anchor = (launcher_position_ == LauncherPosition::LEFT) ? MouseIconIntersection(x, enter_y_) : MouseIconIntersection(enter_x_, y);
int c_icon_size = icon_size_.CP(cv_);
if (anchor)
{
float position =(launcher_position_ == LauncherPosition::LEFT) ? y: x;
for (AbstractLauncherIcon::Ptr const& model_icon : *model_)
{
if (model_icon == anchor)
{
position += c_icon_size / 2;
if (launcher_position_ == LauncherPosition::LEFT)
{
launcher_drag_delta_ = enter_y_ - position;
if (position + c_icon_size / 2 + launcher_drag_delta_ > geo.height)
launcher_drag_delta_ -= (position + c_icon_size / 2 + launcher_drag_delta_) - geo.height;
}
else
{
launcher_drag_delta_ = enter_x_ - position;
if (position + c_icon_size / 2 + launcher_drag_delta_ > geo.width)
launcher_drag_delta_ -= (position + c_icon_size / 2 + launcher_drag_delta_) - geo.width;
}
break;
}
float visibility = model_icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor());
position += (c_icon_size + SPACE_BETWEEN_ICONS.CP(cv_)) * visibility;
}
}
}
float Launcher::IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon) const
{
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()))
return 1.0f; // we are full on in a normal condition
float urgent_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::URGENT, monitor());
return 0.5f + (float)(std::cos(M_PI * (float)(URGENT_BLINKS * 2) * urgent_progress)) * 0.5f;
}
float Launcher::IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon) const
{
float pulse_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::PULSE_ONCE, monitor());
if (pulse_progress == 1.0f)
{
icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, false, monitor());
icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::PULSE_ONCE, monitor());
}
return 0.5f + (float) (std::cos(M_PI * 2.0 * pulse_progress)) * 0.5f;
}
float Launcher::IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon) const
{
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()))
return 0.0f; // we are full on in a normal condition
float urgent_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::URGENT, monitor());
return 0.3f * (float)(std::sin(M_PI * (float)(WIGGLE_CYCLES * 2) * urgent_progress)) * 0.5f;
}
float Launcher::IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon) const
{
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor()))
return 1.0f;
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING, monitor()))
return 1.0f;
float starting_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::STARTING, monitor());
double val = IsBackLightModeToggles() ? 3.0f : 4.0f;
return 1.0f-(0.5f + (float)(std::cos(M_PI * val * starting_progress)) * 0.5f);
}
float Launcher::IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon) const
{
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor()))
return 1.0f;
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING, monitor()))
return 1.0f;
float starting_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::STARTING, monitor());
if (starting_progress == 1.0f)
{
icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false, monitor());
icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::STARTING, monitor());
return starting_progress;
}
return 1.0f-(0.5f + (float)(std::cos(M_PI * (float)(MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
}
float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon) const
{
float result = 0.0f;
float running_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::RUNNING, monitor());
// After we finish the running animation running, we can restore the starting quirk.
if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING, monitor()))
{
icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false, monitor());
icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::STARTING, monitor());
}
float backlight_strength;
if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
backlight_strength = BACKLIGHT_STRENGTH;
else if (IsBackLightModeToggles())
backlight_strength = BACKLIGHT_STRENGTH * running_progress;
else
backlight_strength = 0.0f;
switch (options()->launch_animation())
{
case LAUNCH_ANIMATION_NONE:
result = backlight_strength;
break;
case LAUNCH_ANIMATION_BLINK:
if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
result = IconStartingBlinkValue(icon);
else if (options()->backlight_mode() == BACKLIGHT_ALWAYS_OFF)
result = 1.0f - IconStartingBlinkValue(icon);
else
result = backlight_strength; // The blink concept is a failure in this case (it just doesn't work right)
break;
case LAUNCH_ANIMATION_PULSE:
result = backlight_strength;
if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
result *= CLAMP(running_progress + IconStartingPulseValue(icon), 0.0f, 1.0f);
else if (IsBackLightModeToggles())
result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconStartingPulseValue(icon));
else
result = 1.0f - CLAMP(running_progress + IconStartingPulseValue(icon), 0.0f, 1.0f);
break;
}
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, monitor()))
{
if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON)
result *= CLAMP(running_progress + IconPulseOnceValue(icon), 0.0f, 1.0f);
else if (options()->backlight_mode() == BACKLIGHT_NORMAL)
result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconPulseOnceValue(icon));
else
result = 1.0f - CLAMP(running_progress + IconPulseOnceValue(icon), 0.0f, 1.0f);
}
// urgent serves to bring the total down only
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()) && options()->urgent_animation() == URGENT_ANIMATION_PULSE)
result *= 0.2f + 0.8f * IconUrgentPulseValue(icon);
return result;
}
float Launcher::IconProgressBias(AbstractLauncherIcon::Ptr const& icon) const
{
float result = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::PROGRESS, monitor());
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PROGRESS, monitor()))
return -1.0f + result;
else
return 1.0f - result;
}
bool Launcher::IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const
{
if (options()->backlight_mode() == BACKLIGHT_EDGE_TOGGLE)
return true;
if (options()->backlight_mode() == BACKLIGHT_NORMAL_EDGE_TOGGLE && !icon->WindowVisibleOnMonitor(monitor))
return true;
return false;
}
void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, RenderArg& arg)
{
float stauration = 1.0f - icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::DESAT, monitor());
arg.icon = icon.GetPointer();
arg.alpha = 0.2f + 0.8f * stauration;
arg.saturation = stauration;
arg.colorify = nux::color::White;
arg.running_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor());
arg.running_colored = icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor());
arg.draw_edge_only = IconDrawEdgeOnly(icon);
arg.active_colored = false;
arg.skip = false;
arg.stick_thingy = false;
arg.keyboard_nav_hl = false;
arg.progress_bias = IconProgressBias(icon);
arg.progress = CLAMP(icon->GetProgress(), 0.0f, 1.0f);
arg.draw_shortcut = shortcuts_shown_ && !hide_machine_.GetQuirk(LauncherHideMachine::PLACES_VISIBLE);
arg.system_item = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME ||
icon->GetIconType() == AbstractLauncherIcon::IconType::HUD;
arg.colorify_background = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME ||
icon->GetIconType() == AbstractLauncherIcon::IconType::HUD ||
icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH ||
icon->GetIconType() == AbstractLauncherIcon::IconType::DESKTOP ||
icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE ||
icon->GetIconType() == AbstractLauncherIcon::IconType::EXPO;
// trying to protect against flickering when icon is dragged from dash LP: #863230
if (arg.alpha < 0.2)
{
arg.alpha = 0.2;
arg.saturation = 0.0;
}
arg.active_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, monitor());
/* BFB or HUD icons don't need the active arrow if the overaly is opened
* in another monitor */
if (arg.active_arrow && !IsOverlayOpen() &&
(icon->GetIconType() == AbstractLauncherIcon::IconType::HOME ||
icon->GetIconType() == AbstractLauncherIcon::IconType::HUD))
{
arg.active_arrow = false;
}
if (options()->show_for_all)
arg.running_on_viewport = icon->WindowVisibleOnViewport();
else
arg.running_on_viewport = icon->WindowVisibleOnMonitor(monitor);
guint64 shortcut = icon->GetShortcut();
if (shortcut > 32)
arg.shortcut_label = (char) shortcut;
else
arg.shortcut_label = 0;
// we dont need to show strays
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor()))
{
arg.window_indicators = 0;
}
else
{
if (options()->show_for_all)
arg.window_indicators = std::max(icon->WindowsVisibleOnViewport(), 1);
else
arg.window_indicators = std::max(icon->WindowsVisibleOnMonitor(monitor), 1);
}
arg.backlight_intensity = IconBackgroundIntensity(icon);
arg.shimmer_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::SHIMMER, monitor());
float urgent_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::URGENT, monitor());
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()))
urgent_progress = CLAMP(urgent_progress * 3.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
else
urgent_progress = CLAMP(urgent_progress * 3.0f - 2.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
arg.glow_intensity = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::GLOW, monitor()) + urgent_progress;
if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
{
arg.rotation.z = IconUrgentWiggleValue(icon);
}
if (IsInKeyNavMode())
{
if (icon == model_->Selection())
arg.keyboard_nav_hl = true;
}
}
void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon,
RenderArg& arg,
nux::Point3& center,
nux::Geometry const& parent_abs_geo,
float folding_threshold,
float folded_size,
float folded_spacing,
float autohide_offset,
float folded_z_distance,
float animation_neg_rads)
{
SetupRenderArg(icon, arg);
// reset z
center.z = 0;
float size_modifier = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor());
if (size_modifier < 1.0f)
{
arg.alpha *= size_modifier;
center.z = 300.0f * (1.0f - size_modifier);
}
const float icon_dim = 0.0f; // icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::DROP_DIM, monitor());
float drop_dim_value = 0.2f + 0.8f * (1.0f - icon_dim);
if (drop_dim_value < 1.0f)
arg.alpha *= drop_dim_value;
// trying to protect against flickering when icon is dragged from dash LP: #863230
if (arg.alpha < 0.2)
{
arg.alpha = 0.2;
arg.saturation = 0.0;
}
if (icon == drag_icon_)
{
bool mouse_beyond_drag_threshold = MouseBeyondDragThreshold();
if (mouse_beyond_drag_threshold)
arg.stick_thingy = true;
if (GetActionState() == ACTION_DRAG_ICON ||
(drag_window_ && drag_window_->Animating()) ||
icon->GetIconType() == AbstractLauncherIcon::IconType::SPACER)
{
arg.skip = true;
}
if (drag_icon_animation_.CurrentState() == na::Animation::State::Running)
size_modifier *= drag_icon_animation_.GetCurrentValue();
else if (mouse_beyond_drag_threshold)
size_modifier = 0.0f;
}
if (size_modifier <= 0.0f)
arg.skip = true;
int c_icon_size = icon_size_.CP(cv_);
auto moving_center = (launcher_position_ == LauncherPosition::LEFT) ? center.y : center.x;
// goes for 0.0f when fully unfolded, to 1.0f folded
float folding_progress = CLAMP((moving_center + c_icon_size - folding_threshold) / (float) c_icon_size, 0.0f, 1.0f);
float unfold_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::UNFOLDED, monitor());
float active_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::ACTIVE, monitor());
unfold_progress = CLAMP(unfold_progress + active_progress, 0.0f, 1.0f);
folding_progress *= 1.0f - unfold_progress;
float half_size = (folded_size / 2.0f) + (c_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
float icon_hide_offset = autohide_offset;
float present_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::PRESENTED, monitor());
icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency());
if (present_progress > 0.0f)
{
parent_->ShowWindow(true);
}
// icon is crossing threshold, start folding
center.z += folded_z_distance * folding_progress;
if (launcher_position_ == LauncherPosition::LEFT)
arg.rotation.x = animation_neg_rads * folding_progress;
else
arg.rotation.y = animation_neg_rads * folding_progress;
float spacing_overlap = CLAMP((float)(moving_center + (2.0f * half_size * size_modifier) + (SPACE_BETWEEN_ICONS.CP(cv_) * size_modifier) - folding_threshold) / (float) c_icon_size, 0.0f, 1.0f);
float spacing = (SPACE_BETWEEN_ICONS.CP(cv_) * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
nux::Point3 centerOffset;
float center_transit_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::CENTER_SAVED, monitor());
if (center_transit_progress <= 1.0f)
{
if (launcher_position_ == LauncherPosition::LEFT)
{
int saved_center = icon->GetSavedCenter(monitor).y - parent_abs_geo.y;
centerOffset.y = (saved_center - (center.y + (half_size * size_modifier))) * (1.0f - center_transit_progress);
}
else
{
int saved_center = icon->GetSavedCenter(monitor).x - parent_abs_geo.x;
centerOffset.x = (saved_center - (center.x + (half_size * size_modifier))) * (1.0f - center_transit_progress);
}
}
if (launcher_position_ == LauncherPosition::LEFT)
{
center.y += half_size * size_modifier; // move to center
arg.render_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y + centerOffset.y), roundf(center.z));
arg.logical_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y), roundf(center.z));
}
else
{
center.x += half_size * size_modifier;
arg.render_center = nux::Point3(roundf(center.x + centerOffset.x), roundf(center.y + icon_hide_offset), roundf(center.z));
arg.logical_center = nux::Point3(roundf(center.x), roundf(center.y + icon_hide_offset), roundf(center.z));
}
nux::Point3 icon_center(parent_abs_geo.x + roundf(center.x), parent_abs_geo.y + roundf(center.y), roundf(center.z));
icon->SetCenter(icon_center, monitor);
// FIXME: this is a hack, to avoid that we set the target to the end of the icon
if (!initial_drag_animation_ && icon == drag_icon_ && drag_window_ && drag_window_->Animating())
{
drag_window_->SetAnimationTarget(icon_center.x, icon_center.y);
}
if (launcher_position_ == LauncherPosition::LEFT)
center.y += (half_size * size_modifier) + spacing; // move to end
else
center.x += (half_size * size_modifier) + spacing;
}
float Launcher::DragLimiter(float x)
{
float result = (1 - std::pow(159.0 / 160, std::abs(x))) * 160;
if (x >= 0.0f)
return result;
return -result;
}
nux::Color FullySaturateColor(nux::Color color)
{
float max = std::max({color.red, color.green, color.blue});
if (max > 0.0f)
color = color * (1.0f / max);
return color;
}
void Launcher::RenderArgs(std::list &launcher_args,
nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo, bool& force_show_window)
{
nux::Geometry const& geo = GetGeometry();
LauncherModel::iterator it;
nux::Point3 center;
nux::Color const& colorify = FullySaturateColor(options()->background_color);
float hover_progress = folded_ ? hover_animation_.GetCurrentValue() : 1.0f;
float folded_z_distance = FOLDED_Z_DISTANCE * (1.0f - hover_progress);
float animation_neg_rads = NEG_FOLDED_ANGLE * (1.0f - hover_progress);
float folding_constant = 0.25f;
float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress);
int c_icon_size = icon_size_.CP(cv_);
float folded_size = c_icon_size * folding_not_constant;
float folded_spacing = SPACE_BETWEEN_ICONS.CP(cv_) * folding_not_constant;
if (launcher_position_ == LauncherPosition::LEFT)
{
center.x = geo.width / 2;
center.y = SPACE_BETWEEN_ICONS.CP(cv_);
}
else
{
center.x = SPACE_BETWEEN_ICONS.CP(cv_);
center.y = geo.height / 2;
}
center.z = 0;
int launcher_size = (launcher_position_ == LauncherPosition::LEFT) ? geo.height : geo.width;
folded_ = true;
// compute required height/width of launcher AND folding threshold
float sum = (launcher_position_ == LauncherPosition::LEFT) ? (0.0f + center.y) : (0.0f + center.x);
float folding_threshold = launcher_size - c_icon_size / 2.5f;
for (it = model_->begin(); it != model_->end(); ++it)
{
float visibility = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor());
float size = (c_icon_size + SPACE_BETWEEN_ICONS.CP(cv_)) * visibility;
sum += size;
// magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";
const float magic_constant = 1.3f;
float unfold_progress = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::UNFOLDED, monitor());
float active_progress = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::ACTIVE, monitor());
unfold_progress = CLAMP(unfold_progress + active_progress, 0.0f, 1.0f);
folding_threshold -= CLAMP(sum - launcher_size, 0.0f, size * magic_constant) * (folding_constant + (1.0f - folding_constant) * unfold_progress);
}
if (sum - SPACE_BETWEEN_ICONS.CP(cv_) <= launcher_size)
{
folding_threshold = launcher_size;
folded_ = false;
}
float autohide_offset = 0.0f;
*launcher_alpha = 1.0f;
if (options()->hide_mode != LAUNCHER_HIDE_NEVER || hide_machine_.GetQuirk(LauncherHideMachine::LOCK_HIDE))
{
float autohide_progress = auto_hide_animation_.GetCurrentValue() * (1.0f - DragOutProgress());
if (dash_is_open_)
{
*launcher_alpha = dash_showing_animation_.GetCurrentValue();
}
else if (options()->auto_hide_animation() == FADE_ONLY)
{
*launcher_alpha = 1.0f - autohide_progress;
}
else
{
if (autohide_progress > 0.0f)
{
if (launcher_position_ == LauncherPosition::LEFT)
autohide_offset -= geo.width * autohide_progress;
else
autohide_offset += geo.height * autohide_progress;
if (options()->auto_hide_animation() == FADE_AND_SLIDE)
*launcher_alpha = 1.0f - 0.5f * autohide_progress;
}
}
}
if (options()->hide_mode != LAUNCHER_HIDE_NEVER)
{
float drag_hide_progress = dnd_hide_animation_.GetCurrentValue();
if (launcher_position_ == LauncherPosition::LEFT)
autohide_offset -= geo.width * 0.25f * drag_hide_progress;
else
autohide_offset += geo.height * 0.25f * drag_hide_progress;
hide_machine_.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, (drag_hide_progress >= 1.0f));
}
// Inform the painter where to paint the box
box_geo = geo;
if (options()->hide_mode != LAUNCHER_HIDE_NEVER || hide_machine_.GetQuirk(LauncherHideMachine::LOCK_HIDE))
{
if (launcher_position_ == LauncherPosition::LEFT)
box_geo.x += autohide_offset;
else
box_geo.y += autohide_offset;
}
/* Why we need last_geo? It stores the last box_geo (note: as it is a static variable,
* it is initialized only first time). Infact we call SetDndDelta that calls MouseIconIntersection
* that uses values (HitArea) that are computed in UpdateIconXForm.
* The problem is that in DrawContent we calls first RenderArgs, then UpdateIconXForm. Just
* use last_geo to hack this problem.
*/
static nux::Geometry last_geo = box_geo;
// this happens on hover, basically its a flag and a value in one, we translate this into a dnd offset
if (launcher_position_ == LauncherPosition::LEFT)
{
if (enter_y_ != 0 && enter_y_ + c_icon_size / 2 > folding_threshold)
SetDndDelta(last_geo.x + last_geo.width / 2, center.y, geo);
}
else
{
if (enter_x_ != 0 && enter_x_ + c_icon_size / 2 > folding_threshold)
SetDndDelta(center.x, last_geo.y + last_geo.height / 2, geo);
}
// Update the last_geo value.
last_geo = box_geo;
enter_y_ = 0;
enter_x_ = 0;
// logically dnd exit only restores to the clamped ranges
// hover_progress restores to 0
launcher_drag_delta_max_ = 0.0f;
launcher_drag_delta_min_ = MIN(0.0f, launcher_size - sum);
if (hover_progress > 0.0f && launcher_drag_delta_ != 0)
{
float delta = launcher_drag_delta_;
if (launcher_drag_delta_ > launcher_drag_delta_max_)
delta = launcher_drag_delta_max_ + DragLimiter(delta - launcher_drag_delta_max_);
else if (launcher_drag_delta_ < launcher_drag_delta_min_)
delta = launcher_drag_delta_min_ + DragLimiter(delta - launcher_drag_delta_min_);
if (GetActionState() != ACTION_DRAG_LAUNCHER)
{
// XXX: nux::Animation should allow to define new kinds of easing curves
float dnd_progress = std::pow(drag_over_animation_.GetCurrentValue(), 2);
if (launcher_drag_delta_ > launcher_drag_delta_max_)
delta = launcher_drag_delta_max_ + (delta - launcher_drag_delta_max_) * dnd_progress;
else if (launcher_drag_delta_ < launcher_drag_delta_min_)
delta = launcher_drag_delta_min_ + (delta - launcher_drag_delta_min_) * dnd_progress;
if (dnd_progress == 0.0f)
launcher_drag_delta_ = (int) delta;
}
delta *= hover_progress;
folding_threshold += delta;
if (launcher_position_ == LauncherPosition::LEFT)
center.y += delta;
else
center.x += delta;
}
else
{
launcher_drag_delta_ = 0;
}
// The functional position we wish to represent for these icons is not smooth. Rather than introducing
// special casing to represent this, we use MIN/MAX functions. This helps ensure that even though our
// function is not smooth it is continuous, which is more important for our visual representation (icons
// wont start jumping around). As a general rule ANY if () statements that modify center.y should be seen
// as bugs.
for (it = model_->main_begin(); it != model_->main_end(); ++it)
{
RenderArg arg;
AbstractLauncherIcon::Ptr const& icon = *it;
if (options()->hide_mode == LAUNCHER_HIDE_AUTOHIDE)
HandleUrgentIcon(icon);
FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing,
autohide_offset, folded_z_distance, animation_neg_rads);
arg.colorify = colorify;
launcher_args.push_back(arg);
}
// compute maximum height of shelf
float shelf_sum = 0.0f;
for (it = model_->shelf_begin(); it != model_->shelf_end(); ++it)
{
float visibility = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor());
float size = (c_icon_size + SPACE_BETWEEN_ICONS.CP(cv_)) * visibility;
shelf_sum += size;
}
// add bottom padding
if (shelf_sum > 0.0f)
shelf_sum += SPACE_BETWEEN_ICONS.CP(cv_);
float shelf_delta = 0;
if (launcher_position_ == LauncherPosition::LEFT)
{
shelf_delta = MAX(((launcher_size - shelf_sum) + SPACE_BETWEEN_ICONS.CP(cv_)) - center.y, 0.0f);
center.y += shelf_delta;
}
else
{
shelf_delta = MAX(((launcher_size - shelf_sum) + SPACE_BETWEEN_ICONS.CP(cv_)) - center.x, 0.0f);
center.x += shelf_delta;
}
folding_threshold += shelf_delta;
force_show_window = false;
for (it = model_->shelf_begin(); it != model_->shelf_end(); ++it)
{
RenderArg arg;
AbstractLauncherIcon::Ptr const& icon = *it;
FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing,
autohide_offset, folded_z_distance, animation_neg_rads);
arg.colorify = colorify;
launcher_args.push_back(arg);
if (autohide_offset != 0)
force_show_window = true;
}
}
/* End Render Layout Logic */
void Launcher::ForceReveal(bool force_reveal)
{
hide_machine_.SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, force_reveal);
}
void Launcher::ShowShortcuts(bool show)
{
shortcuts_shown_ = show;
hide_machine_.SetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE, show);
QueueDraw();
}
void Launcher::OnLockHideChanged(GVariant *data)
{
hide_machine_.SetQuirk(LauncherHideMachine::LOCK_HIDE, glib::Variant(data).GetBool());
}
void Launcher::DesaturateIcons()
{
auto& wm = WindowManager::Default();
bool spread_mode = wm.IsScaleActive() || wm.IsExpoActive();
bool inactive_only = spread_mode && wm.IsScaleActiveForGroup();
for (auto const& icon : *model_)
{
bool desaturate = false;
if (!spread_mode)
{
auto type = icon->GetIconType();
if (type != AbstractLauncherIcon::IconType::HOME && type != AbstractLauncherIcon::IconType::HUD)
desaturate = true;
}
else if (!inactive_only || !icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, monitor()))
{
desaturate = true;
}
icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, desaturate, monitor());
}
}
void Launcher::SaturateIcons()
{
for (auto const& icon : *model_)
{
icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false, monitor());
}
}
void Launcher::OnOverlayShown(GVariant* data)
{
// check the type of overlay
unity::glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
int width, height;
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
&overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
std::string identity(overlay_identity.Str());
LOG_DEBUG(logger) << "Overlay shown: " << identity
<< ", " << (can_maximise ? "can maximise" : "can't maximise")
<< ", on monitor " << overlay_monitor
<< " (for monitor " << monitor() << ")";
if (overlay_monitor == monitor())
{
if (identity == "dash")
{
dash_is_open_ = true;
hide_machine_.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, true);
hover_machine_.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, true);
if (options()->hide_mode != LAUNCHER_HIDE_NEVER)
animation::StartOrReverse(dash_showing_animation_, animation::Direction::FORWARD);
}
if (identity == "hud")
{
hud_is_open_ = true;
}
bg_effect_helper_.enabled = true;
// Don't desaturate icons if the mouse is over the launcher:
if (!hovered_)
{
LOG_DEBUG(logger) << "Desaturate on monitor " << monitor();
DesaturateIcons();
}
if (icon_under_mouse_)
icon_under_mouse_->HideTooltip();
}
}
void Launcher::OnOverlayHidden(GVariant* data)
{
// check the type of overlay
unity::glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
int width, height;
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
&overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
std::string identity = overlay_identity.Str();
LOG_DEBUG(logger) << "Overlay hidden: " << identity
<< ", " << (can_maximise ? "can maximise" : "can't maximise")
<< ", on monitor " << overlay_monitor
<< " (for monitor" << monitor() << ")";
if (overlay_monitor == monitor())
{
if (identity == "dash")
{
dash_is_open_ = false;
hide_machine_.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, false);
hover_machine_.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, false);
dash_showing_animation_.Stop();
}
else if (identity == "hud")
{
hud_is_open_ = false;
}
// If they are both now shut, then disable the effect helper and saturate the icons.
if (!IsOverlayOpen())
{
bg_effect_helper_.enabled = false;
LOG_DEBUG(logger) << "Saturate on monitor " << monitor();
SaturateIcons();
}
else if (WindowManager::Default().IsExpoActive())
{
// XXX: This is a workaround, we need to disable blur effect on expo to avoid
// a wrong blurred background. Expo should damage the Launcher.
bg_effect_helper_.enabled = false;
}
}
// as the leave event is no more received when the place is opened
// FIXME: remove when we change the mouse grab strategy in nux
nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
SetStateMouseOverLauncher(GetAbsoluteGeometry().IsInside(pt));
}
bool Launcher::IsOverlayOpen() const
{
auto& wm = WindowManager::Default();
return dash_is_open_ || hud_is_open_ || wm.IsScaleActive() || wm.IsExpoActive();
}
void Launcher::ClearTooltip()
{
if (icon_under_mouse_)
icon_under_mouse_->HideTooltip();
}
void Launcher::SetHidden(bool hide_launcher)
{
if (hide_launcher == hidden_)
return;
hidden_ = hide_launcher;
hide_machine_.SetQuirk(LauncherHideMachine::LAUNCHER_HIDDEN, hide_launcher);
hover_machine_.SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hide_launcher);
if (hide_launcher)
{
hide_machine_.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false);
hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false);
SetStateMouseOverLauncher(false);
}
animation::StartOrReverseIf(auto_hide_animation_, hide_launcher);
postreveal_mousemove_delta_x_ = 0;
postreveal_mousemove_delta_y_ = 0;
if (!hide_launcher)
parent_->ShowWindow(true);
if (nux::GetWindowThread()->IsEmbeddedWindow())
parent_->EnableInputWindow(!hide_launcher, launcher::window_title, false, false);
if (!hide_launcher && GetActionState() == ACTION_DRAG_EXTERNAL)
DndReset();
hidden_changed.emit();
}
void Launcher::UpdateChangeInMousePosition(int delta_x, int delta_y)
{
postreveal_mousemove_delta_x_ += delta_x;
postreveal_mousemove_delta_y_ += delta_y;
// check the state before changing it to avoid uneeded hide calls
if (!hide_machine_.GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) &&
(std::abs(postreveal_mousemove_delta_x_) > MOUSE_DEADZONE ||
std::abs(postreveal_mousemove_delta_y_) > MOUSE_DEADZONE))
{
hide_machine_.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true);
}
}
int Launcher::GetMouseX() const
{
return mouse_position_.x;
}
int Launcher::GetMouseY() const
{
return mouse_position_.y;
}
void Launcher::OnExpoChanged()
{
WindowManager& wm = WindowManager::Default();
bool expo_active = wm.IsExpoActive();
hide_machine_.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, expo_active);
// XXX: We must make sure that we regenerate the blur when expo is fully active
// bg_effect_helper_.enabled = expo_active;
if (expo_active)
{
if (!hovered_)
DesaturateIcons();
if (icon_under_mouse_)
icon_under_mouse_->HideTooltip();
}
else if (!IsOverlayOpen())
{
SaturateIcons();
}
}
void Launcher::OnSpreadChanged()
{
WindowManager& wm = WindowManager::Default();
bool active = wm.IsScaleActive();
hide_machine_.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, active);
bg_effect_helper_.enabled = active;
if (hide_machine_.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
return;
if (active && icon_under_mouse_)
icon_under_mouse_->HideTooltip();
if (active && (!hovered_ || wm.IsScaleActiveForGroup()))
{
// The icons can take some ms to update their active state, this can protect us.
sources_.AddIdle([this] { DesaturateIcons(); return false; }, SCALE_DESATURATE_IDLE);
}
else
{
sources_.Remove(SCALE_DESATURATE_IDLE);
if (!IsOverlayOpen())
SaturateIcons();
}
}
LauncherHideMode Launcher::GetHideMode() const
{
return options()->hide_mode;
}
/* End Launcher Show/Hide logic */
void Launcher::OnOptionsChanged(Options::Ptr options)
{
UpdateOptions(options);
options->option_changed.connect(sigc::mem_fun(this, &Launcher::OnOptionChanged));
}
void Launcher::OnOptionChanged()
{
UpdateOptions(options());
}
void Launcher::OnMonitorChanged(int new_monitor)
{
UScreen* uscreen = UScreen::GetDefault();
auto monitor_geo = uscreen->GetMonitorGeometry(new_monitor);
unity::panel::Style &panel_style = panel::Style::Instance();
int panel_height = panel_style.PanelHeight(new_monitor);
RawPixel launcher_height = icon_size_ + ICON_PADDING * 2 + SIDE_LINE_WIDTH - 2;
cv_ = unity::Settings::Instance().em(monitor);
launcher_height = launcher_height.CP(cv_) - (1_em).CP(cv_);
if (launcher_position_ == LauncherPosition::LEFT)
Resize(nux::Point(monitor_geo.x, monitor_geo.y + panel_height), monitor_geo.height - panel_height);
else
Resize(nux::Point(monitor_geo.x, monitor_geo.y + monitor_geo.height - launcher_height), monitor_geo.width);
icon_renderer_->monitor = new_monitor;
icon_renderer_->scale = cv_->DPIScale();
SetIconSize(options()->tile_size, options()->icon_size);
}
void Launcher::UpdateOptions(Options::Ptr options)
{
SetIconSize(options->tile_size, options->icon_size);
SetHideMode(options->hide_mode);
SetScrollInactiveIcons(options->scroll_inactive_icons);
SetLauncherMinimizeWindow(options->minimize_window_on_click);
OnMonitorChanged(monitor);
if (model_)
{
for (auto const& icon : *model_)
SetupIconAnimations(icon);
}
ConfigureBarrier();
QueueDraw();
}
void Launcher::ConfigureBarrier()
{
float decay_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .3f) + 1;
float reveal_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .025f) + 1;
hide_machine_.reveal_pressure = options()->edge_reveal_pressure() * reveal_responsiveness_mult;
hide_machine_.edge_decay_rate = options()->edge_decay_rate() * decay_responsiveness_mult;
}
void Launcher::SetHideMode(LauncherHideMode hidemode)
{
bool fixed_launcher = (hidemode == LAUNCHER_HIDE_NEVER);
parent_->InputWindowEnableStruts(fixed_launcher);
hide_machine_.SetMode(static_cast(hidemode));
}
BacklightMode Launcher::GetBacklightMode() const
{
return options()->backlight_mode();
}
bool Launcher::IsBackLightModeToggles() const
{
switch (options()->backlight_mode()) {
case BACKLIGHT_NORMAL:
case BACKLIGHT_EDGE_TOGGLE:
case BACKLIGHT_NORMAL_EDGE_TOGGLE:
return true;
default:
return false;
}
}
nux::ObjectPtr const& Launcher::GetActiveTooltip() const
{
return active_tooltip_;
}
nux::ObjectPtr const& Launcher::GetDraggedIcon() const
{
return drag_window_;
}
void Launcher::SetActionState(LauncherActionState actionstate)
{
if (launcher_action_state_ == actionstate)
return;
launcher_action_state_ = actionstate;
hover_machine_.SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE));
}
Launcher::LauncherActionState
Launcher::GetActionState() const
{
return launcher_action_state_;
}
void Launcher::SetHover(bool hovered)
{
if (hovered == hovered_)
return;
hovered_ = hovered;
if (!IsInKeyNavMode() && hovered_)
{
enter_y_ = mouse_position_.y;
enter_x_ = mouse_position_.x;
}
if (folded_)
animation::StartOrReverseIf(hover_animation_, hovered_);
if (IsOverlayOpen() && !hide_machine_.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
{
if (hovered && !hide_machine_.GetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE))
SaturateIcons();
else
DesaturateIcons();
}
}
bool Launcher::MouseOverTopScrollArea()
{
if (launcher_position_ == LauncherPosition::LEFT)
return mouse_position_.y < SCROLL_AREA_HEIGHT.CP(cv_);
else
return mouse_position_.x < SCROLL_AREA_HEIGHT.CP(cv_);
}
bool Launcher::MouseOverBottomScrollArea()
{
if (launcher_position_ == LauncherPosition::LEFT)
return mouse_position_.y >= GetGeometry().height - SCROLL_AREA_HEIGHT.CP(cv_);
else
return mouse_position_.x >= GetGeometry().width - SCROLL_AREA_HEIGHT.CP(cv_);
}
bool Launcher::OnScrollTimeout()
{
bool continue_animation = true;
if (IsInKeyNavMode() || !hovered_ || GetActionState() == ACTION_DRAG_LAUNCHER)
{
continue_animation = false;
}
else if (MouseOverTopScrollArea())
{
if (launcher_drag_delta_ >= launcher_drag_delta_max_)
{
continue_animation = false;
}
else
{
int mouse_distance = 0;
if (launcher_position_ == LauncherPosition::LEFT)
mouse_distance = (SCROLL_AREA_HEIGHT.CP(cv_) - mouse_position_.y);
else
mouse_distance = (SCROLL_AREA_HEIGHT.CP(cv_) - mouse_position_.x);
int speed = static_cast(mouse_distance) / SCROLL_AREA_HEIGHT.CP(cv_) * SCROLL_FPS;
launcher_drag_delta_ += speed;
}
}
else if (MouseOverBottomScrollArea())
{
if (launcher_drag_delta_ <= launcher_drag_delta_min_)
{
continue_animation = false;
}
else
{
int mouse_distance = 0;
if (launcher_position_ == LauncherPosition::LEFT)
mouse_distance = (mouse_position_.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT.CP(cv_));
else
mouse_distance = (mouse_position_.x + 1) - (GetGeometry().width - SCROLL_AREA_HEIGHT.CP(cv_));
int speed = static_cast(mouse_distance) / SCROLL_AREA_HEIGHT.CP(cv_) * SCROLL_FPS;
launcher_drag_delta_ -= speed;
}
}
else
{
continue_animation = false;
}
if (continue_animation)
{
QueueDraw();
}
return continue_animation;
}
void Launcher::EnsureScrollTimer()
{
bool needed = MouseOverTopScrollArea() || MouseOverBottomScrollArea();
if (needed && !sources_.GetSource(SCROLL_TIMEOUT))
{
sources_.AddTimeout(20, sigc::mem_fun(this, &Launcher::OnScrollTimeout), SCROLL_TIMEOUT);
}
else if (!needed)
{
sources_.Remove(SCROLL_TIMEOUT);
}
}
void Launcher::SetUrgentTimer(int urgent_animate_period)
{
sources_.AddTimeoutSeconds(urgent_animate_period, sigc::mem_fun(this, &Launcher::OnUrgentTimeout), URGENT_TIMEOUT);
}
void Launcher::AnimateUrgentIcon(AbstractLauncherIcon::Ptr const& icon)
{
icon->SetQuirk(AbstractLauncherIcon::Quirk::URGENT, false, monitor());
icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::URGENT, monitor());
icon->SetQuirk(AbstractLauncherIcon::Quirk::URGENT, true, monitor());
}
void Launcher::HandleUrgentIcon(AbstractLauncherIcon::Ptr const& icon)
{
if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()))
{
if (animating_urgent_icons_.erase(icon) > 0)
{
if (animating_urgent_icons_.empty())
{
sources_.Remove(URGENT_TIMEOUT);
sources_.Remove(LAST_ANIMATION_URGENT_IDLE);
}
}
return;
}
bool animating = (animating_urgent_icons_.find(icon) != animating_urgent_icons_.end());
if (hidden_ && !animating)
{
bool urgent_timer_running = sources_.GetSource(URGENT_TIMEOUT) != nullptr;
// If the Launcher is hidden, then add a timer to wiggle the urgent icons at
// certain intervals (1m, 2m, 4m, 8m, 16m, & 32m).
if (!urgent_timer_running)
{
urgent_animation_period_ = 0;
urgent_ack_needed_ = true;
SetUrgentTimer(BASE_URGENT_ANIMATION_PERIOD);
}
// If the Launcher is hidden, the timer is running, an urgent icon is newer than the last time
// icons were wiggled, and the timer did not just start, then reset the timer since a new
// urgent icon just showed up.
else if (urgent_timer_running && urgent_animation_period_ != 0)
{
urgent_animation_period_ = 0;
SetUrgentTimer(BASE_URGENT_ANIMATION_PERIOD);
}
animating_urgent_icons_.insert(icon);
}
// If the Launcher is no longer hidden, then after the Launcher is fully revealed, wiggle the
// urgent icon and then stop the timer (if it's running).
else if (!hidden_ && urgent_ack_needed_)
{
sources_.AddIdle([this] {
if (hidden_ || hide_machine_.reveal_progress == 1.0f)
return false;
if (hide_machine_.reveal_progress > 0)
return true;
for (auto const& icon : animating_urgent_icons_)
AnimateUrgentIcon(icon);
sources_.Remove(URGENT_TIMEOUT);
urgent_ack_needed_ = false;
return false;
}, LAST_ANIMATION_URGENT_IDLE);
}
}
bool Launcher::OnUrgentTimeout()
{
bool foundUrgent = false;
if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE && hidden_)
{
// Look for any icons that are still urgent and wiggle them
for (auto icon : *model_)
{
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()))
{
AnimateUrgentIcon(icon);
foundUrgent = true;
}
}
}
// Update the time for when the next wiggle will occur.
if (urgent_animation_period_ == 0)
{
urgent_animation_period_ = BASE_URGENT_ANIMATION_PERIOD;
}
else
{
urgent_animation_period_ = urgent_animation_period_ * DOUBLE_TIME;
}
// If no urgent icons were found or we have reached the time threshold,
// then let's stop the timer. Otherwise, start a new timer with the
// updated wiggle time.
if (!foundUrgent || (urgent_animation_period_ > MAX_URGENT_ANIMATION_DELTA))
{
return false;
}
SetUrgentTimer(urgent_animation_period_);
return false;
}
void Launcher::SetScrollInactiveIcons(bool scroll)
{
AbstractLauncherIcon::scroll_inactive_icons = scroll;
}
void Launcher::SetLauncherMinimizeWindow(bool click_to_minimize)
{
AbstractLauncherIcon::minimize_window_on_click = click_to_minimize;
}
void Launcher::SetIconSize(int tile_size, int icon_size)
{
icon_size_ = tile_size;
icon_renderer_->SetTargetSize(icon_size_.CP(cv_), RawPixel(icon_size).CP(cv_), SPACE_BETWEEN_ICONS.CP(cv_));
AbstractLauncherIcon::icon_size = icon_size_;
nux::Geometry const& parent_geo = parent_->GetGeometry();
if (launcher_position_ == LauncherPosition::LEFT)
Resize(nux::Point(parent_geo.x, parent_geo.y), parent_geo.height);
else
Resize(nux::Point(parent_geo.x, parent_geo.y), parent_geo.width);
}
int Launcher::GetIconSize() const
{
return icon_size_.CP(cv_);
}
void Launcher::Resize(nux::Point const& offset, int size)
{
RawPixel width = 0, height = 0;
if (launcher_position_ == LauncherPosition::LEFT)
{
width = icon_size_ + ICON_PADDING * 2 + SIDE_LINE_WIDTH - 2;
width = width.CP(cv_);
height = size;
SetMaximumHeight(height);
}
else
{
height = icon_size_ + ICON_PADDING * 2 + SIDE_LINE_WIDTH - 2;
height = height.CP(cv_);
width = size;
SetMaximumWidth(width);
}
SetGeometry(nux::Geometry(0, 0, width, height));
parent_->SetGeometry(nux::Geometry(offset.x, offset.y, width, height));
ConfigureBarrier();
}
void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon, int icon_monitor)
{
if (icon_monitor < 0 || icon_monitor == monitor())
QueueDraw();
}
void Launcher::OnIconAdded(AbstractLauncherIcon::Ptr const& icon)
{
SetupIconAnimations(icon);
icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
icon->tooltip_visible.connect(sigc::mem_fun(this, &Launcher::OnTooltipVisible));
if (IsOverlayOpen() && !hovered_)
{
icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true, monitor());
icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::DESAT, monitor());
}
if (icon->IsVisibleOnMonitor(monitor()))
QueueDraw();
}
void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr const& icon)
{
SetIconUnderMouse(AbstractLauncherIcon::Ptr());
if (icon == icon_mouse_down_)
icon_mouse_down_ = nullptr;
if (icon == drag_icon_)
drag_icon_ = nullptr;
animating_urgent_icons_.erase(icon);
if (icon->IsVisibleOnMonitor(monitor()))
QueueDraw();
}
void Launcher::SetupIconAnimations(AbstractLauncherIcon::Ptr const& icon)
{
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::VISIBLE, ANIM_DURATION_SHORT, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::RUNNING, ANIM_DURATION_SHORT, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::ACTIVE, ANIM_DURATION_SHORT, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::STARTING, (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PULSE_ONCE, (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PRESENTED, ANIM_DURATION, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::UNFOLDED, ANIM_DURATION, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::SHIMMER, ANIM_DURATION_LONG, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::CENTER_SAVED, ANIM_DURATION, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PROGRESS, ANIM_DURATION, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::DESAT, ANIM_DURATION_SHORT_SHORT, monitor());
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::GLOW, ANIM_DURATION_SHORT, monitor());
if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::URGENT, (ANIM_DURATION_SHORT * WIGGLE_CYCLES), monitor());
else
icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::URGENT, (ANIM_DURATION_LONG * URGENT_BLINKS * 2), monitor());
}
void Launcher::SetModel(LauncherModel::Ptr model)
{
model_ = model;
auto const& queue_draw_cb = sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw);
for (auto const& icon : *model_)
{
SetupIconAnimations(icon);
icon->needs_redraw.connect(queue_draw_cb);
}
model_->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded));
model_->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved));
model_->order_changed.connect(sigc::mem_fun(this, &Launcher::QueueDraw));
model_->selection_changed.connect(sigc::mem_fun(this, &Launcher::OnSelectionChanged));
}
LauncherModel::Ptr Launcher::GetModel() const
{
return model_;
}
void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& selection)
{
nux::Geometry const& geo = GetGeometry();
int c_icon_size = icon_size_.CP(cv_);
int natural_y = 0;
for (auto icon : *model_)
{
if (!icon->IsVisibleOnMonitor(monitor))
continue;
if (icon == selection)
break;
natural_y += c_icon_size + SPACE_BETWEEN_ICONS.CP(cv_);
}
int max_drag_delta = geo.height - (natural_y + c_icon_size + (2 * SPACE_BETWEEN_ICONS.CP(cv_)));
int min_drag_delta = -natural_y;
launcher_drag_delta_ = std::max(min_drag_delta, std::min(max_drag_delta, launcher_drag_delta_));
}
void Launcher::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection)
{
if (IsInKeyNavMode())
{
EnsureIconOnScreen(selection);
QueueDraw();
}
}
void Launcher::OnTooltipVisible(nux::ObjectPtr view)
{
active_tooltip_ = view;
}
void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
{
}
void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
{
nux::Geometry const& base = GetGeometry();
nux::Geometry bkg_box;
std::list args;
std::list::reverse_iterator rev_it;
float launcher_alpha = 1.0f;
nux::ROPConfig ROP;
ROP.Blend = false;
ROP.SrcBlend = GL_ONE;
ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
bool force_show_window;
nux::Geometry const& geo_absolute = GetAbsoluteGeometry();
RenderArgs(args, bkg_box, &launcher_alpha, geo_absolute, force_show_window);
if (launcher_position_ == LauncherPosition::LEFT)
bkg_box.width -= SIDE_LINE_WIDTH.CP(cv_);
else
bkg_box.height -= SIDE_LINE_WIDTH.CP(cv_);
if (options()->hide_mode != LAUNCHER_HIDE_NEVER &&
bkg_box.x + bkg_box.width <= 0 &&
hide_machine_.reveal_progress <= 0 &&
!force_show_window)
{
parent_->ShowWindow(false);
}
nux::Color clear_colour = nux::Color(0x00000000);
// clear region
GfxContext.PushClippingRectangle(base);
gPainter.PushDrawColorLayer(GfxContext, base, clear_colour, true, ROP);
if (Settings::Instance().GetLowGfxMode() == false)
{
GfxContext.GetRenderStates().SetBlend(true);
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
}
int push_count = 1;
if (launcher_position_ == LauncherPosition::LEFT)
GfxContext.PushClippingRectangle(nux::Geometry(base.x, bkg_box.y, base.width, bkg_box.height));
else
GfxContext.PushClippingRectangle(nux::Geometry(bkg_box.x, base.y, bkg_box.width, base.height));
float reveal_progress = hide_machine_.reveal_progress;
if ((reveal_progress > 0 || last_reveal_progress_ > 0) && launcher_pressure_effect_.IsValid())
{
if (std::abs(last_reveal_progress_ - reveal_progress) <= .1f)
{
last_reveal_progress_ = reveal_progress;
}
else
{
if (last_reveal_progress_ > reveal_progress)
last_reveal_progress_ -= .1f;
else
last_reveal_progress_ += .1f;
}
nux::Color pressure_color = nux::color::White * last_reveal_progress_;
nux::TexCoordXForm texxform_pressure;
int pressure_y = 0, pressure_width = 0, pressure_height = 0;
if (launcher_position_ == LauncherPosition::LEFT)
{
pressure_y = base.y;
pressure_width = launcher_pressure_effect_->GetWidth();
pressure_height = base.height;
}
else
{
pressure_y = base.y + base.height - SIDE_LINE_WIDTH.CP(cv_) - launcher_pressure_effect_->GetHeight();
pressure_width = base.width;
pressure_height = launcher_pressure_effect_->GetHeight();
}
GfxContext.QRP_1Tex(base.x, pressure_y, pressure_width, pressure_height,
launcher_pressure_effect_->GetDeviceTexture(),
texxform_pressure,
pressure_color);
}
if (!Settings::Instance().GetLowGfxMode())
{
if (IsOverlayOpen() && bg_effect_helper_.enabled)
{
nux::ObjectPtr blur_texture;
bool visible = false;
if ((launcher_position_ == LauncherPosition::LEFT && (bkg_box.x + bkg_box.width > 0)) ||
(launcher_position_ == LauncherPosition::BOTTOM && (bkg_box.y < bkg_box.height)))
visible = true;
if (BackgroundEffectHelper::blur_type != unity::BLUR_NONE && visible)
{
blur_texture = bg_effect_helper_.GetBlurRegion();
}
else
{
blur_texture = bg_effect_helper_.GetRegion();
}
if (blur_texture.IsValid())
{
nux::TexCoordXForm texxform_blur_bg;
texxform_blur_bg.flip_v_coord = true;
texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width;
texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height;
GfxContext.PushClippingRectangle(bkg_box);
#ifndef NUX_OPENGLES_20
if (GfxContext.UsingGLSLCodePath())
{
gPainter.PushDrawCompositionLayer(GfxContext, base,
blur_texture,
texxform_blur_bg,
nux::color::White,
options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY,
true, ROP);
}
else
{
gPainter.PushDrawTextureLayer(GfxContext, base,
blur_texture,
texxform_blur_bg,
nux::color::White,
true,
ROP);
}
#else
gPainter.PushDrawCompositionLayer(GfxContext, base,
blur_texture,
texxform_blur_bg,
nux::color::White,
options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY,
true, ROP);
#endif
GfxContext.PopClippingRectangle();
push_count++;
}
unsigned int alpha = 0, src = 0, dest = 0;
GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
// apply the darkening
GfxContext.GetRenderStates().SetBlend(true, GL_ZERO, GL_SRC_COLOR);
gPainter.Paint2DQuadColor(GfxContext, bkg_box, nux::Color(0.9f, 0.9f, 0.9f, 1.0f));
GfxContext.GetRenderStates().SetBlend (alpha, src, dest);
// apply the bg colour
#ifndef NUX_OPENGLES_20
if (GfxContext.UsingGLSLCodePath() == false)
gPainter.Paint2DQuadColor(GfxContext, bkg_box, options()->background_color);
#endif
// apply the shine
GfxContext.GetRenderStates().SetBlend(true, GL_DST_COLOR, GL_ONE);
nux::TexCoordXForm texxform;
texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
texxform.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP);
texxform.uoffset = (1.0f / launcher_sheen_->GetWidth()); // TODO (gord) don't use absolute values here
texxform.voffset = (1.0f / launcher_sheen_->GetHeight()) * panel::Style::Instance().PanelHeight(icon_renderer_->monitor);
GfxContext.QRP_1Tex(base.x, base.y, base.width, base.height,
launcher_sheen_->GetDeviceTexture(),
texxform,
nux::color::White);
//reset the blend state
GfxContext.GetRenderStates().SetBlend (alpha, src, dest);
}
else
{
nux::Color color = options()->background_color;
color.alpha = options()->background_alpha;
gPainter.Paint2DQuadColor(GfxContext, bkg_box, color);
}
}
else
{
nux::Color color = options()->background_color;
color.alpha = 1.0f;
gPainter.Paint2DQuadColor(GfxContext, bkg_box, color);
}
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
// XXX: It would be very cool to move the Rendering part out of the drawing part
icon_renderer_->PreprocessIcons(args, base);
EventLogic();
if (!IsOverlayOpen() && launcher_position_ == LauncherPosition::BOTTOM)
{
const double top_line_opacity = 0.15f * launcher_alpha;
gPainter.Paint2DQuadColor(GfxContext,
nux::Geometry(bkg_box.x,
bkg_box.y,
bkg_box.width,
SIDE_LINE_WIDTH.CP(cv_)),
nux::color::White * top_line_opacity);
gPainter.Paint2DQuadColor(GfxContext,
nux::Geometry(bkg_box.x,
bkg_box.y,
bkg_box.width,
8),
nux::Color(0x70000000),
nux::Color(0x00000000),
nux::Color(0x00000000),
nux::Color(0x70000000));
}
/* draw launcher */
for (rev_it = args.rbegin(); rev_it != args.rend(); ++rev_it)
{
if ((*rev_it).stick_thingy)
{
if (launcher_position_ == LauncherPosition::LEFT)
gPainter.Paint2DQuadColor(GfxContext,
nux::Geometry(bkg_box.x, (*rev_it).render_center.y - 3, bkg_box.width, 2),
nux::Color(0xAAAAAAAA));
else
gPainter.Paint2DQuadColor(GfxContext,
nux::Geometry((*rev_it).render_center.x - 3, bkg_box.y, 2, bkg_box.height),
nux::Color(0xAAAAAAAA));
}
if ((*rev_it).skip)
continue;
icon_renderer_->RenderIcon(GfxContext, *rev_it, bkg_box, base);
}
if (!IsOverlayOpen() && launcher_position_ == LauncherPosition::LEFT)
{
const double right_line_opacity = 0.15f * launcher_alpha;
gPainter.Paint2DQuadColor(GfxContext,
nux::Geometry(bkg_box.x + bkg_box.width,
bkg_box.y,
SIDE_LINE_WIDTH.CP(cv_),
bkg_box.height),
nux::color::White * right_line_opacity);
gPainter.Paint2DQuadColor(GfxContext,
nux::Geometry(bkg_box.x,
bkg_box.y,
bkg_box.width,
8),
nux::Color(0x70000000),
nux::Color(0x00000000),
nux::Color(0x00000000),
nux::Color(0x70000000));
}
// FIXME: can be removed for a bgk_box->SetAlpha once implemented
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::DST_IN);
nux::Color alpha_mask = nux::Color(0xFFAAAAAA) * launcher_alpha;
gPainter.Paint2DQuadColor(GfxContext, bkg_box, alpha_mask);
GfxContext.GetRenderStates().SetColorMask(true, true, true, true);
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
gPainter.PopBackground(push_count);
GfxContext.PopClippingRectangle();
GfxContext.PopClippingRectangle();
}
long Launcher::PostLayoutManagement(long LayoutResult)
{
View::PostLayoutManagement(LayoutResult);
SetMousePosition(0, 0);
return nux::SIZE_EQUAL_HEIGHT | nux::SIZE_EQUAL_WIDTH;
}
void Launcher::OnDragWindowAnimCompleted()
{
HideDragWindow();
QueueDraw();
}
bool Launcher::StartIconDragTimeout(int x, int y)
{
// if we are still waiting…
if (GetActionState() == ACTION_NONE)
{
SetIconUnderMouse(AbstractLauncherIcon::Ptr());
initial_drag_animation_ = true;
StartIconDragRequest(x, y);
}
return false;
}
void Launcher::StartIconDragRequest(int x, int y)
{
auto const& abs_geo = GetAbsoluteGeometry();
int mouse_x = 0, mouse_y = 0;
if (launcher_position_ == LauncherPosition::LEFT)
{
mouse_x = abs_geo.width / 2.0f;
mouse_y = y;
}
else
{
mouse_x = x;
mouse_y = abs_geo.height / 2.0f;
}
auto const& drag_icon = MouseIconIntersection(mouse_x, mouse_y);
// FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
// on an internal Launcher property then
if (drag_icon && last_button_press_ == 1 && drag_icon->position() == AbstractLauncherIcon::Position::FLOATING)
{
auto const& icon_center = drag_icon->GetCenter(monitor);
x += abs_geo.x;
y += abs_geo.y;
SetActionState(ACTION_DRAG_ICON);
StartIconDrag(drag_icon);
UpdateDragWindowPosition(icon_center.x, icon_center.y);
if (initial_drag_animation_)
{
drag_window_->SetAnimationTarget(x, y);
drag_window_->StartQuickAnimation();
}
QueueDraw();
}
else
{
drag_icon_ = nullptr;
HideDragWindow();
}
}
void Launcher::StartIconDrag(AbstractLauncherIcon::Ptr const& icon)
{
using namespace std::placeholders;
if (!icon)
return;
hide_machine_.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
drag_icon_ = icon;
drag_icon_position_ = model_->IconIndex(icon);
HideDragWindow();
auto cb = std::bind(&Launcher::RenderIconToTexture, this, _1, _2, drag_icon_);
drag_window_ = new LauncherDragWindow(GetWidth(), cb);
ShowDragWindow();
}
void Launcher::EndIconDrag()
{
if (drag_window_)
{
AbstractLauncherIcon::Ptr hovered_icon;
if (!drag_window_->Cancelled())
hovered_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y);
if (hovered_icon && hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
{
hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true, monitor());
remove_request.emit(drag_icon_);
HideDragWindow();
QueueDraw();
}
else
{
if (!drag_window_->Cancelled() && model_->IconIndex(drag_icon_) != drag_icon_position_)
{
drag_icon_->Stick(true);
}
auto const& icon_center = drag_icon_->GetCenter(monitor);
drag_window_->SetAnimationTarget(icon_center.x, icon_center.y);
drag_window_->anim_completed.connect(sigc::mem_fun(this, &Launcher::OnDragWindowAnimCompleted));
drag_window_->StartQuickAnimation();
}
}
if (MouseBeyondDragThreshold())
animation::StartOrReverse(drag_icon_animation_, animation::Direction::FORWARD);
hide_machine_.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, false);
}
void Launcher::ShowDragWindow()
{
if (!drag_window_ || drag_window_->IsVisible())
return;
drag_window_->GrabKeyboard();
drag_window_->ShowWindow(true);
drag_window_->PushToFront();
bool is_before;
AbstractLauncherIcon::Ptr const& closer = model_->GetClosestIcon(drag_icon_, is_before);
drag_window_->drag_cancel_request.connect([this, closer, is_before] {
if (is_before)
model_->ReorderAfter(drag_icon_, closer);
else
model_->ReorderBefore(drag_icon_, closer, true);
ResetMouseDragState();
SetActionState(ACTION_DRAG_ICON_CANCELLED);
});
}
void Launcher::HideDragWindow()
{
nux::Geometry const& abs_geo = GetAbsoluteGeometry();
nux::Point const& mouse = nux::GetWindowCompositor().GetMousePosition();
if (abs_geo.IsInside(mouse))
mouse_enter.emit(mouse.x - abs_geo.x, mouse.y - abs_geo.y, 0, 0);
if (!drag_window_)
return;
drag_window_->UnGrabKeyboard();
drag_window_->ShowWindow(false);
drag_window_ = nullptr;
}
void Launcher::UpdateDragWindowPosition(int x, int y)
{
if (!drag_window_)
return;
auto const& icon_geo = drag_window_->GetGeometry();
drag_window_->SetBaseXY(x - icon_geo.width / 2, y - icon_geo.height / 2);
if (!drag_icon_)
return;
auto const& launcher_geo = GetGeometry();
int mouse_x = 0, mouse_y = 0;
if (launcher_position_ == LauncherPosition::LEFT)
{
mouse_x = (launcher_geo.x + launcher_geo.width) / 2.0;
mouse_y = y - GetAbsoluteY();
}
else
{
mouse_x = x - GetAbsoluteX();
mouse_y = (launcher_geo.y + launcher_geo.height) / 2.0;
}
auto const& hovered_icon = MouseIconIntersection(mouse_x, mouse_y);
bool mouse_beyond_drag_threshold = MouseBeyondDragThreshold();
if (hovered_icon && drag_icon_ != hovered_icon)
{
if (!mouse_beyond_drag_threshold)
{
model_->ReorderSmart(drag_icon_, hovered_icon, true);
}
else
{
model_->ReorderBefore(drag_icon_, hovered_icon, false);
}
}
else if (!hovered_icon && mouse_beyond_drag_threshold)
{
// If no icon is hovered, then we can add our icon to the bottom
for (auto it = model_->main_rbegin(); it != model_->main_rend(); ++it)
{
auto const& icon = *it;
if (!icon->IsVisibleOnMonitor(monitor))
continue;
if ((launcher_position_ == LauncherPosition::LEFT && y >= icon->GetCenter(monitor).y) ||
(launcher_position_ == LauncherPosition::BOTTOM && x >= icon->GetCenter(monitor).x))
{
model_->ReorderAfter(drag_icon_, icon);
break;
}
}
}
}
void Launcher::ResetMouseDragState()
{
if (GetActionState() == ACTION_DRAG_ICON)
EndIconDrag();
if (GetActionState() == ACTION_DRAG_LAUNCHER)
hide_machine_.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, false);
SetActionState(ACTION_NONE);
dnd_delta_x_ = 0;
dnd_delta_y_ = 0;
last_button_press_ = 0;
}
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
last_button_press_ = nux::GetEventButton(button_flags);
SetMousePosition(x, y);
MouseDownLogic(x, y, button_flags, key_flags);
}
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
SetMousePosition(x, y);
MouseUpLogic(x, y, button_flags, key_flags);
ResetMouseDragState();
}
void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
{
/* FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
* on an internal Launcher property then
*/
if (last_button_press_ != 1)
return;
SetMousePosition(x, y);
// FIXME: hack (see SetupRenderArg)
initial_drag_animation_ = false;
dnd_delta_y_ += dy;
dnd_delta_x_ += dx;
if (nux::Abs(dnd_delta_y_) < MOUSE_DEADZONE &&
nux::Abs(dnd_delta_x_) < MOUSE_DEADZONE &&
GetActionState() == ACTION_NONE)
return;
SetIconUnderMouse(AbstractLauncherIcon::Ptr());
if (GetActionState() == ACTION_NONE)
{
#ifdef USE_X11
if (nux::Abs(dnd_delta_y_) >= nux::Abs(dnd_delta_x_) && launcher_position_ == LauncherPosition::LEFT)
{
launcher_drag_delta_ += dnd_delta_y_;
SetActionState(ACTION_DRAG_LAUNCHER);
hide_machine_.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true);
}
else if (nux::Abs(dnd_delta_x_) >= nux::Abs(dnd_delta_y_) && launcher_position_ == LauncherPosition::BOTTOM)
{
launcher_drag_delta_ += dnd_delta_x_;
SetActionState(ACTION_DRAG_LAUNCHER);
hide_machine_.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true);
}
else
{
// We we can safely start the icon drag, from the original mouse-down position
sources_.Remove(START_DRAGICON_DURATION);
StartIconDragRequest(x - dnd_delta_x_, y - dnd_delta_y_);
}
#endif
}
else if (GetActionState() == ACTION_DRAG_LAUNCHER)
{
if (launcher_position_ == LauncherPosition::LEFT)
launcher_drag_delta_ += dy;
else
launcher_drag_delta_ += dx;
}
else if (GetActionState() == ACTION_DRAG_ICON)
{
nux::Geometry const& geo = GetAbsoluteGeometry();
UpdateDragWindowPosition(geo.x + x, geo.y + y);
}
QueueDraw();
}
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
SetMousePosition(x, y);
SetStateMouseOverLauncher(true);
EventLogic();
}
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
SetStateMouseOverLauncher(false);
EventLogic();
}
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
{
SetMousePosition(x, y);
if (!hidden_)
UpdateChangeInMousePosition(dx, dy);
// Every time the mouse moves, we check if it is inside an icon...
EventLogic();
if (icon_under_mouse_ && WindowManager::Default().IsScaleActiveForGroup())
{
if (!icon_under_mouse_->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, monitor()))
SaturateIcons();
}
tooltip_manager_.MouseMoved(icon_under_mouse_);
}
void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned long /*button_flags*/, unsigned long key_flags)
{
if (!hovered_)
return;
bool alt_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_ALT);
if (alt_pressed && abs(wheel_delta) != NUX_MOUSEWHEEL_DELTA)
{
ScrollLauncher(wheel_delta);
}
else if (icon_under_mouse_)
{
auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
auto scroll_direction = (wheel_delta < 0) ? AbstractLauncherIcon::ScrollDirection::DOWN : AbstractLauncherIcon::ScrollDirection::UP;
icon_under_mouse_->PerformScroll(scroll_direction, timestamp);
}
}
void Launcher::ScrollLauncher(int wheel_delta)
{
if (wheel_delta < 0)
// scroll down
launcher_drag_delta_ -= SCROLL_AMOUNT.CP(cv_);
else
// scroll up
launcher_drag_delta_ += SCROLL_AMOUNT.CP(cv_);
QueueDraw();
}
#ifdef USE_X11
ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrierWrapper::Ptr const& owner, ui::BarrierEvent::Ptr event)
{
if (hide_machine_.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE) ||
hide_machine_.GetQuirk(LauncherHideMachine::LOCK_HIDE))
{
return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE;
}
nux::Geometry const& abs_geo = GetAbsoluteGeometry();
bool apply_to_reveal = false;
if (launcher_position_ == LauncherPosition::LEFT)
{
if (event->x >= abs_geo.x && event->x <= abs_geo.x + abs_geo.width)
{
if (!hidden_)
return ui::EdgeBarrierSubscriber::Result::ALREADY_HANDLED;
if (options()->reveal_trigger == RevealTrigger::EDGE)
{
if (event->y >= abs_geo.y)
apply_to_reveal = true;
}
else if (options()->reveal_trigger == RevealTrigger::CORNER)
{
if (event->y < abs_geo.y)
apply_to_reveal = true;
}
}
}
else
{
if (event->y >= abs_geo.y && event->y <= abs_geo.y + abs_geo.height)
{
if (!hidden_)
return ui::EdgeBarrierSubscriber::Result::ALREADY_HANDLED;
if (options()->reveal_trigger == RevealTrigger::EDGE)
{
if (event->x >= abs_geo.x + panel::Style::Instance().PanelHeight(monitor()))
apply_to_reveal = true;
}
else if (options()->reveal_trigger == RevealTrigger::CORNER)
{
if (event->x < abs_geo.x + panel::Style::Instance().PanelHeight(monitor()))
apply_to_reveal = true;
}
}
}
if (apply_to_reveal)
{
int root_x_return, root_y_return, win_x_return, win_y_return;
unsigned int mask_return;
Window root_return, child_return;
Display *dpy = nux::GetGraphicsDisplay()->GetX11Display();
if (XQueryPointer (dpy, DefaultRootWindow(dpy), &root_return, &child_return, &root_x_return,
&root_y_return, &win_x_return, &win_y_return, &mask_return))
{
if (mask_return & (Button1Mask | Button3Mask))
return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE;
}
}
if (!apply_to_reveal)
return ui::EdgeBarrierSubscriber::Result::IGNORED;
if (!owner->IsFirstEvent())
{
parent_->ShowWindow(true);
hide_machine_.AddRevealPressure(event->velocity);
}
return ui::EdgeBarrierSubscriber::Result::HANDLED;
}
#endif
bool Launcher::IsInKeyNavMode() const
{
return hide_machine_.GetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE);
}
void Launcher::EnterKeyNavMode()
{
hide_machine_.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true);
hover_machine_.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true);
SaturateIcons();
}
void Launcher::ExitKeyNavMode()
{
hide_machine_.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false);
hover_machine_.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false);
}
void Launcher::RecvQuicklistOpened(nux::ObjectPtr const& quicklist)
{
UScreen* uscreen = UScreen::GetDefault();
if (uscreen->GetMonitorGeometry(monitor).IsInside(nux::Point(quicklist->GetGeometry().x, quicklist->GetGeometry().y)))
{
hide_machine_.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true);
hover_machine_.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true);
EventLogic();
}
}
void Launcher::RecvQuicklistClosed(nux::ObjectPtr const& quicklist)
{
if (!IsInKeyNavMode())
{
nux::Point pt = nux::GetWindowCompositor().GetMousePosition();
if (!GetAbsoluteGeometry().IsInside(pt))
{
// The Quicklist just closed and the mouse is outside the launcher.
SetHover(false);
SetStateMouseOverLauncher(false);
}
}
// Cancel any prior state that was set before the Quicklist appeared.
SetActionState(ACTION_NONE);
hide_machine_.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, false);
hover_machine_.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, false);
EventLogic();
}
void Launcher::EventLogic()
{
if (GetActionState() == ACTION_DRAG_ICON ||
GetActionState() == ACTION_DRAG_LAUNCHER)
return;
AbstractLauncherIcon::Ptr launcher_icon;
if (!hidden_ && !IsInKeyNavMode() && hovered_)
{
launcher_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y);
}
SetIconUnderMouse(launcher_icon);
}
void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y);
if (launcher_icon)
{
if (IsInKeyNavMode())
{
key_nav_terminate_request.emit();
}
model_->SetSelection(model_->IconIndex(launcher_icon));
icon_mouse_down_ = launcher_icon;
// if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app
auto cb_func = sigc::bind(sigc::mem_fun(this, &Launcher::StartIconDragTimeout), x, y);
sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT);
launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
tooltip_manager_.IconClicked();
}
}
void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y);
sources_.Remove(START_DRAGICON_TIMEOUT);
if (icon_mouse_down_ && (icon_mouse_down_ == launcher_icon))
{
icon_mouse_down_->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags);
if (GetActionState() == ACTION_NONE)
{
icon_mouse_down_->mouse_click.emit(nux::GetEventButton(button_flags), monitor, key_flags);
}
}
if (launcher_icon && (icon_mouse_down_ != launcher_icon))
{
launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags);
}
if (GetActionState() == ACTION_DRAG_LAUNCHER)
{
animation::StartOrReverse(drag_over_animation_, animation::Direction::BACKWARD);
}
icon_mouse_down_ = nullptr;
}
AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const
{
LauncherModel::iterator it;
// We are looking for the icon at screen coordinates x, y;
nux::Point2 mouse_position(x, y);
int inside = 0;
for (it = model_->begin(); it != model_->end(); ++it)
{
if (!(*it)->IsVisibleOnMonitor(monitor))
continue;
nux::Point2 screen_coord [4];
for (int i = 0; i < 4; ++i)
{
auto hit_transform = (*it)->GetTransform(AbstractLauncherIcon::TRANSFORM_HIT_AREA, monitor);
screen_coord [i].x = hit_transform [i].x;
screen_coord [i].y = hit_transform [i].y;
}
inside = PointInside2DPolygon(screen_coord, 4, mouse_position, 1);
if (inside)
return (*it);
}
return AbstractLauncherIcon::Ptr();
}
void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, nux::ObjectPtr const& texture, AbstractLauncherIcon::Ptr const& icon)
{
RenderArg arg;
SetupRenderArg(icon, arg);
arg.render_center = nux::Point3(roundf(texture->GetWidth() / 2.0f), roundf(texture->GetHeight() / 2.0f), 0.0f);
arg.logical_center = arg.render_center;
arg.rotation.x = 0.0f;
arg.rotation.y = 0.0f;
arg.running_arrow = false;
arg.active_arrow = false;
arg.skip = false;
arg.window_indicators = 0;
arg.alpha = 1.0f;
std::list drag_args;
drag_args.push_front(arg);
graphics::PushOffscreenRenderTarget(texture);
unsigned int alpha = 0, src = 0, dest = 0;
GfxContext.GetRenderStates().GetBlend(alpha, src, dest);
GfxContext.GetRenderStates().SetBlend(false);
GfxContext.QRP_Color(0, 0, texture->GetWidth(), texture->GetHeight(),
nux::color::Transparent);
GfxContext.GetRenderStates().SetBlend(alpha, src, dest);
nux::Geometry geo(0, 0, texture->GetWidth(), texture->GetWidth());
icon_renderer_->PreprocessIcons(drag_args, geo);
icon_renderer_->RenderIcon(GfxContext, arg, geo, geo);
unity::graphics::PopOffscreenRenderTarget();
}
#ifdef NUX_GESTURES_SUPPORT
nux::GestureDeliveryRequest Launcher::GestureEvent(const nux::GestureEvent &event)
{
switch(event.type)
{
case nux::EVENT_GESTURE_BEGIN:
OnDragStart(event);
break;
case nux::EVENT_GESTURE_UPDATE:
OnDragUpdate(event);
break;
default: // EVENT_GESTURE_END
OnDragFinish(event);
break;
}
return nux::GestureDeliveryRequest::NONE;
}
#endif
bool Launcher::DndIsSpecialRequest(std::string const& uri) const
{
return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);
}
void Launcher::ProcessDndEnter()
{
#ifdef USE_X11
SetStateMouseOverLauncher(true);
dnd_data_.Reset();
drag_action_ = nux::DNDACTION_NONE;
steal_drag_ = false;
data_checked_ = false;
dnd_hovered_icon_ = nullptr;
drag_edge_touching_ = false;
dnd_hide_animation_.Stop();
#endif
}
void Launcher::DndReset()
{
#ifdef USE_X11
dnd_data_.Reset();
bool is_overlay_open = IsOverlayOpen();
for (auto it : *model_)
{
auto icon_type = it->GetIconType();
bool desaturate = false;
if (icon_type != AbstractLauncherIcon::IconType::HOME &&
icon_type != AbstractLauncherIcon::IconType::HUD)
{
desaturate = is_overlay_open && !hovered_;
}
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, desaturate, monitor());
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false, monitor());
}
DndHoveredIconReset();
#endif
}
void Launcher::DndHoveredIconReset()
{
#ifdef USE_X11
SetActionState(ACTION_NONE);
if (steal_drag_ && dnd_hovered_icon_)
{
dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false, monitor());
dnd_hovered_icon_->remove.emit(dnd_hovered_icon_);
}
if (!steal_drag_ && dnd_hovered_icon_)
{
dnd_hovered_icon_->SendDndLeave();
dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, false, monitor());
}
steal_drag_ = false;
drag_edge_touching_ = false;
dnd_hovered_icon_ = nullptr;
#endif
}
void Launcher::ProcessDndLeave()
{
#ifdef USE_X11
SetStateMouseOverLauncher(false);
DndHoveredIconReset();
#endif
}
void Launcher::ProcessDndMove(int x, int y, std::list mimes)
{
#ifdef USE_X11
if (!data_checked_)
{
const std::string uri_list = "text/uri-list";
data_checked_ = true;
dnd_data_.Reset();
auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
// get the data
for (auto const& mime : mimes)
{
if (mime != uri_list)
continue;
dnd_data_.Fill(display.GetDndData(const_cast(uri_list.c_str())));
break;
}
// see if the launcher wants this one
auto const& uris = dnd_data_.Uris();
if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
{return DndIsSpecialRequest(uri);}) != uris.end())
{
steal_drag_ = true;
}
// only set hover once we know our first x/y
SetActionState(ACTION_DRAG_EXTERNAL);
SetStateMouseOverLauncher(true);
}
SetMousePosition(x - parent_->GetGeometry().x, y - parent_->GetGeometry().y);
if (options()->hide_mode != LAUNCHER_HIDE_NEVER)
{
if ((monitor() == 0 && !IsOverlayOpen() && mouse_position_.x == 0 && !drag_edge_touching_) &&
((launcher_position_ == LauncherPosition::LEFT &&
mouse_position_.y <= (parent_->GetGeometry().height - icon_size_.CP(cv_) - 2 * SPACE_BETWEEN_ICONS.CP(cv_))) ||
(launcher_position_ == LauncherPosition::BOTTOM &&
mouse_position_.x <= (parent_->GetGeometry().width - icon_size_.CP(cv_) - 2 * SPACE_BETWEEN_ICONS.CP(cv_)))))
{
if (dnd_hovered_icon_)
{
dnd_hovered_icon_->SendDndLeave();
dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, false, monitor());
}
animation::StartOrReverse(dnd_hide_animation_, animation::Direction::FORWARD);
drag_edge_touching_ = true;
}
else if (drag_edge_touching_ &&
((launcher_position_ == LauncherPosition::LEFT && mouse_position_.x != 0) ||
(launcher_position_ == LauncherPosition::BOTTOM && mouse_position_.y != 0)))
{
animation::StartOrReverse(dnd_hide_animation_, animation::Direction::BACKWARD);
drag_edge_touching_ = false;
}
}
EventLogic();
auto const& hovered_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y);
bool hovered_icon_is_appropriate = false;
if (hovered_icon)
{
if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
steal_drag_ = false;
if (hovered_icon->position() == AbstractLauncherIcon::Position::FLOATING)
hovered_icon_is_appropriate = true;
}
if (steal_drag_)
{
drag_action_ = nux::DNDACTION_COPY;
if (!dnd_hovered_icon_ && hovered_icon_is_appropriate)
{
dnd_hovered_icon_ = new SpacerLauncherIcon(monitor());
model_->AddIcon(dnd_hovered_icon_);
model_->ReorderBefore(dnd_hovered_icon_, hovered_icon, true);
}
else if (dnd_hovered_icon_)
{
if (hovered_icon)
{
if (hovered_icon_is_appropriate)
{
model_->ReorderSmart(dnd_hovered_icon_, hovered_icon, true);
}
else
{
dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false, monitor());
dnd_hovered_icon_->remove.emit(dnd_hovered_icon_);
dnd_hovered_icon_ = nullptr;
}
}
}
}
else
{
if (!drag_edge_touching_ && hovered_icon != dnd_hovered_icon_)
{
if (hovered_icon)
{
hovered_icon->SendDndEnter();
drag_action_ = hovered_icon->QueryAcceptDrop(dnd_data_);
if (drag_action_ != nux::DNDACTION_NONE)
hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, true, monitor());
}
else
{
drag_action_ = nux::DNDACTION_NONE;
}
if (dnd_hovered_icon_)
{
dnd_hovered_icon_->SendDndLeave();
dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, false, monitor());
}
dnd_hovered_icon_ = hovered_icon;
}
}
bool accept;
if (drag_action_ != nux::DNDACTION_NONE)
accept = true;
else
accept = false;
SendDndStatus(accept, drag_action_, nux::Geometry(x, y, 1, 1));
#endif
}
void Launcher::ProcessDndDrop(int x, int y)
{
#ifdef USE_X11
if (steal_drag_)
{
for (auto const& uri : dnd_data_.Uris())
{
if (DndIsSpecialRequest(uri))
add_request.emit(uri, dnd_hovered_icon_);
}
}
else if (dnd_hovered_icon_ && drag_action_ != nux::DNDACTION_NONE)
{
if (IsOverlayOpen())
ubus_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
dnd_hovered_icon_->AcceptDrop(dnd_data_);
}
if (drag_action_ != nux::DNDACTION_NONE)
SendDndFinished(true, drag_action_);
else
SendDndFinished(false, drag_action_);
// reset our shiz
DndReset();
#endif
}
/*
* Returns the current selected icon if it is in keynavmode
* It will return NULL if it is not on keynavmode
*/
AbstractLauncherIcon::Ptr Launcher::GetSelectedMenuIcon() const
{
if (!IsInKeyNavMode())
return AbstractLauncherIcon::Ptr();
return model_->Selection();
}
//
// Key navigation
//
bool Launcher::InspectKeyEvent(unsigned int eventType,
unsigned int keysym,
const char* character)
{
// The Launcher accepts all key inputs.
return true;
}
int Launcher::GetDragDelta() const
{
return launcher_drag_delta_;
}
void Launcher::DndStarted(std::string const& data)
{
#ifdef USE_X11
SetDndQuirk();
dnd_data_.Fill(data.c_str());
auto const& uris = dnd_data_.Uris();
if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
{return DndIsSpecialRequest(uri);}) != uris.end())
{
steal_drag_ = true;
if (IsOverlayOpen())
SaturateIcons();
}
else
{
for (auto const& it : *model_)
{
if (it->ShouldHighlightOnDrag(dnd_data_))
{
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false, monitor());
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true, monitor());
}
else
{
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true, monitor());
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false, monitor());
}
}
}
#endif
}
void Launcher::DndFinished()
{
#ifdef USE_X11
UnsetDndQuirk();
data_checked_ = false;
DndReset();
#endif
}
void Launcher::SetDndQuirk()
{
#ifdef USE_X11
hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
#endif
}
void Launcher::UnsetDndQuirk()
{
#ifdef USE_X11
if (IsOverlayOpen() && !hovered_)
{
DesaturateIcons();
}
else
{
for (auto const& it : *model_)
{
it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false, monitor());
it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false, monitor());
}
}
hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, drag_out_delta_x_ >= DRAG_OUT_PIXELS - 90.0f);
hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
animation::SetValue(dnd_hide_animation_, animation::Direction::BACKWARD);
#endif
}
} // namespace launcher
} // namespace unity
./launcher/DesktopLauncherIcon.cpp 0000644 0000156 0000165 00000004246 12704076362 017323 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
*/
#include "DesktopLauncherIcon.h"
#include "unity-shared/WindowManager.h"
#include "FavoriteStore.h"
#include "config.h"
#include
namespace unity
{
namespace launcher
{
DesktopLauncherIcon::DesktopLauncherIcon()
: SimpleLauncherIcon(IconType::DESKTOP)
, show_in_switcher_(true)
{
WindowManager::Default().show_desktop_changed.connect(sigc::mem_fun(this, &DesktopLauncherIcon::UpdateTooltipText));
UpdateTooltipText();
icon_name = "desktop";
SetQuirk(Quirk::VISIBLE, true);
SetShortcut('d');
}
void DesktopLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
SimpleLauncherIcon::ActivateLauncherIcon(arg);
WindowManager::Default().ShowDesktop();
UpdateTooltipText();
}
void DesktopLauncherIcon::UpdateTooltipText()
{
auto const& wm = WindowManager::Default();
if (wm.InShowDesktop())
tooltip_text = _("Restore Windows");
else
tooltip_text = _("Show Desktop");
}
std::string DesktopLauncherIcon::GetName() const
{
return "DesktopLauncherIcon";
}
std::string DesktopLauncherIcon::GetRemoteUri() const
{
return FavoriteStore::URI_PREFIX_UNITY + "desktop-icon";
}
void DesktopLauncherIcon::SetShowInSwitcher(bool show_in_switcher)
{
show_in_switcher_ = show_in_switcher;
}
bool DesktopLauncherIcon::ShowInSwitcher(bool current)
{
return show_in_switcher_;
}
uint64_t DesktopLauncherIcon::SwitcherPriority()
{
return std::numeric_limits::max();
}
} // namespace launcher
} // namespace unity
./launcher/DevicesSettings.h 0000644 0000156 0000165 00000002572 12704076362 016167 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010-12 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#ifndef UNITYSHELL_DEVICES_SETTINGS_H
#define UNITYSHELL_DEVICES_SETTINGS_H
#include
#include
#include
#include
#include
namespace unity
{
namespace launcher
{
class DevicesSettings : boost::noncopyable, public sigc::trackable
{
public:
typedef std::shared_ptr Ptr;
virtual ~DevicesSettings() {};
virtual bool IsABlacklistedDevice(std::string const& uuid) const = 0;
virtual void TryToBlacklist(std::string const& uuid) = 0;
virtual void TryToUnblacklist(std::string const& uuid) = 0;
sigc::signal changed;
};
}
}
#endif
./launcher/StorageLauncherIcon.h 0000644 0000156 0000165 00000003004 12704076362 016752 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2015 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Marco Trevisan
*/
#ifndef STORAGE_LAUNCHER_ICON_H
#define STORAGE_LAUNCHER_ICON_H
#include "WindowedLauncherIcon.h"
#include "unity-shared/FileManager.h"
namespace unity
{
namespace launcher
{
class StorageLauncherIcon : public virtual WindowedLauncherIcon
{
public:
StorageLauncherIcon(AbstractLauncherIcon::IconType, FileManager::Ptr const&);
protected:
void UpdateStorageWindows();
WindowList GetManagedWindows() const override;
virtual WindowList GetStorageWindows() const = 0;
bool OnShouldHighlightOnDrag(DndData const& dnd_data) override;
private:
void OnWindowStateChanged();
protected:
FileManager::Ptr file_manager_;
WindowList managed_windows_;
connection::Manager windows_connections_;
};
} // namespace launcher
} // namespace unity
#endif // STORAGE_LAUNCHER_ICON_H
./launcher/XdndManager.h 0000644 0000156 0000165 00000002351 12704076362 015247 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Andrea Azzarone
*/
#ifndef UNITYSHELL_XDND_MANAGER_H
#define UNITYSHELL_XDND_MANAGER_H
#include
#include
#include
#include
namespace unity {
class XdndManager : boost::noncopyable {
public:
typedef std::shared_ptr Ptr;
virtual ~XdndManager() {}
virtual int Monitor() const = 0;
sigc::signal dnd_started;
sigc::signal monitor_changed;
sigc::signal dnd_finished;
};
}
#endif
./launcher/TooltipManager.h 0000644 0000156 0000165 00000002662 12704076362 016011 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2013 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jacob Edwards
* Andrea Azzarone
*/
#ifndef LAUNCHER_TOOLTIP_MANAGER_H
#define LAUNCHER_TOOLTIP_MANAGER_H
#include
#include
#include "AbstractLauncherIcon.h"
namespace unity
{
namespace launcher
{
class TooltipManager : public boost::noncopyable
{
public:
TooltipManager();
void SetHover(bool hovered);
void MouseMoved(AbstractLauncherIcon::Ptr const& icon_under_mouse);
void IconClicked();
private:
void Reset();
void ResetTimer(AbstractLauncherIcon::Ptr const& icon_under_mouse);
void StopTimer();
bool skip_timeout_;
AbstractLauncherIcon::Ptr icon_;
glib::Source::UniquePtr hover_timer_;
};
}
}
#endif
./launcher/QuicklistMenuItemLabel.cpp 0000644 0000156 0000165 00000004052 12704076362 017766 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Mirco Müller
* Jay Taoko
* Marco Trevisan
*/
#include "unity-shared/CairoTexture.h"
#include "QuicklistMenuItemLabel.h"
namespace unity
{
QuicklistMenuItemLabel::QuicklistMenuItemLabel(glib::Object const& item, NUX_FILE_LINE_DECL)
: QuicklistMenuItem(QuicklistMenuItemType::LABEL, item, NUX_FILE_LINE_PARAM)
{
InitializeText();
}
std::string QuicklistMenuItemLabel::GetDefaultText() const
{
return "Label";
}
std::string QuicklistMenuItemLabel::GetName() const
{
return "QuicklistMenuItemLabel";
}
void QuicklistMenuItemLabel::UpdateTexture(nux::CairoGraphics& cairoGraphics, double width, double height)
{
cairo_t* cr = cairoGraphics.GetInternalContext();
// draw normal, unchecked version
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
DrawText(cairoGraphics, width, height, nux::color::White);
_normalTexture[0].Adopt(texture_from_cairo_graphics(cairoGraphics));
// draw active/prelight, unchecked version
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
DrawPrelight(cairoGraphics, width, height, nux::color::White);
DrawText(cairoGraphics, width, height, nux::color::White * 0.0f);
_prelightTexture[0].Adopt(texture_from_cairo_graphics(cairoGraphics));
}
} // NAMESPACE
./launcher/QuicklistView.h 0000644 0000156 0000165 00000013662 12704076362 015671 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jay Taoko
* Authored by: Mirco Müller
#include
#include
#include
#include
#include
#include
#include
#include
#include "CairoBaseWindow.h"
#include "QuicklistMenuItem.h"
#include "unity-shared/Introspectable.h"
#include "unity-shared/RawPixel.h"
namespace unity
{
class QuicklistView : public CairoBaseWindow, public debug::Introspectable
{
NUX_DECLARE_OBJECT_TYPE(QuicklistView, unity::CairoBaseWindow);
public:
QuicklistView(int monitor = 0);
void SetText(std::string const& text);
void RemoveAllMenuItem();
void AddMenuItem(QuicklistMenuItem* item);
void RenderQuicklistView();
void SetQuicklistPosition(int x, int y);
void ShowQuicklistWithTipAt(int x, int y, bool restore_input_focus = false);
void Show(bool restore_input_focus = false);
void Hide();
void HideAndEndQuicklistNav();
virtual nux::Area* FindAreaUnderMouse(const nux::Point& mouse_position, nux::NuxEventType event_type) override;
int GetNumItems();
QuicklistMenuItem* GetNthItems(int index);
QuicklistMenuItemType GetNthType(int index);
int GetItemIndex(QuicklistMenuItem* item);
std::list GetChildren();
void SelectFirstItem();
void TestMenuItems(DbusmenuMenuitem* root);
// Introspection
std::string GetName() const;
void AddProperties(debug::IntrospectionData&);
IntrospectableList GetIntrospectableChildren();
void EnableQuicklistForTesting(bool enable_testing);
// Key navigation
virtual bool InspectKeyEvent(unsigned int eventType,
unsigned int keysym,
const char* character);
//Required for a11y
QuicklistMenuItem* GetSelectedMenuItem();
sigc::signal selection_change;
protected:
void Draw(nux::GraphicsEngine& gfxContext, bool forceDraw);
void DrawContent(nux::GraphicsEngine& gfxContext, bool forceDraw);
private:
void RecvCairoTextChanged(QuicklistMenuItem* item);
void RecvCairoTextColorChanged(QuicklistMenuItem* item);
void RecvItemMouseClick(QuicklistMenuItem* item, int x, int y);
void RecvItemMouseRelease(QuicklistMenuItem* item, int x, int y);
void RecvItemMouseEnter(QuicklistMenuItem* item);
void RecvItemMouseLeave(QuicklistMenuItem* item);
void RecvItemMouseDrag(QuicklistMenuItem* item, int x, int y);
void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags);
void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags);
void RecvMouseClick(int x, int y, unsigned long button_flags, unsigned long key_flags);
void RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
void RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
void RecvMouseDownOutsideOfQuicklist(int x, int y, unsigned long button_flags, unsigned long key_flags);
void RecvKeyPressed(unsigned long eventType , /*event type*/
unsigned long keysym , /*event keysym*/
unsigned long state , /*event state*/
const TCHAR* character , /*character*/
unsigned short keyCount);
void RecvStartFocus();
void RecvEndFocus();
void PreLayoutManagement();
long PostLayoutManagement(long layoutResult);
void PositionChildLayout(float offsetX, float offsetY);
void LayoutWindowElements();
void NotifyConfigurationChange(int width, int height);
//! A convenience function to fill in the default quicklist with some random items.
void FillInDefaultItems();
void CancelItemsPrelightStatus();
//! Check the mouse up event sent by an item. Detect the item where the mous is and emit the appropriate signal.
void CheckAndEmitItemSignal(int x, int y);
void ActivateItem(QuicklistMenuItem* item);
void SelectItem(int index);
bool IsMenuItemSelectable(int index);
int CalculateX() const;
int CalculateY() const;
int _anchorX;
int _anchorY;
std::string _labelText;
RawPixel _top_size; // size of the segment from point 13 to 14. See figure in ql_compute_full_mask_path.
RawPixel _padding;
bool _mouse_down;
//iIf true, suppress the Quicklist behaviour that is expected in Unity.
// Keep the Quicklist on screen for testing and automation.
bool _enable_quicklist_for_testing;
bool _restore_input_focus;
nux::HLayout* _hlayout;
nux::VLayout* _vlayout;
nux::VLayout* _item_layout;
nux::SpaceLayout* _left_space; //!< Space from the left of the widget to the left of the text.
nux::SpaceLayout* _right_space; //!< Space from the right of the text to the right of the widget.
nux::SpaceLayout* _top_space; //!< Space from the left of the widget to the left of the text.
nux::SpaceLayout* _bottom_space; //!< Space from the right of the text to the right of the widget.
bool _cairo_text_has_changed;
void UpdateTexture();
std::list _item_list;
// used by keyboard/a11y-navigation
int _current_item_index;
};
} // NAMESPACE
#endif // QUICKLISTVIEW_H
./launcher/StorageLauncherIcon.cpp 0000644 0000156 0000165 00000006310 12704076362 017310 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2015 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Marco Trevisan
*/
#include "StorageLauncherIcon.h"
namespace unity
{
namespace launcher
{
StorageLauncherIcon::StorageLauncherIcon(AbstractLauncherIcon::IconType icon_type, FileManager::Ptr const& fm)
: WindowedLauncherIcon(icon_type)
, file_manager_(fm)
{
file_manager_->locations_changed.connect(sigc::mem_fun(this, &StorageLauncherIcon::UpdateStorageWindows));
}
void StorageLauncherIcon::UpdateStorageWindows()
{
bool active = false;
bool urgent = false;
bool check_visibility = (GetIconType() == IconType::APPLICATION);
bool visible = IsSticky();
managed_windows_ = GetStorageWindows();
windows_connections_.Clear();
for (auto const& win : managed_windows_)
{
windows_connections_.Add(win->monitor.changed.connect([this] (int) { EnsureWindowsLocation(); }));
windows_connections_.Add(win->urgent.changed.connect([this] (bool) { OnWindowStateChanged(); }));
windows_connections_.Add(win->active.changed.connect([this] (bool) { OnWindowStateChanged(); }));
windows_connections_.Add(win->closed.connect([this] { UpdateStorageWindows(); }));
if (!active && win->active())
active = true;
if (!urgent && win->urgent())
urgent = true;
if (check_visibility)
{
windows_connections_.Add(win->visible.changed.connect([this] (bool) { OnWindowStateChanged(); }));
if (!visible && win->visible())
visible = true;
}
}
SetQuirk(Quirk::RUNNING, !managed_windows_.empty());
SetQuirk(Quirk::ACTIVE, active);
SetQuirk(Quirk::URGENT, urgent);
if (check_visibility)
SetQuirk(Quirk::VISIBLE, visible);
EnsureWindowsLocation();
}
WindowList StorageLauncherIcon::GetManagedWindows() const
{
return managed_windows_;
}
void StorageLauncherIcon::OnWindowStateChanged()
{
bool active = false;
bool urgent = false;
bool check_visibility = (GetIconType() == IconType::APPLICATION);
bool visible = IsSticky();
for (auto const& win : managed_windows_)
{
if (!active && win->active())
active = true;
if (!urgent && win->urgent())
urgent = true;
if (check_visibility && !visible && win->visible())
visible = true;
}
SetQuirk(Quirk::ACTIVE, active);
SetQuirk(Quirk::URGENT, urgent);
if (check_visibility)
SetQuirk(Quirk::VISIBLE, visible);
}
bool StorageLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data)
{
for (auto const& uri : dnd_data.Uris())
{
if (uri.find("file://") == 0)
return true;
}
return false;
}
} // namespace launcher
} // namespace unity
./launcher/Launcher.h 0000644 0000156 0000165 00000030350 12704076362 014620 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
* Authored by: Jay Taoko
*/
#ifndef LAUNCHER_H
#define LAUNCHER_H
#include
#include
#include
#include
#ifndef USE_GLES
# include
#endif
#include "unity-shared/AbstractIconRenderer.h"
#include "unity-shared/BackgroundEffectHelper.h"
#include "unity-shared/EMConverter.h"
#include "unity-shared/RawPixel.h"
#include "DevicesSettings.h"
#include "DndData.h"
#include "unity-shared/Introspectable.h"
#include "LauncherModel.h"
#include "LauncherOptions.h"
#include "LauncherDragWindow.h"
#include "LauncherHideMachine.h"
#include "LauncherHoverMachine.h"
#include "unity-shared/MockableBaseWindow.h"
#include "unity-shared/UBusWrapper.h"
#include "SoftwareCenterLauncherIcon.h"
#include "TooltipManager.h"
#ifdef USE_X11
# include "PointerBarrier.h"
# include "EdgeBarrierController.h"
#endif
namespace unity
{
enum class LauncherPosition;
namespace launcher
{
extern const char* window_title;
class AbstractLauncherIcon;
class Launcher : public unity::debug::Introspectable,
#ifdef USE_X11
// TODO: abstract this into a more generic class.
public ui::EdgeBarrierSubscriber,
#endif
public nux::View
{
NUX_DECLARE_OBJECT_TYPE(Launcher, nux::View);
public:
Launcher(MockableBaseWindow* parent, NUX_FILE_LINE_PROTO);
nux::Property monitor;
nux::Property options;
virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
AbstractLauncherIcon::Ptr GetSelectedMenuIcon() const;
void SetScrollInactiveIcons(bool scroll);
void SetLauncherMinimizeWindow(bool click_to_minimize);
void SetIconSize(int tile_size, int icon_size);
int GetIconSize() const;
bool Hidden() const
{
return hidden_;
}
void ForceReveal(bool force);
void ShowShortcuts(bool show);
void SetModel(LauncherModel::Ptr model);
LauncherModel::Ptr GetModel() const;
void StartKeyShowLauncher();
void EndKeyShowLauncher();
void EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& icon);
void SetBacklightMode(BacklightMode mode);
BacklightMode GetBacklightMode() const;
bool IsBackLightModeToggles() const;
MockableBaseWindow* GetParent() const
{
return parent_;
};
nux::ObjectPtr const& GetActiveTooltip() const;
LauncherDragWindow::Ptr const& GetDraggedIcon() const;
virtual void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags);
virtual void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags);
virtual void RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
virtual void RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags);
virtual void RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags);
virtual void RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
virtual void RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags);
virtual void RecvQuicklistOpened(nux::ObjectPtr const& quicklist);
virtual void RecvQuicklistClosed(nux::ObjectPtr const& quicklist);
void ScrollLauncher(int wheel_delta);
int GetMouseX() const;
int GetMouseY() const;
void Resize(nux::Point const& offset, int height);
int GetDragDelta() const;
void SetHover(bool hovered);
void DndStarted(std::string const& mimes);
void DndFinished();
void SetDndQuirk();
void UnsetDndQuirk();
sigc::signal add_request;
sigc::signal remove_request;
sigc::signal selection_change;
sigc::signal hidden_changed;
sigc::signal sc_launcher_icon_animation;
sigc::signal key_nav_terminate_request;
virtual bool InspectKeyEvent(unsigned int eventType,
unsigned int keysym,
const char* character);
void EnterKeyNavMode();
void ExitKeyNavMode();
bool IsInKeyNavMode() const;
bool IsOverlayOpen() const;
void ClearTooltip();
void RenderIconToTexture(nux::GraphicsEngine&, nux::ObjectPtr const&, AbstractLauncherIcon::Ptr const&);
#ifdef NUX_GESTURES_SUPPORT
virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event);
#endif
protected:
// Introspectable methods
std::string GetName() const;
void AddProperties(debug::IntrospectionData&);
void ProcessDndEnter();
void ProcessDndLeave();
void ProcessDndMove(int x, int y, std::list mimes);
void ProcessDndDrop(int x, int y);
private:
typedef nux::ObjectPtr BaseTexturePtr;
LauncherHideMode GetHideMode() const;
void SetHideMode(LauncherHideMode hidemode);
typedef enum
{
ACTION_NONE,
ACTION_DRAG_LAUNCHER,
ACTION_DRAG_ICON,
ACTION_DRAG_ICON_CANCELLED,
ACTION_DRAG_EXTERNAL,
} LauncherActionState;
void ConfigureBarrier();
void OnMonitorChanged(int monitor);
void OnOptionsChanged(Options::Ptr options);
void OnOptionChanged();
void UpdateOptions(Options::Ptr options);
#ifdef NUX_GESTURES_SUPPORT
void OnDragStart(const nux::GestureEvent &event);
void OnDragUpdate(const nux::GestureEvent &event);
void OnDragFinish(const nux::GestureEvent &event);
#endif
#ifdef USE_X11
ui::EdgeBarrierSubscriber::Result HandleBarrierEvent(ui::PointerBarrierWrapper::Ptr const& owner, ui::BarrierEvent::Ptr event);
#endif
void OnExpoChanged();
void OnSpreadChanged();
void OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection);
bool StrutHack();
bool StartIconDragTimeout(int x, int y);
bool OnScrollTimeout();
void SetUrgentTimer(int urgent_wiggle_period);
void AnimateUrgentIcon(AbstractLauncherIcon::Ptr const& icon);
void HandleUrgentIcon(AbstractLauncherIcon::Ptr const& icon);
bool OnUrgentTimeout();
void SetMousePosition(int x, int y);
void SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon);
void SetStateMouseOverLauncher(bool over_launcher);
bool MouseBeyondDragThreshold() const;
void OnDragWindowAnimCompleted();
bool IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const;
void SetActionState(LauncherActionState actionstate);
LauncherActionState GetActionState() const;
void EnsureScrollTimer();
bool MouseOverTopScrollArea();
bool MouseOverBottomScrollArea();
float DragOutProgress() const;
float IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon) const;
float IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon) const;
float IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon) const;
float IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon) const;
float IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon) const;
float IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon) const;
float IconProgressBias(AbstractLauncherIcon::Ptr const& icon) const;
void SetHidden(bool hidden);
void UpdateChangeInMousePosition(int delta_x, int delta_y);
void SetDndDelta(float x, float y, nux::Geometry const& geo);
float DragLimiter(float x);
void SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, ui::RenderArg& arg);
void FillRenderArg(AbstractLauncherIcon::Ptr const& icon,
ui::RenderArg& arg,
nux::Point3& center,
nux::Geometry const& parent_abs_geo,
float folding_threshold,
float folded_size,
float folded_spacing,
float autohide_offset,
float folded_z_distance,
float animation_neg_rads);
void RenderArgs(std::list &launcher_args,
nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo, bool& force_show_window);
void OnIconAdded(AbstractLauncherIcon::Ptr const& icon);
void OnIconRemoved(AbstractLauncherIcon::Ptr const& icon);
void OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon, int monitor);
void SetupIconAnimations(AbstractLauncherIcon::Ptr const& icon);
void OnTooltipVisible(nux::ObjectPtr view);
void OnOverlayHidden(GVariant* data);
void OnOverlayShown(GVariant* data);
void DesaturateIcons();
void SaturateIcons();
void OnBGColorChanged(GVariant *data);
void OnLockHideChanged(GVariant *data);
void OnActionDone(GVariant* data);
virtual AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y) const;
void EventLogic();
void MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags);
void MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags);
void StartIconDragRequest(int x, int y);
void StartIconDrag(AbstractLauncherIcon::Ptr const& icon);
void EndIconDrag();
void ShowDragWindow();
void UpdateDragWindowPosition(int x, int y);
void HideDragWindow();
void ResetMouseDragState();
float GetAutohidePositionMin() const;
float GetAutohidePositionMax() const;
virtual long PostLayoutManagement(long LayoutResult);
void DndReset();
void DndHoveredIconReset();
bool DndIsSpecialRequest(std::string const& uri) const;
void OnDPIChanged();
void LoadTextures();
LauncherModel::Ptr model_;
MockableBaseWindow* parent_;
ui::AbstractIconRenderer::Ptr icon_renderer_;
nux::ObjectPtr active_tooltip_;
std::set animating_urgent_icons_;
// used by keyboard/a11y-navigation
AbstractLauncherIcon::Ptr icon_under_mouse_;
AbstractLauncherIcon::Ptr icon_mouse_down_;
AbstractLauncherIcon::Ptr drag_icon_;
AbstractLauncherIcon::Ptr dnd_hovered_icon_;
bool hovered_;
bool hidden_;
bool folded_;
bool render_drag_window_;
bool shortcuts_shown_;
bool data_checked_;
bool steal_drag_;
bool drag_edge_touching_;
bool initial_drag_animation_;
bool dash_is_open_;
bool hud_is_open_;
LauncherActionState launcher_action_state_;
RawPixel icon_size_;
int dnd_delta_y_;
int dnd_delta_x_;
int postreveal_mousemove_delta_x_;
int postreveal_mousemove_delta_y_;
int launcher_drag_delta_;
int launcher_drag_delta_max_;
int launcher_drag_delta_min_;
int enter_x_;
int enter_y_;
int last_button_press_;
int drag_icon_position_;
int urgent_animation_period_;
bool urgent_ack_needed_;
float drag_out_delta_x_;
bool drag_gesture_ongoing_;
float last_reveal_progress_;
nux::Point mouse_position_;
LauncherDragWindow::Ptr drag_window_;
LauncherHideMachine hide_machine_;
LauncherHoverMachine hover_machine_;
TooltipManager tooltip_manager_;
unity::DndData dnd_data_;
nux::DndAction drag_action_;
BaseTexturePtr launcher_sheen_;
BaseTexturePtr launcher_pressure_effect_;
BackgroundEffectHelper bg_effect_helper_;
LauncherPosition launcher_position_;
connection::Wrapper launcher_position_changed_;
nux::animation::AnimateValue auto_hide_animation_;
nux::animation::AnimateValue hover_animation_;
nux::animation::AnimateValue drag_over_animation_;
nux::animation::AnimateValue drag_out_animation_;
nux::animation::AnimateValue drag_icon_animation_;
nux::animation::AnimateValue dnd_hide_animation_;
nux::animation::AnimateValue dash_showing_animation_;
UBusManager ubus_;
glib::SourceManager sources_;
EMConverter::Ptr cv_;
friend class TestLauncher;
};
}
}
#endif // LAUNCHER_H
./launcher/LauncherModel.cpp 0000644 0000156 0000165 00000025125 12704076362 016140 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
* Marco Trevisan
*/
#include "LauncherModel.h"
#include "AbstractLauncherIcon.h"
#include
namespace unity
{
namespace launcher
{
LauncherModel::LauncherModel()
: selection_(0)
{}
std::string LauncherModel::GetName() const
{
return "LauncherModel";
}
void LauncherModel::AddProperties(debug::IntrospectionData& introspection)
{
introspection
.add("selection", selection_);
}
debug::Introspectable::IntrospectableList LauncherModel::GetIntrospectableChildren()
{
int order = 0;
std::list children;
for (auto const& icon : _inner)
{
if (!icon->removed)
{
icon->SetOrder(++order);
children.push_back(icon.GetPointer());
}
}
return children;
}
bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const
{
return icon->position() == AbstractLauncherIcon::Position::END;
}
bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second)
{
if (first->position() < second->position())
return true;
else if (first->position() > second->position())
return false;
return first->SortPriority() < second->SortPriority();
}
void LauncherModel::PopulatePart(iterator begin, iterator end)
{
AbstractLauncherIcon::Ptr prev_icon;
for (auto it = begin; it != end; ++it)
{
auto const& icon = *it;
_inner.push_back(icon);
if (prev_icon)
{
// Ensuring that the current icon has higher priority than previous one
if (icon->SortPriority() < prev_icon->SortPriority())
{
int new_priority = prev_icon->SortPriority() + 1;
icon->SetSortPriority(new_priority);
}
}
prev_icon = icon;
}
}
bool LauncherModel::Populate()
{
Base copy = _inner;
_inner.clear();
PopulatePart(main_begin(), main_end());
PopulatePart(shelf_begin(), shelf_end());
return copy.size() == _inner.size() && !std::equal(begin(), end(), copy.begin());
}
void LauncherModel::AddIcon(AbstractLauncherIcon::Ptr const& icon)
{
if (!icon || std::find(begin(), end(), icon) != end())
return;
if (IconShouldShelf(icon))
_inner_shelf.push_back(icon);
else
_inner_main.push_back(icon);
Sort();
icon_added.emit(icon);
icon->on_icon_removed_connection = icon->remove.connect(sigc::mem_fun(this, &LauncherModel::OnIconRemove));
}
void LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr const& icon)
{
size_t size;
_inner_shelf.erase(std::remove(_inner_shelf.begin(), _inner_shelf.end(), icon), _inner_shelf.end());
_inner_main.erase(std::remove(_inner_main.begin(), _inner_main.end(), icon), _inner_main.end());
size = _inner.size();
_inner.erase(std::remove(_inner.begin(), _inner.end(), icon), _inner.end());
if (size != _inner.size())
{
icon_removed.emit(icon);
}
}
void LauncherModel::OnIconRemove(AbstractLauncherIcon::Ptr const& icon)
{
icon->removed = true;
timeouts_.AddTimeout(1000, [this, icon] {
RemoveIcon(icon);
return false;
});
}
void LauncherModel::Save()
{
saved.emit();
}
void LauncherModel::Sort()
{
std::stable_sort(_inner_shelf.begin(), _inner_shelf.end(), &LauncherModel::CompareIcons);
std::stable_sort(_inner_main.begin(), _inner_main.end(), &LauncherModel::CompareIcons);
if (Populate())
order_changed.emit();
}
bool LauncherModel::IconHasSister(AbstractLauncherIcon::Ptr const& icon) const
{
if (!icon)
return false;
auto const& container = IconShouldShelf(icon) ? _inner_shelf : _inner_main;
for (auto const& icon_it : container)
{
if (icon_it != icon && icon_it->GetIconType() == icon->GetIconType())
return true;
}
return false;
}
void LauncherModel::ReorderAfter(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other)
{
if (icon == other || icon.IsNull() || other.IsNull())
return;
if (icon->position() != other->position())
return;
icon->SetSortPriority(other->SortPriority() + 1);
for (auto it = std::next(std::find(begin(), end(), other)); it != end(); ++it)
{
auto const& icon_it = *it;
if (icon_it == icon)
continue;
// Increasing the priority of the icons next to the other one
int new_priority = icon_it->SortPriority() + 2;
icon_it->SetSortPriority(new_priority);
}
Sort();
}
void LauncherModel::ReorderBefore(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate)
{
if (icon == other || icon.IsNull() || other.IsNull())
return;
if (icon->position() != other->position())
return;
bool found_target = false;
bool center = false;
for (auto const& icon_it : _inner)
{
if (icon_it == icon)
{
center = !center;
continue;
}
int old_priority = icon_it->SortPriority();
int new_priority = old_priority + (found_target ? 1 : -1);
// We need to reduce the priority of all the icons previous to 'other'
if (icon_it != other && !found_target && other->SortPriority() == old_priority)
new_priority -= 1;
icon_it->SetSortPriority(new_priority);
if (icon_it == other)
{
if (animate && center)
icon_it->SaveCenter();
center = !center;
new_priority += -1;
icon->SetSortPriority(new_priority);
if (animate && center)
icon_it->SaveCenter();
found_target = true;
}
else
{
if (animate && center)
icon_it->SaveCenter();
}
}
Sort();
}
void LauncherModel::ReorderSmart(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate)
{
if (icon == other || icon.IsNull() || other.IsNull())
return;
if (icon->position() != other->position())
return;
bool found_icon = false;
bool found_target = false;
bool center = false;
for (auto const& icon_it : _inner)
{
if (icon_it == icon)
{
found_icon = true;
center = !center;
continue;
}
int old_priority = icon_it->SortPriority();
int new_priority = old_priority + (found_target ? 1 : -1);
// We need to reduce the priority of all the icons previous to 'other'
if (icon_it != other && !found_target && other->SortPriority() == old_priority)
new_priority -= 1;
icon_it->SetSortPriority(new_priority);
if (icon_it == other)
{
if (animate && center)
icon_it->SaveCenter();
center = !center;
new_priority += found_icon ? 1 : -1;
icon->SetSortPriority(new_priority);
if (animate && center)
icon_it->SaveCenter();
found_target = true;
}
else
{
if (animate && center)
icon_it->SaveCenter();
}
}
Sort();
}
int
LauncherModel::Size() const
{
return _inner.size();
}
AbstractLauncherIcon::Ptr const& LauncherModel::Selection() const
{
return _inner[selection_];
}
int LauncherModel::SelectionIndex() const
{
return selection_;
}
void LauncherModel::SetSelection(int selection)
{
int new_selection = std::min(Size() - 1, std::max (0, selection));
if (new_selection == selection_)
return;
selection_ = new_selection;
selection_changed.emit(Selection());
}
void LauncherModel::SelectNext()
{
int temp = selection_;
temp++;
while (temp != selection_)
{
if (temp >= Size())
temp = 0;
if (_inner[temp]->IsVisible())
{
selection_ = temp;
selection_changed.emit(Selection());
break;
}
temp++;
}
}
void LauncherModel::SelectPrevious()
{
int temp = selection_;
temp--;
while (temp != selection_)
{
if (temp < 0)
temp = Size() - 1;
if (_inner[temp]->IsVisible())
{
selection_ = temp;
selection_changed.emit(Selection());
break;
}
temp--;
}
}
AbstractLauncherIcon::Ptr LauncherModel::GetClosestIcon(AbstractLauncherIcon::Ptr const& icon, bool& is_before) const
{
AbstractLauncherIcon::Ptr prev, next;
bool found_target = false;
for (auto const& current : _inner)
{
if (current->position() != icon->position())
continue;
if (!found_target)
{
if (current == icon)
{
found_target = true;
if (prev)
break;
}
else
{
prev = current;
}
}
else
{
next = current;
break;
}
}
is_before = next.IsNull();
return is_before ? prev : next;
}
int LauncherModel::IconIndex(AbstractLauncherIcon::Ptr const& target) const
{
int pos = 0;
bool found = false;
for (auto const& icon : _inner)
{
if (icon == target)
{
found = true;
break;
}
++pos;
}
return found ? pos : -1;
}
/* iterators */
LauncherModel::iterator LauncherModel::begin()
{
return _inner.begin();
}
LauncherModel::iterator LauncherModel::end()
{
return _inner.end();
}
LauncherModel::iterator LauncherModel::at(int index)
{
LauncherModel::iterator it;
int i;
// start currently selected icon
for (it = _inner.begin(), i = 0; it != _inner.end(); ++it, i++)
{
if (i == index)
return it;
}
return (LauncherModel::iterator)NULL;
}
LauncherModel::reverse_iterator LauncherModel::rbegin()
{
return _inner.rbegin();
}
LauncherModel::reverse_iterator LauncherModel::rend()
{
return _inner.rend();
}
LauncherModel::iterator LauncherModel::main_begin()
{
return _inner_main.begin();
}
LauncherModel::iterator LauncherModel::main_end()
{
return _inner_main.end();
}
LauncherModel::reverse_iterator LauncherModel::main_rbegin()
{
return _inner_main.rbegin();
}
LauncherModel::reverse_iterator LauncherModel::main_rend()
{
return _inner_main.rend();
}
LauncherModel::iterator LauncherModel::shelf_begin()
{
return _inner_shelf.begin();
}
LauncherModel::iterator LauncherModel::shelf_end()
{
return _inner_shelf.end();
}
LauncherModel::reverse_iterator LauncherModel::shelf_rbegin()
{
return _inner_shelf.rbegin();
}
LauncherModel::reverse_iterator LauncherModel::shelf_rend()
{
return _inner_shelf.rend();
}
} // namespace launcher
} // namespace unity
./launcher/LauncherController.cpp 0000644 0000156 0000165 00000127011 12704076362 017220 0 ustar jenkins jenkins // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
* Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by: Jason Smith
* Tim Penhey
* Marco Trevisan
*/
#include "config.h"
#include