Package: mozilla-thunderbird
Version: 0.9-6
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-firefox and mozilla-thunderbird.
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-thunderbird depends on:
ii  libatk1.0-0              1.8.0-3         The ATK accessibility toolkit
ii  libc6                    2.3.2.ds1-16    GNU C Library: Shared libraries an
ii  libfontconfig1           2.2.3-4.firefly generic font configuration library
ii  libfreetype6             2.1.7-2.2       FreeType 2 font engine, shared lib
ii  libgcc1                  1:3.4.1-5       GCC support library
ii  libglib2.0-0             2.4.7-1         The GLib library of C routines
ii  libgtk2.0-0              2.4.4-2         The GTK+ graphical user interface 
ii  libpango1.0-0            1.6.0-3         Layout and rendering of internatio
ii  libstdc++5               1:3.3.4-6sarge1 The GNU Standard C++ Library v3
ii  libx11-6                 4.3.0.dfsg.1-6  X Window System protocol client li
ii  libxext6                 4.3.0.dfsg.1-6  X Window System miscellaneous exte
ii  libxft2                  2.1.2-6.firefly FreeType-based font drawing librar
ii  libxp6                   4.3.0.dfsg.1-4  X Window System printing extension
ii  libxrender1              0.8.3-7         X Rendering Extension client libra
ii  libxt6                   4.3.0.dfsg.1-4  X Toolkit Intrinsics
ii  xlibs                    4.3.0.dfsg.1-4  X Window System client libraries m
ii  zlib1g                   1:1.2.1.1-5     compression library - runtime

-- 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-08 18:40:36.000000000 +0800
+++ mozilla/widget/src/gtk2/nsCommonWidget.cpp	2005-01-08 18:42:01.000000000 +0800
@@ -451,3 +451,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-08 18:40:36.000000000 +0800
+++ mozilla/widget/src/gtk2/nsCommonWidget.h	2005-01-08 18:43:26.000000000 +0800
@@ -112,6 +112,9 @@
     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-08 18:40:36.000000000 +0800
+++ mozilla/widget/src/gtk2/nsWindow.cpp	2005-01-08 18:51:37.000000000 +0800
@@ -73,6 +73,11 @@
 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"
@@ -189,7 +194,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;
@@ -276,6 +281,8 @@
 
 nsWindow::~nsWindow()
 {
+    KillICSpotTimer();
+
     LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
     if (mLastDragMotionWindow == this) {
         mLastDragMotionWindow = NULL;
@@ -1155,6 +1162,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;
@@ -3898,6 +3907,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)
 {
@@ -3925,13 +4037,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)
@@ -4175,6 +4294,13 @@
     }
 
     g_free(uniStr);
+
+#ifdef USE_XIM && 1
+    if (window->IMEGetContext()) {
+        window->UpdateICSpot();
+        window->PrimeICSpotTimer();
+    }
+#endif // USE_XIM
 }
 
 #define	START_OFFSET(I)	\
@@ -4302,6 +4428,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-08 18:40:36.000000000 +0800
+++ mozilla/widget/src/gtk2/nsWindow.h	2005-01-08 18:49:40.000000000 +0800
@@ -267,6 +267,11 @@
     GtkIMContext       *mIMContext;
     PRBool             mComposingText;
 
+    nsCOMPtr<nsITimer> mICSpotTimer;
+    static void        ICSpotCallback(nsITimer* aTimer, void* aClosure);
+    nsresult           KillICSpotTimer();
+    nsresult           PrimeICSpotTimer();
+    nsresult           UpdateICSpot();
 #endif
 
 private:

Reply via email to