summaryrefslogtreecommitdiff
path: root/src
diff options
Diffstat (limited to 'src')
-rw-r--r--src/BamfLauncherIcon.cpp224
-rw-r--r--src/BamfLauncherIcon.h8
-rw-r--r--src/FavoriteStore.h1
-rw-r--r--src/FavoriteStoreGSettings.cpp30
-rw-r--r--src/FavoriteStoreGSettings.h1
-rw-r--r--src/IndicatorObjectEntryProxy.h3
-rw-r--r--src/IndicatorObjectEntryProxyRemote.cpp5
-rw-r--r--src/IndicatorObjectFactory.h1
-rw-r--r--src/IndicatorObjectFactoryRemote.cpp81
-rw-r--r--src/IndicatorObjectFactoryRemote.h1
-rw-r--r--src/Launcher.cpp922
-rw-r--r--src/Launcher.h147
-rw-r--r--src/LauncherController.cpp133
-rw-r--r--src/LauncherController.h7
-rw-r--r--src/LauncherDragWindow.cpp117
-rw-r--r--src/LauncherDragWindow.h56
-rw-r--r--src/LauncherIcon.cpp76
-rw-r--r--src/LauncherIcon.h25
-rw-r--r--src/LauncherModel.cpp10
-rw-r--r--src/LauncherModel.h6
-rw-r--r--src/PanelHomeButton.cpp42
-rw-r--r--src/PanelIndicatorObjectEntryView.cpp12
-rw-r--r--src/PanelIndicatorObjectEntryView.h7
-rw-r--r--src/PanelIndicatorObjectView.cpp7
-rw-r--r--src/PanelIndicatorObjectView.h2
-rw-r--r--src/PanelMenuView.cpp671
-rw-r--r--src/PanelMenuView.h103
-rw-r--r--src/PanelView.cpp82
-rw-r--r--src/PanelView.h3
-rw-r--r--src/PlacesController.cpp142
-rw-r--r--src/PlacesController.h56
-rw-r--r--src/PlacesView.cpp131
-rw-r--r--src/PlacesView.h54
-rw-r--r--src/PluginAdapter.cpp171
-rw-r--r--src/PluginAdapter.h33
-rw-r--r--src/QuicklistManager.cpp109
-rw-r--r--src/QuicklistManager.h52
-rw-r--r--src/QuicklistView.cpp100
-rw-r--r--src/QuicklistView.h3
-rw-r--r--src/SimpleLauncherIcon.cpp3
-rw-r--r--src/SimpleLauncherIcon.h2
-rw-r--r--src/TrashLauncherIcon.cpp2
-rw-r--r--src/UBusMessages.h27
-rw-r--r--src/WindowButtons.cpp254
-rw-r--r--src/WindowButtons.h63
-rw-r--r--src/WindowManager.cpp171
-rw-r--r--src/WindowManager.h57
-rw-r--r--src/unityshell.cpp (renamed from src/unity.cpp)57
-rw-r--r--src/unityshell.h (renamed from src/unity.h)36
49 files changed, 3563 insertions, 743 deletions
diff --git a/src/BamfLauncherIcon.cpp b/src/BamfLauncherIcon.cpp
index 20d2b6af6..334963d3d 100644
--- a/src/BamfLauncherIcon.cpp
+++ b/src/BamfLauncherIcon.cpp
@@ -83,6 +83,11 @@ BamfLauncherIcon::BamfLauncherIcon (Launcher* IconManager, BamfApplication *app,
EnsureWindowState ();
UpdateMenus ();
+
+ PluginAdapter::Default ()->window_minimized.connect (sigc::mem_fun (this, &BamfLauncherIcon::OnWindowMinimized));
+
+ /* hack */
+ SetProgress (0.5f);
}
BamfLauncherIcon::~BamfLauncherIcon()
@@ -99,34 +104,56 @@ BamfLauncherIcon::~BamfLauncherIcon()
}
void
+BamfLauncherIcon::OnWindowMinimized (CompWindow *window)
+{
+ if (!OwnsWindow (window->id ()))
+ return;
+
+ Present (0.5f, 600);
+ UpdateQuirkTimeDelayed (300, LAUNCHER_ICON_QUIRK_SHIMMER);
+}
+
+bool
+BamfLauncherIcon::IsSticky ()
+{
+ return bamf_view_is_sticky (BAMF_VIEW (m_App));
+}
+
+const char*
+BamfLauncherIcon::DesktopFile ()
+{
+ return bamf_application_get_desktop_file (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)
+BamfLauncherIcon::OwnsWindow (Window w)
{
GList *children, *l;
BamfView *view;
@@ -145,7 +172,7 @@ BamfLauncherIcon::IconOwnsWindow (Window w)
if (xid == w)
{
owns = true;
- break;
+ break;
}
}
}
@@ -178,6 +205,8 @@ BamfLauncherIcon::Focus ()
{
GList *children, *l;
BamfView *view;
+ bool any_urgent = false;
+ bool any_on_current = false;
children = bamf_view_get_children (BAMF_VIEW (m_App));
@@ -195,12 +224,20 @@ BamfLauncherIcon::Focus ()
CompWindow *window = m_Screen->findWindow ((Window) xid);
if (window)
+ {
+ if (bamf_view_is_urgent (view))
+ any_urgent = true;
windows.push_back (window);
+ }
}
}
+ // not a good sign
if (windows.empty ())
+ {
+ g_list_free (children);
return;
+ }
/* sort the list */
CompWindowList tmp;
@@ -212,10 +249,7 @@ BamfLauncherIcon::Focus ()
}
windows = tmp;
-
/* filter based on workspace */
- bool any_on_current = false;
-
for (it = windows.begin (); it != windows.end (); it++)
{
if ((*it)->defaultViewport () == m_Screen->vp ())
@@ -225,9 +259,36 @@ BamfLauncherIcon::Focus ()
}
}
- /* activate our windows */
+ if (any_urgent)
+ {
+ // we cant use the compiz tracking since it is currently broken
+ /*for (it = windows.begin (); it != windows.end (); it++)
+ {
+ if ((*it)->state () & CompWindowStateDemandsAttentionMask)
+ {
+ (*it)->activate ();
+ break;
+ }
+ }*/
+ for (l = children; l; l = l->next)
+ {
+ 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 (any_on_current)
+ if (window && bamf_view_is_urgent (view))
+ {
+ window->activate ();
+ break;
+ }
+ }
+ }
+ }
+ else if (any_on_current)
{
for (it = windows.begin (); it != windows.end (); it++)
{
@@ -278,6 +339,10 @@ BamfLauncherIcon::Spread ()
void
BamfLauncherIcon::OnMouseClick (int button)
{
+ bool scaleWasActive = PluginAdapter::Default ()->IsScaleActive();
+
+ SimpleLauncherIcon::OnMouseClick (button);
+
if (button != 1)
return;
@@ -287,11 +352,17 @@ BamfLauncherIcon::OnMouseClick (int button)
running = bamf_view_is_running (BAMF_VIEW (m_App));
if (!running)
+ {
+ if (GetQuirk (LAUNCHER_ICON_QUIRK_STARTING))
+ return;
+ SetQuirk (LAUNCHER_ICON_QUIRK_STARTING, true);
OpenInstance ();
- else if (active)
- Spread ();
- else
+ return;
+ }
+ else if (!active)
Focus ();
+ else if (!scaleWasActive)
+ Spread ();
}
void
@@ -400,44 +471,68 @@ BamfLauncherIcon::UpdateMenus ()
// make a client for desktop file actions
if (!DBUSMENU_IS_MENUITEM (_menu_desktop_shortcuts) &&
- bamf_application_get_desktop_file (m_App) != NULL)
+ g_strcmp0 (DesktopFile (), """"))
{
+ GKeyFile *keyfile;
+ GError *error = 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);
- }
+ // check that we have the X-Ayatana-Desktop-Shortcuts flag
+ // not sure if we should do this or if libindicator should shut up
+ // and not report errors when it can't find the key.
+ // so FIXME when ted is around
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_file (keyfile, DesktopFile (), G_KEY_FILE_NONE, &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Could not load desktop file for: %s" , DesktopFile ());
+ g_error_free (error);
+ return;
}
- _menu_desktop_shortcuts = root;
+ if (g_key_file_has_key (keyfile, G_KEY_FILE_DESKTOP_GROUP,
+ "X-Ayatana-Desktop-Shortcuts", 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;
+ g_key_file_free (keyfile);
+
+ }
}
}
@@ -596,11 +691,34 @@ BamfLauncherIcon::GetMenus ()
EnsureMenuItemsReady ();
- result.push_back (_menu_items["Launch"]);
- result.push_back (_menu_items["Pin"]);
+ std::map<std::string, DbusmenuMenuitem *>::iterator it_m;
+ std::list<DbusmenuMenuitem *>::iterator it_l;
+ bool exists;
+ for (it_m = _menu_items.begin (); it_m != _menu_items.end (); it_m++)
+ {
+ const char* key = ((*it_m).first).c_str();
+ if (g_strcmp0 (key , "Quit") == 0 && !bamf_view_is_running (BAMF_VIEW (m_App)))
+ continue;
+
+ exists = false;
+ std::string label_default = dbusmenu_menuitem_property_get ((*it_m).second, DBUSMENU_MENUITEM_PROP_LABEL);
+ for(it_l = result.begin(); it_l != result.end(); it_l++)
+ {
+ const gchar* type = dbusmenu_menuitem_property_get (*it_l, DBUSMENU_MENUITEM_PROP_TYPE);
+ if (type == NULL)//(g_strcmp0 (type, DBUSMENU_MENUITEM_PROP_LABEL) == 0)
+ {
+ std::string label_menu = dbusmenu_menuitem_property_get (*it_l, DBUSMENU_MENUITEM_PROP_LABEL);
+ if (label_menu.compare(label_default) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+ }
- if (bamf_view_is_running (BAMF_VIEW (m_App)))
- result.push_back (_menu_items["Quit"]);
+ if (!exists)
+ result.push_back((*it_m).second);
+ }
return result;
}
diff --git a/src/BamfLauncherIcon.h b/src/BamfLauncherIcon.h
index 0dd30847e..488ab4740 100644
--- a/src/BamfLauncherIcon.h
+++ b/src/BamfLauncherIcon.h
@@ -36,8 +36,10 @@ class BamfLauncherIcon : public SimpleLauncherIcon
{
public:
BamfLauncherIcon(Launcher* IconManager, BamfApplication *app, CompScreen *screen);
- ~BamfLauncherIcon();
+ virtual ~BamfLauncherIcon();
+ const char* DesktopFile ();
+ bool IsSticky ();
protected:
void OnMouseClick (int button);
@@ -46,7 +48,6 @@ protected:
void UpdateIconGeometries (nux::Point3 center);
void OnCenterStabilized (nux::Point3 center);
- bool IconOwnsWindow (Window w);
void AddProperties (GVariantBuilder *builder);
@@ -66,6 +67,9 @@ private:
void Spread ();
void EnsureMenuItemsReady ();
+
+ void OnWindowMinimized (CompWindow *window);
+ bool OwnsWindow (Window w);
static void OnClosed (BamfView *view, gpointer data);
static void OnUserVisibleChanged (BamfView *view, gboolean visible, gpointer data);
diff --git a/src/FavoriteStore.h b/src/FavoriteStore.h
index b67fda7b1..de8b13659 100644
--- a/src/FavoriteStore.h
+++ b/src/FavoriteStore.h
@@ -54,6 +54,7 @@ public:
virtual void AddFavorite (const char *desktop_path, gint position) = 0;
virtual void RemoveFavorite (const char *desktop_path) = 0;
virtual void MoveFavorite (const char *desktop_path, gint position) = 0;
+ virtual void SetFavorites (std::list<const char*> desktop_paths) = 0;
// Signals
// Therse only emit if something has changed the GSettings object externally
diff --git a/src/FavoriteStoreGSettings.cpp b/src/FavoriteStoreGSettings.cpp
index 9c09cb3a8..6ba2c32d0 100644
--- a/src/FavoriteStoreGSettings.cpp
+++ b/src/FavoriteStoreGSettings.cpp
@@ -323,6 +323,36 @@ FavoriteStoreGSettings::MoveFavorite (const char *desktop_path,
Refresh ();
}
+void
+FavoriteStoreGSettings::SetFavorites (std::list<const char *> desktop_paths)
+{
+ char *favs[desktop_paths.size () + 1];
+ favs[desktop_paths.size ()] = NULL;
+
+ int i = 0;
+ std::list<const char*>::iterator it;
+ for (it = desktop_paths.begin (); it != desktop_paths.end (); it++)
+ {
+ favs[i] = get_basename_or_path (*it);
+ i++;
+ }
+
+ m_ignore_signals = true;
+ if (!g_settings_set_strv (m_settings, "favorites", favs))
+ g_warning ("Unable to set favorites from list");
+ m_ignore_signals = false;
+
+ i = 0;
+ while (favs[i] != NULL)
+ {
+ g_free (favs[i]);
+ favs[i] = NULL;
+ i++;
+ }
+
+ Refresh ();
+}
+
void
FavoriteStoreGSettings::Changed (const gchar *key)
{
diff --git a/src/FavoriteStoreGSettings.h b/src/FavoriteStoreGSettings.h
index dbc2f9e3a..f88fd0b1e 100644
--- a/src/FavoriteStoreGSettings.h
+++ b/src/FavoriteStoreGSettings.h
@@ -39,6 +39,7 @@ public:
void AddFavorite (const char *desktop_path, gint position);
void RemoveFavorite (const char *desktop_path);
void MoveFavorite (const char *desktop_path, gint position);
+ void SetFavorites (std::list<const char *> desktop_paths);
void Changed (const char *key);
diff --git a/src/IndicatorObjectEntryProxy.h b/src/IndicatorObjectEntryProxy.h
index c8dff0e12..5ec831506 100644
--- a/src/IndicatorObjectEntryProxy.h
+++ b/src/IndicatorObjectEntryProxy.h
@@ -36,7 +36,8 @@ public:
virtual void ShowMenu (int x, int y, guint32 timestamp, guint32 button) = 0;
// Signals
- sigc::signal<void> Updated;
+ sigc::signal<void> updated;
+ sigc::signal<void, bool> active_changed;
public:
bool label_visible;
diff --git a/src/IndicatorObjectEntryProxyRemote.cpp b/src/IndicatorObjectEntryProxyRemote.cpp
index 87339c17d..56c30a261 100644
--- a/src/IndicatorObjectEntryProxyRemote.cpp
+++ b/src/IndicatorObjectEntryProxyRemote.cpp
@@ -104,7 +104,8 @@ IndicatorObjectEntryProxyRemote::SetActive (bool active)
_active = active;
- Updated.emit ();
+ active_changed.emit (active);
+ updated.emit ();
}
bool
@@ -141,7 +142,7 @@ IndicatorObjectEntryProxyRemote::Refresh (const char *__id,
icon_sensitive = __image_sensitive;
icon_visible = __image_visible;
- Updated.emit ();
+ updated.emit ();
}
const char *
diff --git a/src/IndicatorObjectFactory.h b/src/IndicatorObjectFactory.h
index c267a5b2e..a6f2755ef 100644
--- a/src/IndicatorObjectFactory.h
+++ b/src/IndicatorObjectFactory.h
@@ -45,6 +45,7 @@ public:
sigc::signal<void, IndicatorObjectProxy *> OnObjectRemoved;
sigc::signal<void, int, int> OnMenuPointerMoved;
sigc::signal<void, const char *> OnEntryActivateRequest;
+ sigc::signal<void, const char *> OnEntryActivated;
protected:
std::vector<IndicatorObjectProxy *>_indicators;
diff --git a/src/IndicatorObjectFactoryRemote.cpp b/src/IndicatorObjectFactoryRemote.cpp
index b45efc13e..4257fabcd 100644
--- a/src/IndicatorObjectFactoryRemote.cpp
+++ b/src/IndicatorObjectFactoryRemote.cpp
@@ -56,6 +56,10 @@ static void on_proxy_signal_received (GDBusProxy *proxy,
GVariant *parameters,
IndicatorObjectFactoryRemote *remote);
+static void on_proxy_name_owner_changed (GDBusProxy *proxy,
+ GParamSpec *pspec,
+ IndicatorObjectFactoryRemote *remote);
+
static void on_sync_ready_cb (GObject *source,
GAsyncResult *res,
gpointer data);
@@ -65,25 +69,9 @@ static bool reconnect_to_service (gpointer data);
// Public Methods
IndicatorObjectFactoryRemote::IndicatorObjectFactoryRemote ()
+: _proxy (NULL)
{
- if (g_getenv ("PANEL_USE_LOCAL_SERVICE"))
- {
- run_local_panel_service ();
- g_timeout_add_seconds (1, (GSourceFunc)reconnect_to_service, this);
- }
- else
- {
- // We want to grab the Panel Service object. This is async, which is fine
- g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
- NULL,
- S_NAME,
- S_PATH,
- S_IFACE,
- NULL,
- on_proxy_ready_cb,
- this);
- }
+ Reconnect ();
}
IndicatorObjectFactoryRemote::~IndicatorObjectFactoryRemote ()
@@ -115,14 +103,39 @@ IndicatorObjectFactoryRemote::ForceRefresh ()
}
void
+IndicatorObjectFactoryRemote::Reconnect ()
+{
+ if (g_getenv ("PANEL_USE_LOCAL_SERVICE"))
+ {
+ run_local_panel_service ();
+ g_timeout_add_seconds (1, (GSourceFunc)reconnect_to_service, this);
+ }
+ else
+ {
+ // We want to grab the Panel Service object. This is async, which is fine
+ reconnect_to_service (this);
+ }
+}
+
+void
IndicatorObjectFactoryRemote::OnRemoteProxyReady (GDBusProxy *proxy)
{
- _proxy = proxy;
+ if (_proxy)
+ {
+ // We've been connected before; We don't need new proxy, just continue
+ // rocking with the old one.
+ g_object_unref (proxy);
+ }
+ else
+ {
+ _proxy = proxy;
- // Connect to interesting signals
- // FIXME: Add auto-restarting bits here
- g_signal_connect (_proxy, "g-signal",
- G_CALLBACK (on_proxy_signal_received), this);
+ // Connect to interesting signals
+ g_signal_connect (_proxy, "g-signal",
+ G_CALLBACK (on_proxy_signal_received), this);
+ g_signal_connect (_proxy, "notify::g-name-owner",
+ G_CALLBACK (on_proxy_name_owner_changed), this);
+ }
g_dbus_proxy_call (_proxy,
"Sync",
@@ -227,7 +240,9 @@ IndicatorObjectFactoryRemote::OnEntryActivated (const char *entry_id)
entry->SetActive (g_strcmp0 (entry_id, entry->GetId ()) == 0);
}
- }
+ }
+
+ IndicatorObjectFactory::OnEntryActivated.emit (entry_id);
}
void
@@ -471,6 +486,24 @@ on_proxy_signal_received (GDBusProxy *proxy,
}
static void
+on_proxy_name_owner_changed (GDBusProxy *proxy,
+ GParamSpec *pspec,
+ IndicatorObjectFactoryRemote *remote)
+{
+ char *name_owner;
+
+ name_owner = g_dbus_proxy_get_name_owner (proxy);
+
+ if (name_owner == NULL)
+ {
+ // The panel service has stopped for some reason. Restart it.
+ remote->Reconnect ();
+ }
+
+ g_free (name_owner);
+}
+
+static void
on_sync_ready_cb (GObject *source,
GAsyncResult *res,
gpointer data)
diff --git a/src/IndicatorObjectFactoryRemote.h b/src/IndicatorObjectFactoryRemote.h
index f32bc3fe5..5f9b00611 100644
--- a/src/IndicatorObjectFactoryRemote.h
+++ b/src/IndicatorObjectFactoryRemote.h
@@ -43,6 +43,7 @@ public:
void OnShowMenuRequestReceived (const char *id, int x, int y, guint timestamp, guint32 button);
void Sync (GVariant *args);
void OnEntryActivateRequestReceived (const char *entry_id);
+ void Reconnect ();
void AddProperties (GVariantBuilder *builder);
diff --git a/src/Launcher.cpp b/src/Launcher.cpp
index e0058c602..6d8e3fe5a 100644
--- a/src/Launcher.cpp
+++ b/src/Launcher.cpp
@@ -35,6 +35,7 @@
#include "Launcher.h"
#include "LauncherIcon.h"
#include "LauncherModel.h"
+#include "QuicklistManager.h"
#include "QuicklistView.h"
#define ANIM_DURATION_SHORT 125
@@ -182,13 +183,26 @@ Launcher::Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_DE
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));
+ 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));
+
+ QuicklistManager::Default ()->quicklist_opened.connect (sigc::mem_fun(this, &Launcher::RecvQuicklistOpened));
+ QuicklistManager::Default ()->quicklist_closed.connect (sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
+
+ PluginAdapter::Default ()->window_maximized.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_restored.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_unminimized.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_mapped.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_unmapped.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_shown.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_hidden.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_resized.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
+ PluginAdapter::Default ()->window_moved.connect (sigc::mem_fun (this, &Launcher::OnWindowMaybeIntellihide));
m_ActiveTooltipIcon = NULL;
m_ActiveMenuIcon = NULL;
@@ -230,6 +244,7 @@ Launcher::Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_DE
_launcher_action_state = ACTION_NONE;
_icon_under_mouse = NULL;
_icon_mouse_down = NULL;
+ _drag_icon = NULL;
_icon_image_size = 48;
_icon_glow_size = 62;
_icon_image_size_delta = 6;
@@ -239,14 +254,14 @@ Launcher::Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_DE
_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");
+ _progress_bar_trough = nux::CreateTextureFromFile (PKGDATADIR"/progress_bar_trough.png");
+ _progress_bar_fill = nux::CreateTextureFromFile (PKGDATADIR"/progress_bar_fill.png");
_enter_y = 0;
_dnd_security = 15;
- _dnd_delta = 0;
- _anim_handle = 0;
+ _launcher_drag_delta = 0;
+ _dnd_delta_y = 0;
+ _dnd_delta_x = 0;
_autohide_handle = 0;
_floating = false;
_hovered = false;
@@ -255,6 +270,7 @@ Launcher::Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_DE
_mouse_inside_launcher = false;
_mouse_inside_trigger = false;
_window_over_launcher = false;
+ _render_drag_window = false;
// 0 out timers to avoid wonky startups
_enter_time.tv_sec = 0;
@@ -263,8 +279,16 @@ Launcher::Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_DE
_exit_time.tv_nsec = 0;
_drag_end_time.tv_sec = 0;
_drag_end_time.tv_nsec = 0;
+ _drag_start_time.tv_sec = 0;
+ _drag_start_time.tv_nsec = 0;
+ _drag_threshold_time.tv_sec = 0;
+ _drag_threshold_time.tv_nsec = 0;
_autohide_time.tv_sec = 0;
_autohide_time.tv_nsec = 0;
+
+ _drag_window = NULL;
+ _offscreen_drag_texture = nux::GetThreadGLDeviceFactory()->CreateSystemCapableDeviceTexture (2, 2, 1, nux::BITFMT_R8G8B8A8);
+ _offscreen_progress_texture = nux::GetThreadGLDeviceFactory()->CreateSystemCapableDeviceTexture (2, 2, 1, nux::BITFMT_R8G8B8A8);
}
Launcher::~Launcher()
@@ -289,7 +313,7 @@ Launcher::AddProperties (GVariantBuilder *builder)
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}", "dnd-delta", g_variant_new_int32 (_dnd_delta_y));
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));
@@ -298,8 +322,23 @@ Launcher::AddProperties (GVariantBuilder *builder)
g_variant_builder_add (builder, "{sv}", "mouse-inside-launcher", g_variant_new_boolean (_mouse_inside_launcher));
}
-/* Render Layout Logic */
+void Launcher::SetMousePosition (int x, int y)
+{
+ bool beyond_drag_threshold = MouseBeyondDragThreshold ();
+ _mouse_position = nux::Point2 (x, y);
+
+ if (beyond_drag_threshold != MouseBeyondDragThreshold ())
+ SetTimeStruct (&_drag_threshold_time, &_drag_threshold_time, ANIM_DURATION_SHORT);
+}
+bool Launcher::MouseBeyondDragThreshold ()
+{
+ if (_launcher_action_state != ACTION_DRAG_ICON)
+ return false;
+ return _mouse_position.x > GetGeometry ().width + _icon_size / 2;
+}
+
+/* Render Layout Logic */
float Launcher::GetHoverProgress (struct timespec const &current)
{
if (_hovered)
@@ -313,6 +352,11 @@ 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::DnDStartProgress (struct timespec const &current)
+{
+ return CLAMP ((float) (TimeDelta (&current, &_drag_start_time)) / (float) ANIM_DURATION, 0.0f, 1.0f);
+}
+
float Launcher::AutohideProgress (struct timespec const &current)
{
if (!_autohide)
@@ -324,29 +368,24 @@ float Launcher::AutohideProgress (struct timespec const &current)
return 1.0f - CLAMP ((float) (TimeDelta (&current, &_autohide_time)) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
}
+float Launcher::DragThresholdProgress (struct timespec const &current)
+{
+ if (MouseBeyondDragThreshold ())
+ return 1.0f - CLAMP ((float) (TimeDelta (&current, &_drag_threshold_time)) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
+ else
+ return CLAMP ((float) (TimeDelta (&current, &_drag_threshold_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)
@@ -375,6 +414,14 @@ bool Launcher::IconNeedsAnimation (LauncherIcon *icon, struct timespec const &cu
if (TimeDelta (&current, &time) < ANIM_DURATION_LONG)
return true;
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_CENTER_SAVED);
+ if (TimeDelta (&current, &time) < ANIM_DURATION)
+ return true;
+
+ time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PROGRESS);
+ if (TimeDelta (&current, &time) < ANIM_DURATION)
+ return true;
+
return false;
}
@@ -394,13 +441,20 @@ bool Launcher::AnimationInProgress ()
// hover out animation
if (TimeDelta (&current, &_exit_time) < ANIM_DURATION)
return true;
-
+
+ // drag start animation
+ if (TimeDelta (&current, &_drag_start_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;
+
+ if (TimeDelta (&current, &_drag_threshold_time) < ANIM_DURATION_SHORT)
+ return true;
// animations happening on specific icons
LauncherModel::iterator it;
@@ -469,10 +523,10 @@ void Launcher::SetDndDelta (float x, float y, nux::Geometry geo, struct timespec
if (*it == anchor)
{
position += _icon_size / 2;
- _dnd_delta = _enter_y - position;
+ _launcher_drag_delta = _enter_y - position;
- if (position + _icon_size / 2 + _dnd_delta > geo.height)
- _dnd_delta -= (position + _icon_size / 2 + _dnd_delta) - geo.height;
+ if (position + _icon_size / 2 + _launcher_drag_delta > geo.height)
+ _launcher_drag_delta -= (position + _icon_size / 2 + _launcher_drag_delta) - geo.height;
break;
}
@@ -512,6 +566,13 @@ float Launcher::IconShimmerProgress (LauncherIcon *icon, struct timespec const &
return CLAMP ((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f);
}
+float Launcher::IconCenterTransitionProgress (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec save_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_CENTER_SAVED);
+ int save_ms = TimeDelta (&current, &save_time);
+ return CLAMP ((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f);
+}
+
float Launcher::IconUrgentPulseValue (LauncherIcon *icon, struct timespec const &current)
{
if (!icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
@@ -527,6 +588,12 @@ float Launcher::IconStartingPulseValue (LauncherIcon *icon, struct timespec cons
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);
+ if (starting_progress == 1.0f && !icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
+ {
+ icon->SetQuirk (LAUNCHER_ICON_QUIRK_STARTING, false);
+ icon->ResetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
+ }
+
return 1.0f - (0.5f + (float) (std::cos (M_PI * (float) (MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
}
@@ -538,8 +605,11 @@ float Launcher::IconBackgroundIntensity (LauncherIcon *icon, struct timespec con
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);
+ if (running_progress == 1.0f && icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
+ {
+ icon->SetQuirk (LAUNCHER_ICON_QUIRK_STARTING, false);
+ icon->ResetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
+ }
result = IconStartingPulseValue (icon, current) * BACKLIGHT_STRENGTH;
@@ -561,6 +631,18 @@ float Launcher::IconBackgroundIntensity (LauncherIcon *icon, struct timespec con
return result;
}
+float Launcher::IconProgressBias (LauncherIcon *icon, struct timespec const &current)
+{
+ struct timespec icon_progress_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PROGRESS);
+ int ms = TimeDelta (&current, &icon_progress_time);
+ float result = CLAMP ((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
+
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_PROGRESS))
+ return -1.0f + result;
+ else
+ return result;
+}
+
void Launcher::SetupRenderArg (LauncherIcon *icon, struct timespec const &current, RenderArg &arg)
{
arg.icon = icon;
@@ -569,9 +651,13 @@ void Launcher::SetupRenderArg (LauncherIcon *icon, struct timespec const &curren
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.x_rotation = 0.0f;
+ arg.y_rotation = 0.0f;
+ arg.z_rotation = 0.0f;
arg.skip = false;
-
+ arg.stick_thingy = false;
+ arg.progress_bias = IconProgressBias (icon, current);
+ arg.progress = CLAMP (icon->GetProgress (), 0.0f, 1.0f);
// we dont need to show strays
if (!icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
@@ -583,10 +669,88 @@ void Launcher::SetupRenderArg (LauncherIcon *icon, struct timespec const &curren
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
+
+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
+ urgent_progress = CLAMP (urgent_progress * 3.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
+ else
+ urgent_progress = CLAMP (urgent_progress * 3.0f - 2.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
arg.glow_intensity = urgent_progress;
}
+void Launcher::FillRenderArg (LauncherIcon *icon,
+ RenderArg &arg,
+ nux::Point3 &center,
+ float folding_threshold,
+ float folded_size,
+ float folded_spacing,
+ float autohide_offset,
+ float folded_z_distance,
+ float animation_neg_rads,
+ struct timespec const &current)
+{
+ 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 (icon == _drag_icon)
+ {
+ if (MouseBeyondDragThreshold ())
+ arg.stick_thingy = true;
+
+ if (_launcher_action_state == ACTION_DRAG_ICON || (_drag_window && _drag_window->Animating ()))
+ arg.skip = true;
+ size_modifier *= DragThresholdProgress (current);
+ }
+
+ if (size_modifier <= 0.0f)
+ arg.skip = true;
+
+ // 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.x_rotation = animation_neg_rads * folding_progress;
+
+ float spacing_overlap = CLAMP ((float) (center.y + (2.0f * half_size * size_modifier) + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
+ float spacing = (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier;
+
+ nux::Point3 centerOffset;
+ float center_transit_progress = IconCenterTransitionProgress (icon, current);
+ if (center_transit_progress <= 1.0f)
+ {
+ centerOffset.y = (icon->_saved_center.y - (center.y + (half_size * size_modifier))) * (1.0f - center_transit_progress);
+ }
+
+ center.y += half_size * size_modifier; // move to center
+
+ arg.render_center = nux::Point3 (roundf (center.x + icon_hide_offset), roundf (center.y + centerOffset.y), roundf (center.z));
+ arg.logical_center = nux::Point3 (roundf (center.x + icon_hide_offset), roundf (center.y), roundf (center.z));
+
+ icon->SetCenter (nux::Point3 (roundf (center.x), roundf (center.y), roundf (center.z)));
+
+ if (icon == _drag_icon && _drag_window && _drag_window->Animating ())
+ _drag_window->SetAnimationTarget ((int) center.x, (int) center.y + _parent->GetGeometry ().y);
+
+ center.y += (half_size * size_modifier) + spacing; // move to end
+}
+
float Launcher::DragLimiter (float x)
{
float result = (1 - std::pow (159.0 / 160, std::abs (x))) * 160;
@@ -608,7 +772,6 @@ void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
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);
@@ -643,31 +806,31 @@ void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
_enter_y = 0;
- if (hover_progress > 0.0f && _dnd_delta != 0)
+ if (hover_progress > 0.0f && _launcher_drag_delta != 0)
{
- float delta_y = _dnd_delta;
+ float delta_y = _launcher_drag_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)
+ if (_launcher_drag_delta > max)
delta_y = max + DragLimiter (delta_y - max);
- else if (_dnd_delta < min)
+ else if (_launcher_drag_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)
+ if (_launcher_drag_delta > max)
delta_y = max + (delta_y - max) * dnd_progress;
- else if (_dnd_delta < min)
+ else if (_launcher_drag_delta < min)
delta_y = min + (delta_y - min) * dnd_progress;
if (dnd_progress == 0.0f)
- _dnd_delta = (int) delta_y;
+ _launcher_drag_delta = (int) delta_y;
}
delta_y *= hover_progress;
@@ -676,7 +839,7 @@ void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
}
else
{
- _dnd_delta = 0;
+ _launcher_drag_delta = 0;
}
float autohide_progress = AutohideProgress (current);
@@ -702,48 +865,8 @@ void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
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;
+ FillRenderArg (icon, arg, center, folding_threshold, folded_size, folded_spacing,
+ autohide_offset, folded_z_distance, animation_neg_rads, current);
launcher_args.push_back (arg);
}
@@ -768,50 +891,10 @@ void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
{
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;
-
+
+ FillRenderArg (icon, arg, center, folding_threshold, folded_size, folded_spacing,
+ autohide_offset, folded_z_distance, animation_neg_rads, current);
+
launcher_args.push_back (arg);
}
}
@@ -843,7 +926,11 @@ gboolean Launcher::OnAutohideTimeout (gpointer data)
void
Launcher::EnsureHiddenState ()
{
- if (!_mouse_inside_trigger && !_mouse_inside_launcher && _window_over_launcher)
+ if (!_mouse_inside_trigger &&
+ !_mouse_inside_launcher &&
+ _launcher_action_state == ACTION_NONE &&
+ !QuicklistManager::Default ()->Current() &&
+ _window_over_launcher)
SetHidden (true);
else
SetHidden (false);
@@ -860,7 +947,7 @@ Launcher::CheckWindowOverLauncher ()
{
CompWindow *window = *it;
- if (window->type () != CompWindowTypeNormalMask || window->invisible ())
+ if (window->type () != CompWindowTypeNormalMask || !window->isMapped () || !window->isViewable ())
continue;
if (CompRegion (window->inputRect ()).intersects (CompRect (geo.x, geo.y, geo.width, geo.height)))
@@ -876,27 +963,7 @@ Launcher::CheckWindowOverLauncher ()
}
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)
+Launcher::OnWindowMaybeIntellihide (CompWindow *window)
{
if (_autohide)
CheckWindowOverLauncher ();
@@ -970,6 +1037,19 @@ void Launcher::SetFloating (bool floating)
EnsureAnimation ();
}
+void
+Launcher::EnsureHoverState ()
+{
+ if (_mouse_inside_launcher || QuicklistManager::Default ()->Current() || _launcher_action_state != ACTION_NONE)
+ {
+ SetHover ();
+ }
+ else
+ {
+ UnsetHover ();
+ }
+}
+
void Launcher::SetHover ()
{
if (_hovered)
@@ -1004,17 +1084,16 @@ void Launcher::SetIconSize(int tile_size, int icon_size)
_parent->SetGeometry (nux::Geometry (geo.x, geo.y, tile_size + 12, geo.height));
}
-void Launcher::OnIconAdded (void *icon_pointer)
+void Launcher::OnIconAdded (LauncherIcon *icon)
{
- 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];
+ 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));
@@ -1022,13 +1101,10 @@ void Launcher::OnIconAdded (void *icon_pointer)
AddChild (icon);
}
-void Launcher::OnIconRemoved (void *icon_pointer)
+void Launcher::OnIconRemoved (LauncherIcon *icon)
{
- LauncherIcon *icon = (LauncherIcon *) icon_pointer;
icon->UnReference ();
-
EnsureAnimation();
-
RemoveChild (icon);
}
@@ -1045,7 +1121,7 @@ void Launcher::SetModel (LauncherModel *model)
_model->order_changed.connect (sigc::mem_fun (this, &Launcher::OnOrderChanged));
}
-void Launcher::OnIconNeedsRedraw (void *icon)
+void Launcher::OnIconNeedsRedraw (LauncherIcon *icon)
{
EnsureAnimation();
}
@@ -1068,7 +1144,7 @@ void Launcher::RenderIndicators (nux::GraphicsEngine& GfxContext,
int active,
nux::Geometry geo)
{
- int markerCenter = (int) arg.center.y;
+ int markerCenter = (int) arg.render_center.y;
if (running > 0)
{
@@ -1139,13 +1215,12 @@ void Launcher::RenderIndicators (nux::GraphicsEngine& GfxContext,
void Launcher::RenderIcon(nux::GraphicsEngine& GfxContext,
RenderArg const &arg,
- nux::BaseTexture *icon,
+ nux::IntrusiveSP<nux::IOpenGLBaseTexture> icon,
nux::Color bkg_color,
float alpha,
- nux::Vector4 xform_coords[],
- nux::Geometry geo)
+ nux::Vector4 xform_coords[])
{
- if (icon == NULL || icon->IsNull ())
+ if (icon == NULL)
return;
nux::Matrix4 ObjectMatrix;
@@ -1153,10 +1228,10 @@ void Launcher::RenderIcon(nux::GraphicsEngine& GfxContext,
nux::Matrix4 ProjectionMatrix;
nux::Matrix4 ViewProjectionMatrix;
- if(nux::Abs (arg.folding_rads) < 0.01f)
- icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
+ if(nux::Abs (arg.x_rotation) < 0.01f)
+ icon->SetFiltering(GL_NEAREST, GL_NEAREST);
else
- icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
+ icon->SetFiltering(GL_LINEAR, GL_LINEAR);
nux::Vector4 v0;
nux::Vector4 v1;
@@ -1183,7 +1258,7 @@ void Launcher::RenderIcon(nux::GraphicsEngine& GfxContext,
float s0, t0, s1, t1, s2, t2, s3, t3;
nux::Color color = nux::Color::White;
- if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
+ if (icon->GetResourceType () == nux::RTTEXTURERECTANGLE)
{
s0 = 0.0f; t0 = 0.0f;
s1 = 0.0f; t1 = icon->GetHeight();
@@ -1305,27 +1380,27 @@ void Launcher::DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg const &
GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
+ /* draw tile */
if (arg.backlight_intensity < 1.0f)
{
RenderIcon(GfxContext,
arg,
- _icon_outline_texture,
+ _icon_outline_texture->GetDeviceTexture (),
nux::Color(0xAAFFFFFF),
1.0f - arg.backlight_intensity,
- arg.icon->_xform_coords["Tile"],
- geo);
+ arg.icon->_xform_coords["Tile"]);
}
if (arg.backlight_intensity > 0.0f)
{
RenderIcon(GfxContext,
arg,
- _icon_bkg_texture,
+ _icon_bkg_texture->GetDeviceTexture (),
arg.icon->BackgroundColor (),
arg.backlight_intensity,
- arg.icon->_xform_coords["Tile"],
- geo);
+ arg.icon->_xform_coords["Tile"]);
}
+ /* end tile draw */
GfxContext.GetRenderStates ().SetSeparateBlend (true,
GL_SRC_ALPHA,
@@ -1334,70 +1409,37 @@ void Launcher::DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg const &
GL_ONE);
GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
+ /* draw icon */
RenderIcon (GfxContext,
arg,
- arg.icon->TextureForSize (_icon_image_size),
+ arg.icon->TextureForSize (_icon_image_size)->GetDeviceTexture (),
nux::Color::White,
arg.alpha,
- arg.icon->_xform_coords["Image"],
- geo);
+ arg.icon->_xform_coords["Image"]);
+ /* draw overlay shine */
if (arg.backlight_intensity > 0.0f)
{
RenderIcon(GfxContext,
arg,
- _icon_shine_texture,
+ _icon_shine_texture->GetDeviceTexture (),
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;
- }
+ arg.icon->_xform_coords["Tile"]);
}
+ /* draw glow */
if (arg.glow_intensity > 0.0f)
{
RenderIcon(GfxContext,
arg,
- _icon_glow_texture,
+ _icon_glow_texture->GetDeviceTexture (),
arg.icon->GlowColor (),
arg.glow_intensity,
- arg.icon->_xform_coords["Glow"],
- geo);
+ arg.icon->_xform_coords["Glow"]);
}
-
+
+ /* draw shimmer */
if (arg.shimmer_progress > 0.0f && arg.shimmer_progress < 1.0f)
{
nux::Geometry base = GetGeometry ();
@@ -1412,15 +1454,30 @@ void Launcher::DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg const &
RenderIcon(GfxContext,
arg,
- _icon_glow_texture,
+ _icon_glow_texture->GetDeviceTexture (),
arg.icon->GlowColor (),
fade_out,
- arg.icon->_xform_coords["Glow"],
- geo);
+ arg.icon->_xform_coords["Glow"]);
GfxContext.PopClippingRectangle();
}
+
+ /* draw progress bar */
+ if (arg.progress_bias > -1.0f && arg.progress_bias < 1.0f)
+ {
+ if (_offscreen_progress_texture->GetWidth () != _icon_size || _offscreen_progress_texture->GetHeight () != _icon_size)
+ _offscreen_progress_texture = nux::GetThreadGLDeviceFactory()->CreateSystemCapableDeviceTexture (_icon_size, _icon_size, 1, nux::BITFMT_R8G8B8A8);
+ RenderProgressToTexture (GfxContext, _offscreen_progress_texture, arg.progress, arg.progress_bias);
+
+ RenderIcon(GfxContext,
+ arg,
+ _offscreen_progress_texture,
+ nux::Color::White,
+ 1.0f,
+ arg.icon->_xform_coords["Tile"]);
+ }
+ /* draw indicators */
RenderIndicators (GfxContext,
arg,
arg.running_arrow ? arg.window_indicators : 0,
@@ -1431,12 +1488,15 @@ void Launcher::DrawRenderArg (nux::GraphicsEngine& GfxContext, RenderArg const &
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;
+ // rely on the compiz event loop to come back to us in a nice throttling
+ if (AnimationInProgress ())
+ g_timeout_add (0, &Launcher::AnimationTimeout, this);
+
nux::ROPConfig ROP;
ROP.Blend = false;
ROP.SrcBlend = GL_SRC_ALPHA;
@@ -1444,7 +1504,18 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
RenderArgs (args, bkg_box);
+ if (_drag_icon && _render_drag_window)
+ {
+ RenderIconToTexture (GfxContext, _drag_icon, _offscreen_drag_texture);
+ _drag_window->ShowWindow (true);
+ nux::GetWindowCompositor ().SetAlwaysOnFrontWindow (_drag_window);
+
+ _render_drag_window = false;
+ }
+
+
// clear region
+ GfxContext.PushClippingRectangle(base);
gPainter.PushDrawColorLayer(GfxContext, base, nux::Color(0x00000000), true, ROP);
// clip vertically but not horizontally
@@ -1463,7 +1534,12 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
/* draw launcher */
for (rev_it = args.rbegin (); rev_it != args.rend (); rev_it++)
{
- if ((*rev_it).folding_rads >= 0.0f || (*rev_it).skip)
+ if ((*rev_it).stick_thingy)
+ gPainter.Paint2DQuadColor (GfxContext,
+ nux::Geometry (bkg_box.x, (*rev_it).render_center.y - 3, bkg_box.width, 2),
+ nux::Color(0xAAFFFFFF));
+
+ if ((*rev_it).x_rotation >= 0.0f || (*rev_it).skip)
continue;
DrawRenderArg (GfxContext, *rev_it, bkg_box);
@@ -1471,7 +1547,12 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
for (it = args.begin(); it != args.end(); it++)
{
- if ((*it).folding_rads < 0.0f || (*it).skip)
+ if ((*it).stick_thingy)
+ gPainter.Paint2DQuadColor (GfxContext,
+ nux::Geometry (bkg_box.x, (*it).render_center.y - 3, bkg_box.width, 2),
+ nux::Color(0xAAFFFFFF));
+
+ if ((*it).x_rotation < 0.0f || (*it).skip)
continue;
DrawRenderArg (GfxContext, *it, bkg_box);
@@ -1509,7 +1590,7 @@ long Launcher::PostLayoutManagement(long LayoutResult)
{
View::PostLayoutManagement(LayoutResult);
- _mouse_position = nux::Point2 (0, 0);
+ SetMousePosition (0, 0);
return nux::eCompliantHeight | nux::eCompliantWidth;
}
@@ -1518,27 +1599,76 @@ void Launcher::PositionChildLayout(float offsetX, float offsetY)
{
}
-bool Launcher::TooltipNotify(LauncherIcon* Icon)
+void Launcher::OnDragWindowAnimCompleted ()
{
- if(GetActiveMenuIcon())
- return false;
- return true;
+ if (_drag_window)
+ _drag_window->ShowWindow (false);
+
+ EnsureAnimation ();
}
-bool Launcher::MenuNotify(LauncherIcon* Icon)
+void Launcher::StartIconDrag (LauncherIcon *icon)
{
+ if (!icon)
+ return;
+
+ _drag_icon = icon;
+ if (_drag_window)
+ {
+ _drag_window->ShowWindow (false);
+ _drag_window->UnReference ();
+ _drag_window = NULL;
+ }
+
+ _offscreen_drag_texture = nux::GetThreadGLDeviceFactory()->CreateSystemCapableDeviceTexture (_icon_size, _icon_size, 1, nux::BITFMT_R8G8B8A8);
+ _drag_window = new LauncherDragWindow (_offscreen_drag_texture);
+ _drag_window->SinkReference ();
+
+ _render_drag_window = true;
+}
- return true;
+void Launcher::EndIconDrag ()
+{
+ if (_drag_window)
+ {
+ _drag_window->SetAnimationTarget ((int) (_drag_icon->GetCenter ().x), (int) (_drag_icon->GetCenter ().y));
+ _drag_window->StartAnimation ();
+ _drag_window->anim_completed.connect (sigc::mem_fun (this, &Launcher::OnDragWindowAnimCompleted));
+ }
+
+ if (MouseBeyondDragThreshold ())
+ SetTimeStruct (&_drag_threshold_time, &_drag_threshold_time, ANIM_DURATION_SHORT);
+
+ _render_drag_window = false;
}
-void Launcher::NotifyMenuTermination(LauncherIcon* Icon)
+void Launcher::UpdateDragWindowPosition (int x, int y)
{
+ if (_drag_window)
+ {
+ nux::Geometry geo = _drag_window->GetGeometry ();
+ _drag_window->SetBaseXY (x - geo.width / 2 + _parent->GetGeometry ().x, y - geo.height / 2 + _parent->GetGeometry ().y);
+
+ LauncherIcon *hovered_icon = MouseIconIntersection ((int) (GetGeometry ().x / 2.0f), y);
+
+ struct timespec current;
+ clock_gettime (CLOCK_MONOTONIC, &current);
+ if (_drag_icon && hovered_icon && _drag_icon != hovered_icon)
+ {
+ float progress = DragThresholdProgress (current);
+
+ if (progress >= 1.0f)
+ request_reorder_smart.emit (_drag_icon, hovered_icon, true);
+ else if (progress == 0.0f)
+ request_reorder_before.emit (_drag_icon, hovered_icon, false);
+ }
+ }
}
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
- _mouse_position = nux::Point2 (x, y);
+ SetMousePosition (x, y);
MouseDownLogic (x, y, button_flags, key_flags);
EnsureAnimation ();
@@ -1546,27 +1676,37 @@ void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
- _mouse_position = nux::Point2 (x, y);
+ SetMousePosition (x, y);
nux::Geometry geo = GetGeometry ();
- if (_launcher_action_state == ACTION_DRAG_LAUNCHER && !geo.IsInside(nux::Point(x, y)))
+ if (_launcher_action_state != ACTION_NONE && !geo.IsInside(nux::Point(x, y)))
{
// we are no longer hovered
- UnsetHover ();
+ EnsureHoverState ();
}
-
+
MouseUpLogic (x, y, button_flags, key_flags);
+
+ if (_launcher_action_state == ACTION_DRAG_ICON)
+ EndIconDrag ();
+
_launcher_action_state = ACTION_NONE;
+ _dnd_delta_x = 0;
+ _dnd_delta_y = 0;
+ EnsureHoverState ();
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;
+ SetMousePosition (x, y);
- if (nux::Abs (_dnd_delta) < 15 && _launcher_action_state != ACTION_DRAG_LAUNCHER)
+ _dnd_delta_y += dy;
+ _dnd_delta_x += dx;
+
+ if (nux::Abs (_dnd_delta_y) < 15 &&
+ nux::Abs (_dnd_delta_x) < 15 &&
+ _launcher_action_state == ACTION_NONE)
return;
if (_icon_under_mouse)
@@ -1576,16 +1716,46 @@ void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_
_icon_under_mouse = 0;
}
- _launcher_action_state = ACTION_DRAG_LAUNCHER;
+ if (_launcher_action_state == ACTION_NONE)
+ {
+ SetTimeStruct (&_drag_start_time);
+
+ if (nux::Abs (_dnd_delta_y) >= nux::Abs (_dnd_delta_x))
+ {
+ _launcher_drag_delta += _dnd_delta_y;
+ _launcher_action_state = ACTION_DRAG_LAUNCHER;
+ }
+ else
+ {
+ LauncherIcon *drag_icon = MouseIconIntersection ((int) (GetGeometry ().x / 2.0f), y);
+
+ if (drag_icon)
+ {
+ StartIconDrag (drag_icon);
+ _launcher_action_state = ACTION_DRAG_ICON;
+ UpdateDragWindowPosition (x, y);
+ }
+
+ }
+ }
+ else if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
+ {
+ _launcher_drag_delta += dy;
+ }
+ else if (_launcher_action_state == ACTION_DRAG_ICON)
+ {
+ UpdateDragWindowPosition (x, y);
+ }
+
EnsureAnimation ();
}
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
- _mouse_position = nux::Point2 (x, y);
+ SetMousePosition (x, y);
_mouse_inside_launcher = true;
- SetHover ();
+ EnsureHoverState ();
EventLogic ();
EnsureAnimation ();
@@ -1593,11 +1763,11 @@ void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
{
- _mouse_position = nux::Point2 (x, y);
+ SetMousePosition (x, y);
_mouse_inside_launcher = false;
- if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
- UnsetHover ();
+ if (_launcher_action_state == ACTION_NONE)
+ EnsureHoverState ();
EventLogic ();
EnsureAnimation ();
@@ -1605,7 +1775,7 @@ void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned
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);
+ SetMousePosition (x, y);
// Every time the mouse moves, we check if it is inside an icon...
EventLogic ();
@@ -1613,11 +1783,42 @@ void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_
void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags)
{
+ if (!_hovered)
+ return;
+
+ if (wheel_delta < 0)
+ {
+ // scroll up
+ _launcher_drag_delta += 10;
+ }
+ else
+ {
+ // scroll down
+ _launcher_drag_delta -= 10;
+ }
+
+ EnsureAnimation ();
+}
+
+void Launcher::RecvQuicklistOpened (QuicklistView *quicklist)
+{
+ EventLogic ();
+ EnsureHoverState ();
+ EnsureAnimation ();
+}
+
+void Launcher::RecvQuicklistClosed (QuicklistView *quicklist)
+{
+ SetupAutohideTimer ();
+
+ EventLogic ();
+ EnsureHoverState ();
+ EnsureAnimation ();
}
void Launcher::EventLogic ()
{
- if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
+ if (_launcher_action_state != ACTION_NONE)
return;
LauncherIcon* launcher_icon = 0;
@@ -1661,7 +1862,7 @@ void Launcher::MouseUpLogic (int x, int y, unsigned long button_flags, unsigned
{
_icon_mouse_down->MouseUp.emit (nux::GetEventButton (button_flags));
- if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
+ if (_launcher_action_state == ACTION_NONE)
_icon_mouse_down->MouseClick.emit (nux::GetEventButton (button_flags));
}
@@ -1785,22 +1986,30 @@ void Launcher::UpdateIconXForm (std::list<Launcher::RenderArg> &args)
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;
+ launcher_icon->_folding_angle = (*it).x_rotation;
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;
+ float x = (*it).render_center.x - w/2.0f; // x: top left corner
+ float y = (*it).render_center.y - h/2.0f; // y: top left corner
+ float z = (*it).render_center.z;
+ if ((*it).skip)
+ {
+ w = 1;
+ h = 1;
+ x = -100;
+ y = -100;
+ }
+
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::ROTATEX((*it).x_rotation) * // rotate the icon
+ nux::Matrix4::ROTATEY((*it).y_rotation) *
+ nux::Matrix4::ROTATEZ((*it).z_rotation) *
nux::Matrix4::TRANSLATE(-x - w/2.0f, -y - h/2.0f, -z); // Put the center the icon to (0, 0)
ViewProjectionMatrix = ProjectionMatrix*ViewMatrix*ObjectMatrix;
@@ -1809,25 +2018,25 @@ void Launcher::UpdateIconXForm (std::list<Launcher::RenderArg> &args)
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;
+ x = (*it).render_center.x - _icon_size/2.0f + _icon_image_size_delta/2.0f;
+ y = (*it).render_center.y - _icon_size/2.0f + _icon_image_size_delta/2.0f;
+ z = (*it).render_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;
+ x = (*it).render_center.x - _icon_glow_size/2.0f;
+ y = (*it).render_center.y - _icon_glow_size/2.0f;
+ z = (*it).render_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;
+ x = (*it).logical_center.x - w/2.0f;
+ y = (*it).logical_center.y - h/2.0f;
+ z = (*it).logical_center.z;
SetIconXForm (launcher_icon, ViewProjectionMatrix, geo, x, y, w, h, z, "HitArea");
}
@@ -1909,65 +2118,128 @@ void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& P
float AspectRatio = (float)ViewportWidth/(float)ViewportHeight;
float CameraToScreenDistance = -1.0f;
- float y_cs = -CameraToScreenDistance*tanf(0.5f*Fovy/* *3.1415926/180.0f*/);
+ float y_cs = -CameraToScreenDistance*tanf(0.5f*Fovy/* *M_PI/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;
+void
+Launcher::RenderIconToTexture (nux::GraphicsEngine& GfxContext, LauncherIcon *icon, nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture)
+{
+ RenderArg arg;
+ struct timespec current;
+ clock_gettime (CLOCK_MONOTONIC, &current);
+
+ SetupRenderArg (icon, current, arg);
+ arg.render_center = nux::Point3 (_icon_size / 2.0f, _icon_size / 2.0f, 0.0f);
+ arg.logical_center = arg.render_center;
+ arg.x_rotation = 0.0f;
+ arg.running_arrow = false;
+ arg.active_arrow = false;
+ arg.skip = false;
+ arg.window_indicators = 0;
+ arg.alpha = 1.0f;
+
+ std::list<Launcher::RenderArg> drag_args;
+ drag_args.push_front (arg);
+ UpdateIconXForm (drag_args);
+
+ SetOffscreenRenderTarget (texture);
+ DrawRenderArg (nux::GetGraphicsEngine (), arg, nux::Geometry (0, 0, _icon_size, _icon_size));
+ RestoreSystemRenderTarget ();
}
+void
+Launcher::RenderProgressToTexture (nux::GraphicsEngine& GfxContext, nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture, float progress_fill, float bias)
+{
+ int width = texture->GetWidth ();
+ int height = texture->GetHeight ();
+
+ int progress_width = _progress_bar_trough->GetWidth ();
+ int progress_height = _progress_bar_trough->GetHeight ();
+
+ int fill_width = _progress_bar_fill->GetWidth ();
+ int fill_height = _progress_bar_fill->GetHeight ();
+
+ int fill_offset = (progress_width - fill_width) / 2;
+
+ /* We need to perform a barn doors effect to acheive the slide in and out */
+
+ int left_edge = width / 2 - progress_width / 2;
+ int right_edge = width / 2 + progress_width / 2;
+
+ if (bias < 0.0f)
+ {
+ // pulls the right edge in
+ right_edge -= (int) (-bias * (float) progress_width);
+ }
+ else if (bias > 0.0f)
+ {
+ // pulls the left edge in
+ left_edge += (int) (bias * progress_width);
+ }
+
+ int fill_y = (height - fill_height) / 2;
+ int progress_y = (height - progress_height) / 2;
+ int half_size = (right_edge - left_edge) / 2;
+
+ SetOffscreenRenderTarget (texture);
+
+ // FIXME
+ glClear (GL_COLOR_BUFFER_BIT);
+ nux::TexCoordXForm texxform;
+
+ fill_width *= progress_fill;
+
+ // left door
+ GfxContext.PushClippingRectangle(nux::Geometry (left_edge, 0, half_size, height));
+
+ GfxContext.QRP_GLSL_1Tex (left_edge, progress_y, progress_width, progress_height,
+ _progress_bar_trough->GetDeviceTexture (), texxform, nux::Color::White);
+
+ GfxContext.QRP_GLSL_1Tex (left_edge + fill_offset, fill_y, fill_width, fill_height,
+ _progress_bar_fill->GetDeviceTexture (), texxform, nux::Color::White);
+
+ GfxContext.PopClippingRectangle ();
+
+
+ // right door
+ GfxContext.PushClippingRectangle(nux::Geometry (left_edge + half_size, 0, half_size, height));
+
+ GfxContext.QRP_GLSL_1Tex (right_edge - progress_width, progress_y, progress_width, progress_height,
+ _progress_bar_trough->GetDeviceTexture (), texxform, nux::Color::White);
+
+ GfxContext.QRP_GLSL_1Tex (right_edge - progress_width + fill_offset, fill_y, fill_width, fill_height,
+ _progress_bar_fill->GetDeviceTexture (), texxform, nux::Color::White);
+
+ GfxContext.PopClippingRectangle ();
+
+
+ RestoreSystemRenderTarget ();
+}
+
+void
+Launcher::SetOffscreenRenderTarget (nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture)
+{
+ int width = texture->GetWidth ();
+ int height = texture->GetHeight ();
+
+ nux::GetThreadGLDeviceFactory ()->FormatFrameBufferObject (width, height, nux::BITFMT_R8G8B8A8);
+ nux::GetThreadGLDeviceFactory ()->SetColorRenderTargetSurface (0, texture->GetSurfaceLevel (0));
+ nux::GetThreadGLDeviceFactory ()->ActivateFrameBuffer ();
+
+ nux::GetThreadGraphicsContext ()->SetContext (0, 0, width, height);
+ nux::GetThreadGraphicsContext ()->SetViewport (0, 0, width, height);
+ nux::GetThreadGraphicsContext ()->Push2DWindow (width, height);
+ nux::GetThreadGraphicsContext ()->EmptyClippingRegion();
+}
+
+void
+Launcher::RestoreSystemRenderTarget ()
+{
+ nux::GetWindowCompositor ().RestoreRenderingSurface ();
+}
diff --git a/src/Launcher.h b/src/Launcher.h
index b55111c2d..b759683c5 100644
--- a/src/Launcher.h
+++ b/src/Launcher.h
@@ -27,8 +27,10 @@
#include <Nux/BaseWindow.h>
#include "Introspectable.h"
#include "LauncherIcon.h"
+#include "LauncherDragWindow.h"
#include "NuxGraphics/IOpenGLAsmShader.h"
#include "Nux/TimerProc.h"
+#include "PluginAdapter.h"
class LauncherModel;
class QuicklistView;
@@ -36,54 +38,45 @@ class QuicklistView;
class Launcher : public Introspectable, public nux::View
{
public:
- Launcher(nux::BaseWindow *parent, CompScreen *screen, NUX_FILE_LINE_PROTO);
- ~Launcher();
+ 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);
+ 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;}
+ 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 SetIconSize(int tile_size, int icon_size);
- void NotifyMenuTermination(LauncherIcon* Icon);
+ void SetModel (LauncherModel *model);
- void SetModel (LauncherModel *model);
+ void SetFloating (bool floating);
- void SetFloating (bool floating);
+ void SetAutohide (bool autohide, nux::View *show_trigger);
+ bool AutohideEnabled ();
+
+ nux::BaseWindow* GetParent () { return _parent; };
- 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);
- 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);
+ virtual void RecvQuicklistOpened (QuicklistView *quicklist);
+ virtual void RecvQuicklistClosed (QuicklistView *quicklist);
+ sigc::signal<void, LauncherIcon *, LauncherIcon *, bool> request_reorder_smart;
+ sigc::signal<void, LauncherIcon *, LauncherIcon *, bool> request_reorder_before;
protected:
- // Introspectable methods
- const gchar* GetName ();
- void AddProperties (GVariantBuilder *builder);
+ // Introspectable methods
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
private:
typedef enum
@@ -102,24 +95,37 @@ private:
typedef struct
{
LauncherIcon *icon;
- nux::Point3 center;
- float folding_rads;
+ nux::Point3 render_center;
+ nux::Point3 logical_center;
+ float x_rotation;
+ float y_rotation;
+ float z_rotation;
float alpha;
float backlight_intensity;
float glow_intensity;
float shimmer_progress;
+ float progress;
+ float progress_bias;
bool running_arrow;
bool running_colored;
bool active_arrow;
bool active_colored;
bool skip;
+ bool stick_thingy;
int window_indicators;
} RenderArg;
+ void OnWindowMaybeIntellihide (CompWindow *window);
+
static gboolean AnimationTimeout (gpointer data);
static gboolean OnAutohideTimeout (gpointer data);
static gboolean StrutHack (gpointer data);
+
+ void SetMousePosition (int x, int y);
+
+ bool MouseBeyondDragThreshold ();
+ void OnDragWindowAnimCompleted ();
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);
@@ -127,21 +133,26 @@ private:
bool AnimationInProgress ();
void SetTimeStruct (struct timespec *timer, struct timespec *sister = 0, int sister_relation = 0);
+ void EnsureHoverState ();
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 DnDStartProgress (struct timespec const &current);
+ float DnDExitProgress (struct timespec const &current);
+ float GetHoverProgress (struct timespec const &current);
+ float AutohideProgress (struct timespec const &current);
+ float DragThresholdProgress (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);
+ float IconProgressBias (LauncherIcon *icon, struct timespec const &current);
+ float IconCenterTransitionProgress (LauncherIcon *icon, struct timespec const &current);
void SetHover ();
void UnsetHover ();
@@ -151,16 +162,27 @@ private:
float DragLimiter (float x);
void SetupRenderArg (LauncherIcon *icon, struct timespec const &current, RenderArg &arg);
+ void FillRenderArg (LauncherIcon *icon,
+ RenderArg &arg,
+ nux::Point3 &center,
+ float folding_threshold,
+ float folded_size,
+ float folded_spacing,
+ float autohide_offset,
+ float folded_z_distance,
+ float animation_neg_rads,
+ struct timespec const &current);
+
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 OnIconAdded (LauncherIcon *icon);
+ void OnIconRemoved (LauncherIcon *icon);
void OnOrderChanged ();
- void OnIconNeedsRedraw (void *icon);
+ void OnIconNeedsRedraw (LauncherIcon *icon);
void RenderIndicators (nux::GraphicsEngine& GfxContext,
RenderArg const &arg,
@@ -170,11 +192,13 @@ private:
void RenderIcon (nux::GraphicsEngine& GfxContext,
RenderArg const &arg,
- nux::BaseTexture *icon,
+ nux::IntrusiveSP<nux::IOpenGLBaseTexture> icon,
nux::Color bkg_color,
float alpha,
- nux::Vector4 xform_coords[],
- nux::Geometry geo);
+ nux::Vector4 xform_coords[]);
+
+ void RenderIconToTexture (nux::GraphicsEngine& GfxContext, LauncherIcon *icon, nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture);
+ void RenderProgressToTexture (nux::GraphicsEngine& GfxContext, nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture, float progress_fill, float bias);
void SetIconXForm (LauncherIcon *icon, nux::Matrix4 ViewProjectionMatrix, nux::Geometry geo,
float x, float y, float w, float h, float z, std::string name);
@@ -184,11 +208,17 @@ private:
void EventLogic ();
void MouseDownLogic (int x, int y, unsigned long button_flags, unsigned long key_flags);
void MouseUpLogic (int x, int y, unsigned long button_flags, unsigned long key_flags);
+
+ void StartIconDrag (LauncherIcon *icon);
+ void EndIconDrag ();
+ void UpdateDragWindowPosition (int x, int y);
virtual void PreLayoutManagement();
virtual long PostLayoutManagement(long LayoutResult);
virtual void PositionChildLayout(float offsetX, float offsetY);
+ void SetOffscreenRenderTarget (nux::IntrusiveSP<nux::IOpenGLBaseTexture> texture);
+ void RestoreSystemRenderTarget ();
nux::HLayout* m_Layout;
int m_ContentOffsetY;
@@ -206,6 +236,7 @@ private:
bool _mouse_inside_launcher;
bool _mouse_inside_trigger;
bool _window_over_launcher;
+ bool _render_drag_window;
float _folded_angle;
float _neg_folded_angle;
@@ -215,15 +246,19 @@ private:
LauncherState _launcher_state;
LauncherActionState _launcher_action_state;
+
LauncherIcon* _icon_under_mouse;
LauncherIcon* _icon_mouse_down;
+ LauncherIcon* _drag_icon;
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_delta_y;
+ int _dnd_delta_x;
+ int _launcher_drag_delta;
int _dnd_security;
int _enter_y;
@@ -231,11 +266,12 @@ private:
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;
+ nux::BaseTexture* _progress_bar_trough;
+ nux::BaseTexture* _progress_bar_fill;
+
+ nux::IntrusiveSP<nux::IOpenGLBaseTexture> _offscreen_drag_texture;
+ nux::IntrusiveSP<nux::IOpenGLBaseTexture> _offscreen_progress_texture;
- guint _anim_handle;
guint _autohide_handle;
nux::Matrix4 _view_matrix;
@@ -249,6 +285,7 @@ private:
nux::BaseWindow* _parent;
nux::View* _autohide_trigger;
LauncherModel* _model;
+ LauncherDragWindow* _drag_window;
CompScreen* _screen;
@@ -256,6 +293,8 @@ private:
struct timespec _enter_time;
struct timespec _exit_time;
struct timespec _drag_end_time;
+ struct timespec _drag_start_time;
+ struct timespec _drag_threshold_time;
struct timespec _autohide_time;
};
diff --git a/src/LauncherController.cpp b/src/LauncherController.cpp
index 43d45675e..c295554c7 100644
--- a/src/LauncherController.cpp
+++ b/src/LauncherController.cpp
@@ -41,6 +41,9 @@ LauncherController::LauncherController(Launcher* launcher, CompScreen *screen, n
g_timeout_add (5000, (GSourceFunc) &LauncherController::BamfTimerCallback, this);
InsertExpoAction ();
InsertTrash ();
+
+ _launcher->request_reorder_smart.connect (sigc::mem_fun (this, &LauncherController::OnLauncherRequestReorderSmart));
+ _launcher->request_reorder_before.connect (sigc::mem_fun (this, &LauncherController::OnLauncherRequestReorderBefore));
}
LauncherController::~LauncherController()
@@ -48,41 +51,130 @@ LauncherController::~LauncherController()
_favorite_store->UnReference ();
}
-void
-LauncherController::PresentIconOwningWindow (Window window)
+void
+LauncherController::SortAndSave ()
{
LauncherModel::iterator it;
- LauncherIcon *owner = 0;
+ _model->Sort (&LauncherController::CompareIcons);
+ std::list<const char*> desktop_paths;
for (it = _model->begin (); it != _model->end (); it++)
{
- if ((*it)->IconOwnsWindow (window))
- {
- owner = *it;
- break;
- }
+ BamfLauncherIcon *icon;
+ icon = dynamic_cast<BamfLauncherIcon*> (*it);
+
+ if (!icon)
+ continue;
+
+ if (!icon->IsSticky ())
+ continue;
+
+ const char* desktop_file = icon->DesktopFile ();
+
+ if (desktop_file && strlen (desktop_file) > 0)
+ desktop_paths.push_back (desktop_file);
}
- for (it = _model->shelf_begin (); !owner && it != _model->shelf_end (); it++)
+ _favorite_store->SetFavorites (desktop_paths);
+}
+
+void
+LauncherController::OnLauncherRequestReorderBefore (LauncherIcon *icon, LauncherIcon *other, bool save)
+{
+ if (icon == other)
+ return;
+
+ LauncherModel::iterator it;
+
+ int i = 0;
+ int j = 0;
+ for (it = _model->begin (); it != _model->end (); it++)
{
- if ((*it)->IconOwnsWindow (window))
+ if ((*it) == icon)
+ {
+ j++;
+ continue;
+ }
+
+ if ((*it) == other)
+ {
+ icon->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
+
+ (*it)->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
+ }
+ else
{
- owner = *it;
- break;
+ (*it)->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
}
+ j++;
}
- if (owner)
+ SortAndSave ();
+}
+
+void
+LauncherController::OnLauncherRequestReorderSmart (LauncherIcon *icon, LauncherIcon *other, bool save)
+{
+ if (icon == other)
+ return;
+
+ LauncherModel::iterator it;
+
+ int i = 0;
+ int j = 0;
+ bool skipped = false;
+ for (it = _model->begin (); it != _model->end (); it++)
{
- owner->Present (0.5f, 600);
- owner->UpdateQuirkTimeDelayed (300, LAUNCHER_ICON_QUIRK_SHIMMER);
+ if ((*it) == icon)
+ {
+ skipped = true;
+ j++;
+ continue;
+ }
+
+ if ((*it) == other)
+ {
+ if (!skipped)
+ {
+ icon->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
+ }
+
+ (*it)->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
+
+ if (skipped)
+ {
+ icon->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
+ }
+ }
+ else
+ {
+ (*it)->SetSortPriority (i);
+ if (i != j && save) (*it)->SaveCenter ();
+ i++;
+ }
+ j++;
}
+
+ SortAndSave ();
}
void
LauncherController::OnExpoClicked (int button)
{
- PluginAdapter::Default ()->InitiateExpo ();
+ if (button == 1)
+ PluginAdapter::Default ()->InitiateExpo ();
}
void
@@ -135,12 +227,6 @@ LauncherController::RegisterIcon (LauncherIcon *icon)
(*it)->SetSortPriority (i);
i++;
}
-
- for (it = _model->shelf_begin (); it != _model->shelf_end (); it++)
- {
- (*it)->SetSortPriority (i);
- i++;
- }
}
/* static private */
@@ -193,7 +279,8 @@ LauncherController::CreateFavorite (const char *file_path)
bamf_view_set_sticky (BAMF_VIEW (app), true);
icon = new BamfLauncherIcon (_launcher, app, _screen);
- icon->SetIconType (LAUNCHER_ICON_TYPE_FAVORITE);
+ icon->SetIconType (LAUNCHER_ICON_TYPE_APPLICATION);
+ icon->SetSortPriority (_sort_priority++);
return icon;
}
diff --git a/src/LauncherController.h b/src/LauncherController.h
index 8fffa56e1..a63afd150 100644
--- a/src/LauncherController.h
+++ b/src/LauncherController.h
@@ -43,8 +43,6 @@ public:
LauncherController(Launcher* launcher, CompScreen *screen, nux::BaseWindow* window);
~LauncherController();
- void PresentIconOwningWindow (Window window);
-
private:
BamfMatcher* _matcher;
CompAction* _expo_action;
@@ -55,6 +53,11 @@ private:
FavoriteStore* _favorite_store;
int _sort_priority;
+ void SortAndSave ();
+
+ void OnLauncherRequestReorderSmart (LauncherIcon *icon, LauncherIcon *other, bool save);
+ void OnLauncherRequestReorderBefore (LauncherIcon *icon, LauncherIcon *before, bool save);
+
void InsertExpoAction ();
void InsertTrash ();
diff --git a/src/LauncherDragWindow.cpp b/src/LauncherDragWindow.cpp
new file mode 100644
index 000000000..7fe189e63
--- /dev/null
+++ b/src/LauncherDragWindow.cpp
@@ -0,0 +1,117 @@
+/*
+* 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 "Nux/Nux.h"
+#include "Nux/BaseWindow.h"
+#include "NuxGraphics/GraphicsEngine.h"
+#include "Nux/TextureArea.h"
+
+#include "LauncherDragWindow.h"
+
+NUX_IMPLEMENT_OBJECT_TYPE (LauncherDragWindow);
+
+LauncherDragWindow::LauncherDragWindow (nux::IntrusiveSP<nux::IOpenGLBaseTexture> icon)
+: nux::BaseWindow ("")
+{
+ _icon = icon;
+ _anim_handle = 0;
+ SetBaseSize (_icon->GetWidth(), _icon->GetHeight());
+}
+
+LauncherDragWindow::~LauncherDragWindow ()
+{
+ if (_anim_handle)
+ g_source_remove (_anim_handle);
+}
+
+bool
+LauncherDragWindow::Animating ()
+{
+ return _anim_handle != 0;
+}
+
+void
+LauncherDragWindow::SetAnimationTarget (int x, int y)
+{
+ _animation_target = nux::Point2 (x, y);
+}
+
+void
+LauncherDragWindow::StartAnimation ()
+{
+ if (_anim_handle)
+ return;
+
+ _anim_handle = g_timeout_add (15, &LauncherDragWindow::OnAnimationTimeout, this);
+}
+
+gboolean
+LauncherDragWindow::OnAnimationTimeout (gpointer data)
+{
+ LauncherDragWindow *self = (LauncherDragWindow*) data;
+ nux::Geometry geo = self->GetGeometry ();
+
+ int half_size = geo.width / 2;
+
+ int target_x = (int) (self->_animation_target.x) - half_size;
+ int target_y = (int) (self->_animation_target.y) - half_size;
+
+ int x_delta = (int) ((float) (target_x - geo.x) * .3f);
+ if (abs (x_delta) < 5)
+ x_delta = (x_delta >= 0) ? MIN (5, target_x - geo.x) : MAX (-5, target_x - geo.x);
+
+ int y_delta = (int) ((float) (target_y - geo.y) * .3f);
+ if (abs (y_delta) < 5)
+ y_delta = (y_delta >= 0) ? MIN (5, target_y - geo.y) : MAX (-5, target_y - geo.y);
+
+ self->SetBaseXY (geo.x + x_delta, geo.y + y_delta);
+
+ geo = self->GetGeometry ();
+
+ if (geo.x == target_x && geo.y == target_y)
+ {
+ self->anim_completed.emit ();
+ self->_anim_handle = 0;
+ return false;
+ }
+
+ return true;
+}
+
+void
+LauncherDragWindow::DrawContent (nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+ nux::Geometry geo = GetGeometry ();
+ geo.SetX (0);
+ geo.SetY (0);
+
+ GfxContext.PushClippingRectangle (geo);
+
+ nux::TexCoordXForm texxform;
+ texxform.FlipVCoord (true);
+
+ GfxContext.QRP_GLSL_1Tex (0,
+ 0,
+ _icon->GetWidth(),
+ _icon->GetHeight(),
+ _icon,
+ texxform,
+ nux::Color::White);
+
+ GfxContext.PopClippingRectangle ();
+}
diff --git a/src/LauncherDragWindow.h b/src/LauncherDragWindow.h
new file mode 100644
index 000000000..9e4853834
--- /dev/null
+++ b/src/LauncherDragWindow.h
@@ -0,0 +1,56 @@
+/*
+ * 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 LAUNCHERDRAGWINDOW_H
+#define LAUNCHERDRAGWINDOW_H
+
+#include "Nux/Nux.h"
+#include "Nux/BaseWindow.h"
+#include "NuxGraphics/GraphicsEngine.h"
+
+#include "LauncherIcon.h"
+
+class LauncherDragWindow : public nux::BaseWindow
+{
+ NUX_DECLARE_OBJECT_TYPE (LauncherDragWindow, nux::BaseWindow);
+public:
+ LauncherDragWindow (nux::IntrusiveSP<nux::IOpenGLBaseTexture> icon);
+
+ ~LauncherDragWindow ();
+
+ void DrawContent (nux::GraphicsEngine& gfxContext, bool forceDraw);
+
+ void SetAnimationTarget (int x, int y);
+ void StartAnimation ();
+
+ bool Animating ();
+
+ sigc::signal<void> anim_completed;
+
+private:
+
+ static gboolean OnAnimationTimeout (gpointer data);
+
+ nux::IntrusiveSP<nux::IOpenGLBaseTexture> _icon;
+ nux::Point2 _animation_target;
+ guint32 _anim_handle;
+
+};
+
+#endif // LAUNCHERDRAGWINDOW_H
+
diff --git a/src/LauncherIcon.cpp b/src/LauncherIcon.cpp
index d78eace30..8471a3d2b 100644
--- a/src/LauncherIcon.cpp
+++ b/src/LauncherIcon.cpp
@@ -31,6 +31,7 @@
#include "LauncherIcon.h"
#include "Launcher.h"
+#include "QuicklistManager.h"
#include "QuicklistMenuItem.h"
#include "QuicklistMenuItemLabel.h"
#include "QuicklistMenuItemSeparator.h"
@@ -66,9 +67,9 @@ LauncherIcon::LauncherIcon(Launcher* launcher)
_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;
+
+ QuicklistManager::Default ()->RegisterQuicklist (_quicklist);
// Add to introspection
AddChild (_quicklist);
@@ -292,14 +293,14 @@ nux::NString LauncherIcon::GetTooltipText()
void
LauncherIcon::RecvMouseEnter ()
{
- if (_launcher->GetActiveQuicklist ())
+ if (QuicklistManager::Default ()->Current ())
{
// A quicklist is active
return;
}
int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
- int tip_y = _center.y;
+ int tip_y = _center.y + _launcher->GetParent ()->GetGeometry ().y;
_tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
@@ -318,26 +319,6 @@ 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 ();
@@ -377,15 +358,9 @@ void LauncherIcon::RecvMouseDown (int button)
}
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 ();
-
+ int tip_y = _center.y + _launcher->GetParent ()->GetGeometry ().y;
+ QuicklistManager::Default ()->ShowQuicklist (_quicklist, tip_x, tip_y);
nux::GetWindowCompositor ().SetAlwaysOnFrontWindow (_quicklist);
-
- _quicklist->NeedRedraw ();
}
}
@@ -398,16 +373,6 @@ void LauncherIcon::RecvMouseUp (int button)
}
}
-void LauncherIcon::RecvShowQuicklist (nux::BaseWindow *quicklist)
-{
- _launcher->SetActiveQuicklist (_quicklist);
-}
-
-void LauncherIcon::RecvHideQuicklist (nux::BaseWindow *quicklist)
-{
- _launcher->CancelActiveQuicklist (_quicklist);
-}
-
void LauncherIcon::HideTooltip ()
{
_tooltip->ShowWindow (false);
@@ -434,10 +399,10 @@ LauncherIcon::SetCenter (nux::Point3 center)
_center = center;
int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
- int tip_y = _center.y;
+ int tip_y = _center.y + _launcher->GetParent ()->GetGeometry ().y;
if (_quicklist->IsVisible ())
- _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
+ QuicklistManager::Default ()->ShowQuicklist (_quicklist, tip_x, tip_y);
else if (_tooltip->IsVisible ())
_tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
@@ -453,6 +418,13 @@ LauncherIcon::GetCenter ()
return _center;
}
+void
+LauncherIcon::SaveCenter ()
+{
+ _saved_center = _center;
+ UpdateQuirkTime (LAUNCHER_ICON_QUIRK_CENTER_SAVED);
+}
+
gboolean
LauncherIcon::OnPresentTimeout (gpointer data)
{
@@ -608,6 +580,22 @@ LauncherIcon::RelatedWindows ()
return _related_windows;
}
+void
+LauncherIcon::SetProgress (float progress)
+{
+ if (progress == _progress)
+ return;
+
+ _progress = progress;
+ needs_redraw.emit (this);
+}
+
+float
+LauncherIcon::GetProgress ()
+{
+ return _progress;
+}
+
std::list<DbusmenuMenuitem *> LauncherIcon::Menus ()
{
return GetMenus ();
diff --git a/src/LauncherIcon.h b/src/LauncherIcon.h
index 145775dc5..1ba0821cb 100644
--- a/src/LauncherIcon.h
+++ b/src/LauncherIcon.h
@@ -61,6 +61,8 @@ typedef enum
LAUNCHER_ICON_QUIRK_PRESENTED,
LAUNCHER_ICON_QUIRK_STARTING,
LAUNCHER_ICON_QUIRK_SHIMMER,
+ LAUNCHER_ICON_QUIRK_CENTER_SAVED,
+ LAUNCHER_ICON_QUIRK_PROGRESS,
LAUNCHER_ICON_QUIRK_LAST,
} LauncherIconQuirk;
@@ -69,7 +71,7 @@ class LauncherIcon : public Introspectable, public nux::InitiallyUnownedObject,
{
public:
LauncherIcon(Launcher* launcher);
- ~LauncherIcon();
+ virtual ~LauncherIcon();
void SetTooltipText (const TCHAR* text);
@@ -80,19 +82,21 @@ public:
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 ();
+ void SaveCenter ();
+
int SortPriority ();
int RelatedWindows ();
+
float PresentUrgency ();
+ float GetProgress ();
+
bool GetQuirk (LauncherIconQuirk quirk);
struct timespec GetQuirkTime (LauncherIconQuirk quirk);
@@ -105,17 +109,16 @@ public:
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;
+ sigc::signal<void, LauncherIcon *> show;
+ sigc::signal<void, LauncherIcon *> hide;
+ sigc::signal<void, LauncherIcon *> remove;
+ sigc::signal<void, LauncherIcon *> needs_redraw;
protected:
const gchar * GetName ();
void AddProperties (GVariantBuilder *builder);
@@ -129,6 +132,7 @@ protected:
void SetRelatedWindows (int windows);
void Remove ();
+ void SetProgress (float progress);
void Present (float urgency, int length);
void Unpresent ();
@@ -140,7 +144,6 @@ protected:
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);
@@ -184,12 +187,14 @@ private:
int _sort_priority;
int _related_windows;
float _present_urgency;
+ float _progress;
guint _present_time_handle;
guint _center_stabilize_handle;
bool _quicklist_is_initialized;
nux::Point3 _center;
nux::Point3 _last_stable;
+ nux::Point3 _saved_center;
LauncherIconType _icon_type;
bool _quirks[LAUNCHER_ICON_QUIRK_LAST];
diff --git a/src/LauncherModel.cpp b/src/LauncherModel.cpp
index c109bd519..2ed6c3a7b 100644
--- a/src/LauncherModel.cpp
+++ b/src/LauncherModel.cpp
@@ -81,9 +81,10 @@ LauncherModel::RemoveIcon (LauncherIcon *icon)
_inner.remove (icon);
if (size != _inner.size ())
+ {
icon_removed.emit (icon);
-
- icon->UnReference ();
+ icon->UnReference ();
+ }
}
gboolean
@@ -98,10 +99,10 @@ LauncherModel::RemoveCallback (gpointer data)
}
void
-LauncherModel::OnIconRemove (void *icon_pointer)
+LauncherModel::OnIconRemove (LauncherIcon *icon)
{
RemoveArg *arg = (RemoveArg*) g_malloc0 (sizeof (RemoveArg));
- arg->icon = (LauncherIcon*) icon_pointer;
+ arg->icon = icon;
arg->self = this;
g_timeout_add (1000, &LauncherModel::RemoveCallback, arg);
@@ -114,6 +115,7 @@ LauncherModel::Sort (SortFunc func)
_inner_main.sort (func);
Populate ();
+ order_changed.emit ();
}
int
diff --git a/src/LauncherModel.h b/src/LauncherModel.h
index 6da1b3fda..2c5da9e2c 100644
--- a/src/LauncherModel.h
+++ b/src/LauncherModel.h
@@ -40,7 +40,7 @@ public:
void Sort (SortFunc func);
int Size ();
- void OnIconRemove (void *icon);
+ void OnIconRemove (LauncherIcon *icon);
iterator begin ();
iterator end ();
@@ -57,8 +57,8 @@ public:
reverse_iterator shelf_rbegin ();
reverse_iterator shelf_rend ();
- sigc::signal<void, void *> icon_added;
- sigc::signal<void, void *> icon_removed;
+ sigc::signal<void, LauncherIcon *> icon_added;
+ sigc::signal<void, LauncherIcon *> icon_removed;
sigc::signal<void> order_changed;
private:
diff --git a/src/PanelHomeButton.cpp b/src/PanelHomeButton.cpp
index 154a5972d..711a0d824 100644
--- a/src/PanelHomeButton.cpp
+++ b/src/PanelHomeButton.cpp
@@ -22,6 +22,9 @@
#include "NuxGraphics/GLThread.h"
+#include "../libunity/ubus-server.h"
+#include "UBusMessages.h"
+
#include "PanelHomeButton.h"
#include <glib.h>
@@ -74,17 +77,17 @@ PanelHomeButton::Refresh ()
cairo_destroy (cr);
nux::NBitmapData* bitmap = cairo_graphics.GetBitmap();
-
+
// The Texture is created with a reference count of 1.
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);
-
- nux::ROPConfig rop;
+
+ nux::ROPConfig rop;
rop.Blend = true; // Enable the blending. By default rop.Blend is false.
rop.SrcBlend = GL_ONE; // Set the source blend factor.
rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; // Set the destination blend factor.
@@ -98,12 +101,12 @@ PanelHomeButton::Refresh ()
SetPaintLayer(texture_layer);
// We don't need the texture anymore. Since it hasn't been reference, it ref count should still be 1.
- // UnReference it and it will be destroyed.
+ // UnReference it and it will be destroyed.
texture2D->UnReference ();
-
+
// The texture layer has been cloned by this object when calling SetPaintLayer. It is safe to delete it now.
delete texture_layer;
-
+
NeedRedraw ();
}
@@ -113,31 +116,10 @@ PanelHomeButton::RecvMouseClick (int x,
unsigned long button_flags,
unsigned long key_flags)
{
-#define APPS_URI "file:///usr/share/applications"
-
- /* FIXME: This is just for Alpha 1, so we have some feedback on clicking the
- * PanelHomeButton, and especially because we don't have any other way of
- * launching non-launcher apps right now
- */
if (nux::GetEventButton (button_flags) == 1)
{
- GdkAppLaunchContext *context;
- GError *error = NULL;
-
- context = gdk_app_launch_context_new ();
- gdk_app_launch_context_set_screen (context, gdk_screen_get_default ());
- gdk_app_launch_context_set_timestamp (context, GDK_CURRENT_TIME);
-
- if (!g_app_info_launch_default_for_uri (APPS_URI,
- (GAppLaunchContext *)context,
- &error))
- {
- g_warning ("Unable to launcher applications folder: %s",
- error->message);
- g_error_free (error);
- }
-
- g_object_unref (context);
+ UBusServer *ubus = ubus_server_get_default ();
+ ubus_server_send_message (ubus, UBUS_HOME_BUTTON_ACTIVATED, NULL);
}
}
diff --git a/src/PanelIndicatorObjectEntryView.cpp b/src/PanelIndicatorObjectEntryView.cpp
index cd9a8ceee..a43f0dadd 100644
--- a/src/PanelIndicatorObjectEntryView.cpp
+++ b/src/PanelIndicatorObjectEntryView.cpp
@@ -31,9 +31,6 @@
#include <gtk/gtk.h>
#include <time.h>
-#define PANEL_HEIGHT 24
-#define PADDING 6
-#define SPACING 3
static void draw_menu_bg (cairo_t *cr, int width, int height);
@@ -43,7 +40,8 @@ PanelIndicatorObjectEntryView::PanelIndicatorObjectEntryView (IndicatorObjectEnt
_proxy (proxy),
_util_cg (CAIRO_FORMAT_ARGB32, 1, 1)
{
- _proxy->Updated.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::Refresh));
+ _proxy->active_changed.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::OnActiveChanged));
+ _proxy->updated.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::Refresh));
InputArea::OnMouseDown.connect (sigc::mem_fun (this, &PanelIndicatorObjectEntryView::OnMouseDown));
@@ -55,6 +53,12 @@ PanelIndicatorObjectEntryView::~PanelIndicatorObjectEntryView ()
}
void
+PanelIndicatorObjectEntryView::OnActiveChanged (bool is_active)
+{
+ active_changed.emit (this, is_active);
+}
+
+void
PanelIndicatorObjectEntryView::OnMouseDown (int x, int y, long button_flags, long key_flags)
{
if (_proxy->GetActive ())
diff --git a/src/PanelIndicatorObjectEntryView.h b/src/PanelIndicatorObjectEntryView.h
index 58c9c3606..2bc8971f8 100644
--- a/src/PanelIndicatorObjectEntryView.h
+++ b/src/PanelIndicatorObjectEntryView.h
@@ -28,6 +28,10 @@
#include "Introspectable.h"
+#define PANEL_HEIGHT 24
+#define PADDING 6
+#define SPACING 3
+
class PanelIndicatorObjectEntryView : public nux::TextureArea, public Introspectable
{
public:
@@ -37,10 +41,13 @@ public:
void Refresh ();
void OnMouseDown (int x, int y, long button_flags, long key_flags);
void Activate ();
+ void OnActiveChanged (bool is_active);
const gchar * GetName ();
void AddProperties (GVariantBuilder *builder);
+ sigc::signal<void, PanelIndicatorObjectEntryView *, bool> active_changed;
+
public:
IndicatorObjectEntryProxy *_proxy;
private:
diff --git a/src/PanelIndicatorObjectView.cpp b/src/PanelIndicatorObjectView.cpp
index 52936b710..a3a9f55cb 100644
--- a/src/PanelIndicatorObjectView.cpp
+++ b/src/PanelIndicatorObjectView.cpp
@@ -30,6 +30,13 @@
#include <glib.h>
+PanelIndicatorObjectView::PanelIndicatorObjectView ()
+: View (NUX_TRACKER_LOCATION),
+ _proxy (NULL),
+ _entries ()
+{
+}
+
PanelIndicatorObjectView::PanelIndicatorObjectView (IndicatorObjectProxy *proxy)
: View (NUX_TRACKER_LOCATION),
_proxy (proxy),
diff --git a/src/PanelIndicatorObjectView.h b/src/PanelIndicatorObjectView.h
index cc23dbc73..0c5baf4a0 100644
--- a/src/PanelIndicatorObjectView.h
+++ b/src/PanelIndicatorObjectView.h
@@ -29,6 +29,7 @@
class PanelIndicatorObjectView : public nux::View, public Introspectable
{
public:
+ PanelIndicatorObjectView ();
PanelIndicatorObjectView (IndicatorObjectProxy *proxy);
~PanelIndicatorObjectView ();
@@ -47,7 +48,6 @@ protected:
const gchar * GetChildsName ();
void AddProperties (GVariantBuilder *builder);
-private:
IndicatorObjectProxy *_proxy;
std::vector<PanelIndicatorObjectEntryView *> _entries;
};
diff --git a/src/PanelMenuView.cpp b/src/PanelMenuView.cpp
new file mode 100644
index 000000000..0199f1b1c
--- /dev/null
+++ b/src/PanelMenuView.cpp
@@ -0,0 +1,671 @@
+/*
+ * 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 <glib.h>
+#include <pango/pangocairo.h>
+#include <gtk/gtk.h>
+
+#include "Nux/Nux.h"
+#include "Nux/HLayout.h"
+#include "Nux/VLayout.h"
+#include <Nux/TextureArea.h>
+
+#include "NuxGraphics/GLThread.h"
+#include "Nux/BaseWindow.h"
+#include "Nux/WindowCompositor.h"
+
+#include "PanelMenuView.h"
+
+#include "WindowManager.h"
+
+#include "IndicatorObjectEntryProxy.h"
+
+#include <gio/gdesktopappinfo.h>
+
+#define BUTTONS_WIDTH 72
+
+static void on_active_window_changed (BamfMatcher *matcher,
+ BamfView *old_view,
+ BamfView *new_view,
+ PanelMenuView *self);
+
+
+PanelMenuView::PanelMenuView ()
+: _matcher (NULL),
+ _title_layer (NULL),
+ _util_cg (CAIRO_FORMAT_ARGB32, 1, 1),
+ _gradient_texture (NULL),
+ _title_tex (NULL),
+ _is_inside (false),
+ _is_maximized (false),
+ _last_active_view (NULL)
+{
+ WindowManager *win_manager;
+
+ _matcher = bamf_matcher_get_default ();
+ g_signal_connect (_matcher, "active-window-changed",
+ G_CALLBACK (on_active_window_changed), this);
+
+ _menu_layout = new nux::HLayout ("", NUX_TRACKER_LOCATION);
+
+ /* This is for our parent and for PanelView to read indicator entries, we
+ * shouldn't touch this again
+ */
+ _layout = _menu_layout;
+
+ _window_buttons = new WindowButtons ();
+ _window_buttons->NeedRedraw ();
+ _window_buttons->close_clicked.connect (sigc::mem_fun (this, &PanelMenuView::OnCloseClicked));
+ _window_buttons->minimize_clicked.connect (sigc::mem_fun (this, &PanelMenuView::OnMinimizeClicked));
+ _window_buttons->restore_clicked.connect (sigc::mem_fun (this, &PanelMenuView::OnRestoreClicked));
+ _window_buttons->redraw_signal.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowButtonsRedraw));
+
+ win_manager = WindowManager::Default ();
+ win_manager->window_maximized.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowMaximized));
+ win_manager->window_restored.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowRestored));
+ win_manager->window_unmapped.connect (sigc::mem_fun (this, &PanelMenuView::OnWindowUnmapped));
+
+ Refresh ();
+}
+
+PanelMenuView::~PanelMenuView ()
+{
+ if (_title_layer)
+ delete _title_layer;
+ if (_title_tex)
+ _title_tex->UnReference ();
+
+ _menu_layout->UnReference ();
+ _window_buttons->UnReference ();
+}
+
+void
+PanelMenuView::FullRedraw ()
+{
+ _menu_layout->NeedRedraw ();
+ _window_buttons->NeedRedraw ();
+ NeedRedraw ();
+}
+
+void
+PanelMenuView::SetProxy (IndicatorObjectProxy *proxy)
+{
+ _proxy = proxy;
+ printf ("IndicatorAdded: %s\n", _proxy->GetName ().c_str ());
+
+ _proxy->OnEntryAdded.connect (sigc::mem_fun (this, &PanelMenuView::OnEntryAdded));
+ _proxy->OnEntryMoved.connect (sigc::mem_fun (this, &PanelMenuView::OnEntryMoved));
+ _proxy->OnEntryRemoved.connect (sigc::mem_fun (this, &PanelMenuView::OnEntryRemoved));
+}
+
+long
+PanelMenuView::ProcessEvent (nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
+{
+ long ret = TraverseInfo;
+ nux::Geometry geo = GetGeometry ();
+
+ if (geo.IsPointInside (ievent.e_x, ievent.e_y))
+ {
+ if (_is_inside != true)
+ {
+ _is_inside = true;
+ FullRedraw ();
+ }
+ }
+ else
+ {
+ if (_is_inside != false)
+ {
+ _is_inside = false;
+ FullRedraw ();
+ }
+ }
+
+ if (_is_maximized)
+ ret = _window_buttons->ProcessEvent (ievent, ret, ProcessEventInfo);
+ ret = _menu_layout->ProcessEvent (ievent, ret, ProcessEventInfo);
+
+ return ret;
+}
+
+long PanelMenuView::PostLayoutManagement (long LayoutResult)
+{
+ long res = View::PostLayoutManagement (LayoutResult);
+ int w = _window_buttons->GetContentWidth ();
+
+ nux::Geometry geo = GetGeometry ();
+
+ _window_buttons->SetGeometry (geo.x + PADDING, geo.y, w, geo.height);
+ _window_buttons->ComputeLayout2 ();
+
+ /* Explicitly set the size and position of the widgets */
+ geo.x += PADDING + w + PADDING;
+ geo.width -= PADDING + w + PADDING;
+
+ _menu_layout->SetGeometry (geo.x, geo.y, geo.width, geo.height);
+ _menu_layout->ComputeLayout2();
+
+ Refresh ();
+
+ return res;
+}
+
+void
+PanelMenuView::Draw (nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+ nux::Geometry geo = GetGeometry ();
+ int button_width = PADDING + _window_buttons->GetContentWidth () + PADDING;
+ float factor = 4;
+ button_width /= factor;
+
+ GfxContext.PushClippingRectangle (geo);
+
+ /* "Clear" out the background */
+ nux::ROPConfig rop;
+ rop.Blend = true;
+ rop.SrcBlend = GL_ONE;
+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
+
+ nux::ColorLayer layer (nux::Color (0x00000000), true, rop);
+ gPainter.PushDrawLayer (GfxContext, GetGeometry (), &layer);
+
+ if (_is_maximized)
+ {
+ if (!_is_inside)
+ gPainter.PushDrawLayer (GfxContext, GetGeometry (), _title_layer);
+ }
+ else
+ {
+ if (_is_inside || _last_active_view)
+ {
+ if (_gradient_texture == NULL)
+ {
+ nux::NTextureData texture_data (nux::BITFMT_R8G8B8A8, geo.width, 1, 1);
+ nux::ImageSurface surface = texture_data.GetSurface (0);
+ nux::SURFACE_LOCKED_RECT lockrect;
+ BYTE *dest;
+ int num_row;
+
+ _gradient_texture = nux::GetThreadGLDeviceFactory ()->CreateSystemCapableDeviceTexture (texture_data.GetWidth (), texture_data.GetHeight (), 1, texture_data.GetFormat ());
+
+ _gradient_texture->LockRect (0, &lockrect, 0);
+
+ dest = (BYTE *) lockrect.pBits;
+ num_row = surface.GetBlockHeight ();
+
+ for (int y = 0; y < num_row; y++)
+ {
+ for (int x = 0; x < geo.width; x++)
+ {
+ *(dest + y * lockrect.Pitch + 4*x + 0) = 223; //red
+ *(dest + y * lockrect.Pitch + 4*x + 1) = 219; //green
+ *(dest + y * lockrect.Pitch + 4*x + 2) = 210; //blue
+
+ if (x < button_width * (factor - 1))
+ {
+ *(dest + y * lockrect.Pitch + 4*x + 3) = 0xff;
+ }
+ else if (x < button_width * factor)
+ {
+ *(dest + y * lockrect.Pitch + 4*x + 3) = 255 - 255 * (((float)x-(button_width * (factor -1)))/(float)(button_width));
+ }
+ else
+ {
+ *(dest + y * lockrect.Pitch + 4*x + 3) = 0x00;
+ }
+ }
+ }
+ _gradient_texture->UnlockRect (0);
+ }
+ GfxContext.GetRenderStates ().SetBlend(true, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ nux::TexCoordXForm texxform0;
+ nux::TexCoordXForm texxform1;
+
+ // Modulate the checkboard and the gradient texture
+ GfxContext.QRP_2TexMod(geo.x, geo.y,
+ geo.width, geo.height,
+ _gradient_texture, texxform0,
+ nux::Color::White,
+ _title_tex->GetDeviceTexture (),
+ texxform1,
+ nux::Color::White);
+
+ GfxContext.GetRenderStates ().SetBlend(false);
+
+ // The previous blend is too aggressive on the texture and therefore there
+ // is a slight loss of clarity. This fixes that
+ geo.width = button_width * (factor - 1);
+ gPainter.PushDrawLayer (GfxContext, geo, _title_layer);
+ geo = GetGeometry ();
+ }
+ else
+ {
+ gPainter.PushDrawLayer (GfxContext,
+ geo,
+ _title_layer);
+ }
+ }
+
+ gPainter.PopBackground ();
+
+ GfxContext.PopClippingRectangle();
+}
+
+void
+PanelMenuView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
+{
+ nux::Geometry geo = GetGeometry ();
+
+ GfxContext.PushClippingRectangle (geo);
+
+ if (_is_inside || _last_active_view)
+ {
+ _layout->ProcessDraw (GfxContext, force_draw);
+ }
+
+ if (_is_maximized)
+ {
+ _window_buttons->ProcessDraw (GfxContext, true);
+ }
+
+ GfxContext.PopClippingRectangle();
+}
+
+gchar *
+PanelMenuView::GetActiveViewName ()
+{
+ gchar *label = NULL;
+
+ if (_is_maximized)
+ {
+ BamfWindow *window = bamf_matcher_get_active_window (_matcher);
+
+ if (BAMF_IS_WINDOW (window))
+ label = g_strdup (bamf_view_get_name (BAMF_VIEW (window)));
+ }
+
+ if (!label)
+ {
+ BamfApplication *app = bamf_matcher_get_active_application (_matcher);
+ if (BAMF_IS_APPLICATION (app))
+ {
+ const gchar *filename;
+
+ filename = bamf_application_get_desktop_file (app);
+
+ if (filename && g_strcmp0 (filename, "") != 0)
+ {
+ GDesktopAppInfo *info;
+
+ info = g_desktop_app_info_new_from_filename (bamf_application_get_desktop_file (app));
+
+ if (info)
+ {
+ label = g_strdup (g_app_info_get_display_name (G_APP_INFO (info)));
+ g_object_unref (info);
+ }
+ else
+ {
+ g_warning ("Unable to get GDesktopAppInfo for %s",
+ bamf_application_get_desktop_file (app));
+ }
+ }
+
+ if (label == NULL)
+ {
+ BamfView *active_view;
+
+ active_view = (BamfView *)bamf_matcher_get_active_window (_matcher);
+ if (BAMF_IS_VIEW (active_view))
+ label = g_strdup (bamf_view_get_name (active_view));
+ else
+ label = g_strdup ("");
+ }
+ }
+ else
+ {
+ label = g_strdup (" ");
+ }
+ }
+
+ return label;
+}
+
+void
+PanelMenuView::Refresh ()
+{
+ nux::Geometry geo = GetGeometry ();
+ char *label = GetActiveViewName ();
+ PangoLayout *layout = NULL;
+ PangoFontDescription *desc = NULL;
+ GtkSettings *settings = gtk_settings_get_default ();
+ cairo_t *cr;
+ char *font_description = NULL;
+ GdkScreen *screen = gdk_screen_get_default ();
+ int dpi = 0;
+
+ int x = 0;
+ int y = 0;
+ int width = geo.width;
+ int height = geo.height;
+ int text_width = 0;
+ int text_height = 0;
+
+ if (label)
+ {
+ PangoContext *cxt;
+ PangoRectangle log_rect;
+
+ cr = _util_cg.GetContext ();
+
+ g_object_get (settings,
+ "gtk-font-name", &font_description,
+ "gtk-xft-dpi", &dpi,
+ NULL);
+ desc = pango_font_description_from_string (font_description);
+ pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_font_description (layout, desc);
+ pango_layout_set_text (layout, label, -1);
+
+ cxt = pango_layout_get_context (layout);
+ pango_cairo_context_set_font_options (cxt, gdk_screen_get_font_options (screen));
+ pango_cairo_context_set_resolution (cxt, (float)dpi/(float)PANGO_SCALE);
+ pango_layout_context_changed (layout);
+
+ pango_layout_get_extents (layout, NULL, &log_rect);
+ text_width = log_rect.width / PANGO_SCALE;
+ text_height = log_rect.height / PANGO_SCALE;
+
+ pango_font_description_free (desc);
+ g_free (font_description);
+ cairo_destroy (cr);
+ }
+
+ nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, width, height);
+ cr = cairo_graphics.GetContext();
+ cairo_set_line_width (cr, 1);
+
+ x = PADDING;
+ y = 0;
+
+ if (_is_maximized)
+ x += _window_buttons->GetContentWidth () + PADDING + PADDING;
+
+ if (label)
+ {
+ pango_cairo_update_layout (cr, layout);
+
+ // Once for the homies that couldn't be here
+ cairo_set_source_rgb (cr, 50/255.0f, 50/255.0f, 45/255.0f);
+ cairo_move_to (cr, x, ((height - text_height)/2)-1);
+ pango_cairo_show_layout (cr, layout);
+ cairo_stroke (cr);
+
+ // Once again for the homies that could
+ cairo_set_source_rgba (cr, 223/255.0f, 219/255.0f, 210/255.0f, 1.0f);
+ cairo_move_to (cr, x, (height - text_height)/2);
+ pango_cairo_show_layout (cr, layout);
+ cairo_stroke (cr);
+ }
+
+ cairo_destroy (cr);
+ if (layout)
+ g_object_unref (layout);
+
+ nux::NBitmapData* bitmap = cairo_graphics.GetBitmap();
+
+ // The Texture is created with a reference count of 1.
+ nux::BaseTexture* texture2D = nux::GetThreadGLDeviceFactory ()->CreateSystemCapableTexture ();
+ texture2D->Update(bitmap);
+ delete bitmap;
+
+ if (_title_layer)
+ delete _title_layer;
+
+ nux::TexCoordXForm texxform;
+ texxform.SetTexCoordType (nux::TexCoordXForm::OFFSET_COORD);
+ texxform.SetWrap (nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
+
+ nux::ROPConfig rop;
+ rop.Blend = true;
+ rop.SrcBlend = GL_ONE;
+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
+ _title_layer = new nux::TextureLayer (texture2D->GetDeviceTexture(),
+ texxform,
+ nux::Color::White,
+ false,
+ rop);
+
+
+ if (_title_tex)
+ _title_tex->UnReference ();
+
+ _title_tex = texture2D;
+
+ g_free (label);
+}
+
+void
+PanelMenuView::OnActiveChanged (PanelIndicatorObjectEntryView *view,
+ bool is_active)
+{
+ if (is_active)
+ _last_active_view = view;
+ else
+ {
+ if (_last_active_view == view)
+ {
+ _last_active_view = NULL;
+ }
+ }
+ FullRedraw ();
+}
+
+void
+PanelMenuView::OnEntryAdded (IndicatorObjectEntryProxy *proxy)
+{
+ PanelIndicatorObjectEntryView *view = new PanelIndicatorObjectEntryView (proxy);
+ view->active_changed.connect (sigc::mem_fun (this, &PanelMenuView::OnActiveChanged));
+ _menu_layout->AddView (view, 0, nux::eCenter, nux::eFull);
+ _menu_layout->SetContentDistribution (nux::eStackLeft);
+
+ _entries.push_back (view);
+
+ AddChild (view);
+
+ this->ComputeChildLayout ();
+ NeedRedraw ();
+}
+
+void
+PanelMenuView::OnEntryMoved (IndicatorObjectEntryProxy *proxy)
+{
+ printf ("ERROR: Moving IndicatorObjectEntry not supported\n");
+}
+
+void
+PanelMenuView::OnEntryRemoved(IndicatorObjectEntryProxy *proxy)
+{
+ std::vector<PanelIndicatorObjectEntryView *>::iterator it;
+
+ for (it = _entries.begin(); it != _entries.end(); it++)
+ {
+ PanelIndicatorObjectEntryView *view = static_cast<PanelIndicatorObjectEntryView *> (*it);
+ if (view->_proxy == proxy)
+ {
+ RemoveChild (view);
+ _entries.erase (it);
+ _menu_layout->RemoveChildObject (view);
+
+ break;
+ }
+ }
+
+ this->ComputeChildLayout ();
+ NeedRedraw ();
+}
+
+void
+PanelMenuView::AllMenusClosed ()
+{
+ _is_inside = false;
+ _last_active_view = false;
+
+ FullRedraw ();
+}
+
+void
+PanelMenuView::OnActiveWindowChanged (BamfView *old_view,
+ BamfView *new_view)
+{
+ _is_maximized = false;
+
+ if (BAMF_IS_WINDOW (new_view))
+ {
+ BamfWindow *window = BAMF_WINDOW (new_view);
+ _is_maximized = WindowManager::Default ()->IsWindowMaximized (bamf_window_get_xid (window));
+ }
+
+ Refresh ();
+ FullRedraw ();
+}
+
+void
+PanelMenuView::OnWindowUnmapped (guint32 xid)
+{
+ _decor_map.erase (xid);
+}
+
+void
+PanelMenuView::OnWindowMaximized (guint xid)
+{
+ BamfWindow *window;
+
+ window = bamf_matcher_get_active_window (_matcher);
+ if (BAMF_IS_WINDOW (window) && bamf_window_get_xid (window) == xid)
+ {
+ // We could probably just check if a key is available, but who wants to do that
+ if (_decor_map.find (xid) == _decor_map.end ())
+ _decor_map[xid] = WindowManager::Default ()->IsWindowDecorated (xid);
+
+ if (_decor_map[xid])
+ {
+ WindowManager::Default ()->Undecorate (xid);
+ }
+
+ _is_maximized = true;
+
+ Refresh ();
+ FullRedraw ();
+ }
+}
+
+void
+PanelMenuView::OnWindowRestored (guint xid)
+{
+ BamfWindow *window;
+
+ window = bamf_matcher_get_active_window (_matcher);
+ if (BAMF_IS_WINDOW (window) && bamf_window_get_xid (window) == xid)
+ {
+ _is_maximized = false;
+
+ if (_decor_map[xid])
+ {
+ WindowManager::Default ()->Decorate (xid);
+ }
+
+ Refresh ();
+ FullRedraw ();
+ }
+}
+
+void
+PanelMenuView::OnCloseClicked ()
+{
+ BamfWindow *window;
+
+ window = bamf_matcher_get_active_window (_matcher);
+ if (BAMF_IS_WINDOW (window))
+ WindowManager::Default ()->Close (bamf_window_get_xid (window));
+}
+
+void
+PanelMenuView::OnMinimizeClicked ()
+{
+ BamfWindow *window;
+
+ window = bamf_matcher_get_active_window (_matcher);
+ if (BAMF_IS_WINDOW (window))
+ WindowManager::Default ()->Minimize (bamf_window_get_xid (window));
+}
+
+void
+PanelMenuView::OnRestoreClicked ()
+{
+ BamfWindow *window;
+
+ window = bamf_matcher_get_active_window (_matcher);
+ if (BAMF_IS_WINDOW (window))
+ WindowManager::Default ()->Restore (bamf_window_get_xid (window));
+}
+
+void
+PanelMenuView::OnWindowButtonsRedraw ()
+{
+ FullRedraw ();
+}
+
+// Introspectable
+const gchar *
+PanelMenuView::GetName ()
+{
+ return "MenuView";
+}
+
+const gchar *
+PanelMenuView::GetChildsName ()
+{
+ return "entries";
+}
+
+void
+PanelMenuView::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));
+}
+
+/*
+ * C code for callbacks
+ */
+static void
+on_active_window_changed (BamfMatcher *matcher,
+ BamfView *old_view,
+ BamfView *new_view,
+ PanelMenuView *self)
+{
+ self->OnActiveWindowChanged (old_view, new_view);
+}
diff --git a/src/PanelMenuView.h b/src/PanelMenuView.h
new file mode 100644
index 000000000..66f2f0f04
--- /dev/null
+++ b/src/PanelMenuView.h
@@ -0,0 +1,103 @@
+/*
+ * 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_MENU_VIEW_H
+#define PANEL_MENU_VIEW_H
+
+#include <Nux/View.h>
+#include <map>
+
+#include "IndicatorObjectProxy.h"
+#include "Introspectable.h"
+#include "PanelIndicatorObjectView.h"
+#include "StaticCairoText.h"
+#include "WindowButtons.h"
+
+#include <libbamf/libbamf.h>
+
+class PanelMenuView : public PanelIndicatorObjectView
+{
+public:
+ // This contains all the menubar logic for the Panel. Mainly it contains
+ // the following states:
+ // 1. Unmaximized window + no mouse hover
+ // 2. Unmaximized window + mouse hover
+ // 3. Unmaximized window + active menu (Alt+F/arrow key nav)
+ // 4. Maximized window + no mouse hover
+ // 5. Maximized window + mouse hover
+ // 6. Maximized window + active menu
+ //
+ // It also deals with undecorating maximized windows (and redecorating them
+ // on unmaximize)
+
+ PanelMenuView ();
+ ~PanelMenuView ();
+
+ void FullRedraw ();
+
+ 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 long PostLayoutManagement (long LayoutResult);
+
+ void SetProxy (IndicatorObjectProxy *proxy);
+
+ void OnEntryAdded (IndicatorObjectEntryProxy *proxy);
+ void OnEntryMoved (IndicatorObjectEntryProxy *proxy);
+ void OnEntryRemoved (IndicatorObjectEntryProxy *proxy);
+ void OnActiveChanged (PanelIndicatorObjectEntryView *view, bool is_active);
+ void OnActiveWindowChanged (BamfView *old_view, BamfView *new_view);
+
+ void OnWindowUnmapped (guint xid);
+ void OnWindowMaximized (guint32 xid);
+ void OnWindowRestored (guint32 xid);
+
+ void Refresh ();
+ void AllMenusClosed ();
+
+ void OnCloseClicked ();
+ void OnMinimizeClicked ();
+ void OnRestoreClicked ();
+ void OnWindowButtonsRedraw ();
+
+protected:
+ const gchar * GetName ();
+ const gchar * GetChildsName ();
+ void AddProperties (GVariantBuilder *builder);
+
+private:
+ gchar * GetActiveViewName ();
+
+private:
+ BamfMatcher* _matcher;
+
+ nux::AbstractPaintLayer *_title_layer;
+ nux::HLayout *_menu_layout;
+ nux::CairoGraphics _util_cg;
+ nux::IntrusiveSP<nux::IOpenGLBaseTexture> _gradient_texture;
+ nux::BaseTexture *_title_tex;
+
+ bool _is_inside;
+ bool _is_maximized;
+ PanelIndicatorObjectEntryView *_last_active_view;
+
+ WindowButtons *_window_buttons;
+
+ std::map<guint32, bool> _decor_map;
+};
+#endif
diff --git a/src/PanelView.cpp b/src/PanelView.cpp
index 3809ec815..f938a45a9 100644
--- a/src/PanelView.cpp
+++ b/src/PanelView.cpp
@@ -46,13 +46,17 @@ PanelView::PanelView (NUX_FILE_LINE_DECL)
// Home button
_home_button = new PanelHomeButton ();
_layout->AddView (_home_button, 0, nux::eCenter, nux::eFull);
-
AddChild (_home_button);
+ _menu_view = new PanelMenuView ();
+ _layout->AddView (_menu_view, 1, nux::eCenter, nux::eFull);
+ AddChild (_menu_view);
+
_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));
+ _remote->IndicatorObjectFactory::OnEntryActivated.connect (sigc::mem_fun (this, &PanelView::OnEntryActivated));
}
PanelView::~PanelView ()
@@ -204,7 +208,11 @@ PanelView::OnObjectAdded (IndicatorObjectProxy *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);
+ if (g_strstr_len (proxy->GetName ().c_str (), -1, "appmenu") != NULL)
+ _menu_view->SetProxy (proxy);
+ else
+ _layout->AddView (view, 0, nux::eCenter, nux::eFull);
+
_layout->SetContentDistribution (nux::eStackLeft);
AddChild (view);
@@ -224,40 +232,40 @@ PanelView::OnMenuPointerMoved (int x, int y)
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 *>::iterator it;
- std::list<Area *> my_children = _layout->GetChildren ();
- for (it = my_children.begin(); it != my_children.end(); 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))
{
- 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))
{
- 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;
- }
- }
+ entry->OnMouseDown (x, y, 0, 0);
break;
}
+ }
+ break;
}
}
+ }
}
void
@@ -281,10 +289,18 @@ PanelView::OnEntryActivateRequest (const char *entry_id)
PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
if (g_strcmp0 (entry->GetName (), entry_id) == 0)
- {
- entry->Activate ();
- break;
- }
+ {
+ g_debug ("%s: Activating: %s", G_STRFUNC, entry_id);
+ entry->Activate ();
+ break;
+ }
}
}
}
+
+void
+PanelView::OnEntryActivated (const char *entry_id)
+{
+ if (g_strcmp0 (entry_id, "") == 0)
+ _menu_view->AllMenusClosed ();
+}
diff --git a/src/PanelView.h b/src/PanelView.h
index f6afc4f95..e96bdf41a 100644
--- a/src/PanelView.h
+++ b/src/PanelView.h
@@ -24,6 +24,7 @@
#include <NuxGraphics/GraphicsEngine.h>
#include "PanelHomeButton.h"
+#include "PanelMenuView.h"
#include "IndicatorObjectFactoryRemote.h"
#include "Introspectable.h"
@@ -43,6 +44,7 @@ public:
void OnObjectAdded (IndicatorObjectProxy *proxy);
void OnMenuPointerMoved (int x, int y);
void OnEntryActivateRequest (const char *entry_id);
+ void OnEntryActivated (const char *entry_id);
PanelHomeButton * HomeButton ();
@@ -59,6 +61,7 @@ private:
IndicatorObjectFactoryRemote *_remote;
PanelHomeButton *_home_button;
+ PanelMenuView *_menu_view;
nux::AbstractPaintLayer *_bg_layer;
nux::HLayout *_layout;
diff --git a/src/PlacesController.cpp b/src/PlacesController.cpp
new file mode 100644
index 000000000..cb7d2e417
--- /dev/null
+++ b/src/PlacesController.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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: Gordon Allott <gord.allott@canonical.com>
+ */
+
+#include "config.h"
+
+#include "Nux/Nux.h"
+#include "Nux/HLayout.h"
+
+#include "NuxGraphics/GLThread.h"
+#include <glib.h>
+#include <pango/pangocairo.h>
+#include <gtk/gtk.h>
+
+#include "../libunity/ubus-server.h"
+#include "UBusMessages.h"
+
+#include "PlacesController.h"
+
+PlacesController::PlacesController ()
+{
+
+ // register interest with ubus so that we get activation messages
+ UBusServer *ubus = ubus_server_get_default ();
+ ubus_server_register_interest (ubus, UBUS_HOME_BUTTON_ACTIVATED,
+ (UBusCallback)&PlacesController::ExternalActivation,
+ this);
+
+ _Window = new PlacesView ();
+ _Window->Reference ();
+ _Window->SetConfigureNotifyCallback(&PlacesController::WindowConfigureCallback, this);
+ //_Window->SetBlurredBackground(true);
+ _Window->ShowWindow(false);
+ //_Window->EnableInputWindow(false);
+ //_Window->InputWindowEnableStruts(false);
+
+ _Window->OnMouseDownOutsideArea.connect (sigc::mem_fun (this, &PlacesController::RecvMouseDownOutsideOfView));
+
+}
+
+PlacesController::~PlacesController ()
+{
+ _Window->UnReference ();
+}
+
+void PlacesController::Show ()
+{
+ // show called
+ _Window->Show ();
+}
+
+void PlacesController::Hide ()
+{
+ _Window->Hide ();
+}
+
+void PlacesController::ToggleShowHide ()
+{
+ if (_Window->IsVisible ())
+ Hide ();
+ else
+ Show ();
+}
+
+/* Configure callback for the window */
+void
+PlacesController::WindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
+{
+ GdkScreen *screen = gdk_screen_get_default ();
+ int height = gdk_screen_get_height (screen) - 12;
+ geo = nux::Geometry(32, 12, 1024, height);
+}
+
+void
+PlacesController::ExternalActivation (GVariant *data, void *val)
+{
+ if (g_getenv ("UNITY_ENABLE_PLACES"))
+ {
+ PlacesController *self = (PlacesController*)val;
+ self->ToggleShowHide ();
+ }
+ else
+ {
+ // not removing the nautilus behaviour until we can launch applications in places :)
+ #define APPS_URI "file:///usr/share/applications"
+
+ /* FIXME: This is just for Alpha 1, so we have some feedback on clicking the
+ * PanelHomeButton, and especially because we don't have any other way of
+ * launching non-launcher apps right now
+ */
+ GdkAppLaunchContext *context;
+ GError *error = NULL;
+
+ context = gdk_app_launch_context_new ();
+ gdk_app_launch_context_set_screen (context, gdk_screen_get_default ());
+ gdk_app_launch_context_set_timestamp (context, GDK_CURRENT_TIME);
+
+ if (!g_app_info_launch_default_for_uri (APPS_URI,
+ (GAppLaunchContext *)context,
+ &error))
+ {
+ g_warning ("Unable to launcher applications folder: %s",
+ error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (context);
+ }
+}
+
+void
+PlacesController::RecvMouseDownOutsideOfView (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ Hide ();
+}
+
+/* Introspection */
+const gchar *
+PlacesController::GetName ()
+{
+ return "PlacesController";
+}
+
+void
+PlacesController::AddProperties (GVariantBuilder *builder)
+{
+}
+
diff --git a/src/PlacesController.h b/src/PlacesController.h
new file mode 100644
index 000000000..0b5dbd841
--- /dev/null
+++ b/src/PlacesController.h
@@ -0,0 +1,56 @@
+/*
+ * 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: Gordon Allott <gord.allott@canonical.com>
+ */
+
+#ifndef PLACES_CONTROLLER_H
+#define PLACES_CONTROLLER_H
+
+#include <Nux/TextureArea.h>
+#include <Nux/View.h>
+#include "Nux/Layout.h"
+#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/GraphicsEngine.h>
+
+#include "PlacesView.h"
+#include "Introspectable.h"
+
+class PlacesController : public Introspectable
+{
+public:
+ PlacesController ();
+ ~PlacesController ();
+
+ void Show ();
+ void Hide ();
+ void ToggleShowHide ();
+
+ PlacesView *_Window;
+protected:
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
+
+ static void ExternalActivation (GVariant *data, void *val);
+ static void WindowConfigureCallback(int WindowWidth, int WindowHeight,
+ nux::Geometry& geo, void *user_data);
+
+ void RecvMouseDownOutsideOfView (int x, int y, unsigned long button_flags, unsigned long key_flags);
+
+
+ nux::Layout *_Layout;
+};
+
+#endif // PLACES_CONTROLLER_H
diff --git a/src/PlacesView.cpp b/src/PlacesView.cpp
new file mode 100644
index 000000000..a4cc66e73
--- /dev/null
+++ b/src/PlacesView.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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: Gordon Allott <gord.allott@canonical.com>
+ */
+
+#include "config.h"
+
+#include "Nux/Nux.h"
+#include "NuxGraphics/GLThread.h"
+#include "UBusMessages.h"
+
+#include "PlacesView.h"
+
+NUX_IMPLEMENT_OBJECT_TYPE (PlacesView);
+
+PlacesView::PlacesView (NUX_FILE_LINE_DECL)
+: nux::BaseWindow("", NUX_FILE_LINE_PARAM)
+{
+ Hide ();
+}
+
+PlacesView::~PlacesView ()
+{
+
+}
+
+long PlacesView::ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
+{
+ long ret = TraverseInfo;
+ long ProcEvInfo = 0;
+
+ nux::IEvent window_event = ievent;
+ nux::Geometry base = GetGeometry();
+ window_event.e_x_root = base.x;
+ window_event.e_y_root = base.y;
+
+ // The child layout get the Mouse down button only if the MouseDown happened inside the client view Area
+ nux::Geometry viewGeometry = GetGeometry();
+
+ if (ievent.e_event == nux::NUX_MOUSE_PRESSED)
+ {
+ if (!viewGeometry.IsPointInside (ievent.e_x - ievent.e_x_root, ievent.e_y - ievent.e_y_root) )
+ {
+ ProcEvInfo = nux::eDoNotProcess;
+ }
+ }
+
+ // hide if outside our window
+ if (ievent.e_event == nux::NUX_MOUSE_PRESSED)
+ {
+ if (!(GetGeometry ().IsPointInside (ievent.e_x, ievent.e_y)))
+ {
+ Hide ();
+ return nux::eMouseEventSolved;
+ }
+ }
+
+ return ret;
+}
+
+void PlacesView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
+{
+ nux::Color *color = new nux::Color (0.9, 0.3, 0.1, 1.0);
+ nux::GetPainter ().Paint2DQuadColor (GfxContext, GetGeometry (), *color);
+}
+
+
+void PlacesView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
+{
+
+}
+
+void PlacesView::PostDraw (nux::GraphicsEngine &GfxContext, bool force_draw)
+{
+
+}
+
+void PlacesView::ShowWindow (bool b, bool start_modal)
+{
+ nux::BaseWindow::ShowWindow (b, start_modal);
+}
+
+void PlacesView::Show ()
+{
+ if (IsVisible ())
+ return;
+
+ // FIXME: ShowWindow shouldn't need to be called first
+ ShowWindow (true, false);
+ EnableInputWindow (true, 1);
+ GrabPointer ();
+ NeedRedraw ();
+}
+
+void PlacesView::Hide ()
+{
+ if (!IsVisible ())
+ return;
+
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false, false);
+}
+
+
+/* Introspection */
+const gchar *
+PlacesView::GetName ()
+{
+ return "PlacesView";
+}
+
+void
+PlacesView::AddProperties (GVariantBuilder *builder)
+{
+}
diff --git a/src/PlacesView.h b/src/PlacesView.h
new file mode 100644
index 000000000..43271f503
--- /dev/null
+++ b/src/PlacesView.h
@@ -0,0 +1,54 @@
+/*
+ * 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: Gordon Allott <gord.allott@canonical.com>
+ */
+
+#ifndef PLACES_VIEW_H
+#define PLACES_VIEW_H
+
+#include <Nux/Nux.h>
+#include <Nux/View.h>
+#include <NuxImage/CairoGraphics.h>
+#include "NuxGraphics/GraphicsEngine.h"
+#include "Nux/AbstractPaintLayer.h"
+#include <Nux/BaseWindow.h>
+
+#include "Introspectable.h"
+
+class PlacesView : public nux::BaseWindow, public Introspectable
+{
+ NUX_DECLARE_OBJECT_TYPE (PlacesView, nux::BaseWindow);
+public:
+ PlacesView (NUX_FILE_LINE_PROTO);
+ ~PlacesView ();
+
+ 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);
+ virtual void ShowWindow (bool b, bool start_modal = false);
+
+ void Show ();
+ void Hide ();
+
+protected:
+
+ const gchar* GetName ();
+ void AddProperties (GVariantBuilder *builder);
+};
+
+#endif // PANEL_HOME_BUTTON_H
+
diff --git a/src/PluginAdapter.cpp b/src/PluginAdapter.cpp
index 535793724..9d5caf14d 100644
--- a/src/PluginAdapter.cpp
+++ b/src/PluginAdapter.cpp
@@ -17,6 +17,7 @@
*/
#include <glib.h>
+#include <scale/scale.h>
#include "PluginAdapter.h"
PluginAdapter * PluginAdapter::_default = 0;
@@ -25,28 +26,90 @@ PluginAdapter * PluginAdapter::_default = 0;
PluginAdapter *
PluginAdapter::Default ()
{
- if (!_default)
- return 0;
- return _default;
+ if (!_default)
+ return 0;
+ return _default;
}
/* static */
void
PluginAdapter::Initialize (CompScreen *screen)
{
- _default = new PluginAdapter (screen);
+ _default = new PluginAdapter (screen);
}
PluginAdapter::PluginAdapter(CompScreen *screen)
{
- m_Screen = screen;
- m_ExpoAction = 0;
- m_ScaleAction = 0;
+ m_Screen = screen;
+ m_ExpoAction = 0;
+ m_ScaleAction = 0;
}
PluginAdapter::~PluginAdapter()
{
+}
+
+void
+PluginAdapter::NotifyResized (CompWindow *window, int x, int y, int w, int h)
+{
+ window_resized.emit (window);
+}
+
+void
+PluginAdapter::NotifyMoved (CompWindow *window, int x, int y)
+{
+ window_moved.emit (window);
+}
+
+void
+PluginAdapter::NotifyStateChange (CompWindow *window, unsigned int state, unsigned int last_state)
+{
+ if (!(last_state & MAXIMIZE_STATE) && (state & MAXIMIZE_STATE))
+ {
+ PluginAdapter::window_maximized.emit (window);
+ WindowManager::window_maximized.emit (window->id ());
+ }
+ else if ((last_state & MAXIMIZE_STATE) && !(state & MAXIMIZE_STATE))
+ {
+ PluginAdapter::window_restored.emit (window);
+ WindowManager::window_restored.emit (window->id ());
+ }
+}
+void
+PluginAdapter::Notify (CompWindow *window, CompWindowNotify notify)
+{
+ switch (notify)
+ {
+ case CompWindowNotifyMinimize:
+ window_minimized.emit (window);
+ break;
+ case CompWindowNotifyUnminimize:
+ window_unminimized.emit (window);
+ break;
+ case CompWindowNotifyShade:
+ window_shaded.emit (window);
+ break;
+ case CompWindowNotifyUnshade:
+ window_unshaded.emit (window);
+ break;
+ case CompWindowNotifyHide:
+ window_hidden.emit (window);
+ break;
+ case CompWindowNotifyShow:
+ window_shown.emit (window);
+ break;
+ case CompWindowNotifyMap:
+ PluginAdapter::window_mapped.emit (window);
+ WindowManager::window_mapped.emit (window->id ());
+ break;
+ case CompWindowNotifyUnmap:
+ PluginAdapter::window_unmapped.emit (window);
+ WindowManager::window_unmapped.emit (window->id ());
+ break;
+ default:
+ break;
+ }
}
void
@@ -111,6 +174,35 @@ PluginAdapter::InitiateScale (std::string *match)
m_ScaleAction->initiate () (m_ScaleAction, 0, argument);
}
+bool
+PluginAdapter::IsScaleActive ()
+{
+ SCALE_SCREEN(m_Screen);
+ return (m_ScaleAction && ss && ss->hasGrab ());
+}
+
+void
+PluginAdapter::TerminateScale ()
+{
+ if (!IsScaleActive ())
+ return;
+
+ CompOption::Value value;
+ CompOption::Type type;
+ CompOption::Vector argument;
+ char *name;
+
+ name = (char *) "root";
+ type = CompOption::TypeInt;
+ value.set ((int) m_Screen->root ());
+
+ CompOption arg = CompOption (name, type);
+ arg.set (value);
+ argument.push_back (arg);
+
+ m_ScaleAction->terminate () (m_ScaleAction, 0, argument);
+}
+
void
PluginAdapter::InitiateExpo ()
{
@@ -132,3 +224,68 @@ PluginAdapter::InitiateExpo ()
m_ExpoAction->initiate () (m_ExpoAction, 0, argument);
}
+
+// WindowManager implementation
+bool
+PluginAdapter::IsWindowMaximized (guint xid)
+{
+ Window win = (Window)xid;
+ CompWindow *window;
+
+ window = m_Screen->findWindow (win);
+ if (window)
+ {
+ return window->state () & MAXIMIZE_STATE;
+ }
+
+ return false;
+}
+
+bool
+PluginAdapter::IsWindowDecorated (guint32 xid)
+{
+ Window win = (Window)xid;
+ CompWindow *window;
+
+ window = m_Screen->findWindow (win);
+ if (window)
+ {
+ unsigned int decor = window->mwmDecor ();
+
+ return decor & (MwmDecorAll | MwmDecorTitle);
+ }
+ return true;
+}
+
+void
+PluginAdapter::Restore (guint32 xid)
+{
+ Window win = (Window)xid;
+ CompWindow *window;
+
+ window = m_Screen->findWindow (win);
+ if (window)
+ window->maximize (0);
+}
+
+void
+PluginAdapter::Minimize (guint32 xid)
+{
+ Window win = (Window)xid;
+ CompWindow *window;
+
+ window = m_Screen->findWindow (win);
+ if (window)
+ window->minimize ();
+}
+
+void
+PluginAdapter::Close (guint32 xid)
+{
+ Window win = (Window)xid;
+ CompWindow *window;
+
+ window = m_Screen->findWindow (win);
+ if (window)
+ window->close (CurrentTime);
+}
diff --git a/src/PluginAdapter.h b/src/PluginAdapter.h
index e268c3848..b1764124b 100644
--- a/src/PluginAdapter.h
+++ b/src/PluginAdapter.h
@@ -24,7 +24,9 @@
#include <sigc++/sigc++.h>
-class PluginAdapter : public sigc::trackable
+#include "WindowManager.h"
+
+class PluginAdapter : public sigc::trackable, public WindowManager
{
public:
static PluginAdapter * Default ();
@@ -40,9 +42,38 @@ public:
void SetExpoAction (CompAction *expo);
void InitiateScale (std::string *match);
+
+ bool IsScaleActive ();
+
+ void TerminateScale ();
void InitiateExpo ();
+ void Notify (CompWindow *window, CompWindowNotify notify);
+ void NotifyMoved (CompWindow *window, int x, int y);
+ void NotifyResized (CompWindow *window, int x, int y, int w, int h);
+ void NotifyStateChange (CompWindow *window, unsigned int state, unsigned int last_state);
+
+ // WindowManager implementation
+ bool IsWindowMaximized (guint xid);
+ bool IsWindowDecorated (guint xid);
+ void Restore (guint32 xid);
+ void Minimize (guint32 xid);
+ void Close (guint32 xid);
+
+ sigc::signal<void, CompWindow *> window_maximized;
+ sigc::signal<void, CompWindow *> window_restored;
+ sigc::signal<void, CompWindow *> window_minimized;
+ sigc::signal<void, CompWindow *> window_unminimized;
+ sigc::signal<void, CompWindow *> window_shaded;
+ sigc::signal<void, CompWindow *> window_unshaded;
+ sigc::signal<void, CompWindow *> window_mapped;
+ sigc::signal<void, CompWindow *> window_unmapped;
+ sigc::signal<void, CompWindow *> window_shown;
+ sigc::signal<void, CompWindow *> window_hidden;
+ sigc::signal<void, CompWindow *> window_resized;
+ sigc::signal<void, CompWindow *> window_moved;
+
protected:
PluginAdapter(CompScreen *screen);
diff --git a/src/QuicklistManager.cpp b/src/QuicklistManager.cpp
new file mode 100644
index 000000000..940378953
--- /dev/null
+++ b/src/QuicklistManager.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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: Jamal Fanaian <j@jamalfanaian.com>
+ */
+
+#include "Nux/Nux.h"
+#include "Nux/BaseWindow.h"
+#include "Nux/VLayout.h"
+#include "Nux/WindowCompositor.h"
+#include "QuicklistView.h"
+#include "QuicklistManager.h"
+
+QuicklistManager * QuicklistManager::_default = 0;
+
+/* static */
+QuicklistManager *QuicklistManager::Default ()
+{
+ if (!_default)
+ _default = new QuicklistManager ();
+ return _default;
+}
+
+QuicklistManager::QuicklistManager ()
+{
+ _current_quicklist = 0;
+}
+
+QuicklistManager::~QuicklistManager ()
+{
+}
+
+QuicklistView *QuicklistManager::Current ()
+{
+ return _current_quicklist;
+}
+
+void QuicklistManager::RegisterQuicklist (QuicklistView *quicklist)
+{
+ std::list<QuicklistView*>::iterator it;
+
+ if (std::find (_quicklist_list.begin(), _quicklist_list.end(), quicklist) != _quicklist_list.end()) {
+ // quicklist has already been registered
+ g_warning ("Attempted to register a quicklist that was previously registered");
+ return;
+ }
+
+ _quicklist_list.push_back (quicklist);
+
+ quicklist->sigVisible.connect (sigc::mem_fun (this, &QuicklistManager::RecvShowQuicklist));
+ quicklist->sigHidden.connect (sigc::mem_fun (this, &QuicklistManager::RecvHideQuicklist));
+}
+
+void QuicklistManager::ShowQuicklist (QuicklistView *quicklist, int tip_x,
+ int tip_y, bool hide_existing_if_open)
+{
+ if (_current_quicklist == quicklist)
+ {
+ // this quicklist is already active
+ // do we want to still redraw in case the position has changed?
+ return;
+ }
+
+ if (hide_existing_if_open && _current_quicklist)
+ {
+ HideQuicklist (_current_quicklist);
+ }
+
+ quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
+}
+
+void QuicklistManager::HideQuicklist (QuicklistView *quicklist)
+{
+ quicklist->Hide();
+}
+
+void QuicklistManager::RecvShowQuicklist (nux::BaseWindow *window)
+{
+ QuicklistView *quicklist = (QuicklistView*) window;
+
+ _current_quicklist = quicklist;
+
+ quicklist_opened.emit (quicklist);
+}
+
+void QuicklistManager::RecvHideQuicklist (nux::BaseWindow *window)
+{
+ QuicklistView *quicklist = (QuicklistView*) window;
+
+ if (_current_quicklist == quicklist)
+ {
+ _current_quicklist = 0;
+ }
+
+ quicklist_closed.emit (quicklist);
+}
+
diff --git a/src/QuicklistManager.h b/src/QuicklistManager.h
new file mode 100644
index 000000000..63a271212
--- /dev/null
+++ b/src/QuicklistManager.h
@@ -0,0 +1,52 @@
+/*
+ * 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: Jamal Fanaian <j@jamalfanaian.com>
+ */
+
+#ifndef QUICKLISTMANAGER_H
+#define QUICKLISTMANAGER_H
+
+class QuicklistManager : public sigc::trackable
+{
+public:
+ static QuicklistManager *Default ();
+
+ QuicklistManager ();
+
+ ~QuicklistManager ();
+
+ QuicklistView *Current ();
+
+ void RegisterQuicklist (QuicklistView *quicklist);
+ void ShowQuicklist (QuicklistView *quicklist, int tip_x, int tip_y, bool hide_existing_if_open = true);
+ void HideQuicklist (QuicklistView *quicklist);
+
+ void RecvShowQuicklist (nux::BaseWindow *window);
+ void RecvHideQuicklist (nux::BaseWindow *window);
+
+ sigc::signal<void, QuicklistView*> quicklist_opened;
+ sigc::signal<void, QuicklistView*> quicklist_closed;
+
+private:
+ static QuicklistManager *_default;
+
+ std::list<QuicklistView*> _quicklist_list;
+ QuicklistView *_current_quicklist;
+
+};
+
+#endif
+
diff --git a/src/QuicklistView.cpp b/src/QuicklistView.cpp
index b1cf1ff01..f389ab15d 100644
--- a/src/QuicklistView.cpp
+++ b/src/QuicklistView.cpp
@@ -151,7 +151,7 @@ void QuicklistView::ShowQuicklistWithTipAt (int anchor_tip_x, int anchor_tip_y)
SetBaseX (x);
SetBaseY (y);
- ShowWindow (true);
+ Show ();
}
void QuicklistView::ShowWindow (bool b, bool start_modal)
@@ -159,6 +159,31 @@ void QuicklistView::ShowWindow (bool b, bool start_modal)
BaseWindow::ShowWindow (b, start_modal);
}
+void QuicklistView::Show ()
+{
+ if (!IsVisible())
+ {
+ // FIXME: ShowWindow shouldn't need to be called first
+ ShowWindow (true);
+ EnableInputWindow (true, 1);
+ GrabPointer ();
+ NeedRedraw ();
+ }
+}
+
+void QuicklistView::Hide ()
+{
+ if (IsVisible() && !_enable_quicklist_for_testing)
+ {
+ CancelItemsPrelightStatus ();
+ CaptureMouseDownAnyWhereElse (false);
+ ForceStopFocus (1, 1);
+ UnGrabPointer ();
+ EnableInputWindow (false);
+ ShowWindow (false);
+ }
+}
+
long QuicklistView::ProcessEvent (nux::IEvent& ievent, long TraverseInfo, long ProcessEventInfo)
{
long ret = TraverseInfo;
@@ -198,36 +223,14 @@ long QuicklistView::ProcessEvent (nux::IEvent& ievent, long TraverseInfo, long P
else
{
_mouse_down = false;
- if (IsVisible ())
- {
- if (!_enable_quicklist_for_testing)
- {
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
- }
+ Hide ();
return nux::eMouseEventSolved;
}
}
else if ((ievent.e_event == nux::NUX_MOUSE_RELEASED) && _mouse_down)
{
_mouse_down = false;
- if (IsVisible ())
- {
- if (!_enable_quicklist_for_testing)
- {
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
- }
+ Hide ();
return nux::eMouseEventSolved;
}
@@ -418,15 +421,7 @@ 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 ());
- if (!_enable_quicklist_for_testing)
- {
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
+ Hide ();
}
}
@@ -474,17 +469,9 @@ 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 ());
-
- if (!_enable_quicklist_for_testing)
- {
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
- }
+
+ Hide ();
+ }
}
void QuicklistView::CancelItemsPrelightStatus ()
@@ -570,15 +557,7 @@ void QuicklistView::RecvMouseClick (int x, int y, unsigned long button_flags, un
{
if (IsVisible ())
{
- if (!_enable_quicklist_for_testing)
- {
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
+ Hide ();
}
}
@@ -594,18 +573,7 @@ void QuicklistView::RecvMouseDrag (int x, int y, int dx, int dy, unsigned long b
void QuicklistView::RecvMouseDownOutsideOfQuicklist (int x, int y, unsigned long button_flags, unsigned long key_flags)
{
- if (IsVisible ())
- {
- if (!_enable_quicklist_for_testing)
- {
- CancelItemsPrelightStatus ();
- CaptureMouseDownAnyWhereElse (false);
- ForceStopFocus (1, 1);
- UnGrabPointer ();
- EnableInputWindow (false);
- ShowWindow (false);
- }
- }
+ Hide ();
}
void QuicklistView::RemoveAllMenuItem ()
diff --git a/src/QuicklistView.h b/src/QuicklistView.h
index ada4d9706..26974e908 100644
--- a/src/QuicklistView.h
+++ b/src/QuicklistView.h
@@ -80,6 +80,9 @@ public:
void ShowQuicklistWithTipAt (int anchor_tip_x, int anchor_tip_y);
virtual void ShowWindow (bool b, bool StartModal = false);
+
+ void Show ();
+ void Hide ();
int GetNumItems ();
QuicklistMenuItem* GetNthItems (int index);
diff --git a/src/SimpleLauncherIcon.cpp b/src/SimpleLauncherIcon.cpp
index c61d78956..732710c67 100644
--- a/src/SimpleLauncherIcon.cpp
+++ b/src/SimpleLauncherIcon.cpp
@@ -21,6 +21,7 @@
#include "SimpleLauncherIcon.h"
#include "Launcher.h"
+#include "PluginAdapter.h"
SimpleLauncherIcon::SimpleLauncherIcon (Launcher* IconManager)
: LauncherIcon(IconManager)
@@ -54,6 +55,8 @@ SimpleLauncherIcon::OnMouseUp (int button)
void
SimpleLauncherIcon::OnMouseClick (int button)
{
+ if (button == 1)
+ PluginAdapter::Default ()->TerminateScale ();
}
void
diff --git a/src/SimpleLauncherIcon.h b/src/SimpleLauncherIcon.h
index 7c3cdf7cb..b4359e26f 100644
--- a/src/SimpleLauncherIcon.h
+++ b/src/SimpleLauncherIcon.h
@@ -27,7 +27,7 @@ class SimpleLauncherIcon : public LauncherIcon
{
public:
SimpleLauncherIcon(Launcher* IconManager);
- ~SimpleLauncherIcon();
+ virtual ~SimpleLauncherIcon();
/* override */
nux::BaseTexture * GetTextureForSize (int size);
diff --git a/src/TrashLauncherIcon.cpp b/src/TrashLauncherIcon.cpp
index 24c24ba9b..85ff22d01 100644
--- a/src/TrashLauncherIcon.cpp
+++ b/src/TrashLauncherIcon.cpp
@@ -50,6 +50,8 @@ TrashLauncherIcon::~TrashLauncherIcon()
void
TrashLauncherIcon::OnMouseClick (int button)
{
+ SimpleLauncherIcon::OnMouseClick (button);
+
if (button == 1)
{
GError *error = NULL;
diff --git a/src/UBusMessages.h b/src/UBusMessages.h
new file mode 100644
index 000000000..a4b94ff34
--- /dev/null
+++ b/src/UBusMessages.h
@@ -0,0 +1,27 @@
+/*
+ * 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: Gordon Allott <gord.allott@canonical.com>
+ */
+#ifndef UBUS_MESSAGES_H
+#define UBUS_MESSAGES_H
+
+
+// Add ubus messages here so we can easily export them around the place
+// keep ordered
+
+#define UBUS_HOME_BUTTON_ACTIVATED "PANEL_HOME_ACTIVATED"
+
+#endif // UBUS_MESSAGES_H
diff --git a/src/WindowButtons.cpp b/src/WindowButtons.cpp
new file mode 100644
index 000000000..53a984f29
--- /dev/null
+++ b/src/WindowButtons.cpp
@@ -0,0 +1,254 @@
+/*
+ * 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/HLayout.h"
+#include "Nux/VLayout.h"
+#include "Nux/Button.h"
+
+#include "NuxGraphics/GLThread.h"
+#include "Nux/BaseWindow.h"
+#include "Nux/WindowCompositor.h"
+
+#include "WindowButtons.h"
+
+#include <glib.h>
+
+
+// FIXME: This will be all automatic in the future
+#define AMBIANCE "/usr/share/themes/Ambiance/metacity-1"
+
+enum
+{
+ BUTTON_CLOSE=0,
+ BUTTON_MINIMISE,
+ BUTTON_UNMAXIMISE
+};
+
+class WindowButton : public nux::Button
+{
+ // A single window button
+public:
+ WindowButton (int type)
+ : nux::Button ("X", NUX_TRACKER_LOCATION),
+ _normal_tex (NULL),
+ _prelight_tex (NULL),
+ _pressed_tex (NULL)
+ {
+ if (type == BUTTON_CLOSE)
+ LoadImages ("close");
+ else if (type == BUTTON_MINIMISE)
+ LoadImages ("minimize");
+ else
+ LoadImages ("unmaximize");
+ }
+
+ ~WindowButton ()
+ {
+ _normal_tex->UnReference ();
+ _prelight_tex->UnReference ();
+ _pressed_tex->UnReference ();
+ }
+
+ void Draw (nux::GraphicsEngine &GfxContext, bool force_draw)
+ {
+ nux::Geometry geo = GetGeometry ();
+ nux::BaseTexture *tex;
+ nux::TexCoordXForm texxform;
+
+ GfxContext.PushClippingRectangle (geo);
+
+ if (HasMouseFocus ())
+ {
+ tex = _pressed_tex;
+ }
+ else if (IsMouseInside ())
+ {
+ tex = _prelight_tex;
+ }
+ else
+ {
+ tex = _normal_tex;
+ }
+
+ 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 (tex)
+ GfxContext.QRP_GLSL_1Tex (geo.x,
+ geo.y,
+ (float)geo.width,
+ (float)geo.height,
+ tex->GetDeviceTexture (),
+ texxform,
+ nux::Color::White);
+ GfxContext.GetRenderStates ().SetSeparateBlend (false,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE_MINUS_DST_ALPHA,
+ GL_ONE);
+ GfxContext.PopClippingRectangle();
+ }
+
+ void LoadImages (const char *name)
+ {
+ //FIXME: We need to somehow be theme aware. Or, at least support the themes
+ // we know and have a good default fallback
+ gchar *filename;
+ GError *error = NULL;
+ GdkPixbuf *_normal;
+ GdkPixbuf *_prelight;
+ GdkPixbuf *_pressed;
+
+ filename = g_strdup_printf ("%s/%s.png", AMBIANCE, name);
+ _normal = gdk_pixbuf_new_from_file (filename, &error);
+ if (error)
+ {
+ g_warning ("Unable to load window button %s: %s", filename, error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ else
+ _normal_tex = nux::CreateTextureFromPixbuf (_normal);
+ g_free (filename);
+ g_object_unref (_normal);
+
+ filename = g_strdup_printf ("%s/%s_focused_prelight.png", AMBIANCE, name);
+ _prelight = gdk_pixbuf_new_from_file (filename, &error);
+ if (error)
+ {
+ g_warning ("Unable to load window button %s: %s", filename, error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ else
+ _prelight_tex = nux::CreateTextureFromPixbuf (_prelight);
+ g_free (filename);
+ g_object_unref (_prelight);
+
+ filename = g_strdup_printf ("%s/%s_focused_pressed.png", AMBIANCE, name);
+ _pressed = gdk_pixbuf_new_from_file (filename, &error);
+ if (error)
+ {
+ g_warning ("Unable to load window button %s: %s", name, error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ else
+ _pressed_tex = nux::CreateTextureFromPixbuf (_pressed);
+ g_free (filename);
+ g_object_unref (_pressed);
+
+ if (_normal_tex)
+ SetMinimumSize (_normal_tex->GetWidth (), _normal_tex->GetHeight ());
+ }
+
+private:
+ nux::BaseTexture *_normal_tex;
+ nux::BaseTexture *_prelight_tex;
+ nux::BaseTexture *_pressed_tex;
+};
+
+
+WindowButtons::WindowButtons ()
+: HLayout ("", NUX_TRACKER_LOCATION)
+{
+ WindowButton *but;
+
+ but = new WindowButton (BUTTON_CLOSE);
+ AddView (but, 0, nux::eCenter, nux::eFix);
+ but->sigClick.connect (sigc::mem_fun (this, &WindowButtons::OnCloseClicked));
+ but->OnMouseEnter.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseEnter));
+ but->OnMouseLeave.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseLeave));
+
+ but = new WindowButton (BUTTON_MINIMISE);
+ AddView (but, 0, nux::eCenter, nux::eFix);
+ but->sigClick.connect (sigc::mem_fun (this, &WindowButtons::OnMinimizeClicked));
+ but->OnMouseEnter.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseEnter));
+ but->OnMouseLeave.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseLeave));
+
+ but = new WindowButton (BUTTON_UNMAXIMISE);
+ AddView (but, 0, nux::eCenter, nux::eFix);
+ but->sigClick.connect (sigc::mem_fun (this, &WindowButtons::OnRestoreClicked));
+ but->OnMouseEnter.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseEnter));
+ but->OnMouseLeave.connect (sigc::mem_fun (this, &WindowButtons::RecvMouseLeave));
+
+ SetContentDistribution (nux::eStackLeft);
+}
+
+
+WindowButtons::~WindowButtons ()
+{
+}
+
+void
+WindowButtons::OnCloseClicked ()
+{
+ close_clicked.emit ();
+}
+
+void
+WindowButtons::OnMinimizeClicked ()
+{
+ minimize_clicked.emit ();
+}
+
+void
+WindowButtons::OnRestoreClicked ()
+{
+ restore_clicked.emit ();
+}
+
+const gchar *
+WindowButtons::GetName ()
+{
+ return "window-buttons";
+}
+
+const gchar *
+WindowButtons::GetChildsName ()
+{
+ return "";
+}
+
+void
+WindowButtons::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));
+}
+
+void WindowButtons::RecvMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ redraw_signal.emit ();
+}
+
+void WindowButtons::RecvMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags)
+{
+ redraw_signal.emit ();
+}
+
+
diff --git a/src/WindowButtons.h b/src/WindowButtons.h
new file mode 100644
index 000000000..0f6b3247c
--- /dev/null
+++ b/src/WindowButtons.h
@@ -0,0 +1,63 @@
+/*
+ * 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 WINDOW_BUTTONS_H
+#define WINDOW_BUTTONS_H
+
+#include <Nux/View.h>
+
+#include "Introspectable.h"
+
+class WindowButtons : public nux::HLayout, public Introspectable
+{
+ // These are the [close][minimize][restore] buttons on the panel when there
+ // is a maximized window
+
+public:
+ WindowButtons ();
+ ~WindowButtons ();
+
+ sigc::signal<void> close_clicked;
+ sigc::signal<void> minimize_clicked;
+ sigc::signal<void> restore_clicked;
+ sigc::signal<void> redraw_signal;
+
+protected:
+ const gchar * GetName ();
+ const gchar * GetChildsName ();
+ void AddProperties (GVariantBuilder *builder);
+
+
+ // For testing the buttons
+ void RecvMouseDown (int x, int y, unsigned long button_flags, unsigned long key_flags);
+ void RecvMouseUp (int x, int y, unsigned long button_flags, unsigned long key_flags);
+ void RecvMouseEnter (int x, int y, unsigned long button_flags, unsigned long key_flags);
+ void RecvMouseLeave (int x, int y, unsigned long button_flags, unsigned long key_flags);
+ void RecvMouseClick (int x, int y, unsigned long button_flags, unsigned long key_flags);
+ void RecvMouseMove (int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
+
+private:
+ void OnCloseClicked ();
+ void OnMinimizeClicked ();
+ void OnRestoreClicked ();
+
+private:
+ nux::HLayout *_layout;
+};
+
+#endif
diff --git a/src/WindowManager.cpp b/src/WindowManager.cpp
new file mode 100644
index 000000000..05e835f3b
--- /dev/null
+++ b/src/WindowManager.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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 "WindowManager.h"
+
+#include <gdk/gdkx.h>
+
+typedef struct {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long input_mode;
+ unsigned long status;
+} MotifWmHints, MwmHints;
+
+#define MWM_HINTS_FUNCTIONS (1L << 0)
+#define MWM_HINTS_DECORATIONS (1L << 1)
+#define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS"
+
+static void gdk_window_set_mwm_hints (Window xid,
+ MotifWmHints *new_hints);
+
+
+static WindowManager *window_manager = NULL;
+
+class WindowManagerDummy : public WindowManager
+{
+ bool IsWindowMaximized (guint32 xid)
+ {
+ return false;
+ }
+
+ bool IsWindowDecorated (guint32 xid)
+ {
+ return true;
+ }
+
+ void Restore (guint32 xid)
+ {
+ g_debug ("%s", G_STRFUNC);
+ }
+
+ void Minimize (guint32 xid)
+ {
+ g_debug ("%s", G_STRFUNC);
+ }
+
+ void Close (guint32 xid)
+ {
+ g_debug ("%s", G_STRFUNC);
+ }
+};
+
+WindowManager *
+WindowManager::Default ()
+{
+ if (!window_manager)
+ window_manager = new WindowManagerDummy ();
+
+ return window_manager;
+}
+
+void
+WindowManager::SetDefault (WindowManager *manager)
+{
+ window_manager = manager;
+}
+
+void
+WindowManager::Decorate (guint32 xid)
+{
+ MotifWmHints hints = { 0 };
+
+ hints.flags = MWM_HINTS_DECORATIONS;
+ hints.decorations = GDK_DECOR_ALL;
+
+ gdk_window_set_mwm_hints (xid, &hints);
+}
+
+void
+WindowManager::Undecorate (guint32 xid)
+{
+ MotifWmHints hints = { 0 };
+
+ hints.flags = MWM_HINTS_DECORATIONS;
+ hints.decorations = 0;
+
+ gdk_window_set_mwm_hints (xid, &hints);
+}
+
+/*
+ * Copied over C code
+ */
+static void
+gdk_window_set_mwm_hints (Window xid,
+ MotifWmHints *new_hints)
+{
+ GdkDisplay *display = gdk_display_get_default();
+ Atom hints_atom = None;
+ guchar *data = NULL;
+ MotifWmHints *hints = NULL;
+ Atom type = None;
+ gint format;
+ gulong nitems;
+ gulong bytes_after;
+
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ hints_atom = gdk_x11_get_xatom_by_name_for_display (display,
+ _XA_MOTIF_WM_HINTS);
+
+ gdk_error_trap_push ();
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ xid,
+ hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
+ False, AnyPropertyType, &type, &format, &nitems,
+ &bytes_after, &data);
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ {
+ g_debug ("ERROR: Cannot set decorations");
+ return;
+ }
+
+ if (type != hints_atom || !data)
+ hints = new_hints;
+ else
+ {
+ hints = (MotifWmHints *)data;
+
+ if (new_hints->flags & MWM_HINTS_FUNCTIONS)
+ {
+ hints->flags |= MWM_HINTS_FUNCTIONS;
+ hints->functions = new_hints->functions;
+ }
+ if (new_hints->flags & MWM_HINTS_DECORATIONS)
+ {
+ hints->flags |= MWM_HINTS_DECORATIONS;
+ hints->decorations = new_hints->decorations;
+ }
+ }
+
+ gdk_error_trap_push ();
+ XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+ xid,
+ hints_atom, hints_atom, 32, PropModeReplace,
+ (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ {
+ g_debug ("ERROR: Setting decorations");
+ }
+
+ if (data)
+ XFree (data);
+}
diff --git a/src/WindowManager.h b/src/WindowManager.h
new file mode 100644
index 000000000..429aad2b4
--- /dev/null
+++ b/src/WindowManager.h
@@ -0,0 +1,57 @@
+/*
+ * 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 WINDOW_MANAGER_H
+#define WINDOW_MANAGER_H
+
+#include <glib.h>
+#include <sigc++/sigc++.h>
+
+class WindowManager
+{
+ // This is a glue interface that breaks the dependancy of Unity with Compiz
+ // Basically it has a default implementation that does nothing useful, but
+ // the idea is that unity.cpp uses SetDefault() early enough in it's
+ // initialization so the things that require it get a usable implementation
+ //
+ // Currently only the Panel uses it but hopefully we'll get more of
+ // PluginAdaptor features moved into here and also get the Launcher to use
+ // it.
+
+public:
+ static WindowManager * Default ();
+ static void SetDefault (WindowManager *manager);
+
+ virtual bool IsWindowMaximized (guint32 xid) = 0;
+ virtual bool IsWindowDecorated (guint32 xid) = 0;
+
+ virtual void Restore (guint32 xid) = 0;
+ virtual void Minimize (guint32 xid) = 0;
+ virtual void Close (guint32 xid) = 0;
+
+ virtual void Decorate (guint32 xid);
+ virtual void Undecorate (guint32 xid);
+
+ // Signals
+ sigc::signal<void, guint32> window_mapped;
+ sigc::signal<void, guint32> window_unmapped;
+ sigc::signal<void, guint32> window_maximized;
+ sigc::signal<void, guint32> window_restored;
+};
+
+#endif // WINDOW_MANAGER_H
diff --git a/src/unity.cpp b/src/unityshell.cpp
index d60902979..95d1d8191 100644
--- a/src/unity.cpp
+++ b/src/unityshell.cpp
@@ -31,7 +31,7 @@
#include "LauncherController.h"
#include "PluginAdapter.h"
#include "StartupNotifyService.h"
-#include "unity.h"
+#include "unityshell.h"
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
@@ -288,51 +288,28 @@ UnityWindow::glDraw (const GLMatrix &matrix,
void
UnityWindow::windowNotify (CompWindowNotify n)
{
- 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;
- }
-
+ PluginAdapter::Default ()->Notify (window, n);
window->windowNotify (n);
}
+void
+UnityWindow::stateChangeNotify (unsigned int lastState)
+{
+ PluginAdapter::Default ()->NotifyStateChange (window, window->state (), lastState);
+ window->stateChangeNotify (lastState);
+}
+
void
UnityWindow::moveNotify (int x, int y, bool immediate)
{
- uScreen->launcher->OnWindowMoved (window);
+ PluginAdapter::Default ()->NotifyMoved (window, x, y);
window->moveNotify (x, y, immediate);
}
void
UnityWindow::resizeNotify (int x, int y, int w, int h)
{
- uScreen->launcher->OnWindowResized (window);
+ PluginAdapter::Default ()->NotifyResized (window, x, y, w, h);
window->resizeNotify (x, y, w, h);
}
@@ -391,7 +368,7 @@ UnityScreen::optionChanged (CompOption *opt,
static gboolean
write_logger_data_to_disk (gpointer data)
{
- perf_timeline_logger_write_log (perf_timeline_logger_get_default (), "/tmp/unity-perf.log");
+ LOGGER_WRITE_LOG ("/tmp/unity-perf.log");
return FALSE;
}
@@ -417,6 +394,9 @@ UnityScreen::UnityScreen (CompScreen *screen) :
CompositeScreenInterface::setHandler (cScreen);
GLScreenInterface::setHandler (gScreen);
+ PluginAdapter::Initialize (screen);
+ WindowManager::SetDefault (PluginAdapter::Default ());
+
StartupNotifyService::Default ()->SetSnDisplay (screen->snDisplay (), screen->screenNum ());
nux::NuxInitialize (0);
@@ -432,12 +412,11 @@ UnityScreen::UnityScreen (CompScreen *screen) :
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);
+ g_timeout_add (5000, (GSourceFunc) write_logger_data_to_disk, NULL);
END_FUNCTION ();
}
@@ -517,6 +496,10 @@ void UnityScreen::initLauncher (nux::NThread* thread, void* InitData)
self->panelWindow->EnableInputWindow(true);
self->panelWindow->InputWindowEnableStruts(true);
LOGGER_END_PROCESS ("initLauncher-Panel");
+
+ /* Setup Places */
+ self->placesController = new PlacesController ();
+
g_timeout_add (2000, &UnityScreen::strutHackTimeout, self);
END_FUNCTION ();
diff --git a/src/unity.h b/src/unityshell.h
index cec421f57..6062e16d5 100644
--- a/src/unity.h
+++ b/src/unityshell.h
@@ -30,12 +30,13 @@
#include "Launcher.h"
#include "LauncherController.h"
#include "PanelView.h"
+#include "PlacesController.h"
#include "IntrospectionDBusInterface.h"
#include <Nux/WindowThread.h>
#include <sigc++/sigc++.h>
/* base screen class */
-class UnityScreen :
+class UnityScreen :
public Introspectable,
public sigc::trackable,
public ScreenInterface,
@@ -58,7 +59,7 @@ class UnityScreen :
CompositeScreen *cScreen;
GLScreen *gScreen;
- /* prepares nux for drawing */
+ /* prepares nux for drawing */
void
nuxPrologue ();
@@ -102,36 +103,37 @@ class UnityScreen :
const gchar* GetName ();
void AddProperties (GVariantBuilder *builder);
-
+
private:
static gboolean
initPluginActions (gpointer data);
-
+
static void
initLauncher (nux::NThread* thread, void* InitData);
-
+
void
damageNuxRegions();
-
- void
+
+ void
onRedrawRequested ();
-
- static void
+
+ static void
launcherWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void* user_data);
- static void
+ static void
panelWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void* user_data);
- static void
+ static void
initUnity(nux::NThread* thread, void* InitData);
- static gboolean
+ static gboolean
strutHackTimeout (gpointer data);
-
+
Launcher *launcher;
LauncherController *controller;
PanelView *panelView;
+ PlacesController *placesController;
nux::WindowThread *wt;
nux::BaseWindow *launcherWindow;
nux::BaseWindow *panelWindow;
@@ -161,9 +163,9 @@ class UnityWindow :
CompWindow *window;
GLWindow *gWindow;
-
+
/* basic window draw function */
- bool
+ bool
glDraw (const GLMatrix &matrix,
GLFragment::Attrib &attrib,
const CompRegion &region,
@@ -172,8 +174,10 @@ class UnityWindow :
void windowNotify (CompWindowNotify n);
void moveNotify (int x, int y, bool immediate);
-
+
void resizeNotify (int x, int y, int w, int h);
+
+ void stateChangeNotify (unsigned int lastState);
};
#define EX_SCREEN (screen) \