Implement alertion state for windows.

Add QWindow::alert() and QPlatformWindow::setAlertState().
Add logic to clear alertion state when the window becomes
active. The platform plugins then only need to implement a setter
and a cheap getter and need not handle activation.

Prototypically implement X11 and Windows.

Task-number: QTBUG-30416
Change-Id: Ia70c4722d812462a21f4034b7d52735c9f2bc49c
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
bb10
Friedemann Kleint 2013-04-10 13:55:50 +02:00 committed by The Qt Project
parent 926086b9e3
commit da01deb0ac
11 changed files with 114 additions and 3 deletions

View File

@ -1592,6 +1592,11 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
if (previous == newFocus)
return;
if (newFocus)
if (QPlatformWindow *platformWindow = newFocus->handle())
if (platformWindow->isAlertState())
platformWindow->setAlertState(false);
QObject *previousFocusObject = previous ? previous->focusObject() : 0;
if (previous) {

View File

@ -462,6 +462,32 @@ QString QPlatformWindow::formatWindowTitle(const QString &title, const QString &
return fullTitle;
}
/*!
Reimplement this method to set whether the window demands attention
(for example, by flashing the taskbar icon) depending on \a enabled.
\sa isAlertState()
\since 5.1
*/
void QPlatformWindow::setAlertState(bool enable)
{
Q_UNUSED(enable)
}
/*!
Reimplement this method return whether the window is in
an alert state.
\sa setAlertState()
\since 5.1
*/
bool QPlatformWindow::isAlertState() const
{
return false;
}
/*!
Helper function to get initial geometry on windowing systems which do not
do smart positioning and also do not provide a means of centering a

View File

@ -128,6 +128,9 @@ public:
virtual void setFrameStrutEventsEnabled(bool enabled);
virtual bool frameStrutEventsEnabled() const;
virtual void setAlertState(bool enabled);
virtual bool isAlertState() const;
static QRect initialGeometry(const QWindow *w,
const QRect &initialGeometry, int defaultWidth, int defaultHeight);

View File

@ -58,6 +58,7 @@
#include <private/qevent_p.h>
#include <QtCore/QTimer>
#include <QtCore/QDebug>
#include <QStyleHints>
@ -2150,6 +2151,33 @@ QWindow *QWindow::fromWinId(WId id)
return window;
}
/*!
Causes an alert to be shown for \a msec miliseconds. If \a msec is \c 0 (the
default), then the alert is shown indefinitely until the window becomes
active again.
In alert state, the window indicates that it demands attention, for example by
flashing or bouncing the taskbar entry.
\since 5.1
*/
void QWindow::alert(int msec)
{
Q_D(QWindow);
if (!d->platformWindow || d->platformWindow->isAlertState())
return;
d->platformWindow->setAlertState(true);
if (d->platformWindow->isAlertState() && msec)
QTimer::singleShot(msec, this, SLOT(_q_clearAlert()));
}
void QWindowPrivate::_q_clearAlert()
{
if (platformWindow && platformWindow->isAlertState())
platformWindow->setAlertState(false);
}
#ifndef QT_NO_CURSOR
/*!
\brief set the cursor shape for this window
@ -2233,3 +2261,5 @@ void QWindowPrivate::applyCursor()
#endif // QT_NO_CURSOR
QT_END_NAMESPACE
#include "moc_qwindow.cpp"

View File

@ -290,6 +290,8 @@ public Q_SLOTS:
Q_REVISION(1) void setMaximumWidth(int w);
Q_REVISION(1) void setMaximumHeight(int h);
void alert(int msec);
Q_SIGNALS:
void screenChanged(QScreen *screen);
void modalityChanged(Qt::WindowModality modality);
@ -346,6 +348,7 @@ protected:
QWindow(QWindowPrivate &dd, QWindow *parent);
private:
Q_PRIVATE_SLOT(d_func(), void _q_clearAlert())
QPlatformSurface *surfaceHandle() const;
Q_DISABLE_COPY(QWindow)

View File

@ -125,6 +125,7 @@ public:
virtual QWindow *eventReceiver() { Q_Q(QWindow); return q; }
void updateVisibility();
void _q_clearAlert();
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;

View File

@ -1802,6 +1802,19 @@ QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwex
}
#ifndef Q_OS_WINCE
void QWindowsWindow::setAlertState(bool enabled)
{
if (isAlertState() == enabled)
return;
if (enabled) {
alertWindow(0);
setFlag(AlertState);
} else {
stopAlertWindow();
clearFlag(AlertState);
}
}
void QWindowsWindow::alertWindow(int durationMs)
{
DWORD timeOutMs = GetCaretBlinkTime();

View File

@ -132,7 +132,8 @@ public:
SynchronousGeometryChangeEvent = 0x400,
WithinSetStyle = 0x800,
WithinDestroy = 0x1000,
TouchRegistered = 0x2000
TouchRegistered = 0x2000,
AlertState = 0x4000
};
struct WindowData
@ -255,6 +256,8 @@ public:
void setWindowIcon(const QIcon &icon);
#ifndef Q_OS_WINCE
void setAlertState(bool enabled);
bool isAlertState() const { return testFlag(AlertState); }
void alertWindow(int durationMs = 0);
void stopAlertWindow();
#endif

View File

@ -189,6 +189,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
, m_usingSyncProtocol(false)
, m_deferredActivation(false)
, m_embedded(false)
, m_alertState(false)
, m_netWmUserTimeWindow(XCB_NONE)
, m_dirtyFrameMargins(false)
#if defined(XCB_USE_EGL)
@ -2047,4 +2048,17 @@ void QXcbWindow::setMask(const QRegion &region)
#endif // !QT_NO_SHAPE
void QXcbWindow::setAlertState(bool enabled)
{
if (m_alertState == enabled)
return;
const NetWmStates oldState = netWmStates();
m_alertState = enabled;
if (enabled) {
setNetWmStates(oldState | NetWmStateDemandsAttention);
} else {
setNetWmStates(oldState & ~NetWmStateDemandsAttention);
}
}
QT_END_NAMESPACE

View File

@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE
class QXcbScreen;
class QXcbEGLSurface;
class QIcon;
class QXcbWindow : public QXcbObject, public QPlatformWindow
{
public:
@ -120,6 +119,9 @@ public:
void setMask(const QRegion &region);
#endif // !QT_NO_SHAPE
void setAlertState(bool enabled);
bool isAlertState() const { return m_alertState; }
xcb_window_t xcb_window() const { return m_window; }
uint depth() const { return m_depth; }
QImage::Format imageFormat() const { return m_imageFormat; }
@ -194,6 +196,7 @@ private:
bool m_deferredExpose;
bool m_configureNotifyPending;
bool m_embedded;
bool m_alertState;
xcb_window_t m_netWmUserTimeWindow;
QSurfaceFormat m_format;

View File

@ -55,6 +55,7 @@
#include <qdesktopwidget.h>
#include <qpa/qplatformcursor.h>
#include <qpa/qplatformtheme.h>
#include <qpa/qplatformwindow.h>
#include <qdebug.h>
#include <qpa/qwindowsysteminterface.h>
@ -410,8 +411,17 @@ void QApplication::beep()
{
}
void QApplication::alert(QWidget *, int)
void QApplication::alert(QWidget *widget, int duration)
{
if (widget) {
if (widget->window()->isActiveWindow()&& !widget->window()->windowState() & Qt::WindowMinimized)
return;
if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
window->alert(duration);
} else {
foreach (QWidget *topLevel, topLevelWidgets())
QApplication::alert(topLevel, duration);
}
}
void qt_init(QApplicationPrivate *priv, int type)