Text input and key down events

I have a GUI program that listens for both key down and text input
events. The intended behavior is that each key is processed exactly
once, by exactly one GUI widget. However, when the user presses the the
’1’ key (or any other text input key), it can be processed twice: once
as a text input event by a text input widget and once as a shortcut key
by another widget. The text input widget cannot consume the key down
event because it can’t match the key down event to the corresponding
text input event.

What is the recommended way to handle this? Is there a way to detect if
a particular key down event is used for text input so that I can
suppress these events while listening for text input?–
Rainer Deyke - rainerd at eldwood.com

As a temporary hack, I am setting the text input widget to consume all
key down events where the keysym is in unicode range (i.e. 30th bit not
set), unless either ctrl or alt is pressed. This seems to work.On 2/20/2011 00:42, Rainer Deyke wrote:

I have a GUI program that listens for both key down and text input
events. The intended behavior is that each key is processed exactly
once, by exactly one GUI widget. However, when the user presses the the
’1’ key (or any other text input key), it can be processed twice: once
as a text input event by a text input widget and once as a shortcut key
by another widget. The text input widget cannot consume the key down
event because it can’t match the key down event to the corresponding
text input event.

What is the recommended way to handle this? Is there a way to detect if
a particular key down event is used for text input so that I can
suppress these events while listening for text input?


Rainer Deyke - rainerd at eldwood.com

Why is that a hack?

The way I handle it is to define a general widget type (structure or class,
depending on language). Then each widget (text input, text output, file
selector, etc) attaches callbacks for the types of events they need to
handle. Events are processed by passing them to a processCallBack function
which runs through the widget list and passes the event to the callback
function for the topmost widget in the list that has registered a callback
function for that type of event. The widget that processes the event then
becomes the topmost widget.

The one exception is for an alert or error widget. If one is active, it is the
topmost widget and all events except for SDLQuit are passed to it. That just
means that nothing else will get done until the user responds to the error
widget.

If you think that might be useful for your application, contact me off list
and I’ll send you the code (specify whether you prefer .zip or .tar.gz
format).

JeffOn Monday 21 February 2011 12:15, Rainer Deyke wrote:

On 2/20/2011 00:42, Rainer Deyke wrote:

I have a GUI program that listens for both key down and text input
events. The intended behavior is that each key is processed exactly
once, by exactly one GUI widget. However, when the user presses the the
’1’ key (or any other text input key), it can be processed twice: once
as a text input event by a text input widget and once as a shortcut key
by another widget. The text input widget cannot consume the key down
event because it can’t match the key down event to the corresponding
text input event.

What is the recommended way to handle this? Is there a way to detect if
a particular key down event is used for text input so that I can
suppress these events while listening for text input?

As a temporary hack, I am setting the text input widget to consume all
key down events where the keysym is in unicode range (i.e. 30th bit not
set), unless either ctrl or alt is pressed. This seems to work.

The way I handle it is to define a general widget type (structure or class,
depending on language). Then each widget (text input, text output, file
selector, etc) attaches callbacks for the types of events they need to
handle. Events are processed by passing them to a processCallBack function
which runs through the widget list and passes the event to the callback
function for the topmost widget in the list that has registered a callback
function for that type of event. The widget that processes the event then
becomes the topmost widget.

That’s quite a sane algorithm, although it has one problem: callbacks.
Hard to avoid in C.

Callbacks suck because you lose the stack: your per-widget code becomes
a slave of the event loop.

There are two ways around this. One is to use threads. This also sucks
because it is overkill (consumes resources).

The other is to use a better language :slight_smile: I think (not sure) Go has channels
and fibres but allow me to show you the code I use in Felix:

proc dispatch_event(
keyboard:schannel[SDL_keysym],
active:schannel[SDL_ActiveEvent],
resize:schannel[SDL_ResizeEvent]
)
{
whilst true do
var e : SDL_Event;
poll_event(&e);
match get_type e with
| ?et when et == SDL_ACTIVEEVENT=>
{ write (active, e.active); }

| ?et when et == SDL_VIDEORESIZE=>
  { write (resize, e.resize); }

| ?et when et == SDL_KEYDOWN=>
  { write (keyboard, e.key.keysym); }

| ?et when et == SDL_QUIT=>
  { Quit 0; }

| _ => {}
endmatch;

done;
}

Notice that this code does not seem to be invoking a callback.
It calls a routine to get an event and dispatches the event down
one of two channels.

Here’s is the resizing code:

proc resizechan(x:schannel[SDL_ResizeEvent])
{
whilst true do
handle_resize$ read x;
done;
}

The program units are modular, they all have a stack with
local variables (or so it seems …). They have the look and
feel of threads.

But they’re not. The execution model of the underlying code
is callbacks. (Actually C++ classes with resume() method).
The compiler control-inverts the code, that is it turns it inside
out: it takes code that “thinks” it is the master and turns it into
slave code.

It’s a great pity some of the API’s SDL uses are forced to be callback
driven (Audio I believe). The really big advantage of SDL is that
it is a library NOT a framework that forces you to do everything with
callbacks.

BTW: to understand how important control inversion is, think about parsing
a file with a subroutine called with a single character at a time, as opposed to
reading the data. When you read, you’re the master. When you’re called with
the data you’re a slave.

When you write C you’re using most important control-inversion
function on your computer: the operating system. Actual data from
your disk drive or network is delivered asynchronously and the OS
control inverts so the client application reads it under application
control: the application thinks it is the master.On 22/02/2011, at 8:38 AM, Jeff Post wrote:


john skaller
@john_skaller

Go has goroutines, which are like Windows fibres in that they are
application controlled rather than like threads which are OS scheduler
controlled.
http://golang.org/doc/go_spec.html#Go_statements

A channel is like a typed pipe. It can be used to send and receive
data between goroutines.
http://golang.org/doc/go_spec.html#Channel_types

You can find more documentation for Go here:
http://golang.org/doc/docs.htmlOn 21 February 2011 20:37, john skaller wrote:

The other is to use a better language :slight_smile: I think (not sure) Go has channels
and fibres but allow me to show you the code I use in Felix:

It’s a hack because I have no way to tell if I’m inadvertently consuming
key down events that are not used for text input, or if I’m
inadvertently failing to consume key down events that /are/ used for
text input. My algorithm for detecting if a key is used for text input
is based on guesswork and intuition, not actual knowledge. In fact, I’m
pretty sure that my algorithm is incorrect in some corner cases. For
example, it fails to consume the key down events for modifier keys that
are used for text input.

Even if my algorithm were correct, it would belong in SDL, not in user code.On 2/21/2011 14:38, Jeff Post wrote:

On Monday 21 February 2011 12:15, Rainer Deyke wrote:

On 2/20/2011 00:42, Rainer Deyke wrote:

I have a GUI program that listens for both key down and text input
events. The intended behavior is that each key is processed exactly
once, by exactly one GUI widget. However, when the user presses the the
’1’ key (or any other text input key), it can be processed twice: once
as a text input event by a text input widget and once as a shortcut key
by another widget. The text input widget cannot consume the key down
event because it can’t match the key down event to the corresponding
text input event.

What is the recommended way to handle this? Is there a way to detect if
a particular key down event is used for text input so that I can
suppress these events while listening for text input?

As a temporary hack, I am setting the text input widget to consume all
key down events where the keysym is in unicode range (i.e. 30th bit not
set), unless either ctrl or alt is pressed. This seems to work.

Why is that a hack?


Rainer Deyke - rainerd at eldwood.com

That’s quite a sane algorithm, although it has one problem: callbacks.
Hard to avoid in C.
Callbacks suck because you lose the stack: your per-widget code becomes
a slave of the event loop.

Not a problem in the applications I write. Don’t know about games though since
I don’t write games.

The other is to use a better language :slight_smile: I think (not sure) Go has channels
and fibres but allow me to show you the code I use in Felix:

Since I don’t know Felix I can’t comment on your code (to me, Felix is a cat
– ouch! I guess I’m showing my age :wink: Thanks anyway for providing the
example.

Notice that this code does not seem to be invoking a callback.
The program units are modular, they all have a stack with
local variables (or so it seems …). They have the look and
feel of threads.
But they’re not. The execution model of the underlying code
is callbacks.

Uh, okay. Then I fail to see the difference.

It’s a great pity some of the API’s SDL uses are forced to be callback
driven (Audio I believe). The really big advantage of SDL is that
it is a library NOT a framework that forces you to do everything with
callbacks.

That’s one of many things I like about SDL.

BTW: to understand how important control inversion is, think about parsing
a file with a subroutine called with a single character at a time, as
opposed to reading the data. When you read, you’re the master. When you’re
called with the data you’re a slave.

Funny you should mention that. My latest application does read a file one
character at a time because it needs to parse files written on Linux (LF only
newline), Windows (CR/LF newline), and Mac (CR only newline). Whether it does
so as master or slave is not relevant to the application.

JeffOn Monday 21 February 2011 17:37, john skaller wrote:

It’s a hack because I have no way to tell if I’m inadvertently consuming
key down events that are not used for text input, or if I’m
inadvertently failing to consume key down events that /are/ used for
text input. My algorithm for detecting if a key is used for text input
is based on guesswork and intuition, not actual knowledge. In fact, I’m
pretty sure that my algorithm is incorrect in some corner cases. For
example, it fails to consume the key down events for modifier keys that
are used for text input.

Okay. Without seeing your code I have no way of knowing if my code would be of
use to you. Thought it would be nice to offer you my code though, in case you
might find it useful.

Even if my algorithm were correct, it would belong in SDL, not in user
code.

You might be right, but the biggest advantage I see in SDL is that it doesn’t
force any particular methodology on developers. It merely provides a platform
independent way to access low-level functions.

My offer still stands. Use what might be of use to you and disregard the rest.

JeffOn Monday 21 February 2011 19:11, Rainer Deyke wrote:

It’s a hack because I have no way to tell if I’m inadvertently consuming
key down events that are not used for text input, or if I’m
inadvertently failing to consume key down events that /are/ used for
text input. My algorithm for detecting if a key is used for text input
is based on guesswork and intuition, not actual knowledge. In fact, I’m
pretty sure that my algorithm is incorrect in some corner cases. For
example, it fails to consume the key down events for modifier keys that
are used for text input.

Okay. Without seeing your code I have no way of knowing if my code would be of
use to you. Thought it would be nice to offer you my code though, in case you
might find it useful.

Here is the code I’m talking about:

    if (!(key & 0x20000000) && !(mod & (KMOD_CTRL | KMOD_ALT))) {
      return true;
    }

Even if my algorithm were correct, it would belong in SDL, not in user
code.

You might be right, but the biggest advantage I see in SDL is that it doesn’t
force any particular methodology on developers. It merely provides a platform
independent way to access low-level functions.

Detecting if a given keyboard input event is linked to text input is
basic, low-level stuff. There is way to clean way to implement it on
top of the API SDL provides.On 2/21/2011 21:02, Jeff Post wrote:

On Monday 21 February 2011 19:11, Rainer Deyke wrote:


Rainer Deyke - rainerd at eldwood.com

That’s quite a sane algorithm, although it has one problem: callbacks.
Hard to avoid in C.
Callbacks suck because you lose the stack: your per-widget code becomes
a slave of the event loop.

Not a problem in the applications I write. Don’t know about games though since
I don’t write games.

i don’t mean to be offensive but …

“I am fine with assembler I don’t need high level languages”

“I think gotos are just fine, I don’t need block structured programming languages”

“Procedural code is fine, I don’t need functional programming”

“I am happy with object orientation”.

“I am fine with callbacks”

Its all the same. You don’t understand why what you’re doing is bad, you’re
used to it and you think it is ok.

It isn’t OK.

The other is to use a better language :slight_smile: I think (not sure) Go has channels
and fibres but allow me to show you the code I use in Felix:

Since I don’t know Felix I can’t comment on your code (to me, Felix is a cat
– ouch! I guess I’m showing my age :wink:

Felix is indeed a cat. – ouch I guess I’m showing mine :slight_smile:
[If Guido can name his language after a snake I can use a cat :]

But they’re not. The execution model of the underlying code
is callbacks.

Uh, okay. Then I fail to see the difference.

You can’t see the difference between C and machine code?

It’s called automation: the compiler (in both cases) does a lot
of tedious housework for you and gets it right every time (hopefully :slight_smile:

BTW: to understand how important control inversion is, think about parsing
a file with a subroutine called with a single character at a time, as
opposed to reading the data. When you read, you’re the master. When you’re
called with the data you’re a slave.

Funny you should mention that. My latest application does read a file one
character at a time because it needs to parse files written on Linux (LF only
newline), Windows (CR/LF newline), and Mac (CR only newline). Whether it does
so as master or slave is not relevant to the application.

The issue isn’t whether you read the file one character at a time, but whether you read
the character or are called with it.

The differences is very relevant to the complexity of the code you write.
For example analysing expressions requires recursion. To do recursion you must
have a stack.

You can either use the machine stack, or you can EMULATE a stack, but you can’t
do it without a stack.

Emulating a stack is more work, and therefore more error prone, than using
one integrated into the programming language. But you can’t use the machine
stack if your code is a slave because the only way to get the next character
is to return control. If your code is a master you can read the next character
anywhere in the code, even inside a deeply nested recursive context.On 22/02/2011, at 2:51 PM, Jeff Post wrote:

On Monday 21 February 2011 17:37, john skaller wrote:


john skaller
@john_skaller

I’m not sure if I totally get your problem, but I’ll tell you my
approach to shortcuts.

The gui system keeps a list of the registered shortcuts. When a key
is pressed, the event is checked against these shortcuts. If it
matches one, then the event stops there and the shortcut is activated.
Otherwise it goes on to be processed by the widget which currently
has keyboard focus.

Jonny DOn Tue, Feb 22, 2011 at 1:56 AM, Rainer Deyke wrote:

On 2/21/2011 21:02, Jeff Post wrote:

On Monday 21 February 2011 19:11, Rainer Deyke wrote:

It’s a hack because I have no way to tell if I’m inadvertently consuming
key down events that are not used for text input, or if I’m
inadvertently failing to consume key down events that /are/ used for
text input. ?My algorithm for detecting if a key is used for text input
is based on guesswork and intuition, not actual knowledge. ?In fact, I’m
pretty sure that my algorithm is incorrect in some corner cases. ?For
example, it fails to consume the key down events for modifier keys that
are used for text input.

Okay. Without seeing your code I have no way of knowing if my code would be of
use to you. Thought it would be nice to offer you my code though, in case you
might find it useful.

Here is the code I’m talking about:

? ? ? ?if (!(key & 0x20000000) && !(mod & (KMOD_CTRL | KMOD_ALT))) {
? ? ? ? ?return true;
? ? ? ?}

Even if my algorithm were correct, it would belong in SDL, not in user
code.

You might be right, but the biggest advantage I see in SDL is that it doesn’t
force any particular methodology on developers. It merely provides a platform
independent way to access low-level functions.

Detecting if a given keyboard input event is linked to text input is
basic, low-level stuff. ?There is way to clean way to implement it on
top of the API SDL provides.


Rainer Deyke - rainerd at eldwood.com


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

OK, this isn’t really my thread, but I’ve been watching it, and the more you
say,
the more confused I become. And this last post seems to have devolved into
pure gibberish.

That’s quite a sane algorithm, although it has one problem: callbacks.
Hard to avoid in C.
Callbacks suck because you lose the stack: your per-widget code becomes
a slave of the event loop.

Not a problem in the applications I write. Don’t know about games though since

I don’t write games.

i don’t mean to be offensive but …

“I am fine with assembler I don’t need high level languages”

“I think gotos are just fine, I don’t need block structured programming
languages”

“Procedural code is fine, I don’t need functional programming”

“I am happy with object orientation”.

“I am fine with callbacks”

Its all the same. You don’t understand why what you’re doing is bad, you’re
used to it and you think it is ok.

It isn’t OK.

So then, if I’m parsing your viewpoint correctly, “OOP = bad, functional
programming = good, callbacks = bad”?

…huh?

You do know that callbacks (AKA the use of higher-order functions) are one of
the most fundamental aspects of functional programming, don’t you?

BTW: to understand how important control inversion is, think about parsing
a file with a subroutine called with a single character at a time, as
opposed to reading the data. When you read, you’re the master. When you’re
called with the data you’re a slave.

Funny you should mention that. My latest application does read a file one
character at a time because it needs to parse files written on Linux (LF only

newline), Windows (CR/LF newline), and Mac (CR only newline). Whether it does

so as master or slave is not relevant to the application.

The issue isn’t whether you read the file one character at a time, but whether
you read
the character or are called with it.

The differences is very relevant to the complexity of the code you write.
For example analysing expressions requires recursion. To do recursion you must
have a stack.

You can either use the machine stack, or you can EMULATE a stack, but you can’t
do it without a stack.

Emulating a stack is more work, and therefore more error prone, than using
one integrated into the programming language. But you can’t use the machine
stack if your code is a slave because the only way to get the next character
is to return control. If your code is a master you can read the next character
anywhere in the code, even inside a deeply nested recursive context.

That depends entirely on the complexity of the grammar you’re using. For a
lexer
(tokenizer,) being called one character at a time is perfectly reasonable, if a
bit
slower than optimal, and no stack is required. For a parser, yes, you’re right,
you
should have a stream of tokens available that you can ask for the next token
when
you need it, but it doesn’t sound like he’s actually describing a recursive
parser.

There’s nothing inherently bad about callbacks. For a lot of things, they
greatly
simplify the work you need to do. For others, they’re not appropriate for the
task,
so you use some other technique instead.>----- Original Message ----

From: john skaller
Subject: Re: [SDL] text input and key down events
On 22/02/2011, at 2:51 PM, Jeff Post wrote:

On Monday 21 February 2011 17:37, john skaller wrote:

So then, if I’m parsing your viewpoint correctly, “OOP = bad, functional
programming = good, callbacks = bad”?

…huh?

You do know that callbacks (AKA the use of higher-order functions) are one of
the most fundamental aspects of functional programming, don’t you?

Yes, and often it sucks. There is a difference or two though… in most FPLs
callbacks have a context so its a bit better: the callback is a closure, not
just a context-less function (as in C).

That depends entirely on the complexity of the grammar you’re using. For a
lexer
(tokenizer,) being called one character at a time is perfectly reasonable, if a
bit
slower than optimal, and no stack is required.

It’s only reasonable if the lexer is generated by a tool, which builds
a finite state automaton, or at least an NFA.

For a parser, yes, you’re right,
you
should have a stream of tokens available that you can ask for the next token
when
you need it, but it doesn’t sound like he’s actually describing a recursive
parser.

No, of course not, I just gave that as an example.

There’s nothing inherently bad about callbacks.

There’s nothing inherently bad about assembler or using gotos either.
It’s only bad if you this kind of technology when there’s something better.

For a lot of things, they
greatly
simplify the work you need to do. For others, they’re not appropriate for the
task,
so you use some other technique instead.

I agree. Callbacks are only useful if the state machine they can conveniently
implement via a single client data object are simple.

The problem isn’t callbacks (Felix has callbacks! and as you point out
HOF’s often use callbacks). The problem is when you’re forced to use
them by a framework and your problem is complex enough you demand
the tools of higher level systems: modularity, integrated data and control
flow using a stack, and if you go even higher level you need things like
garbage collection for memory management.

Obviously for simple jobs assembler is just fine.

Most (non-arcade) games and GUI applications are complex enough that
callbacks alone just won’t do.

My point is not that assembler, gotos, procedural code, or OO are bad:
my point is that they’re limited. And a second point needs to be made:
better technology like fibres can’t be implemented without compiler
support. You can’t do block structured programming in assembler
even though you can emulate the principles. You can’t do OO in C,
even though you can emulate it. You can’t do real functional
programming in C++. And you can’t do coroutines
without language support either.

Game programmers are the worst hit by bad technology because games
are the most sophisticated and difficult application around. Which is why
most games are so deficient in many ways … most “so called” strategy games
have hardly any strategy in them, their unit routing algorithms are non-existent
or suck totally – even though good algorithms exist – because the programmers
spend most of their time struggling to implement basic stuff without error,
because the tools they’re using aren’t up to the job.On 23/02/2011, at 1:02 AM, Mason Wheeler wrote:


john skaller
@john_skaller

So then, if I’m parsing your viewpoint correctly, “OOP = bad, functional
programming = good, callbacks = bad”?

…huh?

You do know that callbacks (AKA the use of higher-order functions) are one of
the most fundamental aspects of functional programming, don’t you?

Yes, and often it sucks. There is a difference or two though… in most FPLs
callbacks have a context so its a bit better: the callback is a closure, not
just a context-less function (as in C).

Good point. I’m used to using Delphi, where callbacks are usually
implemented as method pointers, which are basically simple closures that
provide an object for context. SDL uses a similar principle for its callbacks,
putting a user-defined data pointer as part of the signature for a callback.

That depends entirely on the complexity of the grammar you’re using. For a
lexer
(tokenizer,) being called one character at a time is perfectly reasonable, if a

bit
slower than optimal, and no stack is required.

It’s only reasonable if the lexer is generated by a tool, which builds
a finite state automaton, or at least an NFA.

OK, you lost me again. Parser generation I can understand, but a lexer is dead
simple to hand-roll. I wrote a lexer just a few weeks ago. It took a couple
hours
to write and about 10 minutes to debug. Weighs in at a bit under 400 lines of
code for the business logic, plus a keyword table. Child’s play.

There’s nothing inherently bad about callbacks.

There’s nothing inherently bad about assembler or using gotos either.
It’s only bad if you this kind of technology when there’s something better.

I assume you’re still talking about C callbacks with no context here? Also, why
do you keep ragging on ASM? The structured programming theorems prove
that you can write any program without gotos, but there are some things that
simply can’t be done without the use of inline assembly, and IMO any language
with no support for it is crippled.

The problem isn’t callbacks (Felix has callbacks! and as you point out
HOF’s often use callbacks). The problem is when you’re forced to use
them by a framework and your problem is complex enough you demand
the tools of higher level systems: modularity, integrated data and control
flow using a stack, and if you go even higher level you need things like
garbage collection for memory management.

Any examples? I’ve never run across a scenario where a framework forces
you to use a callback for a situation that’s not appropriate for one and it ends
up getting in the way.

Also, WRT garbage collection, I’ve never encountered any programming
problem, no matter how “high-level,” that required it. I consider garbage
collection one of the worst misfeatures of all time. It’s only “necessary” in
functional languages because they’re designed very poorly, based on
fundamental principles such as “let’s pretend we’re not really running
on a Turing machine.” The problem with GC is that it eliminates the
perception of the need to think about memory management, without
eliminating the actual need to think about memory management, thus
eliminating quite a bit of thinking that is still necessary. (See
http://tinyurl.com/9ngt74 and http://tinyurl.com/4pxr822 )

Obviously for simple jobs assembler is just fine.

Most (non-arcade) games and GUI applications are complex enough that
callbacks alone just won’t do.

I don’t know. At work I work on the most complex GUI application I’ve ever
seen. It weighs in at around 3.5 million lines of Delphi code, and if you live
in the USA and watch TV or listen to the radio, chances are it’s running your
station. And, being a GUI application, everything that happens gets kicked
off by an event handler, which is a callback with a method pointer.

My point is not that assembler, gotos, procedural code, or OO are bad:
my point is that they’re limited.

And functional programming isn’t? It’s difficult to even look at a serious
functional language like Lisp or Haskell without saying “this entire thing is
one big abstraction inversion!”

And a second point needs to be made: better technology like fibres can’t
be implemented without compiler support.

Sure it can. I just call the CreateFiber function and I’m good.
http://msdn.microsoft.com/en-us/library/ms682402(v=vs.85).aspx

You can’t do block structured programming in assembler
even though you can emulate the principles. You can’t do OO in C,
even though you can emulate it. You can’t do real functional
programming in C++. And you can’t do coroutines
without language support either.

You know what the difference between doing something the “real” way,
with language support, and emulating the principles is? When it’s not
built into the language as a fundamental abstraction, you can debug
it, examine it, and find ways to improve it. When the language abstracts
all that away, you lose that ability.

That’s part of the reason why I like Delphi. You can do extremely high-level
stuff in it, including functional programming with real, language-supported
closures, but you can also go as low as you need to, all the way down to
inline ASM if necessary.

Game programmers are the worst hit by bad technology because games
are the most sophisticated and difficult application around. Which is why
most games are so deficient in many ways … most “so called” strategy games
have hardly any strategy in them, their unit routing algorithms are
non-existent
or suck totally – even though good algorithms exist – because the programmers
spend most of their time struggling to implement basic stuff without error,
because the tools they’re using aren’t up to the job.

Most of that can be laid at the feet of C++. If game programmers were smart,
they’d use a language with a real object model and decent OO semantics, and
half their trouble would vanish.>----- Original Message ----

From: john skaller
Subject: Re: [SDL] text input and key down events
On 23/02/2011, at 1:02 AM, Mason Wheeler wrote:

Since I am the one implemented text input events for SDL/Cocoa, here is
my comment about this issue:

I have definitely thought about this when I designed the API, however, SDL
on Mac works by intercepting key events in the lowest level (app event
dispatch queue) and send it to the application directly, while text
input events are somehow at a higher level, provided by NSView NSTextInput
protocol. So basically when we intercepting all the key events, we don’t
know which one of them is going to trigger text input events, so we
can’t selectively send or drop any one of them.

My suggestion is that you should disable text input events when you don’t
need them (like in a typical GUI toolkit, it will only accept text input
when the text cursor is focused in a certain text box), and when you do
need them, ignore most of the key events except the ones you can tell that’s
not going to be a text input (functional keys, ctrl/option key combination,
etc.)

  • JiangOn Tue, Feb 22, 2011 at 7:56 AM, Rainer Deyke wrote:

You might be right, but the biggest advantage I see in SDL is that it doesn’t
force any particular methodology on developers. It merely provides a platform
independent way to access low-level functions.

Detecting if a given keyboard input event is linked to text input is
basic, low-level stuff. ?There is way to clean way to implement it on
top of the API SDL provides.

I don’t think that’s offensive; I think it’s silly. You’re making assumptions
that aren’t valid.

JeffOn Tuesday 22 February 2011 05:41, john skaller wrote:

i don’t mean to be offensive but …

“I am fine with assembler I don’t need high level languages”

“I think gotos are just fine, I don’t need block structured programming
languages”

“Procedural code is fine, I don’t need functional programming”

“I am happy with object orientation”.

“I am fine with callbacks”

Its all the same. You don’t understand why what you’re doing is bad,
you’re used to it and you think it is ok.

It isn’t OK.

I’m not. I’ve written (simple) assemblers and compilers, so I know what
parsing is. In this application the “parsing” consists simply of separating a
text input line into specific fields, But it must do so in an OS independent
way.

I really don’t understand why John thinks master/slave is relevant here. The
user presses a key when he’s darned well and ready. Of course the application
is driven by the data–it can’t be otherwise. I think this conversation has
devolved into silliness.

JeffOn Tuesday 22 February 2011 06:02, Mason Wheeler wrote:

That depends entirely on the complexity of the grammar you’re using. For a
lexer
(tokenizer,) being called one character at a time is perfectly reasonable,
if a bit
slower than optimal, and no stack is required. For a parser, yes, you’re
right, you
should have a stream of tokens available that you can ask for the next
token when
you need it, but it doesn’t sound like he’s actually describing a recursive
parser.

You might be interested in Tame, which I think accomplishes something
close to your goal.

Which is part of the webserver that runs okcupid.com:
http://okws.org/doku.php?id=okwsOn 02/21/2011 06:37 PM, john skaller wrote:

On 22/02/2011, at 8:38 AM, Jeff Post wrote:

The way I handle it is to define a general widget type (structure or class,
depending on language). Then each widget (text input, text output, file
selector, etc) attaches callbacks for the types of events they need to
handle. Events are processed by passing them to a processCallBack function
which runs through the widget list and passes the event to the callback
function for the topmost widget in the list that has registered a callback
function for that type of event. The widget that processes the event then
becomes the topmost widget.

That’s quite a sane algorithm, although it has one problem: callbacks.
Hard to avoid in C.

Callbacks suck because you lose the stack: your per-widget code becomes
a slave of the event loop.

There are two ways around this. One is to use threads. This also sucks
because it is overkill (consumes resources).

The other is to use a better language :slight_smile: I think (not sure) Go has channels
and fibres but allow me to show you the code I use in Felix:

proc dispatch_event(
keyboard:schannel[SDL_keysym],
active:schannel[SDL_ActiveEvent],
resize:schannel[SDL_ResizeEvent]
)
{
whilst true do
var e : SDL_Event;
poll_event(&e);
match get_type e with
| ?et when et == SDL_ACTIVEEVENT=>
{ write (active, e.active); }

| ?et when et == SDL_VIDEORESIZE=>
  { write (resize, e.resize); }

| ?et when et == SDL_KEYDOWN=>
  { write (keyboard, e.key.keysym); }

| ?et when et == SDL_QUIT=>
  { Quit 0; }

| _ => {}
endmatch;

done;
}

Notice that this code does not seem to be invoking a callback.
It calls a routine to get an event and dispatches the event down
one of two channels.

Here’s is the resizing code:

proc resizechan(x:schannel[SDL_ResizeEvent])
{
whilst true do
handle_resize$ read x;
done;
}

The program units are modular, they all have a stack with
local variables (or so it seems …). They have the look and
feel of threads.

The program units are modular, they all have a stack with
local variables (or so it seems …). They have the look and
feel of threads.

You might be interested in Tame, which I think accomplishes something
close to your goal.
http://pdos.csail.mit.edu/papers/tame-usenix07.pdf

However it seems Tame is used to manage real concurrency?On 23/02/2011, at 3:55 AM, jon wrote:


john skaller
@john_skaller

My problem is simple. When I press the ‘a’ key I get two events from
SDL: a key down event (SDLK_a) and a text input event (“a”). Widget A
listens for text input events; widget B listens for key down events.
Widget A has priority over widget B. I need to get widget A to consume
all key down events that are used for text input to prevent the same key
from being processed twice, once as a key down event and once as a text
input event. The problem is accurately identifying the key down events
that are used for text input.

My current strategy is for widget A to consume all key down events where
the keysym is in the unicode range and neither ctrl nor alt is pressed.
This is a heuristic that /seems/ to work, but is probably inaccurate.

What I want is simple and accurate way to identify key down events that
are used for text input.

Actually dispatching the events to the widgets is trivial. The only
difficulty is identifying which events should be dispatched and which
should be consumed.On 2/22/2011 06:42, Jonathan Dearborn wrote:

I’m not sure if I totally get your problem, but I’ll tell you my
approach to shortcuts.


Rainer Deyke - rainerd at eldwood.com