]> git.saurik.com Git - wxWidgets.git/blame - src/x11/region.cpp
use SubclassWin() insteaf of just wxAssociateWinWithHandle() to make sure we generate...
[wxWidgets.git] / src / x11 / region.cpp
CommitLineData
83df96d6 1/////////////////////////////////////////////////////////////////////////////
55034339 2// File: src/x11/region.cpp
83df96d6 3// Purpose: Region class
2e579471 4// Author: Julian Smart, Robert Roebling
83df96d6 5// Created: Fri Oct 24 10:46:34 MET 1997
6aa89a22 6// RCS-ID: $Id$
2e579471 7// Copyright: (c) 1997 Julian Smart, Robert Roebling
65571936 8// Licence: wxWindows licence
83df96d6
JS
9/////////////////////////////////////////////////////////////////////////////
10
55034339
WS
11// for compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
83df96d6 14#include "wx/region.h"
e4db172a
WS
15
16#ifndef WX_PRECOMP
17 #include "wx/log.h"
18#endif
19
83df96d6
JS
20#include "wx/gdicmn.h"
21
22#ifdef __VMS__
23#pragma message disable nosimpint
24#endif
7266b672
JS
25#include "wx/x11/private.h"
26#include "X11/Xutil.h"
83df96d6
JS
27#ifdef __VMS__
28#pragma message enable nosimpint
29#endif
7266b672 30
83df96d6 31// ----------------------------------------------------------------------------
1934d291 32// wxRegionRefData: private class containing the information about the region
83df96d6
JS
33// ----------------------------------------------------------------------------
34
1934d291
RR
35class wxRegionRefData : public wxObjectRefData
36{
83df96d6
JS
37public:
38 wxRegionRefData()
39 {
1934d291 40 m_region = NULL;
83df96d6 41 }
55034339 42
1934d291 43 wxRegionRefData(const wxRegionRefData& refData)
83df96d6
JS
44 {
45 m_region = XCreateRegion();
1934d291 46 XUnionRegion( refData.m_region, m_region, m_region );
83df96d6 47 }
55034339 48
83df96d6
JS
49 ~wxRegionRefData()
50 {
1934d291
RR
51 if (m_region)
52 XDestroyRegion( m_region );
83df96d6
JS
53 }
54
1934d291
RR
55 Region m_region;
56};
83df96d6 57
1934d291
RR
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
83df96d6 61
1934d291
RR
62#define M_REGIONDATA ((wxRegionRefData *)m_refData)
63#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
64
e933b5bc
VZ
65IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
66IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
1934d291
RR
67
68// ----------------------------------------------------------------------------
69// wxRegion construction
70// ----------------------------------------------------------------------------
71
72#define M_REGIONDATA ((wxRegionRefData *)m_refData)
73
74void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
75{
76 XRectangle rect;
55034339
WS
77 rect.x = (short)x;
78 rect.y = (short)y;
79 rect.width = (unsigned short)w;
80 rect.height = (unsigned short)h;
81
1934d291 82 m_refData = new wxRegionRefData();
55034339 83
1934d291
RR
84 M_REGIONDATA->m_region = XCreateRegion();
85 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
86}
83df96d6 87
55034339 88wxRegion::wxRegion( size_t WXUNUSED(n), const wxPoint *WXUNUSED(points), int WXUNUSED(fillStyle) )
83df96d6 89{
1934d291
RR
90#if 0
91 XPoint *xpoints = new XPoint[n];
92 for ( size_t i = 0 ; i < n ; i++ )
83df96d6 93 {
1934d291
RR
94 xpoints[i].x = points[i].x;
95 xpoints[i].y = points[i].y;
83df96d6
JS
96 }
97
1934d291
RR
98 m_refData = new wxRegionRefData();
99
100 Region* reg = gdk_region_polygon
101 (
102 gdkpoints,
103 n,
104 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
105 : GDK_EVEN_ODD_RULE
106 );
107
108 M_REGIONDATA->m_region = reg;
109
110 delete [] xpoints;
111#endif
83df96d6
JS
112}
113
1934d291 114wxRegion::~wxRegion()
83df96d6 115{
1934d291 116 // m_refData unrefed in ~wxObject
83df96d6
JS
117}
118
1934d291 119wxObjectRefData *wxRegion::CreateRefData() const
83df96d6 120{
1934d291
RR
121 return new wxRegionRefData;
122}
83df96d6 123
1934d291
RR
124wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
125{
126 return new wxRegionRefData(*(wxRegionRefData *)data);
127}
83df96d6 128
1934d291
RR
129// ----------------------------------------------------------------------------
130// wxRegion comparison
131// ----------------------------------------------------------------------------
83df96d6 132
fbfb8bcc 133bool wxRegion::operator==( const wxRegion& region ) const
83df96d6 134{
55034339
WS
135 if (m_refData == region.m_refData) return true;
136
137 if (!m_refData || !region.m_refData) return false;
1934d291 138
1934d291
RR
139 // compare the regions themselves, not the pointers to ref data!
140 return XEqualRegion( M_REGIONDATA->m_region,
55034339 141 M_REGIONDATA_OF(region)->m_region ) == True;
83df96d6
JS
142}
143
1934d291
RR
144// ----------------------------------------------------------------------------
145// wxRegion operations
146// ----------------------------------------------------------------------------
147
148void wxRegion::Clear()
83df96d6 149{
1934d291
RR
150 UnRef();
151}
83df96d6 152
1934d291
RR
153bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
154{
9afe6c17
VZ
155 // work around for XUnionRectWithRegion() bug: taking a union with an empty
156 // rect results in an empty region (at least XFree 3.3.6 and 4.0 have this
157 // problem)
158 if ( !width || !height )
55034339 159 return true;
9afe6c17 160
83df96d6 161 XRectangle rect;
55034339
WS
162 rect.x = (short)x;
163 rect.y = (short)y;
164 rect.width = (unsigned short)width;
165 rect.height = (unsigned short)height;
166
1934d291
RR
167 if (!m_refData)
168 {
169 m_refData = new wxRegionRefData();
170 M_REGIONDATA->m_region = XCreateRegion();
171 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
172 }
173 else
174 {
175 AllocExclusive();
176
177 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
178 }
179
55034339 180 return true;
83df96d6
JS
181}
182
1934d291 183bool wxRegion::Union( const wxRect& rect )
83df96d6 184{
1934d291
RR
185 return Union( rect.x, rect.y, rect.width, rect.height );
186}
83df96d6 187
1934d291
RR
188bool wxRegion::Union( const wxRegion& region )
189{
190 if (region.IsNull())
55034339 191 return false;
1934d291
RR
192
193 if (!m_refData)
194 {
195 m_refData = new wxRegionRefData();
196 M_REGIONDATA->m_region = XCreateRegion();
197 }
198 else
199 {
200 AllocExclusive();
201 }
55034339 202
1934d291
RR
203 XUnionRegion( M_REGIONDATA->m_region,
204 M_REGIONDATA_OF(region)->m_region,
205 M_REGIONDATA->m_region );
206
55034339 207 return true;
83df96d6
JS
208}
209
1934d291 210bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 211{
1934d291 212 wxRegion reg( x, y, width, height );
83df96d6 213
1934d291 214 return Intersect( reg );
83df96d6
JS
215}
216
1934d291 217bool wxRegion::Intersect( const wxRect& rect )
83df96d6 218{
1934d291 219 wxRegion reg( rect );
55034339 220
1934d291 221 return Intersect( reg );
83df96d6
JS
222}
223
1934d291 224bool wxRegion::Intersect( const wxRegion& region )
83df96d6 225{
1934d291 226 if (region.IsNull())
55034339 227 return false;
1934d291
RR
228
229 if (!m_refData)
230 {
231 m_refData = new wxRegionRefData();
232 M_REGIONDATA->m_region = XCreateRegion();
55034339
WS
233
234 // leave here
235 return true;
1934d291
RR
236 }
237 else
238 {
239 AllocExclusive();
240 }
83df96d6 241
1934d291
RR
242 XIntersectRegion( M_REGIONDATA->m_region,
243 M_REGIONDATA_OF(region)->m_region,
244 M_REGIONDATA->m_region );
245
55034339 246 return true;
83df96d6
JS
247}
248
1934d291
RR
249bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
250{
251 wxRegion reg( x, y, width, height );
252 return Subtract( reg );
253}
83df96d6 254
1934d291 255bool wxRegion::Subtract( const wxRect& rect )
83df96d6 256{
1934d291
RR
257 wxRegion reg( rect );
258 return Subtract( reg );
83df96d6
JS
259}
260
1934d291 261bool wxRegion::Subtract( const wxRegion& region )
83df96d6 262{
1934d291 263 if (region.IsNull())
55034339 264 return false;
1934d291
RR
265
266 if (!m_refData)
267 {
83df96d6 268 m_refData = new wxRegionRefData();
1934d291
RR
269 M_REGIONDATA->m_region = XCreateRegion();
270 }
271 else
272 {
273 AllocExclusive();
83df96d6 274 }
83df96d6 275
1934d291
RR
276 XSubtractRegion( M_REGIONDATA->m_region,
277 M_REGIONDATA_OF(region)->m_region,
278 M_REGIONDATA->m_region );
83df96d6 279
55034339 280 return true;
1934d291 281}
83df96d6 282
1934d291
RR
283bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
284{
285 wxRegion reg( x, y, width, height );
286 return Xor( reg );
287}
83df96d6 288
1934d291
RR
289bool wxRegion::Xor( const wxRect& rect )
290{
291 wxRegion reg( rect );
292 return Xor( reg );
83df96d6
JS
293}
294
1934d291 295bool wxRegion::Xor( const wxRegion& region )
83df96d6 296{
1934d291 297 if (region.IsNull())
55034339 298 return false;
83df96d6 299
1934d291
RR
300 if (!m_refData)
301 {
83df96d6 302 m_refData = new wxRegionRefData();
1934d291 303 M_REGIONDATA->m_region = XCreateRegion();
83df96d6 304 }
1934d291 305 else
83df96d6 306 {
1934d291 307 AllocExclusive();
83df96d6
JS
308 }
309
1934d291
RR
310 XXorRegion( M_REGIONDATA->m_region,
311 M_REGIONDATA_OF(region)->m_region,
312 M_REGIONDATA->m_region );
55034339
WS
313
314 return true;
83df96d6
JS
315}
316
1934d291
RR
317// ----------------------------------------------------------------------------
318// wxRegion tests
319// ----------------------------------------------------------------------------
83df96d6 320
1934d291 321void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
83df96d6 322{
1934d291
RR
323 if (m_refData)
324 {
83df96d6 325 XRectangle rect;
1934d291 326 XClipBox( M_REGIONDATA->m_region, &rect );
83df96d6
JS
327 x = rect.x;
328 y = rect.y;
329 w = rect.width;
330 h = rect.height;
1934d291
RR
331 }
332 else
333 {
334 x = 0;
335 y = 0;
336 w = -1;
337 h = -1;
83df96d6
JS
338 }
339}
340
341wxRect wxRegion::GetBox() const
342{
343 wxCoord x, y, w, h;
1934d291
RR
344 GetBox( x, y, w, h );
345 return wxRect( x, y, w, h );
83df96d6
JS
346}
347
1934d291 348bool wxRegion::Offset( wxCoord x, wxCoord y )
83df96d6 349{
1934d291 350 if (!m_refData)
55034339 351 return false;
83df96d6 352
1934d291
RR
353 AllocExclusive();
354
355 XOffsetRegion( M_REGIONDATA->m_region, x, y );
356
55034339 357 return true;
1934d291 358}
83df96d6 359
1934d291 360bool wxRegion::Empty() const
83df96d6
JS
361{
362 if (!m_refData)
55034339 363 return true;
83df96d6 364
55034339 365 return XEmptyRegion( M_REGIONDATA->m_region ) == True;
83df96d6
JS
366}
367
1934d291 368wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
83df96d6
JS
369{
370 if (!m_refData)
371 return wxOutRegion;
372
1934d291
RR
373 if (XPointInRegion( M_REGIONDATA->m_region, x, y ))
374 return wxInRegion;
375 else
376 return wxOutRegion;
83df96d6
JS
377}
378
1934d291 379wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
83df96d6
JS
380{
381 if (!m_refData)
382 return wxOutRegion;
383
1934d291
RR
384 int res = XRectInRegion( M_REGIONDATA->m_region, x, y, w, h );
385 switch (res)
386 {
387 case RectangleIn: return wxInRegion;
388 case RectangleOut: return wxOutRegion;
83df96d6
JS
389 case RectanglePart: return wxPartRegion;
390 }
391 return wxOutRegion;
392}
393
1934d291 394wxRegionContain wxRegion::Contains(const wxPoint& pt) const
83df96d6 395{
1934d291 396 return Contains( pt.x, pt.y );
83df96d6
JS
397}
398
1934d291 399wxRegionContain wxRegion::Contains(const wxRect& rect) const
83df96d6 400{
1934d291 401 return Contains( rect.x, rect.y, rect.width, rect.height );
83df96d6
JS
402}
403
1934d291 404WXRegion *wxRegion::GetX11Region() const
83df96d6 405{
1934d291
RR
406 if (!m_refData)
407 return (WXRegion*) NULL;
83df96d6 408
1934d291 409 return (WXRegion*) M_REGIONDATA->m_region;
83df96d6
JS
410}
411
1934d291
RR
412// ----------------------------------------------------------------------------
413// wxRegionIterator
414// ----------------------------------------------------------------------------
83df96d6 415
1934d291
RR
416// the following structures must match the private structures
417// in X11 region code ( xc/lib/X11/region.h )
418
419// this makes the Region type transparent
420// and we have access to the region rectangles
83df96d6 421
1934d291
RR
422struct _XBox {
423 short x1, x2, y1, y2;
424};
425
426struct _XRegion {
427 long size , numRects;
428 _XBox *rects, extents;
429};
430
431class wxRIRefData: public wxObjectRefData
83df96d6 432{
1934d291 433public:
83df96d6 434
1934d291
RR
435 wxRIRefData() : m_rects(0), m_numRects(0){}
436 ~wxRIRefData();
437
438 wxRect *m_rects;
439 size_t m_numRects;
440
441 void CreateRects( const wxRegion& r );
442};
83df96d6 443
1934d291 444wxRIRefData::~wxRIRefData()
83df96d6 445{
64423153 446 delete [] m_rects;
83df96d6
JS
447}
448
1934d291 449void wxRIRefData::CreateRects( const wxRegion& region )
83df96d6
JS
450{
451 if (m_rects)
64423153 452 delete [] m_rects;
1934d291
RR
453
454 m_rects = 0;
455 m_numRects = 0;
55034339 456
1934d291 457 if (region.IsEmpty()) return;
55034339 458
1934d291
RR
459 Region r = (Region) region.GetX11Region();
460 if (r)
461 {
461e93f9
JS
462#if wxUSE_NANOX
463 GR_RECT rect;
464 GrGetRegionBox(r, & rect);
465 m_numRects = 1;
466 m_rects = new wxRect[1];
467 m_rects[0].x = rect.x;
468 m_rects[0].y = rect.y;
469 m_rects[0].width = rect.width;
470 m_rects[0].height = rect.height;
471#else
1934d291
RR
472 m_numRects = r->numRects;
473 if (m_numRects)
474 {
475 m_rects = new wxRect[m_numRects];
476 for (size_t i=0; i < m_numRects; ++i)
477 {
478 _XBox &xr = r->rects[i];
479 wxRect &wr = m_rects[i];
480 wr.x = xr.x1;
481 wr.y = xr.y1;
482 wr.width = xr.x2-xr.x1;
483 wr.height = xr.y2-xr.y1;
484 }
485 }
461e93f9 486#endif
1934d291 487 }
83df96d6
JS
488}
489
1934d291 490wxRegionIterator::wxRegionIterator()
83df96d6 491{
1934d291
RR
492 m_refData = new wxRIRefData();
493 Reset();
494}
83df96d6 495
1934d291
RR
496wxRegionIterator::wxRegionIterator( const wxRegion& region )
497{
498 m_refData = new wxRIRefData();
83df96d6
JS
499 Reset(region);
500}
501
1934d291 502void wxRegionIterator::Reset( const wxRegion& region )
83df96d6 503{
83df96d6 504 m_region = region;
1934d291
RR
505 ((wxRIRefData*)m_refData)->CreateRects(region);
506 Reset();
507}
83df96d6 508
1934d291
RR
509bool wxRegionIterator::HaveRects() const
510{
511 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
512}
83df96d6 513
1934d291
RR
514wxRegionIterator::operator bool () const
515{
516 return HaveRects();
83df96d6
JS
517}
518
83df96d6
JS
519void wxRegionIterator::operator ++ ()
520{
1934d291 521 if (HaveRects()) ++m_current;
83df96d6
JS
522}
523
83df96d6
JS
524void wxRegionIterator::operator ++ (int)
525{
1934d291 526 if (HaveRects()) ++m_current;
83df96d6
JS
527}
528
529wxCoord wxRegionIterator::GetX() const
530{
1934d291
RR
531 if( !HaveRects() ) return 0;
532 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
83df96d6
JS
533}
534
535wxCoord wxRegionIterator::GetY() const
536{
1934d291
RR
537 if( !HaveRects() ) return 0;
538 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
83df96d6
JS
539}
540
541wxCoord wxRegionIterator::GetW() const
542{
1934d291
RR
543 if( !HaveRects() ) return -1;
544 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
83df96d6
JS
545}
546
547wxCoord wxRegionIterator::GetH() const
548{
1934d291
RR
549 if( !HaveRects() ) return -1;
550 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
551}
552
553wxRect wxRegionIterator::GetRect() const
554{
555 wxRect r;
556 if( HaveRects() )
557 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
558
559 return r;
83df96d6 560}