Skip to content

Commit d4956a8

Browse files
Fixed screen subcommand to fit per screen paradigm (flameshot-org#4544)
* Fixed screen subcommand to fit per screen paradigm * Full subcommand fix
1 parent 4a32a7e commit d4956a8

File tree

8 files changed

+104
-77
lines changed

8 files changed

+104
-77
lines changed

data/man/man1/flameshot.1

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ Valid for subcommands: full, gui, screen
131131
.RE
132132
.
133133
.PP
134+
\-e, \-\-edit
135+
.RS 4
136+
Interactively select and edit the screenshot region
137+
.br
138+
Valid for subcommands: screen
139+
.RE
140+
.
141+
.PP
134142
\-f, \-\-filename <pattern>
135143
.RS 4
136144
Set the filename pattern
@@ -215,7 +223,7 @@ Valid for subcommands: full, gui, screen
215223
.RS 4
216224
Screenshot region to select
217225
.br
218-
Valid for subcommands: full, gui, screen
226+
Valid for subcommands: gui, screen
219227
.RE
220228
.
221229
.PP
@@ -234,14 +242,6 @@ Enable or disable the trayicon
234242
Valid for subcommands: config
235243
.RE
236244
.
237-
.PP
238-
\-u, \-\-upload
239-
.RS 4
240-
Upload screenshot
241-
.br
242-
Valid for subcommands: full, gui, screen
243-
.RE
244-
.
245245
.\"----------------------------------------------------------------------------
246246
.SH "EXAMPLE USAGE"
247247
.PP

data/shell-completion/flameshot.bash

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ _flameshot() {
1212
prev="${COMP_WORDS[COMP_CWORD-1]}"
1313
cur="${COMP_WORDS[COMP_CWORD]}"
1414
cmd="gui full config launcher screen"
15-
screen_opts="--number -n --path -p --clipboard -c --delay -d --region --raw -r --upload -u --pin --help"
16-
gui_opts="--path -p --clipboard -c --delay -d --region --last-region --raw -r --print-geometry -g --upload -u --pin --accept-on-select -s --help"
17-
full_opts="--path -p --clipboard -c --delay -d --region --raw -r --upload -u --help"
15+
screen_opts="--number -n --edit -e --path -p --clipboard -c --delay -d --region --raw -r --pin --help"
16+
gui_opts="--path -p --clipboard -c --delay -d --region --last-region --raw -r --print-geometry -g --pin --accept-on-select -s --help"
17+
full_opts="--path -p --clipboard -c --delay -d --raw -r --help"
1818
config_opts="--autostart -a --filename -f --notifications -n --trayicon -t --showhelp -s --maincolor -m --contrastcolor -k --check"
1919

2020
case "${prev}" in

data/shell-completion/flameshot.fish

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,19 @@ __flameshot_complete gui --long-option "region" --d
8383
__flameshot_complete gui --long-option "last-region" --description "Repeat screenshot with previously selected region" --no-files
8484
__flameshot_complete gui --long-option "raw" --short-option "r" --description "Print raw PNG capture" --no-files
8585
__flameshot_complete gui --long-option "print-geometry" --short-option "g" --description "Print geometry of the selection" --no-files
86-
__flameshot_complete gui --long-option "upload" --short-option "u" --description "Upload the screenshot" --no-files
8786
__flameshot_complete gui --long-option "pin" --description "Pin the screenshot to the screen" --no-files
8887
__flameshot_complete gui --long-option "accept-on-select" --short-option "s" --description "Accept capture as soon as a selection is made" --no-files
8988
__flameshot_complete gui --long-option "help" --short-option "h" --description "Show the available arguments" --no-files
9089

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

@@ -105,9 +104,7 @@ __flameshot_complete full --no-files
105104
__flameshot_complete full --long-option "path" --short-option "p" --description "Output file or directory" --require-parameter
106105
__flameshot_complete full --long-option "clipboard" --short-option "c" --description "Copy screenshot to the clipboard" --no-files
107106
__flameshot_complete full --long-option "delay" --short-option "d" --description "Delay time in milliseconds" --require-parameter --no-files
108-
__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
109107
__flameshot_complete full --long-option "raw" --short-option "r" --description "Print raw PNG capture" --no-files
110-
__flameshot_complete full --long-option "upload" --short-option "u" --description "Upload the screenshot" --no-files
111108
__flameshot_complete full --long-option "help" --short-option "h" --description "Show the available arguments" --no-files
112109

113110
# LAUNCHER command

data/shell-completion/flameshot.zsh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ _flameshot_gui_opts=(
2424
"--last-region[Repeat screenshot with previously selected region]"
2525
{-r,--raw}'[Print raw PNG capture]'
2626
{-g,--print-geometry}'[Print geometry of the selection in the format WxH+X+Y. Does nothing if raw is specified]'
27-
{-u,--upload}'[Upload screenshot]'
2827
"--pin[Pin the capture to the screen]"
2928
{-s,--accept-on-select}'[Accept capture as soon as a selection is made]'
3029
{-h,--help}'[Show the available arguments]'
@@ -40,12 +39,12 @@ _flameshot_gui() {
4039

4140
_flameshot_screen_opts=(
4241
{-n,--number}'[Define the screen to capture (starting from 0). Default: screen containing the cursor]'
42+
{-e,--edit}'[Interactively select and edit the screenshot region]'
4343
{-p,--path}'[Existing directory or new file to save to]':dir:_files
4444
{-c,--clipboard}'[Save the capture to the clipboard]'
4545
{-d,--delay}'[Delay time in milliseconds]'
4646
"--region[Screenshot region to select <WxH+X+Y or string>]"
4747
{-r,--raw}'[Print raw PNG capture]'
48-
{-u,--upload}'[Upload screenshot]'
4948
"--pin[Pin the capture to the screen]"
5049
{-h,--help}'[Show the available arguments]'
5150
)
@@ -62,9 +61,7 @@ _flameshot_full_opts=(
6261
{-p,--path}'[Existing directory or new file to save to]':dir:_files
6362
{-c,--clipboard}'[Save the capture to the clipboard]'
6463
{-d,--delay}'[Delay time in milliseconds]'
65-
"--region[Screenshot region to select <WxH+X+Y or string>]"
6664
{-r,--raw}'[Print raw PNG capture]'
67-
{-u,--upload}'[Upload screenshot]'
6865
{-h,--help}'[Show the available arguments]'
6966
)
7067

src/core/flameshot.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -146,28 +146,40 @@ void Flameshot::screen(CaptureRequest req, const int screenNumber)
146146
return;
147147
}
148148

149-
bool ok = true;
150-
QScreen* screen;
149+
bool ok = false;
150+
QPixmap p;
151+
QRect geometry;
151152

152153
if (screenNumber < 0) {
153-
QPoint globalCursorPos = QCursor::pos();
154-
screen = qApp->screenAt(globalCursorPos);
154+
ScreenGrabber grabber;
155+
p = grabber.grabEntireDesktop(ok);
156+
if (ok) {
157+
QScreen* selectedScreen = grabber.getSelectedScreen();
158+
if (selectedScreen) {
159+
geometry = ScreenGrabber().screenGeometry(selectedScreen);
160+
} else {
161+
ok = false;
162+
}
163+
}
155164
} else if (screenNumber >= qApp->screens().count()) {
156165
AbstractLogger() << QObject::tr(
157166
"Requested screen exceeds screen count");
158-
emit captureFailed();
159-
return;
167+
ok = false;
160168
} else {
161-
screen = qApp->screens()[screenNumber];
169+
// Specific screen number provided - use grabScreen to bypass selector
170+
QScreen* screen = qApp->screens()[screenNumber];
171+
p = ScreenGrabber().grabScreen(screen, ok);
172+
if (ok) {
173+
geometry = ScreenGrabber().screenGeometry(screen);
174+
}
162175
}
163-
QPixmap p(ScreenGrabber().grabScreen(screen, ok));
176+
164177
if (ok) {
165-
QRect geometry = ScreenGrabber().screenGeometry(screen);
166178
QRect region = req.initialSelection();
167179
if (region.isNull()) {
168-
region = ScreenGrabber().screenGeometry(screen);
180+
region = geometry;
169181
} else {
170-
QRect screenGeom = ScreenGrabber().screenGeometry(screen);
182+
QRect screenGeom = geometry;
171183
screenGeom.moveTopLeft({ 0, 0 });
172184
region = region.intersected(screenGeom);
173185
p = p.copy(region);
@@ -189,13 +201,9 @@ void Flameshot::full(const CaptureRequest& req)
189201
}
190202

191203
bool ok = true;
192-
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
193-
QRect region = req.initialSelection();
194-
if (!region.isNull()) {
195-
p = p.copy(region);
196-
}
204+
QPixmap p(ScreenGrabber().grabFullDesktop(ok));
197205
if (ok) {
198-
QRect selection; // `flameshot full` does not support --selection
206+
QRect selection; // `flameshot full` does not support region selection
199207
exportCapture(p, selection, req);
200208
} else {
201209
emit captureFailed();

src/main.cpp

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,6 @@ int main(int argc, char* argv[])
290290
{ "c", "clipboard" }, QObject::tr("Save the capture to the clipboard"));
291291
CommandOption pinOption("pin",
292292
QObject::tr("Pin the capture to the screen"));
293-
CommandOption uploadOption({ "u", "upload" },
294-
QObject::tr("Upload screenshot"));
295293
CommandOption delayOption({ "d", "delay" },
296294
QObject::tr("Delay time in milliseconds"),
297295
QStringLiteral("milliseconds"));
@@ -345,6 +343,9 @@ int main(int argc, char* argv[])
345343
QObject::tr("default: screen containing the cursor"),
346344
QObject::tr("Screen number"),
347345
QStringLiteral("-1"));
346+
CommandOption editOption(
347+
{ "e", "edit" },
348+
QObject::tr("Interactively select and edit the screenshot region"));
348349

349350
// Add checkers
350351
auto colorChecker = [](const QString& colorCode) -> bool {
@@ -423,26 +424,21 @@ int main(int argc, char* argv[])
423424
useLastRegionOption,
424425
rawImageOption,
425426
selectionOption,
426-
uploadOption,
427427
pinOption,
428428
acceptOnSelectOption },
429429
guiArgument);
430430
parser.AddOptions({ screenNumberOption,
431+
editOption,
431432
clipboardOption,
432433
pathOption,
433434
delayOption,
434435
regionOption,
435436
rawImageOption,
436-
uploadOption,
437437
pinOption },
438438
screenArgument);
439-
parser.AddOptions({ pathOption,
440-
clipboardOption,
441-
delayOption,
442-
regionOption,
443-
rawImageOption,
444-
uploadOption },
445-
fullArgument);
439+
parser.AddOptions(
440+
{ pathOption, clipboardOption, delayOption, rawImageOption },
441+
fullArgument);
446442
parser.AddOptions({ autostartOption,
447443
notificationOption,
448444
filenameOption,
@@ -495,7 +491,6 @@ int main(int argc, char* argv[])
495491
bool raw = parser.isSet(rawImageOption);
496492
bool printGeometry = parser.isSet(selectionOption);
497493
bool pin = parser.isSet(pinOption);
498-
bool upload = parser.isSet(uploadOption);
499494
bool acceptOnSelect = parser.isSet(acceptOnSelectOption);
500495
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
501496
if (!region.isEmpty()) {
@@ -519,13 +514,10 @@ int main(int argc, char* argv[])
519514
if (pin) {
520515
req.addTask(CaptureRequest::PIN);
521516
}
522-
if (upload) {
523-
req.addTask(CaptureRequest::UPLOAD);
524-
}
525517
if (acceptOnSelect) {
526518
req.addTask(CaptureRequest::ACCEPT_ON_SELECT);
527519
if (!clipboard && !raw && path.isEmpty() && !printGeometry &&
528-
!pin && !upload) {
520+
!pin) {
529521
req.addSaveTask();
530522
}
531523
}
@@ -541,16 +533,10 @@ int main(int argc, char* argv[])
541533
path = QDir(path).absolutePath();
542534
}
543535
int delay = parser.value(delayOption).toInt();
544-
QString region = parser.value(regionOption);
545536
bool clipboard = parser.isSet(clipboardOption);
546537
bool raw = parser.isSet(rawImageOption);
547-
bool upload = parser.isSet(uploadOption);
548-
// Not a valid command
549538

550539
CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay);
551-
if (!region.isEmpty()) {
552-
req.setInitialSelection(Region().value(region).toRect());
553-
}
554540
if (clipboard) {
555541
req.addTask(CaptureRequest::COPY);
556542
}
@@ -560,10 +546,7 @@ int main(int argc, char* argv[])
560546
if (raw) {
561547
req.addTask(CaptureRequest::PRINT_RAW);
562548
}
563-
if (upload) {
564-
req.addTask(CaptureRequest::UPLOAD);
565-
}
566-
if (!clipboard && path.isEmpty() && !raw && !upload) {
549+
if (!clipboard && path.isEmpty() && !raw) {
567550
req.addSaveTask();
568551
}
569552
{
@@ -587,9 +570,17 @@ int main(int argc, char* argv[])
587570
bool clipboard = parser.isSet(clipboardOption);
588571
bool raw = parser.isSet(rawImageOption);
589572
bool pin = parser.isSet(pinOption);
590-
bool upload = parser.isSet(uploadOption);
573+
bool edit = parser.isSet(editOption);
574+
575+
CaptureRequest req(edit ? CaptureRequest::GRAPHICAL_MODE
576+
: CaptureRequest::SCREEN_MODE,
577+
delay);
578+
579+
// For edit mode, set the selected monitor
580+
if (edit && screenNumber >= 0) {
581+
req.setSelectedMonitor(screenNumber);
582+
}
591583

592-
CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, screenNumber);
593584
if (!region.isEmpty()) {
594585
if (region.startsWith("screen")) {
595586
AbstractLogger::error()
@@ -612,11 +603,8 @@ int main(int argc, char* argv[])
612603
if (pin) {
613604
req.addTask(CaptureRequest::PIN);
614605
}
615-
if (upload) {
616-
req.addTask(CaptureRequest::UPLOAD);
617-
}
618606

619-
if (!clipboard && !raw && path.isEmpty() && !pin && !upload) {
607+
if (!edit && !clipboard && !raw && path.isEmpty() && !pin) {
620608
req.addSaveTask();
621609
}
622610

src/utils/screengrabber.cpp

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <QKeyEvent>
1515
#include <QLabel>
1616
#include <QMouseEvent>
17+
#include <QPainter>
1718
#include <QPixmap>
1819
#include <QProcess>
1920
#include <QScreen>
@@ -227,6 +228,46 @@ QPixmap ScreenGrabber::grabEntireDesktop(bool& ok, int preSelectedMonitor)
227228
return selectMonitorAndCrop(screenshot, ok);
228229
}
229230

231+
QPixmap ScreenGrabber::grabFullDesktop(bool& ok)
232+
{
233+
ok = true;
234+
QPixmap screenshot;
235+
236+
#if defined(Q_OS_MACOS)
237+
// On macOS, composite all screens into a single pixmap.
238+
const QList<QScreen*> screens = QGuiApplication::screens();
239+
QRect totalGeom;
240+
for (QScreen* s : screens) {
241+
totalGeom = totalGeom.united(s->geometry());
242+
}
243+
qreal maxDpr = 1.0;
244+
for (QScreen* s : screens) {
245+
maxDpr = qMax(maxDpr, s->devicePixelRatio());
246+
}
247+
screenshot = QPixmap(qRound(totalGeom.width() * maxDpr),
248+
qRound(totalGeom.height() * maxDpr));
249+
screenshot.setDevicePixelRatio(maxDpr);
250+
screenshot.fill(Qt::black);
251+
QPainter painter(&screenshot);
252+
for (QScreen* s : screens) {
253+
QRect geom = s->geometry();
254+
QPixmap p = s->grabWindow(0);
255+
QPoint offset = geom.topLeft() - totalGeom.topLeft();
256+
painter.drawPixmap(offset, p);
257+
}
258+
painter.end();
259+
#elif defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
260+
freeDesktopPortal(ok, screenshot);
261+
if (!ok) {
262+
AbstractLogger::error() << tr("Unable to capture screen");
263+
}
264+
#elif defined(Q_OS_WIN)
265+
screenshot = windowsScreenshot(0);
266+
#endif
267+
268+
return screenshot;
269+
}
270+
230271
QRect ScreenGrabber::screenGeometry(QScreen* screen)
231272
{
232273
QRect geometry = screen->geometry();
@@ -242,15 +283,10 @@ QPixmap ScreenGrabber::grabScreen(QScreen* screen, bool& ok)
242283
QPixmap p;
243284
QRect geometry = screenGeometry(screen);
244285
#if defined(Q_OS_LINUX)
245-
p = grabEntireDesktop(ok);
246-
if (ok) {
247-
// Both X11 and Wayland: Use cropToMonitor for consistent handling
248-
// of misaligned monitors and mixed DPI
249-
const QList<QScreen*> screens = QGuiApplication::screens();
250-
int screenIndex = screens.indexOf(screen);
286+
const QList<QScreen*> screens = QGuiApplication::screens();
287+
int screenIndex = screens.indexOf(screen);
251288

252-
return cropToMonitor(p, screenIndex);
253-
}
289+
p = grabEntireDesktop(ok, screenIndex);
254290
#else
255291
ok = true;
256292
return screen->grabWindow(

0 commit comments

Comments
 (0)