Package: mozilla
Version: 2:1.7.3-5
Severity: wishlist
Tags: patch
Hi,
The OverTheSpot mode of XIM is the most common input method for
Chinese/Japanese users,
but it is a pity that gtk2+ library don't support it.
There is a patch written by eliu (Vampire at Wicked Empire) <[EMAIL PROTECTED]>
could make gtk2+ library to support OverTheSpot mode.
Please visit http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=290469 for more
details.
But mozilla/mozilla-firefox/mozilla-thunderbird still need more patches to make
its supporting OverTheSpot mode.
The attached file is the patch for mozilla.
After some testing, we feel that this patch is stable enough to update to the
upstream.
Please consider to apply this.
Thanks.
-- System Information:
Debian Release: 3.1
APT prefers testing
APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.6.8-1-686
Locale: LANG=C, LC_CTYPE=zh_TW.UTF-8
Versions of packages mozilla depends on:
ii dpkg 1.10.23 Package maintenance system for Deb
ii mozilla-browser 2:1.7.3-5 The Mozilla Internet application s
ii mozilla-mailnews 2:1.7.3-5 The Mozilla Internet application s
ii mozilla-psm 2:1.7.3-5 The Mozilla Internet application s
-- no debconf information
diff -uNr mozilla.orig/widget/src/gtk2/nsCommonWidget.cpp mozilla/widget/src/gtk2/nsCommonWidget.cpp
--- mozilla.orig/widget/src/gtk2/nsCommonWidget.cpp 2005-01-03 10:09:03.000000000 +0800
+++ mozilla/widget/src/gtk2/nsCommonWidget.cpp 2005-01-03 10:09:33.000000000 +0800
@@ -459,3 +459,34 @@
return PR_FALSE;
}
+
+#include "nsWindow.h"
+
+extern nsWindow *gFocusWindow;
+
+PRBool nsCommonWidget::OnInput(nsInputEvent &aEvent)
+{
+
+ PRBool ret = PR_FALSE;
+ PRBool releaseWidget = PR_FALSE;
+ nsCommonWidget *widget = NULL;
+
+
+// printf("gFocusWindow win %x\n", gFocusWindow);
+ // rewrite the key event to the window with 'de focus
+ if (gFocusWindow) {
+ widget = gFocusWindow;
+ NS_ADDREF(widget);
+ aEvent.widget = gFocusWindow;
+ releaseWidget = PR_TRUE;
+ }
+ if (mEventCallback) {
+ nsEventStatus aStatus;
+ ret = DispatchEvent(&aEvent, aStatus);
+ }
+
+ if (releaseWidget)
+ NS_RELEASE(widget);
+
+ return ret;
+}
diff -uNr mozilla.orig/widget/src/gtk2/nsCommonWidget.h mozilla/widget/src/gtk2/nsCommonWidget.h
--- mozilla.orig/widget/src/gtk2/nsCommonWidget.h 2005-01-03 10:09:03.000000000 +0800
+++ mozilla/widget/src/gtk2/nsCommonWidget.h 2005-01-03 10:09:34.000000000 +0800
@@ -112,6 +112,10 @@
NS_IMETHOD Enable (PRBool aState);
NS_IMETHOD IsEnabled (PRBool *aState);
+
+ PRBool OnComposition(nsCompositionEvent &aEvent) { return OnInput(aEvent); };
+ PRBool OnInput(nsInputEvent &aEvent);
+
// called when we are destroyed
void OnDestroy(void);
diff -uNr mozilla.orig/widget/src/gtk2/nsWindow.cpp mozilla/widget/src/gtk2/nsWindow.cpp
--- mozilla.orig/widget/src/gtk2/nsWindow.cpp 2005-01-03 10:09:03.000000000 +0800
+++ mozilla/widget/src/gtk2/nsWindow.cpp 2005-01-03 10:09:34.000000000 +0800
@@ -74,6 +74,12 @@
static const char sAccessibilityKey [] = "config.use_system_prefs.accessibility";
#endif
+struct nsXICLookupEntry : public PLDHashEntryHdr {
+ nsWindow* mShellWindow;
+ GtkIMContext* mXIC;
+};
+
+
/* For SetIcon */
#include "nsAppDirectoryServiceDefs.h"
#include "nsXPIDLString.h"
@@ -193,7 +199,7 @@
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
// the current focus window
-static nsWindow *gFocusWindow = NULL;
+nsWindow *gFocusWindow = NULL;
static PRBool gGlobalsInitialized = PR_FALSE;
static PRBool gRaiseWindows = PR_TRUE;
static nsWindow *gPluginFocusWindow = NULL;
@@ -283,6 +289,8 @@
nsWindow::~nsWindow()
{
+ KillICSpotTimer();
+
LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
if (mLastDragMotionWindow == this) {
mLastDragMotionWindow = NULL;
@@ -1120,6 +1128,8 @@
void
nsWindow::LoseFocus(void)
{
+// printf("LoseFocus ... %x\n", this);
+
// make sure that we reset our repeat counter so the next keypress
// for this widget will get the down event
mInKeyRepeat = PR_FALSE;
@@ -1432,6 +1442,7 @@
nsWindow::OnContainerFocusInEvent(GtkWidget *aWidget, GdkEventFocus *aEvent)
{
LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this));
+
// Return if someone has blocked events for this widget. This will
// happen if someone has called gtk_widget_grab_focus() from
// nsWindow::SetFocus() and will prevent recursion.
@@ -4146,6 +4157,109 @@
#ifdef USE_XIM
+nsresult nsWindow::KillICSpotTimer ()
+{
+ if(mICSpotTimer)
+ {
+// printf("KillICSpotTimer %x\n", this);
+ mICSpotTimer->Cancel();
+ mICSpotTimer = nsnull;
+ }
+ return NS_OK;
+}
+
+nsresult nsWindow::PrimeICSpotTimer ()
+{
+ KillICSpotTimer();
+ nsresult err;
+ mICSpotTimer = do_CreateInstance("@mozilla.org/timer;1", &err);
+ if (NS_FAILED(err))
+ return err;
+// printf("PrimeICSpotTimer %x\n", this);
+ mICSpotTimer->InitWithFuncCallback(ICSpotCallback, this, 1000,
+ nsITimer::TYPE_ONE_SHOT);
+ return NS_OK;
+}
+
+void nsWindow::ICSpotCallback(nsITimer * aTimer, void * aClosure)
+{
+ nsWindow *window= NS_REINTERPRET_CAST(nsWindow*, aClosure);
+ if( ! window) return;
+ nsresult res = NS_ERROR_FAILURE;
+
+ GtkIMContext *im = window->IMEGetContext();
+
+ if (im) {
+ res = window->UpdateICSpot();
+ }
+ if(NS_SUCCEEDED(res))
+ {
+// printf("ICSpotCallback\n");
+ window->PrimeICSpotTimer();
+ }
+}
+
+nsresult nsWindow::UpdateICSpot()
+{
+ GtkIMContext *im;
+#if 1
+ if (!gFocusWindow || !(im=gFocusWindow->IMEGetContext()))
+ return NS_ERROR_FAILURE;
+#endif
+
+ // set spot location
+ nsCompositionEvent compEvent(NS_COMPOSITION_QUERY, this);
+ static gint oldx =0;
+ static gint oldy =0;
+
+ compEvent.theReply.mCursorPosition.x=-1;
+ compEvent.theReply.mCursorPosition.y=-1;
+ this->OnComposition(compEvent);
+ // set SpotLocation
+ if((compEvent.theReply.mCursorPosition.x < 0) &&
+ (compEvent.theReply.mCursorPosition.y < 0))
+ return NS_ERROR_FAILURE;
+
+// im=gFocusWindow->IMEGetContext();
+
+ if((compEvent.theReply.mCursorPosition.x != oldx)||
+ (compEvent.theReply.mCursorPosition.y != oldy))
+ {
+ nsRect a,b,c;
+
+ a.x=0; b.x=0;
+ gFocusWindow->WidgetToScreen(a, b);
+
+ GtkWidget *owningWidget =
+ get_gtk_widget_for_gdk_window(gFocusWindow->mDrawingarea->inner_window);
+ nsWindow *owningWindow = get_window_for_gtk_widget(owningWidget);
+ owningWindow->WidgetToScreen(a, c);
+
+ int dx = b.x - c.x, dy = b.y - c.y;
+
+ nsPoint spot;
+ spot.x = dx + compEvent.theReply.mCursorPosition.x;
+ spot.y = dy + compEvent.theReply.mCursorPosition.y
+#if 0
+ + compEvent.theReply.mCursorPosition.height
+#endif
+ ;
+
+ GdkRectangle rect;
+ rect.x = spot.x; rect.y = spot.y;
+ rect.width = compEvent.theReply.mCursorPosition.width;
+ rect.height = 0;
+
+// printf("cursor %d %d %x\n", spot.x, spot.y, im);
+ gtk_im_context_set_cursor_location(im, &rect);
+
+ oldx = compEvent.theReply.mCursorPosition.x;
+ oldy = compEvent.theReply.mCursorPosition.y;
+ }
+ return NS_OK;
+}
+
+
void
nsWindow::IMEDestroyContext(void)
{
@@ -4173,13 +4287,20 @@
if (!im)
return;
+// printf("IMESetFocus im:%x win:%x\n", im, this);
gtk_im_context_focus_in(im);
gIMEFocusWindow = this;
+#if 1
+ UpdateICSpot();
+ PrimeICSpotTimer();
+#endif
}
void
nsWindow::IMELoseFocus(void)
{
+ KillICSpotTimer();
+
LOGIM(("IMELoseFocus %p\n", (void *)this));
GtkIMContext *im = IMEGetContext();
if (!im)
@@ -4423,6 +4544,13 @@
}
g_free(uniStr);
+
+#ifdef USE_XIM && 1
+ if (window->IMEGetContext()) {
+ window->UpdateICSpot();
+ window->PrimeICSpotTimer();
+ }
+#endif // USE_XIM
}
#define START_OFFSET(I) \
@@ -4550,6 +4678,9 @@
GtkIMContext *
IM_get_input_context(MozDrawingarea *aArea)
{
+ if (!aArea)
+ return NULL;
+
GtkWidget *owningWidget =
get_gtk_widget_for_gdk_window(aArea->inner_window);
diff -uNr mozilla.orig/widget/src/gtk2/nsWindow.h mozilla/widget/src/gtk2/nsWindow.h
--- mozilla.orig/widget/src/gtk2/nsWindow.h 2005-01-03 10:09:03.000000000 +0800
+++ mozilla/widget/src/gtk2/nsWindow.h 2005-01-03 10:09:35.000000000 +0800
@@ -269,6 +269,13 @@
GtkIMContext *mIMContext;
PRBool mComposingText;
+ nsCOMPtr<nsITimer> mICSpotTimer;
+ static void ICSpotCallback(nsITimer* aTimer, void* aClosure);
+ nsresult KillICSpotTimer();
+ nsresult PrimeICSpotTimer();
+ nsresult UpdateICSpot();
+
+
#endif
void ResizeTransparencyBitmap(PRInt32 aNewWidth, PRInt32 aNewHeight);