private static void ProcessRawMotion(XIMouse d, ref XIRawEvent raw) { // Note: we use the raw values here, without pointer // ballistics and any other modification. 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) // instead, so we need to flip the vertical offset. d.State.SetScrollRelative((float)h, (float)-v); }
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); d.State.SetScrollRelative((float)h, (float)v); }
void ProcessRawEvent(ref XGenericEventCookie cookie) { lock (Sync) { unsafe { XIRawEvent raw = *(XIRawEvent *)cookie.data; XIMouse mouse; XIKeyboard keyboard; switch (raw.evtype) { case XIEventType.RawMotion: if (GetMouseDevice(raw.deviceid, out mouse)) { ProcessRawMotion(mouse, ref raw); } break; case XIEventType.RawButtonPress: case XIEventType.RawButtonRelease: if (GetMouseDevice(raw.deviceid, out mouse)) { 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; case XIEventType.RawKeyPress: case XIEventType.RawKeyRelease: if (GetKeyboardDevice(raw.deviceid, out keyboard)) { Key key; if (KeyMap.TranslateKey(raw.detail, out key)) { keyboard.State[key] = raw.evtype == XIEventType.RawKeyPress; } } break; } } } }
unsafe static double ReadRawValue(ref XIRawEvent raw, int bit) { double value = 0; if (IsBitSet(raw.valuators.mask, bit)) { // Find the offset where this value is stored. // The offset is equal to the number of bits // set in raw.valuators.mask between [0, bit) int offset = 0; for (int i = 0; i < bit; i++) { if (IsBitSet(raw.valuators.mask, i)) { offset++; } } value = *((double *)raw.raw_values + offset); } return(value); }
unsafe static double ReadRawValue(ref XIRawEvent raw, int bit) { double value = 0; if (IsBitSet(raw.valuators.mask, bit)) { // Find the offset where this value is stored. // The offset is equal to the number of bits // set in raw.valuators.mask between [0, bit) int offset = 0; for (int i = 0; i < bit; i++) { if (IsBitSet(raw.valuators.mask, i)) { offset++; } } value = *((double*)raw.raw_values + offset); } return value; }
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 = 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) // instead, so we need to flip the vertical offset. d.State.SetScrollRelative((float)h, (float)(-v)); }
private void ProcessEvents() { while (true) { XEvent e = new XEvent(); using (new XLock(this.window.Display)) { if (!Functions.XCheckIfEvent(this.window.Display, ref e, this.Predicate, new IntPtr(XI2Mouse.XIOpCode))) { break; } XGenericEventCookie cookie = e.GenericEventCookie; if (Functions.XGetEventData(this.window.Display, ref cookie) != 0) { XIRawEvent xiRawEvent = (XIRawEvent)Marshal.PtrToStructure(cookie.data, typeof(XIRawEvent)); if (!this.rawids.ContainsKey(xiRawEvent.deviceid)) { this.mice.Add(new MouseState()); this.rawids.Add(xiRawEvent.deviceid, this.mice.Count - 1); } MouseState mouseState = this.mice[this.rawids[xiRawEvent.deviceid]]; switch (xiRawEvent.evtype) { case XIEventType.RawButtonPress: switch (xiRawEvent.detail) { case 1: mouseState.EnableBit(0); break; case 2: mouseState.EnableBit(1); break; case 3: mouseState.EnableBit(2); break; case 4: ++mouseState.WheelPrecise; break; case 5: --mouseState.WheelPrecise; break; case 6: mouseState.EnableBit(3); break; case 7: mouseState.EnableBit(4); break; case 8: mouseState.EnableBit(5); break; case 9: mouseState.EnableBit(6); break; case 10: mouseState.EnableBit(7); break; case 11: mouseState.EnableBit(8); break; case 12: mouseState.EnableBit(9); break; case 13: mouseState.EnableBit(10); break; case 14: mouseState.EnableBit(11); break; } case XIEventType.RawButtonRelease: switch (xiRawEvent.detail) { case 1: mouseState.DisableBit(0); break; case 2: mouseState.DisableBit(1); break; case 3: mouseState.DisableBit(2); break; case 6: mouseState.DisableBit(3); break; case 7: mouseState.DisableBit(4); break; case 8: mouseState.DisableBit(5); break; case 9: mouseState.DisableBit(6); break; case 10: mouseState.DisableBit(7); break; case 11: mouseState.DisableBit(8); break; case 12: mouseState.DisableBit(9); break; case 13: mouseState.DisableBit(10); break; case 14: mouseState.DisableBit(11); break; } case XIEventType.RawMotion: double x = 0.0; double y = 0.0; if (XI2Mouse.IsBitSet(xiRawEvent.valuators.mask, 0)) { x = BitConverter.Int64BitsToDouble(Marshal.ReadInt64(xiRawEvent.raw_values, 0)); } if (XI2Mouse.IsBitSet(xiRawEvent.valuators.mask, 1)) { y = BitConverter.Int64BitsToDouble(Marshal.ReadInt64(xiRawEvent.raw_values, 8)); } if (!this.CheckMouseWarp(x, y)) { mouseState.X += (int)x; mouseState.Y += (int)y; break; } else { break; } } this.mice[this.rawids[xiRawEvent.deviceid]] = mouseState; } Functions.XFreeEventData(this.window.Display, ref cookie); } } }
void ProcessEvents() { while (true) { XEvent e = new XEvent(); XGenericEventCookie cookie; using (new XLock(window.Display)) { if (!Functions.XCheckIfEvent(window.Display, ref e, Predicate, new IntPtr(XIOpCode))) { return; } cookie = e.GenericEventCookie; if (Functions.XGetEventData(window.Display, ref cookie) != 0) { XIRawEvent raw = (XIRawEvent) Marshal.PtrToStructure(cookie.data, typeof(XIRawEvent)); if (!rawids.ContainsKey(raw.deviceid)) { mice.Add(new MouseState()); rawids.Add(raw.deviceid, mice.Count - 1); } MouseState state = mice[rawids[raw.deviceid]]; switch (raw.evtype) { case XIEventType.RawMotion: double x = 0, y = 0; if (IsBitSet(raw.valuators.mask, 0)) { x = BitConverter.Int64BitsToDouble(Marshal.ReadInt64(raw.raw_values, 0)); } if (IsBitSet(raw.valuators.mask, 1)) { y = BitConverter.Int64BitsToDouble(Marshal.ReadInt64(raw.raw_values, 8)); } if (!CheckMouseWarp(x, y)) { state.X += (int)x; state.Y += (int)y; } break; case XIEventType.RawButtonPress: switch (raw.detail) { case 1: state.EnableBit((int)MouseButton.Left); break; case 2: state.EnableBit((int)MouseButton.Middle); break; case 3: state.EnableBit((int)MouseButton.Right); break; case 4: state.WheelPrecise++; break; case 5: state.WheelPrecise--; break; case 6: state.EnableBit((int)MouseButton.Button1); break; case 7: state.EnableBit((int)MouseButton.Button2); break; case 8: state.EnableBit((int)MouseButton.Button3); break; case 9: state.EnableBit((int)MouseButton.Button4); break; case 10: state.EnableBit((int)MouseButton.Button5); break; case 11: state.EnableBit((int)MouseButton.Button6); break; case 12: state.EnableBit((int)MouseButton.Button7); break; case 13: state.EnableBit((int)MouseButton.Button8); break; case 14: state.EnableBit((int)MouseButton.Button9); break; } break; case XIEventType.RawButtonRelease: switch (raw.detail) { case 1: state.DisableBit((int)MouseButton.Left); break; case 2: state.DisableBit((int)MouseButton.Middle); break; case 3: state.DisableBit((int)MouseButton.Right); break; case 6: state.DisableBit((int)MouseButton.Button1); break; case 7: state.DisableBit((int)MouseButton.Button2); break; case 8: state.DisableBit((int)MouseButton.Button3); break; case 9: state.DisableBit((int)MouseButton.Button4); break; case 10: state.DisableBit((int)MouseButton.Button5); break; case 11: state.DisableBit((int)MouseButton.Button6); break; case 12: state.DisableBit((int)MouseButton.Button7); break; case 13: state.DisableBit((int)MouseButton.Button8); break; case 14: state.DisableBit((int)MouseButton.Button9); break; } break; } mice[rawids[raw.deviceid]] = state; } Functions.XFreeEventData(window.Display, ref cookie); } } }