Blob Blame History Raw
From 3743256a1975c911f07043f20e1ff861ad14b7b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 20 May 2015 17:44:50 +0200
Subject: [PATCH 1/4] Add top-icons extension

---
 configure.ac                          |   5 +-
 extensions/top-icons/Makefile.am      |   3 +
 extensions/top-icons/extension.js     | 192 ++++++++++++++++++++++++++++++++++
 extensions/top-icons/metadata.json.in |  10 ++
 extensions/top-icons/stylesheet.css   |   1 +
 5 files changed, 209 insertions(+), 2 deletions(-)
 create mode 100644 extensions/top-icons/Makefile.am
 create mode 100644 extensions/top-icons/extension.js
 create mode 100644 extensions/top-icons/metadata.json.in
 create mode 100644 extensions/top-icons/stylesheet.css

diff --git a/configure.ac b/configure.ac
index 6b95674..90b54da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_SUBST([SHELL_VERSION])
 dnl keep this in alphabetic order
 CLASSIC_EXTENSIONS="apps-menu places-menu alternate-tab launch-new-instance window-list"
 DEFAULT_EXTENSIONS="$CLASSIC_EXTENSIONS drive-menu screenshot-window-sizer windowsNavigator workspace-indicator"
-ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows example native-window-placement systemMonitor user-theme"
+ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows example native-window-placement systemMonitor top-icons user-theme"
 AC_SUBST(CLASSIC_EXTENSIONS, [$CLASSIC_EXTENSIONS])
 AC_SUBST(ALL_EXTENSIONS, [$ALL_EXTENSIONS])
 AC_ARG_ENABLE([extensions],
@@ -66,7 +66,7 @@ for e in $enable_extensions; do
 					[AC_MSG_WARN([libgtop-2.0 not found, disabling systemMonitor])])
 			;;
 dnl		keep this in alphabetic order
-		alternate-tab|apps-menu|auto-move-windows|drive-menu|example|launch-new-instance|native-window-placement|places-menu|screenshot-window-sizer|user-theme|window-list|windowsNavigator|workspace-indicator)
+		alternate-tab|apps-menu|auto-move-windows|drive-menu|example|launch-new-instance|native-window-placement|places-menu|screenshot-window-sizer|top-icons|user-theme|window-list|windowsNavigator|workspace-indicator)
 			ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
 			;;
 		*)
@@ -89,6 +89,7 @@ AC_CONFIG_FILES([
   extensions/places-menu/Makefile
   extensions/screenshot-window-sizer/Makefile
   extensions/systemMonitor/Makefile
+  extensions/top-icons/Makefile
   extensions/user-theme/Makefile
   extensions/window-list/Makefile
   extensions/windowsNavigator/Makefile
diff --git a/extensions/top-icons/Makefile.am b/extensions/top-icons/Makefile.am
new file mode 100644
index 0000000..4650164
--- /dev/null
+++ b/extensions/top-icons/Makefile.am
@@ -0,0 +1,3 @@
+EXTENSION_ID = top-icons
+
+include ../../extension.mk
diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js
new file mode 100644
index 0000000..97f8c78
--- /dev/null
+++ b/extensions/top-icons/extension.js
@@ -0,0 +1,192 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+const Main = imports.ui.main;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Panel = imports.ui.panel;
+const PanelMenu = imports.ui.panelMenu;
+const Meta = imports.gi.Meta;
+const Mainloop = imports.mainloop;
+const NotificationDaemon = imports.ui.notificationDaemon;
+
+let trayAddedId = 0;
+let trayRemovedId = 0;
+let getSource = null;
+let icons = [];
+let notificationDaemon;
+
+function init() {
+    if (Main.legacyTray) {
+        notificationDaemon = Main.legacyTray;
+        NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS = imports.ui.legacyTray.STANDARD_TRAY_ICON_IMPLEMENTATIONS;
+    }
+    else if (Main.notificationDaemon._fdoNotificationDaemon) {
+        notificationDaemon = Main.notificationDaemon._fdoNotificationDaemon;
+        getSource = Lang.bind(notificationDaemon, NotificationDaemon.FdoNotificationDaemon.prototype._getSource);
+    }
+    else {
+        notificationDaemon = Main.notificationDaemon;
+        getSource = Lang.bind(notificationDaemon, NotificationDaemon.NotificationDaemon.prototype._getSource);
+    }
+}
+
+function enable() {
+    GLib.idle_add(GLib.PRIORITY_LOW, moveToTop);
+}
+
+function createSource (title, pid, ndata, sender, trayIcon) { 
+  if (trayIcon) {
+    onTrayIconAdded(this, trayIcon, title);
+    return null;
+  }
+
+  return getSource(title, pid, ndata, sender, trayIcon);
+};
+
+function onTrayIconAdded(o, icon, role) {
+    let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
+    if (NotificationDaemon.STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined)
+        return;
+
+    let buttonBox = new PanelMenu.ButtonBox();
+    let box = buttonBox.actor;
+    let parent = box.get_parent();
+
+    let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
+    let iconSize = Panel.PANEL_ICON_SIZE * scaleFactor;
+
+    icon.set_size(iconSize, iconSize);
+    box.add_actor(icon);
+
+    icon.reactive = true;
+
+    if (parent)
+        parent.remove_actor(box);
+
+    icons.push(icon);
+    Main.panel._rightBox.insert_child_at_index(box, 0);
+
+    let clickProxy = new St.Bin({ width: iconSize, height: iconSize });
+    clickProxy.reactive = true;
+    Main.uiGroup.add_actor(clickProxy);
+
+    icon._proxyAlloc = Main.panel._rightBox.connect('allocation-changed', function() {
+        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function() {
+            let [x, y] = icon.get_transformed_position();
+            clickProxy.set_position(x, y);
+        });
+    });
+
+    icon.connect("destroy", function() {
+        Main.panel._rightBox.disconnect(icon._proxyAlloc);
+        clickProxy.destroy();
+    });
+
+    clickProxy.connect('button-release-event', function(actor, event) {
+        icon.click(event);
+    });
+
+    icon._clickProxy = clickProxy;
+
+    /* Fixme: HACK */
+    Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function() {
+        let [x, y] = icon.get_transformed_position();
+        clickProxy.set_position(x, y);
+        return false;
+    });
+    let timerId = 0;
+    let i = 0;
+    timerId = Mainloop.timeout_add(500, function() {
+        icon.set_size(icon.width == iconSize ? iconSize - 1 : iconSize,
+                      icon.width == iconSize ? iconSize - 1 : iconSize);
+        i++;
+        if (i == 2)
+            Mainloop.source_remove(timerId);
+    });
+}
+
+function onTrayIconRemoved(o, icon) {
+    let parent = icon.get_parent();
+    parent.destroy();
+    icon.destroy();
+    icons.splice(icons.indexOf(icon), 1);
+}
+
+function moveToTop() {
+    notificationDaemon._trayManager.disconnect(notificationDaemon._trayIconAddedId);
+    notificationDaemon._trayManager.disconnect(notificationDaemon._trayIconRemovedId);
+    trayAddedId = notificationDaemon._trayManager.connect('tray-icon-added', onTrayIconAdded);
+    trayRemovedId = notificationDaemon._trayManager.connect('tray-icon-removed', onTrayIconRemoved);
+    
+    notificationDaemon._getSource = createSource;
+
+    let toDestroy = [];
+    if (notificationDaemon._sources) {
+        for (let i = 0; i < notificationDaemon._sources.length; i++) {
+            let source = notificationDaemon._sources[i];
+            if (!source.trayIcon)
+                continue;
+            let parent = source.trayIcon.get_parent();
+            parent.remove_actor(source.trayIcon);
+            onTrayIconAdded(this, source.trayIcon, source.initialTitle);
+            toDestroy.push(source);
+        }
+    }
+    else {
+        for (let i = 0; i < notificationDaemon._iconBox.get_n_children(); i++) {
+            let button = notificationDaemon._iconBox.get_child_at_index(i);
+            let icon = button.child;
+            button.remove_actor(icon);
+            onTrayIconAdded(this, icon, '');
+            toDestroy.push(button);
+        }
+    }
+
+    for (let i = 0; i < toDestroy.length; i++) {
+        toDestroy[i].destroy();
+    }
+}
+
+function moveToTray() {
+    if (trayAddedId != 0) {
+        notificationDaemon._trayManager.disconnect(trayAddedId);
+        trayAddedId = 0;
+    }
+
+    if (trayRemovedId != 0) {
+        notificationDaemon._trayManager.disconnect(trayRemovedId);
+        trayRemovedId = 0;
+    }
+    
+    notificationDaemon._trayIconAddedId = notificationDaemon._trayManager.connect('tray-icon-added',
+                                                Lang.bind(notificationDaemon, notificationDaemon._onTrayIconAdded));
+    notificationDaemon._trayIconRemovedId = notificationDaemon._trayManager.connect('tray-icon-removed',
+                                                Lang.bind(notificationDaemon, notificationDaemon._onTrayIconRemoved));
+
+    notificationDaemon._getSource = getSource;
+
+    for (let i = 0; i < icons.length; i++) {
+        let icon = icons[i];
+        let parent = icon.get_parent();
+        if (icon._clicked) {
+            icon.disconnect(icon._clicked);
+        }
+        icon._clicked = undefined;
+        if (icon._proxyAlloc) {
+            Main.panel._rightBox.disconnect(icon._proxyAlloc);
+        }
+        icon._clickProxy.destroy();
+        parent.remove_actor(icon);
+        parent.destroy();
+        notificationDaemon._onTrayIconAdded(notificationDaemon, icon);
+    }
+    
+    icons = [];
+}
+
+function disable() {
+    moveToTray();
+}
diff --git a/extensions/top-icons/metadata.json.in b/extensions/top-icons/metadata.json.in
new file mode 100644
index 0000000..f1e2436
--- /dev/null
+++ b/extensions/top-icons/metadata.json.in
@@ -0,0 +1,10 @@
+{
+"extension-id": "@extension_id@",
+"uuid": "@uuid@",
+"settings-schema": "@gschemaname@",
+"gettext-domain": "@gettext_domain@",
+"name": "Top Icons",
+"description": "Shows legacy tray icons on top",
+"shell-version": [ "@shell_current@" ],
+"url": "http://94.247.144.115/repo/topicons/"
+}
diff --git a/extensions/top-icons/stylesheet.css b/extensions/top-icons/stylesheet.css
new file mode 100644
index 0000000..25134b6
--- /dev/null
+++ b/extensions/top-icons/stylesheet.css
@@ -0,0 +1 @@
+/* This extensions requires no special styling */
-- 
2.7.2


From 5ae70e47ef5417e556b1c5ec5ecc456f3e3d8e38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 20 May 2015 18:05:41 +0200
Subject: [PATCH 2/4] Add dash-to-dock extension

---
 configure.ac                                       |    5 +-
 extensions/dash-to-dock/Makefile.am                |   32 +
 extensions/dash-to-dock/Settings.ui                | 1782 ++++++++++++++++++++
 extensions/dash-to-dock/dockedDash.js              | 1684 ++++++++++++++++++
 extensions/dash-to-dock/extension.js               |   52 +
 extensions/dash-to-dock/intellihide.js             |  278 +++
 extensions/dash-to-dock/media/four.svg             |  132 ++
 extensions/dash-to-dock/media/four_bottom.svg      |  133 ++
 extensions/dash-to-dock/media/four_rtl.svg         |  133 ++
 extensions/dash-to-dock/media/four_top.svg         |  133 ++
 extensions/dash-to-dock/media/logo.svg             |  561 ++++++
 extensions/dash-to-dock/media/one.svg              |  107 ++
 extensions/dash-to-dock/media/one_bottom.svg       |  108 ++
 extensions/dash-to-dock/media/one_rtl.svg          |  108 ++
 extensions/dash-to-dock/media/one_top.svg          |  108 ++
 extensions/dash-to-dock/media/three.svg            |  121 ++
 extensions/dash-to-dock/media/three_bottom.svg     |  122 ++
 extensions/dash-to-dock/media/three_rtl.svg        |  122 ++
 extensions/dash-to-dock/media/three_top.svg        |  122 ++
 extensions/dash-to-dock/media/two.svg              |  118 ++
 extensions/dash-to-dock/media/two_bottom.svg       |  119 ++
 extensions/dash-to-dock/media/two_rtl.svg          |  119 ++
 extensions/dash-to-dock/media/two_top.svg          |  119 ++
 extensions/dash-to-dock/metadata.json.in           |   12 +
 extensions/dash-to-dock/myConvenience.js           |  103 ++
 extensions/dash-to-dock/myDash.js                  | 1672 ++++++++++++++++++
 ...me.shell.extensions.dash-to-dock.gschema.xml.in |  159 ++
 extensions/dash-to-dock/prefs.js                   |  367 ++++
 extensions/dash-to-dock/stylesheet.css             |  181 ++
 29 files changed, 8810 insertions(+), 2 deletions(-)
 create mode 100644 extensions/dash-to-dock/Makefile.am
 create mode 100644 extensions/dash-to-dock/Settings.ui
 create mode 100644 extensions/dash-to-dock/dockedDash.js
 create mode 100644 extensions/dash-to-dock/extension.js
 create mode 100644 extensions/dash-to-dock/intellihide.js
 create mode 100644 extensions/dash-to-dock/media/four.svg
 create mode 100644 extensions/dash-to-dock/media/four_bottom.svg
 create mode 100644 extensions/dash-to-dock/media/four_rtl.svg
 create mode 100644 extensions/dash-to-dock/media/four_top.svg
 create mode 100644 extensions/dash-to-dock/media/logo.svg
 create mode 100644 extensions/dash-to-dock/media/one.svg
 create mode 100644 extensions/dash-to-dock/media/one_bottom.svg
 create mode 100644 extensions/dash-to-dock/media/one_rtl.svg
 create mode 100644 extensions/dash-to-dock/media/one_top.svg
 create mode 100644 extensions/dash-to-dock/media/three.svg
 create mode 100644 extensions/dash-to-dock/media/three_bottom.svg
 create mode 100644 extensions/dash-to-dock/media/three_rtl.svg
 create mode 100644 extensions/dash-to-dock/media/three_top.svg
 create mode 100644 extensions/dash-to-dock/media/two.svg
 create mode 100644 extensions/dash-to-dock/media/two_bottom.svg
 create mode 100644 extensions/dash-to-dock/media/two_rtl.svg
 create mode 100644 extensions/dash-to-dock/media/two_top.svg
 create mode 100644 extensions/dash-to-dock/metadata.json.in
 create mode 100644 extensions/dash-to-dock/myConvenience.js
 create mode 100644 extensions/dash-to-dock/myDash.js
 create mode 100644 extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml.in
 create mode 100644 extensions/dash-to-dock/prefs.js
 create mode 100644 extensions/dash-to-dock/stylesheet.css

diff --git a/configure.ac b/configure.ac
index 90b54da..d40b9e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_SUBST([SHELL_VERSION])
 dnl keep this in alphabetic order
 CLASSIC_EXTENSIONS="apps-menu places-menu alternate-tab launch-new-instance window-list"
 DEFAULT_EXTENSIONS="$CLASSIC_EXTENSIONS drive-menu screenshot-window-sizer windowsNavigator workspace-indicator"
-ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows example native-window-placement systemMonitor top-icons user-theme"
+ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows dash-to-dock example native-window-placement systemMonitor top-icons user-theme"
 AC_SUBST(CLASSIC_EXTENSIONS, [$CLASSIC_EXTENSIONS])
 AC_SUBST(ALL_EXTENSIONS, [$ALL_EXTENSIONS])
 AC_ARG_ENABLE([extensions],
@@ -66,7 +66,7 @@ for e in $enable_extensions; do
 					[AC_MSG_WARN([libgtop-2.0 not found, disabling systemMonitor])])
 			;;
 dnl		keep this in alphabetic order
-		alternate-tab|apps-menu|auto-move-windows|drive-menu|example|launch-new-instance|native-window-placement|places-menu|screenshot-window-sizer|top-icons|user-theme|window-list|windowsNavigator|workspace-indicator)
+		alternate-tab|apps-menu|auto-move-windows|dash-to-dock|drive-menu|example|launch-new-instance|native-window-placement|places-menu|screenshot-window-sizer|top-icons|user-theme|window-list|windowsNavigator|workspace-indicator)
 			ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
 			;;
 		*)
@@ -82,6 +82,7 @@ AC_CONFIG_FILES([
   extensions/alternate-tab/Makefile
   extensions/apps-menu/Makefile
   extensions/auto-move-windows/Makefile
+  extensions/dash-to-dock/Makefile
   extensions/drive-menu/Makefile
   extensions/example/Makefile
   extensions/launch-new-instance/Makefile
diff --git a/extensions/dash-to-dock/Makefile.am b/extensions/dash-to-dock/Makefile.am
new file mode 100644
index 0000000..5e08acf
--- /dev/null
+++ b/extensions/dash-to-dock/Makefile.am
@@ -0,0 +1,32 @@
+EXTENSION_ID = dash-to-dock
+
+EXTRA_MODULES =          \
+	dockedDash.js    \
+	intellihide.js   \
+	myConvenience.js \
+	myDash.js        \
+	prefs.js         \
+	Settings.ui
+
+include ../../extension.mk
+include ../../settings.mk
+
+mediadir = $(extensiondir)/media
+dist_media_DATA = \
+	media/four_bottom.svg  \
+	media/four_rtl.svg     \
+	media/four.svg         \
+	media/four_top.svg     \
+	media/logo.svg         \
+	media/one_bottom.svg   \
+	media/one_rtl.svg      \
+	media/one.svg          \
+	media/one_top.svg      \
+	media/three_bottom.svg \
+	media/three_rtl.svg    \
+	media/three.svg        \
+	media/three_top.svg    \
+	media/two_bottom.svg   \
+	media/two_rtl.svg      \
+	media/two.svg          \
+	media/two_top.svg
diff --git a/extensions/dash-to-dock/Settings.ui b/extensions/dash-to-dock/Settings.ui
new file mode 100644
index 0000000..e283588
--- /dev/null
+++ b/extensions/dash-to-dock/Settings.ui
@@ -0,0 +1,1782 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+  <requires lib="gtk+" version="3.12"/>
+  <object class="GtkAdjustment" id="animation_time_adjustment">
+    <property name="upper">1</property>
+    <property name="step_increment">0.050000000000000003</property>
+    <property name="page_increment">0.25</property>
+  </object>
+  <object class="GtkAdjustment" id="custom_opacity_adjustement">
+    <property name="upper">1</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="dock_size_adjustment">
+    <property name="lower">0.33000000000000002</property>
+    <property name="upper">1</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">0.10000000000000001</property>
+  </object>
+  <object class="GtkAdjustment" id="hide_timeout_adjustment">
+    <property name="upper">1</property>
+    <property name="step_increment">0.050000000000000003</property>
+    <property name="page_increment">0.25</property>
+  </object>
+  <object class="GtkAdjustment" id="icon_size_adjustment">
+    <property name="lower">16</property>
+    <property name="upper">128</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkNotebook" id="settings_notebook">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="margin_left">6</property>
+    <property name="margin_right">6</property>
+    <property name="margin_top">6</property>
+    <property name="margin_bottom">6</property>
+    <child>
+      <object class="GtkBox" id="position_and_size">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">24</property>
+        <property name="margin_right">24</property>
+        <property name="margin_top">24</property>
+        <property name="margin_bottom">24</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">24</property>
+        <child>
+          <object class="GtkFrame" id="dock_display">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="dock_display_listbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="dock_monitor_listboxrow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="dock_monitor_grid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="dock_monitor_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Show the dock on</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="dock_monitor_combo">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="valign">center</property>
+                            <signal name="changed" handler="dock_display_combo_changed_cb" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkListBoxRow" id="dock_position_listboxrow">
+                    <property name="width_request">100</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkBox" id="dock_position_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="dock_position_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Position on screen</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="dock_position_butttons_box">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="spacing">32</property>
+                            <child>
+                              <object class="GtkRadioButton" id="position_left_button">
+                                <property name="label" translatable="yes">Left</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="halign">end</property>
+                                <property name="valign">center</property>
+                                <property name="xalign">0</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="position_left_button_toggled_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="position_bottom_button">
+                                <property name="label" translatable="yes">Bottom</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="halign">center</property>
+                                <property name="xalign">0</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">position_left_button</property>
+                                <signal name="toggled" handler="position_bottom_button_toggled_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="position_top_button">
+                                <property name="label" translatable="yes">Top</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="halign">center</property>
+                                <property name="xalign">0</property>
+                                <property name="image_position">bottom</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">position_left_button</property>
+                                <signal name="toggled" handler="position_top_button_toggled_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="position_right_button">
+                                <property name="label" translatable="yes">Right</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="valign">center</property>
+                                <property name="xalign">0</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">position_left_button</property>
+                                <signal name="toggled" handler="position_right_button_toggled_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="intelligent_autohide_frame">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="listbox3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow14">
+                    <property name="width_request">100</property>
+                    <property name="height_request">80</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="intelligent_autohide_grid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_description7">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Hide the dock when it obstructs a window of the the current application. More refined settings are available.</property>
+                            <property name="wrap">True</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_label8">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Intelligent autohide</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="box3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <object class="GtkButton" id="intelligent_autohide_button">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="halign">center</property>
+                                <property name="valign">center</property>
+                                <property name="xalign">0.46000000834465027</property>
+                                <child>
+                                  <object class="GtkImage" id="image">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="icon_name">emblem-system-symbolic</property>
+                                  </object>
+                                </child>
+                                <style>
+                                  <class name="prefs-button"/>
+                                </style>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSwitch" id="intelligent_autohide_switch">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="halign">end</property>
+                                <property name="valign">center</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="insensitive_messagetray_checkbutton">
+                            <property name="label" translatable="yes">Insensitive Message Tray</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="margin_top">12</property>
+                            <property name="xalign">0</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">2</property>
+                            <property name="width">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="size_frame">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="size_listbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="dock_size_listboxrow">
+                    <property name="width_request">100</property>
+                    <property name="height_request">80</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="dock_size_grid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="dock_size_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Dock size limit</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScale" id="dock_size_scale">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="valign">baseline</property>
+                            <property name="hexpand">True</property>
+                            <property name="adjustment">dock_size_adjustment</property>
+                            <property name="round_digits">0</property>
+                            <property name="digits">2</property>
+                            <property name="value_pos">right</property>
+                            <signal name="format-value" handler="dock_size_scale_format_value_cb" swapped="no"/>
+                            <signal name="value-changed" handler="dock_size_scale_value_changed_cb" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="dock_size_extend_checkbutton">
+                            <property name="label" translatable="yes">Panel mode: extend to the screen edge</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="margin_top">12</property>
+                            <property name="xalign">0</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                            <property name="width">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkListBoxRow" id="icon_size_listboxrow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="icon_size_grid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_label6">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Icon size limit</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScale" id="icon_size_scale">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="valign">baseline</property>
+                            <property name="hexpand">True</property>
+                            <property name="adjustment">icon_size_adjustment</property>
+                            <property name="round_digits">1</property>
+                            <property name="digits">0</property>
+                            <property name="value_pos">right</property>
+                            <signal name="format-value" handler="icon_size_scale_format_value_cb" swapped="no"/>
+                            <signal name="value-changed" handler="icon_size_scale_value_changed_cb" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="icon_size_fixed_checkbutton">
+                            <property name="label" translatable="yes">Fixed icon size: scroll to reveal other icons</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="margin_top">12</property>
+                            <property name="xalign">0</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                            <property name="width">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="general_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Position and size</property>
+      </object>
+      <packing>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="behaviour">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">24</property>
+        <property name="margin_right">24</property>
+        <property name="margin_top">24</property>
+        <property name="margin_bottom">24</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">24</property>
+        <child>
+          <object class="GtkFrame" id="customize_theme1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="listbox9">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow16">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="shrink_dash2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkSwitch" id="show_running_switch">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="shrink_dash_label2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Show running applications</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow17">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="shrink_dash3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkSwitch" id="application_button_first_switch">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="shrink_dash_description1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Move the applications button at the beginning of the dock.</property>
+                            <property name="wrap">True</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="shrink_dash_label3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">&lt;i&gt;Show Applications&lt;/i&gt; icon first</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="built_in_theme_frame3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="listbox6">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow9">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="buitin_theme5">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_description5">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Behaviour when clicking on the icon of a running application.</property>
+                            <property name="wrap">True</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_label5">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Click action</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="click_action_combo">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="valign">center</property>
+                            <items>
+                              <item translatable="yes">Do nothing</item>
+                              <item translatable="yes">Minimize</item>
+                              <item translatable="yes">Launch new instance</item>
+                              <item translatable="yes">Cycle through windows</item>
+                            </items>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow11">
+                    <property name="width_request">100</property>
+                    <property name="height_request">80</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="buitin_theme7">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_description4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">When set to minimize, double clicking minimizes all the windows of the application.</property>
+                            <property name="wrap">True</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_label4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Shift+Click action</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="shift_click_action_combo">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="valign">center</property>
+                            <items>
+                              <item translatable="yes">Do nothing</item>
+                              <item translatable="yes">Minimize window</item>
+                            </items>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="built_in_theme_frame1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="listbox5">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="switch_workspace_grid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="switch_workspace_description">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">The area of the dock close to the screen edge and the &lt;i&gt;Show Applications&lt;/i&gt; icon are active.</property>
+                            <property name="use_markup">True</property>
+                            <property name="wrap">True</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="switch_workspace_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Switch workspace by scrolling on the dock</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSwitch" id="switch_workspace_switch">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="behaviour_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Behavior</property>
+      </object>
+      <packing>
+        <property name="position">1</property>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="appearance">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">24</property>
+        <property name="margin_right">24</property>
+        <property name="margin_top">24</property>
+        <property name="margin_bottom">24</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">24</property>
+        <child>
+          <object class="GtkFrame" id="built_in_theme_frame">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="listbox1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="buitin_theme">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_description">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Few customizations meant to integrate the dock wih the default GNOME theme. Alternatively, specific options can be enabled below.</property>
+                            <property name="wrap">True</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="builtin_theme_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Use built-in theme</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSwitch" id="builtin_theme_switch">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="customize_theme">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkListBox" id="listbox2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="selection_mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="shrink_dash">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkSwitch" id="shrink_dash_switch">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="shrink_dash_description">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Save space reducing padding and border radius.</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="shrink_dash_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Shrink the dash</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkGrid" id="running_dots">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="margin_right">12</property>
+                        <property name="margin_top">12</property>
+                        <property name="margin_bottom">12</property>
+                        <property name="column_spacing">32</property>
+                        <child>
+                          <object class="GtkSwitch" id="running_dots_switch">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="running_dots_description">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Show a dot for each windows of the application.</property>
+                            <style>
+                              <class name="dim-label"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="running_dots_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Show windows counter indicators</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkListBoxRow" id="listboxrow4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <child>
+                      <object class="GtkBox" id="box2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkGrid" id="customize_opacity">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_left">12</property>
+                            <property name="margin_right">12</property>
+                            <property name="margin_top">12</property>
+                            <property name="margin_bottom">12</property>
+                            <property name="column_spacing">32</property>
+                            <child>
+                              <object class="GtkSwitch" id="customize_opacity_switch">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="halign">end</property>
+                                <property name="valign">center</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">0</property>
+                                <property name="height">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="customize_opacity_description">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="hexpand">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Tune the dash background opacity.</property>
+                                <style>
+                                  <class name="dim-label"/>
+                                </style>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="customize_opacity_label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="hexpand">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Customize opacity</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="custom_opacity">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_left">12</property>
+                            <property name="margin_right">12</property>
+                            <property name="margin_top">12</property>
+                            <property name="margin_bottom">12</property>
+                            <property name="spacing">32</property>
+                            <child>
+                              <object class="GtkLabel" id="custom_opacity_label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="label" translatable="yes">Opacity</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkScale" id="custom_opacity_scale">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="adjustment">custom_opacity_adjustement</property>
+                                <property name="lower_stepper_sensitivity">on</property>
+                                <property name="restrict_to_fill_level">False</property>
+                                <property name="fill_level">0</property>
+                                <property name="round_digits">0</property>
+                                <property name="digits">2</property>
+                                <property name="value_pos">right</property>
+                                <signal name="format-value" handler="custom_opacity_scale_format_value_cb" swapped="no"/>
+                                <signal name="value-changed" handler="custom_opacity_scale_value_changed_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">2</property>
+      </packing>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="appearance_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Appearance</property>
+      </object>
+      <packing>
+        <property name="position">2</property>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="about">
+        <property name="can_focus">False</property>
+        <property name="margin_top">24</property>
+        <property name="margin_bottom">24</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">5</property>
+        <child>
+          <object class="GtkImage" id="logo">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="pixbuf">./media/logo.svg</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="padding">10</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="extension_name">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label">&lt;b&gt;Dash to Dock&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <child>
+              <object class="GtkLabel" id="extension_version_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">version: </property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="extension_version">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label">...</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="extension_description">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Moves the dash out of the overview transforming it in a dock</property>
+            <property name="justify">center</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box10">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="spacing">5</property>
+            <child>
+              <object class="GtkLabel" id="label15">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Created by</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label16">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="label">Michele (&lt;a href="mailto:micxgx@gmail.com"&gt;micxgx@gmail.com&lt;/a&gt;)</property>
+                <property name="use_markup">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLinkButton" id="homepage_link">
+            <property name="label">Webpage</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="events"/>
+            <property name="halign">center</property>
+            <property name="relief">none</property>
+            <property name="uri">https://micheleg.github.io/dash-to-dock/</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">5</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="valign">end</property>
+            <property name="label" translatable="yes">&lt;span size="small"&gt;This program comes with ABSOLUTELY NO WARRANTY.
+See the &lt;a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html"&gt;GNU General Public License, version 2 or later&lt;/a&gt; for details.&lt;/span&gt;</property>
+            <property name="use_markup">True</property>
+            <property name="justify">center</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">6</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">3</property>
+      </packing>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="about_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">About</property>
+      </object>
+      <packing>
+        <property name="position">3</property>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkAdjustment" id="pressure_threshold_adjustment">
+    <property name="upper">1000</property>
+    <property name="step_increment">50</property>
+    <property name="page_increment">250</property>
+  </object>
+  <object class="GtkAdjustment" id="show_timeout_adjustment">
+    <property name="upper">1</property>
+    <property name="step_increment">0.050000000000000003</property>
+    <property name="page_increment">0.25</property>
+  </object>
+  <object class="GtkBox" id="intelligent_autohide_advanced_settings_box">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="margin_left">12</property>
+    <property name="margin_right">12</property>
+    <property name="margin_top">12</property>
+    <property name="margin_bottom">12</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkFrame" id="intelligent_autohide_advanced_settings_frame">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkListBox" id="listbox4">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="selection_mode">none</property>
+            <child>
+              <object class="GtkListBoxRow" id="listboxrow8">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkGrid" id="buitin_theme2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">12</property>
+                    <property name="margin_right">12</property>
+                    <property name="margin_top">12</property>
+                    <property name="margin_bottom">12</property>
+                    <property name="column_spacing">32</property>
+                    <child>
+                      <object class="GtkLabel" id="builtin_theme_description2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Show the dock by mouse hover on the screen edge.</property>
+                        <property name="wrap">True</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="builtin_theme_label2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Autohide</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSwitch" id="autohide_switch">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="halign">end</property>
+                        <property name="valign">center</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                        <property name="height">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="require_pressure_checkbutton">
+                        <property name="label" translatable="yes">Push to show: require pressure to show the dock</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="margin_top">12</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkListBoxRow" id="listboxrow15">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkGrid" id="buitin_theme3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">12</property>
+                    <property name="margin_right">12</property>
+                    <property name="margin_top">12</property>
+                    <property name="margin_bottom">12</property>
+                    <property name="column_spacing">32</property>
+                    <child>
+                      <object class="GtkLabel" id="builtin_theme_description3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Show the dock when it doesn't obstruct application windows.</property>
+                        <property name="wrap">True</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="builtin_theme_label3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Dodge windows</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSwitch" id="intellihide_switch">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="halign">end</property>
+                        <property name="valign">center</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                        <property name="height">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="per_app_intellihide_checkbutton">
+                        <property name="label" translatable="yes">Only consider windows of the focused application</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="margin_top">12</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkListBoxRow" id="listboxrow5">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkGrid" id="grid2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">12</property>
+                    <property name="margin_right">12</property>
+                    <property name="margin_top">12</property>
+                    <property name="margin_bottom">12</property>
+                    <property name="hexpand">True</property>
+                    <property name="row_spacing">6</property>
+                    <property name="column_spacing">32</property>
+                    <child>
+                      <object class="GtkSpinButton" id="animation_duration_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="halign">end</property>
+                        <property name="adjustment">animation_time_adjustment</property>
+                        <property name="digits">3</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Animation duration (s)</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="hide_timeout_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="halign">end</property>
+                        <property name="adjustment">hide_timeout_adjustment</property>
+                        <property name="digits">3</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="show_timeout_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="halign">end</property>
+                        <property name="adjustment">show_timeout_adjustment</property>
+                        <property name="digits">3</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="pressure_threshold_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="text" translatable="yes">0.000</property>
+                        <property name="adjustment">pressure_threshold_adjustment</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label9">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Hide timeout (s)</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Show timeout (s)</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Pressure threshold</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">3</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="label_item">
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/extensions/dash-to-dock/dockedDash.js b/extensions/dash-to-dock/dockedDash.js
new file mode 100644
index 0000000..1e145c6
--- /dev/null
+++ b/extensions/dash-to-dock/dockedDash.js
@@ -0,0 +1,1684 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+const Mainloop = imports.mainloop;
+const Params = imports.misc.params;
+
+const Main = imports.ui.main;
+const Dash = imports.ui.dash;
+const IconGrid = imports.ui.iconGrid;
+const MessageTray = imports.ui.messageTray;
+const Overview = imports.ui.overview;
+const OverviewControls = imports.ui.overviewControls;
+const PointerWatcher = imports.ui.pointerWatcher;
+const Tweener = imports.ui.tweener;
+const Signals = imports.signals;
+const ViewSelector = imports.ui.viewSelector;
+const WorkspaceSwitcherPopup= imports.ui.workspaceSwitcherPopup;
+const Layout = imports.ui.layout;
+const LayoutManager = imports.ui.main.layoutManager;
+
+const Me = imports.misc.extensionUtils.getCurrentExtension();
+const Convenience = Me.imports.myConvenience;
+const Intellihide = Me.imports.intellihide;
+const MyDash = Me.imports.myDash;
+
+const DOCK_DWELL_CHECK_INTERVAL = 100;  //TODO
+
+const State = {
+    HIDDEN:  0,
+    SHOWING: 1,
+    SHOWN:   2,
+    HIDING:  3
+};
+
+/* Return the actual position reverseing left and right in rtl */
+function getPosition(settings) {
+    let position = settings.get_enum('dock-position');
+    if(Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
+        if (position == St.Side.LEFT)
+            position = St.Side.RIGHT;
+        else if (position == St.Side.RIGHT)
+            position = St.Side.LEFT;
+    }
+    return position;
+}
+
+/*
+ * A simple St.Widget with one child whose allocation takes into account the
+ * slide out of its child via the _slidex parameter ([0:1]).
+ *
+ * Required since I want to track the input region of this container which is
+ * based on its allocation even if the child overlows the parent actor. By doing
+ * this the region of the dash that is slideout is not steling anymore the input
+ * regions making the extesion usable when the primary monitor is the right one.
+ *
+ * The slidex parameter can be used to directly animate the sliding. The parent
+ * must have a WEST (SOUTH) anchor_point to achieve the sliding to the RIGHT (BOTTOM)
+ * side.
+ *
+ * It can't be an extended object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973.
+ * thus use the Shell.GenericContainer pattern.
+*/
+
+const DashSlideContainer = new Lang.Class({
+    Name: 'DashSlideContainer',
+
+    _init: function(params) {
+
+        /* Default local params */
+        let localDefaults = {
+            side: St.Side.LEFT,
+            initialSlideValue: 1
+        }
+
+        let localParams = Params.parse(params, localDefaults, true);
+
+        if (params){
+            /* Remove local params before passing the params to the parent
+               constructor to avoid errors. */
+            let prop;
+            for (prop in localDefaults) {
+                if ((prop in params))
+                    delete params[prop];
+            }
+        }
+
+        this.actor = new Shell.GenericContainer(params);
+        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
+        this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
+        this.actor.connect('allocate', Lang.bind(this, this._allocate));
+
+        this.actor._delegate = this;
+
+        this._child = null;
+
+        // slide parameter: 1 = visible, 0 = hidden.
+        this._slidex = localParams.initialSlideValue;
+        this._side = localParams.side;
+        this._slideoutSize = 0; // minimum size when slided out
+    },
+
+
+    _allocate: function(actor, box, flags) {
+
+        if (this._child == null)
+            return;
+
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+        let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] =
+            this._child.get_preferred_size();
+
+        let childWidth = natChildWidth;
+        let childHeight = natChildHeight;
+
+        let childBox = new Clutter.ActorBox();
+
+        let slideoutSize = this._slideoutSize;
+
+        if (this._side == St.Side.LEFT) {
+            childBox.x1 = (this._slidex -1)*(childWidth - slideoutSize);
+            childBox.x2 = slideoutSize + this._slidex*(childWidth - slideoutSize);
+            childBox.y1 = 0;
+            childBox.y2 = childBox.y1 + childHeight;
+        } else if (this._side ==  St.Side.RIGHT
+                 || this._side ==  St.Side.BOTTOM) {
+            childBox.x1 = 0;
+            childBox.x2 = childWidth;
+            childBox.y1 = 0;
+            childBox.y2 = childBox.y1 + childHeight;
+        } else if (this._side ==  St.Side.TOP) {
+            childBox.x1 = 0;
+            childBox.x2 = childWidth;
+            childBox.y1 = (this._slidex -1)*(childHeight - slideoutSize);
+            childBox.y2 = slideoutSize + this._slidex*(childHeight - slideoutSize);
+        }
+
+        this._child.allocate(childBox, flags);
+        this._child.set_clip(-childBox.x1, -childBox.y1,
+                             -childBox.x1+availWidth,-childBox.y1 + availHeight);
+    },
+
+    /* Just the child width but taking into account the slided out part */
+    _getPreferredWidth: function(actor, forHeight, alloc) {
+        let [minWidth, natWidth ] = this._child.get_preferred_width(forHeight);
+        if (this._side ==  St.Side.LEFT
+          || this._side == St.Side.RIGHT) {
+            minWidth = (minWidth - this._slideoutSize)*this._slidex + this._slideoutSize;
+            natWidth = (natWidth - this._slideoutSize)*this._slidex + this._slideoutSize;
+        }
+
+        alloc.min_size = minWidth;
+        alloc.natural_size = natWidth;
+    },
+
+    /* Just the child height but taking into account the slided out part */
+    _getPreferredHeight: function(actor, forWidth,  alloc) {
+        let [minHeight, natHeight] = this._child.get_preferred_height(forWidth);
+        if (this._side ==  St.Side.TOP
+          || this._side ==  St.Side.BOTTOM) {
+            minHeight = (minHeight - this._slideoutSize)*this._slidex + this._slideoutSize;
+            natHeight = (natHeight - this._slideoutSize)*this._slidex + this._slideoutSize;
+        }
+        alloc.min_size = minHeight;
+        alloc.natural_size = natHeight;
+    },
+
+    /* I was expecting it to be a virtual function... stil I don't understand
+       how things work.
+    */
+    add_child: function(actor) {
+
+        /* I'm supposed to have only on child */
+        if(this._child !== null) {
+            this.actor.remove_child(actor);
+        }
+
+        this._child = actor;
+        this.actor.add_child(actor);
+    },
+
+    set slidex(value) {
+        this._slidex = value;
+        this._child.queue_relayout();
+    },
+
+    get slidex() {
+        return this._slidex;
+    }
+
+});
+
+const dockedDash = new Lang.Class({
+    Name: 'dockedDash',
+ 
+    _init: function(settings) {
+
+        this._rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
+
+        // Load settings
+        this._settings = settings;
+        this._bindSettingsChanges();
+
+        this._position = getPosition(settings);
+        this._isHorizontal = ( this._position == St.Side.TOP ||
+                               this._position == St.Side.BOTTOM );
+
+        // Temporary ignore hover events linked to autohide for whatever reason
+        this._ignoreHover = false;
+        this._oldignoreHover = null;
+        // This variables are linked to the settings regardles of autohide or intellihide
+        // being temporary disable. Get set by _updateVisibilityMode;
+        this._autohideIsEnabled = null;
+        this._intellihideIsEnabled = null;
+        this._fixedIsEnabled = null;
+
+        // Create intellihide object to monitor windows overlapping
+        this._intellihide = new Intellihide.intellihide(this._settings);
+
+        // initialize dock state
+        this._dockState = State.HIDDEN;
+
+        /* status variable: true when the overview is shown through the dash
+         * applications button.
+         */
+        this.forcedOverview = false;
+
+        // Put dock on the primary monitor
+        this._monitor = Main.layoutManager.primaryMonitor;
+
+        // this store size and the position where the dash is shown;
+        // used by intellihide module to check window overlap.
+        this.staticBox = new Clutter.ActorBox();
+
+        // Initialize pressure barrier variables
+        this._canUsePressure = false;
+        this._pressureBarrier = null;
+        this._barrier = null;
+        this._messageTrayShowing = false;
+        this._removeBarrierTimeoutId = 0;
+
+        // Initialize dwelling system variables
+        this._dockDwelling = false;
+        this._dockWatch = null;
+        this._dockDwellUserTime = 0;
+        this._dockDwellTimeoutId = 0
+
+        // Create a new dash object
+        this.dash = new MyDash.myDash(this._settings);
+
+        // set stored icon size  to the new dash
+        Main.overview.dashIconSize = this.dash.iconSize;
+
+        // connect app icon into the view selector
+        this.dash.showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
+
+        // Create the main actor and the containers for sliding in and out and
+        // centering, turn on track hover
+
+        let positionStyleClass = ['top', 'right', 'bottom', 'left'];
+        // This is the centering actor
+        this.actor = new St.Bin({ name: 'dashtodockContainer',reactive: false,
+            style_class:positionStyleClass[this._position],
+            x_align: this._isHorizontal?St.Align.MIDDLE:St.Align.START,
+            y_align: this._isHorizontal?St.Align.START:St.Align.MIDDLE});
+        this.actor._delegate = this;
+
+        // This is the sliding actor whose allocation is to be tracked for input regions
+        this._slider = new DashSlideContainer({side: this._position, initialSlideValue: 0});
+
+        // This is the actor whose hover status us tracked for autohide
+        this._box = new St.BoxLayout({ name: 'dashtodockBox', reactive: true, track_hover:true } );
+        this._box.connect("notify::hover", Lang.bind(this, this._hoverChanged));
+
+        // Create and apply height constraint to the dash. It's controlled by this.actor height
+        this.constrainSize = new Clutter.BindConstraint({ source: this.actor,
+          coordinate: this._isHorizontal?Clutter.BindCoordinate.WIDTH:Clutter.BindCoordinate.HEIGHT });
+        this.dash.actor.add_constraint(this.constrainSize);
+
+        // Connect global signals
+        this._signalsHandler = new Convenience.GlobalSignalsHandler();
+        this._signalsHandler.add(
+            [
+                Main.overview,
+                'item-drag-begin',
+                Lang.bind(this, this._onDragStart)
+            ],
+            [
+                Main.overview,
+                'item-drag-end',
+                Lang.bind(this, this._onDragEnd)
+            ],
+            [
+                Main.overview,
+                'item-drag-cancelled',
+                Lang.bind(this, this._onDragEnd)
+            ],
+            // update wne monitor changes, for instance in multimonitor when monitor are attached
+            [
+                global.screen,
+                'monitors-changed',
+                Lang.bind(this, this._resetPosition )
+            ],
+            [
+                Main.overview,
+                'showing',
+                Lang.bind(this, this._onOverviewShowing)
+            ],
+            [
+                Main.overview,
+                'hiding',
+                Lang.bind(this, this._onOverviewHiding)
+            ],
+            // Hide on appview
+            [
+                Main.overview.viewSelector,
+                'page-changed',
+                Lang.bind(this, this._pageChanged)
+            ],
+            [
+                Main.overview.viewSelector,
+                'page-empty',
+                Lang.bind(this, this._onPageEmpty)
+            ],
+            // Ensure the ShowAppsButton status is kept in sync
+            [
+                Main.overview.viewSelector._showAppsButton,
+                'notify::checked',
+                Lang.bind(this, this._syncShowAppsButtonToggled)
+            ],
+            [
+                Main.messageTray,
+                'showing',
+                Lang.bind(this, this._onMessageTrayShowing)
+            ],
+            [
+                Main.messageTray,
+                'hiding',
+                Lang.bind(this, this._onMessageTrayHiding)
+            ],
+            // Monitor windows overlapping
+            [
+                this._intellihide,
+                'status-changed',
+                Lang.bind(this, this._updateDashVisibility)
+            ],
+            // Keep dragged icon consistent in size with this dash
+            [
+                this.dash,
+                'icon-size-changed',
+                Lang.bind(this, function() {
+                    Main.overview.dashIconSize = this.dash.iconSize;
+                })
+            ],
+            // This duplicate the similar signal which is in owerview.js.
+            // Being connected and thus executed later this effectively
+            // overwrite any attempt to use the size of the default dash
+            //which given the customization is usually much smaller.
+            // I can't easily disconnect the original signal
+            [
+                Main.overview._controls.dash,
+                'icon-size-changed',
+                Lang.bind(this, function() {
+                    Main.overview.dashIconSize = this.dash.iconSize;
+                })
+            ]
+        );
+
+        this._injectionsHandler = new Convenience.InjectionsHandler();
+        this._themeManager = new themeManager(this._settings, this.actor, this.dash);
+
+        // Since the actor is not a topLevel child and its parent is now not added to the Chrome,
+        // the allocation change of the parent container (slide in and slideout) doesn't trigger
+        // anymore an update of the input regions. Force the update manually.
+        this.actor.connect('notify::allocation',
+                                              Lang.bind(Main.layoutManager, Main.layoutManager._queueUpdateRegions));
+
+        this.dash._container.connect('allocation-changed', Lang.bind(this, this._updateStaticBox));
+        this._slider.actor.connect(this._isHorizontal?'notify::x':'notify::y', Lang.bind(this, this._updateStaticBox));
+
+        // sync hover after a popupmenu is closed
+        this.dash.connect('menu-closed', Lang.bind(this, function(){this._box.sync_hover();}));
+
+        // Restore dash accessibility
+        Main.ctrlAltTabManager.addGroup(
+            this.dash.actor, _("Dash"),'user-bookmarks-symbolic',
+                {focusCallback: Lang.bind(this, this._onAccessibilityFocus)});
+
+        // Load optional features
+        this._optionalScrollWorkspaceSwitch();
+
+         // Delay operations that require the shell to be fully loaded and with
+         // user theme applied.
+
+        this._paintId = this.actor.connect("paint", Lang.bind(this, this._initialize));
+
+        // Hide usual Dash
+        Main.overview._controls.dash.actor.hide();
+
+        // Also set dash width to 1, so it's almost not taken into account by code
+        // calculaing the reserved space in the overview. The reason to keep it at 1 is
+        // to allow its visibility change to trigger an allocaion of the appGrid which
+        // in turn is triggergin the appsIcon spring animation, required when no other
+        // actors has this effect, i.e in horizontal mode and without the workspaceThumnails
+        // 1 static workspace only)
+        Main.overview._controls.dash.actor.set_width(1);
+
+        // Manage the  which is used to reserve space in the overview for the dock
+        // Add and additional dashSpacer positioned according to the dash positioning.
+        // It gets restored on extension unload.
+        this._dashSpacer = new OverviewControls.DashSpacer();
+        this._dashSpacer.setDashActor(this._box);
+
+        // shift overview messageIndicator for bottom dock
+        this._oldMessageIndicatorPosition = Main.overview._controls._indicator.actor.get_first_child().y;
+        if (this._position ==  St.Side.BOTTOM) {
+          this._dashSpacer.connect('notify::height', Lang.bind(this, function(){
+              Main.overview._controls._indicator.actor.get_first_child().y = -this._dashSpacer.height;
+          }));
+        }
+
+        if (this._position ==  St.Side.LEFT)
+          Main.overview._controls._group.insert_child_at_index(this._dashSpacer, this._rtl?-1:0); // insert on first
+        else if (this._position ==  St.Side.RIGHT)
+            Main.overview._controls._group.insert_child_at_index(this._dashSpacer, this._rtl?0:-1); // insert on last
+        else if (this._position ==  St.Side.TOP)
+            Main.overview._overview.insert_child_at_index(this._dashSpacer, 0);
+        else if (this._position ==  St.Side.BOTTOM)
+          Main.overview._overview.insert_child_at_index(this._dashSpacer, -1);
+
+        // Add dash container actor and the container to the Chrome.
+        this.actor.set_child(this._slider.actor);
+        this._slider.add_child(this._box);
+        this._box.add_actor(this.dash.actor);
+
+        // Add aligning container without tracking it for input region (old affectsinputRegion: false that was removed).
+        // The public method trackChrome requires the actor to be child of a tracked actor. Since I don't want the parent
+        // to be tracked I use the private internal _trackActor instead.
+        Main.uiGroup.add_child(this.actor);
+        Main.layoutManager._trackActor(this._slider.actor, {trackFullscreen: true});
+
+        // Keep the dash below the modalDialogGroup
+        Main.layoutManager.uiGroup.set_child_below_sibling(this.actor,Main.layoutManager.modalDialogGroup);
+
+        if ( this._settings.get_boolean('dock-fixed') )
+          Main.layoutManager._trackActor(this.dash.actor, {affectsStruts: true});
+
+        // pretend this._slider is isToplevel child so that fullscreen is actually tracked
+        let index = Main.layoutManager._findActor(this._slider.actor);
+        Main.layoutManager._trackedActors[index].isToplevel = true ;
+
+        // Set initial position
+        this._resetPosition();
+
+    },
+
+    _initialize: function(){
+
+        if(this._paintId>0){
+            this.actor.disconnect(this._paintId);
+            this._paintId=0;
+        }
+
+        this.dash.setIconSize(this._settings.get_int('dash-max-icon-size'), true);
+
+        // Apply custome css class according to the settings
+        this._themeManager.updateCustomTheme();
+
+        // Since Gnome 3.8 dragging an app without having opened the overview before cause the attemp to
+        //animate a null target since some variables are not initialized when the viewSelector is created
+        if(Main.overview.viewSelector._activePage == null)
+                Main.overview.viewSelector._activePage = Main.overview.viewSelector._workspacesPage;
+
+        this._updateVisibilityMode();
+
+        // Setup pressure barrier (GS38+ only)
+        this._updatePressureBarrier();
+        this._updateBarrier();
+
+        // setup dwelling system if pressure barriers are not available
+        this._setupDockDwellIfNeeded();
+
+        // Insensitive Message Tray
+        this._updateInsensitiveTray();
+    },
+
+    destroy: function(){
+
+        // Disconnect global signals
+        this._signalsHandler.destroy();
+        // The dash and intellihide have global signals as well internally
+        this.dash.destroy();
+        this._intellihide.destroy();
+
+        this._injectionsHandler.destroy();
+
+        // Destroy main clutter actor: this should be sufficient removing it and
+        // destroying  all its children
+        this.actor.destroy();
+
+        // Remove barrier timeout
+        if (this._removeBarrierTimeoutId > 0)
+            Mainloop.source_remove(this._removeBarrierTimeoutId);
+
+        // Remove existing barrier
+        this._removeBarrier();
+
+        // Remove pointer watcher
+        if(this._dockWatch){
+            PointerWatcher.getPointerWatcher()._removeWatch(this._dockWatch);
+            this._dockWatch = null;
+        }
+
+        // Remove the dashSpacer
+        this._dashSpacer.destroy();
+
+        // restore messageIndicator position
+        Main.overview._controls._indicator.actor.get_first_child().y = this._oldMessageIndicatorPosition;
+
+        // Reshow normal dash previously hidden, restore panel position if changed.
+        Main.overview._controls.dash.actor.show();
+        Main.overview._controls.dash.actor.set_width(-1); //reset default dash size
+        // This force the recalculation of the icon size
+        Main.overview._controls.dash._maxHeight = -1;
+
+        // reset stored icon size  to the default dash
+        Main.overview.dashIconSize = Main.overview._controls.dash.iconSize;
+        // Reshow panel corners
+        this._revertPanelCorners();
+    },
+
+    _bindSettingsChanges: function() {
+
+        this._settings.connect('changed::scroll-switch-workspace', Lang.bind(this, function(){
+            this._optionalScrollWorkspaceSwitch(this._settings.get_boolean('scroll-switch-workspace'));
+        }));
+
+        this._settings.connect('changed::dash-max-icon-size', Lang.bind(this, function(){
+            this.dash.setIconSize(this._settings.get_int('dash-max-icon-size'));
+        }));
+
+        this._settings.connect('changed::icon-size-fixed', Lang.bind(this, function(){
+            this.dash.setIconSize(this._settings.get_int('dash-max-icon-size'));
+        }));
+
+        this._settings.connect('changed::show-running', Lang.bind(this, function(){
+            this.dash.resetAppIcons();
+        }));
+
+        this._settings.connect('changed::show-apps-at-top', Lang.bind(this, function(){
+            this.dash.resetAppIcons();
+        }));
+
+        this._settings.connect('changed::dock-fixed', Lang.bind(this, function(){
+
+            if(this._settings.get_boolean('dock-fixed')) {
+                Main.layoutManager._trackActor(this.dash.actor, {affectsStruts: true});
+            } else {
+                Main.layoutManager._untrackActor(this.dash.actor);
+            }
+
+            this._resetPosition();
+
+            // Add or remove barrier depending on if dock-fixed
+            this._updateBarrier();
+
+            this._updateVisibilityMode();
+        }));
+
+        this._settings.connect('changed::intellihide', Lang.bind(this, this._updateVisibilityMode));
+
+        this._settings.connect('changed::intellihide-perapp', Lang.bind(this, function(){
+            this._intellihide.forceUpdate();
+        }));
+
+        this._settings.connect('changed::autohide', Lang.bind(this, function(){
+            this._updateVisibilityMode();
+            this._updateBarrier();
+        }));
+        this._settings.connect('changed::extend-height', Lang.bind(this,this._resetPosition));
+        this._settings.connect('changed::preferred-monitor', Lang.bind(this,this._resetPosition));
+        this._settings.connect('changed::height-fraction', Lang.bind(this,this._resetPosition));
+        this._settings.connect('changed::insensitive-message-tray', Lang.bind(this,this._updateInsensitiveTray));
+        this._settings.connect('changed::require-pressure-to-show', Lang.bind(this,function(){
+            // Remove pointer watcher
+            if(this._dockWatch){
+                PointerWatcher.getPointerWatcher()._removeWatch(this._dockWatch);
+                this._dockWatch = null;
+            }
+            this._setupDockDwellIfNeeded();
+            this._updateBarrier();
+        }));
+        this._settings.connect('changed::pressure-threshold', Lang.bind(this,function() {
+            this._updatePressureBarrier();
+            this._updateBarrier();
+        }));
+
+    },
+
+    // This is call when visibility settings change
+    _updateVisibilityMode: function() {
+
+        if (this._settings.get_boolean('dock-fixed')) {
+            this._fixedIsEnabled = true;
+            this._autohideIsEnabled = false;
+            this._intellihideIsEnabled = false;
+        } else {
+            this._fixedIsEnabled = false;
+            this._autohideIsEnabled = this._settings.get_boolean('autohide')
+            this._intellihideIsEnabled = this._settings.get_boolean('intellihide')
+        }
+
+        if (this._intellihideIsEnabled)
+            this._intellihide.enable();
+        else
+            this._intellihide.disable();
+
+        this._updateDashVisibility();
+    },
+
+    /* Show/hide dash based on, in order of priority:
+     * overview visibility
+     * fixed mode
+     * intellihide
+     * autohide
+     * overview visibility
+     */
+    _updateDashVisibility: function() {
+
+        if (Main.overview.visibleTarget)
+            return;
+
+        if ( this._fixedIsEnabled ) {
+            this._removeAnimations();
+            this._animateIn(this._settings.get_double('animation-time'), 0);
+        } else if (this._intellihideIsEnabled) {
+            if ( this._intellihide.getOverlapStatus() ) {
+                this._ignoreHover = false;
+                // Do not hide if autohide is enabled and mouse is hover
+                if (!this._box.hover || !this._autohideIsEnabled) {
+                    this._animateOut(this._settings.get_double('animation-time'), 0);
+                }
+            } else {
+                this._ignoreHover = true;
+                this._removeAnimations();
+                this._animateIn(this._settings.get_double('animation-time'), 0);
+            }
+        } else {
+            if (this._autohideIsEnabled) {
+                this._ignoreHover = false;
+                global.sync_pointer();
+
+                if( this._box.hover ) {
+                    this._animateIn(this._settings.get_double('animation-time'), 0);
+                } else {
+                    this._animateOut(this._settings.get_double('animation-time'), 0);
+                }
+
+            } else {
+                this._animateOut(this._settings.get_double('animation-time'), 0);
+            }
+        }
+    },
+
+    _onOverviewShowing: function() {
+        this._ignoreHover = true;
+        this._intellihide.disable();
+        this._removeAnimations();
+        this._animateIn(this._settings.get_double('animation-time'), 0);
+    },
+
+    _onOverviewHiding: function() {
+        this._ignoreHover = false;
+        this._intellihide.enable();
+        this._updateDashVisibility();
+    },
+
+    _hoverChanged: function() {
+
+        if (!this._ignoreHover) {
+
+            // Skip if dock is not in autohide mode for instance because it is shown
+            // by intellihide.
+            if(this._autohideIsEnabled) {
+                if( this._box.hover ) {
+                    this._show();
+                } else {
+                    this._hide();
+                }
+            }
+        }
+    },
+
+    _show: function() {
+
+        if ( this._dockState == State.HIDDEN || this._dockState == State.HIDING ) {
+
+            if(this._dockState == State.HIDING){
+                // suppress all potential queued hiding animations - i.e. added to Tweener but not started,
+                // always give priority to show
+                this._removeAnimations();
+            }
+
+            this.emit("showing");
+            this._animateIn(this._settings.get_double('animation-time'), 0);
+        }
+    },
+
+    _hide: function() {
+
+        // If no hiding animation is running or queued
+        if ( this._dockState == State.SHOWN || this._dockState == State.SHOWING ) {
+
+            let delay;
+
+            if (this._dockState == State.SHOWING) {
+                //if a show already started, let it finish; queue hide without removing the show.
+                // to obtain this I increase the delay to avoid the overlap and interference 
+                // between the animations
+                delay = this._settings.get_double('hide-delay') + this._settings.get_double('animation-time');
+            } else {
+                delay = this._settings.get_double('hide-delay');
+            }
+
+            this.emit("hiding");
+            this._animateOut(this._settings.get_double('animation-time'), delay);
+
+        }
+    },
+
+    _animateIn: function(time, delay) {
+
+        this._dockState = State.SHOWING;
+
+        Tweener.addTween(this._slider,{
+            slidex: 1,
+            time: time,
+            delay: delay,
+            transition: 'easeOutQuad',
+            onComplete: Lang.bind(this, function() {
+                  this._dockState = State.SHOWN;
+                  // Remove barrier so that mouse pointer is released and can access monitors on other side of dock
+                  // NOTE: Delay needed to keep mouse from moving past dock and re-hiding dock immediately. This
+                  // gives users an opportunity to hover over the dock
+                  if (this._removeBarrierTimeoutId > 0) {
+                      Mainloop.source_remove(this._removeBarrierTimeoutId);
+                  }
+                  this._removeBarrierTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, this._removeBarrier));
+              })
+        });
+    },
+
+    _animateOut: function(time, delay){
+
+        this._dockState = State.HIDING;
+        Tweener.addTween(this._slider,{
+            slidex: 0,
+            time: time,
+            delay: delay ,
+            transition: 'easeOutQuad',
+            onComplete: Lang.bind(this, function() {
+                    this._dockState = State.HIDDEN;
+                    this._updateBarrier();
+            })
+        });
+    },
+
+    // Dwelling system based on the GNOME Shell 3.14 messageTray code.
+    _setupDockDwellIfNeeded: function() {
+        // If we don't have extended barrier features, then we need
+        // to support the old tray dwelling mechanism.
+        if (!global.display.supports_extended_barriers() || !this._settings.get_boolean('require-pressure-to-show')) {
+            let pointerWatcher = PointerWatcher.getPointerWatcher();
+            this._dockWatch = pointerWatcher.addWatch(DOCK_DWELL_CHECK_INTERVAL, Lang.bind(this, this._checkDockDwell));
+            this._dockDwelling = false;
+            this._dockDwellUserTime = 0;
+        }
+    },
+
+    _checkDockDwell: function(x, y) {
+        let monitor = this._monitor;
+
+        // Check for the dock area
+        let shouldDwell = (x >= this.staticBox.x1 && x <= this.staticBox.x2 &&
+                           y >= this.staticBox.y1  && y <= this.staticBox.y2);
+
+        // Check for the correct screen edge
+        // Position is approximated to the lower integer
+        if(this._position==St.Side.LEFT){
+            shouldDwell = shouldDwell &&  x == this._monitor.x;
+        } else if(this._position==St.Side.RIGHT) {
+            shouldDwell = shouldDwell &&  x == this._monitor.x + this._monitor.width - 1;
+        } else if(this._position==St.Side.TOP) {
+            shouldDwell = shouldDwell &&  y == this._monitor.y;
+        } else if (this._position==St.Side.BOTTOM) {
+            shouldDwell = shouldDwell &&  y == this._monitor.y + this._monitor.height - 1;
+        }
+
+        if (shouldDwell) {
+            // We only set up dwell timeout when the user is not hovering over the dock
+            // already (!this._box._hover).
+            // The _dockDwelling variable is used so that we only try to
+            // fire off one dock dwell - if it fails (because, say, the user has the mouse down),
+            // we don't try again until the user moves the mouse up and down again.
+            if (!this._dockDwelling && !this._box._hover && this._dockDwellTimeoutId == 0) {
+                // Save the interaction timestamp so we can detect user input
+                let focusWindow = global.display.focus_window;
+                this._dockDwellUserTime = focusWindow ? focusWindow.user_time : 0;
+
+                this._dockDwellTimeoutId = Mainloop.timeout_add(this._settings.get_double('show-delay')*1000,
+                                                                Lang.bind(this, this._dockDwellTimeout));
+                GLib.Source.set_name_by_id(this._dockDwellTimeoutId, '[dash-to-dock] this._dockDwellTimeout');
+            }
+            this._dockDwelling = true;
+        } else {
+            this._cancelDockDwell();
+            this._dockDwelling = false;
+        }
+    },
+
+    _cancelDockDwell: function() {
+        if (this._dockDwellTimeoutId != 0) {
+            Mainloop.source_remove(this._dockDwellTimeoutId);
+            this._dockDwellTimeoutId = 0;
+        }
+    },
+
+    _dockDwellTimeout: function() {
+        this._dockDwellTimeoutId = 0;
+
+        if (this._monitor.inFullscreen)
+            return GLib.SOURCE_REMOVE;
+
+        // We don't want to open the tray when a modal dialog
+        // is up, so we check the modal count for that. When we are in the
+        // overview we have to take the overview's modal push into account
+        if (Main.modalCount > (Main.overview.visible ? 1 : 0))
+            return GLib.SOURCE_REMOVE;
+
+        // If the user interacted with the focus window since we started the tray
+        // dwell (by clicking or typing), don't activate the message tray
+        let focusWindow = global.display.focus_window;
+        let currentUserTime = focusWindow ? focusWindow.user_time : 0;
+        if (currentUserTime != this._dockDwellUserTime)
+            return GLib.SOURCE_REMOVE;
+
+        // Reuse the pressure version function, the logic is the same
+        this._onPressureSensed();
+        return GLib.SOURCE_REMOVE;
+    },
+
+    _updatePressureBarrier: function() {
+        this._canUsePressure = global.display.supports_extended_barriers();
+        let pressureThreshold = this._settings.get_double('pressure-threshold');
+
+        // Remove existing pressure barrier
+        if (this._pressureBarrier) {
+            this._pressureBarrier.destroy();
+            this._pressureBarrier = null;
+        }
+
+        // Create new pressure barrier based on pressure threshold setting
+        if (this._canUsePressure) {
+            this._pressureBarrier = new Layout.PressureBarrier(pressureThreshold, this._settings.get_double('show-delay')*1000,
+                                Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.OVERVIEW);
+            this._pressureBarrier.connect('trigger', Lang.bind(this, function(barrier){
+                if (this._monitor.inFullscreen)
+                    return;
+                this._onPressureSensed();
+            }));
+        }
+    },
+
+    // handler for mouse pressure sensed
+    _onPressureSensed: function() {
+
+        if (Main.overview.visibleTarget)
+            return;
+
+        // In case the mouse move away from the dock area before hovering it, in such case the leave event
+        // would never be triggered and the dock would stay visible forever.
+        let triggerTimeoutId =  Mainloop.timeout_add(250,
+                                                 Lang.bind(this, function() {
+                                                                      triggerTimeoutId = 0;
+                                                                      this._hoverChanged();
+                                                                      return GLib.SOURCE_REMOVE;
+                                                                  }));
+
+        this._show();
+    },
+
+    _onMessageTrayShowing: function() {
+
+        // Temporary move the dash below the top panel so that it slide below it.
+        Main.layoutManager.uiGroup.set_child_below_sibling(this.actor, Main.layoutManager.panelBox);
+
+        // Remove other tweens that could mess with the state machine
+        Tweener.removeTweens(this.actor);
+        this._oldignoreHover = this._ignoreHover;
+        this._ignoreHover = true;
+        this.dash.cleanUpLabels();
+        Tweener.addTween(this.actor, {
+              y: this._y0 - Main.messageTray.actor.height,
+              time: MessageTray.ANIMATION_TIME,
+              transition: 'easeOutQuad'
+            });
+        this._messageTrayShowing = true;
+        this._updateBarrier();
+    },
+
+    _onMessageTrayHiding: function() {
+
+        // Remove other tweens that could mess with the state machine
+        Tweener.removeTweens(this.actor);
+        Tweener.addTween(this.actor, {
+              y: this._y0,
+              time: MessageTray.ANIMATION_TIME,
+              transition: 'easeOutQuad',
+              onComplete: Lang.bind(this, function(){
+                  // Reset desired dash stack order (on top to accept dnd of app icons)
+                  Main.layoutManager.uiGroup.set_child_below_sibling(this.actor, Main.layoutManager.modalDialogGroup);
+                  // restore previous ignoreHover. If it was not set, set it to false
+                  if (this._oldignoreHover !== null)
+                      this._ignoreHover  = this._oldignoreHover;
+                  this._oldignoreHover == null;
+                  if (!isMouseHover(this._box))
+                      this._box.hover = false;
+                })
+            });
+
+        this._messageTrayShowing = false;
+        this._updateBarrier();
+    },
+
+    // Remove pressure barrier
+    _removeBarrier: function() {
+        if (this._barrier) {
+            if (this._pressureBarrier) {
+                this._pressureBarrier.removeBarrier(this._barrier);
+            }
+            this._barrier.destroy();
+            this._barrier = null;
+        }
+        this._removeBarrierTimeoutId = 0;
+        return false;
+    },
+
+    // Update pressure barrier size
+    _updateBarrier: function() {
+        // Remove existing barrier
+        this._removeBarrier();
+
+        // Manually reset pressure barrier
+        // This is necessary because we remove the pressure barrier when it is triggered to show the dock
+        if (this._pressureBarrier) {
+            this._pressureBarrier._reset();
+            this._pressureBarrier._isTriggered = false;
+        }
+
+        // Create new barrier
+        // Note: dash in fixed position doesn't use pressure barrier
+        if (this._slider.actor.visible && this._canUsePressure && this._autohideIsEnabled && this._settings.get_boolean('require-pressure-to-show') && !this._messageTrayShowing) {
+            let x1, x2, y1, y2, direction;
+
+            if(this._position==St.Side.LEFT){
+                x1 = this.staticBox.x1;
+                x2 = this.staticBox.x1;
+                y1 = this.staticBox.y1;
+                y2 = this.staticBox.y2;
+                direction = Meta.BarrierDirection.POSITIVE_X;
+            } else if(this._position==St.Side.RIGHT) {
+                x1 = this.staticBox.x2;
+                x2 = this.staticBox.x2;
+                y1 = this.staticBox.y1;
+                y2 = this.staticBox.y2;
+                direction = Meta.BarrierDirection.NEGATIVE_X;
+            } else if(this._position==St.Side.TOP) {
+                x1 = this.staticBox.x1;
+                x2 = this.staticBox.x2;
+                y1 = this.staticBox.y1;
+                y2 = this.staticBox.y1;
+                direction = Meta.BarrierDirection.POSITIVE_Y;
+            } else if (this._position==St.Side.BOTTOM) {
+                x1 = this.staticBox.x1;
+                x2 = this.staticBox.x2;
+                y1 = this.staticBox.y2;
+                y2 = this.staticBox.y2;
+                direction = Meta.BarrierDirection.NEGATIVE_Y;
+            }
+
+            this._barrier = new Meta.Barrier({display: global.display,
+                                x1: x1, x2: x2,
+                                y1: y1, y2: y2,
+                                directions: direction});
+            if (this._pressureBarrier) {
+                this._pressureBarrier.addBarrier(this._barrier);
+            }
+        }
+
+    },
+
+    _isPrimaryMonitor: function() {
+        return (this._monitor.x == Main.layoutManager.primaryMonitor.x &&
+             this._monitor.y == Main.layoutManager.primaryMonitor.y);
+    },
+
+    _resetPosition: function() {
+
+        // Ensure variables linked to settings are updated.
+        this._updateVisibilityMode();
+
+        this._monitor = this._getMonitor();
+
+        let unavailableTopSpace = 0;
+        let unavailableBottomSpace = 0;
+
+        let extendHeight = this._settings.get_boolean('extend-height');
+
+        // Reserve space for the dash on the overview
+        // if the dock is on the primary monitor
+        if (this._isPrimaryMonitor()){
+            unavailableTopSpace = Main.panel.actor.height;
+            this._dashSpacer.show();
+        } else {
+            // No space is required in the overview of the dash
+            this._dashSpacer.hide();
+        }
+
+        let fraction = this._settings.get_double('height-fraction');
+
+        if(extendHeight)
+            fraction = 1;
+        else if(fraction<0 || fraction >1)
+            fraction = 0.95;
+
+        let anchor_point;
+
+        if(this._isHorizontal){
+
+            let availableWidth = this._monitor.width;
+            this.actor.width = Math.round( fraction * availableWidth);
+
+            let pos_y;
+            if( this._position == St.Side.BOTTOM) {
+                pos_y =  this._monitor.y + this._monitor.height;
+                anchor_point = Clutter.Gravity.SOUTH_WEST;
+            } else {
+                pos_y =  this._monitor.y + unavailableTopSpace;
+                anchor_point = Clutter.Gravity.NORTH_WEST;
+            }
+
+            this.actor.move_anchor_point_from_gravity(anchor_point);
+            this.actor.x = this._monitor.x + Math.round( (1-fraction)/2 * availableWidth);
+            this.actor.y = pos_y;
+
+            if(extendHeight){
+                this.dash._container.set_width(this.actor.width);
+                this.actor.add_style_class_name('extended');
+            } else {
+                this.dash._container.set_width(-1);
+                this.actor.remove_style_class_name('extended');
+            }
+
+        } else {
+
+            let availableHeight = this._monitor.height - unavailableTopSpace - unavailableBottomSpace;
+            this.actor.height = Math.round( fraction * availableHeight);
+
+            let pos_x;
+            if( this._position == St.Side.RIGHT) {
+                pos_x =  this._monitor.x + this._monitor.width;
+                anchor_point = Clutter.Gravity.NORTH_EAST;
+            } else {
+                pos_x =  this._monitor.x;
+                anchor_point = Clutter.Gravity.NORTH_WEST;
+            }
+
+            this.actor.move_anchor_point_from_gravity(anchor_point);
+            this.actor.x = pos_x;
+            this.actor.y = this._monitor.y + unavailableTopSpace + Math.round( (1-fraction)/2 * availableHeight);
+
+            if(extendHeight){
+                this.dash._container.set_height(this.actor.height);
+                this.actor.add_style_class_name('extended');
+            } else {
+                this.dash._container.set_height(-1);
+                this.actor.remove_style_class_name('extended');
+            }
+        }
+
+        this._y0 = this.actor.y;
+        this._adjustPanelCorners();
+
+        this._updateStaticBox();
+    },
+
+    _updateStaticBox: function() {
+
+        this.staticBox.init_rect(
+            this.actor.x + this._slider.actor.x - (this._position==St.Side.RIGHT?this._box.width:0),
+            this.actor.y + this._slider.actor.y - (this._position==St.Side.BOTTOM?this._box.height:0),
+            this._box.width,
+            this._box.height
+        );
+
+        this._intellihide.updateTargetBox(this.staticBox);
+    },
+
+    // Adjust Panel corners
+    _adjustPanelCorners: function() {
+        let extendHeight = this._settings.get_boolean('extend-height');
+        if (!this._isHorizontal && this._isPrimaryMonitor() && extendHeight && this._fixedIsEnabled) {
+            Main.panel._rightCorner.actor.hide();
+            Main.panel._leftCorner.actor.hide();
+        } else {
+            this._revertPanelCorners();
+        }
+    },
+
+    _revertPanelCorners: function() {
+        Main.panel._leftCorner.actor.show();
+        Main.panel._rightCorner.actor.show();
+    },
+
+    _getMonitor: function(){
+
+        let monitorIndex = this._settings.get_int('preferred-monitor');
+        let monitor;
+
+        if (monitorIndex >0 && monitorIndex< Main.layoutManager.monitors.length)
+            monitor = Main.layoutManager.monitors[monitorIndex];
+        else
+            monitor = Main.layoutManager.primaryMonitor;
+
+        return monitor;
+    },
+
+    _removeAnimations: function() {
+        Tweener.removeTweens(this._slider);
+    },
+
+    _onDragStart: function(){
+        // The dash need to be above the top_window_group, otherwise it doesn't
+        // accept dnd of app icons when not in overiew mode.
+        Main.layoutManager.uiGroup.set_child_above_sibling(this.actor, global.top_window_group);
+        this._oldignoreHover = this._ignoreHover;
+        this._ignoreHover = true;
+        this._animateIn(this._settings.get_double('animation-time'), 0);
+    },
+
+    _onDragEnd: function(){
+        // Restore drag default dash stack order
+        Main.layoutManager.uiGroup.set_child_below_sibling(this.actor, Main.layoutManager.modalDialogGroup);
+        if (this._oldignoreHover !== null)
+            this._ignoreHover  = this._oldignoreHover;
+        this._oldignoreHover = null;
+        this._box.sync_hover();
+        if(Main.overview._shown)
+            this._pageChanged();
+    },
+
+    _pageChanged: function() {
+
+        let activePage = Main.overview.viewSelector.getActivePage();
+        let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS ||
+                           activePage == ViewSelector.ViewPage.APPS);
+
+        if(dashVisible){
+            this._animateIn(this._settings.get_double('animation-time'), 0);
+        } else {
+            this._animateOut(this._settings.get_double('animation-time'), 0);
+        }
+    },
+
+    _onPageEmpty: function() {
+        /* The dash spacer is required only in the WINDOWS view if in the default position.
+         * The 'page-empty' signal is emitted in between a change of view,
+         * signalling the spacer can be added and removed without visible effect,
+         * as it's done for the upstream dashSpacer.
+         *
+         * Moreover, hiding the spacer ensure the appGrid allocaton is triggered.
+         * This matter as the appview spring animation is triggered by to first reallocaton of the appGrid,
+         * (See appDisplay.js, line 202 on GNOME Shell 3.14:
+         *                             this._grid.actor.connect('notify::allocation', ...)
+         * which in turn seems to be triggered by changes in the other actors in the overview.
+         * Normally, as far as I could understand, either the dashSpacer being hidden or the workspacesThumbnails
+         * sliding out would trigger the allocation. However, with no stock dash
+         * and no thumbnails, which happen if the user configured only 1 and static workspace,
+         * the animation out of icons is not played.
+         */
+
+        let activePage = Main.overview.viewSelector.getActivePage();
+        this._dashSpacer.visible = (this._isHorizontal || activePage == ViewSelector.ViewPage.WINDOWS);
+    },
+
+    // Show dock and give key focus to it
+    _onAccessibilityFocus: function(){
+        this._box.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
+        this._animateIn(this._settings.get_double('animation-time'), 0);
+    },
+
+    _onShowAppsButtonToggled: function() {
+
+        // Sync the status of the default appButtons. Only if the two statuses are
+        // different, that means the user interacted with the extension provided
+        // application button, cutomize the behaviour. Otherwise the shell has changed the
+        // status (due to the _syncShowAppsButtonToggled function below) and it
+        // has already performed the desired action.
+
+        let selector = Main.overview.viewSelector;
+
+        if(selector._showAppsButton.checked !== this.dash.showAppsButton.checked){
+
+            // find visible view
+            let visibleView;
+            Main.overview.viewSelector.appDisplay._views.every(function(v, index) {
+                if (v.view.actor.visible) {
+                    visibleView = index;
+                    return false;
+                } else {
+                  return true;
+                }
+            });
+
+            if(this.dash.showAppsButton.checked){
+                // force entering overview if needed
+                if (!Main.overview._shown) {
+
+                    let view = Main.overview.viewSelector.appDisplay._views[visibleView].view;
+                    let grid = view._grid;
+
+                    // Animate in the the appview, hide the appGrid to avoiud flashing
+                    // Go to the appView before entering the overview, skipping the workspaces.
+                    // Do this manually avoiding opacity in transitions so that the setting of the opacity
+                    // to 0 doesn't get overwritten.
+                    Main.overview.viewSelector._activePage.opacity = 0;
+                    Main.overview.viewSelector._activePage.hide();
+                    Main.overview.viewSelector._activePage = Main.overview.viewSelector._appsPage;
+                    Main.overview.viewSelector._activePage.show();
+                    grid.actor.opacity = 0;
+                    selector._showAppsButton.checked = true;
+
+                    // The animation has to be trigered manually because the AppDisplay.animate 
+                    // method is waiting for an allocation not happening, as we skip the workspace view
+                    // and the appgrid could already be allocated from previous shown.
+                    // It has to be triggered after the overview is shown as wrong coordinates are obtained
+                    // otherwise.
+                    let overviewShownId = Main.overview.connect('shown', Lang.bind(this, function(){
+                        Main.overview.disconnect(overviewShownId);
+                        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
+                            grid.actor.opacity = 255;
+                            grid.animateSpring(IconGrid.AnimationDirection.IN, this.dash.showAppsButton);
+                        }));
+                      }));
+
+                    // Finally show the overview
+                    Main.overview.show();
+                    this.forcedOverview = true;
+                } else {
+                    selector._showAppsButton.checked = true;
+                }
+            } else {
+                if (this.forcedOverview) {
+                    // force exiting overview if needed
+
+                    // Manually trigger springout animation without activating the
+                    // workspaceView to avoid the zoomout animation. Hide the appPage
+                    // onComplete to avoid ugly flashing of original icons.
+                    let view = Main.overview.viewSelector.appDisplay._views[visibleView].view;
+                    let grid = view._grid;
+                    view.animate(IconGrid.AnimationDirection.OUT, Lang.bind(this, function(){
+                        Main.overview.viewSelector._appsPage.hide();
+                        Main.overview.hide();
+                        selector._showAppsButton.checked = false;
+                        this.forcedOverview = false;
+                    }));
+
+                } else {
+                    selector._showAppsButton.checked = false;
+                }
+
+            }
+        }
+
+        // whenever the button is unactivated even if not by the user still reset the
+        // forcedOverview flag
+        if( this.dash.showAppsButton.checked==false)
+            this.forcedOverview = false;
+    },
+
+    // Keep ShowAppsButton status in sync with the overview status
+    _syncShowAppsButtonToggled: function() {
+        let status = Main.overview.viewSelector._showAppsButton.checked;
+        if(this.dash.showAppsButton.checked !== status)
+            this.dash.showAppsButton.checked = status;
+    },
+
+    // Optional features enable/disable
+
+    // Switch workspace by scrolling over the dock
+    _optionalScrollWorkspaceSwitch: function() {
+
+        let label = 'optionalScrollWorkspaceSwitch';
+
+        this._settings.connect('changed::scroll-switch-workspace',Lang.bind(this, function(){
+            if(this._settings.get_boolean('scroll-switch-workspace'))
+                Lang.bind(this, enable)();
+            else
+                Lang.bind(this, disable)();
+        }));
+
+        if(this._settings.get_boolean('scroll-switch-workspace'))
+            Lang.bind(this, enable)();
+
+        function enable(){
+
+            this._signalsHandler.removeWithLabel(label);
+
+            this._signalsHandler.addWithLabel(label,
+                [
+                    this._box,
+                    'scroll-event',
+                    Lang.bind(this, onScrollEvent)
+                ]
+            );
+
+            this._optionalScrollWorkspaceSwitchDeadTimeId=0;
+        }
+
+        function disable() {
+            this._signalsHandler.removeWithLabel(label);
+
+            if(this._optionalScrollWorkspaceSwitchDeadTimeId>0){
+                Mainloop.source_remove(this._optionalScrollWorkspaceSwitchDeadTimeId);
+                this._optionalScrollWorkspaceSwitchDeadTimeId=0;
+            }
+        }
+
+        // This was inspired to desktop-scroller@obsidien.github.com
+        function onScrollEvent(actor, event) {
+
+            // When in overview change workscape only in windows view
+            if (Main.overview.visible && Main.overview.viewSelector.getActivePage() !== ViewSelector.ViewPage.WINDOWS)
+                return false;
+
+            let activeWs = global.screen.get_active_workspace();
+            let direction = null;
+
+            switch ( event.get_scroll_direction() ) {
+            case Clutter.ScrollDirection.UP:
+                direction = Meta.MotionDirection.UP;
+                break;
+            case Clutter.ScrollDirection.DOWN:
+                direction = Meta.MotionDirection.DOWN;
+                break;
+            case Clutter.ScrollDirection.SMOOTH:
+                let [dx, dy] = event.get_scroll_delta();
+                if(dy < 0){
+                    direction = Meta.MotionDirection.UP;
+                } else if(dy > 0) {
+                    direction = Meta.MotionDirection.DOWN;
+                }
+                break;
+            }
+
+            if(direction !==null ){
+
+                // Prevent scroll events from triggering too many workspace switches
+                // by adding a 250ms deadtime between each scroll event.
+                // Usefull on laptops when using a touchpad.
+
+                // During the deadtime do nothing
+                if(this._optionalScrollWorkspaceSwitchDeadTimeId>0)
+                    return false;
+                else {
+                    this._optionalScrollWorkspaceSwitchDeadTimeId =
+                            Mainloop.timeout_add(250,
+                                Lang.bind(this, function() {
+                                    this._optionalScrollWorkspaceSwitchDeadTimeId=0;
+                                }
+                    ));
+                }
+
+
+                let ws;
+
+                ws = activeWs.get_neighbor(direction)
+
+                if (Main.wm._workspaceSwitcherPopup == null)
+                    Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
+                    // Set the actor non reactive, so that it doesn't prevent the
+                    // clicks events from reaching the dash actor. I can't see a reason
+                    // why it should be reactive.
+                    Main.wm._workspaceSwitcherPopup.actor.reactive = false;
+                    Main.wm._workspaceSwitcherPopup.connect('destroy', function() {
+                        Main.wm._workspaceSwitcherPopup = null;
+                    });
+
+                // Do not show wokspaceSwithcer in overview
+                if(!Main.overview.visible)
+                  Main.wm._workspaceSwitcherPopup.display(direction, ws.index());
+                Main.wm.actionMoveWorkspace(ws);
+
+                return true;
+
+            } else {
+                return false;
+            }
+        }
+
+    },
+
+    // Makes the message not being triggered by mouse. SOURCE: insensitive-tray extension.
+    _updateInsensitiveTray: function() {
+
+        let insensitive = this._settings.get_boolean('insensitive-message-tray');
+
+        if("_trayPressure" in LayoutManager) {
+            // Systems supporting pressure
+            if (insensitive) {
+                LayoutManager._trayPressure._keybindingMode = null;
+            } else {
+                LayoutManager._trayPressure._keybindingMode =  Shell.KeyBindingMode.NORMAL 
+                                                              | Shell.KeyBindingMode.OVERVIEW;
+            }
+        } else {
+            //systems using the old dwell mechanism
+            if (insensitive) {
+                this._injectionsHandler.addWithLabel('insensitive-message-tray',
+                    [
+                        Main.messageTray,
+                        '_trayDwellTimeout',
+                        function() { return false; }
+                    ]
+                );
+            } else {
+                this._injectionsHandler.removeWithLabel('insensitive-message-tray')
+            }
+        }
+    }
+});
+Signals.addSignalMethods(dockedDash.prototype);
+
+/* 
+ * Manage theme customization and custom theme support
+*/
+const themeManager = new Lang.Class({
+    Name: 'ThemeManager',
+
+    _init: function(settings, actor, dash) {
+
+        this._settings = settings;
+        this._bindSettingsChanges();
+        this._actor = actor;
+        this._dash = dash;
+
+        // initialize colors with generic values
+        this._defaultBackground = {red: 0, green:0, blue: 0, alpha:0};
+        this._defaultBackgroundColor = {red: 0, green:0, blue: 0, alpha:0};
+        this._customizedBackground = {red: 0, green:0, blue: 0, alpha:0};
+
+        this._signalsHandler = new Convenience.GlobalSignalsHandler();
+        this._signalsHandler.add(
+            // When theme changes re-obtain default background color
+            [
+              St.ThemeContext.get_for_stage (global.stage),
+              'changed',
+              Lang.bind(this, this.updateCustomTheme)
+            ],
+            // update :overview pseudoclass
+            [
+                Main.overview,
+                'showing',
+                Lang.bind(this, this._onOverviewShowing)
+            ],
+            [
+                Main.overview,
+                'hiding',
+                Lang.bind(this, this._onOverviewHiding)
+            ]
+        );
+
+        this._updateCustomStyleClasses();
+
+    },
+
+    destroy: function() {
+        this._signalsHandler.destroy();
+    },
+
+    _onOverviewShowing: function() {
+        this._actor.add_style_pseudo_class('overview');
+    },
+
+    _onOverviewHiding: function() {
+        this._actor.remove_style_pseudo_class('overview');
+    },
+
+    _updateBackgroundOpacity: function() {
+
+        let newAlpha = this._settings.get_double('background-opacity');
+
+        this._defaultBackground = 'rgba('+
+            this._defaultBackgroundColor.red + ','+
+            this._defaultBackgroundColor.green + ','+
+            this._defaultBackgroundColor.blue + ','+
+            Math.round(this._defaultBackgroundColor.alpha/2.55)/100 + ')';
+
+        this._customizedBackground = 'rgba('+
+            this._defaultBackgroundColor.red + ','+
+            this._defaultBackgroundColor.green + ','+
+            this._defaultBackgroundColor.blue + ','+
+            newAlpha + ')';
+    },
+
+    _getBackgroundColor: function() {
+
+        // Prevent shell crash if the actor is not on the stage.
+        // It happens enabling/disabling repeatedly the extension
+        if(!this._dash._container.get_stage())
+            return;
+
+        // Remove custom style
+        let oldStyle = this._dash._container.get_style();
+        this._dash._container.set_style(null);
+
+        let themeNode = this._dash._container.get_theme_node();
+        this._dash._container.set_style(oldStyle);
+
+        this._defaultBackgroundColor = themeNode.get_background_color();
+    },
+
+    _updateCustomStyleClasses: function(){
+
+        if (this._settings.get_boolean('apply-custom-theme'))
+            this._actor.add_style_class_name('dashtodock');
+        else {
+            this._actor.remove_style_class_name('dashtodock');
+        }
+
+        if (this._settings.get_boolean('custom-theme-shrink'))
+            this._actor.add_style_class_name('shrink');
+        else {
+            this._actor.remove_style_class_name('shrink');
+        }
+
+        if (this._settings.get_boolean('custom-theme-running-dots'))
+            this._actor.add_style_class_name('running-dots');
+        else {
+            this._actor.remove_style_class_name('running-dots');
+        }
+
+    },
+
+    updateCustomTheme: function() {
+        this._updateCustomStyleClasses();
+        this._getBackgroundColor();
+        this._updateBackgroundOpacity();
+        this._adjustTheme();
+        this._dash._redisplay();
+    },
+
+    /* Reimported back and adapted from atomdock */
+    _adjustTheme: function() {
+        // Prevent shell crash if the actor is not on the stage.
+        // It happens enabling/disabling repeatedly the extension
+        if (!this._dash._container.get_stage()) {
+            return;
+        }
+
+        // Remove prior style edits
+        this._dash._container.set_style(null);
+
+        /* If built-in theme is enabled do nothing else */
+        if( this._settings.get_boolean('apply-custom-theme') )
+            return;
+
+        let newStyle = '';
+        let position = getPosition(this._settings);
+
+        if ( ! this._settings.get_boolean('custom-theme-shrink') ) {
+
+            // obtain theme border settings
+            let themeNode = this._dash._container.get_theme_node();
+            let borderColor = themeNode.get_border_color(St.Side.TOP);
+            let borderWidth = themeNode.get_border_width(St.Side.TOP);
+            let borderRadius = themeNode.get_border_radius(St.Corner.TOPRIGHT);
+
+            /* We're copying border and corner styles to left border and top-left
+            * corner, also removing bottom border and bottom-right corner styles
+            */
+            let borderInner = '';
+            let borderRadiusValue = '';
+            let borderMissingStyle = '';
+
+            if (this._rtl && position != St.Side.RIGHT) {
+                borderMissingStyle = 'border-right: ' + borderWidth + 'px solid ' +
+                       borderColor.to_string() + ';';
+            } else if (!this._rtl && position != St.Side.LEFT){
+                borderMissingStyle = 'border-left: ' + borderWidth + 'px solid ' +
+                       borderColor.to_string() + ';';
+            }
+
+            switch(position) {
+                case St.Side.LEFT:
+                    borderInner = 'border-left';
+                    borderRadiusValue = '0 ' + borderRadius + 'px ' + borderRadius + 'px 0;';
+                    break;
+                case St.Side.RIGHT:
+                    borderInner = 'border-right';
+                    borderRadiusValue = borderRadius + 'px 0 0 ' + borderRadius + 'px;';
+                    break;
+                case St.Side.TOP:
+                    borderInner = 'border-top';
+                    borderRadiusValue = '0 0 ' + borderRadius + 'px ' + borderRadius + 'px;';
+                    break;
+                case St.Side.BOTTOM:
+                    borderInner = 'border-bottom';
+                    borderRadiusValue = borderRadius + 'px ' + borderRadius + 'px 0 0;';
+                    break;
+            }
+
+            newStyle = borderInner + ': none;' +
+            'border-radius: ' + borderRadiusValue +
+            borderMissingStyle ;
+
+            /* I do call set_style possibly twice so that only the background gets the transition.
+            *  The transition-property css rules seems to be unsupported
+            */
+            this._dash._container.set_style(newStyle);
+        }
+
+        /* Customize background */
+        if ( this._settings.get_boolean('opaque-background')  ) {
+            newStyle = newStyle + 'background-color:'+ this._customizedBackground + '; ' +
+                       'transition-delay: 0s; transition-duration: 0.250s;';
+            this._dash._container.set_style(newStyle);
+        }
+    },
+
+    _bindSettingsChanges: function() {
+
+         let keys = ['opaque-background',
+                     'background-opacity',
+                     'apply-custom-theme',
+                     'custom-theme-shrink',
+                     'custom-theme-running-dots',
+                     'extend-height'];
+
+         keys.forEach(function(key){
+            this._settings.connect('changed::'+key,
+                                   Lang.bind(this, this.updateCustomTheme)
+            );
+          }, this );
+
+    }
+});
+
+
+/*
+ * Manually check if mouse "can be" hover from the mouse position. The hover porperty
+ * is not reliable when focus move from the clutter actors to the the windows, giving a false
+ * positive hover status. If the mouse pointer is not in the right position I can be sure
+ * that the hover has to be false.
+*/
+function isMouseHover(actor) {
+    let [pointerX, pointerY, mods] = global.get_pointer();
+
+    let [x, y] = actor.get_transformed_position();
+    let [width, height] =actor.get_transformed_size();
+
+    let test = (pointerX < x + width) &&
+               (pointerX > x) &&
+               (pointerY < y + height) &&
+               (pointerY > y);
+
+   return test;
+}
diff --git a/extensions/dash-to-dock/extension.js b/extensions/dash-to-dock/extension.js
new file mode 100644
index 0000000..4bd19fa
--- /dev/null
+++ b/extensions/dash-to-dock/extension.js
@@ -0,0 +1,52 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Me = imports.misc.extensionUtils.getCurrentExtension();
+const Convenience = Me.imports.convenience;
+const DockedDash = Me.imports.dockedDash;
+
+const Main = imports.ui.main;
+
+let settings;
+let dock;
+
+let oldDash;
+
+function init() {
+
+}
+
+function enable() {
+
+    settings = Convenience.getSettings('org.gnome.shell.extensions.dash-to-dock');
+    dock = new DockedDash.dockedDash(settings);
+
+    /* Pretend I'm the dash: meant to make appgrd swarm animation come from the
+     * right position of the appShowButton.
+     */
+    oldDash  = Main.overview._dash;
+    Main.overview._dash = dock.dash;
+    bindSettingsChanges();
+}
+
+function disable() {
+    dock.destroy();
+    settings.run_dispose();
+    Main.overview._dash = oldDash;
+
+    dock=null;
+    settings = null;
+    oldDash=null;
+}
+
+
+function bindSettingsChanges() {
+    // This settings change require a full reload.
+
+    /* It's easier to just reload the extension when the dock position changes
+     * rather than working out all changes to the differen containers.
+     */
+    settings.connect('changed::dock-position', function(){
+        disable();
+        enable();
+    });
+}
diff --git a/extensions/dash-to-dock/intellihide.js b/extensions/dash-to-dock/intellihide.js
new file mode 100644
index 0000000..0c79cee
--- /dev/null
+++ b/extensions/dash-to-dock/intellihide.js
@@ -0,0 +1,278 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+
+const Main = imports.ui.main;
+const Signals = imports.signals;
+
+const Me = imports.misc.extensionUtils.getCurrentExtension();
+const Convenience = Me.imports.myConvenience;
+
+// A good compromise between reactivity and efficiency; to be tuned.
+const INTELLIHIDE_CHECK_INTERVAL = 100;
+
+const OverlapStatus = {
+    UNDEFINED: -1,
+    FALSE: 0,
+    TRUE: 1
+};
+
+// List of windows type taken into account. Order is important (keep the original
+// enum order).
+const handledWindowTypes = [
+  Meta.WindowType.NORMAL,
+  Meta.WindowType.DIALOG,
+  Meta.WindowType.MODAL_DIALOG,
+  Meta.WindowType.TOOLBAR,
+  Meta.WindowType.MENU,
+  Meta.WindowType.UTILITY,
+  Meta.WindowType.SPLASHSCREEN
+];
+
+/*
+ * A rough and ugly implementation of the intellihide behaviour.
+ * Intallihide object: emit 'status-changed' signal when the overlap of windows
+ * with the provided targetBoxClutter.ActorBox changes;
+ * 
+*/
+
+const intellihide = new Lang.Class({
+    Name: 'Intellihide',
+
+    _init: function(settings) {
+
+        // Load settings
+        this._settings = settings;
+
+        this._signalsHandler = new Convenience.GlobalSignalsHandler();
+        this._tracker = Shell.WindowTracker.get_default();
+        this._focusApp = null;
+
+        this._isEnabled = false;
+        this.status = OverlapStatus.UNDEFINED;
+        this._targetBox = null;
+
+        // Main id of the timeout controlling timeout for updateDockVisibility function 
+        // when windows are dragged around (move and resize)
+        this._windowChangedTimeout = 0;
+
+        // Connect global signals
+        this._signalsHandler.add (
+            // Add timeout when window grab-operation begins and remove it when it ends.
+            [
+                global.display,
+                'grab-op-begin',
+                Lang.bind(this, this._grabOpBegin)
+            ],
+            [
+                global.display,
+                'grab-op-end',
+                Lang.bind(this, this._grabOpEnd)
+            ],
+            // direct maximize/unmazimize are not included in grab-operations
+            [
+                global.window_manager,
+                'maximize', 
+                Lang.bind(this, this._checkOverlap )
+            ],
+            [
+                global.window_manager,
+                'unmaximize',
+                Lang.bind(this, this._checkOverlap )
+            ],
+            // triggered for instance when the window list order changes,
+            // included when the workspace is switched
+            [
+                global.screen,
+                'restacked',
+                Lang.bind(this, this._checkOverlap)
+            ],
+            // update wne monitor changes, for instance in multimonitor when monitor are attached
+            [
+                global.screen,
+                'monitors-changed',
+                Lang.bind(this, this._checkOverlap )
+            ]
+        );
+
+    },
+
+    destroy: function() {
+
+        // Disconnect global signals
+        this._signalsHandler.destroy();
+
+        if(this._windowChangedTimeout>0)
+            Mainloop.source_remove(this._windowChangedTimeout); // Just to be sure
+        this._windowChangedTimeout=0;
+    },
+
+    enable: function() {
+
+      this._isEnabled = true;
+      this._status = OverlapStatus.UNDEFINED;
+      this._checkOverlap();
+    },
+
+    disable: function() {
+        this._isEnabled = false;
+        if(this._windowChangedTimeout>0)
+            Mainloop.source_remove(this._windowChangedTimeout);
+        this._windowChangedTimeout = 0;
+    },
+
+    updateTargetBox: function(box) {
+        this._targetBox = box;
+        this._checkOverlap();
+    },
+
+    forceUpdate: function() {
+        this._status = OverlapStatus.UNDEFINED;
+        this._checkOverlap();
+    },
+
+    getOverlapStatus: function(){
+        if(this._status == OverlapStatus.TRUE)
+            return true;
+        else
+            return false;
+    },
+
+    _grabOpBegin: function() {
+        if(this._isEnabled){
+            if(this._windowChangedTimeout>0)
+                Mainloop.source_remove(this._windowChangedTimeout); // Just to be sure
+
+            this._windowChangedTimeout = Mainloop.timeout_add(INTELLIHIDE_CHECK_INTERVAL,
+                Lang.bind(this, function(){
+                    this._checkOverlap();
+                    return true; // to make the loop continue
+                })
+            );
+        }
+    },
+
+    _grabOpEnd: function() {
+
+            if(this._windowChangedTimeout>0)
+                Mainloop.source_remove(this._windowChangedTimeout);
+
+            this._windowChangedTimeout=0;
+            this._checkOverlap();
+    },
+
+    _checkOverlap: function() {
+
+        if( !this._isEnabled || this._targetBox == null)
+            return;
+
+        let overlaps = OverlapStatus.FALSE;
+        let windows = global.get_window_actors();
+
+        if (windows.length>0){
+
+            // This is the window on top of all others in the current workspace
+            let topWindow = windows[windows.length-1].get_meta_window();
+            // If there isn't a focused app, use that of the window on top
+            this._focusApp = this._tracker.focus_app || this._tracker.get_window_app(topWindow);
+
+            windows = windows.filter(this._intellihideFilterInteresting, this);
+
+            for(let i=0; i< windows.length; i++){
+
+                let win = windows[i].get_meta_window();
+                if(win){
+                    let rect = win.get_outer_rect();
+
+                    let test = ( rect.x < this._targetBox.x2) &&
+                               ( rect.x +rect.width > this._targetBox.x1 ) &&
+                               ( rect.y < this._targetBox.y2 ) &&
+                               ( rect.y +rect.height > this._targetBox.y1 );
+
+                    if(test){
+                        overlaps = OverlapStatus.TRUE;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if ( this._status !== overlaps ) {
+            this._status = overlaps;
+            this.emit('status-changed', this._status);
+        }
+
+    },
+
+    // Filter interesting windows to be considered for intellihide.
+    // Consider all windows visible on the current workspace.
+    // Optionally skip windows of other applications
+    _intellihideFilterInteresting: function(wa){
+
+        var currentWorkspace = global.screen.get_active_workspace_index();
+
+        var meta_win = wa.get_meta_window();
+        if (!meta_win) {
+            return false;
+        }
+
+        if ( !this._handledWindow(meta_win) )
+            return false;
+
+        var wksp = meta_win.get_workspace();
+        var wksp_index = wksp.index();
+
+        // Skip windows of other apps
+        if(this._focusApp && this._settings.get_boolean('intellihide-perapp')) {
+            // The DropDownTerminal extension is not an application per se
+            // so we match its window by wm class instead
+            if (meta_win.get_wm_class() == 'DropDownTerminalWindow')
+                return true;
+
+            let currentApp = this._tracker.get_window_app(meta_win);
+
+            // But consider half maximized windows ( Useful if one is using
+            // two apps side by side and windows which are alwayson top
+            if( this._focusApp != currentApp
+                && !(meta_win.maximized_vertically && !meta_win.maximized_horizontally)
+                && !meta_win.is_above()
+              ) {
+                return false;
+            }
+        }
+
+        if ( wksp_index == currentWorkspace && meta_win.showing_on_its_workspace() ) {
+            return true;
+        } else {
+            return false;
+        }
+
+    },
+
+    // Filter windows by type
+    // inspired by Opacify@gnome-shell.localdomain.pl
+    _handledWindow: function(metaWindow) {
+        // The DropDownTerminal extension uses the POPUP_MENU window type hint
+        // so we match its window by wm class instead
+        if (metaWindow.get_wm_class() == 'DropDownTerminalWindow')
+            return true;
+
+        var wtype = metaWindow.get_window_type();
+        for (var i = 0; i < handledWindowTypes.length; i++) {
+            var hwtype = handledWindowTypes[i];
+            if (hwtype == wtype) {
+                return true;
+            } else if (hwtype > wtype) {
+                return false;
+            }
+        }
+        return false;
+
+    }
+
+});
+
+Signals.addSignalMethods(intellihide.prototype);
diff --git a/extensions/dash-to-dock/media/four.svg b/extensions/dash-to-dock/media/four.svg
new file mode 100644
index 0000000..8653206
--- /dev/null
+++ b/extensions/dash-to-dock/media/four.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="four.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="725"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="46.2185"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer4"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline">
+    <g
+       id="four">
+      <g
+         transform="translate(-1.574707e-8,0.11602783)"
+         id="g4330">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="65.883972"
+           cx="5.8348255"
+           id="path3762-2-6"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="53.883972"
+           cx="5.8348255"
+           id="path3762-2-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="41.883972"
+           cx="5.8348255"
+           id="path3762-2-5"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="29.883972"
+           cx="5.8348255"
+           id="path3762-2-9-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4141"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+</svg>
diff --git a/extensions/dash-to-dock/media/four_bottom.svg b/extensions/dash-to-dock/media/four_bottom.svg
new file mode 100644
index 0000000..3fc4cb2
--- /dev/null
+++ b/extensions/dash-to-dock/media/four_bottom.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="four_bottom.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="44.804286"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer4"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline">
+    <g
+       id="four"
+       transform="rotate(-90,48,48)">
+      <g
+         transform="translate(-1.574707e-8,0.11602783)"
+         id="g4330">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="65.883972"
+           cx="5.8348255"
+           id="path3762-2-6"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="53.883972"
+           cx="5.8348255"
+           id="path3762-2-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="41.883972"
+           cx="5.8348255"
+           id="path3762-2-5"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="29.883972"
+           cx="5.8348255"
+           id="path3762-2-9-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4141"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+</svg>
diff --git a/extensions/dash-to-dock/media/four_rtl.svg b/extensions/dash-to-dock/media/four_rtl.svg
new file mode 100644
index 0000000..67dcf28
--- /dev/null
+++ b/extensions/dash-to-dock/media/four_rtl.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="four_rtl.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="46.2185"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer4"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline">
+    <g
+       id="four"
+       transform="rotate(180,48,48)">
+      <g
+         transform="translate(-1.574707e-8,0.11602783)"
+         id="g4330">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="65.883972"
+           cx="5.8348255"
+           id="path3762-2-6"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="53.883972"
+           cx="5.8348255"
+           id="path3762-2-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="41.883972"
+           cx="5.8348255"
+           id="path3762-2-5"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="29.883972"
+           cx="5.8348255"
+           id="path3762-2-9-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4141"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+</svg>
diff --git a/extensions/dash-to-dock/media/four_top.svg b/extensions/dash-to-dock/media/four_top.svg
new file mode 100644
index 0000000..1b3dfcb
--- /dev/null
+++ b/extensions/dash-to-dock/media/four_top.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="four_top.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="725"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="46.2185"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer4"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline">
+    <g
+       id="four"
+       transform="rotate(90,48,48)">
+      <g
+         transform="translate(-1.574707e-8,0.11602783)"
+         id="g4330">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="65.883972"
+           cx="5.8348255"
+           id="path3762-2-6"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="53.883972"
+           cx="5.8348255"
+           id="path3762-2-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="41.883972"
+           cx="5.8348255"
+           id="path3762-2-5"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="29.883972"
+           cx="5.8348255"
+           id="path3762-2-9-8"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4141"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+</svg>
diff --git a/extensions/dash-to-dock/media/logo.svg b/extensions/dash-to-dock/media/logo.svg
new file mode 100644
index 0000000..509d2e5
--- /dev/null
+++ b/extensions/dash-to-dock/media/logo.svg
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="33.866665mm"
+   height="33.866684mm"
+   viewBox="0 0 33.866665 33.866683"
+   id="svg5179"
+   version="1.1"
+   inkscape:version="0.91+devel r13847 custom"
+   sodipodi:docname="logo.svg">
+  <defs
+     id="defs5181">
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4379-92-4-9-6-8-0">
+      <rect
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.83189655;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+         id="rect4381-17-7-5-2-0-6"
+         width="19.934219"
+         height="33.52573"
+         x="356.02826"
+         y="457.71631" />
+    </clipPath>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter4435-8-5-3-2-13-8"
+       x="-0.22881356"
+       width="1.4576271"
+       y="-0.22881356"
+       height="1.4576271">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.0352993"
+         id="feGaussianBlur4437-6-7-9-8-8-1" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter4365-71-5-7-0-6-2"
+       x="-0.21864407"
+       width="1.437288"
+       y="-0.21864407"
+       height="1.437288">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.98928601"
+         id="feGaussianBlur4367-74-5-92-0-6-5" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4379-6-7-5-8-6-01-2">
+      <rect
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.83189655;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+         id="rect4381-1-8-5-2-0-2-7"
+         width="19.934219"
+         height="33.52573"
+         x="356.02826"
+         y="457.71631" />
+    </clipPath>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter4435-6-1-2-8-2-2-7"
+       x="-0.22881356"
+       width="1.4576271"
+       y="-0.22881356"
+       height="1.4576271">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.0352993"
+         id="feGaussianBlur4437-1-1-3-60-1-4-4" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter4365-4-5-2-24-7-3-3"
+       x="-0.21864407"
+       width="1.437288"
+       y="-0.21864407"
+       height="1.437288">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.98928601"
+         id="feGaussianBlur4367-7-0-7-7-9-0-3" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4379-5-6-0-9-8-7-9">
+      <rect
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.83189655;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+         id="rect4381-6-8-5-9-9-2-4"
+         width="19.934219"
+         height="33.52573"
+         x="356.02826"
+         y="457.71631" />
+    </clipPath>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter4435-63-9-2-4-1-2-6"
+       x="-0.22881356"
+       width="1.4576271"
+       y="-0.22881356"
+       height="1.4576271">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.0352993"
+         id="feGaussianBlur4437-0-5-6-8-8-9-9" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter4365-2-4-3-6-3-1-7"
+       x="-0.21864407"
+       width="1.437288"
+       y="-0.21864407"
+       height="1.437288">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.98928601"
+         id="feGaussianBlur4367-1-2-5-3-5-8-3" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:collect="always"
+       id="filter7280-5-3-4-6-6">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.4835784"
+         id="feGaussianBlur7282-3-5-6-93-8" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="4"
+     inkscape:cx="94.616787"
+     inkscape:cy="11.368268"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1366"
+     inkscape:window-height="704"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata5184">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(136.97858,-11.552354)">
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#0055d4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       id="rect4006-4-6-9-2-0-6"
+       width="33.83363"
+       height="33.859909"
+       x="-136.9473"
+       y="11.552354"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.15440008;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       d="m -130.12265,11.559157 c -4.30029,5.691881 -6.67207,12.608761 -6.82289,19.674442 -0.0115,0.54232 -0.0147,1.0766 0,1.62024 0.11433,4.23572 1.04846,8.50668 2.82497,12.565201 l 31.00865,0 0,-33.859883 -27.01073,0 z"
+       id="path6097-2-6-0-89-4"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate"
+       d="m -136.9473,18.430158 0,0.7896 0,20.641361 0,0.7896 1.23782,0 2.26288,0 1.60528,0 c 0.68577,0 1.23783,-0.3548 1.23783,-0.7896 l 0,-20.641361 c 0,-0.4398 -0.55206,-0.7896 -1.23783,-0.7896 l -1.60528,0 -2.26288,0 z"
+       id="rect4008-7-9-2-0-3-4"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccssssccc"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.15;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.15440008;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       d="m -119.36792,11.559157 c -10.47023,5.721881 -17.57762,16.847401 -17.57762,29.627402 0,1.43804 0.0897,2.841801 0.26432,4.232481 l 33.5693,0 0,-33.859883 -16.256,0 z"
+       id="path6097-4-5-23-9"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       id="rect4247-4-4-5-3-8-1"
+       width="33.83363"
+       height="2.1162443"
+       x="-136.9473"
+       y="11.552354"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       d="m -103.11365,13.668597 0,1.05812 c 0,-0.58196 -0.47338,-1.05812 -1.05731,-1.05812 l 1.05731,0 z"
+       id="rect4272-0-7-8-1-1-3-3-1"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       id="rect4031-9-9-2-4-2-5"
+       width="4.2292037"
+       height="4.2324886"
+       x="-135.89"
+       y="19.488146"
+       rx="1.0583334"
+       ry="1.0583334"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       d="m -136.94728,13.668597 0,1.05812 c 0,-0.58196 0.47337,-1.05812 1.0573,-1.05812 l -1.0573,0 z"
+       id="rect4272-0-2-1-74-41-1-6"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <g
+       id="g4353-9-2-1-5-5-4"
+       transform="matrix(0.10331261,0,0,0.10339285,-173.76079,-27.453246)"
+       clip-path="url(#clipPath4379-92-4-9-6-8-0)"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099">
+      <circle
+         r="5.4295697"
+         cy="477.71164"
+         cx="274.13016"
+         transform="matrix(0.94749688,0,0,0.94749688,96.290796,21.848877)"
+         id="path3153-1-7-3-5-60-3-6"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.42241378;fill:#d7eef4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;filter:url(#filter4435-8-5-3-2-13-8);enable-background:accumulate" />
+      <circle
+         r="5.4295697"
+         cy="477.71164"
+         cx="274.13016"
+         transform="matrix(0.24231546,0,0,0.24231546,289.60229,358.72226)"
+         id="path3153-2-4-1-6-6-9-4-1"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d7eef4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;filter:url(#filter4365-71-5-7-0-6-2);enable-background:accumulate" />
+    </g>
+    <g
+       id="g4589-4-1-1-3-6-2"
+       transform="matrix(0.49926208,0,0,0.49964988,-318.21072,-206.05794)"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099">
+      <g
+         clip-path="url(#clipPath4379-6-7-5-8-6-01-2)"
+         transform="matrix(0.20693061,0,0,0.20693061,289.32686,368.5622)"
+         id="g4353-66-1-4-2-6-94-5">
+        <circle
+           r="5.4295697"
+           cy="477.71164"
+           cx="274.13016"
+           style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.42241378;fill:#d7eef4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;filter:url(#filter4435-6-1-2-8-2-2-7);enable-background:accumulate"
+           id="path3153-1-6-4-5-63-7-1-0"
+           transform="matrix(0.94749688,0,0,0.94749688,96.290796,21.848877)" />
+        <circle
+           r="5.4295697"
+           cy="477.71164"
+           cx="274.13016"
+           style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d7eef4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;filter:url(#filter4365-4-5-2-24-7-3-3);enable-background:accumulate"
+           id="path3153-2-4-7-6-5-8-5-9-5"
+           transform="matrix(0.24231546,0,0,0.24231546,289.60229,358.72226)" />
+      </g>
+      <g
+         clip-path="url(#clipPath4379-5-6-0-9-8-7-9)"
+         transform="matrix(0.20693061,0,0,0.20693061,289.32686,367.53449)"
+         id="g4353-7-2-2-6-4-5-1">
+        <circle
+           r="5.4295697"
+           cy="477.71164"
+           cx="274.13016"
+           style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.42241378;fill:#d7eef4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;filter:url(#filter4435-63-9-2-4-1-2-6);enable-background:accumulate"
+           id="path3153-1-19-3-1-5-5-7-8"
+           transform="matrix(0.94749688,0,0,0.94749688,96.290796,21.848877)" />
+        <circle
+           r="5.4295697"
+           cy="477.71164"
+           cx="274.13016"
+           style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d7eef4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;filter:url(#filter4365-2-4-3-6-3-1-7);enable-background:accumulate"
+           id="path3153-2-4-5-7-9-9-9-7-6"
+           transform="matrix(0.24231546,0,0,0.24231546,289.60229,358.72226)" />
+      </g>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:1.28805089px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none"
+       x="-124.44726"
+       y="13.10139"
+       id="text4824-5-2-0-4-8"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099"
+       transform="scale(0.99961185,1.0003883)"><tspan
+         sodipodi:role="line"
+         id="tspan4826-16-3-8-8-1"
+         x="-124.44726"
+         y="13.10139">Dash to Dock</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:1.28805089px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none"
+       x="-136.50272"
+       y="13.10139"
+       id="text4824-8-8-6-8-7-4"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099"
+       transform="scale(0.99961185,1.0003883)"><tspan
+         sodipodi:role="line"
+         id="tspan4826-1-7-7-5-07-5"
+         x="-136.50272"
+         y="13.10139">Michele</tspan></text>
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       id="rect4031-9-0-8-5-4-0-7-6"
+       width="4.2292037"
+       height="4.2324886"
+       x="-135.89"
+       y="24.778917"
+       rx="1.0583334"
+       ry="1.0583334"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       id="rect4031-9-0-7-3-3-6-0-1"
+       width="4.2292037"
+       height="4.2324886"
+       x="-135.89"
+       y="30.069445"
+       rx="1.0583334"
+       ry="1.0583334"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.04922473;marker:none;enable-background:accumulate"
+       id="rect4031-9-0-6-5-1-3-9-0"
+       width="4.2292037"
+       height="4.2324886"
+       x="-135.89"
+       y="35.359974"
+       rx="1.0583334"
+       ry="1.0583334"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate"
+       d="m -136.9473,17.901078 0,0.52908 2.42849,0 2.21372,0 c 0.94338,0 1.7016,0.3372 1.7016,0.77704 l 0,20.649921 c 0,0.43476 -0.75822,0.7936 -1.7016,0.7936 l -2.21372,0 -2.42849,0 0,0.52904 0.90862,0 2.64325,0 1.88332,0 c 0.80005,0 1.43727,-0.3712 1.43727,-0.82664 l 0,-21.625361 c 0,-0.46072 -0.63722,-0.82668 -1.43727,-0.82668 l -1.88332,0 -2.64325,0 z"
+       id="rect4008-7-0-0-3-3-3-7-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccsssscccccssssccc"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <path
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate"
+       d="m -136.9473,17.901078 0,0.52908 2.42849,0 2.21372,0 c 0.94338,0 1.7016,0.3372 1.7016,0.77704 l 0,20.649921 c 0,0.43476 -0.75822,0.7936 -1.7016,0.7936 l -2.21372,0 -2.42849,0 0,0.52904 0.90862,0 2.64325,0 1.88332,0 c 0.80005,0 1.43727,-0.3712 1.43727,-0.82664 l 0,-21.625361 c 0,-0.46072 -0.63722,-0.82668 -1.43727,-0.82668 l -1.88332,0 -2.64325,0 z"
+       id="rect4008-7-0-0-3-1-5-0-5-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccsssscccccssssccc"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="44.99099"
+       inkscape:export-ydpi="44.99099" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       id="rect6777-7-9-6-9-8"
+       width="20.108335"
+       height="18.256252"
+       x="-125.24149"
+       y="19.139757"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="45"
+       inkscape:export-ydpi="45" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.13229166;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+       id="rect4923-8-7-8-2"
+       width="3.7041669"
+       height="3.7041669"
+       x="-116.71888"
+       y="30.163927"
+       rx="1.0583334"
+       ry="1.0583334" />
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.15;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       d="m -111.94623,19.146638 c -5.49508,1.3884 -10.21465,5.00036 -13.29531,9.92188 l 0,8.334361 20.10833,0 0,-18.256241 -6.81302,0 z"
+       id="path6862-84-2-2-6-7"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="45"
+       inkscape:export-ydpi="45" />
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       d="m -125.02657,18.882038 c -0.11728,0 -0.21496,0.0812 -0.21496,0.1984 l 0,0.44648 0,1.2568 0,0.2148 0.21496,0 19.67838,0 0.215,0 0,-0.2148 0,-1.2568 0,-0.44648 c 0,-0.1172 -0.0977,-0.1984 -0.215,-0.1984 l -19.67838,0 z"
+       id="rect6779-5-8-6-4-6"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="45"
+       inkscape:export-ydpi="45" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       id="rect6779-2-3-9-9-0-8"
+       width="20.108335"
+       height="0.5291667"
+       x="-125.24149"
+       y="20.991808"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="45"
+       inkscape:export-ydpi="45" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate"
+       id="rect6779-2-4-8-0-7-1-1"
+       width="15.875001"
+       height="0.5291667"
+       x="21.521105"
+       y="105.13315"
+       transform="rotate(90)"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="45"
+       inkscape:export-ydpi="45" />
+    <g
+       id="g6839-1-5-1-33-0"
+       transform="matrix(0.02002288,0.02002284,-0.02002288,0.02002284,-106.62848,-6.0229242)"
+       style="fill:#1a1a1a"
+       inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+       inkscape:export-xdpi="45"
+       inkscape:export-ydpi="45">
+      <rect
+         y="616.07727"
+         x="653.01312"
+         height="41.542522"
+         width="11.313708"
+         id="rect6819-8-9-2-56-9"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate" />
+      <rect
+         transform="rotate(90)"
+         y="-679.44122"
+         x="631.19165"
+         height="41.542522"
+         width="11.313708"
+         id="rect6819-3-9-4-3-1-5"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;filter:url(#filter4365-3);enable-background:accumulate" />
+    </g>
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.13229166;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+       id="rect4923-6-8-9-1"
+       width="3.7041669"
+       height="3.7041669"
+       x="-123.59805"
+       y="30.163927"
+       rx="1.0583334"
+       ry="1.0583334" />
+    <g
+       id="g3446"
+       transform="rotate(-30.000002,-120.31213,34.177177)">
+      <g
+         transform="matrix(0.45827179,0.26458336,-0.26458332,0.45827179,-276.94787,-436.87464)"
+         id="g7743-0-4-29-4">
+        <g
+           id="g6197-2-0-5-7-9-0-1"
+           transform="matrix(0.37080516,-0.21408445,0.21408445,0.37080516,363.3709,562.06146)"
+           inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+           inkscape:export-xdpi="45"
+           inkscape:export-ydpi="45"
+           style="opacity:0.5;fill:#000000;stroke:#000000;stroke-width:0.49999997;filter:url(#filter7280-5-3-4-6-6)">
+          <path
+             sodipodi:nodetypes="cccccccccc"
+             inkscape:connector-curvature="0"
+             id="path6155-1-1-7-1-6-6-8"
+             d="m 613.00844,507.15625 -3.84797,6.66054 -3.84797,6.66054 4.29613,-1.12812 0,9.215 6.79962,0 0,-9.19955 4.29612,1.11267 -3.84796,-6.66054 z"
+             style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.07720004;marker:none;filter:url(#filter4365-3);enable-background:accumulate" />
+          <path
+             sodipodi:nodetypes="cccccccccc"
+             inkscape:connector-curvature="0"
+             id="path6155-6-0-01-4-5-6-0-0"
+             d="m 613.00844,507.15625 -3.84797,6.66054 -3.84797,6.66054 4.29613,-1.12812 0,8.80214 6.79962,0 0,-8.78669 4.29612,1.11267 -3.84796,-6.66054 z"
+             style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.16776347;stroke-miterlimit:4;stroke-dasharray:none;marker:none;filter:url(#filter4365-3);enable-background:accumulate" />
+        </g>
+        <g
+           id="g6197-2-7-0-0-0-4"
+           transform="matrix(0.37080516,-0.21408445,0.21408445,0.37080516,362.6209,562.06146)"
+           inkscape:export-filename="/home/michele/Dropbox/lavori/gnome-shell-extension/icon/g5218.png"
+           inkscape:export-xdpi="45"
+           inkscape:export-ydpi="45"
+           style="fill:#000000;stroke:#ffffff;stroke-width:0.49999997">
+          <path
+             sodipodi:nodetypes="cccccccccc"
+             inkscape:connector-curvature="0"
+             id="path6155-1-31-4-92-4-0"
+             d="m 613.00844,507.15625 -3.84797,6.66054 -3.84797,6.66054 4.29613,-1.12812 0,9.11179 6.79962,0 0,-9.09634 4.29612,1.11267 -3.84796,-6.66054 z"
+             style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.07720004;marker:none;filter:url(#filter4365-3);enable-background:accumulate" />
+          <path
+             sodipodi:nodetypes="cccccccccc"
+             inkscape:connector-curvature="0"
+             id="path6155-6-0-8-0-7-97-5"
+             d="m 613.00844,507.15625 -3.84797,6.66054 -3.84797,6.66054 4.29613,-1.12812 0,9.31822 6.79962,0 0,-9.30277 4.29612,1.11267 -3.84796,-6.66054 z"
+             style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.58388174;stroke-miterlimit:4;stroke-dasharray:none;marker:none;filter:url(#filter4365-3);enable-background:accumulate" />
+        </g>
+      </g>
+    </g>
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.13229166;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+       id="rect4923-4-8-4"
+       width="3.7041669"
+       height="3.7041669"
+       x="-123.59805"
+       y="23.020128"
+       rx="1.0583334"
+       ry="1.0583334" />
+    <rect
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.13229166;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+       id="rect4923-2-6-7-8"
+       width="3.7041669"
+       height="3.7041669"
+       x="-116.71888"
+       y="23.020128"
+       rx="1.0583334"
+       ry="1.0583334" />
+  </g>
+</svg>
+
diff --git a/extensions/dash-to-dock/media/one.svg b/extensions/dash-to-dock/media/one.svg
new file mode 100644
index 0000000..0582b88
--- /dev/null
+++ b/extensions/dash-to-dock/media/one.svg
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="one.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="46.2185"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline">
+    <g
+       id="one">
+      <rect
+         y="0"
+         x="0"
+         height="96"
+         width="96.000008"
+         id="rect4138"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <ellipse
+         ry="3.9910278"
+         rx="3.8348253"
+         cy="48"
+         cx="5.8348255"
+         id="path3762-2"
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/one_bottom.svg b/extensions/dash-to-dock/media/one_bottom.svg
new file mode 100644
index 0000000..ebbaf33
--- /dev/null
+++ b/extensions/dash-to-dock/media/one_bottom.svg
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="one_bottom.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="41.975858"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline">
+    <g
+       id="one"
+       transform="rotate(-90,48.000004,48)">
+      <rect
+         y="0"
+         x="0"
+         height="96"
+         width="96.000008"
+         id="rect4138"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <ellipse
+         ry="3.9910278"
+         rx="3.8348253"
+         cy="48"
+         cx="5.8348255"
+         id="path3762-2"
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/one_rtl.svg b/extensions/dash-to-dock/media/one_rtl.svg
new file mode 100644
index 0000000..8f4813e
--- /dev/null
+++ b/extensions/dash-to-dock/media/one_rtl.svg
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="one_rtl.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="43.390072"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline">
+    <g
+       id="one"
+       transform="rotate(180,48.000004,48)">
+      <rect
+         y="0"
+         x="0"
+         height="96"
+         width="96.000008"
+         id="rect4138"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <ellipse
+         ry="3.9910278"
+         rx="3.8348253"
+         cy="48"
+         cx="5.8348255"
+         id="path3762-2"
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/one_top.svg b/extensions/dash-to-dock/media/one_top.svg
new file mode 100644
index 0000000..d771e3a
--- /dev/null
+++ b/extensions/dash-to-dock/media/one_top.svg
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="one_top.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="44.804286"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline">
+    <g
+       id="one"
+       transform="rotate(90,48.000004,48)">
+      <rect
+         y="0"
+         x="0"
+         height="96"
+         width="96.000008"
+         id="rect4138"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+      <ellipse
+         ry="3.9910278"
+         rx="3.8348253"
+         cy="48"
+         cx="5.8348255"
+         id="path3762-2"
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/three.svg b/extensions/dash-to-dock/media/three.svg
new file mode 100644
index 0000000..5d908d6
--- /dev/null
+++ b/extensions/dash-to-dock/media/three.svg
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="three.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="46.2185"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer3"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline">
+    <g
+       id="three">
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9"
+         cx="5.8348255"
+         cy="60"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-9"
+         cx="5.8348255"
+         cy="48"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-1"
+         cx="5.8348255"
+         cy="36"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4140"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/three_bottom.svg b/extensions/dash-to-dock/media/three_bottom.svg
new file mode 100644
index 0000000..30d0ede
--- /dev/null
+++ b/extensions/dash-to-dock/media/three_bottom.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="three_bottom.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="41.975858"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer3"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline">
+    <g
+       id="three"
+       transform="rotate(-90,48,48)">
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9"
+         cx="5.8348255"
+         cy="60"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-9"
+         cx="5.8348255"
+         cy="48"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-1"
+         cx="5.8348255"
+         cy="36"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4140"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/three_rtl.svg b/extensions/dash-to-dock/media/three_rtl.svg
new file mode 100644
index 0000000..f4c2722
--- /dev/null
+++ b/extensions/dash-to-dock/media/three_rtl.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="three_rtl.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="43.390072"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer3"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline">
+    <g
+       id="three"
+       transform="rotate(180,48,48)">
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9"
+         cx="5.8348255"
+         cy="60"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-9"
+         cx="5.8348255"
+         cy="48"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-1"
+         cx="5.8348255"
+         cy="36"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4140"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/three_top.svg b/extensions/dash-to-dock/media/three_top.svg
new file mode 100644
index 0000000..2fca42c
--- /dev/null
+++ b/extensions/dash-to-dock/media/three_top.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="three_top.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="44.804286"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer3"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline">
+    <g
+       id="three"
+       transform="rotate(90,48,48)">
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9"
+         cx="5.8348255"
+         cy="60"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-9"
+         cx="5.8348255"
+         cy="48"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <ellipse
+         style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none"
+         id="path3762-2-9-1"
+         cx="5.8348255"
+         cy="36"
+         rx="3.8348253"
+         ry="3.9910278" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4140"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/two.svg b/extensions/dash-to-dock/media/two.svg
new file mode 100644
index 0000000..4565f34
--- /dev/null
+++ b/extensions/dash-to-dock/media/two.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="two.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="46.2185"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer2"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline">
+    <g
+       id="two">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4139"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+      <g
+         transform="translate(-5.000001,-3.9910297)"
+         id="g4303">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="57.991032"
+           cx="10.834826"
+           id="path3762"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="45.991028"
+           cx="10.834826"
+           id="path3762-2-50"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/two_bottom.svg b/extensions/dash-to-dock/media/two_bottom.svg
new file mode 100644
index 0000000..83e6251
--- /dev/null
+++ b/extensions/dash-to-dock/media/two_bottom.svg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="two_bottom.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="41.975858"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer2"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline">
+    <g
+       id="two"
+       transform="rotate(-90,48,48)">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4139"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+      <g
+         transform="translate(-5.000001,-3.9910297)"
+         id="g4303">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="57.991032"
+           cx="10.834826"
+           id="path3762"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="45.991028"
+           cx="10.834826"
+           id="path3762-2-50"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/two_rtl.svg b/extensions/dash-to-dock/media/two_rtl.svg
new file mode 100644
index 0000000..e6f1159
--- /dev/null
+++ b/extensions/dash-to-dock/media/two_rtl.svg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="two_rtl.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="43.390072"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer2"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline">
+    <g
+       id="two"
+       transform="rotate(180,48,48)">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4139"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+      <g
+         transform="translate(-5.000001,-3.9910297)"
+         id="g4303">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="57.991032"
+           cx="10.834826"
+           id="path3762"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="45.991028"
+           cx="10.834826"
+           id="path3762-2-50"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/media/two_top.svg b/extensions/dash-to-dock/media/two_top.svg
new file mode 100644
index 0000000..4bf86a5
--- /dev/null
+++ b/extensions/dash-to-dock/media/two_top.svg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg11252"
+   version="1.1"
+   inkscape:version="0.91+devel r13910 custom"
+   sodipodi:docname="two_top.svg">
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#141414"
+     bordercolor="#666666"
+     borderopacity="0.21960784"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:window-width="477"
+     inkscape:window-height="463"
+     id="namedview17"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     showborder="true"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="1.4142135"
+     inkscape:cx="13.566081"
+     inkscape:cy="44.804286"
+     inkscape:window-x="306"
+     inkscape:window-y="105"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer2"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-bbox-edge-midpoints="true"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:snap-bbox-midpoints="true"
+     inkscape:snap-page="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-others="true" />
+  <defs
+     id="defs11254" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Layer 1"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer 2"
+     style="display:inline">
+    <g
+       id="two"
+       transform="rotate(90,48,48)">
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.95577884;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect4139"
+         width="96"
+         height="96"
+         x="0"
+         y="0" />
+      <g
+         transform="translate(-5.000001,-3.9910297)"
+         id="g4303">
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="57.991032"
+           cx="10.834826"
+           id="path3762"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+        <ellipse
+           ry="3.9910278"
+           rx="3.8348253"
+           cy="45.991028"
+           cx="10.834826"
+           id="path3762-2-50"
+           style="opacity:1;fill:#a6a6a6;fill-opacity:1;stroke:none;stroke-width:0.9557789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none" />
+      </g>
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Layer 3"
+     style="display:inline" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer 4"
+     style="display:inline" />
+</svg>
diff --git a/extensions/dash-to-dock/metadata.json.in b/extensions/dash-to-dock/metadata.json.in
new file mode 100644
index 0000000..a090272
--- /dev/null
+++ b/extensions/dash-to-dock/metadata.json.in
@@ -0,0 +1,12 @@
+{
+"extension-id": "@extension_id@",
+"uuid": "@uuid@",
+"settings-schema": "@gschemaname@",
+"gettext-domain": "@gettext_domain@",
+"original-author": "micxgx@gmail.com", 
+"name": "Dash to Dock", 
+"description": "A dock for the Gnome Shell. This extension moves the dash out of the overview transforming it in a dock for an easier launching of applications and a faster switching between windows and desktops. Side and bottom placement options are available.", 
+"shell-version": [ "@shell_current@" ],
+"version": 45,
+"url": "https://micheleg.github.io/dash-to-dock/"
+}
diff --git a/extensions/dash-to-dock/myConvenience.js b/extensions/dash-to-dock/myConvenience.js
new file mode 100644
index 0000000..39223a6
--- /dev/null
+++ b/extensions/dash-to-dock/myConvenience.js
@@ -0,0 +1,103 @@
+const Lang = imports.lang;
+
+// simplify global signals and function injections handling
+// abstract class
+const BasicHandler = new Lang.Class({
+    Name: 'dashToDock.BasicHandler',
+
+    _init: function(){
+        this._storage = new Object();
+    },
+
+    add: function(/*unlimited 3-long array arguments*/){
+
+        // convert arguments object to array, concatenate with generic
+        let args = Array.concat('generic', Array.slice(arguments));
+        // call addWithLabel with ags as if they were passed arguments
+        this.addWithLabel.apply(this, args);
+    },
+
+    destroy: function() {
+        for( let label in this._storage )
+            this.removeWithLabel(label);
+    },
+
+    addWithLabel: function( label /* plus unlimited 3-long array arguments*/) {
+
+        if(this._storage[label] == undefined)
+            this._storage[label] = new Array();
+
+        // skip first element of the arguments
+        for( let i = 1; i < arguments.length; i++ ) {
+            this._storage[label].push( this._create(arguments[i]) );
+        }
+
+    },
+
+    removeWithLabel: function(label){
+
+        if(this._storage[label]) {
+            for( let i = 0; i < this._storage[label].length; i++ ) {
+                this._remove(this._storage[label][i]);
+            }
+
+            delete this._storage[label];
+        }
+    },
+
+    /* Virtual methods to be implemented by subclass */
+    // create single element to be stored in the storage structure
+    _create: function(item){
+      throw new Error('no implementation of _create in ' + this);
+    },
+
+    // correctly delete single element
+    _remove: function(item){
+      throw new Error('no implementation of _remove in ' + this);
+    }
+});
+
+// Manage global signals
+const GlobalSignalsHandler = new Lang.Class({
+    Name: 'DashToDock.GlobalSignalHandler',
+    Extends: BasicHandler,
+
+    _create: function(item) {
+
+      let object = item[0];
+      let event = item[1];
+      let callback = item[2]
+      let id = object.connect(event, callback);
+
+      return [object, id];
+    },
+
+    _remove: function(item){
+       item[0].disconnect(item[1]);
+    }
+});
+
+// Manage function injection: both instances and prototype can be overridden
+// and restored
+const InjectionsHandler = new Lang.Class({
+    Name: 'DashToDock.InjectionsHandler',
+    Extends: BasicHandler,
+
+    _create: function(item) {
+
+      let object = item[0];
+      let name = item[1];
+      let injectedFunction = item[2];
+      let original = object[name];
+
+      object[name] = injectedFunction;
+      return [object, name, injectedFunction, original];
+    },
+
+    _remove: function(item) {
+        let object = item[0];
+        let name = item[1];
+        let original = item[3];
+        object[name] = original;
+    }
+});
diff --git a/extensions/dash-to-dock/myDash.js b/extensions/dash-to-dock/myDash.js
new file mode 100644
index 0000000..d44a41c
--- /dev/null
+++ b/extensions/dash-to-dock/myDash.js
@@ -0,0 +1,1672 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Signals = imports.signals;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+const Mainloop = imports.mainloop;
+
+const AppDisplay = imports.ui.appDisplay;
+const AppFavorites = imports.ui.appFavorites;
+const Dash = imports.ui.dash;
+const DND = imports.ui.dnd;
+const IconGrid = imports.ui.iconGrid;
+const Main = imports.ui.main;
+const PopupMenu = imports.ui.popupMenu;
+const Tweener = imports.ui.tweener;
+const Util = imports.misc.util;
+const Workspace = imports.ui.workspace;
+
+const Me = imports.misc.extensionUtils.getCurrentExtension();
+const Convenience = Me.imports.myConvenience;
+
+let DASH_ANIMATION_TIME = Dash.DASH_ANIMATION_TIME;
+let DASH_ITEM_LABEL_SHOW_TIME = Dash.DASH_ITEM_LABEL_SHOW_TIME;
+let DASH_ITEM_LABEL_HIDE_TIME = Dash.DASH_ITEM_LABEL_HIDE_TIME;
+let DASH_ITEM_HOVER_TIMEOUT = Dash.DASH_ITEM_HOVER_TIMEOUT;
+
+/* Return the actual position reverseing left and right in rtl */
+function getPosition(settings) {
+    let position = settings.get_enum('dock-position');
+    if(Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
+        if (position == St.Side.LEFT)
+            position = St.Side.RIGHT;
+        else if (position == St.Side.RIGHT)
+            position = St.Side.LEFT;
+    }
+    return position;
+}
+
+/**
+ * Extend AppIconMenu
+ *
+ * - Pass settings to the constructor
+ * - set popup arrow side based on dash orientation
+ * - Add close windows option based on quitfromdash extension
+ *   (https://github.com/deuill/shell-extension-quitfromdash)
+ */
+
+const myAppIconMenu = new Lang.Class({
+    Name: 'myAppIconMenu',
+    Extends: AppDisplay.AppIconMenu,
+
+    _init: function(source, settings) {
+
+        let side = getPosition(settings);
+
+        // Damm it, there has to be a proper way of doing this...
+        // As I can't call the parent parent constructor (?) passing the side
+        // parameter, I overwite what I need later
+        this.parent(source);
+
+        // Change the initialized side where required.
+        this._arrowSide = side;
+        this._boxPointer._arrowSide = side;
+        this._boxPointer._userArrowSide = side;
+    },
+
+    // helper function for the quit windows abilities
+    _closeWindowInstance: function(metaWindow) {
+        metaWindow.delete(global.get_current_time());
+    },
+
+    _redisplay: function() {
+
+        this.parent();
+
+        // quit menu
+        let app = this._source.app;
+        let count = app.get_n_windows();
+        if ( count > 0) {
+            this._appendSeparator();
+            let quitFromDashMenuText = "";
+            if (count == 1)
+                quitFromDashMenuText = _("Quit");
+            else
+                quitFromDashMenuText = _("Quit " + count + " Windows");
+
+            this._quitfromDashMenuItem = this._appendMenuItem(quitFromDashMenuText);
+            this._quitfromDashMenuItem.connect('activate', Lang.bind(this, function() {
+                let app = this._source.app;
+                let windows = app.get_windows();
+                for (let i = 0; i < windows.length; i++) {
+                    this._closeWindowInstance(windows[i])
+                }
+            }));
+        }
+    }
+});
+
+/**
+ * Extend DashItemContainer
+ *
+ * - Pass settings to the constructor
+ * - set label position based on dash orientation
+ *
+ *  I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973.
+ *  thus use this ugly pattern.
+ */
+
+// define first this function to use it in both extendShowAppsIcon and extendDashItemContainer
+function ItemShowLabel()  {
+    if (!this._labelText) {
+      return;
+    }
+
+    this.label.set_text(this._labelText);
+    this.label.opacity = 0;
+    this.label.show();
+
+    let [stageX, stageY] = this.get_transformed_position();
+    let node = this.label.get_theme_node();
+
+    let itemWidth  = this.allocation.x2 - this.allocation.x1;
+    let itemHeight = this.allocation.y2 - this.allocation.y1;
+
+
+    let labelWidth = this.label.get_width();
+    let labelHeight = this.label.get_height();
+
+    let x, y, xOffset, yOffset;
+
+    let position = getPosition(this._settings);
+      this._isHorizontal = ( position == St.Side.TOP ||
+                             position == St.Side.BOTTOM);
+    let labelOffset = node.get_length('-x-offset');
+
+    switch(position) {
+      case St.Side.LEFT:
+          yOffset = Math.floor((itemHeight - labelHeight) / 2);
+          y = stageY + yOffset;
+          xOffset = labelOffset;
+          x = stageX + this.get_width() + xOffset;
+          break;
+      case St.Side.RIGHT:
+          yOffset = Math.floor((itemHeight - labelHeight) / 2);
+          y = stageY + yOffset;
+          xOffset = labelOffset;
+          x = Math.round(stageX) - labelWidth - xOffset;
+          break;
+      case St.Side.TOP:
+          y = stageY + labelOffset + itemHeight;
+          xOffset = Math.floor((itemWidth - labelWidth) / 2);
+          x = stageX + xOffset;
+          break;
+      case St.Side.BOTTOM:
+          yOffset = labelOffset;
+          y = stageY - labelHeight - yOffset;
+          xOffset = Math.floor((itemWidth - labelWidth) / 2);
+          x = stageX + xOffset;
+          break;
+    }
+
+    // keep the label inside the screen border
+    // Only needed fot the x coordinate.
+
+    // Leave a few pixel gap
+    let gap = 5;
+    let monitor = Main.layoutManager.findMonitorForActor(this);
+    if ( x - monitor.x<gap)
+        x+= monitor.x - x + labelOffset;
+    else if ( x + labelWidth > monitor.x + monitor.width - gap)
+        x-= x + labelWidth -( monitor.x + monitor.width) + gap;
+
+    this.label.set_position(x, y);
+    Tweener.addTween(this.label,
+      { opacity: 255,
+        time: DASH_ITEM_LABEL_SHOW_TIME,
+        transition: 'easeOutQuad',
+      });
+};
+
+function extendDashItemContainer(dashItemContainer, settings) {
+
+    dashItemContainer._settings = settings;
+    dashItemContainer.showLabel = ItemShowLabel;
+};
+
+/*
+ * A menu for the showAppsIcon
+*/
+const myShowAppsIconMenu = new Lang.Class({
+
+    Name: 'dashToDockShowAppsIconMenu',
+    Extends: myAppIconMenu,
+
+    _redisplay: function() {
+        this.removeAll();
+
+        let item = this._appendMenuItem(_("Dash to Dock Settings"));
+
+        item.connect('activate', function () {
+            Util.spawn(["gnome-shell-extension-prefs", Me.metadata.uuid]);
+        });
+    }
+
+});
+
+/**
+ * Extend ShowAppsIcon
+ *
+ * - Pass settings to the constructor
+ * - set label position based on dash orientation
+ * - implement a popupMenu based on the AppIcon code
+ *
+ *  I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973.
+ *  thus use this ugly pattern.
+ */
+
+function extendShowAppsIcon(showAppsIcon, settings){
+
+
+      showAppsIcon._settings = settings;
+      /* the variable equivalent to toggleButton has a different name in the appIcon class
+       (actor): duplicate reference to easily reuse appIcon methods */
+      showAppsIcon.actor =  showAppsIcon.toggleButton;
+
+      // Re-use appIcon methods
+      showAppsIcon._removeMenuTimeout = AppDisplay.AppIcon.prototype._removeMenuTimeout;
+      showAppsIcon._setPopupTimeout = AppDisplay.AppIcon.prototype._setPopupTimeout;
+      showAppsIcon._onButtonPress = AppDisplay.AppIcon.prototype._onButtonPress;
+      showAppsIcon._onKeyboardPopupMenu = AppDisplay.AppIcon.prototype._onKeyboardPopupMenu;
+      showAppsIcon._onLeaveEvent = AppDisplay.AppIcon.prototype._onLeaveEvent;
+      showAppsIcon._onTouchEvent = AppDisplay.AppIcon.prototype._onTouchEvent;
+      showAppsIcon._onMenuPoppedDown = AppDisplay.AppIcon.prototype._onMenuPoppedDown;
+
+
+      // No action on clicked (showing of the appsview is controlled elsewhere)
+      showAppsIcon._onClicked = function(actor, button) {
+          showAppsIcon._removeMenuTimeout();
+      };
+
+
+      showAppsIcon.actor.connect('leave-event', Lang.bind( showAppsIcon, showAppsIcon._onLeaveEvent));
+      showAppsIcon.actor.connect('button-press-event', Lang.bind( showAppsIcon, showAppsIcon._onButtonPress));
+      showAppsIcon.actor.connect('touch-event', Lang.bind( showAppsIcon,  showAppsIcon._onTouchEvent));
+      showAppsIcon.actor.connect('clicked', Lang.bind( showAppsIcon, showAppsIcon._onClicked));
+      showAppsIcon.actor.connect('popup-menu', Lang.bind( showAppsIcon, showAppsIcon._onKeyboardPopupMenu));
+
+      showAppsIcon._menu = null;
+      showAppsIcon._menuManager = new PopupMenu.PopupMenuManager(showAppsIcon);
+      showAppsIcon._menuTimeoutId = 0;
+
+  
+      showAppsIcon.showLabel = ItemShowLabel;
+
+
+      showAppsIcon.popupMenu =  function() {
+
+          showAppsIcon._removeMenuTimeout();
+          showAppsIcon.actor.fake_release();
+
+          if (!showAppsIcon._menu) {
+              showAppsIcon._menu = new myShowAppsIconMenu(showAppsIcon, showAppsIcon._settings);
+              showAppsIcon._menu.connect('open-state-changed', Lang.bind(showAppsIcon, function (menu, isPoppedUp) {
+              if (!isPoppedUp)
+                  showAppsIcon._onMenuPoppedDown();
+              }));
+              let id = Main.overview.connect('hiding', Lang.bind(showAppsIcon, function () { showAppsIcon._menu.close(); }));
+              showAppsIcon._menu.actor.connect('destroy', function() {
+                  Main.overview.disconnect(id);
+              });
+              showAppsIcon._menuManager.addMenu(showAppsIcon._menu);
+          }
+
+          showAppsIcon.emit('menu-state-changed', true);
+
+          showAppsIcon.actor.set_hover(true);
+          showAppsIcon._menu.popup();
+          showAppsIcon._menuManager.ignoreRelease();
+          showAppsIcon.emit('sync-tooltip');
+
+          return false;
+      };
+
+      Signals.addSignalMethods(showAppsIcon);
+}
+
+/* This class is a fork of the upstream DashActor class (ui.dash.js)
+ *
+ * Summary of changes:
+ * - passed settings to class as parameter
+ * - modified chldBox calculations for when 'show-apps-at-top' option is checked
+ * - handle horizontal dash
+ */
+const myDashActor = new Lang.Class({
+    Name: 'DashToDockmyDashActor',
+
+    _init: function(settings) {
+        this._settings = settings;
+        this._rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
+
+        this._position = getPosition(settings);
+        this._isHorizontal = ( this._position == St.Side.TOP ||
+                               this._position == St.Side.BOTTOM );
+
+        let layout = new Clutter.BoxLayout({ orientation:
+          this._isHorizontal?Clutter.Orientation.HORIZONTAL:Clutter.Orientation.VERTICAL });
+
+        this.actor = new Shell.GenericContainer({ name: 'dash',
+                      layout_manager: layout,
+                      clip_to_allocation: true });
+        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
+        this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
+        this.actor.connect('allocate', Lang.bind(this, this._allocate));
+
+        this.actor._delegate = this;
+
+    },
+
+    _allocate: function(actor, box, flags) {
+        let contentBox = box;
+        let availWidth = contentBox.x2 - contentBox.x1;
+        let availHeight = contentBox.y2 - contentBox.y1;
+
+        let [appIcons, showAppsButton] = actor.get_children();
+        let [showAppsMinHeight, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
+        let [showAppsMinWidth, showAppsNatWidth] = showAppsButton.get_preferred_width(availHeight);
+
+        let offset_x = this._isHorizontal?showAppsNatWidth:0;
+        let offset_y = this._isHorizontal?0:showAppsNatHeight;
+
+        let childBox = new Clutter.ActorBox();
+        if( (this._settings.get_boolean('show-apps-at-top') && !this._isHorizontal)
+            || (this._settings.get_boolean('show-apps-at-top') && !this._rtl)
+            || (!this._settings.get_boolean('show-apps-at-top') && this._isHorizontal && this._rtl)
+          ) {
+            childBox.x1 = contentBox.x1 + offset_x;
+            childBox.y1 = contentBox.y1 + offset_y;
+            childBox.x2 = contentBox.x2;
+            childBox.y2 = contentBox.y2;
+            appIcons.allocate(childBox, flags);
+
+            childBox.y1 = contentBox.y1;
+            childBox.x1 = contentBox.x1;
+            childBox.x2 = contentBox.x1 + showAppsNatWidth;
+            childBox.y2 = contentBox.y1 + showAppsNatHeight;
+            showAppsButton.allocate(childBox, flags);
+        } else {
+            childBox.x1 = contentBox.x1;
+            childBox.y1 = contentBox.y1;
+            childBox.x2 = contentBox.x2 - offset_x;
+            childBox.y2 = contentBox.y2 - offset_y;
+            appIcons.allocate(childBox, flags);
+
+            childBox.x2 = contentBox.x2;
+            childBox.y2 = contentBox.y2;
+            childBox.x1 = contentBox.x2 - showAppsNatWidth;
+            childBox.y1 = contentBox.y2 - showAppsNatHeight;
+            showAppsButton.allocate(childBox, flags);
+        }
+    },
+
+    _getPreferredWidth: function(actor, forHeight, alloc) {
+        // We want to request the natural height of all our children
+        // as our natural height, so we chain up to StWidget (which
+        // then calls BoxLayout), but we only request the showApps
+        // button as the minimum size
+
+        let [, natWidth] = this.actor.layout_manager.get_preferred_width(this.actor, forHeight);
+
+        let themeNode = this.actor.get_theme_node();
+        let [, showAppsButton] = this.actor.get_children();
+        let [minWidth, ] = showAppsButton.get_preferred_height(forHeight);
+
+        alloc.min_size = minWidth;
+        alloc.natural_size = natWidth;
+
+    },
+
+    _getPreferredHeight: function(actor, forWidth, alloc) {
+        // We want to request the natural height of all our children
+        // as our natural height, so we chain up to StWidget (which
+        // then calls BoxLayout), but we only request the showApps
+        // button as the minimum size
+
+        let [, natHeight] = this.actor.layout_manager.get_preferred_height(this.actor, forWidth);
+
+        let themeNode = this.actor.get_theme_node();
+        let [, showAppsButton] = this.actor.get_children();
+        let [minHeight, ] = showAppsButton.get_preferred_height(forWidth);
+
+        alloc.min_size = minHeight;
+        alloc.natural_size = natHeight;
+    }
+});
+
+/* This class is a fork of the upstream dash class (ui.dash.js)
+ *
+ * Summary of changes:
+ * - disconnect global signals adding a destroy method;
+ * - play animations even when not in overview mode
+ * - set a maximum icon size
+ * - show running and/or favorite applications
+ * - emit a custom signal when an app icon is added
+ * - hide showApps label when the custom menu is shown.
+ * - add cleanUpLabels method emitting a signal to hide labels
+ * - Add scrollview
+ *   Ensure actor is visible on keyfocus inseid the scrollview
+ * - add 128px icon size, might be usefull for hidpi display
+ * - Sync minimization application target position.
+ */
+
+const baseIconSizes = [ 16, 22, 24, 32, 48, 64, 96, 128 ];
+
+const myDash = new Lang.Class({
+    Name: 'dashToDock.myDash',
+
+    _init : function(settings) {
+        this._maxHeight = -1;
+        this.iconSize = 64;
+        this._availableIconSizes = baseIconSizes;
+        this._shownInitially = false;
+
+        this._settings = settings;
+        this._position = getPosition(settings);
+        this._isHorizontal = ( this._position == St.Side.TOP ||
+                               this._position == St.Side.BOTTOM );
+        this._signalsHandler = new Convenience.GlobalSignalsHandler();
+
+        this._dragPlaceholder = null;
+        this._dragPlaceholderPos = -1;
+        this._animatingPlaceholdersCount = 0;
+        this._showLabelTimeoutId = 0;
+        this._resetHoverTimeoutId = 0;
+        this._ensureAppIconVisibilityTimeoutId = 0;
+        this._labelShowing = false;
+
+        this._containerObject = new myDashActor(settings);
+        this._container = this._containerObject.actor;
+        this._scrollView = new St.ScrollView({ name: 'dashtodockDashScrollview',
+                                               hscrollbar_policy: Gtk.PolicyType.NEVER,
+                                               vscrollbar_policy: Gtk.PolicyType.NEVER,
+                                               enable_mouse_scrolling: false });
+
+        this._scrollView.connect('scroll-event', Lang.bind(this, this._onScrollEvent ));
+
+        this._box = new St.BoxLayout({ vertical: !this._isHorizontal,
+                                       clip_to_allocation: false,
+                                       x_align: Clutter.ActorAlign.START,
+                                       y_align: Clutter.ActorAlign.START });
+        this._box._delegate = this;
+        this._container.add_actor(this._scrollView);
+        this._scrollView.add_actor(this._box);
+
+        this._showAppsIcon = new Dash.ShowAppsIcon();
+        extendShowAppsIcon(this._showAppsIcon, this._settings);
+        this._showAppsIcon.childScale = 1;
+        this._showAppsIcon.childOpacity = 255;
+        this._showAppsIcon.icon.setIconSize(this.iconSize);
+        this._hookUpLabel(this._showAppsIcon);
+
+
+        let appsIcon = this._showAppsIcon;
+        appsIcon.connect('menu-state-changed',
+            Lang.bind(this, function(appsIcon, opened) {
+                this._itemMenuStateChanged(appsIcon, opened);
+            }));
+
+        this.showAppsButton = this._showAppsIcon.toggleButton;
+
+        this._container.add_actor(this._showAppsIcon);
+
+        let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
+        this.actor = new St.Bin({ child: this._container,
+            y_align: St.Align.START, x_align:rtl?St.Align.END:St.Align.START
+        });
+
+        if(this._isHorizontal) {
+            this.actor.connect('notify::width', Lang.bind(this,
+                function() {
+                    if (this._maxHeight != this.actor.width)
+                        this._queueRedisplay();
+                    this._maxHeight = this.actor.width;
+                }));
+        } else {
+            this.actor.connect('notify::height', Lang.bind(this,
+                function() {
+                    if (this._maxHeight != this.actor.height)
+                        this._queueRedisplay();
+                    this._maxHeight = this.actor.height;
+                }));
+        }
+
+        // Update minimization animation target position on allocation of the
+        // container and on scrollview change.
+        this._box.connect('notify::allocation', Lang.bind(this, this._updateAppIconsGeometry));
+        let scrollViewAdjustment = this._isHorizontal?this._scrollView.hscroll.adjustment:this._scrollView.vscroll.adjustment;
+        scrollViewAdjustment.connect('notify::value', Lang.bind(this, this._updateAppIconsGeometry));
+
+        this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay));
+
+        this._appSystem = Shell.AppSystem.get_default();
+
+        this._signalsHandler.add(
+            [
+                this._appSystem,
+                'installed-changed',
+                Lang.bind(this, function() {
+                    AppFavorites.getAppFavorites().reload();
+                    this._queueRedisplay();
+                })
+            ],
+            [
+                AppFavorites.getAppFavorites(),
+                'changed',
+                Lang.bind(this, this._queueRedisplay)
+            ],
+            [
+                this._appSystem,
+                'app-state-changed',
+                Lang.bind(this, this._queueRedisplay)
+            ],
+            [
+                Main.overview,
+                'item-drag-begin',
+                Lang.bind(this, this._onDragBegin)
+            ],
+            [
+                Main.overview,
+                'item-drag-end',
+                Lang.bind(this, this._onDragEnd)
+            ],
+            [
+                Main.overview,
+                'item-drag-cancelled',
+                Lang.bind(this, this._onDragCancelled)
+            ]
+        );
+
+    },
+
+    destroy: function() {
+        this._signalsHandler.destroy();
+    },
+
+    _onScrollEvent: function(actor, event) {
+
+        // reset timeout to avid conflicts with the mousehover event
+        if (this._ensureAppIconVisibilityTimeoutId>0) {
+            Mainloop.source_remove(this._ensureAppIconVisibilityTimeoutId);
+            this._ensureAppIconVisibilityTimeoutId = 0;
+        }
+
+        // Skip to avoid double events mouse
+        if (event.is_pointer_emulated())
+            return Clutter.EVENT_STOP;
+
+        let adjustment, delta;
+
+        if (this._isHorizontal)
+            adjustment = this._scrollView.get_hscroll_bar().get_adjustment();
+        else
+            adjustment = this._scrollView.get_vscroll_bar().get_adjustment();
+
+        let increment = adjustment.step_increment;
+
+        switch ( event.get_scroll_direction() ) {
+        case Clutter.ScrollDirection.UP:
+            delta = -increment;
+            break;
+        case Clutter.ScrollDirection.DOWN:
+            delta = +increment;
+            break;
+        case Clutter.ScrollDirection.SMOOTH:
+            let [dx, dy] = event.get_scroll_delta();
+            delta = dy*increment;
+            // Also consider horizontal component, for instance touchpad
+            if (this._isHorizontal)
+                delta += dx*increment;
+            break;
+
+        }
+
+        adjustment.set_value(adjustment.get_value() + delta);
+
+        return Clutter.EVENT_STOP;
+
+    },
+
+    _onDragBegin: function() {
+        this._dragCancelled = false;
+        this._dragMonitor = {
+            dragMotion: Lang.bind(this, this._onDragMotion)
+        };
+        DND.addDragMonitor(this._dragMonitor);
+
+        if (this._box.get_n_children() == 0) {
+            this._emptyDropTarget = new Dash.EmptyDropTargetItem();
+            this._box.insert_child_at_index(this._emptyDropTarget, 0);
+            this._emptyDropTarget.show(true);
+        }
+    },
+
+    _onDragCancelled: function() {
+        this._dragCancelled = true;
+        this._endDrag();
+    },
+
+    _onDragEnd: function() {
+        if (this._dragCancelled)
+            return;
+
+        this._endDrag();
+    },
+
+    _endDrag: function() {
+        this._clearDragPlaceholder();
+        this._clearEmptyDropTarget();
+        this._showAppsIcon.setDragApp(null);
+        DND.removeDragMonitor(this._dragMonitor);
+    },
+
+    _onDragMotion: function(dragEvent) {
+        let app = Dash.getAppFromSource(dragEvent.source);
+        if (app == null)
+            return DND.DragMotionResult.CONTINUE;
+
+        let showAppsHovered =
+                this._showAppsIcon.contains(dragEvent.targetActor);
+
+        if (!this._box.contains(dragEvent.targetActor) || showAppsHovered)
+            this._clearDragPlaceholder();
+
+        if (showAppsHovered)
+            this._showAppsIcon.setDragApp(app);
+        else
+            this._showAppsIcon.setDragApp(null);
+
+        return DND.DragMotionResult.CONTINUE;
+    },
+
+    _appIdListToHash: function(apps) {
+        let ids = {};
+        for (let i = 0; i < apps.length; i++)
+            ids[apps[i].get_id()] = apps[i];
+        return ids;
+    },
+
+    _queueRedisplay: function () {
+        Main.queueDeferredWork(this._workId);
+    },
+
+    _hookUpLabel: function(item, appIcon) {
+        item.child.connect('notify::hover', Lang.bind(this, function() {
+            this._syncLabel(item, appIcon);
+        }));
+
+        let id = Main.overview.connect('hiding', Lang.bind(this, function() {
+            this._labelShowing = false;
+            item.hideLabel();
+        }));
+
+        let id2 = this.connect('cleanup-labels', Lang.bind(this, function() {
+            // setting the hover to false also hide the label
+            item.child.hover = false;
+        }));
+
+        item.child.connect('destroy', Lang.bind(this, function() {
+            Main.overview.disconnect(id);
+            this.disconnect(id2);
+        }));
+
+        if (appIcon) {
+            appIcon.connect('sync-tooltip', Lang.bind(this, function() {
+                this._syncLabel(item, appIcon);
+            }));
+        }
+    },
+
+    cleanUpLabels: function() {
+        this.emit('cleanup-labels');
+    },
+
+    _createAppItem: function(app) {
+        let appIcon = new myAppIcon(this._settings, app,
+                                             { setSizeManually: true,
+                                               showLabel: false });
+        appIcon._draggable.connect('drag-begin',
+                                   Lang.bind(this, function() {
+                                       appIcon.actor.opacity = 50;
+                                   }));
+        appIcon._draggable.connect('drag-end',
+                                   Lang.bind(this, function() {
+                                       appIcon.actor.opacity = 255;
+                                   }));
+        appIcon.connect('menu-state-changed',
+                        Lang.bind(this, function(appIcon, opened) {
+                            this._itemMenuStateChanged(item, opened);
+                        }));
+
+        let item = new Dash.DashItemContainer();
+        extendDashItemContainer(item, this._settings);
+
+
+        item.setChild(appIcon.actor);
+        appIcon.actor.connect('notify::hover', Lang.bind(this, function() {
+            if (appIcon.actor.hover){
+                this._ensureAppIconVisibilityTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function(){
+                    ensureActorVisibleInScrollView(this._scrollView, appIcon.actor);
+                    this._ensureAppIconVisibilityTimeoutId = 0;
+                    return GLib.SOURCE_REMOVE;
+                }));
+            } else {
+                if (this._ensureAppIconVisibilityTimeoutId>0) {
+                    Mainloop.source_remove(this._ensureAppIconVisibilityTimeoutId);
+                    this._ensureAppIconVisibilityTimeoutId = 0;
+                }
+            }
+        }));
+
+        appIcon.actor.connect('clicked',
+            Lang.bind(this, function(actor) {
+                ensureActorVisibleInScrollView(this._scrollView, actor);
+        }));
+
+        appIcon.actor.connect('key-focus-in',
+            Lang.bind(this, function(actor) {
+
+                let [x_shift, y_shift] = ensureActorVisibleInScrollView(this._scrollView, actor);
+
+                // This signal is triggered also by mouse click. The popup menu is opened at the original
+                // coordinates. Thus correct for the shift which is going to be applied to the scrollview.
+                if (appIcon._menu) {
+                    appIcon._menu._boxPointer.xOffset = -x_shift;
+                    appIcon._menu._boxPointer.yOffset = -y_shift;
+                }
+        }));
+
+        // Override default AppIcon label_actor, now the
+        // accessible_name is set at DashItemContainer.setLabelText
+        appIcon.actor.label_actor = null;
+        item.setLabelText(app.get_name());
+
+        appIcon.icon.setIconSize(this.iconSize);
+        this._hookUpLabel(item, appIcon);
+
+        return item;
+    },
+
+    // Return an array with the "proper" appIcons currently in the dash
+    _getAppIcons: function() {
+        // Only consider children which are "proper"
+        // icons (i.e. ignoring drag placeholders) and which are not
+        // animating out (which means they will be destroyed at the end of
+        // the animation)
+        let iconChildren = this._box.get_children().filter(function(actor) {
+            return actor.child &&
+                   actor.child._delegate &&
+                   actor.child._delegate.icon &&
+                   !actor.animatingOut;
+        });
+
+        let appIcons = iconChildren.map(function(actor){
+            return actor.child._delegate;
+        });
+
+      return appIcons;
+    },
+
+    _updateAppIconsGeometry: function() {
+        let appIcons = this._getAppIcons();
+        appIcons.forEach(function(icon){
+            icon.updateIconGeometry();
+        });
+    },
+
+    _itemMenuStateChanged: function(item, opened) {
+        // When the menu closes, it calls sync_hover, which means
+        // that the notify::hover handler does everything we need to.
+        if (opened) {
+            if (this._showLabelTimeoutId > 0) {
+                Mainloop.source_remove(this._showLabelTimeoutId);
+                this._showLabelTimeoutId = 0;
+            }
+
+            item.hideLabel();
+        } else {
+            // I want to listen from outside when a menu is closed. I used to
+            // add a custom signal to the appIcon, since gnome 3.8 the signal
+            // calling this callback was added upstream.
+            this.emit('menu-closed');
+        }
+    },
+
+    _syncLabel: function (item, appIcon) {
+        let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover();
+
+        if (shouldShow) {
+            if (this._showLabelTimeoutId == 0) {
+                let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
+                this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
+                    Lang.bind(this, function() {
+                        this._labelShowing = true;
+                        item.showLabel();
+                        this._showLabelTimeoutId = 0;
+                        return GLib.SOURCE_REMOVE;
+                    }));
+                GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
+                if (this._resetHoverTimeoutId > 0) {
+                    Mainloop.source_remove(this._resetHoverTimeoutId);
+                    this._resetHoverTimeoutId = 0;
+                }
+            }
+        } else {
+            if (this._showLabelTimeoutId > 0)
+                Mainloop.source_remove(this._showLabelTimeoutId);
+            this._showLabelTimeoutId = 0;
+            item.hideLabel();
+            if (this._labelShowing) {
+                this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
+                    Lang.bind(this, function() {
+                        this._labelShowing = false;
+                        this._resetHoverTimeoutId = 0;
+                        return GLib.SOURCE_REMOVE;
+                    }));
+                GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
+            }
+        }
+    },
+
+    _adjustIconSize: function() {
+        // For the icon size, we only consider children which are "proper"
+        // icons (i.e. ignoring drag placeholders) and which are not
+        // animating out (which means they will be destroyed at the end of
+        // the animation)
+        let iconChildren = this._box.get_children().filter(function(actor) {
+            return actor.child &&
+                   actor.child._delegate &&
+                   actor.child._delegate.icon &&
+                   !actor.animatingOut;
+        });
+
+        iconChildren.push(this._showAppsIcon);
+
+        if (this._maxHeight == -1)
+            return;
+
+        let themeNode = this._container.get_theme_node();
+        let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
+                                                   x2: this._isHorizontal?this._maxHeight:42 /* whatever */,
+                                                   y2: this._isHorizontal?42:this._maxHeight });
+        let maxContent = themeNode.get_content_box(maxAllocation);
+        let availHeight;
+        if (this._isHorizontal)
+            availHeight = maxContent.x2 - maxContent.x1;
+        else
+            availHeight = maxContent.y2 - maxContent.y1;
+        let spacing = themeNode.get_length('spacing');
+
+        let firstButton = iconChildren[0].child;
+        let firstIcon = firstButton._delegate.icon;
+
+        let minHeight, natHeight, maxWidth, natWidth;
+
+        // Enforce the current icon size during the size request
+        firstIcon.setIconSize(this.iconSize);
+        [minHeight, natHeight] = firstButton.get_preferred_height(-1);
+        [minWidth, natWidth] = firstButton.get_preferred_width(-1);
+
+        let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
+        let iconSizes = this._availableIconSizes.map(function(s) {
+            return s * scaleFactor;
+        });
+
+        // Subtract icon padding and box spacing from the available height
+        if(this._isHorizontal){
+            availHeight -= iconChildren.length * (natWidth - this.iconSize * scaleFactor) +
+                           (iconChildren.length - 1) * spacing;
+        } else {
+            availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
+                           (iconChildren.length - 1) * spacing;
+        }
+
+        let availSize = availHeight / iconChildren.length;
+
+
+        let newIconSize = this._availableIconSizes[0];
+        for (let i = 0; i < iconSizes.length; i++) {
+            if (iconSizes[i] < availSize)
+                newIconSize = this._availableIconSizes[i];
+        }
+
+        if (newIconSize == this.iconSize)
+            return;
+
+        let oldIconSize = this.iconSize;
+        this.iconSize = newIconSize;
+        this.emit('icon-size-changed');
+
+        let scale = oldIconSize / newIconSize;
+        for (let i = 0; i < iconChildren.length; i++) {
+            let icon = iconChildren[i].child._delegate.icon;
+
+            // Set the new size immediately, to keep the icons' sizes
+            // in sync with this.iconSize
+            icon.setIconSize(this.iconSize);
+
+            // Don't animate the icon size change when the overview
+            // is transitioning, or when initially filling
+            // the dash
+            if (Main.overview.animationInProgress ||
+                !this._shownInitially)
+                continue;
+
+            let [targetWidth, targetHeight] = icon.icon.get_size();
+
+            // Scale the icon's texture to the previous size and
+            // tween to the new size
+            icon.icon.set_size(icon.icon.width * scale,
+                               icon.icon.height * scale);
+
+            Tweener.addTween(icon.icon,
+                             { width: targetWidth,
+                               height: targetHeight,
+                               time: DASH_ANIMATION_TIME,
+                               transition: 'easeOutQuad',
+                             });
+        }
+    },
+
+    _redisplay: function () {
+        let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
+
+        let running = this._appSystem.get_running();
+
+        let children = this._box.get_children().filter(function(actor) {
+                return actor.child &&
+                       actor.child._delegate &&
+                       actor.child._delegate.app;
+            });
+        // Apps currently in the dash
+        let oldApps = children.map(function(actor) {
+                return actor.child._delegate.app;
+            });
+        // Apps supposed to be in the dash
+        let newApps = [];
+
+        for (let id in favorites)
+            newApps.push(favorites[id]);
+
+        if( this._settings.get_boolean('show-running') ) {
+            for (let i = 0; i < running.length; i++) {
+                let app = running[i];
+                if (app.get_id() in favorites)
+                    continue;
+                newApps.push(app);
+            }
+        }
+
+        // Figure out the actual changes to the list of items; we iterate
+        // over both the list of items currently in the dash and the list
+        // of items expected there, and collect additions and removals.
+        // Moves are both an addition and a removal, where the order of
+        // the operations depends on whether we encounter the position
+        // where the item has been added first or the one from where it
+        // was removed.
+        // There is an assumption that only one item is moved at a given
+        // time; when moving several items at once, everything will still
+        // end up at the right position, but there might be additional
+        // additions/removals (e.g. it might remove all the launchers
+        // and add them back in the new order even if a smaller set of
+        // additions and removals is possible).
+        // If above assumptions turns out to be a problem, we might need
+        // to use a more sophisticated algorithm, e.g. Longest Common
+        // Subsequence as used by diff.
+        let addedItems = [];
+        let removedActors = [];
+
+        let newIndex = 0;
+        let oldIndex = 0;
+        while (newIndex < newApps.length || oldIndex < oldApps.length) {
+            // No change at oldIndex/newIndex
+            if (oldApps[oldIndex] == newApps[newIndex]) {
+                oldIndex++;
+                newIndex++;
+                continue;
+            }
+
+            // App removed at oldIndex
+            if (oldApps[oldIndex] &&
+                newApps.indexOf(oldApps[oldIndex]) == -1) {
+                removedActors.push(children[oldIndex]);
+                oldIndex++;
+                continue;
+            }
+
+            // App added at newIndex
+            if (newApps[newIndex] &&
+                oldApps.indexOf(newApps[newIndex]) == -1) {
+                addedItems.push({ app: newApps[newIndex],
+                                  item: this._createAppItem(newApps[newIndex]),
+                                  pos: newIndex });
+                newIndex++;
+                continue;
+            }
+
+            // App moved
+            let insertHere = newApps[newIndex + 1] &&
+                             newApps[newIndex + 1] == oldApps[oldIndex];
+            let alreadyRemoved = removedActors.reduce(function(result, actor) {
+                let removedApp = actor.child._delegate.app;
+                return result || removedApp == newApps[newIndex];
+            }, false);
+
+            if (insertHere || alreadyRemoved) {
+                let newItem = this._createAppItem(newApps[newIndex]);
+                addedItems.push({ app: newApps[newIndex],
+                                  item: newItem,
+                                  pos: newIndex + removedActors.length });
+                newIndex++;
+            } else {
+                removedActors.push(children[oldIndex]);
+                oldIndex++;
+            }
+        }
+
+        for (let i = 0; i < addedItems.length; i++)
+            this._box.insert_child_at_index(addedItems[i].item,
+                                            addedItems[i].pos);
+
+        for (let i = 0; i < removedActors.length; i++) {
+            let item = removedActors[i];
+
+            // Don't animate item removal when the overview is transitioning
+            if (!Main.overview.animationInProgress)
+                item.animateOutAndDestroy();
+            else
+                item.destroy();
+        }
+
+        this._adjustIconSize();
+
+        for (let i = 0; i < addedItems.length; i++){
+            // Emit a custom signal notifying that a new item has been added
+            this.emit('item-added', addedItems[i]);
+        }
+
+        // Skip animations on first run when adding the initial set
+        // of items, to avoid all items zooming in at once
+
+        let animate = this._shownInitially &&
+            !Main.overview.animationInProgress;
+
+        if (!this._shownInitially)
+            this._shownInitially = true;
+
+        for (let i = 0; i < addedItems.length; i++) {
+            addedItems[i].item.show(animate);
+        }
+
+        // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
+        // Without it, StBoxLayout may use a stale size cache
+        this._box.queue_relayout();
+
+        // This is required for icon reordering when the scrollview is used.
+        this._updateAppIconsGeometry();
+    },
+
+    setIconSize: function (max_size, doNotAnimate) {
+
+        let max_allowed = baseIconSizes[baseIconSizes.length-1];
+        max_size = Math.min(max_size, max_allowed);
+
+        if (this._settings.get_boolean('icon-size-fixed')) {
+            this._availableIconSizes = [ max_size ];
+        } else {
+            this._availableIconSizes = baseIconSizes.filter(
+                function(val){
+                    return (val<max_size);
+                }
+            );
+            this._availableIconSizes.push(max_size);
+        }
+
+        if (doNotAnimate)
+            this._shownInitially = false;
+
+        this._queueRedisplay();
+
+    },
+
+    // Reset the displayed apps icon to mantain the correct order when changing
+    // show favorites/show running settings
+    resetAppIcons : function() {
+
+        let children = this._box.get_children().filter(function(actor) {
+            return actor.child &&
+                actor.child._delegate &&
+                actor.child._delegate.icon;
+        });
+        for (let i = 0; i < children.length; i++) {
+            let item = children[i];
+            item.destroy();
+        }
+
+        // to avoid ugly animations, just suppress them like when dash is first loaded.
+        this._shownInitially = false;
+        this._redisplay();
+
+    },
+
+    _clearDragPlaceholder: function() {
+        if (this._dragPlaceholder) {
+            this._animatingPlaceholdersCount++;
+            this._dragPlaceholder.animateOutAndDestroy();
+            this._dragPlaceholder.connect('destroy',
+                Lang.bind(this, function() {
+                    this._animatingPlaceholdersCount--;
+                }));
+            this._dragPlaceholder = null;
+        }
+        this._dragPlaceholderPos = -1;
+    },
+
+    _clearEmptyDropTarget: function() {
+        if (this._emptyDropTarget) {
+            this._emptyDropTarget.animateOutAndDestroy();
+            this._emptyDropTarget = null;
+        }
+    },
+
+    handleDragOver : function(source, actor, x, y, time) {
+        let app = Dash.getAppFromSource(source);
+
+        // Don't allow favoriting of transient apps
+        if (app == null || app.is_window_backed())
+            return DND.DragMotionResult.NO_DROP;
+
+        let favorites = AppFavorites.getAppFavorites().getFavorites();
+        let numFavorites = favorites.length;
+
+        let favPos = favorites.indexOf(app);
+
+        let children = this._box.get_children();
+        let numChildren = children.length;
+        let boxHeight = 0;
+        for (let i = 0; i < numChildren; i++) {
+            boxHeight += this._isHorizontal?children[i].width:children[i].height;
+        }
+
+        // Keep the placeholder out of the index calculation; assuming that
+        // the remove target has the same size as "normal" items, we don't
+        // need to do the same adjustment there.
+        if (this._dragPlaceholder) {
+            boxHeight -= this._isHorizontal?this._dragPlaceholder.width:this._dragPlaceholder.height;
+            numChildren--;
+        }
+
+        let pos;
+        if (!this._emptyDropTarget){
+            pos = Math.floor((this._isHorizontal?x:y) * numChildren / boxHeight);
+            if (pos >  numChildren)
+                pos = numChildren;
+        } else
+            pos = 0; // always insert at the top when dash is empty
+
+        /* Take into account childredn position in rtl*/
+        if (this._isHorizontal &&
+          Clutter.get_default_text_direction() == Clutter.TextDirection.RTL
+          )
+            pos = numChildren - pos;
+
+        if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
+            this._dragPlaceholderPos = pos;
+
+            // Don't allow positioning before or after self
+            if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
+                this._clearDragPlaceholder();
+                return DND.DragMotionResult.CONTINUE;
+            }
+
+            // If the placeholder already exists, we just move
+            // it, but if we are adding it, expand its size in
+            // an animation
+            let fadeIn;
+            if (this._dragPlaceholder) {
+                this._dragPlaceholder.destroy();
+                fadeIn = false;
+            } else {
+                fadeIn = true;
+            }
+
+            this._dragPlaceholder = new Dash.DragPlaceholderItem();
+            this._dragPlaceholder.child.set_width (this.iconSize);
+            this._dragPlaceholder.child.set_height (this.iconSize / 2);
+            this._box.insert_child_at_index(this._dragPlaceholder,
+                                            this._dragPlaceholderPos);
+            this._dragPlaceholder.show(fadeIn);
+            // Ensure the next and previous icon are visible when moving the placeholder
+            // (I assume there's room for both of them)
+            if (this._dragPlaceholderPos > 1)
+                ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[this._dragPlaceholderPos-1]);
+            if (this._dragPlaceholderPos < this._box.get_children().length-1)
+                ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[this._dragPlaceholderPos+1]);
+        }
+
+        // Remove the drag placeholder if we are not in the
+        // "favorites zone"
+        if (pos > numFavorites)
+            this._clearDragPlaceholder();
+
+        if (!this._dragPlaceholder)
+            return DND.DragMotionResult.NO_DROP;
+
+        let srcIsFavorite = (favPos != -1);
+
+        if (srcIsFavorite)
+            return DND.DragMotionResult.MOVE_DROP;
+
+        return DND.DragMotionResult.COPY_DROP;
+    },
+
+    // Draggable target interface
+    acceptDrop : function(source, actor, x, y, time) {
+        let app = Dash.getAppFromSource(source);
+
+        // Don't allow favoriting of transient apps
+        if (app == null || app.is_window_backed()) {
+            return false;
+        }
+
+        let id = app.get_id();
+
+        let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
+
+        let srcIsFavorite = (id in favorites);
+
+        let favPos = 0;
+        let children = this._box.get_children();
+        for (let i = 0; i < this._dragPlaceholderPos; i++) {
+            if (this._dragPlaceholder &&
+                children[i] == this._dragPlaceholder)
+                continue;
+
+            let childId = children[i].child._delegate.app.get_id();
+            if (childId == id)
+                continue;
+            if (childId in favorites)
+                favPos++;
+        }
+
+        // No drag placeholder means we don't wan't to favorite the app
+        // and we are dragging it to its original position
+        if (!this._dragPlaceholder)
+            return true;
+
+        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
+            function () {
+                let appFavorites = AppFavorites.getAppFavorites();
+                if (srcIsFavorite)
+                    appFavorites.moveFavoriteToPos(id, favPos);
+                else
+                    appFavorites.addFavoriteAtPos(id, favPos);
+                return false;
+            }));
+
+        return true;
+    }
+});
+
+Signals.addSignalMethods(myDash.prototype);
+
+
+/**
+ * Extend AppIcon
+ *
+ * - Pass settings to the constructor and bind settings changes
+ * - Apply a css class based on the number of windows of each application (#N);
+ *   a class of the form "running#N" is applied to the AppWellIcon actor.
+ *   like the original .running one.
+ * - add a .focused style to the focused app
+ * - Customize click actions.
+ * - Update minimization animation target
+ *
+ */
+
+let tracker = Shell.WindowTracker.get_default();
+
+const clickAction = {
+    SKIP: 0,
+    MINIMIZE: 1,
+    LAUNCH: 2,
+    CYCLE_WINDOWS: 3
+};
+
+let recentlyClickedAppLoopId = 0;
+let recentlyClickedApp = null;
+let recentlyClickedAppWindows = null;
+let recentlyClickedAppIndex = 0;
+
+const myAppIcon = new Lang.Class({
+    Name: 'dashToDock.AppIcon',
+    Extends: AppDisplay.AppIcon,
+
+    // settings are required inside.
+    _init: function(settings, app, iconParams, onActivateOverride) {
+
+        this._settings = settings;
+        this._maxN =4;
+
+        this.parent(app, iconParams, onActivateOverride);
+
+        // Monitor windows-changes instead of app state.
+        // Keep using the same Id and function callback (that is extended)
+        if(this._stateChangedId>0){
+            this.app.disconnect(this._stateChangedId);
+            this._stateChangedId=0;
+        }
+
+        this._stateChangedId = this.app.connect('windows-changed',
+                                                Lang.bind(this,
+                                                          this.onWindowsChanged));
+        this._focuseAppChangeId = tracker.connect('notify::focus-app',
+                                                Lang.bind(this,
+                                                          this._onFocusAppChanged));
+
+         /* To keep compatibility with 3.14.0 and 3.14.1
+         * after upstream commit 24c0a1a1d458c8d1ba1b9d3e728a27d347f7833f
+         * (https://bugzilla.gnome.org/show_bug.cgi?id=739497),
+         * temporary call _updateRunningStyle(). This ensure windows counter updates
+         * on 3.14 and 3.14.1 where the parent not-extended method, which have
+         * a different name, is called instead.
+         */
+         this._updateRunningStyle();
+
+    },
+
+    _onDestroy: function() {
+        this.parent();
+
+        // Disconect global signals
+        // stateChangedId is already handled by parent)
+        if(this._focusAppId>0)
+            tracker.disconnect(this._focusAppId);
+    },
+
+    onWindowsChanged: function() {
+
+      this._updateRunningStyle();
+      this.updateIconGeometry();
+
+    },
+
+    // Update taraget for minimization animation
+    updateIconGeometry: function() {
+
+        let rect = new Meta.Rectangle();
+
+        [rect.x, rect.y] = this.actor.get_transformed_position();
+        [rect.width, rect.height] = this.actor.get_transformed_size();
+
+        let windows = this.app.get_windows();
+        windows.forEach(function(w) {
+            w.set_icon_geometry(rect);
+        });
+
+    },
+
+    _updateRunningStyle: function() {
+
+        /* To keep compatibility with 3.14.0 and 3.14.1
+         * after upstream commit 24c0a1a1d458c8d1ba1b9d3e728a27d347f7833f
+         * (https://bugzilla.gnome.org/show_bug.cgi?id=739497),
+         * check for which method is defined
+         */
+        if(AppDisplay.AppIcon.prototype._updateRunningStyle)
+          this.parent();
+        else
+          AppDisplay.AppIcon.prototype._onStateChanged.call(this);
+
+        this._updateCounterClass();
+    },
+
+    popupMenu: function() {
+        this._removeMenuTimeout();
+        this.actor.fake_release();
+        this._draggable.fakeRelease();
+
+        if (!this._menu) {
+            this._menu = new myAppIconMenu(this, this._settings);
+            this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
+                this.activateWindow(window);
+            }));
+            this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) {
+                if (!isPoppedUp)
+                    this._onMenuPoppedDown();
+            }));
+            let id = Main.overview.connect('hiding', Lang.bind(this, function () { this._menu.close(); }));
+            this._menu.actor.connect('destroy', function() {
+                Main.overview.disconnect(id);
+            });
+
+            this._menuManager.addMenu(this._menu);
+        }
+
+        this.emit('menu-state-changed', true);
+
+        this.actor.set_hover(true);
+        this._menu.popup();
+        this._menuManager.ignoreRelease();
+        this.emit('sync-tooltip');
+
+        return false;
+    },
+
+    _onFocusAppChanged: function() {
+        if(tracker.focus_app == this.app)
+            this.actor.add_style_class_name('focused');
+        else
+            this.actor.remove_style_class_name('focused');
+    },
+
+    activate: function(button) {
+
+        if ( !this._settings.get_boolean('customize-click') ){
+            this.parent(button);
+            return;
+        }
+
+        let event = Clutter.get_current_event();
+        let modifiers = event ? event.get_state() : 0;
+        let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK &&
+                            this.app.state == Shell.AppState.RUNNING ||
+                            button && button == 2;
+        let focusedApp = tracker.focus_app;
+
+        if (this.app.state == Shell.AppState.STOPPED || openNewWindow)
+            this.animateLaunch();
+
+        if(button && button == 1 && this.app.state == Shell.AppState.RUNNING) {
+
+            if(modifiers & Clutter.ModifierType.CONTROL_MASK){
+                // Keep default behaviour: launch new window
+                // By calling the parent method I make it compatible
+                // with other extensions tweaking ctrl + click
+                this.parent(button);
+                return;
+
+            } else if (this._settings.get_boolean('minimize-shift') && modifiers & Clutter.ModifierType.SHIFT_MASK){
+                // On double click, minimize all windows in the current workspace
+                minimizeWindow(this.app, event.get_click_count() > 1);
+
+            } else if(this.app == focusedApp && !Main.overview._shown){
+
+                if(this._settings.get_enum('click-action') == clickAction.CYCLE_WINDOWS)
+                    cycleThroughWindows(this.app);
+                else if(this._settings.get_enum('click-action') == clickAction.MINIMIZE)
+                    minimizeWindow(this.app, true);
+                else if(this._settings.get_enum('click-action') == clickAction.LAUNCH)
+                    this.app.open_new_window(-1);
+
+            } else {
+                // Activate all window of the app or only le last used
+                if (this._settings.get_enum('click-action') == clickAction.CYCLE_WINDOWS && !Main.overview._shown){
+                    // If click cycles through windows I can activate one windows at a time
+                    let windows = getAppInterestingWindows(this.app);
+                    let w = windows[0];
+                    Main.activateWindow(w);
+                } else if(this._settings.get_enum('click-action') == clickAction.LAUNCH)
+                    this.app.open_new_window(-1);
+                else if(this._settings.get_enum('click-action') == clickAction.MINIMIZE){
+                    // If click minimizes all, then one expects all windows to be reshown
+                    activateAllWindows(this.app);
+                } else
+                    this.app.activate();
+            }
+        } else {
+         // Default behaviour
+         if (openNewWindow)
+            this.app.open_new_window(-1);
+         else
+            this.app.activate();
+        }
+
+        Main.overview.hide();
+    },
+
+    _updateCounterClass: function() {
+
+        let n = getAppInterestingWindows(this.app).length;
+
+        if(n>this._maxN)
+             n = this._maxN;
+
+        for(let i = 1; i<=this._maxN; i++){
+            let className = 'running'+i;
+            if(i!=n)
+                this.actor.remove_style_class_name(className);
+            else
+                this.actor.add_style_class_name(className);
+        }
+    }
+});
+
+function minimizeWindow(app, param){
+    // Param true make all app windows minimize
+    let windows = getAppInterestingWindows(app);
+    let current_workspace = global.screen.get_active_workspace();
+    for (let i = 0; i < windows.length; i++) {
+        let w = windows[i];
+        if (w.get_workspace() == current_workspace && w.showing_on_its_workspace()){
+            w.minimize();
+            // Just minimize one window. By specification it should be the
+            // focused window on the current workspace.
+            if(!param)
+                break;
+        }
+    }
+}
+
+/*
+ * By default only non minimized windows are activated.
+ * This activates all windows in the current workspace.
+ */
+function activateAllWindows(app){
+
+    // First activate first window so workspace is switched if needed.
+    app.activate();
+
+    // then activate all other app windows in the current workspace
+    let windows = getAppInterestingWindows(app);
+    let activeWorkspace = global.screen.get_active_workspace_index();
+
+    if( windows.length<=0)
+        return;
+
+    let activatedWindows = 0;
+
+    for (let i=windows.length-1; i>=0; i--){
+        if(windows[i].get_workspace().index() == activeWorkspace){
+            Main.activateWindow(windows[i]);
+            activatedWindows++;
+        }
+    }
+}
+
+function cycleThroughWindows(app) {
+
+    // Store for a little amount of time last clicked app and its windows
+    // since the order changes upon window interaction
+    let MEMORY_TIME=3000;
+
+    let app_windows = getAppInterestingWindows(app);
+
+    if(recentlyClickedAppLoopId>0)
+        Mainloop.source_remove(recentlyClickedAppLoopId);
+    recentlyClickedAppLoopId = Mainloop.timeout_add(MEMORY_TIME, resetRecentlyClickedApp);
+
+    // If there isn't already a list of windows for the current app,
+    // or the stored list is outdated, use the current windows list.
+    if( !recentlyClickedApp ||
+        recentlyClickedApp.get_id() != app.get_id() ||
+        recentlyClickedAppWindows.length != app_windows.length
+      ){
+
+        recentlyClickedApp = app;
+        recentlyClickedAppWindows = app_windows;
+        recentlyClickedAppIndex = 0;
+    }
+
+    recentlyClickedAppIndex++;
+    let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length;
+    let window = recentlyClickedAppWindows[index];
+
+    Main.activateWindow(window);
+}
+
+function resetRecentlyClickedApp() {
+
+    if(recentlyClickedAppLoopId>0)
+        Mainloop.source_remove(recentlyClickedAppLoopId);
+    recentlyClickedAppLoopId=0;
+    recentlyClickedApp =null;
+    recentlyClickedAppWindows = null;
+    recentlyClickedAppIndex = 0;
+
+    return false;
+}
+
+function getAppInterestingWindows(app) {
+    // Filter out unnecessary windows, for instance
+    // nautilus desktop window.
+    let windows = app.get_windows().filter(function(w) {
+        return !w.skip_taskbar;
+    });
+
+    return windows;
+}
+
+
+/*
+ * This is a copy of the same function in utils.js, but also adjust horizontal scrolling
+ * and perform few further cheks on the current value to avoid changing the values when
+ * it would be clamp to the current one in any case.
+ * Return the amount of shift applied
+*/
+function ensureActorVisibleInScrollView(scrollView, actor) {
+
+    let adjust_v = true;
+    let adjust_h = true;
+
+    let vadjustment = scrollView.vscroll.adjustment;
+    let hadjustment = scrollView.hscroll.adjustment;
+    let [vvalue, vlower, vupper, vstepIncrement, vpageIncrement, vpageSize] = vadjustment.get_values();
+    let [hvalue, hlower, hupper, hstepIncrement, hpageIncrement, hpageSize] = hadjustment.get_values();
+
+    let [hvalue0, vvalue0] = [hvalue, vvalue];
+
+    let voffset = 0;
+    let hoffset = 0;
+    let fade = scrollView.get_effect("fade");
+    if (fade){
+        voffset = fade.vfade_offset;
+        hoffset = fade.hfade_offset;
+    }
+
+    let box = actor.get_allocation_box();
+    let y1 = box.y1, y2 = box.y2, x1 = box.x1, x2 = box.x2;
+
+    let parent = actor.get_parent();
+    while (parent != scrollView) {
+        if (!parent)
+            throw new Error("actor not in scroll view");
+
+        let box = parent.get_allocation_box();
+        y1 += box.y1;
+        y2 += box.y1;
+        x1 += box.x1;
+        x2 += box.x1;
+        parent = parent.get_parent();
+    }
+
+    if (y1 < vvalue + voffset)
+        vvalue = Math.max(0, y1 - voffset);
+    else if (vvalue < vupper - vpageSize && y2 > vvalue + vpageSize - voffset)
+        vvalue = Math.min(vupper -vpageSize, y2 + voffset - vpageSize);
+
+    if (x1 < hvalue + hoffset)
+        hvalue = Math.max(0, x1 - hoffset);
+    else if (hvalue < hupper - hpageSize && x2 > hvalue + hpageSize - hoffset)
+        hvalue = Math.min(hupper - hpageSize, x2 + hoffset - hpageSize);
+
+    if (vvalue !== vvalue0) {
+        Tweener.addTween(vadjustment,
+                         { value: vvalue,
+                           time: Util.SCROLL_TIME,
+                           transition: 'easeOutQuad' });
+    }
+
+    if (hvalue !== hvalue0) {
+        Tweener.addTween(hadjustment,
+                         { value: hvalue,
+                           time: Util.SCROLL_TIME,
+                           transition: 'easeOutQuad' });
+    }
+
+    return [hvalue- hvalue0, vvalue - vvalue0];
+}
diff --git a/extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml.in b/extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml.in
new file mode 100644
index 0000000..e59f35a
--- /dev/null
+++ b/extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml.in
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist gettext-domain="gnome-shell-extensions">
+  <enum id='org.gnome.shell.extensions.dash-to-dock.clickAction'>
+    <value value='0' nick='skip'/>
+    <value value='1' nick='minimize'/>
+    <value value='2' nick='launch'/>
+    <value value='3' nick='cycle-windows'/>
+  </enum>
+  <!-- this is mean to Match StSide. LEFT and RIGHT actual position in reversed in
+       rtl languages -->
+  <enum id='org.gnome.shell.extensions.dash-to-dock.position'>
+    <value value='0' nick='TOP'/>
+    <value value='1' nick='RIGHT'/>
+    <value value='2' nick='BOTTOM'/>
+    <value value='3' nick='LEFT'/>
+  </enum>
+  <schema path="/org/gnome/shell/extensions/dash-to-dock/" id="org.gnome.shell.extensions.dash-to-dock">
+    <key name="dock-position" enum="org.gnome.shell.extensions.dash-to-dock.position">
+      <default>'LEFT'</default>
+      <summary>Dock position</summary>
+      <description>Dock is shown on the Left, Right, Top or Bottom side of the screen.</description>
+    </key>
+    <key type="d" name="animation-time">
+      <default>0.25</default>
+      <summary>Animation time</summary>
+      <description>Sets the time duration of the autohide effect.</description>
+    </key>
+    <key type="d" name="show-delay">
+      <default>0.25</default>
+      <summary>Show delay</summary>
+      <description>Sets the delay after the mouse reaches the screen border before showing the dock.</description>
+    </key>
+    <key type="d" name="hide-delay">
+      <default>0.20</default>
+      <summary>Show delay</summary>
+      <description>Sets the delay after the mouse left the dock before hiding it.</description>
+    </key>
+    <key type="b" name="opaque-background">
+      <default>false</default>
+      <summary>Dash background is opaque</summary>
+      <description>Makes the background of the dash opaque improving readability when in autohide mode.</description>
+    </key>
+    <key type="d" name="background-opacity">
+      <default>0.8</default>
+      <summary>Opacity of the dash background</summary>
+      <description>Sets the opacity of the dash background  when in autohide mode.</description>
+    </key>
+    <key type="b" name="intellihide">
+      <default>true</default>
+      <summary>Dock dodges windows</summary>
+      <description>Enable or disable intellihide mode</description>
+    </key>
+    <key type="b" name="intellihide-perapp">
+      <default>true</default>
+      <summary>Dock dodges only same app windows</summary>
+      <description></description>
+    </key>
+    <key type="b" name="autohide">
+      <default>true</default>
+      <summary>Dock shown on mouse over</summary>
+      <description>Enable or disable autohide mode</description>
+    </key>
+    <key type="b" name="require-pressure-to-show">
+      <default>true</default>
+      <summary>Require pressure to show dash</summary>
+      <description>Enable or disable requiring pressure to show the dash</description>
+    </key>
+    <key type="d" name="pressure-threshold">
+      <default>100</default>
+      <summary>Pressure threshold</summary>
+      <description>Sets how much pressure is needed to show the dash.</description>
+    </key>
+    <key type="b" name="dock-fixed">
+      <default>false</default>
+      <summary>Dock always visible</summary>
+      <description>Dock is always visible</description>
+    </key>
+    <key type="b" name="scroll-switch-workspace">
+      <default>true</default>
+      <summary>Switch workspace by scrolling over the dock</summary>
+      <description>Add the possibility to switch workspace by mouse scrolling over the dock.</description>
+    </key>
+    <key type="i" name="dash-max-icon-size">
+      <default>48</default>
+      <summary>Maximum dash icon size</summary>
+      <description>Set the allowed maximum dash icon size. Allowed range: 16..64.</description>
+    </key>
+    <key type="b" name="icon-size-fixed">
+      <default>false</default>
+      <summary>Fixed icon size</summary>
+      <description>Keep the icon size fived by scrolling the dock.</description>
+    </key>
+    <key type="b" name="apply-custom-theme">
+      <default>false</default>
+      <summary>Apply custom theme</summary>
+      <description>Apply customization to the dash appearance</description>
+    </key>
+    <key type="b" name="custom-theme-shrink">
+      <default>false</default>
+      <summary>TODO</summary>
+      <description>TODO</description>
+    </key>
+    <key type="b" name="custom-theme-running-dots">
+      <default>false</default>
+      <summary>TODO</summary>
+      <description>TODO</description>
+    </key>
+    <key type="b" name="show-running">
+      <default>true</default>
+      <summary>Show running apps</summary>
+      <description>Show or hide running appplications icons in the dash</description>
+    </key>
+    <key type="b" name="show-apps-at-top">
+      <default>false</default>
+      <summary>Show application button at top</summary>
+      <description>Show appplication button at top of the dash</description>
+    </key>
+    <key type="b" name="bolt-support">
+      <default>true</default>
+      <summary>Basic compatibility with bolt extensions</summary>
+      <description>Make the extension work properly when bolt extensions is enabled</description>
+    </key>
+    <key type="d" name="height-fraction">
+      <default>0.95</default>
+      <summary>Dock max height (fraction of available space)</summary>
+    </key>
+    <key type="b" name="extend-height">
+      <default>false</default>
+      <summary>Extend the dock container to all the available height</summary>
+    </key>
+    <key type="i" name="preferred-monitor">
+      <default>-1</default>
+      <summary>Monitor on which putting the dock</summary>
+      <description>Set on which monitor to put the dock, use -1 for the primary one</description>
+    </key>
+    <key type="b" name="customize-click">
+      <default>true</default>
+      <summary>Customize click behaviour</summary>
+      <description>Customize action on various mouse events</description>
+    </key>
+    <key type="b" name="minimize-shift">
+      <default>true</default>
+      <summary>Minimize on shift+click</summary>
+    </key>
+    <key type="b" name="activate-single-window">
+      <default>true</default>
+      <summary>Activate only one window</summary>
+    </key>
+    <key name="click-action" enum="org.gnome.shell.extensions.dash-to-dock.clickAction">
+      <default>'cycle-windows'</default>
+      <summary>Action when clicking on a running app</summary>
+      <description>Set the action that is executed when clicking on the icon of a running application</description>
+    </key>
+    <key type="b" name="insensitive-message-tray">
+      <default>false</default>
+      <summary>Make message tray not show on mouse-over.</summary>
+    </key>
+  </schema>
+</schemalist>
diff --git a/extensions/dash-to-dock/prefs.js b/extensions/dash-to-dock/prefs.js
new file mode 100644
index 0000000..4afecec
--- /dev/null
+++ b/extensions/dash-to-dock/prefs.js
@@ -0,0 +1,367 @@
+// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Gdk = imports.gi.Gdk;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+
+
+const Gettext = imports.gettext.domain('dashtodock');
+const _ = Gettext.gettext;
+const N_ = function(e) { return e };
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const Me = ExtensionUtils.getCurrentExtension();
+const Convenience = Me.imports.convenience;
+
+const SCALE_UPDATE_TIMEOUT = 500;
+const DEFAULT_ICONS_SIZES = [ 128, 96, 64, 48, 32, 24, 16 ];
+
+const Settings = new Lang.Class({
+    Name: 'DashToDockSettings',
+
+
+    _init: function() {
+
+        this._settings = Convenience.getSettings('org.gnome.shell.extensions.dash-to-dock');
+
+        this._rtl = Gtk.Widget.get_default_direction()==Gtk.TextDirection.RTL;
+
+        this._builder = new Gtk.Builder();
+        this._builder.set_translation_domain(Me.metadata['gettext-domain']);
+        this._builder.add_from_file(Me.path + '/Settings.ui');
+
+        this.widget = this._builder.get_object('settings_notebook');
+
+        // Timeout to delay the update of the settings
+        this._dock_size_timeout = 0;
+        this._icon_size_timeout = 0;
+        this._opacity_timeout = 0;
+
+        this._bindSettings();
+
+        this._builder.connect_signals_full(Lang.bind(this, this._connector));
+
+    },
+
+    // Connect signals
+    _connector: function(builder, object, signal, handler) {
+        object.connect(signal, Lang.bind(this, this._SignalHandler[handler]));
+    },
+
+    _bindSettings: function() {
+
+        /* Position and size panel */
+
+        // Monitor options
+
+        this._monitors = [];
+        // Build options based on the number of monitors and the current settings.
+        let n_monitors = Gdk.Screen.get_default().get_n_monitors();
+        let primary_monitor = Gdk.Screen.get_default().get_primary_monitor();
+
+        let monitor = this._settings.get_int('preferred-monitor');
+
+        // Add primary monitor with index 0, because in GNOME Shell the primary monitor is always 0
+        this._builder.get_object('dock_monitor_combo').append_text(_("Primary monitor"));
+        this._monitors.push(0);
+
+        // Add connected monitors
+        let ctr = 0;
+        for (let i = 0; i < n_monitors; i++) {
+            if (i !== primary_monitor){
+                ctr++;
+                this._monitors.push(ctr);
+                this._builder.get_object('dock_monitor_combo').append_text(_("Secondary monitor ") + ctr);
+            }
+        }
+
+        // If one of the external monitor is set as preferred, show it even if not attached
+        if ( monitor >= n_monitors && monitor !== primary_monitor) {
+            this._monitors.push(monitor)
+            this._builder.get_object('dock_monitor_combo').append_text(_("Secondary monitor ") + ++ctr);
+        }
+
+        this._builder.get_object('dock_monitor_combo').set_active(this._monitors.indexOf(monitor));
+
+        // Position option
+        let position = this._settings.get_enum('dock-position');
+
+        switch (position) {
+            case 0:
+                this._builder.get_object('position_top_button').set_active(true);
+                break;
+            case 1:
+                this._builder.get_object('position_right_button').set_active(true);
+                break;
+            case 2:
+                this._builder.get_object('position_bottom_button').set_active(true);
+                break;
+            case 3:
+                this._builder.get_object('position_left_button').set_active(true);
+                break;
+        }
+
+        if (this._rtl) {
+            /* Left is Right in rtl as a setting */
+            this._builder.get_object('position_left_button').set_label(_("Right"));
+            this._builder.get_object('position_right_button').set_label(_("Left"));
+        }
+
+        // Intelligent autohide options
+        this._settings.bind('dock-fixed',
+                            this._builder.get_object('intelligent_autohide_switch'),
+                            'active',
+                            Gio.SettingsBindFlags.INVERT_BOOLEAN);
+        this._settings.bind('dock-fixed',
+                            this._builder.get_object('intelligent_autohide_button'),
+                            'sensitive',
+                            Gio.SettingsBindFlags.INVERT_BOOLEAN);
+        this._settings.bind('insensitive-message-tray',
+                            this._builder.get_object('insensitive_messagetray_checkbutton'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('autohide',
+                            this._builder.get_object('autohide_switch'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('require-pressure-to-show',
+                            this._builder.get_object('require_pressure_checkbutton'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('intellihide',
+                            this._builder.get_object('intellihide_switch'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('intellihide-perapp',
+                            this._builder.get_object('per_app_intellihide_checkbutton'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('animation-time',
+                            this._builder.get_object('animation_duration_spinbutton'),
+                            'value',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('hide-delay',
+                            this._builder.get_object('hide_timeout_spinbutton'),
+                            'value',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('show-delay',
+                            this._builder.get_object('show_timeout_spinbutton'),
+                            'value',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('pressure-threshold',
+                            this._builder.get_object('pressure_threshold_spinbutton'),
+                            'value',
+                            Gio.SettingsBindFlags.DEFAULT);
+
+        //this._builder.get_object('animation_duration_spinbutton').set_value(this._settings.get_double('animation-time'));
+
+        // Create dialog for intelligent autohide advanced settings
+        this._builder.get_object('intelligent_autohide_button').connect('clicked', Lang.bind(this, function() {
+
+            let dialog = new Gtk.Dialog({ title: _("Intelligent autohide customization"),
+                                          transient_for: this.widget.get_toplevel(),
+                                          use_header_bar: true,
+                                          modal: true });
+
+            // GTK+ leaves positive values for application-defined response ids.
+            // Use +1 for the reset action 
+            dialog.add_button(_("Reset to defaults"), 1);
+
+            let box = this._builder.get_object('intelligent_autohide_advanced_settings_box');
+            dialog.get_content_area().add(box);
+
+            this._settings.bind('intellihide',
+                            this._builder.get_object('per_app_intellihide_checkbutton'),
+                            'sensitive',
+                            Gio.SettingsBindFlags.GET);
+
+            this._settings.bind('autohide',
+                            this._builder.get_object('require_pressure_checkbutton'),
+                            'sensitive',
+                            Gio.SettingsBindFlags.GET);
+
+            dialog.connect('response', Lang.bind(this, function(dialog, id) {
+                if (id == 1) {
+                    // restore default settings for the relevant keys
+                    let keys = ['intellihide', 'autohide', 'intellihide-perapp', 'require-pressure-to-show',
+                                'animation-time', 'show-delay', 'hide-delay'];
+                    keys.forEach(function(val){
+                        this._settings.set_value(val, this._settings.get_default_value(val));
+                    }, this);
+                } else {
+                    // remove the settings box so it doesn't get destroyed;
+                    dialog.get_content_area().remove(box);
+                    dialog.destroy();
+                }
+                return;
+            }));
+
+            dialog.show_all();
+
+        }));
+
+        // size options
+        this._builder.get_object('dock_size_scale').set_value(this._settings.get_double('height-fraction'));
+        this._builder.get_object('dock_size_scale').add_mark(0.9, Gtk.PositionType.TOP, null);
+        let icon_size_scale = this._builder.get_object('icon_size_scale');
+        icon_size_scale.set_range(DEFAULT_ICONS_SIZES[DEFAULT_ICONS_SIZES.length -1], DEFAULT_ICONS_SIZES[0]);
+        icon_size_scale.set_value(this._settings.get_int('dash-max-icon-size'));
+        DEFAULT_ICONS_SIZES.forEach(function(val){
+                icon_size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString());
+        });
+
+        // Corrent for rtl languages
+        if (this._rtl) {
+            // Flip value position: this is not done automatically
+            this._builder.get_object('dock_size_scale').set_value_pos(Gtk.PositionType.LEFT);
+            icon_size_scale.set_value_pos(Gtk.PositionType.LEFT);
+            /* I suppose due to a bug, having a more than one mark and one above a value of 100
+             * makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable
+             * and then manually inverting it
+             */
+            icon_size_scale.set_flippable(false);
+            icon_size_scale.set_inverted(true);
+        }
+
+        this._settings.bind('icon-size-fixed', this._builder.get_object('icon_size_fixed_checkbutton'), 'active', Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('extend-height', this._builder.get_object('dock_size_extend_checkbutton'), 'active', Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('extend-height', this._builder.get_object('dock_size_scale'), 'sensitive', Gio.SettingsBindFlags.INVERT_BOOLEAN);
+
+
+        /* Behavior panel */
+
+        this._settings.bind('show-running',
+                            this._builder.get_object('show_running_switch'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('show-apps-at-top',
+                            this._builder.get_object('application_button_first_switch'),
+                            'active',
+                            Gio.SettingsBindFlags.DEFAULT);
+
+        this._builder.get_object('click_action_combo').set_active(this._settings.get_enum('click-action'));
+        this._builder.get_object('click_action_combo').connect('changed', Lang.bind (this, function(widget) {
+                this._settings.set_enum('click-action', widget.get_active());
+        }));
+
+        this._builder.get_object('shift_click_action_combo').set_active(this._settings.get_boolean('minimize-shift')?0:1);
+
+        this._builder.get_object('shift_click_action_combo').connect('changed', Lang.bind (this, function(widget) {
+                this._settings.set_boolean('minimize-shift', widget.get_active()==1);
+        }));
+
+        this._settings.bind('scroll-switch-workspace', this._builder.get_object('switch_workspace_switch'), 'active', Gio.SettingsBindFlags.DEFAULT);
+
+        /* Appearance Panel */
+
+        this._settings.bind('apply-custom-theme', this._builder.get_object('customize_theme'), 'sensitive', Gio.SettingsBindFlags.INVERT_BOOLEAN | Gio.SettingsBindFlags.GET);
+        this._settings.bind('apply-custom-theme', this._builder.get_object('builtin_theme_switch'), 'active', Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('custom-theme-shrink', this._builder.get_object('shrink_dash_switch'), 'active', Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('custom-theme-running-dots', this._builder.get_object('running_dots_switch'), 'active', Gio.SettingsBindFlags.DEFAULT);
+        this._settings.bind('opaque-background', this._builder.get_object('customize_opacity_switch'), 'active', Gio.SettingsBindFlags.DEFAULT);
+        this._builder.get_object('custom_opacity_scale').set_value(this._settings.get_double('background-opacity'));
+        this._settings.bind('opaque-background', this._builder.get_object('custom_opacity'), 'sensitive', Gio.SettingsBindFlags.DEFAULT);
+
+        /* About Panel */
+
+        this._builder.get_object('extension_version').set_label(Me.metadata.version.toString());
+
+    },
+
+
+    // Object containing all signals defined in the glade file
+    _SignalHandler: {
+
+            dock_display_combo_changed_cb: function (combo) {
+                this._settings.set_int('preferred-monitor', this._monitors[combo.get_active()]);
+            },
+
+            position_top_button_toggled_cb: function (button){
+                if (button.get_active()) 
+                    this._settings.set_enum('dock-position', 0);
+            },
+
+            position_right_button_toggled_cb: function (button) {
+                if (button.get_active()) 
+                    this._settings.set_enum('dock-position', 1);
+            },
+
+            position_bottom_button_toggled_cb: function (button) {
+                if (button.get_active()) 
+                    this._settings.set_enum('dock-position', 2);
+            },
+
+            position_left_button_toggled_cb: function (button) {
+                if (button.get_active()) 
+                    this._settings.set_enum('dock-position', 3);
+            },
+
+            icon_size_combo_changed_cb: function(combo) {
+                this._settings.set_int('dash-max-icon-size', this._allIconSizes[combo.get_active()]);
+            },
+
+            dock_size_scale_format_value_cb: function(scale, value) {
+                return Math.round(value*100)+ ' %';
+            },
+
+            dock_size_scale_value_changed_cb: function(scale){
+                // Avoid settings the size consinuosly
+                if (this._dock_size_timeout >0)
+                    Mainloop.source_remove(this._dock_size_timeout);
+
+                this._dock_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function(){
+                    this._settings.set_double('height-fraction', scale.get_value());
+                    this._dock_size_timeout = 0;
+                    return GLib.SOURCE_REMOVE;
+                }));       
+            },
+
+            icon_size_scale_format_value_cb: function(scale, value) {
+                return value+ ' px';
+            },
+
+            icon_size_scale_value_changed_cb: function(scale){
+                // Avoid settings the size consinuosly
+                if (this._icon_size_timeout >0)
+                    Mainloop.source_remove(this._icon_size_timeout);
+
+                this._icon_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function(){
+                    this._settings.set_int('dash-max-icon-size', scale.get_value());
+                    this._icon_size_timeout = 0;
+                    return GLib.SOURCE_REMOVE;
+                }));       
+            },
+
+            custom_opacity_scale_value_changed_cb: function(scale){
+                // Avoid settings the opacity consinuosly as it's change is animated
+                if (this._opacity_timeout >0)
+                    Mainloop.source_remove(this._opacity_timeout);
+
+                this._opacity_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function(){
+                    this._settings.set_double('background-opacity', scale.get_value());
+                    this._opacity_timeout = 0;
+                    return GLib.SOURCE_REMOVE;
+                }));
+            },
+
+            custom_opacity_scale_format_value_cb: function(scale, value) {
+                return Math.round(value*100) + ' %';
+            }
+    }
+});
+
+function init() {
+    Convenience.initTranslations();
+}
+
+function buildPrefsWidget() {
+    let settings = new Settings();
+    let widget = settings.widget;
+    widget.show_all();
+    return widget;
+}
+
diff --git a/extensions/dash-to-dock/stylesheet.css b/extensions/dash-to-dock/stylesheet.css
new file mode 100644
index 0000000..e2ba893
--- /dev/null
+++ b/extensions/dash-to-dock/stylesheet.css
@@ -0,0 +1,181 @@
+/* Shrink the dash by reducing padding and border radius */
+#dashtodockContainer.shrink #dash,
+#dashtodockContainer.dashtodock #dash {
+    border:1px;
+}
+
+#dashtodockContainer.shrink.left #dash,
+#dashtodockContainer.dashtodock.left #dash {
+    padding: 1px;
+    border-left: 0px;
+    border-radius: 0px 6px 6px 0px;
+}
+
+#dashtodockContainer.shrink.right #dash,
+#dashtodockContainer.dashtodock.right #dash {
+    padding: 1px;
+    border-right: 0px;
+    border-radius: 6px 0px 0px 6px;
+}
+
+#dashtodockContainer.shrink.top #dash,
+#dashtodockContainer.dashtodock.top #dash {
+    padding: 1px;
+    border-top: 0px;
+    border-radius: 0px 0px 6px 6px;
+}
+
+#dashtodockContainer.shrink.bottom #dash,
+#dashtodockContainer.dashtodock.bottom #dash {
+    padding: 1px;
+    border-bottom: 0px;
+    border-radius: 6px 6px 0px 0px;
+}
+
+/* Scrollview style */
+.bottom #dashtodockDashScrollview,
+.top #dashtodockDashScrollview {
+    -st-hfade-offset: 24px;
+}
+
+.left #dashtodockDashScrollview,
+.right #dashtodockDashScrollview {
+    -st-vfade-offset: 24px;
+}
+
+#dashtodockContainer.running-dots .dash-item-container > StButton,
+#dashtodockContainer.dashtodock .dash-item-container > StButton {
+    transition-duration: 250;
+    background-size: contain;
+}
+
+#dashtodockContainer.shrink .dash-item-container > StButton,
+#dashtodockContainer.dashtodock .dash-item-container > StButton {
+   padding: 1px 2px;
+}
+
+/* Dash height extended to the whole available vertical space */
+#dashtodockContainer.extended.top #dash,
+#dashtodockContainer.extended.right #dash,
+#dashtodockContainer.extended.bottom #dash,
+#dashtodockContainer.extended.left #dash {
+    border-radius: 0;
+}
+
+#dashtodockContainer.extended.top #dash,
+#dashtodockContainer.extended.bottom #dash {
+    border-left:0px;
+    border-right:0px;
+}
+
+#dashtodockContainer.extended.right #dash,
+#dashtodockContainer.extended.left #dash {
+    border-top:0px;
+    border-bottom:0px;
+}
+
+/* Running and focused application style */
+
+#dashtodockContainer.running-dots .app-well-app.running > .overview-icon,
+#dashtodockContainer.dashtodock .app-well-app.running > .overview-icon {
+	background-image:none;
+}
+
+#dashtodockContainer.running-dots .app-well-app.focused > .overview-icon,
+#dashtodockContainer.dashtodock .app-well-app.focused > .overview-icon {
+    transition-duration: 250;
+    background-gradient-start: rgba(255, 255, 255, .05);
+    background-gradient-end: rgba(255, 255, 255, .15);
+    background-gradient-direction: vertical;
+    border-radius: 4px;
+    box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 1);
+}
+
+#dashtodockContainer.running-dots.left .running1,
+#dashtodockContainer.dashtodock.left .running1 {
+    background-image: url('./media/one.svg');
+}
+
+#dashtodockContainer.running-dots.right .running1,
+#dashtodockContainer.dashtodock.right .running1 {
+    background-image: url('./media/one_rtl.svg');
+}
+
+#dashtodockContainer.running-dots.bottom .running1,
+#dashtodockContainer.dashtodock.bottom .running1 {
+    background-image: url('./media/one_bottom.svg');
+}
+
+#dashtodockContainer.running-dots.top .running1,
+#dashtodockContainer.dashtodock.top .running1 {
+    background-image: url('./media/one_top.svg');
+}
+
+#dashtodockContainer.running-dots.left .running2,
+#dashtodockContainer.dashtodock.left .running2 {
+    background-image: url('./media/two.svg');
+}
+
+#dashtodockContainer.running-dots.right .running2,
+#dashtodockContainer.dashtodock.right .running2 {
+    background-image: url('./media/two_rtl.svg');
+}
+
+#dashtodockContainer.running-dots.bottom .running2,
+#dashtodockContainer.dashtodock.bottom .running2 {
+    background-image: url('./media/two_bottom.svg');
+}
+
+#dashtodockContainer.running-dots.top .running2,
+#dashtodockContainer.dashtodock.top .running2 {
+    background-image: url('./media/two_top.svg');
+}
+
+#dashtodockContainer.running-dots.left .running3,
+#dashtodockContainer.dashtodock.left .running3 {
+   background-image: url('./media/three.svg');
+}
+
+#dashtodockContainer.running-dots.right .running3,
+#dashtodockContainer.dashtodock.right .running3 {
+    background-image: url('./media/three_rtl.svg');
+}
+
+#dashtodockContainer.running-dots.bottom .running3,
+#dashtodockContainer.dashtodock.bottom .running3 {
+   background-image: url('./media/three_bottom.svg');
+}
+
+#dashtodockContainer.running-dots.top .running3,
+#dashtodockContainer.dashtodock.top .running3 {
+   background-image: url('./media/three_top.svg');
+}
+
+#dashtodockContainer.running-dots.left .running4,
+#dashtodockContainer.dashtodock.left .running4 {
+    background-image: url('./media/four.svg');
+}
+
+#dashtodockContainer.running-dots.right .running4,
+#dashtodockContainer.dashtodock.right .running4 {
+    background-image: url('./media/four_rtl.svg');
+}
+
+#dashtodockContainer.running-dots.bottom .running4,
+#dashtodockContainer.dashtodock.bottom .running4{
+    background-image: url('./media/four_bottom.svg');
+}
+
+#dashtodockContainer.running-dots.top .running4,
+#dashtodockContainer.dashtodock.top .running4 {
+    background-image: url('./media/four_top.svg');
+}
+
+#dashtodockContainer.dashtodock #dash {
+    background: rgba(0,0,0,0.9);
+}
+
+#dashtodockContainer.dashtodock:overview #dash {
+    background: rgba(0,0,0,0.5);
+    transition-duration: 250ms;
+}
-- 
2.7.2


From 93c5d76ce1bd57a1bffb6bb98e23406553b320bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 20 May 2015 18:55:47 +0200
Subject: [PATCH 3/4] Add panel-favorites extension

---
 configure.ac                                |   5 +-
 extensions/panel-favorites/Makefile.am      |   3 +
 extensions/panel-favorites/extension.js     | 267 ++++++++++++++++++++++++++++
 extensions/panel-favorites/metadata.json.in |  10 ++
 extensions/panel-favorites/stylesheet.css   |  14 ++
 5 files changed, 297 insertions(+), 2 deletions(-)
 create mode 100644 extensions/panel-favorites/Makefile.am
 create mode 100644 extensions/panel-favorites/extension.js
 create mode 100644 extensions/panel-favorites/metadata.json.in
 create mode 100644 extensions/panel-favorites/stylesheet.css

diff --git a/configure.ac b/configure.ac
index d40b9e0..92969e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_SUBST([SHELL_VERSION])
 dnl keep this in alphabetic order
 CLASSIC_EXTENSIONS="apps-menu places-menu alternate-tab launch-new-instance window-list"
 DEFAULT_EXTENSIONS="$CLASSIC_EXTENSIONS drive-menu screenshot-window-sizer windowsNavigator workspace-indicator"
-ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows dash-to-dock example native-window-placement systemMonitor top-icons user-theme"
+ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows dash-to-dock example native-window-placement panel-favorites systemMonitor top-icons user-theme"
 AC_SUBST(CLASSIC_EXTENSIONS, [$CLASSIC_EXTENSIONS])
 AC_SUBST(ALL_EXTENSIONS, [$ALL_EXTENSIONS])
 AC_ARG_ENABLE([extensions],
@@ -66,7 +66,7 @@ for e in $enable_extensions; do
 					[AC_MSG_WARN([libgtop-2.0 not found, disabling systemMonitor])])
 			;;
 dnl		keep this in alphabetic order
-		alternate-tab|apps-menu|auto-move-windows|dash-to-dock|drive-menu|example|launch-new-instance|native-window-placement|places-menu|screenshot-window-sizer|top-icons|user-theme|window-list|windowsNavigator|workspace-indicator)
+		alternate-tab|apps-menu|auto-move-windows|dash-to-dock|drive-menu|example|launch-new-instance|native-window-placement|panel-favorites|places-menu|screenshot-window-sizer|top-icons|user-theme|window-list|windowsNavigator|workspace-indicator)
 			ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
 			;;
 		*)
@@ -87,6 +87,7 @@ AC_CONFIG_FILES([
   extensions/example/Makefile
   extensions/launch-new-instance/Makefile
   extensions/native-window-placement/Makefile
+  extensions/panel-favorites/Makefile
   extensions/places-menu/Makefile
   extensions/screenshot-window-sizer/Makefile
   extensions/systemMonitor/Makefile
diff --git a/extensions/panel-favorites/Makefile.am b/extensions/panel-favorites/Makefile.am
new file mode 100644
index 0000000..4ce3128
--- /dev/null
+++ b/extensions/panel-favorites/Makefile.am
@@ -0,0 +1,3 @@
+EXTENSION_ID = panel-favorites
+
+include ../../extension.mk
diff --git a/extensions/panel-favorites/extension.js b/extensions/panel-favorites/extension.js
new file mode 100644
index 0000000..b817dbb
--- /dev/null
+++ b/extensions/panel-favorites/extension.js
@@ -0,0 +1,267 @@
+// Copyright (C) 2011-2013 R M Yorston
+// Licence: GPLv2+
+
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Shell = imports.gi.Shell;
+const Signals = imports.signals;
+const St = imports.gi.St;
+const Mainloop = imports.mainloop;
+
+const AppFavorites = imports.ui.appFavorites;
+const Main = imports.ui.main;
+const Panel = imports.ui.panel;
+const Tweener = imports.ui.tweener;
+
+const PANEL_LAUNCHER_LABEL_SHOW_TIME = 0.15;
+const PANEL_LAUNCHER_LABEL_HIDE_TIME = 0.1;
+const PANEL_LAUNCHER_HOVER_TIMEOUT = 300;
+
+const PanelLauncher = new Lang.Class({
+    Name: 'PanelLauncher',
+
+    _init: function(app) {
+        this.actor = new St.Button({ style_class: 'panel-button',
+                                     reactive: true });
+        this.iconSize = 24;
+        let icon = app.create_icon_texture(this.iconSize);
+        this.actor.set_child(icon);
+        this.actor._delegate = this;
+        let text = app.get_name();
+        if ( app.get_description() ) {
+            text += '\n' + app.get_description();
+        }
+
+        this.label = new St.Label({ style_class: 'panel-launcher-label'});
+        this.label.set_text(text);
+        Main.layoutManager.addChrome(this.label);
+        this.label.hide();
+        this.actor.label_actor = this.label;
+
+        this._app = app;
+        this.actor.connect('clicked', Lang.bind(this, function() {
+            this._app.open_new_window(-1);
+        }));
+        this.actor.connect('notify::hover',
+                Lang.bind(this, this._onHoverChanged));
+        this.actor.opacity = 207;
+
+        this.actor.connect('notify::allocation', Lang.bind(this, this._alloc));
+    },
+
+    _onHoverChanged: function(actor) {
+        actor.opacity = actor.hover ? 255 : 207;
+    },
+
+    _alloc: function() {
+        let size = this.actor.allocation.y2 - this.actor.allocation.y1 - 3;
+        if ( size >= 24 && size != this.iconSize ) {
+            this.actor.get_child().destroy();
+            this.iconSize = size;
+            let icon = this._app.create_icon_texture(this.iconSize);
+            this.actor.set_child(icon);
+        }
+    },
+
+    showLabel: function() {
+        this.label.opacity = 0;
+        this.label.show();
+
+        let [stageX, stageY] = this.actor.get_transformed_position();
+
+        let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
+        let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
+        let labelWidth = this.label.get_width();
+
+        let node = this.label.get_theme_node();
+        let yOffset = node.get_length('-y-offset');
+
+        let y = stageY + itemHeight + yOffset;
+        let x = Math.floor(stageX + itemWidth/2 - labelWidth/2);
+
+        let parent = this.label.get_parent();
+        let parentWidth = parent.allocation.x2 - parent.allocation.x1;
+
+        if ( Clutter.get_default_text_direction() == Clutter.TextDirection.LTR ) {
+            // stop long tooltips falling off the right of the screen
+            x = Math.min(x, parentWidth-labelWidth-6);
+            // but whatever happens don't let them fall of the left
+            x = Math.max(x, 6);
+        }
+        else {
+            x = Math.max(x, 6);
+            x = Math.min(x, parentWidth-labelWidth-6);
+        }
+
+        this.label.set_position(x, y);
+        Tweener.addTween(this.label,
+                         { opacity: 255,
+                           time: PANEL_LAUNCHER_LABEL_SHOW_TIME,
+                           transition: 'easeOutQuad',
+                         });
+    },
+
+    hideLabel: function() {
+        this.label.opacity = 255;
+        Tweener.addTween(this.label,
+                         { opacity: 0,
+                           time: PANEL_LAUNCHER_LABEL_HIDE_TIME,
+                           transition: 'easeOutQuad',
+                           onComplete: Lang.bind(this, function() {
+                               this.label.hide();
+                           })
+                         });
+    },
+
+    destroy: function() {
+        this.label.destroy();
+        this.actor.destroy();
+    }
+});
+
+const PanelFavorites = new Lang.Class({
+    Name: 'PanelFavorites',
+
+    _init: function() {
+        this._showLabelTimeoutId = 0;
+        this._resetHoverTimeoutId = 0;
+        this._labelShowing = false;
+
+        this.actor = new St.BoxLayout({ name: 'panelFavorites',
+                                        x_expand: true, y_expand: true,
+                                        style_class: 'panel-favorites' });
+        this._display();
+
+        this.container = new St.Bin({ y_fill: true,
+                                      x_fill: true,
+                                      child: this.actor });
+
+        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
+        this._installChangedId = Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, this._redisplay));
+        this._changedId = AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._redisplay));
+    },
+
+    _redisplay: function() {
+        for ( let i=0; i<this._buttons.length; ++i ) {
+            this._buttons[i].destroy();
+        }
+
+        this._display();
+    },
+
+    _display: function() {
+        let launchers = global.settings.get_strv(AppFavorites.getAppFavorites().FAVORITE_APPS_KEY);
+
+        this._buttons = [];
+        let j = 0;
+        for ( let i=0; i<launchers.length; ++i ) {
+            let app = Shell.AppSystem.get_default().lookup_app(launchers[i]);
+
+            if ( app == null ) {
+                continue;
+            }
+
+            let launcher = new PanelLauncher(app);
+            this.actor.add(launcher.actor);
+            launcher.actor.connect('notify::hover',
+                        Lang.bind(this, function() {
+                            this._onHover(launcher);
+                        }));
+            this._buttons[j] = launcher;
+            ++j;
+        }
+    },
+
+    // this routine stolen from dash.js
+    _onHover: function(launcher) {
+        if ( launcher.actor.hover ) {
+            if (this._showLabelTimeoutId == 0) {
+                let timeout = this._labelShowing ?
+                                0 : PANEL_LAUNCHER_HOVER_TIMEOUT;
+                this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
+                    Lang.bind(this, function() {
+                        this._labelShowing = true;
+                        launcher.showLabel();
+                        this._showLabelTimeoutId = 0;
+                        return GLib.SOURCE_REMOVE;
+                    }));
+                if (this._resetHoverTimeoutId > 0) {
+                    Mainloop.source_remove(this._resetHoverTimeoutId);
+                    this._resetHoverTimeoutId = 0;
+                }
+            }
+        } else {
+            if (this._showLabelTimeoutId > 0) {
+                Mainloop.source_remove(this._showLabelTimeoutId);
+                this._showLabelTimeoutId = 0;
+            }
+            launcher.hideLabel();
+            if (this._labelShowing) {
+                this._resetHoverTimeoutId = Mainloop.timeout_add(
+                    PANEL_LAUNCHER_HOVER_TIMEOUT,
+                    Lang.bind(this, function() {
+                        this._labelShowing = false;
+                        this._resetHoverTimeoutId = 0;
+                        return GLib.SOURCE_REMOVE;
+                    }));
+            }
+        }
+    },
+
+    _onDestroy: function() {
+        if ( this._installChangedId != 0 ) {
+            Shell.AppSystem.get_default().disconnect(this._installChangedId);
+            this._installChangedId = 0;
+        }
+
+        if ( this._changedId != 0 ) {
+            AppFavorites.getAppFavorites().disconnect(this._changedId);
+            this._changedId = 0;
+        }
+    }
+});
+Signals.addSignalMethods(PanelFavorites.prototype);
+
+let myAddToStatusArea;
+let panelFavorites;
+
+function enable() {
+    Panel.Panel.prototype.myAddToStatusArea = myAddToStatusArea;
+
+    // place panel to left of app menu, or failing that at right end of box
+    let siblings = Main.panel._leftBox.get_children();
+    let appMenu = Main.panel.statusArea['appMenu'];
+    let pos = appMenu ? siblings.indexOf(appMenu.container) : siblings.length;
+
+    panelFavorites = new PanelFavorites();
+    Main.panel.myAddToStatusArea('panel-favorites', panelFavorites,
+                                pos, 'left');
+}
+
+function disable() {
+    delete Panel.Panel.prototype.myAddToStatusArea;
+
+    panelFavorites.actor.destroy();
+    panelFavorites.emit('destroy');
+    panelFavorites = null;
+}
+
+function init() {
+    myAddToStatusArea = function(role, indicator, position, box) {
+        if (this.statusArea[role])
+            throw new Error('Extension point conflict: there is already a status indicator for role ' + role);
+
+        position = position || 0;
+        let boxes = {
+            left: this._leftBox,
+            center: this._centerBox,
+            right: this._rightBox
+        };
+        let boxContainer = boxes[box] || this._rightBox;
+        this.statusArea[role] = indicator;
+        this._addToPanelBox(role, indicator, position, boxContainer);
+        return indicator;
+    };
+}
diff --git a/extensions/panel-favorites/metadata.json.in b/extensions/panel-favorites/metadata.json.in
new file mode 100644
index 0000000..037f281
--- /dev/null
+++ b/extensions/panel-favorites/metadata.json.in
@@ -0,0 +1,10 @@
+{
+"extension-id": "@extension_id@",
+"uuid": "@uuid@",
+"settings-schema": "@gschemaname@",
+"gettext-domain": "@gettext_domain@",
+"name": "Frippery Panel Favorites",
+"description": "Add launchers for Favorites to the panel",
+"shell-version": [ "@shell_current@" ],
+"url": "http://intgat.tigress.co.uk/rmy/extensions/index.html"
+}
diff --git a/extensions/panel-favorites/stylesheet.css b/extensions/panel-favorites/stylesheet.css
new file mode 100644
index 0000000..120adac
--- /dev/null
+++ b/extensions/panel-favorites/stylesheet.css
@@ -0,0 +1,14 @@
+.panel-favorites {
+    spacing: 6px;
+}
+
+.panel-launcher-label {
+    border-radius: 7px;
+    padding: 4px 12px;
+    background-color: rgba(0,0,0,0.9);
+    color: white;
+    text-align: center;
+    font-size: 9pt;
+    font-weight: bold;
+    -y-offset: 6px;
+}
-- 
2.7.2


From b579155a83474964f810b444df1c09f0b1c52b7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 4 Mar 2016 17:07:21 +0100
Subject: [PATCH 4/4] Add updates-dialog extension

---
 configure.ac                                       |   5 +-
 extensions/updates-dialog/Makefile.am              |   5 +
 extensions/updates-dialog/extension.js             | 490 +++++++++++++++++++++
 extensions/updates-dialog/metadata.json.in         |  10 +
 ....shell.extensions.updates-dialog.gschema.xml.in |  30 ++
 extensions/updates-dialog/stylesheet.css           |   1 +
 po/POTFILES.in                                     |   2 +
 7 files changed, 541 insertions(+), 2 deletions(-)
 create mode 100644 extensions/updates-dialog/Makefile.am
 create mode 100644 extensions/updates-dialog/extension.js
 create mode 100644 extensions/updates-dialog/metadata.json.in
 create mode 100644 extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml.in
 create mode 100644 extensions/updates-dialog/stylesheet.css

diff --git a/configure.ac b/configure.ac
index 92969e2..528a2a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_SUBST([SHELL_VERSION])
 dnl keep this in alphabetic order
 CLASSIC_EXTENSIONS="apps-menu places-menu alternate-tab launch-new-instance window-list"
 DEFAULT_EXTENSIONS="$CLASSIC_EXTENSIONS drive-menu screenshot-window-sizer windowsNavigator workspace-indicator"
-ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows dash-to-dock example native-window-placement panel-favorites systemMonitor top-icons user-theme"
+ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows dash-to-dock example native-window-placement panel-favorites systemMonitor top-icons updates-dialog user-theme"
 AC_SUBST(CLASSIC_EXTENSIONS, [$CLASSIC_EXTENSIONS])
 AC_SUBST(ALL_EXTENSIONS, [$ALL_EXTENSIONS])
 AC_ARG_ENABLE([extensions],
@@ -66,7 +66,7 @@ for e in $enable_extensions; do
 					[AC_MSG_WARN([libgtop-2.0 not found, disabling systemMonitor])])
 			;;
 dnl		keep this in alphabetic order
-		alternate-tab|apps-menu|auto-move-windows|dash-to-dock|drive-menu|example|launch-new-instance|native-window-placement|panel-favorites|places-menu|screenshot-window-sizer|top-icons|user-theme|window-list|windowsNavigator|workspace-indicator)
+		alternate-tab|apps-menu|auto-move-windows|dash-to-dock|drive-menu|example|launch-new-instance|native-window-placement|panel-favorites|places-menu|screenshot-window-sizer|top-icons|updates-dialog|user-theme|window-list|windowsNavigator|workspace-indicator)
 			ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
 			;;
 		*)
@@ -92,6 +92,7 @@ AC_CONFIG_FILES([
   extensions/screenshot-window-sizer/Makefile
   extensions/systemMonitor/Makefile
   extensions/top-icons/Makefile
+  extensions/updates-dialog/Makefile
   extensions/user-theme/Makefile
   extensions/window-list/Makefile
   extensions/windowsNavigator/Makefile
diff --git a/extensions/updates-dialog/Makefile.am b/extensions/updates-dialog/Makefile.am
new file mode 100644
index 0000000..4da9b17
--- /dev/null
+++ b/extensions/updates-dialog/Makefile.am
@@ -0,0 +1,5 @@
+EXTENSION_ID = updates-dialog
+
+include ../../extension.mk
+include ../../settings.mk
+
diff --git a/extensions/updates-dialog/extension.js b/extensions/updates-dialog/extension.js
new file mode 100644
index 0000000..2fa62a5
--- /dev/null
+++ b/extensions/updates-dialog/extension.js
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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/>.
+ */
+
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Pango = imports.gi.Pango;
+const PkgKit = imports.gi.PackageKitGlib;
+const Polkit = imports.gi.Polkit;
+const Signals = imports.signals;
+const St = imports.gi.St;
+
+const EndSessionDialog = imports.ui.endSessionDialog;
+const Main = imports.ui.main;
+const ModalDialog = imports.ui.modalDialog;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const Me = ExtensionUtils.getCurrentExtension();
+const Convenience = Me.imports.convenience;
+
+const PkIface = '<node> \
+<interface name="org.freedesktop.PackageKit"> \
+    <method name="CreateTransaction"> \
+        <arg type="o" name="object_path" direction="out"/> \
+    </method> \
+    <signal name="UpdatesChanged"/> \
+</interface> \
+</node>';
+
+const PkOfflineIface = '<node> \
+<interface name="org.freedesktop.PackageKit.Offline"> \
+    <property name="UpdatePrepared" type="b" access="read"/> \
+    <property name="TriggerAction" type="s" access="read"/> \
+    <method name="Trigger"> \
+        <arg type="s" name="action" direction="in"/> \
+    </method> \
+    <method name="Cancel"/> \
+</interface> \
+</node>';
+
+const PkTransactionIface = '<node> \
+<interface name="org.freedesktop.PackageKit.Transaction"> \
+    <method name="SetHints"> \
+        <arg type="as" name="hints" direction="in"/> \
+    </method> \
+    <method name="GetUpdates"> \
+        <arg type="t" name="filter" direction="in"/> \
+    </method> \
+    <method name="UpdatePackages"> \
+        <arg type="t" name="transaction_flags" direction="in"/> \
+        <arg type="as" name="package_ids" direction="in"/> \
+    </method> \
+    <signal name="Package"> \
+        <arg type="u" name="info" direction="out"/> \
+        <arg type="s" name="package_id" direction="out"/> \
+        <arg type="s" name="summary" direction="out"/> \
+    </signal> \
+    <signal name="Finished"> \
+        <arg type="u" name="exit" direction="out"/> \
+        <arg type="u" name="runtime" direction="out"/> \
+    </signal> \
+</interface> \
+</node>';
+
+const LoginManagerIface = '<node> \
+<interface name="org.freedesktop.login1.Manager"> \
+<method name="Reboot"> \
+    <arg type="b" direction="in"/> \
+</method> \
+<method name="CanReboot"> \
+    <arg type="s" direction="out"/> \
+</method> \
+</interface> \
+</node>';
+
+const PkProxy = Gio.DBusProxy.makeProxyWrapper(PkIface);
+const PkOfflineProxy = Gio.DBusProxy.makeProxyWrapper(PkOfflineIface);
+const PkTransactionProxy = Gio.DBusProxy.makeProxyWrapper(PkTransactionIface);
+const LoginManagerProxy = Gio.DBusProxy.makeProxyWrapper(LoginManagerIface);
+
+let pkProxy = null;
+let pkOfflineProxy = null;
+let loginManagerProxy = null;
+let updatesDialog = null;
+let extensionSettings = null;
+let cancellable = null;
+
+let updatesCheckInProgress = false;
+let updatesCheckRequested = false;
+let securityUpdates = [];
+
+function getDetailText(period) {
+    let text = _("Important security updates need to be installed.\n");
+    if (period < 60)
+        text += ngettext("You can close this dialog and get %d minute to finish your work.",
+                         "You can close this dialog and get %d minutes to finish your work.",
+                         period).format(period);
+    else
+        text += ngettext("You can close this dialog and get %d hour to finish your work.",
+                         "You can close this dialog and get %d hours to finish your work.",
+                         Math.floor(period / 60)).format(Math.floor(period / 60));
+    return text;
+}
+
+const UpdatesDialog = new Lang.Class({
+    Name: 'UpdatesDialog',
+    Extends: ModalDialog.ModalDialog,
+
+    _init: function(settings) {
+        this.parent({ styleClass: 'end-session-dialog',
+                      destroyOnClose: false });
+
+        this._gracePeriod = settings.get_uint('grace-period');
+        this._gracePeriod = Math.min(Math.max(10, this._gracePeriod), 24*60);
+        this._lastWarningPeriod = settings.get_uint('last-warning-period');
+        this._lastWarningPeriod = Math.min(Math.max(1, this._lastWarningPeriod), this._gracePeriod - 1);
+        this._lastWarnings = settings.get_uint('last-warnings');
+        this._lastWarnings = Math.min(Math.max(1, this._lastWarnings),
+                                      Math.floor((this._gracePeriod - 1) / this._lastWarningPeriod));
+
+        let messageLayout = new St.BoxLayout({ vertical: true,
+                                               style_class: 'end-session-dialog-layout' });
+        this.contentLayout.add(messageLayout,
+                               { x_fill: true,
+                                 y_fill: true,
+                                 y_expand: true });
+
+        let subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject',
+                                          style: 'padding-bottom: 1em;',
+                                          text: _("Important security updates") });
+        messageLayout.add(subjectLabel,
+                          { x_fill:  false,
+                            y_fill:  false,
+                            x_align: St.Align.START,
+                            y_align: St.Align.START });
+
+        this._detailLabel = new St.Label({ style_class: 'end-session-dialog-description',
+                                           style: 'padding-bottom: 0em;',
+                                           text: getDetailText(this._gracePeriod) });
+        this._detailLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
+        this._detailLabel.clutter_text.line_wrap = true;
+
+        messageLayout.add(this._detailLabel,
+                          { y_fill:  true,
+                            y_align: St.Align.START });
+
+        let buttons = [{ action: Lang.bind(this, this.close),
+                         label:  _("Close"),
+                         key:    Clutter.Escape },
+                       { action: Lang.bind(this, this._done),
+                         label:  _("Restart &amp; Install") }];
+
+        this.setButtons(buttons);
+
+        this._openTimeoutId = 0;
+        this.connect('destroy', Lang.bind(this, this._clearOpenTimeout));
+
+        this._startTimer();
+    },
+
+    _clearOpenTimeout: function() {
+        if (this._openTimeoutId > 0) {
+            GLib.source_remove(this._openTimeoutId);
+            this._openTimeoutId = 0;
+        }
+    },
+
+    tryOpen: function() {
+        if (this._openTimeoutId > 0 || this.open())
+            return;
+
+        this._openTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1,
+                                                       Lang.bind(this, function() {
+                                                           if (!this.open())
+                                                               return GLib.SOURCE_CONTINUE;
+
+                                                           this._clearOpenTimeout();
+                                                           return GLib.SOURCE_REMOVE;
+                                                       }));
+    },
+
+    _startTimer: function() {
+        this._secondsLeft = this._gracePeriod*60;
+
+        this._timerId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, Lang.bind(this,
+            function() {
+                this._secondsLeft -= 1;
+                let minutesLeft = this._secondsLeft / 60;
+                let periodLeft = Math.floor(minutesLeft);
+
+                if (this._secondsLeft == 60 ||
+                    (periodLeft > 0 && periodLeft <= this._lastWarningPeriod * this._lastWarnings &&
+                     minutesLeft % this._lastWarningPeriod == 0)) {
+                    this.tryOpen();
+                    this._detailLabel.text = getDetailText(periodLeft);
+                }
+
+                if (this._secondsLeft > 0) {
+                    if (this._secondsLeft < 60) {
+                        let seconds = EndSessionDialog._roundSecondsToInterval(this._gracePeriod*60, this._secondsLeft, 10);
+                        this._detailLabel.text =
+                            _("Important security updates need to be installed now.\n") +
+                            ngettext("This computer will restart in %d second.",
+                                     "This computer will restart in %d seconds.",
+                                     seconds).format(seconds);
+                    }
+                    return GLib.SOURCE_CONTINUE;
+                }
+
+                this._done();
+                return GLib.SOURCE_REMOVE;
+            }));
+        this.connect('destroy', Lang.bind(this, function() {
+            if (this._timerId > 0) {
+                GLib.source_remove(this._timerId);
+                this._timerId = 0;
+            }
+        }));
+    },
+
+    _done: function() {
+        this.emit('done');
+        this.destroy();
+    },
+
+    getState: function() {
+        return [this._gracePeriod, this._lastWarningPeriod, this._lastWarnings, this._secondsLeft];
+    },
+
+    setState: function(state) {
+        [this._gracePeriod, this._lastWarningPeriod, this._lastWarnings, this._secondsLeft] = state;
+    },
+});
+Signals.addSignalMethods(UpdatesDialog.prototype);
+
+function showDialog() {
+    if (updatesDialog)
+        return;
+
+    updatesDialog = new UpdatesDialog(extensionSettings);
+    updatesDialog.tryOpen();
+    updatesDialog.connect('destroy', function() { updatesDialog = null; });
+    updatesDialog.connect('done', function() {
+        if (pkOfflineProxy.TriggerAction == 'power-off' ||
+            pkOfflineProxy.TriggerAction == 'reboot') {
+            loginManagerProxy.RebootRemote(false);
+        } else {
+            pkOfflineProxy.TriggerRemote('reboot', function(result, error) {
+                if (!error)
+                    loginManagerProxy.RebootRemote(false);
+                else
+                    log('Failed to trigger offline update: %s'.format(error.message));
+            });
+        }
+    });
+}
+
+function cancelDialog(save) {
+    if (!updatesDialog)
+        return;
+
+    if (save) {
+        let state = GLib.Variant.new('(uuuu)', updatesDialog.getState());
+        global.set_runtime_state(Me.uuid, state);
+    }
+    updatesDialog.destroy();
+}
+
+function restoreExistingState() {
+    let state = global.get_runtime_state('(uuuu)', Me.uuid);
+    if (state === null)
+        return false;
+
+    global.set_runtime_state(Me.uuid, null);
+    showDialog();
+    updatesDialog.setState(state.deep_unpack());
+    return true;
+}
+
+function syncState() {
+    if (!pkOfflineProxy || !loginManagerProxy)
+        return;
+
+    if (restoreExistingState())
+        return;
+
+    if (!updatesCheckInProgress &&
+        securityUpdates.length > 0 &&
+        pkOfflineProxy.UpdatePrepared)
+        showDialog();
+    else
+        cancelDialog();
+}
+
+function doPkTransaction(callback) {
+    if (!pkProxy)
+        return;
+
+    pkProxy.CreateTransactionRemote(function(result, error) {
+        if (error) {
+            log('Error creating PackageKit transaction: %s'.format(error.message));
+            checkUpdatesDone();
+            return;
+        }
+
+        new PkTransactionProxy(Gio.DBus.system,
+                               'org.freedesktop.PackageKit',
+                               String(result),
+                               function(proxy, error) {
+                                   if (!error) {
+                                       proxy.SetHintsRemote(
+                                           ['background=true', 'interactive=false'],
+                                           function(result, error) {
+                                               if (error) {
+                                                   log('Error connecting to PackageKit: %s'.format(error.message));
+                                                   checkUpdatesDone();
+                                                   return;
+                                               }
+                                               callback(proxy);
+                                           });
+                                   } else {
+                                       log('Error connecting to PackageKit: %s'.format(error.message));
+                                   }
+                               });
+    });
+}
+
+function pkUpdatePackages(proxy) {
+    proxy.connectSignal('Finished', function(p, e, params) {
+        let [exit, runtime] = params;
+
+        if (exit == PkgKit.ExitEnum.CANCELLED_PRIORITY) {
+            // try again
+            checkUpdates();
+        } else if (exit != PkgKit.ExitEnum.SUCCESS) {
+            log('UpdatePackages failed: %s'.format(PkgKit.ExitEnum.to_string(exit)));
+        }
+
+        checkUpdatesDone();
+    });
+    proxy.UpdatePackagesRemote(1 << PkgKit.TransactionFlagEnum.ONLY_DOWNLOAD, securityUpdates);
+}
+
+function pkGetUpdates(proxy) {
+    proxy.connectSignal('Package', function(p, e, params) {
+        let [info, packageId, summary] = params;
+
+        if (info == PkgKit.InfoEnum.SECURITY)
+            securityUpdates.push(packageId);
+    });
+    proxy.connectSignal('Finished', function(p, e, params) {
+        let [exit, runtime] = params;
+
+        if (exit == PkgKit.ExitEnum.SUCCESS) {
+            if (securityUpdates.length > 0) {
+                doPkTransaction(pkUpdatePackages);
+                return;
+            }
+        } else if (exit == PkgKit.ExitEnum.CANCELLED_PRIORITY) {
+            // try again
+            checkUpdates();
+        } else {
+            log('GetUpdates failed: %s'.format(PkgKit.ExitEnum.to_string(exit)));
+        }
+
+        checkUpdatesDone();
+    });
+    proxy.GetUpdatesRemote(0);
+}
+
+function checkUpdatesDone() {
+    updatesCheckInProgress = false;
+    if (updatesCheckRequested) {
+        updatesCheckRequested = false;
+        checkUpdates();
+    } else {
+        syncState();
+    }
+}
+
+function checkUpdates() {
+    if (updatesCheckInProgress) {
+        updatesCheckRequested = true;
+        return;
+    }
+    updatesCheckInProgress = true;
+    securityUpdates = [];
+    doPkTransaction(pkGetUpdates);
+}
+
+function initSystemProxies() {
+    new PkProxy(Gio.DBus.system,
+                'org.freedesktop.PackageKit',
+                '/org/freedesktop/PackageKit',
+                function(proxy, error) {
+                    if (!error) {
+                        pkProxy = proxy;
+                        let id = pkProxy.connectSignal('UpdatesChanged', checkUpdates);
+                        pkProxy._signalId = id;
+                        checkUpdates();
+                    } else {
+                        log('Error connecting to PackageKit: %s'.format(error.message));
+                    }
+                },
+                cancellable);
+    new PkOfflineProxy(Gio.DBus.system,
+                       'org.freedesktop.PackageKit',
+                       '/org/freedesktop/PackageKit',
+                       function(proxy, error) {
+                           if (!error) {
+                               pkOfflineProxy = proxy;
+                               let id = pkOfflineProxy.connect('g-properties-changed', syncState);
+                               pkOfflineProxy._signalId = id;
+                               syncState();
+                           } else {
+                               log('Error connecting to PackageKit: %s'.format(error.message));
+                           }
+                       },
+                       cancellable);
+    new LoginManagerProxy(Gio.DBus.system,
+                          'org.freedesktop.login1',
+                          '/org/freedesktop/login1',
+                          function(proxy, error) {
+                              if (!error) {
+                                  proxy.CanRebootRemote(cancellable, function(result, error) {
+                                      if (!error && result == 'yes') {
+                                          loginManagerProxy = proxy;
+                                          syncState();
+                                      } else {
+                                          log('Reboot is not available');
+                                      }
+                                  });
+                              } else {
+                                  log('Error connecting to Login manager: %s'.format(error.message));
+                              }
+                          },
+                          cancellable);
+}
+
+function init(metadata) {
+}
+
+function enable() {
+    cancellable = new Gio.Cancellable();
+    extensionSettings = Convenience.getSettings();
+    Polkit.Permission.new("org.freedesktop.packagekit.trigger-offline-update",
+                          null, cancellable, function(p, result) {
+                              try {
+                                  let permission = Polkit.Permission.new_finish(result);
+                                  if (permission && permission.allowed)
+                                      initSystemProxies();
+                                  else
+                                      throw(new Error('not allowed'));
+                              } catch(e) {
+                                  log('No permission to trigger offline updates: %s'.format(e.toString()));
+                              }
+                          });
+}
+
+function disable() {
+    cancelDialog(true);
+    cancellable.cancel();
+    cancellable = null;
+    extensionSettings = null;
+    updatesDialog = null;
+    loginManagerProxy = null;
+    if (pkOfflineProxy) {
+        pkOfflineProxy.disconnect(pkOfflineProxy._signalId);
+        pkOfflineProxy = null;
+    }
+    if (pkProxy) {
+        pkProxy.disconnectSignal(pkProxy._signalId);
+        pkProxy = null;
+    }
+}
diff --git a/extensions/updates-dialog/metadata.json.in b/extensions/updates-dialog/metadata.json.in
new file mode 100644
index 0000000..9946abb
--- /dev/null
+++ b/extensions/updates-dialog/metadata.json.in
@@ -0,0 +1,10 @@
+{
+"extension-id": "@extension_id@",
+"uuid": "@uuid@",
+"settings-schema": "@gschemaname@",
+"gettext-domain": "@gettext_domain@",
+"name": "Updates Dialog",
+"description": "Shows a modal dialog when there are software updates.",
+"shell-version": [ "@shell_current@" ],
+"url": "http://rtcm.fedorapeople.org/updates-dialog"
+}
diff --git a/extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml.in b/extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml.in
new file mode 100644
index 0000000..a4a7f8b
--- /dev/null
+++ b/extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml.in
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+  <schema path="/org/gnome/shell/extensions/updates-dialog/"
+          id="org.gnome.shell.extensions.updates-dialog">
+    <key name="grace-period" type="u">
+      <default>300</default>
+      <summary>Grace period in minutes</summary>
+      <description>
+        When the grace period is over, the computer will automatically
+        reboot and install security updates.
+      </description>
+    </key>
+    <key name="last-warning-period" type="u">
+      <default>10</default>
+      <summary>Last warning dialog period</summary>
+      <description>
+        A last warning dialog is displayed this many minutes before
+        the automatic reboot.
+      </description>
+    </key>
+    <key name="last-warnings" type="u">
+      <default>1</default>
+      <summary>Number of last warning dialogs</summary>
+      <description>
+        How many warning dialogs are displayed. Each is displayed at
+        'last-warning-period' minute intervals.
+      </description>
+    </key>
+  </schema>
+</schemalist>
diff --git a/extensions/updates-dialog/stylesheet.css b/extensions/updates-dialog/stylesheet.css
new file mode 100644
index 0000000..25134b6
--- /dev/null
+++ b/extensions/updates-dialog/stylesheet.css
@@ -0,0 +1 @@
+/* This extensions requires no special styling */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 89bd3ee..b229b6a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -16,6 +16,8 @@ extensions/native-window-placement/org.gnome.shell.extensions.native-window-plac
 extensions/places-menu/extension.js
 extensions/places-menu/placeDisplay.js
 extensions/systemMonitor/extension.js
+extensions/updates-dialog/extension.js
+extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml.in
 extensions/user-theme/extension.js
 extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml.in
 extensions/window-list/extension.js
-- 
2.7.2