Skip to content

Commit 732c4ec

Browse files
committed
Merge branch 'main' of github.com:gioui/gio into HEAD
2 parents 67efd4a + 72a72a2 commit 732c4ec

38 files changed

+698
-2854
lines changed

.builds/apple.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,4 @@ tasks:
7171
CC=$APPLE_TOOLCHAIN_ROOT/tools/clang-macos GOOS=darwin CGO_ENABLED=1 go build ./...
7272
- test_ios: |
7373
cd gio
74-
CC=$APPLE_TOOLCHAIN_ROOT/tools/clang-ios GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build -tags ios ./...
74+
CGO_CFLAGS=-Wno-deprecated-module-dot-map CC=$APPLE_TOOLCHAIN_ROOT/tools/clang-ios GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build -tags ios ./...

.builds/freebsd.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# SPDX-License-Identifier: Unlicense OR MIT
2-
image: freebsd/13.x
2+
image: freebsd/latest
33
packages:
44
- libX11
55
- libxkbcommon

app/GioView.java

+4
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ private void setNavigationColor(int color, int luminance) {
259259
}
260260

261261
private void setHighRefreshRate() {
262+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
263+
return;
264+
}
265+
262266
Context context = getContext();
263267
Display display = context.getDisplay();
264268
Display.Mode[] supportedModes = display.getSupportedModes();

app/ime.go

+27
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// SPDX-License-Identifier: Unlicense OR MIT
2+
23
package app
34

45
import (
56
"unicode"
67
"unicode/utf16"
8+
"unicode/utf8"
79

810
"gioui.org/io/input"
911
"gioui.org/io/key"
@@ -116,3 +118,28 @@ func (e *editorState) RunesIndex(chars int) int {
116118
// Assume runes after snippets are one UTF-16 character each.
117119
return runes + chars
118120
}
121+
122+
// areSnippetsConsistent reports whether the content of the old snippet is
123+
// consistent with the content of the new.
124+
func areSnippetsConsistent(old, new key.Snippet) bool {
125+
// Compute the overlapping range.
126+
r := old.Range
127+
r.Start = max(r.Start, new.Start)
128+
r.End = max(r.End, r.Start)
129+
r.End = min(r.End, new.End)
130+
return snippetSubstring(old, r) == snippetSubstring(new, r)
131+
}
132+
133+
func snippetSubstring(s key.Snippet, r key.Range) string {
134+
for r.Start > s.Start && r.Start < s.End {
135+
_, n := utf8.DecodeRuneInString(s.Text)
136+
s.Text = s.Text[n:]
137+
s.Start++
138+
}
139+
for r.End < s.End && r.End > s.Start {
140+
_, n := utf8.DecodeLastRuneInString(s.Text)
141+
s.Text = s.Text[:len(s.Text)-n]
142+
s.End--
143+
}
144+
return s.Text
145+
}

app/log_windows.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ package app
44

55
import (
66
"log"
7-
"syscall"
87
"unsafe"
8+
9+
syscall "golang.org/x/sys/windows"
910
)
1011

1112
type logger struct{}
1213

1314
var (
14-
kernel32 = syscall.NewLazyDLL("kernel32")
15+
kernel32 = syscall.NewLazySystemDLL("kernel32")
1516
outputDebugStringW = kernel32.NewProc("OutputDebugStringW")
1617
debugView *logger
1718
)

app/metal_darwin.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func newMtlContext(w *window) (*mtlContext, error) {
9696
return nil, errors.New("metal: CAMetalLayer construction failed")
9797
}
9898
queue := C.newCommandQueue(dev)
99-
if layer == 0 {
99+
if queue == 0 {
100100
C.CFRelease(dev)
101101
C.CFRelease(layer)
102102
return nil, errors.New("metal: [MTLDevice newCommandQueue] failed")

app/os.go

-2
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,6 @@ type driver interface {
201201
Configure([]Option)
202202
// SetCursor updates the current cursor to name.
203203
SetCursor(cursor pointer.Cursor)
204-
// Wakeup wakes up the event loop and sends a WakeupEvent.
205-
// Wakeup()
206204
// Perform actions on the window.
207205
Perform(system.Action)
208206
// EditorStateChanged notifies the driver that the editor state changed.

app/os_android.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -575,10 +575,7 @@ func Java_org_gioui_GioView_onFrameCallback(env *C.JNIEnv, class C.jclass, view
575575
if !exist {
576576
return
577577
}
578-
if w.visible && w.animating {
579-
w.draw(env, false)
580-
callVoidMethod(env, w.view, gioView.postFrameCallback)
581-
}
578+
w.draw(env, false)
582579
}
583580

584581
//export Java_org_gioui_GioView_onBack
@@ -882,6 +879,9 @@ func (w *window) draw(env *C.JNIEnv, sync bool) {
882879
},
883880
Sync: sync,
884881
})
882+
if w.animating {
883+
callVoidMethod(env, w.view, gioView.postFrameCallback)
884+
}
885885
a11yActive, err := callBooleanMethod(env, w.view, gioView.isA11yActive)
886886
if err != nil {
887887
panic(err)

app/os_macos.go

+134-14
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,21 @@ static void invalidateCharacterCoordinates(CFTypeRef viewRef) {
312312
}
313313
}
314314
}
315+
316+
static void interpretKeyEvents(CFTypeRef viewRef, CFTypeRef eventRef) {
317+
@autoreleasepool {
318+
NSView *view = (__bridge NSView *)viewRef;
319+
NSEvent *event = (__bridge NSEvent *)eventRef;
320+
[view interpretKeyEvents:[NSArray arrayWithObject:event]];
321+
}
322+
}
323+
324+
static int isMiniaturized(CFTypeRef windowRef) {
325+
@autoreleasepool {
326+
NSWindow *window = (__bridge NSWindow *)windowRef;
327+
return window.miniaturized ? 1 : 0;
328+
}
329+
}
315330
*/
316331
import "C"
317332

@@ -340,9 +355,20 @@ type window struct {
340355
cursor pointer.Cursor
341356
pointerBtns pointer.Buttons
342357
loop *eventLoop
358+
lastMods C.NSUInteger
343359

344360
scale float32
345361
config Config
362+
363+
keysDown map[key.Name]struct{}
364+
// cmdKeys is for storing the current key event while
365+
// waiting for a doCommandBySelector.
366+
cmdKeys cmdKeys
367+
}
368+
369+
type cmdKeys struct {
370+
eventStr string
371+
eventMods key.Modifiers
346372
}
347373

348374
// launched is closed when applicationDidFinishLaunching is called.
@@ -511,7 +537,7 @@ func (w *window) SetCursor(cursor pointer.Cursor) {
511537
}
512538

513539
func (w *window) EditorStateChanged(old, new editorState) {
514-
if old.Selection.Range != new.Selection.Range || old.Snippet != new.Snippet {
540+
if old.Selection.Range != new.Selection.Range || !areSnippetsConsistent(old.Snippet, new.Snippet) {
515541
C.discardMarkedText(w.view)
516542
w.w.SetComposingRegion(key.Range{Start: -1, End: -1})
517543
}
@@ -527,7 +553,7 @@ func (w *window) SetInputHint(_ key.InputHint) {}
527553
func (w *window) SetAnimating(anim bool) {
528554
w.anim = anim
529555
window := C.windowForView(w.view)
530-
if w.anim && window != 0 {
556+
if w.anim && window != 0 && C.isMiniaturized(window) == 0 {
531557
w.displayLink.Start()
532558
} else {
533559
w.displayLink.Stop()
@@ -545,23 +571,92 @@ func (w *window) runOnMain(f func()) {
545571
}
546572

547573
//export gio_onKeys
548-
func gio_onKeys(h C.uintptr_t, cstr C.CFTypeRef, ti C.double, mods C.NSUInteger, keyDown C.bool) {
574+
func gio_onKeys(h C.uintptr_t, event C.CFTypeRef, cstr C.CFTypeRef, ti C.double, mods C.NSUInteger, keyDown C.bool) {
575+
w := windowFor(h)
576+
if w.keysDown == nil {
577+
w.keysDown = make(map[key.Name]struct{})
578+
}
549579
str := nsstringToString(cstr)
550580
kmods := convertMods(mods)
551581
ks := key.Release
552582
if keyDown {
553583
ks = key.Press
584+
w.cmdKeys.eventStr = str
585+
w.cmdKeys.eventMods = kmods
586+
C.interpretKeyEvents(w.view, event)
554587
}
555-
w := windowFor(h)
556588
for _, k := range str {
557589
if n, ok := convertKey(k); ok {
558-
w.ProcessEvent(key.Event{
590+
ke := key.Event{
559591
Name: n,
560592
Modifiers: kmods,
561593
State: ks,
594+
}
595+
if keyDown {
596+
w.keysDown[ke.Name] = struct{}{}
597+
if _, isCmd := convertCommandKey(k); isCmd || kmods.Contain(key.ModCommand) {
598+
// doCommandBySelector already processed the event.
599+
return
600+
}
601+
} else {
602+
if _, pressed := w.keysDown[n]; !pressed {
603+
continue
604+
}
605+
delete(w.keysDown, n)
606+
}
607+
w.ProcessEvent(ke)
608+
}
609+
}
610+
}
611+
612+
//export gio_onCommandBySelector
613+
func gio_onCommandBySelector(h C.uintptr_t) C.bool {
614+
w := windowFor(h)
615+
ev := w.cmdKeys
616+
w.cmdKeys = cmdKeys{}
617+
handled := false
618+
for _, k := range ev.eventStr {
619+
n, ok := convertCommandKey(k)
620+
if !ok && ev.eventMods.Contain(key.ModCommand) {
621+
n, ok = convertKey(k)
622+
}
623+
if !ok {
624+
continue
625+
}
626+
ke := key.Event{
627+
Name: n,
628+
Modifiers: ev.eventMods,
629+
State: key.Press,
630+
}
631+
handled = w.processEvent(ke) || handled
632+
}
633+
return C.bool(handled)
634+
}
635+
636+
//export gio_onFlagsChanged
637+
func gio_onFlagsChanged(h C.uintptr_t, curMods C.NSUInteger) {
638+
w := windowFor(h)
639+
640+
mods := []C.NSUInteger{C.NSControlKeyMask, C.NSAlternateKeyMask, C.NSShiftKeyMask, C.NSCommandKeyMask}
641+
keys := []key.Name{key.NameCtrl, key.NameAlt, key.NameShift, key.NameCommand}
642+
643+
for i, mod := range mods {
644+
wasPressed := w.lastMods&mod != 0
645+
isPressed := curMods&mod != 0
646+
647+
if wasPressed != isPressed {
648+
st := key.Release
649+
if isPressed {
650+
st = key.Press
651+
}
652+
w.ProcessEvent(key.Event{
653+
Name: keys[i],
654+
State: st,
562655
})
563656
}
564657
}
658+
659+
w.lastMods = curMods
565660
}
566661

567662
//export gio_onText
@@ -754,6 +849,15 @@ func gio_substringForProposedRange(h C.uintptr_t, crng C.NSRange, actual C.NSRan
754849
//export gio_insertText
755850
func gio_insertText(h C.uintptr_t, cstr C.CFTypeRef, crng C.NSRange) {
756851
w := windowFor(h)
852+
str := nsstringToString(cstr)
853+
// macOS IME in some cases calls insertText for command keys such as backspace
854+
// instead of doCommandBySelector.
855+
for _, r := range str {
856+
if _, ok := convertCommandKey(r); ok {
857+
w.w.SetComposingRegion(key.Range{Start: -1, End: -1})
858+
return
859+
}
860+
}
757861
state := w.w.EditorState()
758862
rng := state.compose
759863
if rng.Start == -1 {
@@ -765,7 +869,6 @@ func gio_insertText(h C.uintptr_t, cstr C.CFTypeRef, crng C.NSRange) {
765869
End: state.RunesIndex(int(crng.location + crng.length)),
766870
}
767871
}
768-
str := nsstringToString(cstr)
769872
w.w.EditorReplace(rng, str)
770873
w.w.SetComposingRegion(key.Range{Start: -1, End: -1})
771874
start := rng.Start
@@ -834,8 +937,13 @@ func (w *window) draw() {
834937
}
835938

836939
func (w *window) ProcessEvent(e event.Event) {
837-
w.w.ProcessEvent(e)
940+
w.processEvent(e)
941+
}
942+
943+
func (w *window) processEvent(e event.Event) bool {
944+
handled := w.w.ProcessEvent(e)
838945
w.loop.FlushEvents()
946+
return handled
839947
}
840948

841949
func (w *window) Event() event.Event {
@@ -960,10 +1068,10 @@ func osMain() {
9601068
C.gio_main()
9611069
}
9621070

963-
func convertKey(k rune) (key.Name, bool) {
1071+
func convertCommandKey(k rune) (key.Name, bool) {
9641072
var n key.Name
9651073
switch k {
966-
case 0x1b:
1074+
case '\x1b': // ASCII escape.
9671075
n = key.NameEscape
9681076
case C.NSLeftArrowFunctionKey:
9691077
n = key.NameLeftArrow
@@ -973,22 +1081,36 @@ func convertKey(k rune) (key.Name, bool) {
9731081
n = key.NameUpArrow
9741082
case C.NSDownArrowFunctionKey:
9751083
n = key.NameDownArrow
976-
case 0xd:
1084+
case '\r':
9771085
n = key.NameReturn
978-
case 0x3:
1086+
case '\x03':
9791087
n = key.NameEnter
9801088
case C.NSHomeFunctionKey:
9811089
n = key.NameHome
9821090
case C.NSEndFunctionKey:
9831091
n = key.NameEnd
984-
case 0x7f:
1092+
case '\x7f', '\b':
9851093
n = key.NameDeleteBackward
9861094
case C.NSDeleteFunctionKey:
9871095
n = key.NameDeleteForward
1096+
case '\t', 0x19:
1097+
n = key.NameTab
9881098
case C.NSPageUpFunctionKey:
9891099
n = key.NamePageUp
9901100
case C.NSPageDownFunctionKey:
9911101
n = key.NamePageDown
1102+
default:
1103+
return "", false
1104+
}
1105+
return n, true
1106+
}
1107+
1108+
func convertKey(k rune) (key.Name, bool) {
1109+
if n, ok := convertCommandKey(k); ok {
1110+
return n, true
1111+
}
1112+
var n key.Name
1113+
switch k {
9921114
case C.NSF1FunctionKey:
9931115
n = key.NameF1
9941116
case C.NSF2FunctionKey:
@@ -1013,8 +1135,6 @@ func convertKey(k rune) (key.Name, bool) {
10131135
n = key.NameF11
10141136
case C.NSF12FunctionKey:
10151137
n = key.NameF12
1016-
case 0x09, 0x19:
1017-
n = key.NameTab
10181138
case 0x20:
10191139
n = key.NameSpace
10201140
default:

0 commit comments

Comments
 (0)