int2 EventPosition(Sdl2PlatformWindow device, int x, int y)
        {
            // On Windows and Linux (X11) events are given in surface coordinates
            // These must be scaled to our effective window coordinates
            if (Platform.CurrentPlatform != PlatformType.OSX && device.WindowSize != device.SurfaceSize)
            {
                return(new int2((int)(x / device.WindowScale), (int)(y / device.WindowScale)));
            }

            return(new int2(x, y));
        }
        public Sdl2GraphicsContext(Sdl2PlatformWindow window)
        {
            this.window = window;

            // SDL requires us to create the GL context on the main thread to avoid various platform-specific issues.
            // We must then release it from the main thread before we rebind it to the render thread (in InitializeOpenGL below).
            context = SDL.SDL_GL_CreateContext(window.Window);
            if (context == IntPtr.Zero || SDL.SDL_GL_MakeCurrent(window.Window, IntPtr.Zero) < 0)
            {
                throw new InvalidOperationException($"Can not create OpenGL context. (Error: {SDL.SDL_GetError()})");
            }
        }
Example #3
0
        int2 EventPosition(Sdl2PlatformWindow device, int x, int y)
        {
            // On Windows and Linux (X11) events are given in surface coordinates
            // These must be scaled to our effective window coordinates
            // Round fractional components up to avoid rounding small deltas to 0
            if (Platform.CurrentPlatform != PlatformType.OSX && device.EffectiveWindowSize != device.SurfaceSize)
            {
                var s = 1 / device.EffectiveWindowScale;
                return(new int2((int)(Math.Sign(x) / 2f + x * s), (int)(Math.Sign(x) / 2f + y * s)));
            }

            // On macOS we must still account for the user-requested scale modifier
            if (Platform.CurrentPlatform == PlatformType.OSX && device.EffectiveWindowScale != device.NativeWindowScale)
            {
                var s = device.NativeWindowScale / device.EffectiveWindowScale;
                return(new int2((int)(Math.Sign(x) / 2f + x * s), (int)(Math.Sign(x) / 2f + y * s)));
            }

            return(new int2(x, y));
        }
Example #4
0
 public Sdl2GraphicsContext(Sdl2PlatformWindow window)
 {
     this.window = window;
 }
        public void PumpInput(Sdl2PlatformWindow device, 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;

                    // Triggered when moving between displays with different DPI settings
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED:
                        device.WindowSizeChanged();
                        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 = EventPosition(device, 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 = EventPosition(device, 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:
                {
                    var pos = EventPosition(device, e.motion.x, e.motion.y);
                    pendingMotion = new MouseInput(
                        MouseInputEvent.Move, lastButtonBits, scrollDelta,
                        pos, 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), mods, 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,
                        IsRepeat      = e.key.repeat != 0
                    };

                    // 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
                    {
                        inputHandler.OnKeyInput(keyEvent);
                    }

                    break;
                }
                }
            }

            if (pendingMotion != null)
            {
                inputHandler.OnMouseInput(pendingMotion.Value);
                pendingMotion = null;
            }
        }
Example #6
0
        public void PumpInput(Sdl2PlatformWindow device, IInputHandler inputHandler, int2?lockedMousePosition)
        {
            var mods = MakeModifiers((int)SDL.SDL_GetModState());

            inputHandler.ModifierKeys(mods);
            MouseInput?pendingMotion = null;

            while (SDL.SDL_PollEvent(out var e) != 0)
            {
                switch (e.type)
                {
                case SDL.SDL_EventType.SDL_QUIT:
                    // On macOS, we'd like to restrict Cmd + Q from suddenly exiting the game.
                    if (Platform.CurrentPlatform != PlatformType.OSX || !mods.HasModifier(Modifiers.Meta))
                    {
                        Game.Exit();
                    }

                    break;

                case SDL.SDL_EventType.SDL_WINDOWEVENT:
                {
                    switch (e.window.windowEvent)
                    {
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST:
                        device.HasInputFocus = false;
                        break;

                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED:
                        device.HasInputFocus = true;
                        break;

                    // Triggered when moving between displays with different DPI settings
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED:
                        device.WindowSizeChanged();
                        break;

                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_HIDDEN:
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MINIMIZED:
                        device.IsSuspended = true;
                        break;

                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_EXPOSED:
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SHOWN:
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MAXIMIZED:
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESTORED:
                        device.IsSuspended = false;
                        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 input = lockedMousePosition ?? new int2(e.button.x, e.button.y);
                    var pos   = EventPosition(device, input.X, input.Y);

                    inputHandler.OnMouseInput(new MouseInput(
                                                  MouseInputEvent.Down, button, pos, int2.Zero, 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 input = lockedMousePosition ?? new int2(e.button.x, e.button.y);
                    var pos   = EventPosition(device, input.X, input.Y);

                    inputHandler.OnMouseInput(new MouseInput(
                                                  MouseInputEvent.Up, button, pos, int2.Zero, mods,
                                                  MultiTapDetection.InfoFromMouse(e.button.button)));

                    break;
                }

                case SDL.SDL_EventType.SDL_MOUSEMOTION:
                {
                    var mousePos = new int2(e.motion.x, e.motion.y);
                    var input    = lockedMousePosition ?? mousePos;
                    var pos      = EventPosition(device, input.X, input.Y);

                    var delta = lockedMousePosition == null
                                                                ? EventPosition(device, e.motion.xrel, e.motion.yrel)
                                                                : mousePos - lockedMousePosition.Value;

                    pendingMotion = new MouseInput(
                        MouseInputEvent.Move, lastButtonBits, pos, delta, mods, 0);

                    break;
                }

                case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                {
                    SDL.SDL_GetMouseState(out var x, out var y);

                    var pos = EventPosition(device, x, y);
                    inputHandler.OnMouseInput(new MouseInput(MouseInputEvent.Scroll, MouseButton.None, pos, new int2(0, e.wheel.y), mods, 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, mods) :
                                   MultiTapDetection.InfoFromKeyboard(keyCode, mods);

                    var keyEvent = new KeyInput
                    {
                        Event         = type,
                        Key           = keyCode,
                        Modifiers     = mods,
                        UnicodeChar   = (char)e.key.keysym.sym,
                        MultiTapCount = tapCount,
                        IsRepeat      = e.key.repeat != 0
                    };

                    // 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
                    {
                        inputHandler.OnKeyInput(keyEvent);
                    }

                    break;
                }
                }
            }

            if (pendingMotion != null)
            {
                inputHandler.OnMouseInput(pendingMotion.Value);
                pendingMotion = null;
            }
        }