/** * FreeRDP: A Remote Desktop Protocol Implementation * SDL Client * * Copyright 2022 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include "sdl_window.hpp" #include "sdl_disp.hpp" #include "sdl_clip.hpp" #include "sdl_input.hpp" #include "dialogs/sdl_connection_dialog_wrapper.hpp" class SdlContext { public: enum CursorType { CURSOR_NULL, CURSOR_DEFAULT, CURSOR_IMAGE }; explicit SdlContext(rdpContext* context); SdlContext(const SdlContext& other) = delete; SdlContext(SdlContext&& other) = delete; ~SdlContext() = default; SdlContext& operator=(const SdlContext& other) = delete; SdlContext& operator=(SdlContext&& other) = delete; [[nodiscard]] bool redraw(bool suppress = false) const; void setConnected(bool val); [[nodiscard]] bool isConnected() const; void cleanup(); [[nodiscard]] bool resizeable() const; [[nodiscard]] bool toggleResizeable(); [[nodiscard]] bool setResizeable(bool enable); [[nodiscard]] bool fullscreen() const; [[nodiscard]] bool toggleFullscreen(); [[nodiscard]] bool setFullscreen(bool enter, bool forceOriginalDisplay = false); [[nodiscard]] bool setMinimized(); [[nodiscard]] bool grabMouse() const; [[nodiscard]] bool toggleGrabMouse(); [[nodiscard]] bool setGrabMouse(bool enter); [[nodiscard]] bool grabKeyboard() const; [[nodiscard]] bool toggleGrabKeyboard(); [[nodiscard]] bool setGrabKeyboard(bool enter); [[nodiscard]] rdpContext* context() const; [[nodiscard]] rdpClientContext* common() const; [[nodiscard]] bool setCursor(CursorType type); [[nodiscard]] bool setCursor(rdpPointer* cursor); [[nodiscard]] rdpPointer* cursor() const; [[nodiscard]] bool restoreCursor(); void setMonitorIds(const std::vector& ids); [[nodiscard]] const std::vector& monitorIds() const; [[nodiscard]] int64_t monitorId(uint32_t index) const; void push(std::vector&& rects); [[nodiscard]] std::vector pop(); void setHasCursor(bool val); [[nodiscard]] bool hasCursor() const; void setMetadata(); [[nodiscard]] int start(); [[nodiscard]] int join(); [[nodiscard]] bool shallAbort(bool ignoreDialogs = false); [[nodiscard]] bool createWindows(); [[nodiscard]] bool updateWindowList(); [[nodiscard]] bool updateWindow(SDL_WindowID id); [[nodiscard]] bool drawToWindows(const std::vector& rects = {}); [[nodiscard]] bool drawToWindow(SdlWindow& window, const std::vector& rects = {}); [[nodiscard]] bool minimizeAllWindows(); [[nodiscard]] int exitCode() const; [[nodiscard]] SDL_PixelFormat pixelFormat() const; [[nodiscard]] const SdlWindow* getWindowForId(SDL_WindowID id) const; [[nodiscard]] SdlWindow* getWindowForId(SDL_WindowID id); [[nodiscard]] SdlWindow* getFirstWindow(); [[nodiscard]] bool addDisplayWindow(SDL_DisplayID id); [[nodiscard]] bool removeDisplayWindow(SDL_DisplayID id); [[nodiscard]] bool detectDisplays(); [[nodiscard]] rdpMonitor getDisplay(SDL_DisplayID id) const; [[nodiscard]] std::vector getDisplayIds() const; [[nodiscard]] sdlDispContext& getDisplayChannelContext(); [[nodiscard]] sdlInput& getInputChannelContext(); [[nodiscard]] sdlClip& getClipboardChannelContext(); [[nodiscard]] SdlConnectionDialogWrapper& getDialog(); [[nodiscard]] wLog* getWLog(); [[nodiscard]] bool moveMouseTo(const SDL_FPoint& pos); [[nodiscard]] SDL_FPoint screenToPixel(SDL_WindowID id, const SDL_FPoint& pos); [[nodiscard]] SDL_FPoint pixelToScreen(SDL_WindowID id, const SDL_FPoint& pos); [[nodiscard]] SDL_FRect pixelToScreen(SDL_WindowID id, const SDL_FRect& pos); [[nodiscard]] bool handleEvent(const SDL_Event& ev); private: [[nodiscard]] static BOOL preConnect(freerdp* instance); [[nodiscard]] static BOOL postConnect(freerdp* instance); static void postDisconnect(freerdp* instance); static void postFinalDisconnect(freerdp* instance); [[nodiscard]] static BOOL desktopResize(rdpContext* context); [[nodiscard]] static BOOL playSound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound); [[nodiscard]] static BOOL beginPaint(rdpContext* context); [[nodiscard]] static BOOL endPaint(rdpContext* context); [[nodiscard]] static DWORD WINAPI rdpThreadRun(SdlContext* sdl); [[nodiscard]] bool eventToPixelCoordinates(SDL_WindowID id, SDL_Event& ev); [[nodiscard]] SDL_FPoint applyLocalScaling(const SDL_FPoint& val) const; void removeLocalScaling(float& x, float& y) const; [[nodiscard]] bool handleEvent(const SDL_WindowEvent& ev); [[nodiscard]] bool handleEvent(const SDL_DisplayEvent& ev); [[nodiscard]] bool handleEvent(const SDL_MouseButtonEvent& ev); [[nodiscard]] bool handleEvent(const SDL_MouseMotionEvent& ev); [[nodiscard]] bool handleEvent(const SDL_MouseWheelEvent& ev); [[nodiscard]] bool handleEvent(const SDL_TouchFingerEvent& ev); void addOrUpdateDisplay(SDL_DisplayID id); void deleteDisplay(SDL_DisplayID id); [[nodiscard]] bool createPrimary(); [[nodiscard]] std::string windowTitle() const; [[nodiscard]] bool waitForWindowsCreated(); void sdl_client_cleanup(int exit_code, const std::string& error_msg); [[nodiscard]] int sdl_client_thread_connect(std::string& error_msg); [[nodiscard]] int sdl_client_thread_run(std::string& error_msg); [[nodiscard]] int error_info_to_error(DWORD* pcode, char** msg, size_t* len) const; void applyMonitorOffset(SDL_WindowID window, float& x, float& y) const; [[nodiscard]] std::vector updateDisplayOffsetsForNeighbours(SDL_DisplayID id, const std::vector& ignore = {}); void updateMonitorDataFromOffsets(); rdpContext* _context = nullptr; wLog* _log = nullptr; std::atomic _connected = false; bool _cursor_visible = true; rdpPointer* _cursor = nullptr; CursorType _cursorType = CURSOR_NULL; std::vector _monitorIds; std::mutex _queue_mux; std::queue> _queue; /* SDL */ bool _fullscreen = false; bool _resizeable = false; bool _grabMouse = false; bool _grabKeyboard = false; int _exitCode = -1; std::atomic _rdpThreadRunning = false; SDL_PixelFormat _sdlPixelFormat = SDL_PIXELFORMAT_UNKNOWN; CriticalSection _critical; using SDLSurfacePtr = std::unique_ptr; SDLSurfacePtr _primary; SDL_FPoint _localScale{ 1.0f, 1.0f }; sdlDispContext _disp; sdlInput _input; sdlClip _clip; SdlConnectionDialogWrapper _dialog; std::map _displays; std::map _windows; std::map> _offsets; uint32_t _windowWidth = 0; uint32_t _windowHeigth = 0; WinPREvent _windowsCreatedEvent; std::thread _thread; };