rbreaves / kinto

Mac-style shortcut keys for Linux & Windows.
http://kinto.sh
GNU General Public License v2.0
4.37k stars 213 forks source link

Script to mimic macOS screenshot shortcuts #604

Open RedBearAK opened 2 years ago

RedBearAK commented 2 years ago

I figured out how to use the xkeysnail launch() command option and combined it with runuser to run external scripts as my user, triggered with shortcuts. But at the moment I'm hard coding my username into the launched file names, which is obviously not portable.

What would be your recommended method for setting the username in a variable and then using that variable within the kinto.py config file? As usual with python it seems there are multiple methods, and I'm not clear on whether it will return my username or "root" since xkeysnail is running with sudo. In the bash scripts it's as simple as calling $USER.

I'm working on building up a set of scripts that mimic the Cmd+Shift+3/4/5 screenshot functions of macOS. End goal is something that will adapt to most DEs by using the native/default screenshot tool of each environment, or whatever is available, or produce a system notification with libnotify to tell the user to install a screenshot tool.

Only major issue so far is that running a script via runuser somehow completely breaks string comparisons in bash if statement tests, requiring a second layer of scripts that literally just call the main script while passing in an argument. It's very strange and I couldn't find a way around the issue after spending hours googling for solutions.

rbreaves commented 2 years ago

Python can run shell commands easily enough so yea $USER would work.

RedBearAK commented 2 years ago

@rbreaves

From within the config file I was unable to get any usable information. Even the __file__ path refers to some "init" python file in dist-packages. The user comes back as root, no matter what method is used. I gave up on trying to parse it out of the xkeysnail.service file. So in the end I am using manually set python variables for path and user.

_user = 'USER_GOES_HERE'
_path = '/home/' + _user + '/.config/kinto/scripts/'

The good news is that I figured out what I was doing wrong with passing in arguments through runuser with the launch() command, and therefore I don't need the second layer of shell scripts. Just the one script can do everything.

In one sense this ready, if you happen to have gnome-screenshot installed. To test the beep as currently implemented, you'll need to install libasound2-dev and then pip3 install beepy (do it the other way and you may get an error compiling the simpleaudio module). Then just drop the scripts folder from the attached zip archive into your ~/.config/kinto folder, make sure the scripts are all executable, and paste this code at the beginning of your General GUI block (obviously change where it says USER_GOES_HERE to your username to make it work), and restart Kinto:

# Static variables for path and user, manually set: 
_user = 'USER_GOES_HERE'
_path = '/home/' + _user + '/.config/kinto/scripts/'

# None referenced here originally
# - but remote clients and VM software ought to be set here
# These are the typical remaps for ALL GUI based apps
define_keymap(lambda wm_class: wm_class.casefold() not in remotes,{
    ####################################################################################################
    ############################   START OF SCREENSHOT LAUNCH SHORTCUTS   ##############################
    ####################################################################################################
    K("RC-Shift-M-b"): launch(
        ["runuser", "-l", _user, "-c", 
        _path + "beep.py"]),                    # launch beepy error beep
    K("RC-Shift-KEY_3"): launch(
        ["runuser", "-l", _user, "-c", 
        _path + "screenshot.sh screen"]),       # Cmd+Shift+3 screenshot: entire screen
    K("RC-Shift-KEY_4"): launch(
        ["runuser", "-l", _user, "-c", 
        _path + "screenshot.sh area"]),         # Cmd+Shift+4 screenshot: select area
    K("M-RC-Shift-KEY_4"): launch(
        ["runuser", "-l", _user, "-c", 
        _path + "screenshot.sh window"]),       # Option+Cmd+Shift+4 screenshot: window with focus
    K("RC-Shift-KEY_5"): launch(
        ["runuser", "-l", _user, "-c", 
        _path + "screenshot.sh show-app"]),     # Cmd+Shift+5 screenshot: show screenshot tool (app)
    ####################################################################################################
    ############################    END OF SCREENSHOT LAUNCH SHORTCUTS    ##############################
    ####################################################################################################
    # 

That's it.

There are checks in the screenshot script that will stop it from running if your shell $USER variable is root, unset, or an invalid user on your system. So if you don't fix the user nothing should happen.

scripts_2022-01-18.zip

To test: Open your ~/Pictures/Screenshots folder, (script will make one if it doesn't exist) and watch new PNG files being created when you use any of these shortcuts (except the one that brings up the tool):

Cmd+Shift+3 (screen)
Cmd+Shift+4 (area)
Option+Cmd+Shift+4 (window)
Cmd+Shift+5 (show screenshot tool)

And then there's Option+Cmd+Shift+B to test the beep. Don't know yet if there's a way to emulate the macOS toggle between area and window screenshots with the space bar.

I copied the distro name check and the dename.sh script from the Kinto installer, so between those and just testing to see if popular screenshot tools are installed it should be relatively easy to make the screenshot script auto-adapt to different systems. Maybe with accommodations for people with a favorite screenshot tool like Flameshot. If there's something available that would do the window highlighting like macOS does, that would be preferred.

Let me know if you get a chance to take a look at this. It seemed logical to put the scripts in the Kinto config folder and keep everything together, but the path can be easily changed if you want to go a different way.

rbreaves commented 2 years ago

Interesting.. not sure how gnome-screenshot compares to flameshot but I’ve been liking flameshot a lot lately..

RedBearAK commented 2 years ago

@rbreaves

Interesting.. not sure how gnome-screenshot compares to flameshot but I’ve been liking flameshot a lot lately..

Even more interesting, when they jumped from v0.10.x to v11.0.0 (just a few days ago!) they've apparently done a major revamp on the CLI setup and the ability to run Flameshot as a "one off", which I assume refers to doing something like what I'm doing; invoking it from a script with CLI options without relying on interacting with a GUI or a running background service.

I installed the AppImage yesterday and linked it with ~/.local/bin/flameshot, so it should behave the same from CLI as when installed via other methods. I figure with its sophisticated options it's probably one of the more popular "after-market" choices to install, for those who don't just default to using whatever came with their Distro/DE.

You made certain logical choices when building the installer for Kinto, so I wonder if you have any quick observations on the simplest way to approach the logic for figuring out which binary to default to if there is no user customization choice set in the script:

If distro, then if DE, then if $(which binary), do 

If DE, then if distro, then if $(which binary), do

If $(which binary), do [ and then only use distro and/or DE for special cases ]

or, If no custom choice trigger set, just iterate through list of known binaries by rough "distro popularity" until one works

I'm leaning toward the last one because it's simple. But since one of the options (Cmd+Shift+5) is to actually bring up the tool for interactive use, maybe at least testing for DE and prioritizing what would usually be the default for that DE would be best? I do like it when things blend in nicely.

I just want this to be something that for most Linux users would "just work" automatically immediately after a clean install of Kinto, by taking into account most of the known default screenshot tools. Sort of like what I did with the Finder mods, covering all the GUI file managers I could find. With a simple customization trigger at the top of the script, or possibly in a separate "config" file (or maybe even emanating from within the Kinto config file itself through passing another python variable) to switch to another tool and/or image format if so desired.

RedBearAK commented 2 years ago

@rbreaves

Flameshot is obviously something that was meant primarily for mouse usage. It's quite a powerful tool for interactive use, but kind of overkill for one-off CLI usage. Even with the revamped CLI options in v11.0 there is no apparent way to suppress the notifications it wants to pop up, and the notifications come up with the "prohibitory symbol" (circle with slash), as did the notifications from Spectacle. So somehow the environment is still not quite right and they can't find the right icons.

Another thing missing from Flameshot, surprisingly, is any kind of "window" screenshot option. Spectacle does have a couple of different "window" options. But using the area/region options in either one brings up the whole GUI and is not a simple process, whereas getting GNOME Screenshot to do an area selection results in a non-interactive immediate saving of the screenshot with the defined filename. One of the main issues is that both Spectacle and Flameshot present me with save dialogs with a blank filename, which is weird. I don't think that's supposed to happen, but it happens even when I start the apps from a regular app launcher, without feeding them a "path" or "file" CLI argument. Both are Snap packages.

I'm leaning toward the idea that the only way to cleanly mimic the smooth simplicity and automatic "don't think about it" nature of the macOS 3/4/5 screenshot options is to just default to GNOME Screenshot. The GUI is also the simplest, and closest to the simple GUI tool that current macOS presents when you use Cmd+Shift+5. And the GUI doesn't show me a blank filename when saving.

Since other screenshot tools like Spectacle and Flameshot will usually have their own unrelated system shortcuts assigned, or are already tied to the Print Screen key, or are mainly used via mouse from the app indicator, it seems like just standardizing on GNOME Screenshot (or an even simpler tool if one can be found) might not be the worst idea. It shouldn't interfere in any way with the user's other screenshot tools or their workflows with those tools.

Do you have any objection to going in this direction? It would still be possible to let the user edit a variable and redirect the script to one of the alternative binaries. It just doesn't feel right to make anything but GNOME Screenshot the default. Or, as I said, something even simpler, if it exists.

rbreaves commented 2 years ago

I dunno.. this works fine for my flameshot.. also configured it to get rid of a bunch things I'd never use.. all the many different circles.. I mostly just use the Cmd+Shift+4 combo myself.

image

rbreaves commented 2 years ago

Personally I like the additional level of interaction when doing selection based screenshots.. I can immediately decide to use my clipboard or the file system (majority of the time I just want it in the clipboard, not my file system). This is something that annoys me with macOS as it always forces me to view it in a preview window before I can get it into my clipboard..

rbreaves commented 2 years ago

@RedBearAK I am fine with attempting to use whatever the default screenshot utility is there as far as Kinto is concerned - but for Sorun.me I will likely undo that decision and use flameshot.. Also if flameshot is already installed.. I may just want Kinto to prioritize it.

If there is no utility at all I am not sure I want to do anything at all.. I understand the impetus to, but that's getting into Sorun.me realm. Kinto currently only installs dependencies vs nice to have.

RedBearAK commented 2 years ago

@rbreaves

This is something that annoys me with macOS as it always forces me to view it in a preview window before I can get it into my clipboard..

You may want to jump on your Mac and try out the Cmd+Shift+5 shortcut that seems to be new since Mojave. It brings up a selection area and a little toolbar near the bottom of the screen (for me). Kind of difficult to see if you have dark mode enabled, actually, but it's there. There is an "Options" drop-down/pop-up menu on the screenshot toolbar, and one of the options for where to send the screenshot is "Clipboard". If you change the selection from "Desktop" or the other choices, the new setting seems to be retained on subsequent invocations, and it also seems to change the output choice when you use Cmd+Shift+3 or 4. They will now go into the clipboard instead of my Desktop where Hazel would normally sweep them into my Screenshots folder.

So, one less headache for you on macOS? I don't happen to usually do much of anything with most screenshots so the default behavior never bothered me too much.

Shouldn't be too much of a big deal to emulate this customizability in the screenshot script, of going into the clipboard or elsewhere if the user prefers.

If there is no utility at all I am not sure I want to do anything at all.. I understand the impetus to, but that's getting into Sorun.me realm. Kinto currently only installs dependencies vs nice to have.

Yeah, I can understand that point of view. I was thinking of just showing a notification when no suitable tool can be found, it would be quite easy. Maybe copy a text file into the Pictures/Screenshots folder explaining how to make it work by installing binary X, Y, or Z, and open the folder with xdg-open, which should just open it in the default file manager.

rbreaves commented 2 years ago

Oh lol.. well I sorta stopped caring about macOS after Mojave and it no longer gets updates.. so.. I am actually a bit disconnected with the latest versions of macOS tbh.

RedBearAK commented 2 years ago

@rbreaves

Well that shortcut already works on Mojave. I don't know exactly which model you have but the OpenCore Legacy Patcher supports models going back to 2007/2008, to bring them up to Big Sur or Monterey. Anything 2012 or later should work even without additional patches after install. Big Sur actually seems like a pretty stable release.

OCLP just came out with a new release with further improvements. I'll be testing it on my 2011 17-inch MBP shortly. It's actually easier to work with than the earlier dosdude1 patched installers that I used to get Mojave working. I highly recommend it. It's basically turning real Macs into hackintoshes with vanilla installs of macOS on top of a modified EFI boot loader.

https://github.com/dortania/OpenCore-Legacy-Patcher

rbreaves commented 2 years ago

@RedBearAK Oh my macbooks still get updates if I want them - what I meant is the Mojave no longer gets security updates by Apple & that Mojave is pretty much the last macOS release that I actually liked. I really don't like the design direction Apple went in at all.

RedBearAK commented 2 years ago

@rbreaves

Oh my macbooks still get updates if I want them - what I meant is the Mojave no longer gets security updates by Apple & that Mojave is pretty much the last macOS release that I actually liked. I really don't like the design direction Apple went in at all.

Oh, I gotcha. Yeah, it wasn't my favorite at first, the changes. Really since El Capitan, which was excellent. I used that until it was way out of date. But pretty much everything is starting to look like Big Sur lately, even Windows 11, shockingly. And there is only so long I can tolerate being out of date with software. My Mac App Store application updates on the patched Mojave haven't worked for quite some time, probably a couple of years at this point. I don't know how to fix it besides a clean install, so I figure it's a good time to just go ahead with OCLP and Big Sur wherever I can. It's basically the same as GNOME 4x. It's different, but I think you might be surprised at how quickly you could get used to it. I was.

We all have our own path. It's only thanks to Kinto that I can comfortably spend a significant portion of my time in Linux as I juggle upgrading all the Macs in the house. Pretty handy.

RedBearAK commented 2 years ago

@rbreaves

Good news. I'm more impressed with Flameshot than I was a couple of days ago.

Looks like all the strange issues I was having with Flameshot were just teething problems with the Snap package after the major version change, and probably had nothing to do with the runuser environment. Removed the Snap and installed the Ubuntu DEB instead and it is behaving much, MUCH better.

The "--path" argument actually does have an effect, at least with the "gui" mode. There are no more blank file names in the save dialogs even without a path/filename being passed, and the notification pop-ups have the correct Flameshot icon instead of a prohibitory sign icon. So in a sense it's even better behaved than GNOME Screenshot, which doesn't accept the path/file argument when you invoke the GUI. I hope the Flameshot devs will add the "--path" option as a valid option for the "launcher" mode as well. I'll ask.

This is interesting, if you pass the "--path" argument when invoking the "gui" option, Flameshot will immediately save the file when you hit "Enter" after making your selection (and presumably after doing whatever annotations you want) and won't respond to Ctrl+S the way it usually does. Because you've already fed it the path/filename, so the save dialog would be redundant. In other words, it becomes a faster operation and basically identical to the way it works in macOS (except you don't need to hit "Enter" on macOS, but you also don't have options to annotate the screenshot).

Same seems to happen when passing the "gui --clipboard" CLI option instead of "gui --path". Although that actually starts up Flameshot and puts the indicator in the top bar, which other CLI options don't. Most users with Flameshot will already have it running in the background, so that's probably not harmful, but seems like a bug contrary to the intended new "one off" nature of the CLI options.

O. M. Freakin' G. I just tried combining the --clipboard and --path options and it actually worked. In other words when I hit "Enter" after making the selection, it saved a file AND ALSO put it in the clipboard at the same time. I'll have to run through all the CLI options and see if that will work with all the modes.

I should be able to give you a new test version of the screenshot script set up to default to Flameshot (and clipboard as destination, to suit your preference) pretty soon. Except for the completely missing "window" option (assigned to Opt+Cmd+Shift+4 as the alternative to "area/region" selection on Cmd+Shift+4) which will try to use gnome-screenshot if available, and maybe go so far as to attempt to use Spectacle if gnome-screenshot is not installed. Otherwise it will show a notification that Flameshot doesn't have a window option.

rbreaves commented 2 years ago

Except for the completely missing "window" option (assigned to Opt+Cmd+Shift+4 as the alternative to "area/region" selection on Cmd+Shift+4)

Glad that you are liking it more now. Not sure what you mean by missing window option, meaning screen shot of just an app or the area/region? The CLI option gui seems to provide the selection thing just fine for me, but I don't ever try to screenshot just an app window by itself.

I also have configured most of the options to not appear, although it is nice that it provides as much as it does. I wish the imgur had more confirmations involved..

RedBearAK commented 2 years ago

@rbreaves

Yeah, you know how in macOS, if you hit the spacebar after pressing Cmd+Shift+4, it toggles from a crosshair selection tool into a "camera" cursor that then highlights any window you hover over with a light blue overlay? You can toggle back and forth between these modes with the spacebar until you actually make your selection.

Spectacle and GNOME Screenshot have options for selecting a "window" like this. I have used it many times, it's a simple way to get a clean screenshot of just a single window without including any background or cutting anything off the window accidentally. I've often found it very handy when I didn't want a full screenshot or a "window with other context" kind of screenshot.

Flameshot, as far as I can tell, doesn't have an equivalent. At least in v11.0.0. But I assume also in the earlier versions. And I find that pretty odd.

I tried to look into the GUI circles but that seems to be mainly annotation tools and other editing options. No "window" selector tool. There certainly don't appear to be any relevant CLI options.

I'm sure if there's an easy way to note the X/Y coordinates and dimensions of the currently focused window when I invoke the shortcut, I could feed that to Flameshot to mimic a "window" selection, but at the moment I don't know how to approach making that work. Much easier just to use a different binary that supports "window" selection.

Spectacle actually has a couple different "window" options, "window with focus" and "window under mouse". The one equivalent to macOS is actually "window under mouse". So I'll have to look into that.

Oh my, I just noticed there is an "--accept-on-select" option for the Flameshot "gui" argument. That would make a rectangle selection screenshot even faster/simpler and closer to the macOS experience, without needing the "Enter" key. But another thing some users would probably want the option to disable, so I'll keep that in mind.

I'll also have to look up how the "upload" stuff works, and see if that can be added as a simple customization option.

RedBearAK commented 2 years ago

@rbreaves

This version of the screenshot script is set up to default to Flameshot and clipboard only. GNOME Screenshot or Spectacle are used as a fallback for the "window" capture mode (Opt+Cmd+Shift+4, passing "window" to script).

Cmd+Shift+3: Desktop (all monitors)
Opt+Cmd+Shift+3: Single screen
Cmd+Shift+4: Area selection
Opt+Cmd+Shift+4: Window with focus
Cmd+Shift+5: Bring up the screenshot tool
Opt+Cmd+Shift+5: Open the screenshot config file (NOT FINISHED YET)

It's not a perfect solution, you may see notifications of files being written to /tmp when you're using the "clipboard" option in the user config section of the script. But the files get immediately deleted. If you change preferred_output to "both" it will save the files and also put the image in the clipboard.

screenshot_script_2022-01-25.zip

The key maps and launch commands below won't work unless you convert to run xkeysnail in user mode, but the original runuser commands from earlier should still work with the script just fine. Bonus line at the end to open a default file manager window in the user's home folder with Opt+Cmd+Space.

# needs "import os"
_cwd = os.getcwd()

_path = _cwd + '/.config/kinto/scripts/'
    K("RC-Shift-M-b"):      launch([_path + "beep.py", "error"]),               # launch beepy error beep
    K("RC-Shift-KEY_3"):    launch([_path + "screenshot.sh", "desktop"]),       # Cmd+Shift+3       # screenshot: entire desktop (all attached displays, macOS default)
    K("M-RC-Shift-KEY_3"):  launch([_path + "screenshot.sh", "screen"]),        # Opt+Cmd+Shift+3   # screenshot: screen with focus
    K("RC-Shift-KEY_4"):    launch([_path + "screenshot.sh", "area"]),          # Cmd+Shift+4       # screenshot: select area
    K("M-RC-Shift-KEY_4"):  launch([_path + "screenshot.sh", "window"]),        # Opt+Cmd+Shift+4   # screenshot: window with focus
    K("RC-Shift-KEY_5"):    launch([_path + "screenshot.sh", "show-app"]),      # Cmd+Shift+5       # screenshot: show screenshot tool (app)
    K("M-RC-Shift-KEY_5"):  launch([_path + "screenshot.sh", "config"]),        # Opt+Cmd+Shift+5   # open screenshot config file
    K("M-RC-Space"):        launch(["xdg-open", _cwd]),                         # Open default file manager at home folder
RedBearAK commented 2 years ago

@rbreaves

Update on screenshot script:

I've looked around but haven't found any other screenshot utilities for Linux that A) have a GUI mode, and B) have a relatively simple GUI interface, and C) don't also have screencasting or other features, and D) aren't apparently dead projects. (Example: Shutter).

There is maim but that's a CLI only replacement fork of scrot, which isn't maintained anymore. Nothing else seems to be anywhere close to similar to the simple screenshot tool used by macOS, and the CLI tools have no GUI to present to the user, so I think it's not really appropriate to integrate any of them.

So I'm sticking with Flameshot, GNOME Screenshot, and KDE Spectacle, which I expect to cover a rather large percentage of Linux distros' default screenshot tools, plus all of the Linux users who have installed Flameshot for themselves. And if they aren't installed, they can be installed on most distros.

Unless you have any other suggestion I'm not planning on adding any other choice to the screenshot script. If none of the binaries are found with command -v it will throw an error and ask the user to install any one of them to make it work.

Still refining the logic to take a guess at the "best" one to default to if no preference is specified and multiple binaries are found. Right now it mainly defaults to Flameshot, then GNOME Screenshot, then Spectacle.

GNOME Screenshot can't do "single screen" (only "all monitors"), and Flameshot can't do "window", so they fall back on one of the others to perform those actions, and if a suitable tool is not found the user will again get an error and advice to install one of the other tools to make that particular function work. This will only be seen if the user attempts to use Opt+Cmd+Shift+3 or Opt+Cmd+Shift+4 to pass "screen" or "window" to the script.

I'm discussing with the Flameshot devs some issues that can cause unexpected behavior when running their CLI options with a Flameshot daemon already in memory, or with leaving a daemon running if the user didn't have one running, and I hope there will be some solutions to that in the future. They have been somewhat receptive of and understanding of the problem(s) with the way they have implemented some internal logic. Most users of Flameshot will probably never notice, if they typically keep Flameshot running, and don't have a certain setting enabled which is normally disabled by default.

The "config" option is active. All it does at the moment is tell the user to edit the user options in the script and then opens the folder with xdg-open. But I'm thinking of putting the user options in a separate text file that will hang out in the main Kinto directory and get sourced by the script.

screenshot_script_2022-01-26.zip

RedBearAK commented 2 years ago

Split out the user preferences into a separate file and implemented logic to more cleanly deal with the clipboard-only output option. No more temporary files.

Note to self, remember to implement camera sound playback for Flameshot and Spectacle.

screenshot_script_and_prefs_2022-01-27.zip

RedBearAK commented 2 years ago

Updated to use play_sound.py to play the camera-shutter sound for Flameshot and Spectacle, for a more uniform experience between the three tools. The sound can be disabled for Flameshot and Spectacle in the user prefs file, but it's built into GNOME Screenshot and there are no CLI options to turn it off.

scripts_and_sounds_2022-01-29.zip