Page 1 of 1
take a (quick) shot
Posted: Tue Jan 19, 2021 8:43 pm
by HerrBert
Hello.
Not sure if this is the right place to post, so feel free to move this to according place...
All the time i'm using puppy linux now i've been missing the ability to do a 'quick' screenshot of the active window like in Windows with ALT+PRINT.
TBH, in Windows you had to open a graphics editor and paste the image from clipboard, so it was not OOTB.
Here is a way to take the shot of the active window instantly:
Code: Select all
#!/bin/bash
[ -z "`which ffmpeg`" ] && echo "${0}: ffmpeg not found. Exiting..." 1>&2 && exit
[ -z "`which xdotool`" ] && echo "${0}: xdotool not found. Exiting..." 1>&2 && exit
WINID="-id `xdotool getactivewindow`"
[ "$WINID" = "-id " ] && WINID="-root" # if no window open
read MAXX MAXY <<< `xwininfo -root | awk 'NR>=8&&NR<=9 {print $2}' | tr '\n' ' '`
#xwininfo doesn't accept -frame and -id - need to manually calculate frame
read XPOS YPOS FRAME TITLE WIDTH HEIGHT <<< `xwininfo $WINID | sed -e '4,9!d' -e 's/.*: *//g' | tr '\n' ' '`
XPOS=$((XPOS - FRAME))
YPOS=$((YPOS - TITLE))
WIDTH=$((WIDTH + (2 * FRAME)))
HEIGHT=$((HEIGHT + FRAME + TITLE))
[ ${XPOS} -lt 0 ] && WIDTH=$((WIDTH + XPOS)) && XPOS=0
[ ${YPOS} -lt 0 ] && HEIGHT=$((HEIGHT + YPOS)) && YPOS=0
[ $((WIDTH + XPOS)) -ge $MAXX ] && WIDTH=$((MAXX - XPOS))
[ $((HEIGHT + YPOS)) -ge $MAXY ] && HEIGHT=$((MAXY - YPOS))
OFFSET="+${XPOS},${YPOS}"
OUTNAME="/root/quickshot-`date +%y%m%d-%H%M%S`.jpg"
ffmpeg -y -f x11grab -r 25 -s ${WIDTH}x${HEIGHT} -i ${DISPLAY}${OFFSET}+nomouse -c mjpeg -frames 1 "$OUTNAME" 2> /dev/null
defaultimageviewer "$OUTNAME" &
Paste code to a file in /usr/bin or /usr/local/bin, name it quickshot and make it executable.
NOTE: dependencies are ffmpeg and xdotool
If then you add/change in your /root/.jwm/jwmrc-personal:
Code: Select all
<Key mask="A" key="Print">exec:quickshot</Key>
you can take a shot of the active window without clicking any dialogs...
Re: take a (quick) shot
Posted: Tue Jan 19, 2021 8:56 pm
by rockedge
@HerrBert gut gemacht!
A useful tool.
Re: take a (quick) shot
Posted: Tue Jan 19, 2021 9:38 pm
by TerryH
A handy little tool. Thanks.
Re: take a (quick) shot
Posted: Tue Jan 19, 2021 10:51 pm
by cobaka
Hello @HerrBert
Pls read the note in the screenshot below
- snapshot_n.jpg (71.19 KiB) Viewed 1639 times
Cobaka
Re: take a (quick) shot
Posted: Wed Jan 20, 2021 2:34 pm
by HerrBert
I have added [ "$WINID" = "-id " ] && WINID="-root" to the code in the first post to take a screenshot of the whole screen if there is no window open. Otherwise defaultimageviewer gives an error.
Re: take a (quick) shot
Posted: Wed Jan 20, 2021 6:03 pm
by takenp
@HerrBert
There is no xdotool on my Bionicpup by default so I tried to find the way how to use what is in the system.
It is xprop. Xprop can find the active window's id:
Code: Select all
WINID="-id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}")"
Re: take a (quick) shot
Posted: Thu Jan 21, 2021 4:22 am
by MochiMoppel
@takenp Same here. Also on my system xdotool is not preinstalled so I always use xprop. But how does your code work? What does the format switch -f do?
I usually do it this way:
WINID=$(xprop -root _NET_ACTIVE_WINDOW)
WINID="-id ${WINID##* }"
which is faster (using bash, not awk)
Re: take a (quick) shot
Posted: Thu Jan 21, 2021 9:53 am
by takenp
which is faster (using bash, not awk)
I've got above xprop string from stackoverflow's example and of course you are absolutely right. Your sample is more clear, shorter and better
Re: take a (quick) shot
Posted: Thu Jan 21, 2021 11:23 am
by HerrBert
@takenp @MochiMoppel
Thanks for suggesting xprop. Very much appreciated...
I had to fiddle a bit with the case that no window is open and also replaced remaining awk with sed.
Code: Select all
#!/bin/bash
[ -z "`which ffmpeg`" ] && echo "${0}: ffmpeg not found. Exiting..." 1>&2 && exit
WINID=$(xprop -root _NET_ACTIVE_WINDOW)
WINID="${WINID##* }"
[ "$WINID" = "0x0" -o "$WINID" = "found." ] && WINID="-root" || WINID="-id $WINID" # if no window open
read MAXX MAXY <<< `xwininfo -root | sed -e '8,9!d;s/.*: *//g' | tr '\n' ' '`
#xwininfo doesn't accept -frame and -id - need to manually calculate frame
read XPOS YPOS FRAME TITLE WIDTH HEIGHT <<< `xwininfo $WINID | sed -e '4,9!d;s/.*: *//g' | tr '\n' ' '`
XPOS=$((XPOS - FRAME))
YPOS=$((YPOS - TITLE))
WIDTH=$((WIDTH + (2 * FRAME)))
HEIGHT=$((HEIGHT + FRAME + TITLE))
[ ${XPOS} -lt 0 ] && WIDTH=$((WIDTH + XPOS)) && XPOS=0
[ ${YPOS} -lt 0 ] && HEIGHT=$((HEIGHT + YPOS)) && YPOS=0
[ $((WIDTH + XPOS)) -ge $MAXX ] && WIDTH=$((MAXX - XPOS))
[ $((HEIGHT + YPOS)) -ge $MAXY ] && HEIGHT=$((MAXY - YPOS))
OFFSET="+${XPOS},${YPOS}"
OUTNAME="/root/quickshot-`date +%y%m%d-%H%M%S`.jpg"
ffmpeg -y -f x11grab -r 25 -s ${WIDTH}x${HEIGHT} -i ${DISPLAY}${OFFSET}+nomouse -c mjpeg -frames 1 "$OUTNAME" 2> /dev/null
defaultimageviewer "$OUTNAME" &
So no longer depending on xdotool.
Thank you very much.
Re: take a (quick) shot
Posted: Thu Jan 21, 2021 12:37 pm
by MochiMoppel
HerrBert wrote: Thu Jan 21, 2021 11:23 am
I had to fiddle a bit with the case that no window is open
If no window is open in the current desktop you most likely have a currently active window on another desktop, so your script takes a shot of the windowless desktop with the size of whatever the size of the (not visible) current window. This can hardly be what the user expects. Do I miss something here?
and also replaced remaining awk with sed
You could even replace sed with faster bash but may not be as compact.
If you want to keep sed you could also try
read MAXX MAXY <<< `xwininfo -root | sed -n '/Width/,/Height/ s/[^0-9]*//p'`
Not much of a difference but may be easier to understand. In any case there should be no need for tr.
Re: take a (quick) shot
Posted: Thu Jan 21, 2021 2:14 pm
by HerrBert
@MochiMoppel
In any case there should be no need for tr.
Weird situation here. When initially written this code in ScPup64 it didn't work until i added tr.
On Slacko64 7.0 i can remove tr and all works as expected.
I think it won't hurt to keep tr.
Many thanks again.
Re: take a (quick) shot
Posted: Fri Jan 22, 2021 2:59 am
by MochiMoppel
HerrBert wrote: Thu Jan 21, 2021 2:14 pmWeird situation here. When initially written this code in ScPup64 it didn't work until i added tr.
On Slacko64 7.0 i can remove tr and all works as expected.
This can only happen if your IFS variable in ScPup64 does not include the linefeed character. However your code can fail even if you add tr , e.g. if IFS is not set at all.
Here is another idea. Since you already call xprop to get WINID why not use the same call for also getting MAXX and MAXY. Fast and does not depend on IFS, tr, read or sed:
XPROP=$(xprop -root _NET_DESKTOP_GEOMETRY _NET_ACTIVE_WINDOW)
WINID=${XPROP##* }
MAXX=${XPROP%,*}
MAXX=${MAXX##* }
MAXY=${XPROP%$'\n'*}
MAXY=${MAXY##* }
Re: take a (quick) shot
Posted: Fri Jan 22, 2021 5:00 pm
by HerrBert
@MochiMoppel
On the tr-thing i did some very trivial testing on ScPup64:
Code: Select all
# set | grep IFS
IFS=$' \t\n'
# read A B <<<`echo -e "eins zwei"`
# echo $A $B
eins zwei
# read A B <<<`echo -e "eins\nzwei"`
# echo $A $B
eins
# echo -e "eins\nzwei"
eins
zwei
# read -d "\n" A B <<<`echo -e "eins\nzwei"`
# echo $A $B
eins zwei
#
Looks like read ignores IFS...
Since the used ScPup64 is 20.06 and i don't have the latest version 'installed' i'll leave this as a note for all, who have problems with the read command in ScPup64_20.06.
Re: take a (quick) shot
Posted: Sat Jan 23, 2021 8:09 am
by Eastler_Dart
You know about the 'screenshot-functionality' of mtpaint ?
I press Print-Key on keyboard, which automatically opens mtpaint with the shot image of the (whole) screen (one keypress, its done).
If I want only the shot of a window, its quick and easy in mtpaint to drag a border around the Window in the screenshot and chose in menu 'image'->'crop'.
On my Lappy without separate NumBlock, I had to press 'Fn' + 'Print' keys together.
For this, you need mtpaint to be installed (is in most puppies),
and add the Key-shortcut in jwmrc or the included /root/jwm/jwmrc-personal (upup-ef).
the line is: <Key key="Print">exec:mtpaint -s</Key>
If you want to take a shot from a menu (which blocks the print-key while opened),
go to terminal, start command: mtpaint -s 10
so mtpaint waits 10 seconds with the shot, you can minimize the terminalwindow and open the menu you want to have,
wait until the 10 seconds are over, mtpaint comes up with the shot of the menu.
Hope it helps
Re: take a (quick) shot
Posted: Sat Jan 23, 2021 10:20 am
by HerrBert
I know about mtpaint -s and i'm using it as defaultscreenshot, which is way faster than ffmpeg.
This script is just about to grab a shot of the active window without clicking in tas or editing in mtpaint.
Last but not least it is an exercise for me...
Recent versions of mtpaint can be run by script. Maybe it is possible to crop the screenshot by commandline. I don't know if this can be done. Never tried it.
Re: take a (quick) shot
Posted: Sun Jan 24, 2021 5:42 pm
by rockedge
@HerrBert
Have you tried using 'scrot' for taking screenshots?
Code: Select all
scrot -s # select a window or full screen
scrot -d 1 # set a delay for 1 second for a full screenshot
Re: take a (quick) shot
Posted: Thu Jan 28, 2021 5:57 am
by cobaka
@rockedge asked:
Have you tried using 'scrot' for taking screenshots?
Cobaka: I'm using uPupBB32.
Code: Select all
#
# scrot --help
bash: scrot: command not found
# which scrot
#
Scrot does not appear to be part of the Puppy I have (or at least I don't know where to look for it).
Cobaka
Re: take a (quick) shot
Posted: Thu Jan 28, 2021 7:14 am
by MochiMoppel
HerrBert wrote: Sat Jan 23, 2021 10:20 amMaybe it is possible to crop the screenshot by commandline. I don't know if this can be done. Never tried it.
I tried and couldn't make it work. Crop is not the problem. Before applying the crop the crop area has to be selected. Mtpaint seems to have no way to select an area via input parameters. Selection is a hand job.
Re: take a (quick) shot
Posted: Thu Jan 28, 2021 2:01 pm
by HerrBert
scrot also not part of Slacko64 7.0...
@MochiMoppel
I've also tried some things with mtpaint without success, but it fails early at taking a screenshot via
Code: Select all
mtpaint --cmd -file/new screenshot create
Digging a bit deeper i found handbook for recent version of mtpaint at https://github.com/wjaguar/mtpaint_handbook
In chapter 10 there is:
10.5.1 The File Menu
New
The unnamed control is the image type radiobutton pack: "24 bit RGB", ...
In commandline mode, the "Grab Screenshot" option is not present.
so i guess we're out of luck...
Re: take a (quick) shot
Posted: Thu Jan 28, 2021 4:13 pm
by rockedge
Using the PPM search for and install scrot. It is not included in the the later Puppy's but easy to install, very small footprint, easy to use and script.
test in a terminal :
Code: Select all
individual window or full screen
scrot -s
Code: Select all
full window with time delay (seconds)
scrot -d 2
Code: Select all
name image like 2021-1-28_2560x1024_scrot.png and move to screenshots directory
scrot '%Y-%m-%d_$wx$h_scrot.png' -e 'mv $f ~/my-documents/screenshots
Code: Select all
Usage : scrot [OPTIONS]... [FILE]
Where FILE is the target file for the screenshot.
If FILE is not specified, a date-stamped file will be dropped in the
current directory.
See man scrot for more details
-h, --help display this help and exit
-v, --version output version information and exit
-b, --border When selecting a window, grab wm border too
-c, --count show a countdown before taking the shot
-d, --delay NUM wait NUM seconds before taking a shot
-e, --exec APP run APP on the resulting screenshot
-q, --quality NUM Image quality (1-100) high value means
high size, low compression. Default: 75.
For lossless compression formats, like png,
low quality means high compression.
-m, --multidisp For multiple heads, grab shot from each
and join them together.
-s, --select interactively choose a window or rectangle
with the mouse
-u, --focused use the currently focused window
-t, --thumb NUM generate thumbnail too. NUM is the percentage
of the original size for the thumbnail to be,
or the geometry in percent, e.g. 50x60 or 80x20.
-z, --silent Prevent beeping
SPECIAL STRINGS
Both the --exec and filename parameters can take format specifiers
that are expanded by scrot when encountered.
There are two types of format specifier. Characters preceded by a '%'
are interpreted by strftime(2). See man strftime for examples.
These options may be used to refer to the current date and time.
The second kind are internal to scrot and are prefixed by '$'
The following specifiers are recognised:
$f image path/filename (ignored when used in the filename)
$m thumbnail path/filename
$n image name (ignored when used in the filename)
$s image size (bytes) (ignored when used in the filename)
$p image pixel size
$w image width
$h image height
$t image format
$$ prints a literal '$'
\n prints a newline (ignored when used in the filename)
Example:
scrot '%Y-%m-%d_$wx$h_scrot.png' -e 'mv $f ~/images/shots/'
Creates a file called something like 2000-10-30_2560x1024_scrot.png
and moves it to your images directory.
This program is free software see the file COPYING for licensing info.
Copyright Tom Gilbert 2000
Email bugs to <scrot_sucks@linuxbrit.co.uk>
Re: take a (quick) shot
Posted: Thu Jan 28, 2021 6:31 pm
by HerrBert
@rockedge
May be worth to keep an eye on, but ATM installing 3 more dependencies on Slacko64 7.0 is not what i would call a small footprint...
Re: take a (quick) shot
Posted: Thu Jan 28, 2021 8:26 pm
by HerrBert
MochiMoppel wrote: Thu Jan 28, 2021 7:14 am
HerrBert wrote: Sat Jan 23, 2021 10:20 amMaybe it is possible to crop the screenshot by commandline. I don't know if this can be done. Never tried it.
I tried and couldn't make it work. Crop is not the problem. Before applying the crop the crop area has to be selected. Mtpaint seems to have no way to select an area via input parameters. Selection is a hand job.
Apart from crop there's also 'Resize canvas' which was my initial idea, but nothing helps due to not beeing able to take a shot in commandline mode.
Re: take a (quick) shot
Posted: Thu Mar 18, 2021 9:55 am
by wiak
rockedge wrote: Thu Jan 28, 2021 4:13 pm
Using the PPM search for and install scrot. It is not included in the the later Puppy's but easy to install, very small footprint, easy to use and script.
So, anyway, I just stumbled across this thread and noted that HerrBert didn't like the idea of using the wonderful scrot utility because it requires a couple of extra (small, I'd say) libs at least one of which may not be in some Pups.
Well... for more bang for your buck you could install the fantastic program weX (I say, fantastic, that's cos I wrote it, so just saying fantastic for amusement). What has that got to do with the screenshot issue you may ask?...
Well, weX is a pretty accurate, high resolution, X11 screen recorder program, plus can record audio only or webcam (video recorder with audio) or all of screen, webcam (in wee window at bottom right) and audio - or whatever combination of these you wish... It's a bit like Precord on steroids but equally small size being created using bash script and gtkdialog... Yeah, you say, but this thread isn't about capturing X11 so what has weX got to do with that? Well... as it happens weX uses a fork of scrot called 'scrox', which is basically scrot on steroids - actually it is only a few chunks of code added that allow scrox to be used by other programs (in this case weX) to select an area or window on the screen and report the coordinates for further processing. In other words, scrox is scrot, but with a couple of extra options added, so it obeys correctly all the same commands as normal scrot and pretty much same binary size and efficiency. Yeah, it is scrot pretty much so also needs these wee extra libs same as scrot but with just that few kB extra you also get weX screencast, audio, and webcam recorder included (and unlike for Simple Screen Recorder there are no qt libs required)! Now that, ladies and gentlemen, is value for money. Truth to tell, you can actually install scrox on its own (just as a directly compatible substitute for scrot), but why would you when you might as well add tiny wee bash/gtkdialog script weX usefully too? You can find both weX and scrox dotpets here:
viewtopic.php?p=1102#p1102
Note that weX will work on pretty much all recent pups. It should also work on many old ones but may need some config file modifications for that - if you have trouble getting it to work, just ask me and maybe I can help you overcome such difficulties. I don't expect you to have problems at all with scrox since that is just going to work (same as scrot) but notice that if you want to use weX then weX needs scrox (weX won't work with scrot, though having both scrot and scrox is fine - but why have both when scrox contains all of scrot anyway? - you can even make a symlink called scrot that points to scrox if some other program expects scrot to be present...).
Re: take a (quick) shot
Posted: Thu Mar 18, 2021 12:19 pm
by misko_2083
^Thanks for sharing Wiak.
HerrBert wrote: Thu Jan 28, 2021 8:26 pm
MochiMoppel wrote: Thu Jan 28, 2021 7:14 am
HerrBert wrote: Sat Jan 23, 2021 10:20 amMaybe it is possible to crop the screenshot by commandline. I don't know if this can be done. Never tried it.
I tried and couldn't make it work. Crop is not the problem. Before applying the crop the crop area has to be selected. Mtpaint seems to have no way to select an area via input parameters. Selection is a hand job.
Apart from crop there's also 'Resize canvas' which was my initial idea, but nothing helps due to not beeing able to take a shot in commandline mode.
Check out this old thread https://bbs.archlinux.org/viewtopic.php ... 47#p660547
Now the CPU hog issue is easy to fix and I would Print the output like this:
So that eval can be used to set the variables.
What's required is gcc and X development libtrary (Xlib) .
In debian it's libx11-dev.
Save it as xrectsel.c
Code: Select all
#include<stdio.h>
#include<stdlib.h>
#include<X11/Xlib.h>
#include<X11/cursorfont.h>
#include<unistd.h>
/* Select area
Needs Xlib, in Debian it's libx11-dev
compile with
gcc xrectsel.c -Wall -o xrectsel `pkg-config --cflags --libs x11`
https://bbs.archlinux.org/viewtopic.php?pid=660547#p660547
*/
int main(void)
{
int rx = 0, ry = 0, rw = 0, rh = 0;
int rect_x = 0, rect_y = 0, rect_w = 0, rect_h = 0;
int btn_pressed = 0, done = 0;
XEvent ev;
Display *disp = XOpenDisplay(NULL);
if(!disp)
return EXIT_FAILURE;
Screen *scr = NULL;
scr = ScreenOfDisplay(disp, DefaultScreen(disp));
Window root = 0;
root = RootWindow(disp, XScreenNumberOfScreen(scr));
Cursor cursor, cursor2;
cursor = XCreateFontCursor(disp, XC_cross);
cursor2 = XCreateFontCursor(disp, XC_crosshair);
XGCValues gcval;
gcval.foreground = XWhitePixel(disp, 0);
gcval.function = GXxor;
gcval.background = XBlackPixel(disp, 0);
gcval.plane_mask = gcval.background ^ gcval.foreground;
gcval.subwindow_mode = IncludeInferiors;
gcval.line_width = 2;
GC gc;
gc = XCreateGC(disp, root,
GCFunction | GCForeground | GCBackground | GCSubwindowMode | GCLineWidth ,
&gcval);
/* this XGrab* stuff makes XPending true ? */
if ((XGrabPointer
(disp, root, False,
ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync,
GrabModeAsync, root, cursor, CurrentTime) != GrabSuccess))
printf("couldn't grab pointer:");
if ((XGrabKeyboard
(disp, root, False, GrabModeAsync, GrabModeAsync,
CurrentTime) != GrabSuccess))
printf("couldn't grab keyboard:");
while (!done) {
// while (!done && XPending(disp)) {
// XNextEvent(disp, &ev);
if (!XPending(disp)) { usleep(1000); continue; } // fixes the 100% CPU hog issue in original code
if ( (XNextEvent(disp, &ev) >= 0) ) {
switch (ev.type) {
case MotionNotify:
/* this case is purely for drawing rect on screen */
if (btn_pressed) {
if (rect_w) {
/* re-draw the last rect to clear it */
XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h);
} else {
/* Change the cursor to show we're selecting a region */
XChangeActivePointerGrab(disp,
ButtonMotionMask | ButtonReleaseMask,
cursor2, CurrentTime);
}
rect_x = rx;
rect_y = ry;
rect_w = ev.xmotion.x - rect_x;
rect_h = ev.xmotion.y - rect_y;
if (rect_w < 0) {
rect_x += rect_w;
rect_w = 0 - rect_w;
}
if (rect_h < 0) {
rect_y += rect_h;
rect_h = 0 - rect_h;
}
/* draw rectangle */
XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h);
XFlush(disp);
}
break;
case ButtonPress:
btn_pressed = 1;
rx = ev.xbutton.x;
ry = ev.xbutton.y;
break;
case ButtonRelease:
done = 1;
break;
}
}
}
/* clear the drawn rectangle */
if (rect_w) {
XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h);
XFlush(disp);
}
rw = ev.xbutton.x - rx;
rh = ev.xbutton.y - ry;
/* cursor moves backwards */
if (rw < 0) {
rx += rw;
rw = 0 - rw;
}
if (rh < 0) {
ry += rh;
rh = 0 - rh;
}
XCloseDisplay(disp);
printf("X=%i\nY=%i\nWIDTH=%i\nHEIGHT=%i\n", rx, ry, rw, rh);
return EXIT_SUCCESS;
}
Compile with
Code: Select all
gcc xrectsel.c -Wall -o xrectsel `pkg-config --cflags --libs x11`
Now run and select area when the cursor changes.
Code: Select all
./xrectsel
X=534
Y=391
WIDTH=403
HEIGHT=331
Or with eval
Code: Select all
eval $(./xrectsel)
echo $X
564
echo $Y
305