half-baked re-implementation of the major parts of sdorfehs in Hammerspoon
1-- find a window table object from an hs.window object
2spoonfish.window_find_by_hswindow = function(win)
3 for _, w in pairs(spoonfish.windows) do
4 if w["win"] == win then
5 return w
6 end
7 end
8
9 return nil
10end
11
12-- find a window table object from its hs.window id
13spoonfish.window_find_by_id = function(id)
14 for _, w in pairs(spoonfish.windows) do
15 if w["win"]:id() == id then
16 return w
17 end
18 end
19
20 return nil
21end
22
23-- move a window to fit its frame, or hide it if in frame 0
24spoonfish.window_reframe = function(win)
25 if win == nil or win == {} then
26 error("bogus window passed")
27 return
28 end
29
30 if win["frame"] == 0 then
31 error("bogus frame for win " .. win["title"])
32 return
33 end
34
35 local iframe = spoonfish.frame_rect_with_gap(win["space"], win["frame"])
36 win["win"]:move(iframe, nil, true, 0)
37
38 if win["space"] == hs.spaces.activeSpaceOnScreen() then
39 spoonfish.window_reborder(win)
40 end
41end
42
43-- redraw a border and shadow on a window
44spoonfish.window_reborder = function(win)
45 if win == nil or win == {} then
46 error("bogus window passed")
47 return
48 end
49
50 if spoonfish.border_size == 0 then
51 return
52 end
53
54 for _, w in pairs({ "shadow", "border" }) do
55 local irect = spoonfish.frame_rect_with_gap(win["space"], win["frame"])
56 irect = spoonfish.inset(irect, -(spoonfish.border_size))
57
58 if w == "shadow" then
59 irect.x = irect.x + spoonfish.shadow_size
60 irect.y = irect.y + spoonfish.shadow_size
61 end
62
63 if win[w] == nil then
64 win[w] = hs.drawing.rectangle(irect)
65 else
66 win[w]:setFrame(irect)
67 end
68 win[w]:setLevel(hs.drawing.windowLevels.desktopIcon)
69
70 local color
71 if w == "border" then
72 color = spoonfish.border_color
73 elseif w == "shadow" then
74 color = spoonfish.shadow_color
75 end
76 win[w]:setStrokeColor({ ["hex"] = color })
77 win[w]:setFill(true)
78 win[w]:setFillColor({ ["hex"] = color })
79 win[w]:setRoundedRectRadii(14, 14)
80 win[w]:show()
81 end
82end
83
84-- remove a window from the stack and bring up a new window in the frame
85spoonfish.window_remove = function(win)
86 local frame_id = win["frame"]
87 if win["border"] ~= nil then
88 win["border"]:delete()
89 win["border"] = nil
90 end
91 if win["shadow"] ~= nil then
92 win["shadow"]:delete()
93 win["shadow"] = nil
94 end
95 spoonfish.window_restack(win, spoonfish.position.REMOVE)
96 if frame_id ~= 0 then
97 spoonfish.frame_cycle(win["space"], frame_id, false)
98 end
99end
100
101-- move a window to the front or back of the window stack (or remove it)
102spoonfish.window_restack = function(win, pos)
103 if pos == nil then
104 error("invalid position argument")
105 return
106 end
107
108 local new_stack = {}
109 for _, w in ipairs(spoonfish.windows) do
110 if w == win then
111 if pos == spoonfish.position.FRONT then
112 table.insert(new_stack, 1, w)
113 end
114 else
115 table.insert(new_stack, w)
116 end
117 end
118 if pos == spoonfish.position.BACK then
119 table.insert(new_stack, win)
120 end
121 spoonfish.windows = new_stack
122end
123
124-- restore a window but don't bother moving to its frame, window_reframe will
125spoonfish.window_show = function(win)
126 if win["win"]:isMinimized() then
127 win["win"]:unminimize()
128 end
129end
130
131-- return a table of windows not first in any frame
132spoonfish.windows_not_visible = function(space_id)
133 local wins = {}
134 local topwins = {}
135 for _, w in ipairs(spoonfish.windows) do
136 if w["space"] == space_id then
137 if topwins[w["frame"]] == nil then
138 topwins[w["frame"]] = w
139 else
140 table.insert(wins, w)
141 end
142 end
143 end
144 return wins
145end