]> git.mxchange.org Git - flightgear.git/blob - src/GUI/MouseCursor.cxx
541a725a051ef0a06c617efeae3d26ffe458cd69
[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 #include <Main/fg_props.hxx>
41 #include <Main/globals.hxx>
42 #include <Viewer/renderer.hxx>
43 #include <Main/fg_os.hxx> // for fgWarpMouse
44
45 namespace
46 {
47     
48 /**
49  * @brief when no native cursor implementation is available, use the osgViewer support. This
50  * has several limitations but is better than nothing
51  */
52 class StockOSGCursor : public FGMouseCursor
53 {
54 public:
55     StockOSGCursor() :
56         mCursorObscured(false),
57         mCursorVisible(true),
58         mCursor(osgViewer::GraphicsWindow::InheritCursor)
59     {
60         mActualCursor = mCursor;
61         
62         globals->get_renderer()->getViewer()->getWindows(mWindows);
63     }
64
65     virtual void setCursor(Cursor aCursor)
66     {
67         mCursor = translateCursor(aCursor);
68         updateCursor();
69     }
70     
71     virtual void setCursorVisible(bool aVis)
72     {
73         if (mCursorObscured == aVis) {
74             return;
75         }
76         
77         mCursorVisible = aVis;
78         updateCursor();
79     }
80     
81     virtual void hideCursorUntilMouseMove()
82     {
83         if (mCursorObscured) {
84             return;
85         }
86         
87         mCursorObscured = true;
88         updateCursor();
89     }
90     
91     virtual void mouseMoved()
92     {
93         if (mCursorObscured) {
94             mCursorObscured = false;
95             updateCursor();
96         }
97     }
98 private:
99     osgViewer::GraphicsWindow::MouseCursor translateCursor(Cursor aCursor)
100     {
101         switch (aCursor) {
102         case CURSOR_HAND: return osgViewer::GraphicsWindow::HandCursor;
103         case CURSOR_CROSSHAIR: return osgViewer::GraphicsWindow::CrosshairCursor;
104         case CURSOR_IBEAM: return osgViewer::GraphicsWindow::TextCursor;
105         case CURSOR_LEFT_RIGHT: return osgViewer::GraphicsWindow::LeftRightCursor;
106                     
107         default: return osgViewer::GraphicsWindow::InheritCursor;   
108         }
109     }
110     
111     void updateCursor()
112     {
113         osgViewer::GraphicsWindow::MouseCursor cur = osgViewer::GraphicsWindow::InheritCursor;
114         if (mCursorObscured || !mCursorVisible) {
115             cur = osgViewer::GraphicsWindow::NoCursor;
116         } else {
117             cur = mCursor;
118         }
119         
120         if (cur == mActualCursor) {
121             return;
122         }
123         
124         BOOST_FOREACH(osgViewer::GraphicsWindow* gw, mWindows) {
125             gw->setCursor(cur);
126         }
127         
128         mActualCursor = cur;
129     }
130     
131     bool mCursorObscured;
132     bool mCursorVisible;
133     osgViewer::GraphicsWindow::MouseCursor mCursor, mActualCursor;
134     std::vector<osgViewer::GraphicsWindow*> mWindows;
135 };
136     
137 } // of anonymous namespace
138
139 static FGMouseCursor* static_instance = NULL;
140
141 FGMouseCursor::FGMouseCursor() :
142     mAutoHideTimeMsec(10000)
143 {
144 }
145
146 FGMouseCursor* FGMouseCursor::instance()
147 {
148     if (static_instance == NULL) {
149     #ifdef SG_MAC
150         if (true) {
151             static_instance = new CocoaMouseCursor;
152         }
153     #endif
154         
155         // windows
156         
157         // X11
158                 
159         if (static_instance == NULL) {
160             static_instance = new StockOSGCursor;
161         }
162         
163         // initialise mouse-hide delay from global properties
164         
165         globals->get_commands()->addCommand("set-cursor", static_instance, &FGMouseCursor::setCursorCommand);
166     }
167     
168     return static_instance;
169 }
170
171 void FGMouseCursor::setAutoHideTimeMsec(unsigned int aMsec)
172 {
173     mAutoHideTimeMsec = aMsec;
174 }
175
176
177 bool FGMouseCursor::setCursorCommand(const SGPropertyNode* arg)
178 {
179     // JMT 2013 - I would prefer this was a seperate 'warp' command, but
180     // historically set-cursor has done both. 
181     if (arg->hasValue("x") || arg->hasValue("y")) {
182         SGPropertyNode *mx = fgGetNode("/devices/status/mice/mouse/x", true);
183         SGPropertyNode *my = fgGetNode("/devices/status/mice/mouse/y", true);
184         int x = arg->getIntValue("x", mx->getIntValue());
185         int y = arg->getIntValue("y", my->getIntValue());
186         fgWarpMouse(x, y);
187         mx->setIntValue(x);
188         my->setIntValue(y);
189     }
190
191     
192     Cursor c = cursorFromString(arg->getStringValue("cursor"));    
193     setCursor(c);
194     return true;
195 }
196
197 typedef struct {
198     const char * name;
199     FGMouseCursor::Cursor cursor;
200 } MouseCursorMap;
201
202 const MouseCursorMap mouse_cursor_map[] = {
203     { "inherit", FGMouseCursor::CURSOR_ARROW },
204     { "crosshair", FGMouseCursor::CURSOR_CROSSHAIR },
205     { "left-right", FGMouseCursor::CURSOR_LEFT_RIGHT },
206     { "hand", FGMouseCursor::CURSOR_HAND },
207     { "text", FGMouseCursor::CURSOR_IBEAM },
208     { 0, FGMouseCursor::CURSOR_ARROW }
209 };
210
211 FGMouseCursor::Cursor FGMouseCursor::cursorFromString(const char* cursor_name)
212 {
213     for (unsigned int k = 0; mouse_cursor_map[k].name != 0; k++) {
214         if (!strcmp(mouse_cursor_map[k].name, cursor_name)) {
215             return mouse_cursor_map[k].cursor;
216         }
217     }
218
219     SG_LOG(SG_GENERAL, SG_WARN, "unknown cursor:" << cursor_name);
220     return CURSOR_ARROW;
221 }