Re-added the events files for Area.

This commit is contained in:
Pietro Gagliardi 2014-08-04 23:05:31 -04:00
parent f035792c1d
commit 95151ce6ea
2 changed files with 286 additions and 0 deletions

132
redo/events_darwin.go Normal file
View File

@ -0,0 +1,132 @@
// 30 march 2014
package ui
/*
Mac OS X uses its own set of hardware key codes that are different from PC keyboard scancodes, but are positional (like PC keyboard scancodes). These are defined in <HIToolbox/Events.h>, a Carbon header. As far as I can tell, there's no way to include this header without either using an absolute path or linking Carbon into the program, so the constant values are used here instead.
The Cocoa docs do guarantee that -[NSEvent keyCode] results in key codes that are the same as those returned by Carbon; that is, these codes.
*/
// use uintptr to be safe
var keycodeKeys = map[uintptr]byte{
0x00: 'a',
0x01: 's',
0x02: 'd',
0x03: 'f',
0x04: 'h',
0x05: 'g',
0x06: 'z',
0x07: 'x',
0x08: 'c',
0x09: 'v',
0x0B: 'b',
0x0C: 'q',
0x0D: 'w',
0x0E: 'e',
0x0F: 'r',
0x10: 'y',
0x11: 't',
0x12: '1',
0x13: '2',
0x14: '3',
0x15: '4',
0x16: '6',
0x17: '5',
0x18: '=',
0x19: '9',
0x1A: '7',
0x1B: '-',
0x1C: '8',
0x1D: '0',
0x1E: ']',
0x1F: 'o',
0x20: 'u',
0x21: '[',
0x22: 'i',
0x23: 'p',
0x25: 'l',
0x26: 'j',
0x27: '\'',
0x28: 'k',
0x29: ';',
0x2A: '\\',
0x2B: ',',
0x2C: '/',
0x2D: 'n',
0x2E: 'm',
0x2F: '.',
0x32: '`',
0x24: '\n',
0x30: '\t',
0x31: ' ',
0x33: '\b',
}
var keycodeExtKeys = map[uintptr]ExtKey{
0x41: NDot,
0x43: NMultiply,
0x45: NAdd,
0x4B: NDivide,
0x4C: NEnter,
0x4E: NSubtract,
0x52: N0,
0x53: N1,
0x54: N2,
0x55: N3,
0x56: N4,
0x57: N5,
0x58: N6,
0x59: N7,
0x5B: N8,
0x5C: N9,
0x35: Escape,
0x60: F5,
0x61: F6,
0x62: F7,
0x63: F3,
0x64: F8,
0x65: F9,
0x67: F11,
0x6D: F10,
0x6F: F12,
0x72: Insert, // listed as the Help key but it's in the same position on an Apple keyboard as the Insert key on a Windows keyboard; thanks to SeanieB from irc.badnik.net and Psy in irc.freenode.net/#macdev for confirming they have the same code
0x73: Home,
0x74: PageUp,
0x75: Delete,
0x76: F4,
0x77: End,
0x78: F2,
0x79: PageDown,
0x7A: F1,
0x7B: Left,
0x7C: Right,
0x7D: Down,
0x7E: Up,
}
var keycodeModifiers = map[uintptr]Modifiers{
0x37: Super, // left command
0x38: Shift, // left shift
0x3A: Alt, // left option
0x3B: Ctrl, // left control
0x3C: Shift, // right shift
0x3D: Alt, // right alt
0x3E: Ctrl, // right control
// the following is not in Events.h for some reason
// thanks to Nicole and jedivulcan from irc.badnik.net
0x36: Super, // right command
}
func fromKeycode(keycode uintptr) (ke KeyEvent, ok bool) {
if key, ok := keycodeKeys[keycode]; ok {
ke.Key = key
return ke, true
}
if extkey, ok := keycodeExtKeys[keycode]; ok {
ke.ExtKey = extkey
return ke, true
}
return ke, false
}

154
redo/events_notdarwin.go Normal file
View File

@ -0,0 +1,154 @@
// +build !darwin
// Mac OS X uses its own set of position-independent key codes
// 29 march 2014
package ui
import (
"image"
)
/*
Windows and GTK+ have a limit of 2 and 3 clicks, respectively, natively supported. Fortunately, we can simulate the double/triple-click behavior to build higher-order clicks. We can use the same algorithm Windows uses on both:
http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx
For GTK+, we pull the double-click time and double-click distance, which work the same as the equivalents on Windows (so the distance is in all directions), from the GtkSettings system.
On GTK+ this will also allow us to discard the GDK_BUTTON_2PRESS and GDK_BUTTON_3PRESS events, so the button press stream will be just like on other platforms.
Thanks to mclasen, garnacho_, halfline, and tristan in irc.gimp.net/#gtk+.
TODO - technically a GDK_BUTTON_3PRESS is detected in half the time as a GDK_BUTTON_2PRESS... handle?
*/
// the zero value is a reset clickCounter ready for use
// it doesn't matter that all the non-count fields are zero: the first click will fail the curButton test straightaway, so it'll return 1 and set the rest of the structure accordingly
type clickCounter struct {
curButton uint
rect image.Rectangle
prevTime uintptr
count uint
}
// x, y, xdist, ydist, and c.rect must have the same units
// so must time, maxTime, and c.prevTime
func (c *clickCounter) click(button uint, x int, y int, time uintptr, maxTime uintptr, xdist int, ydist int) uint {
if button != c.curButton { // different button; start over
c.count = 0
}
if !image.Pt(x, y).In(c.rect) { // not in the allowed region for a double-click; don't count
c.count = 0
}
if (time - c.prevTime) > maxTime { // too slow; don't count
// note the above expression; time > (c.prevTime + maxTime) can overflow!
c.count = 0
}
c.count++ // if either of the above ifs happened, this will make the click count 1; otherwise it will make the click count 2, 3, 4, 5, ...
// now we need to update the internal structures for the next test
c.curButton = button
c.prevTime = time
c.rect = image.Rect(x-xdist, y-ydist,
x+xdist, y+ydist)
return c.count
}
// call this when losing focus, etc.
func (c *clickCounter) reset() {
c.count = 0
}
/*
For position independence across international keyboard layouts, typewriter keys are read using scancodes (which are always set 1).
Windows provides the scancodes directly in the LPARAM.
GTK+ provides the scancodes directly from the underlying window system via GdkEventKey.hardware_keycode.
On X11, this is scancode + 8 (because X11 keyboard codes have a range of [8,255]).
Wayland is guaranteed to give the same result (thanks ebassi in irc.gimp.net/#gtk+).
On Linux, where evdev is used instead of polling scancodes directly from the keyboard, evdev's typewriter section key code constants are the same as scancodes anyway, so the rules above apply.
Typewriter section scancodes are the same across international keyboards with some exceptions that have been accounted for (see KeyEvent's documentation); see http://www.quadibloc.com/comp/scan.htm for details.
Non-typewriter keys can be handled safely using constants provided by the respective backend API.
Because GTK+ keysyms may or may not obey Num Lock, we also handle the 0-9 and . keys on the numeric keypad with scancodes (they match too).
*/
// use uintptr to be safe; the size of the scancode/hardware key code field on each platform is different
var scancodeKeys = map[uintptr]byte{
0x02: '1',
0x03: '2',
0x04: '3',
0x05: '4',
0x06: '5',
0x07: '6',
0x08: '7',
0x09: '8',
0x0A: '9',
0x0B: '0',
0x0C: '-',
0x0D: '=',
0x0E: '\b', // seems to be safe on GTK+; TODO safe on windows?
0x0F: '\t', // seems to be safe on GTK+; TODO safe on windows?
0x10: 'q',
0x11: 'w',
0x12: 'e',
0x13: 'r',
0x14: 't',
0x15: 'y',
0x16: 'u',
0x17: 'i',
0x18: 'o',
0x19: 'p',
0x1A: '[',
0x1B: ']',
0x1C: '\n', // seems to be safe on GTK+; TODO safe on windows?
0x1E: 'a',
0x1F: 's',
0x20: 'd',
0x21: 'f',
0x22: 'g',
0x23: 'h',
0x24: 'j',
0x25: 'k',
0x26: 'l',
0x27: ';',
0x28: '\'',
0x29: '`',
0x2B: '\\',
0x2C: 'z',
0x2D: 'x',
0x2E: 'c',
0x2F: 'v',
0x30: 'b',
0x31: 'n',
0x32: 'm',
0x33: ',',
0x34: '.',
0x35: '/',
0x39: ' ',
}
var scancodeExtKeys = map[uintptr]ExtKey{
0x47: N7,
0x48: N8,
0x49: N9,
0x4B: N4,
0x4C: N5,
0x4D: N6,
0x4F: N1,
0x50: N2,
0x51: N3,
0x52: N0,
0x53: NDot,
}
func fromScancode(scancode uintptr) (ke KeyEvent, ok bool) {
if key, ok := scancodeKeys[scancode]; ok {
ke.Key = key
return ke, true
}
if extkey, ok := scancodeExtKeys[scancode]; ok {
ke.ExtKey = extkey
return ke, true
}
return ke, false
}