mirror of
https://github.com/akiyosi/goneovim.git
synced 2025-08-05 10:34:36 +02:00
Improve input method
This commit is contained in:
parent
0782ae64ec
commit
eb86edf1ff
7 changed files with 399 additions and 41 deletions
|
@ -2,7 +2,6 @@ package editor
|
|||
|
||||
import (
|
||||
"math"
|
||||
"runtime"
|
||||
|
||||
"github.com/akiyosi/goneovim/util"
|
||||
"github.com/therecipe/qt/core"
|
||||
|
@ -320,10 +319,12 @@ func (c *Cursor) getDrawingPos(x, y, xprime, yprime, deltax, deltay float64) (fl
|
|||
func (c *Cursor) move() {
|
||||
X, Y := c.getDrawingPos(c.x, c.y, c.xprime, c.yprime, c.deltax, c.deltay)
|
||||
|
||||
c.Move2(
|
||||
int(X),
|
||||
int(Y),
|
||||
)
|
||||
iX := int(X)
|
||||
iY := int(Y)
|
||||
|
||||
iX += c.ws.screen.tooltip.cursorVisualPos
|
||||
|
||||
c.Move2(iX, iY)
|
||||
}
|
||||
|
||||
func (c *Cursor) updateFont(targetWin *Window, font *Font) {
|
||||
|
@ -670,9 +671,7 @@ func (c *Cursor) redraw() {
|
|||
c.paint()
|
||||
|
||||
// Fix #119: Wrong candidate window position when using ibus
|
||||
if runtime.GOOS == "linux" {
|
||||
gui.QGuiApplication_InputMethod().Update(core.Qt__ImCursorRectangle)
|
||||
}
|
||||
editor.app.InputMethod().Update(core.Qt__ImCursorRectangle)
|
||||
}
|
||||
|
||||
// paint() is to request update cursor widget.
|
||||
|
|
82
editor/handleime.cpp
Normal file
82
editor/handleime.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include "handleime.h"
|
||||
|
||||
#include <QInputMethodEvent>
|
||||
|
||||
|
||||
int selectionLengthInPreeditStrOnDarwin(void* ptr, int cursorpos) {
|
||||
|
||||
QInputMethodEvent* event = static_cast<QInputMethodEvent*>(ptr);
|
||||
|
||||
QList<QInputMethodEvent::Attribute> attributes;
|
||||
attributes = {};
|
||||
attributes = event->attributes();
|
||||
int ret = attributes.size();
|
||||
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
|
||||
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
|
||||
|
||||
if (a.type == QInputMethodEvent::TextFormat) {
|
||||
|
||||
if (a.start + a.length == cursorpos) {
|
||||
ret = a.length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int selectionLengthInPreeditStr(void* ptr, int cursorpos) {
|
||||
|
||||
QInputMethodEvent* event = static_cast<QInputMethodEvent*>(ptr);
|
||||
|
||||
QList<QInputMethodEvent::Attribute> attributes;
|
||||
attributes = {};
|
||||
attributes = event->attributes();
|
||||
int ret = attributes.size();
|
||||
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
|
||||
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
|
||||
|
||||
if (a.type == QInputMethodEvent::TextFormat) {
|
||||
|
||||
if (a.start == cursorpos) {
|
||||
ret = a.length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cursorPosInPreeditStr(void* ptr) {
|
||||
|
||||
QInputMethodEvent* event = static_cast<QInputMethodEvent*>(ptr);
|
||||
|
||||
|
||||
QList<QInputMethodEvent::Attribute> attributes;
|
||||
attributes = {};
|
||||
attributes = event->attributes();
|
||||
int ret = attributes.size();
|
||||
|
||||
for (int i = 0; i < attributes.size(); i++) {
|
||||
|
||||
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
|
||||
|
||||
if (a.type == QInputMethodEvent::Cursor) {
|
||||
|
||||
ret = a.start;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
22
editor/handleime.go
Normal file
22
editor/handleime.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package editor
|
||||
|
||||
//#include <stdint.h>
|
||||
//#include "handleime.h"
|
||||
import "C"
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/therecipe/qt/gui"
|
||||
)
|
||||
|
||||
func selectionPosInPreeditStr(event *gui.QInputMethodEvent) (cursorPos, selectionLength int) {
|
||||
cursorPos = int(C.cursorPosInPreeditStr(event.Pointer()))
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
selectionLength = int(C.selectionLengthInPreeditStrOnDarwin(event.Pointer(), C.int(cursorPos)))
|
||||
} else {
|
||||
selectionLength = int(C.selectionLengthInPreeditStr(event.Pointer(), C.int(cursorPos)))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
21
editor/handleime.h
Normal file
21
editor/handleime.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef GO_HANDLEIME_H
|
||||
#define GO_HANDLEIME_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int selectionLengthInPreeditStr(void* ptr, int cursorpos);
|
||||
int selectionLengthInPreeditStrOnDarwin(void* ptr, int cursorpos);
|
||||
int cursorPosInPreeditStr(void* ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,6 +1,10 @@
|
|||
package editor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
|
||||
"github.com/therecipe/qt/core"
|
||||
"github.com/therecipe/qt/gui"
|
||||
)
|
||||
|
@ -8,6 +12,11 @@ import (
|
|||
// IMETooltip is the tooltip for Input Method Editor
|
||||
type IMETooltip struct {
|
||||
Tooltip
|
||||
|
||||
cursorPos int
|
||||
selectionLength int
|
||||
|
||||
cursorVisualPos int
|
||||
}
|
||||
|
||||
func (i *IMETooltip) setQpainterFont(p *gui.QPainter) {
|
||||
|
@ -17,12 +26,22 @@ func (i *IMETooltip) setQpainterFont(p *gui.QPainter) {
|
|||
if i.font.fontNew == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// if i.s.ws.palette.widget.IsVisible() {
|
||||
// p.SetFont(
|
||||
// gui.NewQFont2(editor.extFontFamily, editor.extFontSize, 1, false),
|
||||
// )
|
||||
// } else {
|
||||
// p.SetFont(i.font.fontNew)
|
||||
// }
|
||||
p.SetFont(i.getFont())
|
||||
}
|
||||
|
||||
func (i *IMETooltip) getFont() *gui.QFont {
|
||||
if i.s.ws.palette.widget.IsVisible() {
|
||||
p.SetFont(
|
||||
gui.NewQFont2(editor.extFontFamily, editor.extFontSize, 1, false),
|
||||
)
|
||||
return gui.NewQFont2(editor.extFontFamily, editor.extFontSize, 1, false)
|
||||
} else {
|
||||
p.SetFont(i.font.fontNew)
|
||||
return i.font.fontNew
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +75,159 @@ func (i *IMETooltip) getNthWidthAndShift(n int) (float64, int) {
|
|||
|
||||
func (i *IMETooltip) paint(event *gui.QPaintEvent) {
|
||||
p := gui.NewQPainter2(i)
|
||||
|
||||
i.drawBackground(p, i.setQpainterFont, i.getNthWidthAndShift)
|
||||
i.drawForeground(p, i.setQpainterFont, i.getNthWidthAndShift)
|
||||
i.drawPreeditString(p, i.getNthWidthAndShift)
|
||||
|
||||
p.DestroyQPainter()
|
||||
}
|
||||
|
||||
func (i *IMETooltip) drawBackground(p *gui.QPainter, f func(*gui.QPainter), g func(int) (float64, int)) {
|
||||
// f(p)
|
||||
|
||||
// p.SetPen2(i.s.ws.foreground.QColor())
|
||||
|
||||
var bgColor *RGBA
|
||||
if i.s.ws.screenbg == "dark" {
|
||||
bgColor = warpColor(editor.colors.bg, -30)
|
||||
} else {
|
||||
bgColor = warpColor(editor.colors.bg, 30)
|
||||
}
|
||||
|
||||
var height, lineHeight int
|
||||
if i.s.ws.palette.widget.IsVisible() {
|
||||
height = int(
|
||||
math.Ceil(
|
||||
gui.NewQFontMetricsF(
|
||||
gui.NewQFont2(editor.extFontFamily, editor.extFontSize, 1, false),
|
||||
).Height(),
|
||||
),
|
||||
)
|
||||
lineHeight = height
|
||||
} else {
|
||||
height = i.s.tooltip.font.height
|
||||
lineHeight = i.s.tooltip.font.lineHeight
|
||||
}
|
||||
|
||||
if i.text != "" {
|
||||
r := []rune(i.text)
|
||||
var x, rectWidth float64
|
||||
for k := 0; k < len(r); k++ {
|
||||
|
||||
width, _ := g(k)
|
||||
x += width
|
||||
y := float64(lineHeight-height) / 2
|
||||
|
||||
nextWidth, _ := g(k + 1)
|
||||
rectWidth = nextWidth
|
||||
|
||||
height := float64(height) * 1.1
|
||||
if height > float64(lineHeight) {
|
||||
height = float64(lineHeight)
|
||||
}
|
||||
|
||||
// draw background
|
||||
p.FillRect4(
|
||||
core.NewQRectF4(
|
||||
x,
|
||||
y,
|
||||
rectWidth,
|
||||
height,
|
||||
),
|
||||
bgColor.QColor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *IMETooltip) drawPreeditString(p *gui.QPainter, g func(int) (float64, int)) {
|
||||
|
||||
var fgColor *RGBA
|
||||
if i.s.ws.screenbg == "dark" {
|
||||
fgColor = warpColor(editor.colors.fg, 30)
|
||||
} else {
|
||||
fgColor = warpColor(editor.colors.fg, -30)
|
||||
}
|
||||
|
||||
p.SetPen2(fgColor.QColor())
|
||||
|
||||
length := i.s.tooltip.selectionLength
|
||||
start := i.s.tooltip.cursorPos
|
||||
if runtime.GOOS == "darwin" {
|
||||
start = i.s.tooltip.cursorPos - length
|
||||
}
|
||||
|
||||
var height, lineHeight int
|
||||
if i.s.ws.palette.widget.IsVisible() {
|
||||
height = int(
|
||||
math.Ceil(
|
||||
gui.NewQFontMetricsF(
|
||||
gui.NewQFont2(editor.extFontFamily, editor.extFontSize, 1, false),
|
||||
).Height(),
|
||||
),
|
||||
)
|
||||
lineHeight = height
|
||||
} else {
|
||||
height = i.s.tooltip.font.height
|
||||
lineHeight = i.s.tooltip.font.lineHeight
|
||||
}
|
||||
|
||||
if i.text != "" {
|
||||
r := []rune(i.text)
|
||||
|
||||
var x, rectWidth float64
|
||||
for k := 0; k < start+length; k++ {
|
||||
if k >= len(r) {
|
||||
break
|
||||
}
|
||||
|
||||
width, shift := g(k)
|
||||
x += width
|
||||
|
||||
if k < start {
|
||||
continue
|
||||
}
|
||||
|
||||
y := float64(lineHeight-height) / 2
|
||||
|
||||
nextWidth, _ := g(k + 1)
|
||||
rectWidth = nextWidth
|
||||
|
||||
height := float64(height) * 1.1
|
||||
if height > float64(lineHeight) {
|
||||
height = float64(lineHeight)
|
||||
}
|
||||
|
||||
var underlinePos float64 = 1
|
||||
if i.s.ws.palette.widget.IsVisible() {
|
||||
underlinePos = 2
|
||||
}
|
||||
|
||||
// draw underline
|
||||
p.FillRect4(
|
||||
core.NewQRectF4(
|
||||
x,
|
||||
y+height-underlinePos,
|
||||
rectWidth,
|
||||
underlinePos,
|
||||
),
|
||||
fgColor.QColor(),
|
||||
)
|
||||
|
||||
// draw preedit string
|
||||
p.DrawText(
|
||||
core.NewQPointF3(
|
||||
float64(x),
|
||||
float64(shift),
|
||||
),
|
||||
string(r[k]),
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *IMETooltip) pos() (int, int, int, int) {
|
||||
var x, y, candX, candY int
|
||||
ws := i.s.ws
|
||||
|
@ -71,19 +238,21 @@ func (i *IMETooltip) pos() (int, int, int, int) {
|
|||
if ws.palette == nil {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
|
||||
win, ok := s.getWindow(s.ws.cursor.gridid)
|
||||
if !ok {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
font := win.getFont()
|
||||
|
||||
if ws.palette.widget.IsVisible() {
|
||||
// font := gui.NewQFont2(editor.extFontFamily, editor.extFontSize, 1, false)
|
||||
// i.SetFont(font)
|
||||
x = ws.palette.cursorX + ws.palette.patternPadding
|
||||
y = ws.palette.patternPadding + ws.palette.padding + 1
|
||||
candX = x + ws.palette.widget.Pos().X()
|
||||
y = ws.palette.patternPadding + ws.palette.padding
|
||||
candY = y + ws.palette.widget.Pos().Y()
|
||||
} else {
|
||||
win, ok := s.getWindow(s.ws.cursor.gridid)
|
||||
if !ok {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
font := win.getFont()
|
||||
i.setFont(font)
|
||||
row := s.cursor[0]
|
||||
col := s.cursor[1]
|
||||
|
@ -106,6 +275,15 @@ func (i *IMETooltip) pos() (int, int, int, int) {
|
|||
}
|
||||
candY = (row+posy)*font.lineHeight + tablineMarginTop + tablineHeight + tablineMarginBottom
|
||||
}
|
||||
|
||||
candX = candX + i.cursorVisualPos
|
||||
editor.putLog(
|
||||
fmt.Sprintf(
|
||||
"IME preeditstr:: cursor pos in preeditstr: %d",
|
||||
int(float64(i.cursorVisualPos)/font.cellwidth),
|
||||
),
|
||||
)
|
||||
|
||||
return x, y, candX, candY
|
||||
}
|
||||
|
||||
|
@ -133,15 +311,42 @@ func (i *IMETooltip) show() {
|
|||
i.SetParent(i.s.ws.palette.widget)
|
||||
}
|
||||
|
||||
i.SetAutoFillBackground(true)
|
||||
p := gui.NewQPalette()
|
||||
p.SetColor2(gui.QPalette__Background, i.s.ws.background.QColor())
|
||||
i.SetPalette(p)
|
||||
// i.SetAutoFillBackground(true)
|
||||
// p := gui.NewQPalette()
|
||||
// p.SetColor2(gui.QPalette__Background, i.s.ws.background.QColor())
|
||||
// i.SetPalette(p)
|
||||
|
||||
i.Show()
|
||||
i.Raise()
|
||||
}
|
||||
|
||||
func (i *IMETooltip) updateVirtualCursorPos() {
|
||||
g := i.getNthWidthAndShift
|
||||
|
||||
length := i.s.tooltip.selectionLength
|
||||
start := i.s.tooltip.cursorPos
|
||||
|
||||
var x float64
|
||||
if i.text != "" {
|
||||
r := []rune(i.text)
|
||||
|
||||
for k := 0; k < start+length; k++ {
|
||||
if k > len(r) {
|
||||
break
|
||||
}
|
||||
|
||||
width, _ := g(k)
|
||||
x += width
|
||||
|
||||
if k >= start {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i.cursorVisualPos = int(x)
|
||||
}
|
||||
|
||||
func (i *IMETooltip) updateText(text string) {
|
||||
if i.font == nil {
|
||||
return
|
||||
|
|
|
@ -65,6 +65,7 @@ func newScreen() *Screen {
|
|||
func (s *Screen) initInputMethodWidget() {
|
||||
tooltip := NewIMETooltip(s.widget, 0)
|
||||
tooltip.SetVisible(false)
|
||||
tooltip.SetAttribute(core.Qt__WA_OpaquePaintEvent, true)
|
||||
tooltip.ConnectPaintEvent(tooltip.paint)
|
||||
tooltip.s = s
|
||||
s.tooltip = tooltip
|
||||
|
@ -1270,6 +1271,22 @@ func (s *Screen) update() {
|
|||
})
|
||||
}
|
||||
|
||||
func (s *Screen) refresh() {
|
||||
s.windows.Range(func(grid, winITF interface{}) bool {
|
||||
win := winITF.(*Window)
|
||||
if win != nil {
|
||||
// Fill entire background if background color changed
|
||||
if !win.background.equals(s.ws.background) {
|
||||
win.background = s.ws.background.copy()
|
||||
win.fill()
|
||||
}
|
||||
win.Update()
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Screen) runeTextWidth(font *Font, text string) float64 {
|
||||
cjk := 0
|
||||
ascii := 0
|
||||
|
|
|
@ -174,13 +174,11 @@ func newWorkspace(path string) (*Workspace, error) {
|
|||
}
|
||||
|
||||
// palette
|
||||
if editor.config.Editor.ExtCmdline {
|
||||
w.palette = initPalette()
|
||||
w.palette.ws = w
|
||||
w.palette.widget.SetParent(w.widget)
|
||||
w.palette.setColor()
|
||||
w.palette.hide()
|
||||
}
|
||||
w.palette = initPalette()
|
||||
w.palette.ws = w
|
||||
w.palette.widget.SetParent(w.widget)
|
||||
w.palette.setColor()
|
||||
w.palette.hide()
|
||||
|
||||
// popupmenu
|
||||
if editor.config.Editor.ExtPopupmenu {
|
||||
|
@ -2216,8 +2214,6 @@ func (w *Workspace) handleRPCGui(updates []interface{}) {
|
|||
}
|
||||
win.doGetSnapshot = true
|
||||
}
|
||||
// w.maxLineDelta = util.ReflectToInt(updates[1]) - w.maxLine
|
||||
// w.maxLine = util.ReflectToInt(updates[1])
|
||||
|
||||
default:
|
||||
fmt.Println("unhandled Gui event", event)
|
||||
|
@ -2742,24 +2738,48 @@ func (w *Workspace) setFileType(args []interface{}) {
|
|||
|
||||
// InputMethodEvent is
|
||||
func (w *Workspace) InputMethodEvent(event *gui.QInputMethodEvent) {
|
||||
w.screen.tooltip.cursorPos, w.screen.tooltip.selectionLength = selectionPosInPreeditStr(event)
|
||||
|
||||
if event.CommitString() != "" {
|
||||
w.screen.tooltip.cursorVisualPos = 0
|
||||
w.nvim.Input(event.CommitString())
|
||||
w.screen.tooltip.Hide()
|
||||
} else {
|
||||
preeditString := event.PreeditString()
|
||||
|
||||
if preeditString == "" {
|
||||
w.screen.tooltip.Hide()
|
||||
w.cursor.update()
|
||||
w.screen.refresh()
|
||||
} else {
|
||||
w.screen.tooltip.updateText(preeditString)
|
||||
w.screen.tooltip.update()
|
||||
w.screen.tooltip.show()
|
||||
|
||||
}
|
||||
|
||||
w.screen.tooltip.updateVirtualCursorPos()
|
||||
}
|
||||
|
||||
w.cursor.update()
|
||||
|
||||
editor.putLog(
|
||||
fmt.Sprintf(
|
||||
"QInputMethodEvent:: IME preeditstr: cursorpos: %d, selectionLength: %d, cursorVisualPos: %d",
|
||||
w.screen.tooltip.cursorPos,
|
||||
w.screen.tooltip.selectionLength,
|
||||
w.screen.tooltip.cursorVisualPos,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// InputMethodQuery is
|
||||
func (w *Workspace) InputMethodQuery(query core.Qt__InputMethodQuery) *core.QVariant {
|
||||
editor.putLog(
|
||||
fmt.Sprintf(
|
||||
"InputMethodQuery:: query: %d", query,
|
||||
),
|
||||
)
|
||||
|
||||
if query == core.Qt__ImMicroFocus || query == core.Qt__ImCursorRectangle {
|
||||
x, y, candX, candY := w.screen.tooltip.pos()
|
||||
w.screen.tooltip.move(x, y)
|
||||
|
@ -2777,17 +2797,9 @@ func (w *Workspace) InputMethodQuery(query core.Qt__InputMethodQuery) *core.QVar
|
|||
}
|
||||
imrect.SetRect(candX, candY+res+5, 1, w.font.lineHeight)
|
||||
|
||||
if w.palette != nil {
|
||||
if w.palette.widget.IsVisible() {
|
||||
// w.cursor.x = float64(x + w.screen.tooltip.Width())
|
||||
// w.cursor.y = float64(w.palette.patternPadding + w.cursor.shift)
|
||||
// w.cursor.Update()
|
||||
w.cursor.Hide()
|
||||
}
|
||||
}
|
||||
|
||||
return core.NewQVariant31(imrect)
|
||||
}
|
||||
|
||||
return core.NewQVariant()
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue