Merge pull request #227 from aepsil0n/grab-cursor

Implement grabbing of the mouse pointer for X11
This commit is contained in:
tomaka 2015-03-26 16:48:40 +01:00
commit d6ebaaaf5c
6 changed files with 120 additions and 0 deletions

50
examples/grabbing.rs Normal file
View file

@ -0,0 +1,50 @@
#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;
extern crate glutin;
use glutin::{Event, ElementState};
mod support;
#[cfg(target_os = "android")]
android_start!(main);
#[cfg(not(feature = "window"))]
fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
#[cfg(feature = "window")]
fn main() {
let window = glutin::Window::new().unwrap();
window.set_title("glutin - Cursor grabbing test");
unsafe { window.make_current() };
let context = support::load(&window);
let mut grabbed = false;
while !window.is_closed() {
context.draw_frame((0.0, 1.0, 0.0, 1.0));
window.swap_buffers();
for event in window.poll_events() {
match event {
Event::KeyboardInput(ElementState::Pressed, _, _) => {
if grabbed {
grabbed = false;
window.ungrab_cursor();
}
else {
grabbed = true;
window.grab_cursor().ok().expect("could not grab mouse cursor");
}
},
_ => (),
}
}
}
}

View file

@ -358,6 +358,10 @@ impl Window {
pub fn set_cursor(&self, _: MouseCursor) {
}
pub fn grab_cursor(&self) -> Result<(), String> { Ok(()) }
pub fn ungrab_cursor(&self) {}
pub fn hidpi_factor(&self) -> f32 {
1.0
}

View file

@ -255,6 +255,14 @@ impl Window {
unimplemented!()
}
pub fn grab_cursor(&self) -> Result<(), String> {
unimplemented!()
}
pub fn ungrab_cursor(&self) {
unimplemented!()
}
pub fn hidpi_factor(&self) -> f32 {
1.0
}

View file

@ -414,6 +414,22 @@ impl Window {
pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
self.window.set_cursor_position(x, y)
}
/// Grabs the mouse cursor. The cursor's motion will be confined to this
/// window and the window has exclusive access to further events regarding
/// the cursor.
/// Fails if it is not possible to grab the window for some reason, e.g.
/// when another window has already done so.
/// Has no effect on Android.
pub fn grab_cursor(&self) -> Result<(), String> {
self.window.grab_cursor()
}
/// Release a previously grabbed mouse cursor.
pub fn ungrab_cursor(&self) {
self.window.ungrab_cursor();
}
}
impl gl_common::GlFunctionsSource for Window {

View file

@ -42,6 +42,17 @@ pub const Button5: libc::c_uint = 5;
pub const InputOutput: libc::c_uint = 1;
pub const InputOnly: libc::c_uint = 2;
pub const CurrentTime: Time = 0;
pub const GrabModeSync: libc::c_int = 0;
pub const GrabModeAsync: libc::c_int = 1;
pub const GrabSuccess: libc::c_int = 0;
pub const AlreadyGrabbed: libc::c_int = 1;
pub const GrabInvalidTime: libc::c_int = 2;
pub const GrabNotViewable: libc::c_int = 3;
pub const GrabFrozen: libc::c_int = 4;
pub const CWBackPixmap: libc::c_ulong = (1<<0);
pub const CWBackPixel: libc::c_ulong = (1<<1);
pub const CWBorderPixmap: libc::c_ulong = (1<<2);
@ -1470,6 +1481,10 @@ extern "C" {
pub fn XcursorLibraryLoadCursor(dpy: *mut Display, name: *const libc::c_char) -> Cursor;
pub fn XDefineCursor(dby: *mut Display, w: Window, cursor: Cursor);
pub fn XGrabPointer(dpy: *mut Display, w: Window, owner_events: bool, event_mask: libc::c_long,
pointer_mode: libc::c_int, keyboard_mode: libc::c_int, confine_to: Window, cursor: Cursor,
time: Time) -> libc::c_int;
pub fn XUngrabPointer(dpy: *mut Display, time: Time);
}
/*

View file

@ -782,6 +782,33 @@ impl Window {
}
}
pub fn grab_cursor(&self) -> Result<(), String> {
unsafe {
match ffi::XGrabPointer(
self.x.display, self.x.window, false,
ffi::ButtonPressMask | ffi::ButtonReleaseMask | ffi::EnterWindowMask |
ffi::LeaveWindowMask | ffi::PointerMotionMask | ffi::PointerMotionHintMask |
ffi::Button1MotionMask | ffi::Button2MotionMask | ffi::Button3MotionMask |
ffi::Button4MotionMask | ffi::Button5MotionMask | ffi::ButtonMotionMask |
ffi::KeymapStateMask,
ffi::GrabModeAsync, ffi::GrabModeAsync,
self.x.window, 0, ffi::CurrentTime
) {
ffi::GrabSuccess => Ok(()),
ffi::AlreadyGrabbed | ffi::GrabInvalidTime |
ffi::GrabNotViewable | ffi::GrabFrozen
=> Err("cursor could not be grabbed".to_string()),
_ => unreachable!(),
}
}
}
pub fn ungrab_cursor(&self) {
unsafe {
ffi::XUngrabPointer(self.x.display, ffi::CurrentTime);
}
}
pub fn hidpi_factor(&self) -> f32 {
1.0
}