Skip to content

Commit

Permalink
Fix x11 mouse scroll wheel
Browse files Browse the repository at this point in the history
  • Loading branch information
rukai committed Jul 10, 2017
1 parent aad82eb commit 2989515
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "winit"
version = "0.7.2"
version = "0.7.3"
authors = ["The winit contributors, Pierre Krieger <pierre.krieger1708@gmail.com>"]
description = "Cross-platform window creation library."
keywords = ["windowing"]
Expand Down
53 changes: 36 additions & 17 deletions src/platform/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ impl EventsLoop {
for i in 0..xev.valuators.mask_len*8 {
if ffi::XIMaskIsSet(mask, i) {
if let Some(&mut (_, ref mut info)) = physical_device.scroll_axes.iter_mut().find(|&&mut (axis, _)| axis == i) {
let delta = (unsafe { *value } - info.position) / info.increment;
let delta = (unsafe { *value } - info.position) / info.increment; // TODO: Doesn't handle underflow/overflow
info.position = unsafe { *value };
events.push(Event::WindowEvent { window_id: wid, event: MouseWheel {
device_id: did,
Expand Down Expand Up @@ -434,6 +434,15 @@ impl EventsLoop {

ffi::XI_Enter => {
let xev: &ffi::XIEnterEvent = unsafe { &*(xev.data as *const _) };

let mut devices = self.devices.lock().unwrap();
let physical_device = devices.get_mut(&DeviceId(xev.sourceid)).unwrap();
for info in DeviceInfo::get(&self.display, ffi::XIAllDevices).iter() {
if info.deviceid == xev.sourceid {
physical_device.reset_scroll_position(info);
}
}

callback(Event::WindowEvent { window_id: mkwid(xev.event), event: MouseEntered { device_id: mkdid(xev.deviceid) } })
}
ffi::XI_Leave => {
Expand Down Expand Up @@ -799,9 +808,9 @@ impl Device {
fn new(el: &EventsLoop, info: &ffi::XIDeviceInfo) -> Self
{
let name = unsafe { CStr::from_ptr(info.name).to_string_lossy() };
let mut scroll_axes = Vec::new();

let physical_device = info._use == ffi::XISlaveKeyboard || info._use == ffi::XISlavePointer || info._use == ffi::XIFloatingSlave;
if physical_device {
if Device::physical_device(info) {
// Register for global raw events
let mask = ffi::XI_RawMotionMask
| ffi::XI_RawButtonPressMask | ffi::XI_RawButtonReleaseMask
Expand All @@ -814,15 +823,9 @@ impl Device {
};
(el.display.xinput2.XISelectEvents)(el.display.display, el.root, &mut event_mask as *mut ffi::XIEventMask, 1);
}
}

let mut scroll_axes = Vec::new();

if physical_device {
let classes : &[*const ffi::XIAnyClassInfo] =
unsafe { slice::from_raw_parts(info.classes as *const *const ffi::XIAnyClassInfo, info.num_classes as usize) };
// Identify scroll axes
for class_ptr in classes {
for class_ptr in Device::classes(info) {
let class = unsafe { &**class_ptr };
match class._type {
ffi::XIScrollClass => {
Expand All @@ -840,24 +843,40 @@ impl Device {
_ => {}
}
}
// Fix up initial scroll positions
for class_ptr in classes {
}

let mut device = Device {
name: name.into_owned(),
scroll_axes: scroll_axes,
};
device.reset_scroll_position(info);
device
}

fn reset_scroll_position(&mut self, info: &ffi::XIDeviceInfo) {
if Device::physical_device(info) {
for class_ptr in Device::classes(info) {
let class = unsafe { &**class_ptr };
match class._type {
ffi::XIValuatorClass => {
let info = unsafe { mem::transmute::<&ffi::XIAnyClassInfo, &ffi::XIValuatorClassInfo>(class) };
if let Some(&mut (_, ref mut axis)) = scroll_axes.iter_mut().find(|&&mut (axis, _)| axis == info.number) {
if let Some(&mut (_, ref mut axis)) = self.scroll_axes.iter_mut().find(|&&mut (axis, _)| axis == info.number) {
axis.position = info.value;
}
}
_ => {}
}
}
}
}

Device {
name: name.into_owned(),
scroll_axes: scroll_axes,
}
#[inline]
fn physical_device(info: &ffi::XIDeviceInfo) -> bool {
info._use == ffi::XISlaveKeyboard || info._use == ffi::XISlavePointer || info._use == ffi::XIFloatingSlave
}

#[inline]
fn classes(info: &ffi::XIDeviceInfo) -> &[*const ffi::XIAnyClassInfo] {
unsafe { slice::from_raw_parts(info.classes as *const *const ffi::XIAnyClassInfo, info.num_classes as usize) }
}
}

0 comments on commit 2989515

Please sign in to comment.