From owner-freebsd-ports-bugs Fri Mar 7 11:10:36 2003 Delivered-To: freebsd-ports-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2CA7337B405 for ; Fri, 7 Mar 2003 11:10:16 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id E91C043FDD for ; Fri, 7 Mar 2003 11:10:11 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id h27JABNS029087 for ; Fri, 7 Mar 2003 11:10:11 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id h27JABEP029086; Fri, 7 Mar 2003 11:10:11 -0800 (PST) Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 29F2F37B401 for ; Fri, 7 Mar 2003 11:00:44 -0800 (PST) Received: from aeimail.aei.ca (aeimail.aei.ca [206.123.6.14]) by mx1.FreeBSD.org (Postfix) with ESMTP id BE63643FDF for ; Fri, 7 Mar 2003 11:00:39 -0800 (PST) (envelope-from anarcat@anarcat.ath.cx) Received: from shall.anarcat.ath.cx (fq7ae1k21679tg67@dsl-131-237.aei.ca [66.36.131.237]) by aeimail.aei.ca (8.11.6/8.10.1) with ESMTP id h27J0ah00858 for ; Fri, 7 Mar 2003 14:00:37 -0500 (EST) Received: from lenny.anarcat.ath.cx (lenny.anarcat.ath.cx [192.168.0.4]) by shall.anarcat.ath.cx (Postfix) with SMTP id CECD32F4; Fri, 7 Mar 2003 14:00:35 -0500 (EST) Received: by lenny.anarcat.ath.cx (sSMTP sendmail emulation); Fri, 7 Mar 2003 14:00:47 -0500 Message-Id: <20030307190035.CECD32F4@shall.anarcat.ath.cx> Date: Fri, 7 Mar 2003 14:00:47 -0500 From: The Anarcat Reply-To: The Anarcat To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: ports/49010: [patch] dead keys can't be entered in mozilla-devel-gtk2-1.3b Sender: owner-freebsd-ports-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 49010 >Category: ports >Synopsis: [patch] dead keys can't be entered in mozilla-devel-gtk2-1.3b >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Mar 07 11:10:11 PST 2003 >Closed-Date: >Last-Modified: >Originator: The Anarcat >Release: FreeBSD 5.0-RELEASE i386 >Organization: >Environment: System: FreeBSD lenny.anarcat.ath.cx 5.0-RELEASE FreeBSD 5.0-RELEASE #1: Sun Feb 16 23:11:48 EST 2003 anarcat@lenny.anarcat.ath.cx:/usr/src/sys/i386/compile/LENNII i386 >Description: The latest development version of the Mozilla port, compiled with gtk2, shows a pretty annoying bug for non-english users: carets and other dead keys cannot be entered in forms and such. The bugzilla database has the whole story: http://bugzilla.mozilla.org/show_bug.cgi?id=176713 is the original bug, which actually depends on: http://bugzilla.mozilla.org/show_bug.cgi?id=176514 which appeared because XIM was disabled as described in: http://bugzilla.mozilla.org/show_bug.cgi?id=176514#c5 >How-To-Repeat: 1. Start mozilla-gtk2-1.3b 2. try to type a dead key (say a caret) followed by a "e" You should see "ê", but instead "e" shows up. >Fix: [note that I'm still waiting confirmation from the Mozilla developpers that my patch is sane, but it looks ok and works] The port can carry the following patch: --- /usr/ports/www/mozilla-devel-gtk2/Makefile.orig Fri Mar 7 13:56:49 2003 +++ /usr/ports/www/mozilla-devel-gtk2/Makefile Fri Mar 7 13:56:43 2003 @@ -16,4 +16,6 @@ WITH_GTK2= yes MOZILLA= mozilla-devel-gtk2 +EXTRA_PATCHES= ${FILESDIR}/xim_dekita2.patch + .include "${MASTERDIR}/Makefile" And this should be put in the files section of the master port. This patch is also available in bugzilla: http://bugzilla.mozilla.org/attachment.cgi?id=116566&action=view --- /dev/null Fri Mar 7 13:57:43 2003 +++ /usr/ports/www/mozilla-devel/files/xim_dekita2.patch Fri Mar 7 10:28:19 2003 @@ -0,0 +1,517 @@ +Index: Makefile.in +=================================================================== +RCS file: /cvsroot/mozilla/widget/src/gtk2/Makefile.in,v +retrieving revision 1.24 +diff -u -r1.24 Makefile.in +--- widget/src/gtk2/Makefile.in 28 Dec 2002 01:14:45 -0000 1.24 ++++ widget/src/gtk2/Makefile.in 7 Mar 2003 07:39:24 -0000 +@@ -90,7 +90,7 @@ + CFLAGS += $(MOZ_GTK2_CFLAGS) + CXXFLAGS += $(MOZ_GTK2_CFLAGS) + +-#DEFINES += -DUSE_XIM ++DEFINES += -DUSE_XIM + + INCLUDES += \ + -I$(srcdir)/../xpwidgets \ +Index: nsWindow.cpp +=================================================================== +RCS file: /cvsroot/mozilla/widget/src/gtk2/nsWindow.cpp,v +retrieving revision 1.68 +diff -u -r1.68 nsWindow.cpp +--- widget/src/gtk2/nsWindow.cpp 5 Mar 2003 23:17:28 -0000 1.68 ++++ widget/src/gtk2/nsWindow.cpp 6 Mar 2003 02:22:39 -0000 +@@ -179,6 +179,7 @@ + nsWeakPtr gRollupWindow; + + #ifdef USE_XIM ++static nsWindow *gIMEFocusWindow = NULL; + + struct nsXICLookupEntry { + PLDHashEntryHdr mKeyHash; +@@ -186,7 +187,9 @@ + GtkIMContext* mXIC; + }; + +-PLDHashTable nsWindow::gXICLookupTable; ++PLDHashTable nsWindow::gXICLookupTable; ++GdkEventKey* nsWindow::gIMEKeyEvent = NULL; ++PRBool nsWindow::gIMEStringCommited = PR_TRUE; + + static void IM_commit_cb (GtkIMContext *context, + const gchar *str, +@@ -257,61 +260,6 @@ + #endif + } + +-#ifdef USE_XIM +-void +-nsWindow::IMEGetShellWindow(void) +-{ +- GtkWidget* top_window = nsnull; +- GetToplevelWidget(&top_window); +- if (top_window) { +- mIMEShellWindow = get_window_for_gtk_widget(top_window); +- } +-} +- +-GtkIMContext* +-nsWindow::IMEGetContext() +-{ +- if (!mIMEShellWindow) { +- return NULL; +- } +- PLDHashEntryHdr* hash_entry; +- nsXICLookupEntry* entry; +- +- hash_entry = PL_DHashTableOperate(&gXICLookupTable, +- mIMEShellWindow, PL_DHASH_LOOKUP); +- +- if (hash_entry) { +- entry = NS_REINTERPRET_CAST(nsXICLookupEntry *, hash_entry); +- if (entry->mXIC) { +- return entry->mXIC; +- } +- } +- return NULL; +-} +- +-void +-nsWindow::IMECreateContext(GdkWindow* aGdkWindow) +-{ +- PLDHashEntryHdr* hash_entry; +- nsXICLookupEntry* entry; +- GtkIMContext *im = gtk_im_multicontext_new(); +- if (im) { +- hash_entry = PL_DHashTableOperate(&gXICLookupTable, this, PL_DHASH_ADD); +- if (hash_entry) { +- entry = NS_REINTERPRET_CAST(nsXICLookupEntry *, hash_entry); +- entry->mShellWindow = this; +- entry->mXIC = im; +- } +- gtk_im_context_set_client_window(im, aGdkWindow); +- g_signal_connect(G_OBJECT(im), "commit", +- G_CALLBACK(IM_commit_cb), this); +- g_signal_connect(G_OBJECT(im), "preedit_changed", +- G_CALLBACK(IM_preedit_changed_cb), this); +- this->mIMEShellWindow = this; +- } +-} +-#endif +- + nsWindow::~nsWindow() + { + LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this)); +@@ -397,22 +345,7 @@ + } + + #ifdef USE_XIM +- GtkIMContext *im = IMEGetContext(); +- // If this is the focus window and we have an IM context we need +- // to unset the focus on this window before we destroy the window. +- if (im && gFocusWindow == this) { +- LOGFOCUS((" gtk_im_context_focus_out() from Destroy()\n")); +- gtk_im_context_focus_out(im); +- } +- +- // if shell, delete GtkIMContext +- if (im && mShell) { +- gtk_im_context_reset(im); +- PL_DHashTableOperate(&gXICLookupTable, this, PL_DHASH_REMOVE); +- g_object_unref(G_OBJECT(im)); +- } +- +- mIMEShellWindow = nsnull; ++ IMEDestroyContext(); + #endif + + // make sure that we remove ourself as the focus window +@@ -656,21 +589,30 @@ + return NS_OK; + } + ++#ifdef USE_XIM ++ if (mWindowType == eWindowType_child && !mIMEShellWindow) { ++ IMEGetShellWindow(); ++ } ++#endif ++ + // If there is already a focued child window, dispatch a LOSTFOCUS + // event from that widget and unset its got focus flag. +- if (gFocusWindow) ++ if (gFocusWindow) { ++#ifdef USE_XIM ++ // If same ic is focused, do not call LoseFocus() ++ if (mIMEShellWindow != gFocusWindow->mIMEShellWindow) { ++ gFocusWindow->IMELoseFocus(); ++ } ++#endif + gFocusWindow->LoseFocus(); ++ } + + // Set this window to be the focused child window, update our has + // focus flag and dispatch a GOTFOCUS event. + gFocusWindow = this; + + #ifdef USE_XIM +- GtkIMContext *im = IMEGetContext(); +- if (im && !mIsTopLevel) { +- LOGFOCUS((" gtk_im_context_focus_in()\n")); +- gtk_im_context_focus_in(im); +- } ++ IMESetFocus(); + #endif + + LOGFOCUS((" widget now has focus - dispatching events [%p]\n", +@@ -1165,18 +1107,6 @@ + void + nsWindow::LoseFocus(void) + { +-#ifdef USE_XIM +- GtkIMContext *im = IMEGetContext(); +- if (im && !mIsTopLevel) { +- LOGFOCUS((" gtk_im_context_focus_out()\n")); +- gtk_im_context_focus_out(im); +- IMEComposeStart(); +- IMEComposeText(NULL, 0, NULL, NULL); +- IMEComposeEnd(); +- LOG(("gtk_im_context_focus_out\n")); +- } +-#endif +- + // make sure that we reset our repeat counter so the next keypress + // for this widget will get the down event + mInKeyRepeat = PR_FALSE; +@@ -1449,6 +1379,7 @@ + DispatchEvent(&event, status); + } + ++ + void + nsWindow::OnContainerFocusInEvent(GtkWidget *aWidget, GdkEventFocus *aEvent) + { +@@ -1516,6 +1447,9 @@ + + foundit: + ++#ifdef USE_XIM ++ gFocusWindow->IMELoseFocus(); ++#endif + gFocusWindow->LoseFocus(); + + // We only dispatch a deactivate event if we are a toplevel +@@ -1537,7 +1471,7 @@ + #ifdef USE_XIM + GtkIMContext *im = IMEGetContext(); + if (im) { +- if (gtk_im_context_filter_keypress(im, aEvent)) { ++ if (IMFilterKeypress(im, aEvent)) { + LOGFOCUS((" keypress filtered by XIM\n")); + return TRUE; + } +@@ -1621,7 +1555,7 @@ + #ifdef USE_XIM + GtkIMContext *im = IMEGetContext(); + if (im) { +- if (gtk_im_context_filter_keypress(im, aEvent)) { ++ if (IMFilterKeypress(im, aEvent)) { + LOGFOCUS((" keypress filtered by XIM\n")); + return TRUE; + } +@@ -2155,6 +2089,15 @@ + + // and the drawing area + mDrawingarea = moz_drawingarea_new(nsnull, mContainer); ++ ++#ifdef USE_XIM ++#ifndef XIM_CREATE_IC_AT_FOCUS ++ if (mWindowType != eWindowType_popup) { ++ // create im context for shell ++ IMECreateContext(mShell->window); ++ } ++#endif /* XIM_CREATE_IC_AT_FOCUS */ ++#endif /* USE_XIM */ + } + break; + case eWindowType_child: { +@@ -2167,11 +2110,13 @@ + gtk_widget_realize(GTK_WIDGET(mContainer)); + + mDrawingarea = moz_drawingarea_new(nsnull, mContainer); +- } + #ifdef USE_XIM +- // get mIMEShellWindow and keep it +- IMEGetShellWindow(); +-#endif ++#ifndef XIM_CREATE_IC_AT_FOCUS ++ // create im context for gtk container ++ IMECreateContext(GTK_WIDGET(mContainer)->window); ++#endif /* XIM_CREATE_IC_AT_FOCUS */ ++#endif /* USE_XIM */ ++ } + } + break; + default: +@@ -2216,13 +2161,6 @@ + G_CALLBACK(property_notify_event_cb), NULL); + } + +-#ifdef USE_XIM +- if (mShell) { +- // init GtkIMContext for shell +- IMECreateContext(mShell->window); +- } +-#endif +- + if (mContainer) { + g_signal_connect_after(G_OBJECT(mContainer), "size_allocate", + G_CALLBACK(size_allocate_cb), NULL); +@@ -3667,6 +3605,77 @@ + } + + #ifdef USE_XIM ++void ++nsWindow::IMEGetShellWindow(void) ++{ ++ GtkWidget* top_window = nsnull; ++ GetToplevelWidget(&top_window); ++ if (top_window) { ++ mIMEShellWindow = get_window_for_gtk_widget(top_window); ++ if (mIMEShellWindow) { ++ return; ++ } ++ } ++ ++ // find deepest nsWindow ++ if (!mDrawingarea) { ++ return; ++ } ++ GdkWindow *parent = gdk_window_get_parent(mDrawingarea->inner_window); ++ while (parent) { ++ nsWindow *window = get_window_for_gdk_window(parent); ++ if (window == nsnull) { ++ break; ++ } ++ if (window->mContainer) { ++ mIMEShellWindow = window; ++ } ++ parent = gdk_window_get_parent (parent); ++ } ++} ++ ++GtkIMContext* ++nsWindow::IMEGetContext() ++{ ++ if (!mIMEShellWindow) { ++ return NULL; ++ } ++ PLDHashEntryHdr* hash_entry; ++ nsXICLookupEntry* entry; ++ ++ hash_entry = PL_DHashTableOperate(&gXICLookupTable, ++ mIMEShellWindow, PL_DHASH_LOOKUP); ++ ++ if (hash_entry) { ++ entry = NS_REINTERPRET_CAST(nsXICLookupEntry *, hash_entry); ++ if (entry->mXIC) { ++ return entry->mXIC; ++ } ++ } ++ return NULL; ++} ++ ++void ++nsWindow::IMECreateContext(GdkWindow* aGdkWindow) ++{ ++ PLDHashEntryHdr* hash_entry; ++ nsXICLookupEntry* entry; ++ GtkIMContext *im = gtk_im_multicontext_new(); ++ if (im) { ++ hash_entry = PL_DHashTableOperate(&gXICLookupTable, this, PL_DHASH_ADD); ++ if (hash_entry) { ++ entry = NS_REINTERPRET_CAST(nsXICLookupEntry *, hash_entry); ++ entry->mShellWindow = this; ++ entry->mXIC = im; ++ } ++ gtk_im_context_set_client_window(im, aGdkWindow); ++ g_signal_connect(G_OBJECT(im), "commit", ++ G_CALLBACK(IM_commit_cb), this); ++ g_signal_connect(G_OBJECT(im), "preedit_changed", ++ G_CALLBACK(IM_preedit_changed_cb), this); ++ this->mIMEShellWindow = this; ++ } ++} + + void + nsWindow::IMEComposeStart(void) +@@ -3737,6 +3746,26 @@ + DispatchEvent(&compEvent, status); + } + ++PRBool ++nsWindow::IMFilterKeypress (GtkIMContext *context, ++ GdkEventKey *aEvent) ++{ ++ gIMEKeyEvent = aEvent; ++ if (gtk_im_context_filter_keypress(context, aEvent)) { ++ /* return true if the keyevent is commited as string and ++ ** has been dispatched as TextEvent. ++ */ ++ if( gIMEStringCommited ) { ++ return TRUE; ++ } ++ gIMEStringCommited = PR_TRUE; ++ } ++ gIMEKeyEvent = NULL; ++ ++ /* the Keyevent is not filtered by IME */ ++ return FALSE; ++} ++ + /* static */ + void + IM_preedit_changed_cb(GtkIMContext *context, +@@ -3747,7 +3776,8 @@ + PangoAttrList *feedback_list; + + // call for focused window +- nsWindow *window = gFocusWindow; ++ // if gFocusWindow is null, use the last focused gIMEFocusWindow ++ nsWindow *window = gFocusWindow ? gFocusWindow : gIMEFocusWindow; + if (!window) return; + + // Should use cursor_pos ? +@@ -3760,6 +3790,7 @@ + if (!preedit_string || !*preedit_string) { + window->IMEComposeStart(); + window->IMEComposeText(NULL, 0, NULL, NULL); ++ window->IMEComposeEnd(); + return; + } + +@@ -3800,9 +3831,31 @@ + glong uniStrLen; + + // call for focused window +- nsWindow *window = gFocusWindow; ++ // if gFocusWindow is null, use the last focused gIMEFocusWindow ++ nsWindow *window = gFocusWindow ? gFocusWindow : gIMEFocusWindow; + if (!window) return; + ++ /* if the IME does not change the keystrock, we won't send it ++ * through the TextEvent. ++ */ ++ nsWindow::gIMEStringCommited = PR_TRUE; ++ if ( nsWindow::gIMEKeyEvent ) ++ { ++ char keyval_utf8[8]; /* should have at least 6 bytes of space */ ++ gint keyval_utf8_len; ++ keyval_utf8_len = g_unichar_to_utf8( ++ gdk_keyval_to_unicode(nsWindow::gIMEKeyEvent->keyval), ++ keyval_utf8); ++ ++ keyval_utf8[keyval_utf8_len] = '\0'; ++ if ( strcmp(utf8_str, keyval_utf8) == 0) ++ { ++ nsWindow::gIMEStringCommited = PR_FALSE; ++ return; ++ } ++ nsWindow::gIMEKeyEvent = NULL; ++ } ++ + uniStr = NULL; + uniStrLen = 0; + uniStr = g_utf8_to_utf16(utf8_str, -1, NULL, &uniStrLen, NULL); +@@ -3944,6 +3997,60 @@ + *aTextRangeListLengthResult = count + 1; + + pango_attr_iterator_destroy(aFeedbackIterator); ++} ++ ++void ++nsWindow::IMELoseFocus(void) ++{ ++ GtkIMContext *im = IMEGetContext(); ++ if (!im) { ++ return; ++ } ++ gtk_im_context_focus_out(im); ++} ++ ++void ++nsWindow::IMESetFocus(void) ++{ ++ GtkIMContext *im = IMEGetContext(); ++#ifdef XIM_CREATE_IC_AT_FOCUS ++ if (!im && mIMEShellWindow) { ++ if (mIMEShellWindow->mShell) { ++ // init GtkIMContext for shell ++ mIMEShellWindow->IMECreateContext(mIMEShellWindow->mShell->window); ++ } else if (mIMEShellWindow->mContainer) { ++ // init GtkIMContext for mContainer ++ mIMEShellWindow->IMECreateContext(GTK_WIDGET(mIMEShellWindow->mContainer)->window); ++ } ++ } ++ im = IMEGetContext(); ++#endif /* XIM_CREATE_IC_AT_FOCUS */ ++ if (!im) { ++ return; ++ } ++ gtk_im_context_focus_in(im); ++ gIMEFocusWindow = this; ++} ++ ++void ++nsWindow::IMEDestroyContext(void) ++{ ++ GtkIMContext *im = IMEGetContext(); ++ if (im) { ++ // If this is the focus window and we have an IM context we need ++ // to unset the focus on this window before we destroy the window. ++ if (gIMEFocusWindow == this) { ++ gIMEFocusWindow->IMELoseFocus(); ++ gIMEFocusWindow = nsnull; ++ } ++ // if shell, delete GtkIMContext ++ if (mIMEShellWindow == this) { ++ gtk_im_context_set_client_window(im, NULL); ++ PL_DHashTableOperate(&gXICLookupTable, this, PL_DHASH_REMOVE); ++ g_object_unref(G_OBJECT(im)); ++ } ++ } ++ mIMEShellWindow = nsnull; + } + + #endif +Index: nsWindow.h +=================================================================== +RCS file: /cvsroot/mozilla/widget/src/gtk2/nsWindow.h,v +retrieving revision 1.32 +diff -u -r1.32 nsWindow.h +--- widget/src/gtk2/nsWindow.h 17 Feb 2003 18:50:01 -0000 1.32 ++++ widget/src/gtk2/nsWindow.h 6 Mar 2003 02:22:39 -0000 +@@ -239,6 +239,9 @@ + static guint32 mLastButtonPressTime; + + #ifdef USE_XIM ++ void IMEDestroyContext(void); ++ void IMESetFocus(void); ++ void IMELoseFocus(void); + void IMEComposeStart(void); + void IMEComposeText(const PRUnichar *aText, + const PRInt32 aLen, +@@ -249,9 +252,13 @@ + void IMEGetShellWindow(void); + GtkIMContext* IMEGetContext(void); + void IMECreateContext(GdkWindow* aGdkWindow); +- ++ PRBool IMFilterKeypress (GtkIMContext *context, ++ GdkEventKey *aEvent); ++ + nsWindow* mIMEShellWindow; + static PLDHashTable gXICLookupTable; ++ static GdkEventKey* gIMEKeyEvent; ++ static PRBool gIMEStringCommited; + #endif + + private: >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports-bugs" in the body of the message