Contributors:
Masaki Katakai (katakai@japana.sun.com) Hidetoshi Tajima (tajima@eng.sun.com) Reviewers: Yung-Fong Tang (ftang@netscape.com) Stuart Parmenter (pavlov@netscape.com) Erik van del Poel (erik@netscape.com) Submitter of code changes: Hidetoshi Tajima (tajima@eng.sun.com) Approver: Chris Waterson (waterson@eng.sun.com) Bugs fixed: 17916, 28022, 28875, 20983 git-svn-id: svn://10.0.0.236/trunk@61902 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
fb303577c1
commit
1e0ecbf684
@ -594,97 +594,6 @@ void handle_scrollbar_value_changed(GtkAdjustment *adj, gpointer p)
|
||||
#endif
|
||||
}
|
||||
|
||||
static gint composition_start(GdkEventKey *aEvent, nsWidget *aWin)
|
||||
{
|
||||
nsCompositionEvent compEvent;
|
||||
|
||||
compEvent.widget = (nsWidget*)aWin;
|
||||
compEvent.point.x = 0;
|
||||
compEvent.point.y = 0;
|
||||
compEvent.time = aEvent->time;
|
||||
compEvent.message = NS_COMPOSITION_START;
|
||||
compEvent.eventStructType = NS_COMPOSITION_START;
|
||||
compEvent.compositionMessage = NS_COMPOSITION_START;
|
||||
aWin->OnComposition(compEvent);
|
||||
|
||||
// set SpotLocation
|
||||
nsPoint spot;
|
||||
spot.x = compEvent.theReply.mCursorPosition.x;
|
||||
spot.y = compEvent.theReply.mCursorPosition.y +
|
||||
compEvent.theReply.mCursorPosition.height;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static gint composition_draw(GdkEventKey *aEvent, nsWidget *aWin)
|
||||
{
|
||||
nsresult res= NS_OK;
|
||||
if (!aWin->mIMECompositionUniString) {
|
||||
aWin->mIMECompositionUniStringSize = 128;
|
||||
aWin->mIMECompositionUniString =
|
||||
new PRUnichar[aWin->mIMECompositionUniStringSize];
|
||||
}
|
||||
PRUnichar *uniChar;
|
||||
PRInt32 uniCharSize;
|
||||
PRInt32 srcLen = aEvent->length;
|
||||
for (;;) {
|
||||
uniChar = aWin->mIMECompositionUniString;
|
||||
uniCharSize = aWin->mIMECompositionUniStringSize - 1;
|
||||
res = nsGtkIMEHelper::GetSingleton()->ConvertToUnicode(
|
||||
(char*)aEvent->string, &srcLen, uniChar, &uniCharSize);
|
||||
if(NS_ERROR_ABORT == res)
|
||||
return FALSE;
|
||||
if (srcLen == aEvent->length &&
|
||||
uniCharSize < aWin->mIMECompositionUniStringSize - 1) {
|
||||
break;
|
||||
}
|
||||
aWin->mIMECompositionUniStringSize += 32;
|
||||
if(aWin->mIMECompositionUniString)
|
||||
delete [] aWin->mIMECompositionUniString;
|
||||
aWin->mIMECompositionUniString =
|
||||
new PRUnichar[aWin->mIMECompositionUniStringSize];
|
||||
}
|
||||
aWin->mIMECompositionUniString[uniCharSize] = 0;
|
||||
|
||||
nsTextEvent textEvent;
|
||||
textEvent.message = NS_TEXT_EVENT;
|
||||
textEvent.widget = (nsWidget*)aWin;
|
||||
textEvent.time = aEvent->time;
|
||||
textEvent.point.x = 0;
|
||||
textEvent.point.y = 0;
|
||||
textEvent.theText = aWin->mIMECompositionUniString;
|
||||
textEvent.rangeCount = 0;
|
||||
textEvent.rangeArray = nsnull;
|
||||
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.eventStructType = NS_TEXT_EVENT;
|
||||
aWin->OnText(textEvent);
|
||||
|
||||
nsPoint spot;
|
||||
spot.x = textEvent.theReply.mCursorPosition.x;
|
||||
spot.y = textEvent.theReply.mCursorPosition.y +
|
||||
textEvent.theReply.mCursorPosition.height;
|
||||
return True;
|
||||
}
|
||||
|
||||
static gint composition_end(GdkEventKey *aEvent, nsWidget *aWin)
|
||||
{
|
||||
nsCompositionEvent compEvent;
|
||||
|
||||
compEvent.widget = (nsWidget*)aWin;
|
||||
compEvent.point.x = 0;
|
||||
compEvent.point.y = 0;
|
||||
compEvent.time = aEvent->time;
|
||||
compEvent.message = NS_COMPOSITION_END;
|
||||
compEvent.eventStructType = NS_COMPOSITION_END;
|
||||
compEvent.compositionMessage = NS_COMPOSITION_END;
|
||||
aWin->OnComposition(compEvent);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// GTK's text widget already does XIM, so we don't want to do this again
|
||||
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event,
|
||||
gpointer p)
|
||||
@ -794,9 +703,7 @@ gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p)
|
||||
//
|
||||
if (event->length) {
|
||||
if (nsGtkIMEHelper::GetSingleton() && (!kevent.keyCode)) {
|
||||
composition_start(event, win);
|
||||
composition_draw(event, win);
|
||||
composition_end(event, win);
|
||||
win->IMECommitEvent(event);
|
||||
} else {
|
||||
InitKeyPressEvent(event, win, kevent);
|
||||
win->OnKey(kevent);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -23,24 +23,135 @@
|
||||
#ifndef nsGtkIMEHelper_h__
|
||||
#define nsGtkIMEHelper_h__
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsString.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/*
|
||||
* We are gratduate moving IME related function into this class
|
||||
*/
|
||||
class nsGtkIMEHelper {
|
||||
public:
|
||||
nsGtkIMEHelper();
|
||||
~nsGtkIMEHelper();
|
||||
|
||||
nsresult ConvertToUnicode(const char* aSrc, PRInt32* aSrcLen,
|
||||
PRUnichar* aDes, PRInt32* aDesLen);
|
||||
static nsGtkIMEHelper* GetSingleton();
|
||||
|
||||
PRUnichar* aDes, PRInt32* aDesLen);
|
||||
static nsGtkIMEHelper *GetSingleton();
|
||||
PRInt32 MultiByteToUnicode(const char*, const PRInt32,
|
||||
PRUnichar**, PRInt32*);
|
||||
private:
|
||||
nsGtkIMEHelper();
|
||||
nsIUnicodeDecoder* mDecoder;
|
||||
void SetupUnicodeDecoder();
|
||||
static nsGtkIMEHelper *gSingleton;
|
||||
};
|
||||
|
||||
#ifdef USE_XIM
|
||||
class nsIMEPreedit {
|
||||
private:
|
||||
PRInt32 mCaretPosition;
|
||||
nsString* mIMECompUnicode;
|
||||
nsCString* mIMECompAttr;
|
||||
PRUnichar* mCompositionUniString;
|
||||
PRInt32 mCompositionUniStringSize;
|
||||
public:
|
||||
nsIMEPreedit();
|
||||
~nsIMEPreedit();
|
||||
void Reset();
|
||||
PRUnichar* GetPreeditString() const;
|
||||
char* GetPreeditFeedback() const;
|
||||
int GetPreeditLength() const;
|
||||
void SetPreeditString(const XIMText* aText,
|
||||
const PRInt32 aChangeFirst,
|
||||
const PRInt32 aChangeLength);
|
||||
static void IMSetTextRange(const PRInt32 aLen,
|
||||
const char *aFeedback,
|
||||
PRUint32 *,
|
||||
nsTextRangeArray*);
|
||||
};
|
||||
|
||||
class nsIMEStatus {
|
||||
private:
|
||||
Window mIMStatusWindow;
|
||||
Window mIMStatusLabel;
|
||||
XFontSet mFontset;
|
||||
GdkWindow *mParent;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
GC mGC;
|
||||
char *mText;
|
||||
void move();
|
||||
void resize(const char *);
|
||||
void remove_decoration();
|
||||
void getAtoms();
|
||||
static Bool repaint_filter(Display *d, Window w, XEvent *ev,
|
||||
XPointer client_data);
|
||||
static Bool clientmessage_filter(Display *d, Window w, XEvent *ev,
|
||||
XPointer client_data);
|
||||
void CreateNative();
|
||||
void DestroyNative();
|
||||
public:
|
||||
nsIMEStatus();
|
||||
nsIMEStatus(GdkFont*);
|
||||
void SetFont(GdkFont*);
|
||||
~nsIMEStatus();
|
||||
void setText(const char*);
|
||||
void setParentWindow(GdkWindow*);
|
||||
void show();
|
||||
void hide();
|
||||
};
|
||||
|
||||
/* for XIM callback */
|
||||
typedef int (*XIMProc1)(XIC, XPointer, XPointer);
|
||||
typedef struct {
|
||||
XPointer client_data;
|
||||
XIMProc1 callback;
|
||||
} XIMCallback1;
|
||||
|
||||
class nsWidget;
|
||||
|
||||
enum nsIMEPolicy {
|
||||
NSIME_UNKNOWN=0,
|
||||
NSIME_IC_PER_SHELL=1,
|
||||
NSIME_IC_PER_WIDGET=2
|
||||
};
|
||||
|
||||
class nsIMEGtkIC {
|
||||
private:
|
||||
static int preedit_start_cbproc(XIC, XPointer, XPointer);
|
||||
static int preedit_draw_cbproc(XIC, XPointer, XPointer);
|
||||
static int preedit_caret_cbproc(XIC, XPointer, XPointer);
|
||||
static int preedit_done_cbproc(XIC, XPointer, XPointer);
|
||||
static int status_start_cbproc(XIC, XPointer, XPointer);
|
||||
static int status_draw_cbproc(XIC, XPointer, XPointer);
|
||||
static int status_done_cbproc(XIC, XPointer, XPointer);
|
||||
static GdkIMStyle gInputStyle;
|
||||
static nsIMEPolicy gInputPolicy;
|
||||
static nsIMEStatus *gStatus;
|
||||
nsWidget *mClientWidget;
|
||||
nsWidget *mFocusWidget;
|
||||
nsIMEGtkIC(nsWidget*, GdkFont*, GdkFont*);
|
||||
nsIMEGtkIC(nsWidget*, GdkFont*);
|
||||
GdkICPrivate *mIC;
|
||||
GdkICPrivate *mIC_backup;
|
||||
nsIMEPreedit *mPreedit;
|
||||
GdkFont *mStatusFontset;
|
||||
public:
|
||||
nsIMEPreedit *GetPreedit() {return mPreedit;}
|
||||
~nsIMEGtkIC();
|
||||
static nsIMEGtkIC *GetXIC(nsWidget*, GdkFont*, GdkFont*);
|
||||
static nsIMEGtkIC *GetXIC(nsWidget*, GdkFont*);
|
||||
void SetFocusWidget(nsWidget * aFocusWidget);
|
||||
nsWidget* GetFocusWidget();
|
||||
static void UnsetFocusWidget();
|
||||
static GdkIMStyle GetInputStyle();
|
||||
static nsIMEPolicy GetInputPolicy();
|
||||
|
||||
GdkFont *GetPreeditFont();
|
||||
void SetPreeditFont(GdkFont*);
|
||||
void SetStatusFont(GdkFont*);
|
||||
void SetPreeditSpotLocation(unsigned long, unsigned long);
|
||||
void SetPreeditArea(int, int, int, int);
|
||||
PRBool IsPreeditComposing();
|
||||
PRInt32 ResetIC(PRUnichar **aUnichar, PRInt32 *aUnisize);
|
||||
};
|
||||
#endif // USE_XIM
|
||||
#endif // nsGtkIMEHelper_h__
|
||||
|
||||
@ -44,8 +44,6 @@
|
||||
#include "prefapi.h"
|
||||
#include "nsGtkIMEHelper.h"
|
||||
|
||||
|
||||
|
||||
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
||||
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
@ -70,12 +68,19 @@ private:
|
||||
*mLast; // valid only for head of list
|
||||
};
|
||||
|
||||
static nsWidget *GetShellWidget(GdkWindow *gdkWindow);
|
||||
|
||||
nsILookAndFeel *nsWidget::sLookAndFeel = nsnull;
|
||||
PRUint32 nsWidget::sWidgetCount = 0;
|
||||
|
||||
// this is the nsWindow with the focus
|
||||
nsWidget *nsWidget::focusWindow = NULL;
|
||||
|
||||
#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
|
||||
// around so that we can synth drag events properly
|
||||
guint32 nsWidget::sLastEventTime = 0;
|
||||
@ -104,7 +109,6 @@ PRBool nsWidget::OnInput(nsInputEvent &aEvent)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void nsWidget::SetLastEventTime(guint32 aTime)
|
||||
{
|
||||
sLastEventTime = aTime;
|
||||
@ -116,6 +120,7 @@ void nsWidget::GetLastEventTime(guint32 *aTime)
|
||||
*aTime = sLastEventTime;
|
||||
}
|
||||
|
||||
#ifdef USE_XIM
|
||||
nsresult nsWidget::KillICSpotTimer ()
|
||||
{
|
||||
if(mICSpotTimer)
|
||||
@ -179,6 +184,7 @@ nsresult nsWidget::UpdateICSpot()
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif // USE_XIM
|
||||
|
||||
nsCOMPtr<nsIRollupListener> nsWidget::gRollupListener;
|
||||
nsCOMPtr<nsIWidget> nsWidget::gRollupWidget;
|
||||
@ -265,13 +271,22 @@ nsWidget::nsWidget()
|
||||
|
||||
sWidgetCount++;
|
||||
|
||||
#ifdef USE_XIM
|
||||
mIMEEnable = PR_TRUE;
|
||||
mIC = nsnull;
|
||||
mIMECompositionUniString = nsnull;
|
||||
mIMECompositionUniStringSize = 0;
|
||||
mListenForResizes = PR_FALSE;
|
||||
mIMEIsDeactivating = PR_FALSE;
|
||||
mICPerShell = PR_TRUE; // default
|
||||
mXIC = 0;
|
||||
|
||||
mIMEShellWidget = 0;
|
||||
mIMECallComposeStart = PR_FALSE;
|
||||
mIMECallComposeEnd = PR_TRUE;
|
||||
|
||||
mICSpotTimer = nsnull;
|
||||
#endif // USE_XIM
|
||||
mIMECompositionUniString = nsnull;
|
||||
mIMECompositionUniStringSize = 0;
|
||||
|
||||
mListenForResizes = PR_FALSE;
|
||||
mHasFocus = PR_FALSE;
|
||||
if (mGDKHandlerInstalled == PR_FALSE) {
|
||||
mGDKHandlerInstalled = PR_TRUE;
|
||||
@ -312,7 +327,11 @@ nsWidget::nsWidget()
|
||||
|
||||
nsWidget::~nsWidget()
|
||||
{
|
||||
#ifdef USE_XIM
|
||||
mXIC = 0;
|
||||
KillICSpotTimer();
|
||||
#endif // USE_XIM
|
||||
|
||||
#ifdef NOISY_DESTROY
|
||||
IndentByDepth(stdout);
|
||||
printf("nsWidget::~nsWidget:%p\n", this);
|
||||
@ -2153,43 +2172,6 @@ nsWidget::OnFocusInSignal(GdkEventFocus * aGdkFocusEvent)
|
||||
DispatchFocus(event);
|
||||
|
||||
Release();
|
||||
|
||||
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf(" IME is not usable on this window\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mIC)
|
||||
GetXIC();
|
||||
|
||||
if (mIC)
|
||||
{
|
||||
GdkWindow *gdkWindow = (GdkWindow*) GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (gdkWindow)
|
||||
{
|
||||
gdk_im_begin ((GdkIC*)mIC, gdkWindow);
|
||||
UpdateICSpot();
|
||||
PrimeICSpotTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdkWindow is not usable\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("mIC can't created yet\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* virtual */ void
|
||||
@ -2218,40 +2200,6 @@ nsWidget::OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent)
|
||||
DispatchFocus(event);
|
||||
|
||||
Release();
|
||||
|
||||
|
||||
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf(" IME is not usable on this window\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (mIC)
|
||||
{
|
||||
KillICSpotTimer();
|
||||
|
||||
GdkWindow *gdkWindow = (GdkWindow*) GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (gdkWindow)
|
||||
{
|
||||
gdk_im_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdkWindow is not usable\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("mIC isn't created yet\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* virtual */ void
|
||||
@ -2739,300 +2687,143 @@ void nsWidget::SetBackgroundColorNative(GdkColor *aColorNor,
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP nsWidget::ResetInputState()
|
||||
#ifdef USE_XIM
|
||||
void
|
||||
nsWidget::GetXIC()
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
if(nsnull != mIC)
|
||||
{
|
||||
char* uncommitted_text=nsnull;
|
||||
// force IME to commit
|
||||
uncommitted_text = XmbResetIC(mIC->xic);
|
||||
if (gInputStyle == nsnull) {
|
||||
gInputStyle = nsIMEGtkIC::GetInputStyle();
|
||||
}
|
||||
if (nsIMEGtkIC::GetInputPolicy() == NSIME_IC_PER_WIDGET) {
|
||||
mICPerShell = PR_FALSE;
|
||||
}
|
||||
if (gPreeditFontset == nsnull) {
|
||||
gPreeditFontset = gdk_fontset_load("-*-*-*-*-*-*-16-*-*-*-*-*-*-*");
|
||||
mXICFontSize = 16; // default
|
||||
}
|
||||
if (gStatusFontset == nsnull) {
|
||||
gStatusFontset = gdk_fontset_load("-*-*-*-*-*-*-16-*-*-*-*-*-*-*");
|
||||
}
|
||||
if (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
}
|
||||
if (!gInputStyle || !gPreeditFontset || !gStatusFontset || !mIMEShellWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we got any text back, we need to send
|
||||
// the IME events
|
||||
if(uncommitted_text && uncommitted_text[0])
|
||||
{
|
||||
PRInt32 uncommitted_len = nsCRT::strlen(uncommitted_text);
|
||||
|
||||
if(nsGtkIMEHelper::GetSingleton())
|
||||
{
|
||||
// prepare Unicode buffer for conversion
|
||||
if (!mIMECompositionUniString)
|
||||
{
|
||||
mIMECompositionUniStringSize = 128;
|
||||
mIMECompositionUniString =
|
||||
new PRUnichar[mIMECompositionUniStringSize];
|
||||
} // if (!mIMECompositionUniString)
|
||||
PRInt32 uniCharSize;
|
||||
PRInt32 srcLen;
|
||||
// Convert in a for loop untill we got all the Unicode
|
||||
for(;;)
|
||||
{
|
||||
PRUnichar* uniChar=mIMECompositionUniString;
|
||||
srcLen= uncommitted_len;
|
||||
uniCharSize= mIMECompositionUniStringSize - 1;
|
||||
res = nsGtkIMEHelper::GetSingleton()->ConvertToUnicode(
|
||||
(char*)uncommitted_text, &srcLen,
|
||||
uniChar,
|
||||
&uniCharSize);
|
||||
if(NS_ERROR_ABORT == res)
|
||||
break;
|
||||
|
||||
// if we convert all text, break
|
||||
if((srcLen == uncommitted_len) &&
|
||||
(uniCharSize < mIMECompositionUniStringSize -1))
|
||||
break;
|
||||
|
||||
// otherwise, re allocate the buffer
|
||||
mIMECompositionUniStringSize += 32;
|
||||
if( mIMECompositionUniString )
|
||||
delete [] mIMECompositionUniString;
|
||||
mIMECompositionUniString =
|
||||
new PRUnichar[mIMECompositionUniStringSize];
|
||||
} // for(;;)
|
||||
if(NS_SUCCEEDED(res))
|
||||
{
|
||||
|
||||
// null terminate the Unicode string
|
||||
mIMECompositionUniString[uniCharSize] = 0;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// send START_COMPOSITION
|
||||
//-------------------------------------------------------
|
||||
nsCompositionEvent compEvent;
|
||||
compEvent.widget= (nsWidget*) this;
|
||||
compEvent.point.x = compEvent.point.y = 0;
|
||||
compEvent.time = 0;
|
||||
compEvent.message = compEvent.eventStructType
|
||||
= compEvent.compositionMessage = NS_COMPOSITION_START;
|
||||
|
||||
this->OnComposition(compEvent);
|
||||
//-------------------------------------------------------
|
||||
// send Text Event
|
||||
//-------------------------------------------------------
|
||||
nsTextEvent textEvent;
|
||||
textEvent.message =textEvent.eventStructType =NS_TEXT_EVENT;
|
||||
textEvent.widget= (nsWidget*) this;
|
||||
textEvent.point.x = textEvent.point.y = 0;
|
||||
textEvent.time = 0;
|
||||
textEvent.theText = mIMECompositionUniString;
|
||||
textEvent.rangeCount = 0;
|
||||
textEvent.rangeArray = nsnull;
|
||||
textEvent.isShift = textEvent.isControl =
|
||||
textEvent.isAlt = textEvent.isMeta = PR_FALSE;
|
||||
this->OnText(textEvent);
|
||||
|
||||
//-------------------------------------------------------
|
||||
// send END_COMPOSITION
|
||||
//-------------------------------------------------------
|
||||
compEvent.widget= (nsWidget*) this;
|
||||
compEvent.message = compEvent.eventStructType
|
||||
= compEvent.compositionMessage = NS_COMPOSITION_END;
|
||||
this->OnComposition(compEvent);
|
||||
}
|
||||
if (mICPerShell) {
|
||||
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;
|
||||
}
|
||||
XFree(uncommitted_text);
|
||||
}
|
||||
} else {
|
||||
mXIC = nsIMEGtkIC::GetXIC(this, gPreeditFontset, gStatusFontset);
|
||||
if (mXIC) {
|
||||
// fix me! need to know how to get spot location
|
||||
mXIC->SetPreeditSpotLocation(0, mXICFontSize);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
#endif // USE_XIM
|
||||
|
||||
NS_IMETHODIMP nsWidget::ResetInputState()
|
||||
{
|
||||
#ifdef USE_XIM
|
||||
if (mIMEEnable == PR_FALSE) return NS_OK;
|
||||
if (mXIC) {
|
||||
if (mIMEShellWidget->mIMEIsDeactivating == PR_TRUE) {
|
||||
return NS_OK;
|
||||
}
|
||||
PRInt32 uniCharSize =
|
||||
mXIC->ResetIC(&(mIMECompositionUniString),
|
||||
&(mIMECompositionUniStringSize));
|
||||
if (uniCharSize) {
|
||||
mIMECompositionUniString[uniCharSize] = 0;
|
||||
|
||||
nsWidget *saved_focusWindow = 0;
|
||||
if (focusWindow) {
|
||||
saved_focusWindow = focusWindow;
|
||||
focusWindow = 0;
|
||||
}
|
||||
|
||||
IMEComposeStart(nsnull);
|
||||
|
||||
//-------------------------------------------------------
|
||||
// send Text Event
|
||||
//-------------------------------------------------------
|
||||
IMEComposeText(nsnull,
|
||||
mIMECompositionUniString,
|
||||
uniCharSize,
|
||||
nsnull);
|
||||
IMEComposeEnd(nsnull);
|
||||
|
||||
if (saved_focusWindow) {
|
||||
focusWindow = saved_focusWindow;
|
||||
}
|
||||
|
||||
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
|
||||
UpdateICSpot();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GetXIC();
|
||||
}
|
||||
#endif // USE_XIM
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsWidget::PasswordFieldInit()
|
||||
{
|
||||
// to be implemented
|
||||
#ifdef USE_XIM
|
||||
mIMEEnable = PR_FALSE;
|
||||
#endif // USE_XIM
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#define PREF_XIM_PREEDIT "xim.preedit"
|
||||
#define PREF_XIM_STATUS "xim.status"
|
||||
#define SUPPORTED_PREEDIT (GDK_IM_PREEDIT_AREA | \
|
||||
GDK_IM_PREEDIT_POSITION | \
|
||||
GDK_IM_PREEDIT_NOTHING | \
|
||||
GDK_IM_PREEDIT_NONE)
|
||||
// GDK_IM_PREEDIT_CALLBACKS
|
||||
|
||||
#define SUPPORTED_STATUS (GDK_IM_STATUS_NOTHING | \
|
||||
GDK_IM_STATUS_NONE)
|
||||
// GDK_IM_STATUS_AREA
|
||||
// GDK_IM_STATUS_CALLBACKS
|
||||
|
||||
void
|
||||
nsWidget::SetXIC(GdkICPrivate *aIC)
|
||||
{
|
||||
if(mIMEEnable == PR_FALSE) {
|
||||
return;
|
||||
}
|
||||
mIC = aIC;
|
||||
return;
|
||||
}
|
||||
|
||||
GdkICPrivate*
|
||||
nsWidget::GetXIC()
|
||||
{
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
return nsnull;
|
||||
|
||||
if (mIC) return mIC; // mIC is already set
|
||||
|
||||
// IC-per-shell, we share a single IC among all widgets of
|
||||
// a single toplevel widget
|
||||
nsCOMPtr<nsIWidget> widget = this;
|
||||
nsCOMPtr<nsIWidget> root = this;
|
||||
while (widget) {
|
||||
root = widget;
|
||||
widget = getter_AddRefs(widget->GetParent());
|
||||
}
|
||||
nsWidget *root_win = (nsWidget*)root.get(); // this is a toplevel window
|
||||
if (!root_win->mIC) {
|
||||
// create an XIC as this is a new toplevel window
|
||||
|
||||
// open an XIM
|
||||
if (!gdk_xim_ic) {
|
||||
#ifdef NOISY_XIM
|
||||
printf("Try gdk_im_open()\n");
|
||||
#endif
|
||||
if (gdk_im_open() == FALSE){
|
||||
#ifdef NOISY_XIM
|
||||
printf("Can't Open IM\n");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdk_xim_ic is already created\n");
|
||||
#endif
|
||||
}
|
||||
if (gdk_im_ready()) {
|
||||
int height, width;
|
||||
// fontset is hardcoded, but need to get a fontset at the
|
||||
// text insertion point
|
||||
GdkFont *gfontset =
|
||||
gdk_fontset_load("-*-*-*-*-*-*-16-*-*-*-*-*-*-*");
|
||||
// I change it from the font setting from the setting below.
|
||||
// reason is when I use hanIM the font creation failed in ko locale
|
||||
// so far it does not have problem w/ xcin since xcin only support
|
||||
// root window.
|
||||
mXICFontSize = 16;
|
||||
|
||||
//gdk_fontset_load("-misc-fixed-medium-r-normal--*-130-*-*-*-*-*-0");
|
||||
|
||||
GdkWindow *gdkWindow = (GdkWindow*) GetNativeData(NS_NATIVE_WINDOW);
|
||||
|
||||
if (!gdkWindow) return nsnull;
|
||||
|
||||
GdkWindowPrivate *gdkWindow_private = (GdkWindowPrivate*) gdkWindow;
|
||||
GdkICAttr *attr = gdk_ic_attr_new();
|
||||
GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
|
||||
GdkIMStyle style;
|
||||
|
||||
PRInt32 ivalue = 0;
|
||||
nsresult rv;
|
||||
|
||||
GdkIMStyle supported_style = (GdkIMStyle) (SUPPORTED_PREEDIT | SUPPORTED_STATUS);
|
||||
style = gdk_im_decide_style(supported_style);
|
||||
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
||||
if (!NS_FAILED(rv) && (prefs)) {
|
||||
rv = prefs->GetIntPref(PREF_XIM_PREEDIT, &ivalue);
|
||||
if (SUPPORTED_PREEDIT & ivalue) {
|
||||
style = (GdkIMStyle) ((style & GDK_IM_STATUS_MASK) | ivalue);
|
||||
}
|
||||
rv = prefs->GetIntPref(PREF_XIM_STATUS, &ivalue);
|
||||
if (SUPPORTED_STATUS & ivalue) {
|
||||
style = (GdkIMStyle) ((style & GDK_IM_PREEDIT_MASK) | ivalue);
|
||||
}
|
||||
}
|
||||
|
||||
attr->style = style;
|
||||
attr->client_window = gdkWindow;
|
||||
|
||||
attrmask = (GdkICAttributesType) (attrmask | GDK_IC_PREEDIT_COLORMAP);
|
||||
attr->preedit_colormap = gdkWindow_private->colormap;
|
||||
|
||||
switch (style & GDK_IM_PREEDIT_MASK)
|
||||
{
|
||||
case GDK_IM_PREEDIT_POSITION:
|
||||
default:
|
||||
attrmask = (GdkICAttributesType) (attrmask | GDK_IC_PREEDIT_POSITION_REQ);
|
||||
gdk_window_get_size (gdkWindow, &width, &height);
|
||||
|
||||
/* need to know how to get spot location */
|
||||
attr->spot_location.x = 0;
|
||||
attr->spot_location.y = 14;
|
||||
|
||||
attr->preedit_area.x = 0;
|
||||
attr->preedit_area.y = 0;
|
||||
attr->preedit_area.width = width;
|
||||
attr->preedit_area.height = height;
|
||||
attrmask = (GdkICAttributesType) (attrmask | GDK_IC_PREEDIT_AREA);
|
||||
|
||||
attr->preedit_fontset = gfontset;
|
||||
attrmask = (GdkICAttributesType) (attrmask | GDK_IC_PREEDIT_FONTSET);
|
||||
break;
|
||||
}
|
||||
GdkICPrivate *IC = (GdkICPrivate*) gdk_ic_new (attr, attrmask);
|
||||
gdk_ic_attr_destroy(attr);
|
||||
root_win->SetXIC(IC); // set to toplevel
|
||||
SetXIC(IC); // set to myself
|
||||
return IC;
|
||||
}
|
||||
} else {
|
||||
mIC = root_win->mIC;
|
||||
return mIC;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
#ifdef USE_XIM
|
||||
void
|
||||
nsWidget::GetXYFromPosition(unsigned long *aX,
|
||||
unsigned long *aY)
|
||||
{
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
return;
|
||||
|
||||
if (!mIC)
|
||||
return;
|
||||
|
||||
GdkICAttr *attr = gdk_ic_attr_new();
|
||||
GdkICAttributesType attrMask = GDK_IC_PREEDIT_FONTSET;
|
||||
mIC->mask = GDK_IC_PREEDIT_FONTSET; // hack
|
||||
gdk_ic_get_attr((GdkIC*)mIC, attr, attrMask);
|
||||
if (attr->preedit_fontset) {
|
||||
// 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 -= attr->preedit_fontset->descent;
|
||||
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;
|
||||
}
|
||||
}
|
||||
gdk_ic_attr_destroy(attr);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsWidget::SetXICBaseFontSize(int height)
|
||||
{
|
||||
if (height == mXICFontSize)
|
||||
return;
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!mIC) GetXIC();
|
||||
if (mIC)
|
||||
{
|
||||
if (mIMEEnable == PR_FALSE) return;
|
||||
if (nsnull == mXIC) return;
|
||||
if (mXIC) {
|
||||
if (height == mXICFontSize) return;
|
||||
if (gPreeditFontset) {
|
||||
gdk_font_unref(gPreeditFontset);
|
||||
}
|
||||
char xlfdbase[128];
|
||||
sprintf(xlfdbase, "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*", height);
|
||||
GdkFont *gfontset = gdk_fontset_load(xlfdbase);
|
||||
|
||||
if(gfontset) {
|
||||
GdkICAttr *attr = gdk_ic_attr_new();
|
||||
if(attr) {
|
||||
attr->preedit_fontset = gfontset;
|
||||
GdkICAttributesType attrMask = GDK_IC_PREEDIT_FONTSET;
|
||||
gdk_ic_set_attr((GdkIC*)mIC, attr, attrMask);
|
||||
gdk_ic_attr_destroy(attr);
|
||||
}
|
||||
gPreeditFontset = gdk_fontset_load(xlfdbase);
|
||||
if (gPreeditFontset) {
|
||||
mXIC->SetPreeditFont(gPreeditFontset);
|
||||
}
|
||||
mXICFontSize = height;
|
||||
}
|
||||
@ -3040,29 +2831,17 @@ nsWidget::SetXICBaseFontSize(int height)
|
||||
void
|
||||
nsWidget::SetXICSpotLocation(nsPoint aPoint)
|
||||
{
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// NS_ASSERTION( (aPoint.y >0), "strange position for XIC");
|
||||
if(aPoint.y <= 0)
|
||||
return;
|
||||
|
||||
if (!mIC) GetXIC();
|
||||
if (mIC)
|
||||
{
|
||||
GdkICAttr *attr = gdk_ic_attr_new();
|
||||
GdkICAttributesType attrMask = GDK_IC_SPOT_LOCATION;
|
||||
if (mIMEEnable == PR_FALSE) return;
|
||||
if (nsnull == mXIC) return;
|
||||
if (mXIC) {
|
||||
unsigned long x, y;
|
||||
x = aPoint.x, y = aPoint.y;
|
||||
GetXYFromPosition(&x, &y);
|
||||
attr->spot_location.x = x;
|
||||
attr->spot_location.y = y;
|
||||
gdk_ic_set_attr((GdkIC*)mIC, attr, attrMask);
|
||||
gdk_ic_attr_destroy(attr);
|
||||
mXIC->SetPreeditSpotLocation(x, y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif // USE_XIM
|
||||
|
||||
/********************** class ModalWidgetList ***********************/
|
||||
/* This silly little thing is a linked list of widgets that have been
|
||||
@ -3357,3 +3136,332 @@ static gint debugHandleWindowClose(GtkWidget *window, void *data)
|
||||
}
|
||||
|
||||
#endif /* NS_DEBUG */
|
||||
|
||||
#ifdef USE_XIM
|
||||
void
|
||||
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 (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
if (!mIMEShellWidget) return;
|
||||
}
|
||||
if (mIMEShellWidget == this) {
|
||||
return;
|
||||
}
|
||||
if (mXIC) {
|
||||
if (mXIC->IsPreeditComposing() == PR_FALSE) {
|
||||
IMEComposeEnd(nsnull);
|
||||
}
|
||||
mXIC->SetFocusWidget(this);
|
||||
if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
|
||||
UpdateICSpot();
|
||||
PrimeICSpotTimer();
|
||||
}
|
||||
} else {
|
||||
// FIXME: we shouldn't call UnsetFocusWidget() when focus
|
||||
// is moved to toolbar or SetFocusWidget() again to
|
||||
// input Widget (bug 17419)
|
||||
|
||||
// kinput2 does not work well if we call UnsetFocusWidget()
|
||||
// when mIMEIsDeactivating is true
|
||||
if (mIMEShellWidget->mIMEIsDeactivating == PR_FALSE) {
|
||||
nsIMEGtkIC::UnsetFocusWidget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsWidget::IMEActivateWidget()
|
||||
{
|
||||
if (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
if (!mIMEShellWidget) return;
|
||||
}
|
||||
mIMEShellWidget->mIMEIsDeactivating = PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsWidget::IMEDeactivateWidget()
|
||||
{
|
||||
if (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
if (!mIMEShellWidget) return;
|
||||
}
|
||||
mIMEShellWidget->mIMEIsDeactivating = PR_TRUE;
|
||||
}
|
||||
#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) {
|
||||
#ifdef USE_XIM
|
||||
if (gInputStyle & GDK_IM_PREEDIT_CALLBACKS) {
|
||||
IMECheckPreedit_PreProc();
|
||||
}
|
||||
#endif // USE_XIM
|
||||
|
||||
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;
|
||||
IMEComposeStart(aEvent->time);
|
||||
IMEComposeText(aEvent,
|
||||
mIMECompositionUniString,
|
||||
uniCharSize,
|
||||
nsnull);
|
||||
IMEComposeEnd(aEvent->time);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_XIM
|
||||
if (gInputStyle & GDK_IM_PREEDIT_CALLBACKS) {
|
||||
IMECheckPreedit_PostProc();
|
||||
} else if (gInputStyle & GDK_IM_PREEDIT_POSITION) {
|
||||
// update spot location
|
||||
if (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
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
|
||||
// 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 (mICPerShell == PR_FALSE || mIsToplevel == PR_TRUE) {
|
||||
delete mXIC;
|
||||
}
|
||||
mXIC = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
workaround for linux/kinput2
|
||||
|
||||
The order of events is not good when linux/kinput2 is used.
|
||||
|
||||
1. Commit text
|
||||
2. Preedit Draw Callback
|
||||
|
||||
is expected, however, the order is,
|
||||
|
||||
1. Preedit Draw Callback
|
||||
2. Commit text
|
||||
|
||||
so workaround is,
|
||||
|
||||
1) when composed text exits, clear the text
|
||||
2) Commit text (in nsGtkEventHandler)
|
||||
3) when composed text exits, redraw the existing preedit
|
||||
*/
|
||||
|
||||
void nsWidget::IMECheckPreedit_PreProc()
|
||||
{
|
||||
// There is a case that IMECommitEvent is called from non-inputfield
|
||||
// (bug 17419)
|
||||
// mXIC is null so we need to use ShellWidget->mXIC
|
||||
|
||||
if (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
if (!mIMEShellWidget) return;
|
||||
}
|
||||
|
||||
nsIMEGtkIC *XIC_tmp = mXIC ? mXIC : mIMEShellWidget->mXIC;
|
||||
if (XIC_tmp && XIC_tmp->IsPreeditComposing() == PR_TRUE) {
|
||||
IMEComposeText(nsnull, nsnull, nsnull, nsnull); // clear composed string
|
||||
IMEComposeEnd(nsnull); // force to end
|
||||
}
|
||||
}
|
||||
|
||||
void nsWidget::IMECheckPreedit_PostProc()
|
||||
{
|
||||
// There is a case that IMECommitEvent is called from non-inputfield
|
||||
// (bug 17419)
|
||||
// mXIC is null so we need to use ShellWidget->mXIC
|
||||
|
||||
if (!mIMEShellWidget) {
|
||||
mIMEShellWidget = GetShellWidget((GdkWindow*)
|
||||
GetNativeData(NS_NATIVE_WINDOW));
|
||||
NS_ASSERTION(mIMEShellWidget, "GetShellWidget() fails");
|
||||
if (!mIMEShellWidget) return;
|
||||
}
|
||||
nsIMEGtkIC *XIC_tmp = mXIC ? mXIC : mIMEShellWidget->mXIC;
|
||||
if(XIC_tmp && XIC_tmp->IsPreeditComposing() == PR_TRUE) {
|
||||
IMEComposeStart(nsnull); // do not reset compose string
|
||||
nsIMEPreedit *preedit = XIC_tmp->GetPreedit();
|
||||
IMEComposeText(nsnull,
|
||||
preedit->GetPreeditString(),
|
||||
preedit->GetPreeditLength(),
|
||||
preedit->GetPreeditFeedback());
|
||||
}
|
||||
}
|
||||
#endif // USE_XIM
|
||||
|
||||
@ -35,6 +35,10 @@
|
||||
class nsILookAndFeel;
|
||||
class nsIAppShell;
|
||||
class nsIToolkit;
|
||||
#ifdef USE_XIM
|
||||
class nsIMEGtkIC;
|
||||
class nsIMEPreedit;
|
||||
#endif // USE_XIM
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
@ -322,13 +326,56 @@ protected:
|
||||
|
||||
static void SuppressModality(PRBool aSuppress);
|
||||
|
||||
|
||||
public:
|
||||
#ifdef USE_XIM
|
||||
protected:
|
||||
PRBool mIMEEnable;
|
||||
PRUnichar* mIMECompositionUniString;
|
||||
PRInt32 mIMECompositionUniStringSize;
|
||||
PRBool mIMEIsDeactivating;
|
||||
void GetXIC();
|
||||
static GdkFont *gPreeditFontset;
|
||||
static GdkFont *gStatusFontset;
|
||||
static GdkIMStyle gInputStyle;
|
||||
nsIMEGtkIC *mXIC;
|
||||
PRBool mIMECallComposeStart;
|
||||
PRBool mIMECallComposeEnd;
|
||||
nsWidget* mIMEShellWidget;
|
||||
PRBool mICPerShell;
|
||||
void SetXICSpotLocation(nsPoint aPoint);
|
||||
void SetXICBaseFontSize(int height);
|
||||
void IMECheckPreedit_PreProc();
|
||||
void IMECheckPreedit_PostProc();
|
||||
|
||||
void GetXYFromPosition(unsigned long *aX, unsigned long *aY);
|
||||
nsITimer *mICSpotTimer;
|
||||
static void ICSpotCallback(nsITimer* aTimer, void* aClosure);
|
||||
nsresult KillICSpotTimer();
|
||||
nsresult PrimeICSpotTimer();
|
||||
nsresult UpdateICSpot();
|
||||
int mXICFontSize;
|
||||
nsWidget* GetShellWidget2();
|
||||
|
||||
public:
|
||||
void ime_preedit_start();
|
||||
void ime_preedit_draw();
|
||||
void ime_preedit_done();
|
||||
void ime_status_draw();
|
||||
|
||||
void IMEUnsetFocusWidget();
|
||||
void IMESetFocusWidget();
|
||||
void IMEDeactivateWidget();
|
||||
void IMEActivateWidget();
|
||||
void IMEDestroyIC();
|
||||
#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:
|
||||
|
||||
@ -446,29 +493,16 @@ protected:
|
||||
PRUint32 mPreferredWidth, mPreferredHeight;
|
||||
PRBool mListenForResizes;
|
||||
|
||||
GdkICPrivate *mIC;
|
||||
GdkICPrivate *GetXIC();
|
||||
void SetXIC(GdkICPrivate *aIC);
|
||||
void GetXYFromPosition(unsigned long *aX, unsigned long *aY);
|
||||
|
||||
// this is the rollup listener variables
|
||||
static nsCOMPtr<nsIRollupListener> gRollupListener;
|
||||
static nsCOMPtr<nsIWidget> gRollupWidget;
|
||||
static PRBool gRollupConsumeRollupEvent;
|
||||
|
||||
nsITimer* mICSpotTimer;
|
||||
static void ICSpotCallback(nsITimer* aTimer, void* aClosure);
|
||||
// this is the last time that an event happened. we keep this
|
||||
// around so that we can synth drag events properly
|
||||
static guint32 sLastEventTime;
|
||||
public:
|
||||
nsresult KillICSpotTimer();
|
||||
nsresult PrimeICSpotTimer();
|
||||
nsresult UpdateICSpot();
|
||||
|
||||
|
||||
private:
|
||||
int mXICFontSize;
|
||||
static nsILookAndFeel *sLookAndFeel;
|
||||
static PRUint32 sWidgetCount;
|
||||
|
||||
|
||||
@ -208,6 +208,10 @@ NS_IMETHODIMP nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
|
||||
void
|
||||
nsWindow::DestroyNative(void)
|
||||
{
|
||||
#ifdef USE_XIM
|
||||
IMEDestroyIC();
|
||||
#endif // USE_XIM
|
||||
|
||||
// destroy all of the children that are nsWindow() classes
|
||||
// preempting the gdk destroy system.
|
||||
DestroyNativeChildren();
|
||||
@ -844,34 +848,9 @@ nsWindow::SetFocus(void)
|
||||
// check to see if we need to send a focus out event for the old window
|
||||
if (focusWindow)
|
||||
{
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf(" IME is not usable on this window\n");
|
||||
#endif
|
||||
}
|
||||
if (mIC)
|
||||
{
|
||||
GdkWindow *gdkWindow = (GdkWindow*) focusWindow->GetNativeData(NS_NATIVE_WINDOW);
|
||||
focusWindow->KillICSpotTimer();
|
||||
if (gdkWindow)
|
||||
{
|
||||
gdk_im_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdkWindow is not usable\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("mIC isn't created yet\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_XIM
|
||||
focusWindow->IMEUnsetFocusWidget();
|
||||
#endif // USE_XIM
|
||||
// let the current window loose its focus
|
||||
focusWindow->LooseFocus();
|
||||
}
|
||||
@ -881,6 +860,10 @@ nsWindow::SetFocus(void)
|
||||
focusWindow = this;
|
||||
mHasFocus = PR_TRUE;
|
||||
|
||||
#ifdef USE_XIM
|
||||
if (focusWindow) focusWindow->IMESetFocusWidget();
|
||||
#endif // USE_XIM
|
||||
|
||||
// don't recurse
|
||||
if (mBlockFocusEvents)
|
||||
{
|
||||
@ -911,40 +894,6 @@ nsWindow::SetFocus(void)
|
||||
|
||||
mBlockFocusEvents = PR_FALSE;
|
||||
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf(" IME is not usable on this window\n");
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mIC)
|
||||
GetXIC();
|
||||
|
||||
if (mIC)
|
||||
{
|
||||
GdkWindow *gdkWindow = (GdkWindow*) GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (gdkWindow)
|
||||
{
|
||||
gdk_im_begin ((GdkIC*)mIC, gdkWindow);
|
||||
UpdateICSpot();
|
||||
PrimeICSpotTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdkWindow is not usable\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("mIC can't created yet\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(gJustGotDeactivate){
|
||||
gJustGotDeactivate = PR_FALSE;
|
||||
nsGUIEvent eventActivate;
|
||||
@ -961,6 +910,10 @@ nsWindow::SetFocus(void)
|
||||
AddRef();
|
||||
DispatchFocus(eventActivate);
|
||||
Release();
|
||||
|
||||
#ifdef USE_XIM
|
||||
IMEActivateWidget();
|
||||
#endif // USE_XIM
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -992,43 +945,6 @@ nsWindow::OnFocusInSignal(GdkEventFocus * aGdkFocusEvent)
|
||||
DispatchFocus(event);
|
||||
|
||||
Release();
|
||||
|
||||
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf(" IME is not usable on this window\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mIC)
|
||||
GetXIC();
|
||||
|
||||
if (mIC)
|
||||
{
|
||||
GdkWindow *gdkWindow = (GdkWindow*) GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (gdkWindow)
|
||||
{
|
||||
gdk_im_begin ((GdkIC*)mIC, gdkWindow);
|
||||
UpdateICSpot();
|
||||
PrimeICSpotTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdkWindow is not usable\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("mIC can't created yet\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* virtual */ void
|
||||
@ -1055,37 +971,6 @@ nsWindow::OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent)
|
||||
DispatchFocus(event);
|
||||
|
||||
Release();
|
||||
|
||||
|
||||
|
||||
if(mIMEEnable == PR_FALSE)
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf(" IME is not usable on this window\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (mIC)
|
||||
{
|
||||
GdkWindow *gdkWindow = (GdkWindow*) GetNativeData(NS_NATIVE_WINDOW);
|
||||
KillICSpotTimer();
|
||||
if (gdkWindow)
|
||||
{
|
||||
gdk_im_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("gdkWindow is not usable\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NOISY_XIM
|
||||
printf("mIC isn't created yet\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@ -2491,6 +2376,10 @@ gint handle_toplevel_focus_out(GtkWidget * aWidget,
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef USE_XIM
|
||||
widget->IMEDeactivateWidget();
|
||||
#endif // USE_XIM
|
||||
|
||||
// Dispatch NS_DEACTIVATE
|
||||
nsGUIEvent event;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user