Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets
Commits:
97eb12c0 by Vadim Zeitlin at 2025-10-02T14:28:21+02:00
Don't use mnemonic character in tab labels in notebook sample
This results in both cosmetic problems, with the mnemonic being shown by
wxTreeBook, and asserts/crashes when changing notebook type due to
GetPageText() returning the page text without "&" and hence comparison
with RADIOBUTTONS_PAGE_NAME in CreatePage() failing.
For now just don't use mnemonics, even if this just hides the problem
and doesn't really solve it.
See #25840.
- - - - -
b1bb91a2 by Vadim Zeitlin at 2025-10-02T14:28:21+02:00
Fix typo in a comment and reformat recently added code
Correct copy-and-pasto.
See #25844.
- - - - -
5de9ceb6 by Blake-Madden at 2025-10-02T21:16:32+02:00
Clarify wxLog::SetActiveTarget()
Closes #25852.
- - - - -
ac3a4d13 by Vadim Zeitlin at 2025-10-02T23:05:05+02:00
Reformat wxScrollWinEvent ctor
No real changes, just prepare for the upcoming commit.
- - - - -
9e5b420c by Robert Roebling at 2025-10-02T23:19:59+02:00
Implement native scrolling on iOS
- Supports SetTargetWindow() used by e.g. wxDataViewCtrl
- Need to enforce single pixel steps because that is what
finger scrolling does
- Draws before window is visible (I assume for off-screen
drawing into buffer)
- Added localDeviceOrigin like in GTK+, since the native
scroll window moves windows up and this needs to be
corrected in wxWidgets when e.g. reporting mouse event
coordinates, update region and child window positions
- Supports native scrolling physics beyond limits, then
bounces back (like standard on iOS)
- Enforce single pixel steps in wxHtmlWindow
- Supports wxDataViewCtrl with no changes in its code
Closes #25827.
- - - - -
14 changed files:
- include/wx/event.h
- include/wx/osx/core/private.h
- include/wx/osx/iphone/private.h
- include/wx/osx/window.h
- include/wx/scrolwin.h
- interface/wx/event.h
- interface/wx/log.h
- interface/wx/scrolwin.h
- samples/notebook/notebook.h
- src/common/event.cpp
- src/generic/scrlwing.cpp
- src/osx/carbon/dcclient.cpp
- src/osx/iphone/
window.mm
- src/osx/window_osx.cpp
Changes:
=====================================
include/wx/event.h
=====================================
@@ -1746,19 +1746,25 @@ public:
wxScrollWinEvent(wxEventType commandType = wxEVT_NULL,
int pos = 0, int orient = 0);
wxScrollWinEvent(const wxScrollWinEvent& event) : wxEvent(event)
- { m_commandInt = event.m_commandInt;
- m_extraLong = event.m_extraLong; }
+ {
+ m_commandInt = event.m_commandInt;
+ m_extraLong = event.m_extraLong;
+ m_pixelOffset = event.m_pixelOffset;
+ }
int GetOrientation() const { return (int) m_extraLong; }
int GetPosition() const { return m_commandInt; }
+ int GetPixelOffset() const { return m_pixelOffset; }
void SetOrientation(int orient) { m_extraLong = (long) orient; }
void SetPosition(int pos) { m_commandInt = pos; }
+ void SetPixelOffset(int pixelOffset) { m_pixelOffset = pixelOffset; }
wxNODISCARD virtual wxEvent *Clone() const override { return new wxScrollWinEvent(*this); }
protected:
int m_commandInt;
long m_extraLong;
+ int m_pixelOffset;
private:
wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxScrollWinEvent);
=====================================
include/wx/osx/core/private.h
=====================================
@@ -282,6 +282,11 @@ public :
virtual bool SetBackgroundStyle(wxBackgroundStyle style) = 0;
virtual void SetForegroundColour( const wxColour& col ) = 0;
+ virtual void SetDeviceLocalOrigin( wxPoint origin )
+ { m_deviceLocalOrigin = origin; }
+ virtual wxPoint GetDeviceLocalOrigin() const
+ { return m_deviceLocalOrigin; }
+
// all coordinates in native parent widget relative coordinates
virtual void GetContentArea( int &left , int &top , int &width , int &height ) const = 0;
virtual void Move(int x, int y, int width, int height) = 0;
@@ -354,6 +359,11 @@ public :
virtual int GetIncrement() const = 0;
virtual void PulseGauge() = 0;
virtual void SetScrollThumb( wxInt32 value, wxInt32 thumbSize ) = 0;
+ virtual void SetScrollbar( int WXUNUSED(orient), int WXUNUSED(pos), int WXUNUSED(thumb),
+ int WXUNUSED(range), bool WXUNUSED(refresh) ) {}
+ virtual int GetScrollPos(int WXUNUSED(orient)) const { return 0; }
+ virtual void SetScrollPos(int WXUNUSED(orient), int WXUNUSED(pos)) {}
+ virtual void ScrollWindow (int WXUNUSED(dx), int WXUNUSED(dy), const wxRect *WXUNUSED(rect) = nullptr) {}
virtual void SetFont(const wxFont & font) = 0;
@@ -619,6 +629,7 @@ protected :
wxWindowMac* m_wxPeer;
bool m_needsFrame;
bool m_shouldSendEvents;
+ wxPoint m_deviceLocalOrigin;
wxDECLARE_ABSTRACT_CLASS(wxWidgetImpl);
};
=====================================
include/wx/osx/iphone/private.h
=====================================
@@ -38,7 +38,7 @@ wxBitmapBundle WXDLLIMPEXP_CORE wxOSXCreateSystemBitmapBundle(const wxString& id
class WXDLLIMPEXP_CORE wxWidgetIPhoneImpl : public wxWidgetImpl
{
public :
- wxWidgetIPhoneImpl( wxWindowMac* peer , WXWidget w, int flags = 0 ) ;
+ wxWidgetIPhoneImpl( wxWindowMac* peer , WXWidget w, int flags = 0, void* controller = nullptr ) ;
wxWidgetIPhoneImpl() ;
~wxWidgetIPhoneImpl();
@@ -104,7 +104,11 @@ public :
wxInt32 GetMaximum() const;
int GetIncrement() const { return 1; }
void PulseGauge();
+ void SetScrollbar( int orient, int pos, int thumb, int range, bool refresh );
+ int GetScrollPos(int orient) const;
+ void SetScrollPos(int orient, int pos);
void SetScrollThumb( wxInt32 value, wxInt32 thumbSize );
+ void ScrollWindow (int dx, int dy, const wxRect* rect = nullptr);
void SetFont(const wxFont & font);
@@ -126,8 +130,24 @@ public :
virtual void controlAction(void* sender, wxUint32 controlEvent, WX_UIEvent rawEvent);
virtual void controlTextDidChange();
+
+ void* GetController() { return m_controller; }
+ bool GetBlockScrollEvents() const { return m_blockScrollEvents; }
+ void SetBlockScrollWindow( bool block ) { m_blockScrollWindow = block; }
+ bool GetBlockScrollWindow() const { return m_blockScrollWindow; }
+
+ int GetXScrollPixelsPerLine() const { return m_xScrollPixelsPerLine; }
+ int GetYScrollPixelsPerLine() const { return m_yScrollPixelsPerLine; }
+
protected:
- WXWidget m_osxView;
+ WXWidget m_osxView;
+ void* m_controller;
+ bool m_blockScrollEvents;
+ bool m_blockScrollWindow;
+ int m_xScrollPixelsPerLine;
+ int m_yScrollPixelsPerLine;
+
+
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxWidgetIPhoneImpl);
};
@@ -227,7 +247,7 @@ protected :
@end
- @interface wxUIView : UIView
+ @interface wxUIView : UIScrollView
{
}
=====================================
include/wx/osx/window.h
=====================================
@@ -279,6 +279,16 @@ public:
virtual void *OSXGetViewOrWindow() const;
#endif // Cocoa
+#ifdef __WXOSX_IPHONE__
+ void OSXSetScrollTargetWindow( wxWindow *target );
+ wxWindow * OSXGetScrollTargetWindow() { return m_scrollTargetWindow; }
+ const wxWindow * OSXGetScrollTargetWindow() const { return m_scrollTargetWindow; }
+ wxWindow * m_scrollTargetWindow;
+ void OSXSetScrollOwnerWindow( wxWindow *owner );
+ wxWindow * OSXGetScrollOwnerWindow() { return m_scrollOwnerWindow; }
+ wxWindow * m_scrollOwnerWindow;
+#endif
+
void * MacGetCGContextRef() { return m_cgContextRef ; }
void MacSetCGContextRef(void * cg) { m_cgContextRef = cg ; }
=====================================
include/wx/scrolwin.h
=====================================
@@ -182,7 +182,7 @@ public:
// which it is implemented to not use wxWindow::ScrollWindow().
virtual void EnableScrolling(bool x_scrolling, bool y_scrolling);
- // Get the view start
+ // Get the view start in scroll units
void GetViewStart(int *x, int *y) const { DoGetViewStart(x, y); }
wxPoint GetViewStart() const
@@ -192,6 +192,16 @@ public:
return pt;
}
+ // Get the view start in pixels
+ void GetViewStartPixels(int *x, int *y) const { DoGetViewStartPixels(x, y); }
+
+ wxPoint GetViewStartPixels() const
+ {
+ wxPoint pt;
+ DoGetViewStartPixels(&pt.x, &pt.y);
+ return pt;
+ }
+
// Set the scale factor, used in PrepareDC
void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; }
double GetScaleX() const { return m_scaleX; }
@@ -285,6 +295,7 @@ protected:
// implementation of public methods with the same name
virtual void DoGetViewStart(int *x, int *y) const;
+ virtual void DoGetViewStartPixels(int *x, int *y) const;
virtual void DoScroll(int x, int y) = 0;
virtual void DoShowScrollbars(wxScrollbarVisibility horz,
wxScrollbarVisibility vert) = 0;
@@ -354,6 +365,11 @@ protected:
int m_xScrollLinesPerPage;
int m_yScrollLinesPerPage;
+ // Extra offset compared to the multiple of m_[xy]ScrollPosition which is
+ // used to obtain the position in pixels for DoGetViewStartPixels().
+ int m_xScrollPositionPixelOffset;
+ int m_yScrollPositionPixelOffset;
+
bool m_xScrollingEnabled;
bool m_yScrollingEnabled;
=====================================
interface/wx/event.h
=====================================
@@ -1909,6 +1909,22 @@ public:
*/
int GetPosition() const;
+ /**
+ Offset of the scroll position from the nearest position expressed in
+ scroll units.
+
+ In cases where scrolling is possible with single pixel precision,
+ such as when panning on a touch screen with fingers, this returns
+ the offset in pixels of the real position compared to the position
+ obtained by multiplying the current scroll position in scroll units by
+ the size of scroll unit in pixels. For example, if the scroll unit size
+ (pixels per line) is 20px, this function returns a value which can be
+ between 0 and 19.
+
+ @since 3.2.2
+ */
+ int GetPixelOffset() const;
+
void SetOrientation(int orient);
void SetPosition(int pos);
};
=====================================
interface/wx/log.h
=====================================
@@ -331,6 +331,10 @@ public:
active log target is set to @NULL a new default log target will be
created when logging occurs.
+ @note The logging system will take ownership of the target you pass
+ in here. However, it is your responsibility to delete the target you
+ are replacing (i.e., the return value of this function).
+
@see SetThreadActiveTarget()
*/
static wxLog* SetActiveTarget(wxLog* logtarget);
=====================================
interface/wx/scrolwin.h
=====================================
@@ -402,7 +402,7 @@ public:
2-element list (x, y).
@endWxPerlOnly
- @see SetScrollbars(), Scroll()
+ @see SetScrollbars(), Scroll(), GetViewStartPixels()
*/
void GetViewStart(int* x, int* y) const;
@@ -412,6 +412,29 @@ public:
*/
wxPoint GetViewStart() const;
+ /**
+ Get the position at which the visible portion of the window starts
+ in pixels.
+
+ This is similar to GetViewStart() but returns the position in pixels
+ and not in scroll units.
+
+ @param x
+ Receives the first visible horizontal position in scroll pixels.
+ May be @NULL if not needed.
+ @param y
+ Receives the first visible vertical position in scroll pixels.
+ May be @NULL if not needed.
+
+ @see SetScrollbars(), Scroll(), GetViewStart()
+
+ @since 3.3.2
+ */
+ void GetViewStartPixels(int* x, int* y) const;
+
+ /// @overload
+ wxPoint GetViewStartPixels() const;
+
/**
Gets the size in device units of the scrollable window area (as
opposed to the client size, which is the area of the window currently
=====================================
samples/notebook/notebook.h
=====================================
@@ -187,7 +187,7 @@ enum ID_COMMANDS
*/
#define I_WAS_INSERTED_PAGE_NAME "Inserted"
-#define RADIOBUTTONS_PAGE_NAME "Radio &buttons"
+#define RADIOBUTTONS_PAGE_NAME "Radio buttons"
#define VETO_PAGE_NAME "Veto"
#define TEXT_PAGE_NAME "Text"
=====================================
src/common/event.cpp
=====================================
@@ -566,6 +566,7 @@ wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType,
m_eventType = commandType;
m_extraLong = orient;
m_commandInt = pos;
+ m_pixelOffset = 0;
}
// ----------------------------------------------------------------------------
=====================================
src/generic/scrlwing.cpp
=====================================
@@ -326,6 +326,9 @@ wxScrollHelperBase::wxScrollHelperBase(wxWindow *win)
m_xScrollLinesPerPage =
m_yScrollLinesPerPage = 0;
+ m_xScrollPositionPixelOffset =
+ m_yScrollPositionPixelOffset = 0;
+
m_xScrollingEnabled =
m_yScrollingEnabled = true;
@@ -362,6 +365,9 @@ void wxScrollHelperBase::SetScrollbars(int pixelsPerUnitX,
int yPos,
bool noRefresh)
{
+ m_xScrollPositionPixelOffset =
+ m_yScrollPositionPixelOffset = 0;
+
// Convert positions expressed in scroll units to positions in pixels.
int xPosInPixels = (xPos + m_xScrollPosition)*m_xScrollPixelsPerLine,
yPosInPixels = (yPos + m_yScrollPosition)*m_yScrollPixelsPerLine;
@@ -444,6 +450,9 @@ void wxScrollHelperBase::DoSetTargetWindow(wxWindow *target)
#ifdef __WXMAC__
target->MacSetClipChildren() ;
#endif
+#ifdef __WXOSX_IPHONE__
+ m_win->OSXSetScrollTargetWindow( target );
+#endif
// install the event handler which will intercept the events we're
// interested in (but only do it for our real window, not the target window
@@ -474,10 +483,33 @@ void wxScrollHelperBase::SetTargetWindow(wxWindow *target)
void wxScrollHelperBase::HandleOnScroll(wxScrollWinEvent& event)
{
+ int orient = event.GetOrientation();
+ int oldPos = 0;
+
+ if (orient == wxHORIZONTAL)
+ {
+ oldPos = GetViewStartPixels().x;
+ // reset to 0 assuming scrolling by scrollbar or mouse wheel
+ m_xScrollPositionPixelOffset = 0;
+ }
+ else
+ {
+ oldPos = GetViewStartPixels().y;
+ // reset to 0 assuming scrolling by scrollbar or mouse wheel
+ m_yScrollPositionPixelOffset = 0;
+ }
+
int nScrollInc = CalcScrollInc(event);
- if ( nScrollInc == 0 )
+
+ int newPos = 0;
+ if (orient == wxHORIZONTAL)
+ newPos = (m_xScrollPosition + nScrollInc) * m_xScrollPixelsPerLine + m_xScrollPositionPixelOffset;
+ else
+ newPos = (m_yScrollPosition + nScrollInc) * m_yScrollPixelsPerLine + m_yScrollPositionPixelOffset;
+
+ if ( newPos == oldPos )
{
- // can't scroll further
+ // no scrolling done
event.Skip();
return;
@@ -486,12 +518,11 @@ void wxScrollHelperBase::HandleOnScroll(wxScrollWinEvent& event)
bool needsRefresh = false;
int dx = 0,
dy = 0;
- int orient = event.GetOrientation();
if (orient == wxHORIZONTAL)
{
if ( m_xScrollingEnabled )
{
- dx = -m_xScrollPixelsPerLine * nScrollInc;
+ dx = oldPos - newPos;
}
else
{
@@ -502,7 +533,7 @@ void wxScrollHelperBase::HandleOnScroll(wxScrollWinEvent& event)
{
if ( m_yScrollingEnabled )
{
- dy = -m_yScrollPixelsPerLine * nScrollInc;
+ dy = oldPos - newPos;
}
else
{
@@ -596,11 +627,19 @@ int wxScrollHelperBase::CalcScrollInc(wxScrollWinEvent& event)
(event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE))
{
if (orient == wxHORIZONTAL)
+ {
nScrollInc = pos - m_xScrollPosition;
+ m_xScrollPositionPixelOffset = event.GetPixelOffset();
+ }
else
+ {
nScrollInc = pos - m_yScrollPosition;
+ m_yScrollPositionPixelOffset = event.GetPixelOffset();
+ }
}
+// on iOS, overscrolling is allowed
+#ifndef __WXOSX_IPHONE__
if (orient == wxHORIZONTAL)
{
if ( m_xScrollPosition + nScrollInc < 0 )
@@ -635,6 +674,7 @@ int wxScrollHelperBase::CalcScrollInc(wxScrollWinEvent& event)
}
}
}
+#endif
return nScrollInc;
}
@@ -647,12 +687,12 @@ void wxScrollHelperBase::DoPrepareReadOnlyDC(wxReadOnlyDC& dc)
// the m_sign from the DC here, but I leave the
// #ifdef GTK for now.
if (m_win->GetLayoutDirection() == wxLayout_RightToLeft)
- dc.SetDeviceOrigin( pt.x + m_xScrollPosition * m_xScrollPixelsPerLine,
- pt.y - m_yScrollPosition * m_yScrollPixelsPerLine );
+ dc.SetDeviceOrigin( pt.x + (m_xScrollPosition * m_xScrollPixelsPerLine) + m_xScrollPositionPixelOffset,
+ pt.y - (m_yScrollPosition * m_yScrollPixelsPerLine) - m_yScrollPositionPixelOffset );
else
#endif
- dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine,
- pt.y - m_yScrollPosition * m_yScrollPixelsPerLine );
+ dc.SetDeviceOrigin( pt.x - (m_xScrollPosition * m_xScrollPixelsPerLine) - m_xScrollPositionPixelOffset,
+ pt.y - (m_yScrollPosition * m_yScrollPixelsPerLine) - m_yScrollPositionPixelOffset );
dc.SetUserScale( m_scaleX, m_scaleY );
}
@@ -713,7 +753,7 @@ void wxScrollHelperBase::EnableScrolling (bool x_scroll, bool y_scroll)
m_yScrollingEnabled = y_scroll;
}
-// Where the current view starts from
+// Where the current view starts from in units
void wxScrollHelperBase::DoGetViewStart (int *x, int *y) const
{
if ( x )
@@ -722,22 +762,31 @@ void wxScrollHelperBase::DoGetViewStart (int *x, int *y) const
*y = m_yScrollPosition;
}
+// Where the current view starts from in pixels
+void wxScrollHelperBase::DoGetViewStartPixels (int *x, int *y) const
+{
+ if ( x )
+ *x = m_xScrollPosition * m_xScrollPixelsPerLine + m_xScrollPositionPixelOffset;
+ if ( y )
+ *y = m_yScrollPosition * m_yScrollPixelsPerLine + m_yScrollPositionPixelOffset;
+}
+
void wxScrollHelperBase::DoCalcScrolledPosition(int x, int y,
int *xx, int *yy) const
{
if ( xx )
- *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine;
+ *xx = x - (m_xScrollPosition * m_xScrollPixelsPerLine) - m_xScrollPositionPixelOffset;
if ( yy )
- *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine;
+ *yy = y - (m_yScrollPosition * m_yScrollPixelsPerLine) - m_yScrollPositionPixelOffset;
}
void wxScrollHelperBase::DoCalcUnscrolledPosition(int x, int y,
int *xx, int *yy) const
{
if ( xx )
- *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine;
+ *xx = x + (m_xScrollPosition * m_xScrollPixelsPerLine) + m_xScrollPositionPixelOffset;
if ( yy )
- *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine;
+ *yy = y + (m_yScrollPosition * m_yScrollPixelsPerLine) + m_yScrollPositionPixelOffset;
}
// ----------------------------------------------------------------------------
=====================================
src/osx/carbon/dcclient.cpp
=====================================
@@ -47,8 +47,10 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window )
m_ok = true ;
m_window->GetSize( &m_width , &m_height);
+#ifndef __WXOSX_IPHONE__
if ( !m_window->IsShownOnScreen() )
m_width = m_height = 0;
+#endif
CGContextRef cg = (CGContextRef) window->MacGetCGContextRef();
@@ -74,6 +76,10 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window )
if ( window->MacGetLeftBorderSize() != 0 || window->MacGetTopBorderSize() != 0 )
CGContextTranslateCTM( cg , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() );
+ wxWidgetImpl *impl = (wxWidgetImpl *) window->GetPeer();
+ wxPoint origin( impl->GetDeviceLocalOrigin() );
+ CGContextTranslateCTM( cg, -origin.x, -origin.y );
+
wxGraphicsContext* context = wxGraphicsContext::CreateFromNative( cg );
context->SetContentScaleFactor(m_contentScaleFactor);
SetGraphicsContext( context );
@@ -83,6 +89,10 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window )
SetBackground(window->GetBackgroundColour());
SetFont( window->GetFont() ) ;
+
+ wxWidgetImpl *impl = (wxWidgetImpl*)window->GetPeer();
+ wxPoint origin( impl->GetDeviceLocalOrigin() );
+ SetDeviceLocalOrigin( origin.x, origin.y );
}
wxWindowDCImpl::~wxWindowDCImpl()
=====================================
src/osx/iphone/
window.mm
=====================================
@@ -30,7 +30,7 @@
// ----------------------------------------------------------------------------
// These functions are called from the code but are also useful in the debugger
-// (especially wxDumpNSView(), as selectors can be printed out directly anyhow),
+// (especially wxDumpUIView(), 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.
@@ -90,6 +90,64 @@ CGRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const
}
+@interface wxUIScrollViewDelegate : NSObject <UIScrollViewDelegate>
+{
+}
+
+-(void)scrollViewDidScroll:(UIScrollView *)scrollView;
+
+@end
+
+@implementation wxUIScrollViewDelegate
+
+- (id) init
+{
+ self = [super init];
+ return self;
+}
+
+-(void)scrollViewDidScroll:(UIScrollView *)scrollView
+{
+ wxWidgetIPhoneImpl* viewimpl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( scrollView );
+ if ( viewimpl )
+ {
+ wxWindowMac* wxpeer = (wxWindowMac*) viewimpl->GetWXPeer();
+ if (wxpeer)
+ {
+ CGPoint position = [scrollView contentOffset];
+
+ viewimpl->SetDeviceLocalOrigin( wxPoint( -position.x, -position.y ) );
+
+ if (viewimpl->GetBlockScrollEvents())
+ return;
+
+ // iOS already scrolled the window
+ viewimpl->SetBlockScrollWindow( true );
+
+ int unitY = position.y / viewimpl->GetYScrollPixelsPerLine();
+ int offsetY = (int)(position.y) % viewimpl->GetYScrollPixelsPerLine();
+ wxScrollWinEvent vevent( wxEVT_SCROLLWIN_THUMBTRACK, unitY, wxVERTICAL );
+ vevent.SetPixelOffset( offsetY );
+ vevent.SetEventObject( wxpeer );
+ wxpeer->OSXGetScrollOwnerWindow()->HandleWindowEvent( vevent );
+
+ int unitX = position.x / viewimpl->GetXScrollPixelsPerLine();
+ int offsetX = (int)(position.x) % viewimpl->GetXScrollPixelsPerLine();
+ wxScrollWinEvent hevent( wxEVT_SCROLLWIN_THUMBTRACK, unitX, wxHORIZONTAL );
+ hevent.SetPixelOffset( offsetX );
+ hevent.SetEventObject( wxpeer );
+ wxpeer->OSXGetScrollOwnerWindow()->HandleWindowEvent( hevent );
+
+ viewimpl->SetBlockScrollWindow( false );
+ }
+ viewimpl->SetNeedsDisplay();
+ }
+}
+
+@end
+
+
+
@interface UIView(PossibleMethods)
- (void)setTitle:(NSString *)title forState:(UIControlState)state;
@@ -232,8 +290,15 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSSet* touches, UIEvent * nsEvent
@end // wxUIView
+typedef void (*wxOSX_touchEventHandlerPtr)(UIView* self, SEL _cmd, NSSet* touches, UIEvent *event );
+
void wxOSX_touchEvent(UIView* self, SEL _cmd, NSSet* touches, UIEvent *event )
{
+ // Call the superclass handler first as that is e.g. handling mouse events for UISegmentedControls
+ wxOSX_touchEventHandlerPtr superimpl =
+ (wxOSX_touchEventHandlerPtr) [[self superclass] instanceMethodForSelector:_cmd];
+ superimpl(self, _cmd, touches, event );
+
wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
if (impl == nullptr)
return;
@@ -329,8 +394,11 @@ void wxOSXIPhoneClassAddWXMethods(Class c)
wxIMPLEMENT_DYNAMIC_CLASS(wxWidgetIPhoneImpl , wxWidgetImpl);
-wxWidgetIPhoneImpl::wxWidgetIPhoneImpl( wxWindowMac* peer , WXWidget w, int flags ) :
- wxWidgetImpl( peer, flags ), m_osxView(w)
+wxWidgetIPhoneImpl::wxWidgetIPhoneImpl( wxWindowMac* peer , WXWidget w, int flags, void* controller ) :
+ wxWidgetImpl( peer, flags ), m_osxView(w), m_controller(controller),
+ m_blockScrollEvents(false), m_blockScrollWindow(false),
+ m_xScrollPixelsPerLine(0), m_yScrollPixelsPerLine(0)
+
{
}
@@ -381,11 +449,6 @@ void wxWidgetIPhoneImpl::Lower()
[[m_osxView superview] sendSubviewToBack:m_osxView];
}
-void wxWidgetIPhoneImpl::ScrollRect( const wxRect *rect, int dx, int dy )
-{
- SetNeedsDisplay() ;
-}
-
void wxWidgetIPhoneImpl::Move(int x, int y, int width, int height)
{
CGRect r = CGRectMake( x, y, width, height) ;
@@ -416,15 +479,10 @@ void wxWidgetIPhoneImpl::GetContentArea( int&left, int &top, int &width, int &he
height = rect.size.height;
}
-void wxWidgetIPhoneImpl::SetNeedsDisplay( const wxRect* where )
+void wxWidgetIPhoneImpl::SetNeedsDisplay( const wxRect* WXUNUSED(where) )
{
- if ( where )
- {
- CGRect r = CGRectMake( where->x, where->y, where->width, where->height) ;
- [m_osxView setNeedsDisplayInRect:r];
- }
- else
- [m_osxView setNeedsDisplay];
+ // TODO: Use "where" if non-null after adapting it to DeviceLocalOrigin
+ [m_osxView setNeedsDisplay];
}
bool wxWidgetIPhoneImpl::GetNeedsDisplay() const
@@ -466,6 +524,7 @@ void wxWidgetIPhoneImpl::Embed( wxWidgetImpl *parent )
void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
{
+ // TODO: adapt to DeviceLocalOrigin
CGPoint p = CGPointMake( pt->x , pt->y );
p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ];
pt->x = (int)p.x;
@@ -607,6 +666,113 @@ void wxWidgetIPhoneImpl::PulseGauge()
{
}
+void wxWidgetIPhoneImpl::SetScrollPos(int orient, int pos)
+{
+ if (m_blockScrollWindow)
+ return;
+ wxUIView* view = (wxUIView*)m_osxView; // wxUIView derives from UIScrollView
+
+ CGPoint position = [view contentOffset];
+
+ if (orient == wxVERTICAL)
+ {
+ if (m_yScrollPixelsPerLine == 0)
+ return;
+ position = CGPointMake( position.x, pos*m_yScrollPixelsPerLine );
+ }
+ else if (orient == wxHORIZONTAL)
+ {
+ if (m_xScrollPixelsPerLine == 0)
+ return;
+ position = CGPointMake( pos*m_xScrollPixelsPerLine, position.y );
+ }
+
+ m_blockScrollEvents = true;
+ [view setContentOffset: position];
+ m_blockScrollEvents = false;
+
+ SetNeedsDisplay();
+}
+
+int wxWidgetIPhoneImpl::GetScrollPos(int orient) const
+{
+ wxUIView* view = (wxUIView*)m_osxView; // wxUIView derives from UIScrollView
+
+ CGPoint position = [view contentOffset];
+
+ if ((orient == wxVERTICAL) && (m_yScrollPixelsPerLine != 0))
+ {
+ return position.y / m_yScrollPixelsPerLine;
+ }
+ if ((orient == wxHORIZONTAL) && (m_xScrollPixelsPerLine != 0))
+ {
+ return position.x / m_xScrollPixelsPerLine;
+ }
+
+ return 0;
+}
+
+
+void wxWidgetIPhoneImpl::ScrollRect( const wxRect *rect, int dx, int dy )
+{
+}
+
+void wxWidgetIPhoneImpl::ScrollWindow( int dx, int dy, const wxRect *rect )
+{
+ if (m_blockScrollWindow)
+ return;
+
+ wxUIView* view = (wxUIView*)m_osxView; // wxUIView derives from UIScrollView
+
+ CGPoint position = [view contentOffset];
+
+ position.x -= dx;
+ position.y -= dy;
+
+ m_blockScrollEvents = true;
+ [view setContentOffset: position];
+ m_blockScrollEvents = false;
+
+ SetNeedsDisplay();
+}
+
+
+
+void wxWidgetIPhoneImpl::SetScrollbar(int orient, int pos, int thumb,
+ int range, bool refresh)
+{
+ wxUIView* view = (wxUIView*)m_osxView; // wxUIView derives from UIScrollView
+
+ if ( thumb == 0 )
+ return;
+
+ CGPoint position = [view contentOffset];
+ CGSize size = [view contentSize];
+ CGSize viewSize = [view bounds].size;
+
+ if (orient == wxVERTICAL)
+ {
+ CGFloat yScrollPixelsPerLine = viewSize.height/thumb;
+ size = CGSizeMake( size.width, range*yScrollPixelsPerLine );
+ position = CGPointMake( position.x, pos*yScrollPixelsPerLine );
+ m_yScrollPixelsPerLine = (int) yScrollPixelsPerLine;
+ }
+ else if (orient == wxHORIZONTAL)
+ {
+ CGFloat xScrollPixelsPerLine = viewSize.width/thumb;
+ size = CGSizeMake( range*xScrollPixelsPerLine, size.height );
+ position = CGPointMake( pos*xScrollPixelsPerLine, position.y );
+ m_xScrollPixelsPerLine = (int) xScrollPixelsPerLine;
+ }
+
+ m_blockScrollEvents = true;
+ [view setContentSize: size];
+ [view setContentOffset: position];
+ m_blockScrollEvents = false;
+
+ SetNeedsDisplay();
+}
+
void wxWidgetIPhoneImpl::SetScrollThumb( wxInt32 value, wxInt32 thumbSize )
{
}
@@ -715,6 +881,7 @@ bool wxWidgetIPhoneImpl::resignFirstResponder(WXWidget slf, void *_cmd)
void wxWidgetIPhoneImpl::drawRect(CGRect* rect, WXWidget slf, void *WXUNUSED(_cmd))
{
wxRegion updateRgn( wxFromNSRect( slf, *rect ) );
+ updateRgn.Offset( GetDeviceLocalOrigin() );
wxWindow* wxpeer = GetWXPeer();
wxpeer->GetUpdateRegion() = updateRgn;
@@ -788,8 +955,8 @@ void wxWidgetIPhoneImpl::touchEvent(NSSet* touches, UIEvent *event, WXWidget slf
wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
SetupMouseEvent( wxevent , touches, event ) ;
- wxevent.m_x = pt.x;
- wxevent.m_y = pt.y;
+ wxevent.m_x = pt.x + m_deviceLocalOrigin.x;
+ wxevent.m_y = pt.y + m_deviceLocalOrigin.y;
wxevent.SetEventObject( GetWXPeer() ) ;
//?wxevent.SetId( GetWXPeer()->GetId() ) ;
@@ -801,6 +968,8 @@ void wxWidgetIPhoneImpl::controlAction(void* sender, wxUint32 controlEvent, WX_U
{
if ( controlEvent == UIControlEventTouchUpInside )
GetWXPeer()->OSXHandleClicked(0);
+ else if ( controlEvent == UIControlEventValueChanged )
+ GetWXPeer()->OSXHandleClicked(0);
}
void wxWidgetIPhoneImpl::controlTextDidChange()
@@ -904,11 +1073,16 @@ long wxOSXTranslateKey( UIPress* press, int eventType )
retval = '0';
break;
default:
- if ( keyCode >= UIKeyboardHIDUsageKeyboardA && keyCode <= UIKeyboardHIDUsageKeyboardZ ) {
+ if ( keyCode >= UIKeyboardHIDUsageKeyboardA && keyCode <= UIKeyboardHIDUsageKeyboardZ )
+ {
retval = 'a' + (keyCode - UIKeyboardHIDUsageKeyboardA );
- } else if ( keyCode >= UIKeyboardHIDUsageKeyboard1 && keyCode <= UIKeyboardHIDUsageKeyboard9 ) {
+ }
+ else if ( keyCode >= UIKeyboardHIDUsageKeyboard1 && keyCode <= UIKeyboardHIDUsageKeyboard9 )
+ {
retval = '1' + (keyCode - UIKeyboardHIDUsageKeyboard1 );
- } else if ( keyCode >= UIKeyboardHIDUsageKeyboardF1 && keyCode <= UIKeyboardHIDUsageKeyboardF12 ) {
+ }
+ else if ( keyCode >= UIKeyboardHIDUsageKeyboardF1 && keyCode <= UIKeyboardHIDUsageKeyboardF12 )
+ {
retval = WXK_F1 + (keyCode - UIKeyboardHIDUsageKeyboardF1 );
}
break;
@@ -1050,7 +1224,8 @@ void wxWidgetIPhoneImpl::keyEvent( NSSet *presses, UIEvent* event, WXWidget slf,
m_wxPeer->OSXHandleKeyEvent(wxevent);
}
- if ( !handled ) {
+ if ( !handled )
+ {
wxOSX_PressesHandlerPtr superimpl = (wxOSX_PressesHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
superimpl(slf, (SEL)_cmd, presses, event);
}
@@ -1066,8 +1241,10 @@ wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* WX
UIView* sv = (wxpeer->GetParent()->GetHandle() );
CGRect r = CGRectMake( pos.x, pos.y, size.x, size.y) ;
- // Rect bounds = wxMacGetBoundsForControl( wxpeer, pos , size ) ;
wxUIView* v = [[wxUIView alloc] initWithFrame:r];
+ v.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+ wxUIScrollViewDelegate *delegate = [[wxUIScrollViewDelegate alloc] init];
+ [v setDelegate: delegate];
sv.clipsToBounds = YES;
sv.contentMode = UIViewContentModeRedraw;
sv.clearsContextBeforeDrawing = NO;
=====================================
src/osx/window_osx.cpp
=====================================
@@ -217,6 +217,10 @@ void wxWindowMac::Init()
m_clipChildren = false ;
m_cachedClippedRectValid = false ;
m_isNativeWindowWrapper = false;
+#ifdef __WXOSX_IPHONE__
+ m_scrollTargetWindow = this;
+ m_scrollOwnerWindow = this;
+#endif
}
wxWindowMac::~wxWindowMac()
@@ -1397,8 +1401,25 @@ bool wxWindowMac::EnableTouchEvents(int eventsMask)
return GetPeer() ? GetPeer()->EnableTouchEvents(eventsMask) : false;
}
+#ifdef __WXOSX_IPHONE__
+void wxWindowMac::OSXSetScrollOwnerWindow( wxWindow *owner )
+{
+ m_scrollOwnerWindow = owner;
+}
+
+void wxWindowMac::OSXSetScrollTargetWindow( wxWindow *target )
+{
+ m_scrollTargetWindow = target;
+ target->OSXSetScrollOwnerWindow( this );
+}
+#endif
+
int wxWindowMac::GetScrollPos(int orient) const
{
+#ifdef __WXOSX_IPHONE__
+ const wxWidgetImpl *impl = (const wxWidgetImpl*) OSXGetScrollTargetWindow()->GetPeer();
+ return impl->GetScrollPos( orient );
+#endif
#if wxUSE_SCROLLBAR
if ( orient == wxHORIZONTAL )
{
@@ -1452,6 +1473,10 @@ int wxWindowMac::GetScrollThumb(int orient) const
void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
{
+#ifdef __WXOSX_IPHONE__
+ wxWidgetImpl *impl = (wxWidgetImpl*) OSXGetScrollTargetWindow()->GetPeer();
+ impl->SetScrollPos( orient, pos );
+#endif
#if wxUSE_SCROLLBAR
if ( orient == wxHORIZONTAL )
{
@@ -1658,6 +1683,10 @@ void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
DoUpdateScrollbarVisibility();
#endif
+#ifdef __WXOSX_IPHONE__
+ wxWidgetImpl *impl = (wxWidgetImpl*) OSXGetScrollTargetWindow()->GetPeer();
+ impl->SetScrollbar( orient, pos, thumb, range, refresh );
+#endif
}
// Does a physical scroll
@@ -1666,6 +1695,11 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
if ( dx == 0 && dy == 0 )
return ;
+#ifdef __WXOSX_IPHONE__
+ GetPeer()->ScrollWindow( dx, dy, rect );
+ return;
+#endif
+
int width , height ;
GetClientSize( &width , &height ) ;
@@ -1895,8 +1929,11 @@ void wxWindowMac::MacUpdateClippedRects() const
bool wxWindowMac::MacDoRedraw( long time )
{
bool handled = false ;
+#ifndef __WXOSX_IPHONE__
+ // iOS draws before the window is visible, I assume into off-screen buffer
if ( !IsShownOnScreen() )
return handled;
+#endif
wxRegion formerUpdateRgn = m_updateRegion;
wxRegion clientUpdateRgn = formerUpdateRgn;
@@ -1929,6 +1966,9 @@ bool wxWindowMac::MacDoRedraw( long time )
eevent.SetEventObject( this );
if ( ProcessWindowEvent( eevent ) )
break;
+
+ if (!UseBgCol())
+ dc.Clear();
}
if ( UseBgCol() )
@@ -2670,6 +2710,7 @@ void wxWidgetImpl::Init()
m_wantsUserMouse = false;
m_wxPeer = nullptr;
m_needsFrame = true;
+ m_deviceLocalOrigin = wxPoint(0, 0);
}
void wxWidgetImpl::SetNeedsFrame( bool needs )
View it on GitLab:
https://gitlab.com/wxwidgets/wxwidgets/-/compare/16af160f7f04442d1a7d9364e24c4b6b8e05bea0...9e5b420c970fe922051955f1fa1ed35216fffc1a
--
View it on GitLab:
https://gitlab.com/wxwidgets/wxwidgets/-/compare/16af160f7f04442d1a7d9364e24c4b6b8e05bea0...9e5b420c970fe922051955f1fa1ed35216fffc1a
You're receiving this email because of your account on
gitlab.com.