xref: /trunk/main/vcl/source/window/cursor.cxx (revision 9f62ea84)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <vcl/svapp.hxx>
28 #include <vcl/timer.hxx>
29 #include <vcl/settings.hxx>
30 #include <vcl/window.hxx>
31 #include <vcl/cursor.hxx>
32 
33 #include <window.h>
34 
35 #include <tools/poly.hxx>
36 
37 
38 // =======================================================================
39 
40 struct ImplCursorData
41 {
42 	AutoTimer		maTimer;			// Timer
43 	Point			maPixPos;			// Pixel-Position
44 	Point			maPixRotOff;		// Pixel-Offset-Position
45 	Size			maPixSize;			// Pixel-Size
46 	long			mnPixSlant; 		// Pixel-Slant
47 	short			mnOrientation;		// Pixel-Orientation
48 	unsigned char	mnDirection;		// indicates writing direction
49 	sal_uInt16			mnStyle;			// Cursor-Style
50 	sal_Bool			mbCurVisible;		// Ist Cursor aktuell sichtbar
51 	Window* 		mpWindow;			// Zugeordnetes Windows
52 };
53 
54 // =======================================================================
55 
ImplCursorInvert(ImplCursorData * pData)56 static void ImplCursorInvert( ImplCursorData* pData )
57 {
58 	Window* pWindow  = pData->mpWindow;
59 	sal_Bool	bMapMode = pWindow->IsMapModeEnabled();
60 	pWindow->EnableMapMode( sal_False );
61 	sal_uInt16 nInvertStyle;
62 	if ( pData->mnStyle & CURSOR_SHADOW )
63 		nInvertStyle = INVERT_50;
64 	else
65 		nInvertStyle = 0;
66 
67 	Rectangle aRect( pData->maPixPos, pData->maPixSize );
68 	if ( pData->mnDirection || pData->mnOrientation || pData->mnPixSlant )
69 	{
70 		Polygon aPoly( aRect );
71         if( aPoly.GetSize() == 5 )
72         {
73             aPoly[1].X() += 1;  // include the right border
74             aPoly[2].X() += 1;
75 		    if ( pData->mnPixSlant )
76 		    {
77 			    Point aPoint = aPoly.GetPoint( 0 );
78 			    aPoint.X() += pData->mnPixSlant;
79 			    aPoly.SetPoint( aPoint, 0 );
80 			    aPoly.SetPoint( aPoint, 4 );
81 			    aPoint = aPoly.GetPoint( 1 );
82 			    aPoint.X() += pData->mnPixSlant;
83 			    aPoly.SetPoint( aPoint, 1 );
84 		    }
85 
86             // apply direction flag after slant to use the correct shape
87 		    if ( pData->mnDirection )
88             {
89                 Point pAry[7];
90                 int delta = 3*aRect.getWidth()+1;
91                 if( pData->mnDirection == CURSOR_DIRECTION_LTR )
92                 {
93                     // left-to-right
94                     pAry[0] = aPoly.GetPoint( 0 );
95                     pAry[1] = aPoly.GetPoint( 1 );
96                     pAry[2] = pAry[1];
97                     pAry[2].X() += delta;
98                     pAry[3] =  pAry[1];
99                     pAry[3].Y() += delta;
100                     pAry[4] = aPoly.GetPoint( 2 );
101                     pAry[5] = aPoly.GetPoint( 3 );
102                     pAry[6] = aPoly.GetPoint( 4 );
103                 }
104                 else if( pData->mnDirection == CURSOR_DIRECTION_RTL )
105                 {
106                     // right-to-left
107                     pAry[0] = aPoly.GetPoint( 0 );
108                     pAry[1] = aPoly.GetPoint( 1 );
109                     pAry[2] = aPoly.GetPoint( 2 );
110                     pAry[3] = aPoly.GetPoint( 3 );
111                     pAry[4] = pAry[0];
112                     pAry[4].Y() += delta;
113                     pAry[5] =  pAry[0];
114                     pAry[5].X() -= delta;
115                     pAry[6] = aPoly.GetPoint( 4 );
116                 }
117                 aPoly = Polygon( 7, pAry);
118             }
119 
120 		    if ( pData->mnOrientation )
121 			    aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
122 		    pWindow->Invert( aPoly, nInvertStyle );
123         }
124 	}
125 	else
126 		pWindow->Invert( aRect, nInvertStyle );
127 	pWindow->EnableMapMode( bMapMode );
128 }
129 
130 // -----------------------------------------------------------------------
131 
ImplDraw()132 void Cursor::ImplDraw()
133 {
134 	if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
135 	{
136 		Window* pWindow 		= mpData->mpWindow;
137 		mpData->maPixPos		= pWindow->LogicToPixel( maPos );
138 		mpData->maPixSize		= pWindow->LogicToPixel( maSize );
139 		mpData->mnPixSlant		= pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
140 		mpData->mnOrientation	= mnOrientation;
141 		mpData->mnDirection	    = mnDirection;
142 		long nOffsetY			= pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height();
143 
144 		// Position um den Offset korrigieren
145 		mpData->maPixPos.Y() -= nOffsetY;
146 		mpData->maPixRotOff = mpData->maPixPos;
147 		mpData->maPixRotOff.Y() += nOffsetY;
148 
149 		// Wenn groesse 0 ist, nehmen wir die breite, die in den
150 		// Settings eingestellt ist
151 		if ( !mpData->maPixSize.Width() )
152 			mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();
153 
154 		// Ausgabeflaeche berechnen und ausgeben
155 		ImplCursorInvert( mpData );
156 		mpData->mbCurVisible = sal_True;
157 	}
158 }
159 
160 // -----------------------------------------------------------------------
161 
ImplRestore()162 void Cursor::ImplRestore()
163 {
164 	if ( mpData && mpData->mbCurVisible )
165 	{
166 		ImplCursorInvert( mpData );
167 		mpData->mbCurVisible = sal_False;
168 	}
169 }
170 
171 // -----------------------------------------------------------------------
172 
ImplShow(bool bDrawDirect,bool bRestore)173 void Cursor::ImplShow( bool bDrawDirect, bool bRestore )
174 {
175 	if ( mbVisible )
176 	{
177 		Window* pWindow;
178 		if ( mpWindow )
179 			pWindow = mpWindow;
180 		else
181 		{
182 			// Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster
183 			// selektiert, dann zeige den Cursor an
184 			pWindow = Application::GetFocusWindow();
185 			if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
186 				|| !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
187 				pWindow = NULL;
188 		}
189 
190 		if ( pWindow )
191 		{
192 			if ( !mpData )
193 			{
194 				mpData = new ImplCursorData;
195 				mpData->mbCurVisible = sal_False;
196 				mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
197 			}
198 
199 			mpData->mpWindow	= pWindow;
200 			mpData->mnStyle 	= mnStyle;
201 			if ( bDrawDirect || bRestore )
202 				ImplDraw();
203 
204 			if ( !mpWindow && ! ( ! bDrawDirect && mpData->maTimer.IsActive()) )
205 			{
206 				mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
207 				if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
208 					mpData->maTimer.Start();
209 				else if ( !mpData->mbCurVisible )
210 					ImplDraw();
211 			}
212 		}
213 	}
214 }
215 
216 // -----------------------------------------------------------------------
217 
ImplHide(bool i_bStopTimer)218 bool Cursor::ImplHide( bool i_bStopTimer )
219 {
220     bool bWasCurVisible = false;
221 	if ( mpData && mpData->mpWindow )
222 	{
223 	    bWasCurVisible = mpData->mbCurVisible;
224 		if ( mpData->mbCurVisible )
225 			ImplRestore();
226 	}
227 
228     if( mpData && i_bStopTimer )
229     {
230         mpData->maTimer.Stop();
231         mpData->mpWindow = NULL;
232     }
233 
234 	return bWasCurVisible;
235 }
236 
237 // -----------------------------------------------------------------------
238 
ImplNew()239 void Cursor::ImplNew()
240 {
241 	if ( mbVisible && mpData && mpData->mpWindow )
242 	{
243 		if ( mpData->mbCurVisible )
244 			ImplRestore();
245 
246 		ImplDraw();
247 		if ( !mpWindow )
248 		{
249 			if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
250 				mpData->maTimer.Start();
251 		}
252 	}
253 }
254 
255 // -----------------------------------------------------------------------
256 
IMPL_LINK(Cursor,ImplTimerHdl,AutoTimer *,EMPTYARG)257 IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG )
258 {
259 	if ( mpData->mbCurVisible )
260 		ImplRestore();
261 	else
262 		ImplDraw();
263 	return 0;
264 }
265 
266 // =======================================================================
267 
Cursor()268 Cursor::Cursor()
269 {
270 	mpData			= NULL;
271 	mpWindow		= NULL;
272 	mnSlant 		= 0;
273 	mnOffsetY		= 0;
274 	mnOrientation	= 0;
275 	mnDirection 	= 0;
276 	mnStyle 		= 0;
277 	mbVisible		= sal_False;
278 }
279 
280 // -----------------------------------------------------------------------
281 
Cursor(const Cursor & rCursor)282 Cursor::Cursor( const Cursor& rCursor ) :
283 	maSize( rCursor.maSize ),
284 	maPos( rCursor.maPos )
285 {
286 	mpData			= NULL;
287 	mpWindow		= NULL;
288 	mnSlant 		= rCursor.mnSlant;
289 	mnOrientation	= rCursor.mnOrientation;
290 	mnDirection 	= rCursor.mnDirection;
291 	mnStyle 		= 0;
292 	mbVisible		= rCursor.mbVisible;
293 }
294 
295 // -----------------------------------------------------------------------
296 
~Cursor()297 Cursor::~Cursor()
298 {
299 	if ( mpData )
300 	{
301 		if ( mpData->mbCurVisible )
302 			ImplRestore();
303 
304 		delete mpData;
305 	}
306 }
307 
308 // -----------------------------------------------------------------------
309 
SetStyle(sal_uInt16 nStyle)310 void Cursor::SetStyle( sal_uInt16 nStyle )
311 {
312 	if ( mnStyle != nStyle )
313 	{
314 		mnStyle = nStyle;
315 		ImplNew();
316 	}
317 }
318 
319 // -----------------------------------------------------------------------
320 
Show()321 void Cursor::Show()
322 {
323 	if ( !mbVisible )
324 	{
325 		mbVisible = sal_True;
326 		ImplShow();
327 	}
328 }
329 
330 // -----------------------------------------------------------------------
331 
Hide()332 void Cursor::Hide()
333 {
334 	if ( mbVisible )
335 	{
336 		mbVisible = sal_False;
337 		ImplHide( true );
338 	}
339 }
340 
341 // -----------------------------------------------------------------------
342 
SetWindow(Window * pWindow)343 void Cursor::SetWindow( Window* pWindow )
344 {
345 	if ( mpWindow != pWindow )
346 	{
347 		mpWindow = pWindow;
348 		ImplNew();
349 	}
350 }
351 
352 // -----------------------------------------------------------------------
353 
SetPos(const Point & rPoint)354 void Cursor::SetPos( const Point& rPoint )
355 {
356 	if ( maPos != rPoint )
357 	{
358 		maPos = rPoint;
359 		ImplNew();
360 	}
361 }
362 
363 // -----------------------------------------------------------------------
364 
SetOffsetY(long nNewOffsetY)365 void Cursor::SetOffsetY( long nNewOffsetY )
366 {
367 	if ( mnOffsetY != nNewOffsetY )
368 	{
369 		mnOffsetY = nNewOffsetY;
370 		ImplNew();
371 	}
372 }
373 
374 // -----------------------------------------------------------------------
375 
SetSize(const Size & rSize)376 void Cursor::SetSize( const Size& rSize )
377 {
378 	if ( maSize != rSize )
379 	{
380 		maSize = rSize;
381 		ImplNew();
382 	}
383 }
384 
385 // -----------------------------------------------------------------------
386 
SetWidth(long nNewWidth)387 void Cursor::SetWidth( long nNewWidth )
388 {
389 	if ( maSize.Width() != nNewWidth )
390 	{
391 		maSize.Width() = nNewWidth;
392 		ImplNew();
393 	}
394 }
395 
396 // -----------------------------------------------------------------------
397 
SetHeight(long nNewHeight)398 void Cursor::SetHeight( long nNewHeight )
399 {
400 	if ( maSize.Height() != nNewHeight )
401 	{
402 		maSize.Height() = nNewHeight;
403 		ImplNew();
404 	}
405 }
406 
407 // -----------------------------------------------------------------------
408 
SetSlant(long nNewSlant)409 void Cursor::SetSlant( long nNewSlant )
410 {
411 	if ( mnSlant != nNewSlant )
412 	{
413 		mnSlant = nNewSlant;
414 		ImplNew();
415 	}
416 }
417 
418 // -----------------------------------------------------------------------
419 
SetOrientation(short nNewOrientation)420 void Cursor::SetOrientation( short nNewOrientation )
421 {
422 	if ( mnOrientation != nNewOrientation )
423 	{
424 		mnOrientation = nNewOrientation;
425 		ImplNew();
426 	}
427 }
428 
429 // -----------------------------------------------------------------------
430 
SetDirection(unsigned char nNewDirection)431 void Cursor::SetDirection( unsigned char nNewDirection )
432 {
433 	if ( mnDirection != nNewDirection )
434 	{
435 		mnDirection = nNewDirection;
436 		ImplNew();
437 	}
438 }
439 
440 // -----------------------------------------------------------------------
441 
operator =(const Cursor & rCursor)442 Cursor& Cursor::operator=( const Cursor& rCursor )
443 {
444 	maPos			= rCursor.maPos;
445 	maSize			= rCursor.maSize;
446 	mnSlant 		= rCursor.mnSlant;
447 	mnOrientation	= rCursor.mnOrientation;
448 	mnDirection 	= rCursor.mnDirection;
449 	mbVisible		= rCursor.mbVisible;
450 	ImplNew();
451 
452 	return *this;
453 }
454 
455 // -----------------------------------------------------------------------
456 
operator ==(const Cursor & rCursor) const457 sal_Bool Cursor::operator==( const Cursor& rCursor ) const
458 {
459 	if ( (maPos 		== rCursor.maPos)			&&
460 		 (maSize		== rCursor.maSize)			&&
461 		 (mnSlant		== rCursor.mnSlant) 		&&
462 		 (mnOrientation == rCursor.mnOrientation)	&&
463 		 (mnDirection   == rCursor.mnDirection)	    &&
464 		 (mbVisible 	== rCursor.mbVisible) )
465 		return sal_True;
466 	else
467 		return sal_False;
468 }
469