From 822868ca31b16d6f8843bd3d0bf0d8e446c4b5ce Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 1 Jun 2007 19:43:28 +0000 Subject: [PATCH] From Mathias Froelich, "have done an interface to change the mouse cursor in the X11 graphics window. The win32 implementation is still in its original shape since I have no win32 implementation available. I have chosen the enum approach for the first cut. That is benefitial since the user does not need to track creation of mouse cursors for different windows and displays in presence of multiple viewer windows. The default set of available mouse shapes is the same set that was available with glut. That set served many OpenGL applications well, so the hope is that this is enough. Even though, that implementation is still extensible: I have digged out the way SDL defines new mouse cursors and added a still documented out function prototype in the GraphicsWindow that can be used to extend the current implemtation for arbitrary mouse shapes. That is not implemented yet. I hope that somebody with a win32 test system can catch up that implementation on win32." --- include/osgViewer/GraphicsWindow | 33 ++++- include/osgViewer/api/X11/GraphicsWindowX11 | 22 ++-- src/osgViewer/GraphicsWindowX11.cpp | 126 +++++++++++++++----- 3 files changed, 139 insertions(+), 42 deletions(-) diff --git a/include/osgViewer/GraphicsWindow b/include/osgViewer/GraphicsWindow index 219c84adb..5557f3c64 100644 --- a/include/osgViewer/GraphicsWindow +++ b/include/osgViewer/GraphicsWindow @@ -61,8 +61,39 @@ class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgG /** Get focus on if the pointer is in this window.*/ virtual void grabFocusIfPointerInWindow() { osg::notify(osg::NOTICE)<<"GraphicsWindow::grabFocusIfPointerInWindow(..) not implemented."< _mouseCursorMap; }; } diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index 73f752b0c..3be3680c2 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -384,28 +384,112 @@ void GraphicsWindowX11::setWindowRectangle(int x, int y, int width, int height) usleep(100000); } -void GraphicsWindowX11::useCursor(bool cursorOn) +void GraphicsWindowX11::setCursor(MouseCursor mouseCursor) { + Cursor newCursor = getOrCreateCursor(mouseCursor); + if (newCursor == _currentCursor) return; + + _currentCursor = newCursor; + if (!_window) return; Display* display = getDisplayToUse(); + if (!display) return; + XDefineCursor( display, _window, _currentCursor ); + XFlush(display); + XSync(display, 0); - if (cursorOn) - { - _currentCursor = _defaultCursor; - } - else - { - _currentCursor = _nullCursor; - } + _traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor)); +} - if (display && _window) +Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor) +{ + std::map::iterator i = _mouseCursorMap.find(mouseCursor); + if (i != _mouseCursorMap.end()) return i->second; + + Display* display = getDisplayToUse(); + if (!display) return None; + + switch (mouseCursor) { + case NoCursor: { - XDefineCursor( display, _window, _currentCursor ); + // create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation + // since the resource in the x server is reference counted. + char buff[2] = {0,0}; + XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0}; + Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1); + _mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 ); + XFreePixmap(display, pixmap); + // Important to have the pixmap and the buffer still available when the request is sent to the server ... XFlush(display); - XSync(display,0); + XSync(display, 0); + break; } + case RightArrowCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr ); + break; + case LeftArrowCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow ); + break; + case InfoCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 ); + break; + case DestroyCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate ); + break; + case HelpCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow ); + break; + case CycleCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange ); + break; + case SprayCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan ); + break; + case WaitCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch ); + break; + case TextCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm ); + break; + case CrosshairCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair ); + break; + case UpDownCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow ); + break; + case LeftRightCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow ); + break; + case TopSideCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side ); + break; + case BottomSideCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side ); + break; + case LeftSideCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side ); + break; + case RightSideCursor: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side ); + break; + case TopLeftCorner: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner ); + break; + case TopRightCorner: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner ); + break; + case BottomRightCorner: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner ); + break; + case BottomLeftCorner: + _mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner ); + break; - _traits->useCursor = cursorOn; - + case InheritCursor: + default: + _mouseCursorMap[mouseCursor] = None; + break; + }; + return _mouseCursorMap[mouseCursor]; } void GraphicsWindowX11::init() @@ -541,20 +625,6 @@ void GraphicsWindowX11::init() setWindowDecoration(_traits->windowDecoration); - // Create default Cursor - _defaultCursor = XCreateFontCursor( _display, XC_left_ptr ); - - - // Create Null Cursor - { - Pixmap pixmap; - static char buff[2] = {0,0}; - static XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0}; - - pixmap = XCreateBitmapFromData( _display, _parent, buff, 1, 1); - _nullCursor = XCreatePixmapCursor( _display, pixmap, pixmap, &ncol, &ncol, 0, 0 ); - } - useCursor(_traits->useCursor); _deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False);