source: trunk/src/gui/kernel/qcursor_pm.cpp@ 858

Last change on this file since 858 was 659, checked in by Dmitry A. Kuminov, 15 years ago

global: Updated year to 2010 in OS/2-specific headers.

File size: 17.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** Copyright (C) 2010 netlabs.org. OS/2 parts.
8**
9** This file is part of the QtGui module of the Qt Toolkit.
10**
11** $QT_BEGIN_LICENSE:LGPL$
12** Commercial Usage
13** Licensees holding valid Qt Commercial licenses may use this file in
14** accordance with the Qt Commercial License Agreement provided with the
15** Software or, alternatively, in accordance with the terms contained in
16** a written agreement between you and Nokia.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 2.1 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 2.1 requirements
24** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Nokia gives you certain additional
27** rights. These rights are described in the Nokia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file. Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** If you have questions regarding the use of this file, please contact
39** Nokia at [email protected].
40** $QT_END_LICENSE$
41**
42****************************************************************************/
43
44#include <private/qcursor_p.h>
45#include <qbitmap.h>
46#include <qcursor.h>
47
48#ifndef QT_NO_CURSOR
49
50#include <qicon.h>
51#include <qapplication.h>
52#include <qdesktopwidget.h>
53#include <qt_os2.h>
54
55QT_BEGIN_NAMESPACE
56
57extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
58
59extern HPS qt_alloc_mem_ps(int w, int h, HPS compat = 0); // qpixmap_pm.cpp
60extern void qt_free_mem_ps(HPS hps); // qpixmap_pm.cpp
61
62/*****************************************************************************
63 Internal QCursorData class
64 *****************************************************************************/
65
66QCursorData::QCursorData(Qt::CursorShape s)
67 : cshape(s), bm(0), bmm(0), hx(0), hy(0), hptr(NULLHANDLE), isSysPtr(false)
68{
69 ref = 1;
70}
71
72QCursorData::~QCursorData()
73{
74 delete bm;
75 delete bmm;
76 if (hptr && !isSysPtr)
77 WinDestroyPointer(hptr);
78}
79
80
81QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
82{
83 if (!QCursorData::initialized)
84 QCursorData::initialize();
85 if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
86 qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
87 QCursorData *c = qt_cursorTable[0];
88 c->ref.ref();
89 return c;
90 }
91 QCursorData *d = new QCursorData;
92 d->bm = new QBitmap(bitmap);
93 d->bmm = new QBitmap(mask);
94 d->hptr = NULLHANDLE;
95 d->cshape = Qt::BitmapCursor;
96 d->hx = hotX >= 0 ? hotX : bitmap.width()/2;
97 d->hy = hotY >= 0 ? hotY : bitmap.height()/2;
98 return d;
99}
100
101HPOINTER QCursor::handle() const
102{
103 if (!QCursorData::initialized)
104 QCursorData::initialize();
105 if (d->hptr == NULLHANDLE)
106 d->update();
107 return d->hptr;
108}
109
110QCursor::QCursor(HPOINTER handle)
111{
112 d = new QCursorData(Qt::CustomCursor);
113 d->hptr = handle;
114}
115
116#endif //QT_NO_CURSOR
117
118QPoint QCursor::pos()
119{
120 POINTL p;
121 WinQueryPointerPos(HWND_DESKTOP, &p);
122 // flip y coordinate
123 p.y = qt_display_height() - (p.y + 1);
124 return QPoint(p.x, p.y);
125}
126
127void QCursor::setPos(int x, int y)
128{
129 // flip y coordinate
130 y = qt_display_height() - (y + 1);
131 WinSetPointerPos(HWND_DESKTOP, x, y);
132}
133
134#ifndef QT_NO_CURSOR
135
136enum { cursor_uparrow_x = 11, cursor_uparrow_y = 1 };
137static char const * const cursor_uparrow_xpm[] = {
138"24 24 3 1",
139" c None",
140". c #000000",
141"+ c #FFFFFF",
142" ",
143" ++ ",
144" +..+ ",
145" +....+ ",
146" +......+ ",
147" +........+ ",
148" +++..+++ ",
149" +..+ ",
150" +..+ ",
151" +..+ ",
152" +..+ ",
153" +..+ ",
154" +..+ ",
155" +..+ ",
156" +..+ ",
157" +..+ ",
158" +..+ ",
159" +..+ ",
160" +..+ ",
161" +..+ ",
162" +..+ ",
163" ++ ",
164" ",
165" "};
166
167enum { cursor_cross_x = 11, cursor_cross_y = 11 };
168static char const * const cursor_cross_xpm[] = {
169"24 24 3 1",
170" c None",
171". c #FFFFFF",
172"+ c #000000",
173" ",
174" .. ",
175" .++. ",
176" .++. ",
177" .++. ",
178" .++. ",
179" .++. ",
180" .++. ",
181" .++. ",
182" .++. ",
183" ........ ........ ",
184" .++++++++ ++++++++. ",
185" .++++++++ ++++++++. ",
186" ........ ........ ",
187" .++. ",
188" .++. ",
189" .++. ",
190" .++. ",
191" .++. ",
192" .++. ",
193" .++. ",
194" .++. ",
195" .. ",
196" "};
197
198enum { cursor_vsplit_x = 11, cursor_vsplit_y = 11 };
199static char const * const cursor_vsplit_xpm[] = {
200"24 24 3 1",
201" c None",
202". c #000000",
203"+ c #FFFFFF",
204" ",
205" ++ ",
206" +..+ ",
207" +....+ ",
208" +......+ ",
209" +........+ ",
210" +++..+++ ",
211" +..+ ",
212" +++++++++..+++++++++ ",
213" +....................+ ",
214" +....................+ ",
215" ++++++++++++++++++++ ",
216" ++++++++++++++++++++ ",
217" +....................+ ",
218" +....................+ ",
219" +++++++++..+++++++++ ",
220" +..+ ",
221" +++..+++ ",
222" +........+ ",
223" +......+ ",
224" +....+ ",
225" +..+ ",
226" ++ ",
227" "};
228
229enum { cursor_hsplit_x = 11, cursor_hsplit_y = 11 };
230static char const * const cursor_hsplit_xpm[] = {
231"24 24 3 1",
232" c None",
233". c #000000",
234"+ c #FFFFFF",
235" ",
236" ++++++ ",
237" +..++..+ ",
238" +..++..+ ",
239" +..++..+ ",
240" +..++..+ ",
241" +..++..+ ",
242" + +..++..+ + ",
243" +.+ +..++..+ +.+ ",
244" +..+ +..++..+ +..+ ",
245" +...+++..++..+++...+ ",
246" +.........++.........+ ",
247" +.........++.........+ ",
248" +...+++..++..+++...+ ",
249" +..+ +..++..+ +..+ ",
250" +.+ +..++..+ +.+ ",
251" + +..++..+ + ",
252" +..++..+ ",
253" +..++..+ ",
254" +..++..+ ",
255" +..++..+ ",
256" +..++..+ ",
257" ++++++ ",
258" "};
259
260enum { cursor_blank_x = 0, cursor_blank_y = 0 };
261static char const * const cursor_blank_xpm[] = {
262"1 1 1 1",
263" c None",
264" "};
265
266enum { cursor_hand_x = 9, cursor_hand_y = 0 };
267static char const * const cursor_hand_xpm[] = {
268"24 24 3 1",
269" c None",
270". c #FFFFFF",
271"+ c #000000",
272" ++ ",
273" +..+ ",
274" +..+ ",
275" +..+ ",
276" +..+ ",
277" +..+ ",
278" +..+++ ",
279" +..+..+++ ",
280" +..+..+..++ ",
281" ++ +..+..+..+.+ ",
282" +..++..+..+..+.+ ",
283" +...+..........+ ",
284" +.............+ ",
285" +............+ ",
286" +............+ ",
287" +..........+ ",
288" +..........+ ",
289" +........+ ",
290" +........+ ",
291" ++++++++++ ",
292" ++++++++++ ",
293" ++++++++++ ",
294" ",
295" "};
296
297enum { cursor_whatsthis_x = 0, cursor_whatsthis_y = 0 };
298static char const * const cursor_whatsthis_xpm[] = {
299"24 24 3 1",
300" c None",
301". c #000000",
302"+ c #FFFFFF",
303". ",
304".. ++++++ ",
305".+. +......+ ",
306".++. +........+ ",
307".+++. +....++....+ ",
308".++++. +...+ +...+ ",
309".+++++. +...+ +...+ ",
310".++++++. +.+ +....+ ",
311".+++++++. + +....+ ",
312".++++++++. +....+ ",
313".+++++..... +...+ ",
314".++.++. +...+ ",
315".+. .++. +...+ ",
316".. .++. +++ ",
317". .++. +...+ ",
318" .++. +...+ ",
319" .++. +...+ ",
320" .++. +++ ",
321" .. ",
322" ",
323" ",
324" ",
325" ",
326" "};
327
328enum { cursor_openhand_x = 7, cursor_openhand_y = 7 };
329static char const * const cursor_openhand_xpm[] = {
330"16 16 3 1",
331" g None",
332". g #000000",
333"+ g #FFFFFF",
334" .. ",
335" .. .++... ",
336" .++..++.++. ",
337" .++..++.++. . ",
338" .++.++.++..+.",
339" .++.++.++.++.",
340" ..+.+++++++.++.",
341".++..++++++++++.",
342".+++.+++++++++. ",
343" .++++++++++++. ",
344" .+++++++++++. ",
345" .++++++++++. ",
346" .+++++++++. ",
347" .+++++++. ",
348" .++++++. ",
349" "};
350
351enum { cursor_closedhand_x = 7, cursor_closedhand_y = 7 };
352static char const * const cursor_closedhand_xpm[] = {
353"16 16 3 1",
354" g None",
355". g #000000",
356"+ g #FFFFFF",
357" ",
358" ",
359" ",
360" .. .. .. ",
361" .++.++.++.. ",
362" .++++++++.+. ",
363" .+++++++++. ",
364" ..+++++++++. ",
365" .+++++++++++. ",
366" .++++++++++. ",
367" .+++++++++. ",
368" .+++++++. ",
369" .++++++. ",
370" .++++++. ",
371" ",
372" "};
373
374static bool qt_alloc_ps_with_bitmap(int w, int h, bool isMono,
375 HPS &hps, HBITMAP &hbm)
376{
377 hps = qt_alloc_mem_ps(32, 32);
378 if (hps == NULLHANDLE)
379 return false;
380
381 BITMAPINFOHEADER2 bmh;
382 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
383 bmh.cx = w;
384 bmh.cy = h;
385 bmh.cPlanes = 1;
386 bmh.cBitCount = isMono ? 1 : 32;
387 hbm = GpiCreateBitmap(hps, &bmh, 0, 0, 0);
388 if (hbm == NULLHANDLE) {
389 qt_free_mem_ps(hps);
390 return false;
391 }
392
393 GpiSetBitmap(hps, hbm);
394 return true;
395}
396
397static void qt_free_ps_with_bitmap(HPS hps, HBITMAP hbm)
398{
399 GpiSetBitmap(hps, NULLHANDLE);
400 GpiDeleteBitmap(hbm);
401 qt_free_mem_ps(hps);
402}
403
404static HPOINTER combineTwoCursors(LONG idOver, LONG idUnder)
405{
406 HPOINTER hptr = NULLHANDLE;
407
408 POINTERINFO piOver, piUnder;
409 HPOINTER hOver = WinQuerySysPointer(HWND_DESKTOP, idOver, FALSE);
410 WinQueryPointerInfo(hOver, &piOver);
411 HPOINTER hUnder = WinQuerySysPointer(HWND_DESKTOP, idUnder, FALSE);
412 WinQueryPointerInfo(hUnder, &piUnder);
413 if (piOver.hbmColor) {
414 HPS hpsPtr, hpsTmp, hpsMask;
415 HBITMAP hbmPtr, hbmTmp, hbmMask;
416 qt_alloc_ps_with_bitmap(32, 32, false, hpsPtr, hbmPtr);
417 qt_alloc_ps_with_bitmap(32, 32, false, hpsTmp, hbmTmp);
418 qt_alloc_ps_with_bitmap(32, 64, true, hpsMask, hbmMask);
419 // copy the overlying pointer
420 POINTL ptls[] = { { 0, 0 }, { 31, 31 }, { 0, 0 }, { 32, 32 } };
421 GpiWCBitBlt(hpsTmp, piOver.hbmColor, 4, ptls, ROP_SRCCOPY, BBO_IGNORE);
422 // make its transparent pixels black
423 ptls[2].y += 32; ptls[3].y += 32;
424 GpiSetColor(hpsTmp, CLR_TRUE);
425 GpiSetBackColor(hpsTmp, CLR_FALSE);
426 GpiWCBitBlt(hpsTmp, piOver.hbmPointer, 4, ptls, 0x22, BBO_IGNORE);
427 // copy the underlying pointer
428 ptls[2].y -= 32; ptls[3].y -= 32;
429 GpiWCBitBlt(hpsPtr, piUnder.hbmColor, 4, ptls, ROP_SRCCOPY, BBO_IGNORE);
430 // make non-transparent pixels from the overlying pointer black
431 ptls[2].y += 32; ptls[3].y += 32;
432 GpiSetColor(hpsPtr, CLR_TRUE);
433 GpiSetBackColor(hpsPtr, CLR_FALSE);
434 GpiWCBitBlt(hpsPtr, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE);
435 // put the overlying pointer there
436 ptls[2].y -= 32; ptls[3].y -= 32;
437 ptls[1].x ++; ptls[1].y ++;
438 GpiBitBlt(hpsPtr, hpsTmp, 4, ptls, ROP_SRCPAINT, BBO_IGNORE);
439 // copy both underlying pointer's masks
440 ptls[1].x --; ptls[1].y --;
441 ptls[1].y += 32; ptls[3].y += 32;
442 GpiWCBitBlt(hpsMask, piUnder.hbmPointer, 4, ptls, ROP_SRCCOPY, BBO_IGNORE);
443 // add overlying pointer's XOR mask
444 ptls[1].y -= 32; ptls[3].y -= 32;
445 GpiWCBitBlt(hpsMask, piOver.hbmPointer, 4, ptls, ROP_SRCPAINT, BBO_IGNORE);
446 // add overlying pointer's AND mask
447 ptls[0].y += 32; ptls[2].y += 32;
448 ptls[1].y += 32; ptls[3].y += 32;
449 GpiWCBitBlt(hpsMask, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE);
450 // create the new pointer
451 GpiSetBitmap(hpsPtr, NULLHANDLE);
452 GpiSetBitmap(hpsMask, NULLHANDLE);
453 piOver.hbmColor = hbmPtr;
454 piOver.hbmPointer = hbmMask;
455 piOver.hbmMiniColor = NULLHANDLE;
456 piOver.hbmMiniPointer = NULLHANDLE;
457 hptr = WinCreatePointerIndirect(HWND_DESKTOP, &piOver);
458 qt_free_ps_with_bitmap(hpsMask, hbmMask);
459 qt_free_ps_with_bitmap(hpsTmp, hbmTmp);
460 qt_free_ps_with_bitmap(hpsPtr, hbmPtr);
461 } else {
462 HPS hps;
463 HBITMAP hbm;
464 qt_alloc_ps_with_bitmap(32, 64, true, hps, hbm);
465 POINTL ptls[] = { { 0, 0 }, { 31, 63 }, { 0, 0 }, { 32, 64 } };
466 // make a copy of the underlying pointer
467 GpiWCBitBlt(hps, piUnder.hbmPointer, 4, ptls, ROP_SRCCOPY, BBO_IGNORE);
468 // combine AND masks
469 ptls[0].y += 32; ptls[2].y += 32;
470 GpiWCBitBlt(hps, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE);
471 // apply the overlying AND mask to the underlying XOR mask
472 ptls[0].y -= 32; ptls[1].y -= 32;
473 GpiWCBitBlt(hps, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE);
474 // apply the overlying XOR mask to the underlying XOR mask
475 ptls[2].y -= 32; ptls[3].y -= 32;
476 GpiWCBitBlt(hps, piOver.hbmPointer, 4, ptls, ROP_SRCINVERT, BBO_IGNORE);
477 // create the new pointer
478 GpiSetBitmap(hps, 0);
479 hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE,
480 piOver.xHotspot, piOver.yHotspot);
481 qt_free_ps_with_bitmap(hps, hbm);
482 }
483
484 Q_ASSERT(hptr);
485 return hptr;
486}
487
488void QCursorData::update()
489{
490 if (!QCursorData::initialized)
491 QCursorData::initialize();
492
493 if (cshape == Qt::BitmapCursor) {
494 QPixmap pm = pixmap;
495 if (pm.isNull()) {
496 Q_ASSERT(bm && bmm);
497 pm = *bm;
498 pm.setMask(*bmm);
499 }
500 hptr = QPixmap::toPmHPOINTER(QIcon(pm), true, hx, hy);
501 Q_ASSERT(hptr);
502 isSysPtr = false;
503 return;
504 }
505
506 LONG id = 0;
507 char const * const * xpm = 0;
508 int xpm_hx = 0;
509 int xpm_hy = 0;
510
511 switch (cshape) { // map to OS/2 cursor
512 case Qt::ArrowCursor:
513 id = SPTR_ARROW;
514 break;
515 case Qt::UpArrowCursor:
516 xpm = cursor_uparrow_xpm;
517 xpm_hx = cursor_uparrow_x;
518 xpm_hy = cursor_uparrow_y;
519 break;
520 case Qt::CrossCursor:
521 xpm = cursor_cross_xpm;
522 xpm_hx = cursor_cross_x;
523 xpm_hy = cursor_cross_y;
524 break;
525 case Qt::WaitCursor:
526 id = SPTR_WAIT;
527 break;
528 case Qt::IBeamCursor:
529 id = SPTR_TEXT;
530 break;
531 case Qt::SizeVerCursor:
532 id = SPTR_SIZENS;
533 break;
534 case Qt::SizeHorCursor:
535 id = SPTR_SIZEWE;
536 break;
537 case Qt::SizeBDiagCursor:
538 id = SPTR_SIZENESW;
539 break;
540 case Qt::SizeFDiagCursor:
541 id = SPTR_SIZENWSE;
542 break;
543 case Qt::SizeAllCursor:
544 id = SPTR_MOVE;
545 break;
546 case Qt::BlankCursor:
547 xpm = cursor_blank_xpm;
548 xpm_hx = cursor_blank_x;
549 xpm_hy = cursor_blank_y;
550 break;
551 case Qt::SplitVCursor:
552 xpm = cursor_vsplit_xpm;
553 xpm_hx = cursor_vsplit_x;
554 xpm_hy = cursor_vsplit_y;
555 break;
556 case Qt::SplitHCursor:
557 xpm = cursor_hsplit_xpm;
558 xpm_hx = cursor_hsplit_x;
559 xpm_hy = cursor_hsplit_y;
560 break;
561 case Qt::PointingHandCursor:
562 xpm = cursor_hand_xpm;
563 xpm_hx = cursor_hand_x;
564 xpm_hy = cursor_hand_y;
565 break;
566 case Qt::ForbiddenCursor:
567 id = SPTR_ILLEGAL;
568 break;
569 case Qt::WhatsThisCursor:
570 xpm = cursor_whatsthis_xpm;
571 xpm_hx = cursor_whatsthis_x;
572 xpm_hy = cursor_whatsthis_y;
573 break;
574 case Qt::BusyCursor:
575 // we create a busy cursor below as a combination of the standard
576 // arrow and wait cursors
577 hptr = combineTwoCursors(SPTR_ARROW, SPTR_WAIT);
578 isSysPtr = false;
579 return;
580 case Qt::OpenHandCursor:
581 xpm = cursor_openhand_xpm;
582 xpm_hx = cursor_openhand_x;
583 xpm_hy = cursor_openhand_y;
584 break;
585 case Qt::ClosedHandCursor:
586 xpm = cursor_closedhand_xpm;
587 xpm_hx = cursor_closedhand_x;
588 xpm_hy = cursor_closedhand_y;
589 break;
590 default:
591 qWarning("QCursor::update: Invalid cursor shape %d", cshape);
592 return;
593 }
594
595 if (!id) {
596#ifndef QT_NO_IMAGEFORMAT_XPM
597 QPixmap pm(xpm);
598 hptr = QPixmap::toPmHPOINTER(QIcon(pm), true, xpm_hx, xpm_hy);
599 Q_ASSERT(hptr);
600 isSysPtr = false;
601 return;
602#else
603 id = SPTR_ARROW;
604#endif
605 }
606
607 Q_ASSERT(id);
608
609 hptr = WinQuerySysPointer(HWND_DESKTOP, id, FALSE);
610 Q_ASSERT(hptr);
611 isSysPtr = true;
612}
613
614#endif // QT_NO_CURSOR
615
616QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.