fvwm-window-search 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +9 -1
- data/README.md +5 -5
- data/focus.c +80 -0
- data/focus.sh +5 -15
- data/fvwm-window-search +5 -8
- data/lib.c +24 -0
- data/lib.rb +7 -75
- data/winlist.c +124 -0
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2819e711c1b51e6a619fbbf5839481b9a8019fc2c6db40265bda3756c65cad51
|
4
|
+
data.tar.gz: 8a58cab8dfc2e504e83d9b71a430a52bb95a63144fc5c499db02172078c57cb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d0ab3a08c7bf6993e74c6c8aa07cfbbc1d34dfbc0a31bc6e61f190d6db4fbe0201305967522bf7507470df21e8183e49032b78faa9ea8e77b5f71fe0603d0d5
|
7
|
+
data.tar.gz: 58b49f87d0b92f176b6cf4c80ae0d11fc81f471ed096ac64e50bb74c64c5e52cc929ee437c240c298212ee58cf4af4633d965ebe6ebfc15e27f7f2943bf4c48d
|
data/Makefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
out := _out
|
2
2
|
dmenu := $(out)/dmenu
|
3
|
-
dmenu.commit :=
|
3
|
+
dmenu.commit := 1a13d0465d1a6f4f74bc5b07b04c9bd542f20ba6
|
4
|
+
|
5
|
+
all: $(out)/.dmenu.build $(out)/focus $(out)/winlist
|
4
6
|
|
5
7
|
$(out)/.dmenu.build: $(out)/.dmenu.$(dmenu.commit) dmenu.patch
|
6
8
|
patch -d $(dmenu) -p1 < dmenu.patch
|
@@ -12,5 +14,11 @@ $(out)/.dmenu.$(dmenu.commit):
|
|
12
14
|
git -C $(dmenu) checkout $(dmenu.commit) -q
|
13
15
|
touch $@
|
14
16
|
|
17
|
+
libs := x11 jansson
|
18
|
+
LDFLAGS := $(shell pkg-config --libs $(libs))
|
19
|
+
CFLAGS := -g -Wall $(shell pkg-config --cflags $(libs))
|
20
|
+
$(out)/%: %.c lib.c
|
21
|
+
$(LINK.c) $< $(LOADLIBES) $(LDLIBS) -o $@
|
22
|
+
|
15
23
|
# an empty target to satisfy rubygems
|
16
24
|
install:
|
data/README.md
CHANGED
@@ -8,12 +8,12 @@ Incremental window search & immediate switch to the selected window
|
|
8
8
|

|
9
9
|
|
10
10
|
* Should work w/ most stackings X11 window managers.
|
11
|
-
* Filtering by window name/resource/
|
11
|
+
* Filtering by window name/resource/class.
|
12
12
|
|
13
13
|
## Reqs
|
14
14
|
|
15
15
|
* Ruby 2.4+
|
16
|
-
* `
|
16
|
+
* `dnf install jansson-devel`
|
17
17
|
|
18
18
|
## Compilation
|
19
19
|
|
@@ -38,7 +38,7 @@ dmenu:
|
|
38
38
|
fn: Monospace-12
|
39
39
|
b: false
|
40
40
|
selhook-return-key-focus-only: true
|
41
|
-
filter:
|
41
|
+
filter-out:
|
42
42
|
name: ['System Monitor']
|
43
43
|
resource: []
|
44
44
|
class: []
|
@@ -50,8 +50,8 @@ CLO.
|
|
50
50
|
|
51
51
|
[dmenu(1)]: https://manpages.debian.org/unstable/suckless-tools/dmenu.1.en.html
|
52
52
|
|
53
|
-
`filter` key tells what windows should be filtered out. Each value
|
54
|
-
a subkey is an array of regexes. See the defaults in
|
53
|
+
`filter-out` key tells what windows should be filtered out. Each value
|
54
|
+
in a subkey is an array of regexes. See the defaults in
|
55
55
|
`fvwm-window-search` file.
|
56
56
|
|
57
57
|
## Bugs
|
data/focus.c
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <err.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
|
6
|
+
#include <X11/Xlib.h>
|
7
|
+
#include <X11/Xatom.h>
|
8
|
+
|
9
|
+
#include "lib.c"
|
10
|
+
|
11
|
+
ulong str2id(const char *s) {
|
12
|
+
ulong id;
|
13
|
+
if (sscanf(s, "0x%lx", &id) != 1 &&
|
14
|
+
sscanf(s, "0X%lx", &id) != 1 &&
|
15
|
+
sscanf(s, "%lu", &id) != 1) return 0;
|
16
|
+
return id;
|
17
|
+
}
|
18
|
+
|
19
|
+
bool client_msg(Display *dpy, Window id, char *msg,
|
20
|
+
unsigned long data0, unsigned long data1,
|
21
|
+
unsigned long data2, unsigned long data3,
|
22
|
+
unsigned long data4) {
|
23
|
+
XEvent event;
|
24
|
+
long mask = SubstructureRedirectMask | SubstructureNotifyMask;
|
25
|
+
|
26
|
+
event.xclient.type = ClientMessage;
|
27
|
+
event.xclient.serial = 0;
|
28
|
+
event.xclient.send_event = True;
|
29
|
+
event.xclient.message_type = XInternAtom(dpy, msg, False);
|
30
|
+
event.xclient.window = id;
|
31
|
+
event.xclient.format = 32;
|
32
|
+
event.xclient.data.l[0] = data0;
|
33
|
+
event.xclient.data.l[1] = data1;
|
34
|
+
event.xclient.data.l[2] = data2;
|
35
|
+
event.xclient.data.l[3] = data3;
|
36
|
+
event.xclient.data.l[4] = data4;
|
37
|
+
|
38
|
+
if (XSendEvent(dpy, DefaultRootWindow(dpy), False, mask, &event))
|
39
|
+
return true;
|
40
|
+
warnx("cannot send %s event", msg);
|
41
|
+
return false;
|
42
|
+
}
|
43
|
+
|
44
|
+
bool window_activate(Display *dpy, Window id) {
|
45
|
+
long desk = desktop(dpy, id);
|
46
|
+
if (-1 != desk) {
|
47
|
+
client_msg(dpy, DefaultRootWindow(dpy), "_NET_CURRENT_DESKTOP",
|
48
|
+
desk, 0, 0, 0, 0);
|
49
|
+
}
|
50
|
+
|
51
|
+
bool r = client_msg(dpy, id, "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
|
52
|
+
XMapRaised(dpy, id);
|
53
|
+
return r;
|
54
|
+
}
|
55
|
+
|
56
|
+
bool window_center_mouse(Display *dpy, ulong id) {
|
57
|
+
XWindowAttributes attrs;
|
58
|
+
if (!XGetWindowAttributes(dpy, id, &attrs)) return false;
|
59
|
+
if (!XWarpPointer(dpy, 0, id, 0, 0, 0, 0, attrs.width/2, attrs.height/2))
|
60
|
+
return false;
|
61
|
+
XFlush(dpy);
|
62
|
+
return true;
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
int main(int argc, char **argv) {
|
68
|
+
Display *dpy = XOpenDisplay(getenv("DISPLAY"));
|
69
|
+
if (!dpy) errx(1, "failed to open display %s", getenv("DISPLAY"));
|
70
|
+
if (argc != 2) errx(1, "usage: focus window-id");
|
71
|
+
|
72
|
+
ulong id = str2id(argv[1]);
|
73
|
+
if (!id) errx(1, "invalid window id: `%s`", argv[1]);
|
74
|
+
|
75
|
+
XSynchronize(dpy, True); // snake oil?
|
76
|
+
bool r = window_activate(dpy, id);
|
77
|
+
if (!r) return 1;
|
78
|
+
r = window_center_mouse(dpy, id);
|
79
|
+
return !r;
|
80
|
+
}
|
data/focus.sh
CHANGED
@@ -1,22 +1,12 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
|
3
3
|
id=`echo "$1" | awk -F'|' '{print $NF} END { exit $NF == "" ? 1 : 0}'` || {
|
4
|
-
echo "usage: `basename "$0"` '
|
4
|
+
echo "usage: `basename "$0"` 'foo | bar | id'"
|
5
5
|
exit 1
|
6
6
|
}
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
#
|
11
|
-
# +-------------+
|
12
|
-
# | Title |
|
13
|
-
# +-------------+
|
14
|
-
# | ▲ |
|
15
|
-
# | |
|
16
|
-
# | |
|
17
|
-
# +-------------+
|
8
|
+
__filename=`readlink -f "$0"`
|
9
|
+
__dirname=`dirname "${__filename}"`
|
18
10
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
xdotool windowactivate "$id" mousemove --window "$id" "$x" 0
|
11
|
+
# shellcheck disable=2086
|
12
|
+
${__dirname}/_out/focus $id
|
data/fvwm-window-search
CHANGED
@@ -15,7 +15,7 @@ def options
|
|
15
15
|
"b" => true,
|
16
16
|
"i" => true,
|
17
17
|
},
|
18
|
-
"filter" => {
|
18
|
+
"filter-out" => {
|
19
19
|
"name" => [],
|
20
20
|
"resource" => [],
|
21
21
|
"class" => ['^Fvwm', '!^FvwmIdent$']
|
@@ -61,18 +61,15 @@ def menu params, text
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def main
|
64
|
-
['xwininfo', 'xdotool'].each do |util|
|
65
|
-
errx 1, "no #{util} in PATH" unless which util
|
66
|
-
end
|
67
|
-
|
68
64
|
opt = options
|
69
65
|
begin
|
70
|
-
winlist =
|
66
|
+
winlist = windows_filter_out opt["filter-out"], windows
|
71
67
|
rescue RegexpError
|
72
|
-
errx 1, "filter: #{$!}"
|
68
|
+
errx 1, "filter-out: #{$!}"
|
73
69
|
end
|
74
70
|
winlist = winlist.map do |w|
|
75
|
-
|
71
|
+
desk = w['desk'] == -1 ? '*' : w['desk']
|
72
|
+
[desk, w['class'], w['name'], w['host'], '0x'+w['id'].to_s(16)].join ' | '
|
76
73
|
end.join "\n"
|
77
74
|
|
78
75
|
menu opt["dmenu"], winlist
|
data/lib.c
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
bool prop(Display *dpy, Window wid, Atom expected_type, const char *name,
|
2
|
+
u_char **result, ulong *size) {
|
3
|
+
Atom type;
|
4
|
+
int format;
|
5
|
+
ulong bytes_after;
|
6
|
+
|
7
|
+
Atom atom = XInternAtom(dpy, name, False);
|
8
|
+
int r = XGetWindowProperty(dpy, wid, atom, 0L, ~0L, False,
|
9
|
+
expected_type, &type, &format,
|
10
|
+
size, &bytes_after, result);
|
11
|
+
return r == Success && result;
|
12
|
+
}
|
13
|
+
|
14
|
+
long desktop(Display *dpy, Window wid) {
|
15
|
+
u_char *prop_val = NULL;
|
16
|
+
ulong prop_size;
|
17
|
+
if (!prop(dpy, wid, XA_CARDINAL, "_NET_WM_DESKTOP", &prop_val, &prop_size))
|
18
|
+
return -2;
|
19
|
+
|
20
|
+
long r = -1;
|
21
|
+
if (prop_val) r = ((long*)prop_val)[0];
|
22
|
+
free(prop_val);
|
23
|
+
return r;
|
24
|
+
}
|
data/lib.rb
CHANGED
@@ -1,75 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class FvwmWindowSearch::Window
|
4
|
-
def initialize xwininfo_line
|
5
|
-
@line = xwininfo_line.match(/^([x0-9a-f]+)\s+(["\(].+["\)]):\s+\((.*)\)\s+([x0-9+-]+)\s+([0-9+-]+)$/)
|
6
|
-
raise "invalid xwininfo line" unless @line
|
7
|
-
@dim = parse
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse
|
11
|
-
dim = {}
|
12
|
-
if @line[4]
|
13
|
-
m4 = @line[4].match(/^([0-9]+)x([0-9]+)\+([0-9-]+)\+([0-9-]+)$/)
|
14
|
-
if m4
|
15
|
-
dim[:w] = m4[1].to_i
|
16
|
-
dim[:h] = m4[2].to_i
|
17
|
-
dim[:x_rel] = m4[3].to_i
|
18
|
-
dim[:y_rel] = m4[4].to_i
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
if @line[5]
|
23
|
-
m5 = @line[5].match(/^\+([0-9-]+)\+([0-9-]+)$/)
|
24
|
-
if m5
|
25
|
-
dim[:x] = m5[1].to_i
|
26
|
-
dim[:y] = m5[2].to_i
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
dim
|
31
|
-
end
|
32
|
-
|
33
|
-
def id; @line[1]; end
|
34
|
-
|
35
|
-
def name;
|
36
|
-
return unless @line[2]
|
37
|
-
@line[2] == '(has no name)' ? nil : @line[2][1..-2]
|
38
|
-
end
|
39
|
-
|
40
|
-
def resource; @line[3]&.split(' ')&.dig(0)&.slice(1..-2); end
|
41
|
-
def class; @line[3]&.split(' ')&.dig(1)&.slice(1..-2); end
|
42
|
-
def width; @dim[:w]; end
|
43
|
-
def height; @dim[:h]; end
|
44
|
-
def x; @dim[:x]; end # an absolute upper-left X
|
45
|
-
def y; @dim[:y]; end # an absolute upper-left Y
|
46
|
-
def x_rel; @dim[:x_rel]; end
|
47
|
-
def y_rel; @dim[:y_rel]; end
|
48
|
-
|
49
|
-
def useful?
|
50
|
-
return false unless @line
|
51
|
-
return false if width == 0 || height == 0
|
52
|
-
return false if (x == x_rel) && (y == y_rel)
|
53
|
-
return false if x_rel > 0 || y_rel > 0
|
54
|
-
return false unless self.class
|
55
|
-
true
|
56
|
-
end
|
57
|
-
|
58
|
-
def inspect
|
59
|
-
"#<Window> id=#{id}, name=#{name}, resource=#{resource}, class=#{self.class}"
|
60
|
-
end
|
61
|
-
end
|
1
|
+
require "json"
|
62
2
|
|
63
3
|
module FvwmWindowSearch
|
64
4
|
def windows
|
65
|
-
|
66
|
-
.
|
67
|
-
.map(&:strip)
|
68
|
-
.map {|v| Window.new(v)}
|
69
|
-
.select(&:useful?)
|
5
|
+
cmd = File.join(__dir__, '_out/winlist')
|
6
|
+
JSON.parse `#{cmd}`
|
70
7
|
end
|
71
8
|
|
72
|
-
def
|
9
|
+
def windows_filter_out patterns, winlist
|
73
10
|
desired = -> (type, value) {
|
74
11
|
include = patterns[type].select {|v| v[0] != '!'}
|
75
12
|
exclude = patterns[type].select {|v| v[0] == '!'}.map {|v| v[1..-1]}
|
@@ -83,9 +20,9 @@ module FvwmWindowSearch
|
|
83
20
|
true
|
84
21
|
}
|
85
22
|
|
86
|
-
winlist.select { |w| desired.call "class", w
|
87
|
-
.select { |w| desired.call "resource", w
|
88
|
-
.select { |w| desired.call "name", w
|
23
|
+
winlist.select { |w| desired.call "class", w['class'] }
|
24
|
+
.select { |w| desired.call "resource", w['resource'] }
|
25
|
+
.select { |w| desired.call "name", w['name'] }
|
89
26
|
end
|
90
27
|
|
91
28
|
def deep_merge first, second
|
@@ -97,9 +34,4 @@ module FvwmWindowSearch
|
|
97
34
|
$stderr.puts "#{File.basename $0} error: #{msg}"
|
98
35
|
exit exit_code
|
99
36
|
end
|
100
|
-
|
101
|
-
def which cmd
|
102
|
-
ENV['PATH'].split(File::PATH_SEPARATOR).map {|v| File.join v, cmd }
|
103
|
-
.find {|v| File.executable?(v) && !File.directory?(v) }
|
104
|
-
end
|
105
37
|
end
|
data/winlist.c
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <err.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <string.h>
|
6
|
+
#include <math.h>
|
7
|
+
|
8
|
+
#include <X11/Xlib.h>
|
9
|
+
#include <X11/Xatom.h>
|
10
|
+
#include <jansson.h>
|
11
|
+
|
12
|
+
#include "lib.c"
|
13
|
+
|
14
|
+
typedef struct {
|
15
|
+
Window *ids;
|
16
|
+
ulong size;
|
17
|
+
} WinList;
|
18
|
+
|
19
|
+
// result should be freed
|
20
|
+
WinList winlist(Display *dpy) {
|
21
|
+
WinList list;
|
22
|
+
u_char *result;
|
23
|
+
|
24
|
+
if (!prop(dpy, DefaultRootWindow(dpy), XA_WINDOW, "_NET_CLIENT_LIST",
|
25
|
+
&result, &list.size)) {
|
26
|
+
list.size = -1;
|
27
|
+
return list;
|
28
|
+
}
|
29
|
+
|
30
|
+
list.ids = (Window*)result;
|
31
|
+
return list;
|
32
|
+
}
|
33
|
+
|
34
|
+
// result should be freed
|
35
|
+
char* wm_client_machine(Display *dpy, Window wid) {
|
36
|
+
u_char *prop_val = NULL;
|
37
|
+
ulong prop_size;
|
38
|
+
prop(dpy, wid, XA_STRING, "WM_CLIENT_MACHINE", &prop_val, &prop_size);
|
39
|
+
return (char*)prop_val;
|
40
|
+
}
|
41
|
+
|
42
|
+
ulong str_index(const char *s, char ch) {
|
43
|
+
char *p = strchr(s, ch);
|
44
|
+
if (!p) return -1;
|
45
|
+
return (ulong)(p - s);
|
46
|
+
}
|
47
|
+
|
48
|
+
typedef struct {
|
49
|
+
char *resource;
|
50
|
+
char *class_name;
|
51
|
+
} ResClass;
|
52
|
+
|
53
|
+
// result should be freed
|
54
|
+
ResClass wm_class(Display *dpy, Window wid) {
|
55
|
+
ResClass r = {.resource = NULL};
|
56
|
+
|
57
|
+
u_char *prop_val = NULL;
|
58
|
+
ulong prop_size;
|
59
|
+
if (!prop(dpy, wid, XA_STRING, "WM_CLASS", &prop_val, &prop_size))
|
60
|
+
return r;
|
61
|
+
|
62
|
+
ulong idx = str_index((char*)prop_val, '\0');
|
63
|
+
if (idx < prop_size) {
|
64
|
+
r.resource = (char*)malloc(idx+2);
|
65
|
+
snprintf(r.resource, idx+1, "%s", prop_val);
|
66
|
+
|
67
|
+
ulong len = prop_size-idx;
|
68
|
+
r.class_name = (char*)malloc(len+1);
|
69
|
+
snprintf(r.class_name, len, "%s", prop_val+idx+1);
|
70
|
+
}
|
71
|
+
|
72
|
+
free(prop_val);
|
73
|
+
return r;
|
74
|
+
}
|
75
|
+
|
76
|
+
// result should be freed
|
77
|
+
char* wm_name(Display *dpy, Window wid) {
|
78
|
+
u_char *prop_val = NULL;
|
79
|
+
ulong prop_size;
|
80
|
+
|
81
|
+
Atom utf8_str = XInternAtom(dpy, "UTF8_STRING", False);
|
82
|
+
bool r = prop(dpy, wid, utf8_str, "_NET_WM_NAME", &prop_val, &prop_size);
|
83
|
+
if (r && prop_val) return (char*)prop_val;
|
84
|
+
|
85
|
+
prop(dpy, wid, XA_STRING, "WM_NAME", &prop_val, &prop_size);
|
86
|
+
return (char*)prop_val;
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
int main() {
|
92
|
+
Display *dpy = XOpenDisplay(getenv("DISPLAY"));
|
93
|
+
if (!dpy) errx(1, "failed to open display %s", getenv("DISPLAY"));
|
94
|
+
|
95
|
+
json_t *r = json_array();
|
96
|
+
WinList list = winlist(dpy);
|
97
|
+
for (ulong idx = 0; idx < list.size; idx++) {
|
98
|
+
ulong wid = list.ids[idx];
|
99
|
+
|
100
|
+
char *host = wm_client_machine(dpy, wid);
|
101
|
+
char *name = wm_name(dpy, wid);
|
102
|
+
ResClass rc = wm_class(dpy, wid);
|
103
|
+
|
104
|
+
json_t *line = json_object();
|
105
|
+
json_object_set_new(line, "desk", json_integer(desktop(dpy, wid)));
|
106
|
+
json_object_set_new(line, "host", json_string(host));
|
107
|
+
json_object_set_new(line, "name", json_string(name));
|
108
|
+
json_object_set_new(line, "resource", json_string(rc.resource));
|
109
|
+
json_object_set_new(line, "class", json_string(rc.class_name));
|
110
|
+
json_object_set_new(line, "id", json_integer(wid));
|
111
|
+
json_array_append_new(r, line);
|
112
|
+
|
113
|
+
free(host);
|
114
|
+
free(name);
|
115
|
+
free(rc.resource);
|
116
|
+
free(rc.class_name);
|
117
|
+
}
|
118
|
+
XFree(list.ids);
|
119
|
+
|
120
|
+
char *dump = json_dumps(r, JSON_COMPACT);
|
121
|
+
printf("%s\n", dump);
|
122
|
+
free(dump);
|
123
|
+
json_decref(r);
|
124
|
+
}
|
metadata
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fvwm-window-search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Gromnitsky
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: "."
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
A window switcher: search for windows interactively using a patched
|
15
15
|
dmenu utility (comes with the gem). This was originally made for Fvwm,
|
16
16
|
but it's been fully rewritten to work out-of-the-box with any stacking
|
17
|
-
window manager. Requires
|
17
|
+
window manager. Requires jansson-devel C library installed.
|
18
18
|
|
19
19
|
It differs from rofi & co in that it activates (brings up) windows
|
20
20
|
_during_ the search.
|
@@ -30,13 +30,16 @@ files:
|
|
30
30
|
- README.md
|
31
31
|
- dmenu.patch
|
32
32
|
- extconf.rb
|
33
|
+
- focus.c
|
33
34
|
- focus.sh
|
35
|
+
- lib.c
|
34
36
|
- lib.rb
|
37
|
+
- winlist.c
|
35
38
|
homepage: https://github.com/gromnitsky/fvwm-window-search
|
36
39
|
licenses:
|
37
40
|
- MIT
|
38
41
|
metadata: {}
|
39
|
-
post_install_message:
|
42
|
+
post_install_message:
|
40
43
|
rdoc_options: []
|
41
44
|
require_paths:
|
42
45
|
- lib
|
@@ -52,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
55
|
version: '0'
|
53
56
|
requirements: []
|
54
57
|
rubygems_version: 3.1.2
|
55
|
-
signing_key:
|
58
|
+
signing_key:
|
56
59
|
specification_version: 4
|
57
60
|
summary: 'A window switcher: an interactive incremental windows search & selection
|
58
61
|
for X Window'
|