[Git][wxwidgets/wxwidgets][master] 10 commits: Return true from wxProgressDialog::Show() on success

1 view
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Mar 17, 2026, 9:53:42 AM (12 days ago) Mar 17
to wx-commi...@googlegroups.com

Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets

Commits:

  • 2a431831
    by Vadim Zeitlin at 2026-03-15T00:54:47+01:00
    Return true from wxProgressDialog::Show() on success
    
    We accidentally returned false after successfully showing the native
    dialog, which didn't make sense.
    
  • c76e4ff3
    by Vadim Zeitlin at 2026-03-15T00:54:47+01:00
    Remove unnecessary explicit call to wxThread::Create()
    
    Run() creates the thread if necessary, so there is no need to do it
    here.
    
  • 505aa614
    by Vadim Zeitlin at 2026-03-15T01:12:59+01:00
    Remove untranslated error message never shown in practice
    
    Messages shown by wxLogError() are user-visible and so need to be
    translated, but it doesn't seem to be worth doing it for the message
    about failing to start a thread which should be never given -- and if
    the system is so low on resources that it can't create new threads,
    showing this message would probably fail anyhow.
    
    Just replace it with wxLogDebug().
    
  • 75062899
    by Vadim Zeitlin at 2026-03-15T01:43:25+01:00
    Fall back to generic dialog if native wxProgressDialog fails
    
    Even if this is not supposed to happen, fall back to the generic
    progress dialog instead of just hanging if showing the native dialog
    fails, for whatever reason.
    
    This commit is best viewed with Git --color-moved option.
    
  • 82632d60
    by Vadim Zeitlin at 2026-03-15T01:46:11+01:00
    Fix showing wxProgressDialog with wxPD_CAN_SKIP style
    
    This was broken by 02cff90601 (Change return type of wxGetTranslation,
    2026-02-15) which resulted in passing invalid pointer to the already
    destroyed temporary wxString "Skip" to the native dialog -- which
    detected this and failed, resulting in a hang because our code didn't
    handle its error correctly.
    
    Error handling was improved in the preceding commits, but now fix the
    real underlying bug by ensuring the string lives long enough.
    
    Closes #26287.
    
  • f5ffe790
    by Vadim Zeitlin at 2026-03-15T21:56:40+01:00
    Fix crash when opening link in new window in wxWebViewWebKit
    
    The parameters of "ready-to-show" signal handler were deleted, by the
    handler itself, after a first call to it, but at least with the current
    version of webkit2gtk (2.50.4) this handler can be called more than once
    and it crashed when it happened.
    
    Fix this by disconnecting it as soon as it is called, which fixes the
    crash and doesn't seem to have any drawbacks.
    
    Note that we might want to find a better way of passing these parameters
    as currently they are leaked if the handler is not called at all, which
    might happen under some unusual circumstances. But for now just fix the
    crash.
    
    Closes #26298.
    
  • 753b6bc9
    by mcorino at 2026-03-16T13:59:32+01:00
    Add wxEVT_WEBVIEW_BROWSING_DATA_CLEARED to the documentation
    
    Closes #26299.
    
  • 6894d4c7
    by Blake-Madden at 2026-03-17T01:19:59+01:00
    Fix static build regression in wxGTK due to wxMoveToTrash()
    
    Move this function to core library and only define it under the
    platforms that implement it.
    
    This commit is best view using Git --color-moved option.
    
    Closes #26290.
    
  • 1ac87c6f
    by Serdar Pehlivan at 2026-03-17T14:12:05+01:00
    Allow matrix parameter of wxAffineMatrix2D::Get() to be null too
    
    Previously, only the second parameter, in which translation vector was
    returned, could be null. Make it possible to specify null for the first
    parameter if it is not needed too now.
    
    Still check that at least one parameter is not null, as it doesn't make
    sense to call the function otherwise.
    
    Update documentation to reflect the new behaviour.
    
    Closes #26303.
    
  • 03d9f9a8
    by Vadim Zeitlin at 2026-03-17T14:14:47+01:00
    Merge branch 'msw-fix-progress-dialog-skip'
    
    Fix showing wxProgressDialog with wxPD_CAN_SKIP in wxMSW.
    
    See #26293.
    

13 changed files:

Changes:

  • include/wx/filefn.h
    ... ... @@ -440,7 +440,9 @@ WXDLLIMPEXP_BASE bool wxRemoveFile(const wxString& file);
    440 440
         #define wxHAS_MOVE_TO_TRASH
    
    441 441
     #endif
    
    442 442
     
    
    443
    -WXDLLIMPEXP_BASE bool wxMoveToTrash(const wxString& path);
    
    443
    +#ifdef wxHAS_MOVE_TO_TRASH
    
    444
    +    WXDLLIMPEXP_CORE bool wxMoveToTrash(const wxString& path);
    
    445
    +#endif // wxHAS_MOVE_TO_TRASH
    
    444 446
     
    
    445 447
     // Rename file
    
    446 448
     WXDLLIMPEXP_BASE bool wxRenameFile(const wxString& oldpath, const wxString& newpath, bool overwrite = true);
    

  • include/wx/msw/progdlg.h
    ... ... @@ -72,6 +72,12 @@ private:
    72 72
         // Get the task dialog geometry when using the native dialog.
    
    73 73
         wxRect GetTaskDialogRect() const;
    
    74 74
     
    
    75
    +    // Returns true if the dialog is currently using the native task dialog.
    
    76
    +    bool UsingNativeTaskDialog() const { return m_sharedData != nullptr; }
    
    77
    +
    
    78
    +    // Show native dialog for the first time.
    
    79
    +    bool InitAndShowNative();
    
    80
    +
    
    75 81
     
    
    76 82
         wxProgressDialogTaskRunner *m_taskDialogRunner;
    
    77 83
     
    

  • interface/wx/affinematrix2d.h
    ... ... @@ -28,9 +28,11 @@ public:
    28 28
         /**
    
    29 29
             Get the component values of the matrix.
    
    30 30
     
    
    31
    +        At least one of the parameters must be non-NULL.
    
    32
    +
    
    31 33
             @param mat2D
    
    32
    -            The rotational components of the matrix (upper 2 x 2), must be
    
    33
    -            non-null.
    
    34
    +            The rotational components of the matrix (upper 2 x 2),
    
    35
    +            may be @NULL.
    
    34 36
             @param tr
    
    35 37
                 The translational components of the matrix, may be @NULL.
    
    36 38
         */
    

  • interface/wx/filefn.h
    ... ... @@ -356,8 +356,7 @@ bool wxRemoveFile(const wxString& file);
    356 356
         facility.
    
    357 357
     
    
    358 358
         Preprocessor symbol @c wxHAS_MOVE_TO_TRASH is defined if this function is
    
    359
    -    supported on the current platform. If it is not defined, the function still
    
    360
    -    exists but always returns @false without doing anything else.
    
    359
    +    available on the current platform.
    
    361 360
     
    
    362 361
         Implementation details:
    
    363 362
         - Under Windows, this uses @c SHFileOperation with @c FOF_ALLOWUNDO.
    

  • interface/wx/webview.h
    ... ... @@ -2183,3 +2183,4 @@ wxEventType wxEVT_WEBVIEW_FULLSCREEN_CHANGED;
    2183 2183
     wxEventType wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED;
    
    2184 2184
     wxEventType wxEVT_WEBVIEW_SCRIPT_RESULT;
    
    2185 2185
     wxEventType wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED;
    
    2186
    +wxEventType wxEVT_WEBVIEW_BROWSING_DATA_CLEARED;

  • src/common/affinematrix2d.cpp
    ... ... @@ -29,10 +29,16 @@ void wxAffineMatrix2D::Set(const wxMatrix2D &mat2D, const wxPoint2DDouble &tr)
    29 29
     // gets the component values of the matrix
    
    30 30
     void wxAffineMatrix2D::Get(wxMatrix2D *mat2D, wxPoint2DDouble *tr) const
    
    31 31
     {
    
    32
    -    mat2D->m_11 = m_11;
    
    33
    -    mat2D->m_12 = m_12;
    
    34
    -    mat2D->m_21 = m_21;
    
    35
    -    mat2D->m_22 = m_22;
    
    32
    +    wxASSERT_MSG( mat2D || tr,
    
    33
    +                  wxT("at least one parameter must be non-null") );
    
    34
    +
    
    35
    +    if( mat2D )
    
    36
    +    {
    
    37
    +        mat2D->m_11 = m_11;
    
    38
    +        mat2D->m_12 = m_12;
    
    39
    +        mat2D->m_21 = m_21;
    
    40
    +        mat2D->m_22 = m_22;
    
    41
    +    }
    
    36 42
     
    
    37 43
         if ( tr )
    
    38 44
         {
    

  • src/common/filefn.cpp
    ... ... @@ -641,15 +641,6 @@ bool wxRemoveFile(const wxString& file)
    641 641
         return res == 0;
    
    642 642
     }
    
    643 643
     
    
    644
    -#ifndef wxHAS_MOVE_TO_TRASH
    
    645
    -
    
    646
    -bool wxMoveToTrash(const wxString& WXUNUSED(path))
    
    647
    -{
    
    648
    -    return false;
    
    649
    -}
    
    650
    -
    
    651
    -#endif // !wxHAS_MOVE_TO_TRASH
    
    652
    -
    
    653 644
     bool wxMkdir(const wxString& dir, int perm)
    
    654 645
     {
    
    655 646
     #if defined(__WXMAC__) && !defined(__UNIX__)
    

  • src/gtk/webview_webkit2.cpp
    ... ... @@ -423,11 +423,16 @@ class wxReadyToShowParams
    423 423
     public:
    
    424 424
         wxWebViewWebKit* childWebView;
    
    425 425
         wxWebViewWebKit* parentWebView;
    
    426
    +    gulong handlerId = 0;
    
    426 427
     };
    
    427 428
     
    
    428 429
     static void wxgtk_webview_webkit_ready_to_show (WebKitWebView *web_view,
    
    429 430
                                                     wxReadyToShowParams *params)
    
    430 431
     {
    
    432
    +    // This handler must not be called more than once as it deletes params, so
    
    433
    +    // disconnect it immediately.
    
    434
    +    g_signal_handler_disconnect(web_view, params->handlerId);
    
    435
    +
    
    431 436
         wxWebViewWindowFeaturesWebKit features(params->childWebView, web_view);
    
    432 437
         wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW_FEATURES,
    
    433 438
                              params->parentWebView->GetId(),
    
    ... ... @@ -867,9 +872,8 @@ wxWebViewWebKit::wxWebViewWebKit(WebKitWebView* parentWebView, wxWebViewWebKit*
    867 872
         wxReadyToShowParams* params = new wxReadyToShowParams();
    
    868 873
         params->childWebView = this;
    
    869 874
         params->parentWebView = parentWebViewCtrl;
    
    870
    -
    
    871
    -    g_signal_connect(m_web_view, "ready-to-show",
    
    872
    -                     G_CALLBACK(wxgtk_webview_webkit_ready_to_show), params);
    
    875
    +    params->handlerId = g_signal_connect(m_web_view, "ready-to-show",
    
    876
    +                                         G_CALLBACK(wxgtk_webview_webkit_ready_to_show), params);
    
    873 877
     }
    
    874 878
     
    
    875 879
     wxWebViewWebKit::wxWebViewWebKit(const wxWebViewConfiguration &config):
    

  • src/msw/progdlg.cpp
    ... ... @@ -59,6 +59,14 @@ const int wxSPDD_WINDOW_MOVED = 0x2000;
    59 59
     
    
    60 60
     const int Id_SkipBtn = wxID_HIGHEST + 1;
    
    61 61
     
    
    62
    +// Enum indicating whether the native dialog was initialized.
    
    63
    +enum class wxProgressDialogStatus
    
    64
    +{
    
    65
    +    Initializing,
    
    66
    +    Initialized,
    
    67
    +    Failed
    
    68
    +};
    
    69
    +
    
    62 70
     } // anonymous namespace
    
    63 71
     
    
    64 72
     // ============================================================================
    
    ... ... @@ -82,6 +90,10 @@ public:
    82 90
     
    
    83 91
         wxCriticalSection m_cs;
    
    84 92
     
    
    93
    +    // This field is set to either Initialized or Failed by the task dialog
    
    94
    +    // runner thread to indicate whether the dialog was successfully created.
    
    95
    +    wxProgressDialogStatus m_status = wxProgressDialogStatus::Initializing;
    
    96
    +
    
    85 97
         wxWindow *m_parent;     // Parent window only used to center us over it.
    
    86 98
         HWND m_hwnd;            // Task dialog handler
    
    87 99
         long m_style;           // wxProgressDialog style
    
    ... ... @@ -90,6 +102,7 @@ public:
    90 102
         wxString m_title;
    
    91 103
         wxString m_message;
    
    92 104
         wxString m_expandedInformation;
    
    105
    +    wxString m_labelSkip;
    
    93 106
         wxString m_labelCancel; // Privately used by callback.
    
    94 107
         unsigned long m_timeStop;
    
    95 108
         wxIcon m_iconSmall;
    
    ... ... @@ -395,6 +408,8 @@ wxProgressDialog::wxProgressDialog( const wxString& title,
    395 408
           m_message(message),
    
    396 409
           m_title(title)
    
    397 410
     {
    
    411
    +    // Note that here we're testing whether we can use the native task dialog
    
    412
    +    // and not if we are already using it, as UsingNativeTaskDialog() does.
    
    398 413
         if ( HasNativeTaskDialog() )
    
    399 414
         {
    
    400 415
             SetTopParent(parent);
    
    ... ... @@ -402,10 +417,29 @@ wxProgressDialog::wxProgressDialog( const wxString& title,
    402 417
             SetMaximum(maximum);
    
    403 418
     
    
    404 419
             EnsureActiveEventLoopExists();
    
    405
    -        Show();
    
    406
    -        DisableOtherWindows();
    
    420
    +        if ( InitAndShowNative() )
    
    421
    +        {
    
    422
    +            DisableOtherWindows();
    
    423
    +            return;
    
    424
    +        }
    
    407 425
     
    
    408
    -        return;
    
    426
    +        // Showing native dialog failed, fall back to the generic one.
    
    427
    +        if ( m_taskDialogRunner )
    
    428
    +        {
    
    429
    +            // This points to the data owned by m_taskDialogRunner, so don't
    
    430
    +            // keep it dangling after deleting the thread.
    
    431
    +            //
    
    432
    +            // This is also used by UsingNativeTaskDialog().
    
    433
    +            m_sharedData = nullptr;
    
    434
    +
    
    435
    +            // It's critical to use wxTHREAD_WAIT_YIELD here to prevent
    
    436
    +            // deadlocks as the task dialog runner thread might be waiting for
    
    437
    +            // the main thread to process some messages.
    
    438
    +            m_taskDialogRunner->Wait(wxTHREAD_WAIT_YIELD);
    
    439
    +
    
    440
    +            delete m_taskDialogRunner;
    
    441
    +            m_taskDialogRunner = nullptr;
    
    442
    +        }
    
    409 443
         }
    
    410 444
     
    
    411 445
         Create(title, message, maximum, parent, style);
    
    ... ... @@ -469,7 +503,7 @@ wxProgressDialog::~wxProgressDialog()
    469 503
     
    
    470 504
     bool wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
    
    471 505
     {
    
    472
    -    if ( HasNativeTaskDialog() )
    
    506
    +    if ( UsingNativeTaskDialog() )
    
    473 507
         {
    
    474 508
             if ( !DoNativeBeforeUpdate(skip) )
    
    475 509
             {
    
    ... ... @@ -542,7 +576,7 @@ bool wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
    542 576
     
    
    543 577
     bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
    
    544 578
     {
    
    545
    -    if ( HasNativeTaskDialog() )
    
    579
    +    if ( UsingNativeTaskDialog() )
    
    546 580
         {
    
    547 581
             if ( !DoNativeBeforeUpdate(skip) )
    
    548 582
             {
    
    ... ... @@ -577,7 +611,7 @@ bool wxProgressDialog::Pulse(const wxString& newmsg, bool *skip)
    577 611
     
    
    578 612
     void wxProgressDialog::DispatchEvents()
    
    579 613
     {
    
    580
    -    // No need for HasNativeTaskDialog() check, we're only called when this is
    
    614
    +    // No need for UsingNativeTaskDialog() check, we're only called when this is
    
    581 615
         // the case.
    
    582 616
     
    
    583 617
         // We don't need to dispatch the user input events as the task dialog
    
    ... ... @@ -613,7 +647,7 @@ void wxProgressDialog::Resume()
    613 647
     {
    
    614 648
         wxGenericProgressDialog::Resume();
    
    615 649
     
    
    616
    -    if ( HasNativeTaskDialog() )
    
    650
    +    if ( UsingNativeTaskDialog() )
    
    617 651
         {
    
    618 652
             HWND hwnd;
    
    619 653
     
    
    ... ... @@ -648,7 +682,7 @@ void wxProgressDialog::Resume()
    648 682
     
    
    649 683
     WXWidget wxProgressDialog::GetHandle() const
    
    650 684
     {
    
    651
    -    if ( HasNativeTaskDialog() )
    
    685
    +    if ( UsingNativeTaskDialog() )
    
    652 686
         {
    
    653 687
             wxCriticalSectionLocker locker(m_sharedData->m_cs);
    
    654 688
             return m_sharedData->m_hwnd;
    
    ... ... @@ -659,7 +693,7 @@ WXWidget wxProgressDialog::GetHandle() const
    659 693
     
    
    660 694
     int wxProgressDialog::GetValue() const
    
    661 695
     {
    
    662
    -    if ( HasNativeTaskDialog() )
    
    696
    +    if ( UsingNativeTaskDialog() )
    
    663 697
         {
    
    664 698
             wxCriticalSectionLocker locker(m_sharedData->m_cs);
    
    665 699
             return m_sharedData->m_value;
    
    ... ... @@ -670,7 +704,7 @@ int wxProgressDialog::GetValue() const
    670 704
     
    
    671 705
     wxString wxProgressDialog::GetMessage() const
    
    672 706
     {
    
    673
    -    if ( HasNativeTaskDialog() )
    
    707
    +    if ( UsingNativeTaskDialog() )
    
    674 708
             return m_message;
    
    675 709
     
    
    676 710
         return wxGenericProgressDialog::GetMessage();
    
    ... ... @@ -678,7 +712,7 @@ wxString wxProgressDialog::GetMessage() const
    678 712
     
    
    679 713
     void wxProgressDialog::SetRange(int maximum)
    
    680 714
     {
    
    681
    -    if ( HasNativeTaskDialog() )
    
    715
    +    if ( UsingNativeTaskDialog() )
    
    682 716
         {
    
    683 717
             SetMaximum(maximum);
    
    684 718
     
    
    ... ... @@ -695,7 +729,7 @@ void wxProgressDialog::SetRange(int maximum)
    695 729
     
    
    696 730
     bool wxProgressDialog::WasSkipped() const
    
    697 731
     {
    
    698
    -    if ( HasNativeTaskDialog() )
    
    732
    +    if ( UsingNativeTaskDialog() )
    
    699 733
         {
    
    700 734
             if ( !m_sharedData )
    
    701 735
             {
    
    ... ... @@ -712,7 +746,7 @@ bool wxProgressDialog::WasSkipped() const
    712 746
     
    
    713 747
     bool wxProgressDialog::WasCancelled() const
    
    714 748
     {
    
    715
    -    if ( HasNativeTaskDialog() )
    
    749
    +    if ( UsingNativeTaskDialog() )
    
    716 750
         {
    
    717 751
             wxCriticalSectionLocker locker(m_sharedData->m_cs);
    
    718 752
             return m_sharedData->m_state == Canceled;
    
    ... ... @@ -723,7 +757,7 @@ bool wxProgressDialog::WasCancelled() const
    723 757
     
    
    724 758
     void wxProgressDialog::SetTitle(const wxString& title)
    
    725 759
     {
    
    726
    -    if ( HasNativeTaskDialog() )
    
    760
    +    if ( UsingNativeTaskDialog() )
    
    727 761
         {
    
    728 762
             m_title = title;
    
    729 763
     
    
    ... ... @@ -740,7 +774,7 @@ void wxProgressDialog::SetTitle(const wxString& title)
    740 774
     
    
    741 775
     wxString wxProgressDialog::GetTitle() const
    
    742 776
     {
    
    743
    -    if ( HasNativeTaskDialog() )
    
    777
    +    if ( UsingNativeTaskDialog() )
    
    744 778
             return m_title;
    
    745 779
     
    
    746 780
         return wxGenericProgressDialog::GetTitle();
    
    ... ... @@ -748,7 +782,7 @@ wxString wxProgressDialog::GetTitle() const
    748 782
     
    
    749 783
     void wxProgressDialog::SetIcons(const wxIconBundle& icons)
    
    750 784
     {
    
    751
    -    if ( HasNativeTaskDialog() )
    
    785
    +    if ( UsingNativeTaskDialog() )
    
    752 786
         {
    
    753 787
             m_icons = icons; // We can't just call to parent's SetIcons()
    
    754 788
                              // (wxGenericProgressDialog::SetIcons == wxTopLevelWindowMSW::SetIcons)
    
    ... ... @@ -780,7 +814,7 @@ void wxProgressDialog::SetIcons(const wxIconBundle& icons)
    780 814
     
    
    781 815
     void wxProgressDialog::DoMoveWindow(int x, int y, int width, int height)
    
    782 816
     {
    
    783
    -    if ( HasNativeTaskDialog() )
    
    817
    +    if ( UsingNativeTaskDialog() )
    
    784 818
         {
    
    785 819
             if ( m_sharedData )
    
    786 820
             {
    
    ... ... @@ -810,7 +844,7 @@ wxRect wxProgressDialog::GetTaskDialogRect() const
    810 844
     
    
    811 845
     void wxProgressDialog::DoGetPosition(int *x, int *y) const
    
    812 846
     {
    
    813
    -    if ( HasNativeTaskDialog() )
    
    847
    +    if ( UsingNativeTaskDialog() )
    
    814 848
         {
    
    815 849
             const wxRect r = GetTaskDialogRect();
    
    816 850
             if (x)
    
    ... ... @@ -826,7 +860,7 @@ void wxProgressDialog::DoGetPosition(int *x, int *y) const
    826 860
     
    
    827 861
     void wxProgressDialog::DoGetSize(int *width, int *height) const
    
    828 862
     {
    
    829
    -    if ( HasNativeTaskDialog() )
    
    863
    +    if ( UsingNativeTaskDialog() )
    
    830 864
         {
    
    831 865
             const wxRect r = GetTaskDialogRect();
    
    832 866
             if ( width )
    
    ... ... @@ -842,7 +876,7 @@ void wxProgressDialog::DoGetSize(int *width, int *height) const
    842 876
     
    
    843 877
     void wxProgressDialog::Fit()
    
    844 878
     {
    
    845
    -    if ( HasNativeTaskDialog() )
    
    879
    +    if ( UsingNativeTaskDialog() )
    
    846 880
         {
    
    847 881
             wxCriticalSectionLocker locker(m_sharedData->m_cs);
    
    848 882
     
    
    ... ... @@ -856,74 +890,90 @@ void wxProgressDialog::Fit()
    856 890
         wxGenericProgressDialog::Fit();
    
    857 891
     }
    
    858 892
     
    
    859
    -bool wxProgressDialog::Show(bool show)
    
    893
    +bool wxProgressDialog::InitAndShowNative()
    
    860 894
     {
    
    861
    -    if ( HasNativeTaskDialog() )
    
    895
    +    // We're showing the dialog for the first time, create the thread that
    
    896
    +    // will manage it.
    
    897
    +    m_taskDialogRunner = new wxProgressDialogTaskRunner;
    
    898
    +    m_sharedData = m_taskDialogRunner->GetSharedDataObject();
    
    899
    +
    
    900
    +    // Initialize shared data.
    
    901
    +    m_sharedData->m_title = m_title;
    
    902
    +    m_sharedData->m_message = m_message;
    
    903
    +    m_sharedData->m_range = m_maximum;
    
    904
    +    m_sharedData->m_state = Uncancelable;
    
    905
    +    m_sharedData->m_style = GetPDStyle();
    
    906
    +    m_sharedData->m_parent = GetTopParent();
    
    907
    +
    
    908
    +    if ( HasPDFlag(wxPD_CAN_ABORT) )
    
    862 909
         {
    
    863
    -        // The dialog can't be hidden at all and showing it again after it had
    
    864
    -        // been shown before doesn't do anything.
    
    865
    -        if ( !show || m_taskDialogRunner )
    
    866
    -            return false;
    
    910
    +        m_sharedData->m_state = Continue;
    
    911
    +        m_sharedData->m_labelCancel = _("Cancel");
    
    912
    +    }
    
    913
    +    else // Dialog can't be cancelled.
    
    914
    +    {
    
    915
    +        // We still must have at least a single button in the dialog so
    
    916
    +        // just don't call it "Cancel" in this case.
    
    917
    +        m_sharedData->m_labelCancel = _("Close");
    
    918
    +    }
    
    867 919
     
    
    868
    -        // We're showing the dialog for the first time, create the thread that
    
    869
    -        // will manage it.
    
    870
    -        m_taskDialogRunner = new wxProgressDialogTaskRunner;
    
    871
    -        m_sharedData = m_taskDialogRunner->GetSharedDataObject();
    
    920
    +    if ( HasPDFlag(wxPD_ELAPSED_TIME |
    
    921
    +                     wxPD_ESTIMATED_TIME |
    
    922
    +                        wxPD_REMAINING_TIME) )
    
    923
    +    {
    
    924
    +        // Set the expanded information field from the beginning to avoid
    
    925
    +        // having to re-layout the dialog later when it changes.
    
    926
    +        UpdateExpandedInformation(0);
    
    927
    +    }
    
    872 928
     
    
    873
    -        // Initialize shared data.
    
    874
    -        m_sharedData->m_title = m_title;
    
    875
    -        m_sharedData->m_message = m_message;
    
    876
    -        m_sharedData->m_range = m_maximum;
    
    877
    -        m_sharedData->m_state = Uncancelable;
    
    878
    -        m_sharedData->m_style = GetPDStyle();
    
    879
    -        m_sharedData->m_parent = GetTopParent();
    
    929
    +    // Do launch the thread.
    
    930
    +    if ( m_taskDialogRunner->Run() != wxTHREAD_NO_ERROR )
    
    931
    +    {
    
    932
    +        // This should never happen and it's useless to have a user-visible
    
    933
    +        // message (that would need to be translated) for it.
    
    934
    +        wxLogDebug("Unexpectedly failed to launch the task dialog thread");
    
    935
    +        return false;
    
    936
    +    }
    
    880 937
     
    
    881
    -        if ( HasPDFlag(wxPD_CAN_ABORT) )
    
    882
    -        {
    
    883
    -            m_sharedData->m_state = Continue;
    
    884
    -            m_sharedData->m_labelCancel = _("Cancel");
    
    885
    -        }
    
    886
    -        else // Dialog can't be cancelled.
    
    887
    -        {
    
    888
    -            // We still must have at least a single button in the dialog so
    
    889
    -            // just don't call it "Cancel" in this case.
    
    890
    -            m_sharedData->m_labelCancel = _("Close");
    
    891
    -        }
    
    938
    +    // Wait until the dialog is shown as the program may need some time
    
    939
    +    // before it calls Update() and we want to show something to the user
    
    940
    +    // in the meanwhile.
    
    941
    +    auto status = wxProgressDialogStatus::Failed;
    
    942
    +    while ( wxEventLoop::GetActive()->Dispatch() )
    
    943
    +    {
    
    944
    +        wxCriticalSectionLocker locker(m_sharedData->m_cs);
    
    945
    +        status = m_sharedData->m_status;
    
    946
    +        if ( status != wxProgressDialogStatus::Initializing )
    
    947
    +            break;
    
    948
    +    }
    
    892 949
     
    
    893
    -        if ( HasPDFlag(wxPD_ELAPSED_TIME |
    
    894
    -                         wxPD_ESTIMATED_TIME |
    
    895
    -                            wxPD_REMAINING_TIME) )
    
    896
    -        {
    
    897
    -            // Set the expanded information field from the beginning to avoid
    
    898
    -            // having to re-layout the dialog later when it changes.
    
    899
    -            UpdateExpandedInformation(0);
    
    900
    -        }
    
    950
    +    switch ( m_sharedData->m_status )
    
    951
    +    {
    
    952
    +        case wxProgressDialogStatus::Initialized:
    
    953
    +            break;
    
    901 954
     
    
    902
    -        // Do launch the thread.
    
    903
    -        if ( m_taskDialogRunner->Create() != wxTHREAD_NO_ERROR )
    
    904
    -        {
    
    905
    -            wxLogError( "Unable to create thread!" );
    
    906
    -            return false;
    
    907
    -        }
    
    955
    +        case wxProgressDialogStatus::Initializing:
    
    956
    +            wxFAIL_MSG("Unreachable");
    
    957
    +            wxFALLTHROUGH;
    
    908 958
     
    
    909
    -        if ( m_taskDialogRunner->Run() != wxTHREAD_NO_ERROR )
    
    910
    -        {
    
    911
    -            wxLogError( "Unable to start thread!" );
    
    959
    +        case wxProgressDialogStatus::Failed:
    
    912 960
                 return false;
    
    913
    -        }
    
    961
    +    }
    
    914 962
     
    
    915
    -        // Wait until the dialog is shown as the program may need some time
    
    916
    -        // before it calls Update() and we want to show something to the user
    
    917
    -        // in the meanwhile.
    
    918
    -        while ( wxEventLoop::GetActive()->Dispatch() )
    
    919
    -        {
    
    920
    -            wxCriticalSectionLocker locker(m_sharedData->m_cs);
    
    921
    -            if ( m_sharedData->m_hwnd )
    
    922
    -                break;
    
    923
    -        }
    
    963
    +    return true;
    
    964
    +}
    
    924 965
     
    
    925
    -        // Do not show the underlying dialog.
    
    926
    -        return false;
    
    966
    +bool wxProgressDialog::Show(bool show)
    
    967
    +{
    
    968
    +    if ( UsingNativeTaskDialog() )
    
    969
    +    {
    
    970
    +        // The dialog can't be hidden at all and showing it again after it had
    
    971
    +        // been shown before doesn't do anything.
    
    972
    +        if ( !show || m_taskDialogRunner )
    
    973
    +            return false;
    
    974
    +
    
    975
    +        // We don't need to do anything to show it.
    
    976
    +        return true;
    
    927 977
         }
    
    928 978
     
    
    929 979
         return wxGenericProgressDialog::Show( show );
    
    ... ... @@ -1022,7 +1072,11 @@ void* wxProgressDialogTaskRunner::Entry()
    1022 1072
             tdc.lpCallbackData = (LONG_PTR) &m_sharedData;
    
    1023 1073
     
    
    1024 1074
             if ( m_sharedData.m_style & wxPD_CAN_SKIP )
    
    1025
    -            wxTdc.AddTaskDialogButton( tdc, Id_SkipBtn, 0, _("Skip") );
    
    1075
    +        {
    
    1076
    +            m_sharedData.m_labelSkip = _("Skip");
    
    1077
    +            wxTdc.AddTaskDialogButton( tdc, Id_SkipBtn, 0,
    
    1078
    +                                       m_sharedData.m_labelSkip );
    
    1079
    +        }
    
    1026 1080
     
    
    1027 1081
             tdc.dwFlags |= TDF_CALLBACK_TIMER | TDF_SHOW_PROGRESS_BAR;
    
    1028 1082
     
    
    ... ... @@ -1040,15 +1094,26 @@ void* wxProgressDialogTaskRunner::Entry()
    1040 1094
             }
    
    1041 1095
         }
    
    1042 1096
     
    
    1097
    +    HRESULT hr;
    
    1043 1098
         TaskDialogIndirect_t taskDialogIndirect = GetTaskDialogIndirectFunc();
    
    1044
    -    if ( !taskDialogIndirect )
    
    1045
    -        return nullptr;
    
    1099
    +    if ( taskDialogIndirect )
    
    1100
    +    {
    
    1101
    +        int msAns;
    
    1102
    +        hr = taskDialogIndirect(&tdc, &msAns, nullptr, nullptr);
    
    1103
    +    }
    
    1104
    +    else
    
    1105
    +    {
    
    1106
    +        hr = E_UNEXPECTED;
    
    1107
    +    }
    
    1046 1108
     
    
    1047
    -    int msAns;
    
    1048
    -    HRESULT hr = taskDialogIndirect(&tdc, &msAns, nullptr, nullptr);
    
    1049 1109
         if ( FAILED(hr) )
    
    1110
    +    {
    
    1050 1111
             wxLogApiError( "TaskDialogIndirect", hr );
    
    1051 1112
     
    
    1113
    +        wxCriticalSectionLocker locker(m_sharedData.m_cs);
    
    1114
    +        m_sharedData.m_status = wxProgressDialogStatus::Failed;
    
    1115
    +    }
    
    1116
    +
    
    1052 1117
         // If the main thread is waiting for us to exit inside the event loop in
    
    1053 1118
         // Update(), wake it up so that it checks our status again.
    
    1054 1119
         wxWakeUpIdle();
    
    ... ... @@ -1079,6 +1144,9 @@ wxProgressDialogTaskRunner::TaskDialogCallbackProc
    1079 1144
         switch ( uNotification )
    
    1080 1145
         {
    
    1081 1146
             case TDN_CREATED:
    
    1147
    +            // Let the main thread know that the dialog can be used.
    
    1148
    +            sharedData->m_status = wxProgressDialogStatus::Initialized;
    
    1149
    +
    
    1082 1150
                 // Store the HWND for the main thread use.
    
    1083 1151
                 sharedData->m_hwnd = hwnd;
    
    1084 1152
     
    

  • src/msw/utils.cpp
    ... ... @@ -1715,35 +1715,6 @@ wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
    1715 1715
         return hwnd;
    
    1716 1716
     }
    
    1717 1717
     
    
    1718
    -bool wxMoveToTrash(const wxString& path)
    
    1719
    -{
    
    1720
    -    // SHFileOperation needs double null termination string
    
    1721
    -    // but without separator at the end of the path
    
    1722
    -    wxString pathStr(path);
    
    1723
    -    if ( pathStr.Last() == wxFILE_SEP_PATH )
    
    1724
    -        pathStr.RemoveLast();
    
    1725
    -    pathStr += wxT('\0');
    
    1726
    -
    
    1727
    -    SHFILEOPSTRUCT fileop;
    
    1728
    -    wxZeroMemory(fileop);
    
    1729
    -    fileop.wFunc = FO_DELETE;
    
    1730
    -    fileop.pFrom = pathStr.t_str();
    
    1731
    -    fileop.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
    
    1732
    -
    
    1733
    -    const int ret = SHFileOperation(&fileop);
    
    1734
    -    if ( ret != 0 || fileop.fAnyOperationsAborted )
    
    1735
    -    {
    
    1736
    -        // Note that the return value from SHFileOperation() is not a standard
    
    1737
    -        // Win32 error code, so we can't use wxLogSysError() here.
    
    1738
    -        wxLogError(_("'%s' couldn't be moved to trash: error 0x%08x"),
    
    1739
    -                   path,
    
    1740
    -                   ret);
    
    1741
    -        return false;
    
    1742
    -    }
    
    1743
    -
    
    1744
    -    return true;
    
    1745
    -}
    
    1746
    -
    
    1747 1718
     int wxCMPFUNC_CONV wxCmpNatural(const wxString& s1, const wxString& s2)
    
    1748 1719
     {
    
    1749 1720
         return StrCmpLogicalW(s1.wc_str(), s2.wc_str());
    

  • src/msw/utilswin.cpp
    ... ... @@ -14,6 +14,7 @@
    14 14
         #include "wx/utils.h"
    
    15 15
     #endif //WX_PRECOMP
    
    16 16
     
    
    17
    +#include "wx/filefn.h"
    
    17 18
     #include "wx/private/launchbrowser.h"
    
    18 19
     #include "wx/msw/private.h"     // includes <windows.h>
    
    19 20
     #include "wx/msw/private/dpiaware.h"
    
    ... ... @@ -178,3 +179,32 @@ bool wxMSWIsOnSecureScreen()
    178 179
         // level.
    
    179 180
         return wcscmp(name, L"Winlogon") == 0;
    
    180 181
     }
    
    182
    +
    
    183
    +bool wxMoveToTrash(const wxString& path)
    
    184
    +{
    
    185
    +    // SHFileOperation needs double null termination string
    
    186
    +    // but without separator at the end of the path
    
    187
    +    wxString pathStr(path);
    
    188
    +    if ( pathStr.Last() == wxFILE_SEP_PATH )
    
    189
    +        pathStr.RemoveLast();
    
    190
    +    pathStr += wxT('\0');
    
    191
    +
    
    192
    +    SHFILEOPSTRUCT fileop;
    
    193
    +    wxZeroMemory(fileop);
    
    194
    +    fileop.wFunc = FO_DELETE;
    
    195
    +    fileop.pFrom = pathStr.t_str();
    
    196
    +    fileop.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
    
    197
    +
    
    198
    +    const int ret = SHFileOperation(&fileop);
    
    199
    +    if ( ret != 0 || fileop.fAnyOperationsAborted )
    
    200
    +    {
    
    201
    +        // Note that the return value from SHFileOperation() is not a standard
    
    202
    +        // Win32 error code, so we can't use wxLogSysError() here.
    
    203
    +        wxLogError(_("'%s' couldn't be moved to trash: error 0x%08x"),
    
    204
    +                   path,
    
    205
    +                   ret);
    
    206
    +        return false;
    
    207
    +    }
    
    208
    +
    
    209
    +    return true;
    
    210
    +}

  • src/osx/carbon/utilscocoa.mm
    ... ... @@ -12,6 +12,8 @@
    12 12
     #ifndef WX_PRECOMP
    
    13 13
     #include "wx/object.h"
    
    14 14
     #include "wx/math.h"
    
    15
    +#include "wx/intl.h"
    
    16
    +#include "wx/log.h"
    
    15 17
     #endif
    
    16 18
     
    
    17 19
     #if wxOSX_USE_COCOA_OR_CARBON
    
    ... ... @@ -694,4 +696,31 @@ wxOSXEffectiveAppearanceSetter::~wxOSXEffectiveAppearanceSetter()
    694 696
     #endif
    
    695 697
     }
    
    696 698
     
    
    699
    +#ifdef __WXDARWIN_OSX__
    
    700
    +
    
    701
    +// Move file or directory to macOS Trash using NSFileManager.
    
    702
    +bool wxMoveToTrash(const wxString& path)
    
    703
    +{
    
    704
    +    wxCFStringRef cfPath(path);
    
    705
    +    NSURL *fileURL = [NSURL fileURLWithPath:cfPath.AsNSString()];
    
    706
    +    if ( fileURL == nil )
    
    707
    +        return false;
    
    708
    +
    
    709
    +    NSError *error = nil;
    
    710
    +    BOOL ok = [[NSFileManager defaultManager] trashItemAtURL:fileURL
    
    711
    +                                            resultingItemURL:nil
    
    712
    +                                                       error:&error];
    
    713
    +    if ( !ok )
    
    714
    +    {
    
    715
    +        wxLogError(_("'%s' couldn't be moved to trash: %s"),
    
    716
    +                   path,
    
    717
    +                   error ? wxCFStringRef::AsString([error localizedDescription])
    
    718
    +                         : _("unknown error"));
    
    719
    +    }
    
    720
    +
    
    721
    +    return ok;
    
    722
    +}
    
    723
    +
    
    724
    +#endif // __WXDARWIN_OSX__
    
    725
    +
    
    697 726
     #endif

  • src/osx/cocoa/utils_base.mm
    ... ... @@ -388,27 +388,4 @@ bool wxMacInitCocoa()
    388 388
         return cocoaLoaded;
    
    389 389
     }
    
    390 390
     
    
    391
    -// Move file or directory to macOS Trash using NSFileManager.
    
    392
    -bool wxMoveToTrash(const wxString& path)
    
    393
    -{
    
    394
    -    wxCFStringRef cfPath(path);
    
    395
    -    NSURL *fileURL = [NSURL fileURLWithPath:cfPath.AsNSString()];
    
    396
    -    if ( fileURL == nil )
    
    397
    -        return false;
    
    398
    -
    
    399
    -    NSError *error = nil;
    
    400
    -    BOOL ok = [[NSFileManager defaultManager] trashItemAtURL:fileURL
    
    401
    -                                            resultingItemURL:nil
    
    402
    -                                                       error:&error];
    
    403
    -    if ( !ok )
    
    404
    -    {
    
    405
    -        wxLogError(_("'%s' couldn't be moved to trash: %s"),
    
    406
    -                   path,
    
    407
    -                   error ? wxCFStringRef::AsString([error localizedDescription])
    
    408
    -                         : _("unknown error"));
    
    409
    -    }
    
    410
    -
    
    411
    -    return ok;
    
    412
    -}
    
    413
    -
    
    414 391
     #endif // __WXDARWIN_OSX__

Reply all
Reply to author
Forward
0 new messages