diff --git a/interface/resources/images/analog_stick.png b/interface/resources/images/analog_stick.png
index e9457c7307..238c2c74f4 100644
Binary files a/interface/resources/images/analog_stick.png and b/interface/resources/images/analog_stick.png differ
diff --git a/interface/resources/images/analog_stick_base.png b/interface/resources/images/analog_stick_base.png
index 3b7b8aa8a9..ac8c1b9ae8 100644
Binary files a/interface/resources/images/analog_stick_base.png and b/interface/resources/images/analog_stick_base.png differ
diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
index 1a1714ad56..010572fcf2 100644
--- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
@@ -11,6 +11,7 @@
 
 #include <mutex>
 
+#include <QScreen>
 #include <QtGui/QWindow>
 #include <QtGui/QGuiApplication>
 #include <QtWidgets/QAction>
@@ -25,10 +26,14 @@ static const QString FULLSCREEN = "Fullscreen";
 void Basic2DWindowOpenGLDisplayPlugin::customizeContext() {
     auto iconPath = PathUtils::resourcesPath() + "images/analog_stick.png";
     auto image = QImage(iconPath);
+    qreal dpi = getFullscreenTarget()->physicalDotsPerInch();
+    _virtualPadPixelSize = dpi * 512 / 534; // 534 dpi for Pixel XL and Mate 9 Pro
+
     if (image.format() != QImage::Format_ARGB32) {
         image = image.convertToFormat(QImage::Format_ARGB32);
     }
     if ((image.width() > 0) && (image.height() > 0)) {
+        image = image.scaled(_virtualPadPixelSize, _virtualPadPixelSize, Qt::KeepAspectRatio);
 
         _virtualPadStickTexture = gpu::Texture::createStrict(
                 gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
@@ -49,6 +54,8 @@ void Basic2DWindowOpenGLDisplayPlugin::customizeContext() {
         image = image.convertToFormat(QImage::Format_ARGB32);
     }
     if ((image.width() > 0) && (image.height() > 0)) {
+        image = image.scaled(_virtualPadPixelSize, _virtualPadPixelSize, Qt::KeepAspectRatio);
+
         _virtualPadStickBaseTexture = gpu::Texture::createStrict(
                 gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
                 image.width(), image.height(),
@@ -91,7 +98,8 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
     auto& virtualPadManager = VirtualPad::Manager::instance();
     if(virtualPadManager.getLeftVirtualPad()->isBeingTouched()) {
         // render stick base
-        auto stickBaseTransform = DependencyManager::get<CompositorHelper>()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getFirstTouch());
+        auto stickBaseTransform = DependencyManager::get<CompositorHelper>()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getFirstTouch(),
+                                                                                                    _virtualPadPixelSize, _virtualPadPixelSize);
         render([&](gpu::Batch& batch) {
             batch.enableStereo(false);
             batch.setProjectionTransform(mat4());
@@ -103,7 +111,8 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
             batch.draw(gpu::TRIANGLE_STRIP, 4);
         });
         // render stick head
-        auto stickTransform = DependencyManager::get<CompositorHelper>()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getCurrentTouch());
+        auto stickTransform = DependencyManager::get<CompositorHelper>()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getCurrentTouch(),
+                                                                                                    _virtualPadPixelSize, _virtualPadPixelSize);
         render([&](gpu::Batch& batch) {
             batch.enableStereo(false);
             batch.setProjectionTransform(mat4());
diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h
index d9b942bd97..04568dcb27 100644
--- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h
@@ -44,4 +44,5 @@ private:
 
     gpu::TexturePointer _virtualPadStickTexture;
     gpu::TexturePointer _virtualPadStickBaseTexture;
+    qreal _virtualPadPixelSize;
 };
diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp
index 74225b5b39..fb53ca253f 100644
--- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp
+++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp
@@ -458,9 +458,8 @@ glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const
     return result;
 }
 
-glm::mat4 CompositorHelper::getPoint2DTransform(const glm::vec2& point) const {
+glm::mat4 CompositorHelper::getPoint2DTransform(const glm::vec2& point, float sizeX, float sizeY) const {
     glm::mat4 result;
-    static const float PIXEL_SIZE = 512.0f;
     const auto canvasSize = vec2(toGlm(_renderingWidget->size()));;
     QPoint qPoint(point.x,point.y);
     vec2 position = toGlm(_renderingWidget->mapFromGlobal(qPoint));
@@ -469,7 +468,7 @@ glm::mat4 CompositorHelper::getPoint2DTransform(const glm::vec2& point) const {
     position -= 1.0;
     position.y *= -1.0f;
 
-    vec2 size = PIXEL_SIZE / canvasSize;
+    vec2 size = vec2(sizeX / canvasSize.x, sizeY / canvasSize.y);
     result = glm::scale(glm::translate(glm::mat4(), vec3(position, 0.0f)), vec3(size, 1.0f));
     return result;
 }
diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h
index 5b65315f45..234818c740 100644
--- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h
+++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h
@@ -90,7 +90,7 @@ public:
     glm::vec2 getReticleMaximumPosition() const;
 
     glm::mat4 getReticleTransform(const glm::mat4& eyePose = glm::mat4(), const glm::vec3& headPosition = glm::vec3()) const;
-    glm::mat4 getPoint2DTransform(const glm::vec2& point = glm::vec2()) const;
+    glm::mat4 getPoint2DTransform(const glm::vec2& point = glm::vec2(), float sizeX = 512.0f, float sizeY = 512.0f) const;
 
     ReticleInterface* getReticleInterface() { return _reticleInterface; }
 
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
index 53683870df..40bc341fe2 100644
--- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
@@ -22,6 +22,8 @@
 #include <NumericalConstants.h>
 #include "VirtualPadManager.h"
 
+#include <cmath>
+
 const char* TouchscreenVirtualPadDevice::NAME = "TouchscreenVirtualPad";
 
 bool TouchscreenVirtualPadDevice::isSupported() const {
@@ -37,6 +39,21 @@ bool TouchscreenVirtualPadDevice::isSupported() const {
     return false;
 }
 
+void TouchscreenVirtualPadDevice::initFromEvent(const QTouchEvent* event) {
+    QScreen* eventScreen = event->window()->screen();
+    if (_screenDPI != eventScreen->physicalDotsPerInch()) {
+        _screenWidthCenter = eventScreen->size().width() / 2;
+        _screenDPIScale.x = (float)eventScreen->physicalDotsPerInchX();
+        _screenDPIScale.y = (float)eventScreen->physicalDotsPerInchY();
+        _screenDPI = eventScreen->physicalDotsPerInch();
+
+        _fixedPosition = true; // This should be config
+        _fixedRadius = _screenDPI * 256 / 534;
+        qreal margin = _screenDPI * 59 / 534; // 59px is for our 'base' of 534dpi (Pixel XL or Huawei Mate 9 Pro)
+        _fixedCenterPosition = glm::vec2( _fixedRadius + margin, eventScreen->size().height() - margin - _fixedRadius );
+    }
+}
+
 float clip(float n, float lower, float upper) {
     return std::max(lower, std::min(n, upper));
 }
@@ -132,13 +149,7 @@ void TouchscreenVirtualPadDevice::touchBeginEvent(const QTouchEvent* event) {
         return;
     }
     KeyboardMouseDevice::enableTouch(false);
-    QScreen* eventScreen = event->window()->screen();
-    _screenWidthCenter = eventScreen->size().width() / 2;
-    if (_screenDPI != eventScreen->physicalDotsPerInch()) {
-        _screenDPIScale.x = (float)eventScreen->physicalDotsPerInchX();
-        _screenDPIScale.y = (float)eventScreen->physicalDotsPerInchY();
-        _screenDPI = eventScreen->physicalDotsPerInch();
-    }
+    initFromEvent(event);
 }
 
 void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) {
@@ -169,14 +180,13 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) {
     bool rightTouchFound = false;
     for (int i = 0; i < _touchPointCount; ++i) {
         glm::vec2 thisPoint(tPoints[i].pos().x(), tPoints[i].pos().y());
-        if (thisPoint.x < _screenWidthCenter) {
+        if (_validTouchLeft) {
+            leftTouchFound = true;
+            touchLeftUpdate(thisPoint);
+        } else if (touchLeftBeginPointIsValid(thisPoint)) {
             if (!leftTouchFound) {
                 leftTouchFound = true;
-                if (!_validTouchLeft) {
-                    touchLeftBegin(thisPoint);
-                } else {
-                    touchLeftUpdate(thisPoint);
-                }
+                touchLeftBegin(thisPoint);
             }
         } else {
             if (!rightTouchFound) {
@@ -197,10 +207,24 @@ void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) {
     }
 }
 
+bool TouchscreenVirtualPadDevice::touchLeftBeginPointIsValid(glm::vec2 touchPoint) {
+    if (_fixedPosition) {
+        // inside circle
+        return pow(touchPoint.x - _fixedCenterPosition.x,2.0) + pow(touchPoint.y - _fixedCenterPosition.y, 2.0) < pow(_fixedRadius, 2.0);
+    } else {
+        // left side
+        return touchPoint.x < _screenWidthCenter;
+    }
+}
+
 void TouchscreenVirtualPadDevice::touchLeftBegin(glm::vec2 touchPoint) {
     auto& virtualPadManager = VirtualPad::Manager::instance();
     if (virtualPadManager.isEnabled()) {
-        _firstTouchLeftPoint = touchPoint;
+        if (_fixedPosition) {
+            _firstTouchLeftPoint = _fixedCenterPosition;
+        } else {
+            _firstTouchLeftPoint = touchPoint;
+        }
         _validTouchLeft = true;
     }
 }
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
index fd74009ee8..fd2342bfec 100644
--- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
@@ -74,15 +74,21 @@ protected:
     int _screenWidthCenter;
     std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
 
+    bool _fixedPosition;
+    glm::vec2 _fixedCenterPosition;
+    qreal _fixedRadius;
+
     void touchLeftBegin(glm::vec2 touchPoint);
     void touchLeftUpdate(glm::vec2 touchPoint);
     void touchLeftEnd();
+    bool touchLeftBeginPointIsValid(glm::vec2 touchPoint);
     void touchRightBegin(glm::vec2 touchPoint);
     void touchRightUpdate(glm::vec2 touchPoint);
     void touchRightEnd();
 // just for debug
 private:
     void debugPoints(const QTouchEvent* event, QString who);
+    void initFromEvent(const QTouchEvent* event);
 
 };