New: i3 configs
This commit is contained in:
parent
b7db3777a0
commit
183de47980
|
@ -4,7 +4,8 @@
|
||||||
# Additional dependencies:
|
# Additional dependencies:
|
||||||
# - Python's pillow library
|
# - Python's pillow library
|
||||||
# - pip install --user pillow-avif-plugin # Until PIL merges avif support
|
# - pip install --user pillow-avif-plugin # Until PIL merges avif support
|
||||||
# - grim
|
# - grim on wayland or scrot on x11
|
||||||
|
# - slurp on wayland slop on x11
|
||||||
# - swappy
|
# - swappy
|
||||||
import argparse, os, sys, time, re, shutil, tarfile, tempfile, pillow_avif
|
import argparse, os, sys, time, re, shutil, tarfile, tempfile, pillow_avif
|
||||||
from subprocess import run, Popen, PIPE, DEVNULL
|
from subprocess import run, Popen, PIPE, DEVNULL
|
||||||
|
@ -15,20 +16,46 @@ from typing import *
|
||||||
|
|
||||||
# Global constants
|
# Global constants
|
||||||
RELATIVE_DIR = Path("Pictures/screenshots_wayland") # Default save directory
|
RELATIVE_DIR = Path("Pictures/screenshots_wayland") # Default save directory
|
||||||
DIR = Path.home()/RELATIVE_DIR
|
DIR = Path.home() / RELATIVE_DIR
|
||||||
|
|
||||||
DIMENSIONS_REGEX = "([0-9]+),([0-9]+) ([0-9]+)x([0-9]+)"
|
DIMENSIONS_REGEX = "([0-9]+),([0-9]+) ([0-9]+)x([0-9]+)"
|
||||||
|
SLOP_REGEX = "([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+)"
|
||||||
EXTENSION_REGEX = "\.([A-z0-9]+)$"
|
EXTENSION_REGEX = "\.([A-z0-9]+)$"
|
||||||
ORIGINAL_REGEX = "([0-9]+(_[0-9]{0,3})?)\.png"
|
ORIGINAL_REGEX = "([0-9]+(_[0-9]{0,3})?)\.png"
|
||||||
EDIT_REGEX = "([0-9]+(_[0-9]{0,3})?)_edit_([0-9]+)" + EXTENSION_REGEX
|
EDIT_REGEX = "([0-9]+(_[0-9]{0,3})?)_edit_([0-9]+)" + EXTENSION_REGEX
|
||||||
|
|
||||||
DS_BG_LIGHT = 'white'
|
DS_BG_LIGHT = "white"
|
||||||
DS_SHADOW_LIGHT = 'black'
|
DS_SHADOW_LIGHT = "black"
|
||||||
DS_BG_DARK = '#d3869b'
|
DS_BG_DARK = "#d3869b"
|
||||||
DS_SHADOW_DARK = 'black'
|
DS_SHADOW_DARK = "black"
|
||||||
|
|
||||||
DEFAULT_EDIT_QUALITY = 50
|
DEFAULT_EDIT_QUALITY = 50
|
||||||
DEFAULT_EDIT_EXTENSION = 'avif'
|
DEFAULT_EDIT_EXTENSION = "avif"
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenshotDimensions:
|
||||||
|
def __init__(self, x, y, w, h):
|
||||||
|
self.x = int(x)
|
||||||
|
self.y = int(y)
|
||||||
|
self.w = int(w)
|
||||||
|
self.h = int(h)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_string(self, s: str):
|
||||||
|
s = s.strip()
|
||||||
|
if m := re.fullmatch(DIMENSIONS_REGEX, s):
|
||||||
|
return self(m[1], m[2], m[3], m[4])
|
||||||
|
elif m := re.fullmatch(SLOP_REGEX, s):
|
||||||
|
return self(m[3], m[4], m[1], m[2])
|
||||||
|
|
||||||
|
raise Exception(f"`{s}` does not match pattern {DIMENSIONS_REGEX}")
|
||||||
|
|
||||||
|
def as_grim(self) -> str:
|
||||||
|
return f"{self.x},{self.y} {self.w}x{self.h}"
|
||||||
|
|
||||||
|
def as_scrot(self) -> str:
|
||||||
|
return f"{self.x},{self.y},{self.w},{self.h}"
|
||||||
|
|
||||||
|
|
||||||
# Returns a path to an unused screenshot in DIR
|
# Returns a path to an unused screenshot in DIR
|
||||||
def get_sceenshot_path() -> Path:
|
def get_sceenshot_path() -> Path:
|
||||||
|
@ -40,6 +67,7 @@ def get_sceenshot_path() -> Path:
|
||||||
else:
|
else:
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
||||||
# Returns a free path to the last screenshot in DIR
|
# Returns a free path to the last screenshot in DIR
|
||||||
# (original_path, new_edit_path)
|
# (original_path, new_edit_path)
|
||||||
#
|
#
|
||||||
|
@ -59,18 +87,38 @@ def get_edit_path(ext: str) -> (Path, Path):
|
||||||
|
|
||||||
return DIR / originals[-1], DIR / f"{latest}_edit_{new_index}.{ext}"
|
return DIR / originals[-1], DIR / f"{latest}_edit_{new_index}.{ext}"
|
||||||
|
|
||||||
|
|
||||||
# Copies the image to the wayland clipboard
|
# Copies the image to the wayland clipboard
|
||||||
def copy_to_clipboard(pic: Path):
|
def copy_to_clipboard(pic: Path):
|
||||||
with open(pic, 'r') as img:
|
# TODO: xcompatability
|
||||||
run(["wl-copy"], stdin=img, timeout=4)
|
try:
|
||||||
|
if "wayland" in os.environ["XDG_SESSION_TYPE"]:
|
||||||
|
with open(pic, "r") as img:
|
||||||
|
run(["wl-copy"], stdin=img, timeout=4)
|
||||||
|
return
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
run(
|
||||||
|
["xclip", "-selection", "clipboard", "-t", "image/png", "-i", str(pic)],
|
||||||
|
timeout=4,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Interactively gets user to select an area of the screen
|
# Interactively gets user to select an area of the screen
|
||||||
# String matches regex /[0-9]+,[0-9]+ [0-9]+x[0-9]+/
|
def select_area() -> ScreenshotDimensions:
|
||||||
# Example: 287,526 474x369
|
try:
|
||||||
def select_area() -> str:
|
if "wayland" in os.environ["XDG_SESSION_TYPE"]:
|
||||||
slurp = run(["slurp"], text=True, stdout=PIPE)
|
slurp = run(["slurp"], text=True, stdout=PIPE)
|
||||||
slurp.check_returncode()
|
slurp.check_returncode()
|
||||||
return slurp.stdout.strip()
|
return ScreenshotDimensions.from_string(slurp.stdout)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
slop = run(["slop"], text=True, stdout=PIPE)
|
||||||
|
slop.check_returncode()
|
||||||
|
return ScreenshotDimensions.from_string(slop.stdout)
|
||||||
|
|
||||||
|
|
||||||
# Adds drop-shadow to an image. If `img` and `save` are the same path, the image
|
# Adds drop-shadow to an image. If `img` and `save` are the same path, the image
|
||||||
# is overwritten
|
# is overwritten
|
||||||
|
@ -79,26 +127,39 @@ def add_drop_shadow(img: Path, save: Path, back_color: str, shadow_color: str):
|
||||||
mode = img.mode
|
mode = img.mode
|
||||||
|
|
||||||
border_width = max(img.size) // 20 # 5% of larger dim
|
border_width = max(img.size) // 20 # 5% of larger dim
|
||||||
width = img.size[0] + border_width*2
|
width = img.size[0] + border_width * 2
|
||||||
height = img.size[1] + border_width*2
|
height = img.size[1] + border_width * 2
|
||||||
|
|
||||||
shadow = Image.new(mode, img.size, color=shadow_color)
|
shadow = Image.new(mode, img.size, color=shadow_color)
|
||||||
canvas = Image.new(mode, (width, height), color=back_color)
|
canvas = Image.new(mode, (width, height), color=back_color)
|
||||||
|
|
||||||
canvas.paste(shadow, box=(border_width, int(border_width*1.16)))
|
canvas.paste(shadow, box=(border_width, int(border_width * 1.16)))
|
||||||
canvas = canvas.filter(GaussianBlur(border_width // 4))
|
canvas = canvas.filter(GaussianBlur(border_width // 4))
|
||||||
|
|
||||||
canvas.paste(img, box=(border_width, border_width))
|
canvas.paste(img, box=(border_width, border_width))
|
||||||
|
|
||||||
canvas.save(save, optimize=True)
|
canvas.save(save, optimize=True)
|
||||||
|
|
||||||
# Uses grim for wayland to take a screenshot. Default to full screen without
|
|
||||||
# dims. exact_dims must match a slurp regex
|
# Uses grim for wayland, scropt for x to take a screenshot. Default to full
|
||||||
def take_screenshot(path, exact_dims=None):
|
# screen without dims. exact_dims must match a slurp regex
|
||||||
|
def take_screenshot(path, exact_dims: ScreenshotDimensions = None):
|
||||||
|
try:
|
||||||
|
if "wayland" in os.environ["XDG_SESSION_TYPE"]:
|
||||||
|
if exact_dims is not None:
|
||||||
|
run(["grim", "-g", exact_dims.as_grim(), path]).check_returncode()
|
||||||
|
else:
|
||||||
|
run(["grim", path]).check_returncode()
|
||||||
|
return
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# x11 version
|
||||||
if exact_dims is not None:
|
if exact_dims is not None:
|
||||||
run(["grim", "-g", exact_dims, path]).check_returncode()
|
run(["scrot", "-a", exact_dims.as_scrot(), "-F", path]).check_returncode()
|
||||||
else:
|
else:
|
||||||
run(["grim", path]).check_returncode()
|
run(["scrot", "-F", path]).check_returncode()
|
||||||
|
|
||||||
|
|
||||||
# Takes a screenshot as specified by args
|
# Takes a screenshot as specified by args
|
||||||
def take_subcommand(args):
|
def take_subcommand(args):
|
||||||
|
@ -120,6 +181,7 @@ def take_subcommand(args):
|
||||||
if args.file is not None:
|
if args.file is not None:
|
||||||
shutil.copyfile(save_path, args.file)
|
shutil.copyfile(save_path, args.file)
|
||||||
|
|
||||||
|
|
||||||
# Applies an edit to the latest screenshot
|
# Applies an edit to the latest screenshot
|
||||||
def edit_subcommand(args):
|
def edit_subcommand(args):
|
||||||
og_path, edit_path = get_edit_path(args.extension)
|
og_path, edit_path = get_edit_path(args.extension)
|
||||||
|
@ -148,6 +210,7 @@ def edit_subcommand(args):
|
||||||
if args.file is not None:
|
if args.file is not None:
|
||||||
shutil.copyfile(edit_path, args.file)
|
shutil.copyfile(edit_path, args.file)
|
||||||
|
|
||||||
|
|
||||||
# Saves `DIR` into a tar file
|
# Saves `DIR` into a tar file
|
||||||
def archive_subcommand(args):
|
def archive_subcommand(args):
|
||||||
# Get the list of images to backup
|
# Get the list of images to backup
|
||||||
|
@ -161,16 +224,17 @@ def archive_subcommand(args):
|
||||||
|
|
||||||
# Write compressed pictures to tmpdir with progress bar
|
# Write compressed pictures to tmpdir with progress bar
|
||||||
TMP_DIR = tempfile.mkdtemp()
|
TMP_DIR = tempfile.mkdtemp()
|
||||||
ext = f'.{args.extension}'
|
ext = f".{args.extension}"
|
||||||
count = len(pics)
|
count = len(pics)
|
||||||
|
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
f"Compressing {count} images into {ext} @ quality {args.quality}\n")
|
f"Compressing {count} images into {ext} @ quality {args.quality}\n"
|
||||||
sys.stdout.write(f'Progress: 0/{count}')
|
)
|
||||||
|
sys.stdout.write(f"Progress: 0/{count}")
|
||||||
|
|
||||||
for i, pic in enumerate(pics):
|
for i, pic in enumerate(pics):
|
||||||
og = DIR/pic
|
og = DIR / pic
|
||||||
out = TMP_DIR/pic.with_suffix(ext)
|
out = TMP_DIR / pic.with_suffix(ext)
|
||||||
|
|
||||||
with Image.open(og) as img:
|
with Image.open(og) as img:
|
||||||
img.save(out, quality=args.quality, method=6, optimize=True)
|
img.save(out, quality=args.quality, method=6, optimize=True)
|
||||||
|
@ -178,20 +242,21 @@ def archive_subcommand(args):
|
||||||
stat = os.stat(og)
|
stat = os.stat(og)
|
||||||
os.utime(out, times=(stat.st_atime, stat.st_mtime))
|
os.utime(out, times=(stat.st_atime, stat.st_mtime))
|
||||||
|
|
||||||
sys.stdout.write(f'\rProgress: {i+1}/{count}' + ' ' * 40)
|
sys.stdout.write(f"\rProgress: {i+1}/{count}" + " " * 40)
|
||||||
|
|
||||||
sys.stdout.write('\nDone!\n')
|
sys.stdout.write("\nDone!\n")
|
||||||
|
|
||||||
pics = [TMP_DIR/pic.with_suffix(ext) for pic in pics]
|
pics = [TMP_DIR / pic.with_suffix(ext) for pic in pics]
|
||||||
|
|
||||||
# Pack into tar file
|
# Pack into tar file
|
||||||
with tarfile.open(args.tar_path, "w:gz") as tar:
|
with tarfile.open(args.tar_path, "w:gz") as tar:
|
||||||
for pic in pics:
|
for pic in pics:
|
||||||
tar.add(pic, arcname=pic.name)
|
tar.add(pic, arcname=pic.name)
|
||||||
|
|
||||||
|
|
||||||
# Provides a drawing editor for the latest image
|
# Provides a drawing editor for the latest image
|
||||||
def markup_subcommand(args):
|
def markup_subcommand(args):
|
||||||
og_path, edit_path = get_edit_path('png')
|
og_path, edit_path = get_edit_path("png")
|
||||||
|
|
||||||
if args.show_latest:
|
if args.show_latest:
|
||||||
print(og_path)
|
print(og_path)
|
||||||
|
@ -205,6 +270,7 @@ def markup_subcommand(args):
|
||||||
if args.file is not None:
|
if args.file is not None:
|
||||||
shutil.copyfile(edit_path, args.file)
|
shutil.copyfile(edit_path, args.file)
|
||||||
|
|
||||||
|
|
||||||
# ===================================================================
|
# ===================================================================
|
||||||
# Parse args
|
# Parse args
|
||||||
# ===================================================================
|
# ===================================================================
|
||||||
|
@ -214,20 +280,19 @@ def parser_dir(s: str):
|
||||||
else:
|
else:
|
||||||
raise NotADirectoryError(f"`{s}` is not a directory")
|
raise NotADirectoryError(f"`{s}` is not a directory")
|
||||||
|
|
||||||
def parse_dimensions(s: str) -> str:
|
|
||||||
s = s.strip()
|
|
||||||
|
|
||||||
if re.fullmatch(DIMENSIONS_REGEX, s):
|
def parse_dimensions(s: str) -> ScreenshotDimensions:
|
||||||
return s
|
return ScreenshotDimensions.from_string(s)
|
||||||
raise Exception(f"`{s}` does not match pattern {DIMENSIONS_REGEX}")
|
|
||||||
|
|
||||||
def parse_percent(s: str) -> int:
|
def parse_percent(s: str) -> int:
|
||||||
s = s.strip()
|
s = s.strip()
|
||||||
try:
|
try:
|
||||||
return int(re.fullmatch('([0-9]+)%?', s)[1])
|
return int(re.fullmatch("([0-9]+)%?", s)[1])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise Exception(f"{s} is not a valid percent. Does not match /[0-9]+%?/")
|
raise Exception(f"{s} is not a valid percent. Does not match /[0-9]+%?/")
|
||||||
|
|
||||||
|
|
||||||
def parse_size(s: str) -> (int, int):
|
def parse_size(s: str) -> (int, int):
|
||||||
s = s.strip()
|
s = s.strip()
|
||||||
try:
|
try:
|
||||||
|
@ -236,6 +301,7 @@ def parse_size(s: str) -> (int, int):
|
||||||
except:
|
except:
|
||||||
raise Exception(f"{s} does not match size regex /[0-9]+[x ][0-9]+/")
|
raise Exception(f"{s} does not match size regex /[0-9]+[x ][0-9]+/")
|
||||||
|
|
||||||
|
|
||||||
def parse_tar(s: str) -> Path:
|
def parse_tar(s: str) -> Path:
|
||||||
s = s.strip()
|
s = s.strip()
|
||||||
|
|
||||||
|
@ -244,151 +310,172 @@ def parse_tar(s: str) -> Path:
|
||||||
else:
|
else:
|
||||||
raise Exception(f"{s} is not a path to a .{{tar,tgz,tar.gz}} file")
|
raise Exception(f"{s} is not a path to a .{{tar,tgz,tar.gz}} file")
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog="Screenshot Wayland v1.0.0",
|
prog="Screenshot Wayland v1.0.0", description="Take a screenshot on Sway"
|
||||||
description='Take a screenshot on Sway'
|
)
|
||||||
);
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s', '--screenshot-dir',
|
"-s",
|
||||||
|
"--screenshot-dir",
|
||||||
type=parser_dir,
|
type=parser_dir,
|
||||||
metavar="<dir>",
|
metavar="<dir>",
|
||||||
help=f"Save and edit directory. Default: ~/{RELATIVE_DIR}",
|
help=f"Save and edit directory. Default: ~/{RELATIVE_DIR}",
|
||||||
);
|
)
|
||||||
|
|
||||||
# Subcommands ====
|
# Subcommands ====
|
||||||
subcommands = parser.add_subparsers(dest='subcommand', required=True);
|
subcommands = parser.add_subparsers(dest="subcommand", required=True)
|
||||||
# Take ====
|
# Take ====
|
||||||
take_subcmd = subcommands.add_parser(
|
take_subcmd = subcommands.add_parser("take", help="Takes a screenshot")
|
||||||
"take", help="Takes a screenshot");
|
|
||||||
|
|
||||||
take_common = argparse.ArgumentParser(add_help=False);
|
take_common = argparse.ArgumentParser(add_help=False)
|
||||||
take_common.add_argument(
|
take_common.add_argument(
|
||||||
'-c', '--clipboard',
|
"-c",
|
||||||
action='store_true',
|
"--clipboard",
|
||||||
help='Save the screenshot to your clipboard',
|
action="store_true",
|
||||||
);
|
help="Save the screenshot to your clipboard",
|
||||||
|
)
|
||||||
take_common.add_argument(
|
take_common.add_argument(
|
||||||
"file", nargs='?', type=Path,
|
"file", nargs="?", type=Path, help="Save the screenshot to this file name"
|
||||||
help="Save the screenshot to this file name"
|
)
|
||||||
);
|
|
||||||
|
|
||||||
# Different possible screenshot regions
|
# Different possible screenshot regions
|
||||||
region = take_subcmd.add_subparsers(dest='region', required=True);
|
region = take_subcmd.add_subparsers(dest="region", required=True)
|
||||||
full = region.add_parser(
|
full = region.add_parser(
|
||||||
'full', parents=[take_common],
|
"full", parents=[take_common], help="Take a screenshot of the entire screen"
|
||||||
help='Take a screenshot of the entire screen'
|
)
|
||||||
);
|
|
||||||
exact = region.add_parser(
|
exact = region.add_parser(
|
||||||
'exact', parents=[take_common],
|
"exact",
|
||||||
help="Exact dimensions of screenshot: 'x,y width,height'"
|
parents=[take_common],
|
||||||
);
|
help="Exact dimensions of screenshot: 'x,y width,height'",
|
||||||
|
)
|
||||||
select = region.add_parser(
|
select = region.add_parser(
|
||||||
'select', parents=[take_common],
|
"select",
|
||||||
help="Use `slurp` to select a region with your mouse"
|
parents=[take_common],
|
||||||
);
|
help="Use `slurp` or `slop` to select a region with your mouse",
|
||||||
|
)
|
||||||
exact.add_argument(
|
exact.add_argument(
|
||||||
'dimensions',
|
"dimensions",
|
||||||
type=parse_dimensions,
|
type=parse_dimensions,
|
||||||
metavar="'N,N NxN'",
|
metavar="'N,N NxN'",
|
||||||
help="Exact dimensions of screenshot: 'x,y width,height'"
|
help="Exact dimensions of screenshot: 'x,y widthxheight'",
|
||||||
);
|
)
|
||||||
|
|
||||||
# Edit ====
|
# Edit ====
|
||||||
edit_subcmd = subcommands.add_parser(
|
edit_subcmd = subcommands.add_parser(
|
||||||
"edit", help="Apply an edit to the latest screenshot");
|
"edit", help="Apply an edit to the latest screenshot"
|
||||||
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'-r', '--rescale',
|
"-r",
|
||||||
|
"--rescale",
|
||||||
type=parse_percent,
|
type=parse_percent,
|
||||||
metavar="<N%>",
|
metavar="<N%>",
|
||||||
help='Rescale the latest screenshot to <precent> of the original',
|
help="Rescale the latest screenshot to <precent> of the original",
|
||||||
);
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'-s', '--size',
|
"-s",
|
||||||
|
"--size",
|
||||||
type=parse_size,
|
type=parse_size,
|
||||||
metavar="<dims>",
|
metavar="<dims>",
|
||||||
help='Set the dimensions of the latest screenshot',
|
help="Set the dimensions of the latest screenshot",
|
||||||
);
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'-c', '--clipboard',
|
"-c",
|
||||||
action='store_true',
|
"--clipboard",
|
||||||
help='Save the edited screenshot to your clipboard',
|
action="store_true",
|
||||||
);
|
help="Save the edited screenshot to your clipboard",
|
||||||
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'-d', '--drop-shadow',
|
"-d",
|
||||||
action='store',
|
"--drop-shadow",
|
||||||
choices=['light', 'dark'],
|
action="store",
|
||||||
help='Apply a drop shadow with a light/dark background',
|
choices=["light", "dark"],
|
||||||
);
|
help="Apply a drop shadow with a light/dark background",
|
||||||
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'-e', '--extension', metavar="<ext>",
|
"-e",
|
||||||
|
"--extension",
|
||||||
|
metavar="<ext>",
|
||||||
type=str,
|
type=str,
|
||||||
default=DEFAULT_EDIT_EXTENSION,
|
default=DEFAULT_EDIT_EXTENSION,
|
||||||
help='Change image extension and image type saved',
|
help="Change image extension and image type saved",
|
||||||
);
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'-q', '--quality',
|
"-q",
|
||||||
|
"--quality",
|
||||||
type=parse_percent,
|
type=parse_percent,
|
||||||
default=DEFAULT_EDIT_QUALITY,
|
default=DEFAULT_EDIT_QUALITY,
|
||||||
metavar='<N%>',
|
metavar="<N%>",
|
||||||
help='Set quality of new image. [0, 100], higher means bigger file',
|
help="Set quality of new image. [0, 100], higher means bigger file",
|
||||||
);
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
'--overwrite',
|
"--overwrite",
|
||||||
action='store_true',
|
action="store_true",
|
||||||
help='Overwrite original image with the edited image',
|
help="Overwrite original image with the edited image",
|
||||||
);
|
)
|
||||||
edit_subcmd.add_argument(
|
edit_subcmd.add_argument(
|
||||||
"file", nargs='?', type=Path,
|
"file",
|
||||||
|
nargs="?",
|
||||||
|
type=Path,
|
||||||
help="Save the edited screenshot to this file name",
|
help="Save the edited screenshot to this file name",
|
||||||
);
|
)
|
||||||
# Archive ====
|
# Archive ====
|
||||||
archive_subcmd = subcommands.add_parser(
|
archive_subcmd = subcommands.add_parser(
|
||||||
"archive", help="Backup the screenshots directory to a tar file");
|
"archive", help="Backup the screenshots directory to a tar file"
|
||||||
|
)
|
||||||
|
|
||||||
archive_subcmd.add_argument(
|
archive_subcmd.add_argument(
|
||||||
'-e', '--extension',
|
"-e",
|
||||||
|
"--extension",
|
||||||
type=str,
|
type=str,
|
||||||
default=DEFAULT_EDIT_EXTENSION,
|
default=DEFAULT_EDIT_EXTENSION,
|
||||||
metavar="<ext>",
|
metavar="<ext>",
|
||||||
help='Change image extension and image type backed up',
|
help="Change image extension and image type backed up",
|
||||||
);
|
)
|
||||||
archive_subcmd.add_argument(
|
archive_subcmd.add_argument(
|
||||||
'-q', '--quality',
|
"-q",
|
||||||
|
"--quality",
|
||||||
type=parse_percent,
|
type=parse_percent,
|
||||||
default=DEFAULT_EDIT_QUALITY,
|
default=DEFAULT_EDIT_QUALITY,
|
||||||
metavar='<N%>',
|
metavar="<N%>",
|
||||||
help='Set quality of backed up images. [0, 100], higher means bigger file',
|
help="Set quality of backed up images. [0, 100], higher means bigger file",
|
||||||
);
|
)
|
||||||
archive_subcmd.add_argument(
|
archive_subcmd.add_argument(
|
||||||
'which', metavar='<which>',
|
"which",
|
||||||
choices=['all', 'unedited'],
|
metavar="<which>",
|
||||||
help='One of {all,unedited}. Backup only unedited images or all of them',
|
choices=["all", "unedited"],
|
||||||
);
|
help="One of {all,unedited}. Backup only unedited images or all of them",
|
||||||
|
)
|
||||||
archive_subcmd.add_argument(
|
archive_subcmd.add_argument(
|
||||||
"tar_path", metavar='<tar-path>',
|
"tar_path",
|
||||||
|
metavar="<tar-path>",
|
||||||
type=parse_tar,
|
type=parse_tar,
|
||||||
help="Destination tar file. Should be .{tar,tgz,tar.gz}",
|
help="Destination tar file. Should be .{tar,tgz,tar.gz}",
|
||||||
);
|
)
|
||||||
|
|
||||||
# Markup ====
|
# Markup ====
|
||||||
markup_subcmd = subcommands.add_parser(
|
markup_subcmd = subcommands.add_parser(
|
||||||
"markup", help="Markup the latest screenshot in swappy");
|
"markup", help="Markup the latest screenshot in swappy"
|
||||||
|
)
|
||||||
markup_subcmd.add_argument(
|
markup_subcmd.add_argument(
|
||||||
'-c', '--clipboard',
|
"-c",
|
||||||
action='store_true',
|
"--clipboard",
|
||||||
help='Save the screenshot to your clipboard',
|
action="store_true",
|
||||||
);
|
help="Save the screenshot to your clipboard",
|
||||||
|
)
|
||||||
markup_subcmd.add_argument(
|
markup_subcmd.add_argument(
|
||||||
'-s', '--show-latest',
|
"-s",
|
||||||
action='store_true',
|
"--show-latest",
|
||||||
help='Show the path to the latest image and exit',
|
action="store_true",
|
||||||
);
|
help="Show the path to the latest image and exit",
|
||||||
|
)
|
||||||
markup_subcmd.add_argument(
|
markup_subcmd.add_argument(
|
||||||
"file", nargs='?', type=Path,
|
"file",
|
||||||
|
nargs="?",
|
||||||
|
type=Path,
|
||||||
help="Save the edited screenshot to this file name",
|
help="Save the edited screenshot to this file name",
|
||||||
);
|
)
|
||||||
|
|
||||||
args = parser.parse_args();
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Second layer of parser checks
|
# Second layer of parser checks
|
||||||
if args.screenshot_dir is not None:
|
if args.screenshot_dir is not None:
|
||||||
|
|
58
i3/brightness_lock.sh
Executable file
58
i3/brightness_lock.sh
Executable file
|
@ -0,0 +1,58 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Locks the screens and lowers-brightness. Restores brightness on unlock
|
||||||
|
|
||||||
|
# Defaults for levels when restored
|
||||||
|
declare light_restore=3
|
||||||
|
declare ddc_restore=3
|
||||||
|
|
||||||
|
# Levels when dimmed
|
||||||
|
declare -ri light_dim=1
|
||||||
|
declare -ri ddc_dim=1
|
||||||
|
|
||||||
|
get_brightness() {
|
||||||
|
local lvl
|
||||||
|
|
||||||
|
if command -v light &>/dev/null; then
|
||||||
|
lvl="$(light -G)"
|
||||||
|
|
||||||
|
if [[ $lvl =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
|
||||||
|
light_restore="$lvl"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v ddcutil &>/dev/null; then
|
||||||
|
lvl="$(ddcutil getvcp 10 | awk '{
|
||||||
|
gsub(" ",""); # Remove spaces
|
||||||
|
split($0, a, "=");
|
||||||
|
split(a[2], a, ","); print a[1]
|
||||||
|
}')"
|
||||||
|
|
||||||
|
if [[ $lvl =~ ^[0-9]+$ ]]; then
|
||||||
|
ddc_restore="$lvl"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set_brightness() {
|
||||||
|
local -r light_lvl="$1"
|
||||||
|
local -r ddc_lvl="$2"
|
||||||
|
|
||||||
|
if command -v light &>/dev/null; then
|
||||||
|
light -S "$light_lvl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v ddcutil &>/dev/null; then
|
||||||
|
ddcutil setvcp 10 "$ddc_lvl"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
i3lock -i ~/.config/swaylock/default_wallpaper.png &
|
||||||
|
|
||||||
|
get_brightness
|
||||||
|
set_brightness $light_dim $ddc_dim
|
||||||
|
|
||||||
|
while pgrep i3lock &>/dev/null; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
set_brightness $light_restore $ddc_restore
|
405
i3/config
Normal file
405
i3/config
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
# This file has been auto-generated by i3-config-wizard(1).
|
||||||
|
# It will not be overwritten, so edit it as you like.
|
||||||
|
#
|
||||||
|
# Should you change your keyboard layout some time, delete
|
||||||
|
# this file and re-run i3-config-wizard(1).
|
||||||
|
#
|
||||||
|
|
||||||
|
# i3 config file (v4)
|
||||||
|
#
|
||||||
|
# Please see https://i3wm.org/docs/userguide.html for a complete reference!
|
||||||
|
|
||||||
|
set $mod1 Mod4
|
||||||
|
set $mod2 Mod4+Shift
|
||||||
|
|
||||||
|
# Font for window titles. Will also be used by the bar unless a different font
|
||||||
|
# is used in the bar {} block below.
|
||||||
|
#font Meslo LG M Regular Nerd Font Complete:monospace 11
|
||||||
|
font pango:monospace 11
|
||||||
|
|
||||||
|
# This font is widely installed, provides lots of unicode glyphs, right-to-left
|
||||||
|
# text rendering and scalability on retina/hidpi displays (thanks to pango).
|
||||||
|
#font pango:DejaVu Sans Mono 8
|
||||||
|
|
||||||
|
# Pane movement keys - vim
|
||||||
|
set $pane_left h
|
||||||
|
set $pane_down j
|
||||||
|
set $pane_up k
|
||||||
|
set $pane_right l
|
||||||
|
|
||||||
|
# Symmetric keys - mpv
|
||||||
|
set $left_outer q
|
||||||
|
set $left_inner w
|
||||||
|
set $right_inner e
|
||||||
|
set $right_outer r
|
||||||
|
|
||||||
|
# Space movement keys - gaming
|
||||||
|
set $space_up w
|
||||||
|
set $space_left a
|
||||||
|
set $space_down s
|
||||||
|
set $space_right d
|
||||||
|
|
||||||
|
# Resize keys - vim windows
|
||||||
|
set $size_up comma
|
||||||
|
set $size_down period
|
||||||
|
|
||||||
|
set $term alacritty
|
||||||
|
set $menu rlaunch
|
||||||
|
|
||||||
|
# Sound effects and additional features
|
||||||
|
set $volume_command ~/.config/sway/pulse_audio_volume.sh
|
||||||
|
set $volume_change_sound ~/.config/sway/volume_change_sound.mp3
|
||||||
|
set $screenshot_sound ffplay -nodisp -autoexit -v error ~/.config/sway/screenshot_sound.mp3
|
||||||
|
|
||||||
|
# Duplicate screenshot path, for quick uploads
|
||||||
|
set $screenshot_tmp /dev/shm/screenshot_shm.png
|
||||||
|
set $screenshot_script ~/.configs_pointer/bin/screenshot_wayland.py
|
||||||
|
|
||||||
|
#╔─────────────────────────────────────────────────────────────────────────────╗
|
||||||
|
#│ Pαηεs αηd cδηταiηεrs |
|
||||||
|
#╚─────────────────────────────────────────────────────────────────────────────╝
|
||||||
|
# Move focus
|
||||||
|
bindsym $mod1+$pane_left focus left
|
||||||
|
bindsym $mod1+$pane_down focus down
|
||||||
|
bindsym $mod1+$pane_up focus up
|
||||||
|
bindsym $mod1+$pane_right focus right
|
||||||
|
|
||||||
|
# Move focused window
|
||||||
|
bindsym $mod2+$pane_left move left
|
||||||
|
bindsym $mod2+$pane_down move down
|
||||||
|
bindsym $mod2+$pane_up move up
|
||||||
|
bindsym $mod2+$pane_right move right
|
||||||
|
|
||||||
|
# Layout modifiers
|
||||||
|
bindsym $mod2+f floating toggle
|
||||||
|
bindsym $mod2+s layout stacking
|
||||||
|
bindsym $mod2+t layout tabbed
|
||||||
|
bindsym $mod2+r layout toggle
|
||||||
|
|
||||||
|
# Binary split container
|
||||||
|
bindsym $mod1+b split toggle
|
||||||
|
#bindsym $mod1+v split none # Does not exist in i3
|
||||||
|
bindsym $mod1+m fullscreen
|
||||||
|
|
||||||
|
# Switch container layout Stacking|Tabbed|Rotate-bsp
|
||||||
|
bindsym $mod1+s layout stacking
|
||||||
|
bindsym $mod1+t layout tabbed
|
||||||
|
bindsym $mod1+r layout toggle split
|
||||||
|
|
||||||
|
# Traverse window tree
|
||||||
|
bindsym $mod1+u focus parent
|
||||||
|
bindsym $mod1+d focus child
|
||||||
|
|
||||||
|
# Alt-tab cycles windows, like on proprietary systems
|
||||||
|
bindsym $mod1+tab exec ~/.config/sway/cycle_windows.py next
|
||||||
|
bindsym $mod2+tab exec ~/.config/sway/cycle_windows.py previous
|
||||||
|
|
||||||
|
# Swap focus between the tiling area and the floating area
|
||||||
|
#bindsym $mod+space focus mode_toggle
|
||||||
|
|
||||||
|
# Important rust jerk
|
||||||
|
bindsym $mod1+ctrl+r exec wtype "asExpectedOfRust"
|
||||||
|
#bindsym $mod1+ctrl+s reload
|
||||||
|
|
||||||
|
# Automatic upload image to discord
|
||||||
|
bindsym $mod1+ctrl+u exec sudo -u emiliko ~/.configs_pointer/bin/auto_image_upload_discord.sh
|
||||||
|
|
||||||
|
# Paste by typing
|
||||||
|
bindsym Mod4+Ctrl+v exec ~/.configs_pointer/bin/wpastetype.py
|
||||||
|
|
||||||
|
# rEsize containers ====
|
||||||
|
bindsym $mod1+e mode "resize"
|
||||||
|
|
||||||
|
mode "resize" {
|
||||||
|
# Horizontal, shift for fine adjust
|
||||||
|
bindsym $size_up resize grow width 16px
|
||||||
|
bindsym $size_down resize shrink width 16px
|
||||||
|
bindsym $size_up+Shift resize grow width 4px
|
||||||
|
bindsym $size_down+Shift resize shrink width 4px
|
||||||
|
|
||||||
|
# Vertical, shift for fine adjust
|
||||||
|
bindsym $mod1+$size_down resize shrink height 16px
|
||||||
|
bindsym $mod1+$size_up resize grow height 16px
|
||||||
|
bindsym $mod1+$size_down+Shift resize shrink height 4px
|
||||||
|
bindsym $mod1+$size_up+Shift resize grow height 4px
|
||||||
|
|
||||||
|
# Escaping
|
||||||
|
bindsym $mod1+f mode "workspace_tuning"
|
||||||
|
|
||||||
|
bindsym Shift+end mode "default"
|
||||||
|
bindsym Ctrl+k mode "default"
|
||||||
|
bindsym Ctrl+bracketleft mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gaps ====
|
||||||
|
bindsym $mod2+bracketright gaps inner current minus 3
|
||||||
|
bindsym $mod2+bracketleft gaps inner current plus 3
|
||||||
|
#bindsym $mod2+equal gaps toggle
|
||||||
|
# Standard outer gapping for 27" screen
|
||||||
|
bindsym $mod2+c gaps vertical current set 100, \
|
||||||
|
gaps horizontal current set 200
|
||||||
|
# Same as above, shifted left slightly
|
||||||
|
bindsym $mod2+g gaps vertical current set 100, \
|
||||||
|
gaps left current set 150, \
|
||||||
|
gaps right current set 250
|
||||||
|
|
||||||
|
bindsym $mod1+g mode "gapping"
|
||||||
|
mode "gapping" {
|
||||||
|
# General resize
|
||||||
|
bindsym $mod2+bracketright gaps inner current minus 3
|
||||||
|
bindsym $mod2+bracketleft gaps inner current plus 3
|
||||||
|
|
||||||
|
# Horizontal
|
||||||
|
bindsym q gaps left current minus 2
|
||||||
|
bindsym w gaps left current plus 2
|
||||||
|
bindsym e gaps right current plus 2
|
||||||
|
bindsym r gaps right current minus 2
|
||||||
|
|
||||||
|
# Vertical
|
||||||
|
bindsym $mod1+q gaps top current minus 2
|
||||||
|
bindsym $mod1+w gaps top current plus 2
|
||||||
|
bindsym $mod1+e gaps bottom current plus 2
|
||||||
|
bindsym $mod1+r gaps bottom current minus 2
|
||||||
|
|
||||||
|
# Escaping
|
||||||
|
bindsym Shift+end mode "default"
|
||||||
|
bindsym Ctrl+k mode "default"
|
||||||
|
bindsym Ctrl+bracketleft mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
#╔─────────────────────────────────────────────────────────────────────────────╗
|
||||||
|
#│ Wδrksραcεs |
|
||||||
|
#╚─────────────────────────────────────────────────────────────────────────────╝
|
||||||
|
bindsym $mod1+bracketleft workspace prev
|
||||||
|
bindsym $mod1+bracketright workspace next
|
||||||
|
|
||||||
|
bindsym $mod2+a workspace prev
|
||||||
|
bindsym $mod2+d workspace next
|
||||||
|
|
||||||
|
bindsym $mod1+1 workspace number 1
|
||||||
|
bindsym $mod1+2 workspace number 2
|
||||||
|
bindsym $mod1+3 workspace number 3
|
||||||
|
bindsym $mod1+4 workspace number 4
|
||||||
|
bindsym $mod1+5 workspace number 5
|
||||||
|
bindsym $mod1+6 workspace number 6
|
||||||
|
bindsym $mod1+7 workspace number 7
|
||||||
|
bindsym $mod1+8 workspace number 8
|
||||||
|
bindsym $mod1+9 workspace number 9
|
||||||
|
|
||||||
|
# Advanced workspace tuning ====
|
||||||
|
bindsym $mod1+f mode "workspace_tuning"
|
||||||
|
|
||||||
|
mode "workspace_tuning" {
|
||||||
|
|
||||||
|
# Move focused container to workspace
|
||||||
|
bindsym 1 move container to workspace number 1
|
||||||
|
bindsym 2 move container to workspace number 2
|
||||||
|
bindsym 3 move container to workspace number 3
|
||||||
|
bindsym 4 move container to workspace number 4
|
||||||
|
bindsym 5 move container to workspace number 5
|
||||||
|
bindsym 6 move container to workspace number 6
|
||||||
|
bindsym 7 move container to workspace number 7
|
||||||
|
bindsym 8 move container to workspace number 8
|
||||||
|
bindsym 9 move container to workspace number 9
|
||||||
|
|
||||||
|
# Swap containers
|
||||||
|
bindsym $mod1+$pane_left mark --add "_swap", focus left, swap container with mark "_swap", focus left, unmark "_swap"
|
||||||
|
bindsym $mod1+$pane_down mark --add "_swap", focus down, swap container with mark "_swap", focus down, unmark "_swap"
|
||||||
|
bindsym $mod1+$pane_up mark --add "_swap", focus up, swap container with mark "_swap", focus up, unmark "_swap"
|
||||||
|
bindsym $mod1+$pane_right mark --add "_swap", focus right, swap container with mark "_swap", focus right, unmark "_swap"
|
||||||
|
|
||||||
|
# Stack, Tab, Rotate
|
||||||
|
bindsym s layout stacking
|
||||||
|
bindsym t layout tabbed
|
||||||
|
bindsym r layout toggle split
|
||||||
|
|
||||||
|
bindsym f fullscreen
|
||||||
|
bindsym Shift+f fullscreen
|
||||||
|
|
||||||
|
# Escaping
|
||||||
|
bindsym $mod1+e mode "resize"
|
||||||
|
|
||||||
|
bindsym Shift+end mode "default"
|
||||||
|
bindsym Ctrl+k mode "default"
|
||||||
|
bindsym Ctrl+bracketleft mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
#╔─────────────────────────────────────────────────────────────────────────────╗
|
||||||
|
#│ Iηρμτ αηd δμτρμτ αdjμsτmεητs |
|
||||||
|
#╚─────────────────────────────────────────────────────────────────────────────╝
|
||||||
|
# Volume controls
|
||||||
|
bindsym XF86AudioRaiseVolume exec $volume_command 4 $volume_change_sound
|
||||||
|
bindsym XF86AudioLowerVolume exec $volume_command -4 $volume_change_sound
|
||||||
|
bindsym shift+XF86AudioRaiseVolume exec $volume_command 1 $volume_change_sound
|
||||||
|
bindsym shift+XF86AudioLowerVolume exec $volume_command -1 $volume_change_sound
|
||||||
|
bindsym XF86AudioMute exec ~/.config/sway/toggle_mute.sh
|
||||||
|
|
||||||
|
# External brightness control
|
||||||
|
# For laptops
|
||||||
|
bindsym XF86MonBrightnessUp exec light -A 1
|
||||||
|
bindsym XF86MonBrightnessDown exec light -U 1
|
||||||
|
# For external monitors
|
||||||
|
bindsym XF86AudioNext exec ddcutil setvcp 10 + 4
|
||||||
|
bindsym XF86AudioPrev exec ddcutil setvcp 10 - 4
|
||||||
|
bindsym F10 exec ddcutil setvcp 10 + 1
|
||||||
|
bindsym F8 exec ddcutil setvcp 10 - 1
|
||||||
|
bindsym XF86Back exec ddcutil setvcp 12 + 2
|
||||||
|
bindsym Menu exec ddcutil setvcp 12 - 2
|
||||||
|
|
||||||
|
#╔─────────────────────────────────────────────────────────────────────────────╗
|
||||||
|
#│ Hδτkεy dαεmδη |
|
||||||
|
#╚─────────────────────────────────────────────────────────────────────────────╝
|
||||||
|
# Terminal
|
||||||
|
bindsym $mod2+Return exec $term
|
||||||
|
# Chromium
|
||||||
|
bindsym $mod2+n exec chromium
|
||||||
|
# Firefox
|
||||||
|
bindsym $mod2+p exec MOZ_ENABLE_WAYLAND=1 firefox --private-window
|
||||||
|
# App launcher, like spotlight
|
||||||
|
bindsym $mod1+space exec $menu
|
||||||
|
# Reload sway config
|
||||||
|
bindsym $mod1+ctrl+s reload
|
||||||
|
# Close window
|
||||||
|
bindsym $mod2+q kill
|
||||||
|
# Dragging windows
|
||||||
|
#floating_modifier $mod1 normal
|
||||||
|
floating_modifier $mod1
|
||||||
|
# Screenlock
|
||||||
|
bindsym $mod2+i exec ~/.config/i3/brightness_lock.sh
|
||||||
|
# Scratchpad
|
||||||
|
bindsym $mod1+Shift+minus move scratchpad
|
||||||
|
bindsym $mod1+minus scratchpad show
|
||||||
|
# Warpd - Keyboard-driven mouse
|
||||||
|
bindsym Mod4+Control+j exec warpd --hint
|
||||||
|
bindsym Mod4+Control+n exec warpd --normal
|
||||||
|
# Xremap
|
||||||
|
exec sudo ~/.configs_pointer/bin/switch_keyboard.sh pc
|
||||||
|
# IME Module
|
||||||
|
bindsym $mod1+i exec ~/.config/sway/toggle_fcitx.sh
|
||||||
|
# Mako notifications
|
||||||
|
exec mako
|
||||||
|
# Exit sway (hit 3 times repeatedly to force exit)
|
||||||
|
bindsym $mod2+Escape exec ~/.config/sway/sway_exit.sh
|
||||||
|
|
||||||
|
exec --no-startup-id feh --bg-fill ~/.configs_pointer/sway/default_wallpaper.png
|
||||||
|
|
||||||
|
client.focused #F4A66E #F4A66E #000000 #F4A66E #F4A66E
|
||||||
|
|
||||||
|
# Screenshots ====
|
||||||
|
bindsym $mod2+6 mode "screenshots"
|
||||||
|
bindsym $mod2+5 mode "screenshots"; exec $screenshot_script take select -c $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym $mod2+4 mode "screenshots"; exec $screenshot_script take exact "$(~/.config/sway/window_dimensions.py)" && \
|
||||||
|
$screenshot_script edit -c -q 100 -d "$(colo.sh -t)" -e png --overwrite $screenshot_tmp && $screenshot_sound
|
||||||
|
|
||||||
|
mode "screenshots" {
|
||||||
|
# Screenshooting in processing "steps"
|
||||||
|
# 1. Get screenshot
|
||||||
|
bindsym a exec $screenshot_script take select -c $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym f exec $screenshot_script take full -c $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym m mode "default"; exec $screenshot_script markup -c $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym g mode "default"; exec gimp $($screenshot_script markup --show-latest)
|
||||||
|
|
||||||
|
# 2. Downsize the screenshot, since 4k is too big
|
||||||
|
bindsym 1 exec $screenshot_script edit -c -e png -q '40%' -r '50%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 2 exec $screenshot_script edit -c -e png -q '40%' -r '60%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 3 exec $screenshot_script edit -c -e png -q '40%' -r '70%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 4 exec $screenshot_script edit -c -e png -q '40%' -r '80%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 5 exec $screenshot_script edit -c -e png -q '80%' -r '50%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 6 exec $screenshot_script edit -c -e png -q '80%' -r '60%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 7 exec $screenshot_script edit -c -e png -q '80%' -r '70%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 8 exec $screenshot_script edit -c -e png -q '80%' -r '80%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 9 exec $screenshot_script edit -c -e png -q '80%' -r '90%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 0 exec $screenshot_script edit -c -e png -q '80%' -r '100%' $screenshot_tmp && $screenshot_sound
|
||||||
|
|
||||||
|
# OR compress image
|
||||||
|
bindsym space mode "shrink_screenshots"
|
||||||
|
|
||||||
|
# 3. Copy the smaller image back to clipboard and return to default
|
||||||
|
bindsym return mode "default"
|
||||||
|
bindsym Shift+end mode "default"
|
||||||
|
bindsym Ctrl+k mode "default"
|
||||||
|
bindsym Ctrl+bracketleft mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
mode "shrink_screenshots" {
|
||||||
|
# 2. Compress the screenshot, hard
|
||||||
|
bindsym 1 exec $screenshot_script edit -c -e webp -q '40%' -r '50%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 2 exec $screenshot_script edit -c -e webp -q '40%' -r '60%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 3 exec $screenshot_script edit -c -e webp -q '40%' -r '70%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 4 exec $screenshot_script edit -c -e webp -q '40%' -r '80%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 5 exec $screenshot_script edit -c -e webp -q '80%' -r '50%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 6 exec $screenshot_script edit -c -e webp -q '80%' -r '60%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 7 exec $screenshot_script edit -c -e webp -q '80%' -r '70%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 8 exec $screenshot_script edit -c -e webp -q '80%' -r '80%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 9 exec $screenshot_script edit -c -e webp -q '80%' -r '90%' $screenshot_tmp && $screenshot_sound
|
||||||
|
bindsym 0 exec $screenshot_script edit -c -e webp -q '80%' -r '100%' $screenshot_tmp && $screenshot_sound
|
||||||
|
|
||||||
|
bindsym space mode "screenshots"
|
||||||
|
|
||||||
|
# 3. Back out
|
||||||
|
bindsym return mode "default"
|
||||||
|
bindsym Shift+end mode "default"
|
||||||
|
bindsym Ctrl+k mode "default"
|
||||||
|
bindsym Ctrl+bracketleft mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Global mpv ====
|
||||||
|
bindsym $mod2+m mode "mpv_global"
|
||||||
|
|
||||||
|
mode "mpv_global" {
|
||||||
|
bindsym j exec ~/.config/sway/mpv_keys.sh 'j'
|
||||||
|
bindsym k exec ~/.config/sway/mpv_keys.sh 'k'
|
||||||
|
bindsym l exec ~/.config/sway/mpv_keys.sh 'l'
|
||||||
|
bindsym Left exec ~/.config/sway/mpv_keys.sh 'LEFT'
|
||||||
|
bindsym Right exec ~/.config/sway/mpv_keys.sh 'RIGHT'
|
||||||
|
bindsym space exec ~/.config/sway/mpv_keys.sh 'SPACE'
|
||||||
|
bindsym bracketleft exec ~/.config/sway/mpv_keys.sh '['
|
||||||
|
bindsym bracketright exec ~/.config/sway/mpv_keys.sh ']'
|
||||||
|
bindsym minus exec ~/.config/sway/mpv_keys.sh '-'
|
||||||
|
bindsym equal exec ~/.config/sway/mpv_keys.sh '='
|
||||||
|
bindsym m exec ~/.config/sway/mpv_keys.sh 'm'
|
||||||
|
bindsym A exec ~/.config/sway/mpv_keys.sh 'A'
|
||||||
|
|
||||||
|
bindsym return mode "default"
|
||||||
|
bindsym Ctrl+k mode "default"
|
||||||
|
bindsym Shift+End mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
#╔─────────────────────────────────────────────────────────────────────────────╗
|
||||||
|
#│ Sτylεs |
|
||||||
|
#╚─────────────────────────────────────────────────────────────────────────────╝
|
||||||
|
bar {
|
||||||
|
#status_command i3status
|
||||||
|
i3bar_command i3bar --transparency
|
||||||
|
position bottom
|
||||||
|
|
||||||
|
binding_mode_indicator yes
|
||||||
|
|
||||||
|
# Vertical horizontal
|
||||||
|
#gaps 0 10
|
||||||
|
|
||||||
|
mode dock
|
||||||
|
|
||||||
|
status_command while ~/.config/sway/swaybar_status.sh; do sleep 60; done
|
||||||
|
|
||||||
|
colors {
|
||||||
|
# Foreground color
|
||||||
|
statusline #e7d6ad
|
||||||
|
background #22222200
|
||||||
|
|
||||||
|
# border background text
|
||||||
|
focused_workspace #F4B36Eff #F4B36Eff #000000
|
||||||
|
inactive_workspace #00000000 #444444 #e7d6ad
|
||||||
|
urgent_workspace #fadb2f #fadb2f #000000
|
||||||
|
|
||||||
|
binding_mode #8ec07c #8ec07c #000000
|
||||||
|
binding_mode #8ec07c #d3869b #000000
|
||||||
|
binding_mode #fadb2f #fadb2f #000000
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ declare -r UNIX_CONFIGS=(\
|
||||||
) \
|
) \
|
||||||
LINUX_ONLY=(\
|
LINUX_ONLY=(\
|
||||||
# Swayland
|
# Swayland
|
||||||
|
i3 ~/.config/i3
|
||||||
sway ~/.config/sway
|
sway ~/.config/sway
|
||||||
swaylock ~/.config/swaylock
|
swaylock ~/.config/swaylock
|
||||||
xremap ~/.config/xremap
|
xremap ~/.config/xremap
|
||||||
|
|
|
@ -6,33 +6,37 @@
|
||||||
# The printed dimensions will match the slup regex below:
|
# The printed dimensions will match the slup regex below:
|
||||||
# /[0-9]+,[0-9]+ [0-9]+x[0-9]+/
|
# /[0-9]+,[0-9]+ [0-9]+x[0-9]+/
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from subprocess import run, PIPE
|
from subprocess import run, PIPE
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
def get_sway_tree() -> dict:
|
def get_sway_tree() -> dict:
|
||||||
swaymsg = run(["swaymsg", "-t", "get_tree"], stdout=PIPE)
|
swaymsg = run([MSG_COMMAND, "-t", "get_tree"], stdout=PIPE)
|
||||||
swaymsg.check_returncode()
|
swaymsg.check_returncode()
|
||||||
return json.loads(swaymsg.stdout)
|
return json.loads(swaymsg.stdout)
|
||||||
|
|
||||||
|
|
||||||
def format_window_coords(window: dict, rect: dict) -> str:
|
def format_window_coords(window: dict, rect: dict) -> str:
|
||||||
if sum(window.values()) == 0: # Multiple windows selected
|
if sum(window.values()) == 0: # Multiple windows selected
|
||||||
x = rect['x']
|
x = rect["x"]
|
||||||
y = rect['y']
|
y = rect["y"]
|
||||||
w = rect['width']
|
w = rect["width"]
|
||||||
h = rect['height']
|
h = rect["height"]
|
||||||
elif window['y'] + window['height'] == rect['height']: # Account for border
|
elif window["y"] + window["height"] == rect["height"]: # Account for border
|
||||||
x = rect['x'] + window['x']
|
x = rect["x"] + window["x"]
|
||||||
y = rect['y']
|
y = rect["y"]
|
||||||
w = window['width']
|
w = window["width"]
|
||||||
h = window['height'] - window['y']
|
h = window["height"] - window["y"]
|
||||||
else:
|
else:
|
||||||
x = rect['x'] + window['x']
|
x = rect["x"] + window["x"]
|
||||||
y = rect['y'] + window['y']
|
y = rect["y"] + window["y"]
|
||||||
w = window['width']
|
w = window["width"]
|
||||||
h = window['height']
|
h = window["height"]
|
||||||
|
|
||||||
return f"{x},{y} {w}x{h}"
|
return f"{x},{y} {w}x{h}"
|
||||||
|
|
||||||
|
|
||||||
# Return dict indexing path to the first entry with "key" matching "val"
|
# Return dict indexing path to the first entry with "key" matching "val"
|
||||||
# For example, it may return
|
# For example, it may return
|
||||||
# ['nodes', 1, 'nodes', 1, 'nodes', 0, 'nodes', 0]
|
# ['nodes', 1, 'nodes', 1, 'nodes', 0, 'nodes', 0]
|
||||||
|
@ -57,17 +61,27 @@ def trace_json_path(js, find_key, find_val) -> Optional[list]:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def focused_sway_area():
|
def focused_sway_area():
|
||||||
tree = get_sway_tree()
|
tree = get_sway_tree()
|
||||||
trace = trace_json_path(tree, 'focused', True)
|
trace = trace_json_path(tree, "focused", True)
|
||||||
|
|
||||||
if trace is None:
|
if trace is None:
|
||||||
print('No focused window was found')
|
print("No focused window was found")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
for i in trace:
|
for i in trace:
|
||||||
tree = tree[i]
|
tree = tree[i]
|
||||||
return format_window_coords(tree['window_rect'], tree['rect'])
|
return format_window_coords(tree["window_rect"], tree["rect"])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
if "wayland" in os.environ["XDG_SESSION_TYPE"]:
|
||||||
|
MSG_COMMAND = "swaymsg"
|
||||||
|
else:
|
||||||
|
MSG_COMMAND = "i3-msg"
|
||||||
|
except KeyError:
|
||||||
|
MSG_COMMAND = "i3-msg"
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print(focused_sway_area())
|
print(focused_sway_area())
|
||||||
|
|
Loading…
Reference in a new issue