#region Copyright & License Information /* * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion using System; using System.Runtime.InteropServices; using System.Text; using SDL2; namespace OpenRA.Platforms.Default { class Sdl2Input { MouseButton lastButtonBits = MouseButton.None; public string GetClipboardText() { return SDL.SDL_GetClipboardText(); } public bool SetClipboardText(string text) { return SDL.SDL_SetClipboardText(text) == 0; } static MouseButton MakeButton(byte b) { return b == SDL.SDL_BUTTON_LEFT ? MouseButton.Left : b == SDL.SDL_BUTTON_RIGHT ? MouseButton.Right : b == SDL.SDL_BUTTON_MIDDLE ? MouseButton.Middle : 0; } static Modifiers MakeModifiers(int raw) { return ((raw & (int)SDL.SDL_Keymod.KMOD_ALT) != 0 ? Modifiers.Alt : 0) | ((raw & (int)SDL.SDL_Keymod.KMOD_CTRL) != 0 ? Modifiers.Ctrl : 0) | ((raw & (int)SDL.SDL_Keymod.KMOD_LGUI) != 0 ? Modifiers.Meta : 0) | ((raw & (int)SDL.SDL_Keymod.KMOD_RGUI) != 0 ? Modifiers.Meta : 0) | ((raw & (int)SDL.SDL_Keymod.KMOD_SHIFT) != 0 ? Modifiers.Shift : 0); } public void PumpInput(IInputHandler inputHandler) { var mods = MakeModifiers((int)SDL.SDL_GetModState()); var scrollDelta = 0; inputHandler.ModifierKeys(mods); MouseInput? pendingMotion = null; SDL.SDL_Event e; while (SDL.SDL_PollEvent(out e) != 0) { switch (e.type) { case SDL.SDL_EventType.SDL_QUIT: Game.Exit(); break; case SDL.SDL_EventType.SDL_WINDOWEVENT: { switch (e.window.windowEvent) { case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST: Game.HasInputFocus = false; break; case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED: Game.HasInputFocus = true; break; } break; } case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN: { if (pendingMotion != null) { inputHandler.OnMouseInput(pendingMotion.Value); pendingMotion = null; } var button = MakeButton(e.button.button); lastButtonBits |= button; var pos = new int2(e.button.x, e.button.y); inputHandler.OnMouseInput(new MouseInput( MouseInputEvent.Down, button, scrollDelta, pos, mods, MultiTapDetection.DetectFromMouse(e.button.button, pos))); break; } case SDL.SDL_EventType.SDL_MOUSEBUTTONUP: { if (pendingMotion != null) { inputHandler.OnMouseInput(pendingMotion.Value); pendingMotion = null; } var button = MakeButton(e.button.button); lastButtonBits &= ~button; var pos = new int2(e.button.x, e.button.y); inputHandler.OnMouseInput(new MouseInput( MouseInputEvent.Up, button, scrollDelta, pos, mods, MultiTapDetection.InfoFromMouse(e.button.button))); break; } case SDL.SDL_EventType.SDL_MOUSEMOTION: { pendingMotion = new MouseInput( MouseInputEvent.Move, lastButtonBits, scrollDelta, new int2(e.motion.x, e.motion.y), mods, 0); break; } case SDL.SDL_EventType.SDL_MOUSEWHEEL: { int x, y; SDL.SDL_GetMouseState(out x, out y); scrollDelta = e.wheel.y; inputHandler.OnMouseInput(new MouseInput(MouseInputEvent.Scroll, MouseButton.None, scrollDelta, new int2(x, y), Modifiers.None, 0)); break; } case SDL.SDL_EventType.SDL_TEXTINPUT: { var rawBytes = new byte[SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE]; unsafe { Marshal.Copy((IntPtr)e.text.text, rawBytes, 0, SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE); } inputHandler.OnTextInput(Encoding.UTF8.GetString(rawBytes, 0, Array.IndexOf(rawBytes, (byte)0))); break; } case SDL.SDL_EventType.SDL_KEYDOWN: case SDL.SDL_EventType.SDL_KEYUP: { var keyCode = (Keycode)e.key.keysym.sym; var type = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? KeyInputEvent.Down : KeyInputEvent.Up; var tapCount = e.type == SDL.SDL_EventType.SDL_KEYDOWN ? MultiTapDetection.DetectFromKeyboard(keyCode) : MultiTapDetection.InfoFromKeyboard(keyCode); var keyEvent = new KeyInput { Event = type, Key = keyCode, Modifiers = mods, UnicodeChar = (char)e.key.keysym.sym, MultiTapCount = tapCount }; // Special case workaround for windows users if (e.key.keysym.sym == SDL.SDL_Keycode.SDLK_F4 && mods.HasModifier(Modifiers.Alt) && Platform.CurrentPlatform == PlatformType.Windows) Game.Exit(); else { // Only register initial key press if (e.key.repeat == 0) inputHandler.OnKeyInput(keyEvent); } break; } } } if (pendingMotion != null) { inputHandler.OnMouseInput(pendingMotion.Value); pendingMotion = null; } OpenGL.CheckGLError(); } } }