@@ -22,6 +22,125 @@ pub fn setupKeyboardHook() !win32.HHOOK {
2222 return hook .? ;
2323}
2424
25+ /// Process navigation keys for autocomplete UI
26+ fn processNavigationKeys (kbd : * win32.KBDLLHOOKSTRUCT ) callconv (.C ) win32.LRESULT {
27+ // Debug output for suggestion navigation
28+ debug .debugPrint ("Suggestion navigation key: 0x{X}\n " , .{kbd .vkCode });
29+
30+ // Handle navigation keys for autocomplete
31+ switch (kbd .vkCode ) {
32+ win32 .VK_UP = > {
33+ // Move to previous suggestion
34+ manager .navigateToPreviousSuggestion ();
35+ return 1 ; // Prevent default handling
36+ },
37+ win32 .VK_DOWN = > {
38+ // Move to next suggestion
39+ manager .navigateToNextSuggestion ();
40+ return 1 ; // Prevent default handling
41+ },
42+ win32 .VK_TAB , win32 .VK_RIGHT = > {
43+ debug .debugPrint ("Accepting current suggestion\n " , .{});
44+ // Accept current suggestion
45+ manager .acceptCurrentSuggestion ();
46+ return 1 ; // Prevent default handling
47+ },
48+ win32 .VK_RETURN = > {
49+ debug .debugPrint ("Accepting current suggestion with enter\n " , .{});
50+ // Accept current suggestion
51+ manager .acceptCurrentSuggestion ();
52+
53+ // Special handling for return key - after accepting suggestion,
54+ // we also need to properly handle the return key itself, so we don't
55+ // entirely consume it unless explicitly configured otherwise
56+ const config_consume_enter = true ; // Make this configurable
57+ return if (config_consume_enter ) 1 else 0 ;
58+ },
59+ else = > return 0 ,
60+ }
61+ }
62+
63+ /// Process special key combinations like Ctrl+Backspace
64+ fn processSpecialKeys (kbd : * win32.KBDLLHOOKSTRUCT ) callconv (.C ) win32.LRESULT {
65+ // Special handling for Ctrl+Backspace (whole word deletion)
66+ if (kbd .vkCode == win32 .VK_BACK and g_ctrl_pressed ) {
67+ debug .debugPrint ("Ctrl+Backspace detected - deleting whole word\n " , .{});
68+
69+ // First, let the application handle the real Ctrl+Backspace
70+ // by passing it to the next hook
71+ _ = win32 .CallNextHookEx (null , win32 .HC_ACTION , win32 .WM_KEYDOWN , @as (win32 .LPARAM , @bitCast (@intFromPtr (kbd ))));
72+
73+ // Add a small delay to let the OS process the keypress
74+ api .sleep (20 );
75+
76+ // Now force detection of the text field to sync our buffer with the new content
77+ buffer_controller .detectActiveTextField ();
78+
79+ // After syncing, update autocomplete suggestions
80+ const word = buffer_controller .getCurrentWord () catch "" ;
81+ manager .setCurrentWord (word );
82+ manager .getAutocompleteSuggestions () catch {};
83+
84+ // Print current buffer state to verify
85+ buffer_controller .printBufferState ();
86+
87+ // Return 0 to allow the key to be processed (we've already called the next hook)
88+ return 0 ;
89+ }
90+
91+ return -1 ; // Indicates no special key was processed
92+ }
93+
94+ /// Process standard text editing keys (backspace, delete, etc.)
95+ fn processTextEditingKeys (kbd : * win32.KBDLLHOOKSTRUCT ) void {
96+ debug .debugPrint ("Key down: 0x{X}\n " , .{kbd .vkCode });
97+
98+ // Exit application on ESC key
99+ if (kbd .vkCode == win32 .VK_ESCAPE ) {
100+ debug .debugPrint ("ESC pressed - exit\n " , .{});
101+ std .process .exit (0 );
102+ }
103+
104+ // Special key handling for text editing
105+ if (kbd .vkCode == win32 .VK_BACK ) {
106+ // Backspace key
107+ buffer_controller .processBackspace () catch | err | {
108+ debug .debugPrint ("Backspace error: {}\n " , .{err });
109+ };
110+
111+ // Add a small delay to let the backspace take effect
112+ api .sleep (5 );
113+
114+ // Detect the text field again to ensure sync
115+ buffer_controller .detectActiveTextField ();
116+
117+ // Update suggestions based on new text state
118+ const word = buffer_controller .getCurrentWord () catch "" ;
119+ manager .setCurrentWord (word );
120+ manager .getAutocompleteSuggestions () catch {};
121+ } else if (kbd .vkCode == win32 .VK_DELETE ) {
122+ // Delete key
123+ buffer_controller .processDelete () catch | err | {
124+ debug .debugPrint ("Delete error: {}\n " , .{err });
125+ };
126+ } else if (kbd .vkCode == win32 .VK_RETURN ) {
127+ // Enter/Return key
128+ buffer_controller .processReturn () catch | err | {
129+ debug .debugPrint ("Return error: {}\n " , .{err });
130+ };
131+ } else if (kbd .vkCode == win32 .VK_TAB ) {
132+ // Tab key might indicate focus change - detect text field
133+ buffer_controller .detectActiveTextField ();
134+ } else {
135+ // ASCII character input
136+ const char : u8 = @truncate (kbd .vkCode );
137+ buffer_controller .handleCharInput (char );
138+ }
139+
140+ // Debug: print current buffer state
141+ buffer_controller .printBufferState ();
142+ }
143+
25144/// Low-level keyboard hook callback function
26145fn keyboardHookProc (nCode : c_int , wParam : win32.WPARAM , lParam : win32.LPARAM ) callconv (.C ) win32.LRESULT {
27146 // First, immediately check if we should pass this to the next hook
@@ -45,9 +164,6 @@ fn keyboardHookProc(nCode: c_int, wParam: win32.WPARAM, lParam: win32.LPARAM) ca
45164
46165 // Only process keydown events
47166 if (wParam == win32 .WM_KEYDOWN or wParam == win32 .WM_SYSKEYDOWN ) {
48- // Track if we consumed the key
49- var key_consumed = false ;
50-
51167 // Handle navigation keys when autocomplete is visible
52168 if (manager .isSuggestionUIVisible () and
53169 (kbd .vkCode == win32 .VK_UP or
@@ -56,77 +172,13 @@ fn keyboardHookProc(nCode: c_int, wParam: win32.WPARAM, lParam: win32.LPARAM) ca
56172 kbd .vkCode == win32 .VK_RIGHT or
57173 kbd .vkCode == win32 .VK_RETURN ))
58174 {
59- // Debug output for suggestion navigation
60- debug .debugPrint ("Suggestion navigation key: 0x{X}\n " , .{kbd .vkCode });
61-
62- // Handle navigation keys for autocomplete
63- switch (kbd .vkCode ) {
64- win32 .VK_UP = > {
65- // Move to previous suggestion
66- manager .navigateToPreviousSuggestion ();
67- return 1 ; // Prevent default handling
68- },
69- win32 .VK_DOWN = > {
70- // Move to next suggestion
71- manager .navigateToNextSuggestion ();
72- return 1 ; // Prevent default handling
73- },
74- win32 .VK_TAB , win32 .VK_RIGHT = > {
75- debug .debugPrint ("Accepting current suggestion\n " , .{});
76- // Accept current suggestion
77- manager .acceptCurrentSuggestion ();
78- return 1 ; // Prevent default handling
79- },
80- win32 .VK_RETURN = > {
81- debug .debugPrint ("Accepting current suggestion with enter\n " , .{});
82- // Accept current suggestion
83- manager .acceptCurrentSuggestion ();
84-
85- // Special handling for return key - after accepting suggestion,
86- // we also need to properly handle the return key itself, so we don't
87- // entirely consume it unless explicitly configured otherwise
88- const config_consume_enter = true ; // Make this configurable
89- if (! config_consume_enter ) {
90- // Let the app handle enter normally
91- key_consumed = false ;
92- } else {
93- key_consumed = true ;
94- }
95- },
96- else = > {},
97- }
98-
99- // If we consumed the key, prevent default handling
100- if (key_consumed ) {
101- return 1 ;
102- }
175+ const result = processNavigationKeys (kbd );
176+ if (result >= 0 ) return result ;
103177 }
104178
105- // Special handling for Ctrl+Backspace (whole word deletion)
106- if (kbd .vkCode == win32 .VK_BACK and g_ctrl_pressed ) {
107- debug .debugPrint ("Ctrl+Backspace detected - deleting whole word\n " , .{});
108-
109- // First, let the application handle the real Ctrl+Backspace
110- // by passing it to the next hook
111- _ = win32 .CallNextHookEx (null , nCode , wParam , lParam );
112-
113- // Add a small delay to let the OS process the keypress
114- api .sleep (20 );
115-
116- // Now force detection of the text field to sync our buffer with the new content
117- buffer_controller .detectActiveTextField ();
118-
119- // After syncing, update autocomplete suggestions
120- const word = buffer_controller .getCurrentWord () catch "" ;
121- manager .setCurrentWord (word );
122- manager .getAutocompleteSuggestions () catch {};
123-
124- // Print current buffer state to verify
125- buffer_controller .printBufferState ();
126-
127- // Return 0 to allow the key to be processed (we've already called the next hook)
128- return 0 ;
129- }
179+ // Process special key combinations
180+ const special_result = processSpecialKeys (kbd );
181+ if (special_result >= 0 ) return special_result ;
130182
131183 // Limit processing to printable characters and specific control keys
132184 const is_control_key =
@@ -169,52 +221,7 @@ fn keyboardHookProc(nCode: c_int, wParam: win32.WPARAM, lParam: win32.LPARAM) ca
169221 const is_printable = kbd .vkCode >= 0x20 and kbd .vkCode <= 0x7E ;
170222
171223 if (is_control_key or is_printable ) {
172- debug .debugPrint ("Key down: 0x{X}\n " , .{kbd .vkCode });
173-
174- // Exit application on ESC key
175- if (kbd .vkCode == win32 .VK_ESCAPE ) {
176- debug .debugPrint ("ESC pressed - exit\n " , .{});
177- std .process .exit (0 );
178- }
179-
180- // Special key handling for text editing
181- if (kbd .vkCode == win32 .VK_BACK ) {
182- // Backspace key
183- buffer_controller .processBackspace () catch | err | {
184- debug .debugPrint ("Backspace error: {}\n " , .{err });
185- };
186-
187- // Add a small delay to let the backspace take effect
188- api .sleep (5 );
189-
190- // Detect the text field again to ensure sync
191- buffer_controller .detectActiveTextField ();
192-
193- // Update suggestions based on new text state
194- const word = buffer_controller .getCurrentWord () catch "" ;
195- manager .setCurrentWord (word );
196- manager .getAutocompleteSuggestions () catch {};
197- } else if (kbd .vkCode == win32 .VK_DELETE ) {
198- // Delete key
199- buffer_controller .processDelete () catch | err | {
200- debug .debugPrint ("Delete error: {}\n " , .{err });
201- };
202- } else if (kbd .vkCode == win32 .VK_RETURN ) {
203- // Enter/Return key
204- buffer_controller .processReturn () catch | err | {
205- debug .debugPrint ("Return error: {}\n " , .{err });
206- };
207- } else if (kbd .vkCode == win32 .VK_TAB ) {
208- // Tab key might indicate focus change - detect text field
209- buffer_controller .detectActiveTextField ();
210- } else if (is_printable ) {
211- // ASCII character input
212- const char : u8 = @truncate (kbd .vkCode );
213- buffer_controller .handleCharInput (char );
214- }
215-
216- // Debug: print current buffer state
217- buffer_controller .printBufferState ();
224+ processTextEditingKeys (kbd );
218225 }
219226 }
220227 }
0 commit comments