summaryrefslogtreecommitdiff
diff options
authorDidier Roche <didier.roche@canonical.com>2010-12-09 19:31:09 +0100
committerDidier Roche <didier.roche@canonical.com>2010-12-09 19:31:09 +0100
commit491e2f0f05062b3e1032054d573e876ca4f68ddb (patch)
tree28741fcc3181bc64447129ed4559947952417ea6
parent431332d7c1baa3cfee23932a5697550625f81218 (diff)
parentab13eaf44b4bbaf8b322d8e704b85fbc3a3c59a8 (diff)
Import upstream version 3.2.6upstream-3.2.6
(bzr r55.4.36)
-rw-r--r--CMakeLists.txt5
-rw-r--r--INSTALL180
-rw-r--r--README7
-rw-r--r--libunity/CMakeLists.txt1
-rw-r--r--libunity/perf-logger-utility.h34
-rw-r--r--libunity/perf-logger.vala (renamed from unity-private/testing/perf-logger.vala)57
-rw-r--r--po/unity.pot2
-rw-r--r--resources/focused_indicator.pngbin197 -> 337 bytes
-rw-r--r--resources/round_outline_54x54.pngbin1992 -> 2402 bytes
-rw-r--r--resources/running_indicator.pngbin166 -> 345 bytes
-rw-r--r--services/panel-main.c29
-rw-r--r--services/panel-service.c153
-rw-r--r--src/BamfLauncherIcon.cpp448
-rw-r--r--src/BamfLauncherIcon.h25
-rw-r--r--src/IndicatorObjectFactory.h4
-rw-r--r--src/IndicatorObjectFactoryRemote.cpp31
-rw-r--r--src/IndicatorObjectFactoryRemote.h3
-rw-r--r--src/Introspectable.cpp46
-rw-r--r--src/Introspectable.h3
-rw-r--r--src/IntrospectionDBusInterface.cpp4
-rw-r--r--src/Launcher.cpp3840
-rw-r--r--src/Launcher.h509
-rw-r--r--src/LauncherController.cpp9
-rw-r--r--[-rwxr-xr-x]src/LauncherIcon.cpp1175
-rw-r--r--src/LauncherIcon.h397
-rw-r--r--src/LauncherModel.cpp71
-rw-r--r--src/LauncherModel.h10
-rw-r--r--src/PanelHomeButton.cpp18
-rw-r--r--src/PanelHomeButton.h8
-rw-r--r--src/PanelIndicatorObjectEntryView.cpp46
-rw-r--r--src/PanelIndicatorObjectEntryView.h8
-rw-r--r--src/PanelIndicatorObjectView.cpp27
-rw-r--r--src/PanelIndicatorObjectView.h10
-rw-r--r--src/PanelView.cpp511
-rw-r--r--src/PanelView.h126
-rw-r--r--src/QuicklistMenuItem.cpp23
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItem.h10
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemCheckmark.cpp2
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemCheckmark.h0
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemLabel.cpp2
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemLabel.h0
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemRadio.cpp72
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemRadio.h13
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemSeparator.cpp2
-rw-r--r--[-rwxr-xr-x]src/QuicklistMenuItemSeparator.h0
-rw-r--r--src/QuicklistView.cpp173
-rw-r--r--[-rwxr-xr-x]src/QuicklistView.h20
-rw-r--r--src/SimpleLauncherIcon.cpp53
-rw-r--r--src/Tooltip.cpp21
-rw-r--r--src/Tooltip.h12
-rw-r--r--src/TrashLauncherIcon.cpp67
-rw-r--r--src/TrashLauncherIcon.h7
-rw-r--r--src/unity.cpp472
-rw-r--r--src/unity.h14
-rw-r--r--tests/CMakeLists.txt23
-rw-r--r--tests/ui/EventFaker.cpp89
-rw-r--r--tests/ui/EventFaker.h40
-rw-r--r--tests/ui/TestQuicklist.cpp305
-rw-r--r--tests/unit/TestPanelService.cpp48
-rw-r--r--tools/CMakeLists.txt6
-rwxr-xr-xtools/makebootchart.py70
-rwxr-xr-xtools/migrate_favorites.py65
-rwxr-xr-xtools/unity.cmake127
-rw-r--r--unityshell.xml.in1
64 files changed, 5821 insertions, 3713 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48586e7ec..e3eaf5f75 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@ subdirs (libunity services tests tools)
set (PROJECT_NAME "unity")
set (UNITY_MAJOR 3)
set (UNITY_MINOR 2)
-set (UNITY_MICRO 2)
+set (UNITY_MICRO 6)
set (UNITY_VERSION "${UNITY_MAJOR}.${UNITY_MINOR}.${UNITY_MICRO}")
set (UNITY_API_VERSION "3.0")
@@ -74,7 +74,7 @@ endif (${GETTEXT_FOUND} STREQUAL "TRUE")
#
# src (Compiz Plugin)
#
-set (UNITY_PLUGIN_DEPS "nux-0.9;libbamf;dbus-glib-1;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib;x11;libstartup-notification-1.0;gthread-2.0")
+set (UNITY_PLUGIN_DEPS "nux-0.9;libbamf;dbus-glib-1;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib;x11;libstartup-notification-1.0;gthread-2.0;indicator")
find_package (Compiz REQUIRED)
include (CompizPlugin)
@@ -82,6 +82,7 @@ compiz_plugin (unityshell
PKGDEPS ${UNITY_PLUGIN_DEPS}
PLUGINDEPS composite opengl
CFLAGSADD "-DINSTALLPREFIX='\"${CMAKE_INSTALL_PREFIX}\"' -DPKGDATADIR='\"${CMAKE_INSTALL_PREFIX}/share/unity/3\"' -I${CMAKE_BINARY_DIR}"
+ LIBRARIES "unity"
)
#
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 000000000..a52b43df9
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,180 @@
+ Install
+--------------------------------------------------------------------------------
+
+• Notes
+
+ - libunity is an independant library which has a client side API for talking
+ to Unity. However it does not depend on the main Unity codebase and the
+ main Unity codebase does not depend on it.
+
+ - Unity and it's desktop environment modules are all modules of Compiz. We use
+ a patched version of Compiz which uses the GLib main loop instead of the
+ custom Compiz main loop. This allows us to use GNOME libraries easily inside
+ the Unity plugins.
+
+ We are currently working on getting this patch upstreamed, but until then
+ you will need to build this special version of Compiz.
+
+ - libunity is written in Vala and the rest of Unity in C++/C.
+
+ - Unity depends on a library called Nux (lp:nux) which let's us do OpenGL
+ layouts quickly and efficiently.
+
+
+• Dependencies
+
+ These are in Debian package name form, but it should be easy enough to
+ translate them to other systems:
+
+ libglib2.0-dev libgdk-pixbuf2.0-dev libcairo2-dev libpng12-dev libglew1.5-dev
+ libglewmx1.5-dev libxxf86vm-dev libgl1-mesa-dev libsigc++-2.0-dev
+ libpango1.0-dev doxygen cmake pkg-config valac intltool libgee-dev
+ libbamf-dev gsettings-desktop-schemas-dev libgconf2-dev libglib2.0-dev
+ libdbusmenu-glib-dev libgtk2.0-dev libdee-dev libindicator-dev
+ libboost-dev libboost-serialization-dev libmetacity-dev python-dev cython
+
+ However, as with any project, it's probably best to just run autogen/cmake
+ and figure out what you need/is missing. If your distro supports grabbing
+ all the packages needed to build a package, then at least do that for
+ Compiz, as I'm not going to detail everything it needs here.
+
+ In case your distro isn't packaging all the Ayatana software, these links
+ might come in handy:
+
+ https://launchpad.net/dee
+ https://launchpad.net/bamf
+ https://launchpad.net/libindicator
+
+ Also, although we don't hard depend on them, having a few indicators installed
+ will make your experience better:
+
+ https://launchpad.net/indicator-appmenu
+ https://launchpad.net/indicator-application
+ https://launchpad.net/indicator-network
+ https://launchpad.net/indicator-sound
+ https://launchpad.net/indicator-messages
+ https://launchpad.net/indicator-datetime
+ https://launchpad.net/indicator-me
+ https://launchpad.net/indicator-session
+
+• Build Compiz GLib
+
+ This is taken from http://wiki.ubuntu.com/Unity/InstallationGuideFromSource and
+ was originally authored by Sam:
+
+ core:
+
+ git clone git://git.compiz.org/users/dbo/compiz-with-glib-mainloop
+ cd compiz-with-glib-mainloop
+ mkdir build
+ cd build
+ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/unity
+ make
+ sudo make findcompiz_install
+ sudo make install
+
+ exporting paths:
+
+ export PKG_CONFIG_PATH=/opt/unity/lib/pkgconfig:${PKG_CONFIG_PATH}
+ export LD_LIBRARY_PATH=/opt/unity/lib:${LD_LIBRARY_PATH}
+ export LD_RUN_PATH=/opt/unity/lib:${LD_RUN_PATH}
+
+ libcompizconfig:
+
+ git clone git://git.compiz.org/compiz/compizconfig/libcompizconfig
+ cd libcompizconfig
+ mkdir build
+ cd build
+ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/unity
+ make
+ sudo make install
+
+ compizconfig-python:
+
+ git clone git://git.compiz.org/compiz/compizconfig/compizconfig-python
+ cd compizconfig-python
+ python setup.py install --prefix=/opt/unity
+
+ ccsm:
+
+ git clone git://git.compiz.org/compiz/compizconfig/ccsm
+ cd ccsm
+ python setup.py install --prefix=/opt/unity
+
+ plugins-main:
+
+ git clone git://git.compiz.org/compiz/plugins-main
+ cd plugins-main
+ git submodule init
+ git pull origin master
+ git submodule update
+ mkdir build
+ cd build
+ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/unity
+ make
+ sudo make install
+
+ plugins-extra:
+
+ git clone git://git.compiz.org/compiz/plugins-extra
+ cd plugins-extra
+ git submodule init
+ git pull origin master
+ git submodule update
+ mkdir build
+ cd build
+ cmake .. -DCMAKE_INSTALL_PREFIX=/opt/unity
+ make
+ sudo make install
+
+
+• Build Nux
+
+ bzr branch lp:nux
+ cd nux
+ ./autogen.sh --disable-documentation --prefix=/opt/unity
+ make
+ sudo make install
+
+
+• Build Unity
+
+ bzr branch lp:unity
+ cd unity
+ mkdir build; cd build
+ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCOMPIZ_PLUGIN_INSTALL_TYPE=package -DCMAKE_INSTALL_PREFIX=/opt/unity
+ make
+ sudo make install
+
+• Cleanup
+
+ unset PKG_CONFIG_PATH
+ unset LD_LIBRARY_PATH
+ unset LD_RUN_PATH
+
+
+• Testing
+
+ add this to your /home/$USER/.bashrc
+
+ function compiz-unity-setup-env
+ {
+ export PATH=/opt/unity/bin:${PATH}
+ export PYTHONPATH=/opt/unity/lib/python2.6/site-packages
+ }
+
+ Logout, login, then in a terminal do
+
+ $ compiz-unity-setup-env
+ $ compiz --replace cpp &
+ $ ccsm
+
+ And then use the CompizConfig Settings Window to search for and enable the Unity plugin!
+
+
+• Bugs
+
+ If you find bugs in this installation guide or in Unity itself, please report them at
+ https://launchpad.net/unity/+filebug
+
+
diff --git a/README b/README
index 99528074a..5d9256932 100644
--- a/README
+++ b/README
@@ -3,12 +3,15 @@
• Installation
+ Please see INSTALL or http://wiki.ubuntu.com/Unity/InstallationGuideFromSource
+
• Tests
- You can run `make check` in the build directory to run all GTester tests
- In the build directory, ./tests/test-panel will start the panel in
standalone mode, which is great for testing
+
• Environmental Variables
PANEL_USE_LOCAL_SERVICE=${anything}
@@ -16,6 +19,6 @@
D-Bus activation. This is used for testing how the panel reacts when it
starts before the service does.
-• Code Style
-astyle -s2 -b -S -N -w -Y -M80 -p -H -d -j -k3 -n -z2
+• Code Style
+ astyle -s2 -b -S -N -w -Y -M80 -p -H -d -j -k3 -n -z2
diff --git a/libunity/CMakeLists.txt b/libunity/CMakeLists.txt
index 5e59ba7d1..e04fafa07 100644
--- a/libunity/CMakeLists.txt
+++ b/libunity/CMakeLists.txt
@@ -50,6 +50,7 @@ find_package (Vala)
vala_precompile (VALA_C unity-place-activation.vala
unity-place-browser.vala
unity-place.vala
+ perf-logger.vala
PACKAGES gtk+-2.0 gio-2.0 glib-2.0 gobject-2.0 gee-1.0 dbus-glib-1 gio-unix-2.0
OPTIONS --thread
CUSTOM_VAPIS ../vapi/dee-1.0.vapi ../vapi/config.vapi
diff --git a/libunity/perf-logger-utility.h b/libunity/perf-logger-utility.h
new file mode 100644
index 000000000..aee02abea
--- /dev/null
+++ b/libunity/perf-logger-utility.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009-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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by Gordon Allott <gord.allott@canonical.com>
+ *
+ */
+#ifndef _PERF_LOGGER_H_
+#define _PERF_LOGGER_H_
+
+#include <libunity/unity.h>
+
+#define START_FUNCTION() G_STMT_START { \
+ perf_timeline_logger_start_process (perf_timeline_logger_get_default(), G_STRFUNC);\
+ } G_STMT_END
+#define LOGGER_START_PROCESS(process) { perf_timeline_logger_start_process (perf_timeline_logger_get_default(), process);}
+
+#define END_FUNCTION() G_STMT_START { \
+ perf_timeline_logger_end_process (perf_timeline_logger_get_default(), G_STRFUNC);\
+ } G_STMT_END
+#define LOGGER_END_PROCESS(process) { perf_timeline_logger_end_process (perf_timeline_logger_get_default(), process);}
+
+#endif /* PERF_LOGGER_H */
diff --git a/unity-private/testing/perf-logger.vala b/libunity/perf-logger.vala
index 7c66f7db0..5eeca40e3 100644
--- a/unity-private/testing/perf-logger.vala
+++ b/libunity/perf-logger.vala
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Canonical Ltd
+ * Copyright (C) 2009-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
@@ -17,9 +17,8 @@
*
*/
-namespace Unity
+namespace Perf
{
-
public class ProcessInfo
{
public ProcessInfo (string name)
@@ -32,82 +31,86 @@ namespace Unity
public double start;
public double end;
}
-
+
public static TimelineLogger? timeline_singleton;
- public static bool is_logging;
-
+ public static bool is_logging;
+
public class TimelineLogger : Object
{
private Timer global_timer;
private Gee.HashMap<string, ProcessInfo> process_map;
-
- public static unowned Unity.TimelineLogger get_default ()
+
+ public static unowned Perf.TimelineLogger get_default ()
{
- if (Unity.timeline_singleton == null)
+ if (Perf.timeline_singleton == null)
{
- Unity.timeline_singleton = new Unity.TimelineLogger ();
+ Perf.timeline_singleton = new Perf.TimelineLogger ();
}
-
- return Unity.timeline_singleton;
+
+ return Perf.timeline_singleton;
}
-
+
construct
{
this.process_map = new Gee.HashMap<string, ProcessInfo> ();
- this.global_timer = new Timer ();
+ this.global_timer = new Timer ();
this.global_timer.start ();
}
-
+
public void start_process (string name)
{
+ debug ("shoop de whoop");
if (name in this.process_map.keys)
{
warning ("already started process: %s", name);
return;
}
-
+
var info = new ProcessInfo (name);
this.process_map[name] = info;
info.start = this.global_timer.elapsed ();
}
-
+
public void end_process (string name)
{
+ debug ("shonk le donk");
double end_time = this.global_timer.elapsed ();
-
+ print ("the end time is %f", end_time);
+
if (name in this.process_map.keys)
{
this.process_map[name].end = end_time;
}
- else
+ else
{
warning ("process %s not started", name);
}
}
-
+
public void write_log (string filename)
{
debug ("Writing performance log file: %s...", filename);
var log_file = File.new_for_path (filename);
FileOutputStream file_stream;
- try
+ try
{
if (!log_file.query_exists (null)) {
file_stream = log_file.create (FileCreateFlags.NONE, null);
}
- else
+ else
{
file_stream = log_file.replace (null, false, FileCreateFlags.NONE, null);
}
-
+
var output_stream = new DataOutputStream (file_stream);
-
+
foreach (ProcessInfo info in this.process_map.values)
{
- string outline = "%s, %f, %f\n".printf(info.name, info.start, info.end);
- output_stream.put_string (outline, null);
+ string name = info.name.replace (",", ";");
+ string outline = "%s, %f, %f\n".printf(name, info.start, info.end);
+ output_stream.put_string (outline, null);
}
-
+
file_stream.close (null);
} catch (Error e)
{
diff --git a/po/unity.pot b/po/unity.pot
index 1bf78a1c5..283b0ced6 100644
--- a/po/unity.pot
+++ b/po/unity.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: ayatana-dev@lists.launchpad.net\n"
-"POT-Creation-Date: 2010-11-28 20:25-0500\n"
+"POT-Creation-Date: 2010-12-07 14:34-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/resources/focused_indicator.png b/resources/focused_indicator.png
index 42fdad3b2..cf70e5aa2 100644
--- a/resources/focused_indicator.png
+++ b/resources/focused_indicator.png
Binary files differ
diff --git a/resources/round_outline_54x54.png b/resources/round_outline_54x54.png
index 1250c9de4..b6bb3b61c 100644
--- a/resources/round_outline_54x54.png
+++ b/resources/round_outline_54x54.png
Binary files differ
diff --git a/resources/running_indicator.png b/resources/running_indicator.png
index 3169ec967..ab6aab485 100644
--- a/resources/running_indicator.png
+++ b/resources/running_indicator.png
Binary files differ
diff --git a/services/panel-main.c b/services/panel-main.c
index 339310326..38008587f 100644
--- a/services/panel-main.c
+++ b/services/panel-main.c
@@ -73,6 +73,10 @@ static const gchar introspection_xml[] =
" <arg type='i' name='y' />"
" </signal>"
""
+ " <signal name='EntryActivateRequest'>"
+ " <arg type='s' name='entry_id' />"
+ " </signal>"
+ ""
" </interface>"
"</node>";
@@ -137,8 +141,6 @@ handle_method_call (GDBusConnection *connection,
gint32 button;
g_variant_get (parameters, "(suiii)", &entry_id, &timestamp, &x, &y, &button, NULL);
- g_debug ("button: %u", button);
-
panel_service_show_entry (service, entry_id, timestamp, x, y, button);
g_dbus_method_invocation_return_value (invocation, NULL);
@@ -211,6 +213,27 @@ on_service_active_menu_pointer_motion (PanelService *service,
}
static void
+on_service_entry_activate_request (PanelService *service,
+ const gchar *entry_id,
+ GDBusConnection *connection)
+{
+ GError *error = NULL;
+ g_dbus_connection_emit_signal (connection,
+ S_NAME,
+ S_PATH,
+ S_IFACE,
+ "EntryActivateRequest",
+ g_variant_new ("(s)", entry_id),
+ &error);
+
+ if (error)
+ {
+ g_warning ("Unable to emit EntryActivateRequest signal: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
on_bus_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
@@ -231,6 +254,8 @@ on_bus_acquired (GDBusConnection *connection,
G_CALLBACK (on_service_entry_activated), connection);
g_signal_connect (service, "active-menu-pointer-motion",
G_CALLBACK (on_service_active_menu_pointer_motion), connection);
+ g_signal_connect (service, "entry-activate-request",
+ G_CALLBACK (on_service_entry_activate_request), connection);
g_debug ("%s", G_STRFUNC);
g_assert (reg_id > 0);
diff --git a/services/panel-service.c b/services/panel-service.c
index 060aaf06f..290d180fd 100644
--- a/services/panel-service.c
+++ b/services/panel-service.c
@@ -46,8 +46,10 @@ struct _PanelServicePrivate
guint initial_sync_id;
gint32 timeouts[N_TIMEOUT_SLOTS];
+ IndicatorObjectEntry *last_entry;
GtkMenu *last_menu;
guint32 last_menu_id;
+ guint32 last_menu_move_id;
gint32 last_x;
gint32 last_y;
guint32 last_menu_button;
@@ -64,6 +66,7 @@ enum
ENTRY_ACTIVATED = 0,
RE_SYNC,
ACTIVE_MENU_POINTER_MOTION,
+ ENTRY_ACTIVATE_REQUEST,
LAST_SIGNAL
};
@@ -79,8 +82,9 @@ static guint32 _service_signals[LAST_SIGNAL] = { 0 };
static gchar * indicator_order[] = {
"libappmenu.so",
"libapplication.so",
- "libnetwork.so",
"libsoundmenu.so",
+ "libnetwork.so",
+ "libnetworkmenu.so",
"libmessaging.so",
"libdatetime.so",
"libme.so",
@@ -167,6 +171,16 @@ panel_service_class_init (PanelServiceClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ _service_signals[ENTRY_ACTIVATE_REQUEST] =
+ g_signal_new ("entry-activate-request",
+ G_OBJECT_CLASS_TYPE (obj_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+
g_type_class_add_private (obj_class, sizeof (PanelServicePrivate));
}
@@ -476,6 +490,23 @@ on_entry_moved (IndicatorObject *object,
}
static void
+on_indicator_menu_show (IndicatorObject *object,
+ IndicatorObjectEntry *entry,
+ guint32 timestamp,
+ PanelService *self)
+{
+ gchar *entry_id;
+
+ g_return_if_fail (PANEL_IS_SERVICE (self));
+
+ entry_id = g_strdup_printf ("%p", entry);
+
+ g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
+
+ g_free (entry_id);
+}
+
+static void
load_indicator (PanelService *self, IndicatorObject *object, const gchar *_name)
{
PanelServicePrivate *priv = self->priv;
@@ -497,6 +528,8 @@ load_indicator (PanelService *self, IndicatorObject *object, const gchar *_name)
G_CALLBACK (on_entry_removed), self);
g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED,
G_CALLBACK (on_entry_moved), self);
+ g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_MENU_SHOW,
+ G_CALLBACK (on_indicator_menu_show), self);
entries = indicator_object_get_entries (object);
for (entry = entries; entry != NULL; entry = entry->next)
@@ -741,8 +774,11 @@ on_active_menu_hidden (GtkMenu *menu, PanelService *self)
priv->last_menu_button = 0;
g_signal_handler_disconnect (priv->last_menu, priv->last_menu_id);
+ g_signal_handler_disconnect (priv->last_menu, priv->last_menu_move_id);
priv->last_menu = NULL;
priv->last_menu_id = 0;
+ priv->last_menu_move_id = 0;
+ priv->last_entry = NULL;
g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, "");
}
@@ -804,6 +840,111 @@ panel_service_sync_one (PanelService *self, const gchar *indicator_id)
return g_variant_builder_end (&b);
}
+static void
+activate_next_prev_menu (PanelService *self,
+ IndicatorObject *object,
+ IndicatorObjectEntry *entry,
+ GtkMenuDirectionType direction)
+{
+ PanelServicePrivate *priv = self->priv;
+ GSList *indicators = priv->indicators;
+ GList *entries;
+ gint n_entries;
+ IndicatorObjectEntry *new_entry;
+ gchar *id;
+
+ entries = indicator_object_get_entries (object);
+ n_entries = g_list_length (entries);
+ if (n_entries == 1
+ || (g_list_index (entries, entry) == 0 && direction == GTK_MENU_DIR_PARENT)
+ || (g_list_index (entries, entry) == n_entries - 1 && direction == GTK_MENU_DIR_CHILD))
+ {
+ int n_indicators;
+ IndicatorObject *new_object;
+ GList *new_entries;
+
+ n_indicators = g_slist_length (priv->indicators);
+
+ if (g_slist_index (indicators, object) == 0 && direction == GTK_MENU_DIR_PARENT)
+ {
+ new_object = g_slist_nth_data (indicators, n_indicators - 1);
+ }
+ else if (g_slist_index (indicators, object) == n_indicators -1 && direction == GTK_MENU_DIR_CHILD)
+ {
+ new_object = g_slist_nth_data (indicators, 0);
+ }
+ else
+ {
+ gint cur_object_index = g_slist_index (indicators, object);
+ gint new_object_index = cur_object_index + (direction == GTK_MENU_DIR_CHILD ? 1 : -1);
+ new_object = g_slist_nth_data (indicators, new_object_index);
+ }
+
+ new_entries = indicator_object_get_entries (new_object);
+ new_entry = g_list_nth_data (new_entries, direction == GTK_MENU_DIR_PARENT ? g_list_length (new_entries) - 1 : 0);
+
+ g_list_free (new_entries);
+ }
+ else
+ {
+ new_entry = g_list_nth_data (entries, g_list_index (entries, entry) + (direction == GTK_MENU_DIR_CHILD ? 1 : -1));
+ }
+
+ id = g_strdup_printf ("%p", new_entry);
+ g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, id);
+
+ g_free (id);
+ g_list_free (entries);
+}
+
+static void
+on_active_menu_move_current (GtkMenu *menu,
+ GtkMenuDirectionType direction,
+ PanelService *self)
+{
+ PanelServicePrivate *priv;
+ IndicatorObject *object;
+
+ g_return_if_fail (PANEL_IS_SERVICE (self));
+ priv = self->priv;
+
+ /* Not interested in up or down */
+ if (direction == GTK_MENU_DIR_NEXT
+ || direction == GTK_MENU_DIR_PREV)
+ return;
+
+ /* We don't want to distrupt going into submenus */
+ if (direction == GTK_MENU_DIR_CHILD)
+ {
+ GList *children, *c;
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ for (c = children; c; c = c->next)
+ {
+ GtkWidget *item = (GtkWidget *)c->data;
+
+ if (GTK_IS_MENU_ITEM (item)
+ && gtk_widget_get_state (item) == GTK_STATE_PRELIGHT
+ && gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)))
+ {
+ /* Skip direction due to there being a submenu,
+ * and we don't want to inhibit going into that */
+ return;
+ }
+ }
+ g_list_free (children);
+ }
+
+ /* Find the next/prev indicator */
+ object = g_hash_table_lookup (priv->entry2indicator_hash, priv->last_entry);
+ if (object == NULL)
+ {
+ g_warning ("Unable to find IndicatorObject for entry");
+ return;
+ }
+
+ activate_next_prev_menu (self, object, priv->last_entry, direction);
+}
+
void
panel_service_show_entry (PanelService *self,
const gchar *entry_id,
@@ -815,27 +956,37 @@ panel_service_show_entry (PanelService *self,
PanelServicePrivate *priv = self->priv;
IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
+ if (priv->last_entry == entry)
+ return;
+
if (GTK_IS_MENU (priv->last_menu))
{
priv->last_x = 0;
priv->last_y = 0;
g_signal_handler_disconnect (priv->last_menu, priv->last_menu_id);
+ g_signal_handler_disconnect (priv->last_menu, priv->last_menu_move_id);
gtk_menu_popdown (GTK_MENU (priv->last_menu));
+ priv->last_entry = NULL;
priv->last_menu = NULL;
priv->last_menu_id = 0;
+ priv->last_menu_move_id = 0;
priv->last_menu_button = 0;
}
if (entry != NULL && GTK_IS_MENU (entry->menu))
{
+ priv->last_entry = entry;
priv->last_menu = entry->menu;
priv->last_x = x;
priv->last_y = y;
priv->last_menu_button = button;
priv->last_menu_id = g_signal_connect (priv->last_menu, "hide",
G_CALLBACK (on_active_menu_hidden), self);
+ priv->last_menu_move_id = g_signal_connect_after (priv->last_menu, "move-current",
+ G_CALLBACK (on_active_menu_move_current), self);
+
gtk_menu_popup (priv->last_menu, NULL, NULL, positon_menu, self, 0, CurrentTime);
g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id);
diff --git a/src/BamfLauncherIcon.cpp b/src/BamfLauncherIcon.cpp
index d64a8aac4..20d2b6af6 100644
--- a/src/BamfLauncherIcon.cpp
+++ b/src/BamfLauncherIcon.cpp
@@ -25,31 +25,52 @@
#include "FavoriteStore.h"
#include <gio/gdesktopappinfo.h>
-
+#include <libindicator/indicator-desktop-shortcuts.h>
#include <core/core.h>
#include <core/atoms.h>
+struct _ShortcutData
+{
+ BamfLauncherIcon *self;
+ IndicatorDesktopShortcuts *shortcuts;
+ char *nick;
+};
+typedef struct _ShortcutData ShortcutData;
+static void shortcut_data_destroy (ShortcutData *data)
+{
+ g_object_unref (data->shortcuts);
+ g_free (data->nick);
+ g_slice_free (ShortcutData, data);
+}
+
+static void shortcut_activated (DbusmenuMenuitem* _sender, guint timestamp, gpointer userdata)
+{
+ ShortcutData *data = (ShortcutData *)userdata;
+ indicator_desktop_shortcuts_nick_exec (data->shortcuts, data->nick);
+}
+
BamfLauncherIcon::BamfLauncherIcon (Launcher* IconManager, BamfApplication *app, CompScreen *screen)
: SimpleLauncherIcon(IconManager)
{
m_App = app;
m_Screen = screen;
+ _menu_desktop_shortcuts = NULL;
char *icon_name = bamf_view_get_icon (BAMF_VIEW (m_App));
SetTooltipText (bamf_view_get_name (BAMF_VIEW (app)));
SetIconName (icon_name);
SetIconType (LAUNCHER_ICON_TYPE_APPLICATION);
-
+
if (bamf_view_is_sticky (BAMF_VIEW (m_App)))
SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, true);
else
SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, bamf_view_user_visible (BAMF_VIEW (m_App)));
-
+
SetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE, bamf_view_is_active (BAMF_VIEW (m_App)));
SetQuirk (LAUNCHER_ICON_QUIRK_RUNNING, bamf_view_is_running (BAMF_VIEW (m_App)));
-
+
g_free (icon_name);
-
+
g_signal_connect (app, "child-removed", (GCallback) &BamfLauncherIcon::OnChildRemoved, this);
g_signal_connect (app, "child-added", (GCallback) &BamfLauncherIcon::OnChildAdded, this);
g_signal_connect (app, "urgent-changed", (GCallback) &BamfLauncherIcon::OnUrgentChanged, this);
@@ -57,9 +78,9 @@ BamfLauncherIcon::BamfLauncherIcon (Launcher* IconManager, BamfApplication *app,
g_signal_connect (app, "active-changed", (GCallback) &BamfLauncherIcon::OnActiveChanged, this);
g_signal_connect (app, "user-visible-changed", (GCallback) &BamfLauncherIcon::OnUserVisibleChanged, this);
g_signal_connect (app, "closed", (GCallback) &BamfLauncherIcon::OnClosed, this);
-
+
g_object_ref (m_App);
-
+
EnsureWindowState ();
UpdateMenus ();
}
@@ -77,11 +98,39 @@ BamfLauncherIcon::~BamfLauncherIcon()
g_object_unref (m_App);
}
+void
+BamfLauncherIcon::AddProperties (GVariantBuilder *builder)
+{
+ LauncherIcon::AddProperties (builder);
+
+ g_variant_builder_add (builder, "{sv}", "desktop-file", g_variant_new_string (bamf_application_get_desktop_file (m_App)));
+
+ GList *children, *l;
+ BamfView *view;
+
+ children = bamf_view_get_children (BAMF_VIEW (m_App));
+ GVariant* xids[(int) g_list_length (children)];
+
+ int i = 0;
+ for (l = children; l; l = l->next)
+ {
+ view = (BamfView *) l->data;
+
+ if (BAMF_IS_WINDOW (view))
+ {
+ xids[i++] = g_variant_new_uint32 (bamf_window_get_xid (BAMF_WINDOW (view)));
+ }
+ }
+ g_list_free (children);
+ g_variant_builder_add (builder, "{sv}", "xids", g_variant_new_array (G_VARIANT_TYPE_UINT32, xids, i));
+}
+
bool
BamfLauncherIcon::IconOwnsWindow (Window w)
{
GList *children, *l;
BamfView *view;
+ bool owns = false;
children = bamf_view_get_children (BAMF_VIEW (m_App));
@@ -92,87 +141,164 @@ BamfLauncherIcon::IconOwnsWindow (Window w)
if (BAMF_IS_WINDOW (view))
{
guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
-
+
if (xid == w)
- return true;
+ {
+ owns = true;
+ break;
+ }
}
}
-
- return false;
+
+ g_list_free (children);
+ return owns;
}
void
-BamfLauncherIcon::OnMouseClick (int button)
+BamfLauncherIcon::OpenInstance ()
{
- if (button != 1)
- return;
-
- BamfView *view;
- GList *children, *l;
- bool active, running;
GDesktopAppInfo *appInfo;
-
+ GError *error = NULL;
+
+ appInfo = g_desktop_app_info_new_from_filename (bamf_application_get_desktop_file (BAMF_APPLICATION (m_App)));
+ g_app_info_launch (G_APP_INFO (appInfo), NULL, NULL, &error);
+ g_object_unref (appInfo);
+
+ if (error)
+ {
+ g_warning ("%s\n", error->message);
+ g_error_free (error);
+ }
+
+ UpdateQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
+}
+
+void
+BamfLauncherIcon::Focus ()
+{
+ GList *children, *l;
+ BamfView *view;
+
children = bamf_view_get_children (BAMF_VIEW (m_App));
- active = bamf_view_is_active (BAMF_VIEW (m_App));
- running = bamf_view_is_running (BAMF_VIEW (m_App));
-
- if (!running)
+
+ CompWindowList windows;
+
+ /* get the list of windows */
+ for (l = children; l; l = l->next)
{
- appInfo = g_desktop_app_info_new_from_filename (bamf_application_get_desktop_file (BAMF_APPLICATION (m_App)));
- g_app_info_launch (G_APP_INFO (appInfo), NULL, NULL, NULL);
- g_object_unref (appInfo);
-
- UpdateQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
-
+ view = (BamfView *) l->data;
+
+ if (BAMF_IS_WINDOW (view))
+ {
+ guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
+
+ CompWindow *window = m_Screen->findWindow ((Window) xid);
+
+ if (window)
+ windows.push_back (window);
+ }
+ }
+
+ if (windows.empty ())
return;
+
+ /* sort the list */
+ CompWindowList tmp;
+ CompWindowList::iterator it;
+ for (it = m_Screen->windows ().begin (); it != m_Screen->windows ().end (); it++)
+ {
+ if (std::find (windows.begin (), windows.end (), *it) != windows.end ())
+ tmp.push_back (*it);
}
-
- if (active)
+ windows = tmp;
+
+
+ /* filter based on workspace */
+ bool any_on_current = false;
+
+ for (it = windows.begin (); it != windows.end (); it++)
{
- std::list<Window> windowList;
- for (l = children; l; l = l->next)
+ if ((*it)->defaultViewport () == m_Screen->vp ())
{
- view = (BamfView *) l->data;
-
- if (BAMF_IS_WINDOW (view))
- {
- guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
-
- windowList.push_back ((Window) xid);
- }
+ any_on_current = true;
+ break;
}
-
- if (windowList.size () > 1)
+ }
+
+ /* activate our windows */
+
+ if (any_on_current)
+ {
+ for (it = windows.begin (); it != windows.end (); it++)
{
- std::string *match = PluginAdapter::Default ()->MatchStringForXids (&windowList);
- PluginAdapter::Default ()->InitiateScale (match);
- delete match;
+ if ((*it)->defaultViewport () == m_Screen->vp ())
+ {
+ (*it)->activate ();
+ }
}
}
else
{
- for (l = children; l; l = l->next)
+ (*(windows.rbegin ()))->activate ();
+ }
+
+ g_list_free (children);
+}
+
+void
+BamfLauncherIcon::Spread ()
+{
+ BamfView *view;
+ GList *children, *l;
+ children = bamf_view_get_children (BAMF_VIEW (m_App));
+
+ std::list<Window> windowList;
+ for (l = children; l; l = l->next)
+ {
+ view = (BamfView *) l->data;
+
+ if (BAMF_IS_WINDOW (view))
{
- view = (BamfView *) l->data;
-
- if (BAMF_IS_WINDOW (view))
- {
- guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
-
- CompWindow *window = m_Screen->findWindow ((Window) xid);
-
- if (window)
- window->activate ();
- }
+ guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
+
+ windowList.push_back ((Window) xid);
}
}
+
+ if (windowList.size () > 1)
+ {
+ std::string *match = PluginAdapter::Default ()->MatchStringForXids (&windowList);
+ PluginAdapter::Default ()->InitiateScale (match);
+ delete match;
+ }
+
+ g_list_free (children);
+}
+
+void
+BamfLauncherIcon::OnMouseClick (int button)
+{
+ if (button != 1)
+ return;
+
+ bool active, running;
+
+ active = bamf_view_is_active (BAMF_VIEW (m_App));
+ running = bamf_view_is_running (BAMF_VIEW (m_App));
+
+ if (!running)
+ OpenInstance ();
+ else if (active)
+ Spread ();
+ else
+ Focus ();
}
void
BamfLauncherIcon::OnClosed (BamfView *view, gpointer data)
{
BamfLauncherIcon *self = (BamfLauncherIcon *) data;
-
+
if (!bamf_view_is_sticky (BAMF_VIEW (self->m_App)))
self->Remove ();
}
@@ -181,7 +307,7 @@ void
BamfLauncherIcon::OnUserVisibleChanged (BamfView *view, gboolean visible, gpointer data)
{
BamfLauncherIcon *self = (BamfLauncherIcon *) data;
-
+
if (!bamf_view_is_sticky (BAMF_VIEW (self->m_App)))
self->SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, visible);
}
@@ -191,7 +317,7 @@ BamfLauncherIcon::OnRunningChanged (BamfView *view, gboolean running, gpointer d
{
BamfLauncherIcon *self = (BamfLauncherIcon *) data;
self->SetQuirk (LAUNCHER_ICON_QUIRK_RUNNING, running);
-
+
if (running)
{
self->EnsureWindowState ();
@@ -218,15 +344,17 @@ BamfLauncherIcon::EnsureWindowState ()
{
GList *children, *l;
int count = 0;
-
+
children = bamf_view_get_children (BAMF_VIEW (m_App));
for (l = children; l; l = l->next)
{
if (BAMF_IS_WINDOW (l->data))
count++;
}
-
+
SetRelatedWindows (count);
+
+ g_list_free (children);
}
void
@@ -249,7 +377,8 @@ void
BamfLauncherIcon::UpdateMenus ()
{
GList *children, *l;
-
+ IndicatorDesktopShortcuts *desktop_shortcuts;
+
children = bamf_view_get_children (BAMF_VIEW (m_App));
for (l = children; l; l = l->next)
{
@@ -258,14 +387,65 @@ BamfLauncherIcon::UpdateMenus ()
BamfIndicator *indicator = BAMF_INDICATOR (l->data);
std::string path = bamf_indicator_get_dbus_menu_path (indicator);
-
+
// we already have this
if (_menu_clients.find (path) != _menu_clients.end ())
continue;
-
+
DbusmenuClient *client = dbusmenu_client_new (bamf_indicator_get_remote_address (indicator), path.c_str ());
_menu_clients[path] = client;
}
+
+ g_list_free (children);
+
+ // make a client for desktop file actions
+ if (!DBUSMENU_IS_MENUITEM (_menu_desktop_shortcuts) &&
+ bamf_application_get_desktop_file (m_App) != NULL)
+ {
+
+ DbusmenuMenuitem *root = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_set_root (root, TRUE);
+ desktop_shortcuts = indicator_desktop_shortcuts_new (bamf_application_get_desktop_file (m_App),
+ "Unity");
+ const gchar **nicks = indicator_desktop_shortcuts_get_nicks (desktop_shortcuts);
+
+ int index = 0;
+ if (nicks) {
+ while (((gpointer*) nicks)[index]) {
+ const char* name;
+ DbusmenuMenuitem *item;
+ name = g_strdup (indicator_desktop_shortcuts_nick_get_name (desktop_shortcuts,
+ nicks[index]));
+ ShortcutData *data = g_slice_new0 (ShortcutData);
+ data->self = this;
+ data->shortcuts = INDICATOR_DESKTOP_SHORTCUTS (g_object_ref (desktop_shortcuts));
+ data->nick = g_strdup (nicks[index]);
+
+ item = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_LABEL, name);
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ g_signal_connect_data (item, "item-activated",
+ (GCallback) shortcut_activated, (gpointer) data,
+ (GClosureNotify) shortcut_data_destroy, (GConnectFlags)0);
+
+ dbusmenu_menuitem_child_append (root, item);
+
+ index++;
+
+ g_free ((void *)name);
+ }
+ }
+
+ _menu_desktop_shortcuts = root;
+ }
+
+}
+
+void
+BamfLauncherIcon::OnLaunch (DbusmenuMenuitem *item, int time, BamfLauncherIcon *self)
+{
+ self->OpenInstance ();
}
void
@@ -284,10 +464,13 @@ BamfLauncherIcon::OnQuit (DbusmenuMenuitem *item, int time, BamfLauncherIcon *se
{
guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
CompWindow *window = self->m_Screen->findWindow ((Window) xid);
-
- window->close (self->m_Screen->getCurrentTime ());
+
+ if (window)
+ window->close (self->m_Screen->getCurrentTime ());
}
}
+
+ g_list_free (children);
}
void
@@ -296,86 +479,129 @@ BamfLauncherIcon::OnTogglePin (DbusmenuMenuitem *item, int time, BamfLauncherIco
BamfView *view = BAMF_VIEW (self->m_App);
bool sticky = bamf_view_is_sticky (view);
const gchar *desktop_file = bamf_application_get_desktop_file (self->m_App);
-
+
if (sticky)
{
bamf_view_set_sticky (view, false);
if (bamf_view_is_closed (view))
self->Remove ();
-
+
if (desktop_file && strlen (desktop_file) > 0)
FavoriteStore::GetDefault ()->RemoveFavorite (desktop_file);
}
else
{
bamf_view_set_sticky (view, true);
-
+
if (desktop_file && strlen (desktop_file) > 0)
FavoriteStore::GetDefault ()->AddFavorite (desktop_file, -1); //self->SortPriority ());
}
}
-std::list<DbusmenuMenuitem *>
-BamfLauncherIcon::GetMenus ()
+void
+BamfLauncherIcon::EnsureMenuItemsReady ()
{
- std::map<std::string, DbusmenuClient *>::iterator it;
- std::list<DbusmenuMenuitem *> result;
DbusmenuMenuitem *menu_item;
-
- for (it = _menu_clients.begin (); it != _menu_clients.end (); it++)
+
+ /* Launch */
+ if (_menu_items.find ("Launch") == _menu_items.end ())
{
- GList * child = NULL;
- DbusmenuClient *client = (*it).second;
- DbusmenuMenuitem *root = dbusmenu_client_get_root (client);
-
- for (child = dbusmenu_menuitem_get_children(root); child != NULL; child = g_list_next(child))
- {
- DbusmenuMenuitem *item = (DbusmenuMenuitem *) child->data;
-
- if (!item)
- continue;
-
- result.push_back (item);
- }
+ menu_item = dbusmenu_menuitem_new ();
+ g_object_ref (menu_item);
+
+ dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, "Open New Window");
+ dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+
+ g_signal_connect (menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, (GCallback) &BamfLauncherIcon::OnLaunch, this);
+
+ _menu_items["Launch"] = menu_item;
}
-
+
+ /* Pin */
if (_menu_items.find ("Pin") == _menu_items.end ())
{
menu_item = dbusmenu_menuitem_new ();
g_object_ref (menu_item);
-
+
dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_CHECK);
- dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, "Pin To Launcher");
+ dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, "Keep In Launcher");
dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
-
+
g_signal_connect (menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, (GCallback) &BamfLauncherIcon::OnTogglePin, this);
-
+
_menu_items["Pin"] = menu_item;
}
-
- int checked = !bamf_view_is_sticky (BAMF_VIEW (m_App)) ?
+ int checked = !bamf_view_is_sticky (BAMF_VIEW (m_App)) ?
DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED;
-
- dbusmenu_menuitem_property_set_int (_menu_items["Pin"],
- DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
+
+ dbusmenu_menuitem_property_set_int (_menu_items["Pin"],
+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
checked);
- result.push_back (_menu_items["Pin"]);
-
+
+
+ /* Quit */
if (_menu_items.find ("Quit") == _menu_items.end ())
{
menu_item = dbusmenu_menuitem_new ();
g_object_ref (menu_item);
-
+
dbusmenu_menuitem_property_set (menu_item, DBUSMENU_MENUITEM_PROP_LABEL, "Quit");
dbusmenu_menuitem_property_set_bool (menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
-
+
g_signal_connect (menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, (GCallback) &BamfLauncherIcon::OnQuit, this);
-
+
_menu_items["Quit"] = menu_item;
}
-
- result.push_back (_menu_items["Quit"]);
-
+}
+
+std::list<DbusmenuMenuitem *>
+BamfLauncherIcon::GetMenus ()
+{
+ std::map<std::string, DbusmenuClient *>::iterator it;
+ std::list<DbusmenuMenuitem *> result;
+
+ for (it = _menu_clients.begin (); it != _menu_clients.end (); it++)
+ {
+ GList * child = NULL;
+ DbusmenuClient *client = (*it).second;
+ DbusmenuMenuitem *root = dbusmenu_client_get_root (client);
+
+ for (child = dbusmenu_menuitem_get_children(root); child != NULL; child = g_list_next(child))
+ {
+ DbusmenuMenuitem *item = (DbusmenuMenuitem *) child->data;
+
+ if (!item)
+ continue;
+
+ result.push_back (item);
+ }
+ }
+
+ if (DBUSMENU_IS_MENUITEM (_menu_desktop_shortcuts))
+ {
+ GList * child = NULL;
+ DbusmenuMenuitem *root = _menu_desktop_shortcuts;
+
+ for (child = dbusmenu_menuitem_get_children(root); child != NULL; child = g_list_next(child))
+ {
+ DbusmenuMenuitem *item = (DbusmenuMenuitem *) child->data;
+
+ if (!item)
+ continue;
+
+ result.push_back (item);
+ }
+
+ }
+
+ EnsureMenuItemsReady ();
+
+ result.push_back (_menu_items["Launch"]);
+ result.push_back (_menu_items["Pin"]);
+
+ if (bamf_view_is_running (BAMF_VIEW (m_App)))
+ result.push_back (_menu_items["Quit"]);
+
return result;
}
@@ -401,15 +627,17 @@ BamfLauncherIcon::UpdateIconGeometries (nux::Point3 center)
if (BAMF_IS_WINDOW (view))
{
guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
-
+
XChangeProperty (m_Screen->dpy (), xid, Atoms::wmIconGeometry,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) data, 4);
}
}
+
+ g_list_free (children);
}
-void
+void
BamfLauncherIcon::OnCenterStabilized (nux::Point3 center)
{
UpdateIconGeometries (center);
diff --git a/src/BamfLauncherIcon.h b/src/BamfLauncherIcon.h
index 22ea7c656..0dd30847e 100644
--- a/src/BamfLauncherIcon.h
+++ b/src/BamfLauncherIcon.h
@@ -37,26 +37,36 @@ class BamfLauncherIcon : public SimpleLauncherIcon
public:
BamfLauncherIcon(Launcher* IconManager, BamfApplication *app, CompScreen *screen);
~BamfLauncherIcon();
-
-
+
+
protected:
void OnMouseClick (int button);
std::list<DbusmenuMenuitem *> GetMenus ();
-
+
void UpdateIconGeometries (nux::Point3 center);
void OnCenterStabilized (nux::Point3 center);
-
+
bool IconOwnsWindow (Window w);
+ void AddProperties (GVariantBuilder *builder);
+
private:
BamfApplication *m_App;
CompScreen *m_Screen;
std::map<std::string, DbusmenuClient *> _menu_clients;
std::map<std::string, DbusmenuMenuitem *> _menu_items;
-
+ DbusmenuMenuitem *_menu_desktop_shortcuts;
+
void EnsureWindowState ();
+
void UpdateMenus ();
-
+
+ void OpenInstance ();
+ void Focus ();
+ void Spread ();
+
+ void EnsureMenuItemsReady ();
+
static void OnClosed (BamfView *view, gpointer data);
static void OnUserVisibleChanged (BamfView *view, gboolean visible, gpointer data);
static void OnActiveChanged (BamfView *view, gboolean active, gpointer data);
@@ -64,7 +74,8 @@ private:
static void OnUrgentChanged (BamfView *view, gboolean urgent, gpointer data);
static void OnChildAdded (BamfView *view, BamfView *child, gpointer data);
static void OnChildRemoved (BamfView *view, BamfView *child, gpointer data);
-
+
+ static void OnLaunch (DbusmenuMenuitem *item, int time, BamfLauncherIcon *self);
static void OnQuit (DbusmenuMenuitem *item, int time, BamfLauncherIcon *self);
static void OnTogglePin (DbusmenuMenuitem *item, int time, BamfLauncherIcon *self);
};
diff --git a/src/IndicatorObjectFactory.h b/src/IndicatorObjectFactory.h
index 1a9a9b7bc..c267a5b2e 100644
--- a/src/IndicatorObjectFactory.h
+++ b/src/IndicatorObjectFactory.h
@@ -37,10 +37,14 @@ public:
// Indicators (probably though a bunch of removed/added events)
virtual void ForceRefresh () = 0;
+ // For adding factory-specific properties
+ virtual void AddProperties (GVariantBuilder *builder) = 0;
+
// Signals
sigc::signal<void, IndicatorObjectProxy *> OnObjectAdded;
sigc::signal<void, IndicatorObjectProxy *> OnObjectRemoved;
sigc::signal<void, int, int> OnMenuPointerMoved;
+ sigc::signal<void, const char *> OnEntryActivateRequest;
protected:
std::vector<IndicatorObjectProxy *>_indicators;
diff --git a/src/IndicatorObjectFactoryRemote.cpp b/src/IndicatorObjectFactoryRemote.cpp
index 229fe5e25..b45efc13e 100644
--- a/src/IndicatorObjectFactoryRemote.cpp
+++ b/src/IndicatorObjectFactoryRemote.cpp
@@ -230,6 +230,12 @@ IndicatorObjectFactoryRemote::OnEntryActivated (const char *entry_id)
}
}
+void
+IndicatorObjectFactoryRemote::OnEntryActivateRequestReceived (const gchar *entry_id)
+{
+ OnEntryActivateRequest.emit (entry_id);
+}
+
IndicatorObjectProxyRemote *
IndicatorObjectFactoryRemote::IndicatorForID (const char *id)
{
@@ -320,6 +326,27 @@ IndicatorObjectFactoryRemote::Sync (GVariant *args)
g_variant_iter_free (iter);
}
+void
+IndicatorObjectFactoryRemote::AddProperties (GVariantBuilder *builder)
+{
+ gchar *name = NULL;
+ gchar *uname = NULL;
+
+ g_object_get (_proxy,
+ "g-name", &name,
+ "g-name-owner", &uname,
+ NULL);
+
+ g_variant_builder_add (builder, "{sv}", "backend", g_variant_new_string ("remote"));
+ g_variant_builder_add (builder, "{sv}", "service-name", g_variant_new_string (name));
+ g_variant_builder_add (builder, "{sv}", "service-unique-name", g_variant_new_string (uname));
+ g_variant_builder_add (builder, "{sv}", "using-local-service", g_variant_new_boolean (g_getenv ("PANEL_USE_LOCAL_SERVICE") == NULL ? FALSE : TRUE));
+
+ g_free (name);
+ g_free (uname);
+}
+
+
//
// C callbacks, they just link to class methods and aren't interesting
//
@@ -415,6 +442,10 @@ on_proxy_signal_received (GDBusProxy *proxy,
{
remote->OnEntryActivated (g_variant_get_string (g_variant_get_child_value (parameters, 0), NULL));
}
+ else if (g_strcmp0 (signal_name, "EntryActivateRequest") == 0)
+ {
+ remote->OnEntryActivateRequestReceived (g_variant_get_string (g_variant_get_child_value (parameters, 0), NULL));
+ }
else if (g_strcmp0 (signal_name, "ReSync") == 0)
{
const gchar *id = g_variant_get_string (g_variant_get_child_value (parameters, 0), NULL);
diff --git a/src/IndicatorObjectFactoryRemote.h b/src/IndicatorObjectFactoryRemote.h
index 0097d2d70..f32bc3fe5 100644
--- a/src/IndicatorObjectFactoryRemote.h
+++ b/src/IndicatorObjectFactoryRemote.h
@@ -42,6 +42,9 @@ public:
void OnEntryActivated (const char *entry_id);
void OnShowMenuRequestReceived (const char *id, int x, int y, guint timestamp, guint32 button);
void Sync (GVariant *args);
+ void OnEntryActivateRequestReceived (const char *entry_id);
+
+ void AddProperties (GVariantBuilder *builder);
private:
IndicatorObjectProxyRemote* IndicatorForID (const char *id);
diff --git a/src/Introspectable.cpp b/src/Introspectable.cpp
index c64e08a50..a0d39e820 100644
--- a/src/Introspectable.cpp
+++ b/src/Introspectable.cpp
@@ -21,31 +21,39 @@
GVariant*
Introspectable::Introspect ()
{
- GVariant *result;
- GVariant *childResults;
GVariantBuilder *builder;
+ GVariant *result;
+ GVariantBuilder *child_builder;
+ gint n_children = 0;
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+
+ AddProperties (builder);
+
+ child_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+
for (std::list<Introspectable *>::iterator it = _children.begin (); it != _children.end (); it++)
{
- g_variant_builder_add (builder, "{sv}", (*it)->GetName (), (*it)->Introspect () );
+ if ((*it)->GetName ())
+ {
+ g_variant_builder_add (child_builder, "{sv}", (*it)->GetName (), (*it)->Introspect () );
+ n_children++;
+ }
}
- AddProperties (builder);
- childResults = g_variant_new ("(a{sv})", builder);
- g_variant_builder_unref (builder);
+ if (n_children > 0)
+ {
+ GVariant *child_results;
- if (_children.size () > 0)
- {
- builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}") );
- g_variant_builder_add (builder, "{sv}", GetName (), childResults);
- result = g_variant_new ("(a{sv})", builder);
- g_variant_builder_unref (builder);
+ child_results = g_variant_new ("(a{sv})", child_builder);
+ g_variant_builder_add (builder, "{sv}", GetChildsName (), child_results);
+ }
+ g_variant_builder_unref (child_builder);
- return result;
- }
+ result = g_variant_new ("(a{sv})", builder);
+ g_variant_builder_unref (builder);
- return childResults;
+ return result;
}
void
@@ -58,4 +66,10 @@ void
Introspectable::RemoveChild (Introspectable *child)
{
_children.remove (child);
-} \ No newline at end of file
+}
+
+const gchar *
+Introspectable::GetChildsName ()
+{
+ return GetName ();
+}
diff --git a/src/Introspectable.h b/src/Introspectable.h
index c2182025b..5c58b2a7b 100644
--- a/src/Introspectable.h
+++ b/src/Introspectable.h
@@ -31,6 +31,7 @@ public:
protected:
virtual const gchar *GetName () = 0;
+ virtual const gchar *GetChildsName ();
virtual void AddProperties (GVariantBuilder *builder) = 0;
/*
* AddProperties should be implemented as such ...
@@ -51,4 +52,4 @@ private:
std::list<Introspectable *> _children;
};
-#endif \ No newline at end of file
+#endif
diff --git a/src/IntrospectionDBusInterface.cpp b/src/IntrospectionDBusInterface.cpp
index 7e8a1693b..423529e0f 100644
--- a/src/IntrospectionDBusInterface.cpp
+++ b/src/IntrospectionDBusInterface.cpp
@@ -18,7 +18,7 @@
#include "IntrospectionDBusInterface.h"
-#define UNITY_STATE_DEBUG_BUS_NAME "com.canonical.Unity.Debug"
+#define UNITY_STATE_DEBUG_BUS_NAME "com.canonical.Unity"
void DBusMethodCall (GDBusConnection*, const gchar*, const gchar*,
const gchar*, const gchar*, GVariant*,
@@ -220,4 +220,4 @@ IntrospectionDBusInterface::BuildFakeReturn ()
gchar *s = g_variant_print (result, TRUE);
g_free (s);
return result;
-} \ No newline at end of file
+}
diff --git a/src/Launcher.cpp b/src/Launcher.cpp
index 9067b5fa6..e0058c602 100644
--- a/src/Launcher.cpp
+++ b/src/Launcher.cpp
@@ -1,1867 +1,1973 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authored by: Jason Smith <jason.smith@canonical.com>
- * Authored by: Jay Taoko <jay.taoko@canonical.com>
- */
-
-#include <math.h>
-
-#include "Nux/Nux.h"
-#include "Nux/VScrollBar.h"
-#include "Nux/HLayout.h"
-#include "Nux/VLayout.h"
-#include "Nux/MenuPage.h"
-
-#include "NuxGraphics/NuxGraphics.h"
-#include "NuxGraphics/GpuDevice.h"
-#include "NuxGraphics/GLTextureResourceManager.h"
-
-#include "Nux/BaseWindow.h"
-#include "Nux/WindowCompositor.h"
-
-#include "Launcher.h"
-#include "LauncherIcon.h"
-#include "LauncherModel.h"
-#include "QuicklistView.h"
-
-#define ANIM_DURATION_SHORT 125
-#define ANIM_DURATION 200
-#define ANIM_DURATION_LONG 350
-
-#define URGENT_BLINKS 3
-
-#define MAX_STARTING_BLINKS 5
-#define STARTING_BLINK_LAMBDA 3
-
-#define BACKLIGHT_STRENGTH 0.9f
-
-int
-TimeDelta (struct timespec *x, struct timespec *y)
-{
- return ((x->tv_sec - y->tv_sec) * 1000) + ((x->tv_nsec - y->tv_nsec) / 1000000);
-}
-
-static bool USE_ARB_SHADERS = true;
-/*
- Use this shader to pass vertices in screen coordinates in the C++ code and compute use
- the fragment shader to perform the texture perspective correct division.
- This shader assume the following:
- - the projection matrix is orthogonal: glOrtho(0, ScreenWidth, ScreenWidth, 0, Near, Far)
- - vertices x and y are in screen coordinates: Vertex(x_screen, y_screen, 0, 1.0)
- - the vertices w coordinates has been computed 'manually'
- - vertices uv textture coordinates are passed to the shader as: (u/w, v/w, 0, 1/w)
-
- The texture coordinates s=u/w, t=v/w and q=1w are interpolated linearly in screen coordinates.
- In the fragment shader we get the texture coordinates used for the sampling by dividing
- s and t resulting from the interpolation by q.
-
- */
-
-nux::NString gPerspectiveCorrectShader = TEXT (
-"[Vertex Shader] \n\
-#version 120 \n\
-uniform mat4 ViewProjectionMatrix; \n\
- \n\
-attribute vec4 iColor; \n\
-attribute vec4 iTexCoord0; \n\
-attribute vec4 iVertex; \n\
- \n\
-varying vec4 varyTexCoord0; \n\
-varying vec4 varyVertexColor; \n\
- \n\
-void main() \n\
-{ \n\
- varyTexCoord0 = iTexCoord0; \n\
- varyVertexColor = iColor; \n\
- gl_Position = ViewProjectionMatrix * iVertex; \n\
-} \n\
- \n\
-[Fragment Shader] \n\
-#version 120 \n\
-#extension GL_ARB_texture_rectangle : enable \n\
- \n\
-varying vec4 varyTexCoord0; \n\
-varying vec4 varyVertexColor; \n\
- \n\
-uniform sampler2D TextureObject0; \n\
-uniform vec4 color0; \n\
-vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\
-{ \n\
- return texture2D(TexObject, TexCoord.st); \n\
-} \n\
- \n\
-void main() \n\
-{ \n\
- vec4 tex = varyTexCoord0; \n\
- tex.s = tex.s/varyTexCoord0.w; \n\
- tex.t = tex.t/varyTexCoord0.w; \n\
- \n\
- vec4 texel = SampleTexture(TextureObject0, tex); \n\
- gl_FragColor = texel*varyVertexColor; \n\
-} \n\
-");
-
-nux::NString PerspectiveCorrectVtx = TEXT (
- "!!ARBvp1.0 \n\
- ATTRIB iPos = vertex.position; \n\
- ATTRIB iColor = vertex.attrib[3]; \n\
- PARAM mvp[4] = {state.matrix.mvp}; \n\
- OUTPUT oPos = result.position; \n\
- OUTPUT oColor = result.color; \n\
- OUTPUT oTexCoord0 = result.texcoord[0]; \n\
- # Transform the vertex to clip coordinates. \n\
- DP4 oPos.x, mvp[0], iPos; \n\
- DP4 oPos.y, mvp[1], iPos; \n\
- DP4 oPos.z, mvp[2], iPos; \n\
- DP4 oPos.w, mvp[3], iPos; \n\
- MOV oColor, iColor; \n\
- MOV oTexCoord0, vertex.attrib[8]; \n\
- END");
-
-
-
-nux::NString PerspectiveCorrectTexFrg = TEXT (
- "!!ARBfp1.0 \n\
- PARAM color0 = program.local[0]; \n\
- TEMP temp; \n\
- TEMP pcoord; \n\
- TEMP tex0; \n\
- TEMP temp1; \n\
- TEMP recip; \n\
- MOV pcoord, fragment.texcoord[0].w; \n\
- RCP temp, fragment.texcoord[0].w; \n\
- MUL pcoord.xy, fragment.texcoord[0], temp; \n\
- TEX tex0, pcoord, texture[0], 2D; \n\
- MUL result.color, color0, tex0; \n\
- END");
-
-nux::NString PerspectiveCorrectTexRectFrg = TEXT (
- "!!ARBfp1.0 \n\
- PARAM color0 = program.local[0]; \n\
- TEMP temp; \n\
- TEMP pcoord; \n\
- TEMP tex0; \n\
- MOV pcoord, fragment.texcoord[0].w; \n\
- RCP temp, fragment.texcoord[0].w; \n\
- MUL pcoord.xy, fragment.texcoord[0], temp; \n\
- TEX tex0, pcoord, texture[0], RECT; \n\
- MUL result.color, color0, tex0; \n\
- END");
-
-static void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
- int ViewportWidth,
- int ViewportHeight,
- float NearClipPlane,
- float FarClipPlane,
- float Fovy);
-
-Launcher::Launcher(nux::BaseWindow *parent, NUX_FILE_LINE_DECL)
-: View(NUX_FILE_LINE_PARAM)
-, m_ContentOffsetY(0)
-, m_RunningIndicator(0)
-, m_ActiveIndicator(0)
-, m_BackgroundLayer(0)
-, _model (0)
-{
- _parent = parent;
- _active_quicklist = 0;
-
- m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
-
- OnMouseDown.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
- OnMouseUp.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
- OnMouseDrag.connect(sigc::mem_fun(this, &Launcher::RecvMouseDrag));
- OnMouseEnter.connect(sigc::mem_fun(this, &Launcher::RecvMouseEnter));
- OnMouseLeave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave));
- OnMouseMove.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove));
- OnMouseWheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel));
-
- m_ActiveTooltipIcon = NULL;
- m_ActiveMenuIcon = NULL;
-
- SetCompositionLayout(m_Layout);
-
- if(!USE_ARB_SHADERS)
- {
- _shader_program_uv_persp_correction = nux::GetThreadGLDeviceFactory()->CreateShaderProgram();
- _shader_program_uv_persp_correction->LoadIShader(gPerspectiveCorrectShader.GetTCharPtr());
- _shader_program_uv_persp_correction->Link();
- }
- else
- {
- _AsmShaderProg = nux::GetThreadGLDeviceFactory()->CreateAsmShaderProgram();
- _AsmShaderProg->LoadVertexShader (TCHAR_TO_ANSI (*PerspectiveCorrectVtx) );
-
- if ((nux::GetThreadGLDeviceFactory()->SUPPORT_GL_ARB_TEXTURE_NON_POWER_OF_TWO() == false) &&
- (nux::GetThreadGLDeviceFactory()->SUPPORT_GL_EXT_TEXTURE_RECTANGLE () || nux::GetThreadGLDeviceFactory()->SUPPORT_GL_ARB_TEXTURE_RECTANGLE ()))
- {
- // No support for non power of two textures but support for rectangle textures
- _AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexRectFrg) );
- }
- else
- {
- _AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexFrg) );
- }
-
- _AsmShaderProg->Link();
- }
-
- _folded_angle = 1.0f;
- _neg_folded_angle = -1.0f;
- _space_between_icons = 5;
- _launcher_top_y = 0;
- _launcher_bottom_y = 0;
- _folded_z_distance = 10.0f;
- _launcher_state = LAUNCHER_FOLDED;
- _launcher_action_state = ACTION_NONE;
- _icon_under_mouse = NULL;
- _icon_mouse_down = NULL;
- _icon_image_size = 48;
- _icon_glow_size = 62;
- _icon_image_size_delta = 6;
- _icon_size = _icon_image_size + _icon_image_size_delta;
-
- _icon_bkg_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_corner_54x54.png");
- _icon_outline_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_outline_54x54.png");
- _icon_shine_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_shine_54x54.png");
- _icon_glow_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_glow_62x62.png");
- _icon_2indicator = nux::CreateTextureFromFile (PKGDATADIR"/2indicate_54x54.png");
- _icon_3indicator = nux::CreateTextureFromFile (PKGDATADIR"/3indicate_54x54.png");
- _icon_4indicator = nux::CreateTextureFromFile (PKGDATADIR"/4indicate_54x54.png");
-
- _enter_y = 0;
- _dnd_security = 15;
- _dnd_delta = 0;
- _anim_handle = 0;
- _autohide_handle = 0;
- _floating = false;
- _hovered = false;
- _autohide = false;
- _hidden = false;
- _mouse_inside_launcher = false;
-
- // 0 out timers to avoid wonky startups
- _enter_time.tv_sec = 0;
- _enter_time.tv_nsec = 0;
- _exit_time.tv_sec = 0;
- _exit_time.tv_nsec = 0;
- _drag_end_time.tv_sec = 0;
- _drag_end_time.tv_nsec = 0;
- _autohide_time.tv_sec = 0;
- _autohide_time.tv_nsec = 0;
-}
-
-Launcher::~Launcher()
-{
-
-}
-
-/* Render Layout Logic */
-
-float Launcher::GetHoverProgress ()
-{
- struct timespec current;
- clock_gettime (CLOCK_MONOTONIC, &current);
-
- if (_hovered)
- return CLAMP ((float) (TimeDelta (&current, &_enter_time)) / (float) ANIM_DURATION, 0.0f, 1.0f);
- else
- return 1.0f - CLAMP ((float) (TimeDelta (&current, &_exit_time)) / (float) ANIM_DURATION, 0.0f, 1.0f);
-}
-
-float Launcher::DnDExitProgress ()
-{
- struct timespec current;
- clock_gettime (CLOCK_MONOTONIC, &current);
-
- return 1.0f - CLAMP ((float) (TimeDelta (&current, &_drag_end_time)) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
-}
-
-float Launcher::AutohideProgress ()
-{
- if (!_autohide)
- return 0.0f;
-
- struct timespec current;
- clock_gettime (CLOCK_MONOTONIC, &current);
-
- if (_hidden)
- return CLAMP ((float) (TimeDelta (&current, &_autohide_time)) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
- else
- return 1.0f - CLAMP ((float) (TimeDelta (&current, &_autohide_time)) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
-}
-
-gboolean Launcher::AnimationTimeout (gpointer data)
-{
- Launcher *self = (Launcher*) data;
-
- self->NeedRedraw ();
-
- if (self->AnimationInProgress ())
- return true;
-
- // zero out handle so we know we are done
- self->_anim_handle = 0;
- return false;
-}
-
-void Launcher::EnsureAnimation ()
-{
- if (_anim_handle)
- return;
-
- NeedRedraw ();
-
- if (AnimationInProgress ())
- _anim_handle = g_timeout_add (1000 / 60 - 1, &Launcher::AnimationTimeout, this);
-}
-
-bool Launcher::IconNeedsAnimation (LauncherIcon *icon, struct timespec current)
-{
- struct timespec time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
- if (TimeDelta (&current, &time) < ANIM_DURATION_SHORT)
- return true;
-
- time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_RUNNING);
- if (TimeDelta (&current, &time) < ANIM_DURATION_SHORT)
- return true;
-
- time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
- if (TimeDelta (&current, &time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2))
- return true;
-
- time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_URGENT);
- if (TimeDelta (&current, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2))
- return true;
-
- time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
- if (TimeDelta (&current, &time) < ANIM_DURATION)
- return true;
-
- time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_SHIMMER);
- if (TimeDelta (&current, &time) < ANIM_DURATION_LONG)
- return true;
-
- return false;
-}
-
-bool Launcher::AnimationInProgress ()
-{
- // performance here can be improved by caching the longer remaining animation found and short circuiting to that each time
- // this way extra checks may be avoided
-
- // short circuit to avoid unneeded calculations
- struct timespec current;
- clock_gettime (CLOCK_MONOTONIC, &current);
-
- // hover in animation
- if (TimeDelta (&current, &_enter_time) < ANIM_DURATION)
- return true;
-
- // hover out animation
- if (TimeDelta (&current, &_exit_time) < ANIM_DURATION)
- return true;
-
- // drag end animation
- if (TimeDelta (&current, &_drag_end_time) < ANIM_DURATION_LONG)
- return true;
-
- if (TimeDelta (&current, &_autohide_time) < ANIM_DURATION_SHORT)
- return true;
-
- // animations happening on specific icons
- LauncherModel::iterator it;
- for (it = _model->begin (); it != _model->end (); it++)
- if (IconNeedsAnimation (*it, current))
- return true;
-
- return false;
-}
-
-void Launcher::SetTimeStruct (struct timespec *timer, struct timespec *sister, int sister_relation)
-{
- struct timespec current;
- clock_gettime (CLOCK_MONOTONIC, &current);
-
- if (sister)
- {
- int diff = TimeDelta (&current, sister);
-
- if (diff < sister_relation)
- {
- int remove = sister_relation - diff;
- current.tv_sec -= remove / 1000;
- remove = remove % 1000;
-
- if (remove > current.tv_nsec / 1000000)
- {
- current.tv_sec--;
- current.tv_nsec += 1000000000;
- }
- current.tv_nsec -= remove * 1000000;
- }
- }
-
- timer->tv_sec = current.tv_sec;
- timer->tv_nsec = current.tv_nsec;
-}
-
-float IconVisibleProgress (LauncherIcon *icon, struct timespec current)
-{
- if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
- {
- struct timespec icon_visible_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
- int enter_ms = TimeDelta (&current, &icon_visible_time);
- return CLAMP ((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
- }
- else
- {
- struct timespec icon_hide_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
- int hide_ms = TimeDelta (&current, &icon_hide_time);
- return 1.0f - CLAMP ((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
- }
-}
-
-void Launcher::SetDndDelta (float x, float y, nux::Geometry geo, struct timespec current)
-{
- LauncherIcon *anchor = 0;
- LauncherModel::iterator it;
- anchor = MouseIconIntersection (x, _enter_y);
-
- if (anchor)
- {
- float position = y;
- for (it = _model->begin (); it != _model->end (); it++)
- {
- if (*it == anchor)
- {
- position += _icon_size / 2;
- _dnd_delta = _enter_y - position;
-
- if (position + _icon_size / 2 + _dnd_delta > geo.height)
- _dnd_delta -= (position + _icon_size / 2 + _dnd_delta) - geo.height;
-
- break;
- }
- position += (_icon_size + _space_between_icons) * IconVisibleProgress (*it, current);
- }
- }
-}
-
-float Launcher::IconPresentProgress (LauncherIcon *icon, struct timespec current)
-{
- struct timespec icon_present_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
- int ms = TimeDelta (&current, &icon_present_time);
- float result = CLAMP ((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
-
- if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
- return result;
- else
- return 1.0f - result;
-}
-
-float Launcher::IconUrgentProgress (LauncherIcon *icon, struct timespec current)
-{
- struct timespec urgent_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_URGENT);
- int urgent_ms = TimeDelta (&current, &urgent_time);
- float result = CLAMP ((float) urgent_ms / (float) (ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
-
- if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
- return result;
- else
- return 1.0f - result;
-}
-
-float Launcher::IconShimmerProgress (LauncherIcon *icon, struct timespec current)
-{
- struct timespec shimmer_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_SHIMMER);
- int shimmer_ms = TimeDelta (&current, &shimmer_time);
- return CLAMP ((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
-}
-
-float Launcher::IconUrgentPulseValue (LauncherIcon *icon, struct timespec current)
-{
- if (!icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
- return 1.0f; // we are full on in a normal condition
-
- double urgent_progress = (double) IconUrgentProgress (icon, current);
- return 0.5f + (float) (std::cos (M_PI * (float) (URGENT_BLINKS * 2) * urgent_progress)) * 0.5f;
-}
-
-float Launcher::IconStartingPulseValue (LauncherIcon *icon, struct timespec current)
-{
- struct timespec starting_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
- int starting_ms = TimeDelta (&current, &starting_time);
- double starting_progress = (double) CLAMP ((float) starting_ms / (float) (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f);
-
- return 1.0f - (0.5f + (float) (std::cos (M_PI * (float) (MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
-}
-
-float Launcher::IconBackgroundIntensity (LauncherIcon *icon, struct timespec current)
-{
- float result = 0.0f;
- struct timespec running_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_RUNNING);
- int running_ms = TimeDelta (&current, &running_time);
- float running_progress = CLAMP ((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
-
- // After we finish a fade in from running, we can reset the quirk
- if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING) && running_progress == 1.0f)
- icon->ResetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
-
- result = IconStartingPulseValue (icon, current) * BACKLIGHT_STRENGTH;
-
- if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
- {
- // running progress fades in whatever the pulsing did not fill in already
- result += running_progress * (BACKLIGHT_STRENGTH - result);
-
- // urgent serves to bring the total down only
- if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
- result *= 0.2f + 0.8f * IconUrgentPulseValue (icon, current);
- }
- else
- {
- // modestly evil
- result += BACKLIGHT_STRENGTH - running_progress * BACKLIGHT_STRENGTH;
- }
-
- return result;
-}
-
-void Launcher::SetupRenderArg (LauncherIcon *icon, struct timespec current, RenderArg &arg)
-{
- arg.icon = icon;
- arg.alpha = 1.0f;
- arg.running_arrow = false;
- arg.active_arrow = icon->GetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE);
- arg.folding_rads = 0.0f;
- arg.skip = false;
-
- arg.window_indicators = MIN (4, icon->RelatedWindows ());
-
- // we dont need to show strays
- if (arg.window_indicators == 1 || !icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
- arg.window_indicators = 0;
-
- arg.backlight_intensity = IconBackgroundIntensity (icon, current);
- arg.shimmer_progress = IconShimmerProgress (icon, current);
-
- float urgent_progress = IconUrgentProgress (icon, current);
- urgent_progress = CLAMP (urgent_progress * 3, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
- arg.glow_intensity = urgent_progress;
-}
-
-void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
- std::list<Launcher::RenderArg> &shelf_args,
- nux::Geometry &box_geo, nux::Geometry &shelf_geo)
-{
- nux::Geometry geo = GetGeometry ();
- LauncherModel::iterator it;
- nux::Point3 center;
- float hover_progress = GetHoverProgress ();
- float folded_z_distance = _folded_z_distance * (1.0f - hover_progress);
- float animation_neg_rads = _neg_folded_angle * (1.0f - hover_progress);
- int vertical_offset = _parent->GetGeometry ().y;
- struct timespec current;
- clock_gettime (CLOCK_MONOTONIC, &current);
-
- float folding_constant = 0.25f;
- float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress);
-
- int folded_size = (int) (_icon_size * folding_not_constant);
- int folded_spacing = (int) (_space_between_icons * folding_not_constant);
-
- center.x = geo.width / 2;
- center.y = _space_between_icons;
- center.z = 0;
-
- // compute required height of shelf
- float shelf_sum = 0.0f;
- for (it = _model->shelf_begin (); it != _model->shelf_end (); it++)
- {
- float height = (_icon_size + _space_between_icons) * IconVisibleProgress (*it, current);
- shelf_sum += height;
- }
-
- // add bottom padding
- if (shelf_sum > 0.0f)
- shelf_sum += _space_between_icons;
-
- int launcher_height = geo.height - shelf_sum;
-
- // compute required height of launcher AND folding threshold
- float sum = 0.0f + center.y;
- int folding_threshold = launcher_height - _icon_size / 2.5f;
- for (it = _model->begin (); it != _model->end (); it++)
- {
- float height = (_icon_size + _space_between_icons) * IconVisibleProgress (*it, current);
- sum += height;
-
- // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";
- float magic_constant = 1.2f;
-
- float present_progress = IconPresentProgress (*it, current);
- folding_threshold -= CLAMP (sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * present_progress);
- }
-
- // this happens on hover, basically its a flag and a value in one, we translate this into a dnd offset
- if (_enter_y != 0 && _enter_y + _icon_size / 2 > folding_threshold)
- SetDndDelta (center.x, center.y, nux::Geometry (geo.x, geo.y, geo.width, geo.height - shelf_sum), current);
-
- _enter_y = 0;
-
- if (hover_progress > 0.0f && _dnd_delta != 0)
- {
- int delta_y = _dnd_delta;
-
- // logically dnd exit only restores to the clamped ranges
- // hover_progress restores to 0
-
- if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
- {
- float dnd_progress = DnDExitProgress ();
-
- float max = 0.0f;
- float min = MIN (0.0f, launcher_height - sum);
-
- if (_dnd_delta > max)
- delta_y = max + (delta_y - max) * dnd_progress;
- else if (_dnd_delta < min)
- delta_y = min + (delta_y - min) * dnd_progress;
-
- if (dnd_progress == 0.0f)
- _dnd_delta = (int) delta_y;
- }
-
- delta_y *= hover_progress;
- center.y += delta_y;
- }
- else
- {
- _dnd_delta = 0;
- }
-
- float autohide_progress = AutohideProgress ();
- float autohide_offset = 0.0f;
- if (_autohide && autohide_progress > 0.0f)
- {
- autohide_offset -= geo.width * autohide_progress;
- }
-
- // Inform the painter where to paint the box
- box_geo = geo;
-
- if (_floating)
- box_geo.height = sum + shelf_sum + _space_between_icons;
-
- if (_autohide)
- box_geo.x += autohide_offset;
-
- shelf_geo = nux::Geometry (box_geo.x, box_geo.height - shelf_sum, box_geo.width, shelf_sum);
-
- // 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->begin (); it != _model->end (); it++)
- {
- RenderArg arg;
- LauncherIcon *icon = *it;
-
- SetupRenderArg (icon, current, arg);
-
- // reset z
- center.z = 0;
-
- float size_modifier = IconVisibleProgress (icon, current);
- if (size_modifier < 1.0f)
- {
- arg.alpha = size_modifier;
- center.z = 300.0f * (1.0f - size_modifier);
- }
-
- if (size_modifier <= 0.0f)
- {
- arg.skip = true;
- continue;
- }
-
- // goes for 0.0f when fully unfolded, to 1.0f folded
- float folding_progress = CLAMP ((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
- float present_progress = IconPresentProgress (icon, current);
-
- folding_progress *= 1.0f - present_progress;
-
- float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
-
- float icon_hide_offset = autohide_offset;
-
- if (icon->PresentUrgency () == 1)
- icon_hide_offset *= 0.5f + 0.5f * (1.0f - present_progress);
- else if (icon->PresentUrgency () >= 2)
- icon_hide_offset *= 1.0f - present_progress;
-
- // icon is crossing threshold, start folding
- center.z += folded_z_distance * folding_progress;
- arg.folding_rads = animation_neg_rads * folding_progress;
-
- center.y += half_size * size_modifier; // move to center
- arg.center = nux::Point3 (center.x + icon_hide_offset, center.y, center.z); // copy center
- icon->SetCenter (nux::Point3 (center.x, center.y + vertical_offset, center.z));
- center.y += half_size * size_modifier; // move to end
-
- float spacing_overlap = CLAMP ((float) (center.y + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
- //add spacing
- center.y += (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
-
- launcher_args.push_back (arg);
- }
-
- center.y = (box_geo.y + box_geo.height) - shelf_sum + _space_between_icons;
-
- // Place shelf icons
- for (it = _model->shelf_begin (); it != _model->shelf_end (); it++)
- {
- RenderArg arg;
- LauncherIcon *icon = *it;
-
- SetupRenderArg (icon, current, arg);
-
- // reset z
- center.z = 0;
-
- float size_modifier = IconVisibleProgress (icon, current);
- if (size_modifier < 1.0f)
- {
- arg.alpha = size_modifier;
- center.z = 300.0f * (1.0f - size_modifier);
- }
-
- if (size_modifier <= 0.0f)
- {
- arg.skip = true;
- continue;
- }
-
- float half_size = _icon_size / 2.0f;
-
- center.y += half_size * size_modifier; // move to center
- arg.center = nux::Point3 (center.x + autohide_offset, center.y, center.z); // copy center
- icon->SetCenter (nux::Point3 (center.x, center.y + vertical_offset, center.z));
- center.y += half_size * size_modifier; // move to end
- center.y += _space_between_icons * size_modifier;
-
- shelf_args.push_back (arg);
- }
-}
-
-/* End Render Layout Logic */
-
-void Launcher::SetHidden (bool hidden)
-{
- if (hidden == _hidden)
- return;
-
- _hidden = hidden;
- SetTimeStruct (&_autohide_time, &_autohide_time, ANIM_DURATION);
-
- _parent->EnableInputWindow(!hidden);
-
- EnsureAnimation ();
-}
-
-gboolean Launcher::OnAutohideTimeout (gpointer data)
-{
- Launcher *self = (Launcher*) data;
-
- if (self->_hovered || self->_hidden)
- return false;
-
- self->SetHidden (true);
-
- self->_autohide_handle = 0;
- return false;
-}
-
-void Launcher::OnTriggerMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- if (!_autohide || !_hidden)
- return;
-
- SetHidden (false);
-}
-
-void Launcher::SetupAutohideTimer ()
-{
- if (_autohide)
- {
- if (_autohide_handle > 0)
- g_source_remove (_autohide_handle);
- _autohide_handle = g_timeout_add (1000, &Launcher::OnAutohideTimeout, this);
- }
-}
-
-void Launcher::OnTriggerMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- SetupAutohideTimer ();
-}
-
-bool Launcher::AutohideEnabled ()
-{
- return _autohide;
-}
-
-gboolean Launcher::StrutHack (gpointer data)
-{
- Launcher *self = (Launcher *) data;
- self->_parent->InputWindowEnableStruts(false);
- self->_parent->InputWindowEnableStruts(true);
-
- return false;
-}
-
-void Launcher::SetAutohide (bool autohide, nux::View *trigger)
-{
- if (_autohide == autohide)
- return;
-
- if (autohide)
- {
- _parent->InputWindowEnableStruts(false);
- _autohide_trigger = trigger;
- _autohide_trigger->OnMouseEnter.connect (sigc::mem_fun(this, &Launcher::OnTriggerMouseEnter));
- _autohide_trigger->OnMouseLeave.connect (sigc::mem_fun(this, &Launcher::OnTriggerMouseLeave));
- }
- else
- {
- _parent->EnableInputWindow(true);
- g_timeout_add (1000, &Launcher::StrutHack, this);
- _parent->InputWindowEnableStruts(true);
- }
-
- _autohide = autohide;
- EnsureAnimation ();
-}
-
-void Launcher::SetFloating (bool floating)
-{
- if (_floating == floating)
- return;
-
- _floating = floating;
- EnsureAnimation ();
-}
-
-void Launcher::SetHover ()
-{
- if (_hovered)
- return;
-
- _enter_y = (int) _mouse_position.y;
-
- if (_last_shelf_area.y - _enter_y < 5 && _last_shelf_area.y - _enter_y >= 0)
- _enter_y = _last_shelf_area.y - 5;
-
- _hovered = true;
- SetTimeStruct (&_enter_time, &_exit_time, ANIM_DURATION);
-}
-
-void Launcher::UnsetHover ()
-{
- if (!_hovered)
- return;
-
- _hovered = false;
- SetTimeStruct (&_exit_time, &_enter_time, ANIM_DURATION);
- SetupAutohideTimer ();
-}
-
-void Launcher::SetIconSize(int tile_size, int icon_size)
-{
- nux::Geometry geo = _parent->GetGeometry ();
-
- _icon_size = tile_size;
- _icon_image_size = icon_size;
- _icon_image_size_delta = tile_size - icon_size;
-
- // recreate tile textures
-
- _parent->SetGeometry (nux::Geometry (geo.x, geo.y, tile_size + 12, geo.height));
-}
-
-void Launcher::OnIconAdded (void *icon_pointer)
-{
- LauncherIcon *icon = (LauncherIcon *) icon_pointer;
- icon->Reference ();
- EnsureAnimation();
-
- // How to free these properly?
- icon->_xform_coords["HitArea"] = new nux::Vector4[4];
- icon->_xform_coords["Image"] = new nux::Vector4[4];
- icon->_xform_coords["Tile"] = new nux::Vector4[4];
- icon->_xform_coords["Glow"] = new nux::Vector4[4];
-
- // needs to be disconnected
- icon->needs_redraw.connect (sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
-}
-
-void Launcher::OnIconRemoved (void *icon_pointer)
-{
- LauncherIcon *icon = (LauncherIcon *) icon_pointer;
- icon->UnReference ();
-
- EnsureAnimation();
-}
-
-void Launcher::OnOrderChanged ()
-{
-
-}
-
-void Launcher::SetModel (LauncherModel *model)
-{
- _model = model;
- _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::OnOrderChanged));
-}
-
-void Launcher::OnIconNeedsRedraw (void *icon)
-{
- EnsureAnimation();
-}
-
-long Launcher::ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
-{
- long ret = TraverseInfo;
- ret = PostProcessEvent2(ievent, ret, ProcessEventInfo);
- return ret;
-}
-
-void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
-{
-
-}
-
-void Launcher::RenderIcon(nux::GraphicsEngine& GfxContext,
- RenderArg arg,
- nux::BaseTexture *icon,
- nux::Color bkg_color,
- float alpha,
- nux::Vector4 xform_coords[],
- nux::Geometry geo,
- bool render_indicators)
-{
- nux::Matrix4 ObjectMatrix;
- nux::Matrix4 ViewMatrix;
- nux::Matrix4 ProjectionMatrix;
- nux::Matrix4 ViewProjectionMatrix;
-
- if(nux::Abs (arg.folding_rads) < 0.01f)
- icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
- else
- icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
-
- nux::Vector4 v0;
- nux::Vector4 v1;
- nux::Vector4 v2;
- nux::Vector4 v3;
-
- v0.x = xform_coords[0].x ;
- v0.y = xform_coords[0].y ;
- v0.z = xform_coords[0].z ;
- v0.w = xform_coords[0].w ;
- v1.x = xform_coords[1].x ;
- v1.y = xform_coords[1].y ;
- v1.z = xform_coords[1].z ;
- v1.w = xform_coords[1].w ;
- v2.x = xform_coords[2].x ;
- v2.y = xform_coords[2].y ;
- v2.z = xform_coords[2].z ;
- v2.w = xform_coords[2].w ;
- v3.x = xform_coords[3].x ;
- v3.y = xform_coords[3].y ;
- v3.z = xform_coords[3].z ;
- v3.w = xform_coords[3].w ;
-
- float s0, t0, s1, t1, s2, t2, s3, t3;
- nux::Color color = nux::Color::White;
-
- if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
- {
- s0 = 0.0f; t0 = 0.0f;
- s1 = 0.0f; t1 = icon->GetHeight();
- s2 = icon->GetWidth(); t2 = icon->GetHeight();
- s3 = icon->GetWidth(); t3 = 0.0f;
- }
- else
- {
- s0 = 0.0f; t0 = 0.0f;
- s1 = 0.0f; t1 = 1.0f;
- s2 = 1.0f; t2 = 1.0f;
- s3 = 1.0f; t3 = 0.0f;
- }
-
- float VtxBuffer[] =
- {// Perspective correct
- v0.x, v0.y, 0.0f, 1.0f, s0/v0.w, t0/v0.w, 0.0f, 1.0f/v0.w, color.R(), color.G(), color.B(), color.A(),
- v1.x, v1.y, 0.0f, 1.0f, s1/v1.w, t1/v1.w, 0.0f, 1.0f/v1.w, color.R(), color.G(), color.B(), color.A(),
- v2.x, v2.y, 0.0f, 1.0f, s2/v2.w, t2/v2.w, 0.0f, 1.0f/v2.w, color.R(), color.G(), color.B(), color.A(),
- v3.x, v3.y, 0.0f, 1.0f, s3/v3.w, t3/v3.w, 0.0f, 1.0f/v3.w, color.R(), color.G(), color.B(), color.A(),
- };
-
- CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
- CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
-
- int TextureObjectLocation;
- int VertexLocation;
- int TextureCoord0Location;
- int VertexColorLocation;
- int FragmentColor;
-
- if(!USE_ARB_SHADERS)
- {
- _shader_program_uv_persp_correction->Begin();
-
- TextureObjectLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("TextureObject0");
- VertexLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iVertex");
- TextureCoord0Location = _shader_program_uv_persp_correction->GetAttributeLocation("iTexCoord0");
- VertexColorLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iColor");
- FragmentColor = _shader_program_uv_persp_correction->GetUniformLocationARB ("color");
-
- nux::GetGraphicsEngine ().SetTexture(GL_TEXTURE0, icon);
-
- if(TextureObjectLocation != -1)
- CHECKGL( glUniform1iARB (TextureObjectLocation, 0) );
-
- int VPMatrixLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix");
- if(VPMatrixLocation != -1)
- {
- nux::Matrix4 mat = nux::GetGraphicsEngine ().GetModelViewProjectionMatrix ();
- _shader_program_uv_persp_correction->SetUniformLocMatrix4fv ((GLint)VPMatrixLocation, 1, false, (GLfloat*)&(mat.m));
- }
- }
- else
- {
- _AsmShaderProg->Begin();
-
- VertexLocation = nux::VTXATTRIB_POSITION;
- TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0;
- VertexColorLocation = nux::VTXATTRIB_COLOR;
-
- nux::GetGraphicsEngine().SetTexture(GL_TEXTURE0, icon);
- }
-
- CHECKGL( glEnableVertexAttribArrayARB(VertexLocation) );
- CHECKGL( glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer) );
-
- if(TextureCoord0Location != -1)
- {
- CHECKGL( glEnableVertexAttribArrayARB(TextureCoord0Location) );
- CHECKGL( glVertexAttribPointerARB((GLuint)TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4) );
- }
-
- if(VertexColorLocation != -1)
- {
- CHECKGL( glEnableVertexAttribArrayARB(VertexColorLocation) );
- CHECKGL( glVertexAttribPointerARB((GLuint)VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8) );
- }
-
- bkg_color.SetAlpha (bkg_color.A () * alpha);
-
- if(!USE_ARB_SHADERS)
- {
- CHECKGL ( glUniform4fARB (FragmentColor, bkg_color.R(), bkg_color.G(), bkg_color.B(), bkg_color.A() ) );
- nux::GetGraphicsEngine ().SetTexture(GL_TEXTURE0, icon);
- CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
- }
- else
- {
- CHECKGL ( glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, bkg_color.R(), bkg_color.G(), bkg_color.B(), bkg_color.A() ) );
- nux::GetGraphicsEngine ().SetTexture(GL_TEXTURE0, icon);
- CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
- }
-
- if(VertexLocation != -1)
- CHECKGL( glDisableVertexAttribArrayARB(VertexLocation) );
- if(TextureCoord0Location != -1)
- CHECKGL( glDisableVertexAttribArrayARB(TextureCoord0Location) );
- if(VertexColorLocation != -1)
- CHECKGL( glDisableVertexAttribArrayARB(VertexColorLocation) );
-
- if(!USE_ARB_SHADERS)
- {
- _shader_program_uv_persp_correction->End();
- }
- else
- {
- _AsmShaderProg->End();
- }
-
- int markerCenter = (v1.y + v0.y) / 2;
-
- if (arg.running_arrow && render_indicators)
- {
- if (!m_RunningIndicator)
- {
- GdkPixbuf *pbuf = gdk_pixbuf_new_from_file (PKGDATADIR"/running_indicator.png", NULL);
- m_RunningIndicator = nux::CreateTextureFromPixbuf (pbuf);
- g_object_unref (pbuf);
- }
- gPainter.Draw2DTexture (GfxContext, m_RunningIndicator, geo.x, markerCenter - (m_ActiveIndicator->GetHeight () / 2));
- }
-
- if (arg.active_arrow && render_indicators)
- {
- if (!m_ActiveIndicator)
- {
- GdkPixbuf *pbuf = gdk_pixbuf_new_from_file (PKGDATADIR"/focused_indicator.png", NULL);
- m_ActiveIndicator = nux::CreateTextureFromPixbuf (pbuf);
- g_object_unref (pbuf);
- }
- gPainter.Draw2DTexture (GfxContext, m_ActiveIndicator, (geo.x + geo.width) - m_ActiveIndicator->GetWidth (), markerCenter - (m_ActiveIndicator->GetHeight () / 2));
- }
-}
-
-void Launcher::DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg arg, nux::Geometry geo)
-{
- GfxContext.GetRenderStates ().SetSeparateBlend (true,
- GL_SRC_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA,
- GL_ONE_MINUS_DST_ALPHA,
- GL_ONE);
-
- GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
-
- if (arg.backlight_intensity < 1.0f)
- {
- RenderIcon(GfxContext,
- arg,
- _icon_outline_texture,
- nux::Color(0xFF6D6D6D),
- 1.0f - arg.backlight_intensity,
- arg.icon->_xform_coords["Tile"],
- geo,
- false);
- }
-
- if (arg.backlight_intensity > 0.0f)
- {
- RenderIcon(GfxContext,
- arg,
- _icon_bkg_texture,
- arg.icon->BackgroundColor (),
- arg.backlight_intensity,
- arg.icon->_xform_coords["Tile"],
- geo,
- false);
- }
-
- GfxContext.GetRenderStates ().SetSeparateBlend (true,
- GL_SRC_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA,
- GL_ONE_MINUS_DST_ALPHA,
- GL_ONE);
- GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
-
- RenderIcon (GfxContext,
- arg,
- arg.icon->TextureForSize (_icon_image_size),
- nux::Color::White,
- arg.alpha,
- arg.icon->_xform_coords["Image"],
- geo,
- true);
-
- if (arg.backlight_intensity > 0.0f)
- {
- RenderIcon(GfxContext,
- arg,
- _icon_shine_texture,
- nux::Color::White,
- arg.backlight_intensity,
- arg.icon->_xform_coords["Tile"],
- geo,
- false);
- }
-
- switch (arg.window_indicators)
- {
- case 2:
- RenderIcon(GfxContext,
- arg,
- _icon_2indicator,
- nux::Color::White,
- 1.0f,
- arg.icon->_xform_coords["Tile"],
- geo,
- false);
- break;
- case 3:
- RenderIcon(GfxContext,
- arg,
- _icon_3indicator,
- nux::Color::White,
- 1.0f,
- arg.icon->_xform_coords["Tile"],
- geo,
- false);
- break;
- case 4:
- RenderIcon(GfxContext,
- arg,
- _icon_4indicator,
- nux::Color::White,
- 1.0f,
- arg.icon->_xform_coords["Tile"],
- geo,
- false);
- break;
- }
-
- if (arg.glow_intensity > 0.0f)
- {
- RenderIcon(GfxContext,
- arg,
- _icon_glow_texture,
- arg.icon->GlowColor (),
- arg.glow_intensity,
- arg.icon->_xform_coords["Glow"],
- geo,
- false);
- }
-
- if (arg.shimmer_progress > 0.0f && arg.shimmer_progress < 1.0f)
- {
- nux::Geometry base = GetGeometry ();
- int x1 = base.x + base.width;
- int x2 = base.x + base.width;
- float shimmer_constant = 1.9f;
-
- x1 -= geo.width * arg.shimmer_progress * shimmer_constant;
- GfxContext.PushClippingRectangle(nux::Geometry (x1, geo.y, x2 - x1, geo.height));
-
- float fade_out = 1.0f - CLAMP (((x2 - x1) - geo.width) / (geo.width * (shimmer_constant - 1.0f)), 0.0f, 1.0f);
-
- RenderIcon(GfxContext,
- arg,
- _icon_glow_texture,
- arg.icon->GlowColor (),
- fade_out,
- arg.icon->_xform_coords["Glow"],
- geo,
- false);
-
- GfxContext.PopClippingRectangle();
- }
-}
-
-void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
-{
- nux::Geometry base = GetGeometry();
- GfxContext.PushClippingRectangle(base);
- nux::Geometry bkg_box;
- nux::Geometry shelf_box;
- std::list<Launcher::RenderArg> args;
- std::list<Launcher::RenderArg> shelf_args;
-
- nux::ROPConfig ROP;
- ROP.Blend = false;
- ROP.SrcBlend = GL_SRC_ALPHA;
- ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
-
- RenderArgs (args, shelf_args, bkg_box, shelf_box);
- _last_shelf_area = shelf_box;
-
- // clear region
- gPainter.PushDrawColorLayer(GfxContext, base, nux::Color(0x00000000), true, ROP);
-
- // clip vertically but not horizontally
- GfxContext.PushClippingRectangle(nux::Geometry (base.x, bkg_box.y, base.width, bkg_box.height));
- GfxContext.GetRenderStates ().SetSeparateBlend (true,
- GL_SRC_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA,
- GL_ONE_MINUS_DST_ALPHA,
- GL_ONE);
-
- gPainter.Paint2DQuadColor (GfxContext, bkg_box, nux::Color(0xAA000000));
-
- UpdateIconXForm (args);
- UpdateIconXForm (shelf_args);
- EventLogic ();
-
- /* drag launcher */
- std::list<Launcher::RenderArg>::reverse_iterator rev_it;
- for (rev_it = args.rbegin (); rev_it != args.rend (); rev_it++)
- {
- if ((*rev_it).folding_rads >= 0.0f || (*rev_it).skip)
- continue;
-
- DrawRenderArg (GfxContext, *rev_it, bkg_box);
- }
-
- std::list<Launcher::RenderArg>::iterator it;
- for (it = args.begin(); it != args.end(); it++)
- {
- if ((*it).folding_rads < 0.0f || (*it).skip)
- continue;
-
- DrawRenderArg (GfxContext, *it, bkg_box);
- }
-
- /* draw shelf */
- nux::Color shelf_color = nux::Color (0xCC000000);
- nux::Color shelf_zero = nux::Color (0x00000000);
- int shelf_shadow_height = 35;
-
- nux::Geometry shelf_shadow = nux::Geometry (shelf_box.x, shelf_box.y - shelf_shadow_height, shelf_box.width, shelf_shadow_height);
- gPainter.Paint2DQuadColor (GfxContext, shelf_shadow, shelf_zero, shelf_color, shelf_color, shelf_zero);
- gPainter.Paint2DQuadColor (GfxContext, shelf_box, shelf_color);
-
- for (it = shelf_args.begin(); it != shelf_args.end(); it++)
- {
- if ((*it).skip)
- continue;
-
- DrawRenderArg (GfxContext, *it, bkg_box);
- }
-
- gPainter.Paint2DQuadColor (GfxContext, nux::Geometry (bkg_box.x + bkg_box.width - 1, bkg_box.y, 1, bkg_box.height), nux::Color(0x60FFFFFF));
-
- GfxContext.GetRenderStates().SetColorMask (true, true, true, true);
- GfxContext.GetRenderStates ().SetSeparateBlend (false,
- GL_SRC_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA,
- GL_SRC_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA);
-
- gPainter.PopBackground();
- GfxContext.PopClippingRectangle();
- GfxContext.PopClippingRectangle();
-}
-
-void Launcher::PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw)
-{
-}
-
-void Launcher::PreLayoutManagement()
-{
- View::PreLayoutManagement();
- if(m_CompositionLayout)
- {
- m_CompositionLayout->SetGeometry(GetGeometry());
- }
-}
-
-long Launcher::PostLayoutManagement(long LayoutResult)
-{
- View::PostLayoutManagement(LayoutResult);
-
- _mouse_position = nux::Point2 (0, 0);
-
- return nux::eCompliantHeight | nux::eCompliantWidth;
-}
-
-void Launcher::PositionChildLayout(float offsetX, float offsetY)
-{
-}
-
-bool Launcher::TooltipNotify(LauncherIcon* Icon)
-{
- if(GetActiveMenuIcon())
- return false;
- return true;
-}
-
-bool Launcher::MenuNotify(LauncherIcon* Icon)
-{
-
-
- return true;
-}
-
-void Launcher::NotifyMenuTermination(LauncherIcon* Icon)
-{
-}
-
-void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- _mouse_position = nux::Point2 (x, y);
-
- MouseDownLogic (x, y, button_flags, key_flags);
- EnsureAnimation ();
-}
-
-void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- _mouse_position = nux::Point2 (x, y);
- nux::Geometry geo = GetGeometry ();
-
- if (_launcher_action_state == ACTION_DRAG_LAUNCHER && !geo.IsInside(nux::Point(x, y)))
- {
- // we are no longer hovered
- UnsetHover ();
- }
-
- MouseUpLogic (x, y, button_flags, key_flags);
- _launcher_action_state = ACTION_NONE;
- EnsureAnimation ();
-}
-
-void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
-{
- _mouse_position = nux::Point2 (x, y);
-
- _dnd_delta += dy;
-
- if (nux::Abs (_dnd_delta) < 15 && _launcher_action_state != ACTION_DRAG_LAUNCHER)
- return;
-
- if (_icon_under_mouse)
- {
- _icon_under_mouse->MouseLeave.emit ();
- _icon_under_mouse->_mouse_inside = false;
- _icon_under_mouse = 0;
- }
-
- _launcher_action_state = ACTION_DRAG_LAUNCHER;
- EnsureAnimation ();
-}
-
-void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- _mouse_position = nux::Point2 (x, y);
- _mouse_inside_launcher = true;
-
- if (!_last_shelf_area.IsInside (nux::Point (x, y)))
- SetHover ();
-
- EventLogic ();
- EnsureAnimation ();
-}
-
-void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- _mouse_position = nux::Point2 (x, y);
- _mouse_inside_launcher = false;
-
- if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
- UnsetHover ();
-
- EventLogic ();
- EnsureAnimation ();
-}
-
-void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
-{
- _mouse_position = nux::Point2 (x, y);
-
- if (!_last_shelf_area.IsInside (nux::Point (x, y)))
- {
- SetHover ();
- EnsureAnimation ();
- }
- // Every time the mouse moves, we check if it is inside an icon...
-
- EventLogic ();
-}
-
-void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags)
-{
-}
-
-const gchar* Launcher::GetName ()
-{
- return "Launcher";
-}
-
-void Launcher::AddProperties (GVariantBuilder *builder)
-{
-}
-
-void Launcher::EventLogic ()
-{
- if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
- return;
-
- LauncherIcon* launcher_icon = 0;
-
- if (_mouse_inside_launcher)
- launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
-
- if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
- {
- _icon_under_mouse->MouseLeave.emit ();
- _icon_under_mouse->_mouse_inside = false;
- _icon_under_mouse = 0;
- }
-
- if (launcher_icon && (_icon_under_mouse != launcher_icon))
- {
- launcher_icon->MouseEnter.emit ();
- launcher_icon->_mouse_inside = true;
- _icon_under_mouse = launcher_icon;
- }
-}
-
-void Launcher::MouseDownLogic (int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- LauncherIcon* launcher_icon = 0;
- launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
-
- if (launcher_icon)
- {
- _icon_mouse_down = launcher_icon;
- launcher_icon->MouseDown.emit (nux::GetEventButton (button_flags));
- }
-}
-
-void Launcher::MouseUpLogic (int x, int y, unsigned long button_flags, unsigned long key_flags)
-{
- LauncherIcon* launcher_icon = 0;
- launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
-
- if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
- {
- _icon_mouse_down->MouseUp.emit (nux::GetEventButton (button_flags));
-
- if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
- _icon_mouse_down->MouseClick.emit (nux::GetEventButton (button_flags));
- }
-
- if (launcher_icon && (_icon_mouse_down != launcher_icon))
- {
- launcher_icon->MouseUp.emit (nux::GetEventButton (button_flags));
- }
-
- if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
- {
- SetTimeStruct (&_drag_end_time);
- }
-
- _icon_mouse_down = 0;
-}
-
-LauncherIcon* Launcher::MouseIconIntersection (int x, int y)
-{
- LauncherModel::iterator it;
- LauncherModel::reverse_iterator rev_it;
- // We are looking for the icon at screen coordinates x, y;
- nux::Point2 mouse_position(x, y);
- int inside = 0;
-
- for (it = _model->shelf_begin(); it != _model->shelf_end (); it++)
- {
- if (!(*it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
- continue;
-
- nux::Point2 screen_coord [4];
- for (int i = 0; i < 4; i++)
- {
- screen_coord [i].x = (*it)->_xform_coords["HitArea"] [i].x;
- screen_coord [i].y = (*it)->_xform_coords["HitArea"] [i].y;
- }
- inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
- if (inside)
- return (*it);
- }
-
- // Because of the way icons fold and stack on one another, we must proceed in 2 steps.
- for (rev_it = _model->rbegin (); rev_it != _model->rend (); rev_it++)
- {
- if ((*rev_it)->_folding_angle < 0.0f || !(*rev_it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
- continue;
-
- nux::Point2 screen_coord [4];
- for (int i = 0; i < 4; i++)
- {
- screen_coord [i].x = (*rev_it)->_xform_coords["HitArea"] [i].x;
- screen_coord [i].y = (*rev_it)->_xform_coords["HitArea"] [i].y;
- }
- inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
- if (inside)
- return (*rev_it);
- }
-
- for (it = _model->begin(); it != _model->end (); it++)
- {
- if ((*it)->_folding_angle >= 0.0f || !(*it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
- continue;
-
- nux::Point2 screen_coord [4];
- for (int i = 0; i < 4; i++)
- {
- screen_coord [i].x = (*it)->_xform_coords["HitArea"] [i].x;
- screen_coord [i].y = (*it)->_xform_coords["HitArea"] [i].y;
- }
- inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
- if (inside)
- return (*it);
- }
-
- return 0;
-}
-
-void Launcher::SetIconXForm (LauncherIcon *icon, nux::Matrix4 ViewProjectionMatrix, nux::Geometry geo,
- float x, float y, float w, float h, float z, std::string name)
-{
- nux::Vector4 v0 = nux::Vector4(x, y, z, 1.0f);
- nux::Vector4 v1 = nux::Vector4(x, y+h, z, 1.0f);
- nux::Vector4 v2 = nux::Vector4(x+w, y+h, z, 1.0f);
- nux::Vector4 v3 = nux::Vector4(x+w, y, z, 1.0f);
-
- v0 = ViewProjectionMatrix * v0;
- v1 = ViewProjectionMatrix * v1;
- v2 = ViewProjectionMatrix * v2;
- v3 = ViewProjectionMatrix * v3;
-
- v0.divide_xyz_by_w();
- v1.divide_xyz_by_w();
- v2.divide_xyz_by_w();
- v3.divide_xyz_by_w();
-
- // normalize to the viewport coordinates and translate to the correct location
- v0.x = geo.width *(v0.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
- v0.y = -geo.height*(v0.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
- v1.x = geo.width *(v1.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;;
- v1.y = -geo.height*(v1.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
- v2.x = geo.width *(v2.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
- v2.y = -geo.height*(v2.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
- v3.x = geo.width *(v3.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
- v3.y = -geo.height*(v3.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
-
-
- nux::Vector4* vectors = icon->_xform_coords[name];
-
- vectors[0].x = v0.x;
- vectors[0].y = v0.y;
- vectors[0].z = v0.z;
- vectors[0].w = v0.w;
- vectors[1].x = v1.x;
- vectors[1].y = v1.y;
- vectors[1].z = v1.z;
- vectors[1].w = v1.w;
- vectors[2].x = v2.x;
- vectors[2].y = v2.y;
- vectors[2].z = v2.z;
- vectors[2].w = v2.w;
- vectors[3].x = v3.x;
- vectors[3].y = v3.y;
- vectors[3].z = v3.z;
- vectors[3].w = v3.w;
-}
-
-void Launcher::UpdateIconXForm (std::list<Launcher::RenderArg> args)
-{
- nux::Geometry geo = GetGeometry ();
- nux::Matrix4 ObjectMatrix;
- nux::Matrix4 ViewMatrix;
- nux::Matrix4 ProjectionMatrix;
- nux::Matrix4 ViewProjectionMatrix;
-
- GetInverseScreenPerspectiveMatrix(ViewMatrix, ProjectionMatrix, geo.width, geo.height, 0.1f, 1000.0f, DEGTORAD(90));
-
- //LauncherModel::iterator it;
- std::list<Launcher::RenderArg>::iterator it;
- for(it = args.begin(); it != args.end(); it++)
- {
- if ((*it).skip)
- continue;
-
- LauncherIcon* launcher_icon = (*it).icon;
-
- // We to store the icon angle in the icons itself. Makes one thing easier afterward.
- launcher_icon->_folding_angle = (*it).folding_rads;
-
- float w = _icon_size;
- float h = _icon_size;
- float x = (*it).center.x - w/2.0f; // x: top left corner
- float y = (*it).center.y - h/2.0f; // y: top left corner
- float z = (*it).center.z;
-
- ObjectMatrix = nux::Matrix4::TRANSLATE(geo.width/2.0f, geo.height/2.0f, z) * // Translate the icon to the center of the viewport
- nux::Matrix4::ROTATEX((*it).folding_rads) * // rotate the icon
- nux::Matrix4::TRANSLATE(-x - w/2.0f, -y - h/2.0f, -z); // Put the center the icon to (0, 0)
-
- ViewProjectionMatrix = ProjectionMatrix*ViewMatrix*ObjectMatrix;
-
- SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "Tile");
-
- w = _icon_image_size;
- h = _icon_image_size;
- x = (*it).center.x - _icon_size/2.0f + _icon_image_size_delta/2.0f;
- y = (*it).center.y - _icon_size/2.0f + _icon_image_size_delta/2.0f;
- z = (*it).center.z;
-
- SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "Image");
-
- w = _icon_glow_size;
- h = _icon_glow_size;
- x = (*it).center.x - _icon_glow_size/2.0f;
- y = (*it).center.y - _icon_glow_size/2.0f;
- z = (*it).center.z;
-
- SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "Glow");
-
- w = geo.width + 2;
- h = _icon_size + _space_between_icons;
- x = (*it).center.x - w/2.0f;
- y = (*it).center.y - h/2.0f;
- z = (*it).center.z;
-
- SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "HitArea");
- }
-}
-
-void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
- int ViewportWidth,
- int ViewportHeight,
- float NearClipPlane,
- float FarClipPlane,
- float Fovy)
-{
-/*
- Objective:
- Given a perspective matrix defined by (Fovy, AspectRatio, NearPlane, FarPlane), we want to compute
- the ModelView matrix that transform a quad defined by its top-left coord (0, 0) and its
- bottom-right coord (WindowWidth, WindowHeight) into a full screen quad that covers the entire viewport (one to one).
- Any quad that is facing the camera and whose 4 points are on the 4 guiding line of the view frustum (pyramid)
- will always cover the entire viewport one to one (when projected on the screen).
- So all we have to do is to define a quad with x:[-x_cs, x_cs] and y:[-y_cs, y_cs] and find the z distance in eye space (z_cs) so that
- the quad touches the 4 guiding lines of the view frustum.
- We consider a well centered projection view (no skewing, no oblique clipping plane, ...) and derive the following equations:
- x_cs = AspectRatio*y_cs
- y_cs/z_cs = tanf(Fovy/2) ==> z_cs = y_cs*1/tanf(Fovy/2) (this is the absolute value the quad depth value will be -z_cs since we are using OpenGL right hand coord system).
-
- The quad (in camera space) facing the camera and centered around the camera view axis is defined by the points (-x_cs, y_cs) (top-left)
- and the point (x_cs, -y_cs) (bottom-right). If we move that quad along the camera view axis and place it at a distance z_cs of the camera,
- then its 4 corners are each on the 4 lines of the view frustum.
-
- (-x_cs, y_cs) Camera Space
- ^
- __________|__________
- | | |
- | | |
- | |(0, 0) |
- |----------|----------|->
- | | |
- | | |
- |__________|__________|
- (x_cs, -y_cs)
-
- The full-screen quad (in screen space) is defined by the point (0, 0) (top-left) and (WindowWidth, WindowHeight) (bottom-right).
- We can choose and arbitrary value y_cs and compute the z_cs position in camera space that will produce a quad in camera space that projects into
- the full-screen space.
-
- (0, 0) Screen Space
- _____________________->
- | | |
- | | |
- | | |
- |----------|----------|
- | | |
- | | |
- |__________|__________|
- v (WindowWidth, WindowHeight)
-
- The model view matrix is the succession of transformation that convert the quad (0, 0, WindowWidth, WindowHeight) into
- the quad (-x_cs, y_cs, x_cs, -y_cs)
-
- Screen Space Camera Space
- x ----> x_ = x*2*x_cs/WindowWidth - x_cs
- y ----> y_ = -y*2*y_cs/WindowHeight + y_cs
- z ----> z_ = A*z -y_cs*1/tanf(Fovy/2)
- where A is a coefficient that can attenuate the rate of change in depth when the quad moves along the camera axis
-
- If the following is the projection matrix:
-
- (a, 0, 0, 0) a = 1/(AspectRatio*tan(Fovy/2))
- (0, b, 0, 0) b = 1/tan(Fovy/2)
- (0, 0, c, d)
- (0, 0, -1, 0)
-
- and the camera space vertex is (x_cs, y_cs, z_cs, w_cs) projects to the top left corner of the view port on the screen ((-1, 1) in clip space), then
- x_cs*a/(-z_cs) = -1; | z_cs = x_cs*a x_cs*a = -y_cs*b ==> x_cs = y_cs*AspectRatio
- | ==> ==>
- y_cs*b/(-z_cs) = +1; | z_cs = -y_cs*b z_cs = -y_cs*1/tanf(Fovy/2)
-*/
-
-
- float AspectRatio = (float)ViewportWidth/(float)ViewportHeight;
- float CameraToScreenDistance = -1.0f;
- float y_cs = -CameraToScreenDistance*tanf(0.5f*Fovy/* *3.1415926/180.0f*/);
- float x_cs = y_cs*AspectRatio;
- //float CameraToScreenDistance = -y_cs*1.0f/(tanf(0.5f*Fovy/* *3.1415926/180.0f*/));
-
- ViewMatrix = nux::Matrix4::TRANSLATE(-x_cs, y_cs, CameraToScreenDistance) *
- nux::Matrix4::SCALE(2.0f*x_cs/ViewportWidth, -2.0f*y_cs/ViewportHeight, -2.0f * 3 * y_cs/ViewportHeight /* or -2.0f * x_cs/ViewportWidth*/ );
-
- PerspectiveMatrix.Perspective(Fovy, AspectRatio, NearClipPlane, FarClipPlane);
-
-// // Example usage with the matrices above:
-// float W = 300;
-// float H = 300;
-// // centered quad
-// float X = (ViewportWidth - W)/2.0;
-// float Y = (ViewportHeight - H)/2.0;
-// float Z = 0.0f;
-//
-// {
-// glPushMatrix();
-// // Local Transformation of the object
-// glTranslatef(0.0f, 0.0f, ObjectDistanceToCamera);
-// glTranslatef(X + W/2.0f, Y + H/2.0f, 0.0f);
-// glRotatef(cameraAngleY, 1, 0, 0);
-// glRotatef(cameraAngleX, 0, 1, 0);
-// glTranslatef(-X - W/2.0f, -Y - H/2.0f, 0.0f);
-//
-// glBegin(GL_QUADS);
-// {
-// glNormal3f(0.0f, 0.0f, 1.0f);
-//
-// glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
-// glVertex4f(X, Y, Z, 1.0f);
-//
-// glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
-// glVertex4f(X, Y+H, Z, 1.0f);
-//
-// glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
-// glVertex4f(X+W, Y+H, Z, 1.0f);
-//
-// glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
-// glVertex4f(X+W, Y, Z, 1.0f);
-// }
-// glEnd();
-}
-
-void Launcher::SetActiveQuicklist (QuicklistView *quicklist)
-{
- // Assert: _active_quicklist should be 0
- _active_quicklist = quicklist;
-}
-
-QuicklistView *Launcher::GetActiveQuicklist ()
-{
- return _active_quicklist;
-}
-
-void Launcher::CancelActiveQuicklist (QuicklistView *quicklist)
-{
- if (_active_quicklist == quicklist)
- _active_quicklist = 0;
-}
-
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Jason Smith <jason.smith@canonical.com>
+ * Authored by: Jay Taoko <jay.taoko@canonical.com>
+ */
+
+#include <math.h>
+
+#include "Nux/Nux.h"
+#include "Nux/VScrollBar.h"
+#include "Nux/HLayout.h"
+#include "Nux/VLayout.h"
+#include "Nux/MenuPage.h"
+
+#include "NuxGraphics/NuxGraphics.h"
+#include "NuxGraphics/GpuDevice.h"
+#include "NuxGraphics/GLTextureResourceManager.h"
+
+#include "Nux/BaseWindow.h"
+#include "Nux/WindowCompositor.h"
+
+#include "Launcher.h"
+#include "LauncherIcon.h"
+#include "LauncherModel.h"
+#include "QuicklistView.h"
+
+#define ANIM_DURATION_SHORT 125
+#define ANIM_DURATION 200
+#define ANIM_DURATION_LONG 350
+
+#define URGENT_BLINKS 3
+
+#define MAX_STARTING_BLINKS 5
+#define STARTING_BLINK_LAMBDA 3
+
+#define BACKLIGHT_STRENGTH 0.9f
+
+int
+TimeDelta (struct timespec const *x, struct timespec const *y)
+{
+ return ((x->tv_sec - y->tv_sec) * 1000) + ((x->tv_nsec - y->tv_nsec) / 1000000);
+}
+
+static bool USE_ARB_SHADERS = true;
+/*
+ Use this shader to pass vertices in screen coordinates in the C++ code and compute use
+ the fragment shader to perform the texture perspective correct division.
+ This shader assume the following:
+ - the projection matrix is orthogonal: glOrtho(0, ScreenWidth, ScreenWidth, 0, Near, Far)
+ - vertices x and y are in screen coordinates: Vertex(x_screen, y_screen, 0, 1.0)
+ - the vertices w coordinates has been computed 'manually'
+ - vertices uv textture coordinates are passed to the shader as: (u/w, v/w, 0, 1/w)
+
+ The texture coordinates s=u/w, t=v/w and q=1w are interpolated linearly in screen coordinates.
+ In the fragment shader we get the texture coordinates used for the sampling by dividing
+ s and t resulting from the interpolation by q.
+
+ */
+
+nux::NString gPerspectiveCorrectShader = TEXT (
+"[Vertex Shader] \n\
+#version 120 \n\
+uniform mat4 ViewProjectionMatrix; \n\
+ \n\
+attribute vec4 iColor; \n\
+attribute vec4 iTexCoord0; \n\
+attribute vec4 iVertex; \n\
+ \n\
+varying vec4 varyTexCoord0; \n\
+varying vec4 varyVertexColor; \n\
+ \n\
+void main() \n\
+{ \n\
+ varyTexCoord0 = iTexCoord0; \n\
+ varyVertexColor = iColor; \n\
+ gl_Position = ViewProjectionMatrix * iVertex; \n\
+} \n\
+ \n\
+[Fragment Shader] \n\
+#version 120 \n\
+#extension GL_ARB_texture_rectangle : enable \n\
+ \n\
+varying vec4 varyTexCoord0; \n\
+varying vec4 varyVertexColor; \n\
+ \n\
+uniform sampler2D TextureObject0; \n\
+uniform vec4 color0; \n\
+vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\
+{ \n\
+ return texture2D(TexObject, TexCoord.st); \n\
+} \n\
+ \n\
+void main() \n\
+{ \n\
+ vec4 tex = varyTexCoord0; \n\
+ tex.s = tex.s/varyTexCoord0.w; \n\
+ tex.t = tex.t/varyTexCoord0.w; \n\
+ \n\
+ vec4 texel = SampleTexture(TextureObject0, tex); \n\
+ gl_FragColor = texel*varyVertexColor; \n\
+} \n\
+");
+
+nux::NString PerspectiveCorrectVtx = TEXT (
+ "!!ARBvp1.0 \n\
+ ATTRIB iPos = vertex.position; \n\
+ ATTRIB iColor = vertex.attrib[3]; \n\
+ PARAM mvp[4] = {state.matrix.mvp}; \n\
+ OUTPUT oPos = result.position; \n\
+ OUTPUT oColor = result.color; \n\
+ OUTPUT oTexCoord0 = result.texcoord[0]; \n\
+ # Transform the vertex to clip coordinates. \n\
+ DP4 oPos.x, mvp[0], iPos; \n\
+ DP4 oPos.y, mvp[1], iPos; \n\
+ DP4 oPos.z, mvp[2], iPos; \n\
+ DP4 oPos.w, mvp[3], iPos; \n\
+ MOV oColor, iColor; \n\
+ MOV oTexCoord0, vertex.attrib[8]; \n\
+ END");
+
+
+
+nux::NString PerspectiveCorrectTexFrg = TEXT (
+ "!!ARBfp1.0 \n\
+ PARAM color0 = program.local[0]; \n\
+ TEMP temp; \n\
+ TEMP pcoord; \n\
+ TEMP tex0; \n\
+ TEMP temp1; \n\
+ TEMP recip; \n\
+ MOV pcoord, fragment.texcoord[0].w; \n\
+ RCP temp, fragment.texcoord[0].w; \n\
+ MUL pcoord.xy, fragment.texcoord[0], temp; \n\
+ TEX tex0, pcoord, texture[0], 2D; \n\
+ MUL result.color, color0, tex0; \n\
+ END");
+
+nux::NString PerspectiveCorrectTexRectFrg = TEXT (
+ "!!ARBfp1.0 \n\
+ PARAM color0 = program.local[0]; \n\
+ TEMP temp; \n\
+ TEMP pcoord; \n\
+ TEMP tex0; \n\
+ MOV pcoord, fragment.texcoord[0].w; \n\
+ RCP temp, fragment.texcoord[0].w; \n\
+ MUL pcoord.xy, fragment.texcoord[0], temp; \n\
+ TEX tex0, pcoord, texture[0], RECT; \n\
+ MUL result.color, color0, tex0; \n\
+ END");
+
+static void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
+ int ViewportWidth,
+ int ViewportHeight,
+ float NearClipPlane,
+ float FarClipPlane,
+ float Fovy);
+
+Launcher::Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_DECL)
+: View(NUX_FILE_LINE_PARAM)
+, m_ContentOffsetY(0)
+, m_RunningIndicator(0)
+, m_ActiveIndicator(0)
+, m_BackgroundLayer(0)
+, _model (0)
+{
+ _parent = parent;
+ _screen = screen;
+ _active_quicklist = 0;
+
+ m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
+
+ OnMouseDown.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
+ OnMouseUp.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
+ OnMouseDrag.connect(sigc::mem_fun(this, &Launcher::RecvMouseDrag));
+ OnMouseEnter.connect(sigc::mem_fun(this, &Launcher::RecvMouseEnter));
+ OnMouseLeave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave));
+ OnMouseMove.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove));
+ OnMouseWheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel));
+
+ m_ActiveTooltipIcon = NULL;
+ m_ActiveMenuIcon = NULL;
+
+ SetCompositionLayout(m_Layout);
+
+ if(!USE_ARB_SHADERS)
+ {
+ _shader_program_uv_persp_correction = nux::GetThreadGLDeviceFactory()->CreateShaderProgram();
+ _shader_program_uv_persp_correction->LoadIShader(gPerspectiveCorrectShader.GetTCharPtr());
+ _shader_program_uv_persp_correction->Link();
+ }
+ else
+ {
+ _AsmShaderProg = nux::GetThreadGLDeviceFactory()->CreateAsmShaderProgram();
+ _AsmShaderProg->LoadVertexShader (TCHAR_TO_ANSI (*PerspectiveCorrectVtx) );
+
+ if ((nux::GetThreadGLDeviceFactory()->SUPPORT_GL_ARB_TEXTURE_NON_POWER_OF_TWO() == false) &&
+ (nux::GetThreadGLDeviceFactory()->SUPPORT_GL_EXT_TEXTURE_RECTANGLE () || nux::GetThreadGLDeviceFactory()->SUPPORT_GL_ARB_TEXTURE_RECTANGLE ()))
+ {
+ // No support for non power of two textures but support for rectangle textures
+ _AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexRectFrg) );
+ }
+ else
+ {
+ _AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexFrg) );
+ }
+
+ _AsmShaderProg->Link();
+ }
+
+ _folded_angle = 1.0f;
+ _neg_folded_angle = -1.0f;
+ _space_between_icons = 5;
+ _launcher_top_y = 0;
+ _launcher_bottom_y = 0;
+ _folded_z_distance = 10.0f;
+ _launcher_state = LAUNCHER_FOLDED;
+ _launcher_action_state = ACTION_NONE;
+ _icon_under_mouse = NULL;
+ _icon_mouse_down = NULL;
+ _icon_image_size = 48;
+ _icon_glow_size = 62;
+ _icon_image_size_delta = 6;
+ _icon_size = _icon_image_size + _icon_image_size_delta;
+
+ _icon_bkg_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_corner_54x54.png");
+ _icon_outline_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_outline_54x54.png");
+ _icon_shine_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_shine_54x54.png");
+ _icon_glow_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_glow_62x62.png");
+ _icon_2indicator = nux::CreateTextureFromFile (PKGDATADIR"/2indicate_54x54.png");
+ _icon_3indicator = nux::CreateTextureFromFile (PKGDATADIR"/3indicate_54x54.png");
+ _icon_4indicator = nux::CreateTextureFromFile (PKGDATADIR"/4indicate_54x54.png");
+
+ _enter_y = 0;
+ _dnd_security = 15;
+ _dnd_delta = 0;
+ _anim_handle = 0;
+ _autohide_handle = 0;
+ _floating = false;
+ _hovered = false;
+ _autohide = false;
+ _hidden = false;
+ _mouse_inside_launcher = false;
+ _mouse_inside_trigger = false;
+ _window_over_launcher = false;
+
+ // 0 out timers to avoid wonky startups
+ _enter_time.tv_sec = 0;
+ _enter_time.tv_nsec = 0;
+ _exit_time.tv_sec = 0;
+ _exit_time.tv_nsec = 0;
+ _drag_end_time.tv_sec = 0;
+ _drag_end_time.tv_nsec = 0;
+ _autohide_time.tv_sec = 0;
+ _autohide_time.tv_nsec = 0;
+}
+
+Launcher::~Launcher()
+{
+
+}
+
+/* Introspection */
+const gchar *
+Launcher::GetName ()
+{
+ return "Launcher";
+}
+
+void
+Launcher::AddProperties (GVariantBuilder *builder)
+{
+ struct timespec current;
+ clock_gettime (CLOCK_MONOTONIC, &current);
+
+ g_variant_builder_add (builder, "{sv}", "hover-progress", g_variant_new_double ((double) GetHoverProgress (current)));
+ g_variant_builder_add (builder, "{sv}", "dnd-exit-progress", g_variant_new_double ((double) DnDExitProgress (current)));
+ g_variant_builder_add (builder, "{sv}", "autohide-progress", g_variant_new_double ((double) AutohideProgress (current)));
+
+ g_variant_builder_add (builder, "{sv}", "dnd-delta", g_variant_new_int32 (_dnd_delta));
+ g_variant_builder_add (builder, "{sv}", "floating", g_variant_new_boolean (_floating));
+ g_variant_builder_add (builder, "{sv}", "hovered", g_variant_new_boolean (_hovered));
+ g_variant_builder_add (builder, "{sv}", "autohide", g_variant_new_boolean (_autohide));
+ g_variant_builder_add (builder, "{sv}", "hidden", g_variant_new_boolean (_hidden));
+ g_variant_builder_add (builder, "{sv}", "autohide", g_variant_new_boolean (_autohide));
+ g_variant_builder_add (builder, "{sv}", "mouse-inside-launcher", g_variant_new_boolean (_mouse_inside_launcher));
+}
+
+/* Render Layout Logic */
+
+float Launcher::GetHoverProgress (struct timespec const &current)
+{
+ if (_hovered)
+ return CLAMP ((float) (TimeDelta (&current, &_enter_time)) / (float) ANIM_DURATION, 0.0f, 1.0f);
+ else
+ return 1.0f - CLAMP ((float) (TimeDelta (&current, &_exit_time)) / (float) ANIM_DURATION, 0.0f, 1.0f);
+}
+
+float Launcher::DnDExitProgress (struct timespec const &current)
+{
+ return 1.0f - CLAMP ((float) (TimeDelta (&current, &_drag_end_time)) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
+}
+
+float Launcher::AutohideProgress (struct timespec const &current)
+{
+ if (!_autohide)
+ return 0.0f;
+
+ if (_hidden)
+ return CLAMP ((float) (TimeDelta (&current, &_autohide_time)) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
+ else
+ return 1.0f - CLAMP ((float) (TimeDelta (&current, &_autohide_time)) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
+}
+
+gboolean Launcher::AnimationTimeout (gpointer data)
+{
+ Launcher *self = (Launcher*) data;
+
+ self->NeedRedraw ();
+
+ if (self->AnimationInProgress ())
+ return true;
+
+ // zero out handle so we know we are done
+ self->_anim_handle = 0;
+ return false;
+}
+
+void Launcher::EnsureAnimation ()
+{
+ if (_anim_handle)
+ return;
+
+ NeedRedraw ();
+
+ if (AnimationInProgress ())
+ _anim_handle = g_timeout_add (1000 / 60 - 1, &Launcher::AnimationTimeout, this);
+}
+
+bool Launcher::IconNeedsAnimation (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
+ if (TimeDelta (&current, &time) < ANIM_DURATION_SHORT)
+ return true;
+
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_RUNNING);
+ if (TimeDelta (&current, &time) < ANIM_DURATION_SHORT)
+ return true;
+
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
+ if (TimeDelta (&current, &time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2))
+ return true;
+
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_URGENT);
+ if (TimeDelta (&current, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2))
+ return true;
+
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
+ if (TimeDelta (&current, &time) < ANIM_DURATION)
+ return true;
+
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_SHIMMER);
+ if (TimeDelta (&current, &time) < ANIM_DURATION_LONG)
+ return true;
+
+ return false;
+}
+
+bool Launcher::AnimationInProgress ()
+{
+ // performance here can be improved by caching the longer remaining animation found and short circuiting to that each time
+ // this way extra checks may be avoided
+
+ // short circuit to avoid unneeded calculations
+ struct timespec current;
+ clock_gettime (CLOCK_MONOTONIC, &current);
+
+ // hover in animation
+ if (TimeDelta (&current, &_enter_time) < ANIM_DURATION)
+ return true;
+
+ // hover out animation
+ if (TimeDelta (&current, &_exit_time) < ANIM_DURATION)
+ return true;
+
+ // drag end animation
+ if (TimeDelta (&current, &_drag_end_time) < ANIM_DURATION_LONG)
+ return true;
+
+ if (TimeDelta (&current, &_autohide_time) < ANIM_DURATION_SHORT)
+ return true;
+
+ // animations happening on specific icons
+ LauncherModel::iterator it;
+ for (it = _model->begin (); it != _model->end (); it++)
+ if (IconNeedsAnimation (*it, current))
+ return true;
+
+ return false;
+}
+
+void Launcher::SetTimeStruct (struct timespec *timer, struct timespec *sister, int sister_relation)
+{
+ struct timespec current;
+ clock_gettime (CLOCK_MONOTONIC, &current);
+
+ if (sister)
+ {
+ int diff = TimeDelta (&current, sister);
+
+ if (diff < sister_relation)
+ {
+ int remove = sister_relation - diff;
+ current.tv_sec -= remove / 1000;
+ remove = remove % 1000;
+
+ if (remove > current.tv_nsec / 1000000)
+ {
+ current.tv_sec--;
+ current.tv_nsec += 1000000000;
+ }
+ current.tv_nsec -= remove * 1000000;
+ }
+ }
+
+ timer->tv_sec = current.tv_sec;
+ timer->tv_nsec = current.tv_nsec;
+}
+
+float IconVisibleProgress (LauncherIcon *icon, struct timespec const &current)
+{
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
+ {
+ struct timespec icon_visible_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
+ int enter_ms = TimeDelta (&current, &icon_visible_time);
+ return CLAMP ((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
+ }
+ else
+ {
+ struct timespec icon_hide_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
+ int hide_ms = TimeDelta (&current, &icon_hide_time);
+ return 1.0f - CLAMP ((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
+ }
+}
+
+void Launcher::SetDndDelta (float x, float y, nux::Geometry geo, struct timespec const &current)
+{
+ LauncherIcon *anchor = 0;
+ LauncherModel::iterator it;
+ anchor = MouseIconIntersection (x, _enter_y);
+
+ if (anchor)
+ {
+ float position = y;
+ for (it = _model->begin (); it != _model->end (); it++)
+ {
+ if (*it == anchor)
+ {
+ position += _icon_size / 2;
+ _dnd_delta = _enter_y - position;
+
+ if (position + _icon_size / 2 + _dnd_delta > geo.height)
+ _dnd_delta -= (position + _icon_size / 2 + _dnd_delta) - geo.height;
+
+ break;
+ }
+ position += (_icon_size + _space_between_icons) * IconVisibleProgress (*it, current);
+ }
+ }
+}
+
+float Launcher::IconPresentProgress (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec icon_present_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
+ int ms = TimeDelta (&current, &icon_present_time);
+ float result = CLAMP ((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
+
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
+ return result;
+ else
+ return 1.0f - result;
+}
+
+float Launcher::IconUrgentProgress (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec urgent_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_URGENT);
+ int urgent_ms = TimeDelta (&current, &urgent_time);
+ float result = CLAMP ((float) urgent_ms / (float) (ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
+
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
+ return result;
+ else
+ return 1.0f - result;
+}
+
+float Launcher::IconShimmerProgress (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec shimmer_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_SHIMMER);
+ int shimmer_ms = TimeDelta (&current, &shimmer_time);
+ return CLAMP ((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
+}
+
+float Launcher::IconUrgentPulseValue (LauncherIcon *icon, struct timespec const &current)
+{
+ if (!icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
+ return 1.0f; // we are full on in a normal condition
+
+ double urgent_progress = (double) IconUrgentProgress (icon, current);
+ return 0.5f + (float) (std::cos (M_PI * (float) (URGENT_BLINKS * 2) * urgent_progress)) * 0.5f;
+}
+
+float Launcher::IconStartingPulseValue (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec starting_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
+ int starting_ms = TimeDelta (&current, &starting_time);
+ double starting_progress = (double) CLAMP ((float) starting_ms / (float) (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f);
+
+ return 1.0f - (0.5f + (float) (std::cos (M_PI * (float) (MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
+}
+
+float Launcher::IconBackgroundIntensity (LauncherIcon *icon, struct timespec const &current)
+{
+ float result = 0.0f;
+ struct timespec running_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_RUNNING);
+ int running_ms = TimeDelta (&current, &running_time);
+ float running_progress = CLAMP ((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
+
+ // After we finish a fade in from running, we can reset the quirk
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING) && running_progress == 1.0f)
+ icon->ResetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
+
+ result = IconStartingPulseValue (icon, current) * BACKLIGHT_STRENGTH;
+
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
+ {
+ // running progress fades in whatever the pulsing did not fill in already
+ result += running_progress * (BACKLIGHT_STRENGTH - result);
+
+ // urgent serves to bring the total down only
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
+ result *= 0.2f + 0.8f * IconUrgentPulseValue (icon, current);
+ }
+ else
+ {
+ // modestly evil
+ result += BACKLIGHT_STRENGTH - running_progress * BACKLIGHT_STRENGTH;
+ }
+
+ return result;
+}
+
+void Launcher::SetupRenderArg (LauncherIcon *icon, struct timespec const &current, RenderArg &arg)
+{
+ arg.icon = icon;
+ arg.alpha = 1.0f;
+ arg.running_arrow = icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING);
+ arg.active_arrow = icon->GetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE);
+ arg.running_colored = icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT);
+ arg.active_colored = false;
+ arg.folding_rads = 0.0f;
+ arg.skip = false;
+
+
+ // we dont need to show strays
+ if (!icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
+ arg.window_indicators = 0;
+ else
+ arg.window_indicators = MIN (4, icon->RelatedWindows ());
+
+ arg.backlight_intensity = IconBackgroundIntensity (icon, current);
+ arg.shimmer_progress = IconShimmerProgress (icon, current);
+
+ float urgent_progress = IconUrgentProgress (icon, current);
+ urgent_progress = CLAMP (urgent_progress * 3, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
+ arg.glow_intensity = urgent_progress;
+}
+
+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;
+}
+
+void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
+ nux::Geometry &box_geo)
+{
+ nux::Geometry geo = GetGeometry ();
+ LauncherModel::iterator it;
+ nux::Point3 center;
+ struct timespec current;
+ clock_gettime (CLOCK_MONOTONIC, &current);
+
+ float hover_progress = GetHoverProgress (current);
+ float folded_z_distance = _folded_z_distance * (1.0f - hover_progress);
+ float animation_neg_rads = _neg_folded_angle * (1.0f - hover_progress);
+ int vertical_offset = _parent->GetGeometry ().y;
+
+ float folding_constant = 0.25f;
+ float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress);
+
+ float folded_size = _icon_size * folding_not_constant;
+ float folded_spacing = _space_between_icons * folding_not_constant;
+
+ center.x = geo.width / 2;
+ center.y = _space_between_icons;
+ center.z = 0;
+
+ int launcher_height = geo.height;
+
+ // compute required height of launcher AND folding threshold
+ float sum = 0.0f + center.y;
+ float folding_threshold = launcher_height - _icon_size / 2.5f;
+ for (it = _model->begin (); it != _model->end (); it++)
+ {
+ float height = (_icon_size + _space_between_icons) * IconVisibleProgress (*it, current);
+ sum += height;
+
+ // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";
+ float magic_constant = 1.2f;
+
+ float present_progress = IconPresentProgress (*it, current);
+ folding_threshold -= CLAMP (sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * present_progress);
+ }
+
+ // this happens on hover, basically its a flag and a value in one, we translate this into a dnd offset
+ if (_enter_y != 0 && _enter_y + _icon_size / 2 > folding_threshold)
+ SetDndDelta (center.x, center.y, nux::Geometry (geo.x, geo.y, geo.width, geo.height), current);
+
+ _enter_y = 0;
+
+ if (hover_progress > 0.0f && _dnd_delta != 0)
+ {
+ float delta_y = _dnd_delta;
+
+ // logically dnd exit only restores to the clamped ranges
+ // hover_progress restores to 0
+ float max = 0.0f;
+ float min = MIN (0.0f, launcher_height - sum);
+
+ if (_dnd_delta > max)
+ delta_y = max + DragLimiter (delta_y - max);
+ else if (_dnd_delta < min)
+ delta_y = min + DragLimiter (delta_y - min);
+
+ if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
+ {
+ float dnd_progress = DnDExitProgress (current);
+
+ if (_dnd_delta > max)
+ delta_y = max + (delta_y - max) * dnd_progress;
+ else if (_dnd_delta < min)
+ delta_y = min + (delta_y - min) * dnd_progress;
+
+ if (dnd_progress == 0.0f)
+ _dnd_delta = (int) delta_y;
+ }
+
+ delta_y *= hover_progress;
+ center.y += delta_y;
+ folding_threshold += delta_y;
+ }
+ else
+ {
+ _dnd_delta = 0;
+ }
+
+ float autohide_progress = AutohideProgress (current);
+ float autohide_offset = 0.0f;
+ if (_autohide && autohide_progress > 0.0f)
+ {
+ autohide_offset -= geo.width * autohide_progress;
+ }
+
+ // Inform the painter where to paint the box
+ box_geo = geo;
+
+ if (_autohide)
+ box_geo.x += autohide_offset;
+
+ // 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;
+ LauncherIcon *icon = *it;
+
+ SetupRenderArg (icon, current, arg);
+
+ // reset z
+ center.z = 0;
+
+ float size_modifier = IconVisibleProgress (icon, current);
+ if (size_modifier < 1.0f)
+ {
+ arg.alpha = size_modifier;
+ center.z = 300.0f * (1.0f - size_modifier);
+ }
+
+ if (size_modifier <= 0.0f)
+ {
+ arg.skip = true;
+ continue;
+ }
+
+ // goes for 0.0f when fully unfolded, to 1.0f folded
+ float folding_progress = CLAMP ((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
+ float present_progress = IconPresentProgress (icon, current);
+
+ folding_progress *= 1.0f - present_progress;
+
+ float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
+
+ float icon_hide_offset = autohide_offset;
+
+ icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency ());
+
+ // icon is crossing threshold, start folding
+ center.z += folded_z_distance * folding_progress;
+ arg.folding_rads = animation_neg_rads * folding_progress;
+
+ center.y += half_size * size_modifier; // move to center
+ arg.center = nux::Point3 (roundf (center.x + icon_hide_offset), roundf (center.y), roundf (center.z)); // copy center
+ icon->SetCenter (nux::Point3 (roundf (center.x), roundf (center.y + vertical_offset), roundf (center.z)));
+ center.y += half_size * size_modifier; // move to end
+
+ float spacing_overlap = CLAMP ((float) (center.y + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
+ //add spacing
+ center.y += (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
+
+ 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 height = (_icon_size + _space_between_icons) * IconVisibleProgress (*it, current);
+ shelf_sum += height;
+ }
+
+ // add bottom padding
+ if (shelf_sum > 0.0f)
+ shelf_sum += _space_between_icons;
+
+ float shelf_delta = MAX (((launcher_height - shelf_sum) + _space_between_icons) - center.y, 0.0f);
+ folding_threshold += shelf_delta;
+ center.y += shelf_delta;
+
+ for (it = _model->shelf_begin (); it != _model->shelf_end (); it++)
+ {
+ RenderArg arg;
+ LauncherIcon *icon = *it;
+
+ SetupRenderArg (icon, current, arg);
+
+ // reset z
+ center.z = 0;
+
+ float size_modifier = IconVisibleProgress (icon, current);
+ if (size_modifier < 1.0f)
+ {
+ arg.alpha = size_modifier;
+ center.z = 300.0f * (1.0f - size_modifier);
+ }
+
+ if (size_modifier <= 0.0f)
+ {
+ arg.skip = true;
+ continue;
+ }
+
+ // goes for 0.0f when fully unfolded, to 1.0f folded
+ float folding_progress = CLAMP ((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
+ float present_progress = IconPresentProgress (icon, current);
+
+ folding_progress *= 1.0f - present_progress;
+
+ float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
+
+ float icon_hide_offset = autohide_offset;
+
+ icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency ());
+
+ // icon is crossing threshold, start folding
+ center.z += folded_z_distance * folding_progress;
+ arg.folding_rads = animation_neg_rads * folding_progress;
+
+ center.y += half_size * size_modifier; // move to center
+ arg.center = nux::Point3 (roundf (center.x + icon_hide_offset), roundf (center.y), roundf (center.z)); // copy center
+ icon->SetCenter (nux::Point3 (roundf (center.x), roundf (center.y + vertical_offset), roundf (center.z)));
+ center.y += half_size * size_modifier; // move to end
+
+ float spacing_overlap = CLAMP ((float) (center.y + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
+ //add spacing
+ center.y += (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
+
+ launcher_args.push_back (arg);
+ }
+}
+
+/* End Render Layout Logic */
+
+void Launcher::SetHidden (bool hidden)
+{
+ if (hidden == _hidden)
+ return;
+
+ _hidden = hidden;
+ SetTimeStruct (&_autohide_time, &_autohide_time, ANIM_DURATION_SHORT);
+
+ _parent->EnableInputWindow(!hidden);
+
+ EnsureAnimation ();
+}
+
+gboolean Launcher::OnAutohideTimeout (gpointer data)
+{
+ Launcher *self = (Launcher*) data;
+
+ self->EnsureHiddenState ();
+ self->_autohide_handle = 0;
+ return false;
+}
+
+void
+Launcher::EnsureHiddenState ()
+{
+ if (!_mouse_inside_trigger && !_mouse_inside_launcher && _window_over_launcher)
+ SetHidden (true);
+ else
+ SetHidden (false);
+}
+
+void
+Launcher::CheckWindowOverLauncher ()
+{
+ CompWindowList window_list = _screen->windows ();
+ CompWindowList::iterator it;
+ nux::Geometry geo = GetGeometry ();
+
+ for (it = window_list.begin (); it != window_list.end (); it++)
+ {
+ CompWindow *window = *it;
+
+ if (window->type () != CompWindowTypeNormalMask || window->invisible ())
+ continue;
+
+ if (CompRegion (window->inputRect ()).intersects (CompRect (geo.x, geo.y, geo.width, geo.height)))
+ {
+ _window_over_launcher = true;
+ EnsureHiddenState ();
+ return;
+ }
+ }
+
+ _window_over_launcher = false;
+ EnsureHiddenState ();
+}
+
+void
+Launcher::OnWindowMoved (CompWindow *window)
+{
+ if (_autohide)
+ CheckWindowOverLauncher ();
+}
+
+void
+Launcher::OnWindowResized (CompWindow *window)
+{
+ if (_autohide)
+ CheckWindowOverLauncher ();
+}
+
+void
+Launcher::OnWindowAppear (CompWindow *window)
+{
+ if (_autohide)
+ CheckWindowOverLauncher ();
+}
+void
+Launcher::OnWindowDisappear (CompWindow *window)
+{
+ if (_autohide)
+ CheckWindowOverLauncher ();
+}
+
+void Launcher::OnTriggerMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_inside_trigger = true;
+ EnsureHiddenState ();
+}
+
+void Launcher::SetupAutohideTimer ()
+{
+ if (_autohide)
+ {
+ if (_autohide_handle > 0)
+ g_source_remove (_autohide_handle);
+ _autohide_handle = g_timeout_add (1000, &Launcher::OnAutohideTimeout, this);
+ }
+}
+
+void Launcher::OnTriggerMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_inside_trigger = false;
+ SetupAutohideTimer ();
+}
+
+bool Launcher::AutohideEnabled ()
+{
+ return _autohide;
+}
+
+gboolean Launcher::StrutHack (gpointer data)
+{
+ Launcher *self = (Launcher *) data;
+ self->_parent->InputWindowEnableStruts(false);
+ self->_parent->InputWindowEnableStruts(true);
+
+ return false;
+}
+
+void Launcher::SetAutohide (bool autohide, nux::View *trigger)
+{
+ if (_autohide == autohide)
+ return;
+
+ if (autohide)
+ {
+ _parent->InputWindowEnableStruts(false);
+ _autohide_trigger = trigger;
+ _autohide_trigger->OnMouseEnter.connect (sigc::mem_fun(this, &Launcher::OnTriggerMouseEnter));
+ _autohide_trigger->OnMouseLeave.connect (sigc::mem_fun(this, &Launcher::OnTriggerMouseLeave));
+ }
+ else
+ {
+ _parent->EnableInputWindow(true);
+ g_timeout_add (1000, &Launcher::StrutHack, this);
+ _parent->InputWindowEnableStruts(true);
+ }
+
+ _autohide = autohide;
+ EnsureAnimation ();
+}
+
+void Launcher::SetFloating (bool floating)
+{
+ if (_floating == floating)
+ return;
+
+ _floating = floating;
+ EnsureAnimation ();
+}
+
+void Launcher::SetHover ()
+{
+ if (_hovered)
+ return;
+
+ _enter_y = (int) _mouse_position.y;
+
+ _hovered = true;
+ SetTimeStruct (&_enter_time, &_exit_time, ANIM_DURATION);
+}
+
+void Launcher::UnsetHover ()
+{
+ if (!_hovered)
+ return;
+
+ _hovered = false;
+ SetTimeStruct (&_exit_time, &_enter_time, ANIM_DURATION);
+ SetupAutohideTimer ();
+}
+
+void Launcher::SetIconSize(int tile_size, int icon_size)
+{
+ nux::Geometry geo = _parent->GetGeometry ();
+
+ _icon_size = tile_size;
+ _icon_image_size = icon_size;
+ _icon_image_size_delta = tile_size - icon_size;
+
+ // recreate tile textures
+
+ _parent->SetGeometry (nux::Geometry (geo.x, geo.y, tile_size + 12, geo.height));
+}
+
+void Launcher::OnIconAdded (void *icon_pointer)
+{
+ LauncherIcon *icon = (LauncherIcon *) icon_pointer;
+ icon->Reference ();
+ EnsureAnimation();
+
+ // How to free these properly?
+ icon->_xform_coords["HitArea"] = new nux::Vector4[4];
+ icon->_xform_coords["Image"] = new nux::Vector4[4];
+ icon->_xform_coords["Tile"] = new nux::Vector4[4];
+ icon->_xform_coords["Glow"] = new nux::Vector4[4];
+
+ // needs to be disconnected
+ icon->needs_redraw.connect (sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
+
+ AddChild (icon);
+}
+
+void Launcher::OnIconRemoved (void *icon_pointer)
+{
+ LauncherIcon *icon = (LauncherIcon *) icon_pointer;
+ icon->UnReference ();
+
+ EnsureAnimation();
+
+ RemoveChild (icon);
+}
+
+void Launcher::OnOrderChanged ()
+{
+ EnsureAnimation ();
+}
+
+void Launcher::SetModel (LauncherModel *model)
+{
+ _model = model;
+ _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::OnOrderChanged));
+}
+
+void Launcher::OnIconNeedsRedraw (void *icon)
+{
+ EnsureAnimation();
+}
+
+long Launcher::ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
+{
+ long ret = TraverseInfo;
+ ret = PostProcessEvent2(ievent, ret, ProcessEventInfo);
+ return ret;
+}
+
+void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+
+}
+
+void Launcher::RenderIndicators (nux::GraphicsEngine& GfxContext,
+ RenderArg const &arg,
+ int running,
+ int active,
+ nux::Geometry geo)
+{
+ int markerCenter = (int) arg.center.y;
+
+ if (running > 0)
+ {
+ if (!m_RunningIndicator)
+ {
+ GdkPixbuf *pbuf = gdk_pixbuf_new_from_file (PKGDATADIR"/running_indicator.png", NULL);
+ m_RunningIndicator = nux::CreateTextureFromPixbuf (pbuf);
+ g_object_unref (pbuf);
+ }
+ nux::TexCoordXForm texxform;
+
+ nux::Color color = nux::Color::LightGrey;
+
+ if (arg.running_colored)
+ color = nux::Color::SkyBlue;
+
+ std::vector<int> markers;
+ if (running == 1)
+ {
+ markers.push_back (markerCenter);
+ }
+ else if (running == 2)
+ {
+ markers.push_back (markerCenter - 2);
+ markers.push_back (markerCenter + 2);
+ }
+ else
+ {
+ markers.push_back (markerCenter - 4);
+ markers.push_back (markerCenter);
+ markers.push_back (markerCenter + 4);
+ }
+
+ std::vector<int>::iterator it;
+ for (it = markers.begin (); it != markers.end (); it++)
+ {
+ int center = *it;
+ GfxContext.QRP_GLSL_1Tex (geo.x,
+ center - (m_RunningIndicator->GetHeight () / 2),
+ (float) m_RunningIndicator->GetWidth(),
+ (float) m_RunningIndicator->GetHeight(),
+ m_RunningIndicator->GetDeviceTexture(),
+ texxform,
+ color);
+ }
+ }
+
+ if (active > 0)
+ {
+ if (!m_ActiveIndicator)
+ {
+ GdkPixbuf *pbuf = gdk_pixbuf_new_from_file (PKGDATADIR"/focused_indicator.png", NULL);
+ m_ActiveIndicator = nux::CreateTextureFromPixbuf (pbuf);
+ g_object_unref (pbuf);
+ }
+ nux::TexCoordXForm texxform;
+
+ nux::Color color = nux::Color::LightGrey;
+ GfxContext.QRP_GLSL_1Tex ((geo.x + geo.width) - m_ActiveIndicator->GetWidth (),
+ markerCenter - (m_ActiveIndicator->GetHeight () / 2),
+ (float) m_ActiveIndicator->GetWidth(),
+ (float) m_ActiveIndicator->GetHeight(),
+ m_ActiveIndicator->GetDeviceTexture(),
+ texxform,
+ color);
+ }
+}
+
+void Launcher::RenderIcon(nux::GraphicsEngine& GfxContext,
+ RenderArg const &arg,
+ nux::BaseTexture *icon,
+ nux::Color bkg_color,
+ float alpha,
+ nux::Vector4 xform_coords[],
+ nux::Geometry geo)
+{
+ if (icon == NULL || icon->IsNull ())
+ return;
+
+ nux::Matrix4 ObjectMatrix;
+ nux::Matrix4 ViewMatrix;
+ nux::Matrix4 ProjectionMatrix;
+ nux::Matrix4 ViewProjectionMatrix;
+
+ if(nux::Abs (arg.folding_rads) < 0.01f)
+ icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
+ else
+ icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
+
+ nux::Vector4 v0;
+ nux::Vector4 v1;
+ nux::Vector4 v2;
+ nux::Vector4 v3;
+
+ v0.x = xform_coords[0].x ;
+ v0.y = xform_coords[0].y ;
+ v0.z = xform_coords[0].z ;
+ v0.w = xform_coords[0].w ;
+ v1.x = xform_coords[1].x ;
+ v1.y = xform_coords[1].y ;
+ v1.z = xform_coords[1].z ;
+ v1.w = xform_coords[1].w ;
+ v2.x = xform_coords[2].x ;
+ v2.y = xform_coords[2].y ;
+ v2.z = xform_coords[2].z ;
+ v2.w = xform_coords[2].w ;
+ v3.x = xform_coords[3].x ;
+ v3.y = xform_coords[3].y ;
+ v3.z = xform_coords[3].z ;
+ v3.w = xform_coords[3].w ;
+
+ float s0, t0, s1, t1, s2, t2, s3, t3;
+ nux::Color color = nux::Color::White;
+
+ if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
+ {
+ s0 = 0.0f; t0 = 0.0f;
+ s1 = 0.0f; t1 = icon->GetHeight();
+ s2 = icon->GetWidth(); t2 = icon->GetHeight();
+ s3 = icon->GetWidth(); t3 = 0.0f;
+ }
+ else
+ {
+ s0 = 0.0f; t0 = 0.0f;
+ s1 = 0.0f; t1 = 1.0f;
+ s2 = 1.0f; t2 = 1.0f;
+ s3 = 1.0f; t3 = 0.0f;
+ }
+
+ float VtxBuffer[] =
+ {// Perspective correct
+ v0.x, v0.y, 0.0f, 1.0f, s0/v0.w, t0/v0.w, 0.0f, 1.0f/v0.w, color.R(), color.G(), color.B(), color.A(),
+ v1.x, v1.y, 0.0f, 1.0f, s1/v1.w, t1/v1.w, 0.0f, 1.0f/v1.w, color.R(), color.G(), color.B(), color.A(),
+ v2.x, v2.y, 0.0f, 1.0f, s2/v2.w, t2/v2.w, 0.0f, 1.0f/v2.w, color.R(), color.G(), color.B(), color.A(),
+ v3.x, v3.y, 0.0f, 1.0f, s3/v3.w, t3/v3.w, 0.0f, 1.0f/v3.w, color.R(), color.G(), color.B(), color.A(),
+ };
+
+ CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
+ CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
+
+ int TextureObjectLocation;
+ int VertexLocation;
+ int TextureCoord0Location;
+ int VertexColorLocation;
+ int FragmentColor;
+
+ if(!USE_ARB_SHADERS)
+ {
+ _shader_program_uv_persp_correction->Begin();
+
+ TextureObjectLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("TextureObject0");
+ VertexLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iVertex");
+ TextureCoord0Location = _shader_program_uv_persp_correction->GetAttributeLocation("iTexCoord0");
+ VertexColorLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iColor");
+ FragmentColor = _shader_program_uv_persp_correction->GetUniformLocationARB ("color");
+
+ nux::GetGraphicsEngine ().SetTexture(GL_TEXTURE0, icon);
+
+ if(TextureObjectLocation != -1)
+ CHECKGL( glUniform1iARB (TextureObjectLocation, 0) );
+
+ int VPMatrixLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix");
+ if(VPMatrixLocation != -1)
+ {
+ nux::Matrix4 mat = nux::GetGraphicsEngine ().GetModelViewProjectionMatrix ();
+ _shader_program_uv_persp_correction->SetUniformLocMatrix4fv ((GLint)VPMatrixLocation, 1, false, (GLfloat*)&(mat.m));
+ }
+ }
+ else
+ {
+ _AsmShaderProg->Begin();
+
+ VertexLocation = nux::VTXATTRIB_POSITION;
+ TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0;
+ VertexColorLocation = nux::VTXATTRIB_COLOR;
+
+ nux::GetGraphicsEngine().SetTexture(GL_TEXTURE0, icon);
+ }
+
+ CHECKGL( glEnableVertexAttribArrayARB(VertexLocation) );
+ CHECKGL( glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer) );
+
+ if(TextureCoord0Location != -1)
+ {
+ CHECKGL( glEnableVertexAttribArrayARB(TextureCoord0Location) );
+ CHECKGL( glVertexAttribPointerARB((GLuint)TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4) );
+ }
+
+ if(VertexColorLocation != -1)
+ {
+ CHECKGL( glEnableVertexAttribArrayARB(VertexColorLocation) );
+ CHECKGL( glVertexAttribPointerARB((GLuint)VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8) );
+ }
+
+ bkg_color.SetAlpha (bkg_color.A () * alpha);
+
+ if(!USE_ARB_SHADERS)
+ {
+ CHECKGL ( glUniform4fARB (FragmentColor, bkg_color.R(), bkg_color.G(), bkg_color.B(), bkg_color.A() ) );
+ nux::GetGraphicsEngine ().SetTexture(GL_TEXTURE0, icon);
+ CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
+ }
+ else
+ {
+ CHECKGL ( glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, bkg_color.R(), bkg_color.G(), bkg_color.B(), bkg_color.A() ) );
+ nux::GetGraphicsEngine ().SetTexture(GL_TEXTURE0, icon);
+ CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
+ }
+
+ if(VertexLocation != -1)
+ CHECKGL( glDisableVertexAttribArrayARB(VertexLocation) );
+ if(TextureCoord0Location != -1)
+ CHECKGL( glDisableVertexAttribArrayARB(TextureCoord0Location) );
+ if(VertexColorLocation != -1)
+ CHECKGL( glDisableVertexAttribArrayARB(VertexColorLocation) );
+
+ if(!USE_ARB_SHADERS)
+ {
+ _shader_program_uv_persp_correction->End();
+ }
+ else
+ {
+ _AsmShaderProg->End();
+ }
+}
+
+void Launcher::DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg const &arg, nux::Geometry geo)
+{
+ GfxContext.GetRenderStates ().SetSeparateBlend (true,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE_MINUS_DST_ALPHA,
+ GL_ONE);
+
+ GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
+
+ if (arg.backlight_intensity < 1.0f)
+ {
+ RenderIcon(GfxContext,
+ arg,
+ _icon_outline_texture,
+ nux::Color(0xAAFFFFFF),
+ 1.0f - arg.backlight_intensity,
+ arg.icon->_xform_coords["Tile"],
+ geo);
+ }
+
+ if (arg.backlight_intensity > 0.0f)
+ {
+ RenderIcon(GfxContext,
+ arg,
+ _icon_bkg_texture,
+ arg.icon->BackgroundColor (),
+ arg.backlight_intensity,
+ arg.icon->_xform_coords["Tile"],
+ geo);
+ }
+
+ GfxContext.GetRenderStates ().SetSeparateBlend (true,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE_MINUS_DST_ALPHA,
+ GL_ONE);
+ GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
+
+ RenderIcon (GfxContext,
+ arg,
+ arg.icon->TextureForSize (_icon_image_size),
+ nux::Color::White,
+ arg.alpha,
+ arg.icon->_xform_coords["Image"],
+ geo);
+
+ if (arg.backlight_intensity > 0.0f)
+ {
+ RenderIcon(GfxContext,
+ arg,
+ _icon_shine_texture,
+ nux::Color::White,
+ arg.backlight_intensity,
+ arg.icon->_xform_coords["Tile"],
+ geo);
+ }
+
+ if (false)
+ {
+ switch (arg.window_indicators)
+ {
+ case 2:
+ RenderIcon(GfxContext,
+ arg,
+ _icon_2indicator,
+ nux::Color::White,
+ 1.0f,
+ arg.icon->_xform_coords["Tile"],
+ geo);
+ break;
+ case 3:
+ RenderIcon(GfxContext,
+ arg,
+ _icon_3indicator,
+ nux::Color::White,
+ 1.0f,
+ arg.icon->_xform_coords["Tile"],
+ geo);
+ break;
+ case 4:
+ RenderIcon(GfxContext,
+ arg,
+ _icon_4indicator,
+ nux::Color::White,
+ 1.0f,
+ arg.icon->_xform_coords["Tile"],
+ geo);
+ break;
+ }
+ }
+
+ if (arg.glow_intensity > 0.0f)
+ {
+ RenderIcon(GfxContext,
+ arg,
+ _icon_glow_texture,
+ arg.icon->GlowColor (),
+ arg.glow_intensity,
+ arg.icon->_xform_coords["Glow"],
+ geo);
+ }
+
+ if (arg.shimmer_progress > 0.0f && arg.shimmer_progress < 1.0f)
+ {
+ nux::Geometry base = GetGeometry ();
+ int x1 = base.x + base.width;
+ int x2 = base.x + base.width;
+ float shimmer_constant = 1.9f;
+
+ x1 -= geo.width * arg.shimmer_progress * shimmer_constant;
+ GfxContext.PushClippingRectangle(nux::Geometry (x1, geo.y, x2 - x1, geo.height));
+
+ float fade_out = 1.0f - CLAMP (((x2 - x1) - geo.width) / (geo.width * (shimmer_constant - 1.0f)), 0.0f, 1.0f);
+
+ RenderIcon(GfxContext,
+ arg,
+ _icon_glow_texture,
+ arg.icon->GlowColor (),
+ fade_out,
+ arg.icon->_xform_coords["Glow"],
+ geo);
+
+ GfxContext.PopClippingRectangle();
+ }
+
+ RenderIndicators (GfxContext,
+ arg,
+ arg.running_arrow ? arg.window_indicators : 0,
+ arg.active_arrow ? 1 : 0,
+ geo);
+}
+
+void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+ nux::Geometry base = GetGeometry();
+ GfxContext.PushClippingRectangle(base);
+ nux::Geometry bkg_box;
+ std::list<Launcher::RenderArg> args;
+ std::list<Launcher::RenderArg>::reverse_iterator rev_it;
+ std::list<Launcher::RenderArg>::iterator it;
+
+ nux::ROPConfig ROP;
+ ROP.Blend = false;
+ ROP.SrcBlend = GL_SRC_ALPHA;
+ ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
+
+ RenderArgs (args, bkg_box);
+
+ // clear region
+ gPainter.PushDrawColorLayer(GfxContext, base, nux::Color(0x00000000), true, ROP);
+
+ // clip vertically but not horizontally
+ GfxContext.PushClippingRectangle(nux::Geometry (base.x, bkg_box.y, base.width, bkg_box.height));
+ GfxContext.GetRenderStates ().SetSeparateBlend (true,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE_MINUS_DST_ALPHA,
+ GL_ONE);
+
+ gPainter.Paint2DQuadColor (GfxContext, bkg_box, nux::Color(0xAA000000));
+
+ UpdateIconXForm (args);
+ EventLogic ();
+
+ /* draw launcher */
+ for (rev_it = args.rbegin (); rev_it != args.rend (); rev_it++)
+ {
+ if ((*rev_it).folding_rads >= 0.0f || (*rev_it).skip)
+ continue;
+
+ DrawRenderArg (GfxContext, *rev_it, bkg_box);
+ }
+
+ for (it = args.begin(); it != args.end(); it++)
+ {
+ if ((*it).folding_rads < 0.0f || (*it).skip)
+ continue;
+
+ DrawRenderArg (GfxContext, *it, bkg_box);
+ }
+
+
+ gPainter.Paint2DQuadColor (GfxContext, nux::Geometry (bkg_box.x + bkg_box.width - 1, bkg_box.y, 1, bkg_box.height), nux::Color(0x60FFFFFF));
+
+ GfxContext.GetRenderStates().SetColorMask (true, true, true, true);
+ GfxContext.GetRenderStates ().SetSeparateBlend (false,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA);
+
+ gPainter.PopBackground();
+ GfxContext.PopClippingRectangle();
+ GfxContext.PopClippingRectangle();
+}
+
+void Launcher::PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+}
+
+void Launcher::PreLayoutManagement()
+{
+ View::PreLayoutManagement();
+ if(m_CompositionLayout)
+ {
+ m_CompositionLayout->SetGeometry(GetGeometry());
+ }
+}
+
+long Launcher::PostLayoutManagement(long LayoutResult)
+{
+ View::PostLayoutManagement(LayoutResult);
+
+ _mouse_position = nux::Point2 (0, 0);
+
+ return nux::eCompliantHeight | nux::eCompliantWidth;
+}
+
+void Launcher::PositionChildLayout(float offsetX, float offsetY)
+{
+}
+
+bool Launcher::TooltipNotify(LauncherIcon* Icon)
+{
+ if(GetActiveMenuIcon())
+ return false;
+ return true;
+}
+
+bool Launcher::MenuNotify(LauncherIcon* Icon)
+{
+
+
+ return true;
+}
+
+void Launcher::NotifyMenuTermination(LauncherIcon* Icon)
+{
+}
+
+void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_position = nux::Point2 (x, y);
+
+ MouseDownLogic (x, y, button_flags, key_flags);
+ EnsureAnimation ();
+}
+
+void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_position = nux::Point2 (x, y);
+ nux::Geometry geo = GetGeometry ();
+
+ if (_launcher_action_state == ACTION_DRAG_LAUNCHER && !geo.IsInside(nux::Point(x, y)))
+ {
+ // we are no longer hovered
+ UnsetHover ();
+ }
+
+ MouseUpLogic (x, y, button_flags, key_flags);
+ _launcher_action_state = ACTION_NONE;
+ EnsureAnimation ();
+}
+
+void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_position = nux::Point2 (x, y);
+
+ _dnd_delta += dy;
+
+ if (nux::Abs (_dnd_delta) < 15 && _launcher_action_state != ACTION_DRAG_LAUNCHER)
+ return;
+
+ if (_icon_under_mouse)
+ {
+ _icon_under_mouse->MouseLeave.emit ();
+ _icon_under_mouse->_mouse_inside = false;
+ _icon_under_mouse = 0;
+ }
+
+ _launcher_action_state = ACTION_DRAG_LAUNCHER;
+ EnsureAnimation ();
+}
+
+void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_position = nux::Point2 (x, y);
+ _mouse_inside_launcher = true;
+
+ SetHover ();
+
+ EventLogic ();
+ EnsureAnimation ();
+}
+
+void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_position = nux::Point2 (x, y);
+ _mouse_inside_launcher = false;
+
+ if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
+ UnsetHover ();
+
+ EventLogic ();
+ EnsureAnimation ();
+}
+
+void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
+{
+ _mouse_position = nux::Point2 (x, y);
+
+ // Every time the mouse moves, we check if it is inside an icon...
+ EventLogic ();
+}
+
+void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags)
+{
+}
+
+void Launcher::EventLogic ()
+{
+ if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
+ return;
+
+ LauncherIcon* launcher_icon = 0;
+
+ if (_mouse_inside_launcher)
+ launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
+
+ if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
+ {
+ _icon_under_mouse->MouseLeave.emit ();
+ _icon_under_mouse->_mouse_inside = false;
+ _icon_under_mouse = 0;
+ }
+
+ if (launcher_icon && (_icon_under_mouse != launcher_icon))
+ {
+ launcher_icon->MouseEnter.emit ();
+ launcher_icon->_mouse_inside = true;
+ _icon_under_mouse = launcher_icon;
+ }
+}
+
+void Launcher::MouseDownLogic (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ LauncherIcon* launcher_icon = 0;
+ launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
+
+ if (launcher_icon)
+ {
+ _icon_mouse_down = launcher_icon;
+ launcher_icon->MouseDown.emit (nux::GetEventButton (button_flags));
+ }
+}
+
+void Launcher::MouseUpLogic (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ LauncherIcon* launcher_icon = 0;
+ launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
+
+ if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
+ {
+ _icon_mouse_down->MouseUp.emit (nux::GetEventButton (button_flags));
+
+ if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
+ _icon_mouse_down->MouseClick.emit (nux::GetEventButton (button_flags));
+ }
+
+ if (launcher_icon && (_icon_mouse_down != launcher_icon))
+ {
+ launcher_icon->MouseUp.emit (nux::GetEventButton (button_flags));
+ }
+
+ if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
+ {
+ SetTimeStruct (&_drag_end_time);
+ }
+
+ _icon_mouse_down = 0;
+}
+
+LauncherIcon* Launcher::MouseIconIntersection (int x, int y)
+{
+ LauncherModel::iterator it;
+ LauncherModel::reverse_iterator rev_it;
+ // We are looking for the icon at screen coordinates x, y;
+ nux::Point2 mouse_position(x, y);
+ int inside = 0;
+
+ // Because of the way icons fold and stack on one another, we must proceed in 2 steps.
+ for (rev_it = _model->rbegin (); rev_it != _model->rend (); rev_it++)
+ {
+ if ((*rev_it)->_folding_angle < 0.0f || !(*rev_it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
+ continue;
+
+ nux::Point2 screen_coord [4];
+ for (int i = 0; i < 4; i++)
+ {
+ screen_coord [i].x = (*rev_it)->_xform_coords["HitArea"] [i].x;
+ screen_coord [i].y = (*rev_it)->_xform_coords["HitArea"] [i].y;
+ }
+ inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
+ if (inside)
+ return (*rev_it);
+ }
+
+ for (it = _model->begin(); it != _model->end (); it++)
+ {
+ if ((*it)->_folding_angle >= 0.0f || !(*it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
+ continue;
+
+ nux::Point2 screen_coord [4];
+ for (int i = 0; i < 4; i++)
+ {
+ screen_coord [i].x = (*it)->_xform_coords["HitArea"] [i].x;
+ screen_coord [i].y = (*it)->_xform_coords["HitArea"] [i].y;
+ }
+ inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
+ if (inside)
+ return (*it);
+ }
+
+ return 0;
+}
+
+void Launcher::SetIconXForm (LauncherIcon *icon, nux::Matrix4 ViewProjectionMatrix, nux::Geometry geo,
+ float x, float y, float w, float h, float z, std::string name)
+{
+ nux::Vector4 v0 = nux::Vector4(x, y, z, 1.0f);
+ nux::Vector4 v1 = nux::Vector4(x, y+h, z, 1.0f);
+ nux::Vector4 v2 = nux::Vector4(x+w, y+h, z, 1.0f);
+ nux::Vector4 v3 = nux::Vector4(x+w, y, z, 1.0f);
+
+ v0 = ViewProjectionMatrix * v0;
+ v1 = ViewProjectionMatrix * v1;
+ v2 = ViewProjectionMatrix * v2;
+ v3 = ViewProjectionMatrix * v3;
+
+ v0.divide_xyz_by_w();
+ v1.divide_xyz_by_w();
+ v2.divide_xyz_by_w();
+ v3.divide_xyz_by_w();
+
+ // normalize to the viewport coordinates and translate to the correct location
+ v0.x = geo.width *(v0.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
+ v0.y = -geo.height*(v0.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
+ v1.x = geo.width *(v1.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;;
+ v1.y = -geo.height*(v1.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
+ v2.x = geo.width *(v2.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
+ v2.y = -geo.height*(v2.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
+ v3.x = geo.width *(v3.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
+ v3.y = -geo.height*(v3.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
+
+
+ nux::Vector4* vectors = icon->_xform_coords[name];
+
+ vectors[0].x = v0.x;
+ vectors[0].y = v0.y;
+ vectors[0].z = v0.z;
+ vectors[0].w = v0.w;
+ vectors[1].x = v1.x;
+ vectors[1].y = v1.y;
+ vectors[1].z = v1.z;
+ vectors[1].w = v1.w;
+ vectors[2].x = v2.x;
+ vectors[2].y = v2.y;
+ vectors[2].z = v2.z;
+ vectors[2].w = v2.w;
+ vectors[3].x = v3.x;
+ vectors[3].y = v3.y;
+ vectors[3].z = v3.z;
+ vectors[3].w = v3.w;
+}
+
+void Launcher::UpdateIconXForm (std::list<Launcher::RenderArg> &args)
+{
+ nux::Geometry geo = GetGeometry ();
+ nux::Matrix4 ObjectMatrix;
+ nux::Matrix4 ViewMatrix;
+ nux::Matrix4 ProjectionMatrix;
+ nux::Matrix4 ViewProjectionMatrix;
+
+ GetInverseScreenPerspectiveMatrix(ViewMatrix, ProjectionMatrix, geo.width, geo.height, 0.1f, 1000.0f, DEGTORAD(90));
+
+ //LauncherModel::iterator it;
+ std::list<Launcher::RenderArg>::iterator it;
+ for(it = args.begin(); it != args.end(); it++)
+ {
+ if ((*it).skip)
+ continue;
+
+ LauncherIcon* launcher_icon = (*it).icon;
+
+ // We to store the icon angle in the icons itself. Makes one thing easier afterward.
+ launcher_icon->_folding_angle = (*it).folding_rads;
+
+ float w = _icon_size;
+ float h = _icon_size;
+ float x = (*it).center.x - w/2.0f; // x: top left corner
+ float y = (*it).center.y - h/2.0f; // y: top left corner
+ float z = (*it).center.z;
+
+ ObjectMatrix = nux::Matrix4::TRANSLATE(geo.width/2.0f, geo.height/2.0f, z) * // Translate the icon to the center of the viewport
+ nux::Matrix4::ROTATEX((*it).folding_rads) * // rotate the icon
+ nux::Matrix4::TRANSLATE(-x - w/2.0f, -y - h/2.0f, -z); // Put the center the icon to (0, 0)
+
+ ViewProjectionMatrix = ProjectionMatrix*ViewMatrix*ObjectMatrix;
+
+ SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "Tile");
+
+ w = _icon_image_size;
+ h = _icon_image_size;
+ x = (*it).center.x - _icon_size/2.0f + _icon_image_size_delta/2.0f;
+ y = (*it).center.y - _icon_size/2.0f + _icon_image_size_delta/2.0f;
+ z = (*it).center.z;
+
+ SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "Image");
+
+ w = _icon_glow_size;
+ h = _icon_glow_size;
+ x = (*it).center.x - _icon_glow_size/2.0f;
+ y = (*it).center.y - _icon_glow_size/2.0f;
+ z = (*it).center.z;
+
+ SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "Glow");
+
+ w = geo.width + 2;
+ h = _icon_size + _space_between_icons;
+ x = (*it).center.x - w/2.0f;
+ y = (*it).center.y - h/2.0f;
+ z = (*it).center.z;
+
+ SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "HitArea");
+ }
+}
+
+void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
+ int ViewportWidth,
+ int ViewportHeight,
+ float NearClipPlane,
+ float FarClipPlane,
+ float Fovy)
+{
+/*
+ Objective:
+ Given a perspective matrix defined by (Fovy, AspectRatio, NearPlane, FarPlane), we want to compute
+ the ModelView matrix that transform a quad defined by its top-left coord (0, 0) and its
+ bottom-right coord (WindowWidth, WindowHeight) into a full screen quad that covers the entire viewport (one to one).
+ Any quad that is facing the camera and whose 4 points are on the 4 guiding line of the view frustum (pyramid)
+ will always cover the entire viewport one to one (when projected on the screen).
+ So all we have to do is to define a quad with x:[-x_cs, x_cs] and y:[-y_cs, y_cs] and find the z distance in eye space (z_cs) so that
+ the quad touches the 4 guiding lines of the view frustum.
+ We consider a well centered projection view (no skewing, no oblique clipping plane, ...) and derive the following equations:
+ x_cs = AspectRatio*y_cs
+ y_cs/z_cs = tanf(Fovy/2) ==> z_cs = y_cs*1/tanf(Fovy/2) (this is the absolute value the quad depth value will be -z_cs since we are using OpenGL right hand coord system).
+
+ The quad (in camera space) facing the camera and centered around the camera view axis is defined by the points (-x_cs, y_cs) (top-left)
+ and the point (x_cs, -y_cs) (bottom-right). If we move that quad along the camera view axis and place it at a distance z_cs of the camera,
+ then its 4 corners are each on the 4 lines of the view frustum.
+
+ (-x_cs, y_cs) Camera Space
+ ^
+ __________|__________
+ | | |
+ | | |
+ | |(0, 0) |
+ |----------|----------|->
+ | | |
+ | | |
+ |__________|__________|
+ (x_cs, -y_cs)
+
+ The full-screen quad (in screen space) is defined by the point (0, 0) (top-left) and (WindowWidth, WindowHeight) (bottom-right).
+ We can choose and arbitrary value y_cs and compute the z_cs position in camera space that will produce a quad in camera space that projects into
+ the full-screen space.
+
+ (0, 0) Screen Space
+ _____________________->
+ | | |
+ | | |
+ | | |
+ |----------|----------|
+ | | |
+ | | |
+ |__________|__________|
+ v (WindowWidth, WindowHeight)
+
+ The model view matrix is the succession of transformation that convert the quad (0, 0, WindowWidth, WindowHeight) into
+ the quad (-x_cs, y_cs, x_cs, -y_cs)
+
+ Screen Space Camera Space
+ x ----> x_ = x*2*x_cs/WindowWidth - x_cs
+ y ----> y_ = -y*2*y_cs/WindowHeight + y_cs
+ z ----> z_ = A*z -y_cs*1/tanf(Fovy/2)
+ where A is a coefficient that can attenuate the rate of change in depth when the quad moves along the camera axis
+
+ If the following is the projection matrix:
+
+ (a, 0, 0, 0) a = 1/(AspectRatio*tan(Fovy/2))
+ (0, b, 0, 0) b = 1/tan(Fovy/2)
+ (0, 0, c, d)
+ (0, 0, -1, 0)
+
+ and the camera space vertex is (x_cs, y_cs, z_cs, w_cs) projects to the top left corner of the view port on the screen ((-1, 1) in clip space), then
+ x_cs*a/(-z_cs) = -1; | z_cs = x_cs*a x_cs*a = -y_cs*b ==> x_cs = y_cs*AspectRatio
+ | ==> ==>
+ y_cs*b/(-z_cs) = +1; | z_cs = -y_cs*b z_cs = -y_cs*1/tanf(Fovy/2)
+*/
+
+
+ float AspectRatio = (float)ViewportWidth/(float)ViewportHeight;
+ float CameraToScreenDistance = -1.0f;
+ float y_cs = -CameraToScreenDistance*tanf(0.5f*Fovy/* *3.1415926/180.0f*/);
+ float x_cs = y_cs*AspectRatio;
+ //float CameraToScreenDistance = -y_cs*1.0f/(tanf(0.5f*Fovy/* *3.1415926/180.0f*/));
+
+ ViewMatrix = nux::Matrix4::TRANSLATE(-x_cs, y_cs, CameraToScreenDistance) *
+ nux::Matrix4::SCALE(2.0f*x_cs/ViewportWidth, -2.0f*y_cs/ViewportHeight, -2.0f * 3 * y_cs/ViewportHeight /* or -2.0f * x_cs/ViewportWidth*/ );
+
+ PerspectiveMatrix.Perspective(Fovy, AspectRatio, NearClipPlane, FarClipPlane);
+
+// // Example usage with the matrices above:
+// float W = 300;
+// float H = 300;
+// // centered quad
+// float X = (ViewportWidth - W)/2.0;
+// float Y = (ViewportHeight - H)/2.0;
+// float Z = 0.0f;
+//
+// {
+// glPushMatrix();
+// // Local Transformation of the object
+// glTranslatef(0.0f, 0.0f, ObjectDistanceToCamera);
+// glTranslatef(X + W/2.0f, Y + H/2.0f, 0.0f);
+// glRotatef(cameraAngleY, 1, 0, 0);
+// glRotatef(cameraAngleX, 0, 1, 0);
+// glTranslatef(-X - W/2.0f, -Y - H/2.0f, 0.0f);
+//
+// glBegin(GL_QUADS);
+// {
+// glNormal3f(0.0f, 0.0f, 1.0f);
+//
+// glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+// glVertex4f(X, Y, Z, 1.0f);
+//
+// glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
+// glVertex4f(X, Y+H, Z, 1.0f);
+//
+// glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
+// glVertex4f(X+W, Y+H, Z, 1.0f);
+//
+// glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
+// glVertex4f(X+W, Y, Z, 1.0f);
+// }
+// glEnd();
+}
+
+void Launcher::SetActiveQuicklist (QuicklistView *quicklist)
+{
+ // Assert: _active_quicklist should be 0
+ _active_quicklist = quicklist;
+}
+
+QuicklistView *Launcher::GetActiveQuicklist ()
+{
+ return _active_quicklist;
+}
+
+void Launcher::CancelActiveQuicklist (QuicklistView *quicklist)
+{
+ if (_active_quicklist == quicklist)
+ _active_quicklist = 0;
+}
+
diff --git a/src/Launcher.h b/src/Launcher.h
index 2fd3345ef..b55111c2d 100644
--- a/src/Launcher.h
+++ b/src/Launcher.h
@@ -1,245 +1,264 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authored by: Jason Smith <jason.smith@canonical.com>
- * Authored by: Jay Taoko <jay.taoko@canonical.com>
- */
-
-#ifndef LAUNCHER_H
-#define LAUNCHER_H
-
-#include <sys/time.h>
-
-#include <Nux/View.h>
-#include <Nux/BaseWindow.h>
-#include "Introspectable.h"
-#include "LauncherIcon.h"
-#include "NuxGraphics/IOpenGLAsmShader.h"
-#include "Nux/TimerProc.h"
-
-class LauncherModel;
-class QuicklistView;
-
-class Launcher : public Introspectable, public nux::View
-{
-public:
- Launcher(nux::BaseWindow *parent, NUX_FILE_LINE_PROTO);
- ~Launcher();
-
- virtual long ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo);
- virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
- virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
- virtual void PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw);
-
- LauncherIcon* GetActiveTooltipIcon() {return m_ActiveTooltipIcon;}
- LauncherIcon* GetActiveMenuIcon() {return m_ActiveMenuIcon;}
-
- bool TooltipNotify(LauncherIcon* Icon);
- bool MenuNotify(LauncherIcon* Icon);
-
- void SetIconSize(int tile_size, int icon_size);
- void NotifyMenuTermination(LauncherIcon* Icon);
-
- void SetModel (LauncherModel *model);
-
- void SetFloating (bool floating);
-
- void SetAutohide (bool autohide, nux::View *show_trigger);
- bool AutohideEnabled ();
-
- 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);
-
- //! Called by LauncherIcon to signal that a Quicklist is becoming active.
- void SetActiveQuicklist (QuicklistView *quicklist);
- //! Get the active qicklist
- QuicklistView *GetActiveQuicklist ();
- //! Called by LauncherIcon to signal that a Quicklist is becoming unactive.
- void CancelActiveQuicklist (QuicklistView *quicklist);
-
-protected:
- // Introspectable methods
- const gchar* GetName ();
- void AddProperties (GVariantBuilder *builder);
-
-private:
- typedef enum
- {
- LAUNCHER_FOLDED,
- LAUNCHER_UNFOLDED
- } LauncherState;
-
- typedef enum
- {
- ACTION_NONE,
- ACTION_DRAG_LAUNCHER,
- ACTION_DRAG_ICON,
- } LauncherActionState;
-
- typedef struct
- {
- LauncherIcon *icon;
- nux::Point3 center;
- float folding_rads;
- float alpha;
- float backlight_intensity;
- float glow_intensity;
- float shimmer_progress;
- bool running_arrow;
- bool active_arrow;
- bool skip;
- int window_indicators;
- } RenderArg;
-
- static gboolean AnimationTimeout (gpointer data);
- static gboolean OnAutohideTimeout (gpointer data);
- static gboolean StrutHack (gpointer data);
-
- void OnTriggerMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags);
- void OnTriggerMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags);
-
- bool IconNeedsAnimation (LauncherIcon *icon, struct timespec current);
- bool AnimationInProgress ();
- void SetTimeStruct (struct timespec *timer, struct timespec *sister = 0, int sister_relation = 0);
-
- void EnsureAnimation ();
- void SetupAutohideTimer ();
-
- float DnDExitProgress ();
- float GetHoverProgress ();
- float AutohideProgress ();
- float IconPresentProgress (LauncherIcon *icon, struct timespec current);
- float IconUrgentProgress (LauncherIcon *icon, struct timespec current);
- float IconShimmerProgress (LauncherIcon *icon, struct timespec current);
- float IconUrgentPulseValue (LauncherIcon *icon, struct timespec current);
- float IconStartingPulseValue (LauncherIcon *icon, struct timespec current);
- float IconBackgroundIntensity (LauncherIcon *icon, struct timespec current);
-
- void SetHover ();
- void UnsetHover ();
- void SetHidden (bool hidden);
-
- void SetDndDelta (float x, float y, nux::Geometry geo, struct timespec current);
-
- void SetupRenderArg (LauncherIcon *icon, struct timespec current, RenderArg &arg);
- void RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
- std::list<Launcher::RenderArg> &shelf_args,
- nux::Geometry &box_geo, nux::Geometry &shelf_geo);
-
- void DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg arg, nux::Geometry geo);
-
- void OnIconAdded (void *icon_pointer);
- void OnIconRemoved (void *icon_pointer);
- void OnOrderChanged ();
-
- void OnIconNeedsRedraw (void *icon);
-
- void RenderIcon (nux::GraphicsEngine& GfxContext,
- RenderArg arg,
- nux::BaseTexture *icon,
- nux::Color bkg_color,
- float alpha,
- nux::Vector4 xform_coords[],
- nux::Geometry geo,
- bool render_indicators);
-
- void SetIconXForm (LauncherIcon *icon, nux::Matrix4 ViewProjectionMatrix, nux::Geometry geo,
- float x, float y, float w, float h, float z, std::string name);
- void UpdateIconXForm (std::list<Launcher::RenderArg> args);
-
- LauncherIcon* MouseIconIntersection (int x, int y);
- 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);
-
- virtual void PreLayoutManagement();
- virtual long PostLayoutManagement(long LayoutResult);
- virtual void PositionChildLayout(float offsetX, float offsetY);
-
-
- nux::HLayout* m_Layout;
- int m_ContentOffsetY;
-
- LauncherIcon* m_ActiveTooltipIcon;
- LauncherIcon* m_ActiveMenuIcon;
-
-
- QuicklistView* _active_quicklist;
-
- bool _hovered;
- bool _floating;
- bool _autohide;
- bool _hidden;
- bool _mouse_inside_launcher;
-
- float _folded_angle;
- float _neg_folded_angle;
- float _folded_z_distance;
- float _launcher_top_y;
- float _launcher_bottom_y;
-
- LauncherState _launcher_state;
- LauncherActionState _launcher_action_state;
- LauncherIcon* _icon_under_mouse;
- LauncherIcon* _icon_mouse_down;
-
- int _space_between_icons;
- int _icon_size;
- int _icon_image_size;
- int _icon_image_size_delta;
- int _icon_glow_size;
- int _dnd_delta;
- int _dnd_security;
- int _enter_y;
-
- nux::BaseTexture* _icon_bkg_texture;
- nux::BaseTexture* _icon_shine_texture;
- nux::BaseTexture* _icon_outline_texture;
- nux::BaseTexture* _icon_glow_texture;
- nux::BaseTexture* _icon_2indicator;
- nux::BaseTexture* _icon_3indicator;
- nux::BaseTexture* _icon_4indicator;
-
- guint _anim_handle;
- guint _autohide_handle;
-
- nux::Matrix4 _view_matrix;
- nux::Matrix4 _projection_matrix;
- nux::Point2 _mouse_position;
- nux::IntrusiveSP<nux::IOpenGLShaderProgram> _shader_program_uv_persp_correction;
- nux::IntrusiveSP<nux::IOpenGLAsmShaderProgram> _AsmShaderProg;
- nux::BaseTexture* m_RunningIndicator;
- nux::BaseTexture* m_ActiveIndicator;
- nux::AbstractPaintLayer* m_BackgroundLayer;
- nux::BaseWindow* _parent;
- nux::View* _autohide_trigger;
- nux::Geometry _last_shelf_area;
- LauncherModel* _model;
-
- /* event times */
- struct timespec _enter_time;
- struct timespec _exit_time;
- struct timespec _drag_end_time;
- struct timespec _autohide_time;
-};
-
-#endif // LAUNCHER_H
-
-
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Jason Smith <jason.smith@canonical.com>
+ * Authored by: Jay Taoko <jay.taoko@canonical.com>
+ */
+
+#ifndef LAUNCHER_H
+#define LAUNCHER_H
+
+#include <sys/time.h>
+#include <core/core.h>
+
+#include <Nux/View.h>
+#include <Nux/BaseWindow.h>
+#include "Introspectable.h"
+#include "LauncherIcon.h"
+#include "NuxGraphics/IOpenGLAsmShader.h"
+#include "Nux/TimerProc.h"
+
+class LauncherModel;
+class QuicklistView;
+
+class Launcher : public Introspectable, public nux::View
+{
+public:
+ Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_PROTO);
+ ~Launcher();
+
+ virtual long ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo);
+ virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
+ virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
+ virtual void PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw);
+
+ LauncherIcon* GetActiveTooltipIcon() {return m_ActiveTooltipIcon;}
+ LauncherIcon* GetActiveMenuIcon() {return m_ActiveMenuIcon;}
+
+ bool TooltipNotify(LauncherIcon* Icon);
+ bool MenuNotify(LauncherIcon* Icon);
+
+ void SetIconSize(int tile_size, int icon_size);
+ void NotifyMenuTermination(LauncherIcon* Icon);
+
+ void SetModel (LauncherModel *model);
+
+ void SetFloating (bool floating);
+
+ void SetAutohide (bool autohide, nux::View *show_trigger);
+ bool AutohideEnabled ();
+
+ void OnWindowMoved (CompWindow *window);
+ void OnWindowResized (CompWindow *window);
+ void OnWindowAppear (CompWindow *window);
+ void OnWindowDisappear (CompWindow *window);
+
+ 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);
+
+ //! Called by LauncherIcon to signal that a Quicklist is becoming active.
+ void SetActiveQuicklist (QuicklistView *quicklist);
+ //! Get the active qicklist
+ QuicklistView *GetActiveQuicklist ();
+ //! Called by LauncherIcon to signal that a Quicklist is becoming unactive.
+ void CancelActiveQuicklist (QuicklistView *quicklist);
+
+protected:
+ // Introspectable methods
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
+
+private:
+ typedef enum
+ {
+ LAUNCHER_FOLDED,
+ LAUNCHER_UNFOLDED
+ } LauncherState;
+
+ typedef enum
+ {
+ ACTION_NONE,
+ ACTION_DRAG_LAUNCHER,
+ ACTION_DRAG_ICON,
+ } LauncherActionState;
+
+ typedef struct
+ {
+ LauncherIcon *icon;
+ nux::Point3 center;
+ float folding_rads;
+ float alpha;
+ float backlight_intensity;
+ float glow_intensity;
+ float shimmer_progress;
+ bool running_arrow;
+ bool running_colored;
+ bool active_arrow;
+ bool active_colored;
+ bool skip;
+ int window_indicators;
+ } RenderArg;
+
+ static gboolean AnimationTimeout (gpointer data);
+ static gboolean OnAutohideTimeout (gpointer data);
+ static gboolean StrutHack (gpointer data);
+
+ void OnTriggerMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags);
+ void OnTriggerMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags);
+
+ bool IconNeedsAnimation (LauncherIcon *icon, struct timespec const &current);
+ bool AnimationInProgress ();
+ void SetTimeStruct (struct timespec *timer, struct timespec *sister = 0, int sister_relation = 0);
+
+ void EnsureHiddenState ();
+ void EnsureAnimation ();
+ void SetupAutohideTimer ();
+
+ void CheckWindowOverLauncher ();
+
+ float DnDExitProgress (struct timespec const &current);
+ float GetHoverProgress (struct timespec const &current);
+ float AutohideProgress (struct timespec const &current);
+ float IconPresentProgress (LauncherIcon *icon, struct timespec const &current);
+ float IconUrgentProgress (LauncherIcon *icon, struct timespec const &current);
+ float IconShimmerProgress (LauncherIcon *icon, struct timespec const &current);
+ float IconUrgentPulseValue (LauncherIcon *icon, struct timespec const &current);
+ float IconStartingPulseValue (LauncherIcon *icon, struct timespec const &current);
+ float IconBackgroundIntensity (LauncherIcon *icon, struct timespec const &current);
+
+ void SetHover ();
+ void UnsetHover ();
+ void SetHidden (bool hidden);
+
+ void SetDndDelta (float x, float y, nux::Geometry geo, struct timespec const &current);
+ float DragLimiter (float x);
+
+ void SetupRenderArg (LauncherIcon *icon, struct timespec const &current, RenderArg &arg);
+ void RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
+ nux::Geometry &box_geo);
+
+ void DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg const &arg, nux::Geometry geo);
+
+ void OnIconAdded (void *icon_pointer);
+ void OnIconRemoved (void *icon_pointer);
+ void OnOrderChanged ();
+
+ void OnIconNeedsRedraw (void *icon);
+
+ void RenderIndicators (nux::GraphicsEngine& GfxContext,
+ RenderArg const &arg,
+ int running,
+ int active,
+ nux::Geometry geo);
+
+ void RenderIcon (nux::GraphicsEngine& GfxContext,
+ RenderArg const &arg,
+ nux::BaseTexture *icon,
+ nux::Color bkg_color,
+ float alpha,
+ nux::Vector4 xform_coords[],
+ nux::Geometry geo);
+
+ void SetIconXForm (LauncherIcon *icon, nux::Matrix4 ViewProjectionMatrix, nux::Geometry geo,
+ float x, float y, float w, float h, float z, std::string name);
+ void UpdateIconXForm (std::list<Launcher::RenderArg> &args);
+
+ LauncherIcon* MouseIconIntersection (int x, int y);
+ 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);
+
+ virtual void PreLayoutManagement();
+ virtual long PostLayoutManagement(long LayoutResult);
+ virtual void PositionChildLayout(float offsetX, float offsetY);
+
+
+ nux::HLayout* m_Layout;
+ int m_ContentOffsetY;
+
+ LauncherIcon* m_ActiveTooltipIcon;
+ LauncherIcon* m_ActiveMenuIcon;
+
+
+ QuicklistView* _active_quicklist;
+
+ bool _hovered;
+ bool _floating;
+ bool _autohide;
+ bool _hidden;
+ bool _mouse_inside_launcher;
+ bool _mouse_inside_trigger;
+ bool _window_over_launcher;
+
+ float _folded_angle;
+ float _neg_folded_angle;
+ float _folded_z_distance;
+ float _launcher_top_y;
+ float _launcher_bottom_y;
+
+ LauncherState _launcher_state;
+ LauncherActionState _launcher_action_state;
+ LauncherIcon* _icon_under_mouse;
+ LauncherIcon* _icon_mouse_down;
+
+ int _space_between_icons;
+ int _icon_size;
+ int _icon_image_size;
+ int _icon_image_size_delta;
+ int _icon_glow_size;
+ int _dnd_delta;
+ int _dnd_security;
+ int _enter_y;
+
+ nux::BaseTexture* _icon_bkg_texture;
+ nux::BaseTexture* _icon_shine_texture;
+ nux::BaseTexture* _icon_outline_texture;
+ nux::BaseTexture* _icon_glow_texture;
+ nux::BaseTexture* _icon_2indicator;
+ nux::BaseTexture* _icon_3indicator;
+ nux::BaseTexture* _icon_4indicator;
+
+ guint _anim_handle;
+ guint _autohide_handle;
+
+ nux::Matrix4 _view_matrix;
+ nux::Matrix4 _projection_matrix;
+ nux::Point2 _mouse_position;
+ nux::IntrusiveSP<nux::IOpenGLShaderProgram> _shader_program_uv_persp_correction;
+ nux::IntrusiveSP<nux::IOpenGLAsmShaderProgram> _AsmShaderProg;
+ nux::BaseTexture* m_RunningIndicator;
+ nux::BaseTexture* m_ActiveIndicator;
+ nux::AbstractPaintLayer* m_BackgroundLayer;
+ nux::BaseWindow* _parent;
+ nux::View* _autohide_trigger;
+ LauncherModel* _model;
+
+ CompScreen* _screen;
+
+ /* event times */
+ struct timespec _enter_time;
+ struct timespec _exit_time;
+ struct timespec _drag_end_time;
+ struct timespec _autohide_time;
+};
+
+#endif // LAUNCHER_H
+
+
diff --git a/src/LauncherController.cpp b/src/LauncherController.cpp
index 5d5996661..43d45675e 100644
--- a/src/LauncherController.cpp
+++ b/src/LauncherController.cpp
@@ -72,8 +72,11 @@ LauncherController::PresentIconOwningWindow (Window window)
}
}
- owner->Present (2, 600);
- owner->UpdateQuirkTimeDelayed (300, LAUNCHER_ICON_QUIRK_SHIMMER);
+ if (owner)
+ {
+ owner->Present (0.5f, 600);
+ owner->UpdateQuirkTimeDelayed (300, LAUNCHER_ICON_QUIRK_SHIMMER);
+ }
}
void
@@ -177,6 +180,8 @@ LauncherController::CreateFavorite (const char *file_path)
BamfLauncherIcon *icon;
app = bamf_matcher_get_application_for_desktop_file (_matcher, file_path, true);
+ if (!app)
+ return NULL;
if (g_object_get_qdata (G_OBJECT (app), g_quark_from_static_string ("unity-seen")))
{
diff --git a/src/LauncherIcon.cpp b/src/LauncherIcon.cpp
index 0cbe5f36a..d78eace30 100755..100644
--- a/src/LauncherIcon.cpp
+++ b/src/LauncherIcon.cpp
@@ -1,555 +1,620 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authored by: Jason Smith <jason.smith@canonical.com>
- */
-
-#include <sys/time.h>
-
-#include "Nux/Nux.h"
-#include "Nux/VScrollBar.h"
-#include "Nux/HLayout.h"
-#include "Nux/VLayout.h"
-#include "Nux/MenuPage.h"
-#include "Nux/WindowCompositor.h"
-#include "Nux/BaseWindow.h"
-#include "Nux/MenuPage.h"
-#include "NuxCore/Color.h"
-
-#include "LauncherIcon.h"
-#include "Launcher.h"
-
-#include "QuicklistMenuItem.h"
-#include "QuicklistMenuItemLabel.h"
-#include "QuicklistMenuItemSeparator.h"
-#include "QuicklistMenuItemCheckmark.h"
-#include "QuicklistMenuItemRadio.h"
-
-#define DEFAULT_ICON "application-default-icon"
-
-nux::Tooltip *LauncherIcon::_current_tooltip = 0;
-QuicklistView *LauncherIcon::_current_quicklist = 0;
-
-LauncherIcon::LauncherIcon(Launcher* launcher)
-{
- _folding_angle = 0;
- _launcher = launcher;
- m_TooltipText = "blank";
-
- for (int i = 0; i < LAUNCHER_ICON_QUIRK_LAST; i++)
- {
- _quirks[i] = 0;
- _quirk_times[i].tv_sec = 0;
- _quirk_times[i].tv_nsec = 0;
- }
-
- _related_windows = 0;
-
- _background_color = nux::Color::White;
- _glow_color = nux::Color::White;
-
- _mouse_inside = false;
- _tooltip = new nux::Tooltip ();
- _icon_type = LAUNCHER_ICON_TYPE_NONE;
- _sort_priority = 0;
-
- _quicklist = new QuicklistView ();
- _quicklist->sigVisible.connect (sigc::mem_fun (this, &LauncherIcon::RecvShowQuicklist));
- _quicklist->sigHidden.connect (sigc::mem_fun (this, &LauncherIcon::RecvHideQuicklist));
- _quicklist_is_initialized = false;
-
- MouseEnter.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseEnter));
- MouseLeave.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseLeave));
- MouseDown.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseDown));
- MouseUp.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseUp));
-
-}
-
-LauncherIcon::~LauncherIcon()
-{
- if (_present_time_handle)
- g_source_remove (_present_time_handle);
- _present_time_handle = 0;
-
- if (_center_stabilize_handle)
- g_source_remove (_center_stabilize_handle);
- _center_stabilize_handle = 0;
-}
-
-nux::Color LauncherIcon::BackgroundColor ()
-{
- return _background_color;
-}
-
-nux::Color LauncherIcon::GlowColor ()
-{
- return _glow_color;
-}
-
-nux::BaseTexture * LauncherIcon::TextureForSize (int size)
-{
- nux::BaseTexture * result = GetTextureForSize (size);
- return result;
-}
-
-void LauncherIcon::ColorForIcon (GdkPixbuf *pixbuf, nux::Color &background, nux::Color &glow)
-{
- unsigned int width = gdk_pixbuf_get_width (pixbuf);
- unsigned int height = gdk_pixbuf_get_height (pixbuf);
- unsigned int row_bytes = gdk_pixbuf_get_rowstride (pixbuf);
-
- long int rtotal = 0, gtotal = 0, btotal = 0;
- float total = 0.0f;
-
-
- guchar *img = gdk_pixbuf_get_pixels (pixbuf);
-
- for (unsigned int i = 0; i < width; i++)
- {
- for (unsigned int j = 0; j < height; j++)
- {
- guchar *pixels = img + ( j * row_bytes + i * 4);
- guchar r = *(pixels + 0);
- guchar g = *(pixels + 1);
- guchar b = *(pixels + 2);
- guchar a = *(pixels + 3);
-
- float saturation = (MAX (r, MAX (g, b)) - MIN (r, MIN (g, b))) / 255.0f;
- float relevance = .1 + .9 * (a / 255.0f) * saturation;
-
- rtotal += (guchar) (r * relevance);
- gtotal += (guchar) (g * relevance);
- btotal += (guchar) (b * relevance);
-
- total += relevance * 255;
- }
- }
-
- float r, g, b, h, s, v;
- r = rtotal / total;
- g = gtotal / total;
- b = btotal / total;
-
- nux::RGBtoHSV (r, g, b, h, s, v);
-
- if (s > .15f)
- s = 0.4f;
- v = .85f;
-
- nux::HSVtoRGB (r, g, b, h, s, v);
- background = nux::Color (r, g, b);
-
- v = 1.0f;
- nux::HSVtoRGB (r, g, b, h, s, v);
- glow = nux::Color (r, g, b);
-}
-
-nux::BaseTexture * LauncherIcon::TextureFromGtkTheme (const char *icon_name, int size)
-{
- GdkPixbuf *pbuf;
- GtkIconTheme *theme;
- GtkIconInfo *info;
- nux::BaseTexture *result;
- GError *error = NULL;
-
- theme = gtk_icon_theme_get_default ();
-
- if (!icon_name)
- icon_name = g_strdup (DEFAULT_ICON);
-
- info = gtk_icon_theme_lookup_icon (theme,
- icon_name,
- size,
- (GtkIconLookupFlags) 0);
- if (!info)
- {
- info = gtk_icon_theme_lookup_icon (theme,
- DEFAULT_ICON,
- size,
- (GtkIconLookupFlags) 0);
- }
-
- if (gtk_icon_info_get_filename (info) == NULL)
- {
- info = gtk_icon_theme_lookup_icon (theme,
- DEFAULT_ICON,
- size,
- (GtkIconLookupFlags) 0);
- }
-
- pbuf = gtk_icon_info_load_icon (info, &error);
-
- if (GDK_IS_PIXBUF (pbuf))
- {
- result = nux::CreateTextureFromPixbuf (pbuf);
- ColorForIcon (pbuf, _background_color, _glow_color);
-
- g_object_unref (pbuf);
- }
- else
- {
- g_warning ("Unable to load '%s' from icon theme: %s",
- icon_name,
- error ? error->message : "unknown");
-
- if (g_strcmp0 (icon_name, "folder") == 0)
- return NULL;
- else
- return TextureFromGtkTheme ("folder", size);
- }
-
- return result;
-}
-
-void LauncherIcon::SetTooltipText(const TCHAR* text)
-{
- m_TooltipText = text;
- _tooltip->SetText (m_TooltipText);
-}
-
-nux::NString LauncherIcon::GetTooltipText()
-{
- return m_TooltipText;
-}
-
-void
-LauncherIcon::RecvMouseEnter ()
-{
- if (_launcher->GetActiveQuicklist ())
- {
- // A quicklist is active
- return;
- }
-
- int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
- int tip_y = _center.y;
-
- _tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
-
- if (!_quicklist->IsVisible ())
- {
- _tooltip->ShowWindow (true);
- }
-}
-
-void LauncherIcon::RecvMouseLeave ()
-{
- _tooltip->ShowWindow (false);
-}
-
-void LauncherIcon::RecvMouseDown (int button)
-{
- if (button == 3)
- {
- if (_launcher->GetActiveQuicklist () == _quicklist)
- {
- // this quicklist is already active
- return;
- }
-
- if (_launcher->GetActiveQuicklist ())
- {
- // Hide the active quicklist. This will prevent it from Ungrabing the pointer in
- // QuicklistView::RecvMouseDownOutsideOfQuicklist or void QuicklistView::RecvMouseClick.
- // So the new quicklist that is about to be set as active will keep the grab of the pointer.
- // Also disable theinput window.
- _launcher->GetActiveQuicklist ()->EnableInputWindow (false);
- _launcher->GetActiveQuicklist ()->CaptureMouseDownAnyWhereElse (false);
- // This call must be last, because after, _launcher->GetActiveQuicklist () will return Null.
- // the launcher listen to the sigHidden signal emitted by the BaseWindow when it becomes invisible
- // and it set the active window to Null.
- _launcher->GetActiveQuicklist ()->ShowWindow (false);
- }
-
- _tooltip->ShowWindow (false);
-
- _quicklist->RemoveAllMenuItem ();
-
- std::list<DbusmenuMenuitem *> menus = Menus ();
- if (menus.empty ())
- return;
-
- std::list<DbusmenuMenuitem *>::iterator it;
- for (it = menus.begin (); it != menus.end (); it++)
- {
- DbusmenuMenuitem *menu_item = *it;
-
- const gchar* type = dbusmenu_menuitem_property_get (menu_item, DBUSMENU_MENUITEM_PROP_TYPE);
- const gchar* toggle_type = dbusmenu_menuitem_property_get (menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE);
-
- if (g_strcmp0 (type, DBUSMENU_CLIENT_TYPES_SEPARATOR) == 0)
- {
- QuicklistMenuItemSeparator* item = new QuicklistMenuItemSeparator (menu_item, NUX_TRACKER_LOCATION);
- _quicklist->AddMenuItem (item);
- }
- else if (g_strcmp0 (toggle_type, DBUSMENU_MENUITEM_TOGGLE_CHECK) == 0)
- {
- QuicklistMenuItemCheckmark* item = new QuicklistMenuItemCheckmark (menu_item, NUX_TRACKER_LOCATION);
- _quicklist->AddMenuItem (item);
- }
- else if (g_strcmp0 (toggle_type, DBUSMENU_MENUITEM_TOGGLE_RADIO) == 0)
- {
- QuicklistMenuItemRadio* item = new QuicklistMenuItemRadio (menu_item, NUX_TRACKER_LOCATION);
- _quicklist->AddMenuItem (item);
- }
- else //(g_strcmp0 (type, DBUSMENU_MENUITEM_PROP_LABEL) == 0)
- {
- QuicklistMenuItemLabel* item = new QuicklistMenuItemLabel (menu_item, NUX_TRACKER_LOCATION);
- _quicklist->AddMenuItem (item);
- }
- }
-
- int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
- int tip_y = _center.y;
- _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
-
- _quicklist->EnableInputWindow (true, 1);
- _quicklist->GrabPointer ();
-
- nux::GetWindowCompositor ().SetAlwaysOnFrontWindow (_quicklist);
-
- _quicklist->NeedRedraw ();
- }
-}
-
-void LauncherIcon::RecvMouseUp (int button)
-{
- if (button == 3)
- {
- if (_quicklist->IsVisible ())
- _quicklist->CaptureMouseDownAnyWhereElse (true);
- }
-}
-
-void LauncherIcon::RecvShowQuicklist (nux::BaseWindow *quicklist)
-{
- _launcher->SetActiveQuicklist (_quicklist);
-}
-
-void LauncherIcon::RecvHideQuicklist (nux::BaseWindow *quicklist)
-{
- _launcher->CancelActiveQuicklist (_quicklist);
-}
-
-void LauncherIcon::HideTooltip ()
-{
- _tooltip->ShowWindow (false);
-}
-
-gboolean
-LauncherIcon::OnCenterTimeout (gpointer data)
-{
- LauncherIcon *self = (LauncherIcon*)data;
-
- if (self->_last_stable != self->_center)
- {
- self->OnCenterStabilized (self->_center);
- self->_last_stable = self->_center;
- }
-
- self->_center_stabilize_handle = 0;
- return false;
-}
-
-void
-LauncherIcon::SetCenter (nux::Point3 center)
-{
- _center = center;
-
- int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
- int tip_y = _center.y;
-
- if (_quicklist->IsVisible ())
- _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
- else if (_tooltip->IsVisible ())
- _tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
-
- if (_center_stabilize_handle)
- g_source_remove (_center_stabilize_handle);
-
- _center_stabilize_handle = g_timeout_add (500, &LauncherIcon::OnCenterTimeout, this);
-}
-
-nux::Point3
-LauncherIcon::GetCenter ()
-{
- return _center;
-}
-
-gboolean
-LauncherIcon::OnPresentTimeout (gpointer data)
-{
- LauncherIcon *self = (LauncherIcon*) data;
- if (!self->GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
- return false;
-
- self->_present_time_handle = 0;
- self->Unpresent ();
-
- return false;
-}
-
-int LauncherIcon::PresentUrgency ()
-{
- return _present_urgency;
-}
-
-void
-LauncherIcon::Present (int present_urgency, int length)
-{
- if (GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
- return;
-
- if (length >= 0)
- _present_time_handle = g_timeout_add (length, &LauncherIcon::OnPresentTimeout, this);
-
- _present_urgency = present_urgency;
- SetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED, true);
-}
-
-void
-LauncherIcon::Unpresent ()
-{
- if (!GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
- return;
-
- if (_present_time_handle > 0)
- g_source_remove (_present_time_handle);
-
- SetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED, false);
-}
-
-void
-LauncherIcon::SetRelatedWindows (int windows)
-{
- if (_related_windows == windows)
- return;
-
- _related_windows = windows;
- needs_redraw.emit (this);
-}
-
-void
-LauncherIcon::Remove ()
-{
- SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, false);
- remove.emit (this);
-}
-
-void
-LauncherIcon::SetIconType (LauncherIconType type)
-{
- _icon_type = type;
-}
-
-void
-LauncherIcon::SetSortPriority (int priority)
-{
- _sort_priority = priority;
-}
-
-int
-LauncherIcon::SortPriority ()
-{
- return _sort_priority;
-}
-
-LauncherIconType
-LauncherIcon::Type ()
-{
- return _icon_type;
-}
-
-bool
-LauncherIcon::GetQuirk (LauncherIconQuirk quirk)
-{
- return _quirks[quirk];
-}
-
-void
-LauncherIcon::SetQuirk (LauncherIconQuirk quirk, bool value)
-{
- if (_quirks[quirk] == value)
- return;
-
- _quirks[quirk] = value;
- clock_gettime (CLOCK_MONOTONIC, &(_quirk_times[quirk]));
- needs_redraw.emit (this);
-
- // Present on urgent as a general policy
- if (quirk == LAUNCHER_ICON_QUIRK_VISIBLE && value)
- Present (0, 1500);
- if (quirk == LAUNCHER_ICON_QUIRK_URGENT && value)
- Present (1, 1500);
-}
-
-gboolean
-LauncherIcon::OnDelayedUpdateTimeout (gpointer data)
-{
- DelayedUpdateArg *arg = (DelayedUpdateArg *) data;
- LauncherIcon *self = arg->self;
-
- clock_gettime (CLOCK_MONOTONIC, &(self->_quirk_times[arg->quirk]));
- self->needs_redraw.emit (self);
-
- return false;
-}
-
-void
-LauncherIcon::UpdateQuirkTimeDelayed (guint ms, LauncherIconQuirk quirk)
-{
- DelayedUpdateArg *arg = new DelayedUpdateArg ();
- arg->self = this;
- arg->quirk = quirk;
-
- g_timeout_add (ms, &LauncherIcon::OnDelayedUpdateTimeout, arg);
-}
-
-void
-LauncherIcon::UpdateQuirkTime (LauncherIconQuirk quirk)
-{
- clock_gettime (CLOCK_MONOTONIC, &(_quirk_times[quirk]));
- needs_redraw.emit (this);
-}
-
-void
-LauncherIcon::ResetQuirkTime (LauncherIconQuirk quirk)
-{
- _quirk_times[quirk].tv_sec = 0;
- _quirk_times[quirk].tv_nsec = 0;
-}
-
-struct timespec
-LauncherIcon::GetQuirkTime (LauncherIconQuirk quirk)
-{
- return _quirk_times[quirk];
-}
-
-int
-LauncherIcon::RelatedWindows ()
-{
- return _related_windows;
-}
-
-std::list<DbusmenuMenuitem *> LauncherIcon::Menus ()
-{
- return GetMenus ();
-}
-
-std::list<DbusmenuMenuitem *> LauncherIcon::GetMenus ()
-{
- std::list<DbusmenuMenuitem *> result;
- return result;
-}
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Jason Smith <jason.smith@canonical.com>
+ */
+
+#include <sys/time.h>
+
+#include "Nux/Nux.h"
+#include "Nux/VScrollBar.h"
+#include "Nux/HLayout.h"
+#include "Nux/VLayout.h"
+#include "Nux/MenuPage.h"
+#include "Nux/WindowCompositor.h"
+#include "Nux/BaseWindow.h"
+#include "Nux/MenuPage.h"
+#include "NuxCore/Color.h"
+
+#include "LauncherIcon.h"
+#include "Launcher.h"
+
+#include "QuicklistMenuItem.h"
+#include "QuicklistMenuItemLabel.h"
+#include "QuicklistMenuItemSeparator.h"
+#include "QuicklistMenuItemCheckmark.h"
+#include "QuicklistMenuItemRadio.h"
+
+#define DEFAULT_ICON "application-default-icon"
+
+nux::Tooltip *LauncherIcon::_current_tooltip = 0;
+QuicklistView *LauncherIcon::_current_quicklist = 0;
+
+LauncherIcon::LauncherIcon(Launcher* launcher)
+{
+ _folding_angle = 0;
+ _launcher = launcher;
+ m_TooltipText = "blank";
+
+ for (int i = 0; i < LAUNCHER_ICON_QUIRK_LAST; i++)
+ {
+ _quirks[i] = 0;
+ _quirk_times[i].tv_sec = 0;
+ _quirk_times[i].tv_nsec = 0;
+ }
+
+ _related_windows = 0;
+
+ _background_color = nux::Color::White;
+ _glow_color = nux::Color::White;
+
+ _mouse_inside = false;
+ _tooltip = new nux::Tooltip ();
+ _icon_type = LAUNCHER_ICON_TYPE_NONE;
+ _sort_priority = 0;
+
+ _quicklist = new QuicklistView ();
+ _quicklist->sigVisible.connect (sigc::mem_fun (this, &LauncherIcon::RecvShowQuicklist));
+ _quicklist->sigHidden.connect (sigc::mem_fun (this, &LauncherIcon::RecvHideQuicklist));
+ _quicklist_is_initialized = false;
+
+ // Add to introspection
+ AddChild (_quicklist);
+ AddChild (_tooltip);
+
+ MouseEnter.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseEnter));
+ MouseLeave.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseLeave));
+ MouseDown.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseDown));
+ MouseUp.connect (sigc::mem_fun(this, &LauncherIcon::RecvMouseUp));
+
+}
+
+LauncherIcon::~LauncherIcon()
+{
+ // Remove from introspection
+ RemoveChild (_quicklist);
+ RemoveChild (_tooltip);
+
+ if (_present_time_handle)
+ g_source_remove (_present_time_handle);
+ _present_time_handle = 0;
+
+ if (_center_stabilize_handle)
+ g_source_remove (_center_stabilize_handle);
+ _center_stabilize_handle = 0;
+}
+
+const gchar *
+LauncherIcon::GetName ()
+{
+ return "LauncherIcon";
+}
+
+void
+LauncherIcon::AddProperties (GVariantBuilder *builder)
+{
+ g_variant_builder_add (builder, "{sv}", "x", _center.x);
+ g_variant_builder_add (builder, "{sv}", "y", _center.y);
+ g_variant_builder_add (builder, "{sv}", "z", _center.z);
+ g_variant_builder_add (builder, "{sv}", "related-windows", g_variant_new_int32 (_related_windows));
+ g_variant_builder_add (builder, "{sv}", "icon-type", g_variant_new_int32 (_icon_type));
+ g_variant_builder_add (builder, "{sv}", "tooltip-text", g_variant_new_string (m_TooltipText.GetTCharPtr ()));
+
+ g_variant_builder_add (builder, "{sv}", "sort-priority", g_variant_new_int32 (_sort_priority));
+ g_variant_builder_add (builder, "{sv}", "quirk-active", g_variant_new_boolean (GetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE)));
+ g_variant_builder_add (builder, "{sv}", "quirk-visible", g_variant_new_boolean (GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE)));
+ g_variant_builder_add (builder, "{sv}", "quirk-urgent", g_variant_new_boolean (GetQuirk (LAUNCHER_ICON_QUIRK_URGENT)));
+ g_variant_builder_add (builder, "{sv}", "quirk-running", g_variant_new_boolean (GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING)));
+ g_variant_builder_add (builder, "{sv}", "quirk-presented", g_variant_new_boolean (GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED)));
+}
+
+nux::Color LauncherIcon::BackgroundColor ()
+{
+ return _background_color;
+}
+
+nux::Color LauncherIcon::GlowColor ()
+{
+ return _glow_color;
+}
+
+nux::BaseTexture * LauncherIcon::TextureForSize (int size)
+{
+ nux::BaseTexture * result = GetTextureForSize (size);
+ return result;
+}
+
+void LauncherIcon::ColorForIcon (GdkPixbuf *pixbuf, nux::Color &background, nux::Color &glow)
+{
+ unsigned int width = gdk_pixbuf_get_width (pixbuf);
+ unsigned int height = gdk_pixbuf_get_height (pixbuf);
+ unsigned int row_bytes = gdk_pixbuf_get_rowstride (pixbuf);
+
+ long int rtotal = 0, gtotal = 0, btotal = 0;
+ float total = 0.0f;
+
+
+ guchar *img = gdk_pixbuf_get_pixels (pixbuf);
+
+ for (unsigned int i = 0; i < width; i++)
+ {
+ for (unsigned int j = 0; j < height; j++)
+ {
+ guchar *pixels = img + ( j * row_bytes + i * 4);
+ guchar r = *(pixels + 0);
+ guchar g = *(pixels + 1);
+ guchar b = *(pixels + 2);
+ guchar a = *(pixels + 3);
+
+ float saturation = (MAX (r, MAX (g, b)) - MIN (r, MIN (g, b))) / 255.0f;
+ float relevance = .1 + .9 * (a / 255.0f) * saturation;
+
+ rtotal += (guchar) (r * relevance);
+ gtotal += (guchar) (g * relevance);
+ btotal += (guchar) (b * relevance);
+
+ total += relevance * 255;
+ }
+ }
+
+ float r, g, b, h, s, v;
+ r = rtotal / total;
+ g = gtotal / total;
+ b = btotal / total;
+
+ nux::RGBtoHSV (r, g, b, h, s, v);
+
+ if (s > .15f)
+ s = 0.4f;
+ v = .85f;
+
+ nux::HSVtoRGB (r, g, b, h, s, v);
+ background = nux::Color (r, g, b);
+
+ v = 1.0f;
+ nux::HSVtoRGB (r, g, b, h, s, v);
+ glow = nux::Color (r, g, b);
+}
+
+nux::BaseTexture * LauncherIcon::TextureFromGtkTheme (const char *icon_name, int size)
+{
+ GdkPixbuf *pbuf;
+ GtkIconTheme *theme;
+ GtkIconInfo *info;
+ nux::BaseTexture *result;
+ GError *error = NULL;
+
+ theme = gtk_icon_theme_get_default ();
+
+ if (!icon_name)
+ icon_name = g_strdup (DEFAULT_ICON);
+
+ info = gtk_icon_theme_lookup_icon (theme,
+ icon_name,
+ size,
+ (GtkIconLookupFlags) 0);
+ if (!info)
+ {
+ info = gtk_icon_theme_lookup_icon (theme,
+ DEFAULT_ICON,
+ size,
+ (GtkIconLookupFlags) 0);
+ }
+
+ if (gtk_icon_info_get_filename (info) == NULL)
+ {
+ info = gtk_icon_theme_lookup_icon (theme,
+ DEFAULT_ICON,
+ size,
+ (GtkIconLookupFlags) 0);
+ }
+
+ pbuf = gtk_icon_info_load_icon (info, &error);
+
+ if (GDK_IS_PIXBUF (pbuf))
+ {
+ result = nux::CreateTextureFromPixbuf (pbuf);
+ ColorForIcon (pbuf, _background_color, _glow_color);
+
+ g_object_unref (pbuf);
+ }
+ else
+ {
+ g_warning ("Unable to load '%s' from icon theme: %s",
+ icon_name,
+ error ? error->message : "unknown");
+ g_error_free (error);
+
+ if (g_strcmp0 (icon_name, "folder") == 0)
+ return NULL;
+ else
+ return TextureFromGtkTheme ("folder", size);
+ }
+
+ return result;
+}
+
+nux::BaseTexture * LauncherIcon::TextureFromPath (const char *icon_name, int size)
+{
+
+ GdkPixbuf *pbuf;
+ nux::BaseTexture *result;
+ GError *error = NULL;
+
+ if (!icon_name)
+ return TextureFromGtkTheme (DEFAULT_ICON, size);
+
+ pbuf = gdk_pixbuf_new_from_file_at_size (icon_name, size, size, &error);
+
+ if (GDK_IS_PIXBUF (pbuf))
+ {
+ result = nux::CreateTextureFromPixbuf (pbuf);
+ ColorForIcon (pbuf, _background_color, _glow_color);
+
+ g_object_unref (pbuf);
+ }
+ else
+ {
+ g_warning ("Unable to load '%s' icon: %s",
+ icon_name,
+ error->message);
+ g_error_free (error);
+
+ return TextureFromGtkTheme (DEFAULT_ICON, size);
+ }
+
+ return result;
+}
+
+void LauncherIcon::SetTooltipText(const TCHAR* text)
+{
+ m_TooltipText = text;
+ _tooltip->SetText (m_TooltipText);
+}
+
+nux::NString LauncherIcon::GetTooltipText()
+{
+ return m_TooltipText;
+}
+
+void
+LauncherIcon::RecvMouseEnter ()
+{
+ if (_launcher->GetActiveQuicklist ())
+ {
+ // A quicklist is active
+ return;
+ }
+
+ int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
+ int tip_y = _center.y;
+
+ _tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
+
+ if (!_quicklist->IsVisible ())
+ {
+ _tooltip->ShowWindow (true);
+ }
+}
+
+void LauncherIcon::RecvMouseLeave ()
+{
+ _tooltip->ShowWindow (false);
+}
+
+void LauncherIcon::RecvMouseDown (int button)
+{
+ if (button == 3)
+ {
+ if (_launcher->GetActiveQuicklist () == _quicklist)
+ {
+ // this quicklist is already active
+ return;
+ }
+
+ if (_launcher->GetActiveQuicklist ())
+ {
+ // Hide the active quicklist. This will prevent it from Ungrabing the pointer in
+ // QuicklistView::RecvMouseDownOutsideOfQuicklist or void QuicklistView::RecvMouseClick.
+ // So the new quicklist that is about to be set as active will keep the grab of the pointer.
+ // Also disable theinput window.
+ _launcher->GetActiveQuicklist ()->EnableInputWindow (false);
+ _launcher->GetActiveQuicklist ()->CaptureMouseDownAnyWhereElse (false);
+ // This call must be last, because after, _launcher->GetActiveQuicklist () will return Null.
+ // the launcher listen to the sigHidden signal emitted by the BaseWindow when it becomes invisible
+ // and it set the active window to Null.
+ _launcher->GetActiveQuicklist ()->ShowWindow (false);
+ }
+
+ _tooltip->ShowWindow (false);
+
+ _quicklist->RemoveAllMenuItem ();
+
+ std::list<DbusmenuMenuitem *> menus = Menus ();
+ if (menus.empty ())
+ return;
+
+ std::list<DbusmenuMenuitem *>::iterator it;
+ for (it = menus.begin (); it != menus.end (); it++)
+ {
+ DbusmenuMenuitem *menu_item = *it;
+
+ const gchar* type = dbusmenu_menuitem_property_get (menu_item, DBUSMENU_MENUITEM_PROP_TYPE);
+ const gchar* toggle_type = dbusmenu_menuitem_property_get (menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE);
+
+ if (g_strcmp0 (type, DBUSMENU_CLIENT_TYPES_SEPARATOR) == 0)
+ {
+ QuicklistMenuItemSeparator* item = new QuicklistMenuItemSeparator (menu_item, NUX_TRACKER_LOCATION);
+ _quicklist->AddMenuItem (item);
+ }
+ else if (g_strcmp0 (toggle_type, DBUSMENU_MENUITEM_TOGGLE_CHECK) == 0)
+ {
+ QuicklistMenuItemCheckmark* item = new QuicklistMenuItemCheckmark (menu_item, NUX_TRACKER_LOCATION);
+ _quicklist->AddMenuItem (item);
+ }
+ else if (g_strcmp0 (toggle_type, DBUSMENU_MENUITEM_TOGGLE_RADIO) == 0)
+ {
+ QuicklistMenuItemRadio* item = new QuicklistMenuItemRadio (menu_item, NUX_TRACKER_LOCATION);
+ _quicklist->AddMenuItem (item);
+ }
+ else //(g_strcmp0 (type, DBUSMENU_MENUITEM_PROP_LABEL) == 0)
+ {
+ QuicklistMenuItemLabel* item = new QuicklistMenuItemLabel (menu_item, NUX_TRACKER_LOCATION);
+ _quicklist->AddMenuItem (item);
+ }
+ }
+
+ int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
+ int tip_y = _center.y;
+ _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
+
+ _quicklist->EnableInputWindow (true, 1);
+ _quicklist->GrabPointer ();
+
+ nux::GetWindowCompositor ().SetAlwaysOnFrontWindow (_quicklist);
+
+ _quicklist->NeedRedraw ();
+ }
+}
+
+void LauncherIcon::RecvMouseUp (int button)
+{
+ if (button == 3)
+ {
+ if (_quicklist->IsVisible ())
+ _quicklist->CaptureMouseDownAnyWhereElse (true);
+ }
+}
+
+void LauncherIcon::RecvShowQuicklist (nux::BaseWindow *quicklist)
+{
+ _launcher->SetActiveQuicklist (_quicklist);
+}
+
+void LauncherIcon::RecvHideQuicklist (nux::BaseWindow *quicklist)
+{
+ _launcher->CancelActiveQuicklist (_quicklist);
+}
+
+void LauncherIcon::HideTooltip ()
+{
+ _tooltip->ShowWindow (false);
+}
+
+gboolean
+LauncherIcon::OnCenterTimeout (gpointer data)
+{
+ LauncherIcon *self = (LauncherIcon*)data;
+
+ if (self->_last_stable != self->_center)
+ {
+ self->OnCenterStabilized (self->_center);
+ self->_last_stable = self->_center;
+ }
+
+ self->_center_stabilize_handle = 0;
+ return false;
+}
+
+void
+LauncherIcon::SetCenter (nux::Point3 center)
+{
+ _center = center;
+
+ int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
+ int tip_y = _center.y;
+
+ if (_quicklist->IsVisible ())
+ _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
+ else if (_tooltip->IsVisible ())
+ _tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
+
+ if (_center_stabilize_handle)
+ g_source_remove (_center_stabilize_handle);
+
+ _center_stabilize_handle = g_timeout_add (500, &LauncherIcon::OnCenterTimeout, this);
+}
+
+nux::Point3
+LauncherIcon::GetCenter ()
+{
+ return _center;
+}
+
+gboolean
+LauncherIcon::OnPresentTimeout (gpointer data)
+{
+ LauncherIcon *self = (LauncherIcon*) data;
+ if (!self->GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
+ return false;
+
+ self->_present_time_handle = 0;
+ self->Unpresent ();
+
+ return false;
+}
+
+float LauncherIcon::PresentUrgency ()
+{
+ return _present_urgency;
+}
+
+void
+LauncherIcon::Present (float present_urgency, int length)
+{
+ if (GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
+ return;
+
+ if (length >= 0)
+ _present_time_handle = g_timeout_add (length, &LauncherIcon::OnPresentTimeout, this);
+
+ _present_urgency = CLAMP (present_urgency, 0.0f, 1.0f);
+ SetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED, true);
+}
+
+void
+LauncherIcon::Unpresent ()
+{
+ if (!GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
+ return;
+
+ if (_present_time_handle > 0)
+ g_source_remove (_present_time_handle);
+
+ SetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED, false);
+}
+
+void
+LauncherIcon::SetRelatedWindows (int windows)
+{
+ if (_related_windows == windows)
+ return;
+
+ _related_windows = windows;
+ needs_redraw.emit (this);
+}
+
+void
+LauncherIcon::Remove ()
+{
+ SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, false);
+ remove.emit (this);
+}
+
+void
+LauncherIcon::SetIconType (LauncherIconType type)
+{
+ _icon_type = type;
+}
+
+void
+LauncherIcon::SetSortPriority (int priority)
+{
+ _sort_priority = priority;
+}
+
+int
+LauncherIcon::SortPriority ()
+{
+ return _sort_priority;
+}
+
+LauncherIconType
+LauncherIcon::Type ()
+{
+ return _icon_type;
+}
+
+bool
+LauncherIcon::GetQuirk (LauncherIconQuirk quirk)
+{
+ return _quirks[quirk];
+}
+
+void
+LauncherIcon::SetQuirk (LauncherIconQuirk quirk, bool value)
+{
+ if (_quirks[quirk] == value)
+ return;
+
+ _quirks[quirk] = value;
+ clock_gettime (CLOCK_MONOTONIC, &(_quirk_times[quirk]));
+ needs_redraw.emit (this);
+
+ // Present on urgent as a general policy
+ if (quirk == LAUNCHER_ICON_QUIRK_VISIBLE && value)
+ Present (0.5f, 1500);
+ if (quirk == LAUNCHER_ICON_QUIRK_URGENT && value)
+ Present (0.5f, 1500);
+}
+
+gboolean
+LauncherIcon::OnDelayedUpdateTimeout (gpointer data)
+{
+ DelayedUpdateArg *arg = (DelayedUpdateArg *) data;
+ LauncherIcon *self = arg->self;
+
+ clock_gettime (CLOCK_MONOTONIC, &(self->_quirk_times[arg->quirk]));
+ self->needs_redraw.emit (self);
+
+ return false;
+}
+
+void
+LauncherIcon::UpdateQuirkTimeDelayed (guint ms, LauncherIconQuirk quirk)
+{
+ DelayedUpdateArg *arg = new DelayedUpdateArg ();
+ arg->self = this;
+ arg->quirk = quirk;
+
+ g_timeout_add (ms, &LauncherIcon::OnDelayedUpdateTimeout, arg);
+}
+
+void
+LauncherIcon::UpdateQuirkTime (LauncherIconQuirk quirk)
+{
+ clock_gettime (CLOCK_MONOTONIC, &(_quirk_times[quirk]));
+ needs_redraw.emit (this);
+}
+
+void
+LauncherIcon::ResetQuirkTime (LauncherIconQuirk quirk)
+{
+ _quirk_times[quirk].tv_sec = 0;
+ _quirk_times[quirk].tv_nsec = 0;
+}
+
+struct timespec
+LauncherIcon::GetQuirkTime (LauncherIconQuirk quirk)
+{
+ return _quirk_times[quirk];
+}
+
+int
+LauncherIcon::RelatedWindows ()
+{
+ return _related_windows;
+}
+
+std::list<DbusmenuMenuitem *> LauncherIcon::Menus ()
+{
+ return GetMenus ();
+}
+
+std::list<DbusmenuMenuitem *> LauncherIcon::GetMenus ()
+{
+ std::list<DbusmenuMenuitem *> result;
+ return result;
+}
diff --git a/src/LauncherIcon.h b/src/LauncherIcon.h
index 2163f53bc..145775dc5 100644
--- a/src/LauncherIcon.h
+++ b/src/LauncherIcon.h
@@ -1,196 +1,201 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authored by: Jason Smith <jason.smith@canonical.com>
- *
- */
-
-#ifndef LAUNCHERICON_H
-#define LAUNCHERICON_H
-
-#include <Nux/Nux.h>
-#include <Nux/BaseWindow.h>
-#include <NuxCore/Math/MathInc.h>
-
-#include <sigc++/trackable.h>
-#include <sigc++/signal.h>
-#include <sigc++/functors/ptr_fun.h>
-#include <sigc++/functors/mem_fun.h>
-
-#include <gtk/gtk.h>
-#include <libdbusmenu-glib/client.h>
-#include <libdbusmenu-glib/menuitem.h>
-
-#include "Tooltip.h"
-#include "QuicklistView.h"
-
-class Launcher;
-class QuicklistView;
-
-typedef enum
-{
- LAUNCHER_ICON_TYPE_NONE,
- LAUNCHER_ICON_TYPE_BEGIN,
- LAUNCHER_ICON_TYPE_FAVORITE,
- LAUNCHER_ICON_TYPE_APPLICATION,
- LAUNCHER_ICON_TYPE_PLACE,
- LAUNCHER_ICON_TYPE_DEVICE,
- LAUNCHER_ICON_TYPE_TRASH,
- LAUNCHER_ICON_TYPE_END,
-} LauncherIconType;
-
-typedef enum
-{
- LAUNCHER_ICON_QUIRK_VISIBLE,
- LAUNCHER_ICON_QUIRK_ACTIVE,
- LAUNCHER_ICON_QUIRK_RUNNING,
- LAUNCHER_ICON_QUIRK_URGENT,
- LAUNCHER_ICON_QUIRK_PRESENTED,
- LAUNCHER_ICON_QUIRK_STARTING,
- LAUNCHER_ICON_QUIRK_SHIMMER,
-
- LAUNCHER_ICON_QUIRK_LAST,
-} LauncherIconQuirk;
-
-class LauncherIcon : public nux::InitiallyUnownedObject, public sigc::trackable
-{
-public:
- LauncherIcon(Launcher* launcher);
- ~LauncherIcon();
-
- void SetTooltipText (const TCHAR* text);
-
- nux::NString GetTooltipText ();
-
- void RecvMouseEnter ();
- void RecvMouseLeave ();
- void RecvMouseDown (int button);
- void RecvMouseUp (int button);
-
- void RecvShowQuicklist (nux::BaseWindow *quicklist);
- void RecvHideQuicklist (nux::BaseWindow *quicklist);
-
- void HideTooltip ();
-
- void SetCenter (nux::Point3 center);
- nux::Point3 GetCenter ();
-
- int SortPriority ();
-
- int RelatedWindows ();
- int PresentUrgency ();
-
- bool GetQuirk (LauncherIconQuirk quirk);
- struct timespec GetQuirkTime (LauncherIconQuirk quirk);
-
- LauncherIconType Type ();
-
- nux::Color BackgroundColor ();
- nux::Color GlowColor ();
-
- nux::BaseTexture * TextureForSize (int size);
-
- std::list<DbusmenuMenuitem *> Menus ();
-
-
- sigc::signal<void, int> MouseDown;
- sigc::signal<void, int> MouseUp;
- sigc::signal<void> MouseEnter;
- sigc::signal<void> MouseLeave;
- sigc::signal<void, int> MouseClick;
-
- sigc::signal<void, void *> show;
- sigc::signal<void, void *> hide;
- sigc::signal<void, void *> remove;
- sigc::signal<void, void *> needs_redraw;
-protected:
- void SetQuirk (LauncherIconQuirk quirk, bool value);
-
- void UpdateQuirkTimeDelayed (guint ms, LauncherIconQuirk quirk);
- void UpdateQuirkTime (LauncherIconQuirk quirk);
- void ResetQuirkTime (LauncherIconQuirk quirk);
-
- void SetRelatedWindows (int windows);
- void Remove ();
-
-
- void Present (int urgency, int length);
- void Unpresent ();
-
- void SetIconType (LauncherIconType type);
- void SetSortPriority (int priority);
-
- virtual std::list<DbusmenuMenuitem *> GetMenus ();
- virtual nux::BaseTexture * GetTextureForSize (int size) = 0;
-
- virtual void OnCenterStabilized (nux::Point3 center) {};
- virtual bool IconOwnsWindow (Window w) { return false; }
-
- nux::BaseTexture * TextureFromGtkTheme (const char *name, int size);
-
- nux::NString m_TooltipText;
- //! the window this icon belong too.
- nux::BaseWindow* m_Window;
- Launcher* _launcher;
-
- std::map<std::string, nux::Vector4*> _xform_coords;
- bool _mouse_inside;
- float _folding_angle;
-
- nux::Tooltip *_tooltip;
- QuicklistView *_quicklist;
-
- static nux::Tooltip *_current_tooltip;
- static QuicklistView *_current_quicklist;
-
-
- friend class Launcher;
- friend class LauncherController;
-
-private:
- typedef struct
- {
- LauncherIcon *self;
- LauncherIconQuirk quirk;
- } DelayedUpdateArg;
-
- static void ChildRealized (DbusmenuMenuitem *newitem, QuicklistView *quicklist);
- static void RootChanged (DbusmenuClient * client, DbusmenuMenuitem *newroot, QuicklistView *quicklist);
- static gboolean OnPresentTimeout (gpointer data);
- static gboolean OnCenterTimeout (gpointer data);
- static gboolean OnDelayedUpdateTimeout (gpointer data);
-
- void ColorForIcon (GdkPixbuf *pixbuf, nux::Color &background, nux::Color &glow);
-
- nux::Color _background_color;
- nux::Color _glow_color;
- int _sort_priority;
- int _related_windows;
- int _present_urgency;
- guint _present_time_handle;
- guint _center_stabilize_handle;
- bool _quicklist_is_initialized;
-
- nux::Point3 _center;
- nux::Point3 _last_stable;
- LauncherIconType _icon_type;
-
- bool _quirks[LAUNCHER_ICON_QUIRK_LAST];
- struct timespec _quirk_times[LAUNCHER_ICON_QUIRK_LAST];
-
-};
-
-#endif // LAUNCHERICON_H
-
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Jason Smith <jason.smith@canonical.com>
+ *
+ */
+
+#ifndef LAUNCHERICON_H
+#define LAUNCHERICON_H
+
+#include <Nux/Nux.h>
+#include <Nux/BaseWindow.h>
+#include <NuxCore/Math/MathInc.h>
+
+#include <sigc++/trackable.h>
+#include <sigc++/signal.h>
+#include <sigc++/functors/ptr_fun.h>
+#include <sigc++/functors/mem_fun.h>
+
+#include <gtk/gtk.h>
+#include <libdbusmenu-glib/client.h>
+#include <libdbusmenu-glib/menuitem.h>
+
+#include "Tooltip.h"
+#include "QuicklistView.h"
+#include "Introspectable.h"
+
+class Launcher;
+class QuicklistView;
+
+typedef enum
+{
+ LAUNCHER_ICON_TYPE_NONE,
+ LAUNCHER_ICON_TYPE_BEGIN,
+ LAUNCHER_ICON_TYPE_FAVORITE,
+ LAUNCHER_ICON_TYPE_APPLICATION,
+ LAUNCHER_ICON_TYPE_PLACE,
+ LAUNCHER_ICON_TYPE_DEVICE,
+ LAUNCHER_ICON_TYPE_TRASH,
+ LAUNCHER_ICON_TYPE_END,
+} LauncherIconType;
+
+typedef enum
+{
+ LAUNCHER_ICON_QUIRK_VISIBLE,
+ LAUNCHER_ICON_QUIRK_ACTIVE,
+ LAUNCHER_ICON_QUIRK_RUNNING,
+ LAUNCHER_ICON_QUIRK_URGENT,
+ LAUNCHER_ICON_QUIRK_PRESENTED,
+ LAUNCHER_ICON_QUIRK_STARTING,
+ LAUNCHER_ICON_QUIRK_SHIMMER,
+
+ LAUNCHER_ICON_QUIRK_LAST,
+} LauncherIconQuirk;
+
+class LauncherIcon : public Introspectable, public nux::InitiallyUnownedObject, public sigc::trackable
+{
+public:
+ LauncherIcon(Launcher* launcher);
+ ~LauncherIcon();
+
+ void SetTooltipText (const TCHAR* text);
+
+ nux::NString GetTooltipText ();
+
+ void RecvMouseEnter ();
+ void RecvMouseLeave ();
+ void RecvMouseDown (int button);
+ void RecvMouseUp (int button);
+
+ void RecvShowQuicklist (nux::BaseWindow *quicklist);
+ void RecvHideQuicklist (nux::BaseWindow *quicklist);
+
+ void HideTooltip ();
+
+ void SetCenter (nux::Point3 center);
+ nux::Point3 GetCenter ();
+
+ int SortPriority ();
+
+ int RelatedWindows ();
+ float PresentUrgency ();
+
+ bool GetQuirk (LauncherIconQuirk quirk);
+ struct timespec GetQuirkTime (LauncherIconQuirk quirk);
+
+ LauncherIconType Type ();
+
+ nux::Color BackgroundColor ();
+ nux::Color GlowColor ();
+
+ nux::BaseTexture * TextureForSize (int size);
+
+ std::list<DbusmenuMenuitem *> Menus ();
+
+
+ sigc::signal<void, int> MouseDown;
+ sigc::signal<void, int> MouseUp;
+ sigc::signal<void> MouseEnter;
+ sigc::signal<void> MouseLeave;
+ sigc::signal<void, int> MouseClick;
+
+ sigc::signal<void, void *> show;
+ sigc::signal<void, void *> hide;
+ sigc::signal<void, void *> remove;
+ sigc::signal<void, void *> needs_redraw;
+protected:
+ const gchar * GetName ();
+ void AddProperties (GVariantBuilder *builder);
+
+ void SetQuirk (LauncherIconQuirk quirk, bool value);
+
+ void UpdateQuirkTimeDelayed (guint ms, LauncherIconQuirk quirk);
+ void UpdateQuirkTime (LauncherIconQuirk quirk);
+ void ResetQuirkTime (LauncherIconQuirk quirk);
+
+ void SetRelatedWindows (int windows);
+ void Remove ();
+
+
+ void Present (float urgency, int length);
+ void Unpresent ();
+
+ void SetIconType (LauncherIconType type);
+ void SetSortPriority (int priority);
+
+ virtual std::list<DbusmenuMenuitem *> GetMenus ();
+ virtual nux::BaseTexture * GetTextureForSize (int size) = 0;
+
+ virtual void OnCenterStabilized (nux::Point3 center) {};
+ virtual bool IconOwnsWindow (Window w) { return false; }
+
+ nux::BaseTexture * TextureFromGtkTheme (const char *name, int size);
+ nux::BaseTexture * TextureFromPath (const char *name, int size);
+
+ nux::NString m_TooltipText;
+ //! the window this icon belong too.
+ nux::BaseWindow* m_Window;
+ Launcher* _launcher;
+
+ std::map<std::string, nux::Vector4*> _xform_coords;
+ bool _mouse_inside;
+ float _folding_angle;
+
+ nux::Tooltip *_tooltip;
+ QuicklistView *_quicklist;
+
+ static nux::Tooltip *_current_tooltip;
+ static QuicklistView *_current_quicklist;
+
+
+ friend class Launcher;
+ friend class LauncherController;
+
+private:
+ typedef struct
+ {
+ LauncherIcon *self;
+ LauncherIconQuirk quirk;
+ } DelayedUpdateArg;
+
+ static void ChildRealized (DbusmenuMenuitem *newitem, QuicklistView *quicklist);
+ static void RootChanged (DbusmenuClient * client, DbusmenuMenuitem *newroot, QuicklistView *quicklist);
+ static gboolean OnPresentTimeout (gpointer data);
+ static gboolean OnCenterTimeout (gpointer data);
+ static gboolean OnDelayedUpdateTimeout (gpointer data);
+
+ void ColorForIcon (GdkPixbuf *pixbuf, nux::Color &background, nux::Color &glow);
+
+ nux::Color _background_color;
+ nux::Color _glow_color;
+ int _sort_priority;
+ int _related_windows;
+ float _present_urgency;
+ guint _present_time_handle;
+ guint _center_stabilize_handle;
+ bool _quicklist_is_initialized;
+
+ nux::Point3 _center;
+ nux::Point3 _last_stable;
+ LauncherIconType _icon_type;
+
+ bool _quirks[LAUNCHER_ICON_QUIRK_LAST];
+ struct timespec _quirk_times[LAUNCHER_ICON_QUIRK_LAST];
+
+};
+
+#endif // LAUNCHERICON_H
+
diff --git a/src/LauncherModel.cpp b/src/LauncherModel.cpp
index 160bad425..c109bd519 100644
--- a/src/LauncherModel.cpp
+++ b/src/LauncherModel.cpp
@@ -39,6 +39,20 @@ bool LauncherModel::IconShouldShelf (LauncherIcon *icon)
return icon->Type () == LAUNCHER_ICON_TYPE_TRASH;
}
+void
+LauncherModel::Populate ()
+{
+ _inner.clear ();
+
+ iterator it;
+
+ for (it = main_begin (); it != main_end (); it++)
+ _inner.push_back (*it);
+
+ for (it = shelf_begin (); it != shelf_end (); it++)
+ _inner.push_back (*it);
+}
+
void
LauncherModel::AddIcon (LauncherIcon *icon)
{
@@ -47,8 +61,10 @@ LauncherModel::AddIcon (LauncherIcon *icon)
if (IconShouldShelf (icon))
_inner_shelf.push_front (icon);
else
- _inner_launcher.push_front (icon);
-
+ _inner_main.push_front (icon);
+
+ Populate ();
+
icon_added.emit (icon);
icon->remove.connect (sigc::mem_fun (this, &LauncherModel::OnIconRemove));
}
@@ -58,16 +74,13 @@ LauncherModel::RemoveIcon (LauncherIcon *icon)
{
size_t size;
- size = _inner_shelf.size ();
_inner_shelf.remove (icon);
-
- if (size != _inner_shelf.size ())
- icon_removed.emit (icon);
+ _inner_main.remove (icon);
- size = _inner_launcher.size ();
- _inner_launcher.remove (icon);
+ size = _inner.size ();
+ _inner.remove (icon);
- if (size != _inner_launcher.size ())
+ if (size != _inner.size ())
icon_removed.emit (icon);
icon->UnReference ();
@@ -97,38 +110,64 @@ LauncherModel::OnIconRemove (void *icon_pointer)
void
LauncherModel::Sort (SortFunc func)
{
- _inner_launcher.sort (func);
- _inner_shelf.sort (func);
+ _inner.sort (func);
+ _inner_main.sort (func);
+
+ Populate ();
}
int
LauncherModel::Size ()
{
- return _inner_shelf.size () + _inner_launcher.size ();
+ return _inner.size ();
}
LauncherModel::iterator
LauncherModel::begin ()
{
- return _inner_launcher.begin ();
+ return _inner.begin ();
}
LauncherModel::iterator
LauncherModel::end ()
{
- return _inner_launcher.end ();
+ return _inner.end ();
}
LauncherModel::reverse_iterator
LauncherModel::rbegin ()
{
- return _inner_launcher.rbegin ();
+ return _inner.rbegin ();
}
LauncherModel::reverse_iterator
LauncherModel::rend ()
{
- return _inner_launcher.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
diff --git a/src/LauncherModel.h b/src/LauncherModel.h
index 6a8e90bc9..6da1b3fda 100644
--- a/src/LauncherModel.h
+++ b/src/LauncherModel.h
@@ -47,6 +47,11 @@ public:
reverse_iterator rbegin ();
reverse_iterator rend ();
+ iterator main_begin ();
+ iterator main_end ();
+ reverse_iterator main_rbegin ();
+ reverse_iterator main_rend ();
+
iterator shelf_begin ();
iterator shelf_end ();
reverse_iterator shelf_rbegin ();
@@ -57,8 +62,11 @@ public:
sigc::signal<void> order_changed;
private:
- Base _inner_launcher;
+ Base _inner;
Base _inner_shelf;
+ Base _inner_main;
+
+ void Populate ();
bool IconShouldShelf (LauncherIcon *icon);
diff --git a/src/PanelHomeButton.cpp b/src/PanelHomeButton.cpp
index 9fe30194f..154a5972d 100644
--- a/src/PanelHomeButton.cpp
+++ b/src/PanelHomeButton.cpp
@@ -140,3 +140,21 @@ PanelHomeButton::RecvMouseClick (int x,
g_object_unref (context);
}
}
+
+const gchar*
+PanelHomeButton::GetName ()
+{
+ return "HomeButton";
+}
+
+void
+PanelHomeButton::AddProperties (GVariantBuilder *builder)
+{
+ nux::Geometry geo = GetGeometry ();
+
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (geo.x));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (geo.y));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
+ g_variant_builder_add (builder, "{sv}", "have-pixbuf", g_variant_new_boolean (GDK_IS_PIXBUF (_pixbuf)));
+}
diff --git a/src/PanelHomeButton.h b/src/PanelHomeButton.h
index 61138de0c..03de813f6 100644
--- a/src/PanelHomeButton.h
+++ b/src/PanelHomeButton.h
@@ -24,7 +24,9 @@
#include <NuxImage/CairoGraphics.h>
#include <NuxGraphics/GraphicsEngine.h>
-class PanelHomeButton : public nux::TextureArea
+#include "Introspectable.h"
+
+class PanelHomeButton : public nux::TextureArea, public Introspectable
{
public:
PanelHomeButton ();
@@ -32,6 +34,10 @@ public:
void RecvMouseClick (int x, int y, unsigned long button_flags, unsigned long key_flags);
+protected:
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
+
private:
void Refresh ();
diff --git a/src/PanelIndicatorObjectEntryView.cpp b/src/PanelIndicatorObjectEntryView.cpp
index 302cbd5ec..cd9a8ceee 100644
--- a/src/PanelIndicatorObjectEntryView.cpp
+++ b/src/PanelIndicatorObjectEntryView.cpp
@@ -63,13 +63,22 @@ PanelIndicatorObjectEntryView::OnMouseDown (int x, int y, long button_flags, lon
if ((_proxy->label_visible && _proxy->label_sensitive)
|| (_proxy->icon_visible && _proxy->icon_sensitive))
{
- _proxy->ShowMenu (GetGeometry ().x,
+ _proxy->ShowMenu (GetGeometry ().x + 1, //cairo translation
PANEL_HEIGHT,
time (NULL),
nux::GetEventButton (button_flags));
}
}
+void
+PanelIndicatorObjectEntryView::Activate ()
+{
+ _proxy->ShowMenu (GetGeometry ().x + 1, //cairo translation FIXME: Make this into one function
+ PANEL_HEIGHT,
+ time (NULL),
+ 1);
+}
+
static char *
fix_string (const char *string)
{
@@ -253,8 +262,8 @@ draw_menu_bg (cairo_t *cr, int width, int height)
int radius = 4;
double x = 0;
double y = 0;
- double xos = 1.5;
- double yos = 1.5;
+ double xos = 0.5;
+ double yos = 0.5;
/* FIXME */
double mpi = 3.14159265358979323846;
@@ -301,3 +310,34 @@ draw_menu_bg (cairo_t *cr, int width, int height)
cairo_stroke (cr);
cairo_pattern_destroy (pat);
}
+
+const gchar *
+PanelIndicatorObjectEntryView::GetName ()
+{
+ const gchar *name = _proxy->GetId ();
+
+ if (g_strcmp0 (name, "|") == 0)
+ return NULL;
+ else
+ return name;
+}
+
+void
+PanelIndicatorObjectEntryView::AddProperties (GVariantBuilder *builder)
+{
+ nux::Geometry geo = GetGeometry ();
+
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (geo.x));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (geo.y));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
+
+ g_variant_builder_add (builder, "{sv}", "label", g_variant_new_string (_proxy->GetLabel ()));
+ g_variant_builder_add (builder, "{sv}", "label_sensitive", g_variant_new_boolean (_proxy->label_sensitive));
+ g_variant_builder_add (builder, "{sv}", "label_visible", g_variant_new_boolean (_proxy->label_visible));
+
+ g_variant_builder_add (builder, "{sv}", "icon_sensitive", g_variant_new_boolean (_proxy->icon_sensitive));
+ g_variant_builder_add (builder, "{sv}", "icon_visible", g_variant_new_boolean (_proxy->icon_visible));
+
+ g_variant_builder_add (builder, "{sv}", "active", g_variant_new_boolean (_proxy->GetActive ()));
+}
diff --git a/src/PanelIndicatorObjectEntryView.h b/src/PanelIndicatorObjectEntryView.h
index 26e9b1abd..58c9c3606 100644
--- a/src/PanelIndicatorObjectEntryView.h
+++ b/src/PanelIndicatorObjectEntryView.h
@@ -26,7 +26,9 @@
#include "IndicatorObjectEntryProxy.h"
-class PanelIndicatorObjectEntryView : public nux::TextureArea
+#include "Introspectable.h"
+
+class PanelIndicatorObjectEntryView : public nux::TextureArea, public Introspectable
{
public:
PanelIndicatorObjectEntryView (IndicatorObjectEntryProxy *proxy);
@@ -34,6 +36,10 @@ public:
void Refresh ();
void OnMouseDown (int x, int y, long button_flags, long key_flags);
+ void Activate ();
+
+ const gchar * GetName ();
+ void AddProperties (GVariantBuilder *builder);
public:
IndicatorObjectEntryProxy *_proxy;
diff --git a/src/PanelIndicatorObjectView.cpp b/src/PanelIndicatorObjectView.cpp
index 11620cb4e..52936b710 100644
--- a/src/PanelIndicatorObjectView.cpp
+++ b/src/PanelIndicatorObjectView.cpp
@@ -80,6 +80,8 @@ PanelIndicatorObjectView::OnEntryAdded (IndicatorObjectEntryProxy *proxy)
_entries.push_back (view);
+ AddChild (view);
+
this->ComputeChildLayout ();
NeedRedraw ();
}
@@ -100,6 +102,7 @@ PanelIndicatorObjectView::OnEntryRemoved(IndicatorObjectEntryProxy *proxy)
PanelIndicatorObjectEntryView *view = static_cast<PanelIndicatorObjectEntryView *> (*it);
if (view->_proxy == proxy)
{
+ RemoveChild (view);
_entries.erase (it);
_layout->RemoveChildObject (view);
@@ -110,3 +113,27 @@ PanelIndicatorObjectView::OnEntryRemoved(IndicatorObjectEntryProxy *proxy)
this->ComputeChildLayout ();
NeedRedraw ();
}
+
+const gchar *
+PanelIndicatorObjectView::GetName ()
+{
+ return _proxy->GetName ().c_str ();
+}
+
+const gchar *
+PanelIndicatorObjectView::GetChildsName ()
+{
+ return "entries";
+}
+
+void
+PanelIndicatorObjectView::AddProperties (GVariantBuilder *builder)
+{
+ nux::Geometry geo = GetGeometry ();
+
+ /* Now some props from ourselves */
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (geo.x));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (geo.y));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
+}
diff --git a/src/PanelIndicatorObjectView.h b/src/PanelIndicatorObjectView.h
index 6d223198a..cc23dbc73 100644
--- a/src/PanelIndicatorObjectView.h
+++ b/src/PanelIndicatorObjectView.h
@@ -24,7 +24,9 @@
#include "IndicatorObjectProxy.h"
#include "PanelIndicatorObjectEntryView.h"
-class PanelIndicatorObjectView : public nux::View
+#include "Introspectable.h"
+
+class PanelIndicatorObjectView : public nux::View, public Introspectable
{
public:
PanelIndicatorObjectView (IndicatorObjectProxy *proxy);
@@ -39,6 +41,12 @@ public:
void OnEntryRemoved (IndicatorObjectEntryProxy *proxy);
nux::HLayout *_layout;
+
+protected:
+ const gchar * GetName ();
+ const gchar * GetChildsName ();
+ void AddProperties (GVariantBuilder *builder);
+
private:
IndicatorObjectProxy *_proxy;
std::vector<PanelIndicatorObjectEntryView *> _entries;
diff --git a/src/PanelView.cpp b/src/PanelView.cpp
index 4652c2d20..3809ec815 100644
--- a/src/PanelView.cpp
+++ b/src/PanelView.cpp
@@ -1,237 +1,290 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
- */
-
-#include <Nux/Nux.h>
-#include <Nux/BaseWindow.h>
-#include <Nux/HLayout.h>
-#include <Nux/Layout.h>
-#include <Nux/WindowCompositor.h>
-
-#include <NuxImage/CairoGraphics.h>
-#include <NuxImage/ImageSurface.h>
-
-#include <NuxGraphics/GLThread.h>
-#include <NuxGraphics/RenderingPipe.h>
-
-#include <glib.h>
-
-#include "PanelView.h"
-
-#include "IndicatorObjectFactoryRemote.h"
-#include "PanelIndicatorObjectView.h"
-
-PanelView::PanelView (NUX_FILE_LINE_DECL)
-: View (NUX_FILE_LINE_PARAM)
-{
- _bg_layer = new nux::ColorLayer (nux::Color (0xff595853), true);
-
- _layout = new nux::HLayout ("", NUX_TRACKER_LOCATION);
- SetCompositionLayout (_layout);
-
- // Home button
- _home_button = new PanelHomeButton ();
- _layout->AddView (_home_button, 0, nux::eCenter, nux::eFull);
-
- _remote = new IndicatorObjectFactoryRemote ();
- _remote->OnObjectAdded.connect (sigc::mem_fun (this, &PanelView::OnObjectAdded));
- _remote->OnMenuPointerMoved.connect (sigc::mem_fun (this, &PanelView::OnMenuPointerMoved));
-}
-
-PanelView::~PanelView ()
-{
- delete _remote;
- delete _bg_layer;
-}
-
-PanelHomeButton *
-PanelView::HomeButton ()
-{
- return _home_button;
-}
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#include <Nux/Nux.h>
+#include <Nux/BaseWindow.h>
+#include <Nux/HLayout.h>
+#include <Nux/Layout.h>
+#include <Nux/WindowCompositor.h>
+
+#include <NuxImage/CairoGraphics.h>
+#include <NuxImage/ImageSurface.h>
+
+#include <NuxGraphics/GLThread.h>
+#include <NuxGraphics/RenderingPipe.h>
+
+#include <glib.h>
+
+#include "PanelView.h"
+
+#include "IndicatorObjectFactoryRemote.h"
+#include "PanelIndicatorObjectView.h"
+
+PanelView::PanelView (NUX_FILE_LINE_DECL)
+: View (NUX_FILE_LINE_PARAM)
+{
+ _bg_layer = new nux::ColorLayer (nux::Color (0xff595853), true);
+
+ _layout = new nux::HLayout ("", NUX_TRACKER_LOCATION);
+ SetCompositionLayout (_layout);
+
+ // Home button
+ _home_button = new PanelHomeButton ();
+ _layout->AddView (_home_button, 0, nux::eCenter, nux::eFull);
+
+ AddChild (_home_button);
+
+ _remote = new IndicatorObjectFactoryRemote ();
+ _remote->OnObjectAdded.connect (sigc::mem_fun (this, &PanelView::OnObjectAdded));
+ _remote->OnMenuPointerMoved.connect (sigc::mem_fun (this, &PanelView::OnMenuPointerMoved));
+ _remote->OnEntryActivateRequest.connect (sigc::mem_fun (this, &PanelView::OnEntryActivateRequest));
+}
+
+PanelView::~PanelView ()
+{
+ delete _remote;
+ delete _bg_layer;
+}
+
+PanelHomeButton *
+PanelView::HomeButton ()
+{
+ return _home_button;
+}
const gchar* PanelView::GetName ()
{
- return "PanelView";
+ return "Panel";
+}
+
+const gchar *
+PanelView::GetChildsName ()
+{
+ return "indicators";
}
void PanelView::AddProperties (GVariantBuilder *builder)
{
+ nux::Geometry geo = GetGeometry ();
+
+ /* First add some properties from the backend */
+ _remote->AddProperties (builder);
+
+ /* Now some props from ourselves */
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (geo.x));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (geo.y));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
+}
+
+long
+PanelView::ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
+{
+ long ret = TraverseInfo;
+ ret = _layout->ProcessEvent (ievent, ret, ProcessEventInfo);
+ return ret;
+}
+
+void
+PanelView::Draw (nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+ GfxContext.PushClippingRectangle (GetGeometry() );
+
+ gPainter.PushDrawLayer (GfxContext, GetGeometry (), _bg_layer);
+
+ gPainter.PopBackground ();
+
+ GfxContext.PopClippingRectangle ();
+}
+
+void
+PanelView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
+{
+ GfxContext.PushClippingRectangle (GetGeometry() );
+
+ gPainter.PushLayer (GfxContext, GetGeometry (), _bg_layer);
+
+ _layout->ProcessDraw (GfxContext, force_draw);
+
+ gPainter.PopBackground ();
+ GfxContext.PopClippingRectangle();
+}
+
+void
+PanelView::PreLayoutManagement ()
+{
+ nux::View::PreLayoutManagement ();
+}
+
+long
+PanelView::PostLayoutManagement (long LayoutResult)
+{
+ // I'm imagining this is a good as time as any to update the background
+ UpdateBackground ();
+
+ return nux::View::PostLayoutManagement (LayoutResult);
+}
+
+void
+PanelView::UpdateBackground ()
+{
+ nux::Geometry geo = GetGeometry ();
+
+ if (geo.width == _last_width && geo.height == _last_height)
+ return;
+
+ _last_width = geo.width;
+ _last_height = geo.height;
+
+ nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, _last_width, _last_height);
+ cairo_t *cr = cairo_graphics.GetContext();
+ cairo_set_line_width (cr, 1);
+
+ cairo_pattern_t *pat = cairo_pattern_create_linear (0, 0, 0, _last_height);
+ cairo_pattern_add_color_stop_rgb (pat, 0.0f, 89/255.0f, 88/255.0f, 83/255.0f);
+ cairo_pattern_add_color_stop_rgb (pat, 1.0f, 50/255.0f, 50/255.0f, 45/255.0f);
+ cairo_set_source (cr, pat);
+ cairo_rectangle (cr, 0, 0, _last_width, _last_height);
+ cairo_fill (cr);
+ cairo_pattern_destroy (pat);
+
+ cairo_destroy (cr);
+
+ nux::NBitmapData* bitmap = cairo_graphics.GetBitmap();
+
+ nux::BaseTexture* texture2D = nux::GetThreadGLDeviceFactory ()->CreateSystemCapableTexture ();
+ texture2D->Update(bitmap);
+ delete bitmap;
+
+ nux::TexCoordXForm texxform;
+ texxform.SetTexCoordType (nux::TexCoordXForm::OFFSET_COORD);
+ texxform.SetWrap (nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
+ if (_bg_layer)
+ delete _bg_layer;
+
+ nux::ROPConfig rop;
+ rop.Blend = false; // Disable the blending. By default rop.Blend is false.
+ rop.SrcBlend = GL_SRC_ALPHA; // Set the source blend factor.
+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; // Set the destination blend factor.
+
+ _bg_layer = new nux::TextureLayer (texture2D->GetDeviceTexture(),
+ texxform, // The Oject that defines the texture wraping and coordinate transformation.
+ nux::Color::White, // The color used to modulate the texture.
+ true, // Write the alpha value of the texture to the destination buffer.
+ rop // Use the given raster operation to set the blending when the layer is being rendered.
+ );
+
+ texture2D->UnReference ();
+
+ NeedRedraw ();
+}
+
+//
+// Signals
+//
+void
+PanelView::OnObjectAdded (IndicatorObjectProxy *proxy)
+{
+ PanelIndicatorObjectView *view = new PanelIndicatorObjectView (proxy);
+
+ // Appmenu is treated differently as it needs to expand
+ // We could do this in a more special way, but who has the time for special?
+ _layout->AddView (view, (g_strstr_len (proxy->GetName ().c_str (), -1, "appmenu") != NULL), nux::eCenter, nux::eFull);
+ _layout->SetContentDistribution (nux::eStackLeft);
+
+ AddChild (view);
+
+ this->ComputeChildLayout ();
+ NeedRedraw ();
+}
+
+void
+PanelView::OnMenuPointerMoved (int x, int y)
+{
+ nux::Geometry geo = GetGeometry ();
+ nux::Geometry hgeo = _home_button->GetGeometry ();
+
+ if (x <= (hgeo.x + hgeo.width))
+ return;
+
+ if (x >= geo.x && x <= (geo.x + geo.width)
+ && y >= geo.y && y <= (geo.y + geo.height))
+ {
+ std::list<Area *>::iterator it;
+
+ std::list<Area *> my_children = _layout->GetChildren ();
+ for (it = my_children.begin(); it != my_children.end(); it++)
+ {
+ PanelIndicatorObjectView *view = static_cast<PanelIndicatorObjectView *> (*it);
+
+ if (view->_layout == NULL)
+ continue;
+
+ geo = view->GetGeometry ();
+ if (x >= geo.x && x <= (geo.x + geo.width)
+ && y >= geo.y && y <= (geo.y + geo.height))
+ {
+ std::list<Area *>::iterator it2;
+
+ std::list<Area *> its_children = view->_layout->GetChildren ();
+ for (it2 = its_children.begin(); it2 != its_children.end(); it2++)
+ {
+ PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
+
+ geo = entry->GetGeometry ();
+ if (x >= geo.x && x <= (geo.x + geo.width)
+ && y >= geo.y && y <= (geo.y + geo.height))
+ {
+ entry->OnMouseDown (x, y, 0, 0);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+PanelView::OnEntryActivateRequest (const char *entry_id)
+{
+ std::list<Area *>::iterator it;
+
+ std::list<Area *> my_children = _layout->GetChildren ();
+ for (it = my_children.begin(); it != my_children.end(); it++)
+ {
+ PanelIndicatorObjectView *view = static_cast<PanelIndicatorObjectView *> (*it);
+
+ if (view->_layout == NULL)
+ continue;
+
+ std::list<Area *>::iterator it2;
+
+ std::list<Area *> its_children = view->_layout->GetChildren ();
+ for (it2 = its_children.begin(); it2 != its_children.end(); it2++)
+ {
+ PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
+
+ if (g_strcmp0 (entry->GetName (), entry_id) == 0)
+ {
+ entry->Activate ();
+ break;
+ }
+ }
+ }
}
-
-long
-PanelView::ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
-{
- long ret = TraverseInfo;
- ret = _layout->ProcessEvent (ievent, ret, ProcessEventInfo);
- return ret;
-}
-
-void
-PanelView::Draw (nux::GraphicsEngine& GfxContext, bool force_draw)
-{
- GfxContext.PushClippingRectangle (GetGeometry() );
-
- gPainter.PushDrawLayer (GfxContext, GetGeometry (), _bg_layer);
-
- gPainter.PopBackground ();
-
- GfxContext.PopClippingRectangle ();
-}
-
-void
-PanelView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
-{
- GfxContext.PushClippingRectangle (GetGeometry() );
-
- gPainter.PushLayer (GfxContext, GetGeometry (), _bg_layer);
-
- _layout->ProcessDraw (GfxContext, force_draw);
-
- gPainter.PopBackground ();
- GfxContext.PopClippingRectangle();
-}
-
-void
-PanelView::PreLayoutManagement ()
-{
- nux::View::PreLayoutManagement ();
-}
-
-long
-PanelView::PostLayoutManagement (long LayoutResult)
-{
- // I'm imagining this is a good as time as any to update the background
- UpdateBackground ();
-
- return nux::View::PostLayoutManagement (LayoutResult);
-}
-
-void
-PanelView::UpdateBackground ()
-{
- nux::Geometry geo = GetGeometry ();
-
- if (geo.width == _last_width && geo.height == _last_height)
- return;
-
- _last_width = geo.width;
- _last_height = geo.height;
-
- nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, _last_width, _last_height);
- cairo_t *cr = cairo_graphics.GetContext();
- cairo_set_line_width (cr, 1);
-
- cairo_pattern_t *pat = cairo_pattern_create_linear (0, 0, 0, _last_height);
- cairo_pattern_add_color_stop_rgb (pat, 0.0f, 89/255.0f, 88/255.0f, 83/255.0f);
- cairo_pattern_add_color_stop_rgb (pat, 1.0f, 50/255.0f, 50/255.0f, 45/255.0f);
- cairo_set_source (cr, pat);
- cairo_rectangle (cr, 0, 0, _last_width, _last_height);
- cairo_fill (cr);
- cairo_pattern_destroy (pat);
-
- cairo_destroy (cr);
-
- nux::NBitmapData* bitmap = cairo_graphics.GetBitmap();
-
- nux::BaseTexture* texture2D = nux::GetThreadGLDeviceFactory ()->CreateSystemCapableTexture ();
- texture2D->Update(bitmap);
- delete bitmap;
-
- nux::TexCoordXForm texxform;
- texxform.SetTexCoordType (nux::TexCoordXForm::OFFSET_COORD);
- texxform.SetWrap (nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
- if (_bg_layer)
- delete _bg_layer;
-
- nux::ROPConfig rop;
- rop.Blend = false; // Disable the blending. By default rop.Blend is false.
- rop.SrcBlend = GL_SRC_ALPHA; // Set the source blend factor.
- rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; // Set the destination blend factor.
-
- _bg_layer = new nux::TextureLayer (texture2D->GetDeviceTexture(),
- texxform, // The Oject that defines the texture wraping and coordinate transformation.
- nux::Color::White, // The color used to modulate the texture.
- true, // Write the alpha value of the texture to the destination buffer.
- rop // Use the given raster operation to set the blending when the layer is being rendered.
- );
-
- texture2D->UnReference ();
-
- NeedRedraw ();
-}
-
-//
-// Signals
-//
-void
-PanelView::OnObjectAdded (IndicatorObjectProxy *proxy)
-{
- PanelIndicatorObjectView *view = new PanelIndicatorObjectView (proxy);
-
- // Appmenu is treated differently as it needs to expand
- // We could do this in a more special way, but who has the time for special?
- _layout->AddView (view, (g_strstr_len (proxy->GetName ().c_str (), -1, "appmenu") != NULL), nux::eCenter, nux::eFull);
- _layout->SetContentDistribution (nux::eStackLeft);
-
- this->ComputeChildLayout ();
- NeedRedraw ();
-}
-
-void
-PanelView::OnMenuPointerMoved (int x, int y)
-{
- nux::Geometry geo = GetGeometry ();
- nux::Geometry hgeo = _home_button->GetGeometry ();
-
- if (x <= (hgeo.x + hgeo.width))
- return;
-
- if (x >= geo.x && x <= (geo.x + geo.width)
- && y >= geo.y && y <= (geo.y + geo.height))
- {
- std::list<Area *>::iterator it;
-
- std::list<Area *> my_children = _layout->GetChildren ();
- for (it = my_children.begin(); it != my_children.end(); it++)
- {
- PanelIndicatorObjectView *view = static_cast<PanelIndicatorObjectView *> (*it);
-
- geo = view->GetGeometry ();
- if (x >= geo.x && x <= (geo.x + geo.width)
- && y >= geo.y && y <= (geo.y + geo.height))
- {
- std::list<Area *>::iterator it2;
-
- std::list<Area *> its_children = view->_layout->GetChildren ();
- for (it2 = its_children.begin(); it2 != its_children.end(); it2++)
- {
- PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
-
- geo = entry->GetGeometry ();
- if (x >= geo.x && x <= (geo.x + geo.width)
- && y >= geo.y && y <= (geo.y + geo.height))
- {
- entry->OnMouseDown (x, y, 0, 0);
- break;
- }
- }
- break;
- }
- }
- }
-}
diff --git a/src/PanelView.h b/src/PanelView.h
index c775c36b8..f6afc4f95 100644
--- a/src/PanelView.h
+++ b/src/PanelView.h
@@ -1,67 +1,69 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
- */
-
-#ifndef PANEL_VIEW_H
-#define PANEL_VIEW_H
-
-#include <Nux/View.h>
-#include <Nux/TextureArea.h>
-#include <NuxGraphics/GraphicsEngine.h>
-
-#include "PanelHomeButton.h"
-#include "IndicatorObjectFactoryRemote.h"
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#ifndef PANEL_VIEW_H
+#define PANEL_VIEW_H
+
+#include <Nux/View.h>
+#include <Nux/TextureArea.h>
+#include <NuxGraphics/GraphicsEngine.h>
+
+#include "PanelHomeButton.h"
+#include "IndicatorObjectFactoryRemote.h"
#include "Introspectable.h"
-
-class PanelView : public Introspectable, public nux::View
-{
-public:
- PanelView (NUX_FILE_LINE_PROTO);
- ~PanelView ();
-
- virtual long ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo);
- virtual void Draw (nux::GraphicsEngine& GfxContext, bool force_draw);
- virtual void DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw);
-
- virtual void PreLayoutManagement ();
- virtual long PostLayoutManagement (long LayoutResult);
-
- void OnObjectAdded (IndicatorObjectProxy *proxy);
- void OnMenuPointerMoved (int x, int y);
-
+
+class PanelView : public Introspectable, public nux::View
+{
+public:
+ PanelView (NUX_FILE_LINE_PROTO);
+ ~PanelView ();
+
+ virtual long ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo);
+ virtual void Draw (nux::GraphicsEngine& GfxContext, bool force_draw);
+ virtual void DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw);
+
+ virtual void PreLayoutManagement ();
+ virtual long PostLayoutManagement (long LayoutResult);
+
+ void OnObjectAdded (IndicatorObjectProxy *proxy);
+ void OnMenuPointerMoved (int x, int y);
+ void OnEntryActivateRequest (const char *entry_id);
+
PanelHomeButton * HomeButton ();
protected:
// Introspectable methods
- const gchar* GetName ();
- void AddProperties (GVariantBuilder *builder);
-
-private:
- void UpdateBackground ();
-
-private:
- IndicatorObjectFactoryRemote *_remote;
-
- PanelHomeButton *_home_button;
- nux::AbstractPaintLayer *_bg_layer;
- nux::HLayout *_layout;
-
- int _last_width;
- int _last_height;
-};
-
-#endif // PANEL_VIEW_H
+ const gchar * GetName ();
+ const gchar * GetChildsName ();
+ void AddProperties (GVariantBuilder *builder);
+
+private:
+ void UpdateBackground ();
+
+private:
+ IndicatorObjectFactoryRemote *_remote;
+
+ PanelHomeButton *_home_button;
+ nux::AbstractPaintLayer *_bg_layer;
+ nux::HLayout *_layout;
+
+ int _last_width;
+ int _last_height;
+};
+
+#endif // PANEL_VIEW_H
diff --git a/src/QuicklistMenuItem.cpp b/src/QuicklistMenuItem.cpp
index cd0963339..ac1b4d615 100644
--- a/src/QuicklistMenuItem.cpp
+++ b/src/QuicklistMenuItem.cpp
@@ -43,6 +43,7 @@ View (NUX_FILE_LINE_PARAM)
g_warning ("Invalid DbusmenuMenuitem in file %s at line %s.", G_STRFUNC, G_STRLOC);
}
+ _name = 0;
_text = 0;
_color = nux::Color (1.0f, 1.0f, 1.0f, 1.0f);
_menuItem = item;
@@ -118,6 +119,9 @@ View (NUX_FILE_LINE_PARAM)
QuicklistMenuItem::~QuicklistMenuItem ()
{
+ if (_name)
+ g_free (_name);
+
if (_text)
g_free (_text);
}
@@ -444,3 +448,22 @@ QuicklistMenuItem::DrawText (cairo_t* cr,
g_free (fontName);
g_object_unref (layout);
}
+
+// Introspection
+
+const gchar* QuicklistMenuItem::GetName ()
+{
+ return g_strdup (_name);
+}
+
+void QuicklistMenuItem::AddProperties (GVariantBuilder *builder)
+{
+ g_variant_builder_add (builder, "{sv}", "text", g_variant_new_string (_text));
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (GetBaseX ()));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (GetBaseY ()));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (GetBaseWidth ()));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (GetBaseHeight ()));
+ g_variant_builder_add (builder, "{sv}", "enabled", g_variant_new_boolean (GetEnabled ()));
+ g_variant_builder_add (builder, "{sv}", "active", g_variant_new_boolean (GetActive ()));
+
+}
diff --git a/src/QuicklistMenuItem.h b/src/QuicklistMenuItem.h
index d07b3a61c..bf4b245a4 100755..100644
--- a/src/QuicklistMenuItem.h
+++ b/src/QuicklistMenuItem.h
@@ -30,6 +30,8 @@
#include <pango/pango.h>
#include <pango/pangocairo.h>
+#include "Introspectable.h"
+
#define ITEM_INDENT_ABS 16
#define ITEM_CORNER_RADIUS_ABS 3
#define ITEM_MARGIN 4
@@ -43,7 +45,7 @@ typedef enum
MENUITEM_TYPE_RADIO,
} QuicklistMenuItemType;
-class QuicklistMenuItem : public nux::View
+class QuicklistMenuItem : public nux::View, public Introspectable
{
public:
QuicklistMenuItem (DbusmenuMenuitem* item,
@@ -86,6 +88,9 @@ class QuicklistMenuItem : public nux::View
virtual bool GetActive ();
+ // Introspection
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
protected:
gchar* _text;
@@ -139,6 +144,9 @@ class QuicklistMenuItem : public nux::View
int height,
nux::Color color);
+ // Introspection
+ gchar *_name;
+
friend class QuicklistView;
};
diff --git a/src/QuicklistMenuItemCheckmark.cpp b/src/QuicklistMenuItemCheckmark.cpp
index eaa645c58..36dddf298 100755..100644
--- a/src/QuicklistMenuItemCheckmark.cpp
+++ b/src/QuicklistMenuItemCheckmark.cpp
@@ -39,6 +39,7 @@ QuicklistMenuItemCheckmark::QuicklistMenuItemCheckmark (DbusmenuMenuitem* item,
QuicklistMenuItem (item,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemCheckmark");
Initialize (item);
}
@@ -49,6 +50,7 @@ QuicklistMenuItem (item,
debug,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemCheckmark");
Initialize (item);
}
diff --git a/src/QuicklistMenuItemCheckmark.h b/src/QuicklistMenuItemCheckmark.h
index f7d46fc91..f7d46fc91 100755..100644
--- a/src/QuicklistMenuItemCheckmark.h
+++ b/src/QuicklistMenuItemCheckmark.h
diff --git a/src/QuicklistMenuItemLabel.cpp b/src/QuicklistMenuItemLabel.cpp
index 52edd0af6..24504edfd 100755..100644
--- a/src/QuicklistMenuItemLabel.cpp
+++ b/src/QuicklistMenuItemLabel.cpp
@@ -28,6 +28,7 @@ QuicklistMenuItemLabel::QuicklistMenuItemLabel (DbusmenuMenuitem* item,
QuicklistMenuItem (item,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemLabel");
Initialize (item);
}
@@ -38,6 +39,7 @@ QuicklistMenuItem (item,
debug,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemLabel");
Initialize (item);
}
diff --git a/src/QuicklistMenuItemLabel.h b/src/QuicklistMenuItemLabel.h
index 1c8936a58..1c8936a58 100755..100644
--- a/src/QuicklistMenuItemLabel.h
+++ b/src/QuicklistMenuItemLabel.h
diff --git a/src/QuicklistMenuItemRadio.cpp b/src/QuicklistMenuItemRadio.cpp
index 3566ee07e..29b2cef25 100755..100644
--- a/src/QuicklistMenuItemRadio.cpp
+++ b/src/QuicklistMenuItemRadio.cpp
@@ -38,6 +38,7 @@ QuicklistMenuItemRadio::QuicklistMenuItemRadio (DbusmenuMenuitem* item,
QuicklistMenuItem (item,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemRadio");
Initialize (item);
}
@@ -48,6 +49,7 @@ QuicklistMenuItem (item,
debug,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemRadio");
Initialize (item);
}
@@ -57,14 +59,9 @@ QuicklistMenuItemRadio::Initialize (DbusmenuMenuitem* item)
_item_type = MENUITEM_TYPE_LABEL;
if (item)
- _text = dbusmenu_menuitem_property_get (item, DBUSMENU_MENUITEM_PROP_LABEL);
+ _text = g_strdup (dbusmenu_menuitem_property_get (item, DBUSMENU_MENUITEM_PROP_LABEL));
else
- _text = "QuicklistItem";
-
- _normalTexture[0] = NULL;
- _normalTexture[1] = NULL;
- _prelightTexture[0] = NULL;
- _prelightTexture[1] = NULL;
+ _text = g_strdup ("Radio Button");
int textWidth = 1;
int textHeight = 1;
@@ -92,6 +89,15 @@ QuicklistMenuItemRadio::~QuicklistMenuItemRadio ()
void
QuicklistMenuItemRadio::PreLayoutManagement ()
{
+ _pre_layout_width = GetBaseWidth ();
+ _pre_layout_height = GetBaseHeight ();
+
+ if (_normalTexture[0] == 0)
+ {
+ UpdateTexture ();
+ }
+
+ QuicklistMenuItem::PreLayoutManagement ();
}
long
@@ -135,7 +141,7 @@ QuicklistMenuItemRadio::Draw (nux::GraphicsEngine& gfxContext,
bool forceDraw)
{
// Check if the texture have been computed. If they haven't, exit the function.
- if (_normalTexture[0] == NULL)
+ if (!_normalTexture[0])
return;
nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture;
@@ -152,16 +158,41 @@ QuicklistMenuItemRadio::Draw (nux::GraphicsEngine& gfxContext,
GL_ONE,
GL_ONE_MINUS_SRC_ALPHA);
- if (GetActive ())
- if (GetEnabled ())
- texture = _prelightTexture[1]->GetDeviceTexture ();
- else
+ if (GetEnabled ())
+ {
+ if (GetActive () && _prelight)
+ {
texture = _prelightTexture[0]->GetDeviceTexture ();
- else
- if (GetEnabled ())
+ }
+ else if (GetActive ())
+ {
+ texture = _normalTexture[0]->GetDeviceTexture ();
+ }
+
+ if ((!GetActive ()) && _prelight)
+ {
+ texture = _prelightTexture[1]->GetDeviceTexture ();
+ }
+ else if (!GetActive ())
+ {
texture = _normalTexture[1]->GetDeviceTexture ();
+ }
+
+ _color = nux::Color::White;
+ }
+ else
+ {
+ if (GetActive ())
+ {
+ texture = _prelightTexture[0]->GetDeviceTexture ();
+ }
else
+ {
texture = _normalTexture[0]->GetDeviceTexture ();
+ }
+
+ _color = nux::Color::DarkGray;
+ }
gfxContext.QRP_GLSL_1Tex (base.x,
base.y,
@@ -191,8 +222,9 @@ QuicklistMenuItemRadio::PostDraw (nux::GraphicsEngine& gfxContext,
void
QuicklistMenuItemRadio::UpdateTexture ()
{
- int width = GetBaseWidth ();
- int height = GetBaseHeight ();
+ nux::Color transparent = nux::Color (0.0f, 0.0f, 0.0f, 0.0f);
+ int width = GetBaseWidth ();
+ int height = GetBaseHeight ();
_cairoGraphics = new nux::CairoGraphics (CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cr = _cairoGraphics->GetContext ();
@@ -206,7 +238,7 @@ QuicklistMenuItemRadio::UpdateTexture ()
cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 1.0f);
cairo_set_line_width (cr, 1.0f);
- DrawText (cr, width, height, _textColor);
+ DrawText (cr, width, height, nux::Color::White);
nux::NBitmapData* bitmap = _cairoGraphics->GetBitmap ();
@@ -234,7 +266,7 @@ QuicklistMenuItemRadio::UpdateTexture ()
cairo_fill (cr);
cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 1.0f);
- DrawText (cr, width, height, _textColor);
+ DrawText (cr, width, height, nux::Color::White);
bitmap = _cairoGraphics->GetBitmap ();
@@ -264,7 +296,7 @@ QuicklistMenuItemRadio::UpdateTexture ()
cairo_set_source_rgba (cr, 0.0f, 0.0f, 0.0f, 0.0f);
- DrawText (cr, width, height, _textColor);
+ DrawText (cr, width, height, transparent);
bitmap = _cairoGraphics->GetBitmap ();
@@ -297,7 +329,7 @@ QuicklistMenuItemRadio::UpdateTexture ()
cairo_arc (cr, x, y, radius, 0.0f * (G_PI / 180.0f), 360.0f * (G_PI / 180.0f));
cairo_fill (cr);
- DrawText (cr, width, height, _textColor);
+ DrawText (cr, width, height, transparent);
bitmap = _cairoGraphics->GetBitmap ();
diff --git a/src/QuicklistMenuItemRadio.h b/src/QuicklistMenuItemRadio.h
index 1b0de505c..1961fdaf8 100755..100644
--- a/src/QuicklistMenuItemRadio.h
+++ b/src/QuicklistMenuItemRadio.h
@@ -39,6 +39,7 @@ class QuicklistMenuItemRadio : public QuicklistMenuItem
~QuicklistMenuItemRadio ();
+ protected:
void PreLayoutManagement ();
long PostLayoutManagement (long layoutResult);
@@ -56,19 +57,9 @@ class QuicklistMenuItemRadio : public QuicklistMenuItem
void PostDraw (nux::GraphicsEngine& gfxContext,
bool forceDraw);
- private:
- nux::NString _text;
- nux::Color _textColor;
- int _pre_layout_width;
- int _pre_layout_height;
- nux::CairoGraphics* _cairoGraphics;
-
- nux::BaseTexture* _normalTexture[2];
- nux::BaseTexture* _prelightTexture[2];
-
void Initialize (DbusmenuMenuitem* item);
- void UpdateTexture ();
+ virtual void UpdateTexture ();
virtual int CairoSurfaceWidth ();
};
diff --git a/src/QuicklistMenuItemSeparator.cpp b/src/QuicklistMenuItemSeparator.cpp
index f519ac9e5..899ccc19a 100755..100644
--- a/src/QuicklistMenuItemSeparator.cpp
+++ b/src/QuicklistMenuItemSeparator.cpp
@@ -24,6 +24,7 @@ QuicklistMenuItemSeparator::QuicklistMenuItemSeparator (DbusmenuMenuitem* item,
QuicklistMenuItem (item,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemSeparator");
SetMinimumHeight (5);
SetBaseSize (64, 5);
//_normalTexture = NULL;
@@ -38,6 +39,7 @@ QuicklistMenuItem (item,
debug,
NUX_FILE_LINE_PARAM)
{
+ _name = g_strdup ("QuicklistMenuItemSeparator");
SetMinimumHeight (5);
SetBaseSize (64, 5);
//_normalTexture = NULL;
diff --git a/src/QuicklistMenuItemSeparator.h b/src/QuicklistMenuItemSeparator.h
index 31e18d73e..31e18d73e 100755..100644
--- a/src/QuicklistMenuItemSeparator.h
+++ b/src/QuicklistMenuItemSeparator.h
diff --git a/src/QuicklistView.cpp b/src/QuicklistView.cpp
index b344faabe..b1cf1ff01 100644
--- a/src/QuicklistView.cpp
+++ b/src/QuicklistView.cpp
@@ -35,10 +35,13 @@
#include "QuicklistMenuItemCheckmark.h"
#include "QuicklistMenuItemRadio.h"
+#include "Introspectable.h"
+
NUX_IMPLEMENT_OBJECT_TYPE (QuicklistView);
QuicklistView::QuicklistView ()
{
+ _name = g_strdup ("Quicklist");
_texture_bg = 0;
_texture_mask = 0;
_texture_outline = 0;
@@ -89,10 +92,14 @@ QuicklistView::QuicklistView ()
OnMouseDrag.connect (sigc::mem_fun (this, &QuicklistView::RecvMouseDrag));
_mouse_down = false;
+ _enable_quicklist_for_testing = false;
}
QuicklistView::~QuicklistView ()
{
+ if (_name)
+ g_free (_name);
+
if (_texture_bg)
_texture_bg->UnReference ();
@@ -105,11 +112,15 @@ QuicklistView::~QuicklistView ()
std::list<QuicklistMenuItem*>::iterator it;
for (it = _item_list.begin(); it != _item_list.end(); it++)
{
+ // Remove from introspection
+ RemoveChild (*it);
(*it)->UnReference();
}
for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
{
+ // Remove from introspection
+ RemoveChild (*it);
(*it)->UnReference();
}
@@ -117,6 +128,12 @@ QuicklistView::~QuicklistView ()
_item_list.clear ();
}
+void
+QuicklistView::EnableQuicklistForTesting (bool enable_testing)
+{
+ _enable_quicklist_for_testing = enable_testing;
+}
+
void QuicklistView::ShowQuicklistWithTipAt (int anchor_tip_x, int anchor_tip_y)
{
int window_width;
@@ -183,12 +200,15 @@ long QuicklistView::ProcessEvent (nux::IEvent& ievent, long TraverseInfo, long P
_mouse_down = false;
if (IsVisible ())
{
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
+ if (!_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
}
return nux::eMouseEventSolved;
}
@@ -198,17 +218,19 @@ long QuicklistView::ProcessEvent (nux::IEvent& ievent, long TraverseInfo, long P
_mouse_down = false;
if (IsVisible ())
{
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
+ if (!_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
}
return nux::eMouseEventSolved;
}
-
-
+
return ret;
}
@@ -396,12 +418,15 @@ void QuicklistView::RecvItemMouseClick (QuicklistMenuItem* item, int x, int y)
// Check if the mouse was released over an item and emit the signal
CheckAndEmitItemSignal (x + item->GetBaseX (), y + item->GetBaseY ());
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
+ if (!_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
}
}
@@ -449,14 +474,17 @@ void QuicklistView::RecvItemMouseRelease (QuicklistMenuItem* item, int x, int y)
{
// Check if the mouse was released over an item and emit the signal
CheckAndEmitItemSignal (x + item->GetBaseX (), y + item->GetBaseY ());
-
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
+
+ if (!_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
+ }
}
void QuicklistView::CancelItemsPrelightStatus ()
@@ -542,12 +570,15 @@ void QuicklistView::RecvMouseClick (int x, int y, unsigned long button_flags, un
{
if (IsVisible ())
{
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
+ if (!_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
}
}
@@ -565,12 +596,15 @@ void QuicklistView::RecvMouseDownOutsideOfQuicklist (int x, int y, unsigned long
{
if (IsVisible ())
{
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
+ if (!_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
}
}
@@ -579,11 +613,15 @@ void QuicklistView::RemoveAllMenuItem ()
std::list<QuicklistMenuItem*>::iterator it;
for (it = _item_list.begin(); it != _item_list.end(); it++)
{
+ // Remove from introspection
+ RemoveChild (*it);
(*it)->UnReference();
}
for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
{
+ // Remove from introspection
+ RemoveChild (*it);
(*it)->UnReference();
}
@@ -612,6 +650,8 @@ void QuicklistView::AddMenuItem (QuicklistMenuItem* item)
_item_layout->AddView(item, 1, nux::eCenter, nux::eFull);
_item_list.push_back (item);
item->Reference();
+ // Add to introspection
+ AddChild (item);
_cairo_text_has_changed = true;
nux::GetGraphicsThread ()->AddObjectToRefreshList (this);
@@ -1263,26 +1303,29 @@ void QuicklistView::UpdateTexture ()
return;
int size_above_anchor = -1; // equal to sise below
-
- if ((_item_list.size () != 0) || (_default_item_list.size () != 0))
- {
- _top_size = 4;
- size_above_anchor = _top_size;
- int x = _anchorX - _padding;
- int y = _anchorY - _anchor_height/2 - _top_size - _corner_radius - _padding;
- SetBaseX (x);
- SetBaseY (y);
- }
- else
+ if (!_enable_quicklist_for_testing)
{
- _top_size = 0;
- size_above_anchor = -1;
- int x = _anchorX - _padding;
- int y = _anchorY - _anchor_height/2 - _top_size - _corner_radius - _padding;
+ if ((_item_list.size () != 0) || (_default_item_list.size () != 0))
+ {
+ _top_size = 4;
+ size_above_anchor = _top_size;
+ int x = _anchorX - _padding;
+ int y = _anchorY - _anchor_height/2 - _top_size - _corner_radius - _padding;
+
+ SetBaseX (x);
+ SetBaseY (y);
+ }
+ else
+ {
+ _top_size = 0;
+ size_above_anchor = -1;
+ int x = _anchorX - _padding;
+ int y = _anchorY - _anchor_height/2 - _top_size - _corner_radius - _padding;
- SetBaseX (x);
- SetBaseY (y);
+ SetBaseX (x);
+ SetBaseY (y);
+ }
}
float blur_coef = 6.0f;
@@ -1438,3 +1481,19 @@ void QuicklistView::TestMenuItems (DbusmenuMenuitem* root)
}
}
+// Introspection
+
+const gchar* QuicklistView::GetName ()
+{
+ return g_strdup (_name);
+}
+
+void QuicklistView::AddProperties (GVariantBuilder *builder)
+{
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (GetBaseX ()));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (GetBaseY ()));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (GetBaseWidth ()));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (GetBaseHeight ()));
+ g_variant_builder_add (builder, "{sv}", "active", g_variant_new_boolean (IsVisible ()));
+}
+
diff --git a/src/QuicklistView.h b/src/QuicklistView.h
index 08e76d77a..ada4d9706 100755..100644
--- a/src/QuicklistView.h
+++ b/src/QuicklistView.h
@@ -31,6 +31,8 @@
#include "QuicklistMenuItem.h"
+#include "Introspectable.h"
+
#define ANCHOR_WIDTH 10.0f
#define ANCHOR_HEIGHT 18.0f
#define HIGH_LIGHT_Y -30.0f
@@ -50,7 +52,7 @@ class SpaceLayout;
class QuicklistMenuItem;
class QuicklistMenuItemLabel;
-class QuicklistView : public nux::BaseWindow
+class QuicklistView : public nux::BaseWindow, public Introspectable
{
NUX_DECLARE_OBJECT_TYPE (QuicklistView, nux::BaseWindow);
public:
@@ -86,6 +88,12 @@ public:
void TestMenuItems (DbusmenuMenuitem* root);
+ // Introspection
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
+
+ void EnableQuicklistForTesting (bool enable_testing);
+
private:
void RecvCairoTextChanged (QuicklistMenuItem* item);
void RecvCairoTextColorChanged (QuicklistMenuItem* item);
@@ -129,7 +137,11 @@ private:
int _top_size; // size of the segment from point 13 to 14. See figure in ql_compute_full_mask_path.
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;
+
cairo_font_options_t* _fontOpts;
nux::BaseTexture* _texture_bg;
@@ -153,6 +165,10 @@ private:
void UpdateTexture ();
std::list<QuicklistMenuItem*> _item_list;
std::list<QuicklistMenuItem*> _default_item_list;
+
+ // Introspection
+ gchar *_name;
+
};
#endif // QUICKLISTVIEW_H
diff --git a/src/SimpleLauncherIcon.cpp b/src/SimpleLauncherIcon.cpp
index b8b0bffaa..c61d78956 100644
--- a/src/SimpleLauncherIcon.cpp
+++ b/src/SimpleLauncherIcon.cpp
@@ -25,20 +25,20 @@
SimpleLauncherIcon::SimpleLauncherIcon (Launcher* IconManager)
: LauncherIcon(IconManager)
{
- m_Icon = 0;
- m_IconName = 0;
-
- LauncherIcon::MouseDown.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseDown));
- LauncherIcon::MouseUp.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseUp));
- LauncherIcon::MouseClick.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseClick));
- LauncherIcon::MouseEnter.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseEnter));
- LauncherIcon::MouseLeave.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseLeave));
+ m_Icon = 0;
+ m_IconName = 0;
+
+ LauncherIcon::MouseDown.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseDown));
+ LauncherIcon::MouseUp.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseUp));
+ LauncherIcon::MouseClick.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseClick));
+ LauncherIcon::MouseEnter.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseEnter));
+ LauncherIcon::MouseLeave.connect (sigc::mem_fun (this, &SimpleLauncherIcon::OnMouseLeave));
}
SimpleLauncherIcon::~SimpleLauncherIcon()
{
- if (m_Icon)
- m_Icon->UnReference ();
+ if (m_Icon)
+ m_Icon->UnReference ();
}
void
@@ -69,21 +69,34 @@ SimpleLauncherIcon::OnMouseLeave ()
nux::BaseTexture *
SimpleLauncherIcon::GetTextureForSize (int size)
{
- if (m_Icon && size == m_Icon->GetHeight ())
- return m_Icon;
-
- if (m_Icon)
- m_Icon->UnReference ();
-
- if (!m_IconName)
- return 0;
+ if (m_Icon && size == m_Icon->GetHeight ())
+ return m_Icon;
+ if (m_Icon)
+ m_Icon->UnReference ();
+
+ if (!m_IconName)
+ return 0;
+
+ if (g_str_has_prefix (m_IconName, "/"))
+ m_Icon = TextureFromPath (m_IconName, size);
+ else
m_Icon = TextureFromGtkTheme (m_IconName, size);
- return m_Icon;
+ return m_Icon;
}
void
SimpleLauncherIcon::SetIconName (const char *name)
{
- m_IconName = g_strdup (name);
+ if (m_IconName)
+ g_free (m_IconName);
+ m_IconName = g_strdup (name);
+
+ if (m_Icon)
+ {
+ m_Icon->UnReference ();
+ m_Icon = 0;
+ }
+
+ needs_redraw.emit (this);
}
diff --git a/src/Tooltip.cpp b/src/Tooltip.cpp
index f19e6faec..fdde92b16 100644
--- a/src/Tooltip.cpp
+++ b/src/Tooltip.cpp
@@ -38,6 +38,7 @@ namespace nux
Tooltip::Tooltip ()
{
+ _name = g_strdup ("Tooltip");
_texture_bg = 0;
_texture_mask = 0;
_texture_outline = 0;
@@ -83,6 +84,9 @@ namespace nux
Tooltip::~Tooltip ()
{
+ if (_name)
+ g_free (_name);
+
if (_texture_bg)
_texture_bg->UnReference ();
@@ -915,4 +919,21 @@ void ctk_surface_blur (cairo_surface_t* surface,
this->ComputeChildLayout ();
}
+ // Introspection
+
+ const gchar* Tooltip::GetName ()
+ {
+ return g_strdup (_name);
+ }
+
+ void Tooltip::AddProperties (GVariantBuilder *builder)
+ {
+ g_variant_builder_add (builder, "{sv}", "text", g_variant_new_string (_labelText.GetTCharPtr ()));
+ g_variant_builder_add (builder, "{sv}", "x", g_variant_new_int32 (GetBaseX ()));
+ g_variant_builder_add (builder, "{sv}", "y", g_variant_new_int32 (GetBaseY ()));
+ g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (GetBaseWidth ()));
+ g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (GetBaseHeight ()));
+ g_variant_builder_add (builder, "{sv}", "active", g_variant_new_boolean (IsVisible ()));
+ }
+
} // namespace nux
diff --git a/src/Tooltip.h b/src/Tooltip.h
index 1e3f01c94..fbbc063a3 100644
--- a/src/Tooltip.h
+++ b/src/Tooltip.h
@@ -31,6 +31,8 @@
#include <pango/pango.h>
#include <pango/pangocairo.h>
+#include "Introspectable.h"
+
#if defined(NUX_OS_LINUX)
#include <X11/Xlib.h>
#endif
@@ -55,7 +57,7 @@ namespace nux
class HLayout;
class SpaceLayout;
- class Tooltip : public BaseWindow
+ class Tooltip : public BaseWindow, public Introspectable
{
NUX_DECLARE_OBJECT_TYPE (Tooltip, BaseWindow);
public:
@@ -76,6 +78,11 @@ namespace nux
void SetText (NString text);
void ShowTooltipWithTipAt (int anchor_tip_x, int anchor_tip_y);
+
+ // Introspection
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
+
private:
void RecvCairoTextChanged (StaticCairoText* cairo_text);
@@ -119,6 +126,9 @@ namespace nux
bool _cairo_text_has_changed;
void UpdateTexture ();
+
+ // Introspection
+ gchar *_name;
};
}
diff --git a/src/TrashLauncherIcon.cpp b/src/TrashLauncherIcon.cpp
index 7f7caac71..24c24ba9b 100644
--- a/src/TrashLauncherIcon.cpp
+++ b/src/TrashLauncherIcon.cpp
@@ -18,6 +18,8 @@
#include "TrashLauncherIcon.h"
+#include <gio/gio.h>
+
TrashLauncherIcon::TrashLauncherIcon (Launcher* IconManager)
: SimpleLauncherIcon(IconManager)
{
@@ -26,10 +28,23 @@ TrashLauncherIcon::TrashLauncherIcon (Launcher* IconManager)
SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, true);
SetQuirk (LAUNCHER_ICON_QUIRK_RUNNING, false);
SetIconType (LAUNCHER_ICON_TYPE_TRASH);
+
+ m_TrashMonitor = g_file_monitor_directory (g_file_new_for_uri("trash:///"),
+ G_FILE_MONITOR_NONE,
+ NULL,
+ NULL);
+
+ g_signal_connect(m_TrashMonitor,
+ "changed",
+ G_CALLBACK (&TrashLauncherIcon::OnTrashChanged),
+ this);
+
+ UpdateTrashIcon ();
}
TrashLauncherIcon::~TrashLauncherIcon()
{
+ g_object_unref (m_TrashMonitor);
}
void
@@ -38,10 +53,58 @@ TrashLauncherIcon::OnMouseClick (int button)
if (button == 1)
{
GError *error = NULL;
-
+
g_spawn_command_line_async ("xdg-open trash://", &error);
-
+
if (error)
g_error_free (error);
}
}
+
+void
+TrashLauncherIcon::UpdateTrashIcon ()
+{
+ GFile *location;
+ location = g_file_new_for_uri ("trash:///");
+
+ g_file_query_info_async (location,
+ G_FILE_ATTRIBUTE_STANDARD_ICON,
+ G_FILE_QUERY_INFO_NONE,
+ 0,
+ NULL,
+ &TrashLauncherIcon::UpdateTrashIconCb,
+ this);
+
+ g_object_unref(location);
+}
+
+void
+TrashLauncherIcon::UpdateTrashIconCb (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
+{
+ TrashLauncherIcon *self = (TrashLauncherIcon*) data;
+ GFileInfo *info;
+ GIcon *icon;
+
+ info = g_file_query_info_finish (G_FILE (source), res, NULL);
+
+ if (info != NULL) {
+ icon = g_file_info_get_icon (info);
+ self->SetIconName (g_icon_to_string (icon));
+
+ g_object_unref(info);
+ }
+}
+
+void
+TrashLauncherIcon::OnTrashChanged (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer data)
+{
+ TrashLauncherIcon *self = (TrashLauncherIcon*) data;
+ self->UpdateTrashIcon ();
+}
+
diff --git a/src/TrashLauncherIcon.h b/src/TrashLauncherIcon.h
index 1680c5502..c07e1a3fe 100644
--- a/src/TrashLauncherIcon.h
+++ b/src/TrashLauncherIcon.h
@@ -30,6 +30,13 @@ public:
protected:
void OnMouseClick (int button);
+ void UpdateTrashIcon ();
+
+private:
+ GFileMonitor *m_TrashMonitor;
+ static void UpdateTrashIconCb (GObject *source, GAsyncResult *res, gpointer data);
+ static void OnTrashChanged (GFileMonitor *monitor, GFile *file, GFile *other_file,
+ GFileMonitorEvent event_type, gpointer data);
};
diff --git a/src/unity.cpp b/src/unity.cpp
index 1260ea090..d60902979 100644
--- a/src/unity.cpp
+++ b/src/unity.cpp
@@ -39,6 +39,8 @@
#include <core/atoms.h>
+#include "../libunity/perf-logger-utility.h"
+
/* Set up vtable symbols */
COMPIZ_PLUGIN_20090315 (unityshell, UnityPluginVTable);
@@ -47,52 +49,52 @@ static UnityScreen *uScreen = 0;
void
UnityScreen::nuxPrologue ()
{
- /* reset matrices */
- glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
-
- glMatrixMode (GL_PROJECTION);
- glPushMatrix ();
-
- glMatrixMode (GL_MODELVIEW);
- glPushMatrix ();
-
- glGetError();
+ /* reset matrices */
+ glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
+
+ glMatrixMode (GL_PROJECTION);
+ glPushMatrix ();
+
+ glMatrixMode (GL_MODELVIEW);
+ glPushMatrix ();
+
+ glGetError();
}
void
UnityScreen::nuxEpilogue ()
{
- (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
+ (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
- glMatrixMode (GL_PROJECTION);
- glLoadIdentity ();
- glMatrixMode (GL_MODELVIEW);
- glLoadIdentity ();
- glDepthRange (0, 1);
- glViewport (-1, -1, 2, 2);
- glRasterPos2f (0, 0);
+ glMatrixMode (GL_PROJECTION);
+ glLoadIdentity ();
+ glMatrixMode (GL_MODELVIEW);
+ glLoadIdentity ();
+ glDepthRange (0, 1);
+ glViewport (-1, -1, 2, 2);
+ glRasterPos2f (0, 0);
- gScreen->resetRasterPos ();
+ gScreen->resetRasterPos ();
- glMatrixMode (GL_PROJECTION);
- glPopMatrix ();
- glMatrixMode (GL_MODELVIEW);
- glPopMatrix ();
+ glMatrixMode (GL_PROJECTION);
+ glPopMatrix ();
+ glMatrixMode (GL_MODELVIEW);
+ glPopMatrix ();
- glDrawBuffer (GL_BACK);
- glReadBuffer (GL_BACK);
+ glDrawBuffer (GL_BACK);
+ glReadBuffer (GL_BACK);
- glPopAttrib ();
+ glPopAttrib ();
}
void
UnityScreen::paintDisplay (const CompRegion &region)
{
- nuxPrologue ();
- wt->RenderInterfaceFromForeignCmd ();
- nuxEpilogue ();
+ nuxPrologue ();
+ wt->RenderInterfaceFromForeignCmd ();
+ nuxEpilogue ();
- doShellRepaint = false;
+ doShellRepaint = false;
}
/* called whenever we need to repaint parts of the screen */
@@ -103,18 +105,18 @@ UnityScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
CompOutput *output,
unsigned int mask)
{
- bool ret;
+ bool ret;
- doShellRepaint = true;
- allowWindowPaint = true;
+ doShellRepaint = true;
+ allowWindowPaint = true;
- /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
- ret = gScreen->glPaintOutput (attrib, transform, region, output, mask);
+ /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
+ ret = gScreen->glPaintOutput (attrib, transform, region, output, mask);
- if (doShellRepaint)
- paintDisplay (region);
+ if (doShellRepaint)
+ paintDisplay (region);
- return ret;
+ return ret;
}
/* called whenever a plugin needs to paint the entire scene
@@ -127,96 +129,96 @@ UnityScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &attrib,
CompOutput *output,
unsigned int mask)
{
- allowWindowPaint = false;
- gScreen->glPaintOutput (attrib, transform, region, output, mask);
+ allowWindowPaint = false;
+ gScreen->glPaintOutput (attrib, transform, region, output, mask);
}
/* Grab changed nux regions and add damage rects for them */
void
UnityScreen::damageNuxRegions ()
{
- CompRegion region;
- std::vector<nux::Geometry>::iterator it;
- std::vector<nux::Geometry> dirty = wt->GetDrawList ();
- nux::Geometry geo;
-
- for (it = dirty.begin (); it != dirty.end (); it++)
- {
- geo = *it;
- cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
- }
-
- geo = wt->GetWindowCompositor ().GetTooltipMainWindowGeometry();
+ CompRegion region;
+ std::vector<nux::Geometry>::iterator it;
+ std::vector<nux::Geometry> dirty = wt->GetDrawList ();
+ nux::Geometry geo;
+
+ for (it = dirty.begin (); it != dirty.end (); it++)
+ {
+ geo = *it;
cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
- cScreen->damageRegion (CompRegion (lastTooltipArea.x, lastTooltipArea.y, lastTooltipArea.width, lastTooltipArea.height));
-
- lastTooltipArea = geo;
-
- wt->ClearDrawList ();
+ }
+
+ geo = wt->GetWindowCompositor ().GetTooltipMainWindowGeometry();
+ cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
+ cScreen->damageRegion (CompRegion (lastTooltipArea.x, lastTooltipArea.y, lastTooltipArea.width, lastTooltipArea.height));
+
+ lastTooltipArea = geo;
+
+ wt->ClearDrawList ();
}
/* handle X Events */
void
UnityScreen::handleEvent (XEvent *event)
{
- screen->handleEvent (event);
+ screen->handleEvent (event);
- if (screen->otherGrabExist ("deco", "move", NULL))
- {
- wt->ProcessForeignEvent (event, NULL);
- }
-}
+ if (screen->otherGrabExist ("deco", "move", NULL))
+ {
+ wt->ProcessForeignEvent (event, NULL);
+ }
+}
gboolean
UnityScreen::initPluginActions (gpointer data)
{
- CompPlugin *p;
+ CompPlugin *p;
- p = CompPlugin::find ("expo");
+ p = CompPlugin::find ("expo");
- if (p)
+ if (p)
+ {
+ foreach (CompOption &option, p->vTable->getOptions ())
{
- foreach (CompOption &option, p->vTable->getOptions ())
- {
- if (option.name () == "expo_key")
- {
- CompAction *action = &option.value ().action ();
- PluginAdapter::Default ()->SetExpoAction (action);
- break;
- }
- }
+ if (option.name () == "expo_key")
+ {
+ CompAction *action = &option.value ().action ();
+ PluginAdapter::Default ()->SetExpoAction (action);
+ break;
+ }
}
+ }
- p = CompPlugin::find ("scale");
+ p = CompPlugin::find ("scale");
- if (p)
+ if (p)
+ {
+ foreach (CompOption &option, p->vTable->getOptions ())
{
- foreach (CompOption &option, p->vTable->getOptions ())
- {
- if (option.name () == "initiate_all_key")
- {
- CompAction *action = &option.value ().action ();
- PluginAdapter::Default ()->SetScaleAction (action);
- break;
- }
- }
+ if (option.name () == "initiate_all_key")
+ {
+ CompAction *action = &option.value ().action ();
+ PluginAdapter::Default ()->SetScaleAction (action);
+ break;
+ }
}
+ }
- return FALSE;
+ return FALSE;
}
/* Set up expo and scale actions on the launcher */
bool
UnityScreen::initPluginForScreen (CompPlugin *p)
{
- if (p->vTable->name () == "expo" ||
- p->vTable->name () == "scale")
- {
- initPluginActions ((void *) this);
- }
+ if (p->vTable->name () == "expo" ||
+ p->vTable->name () == "scale")
+ {
+ initPluginActions ((void *) this);
+ }
- return screen->initPluginForScreen (p);
+ return screen->initPluginForScreen (p);
}
void
@@ -227,23 +229,28 @@ UnityScreen::AddProperties (GVariantBuilder *builder)
const gchar*
UnityScreen::GetName ()
{
- return "Unity";
+ return "Unity";
}
-bool
-UnityWindow::glPaint (const GLWindowPaintAttrib &attrib, const GLMatrix &matrix,
- const CompRegion &region, unsigned int mask)
+const CompWindowList &
+UnityScreen::getWindowPaintList ()
{
+ CompWindowList &pl = _withRemovedNuxWindows = cScreen->getWindowPaintList ();
+ CompWindowList::iterator it = pl.end ();
const std::list <Window> &xwns = nux::XInputWindow::NativeHandleList ();
- GLWindowPaintAttrib new_tribs (attrib);
- if (std::find (xwns.begin (), xwns.end (), window->id ()) != xwns.end ())
+ while (it != pl.begin ())
{
- new_tribs.opacity = 0;
- }
+ it--;
+ if (std::find (xwns.begin (), xwns.end (), (*it)->id ()) != xwns.end ())
+ {
+ CompWindowList::iterator pit = it;
+ pl.erase (pit);
+ }
+ }
- return gWindow->glPaint (new_tribs, matrix, region, mask);
+ return pl;
}
/* handle window painting in an opengl context
@@ -253,66 +260,110 @@ UnityWindow::glPaint (const GLWindowPaintAttrib &attrib, const GLMatrix &matrix,
* stacked on top of one of the nux input windows
* and if so paint nux and stop us from painting
* other windows or on top of the whole screen */
-bool
+bool
UnityWindow::glDraw (const GLMatrix &matrix,
GLFragment::Attrib &attrib,
const CompRegion &region,
unsigned int mask)
{
- if (uScreen->doShellRepaint && uScreen->allowWindowPaint)
+ if (uScreen->doShellRepaint && uScreen->allowWindowPaint)
+ {
+ const std::list <Window> &xwns = nux::XInputWindow::NativeHandleList ();
+
+ for (CompWindow *w = window; w && uScreen->doShellRepaint; w = w->prev)
{
- const std::list <Window> &xwns = nux::XInputWindow::NativeHandleList ();
-
- for (CompWindow *w = window; w && uScreen->doShellRepaint; w = w->prev)
- {
- if (std::find (xwns.begin (), xwns.end (), w->id ()) != xwns.end ())
- {
- uScreen->paintDisplay (region);
- }
- }
+ if (std::find (xwns.begin (), xwns.end (), w->id ()) != xwns.end ())
+ {
+ uScreen->paintDisplay (region);
+ }
}
+ }
+
+ bool ret = gWindow->glDraw (matrix, attrib, region, mask);
- bool ret = gWindow->glDraw (matrix, attrib, region, mask);
-
- return ret;
+ return ret;
}
/* Called whenever a window is mapped, unmapped, minimized etc */
void
UnityWindow::windowNotify (CompWindowNotify n)
{
- if (n == CompWindowNotifyMinimize)
- uScreen->controller->PresentIconOwningWindow (window->id ());
+ switch (n)
+ {
+ case CompWindowNotifyMinimize:
+ uScreen->controller->PresentIconOwningWindow (window->id ());
+ uScreen->launcher->OnWindowDisappear (window);
+ break;
+ case CompWindowNotifyUnminimize:
+ uScreen->launcher->OnWindowAppear (window);
+ break;
+ case CompWindowNotifyShade:
+ uScreen->launcher->OnWindowDisappear (window);
+ break;
+ case CompWindowNotifyUnshade:
+ uScreen->launcher->OnWindowAppear (window);
+ break;
+ case CompWindowNotifyHide:
+ uScreen->launcher->OnWindowDisappear (window);
+ break;
+ case CompWindowNotifyShow:
+ uScreen->launcher->OnWindowAppear (window);
+ break;
+ case CompWindowNotifyMap:
+ uScreen->launcher->OnWindowAppear (window);
+ break;
+ case CompWindowNotifyUnmap:
+ uScreen->launcher->OnWindowDisappear (window);
+ break;
+ default:
+ break;
+ }
- window->windowNotify (n);
+ window->windowNotify (n);
+}
+
+void
+UnityWindow::moveNotify (int x, int y, bool immediate)
+{
+ uScreen->launcher->OnWindowMoved (window);
+ window->moveNotify (x, y, immediate);
+}
+
+void
+UnityWindow::resizeNotify (int x, int y, int w, int h)
+{
+ uScreen->launcher->OnWindowResized (window);
+ window->resizeNotify (x, y, w, h);
}
/* Configure callback for the launcher window */
-void
+void
UnityScreen::launcherWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
{
- int OurWindowHeight = WindowHeight - 24;
- geo = nux::Geometry(0, 24, geo.width, OurWindowHeight);
+ int OurWindowHeight = WindowHeight - 24;
+ geo = nux::Geometry(0, 24, geo.width, OurWindowHeight);
}
/* Configure callback for the panel window */
-void
+void
UnityScreen::panelWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
{
- geo = nux::Geometry(0, 0, WindowWidth, 24);
+ geo = nux::Geometry(0, 0, WindowWidth, 24);
}
/* Start up nux after OpenGL is initialized */
-void
+void
UnityScreen::initUnity(nux::NThread* thread, void* InitData)
{
- initLauncher(thread, InitData);
-
- nux::ColorLayer background(nux::Color(0x00000000));
- static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
+ START_FUNCTION ();
+ initLauncher(thread, InitData);
+
+ nux::ColorLayer background(nux::Color(0x00000000));
+ static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
+ END_FUNCTION ();
}
-void
+void
UnityScreen::onRedrawRequested ()
{
damageNuxRegions ();
@@ -323,18 +374,25 @@ void
UnityScreen::optionChanged (CompOption *opt,
UnityshellOptions::Options num)
{
- switch (num)
- {
- case UnityshellOptions::LauncherAutohide:
- launcher->SetAutohide (optionGetLauncherAutohide (),
- (nux::View *) panelView->HomeButton ());
- break;
- case UnityshellOptions::LauncherFloat:
- launcher->SetFloating (optionGetLauncherFloat ());
- break;
- default:
- break;
- }
+ switch (num)
+ {
+ case UnityshellOptions::LauncherAutohide:
+ launcher->SetAutohide (optionGetLauncherAutohide (),
+ (nux::View *) panelView->HomeButton ());
+ break;
+ case UnityshellOptions::LauncherFloat:
+ launcher->SetFloating (optionGetLauncherFloat ());
+ break;
+ default:
+ break;
+ }
+}
+
+static gboolean
+write_logger_data_to_disk (gpointer data)
+{
+ perf_timeline_logger_write_log (perf_timeline_logger_get_default (), "/tmp/unity-perf.log");
+ return FALSE;
}
UnityScreen::UnityScreen (CompScreen *screen) :
@@ -344,40 +402,43 @@ UnityScreen::UnityScreen (CompScreen *screen) :
gScreen (GLScreen::get (screen)),
doShellRepaint (false)
{
- int (*old_handler) (Display *, XErrorEvent *);
- old_handler = XSetErrorHandler (NULL);
-
- g_thread_init (NULL);
- dbus_g_thread_init ();
- gtk_init (NULL, NULL);
-
- XSetErrorHandler (old_handler);
-
- /* Wrap compiz interfaces */
- ScreenInterface::setHandler (screen);
- GLScreenInterface::setHandler (gScreen);
-
- StartupNotifyService::Default ()->SetSnDisplay (screen->snDisplay (), screen->screenNum ());
-
- nux::NuxInitialize (0);
- wt = nux::CreateFromForeignWindow (cScreen->output (),
- glXGetCurrentContext (),
- &UnityScreen::initUnity,
- this);
-
- wt->RedrawRequested.connect (sigc::mem_fun (this, &UnityScreen::onRedrawRequested));
-
- wt->Run (NULL);
- uScreen = this;
-
- debugger = new IntrospectionDBusInterface (this);
-
- PluginAdapter::Initialize (screen);
-
- optionSetLauncherAutohideNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
- optionSetLauncherFloatNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
-
- g_timeout_add (0, &UnityScreen::initPluginActions, this);
+ START_FUNCTION ();
+ int (*old_handler) (Display *, XErrorEvent *);
+ old_handler = XSetErrorHandler (NULL);
+
+ g_thread_init (NULL);
+ dbus_g_thread_init ();
+ gtk_init (NULL, NULL);
+
+ XSetErrorHandler (old_handler);
+
+ /* Wrap compiz interfaces */
+ ScreenInterface::setHandler (screen);
+ CompositeScreenInterface::setHandler (cScreen);
+ GLScreenInterface::setHandler (gScreen);
+
+ StartupNotifyService::Default ()->SetSnDisplay (screen->snDisplay (), screen->screenNum ());
+
+ nux::NuxInitialize (0);
+ wt = nux::CreateFromForeignWindow (cScreen->output (),
+ glXGetCurrentContext (),
+ &UnityScreen::initUnity,
+ this);
+
+ wt->RedrawRequested.connect (sigc::mem_fun (this, &UnityScreen::onRedrawRequested));
+
+ wt->Run (NULL);
+ uScreen = this;
+
+ debugger = new IntrospectionDBusInterface (this);
+
+ PluginAdapter::Initialize (screen);
+
+ optionSetLauncherAutohideNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
+ optionSetLauncherFloatNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
+
+ g_timeout_add (0, &UnityScreen::initPluginActions, this);
+ END_FUNCTION ();
}
UnityScreen::~UnityScreen ()
@@ -387,27 +448,30 @@ UnityScreen::~UnityScreen ()
/* Can't create windows until after we have initialized everything */
gboolean UnityScreen::strutHackTimeout (gpointer data)
{
- UnityScreen *self = (UnityScreen*) data;
-
- if (!self->launcher->AutohideEnabled ())
- {
- self->launcherWindow->InputWindowEnableStruts(false);
- self->launcherWindow->InputWindowEnableStruts(true);
- }
-
- self->panelWindow->InputWindowEnableStruts(false);
- self->panelWindow->InputWindowEnableStruts(true);
-
- return FALSE;
+ UnityScreen *self = (UnityScreen*) data;
+
+ if (!self->launcher->AutohideEnabled ())
+ {
+ self->launcherWindow->InputWindowEnableStruts(false);
+ self->launcherWindow->InputWindowEnableStruts(true);
+ }
+
+ self->panelWindow->InputWindowEnableStruts(false);
+ self->panelWindow->InputWindowEnableStruts(true);
+
+ return FALSE;
}
/* Start up the launcher */
void UnityScreen::initLauncher (nux::NThread* thread, void* InitData)
{
+ START_FUNCTION ();
+
UnityScreen *self = (UnityScreen*) InitData;
-
+
+ LOGGER_START_PROCESS ("initLauncher-Launcher");
self->launcherWindow = new nux::BaseWindow(TEXT(""));
- self->launcher = new Launcher(self->launcherWindow);
+ self->launcher = new Launcher(self->launcherWindow, self->screen);
self->AddChild (self->launcher);
nux::HLayout* layout = new nux::HLayout();
@@ -428,8 +492,10 @@ void UnityScreen::initLauncher (nux::NThread* thread, void* InitData)
self->launcherWindow->InputWindowEnableStruts(true);
self->launcher->SetIconSize (54, 48);
+ LOGGER_END_PROCESS ("initLauncher-Launcher");
/* Setup panel */
+ LOGGER_START_PROCESS ("initLauncher-Panel");
self->panelView = new PanelView ();
self->AddChild (self->panelView);
@@ -448,10 +514,12 @@ void UnityScreen::initLauncher (nux::NThread* thread, void* InitData)
self->panelWindow->SetBackgroundColor(nux::Color(0x00000000));
self->panelWindow->SetBlurredBackground(false);
self->panelWindow->ShowWindow(true);
- self->panelWindow->EnableInputWindow(true);
+ self->panelWindow->EnableInputWindow(true);
self->panelWindow->InputWindowEnableStruts(true);
-
+ LOGGER_END_PROCESS ("initLauncher-Panel");
g_timeout_add (2000, &UnityScreen::strutHackTimeout, self);
+
+ END_FUNCTION ();
}
/* Window init */
@@ -460,8 +528,8 @@ UnityWindow::UnityWindow (CompWindow *window) :
window (window),
gWindow (GLWindow::get (window))
{
- WindowInterface::setHandler (window);
- GLWindowInterface::setHandler (gWindow);
+ WindowInterface::setHandler (window);
+ GLWindowInterface::setHandler (gWindow);
}
UnityWindow::~UnityWindow ()
@@ -472,13 +540,13 @@ UnityWindow::~UnityWindow ()
bool
UnityPluginVTable::init ()
{
- if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
- return false;
- if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
- return false;
- if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
- return false;
-
- return true;
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
+ return false;
+ if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
+ return false;
+ if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
+ return false;
+
+ return true;
}
diff --git a/src/unity.h b/src/unity.h
index 25bf84e87..cec421f57 100644
--- a/src/unity.h
+++ b/src/unity.h
@@ -84,6 +84,9 @@ class UnityScreen :
CompOutput *,
unsigned int);
+ /* Pop our InputOutput windows from the paint list */
+ const CompWindowList & getWindowPaintList ();
+
/* handle X11 events */
void handleEvent (XEvent *);
@@ -137,7 +140,9 @@ class UnityScreen :
/* handle paint order */
bool doShellRepaint;
- bool allowWindowPaint;
+ bool allowWindowPaint;
+ bool damaged;
+ CompWindowList _withRemovedNuxWindows;
friend class UnityWindow;
};
@@ -157,10 +162,6 @@ class UnityWindow :
CompWindow *window;
GLWindow *gWindow;
- bool
- glPaint (const GLWindowPaintAttrib &, const GLMatrix &,
- const CompRegion &, unsigned int);
-
/* basic window draw function */
bool
glDraw (const GLMatrix &matrix,
@@ -170,6 +171,9 @@ class UnityWindow :
void windowNotify (CompWindowNotify n);
+ void moveNotify (int x, int y, bool immediate);
+
+ void resizeNotify (int x, int y, int w, int h);
};
#define EX_SCREEN (screen) \
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 412b208ad..6f55fe1df 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable (test-unit
../src/FavoriteStore.h
../src/FavoriteStoreGSettings.cpp
../src/FavoriteStoreGSettings.h
+ ../src/Introspectable.cpp
../src/QuicklistMenuItem.cpp
../src/QuicklistMenuItem.h
../src/QuicklistMenuItemCheckmark.cpp
@@ -76,10 +77,32 @@ add_executable (test-panel
../src/IndicatorObjectProxyRemote.h
../src/IndicatorObjectEntryProxyRemote.cpp
../src/IndicatorObjectEntryProxyRemote.h
+ ../src/Introspectable.cpp
+ ../src/Introspectable.h
../src/PanelHomeButton.cpp
../src/PanelHomeButton.h
)
+add_executable (test-quicklist
+ ui/TestQuicklist.cpp
+ ui/EventFaker.cpp
+ ui/EventFaker.h
+ ../src/Introspectable.cpp
+ ../src/Introspectable.h
+ ../src/QuicklistMenuItem.cpp
+ ../src/QuicklistMenuItem.h
+ ../src/QuicklistMenuItemCheckmark.cpp
+ ../src/QuicklistMenuItemCheckmark.h
+ ../src/QuicklistMenuItemLabel.cpp
+ ../src/QuicklistMenuItemLabel.h
+ ../src/QuicklistMenuItemRadio.cpp
+ ../src/QuicklistMenuItemRadio.h
+ ../src/QuicklistMenuItemSeparator.cpp
+ ../src/QuicklistMenuItemSeparator.h
+ ../src/QuicklistView.cpp
+ ../src/QuicklistView.h
+ )
+
#
# check target
#
diff --git a/tests/ui/EventFaker.cpp b/tests/ui/EventFaker.cpp
new file mode 100644
index 000000000..dca74a362
--- /dev/null
+++ b/tests/ui/EventFaker.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Mirco Müller <mirco.mueller@canonical.com>
+ */
+
+#include "EventFaker.h"
+
+#include "NuxGraphics/GLWindowManager.h"
+#include <X11/Xlib.h>
+
+EventFaker::EventFaker (nux::WindowThread* thread)
+{
+ _thread = thread;
+}
+
+EventFaker::~EventFaker ()
+{
+}
+
+void
+EventFaker::SendClick (nux::View* view)
+{
+ Display* display = NULL;
+ int x = 0;
+ int y = 0;
+
+ // sanity check
+ if (!view)
+ return;
+
+ display = nux::GetThreadGLWindow()->GetX11Display ();
+
+ // get a point inside the view
+ x = view->GetBaseX () + 1;
+ y = view->GetBaseY () + 1;
+
+ // assemble a button-click event
+ XButtonEvent buttonEvent = {
+ ButtonRelease,
+ 0,
+ False,
+ display,
+ 0,
+ 0,
+ 0,
+ CurrentTime,
+ x, y,
+ x, y,
+ 0,
+ Button1,
+ True
+ };
+
+ // send that button-click to the "thread"
+ doEvent (view, (XEvent*) &buttonEvent);
+}
+
+void
+EventFaker::doEvent (nux::View* view,
+ XEvent* event)
+{
+ Display* display = NULL;
+
+ // sanity check
+ if (!view || !event)
+ return;
+
+ display = nux::GetThreadGLWindow()->GetX11Display ();
+ XUngrabPointer (display, CurrentTime);
+ XFlush (display);
+
+ _thread->ProcessForeignEvent (event, NULL);
+
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, false);
+}
diff --git a/tests/ui/EventFaker.h b/tests/ui/EventFaker.h
new file mode 100644
index 000000000..26eef4917
--- /dev/null
+++ b/tests/ui/EventFaker.h
@@ -0,0 +1,40 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Mirco Müller <mirco.mueller@canonical.com>
+ */
+
+#ifndef EVENT_FAKER_H
+#define EVENT_FAKER_H
+
+#include "Nux/Nux.h"
+#include "Nux/WindowThread.h"
+
+class EventFaker
+{
+ public:
+ EventFaker (nux::WindowThread* thread);
+ ~EventFaker ();
+
+ void SendClick (nux::View* view);
+
+ void doEvent (nux::View* view,
+ XEvent* event);
+
+ private:
+ nux::WindowThread* _thread;
+};
+
+#endif // EVENT_FAKER_H
diff --git a/tests/ui/TestQuicklist.cpp b/tests/ui/TestQuicklist.cpp
new file mode 100644
index 000000000..bcf08a6be
--- /dev/null
+++ b/tests/ui/TestQuicklist.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Mirco Müller <mirco.mueller@canonical.com>
+ */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <dbus/dbus-glib.h>
+
+#include "Nux/Nux.h"
+#include "Nux/VLayout.h"
+#include "Nux/WindowThread.h"
+
+#include "QuicklistView.h"
+#include "QuicklistMenuItem.h"
+#include "QuicklistMenuItemLabel.h"
+#include "QuicklistMenuItemSeparator.h"
+#include "QuicklistMenuItemCheckmark.h"
+#include "QuicklistMenuItemRadio.h"
+
+#include "EventFaker.h"
+#include <X11/Xlib.h>
+
+#define WIN_WIDTH 400
+#define WIN_HEIGHT 300
+
+gboolean gResult[3] = {false, false, false};
+
+QuicklistView* gQuicklist = NULL;
+QuicklistMenuItemCheckmark* gCheckmark = NULL;
+QuicklistMenuItemRadio* gRadio = NULL;
+QuicklistMenuItemLabel* gLabel = NULL;
+
+void
+activatedCallback (DbusmenuMenuitem* item,
+ int time,
+ gpointer data)
+{
+ gboolean* result = (gboolean*) data;
+
+ *result = true;
+
+ g_print ("Quicklist-item activated\n");
+}
+
+QuicklistMenuItemCheckmark*
+createCheckmarkItem ()
+{
+ DbusmenuMenuitem* item = NULL;
+ QuicklistMenuItemCheckmark* checkmark = NULL;
+
+ item = dbusmenu_menuitem_new ();
+
+ dbusmenu_menuitem_property_set (item,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ "Unchecked");
+
+ dbusmenu_menuitem_property_set (item,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
+ DBUSMENU_MENUITEM_TOGGLE_CHECK);
+
+ dbusmenu_menuitem_property_set_bool (item,
+ DBUSMENU_MENUITEM_PROP_ENABLED,
+ true);
+
+ dbusmenu_menuitem_property_set_int (item,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
+ DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
+
+ checkmark = new QuicklistMenuItemCheckmark (item, true);
+
+ g_signal_connect (item,
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activatedCallback),
+ &gResult[0]);
+
+ return checkmark;
+}
+
+QuicklistMenuItemRadio*
+createRadioItem ()
+{
+ DbusmenuMenuitem* item = NULL;
+ QuicklistMenuItemRadio* radio = NULL;
+
+ item = dbusmenu_menuitem_new ();
+
+ dbusmenu_menuitem_property_set (item,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ "Radio Active");
+
+ dbusmenu_menuitem_property_set (item,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
+ DBUSMENU_MENUITEM_TOGGLE_RADIO);
+
+ dbusmenu_menuitem_property_set_bool (item,
+ DBUSMENU_MENUITEM_PROP_ENABLED,
+ true);
+
+ dbusmenu_menuitem_property_set_int (item,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
+ DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
+
+ radio = new QuicklistMenuItemRadio (item, true);
+
+ g_signal_connect (item,
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activatedCallback),
+ &gResult[1]);
+
+ return radio;
+}
+
+QuicklistMenuItemLabel*
+createLabelItem ()
+{
+ DbusmenuMenuitem* item = NULL;
+ QuicklistMenuItemLabel* label = NULL;
+
+ item = dbusmenu_menuitem_new ();
+
+ dbusmenu_menuitem_property_set (item,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ "A Label");
+
+ dbusmenu_menuitem_property_set_bool (item,
+ DBUSMENU_MENUITEM_PROP_ENABLED,
+ true);
+
+ label = new QuicklistMenuItemLabel (item, true);
+
+ g_signal_connect (item,
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activatedCallback),
+ &gResult[2]);
+
+ return label;
+}
+
+void
+ThreadWidgetInit (nux::NThread* thread,
+ void* initData)
+{
+ gQuicklist = new QuicklistView ();
+ gQuicklist->Reference ();
+
+ gCheckmark = createCheckmarkItem ();
+ gQuicklist->AddMenuItem (gCheckmark);
+ gRadio = createRadioItem ();
+ gQuicklist->AddMenuItem (gRadio);
+ gLabel = createLabelItem ();
+ gQuicklist->AddMenuItem (gLabel);
+
+ gQuicklist->EnableQuicklistForTesting (true);
+
+ gQuicklist->SetBaseXY (0, 0);
+ gQuicklist->ShowWindow (true);
+}
+
+void
+ControlThread (nux::NThread* thread,
+ void* data)
+{
+ // sleep for 3 seconds
+ nux::SleepForMilliseconds (3000);
+ printf ("ControlThread successfully started\n");
+
+ nux::WindowThread* mainWindowThread = NUX_STATIC_CAST (nux::WindowThread*,
+ data);
+
+ mainWindowThread->SetFakeEventMode (true);
+ Display* display = mainWindowThread->GetWindow ().GetX11Display ();
+
+ // assemble first button-click event
+ XEvent buttonPressEvent;
+ buttonPressEvent.xbutton.type = ButtonPress;
+ buttonPressEvent.xbutton.serial = 0;
+ buttonPressEvent.xbutton.send_event = False;
+ buttonPressEvent.xbutton.display = display;
+ buttonPressEvent.xbutton.window = 0;
+ buttonPressEvent.xbutton.root = 0;
+ buttonPressEvent.xbutton.subwindow = 0;
+ buttonPressEvent.xbutton.time = CurrentTime;
+ buttonPressEvent.xbutton.x = 50;
+ buttonPressEvent.xbutton.y = 30;
+ buttonPressEvent.xbutton.x_root = 0;
+ buttonPressEvent.xbutton.y_root = 0;
+ buttonPressEvent.xbutton.state = 0;
+ buttonPressEvent.xbutton.button = Button1;
+ buttonPressEvent.xbutton.same_screen = True;
+
+ mainWindowThread->PumpFakeEventIntoPipe (mainWindowThread,
+ (XEvent*) &buttonPressEvent);
+
+ while (!mainWindowThread->ReadyForNextFakeEvent ())
+ nux::SleepForMilliseconds (10);
+
+ XEvent buttonReleaseEvent;
+ buttonReleaseEvent.xbutton.type = ButtonRelease;
+ buttonReleaseEvent.xbutton.serial = 0;
+ buttonReleaseEvent.xbutton.send_event = False;
+ buttonReleaseEvent.xbutton.display = display;
+ buttonReleaseEvent.xbutton.window = 0;
+ buttonReleaseEvent.xbutton.root = 0;
+ buttonReleaseEvent.xbutton.subwindow = 0;
+ buttonReleaseEvent.xbutton.time = CurrentTime;
+ buttonReleaseEvent.xbutton.x = 50;
+ buttonReleaseEvent.xbutton.y = 30;
+ buttonReleaseEvent.xbutton.x_root = 0;
+ buttonReleaseEvent.xbutton.y_root = 0;
+ buttonReleaseEvent.xbutton.state = 0;
+ buttonReleaseEvent.xbutton.button = Button1;
+ buttonReleaseEvent.xbutton.same_screen = True;
+
+ mainWindowThread->PumpFakeEventIntoPipe (mainWindowThread,
+ (XEvent*) &buttonReleaseEvent);
+
+ while (!mainWindowThread->ReadyForNextFakeEvent ())
+ nux::SleepForMilliseconds (10);
+
+ // assemble second button-click event
+ buttonPressEvent.xbutton.time = CurrentTime;
+ buttonPressEvent.xbutton.x = 50;
+ buttonPressEvent.xbutton.y = 50;
+ mainWindowThread->PumpFakeEventIntoPipe (mainWindowThread,
+ (XEvent*) &buttonPressEvent);
+ while (!mainWindowThread->ReadyForNextFakeEvent ())
+ nux::SleepForMilliseconds (10);
+
+ buttonReleaseEvent.xbutton.time = CurrentTime;
+ buttonReleaseEvent.xbutton.x = 50;
+ buttonReleaseEvent.xbutton.y = 50;
+ mainWindowThread->PumpFakeEventIntoPipe (mainWindowThread,
+ (XEvent*) &buttonReleaseEvent);
+ while (!mainWindowThread->ReadyForNextFakeEvent ())
+ nux::SleepForMilliseconds (10);
+
+ // assemble third button-click event
+ buttonPressEvent.xbutton.time = CurrentTime;
+ buttonPressEvent.xbutton.x = 50;
+ buttonPressEvent.xbutton.y = 70;
+ mainWindowThread->PumpFakeEventIntoPipe (mainWindowThread,
+ (XEvent*) &buttonPressEvent);
+ while (!mainWindowThread->ReadyForNextFakeEvent ())
+ nux::SleepForMilliseconds (10);
+
+ buttonReleaseEvent.xbutton.time = CurrentTime;
+ buttonReleaseEvent.xbutton.x = 50;
+ buttonReleaseEvent.xbutton.y = 70;
+ mainWindowThread->PumpFakeEventIntoPipe (mainWindowThread,
+ (XEvent*) &buttonReleaseEvent);
+ while (!mainWindowThread->ReadyForNextFakeEvent ())
+ nux::SleepForMilliseconds (10);
+
+ mainWindowThread->SetFakeEventMode (false);
+}
+
+int
+main (int argc, char **argv)
+{
+ nux::WindowThread* wt = NULL;
+ nux::SystemThread* st = NULL;
+
+ g_type_init ();
+ g_thread_init (NULL);
+ gtk_init (&argc, &argv);
+ dbus_g_thread_init ();
+ nux::NuxInitialize (0);
+
+ wt = nux::CreateGUIThread (TEXT ("Unity Quicklist"),
+ WIN_WIDTH,
+ WIN_HEIGHT,
+ 0,
+ &ThreadWidgetInit,
+ NULL);
+
+ st = nux::CreateSystemThread (NULL, ControlThread, wt);
+ if (st)
+ st->Start (NULL);
+
+ wt->Run (NULL);
+
+ gQuicklist->UnReference ();
+ delete st;
+ delete wt;
+
+ g_assert_cmpint (gResult[0], ==, true);
+ g_assert_cmpint (gResult[1], ==, true);
+ g_assert_cmpint (gResult[2], ==, true);
+
+ return 0;
+}
diff --git a/tests/unit/TestPanelService.cpp b/tests/unit/TestPanelService.cpp
index 7136d4056..55206bae6 100644
--- a/tests/unit/TestPanelService.cpp
+++ b/tests/unit/TestPanelService.cpp
@@ -157,6 +157,14 @@ test_object_add_entry (TestObject *self,
return entry;
}
+void
+test_object_show_entry (TestObject *self,
+ IndicatorObjectEntry *entry,
+ guint timestamp)
+{
+ g_signal_emit (self, INDICATOR_OBJECT_SIGNAL_MENU_SHOW_ID, 0, entry, timestamp);
+}
+
//----------------------- /TESTING INDICATOR STUFF ----------------------------
//------------------------ USEFUL FUNCTIONS -----------------------------------
@@ -243,6 +251,7 @@ static void TestAllocation (void);
static void TestIndicatorLoading (void);
static void TestEmptyIndicatorObject (void);
static void TestEntryAddition (void);
+static void TestEntryActivateRequest (void);
void
TestPanelServiceCreateSuite ()
@@ -253,6 +262,7 @@ TestPanelServiceCreateSuite ()
g_test_add_func (_DOMAIN"/IndicatorLoading", TestIndicatorLoading);
g_test_add_func (_DOMAIN"/EmptyIndicatorObject", TestEmptyIndicatorObject);
g_test_add_func (_DOMAIN"/EntryAddition", TestEntryAddition);
+ g_test_add_func (_DOMAIN"/EntryActivateRequest", TestEntryActivateRequest);
}
static void
@@ -351,3 +361,41 @@ TestEntryAddition ()
g_object_unref (object);
g_object_unref (service);
}
+
+static void
+OnEntryActivateRequest (IndicatorObject *object,
+ const gchar *entry_id,
+ const gchar *entry_id_should_be)
+{
+ g_assert_cmpstr (entry_id, ==, entry_id_should_be);
+}
+
+static void
+TestEntryActivateRequest ()
+{
+ PanelService *service;
+ TestObject *object;
+ GList *objects = NULL;
+ IndicatorObjectEntry *entry;
+ gchar *id;
+
+ object = (TestObject *)test_object_new ();
+ entry = test_object_add_entry (object, "Hello", "gtk-apply");
+ id = g_strdup_printf ("%p", entry);
+ g_assert (INDICATOR_IS_OBJECT (object));
+ objects = g_list_append (objects, object);
+
+ service = panel_service_get_default_with_indicators (objects);
+ g_assert (PANEL_IS_SERVICE (service));
+
+ g_signal_connect (service, "entry-activate-request",
+ G_CALLBACK (OnEntryActivateRequest),
+ id);
+
+ test_object_show_entry (object, entry, 1234);
+
+ g_free (id);
+ g_list_free (objects);
+ g_object_unref (object);
+ g_object_unref (service);
+}
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index cec32fdb0..523e56f65 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,5 +1,9 @@
#
# Some unity tools
#
-install(FILES migrate_favorites.py PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
+install(FILES makebootchart.py migrate_favorites.py PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/unity.cmake ${CMAKE_BINARY_DIR}/bin/unity)
+install(FILES ${CMAKE_BINARY_DIR}/bin/unity PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
+GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION bin)
diff --git a/tools/makebootchart.py b/tools/makebootchart.py
index 8ec9bf2a6..891549470 100755
--- a/tools/makebootchart.py
+++ b/tools/makebootchart.py
@@ -24,8 +24,8 @@ import csv
import math
import random
from string import Template
-from socket import gethostname
-from datetime import datetime
+from socket import gethostname
+from datetime import datetime
import re
import subprocess
@@ -39,22 +39,22 @@ def sort_by_domain (x, y):
if x["start"] - y["start"] < 0:
return -1
else:
- return +1
-
+ return +1
+
def gatherinfo (filename):
date = datetime.fromtimestamp(os.path.getmtime(filename))
-
+
cpufile = open ("/proc/cpuinfo")
cpuinfo = cpufile.read (10024)
cpure = re.search (r"^model name\s*: (.*$)", cpuinfo, re.MULTILINE)
cpu = cpure.group(1)
-
+
gpu_prog = subprocess.Popen("glxinfo", stdout=subprocess.PIPE)
- gpu_prog.wait ()
+ gpu_prog.wait ()
gpuinfo = gpu_prog.stdout.read (10024)
gpure = re.search (r"^OpenGL renderer string: (.*$)", gpuinfo, re.MULTILINE)
gpu = gpure.group (1)
-
+
return {"hostname":gethostname(),
"date": date.strftime("%A, %d. %B %Y %I:%M%p"),
"uname": " ".join (os.uname ()),
@@ -67,14 +67,14 @@ width_multiplier = 1000
bar_height = 16
def draw_bg_graph (ctx, seconds, height):
-
+
total_width = seconds * width_multiplier
ctx.set_source_rgba (0.0, 0.0, 0.0, 0.25)
-
+
ctx.move_to (0, 0)
ctx.line_to (total_width, 0)
ctx.stroke ()
-
+
per_ten = 0
for pos in xrange (0, int(total_width), int (0.01 * width_multiplier)):
ctx.set_line_width (1)
@@ -90,67 +90,67 @@ def draw_bg_graph (ctx, seconds, height):
ctx.move_to (pos, 0)
ctx.line_to (pos, height)
ctx.stroke ()
-
+
per_ten += 1
per_ten %= 10
def build_graph (data, filename, info):
-
+
padding_left = 6
padding_right = 100
padding_top = 6
padding_bottom = 6
-
+
total_size = 0.0
for item in data:
if item['end'] > total_size:
total_size = item['end']
-
+
width = total_size * width_multiplier + padding_left + padding_right
height = (len(data) * (bar_height)) + 80 + padding_bottom + padding_top
- surface = cairo.SVGSurface(filename, width, height)
-
+ surface = cairo.SVGSurface(filename, max (width, 800), max (height, 600))
+
ctx = cairo.Context (surface)
#fill background
ctx.set_source_rgb (1, 1, 1)
- ctx.rectangle (0, 0, width, height)
+ ctx.rectangle (0, 0, max (width, 800), max (height, 600))
ctx.fill ()
-
+
#print header
info['total_time'] = "%s secs" % total_size
sheader = header.substitute(info)
-
+
ctx.translate (padding_left, padding_top)
ctx.set_source_rgb (0, 0, 0)
for line in sheader.split("\n"):
ctx.translate (0, 12)
ctx.show_text (line)
ctx.fill ()
-
- ctx.translate (0, 12)
-
- draw_bg_graph (ctx, total_size, len (data) * bar_height + 16)
-
+
+ ctx.translate (6, 12)
+
+ draw_bg_graph (ctx, total_size + 0.5, max (len (data) * bar_height + 64, 500))
+
ctx.set_line_width (1)
for item in data:
x = item['start'] * width_multiplier
x1 = (item['end'] - item['start']) * width_multiplier
ctx.translate (x, 0)
-
+
ctx.set_source_rgba (0.35, 0.65, 0.8, 0.5)
ctx.rectangle (0, 0, x1, 16)
ctx.fill ()
-
+
ctx.set_source_rgba (0.35, 0.65, 0.8, 1.0)
ctx.rectangle (0, 0, x1, 16)
ctx.stroke ()
-
+
ctx.translate (8, 10)
ctx.set_source_rgb (0.0, 0.0, 0.0)
- ctx.show_text ("%s %.2f seconds" % (item['name'], round (item["end"] - item["start"], 2)))
+ ctx.show_text ("%s %.4f seconds" % (item['name'], item["end"] - item["start"]))
ctx.fill()
-
+
ctx.translate (-x-8, 6)
def build_data_structure (input):
@@ -162,13 +162,13 @@ def build_data_structure (input):
start = float(row[1])
end = float(row[2])
structure.append ({"name": name, "start": start, "end": end})
-
+
structure.sort (sort_by_domain)
return structure
-
+
def usage():
- print "use --input=filename.log and --output=filename.svg :)"
+ print "use --input=filename.log and --output=filename.svg :)"
def main():
@@ -179,7 +179,7 @@ def main():
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
-
+
output = None
input = None
for o, a in opts:
@@ -196,7 +196,7 @@ def main():
if (not output or not input):
usage()
sys.exit()
-
+
data = build_data_structure (input)
info = gatherinfo (input)
build_graph (data, output, info)
diff --git a/tools/migrate_favorites.py b/tools/migrate_favorites.py
index f29689fb2..ab0e62b47 100755
--- a/tools/migrate_favorites.py
+++ b/tools/migrate_favorites.py
@@ -7,6 +7,7 @@
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
+import datetime
import gconf
import glob
import gobject
@@ -17,12 +18,34 @@ from xdg import BaseDirectory
LAST_MIGRATION = '3.2.0'
+def get_log_file():
+ ''' open the log file and return it '''
+
+ data_path = "%s/unity" % BaseDirectory.xdg_data_home
+ if not os.path.isdir(data_path):
+ os.mkdir(data_path)
+ try:
+ return open("%s/migration_script.log" % data_path, "a")
+ except IOError:
+ return None
+
+def migrating_chapter_log(name, apps_list, migration_list, log_file):
+ '''Log migration of new launchers'''
+
+ log(" Migration for %s.\n Current app list is: %s\n Candidates are: %s" % (name, apps_list, migration_list), log_file)
+
+
+def log(message, log_file):
+ ''' log if log_file present'''
+ if log_file:
+ log_file.write("%s\n" % message)
+
def get_desktop_dir():
''' no python binding from xdg to get the desktop directory? '''
possible_desktop_folder = None
try:
- for line in file(os.path.expanduser('~/.config/user-dirs.dirs')):
+ for line in file('%s/user-dirs.dirs' % BaseDirectory.xdg_config_home):
values = line.split('=')
if values[0] == 'XDG_DESKTOP_DIR':
try:
@@ -38,13 +61,16 @@ def get_desktop_dir():
pass
return os.path.expanduser('~/Desktop')
-def register_new_app(launcher_location, apps_list):
+def register_new_app(launcher_location, apps_list, log_file):
''' append a new app with full desktop path if valid, take care of dups '''
# default distribution launcher don't go into that function (as don't have an aboslute path)
entry = ""
if os.path.exists(launcher_location):
+ log(" == %s: exists" % launcher_location, log_file)
# try to strip the full path we had in unity mutter if it's part of a xdg path:
+ # or try to get that for other desktop file based on name.
+ candidate_desktop_filename = launcher_location.split("/")[-1]
for xdg_dir in BaseDirectory.xdg_data_dirs:
xdg_app_dir = os.path.join(xdg_dir, "applications", "")
if launcher_location.startswith(xdg_app_dir):
@@ -53,10 +79,21 @@ def register_new_app(launcher_location, apps_list):
if not '/' in candidate_desktop_file:
entry = candidate_desktop_file
break
+ # second chance: try to see if the desktop filename is in xdg path and so, assume it's a match
+ if os.path.exists("%s/%s" % (xdg_app_dir, candidate_desktop_filename)):
+ entry = candidate_desktop_filename
+ break
+
if not entry:
entry = launcher_location
+ log(" %s: real entry is %s" % (launcher_location, entry), log_file)
if entry not in apps_list:
+ log(" --- adding %s as not in app_list" % entry, log_file)
apps_list.append(entry)
+ else:
+ log(" --- NOT adding %s as already in app_list" % entry, log_file)
+ else:
+ log(" == %s: doesn't exist" % launcher_location, log_file)
return apps_list
@@ -76,11 +113,16 @@ client = gconf.client_get_default()
defaults_call = subprocess.Popen(["gsettings", "get", "com.canonical.Unity.Launcher", "favorites"], stdout=subprocess.PIPE)
apps_list = [elem.strip()[1:-1] for elem in defaults_call.communicate()[0].strip()[1:-1].split(',')]
+log_file = get_log_file()
+log("Migration script called on %s\n" % str(datetime.datetime.now()), log_file)
+
# first migration to unity compiz
if migration_level < '3.2.0':
+ log("======= Migration to 3.2.0 =======\n", log_file)
unity_mutter_favorites_list = client.get_list('/desktop/unity/launcher/favorites/favorites_list', gconf.VALUE_STRING)
unity_mutter_launcher_ordered = {}
+ migrating_chapter_log("unity mutter", apps_list, unity_mutter_favorites_list, log_file)
for candidate in unity_mutter_favorites_list:
candidate_path = '/desktop/unity/launcher/favorites/%s' % candidate
if (client.get_string('%s/type' % candidate_path) == 'application'):
@@ -90,21 +132,23 @@ if migration_level < '3.2.0':
# try to preserve the order, will be done in a second loop
unity_mutter_launcher_ordered[position] = launcher_location
for launcher_location in unity_mutter_launcher_ordered:
- apps_list = register_new_app(launcher_location, apps_list)
+ apps_list = register_new_app(launcher_location, apps_list, log_file)
# import netbook-launcher favorites and convert them
lucid_favorites_list = client.get_list('/apps/netbook-launcher/favorites/favorites_list', gconf.VALUE_STRING)
+ migrating_chapter_log("netbook-launcher favorites", apps_list, lucid_favorites_list, log_file)
for candidate in lucid_favorites_list:
candidate_path = '/apps/netbook-launcher/favorites/%s' % candidate
if (client.get_string('%s/type' % candidate_path) == 'application'):
launcher_location = client.get_string('%s/desktop_file' % candidate_path)
if launcher_location:
- apps_list = register_new_app(launcher_location, apps_list)
+ apps_list = register_new_app(launcher_location, apps_list, log_file)
# get GNOME panel favorites and convert them
panel_list = client.get_list('/apps/panel/general/toplevel_id_list', gconf.VALUE_STRING)
candidate_objects = client.get_list('/apps/panel/general/object_id_list', gconf.VALUE_STRING)
+ migrating_chapter_log("gnome-panel items", apps_list, candidate_objects, log_file)
for candidate in candidate_objects:
candidate_path = '/apps/panel/objects/%s' % candidate
if (client.get_string('%s/object_type' % candidate_path) == 'launcher-object'
@@ -113,14 +157,16 @@ if migration_level < '3.2.0':
if launcher_location:
if not launcher_location.startswith('/'):
launcher_location = os.path.expanduser('~/.gnome2/panel2.d/default/launchers/%s' % launcher_location)
- apps_list = register_new_app(launcher_location, apps_list)
+ apps_list = register_new_app(launcher_location, apps_list, log_file)
# get GNOME desktop launchers
desktop_dir = get_desktop_dir()
+ desktop_items = glob.glob('%s/*.desktop' % desktop_dir)
+ migrating_chapter_log("deskop items in %s" % desktop_dir, apps_list, desktop_items, log_file)
for launcher_location in glob.glob('%s/*.desktop' % desktop_dir):
# blacklist ubiquity as will have two ubiquity in the netbook live session then
if not "ubiquity" in launcher_location:
- apps_list = register_new_app(launcher_location, apps_list)
+ apps_list = register_new_app(launcher_location, apps_list, log_file)
# Now write to gsettings!
#print apps_list
@@ -128,6 +174,9 @@ if migration_level < '3.2.0':
if return_code != 0:
print "Settings fail to transition to new unity compiz"
+ log("Settings fail to transition to new unity compiz\n\n", log_file)
+ if log_file:
+ log_file.close()
sys.exit(1)
# some autumn cleanage (gconf binding for recursive_unset seems broken)
@@ -135,6 +184,10 @@ if migration_level < '3.2.0':
subprocess.call(["gconftool-2", "--recursive-unset", "/desktop/unity"])
print "Settings successfully transitionned to new unity compiz"
+log("Migration script ended sucessfully\n\n", log_file)
+if log_file:
+ log_file.close()
+
# stamp that all went well
subprocess.call(["gsettings", "set", "com.canonical.Unity.Launcher", "favorite-migration", "\'%s\'" % LAST_MIGRATION])
sys.exit(0)
diff --git a/tools/unity.cmake b/tools/unity.cmake
new file mode 100755
index 000000000..5c5ccc352
--- /dev/null
+++ b/tools/unity.cmake
@@ -0,0 +1,127 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010 Canonical
+#
+# Authors:
+# Didier Roche <didrocks@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 3.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUTa
+# 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import gconf
+from optparse import OptionParser
+import os
+import signal
+import subprocess
+import sys
+import time
+
+
+def set_unity_env ():
+ '''set variable environnement for unity to run'''
+
+ os.environ['COMPIZ_CONFIG_PROFILE'] = 'ubuntu'
+
+ if not 'DISPLAY' in os.environ:
+ # take an optimistic chance and warn about it :)
+ print "WARNING: no DISPLAY variable set, setting it to :0"
+ os.environ['DISPLAY'] = ':0'
+
+def reset_unity_compiz_profile ():
+ '''reset the compiz/unity profile to a vanilla one'''
+
+ client = gconf.client_get_default()
+
+ # get current compiz profile to know if we need to switch or not
+ # as compiz is setting that as a default key schema each time you
+ # change the profile, the key isn't straightforward to get and set
+ # as compiz set a new schema instead of a value..
+ current_profile_schema = client.get_schema("/apps/compizconfig-1/current_profile")
+ current_profile_gconfvalue = client.get_schema("/apps/compizconfig-1/current_profile").get_default_value()
+ if current_profile_gconfvalue.get_string() == 'unity':
+ print "WARNING: Unity currently default profile, so switching to metacity while resetting the values"
+ subprocess.Popen(["metacity", "--replace"]) #TODO: check if compiz is indeed running
+ # wait for compiz to stop
+ time.sleep(2)
+ current_profile_gconfvalue.set_string('fooo')
+ current_profile_schema.set_default_value(current_profile_gconfvalue)
+ client.set_schema("/apps/compizconfig-1/current_profile", current_profile_schema)
+ # the python binding doesn't recursive-unset right
+ subprocess.Popen(["gconftool-2", "--recursive-unset", "/apps/compiz-1"]).communicate()
+ subprocess.Popen(["gconftool-2", "--recursive-unset", "/apps/compizconfig-1/profiles/unity"]).communicate()
+
+
+def process_and_start_unity (verbose, debug, compiz_args, log_file):
+ '''launch unity under compiz (replace the current shell in any case)'''
+
+ cli = []
+
+ if debug:
+ # we can do more check later as if it's in PATH...
+ if not os.path.isfile('/usr/bin/gdb'):
+ print("ERROR: you don't have gdb in your system. Please install it to run in advanced debug mode.")
+ sys.exit(1)
+ elif 'DESKTOP_SESSION' in os.environ:
+ print("ERROR: it seems you are under a graphical environment. That's incompatible with executing advanced-debug option. You should be in a tty.")
+ sys.exit(1)
+ else:
+ cli.extend(['gdb', '--args'])
+
+ cli.extend(['compiz', '--replace'])
+ if options.verbose:
+ cli.append("--debug")
+ if args:
+ cli.extend(compiz_args)
+
+ if log_file:
+ cli.extend(['2>&1', '|', 'tee', log_file])
+
+ # shell = True as it's the simpest way to | tee.
+ # In this case, we need a string and not a list
+ # FIXME: still some bug with 2>&1 not showing everything before wait()
+ return subprocess.Popen(" ".join(cli), env=dict(os.environ), shell=True)
+
+
+def run_unity (verbose, debug, compiz_args, log_file):
+ '''run the unity shell and handle Ctrl + C'''
+
+ try:
+ unity_instance = process_and_start_unity (verbose, debug, compiz_args, log_file)
+ unity_instance.wait()
+ except KeyboardInterrupt, e:
+ try:
+ os.kill(unity_instance.pid, signal.SIGKILL)
+ except:
+ pass
+ unity_instance.wait()
+ sys.exit(unity_instance.returncode)
+
+if __name__ == '__main__':
+ usage = "usage: %prog [options]"
+ parser = OptionParser(version= "%prog @UNITY_VERSION@", usage=usage)
+
+ parser.add_option("--advanced-debug", action="store_true",
+ help="Run unity under debugging to help debugging an issue. /!\ Only if devs ask for it.")
+ parser.add_option("--log", action="store",
+ help="Store log under filename.")
+ parser.add_option("--reset", action="store_true",
+ help="Reset the unity profile in compiz and restart it.")
+ parser.add_option("-v", "--verbose", action="store_true",
+ help="Get additional debug output from unity.")
+ (options, args) = parser.parse_args()
+
+ set_unity_env()
+ if options.reset:
+ reset_unity_compiz_profile ()
+
+ run_unity (options.verbose, options.advanced_debug, args, options.log)
diff --git a/unityshell.xml.in b/unityshell.xml.in
index 10348ae4f..4da8b8931 100644
--- a/unityshell.xml.in
+++ b/unityshell.xml.in
@@ -32,6 +32,7 @@
</relation>
<requirement>
<plugin>opengl</plugin>
+ <plugin>wall</plugin>
</requirement>
</deps>
<options>