summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2016-10-13 17:47:08 (GMT)
committerPeter Wu <peter@lekensteyn.nl>2016-10-20 20:39:21 (GMT)
commita41e83edbaadd27cd8ea85d4dfa375033e8ade84 (patch)
tree4e37a33a4e2bf47e2b6230947c60e56855aa4a7a
parent1e58394832576d259e02c2a80479343965cd1e47 (diff)
Fix blurry preview on HiDPI displays
THe captured pixmap should always have devicePixelRatio one, it only needs to be changed when it is actually drawn in the preview widget. Also fixes a regression from e4c2e564a5b91497132d9a20d8f521af405286bd ("Replace KScreen by QScreen for current window grab"), now the current screen grab mode will again capture the full screen on HiDPI screens. Tested with: QT_SCALE_FACTOR=2 src/spectacle REVIEW: 129189
-rw-r--r--src/Gui/KSImageWidget.cpp5
-rw-r--r--src/PlatformBackends/X11ImageGrabber.cpp37
-rw-r--r--src/PlatformBackends/X11ImageGrabber.h1
3 files changed, 28 insertions, 15 deletions
diff --git a/src/Gui/KSImageWidget.cpp b/src/Gui/KSImageWidget.cpp
index 365a5f3..a2fa53b 100644
--- a/src/Gui/KSImageWidget.cpp
+++ b/src/Gui/KSImageWidget.cpp
@@ -43,7 +43,10 @@ void KSImageWidget::setScreenshot(const QPixmap &pixmap)
void KSImageWidget::setScaledPixmap()
{
- setPixmap(mPixmap.scaled(size() * mPixmap.devicePixelRatio(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
+ const qreal scale = qApp->devicePixelRatio();
+ QPixmap scaledPixmap = mPixmap.scaled(size() * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ scaledPixmap.setDevicePixelRatio(scale);
+ setPixmap(scaledPixmap);
}
// drag handlers
diff --git a/src/PlatformBackends/X11ImageGrabber.cpp b/src/PlatformBackends/X11ImageGrabber.cpp
index 6dc3ffd..68067c4 100644
--- a/src/PlatformBackends/X11ImageGrabber.cpp
+++ b/src/PlatformBackends/X11ImageGrabber.cpp
@@ -220,17 +220,13 @@ QPixmap X11ImageGrabber::convertFromNative(xcb_image_t *xcbImage)
// utility functions
+// Note: x, y, width and height are measured in device pixels
QPixmap X11ImageGrabber::blendCursorImage(const QPixmap &pixmap, int x, int y, int width, int height)
{
- // first we get the cursor position, compute the co-ordinates of the region
- // of the screen we're grabbing, and see if the cursor is actually visible in
- // the region
+ // If the cursor position lies outside the area, do not bother drawing a cursor.
- const qreal dpr = pixmap.devicePixelRatio();
-
- // cursor position operates on application's device pixel ratio, not the pixmap!
- QPoint cursorPos = QCursor::pos() / dpr * qApp->devicePixelRatio();
- QRect screenRect(x / dpr, y / dpr, width / dpr, height / dpr);
+ QPoint cursorPos = getNativeCursorPosition();
+ QRect screenRect(x, y, width, height);
if (!screenRect.contains(cursorPos)) {
return pixmap;
@@ -254,15 +250,14 @@ QPixmap X11ImageGrabber::blendCursorImage(const QPixmap &pixmap, int x, int y, i
// process the image into a QImage
QImage cursorImage = QImage((quint8 *)pixelData, cursorReply->width, cursorReply->height, QImage::Format_ARGB32_Premultiplied);
- cursorImage.setDevicePixelRatio(dpr);
// a small fix for the cursor position for fancier cursors
- cursorPos -= QPoint(cursorReply->xhot, cursorReply->yhot) / dpr;
+ cursorPos -= QPoint(cursorReply->xhot, cursorReply->yhot);
// now we translate the cursor point to our screen rectangle
- cursorPos -= QPoint(x, y) / dpr;
+ cursorPos -= QPoint(x, y);
// and do the painting
@@ -434,7 +429,6 @@ void X11ImageGrabber::grabTransientWithParent()
// now that we know we have a transient window, let's
// find other possible transient windows and the app window itself.
-
QRegion clipRegion;
QSet<xcb_window_t> transients;
@@ -613,12 +607,14 @@ void X11ImageGrabber::grabCurrentScreen()
{
QPoint cursorPosition = QCursor::pos();
for (auto screen : QGuiApplication::screens()) {
- const QRect screenRect = screen->geometry();
+ QRect screenRect = screen->geometry();
if (!screenRect.contains(cursorPosition)) {
continue;
}
- mPixmap = getToplevelPixmap(screenRect, mCapturePointer);
+ // The screen origin is in native pixels, but the size is device-dependent. Convert these also to native pixels.
+ QRect nativeScreenRect(screenRect.topLeft(), screenRect.size() * screen->devicePixelRatio());
+ mPixmap = getToplevelPixmap(nativeScreenRect, mCapturePointer);
emit pixmapChanged(mPixmap);
return;
}
@@ -701,3 +697,16 @@ xcb_window_t X11ImageGrabber::getTransientWindowParent(xcb_window_t winId, QRect
}
return winInfo.transientFor();
}
+
+QPoint X11ImageGrabber::getNativeCursorPosition()
+{
+ // QCursor::pos() is not used because it requires additional calculations.
+ // Its value is the offset to the origin of the current screen is in
+ // device-independent pixels while the origin itself uses native pixels.
+
+ xcb_connection_t *xcbConn = QX11Info::connection();
+ xcb_query_pointer_cookie_t pointerCookie = xcb_query_pointer_unchecked(xcbConn, QX11Info::appRootWindow());
+ CScopedPointer<xcb_query_pointer_reply_t> pointerReply(xcb_query_pointer_reply(xcbConn, pointerCookie, NULL));
+
+ return QPoint(pointerReply->root_x, pointerReply->root_y);
+}
diff --git a/src/PlatformBackends/X11ImageGrabber.h b/src/PlatformBackends/X11ImageGrabber.h
index 56381e8..9411ba5 100644
--- a/src/PlatformBackends/X11ImageGrabber.h
+++ b/src/PlatformBackends/X11ImageGrabber.h
@@ -84,6 +84,7 @@ class X11ImageGrabber : public ImageGrabber
QPixmap getWindowPixmap(xcb_window_t window, bool blendPointer);
QPixmap convertFromNative(xcb_image_t *xcbImage);
xcb_window_t getTransientWindowParent(xcb_window_t winId, QRect &outRect);
+ QPoint getNativeCursorPosition();
OnClickEventFilter *mNativeEventFilter;
};