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? Albrecht Schlosser May 13, 2021  
 
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.

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.

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, 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

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();

    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.

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.

        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...

        case FL_KEYBOARD:

This will only be triggered if the cell has the input focus, but you know that.

            switch(s) {

                case S_NORM:

As I wrote above, case S_NORM seems to be wrong because there are too many bit combinations and the user needs to activate NumLock. But it may be that that's what you want?

                case S_SHFT: cout << "brd state=shift" << endl; break;

                case S_CTRL: cout << "brd state=ctrl" << endl; return
                EVNOTHANDLED; // seems to be necessary for shortcuts

See "bug" below.

                case S_ALT: cout << "brd state=alt" << endl; break;

                // default: not currently coded

            } // end switch (state)

        break;
...
        case FL_RELEASE: case FL_MOVE: case FL_ENTER:// remainder of
        events are ignored

That comment is not true. These events are not handled, but they are not "ignored": see below.

        case FL_LEAVE: case FL_SHOW: case FL_HIDE:

        case FL_KEYUP: case FL_DRAG: case FL_ACTIVATE:

        case FL_DEACTIVATE: case FL_NO_EVENT:

        break;

        default: cout << "wha???" << endl;

    } // end switch(event)

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.

--
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/db070b2a-42b3-5af7-acc8-ef737b98e801%40online.de.
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'.