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; 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 Reimplement in subclasses to return a handle to the native window
*/ */

View File

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

View File

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

View File

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

View File

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

View File

@ -90,6 +90,7 @@ static inline bool isTransient(const QWidget *w)
QXcbWindow::QXcbWindow(QWindow *window) QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window) : QPlatformWindow(window)
, m_context(0) , m_context(0)
, m_windowState(Qt::WindowNoState)
{ {
m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0)); m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0));
@ -424,6 +425,84 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
return 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) void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
{ {
// in order of decreasing priority // in order of decreasing priority

View File

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

View File

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