--- git.orig/options/default.xml
+++ git/options/default.xml
@@ -496,6 +496,7 @@ QLineEdit#le_status_text {
                 </sounds>
                 <successful-subscription type="bool">true</successful-subscription>
             </notifications>
+            <decorate-windows type="bool">true</decorate-windows>
             <service-discovery>
                 <automatically-get-info type="bool">false</automatically-get-info>
                 <automatically-get-items type="bool">false</automatically-get-items>
--- git.orig/src/groupchatdlg.cpp
+++ git/src/groupchatdlg.cpp
@@ -91,6 +91,7 @@
 #include "pluginmanager.h"
 #endif
 #include "psirichtext.h"
+#include "psiwindowheader.h"
 #include "mcmdsimplesite.h"
 #include "tabcompletion.h"
 #include "vcardfactory.h"
@@ -262,6 +263,7 @@ public:
 public:
     bool trackBar;
     bool tabmode;
+    PsiWindowHeader *winHeader_;
 
     int logHeight;
     int chateditHeight;
@@ -852,6 +854,13 @@ GCMainDlg::GCMainDlg(PsiAccount *pa, con
 
     ui_.setupUi(this);
     d->tabmode = PsiOptions::instance()->getOption("options.ui.tabs.use-tabs").toBool();
+    setWindowBorder(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool());
+    if (!d->tabmode && !isBorder()) {
+        d->winHeader_ = new PsiWindowHeader(this);
+        ui_.vboxLayout1->insertWidget(0, d->winHeader_);
+    }
+    setMargins();
+
     ui_.lb_ident->setAccount(account());
     ui_.lb_ident->setShowJid(false);
     ui_.log->setSessionData(true, false, jid(), jid().full()); //FIXME change conference name
@@ -2331,6 +2340,25 @@ void GCMainDlg::setLooks()
     setMucSelfAvatar();
 }
 
+void GCMainDlg::setMargins()
+{
+    ui_.vboxLayout->setContentsMargins(0,0,0,0);
+    ui_.vboxLayout2->setContentsMargins(4,0,4,4);
+    if (!d->tabmode) {
+        ui_.hboxLayout->setContentsMargins(4,0,4,0);
+        if (!isBorder()) {
+            ui_.vboxLayout1->setContentsMargins(0,0,0,0);
+        }
+        else {
+            ui_.vboxLayout1->setContentsMargins(0,4,0,0);
+        }
+    }
+    else {
+        ui_.vboxLayout1->setContentsMargins(4,4,4,0);
+        ui_.hboxLayout->setContentsMargins(2,0,4,0);
+    }
+}
+
 void GCMainDlg::setToolbuttons()
 {
     ui_.toolbar->clear();
--- git.orig/src/groupchatdlg.h
+++ git/src/groupchatdlg.h
@@ -169,6 +169,7 @@ private:
 
     inline XMPP::Jid jidForNick(const QString &nick) const;
 
+    void setMargins();
     void setMucSelfAvatar();
 };
 
--- git.orig/src/mainwin.cpp
+++ git/src/mainwin.cpp
@@ -130,6 +130,7 @@ public:
     int tabsSize;
     int rosterSize;
     bool isLeftRoster;
+    bool isHide;
 
     PopupAction *optionsButton, *statusButton;
     IconActionGroup *statusGroup, *viewGroups;
@@ -553,6 +554,8 @@ MainWin::MainWin(bool _onTop, bool _asTo
         connect(sp_ss, SIGNAL(triggered()), SLOT(avcallConfig()));*/
     optionChanged("options.ui.contactlist.css");
 
+    setWindowBorder(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool());
+
     reinitAutoHide();
 }
 
@@ -591,6 +594,10 @@ void MainWin::optionChanged(const QStrin
             setStyleSheet(css);
         }
     }
+    else if (option == "options.ui.decorate-windows") {
+        setWindowBorder(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool());
+        show();
+    }
 }
 
 void MainWin::registerAction( IconAction* action )
@@ -1739,6 +1746,7 @@ void MainWin::statusClicked(int x)
 {
     if(x == Qt::MidButton) {
         recvNextEvent();
+        d->isHide = false;
     }
 }
 
@@ -1986,4 +1994,34 @@ void MainWin::resizeEvent(QResizeEvent *
     }
 }
 
+void MainWin::mousePressEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::MidButton && !isBorder()) {
+        d->isHide = true;
+    }
+
+    AdvancedWidget<QMainWindow>::mousePressEvent(e);
+}
+
+void MainWin::mouseReleaseEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::MidButton && !isBorder() && d->isHide) {
+        d->isHide = false;
+        const int x_ = e->globalPos().x();
+        const int y_ = e->globalPos().y();
+        if (x_ >= geometry().left()
+            && x_ <= geometry().right()
+            && y_ >= geometry().top()
+            && y_ <= geometry().bottom()){
+            if (d->asTool){
+                d->mainWin->trayHide();
+            } else {
+                setWindowState(windowState() | Qt::WindowMinimized);
+            }
+        }
+    }
+
+    AdvancedWidget<QMainWindow>::mouseReleaseEvent(e);
+}
+
 //#endif
--- git.orig/src/mainwin.h
+++ git/src/mainwin.h
@@ -26,6 +26,7 @@
 #include <QList>
 #include <QString>
 #include <QStringList>
+#include <QMouseEvent>
 
 #include "advwidget.h"
 #include "xmpp_status.h"
@@ -86,6 +87,8 @@ protected:
 #ifdef Q_OS_WIN
     bool winEvent(MSG *, long *);
 #endif
+    void mousePressEvent(QMouseEvent *e);
+    void mouseReleaseEvent(QMouseEvent *e);
 
 signals:
     void statusChanged(XMPP::Status::Type);
--- git.orig/src/options/opt_application.cpp
+++ git/src/options/opt_application.cpp
@@ -57,6 +57,9 @@ QWidget *OptionsTabApplication::widget()
     w = new OptApplicationUI();
     OptApplicationUI *d = static_cast<OptApplicationUI *>(w);
 
+    d->ck_winDecor->setWhatsThis(
+        tr("Set or remove window decorations for roster and chats."
+        " For chats there are special header with close, hide and maximize buttons"));
     // docklet
     d->ck_docklet->setWhatsThis(
         tr("Makes Psi use a docklet icon, also known as system tray icon."));
@@ -107,6 +110,7 @@ void OptionsTabApplication::applyOptions
     if (!ApplicationInfo::isPortable()) {
         PsiOptions::instance()->setOption("options.keychain.enabled", d->ck_useKeychain->isChecked());
     }
+    PsiOptions::instance()->setOption("options.ui.decorate-windows", d->ck_winDecor->isChecked());
 
     // Auto-update
     PsiOptions::instance()->setOption("options.auto-update.check-on-startup", d->ck_autoUpdate->isChecked());
@@ -177,6 +181,7 @@ void OptionsTabApplication::restoreOptio
     if (!ApplicationInfo::isPortable()) {
         d->ck_useKeychain->setChecked(PsiOptions::instance()->getOption("options.keychain.enabled").toBool());
     }
+    d->ck_winDecor->setChecked(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool());
 
     // docklet
     d->ck_docklet->setChecked( PsiOptions::instance()->getOption("options.ui.systemtray.enable").toBool() );
--- git.orig/src/options/opt_application.ui
+++ git/src/options/opt_application.ui
@@ -22,6 +22,16 @@
     </widget>
    </item>
    <item>
+    <widget class="QCheckBox" name="ck_winDecor" >
+     <property name="text" >
+      <string>Decorate windows</string>
+     </property>
+     <property name="checked" >
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
     <widget class="QCheckBox" name="ck_docklet">
      <property name="text">
       <string>Enable docklet</string>
@@ -240,6 +250,7 @@
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <tabstops>
+  <tabstop>ck_winDecor</tabstop>
   <tabstop>ck_docklet</tabstop>
   <tabstop>ck_dockDCstyle</tabstop>
   <tabstop>ck_dockHideMW</tabstop>
--- git.orig/src/psichatdlg.cpp
+++ git/src/psichatdlg.cpp
@@ -183,6 +183,9 @@ PsiChatDlg::PsiChatDlg(const Jid& jid, P
     connect(account(), SIGNAL(removedContact(PsiContact*)), SLOT(updateContactAdding(PsiContact*)));
     connect(account(), SIGNAL(updateContact(const Jid &)), SLOT(updateContactAdding(const Jid &)));
     mCmdManager_.registerProvider(new ChatDlgMCmdProvider(this));
+    tabmode = PsiOptions::instance()->getOption("options.ui.tabs.use-tabs").toBool();
+    setWindowBorder(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool());
+
     SendButtonTemplatesMenu* menu = getTemplateMenu();
     if (menu) {
         connect(menu, SIGNAL(doPasteAndSend()), this, SLOT(doPasteAndSend()));
@@ -283,6 +286,11 @@ void PsiChatDlg::initUi()
     act_mini_cmd_->setText(tr("Input command..."));
     connect(act_mini_cmd_, SIGNAL(triggered()), SLOT(doMiniCmd()));
     addAction(act_mini_cmd_);
+    if (!tabmode) {
+        winHeader_ = new PsiWindowHeader(this);
+        ui_.vboxLayout1->insertWidget(0, winHeader_);
+    }
+    setMargins();
 
     connect(ui_.log->textWidget(), SIGNAL(quote(const QString &)), ui_.mle->chatEdit(), SLOT(insertAsQuote(const QString &)));
 
@@ -592,6 +600,22 @@ void PsiChatDlg::activated()
     ChatDlg::activated();
 
     updateCountVisibility();
+
+    bool border = PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool();
+    if (!PsiOptions::instance()->getOption("options.ui.tabs.use-tabs").toBool()){
+        if (!winHeader_.isNull())
+            winHeader_->setVisible(!border);
+        setWindowBorder(border);
+        setMargins();
+#if defined(Q_OS_MAC) || defined(Q_WS_HAIKU)
+        //
+#else
+        bringToFront(true);
+#endif
+    } else {
+        if (!winHeader_.isNull())
+            winHeader_->setVisible(false);
+    }
 }
 
 void PsiChatDlg::setContactToolTip(QString text)
@@ -1133,4 +1157,23 @@ void PsiChatDlg::doSwitchJidMode()
     }
 }
 
+void PsiChatDlg::setMargins()
+{
+    ui_.vboxLayout->setContentsMargins(0,0,0,0);
+    ui_.vboxLayout2->setContentsMargins(4,0,4,4);
+    if (!tabmode) {
+        ui_.hboxLayout->setContentsMargins(4,0,4,0);
+        if (!isBorder()) {
+            ui_.vboxLayout1->setContentsMargins(0,0,0,0);
+        }
+        else {
+            ui_.vboxLayout1->setContentsMargins(0,4,0,0);
+        }
+    }
+    else {
+        ui_.vboxLayout1->setContentsMargins(4,4,4,0);
+        ui_.hboxLayout->setContentsMargins(2,0,4,0);
+    }
+}
+
 #include "psichatdlg.moc"
--- git.orig/src/psichatdlg.h
+++ git/src/psichatdlg.h
@@ -10,6 +10,7 @@
 
 #include "ui_chatdlg.h"
 #include "typeaheadfind.h"
+#include "psiwindowheader.h"
 #include "widgets/actionlineedit.h"
 #include "actionlist.h"
 
@@ -86,6 +87,7 @@ private:
     ChatEdit* chatEdit() const;
     void updateAutojidIcon();
     void setJidComboItem(int pos, const QString &text, const Jid &jid, const QString &icon_str);
+    void setMargins();
 
 private:
     Ui::ChatDlg ui_;
@@ -112,9 +114,10 @@ private:
     class ChatDlgMCmdProvider;
 
     static PsiIcon *throbber_icon;
-
+    QPointer <PsiWindowHeader> winHeader_;
     int logHeight;
     int chateditHeight;
+    bool tabmode;
 };
 
 #endif
--- git.orig/src/tabs/tabdlg.cpp
+++ git/src/tabs/tabdlg.cpp
@@ -167,9 +167,19 @@ TabDlg::TabDlg(TabManager* tabManager, c
         delegate_->tabWidgetCreated(this, tabWidget_);
 
     QVBoxLayout *vert1 = new QVBoxLayout(this);
-    vert1->setMargin(1);
+    //Add windowheader widget if window not decorated
+    if (!PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool()
+        && !PsiOptions::instance()->getOption("options.ui.tabs.grouping").toString().contains('A')) {
+        winHeader_ = new PsiWindowHeader(this);
+        vert1->addWidget(winHeader_);
+        vert1->setSpacing(0);
+        vert1->setMargin(0);
+    } else {
+        vert1->setMargin(1);
+    }
     vert1->addWidget(tabWidget_);
 
+
     setAcceptDrops(true);
 
     X11WM_CLASS("tabs");
@@ -189,6 +199,7 @@ TabDlg::TabDlg(TabManager* tabManager, c
 
     if(!PsiOptions::instance()->getOption("options.ui.tabs.grouping").toString().contains('A'))
         setGeometryOptionPath(geometryOption);
+    setWindowBorder(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool());
 }
 
 TabDlg::~TabDlg()
--- git.orig/src/tabs/tabdlg.h
+++ git/src/tabs/tabdlg.h
@@ -29,6 +29,7 @@
 #include "advwidget.h"
 
 #include "tabbablewidget.h"
+#include "psiwindowheader.h"
 
 class PsiCon;
 class ChatTabs;
@@ -174,6 +175,7 @@ private:
     void extinguishFlashingTabs();
     void updateCaption();
     void updateTabBar();
+    PsiWindowHeader *winHeader_;
 };
 
 #endif
--- git.orig/src/tools/advwidget/advwidget.cpp
+++ git/src/tools/advwidget/advwidget.cpp
@@ -386,7 +386,11 @@ bool GAdvancedWidget::Private::eventFilt
             }
             saveGeometryTimer_->start();
         }
-
+#if defined(Q_OS_WIN)
+        if (e->type() == QEvent::Show) {
+            parentWidget_->setAttribute(Qt::WA_Mapped);
+        }
+#endif
         return false;
     }
 
--- git.orig/src/tools/advwidget/advwidget.h
+++ git/src/tools/advwidget/advwidget.h
@@ -1,6 +1,6 @@
 /*
  * advwidget.h - AdvancedWidget template class
- * Copyright (C) 2005-2007  Michail Pishchagin
+ * Copyright (C) 2005-2007  Michail Pishchagin, 2017  Evgeny Khryukin
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,6 +21,7 @@
 #ifndef ADVWIDGET_H
 #define ADVWIDGET_H
 
+#include <QMouseEvent>
 #include <QWidget>
 
 class GAdvancedWidget : public QObject
@@ -65,14 +66,205 @@ class AdvancedWidget : public BaseClass
 {
 private:
     GAdvancedWidget *gAdvWidget;
+#ifdef Q_OS_WIN
+    Qt::WindowFlags deltaflags;
+#endif
+    QPoint movePath_;
+    bool border_;
+    Qt::WindowFrameSection region_;
+    static const int resizeAccuracy_ = 10;
+    enum class WinAction{None, Dragging, Resizing};
+    WinAction action_;
+    Qt::WindowFrameSection getMouseRegion(const int mouse_x, const int mouse_y, const QRect &geom) const
+    {
+        const int top = geom.top();
+        const int bottom = geom.bottom();
+        const int left = geom.left();
+        const int right = geom.right();
+        const int maxtop = top + resizeAccuracy_;
+        const int minbottom = bottom -resizeAccuracy_;
+        if(qAbs(bottom - mouse_y) < resizeAccuracy_
+           && qAbs(mouse_x - left) < resizeAccuracy_) {
+                return Qt::BottomLeftSection;
+        }
+        else if (mouse_x > (left + resizeAccuracy_)
+             && mouse_x < (right - resizeAccuracy_)
+             && qAbs(mouse_y - bottom) < resizeAccuracy_)
+        {
+            return Qt::BottomSection;
+        }
+        else if (qAbs(bottom - mouse_y) < resizeAccuracy_
+             && qAbs(mouse_x - right) < resizeAccuracy_)
+        {
+            return Qt::BottomRightSection;
+        }
+        else if (qAbs(right - mouse_x) < resizeAccuracy_
+             &&  mouse_y > maxtop
+             && mouse_y < minbottom)
+        {
+            return Qt::RightSection;
+        }
+        else if (qAbs(mouse_x - left) < resizeAccuracy_
+             &&  mouse_y > maxtop
+             && mouse_y < minbottom)
+        {
+            return Qt::LeftSection;
+        }
+        else if (qAbs(mouse_y - top) < resizeAccuracy_
+             && mouse_x > (left + resizeAccuracy_)
+             && mouse_x < (right -resizeAccuracy_))
+        {
+            return Qt::TopSection;
+        }
+        else if (qAbs(top - mouse_y) < resizeAccuracy_
+             && qAbs(mouse_x - right) < resizeAccuracy_)
+        {
+            return Qt::TopRightSection;
+        }
+        else if (qAbs(top - mouse_y) < resizeAccuracy_
+             && qAbs(mouse_x - left) < resizeAccuracy_)
+        {
+            return Qt::TopLeftSection;
+        }
+
+        return Qt::NoSection;
+    }
+    void doWindowResize(QWidget *window, const QPoint &eventPos, Qt::WindowFrameSection region)
+    {
+        int ypath = 0;
+        int xpath = 0;
+        const QRect winGeom = window->geometry();
+        const int right = winGeom.right();
+        const int left =  winGeom.left();
+        const int top =  winGeom.top();
+        const int bottom = winGeom.bottom();
+
+        switch (region) {
+        case Qt::BottomLeftSection:
+            ypath =  eventPos.y() - bottom;
+            xpath = left - eventPos.x();
+            if ((window->width() + xpath) < window->minimumWidth()) {
+                xpath = window->minimumWidth() - window->width();
+            }
+            window->setGeometry(window->x() - xpath, window->y(),
+                        window->width() + xpath, window->height() + ypath);
+            break;
+        case Qt::BottomRightSection:
+            ypath = eventPos.y() - bottom;
+            xpath = eventPos.x() - right;
+            window->resize(window->width() + xpath, window->height() + ypath);
+            break;
+        case Qt::TopLeftSection:
+            ypath =  top - eventPos.y();
+            xpath = left - eventPos.x();
+            if ((window->width() + xpath) < window->minimumWidth()) {
+                xpath = window->minimumWidth() - window->width();
+            }
+            if ((window->height() + ypath) < window->minimumHeight()) {
+                ypath = window->minimumHeight() - window->height();
+            }
+            window->setGeometry(window->x() - xpath, window->y() - ypath,
+                        window->width() + xpath, window->height() + ypath);
+            break;
+        case Qt::TopRightSection:
+            ypath =  top - eventPos.y();
+            xpath = eventPos.x() - right;
+            if ((window->width() + xpath) < window->minimumWidth()) {
+                xpath = window->minimumWidth() - window->width();
+            }
+            if ((window->height() + ypath) < window->minimumHeight()) {
+                ypath = window->minimumHeight() - window->height();
+            }
+            window->setGeometry(window->x(), window->y() - ypath,
+                        window->width() + xpath, window->height() + ypath);
+            break;
+        case Qt::BottomSection:
+            ypath =  eventPos.y() - bottom;
+            window->resize(window->width(), window->height() + ypath);
+            break;
+        case Qt::RightSection:
+            xpath =  eventPos.x() - right;
+            window->resize(window->width() + xpath, window->height());
+            break;
+        case Qt::LeftSection:
+            xpath =  left - eventPos.x();
+            if ((window->width() + xpath) < window->minimumWidth()) {
+                xpath = window->minimumWidth() - window->width();
+            }
+            window->setGeometry(window->x() - xpath, window->y(),
+                        window->width() + xpath, window->height());
+            break;
+        case Qt::TopSection:
+            ypath =  top - eventPos.y();
+            if ((window->height() + ypath) < window->minimumHeight()) {
+                ypath = window->minimumHeight() - window->height();
+            }
+            window->setGeometry(window->x(), window->y() - ypath,
+                        window->width(), window->height() + ypath);
+            break;
+        case Qt::NoSection:
+        default:
+            break;
+        }
+    }
+    void updateCursor(Qt::WindowFrameSection region, QWidget *window)
+    {
+        switch (region) {
+        case Qt::BottomLeftSection:
+            window->setCursor(QCursor(Qt::SizeBDiagCursor));
+            break;
+        case Qt::BottomRightSection:
+            window->setCursor(QCursor(Qt::SizeFDiagCursor));
+            break;
+        case Qt::TopLeftSection:
+            window->setCursor(QCursor(Qt::SizeFDiagCursor));
+            break;
+        case Qt::TopRightSection:
+            window->setCursor(QCursor(Qt::SizeBDiagCursor));
+            break;
+        case Qt::BottomSection:
+            window->setCursor(QCursor(Qt::SizeVerCursor));
+            break;
+        case Qt::RightSection:
+            window->setCursor(QCursor(Qt::SizeHorCursor));
+            break;
+        case Qt::LeftSection:
+            window->setCursor(QCursor(Qt::SizeHorCursor));
+            break;
+        case Qt::TopSection:
+            window->setCursor(QCursor(Qt::SizeVerCursor));
+            break;
+        case Qt::NoSection:
+        default:
+            window->setCursor(QCursor(Qt::ArrowCursor));
+            break;
+        }
+    }
+    void enableMouseTracking(bool enabled)
+    {
+        BaseClass::setMouseTracking(enabled);
+        QWidget *bw = BaseClass::window();
+        QList<QWidget *> children = bw->findChildren<QWidget*>();
+        foreach (QWidget *w, children) {
+            w->setMouseTracking(enabled);
+        }
+        if (!enabled) {
+            BaseClass::window()->setCursor(QCursor(Qt::ArrowCursor));
+        }
+    }
+    bool isMaximized() const
+    {
+        return (BaseClass::window()->windowState() == Qt::WindowMaximized)||(BaseClass::window()->windowState() == Qt::WindowFullScreen);
+    }
 
 public:
-    AdvancedWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
+    AdvancedWidget(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr)
         : BaseClass(parent)
-        , gAdvWidget(0)
+        , gAdvWidget(nullptr)
     {
         if (f != 0)
             BaseClass::setWindowFlags(f);
+        border_ = true;
         gAdvWidget = new GAdvancedWidget( this );
     }
 
@@ -151,6 +343,49 @@ public:
         windowTitleChanged();
     }
 
+    void setWindowBorder(bool isDecorated)
+    {
+        Qt::WindowFlags flags = BaseClass::windowFlags();
+#ifdef Q_OS_WIN
+        if (deltaflags == 0) {
+            deltaflags = flags;
+        }
+        if (isDecorated) {
+            if (flags != deltaflags) {
+                flags |= Qt::WindowTitleHint;
+                flags &= ~Qt::FramelessWindowHint;
+                deltaflags = 0;
+                if (flags != BaseClass::windowFlags()) {
+                    setWindowFlags(flags);
+                }
+            }
+        } else {
+            flags &= ~Qt::WindowTitleHint;
+            flags |= Qt::FramelessWindowHint;
+            if (flags != BaseClass::windowFlags()) {
+                setWindowFlags(flags);
+            }
+
+        }
+#else
+        if (isDecorated) {
+            flags &= ~Qt::FramelessWindowHint;
+        } else {
+            flags |= Qt::FramelessWindowHint;
+        }
+        if (flags != BaseClass::windowFlags()) {
+            setWindowFlags(flags);
+        }
+#endif
+        border_ = isDecorated;
+        BaseClass::setMouseTracking(!isDecorated);
+        //enableMouseTracking(!isDecorated);
+    }
+    bool isBorder() const
+    {
+        return border_;
+    }
+
 protected:
     virtual void windowTitleChanged()
     {
@@ -165,6 +400,63 @@ protected:
         }
         BaseClass::changeEvent(event);
     }
+
+protected:
+    void setWindowFlags(Qt::WindowFlags flags)
+    {
+        BaseClass::setWindowFlags(flags);
+    }
+    void mousePressEvent(QMouseEvent *event)
+    {
+        if (!border_ && (event->button()==Qt::LeftButton) && !isMaximized()) {
+            QWidget *window = BaseClass::window();
+            region_ = getMouseRegion(event->globalPos().x(), event->globalPos().y(), window->geometry());
+            if (region_ != Qt::NoSection) {
+                action_ = WinAction::Resizing;
+                updateCursor(region_, BaseClass::window());
+            }
+            else{
+                movePath_ = event->globalPos() - window->pos();
+                action_ = WinAction::Dragging;
+            }
+        }
+        BaseClass::mousePressEvent(event);
+    }
+    void mouseMoveEvent(QMouseEvent *event)
+    {
+        if(!border_ && !isMaximized()) {
+            bool isLeftButton = (event->buttons() & Qt::LeftButton);
+            const QPoint pg = event->globalPos();
+            QWidget *window = BaseClass::window();
+
+            if(!isLeftButton) {
+                Qt::WindowFrameSection region = getMouseRegion(pg.x(), pg.y(), window->geometry());
+
+                updateCursor(region, window);
+            }
+            else if (isLeftButton && action_ == WinAction::Resizing) {
+                doWindowResize(window, pg, region_);
+            }
+            else if(isLeftButton && action_ == WinAction::Dragging) {
+                window->setCursor(QCursor(Qt::SizeAllCursor));
+                window->move(pg - movePath_);
+            }
+        }
+
+        BaseClass::mouseMoveEvent(event);
+    }
+    void mouseReleaseEvent(QMouseEvent *event)
+    {
+        QWidget *window = BaseClass::window();
+        if (!border_ && (event->button() == Qt::LeftButton)
+            && action_ == WinAction::Dragging && !isMaximized()) {
+            movePath_ = QPoint(0,0);
+            action_ = WinAction::None;
+        }
+        window->setCursor(QCursor(Qt::ArrowCursor));
+
+        BaseClass::mouseReleaseEvent(event);
+    }
 };
 
 #endif
--- git.orig/src/widgets/psiwindowheader.cpp
+++ git/src/widgets/psiwindowheader.cpp
@@ -0,0 +1,271 @@
+/*
+ * psiwindowheader.cpp
+ * Copyright (C) 2010-2017  Evgeny Khryukin, Vitaly Tonkacheyev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#include <QIcon>
+#include <QApplication>
+#include <QStyle>
+
+#include "psiwindowheader.h"
+#include "psiiconset.h"
+#include "psioptions.h"
+
+PsiWindowHeader::PsiWindowHeader(QWidget *p)
+    : QWidget(p),
+      maximized_(false)
+{
+    parent_ = p->window();
+    ui_.setupUi(this);
+#ifdef Q_OS_MAC
+    ui_.horiz->insertWidget(0, ui_.closeButton);
+    ui_.horiz->insertWidget(1, ui_.hideButton);
+    ui_.horiz->insertWidget(2, ui_.maximizeButton);
+#endif
+    ui_.hideButton->setIcon(qApp->style()->standardIcon(QStyle::SP_TitleBarMinButton));
+    ui_.maximizeButton->setIcon(qApp->style()->standardIcon(QStyle::SP_TitleBarMaxButton));
+    ui_.closeButton->setIcon(qApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
+    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+    connect(ui_.hideButton, SIGNAL(clicked()), SLOT(hidePressed()));
+    connect(ui_.closeButton, SIGNAL(clicked()), SLOT(closePressed()));
+    connect(ui_.maximizeButton, SIGNAL(clicked()), SLOT(maximizePressed()));
+    setMouseTracking(true);
+    enableMouseTracking(true);
+}
+
+PsiWindowHeader::~PsiWindowHeader()
+{
+    //Disable mouse tracking on widget deletion
+    if(PsiOptions::instance()->getOption("options.ui.decorate-windows").toBool()) {
+        enableMouseTracking(false);
+    }
+}
+
+void PsiWindowHeader::hidePressed()
+{
+    parent_->setWindowState(parent_->windowState() | Qt::WindowMinimized);
+}
+
+void PsiWindowHeader::closePressed()
+{
+    parent_->close();
+}
+
+void PsiWindowHeader::maximizePressed()
+{
+    if(parent_->window()->windowState() != Qt::WindowMaximized) {
+        parent_->window()->showMaximized();
+        maximized_ = true;
+    }
+    else {
+        parent_->window()->showNormal();
+        maximized_ = false;
+    }
+}
+
+void PsiWindowHeader::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        maximizePressed();
+        e->accept();
+    }
+}
+
+void PsiWindowHeader::mousePressEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton && isVisible()) {
+        region_ = getMouseRegion(e->globalPos().x(), e->globalPos().y(), parent_->window()->geometry());
+        if (region_ != Qt::NoSection) {
+            action_ = WinAction::Resizing;
+            updateCursor(region_);
+        }
+        else{
+            movePath_ = e->globalPos() - parent_->window()->pos();
+            action_ = WinAction::Dragging;
+        }
+        e->accept();
+    }
+}
+
+void PsiWindowHeader::mouseMoveEvent(QMouseEvent *e)
+{
+    if(isVisible()) {
+        bool isLeftButton = (e->buttons() & Qt::LeftButton);
+        const QPoint pg = e->globalPos();
+        if (!isLeftButton && !maximized_) {
+            Qt::WindowFrameSection region = getMouseRegion(pg.x(), pg.y(), parent_->window()->geometry());
+            updateCursor(region);
+        }
+        else if(isLeftButton && action_ == WinAction::Resizing && !maximized_) {
+            doWindowResize(parent_->window(), pg, region_);
+        }
+        else if(isLeftButton && action_ == WinAction::Dragging && !maximized_) {
+            setCursor(QCursor(Qt::SizeAllCursor));
+            parent_->window()->move( pg - movePath_ );
+        }
+    }
+    e->accept();
+}
+
+void PsiWindowHeader::doWindowResize(QWidget* window, const QPoint& eventPos, Qt::WindowFrameSection region)
+{
+    int ypath = 0;
+    int xpath = 0;
+    const QRect winGeom = window->geometry();
+    const int right = winGeom.right();
+    const int left =  winGeom.left();
+    const int top =  winGeom.top();
+    switch(region) {
+    case Qt::TopLeftSection:
+        ypath =  top - eventPos.y();
+        xpath = left - eventPos.x();
+        if ((window->width() + xpath) < window->minimumWidth()) {
+            xpath = window->minimumWidth() - window->width();
+        }
+        if ((window->height() + ypath) < window->minimumHeight()) {
+            ypath = window->minimumHeight() - window->height();
+        }
+        window->setGeometry(window->x() - xpath, window->y() - ypath,
+                    window->width() + xpath, window->height() + ypath);
+        break;
+    case Qt::TopRightSection:
+        ypath =  top - eventPos.y();
+        xpath = eventPos.x() - right;
+        if ((window->width() + xpath) < window->minimumWidth()) {
+            xpath = window->minimumWidth() - window->width();
+        }
+        if ((window->height() + ypath) < window->minimumHeight()) {
+            ypath = window->minimumHeight() - window->height();
+        }
+        window->setGeometry(window->x(), window->y() - ypath,
+                    window->width() + xpath, window->height() + ypath);
+        break;
+    case Qt::RightSection:
+        xpath =  eventPos.x() - right;
+        window->resize(window->width() + xpath, window->height());
+        break;
+    case Qt::LeftSection:
+        xpath =  left - eventPos.x();
+        if ((window->width() + xpath) < window->minimumWidth()) {
+            xpath = window->minimumWidth() - window->width();
+        }
+        window->setGeometry(window->x() - xpath, window->y(),
+                    window->width() + xpath, window->height());
+        break;
+    case Qt::TopSection:
+        ypath =  top - eventPos.y();
+        if ((window->height() + ypath) < window->minimumHeight()) {
+            ypath = window->minimumHeight() - window->height();
+        }
+        window->setGeometry(window->x(), window->y() - ypath,
+                    window->width(), window->height() + ypath);
+        break;
+    case(Qt::NoSection):
+    default:
+        break;
+    }
+}
+
+Qt::WindowFrameSection PsiWindowHeader::getMouseRegion(const int mouse_x, const int mouse_y, const QRect &geom) const
+{
+    const int mouseAccuracy = 7;
+    const int top = geom.top();
+    const int left = geom.left();
+    const int right = geom.right();
+    const int maxtop = top + mouseAccuracy;
+    if(qAbs(top - mouse_y) < mouseAccuracy
+        && qAbs(mouse_x - left) < mouseAccuracy) {
+        return Qt::TopLeftSection;
+    }
+    else if(qAbs(top -mouse_y) < mouseAccuracy
+        && qAbs(mouse_x - right) < mouseAccuracy) {
+        return Qt::TopRightSection;
+    }
+    else if (mouse_x > (left + mouseAccuracy)
+        && mouse_x < (right - mouseAccuracy)
+        && qAbs(mouse_y - top) < mouseAccuracy) {
+        return Qt::TopSection;
+    }
+    else if (qAbs(right - mouse_x) < mouseAccuracy
+             &&  mouse_y > maxtop) {
+        return Qt::RightSection;
+    }
+    else if (qAbs(mouse_x - left) < mouseAccuracy
+         &&  mouse_y > maxtop) {
+        return Qt::LeftSection;
+    }
+    return Qt::NoSection;
+}
+
+void PsiWindowHeader::mouseReleaseEvent(QMouseEvent *e)
+{
+    if(isVisible()) {
+        if (e->button() == Qt::LeftButton && action_ == WinAction::Dragging) {
+            movePath_ = QPoint(0,0);
+            action_ = WinAction::None;
+        }
+        int min_x = qMin(ui_.hideButton->geometry().left(), qMin(ui_.maximizeButton->geometry().left(), ui_.closeButton->geometry().left()));
+        int max_x = qMax(ui_.hideButton->geometry().right(), qMax(ui_.maximizeButton->geometry().right(), ui_.closeButton->geometry().right()));
+        if (e->button() == Qt::MidButton) {
+            if (((e->x() > geometry().left() && e->x() < min_x)
+                || (e->x() < geometry().right() && e->x() > max_x ))
+                && e->y() > geometry().top()
+                && e->y() < geometry().bottom()) {
+                hidePressed();
+            }
+        }
+        setCursor(QCursor(Qt::ArrowCursor));
+    }
+    e->accept();
+}
+
+void PsiWindowHeader::updateCursor(Qt::WindowFrameSection region)
+{
+    switch (region) {
+    case Qt::TopLeftSection:
+        setCursor(QCursor(Qt::SizeFDiagCursor));
+        break;
+    case Qt::TopRightSection:
+        setCursor(QCursor(Qt::SizeBDiagCursor));
+        break;
+    case Qt::RightSection:
+        setCursor(QCursor(Qt::SizeHorCursor));
+        break;
+    case Qt::LeftSection:
+        setCursor(QCursor(Qt::SizeHorCursor));
+        break;
+    case Qt::TopSection:
+        setCursor(QCursor(Qt::SizeVerCursor));
+        break;
+    case Qt::NoSection:
+    default:
+        setCursor(QCursor(Qt::ArrowCursor));
+        break;
+    }
+}
+
+void PsiWindowHeader::enableMouseTracking(bool enabled)
+{
+    //Dirty hack to enable mouse tracking for psichatdlg
+    /*foreach (QWidget *w, qApp->allWidgets()) {
+        w->setMouseTracking(enabled);
+    }*/
+    this->setMouseTracking(enabled);
+}
--- git.orig/src/widgets/psiwindowheader.h
+++ git/src/widgets/psiwindowheader.h
@@ -0,0 +1,66 @@
+/*
+ * psiwindowheader.cpp
+ * Copyright (C) 2010-2017  Evgeny Khryukin, Vitaly Tonkacheyev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#ifndef PSIWINDOWHEADER_H
+#define PSIWINDOWHEADER_H
+
+#include "ui_psiwindowheader.h"
+
+#include <QToolButton>
+#include <QMouseEvent>
+#include <QRect>
+
+class PsiWindowHeader : public QWidget
+{
+    Q_OBJECT
+public:
+    PsiWindowHeader(QWidget* p);
+    ~PsiWindowHeader();
+
+private:
+    Ui::PsiWindowHeader ui_;
+    QWidget *parent_;
+private:
+    enum class WinAction{None, Dragging, Resizing};
+    Qt::WindowFrameSection getMouseRegion(const int mouse_x, const int mouse_y, const QRect &geom) const;
+    void doWindowResize(QWidget* window, const QPoint& eventPos, Qt::WindowFrameSection region);
+    void updateCursor(Qt::WindowFrameSection region);
+    void enableMouseTracking(bool enabled);
+private:
+    QPoint movePath_;
+    bool maximized_;
+    Qt::WindowFrameSection region_;
+    WinAction action_;
+
+private slots:
+    void hidePressed();
+    void closePressed();
+    void maximizePressed();
+
+protected:
+    void mouseMoveEvent(QMouseEvent *e);
+    void mousePressEvent(QMouseEvent *e);
+    void mouseReleaseEvent(QMouseEvent *e);
+    void mouseDoubleClickEvent(QMouseEvent *e);
+
+};
+
+#endif // PSIWINDOWHEADER_H
--- git.orig/src/widgets/psiwindowheader.ui
+++ git/src/widgets/psiwindowheader.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PsiWindowHeader</class>
+ <widget class="QWidget" name="PsiWindowHeader">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>130</width>
+    <height>31</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="mouseTracking">
+   <bool>true</bool>
+  </property>
+  <property name="windowTitle">
+   <string>PsiWindowHeader</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <layout class="QHBoxLayout" name="horiz">
+     <property name="spacing">
+      <number>0</number>
+     </property>
+     <item>
+      <widget class="QFrame" name="headerFrame">
+       <property name="frameShape">
+        <enum>QFrame::NoFrame</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Plain</enum>
+       </property>
+       <property name="lineWidth">
+        <number>1</number>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="margin">
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" name="horiz1">
+          <property name="spacing">
+           <number>2</number>
+          </property>
+          <item>
+           <spacer name="spacer">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QToolButton" name="hideButton">
+            <property name="text">
+             <string>...</string>
+            </property>
+            <property name="autoRaise">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QToolButton" name="maximizeButton">
+            <property name="text">
+             <string>...</string>
+            </property>
+            <property name="autoRaise">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QToolButton" name="closeButton">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>...</string>
+            </property>
+            <property name="autoRaise">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- git.orig/src/widgets/widgets.pri
+++ git/src/widgets/widgets.pri
@@ -16,6 +16,7 @@ SOURCES += \
     $$PWD/psitiplabel.cpp \
     $$PWD/psitabwidget.cpp \
     $$PWD/psitabbar.cpp \
+    $$PWD/psiwindowheader.cpp \
     $$PWD/actionlineedit.cpp \
     $$PWD/tabbar.cpp \
     $$PWD/typeaheadfind.cpp \
@@ -45,12 +46,14 @@ HEADERS += \
     $$PWD/psitiplabel.h \
     $$PWD/psitabwidget.h \
     $$PWD/psitabbar.h \
+    $$PWD/psiwindowheader.h \
     $$PWD/actionlineedit.h \
     $$PWD/tabbar.h \
     $$PWD/typeaheadfind.h \
     $$PWD/pixmapratiolabel.h
 
-FORMS += $$PWD/fancypopup.ui
+FORMS += $$PWD/fancypopup.ui \
+    $$PWD/psiwindowheader.ui
 
 # to remove dependency on iconset and stuff
 #DEFINES += WIDGET_PLUGIN
