From acd2fad430d352ba1318ae6aad8ec91270d80291 Mon Sep 17 00:00:00 2001 From: fun840 Date: Mon, 5 Dec 2022 18:54:00 -0500 Subject: [PATCH 1/3] Add gradient & rainbow border --- xborders | 97 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/xborders b/xborders index 6a182d3..7f7bac0 100755 --- a/xborders +++ b/xborders @@ -6,6 +6,7 @@ import subprocess import sys import threading import webbrowser +import colorsys import cairo import gi @@ -28,23 +29,52 @@ BORDER_R = 123 BORDER_G = 88 BORDER_B = 220 BORDER_A = 1 +BORDER_GRADIENT_COLORS = [] NO_VERSION_NOTIFY = False OFFSETS = [0, 0, 0, 0] def set_border_rgba(args): - try: - literal_value = int(args.border_rgba.replace("#", "0x"), 16) - except: - print( - f"`{args.border_rgba}` is an invalid hexadecimal number!", - file=sys.stderr, - ) - sys.exit(1) - args.border_red = literal_value >> (3 * 8) & 0xFF - args.border_green = literal_value >> (2 * 8) & 0xFF - args.border_blue = literal_value >> (1 * 8) & 0xFF - args.border_alpha = (literal_value >> (0 * 8) & 0xFF) / 255 # map from 0 to 1 + + if args.border_rgba: # solid color + try: + literal_value = int(args.border_rgba.replace("#", "0x"), 16) + except: + print( + f"`{args.border_rgba}` is an invalid hexadecimal number!", + file=sys.stderr, + ) + sys.exit(1) + args.border_red = literal_value >> (3 * 8) & 0xFF + args.border_green = literal_value >> (2 * 8) & 0xFF + args.border_blue = literal_value >> (1 * 8) & 0xFF + args.border_alpha = (literal_value >> (0 * 8) & 0xFF) / 255 # map from 0 to 1 + + elif args.border_gradient: # gradient + + for color in args.border_gradient: + try: + literal_value = int(color.replace("#", "0x"), 16) + except: + print( + f"`{args.border_rgba}` is an invalid hexadecimal number!", + file=sys.stderr, + ) + sys.exit(1) + + red = (literal_value >> (3 * 8) & 0xFF) / 255 + green = (literal_value >> (2 * 8) & 0xFF) / 255 + blue = (literal_value >> (1 * 8) & 0xFF) / 255 + alpha = (literal_value >> (0 * 8) & 0xFF) / 255 + + BORDER_GRADIENT_COLORS.append((red, green, blue, alpha)) + + elif args.rainbow: # rainbow + + for i in range(args.rainbow_steps): + color = colorsys.hsv_to_rgb(i / args.rainbow_steps, args.rainbow_value, args.rainbow_brightness) + + BORDER_GRADIENT_COLORS.append((*color, 1)) def get_version(): @@ -100,11 +130,41 @@ def get_args(): default=1, help="The border's alpha value, between zero and 1", ) - parser.add_argument( + color_group = parser.add_mutually_exclusive_group() + color_group.add_argument( "--border-rgba", default=None, help="The colours of the border in hex format, example: #FF0000FF", ) + color_group.add_argument( + "--border-gradient", + default=None, + help="The colors of the border as a gradient, separated by spaces. Example: #FF0000FF #00FF00FF", + nargs="+", + ) + color_group.add_argument( + "--rainbow", + action="store_true", + help="Use a rainbow gradient for the color of the border.", + ) + parser.add_argument( + "--rainbow-steps", + type=int, + default=50, + help="The amount of colors in the rainbow gradient", + ) + parser.add_argument( + "--rainbow-value", + type=float, + default=1, + help="The value / saturation of the colors when using --rainbow, on a scale from 0 to 1." + ) + parser.add_argument( + "--rainbow-brightness", + type=float, + default=1, + help="The brightness of the colors when using --rainbow, on a scale from 0 to 1." + ) parser.add_argument( "--border-mode", type=str, @@ -149,7 +209,7 @@ def get_args(): if args.version is True: print(f"xborders v{get_version()}") exit(0) - if args.border_rgba is not None: + if args.border_rgba is not None or args.border_gradient is not None or args.rainbow is not None: set_border_rgba(args) # Extract the literal values @@ -432,7 +492,14 @@ class Highlight(Gtk.Window): else: ctx.rectangle(x, y, w, h) - ctx.set_source_rgba(BORDER_R / 255, BORDER_G / 255, BORDER_B / 255, BORDER_A) + if BORDER_GRADIENT_COLORS: + grad = cairo.LinearGradient(x, y, x + w, y + h) + for i, color in enumerate(BORDER_GRADIENT_COLORS): + grad.add_color_stop_rgba(i / len(BORDER_GRADIENT_COLORS), *color) + ctx.set_source(grad) + else: + ctx.set_source_rgba(BORDER_R / 255, BORDER_G / 255, BORDER_B / 255, BORDER_A) + ctx.set_line_width(BORDER_WIDTH) ctx.stroke() ctx.restore() From 83aad614cc390f0e167e9c3601570e2a17ee3e5b Mon Sep 17 00:00:00 2001 From: fun840 Date: Mon, 5 Dec 2022 18:54:53 -0500 Subject: [PATCH 2/3] Add absolute gradient --- xborders | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/xborders b/xborders index 7f7bac0..7fc7896 100755 --- a/xborders +++ b/xborders @@ -30,11 +30,13 @@ BORDER_G = 88 BORDER_B = 220 BORDER_A = 1 BORDER_GRADIENT_COLORS = [] +ABSOLUTE_GRADIENT = None NO_VERSION_NOTIFY = False OFFSETS = [0, 0, 0, 0] def set_border_rgba(args): + global BORDER_GRADIENT_COLORS, ABSOLUTE_GRADIENT if args.border_rgba: # solid color try: @@ -75,7 +77,12 @@ def set_border_rgba(args): color = colorsys.hsv_to_rgb(i / args.rainbow_steps, args.rainbow_value, args.rainbow_brightness) BORDER_GRADIENT_COLORS.append((*color, 1)) - + + # generate absolute gradient + if args.absolute_gradient: + ABSOLUTE_GRADIENT = cairo.LinearGradient(0, 0, *get_screen_size(Gdk.Display.get_default())) + for i, color in enumerate(BORDER_GRADIENT_COLORS): + ABSOLUTE_GRADIENT.add_color_stop_rgba(i / len(BORDER_GRADIENT_COLORS), *color) def get_version(): our_location = os.path.dirname(os.path.abspath(__file__)) @@ -142,6 +149,11 @@ def get_args(): help="The colors of the border as a gradient, separated by spaces. Example: #FF0000FF #00FF00FF", nargs="+", ) + parser.add_argument( + "--absolute-gradient", + action="store_true", + help="Use one gradient over the entire screen, and mask the borders to it", + ) color_group.add_argument( "--rainbow", action="store_true", @@ -150,7 +162,7 @@ def get_args(): parser.add_argument( "--rainbow-steps", type=int, - default=50, + default=20, help="The amount of colors in the rainbow gradient", ) parser.add_argument( @@ -493,10 +505,15 @@ class Highlight(Gtk.Window): ctx.rectangle(x, y, w, h) if BORDER_GRADIENT_COLORS: - grad = cairo.LinearGradient(x, y, x + w, y + h) - for i, color in enumerate(BORDER_GRADIENT_COLORS): - grad.add_color_stop_rgba(i / len(BORDER_GRADIENT_COLORS), *color) - ctx.set_source(grad) + + if ABSOLUTE_GRADIENT: + ctx.set_source(ABSOLUTE_GRADIENT) + else: + grad = cairo.LinearGradient(x, y, x + w, y + h) + for i, color in enumerate(BORDER_GRADIENT_COLORS): + grad.add_color_stop_rgba(i / len(BORDER_GRADIENT_COLORS), *color) + ctx.set_source(grad) + else: ctx.set_source_rgba(BORDER_R / 255, BORDER_G / 255, BORDER_B / 255, BORDER_A) From f6e20e09f652ab2bccc8c7efe8607aba8c957ec5 Mon Sep 17 00:00:00 2001 From: fun840 Date: Mon, 5 Dec 2022 19:06:25 -0500 Subject: [PATCH 3/3] Rename rainbow arguments to fit HSV --- xborders | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xborders b/xborders index 7fc7896..27d87c7 100755 --- a/xborders +++ b/xborders @@ -74,7 +74,7 @@ def set_border_rgba(args): elif args.rainbow: # rainbow for i in range(args.rainbow_steps): - color = colorsys.hsv_to_rgb(i / args.rainbow_steps, args.rainbow_value, args.rainbow_brightness) + color = colorsys.hsv_to_rgb(i / args.rainbow_steps, args.rainbow_saturation, args.rainbow_value) BORDER_GRADIENT_COLORS.append((*color, 1)) @@ -166,16 +166,16 @@ def get_args(): help="The amount of colors in the rainbow gradient", ) parser.add_argument( - "--rainbow-value", + "--rainbow-saturation", type=float, default=1, - help="The value / saturation of the colors when using --rainbow, on a scale from 0 to 1." + help="The saturation of the colors when using --rainbow, on a scale from 0 to 1." ) parser.add_argument( - "--rainbow-brightness", + "--rainbow-value", type=float, default=1, - help="The brightness of the colors when using --rainbow, on a scale from 0 to 1." + help="The value (brightness) of the colors when using --rainbow, on a scale from 0 to 1." ) parser.add_argument( "--border-mode",