diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
index 5df2129..ee92943 100644
a
|
b
|
yres = 0
|
56 | 56 | ; Force a non-standard bit depth (if 0 then use the current desktop bit depth) |
57 | 57 | bpp = 0 |
58 | 58 | |
| 59 | ; Render at high-dpi resolution if screen supports it. Will be much slower. |
| 60 | high_dpi = false |
| 61 | |
59 | 62 | ; Preferred display (for multidisplay setups, only works with SDL 2.0) |
60 | 63 | display = 0 |
61 | 64 | |
diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp
index 09c3386..a0bf996 100644
a
|
b
|
InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
80 | 80 | // Yes the mouse position is stored as float to avoid |
81 | 81 | // constant conversions when operating in a |
82 | 82 | // float-based environment. |
83 | | m_MousePos = CPos((float)ev->ev.motion.x * g_GuiScale, (float)ev->ev.motion.y * g_GuiScale); |
| 83 | m_MousePos = CPos((float)ev->ev.motion.x * g_GuiScale * g_DpiScale, (float)ev->ev.motion.y * g_GuiScale * g_DpiScale); |
84 | 84 | |
85 | 85 | SGUIMessage msg(GUIM_MOUSE_MOTION); |
86 | 86 | GUI<SGUIMessage>::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, m_BaseObject, |
… |
… |
InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
107 | 107 | CPos oldMousePos = m_MousePos; |
108 | 108 | if (ev->ev.type == SDL_MOUSEBUTTONDOWN || ev->ev.type == SDL_MOUSEBUTTONUP) |
109 | 109 | { |
110 | | m_MousePos = CPos((float)ev->ev.button.x * g_GuiScale, (float)ev->ev.button.y * g_GuiScale); |
| 110 | m_MousePos = CPos((float)ev->ev.button.x * g_GuiScale * g_DpiScale, (float)ev->ev.button.y * g_GuiScale * g_DpiScale); |
111 | 111 | } |
112 | 112 | |
113 | 113 | // Only one object can be hovered |
diff --git a/source/gui/scripting/GuiScriptConversions.cpp b/source/gui/scripting/GuiScriptConversions.cpp
index b2a83c1..f817d0e 100644
a
|
b
|
|
27 | 27 | // ignore JS_SetProperty return value, because errors should be impossible |
28 | 28 | // and we can't do anything useful in the case of errors anyway |
29 | 29 | |
| 30 | extern float g_DpiScale; |
| 31 | |
30 | 32 | template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableHandleValue ret, SDL_Event_ const& val) |
31 | 33 | { |
32 | 34 | JSAutoRequest rq(cx); |
… |
… |
template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableH
|
87 | 89 | { |
88 | 90 | // SET(obj, "which", (int)val.ev.motion.which); // (not in wsdl.h) |
89 | 91 | // SET(obj, "state", (int)val.ev.motion.state); // (not in wsdl.h) |
90 | | SET(obj, "x", (int)val.ev.motion.x); |
91 | | SET(obj, "y", (int)val.ev.motion.y); |
| 92 | SET(obj, "x", (int)val.ev.motion.x * g_DpiScale); |
| 93 | SET(obj, "y", (int)val.ev.motion.y * g_DpiScale); |
92 | 94 | // SET(obj, "xrel", (int)val.ev.motion.xrel); // (not in wsdl.h) |
93 | 95 | // SET(obj, "yrel", (int)val.ev.motion.yrel); // (not in wsdl.h) |
94 | 96 | break; |
… |
… |
template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableH
|
99 | 101 | // SET(obj, "which", (int)val.ev.button.which); // (not in wsdl.h) |
100 | 102 | SET(obj, "button", (int)val.ev.button.button); |
101 | 103 | SET(obj, "state", (int)val.ev.button.state); |
102 | | SET(obj, "x", (int)val.ev.button.x); |
103 | | SET(obj, "y", (int)val.ev.button.y); |
| 104 | SET(obj, "x", (int)val.ev.button.x * g_DpiScale); |
| 105 | SET(obj, "y", (int)val.ev.button.y * g_DpiScale); |
104 | 106 | break; |
105 | 107 | } |
106 | 108 | case SDL_HOTKEYDOWN: |
diff --git a/source/ps/GameSetup/Config.cpp b/source/ps/GameSetup/Config.cpp
index d27cf8e..e0d0e85 100644
a
|
b
|
CStr g_RenderPath = "default";
|
61 | 61 | |
62 | 62 | int g_xres, g_yres; |
63 | 63 | float g_GuiScale = 1.0f; |
| 64 | float g_DpiScale = 1.0f; |
64 | 65 | bool g_VSync = false; |
65 | 66 | |
66 | 67 | bool g_Quickstart = false; |
diff --git a/source/ps/GameSetup/Config.h b/source/ps/GameSetup/Config.h
index 9173fb2..f02dac0 100644
a
|
b
|
extern CStr g_RenderPath;
|
86 | 86 | |
87 | 87 | extern int g_xres, g_yres; |
88 | 88 | extern float g_GuiScale; |
| 89 | extern float g_DpiScale; |
89 | 90 | extern bool g_VSync; |
90 | 91 | |
91 | 92 | extern bool g_Quickstart; |
diff --git a/source/ps/Globals.cpp b/source/ps/Globals.cpp
index 3c6e639..d6a3153 100644
a
|
b
|
InReaction GlobalsInputHandler(const SDL_Event_* ev)
|
69 | 69 | return IN_PASS; |
70 | 70 | |
71 | 71 | case SDL_MOUSEMOTION: |
72 | | g_mouse_x = ev->ev.motion.x; |
73 | | g_mouse_y = ev->ev.motion.y; |
| 72 | g_mouse_x = ev->ev.motion.x * g_DpiScale; |
| 73 | g_mouse_y = ev->ev.motion.y * g_DpiScale; |
74 | 74 | return IN_PASS; |
75 | 75 | |
76 | 76 | case SDL_MOUSEBUTTONDOWN: |
diff --git a/source/ps/VideoMode.cpp b/source/ps/VideoMode.cpp
index c1aa2cb..e2b4d71 100644
a
|
b
|
CVideoMode g_VideoMode;
|
49 | 49 | CVideoMode::CVideoMode() : |
50 | 50 | m_IsFullscreen(false), m_IsInitialised(false), m_Window(NULL), |
51 | 51 | m_PreferredW(0), m_PreferredH(0), m_PreferredBPP(0), m_PreferredFreq(0), |
52 | | m_ConfigW(0), m_ConfigH(0), m_ConfigBPP(0), m_ConfigFullscreen(false), m_ConfigForceS3TCEnable(true), |
| 52 | m_ConfigW(0), m_ConfigH(0), m_ConfigBPP(0), m_ConfigHighDPI(false), m_ConfigFullscreen(false), m_ConfigForceS3TCEnable(true), |
53 | 53 | m_WindowedW(DEFAULT_WINDOW_W), m_WindowedH(DEFAULT_WINDOW_H), m_WindowedX(0), m_WindowedY(0) |
54 | 54 | { |
55 | 55 | // (m_ConfigFullscreen defaults to false, so users don't get stuck if |
… |
… |
void CVideoMode::ReadConfig()
|
64 | 64 | |
65 | 65 | CFG_GET_VAL("xres", m_ConfigW); |
66 | 66 | CFG_GET_VAL("yres", m_ConfigH); |
| 67 | CFG_GET_VAL("high_dpi", m_ConfigHighDPI); |
67 | 68 | CFG_GET_VAL("bpp", m_ConfigBPP); |
68 | 69 | CFG_GET_VAL("display", m_ConfigDisplay); |
69 | 70 | CFG_GET_VAL("force_s3tc_enable", m_ConfigForceS3TCEnable); |
… |
… |
bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)
|
79 | 80 | { |
80 | 81 | // Note: these flags only take affect in SDL_CreateWindow |
81 | 82 | flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; |
| 83 | if (m_ConfigHighDPI) |
| 84 | flags |= SDL_WINDOW_ALLOW_HIGHDPI; |
82 | 85 | m_WindowedX = m_WindowedY = SDL_WINDOWPOS_CENTERED_DISPLAY(m_ConfigDisplay); |
83 | 86 | |
84 | 87 | m_Window = SDL_CreateWindow("0 A.D.", m_WindowedX, m_WindowedY, w, h, flags); |
… |
… |
bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)
|
147 | 150 | // Grab the current video settings |
148 | 151 | SDL_GetWindowSize(m_Window, &m_CurrentW, &m_CurrentH); |
149 | 152 | m_CurrentBPP = bpp; |
| 153 | LOGMESSAGE("Window Size: %dx%d", m_CurrentW, m_CurrentH); |
| 154 | |
| 155 | // This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI drawable |
| 156 | int drawingWidth, drawingHeight; |
| 157 | SDL_GL_GetDrawableSize(m_Window, &drawingWidth, &drawingHeight); |
| 158 | LOGMESSAGE("Drawable Size: %dx%d", drawingWidth, drawingHeight); |
| 159 | |
| 160 | UpdateRenderer(); |
150 | 161 | |
151 | 162 | if (fullscreen) |
152 | 163 | SDL_SetWindowGrab(m_Window, SDL_TRUE); |
… |
… |
bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen)
|
155 | 166 | |
156 | 167 | m_IsFullscreen = fullscreen; |
157 | 168 | |
158 | | g_xres = m_CurrentW; |
159 | | g_yres = m_CurrentH; |
160 | | |
161 | 169 | return true; |
162 | 170 | } |
163 | 171 | |
… |
… |
bool CVideoMode::ResizeWindow(int w, int h)
|
325 | 333 | |
326 | 334 | m_WindowedW = w; |
327 | 335 | m_WindowedH = h; |
328 | | |
329 | | UpdateRenderer(w, h); |
330 | | |
| 336 | |
331 | 337 | return true; |
332 | 338 | } |
333 | 339 | |
… |
… |
bool CVideoMode::SetFullscreen(bool fullscreen)
|
370 | 376 | if (!SetVideoMode(w, h, bpp, fullscreen)) |
371 | 377 | return false; |
372 | 378 | |
373 | | UpdateRenderer(m_CurrentW, m_CurrentH); |
374 | | |
375 | 379 | return true; |
376 | 380 | } |
377 | 381 | else |
… |
… |
bool CVideoMode::SetFullscreen(bool fullscreen)
|
386 | 390 | if (!SetVideoMode(w, h, bpp, fullscreen)) |
387 | 391 | return false; |
388 | 392 | |
389 | | UpdateRenderer(w, h); |
390 | | |
391 | 393 | return true; |
392 | 394 | } |
393 | 395 | } |
… |
… |
void CVideoMode::UpdatePosition(int x, int y)
|
406 | 408 | } |
407 | 409 | } |
408 | 410 | |
| 411 | void CVideoMode::UpdateRenderer() { |
| 412 | // This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI drawable |
| 413 | int drawingWidth, drawingHeight; |
| 414 | SDL_GL_GetDrawableSize(m_Window, &drawingWidth, &drawingHeight); |
| 415 | UpdateRenderer(drawingWidth, drawingHeight); |
| 416 | |
| 417 | g_xres = drawingWidth; |
| 418 | g_yres = drawingHeight; |
| 419 | g_GuiScale = m_CurrentW / ((float)drawingWidth); |
| 420 | g_DpiScale = ((float)drawingWidth) / m_CurrentW; |
| 421 | } |
| 422 | |
409 | 423 | void CVideoMode::UpdateRenderer(int w, int h) |
410 | 424 | { |
411 | 425 | if (w < 2) w = 2; // avoid GL errors caused by invalid sizes |
diff --git a/source/ps/VideoMode.h b/source/ps/VideoMode.h
index 0a820da..2cc2685 100644
a
|
b
|
public:
|
62 | 62 | */ |
63 | 63 | void UpdatePosition(int x, int y); |
64 | 64 | |
| 65 | /** |
| 66 | * Update the graphics code to start drawing to the new size set for the SDL context. |
| 67 | * This should be called after the GL context has been resized. |
| 68 | */ |
| 69 | void UpdateRenderer(); |
| 70 | |
65 | 71 | /** |
66 | | * Update the graphics code to start drawing to the new size. |
| 72 | * Update the graphics code to start drawing to the specified size. |
67 | 73 | * This should be called after the GL context has been resized. |
68 | 74 | * This can also be used when the GL context is managed externally, not via SDL. |
69 | 75 | */ |
… |
… |
private:
|
105 | 111 | int m_ConfigW; |
106 | 112 | int m_ConfigH; |
107 | 113 | int m_ConfigBPP; |
| 114 | bool m_ConfigHighDPI; |
108 | 115 | int m_ConfigDisplay; |
109 | 116 | bool m_ConfigFullscreen; |
110 | 117 | bool m_ConfigForceS3TCEnable; |