diff --git a/include/SFML/Window/WindowBase.hpp b/include/SFML/Window/WindowBase.hpp index 26a60294..11c8cfd5 100644 --- a/include/SFML/Window/WindowBase.hpp +++ b/include/SFML/Window/WindowBase.hpp @@ -412,6 +412,23 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit popup + /// should show up + /// + /// The position specified is relative to the left-top + /// corner of the window area. + /// + /// It is implementation-specific what happens when negative + /// values are used. X11 handles them as you would expect, + /// but Windows sometimes resets the position to the top-left + /// of the screen. + /// + /// \param position Left-top corner of the preedit popup + /// + //////////////////////////////////////////////////////////// + void setImePreEditPosition(const Vector2i& position); + //////////////////////////////////////////////////////////// /// \brief Get the OS-specific handle of the window /// diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 23cd4c3d..b118e5ba 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -226,6 +226,13 @@ bool WindowImplAndroid::hasFocus() const } +//////////////////////////////////////////////////////////// +void WindowImplAndroid::setImePreEditPosition(const Vector2i& /* position */) +{ + // Not applicable +} + + //////////////////////////////////////////////////////////// void WindowImplAndroid::forwardEvent(const Event& event) { diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index b6c03dbe..03a946f0 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -202,6 +202,15 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const override; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + void setImePreeditPosition(const Vector2i& position) override; + static void forwardEvent(const Event& event); static WindowImplAndroid* singleInstance; diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index dd9ea084..ee030131 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -330,7 +330,7 @@ if(SFML_OS_LINUX) find_package(UDev REQUIRED) target_link_libraries(sfml-window PRIVATE UDev::UDev dl) elseif(SFML_OS_WINDOWS) - target_link_libraries(sfml-window PRIVATE winmm gdi32) + target_link_libraries(sfml-window PRIVATE winmm gdi32 imm32) elseif(SFML_OS_FREEBSD) target_link_libraries(sfml-window PRIVATE usbhid) elseif(SFML_OS_MACOS) diff --git a/src/SFML/Window/DRM/WindowImplDRM.cpp b/src/SFML/Window/DRM/WindowImplDRM.cpp index 9c26f234..a276f477 100644 --- a/src/SFML/Window/DRM/WindowImplDRM.cpp +++ b/src/SFML/Window/DRM/WindowImplDRM.cpp @@ -158,6 +158,14 @@ bool WindowImplDRM::hasFocus() const return true; } + +//////////////////////////////////////////////////////////// +void WindowImplDRM::setImePreEditPosition(const Vector2i& /* position */) +{ + // Not applicable +} + + void WindowImplDRM::processEvents() { sf::Event ev; diff --git a/src/SFML/Window/DRM/WindowImplDRM.hpp b/src/SFML/Window/DRM/WindowImplDRM.hpp index 390909cd..475b91b1 100644 --- a/src/SFML/Window/DRM/WindowImplDRM.hpp +++ b/src/SFML/Window/DRM/WindowImplDRM.hpp @@ -196,6 +196,15 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const override; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + void setImePreeditPosition(const Vector2i& position) override; + protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 26800d40..04d307ae 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -1232,6 +1232,16 @@ bool WindowImplX11::hasFocus() const } +//////////////////////////////////////////////////////////// +void WindowImplX11::setImePreEditPosition(const Vector2i& position) +{ + const XPoint xpos{static_cast(position.x), static_cast(position.y)}; + const XVaNestedList preeditAttr = XVaCreateNestedList(0, XNSpotLocation, &xpos, NULL); + XSetICValues(m_inputContext, XNPreeditAttributes, preeditAttr, NULL); + XFree(preeditAttr); +} + + //////////////////////////////////////////////////////////// void WindowImplX11::grabFocus() { diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 3fb93831..3c2fc640 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -203,6 +203,15 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const override; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + void setImePreEditPosition(const Vector2i& position) override; + protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 29bc0296..f8f43907 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -454,6 +454,21 @@ bool WindowImplWin32::hasFocus() const } +//////////////////////////////////////////////////////////// +void WindowImplWin32::setImePreEditPosition(const Vector2i& position) +{ + if (HIMC himc = ImmGetContext(m_handle); himc != nullptr) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = static_cast(position.x); + cf.ptCurrentPos.y = static_cast(position.y); + cf.dwStyle = CFS_FORCE_POSITION; // Don't let the IME adjust the position + ImmSetCompositionWindow(himc, &cf); + ImmReleaseContext(m_handle, himc); + } +} + + //////////////////////////////////////////////////////////// void WindowImplWin32::registerWindowClass() { @@ -671,7 +686,7 @@ Keyboard::Scancode WindowImplWin32::toScancode(WPARAM wParam, LPARAM lParam) case 86: return Keyboard::Scan::NonUsBackslash; case 87: return Keyboard::Scan::F11; case 88: return Keyboard::Scan::F12; - + case 91: return (HIWORD(lParam) & KF_EXTENDED) ? Keyboard::Scan::LSystem : Keyboard::Scan::Unknown; case 92: return (HIWORD(lParam) & KF_EXTENDED) ? Keyboard::Scan::RSystem : Keyboard::Scan::Unknown; case 93: return (HIWORD(lParam) & KF_EXTENDED) ? Keyboard::Scan::Menu : Keyboard::Scan::Unknown; diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index 32da1196..4bb168b8 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -183,6 +183,15 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const override; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + void setImePreEditPosition(const Vector2i& position) override; + protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system diff --git a/src/SFML/Window/WindowBase.cpp b/src/SFML/Window/WindowBase.cpp index 453927a6..8791230f 100644 --- a/src/SFML/Window/WindowBase.cpp +++ b/src/SFML/Window/WindowBase.cpp @@ -351,6 +351,14 @@ bool WindowBase::hasFocus() const } +//////////////////////////////////////////////////////////// +void WindowBase::setImePreEditPosition(const Vector2i& position) +{ + if (m_impl) + m_impl->setImePreEditPosition(position); +} + + //////////////////////////////////////////////////////////// WindowHandle WindowBase::getNativeHandle() const { diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index 1e38b917..a5615844 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -275,6 +275,15 @@ public: //////////////////////////////////////////////////////////// virtual bool hasFocus() const = 0; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + virtual void setImePreEditPosition(const Vector2i& position) = 0; + //////////////////////////////////////////////////////////// /// \brief Create a Vulkan rendering surface /// diff --git a/src/SFML/Window/iOS/WindowImplUIKit.hpp b/src/SFML/Window/iOS/WindowImplUIKit.hpp index ed88de1c..16c73c5a 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.hpp +++ b/src/SFML/Window/iOS/WindowImplUIKit.hpp @@ -197,6 +197,15 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const override; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + void setImePreEditPosition(const Vector2i& position) override; + //////////////////////////////////////////////////////////// /// \brief Notify an event /// diff --git a/src/SFML/Window/iOS/WindowImplUIKit.mm b/src/SFML/Window/iOS/WindowImplUIKit.mm index 05d66bd4..3f39f097 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.mm +++ b/src/SFML/Window/iOS/WindowImplUIKit.mm @@ -223,6 +223,13 @@ bool WindowImplUIKit::hasFocus() const } +//////////////////////////////////////////////////////////// +void WindowImplUIKit::setImePreeditPosition(const Vector2i& /* position */) +{ + // Not applicable +} + + //////////////////////////////////////////////////////////// void WindowImplUIKit::forwardEvent(Event event) { diff --git a/src/SFML/Window/macOS/WindowImplCocoa.hpp b/src/SFML/Window/macOS/WindowImplCocoa.hpp index 8d3dd14c..c0443f2d 100644 --- a/src/SFML/Window/macOS/WindowImplCocoa.hpp +++ b/src/SFML/Window/macOS/WindowImplCocoa.hpp @@ -371,6 +371,15 @@ public: //////////////////////////////////////////////////////////// bool hasFocus() const override; + //////////////////////////////////////////////////////////// + /// \brief Set the position where the IME preedit window + /// should show up + /// + /// \param position Left-top corner of the preedit window + /// + //////////////////////////////////////////////////////////// + void setImePreEditPosition(const Vector2i& position) override; + protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system diff --git a/src/SFML/Window/macOS/WindowImplCocoa.mm b/src/SFML/Window/macOS/WindowImplCocoa.mm index 36876b89..39e31e0d 100644 --- a/src/SFML/Window/macOS/WindowImplCocoa.mm +++ b/src/SFML/Window/macOS/WindowImplCocoa.mm @@ -546,4 +546,11 @@ bool WindowImplCocoa::hasFocus() const } +//////////////////////////////////////////////////////////// +void WindowImplCocoa::setImePreEditPosition(const Vector2i& /* position */) +{ + // TODO: To implement +} + + } // namespace sf::priv