commit
ee31ea8b75
@ -0,0 +1 @@ |
|||||||
|
swayfocus |
@ -0,0 +1,13 @@ |
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||||
|
Version 2, December 2004 |
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> |
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified |
||||||
|
copies of this license document, and changing it is allowed as long |
||||||
|
as the name is changed. |
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO. |
@ -0,0 +1,19 @@ |
|||||||
|
ifeq ($(PREFIX),) |
||||||
|
PREFIX := /usr/local
|
||||||
|
endif |
||||||
|
|
||||||
|
all: release |
||||||
|
|
||||||
|
.PHONY: clean |
||||||
|
clean: |
||||||
|
rm -f swayfocus
|
||||||
|
|
||||||
|
.PHONY: run |
||||||
|
run: |
||||||
|
crystal run src/swayfocus.cr
|
||||||
|
|
||||||
|
release: |
||||||
|
crystal build --release --no-debug src/swayfocus.cr
|
||||||
|
|
||||||
|
install: |
||||||
|
install swayfocus $(PREFIX)/bin/
|
@ -0,0 +1,28 @@ |
|||||||
|
# SWAYFOCUS - Window Switching Tool For Sway |
||||||
|
|
||||||
|
A tool to focus a specific window in sway, useful for run or raise scripts that would have used xdotool or wmctrl under Xorg. |
||||||
|
Uses swaymsg to communicate. Windows hidden to the system tray don't show up in the get_tree command, so they can't be raised with this. |
||||||
|
|
||||||
|
## Usage |
||||||
|
``` |
||||||
|
Usage: swayfocus [OPTIONS] |
||||||
|
-v, --version Show Version |
||||||
|
-h, --help Show Help |
||||||
|
-p, --print Print window names and exit |
||||||
|
-c, --cycle Cycle through all matching windows in order, instead of selecting the first in the list |
||||||
|
-n WNAME, --name=WNAME Match against window name |
||||||
|
-m WMARK, --mark=WMARK Match against window mark |
||||||
|
-t WTYPE, --type=WTYPE Match against window type (app_id for wayland, class for xwayland) |
||||||
|
``` |
||||||
|
Select at least one matching option. |
||||||
|
|
||||||
|
## Examples |
||||||
|
``` |
||||||
|
swayfocus -p | sort -u | bemenu | xargs swayfocus -c --name= |
||||||
|
# simple window switcher |
||||||
|
``` |
||||||
|
|
||||||
|
## Installation |
||||||
|
``` |
||||||
|
make && sudo make install |
||||||
|
``` |
@ -0,0 +1,125 @@ |
|||||||
|
require "json" |
||||||
|
require "option_parser" |
||||||
|
|
||||||
|
version = "0.1" |
||||||
|
puts "" |
||||||
|
|
||||||
|
class Window |
||||||
|
JSON.mapping({ |
||||||
|
id: UInt32, |
||||||
|
name: String, |
||||||
|
wtype: {type: String, key: "type"}, |
||||||
|
app_id: {type: String, default: ""}, |
||||||
|
wclass: {type: String, key: "class", default: ""}, |
||||||
|
marks: {type: Array(String), default: [] of String}, |
||||||
|
nodes: {type: Array(Window), default: [] of Window}, |
||||||
|
focused: {type: Bool, default: false} |
||||||
|
}) |
||||||
|
|
||||||
|
def clear_nodes |
||||||
|
@nodes = [] of Window |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def node_loop (root : Window) |
||||||
|
list = [] of Window |
||||||
|
root.nodes.each do |node| |
||||||
|
if(node.wtype == "con") |
||||||
|
list << node |
||||||
|
elsif(node.nodes != [] of Window) |
||||||
|
list.concat(node_loop(node)) |
||||||
|
end |
||||||
|
end |
||||||
|
return list |
||||||
|
end |
||||||
|
|
||||||
|
client_tree = Window.from_json(`swaymsg -t get_tree`) |
||||||
|
|
||||||
|
if(client_tree.wtype != "root") |
||||||
|
puts "Malformed client tree." |
||||||
|
exit(1) |
||||||
|
end |
||||||
|
|
||||||
|
window_list = node_loop(client_tree) |
||||||
|
|
||||||
|
def parse_marks(marks : Array(String), mark : String) |
||||||
|
res : Bool = false |
||||||
|
marks.each do |cm| |
||||||
|
if(cm.includes? mark) |
||||||
|
res = true |
||||||
|
end |
||||||
|
end |
||||||
|
return !res |
||||||
|
end |
||||||
|
|
||||||
|
def check_type |
||||||
|
end |
||||||
|
|
||||||
|
cycle = false |
||||||
|
OptionParser.parse do |parser| |
||||||
|
parser.banner = "Usage: swayfocus [OPTIONS]" |
||||||
|
|
||||||
|
parser.on "-v", "--version", "Show Version" do |
||||||
|
puts version |
||||||
|
exit(0) |
||||||
|
end |
||||||
|
|
||||||
|
parser.on "-h", "--help", "Show Help" do |
||||||
|
puts parser |
||||||
|
exit(0) |
||||||
|
end |
||||||
|
|
||||||
|
parser.on "-p", "--print", "Print window names and exit" do |
||||||
|
window_list.each do |win| |
||||||
|
puts win.name |
||||||
|
end |
||||||
|
exit(0) |
||||||
|
end |
||||||
|
|
||||||
|
parser.on "-c", "--cycle", "Cycle through all matching windows in order, instead of selecting the first in the list" do |
||||||
|
cycle = true |
||||||
|
end |
||||||
|
|
||||||
|
parser.on "-n WNAME", "--name=WNAME", "Match against window name" do |wname| |
||||||
|
window_list.reject! {|w| !w.name.includes? wname} |
||||||
|
end |
||||||
|
|
||||||
|
parser.on "-m WMARK", "--mark=WMARK", "Match against window mark" do |wmark| |
||||||
|
window_list.reject! {|w| parse_marks(w.marks, wmark)} |
||||||
|
end |
||||||
|
|
||||||
|
parser.on "-t WTYPE", "--type=WTYPE", "Match against window type (app_id for wayland, class for xwayland)" do |wtype| |
||||||
|
window_list.reject! {|w| !(w.app_id.includes?(wtype) || w.wclass.includes?(wtype))} |
||||||
|
end |
||||||
|
|
||||||
|
parser.invalid_option do |flag| |
||||||
|
STDERR.puts "#{flag} is not a valid option" |
||||||
|
STDERR.puts "" |
||||||
|
STDERR.puts parser |
||||||
|
exit(1) |
||||||
|
end |
||||||
|
|
||||||
|
parser.missing_option do |flag| |
||||||
|
STDERR.puts "#{flag} requires an argument" |
||||||
|
STDERR.puts "" |
||||||
|
STDERR.puts parser |
||||||
|
exit(1) |
||||||
|
end |
||||||
|
|
||||||
|
parser.unknown_args do |
||||||
|
exit(0) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
if(window_list == [] of Window) |
||||||
|
puts "No matching window." |
||||||
|
exit(1) |
||||||
|
end |
||||||
|
if(cycle) |
||||||
|
while(!window_list[window_list.size - 1].focused) |
||||||
|
window_list.push window_list[0] |
||||||
|
window_list.delete_at(0) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Process.exec("swaymsg", [%<[con_id=>+window_list[0].id.to_s+%<]>,"focus"]) |
Loading…
Reference in new issue