📄 qwidget_x11.cpp
字号:
// put it into netWmState if (!returnValue.isEmpty()) { memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom)); } 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 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); 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; // 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; } //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 dialog = popup = false; // force these flags off data.crect.setRect(0, 0, sw, sh); } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) { 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->internalWinId(); 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); QX11InfoData* xd = xinfo.getX11Data(true); // find which screen the window is on... xd->screen = QX11Info::appScreen(); // by default, use the default :) int i; for (i = 0; i < ScreenCount(dpy); i++) { if (RootWindow(dpy, i) == a.root) { xd->screen = i; break; } } xd->depth = a.depth; xd->cells = DisplayCells(dpy, 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); } 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 {#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); } } 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) { XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual()); if (format) picture = XRenderCreatePicture(dpy, id, format, 0, 0); }#endif // QT_NO_XRENDER // NET window types long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 }; int curr_wintype = 0; QtMWMHints mwmhints; mwmhints.flags = 0L; mwmhints.functions = MWM_FUNC_ALL; mwmhints.decorations = MWM_DECOR_ALL; mwmhints.input_mode = 0L; mwmhints.status = 0L; if (topLevel) { ulong wsa_mask = 0; if (type == Qt::SplashScreen) { net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_SPLASH); } else { // if (customize) { mwmhints.decorations = 0L; mwmhints.flags |= MWM_HINTS_DECORATIONS; if (flags & Qt::FramelessWindowHint) { // override netwm type - quick and easy for KDE noborder net_wintypes[curr_wintype++] = ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE); } else { 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; if (flags & Qt::WindowMaximizeButtonHint) mwmhints.decorations |= MWM_DECOR_MAXIMIZE; } } if (tool) { wsa.save_under = True; wsa_mask |= CWSaveUnder; } // ### need a better way to do this if (q->inherits("QMenu")) { // menu netwm type net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_MENU); } else if (q->inherits("QToolBar")) { // toolbar netwm type net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR); } else if (type == Qt::Tool || type == Qt::Drawer) { // utility netwm type net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_UTILITY); } if (dialog) // dialog netwm type net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DIALOG); // normal netwm type - default net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); if (flags & Qt::X11BypassWindowManagerHint) { wsa.override_redirect = True; wsa_mask |= CWOverrideRedirect; } if (wsa_mask && initializeWindow) XChangeWindowAttributes(dpy, id, wsa_mask, &wsa); } if (!initializeWindow) { // do no initialization } else if (popup) { // popup widget wsa.override_redirect = True; wsa.save_under = True; 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 wm_hints.flags = InputHint | StateHint | WindowGroupHint; wm_hints.input = 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, 0, 0, &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[4]; 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 if (flags & Qt::WindowContextHelpButtonHint) protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP); XSetWMProtocols(dpy, id, protocols, n); // set mwm hints SetMWMHints(dpy, id, mwmhints); // set _NET_WM_WINDOW_TYPE if (curr_wintype > 0) XChangeProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, PropModeReplace, (unsigned char *) net_wintypes, curr_wintype); else XDeleteProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE)); // 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 object name as window role QByteArray objName = q->objectName().toLocal8Bit(); XChangeProperty(dpy, id, ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace, (unsigned char *)objName.constData(), objName.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) { // don't erase when resizing wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -