1616
1717use std:: cell:: RefCell ;
1818use std:: collections:: HashMap ;
19- use std:: sync:: Arc ;
20-
21- use lazy_static:: lazy_static;
19+ use std:: rc:: Rc ;
2220
2321use crate :: application:: AppHandler ;
24- use crate :: kurbo:: { Point , Rect } ;
25- use crate :: { KeyCode , KeyModifiers , MouseButton , MouseButtons , MouseEvent } ;
2622
2723use super :: clipboard:: Clipboard ;
2824use super :: error:: Error ;
29- use super :: window:: XWindow ;
30-
31- struct XcbConnection {
32- connection : Arc < xcb:: Connection > ,
33- screen_num : i32 ,
34- }
25+ use super :: window:: Window ;
3526
36- lazy_static ! {
37- static ref XCB_CONNECTION : XcbConnection = XcbConnection :: new( ) ;
27+ #[ derive( Clone ) ]
28+ pub ( crate ) struct Application {
29+ connection : Rc < xcb:: Connection > ,
30+ screen_num : i32 , // Needs a container when no longer const
31+ state : Rc < RefCell < State > > ,
3832}
3933
40- thread_local ! {
41- static WINDOW_MAP : RefCell < HashMap <u32 , XWindow >> = RefCell :: new ( HashMap :: new ( ) ) ;
34+ struct State {
35+ windows : HashMap < u32 , Rc < Window > > ,
4236}
4337
44- #[ derive( Clone ) ]
45- pub ( crate ) struct Application ;
46-
4738impl Application {
4839 pub fn new ( ) -> Result < Application , Error > {
49- Ok ( Application )
40+ let ( conn, screen_num) = match xcb:: Connection :: connect_with_xlib_display ( ) {
41+ Ok ( conn) => conn,
42+ Err ( err) => return Err ( Error :: ConnectionError ( err. to_string ( ) ) ) ,
43+ } ;
44+ let state = Rc :: new ( RefCell :: new ( State {
45+ windows : HashMap :: new ( ) ,
46+ } ) ) ;
47+ Ok ( Application {
48+ connection : Rc :: new ( conn) ,
49+ screen_num,
50+ state,
51+ } )
5052 }
5153
52- pub ( crate ) fn add_xwindow ( id : u32 , xwindow : XWindow ) {
53- WINDOW_MAP . with ( |map| map. borrow_mut ( ) . insert ( id, xwindow) ) ;
54+ pub ( crate ) fn add_window ( & self , id : u32 , window : Rc < Window > ) {
55+ if let Ok ( mut state) = self . state . try_borrow_mut ( ) {
56+ state. windows . insert ( id, window) ;
57+ } else {
58+ log:: warn!( "Application::add_window - state already borrowed" ) ;
59+ }
5460 }
5561
56- pub ( crate ) fn get_connection ( ) -> Arc < xcb:: Connection > {
57- XCB_CONNECTION . connection_cloned ( )
62+ fn remove_window ( & self , id : u32 ) {
63+ if let Ok ( mut state) = self . state . try_borrow_mut ( ) {
64+ state. windows . remove ( & id) ;
65+ } else {
66+ log:: warn!( "Application::remove_window - state already borrowed" ) ;
67+ }
68+ }
69+
70+ fn window ( & self , id : u32 ) -> Option < Rc < Window > > {
71+ if let Ok ( state) = self . state . try_borrow ( ) {
72+ state. windows . get ( & id) . cloned ( )
73+ } else {
74+ log:: warn!( "Application::window - state already borrowed" ) ;
75+ None
76+ }
5877 }
5978
60- pub ( crate ) fn get_screen_num ( ) -> i32 {
61- XCB_CONNECTION . screen_num ( )
79+ #[ inline]
80+ pub ( crate ) fn connection ( & self ) -> & Rc < xcb:: Connection > {
81+ & self . connection
82+ }
83+
84+ #[ inline]
85+ pub ( crate ) fn screen_num ( & self ) -> i32 {
86+ self . screen_num
6287 }
6388
6489 // TODO(x11/events): handle mouse scroll events
6590 pub fn run ( self , _handler : Option < Box < dyn AppHandler > > ) {
66- let conn = XCB_CONNECTION . connection_cloned ( ) ;
6791 loop {
68- if let Some ( ev) = conn . wait_for_event ( ) {
92+ if let Some ( ev) = self . connection . wait_for_event ( ) {
6993 let ev_type = ev. response_type ( ) & !0x80 ;
70- // NOTE: I don't think we should be doing this here, but I'm trying to keep
71- // the code mostly unchanged. My personal feeling is that the best approach
72- // is to dispatch events to the window as early as possible, that is to say
73- // I would send the *raw* events to the window and then let the window figure
74- // out how to handle them. - @cmyr
75- //
76- // Can't get which window to send the raw event to without first parsing the event
77- // and getting the window ID out of it :) - @crsaracco
7894 match ev_type {
7995 xcb:: EXPOSE => {
8096 let expose: & xcb:: ExposeEvent = unsafe { xcb:: cast_event ( & ev) } ;
8197 let window_id = expose. window ( ) ;
82- // TODO(x11/dpi_scaling): when dpi scaling is
83- // implemented, it needs to be used here too
84- let rect = Rect :: from_origin_size (
85- ( expose. x ( ) as f64 , expose. y ( ) as f64 ) ,
86- ( expose. width ( ) as f64 , expose. height ( ) as f64 ) ,
87- ) ;
88- WINDOW_MAP . with ( |map| {
89- let mut windows = map. borrow_mut ( ) ;
90- if let Some ( w) = windows. get_mut ( & window_id) {
91- w. render ( rect) ;
92- }
93- } )
98+ if let Some ( w) = self . window ( window_id) {
99+ w. handle_expose ( expose) ;
100+ } else {
101+ log:: warn!( "EXPOSE - failed to get window" ) ;
102+ }
94103 }
95104 xcb:: KEY_PRESS => {
96105 let key_press: & xcb:: KeyPressEvent = unsafe { xcb:: cast_event ( & ev) } ;
97- let key: u32 = key_press. detail ( ) as u32 ;
98- let key_code: KeyCode = key. into ( ) ;
99-
100106 let window_id = key_press. event ( ) ;
101- println ! ( "window_id {}" , window_id) ;
102- WINDOW_MAP . with ( |map| {
103- let mut windows = map. borrow_mut ( ) ;
104- if let Some ( w) = windows. get_mut ( & window_id) {
105- w. key_down ( key_code) ;
106- }
107- } )
107+ if let Some ( w) = self . window ( window_id) {
108+ w. handle_key_press ( key_press) ;
109+ } else {
110+ log:: warn!( "KEY_PRESS - failed to get window" ) ;
111+ }
108112 }
109113 xcb:: BUTTON_PRESS => {
110114 let button_press: & xcb:: ButtonPressEvent = unsafe { xcb:: cast_event ( & ev) } ;
111115 let window_id = button_press. event ( ) ;
112- let mouse_event = MouseEvent {
113- pos : Point :: new (
114- button_press. event_x ( ) as f64 ,
115- button_press. event_y ( ) as f64 ,
116- ) ,
117- // TODO: Fill with held down buttons
118- buttons : MouseButtons :: new ( ) . with ( MouseButton :: Left ) ,
119- mods : KeyModifiers {
120- shift : false ,
121- alt : false ,
122- ctrl : false ,
123- meta : false ,
124- } ,
125- count : 0 ,
126- button : MouseButton :: Left ,
127- } ;
128- WINDOW_MAP . with ( |map| {
129- let mut windows = map. borrow_mut ( ) ;
130- if let Some ( w) = windows. get_mut ( & window_id) {
131- w. mouse_down ( & mouse_event) ;
132- }
133- } )
116+ if let Some ( w) = self . window ( window_id) {
117+ w. handle_button_press ( button_press) ;
118+ } else {
119+ log:: warn!( "BUTTON_PRESS - failed to get window" ) ;
120+ }
134121 }
135122 xcb:: BUTTON_RELEASE => {
136123 let button_release: & xcb:: ButtonReleaseEvent =
137124 unsafe { xcb:: cast_event ( & ev) } ;
138125 let window_id = button_release. event ( ) ;
139- let mouse_event = MouseEvent {
140- pos : Point :: new (
141- button_release. event_x ( ) as f64 ,
142- button_release. event_y ( ) as f64 ,
143- ) ,
144- // TODO: Fill with held down buttons
145- buttons : MouseButtons :: new ( ) ,
146- mods : KeyModifiers {
147- shift : false ,
148- alt : false ,
149- ctrl : false ,
150- meta : false ,
151- } ,
152- count : 0 ,
153- button : MouseButton :: Left ,
154- } ;
155- WINDOW_MAP . with ( |map| {
156- let mut windows = map. borrow_mut ( ) ;
157- if let Some ( w) = windows. get_mut ( & window_id) {
158- w. mouse_up ( & mouse_event) ;
159- }
160- } )
126+ if let Some ( w) = self . window ( window_id) {
127+ w. handle_button_release ( button_release) ;
128+ } else {
129+ log:: warn!( "BUTTON_RELEASE - failed to get window" ) ;
130+ }
161131 }
162132 xcb:: MOTION_NOTIFY => {
163- let mouse_move: & xcb:: MotionNotifyEvent = unsafe { xcb:: cast_event ( & ev) } ;
164- let window_id = mouse_move. event ( ) ;
165- let mouse_event = MouseEvent {
166- pos : Point :: new (
167- mouse_move. event_x ( ) as f64 ,
168- mouse_move. event_y ( ) as f64 ,
169- ) ,
170- // TODO: Fill with held down buttons
171- buttons : MouseButtons :: new ( ) ,
172- mods : KeyModifiers {
173- shift : false ,
174- alt : false ,
175- ctrl : false ,
176- meta : false ,
177- } ,
178- count : 0 ,
179- button : MouseButton :: None ,
180- } ;
181- WINDOW_MAP . with ( |map| {
182- let mut windows = map. borrow_mut ( ) ;
183- if let Some ( w) = windows. get_mut ( & window_id) {
184- w. mouse_move ( & mouse_event) ;
185- }
186- } )
133+ let motion_notify: & xcb:: MotionNotifyEvent =
134+ unsafe { xcb:: cast_event ( & ev) } ;
135+ let window_id = motion_notify. event ( ) ;
136+ if let Some ( w) = self . window ( window_id) {
137+ w. handle_motion_notify ( motion_notify) ;
138+ } else {
139+ log:: warn!( "MOTION_NOTIFY - failed to get window" ) ;
140+ }
141+ }
142+ xcb:: DESTROY_NOTIFY => {
143+ let destroy_notify: & xcb:: DestroyNotifyEvent =
144+ unsafe { xcb:: cast_event ( & ev) } ;
145+ let window_id = destroy_notify. window ( ) ;
146+ if let Some ( w) = self . window ( window_id) {
147+ w. handle_destroy_notify ( destroy_notify) ;
148+ } else {
149+ log:: warn!( "DESTROY_NOTIFY - failed to get window" ) ;
150+ }
151+ self . remove_window ( window_id) ;
187152 }
188153 _ => { }
189154 }
@@ -192,7 +157,7 @@ impl Application {
192157 }
193158
194159 pub fn quit ( & self ) {
195- // No-op.
160+ // TODO(x11/quit): implement Application::quit
196161 }
197162
198163 pub fn clipboard ( & self ) -> Clipboard {
@@ -207,22 +172,3 @@ impl Application {
207172 "en-US" . into ( )
208173 }
209174}
210-
211- impl XcbConnection {
212- fn new ( ) -> Self {
213- let ( conn, screen_num) = xcb:: Connection :: connect_with_xlib_display ( ) . unwrap ( ) ;
214-
215- Self {
216- connection : Arc :: new ( conn) ,
217- screen_num,
218- }
219- }
220-
221- fn connection_cloned ( & self ) -> Arc < xcb:: Connection > {
222- self . connection . clone ( )
223- }
224-
225- fn screen_num ( & self ) -> i32 {
226- self . screen_num
227- }
228- }
0 commit comments