FLTK logo

Re: [fltk.general] What is the right way to do these shortcuts?

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.general  ]
 
Previous Message ]New Message | Reply ]Next Message ]

Re: What is the right way to do these shortcuts? Dave Jordan May 13, 2021  
 

Thanks, Albrecht, for putting in as much effort as is apparent here.
Below are comments, clarifications, and a few much simpler questions.

On Thu, May 13, 2021 at 4:49 AM Albrecht Schlosser <AlbrechtS.fltk@online.de> wrote:
On 5/12/21 12:13 PM Dave Jordan wrote:
> This method works except for 1 UI flaw and 1 obvious inefficiency, both
> of which are described under switch(e)

Others did already reply with some good stuff, hence I'm trying to be
short and precise with other technical info.

> I know can't be doing it quite right. I have tried test_shortcut; no
> idea whether it's appropriate or what is the correct usage.

Please describe what you want to achieve, this would make it easier to
understand what doesn't work.

> All the shortcuts keys are created here
>
> class Appmenu : public Fl_Menu_Bar {
...

Okay, that should work.

> App *app also contains an Fl_Group which contains > 200 subclassed Fl_Boxes.
> I have written no explicit event handling in the Fl_Group.
> If I do, the Group is going to get /all/ the events before the Boxes do,
> and that will open a whole 'nother can of worms.

Why? It could really be helpful if the group would get the events before
the children so you could filter yourself which events to propagate to
the children and which not to propagate.

The can of worms is not the potential usefulness or lack thereof but merely the extra work i would have of going back thru all the modules
and getting the new object references correct. I could see it maybe as a necessity if i think of some new feature that won't work otherwise...
> class Cell : public Fl_Box {
>
>     int handle(int e) { return brd_handle(this, e); }
>     static int brd_handle(Cell *cell, int e);

As Greg wrote, that's an unnecessary extra step, you don't need the
static method brd_handle(). Just use Cell::handle() for your stuff.

I have the vague idea that i'm telling the compiler not to include all the handling code in every instantiation. i have seen statically declared methods in fltk examples before .
> int Cell::brd_handle(Cell *cell, int e) {
>
>     #define S_NORM 0x100000 // raw bits of event states. to do: also
>     detect capslock
>     #define S_SHFT 0x110000
>     #define S_CTRL 0x140000
>     #define S_ALT 0x180000

*NEVER* do this, i.e. define your own macros with explicit bit values,

saw that coming!
use the symbolic names instead. That's why they are defined. Additional
information: we recently discussed /changing/ some of these bit values
which would break your code because you used bit numbers!

So "translating your code back" to defined names:

#define S_NORM FL_NUM_LOCK // raw bits ...
#define S_SHFT (FL_NUM_LOCK | FL_SHIFT)
#define S_CTRL (FL_NUM_LOCK | FL_CTRL)
#define S_ALT  (FL_NUM_LOCK | FL_ALT)

Note that these bits are intended to be used to test if a particular bit
is set (i.e. a key is pressed or ON (NumLock)). You are testing all
these states for exact values which would fail, for instance, if a user
holds a mouse button pressed while typing a key. That's not unusual,
BTW, I have an application where I can press keys while dragging the mouse.

I also don't understand why you defined

   #define S_NORM 0x100000

This bit is defined in Enumeration.H:

   #define FL_NUM_LOCK     0x00100000

i must have had numlock on while i was generating those bit values. Definitely not what i meant to do.
but they're all gone for not being so useful after all, and for the reasons you stated. I do have enough training to know
it wasn't kosher in the first place :)
 
According to your logic below you require NumLock to be active for every
FL_KEYBOARD event you handle (?). That seems wrong, but see above: you
didn't describe /what/ exactly you want to achieve...

>     int s = Fl::event_state();

So, given the bit structure of the defined constants you might at least
want to change this to

       int s = Fl::event_state() & (FL_NUM_LOCK|FL_SHIFT|FL_CTRL|FL_ALT);
 
which would ignore all other state bits than those you're interested in
(leaving the rest of your tests as-is).

>     int k = Fl::event_key();

what if i want ctrl-x but not alt-x and not ctrl-alt-x?

>     switch(e) {
>
>         // The inefficiency is here in FL_SHORTCUT: every sibling cell
>         is checked to see if it will handle the shortcut.

This is intended. It may not be obvious but that's how shortcuts work.
yes i saw in the docs how FLTK "tries really hard" and its good.

Here it /might/ be useful to implement the handle() method of the parent
group so you can filter events and don't propagate FL_SHORTCUT events to
the children if you really care about that "inefficiency".

>         // And i suppose this is also the source of the UI problem,
>         wherein after all the searching about, if a shortcut
>         function involves another
>
>         // cell taking focus, the old cell will not receive FL_UNFOCUS
>         (leaving it highlighted).

Hmm, I believe this /should/ work. If you call take_focus() and the
focus is assigned to the other cell the current Fl::focus() widget
should IMHO get the FL_UNFOCUS event.

there is something in one of the functions that causes a cell to "forget it has the focus"
i have a workaround for now, and i may become moot soon b/c i think i know what it is.
Ok i just checked and the save() function calls the deactivate method of the container for the cells. that seems like it could do it.
will test and get back.

>         case FL_SHORTCUT: return EVNOTHANDLED; // also need ctrl+key to
>         return nothandledfor shortcuts to work

As Greg already wrote, you should only add cases for events you want to
handle. But see below for another bug...

 
Here's the bug I mentioned before:

The events you want to be ignored by using 'break;' transfer control
after the switch statement and thus

>     return EVHANDLED;

which tells FLTK that you /handled/ the event. That means that the event
is actually _dropped without handling_ it at all and it can't be handled
by any other widget. If that's what you mean with "ignored", well, then
yes, but that's in FLTK event handling two different things and you
should be aware of this.

right, i had those "ignored" cases there so i could see "interesting" event names without scrolling thru hundreds of FL_ENTER and FL_LEAVE
which are irrelevant to everything so far in my UI design.

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/CAPdW6bKQ%2BoVTWnec%2B8xzhkWU5CEdnwS2A2moJbK5D5MrJ81ViA%40mail.gmail.com.
Direct Link to Message ]
 
     
Previous Message ]New Message | Reply ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.