Skip to content

Commit

Permalink
Map Qt6 device-independent coords before grabbing from physical coords.
Browse files Browse the repository at this point in the history
  • Loading branch information
psieg committed Feb 10, 2024
1 parent e3fdd8a commit e52f5f4
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 5 deletions.
35 changes: 31 additions & 4 deletions Software/grab/GrabberBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include "GrabberBase.hpp"
#include "src/debug.h"
#include <cmath>
#include <QScreen>

#ifdef Q_OS_WIN
#include <windows.h>
#endif

namespace
{
Expand Down Expand Up @@ -89,8 +94,18 @@ bool GrabberBase::isGrabbingStarted() const
return m_timer->isActive();
}

const GrabbedScreen * GrabberBase::screenOfRect(const QRect &rect) const
const GrabbedScreen * GrabberBase::screenOfWidget(const QWidget& widget) const
{
#ifdef Q_OS_WIN
// Note that in Qt > 6 we can't use rect matching because the widget coords are in a device-independent
// coordinate system while the screen coords are in the physical one.
HMONITOR widgetMonitor = MonitorFromWindow(reinterpret_cast<HWND>(widget.winId()), MONITOR_DEFAULTTONULL);
for (int i = 0; i < _screensWithWidgets.size(); ++i) {
if (_screensWithWidgets[i].screenInfo.handle == widgetMonitor)
return &_screensWithWidgets[i];
}
#else
QRect rect = widget.frameGeometry();
QPoint center = rect.center();
for (int i = 0; i < _screensWithWidgets.size(); ++i) {
if (_screensWithWidgets[i].screenInfo.rect.contains(center))
Expand All @@ -99,7 +114,8 @@ const GrabbedScreen * GrabberBase::screenOfRect(const QRect &rect) const
for (int i = 0; i < _screensWithWidgets.size(); ++i) {
if (_screensWithWidgets[i].screenInfo.rect.intersects(rect))
return &_screensWithWidgets[i];
}
};
#endif
return NULL;
}

Expand Down Expand Up @@ -145,10 +161,11 @@ void GrabberBase::grab()
_context->grabResult->append(qRgb(0,0,0));
continue;
}
QRect widgetRect = _context->grabWidgets->at(i)->frameGeometry();
const QWidget* widget = _context->grabWidgets->at(i);
QRect widgetRect = widget->frameGeometry();
getValidRect(widgetRect);

const GrabbedScreen *grabbedScreen = screenOfRect(widgetRect);
const GrabbedScreen *grabbedScreen = screenOfWidget(*widget);
if (grabbedScreen == NULL) {
DEBUG_HIGH_LEVEL << Q_FUNC_INFO << " widget is out of screen " << Debug::toString(widgetRect);
_context->grabResult->append(0);
Expand All @@ -157,6 +174,16 @@ void GrabberBase::grab()
DEBUG_HIGH_LEVEL << Q_FUNC_INFO << Debug::toString(widgetRect);
QRect monitorRect = grabbedScreen->screenInfo.rect;

#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_WIN))
// Qt6 uses device independent coordinates but our captured image is in device coordinates.
// Move the topleft corner from its device-independent position to its pyhsical.
QPoint offset = widget->frameGeometry().topLeft() - widget->screen()->geometry().topLeft();
offset *= widget->screen()->devicePixelRatio();
widgetRect.moveTo(grabbedScreen->screenInfo.rect.topLeft() + offset);
widgetRect.setSize(widgetRect.size() * widget->screen()->devicePixelRatio());
DEBUG_HIGH_LEVEL << Q_FUNC_INFO << "adjusted: " << Debug::toString(widgetRect);
#endif

QRect clippedRect = monitorRect.intersected(widgetRect);

// Checking for the 'grabme' widget position inside the monitor that is used to capture color
Expand Down
2 changes: 1 addition & 1 deletion Software/grab/include/GrabberBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public slots:
*/
virtual QList< ScreenInfo > * screensWithWidgets(QList< ScreenInfo > * result, const QList<GrabWidget *> &grabWidgets) = 0;
virtual bool isReallocationNeeded(const QList< ScreenInfo > &grabScreens) const;
const GrabbedScreen * screenOfRect(const QRect &rect) const;
const GrabbedScreen * screenOfWidget(const QWidget &widget) const;

signals:
void frameGrabAttempted(GrabResult grabResult);
Expand Down

0 comments on commit e52f5f4

Please sign in to comment.