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);