aboutsummaryrefslogtreecommitdiffstats
path: root/src/win32
diff options
context:
space:
mode:
authortomaka <pierre.krieger1708@gmail.com>2015-03-30 13:32:28 +0200
committertomaka <pierre.krieger1708@gmail.com>2015-03-30 13:32:28 +0200
commita1b504d16c6734dd064aff84059f45c803d97eb3 (patch)
treeaa3d6c4ea6d9903a7e7953b808401f1d8cd8c5d8 /src/win32
parentc3470abc8e818c3ba1247df243055f5d1f854f2c (diff)
parent2089e9c476691b8d81b9bbe8eb83f4c878614774 (diff)
downloadglutin-a1b504d16c6734dd064aff84059f45c803d97eb3.tar.gz
glutin-a1b504d16c6734dd064aff84059f45c803d97eb3.zip
Merge pull request #328 from tomaka/grab
Cursor grabbing
Diffstat (limited to 'src/win32')
-rw-r--r--src/win32/callback.rs21
-rw-r--r--src/win32/init.rs5
-rw-r--r--src/win32/mod.rs70
3 files changed, 92 insertions, 4 deletions
diff --git a/src/win32/callback.rs b/src/win32/callback.rs
index bbf5b55..1cfb640 100644
--- a/src/win32/callback.rs
+++ b/src/win32/callback.rs
@@ -1,3 +1,4 @@
+use std::mem;
use std::rc::Rc;
use std::cell::RefCell;
use std::sync::mpsc::Sender;
@@ -176,6 +177,26 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
0
},
+ winapi::WM_INPUT => {
+ let mut data: winapi::RAWINPUT = mem::uninitialized();
+ let mut data_size = mem::size_of::<winapi::RAWINPUT>() as winapi::UINT;
+ user32::GetRawInputData(mem::transmute(lparam), winapi::RID_INPUT,
+ mem::transmute(&mut data), &mut data_size,
+ mem::size_of::<winapi::RAWINPUTHEADER>() as winapi::UINT);
+
+ if data.header.dwType == winapi::RIM_TYPEMOUSE {
+ let _x = data.mouse.lLastX; // FIXME: this is not always the relative movement
+ let _y = data.mouse.lLastY;
+ // TODO:
+ //send_event(window, Event::MouseRawMovement { x: x, y: y });
+
+ 0
+
+ } else {
+ user32::DefWindowProcW(window, msg, wparam, lparam)
+ }
+ },
+
winapi::WM_SETFOCUS => {
use events::Event::Focused;
send_event(window, Focused(true));
diff --git a/src/win32/init.rs b/src/win32/init.rs
index 08d54c0..c5e18cc 100644
--- a/src/win32/init.rs
+++ b/src/win32/init.rs
@@ -15,11 +15,13 @@ use Api;
use BuilderAttribs;
use CreationError;
use CreationError::OsError;
+use CursorState;
use GlRequest;
use PixelFormat;
use std::ffi::CString;
use std::sync::mpsc::channel;
+use std::sync::Mutex;
use libc;
use super::gl;
@@ -250,6 +252,7 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
gl_library: gl_library,
events_receiver: events_receiver,
is_closed: AtomicBool::new(false),
+ cursor_state: Mutex::new(CursorState::Normal),
})
}
@@ -265,7 +268,7 @@ unsafe fn register_window_class() -> Vec<u16> {
cbWndExtra: 0,
hInstance: kernel32::GetModuleHandleW(ptr::null()),
hIcon: ptr::null_mut(),
- hCursor: ptr::null_mut(),
+ hCursor: ptr::null_mut(), // must be null in order for cursor state to work properly
hbrBackground: ptr::null_mut(),
lpszMenuName: ptr::null(),
lpszClassName: class_name.as_ptr(),
diff --git a/src/win32/mod.rs b/src/win32/mod.rs
index 41004b3..e20d8b7 100644
--- a/src/win32/mod.rs
+++ b/src/win32/mod.rs
@@ -1,6 +1,8 @@
use std::sync::atomic::AtomicBool;
+use std::mem;
use std::ptr;
use std::ffi::CString;
+use std::sync::Mutex;
use std::sync::mpsc::Receiver;
use libc;
use {CreationError, Event, MouseCursor};
@@ -43,6 +45,9 @@ pub struct Window {
/// True if a `Closed` event has been received.
is_closed: AtomicBool,
+
+ /// The current cursor state.
+ cursor_state: Mutex<CursorState>,
}
unsafe impl Send for Window {}
@@ -148,7 +153,6 @@ impl Window {
/// See the docs in the crate root file.
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
- use std::mem;
let mut rect: winapi::RECT = unsafe { mem::uninitialized() };
if unsafe { user32::GetClientRect(self.window.0, &mut rect) } == 0 {
@@ -163,7 +167,6 @@ impl Window {
/// See the docs in the crate root file.
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
- use std::mem;
let mut rect: winapi::RECT = unsafe { mem::uninitialized() };
if unsafe { user32::GetWindowRect(self.window.0, &mut rect) } == 0 {
@@ -257,7 +260,68 @@ impl Window {
}
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
- unimplemented!();
+ let mut current_state = self.cursor_state.lock().unwrap();
+
+ let foreground_thread_id = unsafe { user32::GetWindowThreadProcessId(self.window.0, ptr::null_mut()) };
+ let current_thread_id = unsafe { kernel32::GetCurrentThreadId() };
+
+ unsafe { user32::AttachThreadInput(foreground_thread_id, current_thread_id, 1) };
+
+ let res = match (state, *current_state) {
+ (CursorState::Normal, CursorState::Normal) => Ok(()),
+ (CursorState::Hide, CursorState::Hide) => Ok(()),
+ (CursorState::Grab, CursorState::Grab) => Ok(()),
+
+ (CursorState::Hide, CursorState::Normal) => {
+ unsafe {
+ user32::SetCursor(ptr::null_mut());
+ *current_state = CursorState::Hide;
+ Ok(())
+ }
+ },
+
+ (CursorState::Normal, CursorState::Hide) => {
+ unsafe {
+ user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW));
+ *current_state = CursorState::Normal;
+ Ok(())
+ }
+ },
+
+ (CursorState::Grab, CursorState::Normal) => {
+ unsafe {
+ user32::SetCursor(ptr::null_mut());
+ let mut rect = mem::uninitialized();
+ if user32::GetClientRect(self.window.0, &mut rect) == 0 {
+ return Err(format!("GetWindowRect failed"));
+ }
+ user32::ClientToScreen(self.window.0, mem::transmute(&mut rect.left));
+ user32::ClientToScreen(self.window.0, mem::transmute(&mut rect.right));
+ if user32::ClipCursor(&rect) == 0 {
+ return Err(format!("ClipCursor failed"));
+ }
+ *current_state = CursorState::Grab;
+ Ok(())
+ }
+ },
+
+ (CursorState::Normal, CursorState::Grab) => {
+ unsafe {
+ user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW));
+ if user32::ClipCursor(ptr::null()) == 0 {
+ return Err(format!("ClipCursor failed"));
+ }
+ *current_state = CursorState::Normal;
+ Ok(())
+ }
+ },
+
+ _ => unimplemented!(),
+ };
+
+ unsafe { user32::AttachThreadInput(foreground_thread_id, current_thread_id, 0) };
+
+ res
}
pub fn hidpi_factor(&self) -> f32 {