aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/advanceddockingsystem/floatingdockcontainer.cpp')
-rw-r--r--src/libs/advanceddockingsystem/floatingdockcontainer.cpp689
1 files changed, 525 insertions, 164 deletions
diff --git a/src/libs/advanceddockingsystem/floatingdockcontainer.cpp b/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
index 18c70834dd..787c58e832 100644
--- a/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
+++ b/src/libs/advanceddockingsystem/floatingdockcontainer.cpp
@@ -41,6 +41,12 @@
#include "dockoverlay.h"
#include "dockwidget.h"
#include "linux/floatingwidgettitlebar.h"
+#ifdef Q_OS_WIN
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "User32.lib")
+#endif
+#endif
#include <QAbstractButton>
#include <QAction>
@@ -56,6 +62,303 @@ static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWar
namespace ADS
{
+#ifdef Q_OS_WIN
+#if 0 // set to 1 if you need this function for debugging
+/**
+ * Just for debugging to convert windows message identifiers to strings
+ */
+static const char* windowsMessageString(int messageId)
+{
+ switch (messageId)
+ {
+ case 0: return "WM_NULL";
+ case 1: return "WM_CREATE";
+ case 2: return "WM_DESTROY";
+ case 3: return "WM_MOVE";
+ case 5: return "WM_SIZE";
+ case 6: return "WM_ACTIVATE";
+ case 7: return "WM_SETFOCUS";
+ case 8: return "WM_KILLFOCUS";
+ case 10: return "WM_ENABLE";
+ case 11: return "WM_SETREDRAW";
+ case 12: return "WM_SETTEXT";
+ case 13: return "WM_GETTEXT";
+ case 14: return "WM_GETTEXTLENGTH";
+ case 15: return "WM_PAINT";
+ case 16: return "WM_CLOSE";
+ case 17: return "WM_QUERYENDSESSION";
+ case 18: return "WM_QUIT";
+ case 19: return "WM_QUERYOPEN";
+ case 20: return "WM_ERASEBKGND";
+ case 21: return "WM_SYSCOLORCHANGE";
+ case 22: return "WM_ENDSESSION";
+ case 24: return "WM_SHOWWINDOW";
+ case 25: return "WM_CTLCOLOR";
+ case 26: return "WM_WININICHANGE";
+ case 27: return "WM_DEVMODECHANGE";
+ case 28: return "WM_ACTIVATEAPP";
+ case 29: return "WM_FONTCHANGE";
+ case 30: return "WM_TIMECHANGE";
+ case 31: return "WM_CANCELMODE";
+ case 32: return "WM_SETCURSOR";
+ case 33: return "WM_MOUSEACTIVATE";
+ case 34: return "WM_CHILDACTIVATE";
+ case 35: return "WM_QUEUESYNC";
+ case 36: return "WM_GETMINMAXINFO";
+ case 38: return "WM_PAINTICON";
+ case 39: return "WM_ICONERASEBKGND";
+ case 40: return "WM_NEXTDLGCTL";
+ case 42: return "WM_SPOOLERSTATUS";
+ case 43: return "WM_DRAWITEM";
+ case 44: return "WM_MEASUREITEM";
+ case 45: return "WM_DELETEITEM";
+ case 46: return "WM_VKEYTOITEM";
+ case 47: return "WM_CHARTOITEM";
+ case 48: return "WM_SETFONT";
+ case 49: return "WM_GETFONT";
+ case 50: return "WM_SETHOTKEY";
+ case 51: return "WM_GETHOTKEY";
+ case 55: return "WM_QUERYDRAGICON";
+ case 57: return "WM_COMPAREITEM";
+ case 61: return "WM_GETOBJECT";
+ case 65: return "WM_COMPACTING";
+ case 68: return "WM_COMMNOTIFY";
+ case 70: return "WM_WINDOWPOSCHANGING";
+ case 71: return "WM_WINDOWPOSCHANGED";
+ case 72: return "WM_POWER";
+ case 73: return "WM_COPYGLOBALDATA";
+ case 74: return "WM_COPYDATA";
+ case 75: return "WM_CANCELJOURNAL";
+ case 78: return "WM_NOTIFY";
+ case 80: return "WM_INPUTLANGCHANGEREQUEST";
+ case 81: return "WM_INPUTLANGCHANGE";
+ case 82: return "WM_TCARD";
+ case 83: return "WM_HELP";
+ case 84: return "WM_USERCHANGED";
+ case 85: return "WM_NOTIFYFORMAT";
+ case 123: return "WM_CONTEXTMENU";
+ case 124: return "WM_STYLECHANGING";
+ case 125: return "WM_STYLECHANGED";
+ case 126: return "WM_DISPLAYCHANGE";
+ case 127: return "WM_GETICON";
+ case 128: return "WM_SETICON";
+ case 129: return "WM_NCCREATE";
+ case 130: return "WM_NCDESTROY";
+ case 131: return "WM_NCCALCSIZE";
+ case 132: return "WM_NCHITTEST";
+ case 133: return "WM_NCPAINT";
+ case 134: return "WM_NCACTIVATE";
+ case 135: return "WM_GETDLGCODE";
+ case 136: return "WM_SYNCPAINT";
+ case 160: return "WM_NCMOUSEMOVE";
+ case 161: return "WM_NCLBUTTONDOWN";
+ case 162: return "WM_NCLBUTTONUP";
+ case 163: return "WM_NCLBUTTONDBLCLK";
+ case 164: return "WM_NCRBUTTONDOWN";
+ case 165: return "WM_NCRBUTTONUP";
+ case 166: return "WM_NCRBUTTONDBLCLK";
+ case 167: return "WM_NCMBUTTONDOWN";
+ case 168: return "WM_NCMBUTTONUP";
+ case 169: return "WM_NCMBUTTONDBLCLK";
+ case 171: return "WM_NCXBUTTONDOWN";
+ case 172: return "WM_NCXBUTTONUP";
+ case 173: return "WM_NCXBUTTONDBLCLK";
+ case 176: return "EM_GETSEL";
+ case 177: return "EM_SETSEL";
+ case 178: return "EM_GETRECT";
+ case 179: return "EM_SETRECT";
+ case 180: return "EM_SETRECTNP";
+ case 181: return "EM_SCROLL";
+ case 182: return "EM_LINESCROLL";
+ case 183: return "EM_SCROLLCARET";
+ case 185: return "EM_GETMODIFY";
+ case 187: return "EM_SETMODIFY";
+ case 188: return "EM_GETLINECOUNT";
+ case 189: return "EM_LINEINDEX";
+ case 190: return "EM_SETHANDLE";
+ case 191: return "EM_GETHANDLE";
+ case 192: return "EM_GETTHUMB";
+ case 193: return "EM_LINELENGTH";
+ case 194: return "EM_REPLACESEL";
+ case 195: return "EM_SETFONT";
+ case 196: return "EM_GETLINE";
+ case 197: return "EM_LIMITTEXT / EM_SETLIMITTEXT";
+ case 198: return "EM_CANUNDO";
+ case 199: return "EM_UNDO";
+ case 200: return "EM_FMTLINES";
+ case 201: return "EM_LINEFROMCHAR";
+ case 202: return "EM_SETWORDBREAK";
+ case 203: return "EM_SETTABSTOPS";
+ case 204: return "EM_SETPASSWORDCHAR";
+ case 205: return "EM_EMPTYUNDOBUFFER";
+ case 206: return "EM_GETFIRSTVISIBLELINE";
+ case 207: return "EM_SETREADONLY";
+ case 209: return "EM_SETWORDBREAKPROC / EM_GETWORDBREAKPROC";
+ case 210: return "EM_GETPASSWORDCHAR";
+ case 211: return "EM_SETMARGINS";
+ case 212: return "EM_GETMARGINS";
+ case 213: return "EM_GETLIMITTEXT";
+ case 214: return "EM_POSFROMCHAR";
+ case 215: return "EM_CHARFROMPOS";
+ case 216: return "EM_SETIMESTATUS";
+ case 217: return "EM_GETIMESTATUS";
+ case 224: return "SBM_SETPOS";
+ case 225: return "SBM_GETPOS";
+ case 226: return "SBM_SETRANGE";
+ case 227: return "SBM_GETRANGE";
+ case 228: return "SBM_ENABLE_ARROWS";
+ case 230: return "SBM_SETRANGEREDRAW";
+ case 233: return "SBM_SETSCROLLINFO";
+ case 234: return "SBM_GETSCROLLINFO";
+ case 235: return "SBM_GETSCROLLBARINFO";
+ case 240: return "BM_GETCHECK";
+ case 241: return "BM_SETCHECK";
+ case 242: return "BM_GETSTATE";
+ case 243: return "BM_SETSTATE";
+ case 244: return "BM_SETSTYLE";
+ case 245: return "BM_CLICK";
+ case 246: return "BM_GETIMAGE";
+ case 247: return "BM_SETIMAGE";
+ case 248: return "BM_SETDONTCLICK";
+ case 255: return "WM_INPUT";
+ case 256: return "WM_KEYDOWN";
+ case 257: return "WM_KEYUP";
+ case 258: return "WM_CHAR";
+ case 259: return "WM_DEADCHAR";
+ case 260: return "WM_SYSKEYDOWN";
+ case 261: return "WM_SYSKEYUP";
+ case 262: return "WM_SYSCHAR";
+ case 263: return "WM_SYSDEADCHAR";
+ case 265: return "WM_UNICHAR / WM_WNT_CONVERTREQUESTEX";
+ case 266: return "WM_CONVERTREQUEST";
+ case 267: return "WM_CONVERTRESULT";
+ case 268: return "WM_INTERIM";
+ case 269: return "WM_IME_STARTCOMPOSITION";
+ case 270: return "WM_IME_ENDCOMPOSITION";
+ case 272: return "WM_INITDIALOG";
+ case 273: return "WM_COMMAND";
+ case 274: return "WM_SYSCOMMAND";
+ case 275: return "WM_TIMER";
+ case 276: return "WM_HSCROLL";
+ case 277: return "WM_VSCROLL";
+ case 278: return "WM_INITMENU";
+ case 279: return "WM_INITMENUPOPUP";
+ case 280: return "WM_SYSTIMER";
+ case 287: return "WM_MENUSELECT";
+ case 288: return "WM_MENUCHAR";
+ case 289: return "WM_ENTERIDLE";
+ case 290: return "WM_MENURBUTTONUP";
+ case 291: return "WM_MENUDRAG";
+ case 292: return "WM_MENUGETOBJECT";
+ case 293: return "WM_UNINITMENUPOPUP";
+ case 294: return "WM_MENUCOMMAND";
+ case 295: return "WM_CHANGEUISTATE";
+ case 296: return "WM_UPDATEUISTATE";
+ case 297: return "WM_QUERYUISTATE";
+ case 306: return "WM_CTLCOLORMSGBOX";
+ case 307: return "WM_CTLCOLOREDIT";
+ case 308: return "WM_CTLCOLORLISTBOX";
+ case 309: return "WM_CTLCOLORBTN";
+ case 310: return "WM_CTLCOLORDLG";
+ case 311: return "WM_CTLCOLORSCROLLBAR";
+ case 312: return "WM_CTLCOLORSTATIC";
+ case 512: return "WM_MOUSEMOVE";
+ case 513: return "WM_LBUTTONDOWN";
+ case 514: return "WM_LBUTTONUP";
+ case 515: return "WM_LBUTTONDBLCLK";
+ case 516: return "WM_RBUTTONDOWN";
+ case 517: return "WM_RBUTTONUP";
+ case 518: return "WM_RBUTTONDBLCLK";
+ case 519: return "WM_MBUTTONDOWN";
+ case 520: return "WM_MBUTTONUP";
+ case 521: return "WM_MBUTTONDBLCLK";
+ case 522: return "WM_MOUSEWHEEL";
+ case 523: return "WM_XBUTTONDOWN";
+ case 524: return "WM_XBUTTONUP";
+ case 525: return "WM_XBUTTONDBLCLK";
+ case 528: return "WM_PARENTNOTIFY";
+ case 529: return "WM_ENTERMENULOOP";
+ case 530: return "WM_EXITMENULOOP";
+ case 531: return "WM_NEXTMENU";
+ case 532: return "WM_SIZING";
+ case 533: return "WM_CAPTURECHANGED";
+ case 534: return "WM_MOVING";
+ case 536: return "WM_POWERBROADCAST";
+ case 537: return "WM_DEVICECHANGE";
+ case 544: return "WM_MDICREATE";
+ case 545: return "WM_MDIDESTROY";
+ case 546: return "WM_MDIACTIVATE";
+ case 547: return "WM_MDIRESTORE";
+ case 548: return "WM_MDINEXT";
+ case 549: return "WM_MDIMAXIMIZE";
+ case 550: return "WM_MDITILE";
+ case 551: return "WM_MDICASCADE";
+ case 552: return "WM_MDIICONARRANGE";
+ case 553: return "WM_MDIGETACTIVE";
+ case 560: return "WM_MDISETMENU";
+ case 561: return "WM_ENTERSIZEMOVE";
+ case 562: return "WM_EXITSIZEMOVE";
+ case 563: return "WM_DROPFILES";
+ case 564: return "WM_MDIREFRESHMENU";
+ case 640: return "WM_IME_REPORT";
+ case 641: return "WM_IME_SETCONTEXT";
+ case 642: return "WM_IME_NOTIFY";
+ case 643: return "WM_IME_CONTROL";
+ case 644: return "WM_IME_COMPOSITIONFULL";
+ case 645: return "WM_IME_SELECT";
+ case 646: return "WM_IME_CHAR";
+ case 648: return "WM_IME_REQUEST";
+ case 656: return "WM_IME_KEYDOWN";
+ case 657: return "WM_IME_KEYUP";
+ case 672: return "WM_NCMOUSEHOVER";
+ case 673: return "WM_MOUSEHOVER";
+ case 674: return "WM_NCMOUSELEAVE";
+ case 675: return "WM_MOUSELEAVE";
+ case 768: return "WM_CUT";
+ case 769: return "WM_COPY";
+ case 770: return "WM_PASTE";
+ case 771: return "WM_CLEAR";
+ case 772: return "WM_UNDO";
+ case 773: return "WM_RENDERFORMAT";
+ case 774: return "WM_RENDERALLFORMATS";
+ case 775: return "WM_DESTROYCLIPBOARD";
+ case 776: return "WM_DRAWCLIPBOARD";
+ case 777: return "WM_PAINTCLIPBOARD";
+ case 778: return "WM_VSCROLLCLIPBOARD";
+ case 779: return "WM_SIZECLIPBOARD";
+ case 780: return "WM_ASKCBFORMATNAME";
+ case 781: return "WM_CHANGECBCHAIN";
+ case 782: return "WM_HSCROLLCLIPBOARD";
+ case 783: return "WM_QUERYNEWPALETTE";
+ case 784: return "WM_PALETTEISCHANGING";
+ case 785: return "WM_PALETTECHANGED";
+ case 786: return "WM_HOTKEY";
+ case 791: return "WM_PRINT";
+ case 792: return "WM_PRINTCLIENT";
+ case 793: return "WM_APPCOMMAND";
+ case 856: return "WM_HANDHELDFIRST";
+ case 863: return "WM_HANDHELDLAST";
+ case 864: return "WM_AFXFIRST";
+ case 895: return "WM_AFXLAST";
+ case 896: return "WM_PENWINFIRST";
+ case 897: return "WM_RCRESULT";
+ case 898: return "WM_HOOKRCRESULT";
+ case 899: return "WM_GLOBALRCCHANGE / WM_PENMISCINFO";
+ case 900: return "WM_SKB";
+ case 901: return "WM_HEDITCTL / WM_PENCTL";
+ case 902: return "WM_PENMISC";
+ case 903: return "WM_CTLINIT";
+ case 904: return "WM_PENEVENT";
+ case 911: return "WM_PENWINLAST";
+ default:
+ return "unknown WM_ message";
+ }
+
+ return "unknown WM_ message";
+}
+#endif
+#endif
+
AbstractFloatingWidget::~AbstractFloatingWidget() = default;
static unsigned int zOrderCounter = 0;
@@ -74,8 +377,9 @@ namespace ADS
DockContainerWidget *m_dropContainer = nullptr;
DockAreaWidget *m_singleDockArea = nullptr;
QPoint m_dragStartPos;
- QWidget *m_mouseEventHandler = nullptr;
- FloatingWidgetTitleBar *m_titleBar = nullptr;
+ bool m_hiding = false;
+ QWidget *m_mouseEventHandler = nullptr; // linux only
+ FloatingWidgetTitleBar *m_titleBar = nullptr; // linux only
/**
* Private data constructor
@@ -90,7 +394,7 @@ namespace ADS
*/
static bool testConfigFlag(DockManager::eConfigFlag flag)
{
- return DockManager::configFlags().testFlag(flag);
+ return DockManager::testConfigFlag(flag);
}
/**
@@ -146,11 +450,11 @@ namespace ADS
if (m_dockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
|| m_dockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea) {
- // Resize the floating widget to the size of the highlighted drop area rectangle
DockOverlay *overlay = m_dockManager->containerOverlay();
if (!overlay->dropOverlayRect().isValid())
overlay = m_dockManager->dockAreaOverlay();
+ // Resize the floating widget to the size of the highlighted drop area rectangle
QRect rect = overlay->dropOverlayRect();
int frameWidth = (q->frameSize().width() - q->rect().width()) / 2;
int titleBarHeight = q->frameSize().height() - q->rect().height() - frameWidth;
@@ -246,25 +550,25 @@ namespace ADS
this,
&FloatingDockContainer::onDockAreasAddedOrRemoved);
-#ifdef Q_OS_LINUX
+ #ifdef Q_OS_LINUX
d->m_titleBar = new FloatingWidgetTitleBar(this);
setWindowFlags(windowFlags() | Qt::Tool);
QDockWidget::setWidget(d->m_dockContainer);
QDockWidget::setFloating(true);
- QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
+ QDockWidget::setFeatures(DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable);
setTitleBarWidget(d->m_titleBar);
connect(d->m_titleBar,
&FloatingWidgetTitleBar::closeRequested,
this,
&FloatingDockContainer::close);
-#else
+ #else
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
QBoxLayout *boxLayout = new QBoxLayout(QBoxLayout::TopToBottom);
boxLayout->setContentsMargins(0, 0, 0, 0);
boxLayout->setSpacing(0);
setLayout(boxLayout);
boxLayout->addWidget(d->m_dockContainer);
-#endif
+ #endif
dockManager->registerFloatingWidget(this);
}
@@ -272,24 +576,26 @@ namespace ADS
: FloatingDockContainer(dockArea->dockManager())
{
d->m_dockContainer->addDockArea(dockArea);
- if (Utils::HostOsInfo::isLinuxHost())
- d->m_titleBar->enableCloseButton(isClosable());
-
- auto dw = topLevelDockWidget();
- if (dw)
+ #ifdef Q_OS_LINUX
+ d->m_titleBar->enableCloseButton(isClosable());
+ #endif
+ if (auto dw = topLevelDockWidget())
dw->emitTopLevelChanged(true);
+
+ d->m_dockManager->notifyWidgetOrAreaRelocation(dockArea);
}
FloatingDockContainer::FloatingDockContainer(DockWidget *dockWidget)
: FloatingDockContainer(dockWidget->dockManager())
{
d->m_dockContainer->addDockWidget(CenterDockWidgetArea, dockWidget);
- if (Utils::HostOsInfo::isLinuxHost())
- d->m_titleBar->enableCloseButton(isClosable());
-
- auto dw = topLevelDockWidget();
- if (dw)
+ #ifdef Q_OS_LINUX
+ d->m_titleBar->enableCloseButton(isClosable());
+ #endif
+ if (auto dw = topLevelDockWidget())
dw->emitTopLevelChanged(true);
+
+ d->m_dockManager->notifyWidgetOrAreaRelocation(dockWidget);
}
FloatingDockContainer::~FloatingDockContainer()
@@ -313,33 +619,56 @@ namespace ADS
}
}
- void FloatingDockContainer::moveEvent(QMoveEvent *event)
+#ifdef Q_OS_WIN
+bool FloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, long *result)
+{
+ QWidget::nativeEvent(eventType, message, result);
+ MSG *msg = static_cast<MSG *>(message);
+ switch (msg->message)
{
- QWidget::moveEvent(event);
- switch (d->m_draggingState) {
- case DraggingMousePressed:
- // TODO Is checking for windows only sufficient or has macOS also problems?
- if (Utils::HostOsInfo::isWindowsHost())
- QApplication::instance()->installEventFilter(this);
-
- d->setState(DraggingFloatingWidget);
- d->updateDropOverlays(QCursor::pos());
- break;
-
- case DraggingFloatingWidget:
- d->updateDropOverlays(QCursor::pos());
- if (Utils::HostOsInfo::isMacHost()) {
- // In macOS when hiding the DockAreaOverlay the application would set
- // the main window as the active window for some reason. This fixes
- // that by resetting the active window to the floating widget after
- // updating the overlays.
- QApplication::setActiveWindow(this);
- }
- break;
- default:
- break;
+ case WM_MOVING:
+ {
+ if (d->isState(DraggingFloatingWidget))
+ d->updateDropOverlays(QCursor::pos());
}
+ break;
+
+ case WM_NCLBUTTONDOWN:
+ if (msg->wParam == HTCAPTION && d->isState(DraggingInactive))
+ {
+ qCInfo(adsLog) << Q_FUNC_INFO << "WM_NCLBUTTONDOWN" << eventType;
+ d->m_dragStartPos = pos();
+ d->setState(DraggingMousePressed);
+ }
+ break;
+
+ case WM_NCLBUTTONDBLCLK:
+ d->setState(DraggingInactive);
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ if (d->isState(DraggingMousePressed))
+ {
+ qCInfo(adsLog) << Q_FUNC_INFO << "WM_ENTERSIZEMOVE" << eventType;
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ }
+ break;
+
+ case WM_EXITSIZEMOVE:
+ if (d->isState(DraggingFloatingWidget))
+ {
+ qCInfo(adsLog) << Q_FUNC_INFO << "WM_EXITSIZEMOVE" << eventType;
+ if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
+ d->handleEscapeKey();
+ else
+ d->titleMouseReleaseEvent();
+ }
+ break;
}
+ return false;
+}
+#endif
void FloatingDockContainer::closeEvent(QCloseEvent *event)
{
@@ -368,112 +697,21 @@ namespace ADS
if (d->m_dockManager->isRestoringState())
return;
+ d->m_hiding = true;
for (auto dockArea : d->m_dockContainer->openedDockAreas()) {
for (auto dockWidget : dockArea->openedDockWidgets())
dockWidget->toggleView(false);
}
+ d->m_hiding = false;
}
- void FloatingDockContainer::showEvent(QShowEvent *event) { Super::showEvent(event); }
-
- bool FloatingDockContainer::event(QEvent *event)
+ void FloatingDockContainer::showEvent(QShowEvent *event)
{
- switch (d->m_draggingState) {
- case DraggingInactive: {
- // Normally we would check here, if the left mouse button is pressed.
- // But from QT version 5.12.2 on the mouse events from
- // QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
- // The event always returns Qt::RightButton even if the left button is clicked.
- // It is really great to work around the whole NonClientMouseArea bugs
-
-
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
- if (event->type() == QEvent::NonClientAreaMouseButtonPress
- /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
-#else
- if (event->type() == QEvent::NonClientAreaMouseButtonPress
- && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
-#endif
- {
- qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonPress"
- << event->type();
- d->m_dragStartPos = pos();
- d->setState(DraggingMousePressed);
- }
- } break;
-
- case DraggingMousePressed:
- switch (event->type()) {
- case QEvent::NonClientAreaMouseButtonDblClick:
- qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonDblClick";
- d->setState(DraggingInactive);
- break;
-
- case QEvent::Resize:
- // If the first event after the mouse press is a resize event, then
- // the user resizes the window instead of dragging it around.
- // But there is one exception. If the window is maximized,
- // then dragging the window via title bar will cause the widget to
- // leave the maximized state. This in turn will trigger a resize event.
- // To know, if the resize event was triggered by user via moving a
- // corner of the window frame or if it was caused by a windows state
- // change, we check, if we are not in maximized state.
- if (!isMaximized()) {
- d->setState(DraggingInactive);
- }
- break;
-
- default:
- break;
- }
- break;
-
- case DraggingFloatingWidget:
- if (event->type() == QEvent::NonClientAreaMouseButtonRelease) {
- qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonRelease";
- d->titleMouseReleaseEvent();
- }
- break;
-
- default:
- break;
- }
-
-#if (ADS_DEBUG_LEVEL > 0)
- qDebug() << "FloatingDockContainer::event " << event->type();
-#endif
- return QWidget::event(event);
- }
-
- bool FloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
- {
- Q_UNUSED(watched);
- // I have not found a way to detect non client area key press events to
- // handle escape key presses. On Windows, if the escape key is pressed while
- // dragging around a widget, the widget position is reset to its start position
- // which in turn generates a QEvent::NonClientAreaMouseButtonRelease event
- // if the mouse is outside of the widget after the move to its initial position
- // or a QEvent::MouseButtonRelease event, if the mouse is inside of the widget
- // after the position has been reset.
- // So we can install an event filter on the application to get these events
- // here to properly cancel dragging and hide the overlays.
- // If we are in DraggingFloatingWidget state, it means the widget
- // has been dragged already but if the position is the same like
- // the start position, then this is an indication that the escape
- // key has been pressed.
- if (event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::NonClientAreaMouseButtonRelease)
- {
- qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::MouseButtonRelease or QEvent::NonClientAreaMouseButtonRelease"
- << "d->m_draggingState " << d->m_draggingState;
- QApplication::instance()->removeEventFilter(this);
- if (d->m_dragStartPos == pos())
- {
- d->handleEscapeKey();
- return true;
- }
- return false;
- }
- return false;
+ Super::showEvent(event);
+ #ifdef Q_OS_LINUX
+ if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
+ window()->activateWindow();
+ #endif
}
void FloatingDockContainer::startFloating(const QPoint &dragStartMousePos,
@@ -481,29 +719,52 @@ namespace ADS
eDragState dragState,
QWidget *mouseEventHandler)
{
+ #ifndef Q_OS_LINUX
+ Q_UNUSED(mouseEventHandler)
+ #endif
resize(size);
d->setState(dragState);
d->m_dragStartMousePosition = dragStartMousePos;
- if (Utils::HostOsInfo::isLinuxHost()) {
- if (DraggingFloatingWidget == dragState) {
- setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
- d->m_mouseEventHandler = mouseEventHandler;
- if (d->m_mouseEventHandler) {
- d->m_mouseEventHandler->grabMouse();
- }
- }
+ #ifdef Q_OS_LINUX
+ if (DraggingFloatingWidget == dragState) {
+ setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
+ d->m_mouseEventHandler = mouseEventHandler;
+ if (d->m_mouseEventHandler)
+ d->m_mouseEventHandler->grabMouse();
}
+ #endif
moveFloating();
show();
}
void FloatingDockContainer::moveFloating()
{
- int borderSize = (frameSize().width() - size().width()) / 2;
+ const int borderSize = (frameSize().width() - size().width()) / 2;
const QPoint moveToPos = QCursor::pos() - d->m_dragStartMousePosition
- QPoint(borderSize, 0);
move(moveToPos);
+
+ switch (d->m_draggingState)
+ {
+ case DraggingMousePressed:
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ break;
+
+ case DraggingFloatingWidget:
+ d->updateDropOverlays(QCursor::pos());
+ // On macOS when hiding the DockAreaOverlay the application would set
+ // the main window as the active window for some reason. This fixes
+ // that by resetting the active window to the floating widget after
+ // updating the overlays.
+ if (Utils::HostOsInfo::isMacHost())
+ QApplication::setActiveWindow(this);
+
+ break;
+ default:
+ break;
+ }
}
bool FloatingDockContainer::isClosable() const
@@ -538,10 +799,14 @@ namespace ADS
void FloatingDockContainer::updateWindowTitle()
{
- auto topLevelDockArea = d->m_dockContainer->topLevelDockArea();
- if (topLevelDockArea) {
- DockWidget *currentWidget = topLevelDockArea->currentDockWidget();
- d->reflectCurrentWidget(currentWidget);
+ // If this floating container will be hidden, then updating the window
+ // title is not required anymore
+ if (d->m_hiding)
+ return;
+
+ if (auto topLevelDockArea = d->m_dockContainer->topLevelDockArea()) {
+ if (DockWidget *currentWidget = topLevelDockArea->currentDockWidget())
+ d->reflectCurrentWidget(currentWidget);
} else {
d->setWindowTitle(QApplication::applicationDisplayName());
setWindowIcon(QApplication::windowIcon());
@@ -557,9 +822,8 @@ namespace ADS
bool FloatingDockContainer::restoreState(DockingStateReader &stream, bool testing)
{
- if (!d->m_dockContainer->restoreState(stream, testing)) {
+ if (!d->m_dockContainer->restoreState(stream, testing))
return false;
- }
onDockAreasAddedOrRemoved();
return true;
@@ -584,16 +848,113 @@ namespace ADS
{
qCInfo(adsLog) << Q_FUNC_INFO;
- if (Utils::HostOsInfo::isLinuxHost()) {
- setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
- setWindowOpacity(1);
- activateWindow();
- if (d->m_mouseEventHandler) {
- d->m_mouseEventHandler->releaseMouse();
- d->m_mouseEventHandler = nullptr;
- }
+ #ifdef Q_OS_LINUX
+ setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
+ setWindowOpacity(1);
+ activateWindow();
+ if (d->m_mouseEventHandler) {
+ d->m_mouseEventHandler->releaseMouse();
+ d->m_mouseEventHandler = nullptr;
}
+ #endif
d->titleMouseReleaseEvent();
}
+#ifdef Q_OS_MACOS
+bool FloatingDockContainer::event(QEvent *event)
+{
+ switch (d->m_draggingState)
+ {
+ case DraggingInactive:
+ {
+ // Normally we would check here, if the left mouse button is pressed.
+ // But from QT version 5.12.2 on the mouse events from
+ // QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
+ // The event always returns Qt::RightButton even if the left button
+ // is clicked.
+ // It is really great to work around the whole NonClientMouseArea
+ // bugs
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
+ if (event->type() == QEvent::NonClientAreaMouseButtonPress
+ /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
+#else
+ if (event->type() == QEvent::NonClientAreaMouseButtonPress
+ && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
+#endif
+ {
+ qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonPress"
+ << event->type();
+ d->m_dragStartPos = pos();
+ d->setState(DraggingMousePressed);
+ }
+ }
+ break;
+
+ case DraggingMousePressed:
+ switch (event->type())
+ {
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonDblClick";
+ d->setState(DraggingInactive);
+ break;
+
+ case QEvent::Resize:
+ // If the first event after the mouse press is a resize event, then
+ // the user resizes the window instead of dragging it around.
+ // But there is one exception. If the window is maximized,
+ // then dragging the window via title bar will cause the widget to
+ // leave the maximized state. This in turn will trigger a resize event.
+ // To know, if the resize event was triggered by user via moving a
+ // corner of the window frame or if it was caused by a windows state
+ // change, we check, if we are not in maximized state.
+ if (!isMaximized())
+ d->setState(DraggingInactive);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case DraggingFloatingWidget:
+ if (event->type() == QEvent::NonClientAreaMouseButtonRelease)
+ {
+ qCInfo(adsLog) << Q_FUNC_INFO << "QEvent::NonClientAreaMouseButtonRelease";
+ d->titleMouseReleaseEvent();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#if (ADS_DEBUG_LEVEL > 0)
+ qDebug() << Q_FUNC_INFO << event->type();
+#endif
+ return QWidget::event(event);
+}
+
+void FloatingDockContainer::moveEvent(QMoveEvent *event)
+{
+ QWidget::moveEvent(event);
+ switch (d->m_draggingState)
+ {
+ case DraggingMousePressed:
+ d->setState(DraggingFloatingWidget);
+ d->updateDropOverlays(QCursor::pos());
+ break;
+
+ case DraggingFloatingWidget:
+ d->updateDropOverlays(QCursor::pos());
+ // On macOS when hiding the DockAreaOverlay the application would set
+ // the main window as the active window for some reason. This fixes
+ // that by resetting the active window to the floating widget after
+ // updating the overlays.
+ QApplication::setActiveWindow(this);
+ break;
+ default:
+ break;
+ }
+}
+#endif
} // namespace ADS