Merge tag '1.11.0-beta1' into jgrpp

# Conflicts:
#	src/console_cmds.cpp
#	src/gfx_func.h
#	src/industry.h
#	src/lang/czech.txt
#	src/lang/estonian.txt
#	src/lang/german.txt
#	src/lang/indonesian.txt
#	src/lang/japanese.txt
#	src/lang/norwegian_bokmal.txt
#	src/lang/russian.txt
#	src/lang/slovak.txt
#	src/saveload/saveload.h
#	src/station_gui.cpp
#	src/town_gui.cpp
#	src/vehicle_gui.cpp
#	src/video/sdl2_v.cpp
#	src/waypoint_gui.cpp
This commit is contained in:
Jonathan G Rennison
2021-02-01 18:58:36 +00:00
130 changed files with 1579 additions and 1104 deletions

View File

@@ -417,6 +417,8 @@ const char *VideoDriver_Allegro::Start(const StringList &parm)
}
_allegro_instance_count++;
this->UpdateAutoResolution();
install_timer();
install_mouse();
install_keyboard();

View File

@@ -70,6 +70,9 @@ public:
/** Main game loop. */
void GameLoop(); // In event.mm.
protected:
Dimension GetScreenSize() const override;
private:
friend class WindowQuartzSubdriver;

View File

@@ -200,6 +200,8 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm)
/* Don't create a window or enter fullscreen if we're just going to show a dialog. */
if (!CocoaSetupApplication()) return NULL;
this->UpdateAutoResolution();
this->orig_res = _cur_resolution;
int width = _cur_resolution.width;
int height = _cur_resolution.height;
@@ -302,6 +304,15 @@ void VideoDriver_Cocoa::EditBoxLostFocus()
HandleTextInput(NULL, true);
}
/**
* Get the resolution of the main screen.
*/
Dimension VideoDriver_Cocoa::GetScreenSize() const
{
NSRect frame = [ [ NSScreen mainScreen ] frame ];
return { static_cast<uint>(NSWidth(frame)), static_cast<uint>(NSHeight(frame)) };
}
/**
* Handle a change of the display area.
*/

View File

@@ -135,6 +135,8 @@ static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
const char *VideoDriver_Dedicated::Start(const StringList &parm)
{
this->UpdateAutoResolution();
int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
_dedicated_video_mem = (bpp == 0) ? nullptr : MallocT<byte>(_cur_resolution.width * _cur_resolution.height * (bpp / 8));

View File

@@ -26,6 +26,8 @@ const char *VideoDriver_Null::Start(const StringList &parm)
_set_error_mode(_OUT_TO_STDERR);
#endif
this->UpdateAutoResolution();
this->ticks = GetDriverParamInt(parm, "ticks", 1000);
this->until_exit = GetDriverParamBool(parm, "until_exit");
_screen.width = _screen.pitch = _cur_resolution.width;

View File

@@ -491,8 +491,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
DEBUG(driver, 1, "SDL2: using mode %ux%ux%d", w, h, bpp);
if (bpp == 0) usererror("Can't use a blitter that blits 0 bpp for normal visuals");
/* Free any previously allocated shadow surface */
if (_sdl_surface != nullptr && _sdl_surface != _sdl_realscreen) SDL_FreeSurface(_sdl_surface);
@@ -505,10 +503,15 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
flags |= SDL_WINDOW_FULLSCREEN;
}
int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
SDL_Rect r;
if (SDL_GetDisplayBounds(this->startup_display, &r) == 0) {
x = r.x + std::max(0, r.w - static_cast<int>(w)) / 2;
y = r.y + std::max(0, r.h - static_cast<int>(h)) / 4; // decent desktops have taskbars at the bottom
}
_sdl_window = SDL_CreateWindow(
caption,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
x, y,
w, h,
flags);
@@ -997,6 +1000,8 @@ int VideoDriver_SDL::PollEvent()
const char *VideoDriver_SDL::Start(const StringList &parm)
{
if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported";
#if defined(WITH_FCITX)
FcitxInit();
#endif
@@ -1016,6 +1021,25 @@ const char *VideoDriver_SDL::Start(const StringList &parm)
}
if (ret_code < 0) return SDL_GetError();
this->startup_display = GetDriverParamInt(parm, "display", -1);
int num_displays = SDL_GetNumVideoDisplays();
if (!IsInsideBS(this->startup_display, 0, num_displays)) {
/* Mouse position decides which display to use */
int mx, my;
SDL_GetGlobalMouseState(&mx, &my);
this->startup_display = 0; // used when mouse is on no screen...
for (int display = 0; display < num_displays; ++display) {
SDL_Rect r;
if (SDL_GetDisplayBounds(display, &r) == 0 && IsInsideBS(mx, r.x, r.w) && IsInsideBS(my, r.y, r.h)) {
DEBUG(driver, 1, "SDL2: Mouse is at (%d, %d), use display %d (%d, %d, %d, %d)", mx, my, display, r.x, r.y, r.w, r.h);
this->startup_display = display;
break;
}
}
}
this->UpdateAutoResolution();
GetVideoModes();
if (!CreateMainSurface(_cur_resolution.width, _cur_resolution.height, false)) {
return SDL_GetError();
@@ -1268,6 +1292,7 @@ bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen)
bool VideoDriver_SDL::AfterBlitterChange()
{
assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0);
int w, h;
SDL_GetWindowSize(_sdl_window, &w, &h);
return CreateMainSurface(w, h, false);
@@ -1283,4 +1308,12 @@ void VideoDriver_SDL::ReleaseBlitterLock()
if (_draw_mutex != nullptr) _draw_mutex->unlock();
}
Dimension VideoDriver_SDL::GetScreenSize() const
{
SDL_DisplayMode mode;
if (SDL_GetCurrentDisplayMode(this->startup_display, &mode) != 0) return VideoDriver::GetScreenSize();
return { static_cast<uint>(mode.w), static_cast<uint>(mode.h) };
}
#endif /* WITH_SDL2 */

View File

@@ -40,6 +40,10 @@ public:
void EditBoxLostFocus() override;
const char *GetName() const override { return "sdl"; }
protected:
Dimension GetScreenSize() const override;
private:
int PollEvent();
void LoopOnce();
@@ -60,6 +64,7 @@ private:
uint32 last_cur_ticks;
uint32 next_tick;
int startup_display;
std::thread draw_thread;
std::unique_lock<std::recursive_mutex> draw_lock;
};

View File

@@ -620,6 +620,8 @@ const char *VideoDriver_SDL::Start(const StringList &parm)
}
if (ret_code < 0) return SDL_GetError();
this->UpdateAutoResolution();
GetVideoModes();
if (!CreateMainSurface(_cur_resolution.width, _cur_resolution.height)) {
return SDL_GetError();

View File

@@ -12,10 +12,19 @@
#include "../driver.h"
#include "../core/geometry_type.hpp"
#include "../core/math_func.hpp"
#include <vector>
extern std::string _ini_videodriver;
extern std::vector<Dimension> _resolutions;
extern Dimension _cur_resolution;
extern bool _rightclick_emulate;
/** The base of all video drivers. */
class VideoDriver : public Driver {
const uint DEFAULT_WINDOW_WIDTH = 640u; ///< Default window width.
const uint DEFAULT_WINDOW_HEIGHT = 480u; ///< Default window height.
public:
/**
* Mark a particular area dirty.
@@ -102,11 +111,27 @@ public:
static VideoDriver *GetInstance() {
return static_cast<VideoDriver*>(*DriverFactoryBase::GetActiveDriver(Driver::DT_VIDEO));
}
protected:
/*
* Get the resolution of the main screen.
*/
virtual Dimension GetScreenSize() const { return { DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT }; }
/**
* Apply resolution auto-detection and clamp to sensible defaults.
*/
void UpdateAutoResolution()
{
if (_cur_resolution.width == 0 || _cur_resolution.height == 0) {
/* Auto-detect a good resolution. We aim for 75% of the screen size.
* Limit width times height times bytes per pixel to fit a 32 bit
* integer, This way all internal drawing routines work correctly. */
Dimension res = this->GetScreenSize();
_cur_resolution.width = ClampU(res.width * 3 / 4, DEFAULT_WINDOW_WIDTH, UINT16_MAX / 2);
_cur_resolution.height = ClampU(res.height * 3 / 4, DEFAULT_WINDOW_HEIGHT, UINT16_MAX / 2);
}
}
};
extern std::string _ini_videodriver;
extern std::vector<Dimension> _resolutions;
extern Dimension _cur_resolution;
extern bool _rightclick_emulate;
#endif /* VIDEO_VIDEO_DRIVER_HPP */

View File

@@ -44,9 +44,6 @@
#define PM_QS_INPUT 0x20000
#endif
typedef BOOL (WINAPI *PFNTRACKMOUSEEVENT)(LPTRACKMOUSEEVENT lpEventTrack);
static PFNTRACKMOUSEEVENT _pTrackMouseEvent = nullptr;
static struct {
HWND main_wnd; ///< Handle to system window.
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
@@ -81,24 +78,24 @@ static Palette _local_palette;
static void MakePalette()
{
_cur_palette.first_dirty = 0;
_cur_palette.count_dirty = 256;
_local_palette = _cur_palette;
LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY));
pal->palVersion = 0x300;
pal->palNumEntries = 256;
for (uint i = 0; i != 256; i++) {
pal->palPalEntry[i].peRed = _cur_palette.palette[i].r;
pal->palPalEntry[i].peGreen = _cur_palette.palette[i].g;
pal->palPalEntry[i].peBlue = _cur_palette.palette[i].b;
pal->palPalEntry[i].peRed = _local_palette.palette[i].r;
pal->palPalEntry[i].peGreen = _local_palette.palette[i].g;
pal->palPalEntry[i].peBlue = _local_palette.palette[i].b;
pal->palPalEntry[i].peFlags = 0;
}
_wnd.gdi_palette = CreatePalette(pal);
if (_wnd.gdi_palette == nullptr) usererror("CreatePalette failed!\n");
_cur_palette.first_dirty = 0;
_cur_palette.count_dirty = 256;
_local_palette = _cur_palette;
}
static void UpdatePalette(HDC dc, uint start, uint count)
@@ -234,31 +231,6 @@ int RedrawScreenDebug()
}
#endif
/* Windows 95 will not have a WM_MOUSELEAVE message, so define it if needed */
#if !defined(WM_MOUSELEAVE)
#define WM_MOUSELEAVE 0x02A3
#endif
#define TID_POLLMOUSE 1
#define MOUSE_POLL_DELAY 75
static void CALLBACK TrackMouseTimerProc(HWND hwnd, UINT msg, UINT_PTR event, DWORD time)
{
RECT rc;
POINT pt;
/* Get the rectangle of our window and translate it to screen coordinates.
* Compare this with the current screen coordinates of the mouse and if it
* falls outside of the area or our window we have left the window. */
GetClientRect(hwnd, &rc);
MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)(LPRECT)&rc, 2);
GetCursorPos(&pt);
if (!PtInRect(&rc, pt) || (WindowFromPoint(pt) != hwnd)) {
KillTimer(hwnd, event);
PostMessage(hwnd, WM_MOUSELEAVE, 0, 0L);
}
}
/**
* Instantiate a new window.
* @param full_screen Whether to make a full screen window or not.
@@ -638,7 +610,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
switch (msg) {
case WM_CREATE:
SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, TrackMouseTimerProc);
_cursor.in_window = false; // Win32 has mouse tracking.
SetCompositionPos(hwnd);
_imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
break;
@@ -735,16 +707,12 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
* tracking the mouse for exiting the window */
if (!_cursor.in_window) {
_cursor.in_window = true;
if (_pTrackMouseEvent != nullptr) {
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
_pTrackMouseEvent(&tme);
} else {
SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, TrackMouseTimerProc);
}
TrackMouseEvent(&tme);
}
if (_cursor.fix_at) {
@@ -1012,27 +980,24 @@ static void RegisterWndClass()
{
static bool registered = false;
if (!registered) {
HINSTANCE hinst = GetModuleHandle(nullptr);
WNDCLASS wnd = {
CS_OWNDC,
WndProcGdi,
0,
0,
hinst,
LoadIcon(hinst, MAKEINTRESOURCE(100)),
LoadCursor(nullptr, IDC_ARROW),
0,
0,
_T("OTTD")
};
if (registered) return;
registered = true;
if (!RegisterClass(&wnd)) usererror("RegisterClass failed");
HINSTANCE hinst = GetModuleHandle(nullptr);
WNDCLASS wnd = {
CS_OWNDC,
WndProcGdi,
0,
0,
hinst,
LoadIcon(hinst, MAKEINTRESOURCE(100)),
LoadCursor(nullptr, IDC_ARROW),
0,
0,
_T("OTTD")
};
/* Dynamically load mouse tracking, as it doesn't exist on Windows 95. */
_pTrackMouseEvent = (PFNTRACKMOUSEEVENT)GetProcAddress(GetModuleHandle(_T("User32")), "TrackMouseEvent");
}
registered = true;
if (!RegisterClass(&wnd)) usererror("RegisterClass failed");
}
static bool AllocateDibSection(int w, int h, bool force)
@@ -1044,8 +1009,6 @@ static bool AllocateDibSection(int w, int h, bool force)
w = std::max(w, 64);
h = std::max(h, 64);
if (bpp == 0) usererror("Can't use a blitter that blits 0 bpp for normal visuals");
if (!force && w == _screen.width && h == _screen.height) return false;
bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
@@ -1056,7 +1019,7 @@ static bool AllocateDibSection(int w, int h, bool force)
bi->bmiHeader.biHeight = -(_wnd.height = h);
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = BI_RGB;
if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
@@ -1119,6 +1082,10 @@ static FVideoDriver_Win32 iFVideoDriver_Win32;
const char *VideoDriver_Win32::Start(const StringList &parm)
{
if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported";
this->UpdateAutoResolution();
memset(&_wnd, 0, sizeof(_wnd));
RegisterWndClass();
@@ -1282,7 +1249,7 @@ void VideoDriver_Win32::MainLoop()
/* Release the thread while sleeping */
if (_draw_threaded) draw_lock.unlock();
Sleep(1);
CSleep(1);
if (_draw_threaded) draw_lock.lock();
NetworkDrawChatMessage();
@@ -1329,6 +1296,7 @@ bool VideoDriver_Win32::ToggleFullscreen(bool full_screen)
bool VideoDriver_Win32::AfterBlitterChange()
{
assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0);
return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
}
@@ -1351,3 +1319,8 @@ void VideoDriver_Win32::EditBoxLostFocus()
SetCompositionPos(_wnd.main_wnd);
SetCandidatePos(_wnd.main_wnd);
}
Dimension VideoDriver_Win32::GetScreenSize() const
{
return { static_cast<uint>(GetSystemMetrics(SM_CXSCREEN)), static_cast<uint>(GetSystemMetrics(SM_CYSCREEN)) };
}

View File

@@ -40,6 +40,9 @@ public:
const char *GetName() const override { return "win32"; }
bool MakeWindow(bool full_screen);
protected:
Dimension GetScreenSize() const override;
};
/** The factory for Windows' video driver. */