diff --git a/TODO.md b/TODO.md index efcb5dbbc..db1c382f8 100644 --- a/TODO.md +++ b/TODO.md @@ -13,18 +13,6 @@ * Add XML tags auto-close. -## Code Editor - -* Support single instance (when a new file is opened while a previous instance exists, open it in the first instance). - -* Search and replace only over selection. - -## UI Editor - -* Integrate the `UICodeEditor` into the editor in order to be able to edit the layouts and CSS in app. - -* Once `UITreeView` is finished add a tree view inspecto of the node tree. - ## StyleSheetParser Detect errors and log them. @@ -33,4 +21,20 @@ Detect errors and log them. Implement a simple tree view widget, to at least cover the most common use cases. +## Code Editor +* Support single instance (when a new file is opened while a previous instance exists, open it in the first instance). + +* Add auto-completion. + +* Once `UITreeView` is finished add a directory/project tree view. + +## UI Editor + +* Integrate the `UICodeEditor` into the editor in order to be able to edit the layouts and CSS in app. + +* Once `UITreeView` is finished add a tree view inspector of the node tree. + +# Log + +* Add log levels. diff --git a/include/eepp/system/luapattern.hpp b/include/eepp/system/luapattern.hpp index 1b4534e4a..4ad8b210d 100644 --- a/include/eepp/system/luapattern.hpp +++ b/include/eepp/system/luapattern.hpp @@ -20,8 +20,8 @@ class EE_API LuaPattern { LuaPattern( const std::string& pattern ); - bool matches( const char* stringSearch, int stringStartOffset, - LuaPattern::Match* matchList, size_t stringLength ); + bool matches( const char* stringSearch, int stringStartOffset, LuaPattern::Match* matchList, + size_t stringLength ); bool matches( const std::string& str, LuaPattern::Match* matchList, int stringStartOffset = 0 ) { @@ -38,8 +38,7 @@ class EE_API LuaPattern { int getNumMatches(); - bool range( int indexGet, int& startMatch, int& endMatch, - LuaPattern::Match* returnedMatched ); + bool range( int indexGet, int& startMatch, int& endMatch, LuaPattern::Match* returnedMatched ); protected: std::string mErr; diff --git a/include/eepp/ui/uimenu.hpp b/include/eepp/ui/uimenu.hpp index 1113955bb..da02337af 100644 --- a/include/eepp/ui/uimenu.hpp +++ b/include/eepp/ui/uimenu.hpp @@ -16,7 +16,7 @@ class EE_API UIMenu : public UIWidget { static UIMenu* New(); static void findBestMenuPos( Vector2f& position, UIMenu* menu, UIMenu* parent = NULL, - UIMenuSubMenu* subMenu = NULL ); + UIMenuSubMenu* subMenu = NULL ); UIMenu(); @@ -82,6 +82,8 @@ class EE_API UIMenu : public UIWidget { void backpropagateHide(); + const Clock& getInactiveTime() const; + protected: friend class UIMenuItem; friend class UIMenuCheckBox; diff --git a/include/eepp/window/input.hpp b/include/eepp/window/input.hpp index d2cd7c6ce..3c5da0475 100644 --- a/include/eepp/window/input.hpp +++ b/include/eepp/window/input.hpp @@ -23,6 +23,11 @@ class EE_API Input { /** Update the Input */ virtual void update() = 0; + /** If timeout is zero waits indefinitely for the next available event otherwise waits until the + * specified timeout for the next available event. + */ + virtual void waitEvent( const Time& timeout = Time::Zero ) = 0; + /** @return If the mouse and keyboard are grabed. */ virtual bool grabInput() = 0; diff --git a/src/eepp/system/luapattern.cpp b/src/eepp/system/luapattern.cpp index 921006faf..d6d32acfa 100644 --- a/src/eepp/system/luapattern.cpp +++ b/src/eepp/system/luapattern.cpp @@ -21,8 +21,7 @@ std::string LuaPattern::match( const std::string& string, const std::string& pat return ""; } -LuaPattern::Match LuaPattern::find( const std::string& string, - const std::string& pattern ) { +LuaPattern::Match LuaPattern::find( const std::string& string, const std::string& pattern ) { LuaPattern matcher( pattern ); int start = 0, end = 0; if ( matcher.find( string, start, end ) ) @@ -38,7 +37,7 @@ LuaPattern::LuaPattern( const std::string& pattern ) : mPattern( pattern ) { } bool LuaPattern::matches( const char* stringSearch, int stringStartOffset, - LuaPattern::Match* matchList, size_t stringLength ) { + LuaPattern::Match* matchList, size_t stringLength ) { LuaPattern::Match matchesBuffer[MAX_DEFAULT_MATCHES]; if ( matchList == NULL ) matchList = matchesBuffer; @@ -55,7 +54,7 @@ bool LuaPattern::matches( const char* stringSearch, int stringStartOffset, } bool LuaPattern::find( const char* stringSearch, int& startMatch, int& endMatch, - int stringStartOffset, int stringLength, int returnMatchIndex ) { + int stringStartOffset, int stringLength, int returnMatchIndex ) { LuaPattern::Match matchesBuffer[MAX_DEFAULT_MATCHES]; if ( matches( stringSearch, stringStartOffset, matchesBuffer, stringLength ) ) { range( returnMatchIndex, startMatch, endMatch, matchesBuffer ); @@ -68,7 +67,7 @@ bool LuaPattern::find( const char* stringSearch, int& startMatch, int& endMatch, } bool LuaPattern::range( int indexGet, int& startMatch, int& endMatch, - LuaPattern::Match* returnedMatched ) { + LuaPattern::Match* returnedMatched ) { if ( indexGet == -1 ) { indexGet = getNumMatches() > 1 ? 1 : 0; } diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index a4d59bed0..f2d273799 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -319,7 +319,10 @@ bool TextDocument::save( IOStream& stream ) { } if ( mForceNewLineAtEndOfFile && !text.empty() && text[text.size() - 1] != '\n' ) { text += "\n"; - textInput( "\n" ); + mLines.emplace_back( TextDocumentLine( "\n" ) ); + notifyTextChanged(); + notifyLineChanged( i ); + notifyLineCountChanged( lastLine, lastLine + 1 ); } } if ( mLineEnding == LineEnding::CRLF ) { diff --git a/src/eepp/ui/uimenu.cpp b/src/eepp/ui/uimenu.cpp index eac13d194..22e66537a 100644 --- a/src/eepp/ui/uimenu.cpp +++ b/src/eepp/ui/uimenu.cpp @@ -452,6 +452,10 @@ void UIMenu::backpropagateHide() { } } +const Clock& UIMenu::getInactiveTime() const { + return mInactiveTime; +} + void UIMenu::nextSel() { if ( mItems.size() ) { if ( mItemSelectedIndex != eeINDEX_NOT_FOUND ) { @@ -624,6 +628,8 @@ void UIMenu::onVisibilityChange() { } else { unsubscribeScheduledUpdate(); } + } else { + mInactiveTime.restart(); } } diff --git a/src/eepp/window/backend/SDL2/inputsdl2.cpp b/src/eepp/window/backend/SDL2/inputsdl2.cpp index a1ec1014c..aa751a356 100644 --- a/src/eepp/window/backend/SDL2/inputsdl2.cpp +++ b/src/eepp/window/backend/SDL2/inputsdl2.cpp @@ -20,324 +20,36 @@ InputSDL::~InputSDL() {} void InputSDL::update() { SDL_Event SDLEvent; - InputEvent EEEvent; - cleanStates(); - - while ( SDL_PollEvent( &SDLEvent ) ) { - switch ( SDLEvent.type ) { - case SDL_WINDOWEVENT: { - switch ( SDLEvent.window.event ) { - case SDL_WINDOWEVENT_RESIZED: { - EEEvent.Type = InputEvent::VideoResize; - EEEvent.resize.w = SDLEvent.window.data1 * mDPIScale; - EEEvent.resize.h = SDLEvent.window.data2 * mDPIScale; - break; - } - case SDL_WINDOWEVENT_HIT_TEST: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowHitTest; - break; - } - case SDL_WINDOWEVENT_TAKE_FOCUS: { - EEEvent.Type = InputEvent::VideoExpose; - EEEvent.expose.type = EEEvent.Type; - break; - } - case SDL_WINDOWEVENT_CLOSE: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 0; - EEEvent.window.type = InputEvent::WindowClose; - break; - } - case SDL_WINDOWEVENT_SIZE_CHANGED: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowSizeChanged; - break; - } - case SDL_WINDOWEVENT_MAXIMIZED: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowMaximized; - break; - } - case SDL_WINDOWEVENT_EXPOSED: { - EEEvent.Type = InputEvent::VideoExpose; - EEEvent.expose.type = EEEvent.Type; - break; - } - case SDL_WINDOWEVENT_MOVED: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowMoved; - break; - } - case SDL_WINDOWEVENT_SHOWN: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowShown; - break; - } - case SDL_WINDOWEVENT_HIDDEN: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 0; - EEEvent.window.type = InputEvent::WindowHidden; - break; - } - case SDL_WINDOWEVENT_MINIMIZED: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 0; - EEEvent.window.type = InputEvent::WindowMinimized; - break; - } - case SDL_WINDOWEVENT_RESTORED: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowRestored; - break; - } - case SDL_WINDOWEVENT_ENTER: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowMouseEnter; - break; - } - case SDL_WINDOWEVENT_LEAVE: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 0; - EEEvent.window.type = InputEvent::WindowMouseLeave; - break; - } - case SDL_WINDOWEVENT_FOCUS_GAINED: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 1; - EEEvent.window.type = InputEvent::WindowKeyboardFocusGain; - break; - } - case SDL_WINDOWEVENT_FOCUS_LOST: { - EEEvent.Type = InputEvent::Window; - EEEvent.window.gain = 0; - EEEvent.window.type = InputEvent::WindowKeyboardFocusLost; - break; - } - } - - break; - } - case SDL_TEXTINPUT: { - String txt = String::fromUtf8( SDLEvent.text.text ); - EEEvent.Type = InputEvent::TextInput; - EEEvent.text.timestamp = SDLEvent.text.timestamp; - EEEvent.text.text = txt[0]; - break; - } - case SDL_KEYDOWN: { - EEEvent.Type = InputEvent::KeyDown; - EEEvent.key.state = SDLEvent.key.state; - EEEvent.key.which = SDLEvent.key.windowID; - EEEvent.key.keysym.sym = (Keycode)SDLEvent.key.keysym.sym; - EEEvent.key.keysym.scancode = (Scancode)SDLEvent.key.keysym.scancode; - EEEvent.key.keysym.mod = SDLEvent.key.keysym.mod; - EEEvent.key.keysym.unicode = 0; - break; - } - case SDL_KEYUP: { - EEEvent.Type = InputEvent::KeyUp; - EEEvent.key.state = SDLEvent.key.state; - EEEvent.key.which = SDLEvent.key.windowID; - EEEvent.key.keysym.sym = (Keycode)SDLEvent.key.keysym.sym; - EEEvent.key.keysym.scancode = (Scancode)SDLEvent.key.keysym.scancode; - EEEvent.key.keysym.mod = SDLEvent.key.keysym.mod; - EEEvent.key.keysym.unicode = 0; - break; - } - case SDL_MOUSEMOTION: { - EEEvent.Type = InputEvent::MouseMotion; - EEEvent.motion.which = SDLEvent.motion.windowID; - EEEvent.motion.state = SDLEvent.motion.state; - EEEvent.motion.x = SDLEvent.motion.x * mDPIScale; - EEEvent.motion.y = SDLEvent.motion.y * mDPIScale; - EEEvent.motion.xrel = SDLEvent.motion.xrel * mDPIScale; - EEEvent.motion.yrel = SDLEvent.motion.yrel * mDPIScale; - break; - } - case SDL_MOUSEBUTTONDOWN: { - EEEvent.Type = InputEvent::MouseButtonDown; - EEEvent.button.button = SDLEvent.button.button; - EEEvent.button.which = SDLEvent.button.windowID; - EEEvent.button.state = SDLEvent.button.state; - EEEvent.button.x = SDLEvent.button.x; - EEEvent.button.y = SDLEvent.button.y; - break; - } - case SDL_MOUSEBUTTONUP: { - EEEvent.Type = InputEvent::MouseButtonUp; - EEEvent.button.button = SDLEvent.button.button; - EEEvent.button.which = SDLEvent.button.windowID; - EEEvent.button.state = SDLEvent.button.state; - EEEvent.button.x = SDLEvent.button.x; - EEEvent.button.y = SDLEvent.button.y; - break; - } - case SDL_MOUSEWHEEL: { - Uint8 button; - int x, y; - - if ( SDLEvent.wheel.y == 0 ) { - break; - } - - SDL_GetMouseState( &x, &y ); - - if ( SDLEvent.wheel.y > 0 ) { - button = EE_BUTTON_WHEELUP; - } else { - button = EE_BUTTON_WHEELDOWN; - } - - EEEvent.button.button = button; - EEEvent.button.x = x; - EEEvent.button.y = y; - EEEvent.button.which = SDLEvent.wheel.windowID; - - EEEvent.Type = InputEvent::MouseButtonDown; - EEEvent.button.state = 1; - processEvent( &EEEvent ); - - EEEvent.Type = InputEvent::MouseButtonUp; - EEEvent.button.state = 0; - break; - } - case SDL_FINGERMOTION: { - EEEvent.Type = InputEvent::FingerMotion; - EEEvent.finger.timestamp = SDLEvent.tfinger.timestamp; - EEEvent.finger.touchId = SDLEvent.tfinger.touchId; - EEEvent.finger.fingerId = SDLEvent.tfinger.fingerId; - EEEvent.finger.x = SDLEvent.tfinger.x; - EEEvent.finger.y = SDLEvent.tfinger.y; - EEEvent.finger.dx = SDLEvent.tfinger.dx; - EEEvent.finger.dy = SDLEvent.tfinger.dy; - EEEvent.finger.pressure = SDLEvent.tfinger.pressure; - break; - } - case SDL_FINGERDOWN: { - EEEvent.Type = InputEvent::FingerDown; - EEEvent.finger.timestamp = SDLEvent.tfinger.timestamp; - EEEvent.finger.touchId = SDLEvent.tfinger.touchId; - EEEvent.finger.fingerId = SDLEvent.tfinger.fingerId; - EEEvent.finger.x = SDLEvent.tfinger.x; - EEEvent.finger.y = SDLEvent.tfinger.y; - EEEvent.finger.dx = SDLEvent.tfinger.dx; - EEEvent.finger.dy = SDLEvent.tfinger.dy; - EEEvent.finger.pressure = SDLEvent.tfinger.pressure; - break; - } - case SDL_FINGERUP: { - EEEvent.Type = InputEvent::FingerUp; - EEEvent.finger.timestamp = SDLEvent.tfinger.timestamp; - EEEvent.finger.touchId = SDLEvent.tfinger.touchId; - EEEvent.finger.fingerId = SDLEvent.tfinger.fingerId; - EEEvent.finger.x = SDLEvent.tfinger.x; - EEEvent.finger.y = SDLEvent.tfinger.y; - EEEvent.finger.dx = SDLEvent.tfinger.dx; - EEEvent.finger.dy = SDLEvent.tfinger.dy; - EEEvent.finger.pressure = SDLEvent.tfinger.pressure; - break; - } - case SDL_JOYAXISMOTION: { - EEEvent.Type = InputEvent::JoyAxisMotion; - EEEvent.jaxis.which = SDLEvent.jaxis.which; - EEEvent.jaxis.axis = SDLEvent.jaxis.axis; - EEEvent.jaxis.value = SDLEvent.jaxis.value; - break; - } - case SDL_JOYBALLMOTION: { - EEEvent.Type = InputEvent::JoyBallMotion; - EEEvent.jball.which = SDLEvent.jball.which; - EEEvent.jball.ball = SDLEvent.jball.ball; - EEEvent.jball.xrel = SDLEvent.jball.xrel; - EEEvent.jball.yrel = SDLEvent.jball.yrel; - break; - } - case SDL_JOYHATMOTION: { - EEEvent.Type = InputEvent::JoyHatMotion; - EEEvent.jhat.which = SDLEvent.jhat.which; - EEEvent.jhat.value = SDLEvent.jhat.value; - EEEvent.jhat.hat = SDLEvent.jhat.hat; - break; - } - case SDL_JOYBUTTONDOWN: { - EEEvent.Type = InputEvent::JoyButtonDown; - EEEvent.jbutton.which = SDLEvent.jbutton.which; - EEEvent.jbutton.state = SDLEvent.jbutton.state; - EEEvent.jbutton.button = SDLEvent.jbutton.button; - break; - } - case SDL_JOYBUTTONUP: { - EEEvent.Type = InputEvent::JoyButtonUp; - EEEvent.jbutton.which = SDLEvent.jbutton.which; - EEEvent.jbutton.state = SDLEvent.jbutton.state; - EEEvent.jbutton.button = SDLEvent.jbutton.button; - break; - } - case SDL_QUIT: { - EEEvent.Type = InputEvent::Quit; - EEEvent.quit.type = EEEvent.Type; - break; - } - case SDL_SYSWMEVENT: { - EEEvent.Type = InputEvent::SysWM; - EEEvent.syswm.msg = (InputEvent::SysWMmsg*)SDLEvent.syswm.msg; - break; - } - case SDL_DROPFILE: { - EEEvent.Type = InputEvent::FileDropped; - EEEvent.file.file = SDLEvent.drop.file; - break; - } - case SDL_DROPTEXT: { - EEEvent.Type = InputEvent::TextDropped; - EEEvent.textdrop.text = SDLEvent.drop.file; - break; - } - default: { - if ( SDLEvent.type >= SDL_USEREVENT && SDLEvent.type < SDL_LASTEVENT ) { - EEEvent.Type = InputEvent::EventUser + SDLEvent.type - SDL_USEREVENT; - EEEvent.user.type = EEEvent.Type; - EEEvent.user.code = SDLEvent.user.code; - EEEvent.user.data1 = SDLEvent.user.data1; - EEEvent.user.data2 = SDLEvent.user.data2; - } else { - EEEvent.Type = InputEvent::NoEvent; - } - } - } - - if ( InputEvent::NoEvent != EEEvent.Type ) { - processEvent( &EEEvent ); - } - - if ( InputEvent::FileDropped == EEEvent.Type || InputEvent::TextDropped == EEEvent.Type ) { - SDL_free( SDLEvent.drop.file ); - } + if ( !mQueuedEvents.empty() ) { + for ( auto prevEvent : mQueuedEvents ) + sendEvent( prevEvent ); + mQueuedEvents.clear(); } - + while ( SDL_PollEvent( &SDLEvent ) ) + sendEvent( SDLEvent ); InputEvent endProcessingEvent; endProcessingEvent.Type = InputEvent::EventsSent; processEvent( &endProcessingEvent ); } +void InputSDL::waitEvent( const Time& timeout ) { + SDL_Event SDLEvent; + if ( timeout == Time::Zero ) { + if ( SDL_WaitEvent( &SDLEvent ) ) + mQueuedEvents.emplace_back( SDLEvent ); + } else if ( SDL_WaitEventTimeout( &SDLEvent, (int)timeout.asMilliseconds() ) ) + mQueuedEvents.emplace_back( SDLEvent ); +} + bool InputSDL::grabInput() { - return ( SDL_GetWindowGrab( reinterpret_cast( mWindow )->GetSDLWindow() ) == - SDL_TRUE ) + return ( SDL_GetWindowGrab( static_cast( mWindow )->GetSDLWindow() ) == SDL_TRUE ) ? true : false; } void InputSDL::grabInput( const bool& Grab ) { - SDL_SetWindowGrab( reinterpret_cast( mWindow )->GetSDLWindow(), + SDL_SetWindowGrab( static_cast( mWindow )->GetSDLWindow(), Grab ? SDL_TRUE : SDL_FALSE ); } @@ -401,6 +113,303 @@ void InputSDL::init() { #endif } +void InputSDL::sendEvent( const SDL_Event& SDLEvent ) { + InputEvent event; + switch ( SDLEvent.type ) { + case SDL_WINDOWEVENT: { + switch ( SDLEvent.window.event ) { + case SDL_WINDOWEVENT_RESIZED: { + event.Type = InputEvent::VideoResize; + 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.window.gain = 1; + event.window.type = InputEvent::WindowHitTest; + break; + } + case SDL_WINDOWEVENT_TAKE_FOCUS: { + event.Type = InputEvent::VideoExpose; + event.expose.type = event.Type; + break; + } + case SDL_WINDOWEVENT_CLOSE: { + event.Type = InputEvent::Window; + event.window.gain = 0; + event.window.type = InputEvent::WindowClose; + break; + } + case SDL_WINDOWEVENT_SIZE_CHANGED: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowSizeChanged; + break; + } + case SDL_WINDOWEVENT_MAXIMIZED: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowMaximized; + break; + } + case SDL_WINDOWEVENT_EXPOSED: { + event.Type = InputEvent::VideoExpose; + event.expose.type = event.Type; + break; + } + case SDL_WINDOWEVENT_MOVED: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowMoved; + break; + } + case SDL_WINDOWEVENT_SHOWN: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowShown; + break; + } + case SDL_WINDOWEVENT_HIDDEN: { + event.Type = InputEvent::Window; + event.window.gain = 0; + event.window.type = InputEvent::WindowHidden; + break; + } + case SDL_WINDOWEVENT_MINIMIZED: { + event.Type = InputEvent::Window; + event.window.gain = 0; + event.window.type = InputEvent::WindowMinimized; + break; + } + case SDL_WINDOWEVENT_RESTORED: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowRestored; + break; + } + case SDL_WINDOWEVENT_ENTER: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowMouseEnter; + break; + } + case SDL_WINDOWEVENT_LEAVE: { + event.Type = InputEvent::Window; + event.window.gain = 0; + event.window.type = InputEvent::WindowMouseLeave; + break; + } + case SDL_WINDOWEVENT_FOCUS_GAINED: { + event.Type = InputEvent::Window; + event.window.gain = 1; + event.window.type = InputEvent::WindowKeyboardFocusGain; + break; + } + case SDL_WINDOWEVENT_FOCUS_LOST: { + event.Type = InputEvent::Window; + event.window.gain = 0; + event.window.type = InputEvent::WindowKeyboardFocusLost; + break; + } + } + + break; + } + case SDL_TEXTINPUT: { + String txt = String::fromUtf8( SDLEvent.text.text ); + event.Type = InputEvent::TextInput; + event.text.timestamp = SDLEvent.text.timestamp; + event.text.text = txt[0]; + break; + } + case SDL_KEYDOWN: { + event.Type = InputEvent::KeyDown; + event.key.state = SDLEvent.key.state; + event.key.which = SDLEvent.key.windowID; + event.key.keysym.sym = (Keycode)SDLEvent.key.keysym.sym; + event.key.keysym.scancode = (Scancode)SDLEvent.key.keysym.scancode; + event.key.keysym.mod = SDLEvent.key.keysym.mod; + event.key.keysym.unicode = 0; + break; + } + case SDL_KEYUP: { + event.Type = InputEvent::KeyUp; + event.key.state = SDLEvent.key.state; + event.key.which = SDLEvent.key.windowID; + event.key.keysym.sym = (Keycode)SDLEvent.key.keysym.sym; + event.key.keysym.scancode = (Scancode)SDLEvent.key.keysym.scancode; + event.key.keysym.mod = SDLEvent.key.keysym.mod; + event.key.keysym.unicode = 0; + break; + } + case SDL_MOUSEMOTION: { + event.Type = InputEvent::MouseMotion; + event.motion.which = SDLEvent.motion.windowID; + event.motion.state = SDLEvent.motion.state; + event.motion.x = SDLEvent.motion.x * mDPIScale; + event.motion.y = SDLEvent.motion.y * mDPIScale; + event.motion.xrel = SDLEvent.motion.xrel * mDPIScale; + event.motion.yrel = SDLEvent.motion.yrel * mDPIScale; + break; + } + case SDL_MOUSEBUTTONDOWN: { + event.Type = InputEvent::MouseButtonDown; + event.button.button = SDLEvent.button.button; + event.button.which = SDLEvent.button.windowID; + event.button.state = SDLEvent.button.state; + event.button.x = SDLEvent.button.x; + event.button.y = SDLEvent.button.y; + break; + } + case SDL_MOUSEBUTTONUP: { + event.Type = InputEvent::MouseButtonUp; + event.button.button = SDLEvent.button.button; + event.button.which = SDLEvent.button.windowID; + event.button.state = SDLEvent.button.state; + event.button.x = SDLEvent.button.x; + event.button.y = SDLEvent.button.y; + break; + } + case SDL_MOUSEWHEEL: { + Uint8 button; + int x, y; + + if ( SDLEvent.wheel.y == 0 ) { + break; + } + + SDL_GetMouseState( &x, &y ); + + if ( SDLEvent.wheel.y > 0 ) { + button = EE_BUTTON_WHEELUP; + } else { + button = EE_BUTTON_WHEELDOWN; + } + + event.button.button = button; + event.button.x = x; + event.button.y = y; + event.button.which = SDLEvent.wheel.windowID; + + event.Type = InputEvent::MouseButtonDown; + event.button.state = 1; + processEvent( &event ); + + event.Type = InputEvent::MouseButtonUp; + event.button.state = 0; + break; + } + case SDL_FINGERMOTION: { + event.Type = InputEvent::FingerMotion; + event.finger.timestamp = SDLEvent.tfinger.timestamp; + event.finger.touchId = SDLEvent.tfinger.touchId; + event.finger.fingerId = SDLEvent.tfinger.fingerId; + event.finger.x = SDLEvent.tfinger.x; + event.finger.y = SDLEvent.tfinger.y; + event.finger.dx = SDLEvent.tfinger.dx; + event.finger.dy = SDLEvent.tfinger.dy; + event.finger.pressure = SDLEvent.tfinger.pressure; + break; + } + case SDL_FINGERDOWN: { + event.Type = InputEvent::FingerDown; + event.finger.timestamp = SDLEvent.tfinger.timestamp; + event.finger.touchId = SDLEvent.tfinger.touchId; + event.finger.fingerId = SDLEvent.tfinger.fingerId; + event.finger.x = SDLEvent.tfinger.x; + event.finger.y = SDLEvent.tfinger.y; + event.finger.dx = SDLEvent.tfinger.dx; + event.finger.dy = SDLEvent.tfinger.dy; + event.finger.pressure = SDLEvent.tfinger.pressure; + break; + } + case SDL_FINGERUP: { + event.Type = InputEvent::FingerUp; + event.finger.timestamp = SDLEvent.tfinger.timestamp; + event.finger.touchId = SDLEvent.tfinger.touchId; + event.finger.fingerId = SDLEvent.tfinger.fingerId; + event.finger.x = SDLEvent.tfinger.x; + event.finger.y = SDLEvent.tfinger.y; + event.finger.dx = SDLEvent.tfinger.dx; + event.finger.dy = SDLEvent.tfinger.dy; + event.finger.pressure = SDLEvent.tfinger.pressure; + break; + } + case SDL_JOYAXISMOTION: { + event.Type = InputEvent::JoyAxisMotion; + event.jaxis.which = SDLEvent.jaxis.which; + event.jaxis.axis = SDLEvent.jaxis.axis; + event.jaxis.value = SDLEvent.jaxis.value; + break; + } + case SDL_JOYBALLMOTION: { + event.Type = InputEvent::JoyBallMotion; + event.jball.which = SDLEvent.jball.which; + event.jball.ball = SDLEvent.jball.ball; + event.jball.xrel = SDLEvent.jball.xrel; + event.jball.yrel = SDLEvent.jball.yrel; + break; + } + case SDL_JOYHATMOTION: { + event.Type = InputEvent::JoyHatMotion; + event.jhat.which = SDLEvent.jhat.which; + event.jhat.value = SDLEvent.jhat.value; + event.jhat.hat = SDLEvent.jhat.hat; + break; + } + case SDL_JOYBUTTONDOWN: { + event.Type = InputEvent::JoyButtonDown; + event.jbutton.which = SDLEvent.jbutton.which; + event.jbutton.state = SDLEvent.jbutton.state; + event.jbutton.button = SDLEvent.jbutton.button; + break; + } + case SDL_JOYBUTTONUP: { + event.Type = InputEvent::JoyButtonUp; + event.jbutton.which = SDLEvent.jbutton.which; + event.jbutton.state = SDLEvent.jbutton.state; + event.jbutton.button = SDLEvent.jbutton.button; + break; + } + case SDL_QUIT: { + event.Type = InputEvent::Quit; + event.quit.type = event.Type; + break; + } + case SDL_SYSWMEVENT: { + event.Type = InputEvent::SysWM; + event.syswm.msg = (InputEvent::SysWMmsg*)SDLEvent.syswm.msg; + break; + } + case SDL_DROPFILE: { + event.Type = InputEvent::FileDropped; + event.file.file = SDLEvent.drop.file; + break; + } + case SDL_DROPTEXT: { + event.Type = InputEvent::TextDropped; + event.textdrop.text = SDLEvent.drop.file; + break; + } + default: { + if ( SDLEvent.type >= SDL_USEREVENT && SDLEvent.type < SDL_LASTEVENT ) { + event.Type = InputEvent::EventUser + SDLEvent.type - SDL_USEREVENT; + event.user.type = event.Type; + event.user.code = SDLEvent.user.code; + event.user.data1 = SDLEvent.user.data1; + event.user.data2 = SDLEvent.user.data2; + } else { + event.Type = InputEvent::NoEvent; + } + } + } + if ( InputEvent::NoEvent != event.Type ) + processEvent( &event ); + if ( InputEvent::FileDropped == event.Type || InputEvent::TextDropped == event.Type ) + SDL_free( SDLEvent.drop.file ); +} + }}}} // namespace EE::Window::Backend::SDL2 #endif diff --git a/src/eepp/window/backend/SDL2/inputsdl2.hpp b/src/eepp/window/backend/SDL2/inputsdl2.hpp index ca8e90b3a..d786ffb1d 100644 --- a/src/eepp/window/backend/SDL2/inputsdl2.hpp +++ b/src/eepp/window/backend/SDL2/inputsdl2.hpp @@ -16,6 +16,8 @@ class EE_API InputSDL : public Input { void update(); + void waitEvent( const Time& timeout = Time::Zero ); + bool grabInput(); void grabInput( const bool& Grab ); @@ -43,10 +45,13 @@ class EE_API InputSDL : public Input { protected: friend class WindowSDL; Float mDPIScale; + std::vector mQueuedEvents; InputSDL( EE::Window::Window* window ); void init(); + + void sendEvent( const SDL_Event& SDLEvent ); }; }}}} // namespace EE::Window::Backend::SDL2 diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 2e119b2eb..6f4a8cad5 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -452,23 +452,7 @@ void App::closeApp() { } void App::mainLoop() { - Input* input = mWindow->getInput(); - - input->update(); - - if ( input->isKeyUp( KEY_F6 ) ) { - mUISceneNode->setHighlightFocus( !mUISceneNode->getHighlightFocus() ); - mUISceneNode->setHighlightOver( !mUISceneNode->getHighlightOver() ); - } - - if ( input->isKeyUp( KEY_F7 ) ) { - mUISceneNode->setDrawBoxes( !mUISceneNode->getDrawBoxes() ); - } - - if ( input->isKeyUp( KEY_F8 ) ) { - mUISceneNode->setDrawDebugData( !mUISceneNode->getDrawDebugData() ); - } - + mWindow->getInput()->update(); Time elapsed = SceneManager::instance()->getElapsed(); SceneManager::instance()->update(); @@ -479,7 +463,7 @@ void App::mainLoop() { mConsole->draw( elapsed ); mWindow->display(); } else { - Sys::sleep( Milliseconds( mWindow->hasFocus() ? 16 : 100 ) ); + mWindow->getInput()->waitEvent( Milliseconds( mWindow->hasFocus() ? 16 : 100 ) ); } } @@ -889,19 +873,36 @@ void App::updateDocumentMenu() { void App::loadKeybindings() { if ( mKeybindings.empty() ) { + KeyBindings bindings( mWindow->getInput() ); + auto defKeybindings = getDefaultKeybindings(); IniFile ini( mKeybindingsPath ); if ( FileSystem::fileExists( mKeybindingsPath ) ) { mKeybindings = ini.getKeyMap( "keybindings" ); } else { - KeyBindings bindings( mWindow->getInput() ); - auto map = getDefaultKeybindings(); - for ( auto it : map ) + for ( auto it : defKeybindings ) ini.setValue( "keybindings", bindings.getShortcutString( it.first ), it.second ); ini.writeFile(); mKeybindings = ini.getKeyMap( "keybindings" ); } for ( auto key : mKeybindings ) mKeybindingsInvert[key.second] = key.first; + + if ( defKeybindings.size() != mKeybindings.size() ) { + bool added = false; + for ( auto key : defKeybindings ) { + auto foundCmd = mKeybindingsInvert.find( key.second ); + auto shortcutStr = bindings.getShortcutString( key.first ); + if ( foundCmd == mKeybindingsInvert.end() && + mKeybindings.find( shortcutStr ) == mKeybindings.end() ) { + mKeybindings[shortcutStr] = key.second; + mKeybindingsInvert[key.second] = shortcutStr; + ini.setValue( "keybindings", shortcutStr, key.second ); + added = true; + } + } + if ( added ) + ini.writeFile(); + } } } @@ -963,11 +964,14 @@ std::map App::getDefaultKeybindings() { std::map App::getLocalKeybindings() { return { {{KEY_RETURN, KEYMOD_LALT}, "fullscreen-toggle"}, - {{KEY_F3, 0}, "repeat-find"}, - {{KEY_F12, 0}, "console-toggle"}, + {{KEY_F3, KEYMOD_NONE}, "repeat-find"}, + {{KEY_F12, KEYMOD_NONE}, "console-toggle"}, {{KEY_F, KEYMOD_CTRL}, "find-replace"}, {{KEY_Q, KEYMOD_CTRL}, "close-app"}, {{KEY_O, KEYMOD_CTRL}, "open-file"}, + {{KEY_F6, KEYMOD_NONE}, "debug-draw-highlight-toggle"}, + {{KEY_F7, KEYMOD_NONE}, "debug-draw-boxes-toggle"}, + {{KEY_F8, KEYMOD_NONE}, "debug-draw-debug-data"}, }; } @@ -1014,6 +1018,14 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { } ); doc.setCommand( "keybindings", [&] { mEditorSplitter->loadFileFromPathInNewTab( mKeybindingsPath ); } ); + doc.setCommand( "debug-draw-boxes-toggle", + [&] { mUISceneNode->setDrawBoxes( !mUISceneNode->getDrawBoxes() ); } ); + doc.setCommand( "debug-draw-highlight-toggle", [&] { + mUISceneNode->setHighlightFocus( !mUISceneNode->getHighlightFocus() ); + mUISceneNode->setHighlightOver( !mUISceneNode->getHighlightOver() ); + } ); + doc.setCommand( "debug-draw-debug-data", + [&] { mUISceneNode->setDrawDebugData( !mUISceneNode->getDrawDebugData() ); } ); editor->addEventListener( Event::OnSave, [&]( const Event* event ) { UICodeEditor* editor = event->getNode()->asType(); @@ -1054,11 +1066,16 @@ void App::createSettingsMenu() { mSettingsMenu->add( "Quit", findIcon( "quit" ), getKeybind( "close-app" ) ); mSettingsButton = mUISceneNode->find( "settings" ); mSettingsButton->addEventListener( Event::MouseClick, [&]( const Event* ) { - Vector2f pos( mSettingsButton->getPixelsPosition() ); - mSettingsButton->nodeToWorldTranslation( pos ); - UIMenu::findBestMenuPos( pos, mSettingsMenu ); - mSettingsMenu->setPixelsPosition( pos ); - mSettingsMenu->show(); + if ( ( !mSettingsMenu->isVisible() || mSettingsMenu->isHiding() ) && + mSettingsMenu->getInactiveTime().getElapsedTime().asMilliseconds() > 1 ) { + Vector2f pos( mSettingsButton->getPixelsPosition() ); + mSettingsButton->nodeToWorldTranslation( pos ); + UIMenu::findBestMenuPos( pos, mSettingsMenu ); + mSettingsMenu->setPixelsPosition( pos ); + mSettingsMenu->show(); + } else { + mSettingsMenu->hide(); + } } ); mSettingsMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) )