mirror of
https://github.com/eliasrenman/dotfiles.git
synced 2026-03-16 20:46:08 +01:00
feat: wofi
This commit is contained in:
32
wofi/config
Normal file
32
wofi/config
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# hide_scroll=true
|
||||||
|
# show=drun
|
||||||
|
# width=35%
|
||||||
|
# lines=15
|
||||||
|
# line_wrap=word
|
||||||
|
# term=alacritty
|
||||||
|
# allow_markup=true
|
||||||
|
# always_parse_args=true
|
||||||
|
# show_all=true
|
||||||
|
# print_command=true
|
||||||
|
# layer=overlay
|
||||||
|
# allow_images=true
|
||||||
|
# insensitive=true
|
||||||
|
# prompt=
|
||||||
|
# image_size=15
|
||||||
|
# display_generic=true
|
||||||
|
# location=center
|
||||||
|
|
||||||
|
width=700
|
||||||
|
height=350
|
||||||
|
show=drun
|
||||||
|
prompt=Search...
|
||||||
|
filter_rate=100
|
||||||
|
allow_markup=true
|
||||||
|
no_actions=true
|
||||||
|
halign=fill
|
||||||
|
orientation=vertical
|
||||||
|
content_halign=fill
|
||||||
|
insensitive=true
|
||||||
|
allow_images=true
|
||||||
|
image_size=30
|
||||||
|
gtk_dark=true
|
||||||
9
wofi/config.screenshot
Normal file
9
wofi/config.screenshot
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
hide_search=true
|
||||||
|
hide_scroll=true
|
||||||
|
insensitive=true
|
||||||
|
width=1
|
||||||
|
show=dmenu
|
||||||
|
lines=5
|
||||||
|
location=centre
|
||||||
|
x=870
|
||||||
|
y=455
|
||||||
61
wofi/style.css
Normal file
61
wofi/style.css
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
Arc-Dark Color Scheme
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @define-color highlight #e30b9b; */
|
||||||
|
@define-color highlight #f7768e;
|
||||||
|
@define-color base1 rgba(0,0,0,0.2);
|
||||||
|
@define-color base2 rgba(0,0,0,0.8);
|
||||||
|
@define-color base3 rgba(0,0,0,0.1);
|
||||||
|
|
||||||
|
*{
|
||||||
|
font-family: JetBrains Mono Nerd Font;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
/* border: 1px solid @highlight; */
|
||||||
|
border-radius: 18px;
|
||||||
|
/* background: rgba(0,0,0,0); */
|
||||||
|
color: #bb9af7;
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(to bottom right, #73daca, #f7768e);
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#input {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
padding:3px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border:none;
|
||||||
|
outline:none;
|
||||||
|
/* color: white; */
|
||||||
|
color: #bb9af7;
|
||||||
|
/* background: @base1; */
|
||||||
|
background-color: #0a0a0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner-box {
|
||||||
|
/* background: @base3; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer-box {
|
||||||
|
margin: 3px;
|
||||||
|
padding:15px;
|
||||||
|
background-color: #0a0a0a;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#text {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #entry:nth-child(even) { */
|
||||||
|
/* background-color: @base1; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
#entry:selected {
|
||||||
|
color: black;
|
||||||
|
background-color: @highlight;
|
||||||
|
border:none;
|
||||||
|
outline:none;
|
||||||
|
}
|
||||||
49
wofi/style.widgets.css
Normal file
49
wofi/style.widgets.css
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Arc-Dark Color Scheme
|
||||||
|
*/
|
||||||
|
|
||||||
|
@define-color highlight #f7768e;
|
||||||
|
@define-color base1 rgba(0,0,0,0.6);
|
||||||
|
@define-color base2 rgba(0,0,0,0.8);
|
||||||
|
@define-color base3 rgba(0,0,0,0.1);
|
||||||
|
|
||||||
|
*{
|
||||||
|
font-family: JetBrainsMono;
|
||||||
|
/* height: fit-content; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#window {
|
||||||
|
border: 2px solid @highlight;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: rgba(0,0,0,0);
|
||||||
|
color: #bb9af7;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner-box {
|
||||||
|
background-color: @base1;
|
||||||
|
/* background-color: @base2; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer-box {
|
||||||
|
/*margin: 5px;
|
||||||
|
padding:5px 10px;
|
||||||
|
*/
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: -32px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#text {
|
||||||
|
padding: 5px;
|
||||||
|
/* color: white; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#entry:nth-child(even) {
|
||||||
|
/* background-color: pink; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#entry:selected {
|
||||||
|
color: black;
|
||||||
|
background-color: @highlight;
|
||||||
|
}
|
||||||
119
wofi/windows.py
Executable file
119
wofi/windows.py
Executable file
@@ -0,0 +1,119 @@
|
|||||||
|
#!/bin/python3
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
ENTER = "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def get_windows():
|
||||||
|
|
||||||
|
command = "swaymsg -t get_tree"
|
||||||
|
process = subprocess.Popen(
|
||||||
|
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
process = subprocess.Popen(
|
||||||
|
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
data = json.loads(process.communicate()[0])
|
||||||
|
|
||||||
|
# Select outputs that are active
|
||||||
|
windows = []
|
||||||
|
for output in data["nodes"]:
|
||||||
|
|
||||||
|
# The scratchpad (under __i3) is not supported
|
||||||
|
if output.get("name") != "__i3" and output.get("type") == "output":
|
||||||
|
workspaces = output.get("nodes", [])
|
||||||
|
for ws in workspaces:
|
||||||
|
if ws.get("type") == "workspace":
|
||||||
|
windows.extend(extract_nodes_iterative(ws))
|
||||||
|
return windows
|
||||||
|
|
||||||
|
|
||||||
|
# Extracts all windows from a sway workspace json object
|
||||||
|
def extract_nodes_iterative(workspace):
|
||||||
|
all_nodes = []
|
||||||
|
|
||||||
|
floating_nodes = workspace.get("floating_nodes", [])
|
||||||
|
|
||||||
|
for floating_node in floating_nodes:
|
||||||
|
all_nodes.append(floating_node)
|
||||||
|
|
||||||
|
nodes = workspace.get("nodes", [])
|
||||||
|
|
||||||
|
for node in nodes:
|
||||||
|
|
||||||
|
# Leaf node
|
||||||
|
if not node.get("nodes"):
|
||||||
|
all_nodes.append(node)
|
||||||
|
# Nested node, handled iterative
|
||||||
|
else:
|
||||||
|
for inner_node in node.get("nodes"):
|
||||||
|
nodes.append(inner_node)
|
||||||
|
|
||||||
|
return all_nodes
|
||||||
|
|
||||||
|
|
||||||
|
# Returns an array of all windows
|
||||||
|
def parse_windows(windows):
|
||||||
|
return [window.get("name") for window in windows]
|
||||||
|
|
||||||
|
|
||||||
|
# Returns a newline seperated UFT-8 encoded string of all windows for wofi
|
||||||
|
def build_wofi_string(windows):
|
||||||
|
return ENTER.join(windows).encode("UTF-8")
|
||||||
|
|
||||||
|
|
||||||
|
# Executes wofi with the given input string
|
||||||
|
def show_wofi(windows):
|
||||||
|
|
||||||
|
command = 'wofi -c ~/.config/wofi/menu -s ~/.config/wofi/style.css -p "Windows: " -d -i --hide-scroll'
|
||||||
|
|
||||||
|
process = subprocess.Popen(
|
||||||
|
command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
return process.communicate(input=windows)[0]
|
||||||
|
|
||||||
|
|
||||||
|
# Returns the sway window id of the window that was selected by the user inside wofi
|
||||||
|
def parse_id(windows, parsed_windows, selected):
|
||||||
|
if not selected:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
selected = (selected.decode("UTF-8"))[:-1] # Remove new line character
|
||||||
|
window_index = int(
|
||||||
|
parsed_windows.index(selected)
|
||||||
|
) # Get index of selected window in the parsed window array
|
||||||
|
return str(
|
||||||
|
windows[window_index].get("id")
|
||||||
|
) # Get sway window id based on the index
|
||||||
|
|
||||||
|
|
||||||
|
# Switches the focus to the given id
|
||||||
|
def switch_window(id):
|
||||||
|
command = "swaymsg [con_id={}] focus".format(id)
|
||||||
|
|
||||||
|
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
|
||||||
|
process.communicate()[0]
|
||||||
|
|
||||||
|
|
||||||
|
# Entry point
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
parser = ArgumentParser(description="Wofi based window switcher")
|
||||||
|
|
||||||
|
windows = get_windows()
|
||||||
|
|
||||||
|
parsed_windows = parse_windows(windows)
|
||||||
|
|
||||||
|
wofi_string = build_wofi_string(parsed_windows)
|
||||||
|
|
||||||
|
selected = show_wofi(wofi_string)
|
||||||
|
|
||||||
|
# Otherwise no point in running
|
||||||
|
if selected:
|
||||||
|
|
||||||
|
selected_id = parse_id(windows, parsed_windows, selected)
|
||||||
|
|
||||||
|
switch_window(selected_id)
|
||||||
Reference in New Issue
Block a user