OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4WindowSDL.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2010-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 /* A wrapper class to OS dependent event and window interfaces, SDL version */
18 
19 #include "C4Include.h"
20 #include "platform/C4Window.h"
21 
22 #include "C4Version.h"
23 #include "lib/C4Rect.h"
24 #include "editor/C4Console.h"
26 #include "game/C4Application.h"
27 #include "graphics/C4DrawGL.h"
28 #include "gui/C4Gui.h"
29 
30 #ifdef SDL_VIDEO_DRIVER_X11
31 #include <X11/Xlib.h>
32 #include <X11/Xutil.h>
33 #include <SDL_syswm.h>
34 #endif
35 
36 /* C4Window */
37 
39  Active(false), pSurface(nullptr), eKind(W_Fullscreen), window(nullptr)
40 #ifdef WITH_QT_EDITOR
41 , glwidget(nullptr)
42 #endif
43 {
44 }
45 
47 {
48  Clear();
49 }
50 
51 static void SetMultisamplingAttributes(int samples)
52 {
53  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, samples > 0 ? 1 : 0);
54  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
55 }
56 
57 C4Window * C4Window::Init(WindowKind windowKind, C4AbstractApp * pApp, const char * Title, const C4Rect * size)
58 {
59  eKind = windowKind;
60 #ifdef WITH_QT_EDITOR
61  if (windowKind == W_Viewport)
62  {
63  // embed into editor: Viewport widget creation handled by C4ConsoleQt
64  ::Console.AddViewport(static_cast<C4ViewportWindow *>(this));
65  return this;
66  }
67 #endif
68 /* SDL_GL_MULTISAMPLEBUFFERS,
69  SDL_GL_MULTISAMPLESAMPLES,*/
70  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
71  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
72  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
73  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
74  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, /*REQUESTED_GL_CTX_MAJOR*/ 3);
75  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, /*REQUESTED_GL_CTX_MINOR*/ 2);
76  SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, (Config.Graphics.DebugOpenGL ? SDL_GL_CONTEXT_DEBUG_FLAG : 0));
77  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
78  SetMultisamplingAttributes(Config.Graphics.MultiSampling);
79  uint32_t flags = SDL_WINDOW_OPENGL;
80  if (windowKind == W_Fullscreen && size->Wdt == -1)
81  flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
82  else if (windowKind == W_Fullscreen && !Config.Graphics.Windowed)
83  flags |= SDL_WINDOW_FULLSCREEN;
84  window = SDL_CreateWindow(Title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, size->Wdt, size->Hgt, flags);
85  if (!window)
86  {
87  Log(SDL_GetError());
88  return nullptr;
89  }
90  SDL_SetWindowData(window, "C4Window", this);
91  Active = true;
92  SDL_ShowCursor(SDL_DISABLE);
93  return this;
94 }
95 
97 {
98  // TODO: Is there some way to do this without requiring a restart?
99  // Maybe re-call SDL_SetVideoMode?
100  C4GUI::TheScreen.ShowMessage(LoadResStr("IDS_CTL_ANTIALIASING_RESTART_MSG"), LoadResStr("IDS_CTL_ANTIALIASING_RESTART_TITLE"), C4GUI::Ico_Notify);
101  return true;
102 }
103 
104 void C4Window::Clear()
105 {
106  if (window) SDL_DestroyWindow(window);
107  window = nullptr;
108 
109 #ifdef WITH_QT_EDITOR
110  if (eKind == W_Viewport)
111  {
112  // embed into editor: Viewport widget creation handled by C4ConsoleQt
113  ::Console.RemoveViewport(static_cast<C4ViewportWindow *>(this));
114  }
115 #endif
116 }
117 
118 void C4Window::EnumerateMultiSamples(std::vector<int>& samples) const
119 {
120  int max_samples;
121  glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
122  samples.clear();
123  for (int s = 2; s <= max_samples; s *= 2)
124  {
125  // Not all multisampling options seem to work. Verify by creating a hidden window.
126  SetMultisamplingAttributes(s);
127  SDL_Window *wnd = SDL_CreateWindow("OpenClonk Test Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 100, 100, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
128  if (wnd)
129  {
130  SDL_DestroyWindow(wnd);
131  samples.push_back(s);
132  }
133  else
134  break;
135  }
136  SetMultisamplingAttributes(Config.Graphics.MultiSampling);
137 }
138 
139 bool C4Window::StorePosition(const char *, const char *, bool) { return true; }
140 
141 bool C4Window::RestorePosition(const char *, const char *, bool) { return true; }
142 
143 // Window size is automatically managed by C4AbstractApp's display mode management.
144 // Just remember the size for others to query.
145 
146 bool C4Window::GetSize(C4Rect * pRect)
147 {
148  pRect->x = pRect->y = 0;
149  SDL_GL_GetDrawableSize(window, &pRect->Wdt, &pRect->Hgt);
150  return true;
151 }
152 
153 void C4Window::SetSize(unsigned int X, unsigned int Y)
154 {
155  SDL_SetWindowSize(window, X, Y);
156 }
157 
158 void C4Window::SetTitle(const char * Title)
159 {
160  SDL_SetWindowTitle(window, Title);
161 }
162 
164 {
165  // just invoke directly
166  PerformUpdate();
167 }
168 
169 static void SetUrgencyHint(SDL_Window *window, bool urgency_hint)
170 {
171 #ifdef SDL_VIDEO_DRIVER_X11
172  SDL_SysWMinfo wminfo;
173  SDL_VERSION(&wminfo.version);
174  if (!SDL_GetWindowWMInfo(window, &wminfo))
175  {
176  LogF("FlashWindow SDL: %s", SDL_GetError());
177  return;
178  }
179 
180  if (wminfo.subsystem == SDL_SYSWM_X11)
181  {
182  auto x11 = wminfo.info.x11;
183  XWMHints *wmhints = XGetWMHints(x11.display, x11.window);
184  if (wmhints == nullptr)
185  wmhints = XAllocWMHints();
186  // Set the window's urgency hint.
187  if (urgency_hint)
188  wmhints->flags |= XUrgencyHint;
189  else
190  wmhints->flags &= ~XUrgencyHint;
191  XSetWMHints(x11.display, x11.window, wmhints);
192  XFree(wmhints);
193  }
194 #endif
195 }
196 
198 {
199  SetUrgencyHint(window, true);
200 }
201 
202 void C4Window::GrabMouse(bool grab)
203 {
204  SDL_SetWindowGrab(window, grab ? SDL_TRUE : SDL_FALSE);
205 }
206 
207 void C4Window::HandleSDLEvent(SDL_WindowEvent &e)
208 {
209  switch (e.event)
210  {
211  case SDL_WINDOWEVENT_FOCUS_GAINED:
212  SetUrgencyHint(window, false);
213  break;
214  case SDL_WINDOWEVENT_RESIZED:
215  case SDL_WINDOWEVENT_SIZE_CHANGED:
216  Application.OnResolutionChanged(e.data1, e.data2);
217  break;
218  default:
219  // We don't care about most events. We should care about more, though.
220  break;
221  }
222 }
bool StorePosition(const char *szWindowName, const char *szSubKey, bool fStoreSize=true)
int32_t DebugOpenGL
Definition: C4Config.h:117
int32_t MultiSampling
Definition: C4Config.h:115
C4Config Config
Definition: C4Config.cpp:833
void GrabMouse(bool grab)
Definition: C4AppT.cpp:104
bool GetSize(C4Rect *pRect)
Definition: C4AppT.cpp:105
C4Console Console
Definition: C4Globals.cpp:45
void FlashWindow()
Definition: C4AppMac.mm:74
void OnResolutionChanged(unsigned int iXRes, unsigned int iYRes) override
int32_t Windowed
Definition: C4Config.h:106
void SetTitle(const char *Title)
Definition: C4AppT.cpp:111
Definition: C4Rect.h:27
virtual void EnumerateMultiSamples(std::vector< int > &samples) const
Definition: C4AppT.cpp:102
virtual void PerformUpdate()
Definition: C4App.cpp:85
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
virtual bool ReInit(C4AbstractApp *pApp)
Definition: C4AppT.cpp:107
C4ConfigGraphics Graphics
Definition: C4Config.h:253
int32_t Wdt
Definition: C4Rect.h:30
void SetSize(unsigned int cx, unsigned int cy)
Definition: C4AppT.cpp:110
int32_t y
Definition: C4Rect.h:30
void AddViewport(C4ViewportWindow *cvp)
Definition: C4ConsoleGUI.h:110
virtual ~C4Window()
Definition: C4WindowSDL.cpp:46
WindowKind eKind
Definition: C4Window.h:275
bool RestorePosition(const char *szWindowName, const char *szSubKey, bool fHidden=false)
Definition: C4AppT.cpp:108
int32_t x
Definition: C4Rect.h:30
bool ShowMessage(const char *szMessage, const char *szCaption, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
void RemoveViewport(C4ViewportWindow *cvp)
Definition: C4ConsoleGUI.h:111
virtual void RequestUpdate()
Definition: C4AppT.cpp:109
bool Active
Definition: C4Window.h:273
bool Log(const char *szMessage)
Definition: C4Log.cpp:192
virtual C4Window * Init(WindowKind windowKind, C4AbstractApp *pApp, const char *Title, const C4Rect *size)
Definition: C4AppT.cpp:106
#define X(sdl, oc)
int32_t Hgt
Definition: C4Rect.h:30
virtual void Clear()
Definition: C4AppT.cpp:99
Screen TheScreen
Definition: C4Gui.cpp:1054
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:250
#define s
C4Application Application
Definition: C4Globals.cpp:44