Merge branch 'osx-fixes'

Miscellaneous macOS bug fixes.

See https://github.com/wxWidgets/wxWidgets/pull/2136
This commit is contained in:
Vadim Zeitlin
2020-12-08 18:43:05 +01:00
12 changed files with 190 additions and 45 deletions

View File

@@ -557,6 +557,9 @@ private:
wxCocoaOutlineDataSource* m_DataSource; wxCocoaOutlineDataSource* m_DataSource;
wxCocoaOutlineView* m_OutlineView; wxCocoaOutlineView* m_OutlineView;
// Width of expander in pixels, computed on demand.
int m_expanderWidth;
}; };
#endif // _WX_DATAVIEWCTRL_COCOOA_H_ #endif // _WX_DATAVIEWCTRL_COCOOA_H_

View File

@@ -306,7 +306,7 @@ private:
wxDataViewColumnPtrArrayType m_ColumnPtrs; // all column pointers are stored in an array wxDataViewColumnPtrArrayType m_ColumnPtrs; // all column pointers are stored in an array
wxDataViewModelNotifier* m_ModelNotifier; // stores the model notifier for the control (does not own the notifier) class wxOSXDataViewModelNotifier* m_ModelNotifier; // stores the model notifier for the control (does not own the notifier)
// wxWidget internal stuff: // wxWidget internal stuff:
wxDECLARE_DYNAMIC_CLASS(wxDataViewCtrl); wxDECLARE_DYNAMIC_CLASS(wxDataViewCtrl);

View File

@@ -170,6 +170,8 @@ protected:
wxArrayPtrVoid m_itemsClientData; wxArrayPtrVoid m_itemsClientData;
private: private:
// Mostly the same as DoSetSelection() but doesn't call EnsureVisible().
void DoSetSelectionWithoutEnsureVisible(int n, bool select);
wxDECLARE_DYNAMIC_CLASS(wxListBox); wxDECLARE_DYNAMIC_CLASS(wxListBox);
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();

View File

@@ -169,16 +169,16 @@ void wxApp::MacReopenApp()
while (node) while (node)
{ {
wxTopLevelWindow* win = (wxTopLevelWindow*) node->GetData(); wxTopLevelWindow* win = (wxTopLevelWindow*) node->GetData();
if ( win->IsShown() ) if ( win->IsIconized() )
{
// we do have a visible, non-iconized toplevelwindow -> do nothing
return;
}
else if ( win->IsIconized() )
{ {
if ( firstIconized == NULL ) if ( firstIconized == NULL )
firstIconized = win; firstIconized = win;
} }
else if ( win->IsShown() )
{
// we do have a visible, non-iconized toplevelwindow -> do nothing
return;
}
node = node->GetNext(); node = node->GetNext();
} }

View File

@@ -348,11 +348,14 @@ void wxRendererMac::DrawSplitterSash( wxWindow *win,
height = wxRendererNative::Get().GetSplitterParams(win).widthSash; height = wxRendererNative::Get().GetSplitterParams(win).widthSash;
// Do not draw over border drawn by wxRendererGeneric::DrawSplitterBorder()
const wxCoord borderAdjust = win->HasFlag(wxSP_3DBORDER) ? 2 : 0;
HIRect splitterRect; HIRect splitterRect;
if (orient == wxVERTICAL) if (orient == wxVERTICAL)
splitterRect = CGRectMake( position, 0, height, size.y ); splitterRect = CGRectMake( position, borderAdjust, height, size.y - 2*borderAdjust );
else else
splitterRect = CGRectMake( 0, position, size.x, height ); splitterRect = CGRectMake( borderAdjust, position, size.x - 2*borderAdjust, height );
// under compositing we should only draw when called by the OS, otherwise just issue a redraw command // under compositing we should only draw when called by the OS, otherwise just issue a redraw command
// strange redraw errors occur if we don't do this // strange redraw errors occur if we don't do this

View File

@@ -139,23 +139,30 @@
- (void)comboBoxSelectionDidChange:(NSNotification *)notification - (void)comboBoxSelectionDidChange:(NSNotification *)notification
{ {
wxUnusedVar(notification); wxUnusedVar(notification);
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); wxNSComboBoxControl* const
impl = (wxNSComboBoxControl* ) wxWidgetImpl::FindFromWXWidget( self );
if ( impl && impl->ShouldSendEvents()) if ( impl && impl->ShouldSendEvents())
{ {
wxComboBox* wxpeer = static_cast<wxComboBox*>(impl->GetWXPeer()); wxComboBox* wxpeer = static_cast<wxComboBox*>(impl->GetWXPeer());
if ( wxpeer ) { if ( wxpeer ) {
const int sel = wxpeer->GetSelection(); const int sel = wxpeer->GetSelection();
const wxString& val = wxpeer->GetString(sel);
// We need to manually set the new value because at this time it
// still contains the old value, but we want GetValue() to return
// the new one if it's called from an event handler invoked below.
impl->SetStringValue(val);
wxCommandEvent event(wxEVT_COMBOBOX, wxpeer->GetId()); wxCommandEvent event(wxEVT_COMBOBOX, wxpeer->GetId());
event.SetEventObject( wxpeer ); event.SetEventObject( wxpeer );
event.SetInt( sel ); event.SetInt( sel );
event.SetString( wxpeer->GetString(sel) ); event.SetString( val );
// For some reason, wxComboBox::GetValue will not return the newly selected item wxpeer->HandleWindowEvent( event );
// while we're inside this callback, so use AddPendingEvent to make sure
// GetValue() returns the right value.
wxpeer->GetEventHandler()->AddPendingEvent( event );
wxCommandEvent eventText(wxEVT_TEXT, wxpeer->GetId());
eventText.SetEventObject( wxpeer );
eventText.SetString( val );
wxpeer->HandleWindowEvent( eventText );
} }
} }
} }

View File

@@ -2045,7 +2045,8 @@ wxCocoaDataViewControl::wxCocoaDataViewControl(wxWindow* peer,
[[NSScrollView alloc] initWithFrame:wxOSXGetFrameForControl(peer,pos,size)] [[NSScrollView alloc] initWithFrame:wxOSXGetFrameForControl(peer,pos,size)]
), ),
m_DataSource(NULL), m_DataSource(NULL),
m_OutlineView([[wxCocoaOutlineView alloc] init]) m_OutlineView([[wxCocoaOutlineView alloc] init]),
m_expanderWidth(0)
{ {
// initialize scrollview (the outline view is part of a scrollview): // initialize scrollview (the outline view is part of a scrollview):
NSScrollView* scrollview = (NSScrollView*) GetWXWidget(); NSScrollView* scrollview = (NSScrollView*) GetWXWidget();
@@ -2175,7 +2176,9 @@ void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos)
: m_width(0), : m_width(0),
m_view(view), m_view(view),
m_column(columnIndex), m_column(columnIndex),
m_indent(0) m_indent(0),
m_expander(0),
m_tableColumn(column)
{ {
// account for indentation in the column with expander // account for indentation in the column with expander
if ( column == [m_view outlineTableColumn] ) if ( column == [m_view outlineTableColumn] )
@@ -2193,18 +2196,27 @@ void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos)
unsigned cellWidth = [cell cellSize].width + 1/*round the float up*/; unsigned cellWidth = [cell cellSize].width + 1/*round the float up*/;
if ( m_indent ) if ( m_indent )
cellWidth += m_indent * ([m_view levelForRow:row] + 1); cellWidth += m_indent * [m_view levelForRow:row];
if ( m_expander == 0 && m_tableColumn == [m_view outlineTableColumn] )
{
NSRect rc = [m_view frameOfOutlineCellAtRow:row];
m_expander = ceil(rc.origin.x + rc.size.width);
}
m_width = wxMax(m_width, cellWidth); m_width = wxMax(m_width, cellWidth);
} }
int GetMaxWidth() const { return m_width; } int GetMaxWidth() const { return m_width; }
int GetExpanderWidth() const { return m_expander; }
private: private:
int m_width; int m_width;
wxCocoaOutlineView *m_view; wxCocoaOutlineView *m_view;
unsigned m_column; unsigned m_column;
int m_indent; int m_indent;
int m_expander;
NSTableColumn *m_tableColumn;
}; };
MaxWidthCalculator calculator(m_OutlineView, column, pos); MaxWidthCalculator calculator(m_OutlineView, column, pos);
@@ -2275,7 +2287,12 @@ void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos)
count); count);
} }
[column setWidth:calculator.GetMaxWidth()]; // there might not necessarily be an expander in the rows we've examined above so let's
// globally store the expander width for re-use because it should always be the same
if ( m_expanderWidth == 0 )
m_expanderWidth = calculator.GetExpanderWidth();
[column setWidth:calculator.GetMaxWidth() + m_expanderWidth];
} }
// //

View File

@@ -149,9 +149,15 @@ public :
protected : protected :
void AdaptColumnWidth ( int w );
wxNSTableView* m_tableView ; wxNSTableView* m_tableView ;
wxNSTableDataSource* m_dataSource; wxNSTableDataSource* m_dataSource;
NSMutableArray* m_widths;
int m_maxWidth;
bool m_autoSize;
} ; } ;
// //
@@ -333,10 +339,14 @@ wxListWidgetCocoaImpl::wxListWidgetCocoaImpl( wxWindowMac* peer, NSScrollView* v
wxWidgetCocoaImpl( peer, view ), m_tableView(tableview), m_dataSource(data) wxWidgetCocoaImpl( peer, view ), m_tableView(tableview), m_dataSource(data)
{ {
InstallEventHandler( tableview ); InstallEventHandler( tableview );
m_widths = [[NSMutableArray alloc] init];
m_maxWidth = 0;
m_autoSize = false;
} }
wxListWidgetCocoaImpl::~wxListWidgetCocoaImpl() wxListWidgetCocoaImpl::~wxListWidgetCocoaImpl()
{ {
[m_widths release];
[m_dataSource release]; [m_dataSource release];
} }
@@ -371,11 +381,7 @@ wxListWidgetColumn* wxListWidgetCocoaImpl::InsertTextColumn( unsigned pos, const
} }
else else
{ {
[col1 setMaxWidth:1000]; m_autoSize = true;
[col1 setMinWidth:10];
// temporary hack, because I cannot get the automatic column resizing
// to work properly
[col1 setWidth:1000];
} }
[col1 setResizingMask: NSTableColumnAutoresizingMask]; [col1 setResizingMask: NSTableColumnAutoresizingMask];
@@ -465,24 +471,65 @@ wxListWidgetColumn* wxListWidgetCocoaImpl::InsertCheckColumn( unsigned pos , con
return wxcol; return wxcol;
} }
void wxListWidgetCocoaImpl::AdaptColumnWidth ( int w )
{
NSTableColumn *col = [[m_tableView tableColumns] objectAtIndex:0];
[col setWidth:w];
m_maxWidth = w;
}
// //
// inserting / removing lines // inserting / removing lines
// //
void wxListWidgetCocoaImpl::ListInsert( unsigned int WXUNUSED(n) ) void wxListWidgetCocoaImpl::ListInsert( unsigned int n )
{ {
[m_tableView reloadData]; [m_tableView reloadData];
if ( m_autoSize )
{
NSCell *cell = [m_tableView preparedCellAtColumn:0 row:n];
NSSize size = [cell cellSize];
int width = (int) ceil(size.width);
[m_widths insertObject:[NSNumber numberWithInteger:width] atIndex:n];
if ( width > m_maxWidth )
AdaptColumnWidth( width );
}
} }
void wxListWidgetCocoaImpl::ListDelete( unsigned int WXUNUSED(n) ) void wxListWidgetCocoaImpl::ListDelete( unsigned int n )
{ {
[m_tableView reloadData]; [m_tableView reloadData];
if ( m_autoSize )
{
[m_widths removeObjectAtIndex:n];
int maxWidth = 0;
for ( NSNumber *number in m_widths )
{
int n = [number intValue];
if ( n > maxWidth )
maxWidth = n;
}
if ( maxWidth < m_maxWidth )
AdaptColumnWidth( maxWidth );
}
} }
void wxListWidgetCocoaImpl::ListClear() void wxListWidgetCocoaImpl::ListClear()
{ {
[m_tableView reloadData]; [m_tableView reloadData];
if ( m_autoSize )
{
[m_widths removeAllObjects];
AdaptColumnWidth( 100 );
}
} }
// selecting // selecting

View File

@@ -128,6 +128,7 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index)
case wxSYS_COLOUR_MENUTEXT: case wxSYS_COLOUR_MENUTEXT:
case wxSYS_COLOUR_WINDOWTEXT: case wxSYS_COLOUR_WINDOWTEXT:
case wxSYS_COLOUR_CAPTIONTEXT: case wxSYS_COLOUR_CAPTIONTEXT:
case wxSYS_COLOUR_INACTIVECAPTIONTEXT:
case wxSYS_COLOUR_INFOTEXT: case wxSYS_COLOUR_INFOTEXT:
case wxSYS_COLOUR_LISTBOXTEXT: case wxSYS_COLOUR_LISTBOXTEXT:
sysColor = [NSColor controlTextColor]; sysColor = [NSColor controlTextColor];
@@ -138,7 +139,6 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index)
case wxSYS_COLOUR_BTNHIGHLIGHT: case wxSYS_COLOUR_BTNHIGHLIGHT:
sysColor = [NSColor controlHighlightColor]; sysColor = [NSColor controlHighlightColor];
break; break;
case wxSYS_COLOUR_INACTIVECAPTIONTEXT:
case wxSYS_COLOUR_GRAYTEXT: case wxSYS_COLOUR_GRAYTEXT:
sysColor = [NSColor disabledControlTextColor]; sysColor = [NSColor disabledControlTextColor];
break; break;

View File

@@ -1470,6 +1470,26 @@ void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
return; return;
} }
// The Infinity IN-USB-2 V15 foot pedal on OS 11 produces spurious mouse
// button events with button number = 10.
// We cannot do anything useful with button numbers > 2, so throw them away.
switch ( [event type] )
{
case NSLeftMouseDown:
case NSRightMouseDown:
case NSOtherMouseDown:
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
if ( [event buttonNumber] > 2 )
return;
break;
default:
// Just to avoid -Wswitch.
break;
}
if ( !DoHandleMouseEvent(event) ) if ( !DoHandleMouseEvent(event) )
{ {
// for plain NSView mouse events would propagate to parents otherwise // for plain NSView mouse events would propagate to parents otherwise
@@ -2420,11 +2440,12 @@ void wxWidgetCocoaImpl::controlTextDidChange()
if ( wxpeer ) if ( wxpeer )
{ {
// since native rtti doesn't have to be enabled and wx' rtti is not aware of the mixin wxTextEntry, workaround is needed // since native rtti doesn't have to be enabled and wx' rtti is not aware of the mixin wxTextEntry, workaround is needed
wxTextCtrl *tc = wxDynamicCast( wxpeer , wxTextCtrl ); if ( wxTextCtrl *tc = wxDynamicCast( wxpeer , wxTextCtrl ) )
wxComboBox *cb = wxDynamicCast( wxpeer , wxComboBox ); {
if ( tc ) tc->MarkDirty();
tc->SendTextUpdatedEventIfAllowed(); tc->SendTextUpdatedEventIfAllowed();
else if ( cb ) }
else if ( wxComboBox *cb = wxDynamicCast( wxpeer , wxComboBox ) )
cb->SendTextUpdatedEventIfAllowed(); cb->SendTextUpdatedEventIfAllowed();
else else
{ {

View File

@@ -73,14 +73,15 @@ public:
virtual bool Cleared() wxOVERRIDE; virtual bool Cleared() wxOVERRIDE;
virtual void Resort() wxOVERRIDE; virtual void Resort() wxOVERRIDE;
// adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data
void AdjustAutosizedColumns();
protected: protected:
// if the dataview control can have a variable row height this method sets the dataview's control row height of // if the dataview control can have a variable row height this method sets the dataview's control row height of
// the passed item to the maximum value occupied by the item in all columns // the passed item to the maximum value occupied by the item in all columns
void AdjustRowHeight(wxDataViewItem const& item); void AdjustRowHeight(wxDataViewItem const& item);
// ... and the same method for a couple of items: // ... and the same method for a couple of items:
void AdjustRowHeights(wxDataViewItemArray const& items); void AdjustRowHeights(wxDataViewItemArray const& items);
// adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data
void AdjustAutosizedColumns();
private: private:
wxDataViewCtrl* m_DataViewCtrlPtr; wxDataViewCtrl* m_DataViewCtrlPtr;
@@ -505,6 +506,9 @@ int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const
void wxDataViewCtrl::Collapse(wxDataViewItem const& item) void wxDataViewCtrl::Collapse(wxDataViewItem const& item)
{ {
GetDataViewPeer()->Collapse(item); GetDataViewPeer()->Collapse(item);
if ( m_ModelNotifier )
m_ModelNotifier->AdjustAutosizedColumns();
} }
void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr)
@@ -518,7 +522,10 @@ void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn
void wxDataViewCtrl::DoExpand(wxDataViewItem const& item, bool expandChildren) void wxDataViewCtrl::DoExpand(wxDataViewItem const& item, bool expandChildren)
{ {
return GetDataViewPeer()->DoExpand(item, expandChildren); GetDataViewPeer()->DoExpand(item, expandChildren);
if ( m_ModelNotifier )
m_ModelNotifier->AdjustAutosizedColumns();
} }
bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const

View File

@@ -191,6 +191,14 @@ void wxListBox::DoSetSelection(int n, bool select)
wxCHECK_RET( n == wxNOT_FOUND || IsValid(n), wxCHECK_RET( n == wxNOT_FOUND || IsValid(n),
wxT("invalid index in wxListBox::SetSelection") ); wxT("invalid index in wxListBox::SetSelection") );
DoSetSelectionWithoutEnsureVisible(n, select);
if (select)
EnsureVisible(n);
}
void wxListBox::DoSetSelectionWithoutEnsureVisible(int n, bool select)
{
m_blockEvents = true; m_blockEvents = true;
if ( n == wxNOT_FOUND ) if ( n == wxNOT_FOUND )
@@ -201,9 +209,6 @@ void wxListBox::DoSetSelection(int n, bool select)
m_blockEvents = false; m_blockEvents = false;
UpdateOldSelections(); UpdateOldSelections();
if (select)
EnsureVisible(n);
} }
bool wxListBox::IsSelected(int n) const bool wxListBox::IsSelected(int n) const
@@ -349,6 +354,23 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter& items,
{ {
int idx = wxNOT_FOUND; int idx = wxNOT_FOUND;
unsigned int startpos = pos; unsigned int startpos = pos;
wxArrayInt selections;
if ( !IsSorted() )
{
if ( HasMultipleSelection() )
{
GetSelections(selections);
}
else
{
int sel = GetSelection();
if ( sel != wxNOT_FOUND )
{
selections.Add(sel);
}
}
}
const unsigned int numItems = items.GetCount(); const unsigned int numItems = items.GetCount();
for ( unsigned int i = 0; i < numItems; ++i ) for ( unsigned int i = 0; i < numItems; ++i )
@@ -367,13 +389,29 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter& items,
GetListPeer()->UpdateLineToEnd(startpos); GetListPeer()->UpdateLineToEnd(startpos);
// Inserting the items may scroll the listbox down to show the last const size_t numSelections = selections.size();
// selected one but we don't want to do it as it could result in e.g. the for ( size_t i = 0; i < numSelections; ++i )
// first items of a listbox be hidden immediately after its creation so {
// show the first selected item instead. Ideal would probably be to if ( startpos <= selections[i] )
// preserve the old selection unchanged, in fact, but I don't know how to {
// get the first visible item so for now do at least this. if ( HasMultipleSelection() )
SetFirstItem(startpos); {
size_t j;
// Do not deselect item if it is to be selected below
for ( j = 0; j < numSelections; ++j )
{
if ( selections[i] == selections[j] + numItems )
break;
}
if ( j == numSelections )
Deselect(selections[i]);
}
DoSetSelectionWithoutEnsureVisible(selections[i] + numItems, true);
}
}
InvalidateBestSize(); InvalidateBestSize();