Focus event on window object from CEF HtmlDialog Javascript?

Is there some information on the limitations of the JS window object from CEF HtmlDialog Javascript ?

I’m noticing silent fails for …

  • window.onfocus

ADD: The CEF API appears to have: Class CefFocusHandler … but may not be implemented for the SketchUp API UI::htmlDialog class.


FYI: Retitled topic to target Focus event. This thread has resulted in an API feature request:


Note:
The following I noticed but are unimportant for my needs or the main subject of this topic thread.

  • window.resizeBy()

  • window.resizeTo()

yes, if you search CEF issue tracker for window.resizeBy() you’ll see it’s deliberate and your Ruby generated dialog is playing the role of the ‘app’…

I bounce the size and position back to ruby and use set_size and set_position

there are also some anomalies because SU is still spoofing a Safari ‘navigator’ tag and CEF that triggers conditionals in the javascript…

john

Right, but this cannot work from within a JS drag operation as the JS --> Ruby is asynchronous.
(I tried it and there’s a funny chase the window edge around the screen comedy routine that results.)

Not that important for the sizing anyway. (Just two functions I noticed.)


What I really need is the window.onfocus so that I can refresh data in the dialog.

I’ve been faking it by setting the <body tabindex="0"> and then
setting up a document.body.onfocus = function, but this requires that the page be clicked in, and then causes the buttons at the bottom to need 2 clicks (the first goes to the body and gives it focus even though the buttons also naturally are in the tab order and I’ve explicitly given them a number tabindex attribute.

I just thought perhaps I’ll try onmouseout and onmousein next to eliminate the click confusion.


Might have to log another API feature request.

EDIT: Filed Issue #430

ADD: The CEF API appears to have: Class CefFocusHandler

this is what I use for focus/blur events,

a bit messy as I just pulled bits from a WIP…

'use strict';
// shorthand
// use rubies 'p()' for loging in js...
const p = console.log.bind( console );

window.addEventListener( 'DOMContentLoaded', ( event ) => {
  // window.addEventListener("resize", reactToHeight);
  //
  //
  document.addEventListener( 'mouseenter', ( e ) => { dlgFocus( e ) } ) // SU_Functions.js
  document.addEventListener( 'mouseleave', ( e ) => { dlgBlur( e ) } ) // start.js
  //
} 

//
function dlgBlur(e) {
  try {
    sketchup.blur_dlg()
  } catch (e) {
    // ...the execution
      p( "test dlgBlur() in chrome desktop..." )
    //! p( e.name );
    //! p( e.message );
    //! p( e.stack );
  }
}

//
function dlgFocus(e) {
  try {
    sketchup.focus_dlg()
  } catch (e) {
    // ...the execution
       p( "test dlgFocus() in chrome desktop..." )
    //! p( e.name );
    //! p( e.message );
    //! p( e.stack );
  }
}
      @dlg.add_action_callback('focus_dlg') do |_d|
       # @mats.purge_unused
        @dlg.show
      end
      
      @dlg.add_action_callback('blur_dlg') do |_d|
        path = Sketchup.active_model.path
        Sketchup.open_file(path) unless path.empty?
      end

john

this is a bad gif of what it does…

john

1 Like

I just want to chip in that mouse enter and mouse leave aren’t the same as window focus and blur. SketchUp 2016 or so blurred the Ruby dialog if the mouse left it, which meant that when selecting text in the console, you had to precisely stop moving the mouse after the text ended and before it left the window not to blur the window and lose focus of the newly selected text. This was extremely annoying! You would have the same result if you moved away the cursor not to have it cover the field you are writing. I would recommend to only use mouse enter/leave if the window is 100% click based, but even then it is a non-standard window behavior.

Right, and so the whole reason for this thread.

As I said above, the attempted workaround required a click in the body of the dialog (which is unnatural and causes issues.)

I need to try another workaround, as this click is interfering with the click on buttons at the bottom of the dialog. (Ie, … it’s button bar area.)

Click based? NO, it’s a tabular data display dialog and normally the mouse is only used to manipulate the scrollbar, perhaps size columns (if I implement this,) resize the window via gripping borders, click heading cells to set sort order, and click buttons in the lower “button bar” area.

It just so happens that the data list I’m implementing as an example has no observer that can fire a refresh. This scenario is likely to happen to others so I’ll need to file a request (for a block form UI::HtmlDialog#set_on_focus method.)

But in the meantime, I have to “hack” it with some kind of workaround, as the body click is a failure.

So, I have to discern somehow that the user themselves are focused on the dialog and any of the mouse manipulation events seems the best way, in the absence of being notified of the window regaining focus.

And yes, I did put a “Refresh” button on the lower left of the dialog.

It seems I may need to implement a timer workaround to check if data has changed

What causes the data to need refreshing in the first place?

Uh … it changes. :roll_eyes:

There are still quite a few things in the SketchUp Ruby ObjectSpace that do not have observers implemented to watch them. Application options (a lot of what you see in the Preferences dialog,) Attribute Dictionaries (other than generic onChangeEntity.) But it also could be external json data files, or Ruby memory objects (data hashes or arrays.)

I just happen to have stumbled upon an example where a button in the dialog opens another model dialog can make changes to the data displayed in the first dialog. When the 2nd modal dialog is closed, the previous dialog (in the application’s child window stack) happens to be the 1st dialog which is again given the focus.
I’d like to know when it loses focus and regains it, so I can check to see if data changed and update it if it was changed. If no change was made, then the dialog should do nothing.

Again, in this scenario there are no API observers that can be attached to the particular data to fire a callback.


To me it does not seem strange at all that this scenario exists. Ie, just the fact the JS window.onfocus and window.onblur exist means that others who came before me recognized this scenario. So if I need it, and others needed it before me, then others are likely to need it in the future.

ADD EVIDENCE: CEF API: Class CefFocusHandler


Now updating the display of data is not the only end use. A common pattern in JS is to only have EventListeners attached when your code really needs them. So it is commonpalce to have functions that attaches and detaches listeners based upon other events. (Ie, something is clicked, dragging begins, the window has focus, an element is being resized, etc. etc.)

Just a note to say that, I know that if a user clicks my dialog’s button to open the modal 2nd dialog, that I can begin a temporary timer to “watch” either a file or a data structure for changes. And when the user dismisses the 2nd modal dialog, I can stop the timer and see if changes occurred. If so do an update.

But, … this little button is not the only way the user could open the 2nd dialog. If they do it through SketchUp’s menu then it’s the main application window that gets the restored focus instead of my 1st dialog.

So workarounds will be not foolproof. It’d be so much easier if we just had an onfocus callback and I wouldn’t have to jump through hoops to prevent timers from running forever.

I’m a bit skeptical to having the window update on hover (or even focus for that matter). You could easily read outdated values by forgetting to hover/focus the window.

I’d look into using observers when possible, use a library to listen to file updates, explicitly call an update method when setting the values from other places (e.g. other windows) or use custom setter methods that not only set the value but also update the window if visible. Or make the window modal and not allow the user to interact elsewhere while it is open.

Why? It means (we can assume) the user is themselves focused on the dialog.
Secondly, the window currently reloads, but I’m rewriting it to only refresh the data from the Ruby side.
And the table then is “redrawn” from the reloaded internal JS data object.

Read? I’m not reading anything from the window. It’s a data table display dialog.

I have no ability to “focus” or “hover” the window, either SketchUp or the user is doing this.
I simply would like to react to these events, so that I can check the data source, and know whether my Rubyside needs to reread the data, format it for display and pass it on over to the JS side as a json object definition. So, hence the need for a real working window.onfocus event.

As I said (above) there is no observer that can watch this data.

You are over complicating the issue. I don’t need a library.
I can hold a snapshot of the data on the Ruby side, and use comparison to see if there’s a change.
I can even first do a quick check on the size, whether it’s in memory or a file on disk (which can also be simply checked for modtime.)

I do not have control of the other window ! It’s not mine … It’s native !

The setter methods are in the core, … and have no idea that my dialog is displaying the data !

Bad idea. It is a reference window.


Obviously you do not understand the situation, and are just arguing for arguments sake.

observers obviously don’t work the same on windows…

adding them is not ‘best practice’ in the mac version of SU…

there are already too many and they break things…

in my code the mouse enter simply notifies Ruby and it dictates what happens next…

dlg.open is only one possible event, and I sometime use to reposition or resize the dlg or inject new javascript…

resizing the dialog manually is the only real issue I’ve encountered, but that can also be done with a javascript to ruby call…

john

When possible. I also listed several other hooks for data being changed.

I’m talking about the user reading the outdated data because they didn’t knew they had the hover the dialog for the data to be correct.

With wrong data until the user has hovered or focused it? Imagine if Entity Info didn’t update when the underlying value update, but when being hovered or focused.

You don’t need to be rude. You could try actually explaining the situation first. So far you have only mentioned implementation.

I asked a question, and John answered the question. I don’t really need help with any workaround (and did not actually ask for it.) You cut into the thread and began an argument using words such as “skeptical” casting doubt on what I’m doing without knowing what I’m doing.

You are disrespectful toward me and I am going to stop communicating with you now. (Muted.)