#Keypress while Dialog open

1 messages · Page 1 of 1 (latest)

fleet crest
#

gonna go ahead and thread this

#

could you show the full details of those objects?

strong heron
#

Sure

fleet crest
#

thanks for taking the time to debug this

strong heron
#

I may be getting confused about which event firing from the debugger is which, but I believe those are correct

fleet crest
#

isShift: false excuseeee me

#

oh my gosh we had a regression

#

(╯°□°)╯︵ ┻━┻

strong heron
#

Am I helping?

fleet crest
#

you're helping

#

I'ma write up a bug and push this fix right away

#

our next release is later this week, but if you want, you could modify the core files to apply the fix or hotpatch that method

strong heron
#

Okay, cool. If it helps at all, once this state is entered my boolean never gets set to 'false' no matter how many times I press the shift key.

fleet crest
#

yeah, because it would fail to match the action on up

#

do you know how to modify the core files?

strong heron
#

I know how to find foundry.js

fleet crest
#

replace getKeyboardEventContext with

  static getKeyboardEventContext(event, up = false) {
    const modifierKeycodes = [
      "Unidentified",
      "AltLeft",
      "AltRight",
      "ControlLeft",
      "ControlRight",
      "MetaLeft",
      "MetaRight",
      "OSLeft",
      "OSRight",
      "ShiftLeft",
      "ShiftRight",
      "Space"
    ];
    let pressed = event.key;

    // Map certain keys to their codes instead
    if ( modifierKeycodes.includes(event.code) || event.code.startsWith("Numpad") ) {
      pressed = event.code;
    }
    pressed = KeyboardManager.standardizeKey(pressed);

    /** @type KeyboardEventContext */
    let context = {
      key: pressed,
      action: "",
      event: event,
      isShift: event.shiftKey || (pressed === "SHIFT"),
      isControl: event.ctrlKey || event.metaKey || (pressed === "CONTROL"),
      isAlt: event.altKey || (pressed === "ALT"),
      hasModifier: false,
      modifiers: [],
      up: up,
      repeat: event.repeat
    };
    context.hasModifier = context.isShift || context.isControl || context.isAlt;
    if ( context.isShift ) context.modifiers.push("SHIFT");
    if ( context.isControl ) context.modifiers.push("CONTROL");
    if ( context.isAlt ) context.modifiers.push("ALT");
    return context;
  }
strong heron
#

Okay, I may have to wait until I've finished the game I'm running right now to implement that. 😛

strong heron
#

What changed there? I have pasted it in and it doesn't seem to have cured the bug, but I'm not sure I successfully saved over foundry.js while it was running.

#

I have this for it in sources:

static getKeyboardEventContext(event, up = false) {
    const modifierKeycodes = [
      "Unidentified",
      "AltLeft",
      "AltRight",
      "ControlLeft",
      "ControlRight",
      "MetaLeft",
      "MetaRight",
      "OSLeft",
      "OSRight",
      "ShiftLeft",
      "ShiftRight",
      "Space"
    ];
    let pressed = event.key;

    // Map certain keys to their codes instead
    if ( modifierKeycodes.includes(event.code) || event.code.startsWith("Numpad") ) {
      pressed = event.code;
    }
    pressed = KeyboardManager.standardizeKey(pressed);

    /** @type KeyboardEventContext */
    let context = {
      key: pressed,
      action: "",
      event: event,
      isShift: event.shiftKey || (pressed === "SHIFT"),
      isControl: event.ctrlKey || event.metaKey || (pressed === "CONTROL"),
      isAlt: event.altKey || (pressed === "ALT"),
      hasModifier: false,
      modifiers: [],
      up: up,
      repeat: event.repeat
    };
    context.hasModifier = context.isShift || context.isControl || context.isAlt;
    if ( context.isShift ) context.modifiers.push("SHIFT");
    if ( context.isControl ) context.modifiers.push("CONTROL");
    if ( context.isAlt ) context.modifiers.push("ALT");
    return context;
  }```
#

Actually, ignore that, it seems to be somewhat fixed now; it's still not releasing it on initially using that dialog, but subsequent shift-ups are now being detected.

strong heron
#

I'm going to manually set the boolean as off when I've done my thing to avoid it getting stuck on, anyway, but it does seem there's an issue in my particular circumstance with the onUp not being fired after my dialog is produced.

#

Okay, hmm, I notice that after my dialog renders and I do my thing, the button isn't deselecting either, which implies the button event isn't completing fully. I think that's the problem I still have.

#

That is, if I exit out of the dialog without selecting anything.

strong heron
#

@fleet crest I don't know if this is a bug or what, but if a button is left selected after its click event is fired (i.e. because the dialog wasn't re-rendered) it doesn't seem to trigger a keydown event if shift is pressed while the button is still focused.

#

Ummm?

#

Yeah, it's a bit hard to show you this, but if a button is focused, no keydown events are fired.

fleet crest
strong heron
#

I'll see what I can do shortly, but as far as I can tell if a click event is fired on a button and it remains focused after the event, this disables key events until you de focus the button. I'll be home from work in about an hour and will see if I can get a proof of concept working.

#

@nova ginkgo corroborated the same issue on the League discord.

fleet crest
#

thanks! that'd be appreciated

strong heron
#

@fleet crest Here you go. This macro - just click the demo button and while it's still focused see what happens while you press shift or any other button in the keybinding log. No activity whatsoever.

#
let content = `<h2>This is a demo button</h2><button type="button">DEMO</button>`;
let width = 400;
let height = 180;

new Dialog({
            title: `Roll a track`,
            content: content,
            buttons: {
                ok: {
                    label: game.i18n.localize("fate-core-official.OK"),
                    callback: async ()=> {
                       // Do the stuff here
                       console.log("You pressed the OK button");
                    }
                    }
                }
        },
        {
            width:width,
            height:height,
        }).render(true);```
#

As soon as you deselect the button, even if the dialog is open, events start firing again.

#

(I repurposed another macro, apologies for the bits that don't apply)

fleet crest
#

@strong heron thanks for this, I was able to replicate. The Dialog button being pressed counts as having Focus, so we discarded the keyevent. Although you probably shouldn't have a button that does nothing, it's something we can fix, and so will do so in the next release

strong heron
#

Hah, yes, well, I'm not saying it's a desirable effect in the first place, buuut...

#

In my case the button DOES do something, but I wasn't calling blur on the button afterwards. So if the user closed the dialog rather than pressing the buttons in it to do stuff, the button was staying focused as the application never re-rendered.

#

So I think there are legitimate situations where it could occur despite it not actually being a button that does nothing. 🙂

#

I'm just gonna bore you with the specific use case now...

This plus button pops up a dialog to select one or more aspects with free invokes to use to bolster the roll, if you press it with shift held. If they select one or more and hit 'okay' my system adds the bonus to the existing roll and re-renders the app, causing the button to be re-rendered and thus defocused.

If they closed the dialog out without selecting an aspect, the dialog exited without having done anything and the button retained focus. Then, if they clicked on it again with shift held down, once or repeatedly, it maintained the unexpected no-shift-held behaviour.

I've now added a blur event after the function is called so it gets defocused whatever happens, but it's an extra step and not one that's intuitive you'd need to add.

fleet crest
#

do you have submitOnClose: true on that dialog?

strong heron
#

I don't believe so, because it's not actually submitting anything via the standard Foundry workflow.

#

It does resolve() on close though.

#
let invokedAspects = await new Promise(resolve => {
                    new Dialog({
                        title: game.i18n.localize("fate-core-official.selectAspects"),
                        content: content,
                        buttons: {
                            ok: {
                                label: "OK",
                                callback: () => {
                                    resolve($('.free_i_selector'))
                                }
                            }
                        },
                        default:"ok",
                        close: () => resolve()
                    }).render(true);
                });```
#

@fleet crest SHOULD I have submitOnClose as true? 😛

fleet crest
#

uhh.. man, I don't know haha

strong heron
#

I was assuming not since I don't need to capture information such as would be the case with a submission workflow. I just grab the field's value with jquery.

fleet crest
#

why do you go that route instead of the submission workflow?

strong heron
#

Expediency, I guess. It was a lot less hassle to do it this way for a very simple application.

#

All I need is a selected aspect and number of free invokes.