Skip to content

Commit 28dc374

Browse files
Added support for proper handling on non client escape key presses on Windows
1 parent 1b6e449 commit 28dc374

File tree

3 files changed

+70
-9
lines changed

3 files changed

+70
-9
lines changed

demo/MainWindow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
505505

506506
// uncomment the following line if you want to use opaque undocking and
507507
// opaque splitter resizing
508-
//CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
508+
// CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
509509

510510
// uncomment the following line if you want a fixed tab width that does
511511
// not change if the visibility of the close button changes

src/FloatingDockContainer.cpp

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <QDebug>
3939
#include <QAbstractButton>
4040
#include <QElapsedTimer>
41+
#include <QTime>
4142

4243
#include "DockContainerWidget.h"
4344
#include "DockAreaWidget.h"
@@ -66,6 +67,7 @@ struct FloatingDockContainerPrivate
6667
QPoint DragStartMousePosition;
6768
CDockContainerWidget *DropContainer = nullptr;
6869
CDockAreaWidget *SingleDockArea = nullptr;
70+
QPoint DragStartPos;
6971
#ifdef Q_OS_LINUX
7072
QWidget* MouseEventHandler = nullptr;
7173
CFloatingWidgetTitleBar* TitleBar = nullptr;
@@ -109,6 +111,10 @@ struct FloatingDockContainerPrivate
109111
#endif
110112
}
111113

114+
/**
115+
* Reflect the current dock widget title in the floating widget windowTitle()
116+
* depending on the CDockManager::FloatingContainerHasWidgetTitle flag
117+
*/
112118
void reflectCurrentWidget(CDockWidget* CurrentWidget)
113119
{
114120
// reflect CurrentWidget's title if configured to do so, otherwise display application name as window title
@@ -133,6 +139,11 @@ struct FloatingDockContainerPrivate
133139
_this->setWindowIcon(QApplication::windowIcon());
134140
}
135141
}
142+
143+
/**
144+
* Handles escape key press when dragging around the floating widget
145+
*/
146+
void handleEscapeKey();
136147
};
137148
// struct FloatingDockContainerPrivate
138149

@@ -264,6 +275,17 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
264275
}
265276
}
266277

278+
279+
//============================================================================
280+
void FloatingDockContainerPrivate::handleEscapeKey()
281+
{
282+
ADS_PRINT("FloatingDockContainerPrivate::handleEscapeKey()");
283+
setState(DraggingInactive);
284+
DockManager->containerOverlay()->hideOverlay();
285+
DockManager->dockAreaOverlay()->hideOverlay();
286+
}
287+
288+
267289
//============================================================================
268290
CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
269291
tFloatingWidgetBase(DockManager),
@@ -363,6 +385,7 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
363385
switch (d->DraggingState)
364386
{
365387
case DraggingMousePressed:
388+
qApp->installEventFilter(this);
366389
d->setState(DraggingFloatingWidget);
367390
d->updateDropOverlays(QCursor::pos());
368391
break;
@@ -380,6 +403,8 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
380403
default:
381404
break;
382405
}
406+
407+
383408
}
384409

385410
//============================================================================
@@ -443,6 +468,7 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
443468
Super::showEvent(event);
444469
}
445470

471+
446472
//============================================================================
447473
bool CFloatingDockContainer::event(QEvent *e)
448474
{
@@ -460,19 +486,16 @@ bool CFloatingDockContainer::event(QEvent *e)
460486
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
461487
if (e->type()
462488
== QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
463-
{
464-
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
465-
d->setState(DraggingMousePressed);
466-
}
467489
#else
468490
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
491+
#endif
469492
{
470-
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
493+
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
494+
d->DragStartPos = pos();
471495
d->setState(DraggingMousePressed);
472496
}
473-
#endif
474497
}
475-
break;
498+
break;
476499

477500
case DraggingMousePressed:
478501
switch (e->type())
@@ -515,12 +538,49 @@ bool CFloatingDockContainer::event(QEvent *e)
515538
}
516539

517540
#if (ADS_DEBUG_LEVEL > 0)
518-
qDebug() << "CFloatingDockContainer::event " << e->type();
541+
qDebug() << QTime::currentTime() << "CFloatingDockContainer::event " << e->type();
519542
#endif
520543
return QWidget::event(e);
521544
}
522545

523546

547+
//============================================================================
548+
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *e)
549+
{
550+
Q_UNUSED(watched);
551+
// I have not found a way to detect non client area key press events to
552+
// handle escape key presses. On Windows, if the escape key is pressed while
553+
// dragging around a widget, the widget position is reset to its start position
554+
// which in turn generates a QEvent::NonClientAreaMouseButtonRelease event
555+
// if the mouse is outside of the widget after the move to its initial position
556+
// or a QEvent::MouseButtonRelease event, if the mouse is inside of teh widget
557+
// after the position has been reset.
558+
// So we can install an event filter on the application to get these events
559+
// here to properly cancel dragging and hide the overlays.
560+
// If we are in DraggingFloatingWidget state, it means the widget
561+
// has been dragged already but if the position is the same like
562+
// the start position, then this is an indication that the escape
563+
// key has been pressed.
564+
if (e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::NonClientAreaMouseButtonRelease)
565+
{
566+
ADS_PRINT("CFloatingDockContainer::eventFilter QEvent::MouseButtonRelease or"
567+
"QEvent::NonClientAreaMouseButtonRelease" << "d->DragggingState " << d->DraggingState);
568+
qApp->removeEventFilter(this);
569+
if (d->DragStartPos == pos())
570+
{
571+
d->handleEscapeKey();
572+
return true;
573+
}
574+
return false;
575+
}
576+
577+
#if (ADS_DEBUG_LEVEL > 0)
578+
qDebug() << QTime::currentTime() << "CFloatingDockContainer::eventFilter " << e->type();
579+
#endif
580+
return false;
581+
}
582+
583+
524584
//============================================================================
525585
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
526586
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)

src/FloatingDockContainer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ private slots:
180180
virtual void closeEvent(QCloseEvent *event) override;
181181
virtual void hideEvent(QHideEvent *event) override;
182182
virtual void showEvent(QShowEvent *event) override;
183+
virtual bool eventFilter(QObject *watched, QEvent *event) override;
183184

184185
public:
185186
using Super = QWidget;

0 commit comments

Comments
 (0)