53989 XIM: over-the-spot hangs with VJE3.0 and ATOK X

(checked in the patch of katakai@japan.sun.com)
r/sr=blizzard
This commit is contained in:
tajima%eng.sun.com 2001-05-15 03:08:08 +00:00
Родитель 906a287308
Коммит bca2539c53
6 изменённых файлов: 645 добавлений и 598 удалений

Просмотреть файл

@ -31,7 +31,6 @@
#include "nsIPref.h" #include "nsIPref.h"
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include "nsWidget.h"
#include "nsWindow.h" #include "nsWindow.h"
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
@ -817,14 +816,14 @@ nsIMEGtkIC::preedit_start_cbproc(XIC xic, XPointer client_data,
{ {
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data; nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
if (!thisXIC) return 0; if (!thisXIC) return 0;
nsWidget *widget = thisXIC->mFocusWidget; nsWindow *fwin = thisXIC->mFocusWindow;
if (!widget) return 0; if (!fwin) return 0;
if (!thisXIC->mPreedit) { if (!thisXIC->mPreedit) {
thisXIC->mPreedit = new nsIMEPreedit(); thisXIC->mPreedit = new nsIMEPreedit();
} }
thisXIC->mPreedit->Reset(); thisXIC->mPreedit->Reset();
widget->ime_preedit_start(); fwin->ime_preedit_start();
return 0; return 0;
} }
@ -834,8 +833,8 @@ nsIMEGtkIC::preedit_draw_cbproc(XIC xic, XPointer client_data,
{ {
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data; nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
if (!thisXIC) return 0; if (!thisXIC) return 0;
nsWidget *widget = thisXIC->mFocusWidget; nsWindow *fwin = thisXIC->mFocusWindow;
if (!widget) return 0; if (!fwin) return 0;
XIMPreeditDrawCallbackStruct *call_data = XIMPreeditDrawCallbackStruct *call_data =
(XIMPreeditDrawCallbackStruct *) call_data_p; (XIMPreeditDrawCallbackStruct *) call_data_p;
@ -847,7 +846,7 @@ nsIMEGtkIC::preedit_draw_cbproc(XIC xic, XPointer client_data,
thisXIC->mPreedit->SetPreeditString(text, thisXIC->mPreedit->SetPreeditString(text,
call_data->chg_first, call_data->chg_first,
call_data->chg_length); call_data->chg_length);
widget->ime_preedit_draw(); fwin->ime_preedit_draw(thisXIC);
return 0; return 0;
} }
@ -864,10 +863,10 @@ nsIMEGtkIC::preedit_done_cbproc(XIC xic, XPointer client_data,
{ {
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data; nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
if (!thisXIC) return 0; if (!thisXIC) return 0;
nsWidget *widget = thisXIC->mFocusWidget; nsWindow *fwin = thisXIC->mFocusWindow;
if (!widget) return 0; if (!fwin) return 0;
widget->ime_preedit_done(); fwin->ime_preedit_done();
return 0; return 0;
} }
@ -877,8 +876,8 @@ nsIMEGtkIC::status_start_cbproc(XIC xic, XPointer client_data,
{ {
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data; nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
if (!thisXIC) return 0; if (!thisXIC) return 0;
nsWidget *widget = thisXIC->mFocusWidget; nsWindow *fwin = thisXIC->mFocusWindow;
if (!widget) return 0; if (!fwin) return 0;
if (!gStatus) return 0; if (!gStatus) return 0;
// focus_window is changed // focus_window is changed
@ -893,8 +892,8 @@ nsIMEGtkIC::status_draw_cbproc(XIC xic, XPointer client_data,
{ {
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data; nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
if (!thisXIC) return 0; if (!thisXIC) return 0;
nsWidget *widget = thisXIC->mFocusWidget; nsWindow *fwin = thisXIC->mFocusWindow;
if (!widget) return 0; if (!fwin) return 0;
if (!gStatus) return 0; if (!gStatus) return 0;
@ -939,10 +938,10 @@ nsIMEGtkIC::status_done_cbproc(XIC xic, XPointer client_data,
return 0; return 0;
} }
nsWidget * nsWindow *
nsIMEGtkIC::GetFocusWidget() nsIMEGtkIC::GetFocusWindow()
{ {
return mFocusWidget; return mFocusWindow;
} }
// workaround for kinput2/over-the-spot/ic-per-shell // workaround for kinput2/over-the-spot/ic-per-shell
@ -965,10 +964,10 @@ nsIMEGtkIC::GetFocusWidget()
// *OverTheSpotConversion.modeLocation: bottomleft // *OverTheSpotConversion.modeLocation: bottomleft
void void
nsIMEGtkIC::SetFocusWidget(nsWidget * aFocusWidget) nsIMEGtkIC::SetFocusWindow(nsWindow * aFocusWindow)
{ {
mFocusWidget = aFocusWidget; mFocusWindow = aFocusWindow;
GdkWindow *gdkWindow = (GdkWindow*)aFocusWidget->GetNativeData(NS_NATIVE_WINDOW); GdkWindow *gdkWindow = (GdkWindow*)aFocusWindow->GetNativeData(NS_NATIVE_WINDOW);
if (!gdkWindow) return; if (!gdkWindow) return;
gdk_im_begin((GdkIC *) mIC, gdkWindow); gdk_im_begin((GdkIC *) mIC, gdkWindow);
@ -987,20 +986,20 @@ nsIMEGtkIC::SetFocusWidget(nsWidget * aFocusWidget)
} }
void void
nsIMEGtkIC::UnsetFocusWidget() nsIMEGtkIC::UnsetFocusWindow()
{ {
gdk_im_end(); gdk_im_end();
} }
nsIMEGtkIC *nsIMEGtkIC::GetXIC(nsWidget * aFocusWidget, GdkFont *aFontSet) nsIMEGtkIC *nsIMEGtkIC::GetXIC(nsWindow * aFocusWindow, GdkFont *aFontSet)
{ {
return nsIMEGtkIC::GetXIC(aFocusWidget, aFontSet, 0); return nsIMEGtkIC::GetXIC(aFocusWindow, aFontSet, 0);
} }
nsIMEGtkIC *nsIMEGtkIC::GetXIC(nsWidget * aFocusWidget, nsIMEGtkIC *nsIMEGtkIC::GetXIC(nsWindow * aFocusWindow,
GdkFont *aFontSet, GdkFont *aStatusFontSet) GdkFont *aFontSet, GdkFont *aStatusFontSet)
{ {
nsIMEGtkIC *newic = new nsIMEGtkIC(aFocusWidget, aFontSet, aStatusFontSet); nsIMEGtkIC *newic = new nsIMEGtkIC(aFocusWindow, aFontSet, aStatusFontSet);
if (!newic->mIC || !newic->mIC->xic) { if (!newic->mIC || !newic->mIC->xic) {
delete newic; delete newic;
return nsnull; return nsnull;
@ -1032,7 +1031,7 @@ nsIMEGtkIC::~nsIMEGtkIC()
mIC = 0; mIC = 0;
mIC_backup = 0; mIC_backup = 0;
mPreedit = 0; mPreedit = 0;
mFocusWidget = 0; mFocusWindow = 0;
} }
// xim.input_policy: // xim.input_policy:
@ -1393,20 +1392,20 @@ nsIMEGtkIC::SetPreeditArea(int aX, int aY, int aW, int aH) {
} }
} }
nsIMEGtkIC::nsIMEGtkIC(nsWidget *aFocusWidget, GdkFont *aFontSet) nsIMEGtkIC::nsIMEGtkIC(nsWindow *aFocusWindow, GdkFont *aFontSet)
{ {
::nsIMEGtkIC(aFocusWidget, aFontSet, 0); ::nsIMEGtkIC(aFocusWindow, aFontSet, 0);
} }
nsIMEGtkIC::nsIMEGtkIC(nsWidget *aFocusWidget, GdkFont *aFontSet, nsIMEGtkIC::nsIMEGtkIC(nsWindow *aFocusWindow, GdkFont *aFontSet,
GdkFont *aStatusFontSet) GdkFont *aStatusFontSet)
{ {
mFocusWidget = 0; mFocusWindow = 0;
mIC = 0; mIC = 0;
mIC_backup = 0; mIC_backup = 0;
mPreedit = 0; mPreedit = 0;
GdkWindow *gdkWindow = (GdkWindow *) aFocusWidget->GetNativeData(NS_NATIVE_WINDOW); GdkWindow *gdkWindow = (GdkWindow *) aFocusWindow->GetNativeData(NS_NATIVE_WINDOW);
if (!gdkWindow) { if (!gdkWindow) {
return; return;
} }

Просмотреть файл

@ -110,7 +110,7 @@ typedef struct {
XIMProc1 callback; XIMProc1 callback;
} XIMCallback1; } XIMCallback1;
class nsWidget; class nsWindow;
enum nsIMEPolicy { enum nsIMEPolicy {
NSIME_UNKNOWN=0, NSIME_UNKNOWN=0,
@ -130,10 +130,10 @@ class nsIMEGtkIC {
static GdkIMStyle gInputStyle; static GdkIMStyle gInputStyle;
static nsIMEPolicy gInputPolicy; static nsIMEPolicy gInputPolicy;
static nsIMEStatus *gStatus; static nsIMEStatus *gStatus;
nsWidget *mClientWidget; nsWindow *mClientWindow;
nsWidget *mFocusWidget; nsWindow *mFocusWindow;
nsIMEGtkIC(nsWidget*, GdkFont*, GdkFont*); nsIMEGtkIC(nsWindow*, GdkFont*, GdkFont*);
nsIMEGtkIC(nsWidget*, GdkFont*); nsIMEGtkIC(nsWindow*, GdkFont*);
GdkICPrivate *mIC; GdkICPrivate *mIC;
GdkICPrivate *mIC_backup; GdkICPrivate *mIC_backup;
nsIMEPreedit *mPreedit; nsIMEPreedit *mPreedit;
@ -141,11 +141,11 @@ class nsIMEGtkIC {
public: public:
nsIMEPreedit *GetPreedit() {return mPreedit;} nsIMEPreedit *GetPreedit() {return mPreedit;}
~nsIMEGtkIC(); ~nsIMEGtkIC();
static nsIMEGtkIC *GetXIC(nsWidget*, GdkFont*, GdkFont*); static nsIMEGtkIC *GetXIC(nsWindow*, GdkFont*, GdkFont*);
static nsIMEGtkIC *GetXIC(nsWidget*, GdkFont*); static nsIMEGtkIC *GetXIC(nsWindow*, GdkFont*);
void SetFocusWidget(nsWidget * aFocusWidget); void SetFocusWindow(nsWindow * aFocusWindow);
nsWidget* GetFocusWidget(); nsWindow* GetFocusWindow();
static void UnsetFocusWidget(); static void UnsetFocusWindow();
static GdkIMStyle GetInputStyle(); static GdkIMStyle GetInputStyle();
static nsIMEPolicy GetInputPolicy(); static nsIMEPolicy GetInputPolicy();

Просмотреть файл

@ -42,7 +42,6 @@
#include "nsGtkUtils.h" // for nsGtkUtils::gdk_keyboard_get_modifiers() #include "nsGtkUtils.h" // for nsGtkUtils::gdk_keyboard_get_modifiers()
#include "nsIPref.h" #include "nsIPref.h"
#include "nsGtkIMEHelper.h"
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID); static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
@ -67,18 +66,11 @@ private:
*mLast; // valid only for head of list *mLast; // valid only for head of list
}; };
static nsWidget *GetShellWidget(GdkWindow *gdkWindow);
PRUint32 nsWidget::sWidgetCount = 0; PRUint32 nsWidget::sWidgetCount = 0;
// this is the nsWindow with the focus // this is the nsWindow with the focus
nsWidget *nsWidget::sFocusWindow = 0; nsWidget *nsWidget::sFocusWindow = 0;
#ifdef USE_XIM
GdkFont *nsWidget::gPreeditFontset = nsnull;
GdkFont *nsWidget::gStatusFontset = nsnull;
GdkIMStyle nsWidget::gInputStyle = (GdkIMStyle)nsnull;
#endif // USE_XIM
// this is the last time that an event happened. we keep this // this is the last time that an event happened. we keep this
// around so that we can synth drag events properly // around so that we can synth drag events properly
guint32 nsWidget::sLastEventTime = 0; guint32 nsWidget::sLastEventTime = 0;
@ -118,89 +110,6 @@ void nsWidget::GetLastEventTime(guint32 *aTime)
*aTime = sLastEventTime; *aTime = sLastEventTime;
} }
#ifdef USE_XIM
nsresult nsWidget::KillICSpotTimer ()
{
if(mICSpotTimer)
{
mICSpotTimer->Cancel();
mICSpotTimer = nsnull;
}
return NS_OK;
}
nsresult nsWidget::PrimeICSpotTimer ()
{
KillICSpotTimer();
nsresult err;
mICSpotTimer = do_CreateInstance("@mozilla.org/timer;1", &err);
if (NS_FAILED(err))
return err;
mICSpotTimer->Init(ICSpotCallback, this, 1000);
return NS_OK;
}
void nsWidget::ICSpotCallback(nsITimer * aTimer, void * aClosure)
{
nsWidget *widget= NS_REINTERPRET_CAST(nsWidget*, aClosure);
if( ! widget) return;
nsresult res = widget->UpdateICSpot();
if(NS_SUCCEEDED(res))
{
widget->PrimeICSpotTimer();
}
}
nsresult nsWidget::UpdateICSpot()
{
// set spot location
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget*)this;
compEvent.point.x = 0;
compEvent.point.y = 0;
compEvent.time = 0;
compEvent.message = NS_COMPOSITION_QUERY;
compEvent.eventStructType = NS_COMPOSITION_QUERY;
compEvent.compositionMessage = NS_COMPOSITION_QUERY;
static gint oldx =0;
static gint oldy =0;
static gint oldw =0;
static gint oldh =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;
// In over-the-spot style, pre-edit can not be drawn properly when
// IMESetFocusWidget() is called at height=1 and width=1
// After resizing, we need to call SetPreeditArea() again
if((oldw != mBounds.width) || (oldh != mBounds.height)) {
GdkWindow *gdkWindow = (GdkWindow*)this->GetNativeData(NS_NATIVE_WINDOW);
if (mXIC && gdkWindow) {
mXIC->SetPreeditArea(0, 0,
(int)((GdkWindowPrivate*)gdkWindow)->width,
(int)((GdkWindowPrivate*)gdkWindow)->height);
}
oldw = mBounds.width;
oldh = mBounds.height;
}
if((compEvent.theReply.mCursorPosition.x != oldx)||
(compEvent.theReply.mCursorPosition.y != oldy))
{
nsPoint spot;
spot.x = compEvent.theReply.mCursorPosition.x;
spot.y = compEvent.theReply.mCursorPosition.y +
compEvent.theReply.mCursorPosition.height;
SetXICBaseFontSize( compEvent.theReply.mCursorPosition.height - 1);
SetXICSpotLocation(spot);
oldx = compEvent.theReply.mCursorPosition.x;
oldy = compEvent.theReply.mCursorPosition.y;
}
return NS_OK;
}
#endif // USE_XIM
nsCOMPtr<nsIRollupListener> nsWidget::gRollupListener; nsCOMPtr<nsIRollupListener> nsWidget::gRollupListener;
nsWeakPtr nsWidget::gRollupWidget; nsWeakPtr nsWidget::gRollupWidget;
PRBool nsWidget::gRollupConsumeRollupEvent = PR_FALSE; PRBool nsWidget::gRollupConsumeRollupEvent = PR_FALSE;
@ -268,20 +177,6 @@ nsWidget::nsWidget()
sWidgetCount++; sWidgetCount++;
#ifdef USE_XIM
mIMEEnable = PR_TRUE;
mXIC = 0;
mIMEShellWidget = 0;
mIMECallComposeStart = PR_FALSE;
mIMECallComposeEnd = PR_TRUE;
mIMEIsBeingActivate = PR_FALSE;
mICSpotTimer = nsnull;
#endif // USE_XIM
mIMECompositionUniString = nsnull;
mIMECompositionUniStringSize = 0;
mListenForResizes = PR_FALSE; mListenForResizes = PR_FALSE;
mHasFocus = PR_FALSE; mHasFocus = PR_FALSE;
if (mGDKHandlerInstalled == PR_FALSE) { if (mGDKHandlerInstalled == PR_FALSE) {
@ -320,11 +215,6 @@ nsWidget::nsWidget()
nsWidget::~nsWidget() nsWidget::~nsWidget()
{ {
#ifdef USE_XIM
mXIC = 0;
KillICSpotTimer();
#endif // USE_XIM
#ifdef NOISY_DESTROY #ifdef NOISY_DESTROY
IndentByDepth(stdout); IndentByDepth(stdout);
printf("nsWidget::~nsWidget:%p\n", this); printf("nsWidget::~nsWidget:%p\n", this);
@ -336,10 +226,6 @@ nsWidget::~nsWidget()
// to be called once // to be called once
Destroy(); Destroy();
if (mIMECompositionUniString) {
delete[] mIMECompositionUniString;
mIMECompositionUniString = nsnull;
}
NS_ASSERTION(!ModalWidgetList::Find(this), "destroying widget without first clearing modality."); NS_ASSERTION(!ModalWidgetList::Find(this), "destroying widget without first clearing modality.");
#ifdef NS_DEBUG #ifdef NS_DEBUG
if (mIsToplevel) { if (mIsToplevel) {
@ -727,10 +613,6 @@ nsWidget::LoseFocus(void)
if (mHasFocus == PR_FALSE) if (mHasFocus == PR_FALSE)
return; return;
#ifdef USE_XIM
IMEUnsetFocusWidget();
#endif // USE_XIM
sFocusWindow = 0; sFocusWindow = 0;
mHasFocus = PR_FALSE; mHasFocus = PR_FALSE;
@ -2521,137 +2403,11 @@ void nsWidget::SetBackgroundColorNative(GdkColor *aColorNor,
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
#ifdef USE_XIM
void
nsWidget::GetXIC()
{
if (gInputStyle == nsnull) {
gInputStyle = nsIMEGtkIC::GetInputStyle();
}
if (gPreeditFontset == nsnull) {
gPreeditFontset = gdk_fontset_load("-*-*-medium-r-*-*-16-*-*-*-*-*-*-*");
mXICFontSize = 16; // default
}
if (gStatusFontset == nsnull) {
gStatusFontset = gdk_fontset_load("-*-*-medium-r-*-*-16-*-*-*-*-*-*-*");
}
IMEGetShellWidget();
if (!gInputStyle || !gPreeditFontset || !gStatusFontset || !mIMEShellWidget) {
return;
}
if (mIMEShellWidget->mXIC){
mXIC = mIMEShellWidget->mXIC;
} else {
mXIC = nsIMEGtkIC::GetXIC(mIMEShellWidget, gPreeditFontset,
gStatusFontset);
if (mXIC) {
// fix me! need to know how to get spot location
mXIC->SetPreeditSpotLocation(0, 14);
mIMEShellWidget->mXIC = mXIC;
}
}
return;
}
#endif // USE_XIM
NS_IMETHODIMP nsWidget::ResetInputState() NS_IMETHODIMP nsWidget::ResetInputState()
{ {
#ifdef USE_XIM
if (mIMEEnable == PR_FALSE) return NS_OK;
if (mXIC) {
IMEGetShellWidget();
if (!mIMEShellWidget) return NS_OK;
// while being called for NS_ACTIVE and NS_DEACTIVATE,
// ignore ResetInputState() call
if (mIMEShellWidget->mIMEIsBeingActivate == PR_TRUE) {
return NS_OK;
}
PRInt32 uniCharSize =
mXIC->ResetIC(&(mIMECompositionUniString),
&(mIMECompositionUniStringSize));
if (uniCharSize) {
mIMECompositionUniString[uniCharSize] = 0;
IMEComposeStart(nsnull);
IMEComposeText(nsnull,
mIMECompositionUniString,
uniCharSize,
nsnull);
}
// Call IMEComposeEnd() to reset the state of field
IMEComposeEnd(nsnull);
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
UpdateICSpot();
}
}
#endif // USE_XIM
return NS_OK; return NS_OK;
} }
#ifdef USE_XIM
void
nsWidget::GetXYFromPosition(unsigned long *aX,
unsigned long *aY)
{
if (mIMEEnable == PR_FALSE) return;
if (nsnull == mXIC) return;
if (mXIC) {
GdkFont *gfontset = mXIC->GetPreeditFont();
if (gfontset) {
// this is currently not working well
// We change from += ascent to -= descent because we change the nsCaret
// code to return the nsPoint from the top of the cursor to the bottom
// of the cursor
*aY -= gfontset->descent;
}
}
return;
}
void
nsWidget::SetXICBaseFontSize(int height)
{
if (mIMEEnable == PR_FALSE) return;
if (nsnull == mXIC) return;
if (mXIC) {
if (height == mXICFontSize) return;
if (height%2) {
height-=1;
}
if (height<2) return;
if (gPreeditFontset) {
gdk_font_unref(gPreeditFontset);
}
char xlfdbase[128];
sprintf(xlfdbase, "-*-*-medium-r-*-*-%d-*-*-*-*-*-*-*", height);
gPreeditFontset = gdk_fontset_load(xlfdbase);
if (gPreeditFontset) {
mXIC->SetPreeditFont(gPreeditFontset);
}
mXICFontSize = height;
}
}
void
nsWidget::SetXICSpotLocation(nsPoint aPoint)
{
if (mIMEEnable == PR_FALSE) return;
if (nsnull == mXIC) return;
if (mXIC) {
unsigned long x, y;
x = aPoint.x, y = aPoint.y;
GetXYFromPosition(&x, &y);
mXIC->SetPreeditSpotLocation(x, y);
}
return;
}
#endif // USE_XIM
/********************** class ModalWidgetList ***********************/ /********************** class ModalWidgetList ***********************/
/* This silly little thing is a linked list of widgets that have been /* This silly little thing is a linked list of widgets that have been
declared modal, in the order of their declaration. We do this only declared modal, in the order of their declaration. We do this only
@ -2904,267 +2660,10 @@ static gint debugHandleWindowClose(GtkWidget *window, void *data)
#endif /* NS_DEBUG */ #endif /* NS_DEBUG */
#ifdef USE_XIM void nsWidget::IMECommitEvent(GdkEventKey *aEvent) {
void NS_ASSERTION(0, "nsWidget::IMECommitEvent() shouldn't be called!\n");
nsWidget::ime_preedit_start() {
IMEComposeStart(nsnull);
} }
void
nsWidget::ime_preedit_draw() {
IMEComposeStart(nsnull);
nsIMEPreedit *preedit = mXIC->GetPreedit();
IMEComposeText(nsnull,
preedit->GetPreeditString(),
preedit->GetPreeditLength(),
preedit->GetPreeditFeedback());
if (mXIC->IsPreeditComposing() == PR_FALSE) {
IMEComposeEnd(nsnull);
}
}
void
nsWidget::ime_preedit_done() {
IMEComposeEnd(nsnull);
}
void
nsWidget::IMEUnsetFocusWidget()
{
KillICSpotTimer();
}
void
nsWidget::IMESetFocusWidget()
{
if (!mXIC) {
GetXIC();
}
IMEGetShellWidget();
if (!mIMEShellWidget) return;
if (mXIC) {
if (mXIC->IsPreeditComposing() == PR_FALSE) {
IMEComposeEnd(nsnull);
}
mXIC->SetFocusWidget(this);
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
UpdateICSpot();
PrimeICSpotTimer();
}
}
}
void
nsWidget::IMEBeingActivate(PRBool aActive)
{
IMEGetShellWidget();
if (!mIMEShellWidget) return;
mIMEShellWidget->mIMEIsBeingActivate = aActive;
}
#endif // USE_XIM
void
nsWidget::IMEComposeStart(guint aTime)
{
#ifdef USE_XIM
if (mIMECallComposeStart == PR_TRUE) {
return;
}
#endif // USE_XIM
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget *) this;
compEvent.point.x = compEvent.point.y = 0;
compEvent.time = aTime;
compEvent.message = compEvent.eventStructType
= compEvent.compositionMessage = NS_COMPOSITION_START;
OnComposition(compEvent);
#ifdef USE_XIM
mIMECallComposeStart = PR_TRUE;
mIMECallComposeEnd = PR_FALSE;
#endif // USE_XIM
}
void
nsWidget::IMECommitEvent(GdkEventKey *aEvent) {
PRInt32 srcLen = aEvent->length;
if (srcLen && aEvent->string && aEvent->string[0] &&
nsGtkIMEHelper::GetSingleton()) {
PRInt32 uniCharSize;
uniCharSize = nsGtkIMEHelper::GetSingleton()->MultiByteToUnicode(
aEvent->string,
srcLen,
&(mIMECompositionUniString),
&(mIMECompositionUniStringSize));
if (uniCharSize) {
mIMECompositionUniString[uniCharSize] = 0;
if(sFocusWindow == 0 && mXIC != 0) {
// Commit event happens when Mozilla window does not have
// input focus but Lookup window (candidate) window has the focus
// At the case, we have to call IME events with focused widget
nsWidget *widget = mXIC->GetFocusWidget();
if (widget) {
widget->IMEComposeStart(aEvent->time);
widget->IMEComposeText(aEvent,
mIMECompositionUniString,
uniCharSize,
nsnull);
widget->IMEComposeEnd(aEvent->time);
}
} else {
IMEComposeStart(aEvent->time);
IMEComposeText(aEvent,
mIMECompositionUniString,
uniCharSize,
nsnull);
IMEComposeEnd(aEvent->time);
}
}
}
#ifdef USE_XIM
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
// update spot location
IMEGetShellWidget();
if (!mIMEShellWidget) return;
nsIMEGtkIC *XIC_tmp = mXIC ? mXIC : mIMEShellWidget->mXIC;
if (XIC_tmp) {
nsWidget *widget = XIC_tmp->GetFocusWidget();
if (widget) {
widget->UpdateICSpot();
widget->PrimeICSpotTimer();
}
}
}
#endif // USE_XIM
}
void
nsWidget::IMEComposeText(GdkEventKey *aEvent,
const PRUnichar *aText, const PRInt32 aLen,
const char *aFeedback) {
nsTextEvent textEvent;
if (aEvent) {
textEvent.isShift = (aEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isControl = (aEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isAlt = (aEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
textEvent.isMeta = PR_FALSE; //(aEvent->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
textEvent.time = aEvent->time;
} else {
textEvent.time = 0;
textEvent.isShift = textEvent.isControl =
textEvent.isAlt = textEvent.isMeta = PR_FALSE;
}
textEvent.message = textEvent.eventStructType = NS_TEXT_EVENT;
textEvent.widget = (nsWidget *)this;
textEvent.point.x = textEvent.point.y = 0;
if (aLen == 0) {
textEvent.theText = nsnull;
textEvent.rangeCount = 0;
textEvent.rangeArray = nsnull;
} else {
textEvent.theText = (PRUnichar*)aText;
textEvent.rangeCount = 0;
textEvent.rangeArray = nsnull;
#ifdef USE_XIM
if (aFeedback) {
nsIMEPreedit::IMSetTextRange(aLen,
aFeedback,
&(textEvent.rangeCount),
&(textEvent.rangeArray));
}
#endif // USE_XIM
}
OnText(textEvent);
#ifdef USE_XIM
if (textEvent.rangeArray) {
delete[] textEvent.rangeArray;
}
#endif // USE_XIM
}
void
nsWidget::IMEComposeEnd(guint aTime)
{
#ifdef USE_XIM
if (mIMECallComposeEnd == PR_TRUE) {
return;
}
#endif // USE_XIM
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget *) this;
compEvent.point.x = compEvent.point.y = 0;
compEvent.time = aTime;
compEvent.message = compEvent.eventStructType
= compEvent.compositionMessage = NS_COMPOSITION_END;
OnComposition(compEvent);
#ifdef USE_XIM
mIMECallComposeStart = PR_FALSE;
mIMECallComposeEnd = PR_TRUE;
#endif // USE_XIM
}
#ifdef USE_XIM
void
nsWidget::IMEGetShellWidget(void)
{
if (!mIMEShellWidget) {
mIMEShellWidget = GetShellWidget((GdkWindow*)
GetNativeData(NS_NATIVE_WINDOW));
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
}
}
// FIXME: need to find more efficient way for finding the shell widget
static nsWidget *
GetShellWidget(GdkWindow *gdkWindow)
{
GdkWindow *parent = gdk_window_get_parent(gdkWindow);
nsWidget *root_win = nsnull;
gpointer data;
while (parent) {
gdk_window_get_user_data(parent, &data);
if (GTK_IS_OBJECT(data)) {
root_win = (nsWidget *) gtk_object_get_data(GTK_OBJECT(data), "nsWindow");
if(root_win && root_win->mIsToplevel == PR_TRUE){
return root_win;
}
}
parent = gdk_window_get_parent(parent);
}
return nsnull;
}
void
nsWidget::IMEDestroyIC()
{
if (!mXIC) return;
if (mIsToplevel == PR_TRUE) {
delete mXIC;
} else {
// see discussion in bug 53989
nsWidget *widget = mXIC->GetFocusWidget();
if (widget && widget == this && mIMEShellWidget) {
mXIC->SetFocusWidget(mIMEShellWidget);
mXIC->UnsetFocusWidget();
}
}
mXIC = 0;
}
#endif // USE_XIM
void nsWidget::DispatchSetFocusEvent(void) void nsWidget::DispatchSetFocusEvent(void)
{ {
NS_ASSERTION(0, "nsWidget::DispatchSetFocusEvent shouldn't be called!\n"); NS_ASSERTION(0, "nsWidget::DispatchSetFocusEvent shouldn't be called!\n");

Просмотреть файл

@ -36,10 +36,6 @@
class nsILookAndFeel; class nsILookAndFeel;
class nsIAppShell; class nsIAppShell;
class nsIToolkit; class nsIToolkit;
#ifdef USE_XIM
class nsIMEGtkIC;
class nsIMEPreedit;
#endif // USE_XIM
#include <gtk/gtk.h> #include <gtk/gtk.h>
@ -49,6 +45,7 @@ class nsIMEPreedit;
#include "nsITimer.h" #include "nsITimer.h"
#include "nsITimerCallback.h" #include "nsITimerCallback.h"
#define NSRECT_TO_GDKRECT(ns,gdk) \ #define NSRECT_TO_GDKRECT(ns,gdk) \
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
gdk.x = ns.x; \ gdk.x = ns.x; \
@ -309,52 +306,8 @@ protected:
PRBool HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel); PRBool HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel);
PRBool IsMouseInWindow ( GdkWindow* inWindow, PRInt32 inMouseX, PRInt32 inMouseY ) ; PRBool IsMouseInWindow ( GdkWindow* inWindow, PRInt32 inMouseX, PRInt32 inMouseY ) ;
#ifdef USE_XIM
protected:
PRBool mIMEEnable;
void GetXIC();
static GdkFont *gPreeditFontset;
static GdkFont *gStatusFontset;
static GdkIMStyle gInputStyle;
nsIMEGtkIC *mXIC;
PRBool mIMECallComposeStart;
PRBool mIMECallComposeEnd;
PRBool mIMEIsBeingActivate;
nsWidget* mIMEShellWidget;
void SetXICSpotLocation(nsPoint aPoint);
void SetXICBaseFontSize(int height);
void GetXYFromPosition(unsigned long *aX, unsigned long *aY);
nsCOMPtr<nsITimer> mICSpotTimer;
static void ICSpotCallback(nsITimer* aTimer, void* aClosure);
nsresult KillICSpotTimer();
nsresult PrimeICSpotTimer();
nsresult UpdateICSpot();
int mXICFontSize;
public: public:
void ime_preedit_start(); virtual void IMECommitEvent(GdkEventKey *aEvent);
void ime_preedit_draw();
void ime_preedit_done();
void ime_status_draw();
void IMEUnsetFocusWidget();
void IMESetFocusWidget();
void IMEGetShellWidget();
void IMEDestroyIC();
void IMEBeingActivate(PRBool aActive);
#endif // USE_XIM
protected:
void IMEComposeStart(guint aTime);
void IMEComposeText(GdkEventKey*,
const PRUnichar *aText,
const PRInt32 aLen,
const char *aFeedback);
void IMEComposeEnd(guint aTime);
PRUnichar* mIMECompositionUniString;
PRInt32 mIMECompositionUniStringSize;
public:
void IMECommitEvent(GdkEventKey *aEvent);
protected: protected:

Просмотреть файл

@ -59,6 +59,8 @@
#include "nsIDragService.h" #include "nsIDragService.h"
#include "nsIDragSessionGTK.h" #include "nsIDragSessionGTK.h"
#include "nsGtkIMEHelper.h"
#include <unistd.h> #include <unistd.h>
#ifdef NEED_USLEEP_PROTOTYPE #ifdef NEED_USLEEP_PROTOTYPE
@ -118,6 +120,20 @@ nsWindow *nsWindow::mLastLeaveWindow = NULL;
PRBool gJustGotDeactivate = PR_FALSE; PRBool gJustGotDeactivate = PR_FALSE;
PRBool gJustGotActivate = PR_FALSE; PRBool gJustGotActivate = PR_FALSE;
#ifdef USE_XIM
struct nsXICLookupEntry {
PLDHashEntryHdr mKeyHash;
nsWindow* mShellWindow;
nsIMEGtkIC* mXIC;
};
PLDHashTable nsWindow::gXICLookupTable;
GdkFont *nsWindow::gPreeditFontset = nsnull;
GdkFont *nsWindow::gStatusFontset = nsnull;
GdkIMStyle nsWindow::gInputStyle = (GdkIMStyle)nsnull;
#endif // USE_XIM
static void printDepth(int depth) { static void printDepth(int depth) {
int i; int i;
for (i=0; i < depth; i++) for (i=0; i < depth; i++)
@ -166,6 +182,23 @@ nsWindow::nsWindow()
mDragMotionY = 0; mDragMotionY = 0;
mDragMotionTime = 0; mDragMotionTime = 0;
// for commit character
mIMECompositionUniString = nsnull;
mIMECompositionUniStringSize = 0;
#ifdef USE_XIM
mIMEEnable = PR_TRUE; //currently will not be used
mIMEShellWindow = 0;
mIMECallComposeStart = PR_FALSE;
mIMECallComposeEnd = PR_TRUE;
mIMEIsBeingActivate = PR_FALSE;
mICSpotTimer = nsnull;
if (gXICLookupTable.ops == NULL) {
PL_DHashTableInit(&gXICLookupTable, PL_DHashGetStubOps(), nsnull,
sizeof(nsXICLookupEntry), PL_DHASH_MIN_SIZE);
}
#endif // USE_XIM
// check to see if we should set our raise pref // check to see if we should set our raise pref
if (!gRaisePrefInitialized) { if (!gRaisePrefInitialized) {
gRaisePrefInitialized = PR_TRUE; gRaisePrefInitialized = PR_TRUE;
@ -188,6 +221,15 @@ nsWindow::nsWindow()
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
nsWindow::~nsWindow() nsWindow::~nsWindow()
{ {
#ifdef USE_XIM
KillICSpotTimer();
#endif // USE_XIM
if (mIMECompositionUniString) {
delete[] mIMECompositionUniString;
mIMECompositionUniString = nsnull;
}
// make sure to unset any drag motion timers here. // make sure to unset any drag motion timers here.
ResetDragMotionTimer(0, 0, 0, 0, 0); ResetDragMotionTimer(0, 0, 0, 0, 0);
@ -310,14 +352,14 @@ NS_IMETHODIMP nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
void void
nsWindow::DestroyNative(void) nsWindow::DestroyNative(void)
{ {
#ifdef USE_XIM
IMEDestroyIC();
#endif // USE_XIM
// destroy all of the children that are nsWindow() classes // destroy all of the children that are nsWindow() classes
// preempting the gdk destroy system. // preempting the gdk destroy system.
DestroyNativeChildren(); DestroyNativeChildren();
#ifdef USE_XIM
IMEDestroyIC();
#endif // USE_XIM
if (mSuperWin) { if (mSuperWin) {
// remove the key from the hash table for the shell_window // remove the key from the hash table for the shell_window
g_hash_table_remove(mWindowLookupTable, mSuperWin->shell_window); g_hash_table_remove(mWindowLookupTable, mSuperWin->shell_window);
@ -1157,7 +1199,7 @@ nsWindow::SetFocus(PRBool aRaise)
mHasFocus = PR_TRUE; mHasFocus = PR_TRUE;
#ifdef USE_XIM #ifdef USE_XIM
if (sFocusWindow) sFocusWindow->IMESetFocusWidget(); IMESetFocusWindow();
#endif // USE_XIM #endif // USE_XIM
DispatchSetFocusEvent(); DispatchSetFocusEvent();
@ -1172,6 +1214,22 @@ nsWindow::SetFocus(PRBool aRaise)
return NS_OK; return NS_OK;
} }
/* virtual */ void
nsWindow::LoseFocus(void)
{
// doesn't do anything. needed for nsWindow housekeeping, really.
if (mHasFocus == PR_FALSE)
return;
#ifdef USE_XIM
IMEUnsetFocusWindow();
#endif // USE_XIM
sFocusWindow = 0;
mHasFocus = PR_FALSE;
}
void nsWindow::DispatchSetFocusEvent(void) void nsWindow::DispatchSetFocusEvent(void)
{ {
#ifdef DEBUG_FOCUS #ifdef DEBUG_FOCUS
@ -3487,3 +3545,481 @@ PRBool ChildWindow::IsChild() const
return PR_TRUE; return PR_TRUE;
} }
#ifdef USE_XIM
nsresult nsWindow::KillICSpotTimer ()
{
if(mICSpotTimer)
{
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;
mICSpotTimer->Init(ICSpotCallback, this, 1000);
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;
nsIMEGtkIC *xic = window->IMEGetInputContext(PR_FALSE);
if (xic) {
res = window->UpdateICSpot(xic);
}
if(NS_SUCCEEDED(res))
{
window->PrimeICSpotTimer();
}
}
nsresult nsWindow::UpdateICSpot(nsIMEGtkIC *aXIC)
{
// set spot location
nsCompositionEvent compEvent;
compEvent.widget = NS_STATIC_CAST(nsWidget *, this);
compEvent.point.x = 0;
compEvent.point.y = 0;
compEvent.time = 0;
compEvent.message = NS_COMPOSITION_QUERY;
compEvent.eventStructType = NS_COMPOSITION_QUERY;
compEvent.compositionMessage = NS_COMPOSITION_QUERY;
static gint oldx =0;
static gint oldy =0;
static gint oldw =0;
static gint oldh =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;
// In over-the-spot style, pre-edit can not be drawn properly when
// IMESetFocusWindow() is called at height=1 and width=1
// After resizing, we need to call SetPreeditArea() again
if((oldw != mBounds.width) || (oldh != mBounds.height)) {
GdkWindow *gdkWindow = (GdkWindow*)this->GetNativeData(NS_NATIVE_WINDOW);
if (gdkWindow) {
aXIC->SetPreeditArea(0, 0,
(int)((GdkWindowPrivate*)gdkWindow)->width,
(int)((GdkWindowPrivate*)gdkWindow)->height);
}
oldw = mBounds.width;
oldh = mBounds.height;
}
if((compEvent.theReply.mCursorPosition.x != oldx)||
(compEvent.theReply.mCursorPosition.y != oldy))
{
nsPoint spot;
spot.x = compEvent.theReply.mCursorPosition.x;
spot.y = compEvent.theReply.mCursorPosition.y +
compEvent.theReply.mCursorPosition.height;
SetXICBaseFontSize(aXIC, compEvent.theReply.mCursorPosition.height - 1);
SetXICSpotLocation(aXIC, spot);
oldx = compEvent.theReply.mCursorPosition.x;
oldy = compEvent.theReply.mCursorPosition.y;
}
return NS_OK;
}
void
nsWindow::GetXYFromPosition(nsIMEGtkIC* aXIC,
unsigned long *aX,
unsigned long *aY)
{
GdkFont *gfontset = aXIC->GetPreeditFont();
if (gfontset) {
// this is currently not working well
// We change from += ascent to -= descent because we change the nsCaret
// code to return the nsPoint from the top of the cursor to the bottom
// of the cursor
*aY -= gfontset->descent;
}
return;
}
void
nsWindow::SetXICBaseFontSize(nsIMEGtkIC* aXIC, int height)
{
if (height == mXICFontSize) return;
if (height%2) {
height-=1;
}
if (height<2) return;
if (gPreeditFontset) {
gdk_font_unref(gPreeditFontset);
}
char xlfdbase[128];
sprintf(xlfdbase, "-*-*-medium-r-*-*-%d-*-*-*-*-*-*-*", height);
gPreeditFontset = gdk_fontset_load(xlfdbase);
if (gPreeditFontset) {
aXIC->SetPreeditFont(gPreeditFontset);
}
mXICFontSize = height;
}
void
nsWindow::SetXICSpotLocation(nsIMEGtkIC* aXIC, nsPoint aPoint)
{
unsigned long x, y;
x = aPoint.x, y = aPoint.y;
GetXYFromPosition(aXIC, &x, &y);
aXIC->SetPreeditSpotLocation(x, y);
}
void
nsWindow::ime_preedit_start() {
IMEComposeStart(nsnull);
}
void
nsWindow::ime_preedit_draw(nsIMEGtkIC *aXIC) {
IMEComposeStart(nsnull);
nsIMEPreedit *preedit = aXIC->GetPreedit();
IMEComposeText(nsnull,
preedit->GetPreeditString(),
preedit->GetPreeditLength(),
preedit->GetPreeditFeedback());
if (aXIC->IsPreeditComposing() == PR_FALSE) {
IMEComposeEnd(nsnull);
}
}
void
nsWindow::ime_preedit_done() {
IMEComposeEnd(nsnull);
}
void
nsWindow::IMEUnsetFocusWindow()
{
KillICSpotTimer();
}
void
nsWindow::IMESetFocusWindow()
{
// there is only one place to get ShellWindow
IMEGetShellWindow();
nsIMEGtkIC *xic = IMEGetInputContext(PR_TRUE);
if (xic) {
if (xic->IsPreeditComposing() == PR_FALSE) {
IMEComposeEnd(nsnull);
}
xic->SetFocusWindow(this);
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
UpdateICSpot(xic);
PrimeICSpotTimer();
}
}
}
void
nsWindow::IMEBeingActivate(PRBool aActive)
{
// mIMEShellWindow has been retrieved in IMESetFocusWindow()
if (mIMEShellWindow) {
mIMEShellWindow->mIMEIsBeingActivate = aActive;
} else {
NS_ASSERTION(0, "mIMEShellWindow should exist");
}
}
void
nsWindow::IMEGetShellWindow(void)
{
if (!mIMEShellWindow) {
nsWindow *mozAreaWindow = nsnull;
GtkWidget *top_mozarea = GetMozArea();
if (top_mozarea) {
mozAreaWindow = NS_STATIC_CAST(nsWindow *,
gtk_object_get_data(GTK_OBJECT(top_mozarea), "nsWindow"));
}
mIMEShellWindow = mozAreaWindow;
NS_ASSERTION(mIMEShellWindow, "IMEGetShellWindow() fails");
}
}
nsIMEGtkIC*
nsWindow::IMEGetInputContext(PRBool aCreate)
{
PLDHashEntryHdr* hash_entry;
nsXICLookupEntry* entry;
if (!mIMEShellWindow) {
return nsnull;
}
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;
}
}
// create new XIC
if (aCreate) {
if (gInputStyle == nsnull) {
gInputStyle = nsIMEGtkIC::GetInputStyle();
}
if (gPreeditFontset == nsnull) {
gPreeditFontset = gdk_fontset_load("-*-*-medium-r-*-*-16-*-*-*-*-*-*-*");
mXICFontSize = 16; // default
}
if (gStatusFontset == nsnull) {
gStatusFontset = gdk_fontset_load("-*-*-medium-r-*-*-16-*-*-*-*-*-*-*");
}
if (!gInputStyle || !gPreeditFontset || !gStatusFontset) {
return nsnull;
}
nsIMEGtkIC *xic = nsIMEGtkIC::GetXIC(mIMEShellWindow, gPreeditFontset,
gStatusFontset);
if (xic) {
xic->SetPreeditSpotLocation(0, 14);
hash_entry = PL_DHashTableOperate(&gXICLookupTable,
mIMEShellWindow,
PL_DHASH_ADD);
if (hash_entry) {
entry = NS_REINTERPRET_CAST(nsXICLookupEntry *, hash_entry);
entry->mShellWindow = mIMEShellWindow;
entry->mXIC = xic;
}
mIMEShellWindow->mIMEShellWindow = mIMEShellWindow;
return xic;
}
}
return nsnull;
}
void
nsWindow::IMEDestroyIC()
{
// do not call IMEGetShellWindow() here
// user mIMEShellWindow to retrieve XIC
nsIMEGtkIC *xic = IMEGetInputContext(PR_FALSE);
// xic=null means mIMEShellWindow is destroyed before
// or xic is never created for this widget
if (!xic) {
return;
}
if (mIMEShellWindow == this) {
// shell widget is being destroyed
// remove XIC from hashtable by mIMEShellWindow key
PL_DHashTableOperate(&gXICLookupTable, mIMEShellWindow, PL_DHASH_REMOVE);
delete xic;
} else {
// xic and mIMEShellWindow are valid
// see discussion in bug 53989
nsWindow *fwin = xic->GetFocusWindow();
if (fwin && fwin == this) {
xic->SetFocusWindow(mIMEShellWindow);
xic->UnsetFocusWindow();
}
}
}
#endif // USE_XIM
void
nsWindow::IMEComposeStart(guint aTime)
{
#ifdef USE_XIM
if (mIMECallComposeStart == PR_TRUE) {
return;
}
#endif // USE_XIM
nsCompositionEvent compEvent;
compEvent.widget = NS_STATIC_CAST(nsWidget *, this);
compEvent.point.x = compEvent.point.y = 0;
compEvent.time = aTime;
compEvent.message = compEvent.eventStructType
= compEvent.compositionMessage = NS_COMPOSITION_START;
OnComposition(compEvent);
#ifdef USE_XIM
mIMECallComposeStart = PR_TRUE;
mIMECallComposeEnd = PR_FALSE;
#endif // USE_XIM
}
void
nsWindow::IMECommitEvent(GdkEventKey *aEvent) {
PRInt32 srcLen = aEvent->length;
if (srcLen && aEvent->string && aEvent->string[0] &&
nsGtkIMEHelper::GetSingleton()) {
PRInt32 uniCharSize;
uniCharSize = nsGtkIMEHelper::GetSingleton()->MultiByteToUnicode(
aEvent->string,
srcLen,
&(mIMECompositionUniString),
&(mIMECompositionUniStringSize));
if (uniCharSize) {
#ifdef USE_XIM
nsIMEGtkIC *xic = IMEGetInputContext(PR_FALSE);
mIMECompositionUniString[uniCharSize] = 0;
if(sFocusWindow == 0 && xic != 0) {
// Commit event happens when Mozilla window does not have
// input focus but Lookup window (candidate) window has the focus
// At the case, we have to call IME events with focused widget
nsWindow *window = xic->GetFocusWindow();
if (window) {
window->IMEComposeStart(aEvent->time);
window->IMEComposeText(aEvent,
mIMECompositionUniString,
uniCharSize,
nsnull);
window->IMEComposeEnd(aEvent->time);
}
} else
#endif // USE_XIM
{
IMEComposeStart(aEvent->time);
IMEComposeText(aEvent,
mIMECompositionUniString,
uniCharSize,
nsnull);
IMEComposeEnd(aEvent->time);
}
}
}
#ifdef USE_XIM
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
// update spot location
nsIMEGtkIC *xic = IMEGetInputContext(PR_FALSE);
if (xic) {
nsWindow *window = xic->GetFocusWindow();
if (window) {
window->UpdateICSpot(xic);
window->PrimeICSpotTimer();
}
}
}
#endif // USE_XIM
}
void
nsWindow::IMEComposeText(GdkEventKey *aEvent,
const PRUnichar *aText, const PRInt32 aLen,
const char *aFeedback) {
nsTextEvent textEvent;
if (aEvent) {
textEvent.isShift = (aEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isControl = (aEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isAlt = (aEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
textEvent.isMeta = PR_FALSE; //(aEvent->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
textEvent.time = aEvent->time;
} else {
textEvent.time = 0;
textEvent.isShift = textEvent.isControl =
textEvent.isAlt = textEvent.isMeta = PR_FALSE;
}
textEvent.message = textEvent.eventStructType = NS_TEXT_EVENT;
textEvent.widget = NS_STATIC_CAST(nsWidget *, this);
textEvent.point.x = textEvent.point.y = 0;
if (aLen == 0) {
textEvent.theText = nsnull;
textEvent.rangeCount = 0;
textEvent.rangeArray = nsnull;
} else {
textEvent.theText = (PRUnichar*)aText;
textEvent.rangeCount = 0;
textEvent.rangeArray = nsnull;
#ifdef USE_XIM
if (aFeedback) {
nsIMEPreedit::IMSetTextRange(aLen,
aFeedback,
&(textEvent.rangeCount),
&(textEvent.rangeArray));
}
#endif // USE_XIM
}
OnText(textEvent);
#ifdef USE_XIM
if (textEvent.rangeArray) {
delete[] textEvent.rangeArray;
}
#endif // USE_XIM
}
void
nsWindow::IMEComposeEnd(guint aTime)
{
#ifdef USE_XIM
if (mIMECallComposeEnd == PR_TRUE) {
return;
}
#endif // USE_XIM
nsCompositionEvent compEvent;
compEvent.widget = NS_STATIC_CAST(nsWidget*, this);
compEvent.point.x = compEvent.point.y = 0;
compEvent.time = aTime;
compEvent.message = compEvent.eventStructType
= compEvent.compositionMessage = NS_COMPOSITION_END;
OnComposition(compEvent);
#ifdef USE_XIM
mIMECallComposeStart = PR_FALSE;
mIMECallComposeEnd = PR_TRUE;
#endif // USE_XIM
}
NS_IMETHODIMP nsWindow::ResetInputState()
{
#ifdef USE_XIM
nsIMEGtkIC *xic = IMEGetInputContext(PR_FALSE);
if (xic) {
// while being called for NS_ACTIVE and NS_DEACTIVATE,
// ignore ResetInputState() call
if (mIMEShellWindow->mIMEIsBeingActivate == PR_TRUE) {
return NS_OK;
}
PRInt32 uniCharSize =
xic->ResetIC(&(mIMECompositionUniString),
&(mIMECompositionUniStringSize));
if (uniCharSize) {
mIMECompositionUniString[uniCharSize] = 0;
IMEComposeStart(nsnull);
IMEComposeText(nsnull,
mIMECompositionUniString,
uniCharSize,
nsnull);
}
// Call IMEComposeEnd() to reset the state of field
IMEComposeEnd(nsnull);
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
UpdateICSpot(xic);
}
}
#endif // USE_XIM
return NS_OK;
}

Просмотреть файл

@ -33,6 +33,12 @@
#include "gtkmozarea.h" #include "gtkmozarea.h"
#include "gdksuperwin.h" #include "gdksuperwin.h"
#ifdef USE_XIM
#include "pldhash.h"
class nsIMEGtkIC;
class nsIMEPreedit;
#endif // USE_XIM
class nsFont; class nsFont;
class nsIAppShell; class nsIAppShell;
@ -89,6 +95,11 @@ public:
NS_IMETHOD GetAttention(void); NS_IMETHOD GetAttention(void);
NS_IMETHOD Destroy(); NS_IMETHOD Destroy();
virtual void LoseFocus(void);
// nsIKBStateControl
NS_IMETHOD ResetInputState();
void QueueDraw(); void QueueDraw();
void UnqueueDraw(); void UnqueueDraw();
void DoPaint(PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height, void DoPaint(PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height,
@ -309,7 +320,56 @@ protected:
static void dumpWindowChildren(Window aWindow, unsigned int depth); static void dumpWindowChildren(Window aWindow, unsigned int depth);
#endif #endif
#ifdef USE_XIM
protected:
nsIMEGtkIC* IMEGetInputContext(PRBool aCreate);
PRBool mIMEEnable;
static GdkFont *gPreeditFontset;
static GdkFont *gStatusFontset;
static GdkIMStyle gInputStyle;
static PLDHashTable gXICLookupTable;
PRBool mIMECallComposeStart;
PRBool mIMECallComposeEnd;
PRBool mIMEIsBeingActivate;
nsWindow* mIMEShellWindow;
void SetXICSpotLocation(nsIMEGtkIC* aXIC, nsPoint aPoint);
void SetXICBaseFontSize(nsIMEGtkIC* aXIC, int height);
void GetXYFromPosition(nsIMEGtkIC* aXIC, unsigned long *aX, unsigned long *aY);
nsCOMPtr<nsITimer> mICSpotTimer;
static void ICSpotCallback(nsITimer* aTimer, void* aClosure);
nsresult KillICSpotTimer();
nsresult PrimeICSpotTimer();
nsresult UpdateICSpot(nsIMEGtkIC* aXIC);
int mXICFontSize;
public:
void ime_preedit_start();
void ime_preedit_draw(nsIMEGtkIC* aXIC);
void ime_preedit_done();
void ime_status_draw();
void IMEUnsetFocusWindow();
void IMESetFocusWindow();
void IMEGetShellWindow();
void IMEDestroyIC();
void IMEBeingActivate(PRBool aActive);
#endif // USE_XIM
protected:
void IMEComposeStart(guint aTime);
void IMEComposeText(GdkEventKey*,
const PRUnichar *aText,
const PRInt32 aLen,
const char *aFeedback);
void IMEComposeEnd(guint aTime);
public:
virtual void IMECommitEvent(GdkEventKey *aEvent);
private: private:
PRUnichar* mIMECompositionUniString;
PRInt32 mIMECompositionUniStringSize;
nsresult SetMiniIcon(GdkPixmap *window_pixmap, nsresult SetMiniIcon(GdkPixmap *window_pixmap,
GdkBitmap *window_mask); GdkBitmap *window_mask);
nsresult SetIcon(GdkPixmap *window_pixmap, nsresult SetIcon(GdkPixmap *window_pixmap,