1 extern crate x11rb; 2 3 use x11rb::connection::Connection; 4 use x11rb::cursor::Handle as CursorHandle; 5 use x11rb::protocol::xproto::*; 6 use x11rb::protocol::Event; 7 use x11rb::resource_manager::Database; 8 use x11rb::wrapper::ConnectionExt as _; 9 10 fn main() { 11 let (conn, screen_num) = x11rb::connect(None).unwrap(); 12 13 // The following is only needed for start_timeout_thread(), which is used for 'tests' 14 let conn1 = std::sync::Arc::new(conn); 15 let conn = &*conn1; 16 17 let screen = &conn.setup().roots[screen_num]; 18 let win_id = conn.generate_id().unwrap(); 19 let gc_id = conn.generate_id().unwrap(); 20 let resource_db = Database::new_from_default(conn).unwrap(); 21 let cursor_handle = CursorHandle::new(conn, screen_num, &resource_db).unwrap(); 22 23 let wm_protocols = conn.intern_atom(false, b"WM_PROTOCOLS").unwrap(); 24 let wm_delete_window = conn.intern_atom(false, b"WM_DELETE_WINDOW").unwrap(); 25 let net_wm_name = conn.intern_atom(false, b"_NET_WM_NAME").unwrap(); 26 let utf8_string = conn.intern_atom(false, b"UTF8_STRING").unwrap(); 27 let wm_protocols = wm_protocols.reply().unwrap().atom; 28 let wm_delete_window = wm_delete_window.reply().unwrap().atom; 29 let net_wm_name = net_wm_name.reply().unwrap().atom; 30 let utf8_string = utf8_string.reply().unwrap().atom; 31 let cursor_handle = cursor_handle.reply().unwrap(); 32 33 let win_aux = CreateWindowAux::new() 34 .event_mask(EventMask::EXPOSURE | EventMask::STRUCTURE_NOTIFY | EventMask::NO_EVENT) 35 .background_pixel(screen.white_pixel) 36 .win_gravity(Gravity::NORTH_WEST) 37 // Just because, we set the cursor to "wait" 38 .cursor(cursor_handle.load_cursor(conn, "wait").unwrap()); 39 40 let gc_aux = CreateGCAux::new().foreground(screen.black_pixel); 41 42 let (mut width, mut height) = (100, 100); 43 44 conn.create_window( 45 screen.root_depth, 46 win_id, 47 screen.root, 48 0, 49 0, 50 width, 51 height, 52 0, 53 WindowClass::INPUT_OUTPUT, 54 0, 55 &win_aux, 56 ) 57 .unwrap(); 58 59 util::start_timeout_thread(conn1.clone(), win_id); 60 61 let title = "Simple Window"; 62 conn.change_property8( 63 PropMode::REPLACE, 64 win_id, 65 AtomEnum::WM_NAME, 66 AtomEnum::STRING, 67 title.as_bytes(), 68 ) 69 .unwrap(); 70 conn.change_property8( 71 PropMode::REPLACE, 72 win_id, 73 net_wm_name, 74 utf8_string, 75 title.as_bytes(), 76 ) 77 .unwrap(); 78 conn.change_property32( 79 PropMode::REPLACE, 80 win_id, 81 wm_protocols, 82 AtomEnum::ATOM, 83 &[wm_delete_window], 84 ) 85 .unwrap(); 86 conn.change_property8( 87 PropMode::REPLACE, 88 win_id, 89 AtomEnum::WM_CLASS, 90 AtomEnum::STRING, 91 b"simple_window\0simple_window\0", 92 ) main(int argc,char * argv[])93 .unwrap(); 94 conn.change_property8( 95 PropMode::REPLACE, 96 win_id, 97 AtomEnum::WM_CLIENT_MACHINE, 98 AtomEnum::STRING, 99 // Text encoding in X11 is complicated. Let's use UTF-8 and hope for the best. 100 gethostname::gethostname() 101 .to_str() 102 .unwrap_or("[Invalid]") 103 .as_bytes(), 104 ) 105 .unwrap(); 106 107 let reply = conn 108 .get_property(false, win_id, AtomEnum::WM_NAME, AtomEnum::STRING, 0, 1024) 109 .unwrap(); 110 let reply = reply.reply().unwrap(); 111 assert_eq!(reply.value, title.as_bytes()); 112 113 conn.create_gc(gc_id, win_id, &gc_aux).unwrap(); 114 115 conn.map_window(win_id).unwrap(); 116 117 conn.flush().unwrap(); 118 119 loop { 120 let event = conn.wait_for_event().unwrap(); 121 println!("{:?})", event); 122 match event { 123 Event::Expose(event) => { 124 if event.count == 0 { 125 // There already is a white background because we set background_pixel to white 126 // when creating the window. 127 let (width, height): (i16, i16) = (width as _, height as _); 128 let points = [ 129 Point { 130 x: width, 131 y: height, 132 }, 133 Point { x: -10, y: -10 }, 134 Point { 135 x: -10, 136 y: height + 10, 137 }, 138 Point { 139 x: width + 10, 140 y: -10, 141 }, 142 ]; 143 conn.poly_line(CoordMode::ORIGIN, win_id, gc_id, &points) 144 .unwrap(); 145 conn.flush().unwrap(); 146 } 147 } 148 Event::ConfigureNotify(event) => { 149 width = event.width; 150 height = event.height; 151 } 152 Event::ClientMessage(event) => { 153 let data = event.data.as_data32(); 154 if event.format == 32 && event.window == win_id && data[0] == wm_delete_window { 155 println!("Window was asked to close"); 156 return; 157 } 158 } 159 Event::Error(_) => println!("Got an unexpected error"), 160 _ => println!("Got an unknown event"), 161 } 162 } 163 } 164 165 include!("integration_test_util/util.rs"); 166