mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 11:18:54 +01:00
42209606b1
Closes #2918
165 lines
4.7 KiB
Go
165 lines
4.7 KiB
Go
// Copyright 2024 The Ebitengine Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package textinput
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
const (
|
|
_ATTR_TARGET_CONVERTED = 0x01
|
|
_ATTR_TARGET_NOTCONVERTED = 0x03
|
|
|
|
_CFS_CANDIDATEPOS = 0x0040
|
|
|
|
_GCS_COMPATTR = 0x0010
|
|
_GCS_COMPCLAUSE = 0x0020
|
|
_GCS_COMPSTR = 0x0008
|
|
_GCS_RESULTSTR = 0x0800
|
|
|
|
_GWL_WNDPROC = -4
|
|
|
|
_ISC_SHOWUICOMPOSITIONWINDOW = 0x80000000
|
|
|
|
_UNICODE_NOCHAR = 0xffff
|
|
|
|
_WM_CHAR = 0x0102
|
|
_WM_IME_COMPOSITION = 0x010F
|
|
_WM_IME_SETCONTEXT = 0x0281
|
|
_WM_SYSCHAR = 0x0106
|
|
_WM_UNICHAR = 0x0109
|
|
)
|
|
|
|
type (
|
|
_HIMC uintptr
|
|
)
|
|
|
|
type _CANDIDATEFORM struct {
|
|
dwIndex uint32
|
|
dwStyle uint32
|
|
ptCurrentPos _POINT
|
|
rcArea _RECT
|
|
}
|
|
|
|
type _POINT struct {
|
|
x int32
|
|
y int32
|
|
}
|
|
|
|
type _RECT struct {
|
|
left int32
|
|
top int32
|
|
right int32
|
|
bottom int32
|
|
}
|
|
|
|
var (
|
|
imm32 = windows.NewLazySystemDLL("imm32.dll")
|
|
user32 = windows.NewLazySystemDLL("user32.dll")
|
|
|
|
procImmAssociateContext = imm32.NewProc("ImmAssociateContext")
|
|
procImmGetCompositionStringW = imm32.NewProc("ImmGetCompositionStringW")
|
|
procImmGetContext = imm32.NewProc("ImmGetContext")
|
|
procImmReleaseContext = imm32.NewProc("ImmReleaseContext")
|
|
procImmSetCandidateWindow = imm32.NewProc("ImmSetCandidateWindow")
|
|
|
|
procCallWindowProcW = user32.NewProc("CallWindowProcW")
|
|
procGetActiveWindow = user32.NewProc("GetActiveWindow")
|
|
procSetWindowLongW = user32.NewProc("SetWindowLongW") // 32-Bit Windows version.
|
|
procSetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW") // 64-Bit Windows version.
|
|
)
|
|
|
|
func _CallWindowProcW(lpPrevWndFunc uintptr, hWnd uintptr, msg uint32, wParam, lParam uintptr) uintptr {
|
|
r, _, _ := procCallWindowProcW.Call(lpPrevWndFunc, hWnd, uintptr(msg), wParam, lParam)
|
|
return r
|
|
}
|
|
|
|
func _GetActiveWindow() windows.HWND {
|
|
r, _, _ := procGetActiveWindow.Call()
|
|
return windows.HWND(r)
|
|
}
|
|
|
|
func _ImmAssociateContext(hwnd windows.HWND, hIMC uintptr) (uintptr, error) {
|
|
r, _, e := procImmAssociateContext.Call(uintptr(hwnd), hIMC)
|
|
if e != nil && !errors.Is(e, windows.ERROR_SUCCESS) {
|
|
return 0, fmt.Errorf("textinput: ImmAssociateContext failed: error code: %w", e)
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func _ImmGetCompositionStringW(unnamedParam1 _HIMC, unnamedParam2 uint32, lpBuf unsafe.Pointer, dwBufLen uint32) (uint32, error) {
|
|
r, _, e := procImmGetCompositionStringW.Call(uintptr(unnamedParam1), uintptr(unnamedParam2), uintptr(lpBuf), uintptr(dwBufLen))
|
|
runtime.KeepAlive(lpBuf)
|
|
if r < 0 {
|
|
return 0, fmt.Errorf("textinput: ImmGetCompositionStringW failed: %d", r)
|
|
}
|
|
if e != nil && e != windows.ERROR_SUCCESS {
|
|
return 0, fmt.Errorf("textinput: ImmGetCompositionStringW failed: %w", e)
|
|
}
|
|
return uint32(r), nil
|
|
}
|
|
|
|
func _ImmGetContext(unnamedParam1 windows.HWND) _HIMC {
|
|
r, _, _ := procImmGetContext.Call(uintptr(unnamedParam1))
|
|
return _HIMC(r)
|
|
}
|
|
|
|
func _ImmReleaseContext(unnamedParam1 windows.HWND, unnamedParam2 _HIMC) error {
|
|
r, _, e := procImmReleaseContext.Call(uintptr(unnamedParam1), uintptr(unnamedParam2))
|
|
if int32(r) == 0 {
|
|
if e != nil && e != windows.ERROR_SUCCESS {
|
|
return fmt.Errorf("textinput: ImmReleaseContext failed: %w", e)
|
|
}
|
|
return fmt.Errorf("textinput: ImmReleaseContext returned 0")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func _ImmSetCandidateWindow(unnamedParam1 _HIMC, lpCandidate *_CANDIDATEFORM) error {
|
|
r, _, e := procImmSetCandidateWindow.Call(uintptr(unnamedParam1), uintptr(unsafe.Pointer(lpCandidate)))
|
|
runtime.KeepAlive(lpCandidate)
|
|
if int32(r) == 0 {
|
|
if e != nil && e != windows.ERROR_SUCCESS {
|
|
return fmt.Errorf("textinput: ImmSetCandidateWindow failed: %w", e)
|
|
}
|
|
return fmt.Errorf("textinput: ImmSetCandidateWindow returned 0")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func _SetWindowLongPtrW(hWnd windows.HWND, nIndex int32, dwNewLong uintptr) (uintptr, error) {
|
|
var p *windows.LazyProc
|
|
if procSetWindowLongPtrW.Find() == nil {
|
|
// 64-Bit Windows.
|
|
p = procSetWindowLongPtrW
|
|
} else {
|
|
// 32-Bit Windows.
|
|
p = procSetWindowLongW
|
|
}
|
|
h, _, e := p.Call(uintptr(hWnd), uintptr(nIndex), dwNewLong)
|
|
if h == 0 {
|
|
if e != nil && e != windows.ERROR_SUCCESS {
|
|
return 0, fmt.Errorf("textinput: SetWindowLongPtrW failed: %w", e)
|
|
}
|
|
return 0, fmt.Errorf("textinput: SetWindowLongPtrW returned 0")
|
|
}
|
|
return h, nil
|
|
}
|