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

Reply via email to