Bug 337036 Crashes in IM_get_owning_window r=katakai, sr=roc

This commit is contained in:
masayuki%d-toybox.com 2006-05-12 08:46:54 +00:00
Родитель 278c093be5
Коммит b4ba4f607e
2 изменённых файлов: 58 добавлений и 46 удалений

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

@ -256,7 +256,7 @@ static void IM_set_text_range (const PRInt32 aLen,
static nsWindow *IM_get_owning_window(MozDrawingarea *aArea); static nsWindow *IM_get_owning_window(MozDrawingarea *aArea);
static GtkIMContext *IM_get_input_context(MozDrawingarea *aArea); static GtkIMContext *IM_get_input_context(nsWindow *window);
// If after selecting profile window, the startup fail, please refer to // If after selecting profile window, the startup fail, please refer to
// http://bugzilla.gnome.org/show_bug.cgi?id=88940 // http://bugzilla.gnome.org/show_bug.cgi?id=88940
@ -745,8 +745,8 @@ nsWindow::SetFocus(PRBool aRaise)
// If the focus window and this window share the same input // If the focus window and this window share the same input
// context we don't have to change the focus of the IME // context we don't have to change the focus of the IME
// context // context
if (IM_get_input_context(this->mDrawingarea) != if (IM_get_input_context(this) !=
IM_get_input_context(gFocusWindow->mDrawingarea)) IM_get_input_context(gFocusWindow))
gFocusWindow->IMELoseFocus(); gFocusWindow->IMELoseFocus();
#endif #endif
gFocusWindow->LoseFocus(); gFocusWindow->LoseFocus();
@ -4777,8 +4777,9 @@ nsChildWindow::~nsChildWindow()
void void
nsWindow::IMEDestroyContext(void) nsWindow::IMEDestroyContext(void)
{ {
if (!mIMEData) { if (!mIMEData || mIMEData->mOwner != this) {
// Clear reference to this. // This nsWindow is not the owner of the instance of mIMEData,
// we should only clear reference to this.
if (IMEComposingWindow() == this) if (IMEComposingWindow() == this)
CancelIMEComposition(); CancelIMEComposition();
if (gIMEFocusWindow == this) if (gIMEFocusWindow == this)
@ -4786,6 +4787,14 @@ nsWindow::IMEDestroyContext(void)
return; return;
} }
/* NOTE:
* This nsWindow is the owner of the instance of mIMEData,
* so, we must free the instance now. But that was referred from other
* nsWindows.(They are children of this.) But we don't need to worry about
* this issue. Because this function is only called on destroying this
* nsWindow. So, the children of this window should already be destroyed.
*/
// If this is the focus window and we have an IM context we need // If this is the focus window and we have an IM context we need
// to unset the focus on this window before we destroy the window. // to unset the focus on this window before we destroy the window.
GtkIMContext *im = IMEGetContext(); GtkIMContext *im = IMEGetContext();
@ -4811,6 +4820,13 @@ nsWindow::IMEDestroyContext(void)
void void
nsWindow::IMESetFocus(void) nsWindow::IMESetFocus(void)
{ {
// Initialize mIMEData for this window
if (!mIMEData) {
nsWindow *win = IMEGetOwningWindow();
if (win)
mIMEData = win->mIMEData;
}
LOGIM(("IMESetFocus %p\n", (void *)this)); LOGIM(("IMESetFocus %p\n", (void *)this));
GtkIMContext *im = IMEGetContext(); GtkIMContext *im = IMEGetContext();
if (!im) if (!im)
@ -4842,17 +4858,17 @@ nsWindow::IMEComposeStart(void)
{ {
LOGIM(("IMEComposeStart [%p]\n", (void *)this)); LOGIM(("IMEComposeStart [%p]\n", (void *)this));
if (!mIMEData) {
NS_ERROR("This widget doesn't support IM");
return;
}
if (IMEComposingWindow()) { if (IMEComposingWindow()) {
NS_WARNING("tried to re-start text composition\n"); NS_WARNING("tried to re-start text composition\n");
return; return;
} }
nsWindow *win = IMEGetOwningWindow(); mIMEData->mComposingWindow = this;
if (win) {
nsIMEData *data = win->mIMEData;
if (data)
data->mComposingWindow = this;
}
nsCompositionEvent compEvent(PR_TRUE, NS_COMPOSITION_START, this); nsCompositionEvent compEvent(PR_TRUE, NS_COMPOSITION_START, this);
@ -4882,6 +4898,11 @@ nsWindow::IMEComposeText (const PRUnichar *aText,
const gint aCursorPos, const gint aCursorPos,
const PangoAttrList *aFeedback) const PangoAttrList *aFeedback)
{ {
if (!mIMEData) {
NS_ERROR("This widget doesn't support IM");
return;
}
// Send our start composition event if we need to // Send our start composition event if we need to
if (!IMEComposingWindow()) if (!IMEComposingWindow())
IMEComposeStart(); IMEComposeStart();
@ -4926,18 +4947,14 @@ void
nsWindow::IMEComposeEnd(void) nsWindow::IMEComposeEnd(void)
{ {
LOGIM(("IMEComposeEnd [%p]\n", (void *)this)); LOGIM(("IMEComposeEnd [%p]\n", (void *)this));
NS_ASSERTION(mIMEData, "This widget doesn't support IM");
if (!IMEComposingWindow()) { if (!IMEComposingWindow()) {
NS_WARNING("tried to end text composition before it was started"); NS_WARNING("tried to end text composition before it was started");
return; return;
} }
nsWindow *win = IMEGetOwningWindow(); mIMEData->mComposingWindow = nsnull;
if (win) {
nsIMEData *data = win->mIMEData;
if (data)
data->mComposingWindow = nsnull;
}
nsCompositionEvent compEvent(PR_TRUE, NS_COMPOSITION_END, this); nsCompositionEvent compEvent(PR_TRUE, NS_COMPOSITION_END, this);
@ -4948,25 +4965,19 @@ nsWindow::IMEComposeEnd(void)
GtkIMContext* GtkIMContext*
nsWindow::IMEGetContext() nsWindow::IMEGetContext()
{ {
return IM_get_input_context(this->mDrawingarea); return IM_get_input_context(this);
} }
PRBool PRBool
nsWindow::IMEIsEnabled(void) nsWindow::IMEIsEnabled(void)
{ {
nsWindow *win = IMEGetOwningWindow(); return mIMEData ? mIMEData->mEnabled : PR_FALSE;
if (!win)
return PR_FALSE;
return win->mIMEData ? win->mIMEData->mEnabled : PR_FALSE;
} }
nsWindow* nsWindow*
nsWindow::IMEComposingWindow(void) nsWindow::IMEComposingWindow(void)
{ {
nsWindow *win = IMEGetOwningWindow(); return mIMEData ? mIMEData->mComposingWindow : nsnull;
if (!win)
return nsnull;
return win->mIMEData ? win->mIMEData->mComposingWindow : nsnull;
} }
nsWindow* nsWindow*
@ -4979,7 +4990,7 @@ nsWindow::IMEGetOwningWindow(void)
void void
nsWindow::IMECreateContext(void) nsWindow::IMECreateContext(void)
{ {
mIMEData = new nsIMEData; mIMEData = new nsIMEData(this);
if (!mIMEData) if (!mIMEData)
return; return;
@ -5080,35 +5091,31 @@ nsWindow::GetIMEOpenState(PRBool* aState)
NS_IMETHODIMP NS_IMETHODIMP
nsWindow::SetIMEEnabled(PRBool aState) nsWindow::SetIMEEnabled(PRBool aState)
{ {
nsWindow *window = IMEGetOwningWindow(); if (!mIMEData || mIMEData->mEnabled == aState)
if (!window || !window->mIMEData || window->mIMEData->mEnabled == aState)
return NS_OK; return NS_OK;
GtkIMContext *focusedIm = nsnull; GtkIMContext *focusedIm = nsnull;
// XXX Don't we need to check gFocusWindow? // XXX Don't we need to check gFocusWindow?
nsWindow *focusedWin = gIMEFocusWindow; nsWindow *focusedWin = gIMEFocusWindow;
if (focusedWin) { if (focusedWin && focusedWin->mIMEData)
nsWindow *owningWin = focusedWin->IMEGetOwningWindow(); focusedIm = focusedWin->mIMEData->mContext;
if (owningWin && owningWin->mIMEData)
focusedIm = owningWin->mIMEData->mContext;
}
if (focusedIm && focusedIm == window->mIMEData->mContext) { if (focusedIm && focusedIm == mIMEData->mContext) {
// Release current IME focus if IME is enabled. // Release current IME focus if IME is enabled.
if (window->mIMEData->mEnabled) { if (mIMEData->mEnabled) {
focusedWin->ResetInputState(); focusedWin->ResetInputState();
focusedWin->IMELoseFocus(); focusedWin->IMELoseFocus();
} }
window->mIMEData->mEnabled = aState; mIMEData->mEnabled = aState;
// Even when aState is not PR_TRUE, we need to set IME focus. // Even when aState is not PR_TRUE, we need to set IME focus.
// Because some IMs are updating the status bar of them in this time. // Because some IMs are updating the status bar of them in this time.
focusedWin->IMESetFocus(); focusedWin->IMESetFocus();
} else { } else {
if (window->mIMEData->mEnabled) if (mIMEData->mEnabled)
ResetInputState(); ResetInputState();
window->mIMEData->mEnabled = aState; mIMEData->mEnabled = aState;
} }
return NS_OK; return NS_OK;
@ -5404,11 +5411,11 @@ IM_get_owning_window(MozDrawingarea *aArea)
/* static */ /* static */
GtkIMContext * GtkIMContext *
IM_get_input_context(MozDrawingarea *aArea) IM_get_input_context(nsWindow *aWindow)
{ {
if (!aArea) if (!aWindow)
return nsnull; return nsnull;
nsWindow::nsIMEData *data = IM_get_owning_window(aArea)->mIMEData; nsWindow::nsIMEData *data = aWindow->mIMEData;
if (!data) if (!data)
return nsnull; return nsnull;
return data->mEnabled ? data->mContext : data->mDummyContext; return data->mEnabled ? data->mContext : data->mDummyContext;

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

@ -287,9 +287,10 @@ public:
/* /*
* |mIMEData| has all IME data for the window and its children widgets. * |mIMEData| has all IME data for the window and its children widgets.
* So, this is created only on owner widget. Therefore, when the * Only stand-alone windows and child windows embedded in non-Mozilla GTK
* focused widget needs the data, it get from its owning window. * containers own IME contexts.
* See |IM_get_input_context|. * But this is referred from all children after the widget gets focus.
* The children refers to its owning window's object.
*/ */
struct nsIMEData { struct nsIMEData {
// Actual context. This is used for handling the user's input. // Actual context. This is used for handling the user's input.
@ -307,12 +308,16 @@ public:
// changing input focus, we will use the original widget of // changing input focus, we will use the original widget of
// mComposingWindow to commit or reset the composition. // mComposingWindow to commit or reset the composition.
nsWindow *mComposingWindow; nsWindow *mComposingWindow;
// Owner of this struct.
// The owner window must free this instance at destroying.
nsWindow *mOwner;
// IME enabled state in this window. // IME enabled state in this window.
PRPackedBool mEnabled; PRPackedBool mEnabled;
nsIMEData() { nsIMEData(nsWindow* aOwner) {
mContext = nsnull; mContext = nsnull;
mDummyContext = nsnull; mDummyContext = nsnull;
mComposingWindow = nsnull; mComposingWindow = nsnull;
mOwner = aOwner;
mEnabled = PR_TRUE; mEnabled = PR_TRUE;
} }
}; };