~eliasnaur/gio

9fe8b684e2a5ac4caea811154db1f2bfd74b2b7b — Elias Naur 3 months ago 2a18a0c app-overhaul
app: introduce Config.Focused that tracks the window focus state

Signed-off-by: Elias Naur <mail@eliasnaur.com>
M app/os.go => app/os.go +2 -0
@@ 45,6 45,8 @@ type Config struct {
	CustomRenderer bool
	// Decorated reports whether window decorations are provided automatically.
	Decorated bool
	// Focused reports whether has the keyboard focus.
	Focused bool
	// decoHeight is the height of the fallback decoration for platforms such
	// as Wayland that may need fallback client-side decorations.
	decoHeight unit.Dp

M app/os_android.go => app/os_android.go +2 -1
@@ 593,7 593,8 @@ func Java_org_gioui_GioView_onBack(env *C.JNIEnv, class C.jclass, view C.jlong) 
//export Java_org_gioui_GioView_onFocusChange
func Java_org_gioui_GioView_onFocusChange(env *C.JNIEnv, class C.jclass, view C.jlong, focus C.jboolean) {
	w := cgo.Handle(view).Value().(*window)
	w.processEvent(key.FocusEvent{Focus: focus == C.JNI_TRUE})
	w.config.Focused = focus == C.JNI_TRUE
	w.processEvent(ConfigEvent{Config: w.config})
}

//export Java_org_gioui_GioView_onWindowInsets

M app/os_ios.go => app/os_ios.go +2 -1
@@ 211,7 211,8 @@ func onDestroy(h C.uintptr_t) {
//export onFocus
func onFocus(h C.uintptr_t, focus int) {
	w := viewFor(h)
	w.ProcessEvent(key.FocusEvent{Focus: focus != 0})
	w.config.Focused = focus != 0
	w.ProcessEvent(ConfigEvent{Config: w.config})
}

//export onLowMemory

M app/os_js.go => app/os_js.go +4 -2
@@ 258,11 258,13 @@ func (w *window) addEventListeners() {
		return nil
	})
	w.addEventListener(w.tarea, "focus", func(this js.Value, args []js.Value) interface{} {
		w.processEvent(key.FocusEvent{Focus: true})
		w.config.Focused = true
		w.processEvent(ConfigEvent{Config: w.config})
		return nil
	})
	w.addEventListener(w.tarea, "blur", func(this js.Value, args []js.Value) interface{} {
		w.processEvent(key.FocusEvent{Focus: false})
		w.config.Focused = false
		w.processEvent(ConfigEvent{Config: w.config})
		w.blur()
		return nil
	})

M app/os_macos.go => app/os_macos.go +2 -1
@@ 612,8 612,9 @@ func gio_onDraw(h C.uintptr_t) {
//export gio_onFocus
func gio_onFocus(h C.uintptr_t, focus C.int) {
	w := windowFor(h)
	w.ProcessEvent(key.FocusEvent{Focus: focus == 1})
	w.SetCursor(w.cursor)
	w.config.Focused = focus == 1
	w.ProcessEvent(ConfigEvent{Config: w.config})
}

//export gio_onChangeScreen

M app/os_wayland.go => app/os_wayland.go +4 -2
@@ 1222,7 1222,8 @@ func gio_onKeyboardEnter(data unsafe.Pointer, keyboard *C.struct_wl_keyboard, se
	w := callbackLoad(unsafe.Pointer(surf)).(*window)
	s.keyboardFocus = w
	s.disp.repeat.Stop(0)
	w.ProcessEvent(key.FocusEvent{Focus: true})
	w.config.Focused = true
	w.ProcessEvent(ConfigEvent{Config: w.config})
}

//export gio_onKeyboardLeave


@@ 1231,7 1232,8 @@ func gio_onKeyboardLeave(data unsafe.Pointer, keyboard *C.struct_wl_keyboard, se
	s.serial = serial
	s.disp.repeat.Stop(0)
	w := s.keyboardFocus
	w.ProcessEvent(key.FocusEvent{Focus: false})
	w.config.Focused = false
	w.ProcessEvent(ConfigEvent{Config: w.config})
}

//export gio_onKeyboardKey

M app/os_windows.go => app/os_windows.go +5 -6
@@ 50,7 50,6 @@ type window struct {
	placement *windows.WindowPlacement

	animating bool
	focused   bool

	borderSize image.Point
	config     Config


@@ 269,11 268,11 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
			Kind: pointer.Cancel,
		})
	case windows.WM_SETFOCUS:
		w.focused = true
		w.ProcessEvent(key.FocusEvent{Focus: true})
		w.config.Focused = true
		w.ProcessEvent(ConfigEvent{Config: w.config})
	case windows.WM_KILLFOCUS:
		w.focused = false
		w.ProcessEvent(key.FocusEvent{Focus: false})
		w.config.Focused = false
		w.ProcessEvent(ConfigEvent{Config: w.config})
	case windows.WM_NCHITTEST:
		if w.config.Decorated {
			// Let the system handle it.


@@ 496,7 495,7 @@ func (w *window) hitTest(x, y int) uintptr {
}

func (w *window) pointerButton(btn pointer.Buttons, press bool, lParam uintptr, kmods key.Modifiers) {
	if !w.focused {
	if !w.config.Focused {
		windows.SetFocus(w.hwnd)
	}


M app/os_x11.go => app/os_x11.go +4 -2
@@ 657,9 657,11 @@ func (h *x11EventHandler) handleEvents() bool {
			// redraw only on the last expose event
			redraw = (*C.XExposeEvent)(unsafe.Pointer(xev)).count == 0
		case C.FocusIn:
			w.ProcessEvent(key.FocusEvent{Focus: true})
			w.config.Focused = true
			w.ProcessEvent(ConfigEvent{Config: w.config})
		case C.FocusOut:
			w.ProcessEvent(key.FocusEvent{Focus: false})
			w.config.Focused = false
			w.ProcessEvent(ConfigEvent{Config: w.config})
		case C.ConfigureNotify: // window configuration change
			cevt := (*C.XConfigureEvent)(unsafe.Pointer(xev))
			if sz := image.Pt(int(cevt.width), int(cevt.height)); sz != w.config.Size {

M app/window.go => app/window.go +10 -0
@@ 630,9 630,19 @@ func (w *Window) processEvent(e event.Event) bool {
		}
		w.coalesced.view = &e2
	case ConfigEvent:
		wasFocused := w.decorations.Config.Focused
		w.decorations.Config = e2.Config
		e2.Config = w.effectiveConfig()
		w.coalesced.cfg = &e2
		if f := w.decorations.Config.Focused; f != wasFocused {
			w.queue.Queue(key.FocusEvent{Focus: f})
		}
		t, handled := w.queue.WakeupTime()
		if handled {
			w.setNextFrame(t)
			w.updateAnimation()
		}
		return handled
	case event.Event:
		focusDir := key.FocusDirection(-1)
		if e, ok := e2.(key.Event); ok && e.State == key.Press {