📄 qwidget_x11.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#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 "qdatetime.h"#include "qcursor.h"#include "qstack.h"#include "qcolormap.h"#include "qdebug.h"#include "private/qbackingstore_p.h"extern bool qt_reuse_double_buffer; // declared in qapplication_x11.cppextern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp#include <private/qpixmap_p.h>#include <private/qpaintengine_x11_p.h>#include "qt_x11_p.h"#include "qx11info_x11.h"#include <stdlib.h>// defined in qapplication_x11.cppbool 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 32767#define WRECT_MAX 8191extern bool qt_nograb();static QWidget *mouseGrb = 0;static QWidget *keyboardGrb = 0;int qt_x11_create_desktop_on_screen = -1;// MWM supportstruct 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 wstatic inline bool isTransient(const QWidget *w){ return ((w->windowType() == Qt::Dialog) || (w->windowType() == Qt::Sheet) || (w->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || (w->windowType() == Qt::Tool) || (w->windowType() == Qt::SplashScreen) || (w->windowType() == Qt::ToolTip) || (w->windowType() == Qt::Drawer));}/***************************************************************************** QWidget member functions *****************************************************************************/extern bool qt_broken_wm;// defined in qapplication_x11.cppextern bool qt_net_supports(Atom);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){ 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->winId(); client_message.format = 32; client_message.message_type = ATOM(_QT_SCROLL_DONE); client_message.data.l[0] = sip.id; XSendEvent(X11->display, scrolled_widget->winId(), 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}Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w){ if (w->testAttribute(Qt::WA_SetCursor)) { QCursor *oc = QApplication::overrideCursor(); if (oc) { XDefineCursor(X11->display, w->winId(), oc->handle()); } else if (w->isEnabled()) { XDefineCursor(X11->display, w->winId(), w->cursor().handle()); } else { // enforce the windows behavior of clearing the cursor on // disabled widgets XDefineCursor(X11->display, w->winId(), XNone); } } else { XDefineCursor(X11->display, w->winId(), XNone); }}Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w){ QApplication::flush(); XEvent ev; QTime t; t.start(); while (!XCheckTypedWindowEvent(X11->display, w->winId(), ReparentNotify, &ev)) { if (XCheckTypedWindowEvent(X11->display, w->winId(), MapNotify, &ev)) break; if (t.elapsed() > 500) return; // give up, no event available qApp->syncX(); // non-busy wait } qApp->x11ProcessEvent(&ev); if (XCheckTypedWindowEvent(X11->display, w->winId(), ConfigureNotify, &ev)) qApp->x11ProcessEvent(&ev);}static 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->winId(); 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);}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; bool topLevel = (flags & Qt::Window); bool popup = (type == Qt::Popup); bool dialog = (type == Qt::Dialog || type == Qt::Sheet || (flags & Qt::MSWindowsFixedSizeDialogHint)); bool desktop = (type == Qt::Desktop); bool tool = (type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer); bool customize = (flags & ( Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowContextHelpButtonHint )); if(topLevel && parentWidget) { // if our parent stays on top, so must we QWidget *ptl = parentWidget->window(); if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint)) flags |= Qt::WindowStaysOnTopHint; } Window parentw, destroyw = 0; WId id; // always initialize if (!window) initializeWindow = true; 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 (parentWidget && parentWidget->d_func()->xinfo.screen() != xinfo.screen()) { xinfo = parentWidget->d_func()->xinfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -