7#include <qpa/qwindowsysteminterface.h>
9#include <qohosdisplayinfo.h>
16#include "render/qohosview.h"
17#include <multimedia/image_framework/image/pixelmap_native.h>
18#include <qarkui/qarkuiutils.h>
19#include <qguiapplication.h>
20#include <qohosapppermissions_p.h>
21#include <qohosjsutils.h>
22#include <qohospixelmapconversions.h>
23#include <qohosutils.h>
24#include <render/qwindowproxyregistry.h>
25#include <window_manager/oh_display_capture.h>
27#include <QtGui/QGuiApplication>
28#include <QtGui/QWindow>
29#include <QtCore/private/qnapi_p.h>
30#include <QtCore/private/qohoslogger_p.h>
31#include <QtGui/private/qhighdpiscaling_p.h>
32#include <QtGui/private/qwindow_p.h>
45 ::OH_PixelmapNative *pixelMapNativePtr;
47 QArkUi::callArkUiOrFailOnErrorResult(
48 Q_OHOS_NAMED_FUNC(::OH_NativeDisplayManager_CaptureScreenPixelmap),
49 static_cast<
std::uint32_t>(displayId.value()), &pixelMapNativePtr);
51 return wrapNativePixelMapPtr(pixelMapNativePtr);
56 QOhosConsumer<std::shared_ptr<::OH_PixelmapNative>> pixelMapOrNullConsumer)
58 static constexpr const char *ohosCustomScreenCapturePermission =
59 "ohos.permission.CUSTOM_SCREEN_CAPTURE";
62 jsState, ohosCustomScreenCapturePermission,
63 [pixelMapOrNullConsumer = std::move(pixelMapOrNullConsumer), displayId](
64 auto &jsState,
bool permissionGranted) {
65 if (permissionGranted) {
66 pixelMapOrNullConsumer(captureScreenPixelmap(jsState, displayId));
69 "%s: %s hasn't been granted by user. Cannot grab window.", Q_FUNC_INFO,
70 ohosCustomScreenCapturePermission);
71 pixelMapOrNullConsumer(
nullptr);
78 auto allWindows =
qApp->allWindows();
79 auto windowItByWId = std::find_if(
80 std::begin(allWindows), std::end(allWindows),
82 return w->winId() == wId;
85 if (windowItByWId == allWindows.end())
88 return *windowItByWId;
92 const QSize &windowSnapshotSize,
const QRect &windowSpaceCaptureRect)
95 windowSpaceCaptureRect.width() < 0
96 ? qMax(0, windowSnapshotSize.width() - windowSpaceCaptureRect.x())
97 : windowSpaceCaptureRect.width(),
98 windowSpaceCaptureRect.height() < 0
99 ? qMax(0, windowSnapshotSize.height() - windowSpaceCaptureRect.y())
100 : windowSpaceCaptureRect.height()
105 const QRect &windowSpaceCaptureRect,
const QRect &windowFragmentRect)
108 qAbs(windowSpaceCaptureRect.x() - windowFragmentRect.x()),
109 qAbs(windowSpaceCaptureRect.y() - windowFragmentRect.y()),
110 windowFragmentRect.width(),
111 windowFragmentRect.height()
117 const QRect &windowSpaceCaptureRect)
119 auto resultSize = calculateResultWindowCapturePixmapSize(
120 QHighDpi::fromNativePixels(capturedWindowPixmap.size(), platformScreen),
121 windowSpaceCaptureRect);
123 if (resultSize.isEmpty())
126 auto windowFragmentRect = capturedWindowPixmap.rect().intersected(
127 QRect(windowSpaceCaptureRect.topLeft(), resultSize));
129 if (windowFragmentRect.isEmpty())
130 return QPixmap(resultSize);
132 auto resultSpaceWindowFragmentRect =
133 calculateResultPixmapWindowFragmentRect(windowSpaceCaptureRect, windowFragmentRect);
135 QPixmap result(resultSize);
138 QHighDpi::toNativePixels(resultSpaceWindowFragmentRect, platformScreen),
139 capturedWindowPixmap,
140 QHighDpi::toNativePixels(windowFragmentRect, platformScreen));
149 switch (jsDisplayOrientation) {
151 return makeQOhosOptional(Qt::ScreenOrientation::PortraitOrientation);
153 return makeQOhosOptional(Qt::ScreenOrientation::LandscapeOrientation);
155 return makeQOhosOptional(Qt::ScreenOrientation::InvertedPortraitOrientation);
157 return makeQOhosOptional(Qt::ScreenOrientation::InvertedLandscapeOrientation);
168 , m_format(QImage::Format_ARGB32_Premultiplied)
170 , m_platformCursor(
new QOhosPlatformCursor())
171 , m_displayInfo(displayInfo)
172 , m_availableGeometry(getAvailableArea())
174 auto __dbg = make_QCScopedDebug(
"QOhosPlatformScreen::QOhosPlatformScreen");
181 auto *platformScreen = screen->handle();
182 if (Q_UNLIKELY(platformScreen ==
nullptr))
183 qOhosReportFatalErrorAndAbort(
"QScreen::handle() returned null");
189 auto windowIds = QOhosWindowProxy::queryWindowIdsByCoordinate(m_displayInfo.id, p);
190 return !windowIds.empty()
197 return m_platformCursor.data();
202 auto geometryChanged = displayInfo.displayGeometryPixels() != m_displayInfo.displayGeometryPixels();
203 auto logicalDpiChanged = displayInfo.densityDPI != m_displayInfo.densityDPI;
205 QVector<QPair<QWindow *, QOhosOptional<QRect>>> windowRectPairs;
207 if (logicalDpiChanged) {
208 for (
auto *window :
qGuiApp->allWindows()) {
209 auto *platformWindow = QOhosPlatformWindow::fromQWindowOrNull(window);
210 if (platformWindow ==
nullptr || platformWindow->screen() !=
this || !window->isVisible())
213 auto *ownedView = platformWindow->ownedViewOrNull();
214 if (ownedView ==
nullptr)
217 windowRectPairs.push_back({
219 ownedView->viewType() == QOhosView::ViewType::EmbeddedWindow
220 ? makeQOhosOptional(window->geometry())
221 : makeEmptyQOhosOptional()});
225 m_displayInfo = displayInfo;
228 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
230 if (logicalDpiChanged) {
231 auto ldpi = logicalDpi();
232 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(
233 screen(), ldpi.first, ldpi.second);
235 QWindowSystemInterface::flushWindowSystemEvents();
237 for (
const auto &windowRectPair : windowRectPairs) {
238 auto *qWindow = windowRectPair.first;
239 auto *platformWindow = QOhosPlatformWindow::fromQWindow(qWindow);
240 if (windowRectPair.second.hasValue())
241 qWindow->setGeometry(windowRectPair.second.value());
242 platformWindow->handleDpiChange();
249 qreal lDpi = m_displayInfo.densityPixels * ohosLogicalDpi;
250 return QDpi(lDpi, lDpi);
257 return m_displayInfo.densityPixels;
268 m_displayInfo.orientation
269 .andThen(tryMapJsDisplayOrientationToQt)
270 .valueOr(Qt::ScreenOrientation::PrimaryOrientation);
275 return Qt::ScreenOrientation::PrimaryOrientation;
280 return QtOhos::evalInJsThreadWithConsumer<QRect>(
281 [&](QtOhos::JsState &jsState, QOhosConsumer<QRect> resultConsumer) {
283 QNapi::Object display;
285 display = jsState.eval<QNapi::Object>(
286 "@ohos.display.getDisplayByIdSync(*)", {m_displayInfo.id.value()});
287 }
catch (
const Napi::Error &error) {
289 "%s: getDisplayByIdSync(%f) failed with error: %s",
290 Q_FUNC_INFO, m_displayInfo.id.value(), error.Message().c_str());
291 resultConsumer(QRect());
295 display.call<QNapi::Promise>(
"getAvailableArea")
296 .withContext(std::move(resultConsumer))
298 [](
const QtOhos::CallbackInfo &cbInfo, QOhosConsumer<QRect> &resultConsumer) {
299 auto availableArea = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
302 availableArea.get<QNapi::Number>(
"left"),
303 availableArea.get<QNapi::Number>(
"top"),
304 availableArea.get<QNapi::Number>(
"width"),
305 availableArea.get<QNapi::Number>(
"height")));
308 [](
const QtOhos::CallbackInfo &cbInfo, QOhosConsumer<QRect> &resultConsumer) {
309 QtOhos::logJsCallbackError(cbInfo,
"Error occurred in JS getAvailableArea()");
310 resultConsumer(QRect());
321 return m_displayInfo;
326 return m_displayInfo.displayGeometryPixels();
331 return !m_availableGeometry.isEmpty() ? m_availableGeometry : geometry();
346 return m_displayInfo.physicalSize();
351 if (rect != m_availableGeometry) {
352 m_availableGeometry = rect;
353 QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
359 auto captureRect = QRect(x, y, width, height);
362 auto *window = tryFindWindowByWIdOrNull(wId);
363 if (window ==
nullptr) {
365 "%s: Cannot find window with the given WId: %lld.", Q_FUNC_INFO, wId);
368 return grabWindowFromCapturedScreenPixmap(
369 this, QOhosPlatformWindow::fromQWindow(window)->makeSnapshot(), captureRect);
372 auto capturedScreenPixmap = QtOhos::evalInJsThreadWithConsumer<QPixmap>(
373 [displayId = m_displayInfo.id](
374 QtOhos::JsState &jsState, QOhosConsumer<QPixmap> resultConsumer) {
375 tryCaptureScreenPixelmapWithPermissionCheck(
377 [resultConsumer = std::move(resultConsumer)](
378 std::shared_ptr<::OH_PixelmapNative> optPixelMap) {
381 ? QPixmap::fromImage(createQImageFromNativePixelMap(optPixelMap.get()))
386 return capturedScreenPixmap.copy(captureRect);
391 return m_displayInfo.name;
static QWindowProxyRegistry & instance()
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)
void tryCaptureScreenPixelmapWithPermissionCheck(QtOhos::JsState &jsState, QOhosDisplayInfo::JsDisplayId displayId, QOhosConsumer< std::shared_ptr<::OH_PixelmapNative > > pixelMapOrNullConsumer)
static const int ohosLogicalDpi
QOhosOptional< Qt::ScreenOrientation > tryMapJsDisplayOrientationToQt(QOhosDisplayInfo::JsDisplayOrientation jsDisplayOrientation)
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)