2 // "$Id: fl_cursor.cxx 8055 2010-12-18 22:31:01Z manolo $"
4 // Mouse cursor support for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // Change the current cursor.
29 // Under X the cursor is attached to the X window. I tried to hide
30 // this and pretend that changing the cursor is a drawing function.
31 // This avoids a field in the Fl_Window, and I suspect is more
32 // portable to other systems.
35 #include <FL/Fl_Window.H>
37 #if !defined(WIN32) && !defined(__APPLE__)
38 # include <X11/cursorfont.h>
40 #include <FL/fl_draw.H>
43 Sets the cursor for the current window to the specified shape and colors.
44 The cursors are defined in the <FL/Enumerations.H> header file.
46 void fl_cursor(Fl_Cursor c
, Fl_Color fg
, Fl_Color bg
) {
47 if (Fl::first_window()) Fl::first_window()->cursor(c
,fg
,bg
);
50 Sets the default window cursor as well as its color.
52 For back compatibility only.
54 void Fl_Window::default_cursor(Fl_Cursor c
, Fl_Color fg
, Fl_Color bg
) {
55 // if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW;
67 # define IDC_HAND MAKEINTRESOURCE(32649)
70 void Fl_Window::cursor(Fl_Cursor c
, Fl_Color c1
, Fl_Color c2
) {
72 // the cursor must be set for the top level window, not for subwindows
73 Fl_Window
*w
= window(), *toplevel
= this;
74 while (w
) { toplevel
= w
; w
= w
->window(); }
75 if (toplevel
!= this) { toplevel
->cursor(c
, c1
, c2
); return; }
76 // now set the actual cursor
77 if (c
== FL_CURSOR_DEFAULT
) {
80 if (c
> FL_CURSOR_NESW
) {
82 } else if (c
== FL_CURSOR_DEFAULT
) {
83 i
->cursor
= fl_default_cursor
;
87 case FL_CURSOR_ARROW
: n
= IDC_ARROW
; break;
88 case FL_CURSOR_CROSS
: n
= IDC_CROSS
; break;
89 case FL_CURSOR_WAIT
: n
= IDC_WAIT
; break;
90 case FL_CURSOR_INSERT
: n
= IDC_IBEAM
; break;
91 case FL_CURSOR_HELP
: n
= IDC_HELP
; break;
92 case FL_CURSOR_HAND
: {
95 // Get the OS version: Windows 98 and 2000 have a standard
97 memset(&osvi
, 0, sizeof(OSVERSIONINFO
));
98 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
101 if (osvi
.dwMajorVersion
> 4 ||
102 (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
> 0 &&
103 osvi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)) n
= IDC_HAND
;
104 else n
= IDC_UPARROW
;
106 case FL_CURSOR_MOVE
: n
= IDC_SIZEALL
; break;
109 case FL_CURSOR_NS
: n
= IDC_SIZENS
; break;
112 case FL_CURSOR_NESW
: n
= IDC_SIZENESW
; break;
115 case FL_CURSOR_WE
: n
= IDC_SIZEWE
; break;
118 case FL_CURSOR_NWSE
: n
= IDC_SIZENWSE
; break;
119 default: n
= IDC_NO
; break;
121 i
->cursor
= LoadCursor(NULL
, n
);
123 SetCursor(i
->cursor
);
126 #elif defined(__APPLE__)
128 #ifdef __BIG_ENDIAN__
130 #elif defined __LITTLE_ENDIAN__
131 // Don't worry. This will be resolved at compile time
132 # define E(x) (x>>8)|((x<<8)&0xff00)
134 # error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined"
137 extern Fl_Offscreen
fl_create_offscreen_with_alpha(int w
, int h
);
140 CGContextRef
Fl_X::help_cursor_image(void)
143 Fl_Offscreen off
= fl_create_offscreen_with_alpha(w
, h
);
144 fl_begin_offscreen(off
);
145 CGContextSetRGBFillColor( (CGContextRef
)off
, 0,0,0,0);
148 fl_font(FL_COURIER_BOLD
, 20);
149 fl_draw("?", 1, h
-1);
151 return (CGContextRef
)off
;
154 CGContextRef
Fl_X::none_cursor_image(void)
157 Fl_Offscreen off
= fl_create_offscreen_with_alpha(w
, h
);
158 fl_begin_offscreen(off
);
159 CGContextSetRGBFillColor( (CGContextRef
)off
, 0,0,0,0);
162 return (CGContextRef
)off
;
165 CGContextRef
Fl_X::watch_cursor_image(void)
170 Fl_Offscreen off
= fl_create_offscreen_with_alpha(w
, h
);
171 fl_begin_offscreen(off
);
172 CGContextSetRGBFillColor( (CGContextRef
)off
, 0,0,0,0);
174 CGContextTranslateCTM( (CGContextRef
)off
, w
/2, h
/2);
176 fl_circle(0, 0, r
+1);
178 fl_rectf(int(-r
*0.7), int(-r
*1.7), int(1.4*r
), int(3.4*r
));
179 fl_rectf(r
-1, -1, 3, 3);
181 fl_pie(-r
, -r
, 2*r
, 2*r
, 0, 360);
184 fl_xyline(0, 0, int(-r
*.7));
185 fl_xyline(0, 0, 0, int(-r
*.7));
187 return (CGContextRef
)off
;
190 CGContextRef
Fl_X::nesw_cursor_image(void)
194 Fl_Offscreen off
= fl_create_offscreen_with_alpha(w
, h
);
195 fl_begin_offscreen(off
);
196 CGContextSetRGBFillColor( (CGContextRef
)off
, 0,0,0,0);
198 CGContextTranslateCTM( (CGContextRef
)off
, 0, h
);
199 CGContextScaleCTM( (CGContextRef
)off
, 1, -1);
201 fl_polygon(0, 0, c
, 0, 0, c
);
202 fl_polygon(r
, r
, r
, r
-c
, r
-c
, r
);
203 fl_line_style(FL_SOLID
, 2, 0);
205 fl_line_style(FL_SOLID
, 0, 0);
207 return (CGContextRef
)off
;
210 CGContextRef
Fl_X::nwse_cursor_image(void)
214 Fl_Offscreen off
= fl_create_offscreen_with_alpha(w
, h
);
215 fl_begin_offscreen(off
);
216 CGContextSetRGBFillColor( (CGContextRef
)off
, 0,0,0,0);
218 CGContextTranslateCTM( (CGContextRef
)off
, 0, h
);
219 CGContextScaleCTM( (CGContextRef
)off
, 1, -1);
221 fl_polygon(r
-1, 0, r
-1, c
, r
-1-c
, 0);
222 fl_polygon(-1, r
, c
-1, r
, -1, r
-c
);
223 fl_line_style(FL_SOLID
, 2, 0);
224 fl_line(r
-1,1, -1,r
+1);
225 fl_line_style(FL_SOLID
, 0, 0);
227 return (CGContextRef
)off
;
230 void Fl_Window::cursor(Fl_Cursor c
, Fl_Color
, Fl_Color
) {
231 if (c
== FL_CURSOR_DEFAULT
) {
234 if (i
) i
->set_cursor(c
);
239 // I like the MSWindows resize cursors, so I duplicate them here:
241 #define CURSORSIZE 16
243 static struct TableEntry
{
244 uchar bits
[CURSORSIZE
*CURSORSIZE
/8];
245 uchar mask
[CURSORSIZE
*CURSORSIZE
/8];
249 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
250 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
251 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
253 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
254 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
255 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
258 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
262 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
266 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
267 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
269 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
270 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
271 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
274 0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
275 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
277 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
278 0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
279 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
280 {{0}, {0}} // FL_CURSOR_NONE & unknown
283 void Fl_Window::cursor(Fl_Cursor c
, Fl_Color fg
, Fl_Color bg
) {
284 if (!shown()) return;
287 if (c
== FL_CURSOR_DEFAULT
) {
296 if (c
>= FL_CURSOR_NS
) {
297 TableEntry
*q
= (c
> FL_CURSOR_NESW
) ? table
+4 : table
+(c
-FL_CURSOR_NS
);
299 XColor dummy
= { 0 };
300 Pixmap p
= XCreateBitmapFromData(fl_display
,
301 RootWindow(fl_display
, fl_screen
), (const char*)(q
->bits
),
302 CURSORSIZE
, CURSORSIZE
);
303 Pixmap m
= XCreateBitmapFromData(fl_display
,
304 RootWindow(fl_display
, fl_screen
), (const char*)(q
->mask
),
305 CURSORSIZE
, CURSORSIZE
);
306 q
->cursor
= XCreatePixmapCursor(fl_display
, p
,m
,&dummy
, &dummy
,
308 XFreePixmap(fl_display
, m
);
309 XFreePixmap(fl_display
, p
);
313 xc
= XCreateFontCursor(fl_display
, (c
-1)*2);
318 Fl::get_color(fg
,r
,g
,b
);
319 fgc
.red
= r
<<8; fgc
.green
= g
<<8; fgc
.blue
= b
<<8;
321 Fl::get_color(bg
,r
,g
,b
);
322 bgc
.red
= r
<<8; bgc
.green
= g
<<8; bgc
.blue
= b
<<8;
323 XRecolorCursor(fl_display
, xc
, &fgc
, &bgc
);
325 XDefineCursor(fl_display
, fl_xid(this), xc
);
326 if (deleteit
) XFreeCursor(fl_display
, xc
);
332 // End of "$Id: fl_cursor.cxx 8055 2010-12-18 22:31:01Z manolo $".