diff --git a/src/core/capturerequest.cpp b/src/core/capturerequest.cpp index 3580ae6a..37813aa1 100644 --- a/src/core/capturerequest.cpp +++ b/src/core/capturerequest.cpp @@ -55,8 +55,8 @@ QByteArray CaptureRequest::serialize() const QDataStream stream(&data, QIODevice::WriteOnly); // Convert enums to integers qint32 tasks = m_tasks, mode = m_mode; - stream << mode << m_delay << tasks << m_data << m_forcedID << m_id - << m_path; + stream << mode << m_delay << tasks << m_data << m_forcedID << m_id << m_path + << m_initialSelection; return data; } @@ -72,6 +72,7 @@ CaptureRequest CaptureRequest::deserialize(const QByteArray& data) stream >> request.m_forcedID; stream >> request.m_id; stream >> request.m_path; + stream >> request.m_initialSelection; // Convert integers to enums request.m_tasks = static_cast(tasks); @@ -104,6 +105,11 @@ CaptureRequest::ExportTask CaptureRequest::tasks() const return m_tasks; } +QRect CaptureRequest::initialSelection() const +{ + return m_initialSelection; +} + void CaptureRequest::addTask(CaptureRequest::ExportTask task) { if (task == SAVE) { @@ -112,6 +118,11 @@ void CaptureRequest::addTask(CaptureRequest::ExportTask task) m_tasks |= task; } +void CaptureRequest::removeTask(CaptureRequest::ExportTask task) +{ + ((int&)m_tasks) &= ~task; +} + void CaptureRequest::addSaveTask(const QString& path) { m_tasks |= SAVE; @@ -124,6 +135,11 @@ void CaptureRequest::addPinTask(const QRect& pinWindowGeometry) m_pinWindowGeometry = pinWindowGeometry; } +void CaptureRequest::setInitialSelection(const QRect& selection) +{ + m_initialSelection = selection; +} + void CaptureRequest::exportCapture(const QPixmap& capture) { if (m_tasks & SAVE) { diff --git a/src/core/capturerequest.h b/src/core/capturerequest.h index ebf4bd15..eda997b6 100644 --- a/src/core/capturerequest.h +++ b/src/core/capturerequest.h @@ -44,10 +44,13 @@ public: QVariant data() const; CaptureMode captureMode() const; ExportTask tasks() const; + QRect initialSelection() const; void addTask(ExportTask task); + void removeTask(ExportTask task); void addSaveTask(const QString& path = QString()); void addPinTask(const QRect& pinWindowGeometry); + void setInitialSelection(const QRect& selection); void exportCapture(const QPixmap& capture); private: @@ -56,7 +59,7 @@ private: QString m_path; ExportTask m_tasks; QVariant m_data; - QRect m_pinWindowGeometry; + QRect m_pinWindowGeometry, m_initialSelection; bool m_forcedID; uint m_id; diff --git a/src/core/controller.cpp b/src/core/controller.cpp index e1e78341..3433ba01 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -328,13 +328,21 @@ void Controller::startScreenGrab(const uint id, const int screenNumber) } QPixmap p(ScreenGrabber().grabScreen(n, ok)); if (ok) { - CaptureRequest& request = *requests().find(id); - QRect geometry = ScreenGrabber().screenGeometry(n); - if (request.tasks() & CaptureRequest::PIN) { - // change geometry for pin task - request.addPinTask(geometry); + CaptureRequest& req = *requests().find(id); + QRect region = req.initialSelection(); + if (region.isNull()) { + region = ScreenGrabber().screenGeometry(n); + } else { + QRect screenGeom = ScreenGrabber().screenGeometry(n); + screenGeom.moveTopLeft({ 0, 0 }); + region = region.intersected(screenGeom); + p = p.copy(region); } - emit captureTaken(id, p, geometry); + if (req.tasks() & CaptureRequest::PIN) { + // change geometry for pin task + req.addPinTask(region); + } + emit captureTaken(id, p, region); } else { emit captureFailed(id); } @@ -556,6 +564,11 @@ void Controller::startFullscreenCapture(const uint id) { bool ok = true; QPixmap p(ScreenGrabber().grabEntireDesktop(ok)); + CaptureRequest req(*requests().find(id)); + QRect region = req.initialSelection(); + if (!region.isNull()) { + p = p.copy(region); + } if (ok) { // selection parameter is unused here emit captureTaken(id, p, {}); diff --git a/src/main.cpp b/src/main.cpp index ba4dd3ae..bd19a93c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include "src/utils/filenamehandler.h" #include "src/utils/pathinfo.h" #include "src/utils/systemnotification.h" +#include "src/utils/valuehandler.h" #include #include #include @@ -160,6 +161,9 @@ int main(int argc, char* argv[]) CommandOption delayOption({ "d", "delay" }, QObject::tr("Delay time in milliseconds"), QStringLiteral("milliseconds")); + CommandOption regionOption("region", + QObject::tr("Screenshot region to select"), + QStringLiteral("WxH+X+Y or string")); CommandOption filenameOption({ "f", "filename" }, QObject::tr("Set the filename pattern"), QStringLiteral("pattern")); @@ -217,10 +221,16 @@ int main(int argc, char* argv[]) QObject::tr("Invalid delay, it must be higher than 0"); const QString numberErr = QObject::tr("Invalid screen number, it must be non negative"); + const QString regionErr = QObject::tr( + "Invalid region, use 'WxH+X+Y' or 'all' or 'screen0/screen1/...'."); auto numericChecker = [](const QString& delayValue) -> bool { int value = delayValue.toInt(); return value >= 0; }; + auto regionChecker = [](const QString& region) -> bool { + Region valueHandler; + return valueHandler.check(region); + }; const QString pathErr = QObject::tr("Invalid path, must be an existing directory or a new file " @@ -246,6 +256,7 @@ int main(int argc, char* argv[]) contrastColorOption.addChecker(colorChecker, colorErr); mainColorOption.addChecker(colorChecker, colorErr); delayOption.addChecker(numericChecker, delayErr); + regionOption.addChecker(regionChecker, regionErr); pathOption.addChecker(pathChecker, pathErr); trayOption.addChecker(booleanChecker, booleanErr); autostartOption.addChecker(booleanChecker, booleanErr); @@ -263,6 +274,7 @@ int main(int argc, char* argv[]) parser.AddOptions({ pathOption, clipboardOption, delayOption, + regionOption, rawImageOption, selectionOption, uploadOption, @@ -273,6 +285,7 @@ int main(int argc, char* argv[]) clipboardOption, pathOption, delayOption, + regionOption, rawImageOption, uploadOption, pinOption }, @@ -280,6 +293,7 @@ int main(int argc, char* argv[]) parser.AddOptions({ pathOption, clipboardOption, delayOption, + regionOption, rawImageOption, uploadOption }, fullArgument); @@ -318,6 +332,7 @@ int main(int argc, char* argv[]) path = QDir(path).absolutePath(); } int delay = parser.value(delayOption).toInt(); + QString region = parser.value(regionOption); bool clipboard = parser.isSet(clipboardOption); bool raw = parser.isSet(rawImageOption); bool printGeometry = parser.isSet(selectionOption); @@ -326,6 +341,9 @@ int main(int argc, char* argv[]) bool acceptOnSelect = parser.isSet(acceptOnSelectOption); DBusUtils dbusUtils; CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path); + if (!region.isEmpty()) { + req.setInitialSelection(Region().value(region).toRect()); + } if (clipboard) { req.addTask(CaptureRequest::COPY); } @@ -379,12 +397,16 @@ int main(int argc, char* argv[]) path = QDir(path).absolutePath(); } int delay = parser.value(delayOption).toInt(); + QString region = parser.value(regionOption); bool clipboard = parser.isSet(clipboardOption); bool raw = parser.isSet(rawImageOption); bool upload = parser.isSet(uploadOption); // Not a valid command CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay); + if (!region.isEmpty()) { + req.setInitialSelection(Region().value(region).toRect()); + } if (clipboard) { req.addTask(CaptureRequest::COPY); } @@ -436,12 +458,23 @@ int main(int argc, char* argv[]) path = QDir(path).absolutePath(); } int delay = parser.value(delayOption).toInt(); + QString region = parser.value(regionOption); bool clipboard = parser.isSet(clipboardOption); bool raw = parser.isSet(rawImageOption); bool pin = parser.isSet(pinOption); bool upload = parser.isSet(uploadOption); CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, number); + if (!region.isEmpty()) { + if (region.startsWith("screen")) { + // TODO use abstract logger + QTextStream(stderr) << "The 'screen' command does not support " + "'--region screen'.\n" + "See flameshot --help.\n"; + exit(1); + } + req.setInitialSelection(Region().value(region).toRect()); + } if (clipboard) { req.addTask(CaptureRequest::COPY); } diff --git a/src/utils/confighandler.cpp b/src/utils/confighandler.cpp index dcfcdcef..09e9d446 100644 --- a/src/utils/confighandler.cpp +++ b/src/utils/confighandler.cpp @@ -75,94 +75,94 @@ bool verifyLaunchFile() static QMap> recognizedGeneralOptions = { // KEY TYPE DEFAULT_VALUE - OPTION("showHelp" ,Bool ( true )), - OPTION("showSidePanelButton" ,Bool ( true )), - OPTION("showDesktopNotification" ,Bool ( true )), - OPTION("disabledTrayIcon" ,Bool ( false )), - OPTION("historyConfirmationToDelete" ,Bool ( true )), - OPTION("checkForUpdates" ,Bool ( true )), + OPTION("showHelp" ,Bool ( true )), + OPTION("showSidePanelButton" ,Bool ( true )), + OPTION("showDesktopNotification" ,Bool ( true )), + OPTION("disabledTrayIcon" ,Bool ( false )), + OPTION("historyConfirmationToDelete" ,Bool ( true )), + OPTION("checkForUpdates" ,Bool ( true )), #if defined(Q_OS_MACOS) - OPTION("startupLaunch" ,Bool ( false )), + OPTION("startupLaunch" ,Bool ( false )), #else - OPTION("startupLaunch" ,Bool ( true )), + OPTION("startupLaunch" ,Bool ( true )), #endif - OPTION("showStartupLaunchMessage" ,Bool ( true )), - OPTION("copyAndCloseAfterUpload" ,Bool ( true )), - OPTION("copyPathAfterSave" ,Bool ( false )), - OPTION("antialiasingPinZoom" ,Bool ( true )), + OPTION("showStartupLaunchMessage" ,Bool ( true )), + OPTION("copyAndCloseAfterUpload" ,Bool ( true )), + OPTION("copyPathAfterSave" ,Bool ( false )), + OPTION("antialiasingPinZoom" ,Bool ( true )), #if !defined(Q_OS_MACOS) - OPTION("useJpgForClipboard" ,Bool ( false )), + OPTION("useJpgForClipboard" ,Bool ( false )), #endif - OPTION("uploadWithoutConfirmation" ,Bool ( false )), - OPTION("saveAfterCopy" ,Bool ( false )), - OPTION("savePath" ,ExistingDir ( )), - OPTION("savePathFixed" ,Bool ( false )), - OPTION("setSaveAsFileExtension" ,SaveFileExtension ( )), - OPTION("uploadHistoryMax" ,LowerBoundedInt(0 , 25 )), - OPTION("undoLimit" ,BoundedInt(0, 999 , 100 )), - // Interface tab - OPTION("uiColor" ,Color ( {116, 0, 150} )), - OPTION("contrastUiColor" ,Color ( {39, 0, 50} )), - OPTION("contrastOpacity" ,BoundedInt(0, 255 , 190 )), - OPTION("buttons" ,ButtonList ( {} )), - // Filename Editor tab - OPTION("filenamePattern" ,FilenamePattern ( {} )), - // Others - OPTION("drawThickness" ,LowerBoundedInt(1 , 3 )), - OPTION("drawFontSize" ,LowerBoundedInt(1 , 8 )), - OPTION("drawColor" ,Color ( Qt::red )), - OPTION("userColors" ,UserColors ( )), - OPTION("ignoreUpdateToVersion" ,String ( "" )), - OPTION("keepOpenAppLauncher" ,Bool ( false )), - OPTION("fontFamily" ,String ( "" )), - // NOTE: If another tool size is added besides drawThickness and - // drawFontSize, remember to update ConfigHandler::toolSize + OPTION("uploadWithoutConfirmation" ,Bool ( false )), + OPTION("saveAfterCopy" ,Bool ( false )), + OPTION("savePath" ,ExistingDir ( )), + OPTION("savePathFixed" ,Bool ( false )), + OPTION("setSaveAsFileExtension" ,SaveFileExtension ( )), + OPTION("uploadHistoryMax" ,LowerBoundedInt(0 , 25 )), + OPTION("undoLimit" ,BoundedInt(0, 999 , 100 )), + // Interface tab + OPTION("uiColor" ,Color ( {116, 0, 150} )), + OPTION("contrastUiColor" ,Color ( {39, 0, 50} )), + OPTION("contrastOpacity" ,BoundedInt(0, 255 , 190 )), + OPTION("buttons" ,ButtonList ( {} )), + // Filename Editor tab + OPTION("filenamePattern" ,FilenamePattern ( {} )), + // Others + OPTION("drawThickness" ,LowerBoundedInt(1 , 3 )), + OPTION("drawFontSize" ,LowerBoundedInt(1 , 8 )), + OPTION("drawColor" ,Color ( Qt::red )), + OPTION("userColors" ,UserColors ( )), + OPTION("ignoreUpdateToVersion" ,String ( "" )), + OPTION("keepOpenAppLauncher" ,Bool ( false )), + OPTION("fontFamily" ,String ( "" )), + // NOTE: If another tool size is added besides drawThickness and + // drawFontSize, remember to update ConfigHandler::toolSize }; static QMap> recognizedShortcuts = { // NAME DEFAULT_SHORTCUT - SHORTCUT("TYPE_PENCIL" , "P" ), - SHORTCUT("TYPE_DRAWER" , "D" ), - SHORTCUT("TYPE_ARROW" , "A" ), - SHORTCUT("TYPE_SELECTION" , "S" ), - SHORTCUT("TYPE_RECTANGLE" , "R" ), - SHORTCUT("TYPE_CIRCLE" , "C" ), - SHORTCUT("TYPE_MARKER" , "M" ), - SHORTCUT("TYPE_MOVESELECTION" , "Ctrl+M" ), - SHORTCUT("TYPE_UNDO" , "Ctrl+Z" ), - SHORTCUT("TYPE_COPY" , "Ctrl+C" ), - SHORTCUT("TYPE_SAVE" , "Ctrl+S" ), - SHORTCUT("TYPE_ACCEPT" , "Return" ), - SHORTCUT("TYPE_EXIT" , "Ctrl+Q" ), - SHORTCUT("TYPE_IMAGEUPLOADER" , ), + SHORTCUT("TYPE_PENCIL" , "P" ), + SHORTCUT("TYPE_DRAWER" , "D" ), + SHORTCUT("TYPE_ARROW" , "A" ), + SHORTCUT("TYPE_SELECTION" , "S" ), + SHORTCUT("TYPE_RECTANGLE" , "R" ), + SHORTCUT("TYPE_CIRCLE" , "C" ), + SHORTCUT("TYPE_MARKER" , "M" ), + SHORTCUT("TYPE_MOVESELECTION" , "Ctrl+M" ), + SHORTCUT("TYPE_UNDO" , "Ctrl+Z" ), + SHORTCUT("TYPE_COPY" , "Ctrl+C" ), + SHORTCUT("TYPE_SAVE" , "Ctrl+S" ), + SHORTCUT("TYPE_ACCEPT" , "Return" ), + SHORTCUT("TYPE_EXIT" , "Ctrl+Q" ), + SHORTCUT("TYPE_IMAGEUPLOADER" , ), #if !defined(Q_OS_MACOS) - SHORTCUT("TYPE_OPEN_APP" , "Ctrl+O" ), + SHORTCUT("TYPE_OPEN_APP" , "Ctrl+O" ), #endif - SHORTCUT("TYPE_PIXELATE" , "B" ), - SHORTCUT("TYPE_INVERT" , "I" ), - SHORTCUT("TYPE_REDO" , "Ctrl+Shift+Z" ), - SHORTCUT("TYPE_TEXT" , "T" ), - SHORTCUT("TYPE_TOGGLE_PANEL" , "Space" ), - SHORTCUT("TYPE_RESIZE_LEFT" , "Shift+Left" ), - SHORTCUT("TYPE_RESIZE_RIGHT" , "Shift+Right" ), - SHORTCUT("TYPE_RESIZE_UP" , "Shift+Up" ), - SHORTCUT("TYPE_RESIZE_DOWN" , "Shift+Down" ), - SHORTCUT("TYPE_SELECT_ALL" , "Ctrl+A" ), - SHORTCUT("TYPE_MOVE_LEFT" , "Left" ), - SHORTCUT("TYPE_MOVE_RIGHT" , "Right" ), - SHORTCUT("TYPE_MOVE_UP" , "Up" ), - SHORTCUT("TYPE_MOVE_DOWN" , "Down" ), - SHORTCUT("TYPE_COMMIT_CURRENT_TOOL" , "Ctrl+Return" ), + SHORTCUT("TYPE_PIXELATE" , "B" ), + SHORTCUT("TYPE_INVERT" , "I" ), + SHORTCUT("TYPE_REDO" , "Ctrl+Shift+Z" ), + SHORTCUT("TYPE_TEXT" , "T" ), + SHORTCUT("TYPE_TOGGLE_PANEL" , "Space" ), + SHORTCUT("TYPE_RESIZE_LEFT" , "Shift+Left" ), + SHORTCUT("TYPE_RESIZE_RIGHT" , "Shift+Right" ), + SHORTCUT("TYPE_RESIZE_UP" , "Shift+Up" ), + SHORTCUT("TYPE_RESIZE_DOWN" , "Shift+Down" ), + SHORTCUT("TYPE_SELECT_ALL" , "Ctrl+A" ), + SHORTCUT("TYPE_MOVE_LEFT" , "Left" ), + SHORTCUT("TYPE_MOVE_RIGHT" , "Right" ), + SHORTCUT("TYPE_MOVE_UP" , "Up" ), + SHORTCUT("TYPE_MOVE_DOWN" , "Down" ), + SHORTCUT("TYPE_COMMIT_CURRENT_TOOL" , "Ctrl+Return" ), #if defined(Q_OS_MACOS) - SHORTCUT("TYPE_DELETE_CURRENT_TOOL" , "Backspace" ), + SHORTCUT("TYPE_DELETE_CURRENT_TOOL" , "Backspace" ), #else - SHORTCUT("TYPE_DELETE_CURRENT_TOOL" , "Delete" ), + SHORTCUT("TYPE_DELETE_CURRENT_TOOL" , "Delete" ), #endif - SHORTCUT("TYPE_PIN" , ), - SHORTCUT("TYPE_SELECTIONINDICATOR" , ), - SHORTCUT("TYPE_SIZEINCREASE" , ), - SHORTCUT("TYPE_SIZEDECREASE" , ), - SHORTCUT("TYPE_CIRCLECOUNT" , ), + SHORTCUT("TYPE_PIN" , ), + SHORTCUT("TYPE_SELECTIONINDICATOR" , ), + SHORTCUT("TYPE_SIZEINCREASE" , ), + SHORTCUT("TYPE_SIZEDECREASE" , ), + SHORTCUT("TYPE_CIRCLECOUNT" , ), }; // clang-format on diff --git a/src/utils/dbusutils.cpp b/src/utils/dbusutils.cpp index ec2e32f0..1a19977c 100644 --- a/src/utils/dbusutils.cpp +++ b/src/utils/dbusutils.cpp @@ -85,8 +85,9 @@ void DBusUtils::selectionTaken(uint id, QByteArray rawImage, QRect selection) file.open(stdout, QIODevice::WriteOnly); QTextStream out(&file); - out << selection.width() << " " << selection.height() << " " - << selection.x() << " " << selection.y() << "\n"; + // TODO also make this change in D-Bus refactor branch + out << selection.width() << "x" << selection.height() << "+" + << selection.x() << "+" << selection.y() << "\n"; file.close(); qApp->exit(); } diff --git a/src/utils/screengrabber.cpp b/src/utils/screengrabber.cpp index 748fd9b1..eb7aab5e 100644 --- a/src/utils/screengrabber.cpp +++ b/src/utils/screengrabber.cpp @@ -130,14 +130,7 @@ QPixmap ScreenGrabber::grabEntireDesktop(bool& ok) } #endif #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) || defined(Q_OS_WIN) - QRect geometry; - for (QScreen* const screen : QGuiApplication::screens()) { - QRect scrRect = screen->geometry(); - scrRect.moveTo(scrRect.x() / screen->devicePixelRatio(), - scrRect.y() / screen->devicePixelRatio()); - geometry = geometry.united(scrRect); - } - + QRect geometry = desktopGeometry(); QPixmap p(QApplication::primaryScreen()->grabWindow( QApplication::desktop()->winId(), geometry.x(), @@ -197,3 +190,16 @@ QPixmap ScreenGrabber::grabScreen(int screenNumber, bool& ok) } return p; } + +QRect ScreenGrabber::desktopGeometry() +{ + QRect geometry; + + for (QScreen* const screen : QGuiApplication::screens()) { + QRect scrRect = screen->geometry(); + scrRect.moveTo(scrRect.x() / screen->devicePixelRatio(), + scrRect.y() / screen->devicePixelRatio()); + geometry = geometry.united(scrRect); + } + return geometry; +} diff --git a/src/utils/screengrabber.h b/src/utils/screengrabber.h index e120a04c..74debffe 100644 --- a/src/utils/screengrabber.h +++ b/src/utils/screengrabber.h @@ -15,6 +15,7 @@ public: QRect screenGeometry(int screenNumber); QPixmap grabScreen(int screenNumber, bool& ok); void freeDesktopPortal(bool& ok, QPixmap& res); + QRect desktopGeometry(); private: DesktopInfo m_info; diff --git a/src/utils/valuehandler.cpp b/src/utils/valuehandler.cpp index 9a31d496..4350f994 100644 --- a/src/utils/valuehandler.cpp +++ b/src/utils/valuehandler.cpp @@ -1,6 +1,7 @@ #include "valuehandler.h" #include "capturetool.h" #include "confighandler.h" +#include "screengrabber.h" #include #include #include @@ -468,4 +469,62 @@ QVariant SaveFileExtension::process(const QVariant& val) QString SaveFileExtension::expected() { return QStringLiteral("supported image extension"); -} \ No newline at end of file +} + +// REGION + +bool Region::check(const QVariant& val) +{ + QVariant region = process(val); + return process(val).isValid(); +} + +#include // TODO remove after FIXME (see below) + +QVariant Region::process(const QVariant& val) +{ + // FIXME: This is temporary, just before D-Bus is removed + char** argv = new char*[1]; + int* argc = new int{ 0 }; + if (QGuiApplication::screens().empty()) + new QApplication(*argc, argv); + + QString str = val.toString(); + + if (str == "all") { + return ScreenGrabber().desktopGeometry(); + } else if (str.startsWith("screen")) { + bool ok; + int number = str.midRef(6).toInt(&ok); + if (!ok || number < 0) { + return {}; + } + return ScreenGrabber().screenGeometry(number); + } + + QRegExp regex("(-{,1}\\d+)" // number (any sign) + "[x,\\.\\s]" // separator ('x', ',', '.', or whitespace) + "(-{,1}\\d+)" // number (any sign) + "[\\+,\\.\\s]*" // separator ('+',',', '.', or whitespace) + "(-{,1}\\d+)" // number (non-negative) + "[\\+,\\.\\s]*" // separator ('+', ',', '.', or whitespace) + "(-{,1}\\d+)" // number (non-negative) + ); + + if (!regex.exactMatch(str)) { + return {}; + } + + int w, h, x, y; + bool w_ok, h_ok, x_ok, y_ok; + w = regex.cap(1).toInt(&w_ok); + h = regex.cap(2).toInt(&h_ok); + x = regex.cap(3).toInt(&x_ok); + y = regex.cap(4).toInt(&y_ok); + + if (!(w_ok && h_ok && x_ok && y_ok)) { + return {}; + } + + return QRect(x, y, w, h).normalized(); +} diff --git a/src/utils/valuehandler.h b/src/utils/valuehandler.h index d6ad65a1..3e9c5370 100644 --- a/src/utils/valuehandler.h +++ b/src/utils/valuehandler.h @@ -205,3 +205,12 @@ class SaveFileExtension : public ValueHandler QVariant process(const QVariant& val) override; QString expected() override; }; + +class Region : public ValueHandler +{ +public: + bool check(const QVariant& val) override; + +private: + QVariant process(const QVariant& val) override; +}; diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp index 510192a4..73fd33dd 100644 --- a/src/widgets/capture/capturewidget.cpp +++ b/src/widgets/capture/capturewidget.cpp @@ -91,8 +91,6 @@ CaptureWidget::CaptureWidget(uint id, m_contrastUiColor = m_config.contrastUiColor(); setMouseTracking(true); initContext(fullScreen, id); - initSelection(); - initShortcuts(); // must be called after initSelection #if (defined(Q_OS_WIN) || defined(Q_OS_MACOS)) // Top left of the whole set of screens QPoint topLeft(0, 0); @@ -143,9 +141,6 @@ CaptureWidget::CaptureWidget(uint id, #endif #endif } - // Create buttons - m_buttonHandler = new ButtonHandler(this); - initButtons(); QVector areas; if (m_context.fullscreen) { QPoint topLeftOffset = QPoint(0, 0); @@ -176,9 +171,15 @@ CaptureWidget::CaptureWidget(uint id, } else { areas.append(rect()); } + + m_buttonHandler = new ButtonHandler(this); m_buttonHandler->updateScreenRegions(areas); m_buttonHandler->hide(); + initButtons(); + initSelection(); // button handler must be initialized before + initShortcuts(); // must be called after initSelection + // Init color picker m_colorPicker = new ColorPicker(this); connect(m_colorPicker, @@ -1037,11 +1038,10 @@ void CaptureWidget::showAppUpdateNotification(const QString& appLatestVersion, void CaptureWidget::initSelection() { + // Be mindful of the order of statements, so that slots are called properly m_selection = new SelectionWidget(m_uiColor, this); - m_selection->setVisible(false); - m_selection->setGeometry(QRect()); + QRect initialSelection = m_context.request()->initialSelection(); connect(m_selection, &SelectionWidget::geometryChanged, this, [this]() { - m_buttonHandler->updatePosition(m_selection->geometry()); QRect constrainedToCaptureArea = m_selection->geometry().intersected(rect()); m_context.selection = extendedRect(constrainedToCaptureArea); @@ -1051,9 +1051,10 @@ void CaptureWidget::initSelection() OverlayMessage::pop(); }); connect(m_selection, &SelectionWidget::geometrySettled, this, [this]() { - if (m_selection->isVisible()) { + if (m_selection->isVisibleTo(this)) { auto req = m_context.request(); if (req->tasks() & CaptureRequest::ACCEPT_ON_SELECT) { + req->removeTask(CaptureRequest::ACCEPT_ON_SELECT); m_captureDone = true; if (req->tasks() & CaptureRequest::PIN) { QRect geometry = m_context.selection; @@ -1063,16 +1064,27 @@ void CaptureWidget::initSelection() } close(); } + m_buttonHandler->updatePosition(m_selection->geometry()); m_buttonHandler->show(); } else { m_buttonHandler->hide(); } }); connect(m_selection, &SelectionWidget::visibilityChanged, this, [this]() { - if (!m_selection->isVisible()) { + if (!m_selection->isVisible() && !m_helpMessage.isEmpty()) { OverlayMessage::push(m_helpMessage); } }); + if (!initialSelection.isNull()) { + initialSelection.moveTopLeft(initialSelection.topLeft() - + mapToGlobal({})); + } + m_selection->setGeometry(initialSelection); + m_selection->setVisible(!initialSelection.isNull()); + if (!initialSelection.isNull()) { + m_context.selection = extendedRect(m_selection->geometry()); + emit m_selection->geometrySettled(); + } } void CaptureWidget::setState(CaptureToolButton* b)