зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
906a287308
Коммит
bca2539c53
|
@ -31,7 +31,6 @@
|
|||
#include "nsIPref.h"
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
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;
|
||||
if (!thisXIC) return 0;
|
||||
nsWidget *widget = thisXIC->mFocusWidget;
|
||||
if (!widget) return 0;
|
||||
nsWindow *fwin = thisXIC->mFocusWindow;
|
||||
if (!fwin) return 0;
|
||||
|
||||
if (!thisXIC->mPreedit) {
|
||||
thisXIC->mPreedit = new nsIMEPreedit();
|
||||
}
|
||||
thisXIC->mPreedit->Reset();
|
||||
widget->ime_preedit_start();
|
||||
fwin->ime_preedit_start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -834,8 +833,8 @@ nsIMEGtkIC::preedit_draw_cbproc(XIC xic, XPointer client_data,
|
|||
{
|
||||
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
|
||||
if (!thisXIC) return 0;
|
||||
nsWidget *widget = thisXIC->mFocusWidget;
|
||||
if (!widget) return 0;
|
||||
nsWindow *fwin = thisXIC->mFocusWindow;
|
||||
if (!fwin) return 0;
|
||||
|
||||
XIMPreeditDrawCallbackStruct *call_data =
|
||||
(XIMPreeditDrawCallbackStruct *) call_data_p;
|
||||
|
@ -847,7 +846,7 @@ nsIMEGtkIC::preedit_draw_cbproc(XIC xic, XPointer client_data,
|
|||
thisXIC->mPreedit->SetPreeditString(text,
|
||||
call_data->chg_first,
|
||||
call_data->chg_length);
|
||||
widget->ime_preedit_draw();
|
||||
fwin->ime_preedit_draw(thisXIC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -864,10 +863,10 @@ nsIMEGtkIC::preedit_done_cbproc(XIC xic, XPointer client_data,
|
|||
{
|
||||
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
|
||||
if (!thisXIC) return 0;
|
||||
nsWidget *widget = thisXIC->mFocusWidget;
|
||||
if (!widget) return 0;
|
||||
nsWindow *fwin = thisXIC->mFocusWindow;
|
||||
if (!fwin) return 0;
|
||||
|
||||
widget->ime_preedit_done();
|
||||
fwin->ime_preedit_done();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -877,8 +876,8 @@ nsIMEGtkIC::status_start_cbproc(XIC xic, XPointer client_data,
|
|||
{
|
||||
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
|
||||
if (!thisXIC) return 0;
|
||||
nsWidget *widget = thisXIC->mFocusWidget;
|
||||
if (!widget) return 0;
|
||||
nsWindow *fwin = thisXIC->mFocusWindow;
|
||||
if (!fwin) return 0;
|
||||
if (!gStatus) return 0;
|
||||
|
||||
// focus_window is changed
|
||||
|
@ -893,8 +892,8 @@ nsIMEGtkIC::status_draw_cbproc(XIC xic, XPointer client_data,
|
|||
{
|
||||
nsIMEGtkIC *thisXIC = (nsIMEGtkIC*)client_data;
|
||||
if (!thisXIC) return 0;
|
||||
nsWidget *widget = thisXIC->mFocusWidget;
|
||||
if (!widget) return 0;
|
||||
nsWindow *fwin = thisXIC->mFocusWindow;
|
||||
if (!fwin) return 0;
|
||||
|
||||
if (!gStatus) return 0;
|
||||
|
||||
|
@ -939,10 +938,10 @@ nsIMEGtkIC::status_done_cbproc(XIC xic, XPointer client_data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
nsWidget *
|
||||
nsIMEGtkIC::GetFocusWidget()
|
||||
nsWindow *
|
||||
nsIMEGtkIC::GetFocusWindow()
|
||||
{
|
||||
return mFocusWidget;
|
||||
return mFocusWindow;
|
||||
}
|
||||
|
||||
// workaround for kinput2/over-the-spot/ic-per-shell
|
||||
|
@ -965,10 +964,10 @@ nsIMEGtkIC::GetFocusWidget()
|
|||
// *OverTheSpotConversion.modeLocation: bottomleft
|
||||
|
||||
void
|
||||
nsIMEGtkIC::SetFocusWidget(nsWidget * aFocusWidget)
|
||||
nsIMEGtkIC::SetFocusWindow(nsWindow * aFocusWindow)
|
||||
{
|
||||
mFocusWidget = aFocusWidget;
|
||||
GdkWindow *gdkWindow = (GdkWindow*)aFocusWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
mFocusWindow = aFocusWindow;
|
||||
GdkWindow *gdkWindow = (GdkWindow*)aFocusWindow->GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (!gdkWindow) return;
|
||||
|
||||
gdk_im_begin((GdkIC *) mIC, gdkWindow);
|
||||
|
@ -987,20 +986,20 @@ nsIMEGtkIC::SetFocusWidget(nsWidget * aFocusWidget)
|
|||
}
|
||||
|
||||
void
|
||||
nsIMEGtkIC::UnsetFocusWidget()
|
||||
nsIMEGtkIC::UnsetFocusWindow()
|
||||
{
|
||||
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)
|
||||
{
|
||||
nsIMEGtkIC *newic = new nsIMEGtkIC(aFocusWidget, aFontSet, aStatusFontSet);
|
||||
nsIMEGtkIC *newic = new nsIMEGtkIC(aFocusWindow, aFontSet, aStatusFontSet);
|
||||
if (!newic->mIC || !newic->mIC->xic) {
|
||||
delete newic;
|
||||
return nsnull;
|
||||
|
@ -1032,7 +1031,7 @@ nsIMEGtkIC::~nsIMEGtkIC()
|
|||
mIC = 0;
|
||||
mIC_backup = 0;
|
||||
mPreedit = 0;
|
||||
mFocusWidget = 0;
|
||||
mFocusWindow = 0;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
mFocusWidget = 0;
|
||||
mFocusWindow = 0;
|
||||
mIC = 0;
|
||||
mIC_backup = 0;
|
||||
mPreedit = 0;
|
||||
|
||||
GdkWindow *gdkWindow = (GdkWindow *) aFocusWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
GdkWindow *gdkWindow = (GdkWindow *) aFocusWindow->GetNativeData(NS_NATIVE_WINDOW);
|
||||
if (!gdkWindow) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ typedef struct {
|
|||
XIMProc1 callback;
|
||||
} XIMCallback1;
|
||||
|
||||
class nsWidget;
|
||||
class nsWindow;
|
||||
|
||||
enum nsIMEPolicy {
|
||||
NSIME_UNKNOWN=0,
|
||||
|
@ -130,10 +130,10 @@ class nsIMEGtkIC {
|
|||
static GdkIMStyle gInputStyle;
|
||||
static nsIMEPolicy gInputPolicy;
|
||||
static nsIMEStatus *gStatus;
|
||||
nsWidget *mClientWidget;
|
||||
nsWidget *mFocusWidget;
|
||||
nsIMEGtkIC(nsWidget*, GdkFont*, GdkFont*);
|
||||
nsIMEGtkIC(nsWidget*, GdkFont*);
|
||||
nsWindow *mClientWindow;
|
||||
nsWindow *mFocusWindow;
|
||||
nsIMEGtkIC(nsWindow*, GdkFont*, GdkFont*);
|
||||
nsIMEGtkIC(nsWindow*, GdkFont*);
|
||||
GdkICPrivate *mIC;
|
||||
GdkICPrivate *mIC_backup;
|
||||
nsIMEPreedit *mPreedit;
|
||||
|
@ -141,11 +141,11 @@ class nsIMEGtkIC {
|
|||
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 nsIMEGtkIC *GetXIC(nsWindow*, GdkFont*, GdkFont*);
|
||||
static nsIMEGtkIC *GetXIC(nsWindow*, GdkFont*);
|
||||
void SetFocusWindow(nsWindow * aFocusWindow);
|
||||
nsWindow* GetFocusWindow();
|
||||
static void UnsetFocusWindow();
|
||||
static GdkIMStyle GetInputStyle();
|
||||
static nsIMEPolicy GetInputPolicy();
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "nsGtkUtils.h" // for nsGtkUtils::gdk_keyboard_get_modifiers()
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "nsGtkIMEHelper.h"
|
||||
|
||||
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
@ -67,18 +66,11 @@ private:
|
|||
*mLast; // valid only for head of list
|
||||
};
|
||||
|
||||
static nsWidget *GetShellWidget(GdkWindow *gdkWindow);
|
||||
|
||||
PRUint32 nsWidget::sWidgetCount = 0;
|
||||
|
||||
// this is the nsWindow with the focus
|
||||
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
|
||||
// around so that we can synth drag events properly
|
||||
guint32 nsWidget::sLastEventTime = 0;
|
||||
|
@ -118,89 +110,6 @@ void nsWidget::GetLastEventTime(guint32 *aTime)
|
|||
*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;
|
||||
nsWeakPtr nsWidget::gRollupWidget;
|
||||
PRBool nsWidget::gRollupConsumeRollupEvent = PR_FALSE;
|
||||
|
@ -268,20 +177,6 @@ nsWidget::nsWidget()
|
|||
|
||||
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;
|
||||
mHasFocus = PR_FALSE;
|
||||
if (mGDKHandlerInstalled == PR_FALSE) {
|
||||
|
@ -320,11 +215,6 @@ nsWidget::nsWidget()
|
|||
|
||||
nsWidget::~nsWidget()
|
||||
{
|
||||
#ifdef USE_XIM
|
||||
mXIC = 0;
|
||||
KillICSpotTimer();
|
||||
#endif // USE_XIM
|
||||
|
||||
#ifdef NOISY_DESTROY
|
||||
IndentByDepth(stdout);
|
||||
printf("nsWidget::~nsWidget:%p\n", this);
|
||||
|
@ -336,10 +226,6 @@ nsWidget::~nsWidget()
|
|||
// to be called once
|
||||
Destroy();
|
||||
|
||||
if (mIMECompositionUniString) {
|
||||
delete[] mIMECompositionUniString;
|
||||
mIMECompositionUniString = nsnull;
|
||||
}
|
||||
NS_ASSERTION(!ModalWidgetList::Find(this), "destroying widget without first clearing modality.");
|
||||
#ifdef NS_DEBUG
|
||||
if (mIsToplevel) {
|
||||
|
@ -727,10 +613,6 @@ nsWidget::LoseFocus(void)
|
|||
if (mHasFocus == PR_FALSE)
|
||||
return;
|
||||
|
||||
#ifdef USE_XIM
|
||||
IMEUnsetFocusWidget();
|
||||
#endif // USE_XIM
|
||||
|
||||
sFocusWindow = 0;
|
||||
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()
|
||||
{
|
||||
#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;
|
||||
}
|
||||
|
||||
#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 ***********************/
|
||||
/* 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
|
||||
|
@ -2904,267 +2660,10 @@ static gint debugHandleWindowClose(GtkWidget *window, void *data)
|
|||
|
||||
#endif /* NS_DEBUG */
|
||||
|
||||
#ifdef USE_XIM
|
||||
void
|
||||
nsWidget::ime_preedit_start() {
|
||||
IMEComposeStart(nsnull);
|
||||
void nsWidget::IMECommitEvent(GdkEventKey *aEvent) {
|
||||
NS_ASSERTION(0, "nsWidget::IMECommitEvent() shouldn't be called!\n");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
NS_ASSERTION(0, "nsWidget::DispatchSetFocusEvent shouldn't be called!\n");
|
||||
|
|
|
@ -36,10 +36,6 @@
|
|||
class nsILookAndFeel;
|
||||
class nsIAppShell;
|
||||
class nsIToolkit;
|
||||
#ifdef USE_XIM
|
||||
class nsIMEGtkIC;
|
||||
class nsIMEPreedit;
|
||||
#endif // USE_XIM
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
@ -49,6 +45,7 @@ class nsIMEPreedit;
|
|||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
|
||||
|
||||
#define NSRECT_TO_GDKRECT(ns,gdk) \
|
||||
PR_BEGIN_MACRO \
|
||||
gdk.x = ns.x; \
|
||||
|
@ -309,52 +306,8 @@ protected:
|
|||
PRBool HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel);
|
||||
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:
|
||||
void ime_preedit_start();
|
||||
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);
|
||||
virtual void IMECommitEvent(GdkEventKey *aEvent);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
#include "nsIDragService.h"
|
||||
#include "nsIDragSessionGTK.h"
|
||||
|
||||
#include "nsGtkIMEHelper.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef NEED_USLEEP_PROTOTYPE
|
||||
|
@ -118,6 +120,20 @@ nsWindow *nsWindow::mLastLeaveWindow = NULL;
|
|||
PRBool gJustGotDeactivate = 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) {
|
||||
int i;
|
||||
for (i=0; i < depth; i++)
|
||||
|
@ -166,6 +182,23 @@ nsWindow::nsWindow()
|
|||
mDragMotionY = 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
|
||||
if (!gRaisePrefInitialized) {
|
||||
gRaisePrefInitialized = PR_TRUE;
|
||||
|
@ -188,6 +221,15 @@ 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.
|
||||
ResetDragMotionTimer(0, 0, 0, 0, 0);
|
||||
|
||||
|
@ -310,14 +352,14 @@ 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();
|
||||
|
||||
#ifdef USE_XIM
|
||||
IMEDestroyIC();
|
||||
#endif // USE_XIM
|
||||
|
||||
if (mSuperWin) {
|
||||
// remove the key from the hash table for the shell_window
|
||||
g_hash_table_remove(mWindowLookupTable, mSuperWin->shell_window);
|
||||
|
@ -1157,7 +1199,7 @@ nsWindow::SetFocus(PRBool aRaise)
|
|||
mHasFocus = PR_TRUE;
|
||||
|
||||
#ifdef USE_XIM
|
||||
if (sFocusWindow) sFocusWindow->IMESetFocusWidget();
|
||||
IMESetFocusWindow();
|
||||
#endif // USE_XIM
|
||||
|
||||
DispatchSetFocusEvent();
|
||||
|
@ -1172,6 +1214,22 @@ nsWindow::SetFocus(PRBool aRaise)
|
|||
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)
|
||||
{
|
||||
#ifdef DEBUG_FOCUS
|
||||
|
@ -3487,3 +3545,481 @@ PRBool ChildWindow::IsChild() const
|
|||
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 "gdksuperwin.h"
|
||||
|
||||
#ifdef USE_XIM
|
||||
#include "pldhash.h"
|
||||
class nsIMEGtkIC;
|
||||
class nsIMEPreedit;
|
||||
#endif // USE_XIM
|
||||
|
||||
class nsFont;
|
||||
class nsIAppShell;
|
||||
|
||||
|
@ -89,6 +95,11 @@ public:
|
|||
NS_IMETHOD GetAttention(void);
|
||||
NS_IMETHOD Destroy();
|
||||
|
||||
virtual void LoseFocus(void);
|
||||
|
||||
// nsIKBStateControl
|
||||
NS_IMETHOD ResetInputState();
|
||||
|
||||
void QueueDraw();
|
||||
void UnqueueDraw();
|
||||
void DoPaint(PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height,
|
||||
|
@ -309,7 +320,56 @@ protected:
|
|||
static void dumpWindowChildren(Window aWindow, unsigned int depth);
|
||||
#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:
|
||||
PRUnichar* mIMECompositionUniString;
|
||||
PRInt32 mIMECompositionUniStringSize;
|
||||
|
||||
nsresult SetMiniIcon(GdkPixmap *window_pixmap,
|
||||
GdkBitmap *window_mask);
|
||||
nsresult SetIcon(GdkPixmap *window_pixmap,
|
||||
|
|
Загрузка…
Ссылка в новой задаче