Merge remote-tracking branch 'github/osx-fixes'
Several fixes for wxOSX, including several focus-related changes. See https://github.com/wxWidgets/wxWidgets/pull/1620
This commit is contained in:
@@ -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.
|
||||
|
@@ -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 \<YOUR OWN PASSWORD\>
|
||||
|
||||
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}
|
||||
----------------------------
|
||||
@@ -80,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
|
||||
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -21,8 +21,6 @@ public:
|
||||
virtual ~wxScreenDCImpl();
|
||||
|
||||
virtual wxBitmap DoGetAsBitmap(const wxRect *subrect) const wxOVERRIDE;
|
||||
private:
|
||||
void* m_overlayWindow;
|
||||
|
||||
private:
|
||||
wxDECLARE_CLASS(wxScreenDCImpl);
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -41,6 +41,39 @@
|
||||
|
||||
#include <objc/objc-runtime.h>
|
||||
|
||||
#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
|
||||
// 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]);
|
||||
|
||||
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 +1109,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);
|
||||
}
|
||||
@@ -1162,15 +1199,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 );
|
||||
@@ -1520,6 +1548,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 +1559,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 +2143,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 +2178,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,42 +2199,10 @@ void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* _cmd)
|
||||
GetWXPeer()->OSXHandleKeyEvent(wxevent2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd)
|
||||
{
|
||||
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)
|
||||
else
|
||||
{
|
||||
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 );
|
||||
}
|
||||
wxLogTrace(TRACE_KEYS, "Doing nothing in doCommandBySelector:");
|
||||
}
|
||||
#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)
|
||||
@@ -2476,8 +2485,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@:" )
|
||||
@@ -3083,10 +3090,23 @@ 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];
|
||||
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
|
||||
@@ -3099,14 +3119,45 @@ bool wxWidgetCocoaImpl::HasFocus() const
|
||||
|
||||
bool wxWidgetCocoaImpl::SetFocus()
|
||||
{
|
||||
if ( !CanFocus() )
|
||||
return false;
|
||||
|
||||
NSView* targetView = m_osxView;
|
||||
if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
|
||||
targetView = [(NSScrollView*) m_osxView documentView];
|
||||
|
||||
[[m_osxView window] makeFirstResponder: targetView] ;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3632,6 +3683,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 +3715,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 +3729,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)
|
||||
@@ -3742,7 +3805,7 @@ void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* oth
|
||||
|
||||
if ( receivedFocus )
|
||||
{
|
||||
wxLogTrace(wxT("Focus"), wxT("focus set(%p)"), static_cast<void*>(thisWindow));
|
||||
wxLogTrace(TRACE_FOCUS, "Set focus for %s", wxDumpWindow(thisWindow));
|
||||
wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
|
||||
thisWindow->HandleWindowEvent(eventFocus);
|
||||
|
||||
@@ -3764,7 +3827,7 @@ void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* oth
|
||||
thisWindow->GetCaret()->OnKillFocus();
|
||||
#endif
|
||||
|
||||
wxLogTrace(wxT("Focus"), wxT("focus lost(%p)"), static_cast<void*>(thisWindow));
|
||||
wxLogTrace(TRACE_FOCUS, "Lost focus in %s", wxDumpWindow(thisWindow));
|
||||
|
||||
wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
|
||||
event.SetEventObject(thisWindow);
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -71,6 +71,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
@@ -542,23 +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 ( !AcceptsFocus() )
|
||||
return ;
|
||||
|
||||
if (wxIsWindowOrParentDisabled((wxWindow*) this))
|
||||
if ( !IsEnabled() )
|
||||
return;
|
||||
|
||||
wxWindow* former = FindFocus() ;
|
||||
@@ -2570,6 +2579,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
|
||||
|
@@ -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;
|
||||
|
@@ -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]")
|
||||
|
Reference in New Issue
Block a user