~eliasnaur/gio-patches

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
11 5

[PATCH gio 0/3] Make widget.Editor keyboard shortcuts extensible

~whereswaldon
Details
Message ID
<160357717109.3483.1149584792398089169-0@git.sr.ht>
DKIM signature
missing
Download raw message
This change changes the material.Editor so that it emits an even
whenever it received a non-text-input event that isn't one of its
builtin keyboard shortcuts. This makes it easy for applications to add
their own keyboard shortcut behavior while the editor widget has focus
(which was previously impossible).

I modified the kitchen demo so
that it can accept ctrl+v to paste into the editors, though I left the
old paste-by-clicking-a-button behavior in there. I don't mind removing
that if it's preferred.

I mostly want this feature to support pasting
and dismissing the editor (by pressing escape) in my applications.
Feedback welcome!
Chris

Chris Waldon (3):
  widget: make Editor emit events for unhandled key.Events
  example: dummy commit to make next patch build
  example/kitchen: paste into editors with ctrl+v

 example/go.mod             |  2 ++
 example/kitchen/kitchen.go | 41 ++++++++++++++++++++++++++++++++++----
 widget/editor.go           | 15 ++++++++++++--
 widget/editor_test.go      | 39 ++++++++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 6 deletions(-)

-- 
2.26.2

[PATCH gio 1/3] widget: make Editor emit events for unhandled key.Events

~whereswaldon
Details
Message ID
<160357717109.3483.1149584792398089169-1@git.sr.ht>
In-Reply-To
<160357717109.3483.1149584792398089169-0@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
Patch: +52 -2
From: Chris Waldon <christopher.waldon.dev@gmail.com>

This enables higher-level application logic to interpret the keypresses,
which can be used (for instance) to detect ctrl+v and request a keyboard
paste.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
---
 widget/editor.go      | 15 +++++++++++++--
 widget/editor_test.go | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/widget/editor.go b/widget/editor.go
index 57784cb..3b29e25 100644
--- a/widget/editor.go
+++ b/widget/editor.go
@@ -142,6 +142,14 @@ type SubmitEvent struct {
	Text string
}

// UnhandledKeyEvent is generated when a non-text-input keypress is
// not recognized by the Editor. Higher-level application logic can
// consume this event to implement other keyboard shortcuts while the
// editor has focus.
type UnhandledKeyEvent struct {
	key.Event
}

type line struct {
	offset f32.Point
	clip   op.CallOp
@@ -251,7 +259,9 @@ func (e *Editor) processKey(gtx layout.Context) {
			if e.command(ke) {
				e.caret.scroll = true
				e.scroller.Stop()
				break
			}
			e.events = append(e.events, UnhandledKeyEvent{ke})
		case key.EditEvent:
			e.caret.scroll = true
			e.scroller.Stop()
@@ -932,5 +942,6 @@ func nullLayout(r io.Reader) ([]text.Line, error) {
	}, rerr
}

func (s ChangeEvent) isEditorEvent() {}
func (s SubmitEvent) isEditorEvent() {}
func (s ChangeEvent) isEditorEvent()       {}
func (s SubmitEvent) isEditorEvent()       {}
func (s UnhandledKeyEvent) isEditorEvent() {}
diff --git a/widget/editor_test.go b/widget/editor_test.go
index 3b003ad..409f91b 100644
--- a/widget/editor_test.go
+++ b/widget/editor_test.go
@@ -300,3 +300,42 @@ func (editMutation) Generate(rand *rand.Rand, size int) reflect.Value {
	t := editMutation(rand.Intn(int(moveLast)))
	return reflect.ValueOf(t)
}

func TestEditorUnhandledKeyEvent(t *testing.T) {
	e := new(Editor)
	e.Focus()
	keyEvent := key.Event{Name: "V", Modifiers: key.ModCtrl}
	handledKeyEvent := key.Event{Name: key.NameUpArrow}
	tq := &testQueue{
		events: []event.Event{
			key.FocusEvent{Focus: true},
			key.EditEvent{Text: "A"},
			keyEvent,
			handledKeyEvent,
		},
	}
	gtx := layout.Context{
		Ops:         new(op.Ops),
		Constraints: layout.Constraints{Max: image.Pt(100, 100)},
		Queue:       tq,
	}
	cache := text.NewCache(gofont.Collection())
	fontSize := unit.Px(10)
	font := text.Font{}
	e.Layout(gtx, cache, font, fontSize)
	foundUnhandled := false
	for _, event := range e.Events() {
		switch event := event.(type) {
		case UnhandledKeyEvent:
			if event.Event == keyEvent {
				foundUnhandled = true
			}
			if event.Event == handledKeyEvent {
				t.Errorf("should not generate UnhandledKeyEvent for handled event: %v", handledKeyEvent)
			}
		}
	}
	if !foundUnhandled {
		t.Errorf("editor did not emit UnhandledKeyEvent")
	}
}
-- 
2.26.2

[PATCH gio 2/3] example: dummy commit to make next patch build

~whereswaldon
Details
Message ID
<160357717109.3483.1149584792398089169-2@git.sr.ht>
In-Reply-To
<160357717109.3483.1149584792398089169-0@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
Patch: +2 -0
From: Chris Waldon <christopher.waldon.dev@gmail.com>

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
---
 example/go.mod | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/example/go.mod b/example/go.mod
index fa0a357..0f11b09 100644
--- a/example/go.mod
+++ b/example/go.mod
@@ -11,3 +11,5 @@ require (
	golang.org/x/image v0.0.0-20200618115811-c13761719519
	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
)

replace gioui.org => ../
-- 
2.26.2

[PATCH gio 3/3] example/kitchen: paste into editors with ctrl+v

~whereswaldon
Details
Message ID
<160357717109.3483.1149584792398089169-3@git.sr.ht>
In-Reply-To
<160357717109.3483.1149584792398089169-0@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
Patch: +37 -4
From: Chris Waldon <christopher.waldon.dev@gmail.com>

Uses command+V on macOS.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
---
 example/kitchen/kitchen.go | 41 ++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/example/kitchen/kitchen.go b/example/kitchen/kitchen.go
index f607493..7584b7a 100644
--- a/example/kitchen/kitchen.go
+++ b/example/kitchen/kitchen.go
@@ -15,12 +15,14 @@ import (
	"log"
	"math"
	"os"
	"runtime"
	"time"

	"gioui.org/app"
	"gioui.org/app/headless"
	"gioui.org/f32"
	"gioui.org/font/gofont"
	"gioui.org/io/key"
	"gioui.org/io/router"
	"gioui.org/io/system"
	"gioui.org/layout"
@@ -116,10 +118,19 @@ func loop(w *app.Window) error {
		case e := <-w.Events():
			switch e := e.(type) {
			case system.ClipboardEvent:
				lineEditor.SetText(e.Text)
				if pasteRequestingEditor == nil {
					lineEditor.Insert(e.Text)
				} else {
					pasteRequestingEditor.Insert(e.Text)
					pasteRequestingEditor = nil
				}
			case system.DestroyEvent:
				return e.Err
			case system.FrameEvent:
				if pasteRequested {
					w.ReadClipboard()
					pasteRequested = false
				}
				gtx := layout.NewContext(&ops, e)
				for iconButton.Clicked() {
					w.WriteClipboard(lineEditor.Text())
@@ -176,8 +187,10 @@ func transformedKitchen(gtx layout.Context, th *material.Theme) layout.Dimension
}

var (
	editor     = new(widget.Editor)
	lineEditor = &widget.Editor{
	pasteRequested        bool
	pasteRequestingEditor *widget.Editor
	editor                = new(widget.Editor)
	lineEditor            = &widget.Editor{
		SingleLine: true,
		Submit:     true,
	}
@@ -240,11 +253,31 @@ func (b iconAndTextButton) Layout(gtx layout.Context) layout.Dimensions {
	})
}

func processUnhandledKey(event key.Event, editor *widget.Editor) {
	modifier := key.ModCtrl
	if runtime.GOOS == "darwin" {
		modifier = key.ModCommand
	}
	if event.Modifiers == modifier && event.Name == "V" {
		pasteRequestingEditor = editor
		pasteRequested = true
	}
}

func kitchen(gtx layout.Context, th *material.Theme) layout.Dimensions {
	for _, e := range lineEditor.Events() {
		if e, ok := e.(widget.SubmitEvent); ok {
		switch e := e.(type) {
		case widget.SubmitEvent:
			topLabel = e.Text
			lineEditor.SetText("")
		case widget.UnhandledKeyEvent:
			processUnhandledKey(e.Event, lineEditor)
		}
	}
	for _, e := range editor.Events() {
		switch e := e.(type) {
		case widget.UnhandledKeyEvent:
			processUnhandledKey(e.Event, editor)
		}
	}
	widgets := []layout.Widget{
-- 
2.26.2

[gio/patches] build failed

builds.sr.ht
Details
Message ID
<C6LGV0KNTZT6.1RZZO4MEIN6FA@cirno2>
In-Reply-To
<160357717109.3483.1149584792398089169-3@git.sr.ht> (view parent)
DKIM signature
missing
Download raw message
gio/patches: FAILED in 9m7s

[Make widget.Editor keyboard shortcuts extensible][0] from [~whereswaldon][1]

[0]: https://lists.sr.ht/~eliasnaur/gio-patches/patches/14507
[1]: christopher.waldon.dev@gmail.com

✓ #326971 SUCCESS gio/patches/linux.yml   https://builds.sr.ht/~eliasnaur/job/326971
✗ #326970 FAILED  gio/patches/freebsd.yml https://builds.sr.ht/~eliasnaur/job/326970
✗ #326969 FAILED  gio/patches/apple.yml   https://builds.sr.ht/~eliasnaur/job/326969
✓ #326972 SUCCESS gio/patches/openbsd.yml https://builds.sr.ht/~eliasnaur/job/326972
Details
Message ID
<C6MOKS2G57EO.1QR36UOVM7GB5@testmac>
In-Reply-To
<160357717109.3483.1149584792398089169-0@git.sr.ht> (view parent)
DKIM signature
pass
Download raw message
On Sun Oct 25, 2020 at 12:06 AM CEST, ~whereswaldon wrote:
> This change changes the material.Editor so that it emits an even
> whenever it received a non-text-input event that isn't one of its
> builtin keyboard shortcuts. This makes it easy for applications to add
> their own keyboard shortcut behavior while the editor widget has focus
> (which was previously impossible).
>
> I modified the kitchen demo so
> that it can accept ctrl+v to paste into the editors, though I left the
> old paste-by-clicking-a-button behavior in there. I don't mind removing
> that if it's preferred.
>
> I mostly want this feature to support pasting
> and dismissing the editor (by pressing escape) in my applications.
> Feedback welcome!
>

Thank you. It's unfortunate that the feature is Editor-specific.
Why not something like

	package event

	// A Spy is a Queue that retains Events from an underlying Queue for
	// later processing. It's useful for reacting to events a widget
	// doesn't recognize.
	type Spy struct
		// Queue is the underlying queue for the Events method.
		Queue Queue

		events []Event
	}

	func (q *Spy) Events(t Tag) []Event

	func (q *Spy) AllEvents() []Event

?

Elias
Details
Message ID
<CAE_4BPD-D3knbGksBXFt6HYz17Wd-VA=z564w_w+ziZffSKKQA@mail.gmail.com>
In-Reply-To
<C6MOKS2G57EO.1QR36UOVM7GB5@testmac> (view parent)
DKIM signature
missing
Download raw message
(I haven't looked at Chris's code.)

How would the Spy know which events were processed and which not?
What if you wrap a Spy around a Spy (around a Spy, around a Spy ...)?

Let's try not to reinvent the Javascript event model, if possible
(bubbling and cancelling and whatnot), which seems very complex.  (If
that's *not* possible, let's try to learn from it and/or other
toolkits' event models.)

I seem to recall (it's been a little while) that In my own code, I
have an ugly hack for this sort of thing for keystrokes, where
basically I mark keys I've consumed/processes as such, and then ignore
already-processed keys at the top of every event processing loop.
(I'm afraid it didn't occur to me to try to generalize this, much less
submit it, more fool I.  Also I admit it probably would've been better
if I'd just removed the key from the queue instead of having to modify
all my event loops, but oh well.  All too often I *Want It To Work
Tonight, Dammit!* and this, uh, impacts my code quality.  :)  I'd love
if this sort of thing were generalized and part of the core API.

-- L

On Mon, Oct 26, 2020 at 4:30 AM Elias Naur <mail@eliasnaur.com> wrote:
>
> On Sun Oct 25, 2020 at 12:06 AM CEST, ~whereswaldon wrote:
> > This change changes the material.Editor so that it emits an even
> > whenever it received a non-text-input event that isn't one of its
> > builtin keyboard shortcuts. This makes it easy for applications to add
> > their own keyboard shortcut behavior while the editor widget has focus
> > (which was previously impossible).
> >
> > I modified the kitchen demo so
> > that it can accept ctrl+v to paste into the editors, though I left the
> > old paste-by-clicking-a-button behavior in there. I don't mind removing
> > that if it's preferred.
> >
> > I mostly want this feature to support pasting
> > and dismissing the editor (by pressing escape) in my applications.
> > Feedback welcome!
> >
>
> Thank you. It's unfortunate that the feature is Editor-specific.
> Why not something like
>
>         package event
>
>         // A Spy is a Queue that retains Events from an underlying Queue for
>         // later processing. It's useful for reacting to events a widget
>         // doesn't recognize.
>         type Spy struct
>                 // Queue is the underlying queue for the Events method.
>                 Queue Queue
>
>                 events []Event
>         }
>
>         func (q *Spy) Events(t Tag) []Event
>
>         func (q *Spy) AllEvents() []Event
>
> ?
>
> Elias
Details
Message ID
<C6MZLJ2Y17TU.1QAWYBVYRZTKQ@themachine>
In-Reply-To
<CAE_4BPD-D3knbGksBXFt6HYz17Wd-VA=z564w_w+ziZffSKKQA@mail.gmail.com> (view parent)
DKIM signature
pass
Download raw message
On Mon Oct 26, 2020 at 11:13, Larry Clapp wrote:
> (I haven't looked at Chris's code.)
>
> How would the Spy know which events were processed and which not?
> What if you wrap a Spy around a Spy (around a Spy, around a Spy ...)?
>

The Spy doesn't, but you do. In other words, Spy is functionality, not
convention. For example, you want to handle the escape key in a certain way,
but only when directed at some widget. Spy is the tool.

> Let's try not to reinvent the Javascript event model, if possible
> (bubbling and cancelling and whatnot), which seems very complex.  (If
> that's *not* possible, let's try to learn from it and/or other
> toolkits' event models.)
>

I'm not sure what you refer to here. Chris' code introduces event
"bubbling" from inside the Editor, I'm proposing event "bubbling" from
the outside in. I'd say both suggestions are equally "bubbly", but Spy
is more generally useful.

Elias
Details
Message ID
<C6TN3AVGBZS3.13FFA53UMWXQR@vendetta>
In-Reply-To
<C6MZLJ2Y17TU.1QAWYBVYRZTKQ@themachine> (view parent)
DKIM signature
pass
Download raw message
On Mon Oct 26, 2020 at 2:09 PM EDT, Elias Naur wrote:
> On Mon Oct 26, 2020 at 11:13, Larry Clapp wrote:
> > (I haven't looked at Chris's code.)
> >
> > How would the Spy know which events were processed and which not?
> > What if you wrap a Spy around a Spy (around a Spy, around a Spy ...)?
> >
>
> The Spy doesn't, but you do. In other words, Spy is functionality, not
> convention. For example, you want to handle the escape key in a certain
> way,
> but only when directed at some widget. Spy is the tool.

So the spy does seem like an interesting primitive to have, but I haven't
yet thought of an API for using it that I like. The problem is that, in
order to use the spy effectively, I need to know details of the implementation
of widgets. If I want to extend the editor's keyboard shortcuts using a spy,
I need to know which keys it already consumes. Otherwise, I may process a
keystroke that the editor also processed, and two effects will occur when
the user (reasonably) only wanted one.

Additionally, if I'm trying to use the spy to examine the events for a
particular widget's tag, I must *know* the tag value that it uses. This
seems very much like an internal implementation detail. I often end up
writing widgets that use several tags for different kinds of events, and
higher-level code trying to handle events would need to know about all of
them.

> > Let's try not to reinvent the Javascript event model, if possible
> > (bubbling and cancelling and whatnot), which seems very complex.  (If
> > that's *not* possible, let's try to learn from it and/or other
> > toolkits' event models.)
> >
>
> I'm not sure what you refer to here. Chris' code introduces event
> "bubbling" from inside the Editor, I'm proposing event "bubbling" from
> the outside in. I'd say both suggestions are equally "bubbly", but Spy
> is more generally useful.

Yeah, so I think we cannot escape the fundamental nature of events. They
are logically "consumed" by some widgets. We need a way to map events to
widgets (which we have), and we need a way to determine which events that
widget consumed (what we're working on now). Ideally we can find a mechanism
that is less complex than the JS model. My initial patch is definitely a
specific case of bubbling that could be generalized.

I think that we need a mechanism for a widget to emit unconsumed events,
though it could be a great deal more general than what I implemented here.
Perhaps we just allow a widget to push events it didn't use *back* into
the queue in a way that marks them as "fair game" for other widgets?

Sorry for the long response time!

Cheers,
Chris
Details
Message ID
<C6TOY6QT0MCX.1SX58AOECY13C@themachine>
In-Reply-To
<C6TN3AVGBZS3.13FFA53UMWXQR@vendetta> (view parent)
DKIM signature
pass
Download raw message
On Tue Nov 3, 2020 at 07:49, Chris Waldon wrote:
> On Mon Oct 26, 2020 at 2:09 PM EDT, Elias Naur wrote:
> > On Mon Oct 26, 2020 at 11:13, Larry Clapp wrote:
> > > (I haven't looked at Chris's code.)
> > >
> > > How would the Spy know which events were processed and which not?
> > > What if you wrap a Spy around a Spy (around a Spy, around a Spy ...)?
> > >
> >
> > The Spy doesn't, but you do. In other words, Spy is functionality, not
> > convention. For example, you want to handle the escape key in a certain
> > way,
> > but only when directed at some widget. Spy is the tool.
>
> So the spy does seem like an interesting primitive to have, but I haven't
> yet thought of an API for using it that I like. The problem is that, in
> order to use the spy effectively, I need to know details of the implementation
> of widgets. If I want to extend the editor's keyboard shortcuts using a spy,
> I need to know which keys it already consumes. Otherwise, I may process a
> keystroke that the editor also processed, and two effects will occur when
> the user (reasonably) only wanted one.
>

Sure, but it seems to me your approach has the reverse problem: your
custom action will not be invoked if the Editor wants it (now or in the
future). That may be ok for some actions, but not all.

That said, I'm not sure Spy belongs in the core either. It seems to me
keyboard shortcuts should be resolved with InputOps similar to pointer
events. Spy is a quick, yet general, approach to achieve your objective.

> Additionally, if I'm trying to use the spy to examine the events for a
> particular widget's tag, I must *know* the tag value that it uses. This
> seems very much like an internal implementation detail. I often end up
> writing widgets that use several tags for different kinds of events, and
> higher-level code trying to handle events would need to know about all of
> them.
>

Why do you need to know the tag(s)? Spy collects every event that flows
through it, regardless of the tag. Its Event method takes a tag only to
implement the Queue interface and to pass it on to the underlying Queue.

> > > Let's try not to reinvent the Javascript event model, if possible
> > > (bubbling and cancelling and whatnot), which seems very complex.  (If
> > > that's *not* possible, let's try to learn from it and/or other
> > > toolkits' event models.)
> > >
> >
> > I'm not sure what you refer to here. Chris' code introduces event
> > "bubbling" from inside the Editor, I'm proposing event "bubbling" from
> > the outside in. I'd say both suggestions are equally "bubbly", but Spy
> > is more generally useful.
>
> Yeah, so I think we cannot escape the fundamental nature of events. They
> are logically "consumed" by some widgets. We need a way to map events to
> widgets (which we have), and we need a way to determine which events that
> widget consumed (what we're working on now). Ideally we can find a mechanism
> that is less complex than the JS model. My initial patch is definitely a
> specific case of bubbling that could be generalized.
>
> I think that we need a mechanism for a widget to emit unconsumed events,
> though it could be a great deal more general than what I implemented here.
> Perhaps we just allow a widget to push events it didn't use *back* into
> the queue in a way that marks them as "fair game" for other widgets?
>

Again, I suspect a nicer solution lies in InputOp filtering so events
are distributed before having to resort to hacks like Spy. Key events
just haven't received the same attention as pointer events (and pointer
events still need work to support use cases such as nested Lists).

Elias
Details
Message ID
<C6TT7RZN5C1K.3M9OYNJGAKT2V@vendetta>
In-Reply-To
<C6TOY6QT0MCX.1SX58AOECY13C@themachine> (view parent)
DKIM signature
pass
Download raw message
On Tue Nov 3, 2020 at 10:17 AM EST, Elias Naur wrote:
> On Tue Nov 3, 2020 at 07:49, Chris Waldon wrote:
> > On Mon Oct 26, 2020 at 2:09 PM EDT, Elias Naur wrote:
> > > On Mon Oct 26, 2020 at 11:13, Larry Clapp wrote:
> > > > (I haven't looked at Chris's code.)
> > > >
> > > > How would the Spy know which events were processed and which not?
> > > > What if you wrap a Spy around a Spy (around a Spy, around a Spy ...)?
> > > >
> > >
> > > The Spy doesn't, but you do. In other words, Spy is functionality, not
> > > convention. For example, you want to handle the escape key in a certain
> > > way,
> > > but only when directed at some widget. Spy is the tool.
> >
> > So the spy does seem like an interesting primitive to have, but I haven't
> > yet thought of an API for using it that I like. The problem is that, in
> > order to use the spy effectively, I need to know details of the implementation
> > of widgets. If I want to extend the editor's keyboard shortcuts using a spy,
> > I need to know which keys it already consumes. Otherwise, I may process a
> > keystroke that the editor also processed, and two effects will occur when
> > the user (reasonably) only wanted one.
> >
>
> Sure, but it seems to me your approach has the reverse problem: your
> custom action will not be invoked if the Editor wants it (now or in the
> future). That may be ok for some actions, but not all.
>
> That said, I'm not sure Spy belongs in the core either. It seems to me
> keyboard shortcuts should be resolved with InputOps similar to pointer
> events. Spy is a quick, yet general, approach to achieve your objective.

Given this comment, would you like for me to make a spy library in gio-extras?

Or should I submit a patch to core with this feature until we have something
better?

> > Additionally, if I'm trying to use the spy to examine the events for a
> > particular widget's tag, I must *know* the tag value that it uses. This
> > seems very much like an internal implementation detail. I often end up
> > writing widgets that use several tags for different kinds of events, and
> > higher-level code trying to handle events would need to know about all of
> > them.
> >
>
> Why do you need to know the tag(s)? Spy collects every event that flows
> through it, regardless of the tag. Its Event method takes a tag only to
> implement the Queue interface and to pass it on to the underlying Queue.

I just now realized that I have completely misunderstood how you intended
for a Spy to be used. They're meant to be more like an op.Stack, where you
create one, wrap the gtx Queue in it, then hand the gtx to a widget to
allow it to do its event processing. On the other side, you use your
AllEvents() method to view the events processed by the widget. The spy
simply copies events as they pass through it.

This would address my immediate need, and is a very simple way of doing so.

I was thinking that you were meant to replace the queue globally with it,
and so my comments came from me trying to figure out how to separate the
events of interest from a vast sea of all events for the whole frame.

The spy mechanism doesn't solve the question of whether the underlying
widget "used" an event, but I don't need that right now anyway.

Thanks for your patience in with me Elias! I feel very stupid. :D
>
> > > > Let's try not to reinvent the Javascript event model, if possible
> > > > (bubbling and cancelling and whatnot), which seems very complex.  (If
> > > > that's *not* possible, let's try to learn from it and/or other
> > > > toolkits' event models.)
> > > >
> > >
> > > I'm not sure what you refer to here. Chris' code introduces event
> > > "bubbling" from inside the Editor, I'm proposing event "bubbling" from
> > > the outside in. I'd say both suggestions are equally "bubbly", but Spy
> > > is more generally useful.
> >
> > Yeah, so I think we cannot escape the fundamental nature of events. They
> > are logically "consumed" by some widgets. We need a way to map events to
> > widgets (which we have), and we need a way to determine which events that
> > widget consumed (what we're working on now). Ideally we can find a mechanism
> > that is less complex than the JS model. My initial patch is definitely a
> > specific case of bubbling that could be generalized.
> >
> > I think that we need a mechanism for a widget to emit unconsumed events,
> > though it could be a great deal more general than what I implemented here.
> > Perhaps we just allow a widget to push events it didn't use *back* into
> > the queue in a way that marks them as "fair game" for other widgets?
> >
>
> Again, I suspect a nicer solution lies in InputOp filtering so events
> are distributed before having to resort to hacks like Spy. Key events
> just haven't received the same attention as pointer events (and pointer
> events still need work to support use cases such as nested Lists).

This is helpful context. Thanks!

Cheers,
Chris
Details
Message ID
<C6UCZSYH483O.226KWL1K1VUI2@themachine>
In-Reply-To
<C6TT7RZN5C1K.3M9OYNJGAKT2V@vendetta> (view parent)
DKIM signature
pass
Download raw message
On Tue Nov 3, 2020 at 12:37, Chris Waldon wrote:
> On Tue Nov 3, 2020 at 10:17 AM EST, Elias Naur wrote:
> > On Tue Nov 3, 2020 at 07:49, Chris Waldon wrote:
> > > On Mon Oct 26, 2020 at 2:09 PM EDT, Elias Naur wrote:
> > > > On Mon Oct 26, 2020 at 11:13, Larry Clapp wrote:
> > > > > (I haven't looked at Chris's code.)
> > > > >
> > > > > How would the Spy know which events were processed and which not?
> > > > > What if you wrap a Spy around a Spy (around a Spy, around a Spy ...)?
> > > > >
> > > >
> > > > The Spy doesn't, but you do. In other words, Spy is functionality, not
> > > > convention. For example, you want to handle the escape key in a certain
> > > > way,
> > > > but only when directed at some widget. Spy is the tool.
> > >
> > > So the spy does seem like an interesting primitive to have, but I haven't
> > > yet thought of an API for using it that I like. The problem is that, in
> > > order to use the spy effectively, I need to know details of the implementation
> > > of widgets. If I want to extend the editor's keyboard shortcuts using a spy,
> > > I need to know which keys it already consumes. Otherwise, I may process a
> > > keystroke that the editor also processed, and two effects will occur when
> > > the user (reasonably) only wanted one.
> > >
> >
> > Sure, but it seems to me your approach has the reverse problem: your
> > custom action will not be invoked if the Editor wants it (now or in the
> > future). That may be ok for some actions, but not all.
> >
> > That said, I'm not sure Spy belongs in the core either. It seems to me
> > keyboard shortcuts should be resolved with InputOps similar to pointer
> > events. Spy is a quick, yet general, approach to achieve your objective.
>
> Given this comment, would you like for me to make a spy library in gio-extras?
>
> Or should I submit a patch to core with this feature until we have something
> better?
>

Yeah, let's let Spy simmer in gio-extras before including it in core.
Perhaps mention it in the newsletter?

Elias
Reply to thread Export thread (mbox)