From ae1888597246e608c5327fccd4fa68273017b8b8 Mon Sep 17 00:00:00 2001
From: "Richard Wedlich (rootzrich)" <richard@rootiniert.de>
Date: Sun, 14 Dec 2014 17:29:54 +0100
Subject: [PATCH] implements autohide taskbar #134. modified for use with qt5.
 implemented xcb events. works ok, ecxcept if the systray plugin is used.

---
 cmake/FindXCB.cmake                |  54 ++++
 panel/CMakeLists.txt               |   4 +
 panel/config/configpaneldialog.cpp |  17 +-
 panel/config/configpaneldialog.h   |   5 +
 panel/config/configpaneldialog.ui  |  24 ++
 panel/lxqtpanel.cpp                | 508 +++++++++++++++++++++++++++++++++----
 panel/lxqtpanel.h                  |  72 +++++-
 panel/lxqtpanelapplication.cpp     |   7 +
 panel/lxqtpanelapplication.h       |   7 +
 panel/lxqtpanellayout.cpp          |   5 +-
 panel/lxqtpanellayout.h            |   2 +
 panel/lxqtpanellimits.h            |   3 +
 panel/plugin.cpp                   |   2 +
 panel/plugin.h                     |   2 +
 plugin-mount/lxqtmountplugin.cpp   |   7 -
 plugin-mount/lxqtmountplugin.h     |   1 -
 plugin-volume/lxqtvolume.cpp       |   4 -
 plugin-volume/lxqtvolume.h         |   1 -
 18 files changed, 654 insertions(+), 71 deletions(-)
 create mode 100644 cmake/FindXCB.cmake

diff --git a/cmake/FindXCB.cmake b/cmake/FindXCB.cmake
new file mode 100644
index 0000000..b23d790
--- /dev/null
+++ b/cmake/FindXCB.cmake
@@ -0,0 +1,54 @@
+# - Try to find libxcb
+# Once done this will define
+#
+# LIBXCB_FOUND - system has libxcb
+# LIBXCB_LIBRARIES - Link these to use libxcb
+# LIBXCB_INCLUDE_DIR - the libxcb include dir
+# LIBXCB_DEFINITIONS - compiler switches required for using libxcb
+
+# Copyright (c) 2008 Helio Chissini de Castro, <helio@kde.org>
+# Copyright (c) 2007, Matthias Kretz, <kretz@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+IF (NOT WIN32)
+ IF (LIBXCB_INCLUDE_DIR AND LIBXCB_LIBRARIES)
+ # in cache already
+ SET(XCB_FIND_QUIETLY TRUE)
+ ENDIF (LIBXCB_INCLUDE_DIR AND LIBXCB_LIBRARIES)
+
+ FIND_PACKAGE(PkgConfig)
+ PKG_CHECK_MODULES(PKG_XCB xcb)
+
+ SET(LIBXCB_DEFINITIONS ${PKG_XCB_CFLAGS})
+
+ FIND_PATH(LIBXCB_INCLUDE_DIR xcb/xcb.h ${PKG_XCB_INCLUDE_DIRS})
+ FIND_LIBRARY(LIBXCB_LIBRARIES NAMES xcb libxcb PATHS ${PKG_XCB_LIBRARY_DIRS})
+
+ include(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(XCB DEFAULT_MSG LIBXCB_LIBRARIES LIBXCB_INCLUDE_DIR)
+
+ MARK_AS_ADVANCED(LIBXCB_INCLUDE_DIR LIBXCB_LIBRARIES XCBPROC_EXECUTABLE)
+ENDIF (NOT WIN32)
diff --git a/panel/CMakeLists.txt b/panel/CMakeLists.txt
index bdbfd9b..4ac9114 100644
--- a/panel/CMakeLists.txt
+++ b/panel/CMakeLists.txt
@@ -1,5 +1,7 @@
 set(PROJECT lxqt-panel)
 
+find_package(XCB REQUIRED)
+
 set(lxqt-panel_PRIV_H_FILES
     lxqtpanel.h
     lxqtpanelapplication.h
@@ -44,6 +46,7 @@ set(MOCS
 set(LIBRARIES
     ${LXQT_LIBRARIES}
     ${QTXDG_LIBRARIES}
+    ${LIBXCB_LIBRARIES}
 )
 
 set(RESOURCES "")
@@ -67,6 +70,7 @@ project(${PROJECT})
 
 include_directories(
     ${CMAKE_CURRENT_BINARY_DIR}
+    ${LIBXCB_INCLUDE_DIR}
     ${LXQT_INCLUDE_DIRS}
     ${LXQT_INCLUDE_DIRS}/LXQt # FIXME: liblxqt seems to be broken, workaround it.
 )
diff --git a/panel/config/configpaneldialog.cpp b/panel/config/configpaneldialog.cpp
index cb34770..27fd079 100644
--- a/panel/config/configpaneldialog.cpp
+++ b/panel/config/configpaneldialog.cpp
@@ -117,6 +117,9 @@ ConfigPanelWidget::ConfigPanelWidget(LxQtPanel *panel, QWidget *parent) :
     mOldPosition = mPanel->position();
     mPosition = mOldPosition;
 
+    mOldAutohideTb = mPanel->autohideTb();
+    mOldAutohideDuration = mPanel->autohideDuration();
+
     ui->spinBox_panelSize->setMinimum(PANEL_MINIMUM_SIZE);
     ui->spinBox_panelSize->setMaximum(PANEL_MAXIMUM_SIZE);
 
@@ -139,6 +142,9 @@ ConfigPanelWidget::ConfigPanelWidget(LxQtPanel *panel, QWidget *parent) :
     connect(ui->comboBox_alignment,         SIGNAL(activated(int)),         this, SLOT(editChanged()));
     connect(ui->comboBox_position,          SIGNAL(activated(int)),         this, SLOT(positionChanged()));
 
+    connect(ui->checkBox_autohideTb,        SIGNAL(stateChanged(int)),      this, SLOT(editChanged()));
+    connect(ui->spinBox_autohideDuration,   SIGNAL(valueChanged(int)),      this, SLOT(editChanged()));
+
     connect(ui->checkBox_customFontColor,   SIGNAL(toggled(bool)),          this, SLOT(editChanged()));
     connect(ui->pushButton_customFontColor, SIGNAL(clicked(bool)),          this, SLOT(pickFontColor()));
     connect(ui->checkBox_customBgColor,     SIGNAL(toggled(bool)),          this, SLOT(editChanged()));
@@ -146,7 +152,7 @@ ConfigPanelWidget::ConfigPanelWidget(LxQtPanel *panel, QWidget *parent) :
     connect(ui->checkBox_customBgImage,     SIGNAL(toggled(bool)),          this, SLOT(editChanged()));
     connect(ui->lineEdit_customBgImage,     SIGNAL(textChanged(QString)),   this, SLOT(editChanged()));
     connect(ui->pushButton_customBgImage,   SIGNAL(clicked(bool)),          this, SLOT(pickBackgroundImage()));
-    connect(ui->slider_opacity,             SIGNAL(sliderReleased()),      this, SLOT(editChanged()));
+    connect(ui->slider_opacity,             SIGNAL(sliderReleased()),       this, SLOT(editChanged()));
 }
 
 
@@ -168,10 +174,14 @@ void ConfigPanelWidget::reset()
     widthTypeChanged();
     ui->spinBox_length->setValue(mOldLength);
 
+    ui->checkBox_autohideTb->setChecked(mOldAutohideTb);
+    ui->spinBox_autohideDuration->setValue(mOldAutohideDuration);
+
     mFontColor.setNamedColor(mOldFontColor.name());
     ui->pushButton_customFontColor->setStyleSheet(QString("background: %1").arg(mOldFontColor.name()));
     mBackgroundColor.setNamedColor(mOldBackgroundColor.name());
     ui->pushButton_customBgColor->setStyleSheet(QString("background: %1").arg(mOldBackgroundColor.name()));
+
     ui->lineEdit_customBgImage->setText(mOldBackgroundImage);
     ui->slider_opacity->setValue(mOldOpacity);
 
@@ -295,6 +305,7 @@ void ConfigPanelWidget::editChanged()
     mPanel->setPosition(mScreenNum, mPosition, true);
 
     mPanel->setFontColor(ui->checkBox_customFontColor->isChecked() ? mFontColor : QColor(), true);
+
     if (ui->checkBox_customBgColor->isChecked())
     {
         mPanel->setBackgroundColor(mBackgroundColor, true);
@@ -308,6 +319,10 @@ void ConfigPanelWidget::editChanged()
 
     QString image = ui->checkBox_customBgImage->isChecked() ? ui->lineEdit_customBgImage->text() : QString();
     mPanel->setBackgroundImage(image, true);
+
+    // autohide
+    mPanel->setAutohide(ui->checkBox_autohideTb->isChecked());
+    mPanel->setAutohideDuration(ui->spinBox_autohideDuration->value());
 }
 
 
diff --git a/panel/config/configpaneldialog.h b/panel/config/configpaneldialog.h
index 605e005..95d303d 100644
--- a/panel/config/configpaneldialog.h
+++ b/panel/config/configpaneldialog.h
@@ -100,7 +100,12 @@ private slots:
     LxQtPanel::Alignment mOldAlignment;
     ILxQtPanel::Position mOldPosition;
     int mOldScreenNum;
+
+    bool mOldAutohideTb;
+    int mOldAutohideDuration;
+
     QColor mOldFontColor;
+
     QColor mOldBackgroundColor;
     QString mOldBackgroundImage;
     int mOldOpacity;
diff --git a/panel/config/configpaneldialog.ui b/panel/config/configpaneldialog.ui
index f72ca29..ba78b64 100644
--- a/panel/config/configpaneldialog.ui
+++ b/panel/config/configpaneldialog.ui
@@ -211,6 +211,30 @@
         </property>
        </widget>
       </item>
+      <item row="3" column="0" colspan="2">
+    <widget class="QCheckBox" name="checkBox_autohideTb">
+        <property name="text">
+         <string>Autohide this panel</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+     <widget class="QLabel" name="label_autohideDelay">
+        <property name="text">
+         <string>Autohide duration: [ms]</string>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="2">
+    <widget class="QSpinBox" name="spinBox_autohideDuration">
+        <property name="minimum">
+         <number>0</number>
+        </property>
+        <property name="maximum">
+         <number>10000</number>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
diff --git a/panel/lxqtpanel.cpp b/panel/lxqtpanel.cpp
index a70e1f0..c7f39db 100644
--- a/panel/lxqtpanel.cpp
+++ b/panel/lxqtpanel.cpp
@@ -48,6 +48,8 @@
 #include <XdgIcon>
 #include <XdgDirs>
 
+#include <xcb/xcb.h>
+
 #include <KF5/KWindowSystem/KWindowSystem>
 #include <KF5/KWindowSystem/NETWM>
 
@@ -66,6 +68,11 @@
 #define CFG_KEY_OPACITY            "opacity"
 #define CFG_KEY_PLUGINS            "plugins"
 
+#define CFG_KEY_AUTOHIDE            "autohideTb"
+#define CFG_KEY_AUTOHIDEDURATION    "autohideDuration"
+#define AUTOHIDETB_SPACE 1 // unit pixels
+
+
 /************************************************
  Returns the Position by the string.
  String is one of "Top", "Left", "Bottom", "Right", string is not case sensitive.
@@ -112,6 +119,13 @@ LxQtPanel::LxQtPanel(const QString &configGroup, QWidget *parent) :
     mIconSize(0),
     mLineCount(0),
     mLength(0),
+    mPanelActivated(0),
+    mChilds(0),
+    mAutoHideActive(false),
+    mAutoHideLock(false),    
+    mAutohidePanel(0),
+    mAutoHidePermanentLock(false),
+    mAnimationOffset(100),    
     mAlignment(AlignmentLeft),
     mPosition(ILxQtPanel::PositionBottom)
 {
@@ -137,6 +151,8 @@ LxQtPanel::LxQtPanel(const QString &configGroup, QWidget *parent) :
     setWindowTitle("LxQt Panel");
     setObjectName(QString("LxQtPanel %1").arg(configGroup));
 
+    animationPanel = new VariantAnimation(parent, &mAnimationOffset);
+
     LxQtPanelWidget = new QFrame(this);
     LxQtPanelWidget->setObjectName("BackgroundWidget");
     QGridLayout* lav = new QGridLayout();
@@ -158,6 +174,9 @@ LxQtPanel::LxQtPanel(const QString &configGroup, QWidget *parent) :
     connect(LxQt::Settings::globalSettings(), SIGNAL(settingsChanged()), this, SLOT(update()));
     connect(lxqtApp, SIGNAL(themeChanged()), this, SLOT(realign()));
 
+    connect(mLayout,SIGNAL(pluginMoving()), this, SLOT(autohidePermanentLock()));
+    connect(mLayout,SIGNAL(pluginMoved()), this, SLOT(autohidePermanentUnlock()));
+
     LxQtPanelApplication *app = reinterpret_cast<LxQtPanelApplication*>(qApp);
     mSettings = app->settings();
     readSettings();
@@ -165,7 +184,19 @@ LxQtPanel::LxQtPanel(const QString &configGroup, QWidget *parent) :
     ensureVisible();
     loadPlugins();
 
+    // panel autohide animation
+    animationPanel->setStartValue(0);
+    animationPanel->setEndValue(100);
+    animationPanel->setEasingCurve(QEasingCurve::OutExpo); //QEasingCurve::OutSine // QEasingCurve::OutInBack // QEasingCurve::OutCirc
+    animationPanel->setDuration(mAutoHideDuration);
+    connect (animationPanel,SIGNAL(valueChanged()), this, SLOT(updateOffset()));
+
+    // startup apply show or hide
+    autohideActive(mAutoHideTb);
+
     show();
+
+    qApp->installNativeEventFilter(this);
 }
 
 
@@ -205,6 +236,9 @@ void LxQtPanel::readSettings()
     if (!image.isEmpty())
         setBackgroundImage(image, false);
 
+    // autohide
+    setAutohide(mSettings->value(CFG_KEY_AUTOHIDE,PANEL_DEFAULT_AUTOHIDE).toBool());
+    setAutohideDuration(mSettings->value(CFG_KEY_AUTOHIDEDURATION,PANEL_DEFAULT_AUTOHIDEDURATION).toInt());
 
     mSettings->endGroup();
 }
@@ -243,6 +277,9 @@ void LxQtPanel::saveSettings(bool later)
 
     mSettings->setValue(CFG_KEY_ALIGNMENT, mAlignment);
 
+    mSettings->setValue(CFG_KEY_AUTOHIDE, mAutoHideTb);
+    mSettings->setValue(CFG_KEY_AUTOHIDEDURATION, mAutoHideDuration);
+
     mSettings->setValue(CFG_KEY_FONTCOLOR, mFontColor.isValid() ? mFontColor : QColor());
     mSettings->setValue(CFG_KEY_BACKGROUNDCOLOR, mBackgroundColor.isValid() ? mBackgroundColor : QColor());
     mSettings->setValue(CFG_KEY_BACKGROUNDIMAGE, QFileInfo(mBackgroundImage).exists() ? mBackgroundImage : QString());
@@ -342,6 +379,7 @@ Plugin *LxQtPanel::loadPlugin(const LxQt::PluginInfo &desktopFile, const QString
         connect(plugin, SIGNAL(startMove()), mLayout, SLOT(startMovePlugin()));
         connect(plugin, SIGNAL(remove()), this, SLOT(removePlugin()));
         connect(this, SIGNAL(realigned()), plugin, SLOT(realign()));
+
         mLayout->addWidget(plugin);
         return plugin;
     }
@@ -354,6 +392,68 @@ Plugin *LxQtPanel::loadPlugin(const LxQt::PluginInfo &desktopFile, const QString
 /************************************************
 
  ************************************************/
+void VariantAnimation::updateCurrentValue(const QVariant &value)
+{
+    if (*currentValue != value.toInt())
+    {
+        *currentValue = value.toInt();
+        emit valueChanged();
+    }
+}
+
+
+
+/************************************************
+
+ ************************************************/
+void LxQtPanel::updateOffset()
+{
+    const QRect currentScreen = QApplication::desktop()->screenGeometry(mScreenNum);
+
+    int defaultsize;
+    if (isHorizontal())
+        defaultsize = rect.height();
+    else
+        defaultsize = rect.width();
+
+    if (mAutoHideTb)
+        mOffset = mAnimationOffset;
+    else
+        mOffset = 100;
+
+    // percent to pixels
+    int mOffsetPixels = (defaultsize * (100 - mOffset)/100);
+    if (mOffsetPixels >= defaultsize)
+        mOffsetPixels = defaultsize - 1;
+
+    if (isHorizontal())
+    {
+        // Position Horiz ......................
+        if (mPosition == ILxQtPanel::PositionTop)
+            rect.moveTop(currentScreen.top() - mOffsetPixels);
+        else
+            rect.moveBottom(currentScreen.bottom() + mOffsetPixels);
+    }
+    else
+    {
+        // Position Vert .......................
+        if (mPosition == ILxQtPanel::PositionLeft)
+            rect.moveLeft(currentScreen.left() - mOffsetPixels);
+        else
+            rect.moveRight(currentScreen.right() + mOffsetPixels);
+     }
+
+    if (rect != geometry())
+    {
+        setGeometry(rect);
+        setFixedSize(rect.size());
+    }
+}
+
+
+/************************************************
+
+ ************************************************/
 void LxQtPanel::realign()
 {
     if (!isVisible())
@@ -371,7 +471,6 @@ void LxQtPanel::realign()
 
     const QRect currentScreen = QApplication::desktop()->screenGeometry(mScreenNum);
     QSize size = sizeHint();
-    QRect rect;
 
     if (isHorizontal())
     {
@@ -380,6 +479,7 @@ void LxQtPanel::realign()
 
         // Size .......................
         rect.setHeight(qMax(PANEL_MINIMUM_SIZE, size.height()));
+
         if (mLengthInPercents)
             rect.setWidth(currentScreen.width() * mLength / 100.0);
         else
@@ -392,7 +492,7 @@ void LxQtPanel::realign()
 
         rect.setWidth(qMax(rect.size().width(), mLayout->minimumSize().width()));
 
-        // Horiz ......................
+        // Alignment
         switch (mAlignment)
         {
         case LxQtPanel::AlignmentLeft:
@@ -407,12 +507,6 @@ void LxQtPanel::realign()
             rect.moveRight(currentScreen.right());
             break;
         }
-
-        // Vert .......................
-        if (mPosition == ILxQtPanel::PositionTop)
-            rect.moveTop(currentScreen.top());
-        else
-            rect.moveBottom(currentScreen.bottom());
     }
     else
     {
@@ -421,6 +515,7 @@ void LxQtPanel::realign()
 
         // Size .......................
         rect.setWidth(qMax(PANEL_MINIMUM_SIZE, size.width()));
+
         if (mLengthInPercents)
             rect.setHeight(currentScreen.height() * mLength / 100.0);
         else
@@ -433,7 +528,7 @@ void LxQtPanel::realign()
 
         rect.setHeight(qMax(rect.size().height(), mLayout->minimumSize().height()));
 
-        // Vert .......................
+        // Alignment
         switch (mAlignment)
         {
         case LxQtPanel::AlignmentLeft:
@@ -448,18 +543,37 @@ void LxQtPanel::realign()
             rect.moveBottom(currentScreen.bottom());
             break;
         }
-
-        // Horiz ......................
-        if (mPosition == ILxQtPanel::PositionLeft)
-            rect.moveLeft(currentScreen.left());
-        else
-            rect.moveRight(currentScreen.right());
     }
-    if (rect != geometry())
+
+    // autohide
+    if (mAutoHideTb)
     {
-        setGeometry(rect);
-        setFixedSize(rect.size());
+        // panel should hide or not?
+        if (mAutoHideActive && !mAutoHideLock  && !mChilds  && !mAutoHidePermanentLock)
+        {
+            // switch animation direction if necessary
+            if (animationPanel->direction() == QAbstractAnimation::Forward)
+            {
+                animationPanel->setDirection(QAbstractAnimation::Backward);
+                if (animationPanel->state() == QAbstractAnimation::Stopped)
+                    animationPanel->start();
+            }
+        }
+        else
+        {
+            // switch animation direction if necessary
+            if (animationPanel->direction() == QAbstractAnimation::Backward)
+            {
+                animationPanel->setDirection(QAbstractAnimation::Forward);
+                if (animationPanel->state() == QAbstractAnimation::Stopped)
+                    animationPanel->start();
+            }
+        }
     }
+
+    // for autohide
+    updateOffset();
+
     // Reserve our space on the screen ..........
     // It's possible that our geometry is not changed, but screen resolution is changed,
     // so resetting WM_STRUT is still needed. To make it simple, we always do it.
@@ -482,44 +596,57 @@ void LxQtPanel::updateWmStrut()
     // So, we use the geometry of the whole screen to calculate the strut rather than using the geometry of individual monitors.
     // Though the spec only mention Xinerama and did not mention XRandR, the rule should still be applied.
     // At least openbox is implemented like this.
-    switch (mPosition)
+    if (mAutoHideTb)
     {
-    case LxQtPanel::PositionTop:
-        KWindowSystem::setExtendedStrut(wid,
-                                        /* Left   */  0, 0, 0,
-                                        /* Right  */  0, 0, 0,
-                                        /* Top    */  height(), rect.left(), rect.right(),
-                                        /* Bottom */  0, 0, 0
-                                       );
-        break;
-
-    case LxQtPanel::PositionBottom:
-        KWindowSystem::setExtendedStrut(wid,
-                                        /* Left   */  0, 0, 0,
-                                        /* Right  */  0, 0, 0,
-                                        /* Top    */  0, 0, 0,
-                                        /* Bottom */  wholeScreen.bottom() - rect.y(), rect.left(), rect.right()
-                                       );
-        break;
-
-    case LxQtPanel::PositionLeft:
-        KWindowSystem::setExtendedStrut(wid,
-                                        /* Left   */  width(), rect.top(), rect.bottom(),
-                                        /* Right  */  0, 0, 0,
-                                        /* Top    */  0, 0, 0,
-                                        /* Bottom */  0, 0, 0
-                                       );
-
-        break;
-
-    case LxQtPanel::PositionRight:
-        KWindowSystem::setExtendedStrut(wid,
-                                        /* Left   */  0, 0, 0,
-                                        /* Right  */  wholeScreen.right() - rect.x(), rect.top(), rect.bottom(),
-                                        /* Top    */  0, 0, 0,
-                                        /* Bottom */  0, 0, 0
-                                       );
-        break;
+                // No space reserved for a hidden taskbar
+                KWindowSystem::setExtendedStrut(wid,
+                                                /* Left   */  0, 0, 0,
+                                                /* Right  */  0, 0, 0,
+                                                /* Top    */  0, 0, 0,
+                                                /* Bottom */  0, 0, 0
+                                               );
+    }
+    else
+    {
+        switch (mPosition)
+        {
+            case LxQtPanel::PositionTop:
+                KWindowSystem::setExtendedStrut(wid,
+                                                /* Left   */  0, 0, 0,
+                                                /* Right  */  0, 0, 0,
+                                                /* Top    */  height(), rect.left(), rect.right(),
+                                                /* Bottom */  0, 0, 0
+                                               );
+                break;
+
+            case LxQtPanel::PositionBottom:
+                KWindowSystem::setExtendedStrut(wid,
+                                                /* Left   */  0, 0, 0,
+                                                /* Right  */  0, 0, 0,
+                                                /* Top    */  0, 0, 0,
+                                                /* Bottom */  wholeScreen.bottom() - rect.y(), rect.left(), rect.right()
+                                               );
+                break;
+
+            case LxQtPanel::PositionLeft:
+                KWindowSystem::setExtendedStrut(wid,
+                                                /* Left   */  width(), rect.top(), rect.bottom(),
+                                                /* Right  */  0, 0, 0,
+                                                /* Top    */  0, 0, 0,
+                                                /* Bottom */  0, 0, 0
+                                               );
+
+                break;
+
+            case LxQtPanel::PositionRight:
+                KWindowSystem::setExtendedStrut(wid,
+                                                /* Left   */  0, 0, 0,
+                                                /* Right  */  wholeScreen.right() - rect.x(), rect.top(), rect.bottom(),
+                                                /* Top    */  0, 0, 0,
+                                                /* Bottom */  0, 0, 0
+                                               );
+                break;
+        }
     }
 }
 
@@ -605,6 +732,11 @@ void LxQtPanel::showAddPluginDialog()
         dialog->setWindowTitle(tr("Add Panel Widgets"));
         dialog->setAttribute(Qt::WA_DeleteOnClose);
         connect(dialog, SIGNAL(pluginSelected(const LxQt::PluginInfo&)), this, SLOT(addPlugin(const LxQt::PluginInfo&)));
+
+        connect(dialog,SIGNAL(destroyed()), this, SLOT(autohidePermanentUnlock()));
+
+        emit autohidePermanentLock();
+
         connect(this, SIGNAL(pluginAdded(QString)), dialog, SLOT(pluginAdded(const QString &)));
         connect(this, SIGNAL(pluginRemoved(QString)), dialog, SLOT(pluginRemoved(const QString &)));
     }
@@ -706,6 +838,50 @@ void LxQtPanel::setIconSize(int value, bool save)
 
 
 /************************************************
+ *
+ * *********************************************/
+void LxQtPanel::setAutohide(bool value)
+{
+    if (mAutoHideTb != value)
+    {
+        mAutoHideTb = value;
+        updateStyleSheet();
+        saveSettings(true);
+
+        if (value)
+        {
+            mAutoHideActive = true;
+            mAutoHideLock = false;
+            mAutoHidePermanentLock = false;            
+            mMapped.clear();
+        }
+
+        realign();
+        emit realigned();
+    }
+}
+
+
+/************************************************
+ *
+ * *********************************************/
+void LxQtPanel::setAutohideDuration(int value)
+{
+    if (mAutoHideDuration != value)
+    {
+        mAutoHideDuration = value;
+        updateStyleSheet();
+        saveSettings(true);
+
+        animationPanel->setDuration(mAutoHideDuration);
+
+        realign();
+        emit realigned();
+    }
+}
+
+
+/************************************************
 
  ************************************************/
 void LxQtPanel::setLineCount(int value, bool save)
@@ -858,6 +1034,192 @@ void LxQtPanel::setOpacity(int opacity, bool save)
 /************************************************
 
  ************************************************/
+void LxQtPanel::autohideActive(bool value)
+{
+    if (!mAutoHideTb && !mAutoHideActive)
+        return;
+
+    mAutoHideActive = value;
+}
+
+
+/************************************************
+
+ ************************************************/
+void LxQtPanel::autohideCheckLock()
+{
+    if (!mMapped.count() && !mChilds)
+        autohideUnlock();
+    else
+        autohideLock();
+}
+
+
+/************************************************
+
+ ************************************************/
+void LxQtPanel::autohideLock()
+{
+    if (!mAutoHideLock)
+    {
+        mAutoHideLock = true;
+
+        realign();
+        emit realigned();
+    }
+}
+
+
+/************************************************
+
+ ************************************************/
+void LxQtPanel::autohideUnlock()
+{
+    if (mAutoHideLock)
+    {
+        mAutoHideLock = false;
+
+        realign();
+        emit realigned();
+    }
+}
+
+
+/************************************************
+Will permanently lock the autohide function. until autohidePermanentUnlock is called.
+Increments mAutoHidePermantenLock. Only if this var is 0 the panel can hide.
+ ************************************************/
+void LxQtPanel::autohidePermanentLock()
+{
+    mAutoHidePermanentLock += 1;
+
+    realign();
+    emit realigned();
+}
+
+
+/************************************************
+
+ ************************************************/
+void LxQtPanel::autohidePermanentUnlock()
+{
+    if (mAutoHidePermanentLock)
+        mAutoHidePermanentLock -= 1;
+
+    realign();
+    emit realigned();
+}
+
+
+/************************************************
+
+ ************************************************/
+bool LxQtPanel::nativeEventFilter(const QByteArray &eventType, void *message, long *)
+{    
+
+    if (!mAutoHideTb)
+        return false;
+
+    if (eventType != "xcb_generic_event_t")
+    {
+        qDebug () << "No XCB Event: " << eventType;
+        return false;
+    }
+
+    xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);
+    int event_type = event->response_type & ~0x80;
+
+    switch (event_type)
+    {
+
+        case XCB_ENTER_NOTIFY:
+        {
+            xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
+
+            mAutohidePanel = enter->event;
+
+            // check if this panel was entered
+            if (effectiveWinId() == enter->event) {
+
+                // This variable is used to indicate that this panel has been hovered (so the initialization is complete)
+                // because at startup the e.g. ChildAdded event is called multiple times, but this is irrelevant for the autohide function
+                mPanelActivated = true;
+
+                // disallow panel to hide
+                autohideActive(false);
+
+                realign();
+                emit realigned();
+            }
+
+            break;
+        }
+
+        case XCB_LEAVE_NOTIFY:
+        {
+            xcb_leave_notify_event_t *leave = (xcb_leave_notify_event_t *)event;
+
+            if (effectiveWinId() == leave->event) {
+
+                // allow panel to hide
+                autohideActive(true);
+
+                realign();
+                emit realigned();
+            }
+
+            break;
+        }
+
+        case XCB_MAP_NOTIFY:
+        {
+            // nativeFilterEvent is called for all panels simultaneously, we want the call only for the panel currently active
+            // in this case mAutohidePanel is set to the corresponding window-id on EnterEvent
+            if (mAutohidePanel == effectiveWinId())
+            {
+
+                xcb_map_notify_event_t *map = (xcb_map_notify_event_t *)event;                
+
+                // add window to mapped list
+                if (mAutoHideTb)
+                {
+                    xcb_drawable_t draw = (xcb_drawable_t )map->event;
+
+                    xcb_query_tree_cookie_t treeCookie     = xcb_query_tree       (QX11Info::connection(), draw);
+                    xcb_query_tree_reply_t *tree           = xcb_query_tree_reply (QX11Info::connection(), treeCookie, NULL);
+
+                    // this check aims for windows opened from within the panel.
+                    // applications that are showing in systray are also causing mapping events, but should not have parent=root window-id.
+                    if (tree->parent == tree->root && mPanelActivated)
+                        mMapped << map->event;
+                    autohideCheckLock();
+                }
+
+            }
+
+            break;
+        }
+
+        case XCB_UNMAP_NOTIFY:
+        {
+
+            xcb_unmap_notify_event_t *unmap = (xcb_unmap_notify_event_t *)event;
+
+            mMapped -= unmap->event;
+            autohideCheckLock();
+
+            break;
+        }
+
+    }
+
+    return false;
+}
+
+
+/************************************************
+
+ ************************************************/
 QRect LxQtPanel::globalGometry() const
 {
     return QRect(mapToGlobal(QPoint(0, 0)), this->size());
@@ -865,6 +1227,41 @@ QRect LxQtPanel::globalGometry() const
 
 
 /************************************************
+when a child is added from the panel it shouldn't hide
+ ************************************************/
+void LxQtPanel::childEvent(QChildEvent *event)
+{
+
+    if (!mAutoHideTb)
+        return;
+
+    switch (event->type())
+    {
+        case QEvent::ChildAdded:
+
+            if (mPanelActivated)
+                mChilds += 1;
+
+            autohideCheckLock();
+        break;
+
+        case QEvent::ChildRemoved:
+
+            if (mChilds <= 1)
+                mChilds = 0;
+            else
+                mChilds -= 1;
+
+            autohideCheckLock();
+        break;
+
+        default:
+            break;
+    }
+}
+
+
+/************************************************
 
  ************************************************/
 bool LxQtPanel::event(QEvent *event)
@@ -908,6 +1305,7 @@ bool LxQtPanel::event(QEvent *event)
     return QFrame::event(event);
 }
 
+
 /************************************************
 
  ************************************************/
diff --git a/panel/lxqtpanel.h b/panel/lxqtpanel.h
index f1b2123..07ed453 100644
--- a/panel/lxqtpanel.h
+++ b/panel/lxqtpanel.h
@@ -29,14 +29,23 @@
 #ifndef LXQTPANEL_H
 #define LXQTPANEL_H
 
+#include <QSet>
+
 #include <QFrame>
 #include <QString>
 #include <QTimer>
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include <QAbstractNativeEventFilter>
+#endif
+
 #include "ilxqtpanel.h"
 #include "lxqtpanelglobals.h"
+#include <QtCore/qvariantanimation.h>
 
 class QMenu;
 class Plugin;
+class VariantAnimation;
 
 namespace LxQt {
 class Settings;
@@ -46,7 +55,7 @@ class LxQtPanelLayout;
 
 /*! \brief The LxQtPanel class provides a single lxqt-panel.
  */
-class LXQT_PANEL_API LxQtPanel : public QFrame, public ILxQtPanel
+class LXQT_PANEL_API LxQtPanel : public QFrame, public QAbstractNativeEventFilter, public ILxQtPanel
 {
     Q_OBJECT
 
@@ -59,6 +68,13 @@ class LXQT_PANEL_API LxQtPanel : public QFrame, public ILxQtPanel
         AlignmentRight  =  1
     };
 
+    enum AutohideMsg {
+        NoMsg = 0,
+        RemoveWindow = 1,
+        SaveWindow = 2,
+        SysTrayConfigure = 3
+    };
+
     LxQtPanel(const QString &configGroup, QWidget *parent = 0);
     virtual ~LxQtPanel();
 
@@ -86,6 +102,10 @@ class LXQT_PANEL_API LxQtPanel : public QFrame, public ILxQtPanel
     int lineCount() const { return mLineCount; }
     int length() const { return mLength; }
     bool lengthInPercents() const { return mLengthInPercents; }
+
+    bool autohideTb() const {return mAutoHideTb; }
+    int autohideDuration() const {return mAutoHideDuration; }
+
     LxQtPanel::Alignment alignment() const { return mAlignment; }
     int screenNum() const { return mScreenNum; }
     QColor fontColor() const { return mFontColor; };
@@ -95,10 +115,19 @@ class LXQT_PANEL_API LxQtPanel : public QFrame, public ILxQtPanel
 
     LxQt::Settings *settings() const { return mSettings; }
 
+    bool nativeEventFilter(const QByteArray &eventType, void *message, long *);
+
 public slots:
     void show();
 
     // Settings
+
+    // autohide
+    void setAutohide(bool value);
+    void setAutohideDuration(int value);
+    void autohidePermanentLock();
+    void autohidePermanentUnlock();
+
     void setPanelSize(int value, bool save);
     void setIconSize(int value, bool save);
     void setLineCount(int value, bool save);
@@ -123,16 +152,21 @@ public slots:
 protected:
     bool event(QEvent *event);
     void showEvent(QShowEvent *event);
+    void childEvent(QChildEvent *event);
 
 private slots:
     void addPlugin(const LxQt::PluginInfo &desktopFile);
     void showConfigDialog();
     void showAddPluginDialog();
     void realign();
+
     void removePlugin();
     void pluginMoved();
     void userRequestForDeletion();
 
+    //autohide    
+    void updateOffset();
+
 private:
     LxQtPanelLayout* mLayout;
     LxQt::Settings *mSettings;
@@ -156,6 +190,25 @@ private slots:
     int mLength;
     bool mLengthInPercents;
 
+    // autohide
+    bool mPanelActivated;
+    bool mChilds;
+    bool mAutoHideTb;
+    int  mAutoHideDuration;
+    bool mAutoHideActive;
+    bool mAutoHideLock;    
+    unsigned long int mAutohidePanel;
+    int  mAutoHidePermanentLock;    
+    void autohideActive(bool value);
+    void autohideLock ();
+    void autohideCheckLock ();
+    void autohideUnlock ();
+    QSet<long int> mMapped;
+    QRect rect;
+    int mOffset;
+    int mAnimationOffset;
+    VariantAnimation *animationPanel;
+
     Alignment mAlignment;
 
     ILxQtPanel::Position mPosition;
@@ -171,5 +224,22 @@ private slots:
     void updateStyleSheet();
 };
 
+class VariantAnimation : public QVariantAnimation
+{
+  Q_OBJECT
+
+public:
+  VariantAnimation(QObject* parent = 0, int* val = 0):
+  QVariantAnimation(parent) { currentValue = val; }
+
+private:
+  int *currentValue;
+
+signals:
+  void valueChanged();
+
+protected:
+  virtual void updateCurrentValue(const QVariant& value);
+};
 
 #endif // LXQTPANEL_H
diff --git a/panel/lxqtpanelapplication.cpp b/panel/lxqtpanelapplication.cpp
index 4e0fa14..9a0830d 100644
--- a/panel/lxqtpanelapplication.cpp
+++ b/panel/lxqtpanelapplication.cpp
@@ -32,6 +32,10 @@
 #include <LXQt/Settings>
 #include <QtDebug>
 #include <QUuid>
+
+//# #include <LXQt/XfitMan>
+
+//# #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
 #include <QScreen>
 #include <QWindow>
 
@@ -174,6 +178,9 @@ void LxQtPanelApplication::screenDestroyed(QObject* screenObj)
         qApp->setQuitOnLastWindowClosed(true);
 }
 
+//#else
+
+
 void LxQtPanelApplication::removePanel(LxQtPanel* panel)
 {
     Q_ASSERT(mPanels.contains(panel));
diff --git a/panel/lxqtpanelapplication.h b/panel/lxqtpanelapplication.h
index 0b5f258..96483e5 100644
--- a/panel/lxqtpanelapplication.h
+++ b/panel/lxqtpanelapplication.h
@@ -32,6 +32,13 @@
 #include <LXQt/Application>
 #include "ilxqtpanelplugin.h"
 
+// from system tray plugin
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include <QAbstractNativeEventFilter>
+#endif
+
 class QScreen;
 
 class LxQtPanel;
diff --git a/panel/lxqtpanellayout.cpp b/panel/lxqtpanellayout.cpp
index 4cabdb1..e98b998 100644
--- a/panel/lxqtpanellayout.cpp
+++ b/panel/lxqtpanellayout.cpp
@@ -945,6 +945,8 @@ void LxQtPanelLayout::startMovePlugin()
         PluginMoveProcessor *moveProcessor = new PluginMoveProcessor(this, plugin);
         moveProcessor->start();
         connect(moveProcessor, SIGNAL(finished()), this, SLOT(finishMovePlugin()));
+
+        emit pluginMoving();
     }
 }
 
@@ -960,6 +962,7 @@ void LxQtPanelLayout::finishMovePlugin()
         Plugin *plugin = moveProcessor->plugin();
         int n = indexOf(plugin);
         plugin->setAlignment(n<mLeftGrid->count() ? Plugin::AlignLeft : Plugin::AlignRight);
-        emit pluginMoved();
     }
+
+    emit pluginMoved();
 }
diff --git a/panel/lxqtpanellayout.h b/panel/lxqtpanellayout.h
index e3b950b..5fbc11f 100644
--- a/panel/lxqtpanellayout.h
+++ b/panel/lxqtpanellayout.h
@@ -74,8 +74,10 @@ class LXQT_PANEL_API LxQtPanelLayout : public QLayout
     void setPosition(ILxQtPanel::Position value);
 
     static bool itemIsSeparate(QLayoutItem *item);
+
 signals:
     void pluginMoved();
+    void pluginMoving();
 
 public slots:
     void startMovePlugin();
diff --git a/panel/lxqtpanellimits.h b/panel/lxqtpanellimits.h
index ffc7dea..935f66b 100644
--- a/panel/lxqtpanellimits.h
+++ b/panel/lxqtpanellimits.h
@@ -35,6 +35,9 @@
 #define PANEL_DEFAULT_ICON_SIZE 22
 #define PANEL_DEFAULT_LINE_COUNT 1
 
+#define PANEL_DEFAULT_AUTOHIDE 0
+#define PANEL_DEFAULT_AUTOHIDEDURATION 300
+
 #define PANEL_DEFAULT_BACKGROUND_COLOR "#CCCCCC"
 
 #define SETTINGS_SAVE_DELAY 3000
diff --git a/panel/plugin.cpp b/panel/plugin.cpp
index e0504e6..67616b5 100644
--- a/panel/plugin.cpp
+++ b/panel/plugin.cpp
@@ -367,11 +367,13 @@ void Plugin::showConfigureDialog()
         dialog = mPlugin->configureDialog();
         refs[name()] = dialog;
         connect(this, SIGNAL(destroyed()), dialog, SLOT(close()));
+        connect(dialog, SIGNAL(destroyed()), mPanel,SLOT(autohidePermanentUnlock()));
     }
 
     if (!dialog)
         return;
 
+    emit autoHidePermanentLock();
     dialog->show();
     dialog->raise();
     dialog->activateWindow();
diff --git a/panel/plugin.h b/panel/plugin.h
index ca47c1f..1f168cb 100644
--- a/panel/plugin.h
+++ b/panel/plugin.h
@@ -88,6 +88,8 @@ public slots:
 signals:
     void startMove();
     void remove();
+    void autoHidePermanentLock();
+    void autoHidePermanentUnlock();
 
 protected:
     void contextMenuEvent(QContextMenuEvent *event);
diff --git a/plugin-mount/lxqtmountplugin.cpp b/plugin-mount/lxqtmountplugin.cpp
index 379ed03..77c78b2 100644
--- a/plugin-mount/lxqtmountplugin.cpp
+++ b/plugin-mount/lxqtmountplugin.cpp
@@ -60,13 +60,6 @@ QWidget *LxQtMountPlugin::widget()
 }
 
 
-void LxQtMountPlugin::realign()
-{
-    if(mPopup)
-        mPopup->hide();
-}
-
-
 QDialog *LxQtMountPlugin::configureDialog()
 {
     if(mPopup)
diff --git a/plugin-mount/lxqtmountplugin.h b/plugin-mount/lxqtmountplugin.h
index a2e66b5..eeef267 100644
--- a/plugin-mount/lxqtmountplugin.h
+++ b/plugin-mount/lxqtmountplugin.h
@@ -55,7 +55,6 @@ class LxQtMountPlugin : public QObject, public ILxQtPanelPlugin
     virtual QWidget *widget();
     virtual QString themeId() const { return "LxQtMount"; }
     virtual ILxQtPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; }
-    void realign();
     QDialog *configureDialog();
 
     LxQt::MountManager *mountManager() const { return mMountManager; }
diff --git a/plugin-volume/lxqtvolume.cpp b/plugin-volume/lxqtvolume.cpp
index 6dd2977..0f9ee2d 100644
--- a/plugin-volume/lxqtvolume.cpp
+++ b/plugin-volume/lxqtvolume.cpp
@@ -226,10 +226,6 @@ QWidget *LxQtVolume::widget()
     return m_volumeButton;
 }
 
-void LxQtVolume::realign()
-{
-}
-
 QDialog *LxQtVolume::configureDialog()
 {
 	if(!m_configDialog)
diff --git a/plugin-volume/lxqtvolume.h b/plugin-volume/lxqtvolume.h
index b72fe3f..e9d159e 100644
--- a/plugin-volume/lxqtvolume.h
+++ b/plugin-volume/lxqtvolume.h
@@ -56,7 +56,6 @@ class LxQtVolume : public QObject, public ILxQtPanelPlugin
     virtual QWidget *widget();
     virtual QString themeId() const { return "Volume"; }
     virtual ILxQtPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; }
-    void realign();
     QDialog *configureDialog();
 
     void setAudioEngine(AudioEngine *engine);
