summaryrefslogtreecommitdiff
path: root/plugins
diff options
authorAndrea Azzarone <azzaronea@gmail.com>2012-09-06 13:01:43 +0200
committerAndrea Azzarone <azzaronea@gmail.com>2012-09-06 13:01:43 +0200
commitf8dc9c803cece59aaae1e140a4b3abf8743f681a (patch)
treefdfda430fbfef22c25fedd7cbce5255ae608c733 /plugins
parent26217b9f7f13db800d0a08d5c5512153c13110fa (diff)
parent1cdca055ffddf2e105015f9f03842a047b002f93 (diff)
Merge trunk.
(bzr r2509.3.2)
Diffstat (limited to 'plugins')
-rw-r--r--plugins/networkarearegion/src/networkarearegion.cpp1
-rw-r--r--plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp2
-rw-r--r--plugins/unitydialog/src/unitydialog.cpp7
-rw-r--r--plugins/unityshell/CMakeLists.txt5
-rw-r--r--plugins/unityshell/resources/preview_next.svg17
-rw-r--r--plugins/unityshell/resources/preview_pause.svg8
-rw-r--r--plugins/unityshell/resources/preview_play.svg9
-rw-r--r--plugins/unityshell/resources/preview_previous.svg28
-rw-r--r--plugins/unityshell/src/CompoundGestureRecognizer.cpp250
-rw-r--r--plugins/unityshell/src/CompoundGestureRecognizer.h71
-rw-r--r--plugins/unityshell/src/GesturalWindowSwitcher.cpp446
-rw-r--r--plugins/unityshell/src/GesturalWindowSwitcher.h85
-rw-r--r--plugins/unityshell/src/GestureEngine.cpp280
-rw-r--r--plugins/unityshell/src/GestureEngine.h68
-rw-r--r--plugins/unityshell/src/ScreenEffectFramebufferObject.cpp4
-rw-r--r--plugins/unityshell/src/UnityGestureBroker.cpp133
-rw-r--r--plugins/unityshell/src/UnityGestureBroker.h52
-rw-r--r--plugins/unityshell/src/UnityGestureTarget.cpp55
-rw-r--r--plugins/unityshell/src/UnityGestureTarget.h44
-rw-r--r--plugins/unityshell/src/WindowGestureTarget.cpp215
-rw-r--r--plugins/unityshell/src/WindowGestureTarget.h57
-rw-r--r--plugins/unityshell/src/WindowMinimizeSpeedController.cpp108
-rw-r--r--plugins/unityshell/src/WindowMinimizeSpeedController.h57
-rw-r--r--plugins/unityshell/src/nux-area-accessible.cpp38
-rw-r--r--plugins/unityshell/src/nux-area-accessible.h4
-rw-r--r--plugins/unityshell/src/nux-base-window-accessible.cpp10
-rw-r--r--plugins/unityshell/src/nux-layout-accessible.cpp4
-rw-r--r--plugins/unityshell/src/nux-object-accessible.cpp8
-rw-r--r--plugins/unityshell/src/nux-view-accessible.cpp6
-rw-r--r--plugins/unityshell/src/unity-launcher-accessible.cpp2
-rw-r--r--plugins/unityshell/src/unity-launcher-icon-accessible.cpp2
-rw-r--r--plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp2
-rw-r--r--plugins/unityshell/src/unity-root-accessible.cpp2
-rw-r--r--plugins/unityshell/src/unity-rvgrid-accessible.cpp7
-rw-r--r--plugins/unityshell/src/unity-switcher-accessible.cpp2
-rw-r--r--plugins/unityshell/src/unitya11y.cpp27
-rw-r--r--plugins/unityshell/src/unitya11ytests.cpp4
-rw-r--r--plugins/unityshell/src/unityshell.cpp947
-rw-r--r--plugins/unityshell/src/unityshell.h78
-rw-r--r--plugins/unityshell/unityshell.xml.in39
40 files changed, 2628 insertions, 556 deletions
diff --git a/plugins/networkarearegion/src/networkarearegion.cpp b/plugins/networkarearegion/src/networkarearegion.cpp
index 896f96289..d0203e701 100644
--- a/plugins/networkarearegion/src/networkarearegion.cpp
+++ b/plugins/networkarearegion/src/networkarearegion.cpp
@@ -64,6 +64,7 @@ void
UnityNETWorkareaRegionScreen::outputChangeNotify()
{
setProperty();
+ screen->outputChangeNotify ();
}
void
diff --git a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp
index 74bd70d7c..ad840204c 100644
--- a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp
+++ b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp
@@ -292,7 +292,7 @@ UnityMTGrabHandlesScreen::handleEvent(XEvent* event)
CompWindowVector::const_iterator cit = clientListStacking.begin();
CompWindowVector::const_iterator oit = mLastClientListStacking.begin();
- for (; cit != clientListStacking.end(); cit++, oit++)
+ for (; cit != clientListStacking.end(); ++cit, oit++)
{
/* All clients from this point onwards in cit are invalidated
* so splice the list to the end of the new client list
diff --git a/plugins/unitydialog/src/unitydialog.cpp b/plugins/unitydialog/src/unitydialog.cpp
index 05b51ddc6..91f7f235e 100644
--- a/plugins/unitydialog/src/unitydialog.cpp
+++ b/plugins/unitydialog/src/unitydialog.cpp
@@ -367,7 +367,7 @@ UnityDialogScreen::donePaint()
continue;
}
- it++;
+ ++it;
}
}
@@ -1383,7 +1383,6 @@ UnityDialogWindow::place(CompPoint& pos)
CompWindow::Geometry transientGeometry;
CompRegion transientPos, outputRegion, outsideArea, outsideRegion;
pos = getChildCenteredPositionForRect(mParent->serverBorderRect());
- int hdirection, vdirection;
transientGeometry = CompWindow::Geometry(pos.x(),
pos.y(),
@@ -1406,8 +1405,8 @@ UnityDialogWindow::place(CompPoint& pos)
int width;
int height;
- hdirection = outsideArea.boundingRect().x() < 0 ? 1 : -1;
- vdirection = outsideArea.boundingRect().y() < 0 ? 1 : -1;
+ int hdirection = outsideArea.boundingRect().x() < 0 ? 1 : -1;
+ int vdirection = outsideArea.boundingRect().y() < 0 ? 1 : -1;
width = outsideArea.boundingRect().width() >=
window->serverBorderRect().width() ? 0 :
diff --git a/plugins/unityshell/CMakeLists.txt b/plugins/unityshell/CMakeLists.txt
index 2e11fb453..c6ad6f75d 100644
--- a/plugins/unityshell/CMakeLists.txt
+++ b/plugins/unityshell/CMakeLists.txt
@@ -6,12 +6,15 @@ set (COMPIZ_PLUGIN_INSTALL_TYPE "package")
compiz_plugin (unityshell
PKGDEPS ${UNITY_PLUGIN_DEPS}
- PLUGINDEPS composite opengl compiztoolbox
+ PLUGINDEPS composite opengl compiztoolbox scale
CFLAGSADD "-DINSTALLPREFIX='\"${CMAKE_INSTALL_PREFIX}\"' -DPKGDATADIR='\"${PKGDATADIR}\"' -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR} ${BOOT_LOGGER_FLAG} -DGETTEXT_PACKAGE='\"unity\"' ${MAINTAINER_CFLAGS} -I${CMAKE_SOURCE_DIR}/dash/ -I${CMAKE_SOURCE_DIR}/launcher/ -I${CMAKE_SOURCE_DIR}/hud/ -I${CMAKE_SOURCE_DIR}/panel/ -I${CMAKE_SOURCE_DIR}/shortcuts/ -I${CMAKE_SOURCE_DIR}/unity-shared/"
LIBDIRS "${CMAKE_BINARY_DIR}/UnityCore"
)
add_dependencies(unityshell unity-core-${UNITY_API_VERSION} dash-lib launcher-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-compiz)
target_link_libraries(unityshell unity-core-${UNITY_API_VERSION} launcher-lib dash-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-compiz)
+set_target_properties(unityshell
+ PROPERTIES INSTALL_RPATH "${CACHED_UNITY_PRIVATE_DEPS_LIBRARY_DIRS}"
+ INSTALL_RPATH_USE_LINK_PATH TRUE)
#
# Data
diff --git a/plugins/unityshell/resources/preview_next.svg b/plugins/unityshell/resources/preview_next.svg
new file mode 100644
index 000000000..75565f866
--- /dev/null
+++ b/plugins/unityshell/resources/preview_next.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="14px" height="21px" viewBox="0 0 14 21" enable-background="new 0 0 14 21" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#FFFFFF" d="M13.998,10.5c0.001,0.001,0.001,0.002,0.002,0.002V10.5C13.999,10.5,13.999,10.5,13.998,10.5z M8.139,5.49
+ C7.364,4.623,6.623,3.718,5.913,2.774S4.576,0.905,4.034,0H0c0.543,0.905,1.208,1.882,1.995,2.929
+ c0.787,1.048,1.622,2.082,2.502,3.104C5.38,7.055,6.275,8.005,7.185,8.885C7.812,9.493,8.417,10.028,9,10.5
+ c-0.583,0.473-1.188,1.009-1.815,1.616c-0.909,0.88-1.805,1.83-2.688,2.852c-0.88,1.022-1.715,2.057-2.502,3.104
+ C1.208,19.12,0.543,20.095,0,21h4.034c0.542-0.905,1.168-1.829,1.878-2.773s1.451-1.85,2.226-2.717
+ c0.775-0.866,1.562-1.661,2.361-2.385c0.688-0.621,2.531-1.949,3.498-2.625c-0.967-0.675-2.81-2.002-3.498-2.624
+ C9.701,7.152,8.914,6.357,8.139,5.49z"/>
+ </g>
+</g>
+</svg>
diff --git a/plugins/unityshell/resources/preview_pause.svg b/plugins/unityshell/resources/preview_pause.svg
new file mode 100644
index 000000000..dade7bb60
--- /dev/null
+++ b/plugins/unityshell/resources/preview_pause.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="7px" height="9px" viewBox="0 0 7 9" enable-background="new 0 0 7 9" xml:space="preserve">
+<rect fill="#FFFFFF" width="2" height="9"/>
+<rect x="5" fill="#FFFFFF" width="2" height="9"/>
+</svg>
diff --git a/plugins/unityshell/resources/preview_play.svg b/plugins/unityshell/resources/preview_play.svg
new file mode 100644
index 000000000..e1d61bf70
--- /dev/null
+++ b/plugins/unityshell/resources/preview_play.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="5px" height="7px" viewBox="0 0 5 7" enable-background="new 0 0 5 7" xml:space="preserve">
+<path fill="#FFFFFF" d="M0,7c0.343-0.184,0.725-0.41,1.145-0.677c0.421-0.268,0.853-0.562,1.296-0.878
+ c0.445-0.318,0.885-0.645,1.322-0.979C4.197,4.132,4.61,3.805,5,3.487C4.61,3.169,4.193,2.843,3.751,2.509
+ C3.307,2.174,2.862,1.852,2.418,1.542C1.975,1.233,1.542,0.945,1.122,0.677C0.701,0.409,0.328,0.184,0,0V7z"/>
+</svg>
diff --git a/plugins/unityshell/resources/preview_previous.svg b/plugins/unityshell/resources/preview_previous.svg
new file mode 100644
index 000000000..70cca99e0
--- /dev/null
+++ b/plugins/unityshell/resources/preview_previous.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="14px" height="21px" viewBox="0 0 14 21" enable-background="new 0 0 14 21" xml:space="preserve">
+<g>
+ <g>
+ <path fill="#FFFFFF" d="M633,400.501c0.001,0,0.001-0.001,0.002-0.001c-0.001,0-0.001-0.001-0.002-0.001V400.501z
+ M642.503,404.967c-0.883-1.021-1.778-1.972-2.687-2.852c-0.629-0.607-1.233-1.143-1.816-1.615
+ c0.583-0.473,1.188-1.008,1.816-1.615c0.908-0.88,1.804-1.83,2.687-2.852c0.882-1.022,1.716-2.057,2.503-3.104
+ c0.786-1.049,1.451-2.025,1.994-2.93h-4.034c-0.542,0.904-1.168,1.829-1.878,2.773c-0.711,0.944-1.452,1.85-2.227,2.717
+ c-0.775,0.866-1.562,1.661-2.362,2.386c-0.687,0.622-2.53,1.948-3.497,2.624c0.967,0.676,2.811,2.002,3.497,2.624
+ c0.8,0.724,1.587,1.52,2.362,2.387c0.774,0.866,1.516,1.771,2.227,2.716c0.71,0.943,1.336,1.868,1.878,2.773H647
+ c-0.543-0.905-1.208-1.882-1.994-2.929C644.219,407.023,643.385,405.989,642.503,404.967z"/>
+ </g>
+</g>
+<g>
+ <g>
+ <path fill="#FFFFFF" d="M0,10.501c0.001,0,0.001-0.001,0.002-0.001c-0.001,0-0.001-0.001-0.002-0.001V10.501z M9.503,14.967
+ c-0.883-1.021-1.778-1.972-2.687-2.852C6.188,11.508,5.583,10.973,5,10.5c0.583-0.473,1.188-1.008,1.816-1.615
+ c0.909-0.88,1.804-1.83,2.687-2.852c0.882-1.022,1.716-2.056,2.503-3.104C12.792,1.881,13.457,0.905,14,0H9.966
+ c-0.542,0.905-1.168,1.83-1.878,2.774C7.377,3.718,6.636,4.623,5.861,5.49C5.086,6.356,4.299,7.151,3.499,7.876
+ C2.812,8.498,0.969,9.824,0.002,10.5c0.967,0.676,2.81,2.002,3.497,2.624c0.8,0.724,1.587,1.52,2.362,2.387
+ c0.774,0.866,1.516,1.771,2.227,2.716C8.798,19.17,9.424,20.095,9.966,21H14c-0.543-0.905-1.208-1.882-1.994-2.929
+ C11.219,17.023,10.385,15.989,9.503,14.967z"/>
+ </g>
+</g>
+</svg>
diff --git a/plugins/unityshell/src/CompoundGestureRecognizer.cpp b/plugins/unityshell/src/CompoundGestureRecognizer.cpp
new file mode 100644
index 000000000..bbbbc88cc
--- /dev/null
+++ b/plugins/unityshell/src/CompoundGestureRecognizer.cpp
@@ -0,0 +1,250 @@
+/*
+ * CompoundGestureRecognizer.cpp
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
+ */
+
+#include "CompoundGestureRecognizer.h"
+#include <NuxCore/Logger.h>
+#include <NuxGraphics/GestureEvent.h>
+
+namespace
+{
+ nux::logging::Logger logger("unity.compound_gesture_recognizer");
+}
+
+namespace unity
+{
+ class CompoundGestureRecognizerPrivate
+ {
+ public:
+ CompoundGestureRecognizerPrivate();
+
+ enum class State
+ {
+ WaitingFirstTapBegin,
+ WaitingFirstTapEnd,
+ WaitingSecondGestureBegin,
+ RecognizingSecondGesture
+ };
+
+ RecognitionResult GestureEvent(nux::GestureEvent const& event);
+
+ RecognitionResult WaitingFirstTapBegin(nux::GestureEvent const& event);
+ RecognitionResult WaitingFirstTapEnd(nux::GestureEvent const& event);
+ RecognitionResult WaitingSecondGestureBegin(nux::GestureEvent const& event);
+ RecognitionResult RecognizingSecondGesture(nux::GestureEvent const& event);
+ void ResetStateMachine();
+
+ State state;
+
+ class GestureInfo
+ {
+ public:
+ GestureInfo() {Clear();}
+ int begin_time;
+ int end_time;
+ int id;
+ int Duration() const {return end_time - begin_time;}
+ void Clear() {begin_time = end_time = id = -1;}
+ };
+ GestureInfo first_gesture;
+ GestureInfo second_gesture;
+ };
+}
+
+using namespace unity;
+
+///////////////////////////////////////////
+// private class
+
+CompoundGestureRecognizerPrivate::CompoundGestureRecognizerPrivate()
+ : state(State::WaitingFirstTapBegin)
+{
+}
+
+RecognitionResult CompoundGestureRecognizerPrivate::GestureEvent(nux::GestureEvent const& event)
+{
+ switch (state)
+ {
+ case State::WaitingFirstTapBegin:
+ return WaitingFirstTapBegin(event);
+ break;
+ case State::WaitingFirstTapEnd:
+ return WaitingFirstTapEnd(event);
+ break;
+ case State::WaitingSecondGestureBegin:
+ return WaitingSecondGestureBegin(event);
+ break;
+ default: // State::RecognizingSecondGesture:
+ return RecognizingSecondGesture(event);
+ }
+}
+
+RecognitionResult CompoundGestureRecognizerPrivate::WaitingFirstTapBegin(nux::GestureEvent const& event)
+{
+ if (event.type == nux::EVENT_GESTURE_BEGIN)
+ {
+ first_gesture.id = event.GetGestureId();
+ first_gesture.begin_time = event.GetTimestamp();
+ state = State::WaitingFirstTapEnd;
+ }
+ return RecognitionResult::NONE;
+}
+
+RecognitionResult CompoundGestureRecognizerPrivate::WaitingFirstTapEnd(nux::GestureEvent const& event)
+{
+ if (event.type != nux::EVENT_GESTURE_END)
+ return RecognitionResult::NONE;
+
+ if (first_gesture.id != event.GetGestureId())
+ {
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ if (event.GetGestureClasses() != nux::TOUCH_GESTURE)
+ {
+ // some other gesture class such as drag or pinch was also recognized,
+ // meaning that the touch points moved too much and therefore it cannot
+ // be a tap.
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ first_gesture.end_time = event.GetTimestamp();
+ if (first_gesture.Duration() > CompoundGestureRecognizer::MAX_TAP_TIME)
+ {
+ // can't be a tap. it took too long
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ state = State::WaitingSecondGestureBegin;
+
+ return RecognitionResult::NONE;
+}
+
+RecognitionResult CompoundGestureRecognizerPrivate::WaitingSecondGestureBegin(
+ nux::GestureEvent const& event)
+{
+
+ if (event.type != nux::EVENT_GESTURE_BEGIN)
+ {
+ // that's not right. there shouldn't be any ongoing gesture now.
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ if (event.GetGestureClasses() != nux::TOUCH_GESTURE)
+ {
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ int interval = event.GetTimestamp() - first_gesture.end_time;
+ if (interval > CompoundGestureRecognizer::MAX_TIME_BETWEEN_GESTURES)
+ {
+ ResetStateMachine();
+ // consider it as the possible first tap of a new compound gesture
+ GestureEvent(event);
+ return RecognitionResult::NONE;
+ }
+
+ second_gesture.id = event.GetGestureId();
+ second_gesture.begin_time = event.GetTimestamp();
+
+ state = State::RecognizingSecondGesture;
+
+ return RecognitionResult::NONE;
+}
+
+RecognitionResult CompoundGestureRecognizerPrivate::RecognizingSecondGesture(
+ nux::GestureEvent const& event)
+{
+ if (event.GetGestureId() != second_gesture.id)
+ {
+ // no simultaneous gestures
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ if (event.GetGestureClasses() != nux::TOUCH_GESTURE)
+ {
+ // some other gesture class such as drag or pinch was also recognized,
+ // meaning that the touch points moved too much and therefore it cannot
+ // be a tap or a hold
+ ResetStateMachine();
+ return RecognitionResult::NONE;
+ }
+
+ RecognitionResult result = RecognitionResult::NONE;
+
+ if (event.type == nux::EVENT_GESTURE_UPDATE)
+ {
+ if (event.GetTimestamp() - second_gesture.begin_time >= CompoundGestureRecognizer::HOLD_TIME)
+ {
+ result = RecognitionResult::TAP_AND_HOLD_RECOGNIZED;
+ ResetStateMachine();
+ }
+ }
+ else if (event.type == nux::EVENT_GESTURE_END)
+ {
+ second_gesture.end_time = event.GetTimestamp();
+
+ if (second_gesture.Duration() <= CompoundGestureRecognizer::MAX_TAP_TIME)
+ {
+ result = RecognitionResult::DOUBLE_TAP_RECOGNIZED;
+ }
+ ResetStateMachine();
+ }
+ else
+ {
+ // This really shouldn't happen.
+ LOG_ERROR(logger) << "Unexpected gesture type."
+ " CompoundGestureRecognizer left in an undefined state.";
+ }
+
+ return result;
+}
+
+void CompoundGestureRecognizerPrivate::ResetStateMachine()
+{
+ first_gesture.Clear();
+ second_gesture.Clear();
+ state = State::WaitingFirstTapBegin;
+}
+
+///////////////////////////////////////////
+// public class
+
+CompoundGestureRecognizer::CompoundGestureRecognizer()
+ : p(new CompoundGestureRecognizerPrivate)
+{
+}
+
+CompoundGestureRecognizer::~CompoundGestureRecognizer()
+{
+ delete p;
+}
+
+RecognitionResult CompoundGestureRecognizer::GestureEvent(nux::GestureEvent const& event)
+{
+ return p->GestureEvent(event);
+}
diff --git a/plugins/unityshell/src/CompoundGestureRecognizer.h b/plugins/unityshell/src/CompoundGestureRecognizer.h
new file mode 100644
index 000000000..bf6e64dfc
--- /dev/null
+++ b/plugins/unityshell/src/CompoundGestureRecognizer.h
@@ -0,0 +1,71 @@
+/*
+ * CompoundGestureRecognizer.h
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
+ */
+
+#ifndef COMPOUND_GESTURE_RECOGNIZER_H
+#define COMPOUND_GESTURE_RECOGNIZER_H
+
+#include <sigc++/sigc++.h>
+
+namespace nux
+{
+ class GestureEvent;
+}
+
+namespace unity
+{
+
+enum class RecognitionResult
+{
+ NONE,
+ DOUBLE_TAP_RECOGNIZED, /*! Returned when a double-tap is recognized */
+ TAP_AND_HOLD_RECOGNIZED, /*!< Returned when a "tap and hold" is recognized
+ At this point the user is still "holding". I.e.,
+ his fingers are still on the touchscreen or
+ trackpad. */
+};
+
+class CompoundGestureRecognizerPrivate;
+
+/*!
+ Recognizes compound gestures. I.e. high level gestures that are maded up by
+ two sequencial regular gestures (like a tap followed by a second tap).
+ */
+class CompoundGestureRecognizer
+{
+ public:
+ // in milliseconds
+ static const int MAX_TIME_BETWEEN_GESTURES = 600;
+ static const int MAX_TAP_TIME = 300;
+ static const int HOLD_TIME = 600;
+
+ CompoundGestureRecognizer();
+ virtual ~CompoundGestureRecognizer();
+
+ virtual RecognitionResult GestureEvent(nux::GestureEvent const& event);
+
+ private:
+ CompoundGestureRecognizerPrivate* p;
+};
+
+} // namespace unity
+
+#endif // COMPOUND_GESTURE_RECOGNIZER_H
diff --git a/plugins/unityshell/src/GesturalWindowSwitcher.cpp b/plugins/unityshell/src/GesturalWindowSwitcher.cpp
new file mode 100644
index 000000000..910762139
--- /dev/null
+++ b/plugins/unityshell/src/GesturalWindowSwitcher.cpp
@@ -0,0 +1,446 @@
+/*
+ * GesturalWindowSwitcher.cpp
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
+ */
+
+#include "GesturalWindowSwitcher.h"
+#include <Nux/Nux.h>
+#include <NuxCore/Logger.h>
+#include "unityshell.h"
+
+namespace
+{
+ nux::logging::Logger logger("unity.gestural_window_switcher");
+}
+
+using namespace nux;
+using namespace unity;
+
+const float GesturalWindowSwitcher::DRAG_DELTA_FOR_CHANGING_SELECTION = 100.0f;
+const float GesturalWindowSwitcher::MOUSE_DRAG_THRESHOLD = 20.0f;
+
+namespace unity
+{
+ class GesturalWindowSwitcherPrivate
+ {
+ public:
+ GesturalWindowSwitcherPrivate();
+ virtual ~GesturalWindowSwitcherPrivate();
+
+ void CloseSwitcherAfterTimeout(int timeout);
+ bool OnCloseSwitcherTimeout();
+ void CloseSwitcher();
+
+ // show the switcher and select the next application/window
+ void InitiateSwitcherNext();
+
+ // show the switcher and select the previous application/window
+ void InitiateSwitcherPrevious();
+
+ void ProcessAccumulatedHorizontalDrag();
+
+ nux::GestureDeliveryRequest GestureEvent(nux::GestureEvent const& event);
+
+ nux::GestureDeliveryRequest WaitingCompoundGesture(nux::GestureEvent const& event);
+ nux::GestureDeliveryRequest WaitingEndOfTapAndHold(nux::GestureEvent const& event);
+ nux::GestureDeliveryRequest WaitingSwitcherManipulation(nux::GestureEvent const& event);
+ nux::GestureDeliveryRequest DraggingSwitcher(nux::GestureEvent const& event);
+ nux::GestureDeliveryRequest RecognizingMouseClickOrDrag(nux::GestureEvent const& event);
+ nux::GestureDeliveryRequest DraggingSwitcherWithMouse(nux::GestureEvent const& event);
+
+ void ProcessSwitcherViewMouseDown(int x, int y,
+ unsigned long button_flags, unsigned long key_flags);
+ void ProcessSwitcherViewMouseUp(int x, int y,
+ unsigned long button_flags, unsigned long key_flags);
+ void ProcessSwitcherViewMouseDrag(int x, int y, int dx, int dy,
+ unsigned long button_flags, unsigned long key_flags);
+
+ void ConnectToSwitcherViewMouseEvents();
+
+ enum class State
+ {
+ WaitingCompoundGesture,
+ WaitingEndOfTapAndHold,
+ WaitingSwitcherManipulation,
+ DraggingSwitcher,
+ RecognizingMouseClickOrDrag,
+ DraggingSwitcherWithMouse,
+ WaitingMandatorySwitcherClose,
+ } state;
+
+ unity::UnityScreen* unity_screen;
+ unity::switcher::Controller::Ptr switcher_controller;
+ CompoundGestureRecognizer gesture_recognizer;
+ CompTimer timer_close_switcher;
+ float accumulated_horizontal_drag;
+ int index_icon_hit;
+
+ sigc::connection view_built_connection;
+ sigc::connection mouse_down_connection;
+ sigc::connection mouse_up_connection;
+ sigc::connection mouse_drag_connection;
+ };
+}
+
+///////////////////////////////////////////
+// private class
+
+GesturalWindowSwitcherPrivate::GesturalWindowSwitcherPrivate()
+{
+ state = State::WaitingCompoundGesture;
+
+ unity_screen = unity::UnityScreen::get(screen);
+ switcher_controller = unity_screen->switcher_controller();
+
+ timer_close_switcher.setCallback(
+ boost::bind(&GesturalWindowSwitcherPrivate::OnCloseSwitcherTimeout, this));
+
+ view_built_connection = switcher_controller->view_built.connect(
+ sigc::mem_fun(this, &GesturalWindowSwitcherPrivate::ConnectToSwitcherViewMouseEvents));
+}
+
+GesturalWindowSwitcherPrivate::~GesturalWindowSwitcherPrivate()
+{
+ view_built_connection.disconnect();
+ mouse_down_connection.disconnect();
+ mouse_up_connection.disconnect();
+ mouse_drag_connection.disconnect();
+}
+
+GestureDeliveryRequest GesturalWindowSwitcherPrivate::GestureEvent(nux::GestureEvent const& event)
+{
+ switch (state)
+ {
+ case State::WaitingCompoundGesture:
+ return WaitingCompoundGesture(event);
+ break;
+ case State::WaitingEndOfTapAndHold:
+ return WaitingEndOfTapAndHold(event);
+ break;
+ case State::WaitingSwitcherManipulation:
+ return WaitingSwitcherManipulation(event);
+ break;
+ case State::DraggingSwitcher:
+ return DraggingSwitcher(event);
+ break;
+ case State::RecognizingMouseClickOrDrag:
+ return RecognizingMouseClickOrDrag(event);
+ break;
+ case State::DraggingSwitcherWithMouse:
+ return DraggingSwitcherWithMouse(event);
+ break;
+ case State::WaitingMandatorySwitcherClose:
+ // do nothing
+ return GestureDeliveryRequest::NONE;
+ break;
+ default:
+ g_assert(false); // should never happen
+ return GestureDeliveryRequest::NONE;
+ break;
+ }
+}
+
+GestureDeliveryRequest GesturalWindowSwitcherPrivate::WaitingCompoundGesture(nux::GestureEvent const& event)
+{
+ GestureDeliveryRequest request = GestureDeliveryRequest::NONE;
+
+ switch (gesture_recognizer.GestureEvent(event))
+ {
+ case RecognitionResult::NONE:
+ // Do nothing;
+ break;
+ case RecognitionResult::DOUBLE_TAP_RECOGNIZED:
+ InitiateSwitcherNext();
+ CloseSwitcherAfterTimeout(GesturalWindowSwitcher::SWITCHER_TIME_AFTER_DOUBLE_TAP);
+ break;
+ default: // RecognitionResult::TAP_AND_HOLD_RECOGNIZED:
+ InitiateSwitcherNext();
+ request = GestureDeliveryRequest::EXCLUSIVITY;
+ state = State::WaitingEndOfTapAndHold;
+ }
+
+ return request;
+}
+
+GestureDeliveryRequest GesturalWindowSwitcherPrivate::WaitingEndOfTapAndHold(nux::GestureEvent const& event)
+{
+ GestureDeliveryRequest request = GestureDeliveryRequest::NONE;
+
+ if (event.type == EVENT_GESTURE_BEGIN)
+ {
+ LOG_ERROR(logger) << "There should be no simultaneous/overlapping gestures.";
+ return request;
+ }
+
+ if (event.type == EVENT_GESTURE_UPDATE)
+ {
+ if (event.GetGestureClasses() & nux::DRAG_GESTURE)
+ {
+ state = State::DraggingSwitcher;
+ accumulated_horizontal_drag = 0.0f;
+ request = DraggingSwitcher(event);
+ }
+ }
+ else // event.type == EVENT_GESTURE_END
+ {
+ CloseSwitcherAfterTimeout(GesturalWindowSwitcher::SWITCHER_TIME_AFTER_HOLD_RELEASED);
+ state = State::WaitingSwitcherManipulation;
+ }
+
+ return request;
+}
+
+GestureDeliveryRequest
+GesturalWindowSwitcherPrivate::WaitingSwitcherManipulation(nux::GestureEvent const& event)
+{
+ GestureDeliveryRequest request = GestureDeliveryRequest::NONE;
+
+ if (event.type == EVENT_GESTURE_BEGIN)
+ {
+ // Don't leak gestures to windows behind the switcher
+ request = GestureDeliveryRequest::EXCLUSIVITY;
+ }
+
+ if (event.GetGestureClasses() & nux::DRAG_GESTURE)
+ {
+ state = State::DraggingSwitcher;
+ timer_close_switcher.stop();
+ DraggingSwitcher(event);
+ }
+
+ return request;
+}
+
+GestureDeliveryRequest GesturalWindowSwitcherPrivate::DraggingSwitcher(nux::GestureEvent const& event)
+{
+ if (event.type == EVENT_GESTURE_BEGIN)
+ {
+ LOG_ERROR(logger) << "There should be no simultaneous/overlapping gestures.";
+ return GestureDeliveryRequest::NONE;
+ }
+
+ if (!(event.GetGestureClasses() & nux::DRAG_GESTURE))
+ {
+ LOG_ERROR(logger) << "Didn't get the expected drag gesture.";
+ return GestureDeliveryRequest::NONE;
+ }
+
+ if (event.type == EVENT_GESTURE_UPDATE)
+ {
+ accumulated_horizontal_drag += event.GetDelta().x;
+ ProcessAccumulatedHorizontalDrag();
+ }
+ else // event.type == EVENT_GESTURE_END
+ {
+ CloseSwitcher();
+ state = State::WaitingCompoundGesture;
+ }
+
+ return GestureDeliveryRequest::NONE;
+}
+
+GestureDeliveryRequest
+GesturalWindowSwitcherPrivate::RecognizingMouseClickOrDrag(nux::GestureEvent const& event)
+{
+ // Mouse press event has come but gestures have precedence over mouse
+ // for interacting with the switcher.
+ // Therefore act in the same way is if the mouse press didn't come
+ return WaitingSwitcherManipulation(event);
+}
+
+GestureDeliveryRequest
+GesturalWindowSwitcherPrivate::DraggingSwitcherWithMouse(nux::GestureEvent const& event)
+{
+ // Mouse press event has come but gestures have precedence over mouse
+ // for interacting with the switcher.
+ // Therefore act in the same way is if the mouse press didn't come
+ return WaitingSwitcherManipulation(event);
+}
+
+void GesturalWindowSwitcherPrivate::CloseSwitcherAfterTimeout(int timeout)
+{
+ timer_close_switcher.stop();
+ // min and max timeouts
+ timer_close_switcher.setTimes(timeout,
+ timeout+50);
+ timer_close_switcher.start();
+}
+
+bool GesturalWindowSwitcherPrivate::OnCloseSwitcherTimeout()
+{
+
+ switch (state)
+ {
+ case State::WaitingSwitcherManipulation:
+ case State::WaitingMandatorySwitcherClose:
+ state = State::WaitingCompoundGesture;
+ CloseSwitcher();
+ break;
+ default:
+ CloseSwitcher();
+ }
+ // I'm assuming that by returning false I'm telling the timer to stop.
+ return false;
+}
+
+void GesturalWindowSwitcherPrivate::CloseSwitcher()
+{
+ switcher_controller->Hide();
+}
+
+void GesturalWindowSwitcherPrivate::InitiateSwitcherNext()
+{
+ timer_close_switcher.stop();
+
+ if (switcher_controller->Visible())
+ switcher_controller->Next();
+ else
+ {
+ unity_screen->SetUpAndShowSwitcher();
+ }
+}
+
+void GesturalWindowSwitcherPrivate::InitiateSwitcherPrevious()
+{
+ timer_close_switcher.stop();
+
+ if (switcher_controller->Visible())
+ {
+ switcher_controller->Prev();
+ }
+}
+
+void GesturalWindowSwitcherPrivate::ProcessSwitcherViewMouseDown(int x, int y,
+ unsigned long button_flags, unsigned long key_flags)
+{
+ if (state != State::WaitingSwitcherManipulation)
+ return;
+
+ // Don't close the switcher while the mouse is pressed over it
+ timer_close_switcher.stop();
+
+ state = State::RecognizingMouseClickOrDrag;
+
+ index_icon_hit = switcher_controller->GetView()->IconIndexAt(x, y);
+ accumulated_horizontal_drag = 0.0f;
+}
+
+void GesturalWindowSwitcherPrivate::ProcessSwitcherViewMouseUp(int x, int y,
+ unsigned long button_flags, unsigned long key_flags)
+{
+ switch (state)
+ {
+ case State::RecognizingMouseClickOrDrag:
+ if (index_icon_hit >= 0)
+ {
+ // it was a click after all.
+ switcher_controller->Select(index_icon_hit);
+ // it was not a double tap gesture but we use the same timeout
+ CloseSwitcherAfterTimeout(GesturalWindowSwitcher::SWITCHER_TIME_AFTER_DOUBLE_TAP);
+ state = State::WaitingMandatorySwitcherClose;
+ }
+ else
+ {
+ CloseSwitcher();
+ state = State::WaitingCompoundGesture;
+ }
+ break;
+ case State::DraggingSwitcherWithMouse:
+ CloseSwitcher();
+ state = State::WaitingCompoundGesture;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+}
+
+void GesturalWindowSwitcherPrivate::ProcessSwitcherViewMouseDrag(int x, int y, int dx, int dy,
+ unsigned long button_flags, unsigned long key_flags)
+{
+ switch (state)
+ {
+ case State::RecognizingMouseClickOrDrag:
+ accumulated_horizontal_drag += dx;
+ if (fabsf(accumulated_horizontal_drag) >=
+ GesturalWindowSwitcher::MOUSE_DRAG_THRESHOLD)
+ {
+ state = State::DraggingSwitcherWithMouse;
+ ProcessAccumulatedHorizontalDrag();
+ }
+ break;
+ case State::DraggingSwitcherWithMouse:
+ accumulated_horizontal_drag += dx;
+ ProcessAccumulatedHorizontalDrag();
+ break;
+ default:
+ // do nothing
+ break;
+ }
+}
+
+void GesturalWindowSwitcherPrivate::ProcessAccumulatedHorizontalDrag()
+{
+ if (accumulated_horizontal_drag >=
+ GesturalWindowSwitcher::DRAG_DELTA_FOR_CHANGING_SELECTION)
+ {
+ InitiateSwitcherNext();
+ accumulated_horizontal_drag = 0.0f;
+ }
+ else if (accumulated_horizontal_drag <=
+ -GesturalWindowSwitcher::DRAG_DELTA_FOR_CHANGING_SELECTION)
+ {
+ InitiateSwitcherPrevious();
+ accumulated_horizontal_drag = 0.0f;
+ }
+}
+
+void GesturalWindowSwitcherPrivate::ConnectToSwitcherViewMouseEvents()
+{
+ unity::switcher::SwitcherView *switcher_view = switcher_controller->GetView();
+ g_assert(switcher_view);
+
+ mouse_down_connection = switcher_view->mouse_down.connect(
+ sigc::mem_fun(this, &GesturalWindowSwitcherPrivate::ProcessSwitcherViewMouseDown));
+
+ mouse_up_connection = switcher_view->mouse_up.connect(
+ sigc::mem_fun(this, &GesturalWindowSwitcherPrivate::ProcessSwitcherViewMouseUp));
+
+ mouse_drag_connection = switcher_view->mouse_drag.connect(
+ sigc::mem_fun(this, &GesturalWindowSwitcherPrivate::ProcessSwitcherViewMouseDrag));
+}
+
+///////////////////////////////////////////
+// public class
+
+GesturalWindowSwitcher::GesturalWindowSwitcher()
+ : p(new GesturalWindowSwitcherPrivate)
+{
+}
+
+GesturalWindowSwitcher::~GesturalWindowSwitcher()
+{
+ delete p;
+}
+
+GestureDeliveryRequest GesturalWindowSwitcher::GestureEvent(nux::GestureEvent const& event)
+{
+ return p->GestureEvent(event);
+}
diff --git a/plugins/unityshell/src/GesturalWindowSwitcher.h b/plugins/unityshell/src/GesturalWindowSwitcher.h
new file mode 100644
index 000000000..527c7e301
--- /dev/null
+++ b/plugins/unityshell/src/GesturalWindowSwitcher.h
@@ -0,0 +1,85 @@
+/*
+ * GesturalWindowSwitcher.h
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
+ */
+
+#ifndef GESTURAL_WINDOW_SWITCHER_H
+#define GESTURAL_WINDOW_SWITCHER_H
+
+#include <Nux/Gesture.h>
+#include "CompoundGestureRecognizer.h"
+#include "SwitcherController.h"
+#include <core/timer.h>
+
+namespace unity
+{
+
+class UnityScreen;
+class GesturalWindowSwitcherPrivate;
+
+/*
+ Manipulates the window switcher according to multi-touch gestures
+
+ The following gestural interactions with the window switcher are implemented:
+
+ 1. 3-fingers double tap -> switches to previous window
+
+ 2. 3-fingers tap followed by 3-fingers hold -> shows window switcher
+ - drag those 3-fingers -> change selected window icon
+ - release fingers -> selects window and closes switcher
+
+ 3. 3-fingers tap followed by 3-fingers hold -> shows window switcher
+ - release fingers -> switcher will kept being shown for some seconds still
+ - drag with one or three fingers -> change selected window
+ - release finger(s) -> selects window and closes switcher
+
+ 4. 3-fingers tap followed by 3-fingers hold -> shows window switcher
+ - release fingers -> switcher will kept being shown for some seconds still
+ - tap on some window icon -> selects that icon and closes the switcher
+
+ */
+class GesturalWindowSwitcher : public nux::GestureTarget
+{
+ public:
+ GesturalWindowSwitcher();
+ virtual ~GesturalWindowSwitcher();
+
+ // in milliseconds
+ static const int SWITCHER_TIME_AFTER_DOUBLE_TAP = 350;
+ static const int SWITCHER_TIME_AFTER_HOLD_RELEASED = 7000;
+
+ // How far, in screen pixels, a drag gesture must go in order
+ // to trigger a change in the selected window.
+ static const float DRAG_DELTA_FOR_CHANGING_SELECTION;
+
+ // How far, in screen pixels, a mouse pointer must move in order
+ // to be considered dragging the switcher.
+ static const float MOUSE_DRAG_THRESHOLD;
+
+ virtual nux::GestureDeliveryRequest GestureEvent(nux::GestureEvent const& event);
+
+ private:
+ GesturalWindowSwitcherPrivate* p;
+};
+typedef std::shared_ptr<GesturalWindowSwitcher> ShPtGesturalWindowSwitcher;
+
+} // namespace unity
+
+#endif // GESTURAL_WINDOW_SWITCHER_H
diff --git a/plugins/unityshell/src/GestureEngine.cpp b/plugins/unityshell/src/GestureEngine.cpp
deleted file mode 100644
index 9bf825b3a..000000000
--- a/plugins/unityshell/src/GestureEngine.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * GestureEngine.cpp
- * This file is part of Unity
- *
- * Copyright (C) 2011 - Canonical Ltd.
- *
- * Unity 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.
- *
- * Unity 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 Unity; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#include <X11/cursorfont.h>
-
-#include "ubus-server.h"
-#include "UBusMessages.h"
-#include "GestureEngine.h"
-#include "PluginAdapter.h"
-
-GestureEngine::GestureEngine(CompScreen* screen)
-{
- _screen = screen;
-
- _drag_id = 0;
- _drag_window = 0;
- _pinch_id = 0;
- _touch_id = 0;
- _drag_grab = 0;
- _pinch_grab = 0;
- _fleur_cursor = XCreateFontCursor (screen->dpy (), XC_fleur);
-
- GeisAdapter& adapter = GeisAdapter::Instance();
-
- adapter.tap.connect(sigc::mem_fun(this, &GestureEngine::OnTap));
-
- adapter.drag_start.connect(sigc::mem_fun(this, &GestureEngine::OnDragStart));
- adapter.drag_update.connect(sigc::mem_fun(this, &GestureEngine::OnDragUpdate));
- adapter.drag_finish.connect(sigc::mem_fun(this, &GestureEngine::OnDragFinish));
-
- adapter.rotate_start.connect(sigc::mem_fun(this, &GestureEngine::OnRotateStart));
- adapter.rotate_update.connect(sigc::mem_fun(this, &GestureEngine::OnRotateUpdate));
- adapter.rotate_finish.connect(sigc::mem_fun(this, &GestureEngine::OnRotateFinish));
-
- adapter.pinch_start.connect(sigc::mem_fun(this, &GestureEngine::OnPinchStart));
- adapter.pinch_update.connect(sigc::mem_fun(this, &GestureEngine::OnPinchUpdate));
- adapter.pinch_finish.connect(sigc::mem_fun(this, &GestureEngine::OnPinchFinish));
-
- adapter.touch_start.connect(sigc::mem_fun(this, &GestureEngine::OnTouchStart));
- adapter.touch_update.connect(sigc::mem_fun(this, &GestureEngine::OnTouchUpdate));
- adapter.touch_finish.connect(sigc::mem_fun(this, &GestureEngine::OnTouchFinish));
-}
-
-GestureEngine::~GestureEngine()
-{
- if (_fleur_cursor)
- XFreeCursor (screen->dpy (), _fleur_cursor);
-}
-
-void
-GestureEngine::OnTap(GeisAdapter::GeisTapData* data)
-{
- if (data->touches == 4)
- {
- UBusServer* ubus = ubus_server_get_default();
- ubus_server_send_message(ubus, UBUS_DASH_EXTERNAL_ACTIVATION, NULL);
- }
-}
-
-CompWindow* GestureEngine::FindCompWindowAtPos(float fpos_x, float fpos_y)
-{
- const CompWindowVector& client_list_stacking = _screen->clientList(true);
-
- int pos_x = fpos_x;
- int pos_y = fpos_y;
-
- for (auto iter = client_list_stacking.rbegin(),
- end = client_list_stacking.rend();
- iter != end; ++iter)
- {
- CompWindow* window = *iter;
-
- if (pos_x >= window->x() && pos_x <= (window->width() + window->x())
- &&
- pos_y >= window->y() && pos_y <= (window->height() + window->y()))
- return window;
- }
-
- return nullptr;
-}
-
-void
-GestureEngine::OnDragStart(GeisAdapter::GeisDragData* data)
-{
- if (data->touches == 3)
- {
- _drag_window = FindCompWindowAtPos(data->focus_x, data->focus_y);
-
-
- if (!_drag_window)
- return;
-
- if (!(_drag_window->actions() & CompWindowActionMoveMask))
- {
- _drag_window = 0;
- return;
- }
-
- /* Don't allow windows to be dragged if completely maximized */
- if ((_drag_window->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE)
- {
- _drag_window = 0;
- return;
- }
-
- if (_drag_grab)
- _screen->removeGrab(_drag_grab, NULL);
- _drag_id = data->id;
- _drag_grab = _screen->pushGrab(_fleur_cursor, "unity");
- _drag_window->grabNotify (_drag_window->serverGeometry ().x (),
- _drag_window->serverGeometry ().y (),
- 0, CompWindowGrabMoveMask | CompWindowGrabButtonMask);
- }
-}
-
-/* FIXME: CompScreen::warpPointer filters out motion events which
- * other plugins may need to process, but for most cases in core
- * they should be filtered out. */
-void
-GestureEngine::OnDragUpdate(GeisAdapter::GeisDragData* data)
-{
- if (_drag_id == data->id && _drag_window)
- {
- unsigned int px = std::max (std::min (pointerX + static_cast <int> (data->delta_x), screen->width ()), 0);
- unsigned int py = std::max (std::min (pointerY + static_cast <int> (data->delta_y), screen->height ()), 0);
-
- if (_drag_window->state () & CompWindowStateMaximizedVertMask)
- py = pointerY;
- if (_drag_window->state () & CompWindowStateMaximizedHorzMask)
- px = pointerX;
-
- XWarpPointer(screen->dpy (),
- None, screen->root (),
- 0, 0, 0, 0,
- px, py);
-
- XSync(screen->dpy (), false);
- _drag_window->move(px - pointerX, py - pointerY, false);
-
- pointerX = px;
- pointerY = py;
- }
-}
-
-void
-GestureEngine::OnDragFinish(GeisAdapter::GeisDragData* data)
-{
- if (_drag_id == data->id && _drag_window)
- {
- _drag_window->ungrabNotify ();
- _drag_window->syncPosition();
- EndDrag();
- }
-}
-
-void
-GestureEngine::EndDrag()
-{
- if (_drag_window)
- {
- _screen->removeGrab(_drag_grab, NULL);
- _drag_grab = 0;
- _drag_window = 0;
- _drag_id = 0;
- }
-}
-
-void
-GestureEngine::OnRotateStart(GeisAdapter::GeisRotateData* data)
-{
-
-}
-void
-GestureEngine::OnRotateUpdate(GeisAdapter::GeisRotateData* data)
-{
-
-}
-void
-GestureEngine::OnRotateFinish(GeisAdapter::GeisRotateData* data)
-{
-
-}
-
-void
-GestureEngine::OnTouchStart(GeisAdapter::GeisTouchData* data)
-{
- if (data->touches == 3 && data->window != 0)
- {
- CompWindow* result = FindCompWindowAtPos(data->focus_x, data->focus_y);
-
- if (result)
- {
- PluginAdapter::Default()->ShowGrabHandles(result, false);
- _touch_id = data->id;
- _touch_window = result;
- }
- }
-}
-
-void
-GestureEngine::OnTouchUpdate(GeisAdapter::GeisTouchData* data)
-{
-
-}
-
-void
-GestureEngine::OnTouchFinish(GeisAdapter::GeisTouchData* data)
-{
- if (_touch_id == data->id)
- {
- if (_touch_window)
- PluginAdapter::Default()->ShowGrabHandles(_touch_window, true);
- _touch_id = 0;
- _touch_window = 0;
- }
-}
-
-void
-GestureEngine::OnPinchStart(GeisAdapter::GeisPinchData* data)
-{
- if (data->touches == 3)
- {
- _pinch_window = FindCompWindowAtPos(data->focus_x, data->focus_y);
-
- if (!_pinch_window)
- return;
-
- _pinch_id = data->id;
-
- if (_pinch_grab)
- _screen->removeGrab(_pinch_grab, NULL);
- _pinch_grab = _screen->pushGrab(_screen->invisibleCursor(), "unity");
- }
-}
-void
-GestureEngine::OnPinchUpdate(GeisAdapter::GeisPinchData* data)
-{
- if (data->id != _pinch_id)
- return;
-
- if (data->radius > 1.25)
- {
- _pinch_window->maximize(MAXIMIZE_STATE);
- EndDrag();
- }
- else if (data->radius < 0.8)
- {
- _pinch_window->maximize(0);
- EndDrag();
- }
-}
-void
-GestureEngine::OnPinchFinish(GeisAdapter::GeisPinchData* data)
-{
- if (_pinch_id == data->id && _pinch_window)
- {
- _screen->removeGrab(_pinch_grab, NULL);
- _pinch_grab = 0;
- _pinch_id = 0;
- }
-}
diff --git a/plugins/unityshell/src/GestureEngine.h b/plugins/unityshell/src/GestureEngine.h
deleted file mode 100644
index bce81628d..000000000
--- a/plugins/unityshell/src/GestureEngine.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * GestureEngine.h
- * This file is part of Unity
- *
- * Copyright (C) 2011 - Canonical Ltd.
- *
- * Unity 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.
- *
- * Unity 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 Unity; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#include <core/core.h>
-
-#include <sigc++/sigc++.h>
-#include "GeisAdapter.h"
-
-class GestureEngine : public sigc::trackable
-{
-public:
- GestureEngine(CompScreen* screen);
- virtual ~GestureEngine();
-
- void OnTap(GeisAdapter::GeisTapData* data);
-
- void OnDragStart(GeisAdapter::GeisDragData* data);
- void OnDragUpdate(GeisAdapter::GeisDragData* data);
- void OnDragFinish(GeisAdapter::GeisDragData* data);
-
- void OnRotateStart(GeisAdapter::GeisRotateData* data);
- void OnRotateUpdate(GeisAdapter::GeisRotateData* data);
- void OnRotateFinish(GeisAdapter::GeisRotateData* data);
-
- void OnPinchStart(GeisAdapter::GeisPinchData* data);
- void OnPinchUpdate(GeisAdapter::GeisPinchData* data);
- void OnPinchFinish(GeisAdapter::GeisPinchData* data);
-
- void OnTouchStart(GeisAdapter::GeisTouchData* data);
- void OnTouchUpdate(GeisAdapter::GeisTouchData* data);
- void OnTouchFinish(GeisAdapter::GeisTouchData* data);
-
- void EndDrag();
-private:
- CompWindow* FindCompWindowAtPos(float pos_x, float pos_y);
-
- CompScreen* _screen;
- CompWindow* _drag_window;
- CompWindow* _pinch_window;
- CompWindow* _touch_window;
- CompScreen::GrabHandle _drag_grab;
- CompScreen::GrabHandle _pinch_grab;
-
- int _drag_id;
- int _pinch_id;
- int _touch_id;
-
- Cursor _fleur_cursor;
-};
diff --git a/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp b/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp
index 99d9ff485..de9be43f3 100644
--- a/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp
+++ b/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp
@@ -17,7 +17,7 @@
* Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
*/
-#ifndef USE_MODERN_COMPIZ_GL
+#ifndef USE_GLES
#include "ScreenEffectFramebufferObject.h"
#include "BackgroundEffectHelper.h"
#include <NuxCore/Logger.h>
@@ -239,5 +239,5 @@ unity::ScreenEffectFramebufferObject::~ScreenEffectFramebufferObject ()
glDeleteTextures (1, &mFBTexture);
}
-#endif // USE_MODERN_COMPIZ_GL
+#endif // USE_GLES
diff --git a/plugins/unityshell/src/UnityGestureBroker.cpp b/plugins/unityshell/src/UnityGestureBroker.cpp
new file mode 100644
index 000000000..89e22ff66
--- /dev/null
+++ b/plugins/unityshell/src/UnityGestureBroker.cpp
@@ -0,0 +1,133 @@
+/*
+ * UnityGestureBroker.cpp
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity 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 Unity; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "UnityGestureBroker.h"
+#include "UnityGestureTarget.h"
+#include "WindowGestureTarget.h"
+
+#include <X11/cursorfont.h>
+
+UnityGestureBroker::UnityGestureBroker()
+ : nux::GestureBroker()
+{
+ g_assert(WindowGestureTarget::fleur_cursor == 0);
+ WindowGestureTarget::fleur_cursor = XCreateFontCursor (screen->dpy (), XC_fleur);
+
+ unity_target.reset(new UnityGestureTarget);
+ gestural_window_switcher_.reset(new unity::GesturalWindowSwitcher);
+}
+
+UnityGestureBroker::~UnityGestureBroker()
+{
+ if (WindowGestureTarget::fleur_cursor)
+ {
+ XFreeCursor (screen->dpy (), WindowGestureTarget::fleur_cursor);
+ WindowGestureTarget::fleur_cursor = 0;
+ }
+}
+
+std::vector<nux::ShPtGestureTarget>
+UnityGestureBroker::FindGestureTargets(const nux::GestureEvent &event)
+{
+ std::vector<nux::ShPtGestureTarget> targets;
+
+ const std::vector<nux::TouchPoint> &touches = event.GetTouches();
+
+ if (touches.size() == 4)
+ {
+ targets.push_back(unity_target);
+ }
+ else if (touches.size() == 3)
+ {
+ targets.push_back(gestural_window_switcher_);
+
+ CompWindow *window = FindWindowHitByGesture(event);
+ if (window)
+ {
+ targets.push_back(nux::ShPtGestureTarget(new WindowGestureTarget(window)));
+ }
+ }
+
+ return targets;
+}
+
+CompWindow *UnityGestureBroker::FindWindowHitByGesture(const nux::GestureEvent &event)
+{
+ if (event.IsDirectTouch())
+ {
+ /* If a direct device is being used (e.g., a touchscreen), all touch
+ points must hit the same window */
+ CompWindow *last_window = nullptr;
+ const std::vector<nux::TouchPoint> &touches = event.GetTouches();
+ for (auto touch : touches)
+ {
+ CompWindow *window = FindCompWindowAtPos(touch.x, touch.y);
+ if (last_window)
+ {
+ if (window != last_window)
+ {
+ return nullptr;
+ }
+ }
+ else
+ {
+ last_window = window;
+ }
+ }
+
+ return last_window;
+ }
+ else
+ {
+ /* If a indirect device is being used (e.g., a trackpad), the individual
+ touch points are not in screen coordinates and therefore it doesn't make
+ sense to hit-test them individually against the window tree. Instead,
+ we use just the focus point, which is the same as the cursor
+ position in this case (which is in screen coordinates). */
+ return FindCompWindowAtPos(event.GetFocus().x, event.GetFocus().y);
+ }
+}
+
+CompWindow* UnityGestureBroker::FindCompWindowAtPos(int pos_x, int pos_y)
+{
+ const CompWindowVector& client_list_stacking = screen->clientList(true);
+
+ for (auto iter = client_list_stacking.rbegin(),
+ end = client_list_stacking.rend();
+ iter != end; ++iter)
+ {
+ CompWindow* window = *iter;
+
+ if (window->minimized())
+ continue;
+
+ if (window->state() & CompWindowStateHiddenMask)
+ continue;
+
+ if (pos_x >= window->x() && pos_x <= (window->width() + window->x())
+ &&
+ pos_y >= window->y() && pos_y <= (window->height() + window->y()))
+ return window;
+ }
+
+ return nullptr;
+}
diff --git a/plugins/unityshell/src/UnityGestureBroker.h b/plugins/unityshell/src/UnityGestureBroker.h
new file mode 100644
index 000000000..75b4f13c1
--- /dev/null
+++ b/plugins/unityshell/src/UnityGestureBroker.h
@@ -0,0 +1,52 @@
+/*
+ * UnityGestureBroker.h
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity 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 Unity; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef UNITY_GESTURE_BROKER
+#define UNITY_GESTURE_BROKER
+
+#include <core/core.h>
+
+#include <Nux/GestureBroker.h>
+#include "GesturalWindowSwitcher.h"
+
+class UnityGestureBroker : public nux::GestureBroker
+{
+public:
+ UnityGestureBroker();
+ virtual ~UnityGestureBroker();
+
+private:
+ std::vector<nux::ShPtGestureTarget>
+ virtual FindGestureTargets(const nux::GestureEvent &event);
+
+ CompWindow *FindWindowHitByGesture(const nux::GestureEvent &event);
+
+ /*!
+ Returns the top-most CompWindow at the given position, if any.
+ */
+ CompWindow* FindCompWindowAtPos(int pos_x, int pos_y);
+
+ nux::ShPtGestureTarget unity_target;
+ unity::ShPtGesturalWindowSwitcher gestural_window_switcher_;
+};
+
+#endif // UNITY_GESTURE_BROKER
diff --git a/plugins/unityshell/src/UnityGestureTarget.cpp b/plugins/unityshell/src/UnityGestureTarget.cpp
new file mode 100644
index 000000000..3c4ff2ab6
--- /dev/null
+++ b/plugins/unityshell/src/UnityGestureTarget.cpp
@@ -0,0 +1,55 @@
+/*
+ * UnityGestureTarget.cpp
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity 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 Unity; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "UnityGestureTarget.h"
+
+#include <Nux/Nux.h> // otherwise unityshell.h inclusion will cause failures
+#include "unityshell.h"
+#include "Launcher.h"
+
+#include "UBusMessages.h"
+#include "ubus-server.h"
+
+using namespace nux;
+
+UnityGestureTarget::UnityGestureTarget()
+{
+ launcher = &unity::UnityScreen::get(screen)->launcher_controller()->launcher();
+}
+
+GestureDeliveryRequest UnityGestureTarget::GestureEvent(const nux::GestureEvent &event)
+{
+ if (event.GetGestureClasses() & DRAG_GESTURE)
+ {
+ if (launcher.IsValid())
+ launcher->GestureEvent(event);
+ }
+ else if (event.GetGestureClasses() == TAP_GESTURE
+ && event.type == EVENT_GESTURE_END)
+ {
+ ubus_server_send_message(ubus_server_get_default(),
+ UBUS_DASH_EXTERNAL_ACTIVATION,
+ NULL);
+ }
+
+ return GestureDeliveryRequest::NONE;
+}
diff --git a/plugins/unityshell/src/UnityGestureTarget.h b/plugins/unityshell/src/UnityGestureTarget.h
new file mode 100644
index 000000000..f47996e63
--- /dev/null
+++ b/plugins/unityshell/src/UnityGestureTarget.h
@@ -0,0 +1,44 @@
+/*
+ * UnityGestureTarget.h
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity 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 Unity; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef UNITY_GESTURE_TARGET_H
+#define UNITY_GESTURE_TARGET_H
+
+#include <Nux/Gesture.h>
+
+/*
+ Target for Unity-level gestures.
+ I.e., for gestures that act on Unity elements, such as
+ the dash or launcher.
+ */
+class UnityGestureTarget : public nux::GestureTarget
+{
+ public:
+ UnityGestureTarget();
+
+ virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event);
+
+ private:
+ nux::ObjectWeakPtr<nux::InputArea> launcher;
+};
+
+#endif // UNITY_GESTURE_TARGET_H
diff --git a/plugins/unityshell/src/WindowGestureTarget.cpp b/plugins/unityshell/src/WindowGestureTarget.cpp
new file mode 100644
index 000000000..8bcaa7b40
--- /dev/null
+++ b/plugins/unityshell/src/WindowGestureTarget.cpp
@@ -0,0 +1,215 @@
+/*
+ * WindowGestureTarget.cpp
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity 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 Unity; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "WindowGestureTarget.h"
+
+#include <Nux/Nux.h> // otherwise unityshell.h inclusion will cause failures
+#include "unityshell.h"
+
+#include "PluginAdapter.h"
+
+using namespace nux;
+
+Cursor WindowGestureTarget::fleur_cursor = 0;
+
+WindowGestureTarget::WindowGestureTarget(CompWindow *window)
+ : window_(window), drag_grab_(0), started_window_move_(false),
+ window_restored_by_pinch_(false)
+{
+ // A workaround for the lack of weak pointers.
+ unity::UnityWindow *unity_window = unity::UnityWindow::get(window);
+
+ connection_window_destruction =
+ unity_window->being_destroyed.connect(
+ sigc::mem_fun(this, &WindowGestureTarget::NullifyWindowPointer));
+}
+
+WindowGestureTarget::~WindowGestureTarget()
+{
+ connection_window_destruction.disconnect();
+ if (drag_grab_)
+ {
+ if (window_)
+ window_->ungrabNotify();
+ screen->removeGrab(drag_grab_, NULL);
+ }
+}
+
+void WindowGestureTarget::NullifyWindowPointer()
+{
+ window_ = nullptr;
+}
+
+GestureDeliveryRequest WindowGestureTarget::GestureEvent(const nux::GestureEvent &event)
+{
+ if (!window_)
+ return GestureDeliveryRequest::NONE;
+
+ switch (event.type)
+ {
+ case nux::EVENT_GESTURE_BEGIN:
+ PluginAdapter::Default()->ShowGrabHandles(window_, false);
+ break;
+ case EVENT_GESTURE_UPDATE:
+ if (event.GetGestureClasses() & PINCH_GESTURE)
+ MaximizeOrRestoreWindowDueToPinch(event);
+ if (event.GetGestureClasses() & DRAG_GESTURE)
+ {
+ if (WindowCanMove())
+ {
+ if (!started_window_move_)
+ {
+ StartWindowMove(event);
+ started_window_move_ = true;
+ }
+ MoveWindow(event);
+ }
+ }
+ break;
+ default: // EVENT_GESTURE_END | EVENT_GESTURE_LOST
+ if (event.GetGestureClasses() & DRAG_GESTURE)
+ {
+ EndWindowMove(event);
+ started_window_move_ = false;
+ }
+ PluginAdapter::Default()->ShowGrabHandles(window_, true);
+ break;
+ };
+
+ return GestureDeliveryRequest::NONE;
+}
+
+bool WindowGestureTarget::WindowCanMove()
+{
+ if (!(window_->actions() & CompWindowActionMoveMask))
+ return false;
+
+ /* Don't allow windows to be dragged if completely maximized */
+ if ((window_->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE)
+ return false;
+
+ /* Don't start moving a window that has just been restored. The user is likely
+ still performing the pinch and not expecting the window to start moving */
+ if (window_restored_by_pinch_)
+ return false;
+
+ return true;
+}
+
+void WindowGestureTarget::MaximizeOrRestoreWindowDueToPinch(const nux::GestureEvent &event)
+{
+ if (event.GetRadius() > 1.25f)
+ {
+ window_->maximize(MAXIMIZE_STATE);
+ RemoveDragGrab();
+ window_restored_by_pinch_ = false;
+ }
+ else if (event.GetRadius() < 0.8f)
+ {
+ if (window_->state() & MAXIMIZE_STATE)
+ {
+ window_->maximize(0);
+ RemoveDragGrab();
+ window_restored_by_pinch_ = true;
+ }
+ }
+}
+
+void WindowGestureTarget::StartWindowMove(const nux::GestureEvent &event)
+{
+ if (!event.IsDirectTouch())
+ {
+ drag_grab_ = screen->pushGrab(fleur_cursor, "unity");
+ window_->grabNotify(window_->serverGeometry().x(),
+ window_->serverGeometry().y(),
+ 0,
+ CompWindowGrabMoveMask | CompWindowGrabButtonMask);
+ }
+}
+
+void WindowGestureTarget::MoveWindow(const nux::GestureEvent &event)
+{
+ const nux::Point2D<float> &delta = event.GetDelta();
+
+ unsigned int px = std::max(std::min(pointerX + static_cast<int>(delta.x),
+ screen->width()),
+ 0);
+
+ unsigned int py = std::max(std::min(pointerY + static_cast<int>(delta.y),
+ screen->height()),
+ 0);
+
+ if (window_->state() & CompWindowStateMaximizedVertMask)
+ py = pointerY;
+ if (window_->state() & CompWindowStateMaximizedHorzMask)
+ px = pointerX;
+
+ if (!event.IsDirectTouch())
+ {
+ /* FIXME: CompScreen::warpPointer filters out motion events which
+ other plugins may need to process, but for most cases in core
+ they should be filtered out. */
+ XWarpPointer(screen->dpy (),
+ None, screen->root (),
+ 0, 0, 0, 0,
+ px, py);
+ }
+
+ XSync(screen->dpy (), false);
+ window_->move(px - pointerX, py - pointerY, false);
+
+ pointerX = px;
+ pointerY = py;
+}
+
+void WindowGestureTarget::EndWindowMove(const nux::GestureEvent &event)
+{
+ window_->ungrabNotify();
+ RemoveDragGrab();
+ window_->syncPosition();
+}
+
+void WindowGestureTarget::RemoveDragGrab()
+{
+ if (drag_grab_)
+ {
+ screen->removeGrab(drag_grab_, NULL);
+ drag_grab_ = 0;
+ }
+}
+
+bool WindowGestureTarget::Equals(const nux::GestureTarget& other) const
+{
+ const WindowGestureTarget *window_target = dynamic_cast<const WindowGestureTarget *>(&other);
+
+ if (window_target)
+ {
+ if (window_ && window_target->window_)
+ return window_->id() == window_target->window_->id();
+ else
+ return window_ == window_target->window_;
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/plugins/unityshell/src/WindowGestureTarget.h b/plugins/unityshell/src/WindowGestureTarget.h
new file mode 100644
index 000000000..e805e3948
--- /dev/null
+++ b/plugins/unityshell/src/WindowGestureTarget.h
@@ -0,0 +1,57 @@
+/*
+ * WindowGestureTarget.h
+ * This file is part of Unity
+ *
+ * Copyright (C) 2012 - Canonical Ltd.
+ *
+ * Unity 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.
+ *
+ * Unity 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 Unity; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef WINDOW_GESTURE_TARGET_H
+#define WINDOW_GESTURE_TARGET_H
+
+#include <Nux/Gesture.h>
+
+#include <core/core.h> // compiz stuff
+
+class WindowGestureTarget : public nux::GestureTarget
+{
+ public:
+ WindowGestureTarget(CompWindow *window);
+ virtual ~WindowGestureTarget();
+
+ virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event);
+
+ static Cursor fleur_cursor;
+
+ CompWindow *window() {return window_;}
+ private:
+ virtual bool Equals(const nux::GestureTarget& other) const;
+ void StartWindowMove(const nux::GestureEvent &event);
+ void MoveWindow(const nux::GestureEvent &event);
+ void EndWindowMove(const nux::GestureEvent &event);
+ void MaximizeOrRestoreWindowDueToPinch(const nux::GestureEvent &event);
+ bool WindowCanMove();
+ void NullifyWindowPointer();
+ void RemoveDragGrab();
+ CompWindow *window_;
+ CompScreen::GrabHandle drag_grab_;
+ bool started_window_move_;
+ bool window_restored_by_pinch_;
+ sigc::connection connection_window_destruction;
+};
+
+#endif // WINDOW_GESTURE_TARGET_H
diff --git a/plugins/unityshell/src/WindowMinimizeSpeedController.cpp b/plugins/unityshell/src/WindowMinimizeSpeedController.cpp
new file mode 100644
index 000000000..66f28d8fc
--- /dev/null
+++ b/plugins/unityshell/src/WindowMinimizeSpeedController.cpp
@@ -0,0 +1,108 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/* Compiz unity plugin
+ * unity.h
+ *
+ * Copyright (c) 2010-11 Canonical Ltd.
+ *
+ * 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 3
+ * 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.
+ *
+ * Your own copyright notice would go above. You are free to choose whatever
+ * licence you want, just take note that some compiz code is GPL and you will
+ * not be able to re-use it if you want to use a different licence.
+ */
+
+#include <gio/gio.h>
+#include <NuxCore/Logger.h>
+
+#include "WindowMinimizeSpeedController.h"
+
+namespace
+{
+
+nux::logging::Logger logger ("unity.WindowMinimizeSpeedController");
+
+namespace local
+{
+const std::string UNITY_SCHEMA = "com.canonical.Unity";
+}
+}
+
+WindowMinimizeSpeedController::WindowMinimizeSpeedController()
+ : _settings(g_settings_new(local::UNITY_SCHEMA.c_str()))
+ , _minimize_count(g_settings_get_int(_settings, "minimize-count"))
+ , _minimize_speed_threshold(g_settings_get_int(_settings, "minimize-speed-threshold"))
+ , _minimize_slow_duration(g_settings_get_int(_settings, "minimize-slow-duration"))
+ , _minimize_fast_duration(g_settings_get_int(_settings, "minimize-fast-duration"))
+{
+ _minimize_count_changed.Connect(_settings, "changed::minimize-count",
+ [&] (GSettings*, gchar* name) {
+ _minimize_count = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+ _minimize_speed_threshold_changed.Connect(_settings, "changed::minimize-speed-threshold",
+ [&] (GSettings*, gchar* name) {
+ _minimize_speed_threshold = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+ _minimize_fast_duration_changed.Connect(_settings, "changed::minimize-fast-duration",
+ [&] (GSettings*, gchar* name) {
+ _minimize_fast_duration = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+ _minimize_slow_duration_changed.Connect(_settings, "changed::minimize-slow-duration",
+ [&] (GSettings*, gchar* name) {
+ _minimize_slow_duration = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+}
+
+void WindowMinimizeSpeedController::UpdateCount()
+{
+ if (_minimize_count < _minimize_speed_threshold) {
+ _minimize_count += 1;
+ g_settings_set_int(_settings, "minimize-count", _minimize_count);
+ }
+}
+
+int WindowMinimizeSpeedController::getDuration()
+{
+ return mDuration;
+}
+
+void WindowMinimizeSpeedController::SetDuration()
+{
+ /* Perform some sanity checks on the configuration values */
+ if (_minimize_fast_duration > _minimize_slow_duration)
+ {
+ LOG_WARN(logger) << "Configuration mismatch: minimize-fast-duration ("
+ << _minimize_fast_duration
+ << ") is longer than minimize-slow-duration ("
+ << _minimize_slow_duration << "). Not changing speed.";
+ return;
+ }
+
+ if (_minimize_count < 0)
+ _minimize_count = 0;
+ if (_minimize_count > _minimize_speed_threshold)
+ _minimize_count = _minimize_speed_threshold;
+
+ /* Adjust the speed so that it gets linearly closer to maximum speed as we
+ approach the threshold */
+ int speed_range = _minimize_slow_duration - _minimize_fast_duration;
+ float position = (_minimize_speed_threshold <= 0) ? 1.0 :
+ static_cast<float>(_minimize_count) / _minimize_speed_threshold;
+ int duration = _minimize_slow_duration - std::ceil(position * speed_range);
+
+ if (duration != mDuration) {
+ mDuration = duration;
+ DurationChanged.emit();
+ }
+}
diff --git a/plugins/unityshell/src/WindowMinimizeSpeedController.h b/plugins/unityshell/src/WindowMinimizeSpeedController.h
new file mode 100644
index 000000000..49bcbad14
--- /dev/null
+++ b/plugins/unityshell/src/WindowMinimizeSpeedController.h
@@ -0,0 +1,57 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/* Compiz unity plugin
+ * unity.h
+ *
+ * Copyright (c) 2010-11 Canonical Ltd.
+ *
+ * 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 3
+ * 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.
+ *
+ * Your own copyright notice would go above. You are free to choose whatever
+ * licence you want, just take note that some compiz code is GPL and you will
+ * not be able to re-use it if you want to use a different licence.
+ */
+
+#ifndef WINDOWMINIMIZESPEEDCONTROLLER_H
+#define WINDOWMINIMIZESPEEDCONTROLLER_H
+
+#include <core/core.h>
+#include <UnityCore/GLibWrapper.h>
+#include <UnityCore/GLibSignal.h>
+#include <sigc++/sigc++.h>
+
+typedef struct _GSettings GSettings;
+
+using namespace unity;
+
+class WindowMinimizeSpeedController
+{
+public:
+ WindowMinimizeSpeedController();
+ void UpdateCount();
+ int getDuration();
+ sigc::signal<void> DurationChanged;
+
+private:
+ void SetDuration();
+
+ glib::Object<GSettings> _settings;
+ int _minimize_count;
+ int _minimize_speed_threshold;
+ int _minimize_slow_duration;
+ int _minimize_fast_duration;
+ glib::Signal<void, GSettings*, gchar* > _minimize_count_changed;
+ glib::Signal<void, GSettings*, gchar* > _minimize_speed_threshold_changed;
+ glib::Signal<void, GSettings*, gchar* > _minimize_slow_duration_changed;
+ glib::Signal<void, GSettings*, gchar* > _minimize_fast_duration_changed;
+ int mDuration;
+};
+
+#endif // WINDOWMINIMIZESPEEDCONTROLLER_H
diff --git a/plugins/unityshell/src/nux-area-accessible.cpp b/plugins/unityshell/src/nux-area-accessible.cpp
index ca4d02696..64a6c0424 100644
--- a/plugins/unityshell/src/nux-area-accessible.cpp
+++ b/plugins/unityshell/src/nux-area-accessible.cpp
@@ -26,26 +26,26 @@
* nux::Area, exposing the common elements on each basic individual
* element (position, extents, etc)
*
- * In this object is also implemented the main support for the focused
- * object. This is complex due several reasons:
+ * In this object the main support for the focused object is also
+ * implemented. This is complex due to several reasons:
*
- * * We need to ensure the proper order when the objects gets the focus
+ * * We need to ensure the proper order when the objects get the focus
*
- * * It doesn't make too sense to give the focus to an object that it
- * is inside a inactive window, so it is also convenient to emit
+ * * It doesn't make sense to give the focus to an object that is
+ * inside an inactive window too, so it is also convenient to emit
* the window:active event before the focus change.
*
- * => this is the reason there is implemented a system to delay the
- * focus notification until the top level window became active
+ * => this is the reason why there is a system to delay the focus
+ * notification, until the top level window becomes active, implemented
*
* * But the main complexity comes from the fact that not all the
- * objects on unity are implementing key nav in the same way.
+ * objects of Unity are implementing key nav the same way.
*
- * * Launcher uses exclusively InputArea methods like
- * SetKeyboardFocus, OnStartKeyboardReceiver, etc. This is the
- * key focus at a low level abstraction
+ * * The Launcher uses InputArea methods like
+ * SetKeyboardFocus, OnStartKeyboardReceiver, etc exclusively.
+ * This is the key focus at a low level abstraction
*
- * * Dash objects uses the events from Focusable. But in the same
+ * * Dash objects use the events from Focusable. But in the same
* way, they require the low level key focus (OnStartFocus) and
* so on
*
@@ -179,10 +179,10 @@ nux_area_accessible_initialize(AtkObject* accessible,
atk_component_add_focus_handler(ATK_COMPONENT(accessible),
nux_area_accessible_focus_handler);
- /* NOTE: we can't search for the parent window on initilization as a
- general rule, or we could enter on a infinite loop. At area this
+ /* NOTE: we can't search for the parent window on initialization as a
+ general rule, or we could enter an infinite loop. At area this
is done on the focus event. On the Switcher this is done on their
- initialize itself */
+ initialization itself */
}
static AtkObject*
@@ -210,7 +210,7 @@ nux_area_accessible_get_parent(AtkObject* obj)
}
/*
- * Checks if the parent actor, and his parent, etc is all visible
+ * Checks if the parent actor, and his parent, etc are all visible
* Used to check the showing state
*/
static gboolean
@@ -349,7 +349,7 @@ nux_area_accessible_grab_focus(AtkComponent* component)
//area = dynamic_cast<nux::Area*>(nux_object);
- /* FIXME: SetFocused doesn't return if the force was succesful or
+ /* FIXME: SetFocused doesn't return if the force was successful or
not, we suppose that this is the case like in cally and gail */
return TRUE;
@@ -494,7 +494,7 @@ on_parent_window_activate_cb(AtkObject* parent_window,
* This method checks if there is any pending notification, and emits
* it if it is possible
*
- * Returns: TRUE if a atk notification was emitted, FALSE otherwise
+ * Returns: TRUE if an atk notification was emitted, FALSE otherwise
*/
gboolean
nux_area_accessible_check_pending_notification(NuxAreaAccessible* self)
@@ -582,7 +582,7 @@ nux_area_accessible_get_parent_window(NuxAreaAccessible* self)
{
g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(self), NULL);
- /* Ensures that at least whe made a search for it */
+ /* At least ensure that we made a search for it */
check_parent_window_connected(self);
return self->priv->parent_window;
diff --git a/plugins/unityshell/src/nux-area-accessible.h b/plugins/unityshell/src/nux-area-accessible.h
index 207247a3f..a5326c63f 100644
--- a/plugins/unityshell/src/nux-area-accessible.h
+++ b/plugins/unityshell/src/nux-area-accessible.h
@@ -49,9 +49,9 @@ struct _NuxAreaAccessibleClass
NuxObjectAccessibleClass parent_class;
/*
- * Usually objects shouldn emit events like focus or selection
+ * Usually objects shouldn't emit events like focus or selection
* changes until the toplevel window is active. This method is
- * called when the toplevel window became active. Redefine it if you
+ * called when the toplevel window becomes active. Redefine it if you
* need to check any pending state change notification.
*/
gboolean(*check_pending_notification)(NuxAreaAccessible* self);
diff --git a/plugins/unityshell/src/nux-base-window-accessible.cpp b/plugins/unityshell/src/nux-base-window-accessible.cpp
index 4ec4a7836..baa991b8b 100644
--- a/plugins/unityshell/src/nux-base-window-accessible.cpp
+++ b/plugins/unityshell/src/nux-base-window-accessible.cpp
@@ -26,11 +26,11 @@
* * Expose the child of BaseWindow (the layout)
* * Window event notification (activate, deactivate, and so on)
*
- * BTW: we consider that one window is active if it has directly the
- * keyboard focus, or if one of his child has the keyboard focus (ie:
+ * BTW: we consider that one window is active, if it directly has
+ * keyboard focus, or if one of its children has keyboard focus (ie:
* the Launcher via GrabKeyboardFocus)
*
- * HasKeyboardFocus is not a reliable to check that:
+ * HasKeyboardFocus is not reliable to check that:
* see bug https://bugs.launchpad.net/nux/+bug/745049
*
* So we need to update the state of the objects using the information
@@ -147,7 +147,7 @@ nux_base_window_accessible_ref_state_set(AtkObject* obj)
atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
- /* HasKeyboardFocus is not a reliable here:
+ /* HasKeyboardFocus is not reliable here:
see bug https://bugs.launchpad.net/nux/+bug/745049 */
if (self->priv->active)
{
@@ -162,7 +162,7 @@ nux_base_window_accessible_ref_state_set(AtkObject* obj)
static void
atk_window_interface_init(AtkWindowIface* iface)
{
- /* AtkWindow just define signals at this moment */
+ /* AtkWindow just defines signals at this moment */
}
/* public */
diff --git a/plugins/unityshell/src/nux-layout-accessible.cpp b/plugins/unityshell/src/nux-layout-accessible.cpp
index 8bec1d9e2..b706df620 100644
--- a/plugins/unityshell/src/nux-layout-accessible.cpp
+++ b/plugins/unityshell/src/nux-layout-accessible.cpp
@@ -24,7 +24,7 @@
*
* #NuxLayoutAccessible implements the required ATK interfaces of
* nux::Layout, implementing the container related methods on
- * AtkObject, in order to expose his objects
+ * AtkObject, in order to expose its objects
*
*/
@@ -203,7 +203,7 @@ search_for_child(AtkObject* accessible,
element_list = layout->GetChildren();
- for (it = element_list.begin(); it != element_list.end(); it++, result++)
+ for (it = element_list.begin(); it != element_list.end(); ++it, result++)
{
current_area = *it;
if (current_area == area)
diff --git a/plugins/unityshell/src/nux-object-accessible.cpp b/plugins/unityshell/src/nux-object-accessible.cpp
index ccdc4b1de..4e25c2963 100644
--- a/plugins/unityshell/src/nux-object-accessible.cpp
+++ b/plugins/unityshell/src/nux-object-accessible.cpp
@@ -23,7 +23,7 @@
* @see_also: nux::Object
*
* #NuxObjectAccessible implements the required ATK interfaces of
- * nux::Object, exposing the common elements on each basic individual
+ * nux::Object, exposing the common elements of each basic individual
* element (position, extents, etc)
*
*/
@@ -129,11 +129,11 @@ nux_object_accessible_initialize(AtkObject* accessible,
/**
* nux_object_accessible_get_object:
*
- * Returns the nux::Object this object is providing accessibility support.
+ * Returns the nux::Object this object is providing accessibility support for.
*
* Note that there isn't a _set method. This is because setting that
- * should only be done during initilization, and it doesn't make sense
- * to change that during the life of the object.
+ * should only be done during initialization, and it doesn't make sense
+ * to change that during the lifetime of the object.
*
*/
nux::Object*
diff --git a/plugins/unityshell/src/nux-view-accessible.cpp b/plugins/unityshell/src/nux-view-accessible.cpp
index d928ed315..7dd14eb49 100644
--- a/plugins/unityshell/src/nux-view-accessible.cpp
+++ b/plugins/unityshell/src/nux-view-accessible.cpp
@@ -165,7 +165,7 @@ nux_view_accessible_ref_state_set(AtkObject* obj)
if (nux_object == NULL) /* defunct */
return state_set;
- /* HasKeyboardFocus is not a reliable here:
+ /* HasKeyboardFocus is not reliable here:
see bug https://bugs.launchpad.net/nux/+bug/745049 */
if (self->priv->key_focused)
atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
@@ -262,7 +262,7 @@ on_change_keyboard_receiver_cb(AtkObject* accessible,
{
self->priv->key_focused = focus_in;
- /* we always led the focus notification to
+ /* we always lead the focus notification to
_check_pending_notification, in order to allow the proper
window_activate -> focus_change order */
self->priv->pending_notification = TRUE;
@@ -275,7 +275,7 @@ nux_view_accessible_check_pending_notification(NuxAreaAccessible* area_accessibl
NuxViewAccessible* self = NULL;
nux::Object* nux_object = NULL;
- /* We also call parent implementation, as we are not totally
+ /* We also call the parent implementation, as we are not totally
overriding check_pending_notification, just adding extra
functionality*/
NUX_AREA_ACCESSIBLE_CLASS(nux_view_accessible_parent_class)->check_pending_notification(area_accessible);
diff --git a/plugins/unityshell/src/unity-launcher-accessible.cpp b/plugins/unityshell/src/unity-launcher-accessible.cpp
index d20deed28..4cb4301ae 100644
--- a/plugins/unityshell/src/unity-launcher-accessible.cpp
+++ b/plugins/unityshell/src/unity-launcher-accessible.cpp
@@ -441,7 +441,7 @@ update_children_index(UnityLauncherAccessible* self)
if (launcher_model == NULL)
return;
- for (it = launcher_model->begin(); it != launcher_model->end(); it++)
+ for (it = launcher_model->begin(); it != launcher_model->end(); ++it)
{
child = dynamic_cast<nux::Object*>((*it).GetPointer());
child_accessible = unity_a11y_get_accessible(child);
diff --git a/plugins/unityshell/src/unity-launcher-icon-accessible.cpp b/plugins/unityshell/src/unity-launcher-icon-accessible.cpp
index 44b5051a7..b0331eb00 100644
--- a/plugins/unityshell/src/unity-launcher-icon-accessible.cpp
+++ b/plugins/unityshell/src/unity-launcher-icon-accessible.cpp
@@ -281,7 +281,7 @@ unity_launcher_icon_accessible_ref_state_set(AtkObject* obj)
icon = dynamic_cast<LauncherIcon*>(nux_object);
- if (icon->GetQuirk(LauncherIcon::QUIRK_VISIBLE))
+ if (icon->GetQuirk(LauncherIcon::Quirk::VISIBLE))
{
atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
diff --git a/plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp b/plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp
index 4d0258492..bdfd7fd81 100644
--- a/plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp
+++ b/plugins/unityshell/src/unity-quicklist-menu-item-accessible.cpp
@@ -210,7 +210,7 @@ unity_quicklist_menu_item_accessible_get_name(AtkObject* obj)
menu_item = dynamic_cast<QuicklistMenuItem*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
if (menu_item != NULL)
{
- name = menu_item->GetLabel();
+ name = menu_item->GetLabel().c_str();
}
}
diff --git a/plugins/unityshell/src/unity-root-accessible.cpp b/plugins/unityshell/src/unity-root-accessible.cpp
index 789f83210..681d676d6 100644
--- a/plugins/unityshell/src/unity-root-accessible.cpp
+++ b/plugins/unityshell/src/unity-root-accessible.cpp
@@ -395,7 +395,7 @@ register_interesting_messages(UnityRootAccessible* self)
sigc::bind(sigc::ptr_fun(ubus_launcher_register_interest_cb),
self));
- ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWTICHER,
+ ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWITCHER,
sigc::bind(sigc::ptr_fun(ubus_launcher_register_interest_cb),
self));
diff --git a/plugins/unityshell/src/unity-rvgrid-accessible.cpp b/plugins/unityshell/src/unity-rvgrid-accessible.cpp
index 0cc379419..4f7058843 100644
--- a/plugins/unityshell/src/unity-rvgrid-accessible.cpp
+++ b/plugins/unityshell/src/unity-rvgrid-accessible.cpp
@@ -146,8 +146,6 @@ check_selection(UnityRvgridAccessible* self)
{
AtkObject* child = NULL;
gint index = 0;
- ResultView::ResultList result_list;
- Result* result;
nux::Object* object = NULL;
ResultViewGrid* rvgrid = NULL;
std::string name;
@@ -162,13 +160,12 @@ check_selection(UnityRvgridAccessible* self)
rvgrid = dynamic_cast<ResultViewGrid*>(object);
- result_list = rvgrid->GetResultList();
index = rvgrid->GetSelectedIndex();
if (index >= 0)
{
- result = &result_list[index];
- name = result->name;
+ Result result(*rvgrid->GetIteratorAtRow(index));
+ name = result.name;
child = ATK_OBJECT(self->priv->result);
self->priv->has_selection = TRUE;
diff --git a/plugins/unityshell/src/unity-switcher-accessible.cpp b/plugins/unityshell/src/unity-switcher-accessible.cpp
index e4e2a968f..189e7d703 100644
--- a/plugins/unityshell/src/unity-switcher-accessible.cpp
+++ b/plugins/unityshell/src/unity-switcher-accessible.cpp
@@ -404,7 +404,7 @@ create_children(UnitySwitcherAccessible* self)
if (switcher_model == NULL)
return;
- for (it = switcher_model->begin(); it != switcher_model->end(); it++)
+ for (it = switcher_model->begin(); it != switcher_model->end(); ++it)
{
child = *it;
child_accessible = unity_launcher_icon_accessible_new(child.GetPointer());
diff --git a/plugins/unityshell/src/unitya11y.cpp b/plugins/unityshell/src/unitya11y.cpp
index fb0016f0d..1035af609 100644
--- a/plugins/unityshell/src/unitya11y.cpp
+++ b/plugins/unityshell/src/unitya11y.cpp
@@ -77,7 +77,6 @@ load_unity_atk_util(nux::WindowThread* wt)
g_type_class_unref(g_type_class_ref(UNITY_TYPE_UTIL_ACCESSIBLE));
}
-/********************************************************************************/
/*
* In order to avoid the atk-bridge loading and the GAIL
* initialization during the gtk_init, it is required to set some
@@ -108,17 +107,17 @@ unity_a11y_init(nux::WindowThread* wt)
a11y_initialized = TRUE;
-// NOTE: we run manually the unit tests while developing by
-// uncommenting this. Take a look to the explanation on
+// NOTE: we run the unit tests manually while developing by
+// uncommenting this. Take a look at the explanation in the
// unitya11ytests.h header for more information
// unity_run_a11y_unit_tests ();
}
/*
- * Finalize the related issues related with the accessibility.
+ * Finalize the issues related with accessibility.
*
- * It mainly clean the resources related with the accessibility
+ * It mainly cleans the resources related with accessibility
*/
void
unity_a11y_finalize(void)
@@ -143,9 +142,9 @@ unity_a11y_finalize(void)
* that would be add a ->get_accessible method on the nux::View
* subclasses itself.
*
- * WARNING: as a reason the previous comment it is true. Take into
- * account that you should be careful with the order you add those
- * defines. The order will be from more specific classes to more
+ * WARNING: as a reason the previous comment is true. Take into
+ * account that you should be careful with the order in which you add
+ * those defines. The order will be from more specific classes to more
* abstracted classes.
*
*/
@@ -211,7 +210,7 @@ on_object_destroy_cb(nux::Object* base_object,
AtkObject* accessible_object)
{
/* NOTE: the pair key:value (base_object:accessible_object) could be
- already removed on on_accessible_destroy_cb. That just mean that
+ already removed on on_accessible_destroy_cb. That just means that
g_hash_table_remove would return FALSE. We don't add a
debug/warning message to avoid being too verbose */
@@ -223,7 +222,7 @@ on_accessible_destroy_cb(gpointer data,
GObject* where_the_object_was)
{
/* NOTE: the pair key:value (base_object:accessible_object) could be
- already removed on on_object_destroy_cb. That just mean that
+ already removed on on_object_destroy_cb. That just means that
g_hash_table_remove would return FALSE. We don't add a
debug/warning message to avoid being too verbose */
@@ -234,9 +233,9 @@ on_accessible_destroy_cb(gpointer data,
* Returns the accessible object of a nux::View object
*
* This method tries to:
- * * Check if area has already a accessibility object
- * * If this is the case, returns that
- * * If not, creates it and return the object
+ * * Check if area already has a accessibility object
+ * * If this is the case, return that
+ * * If not, create it and return the object
*
* FIXME: this should be a temporal method. The best way to implement
* that would be add a ->get_accessible method on the nux::View
@@ -263,7 +262,7 @@ unity_a11y_get_accessible(nux::Object* object)
g_hash_table_insert(accessible_table, object, accessible_object);
/* there are two reasons the object should be removed from the
- * table: base object destroyed, or accessible object
+ * table: base object destroyed or accessible object
* destroyed
*/
g_object_weak_ref(G_OBJECT(accessible_object),
diff --git a/plugins/unityshell/src/unitya11ytests.cpp b/plugins/unityshell/src/unitya11ytests.cpp
index 20328a674..1ec2c1af0 100644
--- a/plugins/unityshell/src/unitya11ytests.cpp
+++ b/plugins/unityshell/src/unitya11ytests.cpp
@@ -48,7 +48,7 @@ using unity::launcher::SimpleLauncherIcon;
* This unit test checks if the destroy management is working:
*
* - If the state of a accessibility object is properly updated after
- * the object destruction
+ * the object's destruction
*
*/
static gboolean
@@ -224,7 +224,7 @@ a11y_unit_test_launcher_connection(void)
g_debug("[a11y] Launcher accessible created correctly");
}
- launcher_icon = new SimpleLauncherIcon();
+ launcher_icon = new SimpleLauncherIcon(unity::launcher::AbstractLauncherIcon::IconType::NONE);
launcher_icon->SinkReference();
launcher_icon_accessible = unity_a11y_get_accessible(launcher_icon);
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index 9290633e8..640fd3654 100644
--- a/plugins/unityshell/src/unityshell.cpp
+++ b/plugins/unityshell/src/unityshell.cpp
@@ -29,8 +29,6 @@
#include "Launcher.h"
#include "LauncherIcon.h"
#include "LauncherController.h"
-#include "GeisAdapter.h"
-#include "DevicesSettings.h"
#include "PluginAdapter.h"
#include "QuicklistManager.h"
#include "StartupNotifyService.h"
@@ -38,14 +36,16 @@
#include "KeyboardUtil.h"
#include "unityshell.h"
#include "BackgroundEffectHelper.h"
+#include "UnityGestureBroker.h"
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <libnotify/notify.h>
+#include <cairo-xlib-xrender.h>
+
+#include <text/text.h>
#include <sstream>
#include <memory>
@@ -83,6 +83,10 @@ nux::logging::Logger logger("unity.shell");
UnityScreen* uScreen = 0;
+static unsigned int CLOSE_ICON_SIZE = 19;
+static unsigned int CLOSE_ICON_SPACE = 5;
+static unsigned int SCALE_WINDOW_TITLE_SIZE = 28;
+
void reset_glib_logging();
void configure_logging();
void capture_g_log_calls(const gchar* log_domain,
@@ -103,15 +107,43 @@ const std::string RELAYOUT_TIMEOUT = "relayout-timeout";
} // namespace local
} // anon namespace
+class WindowCairoContext
+{
+ public:
+ Pixmap pixmap_;
+ cairo_surface_t* surface_;
+ GLTexture::List texture_;
+ cairo_t *cr_;
+
+ WindowCairoContext ()
+ : pixmap_ (0), surface_ (0), cr_ (0)
+ {
+ }
+
+ ~WindowCairoContext ()
+ {
+ if (cr_)
+ cairo_destroy (cr_);
+
+ if (surface_)
+ cairo_surface_destroy (surface_);
+
+ texture_.clear ();
+
+ if (pixmap_)
+ XFreePixmap (screen->dpy (), pixmap_);
+ }
+};
+
UnityScreen::UnityScreen(CompScreen* screen)
: BaseSwitchScreen (screen)
, PluginClassHandler <UnityScreen, CompScreen> (screen)
, screen(screen)
, cScreen(CompositeScreen::get(screen))
, gScreen(GLScreen::get(screen))
+ , animation_controller_(tick_source_)
, debugger_(this)
, enable_shortcut_overlay_(true)
- , gesture_engine_(screen)
, needsRelayout(false)
, _in_paint(false)
, super_keypressed_(false)
@@ -131,10 +163,14 @@ UnityScreen::UnityScreen(CompScreen* screen)
, panel_texture_has_changed_(true)
, paint_panel_(false)
, scale_just_activated_(false)
+ , highlighted_window_(0)
+ , minimize_speed_controller(new WindowMinimizeSpeedController())
{
Timer timer;
+#ifndef USE_GLES
gfloat version;
gchar* extensions;
+#endif
bool failed = false;
configure_logging();
LOG_DEBUG(logger) << __PRETTY_FUNCTION__;
@@ -203,8 +239,6 @@ UnityScreen::UnityScreen(CompScreen* screen)
{
notify_init("unityshell");
- dbus_g_thread_init();
-
unity_a11y_preset_environment();
XSetErrorHandler(old_handler);
@@ -214,10 +248,6 @@ UnityScreen::UnityScreen(CompScreen* screen)
CompositeScreenInterface::setHandler(cScreen);
GLScreenInterface::setHandler(gScreen);
-#ifdef USE_MODERN_COMPIZ_GL
- gScreen->glPaintCompositedOutputSetEnabled (this, true);
-#endif
-
PluginAdapter::Initialize(screen);
WindowManager::SetDefault(PluginAdapter::Default());
AddChild(PluginAdapter::Default());
@@ -287,7 +317,6 @@ UnityScreen::UnityScreen(CompScreen* screen)
optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
- optionSetDevicesOptionNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
@@ -300,6 +329,7 @@ UnityScreen::UnityScreen(CompScreen* screen)
optionSetAutomaximizeValueNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetAltTabTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetAltTabBiasViewportNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
+ optionSetDisableShowDesktopNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetAltTabForwardAllInitiate(boost::bind(&UnityScreen::altTabForwardAllInitiate, this, _1, _2, _3));
optionSetAltTabForwardInitiate(boost::bind(&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
@@ -337,6 +367,7 @@ UnityScreen::UnityScreen(CompScreen* screen)
optionSetOvercomePressureNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetDecayRateNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShowMinimizedWindowsNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
+ optionSetEdgePassedDisabledMsNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetNumLaunchersNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetLauncherCaptureMouseNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
@@ -344,13 +375,13 @@ UnityScreen::UnityScreen(CompScreen* screen)
ubus_manager_.RegisterInterest(UBUS_LAUNCHER_START_KEY_NAV,
sigc::mem_fun(this, &UnityScreen::OnLauncherStartKeyNav));
- ubus_manager_.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWTICHER,
+ ubus_manager_.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWITCHER,
sigc::mem_fun(this, &UnityScreen::OnLauncherStartKeyNav));
ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_NAV,
sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav));
- ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_SWTICHER,
+ ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_SWITCHER,
sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav));
ubus_manager_.RegisterInterest(UBUS_SWITCHER_START,
@@ -362,7 +393,7 @@ UnityScreen::UnityScreen(CompScreen* screen)
auto init_plugins_cb = sigc::mem_fun(this, &UnityScreen::initPluginActions);
sources_.Add(std::make_shared<glib::Idle>(init_plugins_cb, glib::Source::Priority::DEFAULT));
- geis_adapter_.Run();
+ InitGesturesSupport();
CompString name(PKGDATADIR"/panel-shadow.png");
CompString pname("unityshell");
@@ -390,6 +421,10 @@ UnityScreen::UnityScreen(CompScreen* screen)
}
panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged));
+
+ minimize_speed_controller->DurationChanged.connect(
+ sigc::mem_fun(this, &UnityScreen::OnMinimizeDurationChanged)
+ );
}
UnityScreen::~UnityScreen()
@@ -482,7 +517,7 @@ void UnityScreen::CreateSuperNewAction(char shortcut, impl::ActionModifiers flag
void UnityScreen::nuxPrologue()
{
-#ifndef USE_MODERN_COMPIZ_GL
+#ifndef USE_GLES
/* Vertex lighting isn't used in Unity, we disable that state as it could have
* been leaked by another plugin. That should theoretically be switched off
* right after PushAttrib since ENABLE_BIT is meant to restore the LIGHTING
@@ -499,6 +534,17 @@ void UnityScreen::nuxPrologue()
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
+
+#ifndef USE_MODERN_COMPIZ_GL
+ /* This is needed to Fix a crash in glDrawArrays with the NVIDIA driver
+ * see bugs #1031554 and #982626.
+ * The NVIDIA driver looks to see if the legacy GL_VERTEX_ARRAY,
+ * GL_TEXTURE_COORDINATES_ARRAY and other such client states are enabled
+ * first before checking if a vertex buffer is bound and will prefer the
+ * client buffers over the the vertex buffer object. */
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
#endif
glGetError();
@@ -506,8 +552,10 @@ void UnityScreen::nuxPrologue()
void UnityScreen::nuxEpilogue()
{
+#ifndef USE_GLES
#ifndef USE_MODERN_COMPIZ_GL
(*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo);
+#endif
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -528,6 +576,13 @@ void UnityScreen::nuxEpilogue()
glReadBuffer(GL_BACK);
glPopAttrib();
+
+#ifndef USE_MODERN_COMPIZ_GL
+ /* Re-enable the client states that have been disabled in nuxPrologue, for
+ * NVIDIA compatibility reasons */
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
#else
#ifdef USE_GLES
glDepthRangef(0, 1);
@@ -1202,6 +1257,11 @@ void UnityWindow::handleEvent (XEvent *event)
}
}
+CompRect UnityWindow::closeButtonArea ()
+{
+ return close_button_area_;
+}
+
bool UnityScreen::shellCouldBeHidden(CompOutput const& output)
{
std::vector<Window> const& nuxwins(nux::XInputWindow::NativeHandleList());
@@ -1210,7 +1270,7 @@ bool UnityScreen::shellCouldBeHidden(CompOutput const& output)
CompWindowList const& wins = screen->windows();
for ( CompWindowList::const_reverse_iterator r = wins.rbegin()
; r != wins.rend()
- ; r++
+ ; ++r
)
{
CompWindow* w = *r;
@@ -1292,41 +1352,19 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
/* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
-#ifndef USE_MODERN_COMPIZ_GL
if (doShellRepaint && !force && fullscreenRegion.contains(*output))
doShellRepaint = false;
if (doShellRepaint)
+#ifdef USE_MODERN_COMPIZ_GL
+ paintDisplay();
+#else
paintDisplay(region, transform, mask);
#endif
return ret;
}
-#ifdef USE_MODERN_COMPIZ_GL
-void UnityScreen::glPaintCompositedOutput (const CompRegion &region,
- ::GLFramebufferObject *fbo,
- unsigned int mask)
-{
- bool useFbo = false;
-
- if (doShellRepaint)
- {
- oldFbo = fbo->bind ();
- useFbo = fbo->checkStatus () && fbo->tex ();
- if (!useFbo) {
- printf ("bailing from UnityScreen::glPaintCompositedOutput");
- ::GLFramebufferObject::rebind (oldFbo);
- return;
- }
- paintDisplay();
- ::GLFramebufferObject::rebind (oldFbo);
- }
-
- gScreen->glPaintCompositedOutput(region, fbo, mask);
-}
-#endif
-
/* called whenever a plugin needs to paint the entire scene
* transformed */
@@ -1345,10 +1383,16 @@ void UnityScreen::preparePaint(int ms)
{
cScreen->preparePaint(ms);
+ // Emit the current time throught the tick_source. This moves any running
+ // animations along their path.
+ tick_source_.tick(g_get_monotonic_time());
+
for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
wi->HandleAnimations (ms);
+#ifndef USE_MODERN_COMPIZ_GL
compizDamageNux(cScreen->currentDamage());
+#endif
didShellRepaint = false;
firstWindowAboveShell = NULL;
@@ -1412,31 +1456,48 @@ void UnityScreen::compizDamageNux(CompRegion const& damage)
}
}
- auto launchers = launcher_controller_->launchers();
- for (auto launcher : launchers)
+ auto const& launchers = launcher_controller_->launchers();
+ for (auto const& launcher : launchers)
{
if (!launcher->Hidden())
{
- nux::Geometry geo = launcher->GetAbsoluteGeometry();
+ nux::Geometry const& geo = launcher->GetAbsoluteGeometry();
CompRegion launcher_region(geo.x, geo.y, geo.width, geo.height);
+
if (damage.intersects(launcher_region))
launcher->QueueDraw();
- nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
- if (!tooltip.IsNull())
+
+ nux::ObjectPtr<nux::View> const& tooltip = launcher->GetActiveTooltip();
+
+ if (tooltip)
{
- nux::Geometry tip = tooltip->GetAbsoluteGeometry();
- CompRegion tip_region(tip.x, tip.y, tip.width, tip.height);
+ nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
+ CompRegion tip_region(g.x, g.y, g.width, g.height);
+
if (damage.intersects(tip_region))
tooltip->QueueDraw();
}
+
+ nux::ObjectPtr<LauncherDragWindow> const& dragged_icon = launcher->GetDraggedIcon();
+
+ if (dragged_icon)
+ {
+ nux::Geometry const& g = dragged_icon->GetAbsoluteGeometry();
+ CompRegion icon_region(g.x, g.y, g.width, g.height);
+
+ if (damage.intersects(icon_region))
+ dragged_icon->QueueDraw();
+ }
}
}
std::vector<nux::View*> const& panels(panel_controller_->GetPanelViews());
for (nux::View* view : panels)
{
- nux::Geometry geo = view->GetAbsoluteGeometry();
+ nux::Geometry const& geo = view->GetAbsoluteGeometry();
+
CompRegion panel_region(geo.x, geo.y, geo.width, geo.height);
+
if (damage.intersects(panel_region))
view->QueueDraw();
}
@@ -1447,8 +1508,9 @@ void UnityScreen::compizDamageNux(CompRegion const& damage)
QuicklistView* view = qm->Current();
if (view)
{
- nux::Geometry geo = view->GetAbsoluteGeometry();
+ nux::Geometry const& geo = view->GetAbsoluteGeometry();
CompRegion quicklist_region(geo.x, geo.y, geo.width, geo.height);
+
if (damage.intersects(quicklist_region))
view->QueueDraw();
}
@@ -1458,6 +1520,29 @@ void UnityScreen::compizDamageNux(CompRegion const& damage)
/* Grab changed nux regions and add damage rects for them */
void UnityScreen::nuxDamageCompiz()
{
+#ifdef USE_MODERN_COMPIZ_GL
+ /*
+ * If Nux is going to redraw anything then we have to tell Compiz to
+ * redraw everything. This is because Nux has a bad habit (bug??) of drawing
+ * more than just the regions of its DrawList. (LP: #1036519)
+ *
+ * Forunately, this does not happen on most frames. Only when the Unity
+ * Shell needs to redraw something.
+ *
+ * TODO: Try to figure out why redrawing the panel makes the launcher also
+ * redraw even though the launcher's geometry is not in DrawList, and
+ * stop it. Then maybe we can revert back to the old code below #else.
+ */
+ std::vector<nux::Geometry> const& dirty = wt->GetDrawList();
+ if (!dirty.empty())
+ {
+ cScreen->damageRegionSetEnabled(this, false);
+ cScreen->damageScreen();
+ cScreen->damageRegionSetEnabled(this, true);
+ }
+
+#else
+
/*
* WARNING: Nux bug LP: #1014610 (unbounded DrawList growth) will cause
* this code to be called far too often in some cases and
@@ -1471,7 +1556,8 @@ void UnityScreen::nuxDamageCompiz()
CompRegion nux_damage;
std::vector<nux::Geometry> const& dirty = wt->GetDrawList();
- for (auto geo : dirty)
+
+ for (auto const& geo : dirty)
nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
if (launcher_controller_->IsOverlayOpen())
@@ -1481,23 +1567,33 @@ void UnityScreen::nuxDamageCompiz()
nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
}
- auto launchers = launcher_controller_->launchers();
- for (auto launcher : launchers)
+ auto const& launchers = launcher_controller_->launchers();
+ for (auto const& launcher : launchers)
{
if (!launcher->Hidden())
{
nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
- if (!tooltip.IsNull())
+
+ if (tooltip)
{
nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
nux_damage += CompRegion(g.x, g.y, g.width, g.height);
}
+
+ nux::ObjectPtr<LauncherDragWindow> const& dragged_icon = launcher->GetDraggedIcon();
+
+ if (dragged_icon)
+ {
+ nux::Geometry const& g = dragged_icon->GetAbsoluteGeometry();
+ nux_damage += CompRegion(g.x, g.y, g.width, g.height);
+ }
}
}
cScreen->damageRegionSetEnabled(this, false);
cScreen->damageRegion(nux_damage);
cScreen->damageRegionSetEnabled(this, true);
+#endif
}
/* handle X Events */
@@ -1533,6 +1629,24 @@ void UnityScreen::handleEvent(XEvent* event)
launcher_controller_->KeyNavTerminate(false);
EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, false);
}
+ if (PluginAdapter::Default()->IsScaleActive() &&
+ event->xbutton.button == Button1 &&
+ highlighted_window_ != 0)
+ {
+ CompWindow *w = screen->findWindow (highlighted_window_);
+ if (w)
+ {
+ UnityWindow *uw = UnityWindow::get (w);
+ CompPoint pointer (pointerX, pointerY);
+ if (uw->closeButtonArea ().contains (pointer))
+ {
+ w->close (0);
+ skip_other_plugins = true;
+ }
+ }
+
+ }
+
break;
case ButtonRelease:
if (switcher_controller_ && switcher_controller_->Visible())
@@ -1857,6 +1971,21 @@ bool UnityScreen::altTabInitiateCommon(CompAction* action, switcher::ShowMode sh
screen->addAction(&scroll_up);
screen->addAction(&scroll_down);
+ if (!optionGetAltTabBiasViewport())
+ {
+ if (show_mode == switcher::ShowMode::CURRENT_VIEWPORT)
+ show_mode = switcher::ShowMode::ALL;
+ else
+ show_mode = switcher::ShowMode::CURRENT_VIEWPORT;
+ }
+
+ SetUpAndShowSwitcher(show_mode);
+
+ return true;
+}
+
+void UnityScreen::SetUpAndShowSwitcher(switcher::ShowMode show_mode)
+{
// maybe check launcher position/hide state?
WindowManager *wm = WindowManager::Default();
@@ -1868,22 +1997,13 @@ bool UnityScreen::altTabInitiateCommon(CompAction* action, switcher::ShowMode sh
monitor_geo.height -= 200;
switcher_controller_->SetWorkspace(monitor_geo, monitor);
- if (!optionGetAltTabBiasViewport())
- {
- if (show_mode == switcher::ShowMode::CURRENT_VIEWPORT)
- show_mode = switcher::ShowMode::ALL;
- else
- show_mode = switcher::ShowMode::CURRENT_VIEWPORT;
- }
-
RaiseInputWindows();
- auto results = launcher_controller_->GetAltTabIcons(show_mode == switcher::ShowMode::CURRENT_VIEWPORT);
+ auto results = launcher_controller_->GetAltTabIcons(show_mode == switcher::ShowMode::CURRENT_VIEWPORT,
+ switcher_controller_->IsShowDesktopDisabled());
- if (!(results.size() == 1 && results[0]->GetIconType() == AbstractLauncherIcon::IconType::TYPE_DESKTOP))
+ if (switcher_controller_->CanShowSwitcher(results))
switcher_controller_->Show(show_mode, switcher::SortMode::FOCUS_ORDER, false, results);
-
- return true;
}
bool UnityScreen::altTabTerminateCommon(CompAction* action,
@@ -1934,7 +2054,9 @@ bool UnityScreen::altTabForwardAllInitiate(CompAction* action,
CompAction::State state,
CompOption::Vector& options)
{
- if (switcher_controller_->Visible())
+ if (WindowManager::Default()->IsWallActive())
+ return false;
+ else if (switcher_controller_->Visible())
switcher_controller_->Next();
else
altTabInitiateCommon(action, switcher::ShowMode::ALL);
@@ -1992,7 +2114,7 @@ bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State
if (!switcher_controller_->Visible())
{
altTabInitiateCommon(action, switcher::ShowMode::CURRENT_VIEWPORT);
- switcher_controller_->Select(1); // always select the current application
+ switcher_controller_->Select((switcher_controller_->StartIndex())); // always select the current application
}
switcher_controller_->NextDetail();
@@ -2165,10 +2287,9 @@ bool UnityScreen::ShowHudInitiate(CompAction* action,
{
// Look to see if there is a keycode. If there is, then this isn't a
// modifier only keybinding.
- int key_code = 0;
if (options[6].type() != CompOption::TypeUnset)
{
- key_code = options[6].value().i();
+ int key_code = options[6].value().i();
LOG_DEBUG(logger) << "HUD initiate key code: " << key_code;
// show it now, no timings or terminate needed.
return ShowHud();
@@ -2319,7 +2440,7 @@ bool isNuxWindow (CompWindow* value)
auto id = value->id();
// iterate loop by hand rather than use std::find as this is considerably faster
- // we care about performance here becuase of the high frequency in which this function is
+ // we care about performance here because of the high frequency in which this function is
// called (nearly every frame)
unsigned int size = xwns.size();
for (unsigned int i = 0; i < size; ++i)
@@ -2483,6 +2604,40 @@ bool UnityWindow::glDraw(const GLMatrix& matrix,
}
void
+UnityScreen::OnMinimizeDurationChanged ()
+{
+ /* Update the compiz plugin setting with the new computed speed so that it
+ * will be used in the following minimizations */
+ CompPlugin *p = CompPlugin::find("animation");
+ if (p)
+ {
+ CompOption::Vector &opts = p->vTable->getOptions();
+
+ for (CompOption &o : opts)
+ {
+ if (o.name () == std::string ("minimize_durations"))
+ {
+ /* minimize_durations is a list value, but minimize applies only to
+ * normal windows, so there's always one value */
+ CompOption::Value& value = o.value();
+ CompOption::Value::Vector& list = value.list();
+ CompOption::Value::Vector::iterator i = list.begin();
+ if (i != list.end()) {
+ i->set(minimize_speed_controller->getDuration());
+ }
+ value.set(list);
+ screen->setOptionForPlugin(p->vTable->name().c_str(),
+ o.name().c_str(), value);
+ break;
+ }
+ }
+ }
+ else {
+ LOG_WARN(logger) << "Animation plugin not found. Can't set minimize speed.";
+ }
+}
+
+void
UnityWindow::minimize ()
{
if (!window->managed ())
@@ -2595,6 +2750,14 @@ void UnityWindow::windowNotify(CompWindowNotify n)
window->minimizedSetEnabled (this, false);
}
break;
+ case CompWindowNotifyBeforeDestroy:
+ being_destroyed.emit();
+ break;
+ case CompWindowNotifyMinimize:
+ /* Updating the count in dconf will trigger a "changed" signal to which
+ * the method setting the new animation speed is attached */
+ UnityScreen::get(screen)->minimize_speed_controller->UpdateCount();
+ break;
default:
break;
}
@@ -2863,14 +3026,14 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num)
case UnityshellOptions::AutomaximizeValue:
PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);
break;
- case UnityshellOptions::DevicesOption:
- unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption());
- break;
case UnityshellOptions::AltTabTimeout:
switcher_controller_->detail_on_timeout = optionGetAltTabTimeout();
case UnityshellOptions::AltTabBiasViewport:
PluginAdapter::Default()->bias_active_to_viewport = optionGetAltTabBiasViewport();
break;
+ case UnityshellOptions::DisableShowDesktop:
+ switcher_controller_->SetShowDesktopDisabled(optionGetDisableShowDesktop());
+ break;
case UnityshellOptions::ShowMinimizedWindows:
compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::setFunctions (optionGetShowMinimizedWindows ());
screen->enterShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
@@ -2894,9 +3057,13 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num)
break;
case UnityshellOptions::RevealPressure:
launcher_options->edge_reveal_pressure = optionGetRevealPressure() * 100;
+ break;
case UnityshellOptions::EdgeResponsiveness:
launcher_options->edge_responsiveness = optionGetEdgeResponsiveness();
break;
+ case UnityshellOptions::EdgePassedDisabledMs:
+ launcher_options->edge_passed_disabled_ms = optionGetEdgePassedDisabledMs();
+ break;
default:
break;
}
@@ -3037,6 +3204,16 @@ void UnityScreen::initLauncher()
ScheduleRelayout(0);
}
+switcher::Controller::Ptr UnityScreen::switcher_controller()
+{
+ return switcher_controller_;
+}
+
+launcher::Controller::Ptr UnityScreen::launcher_controller()
+{
+ return launcher_controller_;
+}
+
void UnityScreen::InitHints()
{
// TODO move category text into a vector...
@@ -3044,58 +3221,243 @@ void UnityScreen::InitHints()
// Launcher...
std::string const launcher(_("Launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" (Press)"), _("Open Launcher, displays shortcuts."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher" ));
- hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "", _("Open Launcher keyboard navigation mode."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "keyboard_focus"));
- hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "", _("Switch applications via Launcher."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "launcher_switcher_forward"));
- hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + 1 to 9"), _("Same as clicking on a Launcher icon."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + Shift + 1 to 9"), _("Open new window of the app."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", " + T", _("Open the Trash."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
+ hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" (Hold)"),
+ _("Opens the Launcher, displays shortcuts."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher" ));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "",
+ _("Opens Launcher keyboard navigation mode."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "keyboard_focus"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "",
+ _("Switches applications via the Launcher."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "launcher_switcher_forward"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + 1 to 9"),
+ _("Same as clicking on a Launcher icon."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + Shift + 1 to 9"),
+ _("Opens a new window in the app."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", " + T",
+ _("Opens the Trash."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
// Dash...
std::string const dash( _("Dash"));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", _(" (Tap)"), _("Open the Dash Home."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + A", _("Open the Dash App Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + F", _("Open the Dash Files Lens."), shortcut::COMPIZ_KEY_OPTION,"unityshell", "show_launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + M", _("Open the Dash Music Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Switches between Lenses."), shortcut::HARDCODED_OPTION, _("Ctrl + Tab")));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Keys")));
- hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Open currently focused item."), shortcut::HARDCODED_OPTION, _("Enter & Return")));
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", _(" (Tap)"),
+ _("Opens the Dash Home."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + A",
+ _("Opens the Dash App Lens."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + F",
+ _("Opens the Dash Files Lens."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + M",
+ _("Opens the Dash Music Lens."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + V",
+ _("Opens the Dash Video Lens."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_launcher"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "",
+ _("Switches between Lenses."),
+ shortcut::HARDCODED_OPTION,
+ _("Ctrl + Tab")));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "",
+ _("Moves the focus."),
+ shortcut::HARDCODED_OPTION,
+ _("Arrow Keys")));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "",
+ _("Opens the currently focused item."),
+ shortcut::HARDCODED_OPTION,
+ _("Enter")));
// Menu Bar
std::string const menubar(_("HUD & Menu Bar"));
- hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Tap)"), _("Open the HUD."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_hud"));
- hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Press)"), _("Reveals application menu."), shortcut::HARDCODED_OPTION, "Alt"));
- hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "", _("Opens the indicator menu."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "panel_first_menu"));
- hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "", _("Moves focus between indicators."), shortcut::HARDCODED_OPTION, _("Cursor Left or Right")));
+ hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Tap)"),
+ _("Opens the HUD."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "show_hud"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", " (Hold)",
+ _("Reveals the application menu."),
+ shortcut::HARDCODED_OPTION,
+ "Alt"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "",
+ _("Opens the indicator menu."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "panel_first_menu"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "",
+ _("Moves focus between indicators."),
+ shortcut::HARDCODED_OPTION,
+ _("Cursor Left or Right")));
// Switching
std::string const switching(_("Switching"));
- hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "", _("Switch between applications."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_forward"));
- hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "", _("Switch windows of current application."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_next_window"));
- hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Left or Right")));
+ hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "",
+ _("Switches between applications."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "alt_tab_forward"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "",
+ _("Switches windows of current applications."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "unityshell",
+ "alt_tab_next_window"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "",
+ _("Moves the focus."),
+ shortcut::HARDCODED_OPTION,
+ _("Cursor Left or Right")));
// Workspaces
std::string const workspaces(_("Workspaces"));
- hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", "", _("Spread workspaces."), shortcut::COMPIZ_KEY_OPTION, "expo", "expo_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", _(" + Cursor Keys"), _("Switch workspaces."), shortcut::COMPIZ_METAKEY_OPTION, "wall", "left_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", _(" + Cursor Keys"), _("Move focused window to different workspace."), shortcut::COMPIZ_METAKEY_OPTION, "wall", "left_window_key"));
+ hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", "",
+ _("Switches between workspaces."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "expo",
+ "expo_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", _(" + Arrow Keys"),
+ _("Switches workspaces."),
+ shortcut::COMPIZ_METAKEY_OPTION,
+ "wall",
+ "left_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", _(" + Arrow Keys"),
+ _("Moves focused window to another workspace."),
+ shortcut::COMPIZ_METAKEY_OPTION,
+ "wall",
+ "left_window_key"));
+
// Windows
std::string const windows(_("Windows"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Spreads all windows in the current workspace."), shortcut::COMPIZ_KEY_OPTION, "scale", "initiate_all_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Minimises all windows."), shortcut::COMPIZ_KEY_OPTION, "core", "show_desktop_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Maximises the current window."), shortcut::COMPIZ_KEY_OPTION, "core", "maximize_window_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Restores or minimises current window."), shortcut::COMPIZ_KEY_OPTION, "core", "unmaximize_window_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" or Right"), _("Semi-maximises current window."), shortcut::COMPIZ_KEY_OPTION, "grid", "put_left_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Closes current window."), shortcut::COMPIZ_KEY_OPTION, "core", "close_window_key"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Opens window accessibility menu."), shortcut::HARDCODED_OPTION, _("Alt + Space")));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "", _("Places window in corresponding positions."), shortcut::HARDCODED_OPTION, _("Ctrl + Alt + Num")));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Move window."), shortcut::COMPIZ_MOUSE_OPTION, "move", "initiate_button"));
- hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button"));
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Spreads all windows in the current workspace."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "scale",
+ "initiate_all_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Minimises all windows."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "core",
+ "show_desktop_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Maximises the current window."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "core",
+ "maximize_window_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Restores or minimises the current window."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "core",
+ "unmaximize_window_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" or Right"),
+ _("Semi-maximise the current window."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "grid",
+ "put_left_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Closes the current window."),
+ shortcut::COMPIZ_KEY_OPTION,
+ "core",
+ "close_window_key"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Opens the window accessibility menu."),
+ shortcut::HARDCODED_OPTION,
+ _("Alt + Space")));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
+ _("Places the window in corresponding position."),
+ shortcut::HARDCODED_OPTION,
+ _("Ctrl + Alt + Num")));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"),
+ _("Moves the window."),
+ shortcut::COMPIZ_MOUSE_OPTION,
+ "move",
+ "initiate_button"));
+
+ hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"),
+ _("Resizes the window."),
+ shortcut::COMPIZ_MOUSE_OPTION,
+ "resize",
+ "initiate_button"));
+}
+
+void UnityScreen::InitGesturesSupport()
+{
+ std::unique_ptr<nux::GestureBroker> gesture_broker(new UnityGestureBroker);
+ wt->GetWindowCompositor().SetGestureBroker(std::move(gesture_broker));
+
+ gestures_sub_launcher_.reset(new nux::GesturesSubscription);
+ gestures_sub_launcher_->SetGestureClasses(nux::DRAG_GESTURE);
+ gestures_sub_launcher_->SetNumTouches(4);
+ gestures_sub_launcher_->SetWindowId(GDK_ROOT_WINDOW());
+ gestures_sub_launcher_->Activate();
+
+ gestures_sub_dash_.reset(new nux::GesturesSubscription);
+ gestures_sub_dash_->SetGestureClasses(nux::TAP_GESTURE);
+ gestures_sub_dash_->SetNumTouches(4);
+ gestures_sub_dash_->SetWindowId(GDK_ROOT_WINDOW());
+ gestures_sub_dash_->Activate();
+
+ gestures_sub_windows_.reset(new nux::GesturesSubscription);
+ gestures_sub_windows_->SetGestureClasses(nux::TOUCH_GESTURE
+ | nux::DRAG_GESTURE
+ | nux::PINCH_GESTURE);
+ gestures_sub_windows_->SetNumTouches(3);
+ gestures_sub_windows_->SetWindowId(GDK_ROOT_WINDOW());
+ gestures_sub_windows_->Activate();
}
/* Window init */
@@ -3106,9 +3468,11 @@ UnityWindow::UnityWindow(CompWindow* window)
, gWindow(GLWindow::get(window))
, mMinimizeHandler()
, mShowdesktopHandler(nullptr)
+ , window_header_style_(0)
{
WindowInterface::setHandler(window);
GLWindowInterface::setHandler(gWindow);
+ ScaleWindowInterface::setHandler (ScaleWindow::get (window));
if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
window->mapNum ())
@@ -3153,6 +3517,292 @@ UnityWindow::UnityWindow(CompWindow* window)
}
}
+void UnityWindow::DrawTexture (GLTexture* icon,
+ const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ unsigned int mask,
+ float x, float y,
+ int &maxWidth, int &maxHeight)
+{
+ if (icon)
+ {
+ int width, height;
+ width = icon->width ();
+ height = icon->height ();
+
+ if (height > maxHeight)
+ maxHeight = height;
+
+ if (width > maxWidth)
+ maxWidth = width;
+
+ CompRegion iconReg (0, 0, width, height);
+ GLTexture::MatrixList ml (1);
+
+ ml[0] = icon->matrix ();
+ gWindow->vertexBuffer ()->begin ();
+ if (width && height)
+ gWindow->glAddGeometry (ml, iconReg, iconReg);
+
+ if (gWindow->vertexBuffer ()->end ())
+ {
+ GLMatrix wTransform (transform);
+
+ wTransform.translate (x, y, 0.0f);
+
+ gWindow->glDrawTexture (icon, wTransform, attrib, mask);
+ }
+ }
+}
+
+WindowCairoContext* UnityWindow::CreateCairoContext (float width, float height)
+{
+ XRenderPictFormat *format;
+ Screen *xScreen;
+ WindowCairoContext *context = new WindowCairoContext();
+
+ xScreen = ScreenOfDisplay (screen->dpy (), screen->screenNum ());
+
+ format = XRenderFindStandardFormat (screen->dpy (), PictStandardARGB32);
+ context->pixmap_ = XCreatePixmap (screen->dpy (),
+ screen->root (),
+ width, height, 32);
+
+ context->texture_ = GLTexture::bindPixmapToTexture (context->pixmap_,
+ width, height,
+ 32);
+ if (context->texture_.empty ())
+ {
+ delete context;
+ return 0;
+ }
+
+ context->surface_ = cairo_xlib_surface_create_with_xrender_format (screen->dpy (),
+ context->pixmap_,
+ xScreen,
+ format,
+ width,
+ height);
+ context->cr_ = cairo_create (context->surface_);
+
+ // clear
+ cairo_save (context->cr_);
+ cairo_set_operator (context->cr_, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (context->cr_);
+ cairo_restore (context->cr_);
+
+ return context;
+}
+
+void UnityWindow::RenderText (WindowCairoContext *context,
+ float x, float y,
+ float maxWidth, float maxHeight)
+{
+ PangoFontDescription* font = pango_font_description_new ();
+ pango_font_description_set_family (font, "sans");
+ pango_font_description_set_absolute_size (font, 12 * PANGO_SCALE);
+ pango_font_description_set_style (font, PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight (font, PANGO_WEIGHT_BOLD);
+
+ PangoLayout* layout = pango_cairo_create_layout (context->cr_);
+ pango_layout_set_font_description (layout, font);
+ pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+ pango_layout_set_height (layout, maxHeight);
+
+ pango_layout_set_auto_dir (layout, false);
+ pango_layout_set_text (layout,
+ GetWindowName (window->id ()).c_str (),
+ -1);
+
+ /* update the size of the pango layout */
+ pango_layout_set_width (layout, maxWidth * PANGO_SCALE);
+ pango_cairo_update_layout (context->cr_, layout);
+
+ cairo_set_operator (context->cr_, CAIRO_OPERATOR_OVER);
+
+ cairo_set_source_rgba (context->cr_,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0);
+
+ // alignment
+ int lWidth, lHeight;
+ pango_layout_get_pixel_size (layout, &lWidth, &lHeight);
+
+ y = ((maxHeight - lHeight) / 2.0) + y;
+ cairo_translate (context->cr_, x, y);
+ pango_cairo_show_layout (context->cr_, layout);
+}
+
+void UnityWindow::DrawWindowTitle (const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ unsigned int mask,
+ float x, float y, float x2, float y2)
+{
+ const float width = x2 - x;
+
+ // Paint a fake window decoration
+ WindowCairoContext *context = CreateCairoContext (width, SCALE_WINDOW_TITLE_SIZE);
+
+ cairo_save (context->cr_);
+ cairo_push_group (context->cr_);
+
+ // Round window decoration top border
+ const double height = SCALE_WINDOW_TITLE_SIZE;
+ const double aspect = 1.0;
+ const double corner_radius = height / 10.0;
+ const double radius = corner_radius / aspect;
+ const double degrees = M_PI / 180.0;
+
+ cairo_new_sub_path (context->cr_);
+
+ cairo_arc (context->cr_, radius, radius, radius, 180 * degrees, 270 * degrees);
+ cairo_arc (context->cr_, width - radius, radius, radius, -90 * degrees, 0 * degrees);
+ cairo_line_to (context->cr_, width, height);
+ cairo_line_to (context->cr_, 0, height);
+
+ cairo_close_path (context->cr_);
+ cairo_clip (context->cr_);
+
+ // Draw window decoration abased on gtk style
+ gtk_render_background (window_header_style_, context->cr_, 0, 0, width, SCALE_WINDOW_TITLE_SIZE);
+ gtk_render_frame (window_header_style_, context->cr_, 0, 0, width, SCALE_WINDOW_TITLE_SIZE);
+
+ cairo_pop_group_to_source (context->cr_);
+
+ cairo_paint_with_alpha (context->cr_, 1.0);
+ cairo_restore (context->cr_);
+
+ // Draw windows title
+ RenderText (context,
+ CLOSE_ICON_SPACE * 2 + CLOSE_ICON_SIZE,
+ 0.0,
+ width, SCALE_WINDOW_TITLE_SIZE);
+
+ mask |= PAINT_WINDOW_BLEND_MASK;
+ int maxWidth, maxHeight;
+ foreach(GLTexture *icon, context->texture_)
+ {
+ DrawTexture (icon, attrib, transform, mask,
+ x, y,
+ maxWidth , maxHeight);
+ }
+
+ delete context;
+}
+
+void UnityWindow::scalePaintDecoration (const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ const CompRegion& region,
+ unsigned int mask)
+{
+ ScaleWindow *sWindow = ScaleWindow::get (window);
+ if (!sWindow)
+ return;
+
+ sWindow->scalePaintDecoration (attrib, transform, region, mask);
+
+ if (!sWindow->hasSlot()) // animation not finished
+ return;
+
+ if (!window_header_style_)
+ {
+ GtkWidgetPath* widget_path = gtk_widget_path_new ();
+ gint pos = gtk_widget_path_append_type (widget_path, GTK_TYPE_WINDOW);
+ gtk_widget_path_iter_set_name (widget_path, pos, "UnityPanelWidget");
+
+ window_header_style_ = gtk_style_context_new ();
+ gtk_style_context_set_path (window_header_style_, widget_path);
+ gtk_style_context_add_class (window_header_style_, "gnome-panel-menu-bar");
+ gtk_style_context_add_class (window_header_style_, "unity-panel");
+
+ // get close button
+ panel::Style& style = panel::Style::Instance();
+
+ std::vector<std::string> files = style.GetWindowButtonFileNames (panel::WindowButtonType::CLOSE,
+ panel::WindowState::NORMAL);
+
+ CompString pName ("unityshell");
+ foreach (std::string file, files)
+ {
+ CompString fileName (file.c_str ());
+ CompSize size (CLOSE_ICON_SIZE, CLOSE_ICON_SIZE);
+ close_icon_ = GLTexture::readImageToTexture (fileName,
+ pName,
+ size);
+ if (close_icon_.size () != 0)
+ break;
+ }
+
+ if (close_icon_.size () == 0)
+ {
+ CompString fileName (PKGDATADIR"/close_dash.png");
+ CompSize size (CLOSE_ICON_SIZE, CLOSE_ICON_SIZE);
+ close_icon_ = GLTexture::readImageToTexture (fileName,
+ pName,
+ size);
+ }
+ }
+
+ // Make the windows header opaque to override the original
+ GLWindowPaintAttrib sAttrib (attrib);
+ sAttrib.opacity = OPAQUE;
+
+ ScalePosition pos = sWindow->getCurrentPosition ();
+ int maxHeight, maxWidth;
+ // Use "2" as margin to make sure to cover all originial decoration
+ const float width = (window->width () + 4) * pos.scale;
+ const float x = pos.x () + window->x () - (2 * pos.scale);
+ const float y = pos.y () + window->y () - SCALE_WINDOW_TITLE_SIZE;
+ const float iconX = x + CLOSE_ICON_SPACE;
+ const float iconY = y + ((SCALE_WINDOW_TITLE_SIZE - CLOSE_ICON_SIZE) / 2.0);
+
+ maxHeight = maxWidth = 0;
+
+ DrawWindowTitle (sAttrib,
+ transform,
+ mask,
+ x, y,
+ x + width, y + SCALE_WINDOW_TITLE_SIZE);
+
+ mask |= PAINT_WINDOW_BLEND_MASK;
+ foreach(GLTexture *icon, close_icon_)
+ {
+ DrawTexture (icon, sAttrib, transform, mask,
+ iconX, iconY,
+ maxWidth , maxHeight);
+ }
+
+ close_button_area_ = CompRect (iconX, iconY, maxWidth, maxHeight);
+}
+
+void UnityWindow::scaleSelectWindow ()
+{
+ UnityScreen* us = UnityScreen::get(screen);
+
+ if (us->highlighted_window_ != window->id ())
+ {
+ CompositeWindow *cWindow = CompositeWindow::get (window);
+ if (cWindow)
+ cWindow->addDamage ();
+
+ cWindow = 0;
+ CompWindow *old_window = screen->findWindow (us->highlighted_window_);
+ if (old_window)
+ cWindow = CompositeWindow::get (old_window);
+
+ if (cWindow)
+ cWindow->addDamage ();
+
+ us->highlighted_window_ = window->id ();
+ }
+
+ ScaleWindow *sWindow = ScaleWindow::get (window);
+ if (sWindow)
+ sWindow->scaleSelectWindow ();
+}
+
UnityWindow::~UnityWindow()
{
UnityScreen* us = UnityScreen::get(screen);
@@ -3171,6 +3821,9 @@ UnityWindow::~UnityWindow()
window->minimize ();
}
+ if (window_header_style_)
+ g_object_unref (window_header_style_);
+
ShowdesktopHandler::animating_windows.remove (static_cast <ShowdesktopHandlerWindowInterface *> (this));
if (mShowdesktopHandler)
@@ -3210,6 +3863,84 @@ bool UnityPluginVTable::init()
return true;
}
+CompString UnityWindow::GetUtf8Property (Window id,
+ Atom atom)
+{
+ Atom type;
+ int result, format;
+ unsigned long nItems, bytesAfter;
+ char *val;
+ CompString retval;
+ Atom utf8StringAtom;
+
+ utf8StringAtom = XInternAtom (screen->dpy (), "UTF8_STRING", 0);
+ result = XGetWindowProperty (screen->dpy (), id, atom, 0L, 65536, False,
+ utf8StringAtom, &type, &format, &nItems,
+ &bytesAfter, (unsigned char **) &val);
+
+ if (result != Success)
+ return retval;
+
+ if (type == utf8StringAtom && format == 8 && val && nItems > 0)
+ {
+ char valueString[nItems + 1];
+ strncpy (valueString, val, nItems);
+ valueString[nItems] = 0;
+ retval = valueString;
+ }
+ if (val)
+ XFree (val);
+
+ return retval;
+}
+
+CompString UnityWindow::GetTextProperty (Window id,
+ Atom atom)
+{
+ XTextProperty text;
+ CompString retval;
+
+ text.nitems = 0;
+ if (XGetTextProperty (screen->dpy (), id, &text, atom))
+ {
+ if (text.value)
+ {
+ char valueString[text.nitems + 1];
+
+ strncpy (valueString, (char *) text.value, text.nitems);
+ valueString[text.nitems] = 0;
+
+ retval = valueString;
+
+ XFree (text.value);
+ }
+ }
+
+ return retval;
+}
+
+
+CompString UnityWindow::GetWindowName (Window id)
+{
+ CompString name;
+ Atom visibleNameAtom;
+
+ visibleNameAtom = XInternAtom (screen->dpy (), "_NET_WM_VISIBLE_NAME", 0);
+ name = GetUtf8Property (id, visibleNameAtom);
+ if (name.empty ())
+ {
+ Atom wmNameAtom = XInternAtom (screen->dpy (), "_NET_WM_NAME", 0);
+ name = GetUtf8Property (id, wmNameAtom);
+ }
+
+
+ if (name.empty ())
+ name = GetTextProperty (id, XA_WM_NAME);
+
+ return name;
+}
+
+
namespace
{
diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h
index 34e29975e..b9bea314a 100644
--- a/plugins/unityshell/src/unityshell.h
+++ b/plugins/unityshell/src/unityshell.h
@@ -22,11 +22,14 @@
#ifndef UNITYSHELL_H
#define UNITYSHELL_H
+#include <NuxCore/AnimationController.h>
+#include <Nux/GesturesSubscription.h>
#include <Nux/WindowThread.h>
#include <NuxCore/Property.h>
#include <sigc++/sigc++.h>
#include <boost/shared_ptr.hpp>
+#include <scale/scale.h>
#include <core/core.h>
#include <core/pluginclasshandler.h>
#include <composite/composite.h>
@@ -46,12 +49,12 @@
#include "PanelController.h"
#include "PanelStyle.h"
#include "UScreen.h"
-#include "GestureEngine.h"
#include "DebugDBusInterface.h"
#include "SwitcherController.h"
#include "UBusWrapper.h"
#include "UnityshellPrivate.h"
#include "UnityShowdesktopHandler.h"
+#include "ThumbnailGenerator.h"
#ifndef USE_MODERN_COMPIZ_GL
#include "ScreenEffectFramebufferObject.h"
#endif
@@ -62,10 +65,14 @@
#include <dlfcn.h>
#include "HudController.h"
+#include "ThumbnailGenerator.h"
+#include "WindowMinimizeSpeedController.h"
namespace unity
{
+class WindowCairoContext;
+
/* base screen class */
class UnityScreen :
public unity::debug::Introspectable,
@@ -122,11 +129,6 @@ public:
const CompRegion&,
CompOutput*,
unsigned int);
-#ifdef USE_MODERN_COMPIZ_GL
- void glPaintCompositedOutput (const CompRegion &region,
- ::GLFramebufferObject *fbo,
- unsigned int mask);
-#endif
/* paint in the special case that the output is transformed */
void glPaintTransformedOutput(const GLScreenPaintAttrib&,
@@ -190,6 +192,13 @@ public:
bool forcePaintOnTop ();
+ void SetUpAndShowSwitcher(switcher::ShowMode show_mode = switcher::ShowMode::CURRENT_VIEWPORT);
+
+ void OnMinimizeDurationChanged();
+
+ switcher::Controller::Ptr switcher_controller();
+ launcher::Controller::Ptr launcher_controller();
+
protected:
std::string GetName() const;
void AddProperties(GVariantBuilder* builder);
@@ -239,12 +248,17 @@ private:
void OnPanelStyleChanged();
+ void InitGesturesSupport();
+
+ nux::animation::TickSource tick_source_;
+ nux::animation::AnimationController animation_controller_;
+
Settings dash_settings_;
dash::Style dash_style_;
panel::Style panel_style_;
FontSettings font_settings_;
- GeisAdapter geis_adapter_;
internal::FavoriteStoreGSettings favorite_store_;
+ ThumbnailGenerator thumbnail_generator_;
/* The window thread should be the last thing removed, as c++ does it in reverse order */
std::unique_ptr<nux::WindowThread> wt;
@@ -261,7 +275,15 @@ private:
std::list<shortcut::AbstractHint::Ptr> hints_;
bool enable_shortcut_overlay_;
- GestureEngine gesture_engine_;
+ /* Subscription for gestures that manipulate Unity launcher */
+ std::unique_ptr<nux::GesturesSubscription> gestures_sub_launcher_;
+
+ /* Subscription for gestures that manipulate Unity dash */
+ std::unique_ptr<nux::GesturesSubscription> gestures_sub_dash_;
+
+ /* Subscription for gestures that manipulate windows. */
+ std::unique_ptr<nux::GesturesSubscription> gestures_sub_windows_;
+
bool needsRelayout;
bool _in_paint;
bool super_keypressed_;
@@ -323,7 +345,11 @@ private:
UBusManager ubus_manager_;
glib::SourceManager sources_;
+ unity::ThumbnailGenerator thumb_generator;
+ Window highlighted_window_;
+
+ WindowMinimizeSpeedController* minimize_speed_controller;
friend class UnityWindow;
};
@@ -332,6 +358,7 @@ class UnityWindow :
public GLWindowInterface,
public ShowdesktopHandlerWindowInterface,
public compiz::WindowInputRemoverLockAcquireInterface,
+ public WrapableHandler<ScaleWindowInterface, 4>,
public BaseSwitchWindow,
public PluginClassHandler <UnityWindow, CompWindow>
{
@@ -392,12 +419,23 @@ public:
void handleEvent (XEvent *event);
+ CompRect closeButtonArea ();
+
typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>
UnityMinimizedHandler;
std::unique_ptr <UnityMinimizedHandler> mMinimizeHandler;
ShowdesktopHandler *mShowdesktopHandler;
+ //! Emited when CompWindowNotifyBeforeDestroy is received
+ sigc::signal<void> being_destroyed;
+
+ void scaleSelectWindow ();
+ void scalePaintDecoration (const GLWindowPaintAttrib &,
+ const GLMatrix &,
+ const CompRegion &,
+ unsigned int);
+
private:
void DoEnableFocus ();
void DoDisableFocus ();
@@ -429,8 +467,32 @@ private:
compiz::WindowInputRemoverLock::Ptr GetInputRemover ();
+ void DrawWindowTitle (const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ unsigned int mask,
+ float x, float y, float x2, float y2);
+ void DrawTexture (GLTexture *icon,
+ const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ unsigned int mask,
+ float x, float y,
+ int &maxWidth, int &maxHeight);
+ void RenderText (WindowCairoContext *context,
+ float x, float y,
+ float maxWidth, float maxHeight);
+ WindowCairoContext* CreateCairoContext (float width, float height);
+
+ // based on compiz text plugin
+ CompString GetWindowName (Window id);
+ CompString GetUtf8Property (Window id, Atom atom);
+ CompString GetTextProperty (Window id, Atom atom);
+
compiz::WindowInputRemoverLock::Weak input_remover_;
glib::Source::UniquePtr focus_desktop_timeout_;
+
+ GLTexture::List close_icon_;
+ CompRect close_button_area_;
+ GtkStyleContext* window_header_style_;
};
diff --git a/plugins/unityshell/unityshell.xml.in b/plugins/unityshell/unityshell.xml.in
index cafebd1fd..98571394a 100644
--- a/plugins/unityshell/unityshell.xml.in
+++ b/plugins/unityshell/unityshell.xml.in
@@ -95,7 +95,7 @@
<_short>Key to open the first panel menu</_short>
<_long>Open the first menu on the panel, allowing keyboard navigation thereafter.</_long>
<default>&lt;Alt&gt;F10</default>
- </option>
+ </option>
<option name="launcher_switcher_forward" type="key">
<_short>Key to start the launcher application switcher</_short>
<_long>Switch the applications using the launcher</_long>
@@ -119,6 +119,11 @@
<_long>Bias the switcher to windows which are placed on the current viewport</_long>
<default>true</default>
</option>
+ <option name="disable_show_desktop" type="bool">
+ <_short>Disable Show Desktop in the switcher</_short>
+ <_long>Disables the Show Desktop icon in the switcher</_long>
+ <default>false</default>
+ </option>
<option name="alt_tab_forward" type="key">
<_short>Key to start the switcher</_short>
<_long>Start switching between windows</_long>
@@ -200,7 +205,7 @@
<_long>Change how the icons are backlit</_long>
<min>0</min>
<max>4</max>
- <default>0</default>
+ <default>1</default>
<desc>
<value>0</value>
<_name>Backlight Always On</_name>
@@ -329,6 +334,14 @@
<max>1000</max>
<precision>1</precision>
</option>
+ <option name="edge_passed_disabled_ms" type="int">
+ <_short>Duration of Sticky Edge Release after Break</_short>
+ <_long>Sticky edges deactivated for number of milliseconds after the user breaks the barrier</_long>
+ <default>1000</default>
+ <min>0</min>
+ <max>5000</max>
+ <precision>1</precision>
+ </option>
<option name="autohide_animation" type="int">
<_short>Hide Animation</_short>
<_long>Animation played when the launcher is showing or hiding</_long>
@@ -380,27 +393,7 @@
<max>100</max>
<default>75</default>
</option>
-
- <option name="devices_option" type="int">
- <_short>Show Devices</_short>
- <_long>Show devices in the launcher</_long>
- <min>0</min>
- <max>2</max>
- <default>1</default>
- <desc>
- <value>0</value>
- <_name>Never</_name>
- </desc>
- <desc>
- <value>1</value>
- <_name>Only Mounted</_name>
- </desc>
- <desc>
- <value>2</value>
- <_name>Always</_name>
- </desc>
- </option>
-
+
<option name="shortcut_overlay" type="bool">
<_short>Enable Shortcut Hints Overlay</_short>
<_long>Enable Shortcut Hints Overlay</_long>