From 3272509ae50ed30211c11dd7ea2ee2249feac948 Mon Sep 17 00:00:00 2001 From: Steve Browne Date: Fri, 25 Oct 2019 04:10:18 +0200 Subject: [PATCH 01/22] Prevent default OpenGL context creation in wxGLCanvas under macOS This renders unnecessary the previous workarounds for using NSOpenGLView as the base class for wxGLCanvas view, so revert them. See: - 2ab430965c457de680d3a3ea37445b7dfa0090e0 which introduced the use of NSOpenGLView (see https://github.com/wxWidgets/wxWidgets/pull/846). - ea68934b8e3374d03e876f56a1637663de351cb7 for the first workaround due to the use of NSOpenGLView and its default context creation. - 6974a6ceaa8f81168459119f98d7ed9a03b1c88d for the refinement of the workaround above. - e6ae83c386427b1cd2840e5f8059310e8b4fb3ea and b822e9efe8f35e1683665332cf21f941be89404e which tweaked it futher. This commit renders unnecessary all the changes since the initial switch to NSOpenGLView by just preventing NSOpenGLView from creating its own context and thus enforcing the use of wxGLContext associated with wxGLCanvas. Closes https://github.com/wxWidgets/wxWidgets/pull/1617 --- src/osx/cocoa/glcanvas.mm | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/osx/cocoa/glcanvas.mm b/src/osx/cocoa/glcanvas.mm index b2df34d9df..505b3a5e4b 100644 --- a/src/osx/cocoa/glcanvas.mm +++ b/src/osx/cocoa/glcanvas.mm @@ -150,6 +150,13 @@ WXGLPixelFormat WXGLChoosePixelFormat(const int *GLAttrs, impl->doCommandBySelector(aSelector, self, _cmd); } +- (NSOpenGLContext *) openGLContext +{ + // Prevent the NSOpenGLView from making it's own context + // We want to force using wxGLContexts + return NULL; +} + @end bool wxGLCanvas::DoCreate(wxWindow *parent, @@ -201,24 +208,6 @@ bool wxGLContext::SetCurrent(const wxGLCanvas& win) const [m_glContext makeCurrentContext]; - // the missing redraw upon resize problem only happens when linked against 10.14 -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 - // At least under macOS 10.14.5 we need to do this in order to update the - // context with the new size information after the window is resized. - if ( WX_IS_MACOS_AVAILABLE_FULL(10, 14, 5) ) - { - if ( WX_IS_MACOS_AVAILABLE(10, 15) ) - { - // no workaround needed under 10.15 anymore - } - else - { - NSOpenGLView *v = (NSOpenGLView *)win.GetHandle(); - [v setOpenGLContext: m_glContext]; - } - } -#endif - return true; } From 616ad0d92b957dbd625a2905ea4e4320a23c4606 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 Oct 2019 02:47:50 +0200 Subject: [PATCH 02/22] Show status bar fields coordinates in a message box in the sample Showing them directly on the screen using wxClientDC doesn't work in all ports, notable under Mac. See #18469. --- samples/statbar/statbar.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/samples/statbar/statbar.cpp b/samples/statbar/statbar.cpp index 9a4f0e4128..3811033306 100644 --- a/samples/statbar/statbar.cpp +++ b/samples/statbar/statbar.cpp @@ -668,13 +668,28 @@ void MyFrame::OnShowFieldsRect(wxCommandEvent& WXUNUSED(event)) dc.SetPen(*wxRED_PEN); dc.SetBrush(*wxTRANSPARENT_BRUSH); + // Not all systems support drawing using wxClientDC, so also show the + // coordinates in a message box. + wxString msg; + const wxSize size = pStat->GetClientSize(); + msg.Printf("Status bar client size is (%d,%d)\n\n", size.x, size.y); + const int n = pStat->GetFieldsCount(); for ( int i = 0; i < n; i++ ) { wxRect r; if ( pStat->GetFieldRect(i, r) ) + { + msg += wxString::Format("Field %d rectangle is (%d,%d)-(%d,%d)\n", + i, + r.x, r.y, + r.x + r.width, + r.y + r.height); dc.DrawRectangle(r); + } } + + wxLogMessage("%s", msg); } void MyFrame::OnUpdateStatusBarToggle(wxUpdateUIEvent& event) From 288b570e1139b8d43a33772b6165d1700df3f2dc Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 Oct 2019 02:54:50 +0200 Subject: [PATCH 03/22] Don't account for size grip under platforms not showing it Size grip in generic wxStatusBar is only supported in wxGTK as it's drawn using GTK functions, but this is not really a problem as other platforms either use native implementations (MSW, Qt) or shouldn't show size grip anyhow as it looks non-native (Mac). So just ensure we don't leave space for the grip if it's not shown, correcting the change of 6c1b2b23cf5e707b9971e37eb14715836d9e63e3. Closes #18469. --- include/wx/generic/statusbr.h | 2 +- src/generic/statusbr.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/wx/generic/statusbr.h b/include/wx/generic/statusbr.h index 6d0edd6ec2..996012b07a 100644 --- a/include/wx/generic/statusbr.h +++ b/include/wx/generic/statusbr.h @@ -81,7 +81,7 @@ protected: // true if the status bar shows the size grip: for this it must have // wxSTB_SIZEGRIP style and the window it is attached to must be resizable - // and not maximized + // and not maximized (note that currently size grip is only used in wxGTK) bool ShowsSizeGrip() const; // returns the position and the size of the size grip diff --git a/src/generic/statusbr.cpp b/src/generic/statusbr.cpp index eecc549de6..53ca7e1a8c 100644 --- a/src/generic/statusbr.cpp +++ b/src/generic/statusbr.cpp @@ -194,12 +194,17 @@ void wxStatusBarGeneric::DoUpdateFieldWidths() bool wxStatusBarGeneric::ShowsSizeGrip() const { + // Currently drawing size grip is implemented only in wxGTK. +#ifdef __WXGTK20__ if ( !HasFlag(wxSTB_SIZEGRIP) ) return false; wxTopLevelWindow * const tlw = wxDynamicCast(wxGetTopLevelParent(GetParent()), wxTopLevelWindow); return tlw && !tlw->IsMaximized() && tlw->HasFlag(wxRESIZE_BORDER); +#else // !__WXGTK20__ + return false; +#endif // __WXGTK20__/!__WXGTK20__ } void wxStatusBarGeneric::DrawFieldText(wxDC& dc, const wxRect& rect, int i, int textHeight) From 7a475e4695f43fdff6bd73a2521d73dc373b60aa Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 Oct 2019 03:15:20 +0200 Subject: [PATCH 04/22] Mention CFBundleLocalizations in the i18n overview This is still completely undiscoverable, but slightly better than only mentioning this in a Stack Overflow answer referencing a comment in the bug tracker. Closes #9659. --- docs/doxygen/overviews/internationalization.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/doxygen/overviews/internationalization.h b/docs/doxygen/overviews/internationalization.h index dc84c9007f..3d4f7821ec 100644 --- a/docs/doxygen/overviews/internationalization.h +++ b/docs/doxygen/overviews/internationalization.h @@ -59,6 +59,11 @@ Translating your application involves several steps: given language: see wxLocale. +@note Under macOS you also need to list all the supported languages under + @c CFBundleLocalizations key in your application @c Info.plist file + in order to allow the application to support the corresponding locale. + + @section overview_i18n_mofiles Installing translation catalogs The .mo files with compiled catalogs must be included with the application. From 6d1b6c71c47d26be741a153e913d7845475a2a5a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 Oct 2019 03:49:15 +0200 Subject: [PATCH 05/22] Fix wxUpdateUIEvent prcoessing for standard menu items under Mac Handle these events in the menu itself first, then the window and only then at the application level instead of falling back on the application before searching the window for the handler. This requires using the logic already present in the base class DoProcessEvent() method, so make it protected to allow reuse. Closes #4769. --- include/wx/menu.h | 2 +- src/osx/menu_osx.cpp | 18 +----------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/include/wx/menu.h b/include/wx/menu.h index eb262bc2da..af9f2e7364 100644 --- a/include/wx/menu.h +++ b/include/wx/menu.h @@ -398,7 +398,7 @@ protected: static bool ms_locked; -private: +protected: // Common part of SendEvent() and ProcessMenuEvent(): sends the event to // its intended recipients, returns true if it was processed. static bool DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win); diff --git a/src/osx/menu_osx.cpp b/src/osx/menu_osx.cpp index e24ce81579..75251bc06a 100644 --- a/src/osx/menu_osx.cpp +++ b/src/osx/menu_osx.cpp @@ -326,23 +326,7 @@ bool wxMenu::HandleCommandUpdateStatus( wxMenuItem* item, wxWindow* senderWindow wxUpdateUIEvent event(menuid); event.SetEventObject( this ); - bool processed = false; - - // Try the menu's event handler - { - wxEvtHandler *handler = GetEventHandler(); - if ( handler ) - processed = handler->ProcessEvent(event); - } - - // Try the window the menu was popped up from - // (and up through the hierarchy) - if ( !processed ) - { - wxWindow *win = GetWindow(); - if ( win ) - processed = win->HandleWindowEvent(event); - } + bool processed = DoProcessEvent(this, event, GetWindow()); if ( !processed && senderWindow != NULL) { From 2b3e3d6c108e84c5dfdabaca56408233c420e390 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 25 Oct 2019 17:47:02 +0200 Subject: [PATCH 06/22] Show wxRendererNative::DrawChoice() in the render sample too See #18255. --- samples/render/render.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/samples/render/render.cpp b/samples/render/render.cpp index 835490840f..404c8eb54a 100644 --- a/samples/render/render.cpp +++ b/samples/render/render.cpp @@ -315,7 +315,12 @@ private: renderer.DrawItemText(this, dc, "DrawItemText()", wxRect(x2, y, widthListItem, heightListItem).Inflate(-2, -2), m_align, m_flags | wxCONTROL_SELECTED); - y += lineHeight + heightListItem; + y += heightListItem; + + dc.DrawText("DrawChoice()", x1, y + 20); + renderer.DrawChoice(this, dc, wxRect(x2, y, 80, 50), m_flags); + y += 50; + } int m_flags; From 8648f839e7212962ae966ec896b0b3d378ef1761 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 02:46:39 +0200 Subject: [PATCH 07/22] Don't accept focus for wxRadioBox itself in wxOSX The radio box is just a static box and so can't have focus, only its child radio buttons should have it. This resolves the problem with getting stuck on wxRadioBox when full keyboard access is off, as wxControlContainer code tried to give focus to wxRadioBox because its AcceptsFocusFromKeyboard() returned true, but none of its radio buttons could be focused without full keyboard access. However this introduces a new problem with wxRadioBox being skipped when full keyboard access is on, which will be fixed in the following commit. See #18089. --- src/osx/radiobox_osx.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/osx/radiobox_osx.cpp b/src/osx/radiobox_osx.cpp index 50dbb33b2f..2a7b33c827 100644 --- a/src/osx/radiobox_osx.cpp +++ b/src/osx/radiobox_osx.cpp @@ -102,6 +102,9 @@ bool wxRadioBox::Create( wxWindow *parent, if ( !wxControl::Create( parent, id, pos, size, style, val, name ) ) return false; + // The radio box itself never accepts focus, only its child buttons do. + m_container.DisableSelfFocus(); + // during construction we must keep this at 0, otherwise GetBestSize fails m_noItems = 0; m_noRowsOrCols = majorDim; From 198a4e97a05ad14f388a26c073403fddb63e5e95 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 02:58:29 +0200 Subject: [PATCH 08/22] Fix wrongly cached state of children focusability under Mac Remove caching of whether any of the children accept focus in wxControlContainer as it can change at any moment under Mac, due to full keyboard access being turned on and off (which can be done using Ctrl-F7, i.e. easily, and so this might be something users actually do and not just a theoretical edge case). This also incidentally fixes caching of the wrong focusability state during window initialization, when its children are not yet shown, as [NSView canBecomeKeyView:] used for AcceptsFocusFromKeyboard() implementation under Mac, apparently always returns false for hidden windows. The behaviour under the other platforms should remain the same, but AcceptsFocus() is slower now as it always has to query children instead of being able to avoid doing it when we know that none of them accepts focus anyhow. OTOH this only happens to the windows that don't accept focus themselves and, at least at some moment, don't have any children accepting focus neither, which should be quite rare and optimizing this case doesn't seem to be worth the extra code complexity due to extra preprocessor platform checks. Closes #18089. --- include/wx/containr.h | 15 ++++++--------- src/common/containr.cpp | 12 ++++-------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/include/wx/containr.h b/include/wx/containr.h index c9eb5857c5..aa5ffd625c 100644 --- a/include/wx/containr.h +++ b/include/wx/containr.h @@ -44,9 +44,6 @@ public: // By default, we accept focus ourselves. m_acceptsFocusSelf = true; - // But we don't have any children accepting it yet. - m_acceptsFocusChildren = false; - m_inSetFocus = false; m_winLastFocused = NULL; } @@ -79,8 +76,7 @@ public: // Returns whether we or one of our children accepts focus. bool AcceptsFocusRecursively() const - { return AcceptsFocus() || - (m_acceptsFocusChildren && HasAnyChildrenAcceptingFocus()); } + { return AcceptsFocus() || HasAnyChildrenAcceptingFocus(); } // We accept focus from keyboard if we accept it at all. bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); } @@ -119,7 +115,11 @@ protected: private: // Update the window status to reflect whether it is getting focus or not. - void UpdateParentCanFocus(); + void UpdateParentCanFocus(bool acceptsFocusChildren); + void UpdateParentCanFocus() + { + UpdateParentCanFocus(HasAnyFocusableChildren()); + } // Indicates whether the associated window can ever have focus itself. // @@ -129,9 +129,6 @@ private: // ourselves and can only get it if we have any focusable children. bool m_acceptsFocusSelf; - // Cached value remembering whether we have any children accepting focus. - bool m_acceptsFocusChildren; - // a guard against infinite recursion bool m_inSetFocus; }; diff --git a/src/common/containr.cpp b/src/common/containr.cpp index bdf72218af..196ada8172 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -50,25 +50,21 @@ // wxControlContainerBase // ---------------------------------------------------------------------------- -void wxControlContainerBase::UpdateParentCanFocus() +void wxControlContainerBase::UpdateParentCanFocus(bool acceptsFocusChildren) { // In the ports where it does something non trivial, the parent window // should only be focusable if it doesn't have any focusable children // (e.g. native focus handling in wxGTK totally breaks down otherwise). - m_winParent->SetCanFocus(m_acceptsFocusSelf && !m_acceptsFocusChildren); + m_winParent->SetCanFocus(m_acceptsFocusSelf && !acceptsFocusChildren); } bool wxControlContainerBase::UpdateCanFocusChildren() { const bool acceptsFocusChildren = HasAnyFocusableChildren(); - if ( acceptsFocusChildren != m_acceptsFocusChildren ) - { - m_acceptsFocusChildren = acceptsFocusChildren; - UpdateParentCanFocus(); - } + UpdateParentCanFocus(acceptsFocusChildren); - return m_acceptsFocusChildren; + return acceptsFocusChildren; } bool wxControlContainerBase::HasAnyFocusableChildren() const From e303231d009e03ae73a18dee728f03221ca01bf6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 16:54:16 +0200 Subject: [PATCH 09/22] Simplify drawing plain background in AUI toolbars Don't bother adjusting the rectangle, just set the pen correctly to avoid drawing its borders. Closes #17616. --- src/aui/auibar.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/aui/auibar.cpp b/src/aui/auibar.cpp index 4f3a694382..582afd0a31 100644 --- a/src/aui/auibar.cpp +++ b/src/aui/auibar.cpp @@ -228,15 +228,12 @@ void wxAuiGenericToolBarArt::DrawBackground( void wxAuiGenericToolBarArt::DrawPlainBackground(wxDC& dc, wxWindow* WXUNUSED(wnd), - const wxRect& _rect) + const wxRect& rect) { - wxRect rect = _rect; - rect.height++; - dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); + dc.SetPen(*wxTRANSPARENT_PEN); - dc.DrawRectangle(rect.GetX() - 1, rect.GetY() - 1, - rect.GetWidth() + 2, rect.GetHeight() + 1); + dc.DrawRectangle(rect); } void wxAuiGenericToolBarArt::DrawLabel( From bf99c7ae9f20eba472003441540c400d57efc671 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 17:24:46 +0200 Subject: [PATCH 10/22] Fix asserts in wxRibbonButtonBar during destruction Don't do anything when the art provider is being reset during the window destruction: this is at best useless and is actually harmful as the code ended up by requesting the DPI of the TLW parent which could already be half-destroyed. --- src/ribbon/buttonbar.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ribbon/buttonbar.cpp b/src/ribbon/buttonbar.cpp index b0976c1750..17cbd00827 100644 --- a/src/ribbon/buttonbar.cpp +++ b/src/ribbon/buttonbar.cpp @@ -686,6 +686,13 @@ void wxRibbonButtonBar::SetArtProvider(wxRibbonArtProvider* art) wxRibbonControl::SetArtProvider(art); + // There is no need to do anything else when the art provider is reset to + // null during our destruction and this actually results in problems during + // program shutdown due to trying to get DPI of the already destroyed TLW + // parent. + if (!art) + return; + wxClientDC temp_dc(this); size_t btn_count = m_buttons.Count(); size_t btn_i; From 7ec0d640ca383ffb9ef29d5e09bc523b3acb89bd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 18:15:32 +0200 Subject: [PATCH 11/22] Clarify library installation instructions for macOS Don't explain how to install the library first only to say that it shouldn't be done afterwards. Also separate the discussion of installing and distributing the libraries. Closes #16316. --- docs/osx/install.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/osx/install.md b/docs/osx/install.md index 9313a6f737..91d2d61044 100644 --- a/docs/osx/install.md +++ b/docs/osx/install.md @@ -3,7 +3,7 @@ wxWidgets for OS X installation {#plat_osx_install} [TOC] -wxWidgets can be compiled using Apple's Cocoa library. +wxWidgets can be compiled using Apple's Cocoa toolkit. Most OS X developers should start by downloading and installing Xcode from the App Store. It is a free IDE from Apple that provides @@ -45,6 +45,11 @@ Advanced topics {#osx_advanced} Installing library {#osx_install} ------------------ +It is rarely desirable to install non-Apple software into system directories, +so the recommended way of using wxWidgets under macOS is to skip the `make +install` step and simply use the full path to `wx-config` under the build +directory when building application using the library. + If you want to install the library into the system directories you'll need to do this as root. The accepted way of running commands as root is to use the built-in sudo mechanism. First of all, you must be using an @@ -53,18 +58,15 @@ account marked as a "Computer Administrator". Then sudo make install type \ -Note that while using this method is okay for development, it is not -recommended that you require endusers to install wxWidgets into their -system directories in order to use your program. One way to avoid this -is to configure wxWidgets with --disable-shared. Another way to avoid -it is to make a framework for wxWidgets. Making frameworks is beyond -the scope of this document. - -**Note:** -It is rarely desirable to install non-Apple software into system directories. -By configuring the library with --disable-shared and using the full path -to wx-config with the --in-place option you can avoid installing the library. +Distributing applications using wxWidgets +----------------------------------------- +If you build wxWidgets as static libraries, i.e. pass `--disable-shared` option +to configure, you don't need to do anything special to distribute them, as all +the required code is linked into your application itself. When using shared +libraries (which is the default), you need to copy the libraries into your +application bundle and change their paths using `install_name_tool` so that +they are loaded from their new locations. Apple Developer Tools: Xcode {#osx_xcode} ---------------------------- From 456743666ce5df83294c290f966d4d711af028c3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 18:16:52 +0200 Subject: [PATCH 12/22] Remove the section about universal binaries from macOS docs This is not relevant any longer, all supported macOS versions support x86-64 binaries and the latest ones don't support anything else, so there is no need to create i386 binaries any more (and PPC ones don't work since ages). --- docs/osx/install.md | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/docs/osx/install.md b/docs/osx/install.md index 91d2d61044..763fc3877f 100644 --- a/docs/osx/install.md +++ b/docs/osx/install.md @@ -82,45 +82,3 @@ the libraries using commands like this: $ cd utils/wxrc $ g++ -o wxrc wxrc.cpp `wx-config --cxxflags --libs base,xml` - -Creating universal binaries {#osx_universal_bin} ---------------------------- - -The Xcode projects for the wxWidgets library and minimal project are set up -to create universal binaries. - -If using the Apple command line tools, pass --enable-universal_binary when -configuring wxWidgets. This will create the libraries for all the supported -architectures, currently ppc, i386 and x86_64 . You may explicitly specify -the architectures to use as a comma-separated list, -e.g. --enable-universal_binary=i386,x86_64. - -Notice that if you use wx-config --libs to link your application, the -arch -flags are not added automatically as it is possible to link e.g. x86_64-only -program to a "fat" library containing other architectures. If you want to -build a universal application, you need to add the necessary "-arch xxx" flags -to your project or makefile separately. - -As an alternative to using --enable-universal_binary, you can build for -each architecture separately and then use the lipo tool to glue the -binaries together. Assuming building on a PPC system: - -1. First build in the usual way to get the PPC library. - -2. Then, build for Intel, in a different folder. This time use: - - export CFLAGS="-g -isysroot /Developer/SDKs/MacOSX10.7.sdk -arch i386" - export LDFLAGS="-syslibroot,/Developer/SDKs/MacOSX10.7.sdk" - - ./configure --disable-dependency-tracking --enable-static=yes --enable-shared=no \ - --target=i386-apple-darwin8 --host=powerpc-apple-darwin8 --build=i386-apple-darwin8 - -You will need to reverse the powerpc and i386 parameters everywhere to build PPC on an Intel -machine. - -3. Use lipo to glue the binaries together. - -See also: -http://developer.apple.com/technotes/tn2005/tn2137.html - - From df689e739a9643709132b1cbd9e9b85aa05106e6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 26 Oct 2019 23:50:01 +0200 Subject: [PATCH 13/22] Add tracing to key event handling functions No real changes, just make it simpler to understand what's going in wxOSX code when handling key events by sprinkling it with wxLogTrace calls. --- src/osx/cocoa/window.mm | 69 ++++++++++++++++++++++++++++++++++++++++- src/osx/window_osx.cpp | 35 +++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index c182de7fc5..1385439843 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -41,6 +41,37 @@ #include +#define TRACE_KEYS "keyevent" + +// ---------------------------------------------------------------------------- +// debugging helpers +// ---------------------------------------------------------------------------- + +// These functions are called from the code but are also useful in the debugger +// (especially wxDumpNSView(), as selectors can be printed out directly anyhow), +// so make them just static instead of putting them in an anonymous namespace +// to make it easier to call them. + +static wxString wxDumpSelector(SEL cmd) +{ + return wxStringWithNSString(NSStringFromSelector(cmd)); +} + +static wxString wxDumpNSView(NSView* view) +{ + wxWidgetImpl* const impl = wxWidgetImpl::FindFromWXWidget(view); + if ( !impl ) + return wxStringWithNSString([view description]); + + extern wxString wxDumpWindow(wxWindowMac* win); + + return wxString::Format("%s belonging to %s", + wxStringWithNSString([view className]), + wxDumpWindow(impl->GetWXPeer()) + ); +} + + // Get the window with the focus NSView* wxOSXGetViewFromResponder( NSResponder* responder ) @@ -1076,7 +1107,11 @@ void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event) { wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if (impl == NULL) + { + wxLogTrace(TRACE_KEYS, "Dropping %s for %s", + wxDumpSelector(_cmd), wxDumpNSView(self)); return; + } impl->keyEvent(event, self, _cmd); } @@ -1520,6 +1555,9 @@ bool wxWidgetCocoaImpl::SetupCursor(WX_NSEvent event) void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd) { + wxLogTrace(TRACE_KEYS, "Got %s for %s", + wxDumpSelector((SEL)_cmd), wxDumpNSView(slf)); + if ( !m_wxPeer->IsEnabled() ) return; @@ -1528,8 +1566,12 @@ void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd) // there are key equivalents that are not command-combos and therefore not handled by cocoa automatically, // therefore we call the menubar directly here, exit if the menu is handling the shortcut if ( [[[NSApplication sharedApplication] mainMenu] performKeyEquivalent:event] ) + { + wxLogTrace(TRACE_KEYS, "%s processed as key equivalent by the menu", + wxDumpSelector((SEL)_cmd)); return; - + } + m_lastKeyDownEvent = event; } @@ -2108,6 +2150,9 @@ void wxCocoaGesturesImpl::TouchesEnded(NSEvent* event) void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd) { + wxLogTrace(TRACE_KEYS, "Insert text \"%s\" for %s", + wxStringWithNSString(text), wxDumpNSView(slf)); + bool result = false; if ( HasUserKeyHandling() && !m_hasEditor && [text length] > 0) { @@ -2140,6 +2185,9 @@ void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd) void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* _cmd) { + wxLogTrace(TRACE_KEYS, "Selector %s for %s", + wxDumpSelector((SEL)_cmd), wxDumpNSView(slf)); + if ( m_lastKeyDownEvent!=NULL ) { // If we have a corresponding key event, send wxEVT_KEY_DOWN now. @@ -2158,10 +2206,17 @@ void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* _cmd) GetWXPeer()->OSXHandleKeyEvent(wxevent2); } } + else + { + wxLogTrace(TRACE_KEYS, "Doing nothing in doCommandBySelector:"); + } } bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd) { + wxLogTrace(TRACE_KEYS, "Got %s for %s", + wxDumpSelector((SEL)_cmd), wxDumpNSView(slf)); + bool handled = false; wxKeyEvent wxevent(wxEVT_KEY_DOWN); @@ -3632,6 +3687,9 @@ bool wxWidgetCocoaImpl::ShouldHandleKeyNavigation(const wxKeyEvent &WXUNUSED(eve bool wxWidgetCocoaImpl::DoHandleKeyNavigation(const wxKeyEvent &event) { + wxLogTrace(TRACE_KEYS, "Handling key navigation event for %s", + wxDumpNSView(m_osxView)); + bool handled = false; wxWindow *focus = GetWXPeer(); if (focus && event.GetKeyCode() == WXK_TAB) @@ -3661,6 +3719,9 @@ bool wxWidgetCocoaImpl::DoHandleKeyNavigation(const wxKeyEvent &event) bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event) { + wxLogTrace(TRACE_KEYS, "Handling key event for %s", + wxDumpNSView(m_osxView)); + wxKeyEvent wxevent(wxEVT_KEY_DOWN); SetupKeyEvent( wxevent, event ); @@ -3672,10 +3733,16 @@ bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event) wxKeyEvent eventHook(wxEVT_CHAR_HOOK, wxevent); if ( GetWXPeer()->OSXHandleKeyEvent(eventHook) && !eventHook.IsNextEventAllowed() ) + { + wxLogTrace(TRACE_KEYS, "Key down event handled"); return true; + } if (DoHandleKeyNavigation(wxevent)) + { + wxLogTrace(TRACE_KEYS, "Key down event handled as navigation event"); return true; + } } if ( HasUserKeyHandling() && [event type] == NSKeyDown) diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index a069d652b7..9a2bad7ae0 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -71,6 +71,8 @@ #include +#define TRACE_KEYS "keyevent" + #ifdef __WXUNIVERSAL__ wxIMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase); #endif @@ -177,6 +179,27 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxBlindPlateWindow, wxWindow); wxBEGIN_EVENT_TABLE(wxBlindPlateWindow, wxWindow) wxEND_EVENT_TABLE() +// ---------------------------------------------------------------------------- +// debug helpers +// ---------------------------------------------------------------------------- + +// Function used to dump a brief description of a window. +extern +wxString wxDumpWindow(wxWindowMac* win) +{ + if ( !win ) + return "(no window)"; + + wxString s = wxString::Format("%s(%p", + win->GetClassInfo()->GetClassName(), win); + + wxString label = win->GetLabel(); + if ( !label.empty() ) + s += wxString::Format(", \"%s\"", label); + s += ")"; + + return s; +} // ---------------------------------------------------------------------------- // constructors and such @@ -2570,6 +2593,18 @@ bool wxWindowMac::UnregisterHotKey(int hotkeyId) bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) { + wxLogTrace(TRACE_KEYS, "Handling %s event in %s", + event.GetEventType() == wxEVT_KEY_DOWN + ? "key down" + : event.GetEventType() == wxEVT_CHAR + ? "char" + : event.GetEventType() == wxEVT_KEY_UP + ? "key up" + : event.GetEventType() == wxEVT_CHAR_HOOK + ? "char hook" + : "unknown", + wxDumpWindow(this)); + bool handled = false; // moved the ordinary key event sending AFTER the accel evaluation From 87bba02fef2896104a983509b1d480ebf442c7b6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 00:02:29 +0200 Subject: [PATCH 14/22] Stop handling performKeyEquivalent: in wxOSX We can't handle the accelerators (known as "key equivalents" in Cocoa) in this function because it is called for the views in top to bottom order, while wx semantics is for accelerators to be handled in the accelerator table closest to the focused window. So just remove this code and rely on accelerator handling happening in wxWindowMac::OSXHandleKeyEvent() instead. Closes #13937. --- include/wx/osx/cocoa/private.h | 1 - src/osx/cocoa/textctrl.mm | 6 ---- src/osx/cocoa/window.mm | 50 ---------------------------------- 3 files changed, 57 deletions(-) diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index 0f8bff0b67..7e35c0e43c 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -185,7 +185,6 @@ public : virtual void keyEvent(WX_NSEvent event, WXWidget slf, void* _cmd); virtual void insertText(NSString* text, WXWidget slf, void* _cmd); virtual void doCommandBySelector(void* sel, WXWidget slf, void* _cmd); - virtual bool performKeyEquivalent(WX_NSEvent event, WXWidget slf, void* _cmd); virtual bool acceptsFirstResponder(WXWidget slf, void* _cmd); virtual bool becomeFirstResponder(WXWidget slf, void* _cmd); virtual bool resignFirstResponder(WXWidget slf, void* _cmd); diff --git a/src/osx/cocoa/textctrl.mm b/src/osx/cocoa/textctrl.mm index c27e2eaf81..d4d18a5200 100644 --- a/src/osx/cocoa/textctrl.mm +++ b/src/osx/cocoa/textctrl.mm @@ -368,12 +368,6 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; [super flagsChanged:event]; } -- (BOOL) performKeyEquivalent:(NSEvent*) event -{ - BOOL retval = [super performKeyEquivalent:event]; - return retval; -} - - (void) insertText:(id) str { // We should never generate char events for the text being inserted diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 1385439843..eaa006113f 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -1197,15 +1197,6 @@ void wxOSX_touchesEnded(NSView* self, SEL _cmd, NSEvent *event) } #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 -BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event) -{ - wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); - if (impl == NULL) - return NO; - - return impl->performKeyEquivalent(event, self, _cmd); -} - BOOL wxOSX_acceptsFirstResponder(NSView* self, SEL _cmd) { wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); @@ -2212,45 +2203,6 @@ void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* _cmd) } } -bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd) -{ - wxLogTrace(TRACE_KEYS, "Got %s for %s", - wxDumpSelector((SEL)_cmd), wxDumpNSView(slf)); - - bool handled = false; - - wxKeyEvent wxevent(wxEVT_KEY_DOWN); - SetupKeyEvent( wxevent, event ); - - // because performKeyEquivalent is going up the entire view hierarchy, we don't have to - // walk up the ancestors ourselves but let cocoa do it -#if wxUSE_ACCEL - int command = m_wxPeer->GetAcceleratorTable()->GetCommand( wxevent ); - if (command != -1) - { - wxEvtHandler * const handler = m_wxPeer->GetEventHandler(); - - wxCommandEvent command_event( wxEVT_MENU, command ); - command_event.SetEventObject( wxevent.GetEventObject() ); - handled = handler->ProcessEvent( command_event ); - - if ( !handled ) - { - // accelerators can also be used with buttons, try them too - command_event.SetEventType(wxEVT_BUTTON); - handled = handler->ProcessEvent( command_event ); - } - } -#endif // wxUSE_ACCEL - - if ( !handled ) - { - wxOSX_PerformKeyEventHandlerPtr superimpl = (wxOSX_PerformKeyEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; - return superimpl(slf, (SEL)_cmd, event); - } - return YES; -} - bool wxWidgetCocoaImpl::acceptsFirstResponder(WXWidget slf, void *_cmd) { if ( HasUserKeyHandling() ) @@ -2531,8 +2483,6 @@ void wxOSXCocoaClassAddWXMethods(Class c, wxOSXSkipOverrides skipFlags) wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" ) - wxOSX_CLASS_ADD_METHOD(c, @selector(performKeyEquivalent:), (IMP) wxOSX_performKeyEquivalent, "c@:@" ) - wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstResponder), (IMP) wxOSX_acceptsFirstResponder, "c@:" ) wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" ) wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" ) From 3406147690c662842021cf01c017ea1e96279d67 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 00:14:41 +0200 Subject: [PATCH 15/22] Improve tracing of focus event in wxOSX Give more details about the window gaining/losing focus rather than only printing out its address. --- src/osx/cocoa/window.mm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index eaa006113f..fb3a3b9915 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -41,12 +41,16 @@ #include +#define TRACE_FOCUS "focus" #define TRACE_KEYS "keyevent" // ---------------------------------------------------------------------------- // debugging helpers // ---------------------------------------------------------------------------- +// This one is defined in window_osx.cpp. +extern wxString wxDumpWindow(wxWindowMac* win); + // These functions are called from the code but are also useful in the debugger // (especially wxDumpNSView(), as selectors can be printed out directly anyhow), // so make them just static instead of putting them in an anonymous namespace @@ -63,8 +67,6 @@ static wxString wxDumpNSView(NSView* view) if ( !impl ) return wxStringWithNSString([view description]); - extern wxString wxDumpWindow(wxWindowMac* win); - return wxString::Format("%s belonging to %s", wxStringWithNSString([view className]), wxDumpWindow(impl->GetWXPeer()) @@ -3759,7 +3761,7 @@ void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* oth if ( receivedFocus ) { - wxLogTrace(wxT("Focus"), wxT("focus set(%p)"), static_cast(thisWindow)); + wxLogTrace(TRACE_FOCUS, "Set focus for %s", wxDumpWindow(thisWindow)); wxChildFocusEvent eventFocus((wxWindow*)thisWindow); thisWindow->HandleWindowEvent(eventFocus); @@ -3781,7 +3783,7 @@ void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* oth thisWindow->GetCaret()->OnKillFocus(); #endif - wxLogTrace(wxT("Focus"), wxT("focus lost(%p)"), static_cast(thisWindow)); + wxLogTrace(TRACE_FOCUS, "Lost focus in %s", wxDumpWindow(thisWindow)); wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); event.SetEventObject(thisWindow); From 55da22563bf0efd001b75a6cd43940fda14a5091 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 00:19:56 +0200 Subject: [PATCH 16/22] Add even more focus tracing to wxOSX Log CanFocus() results too. --- src/osx/cocoa/window.mm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index fb3a3b9915..748c14140b 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -3093,7 +3093,10 @@ bool wxWidgetCocoaImpl::CanFocus() const NSView* targetView = m_osxView; if ( [m_osxView isKindOfClass:[NSScrollView class] ] ) targetView = [(NSScrollView*) m_osxView documentView]; - return [targetView canBecomeKeyView] == YES; + const bool canFocus = [targetView canBecomeKeyView] == YES; + wxLogTrace(TRACE_FOCUS, "CanFocus(%s) -> %s", + wxDumpNSView(m_osxView), canFocus ? "YES" : "NO"); + return canFocus; } bool wxWidgetCocoaImpl::HasFocus() const @@ -3107,12 +3110,17 @@ bool wxWidgetCocoaImpl::HasFocus() const bool wxWidgetCocoaImpl::SetFocus() { if ( !CanFocus() ) + { + wxLogTrace(TRACE_FOCUS, "Not setting focus to %s", wxDumpNSView(m_osxView)); return false; + } NSView* targetView = m_osxView; if ( [m_osxView isKindOfClass:[NSScrollView class] ] ) targetView = [(NSScrollView*) m_osxView documentView]; + wxLogTrace(TRACE_FOCUS, "Setting focus to %s", wxDumpNSView(m_osxView)); + [[m_osxView window] makeFirstResponder: targetView] ; return true; } From c9faa30987fb2814dd6f3b8222685bad55337d1c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 01:18:27 +0200 Subject: [PATCH 17/22] Remove AcceptsFocus() check from SetFocus() This is partially a workaround for AcceptsFocus() not working as expected for hidden windows under Mac (see the upcoming commits), but also makes sense on its own: the other ports don't check whether the window accepts focus in their SetFocus() implementation and it's not clear why should Mac do this. See #17340. --- src/osx/window_osx.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index 9a2bad7ae0..533e0bbf4c 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -578,9 +578,6 @@ static bool wxIsWindowOrParentDisabled(wxWindow* w) void wxWindowMac::SetFocus() { - if ( !AcceptsFocus() ) - return ; - if (wxIsWindowOrParentDisabled((wxWindow*) this)) return; From a5d719dc19cbc38566e1846bd806246704e568e9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 01:20:39 +0200 Subject: [PATCH 18/22] Fix setting initial focus in wxOSX Previously calls to SetFocus() during construction/initialization of the parent window simply didn't do anything for windows other than wxTextCtrl because CanFocus() always returned false for them because they were not shown yet (while wxTextCtrl implementation overrides CanFocus() to always return true, probably to work around the same problem). Now use [NSView setInitialFirstResponder:] if the window is currently hidden to try to focus it when it's shown. This might still fail if the window is really not focusable (e.g. for non-text windows when full keyboard access is off), but it's not worse than what happens now, and it also may work -- unlike now. Closes #17340. --- src/osx/cocoa/window.mm | 42 +++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 748c14140b..f46386286b 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -3109,19 +3109,45 @@ bool wxWidgetCocoaImpl::HasFocus() const bool wxWidgetCocoaImpl::SetFocus() { - if ( !CanFocus() ) - { - wxLogTrace(TRACE_FOCUS, "Not setting focus to %s", wxDumpNSView(m_osxView)); - return false; - } - NSView* targetView = m_osxView; if ( [m_osxView isKindOfClass:[NSScrollView class] ] ) targetView = [(NSScrollView*) m_osxView documentView]; - wxLogTrace(TRACE_FOCUS, "Setting focus to %s", wxDumpNSView(m_osxView)); + if ( [targetView canBecomeKeyView] ) + { + wxLogTrace(TRACE_FOCUS, "Setting focus to %s", wxDumpNSView(m_osxView)); + + [[m_osxView window] makeFirstResponder: targetView] ; + } + else // can't become key view + { + // This most commonly happens because the window is still hidden, as + // canBecomeKeyView: always returns NO in this case, so schedule this + // window to become focused when it's shown later in this case. + // + // Note that this may still fail to work: if full keyboard access is + // off and this window is not a text control or similar, setting + // initial first responder won't do anything. But this is not really a + // problem and at least it will do the right thing if the window turns + // out to be focusable (i.e. it's a text control or full keyboard + // access is on). + if ( !IsVisible() ) + { + wxLogTrace(TRACE_FOCUS, "Setting initial focus to %s", + wxDumpNSView(m_osxView)); + + [[m_osxView window] setInitialFirstResponder: targetView] ; + } + else // window is shown but doesn't accept focus + { + // Not sure when exactly can this happen, for now just don't do + // anything in this case. + wxLogTrace(TRACE_FOCUS, "Not setting focus to %s", + wxDumpNSView(m_osxView)); + return false; + } + } - [[m_osxView window] makeFirstResponder: targetView] ; return true; } From 37ca3bcae96ce009d64a7a9bdc476971c85c9ced Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 01:30:43 +0200 Subject: [PATCH 19/22] Remove unnecessary wxIsWindowOrParentDisabled() wxWindow::IsEnabled() already returns false if any of the window ancestors are disabled, there is no need to check them explicitly. --- src/osx/window_osx.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index 533e0bbf4c..f3c4260ac7 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -565,20 +565,9 @@ bool wxWindowMac::SetBackgroundColour(const wxColour& col ) return true ; } -static bool wxIsWindowOrParentDisabled(wxWindow* w) -{ - while (w && !w->IsTopLevel()) - { - if (!w->IsEnabled()) - return true; - w = w->GetParent(); - } - return false; -} - void wxWindowMac::SetFocus() { - if (wxIsWindowOrParentDisabled((wxWindow*) this)) + if ( !IsEnabled() ) return; wxWindow* former = FindFocus() ; From 6530323f31de7a852acdff45afe00aa27e982720 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 01:31:21 +0200 Subject: [PATCH 20/22] Add unit test for wxWindow::IsThisEnabled() Check that the child IsEnabled() returns false if its parent is disabled, but its IsThisEnabled() still returns true in this case. --- tests/controls/windowtest.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/controls/windowtest.cpp b/tests/controls/windowtest.cpp index a9ff914f5d..1c3fcc1b81 100644 --- a/tests/controls/windowtest.cpp +++ b/tests/controls/windowtest.cpp @@ -364,6 +364,28 @@ TEST_CASE_METHOD(WindowTestCase, "Window::Enable", "[window]") m_window->Enable(false); CHECK(!m_window->IsEnabled()); + m_window->Enable(); + + + wxWindow* const child = new wxWindow(m_window, wxID_ANY); + CHECK(child->IsEnabled()); + CHECK(child->IsThisEnabled()); + + m_window->Disable(); + CHECK(!child->IsEnabled()); + CHECK(child->IsThisEnabled()); + + child->Disable(); + CHECK(!child->IsEnabled()); + CHECK(!child->IsThisEnabled()); + + m_window->Enable(); + CHECK(!child->IsEnabled()); + CHECK(!child->IsThisEnabled()); + + child->Enable(); + CHECK(child->IsEnabled()); + CHECK(child->IsThisEnabled()); } TEST_CASE_METHOD(WindowTestCase, "Window::FindWindowBy", "[window]") From 85b5337160c14e0afed2d356f664ccac1310e4d7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 01:39:27 +0200 Subject: [PATCH 21/22] Try to improve CanFocus() behaviour for hidden windows This should be less important now that we don't rely on CanFocus() to determine if we should set focus to the window any longer, but it seems to still be better to try to make it work better for hidden windows, so at least return true from it when full keyboard access is on. When it's off, the behaviour is the same as before, but this doesn't affect wxTextCtrl, whose peer NSView overrides CanFocus() to always return true. We almost certainly need to override CanFocus() in other views, notably wxDataViewCtrl, wxSearchCtrl, and any other controls that can have focus even when full keyboard access is off. See #17340. --- src/osx/cocoa/window.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index f46386286b..8a8a12b948 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -3090,6 +3090,16 @@ bool wxWidgetCocoaImpl::GetNeedsDisplay() const bool wxWidgetCocoaImpl::CanFocus() const { + if ( !IsVisible() ) + { + // It's useless to call canBecomeKeyView in this case, it will always + // return false. Try to return something reasonable ourselves, knowing + // that most controls are not focusable when full keyboard access if + // off and wxNSTextViewControl overrides CanFocus() to always return + // true anyhow. + return [NSApp isFullKeyboardAccessEnabled]; + } + NSView* targetView = m_osxView; if ( [m_osxView isKindOfClass:[NSScrollView class] ] ) targetView = [(NSScrollView*) m_osxView documentView]; From d38d8f4f9c204ffcd5b025e37f026ecdf0ad0d6c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Oct 2019 01:44:29 +0200 Subject: [PATCH 22/22] Remove Carbon-specific code from wxScreenDC implementation Carbon is not supported any more and defining m_overlayWindow, which was only used by Carbon code, resulted in "unused private variable" warning from clang. --- include/wx/osx/dcscreen.h | 2 -- src/osx/carbon/dcscreen.cpp | 20 -------------------- 2 files changed, 22 deletions(-) diff --git a/include/wx/osx/dcscreen.h b/include/wx/osx/dcscreen.h index 77d7832f70..1ebcc5e75d 100644 --- a/include/wx/osx/dcscreen.h +++ b/include/wx/osx/dcscreen.h @@ -21,8 +21,6 @@ public: virtual ~wxScreenDCImpl(); virtual wxBitmap DoGetAsBitmap(const wxRect *subrect) const wxOVERRIDE; -private: - void* m_overlayWindow; private: wxDECLARE_CLASS(wxScreenDCImpl); diff --git a/src/osx/carbon/dcscreen.cpp b/src/osx/carbon/dcscreen.cpp index df7b09db24..3db95c5a51 100644 --- a/src/osx/carbon/dcscreen.cpp +++ b/src/osx/carbon/dcscreen.cpp @@ -26,37 +26,17 @@ wxIMPLEMENT_ABSTRACT_CLASS(wxScreenDCImpl, wxWindowDCImpl); wxScreenDCImpl::wxScreenDCImpl( wxDC *owner ) : wxWindowDCImpl( owner ) { -#if wxOSX_USE_COCOA_OR_CARBON CGRect cgbounds ; cgbounds = CGDisplayBounds(CGMainDisplayID()); m_width = (wxCoord)cgbounds.size.width; m_height = (wxCoord)cgbounds.size.height; -#else - wxDisplaySize( &m_width, &m_height ); -#endif -#if wxOSX_USE_COCOA_OR_IPHONE SetGraphicsContext( wxGraphicsContext::Create() ); -#else - Rect bounds; - bounds.top = (short)cgbounds.origin.y; - bounds.left = (short)cgbounds.origin.x; - bounds.bottom = bounds.top + (short)cgbounds.size.height; - bounds.right = bounds.left + (short)cgbounds.size.width; - WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute; - CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, (WindowRef*) &m_overlayWindow ); - ShowWindow((WindowRef)m_overlayWindow); - SetGraphicsContext( wxGraphicsContext::CreateFromNativeWindow( m_overlayWindow ) ); -#endif m_ok = true ; } wxScreenDCImpl::~wxScreenDCImpl() { wxDELETE(m_graphicContext); -#if wxOSX_USE_COCOA_OR_IPHONE -#else - DisposeWindow((WindowRef) m_overlayWindow ); -#endif } #if wxOSX_USE_IPHONE