4#include <QtCore/qdebug.h>
5#include <QtCore/qdatetime.h>
7#include <qpa/qwindowsysteminterface.h>
9#include <qohosdisplayinfo.h>
16#include "render/qohosview.h"
18#include <multimedia/image_framework/image/pixelmap_native.h>
20#include <qarkui/qarkuiutils.h>
21#include <qohosapppermissions_p.h>
22#include <qohosjsutils.h>
23#include <QtGui/private/qohosimageconversions_p.h>
24#include <qohospixelmapconversions.h>
25#include <qohosutils.h>
26#include <render/qwindowproxyregistry.h>
27#include <window_manager/oh_display_capture.h>
29#include <QtGui/qguiapplication.h>
30#include <QtGui/qwindow.h>
31#include <QtCore/private/qnapi_p.h>
32#include <QtCore/private/qohoslogger_p.h>
33#include <QtGui/private/qhighdpiscaling_p.h>
34#include <QtGui/private/qwindow_p.h>
47 ::OH_PixelmapNative *pixelMapNativePtr;
49 QArkUi::callArkUiOrFailOnErrorResult(
50 Q_OHOS_NAMED_FUNC(::OH_NativeDisplayManager_CaptureScreenPixelmap),
51 static_cast<
std::uint32_t>(displayId.value()), &pixelMapNativePtr);
53 return wrapOhosNativePixelMapPtr(pixelMapNativePtr);
58 QOhosConsumer<std::shared_ptr<::OH_PixelmapNative>> pixelMapOrNullConsumer)
60 static constexpr const char *ohosCustomScreenCapturePermission =
61 "ohos.permission.CUSTOM_SCREEN_CAPTURE";
64 jsState, ohosCustomScreenCapturePermission,
65 [pixelMapOrNullConsumer = std::move(pixelMapOrNullConsumer), displayId](
66 auto &jsState,
bool permissionGranted) {
67 if (permissionGranted) {
68 pixelMapOrNullConsumer(captureScreenPixelmap(jsState, displayId));
71 "%s: %s hasn't been granted by user. Cannot grab window.", Q_FUNC_INFO,
72 ohosCustomScreenCapturePermission);
73 pixelMapOrNullConsumer(
nullptr);
80 auto allWindows = qApp->allWindows();
81 auto windowItByWId =
std::find_if(
82 std::begin(allWindows),
std::end(allWindows),
84 return w->winId() == wId;
87 if (windowItByWId == allWindows.end())
90 return *windowItByWId;
94 const QSize &windowSnapshotSize,
const QRect &windowSpaceCaptureRect)
97 windowSpaceCaptureRect.width() < 0
98 ? qMax(0, windowSnapshotSize.width() - windowSpaceCaptureRect.x())
99 : windowSpaceCaptureRect.width(),
100 windowSpaceCaptureRect.height() < 0
101 ? qMax(0, windowSnapshotSize.height() - windowSpaceCaptureRect.y())
102 : windowSpaceCaptureRect.height()
107 const QRect &windowSpaceCaptureRect,
const QRect &windowFragmentRect)
110 qAbs(windowSpaceCaptureRect.x() - windowFragmentRect.x()),
111 qAbs(windowSpaceCaptureRect.y() - windowFragmentRect.y()),
112 windowFragmentRect.width(),
113 windowFragmentRect.height()
119 const QRect &windowSpaceCaptureRect)
121 auto resultSize = calculateResultWindowCapturePixmapSize(
122 QHighDpi::fromNativePixels(capturedWindowPixmap.size(), platformScreen),
123 windowSpaceCaptureRect);
125 if (resultSize.isEmpty())
128 auto windowFragmentRect = capturedWindowPixmap.rect().intersected(
129 QRect(windowSpaceCaptureRect.topLeft(), resultSize));
131 if (windowFragmentRect.isEmpty())
132 return QPixmap(resultSize);
134 auto resultSpaceWindowFragmentRect =
135 calculateResultPixmapWindowFragmentRect(windowSpaceCaptureRect, windowFragmentRect);
137 QPixmap result(resultSize);
140 QHighDpi::toNativePixels(resultSpaceWindowFragmentRect, platformScreen),
141 capturedWindowPixmap,
142 QHighDpi::toNativePixels(windowFragmentRect, platformScreen));
151 switch (jsDisplayOrientation) {
152 case JsDisplayOrientation::PORTRAIT:
153 return Qt::ScreenOrientation::PortraitOrientation;
154 case JsDisplayOrientation::LANDSCAPE:
155 return Qt::ScreenOrientation::LandscapeOrientation;
156 case JsDisplayOrientation::PORTRAIT_INVERTED:
157 return Qt::ScreenOrientation::InvertedPortraitOrientation;
158 case JsDisplayOrientation::LANDSCAPE_INVERTED:
159 return Qt::ScreenOrientation::InvertedLandscapeOrientation;
170 , m_format(QImage::Format_ARGB32_Premultiplied)
172 , m_platformCursor(
new QOhosPlatformCursor())
173 , m_displayInfo(displayInfo)
174 , m_availableGeometry(getAvailableArea())
175 , m_platformScreenListSupplier(std::move(platformScreenListSupplier))
177 auto __dbg = make_QCScopedDebug(
"QOhosPlatformScreen::QOhosPlatformScreen");
184 auto *platformScreen = screen->handle();
185 if (Q_UNLIKELY(platformScreen ==
nullptr))
186 qOhosReportFatalErrorAndAbort(
"QScreen::handle() returned null");
192 for (
auto *platformScreen : virtualSiblings()) {
193 auto *ohosPlatformScreen =
static_cast<QOhosPlatformScreen *>(platformScreen);
195 auto windowIds = QOhosWindowProxy::queryWindowIdsByCoordinate(ohosPlatformScreen->m_displayInfo.id, p);
196 if (!windowIds.empty())
197 return QWindowProxyRegistry::instance().findQWindowByJsWindowIdOrNull(windowIds.front());
205 return m_platformCursor.data();
210 auto geometryChanged = displayInfo.displayGeometryPixels() != m_displayInfo.displayGeometryPixels();
211 auto logicalDpiChanged = displayInfo.densityDPI != m_displayInfo.densityDPI;
213 QVector<QPair<QWindow *, std::optional<QRect>>> windowRectPairs;
215 if (logicalDpiChanged) {
216 for (
auto *window : qGuiApp->allWindows()) {
217 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
218 if (platformWindow ==
nullptr || platformWindow->screen() !=
this || !window->isVisible())
221 auto *ownedView = platformWindow->ownedViewOrNull();
222 if (ownedView ==
nullptr)
225 windowRectPairs.push_back({
227 ownedView->viewType() == QOhosView::ViewType::EmbeddedWindow
228 ? std::optional(window->geometry())
233 m_displayInfo = displayInfo;
236 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
238 if (logicalDpiChanged) {
239 auto ldpi = logicalDpi();
240 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(
241 screen(), ldpi.first, ldpi.second);
243 QWindowSystemInterface::flushWindowSystemEvents();
245 for (
const auto &windowRectPair : windowRectPairs) {
246 auto *qWindow = windowRectPair.first;
247 auto *platformWindow = QOhosPlatformWindow::fromQWindow(qWindow);
248 if (windowRectPair.second.has_value())
249 qWindow->setGeometry(windowRectPair.second.value());
250 platformWindow->handleDpiChange();
257 qreal lDpi = m_displayInfo.densityPixels * ohosLogicalDpi;
258 return QDpi(lDpi, lDpi);
265 return m_displayInfo.densityPixels;
270 return m_displayInfo.refreshRate;
281 qAndThen(m_displayInfo.orientation, tryMapJsDisplayOrientationToQt)
282 .value_or(Qt::ScreenOrientation::PrimaryOrientation);
287 return Qt::ScreenOrientation::PrimaryOrientation;
292 return QtOhos::evalInJsThreadWithPromise<QRect>(
293 [&](QtOhos::JsState &jsState, QOhosTaskPromise<QRect> evalPromise) {
295 QNapi::Object display;
297 display = jsState.eval<QNapi::Object>(
298 "@ohos.display.getDisplayByIdSync(*)", {m_displayInfo.id.value()});
299 }
catch (
const Napi::Error &error) {
301 "%s: getDisplayByIdSync(%f) failed with error: %s",
302 Q_FUNC_INFO, m_displayInfo.id.value(), error.Message().c_str());
303 evalPromise(QRect());
307 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
308 display.evalToPromiseOrRejectOnThrow(
"getAvailableArea()")
310 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo) {
311 auto availableArea = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
314 availableArea.get<QNapi::Number>(
"left"),
315 availableArea.get<QNapi::Number>(
"top"),
316 availableArea.get<QNapi::Number>(
"width"),
317 availableArea.get<QNapi::Number>(
"height")));
320 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
321 QtOhos::logJsCallbackError(cbInfo,
"Error occurred in JS getAvailableArea()");
322 catchPromise(QRect());
334 return m_displayInfo;
339 return m_displayInfo.id.value();
344 return m_displayInfo.displayGeometryPixels();
349 auto screenGeometry = geometry();
350 return !m_availableGeometry.isEmpty()
351 ? m_availableGeometry.translated(screenGeometry.topLeft())
367 return m_displayInfo.physicalSize();
372 if (rect != m_availableGeometry) {
373 m_availableGeometry = rect;
374 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
380 if (!m_displayInfo.isDisplayMainOrExtended())
381 return QPlatformScreen::virtualSiblings();
383 QList<QPlatformScreen *> result;
384 auto allPlatformScreens = m_platformScreenListSupplier();
386 allPlatformScreens.begin(), allPlatformScreens.end(),
387 std::back_inserter(result),
397 auto captureRect = QRect(x, y, width, height);
400 auto *window = tryFindWindowByWIdOrNull(wId);
401 if (window ==
nullptr) {
403 "%s: Cannot find window with the given WId: %lld.", Q_FUNC_INFO, wId);
406 return grabWindowFromCapturedScreenPixmap(
407 this, QOhosPlatformWindow::fromQWindow(window)->makeSnapshot(), captureRect);
410 auto capturedScreenPixmap = QtOhos::evalInJsThreadWithPromise<QPixmap>(
411 [displayId = m_displayInfo.id](
412 QtOhos::JsState &jsState, QOhosTaskPromise<QPixmap> evalPromise) {
413 auto sharedEvalPromise = QtOhos::moveToSharedPtr(std::move(evalPromise).makeChained(Q_FUNC_INFO));
414 tryCaptureScreenPixelmapWithPermissionCheck(
417 std::shared_ptr<::OH_PixelmapNative> optPixelMap) {
418 (*sharedEvalPromise)(
420 ? QPixmap::fromImage(createQImageFromNativePixelMap(optPixelMap.get()))
426 return capturedScreenPixmap.copy(captureRect);
431 return m_displayInfo.name;
void checkAppPermissionGrantedWithConsumer(QtOhos::JsState &jsState, const std::string &permissionName, QOhosConsumer< QtOhos::JsState &, bool > resultConsumer)
Combined button and popup list for selecting options.
QWindow * tryFindWindowByWIdOrNull(WId wId)
QRect calculateResultPixmapWindowFragmentRect(const QRect &windowSpaceCaptureRect, const QRect &windowFragmentRect)
std::optional< Qt::ScreenOrientation > tryMapJsDisplayOrientationToQt(QOhosDisplayInfo::JsDisplayOrientation jsDisplayOrientation)
void tryCaptureScreenPixelmapWithPermissionCheck(QtOhos::JsState &jsState, QOhosDisplayInfo::JsDisplayId displayId, QOhosConsumer< std::shared_ptr<::OH_PixelmapNative > > pixelMapOrNullConsumer)
static const int ohosLogicalDpi
std::shared_ptr<::OH_PixelmapNative > captureScreenPixelmap(QtOhos::JsState &, QOhosDisplayInfo::JsDisplayId displayId)
QSize calculateResultWindowCapturePixmapSize(const QSize &windowSnapshotSize, const QRect &windowSpaceCaptureRect)
QPixmap grabWindowFromCapturedScreenPixmap(const QOhosPlatformScreen *platformScreen, const QPixmap &capturedWindowPixmap, const QRect &windowSpaceCaptureRect)
bool isDisplayMainOrExtended() const
QtOhos::enums::ohos::display::Orientation JsDisplayOrientation