diff --git a/src/PlatformBackends/KWinWaylandImageGrabber.h b/src/PlatformBackends/KWinWaylandImageGrabber.h --- a/src/PlatformBackends/KWinWaylandImageGrabber.h +++ b/src/PlatformBackends/KWinWaylandImageGrabber.h @@ -30,7 +30,7 @@ explicit KWinWaylandImageGrabber(QObject * parent = nullptr); ~KWinWaylandImageGrabber() Q_DECL_OVERRIDE; - QVector supportedModes() const override { return {FullScreen, CurrentScreen, /*ActiveWindow, */WindowUnderCursor, TransientWithParent/*, RectangularRegion*/}; } + QVector supportedModes() const override { return {FullScreen, CurrentScreen, /*ActiveWindow, */WindowUnderCursor, TransientWithParent, RectangularRegion}; } bool onClickGrabSupported() const Q_DECL_OVERRIDE; protected: @@ -42,19 +42,24 @@ void grabWindowUnderCursor() Q_DECL_OVERRIDE; void grabTransientWithParent() Q_DECL_OVERRIDE; QPixmap blendCursorImage(const QPixmap &pixmap, int x, int y, int width, int height) Q_DECL_OVERRIDE; + + private Q_SLOTS: + + void rectangleSelectionConfirmed(const QPixmap &pixmap); + void rectangleSelectionCancelled(); private: - void startReadImage(int readPipe); + void startReadImage(int readPipe, std::function const& cb); enum class Mode { Window, CurrentScreen, FullScreen }; template void callDBus(Mode mode, int writeFd, T argument); template - void grab(Mode mode, T argument); + void grab(Mode mode, std::function const& cb, T argument); }; #endif diff --git a/src/PlatformBackends/KWinWaylandImageGrabber.cpp b/src/PlatformBackends/KWinWaylandImageGrabber.cpp --- a/src/PlatformBackends/KWinWaylandImageGrabber.cpp +++ b/src/PlatformBackends/KWinWaylandImageGrabber.cpp @@ -78,24 +78,55 @@ void KWinWaylandImageGrabber::grabFullScreen() { - grab(Mode::FullScreen, mCapturePointer); + grab(Mode::FullScreen, [this](QPixmap pixmap) { + emit pixmapChanged(pixmap); + }, mCapturePointer); } void KWinWaylandImageGrabber::grabCurrentScreen() { - grab(Mode::CurrentScreen, mCapturePointer); + grab(Mode::CurrentScreen, [this](QPixmap pixmap) { + emit pixmapChanged(pixmap); + }, mCapturePointer); } void KWinWaylandImageGrabber::grabActiveWindow() { // unsupported emit pixmapChanged(QPixmap()); } +void KWinWaylandImageGrabber::rectangleSelectionCancelled() +{ + QObject *sender = QObject::sender(); + sender->disconnect(); + sender->deleteLater(); + + emit imageGrabFailed(); +} + +void KWinWaylandImageGrabber::rectangleSelectionConfirmed(const QPixmap &pixmap) +{ + QObject *sender = QObject::sender(); + sender->disconnect(); + sender->deleteLater(); + + mPixmap = pixmap; + emit pixmapChanged(mPixmap); +} + void KWinWaylandImageGrabber::grabRectangularRegion() { - // unsupported - emit pixmapChanged(QPixmap()); + grab(Mode::FullScreen, [this](QPixmap pixmap) { + if (!pixmap.isNull()) { + QuickEditor *editor = new QuickEditor(pixmap, this); + + connect(editor, &QuickEditor::grabDone, this, &KWinWaylandImageGrabber::rectangleSelectionConfirmed); + connect(editor, &QuickEditor::grabCancelled, this, &KWinWaylandImageGrabber::rectangleSelectionCancelled); + } else { + emit pixmapChanged(pixmap); + } + }, mCapturePointer); } void KWinWaylandImageGrabber::grabWindowUnderCursor() @@ -107,7 +138,9 @@ if (mCapturePointer) { mask |= 1 << 1; } - grab(Mode::Window, mask); + grab(Mode::Window, [this](QPixmap pixmap) { + emit pixmapChanged(pixmap); + }, mask); } void KWinWaylandImageGrabber::grabTransientWithParent() @@ -125,14 +158,14 @@ return pixmap; } -void KWinWaylandImageGrabber::startReadImage(int readPipe) +void KWinWaylandImageGrabber::startReadImage(int readPipe, std::function const& cb) { QFutureWatcher *watcher = new QFutureWatcher(this); QObject::connect(watcher, &QFutureWatcher::finished, this, - [watcher, this] { + [watcher, cb] { watcher->deleteLater(); const QImage img = watcher->result(); - emit pixmapChanged(QPixmap::fromImage(img)); + cb(QPixmap::fromImage(img)); } ); watcher->setFuture(QtConcurrent::run(readImage, readPipe)); @@ -153,16 +186,16 @@ } template -void KWinWaylandImageGrabber::grab(Mode mode, T argument) +void KWinWaylandImageGrabber::grab(Mode mode, std::function const& cb, T argument) { int pipeFds[2]; if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) { emit imageGrabFailed(); return; } callDBus(mode, pipeFds[1], argument); - startReadImage(pipeFds[0]); + startReadImage(pipeFds[0], cb); close(pipeFds[1]); }