Tweak themes for more color consistency.
[ntk.git] / src / fl_cursor.cxx
blob66492551f9ceb35b193de9706137155ff3e4022f
1 //
2 // "$Id: fl_cursor.cxx 8055 2010-12-18 22:31:01Z manolo $"
3 //
4 // Mouse cursor support for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
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
21 // USA.
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.
34 #include <FL/Fl.H>
35 #include <FL/Fl_Window.H>
36 #include <FL/x.H>
37 #if !defined(WIN32) && !defined(__APPLE__)
38 # include <X11/cursorfont.h>
39 #endif
40 #include <FL/fl_draw.H>
42 /**
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);
49 /**
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;
57 cursor_default = c;
58 cursor_fg = fg;
59 cursor_bg = bg;
61 cursor(c, fg, bg);
64 #ifdef WIN32
66 # ifndef IDC_HAND
67 # define IDC_HAND MAKEINTRESOURCE(32649)
68 # endif // !IDC_HAND
70 void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) {
71 if (!shown()) return;
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) {
78 c = cursor_default;
80 if (c > FL_CURSOR_NESW) {
81 i->cursor = 0;
82 } else if (c == FL_CURSOR_DEFAULT) {
83 i->cursor = fl_default_cursor;
84 } else {
85 LPSTR n;
86 switch (c) {
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: {
93 OSVERSIONINFO osvi;
95 // Get the OS version: Windows 98 and 2000 have a standard
96 // hand cursor.
97 memset(&osvi, 0, sizeof(OSVERSIONINFO));
98 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
99 GetVersionEx(&osvi);
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;
105 } break;
106 case FL_CURSOR_MOVE: n = IDC_SIZEALL; break;
107 case FL_CURSOR_N:
108 case FL_CURSOR_S:
109 case FL_CURSOR_NS: n = IDC_SIZENS; break;
110 case FL_CURSOR_NE:
111 case FL_CURSOR_SW:
112 case FL_CURSOR_NESW: n = IDC_SIZENESW; break;
113 case FL_CURSOR_E:
114 case FL_CURSOR_W:
115 case FL_CURSOR_WE: n = IDC_SIZEWE; break;
116 case FL_CURSOR_SE:
117 case FL_CURSOR_NW:
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__
129 # define E(x) x
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)
133 #else
134 # error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined"
135 #endif
137 extern Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h);
140 CGContextRef Fl_X::help_cursor_image(void)
142 int w = 20, h = 20;
143 Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
144 fl_begin_offscreen(off);
145 CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
146 fl_rectf(0,0,w,h);
147 fl_color(FL_BLACK);
148 fl_font(FL_COURIER_BOLD, 20);
149 fl_draw("?", 1, h-1);
150 fl_end_offscreen();
151 return (CGContextRef)off;
154 CGContextRef Fl_X::none_cursor_image(void)
156 int w = 20, h = 20;
157 Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
158 fl_begin_offscreen(off);
159 CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
160 fl_rectf(0,0,w,h);
161 fl_end_offscreen();
162 return (CGContextRef)off;
165 CGContextRef Fl_X::watch_cursor_image(void)
167 int w, h, r = 5;
168 w = 2*r+6;
169 h = 4*r;
170 Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
171 fl_begin_offscreen(off);
172 CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
173 fl_rectf(0,0,w,h);
174 CGContextTranslateCTM( (CGContextRef)off, w/2, h/2);
175 fl_color(FL_WHITE);
176 fl_circle(0, 0, r+1);
177 fl_color(FL_BLACK);
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);
180 fl_color(FL_WHITE);
181 fl_pie(-r, -r, 2*r, 2*r, 0, 360);
182 fl_color(FL_BLACK);
183 fl_circle(0,0,r);
184 fl_xyline(0, 0, int(-r*.7));
185 fl_xyline(0, 0, 0, int(-r*.7));
186 fl_end_offscreen();
187 return (CGContextRef)off;
190 CGContextRef Fl_X::nesw_cursor_image(void)
192 int c = 7, r = 2*c;
193 int w = r, h = r;
194 Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
195 fl_begin_offscreen(off);
196 CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
197 fl_rectf(0,0,w,h);
198 CGContextTranslateCTM( (CGContextRef)off, 0, h);
199 CGContextScaleCTM( (CGContextRef)off, 1, -1);
200 fl_color(FL_BLACK);
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);
204 fl_line(0,1, r,r+1);
205 fl_line_style(FL_SOLID, 0, 0);
206 fl_end_offscreen();
207 return (CGContextRef)off;
210 CGContextRef Fl_X::nwse_cursor_image(void)
212 int c = 7, r = 2*c;
213 int w = r, h = r;
214 Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
215 fl_begin_offscreen(off);
216 CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
217 fl_rectf(0,0,w,h);
218 CGContextTranslateCTM( (CGContextRef)off, 0, h);
219 CGContextScaleCTM( (CGContextRef)off, 1, -1);
220 fl_color(FL_BLACK);
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);
226 fl_end_offscreen();
227 return (CGContextRef)off;
230 void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
231 if (c == FL_CURSOR_DEFAULT) {
232 c = cursor_default;
234 if (i) i->set_cursor(c);
237 #else
239 // I like the MSWindows resize cursors, so I duplicate them here:
241 #define CURSORSIZE 16
242 #define HOTXY 7
243 static struct TableEntry {
244 uchar bits[CURSORSIZE*CURSORSIZE/8];
245 uchar mask[CURSORSIZE*CURSORSIZE/8];
246 Cursor cursor;
247 } table[] = {
248 {{ // FL_CURSOR_NS
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}},
256 {{ // FL_CURSOR_EW
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}},
264 {{ // FL_CURSOR_NWSE
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}},
272 {{ // FL_CURSOR_NESW
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;
285 Cursor xc;
286 int deleteit = 0;
287 if (c == FL_CURSOR_DEFAULT) {
288 c = cursor_default;
289 fg = cursor_fg;
290 bg = cursor_bg;
293 if (!c) {
294 xc = None;
295 } else {
296 if (c >= FL_CURSOR_NS) {
297 TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
298 if (!(q->cursor)) {
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,
307 HOTXY, HOTXY);
308 XFreePixmap(fl_display, m);
309 XFreePixmap(fl_display, p);
311 xc = q->cursor;
312 } else {
313 xc = XCreateFontCursor(fl_display, (c-1)*2);
314 deleteit = 1;
316 XColor fgc;
317 uchar r,g,b;
318 Fl::get_color(fg,r,g,b);
319 fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8;
320 XColor bgc;
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);
329 #endif
332 // End of "$Id: fl_cursor.cxx 8055 2010-12-18 22:31:01Z manolo $".