raiguard/odin-wayland
git clone https://git.raiguard.me/raiguard/odin-wayland
fd8ef50
trunk
1#+build linux 2#+vet explicit-allocators 3package wayland 4 5import intr "base:intrinsics" 6import rt "base:runtime" 7import "core:bufio" 8import "core:bytes" 9import "core:fmt" 10import "core:io" 11import "core:log" 12import "core:math/fixed" 13import "core:os" 14import "core:path/filepath" 15import "core:strconv" 16import "core:strings" 17import "core:sys/linux" 18 19DISPLAY :: Display_ID ( 1 ) // wl_display singleton is hardcoded to an ID of 1. 20 21init :: proc ( session : ^ Session , allocator := context . allocator , frame_allocator := context . temp_allocator ) -> ( ok : bool ) { 22// Set up socket boilerplate. 23{ 24socket_data := & session . socket_data 25 26socket_fd , socket_ok := _get_socket ( allocator ) 27if ! socket_ok { 28return false 29} 30socket_data . fd = socket_fd 31 32socket_data . reader_stream = { 33procedure = _unix_socket_read , 34data = session , 35} 36bufio . reader_init ( & socket_data . reader , socket_data . reader_stream , allocator = allocator ) 37 38socket_data . writer_stream = { 39procedure = _unix_socket_write , 40data = session , 41} 42bufio . writer_init ( & socket_data . writer , socket_data . writer_stream , allocator = allocator ) 43 44bufio . read_writer_init ( & socket_data . read_writer , & socket_data . reader , & socket_data . writer ) 45session . socket_stream = bufio . read_writer_to_stream ( & socket_data . read_writer ) 46} 47 48bytes . buffer_init_allocator ( & session . message_read_buffer , 0 , 16 , allocator = allocator ) 49bytes . buffer_init_allocator ( & session . message_write_buffer , 0 , 16 , allocator = allocator ) 50strings . builder_init ( & session . debug_log_builder , allocator = allocator ) 51 52session . objects . allocator = allocator 53session . next_id = 1 54// wl_display is hardcoded to an ID of 1 in Wayland. 55display_id := _allocate_object ( session , . Display ) 56ensure ( display_id == Object_ID ( DISPLAY )) 57 58session . allocator = allocator 59session . frame_allocator = frame_allocator 60 61wayland_debug_env := os . get_env ( "WAYLAND_DEBUG" , allocator ) 62session . debug_logging_enabled = wayland_debug_env == "1" 63delete ( wayland_debug_env , allocator ) 64 65return true 66} 67 68fini :: proc ( session : ^ Session ) { 69delete ( session . objects ) 70bytes . buffer_destroy ( & session . message_read_buffer ) 71bytes . buffer_destroy ( & session . message_write_buffer ) 72strings . builder_destroy ( & session . debug_log_builder ) 73free_all ( session . frame_allocator ) 74} 75 76pump_events :: proc ( session : ^ Session ) -> Error { 77io . flush ( session . socket_stream ) 78// TODO: Handle events until there are no more events to be handled! 79// for _handle_next_event(session) or_return {} 80_handle_next_event ( session ) or_return 81// free_all(session.frame_allocator) 82return nil 83} 84 85_on_event_internal :: proc ( session : ^ Session , object_id : Object_ID , opcode : Opcode , handler_info : Handler_Info ) { 86// TODO: Gracefully handle if we don't have handler_info for a given object. 87ensure ( object_id in session . objects ) 88object_info := & session . objects [ object_id ] 89object_info . handlers [ opcode ] = handler_info 90} 91 92_handle_next_event :: proc ( session : ^ Session ) -> ( ok : bool , error : Error ) { 93// TODO: Non-blocking 94message := _message_read ( session ) or_return 95// log.debug(message) 96 97object_id := message . header . object_id 98object_info , object_info_ok := session . objects [ object_id ] 99if ! object_info_ok { 100log . errorf ( "Received event for unknown object ID '{}'" , message . header . object_id ) 101return true , nil 102} 103 104handler_info , handler_info_ok := object_info . handlers [ message . header . opcode ] 105if ! handler_info_ok { 106log . error ( "Unhandled event:" , message . header ) 107// TODO: We will need to parse the event in order to log it, so we'll need a special code path for that. 108return true , nil 109} 110 111stream := bytes . buffer_to_stream ( & session . message_read_buffer ) 112handler_info . dispatcher ( session , stream , object_id , message . header . opcode , handler_info ) or_return 113 114return true , nil 115}