summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qwidget_x11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qwidget_x11.cpp')
-rw-r--r--src/gui/kernel/qwidget_x11.cpp3149
1 files changed, 0 insertions, 3149 deletions
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
deleted file mode 100644
index eaa9405c36..0000000000
--- a/src/gui/kernel/qwidget_x11.cpp
+++ /dev/null
@@ -1,3149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qevent.h"
-#include "qwidget.h"
-#include "qdesktopwidget.h"
-#include "qapplication.h"
-#include "qapplication_p.h"
-#include "qnamespace.h"
-#include "qpainter.h"
-#include "qbitmap.h"
-#include "qlayout.h"
-#include "qtextcodec.h"
-#include "qelapsedtimer.h"
-#include "qcursor.h"
-#include "qstack.h"
-#include "qcolormap.h"
-#include "qdebug.h"
-#include "qmenu.h"
-#include "private/qmenu_p.h"
-#include "private/qbackingstore_p.h"
-#include "private/qwindowsurface_x11_p.h"
-
-//extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp
-
-#include <private/qpixmap_x11_p.h>
-#include <private/qpaintengine_x11_p.h>
-#include "qt_x11_p.h"
-#include "qx11info_x11.h"
-
-#include <stdlib.h>
-
-//#define ALIEN_DEBUG
-
-// defined in qapplication_x11.cpp
-//bool qt_wstate_iconified(WId);
-//void qt_updated_rootinfo();
-
-
-#if !defined(QT_NO_IM)
-#include "qinputcontext.h"
-#include "qinputcontextfactory.h"
-#endif
-
-#include "qwidget_p.h"
-
-#define XCOORD_MAX 16383
-#define WRECT_MAX 8191
-
-QT_BEGIN_NAMESPACE
-
-extern bool qt_nograb();
-
-QWidget *QWidgetPrivate::mouseGrabber = 0;
-QWidget *QWidgetPrivate::keyboardGrabber = 0;
-
-void qt_net_remove_user_time(QWidget *tlw);
-void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
-
-int qt_x11_create_desktop_on_screen = -1;
-
-extern void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
-
-// MWM support
-struct QtMWMHints {
- ulong flags, functions, decorations;
- long input_mode;
- ulong status;
-};
-
-enum {
- MWM_HINTS_FUNCTIONS = (1L << 0),
-
- MWM_FUNC_ALL = (1L << 0),
- MWM_FUNC_RESIZE = (1L << 1),
- MWM_FUNC_MOVE = (1L << 2),
- MWM_FUNC_MINIMIZE = (1L << 3),
- MWM_FUNC_MAXIMIZE = (1L << 4),
- MWM_FUNC_CLOSE = (1L << 5),
-
- MWM_HINTS_DECORATIONS = (1L << 1),
-
- MWM_DECOR_ALL = (1L << 0),
- MWM_DECOR_BORDER = (1L << 1),
- MWM_DECOR_RESIZEH = (1L << 2),
- MWM_DECOR_TITLE = (1L << 3),
- MWM_DECOR_MENU = (1L << 4),
- MWM_DECOR_MINIMIZE = (1L << 5),
- MWM_DECOR_MAXIMIZE = (1L << 6),
-
- MWM_HINTS_INPUT_MODE = (1L << 2),
-
- MWM_INPUT_MODELESS = 0L,
- MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
- MWM_INPUT_FULL_APPLICATION_MODAL = 3L
-};
-
-
-static QtMWMHints GetMWMHints(Display *display, Window window)
-{
- QtMWMHints mwmhints;
-
- Atom type;
- int format;
- ulong nitems, bytesLeft;
- uchar *data = 0;
- if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
- ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
- &data) == Success)
- && (type == ATOM(_MOTIF_WM_HINTS)
- && format == 32
- && nitems >= 5)) {
- mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
- } else {
- mwmhints.flags = 0L;
- mwmhints.functions = MWM_FUNC_ALL;
- mwmhints.decorations = MWM_DECOR_ALL;
- mwmhints.input_mode = 0L;
- mwmhints.status = 0L;
- }
-
- if (data)
- XFree(data);
-
- return mwmhints;
-}
-
-static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints)
-{
- if (mwmhints.flags != 0l) {
- XChangeProperty(display, window, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
- PropModeReplace, (unsigned char *) &mwmhints, 5);
- } else {
- XDeleteProperty(display, window, ATOM(_MOTIF_WM_HINTS));
- }
-}
-
-// Returns true if we should set WM_TRANSIENT_FOR on \a w
-static inline bool isTransient(const QWidget *w)
-{
- return ((w->windowType() == Qt::Dialog
- || w->windowType() == Qt::Sheet
- || w->windowType() == Qt::Tool
- || w->windowType() == Qt::SplashScreen
- || w->windowType() == Qt::ToolTip
- || w->windowType() == Qt::Drawer
- || w->windowType() == Qt::Popup)
- && !w->testAttribute(Qt::WA_X11BypassTransientForHint));
-}
-
-static void do_size_hints(QWidget* widget, QWExtra *x);
-
-/*****************************************************************************
- QWidget member functions
- *****************************************************************************/
-
-const uint stdWidgetEventMask = // X event mask
- (uint)(
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- KeymapStateMask |
- ButtonMotionMask | PointerMotionMask |
- EnterWindowMask | LeaveWindowMask |
- FocusChangeMask |
- ExposureMask |
- PropertyChangeMask |
- StructureNotifyMask
- );
-
-const uint stdDesktopEventMask = // X event mask
- (uint)(
- KeymapStateMask |
- EnterWindowMask | LeaveWindowMask |
- PropertyChangeMask
- );
-
-
-/*
- The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
-*/
-
-Window qt_XCreateWindow(const QWidget *creator,
- Display *display, Window parent,
- int x, int y, uint w, uint h,
- int borderwidth, int depth,
- uint windowclass, Visual *visual,
- ulong valuemask, XSetWindowAttributes *attributes);
-Window qt_XCreateSimpleWindow(const QWidget *creator,
- Display *display, Window parent,
- int x, int y, uint w, uint h, int borderwidth,
- ulong border, ulong background);
-void qt_XDestroyWindow(const QWidget *destroyer,
- Display *display, Window window);
-
-
-static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
-{
- if (!scrolled_widget->isWindow() && !scrolled_widget->internalWinId())
- return;
- QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
- X11->sip_list.append(sip);
-
- XClientMessageEvent client_message;
- client_message.type = ClientMessage;
- client_message.window = scrolled_widget->internalWinId();
- client_message.format = 32;
- client_message.message_type = ATOM(_QT_SCROLL_DONE);
- client_message.data.l[0] = sip.id;
-
- XSendEvent(X11->display, scrolled_widget->internalWinId(), False, NoEventMask,
- (XEvent*)&client_message);
-}
-
-static int qt_sip_count(QWidget* scrolled_widget)
-{
- int sips=0;
-
- for (int i = 0; i < X11->sip_list.size(); ++i) {
- const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
- if (sip.scrolled_widget == scrolled_widget)
- sips++;
- }
-
- return sips;
-}
-
-static void create_wm_client_leader()
-{
- if (X11->wm_client_leader) return;
-
- X11->wm_client_leader =
- XCreateSimpleWindow(X11->display,
- QX11Info::appRootWindow(),
- 0, 0, 1, 1, 0, 0, 0);
-
- // set client leader property to itself
- XChangeProperty(X11->display,
- X11->wm_client_leader, ATOM(WM_CLIENT_LEADER),
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *)&X11->wm_client_leader, 1);
-
-#ifndef QT_NO_SESSIONMANAGER
- // If we are session managed, inform the window manager about it
- QByteArray session = qApp->sessionId().toLatin1();
- if (!session.isEmpty()) {
- XChangeProperty(X11->display,
- X11->wm_client_leader, ATOM(SM_CLIENT_ID),
- XA_STRING, 8, PropModeReplace,
- (unsigned char *)session.data(), session.size());
- }
-#endif
-}
-
-/*!
- \internal
- Update the X11 cursor of the widget w.
- \a force is true if this function is called from dispatchEnterLeave, it means that the
- mouse is actually directly under this widget.
- */
-void qt_x11_enforce_cursor(QWidget * w, bool force)
-{
- if (!w->testAttribute(Qt::WA_WState_Created))
- return;
-
- static QPointer<QWidget> lastUnderMouse = 0;
- if (force) {
- lastUnderMouse = w;
- } else if (lastUnderMouse && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
- w = lastUnderMouse;
- } else if (!w->internalWinId()) {
- return; //the mouse is not under this widget, and it's not native, so don't change it
- }
-
- while (!w->internalWinId() && w->parentWidget() && !w->isWindow() && !w->testAttribute(Qt::WA_SetCursor))
- w = w->parentWidget();
-
- QWidget *nativeParent = w;
- if (!w->internalWinId())
- nativeParent = w->nativeParentWidget();
- // This does the same as effectiveWinId(), but since it is possible
- // to not have a native parent widget due to a special hack in
- // qwidget for reparenting widgets to a different X11 screen,
- // added additional check to make sure native parent widget exists.
- if (!nativeParent || !nativeParent->internalWinId())
- return;
- WId winid = nativeParent->internalWinId();
-
- if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
-#ifndef QT_NO_CURSOR
- QCursor *oc = QApplication::overrideCursor();
- if (oc) {
- XDefineCursor(X11->display, winid, oc->handle());
- } else if (w->isEnabled()) {
- XDefineCursor(X11->display, winid, w->cursor().handle());
- } else {
- // enforce the windows behavior of clearing the cursor on
- // disabled widgets
- XDefineCursor(X11->display, winid, XNone);
- }
-#endif
- } else {
- XDefineCursor(X11->display, winid, XNone);
- }
-}
-
-Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
-{
- qt_x11_enforce_cursor(w, false);
-}
-
-void qt_x11_wait_for_window_manager(QWidget *w, bool sendPostedEvents)
-{
- if (!w || (!w->isWindow() && !w->internalWinId()))
- return;
- QApplication::flush();
- XEvent ev;
- QElapsedTimer t;
- t.start();
- static const int maximumWaitTime = 2000;
- if (!w->testAttribute(Qt::WA_WState_Created))
- return;
-
- WId winid = w->internalWinId();
-
- // first deliver events that are already in the local queue
- if (sendPostedEvents)
- QApplication::sendPostedEvents();
-
- // the normal sequence is:
- // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
- // with X11BypassWindowManagerHint:
- // ConfigureNotify ... MapNotify ... Expose
-
- enum State {
- Initial, Mapped
- } state = Initial;
-
- do {
- if (XEventsQueued(X11->display, QueuedAlready)) {
- XNextEvent(X11->display, &ev);
- qApp->x11ProcessEvent(&ev);
-
- switch (state) {
- case Initial:
- if (ev.type == MapNotify && ev.xany.window == winid)
- state = Mapped;
- break;
- case Mapped:
- if (ev.type == Expose && ev.xany.window == winid)
- return;
- break;
- }
- } else {
- if (!XEventsQueued(X11->display, QueuedAfterFlush))
- qApp->syncX(); // non-busy wait
- }
- if (t.elapsed() > maximumWaitTime)
- return;
- } while(1);
-}
-
-Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget *w)
-{
- qt_x11_wait_for_window_manager(w, true);
-}
-
-void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
-{
- if (!w->isVisible()) // not managed by the window manager
- return;
-
- XEvent e;
- e.xclient.type = ClientMessage;
- e.xclient.message_type = ATOM(_NET_WM_STATE);
- e.xclient.display = X11->display;
- e.xclient.window = w->internalWinId();
- e.xclient.format = 32;
- e.xclient.data.l[0] = set ? 1 : 0;
- e.xclient.data.l[1] = one;
- e.xclient.data.l[2] = two;
- e.xclient.data.l[3] = 0;
- e.xclient.data.l[4] = 0;
- XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()),
- false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
-}
-
-struct QX11WindowAttributes {
- const XWindowAttributes *att;
-};
-
-void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a)
-{
- QX11WindowAttributes att;
- att.att = &a;
- qt_x11_getX11InfoForWindow(xinfo,att);
-}
-
-
-static QVector<Atom> getNetWmState(QWidget *w)
-{
- QVector<Atom> returnValue;
-
- // Don't read anything, just get the size of the property data
- Atom actualType;
- int actualFormat;
- ulong propertyLength;
- ulong bytesLeft;
- uchar *propertyData = 0;
- if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, 0,
- False, XA_ATOM, &actualType, &actualFormat,
- &propertyLength, &bytesLeft, &propertyData) == Success
- && actualType == XA_ATOM && actualFormat == 32) {
- returnValue.resize(bytesLeft / 4);
- XFree((char*) propertyData);
- propertyData = 0;
-
- // fetch all data
- if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0,
- returnValue.size(), False, XA_ATOM, &actualType, &actualFormat,
- &propertyLength, &bytesLeft, &propertyData) != Success) {
- returnValue.clear();
- } else if (propertyLength != (ulong)returnValue.size()) {
- returnValue.resize(propertyLength);
- }
-
- // put it into netWmState
- if (!returnValue.isEmpty()) {
- memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
- }
- if (propertyData)
- XFree((char*) propertyData);
- }
-
- return returnValue;
-}
-
-void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
-{
- Q_Q(QWidget);
- Qt::WindowType type = q->windowType();
- Qt::WindowFlags &flags = data.window_flags;
- QWidget *parentWidget = q->parentWidget();
-
- if (type == Qt::ToolTip)
- flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
- if (type == Qt::Popup)
- flags |= Qt::X11BypassWindowManagerHint;
-
- bool topLevel = (flags & Qt::Window);
- bool popup = (type == Qt::Popup);
- bool desktop = (type == Qt::Desktop);
- bool tool = (type == Qt::Tool || type == Qt::SplashScreen
- || type == Qt::ToolTip || type == Qt::Drawer);
-
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::create_sys START:" << q << "topLevel?" << topLevel << "WId:"
- << window << "initializeWindow:" << initializeWindow << "destroyOldWindow" << destroyOldWindow;
-#endif
- if (topLevel) {
- if (parentWidget) { // if our parent stays on top, so must we
- QWidget *ptl = parentWidget->window();
- if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
- flags |= Qt::WindowStaysOnTopHint;
- }
-
- if (type == Qt::SplashScreen) {
- if (X11->isSupportedByWM(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
- flags &= ~Qt::X11BypassWindowManagerHint;
- } else {
- flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
- }
- }
- // All these buttons depend on the system menu, so we enable it
- if (flags & (Qt::WindowMinimizeButtonHint
- | Qt::WindowMaximizeButtonHint
- | Qt::WindowContextHelpButtonHint))
- flags |= Qt::WindowSystemMenuHint;
- }
-
-
- Window parentw, destroyw = 0;
- WId id = 0;
-
- // always initialize
- if (!window)
- initializeWindow = true;
-
- QX11Info *parentXinfo = parentWidget ? &parentWidget->d_func()->xinfo : 0;
-
- if (desktop &&
- qt_x11_create_desktop_on_screen >= 0 &&
- qt_x11_create_desktop_on_screen != xinfo.screen()) {
- // desktop on a certain screen other than the default requested
- QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen];
- xinfo.setX11Data(xd);
- } else if (parentXinfo && (parentXinfo->screen() != xinfo.screen()
- || (parentXinfo->visual() != xinfo.visual()
- && !q->inherits("QGLWidget"))))
- {
- // QGLWidgets have to be excluded here as they have a
- // specially crafted QX11Info structure which can't be swapped
- // out with the parent widgets QX11Info. The parent visual,
- // for instance, might not even be GL capable.
- xinfo = *parentXinfo;
- }
-
- //get display, screen number, root window and desktop geometry for
- //the current screen
- Display *dpy = X11->display;
- int scr = xinfo.screen();
- Window root_win = RootWindow(dpy, scr);
- int sw = DisplayWidth(dpy,scr);
- int sh = DisplayHeight(dpy,scr);
-
- if (desktop) { // desktop widget
- popup = false; // force these flags off
- data.crect.setRect(0, 0, sw, sh);
- } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
- QDesktopWidget *desktopWidget = qApp->desktop();
- if (desktopWidget->isVirtualDesktop()) {
- QRect r = desktopWidget->screenGeometry();
- sw = r.width();
- sh = r.height();
- }
-
- int width = sw / 2;
- int height = 4 * sh / 10;
- if (extra) {
- width = qMax(qMin(width, extra->maxw), extra->minw);
- height = qMax(qMin(height, extra->maxh), extra->minh);
- }
- data.crect.setSize(QSize(width, height));
- }
-
- parentw = topLevel ? root_win : parentWidget->effectiveWinId();
-
- XSetWindowAttributes wsa;
-
- if (window) { // override the old window
- if (destroyOldWindow) {
- if (topLevel)
- X11->dndEnable(q, false);
- destroyw = data.winid;
- }
- id = window;
- setWinId(window);
- XWindowAttributes a;
- XGetWindowAttributes(dpy, window, &a);
- data.crect.setRect(a.x, a.y, a.width, a.height);
-
- if (a.map_state == IsUnmapped)
- q->setAttribute(Qt::WA_WState_Visible, false);
- else
- q->setAttribute(Qt::WA_WState_Visible);
-
- qt_x11_getX11InfoForWindow(&xinfo,a);
-
- } else if (desktop) { // desktop widget
-#ifdef QWIDGET_EXTRA_DEBUG
- qDebug() << "create desktop";
-#endif
- id = (WId)parentw; // id = root window
-// QWidget *otherDesktop = find(id); // is there another desktop?
-// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
-// otherDesktop->d->setWinId(0); // remove id from widget mapper
-// d->setWinId(id); // make sure otherDesktop is
-// otherDesktop->d->setWinId(id); // found first
-// } else {
- setWinId(id);
-// }
- } else if (topLevel || q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) {
-#ifdef QWIDGET_EXTRA_DEBUG
- static int topLevels = 0;
- static int children = 0;
- if (parentw == root_win)
- qDebug() << "create toplevel" << ++topLevels;
- else
- qDebug() << "create child" << ++children;
-#endif
- QRect safeRect = data.crect; //##### must handle huge sizes as well.... i.e. wrect
- if (safeRect.width() < 1|| safeRect.height() < 1) {
- if (topLevel) {
- // top-levels must be at least 1x1
- safeRect.setSize(safeRect.size().expandedTo(QSize(1, 1)));
- } else {
- // create it way off screen, and rely on
- // setWSGeometry() to do the right thing with it later
- safeRect = QRect(-1000,-1000,1,1);
- }
- }
-#ifndef QT_NO_XRENDER
- int screen = xinfo.screen();
- if (topLevel && X11->use_xrender
- && xinfo.depth() != 32 && X11->argbVisuals[screen]
- && q->testAttribute(Qt::WA_TranslucentBackground))
- {
- QX11InfoData *xd = xinfo.getX11Data(true);
-
- xd->screen = screen;
- xd->visual = X11->argbVisuals[screen];
- xd->colormap = X11->argbColormaps[screen];
- xd->depth = 32;
- xd->defaultVisual = false;
- xd->defaultColormap = false;
- xd->cells = xd->visual->map_entries;
- xinfo.setX11Data(xd);
- }
-#endif
- if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
- id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
- safeRect.left(), safeRect.top(),
- safeRect.width(), safeRect.height(),
- 0,
- BlackPixel(dpy, xinfo.screen()),
- WhitePixel(dpy, xinfo.screen()));
- } else {
- wsa.background_pixel = WhitePixel(dpy, xinfo.screen());
- wsa.border_pixel = BlackPixel(dpy, xinfo.screen());
- wsa.colormap = xinfo.colormap();
- id = (WId)qt_XCreateWindow(q, dpy, parentw,
- safeRect.left(), safeRect.top(),
- safeRect.width(), safeRect.height(),
- 0, xinfo.depth(), InputOutput,
- (Visual *) xinfo.visual(),
- CWBackPixel|CWBorderPixel|CWColormap,
- &wsa);
- }
-
- setWinId(id); // set widget id/handle + hd
- }
-
-#ifndef QT_NO_XRENDER
- if (picture) {
- XRenderFreePicture(X11->display, picture);
- picture = 0;
- }
-
- if (X11->use_xrender && !desktop && q->internalWinId()) {
- XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual());
- if (format)
- picture = XRenderCreatePicture(dpy, id, format, 0, 0);
- }
-#endif // QT_NO_XRENDER
-
- QtMWMHints mwmhints;
- mwmhints.flags = 0L;
- mwmhints.functions = 0L;
- mwmhints.decorations = 0;
- mwmhints.input_mode = 0L;
- mwmhints.status = 0L;
-
- if (topLevel) {
- ulong wsa_mask = 0;
- if (type != Qt::SplashScreen) { // && customize) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
-
- bool customize = flags & Qt::CustomizeWindowHint;
- if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
- mwmhints.decorations |= MWM_DECOR_BORDER;
- mwmhints.decorations |= MWM_DECOR_RESIZEH;
-
- if (flags & Qt::WindowTitleHint)
- mwmhints.decorations |= MWM_DECOR_TITLE;
-
- if (flags & Qt::WindowSystemMenuHint)
- mwmhints.decorations |= MWM_DECOR_MENU;
-
- if (flags & Qt::WindowMinimizeButtonHint) {
- mwmhints.decorations |= MWM_DECOR_MINIMIZE;
- mwmhints.functions |= MWM_FUNC_MINIMIZE;
- }
-
- if (flags & Qt::WindowMaximizeButtonHint) {
- mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
- mwmhints.functions |= MWM_FUNC_MAXIMIZE;
- }
-
- if (flags & Qt::WindowCloseButtonHint)
- mwmhints.functions |= MWM_FUNC_CLOSE;
- }
- } else {
- // if type == Qt::SplashScreen
- mwmhints.decorations = MWM_DECOR_ALL;
- }
-
- if (tool) {
- wsa.save_under = True;
- wsa_mask |= CWSaveUnder;
- }
-
- if (flags & Qt::X11BypassWindowManagerHint) {
- wsa.override_redirect = True;
- wsa_mask |= CWOverrideRedirect;
- }
-
- if (wsa_mask && initializeWindow) {
- Q_ASSERT(id);
- XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
- }
-
- if (mwmhints.functions != 0) {
- mwmhints.flags |= MWM_HINTS_FUNCTIONS;
- mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
- } else {
- mwmhints.functions = MWM_FUNC_ALL;
- }
-
- if (!(flags & Qt::FramelessWindowHint)
- && flags & Qt::CustomizeWindowHint
- && flags & Qt::WindowTitleHint
- && !(flags &
- (Qt::WindowMinimizeButtonHint
- | Qt::WindowMaximizeButtonHint
- | Qt::WindowCloseButtonHint))) {
- // a special case - only the titlebar without any button
- mwmhints.flags = MWM_HINTS_FUNCTIONS;
- mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
- mwmhints.decorations = 0;
- }
- }
-
- if (!initializeWindow) {
- // do no initialization
- } else if (popup) { // popup widget
- // set EWMH window types
- setNetWmWindowTypes();
-
- wsa.override_redirect = True;
- wsa.save_under = True;
- Q_ASSERT(id);
- XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
- &wsa);
- } else if (topLevel && !desktop) { // top-level widget
- if (!X11->wm_client_leader)
- create_wm_client_leader();
-
- // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys()
-
- XSizeHints size_hints;
- size_hints.flags = USSize | PSize | PWinGravity;
- size_hints.x = data.crect.left();
- size_hints.y = data.crect.top();
- size_hints.width = data.crect.width();
- size_hints.height = data.crect.height();
- size_hints.win_gravity =
- QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
-
- XWMHints wm_hints; // window manager hints
- memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
- wm_hints.flags = InputHint | StateHint | WindowGroupHint;
- wm_hints.input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
- wm_hints.initial_state = NormalState;
- wm_hints.window_group = X11->wm_client_leader;
-
- XClassHint class_hint;
- QByteArray appName = qAppName().toLatin1();
- class_hint.res_name = appName.data(); // application name
- class_hint.res_class = const_cast<char *>(QX11Info::appClass()); // application class
-
- XSetWMProperties(dpy, id, 0, 0,
- qApp->d_func()->argv, qApp->d_func()->argc,
- &size_hints, &wm_hints, &class_hint);
-
- XResizeWindow(dpy, id,
- qBound(1, data.crect.width(), XCOORD_MAX),
- qBound(1, data.crect.height(), XCOORD_MAX));
- XStoreName(dpy, id, appName.data());
- Atom protocols[5];
- int n = 0;
- protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
- protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
- protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
-#ifndef QT_NO_XSYNC
- protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
-#endif // QT_NO_XSYNC
- if (flags & Qt::WindowContextHelpButtonHint)
- protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
- XSetWMProtocols(dpy, id, protocols, n);
-
- // set mwm hints
- SetMWMHints(dpy, id, mwmhints);
-
- // set EWMH window types
- setNetWmWindowTypes();
-
- // set _NET_WM_PID
- long curr_pid = getpid();
- XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *) &curr_pid, 1);
-
- // when we create a toplevel widget, the frame strut should be dirty
- data.fstrut_dirty = 1;
-
- // declare the widget's window role
- if (QTLWExtra *topData = maybeTopData()) {
- if (!topData->role.isEmpty()) {
- QByteArray windowRole = topData->role.toUtf8();
- XChangeProperty(dpy, id,
- ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
- (unsigned char *)windowRole.constData(), windowRole.length());
- }
- }
-
- // set client leader property
- XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *)&X11->wm_client_leader, 1);
- } else {
- // non-toplevel widgets don't have a frame, so no need to
- // update the strut
- data.fstrut_dirty = 0;
- }
-
- if (initializeWindow && q->internalWinId()) {
- // don't erase when resizing
- wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
- Q_ASSERT(id);
- XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
- }
-
- // set X11 event mask
- if (desktop) {
-// QWidget* main_desktop = find(id);
-// if (main_desktop->testWFlags(Qt::WPaintDesktop))
-// XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
-// else
- XSelectInput(dpy, id, stdDesktopEventMask);
- } else if (q->internalWinId()) {
- XSelectInput(dpy, id, stdWidgetEventMask);
-#if !defined (QT_NO_TABLET)
- QTabletDeviceDataList *tablet_list = qt_tablet_devices();
- if (X11->ptrXSelectExtensionEvent) {
- for (int i = 0; i < tablet_list->size(); ++i) {
- QTabletDeviceData tablet = tablet_list->at(i);
- X11->ptrXSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList),
- tablet.eventCount);
- }
- }
-#endif
- }
-
- if (desktop) {
- q->setAttribute(Qt::WA_WState_Visible);
- } else if (topLevel) { // set X cursor
- if (initializeWindow) {
- qt_x11_enforce_cursor(q);
-
- if (QTLWExtra *topData = maybeTopData())
- if (!topData->caption.isEmpty())
- setWindowTitle_helper(topData->caption);
-
- //always enable dnd: it's not worth the effort to maintain the state
- // NOTE: this always creates topData()
- X11->dndEnable(q, true);
-
- if (maybeTopData() && maybeTopData()->opacity != 255)
- q->setWindowOpacity(maybeTopData()->opacity/255.);
-
- }
- } else if (q->internalWinId()) {
- qt_x11_enforce_cursor(q);
- if (QWidget *p = q->parentWidget()) // reset the cursor on the native parent
- qt_x11_enforce_cursor(p);
- }
-
- if (extra && !extra->mask.isEmpty() && q->internalWinId())
- XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
- extra->mask.handle(), ShapeSet);
-
- if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
- QInputContext *inputContext = q->inputContext();
- if (inputContext)
- inputContext->setFocusWidget(q);
- }
-
- if (destroyw) {
- qt_XDestroyWindow(q, dpy, destroyw);
- if (QTLWExtra *topData = maybeTopData()) {
-#ifndef QT_NO_XSYNC
- if (topData->syncUpdateCounter)
- XSyncDestroyCounter(dpy, topData->syncUpdateCounter);
-#endif
- // we destroyed our old window - reset the top-level state
- createTLSysExtra();
- }
- }
-
- // newly created windows are positioned at the window system's
- // (0,0) position. If the parent uses wrect mapping to expand the
- // coordinate system, we must also adjust this widget's window
- // system position
- if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
- setWSGeometry();
- else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0))
- q->setAttribute(Qt::WA_OutsideWSRange, true);
-
- if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
- Q_ASSERT(q->internalWinId());
- XMapWindow(X11->display, q->internalWinId());
- // Ensure that mapped alien widgets are flushed immediately when re-created as native widgets.
- if (QWindowSurface *surface = q->windowSurface())
- surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint()));
- }
-
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::create_sys END:" << q;
-#endif
-}
-
-static void qt_x11_recreateWidget(QWidget *widget)
-{
- if (widget->inherits("QGLWidget")) {
- // We send QGLWidgets a ParentChange event which causes them to
- // recreate their GL context, which in turn causes them to choose
- // their visual again. Now that WA_TranslucentBackground is set,
- // QGLContext::chooseVisual will select an ARGB visual.
-
- // QGLWidget expects a ParentAboutToChange to be sent first
- QEvent aboutToChangeEvent(QEvent::ParentAboutToChange);
- QApplication::sendEvent(widget, &aboutToChangeEvent);
-
- QEvent parentChangeEvent(QEvent::ParentChange);
- QApplication::sendEvent(widget, &parentChangeEvent);
- } else {
- // For regular widgets, reparent them with their parent which
- // also triggers a recreation of the native window
- QPoint pos = widget->pos();
- bool visible = widget->isVisible();
- if (visible)
- widget->hide();
-
- widget->setParent(widget->parentWidget(), widget->windowFlags());
- widget->move(pos);
- if (visible)
- widget->show();
- }
-}
-
-static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget)
-{
- if (widget->internalWinId())
- qt_x11_recreateWidget(widget);
-
- const QObjectList &children = widget->children();
- for (int i = 0; i < children.size(); ++i) {
- QWidget *child = qobject_cast<QWidget*>(children.at(i));
- if (child)
- qt_x11_recreateNativeWidgetsRecursive(child);
- }
-}
-
-void QWidgetPrivate::x11UpdateIsOpaque()
-{
-#ifndef QT_NO_XRENDER
- Q_Q(QWidget);
- if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
- return;
-
- bool topLevel = (data.window_flags & Qt::Window);
- int screen = xinfo.screen();
- if (topLevel && X11->use_xrender
- && X11->argbVisuals[screen] && xinfo.depth() != 32)
- {
- qt_x11_recreateNativeWidgetsRecursive(q);
- }
-#endif
-}
-
-/*
- Returns true if the background is inherited; otherwise returns
- false.
-
- Mainly used in the paintOnScreen case.
-*/
-bool QWidgetPrivate::isBackgroundInherited() const
-{
- Q_Q(const QWidget);
-
- // windows do not inherit their background
- if (q->isWindow() || q->windowType() == Qt::SubWindow)
- return false;
-
- if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
- return false;
-
- const QPalette &pal = q->palette();
- QPalette::ColorRole bg = q->backgroundRole();
- QBrush brush = pal.brush(bg);
-
- // non opaque brushes leaves us no choice, we must inherit
- if (!q->autoFillBackground() || !brush.isOpaque())
- return true;
-
- if (brush.style() == Qt::SolidPattern) {
- // the background is just a solid color. If there is no
- // propagated contents, then we claim as performance
- // optimization that it was not inheritet. This is the normal
- // case in standard Windows or Motif style.
- const QWidget *w = q->parentWidget();
- if (!w->d_func()->isBackgroundInherited())
- return false;
- }
-
- return true;
-}
-
-void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
-{
- Q_D(QWidget);
- d->aboutToDestroy();
- if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
- d->deactivateWidgetCleanup();
- if (testAttribute(Qt::WA_WState_Created)) {
- setAttribute(Qt::WA_WState_Created, false);
- QObjectList childList = children();
- for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
- register QObject *obj = childList.at(i);
- if (obj->isWidgetType())
- static_cast<QWidget*>(obj)->destroy(destroySubWindows,
- destroySubWindows);
- }
- if (QWidgetPrivate::mouseGrabber == this)
- releaseMouse();
- if (QWidgetPrivate::keyboardGrabber == this)
- releaseKeyboard();
- if (isWindow())
- X11->deferred_map.removeAll(this);
- if (isModal()) {
- // just be sure we leave modal
- QApplicationPrivate::leaveModal(this);
- }
- else if ((windowType() == Qt::Popup))
- qApp->d_func()->closePopup(this);
-
-#ifndef QT_NO_XRENDER
- if (d->picture) {
- if (destroyWindow)
- XRenderFreePicture(X11->display, d->picture);
- d->picture = 0;
- }
-#endif // QT_NO_XRENDER
-
- // delete the _NET_WM_USER_TIME_WINDOW
- qt_net_remove_user_time(this);
-
- if ((windowType() == Qt::Desktop)) {
- if (acceptDrops())
- X11->dndEnable(this, false);
- } else {
- if (isWindow())
- X11->dndEnable(this, false);
- if (destroyWindow)
- qt_XDestroyWindow(this, X11->display, data->winid);
- }
- QT_TRY {
- d->setWinId(0);
- } QT_CATCH (const std::bad_alloc &) {
- // swallow - destructors must not throw
- }
-
- extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
- if (testAttribute(Qt::WA_WState_Reparented))
- qPRCleanup(this);
-
- if(d->ic) {
- delete d->ic;
- } else {
- // release previous focus information participating with
- // preedit preservation of qic
- QInputContext *qic = QApplicationPrivate::inputContext;
- if (qic)
- qic->widgetDestroyed(this);
- }
- }
-}
-
-void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
-{
- Q_Q(QWidget);
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent;
-#endif
- QX11Info old_xinfo = xinfo;
- if (parent && parent->windowType() == Qt::Desktop) {
- // make sure the widget is created on the same screen as the
- // programmer specified desktop widget
- xinfo = parent->d_func()->xinfo;
- parent = 0;
- }
-
- QTLWExtra *topData = maybeTopData();
- bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
- if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
- q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
- extern void qPRCreate(const QWidget *, Window);
-#ifndef QT_NO_CURSOR
- QCursor oldcurs;
-#endif
-
- // dnd unregister (we will register again below)
- if (q->testAttribute(Qt::WA_DropSiteRegistered))
- q->setAttribute(Qt::WA_DropSiteRegistered, false);
-
- // if we are a top then remove our dnd prop for now
- // it will get rest later
- if (q->isWindow() && wasCreated)
- X11->dndEnable(q, false);
-
- if (topData)
- qt_net_remove_user_time(q);
-
-// QWidget *oldparent = q->parentWidget();
- WId old_winid = wasCreated ? data.winid : 0;
- if ((q->windowType() == Qt::Desktop))
- old_winid = 0;
- setWinId(0);
-
-#ifndef QT_NO_XRENDER
- if (picture) {
- XRenderFreePicture(X11->display, picture);
- picture = 0;
- }
-#endif
-
- // hide and reparent our own window away. Otherwise we might get
- // destroyed when emitting the child remove event below. See QWorkspace.
- if (wasCreated && old_winid) {
- XUnmapWindow(X11->display, old_winid);
- if (!old_xinfo.screen() != xinfo.screen())
- XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
- }
- if (topData) {
- topData->parentWinId = 0;
- // zero the frame strut and mark it dirty
- topData->frameStrut.setCoords(0, 0, 0, 0);
-
- // reparenting from top-level, make sure show() works again
- topData->waitingForMapNotify = 0;
- topData->validWMState = 0;
- }
- data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
-
- QObjectPrivate::setParent_helper(parent);
- bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
-
- data.window_flags = f;
- q->setAttribute(Qt::WA_WState_Created, false);
- q->setAttribute(Qt::WA_WState_Visible, false);
- q->setAttribute(Qt::WA_WState_Hidden, false);
- adjustFlags(data.window_flags, q);
- // keep compatibility with previous versions, we need to preserve the created state
- // (but we recreate the winId for the widget being reparented, again for compatibility)
- if (wasCreated)
- createWinId();
- if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
- q->setAttribute(Qt::WA_WState_Hidden);
- q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
-
- if (wasCreated) {
- QObjectList chlist = q->children();
- for (int i = 0; i < chlist.size(); ++i) { // reparent children
- QObject *obj = chlist.at(i);
- if (obj->isWidgetType()) {
- QWidget *w = (QWidget *)obj;
- if (!w->testAttribute(Qt::WA_WState_Created))
- continue;
- if (xinfo.screen() != w->d_func()->xinfo.screen()) {
- // ### force setParent() to not shortcut out (because
- // ### we're setting the parent to the current parent)
- // ### setParent will add child back to the list
- // ### of children so we need to make sure the
- // ### widget won't be added twice.
- w->d_func()->parent = 0;
- this->children.removeOne(w);
- w->setParent(q);
- } else if (!w->isWindow()) {
- w->d_func()->invalidateBuffer(w->rect());
- if (w->internalWinId()) {
- if (w->testAttribute(Qt::WA_NativeWindow)) {
- QWidget *nativeParentWidget = w->nativeParentWidget();
- // Qt::WA_NativeWindow ensures that we always have a nativeParentWidget
- Q_ASSERT(nativeParentWidget != 0);
- QPoint p = w->mapTo(nativeParentWidget, QPoint());
- XReparentWindow(X11->display,
- w->internalWinId(),
- nativeParentWidget->internalWinId(),
- p.x(), p.y());
- } else {
- w->d_func()->setParent_sys(q, w->data->window_flags);
- }
- }
- } else if (isTransient(w)) {
- /*
- when reparenting toplevel windows with toplevel-transient children,
- we need to make sure that the window manager gets the updated
- WM_TRANSIENT_FOR information... unfortunately, some window managers
- don't handle changing WM_TRANSIENT_FOR before the toplevel window is
- visible, so we unmap and remap all toplevel-transient children *after*
- the toplevel parent has been mapped. thankfully, this is easy in Qt :)
-
- note that the WM_TRANSIENT_FOR hint is actually updated in
- QWidgetPrivate::show_sys()
- */
- if (w->internalWinId())
- XUnmapWindow(X11->display, w->internalWinId());
- QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
- }
- }
- }
- qPRCreate(q, old_winid);
- updateSystemBackground();
-
- if (old_winid) {
- Window *cmwret;
- int count;
- if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) {
- Window *cmw;
- int cmw_size = sizeof(Window)*count;
- cmw = new Window[count];
- memcpy((char *)cmw, (char *)cmwret, cmw_size);
- XFree((char *)cmwret);
- int i;
- for (i=0; i<count; i++) {
- if (cmw[i] == old_winid) {
- cmw[i] = q->internalWinId();
- break;
- }
- }
- int top_count;
- if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(),
- &cmwret, &top_count))
- {
- Window *merged_cmw = new Window[count + top_count];
- memcpy((char *)merged_cmw, (char *)cmw, cmw_size);
- memcpy((char *)merged_cmw + cmw_size, (char *)cmwret, sizeof(Window)*top_count);
- delete [] cmw;
- XFree((char *)cmwret);
- cmw = merged_cmw;
- count += top_count;
- }
-
- XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count);
- delete [] cmw;
- }
-
- qt_XDestroyWindow(q, X11->display, old_winid);
- }
- }
-
- // check if we need to register our dropsite
- if (q->testAttribute(Qt::WA_AcceptDrops)
- || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) {
- q->setAttribute(Qt::WA_DropSiteRegistered, true);
- }
-#if !defined(QT_NO_IM)
- ic = 0;
-#endif
- invalidateBuffer(q->rect());
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::setParent_sys END" << q;
-#endif
-}
-
-QPoint QWidgetPrivate::mapToGlobal(const QPoint &pos) const
-{
- Q_Q(const QWidget);
- if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) {
- QPoint p = pos + q->data->crect.topLeft();
- //cannot trust that !isWindow() implies parentWidget() before create
- return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p);
- }
- int x, y;
- Window child;
- QPoint p = mapToWS(pos);
- XTranslateCoordinates(X11->display, q->internalWinId(),
- QApplication::desktop()->screen(xinfo.screen())->internalWinId(),
- p.x(), p.y(), &x, &y, &child);
- return QPoint(x, y);
-}
-
-QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const
-{
- Q_Q(const QWidget);
- if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) {
- //cannot trust that !isWindow() implies parentWidget() before create
- QPoint p = (q->isWindow() || !q->parentWidget()) ? pos : q->parentWidget()->d_func()->mapFromGlobal(pos);
- return p - q->data->crect.topLeft();
- }
- int x, y;
- Window child;
- XTranslateCoordinates(X11->display,
- QApplication::desktop()->screen(xinfo.screen())->internalWinId(),
- q->internalWinId(), pos.x(), pos.y(), &x, &y, &child);
- return mapFromWS(QPoint(x, y));
-}
-
-QPoint QWidget::mapToGlobal(const QPoint &pos) const
-{
- Q_D(const QWidget);
- QPoint offset = data->crect.topLeft();
- const QWidget *w = this;
- const QWidget *p = w->parentWidget();
- while (!w->isWindow() && p) {
- w = p;
- p = p->parentWidget();
- offset += w->data->crect.topLeft();
- }
-
- const QWidgetPrivate *wd = w->d_func();
- QTLWExtra *tlw = wd->topData();
- if (!tlw->embedded)
- return pos + offset;
-
- return d->mapToGlobal(pos);
-}
-
-QPoint QWidget::mapFromGlobal(const QPoint &pos) const
-{
- Q_D(const QWidget);
- QPoint offset = data->crect.topLeft();
- const QWidget *w = this;
- const QWidget *p = w->parentWidget();
- while (!w->isWindow() && p) {
- w = p;
- p = p->parentWidget();
- offset += w->data->crect.topLeft();
- }
-
- const QWidgetPrivate *wd = w->d_func();
- QTLWExtra *tlw = wd->topData();
- if (!tlw->embedded)
- return pos - offset;
-
- return d->mapFromGlobal(pos);
-}
-
-void QWidgetPrivate::updateSystemBackground()
-{
- Q_Q(QWidget);
- if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId())
- return;
- QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole());
- Qt::WindowType type = q->windowType();
- if (brush.style() == Qt::NoBrush
- || q->testAttribute(Qt::WA_NoSystemBackground)
- || q->testAttribute(Qt::WA_UpdatesDisabled)
- || type == Qt::Popup || type == Qt::ToolTip) {
- if (QX11Info::isCompositingManagerRunning()
- && q->testAttribute(Qt::WA_TranslucentBackground)
- && !(q->parent()))
- XSetWindowBackground(X11->display, q->internalWinId(),
- QColormap::instance(xinfo.screen()).pixel(Qt::transparent));
- else
- XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
- }
- else if (brush.style() == Qt::SolidPattern && brush.isOpaque())
- XSetWindowBackground(X11->display, q->internalWinId(),
- QColormap::instance(xinfo.screen()).pixel(brush.color()));
- else if (isBackgroundInherited())
- XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative);
- else if (brush.style() == Qt::TexturePattern) {
- extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
- XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
- static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth());
- } else
- XSetWindowBackground(X11->display, q->internalWinId(),
- QColormap::instance(xinfo.screen()).pixel(brush.color()));
-}
-
-#ifndef QT_NO_CURSOR
-void QWidgetPrivate::setCursor_sys(const QCursor &)
-{
- Q_Q(QWidget);
- qt_x11_enforce_cursor(q);
- XFlush(X11->display);
-}
-
-void QWidgetPrivate::unsetCursor_sys()
-{
- Q_Q(QWidget);
- qt_x11_enforce_cursor(q);
- XFlush(X11->display);
-}
-#endif
-
-static XTextProperty*
-qstring_to_xtp(const QString& s)
-{
- static XTextProperty tp = { 0, 0, 0, 0 };
- static bool free_prop = true; // we can't free tp.value in case it references
- // the data of the static QCString below.
- if (tp.value) {
- if (free_prop)
- XFree(tp.value);
- tp.value = 0;
- free_prop = true;
- }
-
- static const QTextCodec* mapper = QTextCodec::codecForLocale();
- int errCode = 0;
- if (mapper) {
- QByteArray mapped = mapper->fromUnicode(s);
- char* tl[2];
- tl[0] = mapped.data();
- tl[1] = 0;
- errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
-#if defined(QT_DEBUG)
- if (errCode < 0)
- qDebug("qstring_to_xtp result code %d", errCode);
-#endif
- }
- if (!mapper || errCode < 0) {
- static QByteArray qcs;
- qcs = s.toAscii();
- tp.value = (uchar*)qcs.data();
- tp.encoding = XA_STRING;
- tp.format = 8;
- tp.nitems = qcs.length();
- free_prop = false;
- }
-
- // ### If we knew WM could understand unicode, we could use
- // ### a much simpler, cheaper encoding...
- /*
- tp.value = (XChar2b*)s.unicode();
- tp.encoding = XA_UNICODE; // wish
- tp.format = 16;
- tp.nitems = s.length();
- */
-
- return &tp;
-}
-
-void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- if (!q->internalWinId())
- return;
- XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
-
- QByteArray net_wm_name = caption.toUtf8();
- XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
- PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
-}
-
-void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
-{
- Q_Q(QWidget);
- if (!q->testAttribute(Qt::WA_WState_Created))
- return;
- QTLWExtra *topData = this->topData();
- if (topData->iconPixmap && !forceReset)
- // already been set
- return;
-
- // preparing images to set the _NET_WM_ICON property
- QIcon icon = q->windowIcon();
- QVector<long> icon_data;
- Qt::HANDLE pixmap_handle = 0;
- if (!icon.isNull()) {
- QList<QSize> availableSizes = icon.availableSizes();
- if(availableSizes.isEmpty()) {
- // try to use default sizes since the icon can be a scalable image like svg.
- availableSizes.push_back(QSize(16,16));
- availableSizes.push_back(QSize(32,32));
- availableSizes.push_back(QSize(64,64));
- availableSizes.push_back(QSize(128,128));
- }
- for(int i = 0; i < availableSizes.size(); ++i) {
- QSize size = availableSizes.at(i);
- QPixmap pixmap = icon.pixmap(size);
- if (!pixmap.isNull()) {
- QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
- int pos = icon_data.size();
- icon_data.resize(pos + 2 + image.width()*image.height());
- icon_data[pos++] = image.width();
- icon_data[pos++] = image.height();
- if (sizeof(long) == sizeof(quint32)) {
- memcpy(icon_data.data() + pos, image.scanLine(0), image.byteCount());
- } else {
- for (int y = 0; y < image.height(); ++y) {
- uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y));
- for (int x = 0; x < image.width(); ++x)
- icon_data[pos + y*image.width() + x] = scanLine[x];
- }
- }
- }
- }
- if (!icon_data.isEmpty()) {
- extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
- /*
- if the app is running on an unknown desktop, or it is not
- using the default visual, convert the icon to 1bpp as stated
- in the ICCCM section 4.1.2.4; otherwise, create the icon pixmap
- in the default depth (even though this violates the ICCCM)
- */
- if (X11->desktopEnvironment == DE_UNKNOWN
- || !QX11Info::appDefaultVisual(xinfo.screen())
- || !QX11Info::appDefaultColormap(xinfo.screen())) {
- // unknown DE or non-default visual/colormap, use 1bpp bitmap
- if (!forceReset || !topData->iconPixmap)
- topData->iconPixmap = new QPixmap(qt_toX11Pixmap(QBitmap(icon.pixmap(QSize(64,64)))));
- pixmap_handle = topData->iconPixmap->handle();
- } else {
- // default depth, use a normal pixmap (even though this
- // violates the ICCCM), since this works on all DEs known to Qt
- if (!forceReset || !topData->iconPixmap)
- topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
- pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth();
- }
- }
- }
-
- if (!q->internalWinId())
- return;
-
- if (!icon_data.isEmpty()) {
- XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
- PropModeReplace, (unsigned char *) icon_data.data(),
- icon_data.size());
- } else {
- XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
- }
-
- XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
- XWMHints wm_hints;
- if (!h) {
- memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
- h = &wm_hints;
- }
-
- if (pixmap_handle) {
- h->icon_pixmap = pixmap_handle;
- h->flags |= IconPixmapHint;
- } else {
- h->icon_pixmap = 0;
- h->flags &= ~(IconPixmapHint | IconMaskHint);
- }
-
- XSetWMHints(X11->display, q->internalWinId(), h);
- if (h != &wm_hints)
- XFree((char *)h);
-}
-
-void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
-{
- Q_Q(QWidget);
- if (!q->internalWinId())
- return;
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
-
- QByteArray icon_name = iconText.toUtf8();
- XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
- PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
-}
-
-
-void QWidget::grabMouse()
-{
- if (isVisible() && !qt_nograb()) {
- if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
- QWidgetPrivate::mouseGrabber->releaseMouse();
- Q_ASSERT(testAttribute(Qt::WA_WState_Created));
-#ifndef QT_NO_DEBUG
- int status =
-#endif
- XGrabPointer(X11->display, effectiveWinId(), False,
- (uint)(ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | EnterWindowMask |
- LeaveWindowMask),
- GrabModeAsync, GrabModeAsync,
- XNone, XNone, X11->time);
-#ifndef QT_NO_DEBUG
- if (status) {
- const char *s =
- status == GrabNotViewable ? "\"GrabNotViewable\"" :
- status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
- status == GrabFrozen ? "\"GrabFrozen\"" :
- status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
- "<?>";
- qWarning("QWidget::grabMouse: Failed with %s", s);
- }
-#endif
- QWidgetPrivate::mouseGrabber = this;
- }
-}
-
-
-#ifndef QT_NO_CURSOR
-void QWidget::grabMouse(const QCursor &cursor)
-{
- if (!qt_nograb()) {
- if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
- QWidgetPrivate::mouseGrabber->releaseMouse();
- Q_ASSERT(testAttribute(Qt::WA_WState_Created));
-#ifndef QT_NO_DEBUG
- int status =
-#endif
- XGrabPointer(X11->display, effectiveWinId(), False,
- (uint)(ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | EnterWindowMask | LeaveWindowMask),
- GrabModeAsync, GrabModeAsync,
- XNone, cursor.handle(), X11->time);
-#ifndef QT_NO_DEBUG
- if (status) {
- const char *s =
- status == GrabNotViewable ? "\"GrabNotViewable\"" :
- status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
- status == GrabFrozen ? "\"GrabFrozen\"" :
- status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
- "<?>";
- qWarning("QWidget::grabMouse: Failed with %s", s);
- }
-#endif
- QWidgetPrivate::mouseGrabber = this;
- }
-}
-#endif
-
-
-void QWidget::releaseMouse()
-{
- if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
- XUngrabPointer(X11->display, X11->time);
- XFlush(X11->display);
- QWidgetPrivate::mouseGrabber = 0;
- }
-}
-
-
-void QWidget::grabKeyboard()
-{
- if (!qt_nograb()) {
- if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
- QWidgetPrivate::keyboardGrabber->releaseKeyboard();
- XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync,
- X11->time);
- QWidgetPrivate::keyboardGrabber = this;
- }
-}
-
-
-void QWidget::releaseKeyboard()
-{
- if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
- XUngrabKeyboard(X11->display, X11->time);
- QWidgetPrivate::keyboardGrabber = 0;
- }
-}
-
-
-QWidget *QWidget::mouseGrabber()
-{
- return QWidgetPrivate::mouseGrabber;
-}
-
-
-QWidget *QWidget::keyboardGrabber()
-{
- return QWidgetPrivate::keyboardGrabber;
-}
-
-void QWidget::activateWindow()
-{
- QWidget *tlw = window();
- if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
- if (X11->userTime == 0)
- X11->userTime = X11->time;
- qt_net_update_user_time(tlw, X11->userTime);
-
- if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW))
- && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) {
- XEvent e;
- e.xclient.type = ClientMessage;
- e.xclient.message_type = ATOM(_NET_ACTIVE_WINDOW);
- e.xclient.display = X11->display;
- e.xclient.window = tlw->internalWinId();
- e.xclient.format = 32;
- e.xclient.data.l[0] = 1; // 1 == application
- e.xclient.data.l[1] = X11->userTime;
- if (QWidget *aw = QApplication::activeWindow())
- e.xclient.data.l[2] = aw->internalWinId();
- else
- e.xclient.data.l[2] = XNone;
- e.xclient.data.l[3] = 0;
- e.xclient.data.l[4] = 0;
- XSendEvent(X11->display, RootWindow(X11->display, tlw->x11Info().screen()),
- false, SubstructureNotifyMask | SubstructureRedirectMask, &e);
- } else {
- if (!qt_widget_private(tlw)->topData()->waitingForMapNotify)
- XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
- }
- }
-}
-
-void QWidget::setWindowState(Qt::WindowStates newstate)
-{
- Q_D(QWidget);
- bool needShow = false;
- Qt::WindowStates oldstate = windowState();
- if (oldstate == newstate)
- return;
- if (isWindow()) {
- // Ensure the initial size is valid, since we store it as normalGeometry below.
- if (!testAttribute(Qt::WA_Resized) && !isVisible())
- adjustSize();
-
- QTLWExtra *top = d->topData();
-
- if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
- if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
- && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
- if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
- top->normalGeometry = geometry();
- qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
- ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
- ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
- } else if (! (newstate & Qt::WindowFullScreen)) {
- if (newstate & Qt::WindowMaximized) {
- // save original geometry
- const QRect normalGeometry = geometry();
-
- if (isVisible()) {
- data->fstrut_dirty = true;
- const QRect maxRect = QApplication::desktop()->availableGeometry(this);
- const QRect r = top->normalGeometry;
- const QRect fs = d->frameStrut();
- setGeometry(maxRect.x() + fs.left(),
- maxRect.y() + fs.top(),
- maxRect.width() - fs.left() - fs.right(),
- maxRect.height() - fs.top() - fs.bottom());
- top->normalGeometry = r;
- }
-
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- } else {
- // restore original geometry
- setGeometry(top->normalGeometry);
- }
- }
- }
-
- if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
- if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
- if (newstate & Qt::WindowFullScreen) {
- top->normalGeometry = geometry();
- top->fullScreenOffset = d->frameStrut().topLeft();
- }
- qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
- ATOM(_NET_WM_STATE_FULLSCREEN));
- } else {
- needShow = isVisible();
-
- if (newstate & Qt::WindowFullScreen) {
- data->fstrut_dirty = true;
- const QRect normalGeometry = geometry();
- const QPoint fullScreenOffset = d->frameStrut().topLeft();
-
- top->savedFlags = windowFlags();
- setParent(0, Qt::Window | Qt::FramelessWindowHint);
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->screenGeometry(this));
- top->normalGeometry = r;
-
- if (top->normalGeometry.width() < 0) {
- top->normalGeometry = normalGeometry;
- top->fullScreenOffset = fullScreenOffset;
- }
- } else {
- setParent(0, top->savedFlags);
-
- if (newstate & Qt::WindowMaximized) {
- // from fullscreen to maximized
- data->fstrut_dirty = true;
- const QRect maxRect = QApplication::desktop()->availableGeometry(this);
- const QRect r = top->normalGeometry;
- const QRect fs = d->frameStrut();
- setGeometry(maxRect.x() + fs.left(),
- maxRect.y() + fs.top(),
- maxRect.width() - fs.left() - fs.right(),
- maxRect.height() - fs.top() - fs.bottom());
- top->normalGeometry = r;
- } else {
- // restore original geometry
- setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
- -top->fullScreenOffset.y(),
- -top->fullScreenOffset.x(),
- -top->fullScreenOffset.y()));
- }
- }
- }
- }
-
- createWinId();
- Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
- if (isVisible()) {
- if (newstate & Qt::WindowMinimized) {
- XEvent e;
- e.xclient.type = ClientMessage;
- e.xclient.message_type = ATOM(WM_CHANGE_STATE);
- e.xclient.display = X11->display;
- e.xclient.window = data->winid;
- e.xclient.format = 32;
- e.xclient.data.l[0] = IconicState;
- e.xclient.data.l[1] = 0;
- e.xclient.data.l[2] = 0;
- e.xclient.data.l[3] = 0;
- e.xclient.data.l[4] = 0;
- XSendEvent(X11->display,
- RootWindow(X11->display,d->xinfo.screen()),
- False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
- } else {
- setAttribute(Qt::WA_Mapped);
- XMapWindow(X11->display, effectiveWinId());
- }
- }
-
- needShow = false;
- }
- }
-
- data->window_state = newstate;
-
- if (needShow)
- show();
-
- if (newstate & Qt::WindowActive)
- activateWindow();
-
- QWindowStateChangeEvent e(oldstate);
- QApplication::sendEvent(this, &e);
-}
-
-/*!
- \internal
- Platform-specific part of QWidget::show().
-*/
-
-void QWidgetPrivate::show_sys()
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
-
- if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- invalidateBuffer(q->rect());
- q->setAttribute(Qt::WA_Mapped);
- if (QTLWExtra *tlwExtra = maybeTopData())
- tlwExtra->waitingForMapNotify = 0;
- return;
- }
-
- if (q->isWindow()) {
- XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
- XWMHints wm_hints;
- bool got_hints = h != 0;
- if (!got_hints) {
- memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
- h = &wm_hints;
- }
- h->initial_state = q->isMinimized() ? IconicState : NormalState;
- h->flags |= StateHint;
- XSetWMHints(X11->display, q->internalWinId(), h);
- if (got_hints)
- XFree((char *)h);
-
- // update WM_NORMAL_HINTS
- do_size_hints(q, extra);
-
- // udpate WM_TRANSIENT_FOR
- if (isTransient(q)) {
- QWidget *p = q->parentWidget();
-
-#ifndef QT_NO_MENU
- // hackish ... try to find the main window related to this QMenu
- if (qobject_cast<QMenu *>(q)) {
- p = static_cast<QMenuPrivate*>(this)->causedPopup.widget;
- if (!p)
- p = q->parentWidget();
- if (!p)
- p = QApplication::widgetAt(q->pos());
- if (!p)
- p = qApp->activeWindow();
- }
-#endif
- if (p)
- p = p->window();
- if (p) {
- // transient for window
- XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
- } else {
- // transient for group
- XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
- }
- }
-
- // update _MOTIF_WM_HINTS
- QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
-
- if (data.window_modality != Qt::NonModal) {
- switch (data.window_modality) {
- case Qt::WindowModal:
- mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
- break;
- case Qt::ApplicationModal:
- default:
- mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
- break;
- }
- mwmhints.flags |= MWM_HINTS_INPUT_MODE;
- } else {
- mwmhints.input_mode = MWM_INPUT_MODELESS;
- mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
- }
-
- if (q->minimumSize() == q->maximumSize()) {
- // fixed size, remove the resize handle (since mwm/dtwm
- // isn't smart enough to do it itself)
- mwmhints.flags |= MWM_HINTS_FUNCTIONS;
- if (mwmhints.functions == MWM_FUNC_ALL) {
- mwmhints.functions = MWM_FUNC_MOVE;
- } else {
- mwmhints.functions &= ~MWM_FUNC_RESIZE;
- }
-
- if (mwmhints.decorations == MWM_DECOR_ALL) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
- mwmhints.decorations = (MWM_DECOR_BORDER
- | MWM_DECOR_TITLE
- | MWM_DECOR_MENU);
- } else {
- mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
- }
-
- if (q->windowFlags() & Qt::WindowMinimizeButtonHint) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
- mwmhints.decorations |= MWM_DECOR_MINIMIZE;
- mwmhints.functions |= MWM_FUNC_MINIMIZE;
- }
- if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
- mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
- mwmhints.functions |= MWM_FUNC_MAXIMIZE;
- }
- if (q->windowFlags() & Qt::WindowCloseButtonHint)
- mwmhints.functions |= MWM_FUNC_CLOSE;
- }
-
- SetMWMHints(X11->display, q->internalWinId(), mwmhints);
-
- // update _NET_WM_STATE
- QVector<Atom> netWmState = getNetWmState(q);
-
- Qt::WindowFlags flags = q->windowFlags();
- if (flags & Qt::WindowStaysOnTopHint) {
- if (flags & Qt::WindowStaysOnBottomHint)
- qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
- if (!netWmState.contains(ATOM(_NET_WM_STATE_ABOVE)))
- netWmState.append(ATOM(_NET_WM_STATE_ABOVE));
- if (!netWmState.contains(ATOM(_NET_WM_STATE_STAYS_ON_TOP)))
- netWmState.append(ATOM(_NET_WM_STATE_STAYS_ON_TOP));
- } else if (flags & Qt::WindowStaysOnBottomHint) {
- if (!netWmState.contains(ATOM(_NET_WM_STATE_BELOW)))
- netWmState.append(ATOM(_NET_WM_STATE_BELOW));
- }
- if (q->isFullScreen()) {
- if (!netWmState.contains(ATOM(_NET_WM_STATE_FULLSCREEN)))
- netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN));
- }
- if (q->isMaximized()) {
- if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
- netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ));
- if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))
- netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
- }
- if (data.window_modality != Qt::NonModal) {
- if (!netWmState.contains(ATOM(_NET_WM_STATE_MODAL)))
- netWmState.append(ATOM(_NET_WM_STATE_MODAL));
- }
-
- if (!netWmState.isEmpty()) {
- XChangeProperty(X11->display, q->internalWinId(),
- ATOM(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
- (unsigned char *) netWmState.data(), netWmState.size());
- } else {
- XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
- }
-
- // set _NET_WM_USER_TIME
- Time userTime = X11->userTime;
- bool setUserTime = false;
- if (q->testAttribute(Qt::WA_ShowWithoutActivating)) {
- userTime = 0;
- setUserTime = true;
- } else if (userTime != CurrentTime) {
- setUserTime = true;
- }
- if (setUserTime)
- qt_net_update_user_time(q, userTime);
-
-#ifndef QT_NO_XSYNC
- if (!topData()->syncUpdateCounter) {
- XSyncValue value;
- XSyncIntToValue(&value, 0);
- topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
-
- XChangeProperty(X11->display, q->internalWinId(),
- ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
- XA_CARDINAL,
- 32, PropModeReplace,
- (uchar *) &topData()->syncUpdateCounter, 1);
-
- topData()->newCounterValueHi = 0;
- topData()->newCounterValueLo = 0;
- }
-#endif
-
- if (!topData()->embedded
- && (topData()->validWMState || topData()->waitingForMapNotify)
- && !q->isMinimized()) {
- X11->deferred_map.append(q);
- return;
- }
-
- if (q->isMaximized() && !q->isFullScreen()
- && !(X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
- && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
- XMapWindow(X11->display, q->internalWinId());
- data.fstrut_dirty = true;
- qt_x11_wait_for_window_manager(q);
-
- // if the wm was not smart enough to adjust our size, do that manually
- QRect maxRect = QApplication::desktop()->availableGeometry(q);
-
- QTLWExtra *top = topData();
- QRect normalRect = top->normalGeometry;
- const QRect fs = frameStrut();
-
- q->setGeometry(maxRect.x() + fs.left(),
- maxRect.y() + fs.top(),
- maxRect.width() - fs.left() - fs.right(),
- maxRect.height() - fs.top() - fs.bottom());
-
- // restore the original normalGeometry
- top->normalGeometry = normalRect;
- // internalSetGeometry() clears the maximized flag... make sure we set it back
- data.window_state = data.window_state | Qt::WindowMaximized;
- q->setAttribute(Qt::WA_Mapped);
- return;
- }
-
- if (q->isFullScreen() && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
- XMapWindow(X11->display, q->internalWinId());
- qt_x11_wait_for_window_manager(q);
- q->setAttribute(Qt::WA_Mapped);
- return;
- }
- }
-
- invalidateBuffer(q->rect());
-
- if (q->testAttribute(Qt::WA_OutsideWSRange))
- return;
- q->setAttribute(Qt::WA_Mapped);
- if (q->isWindow())
- topData()->waitingForMapNotify = 1;
-
- if (!q->isWindow()
- && (!q->autoFillBackground()
- || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
- if (q->internalWinId()) {
- XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
- XMapWindow(X11->display, q->internalWinId());
- updateSystemBackground();
- }
- return;
- }
-
- if (q->internalWinId())
- XMapWindow(X11->display, q->internalWinId());
-
- // Freedesktop.org Startup Notification
- if (X11->startupId && q->isWindow()) {
- QByteArray message("remove: ID=");
- message.append(X11->startupId);
- sendStartupMessage(message.constData());
- X11->startupId = 0;
- }
-}
-
-/*!
- \internal
- Platform-specific part of QWidget::show().
-*/
-
-void QWidgetPrivate::sendStartupMessage(const char *message) const
-{
- Q_Q(const QWidget);
-
- if (!message)
- return;
-
- XEvent xevent;
- xevent.xclient.type = ClientMessage;
- xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN);
- xevent.xclient.display = X11->display;
- xevent.xclient.window = q->internalWinId();
- xevent.xclient.format = 8;
-
- Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
- uint sent = 0;
- uint length = strlen(message) + 1;
- do {
- if (sent == 20)
- xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
-
- for (uint i = 0; i < 20 && i + sent <= length; i++)
- xevent.xclient.data.b[i] = message[i + sent++];
-
- XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
- } while (sent <= length);
-}
-
-void QWidgetPrivate::setNetWmWindowTypes()
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
-
- if (!q->isWindow()) {
- if (q->internalWinId())
- XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE));
- return;
- }
-
- QVector<long> windowTypes;
-
- // manual selection 1 (these are never set by Qt and take precedence)
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DESKTOP));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DOCK));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NOTIFICATION));
-
- // manual selection 2 (Qt uses these during auto selection);
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
-
- // manual selection 3 (these can be set by Qt, but don't have a
- // corresponding Qt::WindowType). note that order of the *MENU
- // atoms is important
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_MENU));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_COMBO));
- if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DND));
-
- // automatic selection
- switch (q->windowType()) {
- case Qt::Dialog:
- case Qt::Sheet:
- // dialog netwm type
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
- break;
-
- case Qt::Tool:
- case Qt::Drawer:
- // utility netwm type
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
- break;
-
- case Qt::ToolTip:
- // tooltip netwm type
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
- break;
-
- case Qt::SplashScreen:
- // splash netwm type
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
- break;
-
- default:
- break;
- }
-
- if (q->windowFlags() & Qt::FramelessWindowHint) {
- // override netwm type - quick and easy for KDE noborder
- windowTypes.append(ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
- }
-
- // normal netwm type - default
- windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL));
-
- if (!windowTypes.isEmpty()) {
- XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32,
- PropModeReplace, (unsigned char *) windowTypes.constData(),
- windowTypes.count());
- } else {
- XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE));
- }
-}
-
-/*!
- \internal
- Platform-specific part of QWidget::hide().
-*/
-
-void QWidgetPrivate::hide_sys()
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- deactivateWidgetCleanup();
- if (q->isWindow()) {
- X11->deferred_map.removeAll(q);
- if (q->internalWinId()) // in nsplugin, may be 0
- XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen());
- XFlush(X11->display);
- } else {
- invalidateBuffer(q->rect());
- if (q->internalWinId()) // in nsplugin, may be 0
- XUnmapWindow(X11->display, q->internalWinId());
- }
- q->setAttribute(Qt::WA_Mapped, false);
-}
-
-void QWidgetPrivate::setFocus_sys()
-{
-
-}
-
-
-void QWidgetPrivate::raise_sys()
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- if (q->internalWinId())
- XRaiseWindow(X11->display, q->internalWinId());
-}
-
-void QWidgetPrivate::lower_sys()
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- if (q->internalWinId())
- XLowerWindow(X11->display, q->internalWinId());
- if(!q->isWindow())
- invalidateBuffer(q->rect());
-}
-
-void QWidgetPrivate::stackUnder_sys(QWidget* w)
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- if (q->internalWinId() && w->internalWinId()) {
- Window stack[2];
- stack[0] = w->internalWinId();;
- stack[1] = q->internalWinId();
- XRestackWindows(X11->display, stack, 2);
- }
- if(!q->isWindow() || !w->internalWinId())
- invalidateBuffer(q->rect());
-}
-
-
-static void do_size_hints(QWidget* widget, QWExtra *x)
-{
- Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
- XSizeHints s;
- s.flags = 0;
- if (x) {
- QRect g = widget->geometry();
- s.x = g.x();
- s.y = g.y();
- s.width = g.width();
- s.height = g.height();
- if (x->minw > 0 || x->minh > 0) {
- // add minimum size hints
- s.flags |= PMinSize;
- s.min_width = qMin(XCOORD_MAX, x->minw);
- s.min_height = qMin(XCOORD_MAX, x->minh);
- }
- if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
- // add maximum size hints
- s.flags |= PMaxSize;
- s.max_width = qMin(XCOORD_MAX, x->maxw);
- s.max_height = qMin(XCOORD_MAX, x->maxh);
- }
- if (x->topextra &&
- (x->topextra->incw > 0 || x->topextra->inch > 0)) {
- // add resize increment hints
- s.flags |= PResizeInc | PBaseSize;
- s.width_inc = x->topextra->incw;
- s.height_inc = x->topextra->inch;
- s.base_width = x->topextra->basew;
- s.base_height = x->topextra->baseh;
- }
- }
- if (widget->testAttribute(Qt::WA_Moved)) {
- // user (i.e. command-line) specified position
- s.flags |= USPosition;
- s.flags |= PPosition;
- }
- if (widget->testAttribute(Qt::WA_Resized)) {
- // user (i.e. command-line) specified size
- s.flags |= USSize;
- s.flags |= PSize;
- }
- s.flags |= PWinGravity;
- if (widget->testAttribute(Qt::WA_Moved) && x && x->topextra && !x->topextra->posFromMove) {
- // position came from setGeometry(), tell the WM that we don't
- // want our window gravity-shifted
- s.win_gravity = StaticGravity;
- } else {
- // position came from move()
- s.x = widget->x();
- s.y = widget->y();
- s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
- }
- if (widget->internalWinId())
- XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
-}
-
-
-/*
- Helper function for non-toplevel widgets. Helps to map Qt's 32bit
- coordinate system to X11's 16bit coordinate system.
-
- Sets the geometry of the widget to data.crect, but clipped to sizes
- that X can handle. Unmaps widgets that are completely outside the
- valid range.
-
- Maintains data.wrect, which is the geometry of the X widget,
- measured in this widget's coordinate system.
-
- if the parent is not clipped, parentWRect is empty, otherwise
- parentWRect is the geometry of the parent's X rect, measured in
- parent's coord sys
- */
-void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
-
- /*
- There are up to four different coordinate systems here:
- Qt coordinate system for this widget.
- X coordinate system for this widget (relative to wrect).
- Qt coordinate system for parent
- X coordinate system for parent (relative to parent's wrect).
- */
- Display *dpy = xinfo.display();
- QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
- QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
- QRect wrect;
- //xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys)
- QRect xrect = data.crect;
-
- const QWidget *const parent = q->parentWidget();
- QRect parentWRect = parent->data->wrect;
-
- if (parentWRect.isValid()) {
- // parent is clipped, and we have to clip to the same limit as parent
- if (!parentWRect.contains(xrect)) {
- xrect &= parentWRect;
- wrect = xrect;
- //translate from parent's to my Qt coord sys
- wrect.translate(-data.crect.topLeft());
- }
- //translate from parent's Qt coords to parent's X coords
- xrect.translate(-parentWRect.topLeft());
-
- } else {
- // parent is not clipped, we may or may not have to clip
-
- if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
- // This is where the main optimization is: we are already
- // clipped, and if our clip is still valid, we can just
- // move our window, and do not need to move or clip
- // children
-
- QRect vrect = xrect & parent->rect();
- vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
- if (data.wrect.contains(vrect)) {
- xrect = data.wrect;
- xrect.translate(data.crect.topLeft());
- if (data.winid)
- XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
- return;
- }
- }
-
- if (!validRange.contains(xrect)) {
- // we are too big, and must clip
- xrect &=wrectRange;
- wrect = xrect;
- wrect.translate(-data.crect.topLeft());
- //parent's X coord system is equal to parent's Qt coord
- //sys, so we don't need to map xrect.
- }
-
- }
-
- // unmap if we are outside the valid window system coord system
- bool outsideRange = !xrect.isValid();
- bool mapWindow = false;
- if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
- q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
- if (outsideRange) {
- if (data.winid)
- XUnmapWindow(dpy, data.winid);
- q->setAttribute(Qt::WA_Mapped, false);
- } else if (!q->isHidden()) {
- mapWindow = true;
- }
- }
-
- if (outsideRange)
- return;
-
- bool jump = (data.wrect != wrect);
- data.wrect = wrect;
-
-
- // and now recursively for all children...
- // ### can be optimized
- for (int i = 0; i < children.size(); ++i) {
- QObject *object = children.at(i);
- if (object->isWidgetType()) {
- QWidget *w = static_cast<QWidget *>(object);
- if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
- w->d_func()->setWSGeometry(jump);
- }
- }
-
- if (data.winid) {
- // move ourselves to the new position and map (if necessary) after
- // the movement. Rationale: moving unmapped windows is much faster
- // than moving mapped windows
- if (jump) //avoid flicker when jumping
- XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
- if (!parent->internalWinId())
- xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
- XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
- }
-
- //to avoid flicker, we have to show children after the helper widget has moved
- if (jump) {
- for (int i = 0; i < children.size(); ++i) {
- QObject *object = children.at(i);
- if (object->isWidgetType()) {
- QWidget *w = static_cast<QWidget *>(object);
- if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
- w->setAttribute(Qt::WA_Mapped);
- if (w->internalWinId())
- XMapWindow(dpy, w->data->winid);
- }
- }
- }
- }
-
-
- if (jump && data.winid)
- XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
-
- if (mapWindow && !dontShow) {
- q->setAttribute(Qt::WA_Mapped);
- if (data.winid)
- XMapWindow(dpy, data.winid);
- }
-}
-
-void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
-{
- Q_Q(QWidget);
- Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- Display *dpy = X11->display;
-
- if ((q->windowType() == Qt::Desktop))
- return;
- if (q->isWindow()) {
- if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
- && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
- data.window_state &= ~Qt::WindowMaximized;
- if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
- data.window_state &= ~Qt::WindowFullScreen;
- if (QTLWExtra *topData = maybeTopData())
- topData->normalGeometry = QRect(0,0,-1,-1);
- } else {
- uint s = data.window_state;
- s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
- data.window_state = s;
- }
- if (extra) { // any size restrictions?
- w = qMin(w,extra->maxw);
- h = qMin(h,extra->maxh);
- w = qMax(w,extra->minw);
- h = qMax(h,extra->minh);
- }
- QPoint oldPos(q->pos());
- QSize oldSize(q->size());
- QRect oldGeom(data.crect);
- QRect r(x, y, w, h);
-
- // We only care about stuff that changes the geometry, or may
- // cause the window manager to change its state
- if (!q->isWindow() && oldGeom == r)
- return;
-
- data.crect = r;
- bool isResize = q->size() != oldSize;
-
- if (q->isWindow()) {
- if (w == 0 || h == 0) {
- q->setAttribute(Qt::WA_OutsideWSRange, true);
- if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
- hide_sys();
- } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
- q->setAttribute(Qt::WA_OutsideWSRange, false);
-
- // put the window in its place and show it
- if (data.winid)
- XMoveResizeWindow(dpy, data.winid, x, y, w, h);
- topData()->posFromMove = false; // force StaticGravity
- do_size_hints(q, extra);
- show_sys();
- } else {
- q->setAttribute(Qt::WA_OutsideWSRange, false);
- if (!q->isVisible())
- do_size_hints(q, extra);
- if (isMove) {
- if ((data.window_flags & Qt::X11BypassWindowManagerHint) == Qt::X11BypassWindowManagerHint
- // work around 4Dwm's incompliance with ICCCM 4.1.5
- || X11->desktopEnvironment == DE_4DWM) {
- if (data.winid)
- XMoveResizeWindow(dpy, data.winid, x, y, w, h);
- } else if (q->isVisible()
- && topData()->validWMState
- && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) {
- XEvent e;
- e.xclient.type = ClientMessage;
- e.xclient.message_type = ATOM(_NET_MOVERESIZE_WINDOW);
- e.xclient.display = X11->display;
- e.xclient.window = q->internalWinId();
- e.xclient.format = 32;
- e.xclient.data.l[0] = StaticGravity | 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12;
- e.xclient.data.l[1] = x;
- e.xclient.data.l[2] = y;
- e.xclient.data.l[3] = w;
- e.xclient.data.l[4] = h;
- XSendEvent(X11->display, RootWindow(X11->display, q->x11Info().screen()),
- false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
- } else if (data.winid) {
- // pos() is right according to ICCCM 4.1.5
- XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
- }
- } else if (isResize && data.winid) {
- if (!q->isVisible()
- && topData()->validWMState
- && !q->testAttribute(Qt::WA_PendingMoveEvent)) {
- /*
- even though we've not visible, we could be in a
- race w/ the window manager, and it may ignore
- our ConfigureRequest. setting posFromMove to
- false makes sure that doDeferredMap() in
- qapplication_x11.cpp keeps the window in the
- right place
- */
- topData()->posFromMove = false;
- }
- XResizeWindow(dpy, data.winid, w, h);
- }
- }
- if (isResize && !q->testAttribute(Qt::WA_DontShowOnScreen)) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
- q->setAttribute(Qt::WA_WState_ConfigPending);
-
- } else {
- QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
- const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
- const bool disableInTopLevelResize = inTopLevelResize && q->internalWinId();
- if (disableInTopLevelResize) {
- // Top-level resize optimization does not work for native child widgets;
- // disable it for this particular widget.
- tlwExtra->inTopLevelResize = false;
- }
-
- if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) {
- moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
- }
- if (q->testAttribute(Qt::WA_WState_Created))
- setWSGeometry();
-
- if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible())
- invalidateBuffer_resizeHelper(oldPos, oldSize);
-
- if (disableInTopLevelResize)
- tlwExtra->inTopLevelResize = true;
- }
-
- if (q->isVisible()) {
- if (isMove && q->pos() != oldPos) {
- if (X11->desktopEnvironment != DE_4DWM) {
- // pos() is right according to ICCCM 4.1.5
- QMoveEvent e(q->pos(), oldPos);
- QApplication::sendEvent(q, &e);
- } else {
- // work around 4Dwm's incompliance with ICCCM 4.1.5
- QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
- QApplication::sendEvent(q, &e);
- }
- }
- if (isResize) {
- static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
- // If we have a backing store with static contents, we have to disable the top-level
- // resize optimization in order to get invalidated regions for resized widgets.
- // The optimization discards all invalidateBuffer() calls since we're going to
- // repaint everything anyways, but that's not the case with static contents.
- const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
- && !extra->topextra->inTopLevelResize
- && (!extra->topextra->backingStore
- || !extra->topextra->backingStore->hasStaticContents());
- if (setTopLevelResize)
- extra->topextra->inTopLevelResize = true;
- QResizeEvent e(q->size(), oldSize);
- QApplication::sendEvent(q, &e);
- if (setTopLevelResize)
- extra->topextra->inTopLevelResize = false;
- }
- } else {
- if (isMove && q->pos() != oldPos)
- q->setAttribute(Qt::WA_PendingMoveEvent, true);
- if (isResize)
- q->setAttribute(Qt::WA_PendingResizeEvent, true);
- }
-}
-
-void QWidgetPrivate::setConstraints_sys()
-{
- Q_Q(QWidget);
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::setConstraints_sys START" << q;
-#endif
- if (q->testAttribute(Qt::WA_WState_Created))
- do_size_hints(q, extra);
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::setConstraints_sys END" << q;
-#endif
-}
-
-void QWidgetPrivate::scroll_sys(int dx, int dy)
-{
- Q_Q(QWidget);
-
- scrollChildren(dx, dy);
- if (!paintOnScreen()) {
- scrollRect(q->rect(), dx, dy);
- } else {
- scroll_sys(dx, dy, QRect());
- }
-}
-
-void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
-{
- Q_Q(QWidget);
-
- if (!paintOnScreen()) {
- scrollRect(r, dx, dy);
- return;
- }
- bool valid_rect = r.isValid();
- bool just_update = qAbs(dx) > q->width() || qAbs(dy) > q->height();
- QRect sr = valid_rect ? r : clipRect();
- if (just_update)
- q->update();
- else if (!valid_rect)
- dirty.translate(dx, dy);
-
- int x1, y1, x2, y2, w = sr.width(), h = sr.height();
- if (dx > 0) {
- x1 = sr.x();
- x2 = x1+dx;
- w -= dx;
- } else {
- x2 = sr.x();
- x1 = x2-dx;
- w += dx;
- }
- if (dy > 0) {
- y1 = sr.y();
- y2 = y1+dy;
- h -= dy;
- } else {
- y2 = sr.y();
- y1 = y2-dy;
- h += dy;
- }
-
- if (dx == 0 && dy == 0)
- return;
-
- Display *dpy = X11->display;
- // Want expose events
- if (w > 0 && h > 0 && !just_update && q->internalWinId()) {
- GC gc = XCreateGC(dpy, q->internalWinId(), 0, 0);
- XSetGraphicsExposures(dpy, gc, True);
- XCopyArea(dpy, q->internalWinId(), q->internalWinId(), gc, x1, y1, w, h, x2, y2);
- XFreeGC(dpy, gc);
- }
-
- if (!valid_rect && !children.isEmpty()) { // scroll children
- QPoint pd(dx, dy);
- for (int i = 0; i < children.size(); ++i) { // move all children
- register QObject *object = children.at(i);
- if (object->isWidgetType()) {
- QWidget *w = static_cast<QWidget *>(object);
- if (!w->isWindow())
- w->move(w->pos() + pd);
- }
- }
- }
-
- if (just_update)
- return;
-
- // Don't let the server be bogged-down with repaint events
- bool repaint_immediately = (qt_sip_count(q) < 3 && !q->testAttribute(Qt::WA_WState_InPaintEvent));
-
- if (dx) {
- int x = x2 == sr.x() ? sr.x()+w : sr.x();
- if (repaint_immediately)
- q->repaint(x, sr.y(), qAbs(dx), sr.height());
- else if (q->internalWinId())
- XClearArea(dpy, data.winid, x, sr.y(), qAbs(dx), sr.height(), True);
- }
- if (dy) {
- int y = y2 == sr.y() ? sr.y()+h : sr.y();
- if (repaint_immediately)
- q->repaint(sr.x(), y, sr.width(), qAbs(dy));
- else if (q->internalWinId())
- XClearArea(dpy, data.winid, sr.x(), y, sr.width(), qAbs(dy), True);
- }
-
- qt_insert_sip(q, dx, dy); // #### ignores r
-}
-
-int QWidget::metric(PaintDeviceMetric m) const
-{
- Q_D(const QWidget);
- int val;
- if (m == PdmWidth) {
- val = data->crect.width();
- } else if (m == PdmHeight) {
- val = data->crect.height();
- } else {
- Display *dpy = X11->display;
- int scr = d->xinfo.screen();
- switch (m) {
- case PdmDpiX:
- case PdmPhysicalDpiX:
- if (d->extra && d->extra->customDpiX)
- val = d->extra->customDpiX;
- else if (d->parent)
- val = static_cast<QWidget *>(d->parent)->metric(m);
- else
- val = QX11Info::appDpiX(scr);
- break;
- case PdmDpiY:
- case PdmPhysicalDpiY:
- if (d->extra && d->extra->customDpiY)
- val = d->extra->customDpiY;
- else if (d->parent)
- val = static_cast<QWidget *>(d->parent)->metric(m);
- else
- val = QX11Info::appDpiY(scr);
- break;
- case PdmWidthMM:
- val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
- DisplayWidth(dpy,scr);
- break;
- case PdmHeightMM:
- val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
- DisplayHeight(dpy,scr);
- break;
- case PdmNumColors:
- val = d->xinfo.cells();
- break;
- case PdmDepth:
- val = d->xinfo.depth();
- break;
- default:
- val = 0;
- qWarning("QWidget::metric: Invalid metric command");
- }
- }
- return val;
-}
-
-void QWidgetPrivate::createSysExtra()
-{
- extra->compress_events = true;
- extra->xDndProxy = 0;
-}
-
-void QWidgetPrivate::deleteSysExtra()
-{
-}
-
-void QWidgetPrivate::createTLSysExtra()
-{
- extra->topextra->spont_unmapped = 0;
- extra->topextra->dnd = 0;
- extra->topextra->validWMState = 0;
- extra->topextra->waitingForMapNotify = 0;
- extra->topextra->parentWinId = 0;
- extra->topextra->userTimeWindow = 0;
-#ifndef QT_NO_XSYNC
- extra->topextra->syncUpdateCounter = 0;
- extra->topextra->syncRequestTimestamp = 0;
- extra->topextra->newCounterValueHi = 0;
- extra->topextra->newCounterValueLo = 0;
-#endif
-}
-
-void QWidgetPrivate::deleteTLSysExtra()
-{
- // don't destroy input context here. it will be destroyed in
- // QWidget::destroy() destroyInputContext();
-}
-
-void QWidgetPrivate::registerDropSite(bool on)
-{
- Q_UNUSED(on);
-}
-
-void QWidgetPrivate::setMask_sys(const QRegion &region)
-{
- Q_Q(QWidget);
- if (!q->internalWinId())
- return;
-
- if (region.isEmpty()) {
- XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
- XNone, ShapeSet);
- } else {
- XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
- region.handle(), ShapeSet);
- }
-}
-
-/*!
- \internal
-
- Computes the frame rectangle when needed. This is an internal function, you
- should never call this.
-*/
-
-void QWidgetPrivate::updateFrameStrut()
-{
- Q_Q(QWidget);
-
- QTLWExtra *top = topData();
- if (!top->validWMState) {
- return;
- }
- if (!q->isWindow() && !q->internalWinId()) {
- data.fstrut_dirty = false;
- return;
- }
-
- Atom type_ret;
- Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root
- Window *c;
- int i_unused;
- unsigned int nc;
- unsigned char *data_ret;
- unsigned long l_unused;
-
- while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
- if (c && nc > 0)
- XFree(c);
-
- if (! p) {
- qWarning("QWidget::updateFrameStrut: No parent");
- return;
- }
-
- // if the parent window is the root window, an Enlightenment virtual root or
- // a NET WM virtual root window, stop here
- data_ret = 0;
- if (p == r ||
- (XGetWindowProperty(X11->display, p,
- ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
- &type_ret, &i_unused, &l_unused, &l_unused,
- &data_ret) == Success &&
- type_ret == XA_CARDINAL)) {
- if (data_ret)
- XFree(data_ret);
-
- break;
- } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
- int i = 0;
- while (X11->net_virtual_root_list[i] != 0) {
- if (X11->net_virtual_root_list[i++] == p)
- break;
- }
- }
-
- l = w;
- w = p;
- }
-
- // we have our window
- int transx, transy;
- XWindowAttributes wattr;
- if (XTranslateCoordinates(X11->display, l, w,
- 0, 0, &transx, &transy, &p) &&
- XGetWindowAttributes(X11->display, w, &wattr)) {
- top->frameStrut.setCoords(transx,
- transy,
- wattr.width - data.crect.width() - transx,
- wattr.height - data.crect.height() - transy);
-
- // add the border_width for the window managers frame... some window managers
- // do not use a border_width of zero for their frames, and if we the left and
- // top strut, we ensure that pos() is absolutely correct. frameGeometry()
- // will still be incorrect though... perhaps i should have foffset as well, to
- // indicate the frame offset (equal to the border_width on X).
- // - Brad
- top->frameStrut.adjust(wattr.border_width,
- wattr.border_width,
- wattr.border_width,
- wattr.border_width);
- }
-
- data.fstrut_dirty = false;
-}
-
-void QWidgetPrivate::setWindowOpacity_sys(qreal opacity)
-{
- Q_Q(QWidget);
- ulong value = ulong(opacity * 0xffffffff);
- XChangeProperty(QX11Info::display(), q->internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL,
- 32, PropModeReplace, (uchar*)&value, 1);
-}
-
-const QX11Info &QWidget::x11Info() const
-{
- Q_D(const QWidget);
- return d->xinfo;
-}
-
-void QWidgetPrivate::setWindowRole()
-{
- Q_Q(QWidget);
- if (!q->internalWinId())
- return;
- QByteArray windowRole = topData()->role.toUtf8();
- XChangeProperty(X11->display, q->internalWinId(),
- ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
- (unsigned char *)windowRole.constData(), windowRole.length());
-}
-
-Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
-QPaintEngine *QWidget::paintEngine() const
-{
- Q_D(const QWidget);
- if (qt_widget_paintengine()->isActive()) {
- if (d->extraPaintEngine)
- return d->extraPaintEngine;
- QWidget *self = const_cast<QWidget *>(this);
- self->d_func()->extraPaintEngine = new QX11PaintEngine();
- return d->extraPaintEngine;
- }
- return qt_widget_paintengine();
-}
-
-QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
-{
- return new QX11WindowSurface(q_func());
-}
-
-Qt::HANDLE QWidget::x11PictureHandle() const
-{
-#ifndef QT_NO_XRENDER
- Q_D(const QWidget);
- if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
- (void)winId(); // enforce native window
- return d->picture;
-#else
- return 0;
-#endif // QT_NO_XRENDER
-}
-
-#ifndef QT_NO_XRENDER
-XRenderColor QX11Data::preMultiply(const QColor &c)
-{
- XRenderColor color;
- const uint A = c.alpha(),
- R = c.red(),
- G = c.green(),
- B = c.blue();
- color.alpha = (A | A << 8);
- color.red = (R | R << 8) * color.alpha / 0x10000;
- color.green = (G | G << 8) * color.alpha / 0x10000;
- color.blue = (B | B << 8) * color.alpha / 0x10000;
- return color;
-}
-Picture QX11Data::getSolidFill(int screen, const QColor &c)
-{
- if (!X11->use_xrender)
- return XNone;
-
- XRenderColor color = preMultiply(c);
- for (int i = 0; i < X11->solid_fill_count; ++i) {
- if (X11->solid_fills[i].screen == screen
- && X11->solid_fills[i].color.alpha == color.alpha
- && X11->solid_fills[i].color.red == color.red
- && X11->solid_fills[i].color.green == color.green
- && X11->solid_fills[i].color.blue == color.blue)
- return X11->solid_fills[i].picture;
- }
- // none found, replace one
- int i = qrand() % 16;
-
- if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
- XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
- X11->solid_fills[i].picture = 0;
- }
-
- if (!X11->solid_fills[i].picture) {
- Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
- XRenderPictureAttributes attrs;
- attrs.repeat = True;
- X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
- XRenderFindStandardFormat(X11->display, PictStandardARGB32),
- CPRepeat, &attrs);
- XFreePixmap (X11->display, pixmap);
- }
-
- X11->solid_fills[i].color = color;
- X11->solid_fills[i].screen = screen;
- XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
- return X11->solid_fills[i].picture;
-}
-#endif
-
-void QWidgetPrivate::setModal_sys()
-{
-}
-
-void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att)
-{
- QX11InfoData* xd = xinfo->getX11Data(true);
- const XWindowAttributes &a = *(att.att);
- // find which screen the window is on...
- xd->screen = QX11Info::appScreen(); // by default, use the default :)
- int i;
- for (i = 0; i < ScreenCount(X11->display); i++) {
- if (RootWindow(X11->display, i) == a.root) {
- xd->screen = i;
- break;
- }
- }
-
- xd->depth = a.depth;
- xd->cells = DisplayCells(X11->display, xd->screen);
- xd->visual = a.visual;
- xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
- XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo->screen())));
- xd->colormap = a.colormap;
- xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo->screen()));
- xinfo->setX11Data(xd);
-}
-
-void QWidgetPrivate::updateX11AcceptFocus()
-{
- Q_Q(QWidget);
- if (!q->isWindow() || !q->internalWinId())
- return;
-
- XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
- XWMHints wm_hints;
- if (!h) {
- memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
- h = &wm_hints;
- }
- h->flags |= InputHint;
- h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
-
- XSetWMHints(X11->display, q->internalWinId(), h);
- if (h != &wm_hints)
- XFree((char *)h);
-}
-
-QT_END_NAMESPACE