📄 qbackingstore.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 <qglobal.h>#include <qapplication.h>#ifdef Q_WS_WIN# include "qt_windows.h"# include <private/qpaintengine_raster_p.h># ifndef QT_NO_DIRECT3D# include <private/qpaintengine_d3d_p.h># include <private/qwindowsurface_d3d_p.h># endif#endif#include "qbackingstore_p.h"#include "private/qwidget_p.h"#include <qdebug.h>#include <qstack.h>#include <qevent.h>#include <qabstractscrollarea.h>#include "private/qabstractscrollarea_p.h"#ifdef Q_WS_X11# include "private/qt_x11_p.h"#endif#ifdef Q_WS_QWS#include <qscreen_qws.h>#include <qwsdisplay_qws.h>#include <qapplication.h>#include <qwsmanager_qws.h>#include <private/qwsmanager_p.h>#include <unistd.h>#endif#include "qwindowsurface_raster_p.h"#ifdef Q_WS_X11#include "qwindowsurface_x11_p.h"#elif defined(Q_WS_QWS)#include "qwindowsurface_qws_p.h"#endif/***************************************************************************** Top Level Window backing store *****************************************************************************/extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication_xxx.cpp#ifndef Q_WS_QWSstatic bool qt_enable_backingstore = true;#endif#ifdef Q_WS_X11// for compatibility with Qt 4.0Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable){ qt_enable_backingstore = enable;}#endifbool QWidgetBackingStore::paintOnScreen(QWidget *w){#if defined(Q_WS_QWS) || defined(Q_WS_MAC) Q_UNUSED(w); return false;#elif defined(QT_NO_BACKINGSTORE) Q_UNUSED(w); return true;#else if (w && (w->testAttribute(Qt::WA_PaintOnScreen) || !w->isWindow() && w->window()->testAttribute(Qt::WA_PaintOnScreen))) return true; // sanity check for overlarge toplevels. Better: store at least screen size and move offset. if (w && w->isWindow() && (w->width() > 4096 || w->height() > 4096)) return true; static signed char checked_env = -1; if(checked_env == -1) checked_env = (qgetenv("QT_ONSCREEN_PAINT") == "1") ? 1 : 0; return checked_env == 1 || !qt_enable_backingstore;#endif}#ifndef QT_NO_PAINT_DEBUG#ifdef Q_WS_QWSstatic void qt_showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool){ Q_UNUSED(widget); static QWSYellowSurface surface(true); surface.setDelay(msec); surface.flush(widget, rgn, QPoint());}#elsestatic void qt_showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped){ //flags to fool painter bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped);#ifdef Q_WS_WIN Q_UNUSED(unclipped);#else if (unclipped && !QWidgetBackingStore::paintOnScreen(widget)) widget->setAttribute(Qt::WA_PaintUnclipped);#endif bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent); if(setFlag) widget->setAttribute(Qt::WA_WState_InPaintEvent); static int i = 0; //setup the engine QPaintEngine *pe = widget->paintEngine(); if (pe) { pe->setSystemClip(toBePainted); { QPainter p(widget); p.setClipRegion(toBePainted); switch (i) { case 0: p.fillRect(widget->rect(), QColor(255,255,0)); break; case 1: p.fillRect(widget->rect(), QColor(255,200,55)); break; case 2: p.fillRect(widget->rect(), QColor(200,255,55)); break; case 3: p.fillRect(widget->rect(), QColor(200,200,0)); break; } i = (i+1) & 3; p.end(); } } if(setFlag) widget->setAttribute(Qt::WA_WState_InPaintEvent, false); //restore widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped); if (pe) { pe->setSystemClip(QRegion()); //flush if (pe->type() == QPaintEngine::Raster) { QRasterPaintEngine *rpe = static_cast<QRasterPaintEngine *>(pe); rpe->flush(widget, QPoint()); } } QApplication::syncX();#if defined(Q_OS_UNIX) ::usleep(1000*msec);#elif defined(Q_OS_WIN) ::Sleep(msec);#endif}#endifstatic int test_qt_flushPaint(){ static int flush_paint = qgetenv("QT_FLUSH_PAINT").toInt(); return flush_paint;}static bool qt_flushPaint(QWidget *widget, const QRegion &toBePainted){ static int flush_paint = test_qt_flushPaint(); if (!flush_paint) return false; qt_showYellowThing(widget, toBePainted, flush_paint * 10, true); return true;}static void qt_unflushPaint(QWidget *widget, const QRegion &rgn){ if (!QWidgetBackingStore::paintOnScreen(widget)) QWidgetBackingStore::copyToScreen(widget, rgn);}#if !defined(Q_WS_QWS)static bool qt_flushUpdate(QWidget *widget, const QRegion &rgn){ static int checked_env = -1; if(checked_env == -1) { checked_env = qgetenv("QT_FLUSH_UPDATE").toInt(); } if (checked_env == 0) return false; qt_showYellowThing(widget, rgn, checked_env*10, false); return true;}#endif#endif // QT_NO_PAINT_DEBUGvoid qt_syncBackingStore(QRegion rgn, QWidget *widget, bool recursive){ if (!QWidgetBackingStore::paintOnScreen(widget)) { if (QWidgetBackingStore *bs = widget->d_func()->maybeBackingStore()) bs->cleanRegion(rgn, widget, recursive); } else { widget->repaint(rgn); }}void qt_syncBackingStore(QRegion rgn, QWidget *widget){ qt_syncBackingStore(rgn, widget, false);}#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)extern QDirect3DPaintEngine *qt_d3dEngine();#endifQWindowSurface *qt_default_window_surface(QWidget *widget){ QWindowSurface *surface = 0;#ifdef Q_WS_WIN#ifndef QT_NO_DIRECT3D if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) && (widget->windowOpacity() == 1.0f) && qt_d3dEngine()->hasDirect3DSupport()) surface = new QD3DWindowSurface(widget); else surface = new QRasterWindowSurface(widget);#else surface = new QRasterWindowSurface(widget);#endif#elif defined(Q_WS_X11) surface = new QX11WindowSurface(widget);#elif defined(Q_WS_QWS) if (widget->windowType() == Qt::Desktop) return 0; widget->ensurePolished(); surface = qt_screen->createSurface(widget);#else Q_UNUSED(widget);#endif // The QWindowSurface constructor will call QWidget::setWindowSurface(), // but automatically created surfaces should not be added to the topdata.#ifdef Q_BACKINGSTORE_SUBSURFACES Q_ASSERT(widget->d_func()->topData()->windowSurface == surface);#endif widget->d_func()->topData()->windowSurface = 0; return surface;}#ifdef Q_WS_WIN/* Used by QETWidget::translatePaintEvent and expects rgn to be in windowing system coordinates. */void QWidgetBackingStore::blitToScreen(const QRegion &rgn, QWidget *widget){ QWidget *tlw = widget->window(); if (!widget->isVisible() || !tlw->testAttribute(Qt::WA_Mapped) || rgn.isEmpty()) return; if (!QWidgetBackingStore::paintOnScreen(widget)) { QWidgetBackingStore *bs = tlw->d_func()->topData()->backingStore; bs->windowSurface->flush(widget, rgn, widget->mapTo(tlw, QPoint(0, 0))); }}#endif#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && defined(Q_WIN_USE_QT_UPDATE_EVENT))void qt_syncBackingStore(QWidget *widget){ // dirtyOnScreen may get out of sync when widget is scrolled or moved widget->d_func()->dirtyOnScreen &= widget->d_func()->clipRect(); const QRegion dirty = widget->d_func()->dirtyOnScreen; QWidget *tlw = widget->window(); if (!QWidgetBackingStore::paintOnScreen(widget)) { QWidgetBackingStore *bs = tlw->d_func()->topData()->backingStore; bs->cleanRegion(dirty, widget); } else { widget->repaint(dirty); }}#elif defined(Q_WS_QWS)void qt_syncBackingStore(QWidget *widget){ QWidget *tlw = widget->window(); QTLWExtra *topData = tlw->d_func()->topData(); QWidgetBackingStore *bs = topData->backingStore; QWSWindowSurface *surface = 0; if(bs) surface = static_cast<QWSWindowSurface*>(bs->windowSurface); else qWarning("request to sync backing store of widget %p, " "which does not have its backing store defined yet", (void*)widget); QRegion toClean; if (surface) toClean = surface->dirtyRegion();#ifdef Q_BACKINGSTORE_SUBSURFACES if (bs) { QList<QWindowSurface*> subSurfaces = bs->subSurfaces; for (int i = 0; i < subSurfaces.size(); ++i) { QWSWindowSurface *s = static_cast<QWSWindowSurface*>(subSurfaces.at(i)); QPoint offset = s->window()->mapTo(tlw, QPoint()); toClean += s->dirtyRegion().translated(-offset); } }#endif#ifdef Q_WIDGET_USE_DIRTYLIST if (!toClean.isEmpty() || !bs->dirtyWidgets.isEmpty())#else if (!toClean.isEmpty())#endif topData->backingStore->cleanRegion(toClean, tlw);}#elif defined(Q_WS_WIN) && !defined(Q_WIN_USE_QT_UPDATE_EVENT)void qt_syncBackingStore(QWidget *widget){ QWidget *tlw = widget->window(); QTLWExtra *topData = tlw->d_func()->topData(); QWidgetBackingStore *bs = topData->backingStore; if (!bs) return; const QRegion toClean = bs->dirty;#ifdef Q_WIDGET_USE_DIRTYLIST if (!toClean.isEmpty() || !bs->dirtyWidgets.isEmpty())#else if (!toClean.isEmpty())#endif topData->backingStore->cleanRegion(toClean, tlw, false);}#endif // Q_WS_WIN/* A version of QRect::intersects() that does not normalize the rects.*/static inline bool qRectIntersects(const QRect &r1, const QRect &r2){ return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) && qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));}QWidgetBackingStore::QWidgetBackingStore(QWidget *t) : tlw(t){ windowSurface = tlw->windowSurface(); if (!windowSurface) windowSurface = qt_default_window_surface(t);#ifdef Q_BACKINGSTORE_SUBSURFACES // XXX: hw: workaround to ensure all existing subsurfaces are added to the list QList<QObject*> children = t->children(); for (int i = 0; i < children.size(); ++i) { QWidget *child = qobject_cast<QWidget*>(children.at(i)); if (!child) continue; QTLWExtra *extra = child->d_func()->maybeTopData(); if (extra && extra->windowSurface) subSurfaces.append(extra->windowSurface); }#endif}QWidgetBackingStore::~QWidgetBackingStore(){ delete windowSurface; windowSurface = 0;}/* Widget's coordinate system move whole rect by dx,dy rect must be valid doesn't generate any updates*/bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget){ QPoint pos(widget->mapTo(tlw, rect.topLeft()));#ifdef Q_WS_QWS pos += topLevelOffset();#endif return windowSurface->scroll(QRect(pos, rect.size()), dx, dy);}//parent's coordinates; move whole rect; update parent and widget//assume the screen blt has already been done, so we don't need to refresh that partvoid QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy){ Q_Q(QWidget); if (!q->isVisible()) return; QWidget *tlw = q->window(); QTLWExtra* x = tlw->d_func()->topData(); static int accelEnv = -1; if (accelEnv == -1) { accelEnv = qgetenv("QT_NO_FAST_MOVE").toInt() == 0; } QWidget *pw = q->parentWidget(); QPoint toplevelOffset = pw->mapTo(tlw, QPoint()); QWidgetPrivate *pd = pw->d_func(); QRect clipR = pd->clipRect();#ifdef Q_WS_QWS QWidgetBackingStore *wbs = x->backingStore; QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); clipR = clipR.intersected(surface->clipRegion().translated(-toplevelOffset).boundingRect());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -