Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions data/man/man1/flameshot.1
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ Valid for subcommands: full, gui, screen
.RE
.
.PP
\-e, \-\-edit
.RS 4
Interactively select and edit the screenshot region
.br
Valid for subcommands: screen
.RE
.
.PP
\-f, \-\-filename <pattern>
.RS 4
Set the filename pattern
Expand Down Expand Up @@ -215,7 +223,7 @@ Valid for subcommands: full, gui, screen
.RS 4
Screenshot region to select
.br
Valid for subcommands: full, gui, screen
Valid for subcommands: gui, screen
.RE
.
.PP
Expand All @@ -234,14 +242,6 @@ Enable or disable the trayicon
Valid for subcommands: config
.RE
.
.PP
\-u, \-\-upload
.RS 4
Upload screenshot
.br
Valid for subcommands: full, gui, screen
.RE
.
.\"----------------------------------------------------------------------------
.SH "EXAMPLE USAGE"
.PP
Expand Down
6 changes: 3 additions & 3 deletions data/shell-completion/flameshot.bash
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ _flameshot() {
prev="${COMP_WORDS[COMP_CWORD-1]}"
cur="${COMP_WORDS[COMP_CWORD]}"
cmd="gui full config launcher screen"
screen_opts="--number -n --path -p --clipboard -c --delay -d --region --raw -r --upload -u --pin --help"
gui_opts="--path -p --clipboard -c --delay -d --region --last-region --raw -r --print-geometry -g --upload -u --pin --accept-on-select -s --help"
full_opts="--path -p --clipboard -c --delay -d --region --raw -r --upload -u --help"
screen_opts="--number -n --edit -e --path -p --clipboard -c --delay -d --region --raw -r --pin --help"
gui_opts="--path -p --clipboard -c --delay -d --region --last-region --raw -r --print-geometry -g --pin --accept-on-select -s --help"
full_opts="--path -p --clipboard -c --delay -d --raw -r --help"
config_opts="--autostart -a --filename -f --notifications -n --trayicon -t --showhelp -s --maincolor -m --contrastcolor -k --check"

case "${prev}" in
Expand Down
5 changes: 1 addition & 4 deletions data/shell-completion/flameshot.fish
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,19 @@ __flameshot_complete gui --long-option "region" --d
__flameshot_complete gui --long-option "last-region" --description "Repeat screenshot with previously selected region" --no-files
__flameshot_complete gui --long-option "raw" --short-option "r" --description "Print raw PNG capture" --no-files
__flameshot_complete gui --long-option "print-geometry" --short-option "g" --description "Print geometry of the selection" --no-files
__flameshot_complete gui --long-option "upload" --short-option "u" --description "Upload the screenshot" --no-files
__flameshot_complete gui --long-option "pin" --description "Pin the screenshot to the screen" --no-files
__flameshot_complete gui --long-option "accept-on-select" --short-option "s" --description "Accept capture as soon as a selection is made" --no-files
__flameshot_complete gui --long-option "help" --short-option "h" --description "Show the available arguments" --no-files

# SCREEN subcommand
__flameshot_complete screen --no-files
__flameshot_complete screen --long-option "number" --short-option "n" --description "Screen number (starting from 0)" --require-parameter --no-files --arguments "(__flameshot_complete_screen_number)"
__flameshot_complete screen --long-option "edit" --short-option "e" --description "Interactively select and edit the screenshot region" --no-files
__flameshot_complete screen --long-option "path" --short-option "p" --description "Output file or directory" --require-parameter
__flameshot_complete screen --long-option "clipboard" --short-option "c" --description "Copy screenshot to the clipboard" --no-files
__flameshot_complete screen --long-option "delay" --short-option "d" --description "Delay time in milliseconds" --require-parameter --no-files
__flameshot_complete screen --long-option "region" --description "Screenshot region to select (WxH+X+Y)" --require-parameter --no-files --arguments "(__flameshot_complete_region screen)"
__flameshot_complete screen --long-option "raw" --short-option "r" --description "Print raw PNG capture" --no-files
__flameshot_complete screen --long-option "upload" --short-option "u" --description "Upload the screenshot" --no-files
__flameshot_complete screen --long-option "pin" --description "Pin the screenshot to the screen" --no-files
__flameshot_complete screen --long-option "help" --short-option "h" --description "Show the available arguments" --no-files

Expand All @@ -105,9 +104,7 @@ __flameshot_complete full --no-files
__flameshot_complete full --long-option "path" --short-option "p" --description "Output file or directory" --require-parameter
__flameshot_complete full --long-option "clipboard" --short-option "c" --description "Copy screenshot to the clipboard" --no-files
__flameshot_complete full --long-option "delay" --short-option "d" --description "Delay time in milliseconds" --require-parameter --no-files
__flameshot_complete full --long-option "region" --description "Screenshot region to select (WxH+X+Y)" --require-parameter --no-files --arguments "(__flameshot_complete_region full)" --keep-order
__flameshot_complete full --long-option "raw" --short-option "r" --description "Print raw PNG capture" --no-files
__flameshot_complete full --long-option "upload" --short-option "u" --description "Upload the screenshot" --no-files
__flameshot_complete full --long-option "help" --short-option "h" --description "Show the available arguments" --no-files

# LAUNCHER command
Expand Down
5 changes: 1 addition & 4 deletions data/shell-completion/flameshot.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ _flameshot_gui_opts=(
"--last-region[Repeat screenshot with previously selected region]"
{-r,--raw}'[Print raw PNG capture]'
{-g,--print-geometry}'[Print geometry of the selection in the format WxH+X+Y. Does nothing if raw is specified]'
{-u,--upload}'[Upload screenshot]'
"--pin[Pin the capture to the screen]"
{-s,--accept-on-select}'[Accept capture as soon as a selection is made]'
{-h,--help}'[Show the available arguments]'
Expand All @@ -40,12 +39,12 @@ _flameshot_gui() {

_flameshot_screen_opts=(
{-n,--number}'[Define the screen to capture (starting from 0). Default: screen containing the cursor]'
{-e,--edit}'[Interactively select and edit the screenshot region]'
{-p,--path}'[Existing directory or new file to save to]':dir:_files
{-c,--clipboard}'[Save the capture to the clipboard]'
{-d,--delay}'[Delay time in milliseconds]'
"--region[Screenshot region to select <WxH+X+Y or string>]"
{-r,--raw}'[Print raw PNG capture]'
{-u,--upload}'[Upload screenshot]'
"--pin[Pin the capture to the screen]"
{-h,--help}'[Show the available arguments]'
)
Expand All @@ -62,9 +61,7 @@ _flameshot_full_opts=(
{-p,--path}'[Existing directory or new file to save to]':dir:_files
{-c,--clipboard}'[Save the capture to the clipboard]'
{-d,--delay}'[Delay time in milliseconds]'
"--region[Screenshot region to select <WxH+X+Y or string>]"
{-r,--raw}'[Print raw PNG capture]'
{-u,--upload}'[Upload screenshot]'
{-h,--help}'[Show the available arguments]'
)

Expand Down
42 changes: 25 additions & 17 deletions src/core/flameshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,28 +146,40 @@ void Flameshot::screen(CaptureRequest req, const int screenNumber)
return;
}

bool ok = true;
QScreen* screen;
bool ok = false;
QPixmap p;
QRect geometry;

if (screenNumber < 0) {
QPoint globalCursorPos = QCursor::pos();
screen = qApp->screenAt(globalCursorPos);
ScreenGrabber grabber;
p = grabber.grabEntireDesktop(ok);
if (ok) {
QScreen* selectedScreen = grabber.getSelectedScreen();
if (selectedScreen) {
geometry = ScreenGrabber().screenGeometry(selectedScreen);
} else {
ok = false;
}
}
} else if (screenNumber >= qApp->screens().count()) {
AbstractLogger() << QObject::tr(
"Requested screen exceeds screen count");
emit captureFailed();
return;
ok = false;
} else {
screen = qApp->screens()[screenNumber];
// Specific screen number provided - use grabScreen to bypass selector
QScreen* screen = qApp->screens()[screenNumber];
p = ScreenGrabber().grabScreen(screen, ok);
if (ok) {
geometry = ScreenGrabber().screenGeometry(screen);
}
}
QPixmap p(ScreenGrabber().grabScreen(screen, ok));

if (ok) {
QRect geometry = ScreenGrabber().screenGeometry(screen);
QRect region = req.initialSelection();
if (region.isNull()) {
region = ScreenGrabber().screenGeometry(screen);
region = geometry;
} else {
QRect screenGeom = ScreenGrabber().screenGeometry(screen);
QRect screenGeom = geometry;
screenGeom.moveTopLeft({ 0, 0 });
region = region.intersected(screenGeom);
p = p.copy(region);
Expand All @@ -189,13 +201,9 @@ void Flameshot::full(const CaptureRequest& req)
}

bool ok = true;
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
QRect region = req.initialSelection();
if (!region.isNull()) {
p = p.copy(region);
}
QPixmap p(ScreenGrabber().grabFullDesktop(ok));
if (ok) {
QRect selection; // `flameshot full` does not support --selection
QRect selection; // `flameshot full` does not support region selection
exportCapture(p, selection, req);
} else {
emit captureFailed();
Expand Down
52 changes: 20 additions & 32 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,6 @@ int main(int argc, char* argv[])
{ "c", "clipboard" }, QObject::tr("Save the capture to the clipboard"));
CommandOption pinOption("pin",
QObject::tr("Pin the capture to the screen"));
CommandOption uploadOption({ "u", "upload" },
QObject::tr("Upload screenshot"));
CommandOption delayOption({ "d", "delay" },
QObject::tr("Delay time in milliseconds"),
QStringLiteral("milliseconds"));
Expand Down Expand Up @@ -345,6 +343,9 @@ int main(int argc, char* argv[])
QObject::tr("default: screen containing the cursor"),
QObject::tr("Screen number"),
QStringLiteral("-1"));
CommandOption editOption(
{ "e", "edit" },
QObject::tr("Interactively select and edit the screenshot region"));

// Add checkers
auto colorChecker = [](const QString& colorCode) -> bool {
Expand Down Expand Up @@ -423,26 +424,21 @@ int main(int argc, char* argv[])
useLastRegionOption,
rawImageOption,
selectionOption,
uploadOption,
pinOption,
acceptOnSelectOption },
guiArgument);
parser.AddOptions({ screenNumberOption,
editOption,
clipboardOption,
pathOption,
delayOption,
regionOption,
rawImageOption,
uploadOption,
pinOption },
screenArgument);
parser.AddOptions({ pathOption,
clipboardOption,
delayOption,
regionOption,
rawImageOption,
uploadOption },
fullArgument);
parser.AddOptions(
{ pathOption, clipboardOption, delayOption, rawImageOption },
fullArgument);
parser.AddOptions({ autostartOption,
notificationOption,
filenameOption,
Expand Down Expand Up @@ -495,7 +491,6 @@ int main(int argc, char* argv[])
bool raw = parser.isSet(rawImageOption);
bool printGeometry = parser.isSet(selectionOption);
bool pin = parser.isSet(pinOption);
bool upload = parser.isSet(uploadOption);
bool acceptOnSelect = parser.isSet(acceptOnSelectOption);
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
if (!region.isEmpty()) {
Expand All @@ -519,13 +514,10 @@ int main(int argc, char* argv[])
if (pin) {
req.addTask(CaptureRequest::PIN);
}
if (upload) {
req.addTask(CaptureRequest::UPLOAD);
}
if (acceptOnSelect) {
req.addTask(CaptureRequest::ACCEPT_ON_SELECT);
if (!clipboard && !raw && path.isEmpty() && !printGeometry &&
!pin && !upload) {
!pin) {
req.addSaveTask();
}
}
Expand All @@ -541,16 +533,10 @@ 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);
}
Expand All @@ -560,10 +546,7 @@ int main(int argc, char* argv[])
if (raw) {
req.addTask(CaptureRequest::PRINT_RAW);
}
if (upload) {
req.addTask(CaptureRequest::UPLOAD);
}
if (!clipboard && path.isEmpty() && !raw && !upload) {
if (!clipboard && path.isEmpty() && !raw) {
req.addSaveTask();
}
{
Expand All @@ -587,9 +570,17 @@ int main(int argc, char* argv[])
bool clipboard = parser.isSet(clipboardOption);
bool raw = parser.isSet(rawImageOption);
bool pin = parser.isSet(pinOption);
bool upload = parser.isSet(uploadOption);
bool edit = parser.isSet(editOption);

CaptureRequest req(edit ? CaptureRequest::GRAPHICAL_MODE
: CaptureRequest::SCREEN_MODE,
delay);

// For edit mode, set the selected monitor
if (edit && screenNumber >= 0) {
req.setSelectedMonitor(screenNumber);
}

CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, screenNumber);
if (!region.isEmpty()) {
if (region.startsWith("screen")) {
AbstractLogger::error()
Expand All @@ -612,11 +603,8 @@ int main(int argc, char* argv[])
if (pin) {
req.addTask(CaptureRequest::PIN);
}
if (upload) {
req.addTask(CaptureRequest::UPLOAD);
}

if (!clipboard && !raw && path.isEmpty() && !pin && !upload) {
if (!edit && !clipboard && !raw && path.isEmpty() && !pin) {
req.addSaveTask();
}

Expand Down
52 changes: 44 additions & 8 deletions src/utils/screengrabber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <QKeyEvent>
#include <QLabel>
#include <QMouseEvent>
#include <QPainter>
#include <QPixmap>
#include <QProcess>
#include <QScreen>
Expand Down Expand Up @@ -227,6 +228,46 @@ QPixmap ScreenGrabber::grabEntireDesktop(bool& ok, int preSelectedMonitor)
return selectMonitorAndCrop(screenshot, ok);
}

QPixmap ScreenGrabber::grabFullDesktop(bool& ok)
{
ok = true;
QPixmap screenshot;

#if defined(Q_OS_MACOS)
// On macOS, composite all screens into a single pixmap.
const QList<QScreen*> screens = QGuiApplication::screens();
QRect totalGeom;
for (QScreen* s : screens) {
totalGeom = totalGeom.united(s->geometry());
}
qreal maxDpr = 1.0;
for (QScreen* s : screens) {
maxDpr = qMax(maxDpr, s->devicePixelRatio());
}
screenshot = QPixmap(qRound(totalGeom.width() * maxDpr),
qRound(totalGeom.height() * maxDpr));
screenshot.setDevicePixelRatio(maxDpr);
screenshot.fill(Qt::black);
QPainter painter(&screenshot);
for (QScreen* s : screens) {
QRect geom = s->geometry();
QPixmap p = s->grabWindow(0);
QPoint offset = geom.topLeft() - totalGeom.topLeft();
painter.drawPixmap(offset, p);
}
painter.end();
#elif defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
freeDesktopPortal(ok, screenshot);
if (!ok) {
AbstractLogger::error() << tr("Unable to capture screen");
}
#elif defined(Q_OS_WIN)
screenshot = windowsScreenshot(0);
#endif

return screenshot;
}

QRect ScreenGrabber::screenGeometry(QScreen* screen)
{
QRect geometry = screen->geometry();
Expand All @@ -242,15 +283,10 @@ QPixmap ScreenGrabber::grabScreen(QScreen* screen, bool& ok)
QPixmap p;
QRect geometry = screenGeometry(screen);
#if defined(Q_OS_LINUX)
p = grabEntireDesktop(ok);
if (ok) {
// Both X11 and Wayland: Use cropToMonitor for consistent handling
// of misaligned monitors and mixed DPI
const QList<QScreen*> screens = QGuiApplication::screens();
int screenIndex = screens.indexOf(screen);
const QList<QScreen*> screens = QGuiApplication::screens();
int screenIndex = screens.indexOf(screen);

return cropToMonitor(p, screenIndex);
}
p = grabEntireDesktop(ok, screenIndex);
#else
ok = true;
return screen->grabWindow(
Expand Down
Loading
Loading