1 // MouseCursor.cxx - abstract inteface for mouse cursor control
3 // Copyright (C) 2013 James Turner <zakalawe@mac.com>
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "MouseCursor.hxx"
27 #include <boost/foreach.hpp>
29 #include <osgViewer/GraphicsWindow>
30 #include <osgViewer/Viewer>
32 #include <simgear/debug/logstream.hxx>
33 #include <simgear/simgear_config.h>
34 #include <simgear/structure/commands.hxx>
37 #include "CocoaMouseCursor.hxx"
41 #include "WindowsMouseCursor.hxx"
44 #include <Main/fg_props.hxx>
45 #include <Main/globals.hxx>
46 #include <Viewer/renderer.hxx>
47 #include <Main/fg_os.hxx> // for fgWarpMouse
53 * @brief when no native cursor implementation is available, use the osgViewer support. This
54 * has several limitations but is better than nothing
56 class StockOSGCursor : public FGMouseCursor
60 mCursorObscured(false),
62 mCursor(osgViewer::GraphicsWindow::InheritCursor)
64 mActualCursor = mCursor;
66 globals->get_renderer()->getViewer()->getWindows(mWindows);
69 virtual void setCursor(Cursor aCursor)
71 mCursor = translateCursor(aCursor);
75 virtual void setCursorVisible(bool aVis)
77 if (mCursorObscured == aVis) {
81 mCursorVisible = aVis;
85 virtual void hideCursorUntilMouseMove()
87 if (mCursorObscured) {
91 mCursorObscured = true;
95 virtual void mouseMoved()
97 if (mCursorObscured) {
98 mCursorObscured = false;
103 osgViewer::GraphicsWindow::MouseCursor translateCursor(Cursor aCursor)
106 case CURSOR_ARROW: return osgViewer::GraphicsWindow::RightArrowCursor;
107 case CURSOR_HAND: return osgViewer::GraphicsWindow::HandCursor;
108 case CURSOR_CLOSED_HAND: return osgViewer::GraphicsWindow::HandCursor;
109 case CURSOR_CROSSHAIR: return osgViewer::GraphicsWindow::CrosshairCursor;
110 case CURSOR_IBEAM: return osgViewer::GraphicsWindow::TextCursor;
111 case CURSOR_LEFT_RIGHT: return osgViewer::GraphicsWindow::LeftRightCursor;
112 case CURSOR_UP_DOWN: return osgViewer::GraphicsWindow::UpDownCursor;
114 return osgViewer::GraphicsWindow::RightArrowCursor;
120 osgViewer::GraphicsWindow::MouseCursor cur = osgViewer::GraphicsWindow::InheritCursor;
121 if (mCursorObscured || !mCursorVisible) {
122 cur = osgViewer::GraphicsWindow::NoCursor;
127 if (cur == mActualCursor) {
131 BOOST_FOREACH(osgViewer::GraphicsWindow* gw, mWindows) {
138 bool mCursorObscured;
140 osgViewer::GraphicsWindow::MouseCursor mCursor, mActualCursor;
141 std::vector<osgViewer::GraphicsWindow*> mWindows;
144 } // of anonymous namespace
146 static FGMouseCursor* static_instance = NULL;
148 FGMouseCursor::FGMouseCursor() :
149 mAutoHideTimeMsec(10000)
153 FGMouseCursor* FGMouseCursor::instance()
155 if (static_instance == NULL) {
158 static_instance = new CocoaMouseCursor;
162 // set osgViewer cursor inherit, otherwise it will interefere
163 std::vector<osgViewer::GraphicsWindow*> gws;
164 globals->get_renderer()->getViewer()->getWindows(gws);
165 BOOST_FOREACH(osgViewer::GraphicsWindow* gw, gws) {
166 gw->setCursor(osgViewer::GraphicsWindow::InheritCursor);
169 // Windows native curosr disabled while interaction with OSG
170 // is resolved - right now NCHITs (non-client-area hits)
171 // overwire the InheritCursor value above, and hence our cursor
173 // and create our real implementation
174 // static_instance = new WindowsMouseCursor;
179 if (static_instance == NULL) {
180 static_instance = new StockOSGCursor;
183 // initialise mouse-hide delay from global properties
185 globals->get_commands()->addCommand("set-cursor", static_instance, &FGMouseCursor::setCursorCommand);
188 return static_instance;
191 void FGMouseCursor::setAutoHideTimeMsec(unsigned int aMsec)
193 mAutoHideTimeMsec = aMsec;
197 bool FGMouseCursor::setCursorCommand(const SGPropertyNode* arg)
199 // JMT 2013 - I would prefer this was a seperate 'warp' command, but
200 // historically set-cursor has done both.
201 if (arg->hasValue("x") || arg->hasValue("y")) {
202 SGPropertyNode *mx = fgGetNode("/devices/status/mice/mouse/x", true);
203 SGPropertyNode *my = fgGetNode("/devices/status/mice/mouse/y", true);
204 int x = arg->getIntValue("x", mx->getIntValue());
205 int y = arg->getIntValue("y", my->getIntValue());
212 Cursor c = cursorFromString(arg->getStringValue("cursor"));
219 FGMouseCursor::Cursor cursor;
222 const MouseCursorMap mouse_cursor_map[] = {
223 { "inherit", FGMouseCursor::CURSOR_ARROW },
224 { "crosshair", FGMouseCursor::CURSOR_CROSSHAIR },
225 { "left-right", FGMouseCursor::CURSOR_LEFT_RIGHT },
226 { "hand", FGMouseCursor::CURSOR_HAND },
227 { "closed-hand", FGMouseCursor::CURSOR_CLOSED_HAND },
228 { "text", FGMouseCursor::CURSOR_IBEAM },
231 { "drag-horizontal", FGMouseCursor::CURSOR_LEFT_RIGHT },
232 { "drag-vertical", FGMouseCursor::CURSOR_UP_DOWN },
233 { 0, FGMouseCursor::CURSOR_ARROW }
236 FGMouseCursor::Cursor FGMouseCursor::cursorFromString(const char* cursor_name)
238 for (unsigned int k = 0; mouse_cursor_map[k].name != 0; k++) {
239 if (!strcmp(mouse_cursor_map[k].name, cursor_name)) {
240 return mouse_cursor_map[k].cursor;
244 SG_LOG(SG_GENERAL, SG_WARN, "unknown cursor:" << cursor_name);