зеркало из https://github.com/mozilla/gecko-dev.git
Bug 768742 - Implement Full OS/2 IME support. r=daveryeo
This commit is contained in:
Родитель
80b504c7e1
Коммит
a52517ad5a
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче