예제 #1
0
func virtualKeyCodeToSF(vkey C.WPARAM, flags C.LPARAM) Key {
	if key, ok := keyboard_vkeys_map[C.int(vkey)]; ok {
		return key
	}

	switch vkey {
	// Check the scancode to distinguish between left and right shift
	case C.VK_SHIFT:
		scancode := C.UINT((flags & (0xFF << 16)) >> 16)
		if scancode == lShift {
			return KeyLShift
		}
		return KeyRShift

	// Check the "extended" flag to distinguish between left and right alt
	case C.VK_MENU:
		if C.__HIWORD(C.DWORD(flags))&C.KF_EXTENDED != 0 {
			return KeyRAlt
		}
		return KeyLAlt

	// Check the "extended" flag to distinguish between left and right control
	case C.VK_CONTROL:
		if C.__HIWORD(C.DWORD(flags))&C.KF_EXTENDED != 0 {
			return KeyRControl
		}
		return KeyLControl

	}

	return KeyUnknown
}
예제 #2
0
func (wi *windowInternal) processEvent(message C.UINT, wParam C.WPARAM, lParam C.LPARAM) (events []Event, eventErrors []ThreadError) {
	// Don't process any message until window is created
	if wi.window.Handle == nil {
		return
	}

	switch message {
	case C.WM_DESTROY: // Destroy event
		// Here we must cleanup resources !
		wi.cleanup()
	case C.WM_ACTIVATE:
		// TODO fullscreen handling
		if wi.monitor == nil || !wi.monitor.IsValid() {
			break
		}

		// Were we deactivated/iconified?
		wi.inactive = C.__LOWORD(C.DWORD(wParam)) == C.WA_INACTIVE
		minimized := C.__HIWORD(C.DWORD(wParam)) != 0

		if (wi.inactive || minimized) && !wi.minimized {
			// _glfwInputDeactivation();

			// If we are in fullscreen mode we need to iconify
			if wi.monitor != nil && wi.monitor.IsValid() {
				// Do we need to manually iconify?
				if err := ChangeDisplaySettingsExW(&wi.monitor.internal.info.szDevice[0], nil, nil, 0, nil); err != nil {
					// TODO: Error handling
					panic(err)
				}

				if !minimized {
					// Minimize window
					// C.SetWindowULong(wi.window.Handle, C.GWL_STYLE, C.WS_POPUP)
					// C.SetWindowLong(wi.window.Handle, C.GWL_EXSTYLE, 0)
					// C.SetWindowPos(wi.window.Handle, HWND_BOTTOM, 1, 1, 10, 10, C.SWP_HIDEWINDOW)
					C.ShowWindow(wi.window.Handle, C.SW_MINIMIZE)
					minimized = true
				}

				// Restore the original desktop resolution
				if err := ChangeDisplaySettingsExW(&wi.monitor.internal.info.szDevice[0], nil, nil, 0, nil); err != nil {
					// TODO: Error handling
					panic(err)
				}

			}

			// Unlock mouse if locked
			// if !_glfwWin.oldMouseLockValid {
			// 	_glfwWin.oldMouseLock = _glfwWin.mouseLock;
			// 	_glfwWin.oldMouseLockValid = GL_TRUE;
			// 	glfwEnable( GLFW_MOUSE_CURSOR );
			// }
		} else if !wi.inactive || !minimized {
			// If we are in fullscreen mode we need to maximize
			if wi.monitor != nil && wi.monitor.IsValid() && wi.minimized {
				// Change display settings to the user selected mode
				if err := ChangeDisplaySettingsExW(&wi.monitor.internal.info.szDevice[0], wi.devMode, nil, C.CDS_FULLSCREEN, nil); err != nil {
					// TODO error handling
					panic(err)
				}

				// Do we need to manually restore window?
				if minimized {
					// Restore window
					C.ShowWindow(wi.window.Handle, C.SW_RESTORE)
					minimized = false

					// Activate window
					C.ShowWindow(wi.window.Handle, C.SW_SHOW)
					// setForegroundWindow( _glfwWin.window );
					C.SetFocus(wi.window.Handle)
				}

				// Lock mouse, if necessary
				// if _glfwWin.oldMouseLockValid && _glfwWin.oldMouseLock {
				// 	glfwDisable( GLFW_MOUSE_CURSOR );
				// }
				// _glfwWin.oldMouseLockValid = GL_FALSE;
			}
		}

		wi.minimized = minimized

	case C.WM_SETCURSOR: // Set cursor event
		// The mouse has moved, if the cursor is in our window we must refresh the cursor
		if C.__LOWORD(C.DWORD(lParam)) == C.HTCLIENT {
			C.SetCursor(wi.cursor)
		}

	case C.WM_CLOSE: // Close event
		events = append(events, WindowClosedEvent{})

	case C.WM_SIZE: // Resize event
		// Consider only events triggered by a maximize or a un-maximize
		if wParam == C.SIZE_MINIMIZED || wi.resizing {
			break
		}

		// Ignore cases where the window has only been moved
		if x, y := wi.getSize(); wi.lastSizeX == x && wi.lastSizeY == y {
			break
		}

		events = append(events, WindowResizeEvent{
			Width:  wi.lastSizeX,
			Height: wi.lastSizeY,
		})

	case C.WM_ENTERSIZEMOVE: // Start resizing
		wi.resizing = true

	case C.WM_EXITSIZEMOVE: // Stop resizing
		wi.resizing = false
		// Ignore cases where the window has only been moved
		if x, y := wi.getSize(); wi.lastSizeX == x && wi.lastSizeY == y {
			break
		} else {
			wi.lastSizeX, wi.lastSizeY = x, y
		}

		events = append(events, WindowResizeEvent{
			Width:  wi.lastSizeX,
			Height: wi.lastSizeY,
		})

	case C.WM_KILLFOCUS: // Lost focus event
		events = append(events, WindowGainedFocusEvent{})

	case C.WM_SETFOCUS: // Gain focus event
		events = append(events, WindowLostFocusEvent{})

	case C.WM_CHAR: // Text event
		if !wi.keyRepeatEnabled && lParam&(1<<30) != 0 {
			break
		}

		events = append(events, TextEnteredEvent{
			Character: rune(wParam),
		})

	case C.WM_KEYDOWN, C.WM_SYSKEYDOWN: // Keydown event
		if !wi.keyRepeatEnabled && C.__HIWORD(C.DWORD(lParam))&C.KF_REPEAT != 0 {
			break
		}

		events = append(events, KeyPressedEvent{
			Code:    virtualKeyCodeToSF(wParam, lParam),
			Alt:     C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_MENU))) != 0,
			Control: C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_CONTROL))) != 0,
			Shift:   C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_SHIFT))) != 0,
			System:  C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_LWIN))) != 0 || C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_RWIN))) != 0,
		})

	case C.WM_KEYUP, C.WM_SYSKEYUP: // Keyup event
		events = append(events, KeyReleasedEvent{
			Code:    virtualKeyCodeToSF(wParam, lParam),
			Alt:     C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_MENU))) != 0,
			Control: C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_CONTROL))) != 0,
			Shift:   C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_SHIFT))) != 0,
			System:  C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_LWIN))) != 0 || C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_RWIN))) != 0,
		})

	case C.WM_MOUSEWHEEL: // Mouse wheel event
		// Mouse position is in screen coordinates, convert it to window coordinates
		position := C.POINT{
			x: C.LONG(C.__LOWORD(C.DWORD(lParam))),
			y: C.LONG(C.__HIWORD(C.DWORD(lParam))),
		}
		C.__ScreenToClient(wi.window.Handle, &position)

		events = append(events, MouseWheelEvent{
			Delta: int(int16(C.__HIWORD(C.DWORD(wParam))) / 120),
			X:     int(position.x),
			Y:     int(position.y),
		})

	case C.WM_LBUTTONDOWN, C.WM_RBUTTONDOWN: // Mouse left/right button down event
		button := mouse_vkeys_handed_map[mouseKey{message, C.GetSystemMetrics(C.SM_SWAPBUTTON) == C.TRUE}]
		events = append(events, MouseButtonPressedEvent{
			Button: button,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_LBUTTONUP, C.WM_RBUTTONUP: // Mouse left/right button up event
		button := mouse_vkeys_handed_map[mouseKey{message, C.GetSystemMetrics(C.SM_SWAPBUTTON) == C.TRUE}]
		events = append(events, MouseButtonReleasedEvent{
			Button: button,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_MBUTTONDOWN: // Mouse wheel button down event
		events = append(events, MouseButtonPressedEvent{
			Button: MouseMiddle,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_MBUTTONUP: // Mouse wheel button up event
		events = append(events, MouseButtonReleasedEvent{
			Button: MouseMiddle,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_XBUTTONDOWN: // Mouse X button down event
		event := MouseButtonPressedEvent{
			X: int(C.__LOWORD(C.DWORD(lParam))),
			Y: int(C.__HIWORD(C.DWORD(lParam))),
		}

		switch C.__HIWORD(C.DWORD(wParam)) {
		default:
			fallthrough
		case C.XBUTTON1:
			event.Button = MouseXButton1
		case C.XBUTTON2:
			event.Button = MouseXButton2

		}
		events = append(events, event)

	case C.WM_XBUTTONUP: // Mouse X button up event
		event := MouseButtonPressedEvent{
			X: int(C.__LOWORD(C.DWORD(lParam))),
			Y: int(C.__HIWORD(C.DWORD(lParam))),
		}

		switch C.__HIWORD(C.DWORD(wParam)) {
		default:
			fallthrough
		case C.XBUTTON1:
			event.Button = MouseXButton1
		case C.XBUTTON2:
			event.Button = MouseXButton2

		}
		events = append(events, event)

	case C.WM_MOUSEMOVE: // Mouse move event
		// Check if we need to generate a MouseEntered event
		if !wi.isCursorIn {
			mouseEvent := C.TRACKMOUSEEVENT{
				cbSize:    C.TRACKMOUSEEVENT_size,
				hwndTrack: wi.window.Handle,
				dwFlags:   C.TME_LEAVE,
			}
			C.__TrackMouseEvent(&mouseEvent)

			wi.isCursorIn = true

			events = append(events, MouseEnteredEvent{})
		}

		events = append(events, MouseMoveEvent{
			X: int(C.__LOWORD(C.DWORD(lParam))),
			Y: int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_MOUSELEAVE: // Mouse leave event
		wi.isCursorIn = false
		events = append(events, MouseLeftEvent{})

	}

	return
}