]> git.mxchange.org Git - flightgear.git/blob - src/GUI/MouseCursor.cxx
Support for multiple data dirs.
[flightgear.git] / src / GUI / MouseCursor.cxx
1 // MouseCursor.cxx - abstract inteface for  mouse cursor control
2
3 // Copyright (C) 2013 James Turner <zakalawe@mac.com>
4 //
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.
9 //
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.
14 //
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.
18 //
19
20 #ifdef HAVE_CONFIG_H
21   #include "config.h"
22 #endif
23
24 #include "MouseCursor.hxx"
25
26 #include <cstring>
27 #include <boost/foreach.hpp>
28
29 #include <osgViewer/GraphicsWindow>
30 #include <osgViewer/Viewer>
31
32 #include <simgear/debug/logstream.hxx>
33 #include <simgear/simgear_config.h>
34 #include <simgear/structure/commands.hxx>
35
36 #ifdef SG_MAC
37 #include "CocoaMouseCursor.hxx"
38 #endif
39
40 #ifdef SG_WINDOWS
41 #include "WindowsMouseCursor.hxx"
42 #endif
43
44 #include <Main/fg_props.hxx>
45 #include <Main/globals.hxx>
46 #include <Viewer/renderer.hxx>
47 #include <Main/fg_os.hxx> // for fgWarpMouse
48
49 namespace
50 {
51     
52 /**
53  * @brief when no native cursor implementation is available, use the osgViewer support. This
54  * has several limitations but is better than nothing
55  */
56 class StockOSGCursor : public FGMouseCursor
57 {
58 public:
59     StockOSGCursor() :
60         mCursorObscured(false),
61         mCursorVisible(true),
62         mCursor(osgViewer::GraphicsWindow::InheritCursor)
63     {
64         mActualCursor = mCursor;
65         
66         globals->get_renderer()->getViewer()->getWindows(mWindows);
67     }
68
69     virtual void setCursor(Cursor aCursor)
70     {
71         mCursor = translateCursor(aCursor);
72         updateCursor();
73     }
74     
75     virtual void setCursorVisible(bool aVis)
76     {
77         if (mCursorObscured == aVis) {
78             return;
79         }
80         
81         mCursorVisible = aVis;
82         updateCursor();
83     }
84     
85     virtual void hideCursorUntilMouseMove()
86     {
87         if (mCursorObscured) {
88             return;
89         }
90         
91         mCursorObscured = true;
92         updateCursor();
93     }
94     
95     virtual void mouseMoved()
96     {
97         if (mCursorObscured) {
98             mCursorObscured = false;
99             updateCursor();
100         }
101     }
102 private:
103     osgViewer::GraphicsWindow::MouseCursor translateCursor(Cursor aCursor)
104     {
105         switch (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;
113         default:
114                         return osgViewer::GraphicsWindow::RightArrowCursor;  
115         }
116     }
117     
118     void updateCursor()
119     {
120         osgViewer::GraphicsWindow::MouseCursor cur = osgViewer::GraphicsWindow::InheritCursor;
121         if (mCursorObscured || !mCursorVisible) {
122             cur = osgViewer::GraphicsWindow::NoCursor;
123         } else {
124             cur = mCursor;
125         }
126         
127         if (cur == mActualCursor) {
128             return;
129         }
130         
131         BOOST_FOREACH(osgViewer::GraphicsWindow* gw, mWindows) {
132             gw->setCursor(cur);
133         }
134         
135         mActualCursor = cur;
136     }
137     
138     bool mCursorObscured;
139     bool mCursorVisible;
140     osgViewer::GraphicsWindow::MouseCursor mCursor, mActualCursor;
141     std::vector<osgViewer::GraphicsWindow*> mWindows;
142 };
143     
144 } // of anonymous namespace
145
146 static FGMouseCursor* static_instance = NULL;
147
148 FGMouseCursor::FGMouseCursor() :
149     mAutoHideTimeMsec(10000)
150 {
151 }
152
153 FGMouseCursor* FGMouseCursor::instance()
154 {
155     if (static_instance == NULL) {
156     #ifdef SG_MAC
157         if (true) {
158             static_instance = new CocoaMouseCursor;
159         }
160     #endif
161         #ifdef SG_WINDOWS
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);
167         }
168
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
172         // get stuck.
173         // and create our real implementation
174         //      static_instance = new WindowsMouseCursor;
175         #endif
176         
177         // X11
178                 
179         if (static_instance == NULL) {
180             static_instance = new StockOSGCursor;
181         }
182         
183         // initialise mouse-hide delay from global properties
184         
185         globals->get_commands()->addCommand("set-cursor", static_instance, &FGMouseCursor::setCursorCommand);
186     }
187     
188     return static_instance;
189 }
190
191 void FGMouseCursor::setAutoHideTimeMsec(unsigned int aMsec)
192 {
193     mAutoHideTimeMsec = aMsec;
194 }
195
196
197 bool FGMouseCursor::setCursorCommand(const SGPropertyNode* arg)
198 {
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());
206         fgWarpMouse(x, y);
207         mx->setIntValue(x);
208         my->setIntValue(y);
209     }
210
211     
212     Cursor c = cursorFromString(arg->getStringValue("cursor"));    
213     setCursor(c);
214     return true;
215 }
216
217 typedef struct {
218     const char * name;
219     FGMouseCursor::Cursor cursor;
220 } MouseCursorMap;
221
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 },
229     
230 // aliases
231     { "drag-horizontal", FGMouseCursor::CURSOR_LEFT_RIGHT },
232     { "drag-vertical", FGMouseCursor::CURSOR_UP_DOWN },
233     { 0, FGMouseCursor::CURSOR_ARROW }
234 };
235
236 FGMouseCursor::Cursor FGMouseCursor::cursorFromString(const char* cursor_name)
237 {
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;
241         }
242     }
243
244     SG_LOG(SG_GENERAL, SG_WARN, "unknown cursor:" << cursor_name);
245     return CURSOR_ARROW;
246 }