11//! Server listener and connection handling
22use std:: error:: Error ;
3- use std:: io:: { Read , Write } ;
4- use std:: net:: TcpListener ;
3+ use std:: io:: { ErrorKind , Read , Write } ;
4+ use std:: net:: { TcpListener , TcpStream } ;
55#[ cfg( unix) ]
6- use std:: os:: unix:: net:: UnixListener ;
6+ use std:: os:: unix:: net:: { UnixListener , UnixStream } ;
77use std:: sync:: { Arc , Mutex } ;
88use std:: thread;
9+ use std:: time:: Duration ;
910
1011use super :: Server ;
1112use crate :: protocol:: setup:: { SetupRequest , SetupResponse } ;
1213
14+ /// Trait for streams that can set read timeouts
15+ trait TimeoutStream : Read + Write {
16+ fn set_read_timeout ( & self , dur : Option < Duration > ) -> std:: io:: Result < ( ) > ;
17+ }
18+
19+ impl TimeoutStream for TcpStream {
20+ fn set_read_timeout ( & self , dur : Option < Duration > ) -> std:: io:: Result < ( ) > {
21+ TcpStream :: set_read_timeout ( self , dur)
22+ }
23+ }
24+
25+ #[ cfg( unix) ]
26+ impl TimeoutStream for UnixStream {
27+ fn set_read_timeout ( & self , dur : Option < Duration > ) -> std:: io:: Result < ( ) > {
28+ UnixStream :: set_read_timeout ( self , dur)
29+ }
30+ }
31+
1332/// Start TCP listener for X11 connections
1433pub fn start_tcp_listener (
1534 display : u16 ,
@@ -76,7 +95,7 @@ pub fn start_unix_listener(
7695 Ok ( ( ) )
7796}
7897
79- fn handle_client < S : Read + Write > (
98+ fn handle_client < S : TimeoutStream > (
8099 mut stream : S ,
81100 server : Arc < Mutex < Server > > ,
82101) -> Result < ( ) , Box < dyn Error + Send + Sync > > {
@@ -105,12 +124,56 @@ fn handle_client<S: Read + Write>(
105124 // Note: The first request after connection has sequence 1
106125 let mut sequence_number: u16 = 0 ;
107126
127+ // Set read timeout for event polling
128+ // 10ms allows responsive event delivery while still processing requests quickly
129+ stream. set_read_timeout ( Some ( Duration :: from_millis ( 10 ) ) ) ?;
130+
131+ // Helper function to send pending events to the client
132+ // The sequence_number is the client's current request sequence - events use this
133+ fn send_pending_events < W : Write > (
134+ stream : & mut W ,
135+ server : & Arc < Mutex < Server > > ,
136+ client_sequence : u16 ,
137+ ) -> std:: io:: Result < ( ) > {
138+ // Poll for new events and send any pending events
139+ let events_by_window = {
140+ let mut server = server. lock ( ) . unwrap ( ) ;
141+ server. poll_and_queue_events ( ) ;
142+ server. take_all_pending_events ( )
143+ } ;
144+
145+ // Flatten events from all windows and send them
146+ // Patch the sequence number in each event (bytes 2-3) to match the client's sequence
147+ for ( _window, events) in events_by_window {
148+ for mut event_data in events {
149+ // X11 events are 32 bytes, sequence number is at bytes 2-3 (little-endian)
150+ if event_data. len ( ) >= 4 {
151+ let seq_bytes = client_sequence. to_le_bytes ( ) ;
152+ event_data[ 2 ] = seq_bytes[ 0 ] ;
153+ event_data[ 3 ] = seq_bytes[ 1 ] ;
154+ }
155+ stream. write_all ( & event_data) ?;
156+ }
157+ }
158+ Ok ( ( ) )
159+ }
160+
108161 // Handle requests in a loop
109162 loop {
163+ // First, poll and send any pending events to this client
164+ if let Err ( e) = send_pending_events ( & mut stream, & server, sequence_number) {
165+ log:: warn!( "Client {} event send error: {}" , client_id, e) ;
166+ break ;
167+ }
168+
110169 // Read request header (4 bytes minimum)
111170 let mut header = [ 0u8 ; 4 ] ;
112171 match stream. read_exact ( & mut header) {
113172 Ok ( _) => { }
173+ Err ( e) if e. kind ( ) == ErrorKind :: WouldBlock || e. kind ( ) == ErrorKind :: TimedOut => {
174+ // Timeout - no client request, loop back to check for events
175+ continue ;
176+ }
114177 Err ( _) => {
115178 log:: info!( "Client {} disconnected" , client_id) ;
116179 break ;
@@ -4064,6 +4127,134 @@ fn handle_change_keyboard_mapping<S: Write>(
40644127 Ok ( ( ) )
40654128}
40664129
4130+ /// Map macOS keycode (after +8 offset) to X11 keysym
4131+ /// macOS keycodes are not sequential - this provides the correct mapping
4132+ fn macos_keycode_to_keysym ( keycode : u8 ) -> u32 {
4133+ // macOS keycode + 8 = our keycode, so subtract 8 to get macOS keycode
4134+ let mac_keycode = keycode. saturating_sub ( 8 ) ;
4135+
4136+ // macOS virtual key codes to X11 keysyms
4137+ // Reference: Carbon/HIToolbox/Events.h (kVK_* constants)
4138+ match mac_keycode {
4139+ // Letters (QWERTY layout)
4140+ 0 => 0x61 , // kVK_ANSI_A -> 'a'
4141+ 1 => 0x73 , // kVK_ANSI_S -> 's'
4142+ 2 => 0x64 , // kVK_ANSI_D -> 'd'
4143+ 3 => 0x66 , // kVK_ANSI_F -> 'f'
4144+ 4 => 0x68 , // kVK_ANSI_H -> 'h'
4145+ 5 => 0x67 , // kVK_ANSI_G -> 'g'
4146+ 6 => 0x7a , // kVK_ANSI_Z -> 'z'
4147+ 7 => 0x78 , // kVK_ANSI_X -> 'x'
4148+ 8 => 0x63 , // kVK_ANSI_C -> 'c'
4149+ 9 => 0x76 , // kVK_ANSI_V -> 'v'
4150+ 11 => 0x62 , // kVK_ANSI_B -> 'b'
4151+ 12 => 0x71 , // kVK_ANSI_Q -> 'q'
4152+ 13 => 0x77 , // kVK_ANSI_W -> 'w'
4153+ 14 => 0x65 , // kVK_ANSI_E -> 'e'
4154+ 15 => 0x72 , // kVK_ANSI_R -> 'r'
4155+ 16 => 0x79 , // kVK_ANSI_Y -> 'y'
4156+ 17 => 0x74 , // kVK_ANSI_T -> 't'
4157+ 18 => 0x31 , // kVK_ANSI_1 -> '1'
4158+ 19 => 0x32 , // kVK_ANSI_2 -> '2'
4159+ 20 => 0x33 , // kVK_ANSI_3 -> '3'
4160+ 21 => 0x34 , // kVK_ANSI_4 -> '4'
4161+ 22 => 0x36 , // kVK_ANSI_6 -> '6'
4162+ 23 => 0x35 , // kVK_ANSI_5 -> '5'
4163+ 24 => 0x3d , // kVK_ANSI_Equal -> '='
4164+ 25 => 0x39 , // kVK_ANSI_9 -> '9'
4165+ 26 => 0x37 , // kVK_ANSI_7 -> '7'
4166+ 27 => 0x2d , // kVK_ANSI_Minus -> '-'
4167+ 28 => 0x38 , // kVK_ANSI_8 -> '8'
4168+ 29 => 0x30 , // kVK_ANSI_0 -> '0'
4169+ 30 => 0x5d , // kVK_ANSI_RightBracket -> ']'
4170+ 31 => 0x6f , // kVK_ANSI_O -> 'o'
4171+ 32 => 0x75 , // kVK_ANSI_U -> 'u'
4172+ 33 => 0x5b , // kVK_ANSI_LeftBracket -> '['
4173+ 34 => 0x69 , // kVK_ANSI_I -> 'i'
4174+ 35 => 0x70 , // kVK_ANSI_P -> 'p'
4175+ 37 => 0x6c , // kVK_ANSI_L -> 'l'
4176+ 38 => 0x6a , // kVK_ANSI_J -> 'j'
4177+ 39 => 0x27 , // kVK_ANSI_Quote -> '''
4178+ 40 => 0x6b , // kVK_ANSI_K -> 'k'
4179+ 41 => 0x3b , // kVK_ANSI_Semicolon -> ';'
4180+ 42 => 0x5c , // kVK_ANSI_Backslash -> '\'
4181+ 43 => 0x2c , // kVK_ANSI_Comma -> ','
4182+ 44 => 0x2f , // kVK_ANSI_Slash -> '/'
4183+ 45 => 0x6e , // kVK_ANSI_N -> 'n'
4184+ 46 => 0x6d , // kVK_ANSI_M -> 'm'
4185+ 47 => 0x2e , // kVK_ANSI_Period -> '.'
4186+ 50 => 0x60 , // kVK_ANSI_Grave -> '`'
4187+
4188+ // Special keys
4189+ 36 => 0xff0d , // kVK_Return -> XK_Return
4190+ 48 => 0xff09 , // kVK_Tab -> XK_Tab
4191+ 49 => 0x20 , // kVK_Space -> ' '
4192+ 51 => 0xff08 , // kVK_Delete (backspace) -> XK_BackSpace
4193+ 53 => 0xff1b , // kVK_Escape -> XK_Escape
4194+
4195+ // Arrow keys
4196+ 123 => 0xff51 , // kVK_LeftArrow -> XK_Left
4197+ 124 => 0xff53 , // kVK_RightArrow -> XK_Right
4198+ 125 => 0xff54 , // kVK_DownArrow -> XK_Down
4199+ 126 => 0xff52 , // kVK_UpArrow -> XK_Up
4200+
4201+ // Function keys
4202+ 122 => 0xffbe , // kVK_F1 -> XK_F1
4203+ 120 => 0xffbf , // kVK_F2 -> XK_F2
4204+ 99 => 0xffc0 , // kVK_F3 -> XK_F3
4205+ 118 => 0xffc1 , // kVK_F4 -> XK_F4
4206+ 96 => 0xffc2 , // kVK_F5 -> XK_F5
4207+ 97 => 0xffc3 , // kVK_F6 -> XK_F6
4208+ 98 => 0xffc4 , // kVK_F7 -> XK_F7
4209+ 100 => 0xffc5 , // kVK_F8 -> XK_F8
4210+ 101 => 0xffc6 , // kVK_F9 -> XK_F9
4211+ 109 => 0xffc7 , // kVK_F10 -> XK_F10
4212+ 103 => 0xffc8 , // kVK_F11 -> XK_F11
4213+ 111 => 0xffc9 , // kVK_F12 -> XK_F12
4214+
4215+ // Modifier keys
4216+ 56 => 0xffe1 , // kVK_Shift -> XK_Shift_L
4217+ 60 => 0xffe2 , // kVK_RightShift -> XK_Shift_R
4218+ 58 => 0xffe9 , // kVK_Option -> XK_Alt_L
4219+ 61 => 0xffea , // kVK_RightOption -> XK_Alt_R
4220+ 59 => 0xffe3 , // kVK_Control -> XK_Control_L
4221+ 62 => 0xffe4 , // kVK_RightControl -> XK_Control_R
4222+ 55 => 0xffeb , // kVK_Command -> XK_Super_L
4223+ 54 => 0xffec , // kVK_RightCommand -> XK_Super_R
4224+ 57 => 0xffe5 , // kVK_CapsLock -> XK_Caps_Lock
4225+
4226+ // Keypad
4227+ 65 => 0xffae , // kVK_ANSI_KeypadDecimal -> XK_KP_Decimal
4228+ 67 => 0xffaa , // kVK_ANSI_KeypadMultiply -> XK_KP_Multiply
4229+ 69 => 0xffab , // kVK_ANSI_KeypadPlus -> XK_KP_Add
4230+ 71 => 0xff7f , // kVK_ANSI_KeypadClear -> XK_Num_Lock
4231+ 75 => 0xffaf , // kVK_ANSI_KeypadDivide -> XK_KP_Divide
4232+ 76 => 0xff8d , // kVK_ANSI_KeypadEnter -> XK_KP_Enter
4233+ 78 => 0xffad , // kVK_ANSI_KeypadMinus -> XK_KP_Subtract
4234+ 81 => 0xffbd , // kVK_ANSI_KeypadEquals -> XK_KP_Equal
4235+ 82 => 0xffb0 , // kVK_ANSI_Keypad0 -> XK_KP_0
4236+ 83 => 0xffb1 , // kVK_ANSI_Keypad1 -> XK_KP_1
4237+ 84 => 0xffb2 , // kVK_ANSI_Keypad2 -> XK_KP_2
4238+ 85 => 0xffb3 , // kVK_ANSI_Keypad3 -> XK_KP_3
4239+ 86 => 0xffb4 , // kVK_ANSI_Keypad4 -> XK_KP_4
4240+ 87 => 0xffb5 , // kVK_ANSI_Keypad5 -> XK_KP_5
4241+ 88 => 0xffb6 , // kVK_ANSI_Keypad6 -> XK_KP_6
4242+ 89 => 0xffb7 , // kVK_ANSI_Keypad7 -> XK_KP_7
4243+ 91 => 0xffb8 , // kVK_ANSI_Keypad8 -> XK_KP_8
4244+ 92 => 0xffb9 , // kVK_ANSI_Keypad9 -> XK_KP_9
4245+
4246+ // Navigation keys
4247+ 115 => 0xff50 , // kVK_Home -> XK_Home
4248+ 116 => 0xff55 , // kVK_PageUp -> XK_Page_Up
4249+ 117 => 0xffff , // kVK_ForwardDelete -> XK_Delete
4250+ 119 => 0xff57 , // kVK_End -> XK_End
4251+ 121 => 0xff56 , // kVK_PageDown -> XK_Page_Down
4252+
4253+ // Unknown key
4254+ _ => 0 , // NoSymbol
4255+ }
4256+ }
4257+
40674258fn handle_get_keyboard_mapping < S : Write > (
40684259 stream : & mut S ,
40694260 header : & [ u8 ] ,
@@ -4088,9 +4279,8 @@ fn handle_get_keyboard_mapping<S: Write>(
40884279 // Get the sequence number from header
40894280 let sequence = u16:: from_le_bytes ( [ header[ 2 ] , header[ 3 ] ] ) ;
40904281
4091- // Return a minimal keyboard mapping (1 keysym per keycode)
4092- // For simplicity, just return the keycode as the keysym (ASCII-like mapping)
4093- let keysyms_per_keycode = 1u8 ;
4282+ // Return keyboard mapping with 2 keysyms per keycode (normal + shifted)
4283+ let keysyms_per_keycode = 2u8 ;
40944284 let n_keysyms = ( count as usize ) * ( keysyms_per_keycode as usize ) ;
40954285 let reply_length = n_keysyms; // in 4-byte units (each keysym is 4 bytes)
40964286
@@ -4101,17 +4291,44 @@ fn handle_get_keyboard_mapping<S: Write>(
41014291 reply[ 2 ..4 ] . copy_from_slice ( & sequence. to_le_bytes ( ) ) ;
41024292 reply[ 4 ..8 ] . copy_from_slice ( & ( reply_length as u32 ) . to_le_bytes ( ) ) ;
41034293
4104- // Fill in keysyms - map keycodes to basic keysyms
4294+ // Fill in keysyms using macOS keycode mapping
41054295 for i in 0 ..count as usize {
4106- let keycode = first_keycode as usize + i;
4107- // Simple mapping: keycode -> keysym (for printable ASCII)
4108- let keysym = if ( 0x20 ..0x7f ) . contains ( & keycode) {
4109- keycode as u32
4110- } else {
4111- 0 // NoSymbol
4296+ let keycode = ( first_keycode as usize + i) as u8 ;
4297+ let keysym = macos_keycode_to_keysym ( keycode) ;
4298+
4299+ // Calculate shifted keysym for letters and some symbols
4300+ let shifted_keysym = match keysym {
4301+ // Lowercase letters -> uppercase
4302+ 0x61 ..=0x7a => keysym - 0x20 , // 'a'-'z' -> 'A'-'Z'
4303+ // Number row shifted symbols
4304+ 0x31 => 0x21 , // '1' -> '!'
4305+ 0x32 => 0x40 , // '2' -> '@'
4306+ 0x33 => 0x23 , // '3' -> '#'
4307+ 0x34 => 0x24 , // '4' -> '$'
4308+ 0x35 => 0x25 , // '5' -> '%'
4309+ 0x36 => 0x5e , // '6' -> '^'
4310+ 0x37 => 0x26 , // '7' -> '&'
4311+ 0x38 => 0x2a , // '8' -> '*'
4312+ 0x39 => 0x28 , // '9' -> '('
4313+ 0x30 => 0x29 , // '0' -> ')'
4314+ 0x2d => 0x5f , // '-' -> '_'
4315+ 0x3d => 0x2b , // '=' -> '+'
4316+ 0x5b => 0x7b , // '[' -> '{'
4317+ 0x5d => 0x7d , // ']' -> '}'
4318+ 0x5c => 0x7c , // '\' -> '|'
4319+ 0x3b => 0x3a , // ';' -> ':'
4320+ 0x27 => 0x22 , // ''' -> '"'
4321+ 0x60 => 0x7e , // '`' -> '~'
4322+ 0x2c => 0x3c , // ',' -> '<'
4323+ 0x2e => 0x3e , // '.' -> '>'
4324+ 0x2f => 0x3f , // '/' -> '?'
4325+ // For other keys, shifted is the same
4326+ _ => keysym,
41124327 } ;
4113- let offset = 32 + i * 4 ;
4328+
4329+ let offset = 32 + i * 8 ; // 2 keysyms * 4 bytes each
41144330 reply[ offset..offset + 4 ] . copy_from_slice ( & keysym. to_le_bytes ( ) ) ;
4331+ reply[ offset + 4 ..offset + 8 ] . copy_from_slice ( & shifted_keysym. to_le_bytes ( ) ) ;
41154332 }
41164333
41174334 stream. write_all ( & reply) ?;
0 commit comments