Bug 520732 Separate IME related code to another file from gtk2/nsWindow.cp r=katakai+karlt

This commit is contained in:
Masayuki Nakano 2010-03-19 13:21:16 +09:00
parent 3fa0080345
commit 01d8b15eb3
7 changed files with 1664 additions and 1002 deletions

View File

@ -79,6 +79,7 @@ CPPSRCS = \
nsImageToPixbuf.cpp \
nsAccessibilityHelper.cpp \
nsAccelerometerUnix.cpp \
nsGtkIMModule.cpp \
$(NULL)
ifdef MOZ_X11
@ -152,7 +153,6 @@ CXXFLAGS += $(MOZ_GCONF_CFLAGS)
endif
endif
DEFINES += -DUSE_XIM
DEFINES += -DCAIRO_GFX
ifdef MOZ_ENABLE_POSTSCRIPT

View File

@ -51,7 +51,6 @@
#ifdef PR_LOGGING
PRLogModuleInfo *gWidgetLog = nsnull;
PRLogModuleInfo *gWidgetFocusLog = nsnull;
PRLogModuleInfo *gWidgetIMLog = nsnull;
PRLogModuleInfo *gWidgetDragLog = nsnull;
PRLogModuleInfo *gWidgetDrawLog = nsnull;
#endif
@ -89,8 +88,6 @@ nsAppShell::Init()
gWidgetLog = PR_NewLogModule("Widget");
if (!gWidgetFocusLog)
gWidgetFocusLog = PR_NewLogModule("WidgetFocus");
if (!gWidgetIMLog)
gWidgetIMLog = PR_NewLogModule("WidgetIM");
if (!gWidgetDragLog)
gWidgetDragLog = PR_NewLogModule("WidgetDrag");
if (!gWidgetDrawLog)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by the Initial Developer
* are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Masayuki Nakano <masayuki@d-toybox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsGtkIMModule_h__
#define __nsGtkIMModule_h__
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsGUIEvent.h"
// If software keyboard is needed in password field and uses GTK2 IM module
// for inputting characters, we need to enable IME in password field too.
#ifdef MOZ_PLATFORM_MAEMO
#define NS_IME_ENABLED_ON_PASSWORD_FIELD 1
#endif
class nsWindow;
class nsGtkIMModule
{
public:
nsrefcnt AddRef()
{
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "mRefCnt is negative");
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsGtkIMModule", sizeof(*this));
return mRefCnt;
}
nsrefcnt Release()
{
NS_PRECONDITION(mRefCnt != 0, "mRefCnt is alrady zero");
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsGtkIMModule");
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
NS_DELETEXPCOM(this);
return 0;
}
return mRefCnt;
}
protected:
nsAutoRefCnt mRefCnt;
public:
// aOwnerWindow is a pointer of the owner window. When aOwnerWindow is
// destroyed, the related IME contexts are released (i.e., IME cannot be
// used with the instance after that).
nsGtkIMModule(nsWindow* aOwnerWindow);
~nsGtkIMModule();
// OnFocusWindow is a notification that aWindow is going to be focused.
void OnFocusWindow(nsWindow* aWindow);
// OnBlurWindow is a notification that aWindow is going to be unfocused.
void OnBlurWindow(nsWindow* aWindow);
// OnDestroyWindow is a notification that aWindow is going to be destroyed.
void OnDestroyWindow(nsWindow* aWindow);
// OnFocusChangeInGecko is a notification that an editor gets focus.
void OnFocusChangeInGecko(PRBool aFocus);
// OnKeyEvent is called when aWindow gets a native key press event or a
// native key release event. If this returns TRUE, the key event was
// filtered by IME. Otherwise, this returns FALSE.
// NOTE: When the keypress event starts composition, this returns TRUE but
// this dispatches keydown event before compositionstart event.
PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent);
// IME related nsIWidget methods.
nsresult ResetInputState(nsWindow* aCaller);
nsresult SetIMEEnabled(nsWindow* aCaller, PRUint32 aState);
nsresult GetIMEEnabled(PRUint32* aState);
nsresult CancelIMEComposition(nsWindow* aCaller);
// If a software keyboard has been opened, this returns TRUE.
// Otherwise, FALSE.
static PRBool IsVirtualKeyboardOpened();
protected:
// Owner of an instance of this class. This should be top level window.
// The owner window must release the contexts when it's destroyed because
// the IME contexts need the native window. If OnDestroyWindow() is called
// with the owner window, it'll release IME contexts. Otherwise, it'll
// just clean up any existing composition if it's related to the destroying
// child window.
nsWindow* mOwnerWindow;
// A last focused window in this class's context.
nsWindow* mLastFocusedWindow;
// Actual context. This is used for handling the user's input.
GtkIMContext *mContext;
#ifndef NS_IME_ENABLED_ON_PASSWORD_FIELD
// mSimpleContext is used for the password field and
// the |ime-mode: disabled;| editors. These editors disable IME.
// But dead keys should work. Fortunately, the simple IM context of
// GTK2 support only them.
GtkIMContext *mSimpleContext;
#endif // NS_IME_ENABLED_ON_PASSWORD_FIELD
// mDummyContext is a dummy context and will be used in Focus()
// when the state of mEnabled means disabled. This context's IME state is
// always "closed", so it closes IME forcedly.
GtkIMContext *mDummyContext;
// IME enabled state in this window. The values is nsIWidget::IME_STATUS_*.
// Use following helper methods if you don't need the detail of the status.
PRUint32 mEnabled;
// mCompositionStart is the start offset of the composition string in the
// current content. When <textarea> or <input> have focus, it means offset
// from the first character of them. When a HTML editor has focus, it
// means offset from the first character of the root element of the editor.
PRUint32 mCompositionStart;
// mCompositionString is the current composing string. Even if this is
// empty, we can be composing. See mIsComposing.
nsString mCompositionString;
// OnKeyEvent() temporarily sets mProcessingKeyEvent to the given native
// event.
GdkEventKey* mProcessingKeyEvent;
// mIsComposing is set to TRUE when we dispatch the composition start
// event. And it's set to FALSE when we dispatches the composition end
// event. Note that mCompositionString can be empty string even if this is
// TRUE.
PRPackedBool mIsComposing;
// mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And
// it's set to FALSE when we call gtk_im_context_focus_out().
PRPackedBool mIsIMFocused;
// mFilterKeyEvent is used by OnKeyEvent(). If the commit event should
// be processed as simple key event, this is set to TRUE by the commit
// handler.
PRPackedBool mFilterKeyEvent;
// When mIgnoreNativeCompositionEvent is TRUE, all native composition
// should be ignored except that the compositon should be restarted in
// another content (nsIContent). Don't refer this value directly, use
// ShouldIgnoreNativeCompositionEvent().
PRPackedBool mIgnoreNativeCompositionEvent;
// sLastFocusedModule is a pointer to the last focused instance of this
// class. When a instance is destroyed and sLastFocusedModule refers it,
// this is cleared. So, this refers valid pointer always.
static nsGtkIMModule* sLastFocusedModule;
// Callback methods for native IME events. These methods should call
// the related instance methods simply.
static void OnCommitCompositionCallback(GtkIMContext *aContext,
const gchar *aString,
nsGtkIMModule* aModule);
static void OnChangeCompositionCallback(GtkIMContext *aContext,
nsGtkIMModule* aModule);
static void OnStartCompositionCallback(GtkIMContext *aContext,
nsGtkIMModule* aModule);
static void OnEndCompositionCallback(GtkIMContext *aContext,
nsGtkIMModule* aModule);
// The instance methods for the native IME events.
void OnCommitCompositionNative(GtkIMContext *aContext,
const gchar *aString);
void OnChangeCompositionNative(GtkIMContext *aContext);
void OnStartCompositionNative(GtkIMContext *aContext);
void OnEndCompositionNative(GtkIMContext *aContext);
// GetContext() returns current IM context which is chosen by the enabled
// state. So, this means *current* IM context.
GtkIMContext* GetContext();
// "Enabled" means the users can use all IMEs.
// I.e., the focus is in the normal editors.
PRBool IsEnabled();
// "Editable" means the users can input characters. They may be not able to
// use IMEs but they can use dead keys.
// I.e., the focus is in the normal editors or the password editors or
// the |ime-mode: disabled;| editors.
PRBool IsEditable();
// If the owner window and IM context have been destroyed, returns TRUE.
PRBool IsDestroyed() { return !mOwnerWindow; }
// Sets focus to the instance of this class.
void Focus();
// Steals focus from the instance of this class.
void Blur();
// Initializes the instance.
void Init();
// Reset the current composition of IME. All native composition events
// during this processing are ignored.
void ResetIME();
// Gets the current composition string by the native APIs.
void GetCompositionString(nsAString &aCompositionString);
// Generates our text range list from current composition string.
void SetTextRangeList(nsTArray<nsTextRange> &aTextRangeList);
// Sets the offset's cursor position to IME.
void SetCursorPosition(PRUint32 aTargetOffset);
// Queries the current selection offset of the window.
PRUint32 GetSelectionOffset(nsWindow* aWindow);
// Initializes the GUI event.
void InitEvent(nsGUIEvent& aEvent);
// Called before destroying the context to work around some platform bugs.
void PrepareToDestroyContext(GtkIMContext *aContext);
PRBool ShouldIgnoreNativeCompositionEvent();
/**
* WARNING:
* Following methods dispatch gecko events. Then, the focused widget
* can be destroyed, and also it can be stolen focus. If they returns
* FALSE, callers cannot continue the composition.
* - CommitCompositionBy
* - DispatchCompositionStart
* - DispatchCompositionEnd
* - DispatchTextEvent
*/
// Commits the current composition by the aString.
PRBool CommitCompositionBy(const nsAString& aString);
// Dispatches a composition start event or a composition end event.
PRBool DispatchCompositionStart();
PRBool DispatchCompositionEnd();
// Dispatches a text event. If aCheckAttr is TRUE, dispatches a committed
// text event. Otherwise, dispatches a composing text event.
PRBool DispatchTextEvent(PRBool aCheckAttr);
};
#endif // __nsGtkIMModule_h__

File diff suppressed because it is too large Load Diff

View File

@ -81,15 +81,15 @@
#include "prlog.h"
#include "nsTArray.h"
#include "nsGtkIMModule.h"
extern PRLogModuleInfo *gWidgetLog;
extern PRLogModuleInfo *gWidgetFocusLog;
extern PRLogModuleInfo *gWidgetIMLog;
extern PRLogModuleInfo *gWidgetDragLog;
extern PRLogModuleInfo *gWidgetDrawLog;
#define LOG(args) PR_LOG(gWidgetLog, 4, args)
#define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
#define LOGIM(args) PR_LOG(gWidgetIMLog, 4, args)
#define LOGDRAG(args) PR_LOG(gWidgetDragLog, 4, args)
#define LOGDRAW(args) PR_LOG(gWidgetDrawLog, 4, args)
@ -97,7 +97,6 @@ extern PRLogModuleInfo *gWidgetDrawLog;
#define LOG(args)
#define LOGFOCUS(args)
#define LOGIM(args)
#define LOGDRAG(args)
#define LOGDRAW(args)
@ -310,91 +309,22 @@ public:
NS_IMETHOD BeginResizeDrag (nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
#ifdef USE_XIM
void IMEInitData (void);
void IMEReleaseData (void);
void IMEDestroyContext (void);
void IMESetFocus (void);
void IMELoseFocus (void);
void IMEComposeStart (void);
void IMEComposeText (const PRUnichar *aText,
const PRInt32 aLen,
const gchar *aPreeditString,
const gint aCursorPos,
const PangoAttrList *aFeedback);
void IMEComposeEnd (void);
GtkIMContext* IMEGetContext (void);
// "Enabled" means the users can use all IMEs.
// I.e., the focus is in the normal editors.
PRBool IMEIsEnabledState (void);
// "Editable" means the users can input characters. They may be not able to
// use IMEs but they can use dead keys.
// I.e., the forcus is in the normal editors or the password editors or
// the |ime-mode: disabled;| editors.
PRBool IMEIsEditableState(void);
nsWindow* IMEComposingWindow(void);
void IMECreateContext (void);
PRBool IMEFilterEvent (GdkEventKey *aEvent);
void IMESetCursorPosition(const nsTextEventReply& aReply);
MozContainer* GetMozContainer() { return mContainer; }
GdkWindow* GetGdkWindow() { return mGdkWindow; }
PRBool IsDestroyed() { return mIsDestroyed; }
/*
* |mIMEData| has all IME data for the window and its children widgets.
* Only stand-alone windows and child windows embedded in non-Mozilla GTK
* containers own IME contexts.
* But this is referred from all children after the widget gets focus.
* The children refers to its owning window's object.
*/
struct nsIMEData {
// Actual context. This is used for handling the user's input.
GtkIMContext *mContext;
// mSimpleContext is used for the password field and
// the |ime-mode: disabled;| editors. These editors disable IME.
// But dead keys should work. Fortunately, the simple IM context of
// GTK2 support only them.
GtkIMContext *mSimpleContext;
// mDummyContext is a dummy context and will be used in IMESetFocus()
// when mEnabled is false. This mDummyContext IM state is always
// "off", so it works to switch conversion mode to OFF on IM status
// window.
GtkIMContext *mDummyContext;
// This mComposingWindow is set in IMEComposeStart(), when user starts
// composition, then unset in IMEComposeEnd() when user ends the
// composition. We will keep the widget where the actual composition is
// started. During the composition, we may get some events like
// ResetInputStateInternal() and CancelIMECompositionInternal() by
// changing input focus, we will use the original widget of
// mComposingWindow to commit or reset the composition.
nsWindow *mComposingWindow;
// Owner of this struct.
// The owner window must release the contexts at destroying.
nsWindow *mOwner;
// The reference counter. When this will be zero by the decrement,
// the decrementer must free the instance.
PRUint32 mRefCount;
// IME enabled state in this window.
PRUint32 mEnabled;
nsIMEData(nsWindow* aOwner) {
mContext = nsnull;
mSimpleContext = nsnull;
mDummyContext = nsnull;
mComposingWindow = nsnull;
mOwner = aOwner;
mRefCount = 1;
mEnabled = nsIWidget::IME_STATUS_ENABLED;
}
};
nsIMEData *mIMEData;
// If this dispatched the keydown event actually, this returns TRUE,
// otherwise, FALSE.
PRBool DispatchKeyDownEvent(GdkEventKey *aEvent,
PRBool *aIsCancelled);
NS_IMETHOD ResetInputState();
NS_IMETHOD SetIMEOpenState(PRBool aState);
NS_IMETHOD GetIMEOpenState(PRBool* aState);
NS_IMETHOD SetIMEEnabled(PRUint32 aState);
NS_IMETHOD GetIMEEnabled(PRUint32* aState);
NS_IMETHOD CancelIMEComposition();
NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
#endif
void ResizeTransparencyBitmap(PRInt32 aNewWidth, PRInt32 aNewHeight);
void ApplyTransparencyBitmap();
virtual void SetTransparencyMode(nsTransparencyMode aMode);
@ -568,6 +498,20 @@ private:
*flag &= ~mask;
}
/**
* |mIMModule| takes all IME related stuff.
*
* This is owned by the top-level nsWindow or the topmost child
* nsWindow embedded in a non-Gecko widget.
*
* The instance is created when the top level widget is created. And when
* the widget is destroyed, it's released. All child windows refer its
* ancestor widget's instance. So, one set of IM contexts is created for
* all windows in a hierarchy. If the children are released after the top
* level window is released, the children still have a valid pointer,
* however, IME doesn't work at that time.
*/
nsRefPtr<nsGtkIMModule> mIMModule;
};
class nsChildWindow : public nsWindow {

View File

@ -65,7 +65,7 @@ ifdef MOZ_ENABLE_GTK2
CFLAGS += $(MOZ_GTK2_CFLAGS)
endif
DEFINES += -D_IMPL_GTKXTBIN_API -DUSE_XIM
DEFINES += -D_IMPL_GTKXTBIN_API
ifeq ($(OS_ARCH), OpenVMS)
DEFINES += -DGENERIC_MOTIF_REDEFINES