[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48829] branches/soc-2011-tomato: Merging r48826 through r48828 from trunk into soc-2011-tomato

Sergey Sharybin sergey.vfx at gmail.com
Wed Jul 11 12:39:08 CEST 2012


Revision: 48829
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48829
Author:   nazgul
Date:     2012-07-11 10:39:08 +0000 (Wed, 11 Jul 2012)
Log Message:
-----------
Merging r48826 through r48828 from trunk into soc-2011-tomato

Revision Links:
--------------
    http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48826
    http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48828

Modified Paths:
--------------
    branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.cpp
    branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.h
    branches/soc-2011-tomato/intern/ghost/intern/GHOST_WindowX11.cpp
    branches/soc-2011-tomato/intern/ghost/intern/GHOST_WindowX11.h
    branches/soc-2011-tomato/release/scripts/startup/bl_ui/space_clip.py
    branches/soc-2011-tomato/source/blender/editors/mask/mask_edit.c
    branches/soc-2011-tomato/source/blender/editors/mask/mask_intern.h
    branches/soc-2011-tomato/source/blender/editors/mask/mask_ops.c

Property Changed:
----------------
    branches/soc-2011-tomato/
    branches/soc-2011-tomato/source/blender/editors/interface/interface.c
    branches/soc-2011-tomato/source/blender/editors/space_outliner/


Property changes on: branches/soc-2011-tomato
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/ge_harmony:42255,42279-42282,42286,42302,42338,42349,42616,42620,42698-42699,42739,42753,42773-42774,42832,44568,44597-44598,44793-44794
/branches/soc-2011-cucumber:37517,38166-38167,38177,38179-38180,38187,38242,38384,38387,38403-38404,38407,38968,38970,38973,39045,40845,42997-42998,43439
/branches/vgroup_modifiers:38694-39989
/trunk/blender:36831-48825
   + /branches/ge_harmony:42255,42279-42282,42286,42302,42338,42349,42616,42620,42698-42699,42739,42753,42773-42774,42832,44568,44597-44598,44793-44794
/branches/soc-2011-cucumber:37517,38166-38167,38177,38179-38180,38187,38242,38384,38387,38403-38404,38407,38968,38970,38973,39045,40845,42997-42998,43439
/branches/vgroup_modifiers:38694-39989
/trunk/blender:36831-48828

Modified: branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.cpp
===================================================================
--- branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.cpp	2012-07-11 10:37:38 UTC (rev 48828)
+++ branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.cpp	2012-07-11 10:39:08 UTC (rev 48829)
@@ -93,9 +93,12 @@
 		abort(); //was return before, but this would just mean it will crash later
 	}
 
-	/* Open a connection to the X input manager */
 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-	m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
+	/* note -- don't open connection to XIM server here, because the locale
+	 * has to be set before opening the connection but setlocale() has not
+	 * been called yet.  the connection will be opened after entering
+	 * the event loop. */
+	m_xim = NULL;
 #endif
 
 	m_delete_window_atom 
@@ -273,6 +276,35 @@
 	return window;
 }
 
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+static void destroyIMCallback(XIM xim, XPointer ptr, XPointer data)
+{
+	GHOST_PRINT("XIM server died\n");
+
+	if (ptr)
+		*(XIM *)ptr = NULL;
+}
+
+bool GHOST_SystemX11::openX11_IM()
+{
+	if (!m_display)
+		return false;
+
+	/* set locale modifiers such as "@im=ibus" specified by XMODIFIERS */
+	XSetLocaleModifiers("");
+
+	m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
+	if (!m_xim)
+		return false;
+
+	XIMCallback destroy;
+	destroy.callback = (XIMProc)destroyIMCallback;
+	destroy.client_data = (XPointer)&m_xim;
+	XSetIMValues(m_xim, XNDestroyCallback, &destroy, NULL);
+	return true;
+}
+#endif
+
 GHOST_WindowX11 *
 GHOST_SystemX11::
 findGhostWindow(
@@ -408,6 +440,38 @@
 		while (XPending(m_display)) {
 			XEvent xevent;
 			XNextEvent(m_display, &xevent);
+
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+			/* open connection to XIM server and create input context (XIC)
+			 * when receiving the first FocusIn or KeyPress event after startup,
+			 * or recover XIM and XIC when the XIM server has been restarted */
+			if (xevent.type == FocusIn || xevent.type == KeyPress) {
+				if (!m_xim && openX11_IM()) {
+					GHOST_PRINT("Connected to XIM server\n");
+				}
+
+				if (m_xim) {
+					GHOST_WindowX11 * window = findGhostWindow(xevent.xany.window);
+					if (window && !window->getX11_XIC() && window->createX11_XIC()) {
+						GHOST_PRINT("XIM input context created\n");
+						if (xevent.type == KeyPress)
+							/* we can assume the window has input focus
+							 * here, because key events are received only
+							 * when the window is focused. */
+							XSetICFocus(window->getX11_XIC());
+					}
+				}
+			}
+
+			/* dispatch event to XIM server */
+			if ((XFilterEvent(&xevent, (Window)NULL) == True) && (xevent.type != KeyRelease)) {
+				/* do nothing now, the event is consumed by XIM.
+				 * however, KeyRelease event should be processed
+				 * here, otherwise modifiers remain activated.   */
+				continue;
+			}
+#endif
+
 			processEvent(&xevent);
 			anyProcessed = true;
 		}
@@ -535,7 +599,19 @@
 			XKeyEvent *xke = &(xe->xkey);
 			KeySym key_sym = XLookupKeysym(xke, 0);
 			char ascii;
-			char utf8_buf[6]; /* 6 is enough for a utf8 char */
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+			/* utf8_array[] is initial buffer used for Xutf8LookupString().
+			 * if the length of the utf8 string exceeds this array, allocate
+			 * another memory area and call Xutf8LookupString() again.
+			 * the last 5 bytes are used to avoid segfault that might happen
+			 * at the end of this buffer when the constructor of GHOST_EventKey
+			 * reads 6 bytes regardless of the effective data length. */
+			char utf8_array[16 * 6 + 5]; /* 16 utf8 characters */
+			char *utf8_buf = utf8_array;
+			int len = 1; /* at least one null character will be stored */
+#else
+			char *utf8_buf = NULL;
+#endif
 			
 			GHOST_TKey gkey = convertXKey(key_sym);
 			GHOST_TEventType type = (xke->type == KeyPress) ? 
@@ -547,15 +623,20 @@
 			
 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
 			/* getting unicode on key-up events gives XLookupNone status */
-			if (xke->type == KeyPress) {
+			XIC xic = window->getX11_XIC();
+			if (xic && xke->type == KeyPress) {
 				Status status;
-				int len;
 
 				/* use utf8 because its not locale depentant, from xorg docs */
-				if (!(len = Xutf8LookupString(window->getX11_XIC(), xke, utf8_buf, sizeof(utf8_buf), &key_sym, &status))) {
+				if (!(len = Xutf8LookupString(xic, xke, utf8_buf, sizeof(utf8_array) - 5, &key_sym, &status))) {
 					utf8_buf[0] = '\0';
 				}
 
+				if (status == XBufferOverflow) {
+					utf8_buf = (char *) malloc(len + 5);
+					len = Xutf8LookupString(xic, xke, utf8_buf, len, &key_sym, &status);
+				}
+
 				if ((status == XLookupChars || status == XLookupBoth)) {
 					if ((unsigned char)utf8_buf[0] >= 32) { /* not an ascii control character */
 						/* do nothing for now, this is valid utf8 */
@@ -571,19 +652,16 @@
 				else {
 					printf("Bad keycode lookup. Keysym 0x%x Status: %s\n",
 					       (unsigned int) key_sym,
-					       (status == XBufferOverflow ? "BufferOverflow" :
-					        status == XLookupNone ? "XLookupNone" :
+					       (status == XLookupNone ? "XLookupNone" :
 					        status == XLookupKeySym ? "XLookupKeySym" :
 					        "Unknown status"));
 
-					printf("'%.*s' %p %p\n", len, utf8_buf, window->getX11_XIC(), m_xim);
+					printf("'%.*s' %p %p\n", len, utf8_buf, xic, m_xim);
 				}
 			}
 			else {
 				utf8_buf[0] = '\0';
 			}
-#else
-			utf8_buf[0] = '\0';
 #endif
 
 			g_event = new
@@ -595,6 +673,42 @@
 			    ascii,
 			    utf8_buf
 			    );
+
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+			/* when using IM for some languages such as Japanese,
+			 * one event inserts multiple utf8 characters */
+			if (xic && xke->type == KeyPress) {
+				unsigned char c;
+				int i = 0;
+				while (1) {
+					/* search character boundary */
+					if ((unsigned char)utf8_buf[i++] > 0x7f) {
+						for (; i < len; ++i) {
+							c = utf8_buf[i];
+							if (c < 0x80 || c > 0xbf) break;
+						}
+					}
+
+					if (i >= len) break;
+
+					/* enqueue previous character */
+					pushEvent(g_event);
+
+					g_event = new
+					          GHOST_EventKey(
+					    getMilliSeconds(),
+					    type,
+					    window,
+					    gkey,
+					    '\0',
+					    &utf8_buf[i]
+					    );
+				}
+			}
+
+			if (utf8_buf != utf8_array)
+				free(utf8_buf);
+#endif
 			
 			break;
 		}
@@ -675,6 +789,16 @@
 			GHOST_TEventType gtype = (xfe.type == FocusIn) ? 
 			                         GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
 
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+			XIC xic = window->getX11_XIC();
+			if (xic) {
+				if (xe->type == FocusIn)
+					XSetICFocus(xic);
+				else
+					XUnsetICFocus(xic);
+			}
+#endif
+
 			g_event = new 
 			          GHOST_Event(
 			    getMilliSeconds(),

Modified: branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.h
===================================================================
--- branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.h	2012-07-11 10:37:38 UTC (rev 48828)
+++ branches/soc-2011-tomato/intern/ghost/intern/GHOST_SystemX11.h	2012-07-11 10:39:08 UTC (rev 48829)
@@ -309,6 +309,10 @@
 	 * X11 window xwind
 	 */
 
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+	bool openX11_IM();
+#endif
+
 	GHOST_WindowX11 *
 	findGhostWindow(
 	    Window xwind

Modified: branches/soc-2011-tomato/intern/ghost/intern/GHOST_WindowX11.cpp
===================================================================
--- branches/soc-2011-tomato/intern/ghost/intern/GHOST_WindowX11.cpp	2012-07-11 10:37:38 UTC (rev 48828)
+++ branches/soc-2011-tomato/intern/ghost/intern/GHOST_WindowX11.cpp	2012-07-11 10:39:08 UTC (rev 48829)
@@ -401,10 +401,7 @@
 	}
 
 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
-	m_xic = XCreateIC(m_system->getX11_XIM(), XNClientWindow, m_window, XNFocusWindow, m_window,
-	                  XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
-	                  XNResourceName, GHOST_X11_RES_NAME, XNResourceClass,
-	                  GHOST_X11_RES_CLASS, NULL);
+	m_xic = NULL;
 #endif
 
 	// Set the window icon
@@ -478,6 +475,47 @@
 	XFlush(m_display);
 }
 
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+static void destroyICCallback(XIC xic, XPointer ptr, XPointer data)
+{
+	GHOST_PRINT("XIM input context destroyed\n");
+
+	if (ptr) {
+		*(XIC *)ptr = NULL;
+	}
+}
+
+bool GHOST_WindowX11::createX11_XIC()
+{
+	XIM xim = m_system->getX11_XIM();
+	if (!xim)
+		return false;
+
+	XICCallback destroy;
+	destroy.callback = (XICProc)destroyICCallback;
+	destroy.client_data = (XPointer)&m_xic;
+	m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
+	                  XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+	                  XNResourceName, GHOST_X11_RES_NAME,
+	                  XNResourceClass, GHOST_X11_RES_CLASS,
+	                  XNDestroyCallback, &destroy,
+	                  NULL);
+	if (!m_xic)
+		return false;
+
+	unsigned long fevent;
+	XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
+	XSelectInput(m_display, m_window,
+	             ExposureMask | StructureNotifyMask |
+	             KeyPressMask | KeyReleaseMask |
+	             EnterWindowMask | LeaveWindowMask |
+	             ButtonPressMask | ButtonReleaseMask |
+	             PointerMotionMask | FocusChangeMask |

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list