diff --git a/.Xresources b/.Xresources
new file mode 100644
index 0000000..bd83501
--- /dev/null
+++ b/.Xresources
@@ -0,0 +1,2 @@
+Xft.dpi: 144
+Xcursor.size: 24
diff --git a/.config/btop/btop.conf b/.config/btop/btop.conf
new file mode 100644
index 0000000..83011c1
--- /dev/null
+++ b/.config/btop/btop.conf
@@ -0,0 +1,272 @@
+#? Config file for btop v.1.4.6
+
+#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
+#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
+color_theme = "/home/zhenyan121/.config/btop/themes/matugen.theme"
+
+#* If the theme set background should be shown, set to False if you want terminal background transparency.
+theme_background = true
+
+#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
+truecolor = true
+
+#* Set to true to force tty mode regardless if a real tty has been detected or not.
+#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
+force_tty = false
+
+#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
+#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
+#* Use whitespace " " as separator between different presets.
+#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
+presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
+
+#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
+#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
+vim_keys = false
+
+#* Rounded corners on boxes, is ignored if TTY mode is ON.
+rounded_corners = true
+
+#* Use terminal synchronized output sequences to reduce flickering on supported terminals.
+terminal_sync = true
+
+#* Default symbols to use for graph creation, "braille", "block" or "tty".
+#* "braille" offers the highest resolution but might not be included in all fonts.
+#* "block" has half the resolution of braille but uses more common characters.
+#* "tty" uses only 3 different symbols but will work with most fonts and should work in a real TTY.
+#* Note that "tty" only has half the horizontal resolution of the other two, so will show a shorter historical view.
+graph_symbol = "braille"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_cpu = "default"
+
+# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty".
+graph_symbol_gpu = "default"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_mem = "default"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_net = "default"
+
+# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
+graph_symbol_proc = "default"
+
+#* Manually set which boxes to show. Available values are "cpu mem net proc" and "gpu0" through "gpu5", separate values with whitespace.
+shown_boxes = "cpu mem net proc"
+
+#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
+update_ms = 2000
+
+#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
+#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
+proc_sorting = "cpu lazy"
+
+#* Reverse sorting order, True or False.
+proc_reversed = false
+
+#* Show processes as a tree.
+proc_tree = false
+
+#* Use the cpu graph colors in the process list.
+proc_colors = true
+
+#* Use a darkening gradient in the process list.
+proc_gradient = true
+
+#* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
+proc_per_core = false
+
+#* Show process memory as bytes instead of percent.
+proc_mem_bytes = true
+
+#* Show cpu graph for each process.
+proc_cpu_graphs = true
+
+#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
+proc_info_smaps = false
+
+#* Show proc box on left side of screen instead of right.
+proc_left = false
+
+#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
+proc_filter_kernel = false
+
+#* In tree-view, always accumulate child process resources in the parent process.
+proc_aggregate = false
+
+#* Should cpu and memory usage display be preserved for dead processes when paused.
+keep_dead_proc_usage = false
+
+#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
+#* Select from a list of detected attributes from the options menu.
+cpu_graph_upper = "Auto"
+
+#* Sets the CPU stat shown in lower half of the CPU graph, "total" is always available.
+#* Select from a list of detected attributes from the options menu.
+cpu_graph_lower = "Auto"
+
+#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
+show_gpu_info = "Auto"
+
+#* Toggles if the lower CPU graph should be inverted.
+cpu_invert_lower = true
+
+#* Set to True to completely disable the lower CPU graph.
+cpu_single_graph = false
+
+#* Show cpu box at bottom of screen instead of top.
+cpu_bottom = false
+
+#* Shows the system uptime in the CPU box.
+show_uptime = true
+
+#* Shows the CPU package current power consumption in watts. Requires running `make setcap` or `make setuid` or running with sudo.
+show_cpu_watts = true
+
+#* Show cpu temperature.
+check_temp = true
+
+#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
+cpu_sensor = "Auto"
+
+#* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
+show_coretemp = true
+
+#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
+#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
+#* Format "x:y" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries.
+#* Example: "4:0 5:1 6:3"
+cpu_core_map = ""
+
+#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
+temp_scale = "celsius"
+
+#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
+base_10_sizes = false
+
+#* Show CPU frequency.
+show_cpu_freq = true
+
+#* How to calculate CPU frequency, available values: "first", "range", "lowest", "highest" and "average".
+freq_mode = "first"
+
+#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
+#* Special formatting: /host = hostname | /user = username | /uptime = system uptime
+clock_format = "%X"
+
+#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
+background_update = true
+
+#* Custom cpu model name, empty string to disable.
+custom_cpu_name = ""
+
+#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
+#* Only disks matching the filter will be shown. Prepend exclude= to only show disks not matching the filter. Examples: disk_filter="/boot /home/user", disks_filter="exclude=/boot /home/user"
+disks_filter = ""
+
+#* Show graphs instead of meters for memory values.
+mem_graphs = true
+
+#* Show mem box below net box instead of above.
+mem_below_net = false
+
+#* Count ZFS ARC in cached and available memory.
+zfs_arc_cached = true
+
+#* If swap memory should be shown in memory box.
+show_swap = true
+
+#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
+swap_disk = true
+
+#* If mem box should be split to also show disks info.
+show_disks = true
+
+#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
+only_physical = true
+
+#* Read disks list from /etc/fstab. This also disables only_physical.
+use_fstab = true
+
+#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
+zfs_hide_datasets = false
+
+#* Set to true to show available disk space for privileged users.
+disk_free_priv = false
+
+#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
+show_io_stat = true
+
+#* Toggles io mode for disks, showing big graphs for disk read/write speeds.
+io_mode = false
+
+#* Set to True to show combined read/write io graphs in io mode.
+io_graph_combined = false
+
+#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
+#* Example: "/mnt/media:100 /:20 /boot:1".
+io_graph_speeds = ""
+
+#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
+net_download = 100
+
+net_upload = 100
+
+#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
+net_auto = true
+
+#* Sync the auto scaling for download and upload to whichever currently has the highest scale.
+net_sync = true
+
+#* Starts with the Network Interface specified here.
+net_iface = ""
+
+#* "True" shows bitrates in base 10 (Kbps, Mbps). "False" shows bitrates in binary sizes (Kibps, Mibps, etc.). "Auto" uses base_10_sizes.
+base_10_bitrate = "Auto"
+
+#* Show battery stats in top right if battery is present.
+show_battery = true
+
+#* Which battery to use if multiple are present. "Auto" for auto detection.
+selected_battery = "Auto"
+
+#* Show power stats of battery next to charge indicator.
+show_battery_watts = true
+
+#* Set loglevel for "~/.local/state/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
+#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
+log_level = "WARNING"
+
+#* Automatically save current settings to config file on exit.
+save_config_on_exit = true
+
+#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
+nvml_measure_pcie_speeds = true
+
+#* Measure PCIe throughput on AMD cards, may impact performance on certain cards.
+rsmi_measure_pcie_speeds = true
+
+#* Horizontally mirror the GPU graph.
+gpu_mirror_graph = true
+
+#* Set which GPU vendors to show. Available values are "nvidia amd intel"
+shown_gpus = "nvidia amd intel"
+
+#* Custom gpu0 model name, empty string to disable.
+custom_gpu_name0 = ""
+
+#* Custom gpu1 model name, empty string to disable.
+custom_gpu_name1 = ""
+
+#* Custom gpu2 model name, empty string to disable.
+custom_gpu_name2 = ""
+
+#* Custom gpu3 model name, empty string to disable.
+custom_gpu_name3 = ""
+
+#* Custom gpu4 model name, empty string to disable.
+custom_gpu_name4 = ""
+
+#* Custom gpu5 model name, empty string to disable.
+custom_gpu_name5 = ""
diff --git a/.config/btop/themes/matugen.theme b/.config/btop/themes/matugen.theme
new file mode 100644
index 0000000..36361df
--- /dev/null
+++ b/.config/btop/themes/matugen.theme
@@ -0,0 +1,89 @@
+# Matugen template for btop
+
+
+# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
+# example for white: "#ffffff", "#ff" or "255 255 255".
+
+# All graphs and meters can be gradients
+# For single color graphs leave "mid" and "end" variable empty.
+# Use "start" and "end" variables for two color gradient
+# Use "start", "mid" and "end" for three color gradient
+
+# Main background, empty for terminal default, need to be empty if you want transparent background
+theme[main_bg]=""
+
+# Main text color
+theme[main_fg]="#e9e2d4"
+
+# Title color for boxes
+theme[title]="#dcc66e"
+
+# Highlight color for keyboard shortcuts
+theme[hi_fg]="#d1c6a1"
+
+# Background color of selected item in processes box
+theme[selected_bg]="#dcc66e"
+
+# Foreground color of selected item in processes box
+theme[selected_fg]="#3a3000"
+
+# Color of inactive/disabled text
+theme[inactive_fg]="#cdc6b4"
+
+# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
+theme[proc_misc]="#aad0b3"
+
+# Cpu box outline color
+theme[cpu_box]="#969080"
+
+# Memory/disks box outline color
+theme[mem_box]="#969080"
+
+# Net up/down box outline color
+theme[net_box]="#969080"
+
+# Processes box outline color
+theme[proc_box]="#969080"
+
+# Box divider line and small boxes line color
+theme[div_line]="#4b4739"
+
+# Temperature graph colors
+theme[temp_start]="#d1c6a1"
+theme[temp_mid]="#dcc66e"
+theme[temp_end]="#ffb4ab"
+
+# CPU graph colors
+theme[cpu_start]="#d1c6a1"
+theme[cpu_mid]="#dcc66e"
+theme[cpu_end]="#ffb4ab"
+
+# Mem/Disk free meter
+theme[free_start]="#d1c6a1"
+theme[free_mid]=""
+theme[free_end]="#4e472a"
+
+# Mem/Disk cached meter
+theme[cached_start]="#aad0b3"
+theme[cached_mid]=""
+theme[cached_end]="#2c4e38"
+
+# Mem/Disk available meter
+theme[available_start]="#dcc66e"
+theme[available_mid]=""
+theme[available_end]="#534600"
+
+# Mem/Disk used meter
+theme[used_start]="#ffb4ab"
+theme[used_mid]=""
+theme[used_end]="#93000a"
+
+# Download graph colors
+theme[download_start]="#d1c6a1"
+theme[download_mid]="#dcc66e"
+theme[download_end]="#aad0b3"
+
+# Upload graph colors
+theme[upload_start]="#d1c6a1"
+theme[upload_mid]="#dcc66e"
+theme[upload_end]="#aad0b3"
diff --git a/.config/cava/config b/.config/cava/config
new file mode 100644
index 0000000..ff28de1
--- /dev/null
+++ b/.config/cava/config
@@ -0,0 +1,321 @@
+## 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 calculate max number of bars.
+; bar_width = 1
+; bar_spacing = 0
+
+# ceter bars in terminal, if there is space.
+; center_align = 1
+
+# max height of bars in terminal, in percent of terminal height.
+; max_height = 100
+
+
+# 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. To capture the monitor source of a sink node, append '.monitor' to the sink's object name.
+#
+# 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 pipewire, sample_rate will default to 48000, for all other input methods, sample_rate will default to 44100.
+#
+# 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.
+#
+#
+# The 'pipewire' input method has three options to control linking and mixing:
+# active: Force the node to always process. Useful for monitoring sources when no other application is active.
+# remix: Allow pipewire to remix audio channels to match cava's channel count. Useful for surround sound.
+# virtual: Set the node to virtual, to avoid recording notifications from the DE.
+#
+; sample_rate = 44100
+; sample_bits = 16
+; channels = 2
+; autoconnect = 2
+; active = 0
+; remix = 1
+; virtual = 1
+
+
+[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 1024 bars stereo (512 bars mono), 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', 'right' or
+# 'horizontal'. Default is 'bottom'. 'left and 'right' are only supported on sdl
+# and ncruses output. 'horizontal' (bars go up and down from center) is only supported
+# on noncurses output.
+# Note: many fonts have weird or missing glyphs for characters used in orientations
+# other than 'bottom', which can make output 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.
+# On Linux, a fifo will be created if target does not exist.
+# On Windows, a named pipe 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 = 1024
+; sdl_height = 512
+; 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 synchronized sync. 1 = on, 0 = off
+# removes flickering in alacritty terminal emulator.
+# defaults to off since the behaviour in other terminal emulators is unknown
+; synchronized_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'
+
+
+# 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_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'
+
+
+# Horizontal is only supported on noncurses output.
+# Only one color will be calculated per bar.
+; horizontal_gradient = 0
+; 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'
+
+
+# If both vertical and horizontal gradient is enabled, vertical will be blended in this direction.
+# Can be 'up', 'down', 'left' or 'right'. 'up' means the vertical gradient will be blended in from
+# bottom to top. I.e. the bottom will be only the horizontal
+# and top will be only the color of the vertical gradient.
+; blend_direction = 'up'
+
+# use theme file instead of defining colors in this file
+# themes are located in $HOME/.config/cava/themes
+; theme = 'none'
+
+
+[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/.config/cava/shaders/bar_spectrum.frag b/.config/cava/shaders/bar_spectrum.frag
new file mode 100644
index 0000000..e594618
--- /dev/null
+++ b/.config/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 bewteen 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);
+ }
+}
\ No newline at end of file
diff --git a/.config/cava/shaders/eye_of_phi.frag b/.config/cava/shaders/eye_of_phi.frag
new file mode 100644
index 0000000..e499ee7
--- /dev/null
+++ b/.config/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 bewteen 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);
+}
\ No newline at end of file
diff --git a/.config/cava/shaders/northern_lights.frag b/.config/cava/shaders/northern_lights.frag
new file mode 100644
index 0000000..ecd859a
--- /dev/null
+++ b/.config/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/.config/cava/shaders/pass_through.vert b/.config/cava/shaders/pass_through.vert
new file mode 100644
index 0000000..a4f20e5
--- /dev/null
+++ b/.config/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/.config/cava/shaders/spectrogram.frag b/.config/cava/shaders/spectrogram.frag
new file mode 100644
index 0000000..adce70a
--- /dev/null
+++ b/.config/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 bewteen 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);
+ }
+}
\ No newline at end of file
diff --git a/.config/cava/shaders/winamp_line_style_spectrum.frag b/.config/cava/shaders/winamp_line_style_spectrum.frag
new file mode 100644
index 0000000..375ff27
--- /dev/null
+++ b/.config/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 bewteen 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);
+ }
+}
\ No newline at end of file
diff --git a/.config/cava/themes/solarized_dark b/.config/cava/themes/solarized_dark
new file mode 100644
index 0000000..200057c
--- /dev/null
+++ b/.config/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/.config/cava/themes/tricolor b/.config/cava/themes/tricolor
new file mode 100644
index 0000000..b908137
--- /dev/null
+++ b/.config/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/.config/cava/themes/your-theme b/.config/cava/themes/your-theme
new file mode 100644
index 0000000..feef0fb
--- /dev/null
+++ b/.config/cava/themes/your-theme
@@ -0,0 +1,19 @@
+[color]
+background = 'default'
+foreground = '#dcc66e'
+
+; gradient = 0
+gradient = 1
+gradient_color_1 = '#534600'
+gradient_color_2 = '#dcc66e'
+gradient_color_3 = '#f9e287'
+
+horizontal_gradient = 0
+; horizontal_gradient = 1
+horizontal_gradient_color_1 = '#534600'
+horizontal_gradient_color_2 = '#dcc66e'
+horizontal_gradient_color_3 = '#f9e287'
+horizontal_gradient_color_4 = '#dcc66e'
+horizontal_gradient_color_5 = '#534600'
+
+
diff --git a/.config/fcitx5/conf/cached_layouts b/.config/fcitx5/conf/cached_layouts
new file mode 100644
index 0000000..15ac22b
--- /dev/null
+++ b/.config/fcitx5/conf/cached_layouts
@@ -0,0 +1,3740 @@
+[keyboard-bqn]
+Description="键盘 - BQN"
+Language=en
+Label=bqn
+
+[keyboard-apl]
+Description="键盘 - APL"
+Language=en
+Label=apl
+
+[keyboard-apl-dyalog]
+Description="键盘 - APL - APL 符号(Dyalog APL)"
+Language=en
+Label="dlg (dyalog)"
+
+[keyboard-apl-sax]
+Description="键盘 - APL - APL 符号(SAX,Sharp APL for Unix)"
+Language=en
+Label=sax
+
+[keyboard-apl-unified]
+Description="键盘 - APL - APL 符号(统一)"
+Language=en
+Label="ufd (unified)"
+
+[keyboard-apl-apl2]
+Description="键盘 - APL - APL 符号(IBM APL2)"
+Language=en
+Label=apl2
+
+[keyboard-apl-aplplusII]
+Description="键盘 - APL - APL 符号(Manugistics APL*PLUS II)"
+Language=en
+Label="aplII (aplplusII)"
+
+[keyboard-apl-aplx]
+Description="键盘 - APL - APL 符号(APLX 统一)"
+Language=en
+Label=aplx
+
+[keyboard-ua]
+Description="键盘 - 乌克兰语"
+Language=uk
+Label=uk
+
+[keyboard-ua-phonetic]
+Description="键盘 - 乌克兰语 - 乌克兰语(语音助记)"
+Language=uk
+Label="ua (phonetic)"
+
+[keyboard-ua-typewriter]
+Description="键盘 - 乌克兰语 - 乌克兰语(打字机)"
+Language=uk
+Label="ua (typewriter)"
+
+[keyboard-ua-winkeys]
+Description="键盘 - 乌克兰语 - 乌克兰语(Windows)"
+Language=uk
+Label="ua (winkeys)"
+
+[keyboard-ua-winkeysenhanced]
+Description="键盘 - 乌克兰语 - 乌克兰语(Windows 增强)"
+Language=uk
+Label="ua (winkeysenhanced)"
+
+[keyboard-ua-macOS]
+Description="键盘 - 乌克兰语 - 乌克兰语(macOS)"
+Language=uk
+Label="ua (macOS)"
+
+[keyboard-ua-legacy]
+Description="键盘 - 乌克兰语 - 乌克兰语(传统)"
+Language=uk
+Label="ua (legacy)"
+
+[keyboard-ua-homophonic]
+Description="键盘 - 乌克兰语 - 乌克兰语(同音)"
+Language=uk
+Label="ua (homophonic)"
+
+[keyboard-ua-crh]
+Description="键盘 - 乌克兰语 - 克里米亚鞑靼语(土耳其 Q)"
+Language=crh
+Label=crh
+
+[keyboard-ua-crh_f]
+Description="键盘 - 乌克兰语 - 克里米亚鞑靼语(土耳其 F)"
+Language=crh
+Label="crh (crh_f)"
+
+[keyboard-ua-crh_alt]
+Description="键盘 - 乌克兰语 - 克里米亚鞑靼语(土耳其 Alt-Q)"
+Language=crh
+Label="crh (crh_alt)"
+
+[keyboard-ua-sun_type6]
+Description="键盘 - 乌克兰语 - 乌克兰语(Sun Type 6/7)"
+Language=uk
+Label="ua (sun_type6)"
+
+[keyboard-th]
+Description="键盘 - 泰语"
+Language=th
+Label=th
+
+[keyboard-th-tis]
+Description="键盘 - 泰语 - 泰语(TIS-820.2538)"
+Language=th
+Label="th (tis)"
+
+[keyboard-th-pat]
+Description="键盘 - 泰语 - 泰语(Pattachote)"
+Language=th
+Label="th (pat)"
+
+[keyboard-th-mnc]
+Description="键盘 - 泰语 - 泰语(Manoonchai)"
+Language=th
+Label="th (mnc)"
+
+[keyboard-tz]
+Description="键盘 - 斯瓦希里语(坦桑尼亚)"
+Language=sw
+Label=sw
+
+[keyboard-latam]
+Description="键盘 - 西班牙语(拉丁美洲)"
+Language=es
+Label=es
+
+[keyboard-latam-nodeadkeys]
+Description="键盘 - 西班牙语(拉丁美洲) - 西班牙语(拉丁美洲,无死键)"
+Language=es
+Label="latam (nodeadkeys)"
+
+[keyboard-latam-deadtilde]
+Description="键盘 - 西班牙语(拉丁美洲) - 西班牙语(拉丁美洲,波浪号为死键)"
+Language=es
+Label="latam (deadtilde)"
+
+[keyboard-latam-dvorak]
+Description="键盘 - 西班牙语(拉丁美洲) - 西班牙语(拉丁美洲,Dvorak)"
+Language=es
+Label="latam (dvorak)"
+
+[keyboard-latam-colemak]
+Description="键盘 - 西班牙语(拉丁美洲) - 西班牙语(拉丁美洲,Colemak)"
+Language=es
+Label="latam (colemak)"
+
+[keyboard-sk]
+Description="键盘 - 斯洛伐克语"
+Language=sk
+Label=sk
+
+[keyboard-sk-bksl]
+Description="键盘 - 斯洛伐克语 - 斯洛伐克语(额外的反斜杠)"
+Language=sk
+Label="sk (bksl)"
+
+[keyboard-sk-qwerty]
+Description="键盘 - 斯洛伐克语 - 斯洛伐克语(QWERTY)"
+Language=sk
+Label="sk (qwerty)"
+
+[keyboard-sk-qwerty_bksl]
+Description="键盘 - 斯洛伐克语 - 斯洛伐克语(QWERTY,额外的反斜杠)"
+Language=sk
+Label="sk (qwerty_bksl)"
+
+[keyboard-sk-acc]
+Description="键盘 - 斯洛伐克语 - 斯洛伐克语(ACC 布局,只有重音字母)"
+Language=sk
+Label="sk (acc)"
+
+[keyboard-sk-sun_type6]
+Description="键盘 - 斯洛伐克语 - 斯洛伐克语(Sun Type 6/7)"
+Language=sk
+Label="sk (sun_type6)"
+
+[keyboard-ru]
+Description="键盘 - 俄语"
+Language=ru
+Label=ru
+
+[keyboard-ru-phonetic]
+Description="键盘 - 俄语 - 俄语(语音助记)"
+Language=ru
+Label="ru (phonetic)"
+
+[keyboard-ru-phonetic_winkeys]
+Description="键盘 - 俄语 - 俄语(语音助记,Windows)"
+Language=ru
+Label="ru (phonetic_winkeys)"
+
+[keyboard-ru-phonetic_YAZHERTY]
+Description="键盘 - 俄语 - 俄语(语音助记,YAZHERTY)"
+Language=ru
+Label="ru (phonetic_YAZHERTY)"
+
+[keyboard-ru-phonetic_azerty]
+Description="键盘 - 俄语 - 俄语(语音助记,AZERTY)"
+Language=ru
+Label="ru (phonetic_azerty)"
+
+[keyboard-ru-phonetic_dvorak]
+Description="键盘 - 俄语 - 俄语(语音助记,Dvorak)"
+Language=ru
+Label="ru (phonetic_dvorak)"
+
+[keyboard-ru-typewriter]
+Description="键盘 - 俄语 - 俄语(打字机)"
+Language=ru
+Label="ru (typewriter)"
+
+[keyboard-ru-ruchey_ru]
+Description="键盘 - 俄语 - 俄语(工程,RU)"
+Language=ru
+Label="ru (ruchey_ru)"
+
+[keyboard-ru-ruchey_en]
+Description="键盘 - 俄语 - 俄语(工程,EN)"
+Language=ru
+Label="en (ruchey_en)"
+
+[keyboard-ru-legacy]
+Description="键盘 - 俄语 - 俄语(传统)"
+Language=ru
+Label="ru (legacy)"
+
+[keyboard-ru-typewriter-legacy]
+Description="键盘 - 俄语 - 俄语(打字机,传统)"
+Language=ru
+Label="ru (typewriter-legacy)"
+
+[keyboard-ru-dos]
+Description="键盘 - 俄语 - 俄语(DOS)"
+Language=ru
+Label="ru (dos)"
+
+[keyboard-ru-mac]
+Description="键盘 - 俄语 - 俄语(Macintosh)"
+Language=ru
+Label="ru (mac)"
+
+[keyboard-ru-ab]
+Description="键盘 - 俄语 - 阿布哈兹语(俄罗斯)"
+Language=ab
+Label="ru (ab)"
+
+[keyboard-ru-bak]
+Description="键盘 - 俄语 - 巴什基尔语"
+Language=ba
+Label="ru (bak)"
+
+[keyboard-ru-cv]
+Description="键盘 - 俄语 - 楚瓦什语"
+Language=cv
+Label="ru (cv)"
+
+[keyboard-ru-cv_latin]
+Description="键盘 - 俄语 - 楚瓦什语(拉丁)"
+Language=cv
+Label="ru (cv_latin)"
+
+[keyboard-ru-xal]
+Description="键盘 - 俄语 - 卡尔梅克卫拉特语"
+Language=xal
+Label="ru (xal)"
+
+[keyboard-ru-kom]
+Description="键盘 - 俄语 - 科米语"
+Language=kv
+Label="ru (kom)"
+
+[keyboard-ru-chm]
+Description="键盘 - 俄语 - Mari"
+Language=chm
+Label="ru (chm)"
+
+[keyboard-ru-os_legacy]
+Description="键盘 - 俄语 - 奥塞梯语(传统)"
+Language=os
+Label="ru (os_legacy)"
+
+[keyboard-ru-os_winkeys]
+Description="键盘 - 俄语 - 奥塞梯语(Windows)"
+Language=os
+Label="ru (os_winkeys)"
+
+[keyboard-ru-srp]
+Description="键盘 - 俄语 - 塞尔维亚语(俄罗斯)"
+Language=ru
+Label="ru (srp)"
+
+[keyboard-ru-tt]
+Description="键盘 - 俄语 - 鞑靼语"
+Language=tt
+Label="ru (tt)"
+
+[keyboard-ru-udm]
+Description="键盘 - 俄语 - 乌德穆尔特语"
+Language=udm
+Label="ru (udm)"
+
+[keyboard-ru-sah]
+Description="键盘 - 俄语 - 雅库特语"
+Language=sah
+Label="ru (sah)"
+
+[keyboard-ru-chu]
+Description="键盘 - 俄语 - 教会斯拉夫语"
+Language=cu
+Label="ru (chu)"
+
+[keyboard-ru-ruu]
+Description="键盘 - 俄语 - 俄语(带乌克兰语和白俄罗斯语字母)"
+Language=ru
+Label="ru (ruu)"
+
+[keyboard-ru-rulemak]
+Description="键盘 - 俄语 - 俄语(Rulemak,语音助记 Colemak)"
+Language=ru
+Label="ru (rulemak)"
+
+[keyboard-ru-phonetic_mac]
+Description="键盘 - 俄语 - 俄语(语音助记,Macintosh)"
+Language=ru
+Label="ru (phonetic_mac)"
+
+[keyboard-ru-sun_type6]
+Description="键盘 - 俄语 - 俄语(Sun Type 6/7)"
+Language=ru
+Label="ru (sun_type6)"
+
+[keyboard-ru-unipunct]
+Description="键盘 - 俄语 - 俄语(带美式标点)"
+Language=ru
+Label="ru (unipunct)"
+
+[keyboard-ru-gost-6431-75-48]
+Description="键盘 - 俄语 - 俄语(GOST 6431-75)"
+Language=ru
+Label="ru (gost-6431-75-48)"
+
+[keyboard-ru-gost-14289-88]
+Description="键盘 - 俄语 - 俄语(GOST 14289-88)"
+Language=ru
+Label="ru (gost-14289-88)"
+
+[keyboard-ru-prxn]
+Description="键盘 - 俄语 - 俄语(Polyglot and Reactionary)"
+Language=ru
+Label="ru (prxn)"
+
+[keyboard-ru-winkeys-p]
+Description="键盘 - 俄语 - 俄语(适合程序员的)"
+Language=ru
+Label=winkeys-p
+
+[keyboard-ru-typo]
+Description="键盘 - 俄语 - 俄语(带印刷符号)"
+Language=ru
+Label="ru (typo)"
+
+[keyboard-ru-rtu]
+Description="键盘 - 俄语 - 俄语(带鞑靼字母)"
+Language=ru
+Label="ru (rtu)"
+
+[keyboard-ru-diktor]
+Description="键盘 - 俄语 - 俄语(Diktor)"
+Language=ru
+Label=diktor
+
+[keyboard-ru-ruintl_ru]
+Description="键盘 - 俄语 - 俄语(国际,RU)"
+Language=ru
+Label="ru (ruintl_ru)"
+
+[keyboard-ru-ruintl_en]
+Description="键盘 - 俄语 - 俄语(国际,EN)"
+Language=en
+Label="en (ruintl_en)"
+
+[keyboard-br]
+Description="键盘 - 葡萄牙语(巴西)"
+Language=pt
+Label=pt
+
+[keyboard-br-nodeadkeys]
+Description="键盘 - 葡萄牙语(巴西) - 葡萄牙语(巴西,无死键)"
+Language=pt
+Label="br (nodeadkeys)"
+
+[keyboard-br-dvorak]
+Description="键盘 - 葡萄牙语(巴西) - 葡萄牙语(巴西,Dvorak)"
+Language=pt
+Label="br (dvorak)"
+
+[keyboard-br-nativo]
+Description="键盘 - 葡萄牙语(巴西) - 葡萄牙语(巴西,Nativo)"
+Language=pt
+Label="br (nativo)"
+
+[keyboard-br-nativo-us]
+Description="键盘 - 葡萄牙语(巴西) - 葡萄牙语(巴西,用于美式键盘的 Nativo)"
+Language=pt
+Label="br (nativo-us)"
+
+[keyboard-br-thinkpad]
+Description="键盘 - 葡萄牙语(巴西) - 葡萄牙语(巴西,IBM/联想 ThinkPad)"
+Language=pt
+Label="br (thinkpad)"
+
+[keyboard-br-nativo-epo]
+Description="键盘 - 葡萄牙语(巴西) - 世界语(巴西,Nativo)"
+Language=eo
+Label="br (nativo-epo)"
+
+[keyboard-br-rus]
+Description="键盘 - 葡萄牙语(巴西) - 俄语(巴西,语音助记)"
+Language=ru
+Label="ru (rus)"
+
+[keyboard-br-sun_type6]
+Description="键盘 - 葡萄牙语(巴西) - 葡萄牙语(巴西,Sun Type 6/7)"
+Language=pt
+Label="br (sun_type6)"
+
+[keyboard-ro]
+Description="键盘 - 罗马尼亚语"
+Language=ro
+Label=ro
+
+[keyboard-ro-std]
+Description="键盘 - 罗马尼亚语 - 罗马尼亚语(标准)"
+Language=ro
+Label="ro (std)"
+
+[keyboard-ro-winkeys]
+Description="键盘 - 罗马尼亚语 - 罗马尼亚语(Windows)"
+Language=ro
+Label="ro (winkeys)"
+
+[keyboard-ro-crh_dobruja]
+Description="键盘 - 罗马尼亚语 - 克里米亚鞑靼语(Dobruja Q)"
+Language=crh
+Label="crh (crh_dobruja)"
+
+[keyboard-ro-ergonomic]
+Description="键盘 - 罗马尼亚语 - 罗马尼亚语(人体工学盲打)"
+Language=ro
+Label="ro (ergonomic)"
+
+[keyboard-ro-sun_type6]
+Description="键盘 - 罗马尼亚语 - 罗马尼亚语(Sun Type 6/7)"
+Language=ro
+Label="ro (sun_type6)"
+
+[keyboard-pl]
+Description="键盘 - 波兰语"
+Language=pl
+Label=pl
+
+[keyboard-pl-legacy]
+Description="键盘 - 波兰语 - 瑞士语(传统)"
+Language=pl
+Label="pl (legacy)"
+
+[keyboard-pl-qwertz]
+Description="键盘 - 波兰语 - 波兰语(QWERTZ)"
+Language=pl
+Label="pl (qwertz)"
+
+[keyboard-pl-dvorak]
+Description="键盘 - 波兰语 - 波兰语(Dvorak)"
+Language=pl
+Label="pl (dvorak)"
+
+[keyboard-pl-dvorak_quotes]
+Description="键盘 - 波兰语 - 波兰语(Dvorak,波兰语引号在引号键上)"
+Language=pl
+Label="pl (dvorak_quotes)"
+
+[keyboard-pl-dvorak_altquotes]
+Description="键盘 - 波兰语 - 波兰语(Dvorak,波兰语引号在 1 键上)"
+Language=pl
+Label="pl (dvorak_altquotes)"
+
+[keyboard-pl-dvp]
+Description="键盘 - 波兰语 - 波兰语(适合程序员的 Dvorak)"
+Language=pl
+Label="pl (dvp)"
+
+[keyboard-pl-csb]
+Description="键盘 - 波兰语 - 卡舒比语"
+Language=csb
+Label="pl (csb)"
+
+[keyboard-pl-szl]
+Description="键盘 - 波兰语 - 西里西亚语"
+Language=szl
+Label="pl (szl)"
+
+[keyboard-pl-ru_phonetic_dvorak]
+Description="键盘 - 波兰语 - 俄语(波兰,语音助记 Dvorak)"
+Language=ru
+Label="ru (ru_phonetic_dvorak)"
+
+[keyboard-pl-intl]
+Description="键盘 - 波兰语 - 波兰语(国际,带死键)"
+Language=pl
+Label="pl (intl)"
+
+[keyboard-pl-colemak]
+Description="键盘 - 波兰语 - 波兰语(Colemak)"
+Language=pl
+Label="pl (colemak)"
+
+[keyboard-pl-colemak_dh_ansi]
+Description="键盘 - 波兰语 - 波兰语(Colemak-DH)"
+Language=pl
+Label="pl (colemak_dh_ansi)"
+
+[keyboard-pl-colemak_dh]
+Description="键盘 - 波兰语 - 波兰语(Colemak-DH ISO)"
+Language=pl
+Label="pl (colemak_dh)"
+
+[keyboard-pl-sun_type6]
+Description="键盘 - 波兰语 - 波兰语(Sun Type 6/7)"
+Language=pl
+Label="pl (sun_type6)"
+
+[keyboard-pl-glagolica]
+Description="键盘 - 波兰语 - 波兰语(Glagolica)"
+Language=pl
+Label="pl (glagolica)"
+
+[keyboard-pl-lefty]
+Description="键盘 - 波兰语 - 波兰语(Lefty)"
+Language=pl
+Label="pl (lefty)"
+
+[keyboard-trans]
+Description="键盘 - 国际音标"
+Language=
+Label=ipa
+
+[keyboard-trans-qwerty]
+Description="键盘 - 国际音标 - 国际音标(QWERTY)"
+Language=
+Label="trans (qwerty)"
+
+[keyboard-ir]
+Description="键盘 - 波斯语"
+Language=fa
+Label=fa
+
+[keyboard-ir-pes_keypad]
+Description="键盘 - 波斯语 - 波斯语(带波斯语小键盘)"
+Language=fa
+Label="ir (pes_keypad)"
+
+[keyboard-ir-winkeys]
+Description="键盘 - 波斯语 - 波斯语(Windows)"
+Language=fa
+Label="ir (winkeys)"
+
+[keyboard-ir-azb]
+Description="键盘 - 波斯语 - 阿塞拜疆语(伊朗)"
+Language=azb
+Label=azb
+
+[keyboard-ir-ku]
+Description="键盘 - 波斯语 - 库尔德语(伊朗,拉丁 Q)"
+Language=ku
+Label=ku
+
+[keyboard-ir-ku_alt]
+Description="键盘 - 波斯语 - 库尔德语(伊朗,拉丁 Alt-Q)"
+Language=ku
+Label="ku (ku_alt)"
+
+[keyboard-ir-ku_f]
+Description="键盘 - 波斯语 - 库尔德语(伊朗,F)"
+Language=ku
+Label="ku (ku_f)"
+
+[keyboard-ir-ku_ara]
+Description="键盘 - 波斯语 - 库尔德语(伊朗,阿拉伯-拉丁)"
+Language=ku
+Label="ku (ku_ara)"
+
+[keyboard-custom]
+Description="键盘 - 用户自定义布局"
+Language=und
+Label=custom
+
+[keyboard-no]
+Description="键盘 - 挪威语"
+Language=no
+Label=no
+
+[keyboard-no-nodeadkeys]
+Description="键盘 - 挪威语 - 挪威语(无死键)"
+Language=no
+Label="no (nodeadkeys)"
+
+[keyboard-no-winkeys]
+Description="键盘 - 挪威语 - 挪威语(Windows)"
+Language=no
+Label="no (winkeys)"
+
+[keyboard-no-mac]
+Description="键盘 - 挪威语 - 挪威语(Macintosh)"
+Language=no
+Label="no (mac)"
+
+[keyboard-no-mac_nodeadkeys]
+Description="键盘 - 挪威语 - 挪威语(Macintosh,无死键)"
+Language=no
+Label="no (mac_nodeadkeys)"
+
+[keyboard-no-colemak]
+Description="键盘 - 挪威语 - 挪威语(Colemak)"
+Language=no
+Label="no (colemak)"
+
+[keyboard-no-colemak_dh]
+Description="键盘 - 挪威语 - 挪威语(Colemak-DH)"
+Language=no
+Label="no (colemak_dh)"
+
+[keyboard-no-colemak_dh_wide]
+Description="键盘 - 挪威语 - 挪威语(Colemak-DH 宽版)"
+Language=no
+Label="no (colemak_dh_wide)"
+
+[keyboard-no-dvorak]
+Description="键盘 - 挪威语 - 挪威语(Dvorak)"
+Language=no
+Label="no (dvorak)"
+
+[keyboard-no-smi]
+Description="键盘 - 挪威语 - 北萨米语(挪威)"
+Language=se
+Label="no (smi)"
+
+[keyboard-no-smi_nodeadkeys]
+Description="键盘 - 挪威语 - 北萨米语(挪威,无死键)"
+Language=se
+Label="no (smi_nodeadkeys)"
+
+[keyboard-no-sun_type6]
+Description="键盘 - 挪威语 - 挪威语(Sun Type 6/7)"
+Language=no
+Label="no (sun_type6)"
+
+[keyboard-gn]
+Description="键盘 - 西非书面字母(AZERTY)"
+Language=nqo
+Label=nqo
+
+[keyboard-tm]
+Description="键盘 - 土库曼语"
+Language=tk
+Label=tk
+
+[keyboard-tm-alt]
+Description="键盘 - 土库曼语 - 土库曼语(Alt-Q)"
+Language=tk
+Label="tm (alt)"
+
+[keyboard-np]
+Description="键盘 - 尼泊尔语"
+Language=ne
+Label=ne
+
+[keyboard-ancient]
+Description="键盘 - 古代语言"
+Language=got
+Label=xx
+
+[keyboard-ancient-got]
+Description="键盘 - 古代语言 - 哥特语"
+Language=got
+Label="ancient (got)"
+
+[keyboard-ancient-uga]
+Description="键盘 - 古代语言 - 乌加里特语"
+Language=uga
+Label="ancient (uga)"
+
+[keyboard-ancient-ave]
+Description="键盘 - 古代语言 - 阿维斯陀语"
+Language=ae
+Label="ancient (ave)"
+
+[keyboard-ancient-got-alt]
+Description="键盘 - 古代语言 - 哥特语(替代)"
+Language=got
+Label="ancient (got-alt)"
+
+[keyboard-mt]
+Description="键盘 - 马耳他语"
+Language=mt
+Label=mt
+
+[keyboard-mt-us]
+Description="键盘 - 马耳他语 - 马耳他语(美国)"
+Language=mt
+Label="mt (us)"
+
+[keyboard-mt-alt-us]
+Description="键盘 - 马耳他语 - 马耳他语(美国,带 AltGr 覆盖)"
+Language=mt
+Label="mt (alt-us)"
+
+[keyboard-mt-alt-gb]
+Description="键盘 - 马耳他语 - 马耳他语(英国,带 AltGr 覆盖)"
+Language=mt
+Label="mt (alt-gb)"
+
+[keyboard-pt]
+Description="键盘 - 葡萄牙语"
+Language=pt
+Label=pt
+
+[keyboard-pt-nodeadkeys]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(无死键)"
+Language=pt
+Label="pt (nodeadkeys)"
+
+[keyboard-pt-mac]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(Macintosh)"
+Language=pt
+Label="pt (mac)"
+
+[keyboard-pt-mac_nodeadkeys]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(Macintosh,无死键)"
+Language=pt
+Label="pt (mac_nodeadkeys)"
+
+[keyboard-pt-nativo]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(Nativo)"
+Language=pt
+Label="pt (nativo)"
+
+[keyboard-pt-nativo-us]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(用于美式键盘的 Nativo)"
+Language=pt
+Label="pt (nativo-us)"
+
+[keyboard-pt-nativo-epo]
+Description="键盘 - 葡萄牙语 - 世界语(葡萄牙,Nativo)"
+Language=eo
+Label="pt (nativo-epo)"
+
+[keyboard-pt-sun_type6]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(Sun Type 6/7)"
+Language=pt
+Label="pt (sun_type6)"
+
+[keyboard-pt-colemak]
+Description="键盘 - 葡萄牙语 - 葡萄牙语(Colemak)"
+Language=pt
+Label="pt (colemak)"
+
+[keyboard-my]
+Description="键盘 - 马来语(爪夷,阿拉伯键盘)"
+Language=id
+Label=ms
+
+[keyboard-my-phonetic]
+Description="键盘 - 马来语(爪夷,阿拉伯键盘) - 马来语(爪夷,语音助记)"
+Language=id
+Label="my (phonetic)"
+
+[keyboard-mk]
+Description="键盘 - 马其顿语"
+Language=mk
+Label=mk
+
+[keyboard-mk-nodeadkeys]
+Description="键盘 - 马其顿语 - 马其顿语(无死键)"
+Language=mk
+Label="mk (nodeadkeys)"
+
+[keyboard-kg]
+Description="键盘 - 柯尔克孜语(吉尔吉斯语)"
+Language=ky
+Label=ki
+
+[keyboard-kg-phonetic]
+Description="键盘 - 柯尔克孜语(吉尔吉斯语) - 柯尔克孜语(吉尔吉斯语,语音助记)"
+Language=ky
+Label="kg (phonetic)"
+
+[keyboard-tj]
+Description="键盘 - 塔吉克语"
+Language=tg
+Label=tg
+
+[keyboard-tj-legacy]
+Description="键盘 - 塔吉克语 - 塔吉克语(传统)"
+Language=tg
+Label="tj (legacy)"
+
+[keyboard-mv]
+Description="键盘 - 迪维希语"
+Language=dv
+Label=dv
+
+[keyboard-lk]
+Description="键盘 - 僧伽罗语(语音助记)"
+Language=si
+Label=si
+
+[keyboard-lk-us]
+Description="键盘 - 僧伽罗语(语音助记) - 僧伽罗语(美国)"
+Language=si
+Label="si (us)"
+
+[keyboard-lk-tam_unicode]
+Description="键盘 - 僧伽罗语(语音助记) - 泰米尔语(斯里兰卡,TamilNet '99)"
+Language=ta
+Label="ta (tam_unicode)"
+
+[keyboard-lk-tam_TAB]
+Description="键盘 - 僧伽罗语(语音助记) - 泰米尔语(斯里兰卡,TamilNet '99,TAB 编码)"
+Language=ta
+Label="lk (tam_TAB)"
+
+[keyboard-al]
+Description="键盘 - 阿尔巴尼亚语"
+Language=sq
+Label=sq
+
+[keyboard-al-plisi]
+Description="键盘 - 阿尔巴尼亚语 - 阿尔巴尼亚语(Plisi)"
+Language=sq
+Label="al (plisi)"
+
+[keyboard-al-veqilharxhi]
+Description="键盘 - 阿尔巴尼亚语 - 阿尔巴尼亚语(Veqilharxhi)"
+Language=sq
+Label="al (veqilharxhi)"
+
+[keyboard-cz]
+Description="键盘 - 捷克语"
+Language=cs
+Label=cs
+
+[keyboard-cz-bksl]
+Description="键盘 - 捷克语 - 捷克语(额外的反斜杠)"
+Language=cs
+Label="cz (bksl)"
+
+[keyboard-cz-qwerty]
+Description="键盘 - 捷克语 - 捷克语(QWERTY)"
+Language=cs
+Label="cz (qwerty)"
+
+[keyboard-cz-qwerty_bksl]
+Description="键盘 - 捷克语 - 捷克语(QWERTY,额外的反斜杠)"
+Language=cs
+Label="cz (qwerty_bksl)"
+
+[keyboard-cz-winkeys]
+Description="键盘 - 捷克语 - 捷克语(QWERTZ,Windows)"
+Language=cs
+Label="cz (winkeys)"
+
+[keyboard-cz-winkeys-qwerty]
+Description="键盘 - 捷克语 - 捷克语(QWERTY,Windows)"
+Language=cs
+Label="cz (winkeys-qwerty)"
+
+[keyboard-cz-qwerty-mac]
+Description="键盘 - 捷克语 - 捷克语(QWERTY,Macintosh)"
+Language=cs
+Label="cz (qwerty-mac)"
+
+[keyboard-cz-ucw]
+Description="键盘 - 捷克语 - 捷克语(UCW,只有重音字母)"
+Language=cs
+Label="cz (ucw)"
+
+[keyboard-cz-dvorak-ucw]
+Description="键盘 - 捷克语 - 捷克语(美国,Dvorak,支持 UCW)"
+Language=cs
+Label="cz (dvorak-ucw)"
+
+[keyboard-cz-rus]
+Description="键盘 - 捷克语 - 俄语(捷克语,语音助记)"
+Language=ru
+Label="ru (rus)"
+
+[keyboard-cz-sun_type6]
+Description="键盘 - 捷克语 - 捷克语(Sun Type 6/7)"
+Language=cs
+Label="cz (sun_type6)"
+
+[keyboard-cz-prog]
+Description="键盘 - 捷克语 - 捷克语(programming)"
+Language=cs
+Label="cz (prog)"
+
+[keyboard-cz-prog_typo]
+Description="键盘 - 捷克语 - 捷克语(programming,typographic)"
+Language=cs
+Label="cz (prog_typo)"
+
+[keyboard-cz-coder]
+Description="键盘 - 捷克语 - 捷克语(coder)"
+Language=cs
+Label="cz (coder)"
+
+[keyboard-cz-colemak-ucw]
+Description="键盘 - 捷克语 - 捷克语(美国,Colemak,支持 UCW)"
+Language=cs
+Label="cz (colemak-ucw)"
+
+[keyboard-brai]
+Description="键盘 - 盲文"
+Language=
+Label=brl
+
+[keyboard-brai-left_hand]
+Description="键盘 - 盲文 - 盲文(单手,左手)"
+Language=
+Label="brai (left_hand)"
+
+[keyboard-brai-left_hand_invert]
+Description="键盘 - 盲文 - 盲文(单手,左手,大拇指反转)"
+Language=
+Label="brai (left_hand_invert)"
+
+[keyboard-brai-right_hand]
+Description="键盘 - 盲文 - 盲文(单手,右手)"
+Language=
+Label="brai (right_hand)"
+
+[keyboard-brai-right_hand_invert]
+Description="键盘 - 盲文 - 盲文(单手,右手,大拇指反转)"
+Language=
+Label="brai (right_hand_invert)"
+
+[keyboard-se]
+Description="键盘 - 瑞典语"
+Language=sv
+Label=sv
+
+[keyboard-se-nodeadkeys]
+Description="键盘 - 瑞典语 - 瑞典语(无死键)"
+Language=sv
+Label="se (nodeadkeys)"
+
+[keyboard-se-dvorak]
+Description="键盘 - 瑞典语 - 瑞典语(Dvorak)"
+Language=sv
+Label="se (dvorak)"
+
+[keyboard-se-us_dvorak]
+Description="键盘 - 瑞典语 - 瑞典语(Dvorak,国际)"
+Language=sv
+Label="se (us_dvorak)"
+
+[keyboard-se-svdvorak]
+Description="键盘 - 瑞典语 - 瑞典语(Svdvorak)"
+Language=sv
+Label="se (svdvorak)"
+
+[keyboard-se-colemak]
+Description="键盘 - 瑞典语 - 瑞典语(Colemak)"
+Language=sv
+Label="se (colemak)"
+
+[keyboard-se-mac]
+Description="键盘 - 瑞典语 - 瑞典语(Macintosh)"
+Language=sv
+Label="se (mac)"
+
+[keyboard-se-us]
+Description="键盘 - 瑞典语 - 瑞典语(美国)"
+Language=sv
+Label="se (us)"
+
+[keyboard-se-swl]
+Description="键盘 - 瑞典语 - 瑞典手语"
+Language=swl
+Label="se (swl)"
+
+[keyboard-se-smi]
+Description="键盘 - 瑞典语 - 北萨米语(瑞典)"
+Language=se
+Label="se (smi)"
+
+[keyboard-se-rus]
+Description="键盘 - 瑞典语 - 俄语(瑞典,语音助记)"
+Language=ru
+Label="ru (rus)"
+
+[keyboard-se-dvorak_a5]
+Description="键盘 - 瑞典语 - 瑞典语(Dvorak A5)"
+Language=sv
+Label="se (dvorak_a5)"
+
+[keyboard-se-sun_type6]
+Description="键盘 - 瑞典语 - 瑞典语(Sun Type 6/7)"
+Language=sv
+Label="se (sun_type6)"
+
+[keyboard-se-ovd]
+Description="键盘 - 瑞典语 - Elfdalian 语(瑞典,带组合 ogonek)"
+Language=ovd
+Label="se (ovd)"
+
+[keyboard-bg]
+Description="键盘 - 保加利亚语"
+Language=bg
+Label=bg
+
+[keyboard-bg-phonetic]
+Description="键盘 - 保加利亚语 - 保加利亚语(语音助记,传统)"
+Language=bg
+Label="bg (phonetic)"
+
+[keyboard-bg-bas_phonetic]
+Description="键盘 - 保加利亚语 - 保加利亚语(语音助记,新)"
+Language=bg
+Label="bg (bas_phonetic)"
+
+[keyboard-bg-bekl]
+Description="键盘 - 保加利亚语 - 保加利亚语(改进)"
+Language=bg
+Label="bg (bekl)"
+
+[keyboard-pk]
+Description="键盘 - 乌尔都语(巴基斯坦)"
+Language=ur
+Label=ur
+
+[keyboard-pk-urd-crulp]
+Description="键盘 - 乌尔都语(巴基斯坦) - 乌尔都语(巴基斯坦,CRULP)"
+Language=ur
+Label="pk (urd-crulp)"
+
+[keyboard-pk-urd-nla]
+Description="键盘 - 乌尔都语(巴基斯坦) - 乌尔都语(巴基斯坦,NLA)"
+Language=ur
+Label="pk (urd-nla)"
+
+[keyboard-pk-pak_urdu_phonetic]
+Description="键盘 - 乌尔都语(巴基斯坦) - 乌尔都语(Pak Urdu 语音助记)"
+Language=ur
+Label="pk (pak_urdu_phonetic)"
+
+[keyboard-pk-ara]
+Description="键盘 - 乌尔都语(巴基斯坦) - 阿拉伯语(巴基斯坦)"
+Language=ar
+Label="ar (ara)"
+
+[keyboard-pk-snd]
+Description="键盘 - 乌尔都语(巴基斯坦) - 信德语"
+Language=sd
+Label="sd (snd)"
+
+[keyboard-pk-urd-navees]
+Description="键盘 - 乌尔都语(巴基斯坦) - 乌尔都语(巴基斯坦,Navees)"
+Language=ur
+Label="pk (urd-navees)"
+
+[keyboard-au]
+Description="键盘 - 英语(澳大利亚)"
+Language=en
+Label=en
+
+[keyboard-mn]
+Description="键盘 - 蒙古语"
+Language=mn
+Label=mn
+
+[keyboard-dz]
+Description="键盘 - 柏柏尔语(阿尔及利亚,拉丁)"
+Language=tzm
+Label=kab
+
+[keyboard-dz-ber]
+Description="键盘 - 柏柏尔语(阿尔及利亚,拉丁) - 柏柏尔语(阿尔及利亚,提非纳)"
+Language=kab
+Label="kab (ber)"
+
+[keyboard-dz-azerty-deadkeys]
+Description="键盘 - 柏柏尔语(阿尔及利亚,拉丁) - 卡拜尔语(AZERTY,带死键)"
+Language=kab
+Label="kab (azerty-deadkeys)"
+
+[keyboard-dz-qwerty-gb-deadkeys]
+Description="键盘 - 柏柏尔语(阿尔及利亚,拉丁) - 卡拜尔语(QWERTY,英国,带死键)"
+Language=kab
+Label="kab (qwerty-gb-deadkeys)"
+
+[keyboard-dz-qwerty-us-deadkeys]
+Description="键盘 - 柏柏尔语(阿尔及利亚,拉丁) - 卡拜尔语(QWERTY,美国,带死键)"
+Language=kab
+Label="kab (qwerty-us-deadkeys)"
+
+[keyboard-dz-ar]
+Description="键盘 - 柏柏尔语(阿尔及利亚,拉丁) - 阿拉伯语(阿尔及利亚)"
+Language=ar
+Label=ar
+
+[keyboard-me]
+Description="键盘 - 黑山语"
+Language=sr
+Label=sr
+
+[keyboard-me-cyrillic]
+Description="键盘 - 黑山语 - 黑山语(西里尔)"
+Language=sr
+Label="me (cyrillic)"
+
+[keyboard-me-cyrillicyz]
+Description="键盘 - 黑山语 - 黑山语(西里尔,交换 ZE 和 ZHE)"
+Language=sr
+Label="me (cyrillicyz)"
+
+[keyboard-me-cyrillicalternatequotes]
+Description="键盘 - 黑山语 - 黑山语(西里尔,带书名号引号)"
+Language=sr
+Label="me (cyrillicalternatequotes)"
+
+[keyboard-me-latinunicode]
+Description="键盘 - 黑山语 - 黑山语(拉丁,Unicode)"
+Language=sr
+Label="me (latinunicode)"
+
+[keyboard-me-latinyz]
+Description="键盘 - 黑山语 - 黑山语(拉丁,QWERTY)"
+Language=sr
+Label="me (latinyz)"
+
+[keyboard-me-latinunicodeyz]
+Description="键盘 - 黑山语 - 黑山语(拉丁,Unicode,QWERTY)"
+Language=sr
+Label="me (latinunicodeyz)"
+
+[keyboard-me-latinalternatequotes]
+Description="键盘 - 黑山语 - 黑山语(拉丁,带书名号引号)"
+Language=sr
+Label="me (latinalternatequotes)"
+
+[keyboard-lv]
+Description="键盘 - 拉脱维亚语"
+Language=lv
+Label=lv
+
+[keyboard-lv-apostrophe]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(撇号)"
+Language=lv
+Label="lv (apostrophe)"
+
+[keyboard-lv-tilde]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(波浪号)"
+Language=lv
+Label="lv (tilde)"
+
+[keyboard-lv-fkey]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(F)"
+Language=lv
+Label="lv (fkey)"
+
+[keyboard-lv-modern]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(现代拉丁)"
+Language=lv
+Label="lv (modern)"
+
+[keyboard-lv-modern-cyr]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(现代西里尔)"
+Language=lv
+Label="lv (modern-cyr)"
+
+[keyboard-lv-ergonomic]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(人体工学,ŪGJRMV)"
+Language=lv
+Label="lv (ergonomic)"
+
+[keyboard-lv-adapted]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(改良)"
+Language=lv
+Label="lv (adapted)"
+
+[keyboard-lv-dvorak]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(Dvorak)"
+Language=lv
+Label="lv (dvorak)"
+
+[keyboard-lv-ykeydvorak]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(Dvorak,带 Y)"
+Language=lv
+Label="lv (ykeydvorak)"
+
+[keyboard-lv-minuskeydvorak]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(Dvorak,带减号)"
+Language=lv
+Label="lv (minuskeydvorak)"
+
+[keyboard-lv-dvorakprogr]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(适合程序员的 Dvorak)"
+Language=lv
+Label="lv (dvorakprogr)"
+
+[keyboard-lv-ykeydvorakprogr]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(适合程序员的 Dvorak,带 Y)"
+Language=lv
+Label="lv (ykeydvorakprogr)"
+
+[keyboard-lv-minuskeydvorakprogr]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(适合程序员的 Dvorak,带减号)"
+Language=lv
+Label="lv (minuskeydvorakprogr)"
+
+[keyboard-lv-colemak]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(Colemak)"
+Language=lv
+Label="lv (colemak)"
+
+[keyboard-lv-apostrophecolemak]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(Colemak,带撇号)"
+Language=lv
+Label="lv (apostrophecolemak)"
+
+[keyboard-lv-sun_type6]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(Sun Type 6/7)"
+Language=lv
+Label="lv (sun_type6)"
+
+[keyboard-lv-apostrophe-deadquotes]
+Description="键盘 - 拉脱维亚语 - 拉脱维亚语(带撇号,引号为死键)"
+Language=lv
+Label="lv (apostrophe-deadquotes)"
+
+[keyboard-ba]
+Description="键盘 - 波斯尼亚语"
+Language=bs
+Label=bs
+
+[keyboard-ba-alternatequotes]
+Description="键盘 - 波斯尼亚语 - 波斯尼亚语(带书名号引号)"
+Language=bs
+Label="ba (alternatequotes)"
+
+[keyboard-ba-unicode]
+Description="键盘 - 波斯尼亚语 - 波斯尼亚语(带波斯尼亚二重字)"
+Language=bs
+Label="ba (unicode)"
+
+[keyboard-ba-unicodeus]
+Description="键盘 - 波斯尼亚语 - 波斯尼亚语(美国,带罗马尼亚二重字)"
+Language=bs
+Label="ba (unicodeus)"
+
+[keyboard-ba-us]
+Description="键盘 - 波斯尼亚语 - 波斯尼亚语(美国)"
+Language=bs
+Label="ba (us)"
+
+[keyboard-tw]
+Description="键盘 - 台语"
+Language=fox
+Label=zh
+
+[keyboard-tw-indigenous]
+Description="键盘 - 台语 - 台语(原住民)"
+Language=ami
+Label="tw (indigenous)"
+
+[keyboard-tw-saisiyat]
+Description="键盘 - 台语 - 赛夏语(台湾)"
+Language=xsy
+Label="xsy (saisiyat)"
+
+[keyboard-rs]
+Description="键盘 - 塞尔维亚语"
+Language=sr
+Label=sr
+
+[keyboard-rs-alternatequotes]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚语(西里尔,带书名号引号)"
+Language=sr
+Label="rs (alternatequotes)"
+
+[keyboard-rs-yz]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚语(西里尔,交换 ZE 和 ZHE)"
+Language=sr
+Label="rs (yz)"
+
+[keyboard-rs-latin]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚语(拉丁)"
+Language=sr
+Label="rs (latin)"
+
+[keyboard-rs-latinalternatequotes]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚语(拉丁,带书名号引号)"
+Language=sr
+Label="rs (latinalternatequotes)"
+
+[keyboard-rs-latinunicode]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚语(拉丁,Unicode)"
+Language=sr
+Label="rs (latinunicode)"
+
+[keyboard-rs-latinyz]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚(拉丁,QWERTY)"
+Language=sr
+Label="rs (latinyz)"
+
+[keyboard-rs-latinunicodeyz]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚(拉丁,Unicode,QWERTY)"
+Language=sr
+Label="rs (latinunicodeyz)"
+
+[keyboard-rs-rue]
+Description="键盘 - 塞尔维亚语 - 潘诺尼亚卢森尼亚语"
+Language=rue
+Label="rs (rue)"
+
+[keyboard-rs-combiningkeys]
+Description="键盘 - 塞尔维亚语 - 塞尔维亚语(组合重音而不使用死键)"
+Language=sr
+Label="rs (combiningkeys)"
+
+[keyboard-dk]
+Description="键盘 - 丹麦语"
+Language=da
+Label=da
+
+[keyboard-dk-nodeadkeys]
+Description="键盘 - 丹麦语 - 丹麦语(无死键)"
+Language=da
+Label="dk (nodeadkeys)"
+
+[keyboard-dk-winkeys]
+Description="键盘 - 丹麦语 - 丹麦语(Windows)"
+Language=da
+Label="dk (winkeys)"
+
+[keyboard-dk-mac]
+Description="键盘 - 丹麦语 - 丹麦语(Macintosh)"
+Language=da
+Label="dk (mac)"
+
+[keyboard-dk-mac_nodeadkeys]
+Description="键盘 - 丹麦语 - 丹麦语(Macintosh,无死键)"
+Language=da
+Label="dk (mac_nodeadkeys)"
+
+[keyboard-dk-dvorak]
+Description="键盘 - 丹麦语 - 丹麦语(Dvorak)"
+Language=da
+Label="dk (dvorak)"
+
+[keyboard-dk-sun_type6]
+Description="键盘 - 丹麦语 - 丹麦语(Sun Type 6/7)"
+Language=da
+Label="dk (sun_type6)"
+
+[keyboard-bw]
+Description="键盘 - 茨瓦纳语"
+Language=tn
+Label=tn
+
+[keyboard-kr]
+Description="键盘 - 朝鲜语"
+Language=ko
+Label=ko
+
+[keyboard-kr-kr104]
+Description="键盘 - 朝鲜语 - 朝鲜语(兼容 101/104 键)"
+Language=ko
+Label="kr (kr104)"
+
+[keyboard-kr-sun_type6]
+Description="键盘 - 朝鲜语 - 朝鲜语(Sun Type 6/7)"
+Language=ko
+Label="kr (sun_type6)"
+
+[keyboard-nl]
+Description="键盘 - 荷兰语"
+Language=nl
+Label=nl
+
+[keyboard-nl-us]
+Description="键盘 - 荷兰语 - 荷兰语(美国)"
+Language=nl
+Label="nl (us)"
+
+[keyboard-nl-mac]
+Description="键盘 - 荷兰语 - 荷兰语(Macintosh)"
+Language=nl
+Label="nl (mac)"
+
+[keyboard-nl-std]
+Description="键盘 - 荷兰语 - 荷兰语(标准)"
+Language=nl
+Label="nl (std)"
+
+[keyboard-nl-sun_type6]
+Description="键盘 - 荷兰语 - 荷兰语(Sun Type 6/7)"
+Language=nl
+Label="nl (sun_type6)"
+
+[keyboard-et]
+Description="键盘 - 阿姆哈拉语"
+Language=am
+Label=am
+
+[keyboard-be]
+Description="键盘 - 比利时语"
+Language=de
+Label=be
+
+[keyboard-be-oss]
+Description="键盘 - 比利时语 - 比利时语(替代)"
+Language=de
+Label="be (oss)"
+
+[keyboard-be-oss_latin9]
+Description="键盘 - 比利时语 - 比利时语(只包含拉丁-9 字符,替代)"
+Language=de
+Label="be (oss_latin9)"
+
+[keyboard-be-iso-alternate]
+Description="键盘 - 比利时语 - 比利时语(ISO,替代)"
+Language=de
+Label="be (iso-alternate)"
+
+[keyboard-be-nodeadkeys]
+Description="键盘 - 比利时语 - 比利时语(无死键)"
+Language=de
+Label="be (nodeadkeys)"
+
+[keyboard-be-wang]
+Description="键盘 - 比利时语 - 比利时语(王安 724 型 AZERTY)"
+Language=de
+Label="be (wang)"
+
+[keyboard-be-sun_type6]
+Description="键盘 - 比利时语 - 比利时语(Sun Type 6/7)"
+Language=de
+Label="be (sun_type6)"
+
+[keyboard-la]
+Description="键盘 - 老挝语"
+Language=lo
+Label=lo
+
+[keyboard-la-stea]
+Description="键盘 - 老挝语 - 老挝语(STEA)"
+Language=lo
+Label="la (stea)"
+
+[keyboard-bt]
+Description="键盘 - 不丹语"
+Language=dz
+Label=dz
+
+[keyboard-mm]
+Description="键盘 - 缅甸语"
+Language=my
+Label=my
+
+[keyboard-mm-zawgyi]
+Description="键盘 - 缅甸语 - 缅甸语(Zawgyi)"
+Language=my
+Label="my-zwg (zawgyi)"
+
+[keyboard-mm-mnw]
+Description="键盘 - 缅甸语 - 孟语"
+Language=mnw
+Label=mnw
+
+[keyboard-mm-mnw-a1]
+Description="键盘 - 缅甸语 - 孟语(A1)"
+Language=mnw
+Label="mnw (mnw-a1)"
+
+[keyboard-mm-shn]
+Description="键盘 - 缅甸语 - 掸语"
+Language=shn
+Label=shn
+
+[keyboard-mm-zgt]
+Description="键盘 - 缅甸语 - 掸语(Zawgyi)"
+Language=shn
+Label="shn-zwg (zgt)"
+
+[keyboard-si]
+Description="键盘 - 斯洛文尼亚语"
+Language=sl
+Label=sl
+
+[keyboard-si-alternatequotes]
+Description="键盘 - 斯洛文尼亚语 - 斯洛文尼亚语(带书名号引号)"
+Language=sl
+Label="si (alternatequotes)"
+
+[keyboard-si-us]
+Description="键盘 - 斯洛文尼亚语 - 斯洛文尼亚语(美国)"
+Language=sl
+Label="si (us)"
+
+[keyboard-am]
+Description="键盘 - 亚美尼亚语"
+Language=hy
+Label=hy
+
+[keyboard-am-phonetic]
+Description="键盘 - 亚美尼亚语 - 亚美尼亚语(语音助记)"
+Language=hy
+Label="am (phonetic)"
+
+[keyboard-am-phonetic-alt]
+Description="键盘 - 亚美尼亚语 - 亚美尼亚语(替代,语音助记)"
+Language=hy
+Label="am (phonetic-alt)"
+
+[keyboard-am-eastern]
+Description="键盘 - 亚美尼亚语 - 亚美尼亚语(东部)"
+Language=hy
+Label="am (eastern)"
+
+[keyboard-am-eastern-alt]
+Description="键盘 - 亚美尼亚语 - 亚美尼亚语(替代,东部)"
+Language=hy
+Label="am (eastern-alt)"
+
+[keyboard-am-western]
+Description="键盘 - 亚美尼亚语 - 亚美尼亚语(西部)"
+Language=hy
+Label="am (western)"
+
+[keyboard-am-olpc-phonetic]
+Description="键盘 - 亚美尼亚语 - 亚美尼亚语(OLPC,语音助记)"
+Language=hy
+Label="am (olpc-phonetic)"
+
+[keyboard-by]
+Description="键盘 - 白俄罗斯语"
+Language=be
+Label=by
+
+[keyboard-by-legacy]
+Description="键盘 - 白俄罗斯语 - 白俄罗斯语(传统)"
+Language=be
+Label="by (legacy)"
+
+[keyboard-by-latin]
+Description="键盘 - 白俄罗斯语 - 白俄罗斯语(拉丁)"
+Language=be
+Label="by (latin)"
+
+[keyboard-by-intl]
+Description="键盘 - 白俄罗斯语 - 白俄罗斯语(国际)"
+Language=be
+Label="by (intl)"
+
+[keyboard-by-phonetic]
+Description="键盘 - 白俄罗斯语 - 白俄罗斯语(语音助记)"
+Language=be
+Label="by (phonetic)"
+
+[keyboard-by-ru]
+Description="键盘 - 白俄罗斯语 - 俄语(白俄罗斯)"
+Language=ru
+Label="by (ru)"
+
+[keyboard-vn]
+Description="键盘 - 越南语"
+Language=vi
+Label=vi
+
+[keyboard-vn-us]
+Description="键盘 - 越南语 - 越南语(美国)"
+Language=vi
+Label="vn (us)"
+
+[keyboard-vn-fr]
+Description="键盘 - 越南语 - 越南语(法国)"
+Language=vi
+Label="vn (fr)"
+
+[keyboard-vn-aderty]
+Description="键盘 - 越南语 - 越南语(AÐERTY)"
+Language=vi
+Label="vn (aderty)"
+
+[keyboard-vn-qderty]
+Description="键盘 - 越南语 - 越南语(QĐERTY)"
+Language=vi
+Label="vn (qderty)"
+
+[keyboard-ml]
+Description="键盘 - 班巴拉语"
+Language=bm
+Label=bm
+
+[keyboard-ml-fr-oss]
+Description="键盘 - 班巴拉语 - 法语(马里,替代)"
+Language=fr
+Label="fr (fr-oss)"
+
+[keyboard-ml-us-mac]
+Description="键盘 - 班巴拉语 - 英语(马里,美国,Macintosh)"
+Language=en
+Label="en (us-mac)"
+
+[keyboard-ml-us-intl]
+Description="键盘 - 班巴拉语 - 英语(马里,美国,国际)"
+Language=en
+Label="en (us-intl)"
+
+[keyboard-ara]
+Description="键盘 - 阿拉伯语"
+Language=ar
+Label=ar
+
+[keyboard-ara-digits]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(东阿拉伯语数字)"
+Language=ar
+Label="ara (digits)"
+
+[keyboard-ara-azerty]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(AZERTY)"
+Language=ar
+Label="ara (azerty)"
+
+[keyboard-ara-azerty_digits]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(AZERTY,东阿拉伯语数字)"
+Language=ar
+Label="ara (azerty_digits)"
+
+[keyboard-ara-buckwalter]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(Buckwalter)"
+Language=ar
+Label="ara (buckwalter)"
+
+[keyboard-ara-mac]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(Macintosh)"
+Language=ar
+Label="ara (mac)"
+
+[keyboard-ara-mac-phonetic]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(Macintosh,语音助记)"
+Language=ar
+Label="ara (mac-phonetic)"
+
+[keyboard-ara-olpc]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(OLPC)"
+Language=ar
+Label="ara (olpc)"
+
+[keyboard-ara-sun_type6]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(Sun Type 6/7)"
+Language=ar
+Label="ara (sun_type6)"
+
+[keyboard-ara-basic_ext]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(阿拉伯数字,第 4 层带扩展)"
+Language=ar
+Label="ara (basic_ext)"
+
+[keyboard-ara-basic_ext_digits]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(东阿拉伯数字,第 4 层带扩展)"
+Language=ar
+Label="ara (basic_ext_digits)"
+
+[keyboard-ara-ergoarabic]
+Description="键盘 - 阿拉伯语 - 阿拉伯语(ErgoArabic)"
+Language=ar
+Label="ara (ergoarabic)"
+
+[keyboard-ie]
+Description="键盘 - 爱尔兰语"
+Language=en
+Label=ie
+
+[keyboard-ie-UnicodeExpert]
+Description="键盘 - 爱尔兰语 - 爱尔兰语(UnicodeExpert)"
+Language=en
+Label="ie (UnicodeExpert)"
+
+[keyboard-ie-CloGaelach]
+Description="键盘 - 爱尔兰语 - CloGaelach"
+Language=ga
+Label="ie (CloGaelach)"
+
+[keyboard-ie-ogam]
+Description="键盘 - 爱尔兰语 - 欧甘语"
+Language=sga
+Label="ie (ogam)"
+
+[keyboard-ie-ogam_is434]
+Description="键盘 - 爱尔兰语 - 欧甘语(IS434)"
+Language=sga
+Label="ie (ogam_is434)"
+
+[keyboard-cm]
+Description="键盘 - 英语(喀麦隆)"
+Language=en
+Label=cm
+
+[keyboard-cm-french]
+Description="键盘 - 英语(喀麦隆) - 法语(喀麦隆)"
+Language=fr
+Label="fr (french)"
+
+[keyboard-cm-qwerty]
+Description="键盘 - 英语(喀麦隆) - 喀麦隆多语言(QWERTY,国际)"
+Language=en
+Label="cm (qwerty)"
+
+[keyboard-cm-azerty]
+Description="键盘 - 英语(喀麦隆) - 喀麦隆(AZERTY,国际)"
+Language=fr
+Label="cm (azerty)"
+
+[keyboard-cm-dvorak]
+Description="键盘 - 英语(喀麦隆) - 喀麦隆(Dvorak,国际)"
+Language=en
+Label="cm (dvorak)"
+
+[keyboard-cm-mmuock]
+Description="键盘 - 英语(喀麦隆) - 喀麦隆(Mmuock)"
+Language=en
+Label="cm (mmuock)"
+
+[keyboard-iq]
+Description="键盘 - 阿拉伯语(伊拉克)"
+Language=ar
+Label=ar
+
+[keyboard-iq-ku]
+Description="键盘 - 阿拉伯语(伊拉克) - 库尔德语(伊拉克,拉丁 Q)"
+Language=ku
+Label=ku
+
+[keyboard-iq-ku_alt]
+Description="键盘 - 阿拉伯语(伊拉克) - 库尔德语(伊拉克,拉丁 Alt-Q)"
+Language=ku
+Label="ku (ku_alt)"
+
+[keyboard-iq-ku_f]
+Description="键盘 - 阿拉伯语(伊拉克) - 库尔德语(伊拉克,F)"
+Language=ku
+Label="ku (ku_f)"
+
+[keyboard-iq-ku_ara]
+Description="键盘 - 阿拉伯语(伊拉克) - 库尔德语(伊拉克,阿拉伯-拉丁)"
+Language=ku
+Label="ku (ku_ara)"
+
+[keyboard-af]
+Description="键盘 - 达里语"
+Language=prs
+Label=fa
+
+[keyboard-af-ps]
+Description="键盘 - 达里语 - 普什图语"
+Language=ps
+Label=ps
+
+[keyboard-af-uz]
+Description="键盘 - 达里语 - 乌兹别克语(阿富汗)"
+Language=uz
+Label=uz
+
+[keyboard-af-fa-olpc]
+Description="键盘 - 达里语 - 达里语(阿富汗,OLPC)"
+Language=prs
+Label="fa (fa-olpc)"
+
+[keyboard-af-ps-olpc]
+Description="键盘 - 达里语 - 普什图语(阿富汗,OLPC)"
+Language=ps
+Label="ps (ps-olpc)"
+
+[keyboard-af-uz-olpc]
+Description="键盘 - 达里语 - 乌兹别克语(阿富汗,OLPC)"
+Language=uz
+Label="uz (uz-olpc)"
+
+[keyboard-hr]
+Description="键盘 - 克罗地亚语"
+Language=hr
+Label=hr
+
+[keyboard-hr-alternatequotes]
+Description="键盘 - 克罗地亚语 - 克罗地亚语(带书名号引号)"
+Language=hr
+Label="hr (alternatequotes)"
+
+[keyboard-hr-unicode]
+Description="键盘 - 克罗地亚语 - 克罗地亚语(带克罗地亚语二重字)"
+Language=hr
+Label="hr (unicode)"
+
+[keyboard-hr-unicodeus]
+Description="键盘 - 克罗地亚语 - 克罗地亚语(美国,带克罗地亚语二重字)"
+Language=hr
+Label="hr (unicodeus)"
+
+[keyboard-hr-us]
+Description="键盘 - 克罗地亚语 - 克罗地亚语(美国)"
+Language=hr
+Label="hr (us)"
+
+[keyboard-ma]
+Description="键盘 - 阿拉伯语(摩洛哥)"
+Language=ary
+Label=ar
+
+[keyboard-ma-tifinagh]
+Description="键盘 - 阿拉伯语(摩洛哥) - 柏柏尔语(摩洛哥,提非纳)"
+Language=ber
+Label="ber (tifinagh)"
+
+[keyboard-ma-tifinagh-alt]
+Description="键盘 - 阿拉伯语(摩洛哥) - 柏柏尔语(摩洛哥,提非纳,替代)"
+Language=ber
+Label="ber (tifinagh-alt)"
+
+[keyboard-ma-tifinagh-alt-phonetic]
+Description="键盘 - 阿拉伯语(摩洛哥) - 柏柏尔语(摩洛哥,提非纳语音助记,替代)"
+Language=ber
+Label="ber (tifinagh-alt-phonetic)"
+
+[keyboard-ma-tifinagh-extended]
+Description="键盘 - 阿拉伯语(摩洛哥) - 柏柏尔语(摩洛哥,提非纳扩展)"
+Language=ber
+Label="ber (tifinagh-extended)"
+
+[keyboard-ma-tifinagh-phonetic]
+Description="键盘 - 阿拉伯语(摩洛哥) - 柏柏尔语(摩洛哥,提非纳语音助记)"
+Language=ber
+Label="ber (tifinagh-phonetic)"
+
+[keyboard-ma-tifinagh-extended-phonetic]
+Description="键盘 - 阿拉伯语(摩洛哥) - 柏柏尔语(摩洛哥,提非纳扩展语音助记)"
+Language=ber
+Label="ber (tifinagh-extended-phonetic)"
+
+[keyboard-ma-french]
+Description="键盘 - 阿拉伯语(摩洛哥) - 法语(摩洛哥)"
+Language=fr
+Label="fr (french)"
+
+[keyboard-ma-rif]
+Description="键盘 - 阿拉伯语(摩洛哥) - 里夫语"
+Language=rif
+Label=rif
+
+[keyboard-sy]
+Description="键盘 - 阿拉伯语(叙利亚)"
+Language=syr
+Label=ar
+
+[keyboard-sy-syc]
+Description="键盘 - 阿拉伯语(叙利亚) - 叙利亚语"
+Language=syr
+Label=syc
+
+[keyboard-sy-syc_phonetic]
+Description="键盘 - 阿拉伯语(叙利亚) - 叙利亚语(语音助记)"
+Language=syr
+Label="syc (syc_phonetic)"
+
+[keyboard-sy-ku]
+Description="键盘 - 阿拉伯语(叙利亚) - 库尔德语(叙利亚,拉丁 Q)"
+Language=ku
+Label=ku
+
+[keyboard-sy-ku_alt]
+Description="键盘 - 阿拉伯语(叙利亚) - 库尔德语(叙利亚,拉丁 Alt-Q)"
+Language=ku
+Label="ku (ku_alt)"
+
+[keyboard-sy-ku_f]
+Description="键盘 - 阿拉伯语(叙利亚) - 库尔德语(叙利亚,F)"
+Language=ku
+Label="ku (ku_f)"
+
+[keyboard-at]
+Description="键盘 - 德语(奥地利)"
+Language=de
+Label=de
+
+[keyboard-at-nodeadkeys]
+Description="键盘 - 德语(奥地利) - 德语(奥地利,无死键)"
+Language=de
+Label="at (nodeadkeys)"
+
+[keyboard-at-mac]
+Description="键盘 - 德语(奥地利) - 德语(奥地利,Macintosh)"
+Language=de
+Label="at (mac)"
+
+[keyboard-nz]
+Description="键盘 - 英语(新西兰)"
+Language=en
+Label=en
+
+[keyboard-nz-mao]
+Description="键盘 - 英语(新西兰) - 毛利语"
+Language=mi
+Label="mi (mao)"
+
+[keyboard-epo]
+Description="键盘 - 世界语"
+Language=eo
+Label=eo
+
+[keyboard-epo-legacy]
+Description="键盘 - 世界语 - 世界语(传统)"
+Language=eo
+Label="epo (legacy)"
+
+[keyboard-eu]
+Description="键盘 - EurKEY(美国)"
+Language=ca
+Label=eu
+
+[keyboard-za]
+Description="键盘 - 英语(南非)"
+Language=en
+Label=en
+
+[keyboard-fo]
+Description="键盘 - 法罗语"
+Language=fo
+Label=fo
+
+[keyboard-fo-nodeadkeys]
+Description="键盘 - 法罗语 - 法罗语(无死键)"
+Language=fo
+Label="fo (nodeadkeys)"
+
+[keyboard-gb]
+Description="键盘 - 英语(英国)"
+Language=en
+Label=en
+
+[keyboard-gb-extd]
+Description="键盘 - 英语(英国) - 英语(英国,扩展,Windows)"
+Language=en
+Label="gb (extd)"
+
+[keyboard-gb-intl]
+Description="键盘 - 英语(英国) - 英语(英国,国际,带死键)"
+Language=en
+Label="gb (intl)"
+
+[keyboard-gb-dvorak]
+Description="键盘 - 英语(英国) - 英语(英国,Dvorak)"
+Language=en
+Label="gb (dvorak)"
+
+[keyboard-gb-dvorakukp]
+Description="键盘 - 英语(英国) - 英语(英国,Dvorak,带英国标点)"
+Language=en
+Label="gb (dvorakukp)"
+
+[keyboard-gb-mac]
+Description="键盘 - 英语(英国) - 英语(英国,Macintosh)"
+Language=en
+Label="gb (mac)"
+
+[keyboard-gb-mac_intl]
+Description="键盘 - 英语(英国) - 英语(英国,Macintosh,国际)"
+Language=en
+Label="gb (mac_intl)"
+
+[keyboard-gb-colemak]
+Description="键盘 - 英语(英国) - 英语(英国,Colemak)"
+Language=en
+Label="gb (colemak)"
+
+[keyboard-gb-colemak_dh]
+Description="键盘 - 英语(英国) - 英语(英国,Colemak-DH)"
+Language=en
+Label="gb (colemak_dh)"
+
+[keyboard-gb-gla]
+Description="键盘 - 英语(英国) - 苏格兰盖尔语"
+Language=en
+Label="gd (gla)"
+
+[keyboard-gb-pl]
+Description="键盘 - 英语(英国) - 波兰语(英式键盘)"
+Language=pl
+Label=pl
+
+[keyboard-gb-sun_type6]
+Description="键盘 - 英语(英国) - 英语(英国,Sun Type 6/7)"
+Language=en
+Label="gb (sun_type6)"
+
+[keyboard-ke]
+Description="键盘 - 斯瓦希里语(肯尼亚)"
+Language=sw
+Label=sw
+
+[keyboard-ke-kik]
+Description="键盘 - 斯瓦希里语(肯尼亚) - 基库尤语"
+Language=ki
+Label="ki (kik)"
+
+[keyboard-md]
+Description="键盘 - 摩尔多瓦语"
+Language=ro
+Label=ro
+
+[keyboard-md-gag]
+Description="键盘 - 摩尔多瓦语 - 加告兹语(摩尔多瓦)"
+Language=gag
+Label=gag
+
+[keyboard-us]
+Description="键盘 - 英语(美国)"
+Language=en
+Label=en
+
+[keyboard-us-euro]
+Description="键盘 - 英语(美国) - 英语(美国,5 键上是欧元符号)"
+Language=en
+Label="us (euro)"
+
+[keyboard-us-intl]
+Description="键盘 - 英语(美国) - 英语(美国,国际,带死键)"
+Language=en
+Label="us (intl)"
+
+[keyboard-us-alt-intl]
+Description="键盘 - 英语(美国) - 英语(美国,替代,国际)"
+Language=en
+Label="us (alt-intl)"
+
+[keyboard-us-altgr-intl]
+Description="键盘 - 英语(美国) - 英语(国际,带 AltGr 死键)"
+Language=en
+Label="us (altgr-intl)"
+
+[keyboard-us-mac]
+Description="键盘 - 英语(美国) - 英语(Macintosh,ABC,ANSI)"
+Language=en
+Label="us (mac)"
+
+[keyboard-us-mac-iso]
+Description="键盘 - 英语(美国) - 英语(Macintosh,ABC,ISO)"
+Language=en
+Label="us (mac-iso)"
+
+[keyboard-us-colemak]
+Description="键盘 - 英语(美国) - 英语(Colemak)"
+Language=en
+Label="us (colemak)"
+
+[keyboard-us-colemak_dh]
+Description="键盘 - 英语(美国) - 英语(Colemak-DH)"
+Language=en
+Label="us (colemak_dh)"
+
+[keyboard-us-colemak_dh_wide]
+Description="键盘 - 英语(美国) - 英语(Colemak-DH 宽版)"
+Language=en
+Label="us (colemak_dh_wide)"
+
+[keyboard-us-colemak_dh_ortho]
+Description="键盘 - 英语(美国) - 英语(Colemak-DH 正交)"
+Language=en
+Label="us (colemak_dh_ortho)"
+
+[keyboard-us-colemak_dh_iso]
+Description="键盘 - 英语(美国) - 英语(Colemak-DH ISO)"
+Language=en
+Label="us (colemak_dh_iso)"
+
+[keyboard-us-colemak_dh_wide_iso]
+Description="键盘 - 英语(美国) - 英语(Colemak-DH 宽版 ISO)"
+Language=en
+Label="us (colemak_dh_wide_iso)"
+
+[keyboard-us-dvorak]
+Description="键盘 - 英语(美国) - 英语(Dvorak)"
+Language=en
+Label="us (dvorak)"
+
+[keyboard-us-dvorak-intl]
+Description="键盘 - 英语(美国) - 英语(Dvorak,国际,带死键)"
+Language=en
+Label="us (dvorak-intl)"
+
+[keyboard-us-dvorak-alt-intl]
+Description="键盘 - 英语(美国) - 英语(Dvorak,替代,国际)"
+Language=en
+Label="us (dvorak-alt-intl)"
+
+[keyboard-us-dvorak-l]
+Description="键盘 - 英语(美国) - 英语(Dvorak,单手,左手)"
+Language=en
+Label="us (dvorak-l)"
+
+[keyboard-us-dvorak-r]
+Description="键盘 - 英语(美国) - 英语(Dvorak,单手,右手)"
+Language=en
+Label="us (dvorak-r)"
+
+[keyboard-us-dvorak-classic]
+Description="键盘 - 英语(美国) - 英语(经典 Dvorak)"
+Language=en
+Label="us (dvorak-classic)"
+
+[keyboard-us-dvp]
+Description="键盘 - 英语(美国) - 英语(适合程序员的 Dvorak)"
+Language=en
+Label="us (dvp)"
+
+[keyboard-us-dvorak-mac]
+Description="键盘 - 英语(美国) - 英语(Dvorak,Macintosh,ANSI)"
+Language=en
+Label="us (dvorak-mac)"
+
+[keyboard-us-dvorak-mac-iso]
+Description="键盘 - 英语(美国) - 英语(Dvorak,Macintosh,ISO)"
+Language=en
+Label="us (dvorak-mac-iso)"
+
+[keyboard-us-norman]
+Description="键盘 - 英语(美国) - 英语(Norman)"
+Language=en
+Label="us (norman)"
+
+[keyboard-us-symbolic]
+Description="键盘 - 英语(美国) - 英语(美国,符号)"
+Language=en
+Label="us (symbolic)"
+
+[keyboard-us-workman]
+Description="键盘 - 英语(美国) - 英语(Workman)"
+Language=en
+Label="us (workman)"
+
+[keyboard-us-workman-intl]
+Description="键盘 - 英语(美国) - 英语(Workman,国际,带死键)"
+Language=en
+Label="us (workman-intl)"
+
+[keyboard-us-olpc2]
+Description="键盘 - 英语(美国) - 英语(除/乘键切换布局)"
+Language=en
+Label="us (olpc2)"
+
+[keyboard-us-chr]
+Description="键盘 - 英语(美国) - 切罗基语"
+Language=chr
+Label=chr
+
+[keyboard-us-haw]
+Description="键盘 - 英语(美国) - 夏威夷语"
+Language=haw
+Label=haw
+
+[keyboard-us-rus]
+Description="键盘 - 英语(美国) - 俄语(美国,语音助记)"
+Language=ru
+Label="ru (rus)"
+
+[keyboard-us-hbs]
+Description="键盘 - 英语(美国) - 塞尔维亚-克罗地亚语(美国)"
+Language=en
+Label="us (hbs)"
+
+[keyboard-us-intl-unicode]
+Description="键盘 - 英语(美国) - 英语(美国,国际,AltGr Unicode 组合字符)"
+Language=en
+Label="us (intl-unicode)"
+
+[keyboard-us-alt-intl-unicode]
+Description="键盘 - 英语(美国) - 英语(美国,国际,AltGr Unicode 组合字符,替代)"
+Language=en
+Label="us (alt-intl-unicode)"
+
+[keyboard-us-ats]
+Description="键盘 - 英语(美国) - 阿特塞纳语"
+Language=en
+Label="us (ats)"
+
+[keyboard-us-crd]
+Description="键盘 - 英语(美国) - 科达莲萨利希语"
+Language=crd
+Label="us (crd)"
+
+[keyboard-us-cz_sk_de]
+Description="键盘 - 英语(美国) - 捷克语、斯洛伐克语和德语(美国)"
+Language=en
+Label="us (cz_sk_de)"
+
+[keyboard-us-cz_sk_pl_de_es_fi_sv]
+Description="键盘 - 英语(美国) - 捷克语、斯洛伐克语、波兰语、西班牙语、芬兰语、瑞典语和德语(美国)"
+Language=en
+Label="us (cz_sk_pl_de_es_fi_sv)"
+
+[keyboard-us-drix]
+Description="键盘 - 英语(美国) - 英语(Drix)"
+Language=en
+Label="us (drix)"
+
+[keyboard-us-de_se_fi]
+Description="键盘 - 英语(美国) - 德语,瑞典语和芬兰语(美国)"
+Language=en
+Label="us (de_se_fi)"
+
+[keyboard-us-ibm238l]
+Description="键盘 - 英语(美国) - 英语(美国,IBM Arabic 238_L)"
+Language=en
+Label="us (ibm238l)"
+
+[keyboard-us-sun_type6]
+Description="键盘 - 英语(美国) - 英语(美国,Sun Type 6/7)"
+Language=en
+Label="us (sun_type6)"
+
+[keyboard-us-carpalx]
+Description="键盘 - 英语(美国) - 英语(Carpalx)"
+Language=en
+Label="us (carpalx)"
+
+[keyboard-us-carpalx-intl]
+Description="键盘 - 英语(美国) - 英语(Carpalx,国际,带死键)"
+Language=en
+Label="us (carpalx-intl)"
+
+[keyboard-us-carpalx-altgr-intl]
+Description="键盘 - 英语(美国) - 英语(Carpalx,国际,带 AltGr 死键)"
+Language=en
+Label="us (carpalx-altgr-intl)"
+
+[keyboard-us-carpalx-full]
+Description="键盘 - 英语(美国) - 英语(Carpalx,完全优化)"
+Language=en
+Label="us (carpalx-full)"
+
+[keyboard-us-carpalx-full-intl]
+Description="键盘 - 英语(美国) - 英语(Carpalx,完全优化,国际,带死键)"
+Language=en
+Label="us (carpalx-full-intl)"
+
+[keyboard-us-carpalx-full-altgr-intl]
+Description="键盘 - 英语(美国) - 英语(Carpalx,完全优化,国际,带 AltGr 死键)"
+Language=en
+Label="us (carpalx-full-altgr-intl)"
+
+[keyboard-us-3l]
+Description="键盘 - 英语(美国) - 英语(3l)"
+Language=en
+Label="us (3l)"
+
+[keyboard-us-3l-cros]
+Description="键盘 - 英语(美国) - 英语(3l,Chromebook)"
+Language=en
+Label="us (3l-cros)"
+
+[keyboard-us-3l-emacs]
+Description="键盘 - 英语(美国) - 英语(3l,emacs)"
+Language=en
+Label="us (3l-emacs)"
+
+[keyboard-us-workman-p]
+Description="键盘 - 英语(美国) - 英语(Workman-P)"
+Language=en
+Label=workman-p
+
+[keyboard-us-scn]
+Description="键盘 - 英语(美国) - 西西里语(美式键盘)"
+Language=en
+Label="us (scn)"
+
+[keyboard-us-altgr-weur]
+Description="键盘 - 英语(美国) - 英语(西欧 AltGr 死键)"
+Language=en
+Label="us (altgr-weur)"
+
+[keyboard-ge]
+Description="键盘 - 格鲁吉亚语"
+Language=ka
+Label=ka
+
+[keyboard-ge-ergonomic]
+Description="键盘 - 格鲁吉亚语 - 格鲁吉亚语(人体工学)"
+Language=ka
+Label="ge (ergonomic)"
+
+[keyboard-ge-mess]
+Description="键盘 - 格鲁吉亚语 - 格鲁吉亚语(MESS)"
+Language=ka
+Label="ge (mess)"
+
+[keyboard-ge-os]
+Description="键盘 - 格鲁吉亚语 - 奥塞梯语(格鲁吉亚)"
+Language=os
+Label="ge (os)"
+
+[keyboard-ge-ru]
+Description="键盘 - 格鲁吉亚语 - 俄语(格鲁吉亚)"
+Language=ru
+Label=ru
+
+[keyboard-es]
+Description="键盘 - 西班牙语"
+Language=es
+Label=es
+
+[keyboard-es-nodeadkeys]
+Description="键盘 - 西班牙语 - 西班牙语(无死键)"
+Language=es
+Label="es (nodeadkeys)"
+
+[keyboard-es-deadtilde]
+Description="键盘 - 西班牙语 - 西班牙语(波浪号为死键)"
+Language=es
+Label="es (deadtilde)"
+
+[keyboard-es-winkeys]
+Description="键盘 - 西班牙语 - 西班牙语(Windows)"
+Language=es
+Label="es (winkeys)"
+
+[keyboard-es-dvorak]
+Description="键盘 - 西班牙语 - 西班牙语(Dvorak)"
+Language=es
+Label="es (dvorak)"
+
+[keyboard-es-ast]
+Description="键盘 - 西班牙语 - 阿斯图里亚斯语(西班牙,带底部加点的 H 和 L)"
+Language=ast
+Label=ast
+
+[keyboard-es-cat]
+Description="键盘 - 西班牙语 - 加泰罗尼亚语(西班牙,带中间加点的 L)"
+Language=ca
+Label="ca (cat)"
+
+[keyboard-es-sun_type6]
+Description="键盘 - 西班牙语 - 西班牙语(Sun Type 6/7)"
+Language=es
+Label="es (sun_type6)"
+
+[keyboard-ee]
+Description="键盘 - 爱沙尼亚语"
+Language=et
+Label=et
+
+[keyboard-ee-nodeadkeys]
+Description="键盘 - 爱沙尼亚语 - 爱沙尼亚语(无死键)"
+Language=et
+Label="ee (nodeadkeys)"
+
+[keyboard-ee-dvorak]
+Description="键盘 - 爱沙尼亚语 - 爱沙尼亚语(Dvorak)"
+Language=et
+Label="ee (dvorak)"
+
+[keyboard-ee-us]
+Description="键盘 - 爱沙尼亚语 - 爱沙尼亚语(美国)"
+Language=et
+Label="ee (us)"
+
+[keyboard-ee-sun_type6]
+Description="键盘 - 爱沙尼亚语 - 爱沙尼亚语(Sun Type 6/7)"
+Language=et
+Label="ee (sun_type6)"
+
+[keyboard-bd]
+Description="键盘 - 孟加拉语"
+Language=bn
+Label=bn
+
+[keyboard-bd-probhat]
+Description="键盘 - 孟加拉语 - 孟加拉语(Probhat)"
+Language=bn
+Label="bd (probhat)"
+
+[keyboard-ph]
+Description="键盘 - 菲律宾语"
+Language=en
+Label=ph
+
+[keyboard-ph-qwerty-bay]
+Description="键盘 - 菲律宾语 - 菲律宾语(QWERTY,Baybayin)"
+Language=bik
+Label="ph (qwerty-bay)"
+
+[keyboard-ph-capewell-dvorak]
+Description="键盘 - 菲律宾语 - 菲律宾语(Capewell-Dvorak,拉丁)"
+Language=en
+Label="ph (capewell-dvorak)"
+
+[keyboard-ph-capewell-dvorak-bay]
+Description="键盘 - 菲律宾语 - 菲律宾语(Capewell-Dvorak,Baybayin)"
+Language=bik
+Label="ph (capewell-dvorak-bay)"
+
+[keyboard-ph-capewell-qwerf2k6]
+Description="键盘 - 菲律宾语 - 菲律宾语(Capewell-QWERF 2006,拉丁)"
+Language=en
+Label="ph (capewell-qwerf2k6)"
+
+[keyboard-ph-capewell-qwerf2k6-bay]
+Description="键盘 - 菲律宾语 - 菲律宾语(Capewell-QWERF 2006,Baybayin)"
+Language=bik
+Label="ph (capewell-qwerf2k6-bay)"
+
+[keyboard-ph-colemak]
+Description="键盘 - 菲律宾语 - 菲律宾语(Colemak,拉丁)"
+Language=en
+Label="ph (colemak)"
+
+[keyboard-ph-colemak-bay]
+Description="键盘 - 菲律宾语 - 菲律宾语(Colemak,Baybayin)"
+Language=bik
+Label="ph (colemak-bay)"
+
+[keyboard-ph-dvorak]
+Description="键盘 - 菲律宾语 - 菲律宾语(Dvorak,拉丁)"
+Language=en
+Label="ph (dvorak)"
+
+[keyboard-ph-dvorak-bay]
+Description="键盘 - 菲律宾语 - 菲律宾语(Dvorak,Baybayin)"
+Language=bik
+Label="ph (dvorak-bay)"
+
+[keyboard-uz]
+Description="键盘 - 乌兹别克语"
+Language=uz
+Label=uz
+
+[keyboard-uz-latin]
+Description="键盘 - 乌兹别克语 - 乌兹别克语(拉丁)"
+Language=uz
+Label="uz (latin)"
+
+[keyboard-lt]
+Description="键盘 - 立陶宛语"
+Language=lt
+Label=lt
+
+[keyboard-lt-std]
+Description="键盘 - 立陶宛语 - 立陶宛语(标准)"
+Language=lt
+Label="lt (std)"
+
+[keyboard-lt-us]
+Description="键盘 - 立陶宛语 - 立陶宛语(美国)"
+Language=lt
+Label="lt (us)"
+
+[keyboard-lt-ibm]
+Description="键盘 - 立陶宛语 - 立陶宛语(IBM)"
+Language=lt
+Label="lt (ibm)"
+
+[keyboard-lt-lekp]
+Description="键盘 - 立陶宛语 - 立陶宛语(LEKP)"
+Language=lt
+Label="lt (lekp)"
+
+[keyboard-lt-lekpa]
+Description="键盘 - 立陶宛语 - 立陶宛语(LEKPa)"
+Language=lt
+Label="lt (lekpa)"
+
+[keyboard-lt-ratise]
+Description="键盘 - 立陶宛语 - 立陶宛语(Ratise)"
+Language=lt
+Label="lt (ratise)"
+
+[keyboard-lt-sgs]
+Description="键盘 - 立陶宛语 - 萨莫吉提亚语"
+Language=sgs
+Label="lt (sgs)"
+
+[keyboard-lt-us_dvorak]
+Description="键盘 - 立陶宛语 - 立陶宛语(Dvorak)"
+Language=lt
+Label="lt (us_dvorak)"
+
+[keyboard-lt-sun_type6]
+Description="键盘 - 立陶宛语 - 立陶宛语(Sun Type 6/7)"
+Language=lt
+Label="lt (sun_type6)"
+
+[keyboard-fi]
+Description="键盘 - 芬兰语"
+Language=fi
+Label=fi
+
+[keyboard-fi-winkeys]
+Description="键盘 - 芬兰语 - 芬兰语(Windows)"
+Language=fi
+Label="fi (winkeys)"
+
+[keyboard-fi-classic]
+Description="键盘 - 芬兰语 - 芬兰语(经典)"
+Language=fi
+Label="fi (classic)"
+
+[keyboard-fi-nodeadkeys]
+Description="键盘 - 芬兰语 - 芬兰语(经典,无死键)"
+Language=fi
+Label="fi (nodeadkeys)"
+
+[keyboard-fi-mac]
+Description="键盘 - 芬兰语 - 芬兰语(Macintosh)"
+Language=fi
+Label="fi (mac)"
+
+[keyboard-fi-smi]
+Description="键盘 - 芬兰语 - 北萨米语(芬兰)"
+Language=se
+Label="fi (smi)"
+
+[keyboard-fi-sun_type6]
+Description="键盘 - 芬兰语 - 芬兰语(Sun Type 6/7)"
+Language=fi
+Label="fi (sun_type6)"
+
+[keyboard-fi-das]
+Description="键盘 - 芬兰语 - 芬兰语(DAS)"
+Language=fi
+Label="fi (das)"
+
+[keyboard-fi-fidvorak]
+Description="键盘 - 芬兰语 - 芬兰语(Dvorak)"
+Language=fi
+Label="fi (fidvorak)"
+
+[keyboard-cn]
+Description="键盘 - 汉语"
+Language=zh
+Label=zh
+
+[keyboard-cn-altgr-pinyin]
+Description="键盘 - 汉语 - 汉语拼音字母(带 AltGr 死键)"
+Language=zh
+Label="cn (altgr-pinyin)"
+
+[keyboard-cn-mon_trad]
+Description="键盘 - 汉语 - 蒙古语(Bichig)"
+Language=mvf
+Label="cn (mon_trad)"
+
+[keyboard-cn-mon_trad_todo]
+Description="键盘 - 汉语 - 蒙古语(Todo)"
+Language=mvf
+Label="cn (mon_trad_todo)"
+
+[keyboard-cn-mon_trad_xibe]
+Description="键盘 - 汉语 - 蒙古语(Xibe)"
+Language=sjo
+Label="cn (mon_trad_xibe)"
+
+[keyboard-cn-mon_trad_manchu]
+Description="键盘 - 汉语 - 蒙古语(Manchu)"
+Language=mnc
+Label="cn (mon_trad_manchu)"
+
+[keyboard-cn-mon_trad_galik]
+Description="键盘 - 汉语 - 蒙古语(Galik)"
+Language=mvf
+Label="cn (mon_trad_galik)"
+
+[keyboard-cn-mon_todo_galik]
+Description="键盘 - 汉语 - 蒙古语(Todo Galik)"
+Language=mvf
+Label="cn (mon_todo_galik)"
+
+[keyboard-cn-mon_manchu_galik]
+Description="键盘 - 汉语 - 蒙古语(Manchu Galik)"
+Language=mnc
+Label="cn (mon_manchu_galik)"
+
+[keyboard-cn-tib]
+Description="键盘 - 汉语 - 藏语"
+Language=bo
+Label="cn (tib)"
+
+[keyboard-cn-tib_asciinum]
+Description="键盘 - 汉语 - 藏语(带 ASCII 数字)"
+Language=bo
+Label="cn (tib_asciinum)"
+
+[keyboard-cn-ug]
+Description="键盘 - 汉语 - 维吾尔语"
+Language=ug
+Label=ug
+
+[keyboard-ca]
+Description="键盘 - 法语(加拿大)"
+Language=fr
+Label=fr
+
+[keyboard-ca-fr-dvorak]
+Description="键盘 - 法语(加拿大) - 法语(加拿大,Dvorak)"
+Language=fr
+Label="fr (fr-dvorak)"
+
+[keyboard-ca-fr-legacy]
+Description="键盘 - 法语(加拿大) - 法语(加拿大,传统)"
+Language=fr
+Label="fr (fr-legacy)"
+
+[keyboard-ca-multix]
+Description="键盘 - 法语(加拿大) - 加拿大(CSA)"
+Language=fr
+Label="ca (multix)"
+
+[keyboard-ca-eng]
+Description="键盘 - 法语(加拿大) - 英语(加拿大)"
+Language=en
+Label="en (eng)"
+
+[keyboard-ca-ike]
+Description="键盘 - 法语(加拿大) - 因纽特语"
+Language=iu
+Label=ike
+
+[keyboard-ca-kut]
+Description="键盘 - 法语(加拿大) - Kutenai 语"
+Language=fr
+Label=kut
+
+[keyboard-ca-shs]
+Description="键盘 - 法语(加拿大) - 苏斯瓦语"
+Language=fr
+Label=shs
+
+[keyboard-ca-sun_type6]
+Description="键盘 - 法语(加拿大) - 多语言(加拿大,Sun Type 6/7)"
+Language=fr
+Label="ca (sun_type6)"
+
+[keyboard-gh]
+Description="键盘 - 英语(加纳)"
+Language=en
+Label=en
+
+[keyboard-gh-generic]
+Description="键盘 - 英语(加纳) - 英语(加纳,多语言)"
+Language=en
+Label="gh (generic)"
+
+[keyboard-gh-gillbt]
+Description="键盘 - 英语(加纳) - 英语(加纳,GILLBT)"
+Language=en
+Label="gh (gillbt)"
+
+[keyboard-gh-akan]
+Description="键盘 - 英语(加纳) - 阿肯语"
+Language=ak
+Label="ak (akan)"
+
+[keyboard-gh-avn]
+Description="键盘 - 英语(加纳) - Avatime"
+Language=avn
+Label=avn
+
+[keyboard-gh-ewe]
+Description="键盘 - 英语(加纳) - 埃维语"
+Language=ee
+Label="ee (ewe)"
+
+[keyboard-gh-fula]
+Description="键盘 - 英语(加纳) - 富拉语"
+Language=ff
+Label="ff (fula)"
+
+[keyboard-gh-ga]
+Description="键盘 - 英语(加纳) - Ga 语"
+Language=gaa
+Label="gaa (ga)"
+
+[keyboard-gh-hausa]
+Description="键盘 - 英语(加纳) - 豪萨语(加纳)"
+Language=ha
+Label="ha (hausa)"
+
+[keyboard-fr]
+Description="键盘 - 法语"
+Language=fr
+Label=fr
+
+[keyboard-fr-nodeadkeys]
+Description="键盘 - 法语 - 法语(无死键)"
+Language=fr
+Label="fr (nodeadkeys)"
+
+[keyboard-fr-oss]
+Description="键盘 - 法语 - 法语(替代)"
+Language=fr
+Label="fr (oss)"
+
+[keyboard-fr-oss_nodeadkeys]
+Description="键盘 - 法语 - 法语(替代,无死键)"
+Language=fr
+Label="fr (oss_nodeadkeys)"
+
+[keyboard-fr-oss_latin9]
+Description="键盘 - 法语 - 法语(替代,只包含拉丁-9 字符)"
+Language=fr
+Label="fr (oss_latin9)"
+
+[keyboard-fr-latin9]
+Description="键盘 - 法语 - 法语(传统,替代)"
+Language=fr
+Label="fr (latin9)"
+
+[keyboard-fr-latin9_nodeadkeys]
+Description="键盘 - 法语 - 法语(传统,替代,无死键)"
+Language=fr
+Label="fr (latin9_nodeadkeys)"
+
+[keyboard-fr-azerty]
+Description="键盘 - 法语 - 法语(AZERTY)"
+Language=fr
+Label="fr (azerty)"
+
+[keyboard-fr-afnor]
+Description="键盘 - 法语 - 法语(AZERTY,AFNOR)"
+Language=fr
+Label="fr (afnor)"
+
+[keyboard-fr-bepo]
+Description="键盘 - 法语 - 法语(BEPO)"
+Language=fr
+Label="fr (bepo)"
+
+[keyboard-fr-bepo_latin9]
+Description="键盘 - 法语 - 法语(BEPO,只包含拉丁-9 字符)"
+Language=fr
+Label="fr (bepo_latin9)"
+
+[keyboard-fr-bepo_afnor]
+Description="键盘 - 法语 - 法语(BEPO,AFNOR)"
+Language=fr
+Label="fr (bepo_afnor)"
+
+[keyboard-fr-dvorak]
+Description="键盘 - 法语 - 法语(Dvorak)"
+Language=fr
+Label="fr (dvorak)"
+
+[keyboard-fr-ergol]
+Description="键盘 - 法语 - 法语(Ergo-L)"
+Language=fr
+Label="fr (ergol)"
+
+[keyboard-fr-ergol_iso]
+Description="键盘 - 法语 - 法语(Ergo-L,ISO 变种)"
+Language=fr
+Label="fr (ergol_iso)"
+
+[keyboard-fr-mac]
+Description="键盘 - 法语 - 法语(Macintosh)"
+Language=fr
+Label="fr (mac)"
+
+[keyboard-fr-us]
+Description="键盘 - 法语 - 法语(美国)"
+Language=fr
+Label="fr (us)"
+
+[keyboard-fr-bre]
+Description="键盘 - 法语 - 布列塔尼语(法国)"
+Language=br
+Label="fr (bre)"
+
+[keyboard-fr-oci]
+Description="键盘 - 法语 - 奥克语"
+Language=oc
+Label="fr (oci)"
+
+[keyboard-fr-geo]
+Description="键盘 - 法语 - 格鲁吉亚语(法国,AZERTY Tskapo)"
+Language=ka
+Label="fr (geo)"
+
+[keyboard-fr-sun_type6]
+Description="键盘 - 法语 - 法语(Sun Type 6/7)"
+Language=fr
+Label="fr (sun_type6)"
+
+[keyboard-fr-us-alt]
+Description="键盘 - 法语 - 法语(美国,带死键,替代)"
+Language=fr
+Label="fr (us-alt)"
+
+[keyboard-fr-us-azerty]
+Description="键盘 - 法语 - 法语(美国,AZERTY)"
+Language=fr
+Label="fr (us-azerty)"
+
+[keyboard-eg]
+Description="键盘 - 阿拉伯语(埃及)"
+Language=ar
+Label=ar
+
+[keyboard-eg-cop]
+Description="键盘 - 阿拉伯语(埃及) - 科普特语"
+Language=cop
+Label=cop
+
+[keyboard-cd]
+Description="键盘 - 法语(刚果民主共和国)"
+Language=fr
+Label=fr
+
+[keyboard-tg]
+Description="键盘 - 法语(多哥)"
+Language=fr
+Label=fr
+
+[keyboard-kz]
+Description="键盘 - 哈萨克语"
+Language=kk
+Label=kk
+
+[keyboard-kz-kazrus]
+Description="键盘 - 哈萨克语 - 哈萨克语(带俄语)"
+Language=kk
+Label="kz (kazrus)"
+
+[keyboard-kz-ext]
+Description="键盘 - 哈萨克语 - 哈萨克语(扩展)"
+Language=kk
+Label="kz (ext)"
+
+[keyboard-kz-latin]
+Description="键盘 - 哈萨克语 - 哈萨克语(拉丁)"
+Language=kk
+Label="kz (latin)"
+
+[keyboard-kz-ruskaz]
+Description="键盘 - 哈萨克语 - 俄语(哈萨克斯坦,带哈萨克语)"
+Language=kk
+Label="ru (ruskaz)"
+
+[keyboard-ch]
+Description="键盘 - 德语(瑞士)"
+Language=de
+Label=de
+
+[keyboard-ch-de_nodeadkeys]
+Description="键盘 - 德语(瑞士) - 德语(瑞士,无死键)"
+Language=de
+Label="de (de_nodeadkeys)"
+
+[keyboard-ch-de_mac]
+Description="键盘 - 德语(瑞士) - 德语(瑞士,Macintosh)"
+Language=de
+Label="de (de_mac)"
+
+[keyboard-ch-legacy]
+Description="键盘 - 德语(瑞士) - 德语(瑞士,传统)"
+Language=de
+Label="ch (legacy)"
+
+[keyboard-ch-fr]
+Description="键盘 - 德语(瑞士) - 法语(瑞士)"
+Language=fr
+Label=fr
+
+[keyboard-ch-fr_nodeadkeys]
+Description="键盘 - 德语(瑞士) - 法语(瑞士,无死键)"
+Language=fr
+Label="fr (fr_nodeadkeys)"
+
+[keyboard-ch-fr_mac]
+Description="键盘 - 德语(瑞士) - 法语(瑞士,Macintosh)"
+Language=fr
+Label="fr (fr_mac)"
+
+[keyboard-ch-sun_type6_de]
+Description="键盘 - 德语(瑞士) - 德语(瑞士,Sun Type 6/7)"
+Language=de
+Label="ch (sun_type6_de)"
+
+[keyboard-ch-sun_type6_fr]
+Description="键盘 - 德语(瑞士) - 法语(瑞士,Sun Type 6/7)"
+Language=de
+Label="ch (sun_type6_fr)"
+
+[keyboard-gr]
+Description="键盘 - 希腊语"
+Language=el
+Label=gr
+
+[keyboard-gr-simple]
+Description="键盘 - 希腊语 - 希腊语(简易)"
+Language=el
+Label="gr (simple)"
+
+[keyboard-gr-nodeadkeys]
+Description="键盘 - 希腊语 - 希腊语(无死键)"
+Language=el
+Label="gr (nodeadkeys)"
+
+[keyboard-gr-polytonic]
+Description="键盘 - 希腊语 - 希腊语(变音符号)"
+Language=el
+Label="gr (polytonic)"
+
+[keyboard-gr-sun_type6]
+Description="键盘 - 希腊语 - 希腊语(Sun Type 6/7)"
+Language=el
+Label="gr (sun_type6)"
+
+[keyboard-gr-colemak]
+Description="键盘 - 希腊语 - 希腊语(Colemak)"
+Language=el
+Label="gr (colemak)"
+
+[keyboard-tr]
+Description="键盘 - 土耳其语"
+Language=tr
+Label=tr
+
+[keyboard-tr-f]
+Description="键盘 - 土耳其语 - 土耳其语(F)"
+Language=tr
+Label="tr (f)"
+
+[keyboard-tr-e]
+Description="键盘 - 土耳其语 - 土耳其语(E)"
+Language=tr
+Label="tr (e)"
+
+[keyboard-tr-alt]
+Description="键盘 - 土耳其语 - 土耳其语(Alt-Q)"
+Language=tr
+Label="tr (alt)"
+
+[keyboard-tr-intl]
+Description="键盘 - 土耳其语 - 土耳其语(国际,带死键)"
+Language=tr
+Label="tr (intl)"
+
+[keyboard-tr-ku]
+Description="键盘 - 土耳其语 - 库尔德语(土耳其,拉丁 Q)"
+Language=ku
+Label=ku
+
+[keyboard-tr-ku_f]
+Description="键盘 - 土耳其语 - 库尔德语(土耳其,F)"
+Language=ku
+Label="ku (ku_f)"
+
+[keyboard-tr-ku_alt]
+Description="键盘 - 土耳其语 - 库尔德语(土耳其,拉丁 Alt-Q)"
+Language=ku
+Label="ku (ku_alt)"
+
+[keyboard-tr-sun_type6]
+Description="键盘 - 土耳其语 - 土耳其语(Sun Type 6/7)"
+Language=tr
+Label="tr (sun_type6)"
+
+[keyboard-tr-us]
+Description="键盘 - 土耳其语 - 土耳其语(交换 i 和 ı)"
+Language=tr
+Label="tr (us)"
+
+[keyboard-tr-otk]
+Description="键盘 - 土耳其语 - 古代突厥语"
+Language=tr
+Label="tr (otk)"
+
+[keyboard-tr-otkf]
+Description="键盘 - 土耳其语 - 古代突厥语(F)"
+Language=tr
+Label="tr (otkf)"
+
+[keyboard-tr-ot]
+Description="键盘 - 土耳其语 - 奥斯曼土耳其语(Q)"
+Language=tr
+Label="tr (ot)"
+
+[keyboard-tr-otf]
+Description="键盘 - 土耳其语 - 奥斯曼土耳其语(F)"
+Language=tr
+Label="tr (otf)"
+
+[keyboard-il]
+Description="键盘 - 希伯来语"
+Language=he
+Label=he
+
+[keyboard-il-si2]
+Description="键盘 - 希伯来语 - 希伯来语(SI-1452-2)"
+Language=he
+Label="il (si2)"
+
+[keyboard-il-lyx]
+Description="键盘 - 希伯来语 - 希伯来语(lyx)"
+Language=he
+Label="il (lyx)"
+
+[keyboard-il-phonetic]
+Description="键盘 - 希伯来语 - 希伯来语(语音助记)"
+Language=he
+Label="il (phonetic)"
+
+[keyboard-il-biblical]
+Description="键盘 - 希伯来语 - 希伯来语(圣经,Tiro)"
+Language=he
+Label="il (biblical)"
+
+[keyboard-il-biblicalSIL]
+Description="键盘 - 希伯来语 - 希伯来语(Biblical,SIL 语音助记)"
+Language=he
+Label="il (biblicalSIL)"
+
+[keyboard-de]
+Description="键盘 - 德语"
+Language=de
+Label=de
+
+[keyboard-de-deadacute]
+Description="键盘 - 德语 - 德语(尖音符号为死键)"
+Language=de
+Label="de (deadacute)"
+
+[keyboard-de-deadgraveacute]
+Description="键盘 - 德语 - 德语(重音符号和尖音符号为死键)"
+Language=de
+Label="de (deadgraveacute)"
+
+[keyboard-de-deadtilde]
+Description="键盘 - 德语 - 德语(波浪号为死键)"
+Language=de
+Label="de (deadtilde)"
+
+[keyboard-de-nodeadkeys]
+Description="键盘 - 德语 - 德语(无死键)"
+Language=de
+Label="de (nodeadkeys)"
+
+[keyboard-de-e1]
+Description="键盘 - 德语 - 德语(E1)"
+Language=de
+Label="de (e1)"
+
+[keyboard-de-e2]
+Description="键盘 - 德语 - 德语(E2)"
+Language=de
+Label="de (e2)"
+
+[keyboard-de-T3]
+Description="键盘 - 德语 - 德语(T3)"
+Language=de
+Label="de (T3)"
+
+[keyboard-de-us]
+Description="键盘 - 德语 - 德语(美国)"
+Language=de
+Label="de (us)"
+
+[keyboard-de-dvorak]
+Description="键盘 - 德语 - 德语(Dvorak)"
+Language=de
+Label="de (dvorak)"
+
+[keyboard-de-mac]
+Description="键盘 - 德语 - 德语(Macintosh)"
+Language=de
+Label="de (mac)"
+
+[keyboard-de-mac_nodeadkeys]
+Description="键盘 - 德语 - 德语(Macintosh,无死键)"
+Language=de
+Label="de (mac_nodeadkeys)"
+
+[keyboard-de-neo]
+Description="键盘 - 德语 - 德语(Neo 2)"
+Language=de
+Label="de (neo)"
+
+[keyboard-de-qwerty]
+Description="键盘 - 德语 - 德语(QWERTY)"
+Language=de
+Label="de (qwerty)"
+
+[keyboard-de-dsb]
+Description="键盘 - 德语 - 下索布语"
+Language=dsb
+Label="de (dsb)"
+
+[keyboard-de-dsb_qwertz]
+Description="键盘 - 德语 - 下索布语(QWERTZ)"
+Language=dsb
+Label="de (dsb_qwertz)"
+
+[keyboard-de-ro]
+Description="键盘 - 德语 - 罗马尼亚语(德国)"
+Language=ro
+Label="de (ro)"
+
+[keyboard-de-ro_nodeadkeys]
+Description="键盘 - 德语 - 罗马尼亚语(德国,无死键)"
+Language=ro
+Label="de (ro_nodeadkeys)"
+
+[keyboard-de-ru]
+Description="键盘 - 德语 - 俄语(德国,语音助记)"
+Language=ru
+Label=ru
+
+[keyboard-de-tr]
+Description="键盘 - 德语 - 土耳其语(德国)"
+Language=tr
+Label="de (tr)"
+
+[keyboard-de-hu]
+Description="键盘 - 德语 - 德语(带匈牙利字母,无死键)"
+Language=de
+Label="de (hu)"
+
+[keyboard-de-pl]
+Description="键盘 - 德语 - 波兰语(德国,无死键)"
+Language=de
+Label="de (pl)"
+
+[keyboard-de-sun_type6]
+Description="键盘 - 德语 - 德语(Sun Type 6/7)"
+Language=de
+Label="de (sun_type6)"
+
+[keyboard-de-adnw]
+Description="键盘 - 德语 - 德语(Aus der Neo-Welt)"
+Language=de
+Label="de (adnw)"
+
+[keyboard-de-koy]
+Description="键盘 - 德语 - 德语(KOY)"
+Language=de
+Label="de (koy)"
+
+[keyboard-de-bone]
+Description="键盘 - 德语 - 德语(Bone)"
+Language=de
+Label="de (bone)"
+
+[keyboard-de-bone_eszett_home]
+Description="键盘 - 德语 - 德语(Bone,eszett 在中间行)"
+Language=de
+Label="de (bone_eszett_home)"
+
+[keyboard-de-neo_qwertz]
+Description="键盘 - 德语 - 德语(Neo,QWERTZ)"
+Language=de
+Label="de (neo_qwertz)"
+
+[keyboard-de-neo_qwerty]
+Description="键盘 - 德语 - 德语(Neo,QWERTY)"
+Language=de
+Label="de (neo_qwerty)"
+
+[keyboard-de-noted]
+Description="键盘 - 德语 - 德语(Noted)"
+Language=de
+Label="de (noted)"
+
+[keyboard-de-ru-recom]
+Description="键盘 - 德语 - 俄语(德国,推荐)"
+Language=ru
+Label="ru (ru-recom)"
+
+[keyboard-de-ru-translit]
+Description="键盘 - 德语 - 俄语(德国,转写)"
+Language=ru
+Label="ru (ru-translit)"
+
+[keyboard-id]
+Description="键盘 - 印尼语(拉丁)"
+Language=id
+Label=id
+
+[keyboard-id-melayu-phonetic]
+Description="键盘 - 印尼语(拉丁) - 印尼语(Arab Melayu,语音助记)"
+Language=id
+Label="id (melayu-phonetic)"
+
+[keyboard-id-melayu-phoneticx]
+Description="键盘 - 印尼语(拉丁) - 印尼语(Arab Melayu,扩展语音助记)"
+Language=id
+Label="id (melayu-phoneticx)"
+
+[keyboard-id-pegon-phonetic]
+Description="键盘 - 印尼语(拉丁) - 印尼语(Arab Pegon,语音助记)"
+Language=id
+Label="id (pegon-phonetic)"
+
+[keyboard-id-javanese]
+Description="键盘 - 印尼语(拉丁) - 爪哇语"
+Language=id
+Label="id (javanese)"
+
+[keyboard-sn]
+Description="键盘 - 沃洛夫语"
+Language=wo
+Label=wo
+
+[keyboard-az]
+Description="键盘 - 阿塞拜疆语"
+Language=az
+Label=az
+
+[keyboard-az-cyrillic]
+Description="键盘 - 阿塞拜疆语 - 阿塞拜疆语(西里尔)"
+Language=az
+Label="az (cyrillic)"
+
+[keyboard-kh]
+Description="键盘 - 高棉语(柬埔寨)"
+Language=km
+Label=km
+
+[keyboard-hu]
+Description="键盘 - 匈牙利语"
+Language=hu
+Label=hu
+
+[keyboard-hu-standard]
+Description="键盘 - 匈牙利语 - 匈牙利语(标准)"
+Language=hu
+Label="hu (standard)"
+
+[keyboard-hu-nodeadkeys]
+Description="键盘 - 匈牙利语 - 匈牙利语(无死键)"
+Language=hu
+Label="hu (nodeadkeys)"
+
+[keyboard-hu-qwerty]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY)"
+Language=hu
+Label="hu (qwerty)"
+
+[keyboard-hu-101_qwertz_comma_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,101 键,逗号,死键)"
+Language=hu
+Label="hu (101_qwertz_comma_dead)"
+
+[keyboard-hu-101_qwertz_comma_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,101 键,逗号,无死键)"
+Language=hu
+Label="hu (101_qwertz_comma_nodead)"
+
+[keyboard-hu-101_qwertz_dot_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,101 键,点,死键)"
+Language=hu
+Label="hu (101_qwertz_dot_dead)"
+
+[keyboard-hu-101_qwertz_dot_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,101 键,点,无死键)"
+Language=hu
+Label="hu (101_qwertz_dot_nodead)"
+
+[keyboard-hu-101_qwerty_comma_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,101 键,逗号,死键)"
+Language=hu
+Label="hu (101_qwerty_comma_dead)"
+
+[keyboard-hu-101_qwerty_comma_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,101 键,逗号,无死键)"
+Language=hu
+Label="hu (101_qwerty_comma_nodead)"
+
+[keyboard-hu-101_qwerty_dot_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,101 键,点,死键)"
+Language=hu
+Label="hu (101_qwerty_dot_dead)"
+
+[keyboard-hu-101_qwerty_dot_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,101 键,点,无死键)"
+Language=hu
+Label="hu (101_qwerty_dot_nodead)"
+
+[keyboard-hu-102_qwertz_comma_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,102 键,逗号,死键)"
+Language=hu
+Label="hu (102_qwertz_comma_dead)"
+
+[keyboard-hu-102_qwertz_comma_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,102 键,逗号,无死键)"
+Language=hu
+Label="hu (102_qwertz_comma_nodead)"
+
+[keyboard-hu-102_qwertz_dot_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,102 键,点,死键)"
+Language=hu
+Label="hu (102_qwertz_dot_dead)"
+
+[keyboard-hu-102_qwertz_dot_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTZ,102 键,点,无死键)"
+Language=hu
+Label="hu (102_qwertz_dot_nodead)"
+
+[keyboard-hu-102_qwerty_comma_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,102 键,逗号,死键)"
+Language=hu
+Label="hu (102_qwerty_comma_dead)"
+
+[keyboard-hu-102_qwerty_comma_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,102 键,逗号,无死键)"
+Language=hu
+Label="hu (102_qwerty_comma_nodead)"
+
+[keyboard-hu-102_qwerty_dot_dead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,102 键,点,死键)"
+Language=hu
+Label="hu (102_qwerty_dot_dead)"
+
+[keyboard-hu-102_qwerty_dot_nodead]
+Description="键盘 - 匈牙利语 - 匈牙利语(QWERTY,102 键,点,无死键)"
+Language=hu
+Label="hu (102_qwerty_dot_nodead)"
+
+[keyboard-hu-oldhunlig]
+Description="键盘 - 匈牙利语 - 古匈牙利语(含连字)"
+Language=hu
+Label="oldhun(lig) (oldhunlig)"
+
+[keyboard-hu-oldhun_sk_sh]
+Description="键盘 - 匈牙利语 - 古匈牙利语(喀尔巴阡高地,S 作为 Sh)"
+Language=hu
+Label="oldhun(SK,Sh) (oldhun_sk_sh)"
+
+[keyboard-hu-oldhun_sk_sz]
+Description="键盘 - 匈牙利语 - 古匈牙利语(喀尔巴阡高地,S 作为 Sz)"
+Language=hu
+Label="oldhun(SK,Sz) (oldhun_sk_sz)"
+
+[keyboard-hu-us]
+Description="键盘 - 匈牙利语 - 匈牙利语(美国)"
+Language=hu
+Label=us
+
+[keyboard-ng]
+Description="键盘 - 英语(尼日利亚)"
+Language=en
+Label=en
+
+[keyboard-ng-hausa]
+Description="键盘 - 英语(尼日利亚) - 豪萨语(尼日利亚)"
+Language=ha
+Label="ha (hausa)"
+
+[keyboard-ng-igbo]
+Description="键盘 - 英语(尼日利亚) - 伊博语"
+Language=ig
+Label="ig (igbo)"
+
+[keyboard-ng-yoruba]
+Description="键盘 - 英语(尼日利亚) - 约鲁巴语"
+Language=yo
+Label="yo (yoruba)"
+
+[keyboard-is]
+Description="键盘 - 冰岛语"
+Language=is
+Label=is
+
+[keyboard-is-mac_legacy]
+Description="键盘 - 冰岛语 - 冰岛语(Macintosh,传统)"
+Language=is
+Label="is (mac_legacy)"
+
+[keyboard-is-mac]
+Description="键盘 - 冰岛语 - 冰岛语(Macintosh)"
+Language=is
+Label="is (mac)"
+
+[keyboard-is-dvorak]
+Description="键盘 - 冰岛语 - 冰岛语(Dvorak)"
+Language=is
+Label="is (dvorak)"
+
+[keyboard-in]
+Description="键盘 - 印度语言"
+Language=hi
+Label=in
+
+[keyboard-in-asm-kagapa]
+Description="键盘 - 印度语言 - 阿萨姆语(KaGaPa,语音助记)"
+Language=as
+Label="as (asm-kagapa)"
+
+[keyboard-in-ben]
+Description="键盘 - 印度语言 - 孟加拉语(印度)"
+Language=bn
+Label="bn (ben)"
+
+[keyboard-in-ben_probhat]
+Description="键盘 - 印度语言 - 孟加拉语(印度,Probhat)"
+Language=bn
+Label="bn (ben_probhat)"
+
+[keyboard-in-ben_baishakhi]
+Description="键盘 - 印度语言 - 孟加拉语(印度,Baishakhi)"
+Language=bn
+Label="in (ben_baishakhi)"
+
+[keyboard-in-ben_bornona]
+Description="键盘 - 印度语言 - 孟加拉语(印度,Bornona)"
+Language=bn
+Label="in (ben_bornona)"
+
+[keyboard-in-ben-kagapa]
+Description="键盘 - 印度语言 - 孟加拉语(印度,KaGaPa,语音助记)"
+Language=bn
+Label="in (ben-kagapa)"
+
+[keyboard-in-ben_gitanjali]
+Description="键盘 - 印度语言 - 孟加拉语(印度,Gitanjali)"
+Language=bn
+Label="in (ben_gitanjali)"
+
+[keyboard-in-ben_inscript]
+Description="键盘 - 印度语言 - 孟加拉语(印度,Baishakhi InScript)"
+Language=bn
+Label="in (ben_inscript)"
+
+[keyboard-in-eng]
+Description="键盘 - 印度语言 - 英语(印度,带卢比符号)"
+Language=en
+Label="en (eng)"
+
+[keyboard-in-guj]
+Description="键盘 - 印度语言 - 古吉拉特语"
+Language=gu
+Label="gu (guj)"
+
+[keyboard-in-guj-kagapa]
+Description="键盘 - 印度语言 - 古吉拉特语(KaGaPa,语音助记)"
+Language=gu
+Label="gu (guj-kagapa)"
+
+[keyboard-in-bolnagri]
+Description="键盘 - 印度语言 - 印地语(Bolnagri)"
+Language=hi
+Label="hi (bolnagri)"
+
+[keyboard-in-hin-wx]
+Description="键盘 - 印度语言 - 印地语(Wx)"
+Language=hi
+Label="hi (hin-wx)"
+
+[keyboard-in-hin-kagapa]
+Description="键盘 - 印度语言 - 印地语(KaGaPa,语音助记)"
+Language=hi
+Label="hi (hin-kagapa)"
+
+[keyboard-in-kan]
+Description="键盘 - 印度语言 - 卡纳达语"
+Language=kn
+Label="kn (kan)"
+
+[keyboard-in-kan-kagapa]
+Description="键盘 - 印度语言 - 卡纳达语(KaGaPa,语音助记)"
+Language=kn
+Label="kn (kan-kagapa)"
+
+[keyboard-in-mal]
+Description="键盘 - 印度语言 - 马拉雅拉姆语"
+Language=ml
+Label="ml (mal)"
+
+[keyboard-in-mal_lalitha]
+Description="键盘 - 印度语言 - 马拉雅拉姆语(Lalitha)"
+Language=ml
+Label="ml (mal_lalitha)"
+
+[keyboard-in-mal_enhanced]
+Description="键盘 - 印度语言 - 马拉雅拉姆语(改进的 InScript,带卢比符号)"
+Language=ml
+Label="ml (mal_enhanced)"
+
+[keyboard-in-mal_poorna]
+Description="键盘 - 印度语言 - 马拉雅拉姆语(Poorna,扩展 InScript)"
+Language=ml
+Label="ml (mal_poorna)"
+
+[keyboard-in-mni]
+Description="键盘 - 印度语言 - 曼尼普尔语(梅泰)"
+Language=mni
+Label="in (mni)"
+
+[keyboard-in-mar-kagapa]
+Description="键盘 - 印度语言 - 马拉地语(KaGaPa,语音助记)"
+Language=mr
+Label="mr (mar-kagapa)"
+
+[keyboard-in-marathi]
+Description="键盘 - 印度语言 - 马拉地语(改进的 InScript)"
+Language=mr
+Label="in (marathi)"
+
+[keyboard-in-ori]
+Description="键盘 - 印度语言 - 奥里亚语"
+Language=or
+Label="or (ori)"
+
+[keyboard-in-ori-bolnagri]
+Description="键盘 - 印度语言 - 奥里亚语(Bolnagri)"
+Language=or
+Label="or (ori-bolnagri)"
+
+[keyboard-in-ori-wx]
+Description="键盘 - 印度语言 - 奥里亚语(Wx)"
+Language=or
+Label="or (ori-wx)"
+
+[keyboard-in-guru]
+Description="键盘 - 印度语言 - 旁遮普语(Gurmukhi)"
+Language=pa
+Label="pa (guru)"
+
+[keyboard-in-jhelum]
+Description="键盘 - 印度语言 - 旁遮普语(Gurmukhi Jhelum)"
+Language=pa
+Label="pa (jhelum)"
+
+[keyboard-in-san-kagapa]
+Description="键盘 - 印度语言 - 梵语(KaGaPa,语音助记)"
+Language=sa
+Label="sa (san-kagapa)"
+
+[keyboard-in-sat]
+Description="键盘 - 印度语言 - 桑塔利语(桑塔利文)"
+Language=sat
+Label=sat
+
+[keyboard-in-tamilnet]
+Description="键盘 - 印度语言 - 泰米尔语(TamilNet '99)"
+Language=ta
+Label="ta (tamilnet)"
+
+[keyboard-in-tamilnet_tamilnumbers]
+Description="键盘 - 印度语言 - 泰米尔语(TamilNet '99,带泰米尔数字)"
+Language=ta
+Label="ta (tamilnet_tamilnumbers)"
+
+[keyboard-in-tamilnet_TAB]
+Description="键盘 - 印度语言 - 泰米尔语(TamilNet '99,TAB 编码)"
+Language=ta
+Label="ta (tamilnet_TAB)"
+
+[keyboard-in-tamilnet_TSCII]
+Description="键盘 - 印度语言 - 泰米尔语(TamilNet '99,TSCII 编码)"
+Language=ta
+Label="ta (tamilnet_TSCII)"
+
+[keyboard-in-tam]
+Description="键盘 - 印度语言 - 泰米尔语(InScript,带阿拉伯数字)"
+Language=ta
+Label="ta (tam)"
+
+[keyboard-in-tam_tamilnumbers]
+Description="键盘 - 印度语言 - 泰米尔语(InScript,带泰米尔数字)"
+Language=ta
+Label="ta (tam_tamilnumbers)"
+
+[keyboard-in-tel]
+Description="键盘 - 印度语言 - 泰卢固语"
+Language=te
+Label="te (tel)"
+
+[keyboard-in-tel-kagapa]
+Description="键盘 - 印度语言 - 泰卢固语(KaGaPa,语音助记)"
+Language=te
+Label="te (tel-kagapa)"
+
+[keyboard-in-tel-sarala]
+Description="键盘 - 印度语言 - 泰卢固语(Sarala)"
+Language=te
+Label="te (tel-sarala)"
+
+[keyboard-in-urd-phonetic]
+Description="键盘 - 印度语言 - 乌尔都语(语音助记)"
+Language=ur
+Label="ur (urd-phonetic)"
+
+[keyboard-in-urd-phonetic3]
+Description="键盘 - 印度语言 - 乌尔都语(替代,语音助记)"
+Language=ur
+Label="ur (urd-phonetic3)"
+
+[keyboard-in-urd-winkeys]
+Description="键盘 - 印度语言 - 乌尔都语(Windows)"
+Language=ur
+Label="ur (urd-winkeys)"
+
+[keyboard-in-iipa]
+Description="键盘 - 印度语言 - 印度语支 IPA"
+Language=en
+Label="in (iipa)"
+
+[keyboard-in-modi-kagapa]
+Description="键盘 - 印度语言 - Modi(KaGaPa,语音助记)"
+Language=mr
+Label="mr (modi-kagapa)"
+
+[keyboard-in-san-misc]
+Description="键盘 - 印度语言 - 梵文符号"
+Language=sa
+Label="sas (san-misc)"
+
+[keyboard-in-urd-navees]
+Description="键盘 - 印度语言 - 乌尔都语(Navees)"
+Language=ur
+Label="ur (urd-navees)"
+
+[keyboard-it]
+Description="键盘 - 意大利语"
+Language=it
+Label=it
+
+[keyboard-it-nodeadkeys]
+Description="键盘 - 意大利语 - 意大利语(无死键)"
+Language=it
+Label="it (nodeadkeys)"
+
+[keyboard-it-winkeys]
+Description="键盘 - 意大利语 - 意大利语(Windows)"
+Language=it
+Label="it (winkeys)"
+
+[keyboard-it-mac]
+Description="键盘 - 意大利语 - 意大利语(Macintosh)"
+Language=it
+Label="it (mac)"
+
+[keyboard-it-us]
+Description="键盘 - 意大利语 - 意大利语(美国)"
+Language=it
+Label="it (us)"
+
+[keyboard-it-ibm]
+Description="键盘 - 意大利语 - 意大利语(IBM 142)"
+Language=it
+Label="it (ibm)"
+
+[keyboard-it-fur]
+Description="键盘 - 意大利语 - 弗留利语(意大利)"
+Language=fur
+Label="it (fur)"
+
+[keyboard-it-scn]
+Description="键盘 - 意大利语 - 西西里语"
+Language=it
+Label="it (scn)"
+
+[keyboard-it-geo]
+Description="键盘 - 意大利语 - 格鲁吉亚语(意大利)"
+Language=ka
+Label="it (geo)"
+
+[keyboard-it-sun_type6]
+Description="键盘 - 意大利语 - 意大利语(Sun Type 6/7)"
+Language=it
+Label="it (sun_type6)"
+
+[keyboard-it-lld]
+Description="键盘 - 意大利语 - 拉丁语(意大利语键盘)"
+Language=it
+Label="it_lld (lld)"
+
+[keyboard-it-lldde]
+Description="键盘 - 意大利语 - 拉丁语(德语键盘)"
+Language=de
+Label="de_lld (lldde)"
+
+[keyboard-it-dvorak]
+Description="键盘 - 意大利语 - 意大利语(Dvorak)"
+Language=it
+Label="it (dvorak)"
+
+[keyboard-jp]
+Description="键盘 - 日语"
+Language=ja
+Label=ja
+
+[keyboard-jp-kana]
+Description="键盘 - 日语 - 日语(Kana)"
+Language=ja
+Label="jp (kana)"
+
+[keyboard-jp-OADG109A]
+Description="键盘 - 日语 - 日语(OADG 109A)"
+Language=ja
+Label="jp (OADG109A)"
+
+[keyboard-jp-mac]
+Description="键盘 - 日语 - 日语(Macintosh)"
+Language=ja
+Label="jp (mac)"
+
+[keyboard-jp-dvorak]
+Description="键盘 - 日语 - 日语(Dvorak)"
+Language=ja
+Label="jp (dvorak)"
+
+[keyboard-jp-sun_type6]
+Description="键盘 - 日语 - 日语(Sun Type 6)"
+Language=ja
+Label="jp (sun_type6)"
+
+[keyboard-jp-sun_type7]
+Description="键盘 - 日语 - 日语(Sun Type 7,PC 兼容)"
+Language=ja
+Label="jp (sun_type7)"
+
+[keyboard-jp-sun_type7_suncompat]
+Description="键盘 - 日语 - 日语(Sun Type 7,Sun 兼容)"
+Language=ja
+Label="jp (sun_type7_suncompat)"
+
diff --git a/.config/fcitx5/conf/notifications.conf b/.config/fcitx5/conf/notifications.conf
new file mode 100644
index 0000000..04957ce
--- /dev/null
+++ b/.config/fcitx5/conf/notifications.conf
@@ -0,0 +1,3 @@
+# 隐藏通知
+HiddenNotifications=
+
diff --git a/.config/fcitx5/config b/.config/fcitx5/config
new file mode 100644
index 0000000..16aac96
--- /dev/null
+++ b/.config/fcitx5/config
@@ -0,0 +1,83 @@
+[Hotkey]
+# 按住切换键的修饰键时进行轮换切换
+EnumerateWithTriggerKeys=True
+# 向前切换输入法
+EnumerateForwardKeys=
+# 向后切换输入法
+EnumerateBackwardKeys=
+# 轮换输入法时跳过第一个输入法
+EnumerateSkipFirst=False
+# 触发修饰键快捷键的时限 (毫秒)
+ModifierOnlyKeyTimeout=250
+
+[Hotkey/TriggerKeys]
+0=Super+space
+1=Zenkaku_Hankaku
+2=Hangul
+
+[Hotkey/ActivateKeys]
+0=Hangul_Hanja
+
+[Hotkey/DeactivateKeys]
+0=Hangul_Romaja
+
+[Hotkey/AltTriggerKeys]
+0=Shift_L
+
+[Hotkey/EnumerateGroupForwardKeys]
+0=Super+bracketright
+
+[Hotkey/EnumerateGroupBackwardKeys]
+0=Super+bracketright
+
+[Hotkey/PrevPage]
+0=Up
+
+[Hotkey/NextPage]
+0=Down
+
+[Hotkey/PrevCandidate]
+0=Shift+Tab
+
+[Hotkey/NextCandidate]
+0=Tab
+
+[Hotkey/TogglePreedit]
+0=Control+Alt+P
+
+[Behavior]
+# 默认状态为激活
+ActiveByDefault=False
+# 重新聚焦时重置状态
+resetStateWhenFocusIn=No
+# 共享输入状态
+ShareInputState=No
+# 在程序中显示预编辑文本
+PreeditEnabledByDefault=True
+# 切换输入法时显示输入法信息
+ShowInputMethodInformation=True
+# 在焦点更改时显示输入法信息
+showInputMethodInformationWhenFocusIn=False
+# 显示紧凑的输入法信息
+CompactInputMethodInformation=True
+# 显示第一个输入法的信息
+ShowFirstInputMethodInformation=True
+# 默认页大小
+DefaultPageSize=5
+# 覆盖 XKB 选项
+OverrideXkbOption=False
+# 自定义 XKB 选项
+CustomXkbOption=
+# Force Enabled Addons
+EnabledAddons=
+# Force Disabled Addons
+DisabledAddons=
+# Preload input method to be used by default
+PreloadInputMethod=True
+# 允许在密码框中使用输入法
+AllowInputMethodForPassword=False
+# 输入密码时显示预编辑文本
+ShowPreeditForPassword=False
+# 保存用户数据的时间间隔(以分钟为单位)
+AutoSavePeriod=30
+
diff --git a/.config/fcitx5/profile b/.config/fcitx5/profile
new file mode 100644
index 0000000..d264f5e
--- /dev/null
+++ b/.config/fcitx5/profile
@@ -0,0 +1,23 @@
+[Groups/0]
+# Group Name
+Name=默认
+# Layout
+Default Layout=us
+# Default Input Method
+DefaultIM=rime
+
+[Groups/0/Items/0]
+# Name
+Name=keyboard-us
+# Layout
+Layout=
+
+[Groups/0/Items/1]
+# Name
+Name=rime
+# Layout
+Layout=
+
+[GroupOrder]
+0=默认
+
diff --git a/.config/fcitx5/profile_Uc4jVX b/.config/fcitx5/profile_Uc4jVX
new file mode 100644
index 0000000..d264f5e
--- /dev/null
+++ b/.config/fcitx5/profile_Uc4jVX
@@ -0,0 +1,23 @@
+[Groups/0]
+# Group Name
+Name=默认
+# Layout
+Default Layout=us
+# Default Input Method
+DefaultIM=rime
+
+[Groups/0/Items/0]
+# Name
+Name=keyboard-us
+# Layout
+Layout=
+
+[Groups/0/Items/1]
+# Name
+Name=rime
+# Layout
+Layout=
+
+[GroupOrder]
+0=默认
+
diff --git a/.config/fontconfig/fonts.bak b/.config/fontconfig/fonts.bak
new file mode 100644
index 0000000..4243888
--- /dev/null
+++ b/.config/fontconfig/fonts.bak
@@ -0,0 +1,30 @@
+
+
+
+
+
+ sans-serif
+
+
+ Source Han Sans CN
+ Source Han Sans
+ Twemoji
+
+
+
+
+
+ Source Han Sans CN
+
+
+ SemiLight
+
+
+
+
+ true
+ true
+ hintslight
+ rgb
+
+
diff --git a/.config/fontconfig/fonts.conf b/.config/fontconfig/fonts.conf
new file mode 100644
index 0000000..a6e13fa
--- /dev/null
+++ b/.config/fontconfig/fonts.conf
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ sans-serif
+
+ JetBrainsMono Nerd Font
+ Noto Sans CJK SC
+
+
+
+
+
+ serif
+
+ JetBrainsMono Nerd Font
+ Noto Serif CJK SC
+
+
+
+
+
+ monospace
+
+ JetBrainsMono Nerd Font Mono
+ Noto Sans Mono CJK SC
+
+
+
+
+
+ JetBrainsMono Nerd Font
+
+ Symbols Nerd Font
+ Noto Color Emoji
+
+
+
+ JetBrainsMono Nerd Font Mono
+
+ Symbols Nerd Font Mono
+ Noto Color Emoji
+
+
+
+
+
+ true
+ true
+ hintslight
+ rgb
+
+
diff --git a/.config/gtk-3.0/bookmarks b/.config/gtk-3.0/bookmarks
new file mode 100644
index 0000000..f3e8ed4
--- /dev/null
+++ b/.config/gtk-3.0/bookmarks
@@ -0,0 +1,5 @@
+file:///home/zhenyan121/Videos Videos
+file:///home/zhenyan121/Pictures Pictures
+file:///home/zhenyan121/Music Music
+file:///home/zhenyan121/Downloads Downloads
+file:///home/zhenyan121/Documents Documents
diff --git a/.config/kitty/current-theme.conf b/.config/kitty/current-theme.conf
new file mode 100644
index 0000000..3a0a77c
--- /dev/null
+++ b/.config/kitty/current-theme.conf
@@ -0,0 +1,38 @@
+cursor #e9e2d4
+cursor_text_color #cdc6b4
+
+foreground #e9e2d4
+background #15130b
+selection_foreground #373016
+selection_background #d1c6a1
+url_color #dcc66e
+
+# black
+color8 #969080
+color0 #4c4c4c
+
+# red
+color1 #ac8a8c
+color9 #c49ea0
+# green
+color2 #8aac8b
+color10 #9ec49f
+
+# yellow
+color3 #aca98a
+color11 #c4c19e
+
+# blue
+color4 #dcc66e
+color12 #a39ec4
+
+# magenta
+color5 #aad0b3
+color13 #c5ecce
+# cyan
+color6 #8aacab
+color14 #9ec3c4
+
+# white
+color15 #e7e7e7
+color7 #f0f0f0
diff --git a/.config/kitty/kitty.conf b/.config/kitty/kitty.conf
new file mode 100644
index 0000000..3957315
--- /dev/null
+++ b/.config/kitty/kitty.conf
@@ -0,0 +1,40 @@
+#导入颜色文件
+include themes/frappe.conf
+#设置左右边距
+window_padding_width 5
+#隐藏标题栏
+hide_window_decorations yes
+#背景透明度
+background_opacity 0.8
+#字体
+font_family JetBrainsMono Nerd Font
+bold_font auto
+italic_font auto
+bold_italic_font auto
+#字体大小
+font_size 15
+#不要记住窗口大小(yes no)
+remember_window_size no
+initial_window_width 105c
+initial_window_height 30c
+#关闭窗口时不要询问是否关闭
+confirm_os_window_close 0
+#开启光标拖影
+cursor_trail 1
+cursor_shape block
+shell_integration no-cursor
+
+# 1. 启用 splits 布局(必须放在布局列表的首位或明确指定)
+enabled_layouts splits,stack
+
+# 2. 映射快捷键:在当前窗口下方新建分屏
+map f5 launch --location=hsplit --cwd=current
+
+# 3. 映射快捷键:在当前窗口右侧新建分屏
+map f6 launch --location=vsplit --cwd=current
+
+
+# BEGIN_KITTY_THEME
+# Matugen
+include current-theme.conf
+# END_KITTY_THEME
\ No newline at end of file
diff --git a/.config/kitty/kitty.conf.bak b/.config/kitty/kitty.conf.bak
new file mode 100644
index 0000000..df466f7
--- /dev/null
+++ b/.config/kitty/kitty.conf.bak
@@ -0,0 +1,34 @@
+#导入颜色文件
+include themes/frappe.conf
+#设置左右边距
+window_padding_width 5
+#隐藏标题栏
+hide_window_decorations yes
+#背景透明度
+background_opacity 0.8
+#字体
+font_family JetBrainsMono Nerd Font
+bold_font auto
+italic_font auto
+bold_italic_font auto
+#字体大小
+font_size 15
+#不要记住窗口大小(yes no)
+remember_window_size no
+initial_window_width 105c
+initial_window_height 30c
+#关闭窗口时不要询问是否关闭
+confirm_os_window_close 0
+#开启光标拖影
+cursor_trail 1
+cursor_shape block
+shell_integration no-cursor
+
+# 1. 启用 splits 布局(必须放在布局列表的首位或明确指定)
+enabled_layouts splits,stack
+
+# 2. 映射快捷键:在当前窗口下方新建分屏
+map f5 launch --location=hsplit --cwd=current
+
+# 3. 映射快捷键:在当前窗口右侧新建分屏
+map f6 launch --location=vsplit --cwd=current
diff --git a/.config/kitty/themes/frappe.conf b/.config/kitty/themes/frappe.conf
new file mode 100644
index 0000000..fc47a3b
--- /dev/null
+++ b/.config/kitty/themes/frappe.conf
@@ -0,0 +1,84 @@
+# vim:ft=kitty
+
+## name: Catppuccin Kitty Frappé
+## author: Catppuccin Org
+## license: MIT
+## upstream: https://github.com/catppuccin/kitty/blob/main/themes/frappe.conf
+## blurb: Soothing pastel theme for the high-spirited!
+
+
+
+# The basic colors
+foreground #c6d0f5
+background #303446
+selection_foreground #303446
+selection_background #f2d5cf
+
+# Cursor colors
+cursor #f2d5cf
+cursor_text_color #303446
+
+# Scrollbar colors
+scrollbar_handle_color #949cbb
+scrollbar_track_color #51576d
+
+# URL color when hovering with mouse
+url_color #f2d5cf
+
+# Kitty window border colors
+active_border_color #babbf1
+inactive_border_color #737994
+bell_border_color #e5c890
+
+# OS Window titlebar colors
+wayland_titlebar_color system
+macos_titlebar_color system
+
+# Tab bar colors
+active_tab_foreground #232634
+active_tab_background #ca9ee6
+inactive_tab_foreground #c6d0f5
+inactive_tab_background #292c3c
+tab_bar_background #232634
+
+# Colors for marks (marked text in the terminal)
+mark1_foreground #303446
+mark1_background #babbf1
+mark2_foreground #303446
+mark2_background #ca9ee6
+mark3_foreground #303446
+mark3_background #85c1dc
+
+# The 16 terminal colors
+
+# black
+color0 #51576d
+color8 #626880
+
+# red
+color1 #e78284
+color9 #e78284
+
+# green
+color2 #a6d189
+color10 #a6d189
+
+# yellow
+color3 #e5c890
+color11 #e5c890
+
+# blue
+color4 #8caaee
+color12 #8caaee
+
+# magenta
+color5 #f4b8e4
+color13 #f4b8e4
+
+# cyan
+color6 #81c8be
+color14 #81c8be
+
+# white
+color7 #b5bfe2
+color15 #a5adce
diff --git a/.config/kitty/themes/matugen.conf b/.config/kitty/themes/matugen.conf
new file mode 100644
index 0000000..3a0a77c
--- /dev/null
+++ b/.config/kitty/themes/matugen.conf
@@ -0,0 +1,38 @@
+cursor #e9e2d4
+cursor_text_color #cdc6b4
+
+foreground #e9e2d4
+background #15130b
+selection_foreground #373016
+selection_background #d1c6a1
+url_color #dcc66e
+
+# black
+color8 #969080
+color0 #4c4c4c
+
+# red
+color1 #ac8a8c
+color9 #c49ea0
+# green
+color2 #8aac8b
+color10 #9ec49f
+
+# yellow
+color3 #aca98a
+color11 #c4c19e
+
+# blue
+color4 #dcc66e
+color12 #a39ec4
+
+# magenta
+color5 #aad0b3
+color13 #c5ecce
+# cyan
+color6 #8aacab
+color14 #9ec3c4
+
+# white
+color15 #e7e7e7
+color7 #f0f0f0
diff --git a/.config/mako/colors.conf b/.config/mako/colors.conf
new file mode 100644
index 0000000..160a279
--- /dev/null
+++ b/.config/mako/colors.conf
@@ -0,0 +1,3 @@
+background-color=#3c3930
+border-color=#969080
+text-color=#e9e2d4
diff --git a/.config/mako/config b/.config/mako/config
new file mode 100644
index 0000000..75306d4
--- /dev/null
+++ b/.config/mako/config
@@ -0,0 +1,13 @@
+include=~/.config/mako/colors.conf
+border-size=2
+border-radius=8
+icon-border-radius=8
+icons=1
+anchor=top-right
+default-timeout=5000
+margin=10
+padding=10,0
+font=adwaita sans regular 11
+history=1
+max-visible=20
+max-history=100
diff --git a/.config/matugen/config.toml b/.config/matugen/config.toml
new file mode 100755
index 0000000..dc6fbcf
--- /dev/null
+++ b/.config/matugen/config.toml
@@ -0,0 +1,126 @@
+[config.wallpaper]
+command = "swww"
+#arguments = ["img", "--transition-type", "center"]
+#set = false
+
+[templates.waybar]
+input_path = '~/.config/matugen/templates/colors.css'
+output_path = '~/.config/waybar/colors.css'
+#post_hook='ln -s ~/.config/waybar/colors.css ~/.config/waybar-niri-Win11Like/colors.css'
+
+#[templates.pywalfox]
+#input_path = '~/.config/matugen/templates/pywalfox-colors.json'
+#output_path = '~/.cache/wal/colors.json'
+#post_hook = 'pywalfox update &'
+
+[templates.fuzzel]
+input_path = '~/.config/matugen/templates/fuzzel.ini'
+output_path = '~/.config/fuzzel/colors.ini'
+[templates.kitty]
+input_path = '~/.config/matugen/templates/kitty-colors.conf'
+output_path ='~/.config/kitty/themes/matugen.conf'
+post_hook = "kitty +kitten themes --reload-in=all matugen &"
+
+#[templates.fcitx5]
+#input_path = '~/.config/matugen/templates/fcitx5-theme.conf'
+#output_path = '~/.local/share/fcitx5/themes/Matugen/theme.conf'
+#post_hook= 'fcitx5 -r & disown '
+
+[templates.mako]
+input_path = '~/.config/matugen/templates/mako-colors.conf'
+output_path = '~/.config/mako/colors.conf'
+post_hook='makoctl reload &'
+
+[templates.btop]
+input_path = '~/.config/matugen/templates/btop.theme'
+output_path = '~/.config/btop/themes/matugen.theme'
+post_hook = 'killall -SIGUSR1 btop && killall -SIGUSR2 btop &'
+
+[templates.cava]
+input_path = '~/.config/matugen/templates/cava-colors.ini'
+output_path = '~/.config/cava/themes/your-theme'
+#post_hook = "pkill -USR1 cava"
+
+#[templates.starship]
+#input_path = '~/.config/matugen/templates/starship-colors.toml'
+#output_path = '~/.config/starship.toml'
+
+[templates.yazi]
+input_path = '~/.config/matugen/templates/yazi-theme.toml'
+output_path = '~/.config/yazi/theme.toml'
+
+#[templates.wlogout]
+#input_path = '~/.config/matugen/templates/colors.css'
+#output_path = '~/.config/wlogout/colors.css'
+#[templates.wlogout-recolor]
+#input_path = '~/.config/matugen/templates/wlogout/recolor.sh'
+#output_path = '~/.config/wlogout/icons/recolor.sh'
+#post_hook = 'chmod +x ~/.config/wlogout/icons/recolor.sh && bash ~/.config/wlogout/icons/recolor.sh &'
+#[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.swaync]
+#input_path = '~/.config/matugen/templates/swaync-colors.css'
+#output_path = '~/.config/swaync/colors.css'
+#post_hook = 'swaync-client -rs &'
+
+#[templates.ghostty]
+#input_path = '~/.config/matugen/templates/ghostty-colors.conf'
+#output_path = '~/.config/ghostty/themes/Matugen'
+#post_hook = 'pkill -SIGUSR2 ghostty'
+
+#[templates.qt5ct]
+#input_path = '~/.config/matugen/templates/qtct-colors.conf'
+#output_path = '~/.config/qt5ct/colors/matugen.conf'
+
+#[templates.qt6ct]
+#input_path = '~/.config/matugen/templates/qtct-colors.conf'
+#output_path = '~/.config/qt6ct/colors/matugen.conf'
+
+#[templates.color-scheme]
+#input_path = '~/.config/matugen/templates/Matugen.colors'
+#output_path = '~/.local/share/color-schemes/Matugen.colors'
+
+#[templates.hyprland]
+#input_path = '~/.config/matugen/templates/hyprland-colors.conf'
+#output_path = '~/.config/hypr/colors.conf'
+#post_hook = 'hyprctl reload &'
+
+#[templates.niriswitcher]
+#input_path = '~/.config/matugen/templates/niriswitcher-colors.css'
+#output_path = '~/.config/niriswitcher/style.css'
+#post_hook= 'pkill niriswitcher || true && niriswitcher & disown'
+
+[templates.niri]
+input_path = '~/.config/matugen/templates/niri-colors.kdl'
+output_path = '~/.config/niri/colors.kdl'
+post_hook = 'niri msg action load-config-file'
+#[templates.gtk-folder]
+#input_path = '~/.config/matugen/templates/gtk-folder/recolor.sh'
+#output_path = '~/.cache/matugen/recoloricons.sh'
+#post_hook = 'bash ~/.cache/matugen/recoloricons.sh &'
+
+#[templates.swayosd]
+#input_path = '~/.config/matugen/templates/colors.css'
+#output_path = '~/.config/swayosd/colors.css'
+#post_hook = 'pkill swayosd && swayosd-server &'
+
+#[templates.swaylock-effects]
+#input_path = '~/.config/matugen/templates/swaylock-colors'
+#output_path = '~/.config/swaylock/config'
+
+#[templates.fastfetch]
+#input_path = '~/.config/matugen/templates/fastfetch-config.jsonc'
+#output_path = '~/.config/fastfetch/config.jsonc'
+
+#[templates.neovim]
+#input_path = '~/.config/matugen/templates/neovim/template.lua'
+#output_path = '~/.config/nvim/generated.lua'
+#post_hook = 'pkill -SIGUSR1 nvim'
+
+#[templates.hyprlock]
+#input_path = '~/.config/matugen/templates/hyprland-colors.conf'
+#output_path = '~/.config/hypr/colors.conf'
diff --git a/.config/matugen/templates/Matugen.colors b/.config/matugen/templates/Matugen.colors
new file mode 100644
index 0000000..8470630
--- /dev/null
+++ b/.config/matugen/templates/Matugen.colors
@@ -0,0 +1,153 @@
+[UiSettings]
+ColorScheme=Matugen
+
+[ColorEffects:Disabled]
+Color={{colors.surface_dim.default.hex}}
+ColorAmount=0
+ColorEffect=0
+ContrastAmount=0.65
+ContrastEffect=1
+IntensityAmount=0.1
+IntensityEffect=2
+
+[ColorEffects:Inactive]
+ChangeSelectionColor=true
+Color={{colors.surface_variant.default.hex}}
+ColorAmount=0.025
+ColorEffect=2
+ContrastAmount=0.1
+ContrastEffect=2
+Enable=false
+IntensityAmount=0
+IntensityEffect=0
+
+[Colors:Button]
+BackgroundAlternate={{colors.surface_container_low.default.hex}}
+BackgroundNormal={{colors.surface_container_high.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_surface.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:Complementary]
+BackgroundAlternate={{colors.surface_container_low.default.hex}}
+BackgroundNormal={{colors.surface.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_primary_container.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:Header]
+BackgroundAlternate={{colors.surface.default.hex}}
+BackgroundNormal={{colors.surface_container.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_surface.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:Header][Inactive]
+BackgroundAlternate={{colors.surface_container.default.hex}}
+BackgroundNormal={{colors.surface.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_surface.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:Selection]
+BackgroundAlternate={{colors.surface_container_low.default.hex}}
+BackgroundNormal={{colors.primary.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.on_primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary_fixed.default.hex}}
+ForegroundNegative={{colors.error_container.default.hex}}
+ForegroundNeutral={{colors.tertiary_fixed_dim.default.hex}}
+ForegroundNormal={{colors.on_primary.default.hex}}
+ForegroundPositive={{colors.tertiary_container.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:Tooltip]
+BackgroundAlternate={{colors.surface.default.hex}}
+BackgroundNormal={{colors.surface_container.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_background.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:View]
+BackgroundAlternate={{colors.surface_container.default.hex}}
+BackgroundNormal={{colors.background.default.hex}}
+DecorationFocus={{colors.on_primary_container.default.hex}}
+DecorationHover={{colors.on_primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_background.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[Colors:Window]
+BackgroundAlternate={{colors.primary_container.default.hex}}
+BackgroundNormal={{colors.surface_container.default.hex}}
+DecorationFocus={{colors.primary.default.hex}}
+DecorationHover={{colors.primary.default.hex}}
+ForegroundActive={{colors.primary.default.hex}}
+ForegroundInactive={{colors.on_surface_variant.default.hex}}
+ForegroundLink={{colors.secondary.default.hex}}
+ForegroundNegative={{colors.error.default.hex}}
+ForegroundNeutral={{colors.tertiary.default.hex}}
+ForegroundNormal={{colors.on_background.default.hex}}
+ForegroundPositive={{colors.tertiary_fixed.default.hex}}
+ForegroundVisited={{colors.on_secondary_container.default.hex}}
+
+[General]
+ColorScheme=Matugen
+Name=Matugen
+
+[Appearance]
+color_scheme=Matugen
+
+[KDE]
+contrast=4
+
+[WM]
+activeBackground={{colors.primary_container.default.hex}}
+activeBlend={{colors.on_primary_container.default.hex}}
+activeForeground={{colors.on_primary_container.default.hex}}
+inactiveBackground={{colors.surface.default.hex}}
+inactiveBlend={{colors.on_surface_variant.default.hex}}
+inactiveForeground={{colors.on_surface_variant.default.hex}}
+
diff --git a/.config/matugen/templates/btop.theme b/.config/matugen/templates/btop.theme
new file mode 100755
index 0000000..8fc94f6
--- /dev/null
+++ b/.config/matugen/templates/btop.theme
@@ -0,0 +1,89 @@
+# Matugen template for btop
+
+
+# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
+# example for white: "#ffffff", "#ff" or "255 255 255".
+
+# All graphs and meters can be gradients
+# For single color graphs leave "mid" and "end" variable empty.
+# Use "start" and "end" variables for two color gradient
+# Use "start", "mid" and "end" for three color gradient
+
+# Main background, empty for terminal default, need to be empty if you want transparent background
+theme[main_bg]=""
+
+# Main text color
+theme[main_fg]="{{colors.on_surface.default.hex}}"
+
+# Title color for boxes
+theme[title]="{{colors.primary.default.hex}}"
+
+# Highlight color for keyboard shortcuts
+theme[hi_fg]="{{colors.secondary.default.hex}}"
+
+# Background color of selected item in processes box
+theme[selected_bg]="{{colors.primary.default.hex}}"
+
+# Foreground color of selected item in processes box
+theme[selected_fg]="{{colors.on_primary.default.hex}}"
+
+# Color of inactive/disabled text
+theme[inactive_fg]="{{colors.on_surface_variant.default.hex}}"
+
+# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
+theme[proc_misc]="{{colors.tertiary.default.hex}}"
+
+# Cpu box outline color
+theme[cpu_box]="{{colors.outline.default.hex}}"
+
+# Memory/disks box outline color
+theme[mem_box]="{{colors.outline.default.hex}}"
+
+# Net up/down box outline color
+theme[net_box]="{{colors.outline.default.hex}}"
+
+# Processes box outline color
+theme[proc_box]="{{colors.outline.default.hex}}"
+
+# Box divider line and small boxes line color
+theme[div_line]="{{colors.outline_variant.default.hex}}"
+
+# Temperature graph colors
+theme[temp_start]="{{colors.secondary.default.hex}}"
+theme[temp_mid]="{{colors.primary.default.hex}}"
+theme[temp_end]="{{colors.error.default.hex}}"
+
+# CPU graph colors
+theme[cpu_start]="{{colors.secondary.default.hex}}"
+theme[cpu_mid]="{{colors.primary.default.hex}}"
+theme[cpu_end]="{{colors.error.default.hex}}"
+
+# Mem/Disk free meter
+theme[free_start]="{{colors.secondary.default.hex}}"
+theme[free_mid]=""
+theme[free_end]="{{colors.secondary_container.default.hex}}"
+
+# Mem/Disk cached meter
+theme[cached_start]="{{colors.tertiary.default.hex}}"
+theme[cached_mid]=""
+theme[cached_end]="{{colors.tertiary_container.default.hex}}"
+
+# Mem/Disk available meter
+theme[available_start]="{{colors.primary.default.hex}}"
+theme[available_mid]=""
+theme[available_end]="{{colors.primary_container.default.hex}}"
+
+# Mem/Disk used meter
+theme[used_start]="{{colors.error.default.hex}}"
+theme[used_mid]=""
+theme[used_end]="{{colors.error_container.default.hex}}"
+
+# Download graph colors
+theme[download_start]="{{colors.secondary.default.hex}}"
+theme[download_mid]="{{colors.primary.default.hex}}"
+theme[download_end]="{{colors.tertiary.default.hex}}"
+
+# Upload graph colors
+theme[upload_start]="{{colors.secondary.default.hex}}"
+theme[upload_mid]="{{colors.primary.default.hex}}"
+theme[upload_end]="{{colors.tertiary.default.hex}}"
diff --git a/.config/matugen/templates/cava-colors.ini b/.config/matugen/templates/cava-colors.ini
new file mode 100755
index 0000000..f4813b2
--- /dev/null
+++ b/.config/matugen/templates/cava-colors.ini
@@ -0,0 +1,19 @@
+[color]
+background = 'default'
+foreground = '{{colors.primary.default.hex}}'
+
+; gradient = 0
+gradient = 1
+gradient_color_1 = '{{colors.primary_container.default.hex}}'
+gradient_color_2 = '{{colors.primary.default.hex}}'
+gradient_color_3 = '{{colors.on_primary_container.default.hex}}'
+
+horizontal_gradient = 0
+; horizontal_gradient = 1
+horizontal_gradient_color_1 = '{{colors.primary_container.default.hex}}'
+horizontal_gradient_color_2 = '{{colors.primary.default.hex}}'
+horizontal_gradient_color_3 = '{{colors.on_primary_container.default.hex}}'
+horizontal_gradient_color_4 = '{{colors.primary.default.hex}}'
+horizontal_gradient_color_5 = '{{colors.primary_container.default.hex}}'
+
+
diff --git a/.config/matugen/templates/colors.css b/.config/matugen/templates/colors.css
new file mode 100755
index 0000000..f246856
--- /dev/null
+++ b/.config/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/.config/matugen/templates/fastfetch-config.jsonc b/.config/matugen/templates/fastfetch-config.jsonc
new file mode 100644
index 0000000..01c2f39
--- /dev/null
+++ b/.config/matugen/templates/fastfetch-config.jsonc
@@ -0,0 +1,124 @@
+{
+ "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/master/doc/json_schema.json",
+ "logo": {
+ "type": "kitty",
+ //"source": "/home/shorin/Pictures/picture.png",
+ "width": 25,
+ // "height":20,
+ "padding": {
+ "top": 1, // Top padding
+ "left": 2, // Left padding
+ "right": 2 // Right padding
+ },
+ },
+ "display": {
+ "separator": " ", // Separator between keys and values
+ "color": {
+ //"keys": "{{colors.secondary.default.hex}}", // Key color module名字的颜色
+ "title": "{{colors.on_surface_variant.default.hex}}", // Title color 主机名的颜色
+ "output": "{{colors.on_surface_variant.default.hex}}"
+ },
+ },
+ "modules": [
+ "break",
+ {
+ "type": "os", //这是哪个module
+ "key": "OS", //module名字的显示
+ // "keyColor": "#00ff00", //module名字颜色
+ // "format": "{name} {version}", //具体内容
+ "keyColor": "{{colors.primary.default.hex}}",
+
+ },
+ {
+ "type": "kernel",
+ "key": " ├ KER ",
+ "keyColor": "{{colors.primary.default.hex}}",
+
+ },
+ {
+ "type": "packages",
+ "key": " ├ PAK ",
+ "format": "{all}",
+ "keyColor": "{{colors.primary.default.hex}}",
+ },
+ {
+ "type": "title",
+ "key": " └ USR ",
+ "keyColor": "{{colors.primary.default.hex}}",
+ },
+ "break",
+ "break",
+ {
+ "type": "wm",
+ "key": "WM",
+ "keyColor": "{{colors.tertiary.default.hex}}",
+ },
+ {
+ "type": "de",
+ "key": " ├ DES ",
+ "keyColor": "{{colors.tertiary.default.hex}}",
+ //"outputColor": "{{colors.tertiary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "shell",
+ "key": " ├ SHE ",
+ "keyColor": "{{colors.tertiary.default.hex}}",
+ //"outputColor": "{{colors.tertiary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "terminal",
+ "key": " ├ TER ",
+ "keyColor": "{{colors.tertiary.default.hex}}",
+ //"outputColor": "{{colors.tertiary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "terminalfont",
+ "key": " └ TFO ",
+ "keyColor": "{{colors.tertiary.default.hex}}",
+ //"outputColor": "{{colors.tertiary_fixed_dim.default.hex}}"
+ },
+ "break",
+ "break",
+ {
+ "type": "host",
+ "key": "PC ",
+ "keyColor": "{{colors.secondary_fixed.default.hex}}",
+ //"outputColor": "{{colors.secondary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "cpu",
+ "key": " ├ CPU ",
+ "keyColor": "{{colors.secondary_fixed.default.hex}}",
+ //"outputColor": "{{colors.secondary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "memory",
+ "key": " ├ MEM ",
+ "keyColor": "{{colors.secondary_fixed.default.hex}}",
+ //"outputColor": "{{colors.secondary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "gpu",
+ "key": " ├ GPU ",
+ "format": "{1} {2}",
+ "keyColor": "{{colors.secondary_fixed.default.hex}}",
+ //"outputColor": "{{colors.secondary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "display",
+ "key": " ├ MON ",
+ "format": "{name} {width}x{height}@{refresh-rate} ",
+ "keyColor": "{{colors.secondary_fixed.default.hex}}",
+ //"outputColor": "{{colors.secondary_fixed_dim.default.hex}}"
+ },
+ {
+ "type": "disk",
+ "key": " └ DIS ",
+ "keyColor": "{{colors.secondary_fixed.default.hex}}",
+ //"outputColor": "{{colors.secondary_fixed_dim.default.hex}}"
+ },
+ "break",
+ "break",
+ "colors"
+ ]
+}
diff --git a/.config/matugen/templates/fcitx5-theme.conf b/.config/matugen/templates/fcitx5-theme.conf
new file mode 100644
index 0000000..3589610
--- /dev/null
+++ b/.config/matugen/templates/fcitx5-theme.conf
@@ -0,0 +1,296 @@
+# vim: ft=dosini
+[Metadata]
+Name=Matugen
+Version=0.1
+Author=shorin
+Description=WallpaperColorSyncByMatugen
+ScaleWithDPI=True
+
+[InputPanel]
+# 改这个:一般文字颜色
+NormalColor={{colors.on_surface.default.hex}}
+# 高亮文字颜色
+HighlightColor={{colors.on_primary.default.hex}}
+# 高亮背景颜色
+HighlightBackgroundColor={{colors.tertiary.default.hex}}
+# 改这个:这个才是被选中的文字颜色
+HighlightCandidateColor={{colors.on_tertiary.default.hex}}
+# KWin 下启用模糊
+EnableBlur=False
+# 模糊遮罩
+BlurMask=
+# 竖排列表时使用所有横向空间高亮
+FullWidthHighlight=True
+# 页面按钮垂直对齐
+PageButtonAlignment="Last Candidate"
+
+[InputPanel/Background]
+# 改这个:输入法框整体背景颜色
+Color={{colors.surface_container.default.hex}}
+# 边框颜色
+BorderColor={{colors.outline.default.hex}}
+# 改这个:边框宽度
+BorderWidth=2
+
+[InputPanel/Background/Margin]
+# 左侧边距
+Left=2
+# 右侧边距
+Right=2
+# 顶部边距
+Top=2
+# 底部边距
+Bottom=2
+
+[InputPanel/Highlight]
+# 改这个:高亮背景颜色
+Color={{colors.tertiary.default.hex}}
+
+[InputPanel/Highlight/Margin]
+# 左侧边距
+Left=5
+# 右侧边距
+Right=5
+# 顶部边距
+Top=5
+# 底部边距
+Bottom=5
+
+[InputPanel/ContentMargin]
+# 左侧边距
+Left=2
+# 右侧边距
+Right=2
+# 顶部边距
+Top=2
+# 底部边距
+Bottom=2
+
+[InputPanel/TextMargin]
+# 左侧边距
+Left=5
+# 右侧边距
+Right=5
+# 顶部边距
+Top=5
+# 底部边距
+Bottom=5
+
+[Menu]
+# 一般文字颜色
+NormalColor={{colors.on_surface.default.hex}}
+# 选中项文本颜色
+HighlightCandidateColor={{colors.on_surface.default.hex}}
+
+[Menu/Background]
+# 背景图片
+Image=
+# 颜色
+Color={{colors.surface_container.default.hex}}
+# 边框颜色
+BorderColor={{colors.outline.default.hex}}
+# 边框宽度
+BorderWidth=2
+# 覆盖图片
+Overlay=
+# 覆盖图片位置
+Gravity="Top Left"
+# 覆盖图片 X 偏移
+OverlayOffsetX=0
+# 覆盖图片 Y 偏移
+OverlayOffsetY=0
+# 显示区域不足时隐藏覆盖图片
+HideOverlayIfOversize=False
+
+[Menu/Background/Margin]
+# 左侧边距
+Left=2
+# 右侧边距
+Right=2
+# 顶部边距
+Top=2
+# 底部边距
+Bottom=2
+
+
+[Menu/Highlight]
+# 背景图片
+Image=
+# 颜色
+Color={{colors.tertiary.default.hex}}
+# 边框颜色
+BorderColor={{colors.outline.default.hex}}
+# 边框宽度
+BorderWidth=0
+# 覆盖图片
+Overlay=
+# 覆盖图片位置
+Gravity="Top Left"
+# 覆盖图片 X 偏移
+OverlayOffsetX=0
+# 覆盖图片 Y 偏移
+OverlayOffsetY=0
+# 显示区域不足时隐藏覆盖图片
+HideOverlayIfOversize=False
+
+[Menu/Highlight/Margin]
+# 左侧边距
+Left=5
+# 右侧边距
+Right=5
+# 顶部边距
+Top=5
+# 底部边距
+Bottom=5
+
+[Menu/Highlight/OverlayClipMargin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/Separator]
+# 背景图片
+Image=
+# 颜色
+Color=#c0c0c0
+# 边框颜色
+BorderColor=#ffffff00
+# 边框宽度
+BorderWidth=0
+# 覆盖图片
+Overlay=
+# 覆盖图片位置
+Gravity="Top Left"
+# 覆盖图片 X 偏移
+OverlayOffsetX=0
+# 覆盖图片 Y 偏移
+OverlayOffsetY=0
+# 显示区域不足时隐藏覆盖图片
+HideOverlayIfOversize=False
+
+[Menu/Separator/Margin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/Separator/OverlayClipMargin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/CheckBox]
+# 背景图片
+Image=radio.png
+# 颜色
+Color=#ffffff
+# 边框颜色
+BorderColor=#ffffff00
+# 边框宽度
+BorderWidth=0
+# 覆盖图片
+Overlay=
+# 覆盖图片位置
+Gravity="Top Left"
+# 覆盖图片 X 偏移
+OverlayOffsetX=0
+# 覆盖图片 Y 偏移
+OverlayOffsetY=0
+# 显示区域不足时隐藏覆盖图片
+HideOverlayIfOversize=False
+
+[Menu/CheckBox/Margin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/CheckBox/OverlayClipMargin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/SubMenu]
+# 背景图片
+Image=arrow.png
+# 颜色
+Color=#ffffff
+# 边框颜色
+BorderColor=#ffffff00
+# 边框宽度
+BorderWidth=0
+# 覆盖图片
+Overlay=
+# 覆盖图片位置
+Gravity="Top Left"
+# 覆盖图片 X 偏移
+OverlayOffsetX=0
+# 覆盖图片 Y 偏移
+OverlayOffsetY=0
+# 显示区域不足时隐藏覆盖图片
+HideOverlayIfOversize=False
+
+[Menu/SubMenu/Margin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/SubMenu/OverlayClipMargin]
+# 左侧边距
+Left=0
+# 右侧边距
+Right=0
+# 顶部边距
+Top=0
+# 底部边距
+Bottom=0
+
+[Menu/ContentMargin]
+# 左侧边距
+Left=2
+# 右侧边距
+Right=2
+# 顶部边距
+Top=2
+# 底部边距
+Bottom=2
+
+[Menu/TextMargin]
+# 左侧边距
+Left=5
+# 右侧边距
+Right=5
+# 顶部边距
+Top=5
+# 底部边距
+Bottom=5
+
+
diff --git a/.config/matugen/templates/fuzzel.ini b/.config/matugen/templates/fuzzel.ini
new file mode 100755
index 0000000..2e2cbdd
--- /dev/null
+++ b/.config/matugen/templates/fuzzel.ini
@@ -0,0 +1,15 @@
+# Fuzzel Colors
+# Generated with Matugen
+
+[colors]
+background={{colors.surface_container.default.hex_stripped}}ff
+text={{colors.on_surface.default.hex_stripped}}ff
+prompt={{colors.secondary.default.hex_stripped}}ff
+placeholder={{colors.tertiary.default.hex_stripped}}ff
+input={{colors.primary.default.hex_stripped}}ff
+match={{colors.tertiary.default.hex_stripped}}ff
+selection={{colors.secondary.default.hex_stripped}}ff
+selection-text={{colors.on_secondary.default.hex_stripped}}ff
+selection-match={{colors.on_tertiary.default.hex_stripped}}ff
+counter={{colors.secondary.default.hex_stripped}}ff
+border={{colors.secondary.default.hex_stripped}}ff
diff --git a/.config/matugen/templates/ghostty-colors.conf b/.config/matugen/templates/ghostty-colors.conf
new file mode 100755
index 0000000..499cc05
--- /dev/null
+++ b/.config/matugen/templates/ghostty-colors.conf
@@ -0,0 +1,6 @@
+background = {{colors.background.default.hex}}
+foreground = {{colors.on_surface.default.hex}}
+cursor-color = {{colors.on_surface.default.hex}}
+cursor-text = {{colors.on_surface_variant.default.hex}}
+selection-background = {{colors.secondary_fixed_dim.default.hex}}
+selection-foreground = {{colors.on_secondary.default.hex}}
diff --git a/.config/matugen/templates/gtk-colors.css b/.config/matugen/templates/gtk-colors.css
new file mode 100644
index 0000000..3caf395
--- /dev/null
+++ b/.config/matugen/templates/gtk-colors.css
@@ -0,0 +1,17 @@
+@define-color accent_color {{colors.primary_fixed_dim.default.hex}};
+@define-color accent_fg_color {{colors.on_primary.default.hex}};
+@define-color accent_bg_color {{colors.primary.default.hex}};
+@define-color window_bg_color {{colors.surface_container.default.hex}};
+@define-color window_fg_color {{colors.on_surface.default.hex}};
+@define-color headerbar_bg_color {{colors.surface_container.default.hex}};
+@define-color headerbar_fg_color {{colors.on_surface.default.hex}};
+@define-color popover_bg_color {{colors.surface_container.default.hex}};
+@define-color popover_fg_color {{colors.on_surface.default.hex}};
+@define-color view_bg_color {{colors.surface_container_low.default.hex}};
+@define-color view_fg_color {{colors.on_surface.default.hex}};
+@define-color card_bg_color {{colors.surface_container_low.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/.config/matugen/templates/gtk-folder/Adwaita-Matugen/index.theme b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/index.theme
new file mode 100644
index 0000000..a143982
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/index.theme
@@ -0,0 +1,235 @@
+[Icon Theme]
+Name=Adwaita-Matugen
+Comment=The Only One
+Example=folder
+Inherits=Adwaita,AdwaitaLegacy,hicolor
+Hidden=true
+
+# KDE Specific Stuff
+DisplayDepth=32
+LinkOverlay=link_overlay
+LockOverlay=lock_overlay
+ZipOverlay=zip_overlay
+DesktopDefault=48
+DesktopSizes=16,22,32,48,64,72,96,128
+ToolbarDefault=22
+ToolbarSizes=16,22,32,48
+MainToolbarDefault=22
+MainToolbarSizes=16,22,32,48
+SmallDefault=16
+SmallSizes=16
+PanelDefault=32
+PanelSizes=16,22,32,48,64,72,96,128
+
+# Directory list
+Directories=16x16/actions,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/legacy,16x16/mimetypes,16x16/places,16x16/status,16x16/ui,scalable/devices,scalable/mimetypes,scalable/places,scalable/status,scalable/actions,scalable/apps,scalable/categories,scalable/emblems,scalable/emotes,scalable/legacy,scalable/ui,symbolic/actions,symbolic/apps,symbolic/categories,symbolic/devices,symbolic/emblems,symbolic/emotes,symbolic/mimetypes,symbolic/places,symbolic/status,symbolic/legacy,symbolic/ui,
+
+[16x16/actions]
+Context=Actions
+Size=16
+Type=Fixed
+
+[16x16/apps]
+Context=Applications
+Size=16
+Type=Fixed
+
+[16x16/categories]
+Context=Categories
+Size=16
+Type=Fixed
+
+[16x16/devices]
+Context=Devices
+Size=16
+Type=Fixed
+
+[16x16/emblems]
+Context=Emblems
+Size=16
+Type=Fixed
+
+[16x16/emotes]
+Context=Emotes
+Size=16
+Type=Fixed
+
+[16x16/legacy]
+Context=Legacy
+Size=16
+Type=Fixed
+
+[16x16/mimetypes]
+Context=MimeTypes
+Size=16
+Type=Fixed
+
+[16x16/places]
+Context=Places
+Size=16
+Type=Fixed
+
+[16x16/status]
+Context=Status
+Size=16
+Type=Fixed
+
+[16x16/ui]
+Context=UI
+Size=16
+Type=Fixed
+
+[scalable/devices]
+Context=Devices
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/mimetypes]
+Context=MimeTypes
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/places]
+Context=Places
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/status]
+Context=Status
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/actions]
+Context=Actions
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/apps]
+Context=Applications
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/categories]
+Context=Categories
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/emblems]
+Context=Emblems
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/emotes]
+Context=Emotes
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/legacy]
+Context=Legacy
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[scalable/ui]
+Context=UI
+Size=128
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/actions]
+Context=Actions
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/apps]
+Context=Applications
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/categories]
+Context=Categories
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/devices]
+Context=Devices
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/emblems]
+Context=Emblems
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/emotes]
+Context=Emotes
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/mimetypes]
+Context=MimeTypes
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/places]
+Context=Places
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/status]
+Context=Status
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/legacy]
+Context=Legacy
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
+[symbolic/ui]
+Context=UI
+Size=16
+MinSize=8
+MaxSize=512
+Type=Scalable
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/application-x-addon.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/application-x-addon.svg
new file mode 100644
index 0000000..4ee67b4
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/application-x-addon.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/application-x-executable.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/application-x-executable.svg
new file mode 100644
index 0000000..a2f038e
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/application-x-executable.svg
@@ -0,0 +1,37 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/font-x-generic.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/font-x-generic.svg
new file mode 100644
index 0000000..fc93ed9
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/font-x-generic.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/inode-directory.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/inode-directory.svg
new file mode 100644
index 0000000..d89d7c3
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/inode-directory.svg
@@ -0,0 +1,14 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/text-html.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/text-html.svg
new file mode 100644
index 0000000..296603f
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/text-html.svg
@@ -0,0 +1,23 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/text-x-script.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/text-x-script.svg
new file mode 100644
index 0000000..5efac55
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/text-x-script.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/x-office-document.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/x-office-document.svg
new file mode 100644
index 0000000..dd73be1
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/x-office-document.svg
@@ -0,0 +1,27 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/x-office-presentation.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/x-office-presentation.svg
new file mode 100644
index 0000000..41d5d0d
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/mimetypes/x-office-presentation.svg
@@ -0,0 +1,33 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-documents.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-documents.svg
new file mode 100644
index 0000000..7fa7030
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-documents.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-download.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-download.svg
new file mode 100644
index 0000000..f707afa
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-download.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-drag-accept.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-drag-accept.svg
new file mode 100644
index 0000000..d89d7c3
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-drag-accept.svg
@@ -0,0 +1,14 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-music.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-music.svg
new file mode 100644
index 0000000..115b5c7
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-music.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-pictures.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-pictures.svg
new file mode 100644
index 0000000..173d777
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-pictures.svg
@@ -0,0 +1,18 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-publicshare.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-publicshare.svg
new file mode 100644
index 0000000..163320b
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-publicshare.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-remote.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-remote.svg
new file mode 100644
index 0000000..fb05bea
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-remote.svg
@@ -0,0 +1,37 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-templates.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-templates.svg
new file mode 100644
index 0000000..e7f0747
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-templates.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-videos.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-videos.svg
new file mode 100644
index 0000000..665af73
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder-videos.svg
@@ -0,0 +1,18 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder.svg
new file mode 100644
index 0000000..d89d7c3
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/folder.svg
@@ -0,0 +1,14 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/network-server.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/network-server.svg
new file mode 100644
index 0000000..fa65381
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/network-server.svg
@@ -0,0 +1,53 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/network-workgroup.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/network-workgroup.svg
new file mode 100644
index 0000000..92b8866
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/network-workgroup.svg
@@ -0,0 +1,103 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-bookmarks.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-bookmarks.svg
new file mode 100644
index 0000000..af9b0e8
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-bookmarks.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-desktop.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-desktop.svg
new file mode 100644
index 0000000..34d3948
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-desktop.svg
@@ -0,0 +1,18 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-home.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-home.svg
new file mode 100644
index 0000000..f036aa1
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-home.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-trash.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-trash.svg
new file mode 100644
index 0000000..f33215b
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/places/user-trash.svg
@@ -0,0 +1,102 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/status/folder-open.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/status/folder-open.svg
new file mode 100644
index 0000000..d89d7c3
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/status/folder-open.svg
@@ -0,0 +1,14 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/status/user-trash-full.svg b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/status/user-trash-full.svg
new file mode 100644
index 0000000..a95b170
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/Adwaita-Matugen/scalable/status/user-trash-full.svg
@@ -0,0 +1,1079 @@
+
+
diff --git a/.config/matugen/templates/gtk-folder/recolor.sh b/.config/matugen/templates/gtk-folder/recolor.sh
new file mode 100755
index 0000000..bfef57a
--- /dev/null
+++ b/.config/matugen/templates/gtk-folder/recolor.sh
@@ -0,0 +1,264 @@
+#!/usr/bin/env bash
+
+# ==============================================================================
+# Adwaita-Matugen Icon Generator V6 (扁平化配置版)
+# 逻辑:每一组 SVG 文件的颜色变量直接在顶部定义,方便用户微调。
+# ==============================================================================
+
+# ==============================================================================
+# [一] 颜色变量配置区 (用户修改此处)
+# ==============================================================================
+MAIN_COLOR="{{colors.secondary_fixed_dim.default.hex}}"
+MAIN_SHADOW="{{colors.secondary_container.default.hex}}"
+MAIN_DARKER_SHADOW="{{colors.on_secondary.default.hex}}"
+MAIN_HILIGHT="{{colors.secondary.default.hex}}"
+INVERSE_MAIN_COLOR="{{colors.tertiary_fixed_dim.default.hex}}"
+INVERSE_MAIN_HIGHLT="{{colors.tertiary.default.hex}}"
+INVERSE_MAIN_SHADOW="{{colors.tertiary_container.default.hex}}"
+PAPER_COLOR="#fafafa"
+PAPER_FOLE_COLOR="#deddda"
+# ------------------------------------------------------------------------------
+# [1] 文件夹 (folder*.svg / user-home.svg ...)
+# ------------------------------------------------------------------------------
+# 文件夹保持使用 Secondary (次色系),为了不刺眼使用 dim 版本作为主体
+COLOR_FOLDER_BODY=$MAIN_COLOR # 主体 (原 #a4caee)
+COLOR_FOLDER_TOP=$MAIN_HILIGHT # 顶部高光/符号 (原 #afd4ff)
+COLOR_FOLDER_SHADOW=$MAIN_SHADOW # 阴影/渐变暗部 (原 #438de6)
+
+# ------------------------------------------------------------------------------
+# [2] 网络与垃圾桶 (network*.svg / user-trash*.svg)
+# ------------------------------------------------------------------------------
+# 使用 Tertiary (第三色系) 作为强调色
+COLOR_ACCENT_BODY=$INVERSE_MAIN_COLOR # 主体 (原 #1c71d8/垃圾桶身)
+COLOR_ACCENT_LIGHT=$INVERSE_MAIN_HIGHLT # 亮部 (原 #62a0ea/垃圾桶盖亮面)
+COLOR_ACCENT_DARK=$INVERSE_MAIN_SHADOW # 暗部 (原 #1a5fb4/垃圾桶内侧)
+COLOR_TRASH_PAPER="{{colors.on_tertiary_container.default.hex}}" # 废纸团颜色
+
+# ------------------------------------------------------------------------------
+# [3] 脚本与可执行文件 (text-x-script.svg / application-x-executable.svg)
+# ------------------------------------------------------------------------------
+# 重点修正:防止偏淡,主体使用 Primary Default (最鲜艳的主色)
+# 对应 Adwaita 原版光影逻辑:
+COLOR_SCRIPT_BODY=$MAIN_SHADOW # 主体 (原 #3584e4 - 基准蓝)
+COLOR_SCRIPT_HIGHLIGHT=$MAIN_HILIGHT # 高光 (原 #99c1f1 - 亮蓝)
+COLOR_SCRIPT_MID="#f0f0f0" # 侧面/次亮 (原 #62a0ea)
+COLOR_SCRIPT_SHADOW=$MAIN_SHADOW # 阴影 (原 #1c71d8)
+COLOR_SCRIPT_GEAR=$MAIN_DARKER_SHADOW # 齿轮/最深色
+COLOR_SCRIPT_PALE="ffffff" # 极亮部 (原 #d7e8fc)
+
+# ------------------------------------------------------------------------------
+# [4] 网页地球仪 (text-html.svg)
+# ------------------------------------------------------------------------------
+# [新增] 极高光/反光 (原 #b3d3f9, #d7e8fc)
+# 建议:使用 secondary_fixed (通常比 dim 更亮) 或 surface_bright
+COLOR_HTML_PALE="#f0f0f0"
+COLOR_HTML_HIGHLIGHT=$MAIN_HILIGHT # 中间向左上一级左上反光 (原 #99c1f1)
+COLOR_HTML_BODY=$MAIN_SHADOW # 球体中间 (原 #62a0ea)
+COLOR_HTML_MID=$MAIN_SHADOW # 球体中间向右下一级 (原 #3584e4)
+COLOR_HTML_SHADOW=$MAIN_DARKER_SHADOW # 右下 (原 #1c71d8)
+COLOR_HTML_DEEP="{{colors.surface_container.default.hex}}" # 最右下 (原 #1a5fb4)
+# [新增] 纸张背景 (原 #f6f5f4, #deddda) -
+COLOR_DOC_PAPER=$PAPER_COLOR
+COLOR_DOC_FOLD=$PAPER_FOLE_COLOR
+
+# ------------------------------------------------------------------------------
+# [5] 插件图标 (application-x-addon.svg)
+# ------------------------------------------------------------------------------
+# 你的要求:必须和 Folder (Secondary) 颜色一致
+COLOR_ADDON_BODY=$MAIN_COLOR # 主体 (原 #3584e4 -> 对应 Folder Body)
+COLOR_ADDON_HIGHLIGHT=$MAIN_HILIGHT # 高光 (原 #98c1f1 -> 对应 Folder Top)
+COLOR_ADDON_SHADOW=$MAIN_SHADOW # 阴影 (原 #1c71d8 -> 对应 Folder Shadow)
+COLOR_ADDON_DEEP=$MAIN_DARKER_SHADOW # 轮廓 (原 #1a5fb4 -> 对应 Folder Deep)
+
+# ------------------------------------------------------------------------------
+# [6] 字体文件 (font-x-generic.svg)
+# ------------------------------------------------------------------------------
+COLOR_FONT_A=$MAIN_SHADOW # 字母 "A" (原 #3584e4)
+COLOR_FONT_BASE=$MAIN_DARKER_SHADOW # 底座/阴影 (原 #1a5fb4)
+
+# ------------------------------------------------------------------------------
+# [7] Office 文档 (x-office-document.svg)
+# ------------------------------------------------------------------------------
+COLOR_DOC_PAPER=$PAPER_COLOR # 纸张白
+COLOR_DOC_FOLD=$PAPER_FOLE_COLOR # 折角灰
+# 绿色渐变 -> 映射为 Tertiary (强调色)
+COLOR_DOC_GRAD_ACCENT_START=$INVERSE_MAIN_COLOR # 原 #50db81
+COLOR_DOC_GRAD_ACCENT_END=$INVERSE_MAIN_COLOR # 原 #8ff0a4
+# 蓝色阴影 -> 映射为 Primary (主色)
+COLOR_DOC_GRAD_SHADE_START=$MAIN_COLOR # 原 #4a86cf
+COLOR_DOC_GRAD_SHADE_END=$INVERSE_MAIN_COLOR # 原 #87bae1
+
+# ------------------------------------------------------------------------------
+# [8] Office 演示文稿 (x-office-presentation.svg)
+# ------------------------------------------------------------------------------
+# 你的要求:饼图蓝色变 Folder 色,绿色变 Accent 色
+COLOR_PRES_CHART_BLUE=$MAIN_COLOR # 饼图-蓝 (Folder Body)
+COLOR_PRES_CHART_BLUE_DEEP=$MAIN_SHADOW # 饼图-深蓝 (Folder Shadow)
+COLOR_PRES_CHART_GREEN=$INVERSE_MAIN_COLOR # 饼图-绿 (Accent Body)
+COLOR_PRES_CHART_GREEN_DEEP=$INVERSE_MAIN_SHADOW # 饼图-深绿 (Accent Dark)
+# 支架颜色 (保持中性灰或微调)
+COLOR_PRES_STAND_DARK="{{colors.outline.default.hex}}"
+COLOR_PRES_STAND_LIGHT="{{colors.outline.default.hex}}"
+
+
+# ==============================================================================
+# [二] 核心逻辑与 Sed 规则生成
+# ==============================================================================
+
+# 1. 文件夹规则
+CMD_FOLDER="
+s/#a4caee/$COLOR_FOLDER_BODY/g;
+s/#438de6/$COLOR_FOLDER_SHADOW/g;
+s/#62a0ea/$COLOR_FOLDER_SHADOW/g;
+s/#afd4ff/$COLOR_FOLDER_TOP/g;
+s/#c0d5ea/$COLOR_FOLDER_TOP/g"
+
+# 2. 网络规则
+CMD_NETWORK="
+s/#62a0ea/$COLOR_ACCENT_LIGHT/g;
+s/#1c71d8/$COLOR_ACCENT_BODY/g;
+s/#c0bfbc/$COLOR_ACCENT_BODY/g;
+s/#1a5fb4/$COLOR_ACCENT_DARK/g;
+s/#14498a/$COLOR_ACCENT_DARK/g;
+s/#9a9996/$COLOR_ACCENT_DARK/g;
+s/#77767b/$COLOR_FOLDER_SHADOW/g;
+s/#241f31/$COLOR_FOLDER_SHADOW/g;
+s/#3d3846/$COLOR_FOLDER_SHADOW/g"
+
+
+# 3. 垃圾桶规则
+CMD_TRASH="
+s/#2ec27e/$COLOR_ACCENT_BODY/g;
+s/#33d17a/$COLOR_ACCENT_BODY/g;
+s/#26a269/$COLOR_ACCENT_DARK/g;
+s/#26a168/$COLOR_ACCENT_DARK/g;
+s/#9a9996/$COLOR_ACCENT_DARK/g;
+s/#c3c2bc/$COLOR_ACCENT_DARK/g;
+s/#42d390/$COLOR_ACCENT_LIGHT/g;
+s/#ffffff/$COLOR_FOLDER_SHADOW/g;
+s/#deddda/$COLOR_TRASH_PAPER/g;
+s/#f6f5f4/$COLOR_TRASH_PAPER/g;
+s/#77767b/$COLOR_FOLDER_SHADOW/g"
+
+# 4. 脚本/可执行文件规则 (核心光影修正)
+CMD_SCRIPT="
+s/#3584e4/$COLOR_SCRIPT_BODY/g;
+s/#99c1f1/$COLOR_SCRIPT_HIGHLIGHT/g;
+s/#98c1f1/$COLOR_SCRIPT_HIGHLIGHT/g;
+s/#62a0ea/$COLOR_SCRIPT_MID/g;
+s/#1c71d8/$COLOR_SCRIPT_SHADOW/g;
+s/#1a5fb4/$COLOR_SCRIPT_GEAR/g;
+s/#d7e8fc/$COLOR_SCRIPT_PALE/g;
+s/#b3d3f9/$COLOR_SCRIPT_PALE/g"
+
+# 5. 网页地球仪规则 (已补全所有 Hex)
+CMD_HTML="
+s/#f6f5f4/$COLOR_DOC_PAPER/g;
+s/#deddda/$COLOR_DOC_FOLD/g;
+s/#b3d3f9/$COLOR_HTML_PALE/g;
+s/#d7e8fc/$COLOR_HTML_PALE/g;
+s/#62a0ea/$COLOR_HTML_BODY/g;
+s/#3584e4/$COLOR_HTML_MID/g;
+s/#99c1f1/$COLOR_HTML_HIGHLIGHT/g;
+s/#1c71d8/$COLOR_HTML_SHADOW/g;
+s/#1a5fb4/$COLOR_HTML_DEEP/g"
+
+# 6. Addon (拼图) 规则
+CMD_ADDON="
+s/#3584e4/$COLOR_ADDON_BODY/g;
+s/#62a0ea/$COLOR_ADDON_HIGHLIGHT/g;
+s/#98c1f1/$COLOR_ADDON_HIGHLIGHT/g;
+s/#1c71d8/$COLOR_ADDON_SHADOW/g;
+s/#1a5fb4/$COLOR_ADDON_DEEP/g"
+
+# 7. Font (字体) 规则
+CMD_FONT="
+s/#3584e4/$COLOR_FONT_A/g;
+s/#1a5fb4/$COLOR_FONT_BASE/g"
+
+# 8. Document (文档) 规则
+CMD_DOC="
+s/#f6f5f4/$COLOR_DOC_PAPER/g;
+s/#deddda/$COLOR_DOC_FOLD/g;
+s/#50db81/$COLOR_DOC_GRAD_ACCENT_START/g;
+s/#8ff0a4/$COLOR_DOC_GRAD_ACCENT_END/g;
+s/#4a86cf/$COLOR_DOC_GRAD_SHADE_START/g;
+s/#87bae1/$COLOR_DOC_GRAD_SHADE_END/g;
+s/#d7e8fc/$COLOR_SCRIPT_PALE/g;
+s/#b3d3f9/$COLOR_SCRIPT_PALE/g"
+
+# 9. Presentation (PPT) 规则
+CMD_PRES="
+s/#4a86cf/$COLOR_PRES_CHART_BLUE/g;
+s/#1a5fb4/$COLOR_PRES_CHART_BLUE_DEEP/g;
+s/#50db81/$COLOR_PRES_CHART_GREEN/g;
+s/#26a269/$COLOR_PRES_CHART_GREEN_DEEP/g;
+s/#f6f5f4/$COLOR_DOC_PAPER/g;
+s/#ffffff/$COLOR_DOC_PAPER/g;
+s/#414140/$COLOR_PRES_STAND_DARK/g;
+s/#949390/$COLOR_PRES_STAND_LIGHT/g;
+s/#d7e8fc/$COLOR_SCRIPT_PALE/g"
+
+# ==============================================================================
+# [三] 执行核心流程
+# ==============================================================================
+
+TEMPLATE_DIR="$HOME/.config/matugen/templates/gtk-folder/Adwaita-Matugen"
+CURRENT_THEME=$(gsettings get org.gnome.desktop.interface icon-theme | tr -d "'")
+
+if [[ "$CURRENT_THEME" == "Adwaita-Matugen-A" ]]; then
+ TARGET_THEME="Adwaita-Matugen-B"
+else
+ TARGET_THEME="Adwaita-Matugen-A"
+fi
+TARGET_DIR="$HOME/.local/share/icons/$TARGET_THEME"
+
+# 1. 准备目录
+mkdir -p "$TARGET_DIR"
+cp -rf --reflink=auto --no-preserve=mode,ownership "$TEMPLATE_DIR/"* "$TARGET_DIR/"
+sed -i "s/Name=.*/Name=$TARGET_THEME/" "$TARGET_DIR/index.theme"
+
+# 2. 处理 PNG (统一使用文件夹颜色)
+find "$TARGET_DIR" -name "*.png" -print0 | xargs -0 -P0 -I {} magick "{}" \
+ -channel RGB -colorspace gray -sigmoidal-contrast 10,50% \
+ +level-colors "$COLOR_FOLDER_SHADOW","$COLOR_FOLDER_BODY" \
+ +channel "{}"
+
+# 3. 处理 SVG (分模块并行处理)
+
+# [Group 1] Folders
+find "$TARGET_DIR/scalable" \
+ \( -name "folder*.svg" -o -name "user-home*.svg" -o -name "user-desktop*.svg" -o -name "user-bookmarks*.svg" -o -name "inode-directory*.svg" \) \
+ -print0 | xargs -0 -P0 sed -i "$CMD_FOLDER"
+
+# [Group 2] Network
+find "$TARGET_DIR/scalable" -name "network*.svg" -print0 | xargs -0 -P0 sed -i --follow-symlinks "$CMD_NETWORK"
+
+# [Group 3] Trash
+find "$TARGET_DIR/scalable" -name "user-trash*.svg" -print0 | xargs -0 -P0 sed -i --follow-symlinks "$CMD_TRASH"
+
+# [Group 4] Mimetypes - Script & Executable
+find "$TARGET_DIR/scalable/mimetypes" \
+ \( -name "text-x-script*.svg" -o -name "application-x-executable*.svg" \) \
+ -print0 | xargs -0 -P0 sed -i "$CMD_SCRIPT"
+
+# [Group 5] Mimetypes - Addon
+find "$TARGET_DIR/scalable/mimetypes" -name "application-x-addon*.svg" -print0 | xargs -0 -P0 sed -i "$CMD_ADDON"
+
+# [Group 6] Mimetypes - HTML
+find "$TARGET_DIR/scalable/mimetypes" -name "text-html*.svg" -print0 | xargs -0 -P0 sed -i "$CMD_HTML"
+
+# [Group 7] Mimetypes - Font
+find "$TARGET_DIR/scalable/mimetypes" -name "font-x-generic*.svg" -print0 | xargs -0 -P0 sed -i "$CMD_FONT"
+
+# [Group 8] Mimetypes - Document
+find "$TARGET_DIR/scalable/mimetypes" -name "x-office-document*.svg" -print0 | xargs -0 -P0 sed -i "$CMD_DOC"
+
+# [Group 9] Mimetypes - Presentation
+find "$TARGET_DIR/scalable/mimetypes" -name "x-office-presentation*.svg" -print0 | xargs -0 -P0 sed -i "$CMD_PRES"
+
+# 4. 应用变更
+gsettings set org.gnome.desktop.interface icon-theme "$TARGET_THEME"
+flatpak override --user --env=ICON_THEME="$TARGET_THEME" 2>/dev/null || true
+
+exit 0
\ No newline at end of file
diff --git a/.config/matugen/templates/hyprland-colors.conf b/.config/matugen/templates/hyprland-colors.conf
new file mode 100644
index 0000000..d7e6821
--- /dev/null
+++ b/.config/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/.config/matugen/templates/kitty-colors.conf b/.config/matugen/templates/kitty-colors.conf
new file mode 100755
index 0000000..cf99348
--- /dev/null
+++ b/.config/matugen/templates/kitty-colors.conf
@@ -0,0 +1,38 @@
+cursor {{colors.on_surface.default.hex}}
+cursor_text_color {{colors.on_surface_variant.default.hex}}
+
+foreground {{colors.on_surface.default.hex}}
+background {{colors.surface.default.hex}}
+selection_foreground {{colors.on_secondary.default.hex}}
+selection_background {{colors.secondary_fixed_dim.default.hex}}
+url_color {{colors.primary.default.hex}}
+
+# black
+color8 {{colors.outline.default.hex}}
+color0 #4c4c4c
+
+# red
+color1 #ac8a8c
+color9 #c49ea0
+# green
+color2 #8aac8b
+color10 #9ec49f
+
+# yellow
+color3 #aca98a
+color11 #c4c19e
+
+# blue
+color4 {{colors.primary.default.hex}}
+color12 #a39ec4
+
+# magenta
+color5 {{colors.tertiary.default.hex}}
+color13 {{colors.on_tertiary_container.default.hex}}
+# cyan
+color6 #8aacab
+color14 #9ec3c4
+
+# white
+color15 #e7e7e7
+color7 #f0f0f0
diff --git a/.config/matugen/templates/mako-colors.conf b/.config/matugen/templates/mako-colors.conf
new file mode 100644
index 0000000..e406fe8
--- /dev/null
+++ b/.config/matugen/templates/mako-colors.conf
@@ -0,0 +1,3 @@
+background-color={{colors.surface_bright.default.hex}}
+border-color={{colors.outline.default.hex}}
+text-color={{colors.on_surface.default.hex}}
diff --git a/.config/matugen/templates/neovim/init.lua b/.config/matugen/templates/neovim/init.lua
new file mode 100644
index 0000000..da107b2
--- /dev/null
+++ b/.config/matugen/templates/neovim/init.lua
@@ -0,0 +1,73 @@
+-- ==========================================================================
+-- 1. 自动安装插件管理器 (Lazy.nvim)
+-- ==========================================================================
+local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
+if not vim.loop.fs_stat(lazypath) then
+ vim.fn.system({
+ "git",
+ "clone",
+ "--filter=blob:none",
+ "https://github.com/folke/lazy.nvim.git",
+ "--branch=stable",
+ lazypath,
+ })
+end
+vim.opt.rtp:prepend(lazypath)
+
+-- ==========================================================================
+-- 2. 加载插件 (已替换为更稳定的源)
+-- ==========================================================================
+require("lazy").setup({
+ {
+ -- 【关键修改】换成了官方社区版,更稳定,不会报错
+ "RRethy/base16-nvim",
+ lazy = false,
+ priority = 1000,
+ },
+})
+
+-- ==========================================================================
+-- 3. Matugen 热更新逻辑
+-- ==========================================================================
+local function source_matugen()
+ local matugen_path = vim.fn.stdpath('config') .. "/generated.lua"
+
+ local f = io.open(matugen_path, "r")
+ if f ~= nil then
+ io.close(f)
+ -- 尝试执行生成的文件
+ local ok, err = pcall(dofile, matugen_path)
+ if not ok then
+ -- 如果加载出错,只打印提示,不阻断启动
+ print("Matugen Load Error: " .. err)
+ end
+ else
+ -- 如果还没有生成过文件,使用内置主题兜底
+ vim.cmd.colorscheme('habamax')
+ end
+end
+
+-- 热重载函数
+local function matugen_reload()
+ -- 重新加载颜色
+ source_matugen()
+
+ -- 如果你有 lualine,可以在这里刷新
+ -- package.loaded['lualine'] = nil
+ -- require('lualine').setup({ options = { theme = 'base16' } })
+
+ -- 修复一些高亮丢失
+ vim.api.nvim_set_hl(0, "Comment", { italic = true })
+end
+
+-- 监听 Matugen 发出的信号
+vim.api.nvim_create_autocmd("Signal", {
+ pattern = "SIGUSR1",
+ callback = function()
+ matugen_reload()
+ print("Matugen 颜色已更新!")
+ end,
+})
+
+-- 启动时加载一次
+source_matugen()
\ No newline at end of file
diff --git a/.config/matugen/templates/neovim/template.lua b/.config/matugen/templates/neovim/template.lua
new file mode 100644
index 0000000..395f6a1
--- /dev/null
+++ b/.config/matugen/templates/neovim/template.lua
@@ -0,0 +1,59 @@
+-- Auto-generated by Matugen
+
+require('base16-colorscheme').setup({
+ base00 = '{{colors.background.default.hex}}', -- 背景
+ base01 = '{{colors.surface_container_lowest.default.hex}}', --较浅的背景色
+ base02 = '{{colors.surface_container_low.default.hex}}',
+ base03 = '{{colors.primary.default.hex}}', -- 键盘字符,匹配大括号
+ base04 = '{{colors.on_surface_variant.default.hex}}',
+ base05 = '{{colors.primary.default.hex}}', -- 括号,运算符
+ base06 = '{{colors.inverse_on_surface.default.hex}}',
+ base07 = '{{colors.surface_bright.default.hex}}',
+
+ base08 = '{{colors.tertiary.default.hex}}',-- 变量名
+ base09 = '{{colors.secondary_fixed.default.hex}}', -- 整数、布尔值 (True/False)。
+ base0A = '{{colors.secondary.default.hex}}', --类名 (Class)、搜索匹配到的背景
+ base0B = '{{colors.primary_fixed_dim.default.hex}}', -- 字符串
+ base0C = '{{colors.tertiary_fixed_dim.default.hex}}',
+ base0D = '{{colors.primary_container.default.hex}}', -- 函数名
+ base0E = '{{colors.secondary_fixed_dim.default.hex}}', -- 关键词 (if, else, return, import)。
+ base0F = '{{colors.error.default.hex}}',
+})
+
+
+-- We first theme base16, but we also need to fix some other colors that don't
+-- contrast well by default
+
+-- Helper function to set multiple highlight groups at once
+local function set_hl_mutliple(groups, value)
+ for _, v in pairs(groups) do
+ vim.api.nvim_set_hl(0, v, value)
+ end
+end
+
+-- Make selected text stand out more
+vim.api.nvim_set_hl(0, 'Visual', {
+ bg = '{{colors.on_surface.default.hex}}', -- 选中文字背景
+ fg = '{{colors.surface.default.hex}}', -- 选中文字颜色
+})
+
+set_hl_mutliple({ 'TSComment', 'Comment' }, {
+ fg = '{{colors.outline.default.hex}}', -- 注释
+})
+
+set_hl_mutliple({ 'TSMethod', 'Method' }, {
+ fg = '{{colors.tertiary.default.hex}}',
+})
+
+set_hl_mutliple({ 'TSFunction', 'Function' }, {
+ fg = '{{colors.secondary.default.hex}}',
+})
+
+vim.api.nvim_set_hl(0, 'Keyword', {
+ fg = '{{colors.inverse_primary.default.hex}}',
+})
+
+vim.api.nvim_set_hl(0, 'MsgArea', {
+ bg = '{{colors.surface_container.default.hex}}', --底边
+ fg = '{{colors.primary.default.hex}}',
+})
diff --git a/.config/matugen/templates/niri-colors.kdl b/.config/matugen/templates/niri-colors.kdl
new file mode 100644
index 0000000..e97c133
--- /dev/null
+++ b/.config/matugen/templates/niri-colors.kdl
@@ -0,0 +1,13 @@
+layout{
+ focus-ring{
+ active-gradient from="{{colors.primary.default.hex}}cc" to="{{colors.tertiary.default.hex}}cc" angle=135
+ urgent-color "{{colors.error.default.hex}}"
+
+ }
+}
+recent-windows {
+ highlight {
+ active-color "{{colors.surface_bright.default.hex}}"
+ urgent-color "{{colors.error.default.hex}}"
+ }
+}
diff --git a/.config/matugen/templates/niriswitcher-colors.css b/.config/matugen/templates/niriswitcher-colors.css
new file mode 100644
index 0000000..860ba70
--- /dev/null
+++ b/.config/matugen/templates/niriswitcher-colors.css
@@ -0,0 +1,170 @@
+:root {
+ /* 背景 */
+ --bg-color: {{colors.surface.default.rgba | set_alpha: 0.95}};
+ /* 标题颜色 */
+ --label-color: {{colors.on_surface.default.rgba | set_alpha: 1.0}};
+ /* 右上角显示器标签文字的颜色 */
+ --alternate-label-color: {{colors.on_secondary_container.default.rgba | set_alpha: 1.0}};
+ /* 不知道是啥 */
+ --dim-label-color: rgb(142, 142, 147);
+ /* 边框 */
+ --border-color: {{colors.outline.default.rgba | set_alpha: 1.0}};
+ /* 选中窗口的背景高亮和右上角显示器标签背景的颜色 */
+ --highlight-color: {{colors.surface_bright.default.rgba | set_alpha: 0.8}};
+ /* 不知道是啥 */
+ --urgency-color: {{colors.error.default.rgba | set_alpha: 1.0}};
+ /* 左边显示的当前工作区的指示器的颜色 */
+ --indicator-focus-color: {{colors.primary.default.rgba | set_alpha: 0.95}};
+ /* 非当前工作区指示器的颜色 */
+ --indicator-color: rgba(58, 58, 60, .95);
+}
+
+
+#niriswitcher.background {
+ background-color: transparent;
+}
+
+#niriswitcher {on_surface
+ background-color: transparent;
+ padding: 40px;
+}
+
+#main-view {
+ background-color: var(--bg-color);
+ border-radius: 22px;
+ border: 1px solid var(--border-color);
+ padding: 10px 20px 10px;
+ box-shadow: 0 0 20px 5px rgba(0,0,0,.3),
+ 0 0 13px 8px rgba(0,0,0,.2);
+}
+
+.workspace scrollbar, .workspace scrollbar * {
+ background-color: transparent;
+ min-width: 0px;
+ min-height: 0px;
+ opacity: 0;
+}
+
+.workspace scrollbar,
+.workspace scrollbar slider {
+ background: transparent;
+ min-width: 6px;
+ min-height: 6px;
+}
+
+
+#application-title {
+ background: transparent;
+ color: var(--label-color);
+ transition: all 0.2s ease-in-out;
+}
+
+#workspace-name {
+ transition: all 0.2s ease-in-out;
+ background-color: var(--highlight-color);
+ color: var(--alternate-label-color);
+ border-radius: 22px;
+ padding: 3px 9px;
+}
+
+
+#workspaces {
+ margin: 5px 10px 5px;
+}
+
+.workspace-indicator {
+ background-color: var(--indicator-color);
+ transition: background 200ms 20ms;
+ margin:0;
+}
+
+.workspace-indicator:first-child {
+ border-radius: 20% 20% 0 0;
+}
+
+.workspace-indicator:last-child {
+ border-radius: 0 0 20% 20%;
+}
+
+.workspace-indicator.selected {
+ background-color: var(--indicator-focus-color);
+}
+
+.workspace-indicator:hover {
+ background-color: var(--indicator-focus-color);
+}
+
+#workspace-indicators {
+ background: transparent;
+ margin-top: 22px;
+ margin-bottom: 22px;
+ margin-right: 2px;
+}
+
+
+.application {
+ background-color: transparent;
+}
+
+.application-icon {
+ transition: -gtk-icon-filter 0.2s ease-in-out;
+ padding: 10px 15px 10px;
+ -gtk-icon-shadow: 0 1px 1px hsl(0deg 0% 0% / 0.075),
+ 0 2px 2px hsl(0deg 0% 0% / 0.075),
+ 0 4px 4px hsl(0deg 0% 0% / 0.075),
+ 0 8px 8px hsl(0deg 0% 0% / 0.075),
+ 0 16px 16px hsl(0deg 0% 0% / 0.075);
+}
+
+.application-name {
+ transition: opacity 0.2s ease;
+ opacity: 0;
+ color: var(--dim-label-color);
+ margin-top: 3px;
+}
+
+.application.selected .application-name {
+ opacity: 1;
+ color: var(--label-color);
+}
+
+.application.urgent .application-icon {
+ animation-timing-function: linear;
+ animation: urgency-pulse-animation 2.5s infinite;
+}
+
+@keyframes urgency-pulse-animation {
+ 0% {
+ -gtk-icon-filter: drop-shadow(0 0 2px var(--urgency-color));
+ }
+
+ 25% {
+ -gtk-icon-filter: drop-shadow(0 0 5px var(--urgency-color));
+ }
+
+ 50% {
+ -gtk-icon-filter: drop-shadow(0 0 10px var(--urgency-color));
+ }
+
+ 75% {
+ -gtk-icon-filter: drop-shadow(0 0 5px var(--urgency-color));
+ }
+
+ 100% {
+ -gtk-icon-filter: drop-shadow(0 0 2px var(--urgency-color));
+ }
+}
+
+.application.focused .application-name {
+ opacity: 1;
+ color: var(--dim-label-color);
+}
+
+.application.selected .application-icon {
+ transition: background-color 0.1s ease-in;
+ border-radius: 10%;
+ background-color: var(--highlight-color);
+}
+
+@import "/home/shorin/.config/niriswitcher/colors.css";
+
diff --git a/.config/matugen/templates/pywalfox-colors.json b/.config/matugen/templates/pywalfox-colors.json
new file mode 100755
index 0000000..9ddf17f
--- /dev/null
+++ b/.config/matugen/templates/pywalfox-colors.json
@@ -0,0 +1,22 @@
+{
+ "wallpaper": "{{image}}",
+ "alpha": "100",
+ "colors": {
+ "color0": "{{colors.background.default.hex}}",
+ "color1": "",
+ "color2": "",
+ "color3": "",
+ "color4": "",
+ "color5": "",
+ "color6": "",
+ "color7": "",
+ "color8": "",
+ "color9": "",
+ "color10": "{{colors.primary.default.hex}}",
+ "color11": "",
+ "color12": "",
+ "color13": "{{colors.surface_bright.default.hex}}",
+ "color14": "",
+ "color15": "{{colors.on_surface.default.hex}}"
+ }
+}
diff --git a/.config/matugen/templates/qtct-colors.conf b/.config/matugen/templates/qtct-colors.conf
new file mode 100755
index 0000000..5d35cb4
--- /dev/null
+++ b/.config/matugen/templates/qtct-colors.conf
@@ -0,0 +1,5 @@
+[ColorScheme]
+active_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, #ffffff, #cacaca, #9f9f9f, #b8b8b8, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface.default.hex}}, {{colors.scrim.default.hex}}, {{colors.surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.secondary.default.hex}}
+disabled_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, #ffffff, #cacaca, #9f9f9f, #b8b8b8, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface.default.hex}}, {{colors.scrim.default.hex}}, {{colors.surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.secondary.default.hex}}
+inactive_colors={{colors.on_background.default.hex}}, {{colors.surface.default.hex}}, #ffffff, #cacaca, #9f9f9f, #b8b8b8, {{colors.on_background.default.hex}}, #ffffff, {{colors.on_surface.default.hex}}, {{colors.background.default.hex}}, {{colors.background.default.hex}}, {{colors.shadow.default.hex}}, {{colors.primary_container.default.hex}}, {{colors.on_primary_container.default.hex}}, {{colors.secondary.default.hex}}, {{colors.primary.default.hex}}, {{colors.surface.default.hex}}, {{colors.scrim.default.hex}}, {{colors.surface.default.hex}}, {{colors.on_surface.default.hex}}, {{colors.secondary.default.hex}}
+
diff --git a/.config/matugen/templates/starship-colors.toml b/.config/matugen/templates/starship-colors.toml
new file mode 100755
index 0000000..5d6053c
--- /dev/null
+++ b/.config/matugen/templates/starship-colors.toml
@@ -0,0 +1,181 @@
+"$schema" = 'https://starship.rs/config-schema.json'
+format = """
+[](color_orange)\
+$os\
+$username\
+[](bg:color_yellow fg:color_orange)\
+$directory\
+[](fg:color_yellow bg:color_aqua)\
+$git_branch\
+$git_status\
+[](fg:color_aqua bg:color_blue)\
+$c\
+$cpp\
+$rust\
+$golang\
+$nodejs\
+$php\
+$java\
+$kotlin\
+$haskell\
+$python\
+[](fg:color_blue bg:color_bg3)\
+$docker_context\
+$conda\
+$pixi\
+[](fg:color_bg3 bg:color_bg1)\
+$time\
+[ ](fg:color_bg1)\
+$line_break$character"""
+palette = 'colors'
+
+[palettes.colors]
+mustard = '#af8700'
+color_orange = '{{colors.primary_fixed_dim.default.hex}}'
+color_fg0 = '{{colors.on_primary.default.hex}}'
+color_fg1 = '{{colors.on_surface.default.hex}}'
+color_purple = '{{colors.on_tertiary_container.default.hex}}'
+color_bg3 = '{{colors.secondary.default.hex}}'
+color_green = '{{colors.on_primary.default.hex}}'
+color_bg1 = '{{colors.secondary_container.default.hex}}'
+color_blue = '{{colors.inverse_primary.default.hex}}'
+color_red = '{{colors.primary.default.hex}}'
+color_aqua = '{{colors.on_secondary_container.default.hex}}'
+color_yellow = '{{colors.tertiary.default.hex}}'
+
+[os]
+disabled = false
+style = "bg:color_orange fg:color_fg0"
+
+[os.symbols]
+Windows = ""
+Ubuntu = ""
+SUSE = ""
+Raspbian = ""
+Mint = ""
+Macos = ""
+Manjaro = ""
+Linux = ""
+Gentoo = ""
+Fedora = ""
+Alpine = ""
+Amazon = ""
+Android = ""
+Arch = ""
+Artix = ""
+EndeavourOS = ""
+CentOS = ""
+Debian = ""
+Redhat = ""
+RedHatEnterprise = ""
+Pop = ""
+
+[username]
+show_always = true
+style_user = "bg:color_orange fg:color_fg0"
+style_root = "bg:color_orange fg:color_fg0"
+format = '[ $user ]($style)'
+
+[directory]
+style = "fg:color_fg0 bg:color_yellow"
+format = "[ $path ]($style)"
+truncation_length = 3
+truncation_symbol = "…/"
+
+[directory.substitutions]
+"Documents" = " "
+"Downloads" = " "
+"Music" = " "
+"Pictures" = " "
+"Developer" = " "
+
+[git_branch]
+symbol = ""
+style = "bg:color_aqua"
+format = '[[ $symbol $branch ](fg:color_fg0 bg:color_aqua)]($style)'
+
+[git_status]
+style = "bg:color_aqua"
+format = '[[($all_status$ahead_behind )](fg:color_fg0 bg:color_aqua)]($style)'
+
+[nodejs]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[c]
+symbol = " "
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[cpp]
+symbol = " "
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[rust]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[golang]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[php]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[java]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[kotlin]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg1 bg:color_blue)]($style)'
+
+[haskell]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[python]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[docker_context]
+symbol = ""
+style = "bg:color_bg3"
+format = '[[ $symbol( $context) ](fg:#83a598 bg:color_bg3)]($style)'
+
+[conda]
+style = "bg:color_bg3"
+format = '[[ $symbol( $environment) ](fg:#83a598 bg:color_bg3)]($style)'
+
+[pixi]
+style = "bg:color_bg3"
+format = '[[ $symbol( $version)( $environment) ](fg:color_fg0 bg:color_bg3)]($style)'
+
+[time]
+disabled = false
+time_format = "%R"
+style = "bg:color_bg1"
+format = '[[ $time ](fg:color_fg1 bg:color_bg1)]($style)'
+
+[line_break]
+disabled = false
+
+[character]
+disabled = false
+success_symbol = '[](bold fg:color_green)'
+error_symbol = '[](bold fg:color_red)'
+vimcmd_symbol = '[](bold fg:color_green)'
+vimcmd_replace_one_symbol = '[](bold fg:color_purple)'
+vimcmd_replace_symbol = '[](bold fg:color_purple)'
+vimcmd_visual_symbol = '[](bold fg:color_yellow)'
+
diff --git a/.config/matugen/templates/style.css b/.config/matugen/templates/style.css
new file mode 100644
index 0000000..1595b48
--- /dev/null
+++ b/.config/matugen/templates/style.css
@@ -0,0 +1,158 @@
+:root {
+ --bg-color: {{colors.tertiary.default.rgb}};
+ --label-color: {{colors.tertiary.default.rgb}};
+ --alternate-label-color: {{colors.tertiary.default.rgb}};
+ --dim-label-color: {{colors.tertiary.default.rgb}};
+ --border-color: rgba(72, 72, 74, .95);
+ --highlight-color: rgba(99,99,102,0.95);
+ --urgency-color: {{colors.tertiary.default.rgb}};
+ --indicator-focus-color: rgba(10, 132, 255, 0.95);
+ --indicator-color: rgba(58, 58, 60, .95);
+}
+#niriswitcher.background {
+ background-color: transparent;
+}
+
+#niriswitcher {
+ background-color: transparent;
+ padding: 40px;
+}
+
+#main-view {
+ background-color: var(--bg-color);
+ border-radius: 22px;
+ border: 1px solid var(--border-color);
+ padding: 10px 20px 10px;
+ box-shadow: 0 0 20px 5px rgba(0,0,0,.3),
+ 0 0 13px 8px rgba(0,0,0,.2);
+}
+
+.workspace scrollbar, .workspace scrollbar * {
+ background-color: transparent;
+ min-width: 0px;
+ min-height: 0px;
+ opacity: 0;
+}
+
+.workspace scrollbar,
+.workspace scrollbar slider {
+ background: transparent;
+ min-width: 6px;
+ min-height: 6px;
+}
+
+
+#application-title {
+ background: transparent;
+ color: var(--label-color);
+ transition: all 0.2s ease-in-out;
+}
+
+#workspace-name {
+ transition: all 0.2s ease-in-out;
+ background-color: var(--highlight-color);
+ color: var(--alternate-label-color);
+ border-radius: 22px;
+ padding: 3px 9px;
+}
+
+
+#workspaces {
+ margin: 5px 10px 5px;
+}
+
+.workspace-indicator {
+ background-color: var(--indicator-color);
+ transition: background 200ms 20ms;
+ margin:0;
+}
+
+.workspace-indicator:first-child {
+ border-radius: 20% 20% 0 0;
+}
+
+.workspace-indicator:last-child {
+ border-radius: 0 0 20% 20%;
+}
+
+.workspace-indicator.selected {
+ background-color: var(--indicator-focus-color);
+}
+
+.workspace-indicator:hover {
+ background-color: var(--indicator-focus-color);
+}
+
+#workspace-indicators {
+ background: transparent;
+ margin-top: 22px;
+ margin-bottom: 22px;
+ margin-right: 2px;
+}
+
+
+.application {
+ background-color: transparent;
+}
+
+.application-icon {
+ transition: -gtk-icon-filter 0.2s ease-in-out;
+ padding: 10px 15px 10px;
+ -gtk-icon-shadow: 0 1px 1px hsl(0deg 0% 0% / 0.075),
+ 0 2px 2px hsl(0deg 0% 0% / 0.075),
+ 0 4px 4px hsl(0deg 0% 0% / 0.075),
+ 0 8px 8px hsl(0deg 0% 0% / 0.075),
+ 0 16px 16px hsl(0deg 0% 0% / 0.075);
+}
+
+.application-name {
+ transition: opacity 0.2s ease;
+ opacity: 0;
+ color: var(--dim-label-color);
+ margin-top: 3px;
+}
+
+.application.selected .application-name {
+ opacity: 1;
+ color: var(--label-color);
+}
+
+.application.urgent .application-icon {
+ animation-timing-function: linear;
+ animation: urgency-pulse-animation 2.5s infinite;
+}
+
+@keyframes urgency-pulse-animation {
+ 0% {
+ -gtk-icon-filter: drop-shadow(0 0 2px var(--urgency-color));
+ }
+
+ 25% {
+ -gtk-icon-filter: drop-shadow(0 0 5px var(--urgency-color));
+ }
+
+ 50% {
+ -gtk-icon-filter: drop-shadow(0 0 10px var(--urgency-color));
+ }
+
+ 75% {
+ -gtk-icon-filter: drop-shadow(0 0 5px var(--urgency-color));
+ }
+
+ 100% {
+ -gtk-icon-filter: drop-shadow(0 0 2px var(--urgency-color));
+ }
+}
+
+.application.focused .application-name {
+ opacity: 1;
+ color: var(--dim-label-color);
+}
+
+.application.selected .application-icon {
+ transition: background-color 0.1s ease-in;
+ border-radius: 10%;
+ background-color: var(--highlight-color);
+}
+
+
diff --git a/.config/matugen/templates/swaylock-colors b/.config/matugen/templates/swaylock-colors
new file mode 100644
index 0000000..1076419
--- /dev/null
+++ b/.config/matugen/templates/swaylock-colors
@@ -0,0 +1,19 @@
+screenshots
+clock
+indicator
+indicator-radius=200
+indicator-thickness=15
+effect-blur=10x5
+ring-color={{colors.primary_container.default.hex}}
+key-hl-color={{colors.primary.default.hex}}
+line-color={{colors.outline.default.hex}}
+inside-color={{colors.surface_container.default.hex}}
+separator-color={{colors.primary_container.default.hex}}
+ring-ver-color={{colors.tertiary_container.default.hex}}
+inside-ver-color={{colors.tertiary.default.hex}}
+text-ver-color={{colors.on_tertiary.default.hex}}
+line-ver-color={{colors.outline.default.hex}}
+ring-wrong-color={{colors.error_container.default.hex}}
+inside-wrong-color={{colors.error.default.hex}}
+text-wrong-color={{colors.on_error.default.hex}}
+line-wrong-color={{colors.outline.default.hex}}
diff --git a/.config/matugen/templates/swaync-colors.css b/.config/matugen/templates/swaync-colors.css
new file mode 100755
index 0000000..6f74ea1
--- /dev/null
+++ b/.config/matugen/templates/swaync-colors.css
@@ -0,0 +1,5 @@
+:root {
+ <* for name, value in colors *>
+--{{name}}: {{value.default.hex}};
+<* endfor *>
+}
diff --git a/.config/matugen/templates/wlogout/icons/hibernate.png b/.config/matugen/templates/wlogout/icons/hibernate.png
new file mode 100644
index 0000000..a6322aa
Binary files /dev/null and b/.config/matugen/templates/wlogout/icons/hibernate.png differ
diff --git a/.config/matugen/templates/wlogout/icons/lock.png b/.config/matugen/templates/wlogout/icons/lock.png
new file mode 100644
index 0000000..f0b1eaf
Binary files /dev/null and b/.config/matugen/templates/wlogout/icons/lock.png differ
diff --git a/.config/matugen/templates/wlogout/icons/logout.png b/.config/matugen/templates/wlogout/icons/logout.png
new file mode 100644
index 0000000..345a8aa
Binary files /dev/null and b/.config/matugen/templates/wlogout/icons/logout.png differ
diff --git a/.config/matugen/templates/wlogout/icons/reboot.png b/.config/matugen/templates/wlogout/icons/reboot.png
new file mode 100644
index 0000000..29cfa2f
Binary files /dev/null and b/.config/matugen/templates/wlogout/icons/reboot.png differ
diff --git a/.config/matugen/templates/wlogout/icons/shutdown.png b/.config/matugen/templates/wlogout/icons/shutdown.png
new file mode 100644
index 0000000..4d7d499
Binary files /dev/null and b/.config/matugen/templates/wlogout/icons/shutdown.png differ
diff --git a/.config/matugen/templates/wlogout/icons/suspend.png b/.config/matugen/templates/wlogout/icons/suspend.png
new file mode 100644
index 0000000..647bd66
Binary files /dev/null and b/.config/matugen/templates/wlogout/icons/suspend.png differ
diff --git a/.config/matugen/templates/wlogout/recolor.sh b/.config/matugen/templates/wlogout/recolor.sh
new file mode 100755
index 0000000..6df12d7
--- /dev/null
+++ b/.config/matugen/templates/wlogout/recolor.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+# ==========================================
+# 配置区域
+# ==========================================
+# 源图标目录 (Matugen 模板目录)
+SRC_DIR="$HOME/.config/matugen/templates/wlogout/icons"
+
+# 目标图标目录 (实际生效目录)
+DEST_DIR="$HOME/.config/wlogout/icons"
+
+# ==========================================
+# 脚本逻辑
+# ==========================================
+
+# 1. 获取目标颜色参数
+# 我们期望在运行脚本时传入颜色,例如: ./recolor_icons.sh "#ff0000"
+TARGET_COLOR="{{colors.primary.default.hex}}"
+
+# 检查是否提供了颜色参数
+if [ -z "$TARGET_COLOR" ]; then
+ echo "错误: 未提供目标颜色。"
+ echo "用法: $0 <十六进制颜色代码>"
+ echo "示例: $0 \"#ff0000\""
+ exit 1
+fi
+
+# 检查 ImageMagick 是否安装
+if ! command -v magick &> /dev/null; then
+ echo "错误: 未找到 ImageMagick (magick 命令)。请先安装它。"
+ exit 1
+fi
+
+# 检查源目录是否存在
+if [ ! -d "$SRC_DIR" ]; then
+ echo "错误: 源目录不存在: $SRC_DIR"
+ exit 1
+fi
+
+echo "开始处理图标..."
+echo "源目录: $SRC_DIR"
+echo "目标目录: $DEST_DIR"
+echo "应用颜色: $TARGET_COLOR"
+
+# 2. 确保目标目录存在
+# 如果不存在则创建它 (使用 -p 选项,如果已存在也不会报错)
+mkdir -p "$DEST_DIR"
+
+# 3. 循环处理源目录下的所有 PNG 文件
+# 使用 find 命令查找,并配合 while 循环处理,可以安全处理文件名中的特殊字符
+find "$SRC_DIR" -maxdepth 1 -name "*.png" -print0 | while IFS= read -r -d '' img_path; do
+ # 获取文件名 (例如 icon.png)
+ filename=$(basename "$img_path")
+ # 构建目标文件路径
+ dest_path="$DEST_DIR/$filename"
+
+ echo -n "正在处理: $filename ... "
+
+ # 执行 ImageMagick 命令 (核心逻辑)
+ # 1. 读取原图
+ # 2. 转为灰度 (-colorspace Gray)
+ # 3. 设置填充颜色 (-fill "$TARGET_COLOR")
+ # 4. 应用着色 (-tint 100%)
+ # 5. 输出到目标路径
+ magick "$img_path" \
+ -colorspace Gray \
+ -fill "$TARGET_COLOR" \
+ -tint 100% \
+ "$dest_path"
+
+ if [ $? -eq 0 ]; then
+ echo "完成。"
+ else
+ echo "失败!"
+ fi
+done
+
+echo "所有图标处理完毕。"
\ No newline at end of file
diff --git a/.config/matugen/templates/yazi-theme.toml b/.config/matugen/templates/yazi-theme.toml
new file mode 100644
index 0000000..b9db1a9
--- /dev/null
+++ b/.config/matugen/templates/yazi-theme.toml
@@ -0,0 +1,174 @@
+# : Manager [[[
+
+[mgr]
+cwd = { fg = "{{colors.on_surface.default.hex}}" }
+
+# Find
+find_keyword = { fg = "{{colors.error.default.hex}}", bold = true, italic = true, underline = true }
+find_position = { fg = "{{colors.error.default.hex}}", bold = true, italic = true }
+
+# Marker
+marker_copied = { fg = "{{colors.tertiary_fixed.default.hex | auto_lightness: 20.0}}", bg = "{{colors.tertiary_fixed.default.hex | auto_lightness: 20.0}}" }
+marker_cut = { fg = "{{colors.tertiary_fixed.default.hex}}", bg = "{{colors.tertiary_fixed.default.hex}}" }
+marker_marked = { fg = "{{colors.error.default.hex}}", bg = "{{colors.error.default.hex}}" }
+marker_selected = { fg = "{{colors.tertiary.default.hex}}", bg = "{{colors.tertiary.default.hex}}" }
+
+# Count
+count_copied = { fg = "{{colors.on_tertiary_fixed.default.hex}}", bg = "{{colors.tertiary_fixed.default.hex}}" }
+count_cut = { fg = "{{colors.on_tertiary_fixed.default.hex}}", bg = "{{colors.tertiary_fixed.default.hex}}" }
+count_selected = { fg = "{{colors.on_primary.default.hex}}", bg = "{{colors.tertiary.default.hex}}" }
+
+# Border
+border_symbol = "│"
+border_style = { fg = "{{colors.surface_tint.default.hex}}" }
+
+# : ]]]
+
+
+# : Tabs (New Section) [[[
+
+[tabs]
+active = { fg = "{{colors.on_primary.default.hex}}", bg = "{{colors.primary.default.hex}}", bold = true }
+inactive = { fg = "{{colors.primary_fixed.default.hex}}", bg = "{{colors.on_primary_fixed.default.hex}}" }
+
+# : ]]]
+
+
+# : Mode [[[
+
+[mode]
+# Mode
+normal_main = { bg = "{{colors.primary.default.hex}}", fg = "{{colors.on_primary.default.hex}}", bold = true }
+normal_alt = { bg = "{{colors.surface_variant.default.hex}}", fg = "{{colors.on_surface_variant.default.hex}}" }
+
+# Select mode
+select_main = { bg = "{{colors.secondary.default.hex}}", fg = "{{colors.on_secondary.default.hex}}", bold = true }
+select_alt = { bg = "{{colors.surface_variant.default.hex}}", fg = "{{colors.on_surface_variant.default.hex}}" }
+
+# Unset mode
+unset_main = { bg = "{{colors.tertiary.default.hex}}", fg = "{{colors.on_tertiary.default.hex}}", bold = true }
+unset_alt = { bg = "{{colors.surface_variant.default.hex}}", fg = "{{colors.on_surface_variant.default.hex}}" }
+
+# : ]]]
+
+
+# : Status [[[
+
+[status]
+sep_left = { open = "🭁", close = "🭠" }
+sep_right = { open = "🭁", close = "🭠" }
+
+# Progress
+progress_label = { bold = true }
+progress_normal = { fg = "{{colors.primary.default.hex}}", bg = "{{colors.surface_bright.default.hex}}" }
+progress_error = { fg = "{{colors.error.default.hex}}", bg = "{{colors.surface_bright.default.hex}}" }
+
+# Permissions
+perm_type = { fg = "{{colors.secondary.default.hex | auto_lightness: 30.0}}" }
+perm_write = { fg = "{{colors.tertiary.default.hex | auto_lightness: 30.0}}" }
+perm_read = { fg = "{{colors.error.default.hex | auto_lightness: 30.0}}" }
+perm_exec = { fg = "{{colors.tertiary_fixed.default.hex | auto_lightness: 30.0}}" }
+perm_sep = { fg = "{{colors.primary_fixed.default.hex | auto_lightness: 30.0}}" }
+
+# : ]]]
+
+
+# : Picker (Renamed from Select) [[[
+
+[pick]
+border = { fg = "{{colors.primary.default.hex}}" }
+active = { fg = "{{colors.tertiary.default.hex}}", bold = true }
+inactive = {}
+
+# : ]]]
+
+
+# : Input [[[
+
+[input]
+border = { fg = "{{colors.primary.default.hex}}" }
+value = { fg = "{{colors.on_surface.default.hex}}" }
+
+# : ]]]
+
+
+# : Completion (Renamed from Completion) [[[
+
+[cmp]
+border = { fg = "{{colors.primary.default.hex}}", bg = "{{colors.on_primary.default.hex}}" }
+
+# : ]]]
+
+
+# : Tasks [[[
+
+[tasks]
+border = { fg = "{{colors.primary.default.hex}}" }
+title = {}
+hovered = { fg = "{{colors.tertiary_fixed.default.hex}}", underline = true }
+
+# : ]]]
+
+
+# : Which [[[
+
+[which]
+cols = 3
+mask = { bg = "{{colors.surface_bright.default.hex}}" }
+cand = { fg = "{{colors.primary.default.hex}}" }
+rest = { fg = "{{colors.on_primary.default.hex}}" }
+desc = { fg = "{{colors.on_surface.default.hex}}" }
+separator = " ▶ "
+separator_style = { fg = "{{colors.on_surface.default.hex}}" }
+
+# : ]]]
+
+
+# : Help [[[
+
+[help]
+on = { fg = "{{colors.on_surface.default.hex}}" }
+run = { fg = "{{colors.on_surface.default.hex}}" }
+footer = { fg = "{{colors.on_secondary.default.hex}}", bg = "{{colors.secondary.default.hex}}" }
+
+# : ]]]
+
+
+# : Notify [[[
+
+[notify]
+title_info = { fg = "{{colors.tertiary.default.hex}}" }
+title_warn = { fg = "{{colors.primary.default.hex}}" }
+title_error = { fg = "{{colors.error.default.hex}}" }
+
+# : ]]]
+
+
+# : File-specific styles [[[
+
+[filetype]
+
+rules = [
+ # Images
+ { mime = "image/*", fg = "#94e2d5" },
+
+ # Media
+ { mime = "{audio,video}/*", fg = "#f9e2af" },
+
+ # Archives
+ { mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#f5c2e7" },
+
+ # Documents
+ { mime = "application/{pdf,doc,rtf}", fg = "#a6e3a1" },
+
+ # Special files
+ { url = "*", is = "orphan", bg = "{{colors.error_container.default.hex}}" },
+ { url = "*", is = "exec", fg = "{{colors.on_error_container.default.hex}}" },
+
+ # Fallback
+ { url = "*", fg = "{{colors.on_surface.default.hex}}" },
+ { url = "*/", fg = "{{colors.surface_tint.default.hex}}" },
+]
+
+# : ]]]
+
diff --git a/.config/niri/colors.kdl b/.config/niri/colors.kdl
new file mode 100644
index 0000000..7e7c02f
--- /dev/null
+++ b/.config/niri/colors.kdl
@@ -0,0 +1,13 @@
+layout{
+ focus-ring{
+ active-gradient from="#dcc66ecc" to="#aad0b3cc" angle=135
+ urgent-color "#ffb4ab"
+
+ }
+}
+recent-windows {
+ highlight {
+ active-color "#3c3930"
+ urgent-color "#ffb4ab"
+ }
+}
diff --git a/.config/niri/config.kdl b/.config/niri/config.kdl
new file mode 100644
index 0000000..badf714
--- /dev/null
+++ b/.config/niri/config.kdl
@@ -0,0 +1,670 @@
+// 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
+
+environment {
+// LANG "zh_CN.UTF-8"
+// LC_CTYPE "en_US.UTF-8"
+ // qt主题
+ QT_QPA_PLATFORMTHEME "qt6ct"
+}
+cursor {
+ // 主题,存放路径在~/.local/share/icons
+ //xcursor-theme "breeze_cursors"
+ // 大小
+ xcursor-size 32
+ // 闲置多少毫秒自动隐藏光标
+ hide-after-inactive-ms 15000
+}
+// Input device configuration.
+// Find the full list of options on the wiki:
+// https://yalter.github.io/niri/Configuration:-Input
+
+include "colors.kdl"
+input {
+ keyboard {
+ xkb {
+ // You can set rules, model, layout, variant and options.
+ // For more information, see xkeyboard-config(7).
+
+ // For example:
+ // layout "us,ru"
+ // 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
+ // accel-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-follows-mouse
+
+ // 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" {
+ mode "2560x1600@240.000"
+ scale 1.25
+ position x=0 y=0
+ focus-at-startup
+}
+/-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 "1920x1080@120.030"
+
+ // 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 12
+
+ // 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.
+ // 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 3
+
+ // 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 20
+
+ // Spread expands the shadow.
+ spread 2
+
+ // Offset moves the shadow relative to the window.
+ offset x=-4 y=-4
+
+ // 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"
+spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
+spawn-at-startup "mako"
+spawn-at-startup "swww-daemon"
+spawn-at-startup "nm-applet"
+spawn-sh-at-startup "xrdb -merge /home/zhenyan121/.Xresources"
+spawn-sh-at-startup "clipse --listen"
+
+// 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
+}
+
+// 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.
+ match 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$"
+ match app-id="waypaper"
+ 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
+}
+window-rule {
+ //圆角
+ geometry-corner-radius 12
+ //剪掉圆角外的窗口内容
+ clip-to-geometry true
+ //透明度
+ opacity 0.99
+ //禁止边框画到窗口后面
+ draw-border-with-background false
+}
+
+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; }
+ Mod+F12 {spawn-sh "pkill waybar || true && waybar";}
+ Mod+B {spawn "firefox"; }
+ Mod+Alt+V {spawn-sh "kitty -e clipse";}
+
+ Mod+Alt+W {spawn "waypaper";}
+ // Suggested binds for running programs: terminal, app launcher, screen locker.
+ Mod+T hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
+ Mod+D hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; }
+ Mod+E { spawn "nautilus";}
+ 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+Q repeat=false { close-window; }
+
+ 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+Ctrl+Left { move-column-left; }
+ Mod+Ctrl+Down { move-window-down; }
+ Mod+Ctrl+Up { move-window-up; }
+ Mod+Ctrl+Right { move-column-right; }
+ Mod+Ctrl+H { move-column-left; }
+ Mod+Ctrl+J { move-window-down; }
+ Mod+Ctrl+K { move-window-up; }
+ Mod+Ctrl+L { move-column-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+Shift+Left { focus-monitor-left; }
+ Mod+Shift+Down { focus-monitor-down; }
+ Mod+Shift+Up { focus-monitor-up; }
+ Mod+Shift+Right { focus-monitor-right; }
+ Mod+Shift+H { focus-monitor-left; }
+ Mod+Shift+J { focus-monitor-down; }
+ Mod+Shift+K { focus-monitor-up; }
+ Mod+Shift+L { focus-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+Page_Down { focus-workspace-down; }
+ Mod+Page_Up { focus-workspace-up; }
+ Mod+U { focus-workspace-down; }
+ Mod+I { focus-workspace-up; }
+ Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
+ Mod+Ctrl+Page_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+Alt+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+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+Alt+A { 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; }
+}
+// 隐藏窗口标题栏
+prefer-no-csd
diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua
new file mode 100644
index 0000000..3ff3a44
--- /dev/null
+++ b/.config/nvim/init.lua
@@ -0,0 +1,8 @@
+require("config.lazy")
+-- 基础缩进设置
+vim.opt.tabstop = 4 -- 1个Tab显示为4个空格
+vim.opt.shiftwidth = 4 -- 自动缩进时缩进4个空格
+vim.opt.expandtab = true -- 把Tab键变成空格(现代编程通用习惯)
+vim.opt.softtabstop = 4 -- 编辑模式下按退格键退回4个空格
+-- 显示行数
+vim.opt.number = true
diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json
new file mode 100644
index 0000000..7cbbbc2
--- /dev/null
+++ b/.config/nvim/lazy-lock.json
@@ -0,0 +1,16 @@
+{
+ "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" },
+ "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
+ "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" },
+ "mason-lspconfig.nvim": { "branch": "main", "commit": "4cfe411526a7a99c18281135e8b4765ae6330d15" },
+ "mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" },
+ "nvim-autopairs": { "branch": "master", "commit": "c2a0dd0d931d0fb07665e1fedb1ea688da3b80b4" },
+ "nvim-cmp": { "branch": "main", "commit": "85bbfad83f804f11688d1ab9486b459e699292d6" },
+ "nvim-lspconfig": { "branch": "master", "commit": "ac04ec3c2af08e9821b4eb64ede86072b9b213bf" },
+ "nvim-tree.lua": { "branch": "master", "commit": "321bc61580fd066b76861c32de3319c3a6d089e7" },
+ "nvim-treesitter": { "branch": "main", "commit": "31fc7e10cd7c1fd7717b439050d0f91c2c4f0a4b" },
+ "nvim-web-devicons": { "branch": "master", "commit": "6788013bb9cb784e606ada44206b0e755e4323d7" },
+ "ouroboros": { "branch": "master", "commit": "f528c0baf0b872b37036c166a144abcfc4752ec9" },
+ "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
+ "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }
+}
diff --git a/.config/nvim/lua/config/lazy.lua b/.config/nvim/lua/config/lazy.lua
new file mode 100644
index 0000000..0b93d4e
--- /dev/null
+++ b/.config/nvim/lua/config/lazy.lua
@@ -0,0 +1,35 @@
+-- Bootstrap lazy.nvim
+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)
+
+-- Make sure to setup `mapleader` and `maplocalleader` before
+-- loading lazy.nvim so that mappings are correct.
+-- This is also a good place to setup other settings (vim.opt)
+vim.g.mapleader = " "
+vim.g.maplocalleader = "\\"
+
+-- Setup lazy.nvim
+require("lazy").setup({
+ spec = {
+ -- import your plugins
+ { import = "plugins" },
+ },
+ -- Configure any other settings here. See the documentation for more details.
+ -- colorscheme that will be used when installing plugins.
+ install = { colorscheme = { "habamax" } },
+ -- automatically check for plugin updates
+ checker = { enabled = false },
+})
diff --git a/.config/nvim/lua/plugins/autopairs.lua b/.config/nvim/lua/plugins/autopairs.lua
new file mode 100644
index 0000000..4847675
--- /dev/null
+++ b/.config/nvim/lua/plugins/autopairs.lua
@@ -0,0 +1,5 @@
+return {
+ "windwp/nvim-autopairs",
+ event = "InsertEnter", -- 只有进入插入模式时才加载,节省性能
+ config = true -- 相当于调用 require("nvim-autopairs").setup({})
+}
diff --git a/.config/nvim/lua/plugins/colorscheme.lua b/.config/nvim/lua/plugins/colorscheme.lua
new file mode 100644
index 0000000..b827acb
--- /dev/null
+++ b/.config/nvim/lua/plugins/colorscheme.lua
@@ -0,0 +1,11 @@
+-- ~/.config/nvim/lua/plugins/colorscheme.lua
+return {
+ {
+ "folke/tokyonight.nvim",
+ lazy = false, -- 我们希望启动就加载
+ priority = 1000, -- 高优先级,确保先于其他插件加载
+ config = function()
+ vim.cmd.colorscheme("tokyonight-night") -- 加载后,立即设置这个主题
+ end,
+ }
+}
diff --git a/.config/nvim/lua/plugins/lsp.lua b/.config/nvim/lua/plugins/lsp.lua
new file mode 100644
index 0000000..0095341
--- /dev/null
+++ b/.config/nvim/lua/plugins/lsp.lua
@@ -0,0 +1,131 @@
+return {
+ {
+ "neovim/nvim-lspconfig",
+ dependencies = {
+ "williamboman/mason.nvim",
+ "williamboman/mason-lspconfig.nvim",
+ "hrsh7th/nvim-cmp",
+ "hrsh7th/cmp-nvim-lsp",
+ },
+ config = function()
+ -- 1. 初始化 Mason (包管理器)
+ require("mason").setup({
+ ui = { border = "rounded" }
+ })
+
+ -- 2. 配置 mason-lspconfig (自动安装LSP服务器)
+ require("mason-lspconfig").setup({
+ ensure_installed = { "clangd", "lua_ls" },
+ -- 【重要】新框架下,mason-lspconfig 会自动处理安装和配置
+ -- 你不再需要手动调用 `require('lspconfig').xxx.setup()`
+ })
+
+ -- 3. 通用配置:快捷键与能力集
+ local on_attach = function(client, bufnr)
+ local opts = { buffer = bufnr, noremap = true, silent = true }
+ -- 按键映射
+ vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
+ vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
+ vim.keymap.set('n', 'rn', vim.lsp.buf.rename, opts)
+ vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, opts)
+ vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
+ end
+
+ -- 获取自动补全的能力集
+ local capabilities = require('cmp_nvim_lsp').default_capabilities()
+
+ -- 4. 【核心修改】新版 LSP 配置框架
+ -- 全局配置表,mason-lspconfig 会自动将这里定义的配置应用到对应服务器
+ vim.lsp.config = vim.lsp.config or {}
+
+ -- 导入工具函数(用于根目录检测)
+ local util = require("lspconfig.util")
+
+ -- ========== 配置 clangd (C/C++) ==========
+ vim.lsp.config.clangd = {
+ default_config = {
+ cmd = {
+ "clangd",
+ "--background-index",
+ "--clang-tidy",
+ "--header-insertion=never",
+ "--completion-style=detailed",
+ "--all-scopes-completion",
+ "--cross-file-rename",
+ "--completion-parse=auto"
+ },
+ filetypes = { "c", "cpp", "objc", "objcpp", "cuda" },
+ root_dir = function(fname)
+ local root_markers = { '.git', 'compile_commands.json', 'compile_flags.txt', '.clangd', 'Makefile', 'build' }
+ local root = util.root_pattern(unpack(root_markers))(fname)
+ if not root then
+ root = util.find_git_ancestor(fname) or vim.fs.dirname(fname)
+ end
+ return root
+ end,
+ single_file_support = true,
+ capabilities = capabilities,
+ on_attach = on_attach, -- 【重要】在这里绑定快捷键
+ }
+ }
+
+ -- ========== 配置 lua_ls (Lua) ==========
+ vim.lsp.config.lua_ls = {
+ default_config = {
+ settings = {
+ Lua = {
+ runtime = { version = 'LuaJIT' },
+ diagnostics = { globals = { 'vim' } },
+ workspace = {
+ library = vim.api.nvim_get_runtime_file("", true),
+ checkThirdParty = false,
+ },
+ telemetry = { enable = false },
+ },
+ },
+ capabilities = capabilities,
+ on_attach = on_attach, -- 【重要】在这里绑定快捷键
+ }
+ }
+
+ -- 5. 美化UI设置
+ -- 悬浮文档窗口使用圆角边框
+ vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(
+ vim.lsp.handlers.hover, {
+ border = "rounded",
+ }
+ )
+
+ -- 【注意】在新框架下,通常不需要手动创建 LspAttach 自动命令
+ -- 因为每个服务器的 on_attach 已在 default_config 中定义
+ -- mason-lspconfig 会自动处理服务器启动和配置应用
+ end,
+ },
+
+ -- 6. 自动补全配置 (nvim-cmp) - 保持不变,与新旧框架都兼容
+ {
+ "hrsh7th/nvim-cmp",
+ config = function()
+ local cmp = require("cmp")
+ cmp.setup({
+ window = {
+ completion = cmp.config.window.bordered(),
+ documentation = cmp.config.window.bordered(),
+ },
+ view = {
+ entries = { name = 'custom', selection_order = 'near_cursor' }
+ },
+ mapping = cmp.mapping.preset.insert({
+ [''] = cmp.mapping.complete(),
+ [''] = cmp.mapping.confirm({ select = true }),
+ [''] = cmp.mapping.select_next_item(),
+ [''] = cmp.mapping.select_prev_item(),
+ }),
+ sources = cmp.config.sources({
+ { name = 'nvim_lsp' },
+ { name = 'path' },
+ })
+ })
+ end,
+ },
+}
diff --git a/.config/nvim/lua/plugins/lualine.lua b/.config/nvim/lua/plugins/lualine.lua
new file mode 100644
index 0000000..d74e36a
--- /dev/null
+++ b/.config/nvim/lua/plugins/lualine.lua
@@ -0,0 +1,14 @@
+return {
+
+ 'nvim-lualine/lualine.nvim',
+ dependencies = { 'nvim-tree/nvim-web-devicons' },
+ config = function()
+ require('lualine').setup({
+ options = {
+ theme = 'auto',
+ icons_enabled = true, -- 确保图标功能已启用
+ },
+ })
+ end,
+}
+
diff --git a/.config/nvim/lua/plugins/nvim-tree.lua b/.config/nvim/lua/plugins/nvim-tree.lua
new file mode 100644
index 0000000..b061499
--- /dev/null
+++ b/.config/nvim/lua/plugins/nvim-tree.lua
@@ -0,0 +1,38 @@
+return {
+ "nvim-tree/nvim-tree.lua",
+ version = "*",
+ lazy = false,
+ dependencies = { "nvim-tree/nvim-web-devicons" },
+ config = function()
+ require("nvim-tree").setup({
+ -- 这里可以放自定义设置,初始用默认即可
+ })
+ -- 设置一个常用快捷键:空格+e 打开/关闭文件树
+ -- 为 nvim-tree 设置一组实用快捷键
+ vim.keymap.set('n', 'e', ':NvimTreeToggle', { desc = 'Toggle file tree' })
+ vim.keymap.set('n', 'f', function()
+ local current_win = vim.api.nvim_get_current_win()
+ local current_buf = vim.api.nvim_win_get_buf(current_win)
+ local buf_ft = vim.api.nvim_buf_get_option(current_buf, 'filetype')
+
+ if buf_ft == 'NvimTree' then
+ -- 从文件树返回时,尝试回到之前编辑的窗口
+ vim.cmd('wincmd p')
+
+ -- 如果上一个窗口还是文件树(可能只有一个文件树窗口),就关闭它
+ local new_win = vim.api.nvim_get_current_win()
+ local new_buf = vim.api.nvim_win_get_buf(new_win)
+ local new_buf_ft = vim.api.nvim_buf_get_option(new_buf, 'filetype')
+
+ if new_buf_ft == 'NvimTree' then
+ vim.cmd('NvimTreeClose')
+ end
+ else
+ -- 保存当前窗口ID,以便从文件树返回时能准确回来
+ vim.g.last_normal_win = current_win
+ vim.cmd('NvimTreeFindFile')
+ end
+ end, { desc = '智能切换: 文件⇄树' })
+ vim.keymap.set('n', 't', ':NvimTreeFocus', { desc = 'Focus on the file tree' })
+ end,
+}
diff --git a/.config/nvim/lua/plugins/ouroboros.lua b/.config/nvim/lua/plugins/ouroboros.lua
new file mode 100644
index 0000000..bbb680b
--- /dev/null
+++ b/.config/nvim/lua/plugins/ouroboros.lua
@@ -0,0 +1,84 @@
+-- 在你的 Lazy 插件配置文件中(例如:lua/plugins/cpp.lua)
+return {
+ {
+ "jakemason/ouroboros",
+ ft = { "c", "cpp", "h", "hpp" }, -- 可选:按文件类型懒加载
+ dependencies = {
+ "nvim-lua/plenary.nvim" -- 明确声明依赖[citation:8]
+ },
+ config = function()
+ require("ouroboros").setup({
+ -- 基本配置
+ open_all_alternates = false,
+
+ -- 查找策略(按顺序尝试)
+ strategies = {
+ "directory", -- 同一目录
+ "underscore", -- main_window.cpp -> main_window.h
+ "basename", -- 相同基名
+ "subdirectory", -- 在 include/ 或 src/ 中查找
+ "cabal", -- Cabal 项目结构
+ "complement", -- 互补扩展名
+ },
+
+ -- 扩展名映射
+ extension_map = {
+ h = { "cpp", "c", "cc", "cxx", "c++", "m", "mm" },
+ hpp = { "cpp", "cc", "cxx", "c++" },
+ hxx = { "cxx", "cpp" },
+ hh = { "cc", "cpp" },
+ c = { "h" },
+ cc = { "h", "hh" },
+ cpp = { "h", "hpp" },
+ cxx = { "h", "hxx", "hpp" },
+ m = { "h" },
+ mm = { "h" },
+ },
+
+ -- 目录映射(适用于标准项目结构)
+ directory_map = {
+ ["include/(.*)%.h$"] = "src/%1.cpp",
+ ["src/(.*)%.cpp$"] = "include/%1.h",
+ ["inc/(.*)%.hpp$"] = "src/%1.cpp",
+ ["lib/(.*)%.c$"] = "include/%1.h",
+ ["source/(.*)%.cxx$"] = "headers/%1.hxx",
+ },
+
+ -- 自定义匹配函数
+ match_callback = function(filepath, strategies, bufnr)
+ -- 获取文件扩展名
+ local extension = filepath:match("%.(%w+)$") or ""
+
+ -- 如果是测试文件,寻找对应的源文件
+ if filepath:match("_test%.cpp$") then
+ local source_file = filepath:gsub("_test%.cpp$", ".cpp")
+ if vim.fn.filereadable(source_file) == 1 then
+ return { source_file }
+ end
+ end
+
+ -- 返回默认策略
+ return strategies
+ end,
+ })
+
+ -- 键位映射
+ vim.keymap.set("n", "oh", "Ouroboros", {
+ desc = "切换头文件/源文件",
+ noremap = true,
+ silent = true,
+ })
+
+ vim.keymap.set("n", "oa", "OuroborosAll", {
+ desc = "打开所有匹配文件",
+ noremap = true,
+ silent = true,
+ })
+
+ -- 可以添加更多命令
+ vim.api.nvim_create_user_command("AltFile", function()
+ require("ouroboros").switch()
+ end, {})
+ end,
+ },
+}
diff --git a/.config/nvim/lua/plugins/treesitter.lua b/.config/nvim/lua/plugins/treesitter.lua
new file mode 100644
index 0000000..4d36b45
--- /dev/null
+++ b/.config/nvim/lua/plugins/treesitter.lua
@@ -0,0 +1,19 @@
+return {
+ "nvim-treesitter/nvim-treesitter",
+ version = false, -- 建议使用 master 分支
+ build = ":TSUpdate",
+ event = { "BufReadPost", "BufNewFile" }, -- 只有打开文件时才加载,防止启动报错
+ config = function()
+ -- 增加一个保护性检测
+ local status_ok, configs = pcall(require, "nvim-treesitter.configs")
+ if not status_ok then
+ return
+ end
+
+ configs.setup({
+ ensure_installed = { "lua", "vim", "vimdoc", "query", "c", "cpp" }, -- 基础必装
+ highlight = { enable = true },
+ indent = { enable = true }, -- 建议开启,C++ 缩进会更准确
+ })
+ end,
+}
diff --git a/.config/nwg-look/config b/.config/nwg-look/config
new file mode 100644
index 0000000..3f49ae5
--- /dev/null
+++ b/.config/nwg-look/config
@@ -0,0 +1,7 @@
+{
+ "export-settings-ini": true,
+ "export-gtkrc-20": true,
+ "export-index-theme": true,
+ "export-xsettingsd": true,
+ "export-gtk4-symlinks": true
+}
\ No newline at end of file
diff --git a/.config/qt5ct/qt5ct.conf b/.config/qt5ct/qt5ct.conf
new file mode 100644
index 0000000..b356fb5
--- /dev/null
+++ b/.config/qt5ct/qt5ct.conf
@@ -0,0 +1,30 @@
+[Appearance]
+custom_palette=false
+standard_dialogs=gtk3
+style=Fusion
+
+[Fonts]
+fixed="JetBrainsMono Nerd Font,12,-1,5,50,0,0,0,0,0"
+general="JetBrainsMono Nerd Font,12,-1,5,50,0,0,0,0,0"
+
+[Interface]
+activate_item_on_single_click=1
+buttonbox_layout=0
+cursor_flash_time=1000
+dialog_buttons_have_icons=1
+double_click_interval=400
+gui_effects=@Invalid()
+keyboard_scheme=2
+menus_have_icons=true
+show_shortcuts_in_context_menus=true
+stylesheets=@Invalid()
+toolbutton_style=4
+underline_shortcut=1
+wheel_scroll_lines=3
+
+[SettingsWindow]
+geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x3\x45\0\0\x3\xfc\0\0\0\0\0\0\0\0\0\0\x3\x45\0\0\x3\xfc\0\0\0\0\0\0\0\0\x6\xab\0\0\0\0\0\0\0\0\0\0\x3\x45\0\0\x3\xfc)
+
+[Troubleshooting]
+force_raster_widgets=1
+ignored_applications=@Invalid()
diff --git a/.config/qt6ct/qt6ct.conf b/.config/qt6ct/qt6ct.conf
new file mode 100644
index 0000000..96d250f
--- /dev/null
+++ b/.config/qt6ct/qt6ct.conf
@@ -0,0 +1,30 @@
+[Appearance]
+custom_palette=false
+standard_dialogs=gtk3
+style=Fusion
+
+[Fonts]
+fixed="JetBrainsMono Nerd Font,12,-1,5,400,0,0,0,0,0,0,0,0,0,0,1"
+general="JetBrainsMono Nerd Font,12,-1,5,400,0,0,0,0,0,0,0,0,0,0,1"
+
+[Interface]
+activate_item_on_single_click=1
+buttonbox_layout=0
+cursor_flash_time=1000
+dialog_buttons_have_icons=1
+double_click_interval=400
+gui_effects=@Invalid()
+keyboard_scheme=2
+menus_have_icons=true
+show_shortcuts_in_context_menus=true
+stylesheets=@Invalid()
+toolbutton_style=4
+underline_shortcut=1
+wheel_scroll_lines=3
+
+[SettingsWindow]
+geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x2\x9e\0\0\x3\x30\0\0\0\0\0\0\0\0\0\0\x2\x9e\0\0\x3\x30\0\0\0\0\0\0\0\0\x5U\0\0\0\0\0\0\0\0\0\0\x2\x9e\0\0\x3\x30)
+
+[Troubleshooting]
+force_raster_widgets=1
+ignored_applications=@Invalid()
diff --git a/.config/starship.toml b/.config/starship.toml
new file mode 100644
index 0000000..7cca5ee
--- /dev/null
+++ b/.config/starship.toml
@@ -0,0 +1,181 @@
+"$schema" = 'https://starship.rs/config-schema.json'
+
+format = """
+[](color_orange)\
+$os\
+$username\
+[](bg:color_yellow fg:color_orange)\
+$directory\
+[](fg:color_yellow bg:color_aqua)\
+$git_branch\
+$git_status\
+[](fg:color_aqua bg:color_blue)\
+$c\
+$cpp\
+$rust\
+$golang\
+$nodejs\
+$php\
+$java\
+$kotlin\
+$haskell\
+$python\
+[](fg:color_blue bg:color_bg3)\
+$docker_context\
+$conda\
+$pixi\
+[](fg:color_bg3 bg:color_bg1)\
+$time\
+[ ](fg:color_bg1)\
+$line_break$character"""
+
+palette = 'gruvbox_dark'
+
+[palettes.gruvbox_dark]
+color_fg0 = '#fbf1c7'
+color_bg1 = '#3c3836'
+color_bg3 = '#665c54'
+color_blue = '#458588'
+color_aqua = '#689d6a'
+color_green = '#98971a'
+color_orange = '#d65d0e'
+color_purple = '#b16286'
+color_red = '#cc241d'
+color_yellow = '#d79921'
+
+[os]
+disabled = false
+style = "bg:color_orange fg:color_fg0"
+
+[os.symbols]
+Windows = ""
+Ubuntu = ""
+SUSE = ""
+Raspbian = ""
+Mint = ""
+Macos = ""
+Manjaro = ""
+Linux = ""
+Gentoo = ""
+Fedora = ""
+Alpine = ""
+Amazon = ""
+Android = ""
+AOSC = ""
+Arch = ""
+Artix = ""
+EndeavourOS = ""
+CentOS = ""
+Debian = ""
+Redhat = ""
+RedHatEnterprise = ""
+Pop = ""
+
+[username]
+show_always = true
+style_user = "bg:color_orange fg:color_fg0"
+style_root = "bg:color_orange fg:color_fg0"
+format = '[ $user ]($style)'
+
+[directory]
+style = "fg:color_fg0 bg:color_yellow"
+format = "[ $path ]($style)"
+truncation_length = 3
+truncation_symbol = "…/"
+
+[directory.substitutions]
+"Documents" = " "
+"Downloads" = " "
+"Music" = " "
+"Pictures" = " "
+"Developer" = " "
+
+[git_branch]
+symbol = ""
+style = "bg:color_aqua"
+format = '[[ $symbol $branch ](fg:color_fg0 bg:color_aqua)]($style)'
+
+[git_status]
+style = "bg:color_aqua"
+format = '[[($all_status$ahead_behind )](fg:color_fg0 bg:color_aqua)]($style)'
+
+[nodejs]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[c]
+symbol = " "
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[cpp]
+symbol = " "
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[rust]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[golang]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[php]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[java]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[kotlin]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[haskell]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[python]
+symbol = ""
+style = "bg:color_blue"
+format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
+
+[docker_context]
+symbol = ""
+style = "bg:color_bg3"
+format = '[[ $symbol( $context) ](fg:#83a598 bg:color_bg3)]($style)'
+
+[conda]
+style = "bg:color_bg3"
+format = '[[ $symbol( $environment) ](fg:#83a598 bg:color_bg3)]($style)'
+
+[pixi]
+style = "bg:color_bg3"
+format = '[[ $symbol( $version)( $environment) ](fg:color_fg0 bg:color_bg3)]($style)'
+
+[time]
+disabled = false
+time_format = "%R"
+style = "bg:color_bg1"
+format = '[[ $time ](fg:color_fg0 bg:color_bg1)]($style)'
+
+[line_break]
+disabled = false
+
+[character]
+disabled = false
+success_symbol = '[](bold fg:color_green)'
+error_symbol = '[](bold fg:color_red)'
+vimcmd_symbol = '[](bold fg:color_green)'
+vimcmd_replace_one_symbol = '[](bold fg:color_purple)'
+vimcmd_replace_symbol = '[](bold fg:color_purple)'
+vimcmd_visual_symbol = '[](bold fg:color_yellow)'
diff --git a/.config/waybar/colors.css b/.config/waybar/colors.css
new file mode 100755
index 0000000..d8cec45
--- /dev/null
+++ b/.config/waybar/colors.css
@@ -0,0 +1,105 @@
+/*
+* Css Colors
+* Generated with Matugen
+*/
+
+ @define-color background #15130b;
+
+ @define-color error #ffb4ab;
+
+ @define-color error_container #93000a;
+
+ @define-color inverse_on_surface #333027;
+
+ @define-color inverse_primary #6e5e0e;
+
+ @define-color inverse_surface #e9e2d4;
+
+ @define-color on_background #e9e2d4;
+
+ @define-color on_error #690005;
+
+ @define-color on_error_container #ffdad6;
+
+ @define-color on_primary #3a3000;
+
+ @define-color on_primary_container #f9e287;
+
+ @define-color on_primary_fixed #221b00;
+
+ @define-color on_primary_fixed_variant #534600;
+
+ @define-color on_secondary #373016;
+
+ @define-color on_secondary_container #eee2bc;
+
+ @define-color on_secondary_fixed #211b04;
+
+ @define-color on_secondary_fixed_variant #4e472a;
+
+ @define-color on_surface #e9e2d4;
+
+ @define-color on_surface_variant #cdc6b4;
+
+ @define-color on_tertiary #153722;
+
+ @define-color on_tertiary_container #c5ecce;
+
+ @define-color on_tertiary_fixed #00210f;
+
+ @define-color on_tertiary_fixed_variant #2c4e38;
+
+ @define-color outline #969080;
+
+ @define-color outline_variant #4b4739;
+
+ @define-color primary #dcc66e;
+
+ @define-color primary_container #534600;
+
+ @define-color primary_fixed #f9e287;
+
+ @define-color primary_fixed_dim #dcc66e;
+
+ @define-color scrim #000000;
+
+ @define-color secondary #d1c6a1;
+
+ @define-color secondary_container #4e472a;
+
+ @define-color secondary_fixed #eee2bc;
+
+ @define-color secondary_fixed_dim #d1c6a1;
+
+ @define-color shadow #000000;
+
+ @define-color source_color #dabc2c;
+
+ @define-color surface #15130b;
+
+ @define-color surface_bright #3c3930;
+
+ @define-color surface_container #221f17;
+
+ @define-color surface_container_high #2d2a21;
+
+ @define-color surface_container_highest #38352b;
+
+ @define-color surface_container_low #1e1b13;
+
+ @define-color surface_container_lowest #100e07;
+
+ @define-color surface_dim #15130b;
+
+ @define-color surface_tint #dcc66e;
+
+ @define-color surface_variant #4b4739;
+
+ @define-color tertiary #aad0b3;
+
+ @define-color tertiary_container #2c4e38;
+
+ @define-color tertiary_fixed #c5ecce;
+
+ @define-color tertiary_fixed_dim #aad0b3;
+
diff --git a/.config/waybar/config.jsonc b/.config/waybar/config.jsonc
new file mode 100755
index 0000000..293a766
--- /dev/null
+++ b/.config/waybar/config.jsonc
@@ -0,0 +1,65 @@
+{
+ //这个waybar因为大改过一次布局,所以箭头的位置和名字已经完全对不上了,从左到右看吧。
+ "include": [
+ "modules.jsonc",
+ "modules-dividers.jsonc"
+ ],
+ //这一行layer top设置会让waybar显示在最上方
+ "layer": "top",
+ //"output": "DP-2",
+ "position": "top",
+ "fixed-center": true,
+ // "height": 30,
+ "reload_style_on_change": true,
+ "modules-left": [
+ // "ext/workspaces",
+ "niri/workspaces",
+ "custom/right_div#5",
+ "cffi/niri-taskbar",
+ "niri/window",
+ //"dwl/window",
+ // "hyprland/window",
+ "custom/right_div#6"
+ ],
+ "modules-center": [
+ "custom/left_div#3",
+ "bluetooth",
+ "network",
+ "custom/wfrec",
+// "custom/screenshot",
+ "custom/left_div#2",
+ // "idle_inhibitor",
+ "custom/colorpicker",
+ "power-profiles-daemon",
+ "custom/left_div#11",
+ "custom/left_div#1",
+ "custom/applauncher",
+ "custom/right_div#1",
+ "custom/right_div#11",
+ "clock",
+ "custom/right_div#2",
+ //"clock#date",
+ "custom/cava",
+ // "mpris",
+ "custom/right_div#3"
+ //"custom/right_div#4",
+ ],
+ "modules-right": [
+ // "group/backlight",
+ "custom/left_div#7",
+ "custom/updates",
+ "tray",
+ // "custom/mako",
+ "custom/left_div#4",
+ //"backlight/slider",
+ //"backlight",
+ // "group/ddcutil",
+ "group/screenlight",
+ "privacy",
+ "group/audio",
+ "custom/left_div#8",
+ "battery",
+ "custom/left_div#5",
+ "group/powermenu"
+ ]
+}
diff --git a/.config/waybar/logo/bluetooth.png b/.config/waybar/logo/bluetooth.png
new file mode 100755
index 0000000..8f1d82c
Binary files /dev/null and b/.config/waybar/logo/bluetooth.png differ
diff --git a/.config/waybar/modules-dividers.jsonc b/.config/waybar/modules-dividers.jsonc
new file mode 100755
index 0000000..ecab437
--- /dev/null
+++ b/.config/waybar/modules-dividers.jsonc
@@ -0,0 +1,88 @@
+{
+ /*-------------------
+ left dividers
+ -------------------*/
+ "custom/left_div#1": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#11": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#2": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#3": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#4": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#5": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#6": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#7": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#8": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_div#9": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_inv#1": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left_inv#2": {
+ "format": "",
+ "tooltip": false
+ },
+ /*--------------------
+ right dividers
+ --------------------*/
+ "custom/right_div#1": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#11": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#2": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#3": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#4": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#5": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_div#6": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right_inv#1": {
+ "format": "",
+ "tooltip": false
+ }
+}
\ No newline at end of file
diff --git a/.config/waybar/modules.jsonc b/.config/waybar/modules.jsonc
new file mode 100755
index 0000000..a07d2cc
--- /dev/null
+++ b/.config/waybar/modules.jsonc
@@ -0,0 +1,422 @@
+{
+ //电池电量
+ "battery": {
+ "interval": 60,
+ "states": {
+ "critical": 20,
+ },
+ "format": "{icon} {capacity}%",
+ "format-charging": " {capacity}% ",
+ "format-icons": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "tooltip-format": "剩余电量:{capacity}%\n充 放 电 :{power}\n可用时间:{timeTo}\n---\n电池健康度:{health}%",
+ },
+ //时钟
+ "clock": {
+ "interval": 60,
+ "format": " {:%H:%M}",
+ "tooltip-format": "{:%Y/%m/%d %A}\n---\n左键:打开时钟\n右键:打开日历",
+ "max-length": 25,
+ "on-click": "gnome-clocks",
+ "on-click-right": "gnome-calendar",
+ },
+ "clock#date": {
+ // "interval":
+ "format": " {:%m-%d}",
+ // "timezone":
+ // "timezones":
+ // "locale":
+ // "rotate":
+ // "on-click":
+ // "on-click-middle":
+ // "on-click-right":
+ // "on-scroll-up":
+ // "on-scroll-down":
+ // "smooth-scrolling-threshold":
+ // "tooltip":
+ "on-click": "gnome-calendar",
+ "tooltip-format": "{:%Y/%m/%d %A}",
+ },
+ //正在运行的软件
+ "tray": {
+ "icon-size": 22,
+ "spacing": 7,
+ // 自定义图标
+ //"icons": {
+ // "blueman": "/home/shorin/.config/waybar/logo/bluetooth.png",
+ //},
+ },
+ //工作区和窗口名字
+ "niri/workspaces": {
+ "format": "{icon}",
+ "format-icons": {
+ "active": "",
+ "default": "",
+ },
+ },
+ "niri/window": {
+ "format": "{}",
+ "rewrite": {
+ "(.*) - Mozilla Firefox": "🌎 $1",
+ "(.*) - zsh": "> [$1]",
+ },
+ },
+ //网络和蓝牙
+ "group/network-bluetooth": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false,
+ },
+ "modules": [
+ "network",
+ "bluetooth"
+ ],
+ },
+ "network": {
+ "format-disconnected": "{icon}",
+ "format-wifi": "{icon}",
+ "format-ethernet": "{icon}",
+ "format-icons": {
+ "disconnected": "",
+ "wifi": [
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "ethernet": "",
+ },
+ //鼠标悬浮在wifi图标上会显示wifi名称、信号强度、ip地址、设备名
+ "tooltip-format-wifi": "{essid} ({signalStrength}%)\n{ifname} : {ipaddr}\n---\n左键:打开面板\n右键:打开高级网络配置工具",
+ "tooltip-format-ethernet": "{ifname} : {ipaddr}\n---\n左键:打开面板\n右键:打开高级网络配置工具",
+ "tooltip-format-disconnected": "网络未连接\n---\n左键:打开面板\n右键:打开高级网络配置工具",
+ "on-click": "kitty --class nmtui -e nmtui",
+ "on-click-right": "nm-connection-editor",
+ },
+ "bluetooth": {
+ //蓝牙关闭状态下的图标和鼠标悬浮时的提示
+ "format-disabled": "",
+ "tooltip-format-disabled": "左键:启用蓝牙",
+ "format": "",
+ "tooltip-format-on": "左键:禁用蓝牙\n右键:打开面板",
+ //连接状态下的图标和提示
+ "format-connected": "",
+ "tooltip-format-connected": " {:device_alias}\n---\n右键:打开面板",
+ //点击功能
+ "on-click": "~/.config/waybar/scripts/toggle-bluetooth.sh",
+ "on-click-right": "kitty --class bluetui -e bluetui",
+ },
+ //左键循环切换性能模式
+ "power-profiles-daemon": {
+ "format": "{icon}",
+ "tooltip-format": "当前性能模式:{profile}\n---\n左键:切换性能模式",
+ "tooltip": true,
+ "format-icons": {
+ "performance": "",
+ "balanced": "",
+ "power-saver": "",
+ },
+ },
+ //截图
+ "custom/screenshot": {
+ "format": "",
+ "tooltip-format": "左键:快速截图(仅保存到剪贴板)\n右键:打开截图菜单\n中键:打开长截图菜单",
+ "on-click": "~/.config/waybar/scripts/screenshot.sh",
+ "on-click-right": "~/.config/waybar/scripts/power-screenshot.sh",
+ "on-click-middle": "~/.config/waybar/scripts/longshot-sh/longshot.sh"
+ },
+ //wf-recorder
+ "custom/wfrec": {
+ "exec": "~/.config/waybar/scripts/wf-recorder.sh status-json",
+ "return-type": "json",
+ //"interval": 1, // 每秒刷新一次
+ "signal": 9, // 与脚本里的 WAYBAR_SIG 对应
+ "tooltip": true,
+ "on-click": "~/.config/waybar/scripts/wf-recorder.sh toggle", // 左键:开始/停止
+ "on-click-right": "~/.config/waybar/scripts/wf-recorder.sh stop"
+ },
+ //声音模块
+ "group/audio": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false,
+ },
+ "modules": [
+ "pulseaudio",
+ "pulseaudio/slider"
+ ],
+ },
+ "pulseaudio": {
+ "tooltip-format": "左键:静音\n右键:关闭麦克风\n中键:打开面板",
+ "format": "{icon} {format_source} ",
+ "format-bluetooth": " {format_source} ",
+ "format-source": "{volume}%",
+ "format-source-muted": "",
+ "format-muted": " {format_source} ",
+ "format-icons": {
+ "headphone": "",
+ "bluetooth": "",
+ // "speaker":""
+ "speaker": [
+ "",
+ "",
+ ""
+ ],
+ },
+ "on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
+ "on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle",
+ "on-click-middle": "pavucontrol --tab=3",
+ "on-scroll-up": "wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%+",
+ "on-scroll-down": "wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%-",
+ },
+ "pulseaudio/slider": {
+ "min": 0,
+ "max": 100,
+ "orientation": "horizontal",
+ },
+ //多媒体
+ "mpris": {
+ "format": "{player_icon}",
+ "format-paused": "{status_icon}",
+ "player-icons": {
+ "default": "▶",
+ },
+ "status-icons": {
+ "paused": "⏸",
+ },
+ "toooltip": "{dynamic}",
+ "enable-tooltip-len-limits": true,
+ },
+ //logo+程序启动器
+ "custom/applauncher": {
+ "tooltip-format": "左键:软件启动菜单\n右键:切换壁纸",
+ "format": "",
+ "on-click": "fuzzel",
+ "on-click-right": "waypaper",
+// "on-click-middle": "~/.config/scripts/niri_auto_blur_bg.sh || pkill -f niri_auto_blur_bg.sh"
+ },
+ //电源菜单
+ "group/powermenu": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false,
+ },
+ "modules": [
+ "custom/wlogout",
+ "custom/reboot",
+ "custom/logout",
+ "custom/lockscreen",
+ ],
+ },
+ "custom/wlogout": {
+ "tooltip": false,
+ "format": "",
+ "on-click": "systemctl poweroff",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ "custom/lockscreen": {
+ "tooltip": false,
+ "format": "",
+ "on-click": "swaylock || hyprlock",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ "custom/reboot": {
+ "tooltip": false,
+ "format": "",
+ "on-click": "systemctl reboot",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ "custom/logout": {
+ "format": "",
+ "on-click": "niri msg action quit",
+ "tooltip": false,
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ "group/screenlight": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false,
+ },
+ "modules": [
+ "backlight",
+ "backlight/slider",
+
+ ],
+ },
+ //内屏亮度
+ "backlight/slider": {
+ "min": 5,
+ "max": 100,
+ "orientation": "horizontal",
+ },
+ "backlight": {
+ "tooltip": true,
+ "tooltip-format":"调节内屏亮度",
+ "format": ""
+ },
+ //调节外接屏幕亮度
+ "group/ddcutil": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false,
+ },
+ "modules": [
+ "custom/ddcutil-day",
+ "backlight/slider",
+ "backlight",
+ "custom/separator#1",
+ "custom/ddcutil-sleep",
+ "custom/ddcutil-night",
+ ],
+ },
+ "custom/ddcutil-day": {
+ "tooltip-format": "左键:100%外接屏幕亮度\n右键:切换护眼模式",
+ "format": "",
+ "on-click": "ddcutil --display 1 setvcp 10 100 ",
+ "on-click-right": "~/.local/bin/toggle-wlsunset",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ "custom/ddcutil-night": {
+ "tooltip-format": "左键:65%外接屏幕亮度",
+ "format": "",
+ "on-click": "ddcutil --display 1 setvcp 10 65 ",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ "custom/ddcutil-sleep": {
+ "tooltip-format": "左键:5%外接屏幕亮度",
+ "format": "",
+ "on-click": "ddcutil --display 1 setvcp 10 5 ",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+ //swaync通知模块
+ "custom/swaync": {
+ "tooltip": false,
+ "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": "swaync-client -t -sw",
+ "on-click-right": "swaync-client -d -sw",
+ "escape": true,
+ },
+ "custom/mako": {
+ "format": "",
+ "on-click": "makoctl restore",
+ },
+ //gnome-control-center
+ "custom/settings": {
+ "format": "",
+ "on-click": "env XDG_CURRENT_DESKTOP=GNOME gnome-control-center",
+ "tooltip-format": "Open control center",
+ },
+ //获取屏幕颜色colorpicker
+ "custom/colorpicker": {
+ "tooltip": true,
+ "format": "",
+ "on-click": "hyprpicker | wl-copy",
+ "tooltip-format":"左键:提取颜色",
+ },
+ //音频可视化
+ "custom/cava": {
+ "tooltip": false,
+ "format": "{}",
+ "exec": "~/.config/waybar/scripts/cava.sh",
+ },
+ //禁止熄屏
+ "idle_inhibitor": {
+ "format": "{icon}",
+ "format-icons": {
+ "activated": "",
+ "deactivated": "",
+ },
+ "tooltip-format-activated": "自动熄屏已禁止",
+ "tooltip-format-deactivated": "自动熄屏已开启",
+ "on-click-right": "~/.config/scripts/matugen-select-type.sh"
+ },
+ //分隔符
+ "custom/separator#1": {
+ "format": "",
+ "tooltip": false,
+ },
+ //archupdater
+"custom/updates": {
+ "format": "{}{icon}",
+ "return-type": "json",
+ "format-icons": {
+ "has-updates": "",
+ "updated": ""
+ },
+ "exec": "~/.config/waybar/scripts/check-updates.sh",
+ "interval": 3600,
+ "on-click": "kitty -e paru",
+ },
+ //隐私
+ "privacy": {
+ "icon-spacing": 10,
+ "icon-size": 16,
+ "transition-duration": 250,
+ "modules": [
+ {
+ "type": "screenshare",
+ "tooltip": true,
+ "tooltip-icon-size": 24,
+ },
+ ],
+ },
+ "cffi/niri-taskbar": {
+ // module_path
+ "module_path": "/usr/lib/waybar/libniri_taskbar.so",
+ "apps": {
+ "signal": [
+ {
+ "match": "\\([0-9]+\\)$",
+ "class": "unread",
+ },
+ ],
+ },
+ },
+ // dwl and mangowc
+ "ext/workspaces": {
+ "format": "{icon}",
+ //"format-icons": {
+ // "active": "",
+ // "default": ""
+ // },
+ "ignore-hidden": true,
+ "on-click": "activate",
+ "on-click-right": "deactivate",
+ "sort-by-id": true,
+ },
+ "dwl/window": {
+ "format": "[{layout}]{title}",
+ }
+
+}
diff --git a/.config/waybar/modules.jsonc.bak b/.config/waybar/modules.jsonc.bak
new file mode 100755
index 0000000..7aa31d4
--- /dev/null
+++ b/.config/waybar/modules.jsonc.bak
@@ -0,0 +1,356 @@
+{
+ // 电池电量
+ "battery": {
+ "interval": 60,
+ "states": {
+ "critical": 20
+ },
+ "format": "{icon} {capacity}%",
+ "format-charging": " {capacity}% ",
+ "format-icons": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "tooltip-format": "剩余电量:{capacity}%\n充 放 电 :{power}\n可用时间:{timeTo}\n---\n电池健康度:{health}%"
+ },
+
+ // 时钟
+ "clock": {
+ "interval": 60,
+ "format": " {:%H:%M}",
+ "tooltip-format": "{:%Y/%m/%d %A}\n---\n左键:打开时钟\n右键:打开日历",
+ "max-length": 25,
+ "on-click": "gnome-clocks",
+ "on-click-right": "gnome-calendar"
+ },
+
+ // 日期小部件(点击打开日历)
+ "clock#date": {
+ "format": " {:%m-%d}",
+ "on-click": "gnome-calendar",
+ "tooltip-format": "{:%Y/%m/%d %A}"
+ },
+
+ // 系统托盘(蓝牙、输入法等图标)
+ "tray": {
+ "icon-size": 22,
+ "spacing": 7
+ },
+
+ // niri 工作区指示器
+ "niri/workspaces": {
+ "format": "{icon}",
+ "format-icons": {
+ "active": "",
+ "default": ""
+ }
+ },
+
+ // 当前窗口标题美化
+ "niri/window": {
+ "format": "{}",
+ "rewrite": {
+ "(.*) - Mozilla Firefox": "🌎 $1",
+ "(.*) - zsh": "> [$1]"
+ }
+ },
+
+ // 网络 & 蓝牙组合抽屉
+ "group/network-bluetooth": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false
+ },
+ "modules": [
+ "network",
+ "bluetooth"
+ ]
+ },
+
+ // 网络状态
+ "network": {
+ "format-disconnected": "{icon}",
+ "format-wifi": "{icon}",
+ "format-ethernet": "{icon}",
+ "format-icons": {
+ "disconnected": "",
+ "wifi": [
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "ethernet": ""
+ },
+ "tooltip-format-wifi": "{essid} ({signalStrength}%)\n{ifname} : {ipaddr}\n---\n左键:打开面板\n右键:打开高级网络配置工具",
+ "tooltip-format-ethernet": "{ifname} : {ipaddr}\n---\n左键:打开面板\n右键:打开高级网络配置工具",
+ "tooltip-format-disconnected": "网络未连接\n---\n左键:打开面板\n右键:打开高级网络配置工具",
+ "on-click": "kitty --class nmtui -e nmtui",
+ "on-click-right": "nm-connection-editor"
+ },
+
+ // 蓝牙控制
+ "bluetooth": {
+ "format-disabled": "",
+ "tooltip-format-disabled": "左键:启用蓝牙",
+ "format": "",
+ "tooltip-format-on": "左键:禁用蓝牙\n右键:打开面板",
+ "format-connected": "",
+ "tooltip-format-connected": " {:device_alias}\n---\n右键:打开面板",
+ "on-click": "~/.config/waybar/scripts/toggle-bluetooth.sh",
+ "on-click-right": "kitty --class bluetui -e bluetui"
+ },
+
+ // 性能模式切换(左键循环)
+ "power-profiles-daemon": {
+ "format": "{icon}",
+ "tooltip-format": "当前性能模式:{profile}\n---\n左键:切换性能模式",
+ "tooltip": true,
+ "format-icons": {
+ "performance": "",
+ "balanced": "",
+ "power-saver": ""
+ }
+ },
+
+ // 音频组(图标 + 滑块)
+ "group/audio": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false
+ },
+ "modules": [
+ "pulseaudio",
+ "pulseaudio/slider"
+ ]
+ },
+
+ // 音频控制(支持滚动调节麦克风音量)
+ "pulseaudio": {
+ "tooltip-format": "左键:静音\n右键:关闭麦克风\n中键:打开面板",
+ "format": "{icon} {format_source} ",
+ "format-bluetooth": " {format_source} ",
+ "format-source": "{volume}%",
+ "format-source-muted": "",
+ "format-muted": " {format_source} ",
+ "format-icons": {
+ "headphone": "",
+ "bluetooth": "",
+ "speaker": [
+ "",
+ "",
+ ""
+ ]
+ },
+ "on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
+ "on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle",
+ "on-click-middle": "pavucontrol --tab=3",
+ "on-scroll-up": "wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%+",
+ "on-scroll-down": "wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%-"
+ },
+
+ // 音量滑块(横向)
+ "pulseaudio/slider": {
+ "min": 0,
+ "max": 100,
+ "orientation": "horizontal"
+ },
+
+ // 多媒体播放器控制(mpris)
+ "mpris": {
+ "format": "{player_icon}",
+ "format-paused": "{status_icon}",
+ "player-icons": {
+ "default": "▶"
+ },
+ "status-icons": {
+ "paused": "⏸"
+ },
+ "tooltip": "{dynamic}",
+ "enable-tooltip-len-limits": true
+ },
+
+ // 应用启动器 + 壁纸切换
+ "custom/applauncher": {
+ "tooltip-format": "左键:软件启动菜单\n右键:切换壁纸",
+ "format": "",
+ "on-click": "fuzzel",
+ "on-click-right": "waypaper"
+ },
+
+ // 电源菜单组(登出/重启/锁屏)
+ "group/powermenu": {
+ "orientation": "inherit",
+ "drawer": {
+ "transition-left-to-right": false
+ },
+ "modules": [
+ "custom/wlogout",
+ "custom/reboot",
+ "custom/logout",
+ "custom/lockscreen"
+ ]
+ },
+
+ "custom/wlogout": {
+ "tooltip": false,
+ "format": "",
+ "on-click": "wlogout",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+
+ "custom/lockscreen": {
+ "tooltip": false,
+ "format": "",
+ "on-click": "swaylock || hyprlock",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+
+ "custom/reboot": {
+ "tooltip": false,
+ "format": "",
+ "on-click": "systemctl reboot",
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+
+ "custom/logout": {
+ "format": "",
+ "on-click": "niri msg action quit",
+ "tooltip": false,
+ "on-scroll-up": "true",
+ "on-scroll-down": "true"
+ },
+
+ // ✅ 内屏亮度控制模块(已优化,不依赖外屏)
+ // 使用 backlight + slider 组合,适配大多数笔记本/内置显示器
+ "backlight": {
+ "tooltip": true,
+ "tooltip-format": "调节内屏亮度",
+ "format": "{icon}",
+ "format-icons": [
+ "", // 0-10%
+ "", // 10-20%
+ "", // 20-30%
+ "", // 30-40%
+ "", // 40-50%
+ "", // 50-60%
+ "", // 60-70%
+ "", // 70-80%
+ "" // 80-100%
+ ]
+ },
+
+ "backlight/slider": {
+ "min": 5, // 最低亮度设为5避免完全黑屏
+ "max": 100,
+ "orientation": "horizontal"
+ },
+
+ // 通知中心(swaync)
+ "custom/swaync": {
+ "tooltip": false,
+ "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": "swaync-client -t -sw",
+ "on-click-right": "swaync-client -d -sw",
+ "escape": true
+ },
+
+ // 备用通知方案(mako)
+ "custom/mako": {
+ "format": "",
+ "on-click": "makoctl restore"
+ },
+
+ // 系统设置面板
+ "custom/settings": {
+ "format": "",
+ "on-click": "env XDG_CURRENT_DESKTOP=GNOME gnome-control-center",
+ "tooltip-format": "打开系统设置"
+ },
+
+ // 自动更新检查器(Arch Linux)
+ "custom/updates": {
+ "format": "{}{icon}",
+ "return-type": "json",
+ "format-icons": {
+ "has-updates": "",
+ "updated": ""
+ },
+ "exec": "~/.config/waybar/scripts/check-updates.sh",
+ "interval": 3600,
+ "on-click": "kitty -e sysup"
+ },
+
+ // 隐私指示器(如屏幕共享)
+ "privacy": {
+ "icon-spacing": 10,
+ "icon-size": 16,
+ "transition-duration": 250,
+ "modules": [
+ {
+ "type": "screenshare",
+ "tooltip": true,
+ "tooltip-icon-size": 24
+ }
+ ]
+ },
+
+ // niri 任务栏扩展
+ "cffi/niri-taskbar": {
+ "module_path": "/usr/lib/waybar/libniri_taskbar.so",
+ "apps": {
+ "signal": [
+ {
+ "match": "\\([0-9]+\\)$",
+ "class": "unread"
+ }
+ ]
+ }
+ },
+
+ // 兼容 dwl / mangowc 的工作区模块(备用)
+ "ext/workspaces": {
+ "format": "{icon}",
+ "ignore-hidden": true,
+ "on-click": "activate",
+ "on-click-right": "deactivate",
+ "sort-by-id": true
+ },
+
+ // dwl 窗口标题显示
+ "dwl/window": {
+ "format": "[{layout}]{title}"
+ },
+
+ // 分隔符
+ "custom/separator#1": {
+ "format": "",
+ "tooltip": false
+ }
+}
+
diff --git a/.config/waybar/scripts/cava.sh b/.config/waybar/scripts/cava.sh
new file mode 100755
index 0000000..71d7a44
--- /dev/null
+++ b/.config/waybar/scripts/cava.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# 配置
+CHARS="▁▂▃▄▅▆▇█"
+BARS=10
+CONF="/tmp/waybar_cava_config"
+
+# 初始化
+len=$((${#CHARS}-1))
+idle_char="${CHARS:0:1}"
+idle_output=$(printf "%0.s$idle_char" $(seq 1 $BARS))
+
+# 生成 Cava 配置
+cat > "$CONF" </dev/null
+ echo "$idle_output"
+ exit 0
+}
+trap cleanup EXIT INT TERM
+
+# 核心检测:是否存在未暂停的音频流
+is_audio_active() {
+ pactl list sink-inputs 2>/dev/null | grep -q "Corked: no"
+}
+
+# 初始状态
+echo "$idle_output"
+
+while true; do
+ # 如果存在未静音的音频
+ if is_audio_active; then
+ if ! pgrep -P $$ -x cava >/dev/null; then
+ # 这里的 sed 字典是根据你的 CHARS 动态生成的
+ sed_dict="s/;//g;"
+ for ((i=0; i<=${len}; i++)); do
+ sed_dict="${sed_dict}s/$i/${CHARS:$i:1}/g;"
+ done
+ cava -p "$CONF" 2>/dev/null | sed -u "$sed_dict" &
+ fi
+ # 正在播放时,稍微降低检查频率减少 CPU 占用
+ sleep 1
+ else
+ if pgrep -P $$ -x cava >/dev/null; then
+ pkill -P $$ -x cava 2>/dev/null
+ wait 2>/dev/null
+ echo "$idle_output"
+ fi
+ # 没声音时,使用 subscribe 等待事件,被动唤醒,不产生任何循环开销
+ timeout 5s pactl subscribe 2>/dev/null | grep --line-buffered "sink-input" | head -n 1 >/dev/null
+ fi
+done
diff --git a/.config/waybar/scripts/check-updates.sh b/.config/waybar/scripts/check-updates.sh
new file mode 100755
index 0000000..90b05f6
--- /dev/null
+++ b/.config/waybar/scripts/check-updates.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+# === 配置部分 ===
+CACHE_FILE="$HOME/.cache/waybar-updates.json"
+
+# === 函数定义 ===
+generate_json() {
+ local updates=$1
+ local count
+
+ if [ -z "$updates" ]; then
+ count=0
+ else
+ count=$(echo "$updates" | wc -l)
+ fi
+
+ if [ "$count" -gt 0 ]; then
+ local tooltip=$(echo "$updates" | awk '{printf "%s\\n", $0}' | sed 's/"/\\"/g' | head -c -2)
+ printf '{"text": "%s", "alt": "has-updates", "tooltip": "%s"}\n' "$count" "$tooltip"
+ else
+ printf '{"text": "", "alt": "updated", "tooltip": "System is up to date"}\n'
+ fi
+}
+
+# === 主逻辑 ===
+
+# 尝试获取更新
+# 捕获输出
+NEW_UPDATES=$(checkupdates 2>/dev/null)
+STATUS=$?
+
+# === 关键修正 ===
+# checkupdates 退出代码说明:
+# 0 = 有更新
+# 2 = 无更新 (这是正常情况,不是错误!)
+# 1 = 发生错误 (如网络断开、锁被占用)
+
+if [ $STATUS -eq 0 ]; then
+ # --- 情况A:发现更新 ---
+ OUTPUT=$(generate_json "$NEW_UPDATES")
+ echo "$OUTPUT" > "$CACHE_FILE"
+ echo "$OUTPUT"
+
+elif [ $STATUS -eq 2 ]; then
+ # --- 情况B:正常运行,但没有更新 ---
+ # 必须清空缓存或者写入 0 状态,而不是读取旧缓存
+ OUTPUT=$(generate_json "")
+ echo "$OUTPUT" > "$CACHE_FILE"
+ echo "$OUTPUT"
+
+else
+ # --- 情况C:真的出错了 (Exit 1) ---
+ # 比如没网,或者 pacman 锁死
+ # 只有这种时候才读取旧缓存来保底
+ if [ -f "$CACHE_FILE" ]; then
+ cat "$CACHE_FILE"
+ else
+ printf '{"text": "?", "alt": "updated", "tooltip": "Check failed"}\n'
+ fi
+fi
diff --git a/.config/waybar/scripts/longshot-sh/longshot-grim.sh b/.config/waybar/scripts/longshot-sh/longshot-grim.sh
new file mode 100755
index 0000000..60a5d4a
--- /dev/null
+++ b/.config/waybar/scripts/longshot-sh/longshot-grim.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+
+# =================语言=================
+if env | grep -q "zh_CN"; then
+ STR_NEXT="📸 截取下一张 (仅需定高度)"
+ STR_FINISH="💾 完成并处理"
+ STR_ABORT="❌ 放弃"
+ STR_ERR="错误"
+ STR_SAVED="已保存"
+else
+ STR_NEXT="📸 Capture Next (Height only)"
+ STR_FINISH="💾 Finish"
+ STR_ABORT="❌ Abort"
+ STR_ERR="Error"
+ STR_SAVED="Saved"
+fi
+
+# =================配置=================
+CONFIG_DIR="$HOME/.cache/longshot-sh"
+CONFIG_FILE="$CONFIG_DIR/mode"
+SAVE_DIR="$HOME/Pictures/Screenshots/longshots"
+
+TMP_DIR="/tmp/longshot_grim_$(date +%s)"
+FILENAME="longshot_$(date +%Y%m%d_%H%M%S).png"
+RESULT_PATH="$SAVE_DIR/$FILENAME"
+TMP_STITCHED="$TMP_DIR/stitched.png"
+
+mkdir -p "$SAVE_DIR" "$TMP_DIR"
+cleanup() { rm -rf "$TMP_DIR"; }
+trap cleanup EXIT SIGINT SIGTERM
+
+# 菜单工具
+# [修改]: 将 fuzzel 宽度从 45 调整为 30,使其更紧凑
+CMD_FUZZEL="fuzzel -d --anchor=top --y-margin=20 --lines=3 --width=30"
+CMD_WOFI="wofi --dmenu --lines 3"
+CMD_ROFI="rofi -dmenu -l 3"
+
+if command -v fuzzel &> /dev/null; then MENU_CMD="$CMD_FUZZEL"
+elif command -v wofi &> /dev/null; then MENU_CMD="$CMD_WOFI"
+elif command -v rofi &> /dev/null; then MENU_CMD="$CMD_ROFI"
+else exit 1; fi
+
+# [新增]: 动态计算宽度函数 (主要针对 wofi)
+function get_dynamic_width() {
+ local text="$1"
+ # 获取最长行的长度
+ local max_len=$(echo -e "$text" | wc -L)
+ # 计算: 字符数 * 28px + 60px 边距 (可根据屏幕分辨率微调)
+ echo $(( max_len * 28 + 60 ))
+}
+
+# [修改]: 增加对 wofi 的动态宽度支持
+function show_menu() {
+ local content="$1"
+
+ if [[ "$MENU_CMD" == *"wofi"* ]]; then
+ # 如果是 wofi,计算宽度并附加参数
+ local width=$(get_dynamic_width "$content")
+ echo -e "$content" | $MENU_CMD --width "$width"
+ else
+ # 其他工具 (fuzzel/rofi) 保持原样
+ echo -e "$content" | $MENU_CMD
+ fi
+}
+
+# ======================================
+# Step 1: 第一张截图 (直接开始,不询问)
+# ======================================
+# 用户在主菜单点击了 "选择区域",所以这里直接 Slurp
+GEO_1=$(slurp)
+if [ -z "$GEO_1" ]; then exit 0; fi
+
+IFS=', x' read -r FIX_X FIX_Y FIX_W FIX_H <<< "$GEO_1"
+grim -g "$GEO_1" "$TMP_DIR/001.png"
+
+# ======================================
+# Step 2: 循环截图
+# ======================================
+INDEX=2
+DO_SAVE=false
+
+while true; do
+ # 菜单提示下一张 (show_menu 会自动处理宽度)
+ ACTION=$(show_menu "$STR_NEXT\n$STR_FINISH\n$STR_ABORT")
+
+ case "$ACTION" in
+ *"📸"*)
+ sleep 0.2
+ GEO_NEXT=$(slurp)
+ if [ -z "$GEO_NEXT" ]; then continue; fi
+
+ # 锁定宽度和X轴,只取新高度
+ IFS=', x' read -r _TX NEW_Y _TW NEW_H <<< "$GEO_NEXT"
+ FINAL_GEO="${FIX_X},${NEW_Y} ${FIX_W}x${NEW_H}"
+
+ IMG_NAME="$(printf "%03d" $INDEX).png"
+ grim -g "$FINAL_GEO" "$TMP_DIR/$IMG_NAME"
+ ((INDEX++))
+ ;;
+ *"💾"*) DO_SAVE=true; break ;;
+ *"❌"*) exit 0 ;;
+ *) break ;; # 意外退出
+ esac
+done
+
+# ======================================
+# Step 3: 处理与自动动作
+# ======================================
+COUNT=$(ls "$TMP_DIR"/*.png 2>/dev/null | wc -l)
+
+if [ "$COUNT" -gt 0 ] && [ "$DO_SAVE" = true ]; then
+ # 拼接
+ magick "$TMP_DIR"/*.png -append "$TMP_STITCHED"
+ mv "$TMP_STITCHED" "$RESULT_PATH"
+
+ # 复制到剪贴板
+ if command -v wl-copy &> /dev/null; then wl-copy < "$RESULT_PATH"; fi
+
+ # 读取配置执行动作
+ FINAL_MODE=$(cat "$CONFIG_FILE" 2>/dev/null || echo "PREVIEW")
+
+ case "$FINAL_MODE" in
+ "PREVIEW")
+ imv "$RESULT_PATH"
+ ;;
+ "EDIT")
+ if command -v satty &> /dev/null; then satty -f "$RESULT_PATH"
+ else imv "$RESULT_PATH"; fi
+ ;;
+ "SAVE")
+ notify-send -i "$RESULT_PATH" "Longshot" "$STR_SAVED: $(basename "$RESULT_PATH")"
+ ;;
+ esac
+fi
\ No newline at end of file
diff --git a/.config/waybar/scripts/longshot-sh/longshot-wf-recorder.sh b/.config/waybar/scripts/longshot-sh/longshot-wf-recorder.sh
new file mode 100755
index 0000000..038aa15
--- /dev/null
+++ b/.config/waybar/scripts/longshot-sh/longshot-wf-recorder.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+VENV_PYTHON="$SCRIPT_DIR/venv/bin/python"
+PY_STITCH="$SCRIPT_DIR/stitch.py"
+
+CONFIG_DIR="$HOME/.cache/longshot-sh"
+CONFIG_FILE="$CONFIG_DIR/mode"
+SAVE_DIR="$HOME/Pictures/Screenshots/longshots"
+mkdir -p "$SAVE_DIR"
+
+TIMESTAMP=$(date +%Y%m%d_%H%M%S)
+TMP_VIDEO="/tmp/longshot_${TIMESTAMP}.mp4"
+OUTPUT_IMG="${SAVE_DIR}/longshot_${TIMESTAMP}.png"
+
+# 语言
+if env | grep -q "zh_CN"; then
+ TXT_REC="录制中"
+ TXT_MSG="正在拼接..."
+ TXT_SAVED="已保存并复制"
+ WIDTH=6
+else
+ TXT_REC="Recording"
+ TXT_MSG="Stitching..."
+ TXT_SAVED="Saved"
+ WIDTH=10
+fi
+
+# 录制菜单
+if command -v fuzzel &> /dev/null; then
+ MENU_REC_CMD="fuzzel -d --anchor top --y-margin 20 --width $WIDTH --lines 0"
+elif command -v wofi &> /dev/null; then
+ MENU_REC_CMD="wofi -d -i -p Rec"
+else
+ MENU_REC_CMD="rofi -dmenu -p Rec"
+fi
+
+# Step 1: 选区
+GEOMETRY=$(slurp)
+if [ -z "$GEOMETRY" ]; then exit 1; fi
+
+# Step 2: 录制
+wf-recorder -g "$GEOMETRY" -f "$TMP_VIDEO" \
+ -c libx264 -p crf=0 -p preset=ultrafast -p pixel_format=yuv420p \
+ &> /dev/null &
+REC_PID=$!
+
+sleep 0.5
+if ! kill -0 $REC_PID 2>/dev/null; then
+ notify-send "Error" "wf-recorder failed"
+ exit 1
+fi
+
+# Step 3: 停止菜单
+echo "Stop" | $MENU_REC_CMD -p "$TXT_REC" > /dev/null
+
+kill -SIGINT $REC_PID
+wait $REC_PID 2>/dev/null
+
+# Step 4: 处理
+if [ -f "$TMP_VIDEO" ]; then
+ notify-send -t 2000 "Longshot" "$TXT_MSG"
+
+ "$VENV_PYTHON" "$PY_STITCH" "$TMP_VIDEO" "$OUTPUT_IMG"
+ rm -f "$TMP_VIDEO"
+
+ if [ -f "$OUTPUT_IMG" ]; then
+ if command -v wl-copy &> /dev/null; then wl-copy < "$OUTPUT_IMG"; fi
+
+ # 自动执行动作
+ FINAL_MODE=$(cat "$CONFIG_FILE" 2>/dev/null || echo "PREVIEW")
+ case "$FINAL_MODE" in
+ "PREVIEW") imv "$OUTPUT_IMG" ;;
+ "EDIT") if command -v satty &> /dev/null; then satty -f "$OUTPUT_IMG"; else imv "$OUTPUT_IMG"; fi ;;
+ "SAVE") notify-send "Longshot" "$TXT_SAVED: $(basename "$OUTPUT_IMG")" ;;
+ esac
+ fi
+else
+ notify-send "Error" "No video"
+fi
\ No newline at end of file
diff --git a/.config/waybar/scripts/longshot-sh/longshot.sh b/.config/waybar/scripts/longshot-sh/longshot.sh
new file mode 100755
index 0000000..92cb298
--- /dev/null
+++ b/.config/waybar/scripts/longshot-sh/longshot.sh
@@ -0,0 +1,224 @@
+#!/bin/bash
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+VENV_PYTHON="$SCRIPT_DIR/venv/bin/python"
+
+# =================配置区=================
+CONFIG_DIR="$HOME/.cache/longshot-sh"
+mkdir -p "$CONFIG_DIR"
+
+FILE_MODE="$CONFIG_DIR/mode" # PREVIEW / EDIT / SAVE
+FILE_BACKEND="$CONFIG_DIR/backend" # WF / GRIM
+
+# 初始化默认值
+[ ! -f "$FILE_MODE" ] && echo "PREVIEW" > "$FILE_MODE"
+[ ! -f "$FILE_BACKEND" ] && echo "WF" > "$FILE_BACKEND"
+
+# =================语言资源=================
+if env | grep -q "zh_CN"; then
+ TXT_TITLE_WF="缓慢滚动,回车停止"
+ TXT_TITLE_GRIM="记住截图末尾位置"
+
+ TXT_START="📷 选择截图区域"
+ TXT_SETTING="⚙️ 设置"
+ TXT_EXIT="❌ 退出"
+
+ TXT_BACK="🔙 返回主菜单"
+ TXT_SW_BACKEND="📹 切换后端"
+ TXT_SW_ACTION="🛠 切换动作"
+ TXT_PROMPT_ACTION="请选择截图后的动作:"
+
+ TXT_ST_WF="流式录制 (wf-recorder)"
+ TXT_ST_GRIM="分段截图 (grim)"
+
+ TXT_ST_PRE="预览 (imv)"
+ TXT_ST_EDIT="编辑 (satty)"
+ TXT_ST_SAVE="仅保存"
+
+ # 初始化提示
+ TXT_MSG_INIT="首次运行,正在初始化环境..."
+ TXT_MSG_SETUP_DONE="环境初始化完成!"
+ TXT_ERR_SETUP="环境安装失败,请查看 /tmp/longshot_setup.log"
+ TXT_ERR_NO_SETUP="未找到 setup.sh 文件"
+
+ # 新增:依赖缺失提示
+ TXT_ERR_DEP_TITLE="缺少系统依赖"
+ TXT_ERR_DEP_MSG="请安装以下包:"
+else
+ TXT_TITLE_WF="Scroll Slowly, Enter to Stop"
+ TXT_TITLE_GRIM="Remember End Position"
+
+ TXT_START="📷 Select Area"
+ TXT_SETTING="⚙️ Settings"
+ TXT_EXIT="❌ Exit"
+
+ TXT_BACK="🔙 Back"
+ TXT_SW_BACKEND="📹 Switch Backend"
+ TXT_SW_ACTION="🛠 Switch Action"
+ TXT_PROMPT_ACTION="Select action after capture:"
+
+ TXT_ST_WF="Stream (wf-recorder)"
+ TXT_ST_GRIM="Manual (grim)"
+
+ TXT_ST_PRE="Preview"
+ TXT_ST_EDIT="Edit"
+ TXT_ST_SAVE="Save Only"
+
+ # Init messages
+ TXT_MSG_INIT="First run, initializing environment..."
+ TXT_MSG_SETUP_DONE="Environment initialized!"
+ TXT_ERR_SETUP="Setup failed, check /tmp/longshot_setup.log"
+ TXT_ERR_NO_SETUP="setup.sh not found"
+
+ # New: Dependency error
+ TXT_ERR_DEP_TITLE="Missing Dependencies"
+ TXT_ERR_DEP_MSG="Please install:"
+fi
+
+# ================= 1. 系统依赖检测 (新增) =================
+# 检测核心工具: wf-recorder, grim, slurp, imagemagick (magick)
+REQUIRED_TOOLS=("wf-recorder" "grim" "slurp" "magick" "wl-copy")
+MISSING_TOOLS=()
+
+for tool in "${REQUIRED_TOOLS[@]}"; do
+ if ! command -v "$tool" &> /dev/null; then
+ MISSING_TOOLS+=("$tool")
+ fi
+done
+
+if [ ${#MISSING_TOOLS[@]} -ne 0 ]; then
+ # 构建错误信息
+ MSG="${TXT_ERR_DEP_MSG} ${MISSING_TOOLS[*]}"
+
+ # 尝试发送通知
+ if command -v notify-send &> /dev/null; then
+ notify-send -u critical "$TXT_ERR_DEP_TITLE" "$MSG"
+ else
+ # 如果连 notify-send 都没有,这就很尴尬了,尝试用 echo 输出到 stderr
+ echo "❌ $TXT_ERR_DEP_TITLE: $MSG" >&2
+ fi
+ exit 1
+fi
+
+# ================= 2. Python 环境自动检测与修复 =================
+if [ ! -f "$VENV_PYTHON" ]; then
+ notify-send -t 5000 "Longshot" "$TXT_MSG_INIT"
+
+ if [ -f "$SCRIPT_DIR/setup.sh" ]; then
+ chmod +x "$SCRIPT_DIR/setup.sh"
+ "$SCRIPT_DIR/setup.sh" > /tmp/longshot_setup.log 2>&1
+
+ if [ ! -f "$VENV_PYTHON" ]; then
+ notify-send -u critical "Error" "$TXT_ERR_SETUP"
+ exit 1
+ else
+ notify-send -t 3000 "Longshot" "$TXT_MSG_SETUP_DONE"
+ fi
+ else
+ notify-send -u critical "Error" "$TXT_ERR_NO_SETUP"
+ exit 1
+ fi
+fi
+
+# =================菜单工具=================
+if command -v fuzzel &> /dev/null; then
+ MENU_CMD="fuzzel -d --anchor top --y-margin 20 --width 35 --lines 4"
+elif command -v wofi &> /dev/null; then
+ MENU_CMD="wofi -d -i -p Longshot"
+else
+ MENU_CMD="rofi -dmenu"
+fi
+
+# =================主循环=================
+while true; do
+ # 1. 读取当前配置
+ CUR_MODE=$(cat "$FILE_MODE")
+ CUR_BACKEND=$(cat "$FILE_BACKEND")
+
+ # 2. 动态生成 UI 文本
+ CURRENT_TITLE=""
+ if [ "$CUR_BACKEND" == "WF" ]; then
+ CURRENT_TITLE="$TXT_TITLE_WF"
+ else
+ CURRENT_TITLE="$TXT_TITLE_GRIM"
+ fi
+
+ LBL_MODE=""
+ case "$CUR_MODE" in
+ "PREVIEW") LBL_MODE="$TXT_ST_PRE" ;;
+ "EDIT") LBL_MODE="$TXT_ST_EDIT" ;;
+ "SAVE") LBL_MODE="$TXT_ST_SAVE" ;;
+ esac
+
+ LBL_BACKEND=""
+ case "$CUR_BACKEND" in
+ "WF") LBL_BACKEND="$TXT_ST_WF" ;;
+ "GRIM") LBL_BACKEND="$TXT_ST_GRIM" ;;
+ esac
+
+ # 3. 显示主菜单
+ OPTION_START="$TXT_START"
+ OPTION_SETTING="$TXT_SETTING [$LBL_BACKEND | $LBL_MODE]"
+ OPTION_EXIT="$TXT_EXIT"
+
+ if [[ "$MENU_CMD" == *"fuzzel"* ]] || [[ "$MENU_CMD" == *"rofi"* ]]; then
+ CHOICE=$(echo -e "$OPTION_START\n$OPTION_SETTING\n$OPTION_EXIT" | $MENU_CMD -p "$CURRENT_TITLE")
+ else
+ CHOICE=$(echo -e "$OPTION_START\n$OPTION_SETTING\n$OPTION_EXIT" | $MENU_CMD)
+ fi
+
+ # 4. 处理选择
+ if [[ "$CHOICE" == *"$TXT_START"* ]]; then
+ # === 启动后端 ===
+ if [ "$CUR_BACKEND" == "WF" ]; then
+ exec "$SCRIPT_DIR/longshot-wf-recorder.sh"
+ else
+ exec "$SCRIPT_DIR/longshot-grim.sh"
+ fi
+ break
+
+ elif [[ "$CHOICE" == *"$TXT_SETTING"* ]]; then
+ # === 设置菜单循环 ===
+ while true; do
+ S_MODE=$(cat "$FILE_MODE")
+ S_BACK=$(cat "$FILE_BACKEND")
+
+ D_BACK=""; [ "$S_BACK" == "WF" ] && D_BACK="$TXT_ST_WF" || D_BACK="$TXT_ST_GRIM"
+ D_MODE="";
+ case "$S_MODE" in
+ "PREVIEW") D_MODE="$TXT_ST_PRE" ;;
+ "EDIT") D_MODE="$TXT_ST_EDIT" ;;
+ "SAVE") D_MODE="$TXT_ST_SAVE" ;;
+ esac
+
+ ITEM_BACKEND="$TXT_SW_BACKEND [$D_BACK]"
+ ITEM_ACTION="$TXT_SW_ACTION [$D_MODE]"
+
+ if [[ "$MENU_CMD" == *"fuzzel"* ]] || [[ "$MENU_CMD" == *"rofi"* ]]; then
+ S_CHOICE=$(echo -e "$TXT_BACK\n$ITEM_BACKEND\n$ITEM_ACTION" | $MENU_CMD -p "$TXT_SETTING")
+ else
+ S_CHOICE=$(echo -e "$TXT_BACK\n$ITEM_BACKEND\n$ITEM_ACTION" | $MENU_CMD)
+ fi
+
+ if [[ "$S_CHOICE" == *"$TXT_BACK"* ]]; then
+ break
+ elif [[ "$S_CHOICE" == *"$TXT_SW_BACKEND"* ]]; then
+ if [ "$S_BACK" == "WF" ]; then echo "GRIM" > "$FILE_BACKEND"; else echo "WF" > "$FILE_BACKEND"; fi
+ elif [[ "$S_CHOICE" == *"$TXT_SW_ACTION"* ]]; then
+ if [[ "$MENU_CMD" == *"fuzzel"* ]] || [[ "$MENU_CMD" == *"rofi"* ]]; then
+ A_CHOICE=$(echo -e "$TXT_ST_PRE\n$TXT_ST_EDIT\n$TXT_ST_SAVE" | $MENU_CMD -p "$TXT_PROMPT_ACTION")
+ else
+ A_CHOICE=$(echo -e "$TXT_ST_PRE\n$TXT_ST_EDIT\n$TXT_ST_SAVE" | $MENU_CMD)
+ fi
+
+ if [[ "$A_CHOICE" == *"$TXT_ST_PRE"* ]]; then echo "PREVIEW" > "$FILE_MODE"; fi
+ if [[ "$A_CHOICE" == *"$TXT_ST_EDIT"* ]]; then echo "EDIT" > "$FILE_MODE"; fi
+ if [[ "$A_CHOICE" == *"$TXT_ST_SAVE"* ]]; then echo "SAVE" > "$FILE_MODE"; fi
+ else
+ exit 0
+ fi
+ done
+ else
+ exit 0
+ fi
+done
\ No newline at end of file
diff --git a/.config/waybar/scripts/longshot-sh/setup.sh b/.config/waybar/scripts/longshot-sh/setup.sh
new file mode 100755
index 0000000..33f989b
--- /dev/null
+++ b/.config/waybar/scripts/longshot-sh/setup.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+VENV_DIR="$SCRIPT_DIR/venv"
+
+echo "🔧 初始化环境..."
+
+# 1. 检查系统工具
+# 涵盖了两个方案所需的所有工具
+REQUIRED_TOOLS=("wf-recorder" "grim" "slurp" "wl-copy" "magick" "python3")
+MISSING_TOOLS=()
+
+for tool in "${REQUIRED_TOOLS[@]}"; do
+ if ! command -v "$tool" &> /dev/null; then
+ MISSING_TOOLS+=("$tool")
+ fi
+done
+
+if [ ${#MISSING_TOOLS[@]} -ne 0 ]; then
+ echo "⚠️ 警告: 缺少以下系统工具,请使用包管理器安装:"
+ echo " ${MISSING_TOOLS[*]}"
+ echo " (例如 Arch: sudo pacman -S wf-recorder grim slurp wl-clipboard imagemagick python)"
+ echo " (例如 Debian/Ubuntu: sudo apt install wf-recorder grim slurp wl-clipboard imagemagick python3-venv)"
+fi
+
+# 2. Python 虚拟环境
+if [ ! -d "$VENV_DIR" ]; then
+ echo "📦 创建 Python 虚拟环境..."
+ python3 -m venv "$VENV_DIR"
+fi
+
+# 3. 安装 Python 依赖
+echo "⬇️ 安装 Python 库..."
+"$VENV_DIR/bin/pip" install --upgrade pip > /dev/null
+"$VENV_DIR/bin/pip" install opencv-python numpy > /dev/null
+
+# 4. 赋予执行权限
+chmod +x "$SCRIPT_DIR/longshot.sh"
+chmod +x "$SCRIPT_DIR/longshot-wf-recorder.sh"
+chmod +x "$SCRIPT_DIR/longshot-grim.sh"
+chmod +x "$SCRIPT_DIR/stitch.py"
+
+echo "✅ 完成!请运行 ./longshot.sh"
\ No newline at end of file
diff --git a/.config/waybar/scripts/longshot-sh/stitch.py b/.config/waybar/scripts/longshot-sh/stitch.py
new file mode 100755
index 0000000..c57c13b
--- /dev/null
+++ b/.config/waybar/scripts/longshot-sh/stitch.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+import cv2
+import numpy as np
+import sys
+import os
+
+def stitch_video(video_path, output_path):
+ if not os.path.exists(video_path):
+ return
+
+ cap = cv2.VideoCapture(video_path)
+ if not cap.isOpened():
+ print("❌ 无法打开视频")
+ return
+
+ frames = []
+ ret, prev_frame = cap.read()
+ if not ret: return
+
+ frames.append(prev_frame)
+ anchor_frame = prev_frame.copy()
+
+ # ==========================
+ # 核心参数 (手动滚动优化)
+ # ==========================
+ MIN_SCROLL = 2
+ MATCH_CONFIDENCE = 0.5
+
+ # 忽略上下边缘 (防止浏览器地址栏/状态栏干扰)
+ IGNORE_Y_TOP = 0.15
+ IGNORE_Y_BOTTOM = 0.15
+ IGNORE_X = 0.15
+
+ h, w, _ = anchor_frame.shape
+
+ # 有效特征区
+ x1 = int(w * IGNORE_X)
+ x2 = int(w * (1 - IGNORE_X))
+ y1 = int(h * IGNORE_Y_TOP)
+ template_h = int(h * 0.2)
+
+ print(f"⚡ 正在分析 (梯度匹配模式)...")
+
+ last_shift = 0
+ SEARCH_WINDOW = 50
+
+ while True:
+ ret, curr_frame = cap.read()
+ if not ret: break
+
+ # 1. 梯度处理 (解决白底黑字问题)
+ curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)
+ anchor_gray = cv2.cvtColor(anchor_frame, cv2.COLOR_BGR2GRAY)
+
+ curr_grad = cv2.Sobel(curr_gray, cv2.CV_8U, 0, 1, ksize=3)
+ anchor_grad = cv2.Sobel(anchor_gray, cv2.CV_8U, 0, 1, ksize=3)
+
+ # 2. 提取模板
+ template = curr_grad[y1 : y1 + template_h, x1:x2]
+ roi = anchor_grad[y1:, x1:x2]
+
+ # 3. 匹配
+ res = cv2.matchTemplate(roi, template, cv2.TM_CCOEFF_NORMED)
+
+ # 4. 惯性约束
+ if last_shift > 0:
+ mask = np.zeros_like(res)
+ target_y = last_shift
+ y_min = max(0, target_y - SEARCH_WINDOW)
+ y_max = min(res.shape[0], target_y + SEARCH_WINDOW)
+ mask[y_min:y_max, :] = 1
+ res = np.multiply(res, mask)
+
+ min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
+ shift = max_loc[1]
+
+ # 5. 判定
+ if max_val > MATCH_CONFIDENCE and shift > MIN_SCROLL and shift < (roi.shape[0] - 5):
+ new_content_start_y = h - shift
+ if new_content_start_y < h:
+ new_part = curr_frame[new_content_start_y:, :, :]
+ frames.append(new_part)
+ anchor_frame = curr_frame.copy()
+
+ if last_shift == 0: last_shift = shift
+ else: last_shift = int(last_shift * 0.6 + shift * 0.4)
+
+ cap.release()
+
+ if len(frames) > 1:
+ try:
+ full_image = np.vstack(frames)
+ cv2.imwrite(output_path, full_image, [cv2.IMWRITE_PNG_COMPRESSION, 3])
+ print(f"🎉 处理完成")
+ except Exception as e:
+ print(f"❌ 保存失败: {e}")
+ else:
+ print("⚠️ 未检测到滚动,保存第一帧")
+ cv2.imwrite(output_path, frames[0])
+
+if __name__ == "__main__":
+ if len(sys.argv) < 3:
+ print("Usage: python stitch.py ")
+ else:
+ stitch_video(sys.argv[1], sys.argv[2])
\ No newline at end of file
diff --git a/.config/waybar/scripts/old-longshot.sh b/.config/waybar/scripts/old-longshot.sh
new file mode 100755
index 0000000..2acc70a
--- /dev/null
+++ b/.config/waybar/scripts/old-longshot.sh
@@ -0,0 +1,195 @@
+#!/bin/bash
+
+# ==============================================================================
+# 1. 本地化与文案配置
+# ==============================================================================
+# 默认英文
+STR_PROMPT="Longshot> "
+STR_START="⛶ Start Selection (Width as baseline)"
+STR_CANCEL="❌ Cancel"
+STR_NEXT="📸 Capture Next (Height only)"
+STR_SAVE="💾 Save & Finish"
+STR_EDIT="🎨 Edit & Finish"
+STR_ABORT="❌ Abort"
+STR_NOTIFY_TITLE="Longshot"
+STR_NOTIFY_SAVED="Saved to"
+STR_NOTIFY_COPIED="Copied to clipboard"
+STR_ERR_DEP="Missing dependency"
+STR_ERR_MENU="Menu tool not found"
+STR_ERR_TITLE="Error"
+
+# 中文检测
+if env | grep -q "zh_CN"; then
+ STR_PROMPT="长截图> "
+ STR_START="⛶ 开始框选(该图宽视为基准)"
+ STR_CANCEL="❌ 取消"
+ STR_NEXT="📸 截取下一张(只需确定高度)"
+ STR_SAVE="💾 完成并保存"
+ STR_EDIT="🎨 完成并编辑"
+ STR_ABORT="❌ 放弃并退出"
+ STR_NOTIFY_TITLE="长截图完成"
+ STR_NOTIFY_SAVED="已保存至"
+ STR_NOTIFY_COPIED="并已复制到剪贴板"
+ STR_ERR_DEP="缺少核心依赖"
+ STR_ERR_MENU="未找到菜单工具 (fuzzel/rofi/wofi)"
+ STR_ERR_TITLE="错误"
+fi
+
+# ==============================================================================
+# 2. 用户配置与安全初始化
+# ==============================================================================
+SAVE_DIR="$HOME/Pictures/Screenshots/longshots"
+TMP_BASE_NAME="niri_longshot"
+TMP_DIR="/tmp/${TMP_BASE_NAME}_$(date +%s)"
+FILENAME="longshot_$(date +%Y%m%d_%H%M%S).png"
+RESULT_PATH="$SAVE_DIR/$FILENAME"
+TMP_STITCHED="$TMP_DIR/stitched_temp.png"
+
+# --- [保险措施 1] 启动时清理陈旧垃圾 ---
+# 查找 /tmp 下名字包含 niri_longshot 且修改时间超过 10 分钟的目录并删除
+# 这可以防止因断电或 kill -9 导致的垃圾堆积,同时不影响刚启动的其他实例
+find /tmp -maxdepth 1 -type d -name "${TMP_BASE_NAME}_*" -mmin +10 -exec rm -rf {} + 2>/dev/null
+
+# 创建目录
+mkdir -p "$SAVE_DIR"
+mkdir -p "$TMP_DIR"
+
+# --- [保险措施 2] 增强型 Trap ---
+# 无论脚本是正常退出 (EXIT)、被 Ctrl+C (SIGINT)、还是被 kill (SIGTERM),都执行清理
+# 这里的逻辑是:只要脚本进程结束,就删掉本次生成的 TMP_DIR
+cleanup() {
+ rm -rf "$TMP_DIR"
+}
+trap cleanup EXIT SIGINT SIGTERM SIGHUP
+
+# ==============================================================================
+# 3. 依赖与工具探测
+# ==============================================================================
+CMD_FUZZEL="fuzzel -d --anchor=top --y-margin=10 --lines=5 --width=45 --prompt=$STR_PROMPT"
+CMD_ROFI="rofi -dmenu -i -p $STR_PROMPT -l 5"
+CMD_WOFI="wofi --dmenu --lines 5 --prompt $STR_PROMPT"
+
+REQUIRED_CMDS=("grim" "slurp" "magick" "notify-send")
+for cmd in "${REQUIRED_CMDS[@]}"; do
+ if ! command -v "$cmd" &> /dev/null; then
+ PKG_NAME="$cmd"
+ [[ "$cmd" == "magick" ]] && PKG_NAME="imagemagick"
+ notify-send -u critical "$STR_ERR_TITLE" "$STR_ERR_DEP: $cmd\nInstall: sudo pacman -S $PKG_NAME"
+ exit 1
+ fi
+done
+
+EDITOR_CMD=""
+if command -v satty &> /dev/null; then EDITOR_CMD="satty --filename";
+elif command -v swappy &> /dev/null; then EDITOR_CMD="swappy -f"; fi
+
+MENU_CMD=""
+if command -v fuzzel &> /dev/null; then MENU_CMD="$CMD_FUZZEL"
+elif command -v rofi &> /dev/null; then MENU_CMD="$CMD_ROFI"
+elif command -v wofi &> /dev/null; then MENU_CMD="$CMD_WOFI"
+else
+ notify-send -u critical "$STR_ERR_TITLE" "$STR_ERR_MENU"
+ exit 1
+fi
+
+function show_menu() { echo -e "$1" | $MENU_CMD; }
+
+# ==============================================================================
+# 步骤 1: 第一张截图 (基准)
+# ==============================================================================
+
+SELECTION=$(show_menu "$STR_START\n$STR_CANCEL")
+if [[ "$SELECTION" != "$STR_START" ]]; then exit 0; fi
+
+sleep 0.2
+GEO_1=$(slurp)
+# 如果第一步被 Super+Q 杀掉 slurp,GEO_1 为空,脚本会在此退出并触发 cleanup
+if [ -z "$GEO_1" ]; then exit 0; fi
+
+IFS=', x' read -r FIX_X FIX_Y FIX_W FIX_H <<< "$GEO_1"
+grim -g "$GEO_1" "$TMP_DIR/001.png"
+
+# ==============================================================================
+# 步骤 2: 循环截图
+# ==============================================================================
+INDEX=2
+SAVE_MODE=""
+
+while true; do
+ MENU_OPTIONS="$STR_NEXT\n$STR_SAVE"
+ if [[ -n "$EDITOR_CMD" ]]; then MENU_OPTIONS="$MENU_OPTIONS\n$STR_EDIT"; fi
+ MENU_OPTIONS="$MENU_OPTIONS\n$STR_ABORT"
+
+ # 如果此时 Super+Q 杀掉了 Fuzzel,ACTION 为空
+ ACTION=$(show_menu "$MENU_OPTIONS")
+
+ case "$ACTION" in
+ *"📸"*)
+ sleep 0.2
+ GEO_NEXT=$(slurp)
+
+ # 如果此时 Super+Q 杀掉 Slurp,GEO_NEXT 为空,回到菜单
+ if [ -z "$GEO_NEXT" ]; then
+ continue
+ fi
+
+ IFS=', x' read -r _TEMP_X NEW_Y _TEMP_W NEW_H <<< "$GEO_NEXT"
+ FINAL_GEO="${FIX_X},${NEW_Y} ${FIX_W}x${NEW_H}"
+
+ IMG_NAME="$(printf "%03d" $INDEX).png"
+ grim -g "$FINAL_GEO" "$TMP_DIR/$IMG_NAME"
+ ((INDEX++))
+ ;;
+
+ *"💾"*)
+ SAVE_MODE="save"
+ break
+ ;;
+
+ *"🎨"*)
+ SAVE_MODE="edit"
+ break
+ ;;
+
+ *"❌"*)
+ exit 0
+ ;;
+
+ *)
+ # Fuzzel 被 Super+Q 关闭,ACTION 为空,进入这里
+ # 直接 Break 跳出循环,进入保存/拼接流程 (防止误操作导致丢失)
+ # 或者如果你想放弃,这里改成 exit 0
+ break
+ ;;
+ esac
+done
+
+# ==============================================================================
+# 步骤 3: 拼接与后续处理
+# ==============================================================================
+COUNT=$(ls "$TMP_DIR"/*.png 2>/dev/null | wc -l)
+
+if [ "$COUNT" -gt 0 ]; then
+ magick "$TMP_DIR"/*.png -append "$TMP_STITCHED"
+
+ if [[ "$SAVE_MODE" == "edit" ]]; then
+ $EDITOR_CMD "$TMP_STITCHED"
+ fi
+
+ # 只要有保存意向 (SAVE_MODE不为空),或者是因为意外退出且至少有图
+ # 如果你是"意外退出菜单",默认是不保存的 (SAVE_MODE为空)
+ # 这里我们只在显式选择保存/编辑时才保存
+ if [[ -n "$SAVE_MODE" ]]; then
+ mv "$TMP_STITCHED" "$RESULT_PATH"
+
+ COPY_MSG=""
+ if command -v wl-copy &> /dev/null; then
+ wl-copy < "$RESULT_PATH"
+ COPY_MSG="$STR_NOTIFY_COPIED"
+ fi
+
+ notify-send -i "$RESULT_PATH" "$STR_NOTIFY_TITLE" "$STR_NOTIFY_SAVED $FILENAME\n$COPY_MSG"
+ fi
+fi
+
+# 脚本结束,触发 Trap 清理 TMP_DIR
\ No newline at end of file
diff --git a/.config/waybar/scripts/power-screenshot.sh b/.config/waybar/scripts/power-screenshot.sh
new file mode 100755
index 0000000..e22a296
--- /dev/null
+++ b/.config/waybar/scripts/power-screenshot.sh
@@ -0,0 +1,653 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+########################
+# 配置区域(直接改这里)
+########################
+
+NIRI_CONFIG="$HOME/.config/niri/config.kdl" # niri 配置文件
+
+SHOTEDITOR_DEFAULT="satty" # 默认截图编辑器:swappy 或 satty
+COPY_CMD="wl-copy" # 复制到剪贴板的命令
+
+# 菜单程序,按你实际使用的启动器改
+# wofi 示例: MENU_CMD='wofi -d'
+# rofi 示例: MENU_CMD='rofi -dmenu'
+MENU_CMD='fuzzel --dmenu'
+
+# 图片目录
+PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")"
+SCREEN_DIR="$PICTURES_DIR/Screenshots"
+
+########################
+# 本地化(中/英)
+########################
+
+LOCALE="${LC_MESSAGES:-${LANG:-en}}"
+if [[ "$LOCALE" == zh* ]]; then
+ # 通用
+ LABEL_CANCEL="取消"
+ LABEL_SETTINGS="设置"
+ LABEL_EDIT_YES="编辑"
+ LABEL_EDIT_NO="不编辑"
+
+ # Niri 模式
+ LABEL_NIRI_FULL="全屏"
+ LABEL_NIRI_WINDOW="窗口"
+ LABEL_NIRI_REGION="选取区域"
+
+ # Grim 模式
+ LABEL_GRIM_FULL="全屏"
+ LABEL_GRIM_REGION="选取区域"
+
+ # 设置菜单
+ LABEL_SETTINGS_EDITOR="截图工具"
+ LABEL_SETTINGS_BACKEND="后端模式"
+ LABEL_BACKEND_AUTO="自动(检测 Niri)"
+ LABEL_BACKEND_GRIM="仅 Grim+slurp"
+ LABEL_BACK="返回"
+
+ # 编辑开关显示
+ LABEL_EDIT_STATE_ON="编辑:开启"
+ LABEL_EDIT_STATE_OFF="编辑:关闭"
+
+ # 提示文字
+ PROMPT_MAIN="请选择截图模式"
+ PROMPT_SETTINGS="设置 / 更改选项"
+ PROMPT_EDITOR="请选择截图编辑工具"
+ PROMPT_BACKEND="请选择后端模式"
+else
+ LABEL_CANCEL="Cancel"
+ LABEL_SETTINGS="Settings"
+ LABEL_EDIT_YES="Edit"
+ LABEL_EDIT_NO="No edit"
+
+ LABEL_NIRI_FULL="Fullscreen"
+ LABEL_NIRI_WINDOW="Window"
+ LABEL_NIRI_REGION="Region"
+
+ LABEL_GRIM_FULL="Fullscreen"
+ LABEL_GRIM_REGION="Select area"
+
+ LABEL_SETTINGS_EDITOR="Screenshot tool"
+ LABEL_SETTINGS_BACKEND="Backend mode"
+ LABEL_BACKEND_AUTO="Auto (detect Niri)"
+ LABEL_BACKEND_GRIM="Grim+slurp only"
+ LABEL_BACK="Back"
+
+ LABEL_EDIT_STATE_ON="Edit: ON"
+ LABEL_EDIT_STATE_OFF="Edit: OFF"
+
+ PROMPT_MAIN="Choose screenshot mode"
+ PROMPT_SETTINGS="Settings / Options"
+ PROMPT_EDITOR="Choose screenshot editor"
+ PROMPT_BACKEND="Choose backend mode"
+fi
+
+########################
+# 持久化配置路径 (已修改为 .cache 目录)
+########################
+
+XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
+# 旧路径: CONFIG_DIR="$HOME/.config/waybar/waybar-shot"
+CONFIG_DIR="$XDG_CACHE_HOME/waybar-power-screenshot-sh"
+
+BACKEND_FILE="$CONFIG_DIR/backend"
+EDITOR_FILE="$CONFIG_DIR/editor"
+EDIT_MODE_FILE="$CONFIG_DIR/edit_mode" # yes / no
+
+# 确保新的缓存目录存在
+mkdir -p "$CONFIG_DIR"
+
+########################
+# 通用工具函数
+########################
+
+menu() {
+ printf '%s\n' "$@" | eval "$MENU_CMD" 2>/dev/null || true
+}
+
+menu_prompt() {
+ local prompt="$1"
+ shift
+ local esc_prompt="${prompt//\"/\\\"}"
+ printf '%s\n' "$@" | eval "$MENU_CMD --prompt \"$esc_prompt\"" 2>/dev/null || true
+}
+
+load_backend_mode() {
+ local mode
+ if [[ -n "${SHOT_BACKEND:-}" ]]; then
+ mode="$SHOT_BACKEND"
+ elif [[ -f "$BACKEND_FILE" ]]; then
+ mode="$(<"$BACKEND_FILE")"
+ else
+ mode="auto"
+ fi
+ case "$mode" in
+ auto|grim|niri) ;;
+ *) mode="auto" ;;
+ esac
+ printf '%s\n' "$mode"
+}
+
+save_backend_mode() {
+ local mode="$1"
+ # 由于脚本开始时已创建,这里只需要保证文件写入成功
+ printf '%s\n' "$mode" >"$BACKEND_FILE"
+}
+
+load_editor() {
+ local ed
+ if [[ -n "${SHOTEDITOR:-}" ]]; then
+ ed="$SHOTEDITOR"
+ elif [[ -f "$EDITOR_FILE" ]]; then
+ ed="$(<"$EDITOR_FILE")"
+ else
+ ed="$SHOTEDITOR_DEFAULT"
+ fi
+
+ ed="${ed,,}"
+ case "$ed" in
+ swappy|satty) ;;
+ *) ed="$SHOTEDITOR_DEFAULT" ;;
+ esac
+ printf '%s\n' "$ed"
+}
+
+save_editor() {
+ local ed="$1"
+ # 由于脚本开始时已创建,这里只需要保证文件写入成功
+ printf '%s\n' "$ed" >"$EDITOR_FILE"
+}
+
+load_edit_mode() {
+ local v="yes"
+ if [[ -f "$EDIT_MODE_FILE" ]]; then
+ v="$(<"$EDIT_MODE_FILE")"
+ fi
+ case "$v" in
+ yes|no) ;;
+ *) v="yes" ;; # 默认:编辑开启
+ esac
+ printf '%s\n' "$v"
+}
+
+save_edit_mode() {
+ local v="$1"
+ # 由于脚本开始时已创建,这里只需要保证文件写入成功
+ printf '%s\n' "$v" >"$EDIT_MODE_FILE"
+}
+
+detect_backend() {
+ case "$BACKEND_MODE" in
+ niri) echo "niri" ;;
+ grim) echo "grim" ;;
+ auto|*)
+ if command -v niri >/dev/null 2>&1 && pgrep -x niri >/dev/null 2>&1; then
+ echo "niri"
+ else
+ echo "grim"
+ fi
+ ;;
+ esac
+}
+
+choose_editor() {
+ local choice
+ choice="$(menu_prompt "$PROMPT_EDITOR" "swappy" "satty" "$LABEL_BACK")"
+ case "$choice" in
+ swappy|Swappy)
+ SHOTEDITOR="swappy"
+ save_editor "$SHOTEDITOR"
+ ;;
+ satty|Satty)
+ SHOTEDITOR="satty"
+ save_editor "$SHOTEDITOR"
+ ;;
+ *) : ;;
+ esac
+}
+
+choose_backend_mode() {
+ local choice
+ choice="$(menu_prompt "$PROMPT_BACKEND" "$LABEL_BACKEND_AUTO" "$LABEL_BACKEND_GRIM" "$LABEL_BACK")"
+ case "$choice" in
+ "$LABEL_BACKEND_AUTO")
+ BACKEND_MODE="auto"
+ save_backend_mode "$BACKEND_MODE"
+ ;;
+ "$LABEL_BACKEND_GRIM")
+ BACKEND_MODE="grim"
+ save_backend_mode "$BACKEND_MODE"
+ ;;
+ *) : ;;
+ esac
+}
+
+settings_menu() {
+ while :; do
+ local backend_desc editor_line backend_line choice
+
+ if [[ -n "${SHOT_BACKEND:-}" ]]; then
+ backend_desc="${BACKEND_MODE} (env)"
+ else
+ if [[ "$BACKEND_MODE" == "grim" ]]; then
+ backend_desc="$LABEL_BACKEND_GRIM"
+ elif [[ "$BACKEND_MODE" == "niri" ]]; then
+ backend_desc="niri"
+ else
+ backend_desc="$LABEL_BACKEND_AUTO"
+ fi
+ fi
+
+ editor_line="$LABEL_SETTINGS_EDITOR: $SHOTEDITOR"
+ backend_line="$LABEL_SETTINGS_BACKEND: $backend_desc"
+
+ choice="$(menu_prompt "$PROMPT_SETTINGS" "$editor_line" "$backend_line" "$LABEL_BACK")"
+ case "$choice" in
+ "$editor_line") choose_editor ;;
+ "$backend_line")
+ if [[ -n "${SHOT_BACKEND:-}" ]]; then
+ : # 环境变量强制时不改持久化
+ else
+ choose_backend_mode
+ fi
+ ;;
+ *) return ;; # 返回上一层
+ esac
+ done
+}
+
+latest_in_dir() {
+ local dir="$1"
+ find "$dir" -maxdepth 1 -type f -printf '%T@ %p\n' 2>/dev/null \
+ | sort -n | tail -1 | cut -d' ' -f2-
+}
+
+########################
+# 剪贴板相关(Niri 编辑用)
+########################
+
+clip_hash() {
+ wl-paste -t image/png 2>/dev/null \
+ | sha1sum 2>/dev/null \
+ | cut -d' ' -f1 2>/dev/null \
+ || echo ""
+}
+
+wait_clipboard_change() {
+ local old new i
+ old="$(clip_hash)"
+ for i in {1..200}; do # 最多等 ~10 秒
+ new="$(clip_hash)"
+ if [[ -n "$new" && "$new" != "$old" ]]; then
+ return 0
+ fi
+ sleep 0.05
+ done
+ return 1
+}
+
+########################
+# Niri 相关
+########################
+
+get_niri_shot_dir() {
+ [[ -f "$NIRI_CONFIG" ]] || { echo "Config not found: $NIRI_CONFIG" >&2; return 1; }
+
+ local line tpl dir
+ line="$(
+ grep -E '^[[:space:]]*screenshot-path[[:space:]]' "$NIRI_CONFIG" \
+ | grep -v '^[[:space:]]*//' \
+ | tail -n 1 || true
+ )"
+ [[ -n "$line" ]] || { echo "No screenshot-path in config" >&2; return 1; }
+
+ tpl="$(sed -E 's/.*screenshot-path[[:space:]]+"([^"]+)".*/\1/' <<<"$line")"
+ [[ -n "$tpl" ]] || { echo "Failed to parse screenshot-path: $line" >&2; return 1; }
+
+ tpl="${tpl/#\~/$HOME}"
+ dir="${tpl%/*}"
+
+ printf '%s\n' "$dir"
+}
+
+# Grim 用:从文件编辑
+edit_file_image() {
+ local src="$1"
+ local backend="$2" # "niri" 或 "grim"
+
+ local dir ts dst
+
+ if [[ "$backend" == "niri" ]]; then
+ dir="$NIRI_EDIT_DIR"
+ else
+ dir="$SCREEN_DIR"
+ fi
+
+ mkdir -p "$dir"
+ ts="$(date +'%Y-%m-%d_%H-%M-%S')"
+ dst="$dir/$SHOTEDITOR-$ts.png"
+
+ case "$SHOTEDITOR" in
+ satty)
+ satty --filename "$src" --output-filename "$dst"
+ ;;
+ swappy)
+ swappy -f "$src" -o "$dst"
+ ;;
+ *)
+ echo "Unknown SHOTEDITOR: $SHOTEDITOR (use satty or swappy)" >&2
+ return 0
+ ;;
+ esac
+
+ if [[ -f "$dst" ]]; then
+ if [[ "$backend" == "grim" && "$src" == /tmp/* ]]; then
+ rm -f "$src"
+ fi
+ "$COPY_CMD" < "$dst"
+ fi
+}
+
+# Niri 用:从剪贴板编辑
+edit_from_clipboard() {
+ local backend="$1" # 目前只会传 "niri"
+
+ local dir ts dst
+ if [[ "$backend" == "niri" ]]; then
+ dir="$NIRI_EDIT_DIR"
+ else
+ dir="$SCREEN_DIR"
+ fi
+
+ mkdir -p "$dir"
+ ts="$(date +'%Y-%m-%d_%H-%M-%S')"
+ dst="$dir/$SHOTEDITOR-$ts.png"
+
+ case "$SHOTEDITOR" in
+ satty)
+ wl-paste -t image/png 2>/dev/null | satty -f - --output-filename "$dst"
+ ;;
+ swappy)
+ wl-paste -t image/png 2>/dev/null | swappy -f - -o "$dst"
+ ;;
+ *)
+ echo "Unknown SHOTEDITOR: $SHOTEDITOR (use satty or swappy)" >&2
+ return 0
+ ;;
+ esac
+
+ if [[ -f "$dst" ]]; then
+ "$COPY_CMD" < "$dst"
+ fi
+}
+
+niri_capture_and_maybe_edit() {
+ local mode="$1" # fullscreen / window / region
+ local need_edit="$2" # yes / no
+
+ local action
+ case "$mode" in
+ fullscreen) action="screenshot-screen" ;;
+ window) action="screenshot-window" ;;
+ region) action="screenshot" ;;
+ *) return 0 ;;
+ esac
+
+ # 不编辑:用目录里的最新文件判断 screenshot 完成
+ if [[ "$need_edit" != "yes" ]]; then
+ local before shot
+ before="$(latest_in_dir "$NIRI_SHOT_DIR" || true)"
+
+ niri msg action "$action"
+
+ while :; do
+ shot="$(latest_in_dir "$NIRI_SHOT_DIR" || true)"
+ if [[ -z "$before" && -n "$shot" ]] || \
+ [[ -n "$before" && -n "$shot" && "$shot" != "$before" ]]; then
+ break
+ fi
+ sleep 0.05
+ done
+ return 0
+ fi
+
+ # 编辑:基于剪贴板
+ niri msg action "$action"
+
+ if ! wait_clipboard_change; then
+ echo "等待剪贴板中的截图超时" >&2
+ return 0
+ fi
+
+ edit_from_clipboard "niri"
+ return 0
+}
+
+run_niri_flow() {
+ NIRI_SHOT_DIR="$(get_niri_shot_dir)" || return 0
+ NIRI_EDIT_DIR="$NIRI_SHOT_DIR/Edited"
+ mkdir -p "$NIRI_SHOT_DIR" "$NIRI_EDIT_DIR"
+
+ while :; do
+ local choice mode edit_mode edit_label
+
+ edit_mode="$(load_edit_mode)"
+ if [[ "$edit_mode" == "yes" ]]; then
+ edit_label="$LABEL_EDIT_STATE_ON"
+ else
+ edit_label="$LABEL_EDIT_STATE_OFF"
+ fi
+
+ choice="$(menu_prompt "$PROMPT_MAIN" \
+ "$LABEL_NIRI_FULL" \
+ "$LABEL_NIRI_WINDOW" \
+ "$LABEL_NIRI_REGION" \
+ "$edit_label" \
+ "$LABEL_SETTINGS" \
+ "$LABEL_CANCEL"
+ )"
+
+ [[ -z "$choice" || "$choice" == "$LABEL_CANCEL" ]] && return 2
+
+ case "$choice" in
+ "$LABEL_NIRI_FULL") mode="fullscreen" ;;
+ "$LABEL_NIRI_WINDOW") mode="window" ;;
+ "$LABEL_NIRI_REGION") mode="region" ;;
+ "$edit_label")
+ if [[ "$edit_mode" == "yes" ]]; then
+ save_edit_mode "no"
+ else
+ save_edit_mode "yes"
+ fi
+ continue
+ ;;
+ "$LABEL_SETTINGS")
+ # 进入设置菜单(可以在里面改 editor / backend / edit-mode)
+ settings_menu
+
+ # 立即重新加载持久化配置,使修改即时生效
+ SHOTEDITOR="$(load_editor)"
+ BACKEND_MODE="$(load_backend_mode)"
+
+ # 检查后端是否被改动;若改动则通知上层切换后端
+ NEW_BACKEND="$(detect_backend)"
+ if [[ "$NEW_BACKEND" != "niri" ]]; then
+ return 1
+ fi
+
+ continue
+ ;;
+ *)
+ return 2
+ ;;
+ esac
+
+ edit_mode="$(load_edit_mode)"
+ if [[ "$edit_mode" == "yes" ]]; then
+ niri_capture_and_maybe_edit "$mode" "yes"
+ else
+ niri_capture_and_maybe_edit "$mode" "no"
+ fi
+
+ # 截图完成后退出(主循环会根据返回码决定是否结束脚本)
+ return 0
+ done
+}
+
+########################
+# Grim + slurp 相关
+########################
+
+grim_capture_and_maybe_edit() {
+ local mode="$1" # fullscreen / region
+ local need_edit="$2" # yes / no
+
+ mkdir -p "$SCREEN_DIR"
+
+ local ts shot geo
+ ts="$(date +'%Y-%m-%d_%H-%M-%S')"
+
+ if [[ "$need_edit" == "yes" ]]; then
+ # 编辑模式:原图在 /tmp,用完删,只保留编辑后的图
+ shot="/tmp/waybar-shot-$ts.png"
+
+ case "$mode" in
+ fullscreen)
+ grim "$shot"
+ ;;
+ region)
+ geo="$(slurp 2>/dev/null)" || return 0
+ grim -g "$geo" "$shot"
+ ;;
+ *)
+ return 0 ;;
+ esac
+
+ edit_file_image "$shot" "grim"
+ return 0
+ else
+ # 不编辑:原图保存到 Screenshots
+ shot="$SCREEN_DIR/Screenshot_$ts.png"
+
+ case "$mode" in
+ fullscreen)
+ grim "$shot"
+ ;;
+ region)
+ geo="$(slurp 2>/dev/null)" || return 0
+ grim -g "$geo" "$shot"
+ ;;
+ *)
+ return 0 ;;
+ esac
+ return 0
+ fi
+}
+
+run_grim_flow() {
+ mkdir -p "$SCREEN_DIR"
+
+ while :; do
+ local choice mode edit_mode edit_label
+
+ edit_mode="$(load_edit_mode)"
+ if [[ "$edit_mode" == "yes" ]]; then
+ edit_label="$LABEL_EDIT_STATE_ON"
+ else
+ edit_label="$LABEL_EDIT_STATE_OFF"
+ fi
+
+ choice="$(menu_prompt "$PROMPT_MAIN" \
+ "$LABEL_GRIM_FULL" \
+ "$LABEL_GRIM_REGION" \
+ "$edit_label" \
+ "$LABEL_SETTINGS" \
+ "$LABEL_CANCEL"
+ )"
+
+ [[ -z "$choice" || "$choice" == "$LABEL_CANCEL" ]] && return 2
+
+ case "$choice" in
+ "$LABEL_GRIM_FULL") mode="fullscreen" ;;
+ "$LABEL_GRIM_REGION") mode="region" ;;
+ "$edit_label")
+ if [[ "$edit_mode" == "yes" ]]; then
+ save_edit_mode "no"
+ else
+ save_edit_mode "yes"
+ fi
+ continue
+ ;;
+ "$LABEL_SETTINGS")
+ settings_menu
+
+ # 立即重新加载持久化配置,使修改即时生效
+ SHOTEDITOR="$(load_editor)"
+ BACKEND_MODE="$(load_backend_mode)"
+
+ NEW_BACKEND="$(detect_backend)"
+ if [[ "$NEW_BACKEND" != "grim" ]]; then
+ return 1
+ fi
+
+ continue
+ ;;
+ *)
+ return 2
+ ;;
+ esac
+
+ edit_mode="$(load_edit_mode)"
+ if [[ "$edit_mode" == "yes" ]]; then
+ grim_capture_and_maybe_edit "$mode" "yes"
+ else
+ grim_capture_and_maybe_edit "$mode" "no"
+ fi
+
+ return 0
+ done
+}
+
+########################
+# 入口(主循环)
+########################
+
+while :; do
+ BACKEND_MODE="$(load_backend_mode)"
+ SHOTEDITOR="$(load_editor)"
+
+ BACKEND="$(detect_backend)"
+
+ case "$BACKEND" in
+ niri)
+ rc=0
+ run_niri_flow || rc=$?
+ if [[ "$rc" -eq 0 ]]; then
+ exit 0
+ elif [[ "$rc" -eq 1 ]]; then
+ # 后端切换:继续主循环以根据新后端重试
+ continue
+ else
+ # 取消或其他:退出
+ exit 0
+ fi
+ ;;
+ grim)
+ rc=0
+ run_grim_flow || rc=$?
+ if [[ "$rc" -eq 0 ]]; then
+ exit 0
+ elif [[ "$rc" -eq 1 ]]; then
+ continue
+ else
+ exit 0
+ fi
+ ;;
+ *)
+ run_grim_flow
+ exit 0
+ ;;
+ esac
+done
\ No newline at end of file
diff --git a/.config/waybar/scripts/screenshot.sh b/.config/waybar/scripts/screenshot.sh
new file mode 100755
index 0000000..cf4b011
--- /dev/null
+++ b/.config/waybar/scripts/screenshot.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+grim -g "$(slurp)" - | wl-copy
diff --git a/.config/waybar/scripts/toggle-bluetooth.sh b/.config/waybar/scripts/toggle-bluetooth.sh
new file mode 100755
index 0000000..17cddfd
--- /dev/null
+++ b/.config/waybar/scripts/toggle-bluetooth.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+# 检查蓝牙的 rfkill 状态
+# 'rfkill list bluetooth' 会输出蓝牙设备的信息
+# 'grep -q "Soft blocked: yes"' 在输出中安静地 (-q) 查找 "Soft blocked: yes" 字符串
+
+if rfkill list bluetooth | grep -q "Soft blocked: yes"; then
+ # 如果找到了 "Soft blocked: yes" (说明蓝牙被软屏蔽了)
+ # 则执行 unblock 命令来解锁
+ rfkill unblock bluetooth
+ # (可选) 发送一个通知,提供操作反馈
+else
+ # 如果没有找到 "Soft blocked: yes" (说明蓝牙是开启的)
+ # 则执行 block 命令来屏蔽
+ rfkill block bluetooth
+ # (可选) 发送通知
+fi
diff --git a/.config/waybar/scripts/wf-recorder.sh b/.config/waybar/scripts/wf-recorder.sh
new file mode 100755
index 0000000..dc4e8de
--- /dev/null
+++ b/.config/waybar/scripts/wf-recorder.sh
@@ -0,0 +1,791 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+# ================== Runtime state & Persistent Config ==================
+APP="wf-recorder"
+
+# --- 运行时状态 (应在每次会话结束时消失, 遵循 XDG_RUNTIME_DIR) ---
+RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$UID}"
+STATE_DIR="$RUNTIME_DIR/wfrec"
+
+PIDFILE="$STATE_DIR/pid"
+STARTFILE="$STATE_DIR/start"
+SAVEPATH_FILE="$STATE_DIR/save_path"
+MODEFILE="$STATE_DIR/mode" # full/region -> tooltip
+GIF_MARKER="$STATE_DIR/is_gif" # [NEW] 标记当前录制是否为 GIF 模式
+TICKPIDFILE="$STATE_DIR/tickpid"
+WAYBAR_PIDS_CACHE="$STATE_DIR/waybar.pids"
+
+
+# --- 持久性配置 (缓存/设置, 存放在 .cache/ 下, 遵循 XDG_CACHE_HOME) ---
+XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
+CONFIG_DIR="$XDG_CACHE_HOME/wf-recorder-sh" # 目标目录 .cache/wf-recorder-sh
+
+CFG_CODEC="$CONFIG_DIR/codec"
+CFG_FPS="$CONFIG_DIR/framerate"
+CFG_AUDIO="$CONFIG_DIR/audio"
+CFG_DRM="$CONFIG_DIR/drm_device"
+CFG_EXT="$CONFIG_DIR/container_ext" # persisted file format (auto/mp4/mkv/webm)
+
+# 创建所需的目录
+mkdir -p "$STATE_DIR"
+mkdir -p "$CONFIG_DIR"
+
+# Hold chosen mode
+MODE_DECIDED=""
+IS_GIF_MODE="false" # [NEW] 临时变量
+
+# ================== Tunables (ENV overridable) ==================
+# defaults — 默认使用 CPU 编码 (libx264)
+_DEFAULT_CODEC="libx264"
+_DEFAULT_FRAMERATE=""
+_DEFAULT_AUDIO="on"
+_DEFAULT_SAVE_EXT="auto" # auto/mp4/mkv/webm
+
+# --- [NEW] GIF 配置区域 ---
+GIF_WIDTH=720
+GIF_FPS=30
+GIF_DITHER_MODE="bayer:bayer_scale=5"
+GIF_STATS_MODE="diff"
+# -------------------------
+
+# load persisted settings if exist
+codec_from_file=$(cat "$CFG_CODEC" 2>/dev/null || true)
+fps_from_file=$(cat "$CFG_FPS" 2>/dev/null || true)
+audio_from_file=$(cat "$CFG_AUDIO" 2>/dev/null || true)
+drm_from_file=$(cat "$CFG_DRM" 2>/dev/null || true)
+ext_from_file=$(cat "$CFG_EXT" 2>/dev/null || true)
+
+# priority: ENV > persisted > default
+CODEC="${CODEC:-${codec_from_file:-$_DEFAULT_CODEC}}"
+FRAMERATE="${FRAMERATE:-${fps_from_file:-$_DEFAULT_FRAMERATE}}"
+AUDIO="${AUDIO:-${audio_from_file:-$_DEFAULT_AUDIO}}"
+DRM_DEVICE="${DRM_DEVICE:-${drm_from_file:-}}"
+SAVE_EXT="${SAVE_EXT:-${ext_from_file:-$_DEFAULT_SAVE_EXT}}"
+
+TITLE="${TITLE:-}"
+SAVE_DIR_ENV="${SAVE_DIR:-}"
+SAVE_SUBDIR_FS="${SAVE_SUBDIR_FS:-fullscreen}"
+
+OUTPUT="${OUTPUT:-}" # e.g. eDP-1 / DP-2
+OUTPUT_SELECT="${OUTPUT_SELECT:-auto}" # off|auto|menu
+MENU_TITLE_OUTPUT="${MENU_TITLE_OUTPUT:-}"
+MENU_BACKEND="${MENU_BACKEND:-auto}" # auto|fuzzel|wofi|rofi|bemenu|fzf|term
+
+RECORD_MODE="${RECORD_MODE:-ask}" # ask|full|region
+MODE_MENU_TITLE="${MODE_MENU_TITLE:-Select recording mode}"
+REC_AREA="${REC_AREA:-}" # "x,y WIDTHxHEIGHT" (optional)
+GEOM_IN_NAME="${GEOM_IN_NAME:-off}"
+
+WAYBAR_POKE="${WAYBAR_POKE:-on}"
+WAYBAR_SIG="${WAYBAR_SIG:-9}"
+ICON_REC="${ICON_REC:-⏺}"
+ICON_IDLE="${ICON_IDLE:-}"
+
+PKILL_AFTER_STOP="${PKILL_AFTER_STOP:-on}"
+
+# DEBUG: 若设为 on,则在前台运行 wf-recorder,并把输出直接显示到终端(仅终端,不写文件)
+DEBUG="${DEBUG:-off}"
+
+# ================== Utils ==================
+has() { command -v "$1" >/dev/null 2>&1; }
+
+lang_code() {
+ local l="${LC_MESSAGES:-${LANG:-en}}"
+ l="${l,,}"; l="${l%%.*}"; l="${l%%-*}"; l="${l%%_*}"
+ case "$l" in zh|zh-cn|zh-tw|zh-hk) echo zh ;; ja|jp) echo ja ;; *) echo en ;; esac
+}
+
+msg() {
+ local id="$1"; shift
+ case "$(lang_code)" in
+ zh)
+ case "$id" in
+ err_wf_not_found) printf "未找到 wf-recorder" ;;
+ err_need_slurp) printf "需要 slurp 以进行区域选择" ;;
+ err_need_ffmpeg) printf "GIF 转换需要 ffmpeg,但未找到。" ;;
+ warn_drm_ignored) printf "警告:DRM_DEVICE=%s 不存在或不可读,将忽略。" "$@" ;;
+ warn_invalid_fps) printf "警告:FRAMERATE=\"%s\" 非法,已忽略。" "$@" ;;
+ warn_render_unreadable) printf "警告:无效的 render 节点:%s" "$@" ;;
+ cancel_no_mode) printf "已取消:未选择录制模式。" ;;
+ cancel_no_output) printf "已取消:未选择输出。" ;;
+ cancel_no_region) printf "已取消:未选择区域。" ;;
+ warn_multi_outputs_cancel) printf "检测到多个输出但未选择,已取消。" ;;
+ notif_started_full) printf "开始录制(全屏:%s)→ %s" "$@" ;;
+ notif_started_region) printf "开始录制(区域)→ %s" "$@" ;;
+ notif_device_suffix) printf "(设备 %s)" "$@" ;;
+ notif_saved) printf "已保存:%s" "$@" ;;
+ notif_stopped) printf "已停止录制。" ;;
+ notif_processing_gif) printf "正在转换为 GIF,请稍候..." ;;
+ notif_gif_failed) printf "GIF 转换失败,保留原视频。" ;;
+ notif_copied) printf "文件已复制" ;;
+ already_running) printf "already running" ;;
+ not_running) printf "not running" ;;
+ title_mode) printf "选择录制模式" ;;
+ title_output) printf "选择输出" ;;
+ menu_fullscreen) printf "全屏" ;;
+ menu_region) printf "选择区域" ;;
+ menu_gif_region) printf "录制 GIF (区域)" ;;
+ # settings labels -> "标签:值"
+ title_settings) printf "设置..." ;;
+ menu_settings) printf "设置..." ;;
+ menu_set_codec) printf "编码格式:%s" "$@" ;;
+ menu_set_fps) printf "帧率:%s" "$@" ;;
+ menu_set_filefmt) printf "文件格式:%s" "$@" ;;
+ menu_toggle_audio) printf "音频:%s" "$@" ;;
+ menu_set_render) printf "渲染设备:%s" "$@" ;;
+ menu_back) printf "返回" ;;
+ fps_unlimited) printf "不限制" ;;
+ render_auto) printf "自动" ;;
+ ext_auto) printf "自动" ;;
+ title_select_codec) printf "选择编码格式" ;;
+ title_select_fps) printf "选择帧率" ;;
+ title_select_filefmt) printf "选择文件格式" ;;
+ title_select_render) printf "选择渲染设备(/dev/dri/renderD*)" ;;
+ mode_full) printf "全屏" ;;
+ mode_region) printf "区域" ;;
+ prompt_enter_number) printf "输入编号:" ;;
+ menu_exit) printf "退出" ;;
+ *) printf "%s" "$id" ;;
+ esac
+ ;;
+ ja)
+ case "$id" in
+ err_wf_not_found) printf "wf-recorder が見つかりません" ;;
+ err_need_slurp) printf "領域選択には slurp が必要です" ;;
+ err_need_ffmpeg) printf "GIF変換には ffmpeg が必要ですが、見つかりません。" ;;
+ warn_drm_ignored) printf "警告:DRM_DEVICE=%s は無視されます。" "$@" ;;
+ warn_invalid_fps) printf "警告:FRAMERATE=\"%s\" は不正です。" "$@" ;;
+ warn_render_unreadable) printf "警告:無効なレンダー ノード:%s" "$@" ;;
+ cancel_no_mode) printf "キャンセル:録画モード未選択。" ;;
+ cancel_no_output) printf "キャンセル:出力未選択。" ;;
+ cancel_no_region) printf "キャンセル:領域未選択。" ;;
+ warn_multi_outputs_cancel) printf "出力が複数ですが未選択のため中止。" ;;
+ notif_started_full) printf "録画開始(全画面:%s)→ %s" "$@" ;;
+ notif_started_region) printf "録画開始(領域)→ %s" "$@" ;;
+ notif_device_suffix) printf "(デバイス %s)" "$@" ;;
+ notif_saved) printf "保存しました:%s" "$@" ;;
+ notif_stopped) printf "録画を停止しました。" ;;
+ notif_processing_gif) printf "GIF に変換中、お待ちください..." ;;
+ notif_gif_failed) printf "GIF 変換に失敗しました。元の動画を保持します。" ;;
+ notif_copied) printf "ファイルをコピーしました" ;;
+ already_running) printf "already running" ;;
+ not_running) printf "not running" ;;
+ title_mode) printf "録画モードを選択" ;;
+ title_output) printf "出力を選択" ;;
+ menu_fullscreen) printf "全画面" ;;
+ menu_region) printf "領域選択" ;;
+ menu_gif_region) printf "GIF録画 (領域)" ;;
+ # settings labels -> "ラベル:値"(全角コロン)
+ title_settings) printf "設定..." ;;
+ menu_settings) printf "設定..." ;;
+ menu_set_codec) printf "コーデック:%s" "$@" ;;
+ menu_set_fps) printf "フレームレート:%s" "$@" ;;
+ menu_set_filefmt) printf "ファイル形式:%s" "$@" ;;
+ menu_toggle_audio) printf "音声:%s" "$@" ;;
+ menu_set_render) printf "レンダーデバイス:%s" "$@" ;;
+ menu_back) printf "戻る" ;;
+ fps_unlimited) printf "無制限" ;;
+ render_auto) printf "自動" ;;
+ ext_auto) printf "自動" ;;
+ title_select_codec) printf "コーデックを選択" ;;
+ title_select_fps) printf "フレームレートを選択" ;;
+ title_select_filefmt) printf "ファイル形式を選択" ;;
+ title_select_render) printf "レンダーデバイスを選択(/dev/dri/renderD*)" ;;
+ mode_full) printf "全画面" ;;
+ mode_region) printf "領域" ;;
+ prompt_enter_number) printf "番号を入力:" ;;
+ menu_exit) printf "終了" ;;
+ *) printf "%s" "$id" ;;
+ esac
+ ;;
+ *)
+ case "$id" in
+ err_wf_not_found) printf "wf-recorder not found" ;;
+ err_need_slurp) printf "slurp required for region selection" ;;
+ err_need_ffmpeg) printf "ffmpeg is required for GIF conversion but not found." ;;
+ warn_drm_ignored) printf "Warning: DRM_DEVICE=%s ignored." "$@" ;;
+ warn_invalid_fps) printf "Warning: invalid FRAMERATE=\"%s\"." "$@" ;;
+ warn_render_unreadable) printf "Warning: invalid render node: %s" "$@" ;;
+ cancel_no_mode) printf "Canceled: no recording mode selected." ;;
+ cancel_no_output) printf "Canceled: no output selected." ;;
+ cancel_no_region) printf "Canceled: no region selected." ;;
+ warn_multi_outputs_cancel) printf "Multiple outputs but none selected; canceled." ;;
+ notif_started_full) printf "Recording started (fullscreen: %s) → %s" "$@" ;;
+ notif_started_region) printf "Recording started (region) → %s" "$@" ;;
+ notif_device_suffix) printf " (device %s)" "$@" ;;
+ notif_saved) printf "Saved: %s" "$@" ;;
+ notif_stopped) printf "Recording stopped." ;;
+ notif_processing_gif) printf "Converting to GIF, please wait..." ;;
+ notif_gif_failed) printf "GIF conversion failed. Original video kept." ;;
+ notif_copied) printf "File copied" ;;
+ already_running) printf "already running" ;;
+ not_running) printf "not running" ;;
+ title_mode) printf "Select recording mode" ;;
+ title_output) printf "Select output" ;;
+ menu_fullscreen) printf "Fullscreen" ;;
+ menu_region) printf "Region" ;;
+ menu_gif_region) printf "Record GIF (Region)" ;;
+ # settings labels -> "Label: Value"
+ title_settings) printf "Settings..." ;;
+ menu_settings) printf "Settings..." ;;
+ menu_set_codec) printf "Codec: %s" "$@" ;;
+ menu_set_fps) printf "Framerate: %s" "$@" ;;
+ menu_set_filefmt) printf "File Format: %s" "$@" ;;
+ menu_toggle_audio) printf "Audio: %s" "$@" ;;
+ menu_set_render) printf "Render Device: %s" "$@" ;;
+ menu_back) printf "Back" ;;
+ fps_unlimited) printf "unlimited" ;;
+ render_auto) printf "Auto" ;;
+ ext_auto) printf "Auto" ;;
+ title_select_codec) printf "Select Codec" ;;
+ title_select_fps) printf "Select Framerate" ;;
+ title_select_filefmt) printf "Select File Format" ;;
+ title_select_render) printf "Select Render Device (/dev/dri/renderD*)" ;;
+ mode_full) printf "Fullscreen" ;;
+ mode_region) printf "Region" ;;
+ prompt_enter_number) printf "Enter number: " ;;
+ menu_exit) printf "Exit" ;;
+ *) printf "%s" "$id" ;;
+ esac
+ ;;
+ esac
+}
+
+is_running() {
+ [[ -r "$PIDFILE" ]] || return 1
+ local pid; read -r pid <"$PIDFILE" 2>/dev/null || return 1
+ [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null
+}
+notify() { has notify-send && notify-send "wf-recorder" "$1" || true; }
+
+signal_waybar() {
+ local pids
+ if [[ -r "$WAYBAR_PIDS_CACHE" ]]; then
+ pids="$(tr '\n' ' ' <"$WAYBAR_PIDS_CACHE")"
+ if [[ -n "$pids" ]]; then kill -RTMIN+"$WAYBAR_SIG" $pids 2>/dev/null && return 0; fi
+ fi
+ pids="$(pgrep -x -u "$UID" waybar 2>/dev/null | tr '\n' ' ')"
+ [[ -n "$pids" ]] && printf '%s\n' $pids >"$WAYBAR_PIDS_CACHE"
+ [[ -n "$pids" ]] && kill -RTMIN+"$WAYBAR_SIG" $pids 2>/dev/null || true
+}
+emit_waybar_signal() { [[ "${WAYBAR_POKE,,}" == "off" ]] && return 0; signal_waybar; }
+
+start_tick() {
+ if [[ -f "$TICKPIDFILE" ]]; then
+ local tpid; read -r tpid <"$TICKPIDFILE" 2>/dev/null || true
+ [[ -n "$tpid" ]] && kill -TERM "$tpid" 2>/dev/null || true
+ rm -f "$TICKPIDFILE"
+ fi
+ (
+ while :; do
+ [[ -r "$PIDFILE" ]] || break
+ local p; read -r p <"$PIDFILE" 2>/dev/null || p=""
+ [[ -n "$p" ]] && kill -0 "$p" 2>/dev/null || break
+ signal_waybar
+ sleep 1
+ done
+ ) & echo $! >"$TICKPIDFILE"
+}
+stop_tick() {
+ if [[ -f "$TICKPIDFILE" ]]; then
+ local tpid; read -r tpid <"$TICKPIDFILE" 2>/dev/null || true
+ [[ -n "$tpid" ]] && kill -TERM "$tpid" 2>/dev/null || true
+ rm -f "$TICKPIDFILE"
+ fi
+}
+
+get_save_dir() {
+ local videos
+ if has xdg-user-dir; then videos="$(xdg-user-dir VIDEOS 2>/dev/null || true)"; fi
+ videos="${videos:-"$HOME/Videos"}"
+ echo "${SAVE_DIR_ENV:-"$videos/wf-recorder"}"
+}
+
+# --- render device helpers ---
+list_render_nodes() {
+ local d
+ for d in /dev/dri/renderD*; do
+ [[ -r "$d" ]] && printf '%s\n' "$d"
+ done 2>/dev/null || true
+}
+render_display() {
+ local cur="${1:-}"
+ if [[ -z "$cur" ]]; then
+ msg render_auto
+ else
+ printf "%s" "$cur"
+ fi
+}
+pick_render_device() {
+ local dev="${DRM_DEVICE:-}"
+ if [[ -n "$dev" && ! -r "$dev" ]]; then
+ printf '%s\n' "$(msg warn_render_unreadable "$dev")" >&2
+ dev=""
+ fi
+ echo -n "$dev"
+}
+
+# --- file format helpers ---
+ext_for_codec(){ case "${1,,}" in
+ *h264*|*hevc*) echo mp4 ;;
+ *vp9*) echo webm ;;
+ *av1*) echo mkv ;;
+ *) echo mp4 ;;
+esac; }
+choose_ext(){
+ local e="${SAVE_EXT,,}"
+ if [[ -z "$e" || "$e" == "auto" ]]; then
+ ext_for_codec "$CODEC"
+ else
+ case "$e" in mp4|mkv|webm) echo "$e" ;; *) echo mp4 ;; esac
+ fi
+}
+
+# ================== Menus ==================
+__norm() { printf '%s' "$1" | tr -d '\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'; }
+
+_pick_menu_backend() {
+ local pref="${MENU_BACKEND,,}"
+ case "$pref" in fuzzel|wofi|rofi|bemenu|fzf|term) : ;; auto|"") pref="auto" ;; *) pref="auto" ;; esac
+ if [[ "$pref" != "auto" ]]; then
+ if has "$pref"; then echo "$pref"; else [[ -t 0 ]] && echo "term" || echo "none"; fi
+ return
+ fi
+ for b in fuzzel wofi rofi bemenu fzf; do has "$b" && { echo "$b"; return; }; done
+ [[ -t 0 ]] && echo "term" || echo "none"
+}
+
+menu_pick() { # $1:title; items...
+ local title="${1:-Select}"; shift
+ local items=("$@")
+ ((${#items[@]})) || return 130
+
+ local backend; backend="$(_pick_menu_backend)"
+ local sel rc=130
+ case "$backend" in
+ fuzzel) set +e; sel="$(printf '%s\n' "${items[@]}" | fuzzel --dmenu -p "$title")"; rc=$?; set -e ;;
+ wofi) set +e; sel="$(printf '%s\n' "${items[@]}" | wofi --dmenu --prompt "$title")"; rc=$?; set -e ;;
+ rofi) set +e; sel="$(printf '%s\n' "${items[@]}" | rofi -dmenu -p "$title")"; rc=$?; set -e ;;
+ bemenu) set +e; sel="$(printf '%s\n' "${items[@]}" | bemenu -p "$title")"; rc=$?; set -e ;;
+ fzf) set +e; sel="$(printf '%s\n' "${items[@]}" | fzf --prompt "$title> ")"; rc=$?; set -e ;;
+ term)
+ echo "$title"
+ local i=1; for it in "${items[@]}"; do printf ' %d) %s\n' "$i" "$it"; ((i++)); done
+ printf "%s" "$(msg prompt_enter_number)"
+ local idx; set +e; read -r idx; rc=$?; set -e
+ if [[ $rc -eq 0 && -n "$idx" && "$idx" =~ ^[0-9]+$ ]]; then
+ if (( idx>=1 && idx<=${#items[@]} )); then sel="${items[$((idx-1))]}"; rc=0; fi
+ fi
+ ;;
+ none) return 130 ;;
+ esac
+ [[ $rc -ne 0 || -z "${sel:-}" ]] && return 130
+ printf '%s' "$(__norm "$sel")"
+}
+
+# ---------- Outputs ----------
+list_outputs() {
+ local raw
+ if raw="$(wf-recorder -L 2>/dev/null)"; then :; elif has wlr-randr; then raw="$(wlr-randr 2>/dev/null | awk '/^[^ ]/{print $1}')"; else raw=""; fi
+ awk 'BEGIN{RS="[ \t\r\n,]+"} /^[A-Za-z0-9_.:-]+$/ { if ($0 ~ /^(e?DP|HDMI|DVI|VGA|LVDS|Virtual|XWAYLAND)/) seen[$0]=1 } END{for(k in seen) print k}' <<<"$raw" | sort -u
+}
+decide_output() {
+ if [[ -n "$OUTPUT" ]]; then printf '%s' "$OUTPUT"; return 0; fi
+ local -a outs; mapfile -t outs < <(list_outputs || true)
+ local out_title; out_title="${MENU_TITLE_OUTPUT:-$(msg title_output)}"
+ if [[ "${OUTPUT_SELECT}" == "menu" ]] || { [[ "${OUTPUT_SELECT}" == "auto" ]] && ((${#outs[@]} > 1)); }; then
+ local pick; pick="$(menu_pick "$out_title" "${outs[@]}")" || return 130
+ printf '%s' "$pick"; return 0
+ fi
+ if ((${#outs[@]} == 1)); then printf '%s' "${outs[0]}"; else printf '%s\n' "$(msg warn_multi_outputs_cancel)" >&2; return 130; fi
+}
+
+# ---------- Settings ----------
+choose_render_menu() {
+ local -a nodes
+ mapfile -t nodes < <(list_render_nodes | sort -V || true)
+ local auto_item; auto_item="$(msg render_auto)"
+ local pick
+ if ! pick="$(menu_pick "$(msg title_select_render)" "$auto_item" "${nodes[@]}")"; then
+ return 0
+ fi
+ if [[ "$pick" == "$auto_item" ]]; then
+ DRM_DEVICE=""
+ rm -f "$CFG_DRM"
+ return 0
+ fi
+ local sel="$pick"
+ if [[ -n "$sel" && -r "$sel" ]]; then
+ DRM_DEVICE="$sel"
+ printf '%s' "$DRM_DEVICE" >"$CFG_DRM"
+ else
+ printf '%s\n' "$(msg warn_render_unreadable "$sel")" >&2
+ fi
+}
+
+choose_filefmt_menu() {
+ local auto_item; auto_item="$(msg ext_auto)"
+ local pick
+ if ! pick="$(menu_pick "$(msg title_select_filefmt)" "$auto_item" "mp4" "mkv" "webm")"; then
+ return 0
+ fi
+ if [[ "$pick" == "$auto_item" ]]; then
+ SAVE_EXT="auto"
+ rm -f "$CFG_EXT"
+ else
+ case "$pick" in
+ mp4|mkv|webm) SAVE_EXT="$pick"; printf '%s' "$SAVE_EXT" >"$CFG_EXT" ;;
+ *) : ;;
+ esac
+ fi
+}
+
+show_settings_menu() {
+ while :; do
+ local fps_display="${FRAMERATE:-$(msg fps_unlimited)}"
+ local audio_display="${AUDIO}"
+ local render_display_now; render_display_now="$(render_display "$DRM_DEVICE")"
+ local ff_display; if [[ -z "$SAVE_EXT" || "${SAVE_EXT,,}" == "auto" ]]; then ff_display="$(msg ext_auto)"; else ff_display="$SAVE_EXT"; fi
+
+ # ORDER: Framerate → Audio → Codec → File Format → Render → Back
+ local pick; pick="$(menu_pick "$(msg title_settings)" \
+ "$(msg menu_set_fps "$fps_display")" \
+ "$(msg menu_toggle_audio "$audio_display")" \
+ "$(msg menu_set_codec "$CODEC")" \
+ "$(msg menu_set_filefmt "$ff_display")" \
+ "$(msg menu_set_render "$render_display_now")" \
+ "$(msg menu_back)")" || return 0
+
+ if [[ "$pick" == "$(msg menu_set_fps "$fps_display")" ]]; then
+ local newf; newf="$(menu_pick "$(msg title_select_fps)" "60" "30" "120" "144" "165" "240" "$(msg fps_unlimited)")" || continue
+ if [[ "$newf" == "$(msg fps_unlimited)" ]]; then
+ FRAMERATE=""; rm -f "$CFG_FPS"
+ else
+ if [[ "$newf" =~ ^[0-9]+$ && "$newf" -gt 0 ]]; then FRAMERATE="$newf"; printf '%s' "$FRAMERATE" >"$CFG_FPS"; fi
+ fi
+
+ elif [[ "$pick" == "$(msg menu_toggle_audio "$audio_display")" ]]; then
+ if [[ "$AUDIO" == "on" ]]; then AUDIO="off"; else AUDIO="on"; fi
+ printf '%s' "$AUDIO" >"$CFG_AUDIO"
+
+ elif [[ "$pick" == "$(msg menu_set_codec "$CODEC")" ]]; then
+ # 仅保留 CPU (libx264) 与所有常见 VAAPI 编码选项,CPU 放在首位
+ local newc; newc="$(menu_pick "$(msg title_select_codec)" \
+ "libx264" "h264_vaapi" "hevc_vaapi" "av1_vaapi" "vp9_vaapi")" || continue
+ CODEC="$newc"; printf '%s' "$CODEC" >"$CFG_CODEC"
+
+ elif [[ "$pick" == "$(msg menu_set_filefmt "$ff_display")" ]]; then
+ choose_filefmt_menu
+
+ elif [[ "$pick" == "$(msg menu_set_render "$render_display_now")" ]]; then
+ choose_render_menu
+
+ elif [[ "$pick" == "$(msg menu_back)" ]]; then
+ return 0
+ fi
+ # loop to refresh values instantly
+ done
+}
+
+# ---------- Mode selection ----------
+decide_mode() {
+ case "${RECORD_MODE,,}" in
+ full|fullscreen) MODE_DECIDED="full"; return 0 ;;
+ region|area) MODE_DECIDED="region"; return 0 ;;
+ *) ;;
+ esac
+ local L_FULL L_REGION L_GIF L_SETTINGS L_EXIT
+ case "$(lang_code)" in
+ zh) L_FULL="$(msg menu_fullscreen)"; L_REGION="$(msg menu_region)"; L_GIF="$(msg menu_gif_region)"; L_SETTINGS="$(msg menu_settings)"; L_EXIT="$(msg menu_exit)";;
+ ja) L_FULL="$(msg menu_fullscreen)"; L_REGION="$(msg menu_region)"; L_GIF="$(msg menu_gif_region)"; L_SETTINGS="$(msg menu_settings)"; L_EXIT="$(msg menu_exit)";;
+ *) L_FULL="Fullscreen"; L_REGION="Region"; L_GIF="$(msg menu_gif_region)"; L_SETTINGS="$(msg menu_settings)"; L_EXIT="$(msg menu_exit)";;
+ esac
+ local title; title="$(msg title_mode)"
+ while :; do
+ # ORDER: Fullscreen -> Region -> GIF -> Settings -> Exit
+ # [FIXED] 调整菜单顺序以匹配图片要求:全屏在最前,GIF在区域之后
+ local pick; pick="$(menu_pick "$title" "$L_FULL" "$L_REGION" "$L_GIF" "$L_SETTINGS" "$L_EXIT")" || return 130
+ if [[ "$pick" == "$L_FULL" ]]; then MODE_DECIDED="full"; return 0
+ elif [[ "$pick" == "$L_REGION" ]]; then MODE_DECIDED="region"; return 0
+ elif [[ "$pick" == "$L_GIF" ]]; then MODE_DECIDED="region"; IS_GIF_MODE="true"; return 0
+ elif [[ "$pick" == "$L_SETTINGS" ]]; then show_settings_menu; continue
+ elif [[ "$pick" == "$L_EXIT" ]]; then return 130
+ else return 130; fi
+ done
+}
+
+# ---------- Helpers ----------
+geom_token() {
+ local g="$1"
+ awk 'NF==2{split($1,a,","); split($2,b,"x");
+ if(a[1]!=""){printf "%sx%s@%s,%s",b[1],b[2],a[1],a[2]}}' <<<"$g"
+}
+pretty_dur() {
+ local dur="${1:-0}"
+ [[ "$dur" =~ ^[0-9]+$ ]] || dur=0
+ if ((dur>=3600)); then printf "%d:%02d:%02d" $((dur/3600)) $(((dur%3600)/60)) $((dur%60))
+ else printf "%02d:%02d" $((dur/60)) $((dur%60)); fi
+}
+json_escape() { sed ':a;N;$!ba;s/\\/\\\\/g;s/"/\\"/g;s/\n/\\n/g'; }
+
+# ================== Start / Stop ==================
+start_rec() {
+ if is_running; then echo "$(msg already_running)"; exit 0; fi
+ has wf-recorder || { echo "$(msg err_wf_not_found)"; exit 1; }
+
+ MODE_DECIDED=""
+ IS_GIF_MODE="false"
+ if ! decide_mode; then
+ echo "$(msg cancel_no_mode)"; emit_waybar_signal; exit 130
+ fi
+ local mode="$MODE_DECIDED"
+
+ # [NEW] GIF 模式检查
+ if [[ "$IS_GIF_MODE" == "true" ]]; then
+ if ! has ffmpeg; then echo "$(msg err_need_ffmpeg)"; emit_waybar_signal; exit 1; fi
+ # GIF 模式强制使用 mp4 作为中间格式,因为 mp4 兼容性好且编码速度快
+ SAVE_EXT="mp4"
+ touch "$GIF_MARKER"
+ else
+ rm -f "$GIF_MARKER"
+ fi
+
+ local marker="" output="" GEOM="" gtok=""
+ local -a args
+ args=( -c "$CODEC" )
+
+ local ROOT_DIR TARGET_DIR
+ ROOT_DIR="$(get_save_dir)"
+ if [[ "$mode" == "full" ]]; then TARGET_DIR="$ROOT_DIR/${SAVE_SUBDIR_FS}"; else TARGET_DIR="$ROOT_DIR"; fi
+ mkdir -p "$TARGET_DIR"
+
+ if [[ "$mode" == "full" ]]; then
+ output="$(decide_output)" || { echo "$(msg cancel_no_output)"; emit_waybar_signal; exit 130; }
+ [[ -n "$output" ]] && args+=( -o "$output" )
+ marker="FS${output:+-$output}"
+ else
+ if [[ -n "$REC_AREA" ]]; then
+ GEOM="$REC_AREA"
+ else
+ has slurp || { echo "$(msg err_need_slurp)"; emit_waybar_signal; exit 1; }
+ set +e; GEOM="$(slurp)"; local rc=$?; set -e
+ if [[ $rc -ne 0 || -z "${GEOM// /}" ]]; then echo "$(msg cancel_no_region)"; emit_waybar_signal; exit 130; fi
+ fi
+ GEOM="$(echo -n "$GEOM" | tr -s '[:space:]' ' ')"
+ args+=( -g "$GEOM" )
+ if [[ "${GEOM_IN_NAME,,}" == "on" ]]; then gtok="$(geom_token "$GEOM")"; marker="REGION${gtok:+-$gtok}"; else marker="REGION"; fi
+ fi
+
+ local ts safe_title base SAVE_PATH ext
+ ts="$(date +'%Y-%m-%d-%H%M%S')"; safe_title="${TITLE// /_}"
+ base="$ts${safe_title:+-$safe_title}-${marker}"
+ ext="$(choose_ext)"
+ SAVE_PATH="$TARGET_DIR/$base.$ext"
+
+ args=( --file "$SAVE_PATH" "${args[@]}" )
+
+ # Render device
+ local dev; dev="$(pick_render_device)"; [[ -n "$dev" ]] && args+=( -d "$dev" )
+
+ # Audio
+ case "$AUDIO" in off|OFF|0|false) ;; on|ON|1|true|"") args+=( --audio ) ;; *) args+=( --audio="$AUDIO" ) ;; esac
+
+ # Framerate
+ if [[ -n "$FRAMERATE" ]]; then
+ if [[ "$FRAMERATE" =~ ^[0-9]+$ && "$FRAMERATE" -gt 0 ]]; then args+=( --framerate "$FRAMERATE" )
+ else printf '%s\n' "$(msg warn_invalid_fps "$FRAMERATE")" >&2; fi
+ fi
+
+ # Pixel format
+ if [[ "$CODEC" == *"_vaapi" ]]; then args+=( -F "scale_vaapi=format=nv12:out_range=full:out_color_primaries=bt709" )
+ else args+=( -F "format=yuv420p" ); fi
+
+ # === 不保存日志:仅在 DEBUG=on 时将 wf-recorder 输出到终端 ===
+ if [[ "${DEBUG,,}" == "on" ]]; then
+ echo "DEBUG=on: running wf-recorder in foreground"
+ echo "Command: wf-recorder ${args[*]}"
+ wf-recorder "${args[@]}" 2>&1 &
+ local pid=$!
+ echo "$pid" >"$PIDFILE"
+ date +%s >"$STARTFILE"
+ echo "$SAVE_PATH" >"$SAVEPATH_FILE"
+ echo "$mode" >"$MODEFILE"
+ local note; if [[ "$mode" == "full" ]]; then note="$(msg notif_started_full "$output" "$SAVE_PATH")"; else note="$(msg notif_started_region "$SAVE_PATH")"; fi
+ [[ -n "$dev" ]] && note+="$(msg notif_device_suffix "$dev")"
+ echo "$note";
+ emit_waybar_signal
+ start_tick
+ return 0
+ fi
+
+ # 非 DEBUG:后台运行,且不保存任何日志(与原脚本行为相近)
+ setsid nohup wf-recorder "${args[@]}" >/dev/null 2>&1 &
+ local pid=$!
+ echo "$pid" >"$PIDFILE"
+ date +%s >"$STARTFILE"
+ echo "$SAVE_PATH" >"$SAVEPATH_FILE"
+ echo "$mode" >"$MODEFILE"
+
+ local note; if [[ "$mode" == "full" ]]; then note="$(msg notif_started_full "$output" "$SAVE_PATH")"; else note="$(msg notif_started_region "$SAVE_PATH")"; fi
+ [[ -n "$dev" ]] && note+="$(msg notif_device_suffix "$dev")"
+ echo "$note";
+ emit_waybar_signal
+ start_tick
+}
+
+stop_rec() {
+ if ! is_running; then echo "$(msg not_running)"; emit_waybar_signal; exit 0; fi
+ local pid; read -r pid <"$PIDFILE"
+
+ kill -INT "$pid" 2>/dev/null || true
+ for _ in {1..40}; do sleep 0.1; is_running || break; done
+ is_running && kill -TERM "$pid" 2>/dev/null || true
+ sleep 0.2
+ is_running && kill -KILL "$pid" 2>/dev/null || true
+
+ # 停止后清理运行时状态文件
+ rm -f "$PIDFILE" "$MODEFILE"
+ stop_tick
+
+ local save_path=""; [[ -r "$SAVEPATH_FILE" ]] && read -r save_path <"$SAVEPATH_FILE"
+
+ # --- [NEW] GIF Conversion Logic ---
+ if [[ -f "$GIF_MARKER" ]]; then
+ rm -f "$GIF_MARKER"
+ if [[ -n "$save_path" && -f "$save_path" ]]; then
+ notify "$(msg notif_processing_gif)"
+
+ # [FIXED] 确保 GIF 目录存在: .../wf-recorder/gif/
+ local gif_dir="$(get_save_dir)/gif"
+ mkdir -p "$gif_dir"
+
+ local filename=$(basename "$save_path")
+ local gif_out="$gif_dir/${filename%.*}.gif"
+
+ # 使用您提供的滤镜字符串
+ local filters="fps=$GIF_FPS,scale=$GIF_WIDTH:-1:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=$GIF_STATS_MODE[p];[s1][p]paletteuse=dither=$GIF_DITHER_MODE"
+
+ # 运行转换,如果成功则删除原文件
+ if ffmpeg -y -v error -i "$save_path" -vf "$filters" "$gif_out"; then
+ rm "$save_path"
+ save_path="$gif_out"
+ # 更新保存路径以便后续通知使用
+ echo "$save_path" > "$SAVEPATH_FILE"
+ else
+ notify "$(msg notif_gif_failed)"
+ fi
+ fi
+ fi
+ # -----------------------------------
+
+ if [[ -n "$save_path" && -f "$save_path" ]]; then
+ # 生成不带后缀的 latest(例如:.../latest)
+ ln -sf "$(basename "$save_path")" "$(dirname "$save_path")/latest" || true
+
+ # --- [NEW] Auto Copy to Clipboard (as File Object) ---
+ local cp_note=""
+ if command -v wl-copy >/dev/null; then
+ # [CRITICAL FIX] 使用 text/uri-list MIME 类型,并添加 file:// 前缀
+ # 这会让剪贴板将其视为一个“文件”,允许在文件管理器或聊天软件中直接粘贴
+ echo "file://${save_path}" | wl-copy --type text/uri-list
+ cp_note=" $(msg notif_copied)"
+ fi
+ # ------------------------------------
+
+ local s; s="$(msg notif_saved "$save_path")${cp_note}"; echo "$s"; notify "$s"
+ else
+ local s; s="$(msg notif_stopped)"; echo "$s"; notify "$s"
+ fi
+
+ if [[ "${PKILL_AFTER_STOP,,}" != "off" ]]; then
+ for sig in INT TERM KILL; do
+ pgrep -x -u "$UID" "$APP" >/dev/null || break
+ pkill -"$sig" -x -u "$UID" "$APP" 2>/dev/null || true
+ sleep 0.1
+ done
+ fi
+ emit_waybar_signal
+}
+
+# ================== Waybar JSON/status ==================
+tooltip_idle_text() {
+ case "$(lang_code)" in
+ zh) cat <<'EOF'
+屏幕录制(wf-recorder)
+左键:打开录制菜单
+右键:强制关闭
+EOF
+ ;;
+ ja) cat <<'EOF'
+画面録画(wf-recorder)
+左クリック:録画メニューを開く
+右クリック:強制停止
+EOF
+ ;;
+ *) cat <<'EOF'
+Screen recording (wf-recorder)
+Left click: open recording menu
+Right click: force stop
+EOF
+ ;;
+ esac
+}
+tooltip_recording_text() { # $1 elapsed, $2 filepath, $3 mode: full|region
+ local t="$1" p="${2:-}" m="${3:-}"
+ local mode_label
+ case "$m" in full|fullscreen) mode_label="$(msg mode_full)";; region|area) mode_label="$(msg mode_region)";; *) mode_label="";; esac
+ case "$(lang_code)" in
+ zh) [[ -n "$p" ]] && { [[ -n "$mode_label" ]] && printf "录制中(%s)\n已用时:%s\n文件:%s\n" "$mode_label" "$t" "$p" || printf "录制中\n已用时:%s\n文件:%s\n" "$t" "$p"; } || { [[ -n "$mode_label" ]] && printf "录制中(%s)\n已用时:%s\n" "$mode_label" "$t" || printf "录制中\n已用时:%s\n" "$t"; } ;;
+ ja) [[ -n "$p" ]] && { [[ -n "$mode_label" ]] && printf "録画中(%s)\n経過時間:%s\nファイル:%s\n" "$mode_label" "$t" "$p" || printf "録画中\n経過時間:%s\nファイル:%s\n" "$t" "$p"; } || { [[ -n "$mode_label" ]] && printf "録画中(%s)\n経過時間:%s\n" "$mode_label" "$t" || printf "録画中\n経過時間:%s\n" "$t"; } ;;
+ *) [[ -n "$p" ]] && { [[ -n "$mode_label" ]] && printf "Recording (%s)\nElapsed: %s\nFile: %s\n" "$mode_label" "$t" "$p" || printf "Recording\nElapsed: %s\nFile: %s\n" "$t" "$p"; } || { [[ -n "$mode_label" ]] && printf "Recording (%s)\nElapsed: %s\n" "$mode_label" "$t" || printf "Recording\nElapsed: %s\n" "$t"; } ;;
+ esac
+}
+pretty_status_json() {
+ local text tooltip class alt
+ if is_running; then
+ local start=0; [[ -r "$STARTFILE" ]] && read -r start <"$STARTFILE" || true
+ [[ "$start" =~ ^[0-9]+$ ]] || start=0
+ local now dur; now="$(date +%s)"; dur=$((now - start)); (( dur < 0 )) && dur=0
+ local t; t="$(pretty_dur "$dur")"
+ local save_path=""; [[ -r "$SAVEPATH_FILE" ]] && read -r save_path <"$SAVEPATH_FILE" || true
+ local mode=""; [[ -r "$MODEFILE" ]] && read -r mode <"$MODEFILE" || true
+ text="$ICON_REC$t"
+ tooltip="$(tooltip_recording_text "$t" "$save_path" "$mode")"
+ class="recording"; alt="rec"
+ else
+ text="$ICON_IDLE"; tooltip="$(tooltip_idle_text)"; class="idle"; alt="idle"
+ fi
+ printf '{"text":"%s","tooltip":"%s","class":"%s","alt":"%s"}\n' \
+ "$(printf '%s' "$text" | json_escape)" \
+ "$(printf '%s' "$tooltip" | json_escape)" \
+ "$class" "$alt"
+}
+status_rec() {
+ local json="${1:-}"
+ if [[ "$json" == "--json" ]]; then
+ pretty_status_json
+ else
+ if is_running; then
+ local start=0; [[ -r "$STARTFILE" ]] && read -r start <"$STARTFILE" || true
+ [[ "$start" =~ ^[0-9]+$ ]] || start=0
+ local now dur; now="$(date +%s)"; dur=$((now - start)); (( dur < 0 )) && dur=0
+ printf "%s%s\n" "$ICON_REC" "$(pretty_dur "$dur")"
+ else
+ echo "$ICON_IDLE"
+ fi
+ fi
+}
+
+# ================== Main ==================
+case "${1:-toggle}" in
+ start) start_rec ;;
+ stop) stop_rec ;;
+ status) status_rec ;;
+ status-json) status_rec --json ;;
+ waybar) status_rec --json ;;
+ is-active) if is_running; then exit 0; else exit 1; fi ;;
+ toggle) is_running && stop_rec || start_rec ;;
+ settings) show_settings_menu ;;
+ *) echo "Usage: $0 {start|stop|toggle|status|status-json|waybar|is-active|settings}"; exit 2 ;;
+esac
diff --git a/.config/waybar/style.css b/.config/waybar/style.css
new file mode 100755
index 0000000..06c8a14
--- /dev/null
+++ b/.config/waybar/style.css
@@ -0,0 +1,494 @@
+@import "colors.css";
+/* @import "/home/shorin/.cache/wal/colors-waybar.css"; */
+
+/* 核心逻辑:全相对单位 (em) 改造
+ 基准字体大小:18px
+ 如果需要整体放大缩小,只需修改下方的 18px 即可
+*/
+* {
+ border: none;
+ border-radius: 0;
+ font-family: "JetBrainsMono Nerd Font Propo","LXGW WenKai Screen","JetBrains Maple Mono";
+ /* font-family:"0xProto Nerd Font Propo"; */
+ font-size: 16.6px; /* 基准大小 */
+ opacity: 1;
+}
+
+window#waybar {
+ background: transparent;
+ color: @on_surface;
+}
+
+/* 鼠标悬浮信息提示 */
+tooltip {
+ background: @secondary_container;
+ border: 0.17em solid @outline; /* 3px */
+ opacity: 1;
+}
+
+tooltip label {
+ color: @on_surface;
+ font-size: 0.89em; /* 16px */
+}
+
+
+/* 工作区 */
+#workspaces button {
+ padding: 0px 0.56em; /* 10px */
+ background: @surface;
+ color: @tertiary_container;
+}
+
+/* #workspaces label {
+ font-size: 1.22em;
+} */
+
+#workspaces button:hover {
+ background: @on_tertiary;
+}
+
+#workspaces button.active{
+ color:@tertiary;
+}
+
+#custom-right_div.5 {
+ background: @surface_container_high;
+ color: @surface;
+ font-size: 1.39em; /* 25px */
+ padding: 0px;
+}
+
+/* waybar niri taskbar */
+.niri-taskbar {
+ background: @surface_container_high;
+ padding: 0 0 0 0.28em; /* 5px */
+}
+
+.niri-taskbar button:hover {
+ background: @surface_container;
+}
+
+.niri-taskbar button.focused {
+ background: @surface;
+}
+
+.niri-taskbar button.urgent {
+ background-color: @tertiary;
+ animation-name: blink;
+ animation-duration: 0.5s;
+ animation-timing-function: steps(12);
+ animation-iteration-count: infinite;
+ animation-direction: alternate;
+}
+@keyframes blink {
+ to {
+ background-color: @primary;
+ color: @error;
+ }
+}
+
+/* 窗口名 */
+#window {
+ padding: 0px 0.56em; /* 10px */
+ background-color: @surface_container_high;
+ color: @on_surface;
+}
+
+#window label {
+ font-size: 0.89em; /* 16px */
+}
+
+window#waybar.empty #window {
+ background-color: @surface_container_high;
+}
+
+#custom-right_div.6 {
+ color: @surface_container_high;
+ font-size: 1.39em; /* 25px */
+ padding: 0px;
+}
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+
+/* 中间 */
+
+#custom-left_div.3 {
+ color: @surface_container_high;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
+
+
+#bluetooth {
+ padding: 0px 0.3em 0px 0.5em; /* 7px */
+ font-size: 1.25em; /* 20px */
+}
+#bluetooth.disabled{
+ padding: 0px 0.22em 0px 0.46em ;
+}
+
+#network {
+ padding: 0px 0.34em; /* 7px */
+ font-size: 1.2em; /* 22px */
+}
+
+#custom-settings {
+ padding: 0px 0.39em; /* 7px */
+ font-size: 1.06em; /* 19px */
+}
+
+#custom-screenshot {
+ padding: 0 0.4em; /* 7px */
+ font-size: 1.28em; /* 22px */
+}
+
+/* wf-recoder脚本 */
+#custom-wfrec {
+ padding: 0 0.3em; /* 7px */
+ font-size: 1.1em;
+}
+
+#custom-wfrec.recording,
+#custom-wfrec,
+#bluetooth,
+#network,
+#custom-settings,
+#custom-screenshot {
+ background-color: @surface_container_high;
+ color: @secondary;
+}
+
+/* 录制中 */
+#custom-wfrec.recording {
+ color: @error;
+}
+/* #custom-wfrec,
+#custom-screenshot{
+ color: @secondary;
+} */
+
+#custom-left_div.2 {
+ background-color: @surface_container_high;
+ color: @tertiary;
+ padding: 0px 0px;
+ font-size: 1.39em; /* 25px */
+}
+
+#power-profiles-daemon,
+#custom-colorpicker,
+#idle_inhibitor {
+ background-color: @tertiary;
+ color: @on_tertiary;
+ padding: 0px 0.36em; /* 6px */
+}
+#idle_inhibitor.activated{
+ padding: 0px 0.4em 0px 0.4em;
+}
+#power-profiles-daemon{
+ padding: 0px 0.4em 0em 0.36em;
+}
+#power-profiles-daemon.performance {
+ color: @on_error;
+ font-size: 1.28em; /* 23px */
+ padding: 0px 0.32em 0px 0.45em; /* 9px 8px */
+}
+
+#power-profiles-daemon.balanced {
+ color: @on_tertiary;
+}
+
+#power-profiles-daemon.power-saver {
+ color: #1aa052;
+
+}
+
+/* 菜单 */
+#custom-left_div.11 {
+ background-color: @tertiary;
+ color: @surface_container
+}
+#custom-applauncher {
+ font-size: 1.39em; /* 25px */
+ padding: 0px 0.39em; /* 7px */
+ margin: 0px;
+ background-color: @primary;
+ color: @on_primary;
+
+}
+#custom-right_div.1,
+#custom-left_div.1 {
+ background-color: @surface_container;
+ color: @primary;
+}
+#custom-left_div.1,
+#custom-right_div.1 {
+ padding: 0px;
+ margin: 0px;
+ font-size: 1.39em; /* 25px */
+}
+#custom-left_div.11,
+#custom-right_div.11 {
+ margin: 0px;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
+#custom-right_div.11 {
+
+ background-color: @secondary;
+ color: @surface_container;
+}
+
+/*中间右边第二级*/
+
+#clock {
+ padding: 0px 0.45em 0em 0.45em; /* 8px */
+}
+
+#clock {
+ background-color: @secondary;
+ color: @on_secondary;
+}
+
+#custom-right_div.2 {
+ background-color: @surface_container_high;
+ color: @secondary;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
+
+#custom-cava {
+ background-color: @surface_container_high;
+ color: @primary;
+ padding: 0px 0.35em; /* 7px */
+}
+
+#mpris {
+ background-color: @surface_container_high;
+ color: @primary;
+ padding: 0px 0.39em 0px 0px; /* 7px 0 0 */
+}
+
+#custom-right_div.3 {
+
+ color: @surface_container_high;
+ padding: 0px 0.1em 0px 0px ;
+ font-size: 1.39em; /* 25px */
+}
+#custom-right_div.4 {
+ /* background-color: @surface_container_high; */
+ color: @on_secondary;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+/* —————————————————————————————————————————————————————————————————————————— */
+
+/* 右侧 */
+
+
+#custom-left_div.7 {
+ /* background-color: @surface_container_high; */
+ color: @surface_bright;
+ font-size: 1.39em; /* 25px */
+ padding: 0px;
+}
+
+
+#custom-updates {
+ border-radius: 0px;
+ padding: 0px 0.17em 0px 0.39em; /* 3px 7px */
+ background-color: @surface_bright;
+ color: @error;
+
+}
+
+#tray {
+ padding: 0px 0.39em 0px 0.39em; /* 7px */
+ font-size: 1.11em; /* 20px */
+ background-color: @surface_bright;
+}
+
+
+#custom-left_div.4 {
+ background-color: @surface_bright;
+ color: @surface_container_high;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
+/* 亮度 */
+#custom-ddcutil-day,
+#custom-ddcutil-night,
+#custom-ddcutil-sleep,
+#custom-separator.1 {
+ background-color: @surface_container_high;
+ color: @tertiary;
+ padding: 0px 0.33em; /* 5px */
+}
+
+#backlight {
+ background-color: @surface_container_high;
+ color: @tertiary;
+ padding: 0px 0.28em 0px 0px; /* 5px */
+}
+
+#backlight-slider {
+ background-color: @surface_container_high;
+ padding: 0px 0.28em 0px 0px; /* 5px */
+}
+
+#backlight-slider slider {
+ min-height: 0px;
+ min-width: 0px;
+ opacity: 0;
+ background-image: none;
+ border: none;
+ box-shadow: none;
+ background: none;
+}
+
+#backlight-slider trough {
+ min-height: 0.56em; /* 10px */
+ min-width: 4.44em; /* 80px */
+ border-radius: 0.28em; /* 5px */
+ opacity: 0;
+ background-color: @background;
+}
+
+#backlight-slider highlight {
+ min-width: 0.56em; /* 10px */
+ border-radius: 0.28em; /* 5px */
+ background-color: @tertiary;
+}
+
+/* 音视频 */
+#privacy {
+ padding: 0px 0.39em; /* 7px */
+}
+
+#privacy {
+ background-color: @surface_container_high;
+ color: @error;
+}
+
+#pulseaudio {
+ padding: 0px 0px 0px 0.28em; /* 5px */
+}
+
+#pulseaudio-slider {
+ padding: 0px 0px 0px 0.56em; /* 10px */
+ margin: 0px;
+}
+
+#pulseaudio-slider,
+#pulseaudio {
+ background-color: @surface_container_high;
+ color: @tertiary;
+}
+
+#pulseaudio-slider slider {
+ min-height: 0px;
+ min-width: 0px;
+ opacity: 0;
+ background-image: none;
+ box-shadow: none;
+ background: none;
+}
+
+#pulseaudio-slider trough {
+ min-height: 0.56em; /* 10px */
+ min-width: 4.44em; /* 80px */
+ border-radius: 0.28em; /* 5px */
+ background-color: @surface;
+}
+
+#pulseaudio-slider highlight {
+ min-width: 0px;
+ border-radius: 0.28em; /* 5px */
+ background-color: @tertiary;
+}
+
+#custom-left_div.8 {
+ background-color: @surface_container_high;
+ color: @surface_container;
+ font-size: 1.39em; /* 25px */
+ padding: 0px;
+}
+
+
+/* 电池 */
+
+#battery {
+ background-color: @surface_container;
+ color: @secondary;
+ padding: 0px 0.39em; /* 7px */
+}
+
+#battery.critical:not(.charging) {
+ background-color: @surface_container;
+ color: @error;
+ animation-name: blink;
+ animation-duration: 0.5s;
+ animation-timing-function: steps(12);
+ animation-iteration-count: infinite;
+ animation-direction: alternate;
+ padding: 0px 0.39em; /* 7px */
+}
+
+/* powermenu电源菜单 */
+#custom-left_div.5 {
+ background-color: @surface_container;
+ color: @surface;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
+#custom-wlogout {
+ padding: 0px 0.83em 0px 0.56em; /* 15px 10px */
+ font-size: 1.39em; /* 25px */
+}
+
+#custom-wlogout,
+#custom-reboot,
+#custom-lockscreen,
+#custom-logout {
+ background-color: @surface;
+ color: @error;
+ padding: 0px 0.56em; /* 10px */
+}
+
+
+
+
+
+#clock.date {
+ padding: 0px 0.39em; /* 7px */
+}
+#custom-datelogo,
+#clock.date {
+ background-color: @secondary_container;
+ color: @on_secondary_container;
+}
+
+#custom-swaync {
+ background-color: @surface_container_high;
+ color: @on_surface_container;
+ padding: 0px 0.83em; /* 15px */
+}
+
+#custom-mako {
+ background-color: @surface_container_high;
+ color: @on_surface_container;
+ padding: 0px 0.83em; /* 15px */
+}
+
+#custom-left_div.6 {
+ background-color: @surface;
+ color: @surface_container_high;
+ padding: 0px;
+ font-size: 1.39em; /* 25px */
+}
diff --git a/.config/waypaper/config.ini b/.config/waypaper/config.ini
new file mode 100644
index 0000000..2580d25
--- /dev/null
+++ b/.config/waypaper/config.ini
@@ -0,0 +1,27 @@
+[Settings]
+language = en
+folder = ~/Pictures/wallpapers
+monitors = All
+wallpaper = ~/Pictures/wallpapers/wallhaven-yq8w67.jpg
+show_path_in_tooltip = True
+backend = swww
+fill = fill
+sort = name
+color = #ffffff
+subfolders = False
+all_subfolders = False
+show_hidden = False
+show_gifs_only = False
+zen_mode = True
+number_of_columns = 3
+post_command = matugen image $wallpaper
+swww_transition_type = any
+swww_transition_step = 63
+swww_transition_angle = 0
+swww_transition_duration = 2
+swww_transition_fps = 60
+mpvpaper_sound = False
+mpvpaper_options =
+use_xdg_state = False
+stylesheet = /home/zhenyan121/.config/waypaper/style.css
+
diff --git a/.config/yazi/theme.toml b/.config/yazi/theme.toml
new file mode 100644
index 0000000..cda94f4
--- /dev/null
+++ b/.config/yazi/theme.toml
@@ -0,0 +1,174 @@
+# : Manager [[[
+
+[mgr]
+cwd = { fg = "#e9e2d4" }
+
+# Find
+find_keyword = { fg = "#ffb4ab", bold = true, italic = true, underline = true }
+find_position = { fg = "#ffb4ab", bold = true, italic = true }
+
+# Marker
+marker_copied = { fg = "#78d38d", bg = "#78d38d" }
+marker_cut = { fg = "#c5ecce", bg = "#c5ecce" }
+marker_marked = { fg = "#ffb4ab", bg = "#ffb4ab" }
+marker_selected = { fg = "#aad0b3", bg = "#aad0b3" }
+
+# Count
+count_copied = { fg = "#00210f", bg = "#c5ecce" }
+count_cut = { fg = "#00210f", bg = "#c5ecce" }
+count_selected = { fg = "#3a3000", bg = "#aad0b3" }
+
+# Border
+border_symbol = "│"
+border_style = { fg = "#dcc66e" }
+
+# : ]]]
+
+
+# : Tabs (New Section) [[[
+
+[tabs]
+active = { fg = "#3a3000", bg = "#dcc66e", bold = true }
+inactive = { fg = "#f9e287", bg = "#221b00" }
+
+# : ]]]
+
+
+# : Mode [[[
+
+[mode]
+# Mode
+normal_main = { bg = "#dcc66e", fg = "#3a3000", bold = true }
+normal_alt = { bg = "#4b4739", fg = "#cdc6b4" }
+
+# Select mode
+select_main = { bg = "#d1c6a1", fg = "#373016", bold = true }
+select_alt = { bg = "#4b4739", fg = "#cdc6b4" }
+
+# Unset mode
+unset_main = { bg = "#aad0b3", fg = "#153722", bold = true }
+unset_alt = { bg = "#4b4739", fg = "#cdc6b4" }
+
+# : ]]]
+
+
+# : Status [[[
+
+[status]
+sep_left = { open = "🭁", close = "🭠" }
+sep_right = { open = "🭁", close = "🭠" }
+
+# Progress
+progress_label = { bold = true }
+progress_normal = { fg = "#dcc66e", bg = "#3c3930" }
+progress_error = { fg = "#ffb4ab", bg = "#3c3930" }
+
+# Permissions
+perm_type = { fg = "#928147" }
+perm_write = { fg = "#50915f" }
+perm_read = { fg = "#ff2b12" }
+perm_exec = { fg = "#52c66d" }
+perm_sep = { fg = "#dcb20b" }
+
+# : ]]]
+
+
+# : Picker (Renamed from Select) [[[
+
+[pick]
+border = { fg = "#dcc66e" }
+active = { fg = "#aad0b3", bold = true }
+inactive = {}
+
+# : ]]]
+
+
+# : Input [[[
+
+[input]
+border = { fg = "#dcc66e" }
+value = { fg = "#e9e2d4" }
+
+# : ]]]
+
+
+# : Completion (Renamed from Completion) [[[
+
+[cmp]
+border = { fg = "#dcc66e", bg = "#3a3000" }
+
+# : ]]]
+
+
+# : Tasks [[[
+
+[tasks]
+border = { fg = "#dcc66e" }
+title = {}
+hovered = { fg = "#c5ecce", underline = true }
+
+# : ]]]
+
+
+# : Which [[[
+
+[which]
+cols = 3
+mask = { bg = "#3c3930" }
+cand = { fg = "#dcc66e" }
+rest = { fg = "#3a3000" }
+desc = { fg = "#e9e2d4" }
+separator = " ▶ "
+separator_style = { fg = "#e9e2d4" }
+
+# : ]]]
+
+
+# : Help [[[
+
+[help]
+on = { fg = "#e9e2d4" }
+run = { fg = "#e9e2d4" }
+footer = { fg = "#373016", bg = "#d1c6a1" }
+
+# : ]]]
+
+
+# : Notify [[[
+
+[notify]
+title_info = { fg = "#aad0b3" }
+title_warn = { fg = "#dcc66e" }
+title_error = { fg = "#ffb4ab" }
+
+# : ]]]
+
+
+# : File-specific styles [[[
+
+[filetype]
+
+rules = [
+ # Images
+ { mime = "image/*", fg = "#94e2d5" },
+
+ # Media
+ { mime = "{audio,video}/*", fg = "#f9e2af" },
+
+ # Archives
+ { mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#f5c2e7" },
+
+ # Documents
+ { mime = "application/{pdf,doc,rtf}", fg = "#a6e3a1" },
+
+ # Special files
+ { url = "*", is = "orphan", bg = "#93000a" },
+ { url = "*", is = "exec", fg = "#ffdad6" },
+
+ # Fallback
+ { url = "*", fg = "#e9e2d4" },
+ { url = "*/", fg = "#dcc66e" },
+]
+
+# : ]]]
+
diff --git a/.zshrc b/.zshrc
new file mode 100644
index 0000000..d4166db
--- /dev/null
+++ b/.zshrc
@@ -0,0 +1,48 @@
+#语法检查和高亮
+source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
+source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
+#开启tab上下左右选择补全
+zstyle ':completion:*' menu select
+autoload -Uz compinit
+compinit
+
+# 设置历史记录文件的路径
+HISTFILE=~/.zsh_history
+
+# 设置在会话(内存)中和历史文件中保存的条数,建议设置得大一些
+HISTSIZE=1000
+SAVEHIST=1000
+
+# 忽略重复的命令,连续输入多次的相同命令只记一次
+setopt HIST_IGNORE_DUPS
+
+# 忽略以空格开头的命令(用于临时执行一些你不想保存的敏感命令)
+setopt HIST_IGNORE_SPACE
+
+# 在多个终端之间实时共享历史记录
+# 这是实现多终端同步最关键的选项
+setopt SHARE_HISTORY
+
+# 让新的历史记录追加到文件,而不是覆盖
+setopt APPEND_HISTORY
+# 在历史记录中记录命令的执行开始时间和持续时间
+setopt EXTENDED_HISTORY
+
+# 如果 TERM 变量不是 "linux",说明不在 TTY 中
+if [[ "$TERM" != "linux" ]]; then
+
+ alias ls='eza --icons'
+ # End of lines added by compinstall
+ eval "$(starship init zsh)"
+fi
+
+# 针对 TTY 环境自动切换为英文,避免中文乱码
+if [[ "$TERM" == "linux" ]]; then
+ export LANG=en_US.UTF-8
+ export LC_ALL=en_US.UTF-8
+ export LANGUAGE=en_US:en
+ alias ls='eza'
+fi
+eval "$(zoxide init zsh)"
+alias cat='bat'
+alias cd='z' # 或保留 cd,同时用 z 快速跳转
diff --git a/软件.md b/软件.md
new file mode 100644
index 0000000..e43377a
--- /dev/null
+++ b/软件.md
@@ -0,0 +1,259 @@
+以下是根据你提供的 Arch 安装日记,整理出的所有**最终保留未删除**的软件,并按**功能类别分类**。已删除的软件(如 mangoHUD、ghostty、fragments、python-pywal16 等)均不包含在内。
+
+每一行一个软件,格式为:
+
+```
+软件包名 # 分类说明
+```
+
+---
+
+### 🖥️ 基础系统 & 内核
+
+```
+base # 基础系统包
+base-devel # 编译开发工具链
+linux-zen # 主内核
+linux-lts # LTS内核(后安装)
+linux-zen-headers # ZEN内核头文件
+linux-lts-headers # LTS内核头文件
+btrfs-progs # Btrfs 文件系统工具
+amd-ucode # AMD CPU 微码
+linux-firmware # 硬件固件
+efibootmgr # EFI 启动管理
+grub # 引导加载器
+os-prober # 多系统检测
+exfat-utils # exFAT 文件系统支持
+zram-generator # 内存压缩服务
+snapper # Btrfs 快照管理
+snap-pac # Pacman 集成 Snapper
+btrfs-assistant # Btrfs GUI 管理工具
+grub-btrfs # GRUB + Btrfs 快照集成
+inotify-tools # 文件系统事件监控
+switcheroo-control # 混合显卡切换服务
+vulkan-tools # Vulkan 调试工具
+vulkan-radeon # Radeon Vulkan 驱动(备用/兼容)
+```
+
+---
+
+### 🌐 网络 & 连接
+
+```
+networkmanager # 网络管理服务
+network-manager-applet # GNOME 网络托盘小程序
+dnsmasq # DNS/DHCP 服务(用于虚拟机或本地解析)
+bluetui # TUI 蓝牙管理器
+bluez # 蓝牙协议栈(随 GNOME 安装)
+```
+
+---
+
+### 🧑 用户 & 权限 & Shell
+
+```
+sudo # 提权工具
+zsh # 默认 Shell
+vim # 文本编辑器
+neovim # 现代 Vim
+vscode # 图形化代码编辑器
+useradd (wheel) # 普通用户 + wheel组
+visudo # sudoers 配置工具
+paru # AUR 助手
+pacseek # TUI 包搜索工具
+fzf # 模糊查找
+zoxide # 智能目录跳转
+eza # 现代 ls 替代
+bat # 现代 cat 替代
+```
+
+---
+
+### 🖼️ 桌面环境 & 显示管理
+
+```
+gnome-desktop # GNOME 桌面核心
+gdm # GNOME 显示管理器
+gnome-tweaks # GNOME 调优工具
+gnome-extensions-app # 扩展管理器(通过 flatpak 安装 extension-manager)
+gnome-control-center # 设置中心
+gnome-clocks # 时钟应用
+gnome-calendar # 日历应用
+nautilus # 文件管理器(默认)
+nautilus-terminal # 在 Nautilus 中打开终端插件
+nautilus-open-any-terminal # 替代方案(后安装)
+kitty # 终端模拟器(替换 ghostty)
+waypaper # 壁纸管理器(虽 GNOME 不支持但保留)
+swww # Wayland 动态壁纸后端
+waybar # Wayland 状态栏(使用 mechabar 主题)
+fuzzel # Wayland 应用启动器
+nwg-look # GTK 主题切换器
+qt6ct # Qt6 配置工具
+qt5ct # Qt5 配置工具
+roundedWindowsCorners-reborn-git # 窗口圆角插件
+xorg-xrdb # X11 资源数据库(用于缩放/XWayland)
+xdg-desktop-portal-gnome # 桌面门户(Flatpak/Wayland 集成)
+polkit-gnome # PolicyKit 认证代理
+mako # 通知守护进程
+libnotify # 通知库
+```
+
+---
+
+### 🎮 游戏 & Steam 相关
+
+```
+steam # 游戏平台
+uu # UU 加速器(Steam Deck 插件)
+gamescope # 游戏窗口管理器
+mangojuice # MangoHud 的替代品(后安装)
+gamemoderun # 游戏优化运行器
+nvidia-prime # NVIDIA 混合显卡切换
+vulkan-mesa-layer # Vulkan 层(尝试解决独显占用)
+nvdia-settings # NVIDIA 控制面板(隐含安装)
+libva-nvidia-utils # NVIDIA VA-API 支持
+nvtop # NVIDIA GPU 监控
+obs-studio # 录屏/直播
+mpv # 媒体播放器
+wf-recorder # Wayland 录屏
+hyprpicker # 颜色选择器(游戏/截图辅助)
+slurp # 区域选择工具
+wl-clipboard # Wayland 剪贴板
+clipse # 剪贴板历史(推测是 clipman 或类似)
+```
+
+---
+
+### 🎵 音频 & 视频
+
+```
+easyeffects # 音频效果器
+pavucontrol # PulseAudio 音量控制
+celluloid # 视频播放器(GTK MPV 前端)
+loupe # 图片查看器
+mission-center # 系统信息仪表盘
+baobab # 磁盘空间分析器
+ffmpegthumbnailer # 视频缩略图生成
+gst-plugins-base # GStreamer 基础插件
+gst-plugins-good # GStreamer 优质插件
+gst-libav # GStreamer LibAV 插件
+gvfs-smb # SMB 网络文件系统支持
+```
+
+---
+
+### 🖋️ 输入法 & 字体 & 本地化
+
+```
+fcitx5-im # Fcitx5 输入法框架
+fcitx5-rime # Rime 输入引擎
+fcitx5-pinyin-zhwiki # 雾凇拼音词库
+fonts-noto-cjk # 思源黑体(中日韩字体)
+nerd-fonts # 编程字体(带图标)
+jetbrains-mono-nerd # JetBrains Mono Nerd 字体(后设为默认)
+fontconfig # 字体渲染配置
+locale-gen # 本地化生成
+zh_CN.UTF-8 / en_US.UTF-8 # 多语言支持
+```
+
+---
+
+### 📦 开发 & 编译工具
+
+```
+clang # C/C++ 编译器
+cmake # 构建系统
+ninja # 构建工具
+gdb # GNU 调试器
+lldb # LLVM 调试器
+miniconda3 # Python 环境管理器(含 conda)
+reaper # 数字音频工作站(DAW)
+```
+
+---
+
+### 🧰 系统监控 & 工具
+
+```
+btop # 系统资源监控(htop 替代)
+asciiquarium # ASCII 水族馆屏保
+figlet # 大字标题生成
+jp2a # 图片转 ASCII
+toilet # 彩色大字生成
+cowsay # 牛说文本
+lolcat # 彩虹输出
+cbonsai # ASCII 盆栽模拟器
+cava # 音频可视化
+timg # 终端图像查看器
+rssguard # RSS 阅读器
+okular # PDF/文档阅读器(含 VLC 支持版)
+kdenlive # 视频编辑器
+onlyoffice # Office 套件
+transmission-gtk # BT 下载客户端
+marktext # Markdown 编辑器(AUR)
+musicfox # TUI 网易云音乐客户端
+Linuxqq # QQ(AppImage,AUR)
+netease-cloud-music-rust-gtk # 网易云第三方客户端(AUR)
+hmcl # 我的世界启动器
+```
+
+---
+
+### 🧪 虚拟化 & 容器
+
+```
+qemu-full # QEMU 全功能虚拟机
+virt-manager # 虚拟机管理 GUI
+swtpm # TPM 模拟器(用于安全启动虚拟机)
+```
+
+---
+
+### 🎨 主题 & 美化 & 扩展
+
+```
+gnome-shell-extension-steal-my-focus # 自动聚焦窗口扩展
+gnome-shell-extension-clipboard-indicator # 剪贴板历史
+gnome-shell-extension-auto-power-profile # 自动电源模式
+gnome-shell-extension-power-tracker # 电量追踪
+gnome-shell-extension-power-profile-indicator # 电源模式指示器
+gnome-shell-extension-hide-universal-access # 隐藏无障碍菜单
+gnome-shell-extension-tiling-shell # 平铺窗口扩展
+pywalfox # Firefox 主题同步(Firefox 插件配套)
+matugen # 根据壁纸生成配色方案
+```
+
+---
+
+### ⚙️ 服务 & 后台 & 优化
+
+```
+power-profiles-daemon # 性能模式切换服务
+xdg-document-portal.service # 文档门户服务(超时调整)
+local-search-3.service # 本地搜索服务(超时调整)
+gloseterminal → kitty 符号链接 # GNOME Terminal 替换为 Kitty
+EDITOR=vim # 默认编辑器设置
+```
+
+---
+
+### 🌐 浏览器 & 网络工具
+
+```
+firefox # 火狐浏览器
+firefox-i18n-zh-cn # 火狐中文语言包
+```
+
+---
+
+### ✅ 最终备注
+
+- 所有曾安装但被**明确删除或回退**的软件(如 `mangohud`, `ghostty`, `fragments`, `python-pywal16`)**未列入**。
+- 部分软件通过 **AUR** 或 **Flatpak** 安装,已在注释中标明。
+- 部分服务(如 `bluetooth`, `NetworkManager`, `switcheroo-control`, `power-profiles-daemon`)已启用并保留。
+- 所有配置文件修改(如 locale、GRUB、环境变量、xdg-mime)视为系统设置,不列为“软件”。
+
+---
+
+✅ 此列表可用于备份、重装参考、或制作自动化脚本。
+如需导出为可执行的 pacman/paru 安装命令,也可提供。
\ No newline at end of file