fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

fl_cursor.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: fl_cursor.cxx 8055 2010-12-18 22:31:01Z manolo $"
00003 //
00004 // Mouse cursor support for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 // Change the current cursor.
00029 // Under X the cursor is attached to the X window.  I tried to hide
00030 // this and pretend that changing the cursor is a drawing function.
00031 // This avoids a field in the Fl_Window, and I suspect is more
00032 // portable to other systems.
00033 
00034 #include <FL/Fl.H>
00035 #include <FL/Fl_Window.H>
00036 #include <FL/x.H>
00037 #if !defined(WIN32) && !defined(__APPLE__)
00038 #  include <X11/cursorfont.h>
00039 #endif
00040 #include <FL/fl_draw.H>
00041 
00046 void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
00047   if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg);
00048 }
00054 void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
00055 //  if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW;
00056 
00057   cursor_default = c;
00058   cursor_fg      = fg;
00059   cursor_bg      = bg;
00060 
00061   cursor(c, fg, bg);
00062 }
00063 
00064 #ifdef WIN32
00065 
00066 #  ifndef IDC_HAND
00067 #    define IDC_HAND    MAKEINTRESOURCE(32649)
00068 #  endif // !IDC_HAND
00069 
00070 void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) {
00071   if (!shown()) return;
00072   // the cursor must be set for the top level window, not for subwindows
00073   Fl_Window *w = window(), *toplevel = this;
00074   while (w) { toplevel = w; w = w->window(); }
00075   if (toplevel != this) { toplevel->cursor(c, c1, c2); return; }
00076   // now set the actual cursor
00077   if (c == FL_CURSOR_DEFAULT) {
00078     c = cursor_default;
00079   }
00080   if (c > FL_CURSOR_NESW) {
00081     i->cursor = 0;
00082   } else if (c == FL_CURSOR_DEFAULT) {
00083     i->cursor = fl_default_cursor;
00084   } else {
00085     LPSTR n;
00086     switch (c) {
00087     case FL_CURSOR_ARROW:       n = IDC_ARROW; break;
00088     case FL_CURSOR_CROSS:       n = IDC_CROSS; break;
00089     case FL_CURSOR_WAIT:        n = IDC_WAIT; break;
00090     case FL_CURSOR_INSERT:      n = IDC_IBEAM; break;
00091     case FL_CURSOR_HELP:        n = IDC_HELP; break;
00092     case FL_CURSOR_HAND: {
00093           OSVERSIONINFO osvi;
00094 
00095           // Get the OS version: Windows 98 and 2000 have a standard
00096           // hand cursor.
00097           memset(&osvi, 0, sizeof(OSVERSIONINFO));
00098           osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00099           GetVersionEx(&osvi);
00100 
00101           if (osvi.dwMajorVersion > 4 ||
00102               (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0 &&
00103                osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)) n = IDC_HAND;
00104           else n = IDC_UPARROW;
00105         } break;
00106     case FL_CURSOR_MOVE:        n = IDC_SIZEALL; break;
00107     case FL_CURSOR_N:
00108     case FL_CURSOR_S:
00109     case FL_CURSOR_NS:          n = IDC_SIZENS; break;
00110     case FL_CURSOR_NE:
00111     case FL_CURSOR_SW:
00112     case FL_CURSOR_NESW:        n = IDC_SIZENESW; break;
00113     case FL_CURSOR_E:
00114     case FL_CURSOR_W:
00115     case FL_CURSOR_WE:          n = IDC_SIZEWE; break;
00116     case FL_CURSOR_SE:
00117     case FL_CURSOR_NW:
00118     case FL_CURSOR_NWSE:        n = IDC_SIZENWSE; break;
00119     default:                    n = IDC_NO; break;
00120     }
00121     i->cursor = LoadCursor(NULL, n);
00122   }
00123   SetCursor(i->cursor);
00124 }
00125 
00126 #elif defined(__APPLE__)
00127 
00128 #ifdef __BIG_ENDIAN__
00129 # define E(x) x
00130 #elif defined __LITTLE_ENDIAN__
00131 // Don't worry. This will be resolved at compile time
00132 # define E(x) (x>>8)|((x<<8)&0xff00)
00133 #else
00134 # error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined"
00135 #endif
00136 
00137 extern Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h);
00138 
00139 
00140 CGContextRef Fl_X::help_cursor_image(void)
00141 {
00142   int w = 20, h = 20;
00143   Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
00144   fl_begin_offscreen(off);
00145   CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
00146   fl_rectf(0,0,w,h);
00147   fl_color(FL_BLACK);
00148   fl_font(FL_COURIER_BOLD, 20);
00149   fl_draw("?", 1, h-1);
00150   fl_end_offscreen();
00151   return (CGContextRef)off;
00152 }
00153 
00154 CGContextRef Fl_X::none_cursor_image(void)
00155 {
00156   int w = 20, h = 20;
00157   Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
00158   fl_begin_offscreen(off);
00159   CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
00160   fl_rectf(0,0,w,h);
00161   fl_end_offscreen();
00162   return (CGContextRef)off;
00163 }
00164 
00165 CGContextRef Fl_X::watch_cursor_image(void)
00166 {
00167   int w, h, r = 5;
00168   w = 2*r+6;
00169   h = 4*r;
00170   Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
00171   fl_begin_offscreen(off);
00172   CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
00173   fl_rectf(0,0,w,h);
00174   CGContextTranslateCTM( (CGContextRef)off, w/2, h/2);
00175   fl_color(FL_WHITE);
00176   fl_circle(0, 0, r+1);
00177   fl_color(FL_BLACK);
00178   fl_rectf(int(-r*0.7), int(-r*1.7), int(1.4*r), int(3.4*r));
00179   fl_rectf(r-1, -1, 3, 3);
00180   fl_color(FL_WHITE);
00181   fl_pie(-r, -r, 2*r, 2*r, 0, 360);
00182   fl_color(FL_BLACK);
00183   fl_circle(0,0,r);
00184   fl_xyline(0, 0, int(-r*.7));
00185   fl_xyline(0, 0, 0, int(-r*.7));
00186   fl_end_offscreen();
00187   return (CGContextRef)off;
00188 }
00189 
00190 CGContextRef Fl_X::nesw_cursor_image(void)
00191 {
00192   int c = 7, r = 2*c;
00193   int w = r, h = r;
00194   Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
00195   fl_begin_offscreen(off);
00196   CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
00197   fl_rectf(0,0,w,h);
00198   CGContextTranslateCTM( (CGContextRef)off, 0, h);
00199   CGContextScaleCTM( (CGContextRef)off, 1, -1);
00200   fl_color(FL_BLACK);
00201   fl_polygon(0, 0, c, 0, 0, c);
00202   fl_polygon(r, r, r, r-c, r-c, r);
00203   fl_line_style(FL_SOLID, 2, 0);
00204   fl_line(0,1, r,r+1);
00205   fl_line_style(FL_SOLID, 0, 0);
00206   fl_end_offscreen();
00207   return (CGContextRef)off;
00208 }
00209 
00210 CGContextRef Fl_X::nwse_cursor_image(void)
00211 {
00212   int c = 7, r = 2*c;
00213   int w = r, h = r;
00214   Fl_Offscreen off = fl_create_offscreen_with_alpha(w, h);
00215   fl_begin_offscreen(off);
00216   CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
00217   fl_rectf(0,0,w,h);
00218   CGContextTranslateCTM( (CGContextRef)off, 0, h);
00219   CGContextScaleCTM( (CGContextRef)off, 1, -1);
00220   fl_color(FL_BLACK);
00221   fl_polygon(r-1, 0, r-1, c, r-1-c, 0);
00222   fl_polygon(-1, r, c-1, r, -1, r-c);
00223   fl_line_style(FL_SOLID, 2, 0);
00224   fl_line(r-1,1, -1,r+1);
00225   fl_line_style(FL_SOLID, 0, 0);
00226   fl_end_offscreen();
00227   return (CGContextRef)off;
00228 }
00229 
00230 void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
00231   if (c == FL_CURSOR_DEFAULT) {
00232     c = cursor_default;
00233   }
00234   if (i) i->set_cursor(c);
00235 }
00236 
00237 #else
00238 
00239 // I like the MSWindows resize cursors, so I duplicate them here:
00240 
00241 #define CURSORSIZE 16
00242 #define HOTXY 7
00243 static struct TableEntry {
00244   uchar bits[CURSORSIZE*CURSORSIZE/8];
00245   uchar mask[CURSORSIZE*CURSORSIZE/8];
00246   Cursor cursor;
00247 } table[] = {
00248   {{    // FL_CURSOR_NS
00249    0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
00250    0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
00251    0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
00252    {
00253    0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
00254    0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
00255    0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
00256   {{    // FL_CURSOR_EW
00257    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
00258    0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
00259    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
00260    {
00261    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
00262    0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
00263    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
00264   {{    // FL_CURSOR_NWSE
00265    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
00266    0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
00267    0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
00268    {
00269    0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
00270    0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
00271    0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
00272   {{    // FL_CURSOR_NESW
00273    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
00274    0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
00275    0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
00276    {
00277    0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
00278    0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
00279    0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
00280   {{0}, {0}} // FL_CURSOR_NONE & unknown
00281 };
00282 
00283 void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
00284   if (!shown()) return;
00285   Cursor xc;
00286   int deleteit = 0;
00287   if (c == FL_CURSOR_DEFAULT) {
00288     c  = cursor_default;
00289     fg = cursor_fg;
00290     bg = cursor_bg;
00291   }
00292 
00293   if (!c) {
00294     xc = None;
00295   } else {
00296     if (c >= FL_CURSOR_NS) {
00297       TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
00298       if (!(q->cursor)) {
00299         XColor dummy = { 0 };
00300         Pixmap p = XCreateBitmapFromData(fl_display,
00301           RootWindow(fl_display, fl_screen), (const char*)(q->bits),
00302           CURSORSIZE, CURSORSIZE);
00303         Pixmap m = XCreateBitmapFromData(fl_display,
00304           RootWindow(fl_display, fl_screen), (const char*)(q->mask),
00305           CURSORSIZE, CURSORSIZE);
00306         q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy,
00307                                         HOTXY, HOTXY);
00308         XFreePixmap(fl_display, m);
00309         XFreePixmap(fl_display, p);
00310       }
00311       xc = q->cursor;
00312     } else {
00313       xc = XCreateFontCursor(fl_display, (c-1)*2);
00314       deleteit = 1;
00315     }
00316     XColor fgc;
00317     uchar r,g,b;
00318     Fl::get_color(fg,r,g,b);
00319     fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8;
00320     XColor bgc;
00321     Fl::get_color(bg,r,g,b);
00322     bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8;
00323     XRecolorCursor(fl_display, xc, &fgc, &bgc);
00324   }
00325   XDefineCursor(fl_display, fl_xid(this), xc);
00326   if (deleteit) XFreeCursor(fl_display, xc);
00327 }
00328 
00329 #endif
00330 
00331 //
00332 // End of "$Id: fl_cursor.cxx 8055 2010-12-18 22:31:01Z manolo $".
00333 //