From 8b91c939167f938cb4d7b7def9bf47ca25895ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 17 Jul 2022 01:57:28 -0300 Subject: [PATCH] Improved multi-window support. --- include/eepp/window/engine.hpp | 6 ++- include/eepp/window/input.hpp | 5 ++- include/eepp/window/inputevent.hpp | 3 ++ include/eepp/window/window.hpp | 5 +++ projects/linux/ee.creator.user | 4 +- src/eepp/window/backend/SDL2/inputsdl2.cpp | 44 ++++++++++++++++++++- src/eepp/window/backend/SDL2/windowsdl2.cpp | 22 +++++++++++ src/eepp/window/backend/SDL2/windowsdl2.hpp | 9 +++++ src/eepp/window/engine.cpp | 31 ++++++++++----- src/eepp/window/input.cpp | 20 ++++++---- src/eepp/window/window.cpp | 7 ++++ src/tools/ecode/ecode.cpp | 14 +++---- 12 files changed, 140 insertions(+), 30 deletions(-) diff --git a/include/eepp/window/engine.hpp b/include/eepp/window/engine.hpp index 89448f6be..d8500a866 100644 --- a/include/eepp/window/engine.hpp +++ b/include/eepp/window/engine.hpp @@ -51,6 +51,10 @@ class EE_API Engine { /** @return If the window instance is inside the window list. */ bool existsWindow( EE::Window::Window* window ); + void forEachWindow( std::function cb ); + + EE::Window::Window* getWindowID( const Uint32& winID ); + /** Constructs WindowSettings from an ini file It will search for the following properties: Width Window width @@ -145,7 +149,7 @@ class EE_API Engine { friend class Window; Backend::WindowBackendLibrary* mBackend; - std::list mWindows; + std::map mWindows; EE::Window::Window* mWindow; bool mSharedGLContext; Uint32 mMainThreadId; diff --git a/include/eepp/window/input.hpp b/include/eepp/window/input.hpp index 3c5da0475..c71ab85c4 100644 --- a/include/eepp/window/input.hpp +++ b/include/eepp/window/input.hpp @@ -229,6 +229,9 @@ class EE_API Input { /** @return the state of the mod keys. */ const Uint32& getModState() const; + /** Process an input event. Called by the input update. */ + void processEvent( InputEvent* Event ); + protected: friend class Window; @@ -263,8 +266,6 @@ class EE_API Input { std::map mCallbacks; - void processEvent( InputEvent* Event ); - InputFinger* getFingerId( const Int64& fingerId ); void resetFingerWasDown(); diff --git a/include/eepp/window/inputevent.hpp b/include/eepp/window/inputevent.hpp index 422584094..0058c2e19 100644 --- a/include/eepp/window/inputevent.hpp +++ b/include/eepp/window/inputevent.hpp @@ -203,6 +203,9 @@ class InputEvent { /** Event Type */ Uint32 Type; + /** Window ID */ + Uint32 WinID{ 0 }; + /** General event structure */ union { WindowEvent window; diff --git a/include/eepp/window/window.hpp b/include/eepp/window/window.hpp index ce06c59c4..3520a943c 100644 --- a/include/eepp/window/window.hpp +++ b/include/eepp/window/window.hpp @@ -163,6 +163,11 @@ class EE_API Window { /** Creates a new window and GL context */ virtual bool create( WindowSettings Settings, ContextSettings Context ) = 0; + /** Bind the OpenGL context to the current window */ + virtual void makeCurrent() = 0; + + virtual Uint32 getWindowID() = 0; + /** Toogle the screen to Fullscreen, if it's in fullscreen toogle to windowed mode. */ virtual void toggleFullscreen() = 0; diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index b7fea2840..94f75dac1 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -109,7 +109,7 @@ {388e5431-b31b-42b3-b9ad-9002d279d75d} 10 0 - 19 + 16 ../../make/linux diff --git a/src/eepp/window/backend/SDL2/inputsdl2.cpp b/src/eepp/window/backend/SDL2/inputsdl2.cpp index baca2d214..5a068e1a6 100644 --- a/src/eepp/window/backend/SDL2/inputsdl2.cpp +++ b/src/eepp/window/backend/SDL2/inputsdl2.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace EE { namespace Window { namespace Backend { namespace SDL2 { @@ -119,65 +120,76 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { switch ( SDLEvent.window.event ) { case SDL_WINDOWEVENT_RESIZED: { event.Type = InputEvent::VideoResize; + event.WinID = SDLEvent.window.windowID; event.resize.w = SDLEvent.window.data1 * mDPIScale; event.resize.h = SDLEvent.window.data2 * mDPIScale; break; } case SDL_WINDOWEVENT_HIT_TEST: { event.Type = InputEvent::Window; + event.WinID = SDLEvent.window.windowID; event.window.gain = 1; event.window.type = InputEvent::WindowHitTest; break; } case SDL_WINDOWEVENT_TAKE_FOCUS: { event.Type = InputEvent::VideoExpose; + event.WinID = SDLEvent.window.windowID; event.expose.type = event.Type; break; } case SDL_WINDOWEVENT_CLOSE: { event.Type = InputEvent::Window; event.window.gain = 0; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowClose; break; } case SDL_WINDOWEVENT_SIZE_CHANGED: { event.Type = InputEvent::Window; event.window.gain = 1; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowSizeChanged; break; } case SDL_WINDOWEVENT_MAXIMIZED: { event.Type = InputEvent::Window; event.window.gain = 1; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowMaximized; break; } case SDL_WINDOWEVENT_EXPOSED: { event.Type = InputEvent::VideoExpose; + event.WinID = SDLEvent.window.windowID; event.expose.type = event.Type; break; } case SDL_WINDOWEVENT_MOVED: { event.Type = InputEvent::Window; event.window.gain = 1; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowMoved; break; } case SDL_WINDOWEVENT_SHOWN: { event.Type = InputEvent::Window; event.window.gain = 1; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowShown; break; } case SDL_WINDOWEVENT_HIDDEN: { event.Type = InputEvent::Window; event.window.gain = 0; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowHidden; break; } case SDL_WINDOWEVENT_MINIMIZED: { event.Type = InputEvent::Window; event.window.gain = 0; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowMinimized; break; } @@ -190,24 +202,28 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { case SDL_WINDOWEVENT_ENTER: { event.Type = InputEvent::Window; event.window.gain = 1; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowMouseEnter; break; } case SDL_WINDOWEVENT_LEAVE: { event.Type = InputEvent::Window; event.window.gain = 0; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowMouseLeave; break; } case SDL_WINDOWEVENT_FOCUS_GAINED: { event.Type = InputEvent::Window; event.window.gain = 1; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowKeyboardFocusGain; break; } case SDL_WINDOWEVENT_FOCUS_LOST: { event.Type = InputEvent::Window; event.window.gain = 0; + event.WinID = SDLEvent.window.windowID; event.window.type = InputEvent::WindowKeyboardFocusLost; break; } @@ -219,6 +235,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { String txt = String::fromUtf8( SDLEvent.text.text ); event.Type = InputEvent::TextInput; event.text.timestamp = SDLEvent.text.timestamp; + event.WinID = SDLEvent.text.windowID; event.text.text = txt[0]; break; } @@ -230,6 +247,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.key.keysym.scancode = (Scancode)SDLEvent.key.keysym.scancode; event.key.keysym.mod = SDLEvent.key.keysym.mod; event.key.keysym.unicode = 0; + event.WinID = SDLEvent.key.windowID; break; } case SDL_KEYUP: { @@ -240,6 +258,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.key.keysym.scancode = (Scancode)SDLEvent.key.keysym.scancode; event.key.keysym.mod = SDLEvent.key.keysym.mod; event.key.keysym.unicode = 0; + event.WinID = SDLEvent.key.windowID; break; } case SDL_MOUSEMOTION: { @@ -250,6 +269,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.motion.y = SDLEvent.motion.y * mDPIScale; event.motion.xrel = SDLEvent.motion.xrel * mDPIScale; event.motion.yrel = SDLEvent.motion.yrel * mDPIScale; + event.WinID = SDLEvent.motion.windowID; break; } case SDL_MOUSEBUTTONDOWN: { @@ -259,6 +279,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.button.state = SDLEvent.button.state; event.button.x = SDLEvent.button.x; event.button.y = SDLEvent.button.y; + event.WinID = SDLEvent.button.windowID; break; } case SDL_MOUSEBUTTONUP: { @@ -268,6 +289,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.button.state = SDLEvent.button.state; event.button.x = SDLEvent.button.x; event.button.y = SDLEvent.button.y; + event.WinID = SDLEvent.button.windowID; break; } case SDL_MOUSEWHEEL: { @@ -296,6 +318,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.button.x = x; event.button.y = y; event.button.which = SDLEvent.wheel.windowID; + event.WinID = SDLEvent.wheel.windowID; event.Type = InputEvent::MouseButtonDown; event.button.state = 1; @@ -315,6 +338,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.finger.dx = SDLEvent.tfinger.dx; event.finger.dy = SDLEvent.tfinger.dy; event.finger.pressure = SDLEvent.tfinger.pressure; + event.WinID = SDLEvent.tfinger.windowID; break; } case SDL_FINGERDOWN: { @@ -326,6 +350,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.finger.y = SDLEvent.tfinger.y; event.finger.dx = SDLEvent.tfinger.dx; event.finger.dy = SDLEvent.tfinger.dy; + event.WinID = SDLEvent.tfinger.windowID; event.finger.pressure = SDLEvent.tfinger.pressure; break; } @@ -338,6 +363,7 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.finger.y = SDLEvent.tfinger.y; event.finger.dx = SDLEvent.tfinger.dx; event.finger.dy = SDLEvent.tfinger.dy; + event.WinID = SDLEvent.tfinger.windowID; event.finger.pressure = SDLEvent.tfinger.pressure; break; } @@ -390,11 +416,13 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { case SDL_DROPFILE: { event.Type = InputEvent::FileDropped; event.file.file = SDLEvent.drop.file; + event.WinID = SDLEvent.drop.windowID; break; } case SDL_DROPTEXT: { event.Type = InputEvent::TextDropped; event.textdrop.text = SDLEvent.drop.file; + event.WinID = SDLEvent.drop.windowID; break; } default: { @@ -404,13 +432,25 @@ void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { event.user.code = SDLEvent.user.code; event.user.data1 = SDLEvent.user.data1; event.user.data2 = SDLEvent.user.data2; + event.WinID = SDLEvent.user.windowID; } else { event.Type = InputEvent::NoEvent; } } } - if ( InputEvent::NoEvent != event.Type ) - processEvent( &event ); + + EE::Window::Window* win; + + if ( InputEvent::NoEvent != event.Type ) { + if ( event.WinID == mWindow->getWindowID() || event.WinID == 0 ) { + processEvent( &event ); + } else if ( ( win = Engine::instance()->getWindowID( event.WinID ) ) ) { + win->getInput()->processEvent( &event ); + } else { + processEvent( &event ); + } + } + if ( InputEvent::FileDropped == event.Type || InputEvent::TextDropped == event.Type ) SDL_free( SDLEvent.drop.file ); } diff --git a/src/eepp/window/backend/SDL2/windowsdl2.cpp b/src/eepp/window/backend/SDL2/windowsdl2.cpp index 23a055e8a..c2b5e2817 100644 --- a/src/eepp/window/backend/SDL2/windowsdl2.cpp +++ b/src/eepp/window/backend/SDL2/windowsdl2.cpp @@ -379,6 +379,8 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) { SDL_GL_MakeCurrent( mSDLWindow, mGLContext ); + mID = SDL_GetWindowID( mSDLWindow ); + #ifdef EE_USE_WMINFO mWMinfo = eeNew( WMInfo, ( mSDLWindow ) ); #endif @@ -418,6 +420,26 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) { return true; } +Uint32 WindowSDL::getWindowID() { + return mID; +} + +void WindowSDL::makeCurrent() { + SDL_GL_MakeCurrent( mSDLWindow, mGLContext ); +} + +void WindowSDL::close() { + SDL_DestroyWindow( mSDLWindow ); + mSDLWindow = NULL; + mGLContext = NULL; + mGLContextThread = NULL; + Window::close(); +} + +void WindowSDL::setCurrent() { + makeCurrent(); +} + bool WindowSDL::isThreadedGLContext() { #ifdef SDL2_THREADED_GLCONTEXT return mWindow.ContextConfig.SharedGLContext; diff --git a/src/eepp/window/backend/SDL2/windowsdl2.hpp b/src/eepp/window/backend/SDL2/windowsdl2.hpp index 547b16fa5..56d76aca6 100644 --- a/src/eepp/window/backend/SDL2/windowsdl2.hpp +++ b/src/eepp/window/backend/SDL2/windowsdl2.hpp @@ -25,6 +25,14 @@ class EE_API WindowSDL : public Window { bool create( WindowSettings Settings, ContextSettings Context ); + Uint32 getWindowID(); + + void makeCurrent(); + + void close(); + + void setCurrent(); + void toggleFullscreen(); void setTitle( const std::string& title ); @@ -100,6 +108,7 @@ class EE_API WindowSDL : public Window { SDL_GLContext mGLContext; SDL_GLContext mGLContextThread; Mutex mGLContextMutex; + Uint32 mID{ 0 }; #ifdef EE_USE_WMINFO WMInfo* mWMinfo; diff --git a/src/eepp/window/engine.cpp b/src/eepp/window/engine.cpp index ddc05a08d..64ed329e1 100644 --- a/src/eepp/window/engine.cpp +++ b/src/eepp/window/engine.cpp @@ -113,12 +113,12 @@ Engine::~Engine() { } void Engine::destroy() { - std::list::iterator it; - - for ( it = mWindows.begin(); it != mWindows.end(); ++it ) { - eeSAFE_DELETE( *it ); + for ( auto& it : mWindows ) { + eeSAFE_DELETE( it.second ); } + mWindows.clear(); + mWindow = NULL; } @@ -172,7 +172,7 @@ EE::Window::Window* Engine::createWindow( WindowSettings Settings, ContextSettin setCurrentWindow( window ); - mWindows.push_back( mWindow ); + mWindows.insert( { mWindow->getWindowID(), mWindow } ); PixelDensity::setPixelDensity( Settings.PixelDensity ); @@ -180,11 +180,11 @@ EE::Window::Window* Engine::createWindow( WindowSettings Settings, ContextSettin } void Engine::destroyWindow( EE::Window::Window* window ) { - mWindows.remove( window ); + mWindows.erase( window->getWindowID() ); if ( window == mWindow ) { if ( mWindows.size() > 0 ) { - mWindow = mWindows.back(); + mWindow = mWindows.begin()->second; } else { mWindow = NULL; } @@ -196,14 +196,27 @@ void Engine::destroyWindow( EE::Window::Window* window ) { bool Engine::existsWindow( EE::Window::Window* window ) { std::list::iterator it; - for ( it = mWindows.begin(); it != mWindows.end(); ++it ) { - if ( ( *it ) == window ) + for ( auto& it : mWindows ) { + if ( it.second == window ) return true; } return false; } +void Engine::forEachWindow( std::function cb ) { + for ( auto& it : mWindows ) + cb( it.second ); +} + +EE::Window::Window* Engine::getWindowID( const Uint32& winID ) { + for ( auto& it : mWindows ) { + if ( it.first == winID ) + return it.second; + } + return nullptr; +} + EE::Window::Window* Engine::getCurrentWindow() const { return mWindow; } diff --git a/src/eepp/window/input.cpp b/src/eepp/window/input.cpp index 94e9df8d1..8e3682a68 100644 --- a/src/eepp/window/input.cpp +++ b/src/eepp/window/input.cpp @@ -1,3 +1,4 @@ +#include #include namespace EE { namespace Window { @@ -51,6 +52,8 @@ void Input::sendEvent( InputEvent* Event ) { void Input::processEvent( InputEvent* Event ) { switch ( Event->Type ) { case InputEvent::Window: { + if ( Event->window.type == InputEvent::WindowClose ) + mWindow->onCloseRequest(); break; } case InputEvent::KeyDown: { @@ -152,8 +155,8 @@ void Input::processEvent( InputEvent* Event ) { InputFinger* Finger = getFingerId( Event->finger.fingerId ); Finger->writeLast(); - Finger->x = ( Uint16 )( Event->finger.x * (Float)mWindow->getWidth() ); - Finger->y = ( Uint16 )( Event->finger.y * (Float)mWindow->getHeight() ); + Finger->x = (Uint16)( Event->finger.x * (Float)mWindow->getWidth() ); + Finger->y = (Uint16)( Event->finger.y * (Float)mWindow->getHeight() ); Finger->pressure = Event->finger.pressure; Finger->down = true; Finger->xdelta = Event->finger.dx; @@ -169,8 +172,8 @@ void Input::processEvent( InputEvent* Event ) { InputFinger* Finger = getFingerId( Event->finger.fingerId ); Finger->writeLast(); - Finger->x = ( Uint16 )( Event->finger.x * (Float)mWindow->getWidth() ); - Finger->y = ( Uint16 )( Event->finger.y * (Float)mWindow->getHeight() ); + Finger->x = (Uint16)( Event->finger.x * (Float)mWindow->getWidth() ); + Finger->y = (Uint16)( Event->finger.y * (Float)mWindow->getHeight() ); Finger->pressure = Event->finger.pressure; Finger->down = false; Finger->wasDown = true; @@ -187,8 +190,8 @@ void Input::processEvent( InputEvent* Event ) { InputFinger* Finger = getFingerId( Event->finger.fingerId ); Finger->writeLast(); - Finger->x = ( Uint16 )( Event->finger.x * (Float)mWindow->getWidth() ); - Finger->y = ( Uint16 )( Event->finger.y * (Float)mWindow->getHeight() ); + Finger->x = (Uint16)( Event->finger.x * (Float)mWindow->getWidth() ); + Finger->y = (Uint16)( Event->finger.y * (Float)mWindow->getHeight() ); Finger->pressure = Event->finger.pressure; Finger->down = true; Finger->xdelta = Event->finger.dx; @@ -205,7 +208,10 @@ void Input::processEvent( InputEvent* Event ) { break; } case InputEvent::Quit: { - mWindow->onCloseRequest(); + if ( Engine::isEngineRunning() ) { + Engine::instance()->forEachWindow( + [&]( EE::Window::Window* win ) { win->onCloseRequest(); } ); + } break; } } diff --git a/src/eepp/window/window.cpp b/src/eepp/window/window.cpp index 1ad212fdd..083853d73 100644 --- a/src/eepp/window/window.cpp +++ b/src/eepp/window/window.cpp @@ -186,6 +186,10 @@ void Window::createView() { } void Window::setup2D( const bool& KeepView ) { + EE::Window::Window* curWin = Engine::instance()->getCurrentWindow(); + if ( curWin != this ) + Engine::instance()->setCurrentWindow( this ); + GLi->pixelStorei( GL_UNPACK_ALIGNMENT, 1 ); GLi->pixelStorei( GL_PACK_ALIGNMENT, 1 ); @@ -217,6 +221,9 @@ void Window::setup2D( const bool& KeepView ) { GLi->enableClientState( GL_TEXTURE_COORD_ARRAY ); GLi->enableClientState( GL_COLOR_ARRAY ); } + + if ( curWin != this ) + Engine::instance()->setCurrentWindow( curWin ); } const WindowInfo* Window::getWindowInfo() const { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 608bc0f87..4a378f1ef 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2764,15 +2764,15 @@ void App::createSettingsMenu() { } } ); UIMenuSubMenu* colorSchemeMenu = mSettingsMenu->addSubMenu( - i18n( "color_scheme", "Color Scheme" ), nullptr, createColorSchemeMenu() ); - colorSchemeMenu->addEventListener( Event::OnMenuShow, [&, fileTypeMenu]( const Event* ) { - if ( mFileTypeMenuesCreatedWithHeight != mUISceneNode->getPixelsSize().getHeight() ) { - for ( UIPopUpMenu* menu : mFileTypeMenues ) + i18n( "syntax_color_scheme", "Syntax Color Scheme" ), nullptr, createColorSchemeMenu() ); + colorSchemeMenu->addEventListener( Event::OnMenuShow, [&, colorSchemeMenu]( const Event* ) { + if ( mColorSchemeMenuesCreatedWithHeight != mUISceneNode->getPixelsSize().getHeight() ) { + for ( UIPopUpMenu* menu : mColorSchemeMenues ) menu->close(); - mFileTypeMenues.clear(); - auto* newMenu = createFileTypeMenu(); + mColorSchemeMenues.clear(); + auto* newMenu = createColorSchemeMenu(); newMenu->reloadStyle( true, true ); - fileTypeMenu->setSubMenu( newMenu ); + colorSchemeMenu->setSubMenu( newMenu ); } } ); mSettingsMenu->addSubMenu( i18n( "document", "Document" ), nullptr, createDocumentMenu() )