Permalink
Browse files

Merge pull request #164 from thefiddler/x11_scrollfix

[X11] Fix legacy scrolling and absolute pointer motion
  • Loading branch information...
thefiddler committed Aug 10, 2014
2 parents 779ff31 + ffa3df2 commit 680a5eef3cb949bc64f37d4364d3391358316a3e
@@ -136,4 +136,10 @@ enum XIDeviceType
SlaveKeyboard = 4,
FloatingSlave = 5,
}
+
+ enum XIMode
+ {
+ Relative = 0,
+ Absolute = 1
+ }
}
@@ -176,6 +176,9 @@ public static int XSendEvent(IntPtr display, IntPtr window, bool propagate, Even
[DllImport("libX11", EntryPoint = "XInternAtoms")]
public extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
+ [DllImport("libX11", EntryPoint = "XGetAtomName")]
+ public extern static IntPtr XGetAtomName(IntPtr display, IntPtr atom);
+
[DllImport("libX11", EntryPoint = "XSetWMProtocols")]
public extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
@@ -1732,7 +1732,7 @@ struct XIValuatorClassInfo
public double max;
public double value;
public int resolution;
- public int mode;
+ public XIMode mode;
}
struct XIDeviceEvent
@@ -60,21 +60,6 @@ class XIKeyboard
public string Name;
}
- // Atoms
- //static readonly IntPtr ButtonLeft;
- //static readonly IntPtr ButtonMiddle;
- ////static readonly IntPtr ButtonRight;
- //static readonly IntPtr ButtonWheelUp;
- //static readonly IntPtr ButtonWheelDown;
- //static readonly IntPtr ButtonWheelLeft;
- //static readonly IntPtr ButtonWheelRight;
- static readonly IntPtr RelX;
- static readonly IntPtr RelY;
- //static readonly IntPtr RelHorizScroll;
- //static readonly IntPtr RelVertScroll;
- //static readonly IntPtr RelHorizWheel;
- //static readonly IntPtr RelVertWheel;
-
long cursor_x, cursor_y; // For GetCursorState()
List<XIMouse> devices = new List<XIMouse>(); // list of connected mice
Dictionary<int, int> rawids = new Dictionary<int, int>(); // maps hardware device ids to XIMouse ids
@@ -93,31 +78,6 @@ static XI2MouseKeyboard()
{
using (new XLock(API.DefaultDisplay))
{
- // Mouse
- //ButtonLeft = Functions.XInternAtom(API.DefaultDisplay, "Button Left", false);
- //ButtonMiddle = Functions.XInternAtom(API.DefaultDisplay, "Button Middle", false);
- //ButtonRight = Functions.XInternAtom(API.DefaultDisplay, "Button Right", false);
- //ButtonWheelUp = Functions.XInternAtom(API.DefaultDisplay, "Button Wheel Up", false);
- //ButtonWheelDown = Functions.XInternAtom(API.DefaultDisplay, "Button Wheel Down", false);
- //ButtonWheelLeft = Functions.XInternAtom(API.DefaultDisplay, "Button Horiz Wheel Left", false);
- //ButtonWheelRight = Functions.XInternAtom(API.DefaultDisplay, "Button Horiz Wheel Right", false);
- RelX = Functions.XInternAtom(API.DefaultDisplay, "Rel X", false);
- RelY = Functions.XInternAtom(API.DefaultDisplay, "Rel Y", false);
- //RelHorizWheel = Functions.XInternAtom(API.DefaultDisplay, "Rel Horiz Wheel", false);
- //RelVertWheel = Functions.XInternAtom(API.DefaultDisplay, "Rel Vert Wheel", false);
- //RelHorizScroll = Functions.XInternAtom(API.DefaultDisplay, "Rel Horiz Scroll", false);
- //RelVertScroll = Functions.XInternAtom(API.DefaultDisplay, "Rel Vert Scroll", false);
-
- // Multitouch
- //TouchX = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Position X", false);
- //TouchY = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Position Y", false);
- //TouchMajor = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Touch Major", false);
- //TouchMinor = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Touch Minor", false);
- //TouchPressure = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Pressure", false);
- //TouchId = Functions.XInternAtom(API.DefaultDisplay, "Abs MT Tracking ID", false);
- //TouchMaxContacts = Functions.XInternAtom(API.DefaultDisplay, "Max Contacts", false);
-
- // Custom
ExitAtom = Functions.XInternAtom(API.DefaultDisplay, "Exit Input Thread Message", false);
}
}
@@ -391,17 +351,39 @@ void UpdateDevices()
case XIClassType.Valuator:
{
+ // We use relative x/y valuators for mouse movement.
+ // Iff these are not available, we fall back to
+ // absolute x/y valuators.
XIValuatorClassInfo* valuator = (XIValuatorClassInfo*)class_info;
- if (valuator->label == RelX)
+ if (valuator->label == XI.RelativeX)
{
Debug.WriteLine("\tRelative X movement");
d.MotionX = *valuator;
}
- else if (valuator->label == RelY)
+ else if (valuator->label == XI.RelativeY)
{
Debug.WriteLine("\tRelative Y movement");
d.MotionY = *valuator;
}
+ else if (valuator->label == XI.AbsoluteX)
+ {
+ Debug.WriteLine("\tAbsolute X movement");
+ if (d.MotionX.number == -1)
+ d.MotionX = *valuator;
+ }
+ else if (valuator->label == XI.AbsoluteY)
+ {
+ Debug.WriteLine("\tAbsolute X movement");
+ if (d.MotionY.number == -1)
+ d.MotionY = *valuator;
+ }
+ else
+ {
+ IntPtr label = Functions.XGetAtomName(window.Display, valuator->label);
+ Debug.Print("\tUnknown valuator {0}",
+ Marshal.PtrToStringAnsi(label));
+ Functions.XFree(label);
+ }
}
break;
}
@@ -508,6 +490,8 @@ void ProcessRawEvent(ref XGenericEventCookie cookie)
float dx, dy;
MouseButton button = X11KeyMap.TranslateButton(raw.detail, out dx, out dy);
mouse.State[button] = raw.evtype == XIEventType.RawButtonPress;
+ if (mouse.ScrollX.number == -1 && mouse.ScrollY.number == -1)
+ mouse.State.SetScrollRelative(dx, dy);
}
break;
@@ -555,13 +539,27 @@ unsafe static void ProcessRawMotion(XIMouse d, ref XIRawEvent raw)
{
// Note: we use the raw values here, without pointer
// ballistics and any other modification.
- double x = ReadRawValue(ref raw, d.MotionX.number);
- double y = ReadRawValue(ref raw, d.MotionY.number);
- double h = ReadRawValue(ref raw, d.ScrollX.number) / d.ScrollX.increment;
- double v = ReadRawValue(ref raw, d.ScrollY.number) / d.ScrollY.increment;
-
- d.State.X += (int)Math.Round(x);
- d.State.Y += (int)Math.Round(y);
+ double x = 0;
+ double y = 0;
+ double h = 0;
+ double v = 0;
+ if (d.MotionX.number != -1)
+ x = ReadRawValue(ref raw, d.MotionX.number);
+ if (d.MotionY.number != -1)
+ y = ReadRawValue(ref raw, d.MotionY.number);
+ if (d.ScrollX.number != -1)
+ h = ReadRawValue(ref raw, d.ScrollX.number) / d.ScrollX.increment;
+ if (d.ScrollY.number != -1)
+ v = ReadRawValue(ref raw, d.ScrollY.number) / d.ScrollY.increment;
+
+ if (d.MotionX.mode == XIMode.Relative)
+ d.State.X += (int)Math.Round(x);
+ else
+ d.State.X = (int)Math.Round(x);
+ if (d.MotionY.mode == XIMode.Relative)
+ d.State.Y += (int)Math.Round(y);
+ else
+ d.State.Y = (int)Math.Round(y);
// Note: OpenTK follows the windows scrolling convention where
// (+h, +v) = (right, up). XI2 uses (+h, +v) = (right, down)

0 comments on commit 680a5ee

Please sign in to comment.