* X11KeyMap.cs: Added AltGr keycode.

* X11Mouse.cs: Use XQueryPointer instead of trying to hook events.

* X11Keyboard.cs: Improved handling of key modifiers.

* X11Factory.cs: Use new X11Mouse API.

* Functions.cs: Added XButtonGrab/XButtonUngrab.

* API.cs: Added missing XF86 keysyms.
This commit is contained in:
the_fiddler 2010-11-04 17:57:09 +00:00
parent 7e344e2ac2
commit b646cfa06c
6 changed files with 154 additions and 112 deletions

View file

@ -1142,6 +1142,8 @@ XF86VidModeGetGammaRampSize(
Hyper_L = 0xffed, /* Left hyper */
Hyper_R = 0xffee, /* Right hyper */
ISO_Level3_Shift = 0xfe03,
/*
* Latin 1
* (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
@ -1245,6 +1247,79 @@ XF86VidModeGetGammaRampSize(
bar = 0x007c, /* U+007C VERTICAL LINE */
braceright = 0x007d, /* U+007D RIGHT CURLY BRACKET */
asciitilde = 0x007e, /* U+007E TILDE */
// Extra keys
XF86AudioMute = 0x1008ff12,
XF86AudioLowerVolume = 0x1008ff11,
XF86AudioRaiseVolume = 0x1008ff13,
XF86PowerOff = 0x1008ff2a,
XF86Suspend = 0x1008ffa7,
XF86Copy = 0x1008ff57,
XF86Paste = 0x1008ff6d,
XF86Cut = 0x1008ff58,
XF86MenuKB = 0x1008ff65,
XF86Calculator = 0x1008ff1d,
XF86Sleep = 0x1008ff2f,
XF86WakeUp = 0x1008ff2b ,
XF86Explorer = 0x1008ff5d,
XF86Send = 0x1008ff7b,
XF86Xfer = 0x1008ff8a,
XF86Launch1 = 0x1008ff41,
XF86Launch2 = 0x1008ff42,
XF86Launch3 = 0x1008ff43,
XF86Launch4 = 0x1008ff44,
XF86Launch5 = 0x1008ff45,
XF86LaunchA = 0x1008ff4a,
XF86LaunchB = 0x1008ff4b,
XF86WWW = 0x1008ff2e,
XF86DOS = 0x1008ff5a,
XF86ScreenSaver = 0x1008ff2d,
XF86RotateWindows = 0x1008ff74,
XF86Mail = 0x1008ff19,
XF86Favorites = 0x1008ff30,
XF86MyComputer = 0x1008ff33,
XF86Back = 0x1008ff26,
XF86Forward = 0x1008ff27 ,
XF86Eject = 0x1008ff2c,
XF86AudioPlay = 0x1008ff14,
XF86AudioStop = 0x1008ff15,
XF86AudioPrev = 0x1008ff16,
XF86AudioNext = 0x1008ff17,
XF86AudioRecord = 0x1008ff1c,
XF86AudioPause =0x1008ff31,
XF86AudioRewind = 0x1008ff3e,
XF86AudioForward = 0x1008ff97,
XF86Phone = 0x1008ff6e,
XF86Tools = 0x1008ff81,
XF86HomePage = 0x1008ff18,
XF86Close = 0x1008ff56,
XF86Reload = 0x1008ff73,
XF86ScrollUp = 0x1008ff78,
XF86ScrollDown = 0x1008ff79,
XF86New = 0x1008ff68,
XF86TouchpadToggle = 0x1008ffa9,
XF86WebCam = 0x1008ff8f,
XF86Search = 0x1008ff1b,
XF86Finance = 0x1008ff3c,
XF86Shop = 0x1008ff36,
XF86MonBrightnessDown = 0x1008ff03,
XF86MonBrightnessUp = 0x1008ff02,
XF86AudioMedia = 0x1008ff32,
XF86Display = 0x1008ff59,
XF86KbdLightOnOff = 0x1008ff04,
XF86KbdBrightnessDown = 0x1008ff06,
XF86KbdBrightnessUp = 0x1008ff05,
XF86Reply = 0x1008ff72,
XF86MailForward = 0x1008ff90,
XF86Save = 0x1008ff77,
XF86Documents = 0x1008ff5b,
XF86Battery = 0x1008ff93,
XF86Bluetooth = 0x1008ff94,
XF86WLAN = 0x1008ff95,
SunProps = 0x1005ff70,
SunOpen = 0x1005ff73,
}
#endregion

View file

@ -108,8 +108,9 @@ namespace OpenTK.Platform.X11
public extern static int XConnectionNumber(IntPtr diplay);
[DllImport("libX11")]
public extern static int XPending(IntPtr diplay);
[DllImport("libX11", EntryPoint = "XSelectInput")]
public extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
public extern static int XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
[DllImport("libX11", EntryPoint = "XDestroyWindow")]
public extern static int XDestroyWindow(IntPtr display, IntPtr window);
@ -179,6 +180,17 @@ namespace OpenTK.Platform.X11
[DllImport("libX11", EntryPoint = "XUngrabPointer")]
public extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
[DllImport("libX11", EntryPoint = "XGrabButton")]
public extern static int XGrabButton(IntPtr display,
int button, uint modifiers, Window grab_window,
Bool owner_events, EventMask event_mask,
GrabMode pointer_mode, GrabMode keyboard_mode,
Window confine_to, Cursor cursor);
[DllImport("libX11", EntryPoint = "XUngrabButton")]
public extern static int XUngrabButton(IntPtr display, uint button, uint
modifiers, Window grab_window);
[DllImport("libX11", EntryPoint = "XQueryPointer")]
public extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);

View file

@ -88,7 +88,7 @@ namespace OpenTK.Platform.X11
//if (XI2Mouse.IsSupported(IntPtr.Zero))
// return new XI2Mouse(null); // Requires xorg 1.7 or higher.
//else
return new X11Mouse(null); // Always supported.
return new X11Mouse(); // Always supported.
}
#endregion

View file

@ -36,6 +36,7 @@ namespace OpenTK.Platform.X11
this.Add(XKey.Super_R, Key.WinRight);
this.Add(XKey.Meta_L, Key.WinLeft);
this.Add(XKey.Meta_R, Key.WinRight);
this.Add(XKey.ISO_Level3_Shift, Key.AltRight); // Normally AltGr
this.Add(XKey.Menu, Key.Menu);
this.Add(XKey.Tab, Key.Tab);

View file

@ -38,12 +38,36 @@ namespace OpenTK.Platform.X11
{
readonly static X11KeyMap keymap = new X11KeyMap();
readonly static string name = "Core X11 keyboard";
KeyboardState state = new KeyboardState();
readonly byte[] keys = new byte[32];
readonly int KeysymsPerKeycode;
KeyboardState state = new KeyboardState();
public X11Keyboard()
{
Debug.WriteLine("Using X11Keyboard.");
state.IsConnected = true;
IntPtr display = API.DefaultDisplay;
using (new XLock(display))
{
// Find the number of keysyms per keycode.
int first = 0, last = 0;
API.DisplayKeycodes(display, ref first, ref last);
IntPtr keysym_ptr = API.GetKeyboardMapping(display, (byte)first, last - first + 1,
ref KeysymsPerKeycode);
Functions.XFree(keysym_ptr);
try
{
// Request that auto-repeat is only set on devices that support it physically.
// This typically means that it's turned off for keyboards what we want).
// We prefer this method over XAutoRepeatOff/On, because the latter needs to
// be reset before the program exits.
bool supported;
Functions.XkbSetDetectableAutoRepeat(display, true, out supported);
}
catch { }
}
}
public KeyboardState GetState()
@ -78,18 +102,20 @@ namespace OpenTK.Platform.X11
Functions.XQueryKeymap(display, keys);
for (int keycode = 8; keycode < 256; keycode++)
{
IntPtr keysym = Functions.XKeycodeToKeysym(display, (byte)keycode, 0);
IntPtr keysym2 = Functions.XKeycodeToKeysym(display, (byte)keycode, 1);
bool pressed = (keys[keycode >> 3] >> (keycode & 0x07) & 0x01) != 0;
Key key;
if (keymap.TryGetValue((XKey)keysym, out key) ||
keymap.TryGetValue((XKey)keysym2, out key))
for (int mod = 0; mod < KeysymsPerKeycode; mod++)
{
if (pressed)
state.EnableBit((int)key);
else
state.DisableBit((int)key);
IntPtr keysym = Functions.XKeycodeToKeysym(display, (byte)keycode, mod);
if (keysym != IntPtr.Zero && keymap.TryGetValue((XKey)keysym, out key))
{
if (pressed)
state.EnableBit((int)key);
else
state.DisableBit((int)key);
break;
}
}
}
}

View file

@ -34,41 +34,17 @@ namespace OpenTK.Platform.X11
{
sealed class X11Mouse : IMouseDriver2
{
readonly IntPtr display;
MouseState mouse = new MouseState();
X11WindowInfo window;
// Can either attach itself to the specified window or can hook the root window.
public X11Mouse(X11WindowInfo win)
// Can either attach itself to the specified window or can hook the root window.
public X11Mouse()
{
if (win != null)
{
window = win;
}
else
{
using (new XLock(API.DefaultDisplay))
{
window = new X11WindowInfo();
window.Display = API.DefaultDisplay;
window.Screen = Functions.XDefaultScreen(window.Display);
window.RootWindow = Functions.XRootWindow(window.Display, window.Screen);
window.WindowHandle = window.RootWindow;
window.EventMask = EventMask.ButtonMotionMask |
EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;
//Functions.XGrabPointer(window.Display, window.RootWindow, true,
// window.EventMask, GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, IntPtr.Zero,
// IntPtr.Zero, IntPtr.Zero);
//Functions.XSelectInput(window.Display, window.RootWindow, new IntPtr((int)window.EventMask));
}
Debug.WriteLine("Using X11Mouse.");
}
Debug.WriteLine("Using X11Mouse.");
mouse.IsConnected = true;
display = API.DefaultDisplay;
}
// Todo: remove this
public IList<MouseDevice> Mouse { get { throw new NotSupportedException(); } }
public MouseState GetState()
{
ProcessEvents();
@ -98,77 +74,29 @@ namespace OpenTK.Platform.X11
IntPtr root, child;
int root_x, root_y, win_x, win_y;
int buttons;
Functions.XQueryPointer(window.Display, window.WindowHandle, out root, out child,
out root_x, out root_y, out win_x, out win_y, out buttons);
mouse.X = root_x;
mouse.Y = root_y;
WriteBit(MouseButton.Left, buttons & (int)MouseMask.Button1Mask);
WriteBit(MouseButton.Middle, buttons & (int)MouseMask.Button2Mask);
WriteBit(MouseButton.Right, buttons & (int)MouseMask.Button3Mask);
if ((buttons & (int)MouseMask.Button4Mask) != 0)
mouse.WheelPrecise++;
if ((buttons & (int)MouseMask.Button5Mask) != 0)
mouse.WheelPrecise--;
WriteBit(MouseButton.Button1, buttons & (int)MouseMask.Button6Mask);
WriteBit(MouseButton.Button2, buttons & (int)MouseMask.Button7Mask);
WriteBit(MouseButton.Button3, buttons & (int)MouseMask.Button8Mask);
// XEvent e = new XEvent();
//
// while (true)
// {
// using (new XLock(window.Display))
// {
// if (!Functions.XCheckWindowEvent(window.Display, window.WindowHandle, window.EventMask, ref e))
// break;
//
// switch (e.type)
// {
// case XEventName.ButtonPress:
// switch (e.ButtonEvent.button)
// {
// case 1: mouse.EnableBit((int)MouseButton.Left); break;
// case 2: mouse.EnableBit((int)MouseButton.Middle); break;
// case 3: mouse.EnableBit((int)MouseButton.Right); break;
// case 4: mouse.WheelPrecise++; break;
// case 5: mouse.WheelPrecise--; break;
// case 6: mouse.EnableBit((int)MouseButton.Button1); break;
// case 7: mouse.EnableBit((int)MouseButton.Button2); break;
// case 8: mouse.EnableBit((int)MouseButton.Button3); break;
// case 9: mouse.EnableBit((int)MouseButton.Button4); break;
// case 10: mouse.EnableBit((int)MouseButton.Button5); break;
// case 11: mouse.EnableBit((int)MouseButton.Button6); break;
// case 12: mouse.EnableBit((int)MouseButton.Button7); break;
// case 13: mouse.EnableBit((int)MouseButton.Button8); break;
// case 15: mouse.EnableBit((int)MouseButton.Button9); break;
// }
// break;
//
// case XEventName.ButtonRelease:
// switch (e.ButtonEvent.button)
// {
// case 1: mouse.DisableBit((int)MouseButton.Left); break;
// case 2: mouse.DisableBit((int)MouseButton.Middle); break;
// case 3: mouse.DisableBit((int)MouseButton.Right); break;
// case 6: mouse.DisableBit((int)MouseButton.Button1); break;
// case 7: mouse.DisableBit((int)MouseButton.Button2); break;
// case 8: mouse.DisableBit((int)MouseButton.Button3); break;
// case 9: mouse.DisableBit((int)MouseButton.Button4); break;
// case 10: mouse.DisableBit((int)MouseButton.Button5); break;
// case 11: mouse.DisableBit((int)MouseButton.Button6); break;
// case 12: mouse.DisableBit((int)MouseButton.Button7); break;
// case 13: mouse.DisableBit((int)MouseButton.Button8); break;
// case 15: mouse.DisableBit((int)MouseButton.Button9); break;
// }
// break;
//
// case XEventName.MotionNotify:
// mouse.X = e.MotionEvent.x;
// mouse.Y = e.MotionEvent.y;
// break;
// }
// }
// }
using (new XLock(display))
{
IntPtr window = Functions.XRootWindow(display, Functions.XDefaultScreen(display));
Functions.XQueryPointer(display, window, out root, out child,
out root_x, out root_y, out win_x, out win_y, out buttons);
mouse.X = root_x;
mouse.Y = root_y;
WriteBit(MouseButton.Left, buttons & (int)MouseMask.Button1Mask);
WriteBit(MouseButton.Middle, buttons & (int)MouseMask.Button2Mask);
WriteBit(MouseButton.Right, buttons & (int)MouseMask.Button3Mask);
// Note: this will never work right. After spending a week on this, I simply don't care
// anymore. If someone can fix it, please do.
// Note 2: I have tried passively grabbing those buttons - no go (BadAccess).
if ((buttons & (int)MouseMask.Button4Mask) != 0)
mouse.WheelPrecise++;
if ((buttons & (int)MouseMask.Button5Mask) != 0)
mouse.WheelPrecise--;
WriteBit(MouseButton.Button1, buttons & (int)MouseMask.Button6Mask);
WriteBit(MouseButton.Button2, buttons & (int)MouseMask.Button7Mask);
WriteBit(MouseButton.Button3, buttons & (int)MouseMask.Button8Mask);
}
}
}
}