1 // Copyright 2015-2018, The Gtk-rs Project Developers. 2 // See the COPYRIGHT file at the top-level directory of this distribution. 3 // Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT> 4 5 use gdk_sys; 6 use glib::translate::*; 7 use glib_sys; 8 use libc::c_void; 9 use std::fmt; 10 use std::mem; 11 use std::ptr; 12 13 use AxisUse; 14 use Device; 15 #[cfg(any(feature = "v3_22", feature = "dox"))] 16 use DeviceTool; 17 use EventSequence; 18 use EventType; 19 use ModifierType; 20 use Screen; 21 use ScrollDirection; 22 #[cfg(any(feature = "v3_20", feature = "dox"))] 23 use Seat; 24 use Window; 25 26 glib_wrapper! { 27 /// A generic GDK event. 28 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] 29 pub struct Event(Boxed<gdk_sys::GdkEvent>); 30 31 match fn { 32 copy => |ptr| gdk_sys::gdk_event_copy(ptr), 33 free => |ptr| gdk_sys::gdk_event_free(ptr), 34 get_type => || gdk_sys::gdk_event_get_type(), 35 } 36 } 37 38 impl Event { 39 /// Creates a new event. new(type_: EventType) -> Event40 pub fn new(type_: EventType) -> Event { 41 assert_initialized_main_thread!(); 42 unsafe { from_glib_none(gdk_sys::gdk_event_new(type_.to_glib())) } 43 } 44 get() -> Option<Event>45 pub fn get() -> Option<Event> { 46 assert_initialized_main_thread!(); 47 unsafe { from_glib_none(gdk_sys::gdk_event_get()) } 48 } 49 put(&self)50 pub fn put(&self) { 51 unsafe { gdk_sys::gdk_event_put(self.to_glib_none().0) } 52 } 53 54 /// Set the event handler. 55 /// 56 /// The callback `handler` is called for each event. If `None`, event 57 /// handling is disabled. set_handler<F: Fn(&mut Event) + 'static>(handler: Option<F>)58 pub fn set_handler<F: Fn(&mut Event) + 'static>(handler: Option<F>) { 59 assert_initialized_main_thread!(); 60 unsafe extern "C" fn event_handler_trampoline<F: Fn(&mut Event) + 'static>( 61 event: *mut gdk_sys::GdkEvent, 62 ptr: glib_sys::gpointer, 63 ) { 64 if ptr != ptr::null_mut() { 65 let f: &F = &*(ptr as *mut _); 66 let mut event = from_glib_none(event); 67 f(&mut event) 68 } 69 } 70 unsafe extern "C" fn event_handler_destroy<F: Fn(&mut Event) + 'static>( 71 ptr: glib_sys::gpointer, 72 ) { 73 if ptr != ptr::null_mut() { 74 // convert back to Box and free 75 let _boxed: Box<F> = Box::from_raw(ptr as *mut _); 76 } 77 } 78 if let Some(handler) = handler { 79 // allocate and convert to target type 80 // double box to reduce a fat pointer to a simple pointer 81 let boxed: Box<F> = Box::new(handler); 82 let ptr: *mut c_void = Box::into_raw(boxed) as *mut _; 83 unsafe { 84 gdk_sys::gdk_event_handler_set( 85 Some(event_handler_trampoline::<F>), 86 ptr, 87 Some(event_handler_destroy::<F>), 88 ) 89 } 90 } else { 91 unsafe { gdk_sys::gdk_event_handler_set(None, ptr::null_mut(), None) } 92 } 93 } 94 get_axis(&self, axis_use: AxisUse) -> Option<f64>95 pub fn get_axis(&self, axis_use: AxisUse) -> Option<f64> { 96 let mut value = 0f64; 97 if unsafe { 98 from_glib(gdk_sys::gdk_event_get_axis( 99 self.to_glib_none().0, 100 axis_use.to_glib(), 101 &mut value, 102 )) 103 } { 104 Some(value) 105 } else { 106 None 107 } 108 } 109 get_button(&self) -> Option<u32>110 pub fn get_button(&self) -> Option<u32> { 111 let mut button = 0u32; 112 if unsafe { 113 from_glib(gdk_sys::gdk_event_get_button( 114 self.to_glib_none().0, 115 &mut button, 116 )) 117 } { 118 Some(button) 119 } else { 120 None 121 } 122 } 123 get_click_count(&self) -> Option<u32>124 pub fn get_click_count(&self) -> Option<u32> { 125 let mut click_count = 0u32; 126 if unsafe { 127 from_glib(gdk_sys::gdk_event_get_click_count( 128 self.to_glib_none().0, 129 &mut click_count, 130 )) 131 } { 132 Some(click_count) 133 } else { 134 None 135 } 136 } 137 get_coords(&self) -> Option<(f64, f64)>138 pub fn get_coords(&self) -> Option<(f64, f64)> { 139 let mut x_win = 0f64; 140 let mut y_win = 0f64; 141 if unsafe { 142 from_glib(gdk_sys::gdk_event_get_coords( 143 self.to_glib_none().0, 144 &mut x_win, 145 &mut y_win, 146 )) 147 } { 148 Some((x_win, y_win)) 149 } else { 150 None 151 } 152 } 153 get_keycode(&self) -> Option<u16>154 pub fn get_keycode(&self) -> Option<u16> { 155 let mut keycode = 0u16; 156 if unsafe { 157 from_glib(gdk_sys::gdk_event_get_keycode( 158 self.to_glib_none().0, 159 &mut keycode, 160 )) 161 } { 162 Some(keycode) 163 } else { 164 None 165 } 166 } 167 get_keyval(&self) -> Option<u32>168 pub fn get_keyval(&self) -> Option<u32> { 169 let mut keyval = 0u32; 170 if unsafe { 171 from_glib(gdk_sys::gdk_event_get_keyval( 172 self.to_glib_none().0, 173 &mut keyval, 174 )) 175 } { 176 Some(keyval) 177 } else { 178 None 179 } 180 } 181 get_root_coords(&self) -> Option<(f64, f64)>182 pub fn get_root_coords(&self) -> Option<(f64, f64)> { 183 let mut x_root = 0f64; 184 let mut y_root = 0f64; 185 if unsafe { 186 from_glib(gdk_sys::gdk_event_get_root_coords( 187 self.to_glib_none().0, 188 &mut x_root, 189 &mut y_root, 190 )) 191 } { 192 Some((x_root, y_root)) 193 } else { 194 None 195 } 196 } 197 get_scroll_direction(&self) -> Option<ScrollDirection>198 pub fn get_scroll_direction(&self) -> Option<ScrollDirection> { 199 unsafe { 200 let mut direction = mem::uninitialized(); 201 if from_glib(gdk_sys::gdk_event_get_scroll_direction( 202 self.to_glib_none().0, 203 &mut direction, 204 )) { 205 Some(from_glib(direction)) 206 } else { 207 None 208 } 209 } 210 } 211 get_scroll_deltas(&self) -> Option<(f64, f64)>212 pub fn get_scroll_deltas(&self) -> Option<(f64, f64)> { 213 let mut delta_x = 0f64; 214 let mut delta_y = 0f64; 215 if unsafe { 216 from_glib(gdk_sys::gdk_event_get_scroll_deltas( 217 self.to_glib_none().0, 218 &mut delta_x, 219 &mut delta_y, 220 )) 221 } { 222 Some((delta_x, delta_y)) 223 } else { 224 None 225 } 226 } 227 228 #[cfg(any(feature = "v3_20", feature = "dox"))] is_scroll_stop_event(&self) -> bool229 pub fn is_scroll_stop_event(&self) -> bool { 230 unsafe { 231 from_glib(gdk_sys::gdk_event_is_scroll_stop_event( 232 self.to_glib_none().0, 233 )) 234 } 235 } 236 get_state(&self) -> Option<ModifierType>237 pub fn get_state(&self) -> Option<ModifierType> { 238 unsafe { 239 let mut state = mem::uninitialized(); 240 if from_glib(gdk_sys::gdk_event_get_scroll_direction( 241 self.to_glib_none().0, 242 &mut state, 243 )) { 244 Some(from_glib(state as u32)) 245 } else { 246 None 247 } 248 } 249 } 250 get_time(&self) -> u32251 pub fn get_time(&self) -> u32 { 252 unsafe { gdk_sys::gdk_event_get_time(self.to_glib_none().0) } 253 } 254 255 /// Returns the associated `Window` if applicable. get_window(&self) -> Option<Window>256 pub fn get_window(&self) -> Option<Window> { 257 unsafe { from_glib_none(gdk_sys::gdk_event_get_window(self.to_glib_none().0)) } 258 } 259 get_event_sequence(&self) -> Option<EventSequence>260 pub fn get_event_sequence(&self) -> Option<EventSequence> { 261 unsafe { from_glib_none(gdk_sys::gdk_event_get_event_sequence(self.to_glib_none().0)) } 262 } 263 triggers_context_menu(&self) -> bool264 pub fn triggers_context_menu(&self) -> bool { 265 unsafe { 266 from_glib(gdk_sys::gdk_event_triggers_context_menu( 267 self.to_glib_none().0, 268 )) 269 } 270 } 271 272 #[cfg(any(feature = "v3_20", feature = "dox"))] get_seat(&self) -> Option<Seat>273 pub fn get_seat(&self) -> Option<Seat> { 274 unsafe { from_glib_none(gdk_sys::gdk_event_get_seat(self.to_glib_none().0)) } 275 } 276 277 #[cfg(any(feature = "v3_22", feature = "dox"))] get_scancode(&mut self) -> i32278 pub fn get_scancode(&mut self) -> i32 { 279 unsafe { gdk_sys::gdk_event_get_scancode(self.to_glib_none_mut().0) } 280 } 281 282 #[cfg(any(feature = "v3_22", feature = "dox"))] get_pointer_emulated(&mut self) -> bool283 pub fn get_pointer_emulated(&mut self) -> bool { 284 unsafe { 285 from_glib(gdk_sys::gdk_event_get_pointer_emulated( 286 self.to_glib_none_mut().0, 287 )) 288 } 289 } 290 set_screen(&mut self, screen: Option<&Screen>)291 pub fn set_screen(&mut self, screen: Option<&Screen>) { 292 unsafe { gdk_sys::gdk_event_set_screen(self.to_glib_none_mut().0, screen.to_glib_none().0) } 293 } 294 get_screen(&self) -> Option<Screen>295 pub fn get_screen(&self) -> Option<Screen> { 296 unsafe { from_glib_none(gdk_sys::gdk_event_get_screen(self.to_glib_none().0)) } 297 } 298 set_device(&mut self, device: Option<&Device>)299 pub fn set_device(&mut self, device: Option<&Device>) { 300 unsafe { gdk_sys::gdk_event_set_device(self.to_glib_none_mut().0, device.to_glib_none().0) } 301 } 302 get_device(&self) -> Option<Device>303 pub fn get_device(&self) -> Option<Device> { 304 unsafe { from_glib_none(gdk_sys::gdk_event_get_device(self.to_glib_none().0)) } 305 } 306 set_source_device(&mut self, device: Option<&Device>)307 pub fn set_source_device(&mut self, device: Option<&Device>) { 308 unsafe { 309 gdk_sys::gdk_event_set_source_device(self.to_glib_none_mut().0, device.to_glib_none().0) 310 } 311 } 312 get_source_device(&self) -> Option<Device>313 pub fn get_source_device(&self) -> Option<Device> { 314 unsafe { from_glib_none(gdk_sys::gdk_event_get_source_device(self.to_glib_none().0)) } 315 } 316 317 #[cfg(any(feature = "v3_22", feature = "dox"))] set_device_tool(&mut self, device: Option<&DeviceTool>)318 pub fn set_device_tool(&mut self, device: Option<&DeviceTool>) { 319 unsafe { 320 gdk_sys::gdk_event_set_device_tool(self.to_glib_none_mut().0, device.to_glib_none().0) 321 } 322 } 323 324 #[cfg(any(feature = "v3_22", feature = "dox"))] get_device_tool(&self) -> Option<DeviceTool>325 pub fn get_device_tool(&self) -> Option<DeviceTool> { 326 unsafe { from_glib_none(gdk_sys::gdk_event_get_device_tool(self.to_glib_none().0)) } 327 } 328 329 /// Returns the event type. get_event_type(&self) -> EventType330 pub fn get_event_type(&self) -> EventType { 331 from_glib(self.as_ref().type_) 332 } 333 334 /// Returns whether the event was sent explicitly. 335 #[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] get_send_event(&self) -> bool336 pub fn get_send_event(&self) -> bool { 337 from_glib(self.as_ref().send_event as i32) 338 } 339 340 /// Returns `true` if the event type matches `T`. is<T: FromEvent>(&self) -> bool341 pub fn is<T: FromEvent>(&self) -> bool { 342 T::is(self) 343 } 344 345 /// Tries to downcast to a specific event type. downcast<T: FromEvent>(self) -> Result<T, Self>346 pub fn downcast<T: FromEvent>(self) -> Result<T, Self> { 347 T::from(self) 348 } 349 350 /// Tries to downcast to a specific event type. downcast_ref<T: FromEvent>(&self) -> Option<&T>351 pub fn downcast_ref<T: FromEvent>(&self) -> Option<&T> { 352 if T::is(self) { 353 unsafe { Some(mem::transmute::<&Event, &T>(self)) } 354 } else { 355 None 356 } 357 } 358 359 /// Tries to downcast to a specific event type. downcast_mut<T: FromEvent>(&mut self) -> Option<&mut T>360 pub fn downcast_mut<T: FromEvent>(&mut self) -> Option<&mut T> { 361 if T::is(self) { 362 unsafe { Some(mem::transmute::<&mut Event, &mut T>(self)) } 363 } else { 364 None 365 } 366 } 367 } 368 369 impl fmt::Debug for Event { fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>370 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 371 fmt.debug_struct("Event") 372 .field("inner", &self.0) 373 .field("type", &self.get_event_type()) 374 .finish() 375 } 376 } 377 378 /// A helper trait implemented by all event subtypes. 379 pub trait FromEvent: Sized { is(ev: &Event) -> bool380 fn is(ev: &Event) -> bool; from(ev: Event) -> Result<Self, Event>381 fn from(ev: Event) -> Result<Self, Event>; 382 } 383 384 macro_rules! event_wrapper { 385 ($name:ident, $ffi_name:ident) => { 386 impl<'a> ToGlibPtr<'a, *const ::gdk_sys::$ffi_name> for $name { 387 type Storage = &'a Self; 388 389 #[inline] 390 fn to_glib_none(&'a self) -> Stash<'a, *const ::gdk_sys::$ffi_name, Self> { 391 let ptr = ToGlibPtr::<*const ::gdk_sys::GdkEvent>::to_glib_none(&self.0).0; 392 Stash(ptr as *const ::gdk_sys::$ffi_name, self) 393 } 394 } 395 396 impl<'a> ToGlibPtrMut<'a, *mut ::gdk_sys::$ffi_name> for $name { 397 type Storage = &'a mut Self; 398 399 #[inline] 400 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ::gdk_sys::$ffi_name, Self> { 401 let ptr = ToGlibPtrMut::<*mut ::gdk_sys::GdkEvent>::to_glib_none_mut(&mut self.0).0; 402 StashMut(ptr as *mut ::gdk_sys::$ffi_name, self) 403 } 404 } 405 406 impl FromGlibPtrNone<*mut ::gdk_sys::$ffi_name> for $name { 407 #[inline] 408 unsafe fn from_glib_none(ptr: *mut ::gdk_sys::$ffi_name) -> Self { 409 $name(from_glib_none(ptr as *mut ::gdk_sys::GdkEvent)) 410 } 411 } 412 413 impl FromGlibPtrBorrow<*mut ::gdk_sys::$ffi_name> for $name { 414 #[inline] 415 unsafe fn from_glib_borrow(ptr: *mut ::gdk_sys::$ffi_name) -> Self { 416 $name(from_glib_borrow(ptr as *mut ::gdk_sys::GdkEvent)) 417 } 418 } 419 420 impl FromGlibPtrFull<*mut ::gdk_sys::$ffi_name> for $name { 421 #[inline] 422 unsafe fn from_glib_full(ptr: *mut ::gdk_sys::$ffi_name) -> Self { 423 $name(from_glib_full(ptr as *mut ::gdk_sys::GdkEvent)) 424 } 425 } 426 427 impl AsRef<::gdk_sys::$ffi_name> for $name { 428 #[inline] 429 fn as_ref(&self) -> &::gdk_sys::$ffi_name { 430 unsafe { 431 let ptr: *const ::gdk_sys::$ffi_name = self.to_glib_none().0; 432 &*ptr 433 } 434 } 435 } 436 437 impl AsMut<::gdk_sys::$ffi_name> for $name { 438 #[inline] 439 fn as_mut(&mut self) -> &mut ::gdk_sys::$ffi_name { 440 unsafe { 441 let ptr: *mut ::gdk_sys::$ffi_name = self.to_glib_none_mut().0; 442 &mut *ptr 443 } 444 } 445 } 446 }; 447 } 448 449 event_wrapper!(Event, GdkEventAny); 450 451 macro_rules! event_subtype { 452 ($name:ident, $($ty:path)|+) => { 453 impl ::event::FromEvent for $name { 454 #[inline] 455 fn is(ev: &::event::Event) -> bool { 456 skip_assert_initialized!(); 457 match ev.as_ref().type_ { 458 $($ty)|+ => true, 459 _ => false, 460 } 461 } 462 463 #[inline] 464 fn from(ev: ::event::Event) -> Result<Self, ::event::Event> { 465 skip_assert_initialized!(); 466 if Self::is(&ev) { 467 Ok($name(ev)) 468 } 469 else { 470 Err(ev) 471 } 472 } 473 } 474 475 impl ::std::ops::Deref for $name { 476 type Target = ::event::Event; 477 478 fn deref(&self) -> &::event::Event { 479 &self.0 480 } 481 } 482 483 impl ::std::ops::DerefMut for $name { 484 fn deref_mut(&mut self) -> &mut ::event::Event { 485 &mut self.0 486 } 487 } 488 } 489 } 490