mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
io/pointer: added CursorNameOp
The cursor can now be customized for a given area. Signed-off-by: pierre <pierre.curto@gmail.com>
This commit is contained in:
+6
-1
@@ -48,7 +48,8 @@ type Window struct {
|
|||||||
nextFrame time.Time
|
nextFrame time.Time
|
||||||
delayedDraw *time.Timer
|
delayedDraw *time.Timer
|
||||||
|
|
||||||
queue queue
|
queue queue
|
||||||
|
cursor pointer.CursorName
|
||||||
|
|
||||||
callbacks callbacks
|
callbacks callbacks
|
||||||
}
|
}
|
||||||
@@ -414,6 +415,10 @@ func (w *Window) run(opts *window.Options) {
|
|||||||
w.setNextFrame(time.Time{})
|
w.setNextFrame(time.Time{})
|
||||||
w.updateAnimation()
|
w.updateAnimation()
|
||||||
}
|
}
|
||||||
|
if c := w.queue.q.Cursor(); c != w.cursor {
|
||||||
|
w.cursor = c
|
||||||
|
w.SetCursorName(c)
|
||||||
|
}
|
||||||
w.out <- e
|
w.out <- e
|
||||||
}
|
}
|
||||||
w.ack <- struct{}{}
|
w.ack <- struct{}{}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const (
|
|||||||
TypeAux
|
TypeAux
|
||||||
TypeClip
|
TypeClip
|
||||||
TypeProfile
|
TypeProfile
|
||||||
|
TypeCursor
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -55,6 +56,7 @@ const (
|
|||||||
TypeAuxLen = 1
|
TypeAuxLen = 1
|
||||||
TypeClipLen = 1 + 4*4 + 4 + 2 + 4
|
TypeClipLen = 1 + 4*4 + 4 + 2 + 4
|
||||||
TypeProfileLen = 1
|
TypeProfileLen = 1
|
||||||
|
TypeCursorLen = 1 + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t OpType) Size() int {
|
func (t OpType) Size() int {
|
||||||
@@ -81,12 +83,13 @@ func (t OpType) Size() int {
|
|||||||
TypeAuxLen,
|
TypeAuxLen,
|
||||||
TypeClipLen,
|
TypeClipLen,
|
||||||
TypeProfileLen,
|
TypeProfileLen,
|
||||||
|
TypeCursorLen,
|
||||||
}[t-firstOpIndex]
|
}[t-firstOpIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t OpType) NumRefs() int {
|
func (t OpType) NumRefs() int {
|
||||||
switch t {
|
switch t {
|
||||||
case TypeKeyInput, TypePointerInput, TypeProfile, TypeCall, TypeClipboardRead, TypeClipboardWrite:
|
case TypeKeyInput, TypePointerInput, TypeProfile, TypeCall, TypeClipboardRead, TypeClipboardWrite, TypeCursor:
|
||||||
return 1
|
return 1
|
||||||
case TypeImage:
|
case TypeImage:
|
||||||
return 2
|
return 2
|
||||||
|
|||||||
@@ -49,6 +49,11 @@ type AreaOp struct {
|
|||||||
rect image.Rectangle
|
rect image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CursorNameOp sets the cursor for the current area.
|
||||||
|
type CursorNameOp struct {
|
||||||
|
Name CursorName
|
||||||
|
}
|
||||||
|
|
||||||
// InputOp declares an input handler ready for pointer
|
// InputOp declares an input handler ready for pointer
|
||||||
// events.
|
// events.
|
||||||
type InputOp struct {
|
type InputOp struct {
|
||||||
@@ -178,6 +183,11 @@ func (op AreaOp) Add(o *op.Ops) {
|
|||||||
bo.PutUint32(data[14:], uint32(op.rect.Max.Y))
|
bo.PutUint32(data[14:], uint32(op.rect.Max.Y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (op CursorNameOp) Add(o *op.Ops) {
|
||||||
|
data := o.Write1(opconst.TypeCursorLen, op.Name)
|
||||||
|
data[0] = byte(opconst.TypeCursor)
|
||||||
|
}
|
||||||
|
|
||||||
func (h InputOp) Add(o *op.Ops) {
|
func (h InputOp) Add(o *op.Ops) {
|
||||||
data := o.Write1(opconst.TypePointerInputLen, h.Tag)
|
data := o.Write1(opconst.TypePointerInputLen, h.Tag)
|
||||||
data[0] = byte(opconst.TypePointerInput)
|
data[0] = byte(opconst.TypePointerInput)
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import (
|
|||||||
type pointerQueue struct {
|
type pointerQueue struct {
|
||||||
hitTree []hitNode
|
hitTree []hitNode
|
||||||
areas []areaNode
|
areas []areaNode
|
||||||
|
cursors []cursorNode
|
||||||
|
cursor pointer.CursorName
|
||||||
handlers map[event.Tag]*pointerHandler
|
handlers map[event.Tag]*pointerHandler
|
||||||
pointers []pointerInfo
|
pointers []pointerInfo
|
||||||
reader ops.Reader
|
reader ops.Reader
|
||||||
@@ -34,6 +36,11 @@ type hitNode struct {
|
|||||||
tag event.Tag
|
tag event.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cursorNode struct {
|
||||||
|
name pointer.CursorName
|
||||||
|
area int
|
||||||
|
}
|
||||||
|
|
||||||
type pointerInfo struct {
|
type pointerInfo struct {
|
||||||
id pointer.ID
|
id pointer.ID
|
||||||
pressed bool
|
pressed bool
|
||||||
@@ -114,6 +121,11 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t f
|
|||||||
h.area = area
|
h.area = area
|
||||||
h.wantsGrab = h.wantsGrab || op.Grab
|
h.wantsGrab = h.wantsGrab || op.Grab
|
||||||
h.types = h.types | op.Types
|
h.types = h.types | op.Types
|
||||||
|
case opconst.TypeCursor:
|
||||||
|
q.cursors = append(q.cursors, cursorNode{
|
||||||
|
name: encOp.Refs[0].(pointer.CursorName),
|
||||||
|
area: len(q.areas) - 1,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,6 +189,7 @@ func (q *pointerQueue) Frame(root *op.Ops, events *handlerEvents) {
|
|||||||
}
|
}
|
||||||
q.hitTree = q.hitTree[:0]
|
q.hitTree = q.hitTree[:0]
|
||||||
q.areas = q.areas[:0]
|
q.areas = q.areas[:0]
|
||||||
|
q.cursors = q.cursors[:0]
|
||||||
q.reader.Reset(root)
|
q.reader.Reset(root)
|
||||||
q.collectHandlers(&q.reader, events, f32.Affine2D{}, -1, -1, false)
|
q.collectHandlers(&q.reader, events, f32.Affine2D{}, -1, -1, false)
|
||||||
for k, h := range q.handlers {
|
for k, h := range q.handlers {
|
||||||
@@ -314,6 +327,7 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, hits []event.Tag,
|
|||||||
|
|
||||||
if e.Type&h.types == e.Type {
|
if e.Type&h.types == e.Type {
|
||||||
events.Add(k, e)
|
events.Add(k, e)
|
||||||
|
q.cursor = pointer.CursorDefault
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Deliver Enter events.
|
// Deliver Enter events.
|
||||||
@@ -327,11 +341,25 @@ func (q *pointerQueue) deliverEnterLeaveEvents(p *pointerInfo, hits []event.Tag,
|
|||||||
|
|
||||||
if e.Type&h.types == e.Type {
|
if e.Type&h.types == e.Type {
|
||||||
events.Add(k, e)
|
events.Add(k, e)
|
||||||
|
q.hitCursor(h.area)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.entered = append(p.entered[:0], hits...)
|
p.entered = append(p.entered[:0], hits...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *pointerQueue) hitCursor(want int) {
|
||||||
|
for _, c := range q.cursors {
|
||||||
|
idx := c.area
|
||||||
|
for idx != -1 {
|
||||||
|
if idx == want {
|
||||||
|
q.cursor = c.name
|
||||||
|
return
|
||||||
|
}
|
||||||
|
idx = q.areas[idx].next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func searchTag(tags []event.Tag, tag event.Tag) (int, bool) {
|
func searchTag(tags []event.Tag, tag event.Tag) (int, bool) {
|
||||||
for i, t := range tags {
|
for i, t := range tags {
|
||||||
if t == tag {
|
if t == tag {
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ func (q *Router) ReadClipboard() bool {
|
|||||||
return q.cqueue.ReadClipboard()
|
return q.cqueue.ReadClipboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cursor returns the last cursor set.
|
||||||
|
func (q *Router) Cursor() pointer.CursorName {
|
||||||
|
return q.pqueue.cursor
|
||||||
|
}
|
||||||
|
|
||||||
func (q *Router) collect() {
|
func (q *Router) collect() {
|
||||||
for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() {
|
for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() {
|
||||||
switch opconst.OpType(encOp.Data[0]) {
|
switch opconst.OpType(encOp.Data[0]) {
|
||||||
|
|||||||
+4
-1
@@ -379,7 +379,10 @@ func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size
|
|||||||
}
|
}
|
||||||
e.makeValid()
|
e.makeValid()
|
||||||
|
|
||||||
return e.layout(gtx)
|
dims := e.layout(gtx)
|
||||||
|
pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops)
|
||||||
|
pointer.CursorNameOp{Name: pointer.CursorText}.Add(gtx.Ops)
|
||||||
|
return dims
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Editor) layout(gtx layout.Context) layout.Dimensions {
|
func (e *Editor) layout(gtx layout.Context) layout.Dimensions {
|
||||||
|
|||||||
Reference in New Issue
Block a user