void QX11WindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { if (d_ptr->device.isNull()) return; QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); QRegion wrgn(rgn); QRect br = rgn.boundingRect(); if (!wOffset.isNull()) wrgn.translate(-wOffset); QRect wbr = wrgn.boundingRect(); int num; XRectangle *rects = (XRectangle *)qt_getClipRects(wrgn, num); if (num <= 0) return; // qDebug() << "XSetClipRectangles"; // for (int i = 0; i < num; ++i) // qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height; if (num != 1) XSetClipRectangles(X11->display, gc, 0, 0, rects, num, YXBanded); XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc, br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), wbr.x(), wbr.y()); if (num != 1) XSetClipMask(X11->display, gc, XNone); }
void QX11WindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { if (d_ptr->device.isNull()) return; #ifndef Q_FLATTEN_EXPOSE extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp extern QWidgetData* qt_widget_data(QWidget *); QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); GC gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0); QRegion wrgn(rgn); QRect br = rgn.boundingRect(); if (!wOffset.isNull()) wrgn.translate(-wOffset); QRect wbr = wrgn.boundingRect(); // #### why dirty widget here? should be up to date already // if (br.right() + offset.x() >= d_ptr->device.size().width() || br.bottom() + offset.y() >= d_ptr->device.size().height()) { // // QRegion dirty = rgn - QRect(-offset, d_ptr->device.size()); // // qDebug() << dirty; // widget->d_func()->dirtyWidget_sys(rgn - QRect(-offset, d_ptr->device.size())); // } int num; XRectangle *rects = (XRectangle *)qt_getClipRects(wrgn, num); // qDebug() << "XSetClipRectangles"; // for (int i = 0; i < num; ++i) // qDebug() << " " << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height; XSetClipRectangles(X11->display, gc, 0, 0, rects, num, YXBanded); #else Q_UNUSED(rgn); XGCValues values; values.subwindow_mode = IncludeInferiors; GC gc = XCreateGC(X11->display, d_ptr->device.handle(), GCSubwindowMode, &values); #endif XSetGraphicsExposures(X11->display, gc, False); // XFillRectangle(X11->display, widget->handle(), gc, 0, 0, widget->width(), widget->height()); #ifndef Q_FLATTEN_EXPOSE XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc, br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), wbr.x(), wbr.y()); #else Q_ASSERT(widget->isWindow()); XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc, offset.x(), offset.y(), widget->width(), widget->height(), 0, 0); #endif XFreeGC(X11->display, gc); }
void QWidgetPrivate::dirtyWidget_sys(const QRegion &rgn, bool updateImmediately) { Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra *tlwExtra = tlw->d_func()->topData(); QWidgetBackingStore *wbs = tlwExtra->backingStore; QRegion wrgn(rgn); if (tlw != q) { QPoint offs(q->mapTo(tlw, QPoint())); wrgn.translate(offs); } QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); if (surface) { surface->d_ptr->updateImmediately = updateImmediately; if (tlwExtra->proxyWidget) { // Add the existing dirty region to the current update region before // we reset QWSWindowSurface::dirty. We do this in order to always // send an update event on sub-sequent updates/repaints. wrgn += surface->d_ptr->dirty; surface->d_ptr->dirty = QRegion(); // XXX: hw: Make sure we post/send update requests. surface->d_ptr->clip = wrgn; } surface->setDirty(wrgn); // re-get, since setDirty may recreate the surface surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); surface->d_ptr->updateImmediately = false; #ifdef Q_BACKINGSTORE_SUBSURFACES // dirty on all subsurfaces... QList<QWindowSurface*> subSurfaces = wbs->subSurfaces; // XXX: hw: only if region intersects any of the subsurfaces for (int i = 0; i < subSurfaces.size(); ++i) { QWSWindowSurface *s = static_cast<QWSWindowSurface*>(subSurfaces.at(i)); QPoint p = s->window()->mapTo(tlw, QPoint()); // must use widget? s->d_ptr->updateImmediately = updateImmediately; s->setDirty(wrgn.translated(-p)); s->d_ptr->updateImmediately = false; } #endif // Q_BACKINGSTORE_SUBSURFACES } }
/*! Invalidates the \a rgn (in widget's coordinates) of the backing store, i.e. all widgets intersecting with the region will be repainted when the backing store is synced. ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). */ void QWidgetPrivate::invalidateBuffer(const QRegion &rgn) { Q_Q(QWidget); QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (discardInvalidateBufferRequest(q, tlwExtra) || rgn.isEmpty()) return; QRegion wrgn(rgn); wrgn &= clipRect(); if (!graphicsEffect && extra && extra->hasMask) wrgn &= extra->mask; if (wrgn.isEmpty()) return; tlwExtra->backingStore->markDirty(wrgn, q, false, true); }
void QWidgetPrivate::cleanWidget_sys(const QRegion& rgn) { Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (!tlwExtra || !tlwExtra->proxyWidget || tlwExtra->backingStore) return; QRegion wrgn(rgn); if (tlw != q) { QPoint offs(q->mapTo(tlw, QPoint())); wrgn.translate(offs); } if (QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(tlwExtra->backingStore->windowSurface)) surface->d_ptr->dirty -= wrgn; }
void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { Q_D(QRasterWindowSurface); // Not ready for painting yet, bail out. This can happen in // QWidget::create_sys() if (!d->image || rgn.rectCount() == 0) return; #ifdef Q_WS_WIN QRect br = rgn.boundingRect(); if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground) && (qt_widget_private(window())->data.window_flags & Qt::FramelessWindowHint)) { QRect r = window()->frameGeometry(); QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft(); QRect dirtyRect = br.translated(offset + frameOffset); SIZE size = {r.width(), r.height()}; POINT ptDst = {r.x(), r.y()}; POINT ptSrc = {0, 0}; BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA}; RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, d->image->hdc, &ptSrc, 0, &blend, Q_ULW_ALPHA, &dirty}; ptrUpdateLayeredWindowIndirect(window()->internalWinId(), &info); } else { QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); HDC widget_dc = widget->getDC(); QRect wbr = br.translated(-wOffset); BitBlt(widget_dc, wbr.x(), wbr.y(), wbr.width(), wbr.height(), d->image->hdc, br.x() + offset.x(), br.y() + offset.y(), SRCCOPY); widget->releaseDC(widget_dc); } #ifndef QT_NO_DEBUG static bool flush = !qgetenv("QT_FLUSH_WINDOWSURFACE").isEmpty(); if (flush) { SelectObject(qt_win_display_dc(), GetStockObject(BLACK_BRUSH)); Rectangle(qt_win_display_dc(), 0, 0, d->image->width() + 2, d->image->height() + 2); BitBlt(qt_win_display_dc(), 1, 1, d->image->width(), d->image->height(), d->image->hdc, 0, 0, SRCCOPY); } #endif #endif #ifdef Q_WS_X11 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp extern QWidgetData* qt_widget_data(QWidget *); QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); if (widget->window() != window()) { XFreeGC(X11->display, d_ptr->gc); d_ptr->gc = XCreateGC(X11->display, widget->handle(), 0, 0); } QRegion wrgn(rgn); if (!wOffset.isNull()) wrgn.translate(-wOffset); if (wrgn.rectCount() != 1) { int num; XRectangle *rects = (XRectangle *)qt_getClipRects(wrgn, num); XSetClipRectangles(X11->display, d_ptr->gc, 0, 0, rects, num, YXBanded); } QPoint widgetOffset = offset + wOffset; QRect clipRect = widget->rect().translated(widgetOffset).intersected(d_ptr->image->image.rect()); QRect br = rgn.boundingRect().translated(offset).intersected(clipRect); QPoint wpos = br.topLeft() - widgetOffset; #ifndef QT_NO_MITSHM if (d_ptr->image->xshmpm) { XCopyArea(X11->display, d_ptr->image->xshmpm, widget->handle(), d_ptr->gc, br.x(), br.y(), br.width(), br.height(), wpos.x(), wpos.y()); d_ptr->needsSync = true; } else if (d_ptr->image->xshmimg) { XShmPutImage(X11->display, widget->handle(), d_ptr->gc, d_ptr->image->xshmimg, br.x(), br.y(), wpos.x(), wpos.y(), br.width(), br.height(), False); d_ptr->needsSync = true; } else #endif { int depth = widget->x11Info().depth(); const QImage &src = d->image->image; if (src.format() != QImage::Format_RGB32 || depth < 24 || X11->bppForDepth.value(depth) != 32) { Q_ASSERT(src.depth() >= 16); const QImage sub_src(src.scanLine(br.y()) + br.x() * (uint(src.depth()) / 8), br.width(), br.height(), src.bytesPerLine(), src.format()); QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType); data->xinfo = widget->x11Info(); data->fromImage(sub_src, Qt::NoOpaqueDetection); QPixmap pm = QPixmap(data); XCopyArea(X11->display, pm.handle(), widget->handle(), d_ptr->gc, 0 , 0 , br.width(), br.height(), wpos.x(), wpos.y()); } else { // qpaintengine_x11.cpp extern void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image, Drawable hd, GC gc, Display *dpy, Visual *visual, int depth); qt_x11_drawImage(br, wpos, src, widget->handle(), d_ptr->gc, X11->display, (Visual *)widget->x11Info().visual(), depth); } } if (wrgn.rectCount() != 1) XSetClipMask(X11->display, d_ptr->gc, XNone); #endif // FALCON #ifdef Q_WS_MAC Q_UNUSED(offset); // This is mainly done for native components like native "open file" dialog. if (widget->testAttribute(Qt::WA_DontShowOnScreen)) { return; } #ifdef QT_MAC_USE_COCOA this->needsFlush = true; this->regionToFlush += rgn; // The actual flushing will be processed in [view drawRect:rect] qt_mac_setNeedsDisplay(widget); #else // Get a context for the widget. CGContextRef context; CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); CGContextRetain(context); CGContextSaveGState(context); // Flip context. CGContextTranslateCTM(context, 0, widget->height()); CGContextScaleCTM(context, 1, -1); // Clip to region. const QVector<QRect> &rects = rgn.rects(); for (int i = 0; i < rects.size(); ++i) { const QRect &rect = rects.at(i); CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); } CGContextClip(context); QRect r = rgn.boundingRect().intersected(d->image->image.rect()); const CGRect area = CGRectMake(r.x(), r.y(), r.width(), r.height()); CGImageRef image = CGBitmapContextCreateImage(d->image->cg); CGImageRef subImage = CGImageCreateWithImageInRect(image, area); qt_mac_drawCGImage(context, &area, subImage); CGImageRelease(subImage); CGImageRelease(image); QDEndCGContext(port, &context); // Restore context. CGContextRestoreGState(context); CGContextRelease(context); #endif // QT_MAC_USE_COCOA #endif // Q_WS_MAC }
void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { Q_D(QRasterWindowSurface); // Not ready for painting yet, bail out. This can happen in // QWidget::create_sys() if (!d->image) return; #ifdef Q_WS_WIN QRect br = rgn.boundingRect(); #ifndef Q_OS_WINCE if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow) { QRect r = window()->frameGeometry(); QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft(); QRect dirtyRect = br.translated(offset + frameOffset); SIZE size = {r.width(), r.height()}; POINT ptDst = {r.x(), r.y()}; POINT ptSrc = {0, 0}; Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA}; RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, d->image->hdc, &ptSrc, 0, &blend, Q_ULW_ALPHA, &dirty}; (*ptrUpdateLayeredWindowIndirect)(window()->internalWinId(), &info); } else #endif { QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); HDC widget_dc = widget->getDC(); QRect wbr = br.translated(-wOffset); BitBlt(widget_dc, wbr.x(), wbr.y(), wbr.width(), wbr.height(), d->image->hdc, br.x() + offset.x(), br.y() + offset.y(), SRCCOPY); widget->releaseDC(widget_dc); } #ifndef QT_NO_DEBUG static bool flush = !qgetenv("QT_FLUSH_WINDOWSURFACE").isEmpty(); if (flush) { SelectObject(qt_win_display_dc(), GetStockObject(BLACK_BRUSH)); Rectangle(qt_win_display_dc(), 0, 0, d->image->width() + 2, d->image->height() + 2); BitBlt(qt_win_display_dc(), 1, 1, d->image->width(), d->image->height(), d->image->hdc, 0, 0, SRCCOPY); } #endif #endif #ifdef Q_WS_X11 extern void *qt_getClipRects(const QRegion &r, int &num); // in qpaintengine_x11.cpp extern QWidgetData* qt_widget_data(QWidget *); QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft(); if (widget->window() != window()) { XFreeGC(X11->display, d_ptr->gc); d_ptr->gc = XCreateGC(X11->display, widget->handle(), 0, 0); } QRegion wrgn(rgn); if (!wOffset.isNull()) wrgn.translate(-wOffset); QRect wbr = wrgn.boundingRect(); int num; XRectangle *rects = (XRectangle *)qt_getClipRects(wrgn, num); XSetClipRectangles(X11->display, d_ptr->gc, 0, 0, rects, num, YXBanded); QRect br = rgn.boundingRect().translated(offset); #ifndef QT_NO_MITSHM if (d_ptr->image->xshmpm) { XCopyArea(X11->display, d_ptr->image->xshmpm, widget->handle(), d_ptr->gc, br.x(), br.y(), br.width(), br.height(), wbr.x(), wbr.y()); XSync(X11->display, False); } else #endif { const QImage &src = d->image->image; br = br.intersected(src.rect()); if (src.format() != QImage::Format_RGB32) { QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType); data->xinfo = widget->x11Info(); data->fromImage(src, Qt::AutoColor); QPixmap pm = QPixmap(data); XCopyArea(X11->display, pm.handle(), widget->handle(), d_ptr->gc, br.x() , br.y() , br.width(), br.height(), wbr.x(), wbr.y()); } else { // qpaintengine_x11.cpp extern void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image, Drawable hd, GC gc, Display *dpy, Visual *visual, int depth); qt_x11_drawImage(br, wbr.topLeft(), src, widget->handle(), d_ptr->gc, X11->display, (Visual *)widget->x11Info().visual(), widget->x11Info().depth()); } } #endif // FALCON #ifdef Q_WS_MAC // qDebug() << "Flushing" << widget << rgn << offset; // d->image->image.save("flush.png"); // Get a context for the widget. #ifndef QT_MAC_USE_COCOA CGContextRef context; CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); #else extern CGContextRef qt_mac_graphicsContextFor(QWidget *); CGContextRef context = qt_mac_graphicsContextFor(widget); #endif CGContextSaveGState(context); // Flip context. CGContextTranslateCTM(context, 0, widget->height()); CGContextScaleCTM(context, 1, -1); // Clip to region. const QVector<QRect> &rects = rgn.rects(); for (int i = 0; i < rects.size(); ++i) { const QRect &rect = rects.at(i); CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); } CGContextClip(context); QRect r = rgn.boundingRect(); const CGRect area = CGRectMake(r.x(), r.y(), r.width(), r.height()); CGImageRef image = CGBitmapContextCreateImage(d->image->cg); CGImageRef subImage = CGImageCreateWithImageInRect(image, area); qt_mac_drawCGImage(context, &area, subImage); CGImageRelease(subImage); CGImageRelease(image); // CGSize size = { d->image->image.width(), d->image->image.height() }; // CGLayerRef layer = CGLayerCreateWithContext(d->image->cg, size, 0); // CGPoint pt = { 0, 0 }; // CGContextDrawLayerAtPoint(context, pt, layer); // CGLayerRelease(layer); // Restore context. CGContextRestoreGState(context); #ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); #else CGContextFlush(context); #endif #endif }