@@ -3,79 +3,285 @@ package main
33import (
44 "flag"
55 "fmt"
6- "log"
6+ "os"
7+ "os/signal"
78 "strings"
9+ "sync"
10+ "syscall"
811
912 "github.com/jialeicui/golibevdev"
1013 "github.com/samber/lo"
14+ log "github.com/sirupsen/logrus"
1115
1216 "github.com/jialeicui/keyswift/pkg/conf"
1317 "github.com/jialeicui/keyswift/pkg/evdev"
1418 "github.com/jialeicui/keyswift/pkg/keys"
15- "github.com/jialeicui/keyswift/pkg/wininfo "
19+ "github.com/jialeicui/keyswift/pkg/mode "
1620 "github.com/jialeicui/keyswift/pkg/wininfo/dbus"
1721)
1822
1923var (
20- flagKeyboard = flag .String ("keyboard" , "Apple" , "" )
24+ flagKeyboards = flag .String ("keyboards" , "keyboard" , "Comma-separated list of keyboard device name substrings" )
25+ flagConfig = flag .String ("config" , "" , "Configuration file path (defaults to $XDG_CONFIG_HOME/keyswift/config.yaml)" )
26+ // TODO change this to false
27+ flagVerbose = flag .Bool ("verbose" , true , "Enable verbose logging" )
2128)
2229
23- func main () {
24- c , err := conf .LoadConfig (conf .DefaultConfigPath ())
25- if err != nil {
26- log .Fatal (err )
27- }
30+ // InputDevice represents a grabbed input device
31+ type InputDevice struct {
32+ Device * golibevdev.InputDev
33+ Name string
34+ Path string
35+ }
2836
29- fmt .Printf ("Loaded config: %+v\n " , c )
37+ // InputDeviceManager manages multiple input devices
38+ type InputDeviceManager struct {
39+ devices []* InputDevice
40+ wg sync.WaitGroup
41+ }
42+
43+ // NewInputDeviceManager creates a new input device manager
44+ func NewInputDeviceManager () * InputDeviceManager {
45+ return & InputDeviceManager {
46+ devices : make ([]* InputDevice , 0 ),
47+ }
48+ }
3049
31- r , err := dbus .New ()
50+ // AddDevice adds and grabs a new input device
51+ func (m * InputDeviceManager ) AddDevice (name , path string ) error {
52+ dev , err := golibevdev .NewInputDev (path )
3253 if err != nil {
33- log . Fatal ( err )
54+ return fmt . Errorf ( "failed to open input device %s: %w" , path , err )
3455 }
35- defer r .Close ()
3656
37- fmt .Println ("Window Monitor service is running..." )
57+ if err = dev .Grab (); err != nil {
58+ dev .Close ()
59+ return fmt .Errorf ("failed to grab input device %s: %w" , path , err )
60+ }
3861
39- r .OnActiveWindowChange (func (info * wininfo.WinInfo ) {
40- fmt .Printf ("Active window: %s - %s\n " , info .Title , info .Class )
62+ m .devices = append (m .devices , & InputDevice {
63+ Device : dev ,
64+ Name : name ,
65+ Path : path ,
4166 })
67+ return nil
68+ }
4269
43- devs , err := evdev .NewOverviewImpl ().ListInputDevices ()
70+ // ProcessEvents starts processing events from all devices
71+ func (m * InputDeviceManager ) ProcessEvents (virtualKeyboard * golibevdev.UInputDev , modeManager * mode.Manager ) {
72+ for _ , dev := range m .devices {
73+ m .wg .Add (1 )
74+ go func (d * InputDevice ) {
75+ defer m .wg .Done ()
76+ m .processDeviceEvents (d , virtualKeyboard , modeManager )
77+ }(dev )
78+ }
79+ }
80+
81+ // processDeviceEvents processes events from a single device
82+ func (m * InputDeviceManager ) processDeviceEvents (dev * InputDevice , virtualKeyboard * golibevdev.UInputDev , modeManager * mode.Manager ) {
83+ log .Infof ("Starting event processing for device: %s" , dev .Name )
84+ for {
85+ ev , err := dev .Device .NextEvent (golibevdev .ReadFlagNormal )
86+ if err != nil {
87+ log .Errorf ("Error reading from device %s: %v" , dev .Name , err )
88+ return
89+ }
90+
91+ log .Debugf ("[%s] Received event: %+v" , dev .Name , ev )
92+
93+ var handled bool
94+ if ev .Type == golibevdev .EvKey {
95+ // Convert to our event type
96+ event := & mode.Event {
97+ KeyPress : & mode.KeyPressEvent {
98+ Key : keyCodeToString (ev .Code .(golibevdev.KeyEventCode )),
99+ Pressed : ev .Value == 1 ,
100+ Repeated : ev .Value == 2 ,
101+ },
102+ }
103+ log .Debugf ("[%s] Event: %+v" , dev .Name , event .KeyPress )
104+
105+ // Process the event through the mode manager
106+ handled , err = modeManager .ProcessEvent (event )
107+ if err != nil {
108+ log .Errorf ("[%s] Error processing event: %v" , dev .Name , err )
109+ continue
110+ }
111+ }
112+ // If the event wasn't handled by any mode, pass it through directly
113+ if ! handled {
114+ log .Debugf ("[%s] Passing through unhandled event: %+v" , dev .Name , ev )
115+ // Directly send the original key event to the output device
116+ virtualKeyboard .WriteEvent (ev .Type , ev .Code , ev .Value )
117+ }
118+ log .Debug ("--------------------" )
119+ }
120+ }
121+
122+ // Wait waits for all event processing to complete
123+ func (m * InputDeviceManager ) Wait () {
124+ m .wg .Wait ()
125+ }
126+
127+ // Close closes all input devices
128+ func (m * InputDeviceManager ) Close () {
129+ for _ , dev := range m .devices {
130+ log .Infof ("Closing device: %s" , dev .Name )
131+ dev .Device .Close ()
132+ }
133+ }
134+
135+ func main () {
136+ flag .Parse ()
137+
138+ if * flagVerbose {
139+ log .SetLevel (log .DebugLevel )
140+ }
141+
142+ // Load configuration
143+ configPath := * flagConfig
144+ if configPath == "" {
145+ configPath = conf .DefaultConfigPath ()
146+ }
147+
148+ c , err := conf .Load (configPath )
44149 if err != nil {
45150 log .Fatal (err )
46151 }
152+ fmt .Printf ("Loaded config from %s\n " , configPath )
47153
48- dev , ok := lo .Find (devs , func (item * evdev.InputDevice ) bool {
49- return strings .Contains (item .Name , * flagKeyboard )
50- })
51- if ! ok {
52- log .Fatalf ("Keyboard %s not found" , * flagKeyboard )
154+ // Initialize window info service
155+ windowMonitor , err := dbus .New ()
156+ if err != nil {
157+ log .Fatal (err )
53158 }
159+ defer windowMonitor .Close ()
160+ fmt .Println ("Window Monitor service is running..." )
54161
162+ // Initialize virtual keyboard for output
55163 out , err := golibevdev .NewVirtualKeyboard ("keyswift" )
56164 if err != nil {
57165 log .Fatal (err )
58166 }
59167 defer out .Close ()
168+ gnomeKeys := keys .NewGnomeKeys (out )
169+
170+ // Initialize mode manager
171+ modeManager , err := mode .NewManager (c , gnomeKeys , windowMonitor )
172+ if err != nil {
173+ log .Fatal (err )
174+ }
175+ fmt .Println ("Mode manager initialized" )
60176
61- in , err := golibevdev .NewInputDev (dev .Path )
177+ // Find input devices
178+ devs , err := evdev .NewOverviewImpl ().ListInputDevices ()
62179 if err != nil {
63180 log .Fatal (err )
64181 }
65- defer in .Close ()
66182
67- gnome := keys .NewGnomeKeys (out )
183+ // Parse keyboard patterns and find matching devices
184+ keyboardPatterns := strings .Split (* flagKeyboards , "," )
185+ var matchedDevices []* evdev.InputDevice
68186
69- for {
70- ev , err := in .NextEvent (golibevdev .ReadFlagNormal )
71- if err != nil {
72- log .Fatal (err )
73- }
74- if ev .Type != golibevdev .EvKey {
187+ for _ , pattern := range keyboardPatterns {
188+ pattern = strings .TrimSpace (pattern )
189+ if pattern == "" {
75190 continue
76191 }
77- if ev .Code == golibevdev .KeyC {
78- gnome .Copy ()
192+
193+ matches := lo .Filter (devs , func (item * evdev.InputDevice , _ int ) bool {
194+ return strings .Contains (item .Name , pattern )
195+ })
196+
197+ matchedDevices = append (matchedDevices , matches ... )
198+ }
199+
200+ // Remove duplicates
201+ matchedDevices = lo .UniqBy (matchedDevices , func (dev * evdev.InputDevice ) string {
202+ return dev .Path
203+ })
204+
205+ if len (matchedDevices ) == 0 {
206+ fmt .Println ("Available keyboards:" )
207+ for _ , d := range devs {
208+ fmt .Printf (" - %s\n " , d .Name )
79209 }
210+ log .Fatalf ("No keyboards matching patterns: %s" , * flagKeyboards )
211+ }
212+
213+ // Initialize and set up the device manager
214+ deviceManager := NewInputDeviceManager ()
215+ defer deviceManager .Close ()
216+
217+ // Add all matched devices to the manager
218+ for _ , dev := range matchedDevices {
219+ fmt .Printf ("Using keyboard: %s (%s)\n " , dev .Name , dev .Path )
220+ if err := deviceManager .AddDevice (dev .Name , dev .Path ); err != nil {
221+ log .Warnf ("Failed to add device %s: %v" , dev .Name , err )
222+ continue
223+ }
224+ }
225+
226+ // Handle signals
227+ sigChan := make (chan os.Signal , 1 )
228+ signal .Notify (sigChan , syscall .SIGINT , syscall .SIGTERM )
229+
230+ go func () {
231+ <- sigChan
232+ fmt .Println ("Shutting down..." )
233+ deviceManager .Close ()
234+ out .Close ()
235+ windowMonitor .Close ()
236+ os .Exit (0 )
237+ }()
238+
239+ // Start processing events from all devices
240+ fmt .Printf ("Processing events from %d devices... Press Ctrl+C to exit\n " , len (deviceManager .devices ))
241+ deviceManager .ProcessEvents (out , modeManager )
242+
243+ // Wait for all processing to complete (typically won't reach here except on error)
244+ deviceManager .Wait ()
245+ }
246+
247+ // keyCodeToString converts a key code to a string representation
248+ // This is a simplified version - you'd want a complete mapping
249+ func keyCodeToString (code golibevdev.KeyEventCode ) string {
250+ // You'll need a complete mapping from golibevdev key codes to strings
251+ // This is just a starting point
252+ keyMap := map [golibevdev.KeyEventCode ]string {
253+ golibevdev .KeyEsc : "esc" ,
254+ golibevdev .KeyA : "a" ,
255+ golibevdev .KeyB : "b" ,
256+ golibevdev .KeyC : "c" ,
257+ golibevdev .KeyD : "d" ,
258+ golibevdev .KeyE : "e" ,
259+ golibevdev .KeyF : "f" ,
260+ golibevdev .KeyG : "g" ,
261+ golibevdev .KeyH : "h" ,
262+ golibevdev .KeyI : "i" ,
263+ golibevdev .KeyJ : "j" ,
264+ golibevdev .KeyK : "k" ,
265+ golibevdev .KeyL : "l" ,
266+ golibevdev .KeyM : "m" ,
267+ golibevdev .KeyN : "n" ,
268+ golibevdev .KeyO : "o" ,
269+ golibevdev .KeyP : "p" ,
270+ golibevdev .KeyQ : "q" ,
271+ golibevdev .KeyR : "r" ,
272+ golibevdev .KeyS : "s" ,
273+ golibevdev .KeyT : "t" ,
274+ golibevdev .KeyU : "u" ,
275+ golibevdev .KeyV : "v" ,
276+ golibevdev .KeyW : "w" ,
277+ golibevdev .KeyX : "x" ,
278+ golibevdev .KeyY : "y" ,
279+ golibevdev .KeyZ : "z" ,
280+ // Add more keys as needed
281+ }
282+
283+ if name , ok := keyMap [code ]; ok {
284+ return name
80285 }
286+ return code .String ()
81287}
0 commit comments