1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/carbon/dcclient.cpp 3// Purpose: wxClientDC class 4// Author: Stefan Csomor 5// Modified by: 6// Created: 01/02/97 7// RCS-ID: $Id: dcclient.cpp 53969 2008-06-04 04:35:11Z SC $ 8// Copyright: (c) Stefan Csomor 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#include "wx/wxprec.h" 13 14#include "wx/dcclient.h" 15 16#ifndef WX_PRECOMP 17 #include "wx/log.h" 18 #include "wx/window.h" 19 #include "wx/dcmemory.h" 20 #include "wx/settings.h" 21 #include "wx/toplevel.h" 22 #include "wx/math.h" 23 #include "wx/region.h" 24#endif 25 26#include "wx/graphics.h" 27#include "wx/rawbmp.h" 28#include "wx/mac/private.h" 29 30//----------------------------------------------------------------------------- 31// constants 32//----------------------------------------------------------------------------- 33 34//----------------------------------------------------------------------------- 35// wxPaintDC 36//----------------------------------------------------------------------------- 37 38IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC) 39IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) 40IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC) 41 42/* 43 * wxWindowDC 44 */ 45 46#include "wx/mac/uma.h" 47#include "wx/notebook.h" 48#include "wx/tabctrl.h" 49 50 51static wxBrush MacGetBackgroundBrush( wxWindow* window ) 52{ 53 wxBrush bkdBrush = window->MacGetBackgroundBrush() ; 54 55#if !TARGET_API_MAC_OSX 56 // transparency cannot be handled by the OS when not using composited windows 57 wxWindow* parent = window->GetParent() ; 58 59 // if we have some 'pseudo' transparency 60 if ( ! bkdBrush.Ok() || bkdBrush.GetStyle() == wxTRANSPARENT || window->GetBackgroundColour() == wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE ) ) 61 { 62 // walk up until we find something 63 while ( parent != NULL ) 64 { 65 if ( parent->GetBackgroundColour() != wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE ) ) 66 { 67 // if we have any other colours in the hierarchy 68 bkdBrush.SetColour( parent->GetBackgroundColour() ) ; 69 break ; 70 } 71 72 if ( parent->IsKindOf( CLASSINFO(wxTopLevelWindow) ) ) 73 { 74 bkdBrush = parent->MacGetBackgroundBrush() ; 75 break ; 76 } 77 78 if ( parent->IsKindOf( CLASSINFO( wxNotebook ) ) 79#if wxUSE_TAB_DIALOG 80 || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ) 81#endif // wxUSE_TAB_DIALOG 82 ) 83 { 84 Rect extent = { 0 , 0 , 0 , 0 } ; 85 int x , y ; 86 x = y = 0 ; 87 wxSize size = parent->GetSize() ; 88 parent->MacClientToRootWindow( &x , &y ) ; 89 extent.left = x ; 90 extent.top = y ; 91 extent.top-- ; 92 extent.right = x + size.x ; 93 extent.bottom = y + size.y ; 94 bkdBrush.MacSetThemeBackground( kThemeBackgroundTabPane , (WXRECTPTR) &extent ) ; 95 break ; 96 } 97 98 parent = parent->GetParent() ; 99 } 100 } 101 102 if ( !bkdBrush.Ok() || bkdBrush.GetStyle() == wxTRANSPARENT ) 103 { 104 // if we did not find something, use a default 105 bkdBrush.MacSetTheme( kThemeBrushDialogBackgroundActive ) ; 106 } 107#endif 108 109 return bkdBrush ; 110} 111 112wxWindowDC::wxWindowDC() 113{ 114 m_window = NULL ; 115#if wxMAC_USE_CORE_GRAPHICS 116 m_release = false; 117#endif 118} 119 120wxWindowDC::wxWindowDC(wxWindow *window) 121{ 122 m_window = window ; 123 WindowRef rootwindow = (WindowRef) window->MacGetTopLevelWindowRef() ; 124 if (!rootwindow) 125 return; 126 127 m_ok = true ; 128 129#if wxMAC_USE_CORE_GRAPHICS 130 m_window->GetSize( &m_width , &m_height); 131 if ( !m_window->IsShownOnScreen() ) 132 m_width = m_height = 0; 133 134 CGContextRef cg = (CGContextRef) window->MacGetCGContextRef(); 135 m_release = false; 136 if ( cg == NULL ) 137 { 138 SetGraphicsContext( wxGraphicsContext::Create( window ) ) ; 139 } 140 else 141 { 142 CGContextSaveGState( cg ); 143 m_release = true ; 144 // make sure the context is having its origin at the wx-window coordinates of the 145 // view (read at the top of window.cpp about the differences) 146 if ( window->MacGetLeftBorderSize() != 0 || window->MacGetTopBorderSize() != 0 ) 147 CGContextTranslateCTM( cg , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ); 148 149 SetGraphicsContext( wxGraphicsContext::CreateFromNative( cg ) ); 150 } 151 SetClippingRegion( 0 , 0 , m_width , m_height ) ; 152#else 153 int x , y ; 154 x = y = 0 ; 155 window->MacWindowToRootWindow( &x , &y ) ; 156 m_macLocalOrigin.x = x ; 157 m_macLocalOrigin.y = y ; 158 m_macPort = UMAGetWindowPort( rootwindow ) ; 159 160 CopyRgn( (RgnHandle) window->MacGetVisibleRegion(true).GetWXHRGN() , (RgnHandle) m_macBoundaryClipRgn ) ; 161 OffsetRgn( (RgnHandle) m_macBoundaryClipRgn , m_macLocalOrigin.x , m_macLocalOrigin.y ) ; 162 CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; 163#endif 164 SetBackground(MacGetBackgroundBrush(window)); 165 166 SetFont( window->GetFont() ) ; 167} 168 169wxWindowDC::~wxWindowDC() 170{ 171#if wxMAC_USE_CORE_GRAPHICS 172 if ( m_release ) 173 { 174 // this must not necessarily be the current context, we must restore the state of the 175 // cg we started with above (before the CGContextTranslateCTM call) 176 CGContextRef cg = (CGContextRef) m_window->MacGetCGContextRef(); 177 CGContextRestoreGState(cg); 178 } 179#endif 180} 181 182void wxWindowDC::DoGetSize( int* width, int* height ) const 183{ 184#if wxMAC_USE_CORE_GRAPHICS 185 if ( width ) 186 *width = m_width; 187 if ( height ) 188 *height = m_height; 189#else 190 wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") ); 191 m_window->GetSize(width, height); 192#endif 193} 194 195wxBitmap wxWindowDC::DoGetAsBitmap(const wxRect *subrect) const 196{ 197#if wxMAC_USE_CORE_GRAPHICS 198 if (!m_window) 199 return wxNullBitmap; 200 201 ControlRef handle = (ControlRef) m_window->GetHandle(); 202 if ( !handle ) 203 return wxNullBitmap; 204 205 HIRect rect; 206 CGImageRef image; 207 CGContextRef context; 208 void* data; 209 210 size_t bytesPerRow; 211 212 HIViewCreateOffscreenImage( handle, 0, &rect, &image); 213 214 int width = subrect != NULL ? subrect->width : (int)rect.size.width; 215 int height = subrect != NULL ? subrect->height : (int)rect.size.height ; 216 217 wxBitmap bmp = wxBitmap(width, height, 32); 218 219 context = (CGContextRef)bmp.GetHBITMAP(); 220 221 CGContextSaveGState(context); 222 223 CGContextTranslateCTM( context, 0, height ); 224 CGContextScaleCTM( context, 1, -1 ); 225 226 if ( subrect ) 227 rect = CGRectOffset( rect, -subrect->x, -subrect->y ) ; 228 CGContextDrawImage( context, rect, image ); 229 230 CGContextRestoreGState(context); 231 232 return bmp; 233#else 234 return wxNullBitmap; 235#endif 236} 237 238/* 239 * wxClientDC 240 */ 241 242wxClientDC::wxClientDC() 243{ 244 m_window = NULL ; 245} 246 247#if wxMAC_USE_CORE_GRAPHICS 248wxClientDC::wxClientDC(wxWindow *window) : 249 wxWindowDC( window ) 250{ 251 wxCHECK_RET( window, _T("invalid window in wxClientDC") ); 252 wxPoint origin = window->GetClientAreaOrigin() ; 253 m_window->GetClientSize( &m_width , &m_height); 254 if ( !m_window->IsShownOnScreen() ) 255 m_width = m_height = 0; 256 SetDeviceOrigin( origin.x, origin.y ); 257 SetClippingRegion( 0 , 0 , m_width , m_height ) ; 258} 259#else 260wxClientDC::wxClientDC(wxWindow *window) 261{ 262 wxCHECK_RET( window, _T("invalid window in wxClientDC") ); 263 m_window = window ; 264 wxTopLevelWindowMac* rootwindow = window->MacGetTopLevelWindow() ; 265 if (!rootwindow) 266 return; 267 268 WindowRef windowref = (WindowRef) rootwindow->MacGetWindowRef() ; 269 wxPoint origin = window->GetClientAreaOrigin() ; 270 wxSize size = window->GetClientSize() ; 271 int x , y ; 272 x = origin.x ; 273 y = origin.y ; 274 window->MacWindowToRootWindow( &x , &y ) ; 275 m_macPort = UMAGetWindowPort( windowref ) ; 276 m_ok = true ; 277 278 m_macLocalOrigin.x = x ; 279 m_macLocalOrigin.y = y ; 280 SetRectRgn( (RgnHandle) m_macBoundaryClipRgn , origin.x , origin.y , origin.x + size.x , origin.y + size.y ) ; 281 SectRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) window->MacGetVisibleRegion().GetWXHRGN() , (RgnHandle) m_macBoundaryClipRgn ) ; 282 OffsetRgn( (RgnHandle) m_macBoundaryClipRgn , -origin.x , -origin.y ) ; 283 OffsetRgn( (RgnHandle) m_macBoundaryClipRgn , m_macLocalOrigin.x , m_macLocalOrigin.y ) ; 284 CopyRgn( (RgnHandle) m_macBoundaryClipRgn ,(RgnHandle) m_macCurrentClipRgn ) ; 285 286 SetBackground(MacGetBackgroundBrush(window)); 287 SetFont( window->GetFont() ) ; 288} 289#endif 290 291wxClientDC::~wxClientDC() 292{ 293} 294 295#if !wxMAC_USE_CORE_GRAPHICS 296void wxClientDC::DoGetSize(int *width, int *height) const 297{ 298 wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") ); 299 300 m_window->GetClientSize( width, height ); 301} 302#endif 303 304/* 305 * wxPaintDC 306 */ 307 308wxPaintDC::wxPaintDC() 309{ 310 m_window = NULL ; 311} 312 313#if wxMAC_USE_CORE_GRAPHICS 314wxPaintDC::wxPaintDC(wxWindow *window) : 315 wxWindowDC( window ) 316{ 317 wxPoint origin = window->GetClientAreaOrigin() ; 318 m_window->GetClientSize( &m_width , &m_height); 319 SetDeviceOrigin( origin.x, origin.y ); 320 SetClippingRegion( 0 , 0 , m_width , m_height ) ; 321} 322#else 323wxPaintDC::wxPaintDC(wxWindow *window) 324{ 325 m_window = window ; 326 wxTopLevelWindowMac* rootwindow = window->MacGetTopLevelWindow() ; 327 WindowRef windowref = (WindowRef) rootwindow->MacGetWindowRef() ; 328 wxPoint origin = window->GetClientAreaOrigin() ; 329 wxSize size = window->GetClientSize() ; 330 int x , y ; 331 x = origin.x ; 332 y = origin.y ; 333 window->MacWindowToRootWindow( &x , &y ) ; 334 m_macPort = UMAGetWindowPort( windowref ) ; 335 m_ok = true ; 336 337#if wxMAC_USE_CORE_GRAPHICS 338 if ( window->MacGetCGContextRef() ) 339 { 340 m_graphicContext = new wxMacCGContext( (CGContextRef) window->MacGetCGContextRef() ) ; 341 m_graphicContext->SetPen( m_pen ) ; 342 m_graphicContext->SetBrush( m_brush ) ; 343 SetClippingRegion( 0 , 0 , size.x , size.y ) ; 344 SetBackground(MacGetBackgroundBrush(window)); 345 } 346 else 347 { 348 wxLogDebug(wxT("You cannot create a wxPaintDC outside an OS-draw event") ) ; 349 m_graphicContext = NULL ; 350 } 351 // there is no out-of-order drawing on OSX 352#else 353 m_macLocalOrigin.x = x ; 354 m_macLocalOrigin.y = y ; 355 SetRectRgn( (RgnHandle) m_macBoundaryClipRgn , origin.x , origin.y , origin.x + size.x , origin.y + size.y ) ; 356 SectRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) window->MacGetVisibleRegion().GetWXHRGN() , (RgnHandle) m_macBoundaryClipRgn ) ; 357 OffsetRgn( (RgnHandle) m_macBoundaryClipRgn , -origin.x , -origin.y ) ; 358 SectRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) window->GetUpdateRegion().GetWXHRGN() , (RgnHandle) m_macBoundaryClipRgn ) ; 359 OffsetRgn( (RgnHandle) m_macBoundaryClipRgn , m_macLocalOrigin.x , m_macLocalOrigin.y ) ; 360 CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; 361 SetBackground(MacGetBackgroundBrush(window)); 362#endif 363 364 SetFont( window->GetFont() ) ; 365} 366#endif 367 368wxPaintDC::~wxPaintDC() 369{ 370} 371 372#if !wxMAC_USE_CORE_GRAPHICS 373void wxPaintDC::DoGetSize(int *width, int *height) const 374{ 375 wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") ); 376 377 m_window->GetClientSize( width, height ); 378} 379#endif 380