Bug 768742 - Implement Full OS/2 IME support. r=daveryeo

This commit is contained in:
KO Myung-Hun 2012-06-20 19:09:05 +09:00
Родитель 80b504c7e1
Коммит a52517ad5a
3 изменённых файлов: 219 добавлений и 7 удалений

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

@ -26,12 +26,11 @@
#include "nsIModule.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
// class definition headers
#include "nsWindow.h"
#include "nsAppShell.h"
#include "nsAppShellSingleton.h"
#include "nsBidiKeyboard.h"
#include "nsWindow.h"
#include "nsDragService.h"
#include "nsIFile.h"
#include "nsFilePicker.h"

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

@ -22,6 +22,7 @@
* - Window Message Handlers
* - Drag & Drop - Target methods
* - Keyboard Handlers
* - IME
* - Event Dispatch
*
*/
@ -42,11 +43,10 @@
#include "nsTHashtable.h"
#include "nsGkAtoms.h"
#include "wdgtos2rc.h"
#include "mozilla/Preferences.h"
#include <os2im.h>
using namespace mozilla;
//=============================================================================
// Macros
//=============================================================================
@ -163,9 +163,16 @@ static PRUint32 sDragStatus = 0;
#ifdef DEBUG_FOCUS
int currentWindowIdentifier = 0;
#endif
// IME stuffs
static HMODULE sIm32Mod = NULLHANDLE;
static APIRET (APIENTRY *spfnImGetInstance)(HWND, PHIMI);
static APIRET (APIENTRY *spfnImReleaseInstance)(HWND, HIMI);
static APIRET (APIENTRY *spfnImGetConversionString)(HIMI, ULONG, PVOID,
PULONG);
static APIRET (APIENTRY *spfnImGetResultString)(HIMI, ULONG, PVOID, PULONG);
static APIRET (APIENTRY *spfnImRequestIME)(HIMI, ULONG, ULONG, ULONG);
//-----------------------------------------------------------------------------
static PRUint32 WMChar2KeyCode(MPARAM mp1, MPARAM mp2);
//=============================================================================
@ -189,7 +196,7 @@ nsWindow::nsWindow() : nsBaseWidget()
mClipWnd = 0;
mCssCursorHPtr = 0;
mThebesSurface = 0;
mIsComposing = false;
if (!gOS2Flags) {
InitGlobals();
}
@ -274,8 +281,48 @@ void nsWindow::InitGlobals()
if (Preferences::GetBool("os2.trackpoint", false)) {
gOS2Flags |= kIsTrackPoint;
}
InitIME();
}
//-----------------------------------------------------------------------------
// Determine whether to use IME
static
void InitIME()
{
if (!getenv("MOZ_IME_OVERTHESPOT")) {
CHAR szName[CCHMAXPATH];
ULONG rc;
rc = DosLoadModule(szName, sizeof(szName), "os2im", &sIm32Mod);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 104, NULL,
(PFN *)&spfnImGetInstance);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 106, NULL,
(PFN *)&spfnImReleaseInstance);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 118, NULL,
(PFN *)&spfnImGetConversionString);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 122, NULL,
(PFN *)&spfnImGetResultString);
if (!rc)
rc = DosQueryProcAddr(sIm32Mod, 131, NULL,
(PFN *)&spfnImRequestIME);
if (rc) {
DosFreeModule(sIm32Mod);
sIm32Mod = NULLHANDLE;
}
}
}
//-----------------------------------------------------------------------------
// Release Module-level variables.
@ -1841,6 +1888,10 @@ MRESULT nsWindow::ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2)
case WM_QUERYCONVERTPOS:
isDone = OnQueryConvertPos(mp1, mresult);
break;
case WM_IMEREQUEST:
isDone = OnImeRequest(mp1, mp2);
break;
}
// If an event handler signalled that we should consume the event,
// return. Otherwise, pass it on to the default wndproc.
@ -2416,6 +2467,156 @@ bool nsWindow::OnQueryConvertPos(MPARAM mp1, MRESULT& mresult)
return true;
}
bool nsWindow::ImeResultString(HIMI himi)
{
PCHAR pBuf;
ULONG ulBufLen;
// Get a buffer size
ulBufLen = 0;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, NULL, &ulBufLen))
return false;
pBuf = new CHAR[ulBufLen];
if (!pBuf)
return false;
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, pBuf,
&ulBufLen)) {
delete pBuf;
return false;
}
if (!mIsComposing) {
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
InitEvent(start);
DispatchWindowEvent(&start);
mIsComposing = true;
}
nsAutoChar16Buffer outBuf;
PRInt32 outBufLen;
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
delete pBuf;
nsTextEvent text(true, NS_TEXT_TEXT, this);
InitEvent(text);
text.theText = outBuf.Elements();
DispatchWindowEvent(&text);
nsCompositionEvent end(true, NS_COMPOSITION_END, this);
InitEvent(end);
end.data = text.theText;
DispatchWindowEvent(&end);
mIsComposing = false;
return true;
}
bool nsWindow::ImeConversionString(HIMI himi)
{
PCHAR pBuf;
ULONG ulBufLen;
// Get a buffer size
ulBufLen = 0;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, NULL,
&ulBufLen))
return false;
pBuf = new CHAR[ulBufLen];
if (!pBuf)
return false;
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, pBuf,
&ulBufLen)) {
delete pBuf;
return false;
}
if (!mIsComposing) {
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
InitEvent(start);
DispatchWindowEvent(&start);
mIsComposing = true;
}
nsAutoChar16Buffer outBuf;
PRInt32 outBufLen;
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
delete pBuf;
nsAutoTArray<nsTextRange, 4> textRanges;
// Is there a conversion string ?
if (outBufLen) {
nsTextRange newRange;
newRange.mStartOffset = 0;
newRange.mEndOffset = outBufLen;
newRange.mRangeType = NS_TEXTRANGE_SELECTEDRAWTEXT;
textRanges.AppendElement(newRange);
newRange.mStartOffset = outBufLen;
newRange.mEndOffset = newRange.mStartOffset;
newRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
textRanges.AppendElement(newRange);
}
nsTextEvent text(true, NS_TEXT_TEXT, this);
InitEvent(text);
text.theText = outBuf.Elements();
text.rangeArray = textRanges.Elements();
text.rangeCount = textRanges.Length();
DispatchWindowEvent(&text);
if (outBufLen) {
nsCompositionEvent update(true, NS_COMPOSITION_UPDATE, this);
InitEvent(update);
update.data = text.theText;
DispatchWindowEvent(&update);
} else { // IME conversion was canceled ?
nsCompositionEvent end(true, NS_COMPOSITION_END, this);
InitEvent(end);
end.data = text.theText;
DispatchWindowEvent(&end);
mIsComposing = false;
}
return true;
}
bool nsWindow::OnImeRequest(MPARAM mp1, MPARAM mp2)
{
HIMI himi;
bool rc;
if (!sIm32Mod)
return false;
if (SHORT1FROMMP(mp1) != IMR_CONVRESULT)
return false;
if (spfnImGetInstance(mWnd, &himi))
return false;
if (LONGFROMMP(mp2) & IMR_RESULT_RESULTSTRING)
rc = ImeResultString(himi);
else if (LONGFROMMP(mp2) & IMR_CONV_CONVERSIONSTRING)
rc = ImeConversionString(himi);
else
rc = true;
spfnImReleaseInstance(mWnd, himi);
return rc;
}
//-----------------------------------------------------------------------------
// Key handler. Specs for the various text messages are really confused;
@ -2840,6 +3041,14 @@ bool nsWindow::DispatchMouseEvent(PRUint32 aEventType, MPARAM mp1, MPARAM mp2,
? nsMouseEvent::eContextMenuKey
: nsMouseEvent::eNormal);
event.button = aButton;
if (aEventType == NS_MOUSE_BUTTON_DOWN && mIsComposing) {
// If IME is composing, let it complete.
HIMI himi;
spfnImGetInstance(mWnd, &himi);
spfnImRequestIME(himi, REQ_CONVERSIONSTRING, CNV_COMPLETE, 0);
spfnImReleaseInstance(mWnd, himi);
}
if (aEventType == NS_MOUSE_ENTER || aEventType == NS_MOUSE_EXIT) {
// Ignore enter/leave msgs forwarded from the frame to FID_CLIENT

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

@ -55,10 +55,10 @@
#define INCL_NLS
#define INCL_GPI
#include <os2.h>
#include <os2im.h>
//-----------------------------------------------------------------------------
// Items that may not be in the OS/2 Toolkit headers
// For WM_MOUSEENTER/LEAVE, mp2 is the other window.
#ifndef WM_MOUSEENTER
#define WM_MOUSEENTER 0x041E
@ -231,6 +231,9 @@ protected:
bool ReleaseIfDragHPS(HPS aHps);
bool OnTranslateAccelerator(PQMSG pQmsg);
bool OnQueryConvertPos(MPARAM mp1, MRESULT& mresult);
bool ImeResultString(HIMI himi);
bool ImeConversionString(HIMI himi);
bool OnImeRequest(MPARAM mp1, MPARAM mp2);
bool DispatchKeyEvent(MPARAM mp1, MPARAM mp2);
void InitEvent(nsGUIEvent& event, nsIntPoint* pt = 0);
bool DispatchWindowEvent(nsGUIEvent* event);
@ -267,6 +270,7 @@ protected:
HPOINTER mCssCursorHPtr; // created by SetCursor(imgIContainer*)
nsCOMPtr<imgIContainer> mCssCursorImg;// saved by SetCursor(imgIContainer*)
nsRefPtr<gfxOS2Surface> mThebesSurface;
bool mIsComposing;
#ifdef DEBUG_FOCUS
int mWindowIdentifier; // a serial number for each new window
#endif