📄 qbackingstore.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 <qglobal.h>#include <qapplication.h>#ifdef Q_WS_WIN# include "qt_windows.h"# include <private/qpaintengine_raster_p.h>#endif#include "qbackingstore_p.h"#include "private/qwidget_p.h"#include <qdebug.h>#include <qstack.h>#include <qevent.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/***************************************************************************** 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)) 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}#ifdef Q_WS_QWSstatic void qt_showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool){ static int yWinId = 0; if (yWinId == 0) { yWinId = QWidget::qwsDisplay()->takeId(); QWidget::qwsDisplay()->nameRegion(yWinId, "Debug flush paint", "Silly yellow thing"); QWidget::qwsDisplay()->setAltitude(yWinId, 1, true); } QRegion globalRgn = rgn; if (widget) globalRgn.translate(widget->mapToGlobal(QPoint())); QWidget::qwsDisplay()->requestRegion(yWinId, -1, QWSBackingStore::DebugHighlighter, globalRgn, QImage::Format_Invalid); QWidget::qwsDisplay()->setAltitude(yWinId, 1, true); QWidget::qwsDisplay()->repaintRegion(yWinId, false, globalRgn); ::usleep(500*msec); QWidget::qwsDisplay()->requestRegion(yWinId, -1, QWSBackingStore::DebugHighlighter, QRegion(), QImage::Format_Invalid); ::usleep(500*msec);}#elsestatic void qt_showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped){ //flags to fool painter bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped); if (unclipped && !QWidgetBackingStore::paintOnScreen(widget)) widget->setAttribute(Qt::WA_PaintUnclipped); 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 bool qt_flushPaint(QWidget *widget, const QRegion &toBePainted){ static int checked_env = -1; if(checked_env == -1) checked_env = qgetenv("QT_FLUSH_PAINT").toInt(); if (checked_env == 0) return false; qt_showYellowThing(widget, toBePainted, checked_env*10, true); return true;}static void qt_unflushPaint(QWidget *widget, const QRegion &rgn){ if (!QWidgetBackingStore::paintOnScreen(widget)) QWidgetBackingStore::copyToScreen(widget, rgn);}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;}void qt_syncBackingStore(QRegion rgn, QWidget *widget, bool recursive){ if (!QWidgetBackingStore::paintOnScreen(widget)) { QWidget *tlw = widget->window(); tlw->d_func()->topData()->backingStore->cleanRegion(rgn, widget, recursive); } else { widget->repaint(rgn); }}void qt_syncBackingStore(QRegion rgn, QWidget *widget){ qt_syncBackingStore(rgn, widget, false);}#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; QSize tlwSize = tlw->size(); if (!bs || bs->buffer.size() != tlwSize) return; QRasterPaintEngine *engine = (QRasterPaintEngine*) bs->buffer.paintEngine(); HDC engine_dc = engine->getDC(); HDC widget_dc = (HDC) widget->d_func()->hd; bool tmp_widget_dc = false; if (!widget_dc) { widget_dc = GetDC(widget->winId()); tmp_widget_dc = true; } // The position of widget relative to top level's top left QPoint offset = widget->mapTo(tlw, QPoint()); QRect br = rgn.boundingRect(); QRect qbounds = widget->d_func()->mapFromWS(br); BitBlt(widget_dc, br.x(), br.y(), br.width(), br.height(), engine_dc, qbounds.x() + offset.x(), qbounds.y() + offset.y(), SRCCOPY); if (tmp_widget_dc) ReleaseDC(widget->winId(), widget_dc); engine->releaseDC(engine_dc); }}#endif#if defined(Q_WS_X11)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 *wbs = topData->backingStore; QRegion toClean = wbs->dirty_on_screen;#if 0 // debug qDebug() << "qt_syncBackingStore" << tlw << tlw->rect(); qDebug() << "dirty ==" << wbs->dirty; qDebug() << "dirty_on_screen ==" << wbs->dirty_on_screen;#endif if (!toClean.isEmpty()) topData->backingStore->cleanRegion(toClean, tlw);}#endif/* 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)#ifdef Q_WS_WIN , buffer(t)#endif{}QWidgetBackingStore::~QWidgetBackingStore(){}/* Widget's coordinate system
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -