]> git.mxchange.org Git - flightgear.git/blob - src/Viewer/WindowBuilder.cxx
Code cleanups, code updates and fix at least on (possible) devide-by-zero
[flightgear.git] / src / Viewer / WindowBuilder.cxx
1 // Copyright (C) 2008  Tim Moore
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 #ifdef HAVE_CONFIG_H
18 #  include "config.h"
19 #endif
20
21 #include "WindowBuilder.hxx"
22
23 #include "WindowSystemAdapter.hxx"
24 #include <Main/fg_props.hxx>
25
26 #include <sstream>
27
28 #if defined(SG_MAC)
29     #include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
30 #endif
31
32 using namespace std;
33 using namespace osg;
34
35 namespace flightgear
36 {
37 string makeName(const string& prefix, int num)
38 {
39     stringstream stream;
40     stream << prefix << num;
41     return stream.str();
42 }
43
44 ref_ptr<WindowBuilder> WindowBuilder::windowBuilder;
45
46 const string WindowBuilder::defaultWindowName("FlightGear");
47
48 // default to true (historical behaviour), we will clear the flag if
49 // we run another GUI.
50 bool WindowBuilder::poseAsStandaloneApp = true;
51
52 void WindowBuilder::initWindowBuilder(bool stencil)
53 {
54     windowBuilder = new WindowBuilder(stencil);
55 }
56
57 WindowBuilder::WindowBuilder(bool stencil) : defaultCounter(0)
58 {
59     defaultTraits = makeDefaultTraits(stencil);
60 }
61
62 GraphicsContext::Traits*
63 WindowBuilder::makeDefaultTraits(bool stencil)
64 {
65     GraphicsContext::WindowingSystemInterface* wsi
66         = osg::GraphicsContext::getWindowingSystemInterface();
67     GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
68
69     traits->readDISPLAY();
70     if (traits->displayNum < 0)
71         traits->displayNum = 0;
72     if (traits->screenNum < 0)
73         traits->screenNum = 0;
74
75     int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
76     int cbits = (bpp <= 16) ?  5 :  8;
77     int zbits = (bpp <= 16) ? 16 : 24;
78     traits->red = traits->green = traits->blue = cbits;
79     traits->depth = zbits;
80
81     if (stencil)
82         traits->stencil = 8;
83
84     unsigned screenwidth = 0;
85     unsigned screenheight = 0;
86     wsi->getScreenResolution(*traits, screenwidth, screenheight);
87
88     traits->doubleBuffer = true;
89     traits->mipMapGeneration = true;
90     traits->windowName = "FlightGear";
91     // XXX should check per window too.
92     traits->sampleBuffers = fgGetInt("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
93     traits->samples = fgGetInt("/sim/rendering/multi-samples", traits->samples);
94     traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
95     traits->windowDecoration = !fgGetBool("/sim/startup/fullscreen");
96
97     if (!traits->windowDecoration) {
98         // fullscreen
99         traits->supportsResize = false;
100         traits->width = screenwidth;
101         traits->height = screenheight;
102         SG_LOG(SG_VIEW,SG_DEBUG,"Using full screen size for window: " << screenwidth << " x " << screenheight);
103     } else {
104         // window
105         int w = fgGetInt("/sim/startup/xsize");
106         int h = fgGetInt("/sim/startup/ysize");
107         traits->supportsResize = true;
108         traits->width = w;
109         traits->height = h;
110         if ((w>0)&&(h>0))
111         {
112             traits->x = ((unsigned)w>screenwidth) ? 0 : (screenwidth-w)/3;
113             traits->y = ((unsigned)h>screenheight) ? 0 : (screenheight-h)/3;
114         }
115         SG_LOG(SG_VIEW,SG_DEBUG,"Using initial window size: " << w << " x " << h);
116     }
117     return traits;
118 }
119 }
120
121 namespace
122 {
123 // Helper functions that set a value based on a property if it exists,
124 // returning 1 if the value was set.
125
126 inline int setFromProperty(string& place, const SGPropertyNode* node,
127                             const char* name)
128 {
129     const SGPropertyNode* valNode = node->getNode(name);
130     if (valNode) {
131         place = valNode->getStringValue();
132         return 1;
133     }
134     return 0;
135 }
136
137 inline int setFromProperty(int& place, const SGPropertyNode* node,
138                             const char* name)
139 {
140     const SGPropertyNode* valNode = node->getNode(name);
141     if (valNode) {
142         place = valNode->getIntValue();
143         return 1;
144     }
145     return 0;
146 }
147
148 inline int setFromProperty(bool& place, const SGPropertyNode* node,
149                             const char* name)
150 {
151     const SGPropertyNode* valNode = node->getNode(name);
152     if (valNode) {
153         place = valNode->getBoolValue();
154         return 1;
155     }
156     return 0;
157 }
158 }
159
160 namespace flightgear
161 {
162 GraphicsWindow* WindowBuilder::buildWindow(const SGPropertyNode* winNode)
163 {
164     GraphicsContext::WindowingSystemInterface* wsi
165         = osg::GraphicsContext::getWindowingSystemInterface();
166     WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
167     string windowName;
168     if (winNode->hasChild("window-name"))
169         windowName = winNode->getStringValue("window-name");
170     else if (winNode->hasChild("name"))
171         windowName = winNode->getStringValue("name");
172     GraphicsWindow* result = 0;
173     if (!windowName.empty()) {
174         result = wsa->findWindow(windowName);
175         if (result)
176             return result;
177     }
178     GraphicsContext::Traits* traits
179         = new GraphicsContext::Traits(*defaultTraits);
180     int traitsSet = setFromProperty(traits->hostName, winNode, "host-name");
181     traitsSet |= setFromProperty(traits->displayNum, winNode, "display");
182     traitsSet |= setFromProperty(traits->screenNum, winNode, "screen");
183
184     const SGPropertyNode* fullscreenNode = winNode->getNode("fullscreen");
185     const SGPropertyNode* orrNode = winNode->getNode("overrideRedirect");
186
187     if (fullscreenNode && fullscreenNode->getBoolValue()) {
188         // fullscreen mode
189         unsigned width = 0;
190         unsigned height = 0;
191         wsi->getScreenResolution(*traits, width, height);
192         traits->windowDecoration = false;
193         traits->width = width;
194         traits->height = height;
195         traits->supportsResize = false;
196         bool overrideRedirect = orrNode && orrNode->getBoolValue();
197         traits->overrideRedirect = overrideRedirect;
198         traits->x = 0;
199         traits->y = 0;
200         traitsSet = 1;
201     } else {
202         int resizable = 0;
203         if (fullscreenNode && !fullscreenNode->getBoolValue())
204         {
205             traits->windowDecoration = true;
206             resizable = 1;
207         }
208         resizable |= setFromProperty(traits->windowDecoration, winNode,
209                                      "decoration");
210         resizable |= setFromProperty(traits->width, winNode, "width");
211         resizable |= setFromProperty(traits->height, winNode, "height");
212         if (resizable) {
213             traits->supportsResize = true;
214             traitsSet = 1;
215         }
216         // Otherwise use default values.
217     }
218     traitsSet |= setFromProperty(traits->x, winNode, "x");
219     traitsSet |= setFromProperty(traits->y, winNode, "y");
220     if (!windowName.empty() && windowName != traits->windowName) {
221         traits->windowName = windowName;
222         traitsSet = 1;
223     } else if (traitsSet) {
224         traits->windowName = makeName("FlightGear", defaultCounter++);
225     }
226     bool drawGUI = false;
227     traitsSet |= setFromProperty(drawGUI, winNode, "gui");
228     if (traitsSet) {
229         GraphicsContext* gc = GraphicsContext::createGraphicsContext(traits);
230         if (gc) {
231             GraphicsWindow* window = WindowSystemAdapter::getWSA()
232                 ->registerWindow(gc, traits->windowName);
233             if (drawGUI)
234                 window->flags |= GraphicsWindow::GUI;
235             return window;
236         } else {
237             return 0;
238         }
239     } else {
240         // XXX What if the window has no traits, but does have a name?
241         // We should create a "default window" registered with that name.
242         return getDefaultWindow();
243     }
244 }
245
246 GraphicsWindow* WindowBuilder::getDefaultWindow()
247 {
248     GraphicsWindow* defaultWindow
249         = WindowSystemAdapter::getWSA()->findWindow(defaultWindowName);
250     if (defaultWindow)
251         return defaultWindow;
252     GraphicsContext::Traits* traits
253         = new GraphicsContext::Traits(*defaultTraits);
254     traits->windowName = "FlightGear";
255
256 #if defined(SG_MAC)
257     int flags = osgViewer::GraphicsWindowCocoa::WindowData::CheckForEvents;
258
259     // avoid both QApplication and OSG::CocoaViewer doing single-application
260     // init (Apple menu, making front process, etc)
261     if (poseAsStandaloneApp) {
262         flags |= osgViewer::GraphicsWindowCocoa::WindowData::PoseAsStandaloneApp;
263     }
264     traits->inheritedWindowData = new osgViewer::GraphicsWindowCocoa::WindowData(flags);
265 #endif
266
267     GraphicsContext* gc = GraphicsContext::createGraphicsContext(traits);
268     if (gc) {
269         defaultWindow = WindowSystemAdapter::getWSA()
270             ->registerWindow(gc, defaultWindowName);
271         return defaultWindow;
272     } else {
273         SG_LOG(SG_VIEW, SG_ALERT, "getDefaultWindow: failed to create GraphicsContext");
274         return 0;
275     }
276 }
277
278 void WindowBuilder::setPoseAsStandaloneApp(bool b)
279 {
280     poseAsStandaloneApp = b;
281 }
282
283 } // of namespace flightgear