things
This commit is contained in:
parent
c193c25b15
commit
a0fd8a694b
23
box.go
23
box.go
@ -261,6 +261,9 @@ func (this *box) doLayout () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *box) setParent (parent parent) {
|
func (this *box) setParent (parent parent) {
|
||||||
|
if this.parent != parent && this.Focused() {
|
||||||
|
this.SetFocused(false)
|
||||||
|
}
|
||||||
this.parent = parent
|
this.parent = parent
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,3 +319,23 @@ func (this *box) handleMouseUp (button input.Button) {
|
|||||||
listener(button)
|
listener(button)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *box) handleKeyDown (key input.Key, numberPad bool) {
|
||||||
|
for _, listener := range this.on.keyDown.Listeners() {
|
||||||
|
listener(key, numberPad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *box) handleKeyUp (key input.Key, numberPad bool) {
|
||||||
|
for _, listener := range this.on.keyUp.Listeners() {
|
||||||
|
listener(key, numberPad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *box) propagate (callback func (anyBox) bool) bool {
|
||||||
|
return callback(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *box) propagateAlt (callback func (anyBox) bool) bool {
|
||||||
|
return callback(this)
|
||||||
|
}
|
||||||
|
@ -227,3 +227,23 @@ func (this *containerBox) boxUnder (point image.Point) anyBox {
|
|||||||
|
|
||||||
return this.box.boxUnder(point)
|
return this.box.boxUnder(point)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *containerBox) propagate (callback func (anyBox) bool) bool {
|
||||||
|
for _, box := range this.children {
|
||||||
|
box := box.(anyBox)
|
||||||
|
if !box.propagate(callback) { return false }
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *containerBox) propagateAlt (callback func (anyBox) bool) bool {
|
||||||
|
if !callback(this) { return false}
|
||||||
|
|
||||||
|
for _, box := range this.children {
|
||||||
|
box := box.(anyBox)
|
||||||
|
if !box.propagateAlt(callback) { return false }
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
170
event.go
170
event.go
@ -8,6 +8,102 @@ import "git.tebibyte.media/tomo/xgbkb"
|
|||||||
import "github.com/jezek/xgbutil/xevent"
|
import "github.com/jezek/xgbutil/xevent"
|
||||||
import "git.tebibyte.media/tomo/tomo/input"
|
import "git.tebibyte.media/tomo/tomo/input"
|
||||||
|
|
||||||
|
var buttonCodeTable = map[xproto.Keysym] input.Key {
|
||||||
|
0xFFFFFF: input.KeyNone,
|
||||||
|
|
||||||
|
0xFF63: input.KeyInsert,
|
||||||
|
0xFF67: input.KeyMenu,
|
||||||
|
0xFF61: input.KeyPrintScreen,
|
||||||
|
0xFF6B: input.KeyPause,
|
||||||
|
0xFFE5: input.KeyCapsLock,
|
||||||
|
0xFF14: input.KeyScrollLock,
|
||||||
|
0xFF7F: input.KeyNumLock,
|
||||||
|
0xFF08: input.KeyBackspace,
|
||||||
|
0xFF09: input.KeyTab,
|
||||||
|
0xFE20: input.KeyTab,
|
||||||
|
0xFF0D: input.KeyEnter,
|
||||||
|
0xFF1B: input.KeyEscape,
|
||||||
|
|
||||||
|
0xFF52: input.KeyUp,
|
||||||
|
0xFF54: input.KeyDown,
|
||||||
|
0xFF51: input.KeyLeft,
|
||||||
|
0xFF53: input.KeyRight,
|
||||||
|
0xFF55: input.KeyPageUp,
|
||||||
|
0xFF56: input.KeyPageDown,
|
||||||
|
0xFF50: input.KeyHome,
|
||||||
|
0xFF57: input.KeyEnd,
|
||||||
|
|
||||||
|
0xFFE1: input.KeyLeftShift,
|
||||||
|
0xFFE2: input.KeyRightShift,
|
||||||
|
0xFFE3: input.KeyLeftControl,
|
||||||
|
0xFFE4: input.KeyRightControl,
|
||||||
|
|
||||||
|
0xFFE7: input.KeyLeftMeta,
|
||||||
|
0xFFE8: input.KeyRightMeta,
|
||||||
|
0xFFE9: input.KeyLeftAlt,
|
||||||
|
0xFFEA: input.KeyRightAlt,
|
||||||
|
0xFFEB: input.KeyLeftSuper,
|
||||||
|
0xFFEC: input.KeyRightSuper,
|
||||||
|
0xFFED: input.KeyLeftHyper,
|
||||||
|
0xFFEE: input.KeyRightHyper,
|
||||||
|
|
||||||
|
0xFFFF: input.KeyDelete,
|
||||||
|
|
||||||
|
0xFFBE: input.KeyF1,
|
||||||
|
0xFFBF: input.KeyF2,
|
||||||
|
0xFFC0: input.KeyF3,
|
||||||
|
0xFFC1: input.KeyF4,
|
||||||
|
0xFFC2: input.KeyF5,
|
||||||
|
0xFFC3: input.KeyF6,
|
||||||
|
0xFFC4: input.KeyF7,
|
||||||
|
0xFFC5: input.KeyF8,
|
||||||
|
0xFFC6: input.KeyF9,
|
||||||
|
0xFFC7: input.KeyF10,
|
||||||
|
0xFFC8: input.KeyF11,
|
||||||
|
0xFFC9: input.KeyF12,
|
||||||
|
|
||||||
|
0xFF20: input.KeyDead,
|
||||||
|
}
|
||||||
|
|
||||||
|
var keypadCodeTable = map[xproto.Keysym] input.Key {
|
||||||
|
0xff80: input.Key(' '),
|
||||||
|
0xff89: input.KeyTab,
|
||||||
|
0xff8d: input.KeyEnter,
|
||||||
|
0xff91: input.KeyF1,
|
||||||
|
0xff92: input.KeyF2,
|
||||||
|
0xff93: input.KeyF3,
|
||||||
|
0xff94: input.KeyF4,
|
||||||
|
0xff95: input.KeyHome,
|
||||||
|
0xff96: input.KeyLeft,
|
||||||
|
0xff97: input.KeyUp,
|
||||||
|
0xff98: input.KeyRight,
|
||||||
|
0xff99: input.KeyDown,
|
||||||
|
0xff9a: input.KeyPageUp,
|
||||||
|
0xff9b: input.KeyPageDown,
|
||||||
|
0xff9c: input.KeyEnd,
|
||||||
|
0xff9d: input.KeyHome,
|
||||||
|
0xff9e: input.KeyInsert,
|
||||||
|
0xff9f: input.KeyDelete,
|
||||||
|
0xffbd: input.Key('='),
|
||||||
|
0xffaa: input.Key('*'),
|
||||||
|
0xffab: input.Key('+'),
|
||||||
|
0xffac: input.Key(','),
|
||||||
|
0xffad: input.Key('-'),
|
||||||
|
0xffae: input.Key('.'),
|
||||||
|
0xffaf: input.Key('/'),
|
||||||
|
|
||||||
|
0xffb0: input.Key('0'),
|
||||||
|
0xffb1: input.Key('1'),
|
||||||
|
0xffb2: input.Key('2'),
|
||||||
|
0xffb3: input.Key('3'),
|
||||||
|
0xffb4: input.Key('4'),
|
||||||
|
0xffb5: input.Key('5'),
|
||||||
|
0xffb6: input.Key('6'),
|
||||||
|
0xffb7: input.Key('7'),
|
||||||
|
0xffb8: input.Key('8'),
|
||||||
|
0xffb9: input.Key('9'),
|
||||||
|
}
|
||||||
|
|
||||||
func (window *window) handleExpose (
|
func (window *window) handleExpose (
|
||||||
connection *xgbutil.XUtil,
|
connection *xgbutil.XUtil,
|
||||||
event xevent.ExposeEvent,
|
event xevent.ExposeEvent,
|
||||||
@ -74,6 +170,80 @@ func (window *window) exposeEventFollows (event xproto.ConfigureNotifyEvent) (fo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keycodeToKey (keycode xproto.Keycode, state uint16) (input.Key, bool) {
|
||||||
|
keysym, char := xgbkb.KeycodeToKeysym(keycode, state)
|
||||||
|
|
||||||
|
if xgbkb.IsOnNumpad(keysym) {
|
||||||
|
// look up in keypad table
|
||||||
|
key := keypadCodeTable[keysym]
|
||||||
|
return key, true
|
||||||
|
} else {
|
||||||
|
// look up in control code table
|
||||||
|
key, isControl := buttonCodeTable[keysym]
|
||||||
|
if isControl {
|
||||||
|
return key, false
|
||||||
|
} else {
|
||||||
|
// return as rune
|
||||||
|
return input.Key(char), false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (window *window) handleKeyPress (
|
||||||
|
connection *xgbutil.XUtil,
|
||||||
|
event xevent.KeyPressEvent,
|
||||||
|
) {
|
||||||
|
if window.hasModal { return }
|
||||||
|
|
||||||
|
keyEvent := *event.KeyPressEvent
|
||||||
|
key, numberPad := keycodeToKey(keyEvent.Detail, keyEvent.State)
|
||||||
|
window.updateModifiers(keyEvent.State)
|
||||||
|
|
||||||
|
if key == input.KeyTab && window.modifiers.Alt {
|
||||||
|
if window.modifiers.Shift {
|
||||||
|
window.focusPrevious()
|
||||||
|
} else {
|
||||||
|
window.focusNext()
|
||||||
|
}
|
||||||
|
} else if key == input.KeyEscape && window.shy {
|
||||||
|
window.Close()
|
||||||
|
} else if window.focused != nil {
|
||||||
|
window.focused.handleKeyDown(key, numberPad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (window *window) handleKeyRelease (
|
||||||
|
connection *xgbutil.XUtil,
|
||||||
|
event xevent.KeyReleaseEvent,
|
||||||
|
) {
|
||||||
|
if window.hasModal { return }
|
||||||
|
|
||||||
|
keyEvent := *event.KeyReleaseEvent
|
||||||
|
|
||||||
|
// do not process this event if it was generated from a key repeat
|
||||||
|
nextEvents := xevent.Peek(window.backend.x)
|
||||||
|
if len(nextEvents) > 0 {
|
||||||
|
untypedEvent := nextEvents[0]
|
||||||
|
if untypedEvent.Err == nil {
|
||||||
|
typedEvent, ok :=
|
||||||
|
untypedEvent.Event.(xproto.KeyPressEvent)
|
||||||
|
|
||||||
|
if ok && typedEvent.Detail == keyEvent.Detail &&
|
||||||
|
typedEvent.Event == keyEvent.Event &&
|
||||||
|
typedEvent.State == keyEvent.State {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
key, numberPad := keycodeToKey(keyEvent.Detail, keyEvent.State)
|
||||||
|
window.updateModifiers(keyEvent.State)
|
||||||
|
|
||||||
|
if window.focused != nil {
|
||||||
|
window.focused.handleKeyUp(key, numberPad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (window *window) handleButtonPress (
|
func (window *window) handleButtonPress (
|
||||||
connection *xgbutil.XUtil,
|
connection *xgbutil.XUtil,
|
||||||
|
60
system.go
60
system.go
@ -48,6 +48,9 @@ type anyBox interface {
|
|||||||
boxUnder (image.Point) anyBox
|
boxUnder (image.Point) anyBox
|
||||||
recalculateMinimumSize ()
|
recalculateMinimumSize ()
|
||||||
|
|
||||||
|
propagate (func (anyBox) bool) bool
|
||||||
|
propagateAlt (func (anyBox) bool) bool
|
||||||
|
|
||||||
handleFocusEnter ()
|
handleFocusEnter ()
|
||||||
handleFocusLeave ()
|
handleFocusLeave ()
|
||||||
// handleDndEnter ()
|
// handleDndEnter ()
|
||||||
@ -59,8 +62,8 @@ type anyBox interface {
|
|||||||
handleMouseDown (input.Button)
|
handleMouseDown (input.Button)
|
||||||
handleMouseUp (input.Button)
|
handleMouseUp (input.Button)
|
||||||
// handleScroll (float64, float64)
|
// handleScroll (float64, float64)
|
||||||
// handleKeyDown (input.Key, bool)
|
handleKeyDown (input.Key, bool)
|
||||||
// handleKeyUp (input.Key, bool)
|
handleKeyUp (input.Key, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertAnyBox (unknown tomo.Box) anyBox {
|
func assertAnyBox (unknown tomo.Box) anyBox {
|
||||||
@ -119,17 +122,68 @@ func (window *window) focus (box anyBox) {
|
|||||||
window.invalidateDraw(previous)
|
window.invalidateDraw(previous)
|
||||||
previous.handleFocusLeave()
|
previous.handleFocusLeave()
|
||||||
}
|
}
|
||||||
if box != nil {
|
if box != nil && box.canBeFocused() {
|
||||||
window.invalidateDraw(box)
|
window.invalidateDraw(box)
|
||||||
box.handleFocusEnter()
|
box.handleFocusEnter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (window *window) anyFocused () bool {
|
||||||
|
return window.focused != nil
|
||||||
|
}
|
||||||
|
|
||||||
func (this *window) boxUnder (point image.Point) anyBox {
|
func (this *window) boxUnder (point image.Point) anyBox {
|
||||||
if this.root == nil { return nil }
|
if this.root == nil { return nil }
|
||||||
return this.root.boxUnder(point)
|
return this.root.boxUnder(point)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *window) focusNext () {
|
||||||
|
found := !this.anyFocused()
|
||||||
|
focused := false
|
||||||
|
this.propagateAlt (func (box anyBox) bool {
|
||||||
|
if found {
|
||||||
|
// looking for the next box to select
|
||||||
|
if box.canBeFocused() {
|
||||||
|
// found it
|
||||||
|
this.focus(box)
|
||||||
|
focused = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// looking for the current focused element
|
||||||
|
if box == this.focused {
|
||||||
|
// found it
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if !focused { this.focus(nil) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *window) focusPrevious () {
|
||||||
|
var behind anyBox
|
||||||
|
this.propagate (func (box anyBox) bool {
|
||||||
|
if box == this.focused {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if box.canBeFocused() { behind = box }
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
this.focus(behind)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *window) propagate (callback func (box anyBox) bool) {
|
||||||
|
if this.root == nil { return }
|
||||||
|
this.root.propagate(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *window) propagateAlt (callback func (box anyBox) bool) {
|
||||||
|
if this.root == nil { return }
|
||||||
|
this.root.propagateAlt(callback)
|
||||||
|
}
|
||||||
|
|
||||||
func (window *window) afterEvent () {
|
func (window *window) afterEvent () {
|
||||||
if window.xCanvas == nil { return }
|
if window.xCanvas == nil { return }
|
||||||
|
|
||||||
|
@ -109,10 +109,10 @@ func (backend *Backend) newWindow (
|
|||||||
Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
xevent.ConfigureNotifyFun(window.handleConfigureNotify).
|
xevent.ConfigureNotifyFun(window.handleConfigureNotify).
|
||||||
Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
// xevent.KeyPressFun(window.handleKeyPress).
|
xevent.KeyPressFun(window.handleKeyPress).
|
||||||
// Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
// xevent.KeyReleaseFun(window.handleKeyRelease).
|
xevent.KeyReleaseFun(window.handleKeyRelease).
|
||||||
// Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
xevent.ButtonPressFun(window.handleButtonPress).
|
xevent.ButtonPressFun(window.handleButtonPress).
|
||||||
Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
xevent.ButtonReleaseFun(window.handleButtonRelease).
|
xevent.ButtonReleaseFun(window.handleButtonRelease).
|
||||||
|
Reference in New Issue
Block a user