]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/cursor.cpp
merged MapBitmap() from 2.2 branch
[wxWidgets.git] / src / motif / cursor.cpp
index 4ecd0ad6d557fa7ecbe8757fa76ea4f381427d29..24ce2516a07ba91ac5d28449f00b28a113dde5a5 100644 (file)
 #endif
 
 #include "wx/cursor.h"
+#include "wx/gdicmn.h"
 #include "wx/icon.h"
+#include "wx/app.h"
+#include "wx/utils.h"
 
-#if !USE_SHARED_LIBRARIES
-IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap)
+#ifdef __VMS__
+#pragma message disable nosimpint
+#endif
+#include <Xm/Xm.h>
+#include <X11/cursorfont.h>
+#ifdef __VMS__
+#pragma message enable nosimpint
 #endif
 
+#include "wx/motif/private.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap)
+IMPLEMENT_DYNAMIC_CLASS(wxXCursor, wxObject)
+
 wxCursorRefData::wxCursorRefData()
 {
     m_width = 32; m_height = 32;
-
-/* TODO
-    m_hCursor = 0 ;
-*/
+    m_cursorId = wxCURSOR_NONE;
 }
 
 wxCursorRefData::~wxCursorRefData()
 {
-    // TODO: destroy cursor
+    wxNode* node = m_cursors.First();
+    while (node)
+    {
+        wxXCursor* c = (wxXCursor*) node->Data();
+        // TODO: how to delete cursor?
+        // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ??
+        delete c;
+        node = node->Next();
+    }
 }
 
-// Cursors
 wxCursor::wxCursor()
 {
 }
 
-wxCursor::wxCursor(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSED(height),
-    int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY), const char WXUNUSED(maskBits)[])
+wxCursor::wxCursor(const char bits[], int width, int height,
+    int hotSpotX, int hotSpotY, const char maskBits[])
 {
-}
+    m_refData = new wxCursorRefData;
 
-wxCursor::wxCursor(const wxString& cursor_file, long flags, int hotSpotX, int hotSpotY)
-{
-    m_refData = new wxIconRefData;
+    Display *dpy = (Display*) wxGetDisplay();
+    int screen_num =  DefaultScreen (dpy);
 
-    // TODO: create cursor from a file
-}
+    Pixmap pixmap = XCreatePixmapFromBitmapData (dpy,
+                                          RootWindow (dpy, DefaultScreen(dpy)),
+                                          (char*) bits, width, height,
+                                          1 , 0 , 1);
 
-// Cursors by stock number
-wxCursor::wxCursor(int cursor_type)
-{
-  m_refData = new wxIconRefData;
-
-/* TODO
-  switch (cursor_type)
-  {
-    case wxCURSOR_WAIT:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_WAIT);
-      break;
-    case wxCURSOR_IBEAM:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_IBEAM);
-      break;
-    case wxCURSOR_CROSS:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_CROSS);
-      break;
-    case wxCURSOR_SIZENWSE:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZENWSE);
-      break;
-    case wxCURSOR_SIZENESW:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZENESW);
-      break;
-    case wxCURSOR_SIZEWE:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZEWE);
-      break;
-    case wxCURSOR_SIZENS:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZENS);
-      break;
-    case wxCURSOR_CHAR:
+    Pixmap mask_pixmap = None;
+    if (maskBits != NULL)
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW);
-      break;
+        mask_pixmap = XCreatePixmapFromBitmapData (dpy,
+                                          RootWindow (dpy, DefaultScreen(dpy)),
+                                          (char*) maskBits, width, height,
+                                          1 , 0 , 1);
     }
-    case wxCURSOR_HAND:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_HAND");
-      break;
-    }
-    case wxCURSOR_BULLSEYE:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_BULLSEYE");
-      break;
-    }
-    case wxCURSOR_PENCIL:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PENCIL");
-      break;
-    }
-    case wxCURSOR_MAGNIFIER:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_MAGNIFIER");
-      break;
-    }
-    case wxCURSOR_NO_ENTRY:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_NO_ENTRY");
-      break;
-    }
-    case wxCURSOR_LEFT_BUTTON:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW);
-      break;
-    }
-    case wxCURSOR_RIGHT_BUTTON:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW);
-      break;
-    }
-    case wxCURSOR_MIDDLE_BUTTON:
-    {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW);
-      break;
-    }
-    case wxCURSOR_SIZING:
+
+    XColor foreground_color;
+    XColor background_color;
+    foreground_color.pixel = BlackPixel(dpy, screen_num);
+    background_color.pixel = WhitePixel(dpy, screen_num);
+    Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
+    XQueryColor(dpy, cmap, &foreground_color);
+    XQueryColor(dpy, cmap, &background_color);
+
+    Cursor cursor = XCreatePixmapCursor (dpy,
+                                  pixmap,
+                                  mask_pixmap,
+                                  &foreground_color,
+                                  &background_color,
+                                  hotSpotX , 
+                                  hotSpotY);
+
+    XFreePixmap( dpy, pixmap );
+    if (mask_pixmap != None)
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_SIZING");
-      break;
+        XFreePixmap( dpy, mask_pixmap );
     }
-    case wxCURSOR_WATCH:
+
+    if (cursor)
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_WATCH");
-      break;
+        wxXCursor *c = new wxXCursor;
+
+        c->m_cursor = (WXCursor) cursor;
+        c->m_display = (WXDisplay*) dpy;
+        M_CURSORDATA->m_cursors.Append(c);
+        M_CURSORDATA->m_ok = TRUE;
     }
-    case wxCURSOR_SPRAYCAN:
+    else
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_ROLLER");
-      break;
+        M_CURSORDATA->m_ok = TRUE;
     }
-    case wxCURSOR_PAINT_BRUSH:
+}
+
+wxCursor::wxCursor(const wxString& name, long flags, int hotSpotX, int hotSpotY)
+{
+    // Must be an XBM file
+    if (flags != wxBITMAP_TYPE_XBM)
+        return;
+
+    m_refData = new wxCursorRefData;
+
+    int hotX = -1, hotY = -1;
+    unsigned int w, h;
+    Pixmap pixmap;
+
+    Display *dpy = (Display*) wxGetDisplay();
+    int screen_num =  DefaultScreen (dpy);
+
+    int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
+                        (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
+
+    M_BITMAPDATA->m_width = w;
+    M_BITMAPDATA->m_height = h;
+    M_BITMAPDATA->m_depth = 1;
+
+    if ((value == BitmapFileInvalid) ||
+        (value == BitmapOpenFailed) ||
+        (value == BitmapNoMemory))
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PBRUSH");
-      break;
     }
-    case wxCURSOR_POINT_LEFT:
+    else
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PLEFT");
-      break;
+        XColor foreground_color;
+        XColor background_color;
+        foreground_color.pixel = BlackPixel(dpy, screen_num);
+        background_color.pixel = WhitePixel(dpy, screen_num);
+        Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy);
+        XQueryColor(dpy, cmap, &foreground_color);
+        XQueryColor(dpy, cmap, &background_color);
+
+        // TODO: how do we determine whether hotX, hotY were read correctly?
+        if (hotX < 0 || hotY < 0)
+        {
+            hotX = hotSpotX;
+            hotY = hotSpotY;
+        }
+        if (hotX < 0 || hotY < 0)
+        {
+            hotX = 0;
+            hotY = 0;
+        }
+
+        Pixmap mask_pixmap = None;
+        Cursor cursor = XCreatePixmapCursor (dpy,
+                                      pixmap,
+                                      mask_pixmap,
+                                      &foreground_color,
+                                      &background_color,
+                                      hotX,
+                                      hotY);
+
+        XFreePixmap( dpy, pixmap );
+        if (cursor)
+        {
+            wxXCursor *c = new wxXCursor;
+
+            c->m_cursor = (WXCursor) cursor;
+            c->m_display = (WXDisplay*) dpy;
+            M_CURSORDATA->m_cursors.Append(c);
+            M_CURSORDATA->m_ok = TRUE;
+        }
     }
-    case wxCURSOR_POINT_RIGHT:
+
+}
+
+// Cursors by stock number
+wxCursor::wxCursor(wxStockCursor id)
+{
+    m_refData = new wxCursorRefData;
+    M_CURSORDATA->m_cursorId = id;
+    M_CURSORDATA->m_ok = TRUE;
+
+    WXDisplay* display = wxGetDisplay();
+    if (!display)
+      return;
+
+    WXCursor cursor = GetXCursor(display);
+    if (cursor)
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PRIGHT");
-      break;
+        wxXCursor* c = new wxXCursor;
+        c->m_cursor = cursor;
+        c->m_display = wxGetDisplay();
+        M_CURSORDATA->m_cursors.Append(c);
+        M_CURSORDATA->m_ok = TRUE;
     }
-    case wxCURSOR_QUESTION_ARROW:
+}
+
+wxCursor::~wxCursor()
+{
+}
+
+// Motif-specific: create/get a cursor for the current display
+WXCursor wxCursor::GetXCursor(WXDisplay* display)
+{
+    if (!M_CURSORDATA)
+        return (WXCursor) 0;
+    wxNode* node = M_CURSORDATA->m_cursors.First();
+    while (node)
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_QARROW");
-      break;
+        wxXCursor* c = (wxXCursor*) node->Data();
+        if (c->m_display == display)
+            return c->m_cursor;
+        node = node->Next();
     }
-    case wxCURSOR_BLANK:
+
+    // No cursor for this display, so let's see if we're an id-type cursor.
+
+    if (M_CURSORDATA->m_cursorId != wxCURSOR_NONE)
     {
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_BLANK");
-      break;
+        WXCursor cursor = MakeCursor(display, M_CURSORDATA->m_cursorId);
+        if (cursor)
+        {
+            wxXCursor* c = new wxXCursor;
+            c->m_cursor = cursor;
+            c->m_display = display;
+            M_CURSORDATA->m_cursors.Append(c);
+            return cursor;
+        }
+        else
+            return (WXCursor) 0;
     }
-    default:
-    case wxCURSOR_ARROW:
-      M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW);
-      break;
-  }
-*/
 
+    // Not an id-type cursor, so we don't know how to create it.
+    return (WXCursor) 0;
 }
 
-wxCursor::~wxCursor()
+// Make a cursor from standard id
+WXCursor wxCursor::MakeCursor(WXDisplay* display, wxStockCursor id)
 {
+    Display* dpy = (Display*) display;
+    Cursor cursor = (Cursor) 0;
+
+    switch (id)
+    {
+        case wxCURSOR_WAIT:
+        {
+            cursor = XCreateFontCursor (dpy, XC_watch);
+            break;
+        }
+        case wxCURSOR_CROSS:
+        {
+            cursor = XCreateFontCursor (dpy, XC_crosshair);
+            break;
+        }
+        case wxCURSOR_CHAR:
+        {
+            // Nothing
+            break;
+        }
+        case wxCURSOR_HAND:
+        {
+            cursor = XCreateFontCursor (dpy, XC_hand1);
+            break;
+        }
+        case wxCURSOR_BULLSEYE:
+        {
+            cursor = XCreateFontCursor (dpy, XC_target);
+            break;
+        }
+        case wxCURSOR_PENCIL:
+       {
+            cursor = XCreateFontCursor (dpy, XC_pencil);
+            break;
+        }
+        case wxCURSOR_MAGNIFIER:
+        {
+            cursor = XCreateFontCursor (dpy, XC_sizing);
+            break;
+        }
+        case wxCURSOR_IBEAM:
+        {
+            cursor = XCreateFontCursor (dpy, XC_xterm);
+            break;
+        }
+        case wxCURSOR_NO_ENTRY:
+        {
+            cursor = XCreateFontCursor (dpy, XC_pirate);
+            break;
+        }
+        case wxCURSOR_LEFT_BUTTON:
+        {
+            cursor = XCreateFontCursor (dpy, XC_leftbutton);
+            break;
+        }
+        case wxCURSOR_RIGHT_BUTTON:
+        {
+            cursor = XCreateFontCursor (dpy, XC_rightbutton);
+            break;
+        }
+        case wxCURSOR_MIDDLE_BUTTON:
+        {
+            cursor = XCreateFontCursor (dpy, XC_middlebutton);
+            break;
+        }
+        case wxCURSOR_QUESTION_ARROW:
+        {
+            cursor = XCreateFontCursor (dpy, XC_question_arrow);
+            break;
+        }
+        case wxCURSOR_SIZING:
+        {
+            cursor = XCreateFontCursor (dpy, XC_sizing);
+            break;
+        }
+        case wxCURSOR_WATCH:
+        {
+            cursor = XCreateFontCursor (dpy, XC_watch);
+            break;
+        }
+        case wxCURSOR_SPRAYCAN:
+        {
+            cursor = XCreateFontCursor (dpy, XC_spraycan);
+            break;
+        }
+        case wxCURSOR_PAINT_BRUSH:
+        {
+            cursor = XCreateFontCursor (dpy, XC_spraycan);
+            break;
+        }
+        case wxCURSOR_SIZENWSE:
+        case wxCURSOR_SIZENESW:
+        {
+            // Not available in X
+            cursor = XCreateFontCursor (dpy, XC_crosshair);
+            break;
+        }
+        case wxCURSOR_SIZEWE:
+        {
+            cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
+            break;
+        }
+        case wxCURSOR_SIZENS:
+        {
+            cursor = XCreateFontCursor (dpy, XC_sb_v_double_arrow);
+            break;
+        }
+        case wxCURSOR_POINT_LEFT:
+        {
+            cursor = XCreateFontCursor (dpy, XC_sb_left_arrow);
+            break;
+        }
+        case wxCURSOR_POINT_RIGHT:
+        {
+            cursor = XCreateFontCursor (dpy, XC_sb_right_arrow);
+            break;
+        }
+        // (JD Huggins) added more stock cursors for X
+        // X-only cursors BEGIN
+        case wxCURSOR_CROSS_REVERSE:
+        {
+            cursor = XCreateFontCursor(dpy, XC_cross_reverse);
+            break;
+        }
+        case wxCURSOR_DOUBLE_ARROW:
+        {
+            cursor = XCreateFontCursor(dpy, XC_double_arrow);
+            break;
+        }
+        case wxCURSOR_BASED_ARROW_UP:
+        {
+            cursor = XCreateFontCursor(dpy, XC_based_arrow_up);
+            break;
+        }
+        case wxCURSOR_BASED_ARROW_DOWN:
+        {
+            cursor = XCreateFontCursor(dpy, XC_based_arrow_down);
+            break;
+        }
+        default:
+        case wxCURSOR_ARROW:
+        {
+            cursor = XCreateFontCursor (dpy, XC_top_left_arrow);
+            break;
+        }
+        case wxCURSOR_BLANK:
+        {
+            GC gc;
+            XGCValues gcv;
+            Pixmap empty_pixmap;
+            XColor blank_color;
+
+            empty_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
+                              16, 16, 1);
+            gcv.function = GXxor;
+            gc = XCreateGC (dpy,
+                    empty_pixmap,
+                    GCFunction,
+                    &gcv);
+            XCopyArea (dpy,
+                   empty_pixmap,
+                   empty_pixmap,
+                   gc,
+                   0, 0,
+                   16, 16,
+                   0, 0);
+            XFreeGC (dpy, gc);
+            cursor = XCreatePixmapCursor (dpy,
+                            empty_pixmap,
+                            empty_pixmap,
+                            &blank_color,
+                            &blank_color,
+                            8, 8);
+
+            break;
+        }
+    }
+    return (WXCursor) cursor;
 }
 
 // Global cursor setting
-void wxSetCursor(const wxCursor& cursor)
+void wxSetCursor(const wxCursor& WXUNUSED(cursor))
 {
-  // TODO (optional on platforms with no global cursor)
+  // Nothing to do for Motif (no global cursor)
 }