Use a single wxSize instead of (w,h) pair in wxBufferedDC No real changes, just replace a pair of int parameters with a single wxSize one. This makes the code a bit more readable.
Don't reinvent wxAutoBufferedPaintDC in wxAuiTabContainer code Remove code in wxAuiTabContainer::Render() which was basically doing the same thing as wxAutoBufferedPaintDC does except without using shared buffer optimization. This code predates wxAutoBufferedPaintDC appearance, so it made sense originally but it doesn't make sense since a very long time any more.
Use 24bpp backing store bitmap in wxMSW to speed up drawing on it Avoid the overhead of converting the backing store bitmap to DIB and back when drawing bitmaps with alpha on it in AlphaBlt(), which may be very significant, by using 24bpp bitmap: as it doesn't have alpha, it doesn't need to be adjusted after drawing on it. This is ugly and it would be better to have a better implementation of AlphaBlt(), but it's not clear how to do it, and for now this fixes a real user-visible problem. See #14403. Closes #23841.
wxQt: Refer to base class type by a shorter name No real changes.
wxQt: Revert commit 6ead206 Added in 2019-02-11 (Fix wxQT wxTreeCtrl drawing issues under Linux) The warnings are already fixed by the recent changes to the wxQt code.
wxQt: Fix a potential crash when destroying a wxTreeCtrl in edit mode Closes #24693
wxQt: Always accept when a wxTreeCtrl item remains unchanged after editing
Support EGL 1.4 instead of previously required 1.5 Check for the availability of eglCreatePlatformWindowSurfaceEXT() if EGL version is < 1.5 and use it if it's available, as it allows applications using wxGLCanvasEGL to work on some (many?) systems without EGL 1.5 support. Closes #22325. Co-authored-by: Vadim Zeitlin <va...@wxwidgets.org>
Translate the error about too low EGL version This error is user-visible and so should be translated. Also remove the unnecessary call to wxString::Format().
Do not log bogus system error in wxRenameFile() There is no failed system call at this point, so there is no relevant system error available either. Closes #25985.
Fix initial scale of wxGLCanvas under EGL/Wayland The scale of the canvas was set up correctly only once we received "size-allocate" signal from GTK, but this doesn't necessarily happen when the window is first shown and after its scale factor is actually known. Ensure that we use the correct scale by catching the notification about its change too. This makes buffer scale factor correct from the very beginning, without having to wait for a resize. See #23733, #25465.
Make wxGLCanvasEGL friend function a normal member one No real changes, it's just not necessary to have wxEGLUpdatePosition() friend function any more as it's only called from wxEGLUpdateGeometry() which is itself a friend function and so can call normal private member functions. This hopefully makes things a bit more clear.
wxQt: Fix wxWindow::SetSize() for toplevel windows - revisited No real changes, just a revision of this commit 846502ec5b (Fix wxWindow::SetSize() for toplevel windows, 2024-10-01) to test for WA_PendingResizeEvent instead of storing m_pendingSize variable.
wxQt: Test for pending client size using WA_PendingResizeEvent attribute No real changes, just make the test more clear that m_pendingClientSize is only set when the resize event is pending as reported by the Qt kernel.
Merge branch 'avoid-slow-alphablt' Avoid slow drawing of bitmaps with alpha in wxAUI. See #25983.
Merge branch 'support-egl-1.4' Support EGL 1.4 instead of previously required 1.5. See #25986.
Merge branch 'qt-treectrl-fix' of github.com:AliKet/wxWidgets wxQt: Fix potential crash when destroying a wxTreeCtrl in edit mode. See #25987.
Merge branch 'egl-fix-initial-scale' Fix initial scale of wxGLCanvas under EGL/Wayland. See #25994.
Merge branch 'qt-pending-resize' of github.com:AliKet/wxWidgets wxQt: Improve handling pending resize. See #25995.
| ... | ... | @@ -90,7 +90,7 @@ public: |
| 90 | 90 | {
|
| 91 | 91 | InitCommon(dc, style);
|
| 92 | 92 | |
| 93 | - UseBuffer(area.x, area.y);
|
|
| 93 | + UseBuffer(area);
|
|
| 94 | 94 | }
|
| 95 | 95 | |
| 96 | 96 | // Blits the buffer to the dc, and detaches the dc from the buffer (so it
|
| ... | ... | @@ -116,7 +116,7 @@ private: |
| 116 | 116 | }
|
| 117 | 117 | |
| 118 | 118 | // check that the bitmap is valid and use it
|
| 119 | - void UseBuffer(wxCoord w = -1, wxCoord h = -1);
|
|
| 119 | + void UseBuffer(wxSize size = wxDefaultSize);
|
|
| 120 | 120 | |
| 121 | 121 | // the underlying DC to which we copy everything drawn on this one in
|
| 122 | 122 | // UnMask()
|
| ... | ... | @@ -257,9 +257,6 @@ private: |
| 257 | 257 | |
| 258 | 258 | bool m_mouseInside;
|
| 259 | 259 | |
| 260 | - bool m_pendingSize = false; // to properly set the size of the TLW if SetSize()
|
|
| 261 | - // is called before the window is shown.
|
|
| 262 | - |
|
| 263 | 260 | wxSize m_pendingClientSize;
|
| 264 | 261 | |
| 265 | 262 | #if wxUSE_ACCEL
|
| ... | ... | @@ -131,6 +131,20 @@ public: |
| 131 | 131 | wl_egl_window *m_wlEGLWindow = nullptr;
|
| 132 | 132 | |
| 133 | 133 | private:
|
| 134 | + // Set correct m_wlSubsurface position.
|
|
| 135 | + //
|
|
| 136 | + // This is defined only when using Wayland.
|
|
| 137 | + void UpdateSubsurfacePosition();
|
|
| 138 | + |
|
| 139 | + // Call eglCreatePlatformWindowSurface() when using EGL 1.5 or later,
|
|
| 140 | + // otherwise try eglCreatePlatformWindowSurfaceEXT() if it's available and
|
|
| 141 | + // fall back on eglCreateWindowSurface() otherwise.
|
|
| 142 | + //
|
|
| 143 | + // This function uses m_display and m_config which must be initialized
|
|
| 144 | + // before using it and should be passed either m_xwindow or m_wlEGLWindow
|
|
| 145 | + // depending on whether we are using X11 or Wayland.
|
|
| 146 | + EGLSurface CallCreatePlatformWindowSurface(void *window) const;
|
|
| 147 | + |
|
| 134 | 148 | |
| 135 | 149 | EGLConfig m_config = nullptr;
|
| 136 | 150 | EGLDisplay m_display = nullptr;
|
| ... | ... | @@ -147,8 +161,8 @@ private: |
| 147 | 161 | // the global/default versions of the above
|
| 148 | 162 | static EGLConfig ms_glEGLConfig;
|
| 149 | 163 | |
| 150 | - friend void wxEGLUpdatePosition(wxGLCanvasEGL* win);
|
|
| 151 | - friend void wxEGLSetScale(wxGLCanvasEGL* win, int scale);
|
|
| 164 | + // Called from GTK callbacks and needs access to private members.
|
|
| 165 | + friend void wxEGLUpdateGeometry(GtkWidget* widget, wxGLCanvasEGL* win);
|
|
| 152 | 166 | };
|
| 153 | 167 | |
| 154 | 168 | // ----------------------------------------------------------------------------
|
| ... | ... | @@ -901,34 +901,15 @@ void wxAuiTabContainer::RenderButtons(wxDC& dc, wxWindow* wnd, |
| 901 | 901 | // Render() renders the tab catalog to the specified DC
|
| 902 | 902 | // It is a virtual function and can be overridden to
|
| 903 | 903 | // provide custom drawing capabilities
|
| 904 | -void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
|
|
| 904 | +void wxAuiTabContainer::Render(wxDC* pdc, wxWindow* wnd)
|
|
| 905 | 905 | {
|
| 906 | - if (!raw_dc || !raw_dc->IsOk())
|
|
| 907 | - return;
|
|
| 908 | - |
|
| 909 | 906 | if (m_rect.IsEmpty())
|
| 910 | 907 | return;
|
| 911 | 908 | |
| 912 | 909 | size_t i;
|
| 913 | 910 | size_t page_count = m_pages.GetCount();
|
| 914 | 911 | |
| 915 | -#if wxALWAYS_NATIVE_DOUBLE_BUFFER
|
|
| 916 | - wxDC& dc = *raw_dc;
|
|
| 917 | -#else
|
|
| 918 | - wxMemoryDC dc;
|
|
| 919 | - |
|
| 920 | - // use the same layout direction as the window DC uses to ensure that the
|
|
| 921 | - // text is rendered correctly
|
|
| 922 | - dc.SetLayoutDirection(raw_dc->GetLayoutDirection());
|
|
| 923 | - |
|
| 924 | - wxBitmap bmp;
|
|
| 925 | - // create off-screen bitmap
|
|
| 926 | - bmp.Create(m_rect.GetWidth(), m_rect.GetHeight(),*raw_dc);
|
|
| 927 | - dc.SelectObject(bmp);
|
|
| 928 | - |
|
| 929 | - if (!dc.IsOk())
|
|
| 930 | - return;
|
|
| 931 | -#endif
|
|
| 912 | + wxDC& dc = *pdc;
|
|
| 932 | 913 | |
| 933 | 914 | // draw background
|
| 934 | 915 | m_art->DrawBackground(dc, wnd, m_rect);
|
| ... | ... | @@ -1015,13 +996,6 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd) |
| 1015 | 996 | {
|
| 1016 | 997 | m_art->DrawPageTab(dc, wnd, m_pages.Item(active), active_rect);
|
| 1017 | 998 | }
|
| 1018 | - |
|
| 1019 | - |
|
| 1020 | -#if !wxALWAYS_NATIVE_DOUBLE_BUFFER
|
|
| 1021 | - raw_dc->Blit(m_rect.x, m_rect.y,
|
|
| 1022 | - m_rect.GetWidth(), m_rect.GetHeight(),
|
|
| 1023 | - &dc, 0, 0);
|
|
| 1024 | -#endif
|
|
| 1025 | 999 | }
|
| 1026 | 1000 | |
| 1027 | 1001 | // Is the tab visible?
|
| ... | ... | @@ -1409,7 +1383,7 @@ wxRect wxAuiTabCtrl::GetHintScreenRect() const |
| 1409 | 1383 | |
| 1410 | 1384 | void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
|
| 1411 | 1385 | {
|
| 1412 | - wxPaintDC dc(this);
|
|
| 1386 | + wxAutoBufferedPaintDC dc(this);
|
|
| 1413 | 1387 | |
| 1414 | 1388 | if (GetPageCount() > 0)
|
| 1415 | 1389 | Render(&dc, this);
|
| ... | ... | @@ -44,19 +44,18 @@ public: |
| 44 | 44 | virtual bool OnInit() override { return true; }
|
| 45 | 45 | virtual void OnExit() override { wxDELETE(ms_buffer); }
|
| 46 | 46 | |
| 47 | - static wxBitmap* GetBuffer(wxDC* dc, int w, int h)
|
|
| 47 | + static wxBitmap* GetBuffer(wxDC* dc, wxSize size)
|
|
| 48 | 48 | {
|
| 49 | 49 | if ( ms_usingSharedBuffer )
|
| 50 | - return DoCreateBuffer(dc, w, h);
|
|
| 50 | + return DoCreateBuffer(dc, size);
|
|
| 51 | 51 | |
| 52 | 52 | if ( !ms_buffer ||
|
| 53 | - w > ms_buffer->GetLogicalWidth() ||
|
|
| 54 | - h > ms_buffer->GetLogicalHeight() ||
|
|
| 53 | + !ms_buffer->GetLogicalSize().IsAtLeast(size) ||
|
|
| 55 | 54 | (dc && dc->GetContentScaleFactor() != ms_buffer->GetScaleFactor()) )
|
| 56 | 55 | {
|
| 57 | 56 | delete ms_buffer;
|
| 58 | 57 | |
| 59 | - ms_buffer = DoCreateBuffer(dc, w, h);
|
|
| 58 | + ms_buffer = DoCreateBuffer(dc, size);
|
|
| 60 | 59 | }
|
| 61 | 60 | |
| 62 | 61 | ms_usingSharedBuffer = true;
|
| ... | ... | @@ -77,14 +76,30 @@ public: |
| 77 | 76 | }
|
| 78 | 77 | |
| 79 | 78 | private:
|
| 80 | - static wxBitmap* DoCreateBuffer(wxDC* dc, int w, int h)
|
|
| 79 | + static wxBitmap* DoCreateBuffer(wxDC* dc, wxSize size)
|
|
| 81 | 80 | {
|
| 82 | 81 | const double scale = dc ? dc->GetContentScaleFactor() : 1.0;
|
| 83 | 82 | wxBitmap* const buffer = new wxBitmap;
|
| 84 | 83 | |
| 85 | 84 | // we must always return a valid bitmap but creating a bitmap of
|
| 86 | 85 | // size 0 would fail, so create a 1*1 bitmap in this case
|
| 87 | - buffer->CreateWithLogicalSize(wxMax(w, 1), wxMax(h, 1), scale);
|
|
| 86 | + size.IncTo(wxSize(1, 1));
|
|
| 87 | + |
|
| 88 | + // Explicitly request 24bpp bitmap under MSW to avoid slow down when
|
|
| 89 | + // drawing bitmaps with alpha channel on 32bpp bitmap: as explained in
|
|
| 90 | + // AlphaBlt() implementation in src/msw/dc.cpp, we need to manually
|
|
| 91 | + // reset alpha values in this case, which involves converting the
|
|
| 92 | + // bitmap to DIB and back and may be very slow. As we don't really care
|
|
| 93 | + // about the alpha values in the backing store bitmap (everything is
|
|
| 94 | + // already blended when drawing to it), use 24bpp bitmap to avoid this.
|
|
| 95 | + constexpr int depth =
|
|
| 96 | +#if defined(__WXMSW__)
|
|
| 97 | + 24;
|
|
| 98 | +#else
|
|
| 99 | + wxBITMAP_SCREEN_DEPTH;
|
|
| 100 | +#endif
|
|
| 101 | + |
|
| 102 | + buffer->CreateWithLogicalSize(size, scale, depth);
|
|
| 88 | 103 | |
| 89 | 104 | return buffer;
|
| 90 | 105 | }
|
| ... | ... | @@ -104,18 +119,18 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxSharedDCBufferManager, wxModule); |
| 104 | 119 | // wxBufferedDC
|
| 105 | 120 | // ============================================================================
|
| 106 | 121 | |
| 107 | -void wxBufferedDC::UseBuffer(wxCoord w, wxCoord h)
|
|
| 122 | +void wxBufferedDC::UseBuffer(wxSize size)
|
|
| 108 | 123 | {
|
| 109 | - wxCHECK_RET( w >= -1 && h >= -1, "Invalid buffer size" );
|
|
| 124 | + wxCHECK_RET( size.x >= -1 && size.y >= -1, "Invalid buffer size" );
|
|
| 110 | 125 | |
| 111 | 126 | if ( !m_buffer || !m_buffer->IsOk() )
|
| 112 | 127 | {
|
| 113 | - if ( w == -1 || h == -1 )
|
|
| 114 | - m_dc->GetSize(&w, &h);
|
|
| 128 | + if ( !size.IsFullySpecified() )
|
|
| 129 | + size = m_dc->GetSize();
|
|
| 115 | 130 | |
| 116 | - m_buffer = wxSharedDCBufferManager::GetBuffer(m_dc, w, h);
|
|
| 131 | + m_buffer = wxSharedDCBufferManager::GetBuffer(m_dc, size);
|
|
| 117 | 132 | m_style |= wxBUFFER_USES_SHARED_BUFFER;
|
| 118 | - m_area.Set(w,h);
|
|
| 133 | + m_area = size;
|
|
| 119 | 134 | }
|
| 120 | 135 | else
|
| 121 | 136 | m_area = m_buffer->GetSize();
|
| ... | ... | @@ -601,7 +601,7 @@ wxRenameFile(const wxString& file1, const wxString& file2, bool overwrite) |
| 601 | 601 | |
| 602 | 602 | if ( !overwrite && wxFileExists(file2) )
|
| 603 | 603 | {
|
| 604 | - wxLogSysError
|
|
| 604 | + wxLogError
|
|
| 605 | 605 | (
|
| 606 | 606 | _("Failed to rename the file '%s' to '%s' because the destination file already exists."),
|
| 607 | 607 | file1.c_str(), file2.c_str()
|
| ... | ... | @@ -20,6 +20,7 @@ |
| 20 | 20 | #include "wx/qt/private/winevent.h"
|
| 21 | 21 | #include "wx/qt/private/treeitemdelegate.h"
|
| 22 | 22 | |
| 23 | +#include <QtWidgets/QApplication>
|
|
| 23 | 24 | #include <QtWidgets/QTreeWidget>
|
| 24 | 25 | #include <QtWidgets/QHeaderView>
|
| 25 | 26 | #include <QtWidgets/QScrollBar>
|
| ... | ... | @@ -175,9 +176,11 @@ private: |
| 175 | 176 | |
| 176 | 177 | class wxQTreeWidget : public wxQtEventSignalHandler<QTreeWidget, wxTreeCtrl>
|
| 177 | 178 | {
|
| 179 | + using BaseClass = wxQtEventSignalHandler<QTreeWidget, wxTreeCtrl>;
|
|
| 180 | + |
|
| 178 | 181 | public:
|
| 179 | 182 | wxQTreeWidget(wxWindow *parent, wxTreeCtrl *handler) :
|
| 180 | - wxQtEventSignalHandler<QTreeWidget, wxTreeCtrl>(parent, handler),
|
|
| 183 | + BaseClass(parent, handler),
|
|
| 181 | 184 | m_item_delegate(handler),
|
| 182 | 185 | m_closing_editor(0)
|
| 183 | 186 | {
|
| ... | ... | @@ -217,14 +220,6 @@ public: |
| 217 | 220 | });
|
| 218 | 221 | }
|
| 219 | 222 | |
| 220 | - virtual void paintEvent(QPaintEvent* event) override
|
|
| 221 | - {
|
|
| 222 | - //QT generates warnings if we try to paint to a QTreeWidget
|
|
| 223 | - //(perhaps because it's a compound widget) so we've disabled
|
|
| 224 | - //wx paint and erase background events
|
|
| 225 | - QTreeWidget::paintEvent(event);
|
|
| 226 | - }
|
|
| 227 | - |
|
| 228 | 223 | virtual void mouseReleaseEvent(QMouseEvent * event) override
|
| 229 | 224 | {
|
| 230 | 225 | const QPoint qPos = event->pos();
|
| ... | ... | @@ -264,7 +259,7 @@ public: |
| 264 | 259 | }
|
| 265 | 260 | }
|
| 266 | 261 | |
| 267 | - return wxQtEventSignalHandler<QTreeWidget, wxTreeCtrl>::mouseReleaseEvent(event);
|
|
| 262 | + return BaseClass::mouseReleaseEvent(event);
|
|
| 268 | 263 | }
|
| 269 | 264 | |
| 270 | 265 | wxTextCtrl *GetEditControl()
|
| ... | ... | @@ -357,6 +352,48 @@ protected: |
| 357 | 352 | QTreeView::selectionChanged(selected, deselected);
|
| 358 | 353 | }
|
| 359 | 354 | |
| 355 | + // Helper class which tries to close any open editor as early as possible
|
|
| 356 | + // when the application is shutting down to avoid a crash if closeEditor()
|
|
| 357 | + // pops up any message box. IOW, showing a message/dialog box (using exec())
|
|
| 358 | + // while the application is closing down is dangerous.
|
|
| 359 | + // See note in the Qt documentation of QDialog::exec()
|
|
| 360 | + class SafeEditorCloser : public QObject
|
|
| 361 | + {
|
|
| 362 | + public:
|
|
| 363 | + explicit SafeEditorCloser(wxQTreeWidget* qTreeWidget)
|
|
| 364 | + : m_qTreeWidget(qTreeWidget)
|
|
| 365 | + {
|
|
| 366 | + qApp->installEventFilter(this);
|
|
| 367 | + }
|
|
| 368 | + |
|
| 369 | + ~SafeEditorCloser()
|
|
| 370 | + {
|
|
| 371 | + qApp->removeEventFilter(this);
|
|
| 372 | + }
|
|
| 373 | + |
|
| 374 | + protected:
|
|
| 375 | + bool eventFilter(QObject* obj, QEvent* event) override
|
|
| 376 | + {
|
|
| 377 | + if ( event->type() == QEvent::Close )
|
|
| 378 | + {
|
|
| 379 | + // Don't try to close the editor if there is any active popup window
|
|
| 380 | + // (e.g. selecting Quit from the menu) because the application would
|
|
| 381 | + // hang if closeEditor() pops up any message box.
|
|
| 382 | + if ( !QApplication::activePopupWidget() )
|
|
| 383 | + {
|
|
| 384 | + // This will close any currently opened editor.
|
|
| 385 | + m_qTreeWidget->setCurrentItem(nullptr);
|
|
| 386 | + }
|
|
| 387 | + }
|
|
| 388 | + |
|
| 389 | + return QObject::eventFilter(obj, event);
|
|
| 390 | + }
|
|
| 391 | + |
|
| 392 | + wxQTreeWidget* const m_qTreeWidget;
|
|
| 393 | + };
|
|
| 394 | + |
|
| 395 | + std::unique_ptr<SafeEditorCloser> m_editorCloser;
|
|
| 396 | + |
|
| 360 | 397 | bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event) override
|
| 361 | 398 | {
|
| 362 | 399 | // AllEditTriggers means that editor is about to open, not waiting for double click
|
| ... | ... | @@ -369,6 +406,8 @@ protected: |
| 369 | 406 | return true;
|
| 370 | 407 | }
|
| 371 | 408 | |
| 409 | + m_startEditorText = wxQtConvertString(itemFromIndex(index)->text(0));
|
|
| 410 | + |
|
| 372 | 411 | // Allow event handlers to veto opening the editor
|
| 373 | 412 | wxTreeEvent wx_event(
|
| 374 | 413 | wxEVT_TREE_BEGIN_LABEL_EDIT,
|
| ... | ... | @@ -378,7 +417,15 @@ protected: |
| 378 | 417 | if (GetHandler()->HandleWindowEvent(wx_event) && !wx_event.IsAllowed())
|
| 379 | 418 | return false;
|
| 380 | 419 | }
|
| 381 | - return QTreeWidget::edit(index, trigger, event);
|
|
| 420 | + |
|
| 421 | + if ( QTreeWidget::edit(index, trigger, event) )
|
|
| 422 | + {
|
|
| 423 | + m_editorCloser.reset(new SafeEditorCloser(this));
|
|
| 424 | + |
|
| 425 | + return true;
|
|
| 426 | + }
|
|
| 427 | + |
|
| 428 | + return false;
|
|
| 382 | 429 | }
|
| 383 | 430 | |
| 384 | 431 | void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint) override
|
| ... | ... | @@ -390,6 +437,15 @@ protected: |
| 390 | 437 | if (guard.IsInside())
|
| 391 | 438 | return;
|
| 392 | 439 | |
| 440 | + m_editorCloser.reset(nullptr);
|
|
| 441 | + |
|
| 442 | + if (!GetHandler())
|
|
| 443 | + {
|
|
| 444 | + // The handler may have already been destroyed, when quitting
|
|
| 445 | + // the application using Ctrl+Q for example.
|
|
| 446 | + return;
|
|
| 447 | + }
|
|
| 448 | + |
|
| 393 | 449 | // There can be multiple calls to close editor when the item loses focus
|
| 394 | 450 | const QModelIndex current_index = m_item_delegate.GetCurrentModelIndex();
|
| 395 | 451 | if (!current_index.isValid())
|
| ... | ... | @@ -400,7 +456,10 @@ protected: |
| 400 | 456 | GetHandler(),
|
| 401 | 457 | wxQtConvertTreeItem(itemFromIndex(current_index))
|
| 402 | 458 | );
|
| 403 | - if (hint == QAbstractItemDelegate::RevertModelCache)
|
|
| 459 | + |
|
| 460 | + const wxString editor_text = m_item_delegate.GetEditControl()->GetLineText(0);
|
|
| 461 | + |
|
| 462 | + if (hint == QAbstractItemDelegate::RevertModelCache || editor_text == m_startEditorText)
|
|
| 404 | 463 | {
|
| 405 | 464 | event.SetEditCanceled(true);
|
| 406 | 465 | EmitEvent(event);
|
| ... | ... | @@ -408,7 +467,6 @@ protected: |
| 408 | 467 | else
|
| 409 | 468 | {
|
| 410 | 469 | // Allow event handlers to decide whether to accept edited text
|
| 411 | - const wxString editor_text = m_item_delegate.GetEditControl()->GetLineText(0);
|
|
| 412 | 470 | event.SetLabel(editor_text);
|
| 413 | 471 | if (!GetHandler()->HandleWindowEvent(event) || event.IsAllowed())
|
| 414 | 472 | m_item_delegate.AcceptModelData(editor, model(), current_index);
|
| ... | ... | @@ -595,7 +653,7 @@ private: |
| 595 | 653 | virtual void mouseMoveEvent(QMouseEvent *event) override
|
| 596 | 654 | {
|
| 597 | 655 | const bool wasDragging = state() == DraggingState;
|
| 598 | - wxQtEventSignalHandler<QTreeWidget, wxTreeCtrl>::mouseMoveEvent(event);
|
|
| 656 | + BaseClass::mouseMoveEvent(event);
|
|
| 599 | 657 | |
| 600 | 658 | const bool nowDragging = state() == DraggingState;
|
| 601 | 659 | if ( !wasDragging && nowDragging )
|
| ... | ... | @@ -643,6 +701,8 @@ private: |
| 643 | 701 | typedef std::map<QTreeWidgetItem*,ImageState> ImageStateMap;
|
| 644 | 702 | ImageStateMap m_imageStates;
|
| 645 | 703 | |
| 704 | + wxString m_startEditorText;
|
|
| 705 | + |
|
| 646 | 706 | // Place holder image to reserve enough space in a row
|
| 647 | 707 | // for us to draw our icon
|
| 648 | 708 | QPixmap m_placeHolderImage;
|
| ... | ... | @@ -697,8 +757,6 @@ bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id, |
| 697 | 757 | |
| 698 | 758 | wxTreeCtrl::~wxTreeCtrl()
|
| 699 | 759 | {
|
| 700 | - if ( GetQTreeWidget() )
|
|
| 701 | - GetQTreeWidget()->deleteLater();
|
|
| 702 | 760 | }
|
| 703 | 761 | |
| 704 | 762 | wxQTreeWidget* wxTreeCtrl::GetQTreeWidget() const
|
| ... | ... | @@ -1215,14 +1215,6 @@ void wxWindowQt::DoSetSize(int x, int y, int width, int height, int sizeFlags ) |
| 1215 | 1215 | height = BEST_SIZE.y;
|
| 1216 | 1216 | }
|
| 1217 | 1217 | |
| 1218 | - if ( !GetHandle()->isVisible() && QtGetClientWidget() != GetHandle() )
|
|
| 1219 | - {
|
|
| 1220 | - if ( width != -1 && height != -1 )
|
|
| 1221 | - {
|
|
| 1222 | - m_pendingSize = true;
|
|
| 1223 | - }
|
|
| 1224 | - }
|
|
| 1225 | - |
|
| 1226 | 1218 | int w, h;
|
| 1227 | 1219 | GetSize(&w, &h);
|
| 1228 | 1220 | if (width == -1)
|
| ... | ... | @@ -1294,7 +1286,7 @@ void wxWindowQt::DoMoveWindow(int x, int y, int width, int height) |
| 1294 | 1286 | |
| 1295 | 1287 | const auto clientSize = wxQtSetClientSize(qtWidget, width, height);
|
| 1296 | 1288 | |
| 1297 | - if (!qtWidget->isVisible() && clientSize.x > 0 && clientSize.y > 0)
|
|
| 1289 | + if ( qtWidget->testAttribute(Qt::WA_PendingResizeEvent) )
|
|
| 1298 | 1290 | {
|
| 1299 | 1291 | m_pendingClientSize = clientSize;
|
| 1300 | 1292 | }
|
| ... | ... | @@ -2001,12 +1993,11 @@ bool wxWindowQt::QtHandleShowEvent ( QWidget *handler, QEvent *event ) |
| 2001 | 1993 | if ( GetHandle() != handler )
|
| 2002 | 1994 | return false;
|
| 2003 | 1995 | |
| 2004 | - if ( m_pendingSize )
|
|
| 1996 | + if ( handler != QtGetClientWidget() &&
|
|
| 1997 | + handler->testAttribute(Qt::WA_PendingResizeEvent) )
|
|
| 2005 | 1998 | {
|
| 2006 | - const auto frameSize = GetHandle()->geometry().size();
|
|
| 2007 | - wxQtSetClientSize(GetHandle(), frameSize.width(), frameSize.height());
|
|
| 2008 | - |
|
| 2009 | - m_pendingSize = false;
|
|
| 1999 | + const auto frameSize = handler->geometry().size();
|
|
| 2000 | + wxQtSetClientSize(handler, frameSize.width(), frameSize.height());
|
|
| 2010 | 2001 | }
|
| 2011 | 2002 | |
| 2012 | 2003 | wxShowEvent e(GetId(), event->type() == QEvent::Show);
|
| ... | ... | @@ -37,8 +37,17 @@ |
| 37 | 37 | |
| 38 | 38 | #include <memory>
|
| 39 | 39 | |
| 40 | +namespace
|
|
| 41 | +{
|
|
| 42 | + |
|
| 40 | 43 | constexpr const char* TRACE_EGL = "glegl";
|
| 41 | 44 | |
| 45 | +// EGL version initialized by InitConfig().
|
|
| 46 | +EGLint gs_eglMajor = 0;
|
|
| 47 | +EGLint gs_eglMinor = 0;
|
|
| 48 | + |
|
| 49 | +} // anonymous namespace
|
|
| 50 | + |
|
| 42 | 51 | // ----------------------------------------------------------------------------
|
| 43 | 52 | // wxGLContextAttrs: OpenGL rendering context attributes
|
| 44 | 53 | // ----------------------------------------------------------------------------
|
| ... | ... | @@ -420,10 +429,9 @@ void wxGLCanvasEGL::OnWLFrameCallback() |
| 420 | 429 | |
| 421 | 430 | #ifdef GDK_WINDOWING_WAYLAND
|
| 422 | 431 | |
| 423 | -// Helper declared as friend in the header and so can access m_wlSubsurface.
|
|
| 424 | -void wxEGLUpdatePosition(wxGLCanvasEGL* win)
|
|
| 432 | +void wxGLCanvasEGL::UpdateSubsurfacePosition()
|
|
| 425 | 433 | {
|
| 426 | - if ( !win->m_wlSubsurface )
|
|
| 434 | + if ( !m_wlSubsurface )
|
|
| 427 | 435 | {
|
| 428 | 436 | // In some circumstances such as when reparenting a canvas between two hidden
|
| 429 | 437 | // toplevel windows, GTK will call size-allocate before mapping the canvas
|
| ... | ... | @@ -432,13 +440,21 @@ void wxEGLUpdatePosition(wxGLCanvasEGL* win) |
| 432 | 440 | }
|
| 433 | 441 | |
| 434 | 442 | int x, y;
|
| 435 | - gdk_window_get_origin(win->GTKGetDrawingWindow(), &x, &y);
|
|
| 436 | - wl_subsurface_set_position(win->m_wlSubsurface, x, y);
|
|
| 443 | + gdk_window_get_origin(GTKGetDrawingWindow(), &x, &y);
|
|
| 444 | + wl_subsurface_set_position(m_wlSubsurface, x, y);
|
|
| 437 | 445 | }
|
| 438 | 446 | |
| 439 | -// Helper declared as friend in the header and so can access m_wlSurface.
|
|
| 440 | -void wxEGLSetScale(wxGLCanvasEGL* win, int scale)
|
|
| 447 | +// Helper declared as friend in the header and so can access member variables.
|
|
| 448 | +//
|
|
| 449 | +// Used when size or scale factor changes
|
|
| 450 | +void wxEGLUpdateGeometry(GtkWidget* widget, wxGLCanvasEGL* win)
|
|
| 441 | 451 | {
|
| 452 | + int scale = gtk_widget_get_scale_factor(widget);
|
|
| 453 | + wl_egl_window_resize(win->m_wlEGLWindow, win->m_width * scale,
|
|
| 454 | + win->m_height * scale, 0, 0);
|
|
| 455 | + |
|
| 456 | + win->UpdateSubsurfacePosition();
|
|
| 457 | + |
|
| 442 | 458 | wl_surface_set_buffer_scale(win->m_wlSurface, scale);
|
| 443 | 459 | }
|
| 444 | 460 | |
| ... | ... | @@ -497,17 +513,76 @@ static void gtk_glcanvas_size_callback(GtkWidget *widget, |
| 497 | 513 | GtkAllocation *,
|
| 498 | 514 | wxGLCanvasEGL *win)
|
| 499 | 515 | {
|
| 500 | - int scale = gtk_widget_get_scale_factor(widget);
|
|
| 501 | - wl_egl_window_resize(win->m_wlEGLWindow, win->m_width * scale,
|
|
| 502 | - win->m_height * scale, 0, 0);
|
|
| 516 | + wxEGLUpdateGeometry(widget, win);
|
|
| 517 | +}
|
|
| 503 | 518 | |
| 504 | - wxEGLUpdatePosition(win);
|
|
| 505 | - wxEGLSetScale(win, scale);
|
|
| 519 | +static void gtk_glcanvas_scale_factor_notify(GtkWidget* widget,
|
|
| 520 | + GParamSpec*,
|
|
| 521 | + wxGLCanvasEGL *win)
|
|
| 522 | +{
|
|
| 523 | + wxEGLUpdateGeometry(widget, win);
|
|
| 506 | 524 | }
|
| 507 | 525 | |
| 508 | 526 | } // extern "C"
|
| 509 | 527 | #endif // GDK_WINDOWING_WAYLAND
|
| 510 | 528 | |
| 529 | +EGLSurface wxGLCanvasEGL::CallCreatePlatformWindowSurface(void *window) const
|
|
| 530 | +{
|
|
| 531 | + // Type of eglCreatePlatformWindowSurface[EXT]().
|
|
| 532 | + typedef EGLSurface (*CreatePlatformWindowSurface)(EGLDisplay display,
|
|
| 533 | + EGLConfig config,
|
|
| 534 | + void* window,
|
|
| 535 | + EGLAttrib const* attrib_list);
|
|
| 536 | + |
|
| 537 | + if ( gs_eglMajor > 1 || (gs_eglMajor == 1 && gs_eglMinor >= 5) )
|
|
| 538 | + {
|
|
| 539 | + // EGL 1.5 or later: use eglCreatePlatformWindowSurface() which must be
|
|
| 540 | + // available.
|
|
| 541 | + static CreatePlatformWindowSurface s_eglCreatePlatformWindowSurface = nullptr;
|
|
| 542 | + if ( !s_eglCreatePlatformWindowSurface )
|
|
| 543 | + {
|
|
| 544 | + s_eglCreatePlatformWindowSurface = reinterpret_cast<CreatePlatformWindowSurface>(
|
|
| 545 | + eglGetProcAddress("eglCreatePlatformWindowSurface"));
|
|
| 546 | + }
|
|
| 547 | + |
|
| 548 | + // This check is normally superfluous but avoid crashing just in case
|
|
| 549 | + // it isn't.
|
|
| 550 | + if ( s_eglCreatePlatformWindowSurface )
|
|
| 551 | + {
|
|
| 552 | + return s_eglCreatePlatformWindowSurface(m_display, m_config,
|
|
| 553 | + window,
|
|
| 554 | + nullptr);
|
|
| 555 | + }
|
|
| 556 | + }
|
|
| 557 | + |
|
| 558 | + // Try loading the appropriate EGL function on first use.
|
|
| 559 | + static CreatePlatformWindowSurface s_eglCreatePlatformWindowSurfaceEXT = nullptr;
|
|
| 560 | + static bool s_extFuncInitialized = false;
|
|
| 561 | + if ( !s_extFuncInitialized )
|
|
| 562 | + {
|
|
| 563 | + s_extFuncInitialized = true;
|
|
| 564 | + |
|
| 565 | + if ( IsExtensionSupported("EGL_EXT_platform_base") )
|
|
| 566 | + {
|
|
| 567 | + s_eglCreatePlatformWindowSurfaceEXT = reinterpret_cast<CreatePlatformWindowSurface>(
|
|
| 568 | + eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
|
|
| 569 | + }
|
|
| 570 | + }
|
|
| 571 | + |
|
| 572 | + if ( s_eglCreatePlatformWindowSurfaceEXT )
|
|
| 573 | + {
|
|
| 574 | + return s_eglCreatePlatformWindowSurfaceEXT(m_display, m_config,
|
|
| 575 | + window,
|
|
| 576 | + nullptr);
|
|
| 577 | + }
|
|
| 578 | + else
|
|
| 579 | + {
|
|
| 580 | + return eglCreateWindowSurface(m_display, m_config,
|
|
| 581 | + reinterpret_cast<EGLNativeWindowType>(window),
|
|
| 582 | + nullptr);
|
|
| 583 | + }
|
|
| 584 | +}
|
|
| 585 | + |
|
| 511 | 586 | bool wxGLCanvasEGL::CreateSurface()
|
| 512 | 587 | {
|
| 513 | 588 | m_display = GetDisplay();
|
| ... | ... | @@ -528,8 +603,7 @@ bool wxGLCanvasEGL::CreateSurface() |
| 528 | 603 | }
|
| 529 | 604 | |
| 530 | 605 | m_xwindow = GDK_WINDOW_XID(window);
|
| 531 | - m_surface = eglCreatePlatformWindowSurface(m_display, m_config,
|
|
| 532 | - &m_xwindow, nullptr);
|
|
| 606 | + m_surface = CallCreatePlatformWindowSurface(&m_xwindow);
|
|
| 533 | 607 | }
|
| 534 | 608 | #endif
|
| 535 | 609 | #ifdef GDK_WINDOWING_WAYLAND
|
| ... | ... | @@ -560,8 +634,7 @@ bool wxGLCanvasEGL::CreateSurface() |
| 560 | 634 | wl_surface_set_buffer_scale(m_wlSurface, scale);
|
| 561 | 635 | m_wlEGLWindow = wl_egl_window_create(m_wlSurface, w * scale,
|
| 562 | 636 | h * scale);
|
| 563 | - m_surface = eglCreatePlatformWindowSurface(m_display, m_config,
|
|
| 564 | - m_wlEGLWindow, nullptr);
|
|
| 637 | + m_surface = CallCreatePlatformWindowSurface(m_wlEGLWindow);
|
|
| 565 | 638 | |
| 566 | 639 | // We need to use "map-event" instead of "map" to ensure that the
|
| 567 | 640 | // widget's underlying Wayland surface has been created.
|
| ... | ... | @@ -574,8 +647,17 @@ bool wxGLCanvasEGL::CreateSurface() |
| 574 | 647 | // Not unmapping the canvas as soon as possible causes problems when reparenting
|
| 575 | 648 | g_signal_connect(m_widget, "unmap",
|
| 576 | 649 | G_CALLBACK(gtk_glcanvas_unmap_callback), this);
|
| 650 | + |
|
| 651 | + // We connect to "size-allocate" to update the position of the
|
|
| 652 | + // subsurface when the toplevel window is moved, which also updates the
|
|
| 653 | + // scale as a side effect, but we need to also separately connect to
|
|
| 654 | + // "notify::scale-factor" to catch scale changes, which is especially
|
|
| 655 | + // important initially, as we don't get a "size-allocate" with the
|
|
| 656 | + // correct scale when the window is created.
|
|
| 577 | 657 | g_signal_connect(m_widget, "size-allocate",
|
| 578 | 658 | G_CALLBACK(gtk_glcanvas_size_callback), this);
|
| 659 | + g_signal_connect(m_widget, "notify::scale-factor",
|
|
| 660 | + G_CALLBACK (gtk_glcanvas_scale_factor_notify), this);
|
|
| 579 | 661 | }
|
| 580 | 662 | #endif
|
| 581 | 663 | |
| ... | ... | @@ -626,7 +708,7 @@ void wxGLCanvasEGL::CreateWaylandSubsurface() |
| 626 | 708 | wxCHECK_RET( m_wlSubsurface, "Unable to get EGL subsurface" );
|
| 627 | 709 | |
| 628 | 710 | wl_subsurface_set_desync(m_wlSubsurface);
|
| 629 | - wxEGLUpdatePosition(this);
|
|
| 711 | + UpdateSubsurfacePosition();
|
|
| 630 | 712 | m_wlFrameCallbackHandler = wl_surface_frame(surface);
|
| 631 | 713 | wl_callback_add_listener(m_wlFrameCallbackHandler,
|
| 632 | 714 | &wl_frame_listener, this);
|
| ... | ... | @@ -671,22 +753,20 @@ EGLConfig wxGLCanvasEGL::InitConfig(const wxGLAttributes& dispAttrs) |
| 671 | 753 | return nullptr;
|
| 672 | 754 | }
|
| 673 | 755 | |
| 674 | - EGLint eglMajor = 0;
|
|
| 675 | - EGLint eglMinor = 0;
|
|
| 676 | - if ( !eglInitialize(dpy, &eglMajor, &eglMinor) )
|
|
| 756 | + if ( !eglInitialize(dpy, &gs_eglMajor, &gs_eglMinor) )
|
|
| 677 | 757 | {
|
| 678 | 758 | wxFAIL_MSG("eglInitialize failed");
|
| 679 | 759 | return nullptr;
|
| 680 | 760 | }
|
| 681 | 761 | |
| 682 | 762 | // The runtime EGL version cannot be known until EGL has been initialized.
|
| 683 | - if ( eglMajor < 1 || (eglMajor == 1 && eglMinor < 5) )
|
|
| 763 | + if ( gs_eglMajor < 1 || (gs_eglMajor == 1 && gs_eglMinor < 4) )
|
|
| 684 | 764 | {
|
| 685 | 765 | // Ignore the return value here, we cannot recover at this point.
|
| 686 | 766 | eglTerminate(dpy);
|
| 687 | - wxLogError(wxString::Format(
|
|
| 688 | - "EGL version is %d.%d. EGL version 1.5 or greater is required.",
|
|
| 689 | - eglMajor, eglMinor));
|
|
| 767 | + wxLogError(
|
|
| 768 | + _("EGL version is %d.%d but version 1.4 or greater is required."),
|
|
| 769 | + gs_eglMajor, gs_eglMinor);
|
|
| 690 | 770 | return nullptr;
|
| 691 | 771 | }
|
| 692 | 772 |
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help