SketchUp / api-issue-tracker

Public issue tracker for the SketchUp and LayOut's APIs
https://developer.sketchup.com/
38 stars 10 forks source link

UI::HtmlDialog: another bug on Mac - Cannot launch a modal dialog from another dialog #526

Open Fredosixx opened 4 years ago

Fredosixx commented 4 years ago

Platform: Mac OSX only SU versions: All SU2017 to SU2020

Another big bug, with 2 side effects

if you launch a modal dialog box from another HtmlDialog window, say in an event click on a button, the modal dialog shows with NO HTML content and crashes Sketchup when closed. You need to launch the modal dialog box within a timer.

This can be tested with the following code

def test_modal_mac(modal=false)
    @count = 0
    test_modal_mac_sub(modal)
end

def test_modal_mac_sub(modal=false)
    #For Windows, as a start_timer with a modal dialog would repeat indefinitely
    @count += 1
    puts "LAUNCH count = #{@count}"
    return if @count > 2

    #HTML content
    html_text = ''
    html_text += %q(<!DOCTYPE HTML>)
    html_text += %q(<META http-equiv='Content-Script-Type' content='text/javascript'>)
    html_text += %q(<META http-equiv='Content-Type' Content='text/html; charset=UTF-8'>)
    html_text += "<button onclick='sketchup.onclick(true)'>Click Deferred launch</button><br><br>"
    html_text += "<button onclick='sketchup.onclick(false)'>Click Synchronous launch</button>"

    #Creating the HtmlDialog
    hsh = { :dialog_title => 'Test modal HtmlDialog', :preferences_key => modal.inspect.to_s }
    wdlg = UI::HtmlDialog.new hsh
    wdlg.set_position(0, 0) if modal
    wdlg.add_action_callback("onclick") do |action_context, deferred, p2| 
        puts "Launch dialog in Modal - deferred = #{deferred.inspect}"
        if deferred
            UI.start_timer(0) { test_modal_mac_sub(true) }
        else
            test_modal_mac_sub true
        end    
    end    
    wdlg.set_html html_text
    (modal) ? wdlg.show_modal : wdlg.show
end    

TEST 1 1) Launch test_modal_mac from the Ruby console 2) Click on the button 'Deferred launch' 3) The modal dialog (the same one actually) appears on the screen

TEST 2 [first, close the 2 dialogs] 1) Launch test_modal_mac from the Ruby console 2) Click on the button 'Synchronous launch' 3) The modal dialog appears with no content. It is simply NOT loaded. Worse, if you close it Sketchup crashes.

TEST 3 1) Launch test_modal_mac true from the Ruby console 2) this displays the dialog in modal This shows that the issue is when you launch a modal dialog box from another HtmlDialog

As side effects 1) On Mac, you CANNOT launch a modal dialog from another modal dialog, since timers are not executed by a modal dialog before it closes

2) On Windows, if you launch a modal dialog within a timer, then it is loaded indefinitely. This is an old bug which also exists when you execute UI.messagebox within a timer (but it odes not happen on Mac).

DanRathbun commented 4 years ago
  1. What happens if you give some interval other than 0 for the timer ? Ie, give Ruby time to return from the if statement and then the callback block, before the same method gets called recursively.

  2. What happens if the second dialog is created in another method. Ie, I think we should remove the possibility that this is a recursive method call "runaway" or lock up situation.

    def test_modal_mac_child(modal=false)
      wdlg = UI::HtmlDialog.new(
        dialog_title: "Child Dialog",
        preferences_key: "Test_Child_Dialog"
      )
      wdlg.set_position(100, 100)
      wdlg.set_html %[
      <!DOCTYPE html>
      <html>
          <body>
              <br><br>
              #{modal ? "Modal " : ""}Child Dialog
              <br><br>
          </body>
      </html>
      ]
      modal ? wdlg.show_modal : wdlg.show
    end
Fredosixx commented 4 years ago

1) Timer delay has no influence. Again, this WORKS with a timer, even with 0 delay

2) Using your Mac Two dialog gives the same result: the child modal dialog does NOT load (and crashes SU when you close it).


def test_modal_mac(modal=false)
    @count = 0
    test_modal_mac_sub(modal)
end

def test_modal_mac_sub(modal=false)
    #For Windows, as a start_timer with a modal dialog would repeat indefinitely
    @count += 1
    puts "LAUNCH count = #{@count}"
    return if @count > 2

    #HTML content
    html_text = ''
    html_text += %q(<!DOCTYPE HTML>)
    html_text += %q(<META http-equiv='Content-Script-Type' content='text/javascript'>)
    html_text += %q(<META http-equiv='Content-Type' Content='text/html; charset=UTF-8'>)
    html_text += "<button onclick='sketchup.onclick(true)'>Click Deferred launch</button><br><br>"
    html_text += "<button onclick='sketchup.onclick(false)'>Click Synchronous launch</button>"

    #Creating the HtmlDialog
    hsh = { :dialog_title => 'Test modal HtmlDialog', :preferences_key => modal.inspect.to_s }
    wdlg = UI::HtmlDialog.new hsh
    wdlg.set_position(0, 0) if modal
    wdlg.add_action_callback("onclick") do |action_context, deferred, p2| 
        puts "Launch dialog in Modal - deferred = #{deferred.inspect}"
        if deferred
            UI.start_timer(0) { test_modal_mac_two(true) }
        else
            test_modal_mac_two true
        end    
    end    
    wdlg.set_html html_text
    (modal) ? wdlg.show_modal : wdlg.show
end  

def test_modal_mac_two(modal=false)
  wdlg = UI::HtmlDialog.new(
    dialog_title: "Child Dialog",
    preferences_key: "Test_Child_Dialog"
  )
  wdlg.set_position(100, 100)
  wdlg.set_html %[
  <!DOCTYPE html>
  <html>
      <body>
          <br><br>
          #{modal ? "Modal " : ""}Child Dialog
          <br><br>
      </body>
  </html>
  ]
  modal ? wdlg.show_modal : wdlg.show
end  
Fredosixx commented 4 years ago

Here is a video illustrating the problem

1) Deferred : UI.start_timer(0) { test_modal_mac_two(true) }. It WORKS. The timer delay has no influence

2) Synchronous: test_modal_mac_two(true). BIG BUG.

Test Modal Mac

sketchupbot commented 3 years ago

Logged as: SKEXT-2803

mariocha commented 2 years ago

Fredo, can you confirm that such a modal (with timer) does suspend the ruby run until clicked and dismissed, like a UI.inputbox does ? I just learned that, on Mac, there are Document-Modal dialogs or App-Modal ones?

An alternative to count could be: Sketchup.platform =~ /osx/ ? UI.start_timer(0){ method } : method

Fredosixx commented 2 years ago

I think that it is even worse. when a modal dialog is displayed, the execution of timer body is deferred to the close of the dialog.

Fredosixx commented 4 months ago

Any chance that someone looks at this very annoying (and old) problem?