diff --git a/cava/config b/cava/config new file mode 100644 index 0000000..6b6343d --- /dev/null +++ b/cava/config @@ -0,0 +1,291 @@ +# ┳┳┓┏┓┏┳┓┳┳┏┓┏┓┳┓ ┏┓┏┓┓┏┏┓ +# ┃┃┃┣┫ ┃ ┃┃┃┓┣ ┃┃━━┃ ┣┫┃┃┣┫ +# ┛ ┗┛┗ ┻ ┗┛┗┛┗┛┛┗ ┗┛┛┗┗┛┛┗ +# + + + + + +## Configuration file for CAVA. +# Remove the ; to change parameters. + +[general] + +# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0 +; mode = normal + +# Accepts only non-negative values. +; framerate = 60 + +# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off +# new as of 0.6.0 autosens of low values (dynamic range) +# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0 +; autosens = 1 +; overshoot = 20 + +# Manual sensitivity in %. If autosens is enabled, this will only be the initial value. +# 200 means double height. Accepts only non-negative values. +; sensitivity = 100 + +# The number of bars (0-512). 0 sets it to auto (fill up console). +# Bars' width and space between bars in number of characters. +; bars = 0 +; bar_width = 2 +; bar_spacing = 1 +# bar_height is only used for output in "noritake" format +; bar_height = 32 + +# For SDL width and space between bars is in pixels, defaults are: +; bar_width = 20 +; bar_spacing = 5 + +# sdl_glsl have these default values, they are only used to calulate max number of bars. +; bar_width = 1 +; bar_spacing = 0 + + +# Lower and higher cutoff frequencies for lowest and highest bars +# the bandwidth of the visualizer. +# Note: there is a minimum total bandwidth of 43Mhz x number of bars. +# Cava will automatically increase the higher cutoff if a too low band is specified. +; lower_cutoff_freq = 50 +; higher_cutoff_freq = 10000 + + +# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and +# only check for input once per second. Cava will wake up once input is detected. 0 = disable. +; sleep_timer = 0 + + +[input] + +# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss', 'jack' or 'shmem' +# Defaults to 'oss', 'pipewire', 'sndio', 'jack', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with. +# On Mac it defaults to 'portaudio' or 'fifo' +# On windows this is automatic and no input settings are needed. +# +# All input methods uses the same config variable 'source' +# to define where it should get the audio. +# +# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink +# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them). +# +# For pipewire 'source' will be the object name or object.serial of the device to capture from. +# Both input and output devices are supported. +# +# For alsa 'source' will be the capture device. +# For fifo 'source' will be the path to fifo-file. +# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address +# +# For sndio 'source' will be a raw recording audio descriptor or a monitoring sub-device, e.g. 'rsnd/2' or 'snd/1'. Default: 'default'. +# README.md contains further information on how to setup CAVA for sndio. +# +# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device. +# README.md contains further information on how to setup CAVA for OSS on FreeBSD. +# +# For jack 'source' will be the name of the JACK server to connect to, e.g. 'foobar'. Default: 'default'. +# README.md contains further information on how to setup CAVA for JACK. +# + method = pulse + source = auto + + method = pipewire + source = auto + +; method = alsa +; source = hw:Loopback,1 + +; method = fifo +; source = /tmp/mpd.fifo + +; method = shmem +; source = /squeezelite-AA:BB:CC:DD:EE:FF + +; method = portaudio +; source = auto + +; method = sndio +; source = default + +; method = oss +; source = /dev/dsp + +; method = jack +; source = default + +# The options 'sample_rate', 'sample_bits', 'channels' and 'autoconnect' can be configured for some input methods: +# sample_rate: fifo, pipewire, sndio, oss +# sample_bits: fifo, pipewire, sndio, oss +# channels: sndio, oss, jack +# autoconnect: jack +# Other methods ignore these settings. +# +# For 'sndio' and 'oss' they are only preferred values, i.e. if the values are not supported +# by the chosen audio device, the device will use other supported values instead. +# Example: 48000, 32 and 2, but the device only supports 44100, 16 and 1, then it +# will use 44100, 16 and 1. +# +; sample_rate = 44100 +; sample_bits = 16 +; channels = 2 +; autoconnect = 2 + + +[output] + +# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl' +# or 'sdl_glsl'. +# 'noncurses' (default) uses a buffer and cursor movements to only print +# changes from frame to frame in the terminal. Uses less resources and is less +# prone to tearing (vsync issues) than 'ncurses'. +# +# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data +# stream of the bar heights that can be used to send to other applications. +# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above. +# +# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display +# in graphic mode. It only support the 3000 series graphical VFDs for now. +# +# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context. +# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or +# use one of the predefined ones. +; method = noncurses + +# Orientation of the visualization. Can be 'bottom', 'top', 'left' or 'right'. +# Default is 'bottom'. Other orientations are only supported on sdl and ncruses +# output. Note: many fonts have weird glyphs for 'top' and 'right' characters, +# which can make ncurses not look right. +; orientation = bottom + +# Visual channels. Can be 'stereo' or 'mono'. +# 'stereo' mirrors both channels with low frequencies in center. +# 'mono' outputs left to right lowest to highest frequencies. +# 'mono_option' set mono to either take input from 'left', 'right' or 'average'. +# set 'reverse' to 1 to display frequencies the other way around. +; channels = stereo +; mono_option = average +; reverse = 0 + +# Raw output target. A fifo will be created if target does not exist. +; raw_target = /dev/stdout + +# Raw data format. Can be 'binary' or 'ascii'. +; data_format = binary + +# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530). +; bit_format = 16bit + +# Ascii max value. In 'ascii' mode range will run from 0 to value specified here +; ascii_max_range = 1000 + +# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters. +# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)). +; bar_delimiter = 59 +; frame_delimiter = 10 + +# sdl window size and position. -1,-1 is centered. +; sdl_width = 1000 +; sdl_height = 500 +; sdl_x = -1 +; sdl_y= -1 +; sdl_full_screen = 0 + +# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none' +# 'frequency' displays the lower cut off frequency of the bar above. +# Only supported on ncurses and noncurses output. +; xaxis = none + +# enable alacritty synchronized updates. 1 = on, 0 = off +# removes flickering in alacritty terminal emulator. +# defaults to off since the behaviour in other terminal emulators is unknown +; alacritty_sync = 0 + +# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders +; vertex_shader = pass_through.vert +; fragment_shader = bar_spectrum.frag + +; for glsl output mode, keep rendering even if no audio +; continuous_rendering = 0 + +# disable console blank (screen saver) in tty +# (Not supported on FreeBSD) +; disable_blanking = 0 + +# show a flat bar at the bottom of the screen when idle, 1 = on, 0 = off +; show_idle_bar_heads = 1 + +# show waveform instead of frequency spectrum, 1 = on, 0 = off +; waveform = 0 + +[color] + +# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow. +# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires +# a terminal that can change color definitions such as Gnome-terminal or rxvt. +# default is to keep current terminal color +; background = default +; foreground = default + +# SDL and sdl_glsl only support hex code colors, these are the default: +; background = '#111111' +; foreground = '#33ffff' + +# these are default +# Gradient mode, only hex defined colors are supported, +# background must also be defined in hex or remain commented out. 1 = on, 0 = off. +# You can define as many as 8 different colors. They range from bottom to top of screen +; gradient = 0 +; gradient_count = 8 +; gradient_color_1 = '#59cc33' +; gradient_color_2 = '#80cc33' +; gradient_color_3 = '#a6cc33' +; gradient_color_4 = '#cccc33' +; gradient_color_5 = '#cca633' +; gradient_color_6 = '#cc8033' +; gradient_color_7 = '#cc5933' +; gradient_color_8 = '#cc3333' + +# for matugen +gradient = 1 +gradient_count = 2 +gradient_color_1 = '#3b383e' +gradient_color_2 = '#d4bbfc' + +[smoothing] + +# Percentage value for integral smoothing. Takes values from 0 - 100. +# Higher values means smoother, but less precise. 0 to disable. +# DEPRECATED as of 0.8.0, use noise_reduction instead +; integral = 77 + +# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable. +; monstercat = 0 +; waves = 0 + +# Set gravity percentage for "drop off". Higher values means bars will drop faster. +# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop off". +# DEPRECATED as of 0.8.0, use noise_reduction instead +; gravity = 100 + + +# In bar height, bars that would have been lower that this will not be drawn. +# DEPRECATED as of 0.8.0 +; ignore = 0 + +# Noise reduction, int 0 - 100. default 77 +# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth +# 100 will be very slow and smooth, 0 will be fast but noisy. +; noise_reduction = 77 + + +[eq] + +# This one is tricky. You can have as much keys as you want. +# Remember to uncomment more than one key! More keys = more precision. +# Look at readme.md on github for further explanations and examples. +; 1 = 1 # bass +; 2 = 1 +; 3 = 1 # midtone +; 4 = 1 +; 5 = 1 # treble diff --git a/cava/shaders/bar_spectrum.frag b/cava/shaders/bar_spectrum.frag new file mode 100644 index 0000000..473301c --- /dev/null +++ b/cava/shaders/bar_spectrum.frag @@ -0,0 +1,73 @@ +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +// bar values. defaults to left channels first (low to high), then right (high to low). +uniform float bars[512]; + +uniform int bars_count; // number of bars (left + right) (configurable) +uniform int bar_width; // bar width (configurable), not used here +uniform int bar_spacing; // space between bars (configurable) + +uniform vec3 u_resolution; // window resolution + +// colors, configurable in cava config file (r,g,b) (0.0 - 1.0) +uniform vec3 bg_color; // background color +uniform vec3 fg_color; // foreground color + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; // gradient colors + +uniform float shader_time; // shader execution time s (not used here) + +uniform sampler2D inputTexture; // Texture from the last render pass (not used here) + +vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) { + // create color based on fraction of this color and next color + float yr = (y - y_min) / (y_max - y_min); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +void main() { + // find which bar to use based on where we are on the x axis + float x = u_resolution.x * fragCoord.x; + int bar = int(bars_count * fragCoord.x); + + // calculate a bar size + float bar_size = u_resolution.x / bars_count; + + // the y coordinate and bar values are the same + float y = bars[bar]; + + // make sure there is a thin line at bottom + if (y * u_resolution.y < 1.0) { + y = 1.0 / u_resolution.y; + } + + // draw the bar up to current height + if (y > fragCoord.y) { + // make some space between bars basen on settings + if (x > (bar + 1) * (bar_size)-bar_spacing) { + fragColor = vec4(bg_color, 1.0); + } else { + if (gradient_count == 0) { + fragColor = vec4(fg_color, 1.0); + } else { + // find which color in the configured gradient we are at + int color = int((gradient_count - 1) * fragCoord.y); + + // find where on y this and next color is supposed to be + float y_min = color / (gradient_count - 1.0); + float y_max = (color + 1.0) / (gradient_count - 1.0); + + // make color + fragColor = vec4(normalize_C(fragCoord.y, gradient_colors[color], + gradient_colors[color + 1], y_min, y_max), + 1.0); + } + } + } else { + fragColor = vec4(bg_color, 1.0); + } +} diff --git a/cava/shaders/eye_of_phi.frag b/cava/shaders/eye_of_phi.frag new file mode 100644 index 0000000..b66b607 --- /dev/null +++ b/cava/shaders/eye_of_phi.frag @@ -0,0 +1,117 @@ +#version 330 + +// this shader was stolen from shadertoy user ChunderFPV + +#define SCALE 8.0 +#define PI radians(180.0) +#define TAU (PI * 2.0) +#define CS(a) vec2(cos(a), sin(a)) +#define PT(u, r) smoothstep(0.0, r, r - length(u)) + +in vec2 fragCoord; +out vec4 fragColor; + +uniform float bars[512]; + +uniform int bars_count; // number of bars (left + right) (configurable) +uniform float shader_time; // shader execution time s +uniform int bar_width; // bar width (configurable), not used here +uniform int bar_spacing; // space between bars (configurable) + +uniform vec3 u_resolution; // window resolution + +// colors, configurable in cava config file (r,g,b) (0.0 - 1.0) +uniform vec3 bg_color; // background color +uniform vec3 fg_color; // foreground color + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; // gradient colors + +// gradient map ( color, equation, time, width, shadow, reciprocal ) +vec3 gm(vec3 c, float n, float t, float w, float d, bool i) { + float g = min(abs(n), 1.0 / abs(n)); + float s = abs(sin(n * PI - t)); + if (i) + s = min(s, abs(sin(PI / n + t))); + return (1.0 - pow(abs(s), w)) * c * pow(g, d) * 6.0; +} + +// denominator spiral, use 1/n for numerator +// ( screen xy, spiral exponent, decimal, line width, hardness, rotation ) +float ds(vec2 u, float e, float n, float w, float h, float ro) { + float ur = length(u); // unit radius + float sr = pow(ur, e); // spiral radius + float a = round(sr) * n * TAU; // arc + vec2 xy = CS(a + ro) * ur; // xy coords + float l = PT(u - xy, w); // line + float s = mod(sr + 0.5, 1.0); // gradient smooth + s = min(s, 1.0 - s); // darken filter + return l * s * h; +} + +void main() { + float t = shader_time / PI * 2.0; + vec4 m = vec4(0, 0, 0, 0); // iMouse; + m.xy = m.xy * 2.0 / u_resolution.xy - 1.0; // ±1x, ±1y + if (m.z > 0.0) + t += m.y * SCALE; // move time with mouse y + float z = (m.z > 0.0) ? pow(1.0 - abs(m.y), sign(m.y)) : 1.0; // zoom (+) + float e = (m.z > 0.0) ? pow(1.0 - abs(m.x), -sign(m.x)) + : 1.0; // screen exponent (+) + float se = (m.z > 0.0) ? e * -sign(m.y) : 1.0; // spiral exponent + vec3 bg = vec3(0); // black background + + float aa = 3.0; // anti-aliasing + + for (float j = 0.0; j < aa; j++) + for (float k = 0.0; k < aa; k++) { + vec3 c = vec3(0); + vec2 o = vec2(j, k) / aa; + vec2 uv = (fragCoord * u_resolution.xy - 0.5 * u_resolution.xy + o) / + u_resolution.y * SCALE * z; // apply cartesian, scale and zoom + if (m.z > 0.0) + uv = + exp(log(abs(uv)) * e) * sign(uv); // warp screen space with exponent + + float px = length(fwidth(uv)); // pixel width + float x = uv.x; // every pixel on x + float y = uv.y; // every pixel on y + float l = length(uv); // hypot of xy: sqrt(x*x+y*y) + + float mc = (x * x + y * y - 1.0) / y; // metallic circle at xy + float g = min(abs(mc), 1.0 / abs(mc)); // gradient + vec3 gold = vec3(1.0, 0.6, 0.0) * g * l; + vec3 blue = vec3(0.3, 0.5, 0.9) * (1.0 - g); + vec3 rgb = max(gold, blue); + + float w = 0.1; // line width + float d = 0.4; // shadow depth + c = max(c, gm(rgb, mc, -t, w * bars[0], d, false)); // metallic + c = max(c, gm(rgb, abs(y / x) * sign(y), -t, w * bars[1], d, + false)); // tangent + c = max(c, gm(rgb, (x * x) / (y * y) * sign(y), -t, w * bars[2], d, + false)); // sqrt cotangent + c = max(c, gm(rgb, (x * x) + (y * y), t, w * bars[3], d, + true)); // sqrt circles + + c += rgb * ds(uv, se, t / TAU, px * 2.0 * bars[4], 2.0, 0.0); // spiral 1a + c += rgb * ds(uv, se, t / TAU, px * 2.0 * bars[5], 2.0, PI); // spiral 1b + c += + rgb * ds(uv, -se, t / TAU, px * 2.0 * bars[6], 2.0, 0.0); // spiral 2a + c += rgb * ds(uv, -se, t / TAU, px * 2.0 * bars[7], 2.0, PI); // spiral 2b + c = max(c, 0.0); // clear negative color + + c += pow(max(1.0 - l, 0.0), 3.0 / z); // center glow + + if (m.z > 0.0) // display grid on click + { + vec2 xyg = abs(fract(uv + 0.5) - 0.5) / px; // xy grid + c.gb += 0.2 * (1.0 - min(min(xyg.x, xyg.y), 1.0)); + } + bg += c; + } + bg /= aa * aa; + bg *= sqrt(bg) * 1.5; + + fragColor = vec4(bg, 1.0); +} diff --git a/cava/shaders/northern_lights.frag b/cava/shaders/northern_lights.frag new file mode 100644 index 0000000..ecd859a --- /dev/null +++ b/cava/shaders/northern_lights.frag @@ -0,0 +1,34 @@ +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +// bar values. defaults to left channels first (low to high), then right (high to low). +uniform float bars[512]; + +uniform int bars_count; // number of bars (left + right) (configurable) + +uniform vec3 u_resolution; // window resolution, not used here + +//colors, configurable in cava config file +uniform vec3 bg_color; // background color(r,g,b) (0.0 - 1.0), not used here +uniform vec3 fg_color; // foreground color, not used here + +void main() +{ + // find which bar to use based on where we are on the x axis + int bar = int(bars_count * fragCoord.x); + + float bar_y = 1.0 - abs((fragCoord.y - 0.5)) * 2.0; + float y = (bars[bar]) * bar_y; + + float bar_x = (fragCoord.x - float(bar) / float(bars_count)) * bars_count; + float bar_r = 1.0 - abs((bar_x - 0.5)) * 2; + + bar_r = bar_r * bar_r * 2; + + // set color + fragColor.r = fg_color.x * y * bar_r; + fragColor.g = fg_color.y * y * bar_r; + fragColor.b = fg_color.z * y * bar_r; +} diff --git a/cava/shaders/orion_circle.frag b/cava/shaders/orion_circle.frag new file mode 100644 index 0000000..3180023 --- /dev/null +++ b/cava/shaders/orion_circle.frag @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2026 rezky_nightky + +// Static Orion (non-rotating) + +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +uniform float bars[512]; + +uniform int bars_count; +uniform int bar_width; +uniform int bar_spacing; + +uniform vec3 u_resolution; + +uniform vec3 bg_color; +uniform vec3 fg_color; + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; + +vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) { + const float EPS = 0.0001; + float yr = (y - y_min) / max(y_max - y_min, EPS); + yr = clamp(yr, 0.0, 1.0); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +void main() { + vec2 p = fragCoord - vec2(0.5); + p.x *= u_resolution.x / u_resolution.y; + + float base_radius = 0.35; + float max_len = 0.15; + float pad = 2.0 / u_resolution.y; + float min_r = max(base_radius - pad, 0.0); + float max_r = base_radius + max_len + pad; + + float r2 = dot(p, p); + if (r2 < min_r * min_r || r2 > max_r * max_r) { + fragColor = vec4(bg_color, 1.0); + return; + } + + float r = sqrt(r2); + + float theta = atan(p.y, p.x); + + float pi = radians(180.0); + float tau = pi * 2.0; + + float a = (theta + pi) / tau; + a = fract(a); + + int bc = min(bars_count, 512); + if (bc <= 0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + float cell = a * float(bc); + int bar = int(floor(cell)); + bar = clamp(bar, 0, bc - 1); + int bar_next = bar + 1; + if (bar_next >= bc) { + bar_next = 0; + } + float f = fract(cell); + + float fill = float(bar_width) / max(float(bar_width + bar_spacing), 1.0); + float angular = abs(f - 0.5); + float px = max(length(dFdx(p)), length(dFdy(p))); + float df = 0.35 * (float(bc) * px) / (tau * max(r, px)); + float gap_half = (1.0 - fill) * 0.5; + float eps = 1.0 / (float(bc) * 2048.0); + float gap_cap = max(gap_half - eps, 0.0); + float df_cap = min(gap_cap, fill * 0.15); + df = min(df, max(df_cap, 1e-6)); + float angular_alpha = 1.0 - smoothstep(fill * 0.5 - df, fill * 0.5 + df, angular); + angular_alpha *= step(angular, fill * 0.5 + df); + angular_alpha *= step(0.01, angular_alpha); + + float y0 = clamp(bars[bar], 0.0, 1.0); + float y1 = clamp(bars[bar_next], 0.0, 1.0); + float y = mix(y0, y1, f); + + float amp = y * (1.0 + 0.8 * (1.0 - y)); + + float min_len = 1.0 / u_resolution.y; + float max_len_cap = max(max_len - min_len, min_len); + float len = min(max(amp * max_len, min_len), max_len_cap); + float act = smoothstep(0.0, min_len / max_len, amp); + + float dr = clamp(px, min_len, 2.0 * min_len); + float inner = smoothstep(base_radius - dr, base_radius + dr, r); + float outer = 1.0 - smoothstep(base_radius + len - dr, base_radius + len + dr, r); + float radial_alpha = inner * outer * act; + float outer_cap = 1.0 - smoothstep(base_radius + max_len - dr, base_radius + max_len + dr, r); + radial_alpha *= outer_cap; + + float alpha = angular_alpha * radial_alpha; + alpha *= step(0.0035, alpha); + + if (alpha == 0.0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + vec3 col; + if (gradient_count == 0) { + col = fg_color; + } else { + if (gradient_count == 1) { + col = gradient_colors[0]; + } else { + int color = int(floor((gradient_count - 1) * amp)); + color = clamp(color, 0, gradient_count - 2); + float y_min = float(color) / (gradient_count - 1.0); + float y_max = float(color + 1) / (gradient_count - 1.0); + col = + normalize_C(amp, gradient_colors[color], gradient_colors[color + 1], y_min, y_max); + } + } + + fragColor = vec4(mix(bg_color, col, alpha), 1.0); +} diff --git a/cava/shaders/orion_circle_rotate.frag b/cava/shaders/orion_circle_rotate.frag new file mode 100644 index 0000000..67db217 --- /dev/null +++ b/cava/shaders/orion_circle_rotate.frag @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2026 rezky_nightky + +// Rotate Orion + +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +uniform float bars[512]; + +uniform int bars_count; +uniform int bar_width; +uniform int bar_spacing; + +uniform vec3 u_resolution; + +uniform vec3 bg_color; +uniform vec3 fg_color; + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; + +uniform float shader_time; + +vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) { + const float EPS = 0.0001; + float yr = (y - y_min) / max(y_max - y_min, EPS); + yr = clamp(yr, 0.0, 1.0); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +void main() { + vec2 p = fragCoord - vec2(0.5); + p.x *= u_resolution.x / u_resolution.y; + + float base_radius = 0.35; + float max_len = 0.15; + float pad = 2.0 / u_resolution.y; + float min_r = max(base_radius - pad, 0.0); + float max_r = base_radius + max_len + pad; + + float r2 = dot(p, p); + if (r2 < min_r * min_r || r2 > max_r * max_r) { + fragColor = vec4(bg_color, 1.0); + return; + } + + float r = sqrt(r2); + + float theta = atan(p.y, p.x); + + float pi = radians(180.0); + float tau = pi * 2.0; + + float a = (theta + pi) / tau; + a = fract(a); + + int bc = min(bars_count, 512); + if (bc <= 0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + // Note: rotation is achieved by phase-shifting bar sampling, not by rotating geometry. + float rotate_speed = 0.10; + float t = fract(shader_time * 0.1); + float phase = fract(t * (rotate_speed / 0.1)); + + float sweep_speed = 0.12; + float sweep_pos = fract(t * (sweep_speed / 0.1)); + float da = abs(a - sweep_pos); + da = min(da, 1.0 - da); + float sweep = 1.0 - smoothstep(0.0, 0.08 + fwidth(a), da); + + float a_sample = fract(a + phase); + + float cell = a_sample * float(bc); + int bar = int(floor(cell)); + bar = clamp(bar, 0, bc - 1); + int bar_next = bar + 1; + if (bar_next >= bc) { + bar_next = 0; + } + float f = fract(cell); + + float fill = float(bar_width) / max(float(bar_width + bar_spacing), 1.0); + float angular = abs(f - 0.5); + float px = max(length(dFdx(p)), length(dFdy(p))); + float df = 0.35 * (float(bc) * px) / (tau * max(r, px)); + float gap_half = (1.0 - fill) * 0.5; + float eps = 1.0 / (float(bc) * 2048.0); + float gap_cap = max(gap_half - eps, 0.0); + float df_cap = min(gap_cap, fill * 0.15); + df = min(df, max(df_cap, 1e-6)); + float angular_alpha = 1.0 - smoothstep(fill * 0.5 - df, fill * 0.5 + df, angular); + angular_alpha *= step(angular, fill * 0.5 + df); + angular_alpha *= step(0.01, angular_alpha); + + float y0 = clamp(bars[bar], 0.0, 1.0); + float y1 = clamp(bars[bar_next], 0.0, 1.0); + float y = mix(y0, y1, f); + + float amp = y * (1.0 + 0.8 * (1.0 - y)); + + float min_len = 1.0 / u_resolution.y; + float max_len_cap = max(max_len - min_len, min_len); + float len = min(max(amp * max_len, min_len), max_len_cap); + float act = smoothstep(0.0, min_len / max_len, amp); + + float dr = clamp(px, min_len, 2.0 * min_len); + float inner = smoothstep(base_radius - dr, base_radius + dr, r); + float outer = 1.0 - smoothstep(base_radius + len - dr, base_radius + len + dr, r); + float radial_alpha = inner * outer * act; + float outer_cap = 1.0 - smoothstep(base_radius + max_len - dr, base_radius + max_len + dr, r); + radial_alpha *= outer_cap; + + float alpha = angular_alpha * radial_alpha; + alpha *= step(0.0035, alpha); + + if (alpha == 0.0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + vec3 col; + if (gradient_count == 0) { + col = fg_color; + } else { + if (gradient_count == 1) { + col = gradient_colors[0]; + } else { + int color = int(floor((gradient_count - 1) * amp)); + color = clamp(color, 0, gradient_count - 2); + float y_min = float(color) / (gradient_count - 1.0); + float y_max = float(color + 1) / (gradient_count - 1.0); + col = normalize_C(amp, gradient_colors[color], gradient_colors[color + 1], y_min, y_max); + } + } + + col = min(col * (1.0 + 0.35 * sweep * alpha), vec3(1.0)); + + fragColor = vec4(mix(bg_color, col, alpha), 1.0); +} diff --git a/cava/shaders/orion_saturn_core.frag b/cava/shaders/orion_saturn_core.frag new file mode 100644 index 0000000..b8e4fc7 --- /dev/null +++ b/cava/shaders/orion_saturn_core.frag @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2026 rezky_nightky + +// Orion Saturn core + +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +uniform float bars[512]; + +uniform int bars_count; +uniform int bar_width; +uniform int bar_spacing; + +uniform vec3 u_resolution; + +uniform vec3 bg_color; +uniform vec3 fg_color; + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; + +vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) { + const float EPS = 0.0001; + float yr = (y - y_min) / max(y_max - y_min, EPS); + yr = clamp(yr, 0.0, 1.0); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +vec3 gradient_map(float amp) { + if (gradient_count == 0) { + return fg_color; + } + + if (gradient_count == 1) { + return gradient_colors[0]; + } + + int color = int(floor((gradient_count - 1) * amp)); + color = clamp(color, 0, gradient_count - 2); + float y_min = float(color) / (gradient_count - 1.0); + float y_max = float(color + 1) / (gradient_count - 1.0); + return normalize_C(amp, gradient_colors[color], gradient_colors[color + 1], y_min, y_max); +} + +void main() { + vec2 p = fragCoord - vec2(0.5); + p.x *= u_resolution.x / u_resolution.y; + + float base_radius = 0.35; + float max_len = 0.15; + float pad = 2.0 / u_resolution.y; + + float max_r = base_radius + max_len + pad; + + float r2 = dot(p, p); + if (r2 > max_r * max_r) { + fragColor = vec4(bg_color, 1.0); + return; + } + + int bc = min(bars_count, 512); + if (bc <= 0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + float r = sqrt(r2); + + float pi = radians(180.0); + float tau = pi * 2.0; + + float theta = atan(p.y, p.x); + float a = fract((theta + pi) / tau); + + float cell = a * float(bc); + int bar = int(floor(cell)); + bar = clamp(bar, 0, bc - 1); + int bar_next = bar + 1; + if (bar_next >= bc) { + bar_next = 0; + } + float f = fract(cell); + + float fill = float(bar_width) / max(float(bar_width + bar_spacing), 1.0); + float angular = abs(f - 0.5); + float px_ang = max(length(dFdx(p)), length(dFdy(p))); + float df = 0.35 * (float(bc) * px_ang) / (tau * max(r, px_ang)); + float gap_half = (1.0 - fill) * 0.5; + float eps = 1.0 / (float(bc) * 2048.0); + float gap_cap = max(gap_half - eps, 0.0); + float df_cap = min(gap_cap, fill * 0.15); + df = min(df, max(df_cap, 1e-6)); + float angular_alpha = 1.0 - smoothstep(fill * 0.5 - df, fill * 0.5 + df, angular); + angular_alpha *= step(angular, fill * 0.5 + df); + angular_alpha *= step(0.01, angular_alpha); + + float y0 = clamp(bars[bar], 0.0, 1.0); + float y1 = clamp(bars[bar_next], 0.0, 1.0); + float y = mix(y0, y1, f); + float amp = y * (1.0 + 0.8 * (1.0 - y)); + + float min_len = 1.0 / u_resolution.y; + float max_len_cap = max(max_len - min_len, min_len); + float len = min(max(amp * max_len, min_len), max_len_cap); + float act = smoothstep(0.0, min_len / max_len, amp); + + float dr = clamp(px_ang, min_len, 2.0 * min_len); + float inner = smoothstep(base_radius - dr, base_radius + dr, r); + float outer = 1.0 - smoothstep(base_radius + len - dr, base_radius + len + dr, r); + float radial_alpha = inner * outer * act; + float outer_cap = 1.0 - smoothstep(base_radius + max_len - dr, base_radius + max_len + dr, r); + radial_alpha *= outer_cap; + + float ring_alpha = angular_alpha * radial_alpha; + ring_alpha *= step(0.0035, ring_alpha); + + float core_energy = 0.0; + int core_samples = 0; + + int core_limit = min(bc, 64); + for (int i = 0; i < core_limit; i += 2) { + core_energy += clamp(bars[i], 0.0, 1.0); + core_samples++; + } + core_energy /= max(float(core_samples), 1.0); + + float core_amp = core_energy * (1.0 + 0.8 * (1.0 - core_energy)); + + float core_radius = mix(0.07, 0.25, clamp(core_amp * 1.1, 0.0, 1.0)); + + float px = 1.0 / u_resolution.y; + float core_edge = max(px * 1.5, 0.003); + float core_act = smoothstep(0.0, 0.04, core_amp); + + float core_feather = core_edge + dr; + float core_alpha = 1.0 - smoothstep(core_radius - core_feather, core_radius + core_feather, r); + core_alpha = clamp(core_alpha, 0.0, 1.0) * core_act; + + if (ring_alpha == 0.0 && core_alpha == 0.0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + vec3 col_core = gradient_map(core_amp); + vec3 col_ring = gradient_map(amp); + + vec3 col = mix(bg_color, col_core, core_alpha); + col = mix(col, col_ring, ring_alpha); + fragColor = vec4(col, 1.0); +} diff --git a/cava/shaders/orion_saturn_subring.frag b/cava/shaders/orion_saturn_subring.frag new file mode 100644 index 0000000..9b274e2 --- /dev/null +++ b/cava/shaders/orion_saturn_subring.frag @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2026 rezky_nightky + +// Orion Saturn subring + +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +uniform float bars[512]; + +uniform int bars_count; +uniform int bar_width; +uniform int bar_spacing; + +uniform vec3 u_resolution; + +uniform vec3 bg_color; +uniform vec3 fg_color; + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; + +vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) { + const float EPS = 0.0001; + float yr = (y - y_min) / max(y_max - y_min, EPS); + yr = clamp(yr, 0.0, 1.0); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +vec3 gradient_map(float amp) { + if (gradient_count == 0) { + return fg_color; + } + + if (gradient_count == 1) { + return gradient_colors[0]; + } + + int color = int(floor((gradient_count - 1) * amp)); + color = clamp(color, 0, gradient_count - 2); + float y_min = float(color) / (gradient_count - 1.0); + float y_max = float(color + 1) / (gradient_count - 1.0); + return normalize_C(amp, gradient_colors[color], gradient_colors[color + 1], y_min, y_max); +} + +void main() { + vec2 p = fragCoord - vec2(0.5); + p.x *= u_resolution.x / u_resolution.y; + + float base_radius = 0.35; + float max_len = 0.15; + float pad = 2.0 / u_resolution.y; + + float max_r = base_radius + max_len + pad; + + float r2 = dot(p, p); + + if (r2 > max_r * max_r) { + fragColor = vec4(bg_color, 1.0); + return; + } + + int bc = min(bars_count, 512); + if (bc <= 0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + float r = sqrt(r2); + + float pi = radians(180.0); + float tau = pi * 2.0; + + float theta = atan(p.y, p.x); + float a = fract((theta + pi) / tau); + + float cell = a * float(bc); + int bar = int(floor(cell)); + bar = clamp(bar, 0, bc - 1); + int bar_next = bar + 1; + if (bar_next >= bc) { + bar_next = 0; + } + float f = fract(cell); + + float fill = float(bar_width) / max(float(bar_width + bar_spacing), 1.0); + float angular = abs(f - 0.5); + float px = max(length(dFdx(p)), length(dFdy(p))); + float df = 0.35 * (float(bc) * px) / (tau * max(r, px)); + float gap_half = (1.0 - fill) * 0.5; + float eps = 1.0 / (float(bc) * 2048.0); + float gap_cap = max(gap_half - eps, 0.0); + float df_cap = min(gap_cap, fill * 0.15); + df = min(df, max(df_cap, 1e-6)); + float angular_alpha = 1.0 - smoothstep(fill * 0.5 - df, fill * 0.5 + df, angular); + angular_alpha *= step(angular, fill * 0.5 + df); + angular_alpha *= step(0.01, angular_alpha); + + float y0 = clamp(bars[bar], 0.0, 1.0); + float y1 = clamp(bars[bar_next], 0.0, 1.0); + float y = mix(y0, y1, f); + float amp = y * (1.0 + 0.8 * (1.0 - y)); + + float min_len = 1.0 / u_resolution.y; + float max_len_cap = max(max_len - min_len, min_len); + float len = min(max(amp * max_len, min_len), max_len_cap); + float act = smoothstep(0.0, min_len / max_len, amp); + + float dr = clamp(px, min_len, 2.0 * min_len); + float inner = smoothstep(base_radius - dr, base_radius + dr, r); + float outer = 1.0 - smoothstep(base_radius + len - dr, base_radius + len + dr, r); + float radial_alpha = inner * outer * act; + float outer_cap = 1.0 - smoothstep(base_radius + max_len - dr, base_radius + max_len + dr, r); + radial_alpha *= outer_cap; + + float ring_alpha = angular_alpha * radial_alpha; + ring_alpha *= step(0.0035, ring_alpha); + + float core_energy = 0.0; + int core_samples = 0; + + int core_limit = min(bc, 64); + for (int i = 0; i < core_limit; i += 4) { + core_energy += clamp(bars[i], 0.0, 1.0); + core_samples++; + } + core_energy /= max(float(core_samples), 1.0); + + float core_amp = core_energy * (1.0 + 0.8 * (1.0 - core_energy)); + float core_radius = mix(0.05, 0.18, clamp(core_amp * 1.2, 0.0, 1.0)); + + float core_act = smoothstep(0.0, 0.04, core_amp); + float core_half_thickness = 0.007; + + float core = smoothstep(core_radius - core_half_thickness - dr, + core_radius - core_half_thickness + dr, r) - + smoothstep(core_radius + core_half_thickness - dr, + core_radius + core_half_thickness + dr, r); + float core_alpha = clamp(core, 0.0, 1.0) * core_act; + + if (ring_alpha == 0.0 && core_alpha == 0.0) { + fragColor = vec4(bg_color, 1.0); + return; + } + + vec3 col_ring = gradient_map(amp); + vec3 col_core = gradient_map(core_amp); + + vec3 col = mix(bg_color, col_ring, ring_alpha); + col = mix(col, col_core, core_alpha); + fragColor = vec4(col, 1.0); +} diff --git a/cava/shaders/pass_through.vert b/cava/shaders/pass_through.vert new file mode 100644 index 0000000..a4f20e5 --- /dev/null +++ b/cava/shaders/pass_through.vert @@ -0,0 +1,14 @@ +#version 330 + + +// Input vertex data, different for all executions of this shader. +layout(location = 0) in vec3 vertexPosition_modelspace; + +// Output data ; will be interpolated for each fragment. +out vec2 fragCoord; + +void main() +{ + gl_Position = vec4(vertexPosition_modelspace,1); + fragCoord = (vertexPosition_modelspace.xy+vec2(1,1))/2.0; +} diff --git a/cava/shaders/spectrogram.frag b/cava/shaders/spectrogram.frag new file mode 100644 index 0000000..18afbe3 --- /dev/null +++ b/cava/shaders/spectrogram.frag @@ -0,0 +1,53 @@ +#version 330 + +in vec2 fragCoord; +out vec4 fragColor; + +// bar values. defaults to left channels first (low to high), then right (high +// to low). +uniform float bars[512]; + +uniform int bars_count; // number of bars (left + right) (configurable) +uniform int bar_width; // bar width (configurable), not used here +uniform int bar_spacing; // space between bars (configurable) + +uniform vec3 u_resolution; // window resolution + +// colors, configurable in cava config file (r,g,b) (0.0 - 1.0) +uniform vec3 bg_color; // background color +uniform vec3 fg_color; // foreground color + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; // gradient colors + +uniform sampler2D inputTexture; // Texture from the last render pass + +vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) { + // create color based on fraction of this color and next color + float yr = (y - y_min) / (y_max - y_min); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +void main() { + // find which bar to use based on where we are on the y axis + int bar = int(bars_count * fragCoord.y); + float y = bars[bar]; + float band_size = 1.0 / float(bars_count); + float current_band_min = bar * band_size; + float current_band_max = (bar + 1) * band_size; + + int hist_length = 512; + float win_size = 1.0 / hist_length; + + if (fragCoord.x > 1.0 - win_size) { + + if (fragCoord.y > current_band_min && fragCoord.y < current_band_max) { + + fragColor = vec4(fg_color * y, 1.0); + } + } else { + vec2 offsetCoord = fragCoord; + offsetCoord.x += float(win_size); + fragColor = texture(inputTexture, offsetCoord); + } +} diff --git a/cava/shaders/winamp_line_style_spectrum.frag b/cava/shaders/winamp_line_style_spectrum.frag new file mode 100644 index 0000000..3bcc24a --- /dev/null +++ b/cava/shaders/winamp_line_style_spectrum.frag @@ -0,0 +1,112 @@ +#version 330 + +// Emulate the "line style" spectrum analyzer from Winamp 2. +// Try this config for a demonstration: + +/* +[general] +bar_width = 2 +bar_spacing = 0 +higher_cutoff_freq = 22000 + +[output] +method = sdl_glsl +channels = mono +fragment_shader = winamp_line_style_spectrum.frag + +[color] +background = '#000000' +gradient = 1 +gradient_color_1 = '#319C08' +gradient_color_2 = '#29CE10' +gradient_color_3 = '#BDDE29' +gradient_color_4 = '#DEA518' +gradient_color_5 = '#D66600' +gradient_color_6 = '#CE2910' + +[smoothing] +noise_reduction = 10 +*/ + +in vec2 fragCoord; +out vec4 fragColor; + +// bar values. defaults to left channels first (low to high), then right (high to low). +uniform float bars[512]; + +uniform int bars_count; // number of bars (left + right) (configurable) +uniform int bar_width; // bar width (configurable), not used here +uniform int bar_spacing; // space between bars (configurable) + +uniform vec3 u_resolution; // window resolution + +//colors, configurable in cava config file (r,g,b) (0.0 - 1.0) +uniform vec3 bg_color; // background color +uniform vec3 fg_color; // foreground color + +uniform int gradient_count; +uniform vec3 gradient_colors[8]; // gradient colors + +vec3 normalize_C(float y,vec3 col_1, vec3 col_2, float y_min, float y_max) +{ + //create color based on fraction of this color and next color + float yr = (y - y_min) / (y_max - y_min); + return col_1 * (1.0 - yr) + col_2 * yr; +} + +void main() +{ + // find which bar to use based on where we are on the x axis + float x = u_resolution.x * fragCoord.x; + int bar = int(bars_count * fragCoord.x); + + //calculate a bar size + float bar_size = u_resolution.x / bars_count; + + //the y coordinate is stretched by 4X to resemble Winamp + float y = min(bars[bar] * 4.0, 1.0); + + // make sure there is a thin line at bottom + if (y * u_resolution.y < 1.0) + { + y = 1.0 / u_resolution.y; + } + + vec4 bar_color; + + if (gradient_count == 0) + { + bar_color = vec4(fg_color,1.0); + } + else + { + //find color in the configured gradient for the top of the bar + int color = int((gradient_count - 1) * y); + + //find where on y this and next color is supposed to be + float y_min = float(color) / (gradient_count - 1.0); + float y_max = float(color + 1) / (gradient_count - 1.0); + + //make a solid color for the entire bar + bar_color = vec4(normalize_C(y, gradient_colors[color], gradient_colors[color + 1], y_min, y_max), 1.0); + } + + + //draw the bar up to current height + if (y > fragCoord.y) + { + //make some space between bars based on settings + if (x > (bar + 1) * (bar_size) - bar_spacing) + { + fragColor = vec4(bg_color,1.0); + } + else + { + fragColor = bar_color; + } + } + else + { + fragColor = vec4(bg_color,1.0); + } +} diff --git a/cava/themes/solarized_dark b/cava/themes/solarized_dark new file mode 100644 index 0000000..200057c --- /dev/null +++ b/cava/themes/solarized_dark @@ -0,0 +1,15 @@ +[color] +background = '#001e26' +foreground = '#708183' + +gradient = 1 +gradient_color_1 = '#268bd2' +gradient_color_2 = '#6c71c4' +gradient_color_3 = '#cb4b16' + +horizontal_gradient = 1 +horizontal_gradient_color_1 = '#586e75' +horizontal_gradient_color_2 = '#b58900' +horizontal_gradient_color_3 = '#839496' + +blend_direction = 'up' \ No newline at end of file diff --git a/cava/themes/tricolor b/cava/themes/tricolor new file mode 100644 index 0000000..b908137 --- /dev/null +++ b/cava/themes/tricolor @@ -0,0 +1,10 @@ +[color] +horizontal_gradient = 1 +horizontal_gradient_color_1 = '#c45161' +horizontal_gradient_color_2 = '#e094a0' +horizontal_gradient_color_3 = '#f2b6c0' +horizontal_gradient_color_4 = '#f2dde1' +horizontal_gradient_color_5 = '#cbc7d8' +horizontal_gradient_color_6 = '#8db7d2' +horizontal_gradient_color_7 = '#5e62a9' +horizontal_gradient_color_8 = '#434279' \ No newline at end of file diff --git a/hypr/colors.conf b/hypr/colors.conf new file mode 100644 index 0000000..8bf3992 --- /dev/null +++ b/hypr/colors.conf @@ -0,0 +1,151 @@ + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$background = rgba(151218ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$error = rgba(ffb4abff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$error_container = rgba(93000aff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$inverse_on_surface = rgba(322f35ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$inverse_primary = rgba(69548dff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$inverse_surface = rgba(e7e0e8ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_background = rgba(e7e0e8ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_error = rgba(690005ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_error_container = rgba(ffdad6ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_primary = rgba(3a255bff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_primary_container = rgba(ecdcffff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_primary_fixed = rgba(240e45ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_primary_fixed_variant = rgba(513c73ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_secondary = rgba(342d40ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_secondary_container = rgba(eadef7ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_secondary_fixed = rgba(1f182aff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_secondary_fixed_variant = rgba(4b4357ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_surface = rgba(e7e0e8ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_surface_variant = rgba(cbc4cfff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_tertiary = rgba(4a252fff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_tertiary_container = rgba(ffd9e0ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_tertiary_fixed = rgba(32101aff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$on_tertiary_fixed_variant = rgba(643b45ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$outline = rgba(958e99ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$outline_variant = rgba(49454eff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$primary = rgba(d4bbfcff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$primary_container = rgba(513c73ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$primary_fixed = rgba(ecdcffff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$primary_fixed_dim = rgba(d4bbfcff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$scrim = rgba(000000ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$secondary = rgba(cec2dbff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$secondary_container = rgba(4b4357ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$secondary_fixed = rgba(eadef7ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$secondary_fixed_dim = rgba(cec2dbff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$shadow = rgba(000000ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$source_color = rgba(533d78ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface = rgba(151218ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_bright = rgba(3b383eff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_container = rgba(211e24ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_container_high = rgba(2c292fff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_container_highest = rgba(37343aff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_container_low = rgba(1d1a20ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_container_lowest = rgba(0f0d12ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_dim = rgba(151218ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_tint = rgba(d4bbfcff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$surface_variant = rgba(49454eff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$tertiary = rgba(f1b7c3ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$tertiary_container = rgba(643b45ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$tertiary_fixed = rgba(ffd9e0ff) + +$image = /home/sinsa/Pictures/wallpapers/viola-casa.jpg +$tertiary_fixed_dim = rgba(f1b7c3ff) + diff --git a/hypr/configs/UserAnimations.conf b/hypr/configs/UserAnimations.conf new file mode 100644 index 0000000..da01b8e --- /dev/null +++ b/hypr/configs/UserAnimations.conf @@ -0,0 +1,26 @@ + +animations { + enabled = yes + + bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + bezier = been, 0.24, 0.9, 0.25, 0.91 + bezier = been2, 0,0.94,0.5,0.99 + bezier = menu_decel, 0.1, 1, 0, 1 + bezier = linear, 0.0, 0.0, 1.0, 1.0 + bezier = wind, 0.05, 0.9, 0.1, 1.05 + bezier = winIn, 0.1, 1.1, 0.1, 1.1 + bezier = winOut, 0.3, -0.3, 0, 1 + bezier = slow, 0, 0.85, 0.3, 1 + bezier = overshot, 0.7, 0.6, 0.1, 1.1 + bezier = bounce, 1.1, 1.6, 0.1, 0.85 + bezier = sligshot, 1, -1, 0.15, 1.25 + bezier = nice, 0, 6.9, 0.5, -4.20 + + animation = windowsIn, 1, 5, slow, popin + animation = windowsOut, 1, 7, been, popin 70% + animation = windowsMove, 1, 5, wind, slide + animation = border, 1, 1, linear + animation = fade, 1, 5, overshot + animation = workspaces, 1, 5, wind + animation = windows, 1, 5, bounce, popin +} diff --git a/hypr/configs/input.conf b/hypr/configs/input.conf new file mode 100644 index 0000000..4b9222b --- /dev/null +++ b/hypr/configs/input.conf @@ -0,0 +1,29 @@ +input { + kb_layout = us + kb_variant = + kb_model = + kb_options = + kb_rules = + + follow_mouse = 1 + sensitivity = 0 # -1.0 - 1.0, 0 means no modification. + accel_profile=flat + follow_mouse=1 + force_no_accel=1 + + touchpad { + natural_scroll = true + } +} + +# https://wiki.hyprland.org/Configuring/Variables/#gestures +gestures { + workspace_swipe = true +} + +# Example per-device config +# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more +device { + name = epic-mouse-v1 + sensitivity = -0.5 +} diff --git a/hypr/configs/keybinds.conf b/hypr/configs/keybinds.conf new file mode 100644 index 0000000..af30952 --- /dev/null +++ b/hypr/configs/keybinds.conf @@ -0,0 +1,98 @@ +################### +### KEYBINDINGS ### +################### + +# See https://wiki.hyprland.org/Configuring/Keywords/ +$mainMod = SUPER # Sets "Windows" key as main modifier + +# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more +bind = $mainMod, Return, exec, $terminal +bind = $mainMod SHIFT, RETURN, exec, [float; size 800 550] $terminal +bind = $mainMod, Q, killactive, +bind = CTRL ALT, Delete, exec, hyprctl dispatch exit 0 # exit Hyprland +bind = $mainMod, E, exec, $fileManager +bind = $mainMod, Space, togglefloating, +bind = $mainMod, D, exec, $menu +bind = $mainMod, P, pseudo, # dwindle +bind = $mainMod, J, togglesplit, # dwindle +bind = $mainMod, R, exec, ~/.config/hypr/scripts/wbrestart.sh +bind = $mainMod, B, exec, xdg-open "https://" # default browser +bind = $mainMod, L, exec, ~/.config/hypr/scripts/hyprlock.sh +bind = $mainMod SHIFT, F, fullscreen +bind = $mainMod SHIFT, S, exec, ~/.config/hypr/scripts/screenshot.sh +bind = $mainMod, W, exec, ~/.config/hypr/scripts/wppicker.sh +bind = $mainMod SHIFT, Q, exec, ~/.config/hypr/scripts/KillActiveProcess.sh # Kill active process +bind = $mainMod, C, exec, hyprpicker -a +bind = $mainMod CTRL, B, exec, ~/.config/hypr/scripts/WaybarStyles.sh # Waybar Styles Menu +bind = $mainMod ALT, B, exec, ~/.config/hypr/scripts/WaybarLayout.sh # Waybar Layout Menu +bind = $mainMod, H, exec, pkill -SIGUSR1 waybar # Hide Waybar +bind = $mainMod SHIFT, E, exec, kitty yazi # Yazi File Manager + +# Move focus with mainMod + arrow keys +bind = $mainMod, left, movefocus, l +bind = $mainMod, right, movefocus, r +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d + +# Move Windows +bind = $mainMod CTRL, left, movewindow, l +bind = $mainMod CTRL, right, movewindow, r +bind = $mainMod CTRL, up, movewindow, u +bind = $mainMod CTRL, down, movewindow, d + +# Resize windows +binde = $mainMod SHIFT, left, resizeactive,-50 0 +binde = $mainMod SHIFT, right, resizeactive,50 0 +binde = $mainMod SHIFT, up, resizeactive,0 -50 +binde = $mainMod SHIFT, down, resizeactive,0 50 + +# Switch workspaces with mainMod + [0-9] +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 + +# Move active window to a workspace with mainMod + SHIFT + [0-9] +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 +bind = $mainMod SHIFT, 0, movetoworkspace, 10 + +# Example special workspace (scratchpad) +#bind = $mainMod, S, togglespecialworkspace, magic +#bind = $mainMod SHIFT, S, movetoworkspace, special:magic + +# Scroll through existing workspaces with mainMod + scroll +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# Move/resize windows with mainMod + LMB/RMB and dragging +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +# Laptop multimedia keys for volume and LCD brightness +bindel = ,XF86AudioRaiseVolume, exec, ~/.config/hypr/scripts/volume.sh --inc +bindel = ,XF86AudioLowerVolume, exec, ~/.config/hypr/scripts/volume.sh --dec +bindel = ,XF86AudioMute, exec, ~/.config/hypr/scripts/volume.sh --toggle +bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +bindel = ,XF86MonBrightnessUp, exec, ~/.config/hypr/scripts/brightness.sh --inc +bindel = ,XF86MonBrightnessDown, exec, ~/.config/hypr/scripts/brightness.sh --dec + +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous + diff --git a/hypr/configs/looknfeel.conf b/hypr/configs/looknfeel.conf new file mode 100644 index 0000000..a57cebd --- /dev/null +++ b/hypr/configs/looknfeel.conf @@ -0,0 +1,50 @@ +general { + gaps_in = 5 + gaps_out = 10 + + border_size = 2 + +# col.active_border = $outline + col.active_border = $primary $secondary 45deg + col.inactive_border = $outline_variant + + # Set to true enable resizing windows by clicking and dragging on borders and gaps + resize_on_border = true + + # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on + allow_tearing = false + + layout = dwindle +} + +# https://wiki.hyprland.org/Configuring/Variables/#decoration +decoration { + rounding = 10 + rounding_power = 2 + + # Change transparency of focused and unfocused windows + active_opacity = 1.0 + inactive_opacity = 1.0 + + shadow { + enabled = false + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } + + # https://wiki.hyprland.org/Configuring/Variables/#blur + blur { + enabled = true + size = 5 + passes = 3 + ignore_opacity = true + new_optimizations = true + special = false + popups = true + xray = true + + vibrancy = 0.1696 + } +} + diff --git a/hypr/configs/tags.conf b/hypr/configs/tags.conf new file mode 100644 index 0000000..107e071 --- /dev/null +++ b/hypr/configs/tags.conf @@ -0,0 +1,14 @@ +windowrule = match:class ^(mpv|vlc)$, tag +multimedia_video +windowrule = match:class ^(nm-applet|nm-connection-editor|blueman-manager|org.gnome.FileRoller)$, tag +settings + +windowrule = match:class ^(org.gnome.DiskUtility|wihotspot(-gui)?)$, tag +settings + + +#windowrule = tag, +multimedia_video, class:(mpv|vlc)$ + + +#windowrule = tag +settings, class:^(nm-applet|nm-connection-editor|blueman-manager|org.gnome.FileRoller)$ +#windowrule = tag +settings, class:^(org.gnome.DiskUtility|wihotspot(-gui)?)$ +#windowrule = tag +viewer, class:^(org.gnome.SystemMonitor)$ # system monitor +#windowrule = tag +viewer, class:^(org.gnome.Evince)$ # document viewer +#windowrule = tag +viewer, class:^(eog|org.gnome.Loupe)$ # image viewer diff --git a/hypr/configs/windowrules.conf b/hypr/configs/windowrules.conf new file mode 100644 index 0000000..8575265 --- /dev/null +++ b/hypr/configs/windowrules.conf @@ -0,0 +1,41 @@ +# APPLICATIONS OPACITY +# windowrule = opacity 0.8 override, match:class ^(org.gnome.Nautilus)$ +windowrule = opacity 0.9 override, match:class ^(gedit|org.gnome.TextEditor|mousepad)$ +windowrule = opacity 0.9 override, match:class ^(org.pulseaudio.pavucontrol)$ +windowrule = opacity 0.9 override, match:class ^(kitty)$ +windowrule = opacity 0.85 override 0.7 override 1 override, match:class ^(discord|vesktop|org.telegram.desktop)$ +windowrule = opacity 0.8 override 0.6 override 1 override, match:class ^(Spotify)$ +windowrule = opacity 0.9 override 0.7 override 1 override, match:class ^(zen)$ + +windowrule = opacity 1.0 override 1 override 1 override, match:class ^(zen-twilight)$ + + + +# FLOAT & SIZE +windowrule = size 900 506, float on, match:tag multimedia_video* +windowrule = float on, size 50% 60%, match:class ^(org.pulseaudio.pavucontrol)$ + +# Ignore maximize requests +windowrule = suppress_event maximize, match:class .* + +## Fix XWayland dragging +#windowrule = no_focus on, match:class ^$,title ^$,xwayland 1,float 1,fullscreen 0,pin 0 +# +## POP UPS AND DIALOGUES +# +#windowrulev2 = size 50%% 60%%, float, center, title:^(Save As|Save a File|Pick Files)$ +#windowrulev2 = size 70%% 60%%, float, initialTitle:^(Open Files)$ +# +# WAYBAR +layerrule = blur on, ignore_alpha 0.5, match:namespace waybar + +# NOTIFICATIONS +layerrule = ignore_alpha 0.5, match:namespace tag:notif* + +# LOGOUT +layerrule = blur on, match:namespace logout_dialog + +# SWAYNC +layerrule = blur on, ignore_alpha on, ignore_alpha 0.5, xray 0, match:namespace swaync-control-center +layerrule = blur on, ignore_alpha on, ignore_alpha 0.5, xray 0, match:namespace swaync-notification-window + diff --git a/hypr/configs/windowrules.conf.bk b/hypr/configs/windowrules.conf.bk new file mode 100644 index 0000000..6efe0be --- /dev/null +++ b/hypr/configs/windowrules.conf.bk @@ -0,0 +1,58 @@ +# APPLIACTIONS BLUR +#windowrule = noblur , tag:multimedia_video* +#windowrule = opacity 1.0, tag:multimedia_video* +#windowrule = opacity 0.8, tag:settings* +windowrule = opacity 0.8, class: ^(org.gnome.Nautilus)$ +windowrule = opacity 0.9, class:^(gedit|org.gnome.TextEditor|mousepad)$ +windowrule = opacity 0.9, class:^(org.pulseaudio.pavucontrol)$ +windowrule = opacity 0.9, class:^(kitty)$ +windowrule = opacity 0.85 override 0.7 override 1 override, class:^(discord|vesktop|org.telegram.desktop)$ +windowrule = opacity 0.8 override 0.6 override 1 override, class:^(Spotify)$ +windowrule = opacity 0.9 override 0.7 override 1 override, class:^(zen)$ +#windowrule = opacity 0.8 override 0.6 override 1 override, tag:viewer* + +# LAYER RULES +#layerrule = blur, rofi +#layerrule = ignorezero, rofi +#layerrule = ignorealpha 0.5, rofi +#layerrule = dimaround, rofi +#layerrule = animation popin 10%, rofi +#layerrule = blur, notifications +#layerrule = ignorezero, notifications +layerrule = blur, waybar +#layerrule = ignorezero, waybar +layerrule = ignorealpha 0.5, waybar +layerrule = ignorealpha 0.5, tag:notif* +layerrule = blur, logout_dialog + +# SWAYNC BLUR & XRAY +layerrule = blur, swaync-control-center +layerrule = blur, swaync-notification-window +layerrule = ignorezero, swaync-control-center +layerrule = ignorezero, swaync-notification-window +layerrule = ignorealpha 0.5, swaync-control-center +layerrule = ignorealpha 0.5, swaync-notification-window +layerrule = xray 0, swaync-control-center +layerrule = xray 0, swaync-notification-window + +#FLOAT +#windowrule = float, tag:settings* +#windowrule = float, tag:viewer* +#windowrule = float, tag:multimedia_video* +windowrule = size 900 506, tag:multimedia_video* +windowrule = float, class:^(org.pulseaudio.pavucontrol)$ +windowrule = size 50% 60%, class:^(org.pulseaudio.pavucontrol)$ + +# Ignore maximize requests from apps. You'll probably like this. +windowrule = suppressevent maximize, class:.* + +# Fix some dragging issues with XWayland +windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 + +# POP UPS AND DIALOGUES +windowrule = float, title:^(Save As|Save a File|Pick Files)$ +windowrule = size 50% 60%, title:^(Save As|Save a File|Pick Files)$ +windowrule = center, title:^(Save As|Save a File|Pick Files)$ + +windowrule = float, initialTitle:(Open Files) +windowrule = size 70% 60%, initialTitle:(Open Files) diff --git a/hypr/current_wallpaper b/hypr/current_wallpaper new file mode 120000 index 0000000..1d0b67c --- /dev/null +++ b/hypr/current_wallpaper @@ -0,0 +1 @@ +/home/sinsa/Pictures/wallpapers/viola-casa.jpg \ No newline at end of file diff --git a/hypr/hypridle.conf b/hypr/hypridle.conf new file mode 100644 index 0000000..d34424a --- /dev/null +++ b/hypr/hypridle.conf @@ -0,0 +1,35 @@ +general { + lock_cmd = pidof hyprlock || hyprlock # avoid starting multiple hyprlock instances. + before_sleep_cmd = loginctl lock-session # lock before suspend. + after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display. +# unlock_cmd = /home/sinsa/.local/bin/eduroamcondizionale +} + +listener { + timeout = 150 # 2.5min. + on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor. + on-resume = brightnessctl -r # monitor backlight restore. +} + +# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight. +listener { + timeout = 150 # 2.5min. + on-timeout = brightnessctl -sd rgb:kbd_backlight set 0 # turn off keyboard backlight. + on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight. +} + +listener { + timeout = 300 # 5min + on-timeout = loginctl lock-session # lock screen when timeout has passed +} + +listener { + timeout = 330 # 5.5min + on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed + on-resume = hyprctl dispatch dpms on && brightnessctl -r # screen on when activity is detected after timeout has fired. +} + +listener { + timeout = 1800 # 30min + on-timeout = systemctl suspend # suspend pc +} diff --git a/hypr/hyprland.conf b/hypr/hyprland.conf new file mode 100644 index 0000000..59773c6 --- /dev/null +++ b/hypr/hyprland.conf @@ -0,0 +1,450 @@ +# ####################################################################################### +# AUTOGENERATED HYPRLAND CONFIG. +# EDIT THIS CONFIG ACCORDING TO THE WIKI INSTRUCTIONS. +# ####################################################################################### + + + +# This is an example Hyprland config file. +# Refer to the wiki for more information. +# https://wiki.hypr.land/Configuring/ + +# Please note not all available settings / options are set here. +# For a full list, see the wiki + +# You can split this configuration into multiple files +# Create your files separately and then link them to this file like this: +# source = ~/.config/hypr/myColors.conf +source = colors.conf + +################ +### MONITORS ### +################ + +# See https://wiki.hypr.land/Configuring/Monitors/ +monitor= eDP-1, 3072x1920@60, auto, auto + + + +################### +### MY PROGRAMS ### +################### + +# See https://wiki.hypr.land/Configuring/Keywords/ + +# Set programs that you use +$terminal = kitty +$fileManager = nautilus +# $menu = hyprlauncher +$menu = rofi -show drun + +################# +### AUTOSTART ### +################# + +# Autostart necessary processes (like notifications daemons, status bars, etc.) +# Or execute your favorite apps at launch like this: + +exec-once = $terminal +# exec-once = nm-applet & +# exec-once = waybar & hyprpaper +# exec-once = nm-applet +exec-once = awww-daemon +# exec-once = blueman-applet +exec-once = swaync +# exec-once = hyprpanel +# exec-once = hyprpaper +# exec-once = ashell & hyprpaper +exec-once = systemctl --user start hyprpolkitagent +#exec-once = nextcloud +exec-once =/usr/bin/nextcloud --background +exec-once = hypridle +exec-once = /home/sinsa/.local/bin/eduroamcondizionale +exec-once = sleep 0.5 ; waybar -c /home/sinsa/.config/waybar/configs/default -s /home/sinsa/.config/waybar/style/islands.css >> $HOME/.local/log/waybar.log +exec-once = wl-paste --type text --watch cliphist store +exec-once = wl-paste --type image --watch cliphist store +exec-once = vorta -d +exec-once = syncthing +############################# +### ENVIRONMENT VARIABLES ### +############################# + +# See https://wiki.hypr.land/Configuring/Environment-variables/ + +env = XCURSOR_SIZE,24 +env = HYPRCURSOR_SIZE,24 + + +################### +### PERMISSIONS ### +################### + +# See https://wiki.hypr.land/Configuring/Permissions/ +# Please note permission changes here require a Hyprland restart and are not applied on-the-fly +# for security reasons + +# ecosystem { +# enforce_permissions = 1 +# } + +# permission = /usr/(bin|local/bin)/grim, screencopy, allow +# permission = /usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland, screencopy, allow +# permission = /usr/(bin|local/bin)/hyprpm, plugin, allow + + +##################### +### LOOK AND FEEL ### +##################### + +source= ~/.config/hypr/configs/looknfeel.conf + + +# ANIMATION +source= ~/.config/hypr/configs/UserAnimations.conf + + + + +# Ref https://wiki.hypr.land/Configuring/Workspace-Rules/ +# "Smart gaps" / "No gaps when only" +# uncomment all if you wish to use that. +# workspace = w[tv1], gapsout:0, gapsin:0 +# workspace = f[1], gapsout:0, gapsin:0 +# windowrule { +# name = no-gaps-wtv1 +# match:float = false +# match:workspace = w[tv1] +# +# border_size = 0 +# rounding = 0 +# } +# +# windowrule { +# name = no-gaps-f1 +# match:float = false +# match:workspace = f[1] +# +# border_size = 0 +# rounding = 0 +# } + +# See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more +dwindle { + pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below + preserve_split = true # You probably want this +} + +# See https://wiki.hypr.land/Configuring/Master-Layout/ for more +master { + new_status = master +} + +# https://wiki.hypr.land/Configuring/Variables/#misc +misc { + force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers + disable_hyprland_logo = true # If true disables the random hyprland logo / anime girl background. :( +} + + + +device { + name = royuan-rt100-wired-system-control + kb_layout = us +} + +############# +### INPUT ### +############# + +# https://wiki.hypr.land/Configuring/Variables/#input +input { + kb_layout = it +# kb_variant = intl +# kb_model = +# kb_options = +# kb_rules = + follow_mouse = 1 + sensitivity = 0 # -1.0 - 1.0, 0 means no modification. + + touchpad { + clickfinger_behavior = 0 + natural_scroll = true + } +} + +device { + name = royuan-rt100-wired-system-control + kb_layout = us + kb_variant = intl, + + } + + +device { + name = royuan-rt100-wired-keyboard + kb_layout = us + kb_variant = intl + } + +device { + name = royuan-rt100-wired-consumer-control + kb_layout = us + kb_variant = intl + } + + +device { + name = royuan-rt100-wired + kb_layout = us + kb_variant = intl + } + + + + +device { + name = at-translated-set-2-keyboard + kb_layout = it +} + + + +# +#input { +# kb_layout = us +# kb_variant = intl +# device = royuan-rt100-wired-keyboard +#} +# + + + +# See https://wiki.hypr.land/Configuring/Gestures + +# -------- GESTURES --------- + +# gesture = 3, horizontal, workspace +gesture = 3, swipe, move +gesture = 4, vertical, fullscreen, maximize +gesture = 4, horizontal, workspace +gesture = 3, pinchout, float +gesture = 3, pinchin, float + + + +# Example per-device config +# See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more +device { + name = epic-mouse-v1 + sensitivity = -0.5 +} + + +################### +### KEYBINDINGS ### +################### + +# See https://wiki.hypr.land/Configuring/Keywords/ +$mainMod = SUPER # Sets "Windows" key as main modifier + +# Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more +bind = $mainMod, Q, exec, $terminal +bind = $mainMod, C, killactive, +bind = $mainMod, M, exec, command -v hyprshutdown >/dev/null 2>&1 && hyprshutdown || hyprctl dispatch exit +bind = $mainMod, E, exec, $fileManager +bind = $mainMod, V, togglefloating, +bind = $mainMod, RETURN, exec, export PATH="$HOME/.local/bin:$PATH" && $menu +bind = $mainMod, P, pseudo, # dwindle +# bind = $mainMod, J, layoutmsg # dwindle +bind = $mainMod, J, layoutmsg, togglesplit +bind = $mainMod, N, exec, $HOME/.local/bin/hyprltm-net +bind = $mainMod, W, exec, /home/sinsa/.config/hypr/scripts/rw.sh +bind = $mainMod, O, exec, pkill waybar +bind = $mainMod SHIFT, O, exec, waybar -c $HOME/.config/waybar/configs/default -s $HOME/.config/waybar/style/islands.css +#OPEN COPY PASTE HYSTORY + +bind = $mainMod SHIFT, V, exec, cliphist list | rofi -dmenu | cliphist decode | wl-copy + + +# CONNECT AUTOMATICALLY TO EDUROAM + +bind = $mainMod, L, exec, $HOME/.local/bin/eduroam + + +# SWITCH KEYBOARD LAYOUT +# WIP!!! +# bind = $mainMod, space, + + +bind = $mainMod, Z, exec, $HOME/.local/bin/zen-twilight + + + +binde = SUPER SHIFT, 201, exec, notify-send hello + + +# Fullscreen window + +bind = $mainMod SHIFT, F, fullscreen, 0 +bind = $mainMod , F, fullscreen, 1 + + + + + +# Move focus with mainMod + arrow keys +bind = $mainMod, left, movefocus, l +bind = $mainMod, right, movefocus, r +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d + +# Switch workspaces with mainMod + [0-9] +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 + +bind = $mainMod CTRL, left, workspace, r-1 + +bind = $mainMod CTRL, right, workspace, r+1 + + +# Move active window to a workspace with mainMod + SHIFT + [0-9] +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 +bind = $mainMod SHIFT, 0, movetoworkspace, 10 + +bind = $mainMod CTRL SHIFT, left, movetoworkspace, r-1 +bind = $mainMod CTRL SHIFT, right, movetoworkspace, r+1 + +# Move window +bind = $mainMod SHIFT, left, movewindow, l +bind = $mainMod SHIFT, right, movewindow,r +bind = $mainMod SHIFT, up, movewindow, u +bind = $mainMod SHIFT, down, movewindow, d + + +# Resize window + +binde = $mainMod ALT, right, resizeactive, 10 0 +binde = $mainMod ALT, left, resizeactive, -10 0 +binde = $mainMod ALT, up, resizeactive, 0 -10 +binde = $mainMod ALT, down, resizeactive, 0 10 + +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# Move/resize windows with mainMod + LMB/RMB and dragging +bindm = $mainMod, mouse:272, movewindow +# bindm = $mainMod, mouse:273, resizewindow +bindm = $mainMod SHIFT, mouse:272, resizewindow + + +bind = , Print, exec, hyprshot -m region -o /home/sinsa/Pictures/Screenshots/ +bind = $mainMod ,Print, exec, hyprshot -zm region --clipboard-only -o /home/sinsa/Pictures/Screenshots/ + +# Laptop multimedia keys for volume and LCD brightness + +bindel = ,XF86AudioRaiseVolume, exec, $HOME/.config/hypr/scripts/volume.sh --inc +bindel = ,XF86AudioLowerVolume, exec, $HOME/.config/hypr/scripts/volume.sh --dec +bindel = ,XF86AudioMute, exec, $HOME/.config/hypr/scripts/volume.sh --toggle +bindel = ,XF86AudioMicMute, exec, $HOME/.config/hypr/scripts/volume.sh --toggle-mic +bindel = ,XF86MonBrightnessUp, exec, $HOME/.config/hypr/scripts/brightness.sh --inc +bindel = ,XF86MonBrightnessDown, exec, $HOME/.config/hypr/scripts/brightness.sh --dec + +#bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ +#bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +#bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +#bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +#bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+ +#bindel = ,XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%- + + + + + + +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous + + +# Lock +bindl=,switch:Lid Switch, exec, hyprlock + + + + + + + + + + +############################## +### WINDOWS AND WORKSPACES ### +############################## + + + + + + +# See https://wiki.hypr.land/Configuring/Window-Rules/ for more +# See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules + + + +### TAGS ### +source= ~/.config/hypr/configs/tags.conf + +# Example windowrules that are useful + +### WINDOWRULES AND LAYERRULES ### +source = ~/.config/hypr/configs/windowrules.conf + +#windowrule { +# # Ignore maximize requests from all apps. You'll probably like this. +# name = suppress-maximize-events +# match:class = .* +# +# suppress_event = maximize +#} +# +#windowrule { +# # Fix some dragging issues with XWayland +# name = fix-xwayland-drags +# match:class = ^$ +# match:title = ^$ +# match:xwayland = true +# match:float = true +# match:fullscreen = false +# match:pin = false +# +# no_focus = true +#} +# +## Hyprland-run windowrule +#windowrule { +# name = move-hyprland-run +# +# match:class = hyprland-run +# +# move = 20 monitor_h-120 +# float = yes +#} diff --git a/hypr/hyprland.conf.bk b/hypr/hyprland.conf.bk new file mode 100644 index 0000000..49a6f0e --- /dev/null +++ b/hypr/hyprland.conf.bk @@ -0,0 +1,480 @@ +# ####################################################################################### +# AUTOGENERATED HYPRLAND CONFIG. +# EDIT THIS CONFIG ACCORDING TO THE WIKI INSTRUCTIONS. +# ####################################################################################### + + + +# This is an example Hyprland config file. +# Refer to the wiki for more information. +# https://wiki.hypr.land/Configuring/ + +# Please note not all available settings / options are set here. +# For a full list, see the wiki + +# You can split this configuration into multiple files +# Create your files separately and then link them to this file like this: +# source = ~/.config/hypr/myColors.conf + + +################ +### MONITORS ### +################ + +# See https://wiki.hypr.land/Configuring/Monitors/ +monitor= DP-1, 3072x1920@140, auto, auto + + +################### +### MY PROGRAMS ### +################### + +# See https://wiki.hypr.land/Configuring/Keywords/ + +# Set programs that you use +$terminal = kitty +$fileManager = nautilus +# $menu = hyprlauncher +$menu = rofi -show drun + +################# +### AUTOSTART ### +################# + +# Autostart necessary processes (like notifications daemons, status bars, etc.) +# Or execute your favorite apps at launch like this: + +exec-once = $terminal +# exec-once = nm-applet & +# exec-once = waybar & hyprpaper +# exec-once = nm-applet +exec-once = waybar -c /home/sinsa/.config/waybar/configs/default -s /home/sinsa/.config/waybar/style/islands.css +exec-once = swww-daemon +exec-once = blueman-applet +exec-once = swaync +# exec-once = hyprpanel +# exec-once = hyprpaper +# exec-once = ashell & hyprpaper +exec-once = systemctl --user start hyprpolkitagent +exec-once = nextcloud +exec-once = hypridle +exec-once = /home/sinsa/.local/bin/eduroamcondizionale +############################# +### ENVIRONMENT VARIABLES ### +############################# + +# See https://wiki.hypr.land/Configuring/Environment-variables/ + +env = XCURSOR_SIZE,24 +env = HYPRCURSOR_SIZE,24 + + +################### +### PERMISSIONS ### +################### + +# See https://wiki.hypr.land/Configuring/Permissions/ +# Please note permission changes here require a Hyprland restart and are not applied on-the-fly +# for security reasons + +# ecosystem { +# enforce_permissions = 1 +# } + +# permission = /usr/(bin|local/bin)/grim, screencopy, allow +# permission = /usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland, screencopy, allow +# permission = /usr/(bin|local/bin)/hyprpm, plugin, allow + + +##################### +### LOOK AND FEEL ### +##################### + +# Refer to https://wiki.hypr.land/Configuring/Variables/ + +# https://wiki.hypr.land/Configuring/Variables/#general +general { + gaps_in = 5 + gaps_out = 20 + + border_size = 2 + + # https://wiki.hypr.land/Configuring/Variables/#variable-types for info about colors + +# CIANO TO BLU +# col.active_border = rgba(00ffffff) rgba(57a7e6ff) 45deg + + + col.active_border = rgba(00bbffff) rgba(57a7e6ff) 45deg + col.inactive_border = rgba(595959aa) + + # Set to true enable resizing windows by clicking and dragging on borders and gaps + resize_on_border = true + + # Please see https://wiki.hypr.land/Configuring/Tearing/ before you turn this on + allow_tearing = false + + layout = dwindle +} + +# https://wiki.hypr.land/Configuring/Variables/#decoration +decoration { + rounding = 10 + rounding_power = 2 + + # Change transparency of focused and unfocused windows + active_opacity = 1.0 + inactive_opacity = 1.0 + + shadow { + enabled = true + range = 4 + render_power = 3 + color = rgba(1a1a1aee) + } + + # https://wiki.hypr.land/Configuring/Variables/#blur + blur { + enabled = true + size = 3 + passes = 1 + + vibrancy = 0.1696 + } +} + + + +# https://wiki.hypr.land/Configuring/Variables/#animations +animations { + enabled = yes, please :) + + # Default curves, see https://wiki.hypr.land/Configuring/Animations/#curves + # NAME, X0, Y0, X1, Y1 + bezier = easeOutQuint, 0.23, 1, 0.32, 1 + bezier = easeInOutCubic, 0.65, 0.05, 0.36, 1 + bezier = linear, 0, 0, 1, 1 + bezier = almostLinear, 0.5, 0.5, 0.75, 1 + bezier = quick, 0.15, 0, 0.1, 1 + + # Default animations, see https://wiki.hypr.land/Configuring/Animations/ + # NAME, ONOFF, SPEED, CURVE, [STYLE] + animation = global, 1, 10, default + animation = border, 1, 5.39, easeOutQuint + animation = windows, 1, 4.79, easeOutQuint + animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% + animation = windowsOut, 1, 1.49, linear, popin 87% + animation = fadeIn, 1, 1.73, almostLinear + animation = fadeOut, 1, 1.46, almostLinear + animation = fade, 1, 3.03, quick + animation = layers, 1, 3.81, easeOutQuint + animation = layersIn, 1, 4, easeOutQuint, fade + animation = layersOut, 1, 1.5, linear, fade + animation = fadeLayersIn, 1, 1.79, almostLinear + animation = fadeLayersOut, 1, 1.39, almostLinear + animation = workspaces, 1, 1.94, almostLinear, fade + animation = workspacesIn, 1, 1.21, almostLinear, fade + animation = workspacesOut, 1, 1.94, almostLinear, fade + animation = zoomFactor, 1, 7, quick +} + +# Ref https://wiki.hypr.land/Configuring/Workspace-Rules/ +# "Smart gaps" / "No gaps when only" +# uncomment all if you wish to use that. +# workspace = w[tv1], gapsout:0, gapsin:0 +# workspace = f[1], gapsout:0, gapsin:0 +# windowrule { +# name = no-gaps-wtv1 +# match:float = false +# match:workspace = w[tv1] +# +# border_size = 0 +# rounding = 0 +# } +# +# windowrule { +# name = no-gaps-f1 +# match:float = false +# match:workspace = f[1] +# +# border_size = 0 +# rounding = 0 +# } + +# See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more +dwindle { + pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below + preserve_split = true # You probably want this +} + +# See https://wiki.hypr.land/Configuring/Master-Layout/ for more +master { + new_status = master +} + +# https://wiki.hypr.land/Configuring/Variables/#misc +misc { + force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers + disable_hyprland_logo = true # If true disables the random hyprland logo / anime girl background. :( +} + + + +device { + name = royuan-rt100-wired-system-control + kb_layout = us +} + +############# +### INPUT ### +############# + +# https://wiki.hypr.land/Configuring/Variables/#input +input { + kb_layout = it +# kb_variant = intl +# kb_model = +# kb_options = +# kb_rules = + follow_mouse = 1 + sensitivity = 0 # -1.0 - 1.0, 0 means no modification. + + touchpad { + clickfinger_behavior = 0 + natural_scroll = true + } +} + +device { + name = royuan-rt100-wired-system-control + kb_layout = us + kb_variant = intl, + + kb_options = altwin:swap_alt_win, nodeadkeys +} + + +device { + name = royuan-rt100-wired-keyboard + kb_layout = us + kb_variant = intl + kb_options = altwin:swap_alt_win, nodeadkeys +} + +device { + name = royuan-rt100-wired-consumer-control + kb_layout = us + kb_variant = intl + kb_options = altwin:swap_alt_win, nodeadkeys +} + + +device { + name = royuan-rt100-wired + kb_layout = us + kb_variant = intl + kb_options = altwin:swap_alt_win, nodeadkeys +} + + + + +device { + name = at-translated-set-2-keyboard + kb_layout = it +} + + + +# +#input { +# kb_layout = us +# kb_variant = intl +# device = royuan-rt100-wired-keyboard +#} +# + + + +# See https://wiki.hypr.land/Configuring/Gestures + +# -------- GESTURES --------- + +# gesture = 3, horizontal, workspace +gesture = 3, swipe, move +gesture = 4, vertical, fullscreen, maximize +gesture = 4, horizontal, workspace +gesture = 3, pinchout, float +gesture = 3, pinchin, float + + + +# Example per-device config +# See https://wiki.hypr.land/Configuring/Keywords/#per-device-input-configs for more +device { + name = epic-mouse-v1 + sensitivity = -0.5 +} + + +################### +### KEYBINDINGS ### +################### + +# See https://wiki.hypr.land/Configuring/Keywords/ +$mainMod = SUPER # Sets "Windows" key as main modifier + +# Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more +bind = $mainMod, Q, exec, $terminal +bind = $mainMod, C, killactive, +bind = $mainMod, M, exec, command -v hyprshutdown >/dev/null 2>&1 && hyprshutdown || hyprctl dispatch exit +bind = $mainMod, E, exec, $fileManager +bind = $mainMod, V, togglefloating, +bind = $mainMod, RETURN, exec, $menu +bind = $mainMod, P, pseudo, # dwindle +bind = $mainMod, J, layoutmsg # dwindle +bind = $mainMod, N, exec, $HOME/.local/bin/hyprltm-net +bind = $mainMod, W, exec, /home/sinsa/.config/hypr/scripts/rw.sh + +# CONNECT AUTOMATICALLY TO EDUROAM + +bind = $mainMod, L, exec, $HOME/.local/bin/eduroam + + +# SWITCH KEYBOARD LAYOUT +# WIP!!! +# bind = $mainMod, space, + + +bind = $mainMod, Z, exec, /home/sinsa/.local/bin/zen-twilight + + +# Fullscreen window + +bind = $mainMod SHIFT, F, fullscreen, 0 +bind = $mainMod , F, fullscreen, 1 + + + + + +# Move focus with mainMod + arrow keys +bind = $mainMod, left, movefocus, l +bind = $mainMod, right, movefocus, r +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d + +# Switch workspaces with mainMod + [0-9] +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 + +# Move active window to a workspace with mainMod + SHIFT + [0-9] +bind = $mainMod CTRL, 1, movetoworkspace, 1 +bind = $mainMod CTRL, 2, movetoworkspace, 2 +bind = $mainMod CTRL, 3, movetoworkspace, 3 +bind = $mainMod CTRL, 4, movetoworkspace, 4 +bind = $mainMod CTRL, 5, movetoworkspace, 5 +bind = $mainMod CTRL, 6, movetoworkspace, 6 +bind = $mainMod CTRL, 7, movetoworkspace, 7 +bind = $mainMod CTRL, 8, movetoworkspace, 8 +bind = $mainMod CTRL, 9, movetoworkspace, 9 +bind = $mainMod CTRL, 0, movetoworkspace, 10 + + + +# Move window +bind = $mainMod SHIFT, left, movewindow, l +bind = $mainMod SHIFT, right, movewindow,r +bind = $mainMod SHIFT, up, movewindow, u +bind = $mainMod SHIFT, down, movewindow, d + + +# Resize window + +bind = $mainMod ALT, right, resizeactive, 10 0 +bind = $mainMod ALT, left, resizeactive, -10 0 +bind = $mainMod ALT, up, resizeactive, 0 -10 +bind = $mainMod ALT, down, resizeactive, 0 10 + +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 + +# Move/resize windows with mainMod + LMB/RMB and dragging +bindm = $mainMod, mouse:272, movewindow +# bindm = $mainMod, mouse:273, resizewindow +bindm = $mainMod SHIFT, mouse:272, resizewindow + + + +# Laptop multimedia keys for volume and LCD brightness +bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ +bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+ +bindel = ,XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%- + + + + + + +# Requires playerctl +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioPause, exec, playerctl play-pause +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPrev, exec, playerctl previous + + +# Lock +bindl=,switch:Lid Switch, exec, hyprlock + + + +############################## +### WINDOWS AND WORKSPACES ### +############################## + +# See https://wiki.hypr.land/Configuring/Window-Rules/ for more +# See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules + +# Example windowrules that are useful + +windowrule { + # Ignore maximize requests from all apps. You'll probably like this. + name = suppress-maximize-events + match:class = .* + + suppress_event = maximize +} + +windowrule { + # Fix some dragging issues with XWayland + name = fix-xwayland-drags + match:class = ^$ + match:title = ^$ + match:xwayland = true + match:float = true + match:fullscreen = false + match:pin = false + + no_focus = true +} + +# Hyprland-run windowrule +windowrule { + name = move-hyprland-run + + match:class = hyprland-run + + move = 20 monitor_h-120 + float = yes +} diff --git a/hypr/hyprlock.conf b/hypr/hyprlock.conf new file mode 100644 index 0000000..46d09f1 --- /dev/null +++ b/hypr/hyprlock.conf @@ -0,0 +1,148 @@ +source = colors.conf +$Scripts = $HOME/.config/hypr/scripts + +auth { + pam { + enabled = true + } + + + fingerprint { + enabled = true + ready_message = "Scan fingerprint to unlock" + present_message = "Scanning" + retry_delay = 250 + } + +} + + + +general { + grace = 1 + fractional_scaling = 2 + immediate_render = true +} + +background { + monitor = + # NOTE: use only 1 path + # path = screenshot # screenshot of your desktop + #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_modified # by wallpaper effects + path = ~/.config/hypr/current_wallpaper # CURRENT WALLPAPER + + color = rgb(0,0,0) # color will be rendered initially until path is available + + # all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations + blur_size = 3 + blur_passes = 2 # 0 disables blurring + noise = 0.0117 + contrast = 1.3000 # Vibrant!!! + brightness = 0.6000 + vibrancy = 0.2100 + vibrancy_darkness = 0.0 +} + + +# Hours +label { + monitor = + text = cmd[update:1000] echo " $(date +"%H") " + color = $on_secondary_container + font_size = 112 + font_family = Adwaita Sans + shadow_passes = 0 + shadow_size = 0 + + position = 0, 220 + halign = center + valign = center +} + +# Minutes +label { + monitor = + text = cmd[update:1000] echo " $(date +"%M") " + color = $on_secondary_container + font_size = 112 + font_family = Adwaita Sans + shadow_passes = 0 + shadow_size = 0 + + position = 0, 80 + halign = center + valign = center +} + +# Today +label { + monitor = + text = cmd[update:18000000] echo " "$(date +'%A')" " + color = $secondary + font_size = 18 + font_family = JetBrainsMono NFM + + position = 0, -15 + halign = center + valign = center +} + +# Week +label { + monitor = + text = cmd[update:18000000] echo " "$(date +'%d %b')" " + color = $secondary + font_size = 14 + font_family = JetBrainsMono Nerd Font 10 + + position = 0, -40 + halign = center + valign = center +} + +# Degrees +#label { + monitor = + text = cmd[update:18000000] echo "Feels like $(curl -s 'wttr.in?format=%t' | tr -d '+') " + color = $color8 + font_size = 14 + font_family = JetBrainsMono NFM + + position = 0, 40 + halign = center + valign = bottom +} + +# USER +#label { + monitor = + text = $USER + color = $color8 + font_size = 14 + font_family = JetBrainsMono NFM Bold + position = 0, 200 + halign = center + valign = bottom +} + +input-field { + monitor = + size = 250, 50 + outline_thickness = 3 + + dots_size = 0.26 # Scale of input-field height, 0.2 - 0.8 + dots_spacing = 0.64 # Scale of dots' absolute size, 0.0 - 1.0 + dots_center = true + dots_rouding = -1 + + rounding = 22 + outer_color = $source_color + inner_color = rgba(255, 255, 255, 0.1) + font_color = $secondary + fade_on_empty = true + placeholder_text = Password... # Text rendered in the input box when it's empty. + + position = 0, 120 + halign = center + valign = bottom +} diff --git a/hypr/hyprlock.conf.bk b/hypr/hyprlock.conf.bk new file mode 100644 index 0000000..59734a3 --- /dev/null +++ b/hypr/hyprlock.conf.bk @@ -0,0 +1,75 @@ + +auth { + pam { + enabled = true + } + + + fingerprint { + enabled = true + ready_message = "Scan fingerprint to unlock" + present_message = "Scanning" + retry_delay = 250 + } + +} + +background { + monitor = + path = ~/Pictures/Sfondi/4.jpg + blur_passes = 3 + contrast = 0.8916 + brightness = 0.8172 + vibrancy = 0.1696 + vibrancy_darkness = 0.0 +} + + + + +# Date display +label { + monitor = + text = cmd[update:1000] echo -e "$(LC_TIME=en_US.UTF-8 date +"%A, %B %d")" + color = rgba(216, 222, 233, 0.90) + font_size = 25 + font_family = SF Pro Display Semibold + position = 0, 350 + halign = center + valign = center +} + +# Time display +label { + monitor = + text = cmd[update:1000] echo "$(date +"%H:%M")" + color = rgba(216, 222, 233, 0.90) + font_size = 120 + font_family = SF Pro Display Bold + position = 0, 230 + halign = center + valign = center +} + + + +input-field { + monitor = + size = 280, 55 + outline_thickness = 2 + dots_size = 0.2 + dots_spacing = 0.2 + dots_center = true + outer_color = rgba(0, 0, 0, 0) + inner_color = rgba(255, 255, 255, 0.1) + font_color = rgb(200, 200, 200) + fade_on_empty = false + font_family = SF Pro Display Bold + placeholder_text = Hi Sinsa :) + hide_input = false + position = 0, -210 + halign = center + valign = center +} + + diff --git a/hypr/hyprpaper.conf b/hypr/hyprpaper.conf new file mode 100644 index 0000000..749ff15 --- /dev/null +++ b/hypr/hyprpaper.conf @@ -0,0 +1,14 @@ +preload=/home/sinsa/Pictures/hypr5.jpg +splash = false +# wallpaper { +# monitor = +# path = /home/sinsa/Pictures/Sfondi/6.jpg +# fit_mode = cover +# } + +wallpaper { + monitor = + path = /home/sinsa/.config/hypr/current_wallpaper + fit_mode = cover +} + diff --git a/hypr/scripts/AirplaneMode.sh b/hypr/scripts/AirplaneMode.sh new file mode 100755 index 0000000..db89ca5 --- /dev/null +++ b/hypr/scripts/AirplaneMode.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## +# Airplane Mode. Turning on or off all wifi using rfkill. + +notif="$HOME/.config/swaync/images/airplane.png" + +# Check if any wireless device is blocked +wifi_blocked=$(rfkill list wifi | grep -o "Soft blocked: yes") + +if [ -n "$wifi_blocked" ]; then + rfkill unblock wifi + notify-send -u low -i "$notif" " Airplane" " mode: OFF" +else + rfkill block wifi + notify-send -u low -i "$notif" " Airplane" " mode: ON" +fi diff --git a/hypr/scripts/KillActiveProcess.sh b/hypr/scripts/KillActiveProcess.sh new file mode 100755 index 0000000..bee146d --- /dev/null +++ b/hypr/scripts/KillActiveProcess.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## + +# Copied from Discord post. Thanks to @Zorg + + +# Get id of an active window +active_pid=$(hyprctl activewindow | grep -o 'pid: [0-9]*' | cut -d' ' -f2) + +# Close active window +kill $active_pid \ No newline at end of file diff --git a/hypr/scripts/WaybarLayout.sh b/hypr/scripts/WaybarLayout.sh new file mode 100755 index 0000000..18f4b93 --- /dev/null +++ b/hypr/scripts/WaybarLayout.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## +# Script for waybar layout or configs + +IFS=$'\n\t' + +# Define directories +waybar_layouts="$HOME/.config/waybar/configs" +waybar_config="$HOME/.config/waybar/config" +SCRIPTSDIR="$HOME/.config/hypr/scripts" +rofi_config="$HOME/.config/rofi/config.rasi" +msg=' Choose Waybar Layout ' + +# Function to display menu options +menu() { + options=() + while IFS= read -r file; do + options+=("$(basename "$file")") + done < <(find -L "$waybar_layouts" -maxdepth 1 -type f -exec basename {} \; | sort ) + + printf '%s\n' "${options[@]}" +} + +# Apply selected configuration +apply_config() { + ln -sf "$waybar_layouts/$1" "$waybar_config" + "${SCRIPTSDIR}/wbrestart.sh" & +} + +# Main function +main() { + choice=$(menu | rofi -i -dmenu -config "$rofi_config" -mesg "$msg") + + if [[ -z "$choice" ]]; then + echo "No option selected. Exiting." + exit 0 + fi + + case $choice in + "no panel") + pgrep -x "waybar" && pkill waybar || true + ;; + *) + apply_config "$choice" + ;; + esac +} + +# Kill Rofi if already running before execution +if pgrep -x "rofi" >/dev/null; then + pkill rofi + #exit 0 +fi + +main diff --git a/hypr/scripts/WaybarStyles.sh b/hypr/scripts/WaybarStyles.sh new file mode 100755 index 0000000..43c6790 --- /dev/null +++ b/hypr/scripts/WaybarStyles.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## +# Script for waybar styles + +IFS=$'\n\t' + +# Define directories +waybar_styles="$HOME/.config/waybar/style" +waybar_style="$HOME/.config/waybar/style.css" +SCRIPTSDIR="$HOME/.config/hypr/scripts" +rofi_config="$HOME/.config/rofi/config.rasi" +msg=' Choose Waybar Style' + +# Function to display menu options +menu() { + options=() + while IFS= read -r file; do + if [ -f "$waybar_styles/$file" ]; then + options+=("$(basename "$file" .css)") + fi + done < <(find -L "$waybar_styles" -maxdepth 1 -type f -name '*.css' -exec basename {} \; | sort ) + + printf '%s\n' "${options[@]}" +} + +# Apply selected style +apply_style() { + ln -sf "$waybar_styles/$1.css" "$waybar_style" + "${SCRIPTSDIR}/wbrestart.sh" & +} + +# Main function +main() { + choice=$(menu | rofi -i -dmenu -config "$rofi_config" -mesg "$msg") + + if [[ -z "$choice" ]]; then + echo "No option selected. Exiting." + exit 0 + fi + + apply_style "$choice" +} + +# Kill Rofi if already running before execution +if pgrep -x "rofi" >/dev/null; then + pkill rofi + #exit 0 +fi + +main diff --git a/hypr/scripts/Wlogout.sh b/hypr/scripts/Wlogout.sh new file mode 100755 index 0000000..2097474 --- /dev/null +++ b/hypr/scripts/Wlogout.sh @@ -0,0 +1,2 @@ +#!/bin/zsh +wlogout diff --git a/hypr/scripts/brightness.sh b/hypr/scripts/brightness.sh new file mode 100755 index 0000000..4473161 --- /dev/null +++ b/hypr/scripts/brightness.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## +# Script for Monitor backlights (if supported) using brightnessctl + +iDIR="$HOME/.config/swaync/icons" +notification_timeout=1000 +step=5 # INCREASE/DECREASE BY THIS VALUE + +# Get brightness +get_backlight() { + brightnessctl -m | cut -d, -f4 | sed 's/%//' +} + +# Get icons +get_icon() { + current=$(get_backlight) + if [ "$current" -le "20" ]; then + icon="$iDIR/brightness-20.png" + elif [ "$current" -le "40" ]; then + icon="$iDIR/brightness-40.png" + elif [ "$current" -le "60" ]; then + icon="$iDIR/brightness-60.png" + elif [ "$current" -le "80" ]; then + icon="$iDIR/brightness-80.png" + else + icon="$iDIR/brightness-100.png" + fi +} + +# Notify +notify_user() { + notify-send -e -h string:x-canonical-private-synchronous:brightness_notif -h int:value:$current -u low -i $icon "Screen" "Brightness:$current%" +} + +# Change brightness +change_backlight() { + local current_brightness + current_brightness=$(get_backlight) + + # Calculate new brightness + if [[ "$1" == "+${step}%" ]]; then + new_brightness=$((current_brightness + step)) + elif [[ "$1" == "${step}%-" ]]; then + new_brightness=$((current_brightness - step)) + fi + + # Ensure new brightness is within valid range + if ((new_brightness < 5)); then + new_brightness=5 + elif ((new_brightness > 100)); then + new_brightness=100 + fi + + brightnessctl set "${new_brightness}%" + get_icon + current=$new_brightness + notify_user +} + +# Execute accordingly +case "$1" in +"--get") + get_backlight + ;; +"--inc") + change_backlight "+${step}%" + ;; +"--dec") + change_backlight "${step}%-" + ;; +*) + get_backlight + ;; +esac diff --git a/hypr/scripts/hyprlock.sh b/hypr/scripts/hyprlock.sh new file mode 100755 index 0000000..a598b42 --- /dev/null +++ b/hypr/scripts/hyprlock.sh @@ -0,0 +1,2 @@ +#!/bin/zsh +hyprlock diff --git a/hypr/scripts/rw.sh b/hypr/scripts/rw.sh new file mode 100755 index 0000000..b516b3f --- /dev/null +++ b/hypr/scripts/rw.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +pkill waybar +waybar -c /home/sinsa/.config/waybar/configs/default -s /home/sinsa/.config/waybar/style/islands.css diff --git a/hypr/scripts/screenshot.sh b/hypr/scripts/screenshot.sh new file mode 100755 index 0000000..3208e7d --- /dev/null +++ b/hypr/scripts/screenshot.sh @@ -0,0 +1,2 @@ +!#/bin/zsh +grim -g "$(slurp)" & diff --git a/hypr/scripts/volume.sh b/hypr/scripts/volume.sh new file mode 100755 index 0000000..ea66410 --- /dev/null +++ b/hypr/scripts/volume.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## +# Scripts for volume controls for audio and mic + +iDIR="$HOME/.config/swaync/icons" +sDIR="$HOME/.config/hypr/scripts" + +# Get Volume +get_volume() { + volume=$(pamixer --get-volume) + if [[ "$volume" -eq "0" ]]; then + echo "Muted" + else + echo "$volume %" + fi +} + +# Get icons +get_icon() { + current=$(get_volume) + if [[ "$current" == "Muted" ]]; then + echo "$iDIR/volume-mute.png" + elif [[ "${current%\%}" -le 30 ]]; then + echo "$iDIR/volume-low.png" + elif [[ "${current%\%}" -le 60 ]]; then + echo "$iDIR/volume-mid.png" + else + echo "$iDIR/volume-high.png" + fi +} + +# Notify +notify_user() { + if [[ "$(get_volume)" == "Muted" ]]; then + notify-send -e -h string:x-canonical-private-synchronous:volume_notif -u low -i "$(get_icon)" " Volume:" " Muted" + else + notify-send -e -h int:value:"$(get_volume | sed 's/%//')" -h string:x-canonical-private-synchronous:volume_notif -u low -i "$(get_icon)" " Volume Level:" " $(get_volume)" && + "$sDIR/Sounds.sh" --volume + fi +} + +# Increase Volume +inc_volume() { + if [ "$(pamixer --get-mute)" == "true" ]; then + toggle_mute + else + pamixer -i 5 --allow-boost --set-limit 150 && notify_user + fi +} + +# Decrease Volume +dec_volume() { + if [ "$(pamixer --get-mute)" == "true" ]; then + toggle_mute + else + pamixer -d 5 && notify_user + fi +} + +# Toggle Mute +toggle_mute() { + if [ "$(pamixer --get-mute)" == "false" ]; then + pamixer -m && notify-send -e -u low -i "$iDIR/volume-mute.png" " Mute" + elif [ "$(pamixer --get-mute)" == "true" ]; then + pamixer -u && notify-send -e -u low -i "$(get_icon)" " Volume:" " Switched ON" + fi +} + +# Toggle Mic +toggle_mic() { + if [ "$(pamixer --default-source --get-mute)" == "false" ]; then + pamixer --default-source -m && notify-send -e -u low -i "$iDIR/microphone-mute.png" " Microphone:" " Switched OFF" + elif [ "$(pamixer --default-source --get-mute)" == "true" ]; then + pamixer -u --default-source u && notify-send -e -u low -i "$iDIR/microphone.png" " Microphone:" " Switched ON" + fi +} +# Get Mic Icon +get_mic_icon() { + current=$(pamixer --default-source --get-volume) + if [[ "$current" -eq "0" ]]; then + echo "$iDIR/microphone-mute.png" + else + echo "$iDIR/microphone.png" + fi +} + +# Get Microphone Volume +get_mic_volume() { + volume=$(pamixer --default-source --get-volume) + if [[ "$volume" -eq "0" ]]; then + echo "Muted" + else + echo "$volume %" + fi +} + +# Notify for Microphone +notify_mic_user() { + volume=$(get_mic_volume) + icon=$(get_mic_icon) + notify-send -e -h int:value:"$volume" -h "string:x-canonical-private-synchronous:volume_notif" -u low -i "$icon" " Mic Level:" " $volume" +} + +# Increase MIC Volume +inc_mic_volume() { + if [ "$(pamixer --default-source --get-mute)" == "true" ]; then + toggle_mic + else + pamixer --default-source -i 5 && notify_mic_user + fi +} + +# Decrease MIC Volume +dec_mic_volume() { + if [ "$(pamixer --default-source --get-mute)" == "true" ]; then + toggle-mic + else + pamixer --default-source -d 5 && notify_mic_user + fi +} + +# Execute accordingly +if [[ "$1" == "--get" ]]; then + get_volume +elif [[ "$1" == "--inc" ]]; then + inc_volume +elif [[ "$1" == "--dec" ]]; then + dec_volume +elif [[ "$1" == "--toggle" ]]; then + toggle_mute +elif [[ "$1" == "--toggle-mic" ]]; then + toggle_mic +elif [[ "$1" == "--get-icon" ]]; then + get_icon +elif [[ "$1" == "--get-mic-icon" ]]; then + get_mic_icon +elif [[ "$1" == "--mic-inc" ]]; then + inc_mic_volume +elif [[ "$1" == "--mic-dec" ]]; then + dec_mic_volume +else + get_volume +fi + diff --git a/hypr/scripts/vpn.sh b/hypr/scripts/vpn.sh new file mode 100755 index 0000000..4da33be --- /dev/null +++ b/hypr/scripts/vpn.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +ICON_CONN="󰒄" +ICON_DISCONN="󰲛" + +a=$(nmcli connection show --active | grep "casa") + +if [ $(nmcli connection show --active | grep "casa") ]; then + TEXT="$ICON_CONN" +else + TEXT="$ICON_DISCONN" +fi + +printf '{"text":"%s"}\n' "$TEXT" diff --git a/hypr/scripts/waybarcava.sh b/hypr/scripts/waybarcava.sh new file mode 100755 index 0000000..d31a05b --- /dev/null +++ b/hypr/scripts/waybarcava.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ## +# Not my own work. This was added through Github PR. Credit to original author + +#----- Optimized bars animation without much CPU usage increase -------- +bar="▁▂▃▄▅▆▇█" +dict="s/;//g" + +# Calculate the length of the bar outside the loop +bar_length=${#bar} + +# Create dictionary to replace char with bar +for ((i = 0; i < bar_length; i++)); do + dict+=";s/$i/${bar:$i:1}/g" +done + +# Create cava config +config_file="/tmp/bar_cava_config" +cat >"$config_file" </dev/null); do echo -en "$a\0icon\x1f$a\n"; done | rofi -dmenu -p "") +[ -z "$SELECTED_WALL" ] && exit 1 +SELECTED_PATH="$WALLPAPER_DIR/$SELECTED_WALL" + +# === SET WALLPAPER === +matugen image "$SELECTED_PATH" + +# === CREATE SYMLINK === +mkdir -p "$(dirname "$SYMLINK_PATH")" +ln -sf "$SELECTED_PATH" "$SYMLINK_PATH" diff --git a/kitty/colors.conf b/kitty/colors.conf new file mode 100644 index 0000000..e2349f3 --- /dev/null +++ b/kitty/colors.conf @@ -0,0 +1,27 @@ +# Core Colors +background #151218 +foreground #e7e0e8 +selection_foreground #d4bbfc +selection_background #3a255b +cursor #d4bbfc +cursor_text_color #151218 + +# Regular Colors +color0 #151218 +color1 #ffb4ab +color2 #d4bbfc +color3 #f1b7c3 +color4 #ecdcff +color5 #eadef7 +color6 #cec2db +color7 #e7e0e8 + +# Bright Colors +color8 #3b383e +color9 #ffb4ab +color10 #d4bbfc +color11 #f1b7c3 +color12 #ecdcff +color13 #eadef7 +color14 #cec2db +color15 #e7e0e8 diff --git a/kitty/current-theme.conf b/kitty/current-theme.conf new file mode 100644 index 0000000..dda305c --- /dev/null +++ b/kitty/current-theme.conf @@ -0,0 +1,80 @@ +# vim:ft=kitty + +## name: Catppuccin-Mocha +## author: Pocco81 (https://github.com/Pocco81) +## license: MIT +## upstream: https://github.com/catppuccin/kitty/blob/main/themes/mocha.conf +## blurb: Soothing pastel theme for the high-spirited! + + + +# The basic colors +foreground #CDD6F4 +background #1E1E2E +selection_foreground #1E1E2E +selection_background #F5E0DC + +# Cursor colors +cursor #F5E0DC +cursor_text_color #1E1E2E + +# URL underline color when hovering with mouse +url_color #F5E0DC + +# Kitty window border colors +active_border_color #B4BEFE +inactive_border_color #6C7086 +bell_border_color #F9E2AF + +# OS Window titlebar colors +wayland_titlebar_color system +macos_titlebar_color system + +# Tab bar colors +active_tab_foreground #11111B +active_tab_background #CBA6F7 +inactive_tab_foreground #CDD6F4 +inactive_tab_background #181825 +tab_bar_background #11111B + +# Colors for marks (marked text in the terminal) +mark1_foreground #1E1E2E +mark1_background #B4BEFE +mark2_foreground #1E1E2E +mark2_background #CBA6F7 +mark3_foreground #1E1E2E +mark3_background #74C7EC + +# The 16 terminal colors + +# black +color0 #45475A +color8 #585B70 + +# red +color1 #F38BA8 +color9 #F38BA8 + +# green +color2 #A6E3A1 +color10 #A6E3A1 + +# yellow +color3 #F9E2AF +color11 #F9E2AF + +# blue +color4 #89B4FA +color12 #89B4FA + +# magenta +color5 #F5C2E7 +color13 #F5C2E7 + +# cyan +color6 #94E2D5 +color14 #94E2D5 + +# white +color7 #BAC2DE +color15 #A6ADC8 diff --git a/kitty/current-theme.conf.old b/kitty/current-theme.conf.old new file mode 100644 index 0000000..dda305c --- /dev/null +++ b/kitty/current-theme.conf.old @@ -0,0 +1,80 @@ +# vim:ft=kitty + +## name: Catppuccin-Mocha +## author: Pocco81 (https://github.com/Pocco81) +## license: MIT +## upstream: https://github.com/catppuccin/kitty/blob/main/themes/mocha.conf +## blurb: Soothing pastel theme for the high-spirited! + + + +# The basic colors +foreground #CDD6F4 +background #1E1E2E +selection_foreground #1E1E2E +selection_background #F5E0DC + +# Cursor colors +cursor #F5E0DC +cursor_text_color #1E1E2E + +# URL underline color when hovering with mouse +url_color #F5E0DC + +# Kitty window border colors +active_border_color #B4BEFE +inactive_border_color #6C7086 +bell_border_color #F9E2AF + +# OS Window titlebar colors +wayland_titlebar_color system +macos_titlebar_color system + +# Tab bar colors +active_tab_foreground #11111B +active_tab_background #CBA6F7 +inactive_tab_foreground #CDD6F4 +inactive_tab_background #181825 +tab_bar_background #11111B + +# Colors for marks (marked text in the terminal) +mark1_foreground #1E1E2E +mark1_background #B4BEFE +mark2_foreground #1E1E2E +mark2_background #CBA6F7 +mark3_foreground #1E1E2E +mark3_background #74C7EC + +# The 16 terminal colors + +# black +color0 #45475A +color8 #585B70 + +# red +color1 #F38BA8 +color9 #F38BA8 + +# green +color2 #A6E3A1 +color10 #A6E3A1 + +# yellow +color3 #F9E2AF +color11 #F9E2AF + +# blue +color4 #89B4FA +color12 #89B4FA + +# magenta +color5 #F5C2E7 +color13 #F5C2E7 + +# cyan +color6 #94E2D5 +color14 #94E2D5 + +# white +color7 #BAC2DE +color15 #A6ADC8 diff --git a/kitty/kitty.conf b/kitty/kitty.conf new file mode 100644 index 0000000..0fe93a3 --- /dev/null +++ b/kitty/kitty.conf @@ -0,0 +1,3020 @@ +# vim:fileencoding=utf-8:foldmethod=marker + +#: Fonts {{{ + +#: kitty has very powerful font management. You can configure +#: individual font faces and even specify special fonts for particular +#: characters. + +# font_family monospace +# bold_font auto +# italic_font auto +# bold_italic_font auto + +#: You can specify different fonts for the bold/italic/bold-italic +#: variants. The easiest way to select fonts is to run the `kitten +#: choose-fonts` command which will present a nice UI for you to +#: select the fonts you want with previews and support for selecting +#: variable fonts and font features. If you want to learn to select +#: fonts manually, read the font specification syntax +#: . + +# font_size 11.0 + +#: Font size (in pts). + +# force_ltr no + +#: kitty does not support BIDI (bidirectional text), however, for RTL +#: scripts, words are automatically displayed in RTL. That is to say, +#: in an RTL script, the words "HELLO WORLD" display in kitty as +#: "WORLD HELLO", and if you try to select a substring of an RTL- +#: shaped string, you will get the character that would be there had +#: the string been LTR. For example, assuming the Hebrew word ירושלים, +#: selecting the character that on the screen appears to be ם actually +#: writes into the selection buffer the character י. kitty's default +#: behavior is useful in conjunction with a filter to reverse the word +#: order, however, if you wish to manipulate RTL glyphs, it can be +#: very challenging to work with, so this option is provided to turn +#: it off. Furthermore, this option can be used with the command line +#: program GNU FriBidi +#: to get BIDI support, because it will force kitty to always treat +#: the text as LTR, which FriBidi expects for terminals. + +# symbol_map + +#: E.g. symbol_map U+E0A0-U+E0A3,U+E0C0-U+E0C7 PowerlineSymbols + +#: Map the specified Unicode codepoints to a particular font. Useful +#: if you need special rendering for some symbols, such as for +#: Powerline. Avoids the need for patched fonts. Each Unicode code +#: point is specified in the form `U+`. You +#: can specify multiple code points, separated by commas and ranges +#: separated by hyphens. This option can be specified multiple times. +#: The syntax is:: + +#: symbol_map codepoints Font Family Name + +# narrow_symbols + +#: E.g. narrow_symbols U+E0A0-U+E0A3,U+E0C0-U+E0C7 1 + +#: Usually, for Private Use Unicode characters and some symbol/dingbat +#: characters, if the character is followed by one or more spaces, +#: kitty will use those extra cells to render the character larger, if +#: the character in the font has a wide aspect ratio. Using this +#: option you can force kitty to restrict the specified code points to +#: render in the specified number of cells (defaulting to one cell). +#: This option can be specified multiple times. The syntax is:: + +#: narrow_symbols codepoints [optionally the number of cells] + +# disable_ligatures never + +#: Choose how you want to handle multi-character ligatures. The +#: default is to always render them. You can tell kitty to not render +#: them when the cursor is over them by using cursor to make editing +#: easier, or have kitty never render them at all by using always, if +#: you don't like them. The ligature strategy can be set per-window +#: either using the kitty remote control facility or by defining +#: shortcuts for it in kitty.conf, for example:: + +#: map alt+1 disable_ligatures_in active always +#: map alt+2 disable_ligatures_in all never +#: map alt+3 disable_ligatures_in tab cursor + +#: Note that this refers to programming ligatures, typically +#: implemented using the calt OpenType feature. For disabling general +#: ligatures, use the font_features option. + +# font_features + +#: E.g. font_features none + +#: Choose exactly which OpenType features to enable or disable. Note +#: that for the main fonts, features can be specified when selecting +#: the font using the choose-fonts kitten. This setting is useful for +#: fallback fonts. + +#: Some fonts might have features worthwhile in a terminal. For +#: example, Fira Code includes a discretionary feature, zero, which in +#: that font changes the appearance of the zero (0), to make it more +#: easily distinguishable from Ø. Fira Code also includes other +#: discretionary features known as Stylistic Sets which have the tags +#: ss01 through ss20. + +#: For the exact syntax to use for individual features, see the +#: HarfBuzz documentation . + +#: Note that this code is indexed by PostScript name, and not the font +#: family. This allows you to define very precise feature settings; +#: e.g. you can disable a feature in the italic font but not in the +#: regular font. + +#: On Linux, font features are first read from the FontConfig database +#: and then this option is applied, so they can be configured in a +#: single, central place. + +#: To get the PostScript name for a font, use the `fc-scan file.ttf` +#: command on Linux or the `Font Book tool on macOS +#: `__. + +#: Enable alternate zero and oldstyle numerals:: + +#: font_features FiraCode-Retina +zero +onum + +#: Enable only alternate zero in the bold font:: + +#: font_features FiraCode-Bold +zero + +#: Disable the normal ligatures, but keep the calt feature which (in +#: this font) breaks up monotony:: + +#: font_features TT2020StyleB-Regular -liga +calt + +#: In conjunction with force_ltr, you may want to disable Arabic +#: shaping entirely, and only look at their isolated forms if they +#: show up in a document. You can do this with e.g.:: + +#: font_features UnifontMedium +isol -medi -fina -init + +# modify_font + +#: Modify font characteristics such as the position or thickness of +#: the underline and strikethrough. The modifications can have the +#: suffix px for pixels or % for percentage of original value. No +#: suffix means use pts. For example:: + +#: modify_font underline_position -2 +#: modify_font underline_thickness 150% +#: modify_font strikethrough_position 2px + +#: Additionally, you can modify the size of the cell in which each +#: font glyph is rendered and the baseline at which the glyph is +#: placed in the cell. For example:: + +#: modify_font cell_width 80% +#: modify_font cell_height -2px +#: modify_font baseline 3 + +#: Note that modifying the baseline will automatically adjust the +#: underline and strikethrough positions by the same amount. +#: Increasing the baseline raises glyphs inside the cell and +#: decreasing it lowers them. Decreasing the cell size might cause +#: rendering artifacts, so use with care. + +# box_drawing_scale 0.001, 1, 1.5, 2 + +#: The sizes of the lines used for the box drawing Unicode characters. +#: These values are in pts. They will be scaled by the monitor DPI to +#: arrive at a pixel value. There must be four values corresponding to +#: thin, normal, thick, and very thick lines. + +# undercurl_style thin-sparse + +#: The style with which undercurls are rendered. This option takes the +#: form (thin|thick)-(sparse|dense). Thin and thick control the +#: thickness of the undercurl. Sparse and dense control how often the +#: curl oscillates. With sparse the curl will peak once per character, +#: with dense twice. Changing this option dynamically via reloading +#: the config or remote control is undefined. + +# underline_exclusion 1 + +#: By default kitty renders gaps in underlines when they overlap with +#: descenders (the parts of letters below the baseline, such as for y, +#: q, p etc.). This option controls the thickness of the gaps. It can +#: be either a unitless number in which case it is a fraction of the +#: underline thickness as specified in the font or it can have a +#: suffix of px for pixels or pt for points. Set to zero to disable +#: the gaps. Changing this option dynamically via reloading the config +#: or remote control is undefined. + +# text_composition_strategy platform + +#: Control how kitty composites text glyphs onto the background color. +#: The default value of platform tries for text rendering as close to +#: "native" for the platform kitty is running on as possible. + +#: A value of legacy uses the old (pre kitty 0.28) strategy for how +#: glyphs are composited. This will make dark text on light +#: backgrounds look thicker and light text on dark backgrounds +#: thinner. It might also make some text appear like the strokes are +#: uneven. + +#: You can fine tune the actual contrast curve used for glyph +#: composition by specifying up to two space-separated numbers for +#: this setting. + +#: The first number is the gamma adjustment, which controls the +#: thickness of dark text on light backgrounds. Increasing the value +#: will make text appear thicker. The default value for this is 1.0 on +#: Linux and 1.7 on macOS. Valid values are 0.01 and above. The result +#: is scaled based on the luminance difference between the background +#: and the foreground. Dark text on light backgrounds receives the +#: full impact of the curve while light text on dark backgrounds is +#: affected very little. + +#: The second number is an additional multiplicative contrast. It is +#: percentage ranging from 0 to 100. The default value is 0 on Linux +#: and 30 on macOS. + +#: If you wish to achieve similar looking thickness in light and dark +#: themes, a good way to experiment is start by setting the value to +#: 1.0 0 and use a dark theme. Then adjust the second parameter until +#: it looks good. Then switch to a light theme and adjust the first +#: parameter until the perceived thickness matches the dark theme. + +# text_fg_override_threshold 0 + +#: A setting to prevent low contrast between foreground and background +#: colors. Useful when working with applications that use colors that +#: do not contrast well with your preferred color scheme. The default +#: value is 0, which means no color overriding is performed. There are +#: two modes of operation: + +#: A value with the suffix ratio represents the minimum accepted +#: contrast ratio between the foreground and background color. +#: Possible values range from 0.0 ratio to 21.0 ratio. For example, to +#: meet WCAG level AA +#: +#: a value of 4.5 ratio can be provided. The algorithm is implemented +#: using HSLuv which enables it to change the +#: perceived lightness of a color just as much as needed without +#: really changing its hue and saturation. + +#: A value with the suffix % represents the minimum accepted +#: difference in luminance between the foreground and background +#: color, below which kitty will override the foreground color. It is +#: percentage ranging from 0 % to 100 %. If the difference in +#: luminance of the foreground and background is below this threshold, +#: the foreground color will be set to white if the background is dark +#: or black if the background is light. + +#: WARNING: Some programs use characters (such as block characters) +#: for graphics display and may expect to be able to set the +#: foreground and background to the same color (or similar colors). If +#: you see unexpected stripes, dots, lines, incorrect color, no color +#: where you expect color, or any kind of graphic display problem try +#: setting text_fg_override_threshold to 0 to see if this is the cause +#: of the problem or consider using the ratio mode of operation +#: described above instead of the % mode of operation. + +#: }}} + +#: Text cursor customization {{{ + +# cursor #cccccc + +#: Default text cursor color. If set to the special value none the +#: cursor will be rendered with a "reverse video" effect. Its color +#: will be the color of the text in the cell it is over and the text +#: will be rendered with the background color of the cell. Note that +#: if the program running in the terminal sets a cursor color, this +#: takes precedence. Also, the cursor colors are modified if the cell +#: background and foreground colors have very low contrast. Note that +#: some themes set this value, so if you want to override it, place +#: your value after the lines where the theme file is included. + +# cursor_text_color #111111 + +#: The color of text under the cursor. If you want it rendered with +#: the background color of the cell underneath instead, use the +#: special keyword: `background`. Note that if cursor is set to none +#: then this option is ignored. Note that some themes set this value, +#: so if you want to override it, place your value after the lines +#: where the theme file is included. + +# cursor_shape block +cursor_trail 10 +cursor_trail_decay 0.1 0.3 +cursor_trail_start_threshold 0 + +#: The cursor shape can be one of block, beam, underline. Note that +#: when reloading the config this will be changed only if the cursor +#: shape has not been set by the program running in the terminal. This +#: sets the default cursor shape, applications running in the terminal +#: can override it. In particular, shell integration +#: in kitty sets +#: the cursor shape to beam at shell prompts. You can avoid this by +#: setting shell_integration to no-cursor. + + + +# cursor_shape_unfocused hollow + +#: Defines the text cursor shape when the OS window is not focused. +#: The unfocused cursor shape can be one of block, beam, underline, +#: hollow and unchanged (leave the cursor shape as it is). + +# cursor_beam_thickness 1.2 + +#: The thickness of the beam cursor (in pts). + +# cursor_underline_thickness 2.0 + +#: The thickness of the underline cursor (in pts). + +# cursor_blink_interval 1.5 + +#: The interval to blink the cursor (in seconds). Set to zero to +#: disable blinking. Negative values mean use system default. Note +#: that the minimum interval will be limited to repaint_delay. You can +#: also animate the cursor blink by specifying an easing function. For +#: example, setting this to option to 0.5 ease-in-out will cause the +#: cursor blink to be animated over a second, in the first half of the +#: second it will go from opaque to transparent and then back again +#: over the next half. You can specify different easing functions for +#: the two halves, for example: -1 linear ease-out. kitty supports all +#: the CSS easing functions . Note that turning on animations +#: uses extra power as it means the screen is redrawn multiple times +#: per blink interval. See also, cursor_stop_blinking_after. This +#: setting also controls blinking text, which blinks in exact rhythm +#: with the cursor. + +# cursor_stop_blinking_after 15.0 + +#: Stop blinking cursor after the specified number of seconds of +#: keyboard inactivity. Set to zero to never stop blinking. This +#: setting also controls blinking text, which blinks in exact rhythm +#: with the cursor. + +cursor_trail 1 + +#: Set this to a value larger than zero to enable a "cursor trail" +#: animation. This is an animation that shows a "trail" following the +#: movement of the text cursor. It makes it easy to follow large +#: cursor jumps and makes for a cool visual effect of the cursor +#: zooming around the screen. The actual value of this option controls +#: when the animation is triggered. It is a number of milliseconds. +#: The trail animation only follows cursors that have stayed in their +#: position for longer than the specified number of milliseconds. This +#: prevents trails from appearing for cursors that rapidly change +#: their positions during UI updates in complex applications. See +#: cursor_trail_decay to control the animation speed and +#: cursor_trail_start_threshold to control when a cursor trail is +#: started. + +cursor_trail_decay 0.1 0.4 + +#: Controls the decay times for the cursor trail effect when the +#: cursor_trail is enabled. This option accepts two positive float +#: values specifying the fastest and slowest decay times in seconds. +#: The first value corresponds to the fastest decay time (minimum), +#: and the second value corresponds to the slowest decay time +#: (maximum). The second value must be equal to or greater than the +#: first value. Smaller values result in a faster decay of the cursor +#: trail. Adjust these values to control how quickly the cursor trail +#: fades away. + +cursor_trail_start_threshold 2 + +#: Set the distance threshold for starting the cursor trail. This +#: option accepts a positive integer value that represents the minimum +#: number of cells the cursor must move before the trail is started. +#: When the cursor moves less than this threshold, the trail is +#: skipped, reducing unnecessary cursor trail animation. + +# cursor_trail_color none + +#: Set the color of the cursor trail when cursor_trail is enabled. If +#: set to 'none' (the default), the cursor trail will use the cursor's +#: background color. Otherwise, specify a color value (e.g., #ff0000 +#: for red, or a named color like 'red'). This allows you to customize +#: the appearance of the cursor trail independently of the cursor +#: color. + +#: }}} + +#: Scrollback {{{ + +scrollback_lines 5000 + +#: Number of lines of history to keep in memory for scrolling back. +#: Memory is allocated on demand. Negative numbers are (effectively) +#: infinite scrollback. Note that using very large scrollback is not +#: recommended as it can slow down performance of the terminal and +#: also use large amounts of RAM. Instead, consider using +#: scrollback_pager_history_size. Note that on config reload if this +#: is changed it will only affect newly created windows, not existing +#: ones. + +# scrollbar scrolled + +#: Control when the scrollbar is displayed. + +#: scrolled +#: means when the scrolling backwards has started. +#: hovered +#: means when the mouse is hovering on the right edge of the window. +#: scrolled-and-hovered +#: means when the mouse is over the scrollbar region *and* scrolling backwards has started. +#: always +#: means whenever any scrollback is present +#: never +#: means disable the scrollbar. + +# scrollbar_interactive yes + +#: If disabled, the scrollbar will not be controllable via th emouse +#: and all mouse events will pass through the scrollbar. + +# scrollbar_jump_on_click yes + +#: When enabled clicking in the scrollbar track will cause the scroll +#: position to jump to the clicked location, otherwise the scroll +#: position will only move towards the position by a single screenful, +#: which is how traditional scrollbars behave. + +# scrollbar_width 0.5 + +#: The width of the scroll bar in units of cell width. + +# scrollbar_hover_width 1 + +#: The width of the scroll bar when the mouse is hovering over it, in +#: units of cell width. + +# scrollbar_handle_opacity 0.5 + +#: The opacity of the scrollbar handle, 0 being fully transparent and +#: 1 being full opaque. + +# scrollbar_radius 0.3 + +#: The radius (curvature) of the scrollbar handle in units of cell +#: width. Should be less than scrollbar_width. + +# scrollbar_gap 0.1 + +#: The gap between the scrollbar and the window edge in units of cell +#: width. + +# scrollbar_min_handle_height 1 + +#: The minimum height of the scrollbar handle in units of cell height. +#: Prevents the handle from becoming too small when there is a lot of +#: scrollback. + +# scrollbar_hitbox_expansion 0.25 + +#: The extra area around the handle to allow easier grabbing of the +#: scollbar in units of cell width. + +# scrollbar_track_opacity 0 + +#: The opacity of the scrollbar track, 0 being fully transparent and 1 +#: being full opaque. + +# scrollbar_track_hover_opacity 0.1 + +#: The opacity of the scrollbar track when the mouse is over the +#: scrollbar, 0 being fully transparent and 1 being full opaque. + +# scrollbar_handle_color foreground + +#: The color of the scrollbar handle. A value of foreground means to +#: use the current foreground text color, a value of +#: selection_background means to use the current selection background +#: color. Also, you can use an arbitrary color, such as #12af59 or +#: red. + +# scrollbar_track_color foreground + +#: The color of the scrollbar track. A value of foreground means to +#: use the current foreground text color, a value of +#: selection_background means to use the current selection background +#: color. Also, you can use an arbitrary color, such as #12af59 or +#: red. + +# scrollback_pager less --chop-long-lines --RAW-CONTROL-CHARS +INPUT_LINE_NUMBER + +#: Program with which to view scrollback in a new window. The +#: scrollback buffer is passed as STDIN to this program. If you change +#: it, make sure the program you use can handle ANSI escape sequences +#: for colors and text formatting. INPUT_LINE_NUMBER in the command +#: line above will be replaced by an integer representing which line +#: should be at the top of the screen. Similarly CURSOR_LINE and +#: CURSOR_COLUMN will be replaced by the current cursor position or +#: set to 0 if there is no cursor, for example, when showing the last +#: command output. + +#: If you would rather use neovim to view the scrollback, use +#: something like this:: + +#: scrollback_pager nvim --cmd 'set eventignore=FileType' +'nnoremap q ZQ' +'call nvim_open_term(0, {})' +'set nomodified nolist' +'$' - + +#: The above works for neovim 0.12 and newer. There is also a +#: dedicated plugin kitty-scrollback.nvim +#: you can use +#: with more features that works with older neovim as well. + +# scrollback_pager_history_size 0 + +#: Separate scrollback history size (in MB), used only for browsing +#: the scrollback buffer with pager. This separate buffer is not +#: available for interactive scrolling but will be piped to the pager +#: program when viewing scrollback buffer in a separate window. The +#: current implementation stores the data in UTF-8, so approximately +#: 10000 lines per megabyte at 100 chars per line, for pure ASCII, +#: unformatted text. A value of zero or less disables this feature. +#: The maximum allowed size is 4GB. Note that on config reload if this +#: is changed it will only affect newly created windows, not existing +#: ones. + +# scrollback_fill_enlarged_window no + +#: Fill new space with lines from the scrollback buffer after +#: enlarging a window. + +# wheel_scroll_multiplier 5.0 + +#: Multiplier for the number of lines scrolled by the mouse wheel. +#: Note that this is only used for low precision scrolling devices, +#: not for high precision scrolling devices on platforms such as macOS +#: and Wayland. Use negative numbers to change scroll direction. See +#: also wheel_scroll_min_lines. + +# wheel_scroll_min_lines 1 + +#: The minimum number of lines scrolled by the mouse wheel. The scroll +#: multiplier wheel_scroll_multiplier only takes effect after it +#: reaches this number. Note that this is only used for low precision +#: scrolling devices like wheel mice that scroll by very small amounts +#: when using the wheel. With a negative number, the minimum number of +#: lines will always be added. + +# touch_scroll_multiplier 1.0 + +#: Multiplier for the number of lines scrolled by a touchpad. Note +#: that this is only used for high precision scrolling devices on +#: platforms such as macOS and Wayland. Use negative numbers to change +#: scroll direction. + +#: }}} + +#: Mouse {{{ + +# mouse_hide_wait 3.0 + +#: Hide mouse cursor after the specified number of seconds of the +#: mouse not being used. Set to zero to disable mouse cursor hiding. +#: Set to a negative value to hide the mouse cursor immediately when +#: typing text. Disabled by default on macOS as getting it to work +#: robustly with the ever-changing sea of bugs that is Cocoa is too +#: much effort. + +#: By default, once the cursor is hidden, it is immediately unhidden +#: on any further mouse events. + +#: Two formats are supported: +#: - +#: - + +#: To change the unhide behavior, the optional parameters , , and may be set. + +#: +#: Waits for the specified number of seconds after mouse events before unhiding the +#: mouse cursor. Set to zero to unhide mouse cursor immediately on mouse activity. +#: This is useful to prevent the mouse cursor from unhiding on accidental swipes on +#: the trackpad. + +#: +#: Sets the threshold of mouse activity required to unhide the mouse cursor, when +#: the option is non-zero. When is zero, this has no +#: effect. + +#: For example, if is 40 and is 2.5, when kitty +#: detects a mouse event, it records the number of mouse events in the next 2.5 +#: seconds, and checks if that exceeds 40 * 2.5 = 100. If it does, then the mouse +#: cursor is unhidden, otherwise nothing happens. + +#: +#: Controls what mouse events may unhide the mouse cursor. If enabled, both scroll +#: and movement events may unhide the cursor. If disabled, only mouse movements can +#: unhide the cursor. + +#: Examples of valid values: +#: - 0.0 +#: - 1.0 +#: - -1.0 +#: - 0.1 3.0 40 yes + +# url_color #0087bd +# url_style curly + +#: The color and style for highlighting URLs on mouse-over. url_style +#: can be one of: none, straight, double, curly, dotted, dashed. + +# open_url_with default + +#: The program to open clicked URLs. The special value default will +#: first look for any URL handlers defined via the open_actions +#: facility and if non +#: are found, it will use the Operating System's default URL handler +#: (open on macOS and xdg-open on Linux). + +# url_prefixes file ftp ftps gemini git gopher http https irc ircs kitty mailto news sftp ssh + +#: The set of URL prefixes to look for when detecting a URL under the +#: mouse cursor. + +# detect_urls yes + +#: Detect URLs under the mouse. Detected URLs are highlighted with an +#: underline and the mouse cursor becomes a hand over them. Even if +#: this option is disabled, URLs are still clickable. See also the +#: underline_hyperlinks option to control how hyperlinks (as opposed +#: to plain text URLs) are displayed. + +# url_excluded_characters + +#: Additional characters to be disallowed from URLs, when detecting +#: URLs under the mouse cursor. By default, all characters that are +#: legal in URLs are allowed. Additionally, newlines are allowed (but +#: stripped). This is to accommodate programs such as mutt that add +#: hard line breaks even for continued lines. \n can be added to this +#: option to disable this behavior. Special characters can be +#: specified using backslash escapes, to specify a backslash use a +#: double backslash. + +# show_hyperlink_targets no + +#: When the mouse hovers over a terminal hyperlink, show the actual +#: URL that will be activated when the hyperlink is clicked. + +# underline_hyperlinks hover + +#: Control how hyperlinks are underlined. They can either be +#: underlined on mouse hover, always (i.e. permanently underlined) or +#: never which means that kitty will not apply any underline styling +#: to hyperlinks. Note that the value of always only applies to real +#: (OSC 8) hyperlinks not text that is detected to be a URL on mouse +#: hover. Uses the url_style and url_color settings for the underline +#: style. Note that reloading the config and changing this value +#: to/from always will only affect text subsequently received by +#: kitty. + +# copy_on_select no + +#: Copy to clipboard or a private buffer on select. With this set to +#: clipboard, selecting text with the mouse will cause the text to be +#: copied to clipboard. Useful on platforms such as macOS that do not +#: have the concept of primary selection. You can instead specify a +#: name such as a1 to copy to a private kitty buffer. Map a shortcut +#: with the paste_from_buffer action to paste from this private +#: buffer. For example:: + +#: copy_on_select a1 +#: map shift+cmd+v paste_from_buffer a1 + +#: Note that copying to the clipboard is a security risk, as all +#: programs, including websites open in your browser can read the +#: contents of the system clipboard. + +# clear_selection_on_clipboard_loss no + +#: When the contents of the clipboard no longer reflect the current +#: selection, clear it. This is primarily useful on platforms such as +#: Linux where selecting text automatically copies it to a special +#: "primary selection" clipboard or if you have copy_on_select set to +#: clipboard. + +#: Note that on macOS the system does not provide notifications when +#: the clipboard owner is changed, so there, copying to clipboard in a +#: non-kitty application will not clear selections even if +#: copy_on_select is enabled. + +# paste_actions quote-urls-at-prompt,confirm + +#: A comma separated list of actions to take when pasting text into +#: the terminal. The supported paste actions are: + +#: quote-urls-at-prompt: +#: If the text being pasted is a URL and the cursor is at a shell prompt, +#: automatically quote the URL (needs shell_integration). +#: replace-dangerous-control-codes +#: Replace dangerous control codes from pasted text, without confirmation. +#: replace-newline +#: Replace the newline character from pasted text, without confirmation. +#: confirm: +#: Confirm the paste if the text to be pasted contains any terminal control codes +#: as this can be dangerous, leading to code execution if the shell/program running +#: in the terminal does not properly handle these. +#: confirm-if-large +#: Confirm the paste if it is very large (larger than 16KB) as pasting +#: large amounts of text into shells can be very slow. +#: filter: +#: Run the filter_paste() function from the file paste-actions.py in +#: the kitty config directory on the pasted text. The text returned by the +#: function will be actually pasted. +#: no-op: +#: Has no effect. + +# strip_trailing_spaces never + +#: Remove spaces at the end of lines when copying to clipboard. A +#: value of smart will do it when using normal selections, but not +#: rectangle selections. A value of always will always do it. + +# select_by_word_characters @-./_~?&=%+# + +#: Characters considered part of a word when double clicking. In +#: addition to these characters any character that is marked as an +#: alphanumeric character in the Unicode database will be matched. + +# select_by_word_characters_forward + +#: Characters considered part of a word when extending the selection +#: forward on double clicking. In addition to these characters any +#: character that is marked as an alphanumeric character in the +#: Unicode database will be matched. + +#: If empty (default) select_by_word_characters will be used for both +#: directions. + +# click_interval -1.0 + +#: The interval between successive clicks to detect double/triple +#: clicks (in seconds). Negative numbers will use the system default +#: instead, if available, or fallback to 0.5. + +# focus_follows_mouse no + +#: Set the active window to the window under the mouse when moving the +#: mouse around. On macOS, this will also cause the OS Window under +#: the mouse to be focused automatically when the mouse enters it. + +# pointer_shape_when_grabbed arrow + +#: The shape of the mouse pointer when the program running in the +#: terminal grabs the mouse. + +# default_pointer_shape beam + +#: The default shape of the mouse pointer. + +# pointer_shape_when_dragging beam crosshair + +#: The default shape of the mouse pointer when dragging across text. +#: The optional second value sets the shape when dragging in +#: rectangular selection mode. + +#: Mouse actions {{{ + +#: Mouse buttons can be mapped to perform arbitrary actions. The +#: syntax is: + +#: .. code-block:: none + +#: mouse_map button-name event-type modes action + +#: Where button-name is one of left, middle, right, b1 ... b8 with +#: added keyboard modifiers. For example: ctrl+shift+left refers to +#: holding the Ctrl+Shift keys while clicking with the left mouse +#: button. The value b1 ... b8 can be used to refer to up to eight +#: buttons on a mouse. + +#: event-type is one of press, release, doublepress, triplepress, +#: click, doubleclick. modes indicates whether the action is performed +#: when the mouse is grabbed by the program running in the terminal, +#: or not. The values are grabbed or ungrabbed or a comma separated +#: combination of them. grabbed refers to when the program running in +#: the terminal has requested mouse events. Note that the click and +#: double click events have a delay of click_interval to disambiguate +#: from double and triple presses. + +#: You can run kitty with the kitty --debug-input command line option +#: to see mouse events. See the builtin actions below to get a sense +#: of what is possible. + +#: If you want to unmap a button, map it to nothing. For example, to +#: disable opening of URLs with a plain click:: + +#: mouse_map left click ungrabbed + +#: See all the mappable actions including mouse actions here +#: . + +#: .. note:: +#: Once a selection is started, releasing the button that started it will +#: automatically end it and no release event will be dispatched. + +# clear_all_mouse_actions no + +#: Remove all mouse action definitions up to this point. Useful, for +#: instance, to remove the default mouse actions. + +#: Click the link under the mouse or move the cursor + +# mouse_map left click ungrabbed mouse_handle_click selection link prompt + +#:: First check for a selection and if one exists do nothing. Then +#:: check for a link under the mouse cursor and if one exists, click +#:: it. Finally check if the click happened at the current shell +#:: prompt and if so, move the cursor to the click location. Note +#:: that this requires shell integration +#:: to work. + +#: Click the link under the mouse or move the cursor even when grabbed + +# mouse_map shift+left click grabbed,ungrabbed mouse_handle_click selection link prompt + +#:: Same as above, except that the action is performed even when the +#:: mouse is grabbed by the program running in the terminal. + +#: Click the link under the mouse cursor + +# mouse_map ctrl+shift+left release grabbed,ungrabbed mouse_handle_click link + +#:: Variant with Ctrl+Shift is present because the simple click based +#:: version has an unavoidable delay of click_interval, to +#:: disambiguate clicks from double clicks. + +#: Discard press event for link click + +# mouse_map ctrl+shift+left press grabbed discard_event + +#:: Prevent this press event from being sent to the program that has +#:: grabbed the mouse, as the corresponding release event is used to +#:: open a URL. + +#: Paste from the primary selection + +# mouse_map middle release ungrabbed paste_from_selection + +#: Start selecting text + +# mouse_map left press ungrabbed mouse_selection normal + +#: Start selecting text in a rectangle + +# mouse_map ctrl+alt+left press ungrabbed mouse_selection rectangle + +#: Select a word + +# mouse_map left doublepress ungrabbed mouse_selection word + +#: Select a line + +# mouse_map left triplepress ungrabbed mouse_selection line + +#: Select line from point + +# mouse_map ctrl+alt+left triplepress ungrabbed mouse_selection line_from_point + +#:: Select from the clicked point to the end of the line. If you +#:: would like to select the word at the point and then extend to the +#:: rest of the line, change `line_from_point` to +#:: `word_and_line_from_point`. + +#: Extend the current selection + +# mouse_map right press ungrabbed mouse_selection extend + +#:: If you want only the end of the selection to be moved instead of +#:: the nearest boundary, use move-end instead of extend. + +#: Paste from the primary selection even when grabbed + +# mouse_map shift+middle release ungrabbed,grabbed paste_selection +# mouse_map shift+middle press grabbed discard_event + +#: Start selecting text even when grabbed + +# mouse_map shift+left press ungrabbed,grabbed mouse_selection normal + +#: Start selecting text in a rectangle even when grabbed + +# mouse_map ctrl+shift+alt+left press ungrabbed,grabbed mouse_selection rectangle + +#: Select a word even when grabbed + +# mouse_map shift+left doublepress ungrabbed,grabbed mouse_selection word + +#: Select a line even when grabbed + +# mouse_map shift+left triplepress ungrabbed,grabbed mouse_selection line + +#: Select line from point even when grabbed + +# mouse_map ctrl+shift+alt+left triplepress ungrabbed,grabbed mouse_selection line_from_point + +#:: Select from the clicked point to the end of the line even when +#:: grabbed. If you would like to select the word at the point and +#:: then extend to the rest of the line, change `line_from_point` to +#:: `word_and_line_from_point`. + +#: Extend the current selection even when grabbed + +# mouse_map shift+right press ungrabbed,grabbed mouse_selection extend + +#: Show clicked command output in pager + +# mouse_map ctrl+shift+right press ungrabbed mouse_show_command_output + +#:: Requires shell integration +#:: to work. + +#: }}} + +#: }}} + +#: Performance tuning {{{ + +# repaint_delay 10 + +#: Delay between screen updates (in milliseconds). Decreasing it, +#: increases frames-per-second (FPS) at the cost of more CPU usage. +#: The default value yields ~100 FPS which is more than sufficient for +#: most uses. Note that to actually achieve 100 FPS, you have to +#: either set sync_to_monitor to no or use a monitor with a high +#: refresh rate. Also, to minimize latency when there is pending input +#: to be processed, this option is ignored. + +# input_delay 3 + +#: Delay before input from the program running in the terminal is +#: processed (in milliseconds). Note that decreasing it will increase +#: responsiveness, but also increase CPU usage and might cause flicker +#: in full screen programs that redraw the entire screen on each loop, +#: because kitty is so fast that partial screen updates will be drawn. +#: This setting is ignored when the input buffer is almost full. + +# sync_to_monitor yes + +#: Sync screen updates to the refresh rate of the monitor. This +#: prevents screen tearing +#: when scrolling. +#: However, it limits the rendering speed to the refresh rate of your +#: monitor. With a very high speed mouse/high keyboard repeat rate, +#: you may notice some slight input latency. If so, set this to no. + +#: }}} + +#: Terminal bell {{{ + +# enable_audio_bell yes + +#: The audio bell. Useful to disable it in environments that require +#: silence. + +# visual_bell_duration 0.0 + +#: The visual bell duration (in seconds). Flash the screen when a bell +#: occurs for the specified number of seconds. Set to zero to disable. +#: The flash is animated, fading in and out over the specified +#: duration. The easing function used for the fading can be +#: controlled. For example, 2.0 linear will casuse the flash to fade +#: in and out linearly. The default if unspecified is to use ease-in- +#: out which fades slowly at the start, middle and end. You can +#: specify different easing functions for the fade-in and fade-out +#: parts, like this: 2.0 ease-in linear. kitty supports all the CSS +#: easing functions . + +# visual_bell_color none + +#: The color used by visual bell. Set to none will fall back to +#: selection background color. If you feel that the visual bell is too +#: bright, you can set it to a darker color. + +# window_alert_on_bell yes + +#: Request window attention on bell. Makes the dock icon bounce on +#: macOS or the taskbar flash on Linux. + +# bell_on_tab "🔔 " + +#: Some text or a Unicode symbol to show on the tab if a window in the +#: tab that does not have focus has a bell. If you want to use leading +#: or trailing spaces, surround the text with quotes. See +#: tab_title_template for how this is rendered. + +#: For backwards compatibility, values of yes, y and true are +#: converted to the default bell symbol and no, n, false and none are +#: converted to the empty string. + +# command_on_bell none + +#: Program to run when a bell occurs. The environment variable +#: KITTY_CHILD_CMDLINE can be used to get the program running in the +#: window in which the bell occurred. + +# bell_path none + +#: Path to a sound file to play as the bell sound. If set to none, the +#: system default bell sound is used. Must be in a format supported by +#: the operating systems sound API, such as WAV or OGA on Linux +#: (libcanberra) or AIFF, MP3 or WAV on macOS (NSSound). Relative +#: paths are resolved with respect to the kitty config directory. + +# linux_bell_theme __custom + +#: The XDG Sound Theme kitty will use to play the bell sound. On +#: Wayland, when the compositor supports it, it is asked to play the +#: system default bell sound, and this setting has no effect. Note +#: that Hyprland claims to support this protocol, but does not +#: actually play a sound +#: . This setting +#: defaults to the custom theme name specified in the XDG Sound theme +#: specification , falling back to the default +#: freedesktop theme if it does not exist. To change your sound theme +#: desktop wide, create +#: :file:~/.local/share/sounds/__custom/index.theme` with the +#: contents: + +#: [Sound Theme] + +#: Inherits=name-of-the-sound-theme-you-want-to-use + +#: Replace name-of-the-sound-theme-you-want-to-use with the actual +#: theme name. Now all compliant applications should use sounds from +#: this theme. + +#: }}} + +#: Window layout {{{ + +# remember_window_size yes +# initial_window_width 640 +# initial_window_height 400 + +#: If enabled, the OS Window size will be remembered so that new +#: instances of kitty will have the same size as the previous +#: instance. If disabled, the OS Window will initially have size +#: configured by initial_window_width/height, in pixels. You can use a +#: suffix of "c" on the width/height values to have them interpreted +#: as number of cells instead of pixels. + +# remember_window_position no + +#: If enabled, the OS Window position will be remembered so that new +#: instances of kitty will have the same position as the previous +#: instance. If disabled, the OS Window will be placed by the window +#: manager. Note that remembering of position only works if the +#: underlying desktop environment/window manager supports it. It never +#: works on Wayland. See also kitty --position to specify the position +#: when launching kitty. + +# enabled_layouts * + +#: The enabled window layouts. A comma separated list of layout names. +#: The special value all means all layouts. The first listed layout +#: will be used as the startup layout. Default configuration is all +#: layouts in alphabetical order. For a list of available layouts, see +#: the layouts . + +# window_resize_step_cells 2 +# window_resize_step_lines 2 + +#: The step size (in units of cell width/cell height) to use when +#: resizing kitty windows in a layout with the shortcut +#: start_resizing_window. The cells value is used for horizontal +#: resizing, and the lines value is used for vertical resizing. + +# window_border_width 0.5pt + +#: The width of window borders. Can be either in pixels (px) or pts +#: (pt). Values in pts will be rounded to the nearest number of pixels +#: based on screen resolution. If not specified, the unit is assumed +#: to be pts. Note that borders are displayed only when more than one +#: window is visible. They are meant to separate multiple windows. + +# draw_minimal_borders yes + +#: Draw only the minimum borders needed. This means that only the +#: borders that separate the window from a neighbor are drawn. Note +#: that setting a non-zero window_margin_width overrides this and +#: causes all borders to be drawn. + +# draw_window_borders_for_single_window no + +#: Draw borders around a window even when there is only a single +#: window visible. When enabled and there is only a single window, +#: full borders are drawn around it (as if draw_minimal_borders is +#: false). The border will show in the active color when the window is +#: focused and the OS window has focus, and in the inactive color when +#: the OS window loses focus. This provides a clear visual indicator +#: of whether the kitty window is focused. When there are multiple +#: windows visible, this option has no effect and normal border +#: drawing rules apply. + +# window_margin_width 0 + +#: The window margin (in pts) (blank area outside the border). A +#: single value sets all four sides. Two values set the vertical and +#: horizontal sides. Three values set top, horizontal and bottom. Four +#: values set top, right, bottom and left. + +# single_window_margin_width -1 + +#: The window margin to use when only a single window is visible (in +#: pts). Negative values will cause the value of window_margin_width +#: to be used instead. A single value sets all four sides. Two values +#: set the vertical and horizontal sides. Three values set top, +#: horizontal and bottom. Four values set top, right, bottom and left. + +# window_padding_width 0 + +#: The window padding (in pts) (blank area between the text and the +#: window border). A single value sets all four sides. Two values set +#: the vertical and horizontal sides. Three values set top, horizontal +#: and bottom. Four values set top, right, bottom and left. + +# single_window_padding_width -1 + +#: The window padding to use when only a single window is visible (in +#: pts). Negative values will cause the value of window_padding_width +#: to be used instead. A single value sets all four sides. Two values +#: set the vertical and horizontal sides. Three values set top, +#: horizontal and bottom. Four values set top, right, bottom and left. + +# placement_strategy center + +#: When the window size is not an exact multiple of the cell size, the +#: cell area of the terminal window will have some extra padding on +#: the sides. You can control how that padding is distributed with +#: this option. Using a value of center means the cell area will be +#: placed centrally. A value of top-left means the padding will be +#: only at the bottom and right edges. The value can be one of: top- +#: left, top, top-right, left, center, right, bottom-left, bottom, +#: bottom-right. + +# active_border_color #00ff00 + +#: The color for the border of the active window. Set this to none to +#: not draw borders around the active window. + +# inactive_border_color #cccccc + +#: The color for the border of inactive windows. + +# bell_border_color #ff5a00 + +#: The color for the border of inactive windows in which a bell has +#: occurred. + +# inactive_text_alpha 1.0 + +#: Fade the text in inactive windows by the specified amount (a number +#: between zero and one, with zero being fully faded). + +# hide_window_decorations no + +#: Hide the window decorations (title-bar and window borders) with +#: yes. On macOS, titlebar-only and titlebar-and-corners can be used +#: to only hide the titlebar and the rounded corners. Whether this +#: works and exactly what effect it has depends on the window +#: manager/operating system. Note that the effects of changing this +#: option when reloading config are undefined. When using titlebar- +#: only, it is useful to also set window_margin_width and +#: placement_strategy to prevent the rounded corners from clipping +#: text. Or use titlebar-and-corners. + +# window_logo_path none + +#: Path to a logo image. Must be in PNG/JPEG/WEBP/GIF/TIFF/BMP format. +#: Relative paths are interpreted relative to the kitty config +#: directory. The logo is displayed in a corner of every kitty window. +#: The position is controlled by window_logo_position. Individual +#: windows can be configured to have different logos either using the +#: launch action or the remote control +#: facility. + +# window_logo_position bottom-right + +#: Where to position the window logo in the window. The value can be +#: one of: top-left, top, top-right, left, center, right, bottom-left, +#: bottom, bottom-right. + +# window_logo_alpha 0.5 + +#: The amount the logo should be faded into the background. With zero +#: being fully faded and one being fully opaque. + +# window_logo_scale 0 + +#: The percentage (0-100] of the window size to which the logo should +#: scale. Using a single number means the logo is scaled to that +#: percentage of the shortest window dimension, while preserving +#: aspect ratio of the logo image. + +#: Using two numbers means the width and height of the logo are scaled +#: to the respective percentage of the window's width and height. + +#: Using zero as the percentage disables scaling in that dimension. A +#: single zero (the default) disables all scaling of the window logo. + +# resize_debounce_time 0.1 0.5 + +#: The time to wait (in seconds) before asking the program running in +#: kitty to resize and redraw the screen during a live resize of the +#: OS window, when no new resize events have been received, i.e. when +#: resizing is either paused or finished. On platforms such as macOS, +#: where the operating system sends events corresponding to the start +#: and end of a live resize, the second number is used for redraw- +#: after-pause since kitty can distinguish between a pause and end of +#: resizing. On such systems the first number is ignored and redraw is +#: immediate after end of resize. On other systems only the first +#: number is used so that kitty is "ready" quickly after the end of +#: resizing, while not also continuously redrawing, to save energy. + +# resize_in_steps no + +#: Resize the OS window in steps as large as the cells, instead of +#: with the usual pixel accuracy. Combined with initial_window_width +#: and initial_window_height in number of cells, this option can be +#: used to keep the margins as small as possible when resizing the OS +#: window. Note that this does not currently work on Wayland. + +# visual_window_select_characters 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ + +#: The list of characters for visual window selection. For example, +#: for selecting a window to focus on with focus_visible_window. The +#: value should be a series of unique numbers or alphabets, case +#: insensitive, from the set 0-9A-Z\-=[];',./\\`. Specify your +#: preference as a string of characters. + +# confirm_os_window_close -1 + +#: Ask for confirmation when closing an OS window or a tab with at +#: least this number of kitty windows in it by window manager (e.g. +#: clicking the window close button or pressing the operating system +#: shortcut to close windows) or by the close_tab action. A value of +#: zero disables confirmation. This confirmation also applies to +#: requests to quit the entire application (all OS windows, via the +#: quit action). Negative values are converted to positive ones, +#: however, with shell_integration enabled, using negative values +#: means windows sitting at a shell prompt are not counted, only +#: windows where some command is currently running. You can also have +#: backgrounded jobs prevent closing, by adding count-background to +#: the setting, for example: -1 count-background. Note that if you +#: want confirmation when closing individual windows, you can map the +#: close_window_with_confirmation action. + +#: }}} + +#: Tab bar {{{ + +# tab_bar_edge bottom + +#: The edge to show the tab bar on, top or bottom. + +# tab_bar_margin_width 0.0 + +#: The margin to the left and right of the tab bar (in pts). + +# tab_bar_margin_height 0.0 0.0 + +#: The margin above and below the tab bar (in pts). The first number +#: is the margin between the edge of the OS Window and the tab bar. +#: The second number is the margin between the tab bar and the +#: contents of the current tab. + +tab_bar_style powerline +tab_powerline_style round + +#: The tab bar style, can be one of: + +#: fade +#: Each tab's edges fade into the background color. (See also tab_fade) +#: slant +#: Tabs look like the tabs in a physical file. +#: separator +#: Tabs are separated by a configurable separator. (See also +#: tab_separator) +#: powerline +#: Tabs are shown as a continuous line with "fancy" separators. +#: (See also tab_powerline_style) +#: custom +#: A user-supplied Python function called draw_tab is loaded from the file +#: tab_bar.py in the kitty config directory. For examples of how to +#: write such a function, see the functions named draw_tab_with_* in +#: kitty's source code: kitty/tab_bar.py. See also +#: this discussion +#: for examples from kitty users. +#: hidden +#: The tab bar is hidden. If you use this, you might want to create +#: a mapping for the select_tab action which presents you with a list of +#: tabs and allows for easy switching to a tab. + +# tab_bar_filter + +#: A search expression . Only tabs that match this expression will +#: be shown in the tab bar. The currently active tab is always shown, +#: regardless of whether it matches or not. When using this option, +#: the tab bar may be displayed with less tabs than specified in +#: tab_bar_min_tabs, as evaluating the filter is expensive and is done +#: only at display time. This is most useful when using sessions +#: . An expression of +#: session:~ or session:^$ will show only tabs that belong to the +#: current session or no session. The various tab navigation actions +#: such as goto_tab, next_tab, previous_tab, etc. are automatically +#: restricted to work only on matching tabs. + +# tab_bar_align left + +#: The horizontal alignment of the tab bar, can be one of: left, +#: center, right. + +tab_bar_min_tabs 1 + +#: The minimum number of tabs that must exist before the tab bar is +#: shown. + +# tab_switch_strategy previous + +#: The algorithm to use when switching to a tab when the current tab +#: is closed. The default of previous will switch to the last used +#: tab. A value of left will switch to the tab to the left of the +#: closed tab. A value of right will switch to the tab to the right of +#: the closed tab. A value of last will switch to the right-most tab. + +# tab_fade 0.25 0.5 0.75 1 + +#: Control how each tab fades into the background when using fade for +#: the tab_bar_style. Each number is an alpha (between zero and one) +#: that controls how much the corresponding cell fades into the +#: background, with zero being no fade and one being full fade. You +#: can change the number of cells used by adding/removing entries to +#: this list. + +# tab_separator " ┇" + +#: The separator between tabs in the tab bar when using separator as +#: the tab_bar_style. + +# tab_powerline_style angled + +#: The powerline separator style between tabs in the tab bar when +#: using powerline as the tab_bar_style, can be one of: angled, +#: slanted, round. + +# tab_activity_symbol none + +#: Some text or a Unicode symbol to show on the tab if a window in the +#: tab that does not have focus has some activity. If you want to use +#: leading or trailing spaces, surround the text with quotes. See +#: tab_title_template for how this is rendered. + +# tab_title_max_length 0 + +#: The maximum number of cells that can be used to render the text in +#: a tab. A value of zero means that no limit is applied. + +# tab_title_template "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{tab.last_focused_progress_percent}{title}" + +#: A template to render the tab title. The default just renders the +#: title with optional symbols for bell and activity. If you wish to +#: include the tab-index as well, use something like: {index}:{title}. +#: Useful if you have shortcuts mapped for goto_tab N. If you prefer +#: to see the index as a superscript, use {sup.index}. All data +#: available is: + +#: title +#: The current tab title. +#: index +#: The tab index usable with goto_tab N goto_tab shortcuts. +#: layout_name +#: The current layout name. +#: session_name +#: The name of the kitty session file from which this tab was created, if any. +#: active_session_name +#: The name of the kitty session file from which the active window in this tab was created, if any. +#: num_windows +#: The number of windows in the tab. +#: num_window_groups +#: The number of window groups (a window group is a window and all of its overlay windows) in the tab. +#: tab.active_wd +#: The working directory of the currently active window in the tab +#: (expensive, requires syscall). Use tab.active_oldest_wd to get +#: the directory of the oldest foreground process rather than the newest. +#: tab.active_exe +#: The name of the executable running in the foreground of the currently +#: active window in the tab (expensive, requires syscall). Use +#: tab.active_oldest_exe for the oldest foreground process. +#: max_title_length +#: The maximum title length available. +#: keyboard_mode +#: The name of the current keyboard mode or the empty string if no keyboard mode is active. +#: tab.last_focused_progress_percent +#: If a command running in a window reports the progress for a task, show this progress as a percentage +#: from the most recently focused window in the tab. Empty string if no progress is reported. +#: tab.progress_percent +#: If a command running in a window reports the progress for a task, show this progress as a percentage +#: from all windows in the tab, averaged. Empty string is no progress is reported. +#: custom +#: This will call a function named draw_title(data) from the file tab_bar.py placed in +#: the kitty config directory. The function will be passed a dictionary of data, the same data that +#: can be used in this template. It can then perform arbitrarily complex processing and return a string. +#: For example: tab_title_template "{custom}" will use the output of the function as the tab title. +#: Any print statements in the draw_title() will print to the STDOUT of the kitty process, useful +#: for debugging. + + +#: Note that formatting is done by Python's string formatting +#: machinery, so you can use, for instance, {layout_name[:2].upper()} +#: to show only the first two letters of the layout name, upper-cased. +#: If you want to style the text, you can use styling directives, for +#: example: +#: `{fmt.fg.red}red{fmt.fg.tab}normal{fmt.bg._00FF00}greenbg{fmt.bg.tab}`. +#: Similarly, for bold and italic: +#: `{fmt.bold}bold{fmt.nobold}normal{fmt.italic}italic{fmt.noitalic}`. +#: The 256 eight terminal colors can be used as `fmt.fg.color0` +#: through `fmt.fg.color255`. Note that for backward compatibility, if +#: {bell_symbol} or {activity_symbol} are not present in the template, +#: they are prepended to it. + +# active_tab_title_template none + +#: Template to use for active tabs. If not specified falls back to +#: tab_title_template. + +# active_tab_foreground #000 +# active_tab_background #eee +# active_tab_font_style bold-italic +# inactive_tab_foreground #444 +# inactive_tab_background #999 +# inactive_tab_font_style normal + +#: Tab bar colors and styles. +# tab_bar_background none + +#: Background color for the tab bar. Defaults to using the terminal +#: background color. + +# tab_bar_margin_color none + +#: Color for the tab bar margin area. Defaults to using the terminal +#: background color for margins above and below the tab bar. For side +#: margins the default color is chosen to match the background color +#: of the neighboring tab. + +#: }}} + +#: +#Color scheme {{{ + +# foreground #dddddd +# background #000000 + +#: The foreground and background colors. + +background_opacity 0.8 + +#: The opacity of the terminal background color. A number between zero +#: and one, where one is opaque and zero is fully transparent. This +#: will only work if supported by the OS (for instance, when using a +#: compositor under X11). Note that it only sets the background +#: color's opacity in cells that have the same background color as the +#: default terminal background, so that things like the status bar in +#: vim, powerline prompts, etc. still look good. But it means that if +#: you use a color theme with a background color in your editor, it +#: will not be rendered as transparent. Instead you should change the +#: default background color in your kitty config and not use a +#: background color in the editor color scheme. Or use the escape +#: codes to set the terminals default colors in a shell script to +#: launch your editor. See also transparent_background_colors. Be +#: aware that using a value less than 1.0 is a (possibly significant) +#: performance hit. When using a low value for this setting, it is +#: desirable that you set the background color to a color the matches +#: the general color of the desktop background, for best text +#: rendering. Note also, that this setting does not apply to the +#: background_image, if any. The background image can itself have +#: transparency via its alpha channel if desired, and that will be +#: respected. + +#: If you want to dynamically change transparency of windows, set +#: dynamic_background_opacity to yes (this is off by default as it has +#: a performance cost). Changing this option when reloading the config +#: will only work if dynamic_background_opacity was enabled in the +#: original config. + +# background_blur 0 + +#: Set to a positive value to enable background blur (blurring of the +#: visuals behind a transparent window) on platforms that support it. +#: Only takes effect when background_opacity is less than one. On +#: macOS, this will also control the blur radius (amount of blurring). +#: Setting it to too high a value will cause severe performance issues +#: and/or rendering artifacts. Usually, values up to 64 work well. +#: Note that this might cause performance issues, depending on how the +#: platform implements it, so use with care. Currently supported on +#: macOS and KDE. + +# transparent_background_colors + +#: A space separated list of upto 7 colors, with opacity. When the +#: background color of a cell matches one of these colors, it is +#: rendered semi-transparent using the specified opacity. + +#: Useful in more complex UIs like editors where you could want more +#: than a single background color to be rendered as transparent, for +#: instance, for a cursor highlight line background or a highlighted +#: block. Terminal applications can set this color using The kitty +#: color control escape code. + +#: The syntax for specifying colors is: color@opacity, where the +#: @opacity part is optional. When unspecified, the value of +#: background_opacity is used. For example:: + +#: transparent_background_colors red@0.5 #00ff00@0.3 + +#: Note that you must also set background_opacity to something less +#: than 1 for this setting to work properly. + +# dynamic_background_opacity no + +#: Allow changing of the background_opacity dynamically, using either +#: keyboard shortcuts (increase_background_opacity and +#: decrease_background_opacity) or the remote control facility. +#: Changing this option by reloading the config is not supported. + +# background_image none + +#: Path to a background image. Must be in PNG/JPEG/WEBP/TIFF/GIF/BMP +#: format. Note that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_image_layout tiled + +#: Whether to tile, scale or clamp the background image. The value can +#: be one of tiled, mirror-tiled, scaled, clamped, centered or +#: cscaled. The scaled and cscaled values scale the image to the +#: window size, with cscaled preserving the image aspect ratio. Note +#: that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_image_linear no + +#: When background image is scaled, whether linear interpolation +#: should be used. Note that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_tint 0.0 + +#: How much to tint the background image by the background color. This +#: option makes it easier to read the text. Tinting is done using the +#: current background color for each window. This option applies only +#: if background_image is set. Note that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_tint_gaps 1.0 + +#: How much to tint the background image at the window gaps by the +#: background color, after applying background_tint. Since this is +#: multiplicative with background_tint, it can be used to lighten the +#: tint over the window gaps for a *separated* look. Note that when +#: using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# dim_opacity 0.4 + +#: How much to dim text that has the DIM/FAINT attribute set. One +#: means no dimming and zero means fully dimmed (i.e. invisible). + +# selection_foreground #000000 +# selection_background #fffacd + +#: The foreground and background colors for text selected with the +#: mouse. Setting both of these to none will cause a "reverse video" +#: effect for selections, where the selection will be the cell text +#: color and the text will become the cell background color. Setting +#: only selection_foreground to none will cause the foreground color +#: to be used unchanged. Note that these colors can be overridden by +#: the program running in the terminal. + +#: The color table {{{ + +#: The 256 terminal colors. There are 8 basic colors, each color has a +#: dull and bright version, for the first 16 colors. You can set the +#: remaining 240 colors as color16 to color255. + +# color0 #000000 +# color8 #767676 + +#: black + +# color1 #cc0403 +# color9 #f2201f + +#: red + +# color2 #19cb00 +# color10 #23fd00 + +#: green + +# color3 #cecb00 +# color11 #fffd00 + +#: yellow + +# color4 #0d73cc +# color12 #1a8fff + +#: blue + +# color5 #cb1ed1 +# color13 #fd28ff + +#: magenta + +# color6 #0dcdcd +# color14 #14ffff + +#: cyan + +# color7 #dddddd +# color15 #ffffff + +#: white + +# mark1_foreground black + +#: Color for marks of type 1 + +# mark1_background #98d3cb + +#: Color for marks of type 1 (light steel blue) + +# mark2_foreground black + +#: Color for marks of type 2 + +# mark2_background #f2dcd3 + +#: Color for marks of type 1 (beige) + +# mark3_foreground black + +#: Color for marks of type 3 + +# mark3_background #f274bc + +#: Color for marks of type 3 (violet) + +#: }}} + +#: }}} + +#: Advanced {{{ + +# shell . + +#: The shell program to execute. The default value of . means to use +#: the value of of the SHELL environment variable or if unset, +#: whatever shell is set as the default shell for the current user. +#: Note that on macOS if you change this, you might need to add +#: --login and --interactive to ensure that the shell starts in +#: interactive mode and reads its startup rc files. Environment +#: variables are expanded in this setting. + +# editor . + +#: The terminal based text editor (such as vim or nano) to use when +#: editing the kitty config file or similar tasks. + +#: The default value of . means to use the environment variables +#: VISUAL and EDITOR in that order. If these variables aren't set, +#: kitty will run your shell ($SHELL -l -i -c env) to see if your +#: shell startup rc files set VISUAL or EDITOR. If that doesn't work, +#: kitty will cycle through various known editors (vim, emacs, etc.) +#: and take the first one that exists on your system. + +# close_on_child_death no + +#: Close the window when the child process (usually the shell) exits. +#: With the default value no, the terminal will remain open when the +#: child exits as long as there are still other processes outputting +#: to the terminal (for example disowned or backgrounded processes). +#: When enabled with yes, the window will close as soon as the child +#: process exits. Note that setting it to yes means that any +#: background processes still using the terminal can fail silently +#: because their stdout/stderr/stdin no longer work. + +# remote_control_password + +#: Allow other programs to control kitty using passwords. This option +#: can be specified multiple times to add multiple passwords. If no +#: passwords are present kitty will ask the user for permission if a +#: program tries to use remote control with a password. A password can +#: also *optionally* be associated with a set of allowed remote +#: control actions. For example:: + +#: remote_control_password "my passphrase" get-colors set-colors focus-window focus-tab + +#: Only the specified actions will be allowed when using this +#: password. Glob patterns can be used too, for example:: + +#: remote_control_password "my passphrase" set-tab-* resize-* + +#: To get a list of available actions, run:: + +#: kitten @ --help + +#: A set of actions to be allowed when no password is sent can be +#: specified by using an empty password. For example:: + +#: remote_control_password "" *-colors + +#: Finally, the path to a python module can be specified that provides +#: a function is_cmd_allowed that is used to check every remote +#: control command. For example:: + +#: remote_control_password "my passphrase" my_rc_command_checker.py + +#: Relative paths are resolved from the kitty configuration directory. +#: See rc_custom_auth for details. + +# allow_remote_control no + +#: Allow other programs to control kitty. If you turn this on, other +#: programs can control all aspects of kitty, including sending text +#: to kitty windows, opening new windows, closing windows, reading the +#: content of windows, etc. Note that this even works over SSH +#: connections. The default setting of no prevents any form of remote +#: control. The meaning of the various values are: + +#: password +#: Remote control requests received over both the TTY device and the socket +#: are confirmed based on passwords, see remote_control_password. + +#: socket-only +#: Remote control requests received over a socket are accepted +#: unconditionally. Requests received over the TTY are denied. +#: See listen_on. + +#: socket +#: Remote control requests received over a socket are accepted +#: unconditionally. Requests received over the TTY are confirmed based on +#: password. + +#: no +#: Remote control is completely disabled. + +#: yes +#: Remote control requests are always accepted. + +# listen_on none + +#: Listen to the specified socket for remote control connections. Note +#: that this will apply to all kitty instances. It can be overridden +#: by the kitty --listen-on command line option. For UNIX sockets, +#: such as unix:${TEMP}/mykitty or unix:@mykitty (on Linux). +#: Environment variables are expanded and relative paths are resolved +#: with respect to the temporary directory. If {kitty_pid} is present, +#: then it is replaced by the PID of the kitty process, otherwise the +#: PID of the kitty process is appended to the value, with a hyphen. +#: For TCP sockets such as tcp:localhost:0 a random port is always +#: used even if a non-zero port number is specified. See the help for +#: kitty --listen-on for more details. Note that this will be ignored +#: unless allow_remote_control is set to either: yes, socket or +#: socket-only. Changing this option by reloading the config is not +#: supported. + +# env + +#: Specify the environment variables to be set in all child processes. +#: Using the name with an equal sign (e.g. env VAR=) will set it to +#: the empty string. Specifying only the name (e.g. env VAR) will +#: remove the variable from the child process' environment. Note that +#: environment variables are expanded recursively, for example:: + +#: env VAR1=a +#: env VAR2=${HOME}/${VAR1}/b + +#: The value of VAR2 will be /a/b. + +#: Use the special value read_from_shell to have kitty read the +#: specified variables from your login shell shell configuration. +#: Useful if your shell startup files setup a bunch of environment +#: variables that you want available to kitty and in kitty session +#: files. Each variable name is treated as a glob pattern to match. +#: For example: env read_from_shell=PATH LANG LC_* XDG_* EDITOR +#: VISUAL. Note that these variables are only read after the +#: configuration is fully processed, thus they are not available for +#: recursive expansion and they will override any variables set by +#: other env directives. + +# filter_notification + +#: Specify rules to filter out notifications sent by applications +#: running in kitty. Can be specified multiple times to create +#: multiple filter rules. A rule specification is of the form +#: field:regexp. A filter rule can match on any of the fields: title, +#: body, app, type. The special value of all filters out all +#: notifications. Rules can be combined using Boolean operators. Some +#: examples:: + +#: filter_notification title:hello or body:"abc.*def" +#: # filter out notification from vim except for ones about updates, (?i) +#: # makes matching case insensitive. +#: filter_notification app:"[ng]?vim" and not body:"(?i)update" +#: # filter out all notifications +#: filter_notification all + +#: The field app is the name of the application sending the +#: notification and type is the type of the notification. Not all +#: applications will send these fields, so you can also match on the +#: title and body of the notification text. More sophisticated +#: programmatic filtering and custom actions on notifications can be +#: done by creating a notifications.py file in the kitty config +#: directory (~/.config/kitty). An annotated sample is available +#: . + +# watcher + +#: Path to python file which will be loaded for watchers +#: . Can be +#: specified more than once to load multiple watchers. The watchers +#: will be added to every kitty window. Relative paths are resolved +#: relative to the kitty config directory. Note that reloading the +#: config will only affect windows created after the reload. + +# exe_search_path + +#: Control where kitty finds the programs to run. The default search +#: order is: First search the system wide PATH, then ~/.local/bin and +#: ~/bin. If still not found, the PATH defined in the login shell +#: after sourcing all its startup files is tried. Finally, if present, +#: the PATH specified by the env option is tried. + +#: This option allows you to prepend, append, or remove paths from +#: this search order. It can be specified multiple times for multiple +#: paths. A simple path will be prepended to the search order. A path +#: that starts with the + sign will be append to the search order, +#: after ~/bin above. A path that starts with the - sign will be +#: removed from the entire search order. For example:: + +#: exe_search_path /some/prepended/path +#: exe_search_path +/some/appended/path +#: exe_search_path -/some/excluded/path + +# update_check_interval 24 + +#: The interval to periodically check if an update to kitty is +#: available (in hours). If an update is found, a system notification +#: is displayed informing you of the available update. The default is +#: to check every 24 hours, set to zero to disable. Update checking is +#: only done by the official binary builds. Distro packages or source +#: builds do not do update checking. Changing this option by reloading +#: the config is not supported. + +# startup_session none + +#: Path to a session file to use for all kitty instances. Can be +#: overridden by using the kitty --session =none command line option +#: for individual instances. See sessions +#: in the kitty +#: documentation for details. Note that relative paths are interpreted +#: with respect to the kitty config directory. Environment variables +#: in the path are expanded. Changing this option by reloading the +#: config is not supported. Note that if kitty is invoked with command +#: line arguments specifying a command to run, this option is ignored. + +# clipboard_control write-clipboard write-primary read-clipboard-ask read-primary-ask + +#: Allow programs running in kitty to read and write from the +#: clipboard. You can control exactly which actions are allowed. The +#: possible actions are: write-clipboard, read-clipboard, write- +#: primary, read-primary, read-clipboard-ask, read-primary-ask. The +#: default is to allow writing to the clipboard and primary selection +#: and to ask for permission when a program tries to read from the +#: clipboard. Note that disabling the read confirmation is a security +#: risk as it means that any program, even the ones running on a +#: remote server via SSH can read your clipboard. See also +#: clipboard_max_size. + +# clipboard_max_size 512 + +#: The maximum size (in MB) of data from programs running in kitty +#: that will be stored for writing to the system clipboard. A value of +#: zero means no size limit is applied. See also clipboard_control. + +# file_transfer_confirmation_bypass + +#: The password that can be supplied to the file transfer kitten +#: to skip the +#: transfer confirmation prompt. This should only be used when +#: initiating transfers from trusted computers, over trusted networks +#: or encrypted transports, as it allows any programs running on the +#: remote machine to read/write to the local filesystem, without +#: permission. + +# allow_hyperlinks yes + +#: Process hyperlink escape sequences (OSC 8). If disabled OSC 8 +#: escape sequences are ignored. Otherwise they become clickable +#: links, that you can click with the mouse or by using the hints +#: kitten . The +#: special value of ask means that kitty will ask before opening the +#: link when clicked. + +# shell_integration enabled + +#: Enable shell integration on supported shells. This enables features +#: such as jumping to previous prompts, browsing the output of the +#: previous command in a pager, etc. on supported shells. Set to +#: disabled to turn off shell integration, completely. It is also +#: possible to disable individual features, set to a space separated +#: list of these values: no-rc, no-cursor, no-title, no-cwd, no- +#: prompt-mark, no-complete, no-sudo. See Shell integration +#: for details. + +# allow_cloning ask + +#: Control whether programs running in the terminal can request new +#: windows to be created. The canonical example is clone-in-kitty +#: . +#: By default, kitty will ask for permission for each clone request. +#: Allowing cloning unconditionally gives programs running in the +#: terminal (including over SSH) permission to execute arbitrary code, +#: as the user who is running the terminal, on the computer that the +#: terminal is running on. + +# clone_source_strategies venv,conda,env_var,path + +#: Control what shell code is sourced when running clone-in-kitty in +#: the newly cloned window. The supported strategies are: + +#: venv +#: Source the file $VIRTUAL_ENV/bin/activate. This is used by the +#: Python stdlib venv module and allows cloning venvs automatically. +#: conda +#: Run conda activate $CONDA_DEFAULT_ENV. This supports the virtual +#: environments created by conda. +#: env_var +#: Execute the contents of the environment variable +#: KITTY_CLONE_SOURCE_CODE with eval. +#: path +#: Source the file pointed to by the environment variable +#: KITTY_CLONE_SOURCE_PATH. + +#: This option must be a comma separated list of the above values. +#: Only the first valid match, in the order specified, is sourced. + +notify_on_cmd_finish invisible 15.00 + +#: Show a desktop notification when a long-running command finishes +#: (needs shell_integration). The possible values are: + +#: never +#: Never send a notification. + +#: unfocused +#: Only send a notification when the window does not have keyboard focus. + +#: invisible +#: Only send a notification when the window both is unfocused and not visible +#: to the user, for example, because it is in an inactive tab or its OS window +#: is not currently visible (on platforms that support OS window visibility querying +#: this considers an OS Window visible iff it is active). + +#: always +#: Always send a notification, regardless of window state. + +#: There are two optional arguments: + +#: First, the minimum duration for what is considered a long running +#: command. The default is 5 seconds. Specify a second argument to set +#: the duration. For example: invisible 15. Do not set the value too +#: small, otherwise a command that launches a new OS Window and exits +#: will spam a notification. + +#: Second, the action to perform. The default is notify. The possible +#: values are: + +#: notify +#: Send a desktop notification. The subsequent arguments are optional and specify when +#: the notification is automatically cleared. The set of possible events when the notification is +#: cleared are: focus and next. focus means that when the notification +#: policy is unfocused or invisible the notification is automatically cleared +#: when the window regains focus. The value of next means that the previous notification +#: is cleared when the next notification is shown. The default when no arguments are specified +#: is: focus next. + +#: bell +#: Ring the terminal bell. + +#: notify-bell +#: Send a desktop notification and ring the terminal bell. +#: The arguments are the same as for `notify`. + +#: command +#: Run a custom command. All subsequent arguments are the cmdline to run. + +#: Some more examples:: + +#: # Send a notification when a command takes more than 5 seconds in an unfocused window +#: notify_on_cmd_finish unfocused +#: # Send a notification when a command takes more than 10 seconds in a invisible window +#: notify_on_cmd_finish invisible 10.0 +#: # Ring a bell when a command takes more than 10 seconds in a invisible window +#: notify_on_cmd_finish invisible 10.0 bell +#: # Run 'notify-send' when a command takes more than 10 seconds in a invisible window +#: # Here %c is replaced by the current command line and %s by the job exit code +#: notify_on_cmd_finish invisible 10.0 command notify-send "job finished with status: %s" %c +#: # Do not clear previous notification when next command finishes or window regains focus +#: notify_on_cmd_finish invisible 5.0 notify + +# term xterm-kitty + +#: The value of the TERM environment variable to set. Changing this +#: can break many terminal programs, only change it if you know what +#: you are doing, not because you read some advice on "Stack Overflow" +#: to change it. The TERM variable is used by various programs to get +#: information about the capabilities and behavior of the terminal. If +#: you change it, depending on what programs you run, and how +#: different the terminal you are changing it to is, various things +#: from key-presses, to colors, to various advanced features may not +#: work. Changing this option by reloading the config will only affect +#: newly created windows. + +# terminfo_type path + +#: The value of the TERMINFO environment variable to set. This +#: variable is used by programs running in the terminal to search for +#: terminfo databases. The default value of path causes kitty to set +#: it to a filesystem location containing the kitty terminfo database. +#: A value of direct means put the entire database into the env var +#: directly. This can be useful when connecting to containers, for +#: example. But, note that not all software supports this. A value of +#: none means do not touch the variable. + +# forward_stdio no + +#: Forward STDOUT and STDERR of the kitty process to child processes. +#: This is useful for debugging as it allows child processes to print +#: to kitty's STDOUT directly. For example, echo hello world +#: >&$KITTY_STDIO_FORWARDED in a shell will print to the parent +#: kitty's STDOUT. Sets the KITTY_STDIO_FORWARDED=fdnum environment +#: variable so child processes know about the forwarding. Note that on +#: macOS this prevents the shell from being run via the login utility +#: so getlogin() will not work in programs run in this session. + +# menu_map + +#: Specify entries for various menus in kitty. Currently only the +#: global menubar on macOS is supported. For example:: + +#: menu_map global "Actions::Launch something special" launch --hold --type=os-window sh -c "echo hello world" + +#: This will create a menu entry named "Launch something special" in +#: an "Actions" menu in the macOS global menubar. Sub-menus can be +#: created by adding more levels separated by the :: characters. + +#: }}} + + +#: OS specific tweaks {{{ + +# wayland_titlebar_color system + +#: The color of the kitty window's titlebar on Wayland systems with +#: client side window decorations such as GNOME. A value of system +#: means to use the default system colors, a value of background means +#: to use the background color of the currently active kitty window +#: and finally you can use an arbitrary color, such as #12af59 or red. + +# macos_titlebar_color system + +#: The color of the kitty window's titlebar on macOS. A value of +#: system means to use the default system color, light or dark can +#: also be used to set it explicitly. A value of background means to +#: use the background color of the currently active window and finally +#: you can use an arbitrary color, such as #12af59 or red. + +# macos_option_as_alt no + +#: Use the Option key as an Alt key on macOS. With this set to no, +#: kitty will use the macOS native Option+Key to enter Unicode +#: character behavior. This will break any Alt+Key keyboard shortcuts +#: in your terminal programs, but you can use the macOS Unicode input +#: technique. You can use the values: left, right or both to use only +#: the left, right or both Option keys as Alt, instead. Note that +#: kitty itself always treats Option the same as Alt. This means you +#: cannot use this option to configure different kitty shortcuts for +#: Option+Key vs. Alt+Key. Also, any kitty shortcuts using +#: Option/Alt+Key will take priority, so that any such key presses +#: will not be passed to terminal programs running inside kitty. +#: Changing this option by reloading the config is not supported. + +# macos_hide_from_tasks no + +#: Hide the kitty window from running tasks on macOS (⌘+Tab and the +#: Dock). Changing this option by reloading the config is not +#: supported. + +# macos_quit_when_last_window_closed no + +#: Have kitty quit when all the top-level windows are closed on macOS. +#: By default, kitty will stay running, even with no open windows, as +#: is the expected behavior on macOS. + +# macos_window_resizable yes + +#: Disable this if you want kitty top-level OS windows to not be +#: resizable on macOS. + +# macos_thicken_font 0 + +#: Draw an extra border around the font with the given width, to +#: increase legibility at small font sizes on macOS. For example, a +#: value of 0.75 will result in rendering that looks similar to sub- +#: pixel antialiasing at common font sizes. Note that in modern kitty, +#: this option is obsolete (although still supported). Consider using +#: text_composition_strategy instead. + +# macos_traditional_fullscreen no + +#: Use the macOS traditional full-screen transition, that is faster, +#: but less pretty. + +# macos_show_window_title_in all + +#: Control where the window title is displayed on macOS. A value of +#: window will show the title of the currently active window at the +#: top of the macOS window. A value of menubar will show the title of +#: the currently active window in the macOS global menu bar, making +#: use of otherwise wasted space. A value of all will show the title +#: in both places, and none hides the title. See +#: macos_menubar_title_max_length for how to control the length of the +#: title in the menu bar. + +# macos_menubar_title_max_length 0 + +#: The maximum number of characters from the window title to show in +#: the macOS global menu bar. Values less than one means that there is +#: no maximum limit. + +# macos_custom_beam_cursor no + +#: Use a custom mouse cursor for macOS that is easier to see on both +#: light and dark backgrounds. Nowadays, the default macOS cursor +#: already comes with a white border. WARNING: this might make your +#: mouse cursor invisible on dual GPU machines. Changing this option +#: by reloading the config is not supported. + +# macos_colorspace srgb + +#: The colorspace in which to interpret terminal colors. The default +#: of srgb will cause colors to match those seen in web browsers. The +#: value of default will use whatever the native colorspace of the +#: display is. The value of displayp3 will use Apple's special +#: snowflake display P3 color space, which will result in over +#: saturated (brighter) colors with some color shift. Reloading +#: configuration will change this value only for newly created OS +#: windows. + +# linux_display_server auto + +#: Choose between Wayland and X11 backends. By default, an appropriate +#: backend based on the system state is chosen automatically. Set it +#: to x11 or wayland to force the choice. Changing this option by +#: reloading the config is not supported. + +# wayland_enable_ime yes + +#: Enable Input Method Extension on Wayland. This is typically used +#: for inputting text in East Asian languages. However, its +#: implementation in Wayland is often buggy and introduces latency +#: into the input loop, so disable this if you know you dont need it. +#: Changing this option by reloading the config is not supported, it +#: will not have any effect. + +#: }}} + + + +#: Keyboard shortcuts {{{ + +#: Keys are identified simply by their lowercase Unicode characters. +#: For example: a for the A key, [ for the left square bracket key, +#: etc. For functional keys, such as Enter or Escape, the names are +#: present at Functional key definitions +#: . +#: For modifier keys, the names are ctrl (control, ⌃), shift (⇧), alt +#: (opt, option, ⌥), super (cmd, command, ⌘). + +#: Simple shortcut mapping is done with the map directive. For full +#: details on advanced mapping including modal and per application +#: maps, see mapping . Some +#: quick examples to illustrate common tasks:: + +#: # unmap a keyboard shortcut, passing it to the program running in kitty +#: map kitty_mod+space +#: # completely ignore a keyboard event +#: map ctrl+alt+f1 discard_event +#: # combine multiple actions +#: map kitty_mod+e combine : new_window : next_layout +#: # multi-key shortcuts +#: map ctrl+x>ctrl+y>z action + +#: The full list of actions that can be mapped to key presses is +#: available here . + +# kitty_mod ctrl+shift + +#: Special modifier key alias for default shortcuts. You can change +#: the value of this option to alter all default shortcuts that use +#: kitty_mod. + +# clear_all_shortcuts no + +#: Remove all shortcut definitions up to this point. Useful, for +#: instance, to remove the default shortcuts. + +# action_alias + +#: E.g. action_alias launch_tab launch --type=tab --cwd=current + +#: Define action aliases to avoid repeating the same options in +#: multiple mappings. Aliases can be defined for any action and will +#: be expanded recursively. For example, the above alias allows you to +#: create mappings to launch a new tab in the current working +#: directory without duplication:: + +#: map f1 launch_tab vim +#: map f2 launch_tab emacs + +#: Similarly, to alias kitten invocation:: + +#: action_alias hints kitten hints --hints-offset=0 + +# kitten_alias + +#: E.g. kitten_alias hints hints --hints-offset=0 + +#: Like action_alias above, but specifically for kittens. Generally, +#: prefer to use action_alias. This option is a legacy version, +#: present for backwards compatibility. It causes all invocations of +#: the aliased kitten to be substituted. So the example above will +#: cause all invocations of the hints kitten to have the --hints- +#: offset=0 option applied. + +#: Clipboard {{{ + +#: Copy to clipboard + +# map kitty_mod+c copy_to_clipboard + +#:: There is also a copy_or_interrupt action that can be optionally +#:: mapped to Ctrl+C. It will copy only if there is a selection and +#:: send an interrupt otherwise. Similarly, +#:: copy_and_clear_or_interrupt will copy and clear the selection or +#:: send an interrupt if there is no selection. The copy_or_noop +#:: action will copy if there is a selection and pass the key through +#:: to the application running in the terminal if there is no +#:: selection. + +#: Copy to clipboard or pass through + +# map cmd+c copy_or_noop + +#: Paste from clipboard + +# map kitty_mod+v paste_from_clipboard +# map cmd+v paste_from_clipboard + +#: Paste from selection + +# map kitty_mod+s paste_from_selection +# map shift+insert paste_from_selection + +#: Pass selection to program + +# map kitty_mod+o pass_selection_to_program + +#:: You can also pass the contents of the current selection to any +#:: program with pass_selection_to_program. By default, the system's +#:: open program is used, but you can specify your own, the selection +#:: will be passed as a command line argument to the program. For +#:: example:: + +#:: map kitty_mod+o pass_selection_to_program firefox + +#:: You can pass the current selection to a terminal program running +#:: in a new kitty window, by using the @selection placeholder:: + +#:: map kitty_mod+y new_window less @selection + +#: }}} + +#: Scrolling {{{ + +#: Scroll line up + +# map kitty_mod+up scroll_line_up +# map kitty_mod+k scroll_line_up +# map opt+cmd+page_up scroll_line_up +# map cmd+up scroll_line_up + +#: Scroll line down + +# map kitty_mod+down scroll_line_down +# map kitty_mod+j scroll_line_down +# map opt+cmd+page_down scroll_line_down +# map cmd+down scroll_line_down + +#: Scroll page up + +# map kitty_mod+page_up scroll_page_up +# map cmd+page_up scroll_page_up + +#: Scroll page down + +# map kitty_mod+page_down scroll_page_down +# map cmd+page_down scroll_page_down + +#: Scroll to top + +# map kitty_mod+home scroll_home +# map cmd+home scroll_home + +#: Scroll to bottom + +# map kitty_mod+end scroll_end +# map cmd+end scroll_end + +#: Scroll to previous shell prompt + +# map kitty_mod+z scroll_to_prompt -1 + +#:: Use a parameter of 0 for scroll_to_prompt to scroll to the last +#:: jumped to or the last clicked position. Requires shell +#:: integration +#:: to work. + +#: Scroll to next shell prompt + +# map kitty_mod+x scroll_to_prompt 1 + +#: Browse scrollback buffer in pager + +# map kitty_mod+h show_scrollback + +#:: You can pipe the contents of the current screen and history +#:: buffer as STDIN to an arbitrary program using launch --stdin- +#:: source. For example, the following opens the scrollback buffer in +#:: less in an overlay window:: + +#:: map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay less +G -R + +#:: For more details on piping screen and buffer contents to external +#:: programs, see launch . + +#: Browse output of the last shell command in pager + +# map kitty_mod+g show_last_command_output + +#:: You can also define additional shortcuts to get the command +#:: output. For example, to get the first command output on screen:: + +#:: map f1 show_first_command_output_on_screen + +#:: To get the command output that was last accessed by a keyboard +#:: action or mouse action:: + +#:: map f1 show_last_visited_command_output + +#:: You can pipe the output of the last command run in the shell +#:: using the launch action. For example, the following opens the +#:: output in less in an overlay window:: + +#:: map f1 launch --stdin-source=@last_cmd_output --stdin-add-formatting --type=overlay less +G -R + +#:: To get the output of the first command on the screen, use +#:: @first_cmd_output_on_screen. To get the output of the last jumped +#:: to command, use @last_visited_cmd_output. + +#:: Requires shell integration +#:: to work. + +#: Search the scrollback within a pager + +# map kitty_mod+/ search_scrollback +# map cmd+f search_scrollback + +#:: Search for currently selected text in the scrollback using the +#:: configured scrollback_pager. Assumes that pressing the / key +#:: triggers search mode in the pager. If you want to create a manual +#:: mapping with a special pager for this, you can use something +#:: like: + +#:: map f1 combine : launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay mypager : send_key / + +#:: For more sophisticated control, such as using the current +#:: selection, use remote_control_script. + +#: }}} + +#: Window management {{{ + +#: New window + +# map kitty_mod+enter new_window +# map cmd+enter new_window + +#:: You can open a new kitty window running an arbitrary program, for +#:: example:: + +#:: map kitty_mod+y launch mutt + +#:: You can open a new window with the current working directory set +#:: to the working directory of the current window using:: + +#:: map ctrl+alt+enter launch --cwd=current + +#:: You can open a new window that is allowed to control kitty via +#:: the kitty remote control facility with launch --allow-remote- +#:: control. Any programs running in that window will be allowed to +#:: control kitty. For example:: + +#:: map ctrl+enter launch --allow-remote-control some_program + +#:: You can open a new window next to the currently active window or +#:: as the first window, with:: + +#:: map ctrl+n launch --location=neighbor +#:: map ctrl+f launch --location=first + +#:: For more details, see launch +#:: . + +#: New OS window + +# map kitty_mod+n new_os_window +# map cmd+n new_os_window + +#:: Works like new_window above, except that it opens a top-level OS +#:: window. In particular you can use new_os_window_with_cwd to open +#:: a window with the current working directory. + +#: Close window + +# map kitty_mod+w close_window +# map shift+cmd+d close_window + +#: Next window + +# map kitty_mod+] next_window + +#: Previous window + +# map kitty_mod+[ previous_window + +#: Move window forward + +# map kitty_mod+f move_window_forward + +#: Move window backward + +# map kitty_mod+b move_window_backward + +#: Move window to top + +# map kitty_mod+` move_window_to_top + +#: Start resizing window + +# map kitty_mod+r start_resizing_window +# map cmd+r start_resizing_window + +#: First window + +# map kitty_mod+1 first_window +# map cmd+1 first_window + +#: Second window + +# map kitty_mod+2 second_window +# map cmd+2 second_window + +#: Third window + +# map kitty_mod+3 third_window +# map cmd+3 third_window + +#: Fourth window + +# map kitty_mod+4 fourth_window +# map cmd+4 fourth_window + +#: Fifth window + +# map kitty_mod+5 fifth_window +# map cmd+5 fifth_window + +#: Sixth window + +# map kitty_mod+6 sixth_window +# map cmd+6 sixth_window + +#: Seventh window + +# map kitty_mod+7 seventh_window +# map cmd+7 seventh_window + +#: Eighth window + +# map kitty_mod+8 eighth_window +# map cmd+8 eighth_window + +#: Ninth window + +# map kitty_mod+9 ninth_window +# map cmd+9 ninth_window + +#: Tenth window + +# map kitty_mod+0 tenth_window + +#: Visually select and focus window + +# map kitty_mod+f7 focus_visible_window + +#:: Display overlay numbers and alphabets on the window, and switch +#:: the focus to the window when you press the key. When there are +#:: only two windows, the focus will be switched directly without +#:: displaying the overlay. You can change the overlay characters and +#:: their order with option visual_window_select_characters. + +#: Visually swap window with another + +# map kitty_mod+f8 swap_with_window + +#:: Works like focus_visible_window above, but swaps the window. + +#: }}} + +#: Tab management {{{ + +#: Next tab + +# map kitty_mod+right next_tab +# map shift+cmd+] next_tab +# map ctrl+tab next_tab + +#: Previous tab + +# map kitty_mod+left previous_tab +# map shift+cmd+[ previous_tab +# map ctrl+shift+tab previous_tab + +#: New tab + +# map kitty_mod+t new_tab +# map cmd+t new_tab + +#: Close tab + +# map kitty_mod+q close_tab +# map cmd+w close_tab + +#: Close OS window + +# map shift+cmd+w close_os_window + +#: Move tab forward + +# map kitty_mod+. move_tab_forward + +#: Move tab backward + +# map kitty_mod+, move_tab_backward + +#: Set tab title + +# map kitty_mod+alt+t set_tab_title +# map shift+cmd+i set_tab_title + + +#: You can also create shortcuts to go to specific tabs, with 1 being +#: the first tab, 2 the second tab and -1 being the previously active +#: tab, -2 being the tab active before the previously active tab and +#: so on. Any number larger than the number of tabs goes to the last +#: tab and any number less than the number of previously used tabs in +#: the history goes to the oldest previously used tab in the history:: + +#: map ctrl+alt+1 goto_tab 1 +#: map ctrl+alt+2 goto_tab 2 + +#: Just as with new_window above, you can also pass the name of +#: arbitrary commands to run when using new_tab and new_tab_with_cwd. +#: Finally, if you want the new tab to open next to the current tab +#: rather than at the end of the tabs list, use:: + +#: map ctrl+t new_tab !neighbor [optional cmd to run] +#: }}} + +#: Layout management {{{ + +#: Next layout + +# map kitty_mod+l next_layout + + +#: You can also create shortcuts to switch to specific layouts:: + +#: map ctrl+alt+t goto_layout tall +#: map ctrl+alt+s goto_layout stack + +#: Similarly, to switch back to the previous layout:: + +#: map ctrl+alt+p last_used_layout + +#: There is also a toggle_layout action that switches to the named +#: layout or back to the previous layout if in the named layout. +#: Useful to temporarily "zoom" the active window by switching to the +#: stack layout:: + +#: map ctrl+alt+z toggle_layout stack +#: }}} + +#: Font sizes {{{ + +#: You can change the font size for all top-level kitty OS windows at +#: a time or only the current one. + +#: Increase font size + +# map kitty_mod+equal change_font_size all +2.0 +# map kitty_mod+plus change_font_size all +2.0 +# map kitty_mod+kp_add change_font_size all +2.0 +# map cmd+plus change_font_size all +2.0 +# map cmd+equal change_font_size all +2.0 +# map shift+cmd+equal change_font_size all +2.0 + +#: Decrease font size + +# map kitty_mod+minus change_font_size all -2.0 +# map kitty_mod+kp_subtract change_font_size all -2.0 +# map cmd+minus change_font_size all -2.0 +# map shift+cmd+minus change_font_size all -2.0 + +#: Reset font size + +# map kitty_mod+backspace change_font_size all 0 +# map cmd+0 change_font_size all 0 + + +#: To setup shortcuts for specific font sizes:: + +#: map kitty_mod+f6 change_font_size all 10.0 + +#: To setup shortcuts to change only the current OS window's font +#: size:: + +#: map kitty_mod+f6 change_font_size current 10.0 + +#: To setup shortcuts to multiply/divide the font size:: + +#: map kitty_mod+f6 change_font_size all *2.0 +#: map kitty_mod+f6 change_font_size all /2.0 +#: }}} + +#: Select and act on visible text {{{ + +#: Use the hints kitten to select text and either pass it to an +#: external program or insert it into the terminal or copy it to the +#: clipboard. + +#: Open URL + +# map kitty_mod+e open_url_with_hints + +#:: Open a currently visible URL using the keyboard. The program used +#:: to open the URL is specified in open_url_with. + +#: Insert selected path + +# map kitty_mod+p>f kitten hints --type path --program - + +#:: Select a path/filename and insert it into the terminal. Useful, +#:: for instance to run git commands on a filename output from a +#:: previous git command. + +#: Open selected path + +# map kitty_mod+p>shift+f kitten hints --type path + +#:: Select a path/filename and open it with the default open program. + +#: Insert chosen file + +# map kitty_mod+p>c kitten choose-files + +#:: Select a file using the choose-files +#:: kitten +#:: and insert it into the terminal. + +#: Insert chosen directory + +# map kitty_mod+p>d kitten choose-files --mode=dir + +#:: Select a directory using the choose-files +#:: kitten +#:: and insert it into the terminal. + +#: Insert selected line + +# map kitty_mod+p>l kitten hints --type line --program - + +#:: Select a line of text and insert it into the terminal. Useful for +#:: the output of things like: `ls -1`. + +#: Insert selected word + +# map kitty_mod+p>w kitten hints --type word --program - + +#:: Select words and insert into terminal. + +#: Insert selected hash + +# map kitty_mod+p>h kitten hints --type hash --program - + +#:: Select something that looks like a hash and insert it into the +#:: terminal. Useful with git, which uses SHA1 hashes to identify +#:: commits. + +#: Open the selected file at the selected line + +# map kitty_mod+p>n kitten hints --type linenum + +#:: Select something that looks like filename:linenum and open it in +#:: your default editor at the specified line number. + +#: Open the selected hyperlink + +# map kitty_mod+p>y kitten hints --type hyperlink + +#:: Select a hyperlink (i.e. a URL that has been marked as such by +#:: the terminal program, for example, by `ls --hyperlink=auto`). + + +#: The hints kitten has many more modes of operation that you can map +#: to different shortcuts. For a full description see hints kitten +#: . + +#: }}} + +#: Miscellaneous {{{ + +#: Show documentation + +# map kitty_mod+f1 show_kitty_doc overview + +#: Toggle fullscreen + +# map kitty_mod+f11 toggle_fullscreen +# map ctrl+cmd+f toggle_fullscreen + +#: Toggle maximized + +# map kitty_mod+f10 toggle_maximized + +#: Toggle macOS secure keyboard entry + +# map opt+cmd+s toggle_macos_secure_keyboard_entry + +#: macOS Cycle through OS Windows + +# map cmd+` macos_cycle_through_os_windows + +#: macOS Cycle through OS Windows backwards + +# map cmd+shift+` macos_cycle_through_os_windows_backwards + +#: Unicode input + +# map kitty_mod+u kitten unicode_input +# map ctrl+cmd+space kitten unicode_input + +#: Edit config file + +# map kitty_mod+f2 edit_config_file +# map cmd+, edit_config_file + +#: Open the kitty command shell + +# map kitty_mod+escape kitty_shell window + +#:: Open the kitty shell in a new window / tab / overlay / os_window +#:: to control kitty using commands. + +Increase background opacity = 0.8 + +# map kitty_mod+a>m set_background_opacity +0.1 + +#: Decrease background opacity + +# map kitty_mod+a>l set_background_opacity -0.1 + +#: Make background fully opaque + +# map kitty_mod+a>1 set_background_opacity 1 + +#: Reset background opacity + +# map kitty_mod+a>d set_background_opacity default + +#: Reset the terminal + +# map kitty_mod+delete clear_terminal reset active +# map opt+cmd+r clear_terminal reset active + +#:: You can create shortcuts to clear/reset the terminal. For +#:: example:: + +#:: # Reset the terminal +#:: map f1 clear_terminal reset active +#:: # Clear the terminal screen by erasing all contents +#:: map f1 clear_terminal clear active +#:: # Clear the terminal scrollback by erasing it +#:: map f1 clear_terminal scrollback active +#:: # Scroll the contents of the screen into the scrollback +#:: map f1 clear_terminal scroll active +#:: # Clear everything on screen up to the line with the cursor or the start of the current prompt (needs shell integration) +#:: map f1 clear_terminal to_cursor active +#:: # Same as above except cleared lines are moved into scrollback +#:: map f1 clear_terminal to_cursor_scroll active +#:: # Erase the last command and its output (needs shell integration to work) +#:: map f1 clear_terminal last_command active + +#:: If you want to operate on all kitty windows instead of just the +#:: current one, use all instead of active. + +#:: Some useful functions that can be defined in the shell rc files +#:: to perform various kinds of clearing of the current window: + +#:: .. code-block:: sh + +#:: clear-only-screen() { +#:: printf "\e[H\e[2J" +#:: } + +#:: clear-screen-and-scrollback() { +#:: printf "\e[H\e[3J" +#:: } + +#:: clear-screen-saving-contents-in-scrollback() { +#:: printf "\e[H\e[22J" +#:: } + +#:: For instance, using these escape codes, it is possible to remap +#:: Ctrl+L to both scroll the current screen contents into the +#:: scrollback buffer and clear the screen, instead of just clearing +#:: the screen. For ZSH, in ~/.zshrc, add: + +#:: .. code-block:: zsh + +#:: ctrl_l() { +#:: builtin print -rn -- $'\r\e[0J\e[H\e[22J' >"$TTY" +#:: builtin zle .reset-prompt +#:: builtin zle -R +#:: } +#:: zle -N ctrl_l +#:: bindkey '^l' ctrl_l + +#:: Alternatively, you can just add map ctrl+l clear_terminal +#:: to_cursor_scroll active to kitty.conf which works with no changes +#:: to the shell rc files, but only clears up to the prompt, it does +#:: not clear any text at the prompt itself. + +#: Clear to start + +# map cmd+k clear_terminal to_cursor active + +#: Clear scrollback + +# map option+cmd+k clear_terminal scrollback active + +#: Clear the last command + +# map cmd+l clear_terminal last_command active + +#: Clear screen + +# map cmd+ctrl+l clear_terminal to_cursor_scroll active + +#: Reload kitty.conf + +# map kitty_mod+f5 load_config_file +# map ctrl+cmd+, load_config_file + +#:: Reload kitty.conf, applying any changes since the last time it +#:: was loaded. Note that a handful of options cannot be dynamically +#:: changed and require a full restart of kitty. Particularly, when +#:: changing shortcuts for actions located on the macOS global menu +#:: bar, a full restart is needed. You can also map a keybinding to +#:: load a different config file, for example:: + +#:: map f5 load_config /path/to/alternative/kitty.conf + +#:: Note that all options from the original kitty.conf are discarded, +#:: in other words the new configuration *replace* the old ones. + +#: Debug kitty configuration + +# map kitty_mod+f6 debug_config +# map opt+cmd+, debug_config + +#:: Show details about exactly what configuration kitty is running +#:: with and its host environment. Useful for debugging issues. + +#: Send arbitrary text on key presses + +#:: E.g. map ctrl+shift+alt+h send_text all Hello World + +#:: You can tell kitty to send arbitrary (UTF-8) encoded text to the +#:: client program when pressing specified shortcut keys. For +#:: example:: + +#:: map ctrl+alt+a send_text all Special text + +#:: This will send "Special text" when you press the Ctrl+Alt+A key +#:: combination. The text to be sent decodes ANSI C escapes +#:: so you can use escapes like \e to send control +#:: codes or \u21fb to send Unicode characters (or you can just input +#:: the Unicode characters directly as UTF-8 text). You can use +#:: `kitten show-key` to get the key escape codes you want to +#:: emulate. + +#:: The first argument to send_text is the keyboard modes in which to +#:: activate the shortcut. The possible values are normal, +#:: application, kitty or a comma separated combination of them. The +#:: modes normal and application refer to the DECCKM cursor key mode +#:: for terminals, and kitty refers to the kitty extended keyboard +#:: protocol. The special value all means all of them. + +#:: Some more examples:: + +#:: # Output a word and move the cursor to the start of the line (like typing and pressing Home) +#:: map ctrl+alt+a send_text normal Word\e[H +#:: map ctrl+alt+a send_text application Word\eOH +#:: # Run a command at a shell prompt (like typing the command and pressing Enter) +#:: map ctrl+alt+a send_text normal,application some command with arguments\r + +#: Open kitty Website + +# map shift+cmd+/ open_url https://sw.kovidgoyal.net/kitty/ + +#: Hide macOS kitty application + +# map cmd+h hide_macos_app + +#: Hide macOS other applications + +# map opt+cmd+h hide_macos_other_apps + +#: Minimize macOS window + +# map cmd+m minimize_macos_window + +#: Quit kitty + +# map cmd+q quit + +#: }}} + +#: }}} + + +shell_integration no-cursor + +# BEGIN_KITTY_FONTS +font_family family="JetBrainsMono Nerd Font" +bold_font auto +italic_font auto +bold_italic_font auto +# END_KITTY_FONTS + + +# BEGIN_KITTY_THEME +# Catppuccin-Mocha +include current-theme.conf +# END_KITTY_THEME +# +# include colors.conf diff --git a/kitty/kitty.conf.bak b/kitty/kitty.conf.bak new file mode 100644 index 0000000..ca04370 --- /dev/null +++ b/kitty/kitty.conf.bak @@ -0,0 +1,3020 @@ +# vim:fileencoding=utf-8:foldmethod=marker + +#: Fonts {{{ + +#: kitty has very powerful font management. You can configure +#: individual font faces and even specify special fonts for particular +#: characters. + +# font_family monospace +# bold_font auto +# italic_font auto +# bold_italic_font auto + +#: You can specify different fonts for the bold/italic/bold-italic +#: variants. The easiest way to select fonts is to run the `kitten +#: choose-fonts` command which will present a nice UI for you to +#: select the fonts you want with previews and support for selecting +#: variable fonts and font features. If you want to learn to select +#: fonts manually, read the font specification syntax +#: . + +# font_size 11.0 + +#: Font size (in pts). + +# force_ltr no + +#: kitty does not support BIDI (bidirectional text), however, for RTL +#: scripts, words are automatically displayed in RTL. That is to say, +#: in an RTL script, the words "HELLO WORLD" display in kitty as +#: "WORLD HELLO", and if you try to select a substring of an RTL- +#: shaped string, you will get the character that would be there had +#: the string been LTR. For example, assuming the Hebrew word ירושלים, +#: selecting the character that on the screen appears to be ם actually +#: writes into the selection buffer the character י. kitty's default +#: behavior is useful in conjunction with a filter to reverse the word +#: order, however, if you wish to manipulate RTL glyphs, it can be +#: very challenging to work with, so this option is provided to turn +#: it off. Furthermore, this option can be used with the command line +#: program GNU FriBidi +#: to get BIDI support, because it will force kitty to always treat +#: the text as LTR, which FriBidi expects for terminals. + +# symbol_map + +#: E.g. symbol_map U+E0A0-U+E0A3,U+E0C0-U+E0C7 PowerlineSymbols + +#: Map the specified Unicode codepoints to a particular font. Useful +#: if you need special rendering for some symbols, such as for +#: Powerline. Avoids the need for patched fonts. Each Unicode code +#: point is specified in the form `U+`. You +#: can specify multiple code points, separated by commas and ranges +#: separated by hyphens. This option can be specified multiple times. +#: The syntax is:: + +#: symbol_map codepoints Font Family Name + +# narrow_symbols + +#: E.g. narrow_symbols U+E0A0-U+E0A3,U+E0C0-U+E0C7 1 + +#: Usually, for Private Use Unicode characters and some symbol/dingbat +#: characters, if the character is followed by one or more spaces, +#: kitty will use those extra cells to render the character larger, if +#: the character in the font has a wide aspect ratio. Using this +#: option you can force kitty to restrict the specified code points to +#: render in the specified number of cells (defaulting to one cell). +#: This option can be specified multiple times. The syntax is:: + +#: narrow_symbols codepoints [optionally the number of cells] + +# disable_ligatures never + +#: Choose how you want to handle multi-character ligatures. The +#: default is to always render them. You can tell kitty to not render +#: them when the cursor is over them by using cursor to make editing +#: easier, or have kitty never render them at all by using always, if +#: you don't like them. The ligature strategy can be set per-window +#: either using the kitty remote control facility or by defining +#: shortcuts for it in kitty.conf, for example:: + +#: map alt+1 disable_ligatures_in active always +#: map alt+2 disable_ligatures_in all never +#: map alt+3 disable_ligatures_in tab cursor + +#: Note that this refers to programming ligatures, typically +#: implemented using the calt OpenType feature. For disabling general +#: ligatures, use the font_features option. + +# font_features + +#: E.g. font_features none + +#: Choose exactly which OpenType features to enable or disable. Note +#: that for the main fonts, features can be specified when selecting +#: the font using the choose-fonts kitten. This setting is useful for +#: fallback fonts. + +#: Some fonts might have features worthwhile in a terminal. For +#: example, Fira Code includes a discretionary feature, zero, which in +#: that font changes the appearance of the zero (0), to make it more +#: easily distinguishable from Ø. Fira Code also includes other +#: discretionary features known as Stylistic Sets which have the tags +#: ss01 through ss20. + +#: For the exact syntax to use for individual features, see the +#: HarfBuzz documentation . + +#: Note that this code is indexed by PostScript name, and not the font +#: family. This allows you to define very precise feature settings; +#: e.g. you can disable a feature in the italic font but not in the +#: regular font. + +#: On Linux, font features are first read from the FontConfig database +#: and then this option is applied, so they can be configured in a +#: single, central place. + +#: To get the PostScript name for a font, use the `fc-scan file.ttf` +#: command on Linux or the `Font Book tool on macOS +#: `__. + +#: Enable alternate zero and oldstyle numerals:: + +#: font_features FiraCode-Retina +zero +onum + +#: Enable only alternate zero in the bold font:: + +#: font_features FiraCode-Bold +zero + +#: Disable the normal ligatures, but keep the calt feature which (in +#: this font) breaks up monotony:: + +#: font_features TT2020StyleB-Regular -liga +calt + +#: In conjunction with force_ltr, you may want to disable Arabic +#: shaping entirely, and only look at their isolated forms if they +#: show up in a document. You can do this with e.g.:: + +#: font_features UnifontMedium +isol -medi -fina -init + +# modify_font + +#: Modify font characteristics such as the position or thickness of +#: the underline and strikethrough. The modifications can have the +#: suffix px for pixels or % for percentage of original value. No +#: suffix means use pts. For example:: + +#: modify_font underline_position -2 +#: modify_font underline_thickness 150% +#: modify_font strikethrough_position 2px + +#: Additionally, you can modify the size of the cell in which each +#: font glyph is rendered and the baseline at which the glyph is +#: placed in the cell. For example:: + +#: modify_font cell_width 80% +#: modify_font cell_height -2px +#: modify_font baseline 3 + +#: Note that modifying the baseline will automatically adjust the +#: underline and strikethrough positions by the same amount. +#: Increasing the baseline raises glyphs inside the cell and +#: decreasing it lowers them. Decreasing the cell size might cause +#: rendering artifacts, so use with care. + +# box_drawing_scale 0.001, 1, 1.5, 2 + +#: The sizes of the lines used for the box drawing Unicode characters. +#: These values are in pts. They will be scaled by the monitor DPI to +#: arrive at a pixel value. There must be four values corresponding to +#: thin, normal, thick, and very thick lines. + +# undercurl_style thin-sparse + +#: The style with which undercurls are rendered. This option takes the +#: form (thin|thick)-(sparse|dense). Thin and thick control the +#: thickness of the undercurl. Sparse and dense control how often the +#: curl oscillates. With sparse the curl will peak once per character, +#: with dense twice. Changing this option dynamically via reloading +#: the config or remote control is undefined. + +# underline_exclusion 1 + +#: By default kitty renders gaps in underlines when they overlap with +#: descenders (the parts of letters below the baseline, such as for y, +#: q, p etc.). This option controls the thickness of the gaps. It can +#: be either a unitless number in which case it is a fraction of the +#: underline thickness as specified in the font or it can have a +#: suffix of px for pixels or pt for points. Set to zero to disable +#: the gaps. Changing this option dynamically via reloading the config +#: or remote control is undefined. + +# text_composition_strategy platform + +#: Control how kitty composites text glyphs onto the background color. +#: The default value of platform tries for text rendering as close to +#: "native" for the platform kitty is running on as possible. + +#: A value of legacy uses the old (pre kitty 0.28) strategy for how +#: glyphs are composited. This will make dark text on light +#: backgrounds look thicker and light text on dark backgrounds +#: thinner. It might also make some text appear like the strokes are +#: uneven. + +#: You can fine tune the actual contrast curve used for glyph +#: composition by specifying up to two space-separated numbers for +#: this setting. + +#: The first number is the gamma adjustment, which controls the +#: thickness of dark text on light backgrounds. Increasing the value +#: will make text appear thicker. The default value for this is 1.0 on +#: Linux and 1.7 on macOS. Valid values are 0.01 and above. The result +#: is scaled based on the luminance difference between the background +#: and the foreground. Dark text on light backgrounds receives the +#: full impact of the curve while light text on dark backgrounds is +#: affected very little. + +#: The second number is an additional multiplicative contrast. It is +#: percentage ranging from 0 to 100. The default value is 0 on Linux +#: and 30 on macOS. + +#: If you wish to achieve similar looking thickness in light and dark +#: themes, a good way to experiment is start by setting the value to +#: 1.0 0 and use a dark theme. Then adjust the second parameter until +#: it looks good. Then switch to a light theme and adjust the first +#: parameter until the perceived thickness matches the dark theme. + +# text_fg_override_threshold 0 + +#: A setting to prevent low contrast between foreground and background +#: colors. Useful when working with applications that use colors that +#: do not contrast well with your preferred color scheme. The default +#: value is 0, which means no color overriding is performed. There are +#: two modes of operation: + +#: A value with the suffix ratio represents the minimum accepted +#: contrast ratio between the foreground and background color. +#: Possible values range from 0.0 ratio to 21.0 ratio. For example, to +#: meet WCAG level AA +#: +#: a value of 4.5 ratio can be provided. The algorithm is implemented +#: using HSLuv which enables it to change the +#: perceived lightness of a color just as much as needed without +#: really changing its hue and saturation. + +#: A value with the suffix % represents the minimum accepted +#: difference in luminance between the foreground and background +#: color, below which kitty will override the foreground color. It is +#: percentage ranging from 0 % to 100 %. If the difference in +#: luminance of the foreground and background is below this threshold, +#: the foreground color will be set to white if the background is dark +#: or black if the background is light. + +#: WARNING: Some programs use characters (such as block characters) +#: for graphics display and may expect to be able to set the +#: foreground and background to the same color (or similar colors). If +#: you see unexpected stripes, dots, lines, incorrect color, no color +#: where you expect color, or any kind of graphic display problem try +#: setting text_fg_override_threshold to 0 to see if this is the cause +#: of the problem or consider using the ratio mode of operation +#: described above instead of the % mode of operation. + +#: }}} + +#: Text cursor customization {{{ + +# cursor #cccccc + +#: Default text cursor color. If set to the special value none the +#: cursor will be rendered with a "reverse video" effect. Its color +#: will be the color of the text in the cell it is over and the text +#: will be rendered with the background color of the cell. Note that +#: if the program running in the terminal sets a cursor color, this +#: takes precedence. Also, the cursor colors are modified if the cell +#: background and foreground colors have very low contrast. Note that +#: some themes set this value, so if you want to override it, place +#: your value after the lines where the theme file is included. + +# cursor_text_color #111111 + +#: The color of text under the cursor. If you want it rendered with +#: the background color of the cell underneath instead, use the +#: special keyword: `background`. Note that if cursor is set to none +#: then this option is ignored. Note that some themes set this value, +#: so if you want to override it, place your value after the lines +#: where the theme file is included. + +# cursor_shape block +cursor_trail 10 +cursor_trail_decay 0.1 0.3 +cursor_trail_start_threshold 0 + +#: The cursor shape can be one of block, beam, underline. Note that +#: when reloading the config this will be changed only if the cursor +#: shape has not been set by the program running in the terminal. This +#: sets the default cursor shape, applications running in the terminal +#: can override it. In particular, shell integration +#: in kitty sets +#: the cursor shape to beam at shell prompts. You can avoid this by +#: setting shell_integration to no-cursor. + + + +# cursor_shape_unfocused hollow + +#: Defines the text cursor shape when the OS window is not focused. +#: The unfocused cursor shape can be one of block, beam, underline, +#: hollow and unchanged (leave the cursor shape as it is). + +# cursor_beam_thickness 1.2 + +#: The thickness of the beam cursor (in pts). + +# cursor_underline_thickness 2.0 + +#: The thickness of the underline cursor (in pts). + +# cursor_blink_interval 1.5 + +#: The interval to blink the cursor (in seconds). Set to zero to +#: disable blinking. Negative values mean use system default. Note +#: that the minimum interval will be limited to repaint_delay. You can +#: also animate the cursor blink by specifying an easing function. For +#: example, setting this to option to 0.5 ease-in-out will cause the +#: cursor blink to be animated over a second, in the first half of the +#: second it will go from opaque to transparent and then back again +#: over the next half. You can specify different easing functions for +#: the two halves, for example: -1 linear ease-out. kitty supports all +#: the CSS easing functions . Note that turning on animations +#: uses extra power as it means the screen is redrawn multiple times +#: per blink interval. See also, cursor_stop_blinking_after. This +#: setting also controls blinking text, which blinks in exact rhythm +#: with the cursor. + +# cursor_stop_blinking_after 15.0 + +#: Stop blinking cursor after the specified number of seconds of +#: keyboard inactivity. Set to zero to never stop blinking. This +#: setting also controls blinking text, which blinks in exact rhythm +#: with the cursor. + +cursor_trail 1 + +#: Set this to a value larger than zero to enable a "cursor trail" +#: animation. This is an animation that shows a "trail" following the +#: movement of the text cursor. It makes it easy to follow large +#: cursor jumps and makes for a cool visual effect of the cursor +#: zooming around the screen. The actual value of this option controls +#: when the animation is triggered. It is a number of milliseconds. +#: The trail animation only follows cursors that have stayed in their +#: position for longer than the specified number of milliseconds. This +#: prevents trails from appearing for cursors that rapidly change +#: their positions during UI updates in complex applications. See +#: cursor_trail_decay to control the animation speed and +#: cursor_trail_start_threshold to control when a cursor trail is +#: started. + +cursor_trail_decay 0.1 0.4 + +#: Controls the decay times for the cursor trail effect when the +#: cursor_trail is enabled. This option accepts two positive float +#: values specifying the fastest and slowest decay times in seconds. +#: The first value corresponds to the fastest decay time (minimum), +#: and the second value corresponds to the slowest decay time +#: (maximum). The second value must be equal to or greater than the +#: first value. Smaller values result in a faster decay of the cursor +#: trail. Adjust these values to control how quickly the cursor trail +#: fades away. + +cursor_trail_start_threshold 2 + +#: Set the distance threshold for starting the cursor trail. This +#: option accepts a positive integer value that represents the minimum +#: number of cells the cursor must move before the trail is started. +#: When the cursor moves less than this threshold, the trail is +#: skipped, reducing unnecessary cursor trail animation. + +# cursor_trail_color none + +#: Set the color of the cursor trail when cursor_trail is enabled. If +#: set to 'none' (the default), the cursor trail will use the cursor's +#: background color. Otherwise, specify a color value (e.g., #ff0000 +#: for red, or a named color like 'red'). This allows you to customize +#: the appearance of the cursor trail independently of the cursor +#: color. + +#: }}} + +#: Scrollback {{{ + +scrollback_lines 5000 + +#: Number of lines of history to keep in memory for scrolling back. +#: Memory is allocated on demand. Negative numbers are (effectively) +#: infinite scrollback. Note that using very large scrollback is not +#: recommended as it can slow down performance of the terminal and +#: also use large amounts of RAM. Instead, consider using +#: scrollback_pager_history_size. Note that on config reload if this +#: is changed it will only affect newly created windows, not existing +#: ones. + +# scrollbar scrolled + +#: Control when the scrollbar is displayed. + +#: scrolled +#: means when the scrolling backwards has started. +#: hovered +#: means when the mouse is hovering on the right edge of the window. +#: scrolled-and-hovered +#: means when the mouse is over the scrollbar region *and* scrolling backwards has started. +#: always +#: means whenever any scrollback is present +#: never +#: means disable the scrollbar. + +# scrollbar_interactive yes + +#: If disabled, the scrollbar will not be controllable via th emouse +#: and all mouse events will pass through the scrollbar. + +# scrollbar_jump_on_click yes + +#: When enabled clicking in the scrollbar track will cause the scroll +#: position to jump to the clicked location, otherwise the scroll +#: position will only move towards the position by a single screenful, +#: which is how traditional scrollbars behave. + +# scrollbar_width 0.5 + +#: The width of the scroll bar in units of cell width. + +# scrollbar_hover_width 1 + +#: The width of the scroll bar when the mouse is hovering over it, in +#: units of cell width. + +# scrollbar_handle_opacity 0.5 + +#: The opacity of the scrollbar handle, 0 being fully transparent and +#: 1 being full opaque. + +# scrollbar_radius 0.3 + +#: The radius (curvature) of the scrollbar handle in units of cell +#: width. Should be less than scrollbar_width. + +# scrollbar_gap 0.1 + +#: The gap between the scrollbar and the window edge in units of cell +#: width. + +# scrollbar_min_handle_height 1 + +#: The minimum height of the scrollbar handle in units of cell height. +#: Prevents the handle from becoming too small when there is a lot of +#: scrollback. + +# scrollbar_hitbox_expansion 0.25 + +#: The extra area around the handle to allow easier grabbing of the +#: scollbar in units of cell width. + +# scrollbar_track_opacity 0 + +#: The opacity of the scrollbar track, 0 being fully transparent and 1 +#: being full opaque. + +# scrollbar_track_hover_opacity 0.1 + +#: The opacity of the scrollbar track when the mouse is over the +#: scrollbar, 0 being fully transparent and 1 being full opaque. + +# scrollbar_handle_color foreground + +#: The color of the scrollbar handle. A value of foreground means to +#: use the current foreground text color, a value of +#: selection_background means to use the current selection background +#: color. Also, you can use an arbitrary color, such as #12af59 or +#: red. + +# scrollbar_track_color foreground + +#: The color of the scrollbar track. A value of foreground means to +#: use the current foreground text color, a value of +#: selection_background means to use the current selection background +#: color. Also, you can use an arbitrary color, such as #12af59 or +#: red. + +# scrollback_pager less --chop-long-lines --RAW-CONTROL-CHARS +INPUT_LINE_NUMBER + +#: Program with which to view scrollback in a new window. The +#: scrollback buffer is passed as STDIN to this program. If you change +#: it, make sure the program you use can handle ANSI escape sequences +#: for colors and text formatting. INPUT_LINE_NUMBER in the command +#: line above will be replaced by an integer representing which line +#: should be at the top of the screen. Similarly CURSOR_LINE and +#: CURSOR_COLUMN will be replaced by the current cursor position or +#: set to 0 if there is no cursor, for example, when showing the last +#: command output. + +#: If you would rather use neovim to view the scrollback, use +#: something like this:: + +#: scrollback_pager nvim --cmd 'set eventignore=FileType' +'nnoremap q ZQ' +'call nvim_open_term(0, {})' +'set nomodified nolist' +'$' - + +#: The above works for neovim 0.12 and newer. There is also a +#: dedicated plugin kitty-scrollback.nvim +#: you can use +#: with more features that works with older neovim as well. + +# scrollback_pager_history_size 0 + +#: Separate scrollback history size (in MB), used only for browsing +#: the scrollback buffer with pager. This separate buffer is not +#: available for interactive scrolling but will be piped to the pager +#: program when viewing scrollback buffer in a separate window. The +#: current implementation stores the data in UTF-8, so approximately +#: 10000 lines per megabyte at 100 chars per line, for pure ASCII, +#: unformatted text. A value of zero or less disables this feature. +#: The maximum allowed size is 4GB. Note that on config reload if this +#: is changed it will only affect newly created windows, not existing +#: ones. + +# scrollback_fill_enlarged_window no + +#: Fill new space with lines from the scrollback buffer after +#: enlarging a window. + +# wheel_scroll_multiplier 5.0 + +#: Multiplier for the number of lines scrolled by the mouse wheel. +#: Note that this is only used for low precision scrolling devices, +#: not for high precision scrolling devices on platforms such as macOS +#: and Wayland. Use negative numbers to change scroll direction. See +#: also wheel_scroll_min_lines. + +# wheel_scroll_min_lines 1 + +#: The minimum number of lines scrolled by the mouse wheel. The scroll +#: multiplier wheel_scroll_multiplier only takes effect after it +#: reaches this number. Note that this is only used for low precision +#: scrolling devices like wheel mice that scroll by very small amounts +#: when using the wheel. With a negative number, the minimum number of +#: lines will always be added. + +# touch_scroll_multiplier 1.0 + +#: Multiplier for the number of lines scrolled by a touchpad. Note +#: that this is only used for high precision scrolling devices on +#: platforms such as macOS and Wayland. Use negative numbers to change +#: scroll direction. + +#: }}} + +#: Mouse {{{ + +# mouse_hide_wait 3.0 + +#: Hide mouse cursor after the specified number of seconds of the +#: mouse not being used. Set to zero to disable mouse cursor hiding. +#: Set to a negative value to hide the mouse cursor immediately when +#: typing text. Disabled by default on macOS as getting it to work +#: robustly with the ever-changing sea of bugs that is Cocoa is too +#: much effort. + +#: By default, once the cursor is hidden, it is immediately unhidden +#: on any further mouse events. + +#: Two formats are supported: +#: - +#: - + +#: To change the unhide behavior, the optional parameters , , and may be set. + +#: +#: Waits for the specified number of seconds after mouse events before unhiding the +#: mouse cursor. Set to zero to unhide mouse cursor immediately on mouse activity. +#: This is useful to prevent the mouse cursor from unhiding on accidental swipes on +#: the trackpad. + +#: +#: Sets the threshold of mouse activity required to unhide the mouse cursor, when +#: the option is non-zero. When is zero, this has no +#: effect. + +#: For example, if is 40 and is 2.5, when kitty +#: detects a mouse event, it records the number of mouse events in the next 2.5 +#: seconds, and checks if that exceeds 40 * 2.5 = 100. If it does, then the mouse +#: cursor is unhidden, otherwise nothing happens. + +#: +#: Controls what mouse events may unhide the mouse cursor. If enabled, both scroll +#: and movement events may unhide the cursor. If disabled, only mouse movements can +#: unhide the cursor. + +#: Examples of valid values: +#: - 0.0 +#: - 1.0 +#: - -1.0 +#: - 0.1 3.0 40 yes + +# url_color #0087bd +# url_style curly + +#: The color and style for highlighting URLs on mouse-over. url_style +#: can be one of: none, straight, double, curly, dotted, dashed. + +# open_url_with default + +#: The program to open clicked URLs. The special value default will +#: first look for any URL handlers defined via the open_actions +#: facility and if non +#: are found, it will use the Operating System's default URL handler +#: (open on macOS and xdg-open on Linux). + +# url_prefixes file ftp ftps gemini git gopher http https irc ircs kitty mailto news sftp ssh + +#: The set of URL prefixes to look for when detecting a URL under the +#: mouse cursor. + +# detect_urls yes + +#: Detect URLs under the mouse. Detected URLs are highlighted with an +#: underline and the mouse cursor becomes a hand over them. Even if +#: this option is disabled, URLs are still clickable. See also the +#: underline_hyperlinks option to control how hyperlinks (as opposed +#: to plain text URLs) are displayed. + +# url_excluded_characters + +#: Additional characters to be disallowed from URLs, when detecting +#: URLs under the mouse cursor. By default, all characters that are +#: legal in URLs are allowed. Additionally, newlines are allowed (but +#: stripped). This is to accommodate programs such as mutt that add +#: hard line breaks even for continued lines. \n can be added to this +#: option to disable this behavior. Special characters can be +#: specified using backslash escapes, to specify a backslash use a +#: double backslash. + +# show_hyperlink_targets no + +#: When the mouse hovers over a terminal hyperlink, show the actual +#: URL that will be activated when the hyperlink is clicked. + +# underline_hyperlinks hover + +#: Control how hyperlinks are underlined. They can either be +#: underlined on mouse hover, always (i.e. permanently underlined) or +#: never which means that kitty will not apply any underline styling +#: to hyperlinks. Note that the value of always only applies to real +#: (OSC 8) hyperlinks not text that is detected to be a URL on mouse +#: hover. Uses the url_style and url_color settings for the underline +#: style. Note that reloading the config and changing this value +#: to/from always will only affect text subsequently received by +#: kitty. + +# copy_on_select no + +#: Copy to clipboard or a private buffer on select. With this set to +#: clipboard, selecting text with the mouse will cause the text to be +#: copied to clipboard. Useful on platforms such as macOS that do not +#: have the concept of primary selection. You can instead specify a +#: name such as a1 to copy to a private kitty buffer. Map a shortcut +#: with the paste_from_buffer action to paste from this private +#: buffer. For example:: + +#: copy_on_select a1 +#: map shift+cmd+v paste_from_buffer a1 + +#: Note that copying to the clipboard is a security risk, as all +#: programs, including websites open in your browser can read the +#: contents of the system clipboard. + +# clear_selection_on_clipboard_loss no + +#: When the contents of the clipboard no longer reflect the current +#: selection, clear it. This is primarily useful on platforms such as +#: Linux where selecting text automatically copies it to a special +#: "primary selection" clipboard or if you have copy_on_select set to +#: clipboard. + +#: Note that on macOS the system does not provide notifications when +#: the clipboard owner is changed, so there, copying to clipboard in a +#: non-kitty application will not clear selections even if +#: copy_on_select is enabled. + +# paste_actions quote-urls-at-prompt,confirm + +#: A comma separated list of actions to take when pasting text into +#: the terminal. The supported paste actions are: + +#: quote-urls-at-prompt: +#: If the text being pasted is a URL and the cursor is at a shell prompt, +#: automatically quote the URL (needs shell_integration). +#: replace-dangerous-control-codes +#: Replace dangerous control codes from pasted text, without confirmation. +#: replace-newline +#: Replace the newline character from pasted text, without confirmation. +#: confirm: +#: Confirm the paste if the text to be pasted contains any terminal control codes +#: as this can be dangerous, leading to code execution if the shell/program running +#: in the terminal does not properly handle these. +#: confirm-if-large +#: Confirm the paste if it is very large (larger than 16KB) as pasting +#: large amounts of text into shells can be very slow. +#: filter: +#: Run the filter_paste() function from the file paste-actions.py in +#: the kitty config directory on the pasted text. The text returned by the +#: function will be actually pasted. +#: no-op: +#: Has no effect. + +# strip_trailing_spaces never + +#: Remove spaces at the end of lines when copying to clipboard. A +#: value of smart will do it when using normal selections, but not +#: rectangle selections. A value of always will always do it. + +# select_by_word_characters @-./_~?&=%+# + +#: Characters considered part of a word when double clicking. In +#: addition to these characters any character that is marked as an +#: alphanumeric character in the Unicode database will be matched. + +# select_by_word_characters_forward + +#: Characters considered part of a word when extending the selection +#: forward on double clicking. In addition to these characters any +#: character that is marked as an alphanumeric character in the +#: Unicode database will be matched. + +#: If empty (default) select_by_word_characters will be used for both +#: directions. + +# click_interval -1.0 + +#: The interval between successive clicks to detect double/triple +#: clicks (in seconds). Negative numbers will use the system default +#: instead, if available, or fallback to 0.5. + +# focus_follows_mouse no + +#: Set the active window to the window under the mouse when moving the +#: mouse around. On macOS, this will also cause the OS Window under +#: the mouse to be focused automatically when the mouse enters it. + +# pointer_shape_when_grabbed arrow + +#: The shape of the mouse pointer when the program running in the +#: terminal grabs the mouse. + +# default_pointer_shape beam + +#: The default shape of the mouse pointer. + +# pointer_shape_when_dragging beam crosshair + +#: The default shape of the mouse pointer when dragging across text. +#: The optional second value sets the shape when dragging in +#: rectangular selection mode. + +#: Mouse actions {{{ + +#: Mouse buttons can be mapped to perform arbitrary actions. The +#: syntax is: + +#: .. code-block:: none + +#: mouse_map button-name event-type modes action + +#: Where button-name is one of left, middle, right, b1 ... b8 with +#: added keyboard modifiers. For example: ctrl+shift+left refers to +#: holding the Ctrl+Shift keys while clicking with the left mouse +#: button. The value b1 ... b8 can be used to refer to up to eight +#: buttons on a mouse. + +#: event-type is one of press, release, doublepress, triplepress, +#: click, doubleclick. modes indicates whether the action is performed +#: when the mouse is grabbed by the program running in the terminal, +#: or not. The values are grabbed or ungrabbed or a comma separated +#: combination of them. grabbed refers to when the program running in +#: the terminal has requested mouse events. Note that the click and +#: double click events have a delay of click_interval to disambiguate +#: from double and triple presses. + +#: You can run kitty with the kitty --debug-input command line option +#: to see mouse events. See the builtin actions below to get a sense +#: of what is possible. + +#: If you want to unmap a button, map it to nothing. For example, to +#: disable opening of URLs with a plain click:: + +#: mouse_map left click ungrabbed + +#: See all the mappable actions including mouse actions here +#: . + +#: .. note:: +#: Once a selection is started, releasing the button that started it will +#: automatically end it and no release event will be dispatched. + +# clear_all_mouse_actions no + +#: Remove all mouse action definitions up to this point. Useful, for +#: instance, to remove the default mouse actions. + +#: Click the link under the mouse or move the cursor + +# mouse_map left click ungrabbed mouse_handle_click selection link prompt + +#:: First check for a selection and if one exists do nothing. Then +#:: check for a link under the mouse cursor and if one exists, click +#:: it. Finally check if the click happened at the current shell +#:: prompt and if so, move the cursor to the click location. Note +#:: that this requires shell integration +#:: to work. + +#: Click the link under the mouse or move the cursor even when grabbed + +# mouse_map shift+left click grabbed,ungrabbed mouse_handle_click selection link prompt + +#:: Same as above, except that the action is performed even when the +#:: mouse is grabbed by the program running in the terminal. + +#: Click the link under the mouse cursor + +# mouse_map ctrl+shift+left release grabbed,ungrabbed mouse_handle_click link + +#:: Variant with Ctrl+Shift is present because the simple click based +#:: version has an unavoidable delay of click_interval, to +#:: disambiguate clicks from double clicks. + +#: Discard press event for link click + +# mouse_map ctrl+shift+left press grabbed discard_event + +#:: Prevent this press event from being sent to the program that has +#:: grabbed the mouse, as the corresponding release event is used to +#:: open a URL. + +#: Paste from the primary selection + +# mouse_map middle release ungrabbed paste_from_selection + +#: Start selecting text + +# mouse_map left press ungrabbed mouse_selection normal + +#: Start selecting text in a rectangle + +# mouse_map ctrl+alt+left press ungrabbed mouse_selection rectangle + +#: Select a word + +# mouse_map left doublepress ungrabbed mouse_selection word + +#: Select a line + +# mouse_map left triplepress ungrabbed mouse_selection line + +#: Select line from point + +# mouse_map ctrl+alt+left triplepress ungrabbed mouse_selection line_from_point + +#:: Select from the clicked point to the end of the line. If you +#:: would like to select the word at the point and then extend to the +#:: rest of the line, change `line_from_point` to +#:: `word_and_line_from_point`. + +#: Extend the current selection + +# mouse_map right press ungrabbed mouse_selection extend + +#:: If you want only the end of the selection to be moved instead of +#:: the nearest boundary, use move-end instead of extend. + +#: Paste from the primary selection even when grabbed + +# mouse_map shift+middle release ungrabbed,grabbed paste_selection +# mouse_map shift+middle press grabbed discard_event + +#: Start selecting text even when grabbed + +# mouse_map shift+left press ungrabbed,grabbed mouse_selection normal + +#: Start selecting text in a rectangle even when grabbed + +# mouse_map ctrl+shift+alt+left press ungrabbed,grabbed mouse_selection rectangle + +#: Select a word even when grabbed + +# mouse_map shift+left doublepress ungrabbed,grabbed mouse_selection word + +#: Select a line even when grabbed + +# mouse_map shift+left triplepress ungrabbed,grabbed mouse_selection line + +#: Select line from point even when grabbed + +# mouse_map ctrl+shift+alt+left triplepress ungrabbed,grabbed mouse_selection line_from_point + +#:: Select from the clicked point to the end of the line even when +#:: grabbed. If you would like to select the word at the point and +#:: then extend to the rest of the line, change `line_from_point` to +#:: `word_and_line_from_point`. + +#: Extend the current selection even when grabbed + +# mouse_map shift+right press ungrabbed,grabbed mouse_selection extend + +#: Show clicked command output in pager + +# mouse_map ctrl+shift+right press ungrabbed mouse_show_command_output + +#:: Requires shell integration +#:: to work. + +#: }}} + +#: }}} + +#: Performance tuning {{{ + +# repaint_delay 10 + +#: Delay between screen updates (in milliseconds). Decreasing it, +#: increases frames-per-second (FPS) at the cost of more CPU usage. +#: The default value yields ~100 FPS which is more than sufficient for +#: most uses. Note that to actually achieve 100 FPS, you have to +#: either set sync_to_monitor to no or use a monitor with a high +#: refresh rate. Also, to minimize latency when there is pending input +#: to be processed, this option is ignored. + +# input_delay 3 + +#: Delay before input from the program running in the terminal is +#: processed (in milliseconds). Note that decreasing it will increase +#: responsiveness, but also increase CPU usage and might cause flicker +#: in full screen programs that redraw the entire screen on each loop, +#: because kitty is so fast that partial screen updates will be drawn. +#: This setting is ignored when the input buffer is almost full. + +# sync_to_monitor yes + +#: Sync screen updates to the refresh rate of the monitor. This +#: prevents screen tearing +#: when scrolling. +#: However, it limits the rendering speed to the refresh rate of your +#: monitor. With a very high speed mouse/high keyboard repeat rate, +#: you may notice some slight input latency. If so, set this to no. + +#: }}} + +#: Terminal bell {{{ + +# enable_audio_bell yes + +#: The audio bell. Useful to disable it in environments that require +#: silence. + +# visual_bell_duration 0.0 + +#: The visual bell duration (in seconds). Flash the screen when a bell +#: occurs for the specified number of seconds. Set to zero to disable. +#: The flash is animated, fading in and out over the specified +#: duration. The easing function used for the fading can be +#: controlled. For example, 2.0 linear will casuse the flash to fade +#: in and out linearly. The default if unspecified is to use ease-in- +#: out which fades slowly at the start, middle and end. You can +#: specify different easing functions for the fade-in and fade-out +#: parts, like this: 2.0 ease-in linear. kitty supports all the CSS +#: easing functions . + +# visual_bell_color none + +#: The color used by visual bell. Set to none will fall back to +#: selection background color. If you feel that the visual bell is too +#: bright, you can set it to a darker color. + +# window_alert_on_bell yes + +#: Request window attention on bell. Makes the dock icon bounce on +#: macOS or the taskbar flash on Linux. + +# bell_on_tab "🔔 " + +#: Some text or a Unicode symbol to show on the tab if a window in the +#: tab that does not have focus has a bell. If you want to use leading +#: or trailing spaces, surround the text with quotes. See +#: tab_title_template for how this is rendered. + +#: For backwards compatibility, values of yes, y and true are +#: converted to the default bell symbol and no, n, false and none are +#: converted to the empty string. + +# command_on_bell none + +#: Program to run when a bell occurs. The environment variable +#: KITTY_CHILD_CMDLINE can be used to get the program running in the +#: window in which the bell occurred. + +# bell_path none + +#: Path to a sound file to play as the bell sound. If set to none, the +#: system default bell sound is used. Must be in a format supported by +#: the operating systems sound API, such as WAV or OGA on Linux +#: (libcanberra) or AIFF, MP3 or WAV on macOS (NSSound). Relative +#: paths are resolved with respect to the kitty config directory. + +# linux_bell_theme __custom + +#: The XDG Sound Theme kitty will use to play the bell sound. On +#: Wayland, when the compositor supports it, it is asked to play the +#: system default bell sound, and this setting has no effect. Note +#: that Hyprland claims to support this protocol, but does not +#: actually play a sound +#: . This setting +#: defaults to the custom theme name specified in the XDG Sound theme +#: specification , falling back to the default +#: freedesktop theme if it does not exist. To change your sound theme +#: desktop wide, create +#: :file:~/.local/share/sounds/__custom/index.theme` with the +#: contents: + +#: [Sound Theme] + +#: Inherits=name-of-the-sound-theme-you-want-to-use + +#: Replace name-of-the-sound-theme-you-want-to-use with the actual +#: theme name. Now all compliant applications should use sounds from +#: this theme. + +#: }}} + +#: Window layout {{{ + +# remember_window_size yes +# initial_window_width 640 +# initial_window_height 400 + +#: If enabled, the OS Window size will be remembered so that new +#: instances of kitty will have the same size as the previous +#: instance. If disabled, the OS Window will initially have size +#: configured by initial_window_width/height, in pixels. You can use a +#: suffix of "c" on the width/height values to have them interpreted +#: as number of cells instead of pixels. + +# remember_window_position no + +#: If enabled, the OS Window position will be remembered so that new +#: instances of kitty will have the same position as the previous +#: instance. If disabled, the OS Window will be placed by the window +#: manager. Note that remembering of position only works if the +#: underlying desktop environment/window manager supports it. It never +#: works on Wayland. See also kitty --position to specify the position +#: when launching kitty. + +# enabled_layouts * + +#: The enabled window layouts. A comma separated list of layout names. +#: The special value all means all layouts. The first listed layout +#: will be used as the startup layout. Default configuration is all +#: layouts in alphabetical order. For a list of available layouts, see +#: the layouts . + +# window_resize_step_cells 2 +# window_resize_step_lines 2 + +#: The step size (in units of cell width/cell height) to use when +#: resizing kitty windows in a layout with the shortcut +#: start_resizing_window. The cells value is used for horizontal +#: resizing, and the lines value is used for vertical resizing. + +# window_border_width 0.5pt + +#: The width of window borders. Can be either in pixels (px) or pts +#: (pt). Values in pts will be rounded to the nearest number of pixels +#: based on screen resolution. If not specified, the unit is assumed +#: to be pts. Note that borders are displayed only when more than one +#: window is visible. They are meant to separate multiple windows. + +# draw_minimal_borders yes + +#: Draw only the minimum borders needed. This means that only the +#: borders that separate the window from a neighbor are drawn. Note +#: that setting a non-zero window_margin_width overrides this and +#: causes all borders to be drawn. + +# draw_window_borders_for_single_window no + +#: Draw borders around a window even when there is only a single +#: window visible. When enabled and there is only a single window, +#: full borders are drawn around it (as if draw_minimal_borders is +#: false). The border will show in the active color when the window is +#: focused and the OS window has focus, and in the inactive color when +#: the OS window loses focus. This provides a clear visual indicator +#: of whether the kitty window is focused. When there are multiple +#: windows visible, this option has no effect and normal border +#: drawing rules apply. + +# window_margin_width 0 + +#: The window margin (in pts) (blank area outside the border). A +#: single value sets all four sides. Two values set the vertical and +#: horizontal sides. Three values set top, horizontal and bottom. Four +#: values set top, right, bottom and left. + +# single_window_margin_width -1 + +#: The window margin to use when only a single window is visible (in +#: pts). Negative values will cause the value of window_margin_width +#: to be used instead. A single value sets all four sides. Two values +#: set the vertical and horizontal sides. Three values set top, +#: horizontal and bottom. Four values set top, right, bottom and left. + +# window_padding_width 0 + +#: The window padding (in pts) (blank area between the text and the +#: window border). A single value sets all four sides. Two values set +#: the vertical and horizontal sides. Three values set top, horizontal +#: and bottom. Four values set top, right, bottom and left. + +# single_window_padding_width -1 + +#: The window padding to use when only a single window is visible (in +#: pts). Negative values will cause the value of window_padding_width +#: to be used instead. A single value sets all four sides. Two values +#: set the vertical and horizontal sides. Three values set top, +#: horizontal and bottom. Four values set top, right, bottom and left. + +# placement_strategy center + +#: When the window size is not an exact multiple of the cell size, the +#: cell area of the terminal window will have some extra padding on +#: the sides. You can control how that padding is distributed with +#: this option. Using a value of center means the cell area will be +#: placed centrally. A value of top-left means the padding will be +#: only at the bottom and right edges. The value can be one of: top- +#: left, top, top-right, left, center, right, bottom-left, bottom, +#: bottom-right. + +# active_border_color #00ff00 + +#: The color for the border of the active window. Set this to none to +#: not draw borders around the active window. + +# inactive_border_color #cccccc + +#: The color for the border of inactive windows. + +# bell_border_color #ff5a00 + +#: The color for the border of inactive windows in which a bell has +#: occurred. + +# inactive_text_alpha 1.0 + +#: Fade the text in inactive windows by the specified amount (a number +#: between zero and one, with zero being fully faded). + +# hide_window_decorations no + +#: Hide the window decorations (title-bar and window borders) with +#: yes. On macOS, titlebar-only and titlebar-and-corners can be used +#: to only hide the titlebar and the rounded corners. Whether this +#: works and exactly what effect it has depends on the window +#: manager/operating system. Note that the effects of changing this +#: option when reloading config are undefined. When using titlebar- +#: only, it is useful to also set window_margin_width and +#: placement_strategy to prevent the rounded corners from clipping +#: text. Or use titlebar-and-corners. + +# window_logo_path none + +#: Path to a logo image. Must be in PNG/JPEG/WEBP/GIF/TIFF/BMP format. +#: Relative paths are interpreted relative to the kitty config +#: directory. The logo is displayed in a corner of every kitty window. +#: The position is controlled by window_logo_position. Individual +#: windows can be configured to have different logos either using the +#: launch action or the remote control +#: facility. + +# window_logo_position bottom-right + +#: Where to position the window logo in the window. The value can be +#: one of: top-left, top, top-right, left, center, right, bottom-left, +#: bottom, bottom-right. + +# window_logo_alpha 0.5 + +#: The amount the logo should be faded into the background. With zero +#: being fully faded and one being fully opaque. + +# window_logo_scale 0 + +#: The percentage (0-100] of the window size to which the logo should +#: scale. Using a single number means the logo is scaled to that +#: percentage of the shortest window dimension, while preserving +#: aspect ratio of the logo image. + +#: Using two numbers means the width and height of the logo are scaled +#: to the respective percentage of the window's width and height. + +#: Using zero as the percentage disables scaling in that dimension. A +#: single zero (the default) disables all scaling of the window logo. + +# resize_debounce_time 0.1 0.5 + +#: The time to wait (in seconds) before asking the program running in +#: kitty to resize and redraw the screen during a live resize of the +#: OS window, when no new resize events have been received, i.e. when +#: resizing is either paused or finished. On platforms such as macOS, +#: where the operating system sends events corresponding to the start +#: and end of a live resize, the second number is used for redraw- +#: after-pause since kitty can distinguish between a pause and end of +#: resizing. On such systems the first number is ignored and redraw is +#: immediate after end of resize. On other systems only the first +#: number is used so that kitty is "ready" quickly after the end of +#: resizing, while not also continuously redrawing, to save energy. + +# resize_in_steps no + +#: Resize the OS window in steps as large as the cells, instead of +#: with the usual pixel accuracy. Combined with initial_window_width +#: and initial_window_height in number of cells, this option can be +#: used to keep the margins as small as possible when resizing the OS +#: window. Note that this does not currently work on Wayland. + +# visual_window_select_characters 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ + +#: The list of characters for visual window selection. For example, +#: for selecting a window to focus on with focus_visible_window. The +#: value should be a series of unique numbers or alphabets, case +#: insensitive, from the set 0-9A-Z\-=[];',./\\`. Specify your +#: preference as a string of characters. + +# confirm_os_window_close -1 + +#: Ask for confirmation when closing an OS window or a tab with at +#: least this number of kitty windows in it by window manager (e.g. +#: clicking the window close button or pressing the operating system +#: shortcut to close windows) or by the close_tab action. A value of +#: zero disables confirmation. This confirmation also applies to +#: requests to quit the entire application (all OS windows, via the +#: quit action). Negative values are converted to positive ones, +#: however, with shell_integration enabled, using negative values +#: means windows sitting at a shell prompt are not counted, only +#: windows where some command is currently running. You can also have +#: backgrounded jobs prevent closing, by adding count-background to +#: the setting, for example: -1 count-background. Note that if you +#: want confirmation when closing individual windows, you can map the +#: close_window_with_confirmation action. + +#: }}} + +#: Tab bar {{{ + +# tab_bar_edge bottom + +#: The edge to show the tab bar on, top or bottom. + +# tab_bar_margin_width 0.0 + +#: The margin to the left and right of the tab bar (in pts). + +# tab_bar_margin_height 0.0 0.0 + +#: The margin above and below the tab bar (in pts). The first number +#: is the margin between the edge of the OS Window and the tab bar. +#: The second number is the margin between the tab bar and the +#: contents of the current tab. + +tab_bar_style powerline +tab_powerline_style round + +#: The tab bar style, can be one of: + +#: fade +#: Each tab's edges fade into the background color. (See also tab_fade) +#: slant +#: Tabs look like the tabs in a physical file. +#: separator +#: Tabs are separated by a configurable separator. (See also +#: tab_separator) +#: powerline +#: Tabs are shown as a continuous line with "fancy" separators. +#: (See also tab_powerline_style) +#: custom +#: A user-supplied Python function called draw_tab is loaded from the file +#: tab_bar.py in the kitty config directory. For examples of how to +#: write such a function, see the functions named draw_tab_with_* in +#: kitty's source code: kitty/tab_bar.py. See also +#: this discussion +#: for examples from kitty users. +#: hidden +#: The tab bar is hidden. If you use this, you might want to create +#: a mapping for the select_tab action which presents you with a list of +#: tabs and allows for easy switching to a tab. + +# tab_bar_filter + +#: A search expression . Only tabs that match this expression will +#: be shown in the tab bar. The currently active tab is always shown, +#: regardless of whether it matches or not. When using this option, +#: the tab bar may be displayed with less tabs than specified in +#: tab_bar_min_tabs, as evaluating the filter is expensive and is done +#: only at display time. This is most useful when using sessions +#: . An expression of +#: session:~ or session:^$ will show only tabs that belong to the +#: current session or no session. The various tab navigation actions +#: such as goto_tab, next_tab, previous_tab, etc. are automatically +#: restricted to work only on matching tabs. + +# tab_bar_align left + +#: The horizontal alignment of the tab bar, can be one of: left, +#: center, right. + +tab_bar_min_tabs 1 + +#: The minimum number of tabs that must exist before the tab bar is +#: shown. + +# tab_switch_strategy previous + +#: The algorithm to use when switching to a tab when the current tab +#: is closed. The default of previous will switch to the last used +#: tab. A value of left will switch to the tab to the left of the +#: closed tab. A value of right will switch to the tab to the right of +#: the closed tab. A value of last will switch to the right-most tab. + +# tab_fade 0.25 0.5 0.75 1 + +#: Control how each tab fades into the background when using fade for +#: the tab_bar_style. Each number is an alpha (between zero and one) +#: that controls how much the corresponding cell fades into the +#: background, with zero being no fade and one being full fade. You +#: can change the number of cells used by adding/removing entries to +#: this list. + +# tab_separator " ┇" + +#: The separator between tabs in the tab bar when using separator as +#: the tab_bar_style. + +# tab_powerline_style angled + +#: The powerline separator style between tabs in the tab bar when +#: using powerline as the tab_bar_style, can be one of: angled, +#: slanted, round. + +# tab_activity_symbol none + +#: Some text or a Unicode symbol to show on the tab if a window in the +#: tab that does not have focus has some activity. If you want to use +#: leading or trailing spaces, surround the text with quotes. See +#: tab_title_template for how this is rendered. + +# tab_title_max_length 0 + +#: The maximum number of cells that can be used to render the text in +#: a tab. A value of zero means that no limit is applied. + +# tab_title_template "{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{tab.last_focused_progress_percent}{title}" + +#: A template to render the tab title. The default just renders the +#: title with optional symbols for bell and activity. If you wish to +#: include the tab-index as well, use something like: {index}:{title}. +#: Useful if you have shortcuts mapped for goto_tab N. If you prefer +#: to see the index as a superscript, use {sup.index}. All data +#: available is: + +#: title +#: The current tab title. +#: index +#: The tab index usable with goto_tab N goto_tab shortcuts. +#: layout_name +#: The current layout name. +#: session_name +#: The name of the kitty session file from which this tab was created, if any. +#: active_session_name +#: The name of the kitty session file from which the active window in this tab was created, if any. +#: num_windows +#: The number of windows in the tab. +#: num_window_groups +#: The number of window groups (a window group is a window and all of its overlay windows) in the tab. +#: tab.active_wd +#: The working directory of the currently active window in the tab +#: (expensive, requires syscall). Use tab.active_oldest_wd to get +#: the directory of the oldest foreground process rather than the newest. +#: tab.active_exe +#: The name of the executable running in the foreground of the currently +#: active window in the tab (expensive, requires syscall). Use +#: tab.active_oldest_exe for the oldest foreground process. +#: max_title_length +#: The maximum title length available. +#: keyboard_mode +#: The name of the current keyboard mode or the empty string if no keyboard mode is active. +#: tab.last_focused_progress_percent +#: If a command running in a window reports the progress for a task, show this progress as a percentage +#: from the most recently focused window in the tab. Empty string if no progress is reported. +#: tab.progress_percent +#: If a command running in a window reports the progress for a task, show this progress as a percentage +#: from all windows in the tab, averaged. Empty string is no progress is reported. +#: custom +#: This will call a function named draw_title(data) from the file tab_bar.py placed in +#: the kitty config directory. The function will be passed a dictionary of data, the same data that +#: can be used in this template. It can then perform arbitrarily complex processing and return a string. +#: For example: tab_title_template "{custom}" will use the output of the function as the tab title. +#: Any print statements in the draw_title() will print to the STDOUT of the kitty process, useful +#: for debugging. + + +#: Note that formatting is done by Python's string formatting +#: machinery, so you can use, for instance, {layout_name[:2].upper()} +#: to show only the first two letters of the layout name, upper-cased. +#: If you want to style the text, you can use styling directives, for +#: example: +#: `{fmt.fg.red}red{fmt.fg.tab}normal{fmt.bg._00FF00}greenbg{fmt.bg.tab}`. +#: Similarly, for bold and italic: +#: `{fmt.bold}bold{fmt.nobold}normal{fmt.italic}italic{fmt.noitalic}`. +#: The 256 eight terminal colors can be used as `fmt.fg.color0` +#: through `fmt.fg.color255`. Note that for backward compatibility, if +#: {bell_symbol} or {activity_symbol} are not present in the template, +#: they are prepended to it. + +# active_tab_title_template none + +#: Template to use for active tabs. If not specified falls back to +#: tab_title_template. + +# active_tab_foreground #000 +# active_tab_background #eee +# active_tab_font_style bold-italic +# inactive_tab_foreground #444 +# inactive_tab_background #999 +# inactive_tab_font_style normal + +#: Tab bar colors and styles. +# tab_bar_background none + +#: Background color for the tab bar. Defaults to using the terminal +#: background color. + +# tab_bar_margin_color none + +#: Color for the tab bar margin area. Defaults to using the terminal +#: background color for margins above and below the tab bar. For side +#: margins the default color is chosen to match the background color +#: of the neighboring tab. + +#: }}} + +#: +#Color scheme {{{ + +# foreground #dddddd +# background #000000 + +#: The foreground and background colors. + +background_opacity 0.8 + +#: The opacity of the terminal background color. A number between zero +#: and one, where one is opaque and zero is fully transparent. This +#: will only work if supported by the OS (for instance, when using a +#: compositor under X11). Note that it only sets the background +#: color's opacity in cells that have the same background color as the +#: default terminal background, so that things like the status bar in +#: vim, powerline prompts, etc. still look good. But it means that if +#: you use a color theme with a background color in your editor, it +#: will not be rendered as transparent. Instead you should change the +#: default background color in your kitty config and not use a +#: background color in the editor color scheme. Or use the escape +#: codes to set the terminals default colors in a shell script to +#: launch your editor. See also transparent_background_colors. Be +#: aware that using a value less than 1.0 is a (possibly significant) +#: performance hit. When using a low value for this setting, it is +#: desirable that you set the background color to a color the matches +#: the general color of the desktop background, for best text +#: rendering. Note also, that this setting does not apply to the +#: background_image, if any. The background image can itself have +#: transparency via its alpha channel if desired, and that will be +#: respected. + +#: If you want to dynamically change transparency of windows, set +#: dynamic_background_opacity to yes (this is off by default as it has +#: a performance cost). Changing this option when reloading the config +#: will only work if dynamic_background_opacity was enabled in the +#: original config. + +# background_blur 0 + +#: Set to a positive value to enable background blur (blurring of the +#: visuals behind a transparent window) on platforms that support it. +#: Only takes effect when background_opacity is less than one. On +#: macOS, this will also control the blur radius (amount of blurring). +#: Setting it to too high a value will cause severe performance issues +#: and/or rendering artifacts. Usually, values up to 64 work well. +#: Note that this might cause performance issues, depending on how the +#: platform implements it, so use with care. Currently supported on +#: macOS and KDE. + +# transparent_background_colors + +#: A space separated list of upto 7 colors, with opacity. When the +#: background color of a cell matches one of these colors, it is +#: rendered semi-transparent using the specified opacity. + +#: Useful in more complex UIs like editors where you could want more +#: than a single background color to be rendered as transparent, for +#: instance, for a cursor highlight line background or a highlighted +#: block. Terminal applications can set this color using The kitty +#: color control escape code. + +#: The syntax for specifying colors is: color@opacity, where the +#: @opacity part is optional. When unspecified, the value of +#: background_opacity is used. For example:: + +#: transparent_background_colors red@0.5 #00ff00@0.3 + +#: Note that you must also set background_opacity to something less +#: than 1 for this setting to work properly. + +# dynamic_background_opacity no + +#: Allow changing of the background_opacity dynamically, using either +#: keyboard shortcuts (increase_background_opacity and +#: decrease_background_opacity) or the remote control facility. +#: Changing this option by reloading the config is not supported. + +# background_image none + +#: Path to a background image. Must be in PNG/JPEG/WEBP/TIFF/GIF/BMP +#: format. Note that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_image_layout tiled + +#: Whether to tile, scale or clamp the background image. The value can +#: be one of tiled, mirror-tiled, scaled, clamped, centered or +#: cscaled. The scaled and cscaled values scale the image to the +#: window size, with cscaled preserving the image aspect ratio. Note +#: that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_image_linear no + +#: When background image is scaled, whether linear interpolation +#: should be used. Note that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_tint 0.0 + +#: How much to tint the background image by the background color. This +#: option makes it easier to read the text. Tinting is done using the +#: current background color for each window. This option applies only +#: if background_image is set. Note that when using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# background_tint_gaps 1.0 + +#: How much to tint the background image at the window gaps by the +#: background color, after applying background_tint. Since this is +#: multiplicative with background_tint, it can be used to lighten the +#: tint over the window gaps for a *separated* look. Note that when +#: using auto_color_scheme +#: +#: this option is overridden by the color scheme file and must be set +#: inside it to take effect. + +# dim_opacity 0.4 + +#: How much to dim text that has the DIM/FAINT attribute set. One +#: means no dimming and zero means fully dimmed (i.e. invisible). + +# selection_foreground #000000 +# selection_background #fffacd + +#: The foreground and background colors for text selected with the +#: mouse. Setting both of these to none will cause a "reverse video" +#: effect for selections, where the selection will be the cell text +#: color and the text will become the cell background color. Setting +#: only selection_foreground to none will cause the foreground color +#: to be used unchanged. Note that these colors can be overridden by +#: the program running in the terminal. + +#: The color table {{{ + +#: The 256 terminal colors. There are 8 basic colors, each color has a +#: dull and bright version, for the first 16 colors. You can set the +#: remaining 240 colors as color16 to color255. + +# color0 #000000 +# color8 #767676 + +#: black + +# color1 #cc0403 +# color9 #f2201f + +#: red + +# color2 #19cb00 +# color10 #23fd00 + +#: green + +# color3 #cecb00 +# color11 #fffd00 + +#: yellow + +# color4 #0d73cc +# color12 #1a8fff + +#: blue + +# color5 #cb1ed1 +# color13 #fd28ff + +#: magenta + +# color6 #0dcdcd +# color14 #14ffff + +#: cyan + +# color7 #dddddd +# color15 #ffffff + +#: white + +# mark1_foreground black + +#: Color for marks of type 1 + +# mark1_background #98d3cb + +#: Color for marks of type 1 (light steel blue) + +# mark2_foreground black + +#: Color for marks of type 2 + +# mark2_background #f2dcd3 + +#: Color for marks of type 1 (beige) + +# mark3_foreground black + +#: Color for marks of type 3 + +# mark3_background #f274bc + +#: Color for marks of type 3 (violet) + +#: }}} + +#: }}} + +#: Advanced {{{ + +# shell . + +#: The shell program to execute. The default value of . means to use +#: the value of of the SHELL environment variable or if unset, +#: whatever shell is set as the default shell for the current user. +#: Note that on macOS if you change this, you might need to add +#: --login and --interactive to ensure that the shell starts in +#: interactive mode and reads its startup rc files. Environment +#: variables are expanded in this setting. + +# editor . + +#: The terminal based text editor (such as vim or nano) to use when +#: editing the kitty config file or similar tasks. + +#: The default value of . means to use the environment variables +#: VISUAL and EDITOR in that order. If these variables aren't set, +#: kitty will run your shell ($SHELL -l -i -c env) to see if your +#: shell startup rc files set VISUAL or EDITOR. If that doesn't work, +#: kitty will cycle through various known editors (vim, emacs, etc.) +#: and take the first one that exists on your system. + +# close_on_child_death no + +#: Close the window when the child process (usually the shell) exits. +#: With the default value no, the terminal will remain open when the +#: child exits as long as there are still other processes outputting +#: to the terminal (for example disowned or backgrounded processes). +#: When enabled with yes, the window will close as soon as the child +#: process exits. Note that setting it to yes means that any +#: background processes still using the terminal can fail silently +#: because their stdout/stderr/stdin no longer work. + +# remote_control_password + +#: Allow other programs to control kitty using passwords. This option +#: can be specified multiple times to add multiple passwords. If no +#: passwords are present kitty will ask the user for permission if a +#: program tries to use remote control with a password. A password can +#: also *optionally* be associated with a set of allowed remote +#: control actions. For example:: + +#: remote_control_password "my passphrase" get-colors set-colors focus-window focus-tab + +#: Only the specified actions will be allowed when using this +#: password. Glob patterns can be used too, for example:: + +#: remote_control_password "my passphrase" set-tab-* resize-* + +#: To get a list of available actions, run:: + +#: kitten @ --help + +#: A set of actions to be allowed when no password is sent can be +#: specified by using an empty password. For example:: + +#: remote_control_password "" *-colors + +#: Finally, the path to a python module can be specified that provides +#: a function is_cmd_allowed that is used to check every remote +#: control command. For example:: + +#: remote_control_password "my passphrase" my_rc_command_checker.py + +#: Relative paths are resolved from the kitty configuration directory. +#: See rc_custom_auth for details. + +# allow_remote_control no + +#: Allow other programs to control kitty. If you turn this on, other +#: programs can control all aspects of kitty, including sending text +#: to kitty windows, opening new windows, closing windows, reading the +#: content of windows, etc. Note that this even works over SSH +#: connections. The default setting of no prevents any form of remote +#: control. The meaning of the various values are: + +#: password +#: Remote control requests received over both the TTY device and the socket +#: are confirmed based on passwords, see remote_control_password. + +#: socket-only +#: Remote control requests received over a socket are accepted +#: unconditionally. Requests received over the TTY are denied. +#: See listen_on. + +#: socket +#: Remote control requests received over a socket are accepted +#: unconditionally. Requests received over the TTY are confirmed based on +#: password. + +#: no +#: Remote control is completely disabled. + +#: yes +#: Remote control requests are always accepted. + +# listen_on none + +#: Listen to the specified socket for remote control connections. Note +#: that this will apply to all kitty instances. It can be overridden +#: by the kitty --listen-on command line option. For UNIX sockets, +#: such as unix:${TEMP}/mykitty or unix:@mykitty (on Linux). +#: Environment variables are expanded and relative paths are resolved +#: with respect to the temporary directory. If {kitty_pid} is present, +#: then it is replaced by the PID of the kitty process, otherwise the +#: PID of the kitty process is appended to the value, with a hyphen. +#: For TCP sockets such as tcp:localhost:0 a random port is always +#: used even if a non-zero port number is specified. See the help for +#: kitty --listen-on for more details. Note that this will be ignored +#: unless allow_remote_control is set to either: yes, socket or +#: socket-only. Changing this option by reloading the config is not +#: supported. + +# env + +#: Specify the environment variables to be set in all child processes. +#: Using the name with an equal sign (e.g. env VAR=) will set it to +#: the empty string. Specifying only the name (e.g. env VAR) will +#: remove the variable from the child process' environment. Note that +#: environment variables are expanded recursively, for example:: + +#: env VAR1=a +#: env VAR2=${HOME}/${VAR1}/b + +#: The value of VAR2 will be /a/b. + +#: Use the special value read_from_shell to have kitty read the +#: specified variables from your login shell shell configuration. +#: Useful if your shell startup files setup a bunch of environment +#: variables that you want available to kitty and in kitty session +#: files. Each variable name is treated as a glob pattern to match. +#: For example: env read_from_shell=PATH LANG LC_* XDG_* EDITOR +#: VISUAL. Note that these variables are only read after the +#: configuration is fully processed, thus they are not available for +#: recursive expansion and they will override any variables set by +#: other env directives. + +# filter_notification + +#: Specify rules to filter out notifications sent by applications +#: running in kitty. Can be specified multiple times to create +#: multiple filter rules. A rule specification is of the form +#: field:regexp. A filter rule can match on any of the fields: title, +#: body, app, type. The special value of all filters out all +#: notifications. Rules can be combined using Boolean operators. Some +#: examples:: + +#: filter_notification title:hello or body:"abc.*def" +#: # filter out notification from vim except for ones about updates, (?i) +#: # makes matching case insensitive. +#: filter_notification app:"[ng]?vim" and not body:"(?i)update" +#: # filter out all notifications +#: filter_notification all + +#: The field app is the name of the application sending the +#: notification and type is the type of the notification. Not all +#: applications will send these fields, so you can also match on the +#: title and body of the notification text. More sophisticated +#: programmatic filtering and custom actions on notifications can be +#: done by creating a notifications.py file in the kitty config +#: directory (~/.config/kitty). An annotated sample is available +#: . + +# watcher + +#: Path to python file which will be loaded for watchers +#: . Can be +#: specified more than once to load multiple watchers. The watchers +#: will be added to every kitty window. Relative paths are resolved +#: relative to the kitty config directory. Note that reloading the +#: config will only affect windows created after the reload. + +# exe_search_path + +#: Control where kitty finds the programs to run. The default search +#: order is: First search the system wide PATH, then ~/.local/bin and +#: ~/bin. If still not found, the PATH defined in the login shell +#: after sourcing all its startup files is tried. Finally, if present, +#: the PATH specified by the env option is tried. + +#: This option allows you to prepend, append, or remove paths from +#: this search order. It can be specified multiple times for multiple +#: paths. A simple path will be prepended to the search order. A path +#: that starts with the + sign will be append to the search order, +#: after ~/bin above. A path that starts with the - sign will be +#: removed from the entire search order. For example:: + +#: exe_search_path /some/prepended/path +#: exe_search_path +/some/appended/path +#: exe_search_path -/some/excluded/path + +# update_check_interval 24 + +#: The interval to periodically check if an update to kitty is +#: available (in hours). If an update is found, a system notification +#: is displayed informing you of the available update. The default is +#: to check every 24 hours, set to zero to disable. Update checking is +#: only done by the official binary builds. Distro packages or source +#: builds do not do update checking. Changing this option by reloading +#: the config is not supported. + +# startup_session none + +#: Path to a session file to use for all kitty instances. Can be +#: overridden by using the kitty --session =none command line option +#: for individual instances. See sessions +#: in the kitty +#: documentation for details. Note that relative paths are interpreted +#: with respect to the kitty config directory. Environment variables +#: in the path are expanded. Changing this option by reloading the +#: config is not supported. Note that if kitty is invoked with command +#: line arguments specifying a command to run, this option is ignored. + +# clipboard_control write-clipboard write-primary read-clipboard-ask read-primary-ask + +#: Allow programs running in kitty to read and write from the +#: clipboard. You can control exactly which actions are allowed. The +#: possible actions are: write-clipboard, read-clipboard, write- +#: primary, read-primary, read-clipboard-ask, read-primary-ask. The +#: default is to allow writing to the clipboard and primary selection +#: and to ask for permission when a program tries to read from the +#: clipboard. Note that disabling the read confirmation is a security +#: risk as it means that any program, even the ones running on a +#: remote server via SSH can read your clipboard. See also +#: clipboard_max_size. + +# clipboard_max_size 512 + +#: The maximum size (in MB) of data from programs running in kitty +#: that will be stored for writing to the system clipboard. A value of +#: zero means no size limit is applied. See also clipboard_control. + +# file_transfer_confirmation_bypass + +#: The password that can be supplied to the file transfer kitten +#: to skip the +#: transfer confirmation prompt. This should only be used when +#: initiating transfers from trusted computers, over trusted networks +#: or encrypted transports, as it allows any programs running on the +#: remote machine to read/write to the local filesystem, without +#: permission. + +# allow_hyperlinks yes + +#: Process hyperlink escape sequences (OSC 8). If disabled OSC 8 +#: escape sequences are ignored. Otherwise they become clickable +#: links, that you can click with the mouse or by using the hints +#: kitten . The +#: special value of ask means that kitty will ask before opening the +#: link when clicked. + +# shell_integration enabled + +#: Enable shell integration on supported shells. This enables features +#: such as jumping to previous prompts, browsing the output of the +#: previous command in a pager, etc. on supported shells. Set to +#: disabled to turn off shell integration, completely. It is also +#: possible to disable individual features, set to a space separated +#: list of these values: no-rc, no-cursor, no-title, no-cwd, no- +#: prompt-mark, no-complete, no-sudo. See Shell integration +#: for details. + +# allow_cloning ask + +#: Control whether programs running in the terminal can request new +#: windows to be created. The canonical example is clone-in-kitty +#: . +#: By default, kitty will ask for permission for each clone request. +#: Allowing cloning unconditionally gives programs running in the +#: terminal (including over SSH) permission to execute arbitrary code, +#: as the user who is running the terminal, on the computer that the +#: terminal is running on. + +# clone_source_strategies venv,conda,env_var,path + +#: Control what shell code is sourced when running clone-in-kitty in +#: the newly cloned window. The supported strategies are: + +#: venv +#: Source the file $VIRTUAL_ENV/bin/activate. This is used by the +#: Python stdlib venv module and allows cloning venvs automatically. +#: conda +#: Run conda activate $CONDA_DEFAULT_ENV. This supports the virtual +#: environments created by conda. +#: env_var +#: Execute the contents of the environment variable +#: KITTY_CLONE_SOURCE_CODE with eval. +#: path +#: Source the file pointed to by the environment variable +#: KITTY_CLONE_SOURCE_PATH. + +#: This option must be a comma separated list of the above values. +#: Only the first valid match, in the order specified, is sourced. + +notify_on_cmd_finish invisible 15.00 + +#: Show a desktop notification when a long-running command finishes +#: (needs shell_integration). The possible values are: + +#: never +#: Never send a notification. + +#: unfocused +#: Only send a notification when the window does not have keyboard focus. + +#: invisible +#: Only send a notification when the window both is unfocused and not visible +#: to the user, for example, because it is in an inactive tab or its OS window +#: is not currently visible (on platforms that support OS window visibility querying +#: this considers an OS Window visible iff it is active). + +#: always +#: Always send a notification, regardless of window state. + +#: There are two optional arguments: + +#: First, the minimum duration for what is considered a long running +#: command. The default is 5 seconds. Specify a second argument to set +#: the duration. For example: invisible 15. Do not set the value too +#: small, otherwise a command that launches a new OS Window and exits +#: will spam a notification. + +#: Second, the action to perform. The default is notify. The possible +#: values are: + +#: notify +#: Send a desktop notification. The subsequent arguments are optional and specify when +#: the notification is automatically cleared. The set of possible events when the notification is +#: cleared are: focus and next. focus means that when the notification +#: policy is unfocused or invisible the notification is automatically cleared +#: when the window regains focus. The value of next means that the previous notification +#: is cleared when the next notification is shown. The default when no arguments are specified +#: is: focus next. + +#: bell +#: Ring the terminal bell. + +#: notify-bell +#: Send a desktop notification and ring the terminal bell. +#: The arguments are the same as for `notify`. + +#: command +#: Run a custom command. All subsequent arguments are the cmdline to run. + +#: Some more examples:: + +#: # Send a notification when a command takes more than 5 seconds in an unfocused window +#: notify_on_cmd_finish unfocused +#: # Send a notification when a command takes more than 10 seconds in a invisible window +#: notify_on_cmd_finish invisible 10.0 +#: # Ring a bell when a command takes more than 10 seconds in a invisible window +#: notify_on_cmd_finish invisible 10.0 bell +#: # Run 'notify-send' when a command takes more than 10 seconds in a invisible window +#: # Here %c is replaced by the current command line and %s by the job exit code +#: notify_on_cmd_finish invisible 10.0 command notify-send "job finished with status: %s" %c +#: # Do not clear previous notification when next command finishes or window regains focus +#: notify_on_cmd_finish invisible 5.0 notify + +# term xterm-kitty + +#: The value of the TERM environment variable to set. Changing this +#: can break many terminal programs, only change it if you know what +#: you are doing, not because you read some advice on "Stack Overflow" +#: to change it. The TERM variable is used by various programs to get +#: information about the capabilities and behavior of the terminal. If +#: you change it, depending on what programs you run, and how +#: different the terminal you are changing it to is, various things +#: from key-presses, to colors, to various advanced features may not +#: work. Changing this option by reloading the config will only affect +#: newly created windows. + +# terminfo_type path + +#: The value of the TERMINFO environment variable to set. This +#: variable is used by programs running in the terminal to search for +#: terminfo databases. The default value of path causes kitty to set +#: it to a filesystem location containing the kitty terminfo database. +#: A value of direct means put the entire database into the env var +#: directly. This can be useful when connecting to containers, for +#: example. But, note that not all software supports this. A value of +#: none means do not touch the variable. + +# forward_stdio no + +#: Forward STDOUT and STDERR of the kitty process to child processes. +#: This is useful for debugging as it allows child processes to print +#: to kitty's STDOUT directly. For example, echo hello world +#: >&$KITTY_STDIO_FORWARDED in a shell will print to the parent +#: kitty's STDOUT. Sets the KITTY_STDIO_FORWARDED=fdnum environment +#: variable so child processes know about the forwarding. Note that on +#: macOS this prevents the shell from being run via the login utility +#: so getlogin() will not work in programs run in this session. + +# menu_map + +#: Specify entries for various menus in kitty. Currently only the +#: global menubar on macOS is supported. For example:: + +#: menu_map global "Actions::Launch something special" launch --hold --type=os-window sh -c "echo hello world" + +#: This will create a menu entry named "Launch something special" in +#: an "Actions" menu in the macOS global menubar. Sub-menus can be +#: created by adding more levels separated by the :: characters. + +#: }}} + + +#: OS specific tweaks {{{ + +# wayland_titlebar_color system + +#: The color of the kitty window's titlebar on Wayland systems with +#: client side window decorations such as GNOME. A value of system +#: means to use the default system colors, a value of background means +#: to use the background color of the currently active kitty window +#: and finally you can use an arbitrary color, such as #12af59 or red. + +# macos_titlebar_color system + +#: The color of the kitty window's titlebar on macOS. A value of +#: system means to use the default system color, light or dark can +#: also be used to set it explicitly. A value of background means to +#: use the background color of the currently active window and finally +#: you can use an arbitrary color, such as #12af59 or red. + +# macos_option_as_alt no + +#: Use the Option key as an Alt key on macOS. With this set to no, +#: kitty will use the macOS native Option+Key to enter Unicode +#: character behavior. This will break any Alt+Key keyboard shortcuts +#: in your terminal programs, but you can use the macOS Unicode input +#: technique. You can use the values: left, right or both to use only +#: the left, right or both Option keys as Alt, instead. Note that +#: kitty itself always treats Option the same as Alt. This means you +#: cannot use this option to configure different kitty shortcuts for +#: Option+Key vs. Alt+Key. Also, any kitty shortcuts using +#: Option/Alt+Key will take priority, so that any such key presses +#: will not be passed to terminal programs running inside kitty. +#: Changing this option by reloading the config is not supported. + +# macos_hide_from_tasks no + +#: Hide the kitty window from running tasks on macOS (⌘+Tab and the +#: Dock). Changing this option by reloading the config is not +#: supported. + +# macos_quit_when_last_window_closed no + +#: Have kitty quit when all the top-level windows are closed on macOS. +#: By default, kitty will stay running, even with no open windows, as +#: is the expected behavior on macOS. + +# macos_window_resizable yes + +#: Disable this if you want kitty top-level OS windows to not be +#: resizable on macOS. + +# macos_thicken_font 0 + +#: Draw an extra border around the font with the given width, to +#: increase legibility at small font sizes on macOS. For example, a +#: value of 0.75 will result in rendering that looks similar to sub- +#: pixel antialiasing at common font sizes. Note that in modern kitty, +#: this option is obsolete (although still supported). Consider using +#: text_composition_strategy instead. + +# macos_traditional_fullscreen no + +#: Use the macOS traditional full-screen transition, that is faster, +#: but less pretty. + +# macos_show_window_title_in all + +#: Control where the window title is displayed on macOS. A value of +#: window will show the title of the currently active window at the +#: top of the macOS window. A value of menubar will show the title of +#: the currently active window in the macOS global menu bar, making +#: use of otherwise wasted space. A value of all will show the title +#: in both places, and none hides the title. See +#: macos_menubar_title_max_length for how to control the length of the +#: title in the menu bar. + +# macos_menubar_title_max_length 0 + +#: The maximum number of characters from the window title to show in +#: the macOS global menu bar. Values less than one means that there is +#: no maximum limit. + +# macos_custom_beam_cursor no + +#: Use a custom mouse cursor for macOS that is easier to see on both +#: light and dark backgrounds. Nowadays, the default macOS cursor +#: already comes with a white border. WARNING: this might make your +#: mouse cursor invisible on dual GPU machines. Changing this option +#: by reloading the config is not supported. + +# macos_colorspace srgb + +#: The colorspace in which to interpret terminal colors. The default +#: of srgb will cause colors to match those seen in web browsers. The +#: value of default will use whatever the native colorspace of the +#: display is. The value of displayp3 will use Apple's special +#: snowflake display P3 color space, which will result in over +#: saturated (brighter) colors with some color shift. Reloading +#: configuration will change this value only for newly created OS +#: windows. + +# linux_display_server auto + +#: Choose between Wayland and X11 backends. By default, an appropriate +#: backend based on the system state is chosen automatically. Set it +#: to x11 or wayland to force the choice. Changing this option by +#: reloading the config is not supported. + +# wayland_enable_ime yes + +#: Enable Input Method Extension on Wayland. This is typically used +#: for inputting text in East Asian languages. However, its +#: implementation in Wayland is often buggy and introduces latency +#: into the input loop, so disable this if you know you dont need it. +#: Changing this option by reloading the config is not supported, it +#: will not have any effect. + +#: }}} + + + +#: Keyboard shortcuts {{{ + +#: Keys are identified simply by their lowercase Unicode characters. +#: For example: a for the A key, [ for the left square bracket key, +#: etc. For functional keys, such as Enter or Escape, the names are +#: present at Functional key definitions +#: . +#: For modifier keys, the names are ctrl (control, ⌃), shift (⇧), alt +#: (opt, option, ⌥), super (cmd, command, ⌘). + +#: Simple shortcut mapping is done with the map directive. For full +#: details on advanced mapping including modal and per application +#: maps, see mapping . Some +#: quick examples to illustrate common tasks:: + +#: # unmap a keyboard shortcut, passing it to the program running in kitty +#: map kitty_mod+space +#: # completely ignore a keyboard event +#: map ctrl+alt+f1 discard_event +#: # combine multiple actions +#: map kitty_mod+e combine : new_window : next_layout +#: # multi-key shortcuts +#: map ctrl+x>ctrl+y>z action + +#: The full list of actions that can be mapped to key presses is +#: available here . + +# kitty_mod ctrl+shift + +#: Special modifier key alias for default shortcuts. You can change +#: the value of this option to alter all default shortcuts that use +#: kitty_mod. + +# clear_all_shortcuts no + +#: Remove all shortcut definitions up to this point. Useful, for +#: instance, to remove the default shortcuts. + +# action_alias + +#: E.g. action_alias launch_tab launch --type=tab --cwd=current + +#: Define action aliases to avoid repeating the same options in +#: multiple mappings. Aliases can be defined for any action and will +#: be expanded recursively. For example, the above alias allows you to +#: create mappings to launch a new tab in the current working +#: directory without duplication:: + +#: map f1 launch_tab vim +#: map f2 launch_tab emacs + +#: Similarly, to alias kitten invocation:: + +#: action_alias hints kitten hints --hints-offset=0 + +# kitten_alias + +#: E.g. kitten_alias hints hints --hints-offset=0 + +#: Like action_alias above, but specifically for kittens. Generally, +#: prefer to use action_alias. This option is a legacy version, +#: present for backwards compatibility. It causes all invocations of +#: the aliased kitten to be substituted. So the example above will +#: cause all invocations of the hints kitten to have the --hints- +#: offset=0 option applied. + +#: Clipboard {{{ + +#: Copy to clipboard + +# map kitty_mod+c copy_to_clipboard + +#:: There is also a copy_or_interrupt action that can be optionally +#:: mapped to Ctrl+C. It will copy only if there is a selection and +#:: send an interrupt otherwise. Similarly, +#:: copy_and_clear_or_interrupt will copy and clear the selection or +#:: send an interrupt if there is no selection. The copy_or_noop +#:: action will copy if there is a selection and pass the key through +#:: to the application running in the terminal if there is no +#:: selection. + +#: Copy to clipboard or pass through + +# map cmd+c copy_or_noop + +#: Paste from clipboard + +# map kitty_mod+v paste_from_clipboard +# map cmd+v paste_from_clipboard + +#: Paste from selection + +# map kitty_mod+s paste_from_selection +# map shift+insert paste_from_selection + +#: Pass selection to program + +# map kitty_mod+o pass_selection_to_program + +#:: You can also pass the contents of the current selection to any +#:: program with pass_selection_to_program. By default, the system's +#:: open program is used, but you can specify your own, the selection +#:: will be passed as a command line argument to the program. For +#:: example:: + +#:: map kitty_mod+o pass_selection_to_program firefox + +#:: You can pass the current selection to a terminal program running +#:: in a new kitty window, by using the @selection placeholder:: + +#:: map kitty_mod+y new_window less @selection + +#: }}} + +#: Scrolling {{{ + +#: Scroll line up + +# map kitty_mod+up scroll_line_up +# map kitty_mod+k scroll_line_up +# map opt+cmd+page_up scroll_line_up +# map cmd+up scroll_line_up + +#: Scroll line down + +# map kitty_mod+down scroll_line_down +# map kitty_mod+j scroll_line_down +# map opt+cmd+page_down scroll_line_down +# map cmd+down scroll_line_down + +#: Scroll page up + +# map kitty_mod+page_up scroll_page_up +# map cmd+page_up scroll_page_up + +#: Scroll page down + +# map kitty_mod+page_down scroll_page_down +# map cmd+page_down scroll_page_down + +#: Scroll to top + +# map kitty_mod+home scroll_home +# map cmd+home scroll_home + +#: Scroll to bottom + +# map kitty_mod+end scroll_end +# map cmd+end scroll_end + +#: Scroll to previous shell prompt + +# map kitty_mod+z scroll_to_prompt -1 + +#:: Use a parameter of 0 for scroll_to_prompt to scroll to the last +#:: jumped to or the last clicked position. Requires shell +#:: integration +#:: to work. + +#: Scroll to next shell prompt + +# map kitty_mod+x scroll_to_prompt 1 + +#: Browse scrollback buffer in pager + +# map kitty_mod+h show_scrollback + +#:: You can pipe the contents of the current screen and history +#:: buffer as STDIN to an arbitrary program using launch --stdin- +#:: source. For example, the following opens the scrollback buffer in +#:: less in an overlay window:: + +#:: map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay less +G -R + +#:: For more details on piping screen and buffer contents to external +#:: programs, see launch . + +#: Browse output of the last shell command in pager + +# map kitty_mod+g show_last_command_output + +#:: You can also define additional shortcuts to get the command +#:: output. For example, to get the first command output on screen:: + +#:: map f1 show_first_command_output_on_screen + +#:: To get the command output that was last accessed by a keyboard +#:: action or mouse action:: + +#:: map f1 show_last_visited_command_output + +#:: You can pipe the output of the last command run in the shell +#:: using the launch action. For example, the following opens the +#:: output in less in an overlay window:: + +#:: map f1 launch --stdin-source=@last_cmd_output --stdin-add-formatting --type=overlay less +G -R + +#:: To get the output of the first command on the screen, use +#:: @first_cmd_output_on_screen. To get the output of the last jumped +#:: to command, use @last_visited_cmd_output. + +#:: Requires shell integration +#:: to work. + +#: Search the scrollback within a pager + +# map kitty_mod+/ search_scrollback +# map cmd+f search_scrollback + +#:: Search for currently selected text in the scrollback using the +#:: configured scrollback_pager. Assumes that pressing the / key +#:: triggers search mode in the pager. If you want to create a manual +#:: mapping with a special pager for this, you can use something +#:: like: + +#:: map f1 combine : launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay mypager : send_key / + +#:: For more sophisticated control, such as using the current +#:: selection, use remote_control_script. + +#: }}} + +#: Window management {{{ + +#: New window + +# map kitty_mod+enter new_window +# map cmd+enter new_window + +#:: You can open a new kitty window running an arbitrary program, for +#:: example:: + +#:: map kitty_mod+y launch mutt + +#:: You can open a new window with the current working directory set +#:: to the working directory of the current window using:: + +#:: map ctrl+alt+enter launch --cwd=current + +#:: You can open a new window that is allowed to control kitty via +#:: the kitty remote control facility with launch --allow-remote- +#:: control. Any programs running in that window will be allowed to +#:: control kitty. For example:: + +#:: map ctrl+enter launch --allow-remote-control some_program + +#:: You can open a new window next to the currently active window or +#:: as the first window, with:: + +#:: map ctrl+n launch --location=neighbor +#:: map ctrl+f launch --location=first + +#:: For more details, see launch +#:: . + +#: New OS window + +# map kitty_mod+n new_os_window +# map cmd+n new_os_window + +#:: Works like new_window above, except that it opens a top-level OS +#:: window. In particular you can use new_os_window_with_cwd to open +#:: a window with the current working directory. + +#: Close window + +# map kitty_mod+w close_window +# map shift+cmd+d close_window + +#: Next window + +# map kitty_mod+] next_window + +#: Previous window + +# map kitty_mod+[ previous_window + +#: Move window forward + +# map kitty_mod+f move_window_forward + +#: Move window backward + +# map kitty_mod+b move_window_backward + +#: Move window to top + +# map kitty_mod+` move_window_to_top + +#: Start resizing window + +# map kitty_mod+r start_resizing_window +# map cmd+r start_resizing_window + +#: First window + +# map kitty_mod+1 first_window +# map cmd+1 first_window + +#: Second window + +# map kitty_mod+2 second_window +# map cmd+2 second_window + +#: Third window + +# map kitty_mod+3 third_window +# map cmd+3 third_window + +#: Fourth window + +# map kitty_mod+4 fourth_window +# map cmd+4 fourth_window + +#: Fifth window + +# map kitty_mod+5 fifth_window +# map cmd+5 fifth_window + +#: Sixth window + +# map kitty_mod+6 sixth_window +# map cmd+6 sixth_window + +#: Seventh window + +# map kitty_mod+7 seventh_window +# map cmd+7 seventh_window + +#: Eighth window + +# map kitty_mod+8 eighth_window +# map cmd+8 eighth_window + +#: Ninth window + +# map kitty_mod+9 ninth_window +# map cmd+9 ninth_window + +#: Tenth window + +# map kitty_mod+0 tenth_window + +#: Visually select and focus window + +# map kitty_mod+f7 focus_visible_window + +#:: Display overlay numbers and alphabets on the window, and switch +#:: the focus to the window when you press the key. When there are +#:: only two windows, the focus will be switched directly without +#:: displaying the overlay. You can change the overlay characters and +#:: their order with option visual_window_select_characters. + +#: Visually swap window with another + +# map kitty_mod+f8 swap_with_window + +#:: Works like focus_visible_window above, but swaps the window. + +#: }}} + +#: Tab management {{{ + +#: Next tab + +# map kitty_mod+right next_tab +# map shift+cmd+] next_tab +# map ctrl+tab next_tab + +#: Previous tab + +# map kitty_mod+left previous_tab +# map shift+cmd+[ previous_tab +# map ctrl+shift+tab previous_tab + +#: New tab + +# map kitty_mod+t new_tab +# map cmd+t new_tab + +#: Close tab + +# map kitty_mod+q close_tab +# map cmd+w close_tab + +#: Close OS window + +# map shift+cmd+w close_os_window + +#: Move tab forward + +# map kitty_mod+. move_tab_forward + +#: Move tab backward + +# map kitty_mod+, move_tab_backward + +#: Set tab title + +# map kitty_mod+alt+t set_tab_title +# map shift+cmd+i set_tab_title + + +#: You can also create shortcuts to go to specific tabs, with 1 being +#: the first tab, 2 the second tab and -1 being the previously active +#: tab, -2 being the tab active before the previously active tab and +#: so on. Any number larger than the number of tabs goes to the last +#: tab and any number less than the number of previously used tabs in +#: the history goes to the oldest previously used tab in the history:: + +#: map ctrl+alt+1 goto_tab 1 +#: map ctrl+alt+2 goto_tab 2 + +#: Just as with new_window above, you can also pass the name of +#: arbitrary commands to run when using new_tab and new_tab_with_cwd. +#: Finally, if you want the new tab to open next to the current tab +#: rather than at the end of the tabs list, use:: + +#: map ctrl+t new_tab !neighbor [optional cmd to run] +#: }}} + +#: Layout management {{{ + +#: Next layout + +# map kitty_mod+l next_layout + + +#: You can also create shortcuts to switch to specific layouts:: + +#: map ctrl+alt+t goto_layout tall +#: map ctrl+alt+s goto_layout stack + +#: Similarly, to switch back to the previous layout:: + +#: map ctrl+alt+p last_used_layout + +#: There is also a toggle_layout action that switches to the named +#: layout or back to the previous layout if in the named layout. +#: Useful to temporarily "zoom" the active window by switching to the +#: stack layout:: + +#: map ctrl+alt+z toggle_layout stack +#: }}} + +#: Font sizes {{{ + +#: You can change the font size for all top-level kitty OS windows at +#: a time or only the current one. + +#: Increase font size + +# map kitty_mod+equal change_font_size all +2.0 +# map kitty_mod+plus change_font_size all +2.0 +# map kitty_mod+kp_add change_font_size all +2.0 +# map cmd+plus change_font_size all +2.0 +# map cmd+equal change_font_size all +2.0 +# map shift+cmd+equal change_font_size all +2.0 + +#: Decrease font size + +# map kitty_mod+minus change_font_size all -2.0 +# map kitty_mod+kp_subtract change_font_size all -2.0 +# map cmd+minus change_font_size all -2.0 +# map shift+cmd+minus change_font_size all -2.0 + +#: Reset font size + +# map kitty_mod+backspace change_font_size all 0 +# map cmd+0 change_font_size all 0 + + +#: To setup shortcuts for specific font sizes:: + +#: map kitty_mod+f6 change_font_size all 10.0 + +#: To setup shortcuts to change only the current OS window's font +#: size:: + +#: map kitty_mod+f6 change_font_size current 10.0 + +#: To setup shortcuts to multiply/divide the font size:: + +#: map kitty_mod+f6 change_font_size all *2.0 +#: map kitty_mod+f6 change_font_size all /2.0 +#: }}} + +#: Select and act on visible text {{{ + +#: Use the hints kitten to select text and either pass it to an +#: external program or insert it into the terminal or copy it to the +#: clipboard. + +#: Open URL + +# map kitty_mod+e open_url_with_hints + +#:: Open a currently visible URL using the keyboard. The program used +#:: to open the URL is specified in open_url_with. + +#: Insert selected path + +# map kitty_mod+p>f kitten hints --type path --program - + +#:: Select a path/filename and insert it into the terminal. Useful, +#:: for instance to run git commands on a filename output from a +#:: previous git command. + +#: Open selected path + +# map kitty_mod+p>shift+f kitten hints --type path + +#:: Select a path/filename and open it with the default open program. + +#: Insert chosen file + +# map kitty_mod+p>c kitten choose-files + +#:: Select a file using the choose-files +#:: kitten +#:: and insert it into the terminal. + +#: Insert chosen directory + +# map kitty_mod+p>d kitten choose-files --mode=dir + +#:: Select a directory using the choose-files +#:: kitten +#:: and insert it into the terminal. + +#: Insert selected line + +# map kitty_mod+p>l kitten hints --type line --program - + +#:: Select a line of text and insert it into the terminal. Useful for +#:: the output of things like: `ls -1`. + +#: Insert selected word + +# map kitty_mod+p>w kitten hints --type word --program - + +#:: Select words and insert into terminal. + +#: Insert selected hash + +# map kitty_mod+p>h kitten hints --type hash --program - + +#:: Select something that looks like a hash and insert it into the +#:: terminal. Useful with git, which uses SHA1 hashes to identify +#:: commits. + +#: Open the selected file at the selected line + +# map kitty_mod+p>n kitten hints --type linenum + +#:: Select something that looks like filename:linenum and open it in +#:: your default editor at the specified line number. + +#: Open the selected hyperlink + +# map kitty_mod+p>y kitten hints --type hyperlink + +#:: Select a hyperlink (i.e. a URL that has been marked as such by +#:: the terminal program, for example, by `ls --hyperlink=auto`). + + +#: The hints kitten has many more modes of operation that you can map +#: to different shortcuts. For a full description see hints kitten +#: . + +#: }}} + +#: Miscellaneous {{{ + +#: Show documentation + +# map kitty_mod+f1 show_kitty_doc overview + +#: Toggle fullscreen + +# map kitty_mod+f11 toggle_fullscreen +# map ctrl+cmd+f toggle_fullscreen + +#: Toggle maximized + +# map kitty_mod+f10 toggle_maximized + +#: Toggle macOS secure keyboard entry + +# map opt+cmd+s toggle_macos_secure_keyboard_entry + +#: macOS Cycle through OS Windows + +# map cmd+` macos_cycle_through_os_windows + +#: macOS Cycle through OS Windows backwards + +# map cmd+shift+` macos_cycle_through_os_windows_backwards + +#: Unicode input + +# map kitty_mod+u kitten unicode_input +# map ctrl+cmd+space kitten unicode_input + +#: Edit config file + +# map kitty_mod+f2 edit_config_file +# map cmd+, edit_config_file + +#: Open the kitty command shell + +# map kitty_mod+escape kitty_shell window + +#:: Open the kitty shell in a new window / tab / overlay / os_window +#:: to control kitty using commands. + +Increase background opacity = 0.8 + +# map kitty_mod+a>m set_background_opacity +0.1 + +#: Decrease background opacity + +# map kitty_mod+a>l set_background_opacity -0.1 + +#: Make background fully opaque + +# map kitty_mod+a>1 set_background_opacity 1 + +#: Reset background opacity + +# map kitty_mod+a>d set_background_opacity default + +#: Reset the terminal + +# map kitty_mod+delete clear_terminal reset active +# map opt+cmd+r clear_terminal reset active + +#:: You can create shortcuts to clear/reset the terminal. For +#:: example:: + +#:: # Reset the terminal +#:: map f1 clear_terminal reset active +#:: # Clear the terminal screen by erasing all contents +#:: map f1 clear_terminal clear active +#:: # Clear the terminal scrollback by erasing it +#:: map f1 clear_terminal scrollback active +#:: # Scroll the contents of the screen into the scrollback +#:: map f1 clear_terminal scroll active +#:: # Clear everything on screen up to the line with the cursor or the start of the current prompt (needs shell integration) +#:: map f1 clear_terminal to_cursor active +#:: # Same as above except cleared lines are moved into scrollback +#:: map f1 clear_terminal to_cursor_scroll active +#:: # Erase the last command and its output (needs shell integration to work) +#:: map f1 clear_terminal last_command active + +#:: If you want to operate on all kitty windows instead of just the +#:: current one, use all instead of active. + +#:: Some useful functions that can be defined in the shell rc files +#:: to perform various kinds of clearing of the current window: + +#:: .. code-block:: sh + +#:: clear-only-screen() { +#:: printf "\e[H\e[2J" +#:: } + +#:: clear-screen-and-scrollback() { +#:: printf "\e[H\e[3J" +#:: } + +#:: clear-screen-saving-contents-in-scrollback() { +#:: printf "\e[H\e[22J" +#:: } + +#:: For instance, using these escape codes, it is possible to remap +#:: Ctrl+L to both scroll the current screen contents into the +#:: scrollback buffer and clear the screen, instead of just clearing +#:: the screen. For ZSH, in ~/.zshrc, add: + +#:: .. code-block:: zsh + +#:: ctrl_l() { +#:: builtin print -rn -- $'\r\e[0J\e[H\e[22J' >"$TTY" +#:: builtin zle .reset-prompt +#:: builtin zle -R +#:: } +#:: zle -N ctrl_l +#:: bindkey '^l' ctrl_l + +#:: Alternatively, you can just add map ctrl+l clear_terminal +#:: to_cursor_scroll active to kitty.conf which works with no changes +#:: to the shell rc files, but only clears up to the prompt, it does +#:: not clear any text at the prompt itself. + +#: Clear to start + +# map cmd+k clear_terminal to_cursor active + +#: Clear scrollback + +# map option+cmd+k clear_terminal scrollback active + +#: Clear the last command + +# map cmd+l clear_terminal last_command active + +#: Clear screen + +# map cmd+ctrl+l clear_terminal to_cursor_scroll active + +#: Reload kitty.conf + +# map kitty_mod+f5 load_config_file +# map ctrl+cmd+, load_config_file + +#:: Reload kitty.conf, applying any changes since the last time it +#:: was loaded. Note that a handful of options cannot be dynamically +#:: changed and require a full restart of kitty. Particularly, when +#:: changing shortcuts for actions located on the macOS global menu +#:: bar, a full restart is needed. You can also map a keybinding to +#:: load a different config file, for example:: + +#:: map f5 load_config /path/to/alternative/kitty.conf + +#:: Note that all options from the original kitty.conf are discarded, +#:: in other words the new configuration *replace* the old ones. + +#: Debug kitty configuration + +# map kitty_mod+f6 debug_config +# map opt+cmd+, debug_config + +#:: Show details about exactly what configuration kitty is running +#:: with and its host environment. Useful for debugging issues. + +#: Send arbitrary text on key presses + +#:: E.g. map ctrl+shift+alt+h send_text all Hello World + +#:: You can tell kitty to send arbitrary (UTF-8) encoded text to the +#:: client program when pressing specified shortcut keys. For +#:: example:: + +#:: map ctrl+alt+a send_text all Special text + +#:: This will send "Special text" when you press the Ctrl+Alt+A key +#:: combination. The text to be sent decodes ANSI C escapes +#:: so you can use escapes like \e to send control +#:: codes or \u21fb to send Unicode characters (or you can just input +#:: the Unicode characters directly as UTF-8 text). You can use +#:: `kitten show-key` to get the key escape codes you want to +#:: emulate. + +#:: The first argument to send_text is the keyboard modes in which to +#:: activate the shortcut. The possible values are normal, +#:: application, kitty or a comma separated combination of them. The +#:: modes normal and application refer to the DECCKM cursor key mode +#:: for terminals, and kitty refers to the kitty extended keyboard +#:: protocol. The special value all means all of them. + +#:: Some more examples:: + +#:: # Output a word and move the cursor to the start of the line (like typing and pressing Home) +#:: map ctrl+alt+a send_text normal Word\e[H +#:: map ctrl+alt+a send_text application Word\eOH +#:: # Run a command at a shell prompt (like typing the command and pressing Enter) +#:: map ctrl+alt+a send_text normal,application some command with arguments\r + +#: Open kitty Website + +# map shift+cmd+/ open_url https://sw.kovidgoyal.net/kitty/ + +#: Hide macOS kitty application + +# map cmd+h hide_macos_app + +#: Hide macOS other applications + +# map opt+cmd+h hide_macos_other_apps + +#: Minimize macOS window + +# map cmd+m minimize_macos_window + +#: Quit kitty + +# map cmd+q quit + +#: }}} + +#: }}} + + +shell_integration no-cursor + +# BEGIN_KITTY_FONTS +font_family family="JetBrainsMono Nerd Font" +bold_font auto +italic_font auto +bold_italic_font auto +# END_KITTY_FONTS + + +# BEGIN_KITTY_THEME +# Noctalia +include current-theme.conf +# END_KITTY_THEME +# +# include colors.conf diff --git a/matugen/config.toml b/matugen/config.toml new file mode 100644 index 0000000..a84ed34 --- /dev/null +++ b/matugen/config.toml @@ -0,0 +1,45 @@ +[config.wallpaper] +command = "awww" +arguments = ["img", "--transition-type", "any", "--transition-fps", "60"] +set = true + +[templates.waybar] +input_path = '~/.config/matugen/templates/colors.css' +output_path = '~/.config/waybar/colors.css' +post_hook = 'pkill -SIGUSR2 waybar' + +[templates.kitty] +input_path = '~/.config/matugen/templates/kitty-colors.conf' +output_path = '~/.config/kitty/colors.conf' +post_hook = "kill -SIGUSR1 $(pidof kitty)" + +[templates.hyprland] +input_path = '~/.config/matugen/templates/hyprland-colors.conf' +output_path = '~/.config/hypr/colors.conf' +post_hook = 'hyprctl reload' + +[templates.gtk3] +input_path = '~/.config/matugen/templates/gtk-colors.css' +output_path = '~/.config/gtk-3.0/colors.css' + +[templates.gtk4] +input_path = '~/.config/matugen/templates/gtk-colors.css' +output_path = '~/.config/gtk-4.0/colors.css' + +[templates.rofi] +input_path = '~/.config/matugen/templates/rofi-colors.rasi' +output_path = '~/.config/rofi/colors.rasi' + +[templates.cava] +input_path = '~/.config/matugen/templates/matugen-cava' +output_path = '~/.config/cava/config' +post_hook = "pkill -USR1 cava" + +[templates.spicetify] +input_path = '~/.config/matugen/templates/spotify-colors.ini' +output_path = '~/.config/spicetify/Themes/text/color.ini' + +[templates.vesktop] +input_path = '~/.config/matugen/templates/midnight-discord.css' +output_path = '~/.config/vesktop/themes/matugen.css' + diff --git a/matugen/templates/colors.css b/matugen/templates/colors.css new file mode 100644 index 0000000..f246856 --- /dev/null +++ b/matugen/templates/colors.css @@ -0,0 +1,7 @@ +/* +* Css Colors +* Generated with Matugen +*/ +<* for name, value in colors *> + @define-color {{name}} {{value.default.hex}}; +<* endfor *> diff --git a/matugen/templates/gtk-colors.css b/matugen/templates/gtk-colors.css new file mode 100644 index 0000000..64abe77 --- /dev/null +++ b/matugen/templates/gtk-colors.css @@ -0,0 +1,23 @@ +/* +* GTK Colors +* Generated with Matugen +*/ + +@define-color accent_color {{colors.primary_fixed_dim.default.hex}}; +@define-color accent_fg_color {{colors.on_primary_fixed.default.hex}}; +@define-color accent_bg_color {{colors.primary_fixed_dim.default.hex}}; +@define-color window_bg_color {{colors.surface_dim.default.hex}}; +@define-color window_fg_color {{colors.on_surface.default.hex}}; +@define-color headerbar_bg_color {{colors.surface_dim.default.hex}}; +@define-color headerbar_fg_color {{colors.on_surface.default.hex}}; +@define-color popover_bg_color {{colors.surface_dim.default.hex}}; +@define-color popover_fg_color {{colors.on_surface.default.hex}}; +@define-color view_bg_color {{colors.surface.default.hex}}; +@define-color view_fg_color {{colors.on_surface.default.hex}}; +@define-color card_bg_color {{colors.surface.default.hex}}; +@define-color card_fg_color {{colors.on_surface.default.hex}}; +@define-color sidebar_bg_color @window_bg_color; +@define-color sidebar_fg_color @window_fg_color; +@define-color sidebar_border_color @window_bg_color; +@define-color sidebar_backdrop_color @window_bg_color; + diff --git a/matugen/templates/hyprland-colors.conf b/matugen/templates/hyprland-colors.conf new file mode 100644 index 0000000..d7e6821 --- /dev/null +++ b/matugen/templates/hyprland-colors.conf @@ -0,0 +1,4 @@ +<* for name, value in colors *> +$image = {{image}} +${{name}} = rgba({{value.default.hex_stripped}}ff) +<* endfor *> diff --git a/matugen/templates/kitty-colors.conf b/matugen/templates/kitty-colors.conf new file mode 100644 index 0000000..29806f8 --- /dev/null +++ b/matugen/templates/kitty-colors.conf @@ -0,0 +1,27 @@ +# Core Colors +background {{ colors.background.default.hex }} +foreground {{ colors.on_surface.default.hex }} +selection_foreground {{ colors.primary.default.hex }} +selection_background {{ colors.on_primary.default.hex }} +cursor {{ colors.primary.default.hex }} +cursor_text_color {{ colors.surface.default.hex }} + +# Regular Colors +color0 {{ colors.surface.default.hex }} +color1 {{ colors.error.default.hex }} +color2 {{ colors.primary.default.hex }} +color3 {{ colors.tertiary.default.hex }} +color4 {{ colors.on_primary_container.default.hex }} +color5 {{ colors.on_secondary_container.default.hex }} +color6 {{ colors.secondary.default.hex }} +color7 {{ colors.on_surface.default.hex }} + +# Bright Colors +color8 {{ colors.surface_bright.default.hex }} +color9 {{ colors.error.default.hex }} +color10 {{ colors.primary.default.hex }} +color11 {{ colors.tertiary.default.hex }} +color12 {{ colors.on_primary_container.default.hex }} +color13 {{ colors.on_secondary_container.default.hex }} +color14 {{ colors.secondary.default.hex }} +color15 {{ colors.on_surface.default.hex }} diff --git a/matugen/templates/matugen-cava b/matugen/templates/matugen-cava new file mode 100644 index 0000000..dc134ca --- /dev/null +++ b/matugen/templates/matugen-cava @@ -0,0 +1,291 @@ +# ┳┳┓┏┓┏┳┓┳┳┏┓┏┓┳┓ ┏┓┏┓┓┏┏┓ +# ┃┃┃┣┫ ┃ ┃┃┃┓┣ ┃┃━━┃ ┣┫┃┃┣┫ +# ┛ ┗┛┗ ┻ ┗┛┗┛┗┛┛┗ ┗┛┛┗┗┛┛┗ +# + + + + + +## Configuration file for CAVA. +# Remove the ; to change parameters. + +[general] + +# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0 +; mode = normal + +# Accepts only non-negative values. +; framerate = 60 + +# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off +# new as of 0.6.0 autosens of low values (dynamic range) +# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0 +; autosens = 1 +; overshoot = 20 + +# Manual sensitivity in %. If autosens is enabled, this will only be the initial value. +# 200 means double height. Accepts only non-negative values. +; sensitivity = 100 + +# The number of bars (0-512). 0 sets it to auto (fill up console). +# Bars' width and space between bars in number of characters. +; bars = 0 +; bar_width = 2 +; bar_spacing = 1 +# bar_height is only used for output in "noritake" format +; bar_height = 32 + +# For SDL width and space between bars is in pixels, defaults are: +; bar_width = 20 +; bar_spacing = 5 + +# sdl_glsl have these default values, they are only used to calulate max number of bars. +; bar_width = 1 +; bar_spacing = 0 + + +# Lower and higher cutoff frequencies for lowest and highest bars +# the bandwidth of the visualizer. +# Note: there is a minimum total bandwidth of 43Mhz x number of bars. +# Cava will automatically increase the higher cutoff if a too low band is specified. +; lower_cutoff_freq = 50 +; higher_cutoff_freq = 10000 + + +# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and +# only check for input once per second. Cava will wake up once input is detected. 0 = disable. +; sleep_timer = 0 + + +[input] + +# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss', 'jack' or 'shmem' +# Defaults to 'oss', 'pipewire', 'sndio', 'jack', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with. +# On Mac it defaults to 'portaudio' or 'fifo' +# On windows this is automatic and no input settings are needed. +# +# All input methods uses the same config variable 'source' +# to define where it should get the audio. +# +# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink +# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them). +# +# For pipewire 'source' will be the object name or object.serial of the device to capture from. +# Both input and output devices are supported. +# +# For alsa 'source' will be the capture device. +# For fifo 'source' will be the path to fifo-file. +# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address +# +# For sndio 'source' will be a raw recording audio descriptor or a monitoring sub-device, e.g. 'rsnd/2' or 'snd/1'. Default: 'default'. +# README.md contains further information on how to setup CAVA for sndio. +# +# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device. +# README.md contains further information on how to setup CAVA for OSS on FreeBSD. +# +# For jack 'source' will be the name of the JACK server to connect to, e.g. 'foobar'. Default: 'default'. +# README.md contains further information on how to setup CAVA for JACK. +# + method = pulse + source = auto + + method = pipewire + source = auto + +; method = alsa +; source = hw:Loopback,1 + +; method = fifo +; source = /tmp/mpd.fifo + +; method = shmem +; source = /squeezelite-AA:BB:CC:DD:EE:FF + +; method = portaudio +; source = auto + +; method = sndio +; source = default + +; method = oss +; source = /dev/dsp + +; method = jack +; source = default + +# The options 'sample_rate', 'sample_bits', 'channels' and 'autoconnect' can be configured for some input methods: +# sample_rate: fifo, pipewire, sndio, oss +# sample_bits: fifo, pipewire, sndio, oss +# channels: sndio, oss, jack +# autoconnect: jack +# Other methods ignore these settings. +# +# For 'sndio' and 'oss' they are only preferred values, i.e. if the values are not supported +# by the chosen audio device, the device will use other supported values instead. +# Example: 48000, 32 and 2, but the device only supports 44100, 16 and 1, then it +# will use 44100, 16 and 1. +# +; sample_rate = 44100 +; sample_bits = 16 +; channels = 2 +; autoconnect = 2 + + +[output] + +# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl' +# or 'sdl_glsl'. +# 'noncurses' (default) uses a buffer and cursor movements to only print +# changes from frame to frame in the terminal. Uses less resources and is less +# prone to tearing (vsync issues) than 'ncurses'. +# +# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data +# stream of the bar heights that can be used to send to other applications. +# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above. +# +# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display +# in graphic mode. It only support the 3000 series graphical VFDs for now. +# +# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context. +# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or +# use one of the predefined ones. +; method = noncurses + +# Orientation of the visualization. Can be 'bottom', 'top', 'left' or 'right'. +# Default is 'bottom'. Other orientations are only supported on sdl and ncruses +# output. Note: many fonts have weird glyphs for 'top' and 'right' characters, +# which can make ncurses not look right. +; orientation = bottom + +# Visual channels. Can be 'stereo' or 'mono'. +# 'stereo' mirrors both channels with low frequencies in center. +# 'mono' outputs left to right lowest to highest frequencies. +# 'mono_option' set mono to either take input from 'left', 'right' or 'average'. +# set 'reverse' to 1 to display frequencies the other way around. +; channels = stereo +; mono_option = average +; reverse = 0 + +# Raw output target. A fifo will be created if target does not exist. +; raw_target = /dev/stdout + +# Raw data format. Can be 'binary' or 'ascii'. +; data_format = binary + +# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530). +; bit_format = 16bit + +# Ascii max value. In 'ascii' mode range will run from 0 to value specified here +; ascii_max_range = 1000 + +# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters. +# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)). +; bar_delimiter = 59 +; frame_delimiter = 10 + +# sdl window size and position. -1,-1 is centered. +; sdl_width = 1000 +; sdl_height = 500 +; sdl_x = -1 +; sdl_y= -1 +; sdl_full_screen = 0 + +# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none' +# 'frequency' displays the lower cut off frequency of the bar above. +# Only supported on ncurses and noncurses output. +; xaxis = none + +# enable alacritty synchronized updates. 1 = on, 0 = off +# removes flickering in alacritty terminal emulator. +# defaults to off since the behaviour in other terminal emulators is unknown +; alacritty_sync = 0 + +# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders +; vertex_shader = pass_through.vert +; fragment_shader = bar_spectrum.frag + +; for glsl output mode, keep rendering even if no audio +; continuous_rendering = 0 + +# disable console blank (screen saver) in tty +# (Not supported on FreeBSD) +; disable_blanking = 0 + +# show a flat bar at the bottom of the screen when idle, 1 = on, 0 = off +; show_idle_bar_heads = 1 + +# show waveform instead of frequency spectrum, 1 = on, 0 = off +; waveform = 0 + +[color] + +# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow. +# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires +# a terminal that can change color definitions such as Gnome-terminal or rxvt. +# default is to keep current terminal color +; background = default +; foreground = default + +# SDL and sdl_glsl only support hex code colors, these are the default: +; background = '#111111' +; foreground = '#33ffff' + +# these are default +# Gradient mode, only hex defined colors are supported, +# background must also be defined in hex or remain commented out. 1 = on, 0 = off. +# You can define as many as 8 different colors. They range from bottom to top of screen +; gradient = 0 +; gradient_count = 8 +; gradient_color_1 = '#59cc33' +; gradient_color_2 = '#80cc33' +; gradient_color_3 = '#a6cc33' +; gradient_color_4 = '#cccc33' +; gradient_color_5 = '#cca633' +; gradient_color_6 = '#cc8033' +; gradient_color_7 = '#cc5933' +; gradient_color_8 = '#cc3333' + +# for matugen +gradient = 1 +gradient_count = 2 +gradient_color_1 = '{{colors.surface_bright.default.hex}}' +gradient_color_2 = '{{colors.primary.default.hex}}' + +[smoothing] + +# Percentage value for integral smoothing. Takes values from 0 - 100. +# Higher values means smoother, but less precise. 0 to disable. +# DEPRECATED as of 0.8.0, use noise_reduction instead +; integral = 77 + +# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable. +; monstercat = 0 +; waves = 0 + +# Set gravity percentage for "drop off". Higher values means bars will drop faster. +# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop off". +# DEPRECATED as of 0.8.0, use noise_reduction instead +; gravity = 100 + + +# In bar height, bars that would have been lower that this will not be drawn. +# DEPRECATED as of 0.8.0 +; ignore = 0 + +# Noise reduction, int 0 - 100. default 77 +# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth +# 100 will be very slow and smooth, 0 will be fast but noisy. +; noise_reduction = 77 + + +[eq] + +# This one is tricky. You can have as much keys as you want. +# Remember to uncomment more than one key! More keys = more precision. +# Look at readme.md on github for further explanations and examples. +; 1 = 1 # bass +; 2 = 1 +; 3 = 1 # midtone +; 4 = 1 +; 5 = 1 # treble diff --git a/matugen/templates/midnight-discord.css b/matugen/templates/midnight-discord.css new file mode 100644 index 0000000..90f744e --- /dev/null +++ b/matugen/templates/midnight-discord.css @@ -0,0 +1,99 @@ +/** + * @name midnight + * @description A dark, rounded discord theme. + * @author refact0r + * @version 1.6.2 + * @invite nz87hXyvcy + * @website https://github.com/refact0r/midnight-discord + * @source https://github.com/refact0r/midnight-discord/blob/master/midnight.theme.css + * @authorId 508863359777505290 + * @authorLink https://www.refact0r.dev +*/ + +/* IMPORTANT: make sure to enable dark mode in discord settings for the theme to apply properly!!! */ + +@import url('https://raw.githubusercontent.com/refact0r/midnight-discord/refs/heads/master/themes/midnight.theme.css'); + +/* customize things here */ +:root { + /* font, change to 'gg sans' for default discord font*/ + --font: 'figtree'; + + /* top left corner text */ + --corner-text: 'Midnight'; + + /* color of status indicators and window controls */ + --online-indicator: {{colors.inverse_primary.default.hex}}; /* change to #23a55a for default green */ + --dnd-indicator: {{colors.error.default.hex}}; /* change to #f13f43 for default red */ + --idle-indicator: {{colors.tertiary_container.default.hex}}; /* change to #f0b232 for default yellow */ + --streaming-indicator: {{colors.on_primary.default.hex}}; /* change to #593695 for default purple */ + + /* accent colors */ + --accent-1: {{colors.tertiary.default.hex}}; /* links */ + --accent-2: {{colors.primary.default.hex}}; /* general unread/mention elements, some icons when active */ + --accent-3: {{colors.primary.default.hex}}; /* accent buttons */ + --accent-4: {{colors.surface_bright.default.hex}}; /* accent buttons when hovered */ + --accent-5: {{colors.primary_fixed_dim.default.hex}}; /* accent buttons when clicked */ + --mention: {{colors.surface.default.hex}}; /* mentions & mention messages */ + --mention-hover: {{colors.surface_bright.default.hex}}; /* mentions & mention messages when hovered */ + + /* text colors */ + --text-0: {{colors.surface.default.hex}}; /* text on colored elements */ + --text-1: {{colors.on_surface.default.hex}}; /* other normally white text */ + --text-2: {{colors.on_surface.default.hex}}; /* headings and important text */ + --text-3: {{colors.on_surface_variant.default.hex}}; /* normal text */ + --text-4: {{colors.on_surface_variant.default.hex}}; /* icon buttons and channels */ + --text-5: {{colors.outline.default.hex}}; /* muted channels/chats and timestamps */ + + /* background and dark colors */ + --bg-1: {{colors.primary.default.hex}}; /* dark buttons when clicked */ + --bg-2: {{colors.surface_container_high.default.hex}}; /* dark buttons */ + --bg-3: {{colors.surface_container_low.default.hex}}; /* spacing, secondary elements */ + --bg-4: {{colors.surface.default.hex}}; /* main background color */ + --hover: {{colors.surface_bright.default.hex}}; /* channels and buttons when hovered */ + --active: {{colors.surface_bright.default.hex}}; /* channels and buttons when clicked or selected */ + --message-hover: {{colors.surface_bright.default.hex}}; /* messages when hovered */ + + /* amount of spacing and padding */ + --spacing: 12px; + + /* animations */ + /* ALL ANIMATIONS CAN BE DISABLED WITH REDUCED MOTION IN DISCORD SETTINGS */ + --list-item-transition: 0.2s ease; /* channels/members/settings hover transition */ + --unread-bar-transition: 0.2s ease; /* unread bar moving into view transition */ + --moon-spin-transition: 0.4s ease; /* moon icon spin */ + --icon-spin-transition: 1s ease; /* round icon button spin (settings, emoji, etc.) */ + + /* corner roundness (border-radius) */ + --roundness-xl: 22px; /* roundness of big panel outer corners */ + --roundness-l: 20px; /* popout panels */ + --roundness-m: 16px; /* smaller panels, images, embeds */ + --roundness-s: 12px; /* members, settings inputs */ + --roundness-xs: 10px; /* channels, buttons */ + --roundness-xxs: 8px; /* searchbar, small elements */ + + /* direct messages moon icon */ + /* change to block to show, none to hide */ + --discord-icon: none; /* discord icon */ + --moon-icon: block; /* moon icon */ + --moon-icon-url: url('https://upload.wikimedia.org/wikipedia/commons/c/c4/Font_Awesome_5_solid_moon.svg'); /* custom icon url */ + --moon-icon-size: auto; + + /* filter uncolorable elements to fit theme */ + /* (just set to none, they're too much work to configure) */ + --login-bg-filter: saturate(0.3) hue-rotate(-15deg) brightness(0.4); /* login background artwork */ + --green-to-accent-3-filter: hue-rotate(56deg) saturate(1.43); /* add friend page explore icon */ + --blurple-to-accent-3-filter: hue-rotate(304deg) saturate(0.84) brightness(1.2); /* add friend page school icon */ +} + +/* Selected chat/friend text */ +.selected_f5eb4b, +.selected_f6f816 .link_d8bfb3 { + color: var(--text-0) !important; + background: var(--accent-3) !important; +} + +.selected_f6f816 .link_d8bfb3 * { + color: var(--text-0) !important; + fill: var(--text-0) !important; +} diff --git a/matugen/templates/rofi-colors.rasi b/matugen/templates/rofi-colors.rasi new file mode 100644 index 0000000..e6506e2 --- /dev/null +++ b/matugen/templates/rofi-colors.rasi @@ -0,0 +1,47 @@ +* { + primary: {{colors.primary.default.hex}}; + primary-fixed: {{colors.primary_fixed.default.hex}}; + primary-fixed-dim: {{colors.primary_fixed_dim.default.hex}}; + on-primary: {{colors.on_primary.default.hex}}; + on-primary-fixed: {{colors.on_primary_fixed.default.hex}}; + on-primary-fixed-variant: {{colors.on_primary_fixed_variant.default.hex}}; + primary-container: {{colors.primary_container.default.hex}}; + on-primary-container: {{colors.on_primary_container.default.hex}}; + secondary: {{colors.secondary.default.hex}}; + secondary-fixed: {{colors.secondary_fixed.default.hex}}; + secondary-fixed-dim: {{colors.secondary_fixed_dim.default.hex}}; + on-secondary: {{colors.on_secondary.default.hex}}; + on-secondary-fixed: {{colors.on_secondary_fixed.default.hex}}; + on-secondary-fixed-variant: {{colors.on_secondary_fixed_variant.default.hex}}; + secondary-container: {{colors.secondary_container.default.hex}}; + on-secondary-container: {{colors.on_secondary_container.default.hex}}; + tertiary: {{colors.tertiary.default.hex}}; + tertiary-fixed: {{colors.tertiary_fixed.default.hex}}; + tertiary-fixed-dim: {{colors.tertiary_fixed_dim.default.hex}}; + on-tertiary: {{colors.on_tertiary.default.hex}}; + on-tertiary-fixed: {{colors.on_tertiary_fixed.default.hex}}; + on-tertiary-fixed-variant: {{colors.on_tertiary_fixed_variant.default.hex}}; + tertiary-container: {{colors.tertiary_container.default.hex}}; + on-tertiary-container: {{colors.on_tertiary_container.default.hex}}; + error: {{colors.error.default.hex}}; + on-error: {{colors.on_error.default.hex}}; + error-container: {{colors.error_container.default.hex}}; + on-error-container: {{colors.on_error_container.default.hex}}; + surface: {{colors.surface.default.hex}}; + on-surface: {{colors.on_surface.default.hex}}; + on-surface-variant: {{colors.on_surface_variant.default.hex}}; + outline: {{colors.outline.default.hex}}; + outline-variant: {{colors.outline_variant.default.hex}}; + shadow: {{colors.shadow.default.hex}}; + scrim: {{colors.scrim.default.hex}}; + inverse-surface: {{colors.inverse_surface.default.hex}}; + inverse-on-surface: {{colors.inverse_on_surface.default.hex}}; + inverse-primary: {{colors.inverse_primary.default.hex}}; + surface-dim: {{colors.surface_dim.default.hex}}; + surface-bright: {{colors.surface_bright.default.hex}}; + surface-container-lowest: {{colors.surface_container_lowest.default.hex}}; + surface-container-low: {{colors.surface_container_low.default.hex}}; + surface-container: {{colors.surface_container.default.hex}}; + surface-container-high: {{colors.surface_container_high.default.hex}}; + surface-container-highest: {{colors.surface_container_highest.default.hex}}; +} diff --git a/matugen/templates/spotify-colors.ini b/matugen/templates/spotify-colors.ini new file mode 100644 index 0000000..23117b5 --- /dev/null +++ b/matugen/templates/spotify-colors.ini @@ -0,0 +1,14 @@ +[Spicetify] +accent = {{ colors.on_surface.default.hex_stripped }} +accent-active = {{ colors.primary.default.hex_stripped }} +accent-inactive = {{ colors.surface.default.hex_stripped }} +banner = {{ colors.primary.default.hex_stripped }} +border-active = {{ colors.outline.default.hex_stripped }} +border-inactive = {{ colors.outline_variant.default.hex_stripped }} +header = {{ colors.on_surface.default.hex_stripped }} +highlight = {{ colors.surface_container_low.default.hex_stripped }} +main = {{ colors.surface.default.hex_stripped }} +notification = {{ colors.tertiary.default.hex_stripped }} +notification-error = {{ colors.error.default.hex_stripped }} +subtext = {{ colors.on_surface_variant.default.hex_stripped }} +text = {{ colors.on_surface.default.hex_stripped }} diff --git a/niri/config.kdl b/niri/config.kdl new file mode 100644 index 0000000..3ae0d62 --- /dev/null +++ b/niri/config.kdl @@ -0,0 +1,673 @@ +// This config is in the KDL format: https://kdl.dev +// "/-" comments out the following node. +// Check the wiki for a full description of the configuration: +// https://yalter.github.io/niri/Configuration:-Introduction + +// Input device configuration. +// Find the full list of options on the wiki: +// https://yalter.github.io/niri/Configuration:-Input +input { + keyboard { + xkb { + // You can set rules, model, layout, variant and options. + // For more information, see xkeyboard-config(7). + + // For example: + layout "it,us" + // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps" + + // If this section is empty, niri will fetch xkb settings + // from org.freedesktop.locale1. You can control these using + // localectl set-x11-keymap. + } + + // Enable numlock on startup, omitting this setting disables it. + numlock + } + + // Next sections include libinput settings. + // Omitting settings disables them, or leaves them at their default values. + // All commented-out settings here are examples, not defaults. + touchpad { + // off + tap + // dwt + // dwtp + // drag false + // drag-lock + natural-scroll + // acel-speed 0.2 + // accel-profile "flat" + // scroll-method "two-finger" + // disabled-on-external-mouse + } + + mouse { + // off + // natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "no-scroll" + + } + + trackpoint { + // off + // natural-scroll + // accel-speed 0.2 + // accel-profile "flat" + // scroll-method "on-button-down" + // scroll-button 273 + // scroll-button-lock + // middle-emulation + } + + // Uncomment this to make the mouse warp to the center of newly focused windows. + // warp-mouse-to-focus + + // Focus windows and outputs automatically when moving the mouse into them. + // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen. + focus-follows-mouse max-scroll-amount="0%" +} + +// You can configure outputs by their name, which you can find +// by running `niri msg outputs` while inside a niri instance. +// The built-in laptop monitor is usually called "eDP-1". +// Find more information on the wiki: +// https://yalter.github.io/niri/Configuration:-Outputs +// Remember to uncomment the node by removing "/-"! +output "eDP-1" { + // Uncomment this line to disable this output. + // off + + // Resolution and, optionally, refresh rate of the output. + // The format is "x" or "x@". + // If the refresh rate is omitted, niri will pick the highest refresh rate + // for the resolution. + // If the mode is omitted altogether or is invalid, niri will pick one automatically. + // Run `niri msg outputs` while inside a niri instance to list all outputs and their modes. + mode "3072x1920@120.000" + + // You can use integer or fractional scale, for example use 1.5 for 150% scale. + scale 2 + + // Transform allows to rotate the output counter-clockwise, valid values are: + // normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270. + transform "normal" + + // Position of the output in the global coordinate space. + // This affects directional monitor actions like "focus-monitor-left", and cursor movement. + // The cursor can only move between directly adjacent outputs. + // Output scale and rotation has to be taken into account for positioning: + // outputs are sized in logical, or scaled, pixels. + // For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080, + // so to put another output directly adjacent to it on the right, set its x to 1920. + // If the position is unset or results in an overlap, the output is instead placed + // automatically. + position x=1280 y=0 +} + +// Settings that influence how windows are positioned and sized. +// Find more information on the wiki: +// https://yalter.github.io/niri/Configuration:-Layout +layout { + // Set gaps around windows in logical pixels. + gaps 16 + + // When to center a column when changing focus, options are: + // - "never", default behavior, focusing an off-screen column will keep at the left + // or right edge of the screen. + // - "always", the focused column will always be centered. + // - "on-overflow", focusing a column will center it if it doesn't fit + // together with the previously focused column. + center-focused-column "never" + + // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between. + preset-column-widths { + // Proportion sets the width as a fraction of the output width, taking gaps into account. + // For example, you can perfectly fit four windows sized "proportion 0.25" on an output. + // The default preset widths are 1/3, 1/2 and 2/3 of the output. + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + + // Fixed sets the width in logical pixels exactly. + // fixed 1920 + } + + // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between. + // preset-window-heights { } + + // You can change the default width of the new windows. + default-column-width { proportion 0.5; } + // If you leave the brackets empty, the windows themselves will decide their initial width. + // default-column-width {} + + // By default focus ring and border are rendered as a solid background rectangle + // behind windows. That is, they will show up through semitransparent windows. + // This is because windows using client-side decorations can have an arbitrary shape. + // + // If you don't like that, you should uncomment `prefer-no-csd` below. + // prefer-no-csd + // Niri will draw focus ring and border *around* windows that agree to omit their + // client-side decorations. + // + // Alternatively, you can override it with a window rule called + // draw-border-with-background + + // You can change how the focus ring looks. + focus-ring { + // Uncomment this line to disable the focus ring. + // off + // How many logical pixels the ring extends out from the windows. + width 2 + + // Colors can be set in a variety of ways: + // - CSS named colors: "red" + // - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" + // - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others. + + // Color of the ring on the active monitor. + active-color "#7fc8ff" + + // Color of the ring on inactive monitors. + // + // The focus ring only draws around the active window, so the only place + // where you can see its inactive-color is on other monitors. + inactive-color "#505050" + + // You can also use gradients. They take precedence over solid colors. + // Gradients are rendered the same as CSS linear-gradient(angle, from, to). + // The angle is the same as in linear-gradient, and is optional, + // defaulting to 180 (top-to-bottom gradient). + // You can use any CSS linear-gradient tool on the web to set these up. + // Changing the color space is also supported, check the wiki for more info. + // + // active-gradient from="#80c8ff" to="#c7ff7f" angle=45 + + // You can also color the gradient relative to the entire view + // of the workspace, rather than relative to just the window itself. + // To do that, set relative-to="workspace-view". + // + // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" + } + + // You can also add a border. It's similar to the focus ring, but always visible. + border { + // The settings are the same as for the focus ring. + // If you enable the border, you probably want to disable the focus ring. + off + + width 4 + active-color "#ffc87f" + inactive-color "#505050" + + // Color of the border around windows that request your attention. + urgent-color "#9b0000" + + // Gradients can use a few different interpolation color spaces. + // For example, this is a pastel rainbow gradient via in="oklch longer hue". + // + // active-gradient from="#e5989b" to="#ffb4a2" angle=45 relative-to="workspace-view" in="oklch longer hue" + + // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" + } + + // You can enable drop shadows for windows. + shadow { + // Uncomment the next line to enable shadows. + // on + + // By default, the shadow draws only around its window, and not behind it. + // Uncomment this setting to make the shadow draw behind its window. + // + // Note that niri has no way of knowing about the CSD window corner + // radius. It has to assume that windows have square corners, leading to + // shadow artifacts inside the CSD rounded corners. This setting fixes + // those artifacts. + // + // However, instead you may want to set prefer-no-csd and/or + // geometry-corner-radius. Then, niri will know the corner radius and + // draw the shadow correctly, without having to draw it behind the + // window. These will also remove client-side shadows if the window + // draws any. + // + // draw-behind-window true + + // You can change how shadows look. The values below are in logical + // pixels and match the CSS box-shadow properties. + + // Softness controls the shadow blur radius. + softness 30 + + // Spread expands the shadow. + spread 5 + + // Offset moves the shadow relative to the window. + offset x=0 y=5 + + // You can also change the shadow color and opacity. + color "#0007" + } + + // Struts shrink the area occupied by windows, similarly to layer-shell panels. + // You can think of them as a kind of outer gaps. They are set in logical pixels. + // Left and right struts will cause the next window to the side to always be visible. + // Top and bottom struts will simply add outer gaps in addition to the area occupied by + // layer-shell panels and regular gaps. + struts { + // left 64 + // right 64 + // top 64 + // bottom 64 + } +} + +// Add lines like this to spawn processes at startup. +// Note that running niri as a session supports xdg-desktop-autostart, +// which may be more convenient to use. +// See the binds section below for more spawn examples. + +// This line starts waybar, a commonly used bar for Wayland compositors. +// spawn-at-startup "waybar" "-c /home/sinsa/.config/waybar/configs/defaultNIRI" "-s /home/sinsa/.config/waybar/style/islands.css" + +//spawn-sh-at-startup "waybar -c /home/sinsa/.config/waybar/configs/defaultNIRI -s /home/sinsa/.config/waybar/style/islands.css" +//spawn-sh-at-startup "awww-daemon" +//spawn-sh-at-startup "awww-daemon -n overlay" +//spawn-sh-at-startup "awww img /home/sinsa/.config/hypr/current_wallpaper" +//spawn-sh-at-startup "awww img -n overlay /home/sinsa/.config/hypr/current_wallpaper" +spawn-at-startup "/usr/lib/hyprpolkitagent/hyprpolkitagent" +spawn-at-startup "kitty" +spawn-sh-at-startup "qs -c noctalia-shell" + +prefer-no-csd + +// To run a shell command (with variables, pipes, etc.), use spawn-sh-at-startup: +// spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell" + +hotkey-overlay { + // Uncomment this line to disable the "Important Hotkeys" pop-up at startup. + // skip-at-startup +} + +// Uncomment this line to ask the clients to omit their client-side decorations if possible. +// If the client will specifically ask for CSD, the request will be honored. +// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners. +// This option will also fix border/focus ring drawing behind some semitransparent windows. +// After enabling or disabling this, you need to restart the apps for this to take effect. +// prefer-no-csd + +// You can change the path where screenshots are saved. +// A ~ at the front will be expanded to the home directory. +// The path is formatted with strftime(3) to give you the screenshot date and time. +screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" + +// You can also set this to null to disable saving screenshots to disk. +// screenshot-path null + +// Animation settings. +// The wiki explains how to configure individual animations: +// https://yalter.github.io/niri/Configuration:-Animations +animations { + // Uncomment to turn off all animations. + // off + + // Slow down all animations by this factor. Values below 1 speed them up instead. + // slowdown 3.0 +} + +// layer-rule { + +// This is for swww; change for other wallpaper tools. + +// Find the right namespace by running niri msg layers. + +//match namespace="^awww-daemonoverlay$" + +//place-within-backdrop true + +//} + +layer-rule { + match namespace="^noctalia-overview*" + place-within-backdrop true +} + + +/- window-rule { + open-maximized true +} + + + +window-rule { + geometry-corner-radius 12 +} +// Window rules let you adjust behavior for individual windows. +// Find more information on the wiki: +// https://yalter.github.io/niri/Configuration:-Window-Rules + +// Work around WezTerm's initial configure bug +// by setting an empty default-column-width. +window-rule { + // This regular expression is intentionally made as specific as possible, + // since this is the default config, and we want no false positives. + // You can get away with just app-id="wezterm" if you want. + //matchatch app-id=r#"^org\.wezfurlong\.wezterm$"# + // default-column-width {} +} + +// Open the Firefox picture-in-picture player as floating by default. +window-rule { + // This app-id regular expression will work for both: + // - host Firefox (app-id is "firefox") + // - Flatpak Firefox (app-id is "org.mozilla.firefox") + // match app-id=r#"firefox$"# title="^Picture-in-Picture$" + // open-floating true +} + +// Example: block out two password managers from screen capture. +// (This example rule is commented out with a "/-" in front.) +/-window-rule { + match app-id=r#"^org\.keepassxc\.KeePassXC$"# + match app-id=r#"^org\.gnome\.World\.Secrets$"# + + block-out-from "screen-capture" + + // Use this instead if you want them visible on third-party screenshot tools. + // block-out-from "screencast" +} + +// Example: enable rounded corners for all windows. +// (This example rule is commented out with a "/-" in front.) +window-rule { + geometry-corner-radius 12 + clip-to-geometry true +} + +switch-events { + lid-close { + spawn "qs" "-c" "noctalia-shell" "ipc" "call" "sessionMenu" "lockAndSuspend" + } +} + + +binds { + // Keys consist of modifiers separated by + signs, followed by an XKB key name + // in the end. To find an XKB name for a particular key, you may use a program + // like wev. + // + // "Mod" is a special modifier equal to Super when running on a TTY, and to Alt + // when running as a winit window. + // + // Most actions that you can bind here can also be invoked programmatically with + // `niri msg action do-something`. + + // Mod-Shift-/, which is usually the same as Mod-?, + // shows a list of important hotkeys. + Mod+Shift+Slash { show-hotkey-overlay; } + + // Suggested binds for running programs: terminal, app launcher, screen locker. + Mod+Q hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; } + Mod+D hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; } + Super+Alt+L hotkey-overlay-title="Lock the Screen: swaylock" { spawn "swaylock"; } + + // Use spawn-sh to run a shell command. Do this if you need pipes, multiple commands, etc. + // Note: the entire command goes as a single argument. It's passed verbatim to `sh -c`. + // For example, this is a standard bind to toggle the screen reader (orca). + Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; } + + // Example volume keys mappings for PipeWire & WirePlumber. + // The allow-when-locked=true property makes them work even when the session is locked. + // Using spawn-sh allows to pass multiple arguments together with the command. + // "-l 1.0" limits the volume to 100%. + XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; } + XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; } + XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } + + // Example media keys mapping using playerctl. + // This will work with any MPRIS-enabled media player. + XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; } + XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; } + XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; } + XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; } + + // Example brightness key mappings for brightnessctl. + // You can use regular spawn with multiple arguments too (to avoid going through "sh"), + // but you need to manually put each argument in separate "" quotes. + XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; } + + // Open/close the Overview: a zoomed-out view of workspaces and windows. + // You can also move the mouse into the top-left hot corner, + // or do a four-finger swipe up on a touchpad. + Mod+O repeat=false { toggle-overview; } + + Mod+C repeat=false { close-window; } + Mod+return { spawn-sh "qs -c noctalia-shell ipc call launcher toggle"; } + Mod+Left { focus-column-left; } + Mod+Down { focus-window-down; } + Mod+Up { focus-window-up; } + Mod+Right { focus-column-right; } + Mod+H { focus-column-left; } + Mod+J { focus-window-down; } + Mod+K { focus-window-up; } + Mod+L { focus-column-right; } + + Mod+Shift+Left { move-column-left-or-to-monitor-left; } + Mod+Shift+Down { move-window-down; } + Mod+Shift+Up { move-window-up; } + Mod+Shift+Right { move-column-right-or-to-monitor-right; } + Mod+Shift+H { move-column-left; } + Mod+Shift+J { move-window-down; } + Mod+Shift+K { move-window-up; } + Mod+Shift+L { move-column-right-or-to-monitor-right; } + + // Alternative commands that move across workspaces when reaching + // the first or last window in a column. + // Mod+J { focus-window-or-workspace-down; } + // Mod+K { focus-window-or-workspace-up; } + // Mod+Ctrl+J { move-window-down-or-to-workspace-down; } + // Mod+Ctrl+K { move-window-up-or-to-workspace-up; } + + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + Mod+Ctrl+Left { focus-monitor-left; } + //Mod+Alt+Ctrl+Down { focus-monitor-down; } + //Mod+Alt+Ctrl+Up { focus-monitor-up; } + Mod+Ctrl+Right { focus-monitor-right; } + //Mod+Alt+Ctrl+H { focus-monitor-left; } + //Mod+Alt+Ctrl+J { focus-monitor-down; } + //Mod+Alt+Ctrl+K { focus-monitor-up; } + //Mod+Alt+Ctrl+L { focus-monitor-right; } + Mod+Shift+Page_Up {move-column-to-monitor-left; } + Mod+Shift+Page_Down {move-column-to-monitor-right; } + //Mod+Shift+Ctrl+Left { move-column-to-monitor-left; } + //Mod+Shift+Ctrl+Down { move-column-to-monitor-down; } + //Mod+Shift+Ctrl+Up { move-column-to-monitor-up; } + //Mod+Shift+Ctrl+Right { move-column-to-monitor-right; } + //Mod+Shift+Ctrl+H { move-column-to-monitor-left; } + //Mod+Shift+Ctrl+J { move-column-to-monitor-down; } + //Mod+Shift+Ctrl+K { move-column-to-monitor-up; } + //Mod+Shift+Ctrl+L { move-column-to-monitor-right; } + + // Alternatively, there are commands to move just a single window: + // Mod+Shift+Ctrl+Left { move-window-to-monitor-left; } + // ... + + // And you can also move a whole workspace to another monitor: + // Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; } + // ... + + Mod+Ctrl+down { focus-workspace-down; } + Mod+Ctrl+up {focus-workspace-up; } + Mod+U { focus-workspace-down; } + Mod+I { focus-workspace-up; } + Mod+Ctrl+Shift+down { move-column-to-workspace-down; } + Mod+Ctrl+Shift+up { move-column-to-workspace-up; } + Mod+Ctrl+U { move-column-to-workspace-down; } + Mod+Ctrl+I { move-column-to-workspace-up; } + + // Alternatively, there are commands to move just a single window: + // Mod+Ctrl+Page_Down { move-window-to-workspace-down; } + // ... + + //Mod+Shift+Page_Down { move-workspace-down; } + //Mod+Shift+Page_Up { move-workspace-up; } + Mod+Shift+U { move-workspace-down; } + Mod+Shift+I { move-workspace-up; } + + // You can bind mouse wheel scroll ticks using the following syntax. + // These binds will change direction based on the natural-scroll setting. + // + // To avoid scrolling through workspaces really fast, you can use + // the cooldown-ms property. The bind will be rate-limited to this value. + // You can set a cooldown on any bind, but it's most useful for the wheel. + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; } + + Mod+WheelScrollRight { focus-column-right; } + Mod+WheelScrollLeft { focus-column-left; } + Mod+Ctrl+WheelScrollRight { move-column-right; } + Mod+Ctrl+WheelScrollLeft { move-column-left; } + + // Usually scrolling up and down with Shift in applications results in + // horizontal scrolling; these binds replicate that. + Mod+Shift+WheelScrollDown { focus-column-right; } + Mod+Shift+WheelScrollUp { focus-column-left; } + Mod+Ctrl+Shift+WheelScrollDown { move-column-right; } + Mod+Ctrl+Shift+WheelScrollUp { move-column-left; } + + // Similarly, you can bind touchpad scroll "ticks". + // Touchpad scrolling is continuous, so for these binds it is split into + // discrete intervals. + // These binds are also affected by touchpad's natural-scroll, so these + // example binds are "inverted", since we have natural-scroll enabled for + // touchpads by default. + // Mod+TouchpadScrollDown { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02+"; } + // Mod+TouchpadScrollUp { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02-"; } + + // You can refer to workspaces by index. However, keep in mind that + // niri is a dynamic workspace system, so these commands are kind of + // "best effort". Trying to refer to a workspace index bigger than + // the current workspace count will instead refer to the bottommost + // (empty) workspace. + // + // For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on + // will all refer to the 3rd workspace. + Mod+1 { focus-workspace 1; } + Mod+2 { focus-workspace 2; } + Mod+3 { focus-workspace 3; } + Mod+4 { focus-workspace 4; } + Mod+5 { focus-workspace 5; } + Mod+6 { focus-workspace 6; } + Mod+7 { focus-workspace 7; } + Mod+8 { focus-workspace 8; } + Mod+9 { focus-workspace 9; } + Mod+Ctrl+1 { move-column-to-workspace 1; } + Mod+Ctrl+2 { move-column-to-workspace 2; } + Mod+Ctrl+3 { move-column-to-workspace 3; } + Mod+Ctrl+4 { move-column-to-workspace 4; } + Mod+Ctrl+5 { move-column-to-workspace 5; } + Mod+Ctrl+6 { move-column-to-workspace 6; } + Mod+Ctrl+7 { move-column-to-workspace 7; } + Mod+Ctrl+8 { move-column-to-workspace 8; } + Mod+Ctrl+9 { move-column-to-workspace 9; } + + // Alternatively, there are commands to move just a single window: + // Mod+Ctrl+1 { move-window-to-workspace 1; } + + // Switches focus between the current and the previous workspace. + // Mod+Tab { focus-workspace-previous; } + + // The following binds move the focused window in and out of a column. + // If the window is alone, they will consume it into the nearby column to the side. + // If the window is already in a column, they will expel it out. + Mod+BracketLeft { consume-or-expel-window-left; } + Mod+BracketRight { consume-or-expel-window-right; } + + // Consume one window from the right to the bottom of the focused column. + Mod+Comma { consume-window-into-column; } + // Expel the bottom window from the focused column to the right. + Mod+Period { expel-window-from-column; } + + Mod+R { switch-preset-column-width; } + // Cycling through the presets in reverse order is also possible. + // Mod+R { switch-preset-column-width-back; } + Mod+Shift+R { switch-preset-window-height; } + Mod+Ctrl+R { reset-window-height; } + Mod+F { maximize-column; } + Mod+Shift+F { fullscreen-window; } + + // Expand the focused column to space not taken up by other fully visible columns. + // Makes the column "fill the rest of the space". + Mod+Ctrl+F { expand-column-to-available-width; } + + Mod+Shift+C { center-column; } + + // Center all fully visible columns on screen. + Mod+Ctrl+C { center-visible-columns; } + + // Finer width adjustments. + // This command can also: + // * set width in pixels: "1000" + // * adjust width in pixels: "-5" or "+5" + // * set width as a percentage of screen width: "25%" + // * adjust width as a percentage of screen width: "-10%" or "+10%" + // Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0, + // set-column-width "100" will make the column occupy 200 physical screen pixels. + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + // Finer height adjustments when in column with other windows. + Mod+Shift+Minus { set-window-height "-10%"; } + Mod+Shift+Equal { set-window-height "+10%"; } + + // Move the focused window between the floating and the tiling layout. + Mod+V { toggle-window-floating; } + Mod+Shift+V { switch-focus-between-floating-and-tiling; } + + // Toggle tabbed column display mode. + // Windows in this column will appear as vertical tabs, + // rather than stacked on top of each other. + Mod+W { toggle-column-tabbed-display; } + + // Actions to switch layouts. + // Note: if you uncomment these, make sure you do NOT have + // a matching layout switch hotkey configured in xkb options above. + // Having both at once on the same hotkey will break the switching, + // since it will switch twice upon pressing the hotkey (once by xkb, once by niri). + // Mod+Space { switch-layout "next"; } + // Mod+Shift+Space { switch-layout "prev"; } + + Print { screenshot; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + + // Applications such as remote-desktop clients and software KVM switches may + // request that niri stops processing the keyboard shortcuts defined here + // so they may, for example, forward the key presses as-is to a remote machine. + // It's a good idea to bind an escape hatch to toggle the inhibitor, + // so a buggy application can't hold your session hostage. + // + // The allow-inhibiting=false property can be applied to other binds as well, + // which ensures niri always processes them, even when an inhibitor is active. + Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; } + + // The quit action will show a confirmation dialog to avoid accidental exits. + Mod+Shift+E { quit; } + Ctrl+Alt+Delete { quit; } + + // Powers off the monitors. To turn them back on, do any input like + // moving the mouse or pressing any other key. + Mod+Shift+P { power-off-monitors; } +} + +include "./noctalia.kdl" + diff --git a/niri/noctalia.kdl b/niri/noctalia.kdl new file mode 100644 index 0000000..3e0ef4c --- /dev/null +++ b/niri/noctalia.kdl @@ -0,0 +1,35 @@ +layout { + + focus-ring { + active-color "#d5bbff" + inactive-color "#141316" + urgent-color "#ffb4ab" + } + + border { + active-color "#d5bbff" + inactive-color "#141316" + urgent-color "#ffb4ab" + } + + shadow { + color "#00000070" + } + + tab-indicator { + active-color "#d5bbff" + inactive-color "#543587" + urgent-color "#ffb4ab" + } + + insert-hint { + color "#d5bbff80" + } +} + +recent-windows { + highlight { + active-color "#d5bbff" + urgent-color "#ffb4ab" + } +} diff --git a/noctalia/colors.json b/noctalia/colors.json new file mode 100644 index 0000000..22615d8 --- /dev/null +++ b/noctalia/colors.json @@ -0,0 +1,25 @@ +{ + "mPrimary": "#d5bbff", + "mOnPrimary": "#3d1c6f", + + "mSecondary": "#cec2db", + "mOnSecondary": "#342d40", + + "mTertiary": "#f1b7c3", + "mOnTertiary": "#4a252f", + + "mError": "#ffb4ab", + "mOnError": "#690005", + + "mSurface": "#141316", + "mOnSurface": "#e6e1e6", + + "mSurfaceVariant": "#211f22", + "mOnSurfaceVariant": "#cbc4cf", + + "mOutline": "#49454e", + "mShadow": "#000000", + + "mHover": "#f1b7c3", + "mOnHover": "#4a252f" +} \ No newline at end of file diff --git a/noctalia/colorschemes/Murasaki/Murasaki.json b/noctalia/colorschemes/Murasaki/Murasaki.json new file mode 100644 index 0000000..71c2965 --- /dev/null +++ b/noctalia/colorschemes/Murasaki/Murasaki.json @@ -0,0 +1,94 @@ +{ + "dark": { + "mPrimary": "#e8bcfb", + "mOnPrimary": "#8e0cc6", + "mSecondary": "#8e0cc6", + "mOnSecondary": "#e8bcfb", + "mTertiary": "#066f50", + "mOnTertiary": "#90f9d9", + "mError": "#e80e4f", + "mOnError": "#fee7ee", + "mSurface": "#300443", + "mOnSurface": "#fef7e7", + "mSurfaceVariant": "#50066f", + "mOnSurfaceVariant": "#e8bcfb", + "mOutline": "#8e0cc6", + "mShadow": "#110118", + "mHover": "#6f099a", + "mOnHover": "#fef7e7", + "terminal": { + "foreground": "#f7e7fe", + "background": "#110118", + "normal": { + "black": "#110118", + "red": "#e80e4f", + "green": "#cb62f8", + "yellow": "#e8a70e", + "blue": "#bc39f3", + "magenta": "#e80ebc", + "cyan": "#a70ee8", + "white": "#e8bcfb" + }, + "bright": { + "black": "#310345", + "red": "#c73859", + "green": "#da8efa", + "yellow": "#f3bc39", + "blue": "#ca65f6", + "magenta": "#f339ce", + "cyan": "#bc39f3", + "white": "#f7e7fe" + }, + "cursor": "#f7e7fe", + "cursorText": "#110118", + "selectionFg": "#f7e7fe", + "selectionBg": "#50066f" + } + }, + "light": { + "mPrimary": "#8e0cc6", + "mOnPrimary": "#e8bcfb", + "mSecondary": "#ca65f6", + "mOnSecondary": "#a70ee8", + "mTertiary": "#bcfbe8", + "mOnTertiary": "#066f50", + "mError": "#f33971", + "mOnError": "#430417", + "mSurface": "#f7e7fe", + "mOnSurface": "#6f099a", + "mSurfaceVariant": "#e8bcfb", + "mOnSurfaceVariant": "#50066f", + "mOutline": "#ca65f6", + "mShadow": "#f7e7fe", + "mHover": "#d990f9", + "mOnHover": "#300443", + "terminal": { + "foreground": "#110118", + "background": "#f7e7fe", + "normal": { + "black": "#110118", + "red": "#e80e4f", + "green": "#cb62f8", + "yellow": "#e8a70e", + "blue": "#bc39f3", + "magenta": "#e80ebc", + "cyan": "#a70ee8", + "white": "#e8bcfb" + }, + "bright": { + "black": "#310345", + "red": "#c73859", + "green": "#da8efa", + "yellow": "#f3bc39", + "blue": "#ca65f6", + "magenta": "#f339ce", + "cyan": "#bc39f3", + "white": "#f7e7fe" + }, + "cursor": "#110118", + "cursorText": "#f7e7fe", + "selectionFg": "#50066f", + "selectionBg": "#e8bcfb" + } + } +} diff --git a/noctalia/plugins.json b/noctalia/plugins.json new file mode 100644 index 0000000..107ef28 --- /dev/null +++ b/noctalia/plugins.json @@ -0,0 +1,32 @@ +{ + "sources": [ + { + "enabled": true, + "name": "Noctalia Plugins", + "url": "https://github.com/noctalia-dev/noctalia-plugins" + } + ], + "states": { + "catwalk": { + "enabled": false, + "sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins" + }, + "fancy-audiovisualizer": { + "enabled": true, + "sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins" + }, + "file-search": { + "enabled": true, + "sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins" + }, + "kde-connect": { + "enabled": true, + "sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins" + }, + "slowbongo": { + "enabled": false, + "sourceUrl": "https://github.com/noctalia-dev/noctalia-plugins" + } + }, + "version": 2 +} diff --git a/noctalia/plugins/catwalk/BarWidget.qml b/noctalia/plugins/catwalk/BarWidget.qml new file mode 100644 index 0000000..ad38e6b --- /dev/null +++ b/noctalia/plugins/catwalk/BarWidget.qml @@ -0,0 +1,193 @@ +import QtQuick +import QtQuick.Effects +import Quickshell +import Quickshell.Io +import qs.Commons +import qs.Modules.Bar.Extras +import qs.Services.UI +import qs.Widgets +import qs.Services.System + +Item { + id: root + + property var pluginApi: null + property ShellScreen screen + property string widgetId: "" + property string section: "" + property int sectionWidgetIndex: -1 + property int sectionWidgetsCount: 0 + + // Per-screen bar properties + readonly property string screenName: screen?.name ?? "" + readonly property string barPosition: Settings.getBarPositionForScreen(screenName) + readonly property bool barIsVertical: barPosition === "left" || barPosition === "right" + readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName) + + property url currentIconSource + + property string tooltipText: { + if (!pluginApi) return ""; + return root.isRunning ? (pluginApi.tr("tooltip.running") || "Running") : (pluginApi.tr("tooltip.sleeping") || "Sleeping"); + } + + property string tooltipDirection: BarService.getTooltipDirection() + property bool enabled: true + property bool allowClickWhenDisabled: false + property bool hovering: false + + property color colorBg: Color.mSurfaceVariant + property color colorFg: Color.mPrimary + property color colorBgHover: Color.mHover + property color colorFgHover: Color.mOnHover + property color colorBorder: Color.mOutline + property color colorBorderHover: Color.mOutline + property real customRadius: Style.radiusL + + signal entered + signal exited + signal clicked + signal rightClicked + signal middleClicked + signal wheel(int angleDelta) + + readonly property real contentWidth: barIsVertical ? capsuleHeight : Math.round(capsuleHeight + Style.marginXS * 2) + readonly property real contentHeight: capsuleHeight + + implicitWidth: contentWidth + implicitHeight: contentHeight + + // --- Catwalk Specific Logic --- + property int frameIndex: 0 + property int idleFrameIndex: 0 + readonly property bool isRunning: root.pluginApi?.mainInstance?.isRunning ?? false + readonly property var icons: root.pluginApi?.mainInstance?.icons || [] + readonly property var idleIcons: root.pluginApi?.mainInstance?.idleIcons || [] + readonly property real cpuUsage: root.pluginApi?.mainInstance?.cpuUsage ?? 0 + + function openPanel() { + if (pluginApi) { + var result = pluginApi.openPanel(root.screen); + Logger.i("Catwalk", "OpenPanel result:", result); + } else { + Logger.e("Catwalk", "PluginAPI is null"); + } + } + + function openExternalMonitor() { + Quickshell.execDetached(["sh", "-c", Settings.data.systemMonitor.externalMonitor]); + } + + Timer { + interval: Math.max(30, 200 - root.cpuUsage * 1.7) + running: root.isRunning + repeat: true + onTriggered: { + root.frameIndex = (root.frameIndex + 1) % root.icons.length + } + } + + Timer { + interval: 400 + running: !root.isRunning + repeat: true + onTriggered: { + root.idleFrameIndex = (root.idleFrameIndex + 1) % root.idleIcons.length + } + } + + currentIconSource: (root.icons && root.icons.length > 0 && root.idleIcons && root.idleIcons.length > 0) + ? (root.isRunning + ? Qt.resolvedUrl(root.icons[root.frameIndex % root.icons.length]) + : Qt.resolvedUrl(root.idleIcons[root.idleFrameIndex % root.idleIcons.length])) + : "" + + Rectangle { + id: visualCapsule + x: Style.pixelAlignCenter(parent.width, width) + y: Style.pixelAlignCenter(parent.height, height) + width: root.contentWidth + height: root.contentHeight + opacity: root.enabled ? Style.opacityFull : Style.opacityMedium + color: mouseArea.containsMouse ? Color.mHover : Style.capsuleColor + radius: Math.min((customRadius >= 0 ? customRadius : Style.iRadiusL), width / 2) + border.color: Style.capsuleBorderColor + border.width: Style.capsuleBorderWidth + + Behavior on color { + ColorAnimation { + duration: Style.animationNormal + easing.type: Easing.InOutQuad + } + } + + Image { + id: iconImage + source: root.currentIconSource + x: Style.pixelAlignCenter(parent.width, width) + y: Style.pixelAlignCenter(parent.height, height) + + width: Style.toOdd(visualCapsule.width - Style.marginXS * 2) + height: width + + // Render SVG at exact target size for crisp output + sourceSize: Qt.size(width, height) + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: false + + // This enables the "mask" behavior to recolor the icon + layer.enabled: true + layer.effect: MultiEffect { + colorization: 1.0 + colorizationColor: Settings.data.colorSchemes.darkMode ? "white" : "black" + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + hoverEnabled: true + onEntered: { + root.hovering = true; + if (root.tooltipText) { + TooltipService.show(root, root.tooltipText, root.tooltipDirection); + } + root.entered(); + } + onExited: { + root.hovering = false; + if (root.tooltipText) { + TooltipService.hide(); + } + root.exited(); + } + onClicked: function (mouse) { + if (root.tooltipText) { + TooltipService.hide(); + } + + Logger.i("Catwalk", "Clicked! API:", !!pluginApi, "Screen:", root.screen ? root.screen.name : "null"); + + if (!root.enabled && !root.allowClickWhenDisabled) { + return; + } + // Open Panel on left/right click + // Open external monitor on middle click + if (mouse.button === Qt.LeftButton) { + root.openPanel(); + root.clicked(); + } else if (mouse.button === Qt.RightButton) { + root.openPanel(); + root.rightClicked(); + } else if (mouse.button === Qt.MiddleButton) { + root.openExternalMonitor(); + root.middleClicked(); + } + } + onWheel: wheel => root.wheel(wheel.angleDelta.y) + } +} diff --git a/noctalia/plugins/catwalk/DesktopWidget.qml b/noctalia/plugins/catwalk/DesktopWidget.qml new file mode 100644 index 0000000..931bf33 --- /dev/null +++ b/noctalia/plugins/catwalk/DesktopWidget.qml @@ -0,0 +1,85 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Effects +import Quickshell +import qs.Commons +import qs.Modules.DesktopWidgets +import qs.Widgets +import qs.Services.System + +DraggableDesktopWidget { + id: root + property var pluginApi: null + + implicitWidth: 200 + implicitHeight: 80 + + showBackground: !(root.pluginApi?.mainInstance?.hideBackground ?? false) + + property int frameIndex: 0 + + readonly property var icons: root.pluginApi?.mainInstance?.icons || [] + + property int idleFrameIndex: 0 + readonly property var idleIcons: root.pluginApi?.mainInstance?.idleIcons || [] + + readonly property bool isRunning: root.pluginApi?.mainInstance?.isRunning ?? false + readonly property real cpuUsage: root.pluginApi?.mainInstance?.cpuUsage ?? 0 + + Timer { + interval: Math.max(30, 200 - root.cpuUsage * 1.7) + running: root.isRunning + repeat: true + onTriggered: { + root.frameIndex = (root.frameIndex + 1) % root.icons.length + } + } + + Timer { + interval: 400 + running: !root.isRunning + repeat: true + onTriggered: { + root.idleFrameIndex = (root.idleFrameIndex + 1) % root.idleIcons.length + } + } + + property url currentIconSource: (root.icons && root.icons.length > 0 && root.idleIcons && root.idleIcons.length > 0) + ? (root.isRunning + ? Qt.resolvedUrl(root.icons[root.frameIndex % root.icons.length]) + : Qt.resolvedUrl(root.idleIcons[root.idleFrameIndex % root.idleIcons.length])) + : "" + + RowLayout { + anchors.fill: parent + spacing: 5 + + Image { + id: iconImage + source: root.currentIconSource + Layout.fillHeight: true + Layout.preferredWidth: height + + sourceSize.height: height + sourceSize.width: width + + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: false + + layer.enabled: true + layer.effect: MultiEffect { + colorization: 1.0 + colorizationColor: Settings.data.colorSchemes.darkMode ? "white" : "black" + } + } + + Text { + text: Math.round(root.cpuUsage) + "%" + color: Settings.data.colorSchemes.darkMode ? "white" : "black" + font.bold: true + font.pixelSize: 40 + Layout.alignment: Qt.AlignVCenter + } + } +} diff --git a/noctalia/plugins/catwalk/Main.qml b/noctalia/plugins/catwalk/Main.qml new file mode 100644 index 0000000..7096062 --- /dev/null +++ b/noctalia/plugins/catwalk/Main.qml @@ -0,0 +1,18 @@ +import QtQuick +import Quickshell +import qs.Services.System + +Item { + id: root + + property var pluginApi: null + + readonly property real minimumThreshold: pluginApi?.pluginSettings?.minimumThreshold || 10 + readonly property bool hideBackground: pluginApi?.pluginSettings?.hideBackground ?? false + + property real cpuUsage: SystemStatService.cpuUsage + readonly property bool isRunning: cpuUsage >= minimumThreshold + + readonly property var icons: ["icons/my-active-0-symbolic.svg", "icons/my-active-1-symbolic.svg", "icons/my-active-2-symbolic.svg", "icons/my-active-3-symbolic.svg", "icons/my-active-4-symbolic.svg"] + readonly property var idleIcons: ["icons/my-idle-0-symbolic.svg", "icons/my-idle-1-symbolic.svg", "icons/my-idle-2-symbolic.svg", "icons/my-idle-3-symbolic.svg"] +} diff --git a/noctalia/plugins/catwalk/Panel.qml b/noctalia/plugins/catwalk/Panel.qml new file mode 100644 index 0000000..0eeb67c --- /dev/null +++ b/noctalia/plugins/catwalk/Panel.qml @@ -0,0 +1,102 @@ +import QtQuick +import QtQuick.Effects +import QtQuick.Layouts +import qs.Commons +import qs.Services.System +import qs.Widgets + +Item { + id: root + property var pluginApi: null + + // SmartPanel properties + readonly property var geometryPlaceholder: panelContainer + readonly property bool allowAttach: true + property real contentPreferredWidth: 300 * Style.uiScaleRatio + property real contentPreferredHeight: 300 * Style.uiScaleRatio + + anchors.fill: parent + + Rectangle { + id: panelContainer + anchors.fill: parent + color: "transparent" + + Rectangle { + anchors.fill: parent + anchors.margins: Style.marginL + color: Color.mSurface + radius: Style.radiusL + border.color: Color.mOutline + border.width: Style.borderS + + ColumnLayout { + anchors.centerIn: parent + spacing: Style.marginL + + // Big Cat + Item { + id: bigCatItem + Layout.preferredWidth: 128 * Style.uiScaleRatio + Layout.preferredHeight: 128 * Style.uiScaleRatio + Layout.alignment: Qt.AlignHCenter + + property int frameIndex: 0 + + readonly property bool isRunning: root.pluginApi?.mainInstance?.isRunning ?? false + readonly property var icons: root.pluginApi?.mainInstance?.icons || [] + + property int idleFrameIndex: 0 + readonly property var idleIcons: root.pluginApi?.mainInstance?.idleIcons || [] + + readonly property real cpuUsage: root.pluginApi?.mainInstance?.cpuUsage ?? 0 + + Timer { + interval: Math.max(30, 200 - bigCatItem.cpuUsage * 1.7) + running: bigCatItem.isRunning + repeat: true + onTriggered: bigCatItem.frameIndex = (bigCatItem.frameIndex + 1) % bigCatItem.icons.length + } + + Timer { + interval: 400 + running: !bigCatItem.isRunning + repeat: true + onTriggered: bigCatItem.idleFrameIndex = (bigCatItem.idleFrameIndex + 1) % bigCatItem.idleIcons.length + } + + Image { + id: bigCatImage + anchors.fill: parent + + source: (bigCatItem.icons && bigCatItem.icons.length > 0 && bigCatItem.idleIcons && bigCatItem.idleIcons.length > 0) + ? (bigCatItem.isRunning + ? Qt.resolvedUrl(bigCatItem.icons[bigCatItem.frameIndex % bigCatItem.icons.length]) + : Qt.resolvedUrl(bigCatItem.idleIcons[bigCatItem.idleFrameIndex % bigCatItem.idleIcons.length])) + : "" + + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + + // This handles the programmatic coloring + layer.enabled: true + layer.effect: MultiEffect { + colorization: 1.0 + colorizationColor: Settings.data.colorSchemes.darkMode ? "white" : "black" + } + } + } + + // CPU Stats + Text { + Layout.alignment: Qt.AlignHCenter + text: (pluginApi?.tr("panel.cpuLabel") || "CPU: {usage}%").replace("{usage}", Math.round(root.pluginApi?.mainInstance?.cpuUsage ?? 0)) + font.pointSize: Style.fontSizeXL + font.weight: Font.Bold + color: Settings.data.colorSchemes.darkMode ? "white" : "black" + } + } + } + } +} \ No newline at end of file diff --git a/noctalia/plugins/catwalk/README.md b/noctalia/plugins/catwalk/README.md new file mode 100644 index 0000000..52b094c --- /dev/null +++ b/noctalia/plugins/catwalk/README.md @@ -0,0 +1,34 @@ +# Catwalk Plugin for Noctalia + +A cute animated cat for your Noctalia bar that reacts to your system's CPU usage. + +## Features + +- **Animated Cat**: The cat walks/runs on your bar based on CPU usage +- **CPU-Based Animation**: + - Below minimum threshold: Shows idle animation with "Zz" bubbles + - Above minimum threshold: Walks faster as CPU usage increases + - Speed scales continuously with CPU load +- **Popup Panel**: Click the cat to open a larger animated version with CPU stats +- **Theme Support**: Automatically switches between light/dark mode icons +- **Configurable Settings**: Adjust the minimum CPU threshold for running animation + +## Installation + +This plugin is part of the `noctalia-plugins` repository. + +## Configuration + +Access the plugin settings in Noctalia to configure: + +- **Minimum CPU Threshold**: Set the CPU usage percentage (5-25%) above which the cat starts running. Below this, it stays idle with "Zz" animation. + +## Usage + +- The cat icon appears on your bar +- It automatically animates based on your CPU usage +- Click to open the CPU stats panel + +## Requirements + +- Noctalia 3.6.0 or later diff --git a/noctalia/plugins/catwalk/Settings.qml b/noctalia/plugins/catwalk/Settings.qml new file mode 100644 index 0000000..c1721bf --- /dev/null +++ b/noctalia/plugins/catwalk/Settings.qml @@ -0,0 +1,75 @@ +import QtQuick +import QtQuick.Layouts +import qs.Widgets +import qs.Commons + +ColumnLayout { + id: root + + // Plugin API (injected by the settings dialog system) + property var pluginApi: null + + // Local state - track changes before saving + property real valueMinimumThreshold: pluginApi?.mainInstance?.minimumThreshold ?? (pluginApi?.pluginSettings?.minimumThreshold || 10) + property bool valueHideBackground: pluginApi?.mainInstance?.hideBackground ?? (pluginApi?.pluginSettings?.hideBackground ?? false) + + spacing: Style.marginM + + Component.onCompleted: { + Logger.i("Catwalk", "Settings UI loaded"); + } + + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginS + + NLabel { + label: pluginApi?.tr("settings.minimumThreshold.label") || "Minimum CPU Threshold" + description: pluginApi?.tr("settings.minimumThreshold.description") || "CPU usage must be above this percentage for the cat to start running" + } + + NSlider { + id: thresholdSlider + from: 5 + to: 25 + value: root.valueMinimumThreshold + stepSize: 1 + onValueChanged: { + root.valueMinimumThreshold = value + } + } + + Text { + text: (pluginApi?.tr("settings.currentThreshold") || "Current threshold: {value}%").replace("{value}", thresholdSlider.value) + color: Color.mOnSurfaceVariant + font.pointSize: Style.fontSizeS + } + } + + NToggle { + label: pluginApi?.tr("settings.hideBackground.label") || "Hide Background" + description: pluginApi?.tr("settings.hideBackground.description") || "Hide the background of the desktop widget" + + checked: root.valueHideBackground + onToggled: function(checked) { + root.valueHideBackground = checked + } + } + + // This function is called by the dialog to save settings + function saveSettings() { + if (!pluginApi) { + Logger.e("Catwalk", "Cannot save settings: pluginApi is null"); + return; + } + + // Update the plugin settings object + pluginApi.pluginSettings.minimumThreshold = root.valueMinimumThreshold; + pluginApi.pluginSettings.hideBackground = root.valueHideBackground; + + // Save to disk + pluginApi.saveSettings(); + + Logger.i("Catwalk", "Settings saved successfully"); + } +} \ No newline at end of file diff --git a/noctalia/plugins/catwalk/i18n/de.json b/noctalia/plugins/catwalk/i18n/de.json new file mode 100644 index 0000000..4424d88 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/de.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Aktuelle Schwelle: {value}%", + "hideBackground": { + "description": "Verstecke den Hintergrund des Desktop-Widgets", + "label": "Hintergrund ausblenden" + }, + "minimumThreshold": { + "description": "Die CPU-Auslastung muss über diesem Prozentsatz liegen, damit die Katze zu laufen beginnt", + "label": "Minimale CPU-Schwelle" + }, + "title": "Catwalk-Einstellungen" + }, + "tooltip": { + "running": "Katze läuft", + "sleeping": "Katze schläft" + } +} diff --git a/noctalia/plugins/catwalk/i18n/en.json b/noctalia/plugins/catwalk/i18n/en.json new file mode 100644 index 0000000..93248a1 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/en.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Current threshold: {value}%", + "hideBackground": { + "description": "Hide the background of the desktop widget", + "label": "Hide Background" + }, + "minimumThreshold": { + "description": "CPU usage must be above this percentage for the cat to start running", + "label": "Minimum CPU Threshold" + }, + "title": "Catwalk Settings" + }, + "tooltip": { + "running": "Cat is running", + "sleeping": "Cat is sleeping" + } +} diff --git a/noctalia/plugins/catwalk/i18n/es.json b/noctalia/plugins/catwalk/i18n/es.json new file mode 100644 index 0000000..873824e --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/es.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Umbral actual: {value}%", + "hideBackground": { + "description": "Ocultar el fondo del widget de escritorio", + "label": "Ocultar fondo" + }, + "minimumThreshold": { + "description": "El uso de CPU debe estar por encima de este porcentaje para que el gato empiece a correr", + "label": "Umbral mínimo de CPU" + }, + "title": "Configuración de Catwalk" + }, + "tooltip": { + "running": "El gato está corriendo", + "sleeping": "El gato está durmiendo" + } +} diff --git a/noctalia/plugins/catwalk/i18n/fr.json b/noctalia/plugins/catwalk/i18n/fr.json new file mode 100644 index 0000000..1b5be2f --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/fr.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU : {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Seuil actuel : {value}%", + "hideBackground": { + "description": "Masquer l'arrière-plan du widget de bureau", + "label": "Masquer l'arrière-plan" + }, + "minimumThreshold": { + "description": "L'utilisation du CPU doit être supérieure à ce pourcentage pour que le chat commence à courir", + "label": "Seuil minimum CPU" + }, + "title": "Paramètres Catwalk" + }, + "tooltip": { + "running": "Le chat court", + "sleeping": "Le chat dort" + } +} diff --git a/noctalia/plugins/catwalk/i18n/hu.json b/noctalia/plugins/catwalk/i18n/hu.json new file mode 100644 index 0000000..6de0c91 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/hu.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Sétasáv" + }, + "settings": { + "currentThreshold": "Aktuális küszöbérték: {value}%", + "hideBackground": { + "description": "Asztali widget hátterének elrejtése", + "label": "Háttér elrejtése" + }, + "minimumThreshold": { + "description": "A processzorhasználatnak e fölött a százalék felett kell lennie, hogy a macska futni kezdjen", + "label": "Minimum CPU Küszöbérték" + }, + "title": "Catwalk beállítások" + }, + "tooltip": { + "running": "A Noctalia fut.", + "sleeping": "A macska alszik" + } +} diff --git a/noctalia/plugins/catwalk/i18n/it.json b/noctalia/plugins/catwalk/i18n/it.json new file mode 100644 index 0000000..46d374e --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/it.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Soglia attuale: {value}%", + "hideBackground": { + "description": "Nascondi lo sfondo del widget desktop", + "label": "Nascondi sfondo" + }, + "minimumThreshold": { + "description": "L'utilizzo della CPU deve essere superiore a questa percentuale affinché il gatto inizi a correre", + "label": "Soglia minima CPU" + }, + "title": "Impostazioni Catwalk" + }, + "tooltip": { + "running": "Il gatto sta correndo", + "sleeping": "Il gatto sta dormendo" + } +} diff --git a/noctalia/plugins/catwalk/i18n/ja.json b/noctalia/plugins/catwalk/i18n/ja.json new file mode 100644 index 0000000..93dbf46 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/ja.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "現在のしきい値: {value}%", + "hideBackground": { + "description": "デスクトップウィジェットの背景を隠す", + "label": "背景を隠す" + }, + "minimumThreshold": { + "description": "猫が走り始めるにはCPU使用率がこの割合を超えている必要があります", + "label": "最小CPUしきい値" + }, + "title": "Catwalk設定" + }, + "tooltip": { + "running": "猫が走っています", + "sleeping": "猫が寝ています" + } +} diff --git a/noctalia/plugins/catwalk/i18n/ku.json b/noctalia/plugins/catwalk/i18n/ku.json new file mode 100644 index 0000000..e5bc9d5 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/ku.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Rêwînga pisîkan" + }, + "settings": { + "currentThreshold": "Astana niha: {value}%", + "hideBackground": { + "description": "Paşxana wîceta sermaseyê veşêre", + "label": "Veşartina Paşxanê" + }, + "minimumThreshold": { + "description": "Divê bikaranîna CPU ji vê rêjeyê bilindtir be da ku pisîk dest bi bezê bike", + "label": "Sînorê herî kêm ê CPU" + }, + "title": "Mîhenên Catwalkê" + }, + "tooltip": { + "running": "Pisîk direve", + "sleeping": "Pisîk radizê." + } +} diff --git a/noctalia/plugins/catwalk/i18n/nl.json b/noctalia/plugins/catwalk/i18n/nl.json new file mode 100644 index 0000000..efb83a6 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/nl.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Huidige drempelwaarde: {value}%", + "hideBackground": { + "description": "Verberg de achtergrond van de bureaubladwidget", + "label": "Achtergrond verbergen" + }, + "minimumThreshold": { + "description": "CPU-gebruik moet boven dit percentage liggen voordat de kat begint te rennen.", + "label": "Minimale CPU-drempel" + }, + "title": "Catwalk Instellingen" + }, + "tooltip": { + "running": "Kat rent", + "sleeping": "Kat slaapt" + } +} diff --git a/noctalia/plugins/catwalk/i18n/pl.json b/noctalia/plugins/catwalk/i18n/pl.json new file mode 100644 index 0000000..558416a --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/pl.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Wybieg" + }, + "settings": { + "currentThreshold": "Aktualny próg: {value}%", + "hideBackground": { + "description": "Ukryj tło widżetu pulpitu", + "label": "Ukryj tło" + }, + "minimumThreshold": { + "description": "Użycie CPU musi przekraczać ten procent, aby kot zaczął biegać", + "label": "Minimalny próg użycia CPU" + }, + "title": "Ustawienia Catwalk" + }, + "tooltip": { + "running": "Kot jest uruchomiony", + "sleeping": "Kot śpi" + } +} diff --git a/noctalia/plugins/catwalk/i18n/pt.json b/noctalia/plugins/catwalk/i18n/pt.json new file mode 100644 index 0000000..0efb112 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/pt.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Limite atual: {value}%", + "hideBackground": { + "description": "Ocultar o fundo do widget da área de trabalho", + "label": "Ocultar fundo" + }, + "minimumThreshold": { + "description": "O uso da CPU deve estar acima desta porcentagem para o gato começar a correr", + "label": "Limite mínimo de CPU" + }, + "title": "Configurações do Catwalk" + }, + "tooltip": { + "running": "O gato está correndo", + "sleeping": "O gato está dormindo" + } +} diff --git a/noctalia/plugins/catwalk/i18n/ru.json b/noctalia/plugins/catwalk/i18n/ru.json new file mode 100644 index 0000000..53ef758 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/ru.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Catwalk" + }, + "settings": { + "currentThreshold": "Текущий порог: {value}%", + "hideBackground": { + "description": "Скрыть фон виджета рабочего стола", + "label": "Скрыть фон" + }, + "minimumThreshold": { + "description": "Использование CPU должно быть выше этого процента, чтобы кот начал бежать", + "label": "Минимальный порог CPU" + }, + "title": "Настройки Catwalk" + }, + "tooltip": { + "running": "Кот бежит", + "sleeping": "Кот спит" + } +} diff --git a/noctalia/plugins/catwalk/i18n/tr.json b/noctalia/plugins/catwalk/i18n/tr.json new file mode 100644 index 0000000..95bee2e --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/tr.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU: {usage}%", + "title": "Podyum" + }, + "settings": { + "currentThreshold": "Mevcut eşik: {value}%", + "hideBackground": { + "description": "Masaüstü bileşeninin arka planını gizle", + "label": "Arka planı gizle" + }, + "minimumThreshold": { + "description": "CPU kullanımı, kedinin koşmaya başlaması için bu yüzdeden yüksek olmalıdır.", + "label": "Minimum CPU Eşiği" + }, + "title": "Podyum Ayarları" + }, + "tooltip": { + "running": "Kedi koşuyor.", + "sleeping": "Kedi uyuyor." + } +} diff --git a/noctalia/plugins/catwalk/i18n/uk-UA.json b/noctalia/plugins/catwalk/i18n/uk-UA.json new file mode 100644 index 0000000..e109beb --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/uk-UA.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "ЦП: {usage}%", + "title": "Подіум" + }, + "settings": { + "currentThreshold": "Поточний поріг: {value}%", + "hideBackground": { + "description": "Приховати фон віджета робочого столу", + "label": "Приховати фон" + }, + "minimumThreshold": { + "description": "Використання ЦП має бути вище цього відсотка, щоб кіт почав бігати.", + "label": "Мінімальний поріг ЦП" + }, + "title": "Налаштування подіуму" + }, + "tooltip": { + "running": "Кіт біжить", + "sleeping": "Кіт спить" + } +} diff --git a/noctalia/plugins/catwalk/i18n/zh-CN.json b/noctalia/plugins/catwalk/i18n/zh-CN.json new file mode 100644 index 0000000..37a9709 --- /dev/null +++ b/noctalia/plugins/catwalk/i18n/zh-CN.json @@ -0,0 +1,22 @@ +{ + "panel": { + "cpuLabel": "CPU:{usage}%", + "title": "猫步" + }, + "settings": { + "currentThreshold": "当前阈值:{value}%", + "hideBackground": { + "description": "隐藏桌面小部件的背景", + "label": "隐藏背景" + }, + "minimumThreshold": { + "description": "CPU 使用率必须高于此百分比,猫才能开始跑动。", + "label": "最低CPU阈值" + }, + "title": "时装秀场布置" + }, + "tooltip": { + "running": "猫在跑", + "sleeping": "猫在睡觉" + } +} diff --git a/noctalia/plugins/catwalk/icons/my-active-0-symbolic.svg b/noctalia/plugins/catwalk/icons/my-active-0-symbolic.svg new file mode 100644 index 0000000..7abf1a0 --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-active-0-symbolic.svg @@ -0,0 +1,32 @@ + + + + + + + + + image/svg+xml + + RunCat: Frame 0 + + + + RunCat: Frame 0 + + diff --git a/noctalia/plugins/catwalk/icons/my-active-1-symbolic.svg b/noctalia/plugins/catwalk/icons/my-active-1-symbolic.svg new file mode 100644 index 0000000..3a06046 --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-active-1-symbolic.svg @@ -0,0 +1,32 @@ + + + + + + + + + image/svg+xml + + RunCat: Frame 1 + + + + RunCat: Frame 1 + + diff --git a/noctalia/plugins/catwalk/icons/my-active-2-symbolic.svg b/noctalia/plugins/catwalk/icons/my-active-2-symbolic.svg new file mode 100644 index 0000000..769737c --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-active-2-symbolic.svg @@ -0,0 +1,32 @@ + + + + + + + + + image/svg+xml + + RunCat: Frame 2 + + + + RunCat: Frame 2 + + diff --git a/noctalia/plugins/catwalk/icons/my-active-3-symbolic.svg b/noctalia/plugins/catwalk/icons/my-active-3-symbolic.svg new file mode 100644 index 0000000..79ec50c --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-active-3-symbolic.svg @@ -0,0 +1,32 @@ + + + + + + + + + image/svg+xml + + RunCat: Frame 3 + + + + RunCat: Frame 3 + + diff --git a/noctalia/plugins/catwalk/icons/my-active-4-symbolic.svg b/noctalia/plugins/catwalk/icons/my-active-4-symbolic.svg new file mode 100644 index 0000000..a3a2623 --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-active-4-symbolic.svg @@ -0,0 +1,32 @@ + + + + + + + + + image/svg+xml + + RunCat: Frame 4 + + + + RunCat: Frame 4 + + diff --git a/noctalia/plugins/catwalk/icons/my-idle-0-symbolic.svg b/noctalia/plugins/catwalk/icons/my-idle-0-symbolic.svg new file mode 100644 index 0000000..e6e5028 --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-idle-0-symbolic.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/noctalia/plugins/catwalk/icons/my-idle-1-symbolic.svg b/noctalia/plugins/catwalk/icons/my-idle-1-symbolic.svg new file mode 100644 index 0000000..ef0831c --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-idle-1-symbolic.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/noctalia/plugins/catwalk/icons/my-idle-2-symbolic.svg b/noctalia/plugins/catwalk/icons/my-idle-2-symbolic.svg new file mode 100644 index 0000000..b0b3e2a --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-idle-2-symbolic.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/noctalia/plugins/catwalk/icons/my-idle-3-symbolic.svg b/noctalia/plugins/catwalk/icons/my-idle-3-symbolic.svg new file mode 100644 index 0000000..af78795 --- /dev/null +++ b/noctalia/plugins/catwalk/icons/my-idle-3-symbolic.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/noctalia/plugins/catwalk/manifest.json b/noctalia/plugins/catwalk/manifest.json new file mode 100644 index 0000000..74e5518 --- /dev/null +++ b/noctalia/plugins/catwalk/manifest.json @@ -0,0 +1,32 @@ +{ + "id": "catwalk", + "name": "Catwalk", + "version": "1.1.7", + "minNoctaliaVersion": "3.6.0", + "author": "MannuVilasara", + "license": "MIT", + "repository": "https://github.com/noctalia-dev/noctalia-plugins", + "description": "A cute animated cat for your bar.", + "tags": [ + "Bar", + "Desktop", + "Panel", + "Fun" + ], + "entryPoints": { + "main": "Main.qml", + "barWidget": "BarWidget.qml", + "desktopWidget": "DesktopWidget.qml", + "panel": "Panel.qml", + "settings": "Settings.qml" + }, + "dependencies": { + "plugins": [] + }, + "metadata": { + "defaultSettings": { + "minimumThreshold": 10, + "hideBackground": false + } + } +} diff --git a/noctalia/plugins/catwalk/preview.png b/noctalia/plugins/catwalk/preview.png new file mode 100644 index 0000000..5e73151 Binary files /dev/null and b/noctalia/plugins/catwalk/preview.png differ diff --git a/noctalia/plugins/catwalk/settings.json b/noctalia/plugins/catwalk/settings.json new file mode 100644 index 0000000..7b53704 --- /dev/null +++ b/noctalia/plugins/catwalk/settings.json @@ -0,0 +1,4 @@ +{ + "minimumThreshold": 5, + "hideBackground": false +} diff --git a/noctalia/plugins/fancy-audiovisualizer/DesktopWidget.qml b/noctalia/plugins/fancy-audiovisualizer/DesktopWidget.qml new file mode 100644 index 0000000..6c934aa --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/DesktopWidget.qml @@ -0,0 +1,150 @@ +import QtQuick +import Quickshell +import qs.Commons +import qs.Modules.DesktopWidgets +import qs.Services.Media + +DraggableDesktopWidget { + id: root + + property var pluginApi: null + + implicitWidth: Math.round(300 * widgetScale) + implicitHeight: Math.round(300 * widgetScale) + + showBackground: false + + // Scaled dimensions + readonly property int scaledRadiusL: Math.round(Style.radiusL * widgetScale) + + // Settings from plugin + readonly property real sensitivity: widgetData?.sensitivity ?? pluginApi?.pluginSettings?.sensitivity ?? pluginApi?.manifest?.metadata?.defaultSettings?.sensitivity + readonly property real rotationSpeed: widgetData?.rotationSpeed ?? pluginApi?.pluginSettings?.rotationSpeed ?? pluginApi?.manifest?.metadata?.defaultSettings?.rotationSpeed + readonly property real barWidth: widgetData?.barWidth ?? pluginApi?.pluginSettings?.barWidth ?? pluginApi?.manifest?.metadata?.defaultSettings?.barWidth + readonly property real ringOpacity: widgetData?.ringOpacity ?? pluginApi?.pluginSettings?.ringOpacity ?? pluginApi?.manifest?.metadata?.defaultSettings?.ringOpacity + readonly property real bloomIntensity: widgetData?.bloomIntensity ?? pluginApi.pluginSettings?.bloomIntensity ?? pluginApi?.manifest?.metadata?.defaultSettings?.bloomIntensity + readonly property int visualizationMode: widgetData?.visualizationMode ?? pluginApi?.pluginSettings?.visualizationMode ?? pluginApi?.manifest?.metadata?.defaultSettings?.visualizationMode ?? 3 + readonly property real waveThickness: widgetData?.waveThickness ?? pluginApi?.pluginSettings?.waveThickness ?? pluginApi?.manifest?.metadata?.defaultSettings?.waveThickness ?? 1.0 + readonly property real innerDiameter: widgetData?.innerDiameter ?? pluginApi?.pluginSettings?.innerDiameter ?? pluginApi?.manifest?.metadata?.defaultSettings?.innerDiameter ?? 0.7 + readonly property bool fadeWhenIdle: widgetData?.fadeWhenIdle ?? pluginApi?.pluginSettings?.fadeWhenIdle ?? false + readonly property bool useCustomColors: widgetData?.useCustomColors ?? pluginApi?.pluginSettings?.useCustomColors ?? false + readonly property color customPrimaryColor: widgetData?.customPrimaryColor ?? pluginApi?.pluginSettings?.customPrimaryColor ?? "#6750A4" + readonly property color customSecondaryColor: widgetData?.customSecondaryColor ?? pluginApi?.pluginSettings?.customSecondaryColor ?? "#625B71" + + // Animation time for shader (0 to 3600, 1 hour cycle) + property real shaderTime: 0 + NumberAnimation on shaderTime { + loops: Animation.Infinite + from: 0 + to: 3600 + duration: 3600000 + running: !SpectrumService.isIdle + } + + // Hidden canvas that encodes audio data as a 32x1 texture + Canvas { + id: audioCanvas + width: 32 + height: 1 + visible: false + + onPaint: { + var ctx = getContext("2d"); + var values = SpectrumService.values; + if (!values || values.length === 0) { + ctx.fillStyle = "black"; + ctx.fillRect(0, 0, 32, 1); + return; + } + for (var i = 0; i < 32; i++) { + var v = values[i] || 0; + // Encode amplitude in grayscale (R=G=B=amplitude) + var c = Math.floor(v * 255); + ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")"; + ctx.fillRect(i, 0, 1, 1); + } + } + } + + // Trigger canvas repaint when audio data changes + Connections { + target: SpectrumService + function onValuesChanged() { + if (!SpectrumService.isIdle) { + audioCanvas.requestPaint(); + } + } + } + + // Unique instance ID for SpectrumService registration + // This prevents the old widget's destruction from unregistering the new widget + readonly property string spectrumInstanceId: "plugin:fancy-audiovisualizer:" + Date.now() + Math.random() + + // Register with SpectrumService when pluginApi becomes available + onPluginApiChanged: { + if (pluginApi) { + SpectrumService.registerComponent(spectrumInstanceId); + audioCanvas.requestPaint(); + } + } + + Component.onDestruction: { + SpectrumService.unregisterComponent(spectrumInstanceId); + } + + // Audio texture source (outside ShaderEffect to avoid 'source' property warning) + ShaderEffectSource { + id: audioTextureSource + sourceItem: audioCanvas + live: true + hideSource: true + } + + // The shader effect visualization + ShaderEffect { + id: visualizer + anchors.fill: parent + visible: pluginApi !== null + opacity: (root.fadeWhenIdle && SpectrumService.isIdle) ? 0 : 1 + + Behavior on opacity { + NumberAnimation { duration: 500; easing.type: Easing.InOutQuad } + } + + // Audio texture - named 'source' to match ShaderEffectSource's property and avoid warning + property var source: audioTextureSource + + // Uniforms passed to shader + property real time: root.shaderTime + property real itemWidth: visualizer.width + property real itemHeight: visualizer.height + property color primaryColor: root.useCustomColors ? root.customPrimaryColor : Color.mPrimary + property color secondaryColor: root.useCustomColors ? root.customSecondaryColor : Color.mSecondary + property real sensitivity: root.sensitivity + property real rotationSpeed: root.rotationSpeed + property real barWidth: root.barWidth + property real ringOpacity: root.ringOpacity + property real cornerRadius: scaledRadiusL + property real bloomIntensity: root.bloomIntensity + property real visualizationMode: root.visualizationMode + property real waveThickness: root.waveThickness + property real innerDiameter: root.innerDiameter + + fragmentShader: pluginApi ? Qt.resolvedUrl(pluginApi.pluginDir + "/shaders/visualizer.frag.qsb") : "" + } + + // Fallback when shader not loaded + Rectangle { + anchors.fill: parent + color: Color.mSurface + radius: scaledRadiusL + visible: !visualizer.visible || visualizer.fragmentShader === "" + + Text { + anchors.centerIn: parent + text: "Loading..." + color: Color.mOnSurface + font.pointSize: Math.round(Style.fontSizeM * widgetScale) + } + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/DesktopWidgetSettings.qml b/noctalia/plugins/fancy-audiovisualizer/DesktopWidgetSettings.qml new file mode 100644 index 0000000..3122c24 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/DesktopWidgetSettings.qml @@ -0,0 +1,244 @@ +import QtQuick +import QtQuick.Layouts +import qs.Commons +import qs.Widgets + +ColumnLayout { + id: root + + property var pluginApi: null + property var widgetSettings: null + property var screen: null + + spacing: Style.marginM + + // Local state for editing + property real valueSensitivity: widgetSettings?.data?.sensitivity ?? pluginApi?.pluginSettings?.sensitivity ?? 1.5 + property real valueRotationSpeed: widgetSettings?.data?.rotationSpeed ?? pluginApi?.pluginSettings?.rotationSpeed ?? 0.5 + property real valueBarWidth: widgetSettings?.data?.barWidth ?? pluginApi?.pluginSettings?.barWidth ?? 0.6 + property real valueRingOpacity: widgetSettings?.data?.ringOpacity ?? pluginApi?.pluginSettings?.ringOpacity ?? 0.8 + property real valueBloomIntensity: widgetSettings?.data?.bloomIntensity ?? pluginApi?.pluginSettings?.bloomIntensity ?? 0.5 + property int valueVisualizationMode: widgetSettings?.data?.visualizationMode ?? pluginApi?.pluginSettings?.visualizationMode ?? 3 + property real valueWaveThickness: widgetSettings?.data?.waveThickness ?? pluginApi?.pluginSettings?.waveThickness ?? 1.0 + property real valueInnerDiameter: widgetSettings?.data?.innerDiameter ?? pluginApi?.pluginSettings?.innerDiameter ?? 0.7 + property bool valueFadeWhenIdle: widgetSettings?.data?.fadeWhenIdle ?? pluginApi?.pluginSettings?.fadeWhenIdle ?? true + property bool valueUseCustomColors: widgetSettings?.data?.useCustomColors ?? pluginApi?.pluginSettings?.useCustomColors ?? false + property color valueCustomPrimaryColor: widgetSettings?.data?.customPrimaryColor ?? pluginApi?.pluginSettings?.customPrimaryColor ?? "#6750A4" + property color valueCustomSecondaryColor: widgetSettings?.data?.customSecondaryColor ?? pluginApi?.pluginSettings?.customSecondaryColor ?? "#625B71" + + // Mode helpers + readonly property bool modeHasBars: valueVisualizationMode === 0 || valueVisualizationMode === 3 || valueVisualizationMode === 5 + readonly property bool modeHasWave: valueVisualizationMode === 1 || valueVisualizationMode === 4 || valueVisualizationMode === 5 + readonly property bool modeHasRings: valueVisualizationMode >= 2 + + NHeader { + label: pluginApi?.tr("settings.title") ?? "Visualizer Settings" + description: pluginApi?.tr("settings.description") ?? "Configure the audio visualizer appearance" + } + + // Visualization mode selector + NComboBox { + Layout.fillWidth: true + label: pluginApi?.tr("settings.visualizationMode") ?? "Visualization Mode" + description: pluginApi?.tr("settings.visualizationMode-description") ?? "Choose visualization style" + model: [ + {"key": "0", "name": pluginApi?.tr("settings.mode.bars") ?? "Bars"}, + {"key": "1", "name": pluginApi?.tr("settings.mode.wave") ?? "Wave"}, + {"key": "2", "name": pluginApi?.tr("settings.mode.rings") ?? "Rings"}, + {"key": "3", "name": pluginApi?.tr("settings.mode.barsRings") ?? "Bars + Rings"}, + {"key": "4", "name": pluginApi?.tr("settings.mode.waveRings") ?? "Wave + Rings"}, + {"key": "5", "name": pluginApi?.tr("settings.mode.all") ?? "All"} + ] + currentKey: String(root.valueVisualizationMode) + onSelected: key => { + root.valueVisualizationMode = parseInt(key); + root.saveSettings(); + } + } + + // Wave thickness slider (shown when mode includes wave) + NValueSlider { + Layout.fillWidth: true + visible: root.modeHasWave + label: pluginApi?.tr("settings.waveThickness") ?? "Wave Thickness" + value: root.valueWaveThickness + from: 0.3 + to: 2.0 + stepSize: 0.1 + onMoved: value => { + root.valueWaveThickness = value; + root.saveSettings(); + } + } + + // Sensitivity slider + NValueSlider { + Layout.fillWidth: true + label: pluginApi?.tr("settings.sensitivity") ?? "Sensitivity" + value: root.valueSensitivity + from: 0.5 + to: 3.0 + stepSize: 0.1 + onMoved: value => { + root.valueSensitivity = value; + root.saveSettings(); + } + } + + // Rotation speed slider + NValueSlider { + Layout.fillWidth: true + label: pluginApi?.tr("settings.rotationSpeed") ?? "Rotation Speed" + value: root.valueRotationSpeed + from: 0.0 + to: 2.0 + stepSize: 0.1 + onMoved: value => { + root.valueRotationSpeed = value; + root.saveSettings(); + } + } + + // Bar width slider (shown when mode includes bars) + NValueSlider { + Layout.fillWidth: true + visible: root.modeHasBars + label: pluginApi?.tr("settings.barWidth") ?? "Bar Width" + value: root.valueBarWidth + from: 0.2 + to: 1.0 + stepSize: 0.1 + onMoved: value => { + root.valueBarWidth = value; + root.saveSettings(); + } + } + + // Ring opacity slider (shown when mode includes rings) + NValueSlider { + Layout.fillWidth: true + visible: root.modeHasRings + label: pluginApi?.tr("settings.ringOpacity") ?? "Ring Opacity" + value: root.valueRingOpacity + from: 0.0 + to: 1.0 + stepSize: 0.1 + onMoved: value => { + root.valueRingOpacity = value; + root.saveSettings(); + } + } + + // Base diameter slider + NValueSlider { + Layout.fillWidth: true + label: pluginApi?.tr("settings.innerDiameter") ?? "Inner Diameter" + value: root.valueInnerDiameter + from: 0 + to: 1 + stepSize: 0.05 + onMoved: value => { + root.valueInnerDiameter = value; + root.saveSettings(); + } + } + + // Bloom intensity slider + NValueSlider { + Layout.fillWidth: true + label: pluginApi?.tr("settings.bloomIntensity") ?? "Bloom Intensity" + value: root.valueBloomIntensity + from: 0.0 + to: 1.0 + stepSize: 0.05 + onMoved: value => { + root.valueBloomIntensity = value; + root.saveSettings(); + } + } + + // Fade when idle toggle + NToggle { + label: pluginApi?.tr("settings.fadeWhenIdle") ?? "Fade When Idle" + description: pluginApi?.tr("settings.fadeWhenIdle-description") ?? "Fade out visualizer when no audio is playing" + checked: root.valueFadeWhenIdle + onToggled: checked => { + root.valueFadeWhenIdle = checked; + root.saveSettings(); + } + } + + // Use custom colors toggle + NToggle { + label: pluginApi?.tr("settings.useCustomColors") ?? "Use Custom Colors" + description: pluginApi?.tr("settings.useCustomColors-description") ?? "Override theme colors with custom colors" + checked: root.valueUseCustomColors + onToggled: checked => { + root.valueUseCustomColors = checked; + root.saveSettings(); + } + } + + // Custom primary color picker + RowLayout { + Layout.fillWidth: true + visible: root.valueUseCustomColors + spacing: Style.marginM + + NText { + text: pluginApi?.tr("settings.customPrimaryColor") ?? "Primary Color" + Layout.fillWidth: true + } + + NColorPicker { + screen: Screen + selectedColor: root.valueCustomPrimaryColor + onColorSelected: color => { + root.valueCustomPrimaryColor = color; + root.saveSettings(); + } + } + } + + // Custom secondary color picker + RowLayout { + Layout.fillWidth: true + visible: root.valueUseCustomColors + spacing: Style.marginM + + NText { + text: pluginApi?.tr("settings.customSecondaryColor") ?? "Secondary Color" + Layout.fillWidth: true + } + + NColorPicker { + screen: Screen + selectedColor: root.valueCustomSecondaryColor + onColorSelected: color => { + root.valueCustomSecondaryColor = color; + root.saveSettings(); + } + } + } + + // Called when user clicks Apply/Save + function saveSettings() { + if (!widgetSettings) + return; + + widgetSettings.data.sensitivity = root.valueSensitivity; + widgetSettings.data.rotationSpeed = root.valueRotationSpeed; + widgetSettings.data.barWidth = root.valueBarWidth; + widgetSettings.data.ringOpacity = root.valueRingOpacity; + widgetSettings.data.bloomIntensity = root.valueBloomIntensity; + widgetSettings.data.visualizationMode = root.valueVisualizationMode; + widgetSettings.data.waveThickness = root.valueWaveThickness; + widgetSettings.data.innerDiameter = root.valueInnerDiameter; + widgetSettings.data.fadeWhenIdle = root.valueFadeWhenIdle; + widgetSettings.data.useCustomColors = root.valueUseCustomColors; + widgetSettings.data.customPrimaryColor = root.valueCustomPrimaryColor.toString(); + widgetSettings.data.customSecondaryColor = root.valueCustomSecondaryColor.toString(); + + widgetSettings.save(); + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/README.md b/noctalia/plugins/fancy-audiovisualizer/README.md new file mode 100644 index 0000000..93a4d46 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/README.md @@ -0,0 +1,38 @@ +# Fancy Audiovisualizer + +A circular audio visualizer desktop widget for Noctalia Shell with shader-based rendering and multiple visualization modes. + +## Features + +- **Multiple Visualization Modes**: Bars, Wave, Rings, or combinations (Bars+Rings, Wave+Rings, All) +- **Shader-Based Rendering**: Smooth, GPU-accelerated visualization using custom fragment shaders +- **Theme Integration**: Automatically uses Noctalia theme colors, with optional custom color override +- **Configurable Appearance**: Adjust sensitivity, rotation speed, bar width, ring opacity, bloom intensity, and more +- **Idle Fade**: Optional fade-out when no audio is playing + +## Installation + +This plugin is part of the `noctalia-plugins` repository. + +## Configuration + +Access the plugin settings in Noctalia to configure the following options: + +- **Visualization Mode**: Choose between Bars, Wave, Rings, Bars+Rings, Wave+Rings, or All +- **Wave Thickness**: Thickness of the wave visualization (when enabled) +- **Sensitivity**: Audio response sensitivity (0.5 - 3.0) +- **Rotation Speed**: Speed of visualization rotation (0.0 - 2.0) +- **Bar Width**: Width of audio bars (when enabled) +- **Ring Opacity**: Opacity of background rings (when enabled) +- **Inner Diameter**: Size of the inner empty area +- **Bloom Intensity**: Glow/bloom effect strength +- **Fade When Idle**: Fade out when no audio is playing +- **Custom Colors**: Override theme colors with custom primary and secondary colors + +## Usage + +Add the widget to your desktop via the Noctalia desktop widgets interface. The visualizer responds to system audio. + +## Requirements + +- Noctalia 3.7.2 or later diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/de.json b/noctalia/plugins/fancy-audiovisualizer/i18n/de.json new file mode 100644 index 0000000..002193d --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/de.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Balkenbreite", + "bloomIntensity": "Blütenintensität", + "customPrimaryColor": "Primärfarbe", + "customSecondaryColor": "Sekundärfarbe", + "description": "Audiovisualisierungsdarstellung konfigurieren", + "fadeWhenIdle": "Ausblenden bei Inaktivität", + "fadeWhenIdle-description": "Visualisierer ausblenden, wenn keine Audioausgabe erfolgt", + "innerDiameter": "Innendurchmesser", + "mode": { + "all": "Alle", + "bars": "Bars", + "barsRings": "Barren + Ringe", + "rings": "Ringe", + "wave": "Welle", + "waveRings": "Welle + Ringe" + }, + "ringOpacity": "Ring-Opazität", + "rotationSpeed": "Drehzahl", + "sensitivity": "Empfindlichkeit", + "title": "Visualisierungseinstellungen", + "useCustomColors": "Benutzerdefinierte Farben verwenden", + "useCustomColors-description": "Themenfarben mit benutzerdefinierten Farben überschreiben", + "visualizationMode": "Visualisierungsmodus", + "visualizationMode-description": "Visualisierungsstil wählen", + "waveThickness": "Wellendicke" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/en.json b/noctalia/plugins/fancy-audiovisualizer/i18n/en.json new file mode 100644 index 0000000..f9e8ba2 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/en.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Bar Width", + "bloomIntensity": "Bloom Intensity", + "customPrimaryColor": "Primary Color", + "customSecondaryColor": "Secondary Color", + "description": "Configure the audio visualizer appearance", + "fadeWhenIdle": "Fade When Idle", + "fadeWhenIdle-description": "Fade out visualizer when no audio is playing", + "innerDiameter": "Inner Diameter", + "mode": { + "all": "All", + "bars": "Bars", + "barsRings": "Bars + Rings", + "rings": "Rings", + "wave": "Wave", + "waveRings": "Wave + Rings" + }, + "ringOpacity": "Ring Opacity", + "rotationSpeed": "Rotation Speed", + "sensitivity": "Sensitivity", + "title": "Visualizer Settings", + "useCustomColors": "Use Custom Colors", + "useCustomColors-description": "Override theme colors with custom colors", + "visualizationMode": "Visualization Mode", + "visualizationMode-description": "Choose visualization style", + "waveThickness": "Wave Thickness" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/es.json b/noctalia/plugins/fancy-audiovisualizer/i18n/es.json new file mode 100644 index 0000000..09bb647 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/es.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Ancho de barra", + "bloomIntensity": "Intensidad de floración", + "customPrimaryColor": "Color primario", + "customSecondaryColor": "Color secundario", + "description": "Configurar la apariencia del visualizador de audio", + "fadeWhenIdle": "Desvanecer al estar inactivo", + "fadeWhenIdle-description": "Atenuar el visualizador cuando no se reproduce audio.", + "innerDiameter": "Diámetro interior", + "mode": { + "all": "Todo", + "bars": "Barras", + "barsRings": "Barras + Anillas", + "rings": "Anillos", + "wave": "Ola", + "waveRings": "Onda + Anillos" + }, + "ringOpacity": "Opacidad del anillo", + "rotationSpeed": "Velocidad de rotación", + "sensitivity": "Sensibilidad", + "title": "Ajustes del Visualizador", + "useCustomColors": "Usar colores personalizados", + "useCustomColors-description": "Anular los colores del tema con colores personalizados", + "visualizationMode": "Modo de visualización", + "visualizationMode-description": "Elegir estilo de visualización", + "waveThickness": "Espesor de la onda" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/fr.json b/noctalia/plugins/fancy-audiovisualizer/i18n/fr.json new file mode 100644 index 0000000..5a4c10a --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/fr.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Largeur de la barre", + "bloomIntensity": "Intensité de l'éclat", + "customPrimaryColor": "Couleur primaire", + "customSecondaryColor": "Couleur secondaire", + "description": "Configurer l'apparence du visualiseur audio", + "fadeWhenIdle": "Estomper en cas d'inactivité", + "fadeWhenIdle-description": "Estomper le visualiseur en l'absence de son.", + "innerDiameter": "Diamètre intérieur", + "mode": { + "all": "Tout", + "bars": "Barres", + "barsRings": "Barres + Anneaux", + "rings": "Anneaux", + "wave": "Vague", + "waveRings": "Onde + Anneaux" + }, + "ringOpacity": "Opacité de l'anneau", + "rotationSpeed": "Vitesse de rotation", + "sensitivity": "Sensibilité", + "title": "Paramètres du visualiseur", + "useCustomColors": "Utiliser des couleurs personnalisées", + "useCustomColors-description": "Remplacer les couleurs du thème par des couleurs personnalisées", + "visualizationMode": "Mode de visualisation", + "visualizationMode-description": "Choisir le style de visualisation", + "waveThickness": "Épaisseur de la vague" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/hu.json b/noctalia/plugins/fancy-audiovisualizer/i18n/hu.json new file mode 100644 index 0000000..c2b4a9b --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/hu.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Sávszélesség", + "bloomIntensity": "Virágzás intenzitása", + "customPrimaryColor": "Elsődleges szín", + "customSecondaryColor": "Másodlagos szín", + "description": "Az audio vizualizáló megjelenésének beállítása", + "fadeWhenIdle": "Halványítás tétlenség esetén", + "fadeWhenIdle-description": "A vizualizáció elhalványítása, ha nincs hang lejátszva", + "innerDiameter": "Belső átmérő", + "mode": { + "all": "Összes", + "bars": "Sávok", + "barsRings": "Sávok + Gyűrűk", + "rings": "Gyűrűk", + "wave": "Hullám", + "waveRings": "Hullám + Gyűrűk" + }, + "ringOpacity": "Gyűrű átlátszósága", + "rotationSpeed": "Forgási sebesség", + "sensitivity": "Érzékenység", + "title": "Vizualizációs beállítások", + "useCustomColors": "Egyéni színek használata", + "useCustomColors-description": "A téma színeinek felülírása egyéni színekkel", + "visualizationMode": "Megjelenítési mód", + "visualizationMode-description": "Válassz megjelenítési stílust", + "waveThickness": "Hullámvastagság" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/it.json b/noctalia/plugins/fancy-audiovisualizer/i18n/it.json new file mode 100644 index 0000000..11a75ac --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/it.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Breite der Leiste", + "bloomIntensity": "Intensità Bloom", + "customPrimaryColor": "Ngjyra parësore", + "customSecondaryColor": "Ngjyra dytësore", + "description": "Konfigurieren Sie das Aussehen des Audio-Visualisierers.", + "fadeWhenIdle": "Verblassen im Leerlauf", + "fadeWhenIdle-description": "Vizualizátor eltüntetése, ha nincs hang lejátszva.", + "innerDiameter": "Innendurchmesser", + "mode": { + "all": "Kaikki", + "bars": "Pritličja", + "barsRings": "Stangen + Ringe", + "rings": "Hringar", + "wave": "Val", + "waveRings": "Welle + Ringe" + }, + "ringOpacity": "Neprůhlednost prstence", + "rotationSpeed": "Schnelllaufdrehzahl", + "sensitivity": "Ndjeshmëri", + "title": "Mga Setting ng Visualizer", + "useCustomColors": "Përdorni Ngjyra të Personalizuara", + "useCustomColors-description": "Ngjyrat e personalizuara mbivendosin ngjyrat e temës", + "visualizationMode": "Módszer megjelenítése", + "visualizationMode-description": "Zgjidhni stilin e vizualizimit", + "waveThickness": "Onda-lodiera" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/ja.json b/noctalia/plugins/fancy-audiovisualizer/i18n/ja.json new file mode 100644 index 0000000..f720102 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/ja.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "バーの幅", + "bloomIntensity": "開花強度", + "customPrimaryColor": "原色", + "customSecondaryColor": "二次色", + "description": "オーディオビジュアライザーの外観を設定します。", + "fadeWhenIdle": "アイドル時にフェード", + "fadeWhenIdle-description": "音声が再生されていないときは、ビジュアライザーをフェードアウトする", + "innerDiameter": "内径", + "mode": { + "all": "すべて", + "bars": "バー", + "barsRings": "鉄棒と輪", + "rings": "リング", + "wave": "波", + "waveRings": "波紋 + リング" + }, + "ringOpacity": "リングの不透明度", + "rotationSpeed": "回転速度", + "sensitivity": "感度", + "title": "ビジュアライザー設定", + "useCustomColors": "カスタムカラーを使用する", + "useCustomColors-description": "カスタムカラーでテーマの色をオーバーライドする", + "visualizationMode": "可視化モード", + "visualizationMode-description": "視覚化のスタイルを選択", + "waveThickness": "波厚" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/ku.json b/noctalia/plugins/fancy-audiovisualizer/i18n/ku.json new file mode 100644 index 0000000..6a2ef70 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/ku.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Firehiya Barê", + "bloomIntensity": "Zehfîya Gurtî", + "customPrimaryColor": "Rengê Seretayî", + "customSecondaryColor": "Rengê Duyemîn", + "description": "Xuyakirina dîmenê bihîstwerî yê dengî", + "fadeWhenIdle": "Dema de bêdengiyê vemirîne", + "fadeWhenIdle-description": "Dîmenkerê dema ku tu deng lê nabe, hêdî hêdî winda bike", + "innerDiameter": "Dirêjbûna Hundir", + "mode": { + "all": "Hemû", + "bars": "Bars", + "barsRings": "Bars + Rings", + "rings": "Xelqet", + "wave": "Pêl", + "waveRings": "Pêl + Xelek" + }, + "ringOpacity": "Ronahiya Zengil", + "rotationSpeed": "Leza Şewitandinê", + "sensitivity": "Hesasiyet", + "title": "Mîhengên Dîmenderê", + "useCustomColors": "Rengên Xweser Bikar Bîne", + "useCustomColors-description": "Rengên mijarê bi rengên xwerû biguherîne", + "visualizationMode": "Şêwaza Dîmenkirinê", + "visualizationMode-description": "Şêwaza dîtinê hilbijêre", + "waveThickness": "Qalinîya Pêlê" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/nl.json b/noctalia/plugins/fancy-audiovisualizer/i18n/nl.json new file mode 100644 index 0000000..b3b845e --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/nl.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Balkbreedte", + "bloomIntensity": "Bloei Intensiteit", + "customPrimaryColor": "Primaire kleur", + "customSecondaryColor": "Secundaire kleur", + "description": "Configureer de weergave van de audio visualisatie.", + "fadeWhenIdle": "Vervagen bij inactiviteit", + "fadeWhenIdle-description": "Visualiseerder laten vervagen wanneer er geen audio wordt afgespeeld.", + "innerDiameter": "Binnendiameter", + "mode": { + "all": "Alles", + "bars": "Bars", + "barsRings": "Rekstok + Ringen", + "rings": "Ringen", + "wave": "Golf", + "waveRings": "Golf + Ringen" + }, + "ringOpacity": "Ringondoorzichtigheid", + "rotationSpeed": "Rotatiesnelheid", + "sensitivity": "Gevoeligheid", + "title": "Visualisatie-instellingen", + "useCustomColors": "Aangepaste kleuren gebruiken", + "useCustomColors-description": "Themakleuren overschrijven met aangepaste kleuren", + "visualizationMode": "Visualisatiemodus", + "visualizationMode-description": "Kies visualisatiestijl", + "waveThickness": "Golflaagdikte" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/pl.json b/noctalia/plugins/fancy-audiovisualizer/i18n/pl.json new file mode 100644 index 0000000..d3030df --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/pl.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Szerokość paska", + "bloomIntensity": "Intensywność Rozkwitu", + "customPrimaryColor": "Kolor podstawowy", + "customSecondaryColor": "Kolor dodatkowy", + "description": "Skonfiguruj wygląd wizualizatora dźwięku", + "fadeWhenIdle": "Przyciemnij przy bezczynności", + "fadeWhenIdle-description": "Wycisz wizualizator, gdy nie jest odtwarzany dźwięk", + "innerDiameter": "Średnica wewnętrzna", + "mode": { + "all": "Wszystkie", + "bars": "Paski", + "barsRings": "Paski + Pierścienie", + "rings": "Pierścienie", + "wave": "Fala", + "waveRings": "Fala + Pierścienie" + }, + "ringOpacity": "Krycie pierścienia", + "rotationSpeed": "Prędkość obrotu", + "sensitivity": "Czułość", + "title": "Ustawienia wizualizatora", + "useCustomColors": "Użyj własnych kolorów", + "useCustomColors-description": "Zastąp kolory motywu własnymi kolorami", + "visualizationMode": "Tryb wizualizacji", + "visualizationMode-description": "Wybierz styl wizualizacji", + "waveThickness": "Grubość fali" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/pt.json b/noctalia/plugins/fancy-audiovisualizer/i18n/pt.json new file mode 100644 index 0000000..c3e5e54 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/pt.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Largura da Barra", + "bloomIntensity": "Intensidade do Bloom", + "customPrimaryColor": "Cor primária", + "customSecondaryColor": "Cor secundária", + "description": "Configurar a aparência do visualizador de áudio", + "fadeWhenIdle": "Desaparecer quando inativo", + "fadeWhenIdle-description": "Desvanecer o visualizador quando nenhum áudio estiver sendo reproduzido.", + "innerDiameter": "Diâmetro interno", + "mode": { + "all": "Tudo", + "bars": "Barras", + "barsRings": "Barras + Argolas", + "rings": "Anéis", + "wave": "Onda", + "waveRings": "Onda + Anéis" + }, + "ringOpacity": "Opacidade do Anel", + "rotationSpeed": "Velocidade de rotação", + "sensitivity": "Sensibilidade", + "title": "Configurações do Visualizador", + "useCustomColors": "Usar Cores Personalizadas", + "useCustomColors-description": "Substituir as cores do tema por cores personalizadas", + "visualizationMode": "Modo de Visualização", + "visualizationMode-description": "Escolha o estilo de visualização", + "waveThickness": "Espessura da onda" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/ru.json b/noctalia/plugins/fancy-audiovisualizer/i18n/ru.json new file mode 100644 index 0000000..99537de --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/ru.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Ширина полосы", + "bloomIntensity": "Интенсивность свечения", + "customPrimaryColor": "Основной цвет", + "customSecondaryColor": "Вторичный цвет", + "description": "Настроить внешний вид визуализатора звука", + "fadeWhenIdle": "Затухать в режиме ожидания", + "fadeWhenIdle-description": "Затухать визуализатору при отсутствии воспроизведения аудио.", + "innerDiameter": "Внутренний диаметр", + "mode": { + "all": "Всё", + "bars": "Бары", + "barsRings": "Турники + Кольца", + "rings": "Кольца", + "wave": "Волна", + "waveRings": "Волна + Кольца" + }, + "ringOpacity": "Прозрачность кольца", + "rotationSpeed": "Скорость вращения", + "sensitivity": "Чувствительность", + "title": "Настройки визуализатора", + "useCustomColors": "Использовать пользовательские цвета", + "useCustomColors-description": "Переопределить цвета темы пользовательскими цветами", + "visualizationMode": "Режим визуализации", + "visualizationMode-description": "Выберите стиль визуализации", + "waveThickness": "Толщина волны" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/tr.json b/noctalia/plugins/fancy-audiovisualizer/i18n/tr.json new file mode 100644 index 0000000..2f5b9a5 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/tr.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Çubuk Genişliği", + "bloomIntensity": "Çiçeklenme Yoğunluğu", + "customPrimaryColor": "Ana Renk", + "customSecondaryColor": "İkincil Renk", + "description": "Ses görselleştirici görünümünü yapılandır", + "fadeWhenIdle": "Boşta Kalınca Karart", + "fadeWhenIdle-description": "Ses çalmadığında görselleştiriciyi soldur.", + "innerDiameter": "İç Çap", + "mode": { + "all": "Tüm", + "bars": "Barlar", + "barsRings": "Barfiks Demiri + Halkalar", + "rings": "Yüzükler", + "wave": "Dalga", + "waveRings": "Dalga + Halkalar" + }, + "ringOpacity": "Halka Opaklığı", + "rotationSpeed": "Dönme Hızı", + "sensitivity": "Hassasiyet", + "title": "Görselleştirici Ayarları", + "useCustomColors": "Özel Renkleri Kullan", + "useCustomColors-description": "Tema renklerini özel renklerle geçersiz kıl", + "visualizationMode": "Görselleştirme Modu", + "visualizationMode-description": "Görselleştirme stilini seçin", + "waveThickness": "Dalga Kalınlığı" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/uk-UA.json b/noctalia/plugins/fancy-audiovisualizer/i18n/uk-UA.json new file mode 100644 index 0000000..c142545 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/uk-UA.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Ширина бруска", + "bloomIntensity": "Інтенсивність світіння", + "customPrimaryColor": "Основний колір", + "customSecondaryColor": "Вторинний колір", + "description": "Налаштуйте вигляд аудіовізуалізатора", + "fadeWhenIdle": "Згасати в режимі очікування", + "fadeWhenIdle-description": "Затемнювати візуалізатор, коли не відтворюється звук.", + "innerDiameter": "Внутрішній діаметр", + "mode": { + "all": "Все", + "bars": "Бари", + "barsRings": "Бруси + Кільця", + "rings": "Кільця", + "wave": "Хвиля", + "waveRings": "Хвиля + Кільця" + }, + "ringOpacity": "Прозорість кільця", + "rotationSpeed": "Швидкість обертання", + "sensitivity": "Чутливість", + "title": "Налаштування візуалізатора", + "useCustomColors": "Використовувати власні кольори", + "useCustomColors-description": "Перевизначити кольори теми власними кольорами", + "visualizationMode": "Режим візуалізації", + "visualizationMode-description": "Виберіть стиль візуалізації", + "waveThickness": "Товщина хвилі" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/vi.json b/noctalia/plugins/fancy-audiovisualizer/i18n/vi.json new file mode 100644 index 0000000..566081a --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/vi.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "Độ rộng thanh", + "bloomIntensity": "Cường độ hiệu ứng bloom", + "customPrimaryColor": "Màu chính tùy chỉnh", + "customSecondaryColor": "Màu phụ tùy chỉnh", + "description": "Cấu hình giao diện trình hiển thị âm thanh", + "fadeWhenIdle": "Làm mờ khi không hoạt động", + "fadeWhenIdle-description": "Làm mờ trình hiển thị khi không có âm thanh", + "innerDiameter": "Đường kính bên trong", + "mode": { + "all": "Tất cả", + "bars": "Thanh", + "barsRings": "Thanh + Vòng", + "rings": "Vòng", + "wave": "Sóng", + "waveRings": "Sóng + Vòng" + }, + "ringOpacity": "Độ mờ vòng", + "rotationSpeed": "Tốc độ xoay", + "sensitivity": "Độ nhạy", + "title": "Cài đặt trình hiển thị", + "useCustomColors": "Dùng màu tùy chỉnh", + "useCustomColors-description": "Ghi đè màu giao diện bằng màu tùy chỉnh", + "visualizationMode": "Chế độ hiển thị", + "visualizationMode-description": "Chọn kiểu hiển thị", + "waveThickness": "Độ dày sóng" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/i18n/zh-CN.json b/noctalia/plugins/fancy-audiovisualizer/i18n/zh-CN.json new file mode 100644 index 0000000..84490dd --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/i18n/zh-CN.json @@ -0,0 +1,29 @@ +{ + "settings": { + "barWidth": "条宽", + "bloomIntensity": "光晕强度", + "customPrimaryColor": "原色", + "customSecondaryColor": "间色", + "description": "配置音频可视化效果外观", + "fadeWhenIdle": "空闲时淡出", + "fadeWhenIdle-description": "当没有音频播放时淡出可视化工具", + "innerDiameter": "内径", + "mode": { + "all": "全部", + "bars": "酒吧", + "barsRings": "单杠 + 吊环", + "rings": "戒指", + "wave": "波浪", + "waveRings": "波浪 + 环" + }, + "ringOpacity": "环透明度", + "rotationSpeed": "转速", + "sensitivity": "敏感性", + "title": "可视化设置", + "useCustomColors": "使用自定义颜色", + "useCustomColors-description": "使用自定义颜色覆盖主题颜色", + "visualizationMode": "可视化模式", + "visualizationMode-description": "选择可视化风格", + "waveThickness": "波浪厚度" + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/manifest.json b/noctalia/plugins/fancy-audiovisualizer/manifest.json new file mode 100644 index 0000000..7f12a52 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/manifest.json @@ -0,0 +1,38 @@ +{ + "id": "fancy-audiovisualizer", + "name": "Fancy Audiovisualizer", + "version": "1.1.2", + "minNoctaliaVersion": "4.6.6", + "author": "Noctalia Team", + "official": true, + "license": "MIT", + "repository": "https://github.com/noctalia-dev/noctalia-plugins", + "description": "Lemmy's fancy circular audio visualizer.", + "tags": [ + "Desktop", + "Audio" + ], + "entryPoints": { + "desktopWidget": "DesktopWidget.qml", + "desktopWidgetSettings": "DesktopWidgetSettings.qml" + }, + "dependencies": { + "plugins": [] + }, + "metadata": { + "defaultSettings": { + "sensitivity": 1.5, + "rotationSpeed": 0.5, + "barWidth": 0.6, + "ringOpacity": 0.8, + "bloomIntensity": 0.5, + "visualizationMode": 3, + "waveThickness": 1.0, + "innerDiameter": 0.7, + "fadeWhenIdle": false, + "useCustomColors": false, + "customPrimaryColor": "#6750A4", + "customSecondaryColor": "#625B71" + } + } +} diff --git a/noctalia/plugins/fancy-audiovisualizer/preview.png b/noctalia/plugins/fancy-audiovisualizer/preview.png new file mode 100644 index 0000000..0ef1556 Binary files /dev/null and b/noctalia/plugins/fancy-audiovisualizer/preview.png differ diff --git a/noctalia/plugins/fancy-audiovisualizer/shaders/visualizer.frag b/noctalia/plugins/fancy-audiovisualizer/shaders/visualizer.frag new file mode 100644 index 0000000..51eb9c5 --- /dev/null +++ b/noctalia/plugins/fancy-audiovisualizer/shaders/visualizer.frag @@ -0,0 +1,559 @@ +#version 450 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + float time; + float itemWidth; + float itemHeight; + vec4 primaryColor; + vec4 secondaryColor; + float sensitivity; + float rotationSpeed; + float barWidth; + float ringOpacity; + float cornerRadius; + float bloomIntensity; + float visualizationMode; // 0=bars, 1=wave, 2=rings, 3=bars+rings, 4=wave+rings, 5=all + float waveThickness; + float innerDiameter; +} ubuf; + +// Mode helper functions +bool hasRings() { return ubuf.visualizationMode >= 2.0; } +bool hasBars() { return ubuf.visualizationMode == 0.0 || ubuf.visualizationMode == 3.0 || ubuf.visualizationMode >= 5.0; } +bool hasWave() { return ubuf.visualizationMode == 1.0 || ubuf.visualizationMode == 4.0 || ubuf.visualizationMode >= 5.0; } + +layout(binding = 1) uniform sampler2D source; + +#define TWOPI 6.28318530718 +#define PI 3.14159265359 +#define NBARS 32 + +// Sample audio amplitude at normalized position (0.0-1.0) +float getAudio(float pos) { + return texture(source, vec2(clamp(pos, 0.0, 1.0), 0.5)).r; +} + +// Smoothed audio sampling with interpolation +float smoothAudio(float pos) { + float idx = pos * float(NBARS - 1); + float frac = fract(idx); + float i0 = floor(idx) / float(NBARS - 1); + float i1 = ceil(idx) / float(NBARS - 1); + return mix(getAudio(i0), getAudio(i1), frac) * ubuf.sensitivity; +} + +// Frequency band helpers +float getBass() { return smoothAudio(0.05); } +float getMid() { return smoothAudio(0.3); } +float getHighMid() { return smoothAudio(0.6); } +float getTreble() { return smoothAudio(0.9); } + +// SDF for rounded rectangle +float roundedBoxSDF(vec2 center, vec2 size, float radius) { + vec2 q = abs(center) - size + radius; + return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius; +} + +// Compute polar wave visualization +vec4 computePolarWave(vec2 uv, float iTime, float bass, float mid, float highMid, float treble) { + float aspect = ubuf.itemWidth / ubuf.itemHeight; + vec2 centered = (uv - 0.5) * 2.0; + centered.x *= aspect; + + float theta = atan(centered.y, centered.x); + float d = length(centered); + float innerRadius = ubuf.innerDiameter / 2.0; + float baseRadius = 0.35; // Fixed reference for outer extent + + vec4 color = vec4(0.0); + + // RING SYSTEM + if (hasRings()) { + // Center Waves + if (d < innerRadius * 0.6) { + float wave = mid * 0.8; + float ripple = sin(d * 25.0 + wave * 15.0 - iTime * 2.0); + if (ripple > 0.7) { + float intensity = clamp(mid * 0.6, 0.0, 0.4); + vec4 waveColor = ubuf.secondaryColor * intensity * ubuf.ringOpacity; + color = max(color, waveColor); + } + } + + // Energy Ring + float energyRad = innerRadius * 0.65; + float energyThickness = 0.015 + clamp(highMid * 0.02, 0.0, 0.03); + if (d > energyRad - energyThickness && d < energyRad + energyThickness) { + float segmentAngle = theta * 8.0 + highMid * 3.0 + iTime; + if (mod(segmentAngle, 1.0) < 0.6) { + float alpha = clamp(highMid * 2.0, 0.3, 1.0) * ubuf.ringOpacity; + vec4 energyColor = mix(ubuf.primaryColor, ubuf.secondaryColor, 0.5) * alpha; + color = max(color, energyColor); + } + } + + // Particle Ring + float particleRad = innerRadius * 0.75; + if (d > particleRad - 0.02 && d < particleRad + 0.02) { + float particleAngle = theta + treble * 2.0 + iTime * 0.5; + float particleSpacing = TWOPI / 16.0; + if (mod(particleAngle, particleSpacing) < 0.15) { + float brightness = 0.5 + clamp(treble * 1.5, 0.0, 0.5); + vec4 particleColor = ubuf.secondaryColor * brightness * ubuf.ringOpacity; + color = max(color, particleColor); + } + } + + // Tech Grid Ring + float gridRad = innerRadius * 0.85; + if (d > gridRad - 0.012 && d < gridRad + 0.012) { + float gridAngle = theta + iTime * ubuf.rotationSpeed; + float gridDensity = 0.08 + clamp(mid * 0.05, 0.0, 0.1); + if (mod(gridAngle, 0.2) < gridDensity) { + vec4 gridColor = ubuf.primaryColor * 0.7 * ubuf.ringOpacity; + gridColor.rgb += vec3(0.1, 0.15, 0.2) * clamp(mid, 0.0, 0.8); + color = max(color, gridColor); + } + } + + // Accent Ring + float accentRad = innerRadius * 0.92; + float pulse = clamp(bass * 0.08, 0.0, 0.05); + if (d > accentRad - pulse - 0.008 && d < accentRad + pulse + 0.015) { + float colorShift = clamp(bass * 0.5, 0.0, 1.0); + vec4 ringColor = mix(ubuf.secondaryColor * 0.7, ubuf.primaryColor, colorShift); + ringColor.a = ubuf.ringOpacity; + ringColor.rgb *= 1.0 + bass * 0.3; + color = max(color, ringColor); + } + + // Outer Ring + float outerRad = innerRadius + bass * 0.05; + if (d > outerRad - 0.008 && d < outerRad + 0.008) { + vec4 outerColor = ubuf.primaryColor * ubuf.ringOpacity; + outerColor.rgb += vec3(0.2, 0.3, 0.4) * clamp(treble * 0.5, 0.0, 0.3); + outerColor.rgb *= 1.0 + bass * 0.4; + color = max(color, outerColor); + } + } + + // POLAR WAVE - filled shape with mirrored bands (64 visual bands from 32 samples) + if (hasWave()) { + float adjustedTheta = theta + PI + iTime * ubuf.rotationSpeed * 0.2; + + // Map angle to 0-1 range around the full circle + float normalizedAngle = mod(adjustedTheta, TWOPI) / TWOPI; + + // Mirror: first half (0-0.5) maps to bands 0->31, second half (0.5-1) maps back 31->0 + float mirroredPos = normalizedAngle < 0.5 ? normalizedAngle * 2.0 : (1.0 - normalizedAngle) * 2.0; + + // Catmull-Rom spline interpolation for smooth curve through mirrored bands + float bandPos = mirroredPos * float(NBARS - 1); + float fband1 = floor(bandPos); + float fband0 = max(fband1 - 1.0, 0.0); + float fband2 = min(fband1 + 1.0, float(NBARS - 1)); + float fband3 = min(fband1 + 2.0, float(NBARS - 1)); + + float t = fract(bandPos); + + // Sample the 4 control points + float p0 = getAudio(fband0 / float(NBARS - 1)) * ubuf.sensitivity; + float p1 = getAudio(fband1 / float(NBARS - 1)) * ubuf.sensitivity; + float p2 = getAudio(fband2 / float(NBARS - 1)) * ubuf.sensitivity; + float p3 = getAudio(fband3 / float(NBARS - 1)) * ubuf.sensitivity; + + // Catmull-Rom spline interpolation + float t2 = t * t; + float t3 = t2 * t; + float smoothedAudio = 0.5 * ( + (2.0 * p1) + + (-p0 + p2) * t + + (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 + + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3 + ); + smoothedAudio = max(smoothedAudio, 0.0); + + // Calculate wave radius at this angle + float waveDisplacement = smoothedAudio * 0.5; + float waveRadius = baseRadius + waveDisplacement; // Fixed outer extent + + // Fill the entire area from inner to wave edge + if (d >= innerRadius && d <= waveRadius) { + float fillFactor = (d - innerRadius) / max(waveRadius - innerRadius, 0.001); + + // Gradient from primary at base to accent at edge + vec3 fillColor = mix(ubuf.primaryColor.rgb * 0.8, ubuf.secondaryColor.rgb, fillFactor); + + // Boost brightness with bass + fillColor *= 1.0 + bass * 0.3; + + // Alpha: stronger near the edge, fades toward center + float fillAlpha = mix(0.4, 1.0, fillFactor) * ubuf.waveThickness; + fillAlpha = clamp(fillAlpha, 0.0, 1.0); + + vec4 fill = vec4(fillColor, fillAlpha); + color = max(color, fill); + } + + // Bright edge line at the wave boundary + float edgeThickness = ubuf.waveThickness * 0.025; + float distToEdge = abs(d - waveRadius); + if (distToEdge < edgeThickness) { + float edgeFactor = 1.0 - smoothstep(0.0, edgeThickness, distToEdge); + vec3 edgeColor = ubuf.secondaryColor.rgb * (1.2 + smoothedAudio * 0.5); + + // Add highlight at peaks + if (smoothedAudio > 0.5) { + edgeColor += vec3(0.3, 0.4, 0.5) * (smoothedAudio - 0.5); + } + + vec4 edge = vec4(edgeColor, edgeFactor); + color = max(color, edge); + } + } + + return color; +} + +// Compute visualization color at given UV coordinates +// Returns vec4 with RGB color and alpha +vec4 computeVisualization(vec2 uv, float iTime, float bass, float mid, float highMid, float treble) { + float aspect = ubuf.itemWidth / ubuf.itemHeight; + vec2 centered = (uv - 0.5) * 2.0; + centered.x *= aspect; + + float theta = atan(centered.y, centered.x); + float d = length(centered); + float innerRadius = ubuf.innerDiameter / 2.0; + float baseRadius = 0.35; // Fixed reference for outer extent + + vec4 color = vec4(0.0); + + // RING SYSTEM + if (hasRings()) { + // Center Waves + if (d < innerRadius * 0.6) { + float wave = mid * 0.8; + float ripple = sin(d * 25.0 + wave * 15.0 - iTime * 2.0); + if (ripple > 0.7) { + float intensity = clamp(mid * 0.6, 0.0, 0.4); + vec4 waveColor = ubuf.secondaryColor * intensity * ubuf.ringOpacity; + color = max(color, waveColor); + } + } + + // Energy Ring + float energyRad = innerRadius * 0.65; + float energyThickness = 0.015 + clamp(highMid * 0.02, 0.0, 0.03); + if (d > energyRad - energyThickness && d < energyRad + energyThickness) { + float segmentAngle = theta * 8.0 + highMid * 3.0 + iTime; + if (mod(segmentAngle, 1.0) < 0.6) { + float alpha = clamp(highMid * 2.0, 0.3, 1.0) * ubuf.ringOpacity; + vec4 energyColor = mix(ubuf.primaryColor, ubuf.secondaryColor, 0.5) * alpha; + color = max(color, energyColor); + } + } + + // Particle Ring + float particleRad = innerRadius * 0.75; + if (d > particleRad - 0.02 && d < particleRad + 0.02) { + float particleAngle = theta + treble * 2.0 + iTime * 0.5; + float particleSpacing = TWOPI / 16.0; + if (mod(particleAngle, particleSpacing) < 0.15) { + float brightness = 0.5 + clamp(treble * 1.5, 0.0, 0.5); + vec4 particleColor = ubuf.secondaryColor * brightness * ubuf.ringOpacity; + color = max(color, particleColor); + } + } + + // Tech Grid Ring + float gridRad = innerRadius * 0.85; + if (d > gridRad - 0.012 && d < gridRad + 0.012) { + float gridAngle = theta + iTime * ubuf.rotationSpeed; + float gridDensity = 0.08 + clamp(mid * 0.05, 0.0, 0.1); + if (mod(gridAngle, 0.2) < gridDensity) { + vec4 gridColor = ubuf.primaryColor * 0.7 * ubuf.ringOpacity; + gridColor.rgb += vec3(0.1, 0.15, 0.2) * clamp(mid, 0.0, 0.8); + color = max(color, gridColor); + } + } + + // Accent Ring + float accentRad = innerRadius * 0.92; + float pulse = clamp(bass * 0.08, 0.0, 0.05); + if (d > accentRad - pulse - 0.008 && d < accentRad + pulse + 0.015) { + float colorShift = clamp(bass * 0.5, 0.0, 1.0); + vec4 ringColor = mix(ubuf.secondaryColor * 0.7, ubuf.primaryColor, colorShift); + ringColor.a = ubuf.ringOpacity; + ringColor.rgb *= 1.0 + bass * 0.3; + color = max(color, ringColor); + } + + // Outer Ring + float outerRad = innerRadius + bass * 0.05; + if (d > outerRad - 0.008 && d < outerRad + 0.008) { + vec4 outerColor = ubuf.primaryColor * ubuf.ringOpacity; + outerColor.rgb += vec3(0.2, 0.3, 0.4) * clamp(treble * 0.5, 0.0, 0.3); + outerColor.rgb *= 1.0 + bass * 0.4; + color = max(color, outerColor); + } + } + + // CIRCULAR AUDIO BARS (64 bars, mirrored from 32 audio samples) + if (hasBars() && d > innerRadius) { + // Double the visual bars by using NBARS * 2 + float section = TWOPI / float(NBARS * 2); + float center = section / 2.0; + + float adjustedTheta = theta + PI + iTime * ubuf.rotationSpeed * 0.2; + float m = mod(adjustedTheta, section); + float ym = d * sin(center - m); + + float barW = ubuf.barWidth * 0.015; + if (abs(ym) < barW) { + // Calculate position in the circle (0.0 to 1.0) + float circlePos = mod(adjustedTheta, TWOPI) / TWOPI; + // Mirror: first half (0-0.5) maps to 0-1, second half (0.5-1) maps back 1-0 + float mirroredPos = circlePos < 0.5 ? circlePos * 2.0 : (1.0 - circlePos) * 2.0; + float v = smoothAudio(mirroredPos); + + float wave = sin(theta * 3.0 + mid * 5.0) * clamp(mid * 0.03, 0.0, 0.05); + v += wave; + v = max(v, 0.0); + + float barStart = innerRadius; + float barEnd = baseRadius + v * 0.5; // Fixed outer extent + + if (d >= barStart && d <= barEnd) { + float heightFactor = (d - barStart) / max(barEnd - barStart, 0.001); + + vec3 bottomColor = ubuf.primaryColor.rgb * 0.6; + vec3 middleColor = ubuf.primaryColor.rgb; + vec3 topColor = ubuf.secondaryColor.rgb; + + vec3 barColor; + if (heightFactor < 0.5) { + barColor = mix(bottomColor, middleColor, heightFactor * 2.0); + } else { + barColor = mix(middleColor, topColor, (heightFactor - 0.5) * 2.0); + } + + barColor *= 1.0 + bass * 0.4; + + if (heightFactor > 0.85) { + barColor += vec3(0.3, 0.4, 0.5) * clamp(treble * 0.8, 0.0, 0.5); + } + + float edgeFactor = 1.0 - smoothstep(barW * 0.7, barW, abs(ym)); + vec4 finalBarColor = vec4(barColor, edgeFactor); + color = max(color, finalBarColor); + } + } + } + + return color; +} + +void main() { + // ============================================ + // DYNAMIC CONTENT SCALING + // ============================================ + // Calculate max possible extent from current settings to guarantee + // nothing ever reaches the widget border. + // + // Max visualization radius in centered space [-1,1]: + // Bars/Wave: baseRadius(0.35) + sensitivity * 0.5 + // Rings: innerDiameter/2 + sensitivity * 0.05 (always smaller) + // + // Bloom reach: exp(-dist * minDecayRate / bloomIntensity) decays to + // < 1/255 at dist ≈ bloomIntensity * 1.0 (from solving exp decay + // with worst-case amplitude * multiplier chain) + // + // contentScale maps the widget edge to ±contentScale in centered space, + // so setting it to maxTotalRadius ensures everything fits. + + float maxContentRadius = 0.35 + ubuf.sensitivity * 0.5; + float maxBloomReach = ubuf.bloomIntensity * 1.0; + float maxTotalRadius = maxContentRadius + maxBloomReach; + float contentScale = max(maxTotalRadius * 1.05, 1.0); // 5% safety margin + + vec2 uv = (qt_TexCoord0 - 0.5) * contentScale + 0.5; + + // Convert linear time (0-3600) to smooth oscillation for seamless looping + // sin() ensures perfect continuity when QML wraps from 3600 back to 0 + float iTime = sin(ubuf.time * TWOPI / 3600.0) * 1800.0 + 1800.0; + + // Frequency analysis + float bass = getBass(); + float mid = getMid(); + float highMid = getHighMid(); + float treble = getTreble(); + + // Get base visualization color based on mode + // Mode 0: bars only, Mode 1: wave only, Mode 2: rings only + // Mode 3: bars+rings, Mode 4: wave+rings, Mode 5: all + vec4 color; + if (hasWave() && !hasBars()) { + // Wave only or wave+rings (modes 1, 4) + color = computePolarWave(uv, iTime, bass, mid, highMid, treble); + } else if (hasBars() && !hasWave()) { + // Bars only or bars+rings (modes 0, 3) + color = computeVisualization(uv, iTime, bass, mid, highMid, treble); + } else if (hasWave() && hasBars()) { + // All mode (5) - combine both + vec4 barsColor = computeVisualization(uv, iTime, bass, mid, highMid, treble); + vec4 waveColor = computePolarWave(uv, iTime, bass, mid, highMid, treble); + color = max(barsColor, waveColor); + } else { + // Rings only (mode 2) - still need to call one of them for ring rendering + color = computeVisualization(uv, iTime, bass, mid, highMid, treble); + } + + // ============================================ + // BLOOM EFFECT - Glow based on distance to geometry + // ============================================ + + if (ubuf.bloomIntensity > 0.01 && color.a < 0.01) { + // Only apply bloom where there's no geometry (empty space) + // Find distance to nearest bright element + + float aspect = ubuf.itemWidth / ubuf.itemHeight; + vec2 centered = (uv - 0.5) * 2.0; + centered.x *= aspect; + float d = length(centered); + float theta = atan(centered.y, centered.x); + + float innerRadius = ubuf.innerDiameter / 2.0; + float baseRadius = 0.35; // Fixed reference for outer extent + float glowAmount = 0.0; + vec3 glowColor = vec3(0.0); + + // Glow from rings (if enabled) + if (hasRings()) { + // Outer ring glow + float outerRad = innerRadius + bass * 0.05; + float ringDist = abs(d - outerRad); + float ringGlow = exp(-ringDist * 8.0 / ubuf.bloomIntensity) * (1.0 + bass * 0.5); + glowColor += ubuf.primaryColor.rgb * ringGlow; + glowAmount = max(glowAmount, ringGlow); + + // Accent ring glow + float accentRad = innerRadius * 0.92; + float accentDist = abs(d - accentRad); + float accentGlow = exp(-accentDist * 10.0 / ubuf.bloomIntensity) * (0.7 + bass * 0.3); + glowColor += mix(ubuf.secondaryColor.rgb, ubuf.primaryColor.rgb, 0.5) * accentGlow; + glowAmount = max(glowAmount, accentGlow); + } + + // Glow from visualization (bars or polar wave) + if ((hasBars() || hasWave()) && d > innerRadius * 0.8) { + float adjustedTheta = theta + PI + iTime * ubuf.rotationSpeed * 0.2; + float circlePos = mod(adjustedTheta, TWOPI) / TWOPI; + float mirroredPos = circlePos < 0.5 ? circlePos * 2.0 : (1.0 - circlePos) * 2.0; + float v = smoothAudio(mirroredPos); + + if (hasWave()) { + // Polar wave bloom - Catmull-Rom spline with mirroring matching main render + float mirroredPos = circlePos < 0.5 ? circlePos * 2.0 : (1.0 - circlePos) * 2.0; + float bandPos = mirroredPos * float(NBARS - 1); + float fband1 = floor(bandPos); + float fband0 = max(fband1 - 1.0, 0.0); + float fband2 = min(fband1 + 1.0, float(NBARS - 1)); + float fband3 = min(fband1 + 2.0, float(NBARS - 1)); + + float t = fract(bandPos); + float p0 = getAudio(fband0 / float(NBARS - 1)) * ubuf.sensitivity; + float p1 = getAudio(fband1 / float(NBARS - 1)) * ubuf.sensitivity; + float p2 = getAudio(fband2 / float(NBARS - 1)) * ubuf.sensitivity; + float p3 = getAudio(fband3 / float(NBARS - 1)) * ubuf.sensitivity; + + float t2 = t * t; + float t3 = t2 * t; + float smoothedAudio = 0.5 * ( + (2.0 * p1) + + (-p0 + p2) * t + + (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 + + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3 + ); + smoothedAudio = max(smoothedAudio, 0.0); + + float waveRadius = baseRadius + smoothedAudio * 0.5; + + // Glow from the filled area and edge + float distToWave = abs(d - waveRadius); + float waveGlow = exp(-distToWave * 8.0 / ubuf.bloomIntensity) * smoothedAudio * 2.5; + + vec3 waveGlowColor = mix(ubuf.primaryColor.rgb, ubuf.secondaryColor.rgb, smoothedAudio); + glowColor += waveGlowColor * waveGlow; + glowAmount = max(glowAmount, waveGlow); + } + + if (hasBars()) { + // Bars bloom + float section = TWOPI / float(NBARS * 2); + float m = mod(adjustedTheta, section); + float center = section / 2.0; + + float barAngleDist = min(abs(m - center), section - abs(m - center)); + float barEnd = baseRadius + v * 0.5; // Fixed outer extent + + float radialDist = 0.0; + if (d < innerRadius) { + radialDist = innerRadius - d; + } else if (d > barEnd) { + radialDist = d - barEnd; + } + + float totalDist = length(vec2(barAngleDist * d, radialDist)); + float barGlow = exp(-totalDist * 15.0 / ubuf.bloomIntensity) * v * 2.0; + + float heightFactor = clamp((d - innerRadius) / max(barEnd - innerRadius, 0.001), 0.0, 1.0); + vec3 barGlowColor = mix(ubuf.primaryColor.rgb, ubuf.secondaryColor.rgb, heightFactor); + + glowColor += barGlowColor * barGlow; + glowAmount = max(glowAmount, barGlow); + } + } + + // Apply bloom + float bloomMult = ubuf.bloomIntensity * (1.0 + bass * 0.5); + color.rgb = glowColor * bloomMult; + color.a = glowAmount * bloomMult * 0.6; + + // Clamp to reasonable values + color.rgb = min(color.rgb, vec3(1.5)); + color.a = min(color.a, 0.8); + } + + // ============================================ + // EDGE FADE - radial falloff that only affects the bloom zone + // ============================================ + // Fade starts just past where main content ends (maxContentRadius) + // and reaches zero at the widget edge (contentScale) in centered space. + // This catches bloom tails without affecting the main visualization. + + vec2 fromCenter = (qt_TexCoord0 - 0.5) * 2.0; // -1 to 1 in widget space + float edgeProximity = max(abs(fromCenter.x), abs(fromCenter.y)); // box distance + float fadeStart = maxContentRadius / contentScale; // where content ends in widget space + float edgeFade = 1.0 - smoothstep(fadeStart, 1.0, edgeProximity); + color *= edgeFade; + + // ============================================ + // CORNER MASKING + // ============================================ + + vec2 pixelPos = qt_TexCoord0 * vec2(ubuf.itemWidth, ubuf.itemHeight); + vec2 centerPos = pixelPos - vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5; + vec2 halfSize = vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5; + float dist = roundedBoxSDF(centerPos, halfSize, ubuf.cornerRadius); + float cornerMask = 1.0 - smoothstep(-1.0, 0.0, dist); + + // Final output with premultiplied alpha + float finalAlpha = color.a * ubuf.qt_Opacity * cornerMask; + fragColor = vec4(color.rgb * finalAlpha, finalAlpha); +} diff --git a/noctalia/plugins/fancy-audiovisualizer/shaders/visualizer.frag.qsb b/noctalia/plugins/fancy-audiovisualizer/shaders/visualizer.frag.qsb new file mode 100644 index 0000000..728d8c0 Binary files /dev/null and b/noctalia/plugins/fancy-audiovisualizer/shaders/visualizer.frag.qsb differ diff --git a/noctalia/plugins/file-search/LauncherProvider.qml b/noctalia/plugins/file-search/LauncherProvider.qml new file mode 100644 index 0000000..3ca5e88 --- /dev/null +++ b/noctalia/plugins/file-search/LauncherProvider.qml @@ -0,0 +1,448 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Commons + +Item { + id: root + + property var pluginApi: null + + // Provider metadata + property string name: pluginApi?.tr("provider.name") + property var launcher: null + property bool handleSearch: false + property string supportedLayouts: "list" + property bool supportsAutoPaste: false + + // Search state + property var currentResults: [] + property string currentQuery: "" + property bool searching: false + property int nextRequestId: 0 + property int activeRequestId: 0 + property int fileProcessRequestId: 0 + property int dirProcessRequestId: 0 + property int pendingProcessCount: 0 + property bool currentRequestFailed: false + property var pendingResultsByType: ({ "files": [], "dirs": [] }) + property string fdCommandPath: "" + property bool fdAvailable: false + + // Settings shortcuts + property var cfg: pluginApi?.pluginSettings || ({}) + property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({}) + property bool showHidden: cfg.showHidden ?? defaults.showHidden ?? false + property int maxResults: cfg.maxResults ?? defaults.maxResults ?? 0 + property string fileOpener: cfg.fileOpener ?? defaults.fileOpener ?? "xdg-open" + property string fdCommand: cfg.fdCommand ?? defaults.fdCommand ?? "fd" + property string searchDirectory: cfg.searchDirectory ?? defaults.searchDirectory ?? "~" + + Process { + id: fileSearchProcess + running: false + + stdout: StdioCollector { + id: fileStdoutCollector + } + + stderr: StdioCollector { + id: fileStderrCollector + } + + onExited: function(exitCode) { + root.handleSearchProcessExit("files", fileProcessRequestId, exitCode, fileStdoutCollector.text, fileStderrCollector.text); + } + } + + Process { + id: dirSearchProcess + running: false + + stdout: StdioCollector { + id: dirStdoutCollector + } + + stderr: StdioCollector { + id: dirStderrCollector + } + + onExited: function(exitCode) { + root.handleSearchProcessExit("dirs", dirProcessRequestId, exitCode, dirStdoutCollector.text, dirStderrCollector.text); + } + } + + // Debounce timer for search + Timer { + id: searchDebouncer + interval: 300 + repeat: false + onTriggered: root.executeSearch(root.currentQuery) + } + + function init() { + Logger.i("FileSearch", "Initializing plugin"); + fdCommandPath = fdCommand; + fdAvailable = true; + Logger.i("FileSearch", "Using fd command:", fdCommandPath); + } + + function handleCommand(searchText) { + return searchText.startsWith(">file"); + } + + function commands() { + return [{ + "name": ">file", + "description": pluginApi?.tr("launcher.command.description"), + "icon": "file-search", + "isTablerIcon": true, + "isImage": false, + "onActivate": function() { + launcher.setSearchText(">file "); + } + }]; + } + + function getResults(searchText) { + if (!searchText.startsWith(">file")) { + return []; + } + + if (!fdAvailable) { + return [{ + "name": pluginApi?.tr("launcher.errors.fdNotFound.title"), + "description": pluginApi?.tr("launcher.errors.fdNotFound.description"), + "icon": "alert-circle", + "isTablerIcon": true, + "isImage": false, + "onActivate": function() {} + }]; + } + + var query = searchText.slice(5).trim(); + + if (query === "") { + return [{ + "name": pluginApi?.tr("launcher.prompts.emptyQuery.title"), + "description": pluginApi?.tr("launcher.prompts.emptyQuery.description", { "root": displaySearchDirectory() }), + "icon": "file-search", + "isTablerIcon": true, + "isImage": false, + "onActivate": function() {} + }]; + } + + if (query !== currentQuery) { + currentQuery = query; + activeRequestId = 0; + currentRequestFailed = false; + searching = true; + searchDebouncer.restart(); + + return [{ + "name": pluginApi?.tr("launcher.prompts.searching.title"), + "description": pluginApi?.tr("launcher.prompts.searching.description", { "query": query }), + "icon": "refresh", + "isTablerIcon": true, + "isImage": false, + "onActivate": function() {} + }]; + } + + if (searching) { + return [{ + "name": pluginApi?.tr("launcher.prompts.searching.title"), + "description": pluginApi?.tr("launcher.prompts.searching.description", { "query": query }), + "icon": "refresh", + "isTablerIcon": true, + "isImage": false, + "onActivate": function() {} + }]; + } + + return currentResults; + } + + function executeSearch(query) { + if (!fdAvailable || query === "") { + return; + } + + Logger.d("FileSearch", "Executing search for:", query); + + if (fileSearchProcess.running) { + fileSearchProcess.running = false; + } + if (dirSearchProcess.running) { + dirSearchProcess.running = false; + } + + var expandedDir = expandHomePath(searchDirectory); + + nextRequestId += 1; + var requestId = nextRequestId; + activeRequestId = requestId; + currentRequestFailed = false; + pendingProcessCount = 2; + pendingResultsByType = ({ "files": [], "dirs": [] }); + + var commonArgs = []; + + if (showHidden) { + commonArgs.push("--hidden"); + } + + if (maxResults > 0) { + commonArgs.push("--max-results", maxResults.toString()); + } + commonArgs.push("--base-directory", expandedDir); + commonArgs.push("--absolute-path"); + commonArgs.push("--color", "never"); + commonArgs.push(query); + + var fileArgs = ["--type", "f"].concat(commonArgs); + var dirArgs = ["--type", "d"].concat(commonArgs); + + fileProcessRequestId = requestId; + fileSearchProcess.command = [fdCommandPath].concat(fileArgs); + fileSearchProcess.running = true; + + dirProcessRequestId = requestId; + dirSearchProcess.command = [fdCommandPath].concat(dirArgs); + dirSearchProcess.running = true; + + Logger.d("FileSearch", "Running file command:", fdCommandPath, fileArgs.join(" ")); + Logger.d("FileSearch", "Running dir command:", fdCommandPath, dirArgs.join(" ")); + } + + function handleSearchProcessExit(kind, requestId, exitCode, stdoutText, stderrText) { + if (requestId !== activeRequestId || currentRequestFailed) { + return; + } + + if (exitCode !== 0) { + currentRequestFailed = true; + searching = false; + pendingProcessCount = 0; + Logger.e("FileSearch", "fd command failed with exit code:", exitCode); + Logger.e("FileSearch", "stderr:", stderrText); + currentResults = [{ + "name": pluginApi?.tr("launcher.errors.fdNotFound.title"), + "description": pluginApi?.tr("launcher.errors.fdNotFound.description"), + "icon": "alert-circle", + "isTablerIcon": true, + "onActivate": function() {} + }]; + if (launcher) { + launcher.updateResults(); + } + return; + } + + pendingResultsByType[kind] = parseRawPaths(stdoutText); + pendingProcessCount -= 1; + + if (pendingProcessCount <= 0) { + finalizeSearchResults(requestId); + } + } + + function finalizeSearchResults(requestId) { + if (requestId !== activeRequestId || currentRequestFailed) { + return; + } + + var results = []; + + for (var i = 0; i < pendingResultsByType.dirs.length; i++) { + results.push(formatFileEntry(pendingResultsByType.dirs[i], true)); + } + for (var j = 0; j < pendingResultsByType.files.length; j++) { + results.push(formatFileEntry(pendingResultsByType.files[j], false)); + } + + results = sortResults(results, currentQuery); + + if (maxResults > 0 && results.length > maxResults) { + results = results.slice(0, maxResults); + } + + if (results.length === 0) { + results.push({ + "name": pluginApi?.tr("launcher.prompts.noResults.title"), + "description": pluginApi?.tr("launcher.prompts.noResults.description", { "query": currentQuery }), + "icon": "file-off", + "isTablerIcon": true, + "isImage": false, + "onActivate": function() {} + }); + searching = false; + currentResults = results; + if (launcher) { + launcher.updateResults(); + } + return; + } + + searching = false; + currentResults = results; + Logger.d("FileSearch", "Found", results.length, "results"); + if (launcher) { + launcher.updateResults(); + } + } + + function parseRawPaths(output) { + var trimmed = output.trim(); + if (trimmed === "") { + return []; + } + return trimmed.split("\n").filter(function(line) { return line.trim() !== ""; }); + } + + function expandHomePath(pathValue) { + var expandedPath = pathValue; + if (expandedPath.startsWith("~")) { + expandedPath = Quickshell.env("HOME") + expandedPath.substring(1); + } + return expandedPath; + } + + function displaySearchDirectory() { + var expandedPath = expandHomePath(searchDirectory); + var homeDir = Quickshell.env("HOME"); + if (expandedPath.startsWith(homeDir)) { + return "~" + expandedPath.slice(homeDir.length); + } + return expandedPath; + } + + function sortResults(results, query) { + var queryLower = query.toLowerCase(); + results.sort(function(a, b) { + var rankA = resultRank(a, queryLower); + var rankB = resultRank(b, queryLower); + if (rankA !== rankB) { + return rankA - rankB; + } + + var nameA = (a.name || "").toLowerCase(); + var nameB = (b.name || "").toLowerCase(); + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } + return (a.description || "").length - (b.description || "").length; + }); + return results; + } + + function resultRank(result, queryLower) { + var name = (result.name || "").toLowerCase(); + var description = (result.description || "").toLowerCase(); + var fullPath = description + "/" + name; + + if (name === queryLower) { + return 0; + } + if (name.startsWith(queryLower)) { + return 1; + } + if (name.indexOf(queryLower) !== -1) { + return 2; + } + if (fullPath.indexOf(queryLower) !== -1) { + return 3; + } + return 4; + } + + function formatFileEntry(filePath, forcedIsDirectory) { + var normalizedPath = filePath; + while (normalizedPath.length > 1 && normalizedPath.endsWith("/")) { + normalizedPath = normalizedPath.slice(0, -1); + } + + var isDirectory = (forcedIsDirectory !== undefined) ? forcedIsDirectory : normalizedPath !== filePath; + var parts = normalizedPath.split("/"); + var filename = parts[parts.length - 1]; + var parentPath = parts.slice(0, -1).join("/"); + + if (filename === "") { + filename = normalizedPath; + } + + var homeDir = Quickshell.env("HOME"); + if (parentPath.startsWith(homeDir)) { + parentPath = "~" + parentPath.slice(homeDir.length); + } + + return { + "name": filename, + "description": parentPath, + "icon": isDirectory ? "folder" : getFileIcon(filename), + "isTablerIcon": true, + "isImage": false, + "singleLine": false, + "onActivate": function() { + root.openFile(normalizedPath); + } + }; + } + + function getFileIcon(filename) { + var ext = filename.split(".").pop().toLowerCase(); + + // Images + if (["jpg", "jpeg", "png", "gif", "svg", "webp", "bmp", "ico"].indexOf(ext) !== -1) { + return "photo"; + } + + // Documents + if (["txt", "md", "pdf", "doc", "docx", "odt", "rtf"].indexOf(ext) !== -1) { + return "file-text"; + } + + // Code files + if (["js", "ts", "py", "java", "cpp", "c", "h", "qml", "rs", "go", "rb", "php", "html", "css", "json", "xml", "yaml", "yml"].indexOf(ext) !== -1) { + return "code"; + } + + // Archives + if (["zip", "tar", "gz", "bz2", "xz", "7z", "rar"].indexOf(ext) !== -1) { + return "file-zip"; + } + + // Audio + if (["mp3", "wav", "flac", "ogg", "m4a", "aac", "wma"].indexOf(ext) !== -1) { + return "music"; + } + + // Video + if (["mp4", "mkv", "avi", "mov", "wmv", "flv", "webm"].indexOf(ext) !== -1) { + return "video"; + } + + // Spreadsheets + if (["xls", "xlsx", "ods", "csv"].indexOf(ext) !== -1) { + return "table"; + } + + // Presentations + if (["ppt", "pptx", "odp"].indexOf(ext) !== -1) { + return "presentation"; + } + + // Default + return "file"; + } + + function openFile(filePath) { + Logger.i("FileSearch", "Opening file:", filePath); + Quickshell.execDetached([fileOpener, filePath]); + launcher.close(); + } +} diff --git a/noctalia/plugins/file-search/Main.qml b/noctalia/plugins/file-search/Main.qml new file mode 100644 index 0000000..087fe1e --- /dev/null +++ b/noctalia/plugins/file-search/Main.qml @@ -0,0 +1,68 @@ +import QtQuick +import Quickshell.Io +import qs.Commons +import qs.Services.UI + +Item { + property var pluginApi: null + + Component.onCompleted: { + if (pluginApi) { + Logger.i("FileSearch", "Plugin initialized"); + } + } + + IpcHandler { + target: "plugin:file-search" + + // Toggle launcher in file search mode + function toggle() { + if (!pluginApi) return; + + pluginApi.withCurrentScreen(screen => { + var launcherPanel = PanelService.getPanel("launcherPanel", screen); + if (!launcherPanel) { + Logger.e("FileSearch", "Could not get launcher panel"); + return; + } + + var searchText = launcherPanel.searchText || ""; + var isInFileMode = searchText.startsWith(">file"); + + if (!launcherPanel.isPanelOpen) { + // Launcher closed - open with file search + Logger.i("FileSearch", "Opening launcher in file search mode"); + launcherPanel.open(); + launcherPanel.setSearchText(">file "); + } else if (isInFileMode) { + // Already in file mode - close launcher + Logger.i("FileSearch", "Closing launcher (toggle off)"); + launcherPanel.close(); + } else { + // Launcher open but different mode - switch to file search + Logger.i("FileSearch", "Switching to file search mode"); + launcherPanel.setSearchText(">file "); + } + }); + } + + // Open launcher with file search and specific query + function search(query: string) { + if (!pluginApi) return; + + pluginApi.withCurrentScreen(screen => { + var launcherPanel = PanelService.getPanel("launcherPanel", screen); + if (!launcherPanel) { + Logger.e("FileSearch", "Could not get launcher panel"); + return; + } + + var searchQuery = query || ""; + Logger.i("FileSearch", "Opening launcher with search query:", searchQuery); + + launcherPanel.open(); + launcherPanel.setSearchText(">file " + searchQuery); + }); + } + } +} diff --git a/noctalia/plugins/file-search/README.md b/noctalia/plugins/file-search/README.md new file mode 100644 index 0000000..1d5ef34 --- /dev/null +++ b/noctalia/plugins/file-search/README.md @@ -0,0 +1,25 @@ +# File Search Plugin + +File search from the launcher. + +## Requirements + +This plugin requires [fd](https://github.com/sharkdp/fd#installation) to be installed. + +## Usage + +**Access from launcher:** + +Type `>file` in the Noctalia launcher to activate file search. + +**Toggle file search:** + +```bash +noctalia-shell ipc call plugin:file-search toggle +``` + +**Search with pre-filled query:** + +```bash +noctalia-shell ipc call plugin:file-search search "eko" +``` diff --git a/noctalia/plugins/file-search/Settings.qml b/noctalia/plugins/file-search/Settings.qml new file mode 100644 index 0000000..19efae2 --- /dev/null +++ b/noctalia/plugins/file-search/Settings.qml @@ -0,0 +1,142 @@ +import QtQuick +import QtQuick.Layouts +import qs.Commons +import qs.Widgets + +ColumnLayout { + id: root + + property var pluginApi: null + + property var cfg: pluginApi?.pluginSettings || ({}) + property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({}) + + property bool valueShowHidden: cfg.showHidden ?? defaults.showHidden + property int valueMaxResults: cfg.maxResults ?? defaults.maxResults + property string valueFileOpener: cfg.fileOpener ?? defaults.fileOpener + property string valueFdCommand: cfg.fdCommand ?? defaults.fdCommand + property string valueSearchDirectory: cfg.searchDirectory ?? defaults.searchDirectory + + spacing: Style.marginL + + Component.onCompleted: { + Logger.d("FileSearch", "Settings UI loaded"); + } + + ColumnLayout { + spacing: Style.marginM + Layout.fillWidth: true + + // Show Hidden Files Toggle + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM + + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginS + + NText { + text: pluginApi?.tr("settings.showHidden.label") + font.pointSize: Style.fontSizeL + font.weight: Font.Medium + color: Color.mOnSurface + Layout.fillWidth: true + } + } + + NToggle { + checked: root.valueShowHidden + onToggled: root.valueShowHidden = checked + } + } + + // File Opener Input + NTextInput { + Layout.fillWidth: true + label: pluginApi?.tr("settings.fileOpener.label") + description: pluginApi?.tr("settings.fileOpener.description") + placeholderText: pluginApi?.tr("settings.fileOpener.placeholder") + text: root.valueFileOpener + onTextChanged: root.valueFileOpener = text + } + + // Search Directory Input + NTextInput { + Layout.fillWidth: true + label: pluginApi?.tr("settings.searchDirectory.label") + description: pluginApi?.tr("settings.searchDirectory.description") + placeholderText: pluginApi?.tr("settings.searchDirectory.placeholder") + text: root.valueSearchDirectory + onTextChanged: root.valueSearchDirectory = text + } + + // fd Command Path Input + NTextInput { + Layout.fillWidth: true + label: pluginApi?.tr("settings.fdCommand.label") + description: pluginApi?.tr("settings.fdCommand.description") + placeholderText: pluginApi?.tr("settings.fdCommand.placeholder") + text: root.valueFdCommand + onTextChanged: root.valueFdCommand = text + } + } + + // Max Results Slider + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginS + + RowLayout { + Layout.fillWidth: true + + NText { + text: pluginApi?.tr("settings.maxResults.label") + font.pointSize: Style.fontSizeL + font.weight: Font.Medium + color: Color.mOnSurface + Layout.fillWidth: true + } + + NText { + text: root.valueMaxResults === 0 ? pluginApi?.tr("settings.maxResults.unlimited") : root.valueMaxResults.toString() + font.pointSize: Style.fontSizeM + font.weight: Font.Medium + color: Color.mPrimary + } + } + + NText { + text: pluginApi?.tr("settings.maxResults.description") + font.pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + + NSlider { + Layout.fillWidth: true + from: 0 + to: 200 + stepSize: 10 + value: root.valueMaxResults + onMoved: root.valueMaxResults = Math.round(value) + } + } + + function saveSettings() { + if (!pluginApi) { + Logger.e("FileSearch", "Cannot save settings: pluginApi is null"); + return; + } + + pluginApi.pluginSettings.showHidden = root.valueShowHidden; + pluginApi.pluginSettings.maxResults = root.valueMaxResults; + pluginApi.pluginSettings.fileOpener = root.valueFileOpener; + pluginApi.pluginSettings.searchDirectory = root.valueSearchDirectory; + pluginApi.pluginSettings.fdCommand = root.valueFdCommand; + pluginApi.saveSettings(); + + Logger.d("FileSearch", "Settings saved successfully"); + } +} diff --git a/noctalia/plugins/file-search/i18n/en.json b/noctalia/plugins/file-search/i18n/en.json new file mode 100644 index 0000000..8a56924 --- /dev/null +++ b/noctalia/plugins/file-search/i18n/en.json @@ -0,0 +1,55 @@ +{ + "provider": { + "name": "File Search" + }, + "launcher": { + "command": { + "description": "Search files and folders" + }, + "errors": { + "fdNotFound": { + "title": "fd not found", + "description": "Please install fd to use file search" + } + }, + "prompts": { + "emptyQuery": { + "title": "Type to search files and folders", + "description": "Start typing to search in {{root}}" + }, + "searching": { + "title": "Searching...", + "description": "Looking for files and folders matching: {{query}}" + }, + "noResults": { + "title": "No results found", + "description": "No files or folders matching '{{query}}'" + } + } + }, + "settings": { + "showHidden": { + "label": "Include hidden files" + }, + "fileOpener": { + "label": "File opener command", + "description": "Command used to open files and folders", + "placeholder": "xdg-open" + }, + "searchDirectory": { + "label": "Search directory", + "description": "Directory to search for files and folders", + "placeholder": "~" + }, + "fdCommand": { + "label": "fd command path", + "description": "Command name or full path", + "placeholder": "fd" + }, + "maxResults": { + "label": "Maximum results", + "unlimited": "Unlimited", + "description": "Limit the number of search results displayed (set to 0 for unlimited)" + } + } +} diff --git a/noctalia/plugins/file-search/manifest.json b/noctalia/plugins/file-search/manifest.json new file mode 100644 index 0000000..2e42692 --- /dev/null +++ b/noctalia/plugins/file-search/manifest.json @@ -0,0 +1,31 @@ +{ + "id": "file-search", + "name": "File Search", + "version": "1.0.1", + "minNoctaliaVersion": "4.1.2", + "author": "ericbreh", + "license": "MIT", + "repository": "https://github.com/noctalia-dev/noctalia-plugins", + "description": "File search from the launcher.", + "tags": [ + "Launcher", + "Productivity" + ], + "entryPoints": { + "main": "Main.qml", + "launcherProvider": "LauncherProvider.qml", + "settings": "Settings.qml" + }, + "dependencies": { + "plugins": [] + }, + "metadata": { + "defaultSettings": { + "showHidden": false, + "maxResults": 0, + "fileOpener": "xdg-open", + "searchDirectory": "~", + "fdCommand": "fd" + } + } +} diff --git a/noctalia/plugins/file-search/preview.png b/noctalia/plugins/file-search/preview.png new file mode 100644 index 0000000..e6cf000 Binary files /dev/null and b/noctalia/plugins/file-search/preview.png differ diff --git a/noctalia/plugins/kde-connect/BarWidget.qml b/noctalia/plugins/kde-connect/BarWidget.qml new file mode 100644 index 0000000..6e04602 --- /dev/null +++ b/noctalia/plugins/kde-connect/BarWidget.qml @@ -0,0 +1,53 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import qs.Commons +import qs.Modules.Bar.Extras +import qs.Modules.Panels.Settings +import qs.Services.Hardware +import qs.Services.UI +import qs.Widgets +import "./Services" + +Item { + id: root + + property var pluginApi: null + + property ShellScreen screen + + // Widget properties passed from Bar.qml for per-instance settings + property string widgetId: "" + property string section: "" + property int sectionWidgetIndex: -1 + property int sectionWidgetsCount: 0 + + // Explicit screenName property ensures reactive binding when screen changes + readonly property string screenName: screen ? screen.name : "" + + implicitWidth: pill.width + implicitHeight: pill.height + visible: !hideIfNoDeviceConnected ? true : KDEConnect.anyDevicesConnected; + opacity: (!hideIfNoDeviceConnected ? true : KDEConnect.anyDevicesConnected) ? 1.0 : 0.0; + + property bool hideIfNoDeviceConnected: !(root.pluginApi?.mainInstance?.hideIfNoDeviceConnected ?? false) + + + BarPill { + id: pill + + screen: root.screen + oppositeDirection: BarService.getPillDirection(root) + customIconColor: Color.resolveColorKeyOptional(root.iconColorKey) + customTextColor: Color.resolveColorKeyOptional(root.textColorKey) + icon: KDEConnectUtils.getConnectionStateIcon(KDEConnect.mainDevice, KDEConnect.daemonAvailable) + autoHide: false // Important to be false so we can hover as long as we want + text: !KDEConnect.daemonAvailable || KDEConnect.mainDevice === null || KDEConnect.mainDevice.battery === -1 ? "" : (KDEConnect.mainDevice.battery + "%") + tooltipText: pluginApi?.tr("bar.tooltip") + onClicked: { + if (pluginApi) { + pluginApi.openPanel(root.screen, this); + } + } + } +} diff --git a/noctalia/plugins/kde-connect/ControlCenterWidget.qml b/noctalia/plugins/kde-connect/ControlCenterWidget.qml new file mode 100644 index 0000000..5c41829 --- /dev/null +++ b/noctalia/plugins/kde-connect/ControlCenterWidget.qml @@ -0,0 +1,27 @@ +import QtQuick +import Quickshell +import qs.Widgets +import "./Services" + +NIconButtonHot { + property ShellScreen screen + property var pluginApi: null + + function getTooltip(device) { + const batteryLabel = pluginApi?.tr("panel.card.battery") || "Battery"; + const stateLabel = pluginApi?.tr("control_center.state-label") || "State"; + + const batteryLine = (device !== null && device.reachable && device.paired && device.battery !== -1) ? (batteryLabel + ": " + device.battery + "%\n") : ""; + + const stateKey = KDEConnectUtils.getConnectionStateKey(device, KDEConnect.daemonAvailable); + const stateValue = pluginApi?.tr(stateKey) || "Unknown"; + const stateLine = stateLabel + ": " + stateValue; + + return batteryLine + stateLine; + } + + icon: KDEConnectUtils.getConnectionStateIcon(KDEConnect.mainDevice, KDEConnect.daemonAvailable) + tooltipText: getTooltip(KDEConnect.mainDevice) + + onClicked: pluginApi?.togglePanel(screen, this) +} diff --git a/noctalia/plugins/kde-connect/LICENSE b/noctalia/plugins/kde-connect/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/noctalia/plugins/kde-connect/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/noctalia/plugins/kde-connect/Main.qml b/noctalia/plugins/kde-connect/Main.qml new file mode 100644 index 0000000..fad6414 --- /dev/null +++ b/noctalia/plugins/kde-connect/Main.qml @@ -0,0 +1,24 @@ +import QtQuick +import Quickshell.Io +import qs.Services.UI +import qs.Commons +import "./Services" + +Item { + property var pluginApi: null + + onPluginApiChanged: { + KDEConnect.setMainDevice(pluginApi?.pluginSettings?.mainDeviceId || "") + } + + IpcHandler { + target: "plugin:kde-connect" + function toggle() { + if (pluginApi) { + pluginApi.withCurrentScreen(screen => { + pluginApi.openPanel(screen); + }); + } + } + } +} \ No newline at end of file diff --git a/noctalia/plugins/kde-connect/Panel.qml b/noctalia/plugins/kde-connect/Panel.qml new file mode 100644 index 0000000..dbb479d --- /dev/null +++ b/noctalia/plugins/kde-connect/Panel.qml @@ -0,0 +1,767 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import qs.Commons +import qs.Services.UI +import qs.Widgets +import "./Services" +import Quickshell + +// Panel Component +Item { + id: root + + // Plugin API (injected by PluginPanelSlot) + property var pluginApi: null + + // SmartPanel + readonly property var geometryPlaceholder: panelContainer + + property real contentPreferredWidth: 440 * Style.uiScaleRatio + property real contentPreferredHeight: 360 * Style.uiScaleRatio * Settings.data.ui.fontDefaultScale + + readonly property bool allowAttach: true + + property bool deviceSwitcherOpen: false + + anchors.fill: parent + + Component.onCompleted: { + if (pluginApi) { + Logger.i("KDEConnect", "Panel initialized"); + } + } + + Rectangle { + id: panelContainer + anchors.fill: parent + color: "transparent" + + ColumnLayout { + id: deviceData + + function getBatteryIcon(percentage, isCharging) { + if (percentage < 0) return "battery-exclamation" + if (isCharging) return "battery-charging-2" + if (percentage < 5) return "battery" + if (percentage < 25) return "battery-1" + if (percentage < 50) return "battery-2" + if (percentage < 75) return "battery-3" + return "battery-4" + } + + function getCellularTypeIcon(type) { + switch (type) { + case "5G": + return "signal-5g" + case "LTE": + return "signal-4g" + case "HSPA": + return "signal-h" + case "UMTS": + return "signal-3g" + case "EDGE": + return "signal-e" + case "GPRS": + return "signal-g" + case "GSM": + return "signal-2g" + case "CDMA": + return "signal-3g" + case "CDMA2000": + return "signal-3g" + case "iDEN": + return "signal-2g" + default: + return "wave-square" + } + } + + function getCellularStrengthIcon(strength) { + switch (strength) { + case 0: + return "antenna-bars-1" + case 1: + return "antenna-bars-2" + case 2: + return "antenna-bars-3" + case 3: + return "antenna-bars-4" + case 4: + return "antenna-bars-5" + default: + return "antenna-bars-off" + } + } + + function getSignalStrengthText(strength) { + switch (strength) { + case 0: + return pluginApi?.tr("panel.signal.very-weak") + case 1: + return pluginApi?.tr("panel.signal.weak") + case 2: + return pluginApi?.tr("panel.signal.fair") + case 3: + return pluginApi?.tr("panel.signal.good") + case 4: + return pluginApi?.tr("panel.signal.excellent") + default: + return pluginApi?.tr("panel.unknown") + } + } + + anchors { + fill: parent + margins: Style.marginL + } + spacing: Style.marginL + + NBox { + id: headerBox + Layout.fillWidth: true + implicitHeight: headerRow.implicitHeight + (Style.marginXL) + + RowLayout { + id: headerRow + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + NIcon { + icon: "device-mobile" + pointSize: Style.fontSizeXXL + color: Color.mPrimary + } + + NText { + text: pluginApi?.tr("panel.title") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + } + + NIconButton { + readonly property bool multipleDevices: KDEConnect.devices.length > 1 + icon: "swipe" + tooltipText: multipleDevices ? pluginApi?.tr("panel.other-devices") : "" + baseSize: Style.baseWidgetSize * 0.8 + onClicked: { + deviceSwitcherOpen = !deviceSwitcherOpen + } + enabled: KDEConnect.daemonAvailable && multipleDevices + opacity: multipleDevices ? 1.0 : 0.0 + } + + Item { + Layout.fillWidth: true + } + + NIconButton { + icon: "close" + tooltipText: I18n.tr("common.close") + baseSize: Style.baseWidgetSize * 0.8 + onClicked: { + if (pluginApi) + pluginApi.withCurrentScreen(s => pluginApi.closePanel(s)); + } + } + } + } + + Loader { + Layout.fillWidth: true + Layout.fillHeight: true + active: true + sourceComponent: (KDEConnect.busctlCmd === null || KDEConnect.busctlCmd === "") ? busctlNotFoundCard : + (!KDEConnect.daemonAvailable) ? kdeConnectDaemonNotRunningCard : + (deviceSwitcherOpen) ? deviceSwitcherCard : + (KDEConnect.mainDevice !== null && !KDEConnect.mainDevice.reachable) ? deviceNotReachableCard : + (KDEConnect.mainDevice !== null && KDEConnect.mainDevice.paired) ? deviceConnectedCard : + (KDEConnect.mainDevice !== null && !KDEConnect.mainDevice.paired) ? noDevicePairedCard : + (KDEConnect.devices.length === 0) ? noDevicesAvailableCard : + null + } + + Component { + id: deviceConnectedCard + + Rectangle { + Layout.fillWidth: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + Component.onCompleted: { + root.contentPreferredHeight = headerBox.height + contentLayout.implicitHeight + (Style.marginL * 8) + } + + Component.onDestruction: { + root.contentPreferredHeight = 360 * Style.uiScaleRatio * Settings.data.ui.fontDefaultScale + } + + ColumnLayout { + id: contentLayout + anchors { + fill: parent + margins: Style.marginL + } + spacing: Style.marginL + + RowLayout { + NText { + text: KDEConnect.mainDevice.name + pointSize: Style.fontSizeXXL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + Layout.fillWidth: true + } + + NFilePicker { + id: shareFilePicker + title: pluginApi?.tr("panel.send-file-picker") + selectionMode: "files" + initialPath: Quickshell.env("HOME") + nameFilters: ["*"] + onAccepted: paths => { + if (paths.length > 0) { + for (const path of paths) { + KDEConnect.shareFile(KDEConnect.mainDevice.id, path) + } + } + } + } + + NIconButton { + icon: "device-mobile-search" + tooltipText: pluginApi?.tr("panel.browse-device") + onClicked: { + KDEConnect.browseFiles(KDEConnect.mainDevice.id) + } + } + + NIconButton { + icon: "device-mobile-share" + tooltipText: pluginApi?.tr("panel.send-file") + onClicked: { + shareFilePicker.open() + } + } + + NIconButton { + icon: "radar" + tooltipText: pluginApi?.tr("panel.find-device") + onClicked: { + KDEConnect.triggerFindMyPhone(KDEConnect.mainDevice.id) + } + } + } + + // Device Status + Loader { + Layout.fillWidth: true + Layout.fillHeight: true + active: KDEConnect.mainDevice !== null + sourceComponent: deviceStatsWithPhone + } + + } + + Component { + id: deviceStatsWithPhone + + RowLayout { + spacing: Style.marginM + + Rectangle { + width: 100 * Style.uiScaleRatio + color: "transparent" + Layout.fillHeight: true + Layout.alignment: Qt.AlignCenter + + PhoneDisplay { + Layout.alignment: Qt.AlignCenter + backgroundImage: "" + + onClicked: KDEConnect.wakeUpDevice(KDEConnect.mainDevice.id) + } + } + + Item { + width: Style.marginL + } + + // Stats Grid + GridLayout { + Layout.fillWidth: true + Layout.alignment: Qt.AlignTop + columns: 1 + rowSpacing: Style.marginL + + // Battery Section + RowLayout { + spacing: Style.marginM + + NIcon { + icon: deviceData.getBatteryIcon(KDEConnect.mainDevice.battery, KDEConnect.mainDevice.charging) + pointSize: Style.fontSizeXXXL + applyUiScale: true + color: Color.mOnSurface + } + + ColumnLayout { + spacing: 2 * Style.uiScaleRatio + + NText { + text: pluginApi?.tr("panel.card.battery") + pointSize: Style.fontSizeS + color: Color.mOnSurface + } + + NText { + text: KDEConnect.mainDevice.battery < 0 ? pluginApi?.tr("panel.unknown") : (KDEConnect.mainDevice.battery + "%") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + } + } + } + + // Network Type Section + RowLayout { + spacing: Style.marginM + + NIcon { + icon: deviceData.getCellularTypeIcon(KDEConnect.mainDevice.cellularNetworkType) + pointSize: Style.fontSizeXXXL + applyUiScale: true + color: Color.mOnSurface + } + + ColumnLayout { + spacing: 2 * Style.uiScaleRatio + + NText { + text: pluginApi?.tr("panel.card.network") + pointSize: Style.fontSizeS + color: Color.mOnSurface + } + + NText { + text: KDEConnect.mainDevice.cellularNetworkType || pluginApi?.tr("panel.unknown") + pointSize: Style.fontSizeL + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + } + } + } + + // Signal Strength Section + RowLayout { + spacing: Style.marginM + + NIcon { + icon: deviceData.getCellularStrengthIcon(KDEConnect.mainDevice.cellularNetworkStrength) + pointSize: Style.fontSizeXXXL + applyUiScale: true + color: Color.mOnSurface + } + + ColumnLayout { + spacing: 2 * Style.uiScaleRatio + + NText { + text: pluginApi?.tr("panel.card.signal-strength") + pointSize: Style.fontSizeS + color: Color.mOnSurface + } + + NText { + text: deviceData.getSignalStrengthText(KDEConnect.mainDevice.cellularNetworkStrength) + pointSize: Style.fontSizeL + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + } + } + } + + // Notifications Section + RowLayout { + spacing: Style.marginM + + NIcon { + icon: "notification" + pointSize: Style.fontSizeXXXL + applyUiScale: true + color: Color.mOnSurface + } + + ColumnLayout { + spacing: 2 * Style.uiScaleRatio + + NText { + text: pluginApi?.tr("panel.card.notifications") + pointSize: Style.fontSizeS + color: Color.mOnSurface + } + + NText { + text: KDEConnect.mainDevice.notificationIds.length + pointSize: Style.fontSizeL + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + } + } + } + + } + } + } + } + } + + Component { + id: noDevicePairedCard + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + ColumnLayout { + anchors { + fill: parent + margins: Style.marginL + } + spacing: Style.marginL + + RowLayout { + NText { + text: KDEConnect.mainDevice.name + pointSize: Style.fontSizeXXL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + Layout.fillWidth: true + } + } + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: "transparent" + + ColumnLayout { + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + NButton { + text: pluginApi?.tr("panel.pair") + Layout.alignment: Qt.AlignHCenter + enabled: !KDEConnect.mainDevice.pairRequested + onClicked: { + KDEConnect.requestPairing(KDEConnect.mainDevice.id) + KDEConnect.mainDevice.pairRequested = true + KDEConnect.refreshDevices() + } + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: Style.marginM + + NIcon { + icon: "key" + pointSize: Style.fontSizeXL + color: Color.mOnSurface + Layout.alignment: Qt.AlignHCenter + opacity: KDEConnect.mainDevice.pairRequested ? 1.0 : 0.0 + } + + NText { + text: KDEConnect.mainDevice.verificationKey + Layout.alignment: Qt.AlignHCenter + pointSize: Style.fontSizeL + font.weight: Style.fontWeightBold + color: Color.mOnSurface + opacity: KDEConnect.mainDevice.pairRequested ? 1.0 : 0.0 + } + } + + NBusyIndicator { + Layout.alignment: Qt.AlignHCenter + opacity: KDEConnect.mainDevice.pairRequested ? 1.0 : 0.0 + size: Style.baseWidgetSize * 0.5 + running: KDEConnect.mainDevice.pairRequested + } + } + } + } + } + } + + Component { + id: noDevicesAvailableCard + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + ColumnLayout { + id: emptyState + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + Item { + Layout.fillHeight: true + } + + NIcon { + icon: "device-mobile-off" + pointSize: 48 * Style.uiScaleRatio + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignHCenter + } + + Item {} + + NText { + text: pluginApi?.tr("panel.kdeconnect-error.no-devices") + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + } + + Item { + Layout.fillHeight: true + } + } + } + } + + Component { + id: deviceNotReachableCard + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + ColumnLayout { + id: emptyState + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + Item { + Layout.fillHeight: true + } + + NIcon { + icon: "device-mobile-off" + pointSize: 48 * Style.uiScaleRatio + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignHCenter + } + + Item {} + + NText { + text: pluginApi?.tr("panel.kdeconnect-error.device-unavailable") + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + } + + Item { + + } + + NButton { + text: pluginApi?.tr("panel.unpair") + Layout.alignment: Qt.AlignHCenter + onClicked: { + KDEConnect.unpairDevice(KDEConnect.mainDevice.id) + } + } + + Item { + Layout.fillHeight: true + } + } + } + } + + + Component { + id: busctlNotFoundCard + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + ColumnLayout { + id: emptyState + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + Item { + Layout.fillHeight: true + } + + NIcon { + icon: "exclamation-circle" + pointSize: 48 * Style.uiScaleRatio + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignHCenter + } + + Item {} + + NText { + text: pluginApi?.tr("panel.busctl-error.unavailable-title") + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + NText { + text: pluginApi?.tr("panel.busctl-error.unavailable-desc") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + + Item { + Layout.fillHeight: true + } + } + } + } + + Component { + id: kdeConnectDaemonNotRunningCard + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + ColumnLayout { + id: emptyState + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + Item { + Layout.fillHeight: true + } + + NIcon { + icon: "exclamation-circle" + pointSize: 48 * Style.uiScaleRatio + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignHCenter + } + + Item {} + + NText { + text: pluginApi?.tr("panel.kdeconnect-error.unavailable-title") + pointSize: Style.fontSizeL + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + NText { + text: pluginApi?.tr("panel.kdeconnect-error.unavailable-desc") + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + Layout.alignment: Qt.AlignCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + + Item { + Layout.fillHeight: true + } + } + } + } + + Component { + id: deviceSwitcherCard + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM + + NScrollView{ + horizontalPolicy: ScrollBar.AlwaysOff + verticalPolicy: ScrollBar.AsNeeded + contentWidth: parent.width + reserveScrollbarSpace: false + gradientColor: Color.mSurface + + ColumnLayout { + id: emptyState + anchors.fill: parent + anchors.margins: Style.marginM + spacing: Style.marginM + + Repeater { + model: KDEConnect.devices + Layout.fillWidth: true + + NButton { + required property var modelData + text: modelData.name + Layout.fillWidth: true + backgroundColor: modelData.id === KDEConnect.mainDevice.id ? Color.mSecondary : Color.mPrimary + + onClicked: { + KDEConnect.setMainDevice(modelData.id); + deviceSwitcherOpen = false; + + pluginApi.pluginSettings.mainDeviceId = modelData.id; + pluginApi.saveSettings(); + } + } + } + + Item { + Layout.fillHeight: true + } + } + } + } + } + } + } +} diff --git a/noctalia/plugins/kde-connect/PhoneDisplay.qml b/noctalia/plugins/kde-connect/PhoneDisplay.qml new file mode 100644 index 0000000..fdd5566 --- /dev/null +++ b/noctalia/plugins/kde-connect/PhoneDisplay.qml @@ -0,0 +1,125 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Effects +import qs.Commons +import qs.Widgets + +Rectangle { + id: phoneRoot + + property string backgroundImage: "" // Path to background image + + height: parent ? parent.height : 235 + width: (height / 235) * 115 + + readonly property real scaleFactor: Math.min(width / 115, height / 235) + radius: 20 * scaleFactor + + color: "#1c1c1e" + + signal clicked; + + MultiEffect { + source: phoneRect + anchors.fill: phoneRect + shadowEnabled: true + shadowBlur: phoneRect.scale > 0.97 ? 0.8 : 0.3 + shadowVerticalOffset: phoneRect.scale > 0.97 ? 8 : 2 + shadowColor: "#80000000" + + Behavior on shadowBlur { NumberAnimation { duration: 100 } } + Behavior on shadowVerticalOffset { NumberAnimation { duration: 100 } } + } + + RectangularShadow { + anchors.fill: phoneRect + radius: phoneRoot.radius + blur: 15 + spread: 1 + } + + // Bezel/frame + Rectangle { + id: phoneRect + + Behavior on scale { + NumberAnimation { duration: 100; easing.type: Easing.OutCubic } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + onEntered: phoneRect.scale = 1.02 + onExited: phoneRect.scale = 1.0 + onPressed: phoneRect.scale = 0.99 + onReleased: phoneRect.scale = containsMouse ? 1.02 : 1.0 + onClicked: phoneRoot.clicked(); + } + + anchors { + fill: parent + margins: 2 * phoneRoot.scaleFactor + } + radius: 18 * phoneRoot.scaleFactor + color: "black" + + // Screen + Rectangle { + id: screen + anchors { + fill: parent + margins: 1 * phoneRoot.scaleFactor + } + radius: 17 * phoneRoot.scaleFactor + color: "black" + clip: true + + // Background wallpaper + Image { + anchors.fill: parent + source: phoneRoot.backgroundImage + fillMode: Image.PreserveAspectCrop + visible: phoneRoot.backgroundImage !== "" + + // Fallback gradient if no image + Rectangle { + anchors.fill: parent + visible: phoneRoot.backgroundImage === "" + gradient: Gradient { + GradientStop { position: 0.0; color: "#2c3e50" } + GradientStop { position: 1.0; color: "#34495e" } + } + } + } + + // Dynamic Island + Rectangle { + id: dynamicIsland + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + topMargin: 6 * phoneRoot.scaleFactor + } + width: 48 * phoneRoot.scaleFactor + height: 10 * phoneRoot.scaleFactor + radius: 5 * phoneRoot.scaleFactor + color: "black" + } + + // Home indicator (bottom gesture bar) + Rectangle { + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + bottomMargin: 6 * phoneRoot.scaleFactor + } + width: 40 * phoneRoot.scaleFactor + height: 4 * phoneRoot.scaleFactor + radius: 2 * phoneRoot.scaleFactor + color: "white" + opacity: 0.4 + } + } + } +} diff --git a/noctalia/plugins/kde-connect/README.md b/noctalia/plugins/kde-connect/README.md new file mode 100644 index 0000000..25e1002 --- /dev/null +++ b/noctalia/plugins/kde-connect/README.md @@ -0,0 +1,28 @@ +# Noctalia KDE Connect + +A Plugin integrating your mobile devices into a panel using KDEConnect + +> [!IMPORTANT] +> Please submit any Pull Requests to https://github.com/WerWolv/noctalia-kde-connect and **NOT** to the noctalia-plugins repository! + +## Features +- Support for multiple devices +- Panel to manage all devices + - Current battery charge and if the device is plugged in + - Mobile network connection state + - Number of notifications + - Wake up the device from the panel + - Browse files on the device + - Send files to the device + - Make the device ring + +## Requirements + +- `kdeconnectd` needs to be running which can be installed by setting up the official KDE Connect app + - In case it's not getting started by default, you might need to configure a systemd service for it +- Certain functionality will only work when enabling the right plugins on the device. Otherwise, they might not work or simply display "Unknown" +- The "Browse files" option mounts the device over SFTP using sshfs. Make sure you have `libfuse` and `sshfs` installed + - If clicking the button just opens the file browser without displaying anything, make sure you have the option enabled on your phone and that your file browser has permissions to access that path. + - If your file browser is sandboxed (e.g. when installed as a Flatpak or Snap), it's possible that it won't have access. Install it through the package manager instead + - On some systems kdeconnect's URL handler isn't configured properly and the button will instead just open your web browser + - In that case you can override the file handler by running `xdg-mime default org.kde.dolphin.desktop x-scheme-handler/kdeconnect` diff --git a/noctalia/plugins/kde-connect/Services/KDEConnect.qml b/noctalia/plugins/kde-connect/Services/KDEConnect.qml new file mode 100644 index 0000000..e7092a8 --- /dev/null +++ b/noctalia/plugins/kde-connect/Services/KDEConnect.qml @@ -0,0 +1,457 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Commons + +QtObject { + id: root + + property list devices: [] + property bool daemonAvailable: false + property int pendingDeviceCount: 0 + property list pendingDevices: [] + + property var mainDevice: null + property string mainDeviceId: "" + property string busctlCmd: "" + + property bool anyDevicesConnected: false; + + onDevicesChanged: { + setMainDevice(root.mainDeviceId) + } + + Component.onCompleted: { + checkDaemon(); + } + + // Check if KDE Connect daemon is available + function checkDaemon(): void { + detectBusctlProc.running = true; + } + + // Refresh the list of devices + function refreshDevices(): void { + getDevicesProc.running = true; + } + + function setMainDevice(deviceId: string): void { + root.mainDeviceId = deviceId; + updateMainDevice(false); + } + + function updateMainDevice(checkReachable) { + let newMain; + if (checkReachable) { + newMain = devices.find((device) => device.id === root.mainDeviceId && device.reachable); + if (newMain === undefined) + newMain = devices.find((device) => device.reachable); + if (newMain === undefined) + newMain = devices.length === 0 ? null : devices[0]; + } else { + newMain = devices.find((device) => device.id === root.mainDeviceId); + if (newMain === undefined) + newMain = devices.length === 0 ? null : devices[0]; + } + + if (root.mainDevice !== newMain) { + root.mainDevice = newMain; + } + + anyDevicesConnected = devices.find((device) => device.reachable) !== undefined; + } + + function triggerFindMyPhone(deviceId: string): void { + const proc = findMyPhoneComponent.createObject(root, { deviceId: deviceId }); + proc.running = true; + } + + function browseFiles(deviceId: string): void { + const proc = browseFilesComponent.createObject(root, { deviceId: deviceId }); + proc.running = true; + } + + // Share a file with a device + function shareFile(deviceId: string, filePath: string): void { + var proc = shareComponent.createObject(root, { + deviceId: deviceId, + filePath: filePath + }); + proc.running = true; + } + + function requestPairing(deviceId: string): void { + const proc = requestPairingComponent.createObject(root, { deviceId: deviceId }); + proc.running = true; + } + + function unpairDevice(deviceId: string): void { + const proc = unpairingComponent.createObject(root, { deviceId: deviceId }); + proc.running = true; + } + + function wakeUpDevice(deviceId: string): void { + const proc = wakeUpDeviceComponent.createObject(root, { deviceId: deviceId }); + proc.running = true; + } + + function busctlCall(obj, itf, method, params = []) { + let result = [ root.busctlCmd, "--user", "call", "--json=short", "org.kde.kdeconnect", obj, itf, method ]; + return result.concat(params); + } + + function busctlGet(obj, itf, prop) { + return [ root.busctlCmd, "--user", "get-property", "--json=short", "org.kde.kdeconnect", obj, itf, prop ]; + } + + function busctlData(text) { + if (text === "") + return ""; + + try { + let result = JSON.parse(text)?.data; + if (Array.isArray(result) && Array.isArray(result[0])) + return result[0] + else + return result; + } catch (e) { + Logger.e("KDEConnect", "Failed to parse busctl response: ", text) + return null; + } + } + + property Process detectBusctlProc: Process { + command: ["which", "busctl"] + stdout: StdioCollector { + onStreamFinished: { + if (root.busctlCmd !== "") { + root.daemonCheckProc.running = true + return + } + + let location = text.trim() + if (location !== "") { + root.busctlCmd = location + root.daemonCheckProc.running = true + Logger.i("KDEConnect", "Found busctl command:", location) + } + } + } + } + + // Check daemon + property Process daemonCheckProc: Process { + command: [root.busctlCmd, "--user", "status", "org.kde.kdeconnect"] + onExited: (exitCode, exitStatus) => { + root.daemonAvailable = exitCode == 0; + if (root.daemonAvailable) { + forceOnNetworkChange.running = true; + } else { + root.devices = [] + root.mainDevice = null + } + } + } + + property Process forceOnNetworkChange: Process { + command: busctlCall("/modules/kdeconnect", "org.kde.kdeconnect.daemon", "forceOnNetworkChange") + stdout: StdioCollector { + onStreamFinished: { + getDevicesProc.running = true; + } + } +} + + // Get device list + property Process getDevicesProc: Process { + command: busctlCall("/modules/kdeconnect", "org.kde.kdeconnect.daemon", "devices") + stdout: StdioCollector { + onStreamFinished: { + const deviceIds = busctlData(text); + + root.pendingDevices = []; + root.pendingDeviceCount = deviceIds.length; + + deviceIds.forEach(deviceId => { + const loader = deviceLoaderComponent.createObject(root, { deviceId: deviceId }); + loader.start(); + }); + } + } + } + + // Component that loads all info for a single device + property Component deviceLoaderComponent: Component { + QtObject { + id: loader + property string deviceId: "" + property var deviceData: ({ + id: deviceId, + name: "", + reachable: false, + paired: false, + pairRequested: false, + verificationKey: "", + charging: false, + battery: -1, + cellularNetworkType: "", + cellularNetworkStrength: -1, + notificationIds: [] + }) + + function start() { + nameProc.running = true + } + + property Process nameProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId, "org.kde.kdeconnect.device", "name") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.name = busctlData(text); + + reachableProc.running = true; + } + } + } + + property Process reachableProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId, "org.kde.kdeconnect.device", "isReachable") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.reachable = busctlData(text); + + pairingRequestedProc.running = true; + } + } + } + + property Process pairingRequestedProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId, "org.kde.kdeconnect.device", "isPairRequested") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.pairRequested = busctlData(text); + + verificationKeyProc.running = true; + } + } + } + + property Process verificationKeyProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId, "org.kde.kdeconnect.device", "verificationKey") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.verificationKey = busctlData(text); + + pairedProc.running = true; + } + } + } + + property Process pairedProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId, "org.kde.kdeconnect.device", "isPaired") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.paired = busctlData(text); + + if (loader.deviceData.paired) + activeNotificationsProc.running = true; + else + finalize() + } + } + } + + property Process activeNotificationsProc: Process { + command: busctlCall("/modules/kdeconnect/devices/" + loader.deviceId + "/notifications", "org.kde.kdeconnect.device.notifications", "activeNotifications"); + stdout: StdioCollector { + onStreamFinished: { + let ids = busctlData(text); + loader.deviceData.notificationIds = ids + + cellularNetworkTypeProc.running = true; + } + } + } + + property Process cellularNetworkTypeProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId + "/connectivity_report", "org.kde.kdeconnect.device.connectivity_report", "cellularNetworkType") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.cellularNetworkType = busctlData(text); + cellularNetworkStrengthProc.running = true; + } + } + } + + property Process cellularNetworkStrengthProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId + "/connectivity_report", "org.kde.kdeconnect.device.connectivity_report", "cellularNetworkStrength") + stdout: StdioCollector { + onStreamFinished: { + const strength = busctlData(text); + loader.deviceData.cellularNetworkStrength = strength; + isChargingProc.running = true; + } + } + } + + property Process isChargingProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId + "/battery", "org.kde.kdeconnect.device.battery", "isCharging") + stdout: StdioCollector { + onStreamFinished: { + loader.deviceData.charging = busctlData(text); + batteryProc.running = true; + } + } + } + + property Process batteryProc: Process { + command: busctlGet("/modules/kdeconnect/devices/" + loader.deviceId + "/battery", "org.kde.kdeconnect.device.battery", "charge") + stdout: StdioCollector { + onStreamFinished: { + const charge = busctlData(text); + if (!isNaN(charge)) { + loader.deviceData.battery = charge; + } + + finalize(); + } + } + } + + function finalize() { + root.pendingDevices = root.pendingDevices.concat([loader.deviceData]); + + if (root.pendingDevices.length === root.pendingDeviceCount) { + let newDevices = root.pendingDevices + newDevices.sort((a, b) => a.name.localeCompare(b.name)) + + let prevMainDevice = root.devices.find((device) => device.id === root.mainDeviceId); + let newMainDevice = newDevices.find((device) => device.id === root.mainDeviceId); + + let deviceNotReachableAnymore = + prevMainDevice === undefined || + ( + (prevMainDevice?.reachable ?? false) && + !(newMainDevice?.reachable ?? false) + ) || + ( + (prevMainDevice?.paired ?? false) && + !(newMainDevice?.paired ?? false) + ) + + root.devices = newDevices + root.pendingDevices = [] + updateMainDevice(deviceNotReachableAnymore); + } + + loader.destroy(); + } + } + } + + // FindMyPhone component + property Component findMyPhoneComponent: Component { + Process { + id: proc + property string deviceId: "" + command: busctlCall("/modules/kdeconnect/devices/" + deviceId + "/findmyphone", "org.kde.kdeconnect.device.findmyphone", "ring") + stdout: StdioCollector { + onStreamFinished: proc.destroy() + } + } + } + + // SFTP Browse component + property Component browseFilesComponent: Component { + Process { + id: mountProc + property string deviceId: "" + command: busctlCall("/modules/kdeconnect/devices/" + deviceId + "/sftp", "org.kde.kdeconnect.device.sftp", "mountAndWait") + stdout: StdioCollector { + onStreamFinished: rootDirProc.running = true + } + + property Process rootDirProc: Process { + command: busctlCall("/modules/kdeconnect/devices/" + mountProc.deviceId + "/sftp", "org.kde.kdeconnect.device.sftp", "getDirectories") + stdout: StdioCollector { + onStreamFinished: { + const dirs = busctlData(text); + const path = Object.keys(dirs[0])[0]; + if (!Qt.openUrlExternally("file://" + path)) { + Logger.e("KDEConnect", "Failed to open file manager for path:", path); + } + + mountProc.destroy(); + } + } + } + } + } + + // Request Pairing Component + property Component requestPairingComponent: Component { + Process { + id: proc + property string deviceId: "" + command: busctlCall("/modules/kdeconnect/devices/" + deviceId, "org.kde.kdeconnect.device", "requestPairing") + stdout: StdioCollector { + onStreamFinished: proc.destroy() + } + } + } + + // Unpairing Component + property Component unpairingComponent: Component { + Process { + id: proc + property string deviceId: "" + command: busctlCall("/modules/kdeconnect/devices/" + deviceId, "org.kde.kdeconnect.device", "unpair") + stdout: StdioCollector { + onStreamFinished: { + KDEConnect.refreshDevices() + proc.destroy() + } + } + } + } + + // Wake up Device Component + property Component wakeUpDeviceComponent: Component { + Process { + id: proc + property string deviceId: "" + command: busctlCall("/modules/kdeconnect/devices/" + deviceId + "/remotecontrol", "org.kde.kdeconnect.device.remotecontrol", "sendCommand", [ "a{sv}", "1", "singleclick", "b", "true" ]) + stdout: StdioCollector { + onStreamFinished: { + KDEConnect.refreshDevices() + proc.destroy() + } + } + } + } + + // Share file component + property Component shareComponent: Component { + Process { + id: proc + property string deviceId: "" + property string filePath: "" + command: busctlCall("/modules/kdeconnect/devices/" + deviceId + "/share", "org.kde.kdeconnect.device.share", "shareUrl", [ "file://" + filePath ]) + stdout: StdioCollector { + onStreamFinished: { + proc.destroy() + } + } + } + } + + // Periodic refresh timer + property Timer refreshTimer: Timer { + interval: 5000 + running: true + repeat: true + onTriggered: root.checkDaemon() + } +} \ No newline at end of file diff --git a/noctalia/plugins/kde-connect/Services/KDEConnectUtils.qml b/noctalia/plugins/kde-connect/Services/KDEConnectUtils.qml new file mode 100644 index 0000000..158e8a1 --- /dev/null +++ b/noctalia/plugins/kde-connect/Services/KDEConnectUtils.qml @@ -0,0 +1,40 @@ +pragma Singleton + +import QtQuick + +QtObject { + function getConnectionStateIcon(device, daemonAvailable) { + if (!daemonAvailable) + return "exclamation-circle"; + + if (device === null || !device.reachable) + return "device-mobile-off"; + + if (device.battery >= 0 && device.battery < 10) + return "device-mobile-exclamation" + + if (device.notificationIds.length > 0) + return "device-mobile-message"; + else if (device.charging) + return "device-mobile-bolt"; + else + return "device-mobile"; + } + + // Returns raw state keys for translation + function getConnectionStateKey(device, daemonAvailable) { + if (!daemonAvailable) + return "control_center.state.unavailable"; + + if (device === null) + return "control_center.state.no-device"; + + if (!device.reachable) + return "control_center.state.disconnected"; + + if (!device.paired) + return "control_center.state.not-paired"; + + return "control_center.state.connected"; + } +} diff --git a/noctalia/plugins/kde-connect/Services/qmldir b/noctalia/plugins/kde-connect/Services/qmldir new file mode 100644 index 0000000..c9770c0 --- /dev/null +++ b/noctalia/plugins/kde-connect/Services/qmldir @@ -0,0 +1,2 @@ +singleton KDEConnect 1.0 KDEConnect.qml +singleton KDEConnectUtils 1.0 KDEConnectUtils.qml diff --git a/noctalia/plugins/kde-connect/Settings.qml b/noctalia/plugins/kde-connect/Settings.qml new file mode 100644 index 0000000..129922c --- /dev/null +++ b/noctalia/plugins/kde-connect/Settings.qml @@ -0,0 +1,44 @@ +import QtQuick +import QtQuick.Layouts +import qs.Commons +import qs.Widgets + +ColumnLayout { + id: root + + property var pluginApi: null + + property var cfg: pluginApi?.pluginSettings || ({}) + property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({}) + + property bool hideIfNoDeviceConnected: pluginApi?.mainInstance?.hideIfNoDeviceConnected ?? (pluginApi?.pluginSettings?.hideIfNoDeviceConnected ?? false) + + spacing: Style.marginL + + ColumnLayout { + spacing: Style.marginM + Layout.fillWidth: true + + NToggle { + label: pluginApi?.tr("settings.no-device-connected-hide.label") + description: pluginApi?.tr("settings.no-device-connected-hide.description") + + checked: root.hideIfNoDeviceConnected + onToggled: function(checked) { + root.hideIfNoDeviceConnected = checked + } + } + } + + function saveSettings() { + if (!pluginApi) { + Logger.e("KDEConnect", "Cannot save settings: pluginApi is null"); + return; + } + + pluginApi.pluginSettings.hideIfNoDeviceConnected = root.hideIfNoDeviceConnected; + pluginApi.saveSettings(); + + Logger.d("KDEConnect", "Settings saved successfully"); + } +} \ No newline at end of file diff --git a/noctalia/plugins/kde-connect/i18n/de.json b/noctalia/plugins/kde-connect/i18n/de.json new file mode 100644 index 0000000..6d5376c --- /dev/null +++ b/noctalia/plugins/kde-connect/i18n/de.json @@ -0,0 +1,55 @@ +{ + "panel": { + "title": "Verbundene Geräte", + "signal": { + "very-weak": "Sehr schwach", + "weak": "Schwach", + "fair": "Okay", + "good": "Gut", + "excellent": "Ausgezeichnet" + }, + "unknown": "Unbekannt", + "card": { + "battery": "Akkustand", + "network": "Netzwerk", + "signal-strength": "Signalstärke", + "notifications": "Benachrichtigungen" + }, + "other-devices": "Andere Geräte", + "send-file-picker": "Datei zum Senden an Gerät auswählen", + "send-file": "Datei senden", + "browse-files": "Dateien auf Gerät durchsuchen", + "find-device": "Mein Gerät suchen", + "pair": "Mit Gerät koppeln", + "unpair": "Gerät entkoppeln", + "kdeconnect-error": { + "no-devices": "Kein Gerät mit KDE Connect gefunden", + "unavailable-title": "kdeconnectd scheint nicht zu laufen!", + "unavailable-desc": "Sicherstellen, dass die KDE Connect-Anwendung auf Ihrem System installiert ist und dass der kdeconnectd-Daemon gestartet wurde", + "device-unavailable": "Das Gerät ist derzeit nicht verfügbar." + }, + "busctl-error": { + "unavailable-title": "busctl kann nicht gefunden werden!", + "unavailable-desc": "Stelle sicher, dass busctl (teil von systemd) auf deinem System installiert ist" + } + }, + "bar": { + "tooltip": "Verbundene Geräte" + }, + "control_center": { + "state-label": "Status", + "state": { + "connected": "Verbunden", + "disconnected": "Getrennt", + "unavailable": "Nicht verfügbar", + "no-device": "Kein Gerät", + "not-paired": "Nicht gekoppelt" + } + }, + "settings": { + "no-device-connected-hide": { + "label": "Verstecken wenn nicht verbunden", + "description": "Verstecke den Knopf in der Leiste, wenn kein Gerät verbunden ist" + } + } +} diff --git a/noctalia/plugins/kde-connect/i18n/en.json b/noctalia/plugins/kde-connect/i18n/en.json new file mode 100644 index 0000000..2acc2ee --- /dev/null +++ b/noctalia/plugins/kde-connect/i18n/en.json @@ -0,0 +1,55 @@ +{ + "panel": { + "title": "Connected Devices", + "signal": { + "very-weak": "Very Weak", + "weak": "Weak", + "fair": "Fair", + "good": "Good", + "excellent": "Excellent" + }, + "unknown": "Unknown", + "card": { + "battery": "Battery", + "network": "Network", + "signal-strength": "Signal Strength", + "notifications": "Notifications" + }, + "other-devices": "Other Devices", + "send-file-picker": "Pick file to send to device", + "send-file": "Send File", + "browse-device": "Browse Device Files", + "find-device": "Find my Device", + "pair": "Pair with Device", + "unpair": "Unpair Device", + "kdeconnect-error": { + "no-devices": "No device running KDE Connect found", + "unavailable-title": "kdeconnectd does not seem to be running!", + "unavailable-desc": "Make sure you've installed the KDE Connect Application on your system and that it has started the kdeconnectd daemon", + "device-unavailable": "Device is currently unavailable" + }, + "busctl-error": { + "unavailable-title": "busctl cannot be found!", + "unavailable-desc": "Make sure busctl (part of systemd) is installed on your system" + } + }, + "bar": { + "tooltip": "Connected Devices" + }, + "control_center": { + "state-label": "State", + "state": { + "connected": "Connected", + "disconnected": "Disconnected", + "unavailable": "Unavailable", + "no-device": "No device", + "not-paired": "Not paired" + } + }, + "settings": { + "no-device-connected-hide": { + "label": "Hide if unavailable", + "description": "Hide the bar button entirely if no device is connected" + } + } +} diff --git a/noctalia/plugins/kde-connect/i18n/fr.json b/noctalia/plugins/kde-connect/i18n/fr.json new file mode 100644 index 0000000..9571791 --- /dev/null +++ b/noctalia/plugins/kde-connect/i18n/fr.json @@ -0,0 +1,44 @@ +{ + "panel": { + "title": "Appareils connectés", + "signal": { + "very-weak": "Très faible", + "weak": "Faible", + "fair": "Moyen", + "good": "Bon", + "excellent": "Excellent" + }, + "unknown": "Inconnu", + "card": { + "battery": "Batterie", + "network": "Réseau", + "signal-strength": "Force du signal", + "notifications": "Notifications" + }, + "other-devices": "Autres appareils", + "send-file-picker": "Choisir un fichier à envoyer à l'appareil", + "send-file": "Envoyer un fichier", + "find-device": "Trouver mon appareil", + "pair": "Coupler avec l'appareil", + "unpair": "Découpler l'appareil", + "kdeconnect-error": { + "no-devices": "Aucun appareil exécutant KDE Connect trouvé", + "unavailable-title": "kdeconnectd ne semble pas être en cours d'exécution !", + "unavailable-desc": "Assurez-vous d'avoir installé l'application KDE Connect sur votre système et qu'elle a démarré le démon kdeconnectd", + "device-unavailable": "L'appareil est actuellement indisponible" + } + }, + "bar": { + "tooltip": "Appareils connectés" + }, + "control_center": { + "state-label": "État", + "state": { + "connected": "Connecté", + "disconnected": "Déconnecté", + "unavailable": "Indisponible", + "no-device": "Aucun appareil", + "not-paired": "Non couplé" + } + } +} diff --git a/noctalia/plugins/kde-connect/i18n/pt.json b/noctalia/plugins/kde-connect/i18n/pt.json new file mode 100644 index 0000000..25e252b --- /dev/null +++ b/noctalia/plugins/kde-connect/i18n/pt.json @@ -0,0 +1,48 @@ +{ + "panel": { + "title": "Dispositivos Conectados", + "signal": { + "very-weak": "Muito Fraco", + "weak": "Fraco", + "fair": "Justo", + "good": "Bom", + "excellent": "Excelente" + }, + "unknown": "Desconhecido", + "card": { + "battery": "Bateria", + "network": "Rede", + "signal-strength": "Intensidade do Signal", + "notifications": "Notificações" + }, + "other-devices": "Outros Dispositivos", + "send-file-picker": "Selecione o arquivo para enviar ao dispositivo", + "send-file": "Enviar Arquivo", + "find-device": "Encontrar meu Dispositivo", + "pair": "Emparelhar meu Dispositivo", + "unpair": "Desemparelhar meu dispositivo", + "kdeconnect-error": { + "no-devices": "Nenhum dispositivo executando o KDE Connect encontrado", + "unavailable-title": "O kdeconnectd parece não estar em execução!", + "unavailable-desc": "Certifique-se de ter instalado o aplicativo KDE Connect em seu sistema e de que o daemon kdeconnectd esteja em execução", + "device-unavailable": "O dispositivo está indisponível no momento" + }, + "busctl-error": { + "unavailable-title": "O busctl não foi encontrado!", + "unavailable-desc": "Certifique-se de que o busctl esteja instalado em seu sistema" + } + }, + "bar": { + "tooltip": "Dispositivos conectados" + }, + "control_center": { + "state-label": "Estado", + "state": { + "connected": "Conectado", + "disconnected": "Desconectado", + "unavailable": "Indisponível", + "no-device": "Nenhum dispositivo", + "not-paired": "Não pareado" + } + } +} diff --git a/noctalia/plugins/kde-connect/i18n/ru.json b/noctalia/plugins/kde-connect/i18n/ru.json new file mode 100644 index 0000000..0d8d1d3 --- /dev/null +++ b/noctalia/plugins/kde-connect/i18n/ru.json @@ -0,0 +1,49 @@ +{ + "panel": { + "title": "Подключённые устройства", + "signal": { + "very-weak": "Очень слабое", + "weak": "Слабое", + "fair": "Среднее", + "good": "Хорошее", + "excellent": "Отличное" + }, + "unknown": "Неизвестно", + "card": { + "battery": "Батарея", + "network": "Сеть", + "signal-strength": "Качество сигнала", + "notifications": "Уведомления" + }, + "other-devices": "Другие устройства", + "send-file-picker": "Выберите файл для отправки на устройство", + "send-file": "Отправить файл", + "browse-device": "Просмотреть файлы на устройстве", + "find-device": "Найти моё устройство", + "pair": "Сопрячь устройство", + "unpair": "Разорвать сопряжение", + "kdeconnect-error": { + "no-devices": "Устройства с KDE Connect не обнаружены", + "unavailable-title": "Похоже, kdeconnectd не запущен!", + "unavailable-desc": "Убедитесь, что KDE Connect установлен в системе и служба kdeconnectd работает.", + "device-unavailable": "Устройство сейчас недоступно" + }, + "busctl-error": { + "unavailable-title": "Не удаётся найти busctl!", + "unavailable-desc": "Убедитесь, что busctl установлен в вашей системе" + } + }, + "bar": { + "tooltip": "Подключённые устройства" + }, + "control_center": { + "state-label": "Статус", + "state": { + "connected": "Подключено", + "disconnected": "Не подключено", + "unavailable": "Недоступно", + "no-device": "Нет устройства", + "not-paired": "Нет сопряжения" + } + } +} diff --git a/noctalia/plugins/kde-connect/manifest.json b/noctalia/plugins/kde-connect/manifest.json new file mode 100644 index 0000000..dc7788a --- /dev/null +++ b/noctalia/plugins/kde-connect/manifest.json @@ -0,0 +1,30 @@ +{ + "id": "kde-connect", + "name": "KDE Connect", + "version": "1.2.1", + "minNoctaliaVersion": "4.4.0", + "author": "WerWolv", + "official": false, + "license": "GPLv2", + "repository": "https://github.com/WerWolv/noctalia-kde-connect", + "description": "A Plugin integrating your mobile devices into a panel using KDEConnect", + "tags": [ + "Bar", + "Panel", + "Utility", + "System" + ], + "entryPoints": { + "main": "Main.qml", + "barWidget": "BarWidget.qml", + "controlCenterWidget": "ControlCenterWidget.qml", + "panel": "Panel.qml", + "settings": "Settings.qml" + }, + "dependencies": { + "plugins": [] + }, + "metadata": { + "defaultSettings": {} + } +} diff --git a/noctalia/plugins/kde-connect/preview.png b/noctalia/plugins/kde-connect/preview.png new file mode 100644 index 0000000..94a7d7d Binary files /dev/null and b/noctalia/plugins/kde-connect/preview.png differ diff --git a/noctalia/plugins/slowbongo/BarWidget.qml b/noctalia/plugins/slowbongo/BarWidget.qml new file mode 100644 index 0000000..00d2329 --- /dev/null +++ b/noctalia/plugins/slowbongo/BarWidget.qml @@ -0,0 +1,248 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Widgets +import qs.Services.UI + +Item { + id: root + + property var pluginApi: null + + property ShellScreen screen + property string widgetId: "" + property string section: "" + property int sectionWidgetIndex: -1 + property int sectionWidgetsCount: 0 + + readonly property var mainInstance: pluginApi?.mainInstance + readonly property string screenName: screen?.name ?? "" + readonly property string resolvedBarPosition: Settings.getBarPositionForScreen(screenName) + readonly property bool isBarVertical: resolvedBarPosition === "left" || resolvedBarPosition === "right" + readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName) + readonly property real barFontSize: Style.getBarFontSizeForScreen(screenName) + + // Settings tie-ins + readonly property real catSize: mainInstance?.catSize ?? 1.0 + readonly property real catOffsetY: mainInstance?.catOffsetY ?? 0.0 + readonly property real widthPadding: pluginApi?.pluginSettings?.widthPadding ?? 0.2 + + // Orientation-aware cat sizing (both driven by the catSize slider) + readonly property real catSizeHorizontal: catSize + readonly property real catSizeVertical: catSize * 0.50 + readonly property real activeCatSize: isBarVertical ? catSizeVertical : catSizeHorizontal + + // Glyph map: b = left paw up, d = left paw down, c = right paw up, a = right paw down, e+f = sleep, g+h = blink + readonly property var glyphMap: ["bc", "dc", "ba", "da"] // [idle, leftSlap, rightSlap, bothSlap] + readonly property string sleepGlyph: "ef" + readonly property string blinkGlyph: "gh" + + readonly property int catState: mainInstance?.catState ?? 0 + readonly property bool paused: mainInstance?.paused ?? false + readonly property bool waiting: mainInstance?.waiting ?? false + readonly property string catColorKey: mainInstance?.catColor ?? "default" + readonly property bool blinking: mainInstance?.blinking ?? false + readonly property bool showRainbowColor: mainInstance?.showRainbowColor ?? false + readonly property string rainbowColor: mainInstance?.currentRainbowColor ?? "#ff0000" + + function resolveColor(key) { + switch (key) { + case "primary": return Color.mPrimary + case "secondary": return Color.mSecondary + case "tertiary": return Color.mTertiary + case "error": return Color.mError + default: return Color.mOnSurface + } + } + + readonly property color resolvedCatColor: showRainbowColor ? rainbowColor : resolveColor(catColorKey) + + // Sizing: capsule dimensions drive implicit size + readonly property real horizontalPadding: capsuleHeight * widthPadding + readonly property real contentWidth: isBarVertical + ? capsuleHeight + : catText.implicitWidth + horizontalPadding + (paused ? pauseExpandAmount : 0) + readonly property real contentHeight: isBarVertical + ? catText.implicitHeight + horizontalPadding + (paused ? pauseExpandAmount : 0) + : capsuleHeight + + // Pause indicator expand/slide + readonly property real pauseIconSize: capsuleHeight * 0.45 + readonly property real pauseExpandAmount: capsuleHeight * 0.8 + readonly property real pauseSlideOffset: paused ? -pauseExpandAmount / 2 : 0 + + implicitWidth: contentWidth + implicitHeight: contentHeight + + FontLoader { + id: bongoFont + source: pluginApi ? pluginApi.pluginDir + "/bongocat-Regular.otf" : "" + } + + Rectangle { + id: visualCapsule + x: Style.pixelAlignCenter(parent.width, width) + y: Style.pixelAlignCenter(parent.height, height) + width: root.contentWidth + height: root.contentHeight + radius: Style.radiusL + + Behavior on width { + NumberAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic } + } + Behavior on height { + NumberAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic } + } + color: mouseArea.containsMouse ? Color.mHover : (root.paused ? root.resolvedCatColor : Style.capsuleColor) + border.color: Style.capsuleBorderColor + border.width: Style.capsuleBorderWidth + + Behavior on color { + ColorAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic } + } + + Text { + id: catText + anchors.centerIn: parent + anchors.horizontalCenterOffset: root.isBarVertical ? 0 : root.pauseSlideOffset + anchors.verticalCenterOffset: root.capsuleHeight * root.catOffsetY + (root.isBarVertical ? root.pauseSlideOffset : 0) + font.family: bongoFont.name + font.pixelSize: root.capsuleHeight * root.activeCatSize + font.weight: Font.Thin + color: mouseArea.containsMouse ? Color.mOnHover : (root.paused ? Color.mSurface : root.resolvedCatColor) + text: (root.paused || root.waiting) ? root.sleepGlyph : (root.blinking ? root.blinkGlyph : (root.glyphMap[root.catState] ?? "bc")) + + Behavior on anchors.horizontalCenterOffset { + NumberAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic } + } + Behavior on anchors.verticalCenterOffset { + NumberAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic } + } + } + + NIcon { + id: pauseIcon + icon: "player-pause-filled" + pointSize: root.pauseIconSize + applyUiScale: false + color: catText.color + opacity: root.paused ? 1 : 0 + x: root.isBarVertical + ? (parent.width - width) / 2 + : parent.width - (root.pauseExpandAmount + width) / 2 - root.capsuleHeight * 0.20 + y: root.isBarVertical + ? parent.height - (root.pauseExpandAmount + height) / 2 - root.capsuleHeight * 0.10 + : (parent.height - height) / 2 + + Behavior on opacity { + NumberAnimation { duration: Style.animationFast; easing.type: Easing.OutCubic } + } + } + + Repeater { + id: zzzRepeater + property real catFontSize: catText.font.pixelSize + property color catFontColor: catText.color + property real catX: catText.x + property real catY: catText.y + property real catW: catText.width + property bool sleeping: root.paused || root.waiting + + readonly property real baseScale: 0.28 + readonly property real scaleStep: 0.07 + readonly property real xOrigin: 0.55 + readonly property real xSpacing: 0.18 + readonly property real floatHeight: 0.7 + readonly property int staggerDelay: 500 + readonly property int floatDuration: 1800 + readonly property int fadeInDuration: 300 + readonly property int fadeOutDuration: 1500 + + model: 3 + delegate: Text { + id: zItem + required property int index + text: "z" + font.pixelSize: zzzRepeater.catFontSize * (zzzRepeater.baseScale + index * zzzRepeater.scaleStep) + font.weight: Font.Bold + color: zzzRepeater.catFontColor + visible: zzzRepeater.sleeping + opacity: 0 + x: zzzRepeater.catX + zzzRepeater.catW * zzzRepeater.xOrigin + index * zzzRepeater.catFontSize * zzzRepeater.xSpacing + y: zzzRepeater.catY + + SequentialAnimation { + id: zAnim + running: zzzRepeater.sleeping + loops: Animation.Infinite + + PauseAnimation { duration: zItem.index * zzzRepeater.staggerDelay } + + ParallelAnimation { + NumberAnimation { + target: zItem; property: "y" + from: zzzRepeater.catY + to: zzzRepeater.catY - zzzRepeater.catFontSize * zzzRepeater.floatHeight + duration: zzzRepeater.floatDuration + easing.type: Easing.OutQuad + } + SequentialAnimation { + NumberAnimation { + target: zItem; property: "opacity" + from: 0; to: 1 + duration: zzzRepeater.fadeInDuration + } + NumberAnimation { + target: zItem; property: "opacity" + from: 1; to: 0 + duration: zzzRepeater.fadeOutDuration + easing.type: Easing.InQuad + } + } + } + } + + onVisibleChanged: { + if (!visible) { + zAnim.stop(); + opacity = 0; + y = zzzRepeater.catY; + } + } + } + } + + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + cursorShape: Qt.PointingHandCursor + onClicked: mouse => { + if (mouse.button === Qt.RightButton) { + PanelService.showContextMenu(contextMenu, root, screen); + } else if (root.mainInstance) { + root.mainInstance.paused = !root.mainInstance.paused; + } + } + } + + NPopupContextMenu { + id: contextMenu + model: [{ + "label": I18n.tr("actions.widget-settings"), + "action": "widget-settings", + "icon": "settings" + }] + onTriggered: action => { + contextMenu.close(); + PanelService.closeContextMenu(screen); + if (action === "widget-settings") { + BarService.openPluginSettings(screen, pluginApi.manifest); + } + } + } +} diff --git a/noctalia/plugins/slowbongo/Main.qml b/noctalia/plugins/slowbongo/Main.qml new file mode 100644 index 0000000..597ab39 --- /dev/null +++ b/noctalia/plugins/slowbongo/Main.qml @@ -0,0 +1,441 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Commons +import qs.Services.Media +import qs.Services.UI + +Item { + id: root + + // === EXTERNAL API === + property var pluginApi: null + + // === CORE STATE === + property int catState: 0 // 0 = idle (both paws up), 1 = left slap, 2 = right slap, 3 = both slap + property bool leftWasLast: false // Track which paw slapped last to alternate + property bool paused: false + property bool waiting: false + property bool blinking: false + property int pendingCatState: 0 // State to transition to after reset delay + + // === INSTANCE IDENTIFICATION === + readonly property string spectrumInstanceId: "plugin:slowbongo:" + Date.now() + Math.random() + + // === INPUT DEVICES (from settings) === + readonly property var inputDevices: { + const saved = pluginApi?.pluginSettings?.inputDevices; + if (saved && saved.length > 0) return saved; + return []; + } + + onPluginApiChanged: { + if (pluginApi) { + SpectrumService.registerComponent(spectrumInstanceId); + Logger.i("SlowBongo", "Registered with SpectrumService for audio detection"); + } + } + + Component.onDestruction: SpectrumService.unregisterComponent(spectrumInstanceId) + + // === IPC CONTROL === + IpcHandler { + target: "plugin:slowbongo" + + function pause() { + root.paused = true + } + + function resume() { + root.paused = false + } + + function toggle() { + root.paused = !root.paused + } + } + + // === SETTINGS === + readonly property int idleTimeout: pluginApi?.pluginSettings?.idleTimeout ?? 250 + readonly property int waitingTimeout: pluginApi?.pluginSettings?.waitingTimeout ?? 5000 + readonly property string catColor: pluginApi?.pluginSettings?.catColor ?? "default" + readonly property real catSize: pluginApi?.pluginSettings?.catSize ?? 1.0 + readonly property real catOffsetY: pluginApi?.pluginSettings?.catOffsetY ?? 0.0 + readonly property bool raveMode: pluginApi?.pluginSettings?.raveMode ?? false + readonly property bool tappyMode: pluginApi?.pluginSettings?.tappyMode ?? false + readonly property bool useMprisFilter: pluginApi?.pluginSettings?.useMprisFilter ?? false + + // === AUDIO REACTIVE STATE === + readonly property bool anyMusicPlaying: !SpectrumService.isIdle + property int rainbowIndex: 0 + readonly property var rainbowColors: ['#aa0000', '#b65c02', '#bb9c14', '#00a100', '#01019b', '#37005c', '#6a0196'] + property real audioIntensity: 0 + property real smoothedIntensity: 0 + property real previousIntensity: 0 + property real bassIntensity: 0 + readonly property real beatThreshold: 0.07 + readonly property real bigBeatThreshold: 0.67 + readonly property real beatDeltaThreshold: 0.014 // Minimum sudden increase to count as beat + property bool isFlashing: false + + // === COMPUTED MODE FLAGS === + readonly property bool mprisAllowed: !useMprisFilter || MediaService.isPlaying + readonly property bool useTappyMode: tappyMode && anyMusicPlaying && mprisAllowed + readonly property string currentRainbowColor: rainbowColors[rainbowIndex] + readonly property bool useRaveColors: raveMode && anyMusicPlaying && mprisAllowed + readonly property bool showRainbowColor: useRaveColors && isFlashing + + // === AUDIO REACTIVE CONNECTIONS === + Connections { + target: SpectrumService + function onValuesChanged() { + if (root.paused) return; + if (!root.useRaveColors && !root.useTappyMode) return; + + if (!SpectrumService.values || SpectrumService.values.length === 0) { + root.audioIntensity = 0; + return; + } + + const subBassCount = Math.min(4, SpectrumService.values.length); + const bassCount = Math.min(8, SpectrumService.values.length); + const midCount = Math.min(16, SpectrumService.values.length); + + let subBassSum = 0; + for (let i = 0; i < subBassCount; i++) { + subBassSum += SpectrumService.values[i] || 0; + } + + let bassSum = 0; + for (let i = 0; i < bassCount; i++) { + bassSum += SpectrumService.values[i] || 0; + } + + let midSum = 0; + for (let i = 8; i < midCount; i++) { + midSum += SpectrumService.values[i] || 0; + } + + const subBassAvg = subBassSum / subBassCount; + const bassAvg = bassSum / bassCount; + const midAvg = midSum / Math.max(1, midCount - 8); + + root.bassIntensity = subBassAvg; + root.audioIntensity = (bassAvg * 0.8) + (midAvg * 0.6); + + const alpha = 0.75; + root.previousIntensity = root.smoothedIntensity; + root.smoothedIntensity = alpha * root.audioIntensity + (1 - alpha) * root.smoothedIntensity; + + const intensityDelta = root.smoothedIntensity - root.previousIntensity; + const isBeat = (intensityDelta > root.beatDeltaThreshold && root.smoothedIntensity > root.beatThreshold * 0.5) + || (root.smoothedIntensity > root.beatThreshold && intensityDelta > 0); + + if (isBeat && !beatCooldownTimer.running) { + if (root.useRaveColors) { + root.rainbowIndex = (root.rainbowIndex + 1) % root.rainbowColors.length; + root.isFlashing = true; + flashTimer.restart(); + } + + if (root.useTappyMode) { + root.musicEvent(root.bassIntensity > root.bigBeatThreshold); + } + + beatCooldownTimer.restart(); + } + } + } + + // === TIMERS === + Timer { + id: beatCooldownTimer + interval: 70 + repeat: false + } + + Timer { + id: flashTimer + interval: 100 + repeat: false + onTriggered: root.isFlashing = false + } + + Timer { + id: stateResetTimer + interval: 40 + repeat: false + onTriggered: root.catState = root.pendingCatState + } + + // === MUSIC HANDLER === + function musicEvent(isBigHit = false) { + if (root.paused) return; + root.waiting = false; + + let targetState; + if (isBigHit) { + targetState = 3; + } else { + root.leftWasLast = !root.leftWasLast; + targetState = root.leftWasLast ? 1 : 2; + } + + const needsReset = root.catState !== 0 && ((isBigHit && root.catState !== 3) || (!isBigHit && root.catState === 3)); + + if (needsReset) { + root.catState = 0; + root.pendingCatState = targetState; + stateResetTimer.restart(); + } else { + root.catState = targetState; + } + + idleTimer.restart(); + waitingTimer.restart(); + } + + // === KEY PRESS HANDLER === + function onKeyPress(isBigHit = false) { + if (root.paused) return; + root.waiting = false; + + let targetState; + if (isBigHit) { + targetState = 3; + } else { + if (root.catState !== 0){ + targetState = 3; + } else { + root.leftWasLast = !root.leftWasLast; + targetState = root.leftWasLast ? 1 : 2; + } + } + + root.catState = targetState; + waitingTimer.restart(); + } + + function onKeyRelease(isBigHit = false) { + if (root.paused) return; + root.waiting = false; + + let targetState; + if (isBigHit) { + targetState = 0; + } else { + if (root.catState === 3){ + targetState = root.leftWasLast ? 1 : 2; + } else { + targetState = 0; + } + } + + root.catState = targetState; + waitingTimer.restart(); + } + + function onKeyRepeat(isBigHit = false){ + if (root.paused) return; + root.waiting = false; + + let targetState; + if (root.catState !== 0) { + targetState = root.catState; + } else { + if (isBigHit){ + targetState = 3; + } else { + targetState = root.leftWasLast ? 1 : 2; + } + } + + root.catState = targetState; + waitingTimer.restart(); + } + + // === STATE CHANGE HANDLERS === + onPausedChanged: { + if (root.paused) { + idleTimer.stop(); + waitingTimer.stop(); + root.waiting = false; + root.blinking = false; + root.catState = 0; + } else { + waitingTimer.restart(); + } + } + + onWaitingChanged: { + if (root.waiting) { + root.blinking = false; + } + } + + // === IDLE & WAITING TIMERS === + Timer { + id: idleTimer + interval: root.idleTimeout + repeat: false + onTriggered: root.catState = 0 + } + + Timer { + id: waitingTimer + interval: root.waitingTimeout + repeat: false + onTriggered: root.waiting = true + } + + // === BLINK ANIMATION === + Timer { + id: blinkIntervalTimer + interval: 6000 + Math.random() * 8000 + repeat: true + running: !root.paused && !root.waiting + onTriggered: { + interval = 6000 + Math.random() * 8000; + if (Math.random() < 0.5) { + root.blinking = true; + blinkDurationTimer.start(); + } else { + root.blinkFlutterCount = 0; + root.blinking = true; + flutterTimer.start(); + } + } + } + + property int blinkFlutterCount: 0 + + Timer { + id: blinkDurationTimer + interval: 450 + repeat: false + onTriggered: root.blinking = false + } + + Timer { + id: flutterTimer + interval: 120 + repeat: false + onTriggered: { + root.blinkFlutterCount++; + root.blinking = !root.blinking; + if (root.blinkFlutterCount < 4) { + flutterTimer.start(); + } else { + root.blinking = false; + } + } + } + + // === INPUT DEVICE MONITORING === + Repeater { + model: root.inputDevices + + Item { + id: deviceMonitor + required property string modelData + + property int retryCount: 0 + property bool hasNotified: false + readonly property var retryIntervals: [30000, 90000, 300000] // 30s, 1:30, 5min + + Process { + id: evtestProc + command: ["evtest", deviceMonitor.modelData] + running: true + + stdout: SplitParser { + onRead: data => { + if (data.includes("EV_KEY")) { + // Detect spacebar/enter for double slap (both paws) + const isBigHit = data.includes("KEY_SPACE") || data.includes("KEY_ENTER"); + // Key pressed + // Ignore BTN_TOOL_ events to avoid double events with touchpads + if (data.includes("value 1") && !data.includes("BTN_TOOL_")){ + root.onKeyPress(isBigHit); + // Key released + } else if (data.includes("value 0")) { + root.onKeyRelease(isBigHit); + // Key repeat + } else if (data.includes("value 2")) { + root.onKeyRepeat(isBigHit); + } + } + } + } + + stderr: StdioCollector {} + + onRunningChanged: { + if (running) { + deviceMonitor.retryCount = 0; + deviceMonitor.hasNotified = false; + } + } + + onExited: exitCode => { + Logger.w("Slow Bongo", "evtest (" + deviceMonitor.modelData + ") exited with code " + exitCode); + + if (exitCode !== 0) { + deviceMonitor.retryCount++; + + if (!deviceMonitor.hasNotified) { + ToastService.showWarning( + root.pluginApi?.tr("toast.evtest-error") ?? "SlowBongo", + root.pluginApi?.tr("toast.device-disconnected") ?? ("Device disconnected: " + deviceMonitor.modelData) + ); + deviceMonitor.hasNotified = true; + } + + if (deviceMonitor.retryCount <= deviceMonitor.retryIntervals.length) { + const interval = deviceMonitor.retryIntervals[deviceMonitor.retryCount - 1]; + Logger.i("Slow Bongo", "Will retry in " + Math.floor(interval / 1000) + "s (attempt " + deviceMonitor.retryCount + "/" + deviceMonitor.retryIntervals.length + ")"); + restartTimer.interval = interval; + restartTimer.start(); + } else { + Logger.w("Slow Bongo", "Max retries reached for device: " + deviceMonitor.modelData + ". Giving up."); + ToastService.showInfo( + root.pluginApi?.tr("toast.device-gave-up") ?? "SlowBongo", + root.pluginApi?.tr("toast.device-gave-up-desc") ?? ("Stopped trying to reconnect to: " + deviceMonitor.modelData) + ); + } + } else { + restartTimer.interval = deviceMonitor.retryIntervals[0]; + restartTimer.start(); + } + } + } + + Timer { + id: restartTimer + repeat: false + onTriggered: deviceCheckProc.running = true + } + + Process { + id: deviceCheckProc + command: ["test", "-e", deviceMonitor.modelData] + running: false + + onExited: exitCode => { + if (exitCode === 0) { + Logger.i("Slow Bongo", "Device detected, restarting monitoring: " + deviceMonitor.modelData); + evtestProc.running = true; + } else if (deviceMonitor.retryCount < deviceMonitor.retryIntervals.length) { + deviceMonitor.retryCount++;; + const interval = deviceMonitor.retryIntervals[deviceMonitor.retryCount - 1]; + Logger.i("Slow Bongo", "Device " + deviceMonitor.modelData + " not found, will retry in " + Math.floor(interval / 1000) + "s (attempt " + deviceMonitor.retryCount + "/" + deviceMonitor.retryIntervals.length + ")"); + restartTimer.interval = interval; + restartTimer.start(); + } else { + Logger.w("Slow Bongo", "Max retries reached for device: " + deviceMonitor.modelData + ". Giving up."); + } + } + } + } + } +} diff --git a/noctalia/plugins/slowbongo/README.md b/noctalia/plugins/slowbongo/README.md new file mode 100644 index 0000000..40c12a0 --- /dev/null +++ b/noctalia/plugins/slowbongo/README.md @@ -0,0 +1,106 @@ +# Slow Bongo +![Picture of a cute lil bongocatto](https://raw.githubusercontent.com/tuibird/slowbongo/refs/heads/main/slowbongo.png) + +A bongo cat that sits in your bar and slaps when you type. This is very early days, there will be bugs. + +## Features + +- **Bar Widget**: Compact widget that fits seamlessly in your Noctalia bar +- **Keyboard Reactive**: Cat taps its paws in alternation when you type +- **Audio Reactive**: Optional rave mode and tappy mode that react to music +- **Easy pause**: Can quickly pause and un-pause reactivity with a single left click. +- **Customizable Appearance**: Choose from multiple color schemes and adjust size +- **Font-Based Animation**: Uses a bongo cat font for easy rendering +- **Bar Widget**: Compact widget that fits seamlessly in your Noctalia bar + +## Installation + +1. Navigate to the Noctalia settings plugins section. + +2. Enter the sources sub-menu. + +3. Add Slow Bongo as a custom repository. + ```bash + https://github.com/tuibird/slowbongo.git + ``` + +4. Open the Noctalia plugins store and enable **Slow Bongo**. + +## Configuration + +The plugin offers several customization options available in the settings panel: + +### Input Devices + +The plugin automatically detects keyboard input devices on first run. You can manually select which input devices to monitor from the settings panel. + +### Colors + +The colours are all pulled from your current Noctalia colourscheme. + +### Rave Mode + +When enabled, the cat changes colors to the beat when music is playing. + +### Tappy Mode + +When enabled, the cat taps along to the beat when music is playing instead of only reacting to keyboard input. + +### Size and Position + +- **Cat Size**: Scale the cat from 50% to 150% of default size +- **Vertical Position**: Fine-tune the cat's vertical alignment in the bar + +## Requirements + +### Essential + +- **evtest**: Required for keyboard input detection + ```bash + # Fedora/RHEL + sudo dnf install evtest + + # Ubuntu/Debian + sudo apt install evtest + + # Arch + sudo pacman -S evtest + ``` + +- **Input group membership**: Your user must be in the `input` group to read keyboard events + ```bash + sudo usermod -a -G input $USER + ``` + Restart for the group change to take effect. + +## Troubleshooting + +### Cat not responding to keyboard input + +1. Check that `evtest` is installed: + ```bash + which evtest + ``` + +2. Verify you're in the `input` group: + ```bash + id -nG | grep input + ``` + +3. Make sure at least one input device is selected in the settings panel. + +## Technical Details + +- Uses `evtest` to monitor keyboard events from `/dev/input/event*` devices +- Integrates with Noctalia's SpectrumService for audio visualization +- Custom font file (`bongocatfont.woff`) contains the cat animations +- Alternates between left (1) and right (2) paw animations, returning to idle (0) after configurable timeout + +## License + +MIT + +## Credits + +- Thank you to [Kitgore](https://github.com/kitgore) for the inital bongo cat font +- Noctalia plugins for the amazing guides/examples diff --git a/noctalia/plugins/slowbongo/Settings.qml b/noctalia/plugins/slowbongo/Settings.qml new file mode 100644 index 0000000..e9fc813 --- /dev/null +++ b/noctalia/plugins/slowbongo/Settings.qml @@ -0,0 +1,455 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell.Io +import qs.Commons +import qs.Widgets + +ColumnLayout { + id: root + spacing: Style.marginL + + property var pluginApi: null + + // Requirement check states + property bool evtestInstalled: false + property bool inInputGroup: false + property string currentUser: "" + + // Editable settings properties + property string editCatColor: { + let saved = pluginApi?.pluginSettings?.catColor + if (saved && saved.length > 0) return saved + return pluginApi?.manifest?.metadata?.defaultSettings?.catColor ?? "none" + } + + property real editCatSize: { + let saved = pluginApi?.pluginSettings?.catSize + if (saved !== undefined && saved !== null) return saved + return pluginApi?.manifest?.metadata?.defaultSettings?.catSize ?? 1.0 + } + + property real editCatOffsetY: { + let saved = pluginApi?.pluginSettings?.catOffsetY + if (saved !== undefined && saved !== null) return saved + return pluginApi?.manifest?.metadata?.defaultSettings?.catOffsetY ?? 0.11 + } + + property var editInputDevices: { + let saved = pluginApi?.pluginSettings?.inputDevices + if (saved && saved.length > 0) return saved + let legacy = pluginApi?.pluginSettings?.inputDevice + ?? pluginApi?.manifest?.metadata?.defaultSettings?.inputDevice + return legacy ? [legacy] : [] + } + + property bool editRaveMode: { + let saved = pluginApi?.pluginSettings?.raveMode + if (saved !== undefined && saved !== null) return saved + return pluginApi?.manifest?.metadata?.defaultSettings?.raveMode ?? false + } + + property bool editTappyMode: { + let saved = pluginApi?.pluginSettings?.tappyMode + if (saved !== undefined && saved !== null) return saved + return pluginApi?.manifest?.metadata?.defaultSettings?.tappyMode ?? false + } + + property bool editUseMprisFilter: { + let saved = pluginApi?.pluginSettings?.useMprisFilter + if (saved !== undefined && saved !== null) return saved + return pluginApi?.manifest?.metadata?.defaultSettings?.useMprisFilter ?? false + } + + // Status colors (with fallback for theme compatibility) + readonly property color statusSuccessColor: Color.mPrimary + readonly property color statusErrorColor: Color.mError ?? "#c00202" + + property var inputDevices: [] + + function isSelected(key) { + return root.editInputDevices.indexOf(key) >= 0 + } + + function toggleDevice(key) { + let list = root.editInputDevices.slice() + let idx = list.indexOf(key) + if (idx >= 0) + list.splice(idx, 1) + else + list.push(key) + root.editInputDevices = list + } + + Component.onCompleted: { + evtestCheck.running = true + userCheck.running = true + byIdListProcess.running = true + } + + Process { + id: evtestCheck + command: ["which", "evtest"] + stdout: StdioCollector {} + stderr: StdioCollector {} + onExited: function(exitCode, exitStatus) { + root.evtestInstalled = (exitCode == 0) + } + } + + Process { + id: userCheck + command: ["id", "-un"] + stdout: SplitParser { + onRead: data => { + root.currentUser = data.trim() + } + } + stderr: StdioCollector {} + onExited: function(exitCode, exitStatus) { + if (exitCode == 0 && root.currentUser.length > 0) + groupCheck.running = true + } + } + + Process { + id: groupCheck + command: ["sh", "-c", "id -nG '" + root.currentUser + "' | tr ' ' '\\n' | grep -qx input"] + stdout: StdioCollector {} + stderr: StdioCollector {} + onExited: function(exitCode, exitStatus) { + root.inInputGroup = (exitCode == 0) + } + } + + // Try by-id first + Process { + id: byIdListProcess + command: ["sh", "-c", "[ -d /dev/input/by-id ] && for f in /dev/input/by-id/*-event-*; do [ -e \"$f\" ] && echo \"$(basename \"$f\")|$(readlink -f \"$f\")\"; done || true"] + + stdout: SplitParser { + onRead: data => { + const line = data.trim() + if (line.length === 0) return + const parts = line.split("|") + if (parts.length !== 2) return + const name = parts[0] + const resolved = parts[1] + if (!resolved.startsWith("/dev/input/event")) return + + const eventNum = resolved.replace(/.*\//, "") + let friendly = name + .replace(/^usb-/, "") + .replace(/-event-\w+$/, "") + .replace(/-if\d+$/, "") + .replace(/_/g, " ") + + root.inputDevices = root.inputDevices.concat([{ + key: resolved, + name: friendly, + eventDev: eventNum + }]) + } + } + + stderr: StdioCollector {} + + onExited: function(exitCode, exitStatus) { + // Always try to get names from sysfs + sysfsListProcess.running = true + } + } + + // Get device names from sysfs + Process { + id: sysfsListProcess + command: ["sh", "-c", "for f in /dev/input/event*; do [ -c \"$f\" ] && echo \"$f|$(cat /sys/class/input/$(basename $f)/device/name 2>/dev/null || basename $f)\"; done"] + running: false + + stdout: SplitParser { + onRead: data => { + const line = data.trim() + if (line.length === 0) return + const parts = line.split("|") + if (parts.length !== 2) return + const device = parts[0] + const name = parts[1] + const eventNum = device.replace(/.*\//, "") + + // Filter out non-keyboardy devices + const nameLower = name.toLowerCase() + const excludePatterns = [ + /power button/i, + /sleep button/i, + /lid switch/i, + /video bus/i, + /audio/i, + /hdmi/i, + /speaker/i, + /headphone/i, + /mic\b/i + ] + + const shouldExclude = excludePatterns.some(pattern => pattern.test(name)) + if (shouldExclude) return + + // Check if we already have this device from by-id + const exists = root.inputDevices.some(d => d.key === device) + if (!exists) { + root.inputDevices = root.inputDevices.concat([{ + key: device, + name: name, + eventDev: eventNum + }]) + } + } + } + + stderr: StdioCollector {} + } + + // Requirements Section + Text { + text: pluginApi?.tr("settings.requirements") + color: Color.mOnSurface + font.pointSize: Style.fontSizeM + font.weight: Font.DemiBold + } + + NBox { + Layout.fillWidth: true + implicitHeight: reqContent.implicitHeight + Style.marginM * 2 + + ColumnLayout { + id: reqContent + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: Style.marginM + spacing: Style.marginS + + RowLayout { + spacing: Style.marginS + NIcon { + icon: root.evtestInstalled ? "circle-check-filled" : "circle-x-filled" + color: root.evtestInstalled ? root.statusSuccessColor : root.statusErrorColor + pointSize: Style.fontSizeM + } + Text { + text: root.evtestInstalled + ? pluginApi?.tr("settings.evtest-installed") + : pluginApi?.tr("settings.evtest-not-installed") + color: root.evtestInstalled ? root.statusSuccessColor : root.statusErrorColor + font.pointSize: Style.fontSizeM + } + } + + RowLayout { + spacing: Style.marginS + NIcon { + icon: root.inInputGroup ? "circle-check-filled" : "circle-x-filled" + color: root.inInputGroup ? root.statusSuccessColor : root.statusErrorColor + pointSize: Style.fontSizeM + } + Text { + text: root.inInputGroup + ? pluginApi?.tr("settings.in-input-group") + : pluginApi?.tr("settings.not-in-input-group") + color: root.inInputGroup ? root.statusSuccessColor : root.statusErrorColor + font.pointSize: Style.fontSizeM + } + } + } + } + + NDivider { + Layout.fillWidth: true + } + + // Widget Color + NColorChoice { + label: pluginApi?.tr("settings.colours") + currentKey: root.editCatColor + onSelected: key => { root.editCatColor = key; } + } + + // Cat Size Section + NValueSlider { + Layout.fillWidth: true + label: pluginApi?.tr("settings.cat-size") + value: root.editCatSize + from: 0.5 + to: 1.5 + stepSize: 0.01 + defaultValue: 1.0 + showReset: true + text: Math.round(root.editCatSize * 100) + "%" + onMoved: value => root.editCatSize = value + } + + // Vertical Position Section + NValueSlider { + Layout.fillWidth: true + label: pluginApi?.tr("settings.vertical-position") + value: root.editCatOffsetY + from: -0.39 + to: 0.61 + stepSize: 0.01 + defaultValue: 0.11 + showReset: true + text: { let v = Math.round(-(root.editCatOffsetY - 0.11) * 100) / 100; return (v > 0 ? "+" : "") + v.toFixed(2) } + onMoved: value => root.editCatOffsetY = value + } + + // Rave Mode + NToggle { + label: pluginApi?.tr("settings.rave-mode") + description: pluginApi?.tr("settings.rave-mode-desc") + checked: root.editRaveMode + onToggled: checked => root.editRaveMode = checked + defaultValue: pluginApi?.manifest?.metadata?.defaultSettings?.raveMode ?? false + } + + // Tappy Mode + NToggle { + label: pluginApi?.tr("settings.tappy-mode") + description: pluginApi?.tr("settings.tappy-mode-desc") + checked: root.editTappyMode + onToggled: checked => root.editTappyMode = checked + defaultValue: pluginApi?.manifest?.metadata?.defaultSettings?.tappyMode ?? false + } + + // MPRIS Filtering + NToggle { + label: pluginApi?.tr("settings.mpris-filter") + description: pluginApi?.tr("settings.mpris-filter-desc") + checked: root.editUseMprisFilter + onToggled: checked => root.editUseMprisFilter = checked + defaultValue: pluginApi?.manifest?.metadata?.defaultSettings?.useMprisFilter ?? false + } + + NDivider { + Layout.fillWidth: true + } + + // Input Devices Section + Text { + text: pluginApi?.tr("settings.input-devices") || "Input Devices" + color: Color.mOnSurface + font.pointSize: Style.fontSizeM + font.weight: Font.DemiBold + } + + NBox { + Layout.fillWidth: true + implicitHeight: devContent.implicitHeight + Style.marginM * 2 + + ColumnLayout { + id: devContent + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: Style.marginM + spacing: Style.marginS + + Repeater { + model: root.inputDevices + + Rectangle { + required property var modelData + + property bool isChecked: root.isSelected(modelData.key) + property bool isHovered: mouseArea.containsMouse + + Layout.fillWidth: true + implicitHeight: rowContent.implicitHeight + Style.marginS * 2 + radius: Style.iRadiusXS + color: isHovered ? Color.mSurfaceVariant : "transparent" + + Behavior on color { + ColorAnimation { duration: Style.animationFast } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + onClicked: root.toggleDevice(modelData.key) + } + + RowLayout { + id: rowContent + anchors.fill: parent + anchors.leftMargin: Style.marginS + anchors.rightMargin: Style.marginS + spacing: Style.marginM + + Rectangle { + id: checkBox + implicitWidth: Math.round(Style.baseWidgetSize * 0.7) + implicitHeight: Math.round(Style.baseWidgetSize * 0.7) + radius: Style.iRadiusXS + color: parent.parent.isChecked ? Color.mPrimary : Color.mSurface + border.color: parent.parent.isHovered ? Color.mPrimary : Color.mOutline + border.width: Style.borderS + + Behavior on color { + ColorAnimation { duration: Style.animationFast } + } + Behavior on border.color { + ColorAnimation { duration: Style.animationFast } + } + + NIcon { + visible: parent.parent.parent.isChecked + anchors.centerIn: parent + anchors.horizontalCenterOffset: -1 + icon: "check" + color: Color.mOnPrimary + pointSize: Math.max(Style.fontSizeXS, checkBox.implicitWidth * 0.5) + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + Text { + text: parent.parent.parent.modelData.name + color: Color.mOnSurface + font.pointSize: Style.fontSizeM + elide: Text.ElideRight + Layout.fillWidth: true + } + + Text { + text: parent.parent.parent.modelData.eventDev + color: Color.mOnSurfaceVariant + font.pointSize: Style.fontSizeS + visible: text !== "" + elide: Text.ElideRight + Layout.fillWidth: true + } + } + } + } + } + } + } + + function saveSettings() { + if (!pluginApi) { + Logger.e("Slow Bongo", "Cannot save settings: pluginApi is null") + return + } + pluginApi.pluginSettings.inputDevices = root.editInputDevices + pluginApi.pluginSettings.catColor = root.editCatColor + pluginApi.pluginSettings.catSize = root.editCatSize + pluginApi.pluginSettings.catOffsetY = root.editCatOffsetY + pluginApi.pluginSettings.raveMode = root.editRaveMode + pluginApi.pluginSettings.tappyMode = root.editTappyMode + pluginApi.pluginSettings.useMprisFilter = root.editUseMprisFilter + pluginApi.saveSettings() + Logger.i("Slow Bongo", "Settings saved successfully") + } +} diff --git a/noctalia/plugins/slowbongo/bongocat-Regular.otf b/noctalia/plugins/slowbongo/bongocat-Regular.otf new file mode 100644 index 0000000..2006885 Binary files /dev/null and b/noctalia/plugins/slowbongo/bongocat-Regular.otf differ diff --git a/noctalia/plugins/slowbongo/i18n/de.json b/noctalia/plugins/slowbongo/i18n/de.json new file mode 100644 index 0000000..58dd729 --- /dev/null +++ b/noctalia/plugins/slowbongo/i18n/de.json @@ -0,0 +1,36 @@ +{ + "description": "Eine Bongo-Katze, die in deiner Bar sitzt und klopft, wenn du tippst", + "settings": { + "requirements": "Voraussetzungen", + "input-devices": "Eingabegeräte", + "colours": "Farben", + "cat-size": "Katzengröße", + "vertical-position": "Vertikale Position", + "size-label": "Größe:", + "y-offset-label": "Y-Versatz:", + "rave-mode": "Rave Modus", + "rave-mode-desc": "Ändere die Farben im Takt der Musik, wenn Musik abgespielt wird", + "tappy-mode": "Tappy Modus", + "tappy-mode-desc": "Lass die Katze im Takt der Musik mit den Pfoten klopfen", + "mpris-filter": "MPRIS Filterung", + "mpris-filter-desc": "Reagiert nur auf Audio, wenn ein nicht auf der Blacklist stehender Mediaplayer abgespielt wird (verwendet die Noctalia-Shell Audio Blacklist)", + "evtest-installed": "evtest ist installiert", + "evtest-not-installed": "evtest ist nicht installiert", + "in-input-group": "Benutzer ist in der input Gruppe", + "not-in-input-group": "Benutzer ist nicht in der input Gruppe" + }, + "colors": { + "default": "Standard", + "primary": "Primär", + "secondary": "Sekundär", + "tertiary": "Teritär" + }, + "toast": { + "auto-detect-success": "SlowBongo", + "auto-detect-success-desc": "Automatisch erkannte Tastaturen", + "auto-detect-failed": "SlowBongo", + "auto-detect-failed-desc": "Tastaturen konnten nicht erkannt werden. Bitte manuell in den Einstellungen konfigurieren.", + "evtest-error": "SlowBongo", + "evtest-error-desc": "Die Tastaturüberwachung wurde unerwartet beendet. Neustart..." + } +} diff --git a/noctalia/plugins/slowbongo/i18n/en.json b/noctalia/plugins/slowbongo/i18n/en.json new file mode 100644 index 0000000..9c0c29b --- /dev/null +++ b/noctalia/plugins/slowbongo/i18n/en.json @@ -0,0 +1,36 @@ +{ + "description": "A bongo cat that sits in your bar and slaps when you type.", + "settings": { + "requirements": "Requirements", + "input-devices": "Input Devices", + "colours": "Colours", + "cat-size": "Cat Size", + "vertical-position": "Vertical Position", + "size-label": "Size:", + "y-offset-label": "Y Offset:", + "rave-mode": "Rave Mode", + "rave-mode-desc": "Change colors to the beat when music is playing", + "tappy-mode": "Tappy Mode", + "tappy-mode-desc": "Make the cat tap along to the beat when music is playing", + "mpris-filter": "MPRIS Filtering", + "mpris-filter-desc": "Only react to audio when a non-blacklisted media player is playing (uses Noctalia Shell audio blacklist)", + "evtest-installed": "evtest is installed", + "evtest-not-installed": "evtest is not installed", + "in-input-group": "User is in the input group", + "not-in-input-group": "User is not in the input group" + }, + "colors": { + "default": "Default", + "primary": "Primary", + "secondary": "Secondary", + "tertiary": "Tertiary" + }, + "toast": { + "auto-detect-success": "SlowBongo", + "auto-detect-success-desc": "Auto-detected keyboard devices", + "auto-detect-failed": "SlowBongo", + "auto-detect-failed-desc": "Could not detect keyboard devices. Please configure manually in settings.", + "evtest-error": "SlowBongo", + "evtest-error-desc": "Keyboard monitoring stopped unexpectedly. Restarting..." + } +} diff --git a/noctalia/plugins/slowbongo/manifest.json b/noctalia/plugins/slowbongo/manifest.json new file mode 100644 index 0000000..a831348 --- /dev/null +++ b/noctalia/plugins/slowbongo/manifest.json @@ -0,0 +1,34 @@ +{ + "id": "slowbongo", + "name": "Slow Bongo", + "version": "0.8.0", + "minNoctaliaVersion": "3.6.0", + "author": "tui", + "description": "A bongo cat that sits in your bar and slaps when you type.", + "license": "MIT", + "repository": "https://github.com/noctalia-dev/noctalia-plugins", + "tags": [ + "Bar", + "Audio", + "Fun"], + "entryPoints": { + "main": "Main.qml", + "barWidget": "BarWidget.qml", + "settings": "Settings.qml" + }, + "dependencies": { + "plugins": [] + }, + "metadata": { + "defaultSettings": { + "idleTimeout": 150, + "waitingTimeout": 30000, + "catColor": "default", + "catSize": 1.0, + "catOffsetY": 0.0, + "raveMode": false, + "tappyMode": false, + "useMprisFilter": false + } + } +} diff --git a/noctalia/plugins/slowbongo/preview.png b/noctalia/plugins/slowbongo/preview.png new file mode 100644 index 0000000..3c13819 Binary files /dev/null and b/noctalia/plugins/slowbongo/preview.png differ diff --git a/noctalia/plugins/slowbongo/settings.json b/noctalia/plugins/slowbongo/settings.json new file mode 100644 index 0000000..d06a844 --- /dev/null +++ b/noctalia/plugins/slowbongo/settings.json @@ -0,0 +1,13 @@ +{ + "idleTimeout": 150, + "waitingTimeout": 30000, + "catColor": "default", + "catSize": 1, + "catOffsetY": 0, + "raveMode": false, + "tappyMode": true, + "useMprisFilter": false, + "inputDevices": [ + "/dev/input/event3" + ] +} diff --git a/noctalia/settings.json b/noctalia/settings.json new file mode 100644 index 0000000..9f5082c --- /dev/null +++ b/noctalia/settings.json @@ -0,0 +1,793 @@ +{ + "appLauncher": { + "autoPasteClipboard": false, + "clipboardWatchImageCommand": "wl-paste --type image --watch cliphist store", + "clipboardWatchTextCommand": "wl-paste --type text --watch cliphist store", + "clipboardWrapText": true, + "customLaunchPrefix": "", + "customLaunchPrefixEnabled": false, + "density": "default", + "enableClipPreview": true, + "enableClipboardChips": true, + "enableClipboardHistory": true, + "enableClipboardSmartIcons": true, + "enableSessionSearch": true, + "enableSettingsSearch": true, + "enableWindowsSearch": true, + "iconMode": "tabler", + "ignoreMouseInput": false, + "overviewLayer": false, + "pinnedApps": [ + ], + "position": "center", + "screenshotAnnotationTool": "", + "showCategories": true, + "showIconBackground": true, + "sortByMostUsed": true, + "terminalCommand": "kitty -e", + "viewMode": "list" + }, + "audio": { + "mprisBlacklist": [ + ], + "preferredPlayer": "", + "spectrumFrameRate": 120, + "spectrumMirrored": true, + "visualizerType": "linear", + "volumeFeedback": false, + "volumeFeedbackSoundFile": "", + "volumeOverdrive": false, + "volumeStep": 5 + }, + "bar": { + "autoHideDelay": 500, + "autoShowDelay": 150, + "backgroundOpacity": 0.93, + "barType": "floating", + "capsuleColorKey": "none", + "capsuleOpacity": 1, + "contentPadding": 2, + "density": "default", + "displayMode": "always_visible", + "enableExclusionZoneInset": false, + "fontScale": 1, + "frameRadius": 12, + "frameThickness": 8, + "hideOnOverview": false, + "marginHorizontal": 4, + "marginVertical": 4, + "middleClickAction": "none", + "middleClickCommand": "", + "middleClickFollowMouse": false, + "monitors": [ + ], + "mouseWheelAction": "none", + "mouseWheelWrap": true, + "outerCorners": true, + "position": "top", + "reverseScroll": false, + "rightClickAction": "controlCenter", + "rightClickCommand": "", + "rightClickFollowMouse": true, + "screenOverrides": [ + ], + "showCapsule": false, + "showOnWorkspaceSwitch": true, + "showOutline": false, + "useSeparateOpacity": true, + "widgetSpacing": 6, + "widgets": { + "center": [ + { + "compactMode": false, + "hideMode": "hidden", + "hideWhenIdle": false, + "id": "MediaMini", + "maxWidth": 200, + "panelShowAlbumArt": true, + "scrollingMode": "hover", + "showAlbumArt": false, + "showArtistFirst": false, + "showProgressRing": true, + "showVisualizer": true, + "textColor": "none", + "useFixedWidth": true, + "visualizerType": "linear" + } + ], + "left": [ + { + "colorizeDistroLogo": false, + "colorizeSystemIcon": "none", + "colorizeSystemText": "none", + "customIconPath": "", + "enableColorization": true, + "icon": "noctalia", + "id": "ControlCenter", + "useDistroLogo": true + }, + { + "clockColor": "none", + "customFont": "Sans Serif", + "formatHorizontal": "HH:mm", + "formatVertical": "HH mm - dd MM", + "id": "Clock", + "tooltipFormat": "HH:mm ddd, MMM dd", + "useCustomFont": true + }, + { + "characterCount": 2, + "colorizeIcons": false, + "emptyColor": "secondary", + "enableScrollWheel": true, + "focusedColor": "primary", + "followFocusedScreen": false, + "fontWeight": "bold", + "groupedBorderOpacity": 1, + "hideUnoccupied": true, + "iconScale": 0.8, + "id": "Workspace", + "labelMode": "none", + "occupiedColor": "secondary", + "pillSize": 0.6, + "showApplications": true, + "showApplicationsHover": false, + "showBadge": true, + "showLabelsOnlyWhenOccupied": true, + "unfocusedIconsOpacity": 1 + }, + { + "colorizeIcons": false, + "hideMode": "hidden", + "id": "ActiveWindow", + "maxWidth": 250, + "scrollingMode": "hover", + "showIcon": false, + "showText": true, + "textColor": "none", + "useFixedWidth": false + } + ], + "right": [ + { + "blacklist": [ + ], + "chevronColor": "none", + "colorizeIcons": false, + "drawerEnabled": false, + "hidePassive": false, + "id": "Tray", + "pinned": [ + ] + }, + { + "compactMode": true, + "diskPath": "/", + "iconColor": "none", + "id": "SystemMonitor", + "showCpuCores": false, + "showCpuFreq": false, + "showCpuTemp": true, + "showCpuUsage": true, + "showDiskAvailable": false, + "showDiskUsage": false, + "showDiskUsageAsPercent": false, + "showGpuTemp": false, + "showLoadAverage": false, + "showMemoryAsPercent": false, + "showMemoryUsage": true, + "showNetworkStats": false, + "showSwapUsage": false, + "textColor": "none", + "useMonospaceFont": true, + "usePadding": false + }, + { + "displayMode": "onhover", + "iconColor": "none", + "id": "Network", + "textColor": "none" + }, + { + "displayMode": "onhover", + "iconColor": "none", + "id": "VPN", + "textColor": "none" + }, + { + "displayMode": "onhover", + "iconColor": "none", + "id": "Volume", + "middleClickCommand": "pwvucontrol || pavucontrol", + "textColor": "none" + }, + { + "applyToAllMonitors": false, + "displayMode": "onhover", + "iconColor": "none", + "id": "Brightness", + "textColor": "none" + }, + { + "displayMode": "onhover", + "iconColor": "none", + "id": "Bluetooth", + "textColor": "none" + }, + { + "deviceNativePath": "__default__", + "displayMode": "graphic-clean", + "hideIfIdle": false, + "hideIfNotDetected": true, + "id": "Battery", + "showNoctaliaPerformance": true, + "showPowerProfiles": true + }, + { + "displayMode": "onhover", + "iconColor": "none", + "id": "KeyboardLayout", + "showIcon": false, + "textColor": "none" + }, + { + "hideWhenZero": false, + "hideWhenZeroUnread": false, + "iconColor": "none", + "id": "NotificationHistory", + "showUnreadBadge": true, + "unreadBadgeColor": "primary" + }, + { + "iconColor": "none", + "id": "SessionMenu" + } + ] + } + }, + "brightness": { + "backlightDeviceMappings": [ + ], + "brightnessStep": 5, + "enableDdcSupport": false, + "enforceMinimum": true + }, + "calendar": { + "cards": [ + { + "enabled": true, + "id": "calendar-header-card" + }, + { + "enabled": true, + "id": "calendar-month-card" + }, + { + "enabled": true, + "id": "weather-card" + } + ] + }, + "colorSchemes": { + "darkMode": true, + "generationMethod": "tonal-spot", + "manualSunrise": "06:30", + "manualSunset": "18:30", + "monitorForColors": "", + "predefinedScheme": "Noctalia (default)", + "schedulingMode": "off", + "syncGsettings": true, + "useWallpaperColors": true + }, + "controlCenter": { + "cards": [ + { + "enabled": true, + "id": "profile-card" + }, + { + "enabled": true, + "id": "shortcuts-card" + }, + { + "enabled": true, + "id": "audio-card" + }, + { + "enabled": false, + "id": "brightness-card" + }, + { + "enabled": true, + "id": "weather-card" + }, + { + "enabled": true, + "id": "media-sysmon-card" + } + ], + "diskPath": "/", + "position": "close_to_bar_button", + "shortcuts": { + "left": [ + { + "id": "Network" + }, + { + "id": "Bluetooth" + }, + { + "id": "WallpaperSelector" + }, + { + "id": "NoctaliaPerformance" + } + ], + "right": [ + { + "id": "Notifications" + }, + { + "id": "PowerProfile" + }, + { + "id": "KeepAwake" + }, + { + "id": "NightLight" + } + ] + } + }, + "desktopWidgets": { + "enabled": false, + "gridSnap": false, + "gridSnapScale": false, + "monitorWidgets": [ + { + "name": "eDP-1", + "widgets": [ + { + "colorName": "primary", + "height": 72, + "hideWhenIdle": false, + "id": "AudioVisualizer", + "roundedCorners": true, + "scale": 1.116249091396632, + "showBackground": true, + "visualizerType": "linear", + "width": 320, + "x": 1078, + "y": 700 + }, + { + "clockColor": "none", + "clockStyle": "digital", + "customFont": "", + "format": "HH:mm\\nd MMMM yyyy", + "id": "Clock", + "roundedCorners": true, + "scale": 1, + "showBackground": true, + "useCustomFont": false, + "x": 696, + "y": 408 + }, + { + "defaultSettings": { + "barWidth": 0.6, + "bloomIntensity": 0.5, + "customPrimaryColor": "#6750A4", + "customSecondaryColor": "#625B71", + "fadeWhenIdle": false, + "innerDiameter": 0.7, + "ringOpacity": 0.8, + "rotationSpeed": 0.5, + "sensitivity": 1.5, + "useCustomColors": false, + "visualizationMode": 3, + "waveThickness": 1 + }, + "id": "plugin:fancy-audiovisualizer", + "scale": 1.462436786352546, + "showBackground": true, + "x": 33, + "y": 64 + }, + { + "diskPath": "/", + "id": "SystemStat", + "layout": "bottom", + "roundedCorners": true, + "scale": 1, + "showBackground": true, + "statType": "CPU", + "x": 1116, + "y": 198 + } + ] + } + ], + "overviewEnabled": true + }, + "dock": { + "animationSpeed": 1, + "backgroundOpacity": 1, + "colorizeIcons": false, + "deadOpacity": 0.6, + "displayMode": "auto_hide", + "dockType": "floating", + "enabled": true, + "floatingRatio": 1, + "groupApps": true, + "groupClickAction": "cycle", + "groupContextMenuMode": "extended", + "groupIndicatorStyle": "dots", + "inactiveIndicators": true, + "indicatorColor": "primary", + "indicatorOpacity": 0.6, + "indicatorThickness": 3, + "launcherIcon": "", + "launcherIconColor": "none", + "launcherPosition": "end", + "launcherUseDistroLogo": false, + "monitors": [ + ], + "onlySameOutput": true, + "pinnedApps": [ + ], + "pinnedStatic": false, + "position": "bottom", + "showDockIndicator": false, + "showLauncherIcon": true, + "sitOnFrame": false, + "size": 1 + }, + "general": { + "allowPanelsOnScreenWithoutBar": true, + "allowPasswordWithFprintd": true, + "animationDisabled": false, + "animationSpeed": 1, + "autoStartAuth": false, + "avatarImage": "/home/sinsa/.face", + "boxRadiusRatio": 1, + "clockFormat": "hh\\nmm", + "clockStyle": "custom", + "compactLockScreen": false, + "dimmerOpacity": 0.2, + "enableBlurBehind": true, + "enableLockScreenCountdown": true, + "enableLockScreenMediaControls": false, + "enableShadows": true, + "forceBlackScreenCorners": false, + "iRadiusRatio": 1, + "keybinds": { + "keyDown": [ + "Down" + ], + "keyEnter": [ + "Return", + "Enter" + ], + "keyEscape": [ + "Esc" + ], + "keyLeft": [ + "Left" + ], + "keyRemove": [ + "Del" + ], + "keyRight": [ + "Right" + ], + "keyUp": [ + "Up" + ] + }, + "language": "", + "lockOnSuspend": true, + "lockScreenAnimations": true, + "lockScreenBlur": 0, + "lockScreenCountdownDuration": 10000, + "lockScreenMonitors": [ + ], + "lockScreenTint": 0, + "passwordChars": false, + "radiusRatio": 1, + "reverseScroll": false, + "scaleRatio": 1, + "screenRadiusRatio": 1, + "shadowDirection": "bottom_right", + "shadowOffsetX": 2, + "shadowOffsetY": 3, + "showChangelogOnStartup": true, + "showHibernateOnLockScreen": false, + "showScreenCorners": false, + "showSessionButtonsOnLockScreen": true, + "smoothScrollEnabled": true, + "telemetryEnabled": false + }, + "hooks": { + "colorGeneration": "", + "darkModeChange": "", + "enabled": true, + "performanceModeDisabled": "", + "performanceModeEnabled": "", + "screenLock": "", + "screenUnlock": "", + "session": "", + "startup": "", + "wallpaperChange": "" + }, + "idle": { + "customCommands": "[]", + "enabled": true, + "fadeDuration": 5, + "lockCommand": "", + "lockTimeout": 330, + "resumeLockCommand": "", + "resumeScreenOffCommand": "", + "resumeSuspendCommand": "", + "screenOffCommand": "", + "screenOffTimeout": 300, + "suspendCommand": "", + "suspendTimeout": 1800 + }, + "location": { + "analogClockInCalendar": false, + "autoLocate": false, + "firstDayOfWeek": -1, + "hideWeatherCityName": false, + "hideWeatherTimezone": false, + "name": "Padua", + "showCalendarEvents": true, + "showCalendarWeather": true, + "showWeekNumberInCalendar": false, + "use12hourFormat": false, + "useFahrenheit": false, + "weatherEnabled": true, + "weatherShowEffects": true, + "weatherTaliaMascotAlways": false + }, + "network": { + "bluetoothAutoConnect": true, + "bluetoothDetailsViewMode": "grid", + "bluetoothHideUnnamedDevices": false, + "bluetoothRssiPollIntervalMs": 60000, + "bluetoothRssiPollingEnabled": false, + "disableDiscoverability": false, + "networkPanelView": "wifi", + "wifiDetailsViewMode": "grid" + }, + "nightLight": { + "autoSchedule": true, + "dayTemp": "6500", + "enabled": false, + "forced": false, + "manualSunrise": "06:30", + "manualSunset": "18:30", + "nightTemp": "4000" + }, + "noctaliaPerformance": { + "disableDesktopWidgets": true, + "disableWallpaper": true + }, + "notifications": { + "backgroundOpacity": 1, + "clearDismissed": true, + "criticalUrgencyDuration": 15, + "density": "default", + "enableBatteryToast": true, + "enableKeyboardLayoutToast": true, + "enableMarkdown": false, + "enableMediaToast": false, + "enabled": true, + "location": "top_right", + "lowUrgencyDuration": 3, + "monitors": [ + ], + "normalUrgencyDuration": 8, + "overlayLayer": true, + "respectExpireTimeout": false, + "saveToHistory": { + "critical": true, + "low": true, + "normal": true + }, + "sounds": { + "criticalSoundFile": "", + "enabled": false, + "excludedApps": "discord,firefox,chrome,chromium,edge", + "lowSoundFile": "", + "normalSoundFile": "", + "separateSounds": false, + "volume": 0.5 + } + }, + "osd": { + "autoHideMs": 2000, + "backgroundOpacity": 1, + "enabled": true, + "enabledTypes": [ + 0, + 1, + 2 + ], + "location": "top_right", + "monitors": [ + ], + "overlayLayer": true + }, + "plugins": { + "autoUpdate": false, + "notifyUpdates": true + }, + "sessionMenu": { + "countdownDuration": 10000, + "enableCountdown": true, + "largeButtonsLayout": "grid", + "largeButtonsStyle": true, + "position": "center", + "powerOptions": [ + { + "action": "lock", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "1" + }, + { + "action": "suspend", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "2" + }, + { + "action": "hibernate", + "command": "", + "countdownEnabled": true, + "enabled": false, + "keybind": "" + }, + { + "action": "logout", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "3" + }, + { + "action": "rebootToUefi", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "4" + }, + { + "action": "userspaceReboot", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "5" + }, + { + "action": "reboot", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "6" + }, + { + "action": "shutdown", + "command": "", + "countdownEnabled": true, + "enabled": true, + "keybind": "7" + } + ], + "showHeader": true, + "showKeybinds": false + }, + "settingsVersion": 59, + "systemMonitor": { + "batteryCriticalThreshold": 5, + "batteryWarningThreshold": 20, + "cpuCriticalThreshold": 90, + "cpuWarningThreshold": 80, + "criticalColor": "", + "diskAvailCriticalThreshold": 10, + "diskAvailWarningThreshold": 20, + "diskCriticalThreshold": 90, + "diskWarningThreshold": 80, + "enableDgpuMonitoring": false, + "externalMonitor": "resources || missioncenter || jdsystemmonitor || corestats || system-monitoring-center || gnome-system-monitor || plasma-systemmonitor || mate-system-monitor || ukui-system-monitor || deepin-system-monitor || pantheon-system-monitor", + "gpuCriticalThreshold": 90, + "gpuWarningThreshold": 80, + "memCriticalThreshold": 90, + "memWarningThreshold": 80, + "swapCriticalThreshold": 90, + "swapWarningThreshold": 80, + "tempCriticalThreshold": 90, + "tempWarningThreshold": 80, + "useCustomColors": false, + "warningColor": "" + }, + "templates": { + "activeTemplates": [ + { + "enabled": true, + "id": "zenBrowser" + }, + { + "enabled": true, + "id": "niri" + } + ], + "enableUserTheming": false + }, + "ui": { + "boxBorderEnabled": false, + "fontDefault": "Sans Serif", + "fontDefaultScale": 1, + "fontFixed": "monospace", + "fontFixedScale": 1, + "panelBackgroundOpacity": 0.93, + "panelsAttachedToBar": true, + "scrollbarAlwaysVisible": true, + "settingsPanelMode": "attached", + "settingsPanelSideBarCardStyle": false, + "tooltipsEnabled": true, + "translucentWidgets": false + }, + "wallpaper": { + "automationEnabled": false, + "directory": "/home/sinsa/Pictures/wallpapers", + "enableMultiMonitorDirectories": false, + "enabled": true, + "favorites": [ + ], + "fillColor": "#000000", + "fillMode": "crop", + "hideWallpaperFilenames": false, + "linkLightAndDarkWallpapers": true, + "monitorDirectories": [ + ], + "overviewBlur": 0.4, + "overviewEnabled": true, + "overviewTint": 0.6, + "panelPosition": "center", + "randomIntervalSec": 300, + "setWallpaperOnAllMonitors": true, + "showHiddenFiles": false, + "skipStartupTransition": false, + "solidColor": "#1a1a2e", + "sortOrder": "name_desc", + "transitionDuration": 1500, + "transitionEdgeSmoothness": 0.05, + "transitionType": [ + "fade", + "disc", + "stripes", + "wipe", + "pixelate", + "honeycomb" + ], + "useOriginalImages": true, + "useSolidColor": false, + "useWallhaven": false, + "viewMode": "browse", + "wallhavenApiKey": "", + "wallhavenCategories": "111", + "wallhavenOrder": "desc", + "wallhavenPurity": "100", + "wallhavenQuery": "", + "wallhavenRatios": "", + "wallhavenResolutionHeight": "", + "wallhavenResolutionMode": "atleast", + "wallhavenResolutionWidth": "", + "wallhavenSorting": "relevance", + "wallpaperChangeMode": "random" + } +} diff --git a/nvim/.gitignore b/nvim/.gitignore new file mode 100644 index 0000000..cc5457a --- /dev/null +++ b/nvim/.gitignore @@ -0,0 +1,8 @@ +tt.* +.tests +doc/tags +debug +.repro +foo.* +*.log +data diff --git a/nvim/.neoconf.json b/nvim/.neoconf.json new file mode 100644 index 0000000..7c48087 --- /dev/null +++ b/nvim/.neoconf.json @@ -0,0 +1,15 @@ +{ + "neodev": { + "library": { + "enabled": true, + "plugins": true + } + }, + "neoconf": { + "plugins": { + "lua_ls": { + "enabled": true + } + } + } +} diff --git a/nvim/LICENSE b/nvim/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/nvim/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/nvim/README.md b/nvim/README.md new file mode 100644 index 0000000..185280b --- /dev/null +++ b/nvim/README.md @@ -0,0 +1,4 @@ +# 💤 LazyVim + +A starter template for [LazyVim](https://github.com/LazyVim/LazyVim). +Refer to the [documentation](https://lazyvim.github.io/installation) to get started. diff --git a/nvim/init.lua b/nvim/init.lua new file mode 100644 index 0000000..2514f9e --- /dev/null +++ b/nvim/init.lua @@ -0,0 +1,2 @@ +-- bootstrap lazy.nvim, LazyVim and your plugins +require("config.lazy") diff --git a/nvim/lazy-lock.json b/nvim/lazy-lock.json new file mode 100644 index 0000000..3155323 --- /dev/null +++ b/nvim/lazy-lock.json @@ -0,0 +1,37 @@ +{ + "LazyVim": { "branch": "main", "commit": "fca0af57cc3851b14f96a795a9c9bfafc5096dd1" }, + "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, + "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, + "catppuccin": { "branch": "main", "commit": "384f304c8b04664c9e0091fbfb3923c5f97c1bcf" }, + "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, + "cornelis": { "branch": "master", "commit": "deda7eb399efe94cc49c645da7b6f94780fe0c19" }, + "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" }, + "grug-far.nvim": { "branch": "main", "commit": "dc4684e163971bb1f5bfb93fbd4bb3e892bf9b15" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, + "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, + "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "a676ab7282da8d651e175118bcf54483ca11e46d" }, + "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, + "mini.ai": { "branch": "main", "commit": "4b0a6207341d895b6cfe9bcb1e4d3e8607bfe4f4" }, + "mini.icons": { "branch": "main", "commit": "5b9076dae1bfbe47ba4a14bc8b967cde0ab5d77e" }, + "mini.pairs": { "branch": "main", "commit": "b7fde3719340946feb75017ef9d75edebdeb0566" }, + "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-hs.vim": { "branch": "develop", "commit": "d4a6b7278ae6a1fdc64e300c3ebc1e24719af342" }, + "nvim-lint": { "branch": "master", "commit": "606b823a57b027502a9ae00978ebf4f5d5158098" }, + "nvim-lspconfig": { "branch": "master", "commit": "1d13d2b0df9a0a02904c76d7ad6810f71d404406" }, + "nvim-treesitter": { "branch": "main", "commit": "b9f9d692f1c7f0427502a3b84fa25d4bedb29ec1" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "4e91b5d0394329a229725b021a8ea217099826ef" }, + "nvim-ts-autotag": { "branch": "main", "commit": "8e1c0a389f20bf7f5b0dd0e00306c1247bda2595" }, + "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "snacks.nvim": { "branch": "main", "commit": "a049339328e2599ad6e85a69fa034ac501e921b2" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, + "ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" }, + "vim-textobj-user": { "branch": "master", "commit": "41a675ddbeefd6a93664a4dc52f302fe3086a933" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/nvim/lazyvim.json b/nvim/lazyvim.json new file mode 100644 index 0000000..d8bcaf6 --- /dev/null +++ b/nvim/lazyvim.json @@ -0,0 +1,10 @@ +{ + "extras": [ + + ], + "install_version": 8, + "news": { + "NEWS.md": "11866" + }, + "version": 8 +} \ No newline at end of file diff --git a/nvim/lua/config/autocmds.lua b/nvim/lua/config/autocmds.lua new file mode 100644 index 0000000..4221e75 --- /dev/null +++ b/nvim/lua/config/autocmds.lua @@ -0,0 +1,8 @@ +-- Autocmds are automatically loaded on the VeryLazy event +-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua +-- +-- Add any additional autocmds here +-- with `vim.api.nvim_create_autocmd` +-- +-- Or remove existing autocmds by their group name (which is prefixed with `lazyvim_` for the defaults) +-- e.g. vim.api.nvim_del_augroup_by_name("lazyvim_wrap_spell") diff --git a/nvim/lua/config/keymaps.lua b/nvim/lua/config/keymaps.lua new file mode 100644 index 0000000..2c134f7 --- /dev/null +++ b/nvim/lua/config/keymaps.lua @@ -0,0 +1,3 @@ +-- Keymaps are automatically loaded on the VeryLazy event +-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua +-- Add any additional keymaps here diff --git a/nvim/lua/config/lazy.lua b/nvim/lua/config/lazy.lua new file mode 100644 index 0000000..d73bfa1 --- /dev/null +++ b/nvim/lua/config/lazy.lua @@ -0,0 +1,53 @@ +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup({ + spec = { + -- add LazyVim and import its plugins + { "LazyVim/LazyVim", import = "lazyvim.plugins" }, + -- import/override with your plugins + { import = "plugins" }, + }, + defaults = { + -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. + -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. + lazy = false, + -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, + -- have outdated releases, which may break your Neovim install. + version = false, -- always use the latest git commit + -- version = "*", -- try installing the latest stable version for plugins that support semver + }, + install = { colorscheme = { "tokyonight", "habamax" } }, + checker = { + enabled = true, -- check for plugin updates periodically + notify = false, -- notify on update + }, -- automatically check for plugin updates + performance = { + rtp = { + -- disable some rtp plugins + disabled_plugins = { + "gzip", + -- "matchit", + -- "matchparen", + -- "netrwPlugin", + "tarPlugin", + "tohtml", + "tutor", + "zipPlugin", + }, + }, + }, +}) diff --git a/nvim/lua/config/options.lua b/nvim/lua/config/options.lua new file mode 100644 index 0000000..3ea1454 --- /dev/null +++ b/nvim/lua/config/options.lua @@ -0,0 +1,3 @@ +-- Options are automatically loaded before lazy.nvim startup +-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua +-- Add any additional options here diff --git a/nvim/lua/plugins/agda.lua b/nvim/lua/plugins/agda.lua new file mode 100644 index 0000000..41fdd0a --- /dev/null +++ b/nvim/lua/plugins/agda.lua @@ -0,0 +1,12 @@ +return { + + { + "isovector/cornelis", + name = "cornelis", + ft = "agda", + build = "stack install", + dependencies = { "neovimhaskell/nvim-hs.vim", "kana/vim-textobj-user" }, + version = "*", + enabled = true, + }, +} diff --git a/nvim/lua/plugins/example.lua b/nvim/lua/plugins/example.lua new file mode 100644 index 0000000..17f53d6 --- /dev/null +++ b/nvim/lua/plugins/example.lua @@ -0,0 +1,197 @@ +-- since this is just an example spec, don't actually load anything here and return an empty spec +-- stylua: ignore +if true then return {} end + +-- every spec file under the "plugins" directory will be loaded automatically by lazy.nvim +-- +-- In your plugin files, you can: +-- * add extra plugins +-- * disable/enabled LazyVim plugins +-- * override the configuration of LazyVim plugins +return { + -- add gruvbox + { "ellisonleao/gruvbox.nvim" }, + + -- Configure LazyVim to load gruvbox + { + "LazyVim/LazyVim", + opts = { + colorscheme = "gruvbox", + }, + }, + + -- change trouble config + { + "folke/trouble.nvim", + -- opts will be merged with the parent spec + opts = { use_diagnostic_signs = true }, + }, + + -- disable trouble + { "folke/trouble.nvim", enabled = false }, + + -- override nvim-cmp and add cmp-emoji + { + "hrsh7th/nvim-cmp", + dependencies = { "hrsh7th/cmp-emoji" }, + ---@param opts cmp.ConfigSchema + opts = function(_, opts) + table.insert(opts.sources, { name = "emoji" }) + end, + }, + + -- change some telescope options and a keymap to browse plugin files + { + "nvim-telescope/telescope.nvim", + keys = { + -- add a keymap to browse plugin files + -- stylua: ignore + { + "fp", + function() require("telescope.builtin").find_files({ cwd = require("lazy.core.config").options.root }) end, + desc = "Find Plugin File", + }, + }, + -- change some options + opts = { + defaults = { + layout_strategy = "horizontal", + layout_config = { prompt_position = "top" }, + sorting_strategy = "ascending", + winblend = 0, + }, + }, + }, + + -- add pyright to lspconfig + { + "neovim/nvim-lspconfig", + ---@class PluginLspOpts + opts = { + ---@type lspconfig.options + servers = { + -- pyright will be automatically installed with mason and loaded with lspconfig + pyright = {}, + }, + }, + }, + + -- add tsserver and setup with typescript.nvim instead of lspconfig + { + "neovim/nvim-lspconfig", + dependencies = { + "jose-elias-alvarez/typescript.nvim", + init = function() + require("lazyvim.util").lsp.on_attach(function(_, buffer) + -- stylua: ignore + vim.keymap.set( "n", "co", "TypescriptOrganizeImports", { buffer = buffer, desc = "Organize Imports" }) + vim.keymap.set("n", "cR", "TypescriptRenameFile", { desc = "Rename File", buffer = buffer }) + end) + end, + }, + ---@class PluginLspOpts + opts = { + ---@type lspconfig.options + servers = { + -- tsserver will be automatically installed with mason and loaded with lspconfig + tsserver = {}, + }, + -- you can do any additional lsp server setup here + -- return true if you don't want this server to be setup with lspconfig + ---@type table + setup = { + -- example to setup with typescript.nvim + tsserver = function(_, opts) + require("typescript").setup({ server = opts }) + return true + end, + -- Specify * to use this function as a fallback for any server + -- ["*"] = function(server, opts) end, + }, + }, + }, + + -- for typescript, LazyVim also includes extra specs to properly setup lspconfig, + -- treesitter, mason and typescript.nvim. So instead of the above, you can use: + { import = "lazyvim.plugins.extras.lang.typescript" }, + + -- add more treesitter parsers + { + "nvim-treesitter/nvim-treesitter", + opts = { + ensure_installed = { + "bash", + "html", + "javascript", + "json", + "lua", + "markdown", + "markdown_inline", + "python", + "query", + "regex", + "tsx", + "typescript", + "vim", + "yaml", + }, + }, + }, + + -- since `vim.tbl_deep_extend`, can only merge tables and not lists, the code above + -- would overwrite `ensure_installed` with the new value. + -- If you'd rather extend the default config, use the code below instead: + { + "nvim-treesitter/nvim-treesitter", + opts = function(_, opts) + -- add tsx and treesitter + vim.list_extend(opts.ensure_installed, { + "tsx", + "typescript", + }) + end, + }, + + -- the opts function can also be used to change the default opts: + { + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + opts = function(_, opts) + table.insert(opts.sections.lualine_x, { + function() + return "😄" + end, + }) + end, + }, + + -- or you can return new options to override all the defaults + { + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + opts = function() + return { + --[[add your custom lualine config here]] + } + end, + }, + + -- use mini.starter instead of alpha + { import = "lazyvim.plugins.extras.ui.mini-starter" }, + + -- add jsonls and schemastore packages, and setup treesitter for json, json5 and jsonc + { import = "lazyvim.plugins.extras.lang.json" }, + + -- add any tools you want to have installed below + { + "williamboman/mason.nvim", + opts = { + ensure_installed = { + "stylua", + "shellcheck", + "shfmt", + "flake8", + }, + }, + }, +} diff --git a/nvim/stylua.toml b/nvim/stylua.toml new file mode 100644 index 0000000..5d6c50d --- /dev/null +++ b/nvim/stylua.toml @@ -0,0 +1,3 @@ +indent_type = "Spaces" +indent_width = 2 +column_width = 120 \ No newline at end of file diff --git a/obsidian/Cache/Cache_Data/34ec97c848ca943b_0 b/obsidian/Cache/Cache_Data/34ec97c848ca943b_0 new file mode 100644 index 0000000..ee8ede1 Binary files /dev/null and b/obsidian/Cache/Cache_Data/34ec97c848ca943b_0 differ diff --git a/obsidian/Cache/Cache_Data/5283edf90cf4ab50_0 b/obsidian/Cache/Cache_Data/5283edf90cf4ab50_0 new file mode 100644 index 0000000..68059e3 Binary files /dev/null and b/obsidian/Cache/Cache_Data/5283edf90cf4ab50_0 differ diff --git a/obsidian/Cache/Cache_Data/84841a6901110da4_0 b/obsidian/Cache/Cache_Data/84841a6901110da4_0 new file mode 100644 index 0000000..749bd79 Binary files /dev/null and b/obsidian/Cache/Cache_Data/84841a6901110da4_0 differ diff --git a/obsidian/Cache/Cache_Data/fc52697cff125bba_0 b/obsidian/Cache/Cache_Data/fc52697cff125bba_0 new file mode 100644 index 0000000..4a71ec9 Binary files /dev/null and b/obsidian/Cache/Cache_Data/fc52697cff125bba_0 differ diff --git a/obsidian/Cache/Cache_Data/index b/obsidian/Cache/Cache_Data/index new file mode 100644 index 0000000..79bd403 Binary files /dev/null and b/obsidian/Cache/Cache_Data/index differ diff --git a/obsidian/Cache/Cache_Data/index-dir/the-real-index b/obsidian/Cache/Cache_Data/index-dir/the-real-index new file mode 100644 index 0000000..6620e51 Binary files /dev/null and b/obsidian/Cache/Cache_Data/index-dir/the-real-index differ diff --git a/obsidian/Cache/No_Vary_Search/journal.baj b/obsidian/Cache/No_Vary_Search/journal.baj new file mode 100644 index 0000000..3caac6c --- /dev/null +++ b/obsidian/Cache/No_Vary_Search/journal.baj @@ -0,0 +1 @@ +K{calendar}", + "calendar": { + "mode": "year", + "mode-mon-col": 3, + "weeks-pos": "right", + "on-scroll": 1, + "format": { + "months": "{}", + "days": "{}", + "weeks": "W{}", + "weekdays": "{}", + "today": "{}" + } + } +}, + +"actions": { + "on-click-right": "mode", + "on-click-forward": "tz_up", + "on-click-backward": "tz_down", + "on-scroll-up": "shift_up", + "on-scroll-down": "shift_down" +}, + +"clock#2": { + "format": " {:%I:%M %p}", // AM PM format + //"format": " {:%H:%M}",// 24H + "format-alt": "{:%A | %H:%M | %e %B}", + "tooltip-format": "{:%Y %B}\n{calendar}" +}, + +"clock#3": { + "format": "{:%I:%M %p - %d/%b}",//for AM/PM + //"format": "{:%H:%M - %d/%b}",// 24H + "tooltip": false +}, + +"clock#4": { + "interval": 60, + "format": "{:%B | %a %d, %Y | %I:%M %p}",// AM PM format + //"format": "{:%B | %a %d, %Y | %H:%M}",// 24H + "format-alt": "{:%a %b %d, %G}", + "tooltip-format": "{:%B %Y}\n{calendar}", +}, + +"clock#5": { + "format": "{:%A, %I:%M %P}",// AM PM format + //"format": "{:%a %d | %H:%M}",// 24H + "format-alt": "{:%A, %d %B, %Y (%R)}", + "tooltip-format": "{:%B %Y}\n{calendar}", +}, + +"cpu": { + "format": "{usage}% 󰍛", + "interval": 1, + "min-length": 5, + "format-alt-click": "click", + "format-alt": "{icon0}{icon1}{icon2}{icon3} {usage:>2}% 󰍛", + "format-icons": [ + "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" + ], + "on-click-right": "gnome-system-monitor", +}, + +"disk": { + "interval": 30, + //"format": "󰋊", + "path": "/", + //"format-alt-click": "click", + "format": "{percentage_used}% 󰋊", + //"tooltip": true, + "tooltip-format": "{used} used out of {total} on {path} ({percentage_used}%)", +}, + +"hyprland/language": { + "format": "Lang: {}", + "format-en": "US", + "format-tr": "Korea", + "keyboard-name": "at-translated-set-2-keyboard", + "on-click": "hyprctl switchxkblayout $SET_KB next" +}, + +"hyprland/submap": { + "format": " {}", // Icon: expand-arrows-alt + "tooltip": false, +}, + +"hyprland/window": { + "format": "{}", + "max-length": 50, + "separate-outputs": true, + "offscreen-css": true, + "offscreen-css-text": "(inactive)", + "rewrite": { + "(.*) — Mozilla Firefox": " $1", + "(.*) - fish": "> [$1]", + "(.*) - zsh": "> [$1]", + "(.*) - $term": "> [$1]", + "(.*) - kitty": "> [$1]", + }, +}, + +"idle_inhibitor": { + "tooltip": true, + "tooltip-format-activated": "Idle_inhibitor active", + "tooltip-format-deactivated": "Idle_inhibitor not active", + "format": "{icon}", + "format-icons": { + "activated": " ", + "deactivated": " ", + } +}, + +"keyboard-state": { + //"numlock": true, + "capslock": true, + "format": { + "numlock": "N {icon}", + "capslock": "󰪛 {icon}", + }, + "format-icons": { + "locked": "", + "unlocked": "" + }, +}, + +"memory": { + "interval": 10, + "format": "{used:0.1f}G ", + "format-alt": "{percentage}% ", + "format-alt-click": "click", + "tooltip": true, + "tooltip-format": "{used:0.1f}GB/{total:0.1f}G", + "on-click-right": "$HOME/.config/hypr/scripts/WaybarScripts.sh --btop" +}, + +"mpris": { + "interval": 10, +// "format": "{player_icon} {dynamic}", + "format": "{player_icon} Media", +// "format-paused": "{status_icon} {artist} {title}", + "format-paused": "{status_icon} Media", + "on-click": "playerctl play-pause", +// "on-click": "playerctl previous", + "on-click-right": "playerctl next", + "scroll-step": 5.0, + "on-scroll-up": "$HOME/.config/hypr/scripts/volume.sh --inc", + "on-scroll-down": "$HOME/.config/hypr/scripts/volume.sh --dec", + "smooth-scrolling-threshold": 1, + "tooltip": true, + "tooltip-format": "{status_icon} {dynamic}\nClick: Play-Pause", + "player-icons": { + "chromium": "", +// "default": "", + "default": "󰌳", + "firefox": "󰗝", + "zen-twiligth": "󰗝", + "kdeconnect": "", + "mopidy": "", + "mpv": "󰐹", + "spotify": "", + "vlc": "󰕼", + }, + "status-icons": { + "paused": "󰐎", + "playing": "", + "stopped": "", + }, + "dynamic-order": ["artist", "title"], +// "ignored-players": ["firefox", "zen"], + "max-length": 10, +}, + +"network": { + "format": "{ifname}", + "format-wifi": "{icon}", + "format-ethernet": "󰌘", + "format-disconnected": "󰌙", + "tooltip-format": "{ipaddr}  {bandwidthUpBits}  {bandwidthDownBits}", + "format-linked": "󰈁 {ifname} (No IP)", + "tooltip-format-wifi": "{essid} {icon} {signalStrength}%", + "tooltip-format-ethernet": "{ifname} 󰌘", + "tooltip-format-disconnected": "󰌙 Disconnected", + "max-length": 30, + "format-icons": [ + "󰤯", "󰤟", "󰤢", "󰤥", "󰤨" + ], + "on-click-right": "$HOME/.config/hypr/scripts/WaybarScripts.sh --nmtui" +}, + +"network#speed": { + "interval": 1, + "format": "{ifname}", + "format-wifi": "{icon}  {bandwidthUpBytes}  {bandwidthDownBytes}", + "format-ethernet": "󰌘  {bandwidthUpBytes}  {bandwidthDownBytes}", +// "format-disconnected": "󰌙", + "format-disconnected": "󰲛", + "tooltip-format": "{ipaddr}", + "format-linked": "󰈁 {ifname} (No IP)", + "tooltip-format-wifi": "{essid} {icon} {signalStrength}%", + "tooltip-format-ethernet": "{ifname} 󰌘", + "tooltip-format-disconnected": "󰌙 Disconnected", + "min-length": 24, + "max-length": 24, + "format-icons": [ + "󰤯", "󰤟", "󰤢", "󰤥", "󰤨" + ] +}, + +"power-profiles-daemon": { + "format": "{icon}", + "tooltip-format": "Power profile: {profile}\nDriver: {driver}", + "tooltip": true, + "format-icons": { + "default": "", + "performance": "", + "balanced": "", + "power-saver": "" + } +}, + +"pulseaudio": { + "format": "{icon} {volume}%", + "format-bluetooth": "{icon} 󰂱 {volume}%", + "format-muted": "󰖁", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": [ + "", "", "󰕾", "" + ], + "ignored-sinks": [ + "Easy Effects Sink" + ], + }, + "scroll-step": 5.0, + "on-click": "$HOME/.config/hypr/scripts/volume.sh --toggle", + "on-click-right": "pavucontrol -t 3", + "on-scroll-up": "$HOME/.config/hypr/scripts/volume.sh --inc", + "on-scroll-down": "$HOME/.config/hypr/scripts/volume.sh --dec", + "tooltip-format": "{icon} {desc} | {volume}%", + "smooth-scrolling-threshold": 1, +}, + +"pulseaudio#1": { + "format": "{icon} {volume}%", + "format-bluetooth": "{icon} {volume}%", + "format-bluetooth-muted": " {icon}", + "format-muted": "󰸈", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pamixer --toggle-mute", + "on-click-right": "pavucontrol -t 3", + "tooltip": true, + "tooltip-format": "{icon} {desc} | {volume}%", +}, + +"pulseaudio#microphone": { + "format": "{format_source}", + "format-source": " {volume}%", + "format-source-muted": "", + "on-click": "$HOME/.config/hypr/scripts/volume.sh --toggle-mic", + "on-click-right": "pavucontrol -t 4", + "on-scroll-up": "$HOME/.config/hypr/scripts/volume.sh --mic-inc", + "on-scroll-down": "$HOME/.config/hypr/scripts/volume.sh --mic-dec", + "tooltip-format": "{source_desc} | {source_volume}%", + "scroll-step": 5, +}, + +"tray": { + "icon-size": 20, + "spacing": 4, +}, + +"wireplumber": { + "format": "{icon} {volume} %", + "format-muted": " Mute", + "on-click": "$HOME/.config/hypr/scripts/volume.sh --toggle", + "on-click-right": "pavucontrol -t 3", + "on-scroll-up": "$HOME/.config/hypr/scripts/volume.sh --inc", + "on-scroll-down": "$HOME/.config/hypr/scripts/volume.sh --dec", + "format-icons": [ + "", "", "󰕾", "" + ], +}, + +"wlr/taskbar": { + "format": "{icon} {name}", + "icon-size": 16, + "all-outputs": false, + "tooltip-format": "{title}", + "on-click": "activate", + "on-click-middle": "close", + "ignore-list": [ + "wofi", + "rofi", + "kitty", + "kitty-dropterm" + ], +}, + + +"custom/archicon": { + "format": "", + "tooltip": true, + "tooltip-format": "Ciao Sinsa :)", + "on-click": "rofi -show drun" +}, + +"cava": { +// "cava_config": "$HOME/.config/cava/config", + "framerate": 60, + "autosens": 0, +// "sensitivity": 0, + "bars": 18, + "lower_cutoff_freq": 50, + "higher_cutoff_freq": 10000, + "hide_on_silence": false, + "format_silent": "ciao", + // "sleep_timer": 5, + "method": "pipewire", + "source": "auto", + "stereo": true, + "reverse": false, + "bar_delimiter": 0, + "monstercat": false, + "waves": true, +// "noise_reduction": 0.77, + "input_delay": 2, +// "format-icons": [" ","▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ], + "format-icons": [ " ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ], + "on-click": "playerctl play-pause", + "tooltip": true, + "tooltip-format": "ciao", + "menu": "click", + + }, + +} diff --git a/waybar/ModulesCustom b/waybar/ModulesCustom new file mode 100644 index 0000000..276f3ed --- /dev/null +++ b/waybar/ModulesCustom @@ -0,0 +1,300 @@ +//* ---- 💫 https://github.com/JaKooLit 💫 ---- *// +/* Waybar Modules - Custom Modules */ +/* Basically created to reduce the lines in Waybar Modules bank */ +/* NOTE: This is only for Custom Modules */ +/* Custom Modules like weather browser, tty, file manager at the beginning */ + +{ +"custom/weather": { + "format": "{}", + "format-alt": "{alt}: {}", + "format-alt-click": "click", + "interval": 3600, + "return-type": "json", + "exec": "$HOME/.config/hypr/UserScripts/Weather.py", + //"exec": "$HOME/.config/hypr/UserScripts/Weather.sh", + //"exec-if": "ping wttr.in -c1", + "tooltip": true, +}, + +"custom/file_manager": { + "format": " ", + "on-click": "xdg-open . &", + "tooltip": true, + "tooltip-format": "File Manager", +}, + +"custom/tty": { + "format": " ", + "on-click": "$HOME/.config/hypr/scripts/WaybarScripts.sh --term", + "tooltip": true, + "tooltip-format": "Launch Terminal", +}, + +"custom/browser": { + "format": " ", + "on-click": "xdg-open https://", + "tooltip": true, + "tooltip-format": "Launch Browser", +}, + +"custom/settings": { + "format": " ", + "on-click": "$HOME/.config/hypr/scripts/Kool_Quick_Settings.sh", + "tooltip": true, + "tooltip-format": "Launch KooL Hyprland Settings Menu", +}, + +"custom/cycle_wall": { + "format": " ", + "on-click": "$HOME/.config/hypr/UserScripts/WallpaperSelect.sh", + "on-click-right": "$HOME/.config/hypr/UserScripts/WallpaperRandom.sh", + "on-click-middle": "$HOME/.config/hypr/scripts/WaybarStyles.sh", + "tooltip": true, + "tooltip-format": "Left Click: Wallpaper Menu\nMiddle Click: Random wallpaper\nRight Click: Waybar Styles Menu", +}, + +"custom/hint": { + "format": "󰺁 HINT!", + "on-click": "$HOME/.config/hypr/scripts/KeyHints.sh", + "on-click-right": "$HOME/.config/hypr/scripts/KeyBinds.sh", + "tooltip": true, + "tooltip-format": "Left Click: Quick Tips\nRight Click: Keybinds", +}, + +"custom/dot_update": { + "format": " 󰁈 ", + "on-click": "$HOME/.config/hypr/scripts/KooLsDotsUpdate.sh", + "tooltip": true, + "tooltip-format": "Check KooL Dots update\nIf available", +}, + +// Hypridle inhibitor +"custom/hypridle": { + "format": "󱫗 ", + "return-type": "json", + "escape": true, + "exec-on-event": true, + "interval": 60, + "exec": "$HOME/.config/hypr/scripts/Hypridle.sh status", + "on-click": "$HOME/.config/hypr/scripts/Hypridle.sh toggle", + "on-click-right": "hyprlock" +}, + +"custom/keyboard": { + "exec": "cat $HOME/.cache/kb_layout", + "interval": 1, + "format": " {}", + "on-click": "$HOME/.config/hypr/scripts/SwitchKeyboardLayout.sh", +}, + +"custom/light_dark": { + "format": "󰔎 ", + "on-click": "$HOME/.config/hypr/scripts/DarkLight.sh", + "on-click-right": "$HOME/.config/hypr/scripts/WaybarStyles.sh", + "on-click-middle": "$HOME/.config/hypr/UserScripts/WallpaperSelect.sh", + "tooltip": true, + "tooltip-format": "Left Click: Switch Dark-Light Themes\nMiddle Click: Wallpaper Menu\nRight Click: Waybar Styles Menu", +}, + +"custom/lock": { + "format": "󰌾", + "on-click": "$HOME/.config/hypr/scripts/LockScreen.sh", + "tooltip": true, + "tooltip-format": "󰷛 Screen Lock", +}, + +"custom/menu": { + "format": "  ", + "on-click": "pkill rofi || rofi -show drun -modi run,drun,filebrowser,window", + "on-click-middle": "$HOME/.config/hypr/UserScripts/WallpaperSelect.sh", + "on-click-right": "$HOME/.config/hypr/scripts/WaybarLayout.sh", + "tooltip": true, + "tooltip-format": "Left Click: Rofi Menu\nMiddle Click: Wallpaper Menu\nRight Click: Waybar Layout Menu", +}, +// This is a custom cava visualizer +"custom/cava_mviz": { + "exec": "$HOME/.config/hypr/scripts/waybarcava.sh", + "format": "{}" +}, + +"custom/playerctl": { + "format": "{}", + "return-type": "json", + "max-length": 25, + "exec": "playerctl -a metadata --format '{\"text\": \"{{artist}} {{markup_escape(title)}}\", \"tooltip\": \"{{playerName}} : {{markup_escape(title)}}\", \"alt\": \"{{status}}\", \"class\": \"{{status}}\"}' -F", + "on-click-middle": "playerctl play-pause", + "on-click": "playerctl previous", + "on-click-right": "playerctl next", + "scroll-step": 5.0, + "on-scroll-up": "$HOME/.config/hypr/scripts/volume.sh --inc", + "on-scroll-down": "$HOME/.config/hypr/scripts/volume.sh --dec", + "smooth-scrolling-threshold": 1, +}, + +"custom/power": { + "format": "⏻", + "on-click": "$HOME/.config/hypr/scripts/Wlogout.sh", + "on-click-right": "$HOME/.config/hypr/scripts/ChangeBlur.sh", + "tooltip": true, + "tooltip-format":"Logout Menu", +}, + +"custom/reboot": { + "format": "󰜉", + "on-click": "systemctl reboot", + "tooltip": true, + "tooltip-format": "Left Click: Reboot", +}, + +"custom/quit": { + "format": "󰗼", + "on-click": "hyprctl dispatch exit", + "tooltip": true, + "tooltip-format": "Left Click: Exit Hyprland", +}, + +"custom/swaync": { + "tooltip": true, + "tooltip-format": "Left Click: Launch Notification Center\nRight Click: Do not Disturb", + "format": "{} {icon} ", + "format-icons": { + "notification": "", + "none": "", + "dnd-notification": "", + "dnd-none": "", + "inhibited-notification": "", + "inhibited-none": "", + "dnd-inhibited-notification": "", + "dnd-inhibited-none": "" + }, + "return-type": "json", + "exec-if": "which swaync-client", + "exec": "swaync-client -swb", + "on-click": "sleep 0.1 && swaync-client -t -sw", + "on-click-right": "swaync-client -d -sw", + "escape": true, +}, +// NOTE:! This is mainly for Arch and Arch Based Distros depend: pacman-contrib +// Other Distro dont have notifications but can use to check for update for any other distro +"custom/updater": { + "format": " {}", + "exec": "checkupdates | wc -l", + "exec-if": "[[ $(checkupdates | wc -l) ]]", + "interval": 43200, // (Arch Linux will try to check 12 hrs interval only + "on-click": "$HOME/.config/hypr/scripts/Distro_update.sh", + "tooltip": true, + "tooltip-format": "Left Click: Update System\nArch (w/ notification)\nFedora, OpenSuse, Debian/Ubuntu click to update", +}, + +//VPN checker and user + +"custom/vpn": { + "format": "{}", + "return-type": "json", + "interval": 3, + "exec": "~/.config/hypr/scripts/vpn.sh", + "tooltip": true +}, + +"custom/cava": { + "format": "{icon}{text}", + "format-icons": { + // "Playing": " ", // Uncomment if not using caway + "Paused": " ", + "Stopped": "‭ﭥ ", // This stop symbol is RTL. So ‭ is left-to-right override. + }, + "escape": true, + "tooltip": true, + "exec": "~/.config/waybar/caway", + "return-type": "json", + "on-click": "playerctl play-pause", + "on-scroll-up": "playerctl previous", + "on-scroll-down": "playerctl next", + "on-click-right": "g4music", + "max-length": 35 + }, + + + +// Separators +"custom/separator#dot": { + "format": "", + "interval": "once", + "tooltip": false +}, +"custom/separator#dot-line": { + "format": "", + "interval": "once", + "tooltip": false +}, +"custom/separator#line": { + "format": "|", + "interval": "once", + "tooltip": false +}, +"custom/separator#blank": { + "format": "", + "interval": "once", + "tooltip": false +}, +"custom/separator#blank_2": { + "format": " ", + "interval": "once", + "tooltip": false +}, +"custom/separator#blank_3": { + "format": " ", + "interval": "once", + "tooltip": false +}, +"custom/arrow1": { + "format": "", + "tooltip": false +}, + +"custom/arrow2": { + "format": "", + "tooltip": false +}, + +"custom/arrow3": { + "format": "", + "tooltip": false +}, + +"custom/arrow4": { + "format": "", + "tooltip": false +}, + +"custom/arrow5": { + "format": "", + "tooltip": false +}, + +"custom/arrow6": { + "format": "", + "tooltip": false +}, + +"custom/arrow7": { + "format": "", + "tooltip": false +}, + +"custom/arrow8": { + "format": "", + "tooltip": false +}, + +"custom/arrow9": { + "format": "", + "tooltip": false +}, + +"custom/arrow10": { + "format": "", + "tooltip": false +} +} diff --git a/waybar/ModulesGroups b/waybar/ModulesGroups new file mode 100644 index 0000000..8271d83 --- /dev/null +++ b/waybar/ModulesGroups @@ -0,0 +1,140 @@ +//* ---- 💫 https://github.com/JaKooLit 💫 ---- *// +/* Waybar Modules - Groups Modules */ +/* Basically created to reduce the lines in Waybar Modules bank */ +/* NOTE: This is only for Groups */ + +{ +// GROUPS +"group/app_drawer": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "custom/menu", + "transition-left-to-right": true + }, + "modules": [ + "custom/menu", + "custom/light_dark", + "custom/file_manager", + "custom/tty", + "custom/browser", + "custom/settings", + ] +}, +"group/motherboard": { + "orientation": "horizontal", + "modules": [ + "cpu", + "power-profiles-daemon", + "memory", + "temperature", + "disk", + ] +}, + +"group/mobo_drawer": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "cpu", + "transition-left-to-right": true + }, + "modules": [ + "battery", + "memory", + "cpu", + "power-profiles-daemon", + "disk", + "temperature", + ] +}, +"group/laptop": { + "orientation": "inherit", + "modules": [ + "backlight", + "battery", + ] +}, +"group/audio": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "pulseaudio", + "transition-left-to-right": true + }, + "modules": [ + "pulseaudio", + "pulseaudio#microphone", + ] +}, + +"group/connections": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "network", + "transition-left-to-right": true + }, + "modules": [ + "network", + "bluetooth", + "backlight", + ] +}, + +"group/status": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "custom/power", + "transition-left-to-right": false + }, + "modules": [ + "custom/power", + "custom/lock", + "keyboard-state", + "custom/keyboard", + ] +}, +"group/notify": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "custom/swaync", + "transition-left-to-right": false + }, + "modules": [ + "custom/swaync", + ] +}, + +"group/power": { + "orientation": "inherit", + "drawer": { + "transition-duration": 500, + "children-class": "drawer-child", + "transition-left-to-right": false + }, + "modules": [ + "custom/power", + "custom/quit", + "custom/lock", + "custom/reboot" + ] +}, +// groups for vertical +"group/power#vert": { + "orientation": "inherit", + "drawer": { + "transition-duration": 300, + "children-class": "not-memory", + "transition-left-to-right": false + }, + "modules": [ + "custom/power", + "custom/lock", + "custom/logout", + "custom/reboot" + ] +}, +} diff --git a/waybar/ModulesWorkspaces b/waybar/ModulesWorkspaces new file mode 100644 index 0000000..15494ca --- /dev/null +++ b/waybar/ModulesWorkspaces @@ -0,0 +1,321 @@ +//* ---- 💫 https://github.com/JaKooLit 💫 ---- *// +/* Waybar Workspaces modules */ + +/* Generally, this is a potential expanding of choices for hyprland/workspace */ +// HYPRLAND WORKSPACES. CHOOSE as desired and place on waybar configs + +{ +// CIRCLES Style +"hyprland/workspaces": { + "active-only": false, + "all-outputs": true, + "format": "{icon}", + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "persistent-workspaces": { + "*": 1 + }, + "format-icons": { + "active": "", + "default": "", + }, +}, +// ROMAN Numerals style +"hyprland/workspaces#roman": { + "active-only": false, + "all-outputs": true, + "format": "{icon}", + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "persistent-workspaces": { + "*": 5 + }, + "format-icons": { + "1": "I", + "2": "II", + "3": "III", + "4": "IV", + "5": "V", + "6": "VI", + "7": "VII", + "8": "VIII", + "9": "IX", + "10": "X", + }, +}, +// PACMAN Style +"hyprland/workspaces#pacman": { + "active-only": false, + "all-outputs": true, + "format": "{icon}", + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "show-special": false, + "persistent-workspaces": { + "*": 5 + }, + "format": "{icon}", + "format-icons": { + "active": "󰮯", + "empty": "", + "default": "󰊠", + }, +}, +// Kanji / Japanese style +"hyprland/workspaces#kanji": { + "disable-scroll": true, + "show-special": false, + "all-outputs": true, + "format": "{icon}", + "persistent-workspaces": { + "*": 5 + }, + "format-icons": { + "1": "一", + "2": "二", + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "7": "七", + "8": "八", + "9": "九", + "10": "十", + } +}, +// for Camilla or Spanish +"hyprland/workspaces#cam": { + "active-only":false, + "all-outputs": true, + "format": "{icon}", + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "persistent-workspaces": { + "*": 5 + }, + "format-icons": { + "1": "Uno", + "2": "Due", + "3": "Tre", + "4": "Quattro", + "5": "Cinque", + "6":"Sei", + "7":"Sette", + "8":"Otto", + "9":"Nove", + "10":"Dieci" + } + }, + +// NUMBERS and ICONS style +"hyprland/workspaces#4": { + "format": "{name}", + "format": " {name} {icon} ", + //"format": " {icon} ", + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "all-outputs": true, + "sort-by-number": true, + "format-icons": { + "1": " ", + "2": " ", + "3": " ", + "4": " ", + "5": " ", + "6": " ", + "7": "", + "8": " ", + "9": "", + "10": "10", + "focused": "", + "default": "", + }, +}, +// numbers styles +"hyprland/workspaces#numbers": { + "active-only": false, + "all-outputs": true, + "format": "{icon}", + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "persistent-workspaces": { + "*": 5 + }, + "format-icons": { + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9", + "10": "10", + }, +}, +// ALPHABET Style +"hyprland/workspaces#alpha": { + "active-only": false, + "all-outputs": true, + "format": "{icon}", + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "persistent-workspaces": { + "*": 5 + }, + "format-icons": { + "1": "A", + "2": "B", + "3": "C", + "4": "D", + "5": "E", + "6": "F", + "7": "G", + "8": "H", + "9": "I", + "10": "J", + }, +}, +// NUMBERS and ICONS style with window rewrite +"hyprland/workspaces#rw": { + "disable-scroll": true, + "all-outputs": false, + "warp-on-scroll": false, + "sort-by-number": true, + "show-special": false, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace e+1", + "on-scroll-down": "hyprctl dispatch workspace e-1", + "persistent-workspaces": { + "*": 1 + }, + // "format": "{icon} {windows}", + "format": "{windows}", + + + "format-window-separator": "|", + "window-rewrite-default": "󰣆", + "window-rewrite": { + "title<.*amazon.*>": "", + "title<.*reddit.*>": "", + "title<.*idagio.*>": "𝄢", + "class": " ", + //"class": "", + //"class": "bank󰖟", + "class": "󰗝", + "class": "", + "class": " ", + "class": "", + "class": "", + "class": "🦁", + "class": "", + "class": "🦊", + "class": "", + "class": "󰄛", + "class": "", + "class": "", + "class": "", + "class": "", + "class": "", + "title": "", + "class": "", + "class<[Tt]hunderbird|[Tt]hunderbird-esr>": "", + "class": "", + "title<.*gmail.*>": "󰊫", + "class": "󱞎", + "class<[Tt]elegram-desktop|org.telegram.desktop|io.github.tdesktop_x64.TDesktop>": "", + "class": "", + "title<.*whatsapp.*>": "", + "title<.*zapzap.*>": "", + "title<.*messenger.*>": "", + "title<.*facebook.*>": "", + "title<.*reddit.*>": "", + "class": "󰠮", + "class": "", + "class": "", + "title<.*ChatGPT.*>": "󰚩", + "title<.*deepseek.*>": "󰚩", + "title<.*qwen.*>": "󰚩", + "class": "󰅳", + "class": "", + "class": "🪨", + "class": "", + "class": "", + "class": "󰎆", + "title<.*Picture-in-Picture.*>": "", + "title<.*youtube.*>": "", + "class": "󰕼", + "title<.*cmus.*>": "", + "class<[Ss]potify>": "", + "title<.*.pdf>": "", + "class": "", + "class": "", + "class<.virt-manager-wrapped>": "", + "class": "💽", + "title": "💽", + "class": "🖥️", + "class": "󰍳", + "class": "󰨞", + "class": "󰵁", + "class": "󰅩", + "title<.*github.*>": "", + "class": "", + "class": "", + "class": "󰏆", + "class": "", + "title": "", + "title": "", + //"title<.*vim ~ .*>": "", + //"title<.*nvim.*>": "", + "title<.*figma.*>": "", + "title<.*jira.*>": "", + "class": "", + + "class": "", + + "class": "󰒃", + "class": "", + "class<[Pp]avucontrol|org.pulseaudio.pavucontrol>": "󱡫", + "class": "", + "class": "󰝰", + "class":"", + "class": "", + "class": "📱", + "class": "", + "class": "󰓃", + "class":"", + "class": "󰹛", + } + }, +} + + +"niri/workspaces": { + "format": "{index}", + +}, + +"wlr/taskbar": { + "format": "{icon}", + "icon-size": {}, + "icon-theme": "${i_theme}", + "spacing": 0, + "tooltip-format": "{icon}", + "on-click": "activate", + "on-click-middle": "close", + "on-click-right": "fullscreen" +}, diff --git a/waybar/caway b/waybar/caway new file mode 100755 index 0000000..9aa31d2 --- /dev/null +++ b/waybar/caway @@ -0,0 +1,114 @@ +#!/usr/bin/bash + +# Nuke all internal spawns when script dies +trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM + +BARS=18 +FRAMERATE=60 +EQUILIZER=1 + +# Get script options +while getopts 'b:f:m:eh' flag; do + case "${flag}" in + b) BARS="${OPTARG}" ;; + f) FRAMERATE="${OPTARG}" ;; + e) EQUILIZER=0 ;; + h) + echo "caway usage: caway [ options ... ]" + echo "where options include:" + echo + echo " -b (Number of bars to display. Default 8)" + echo " -f (Framerate of the equilizer. Default 60)" + echo " -e (Disable equilizer. Default enabled)" + echo " -h (Show help message)" + exit 0 + ;; + esac +done + +bar="▁▂▃▄▅▆▇█" +dict="s/;//g;" + +# creating "dictionary" to replace char with bar + thin space " " +i=0 +while [ $i -lt ${#bar} ]; do + dict="${dict}s/$i/${bar:$i:1} /g;" + i=$((i = i + 1)) +done + +# Remove last extra thin space +dict="${dict}s/.$//;" + +clean_create_pipe() { + if [ -p $1 ]; then + unlink $1 + fi + mkfifo $1 +} + +kill_pid_file() { + if [[ -f $1 ]]; then + while read pid; do + { kill "$pid" && wait "$pid"; } 2>/dev/null + done <$1 + fi +} + +# PID of the cava process and while loop launched from the script +cava_waybar_pid="/tmp/cava_waybar_pid" + +# Clean pipe for cava +cava_waybar_pipe="/tmp/cava_waybar.fifo" +clean_create_pipe $cava_waybar_pipe + +# Custom cava config +cava_waybar_config="/tmp/cava_waybar_config" +echo " +[general] +mode = normal +framerate = $FRAMERATE +bars = $BARS + +[output] +method = raw +raw_target = $cava_waybar_pipe +data_format = ascii +ascii_max_range = 7 +" >$cava_waybar_config + +# Clean pipe for playerctl +playerctl_waybar_pipe="/tmp/playerctl_waybar.fifo" +clean_create_pipe $playerctl_waybar_pipe + +# playerctl output into playerctl_waybar_pipe +playerctl -a metadata --format '{"text": "{{artist}} - {{title}}", "tooltip": "{{playerName}} : {{markup_escape(artist)}} - {{markup_escape(title)}}", "alt": "{{status}}", "class": "{{status}}"}' -F >$playerctl_waybar_pipe & + +# Read the playerctl o/p via its fifo pipe +while read -r line; do + # Kill the cava process to stop the input to cava_waybar_pipe + kill_pid_file $cava_waybar_pid + + echo "$line" | jq --unbuffered --compact-output + + # If the class says "Playing" and equilizer is enabled + # then show the cava equilizer + if [[ $EQUILIZER == 1 && $(echo $line | jq -r '.class') == 'Playing' ]]; then + # Show the playing title for 2 seconds + sleep 2 + + # cava output into cava_waybar_pipe + cava -p $cava_waybar_config >$cava_waybar_pipe & + + # Save the PID of child process + echo $! >$cava_waybar_pid + + # Read the cava o/p via its fifo pipe + while read -r cmd2; do + # Change the "text" key to bars + echo "$line" | jq --arg a $(echo $cmd2 | sed "$dict") '.text = $a' --unbuffered --compact-output + done <$cava_waybar_pipe & # Do this fifo read in background + + # Save the while loop PID into the file as well + echo $! >>$cava_waybar_pid + fi +done <$playerctl_waybar_pipe diff --git a/waybar/colors.css b/waybar/colors.css new file mode 100644 index 0000000..626fa5c --- /dev/null +++ b/waybar/colors.css @@ -0,0 +1,105 @@ +/* +* Css Colors +* Generated with Matugen +*/ + + @define-color background #151218; + + @define-color error #ffb4ab; + + @define-color error_container #93000a; + + @define-color inverse_on_surface #322f35; + + @define-color inverse_primary #69548d; + + @define-color inverse_surface #e7e0e8; + + @define-color on_background #e7e0e8; + + @define-color on_error #690005; + + @define-color on_error_container #ffdad6; + + @define-color on_primary #3a255b; + + @define-color on_primary_container #ecdcff; + + @define-color on_primary_fixed #240e45; + + @define-color on_primary_fixed_variant #513c73; + + @define-color on_secondary #342d40; + + @define-color on_secondary_container #eadef7; + + @define-color on_secondary_fixed #1f182a; + + @define-color on_secondary_fixed_variant #4b4357; + + @define-color on_surface #e7e0e8; + + @define-color on_surface_variant #cbc4cf; + + @define-color on_tertiary #4a252f; + + @define-color on_tertiary_container #ffd9e0; + + @define-color on_tertiary_fixed #32101a; + + @define-color on_tertiary_fixed_variant #643b45; + + @define-color outline #958e99; + + @define-color outline_variant #49454e; + + @define-color primary #d4bbfc; + + @define-color primary_container #513c73; + + @define-color primary_fixed #ecdcff; + + @define-color primary_fixed_dim #d4bbfc; + + @define-color scrim #000000; + + @define-color secondary #cec2db; + + @define-color secondary_container #4b4357; + + @define-color secondary_fixed #eadef7; + + @define-color secondary_fixed_dim #cec2db; + + @define-color shadow #000000; + + @define-color source_color #533d78; + + @define-color surface #151218; + + @define-color surface_bright #3b383e; + + @define-color surface_container #211e24; + + @define-color surface_container_high #2c292f; + + @define-color surface_container_highest #37343a; + + @define-color surface_container_low #1d1a20; + + @define-color surface_container_lowest #0f0d12; + + @define-color surface_dim #151218; + + @define-color surface_tint #d4bbfc; + + @define-color surface_variant #49454e; + + @define-color tertiary #f1b7c3; + + @define-color tertiary_container #643b45; + + @define-color tertiary_fixed #ffd9e0; + + @define-color tertiary_fixed_dim #f1b7c3; + diff --git a/waybar/configs/BK/default.1.bk b/waybar/configs/BK/default.1.bk new file mode 100644 index 0000000..a0f5b46 --- /dev/null +++ b/waybar/configs/BK/default.1.bk @@ -0,0 +1,58 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 3, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "custom/archicon", + "clock", + "custom/separator#blank", + "hyprland/workspaces#rw" +// "custom/separator#blank" + // "hyprland/window", + ], + +"modules-center": [ +// "wlr/taskbar", + "mpris", + "cava", + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/mobo_drawer", +// "battery", +// "custom/separator#blank", + "group/connections", +// "network", +// "bluetooth", + "group/audio", +// "custom/separator#blank", +// "backlight", + "tray", +// "clock", + "group/notify", + "custom/power", + ], +} + diff --git a/waybar/configs/Modules b/waybar/configs/Modules new file mode 100644 index 0000000..e69de29 diff --git a/waybar/configs/[TOP] 0-Ja-0 Been modified b/waybar/configs/[TOP] 0-Ja-0 Been modified new file mode 100644 index 0000000..44c05ca --- /dev/null +++ b/waybar/configs/[TOP] 0-Ja-0 Been modified @@ -0,0 +1,50 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", +# "$HOME/.config/waybar/UserModules", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 3, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + "clock", + "custom/separator#blank", + "tray", + ], + +"modules-center": [ + "group/app_drawer", + "custom/separator#dot-line", + "hyprland/workspaces#kanji", + "custom/separator#dot-line", + "group/notify", + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/laptop", + "custom/separator#blank", + "group/mobo_drawer", + "custom/separator#line", + "group/audio", + "custom/separator#dot-line", + "custom/separator#blank", + "group/status", + ], +} diff --git a/waybar/configs/bintang default b/waybar/configs/bintang default new file mode 100644 index 0000000..15f4f42 --- /dev/null +++ b/waybar/configs/bintang default @@ -0,0 +1,46 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 3, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "clock", + "custom/separator#blank", + "tray", + ], + +"modules-center": [ + "hyprland/workspaces#rw", + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/notify", + "battery", + "custom/separator#blank", + "group/audio", + "custom/separator#blank", + "custom/power", + ], +} + diff --git a/waybar/configs/default b/waybar/configs/default new file mode 100644 index 0000000..5e34c9d --- /dev/null +++ b/waybar/configs/default @@ -0,0 +1,61 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 3, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "custom/archicon", + "clock", + "custom/separator#blank", + "hyprland/workspaces#rw" +// "custom/separator#blank" + // "hyprland/window", + ], + +"modules-center": [ +// "wlr/taskbar", +// "mpris", +// "custom/cava" +// "custom/playerinfo" + "cava" + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/mobo_drawer", +// "battery", +// "custom/separator#blank", + "group/connections", +// "network", +// "bluetooth", + "group/audio", +// "custom/separator#blank", +// "backlight", + "tray", +// "clock", + "group/notify", + "custom/power" +// "custom/vpn", + ], +} + diff --git a/waybar/configs/defaultNIRI b/waybar/configs/defaultNIRI new file mode 100644 index 0000000..f38c9bc --- /dev/null +++ b/waybar/configs/defaultNIRI @@ -0,0 +1,61 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 3, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "custom/archicon", + "clock", + "custom/separator#blank", + "niri/workspaces" +// "custom/separator#blank" + // "hyprland/window", + ], + +"modules-center": [ +// "wlr/taskbar", +// "mpris", +// "custom/cava" +// "custom/playerinfo" + "cava" + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/mobo_drawer", +// "battery", +// "custom/separator#blank", + "group/connections", +// "network", +// "bluetooth", + "group/audio", +// "custom/separator#blank", +// "backlight", + "tray", +// "clock", + "group/notify", + "custom/power" +// "custom/vpn", + ], +} + diff --git a/waybar/configs/mpris middle b/waybar/configs/mpris middle new file mode 100644 index 0000000..aaec387 --- /dev/null +++ b/waybar/configs/mpris middle @@ -0,0 +1,49 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + "$HOME/.config/waybar/UserModules", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 3, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "clock", + "custom/separator#blank", + "tray", + "custom/separator#blank", + "hyprland/workspaces#alpha", + ], + +"modules-center": [ + "mpris", + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/notify", + "battery", + "custom/separator#blank", + "group/audio", + "custom/separator#blank", + "custom/power", + ], +} + diff --git a/waybar/configs/taskbar b/waybar/configs/taskbar new file mode 100644 index 0000000..ed73e13 --- /dev/null +++ b/waybar/configs/taskbar @@ -0,0 +1,48 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + "$HOME/.config/waybar/UserModules", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 0, +"margin-left": 0, +"margin-right": 0, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "tray", + "custom/separator#line", + "custom/separator#blank", + "hyprland/workspaces#alpha", + ], + +"modules-center": [ + "clock", + ], + +"modules-right": [ + //"mpris", + "group/notify", + "custom/separator#dot-line", + "battery", + "custom/separator#blank", + "group/audio", + "custom/separator#dot-line", + "custom/power", + ], +} + diff --git a/waybar/configs/window middle b/waybar/configs/window middle new file mode 100644 index 0000000..1910f31 --- /dev/null +++ b/waybar/configs/window middle @@ -0,0 +1,49 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ + +/* My Mostly Used waybar config incase you wonder :) */ +{ +"include": [ + "$HOME/.config/waybar/Modules", + "$HOME/.config/waybar/ModulesWorkspaces", + "$HOME/.config/waybar/ModulesCustom", + "$HOME/.config/waybar/ModulesGroups", + "$HOME/.config/waybar/UserModules", + ], +"layer": "bottom", +//"mode": "dock", +"exclusive": true, +"passthrough": false, +"position": "top", +"spacing": 3, +"fixed-center": true, +"ipc": true, +"margin-top": 5, +"margin-left": 8, +"margin-right": 8, + +"modules-left": [ + //"idle_inhibitor", + //"custom/separator#blank", + "clock", + "custom/separator#dot-blank", + "tray", + "custom/separator#blank", + "hyprland/workspaces#alpha", + ], + +"modules-center": [ + "hyprland/window", + ], + +"modules-right": [ + //"mpris", + //"custom/separator#dot-line", + "group/notify", + "battery", + "custom/separator#blank", + "group/audio", + "custom/separator#blank", + "custom/power", + ], +} + diff --git a/waybar/style/bintang default.css b/waybar/style/bintang default.css new file mode 100644 index 0000000..d0eb472 --- /dev/null +++ b/waybar/style/bintang default.css @@ -0,0 +1,216 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ +/* Black & White MonoChrome */ +/* @import '../../.config/waybar/wallust/colors-waybar.css'; */ +@import "colors.css"; + + +* { + font-family: "JetBrainsMono Nerd Font Propo"; + font-weight: bold; + min-height: 0; + /* set font-size to 100% if font scaling is set to 1.00 using nwg-look */ + font-size: 98%; + font-feature-settings: '"zero", "ss01", "ss02", "ss03", "ss04", "ss05", "cv31"'; +} + +window#waybar, +window#waybar.empty, +window#waybar.empty #window { + background-color: transparent; + padding: 0px; + border: 0px; +} + +tooltip { + color: @inverse_surface; + background: rgba(0, 0, 0, 0.8); + border-radius: 20px; +} + +tooltip label{ + color: @inverse_surface; +} +/*-----module groups----*/ +.modules-right { + background-color: rgba(0,0,0,0.5); + color: @secondary; + border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-center { + background-color: rgba(0,0,0,0.5); + color: @secondary; + border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-left { + background-color: rgba(0,0,0,0.5); + color: @secondary; + border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +/*-----modules indv----*/ +#taskbar button, +#workspaces button { + color: @outline; + box-shadow: none; + text-shadow: none; + padding: 0px; + border-radius: 9px; + padding-left: 4px; + padding-right: 4px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.5s cubic-bezier(.55,-0.68,.48,1.682); +} +#taskbar button:hover, +#workspaces button:hover { + color: @on_secondary_fixed_variant; + border-radius: 20px; + padding-left: 2px; + padding-right: 2px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); +} + +#taskbar button.active, +#workspaces button.active { + color: @inverse_surface; + padding-left: 8px; + padding-right: 8px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); +} + +#workspaces button.urgent { + color: @on_secondary; + border-radius: 10px; +} + +#workspaces button.persistent { + border-radius: 10px; +} + +#backlight, +#backlight-slider, +#battery, +#bluetooth, +#clock, +#cpu, +#disk, +#idle_inhibitor, +#keyboard-state, +#memory, +#mode, +#mpris, +#network, +#power-profiles-daemon, +#pulseaudio, +#pulseaudio-slider, +#taskbar, +#temperature, +#tray, +#window, +#wireplumber, +#workspaces, +#custom-backlight, +#custom-browser, +#custom-cava_mviz, +#custom-cycle_wall, +#custom-dot_update, +#custom-file_manager, +#custom-keybinds, +#custom-keyboard, +#custom-light_dark, +#custom-lock, +#custom-hint, +#custom-hypridle, +#custom-menu, +#custom-playerctl, +#custom-power_vertical, +#custom-power, +#custom-quit, +#custom-reboot, +#custom-settings, +#custom-spotify, +#custom-swaync, +#custom-tty, +#custom-updater, +#custom-weather, +#custom-weather.clearNight, +#custom-weather.cloudyFoggyDay, +#custom-weather.cloudyFoggyNight, +#custom-weather.default, +#custom-weather.rainyDay, +#custom-weather.rainyNight, +#custom-weather.severe, +#custom-weather.showyIcyDay, +#custom-weather.snowyIcyNight, +#custom-weather.sunnyDay { + padding-top: 4px; + padding-bottom: 4px; + padding-right: 6px; + padding-left: 6px; +} +/*-----Indicators----*/ +#custom-hypridle.notactive, +#idle_inhibitor.activated { + color: #39FF14; +} + +#pulseaudio.muted { + color: #cc3436; +} +#temperature.critical { + color: red; +} + +@keyframes blink { + to { + color: #000000; + } +} + +#battery.critical:not(.charging) { + color: #f53c3c; +} + +#backlight-slider slider, +#pulseaudio-slider slider { + min-width: 0px; + min-height: 0px; + opacity: 0; + background-image: none; + border: none; + box-shadow: none; +} + +#backlight-slider trough, +#pulseaudio-slider trough { + min-width: 80px; + min-height: 5px; + border-radius: 5px; +} + +#backlight-slider highlight, +#pulseaudio-slider highlight { + min-height: 10px; + border-radius: 5px; +} diff --git a/waybar/style/colors.css b/waybar/style/colors.css new file mode 120000 index 0000000..b0c5580 --- /dev/null +++ b/waybar/style/colors.css @@ -0,0 +1 @@ +/home/sinsa/.config/waybar/colors.css \ No newline at end of file diff --git a/waybar/style/full bar.css b/waybar/style/full bar.css new file mode 100644 index 0000000..952f8c0 --- /dev/null +++ b/waybar/style/full bar.css @@ -0,0 +1,222 @@ +/* ---- 💫 https://github.com/JaKooLit 💫 ---- */ +/* Black & White MonoChrome */ +/* @import '../../.config/waybar/wallust/colors-waybar.css'; */ +@import "colors.css"; + + +* { + font-family: "JetBrainsMono Nerd Font Propo"; + font-weight: bold; + min-height: 0; + /* set font-size to 100% if font scaling is set to 1.00 using nwg-look */ + font-size: 100%; + font-feature-settings: '"zero", "ss01", "ss02", "ss03", "ss04", "ss05", "cv31"'; +} + +window#waybar, +window#waybar.empty, +window#waybar.empty #window { + background-color: alpha(@background, .70); + border-radius: 0px; + margin-top: 0px; + margin-bottom: 0px; + margin-right: 0px; + margin-left: 0px; +} + +tooltip { + color: @inverse_surface; + background: rgba(0, 0, 0, 0.8); + border-radius: 20px; +} + +tooltip label{ + color: @inverse_surface; +} +/*-----module groups----*/ +.modules-right { +/* background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white;*/ + border-radius: 20px; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-center { +/* background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white;*/ + border-radius: 20px; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-left { +/* background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white;*/ + border-radius: 20px; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +/*-----modules indv----*/ +#taskbar button, +#workspaces button { + color: @outline; + box-shadow: none; + text-shadow: none; + padding: 0px; + padding-bottom: 0px; + padding-top: 1px; + border-radius: 9px; + padding-left: 4px; + padding-right: 4px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.5s cubic-bezier(.55,-0.68,.48,1.682); +} + +#taskbar button:hover, +#workspaces button:hover { + color: @on_secondary_fixed_variant; + border-radius: 20px; + padding-left: 2px; + padding-right: 2px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); +} + +#taskbar button.active, +#workspaces button.active { + color: @primary; + padding-left: 8px; + padding-right: 8px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); +} + +#workspaces button.urgent { + color: @on_secondary; + border-radius: 10px; +} + +#workspaces button.persistent { + border-radius: 10px; +} + +#backlight, +#backlight-slider, +#battery, +#bluetooth, +#clock, +#cpu, +#disk, +#idle_inhibitor, +#keyboard-state, +#memory, +#mode, +#mpris, +#network, +#power-profiles-daemon, +#pulseaudio, +#pulseaudio-slider, +#taskbar, +#temperature, +#tray, +#window, +#wireplumber, +#workspaces, +#custom-backlight, +#custom-browser, +#custom-cava_mviz, +#custom-cycle_wall, +#custom-dot_update, +#custom-file_manager, +#custom-keybinds, +#custom-keyboard, +#custom-light_dark, +#custom-lock, +#custom-hint, +#custom-hypridle, +#custom-menu, +#custom-playerctl, +#custom-power_vertical, +#custom-power, +#custom-quit, +#custom-reboot, +#custom-settings, +#custom-spotify, +#custom-swaync, +#custom-tty, +#custom-updater, +#custom-weather, +#custom-weather.clearNight, +#custom-weather.cloudyFoggyDay, +#custom-weather.cloudyFoggyNight, +#custom-weather.default, +#custom-weather.rainyDay, +#custom-weather.rainyNight, +#custom-weather.severe, +#custom-weather.showyIcyDay, +#custom-weather.snowyIcyNight, +#custom-weather.sunnyDay { + padding-top: 4px; + padding-bottom: 4px; + padding-right: 6px; + padding-left: 6px; +} +/*-----Indicators----*/ +#custom-hypridle.notactive, +#idle_inhibitor.activated { + color: #39FF14; +} + +#pulseaudio.muted { + color: #cc3436; +} +#temperature.critical { + color: red; +} + +@keyframes blink { + to { + color: #000000; + } +} + +#battery.critical:not(.charging) { + color: #f53c3c; +} + +#backlight-slider slider, +#pulseaudio-slider slider { + min-width: 0px; + min-height: 0px; + opacity: 0; + background-image: none; + border: none; + box-shadow: none; +} + +#backlight-slider trough, +#pulseaudio-slider trough { + min-width: 80px; + min-height: 5px; + border-radius: 5px; +} + +#backlight-slider highlight, +#pulseaudio-slider highlight { + min-height: 10px; + border-radius: 5px; +} diff --git a/waybar/style/islands no transparent.css b/waybar/style/islands no transparent.css new file mode 100644 index 0000000..a975fc4 --- /dev/null +++ b/waybar/style/islands no transparent.css @@ -0,0 +1,230 @@ +@import "colors.css"; + + +* { + font-family: "JetBrainsMono Nerd Font Propo"; + font-weight: bold; + min-height: 0; + /* set font-size to 100% if font scaling is set to 1.00 using nwg-look */ + font-size: 98%; + font-feature-settings: '"zero", "ss01", "ss02", "ss03", "ss04", "ss05", "cv31"'; +} + +window#waybar, +window#waybar.empty, +window#waybar.empty #window { + background-color: transparent; + padding: 0px; + border: 0px; +} + +tooltip { + color: @inverse_surface; + background: rgba(0, 0, 0, 0.8); + border-radius: 20px; +} + +tooltip label{ + color: @inverse_surface; +} +/*-----module groups----*/ +.modules-right { + /*background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px;*/ + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-center { + /*background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px;*/ + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-left { + /*background-color: rgba(0,0,0,0.5);*/ + color: @secondary; + /*border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px;*/ + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +/*-----modules indv----*/ +#taskbar button, +#workspaces button { + color: @outline; + box-shadow: none; + text-shadow: none; + padding: 0px; + padding-bottom: 0px; + padding-top: 1px; + border-radius: 9px; + padding-left: 4px; + padding-right: 4px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.5s cubic-bezier(.55,-0.68,.48,1.682); +} +#taskbar button:hover, +#workspaces button:hover { + color: @primary; + border-radius: 20px; + padding-left: 2px; + padding-right: 2px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); +} + +#taskbar button.active, +#workspaces button.active { + color: @background; + background-color: alpha(@primary_fixed, 1); + padding-left: 10px; + padding-right: 10px; + animation: gradient_f 20s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); +} + +#workspaces button.urgent { + color: @primary; + border-radius: 10px; +} + +#workspaces button.persistent { + border-radius: 10px; +} + +#custom-swaync { + background-color: alpha(@surface_container, 1); + /* border: 1px solid @surface_container; */ + border-radius: 20px; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 8px; + padding-left: 15px; + margin: 0 0 0 5px; +} + +#backlight, +#backlight-slider, +#battery, +#bluetooth, +#clock, +#cpu, +#disk, +#idle_inhibitor, +#keyboard-state, +#memory, +#mode, +#mpris, +#network, +#power-profiles-daemon, +#pulseaudio, +#pulseaudio-slider, +#taskbar, +#temperature, +#tray, +#window, +#wireplumber, +#workspaces, +#custom-backlight, +#custom-browser, +#custom-cava_mviz, +#custom-cycle_wall, +#custom-dot_update, +#custom-file_manager, +#custom-keybinds, +#custom-keyboard, +#custom-light_dark, +#custom-lock, +#custom-hint, +#custom-hypridle, +#custom-menu, +#custom-playerctl, +#custom-power_vertical, +#custom-power, +#custom-quit, +#custom-reboot, +#custom-settings, +#custom-spotify, +#custom-tty, +#custom-updater, +#custom-weather, +#custom-weather.clearNight, +#custom-weather.cloudyFoggyDay, +#custom-weather.cloudyFoggyNight, +#custom-weather.default, +#custom-weather.rainyDay, +#custom-weather.rainyNight, +#custom-weather.severe, +#custom-weather.showyIcyDay, +#custom-weather.snowyIcyNight, +#custom-weather.sunnyDay { + background-color: alpha(@surface_container, 1); + /* border: 1px solid @surface_container; */ + border-radius: 20px; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 15px; + padding-left: 15px; + margin: 0 0 0 5px; +} +/*-----Indicators----*/ +#custom-hypridle.notactive, +#idle_inhibitor.activated { + color: #39FF14; +} + +#pulseaudio.muted { + color: #cc3436; +} +#temperature.critical { + color: red; +} + +@keyframes blink { + to { + color: #000000; + } +} + +#battery.critical:not(.charging) { + color: #f53c3c; +} + +#backlight-slider slider, +#pulseaudio-slider slider { + min-width: 0px; + min-height: 0px; + opacity: 0; + background-image: none; + border: none; + box-shadow: none; +} + +#backlight-slider trough, +#pulseaudio-slider trough { + min-width: 80px; + min-height: 5px; + border-radius: 5px; +} + +#backlight-slider highlight, +#pulseaudio-slider highlight { + min-height: 10px; + border-radius: 5px; +} diff --git a/waybar/style/islands.css b/waybar/style/islands.css new file mode 100644 index 0000000..acc6d05 --- /dev/null +++ b/waybar/style/islands.css @@ -0,0 +1,237 @@ +@import "colors.css"; +@import "mocha.css"; + +* { + font-family: 'JetBrains Mono Nerd Font Propo'; + font-weight: bold ; + min-height: 0; + /* set font-size to 100% if font scaling is set to 1.00 using nwg-look */ + font-size: 100%; + font-feature-settings: '"zero", "ss01", "ss02", "ss03", "ss04", "ss05", "cv31"'; +} + +window#waybar, +window#waybar.empty, +window#waybar.empty #window { + background-color: transparent; + padding: 0px; + border: 0px; + color : @text; +} + +tooltip { + color: @inverse_surface; + background: rgba(0, 0, 0, 0.8); + border-radius: 20px; +} + +tooltip label{ + color: @inverse_surface; +} +/*-----module groups----*/ +.modules-right { + /*background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px;*/ + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-center { + /*background-color: rgba(0,0,0,0.5);*/ + color: @secondary; +/* border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px;*/ + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +.modules-left { + /*background-color: rgba(0,0,0,0.5);*/ + color: @secondary; + /*border-bottom: 0px; + border-style: solid; + border-color: white; + border-radius: 20px;*/ + padding-top: 2px; + padding-bottom: 2px; + padding-right: 4px; + padding-left: 4px; +} +/*-----modules indv----*/ +#taskbar button, +#workspaces button { + color: @outline; + box-shadow: none; + text-shadow: none; + padding: 0px; + padding-bottom: 0px; + padding-top: 1px; + border-radius: 9px; + padding-left: 4px; + padding-right: 4px; +/* animation: gradient_f 5s ease-in infinite; + transition: all 0.5s cubic-bezier(.55,-0.68,.48,1.682); */ +} +#taskbar button:hover, +#workspaces button:hover { + color: @primary; + border-radius: 20px; + padding-left: 2px; + padding-right: 2px; +/* animation: gradient_f 5s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); */ +} + +#taskbar button.active, +#workspaces button.active { + color: @background; + background-color: alpha(@primary_fixed, 0.75); + padding-left: 10px; + padding-right: 10px; +/* animation: gradient_f 5s ease-in infinite; + transition: all 0.3s cubic-bezier(.55,-0.68,.48,1.682); */ +} + +#workspaces button.urgent { + /* color: @primary; */ + border-radius: 10px; +} + +#workspaces button.persistent { + border-radius: 10px; +} + +#custom-swaync { + background-color: alpha(@surface_container, 0.75); + /* border: 1px solid @surface_container; */ + border-radius: 20px; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 8px; + padding-left: 15px; + margin: 0 0 0 5px; +} +#cava, +#cava.silent, +#backlight, +#backlight-slider, +#battery, +#bluetooth, +#clock, +#cpu, +#disk, +#idle_inhibitor, +#keyboard-state, +#memory, +#mode, +#mpris, +#network, +#power-profiles-daemon, +#pulseaudio, +#pulseaudio-slider, +#taskbar, +#temperature, +#tray, +#window, +#wireplumber, +#workspaces, +#custom-backlight, +#custom-browser, +#custom-cava_mviz, +#custom-cycle_wall, +#custom-dot_update, +#custom-file_manager, +#custom-keybinds, +#custom-keyboard, +#custom-light_dark, +#custom-lock, +#custom-hint, +#custom-hypridle, +#custom-menu, +#custom-playerctl, +#custom-power_vertical, +#custom-power, +#custom-quit, +#custom-reboot, +#custom-settings, +#custom-spotify, +#custom-tty, +#custom-updater, +#custom-weather, +#custom-weather.clearNight, +#custom-weather.cloudyFoggyDay, +#custom-weather.cloudyFoggyNight, +#custom-weather.default, +#custom-weather.rainyDay, +#custom-weather.rainyNight, +#custom-weather.severe, +#custom-weather.showyIcyDay, +#custom-weather.snowyIcyNight, +#custom-archicon, +#custom-vpn, +#custom-cava, +#custom-playerinfo, +#custom-weather.sunnyDay { + background-color: alpha(@surface_container, 0.75); + /* border: 1px solid @surface_container; */ + border-radius: 20px; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 15px; + padding-left: 15px; + margin: 0 0 0 5px; +} +/*-----Indicators----*/ +#custom-hypridle.notactive, +#idle_inhibitor.activated { + color: #39FF14; +} + +#pulseaudio.muted { + color: #cc3436; +} +#temperature.critical { + color: red; +} + +@keyframes blink { + to { + color: #000000; + } +} + +#battery.critical:not(.charging) { + color: #f53c3c; +} + +#backlight-slider slider, +#pulseaudio-slider slider { + min-width: 0px; + min-height: 0px; + opacity: 0; + background-image: none; + border: none; + box-shadow: none; +} + +#backlight-slider trough, +#pulseaudio-slider trough { + min-width: 80px; + min-height: 5px; + border-radius: 5px; +} + +#backlight-slider highlight, +#pulseaudio-slider highlight { + min-height: 10px; + border-radius: 5px; +} + diff --git a/waybar/style/mocha.css b/waybar/style/mocha.css new file mode 100644 index 0000000..0eb6a82 --- /dev/null +++ b/waybar/style/mocha.css @@ -0,0 +1,26 @@ +@define-color rosewater #f5e0dc; +@define-color flamingo #f2cdcd; +@define-color pink #f5c2e7; +@define-color mauve #cba6f7; +@define-color red #f38ba8; +@define-color maroon #eba0ac; +@define-color peach #fab387; +@define-color yellow #f9e2af; +@define-color green #a6e3a1; +@define-color teal #94e2d5; +@define-color sky #89dceb; +@define-color sapphire #74c7ec; +@define-color blue #89b4fa; +@define-color lavender #b4befe; +@define-color text #cdd6f4; +@define-color subtext1 #bac2de; +@define-color subtext0 #a6adc8; +@define-color overlay2 #9399b2; +@define-color overlay1 #7f849c; +@define-color overlay0 #6c7086; +@define-color surface2 #585b70; +@define-color surface1 #45475a; +@define-color surface0 #313244; +@define-color base #1e1e2e; +@define-color mantle #181825; +@define-color crust #11111b; diff --git a/waybar/style/style.css b/waybar/style/style.css new file mode 100644 index 0000000..f126249 --- /dev/null +++ b/waybar/style/style.css @@ -0,0 +1,202 @@ +@import "mocha.css"; + +* { + font-family: FantasqueSansMono Nerd Font; + font-size: 17px; + min-height: 0; +} + +#waybar { + background: transparent; + color: @text; + margin: 5px 5px; +} + +#workspaces { + border-radius: 1rem; + margin: 5px; + background-color: @surface0; + margin-left: 1rem; +} + +#workspaces button { + color: @lavender; + border-radius: 1rem; + padding: 0.4rem; +} + +#workspaces button.active { + color: @sky; + border-radius: 1rem; +} + +#workspaces button:hover { + color: @sapphire; + border-radius: 1rem; +} + +#custom-music, +#tray, +#backlight, +#clock, +#battery, +#pulseaudio, +#custom-lock, +#custom-power { + background-color: @surface0; + padding: 0.5rem 1rem; + margin: 5px 0; +} + +#clock { + color: @blue; + border-radius: 0px 1rem 1rem 0px; + margin-right: 1rem; +} + +#battery { + color: @green; +} + +#battery.charging { + color: @green; +} + +#battery.warning:not(.charging) { + color: @red; +} + +#backlight { + color: @yellow; +} + +#backlight, #battery { + border-radius: 0; +} + +#pulseaudio { + color: @maroon; + border-radius: 1rem 0px 0px 1rem; + margin-left: 1rem; +} + +#custom-music { + color: @mauve; + border-radius: 1rem; +} + +#custom-lock { + border-radius: 1rem 0px 0px 1rem; + color: @lavender; +} + +#custom-power { + margin-right: 1rem; + border-radius: 0px 1rem 1rem 0px; + color: @red; +} + +#tray { + margin-right: 1rem; + border-radius: 1rem; +} +#cava, +#backlight, +#backlight-slider, +#battery, +#bluetooth, +#clock, +#cpu, +#disk, +#idle_inhibitor, +#keyboard-state, +#memory, +#mode, +#mpris, +#network, +#power-profiles-daemon, +#pulseaudio, +#pulseaudio-slider, +#taskbar, +#temperature, +#tray, +#window, +#wireplumber, +#workspaces, +#custom-backlight, +#custom-browser, +#custom-cava_mviz, +#custom-cycle_wall, +#custom-dot_update, +#custom-file_manager, +#custom-keybinds, +#custom-keyboard, +#custom-light_dark, +#custom-lock, +#custom-hint, +#custom-hypridle, +#custom-menu, +#custom-playerctl, +#custom-power_vertical, +#custom-power, +#custom-quit, +#custom-reboot, +#custom-settings, +#custom-spotify, +#custom-tty, +#custom-updater, +#custom-weather, +#custom-weather.clearNight, +#custom-weather.cloudyFoggyDay, +#custom-weather.cloudyFoggyNight, +#custom-weather.default, +#custom-weather.rainyDay, +#custom-weather.rainyNight, +#custom-weather.severe, +#custom-weather.showyIcyDay, +#custom-weather.snowyIcyNight, +#custom-archicon, +#custom-hypridle.notactive, +#idle_inhibitor.activated { + color: #39FF14; +} + +#pulseaudio.muted { + color: #cc3436; +} +#temperature.critical { + color: red; +} + +@keyframes blink { + to { + color: #000000; + } +} + +#battery.critical:not(.charging) { + color: #f53c3c; +} + +#backlight-slider slider, +#pulseaudio-slider slider { + min-width: 0px; + min-height: 0px; + opacity: 0; + background-image: none; + border: none; + box-shadow: none; +} + +#backlight-slider trough, +#pulseaudio-slider trough { + min-width: 80px; + min-height: 5px; + border-radius: 5px; +} + +#backlight-slider highlight, +#pulseaudio-slider highlight { + min-height: 10px; + border-radius: 5px; +}