📄 qwidget_x11.cpp
字号:
} //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 q->data->crect.setRect(0, 0, sw, sh); } else if (topLevel) { // calc pos/size from screen q->data->crect.setRect(sw/4, 3*sh/10, sw/2, 4*sh/10); } else { // child widget q->data->crect.setRect(0, 0, 100, 30); } parentw = topLevel ? root_win : parentWidget->winId(); XSetWindowAttributes wsa; if (window) { // override the old window if (destroyOldWindow) destroyw = data.winid; id = window; setWinId(window); XWindowAttributes a; XGetWindowAttributes(dpy, window, &a); q->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 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 (xinfo.defaultVisual() && xinfo.defaultColormap()) { id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw, q->data->crect.left(), q->data->crect.top(), q->data->crect.width(), q->data->crect.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, data.crect.left(), data.crect.top(), data.crect.width(), data.crect.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) { picture = XRenderCreatePicture(dpy, id, XRenderFindVisualFormat (dpy, (Visual *) xinfo.visual()), 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; bool custom_decorations = customize; if (!customize) { if (dialog) { custom_decorations = true; flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint; } else if (type == Qt::SplashScreen) { if (qt_net_supports(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) { flags &= ~Qt::X11BypassWindowManagerHint; net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_SPLASH); } else { custom_decorations = true; flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint; } } else if (type == Qt::Tool) { custom_decorations = true; flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint; } else { custom_decorations = true; flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint; } } if (custom_decorations) { mwmhints.decorations = 0L; mwmhints.flags |= MWM_HINTS_DECORATIONS; // All these buttons depend on the system menu, so we enable it if (flags & (Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowContextHelpButtonHint)) flags |= Qt::WindowSystemMenuHint; 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); } else if (!customize) { flags |= Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint; } 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, data.crect.width(), data.crect.height()); 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); } // 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 { XSelectInput(dpy, id, stdWidgetEventMask);#if !defined (QT_NO_TABLET) QTabletDeviceDataList *tablet_list = qt_tablet_devices(); for (int i = 0; i < tablet_list->size(); ++i) { QTabletDeviceData tablet = tablet_list->at(i); XSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList), tablet.eventCount); }#endif } if (desktop) { q->setAttribute(Qt::WA_WState_Visible); } else if (topLevel) { // set X cursor q->setAttribute(Qt::WA_SetCursor); if (initializeWindow) qt_x11_enforce_cursor(q); } if (destroyw) qt_XDestroyWindow(q, dpy, destroyw); // 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();#if 0 static bool onScreen = false; q->setAttribute(Qt::WA_PaintOnScreen, onScreen); onScreen = !onScreen;#endif#if !defined(QT_NO_IM) ic = 0;#endif}/*! Frees up window system resources. Destroys the widget window if \a destroyWindow is true. destroy() calls itself recursively for all the child widgets, passing \a destroySubWindows for the \a destroyWindow parameter. To have more control over destruction of subwidgets, destroy subwidgets selectively first. This function is usually called from the QWidget destructor.*/void QWidget::destroy(bool destroyWindow, bool destroySubWindows){ Q_D(QWidget); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(geometry()); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { setAttribute(Qt::WA_WState_Created, false); QObjectList childs = children(); for (int i = 0; i < childs.size(); ++i) { // destroy all widget children register QObject *obj = childs.at(i); if (obj->isWidgetType()) static_cast<QWidget*>(obj)->destroy(destroySubWindows, destroySubWindows); } if (mouseGrb == this) releaseMouse(); if (keyboardGrb == this) releaseKeyboard();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -