Initial QPlatformWindow window state setting API and xcb implementation.

This commit is contained in:
Samuel Rødal 2011-05-13 11:51:41 +02:00
parent 6697f2a899
commit 850b602c7a
8 changed files with 144 additions and 29 deletions

View File

@ -116,6 +116,17 @@ Qt::WindowFlags QPlatformWindow::setWindowFlags(Qt::WindowFlags flags)
return flags;
}
/*!
Requests setting the window state of this surface
to \a type. Returns the actual state set.
Qt::WindowActive can be ignored.
*/
Qt::WindowState QPlatformWindow::setWindowState(Qt::WindowState)
{
return Qt::WindowNoState;
}
/*!
Reimplement in subclasses to return a handle to the native window
*/

View File

@ -71,6 +71,8 @@ public:
virtual void setVisible(bool visible);
virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
virtual Qt::WindowState setWindowState(Qt::WindowState state);
virtual WId winId() const;
virtual void setParent(const QPlatformWindow *window);

View File

@ -89,6 +89,8 @@ void QWindow::create()
d->windowFlags = d->platformWindow->setWindowFlags(d->windowFlags);
if (!d->windowTitle.isNull())
d->platformWindow->setWindowTitle(d->windowTitle);
if (d->windowState != Qt::WindowNoState)
d->windowState = d->platformWindow->setWindowState(d->windowState);
QObjectList childObjects = children();
for (int i = 0; i < childObjects.size(); i ++) {
@ -232,16 +234,24 @@ void QWindow::requestActivateWindow()
}
}
Qt::WindowStates QWindow::windowState() const
Qt::WindowState QWindow::windowState() const
{
qDebug() << "unimplemented:" << __FILE__ << __LINE__;
return Qt::WindowNoState;
Q_D(const QWindow);
return d->windowState;
}
void QWindow::setWindowState(Qt::WindowStates state)
void QWindow::setWindowState(Qt::WindowState state)
{
Q_UNUSED(state);
qDebug() << "unimplemented:" << __FILE__ << __LINE__;
if (state == Qt::WindowActive) {
requestActivateWindow();
return;
}
Q_D(QWindow);
if (d->platformWindow)
d->windowState = d->platformWindow->setWindowState(state);
else
d->windowState = state;
}
QSize QWindow::minimumSize() const

View File

@ -111,8 +111,8 @@ public:
void setOpacity(qreal level);
void requestActivateWindow();
Qt::WindowStates windowState() const;
void setWindowState(Qt::WindowStates state);
Qt::WindowState windowState() const;
void setWindowState(Qt::WindowState state);
QSize minimumSize() const;
QSize maximumSize() const;

View File

@ -64,6 +64,7 @@ public:
, visible(false)
, glContext(0)
, surface(0)
, windowState(Qt::WindowNoState)
{
isWindow = true;
}
@ -82,6 +83,7 @@ public:
QRect geometry;
QWindowContext *glContext;
QWindowSurface *surface;
Qt::WindowState windowState;
};

View File

@ -90,6 +90,7 @@ static inline bool isTransient(const QWidget *w)
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_context(0)
, m_windowState(Qt::WindowNoState)
{
m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0));
@ -424,6 +425,84 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
return flags;
}
void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
{
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.window = m_window;
event.type = atom(QXcbAtom::_NET_WM_STATE);
event.data.data32[0] = set ? 1 : 0;
event.data.data32[1] = one;
event.data.data32[2] = two;
event.data.data32[3] = 0;
event.data.data32[4] = 0;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
{
if (state == m_windowState)
return state;
// unset old state
switch (m_windowState) {
case Qt::WindowMinimized:
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
break;
case Qt::WindowMaximized:
changeNetWmState(false,
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
break;
case Qt::WindowFullScreen:
changeNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
break;
default:
break;
}
// set new state
switch (state) {
case Qt::WindowMinimized:
{
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.window = m_window;
event.type = atom(QXcbAtom::WM_CHANGE_STATE);
event.data.data32[0] = XCB_WM_STATE_ICONIC;
event.data.data32[1] = 0;
event.data.data32[2] = 0;
event.data.data32[3] = 0;
event.data.data32[4] = 0;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
break;
case Qt::WindowMaximized:
changeNetWmState(true,
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
break;
case Qt::WindowFullScreen:
changeNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
break;
case Qt::WindowNoState:
break;
default:
break;
}
connection()->sync();
m_windowState = state;
return m_windowState;
}
void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
{
// in order of decreasing priority

View File

@ -62,6 +62,7 @@ public:
void setVisible(bool visible);
Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
Qt::WindowState setWindowState(Qt::WindowState state);
WId winId() const;
void setParent(const QPlatformWindow *window);
@ -93,6 +94,7 @@ public:
private:
void setNetWmWindowTypes(Qt::WindowFlags flags);
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
QXcbScreen *m_screen;
@ -103,6 +105,7 @@ private:
xcb_sync_counter_t m_syncCounter;
bool m_hasReceivedSyncRequest;
Qt::WindowState m_windowState;
};
#endif

View File

@ -443,7 +443,7 @@ void QWidgetPrivate::setFullScreenSize_helper()
data.in_set_window_state = old_state;
}
static Qt::WindowStates effectiveState(Qt::WindowStates state)
static Qt::WindowState effectiveState(Qt::WindowStates state)
{
if (state & Qt::WindowMinimized)
return Qt::WindowMinimized;
@ -466,8 +466,8 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
data->window_state = newstate;
data->in_set_window_state = 1;
bool needShow = false;
Qt::WindowStates newEffectiveState = effectiveState(newstate);
Qt::WindowStates oldEffectiveState = effectiveState(oldstate);
Qt::WindowState newEffectiveState = effectiveState(newstate);
Qt::WindowState oldEffectiveState = effectiveState(oldstate);
if (isWindow() && newEffectiveState != oldEffectiveState) {
d->createTLExtra();
if (oldEffectiveState == Qt::WindowNoState) { //normal
@ -479,24 +479,32 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
needShow = true;
}
if (newEffectiveState == Qt::WindowMinimized) {
//### not ideal...
hide();
needShow = false;
} else if (newEffectiveState == Qt::WindowFullScreen) {
d->topData()->savedFlags = windowFlags();
setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
d->setFullScreenSize_helper();
raise();
needShow = true;
} else if (newEffectiveState == Qt::WindowMaximized) {
createWinId();
d->setMaxWindowState_helper();
} else { //normal
QRect r = d->topData()->normalGeometry;
if (r.width() >= 0) {
d->topData()->normalGeometry = QRect(0,0,-1,-1);
setGeometry(r);
Q_ASSERT(windowHandle());
windowHandle()->setWindowState(newEffectiveState);
bool supported = windowHandle()->windowState() == newEffectiveState;
if (!supported) {
// emulate the window state
if (newEffectiveState == Qt::WindowMinimized) {
//### not ideal...
hide();
needShow = false;
} else if (newEffectiveState == Qt::WindowFullScreen) {
d->topData()->savedFlags = windowFlags();
setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
d->setFullScreenSize_helper();
raise();
needShow = true;
} else if (newEffectiveState == Qt::WindowMaximized) {
createWinId();
d->setMaxWindowState_helper();
} else if (newEffectiveState == Qt::WindowNoState) {
// reset old geometry
QRect r = d->topData()->normalGeometry;
if (r.width() >= 0) {
d->topData()->normalGeometry = QRect(0,0,-1,-1);
setGeometry(r);
}
}
}
}