From fe8f794343fc22d3da1e6f003fdd754d2bdf9339 Mon Sep 17 00:00:00 2001 From: David Elliott Date: Mon, 21 Jul 2003 17:06:02 +0000 Subject: [PATCH] Implemented wxDC stack with focus locking and unlocking Implemented wxClientDC git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@22201 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/cocoa/dc.h | 35 +++++++++++++-- include/wx/cocoa/dcclient.h | 8 ++++ include/wx/cocoa/dcmemory.h | 3 ++ src/cocoa/dc.mm | 85 ++++++++++++++++++++++++++++++++++++- src/cocoa/dcclient.mm | 61 ++++++++++++++++++-------- src/cocoa/dcmemory.cpp | 10 +++++ 6 files changed, 180 insertions(+), 22 deletions(-) diff --git a/include/wx/cocoa/dc.h b/include/wx/cocoa/dc.h index 8d53d84c68..dd4b3fdbe5 100644 --- a/include/wx/cocoa/dc.h +++ b/include/wx/cocoa/dc.h @@ -12,6 +12,9 @@ #ifndef __WX_COCOA_DC_H__ #define __WX_COCOA_DC_H__ +class WXDLLEXPORT wxDC; +WX_DECLARE_LIST(wxDC, wxCocoaDCStack); + //========================================================================= // wxDC //========================================================================= @@ -19,17 +22,44 @@ class WXDLLEXPORT wxDC: public wxDCBase { DECLARE_DYNAMIC_CLASS(wxDC) DECLARE_NO_COPY_CLASS(wxDC) +//------------------------------------------------------------------------- +// Initialization +//------------------------------------------------------------------------- public: wxDC(); ~wxDC(); +//------------------------------------------------------------------------- +// wxCocoa specifics +//------------------------------------------------------------------------- +public: static void CocoaInitializeTextSystem(); static void CocoaShutdownTextSystem(); - static wxDC *sm_focusedDC; static WX_NSTextStorage sm_cocoaNSTextStorage; static WX_NSLayoutManager sm_cocoaNSLayoutManager; static WX_NSTextContainer sm_cocoaNSTextContainer; - +protected: +// DC stack + static wxCocoaDCStack sm_cocoaDCStack; + virtual bool CocoaLockFocus(); + virtual bool CocoaUnlockFocus(); + bool CocoaUnwindStackAndTakeFocus(); + inline bool CocoaTakeFocus() + { + wxCocoaDCStack::Node *node = sm_cocoaDCStack.GetFirst(); + if(node && (node->GetData() == this)) + return true; + return CocoaUnwindStackAndTakeFocus(); + } + void CocoaUnwindStackAndLoseFocus(); +// DC flipping/transformation + void CocoaApplyTransformations(); + float m_cocoaHeight; + bool m_cocoaFlipped; +//------------------------------------------------------------------------- +// Implementation +//------------------------------------------------------------------------- +public: // implement base class pure virtuals // ---------------------------------- @@ -126,7 +156,6 @@ protected: virtual void DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle = wxODDEVEN_RULE); - }; #endif // __WX_COCOA_DC_H__ diff --git a/include/wx/cocoa/dcclient.h b/include/wx/cocoa/dcclient.h index 481c3e672b..2f97299db4 100644 --- a/include/wx/cocoa/dcclient.h +++ b/include/wx/cocoa/dcclient.h @@ -41,6 +41,10 @@ public: // Create a DC corresponding to a window wxClientDC(wxWindow *win); ~wxClientDC(void); +protected: +// DC stack + virtual bool CocoaLockFocus(); + virtual bool CocoaUnlockFocus(); }; class wxPaintDC: public wxWindowDC @@ -51,6 +55,10 @@ public: // Create a DC corresponding to a window wxPaintDC(wxWindow *win); ~wxPaintDC(void); +protected: +// DC stack + virtual bool CocoaLockFocus(); + virtual bool CocoaUnlockFocus(); }; #endif // __WX_COCOA_DCCLIENT_H__ diff --git a/include/wx/cocoa/dcmemory.h b/include/wx/cocoa/dcmemory.h index 0c5943a18f..bb83332dfb 100644 --- a/include/wx/cocoa/dcmemory.h +++ b/include/wx/cocoa/dcmemory.h @@ -23,6 +23,9 @@ public: ~wxMemoryDC(void); virtual void SelectObject(const wxBitmap& bitmap); virtual void DoGetSize(int *width, int *height) const; +// DC stack + virtual bool CocoaLockFocus(); + virtual bool CocoaUnlockFocus(); }; #endif // __WX_COCOA_DCMEMORY_H__ diff --git a/src/cocoa/dc.mm b/src/cocoa/dc.mm index 7f19fe7709..2d230c92b3 100644 --- a/src/cocoa/dc.mm +++ b/src/cocoa/dc.mm @@ -24,11 +24,14 @@ #import #import +#include +WX_DEFINE_LIST(wxCocoaDCStack); + IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) -wxDC *wxDC::sm_focusedDC = NULL; WX_NSTextStorage wxDC::sm_cocoaNSTextStorage = nil; WX_NSLayoutManager wxDC::sm_cocoaNSLayoutManager = nil; WX_NSTextContainer wxDC::sm_cocoaNSTextContainer = nil; +wxCocoaDCStack wxDC::sm_cocoaDCStack; void wxDC::CocoaInitializeTextSystem() { @@ -57,16 +60,93 @@ void wxDC::CocoaShutdownTextSystem() [sm_cocoaNSTextStorage release]; sm_cocoaNSTextStorage = nil; } +void wxDC::CocoaUnwindStackAndLoseFocus() +{ + wxCocoaDCStack::Node *ourNode=sm_cocoaDCStack.Find(this); + if(ourNode) + { + wxCocoaDCStack::Node *node=sm_cocoaDCStack.GetFirst(); + for(;node!=ourNode; node=sm_cocoaDCStack.GetFirst()) + { + wxDC *dc = node->GetData(); + wxASSERT(dc); + wxASSERT(dc!=this); + if(!dc->CocoaUnlockFocus()) + { + wxFAIL_MSG("Unable to unlock focus on higher-level DC!"); + } + sm_cocoaDCStack.DeleteNode(node); + } + wxASSERT(node==ourNode); + wxASSERT(ourNode->GetData() == this); + ourNode->GetData()->CocoaUnlockFocus(); + sm_cocoaDCStack.DeleteNode(ourNode); + } +} + +bool wxDC::CocoaUnwindStackAndTakeFocus() +{ + wxCocoaDCStack::Node *node=sm_cocoaDCStack.GetFirst(); + for(;node;node = sm_cocoaDCStack.GetFirst()) + { + wxDC *dc = node->GetData(); + wxASSERT(dc); + // If we're on the stack, then it's unwound enough and we have focus + if(dc==this) + return true; + // If unable to unlockFocus (e.g. wxPaintDC) stop here + if(!dc->CocoaUnlockFocus()) + break; + sm_cocoaDCStack.DeleteNode(node); + } + return CocoaLockFocus(); +} + wxDC::wxDC(void) { + m_cocoaFlipped = false; + m_cocoaHeight = 0.0; } wxDC::~wxDC(void) { } +bool wxDC::CocoaLockFocus() +{ + return false; +} + +bool wxDC::CocoaUnlockFocus() +{ + return false; +} + +void wxDC::CocoaApplyTransformations() +{ + // This transform flips the graphics since wxDC uses top-left origin + if(!m_cocoaFlipped) + { + // The transform is auto released + NSAffineTransform *transform = [NSAffineTransform transform]; + /* x' = 1x + 0y + 0 + y' = 0x + -1y + window's height + */ + NSAffineTransformStruct matrix = { + 1, 0 + , 0, -1 + , 0, m_cocoaHeight + }; + [transform setTransformStruct: matrix]; + // Apply the transform + [transform concat]; + } + // TODO: Apply scaling transformation +} + void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) { + if(!CocoaTakeFocus()) return; NSBezierPath *bezpath = [NSBezierPath bezierPathWithRect:NSMakeRect(x,y,width,height)]; [m_textForegroundColour.GetNSColor() set]; [bezpath stroke]; @@ -76,6 +156,7 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) { + if(!CocoaTakeFocus()) return; NSBezierPath *bezpath = [NSBezierPath bezierPath]; [bezpath moveToPoint:NSMakePoint(x1,y1)]; [bezpath lineToPoint:NSMakePoint(x2,y2)]; @@ -108,6 +189,7 @@ void wxDC::DoGetTextExtent(const wxString& text, wxCoord *x, wxCoord *y, wxCoord void wxDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y) { + if(!CocoaTakeFocus()) return; wxASSERT_MSG(sm_cocoaNSTextStorage && sm_cocoaNSLayoutManager && sm_cocoaNSTextContainer, "Text system has not been initialized. BAD PROGRAMMER!"); NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithCString:text.c_str()]]; @@ -309,6 +391,7 @@ void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) void wxDC::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask) { + if(!CocoaTakeFocus()) return; if(!bmp.Ok()) return; diff --git a/src/cocoa/dcclient.mm b/src/cocoa/dcclient.mm index b64c2ac01c..cfa266129a 100644 --- a/src/cocoa/dcclient.mm +++ b/src/cocoa/dcclient.mm @@ -11,12 +11,14 @@ #include "wx/dcclient.h" #include "wx/window.h" +#include "wx/log.h" #import #import #import #import #import +#import /* * wxWindowDC @@ -67,8 +69,32 @@ wxClientDC::wxClientDC( wxWindow *window ) wxClientDC::~wxClientDC(void) { + CocoaUnwindStackAndLoseFocus(); }; +bool wxClientDC::CocoaLockFocus() +{ + wxLogDebug("Locking focus on wxClientDC=%p, NSView=%p",this, m_window->GetNSView()); + if([m_window->GetNSView() lockFocusIfCanDraw]) + { + sm_cocoaDCStack.Insert(this); + m_cocoaFlipped = [m_window->GetNSView() isFlipped]; + m_cocoaHeight = [m_window->GetNSView() bounds].size.height; + CocoaApplyTransformations(); + return true; + } + wxLogDebug("focus lock failed!"); + return false; +} + +bool wxClientDC::CocoaUnlockFocus() +{ + wxLogDebug("Unlocking focus on wxClientDC=%p, NSView=%p",this, m_window->GetNSView()); + [[m_window->GetNSView() window] flushWindow]; + [m_window->GetNSView() unlockFocus]; + return true; +} + /* * wxPaintDC */ @@ -82,27 +108,26 @@ wxPaintDC::wxPaintDC( wxWindow *window ) { m_window = window; wxASSERT_MSG([NSView focusView]==window->GetNSView(), "PaintDC's NSView does not have focus. Please use wxPaintDC only as the first DC created in a paint handler"); - // This transform flips the graphics since wxDC uses top-left origin - if(![window->GetNSView() isFlipped]) - { - // The transform is auto released - NSAffineTransform *transform = [NSAffineTransform transform]; - /* x' = 1x + 0y + 0 - y' = 0x + -1y + window's height - */ - NSAffineTransformStruct matrix = { - 1, 0 - , 0, -1 - , 0, [window->GetNSView() bounds].size.height - }; - [transform setTransformStruct: matrix]; - // Apply the transform - [transform concat]; - } - // TODO: Apply scaling transformation + sm_cocoaDCStack.Insert(this); + m_cocoaFlipped = [window->GetNSView() isFlipped]; + m_cocoaHeight = [window->GetNSView() bounds].size.height; + CocoaApplyTransformations(); }; wxPaintDC::~wxPaintDC(void) { + CocoaUnwindStackAndLoseFocus(); }; +bool wxPaintDC::CocoaLockFocus() +{ + wxFAIL_MSG("wxPaintDC cannot be asked to lock focus!"); + return false; +} + +bool wxPaintDC::CocoaUnlockFocus() +{ + // wxPaintDC focus can never be unlocked. + return false; +} + diff --git a/src/cocoa/dcmemory.cpp b/src/cocoa/dcmemory.cpp index af89b673c5..377615be15 100644 --- a/src/cocoa/dcmemory.cpp +++ b/src/cocoa/dcmemory.cpp @@ -31,6 +31,16 @@ wxMemoryDC::~wxMemoryDC(void) { } +bool wxMemoryDC::CocoaLockFocus() +{ + return false; +} + +bool wxMemoryDC::CocoaUnlockFocus() +{ + return false; +} + void wxMemoryDC::SelectObject( const wxBitmap& bitmap ) { } -- 2.45.2