X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4bb6408c2631988fab9925014c6619358bf867de..fc9ef629ac8733c4f0b844356782cca80ae09c4b:/src/motif/cursor.cpp diff --git a/src/motif/cursor.cpp b/src/motif/cursor.cpp index 4ecd0ad6d5..c1027a775e 100644 --- a/src/motif/cursor.cpp +++ b/src/motif/cursor.cpp @@ -14,174 +14,423 @@ #endif #include "wx/cursor.h" +#include "wx/gdicmn.h" #include "wx/icon.h" +#include "wx/app.h" +#include "wx/utils.h" + +#include +#include + +#include "wx/motif/private.h" #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap) +IMPLEMENT_DYNAMIC_CLASS(wxXCursor, wxObject) #endif 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: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW); - break; - } - 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: + Pixmap mask_pixmap = None; + if (maskBits != NULL) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PENCIL"); - break; + mask_pixmap = XCreatePixmapFromBitmapData (dpy, + RootWindow (dpy, DefaultScreen(dpy)), + (char*) maskBits, width, height, + 1 , 0 , 1); } - 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) }