Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorSeverin <julian_eisel@web.de>2014-12-07 02:58:17 +0300
committerSeverin <julian_eisel@web.de>2014-12-07 02:58:17 +0300
commite81d077c852f43b635f10972479e36909a66d60c (patch)
tree35eabcec49938e0d66c083354fa6c0c600372a12 /intern
parent06515475b9c87c553d75481abfa600a0f7a5faf8 (diff)
Input Method Editor (IME) support for text buttons
Original patch by @random (D765) with some minor work done by @campbell and me. At this place, I'd like call out a number of people who were involved and deserve a big "Thank you!": * At the first place @randon who developed and submitted the patch * The Blendercn community which helped a lot with testing - espacially * @yuzukyo, @leon_cheung and @kjym3 * @campbellbarton, @mont29 and @sergey for their help and advises during * review * @ton who realized the importance of this early on and asked me for * reviewing We are still not finished, as this is only the first part of the implementaion, but there's more to come!
Diffstat (limited to 'intern')
-rw-r--r--intern/ghost/CMakeLists.txt10
-rw-r--r--intern/ghost/GHOST_C-api.h24
-rw-r--r--intern/ghost/GHOST_IWindow.h23
-rw-r--r--intern/ghost/GHOST_Types.h20
-rw-r--r--intern/ghost/SConscript7
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp18
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp65
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h9
-rw-r--r--intern/ghost/intern/GHOST_Window.h16
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp13
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h19
11 files changed, 224 insertions, 0 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 3ce269c2b4f..dc55a81b0d8 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -280,6 +280,16 @@ elseif(WIN32)
)
endif()
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+
+ list(APPEND SRC
+ intern/GHOST_ImeWin32.cpp
+
+ intern/GHOST_ImeWin32.h
+ )
+ endif()
+
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerWin32.cpp
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 7b47f0526a2..c0f2651dd8b 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -897,6 +897,30 @@ extern int GHOST_UseNativePixels(void);
*/
extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
+/**
+ * Enable IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * \param windowhandle Window handle of the caller
+ * \param x Requested x-coordinate of the rectangle
+ * \param y Requested y-coordinate of the rectangle
+ * \param w Requested width of the rectangle
+ * \param h Requested height of the rectangle
+ * \param complete Whether or not to complete the ongoing composition
+ * true: Start a new composition
+ * false: Move the IME windows to the given position without finishing it.
+ */
+extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int complete);
+/**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ * \param windowhandle The window handle of the caller
+ */
+extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
#ifdef __cplusplus
}
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 71dc193a81b..3f8215dc7c2 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -331,6 +331,29 @@ public:
virtual float getNativePixelSize(void) = 0;
+#ifdef WITH_INPUT_IME
+ /**
+ * Enable IME attached to the given window, i.e. allows user-input
+ * events to be dispatched to the IME.
+ * \param x Requested x-coordinate of the rectangle
+ * \param y Requested y-coordinate of the rectangle
+ * \param w Requested width of the rectangle
+ * \param h Requested height of the rectangle
+ * \param complete Whether or not to complete the ongoing composition
+ * true: Start a new composition
+ * false: Move the IME windows to the given position without finishing it.
+ */
+ virtual void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed) = 0;
+
+ /**
+ * Disable the IME attached to the given window, i.e. prohibits any user-input
+ * events from being dispatched to the IME.
+ */
+ virtual void endIME() = 0;
+#endif /* WITH_INPUT_IME */
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 7333ba025a5..c4a7490c71c 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -190,6 +190,10 @@ typedef enum {
GHOST_kEventTimer,
+ GHOST_kEventImeCompositionStart,
+ GHOST_kEventImeComposition,
+ GHOST_kEventImeCompositionEnd,
+
GHOST_kNumEventTypes
} GHOST_TEventType;
@@ -436,6 +440,22 @@ typedef struct {
GHOST_TEventDataPtr data;
} GHOST_TEventDragnDropData;
+/** similar to wmImeData */
+typedef struct {
+ /** size_t */
+ GHOST_TUserDataPtr result_len, composite_len;
+ /** char * utf8 encoding */
+ GHOST_TUserDataPtr result, composite;
+ /** Cursor position in the IME composition. */
+ int cursor_position;
+ /** Represents the position of the beginning of the selection */
+ int target_start;
+ /** Represents the position of the end of the selection */
+ int target_end;
+ /** custom temporal data */
+ GHOST_TUserDataPtr tmp;
+} GHOST_TEventImeData;
+
typedef struct {
int count;
GHOST_TUns8 **strings;
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index 5a4572c164d..a41fadf9ac7 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -154,6 +154,13 @@ if env['BF_GHOST_DEBUG']:
else:
sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp')
+if env['WITH_BF_IME']:
+ if window_system in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ defs.append('WITH_INPUT_IME')
+ else:
+ sources.remove('intern' + os.sep + 'GHOST_ImeWin32.h')
+ sources.remove('intern' + os.sep + 'GHOST_ImeWin32.cpp')
+
if env['WITH_BF_3DMOUSE']:
defs.append('WITH_INPUT_NDOF')
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 5a2e638f01a..0da77ac5e20 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -915,3 +915,21 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+
+void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int complete)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->beginIME(x, y, w, h, complete);
+}
+
+void GHOST_EndIME(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ window->endIME();
+}
+
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 3b793fda968..4247c4f31ce 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -792,6 +792,15 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
return new GHOST_Event(system->getMilliSeconds(), type, window);
}
+#ifdef WITH_INPUT_IME
+GHOST_Event *GHOST_SystemWin32::processImeEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TEventImeData *data)
+{
+ GHOST_System *system = (GHOST_System *)getSystem();
+ return new GHOST_EventIME(system->getMilliSeconds(), type, window, data);
+}
+#endif
+
+
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(
GHOST_TEventType eventType,
GHOST_TDragnDropTypes draggedObjectType,
@@ -904,6 +913,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
LRESULT lResult = 0;
GHOST_SystemWin32 *system = ((GHOST_SystemWin32 *)getSystem());
+ GHOST_EventManager *eventManager = system->getEventManager();
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
@@ -912,8 +922,13 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
switch (msg) {
// we need to check if new key layout has AltGr
case WM_INPUTLANGCHANGE:
+ {
system->handleKeyboardChange();
+#ifdef WITH_INPUT_IME
+ window->getImeInput()->SetInputLanguage();
+#endif
break;
+ }
////////////////////////////////////////////////////////////////////////
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
@@ -949,6 +964,56 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
}
+#ifdef WITH_INPUT_IME
+ ////////////////////////////////////////////////////////////////////////
+ // IME events, processed, read more in GHOST_IME.h
+ ////////////////////////////////////////////////////////////////////////
+ case WM_IME_SETCONTEXT:
+ {
+ window->getImeInput()->SetInputLanguage();
+ window->getImeInput()->CreateImeWindow(window->getHWND());
+ window->getImeInput()->CleanupComposition(window->getHWND());
+ window->getImeInput()->CheckFirst(window->getHWND());
+ break;
+ }
+ case WM_IME_STARTCOMPOSITION:
+ {
+ eventHandled = true;
+ /* remove input event before start comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ window->getImeInput()->CreateImeWindow(window->getHWND());
+ window->getImeInput()->ResetComposition(window->getHWND());
+ event = processImeEvent(
+ GHOST_kEventImeCompositionStart,
+ window,
+ &window->getImeInput()->eventImeData);
+ break;
+ }
+ case WM_IME_COMPOSITION:
+ {
+ eventHandled = true;
+ window->getImeInput()->UpdateImeWindow(window->getHWND());
+ window->getImeInput()->UpdateInfo(window->getHWND());
+ event = processImeEvent(
+ GHOST_kEventImeComposition,
+ window,
+ &window->getImeInput()->eventImeData);
+ break;
+ }
+ case WM_IME_ENDCOMPOSITION:
+ {
+ eventHandled = true;
+ /* remove input event after end comp event, avoid redundant input */
+ eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
+ window->getImeInput()->ResetComposition(window->getHWND());
+ window->getImeInput()->DestroyImeWindow(window->getHWND());
+ event = processImeEvent(
+ GHOST_kEventImeCompositionEnd,
+ window,
+ &window->getImeInput()->eventImeData);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 79fed06c6a5..cb3b8ee3cfc 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -307,6 +307,15 @@ protected:
static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window);
/**
+ * Creates a IME event.
+ * \param type The type of event to create.
+ * \param window The window receiving the event (the active window).
+ * \param data IME data.
+ * \return The event created.
+ */
+ static GHOST_Event *processImeEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TEventImeData *data);
+
+ /**
* Handles minimum window size.
* \param minmax The MINMAXINFO structure.
*/
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 15b81998aab..ac31c54666b 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -295,6 +295,22 @@ public:
return 1.0f;
}
+#ifdef WITH_INPUT_IME
+ virtual void beginIME(GHOST_TInt32 x,
+ GHOST_TInt32 y,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h,
+ int completed)
+ {
+ /* do nothing temporarily if not in windows */
+ }
+
+ virtual void endIME()
+ {
+ /* do nothing temporarily if not in windows */
+ }
+#endif /* WITH_INPUT_IME */
+
protected:
/**
* Tries to install a rendering context in this window.
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 64ea7192616..4e384881f2c 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -1050,3 +1050,16 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
return GHOST_kFailure;
}
+
+#ifdef WITH_INPUT_IME
+void GHOST_WindowWin32::beginIME(GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 w, GHOST_TInt32 h, int completed)
+{
+ this->getImeInput()->BeginIME(this->getHWND(), GHOST_Rect(x, y - h , x, y), (bool)completed);
+}
+
+
+void GHOST_WindowWin32::endIME()
+{
+ this->getImeInput()->EndIME(this->getHWND());
+}
+#endif /* WITH_INPUT_IME */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 7b12d8c583e..c4575d0f9b0 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -39,6 +39,9 @@
#include "GHOST_Window.h"
#include "GHOST_TaskbarWin32.h"
+#ifdef WITH_INPUT_IME
+# include "GHOST_ImeWin32.h"
+#endif
#include <wintab.h>
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
@@ -253,6 +256,17 @@ public:
/** if the window currently resizing */
bool m_inLiveResize;
+#ifdef WITH_INPUT_IME
+ GHOST_ImeWin32 *getImeInput() {return &m_imeImput;}
+
+ virtual void beginIME(
+ GHOST_TInt32 x, GHOST_TInt32 y,
+ GHOST_TInt32 w, GHOST_TInt32 h,
+ int completed);
+
+ virtual void endIME();
+#endif /* WITH_INPUT_IME */
+
private:
/**
@@ -339,6 +353,11 @@ private:
/** Hwnd to parent window */
GHOST_TEmbedderWindowID m_parentWindowHwnd;
+
+#ifdef WITH_INPUT_IME
+ /** Handle input method editors event */
+ GHOST_ImeWin32 m_imeImput;
+#endif
};
#endif // __GHOST_WINDOWWIN32_H__