12 #include "../stdafx.h" 13 #include "../openttd.h" 14 #include "../gfx_func.h" 15 #include "../os/windows/win32.h" 17 #include "../blitter/factory.hpp" 18 #include "../network/network.h" 19 #include "../core/math_func.hpp" 20 #include "../core/random_func.hpp" 21 #include "../texteff.hpp" 22 #include "../thread/thread.h" 23 #include "../progress.h" 24 #include "../window_gui.h" 25 #include "../window_func.h" 26 #include "../framerate_type.h" 31 #include "../safeguards.h" 34 #ifndef MAPVK_VK_TO_CHAR 35 #define MAPVK_VK_TO_CHAR (2) 39 #define PM_QS_INPUT 0x20000 42 typedef BOOL (WINAPI *PFNTRACKMOUSEEVENT)(LPTRACKMOUSEEVENT lpEventTrack);
43 static PFNTRACKMOUSEEVENT _pTrackMouseEvent = NULL;
60 bool _force_full_redraw;
61 bool _window_maximize;
79 static void MakePalette()
81 LOGPALETTE *pal = (LOGPALETTE*)alloca(
sizeof(LOGPALETTE) + (256 - 1) *
sizeof(PALETTEENTRY));
83 pal->palVersion = 0x300;
84 pal->palNumEntries = 256;
86 for (uint i = 0; i != 256; i++) {
90 pal->palPalEntry[i].peFlags = 0;
93 _wnd.gdi_palette = CreatePalette(pal);
94 if (_wnd.gdi_palette == NULL)
usererror(
"CreatePalette failed!\n");
101 static void UpdatePalette(HDC dc, uint start, uint count)
106 for (i = 0; i != count; i++) {
107 rgb[i].rgbRed = _local_palette.
palette[start + i].r;
108 rgb[i].rgbGreen = _local_palette.
palette[start + i].g;
109 rgb[i].rgbBlue = _local_palette.
palette[start + i].b;
110 rgb[i].rgbReserved = 0;
113 SetDIBColorTable(dc, start, count, rgb);
116 bool VideoDriver_Win32::ClaimMousePointer()
118 MyShowCursor(
false,
true);
128 #define AS(x, z) {x, 0, z} 129 #define AM(x, y, z, w) {x, y - x, z} 133 AM(VK_PRIOR, VK_DOWN, WKC_PAGEUP, WKC_DOWN),
135 AM(
'A',
'Z',
'A',
'Z'),
136 AM(
'0',
'9',
'0',
'9'),
138 AS(VK_ESCAPE, WKC_ESC),
139 AS(VK_PAUSE, WKC_PAUSE),
140 AS(VK_BACK, WKC_BACKSPACE),
141 AM(VK_INSERT, VK_DELETE, WKC_INSERT, WKC_DELETE),
143 AS(VK_SPACE, WKC_SPACE),
144 AS(VK_RETURN, WKC_RETURN),
148 AM(VK_F1, VK_F12, WKC_F1, WKC_F12),
151 AM(VK_NUMPAD0, VK_NUMPAD9,
'0',
'9'),
152 AS(VK_DIVIDE, WKC_NUM_DIV),
153 AS(VK_MULTIPLY, WKC_NUM_MUL),
154 AS(VK_SUBTRACT, WKC_NUM_MINUS),
155 AS(VK_ADD, WKC_NUM_PLUS),
156 AS(VK_DECIMAL, WKC_NUM_DECIMAL),
172 static uint MapWindowsKey(uint sym)
177 for (map = _vk_mapping; map !=
endof(_vk_mapping); ++map) {
178 if ((uint)(sym - map->vk_from) <= map->vk_count) {
179 key = sym - map->vk_from + map->map_to;
184 if (GetAsyncKeyState(VK_SHIFT) < 0) key |= WKC_SHIFT;
185 if (GetAsyncKeyState(VK_CONTROL) < 0) key |= WKC_CTRL;
186 if (GetAsyncKeyState(VK_MENU) < 0) key |= WKC_ALT;
190 static bool AllocateDibSection(
int w,
int h,
bool force =
false);
192 static void ClientSizeChanged(
int w,
int h)
195 if (AllocateDibSection(w, h)) {
210 int RedrawScreenDebug()
215 HPALETTE old_palette;
219 dc = GetDC(_wnd.main_wnd);
220 dc2 = CreateCompatibleDC(dc);
222 old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
223 old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
224 BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
225 SelectPalette(dc, old_palette, TRUE);
226 SelectObject(dc2, old_bmp);
228 ReleaseDC(_wnd.main_wnd, dc);
235 #if !defined(WM_MOUSELEAVE) 236 #define WM_MOUSELEAVE 0x02A3 238 #define TID_POLLMOUSE 1 239 #define MOUSE_POLL_DELAY 75 241 static void CALLBACK TrackMouseTimerProc(HWND hwnd, UINT msg, UINT_PTR event, DWORD time)
249 GetClientRect(hwnd, &rc);
250 MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)(LPRECT)&rc, 2);
253 if (!PtInRect(&rc, pt) || (WindowFromPoint(pt) != hwnd)) {
254 KillTimer(hwnd, event);
255 PostMessage(hwnd, WM_MOUSELEAVE, 0, 0L);
266 _fullscreen = full_screen;
269 if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
270 DestroyWindow(_wnd.main_wnd);
277 memset(&settings, 0,
sizeof(settings));
283 (_display_hz != 0 ? DM_DISPLAYFREQUENCY : 0);
285 settings.dmPelsWidth = _wnd.width_org;
286 settings.dmPelsHeight = _wnd.height_org;
287 settings.dmDisplayFrequency = _display_hz;
290 if (settings.dmBitsPerPel == 8 &&
291 (_support8bpp !=
S8BPP_HARDWARE || ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL)) {
292 settings.dmBitsPerPel = 32;
296 if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) {
298 GetWindowRect(GetDesktopWindow(), &r);
301 if ((
int)settings.dmPelsWidth != r.right - r.left || (
int)settings.dmPelsHeight != r.bottom - r.top) {
306 if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
310 }
else if (_wnd.fullscreen) {
312 ChangeDisplaySettings(NULL, 0);
314 _wnd.width = _bck_resolution.width;
315 _wnd.height = _bck_resolution.height;
320 DWORD style, showstyle;
323 showstyle = SW_SHOWNORMAL;
324 _wnd.fullscreen = full_screen;
325 if (_wnd.fullscreen) {
327 SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
329 style = WS_OVERLAPPEDWINDOW;
331 if (_window_maximize) showstyle = SW_SHOWMAXIMIZED;
332 SetRect(&r, 0, 0, _wnd.width, _wnd.height);
335 AdjustWindowRect(&r, style, FALSE);
336 w = r.right - r.left;
337 h = r.bottom - r.top;
339 if (_wnd.main_wnd != NULL) {
340 if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
342 int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
343 int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
345 char window_title[64];
346 seprintf(window_title,
lastof(window_title),
"OpenTTD %s", _openttd_revision);
348 _wnd.main_wnd = CreateWindow(_T(
"OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(NULL), 0);
349 if (_wnd.main_wnd == NULL)
usererror(
"CreateWindow failed");
350 ShowWindow(_wnd.main_wnd, showstyle);
365 HDC dc2 = CreateCompatibleDC(dc);
366 HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
367 HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
390 BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
391 SelectPalette(dc, old_palette, TRUE);
392 SelectObject(dc2, old_bmp);
396 static void PaintWindowThread(
void *)
408 ClientToScreen(_wnd.main_wnd, &pt);
409 OffsetRect(&_wnd.update_rect, pt.x, pt.y);
413 HRGN rgn = CreateRectRgnIndirect(&_wnd.update_rect);
414 HDC dc = GetDCEx(_wnd.main_wnd, rgn, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTRGN);
419 SetRectEmpty(&_wnd.update_rect);
420 ReleaseDC(_wnd.main_wnd, dc);
429 _draw_thread->
Exit();
435 #if !defined(UNICODE) 436 static char prev_char = 0;
438 char input[2] = {(char)charcode, 0};
441 if (prev_char != 0) {
443 input[0] = prev_char;
444 input[1] = (char)charcode;
446 }
else if (IsDBCSLeadByte(charcode)) {
448 prev_char = charcode;
454 int len = MultiByteToWideChar(CP_ACP, 0, input, input_len, w, 2);
465 DEBUG(driver, 1,
"Invalid DBCS character sequence encountered, dropping input");
470 static WChar prev_char = 0;
474 if (prev_char != 0)
DEBUG(driver, 1,
"Got two UTF-16 lead surrogates, dropping the first one");
475 prev_char = charcode;
480 if (prev_char != 0) {
484 DEBUG(driver, 1,
"Got an UTF-16 lead surrogate without a trail surrogate, dropping the lead surrogate");
498 return (_imm_props & IME_PROP_AT_CARET) && !(_imm_props & IME_PROP_SPECIAL_UI);
504 HIMC hIMC = ImmGetContext(hwnd);
507 cf.dwStyle = CFS_POINT;
512 cf.ptCurrentPos.x = _focused_window->
left + pt.x;
513 cf.ptCurrentPos.y = _focused_window->
top + pt.y;
515 cf.ptCurrentPos.x = 0;
516 cf.ptCurrentPos.y = 0;
518 ImmSetCompositionWindow(hIMC, &cf);
520 ImmReleaseContext(hwnd, hIMC);
526 HIMC hIMC = ImmGetContext(hwnd);
530 cf.dwStyle = CFS_EXCLUDE;
534 cf.ptCurrentPos.x = _focused_window->
left + pt.x;
535 cf.ptCurrentPos.y = _focused_window->
top + pt.y;
537 cf.rcArea.left = _focused_window->
left;
538 cf.rcArea.top = _focused_window->
top;
539 cf.rcArea.right = _focused_window->
left + _focused_window->
width;
540 cf.rcArea.bottom = _focused_window->
top + _focused_window->
height;
548 cf.ptCurrentPos.x = 0;
549 cf.ptCurrentPos.y = 0;
550 SetRectEmpty(&cf.rcArea);
552 ImmSetCandidateWindow(hIMC, &cf);
554 ImmReleaseContext(hwnd, hIMC);
560 HIMC hIMC = ImmGetContext(hwnd);
563 if (lParam & GCS_RESULTSTR) {
565 LONG len = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
566 TCHAR *str = (TCHAR *)_alloca(len +
sizeof(TCHAR));
567 len = ImmGetCompositionString(hIMC, GCS_RESULTSTR, str, len);
568 str[len /
sizeof(TCHAR)] =
'\0';
578 lParam &= ~(GCS_RESULTSTR | GCS_RESULTCLAUSE | GCS_RESULTREADCLAUSE | GCS_RESULTREADSTR);
583 LONG len = ImmGetCompositionString(hIMC, GCS_COMPSTR, NULL, 0);
584 TCHAR *str = (TCHAR *)_alloca(len +
sizeof(TCHAR));
585 len = ImmGetCompositionString(hIMC, GCS_COMPSTR, str, len);
586 str[len /
sizeof(TCHAR)] =
'\0';
589 static char utf8_buf[1024];
593 LONG caret_bytes = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);
594 const char *caret = utf8_buf;
595 for (
const TCHAR *c = str; *c !=
'\0' && *caret !=
'\0' && caret_bytes > 0; c++, caret_bytes--) {
600 if (IsDBCSLeadByte(*c)) {
613 lParam &= ~(GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE | GCS_CURSORPOS | GCS_DELTASTART);
616 ImmReleaseContext(hwnd, hIMC);
618 return lParam != 0 ? DefWindowProc(hwnd, WM_IME_COMPOSITION, wParam, lParam) : 0;
624 HIMC hIMC = ImmGetContext(hwnd);
625 if (hIMC != NULL) ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
626 ImmReleaseContext(hwnd, hIMC);
631 static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
633 static uint32 keycode = 0;
634 static bool console =
false;
635 static bool in_sizemove =
false;
639 SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, TrackMouseTimerProc);
644 case WM_ENTERSIZEMOVE:
648 case WM_EXITSIZEMOVE:
656 GetUpdateRect(hwnd, &r, FALSE);
657 UnionRect(&_wnd.update_rect, &_wnd.update_rect, &r);
660 ValidateRect(hwnd, NULL);
665 BeginPaint(hwnd, &ps);
671 case WM_PALETTECHANGED:
672 if ((HWND)wParam == hwnd)
return 0;
675 case WM_QUERYNEWPALETTE: {
676 HDC hDC = GetWindowDC(hwnd);
677 HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE);
678 UINT nChanged = RealizePalette(hDC);
680 SelectPalette(hDC, hOldPalette, TRUE);
681 ReleaseDC(hwnd, hDC);
682 if (nChanged != 0) InvalidateRect(hwnd, NULL, FALSE);
687 HandleExitGameRequest();
728 int x = (int16)LOWORD(lParam);
729 int y = (int16)HIWORD(lParam);
736 if (_pTrackMouseEvent != NULL) {
738 tme.cbSize =
sizeof(tme);
739 tme.dwFlags = TME_LEAVE;
740 tme.hwndTrack = hwnd;
742 _pTrackMouseEvent(&tme);
744 SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, TrackMouseTimerProc);
752 while (PeekMessage(&m, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE | PM_NOYIELD | PM_QS_INPUT)) {
753 x = (int16)LOWORD(m.lParam);
754 y = (int16)HIWORD(m.lParam);
760 pt.x = _cursor.
pos.x;
761 pt.y = _cursor.
pos.y;
762 ClientToScreen(hwnd, &pt);
763 SetCursorPos(pt.x, pt.y);
770 case WM_INPUTLANGCHANGE:
774 case WM_IME_SETCONTEXT:
779 case WM_IME_STARTCOMPOSITION:
784 case WM_IME_COMPOSITION:
787 case WM_IME_ENDCOMPOSITION:
797 #if !defined(UNICODE) 799 if (
GB(wParam, 8, 8) != 0) {
808 console =
GB(lParam, 16, 8) == 41;
812 uint scancode =
GB(lParam, 16, 8);
813 uint charcode = wParam;
817 if (console && scancode == 41) {
824 uint cur_keycode = keycode;
832 uint scancode =
GB(lParam, 16, 8);
833 keycode = scancode == 41 ? (uint)WKC_BACKQUOTE : MapWindowsKey(wParam);
837 if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
838 if ((msg.message == WM_CHAR || msg.message == WM_DEADCHAR) &&
GB(lParam, 16, 8) ==
GB(msg.lParam, 16, 8)) {
843 uint charcode = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
852 if (
HasBit(charcode, 31) && !console) {
853 if (scancode == 41) {
862 uint cur_keycode = keycode;
872 ToggleFullScreen(!_wnd.fullscreen);
889 if (wParam != SIZE_MINIMIZED) {
892 _window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen));
893 if (_window_maximize || _fullscreen) _bck_resolution =
_cur_resolution;
894 ClientSizeChanged(LOWORD(lParam), HIWORD(lParam));
899 RECT *r = (RECT*)lParam;
903 SetRect(&r2, 0, 0, 0, 0);
904 AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
906 w = r->right - r->left - (r2.right - r2.left);
907 h = r->bottom - r->top - (r2.bottom - r2.top);
910 SetRect(&r2, 0, 0, w, h);
912 AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
913 w = r2.right - r2.left;
914 h = r2.bottom - r2.top;
918 r->bottom = r->top + h;
921 case WMSZ_BOTTOMLEFT:
922 r->bottom = r->top + h;
923 r->left = r->right - w;
926 case WMSZ_BOTTOMRIGHT:
927 r->bottom = r->top + h;
928 r->right = r->left + w;
932 r->left = r->right - w;
936 r->right = r->left + w;
940 r->top = r->bottom - h;
944 r->top = r->bottom - h;
945 r->left = r->right - w;
949 r->top = r->bottom - h;
950 r->right = r->left + w;
957 #if !defined(WM_MOUSEWHEEL) 958 # define WM_MOUSEWHEEL 0x020A 960 #if !defined(GET_WHEEL_DELTA_WPARAM) 961 # define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD(wparam)) 964 case WM_MOUSEWHEEL: {
965 int delta = GET_WHEEL_DELTA_WPARAM(wParam);
969 }
else if (delta > 0) {
977 _wnd.has_focus =
true;
982 _wnd.has_focus =
false;
987 if (_exit_game)
break;
989 bool active = (LOWORD(wParam) != WA_INACTIVE);
990 bool minimized = (HIWORD(wParam) != 0);
991 if (_wnd.fullscreen) {
992 if (active && minimized) {
994 ShowWindow(hwnd, SW_RESTORE);
996 }
else if (!active && !minimized) {
998 ShowWindow(hwnd, SW_MINIMIZE);
999 ChangeDisplaySettings(NULL, 0);
1006 return DefWindowProc(hwnd, msg, wParam, lParam);
1009 static void RegisterWndClass()
1011 static bool registered =
false;
1014 HINSTANCE hinst = GetModuleHandle(NULL);
1021 LoadIcon(hinst, MAKEINTRESOURCE(100)),
1022 LoadCursor(NULL, IDC_ARROW),
1029 if (!RegisterClass(&wnd))
usererror(
"RegisterClass failed");
1032 _pTrackMouseEvent = (PFNTRACKMOUSEEVENT)GetProcAddress(GetModuleHandle(_T(
"User32")),
"TrackMouseEvent");
1036 static bool AllocateDibSection(
int w,
int h,
bool force)
1045 if (bpp == 0)
usererror(
"Can't use a blitter that blits 0 bpp for normal visuals");
1047 if (!force && w == _screen.width && h == _screen.height)
return false;
1049 bi = (BITMAPINFO*)alloca(
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * 256);
1050 memset(bi, 0,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * 256);
1051 bi->bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
1053 bi->bmiHeader.biWidth = _wnd.width = w;
1054 bi->bmiHeader.biHeight = -(_wnd.height = h);
1056 bi->bmiHeader.biPlanes = 1;
1058 bi->bmiHeader.biCompression = BI_RGB;
1060 if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
1063 _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, NULL, 0);
1064 if (_wnd.dib_sect == NULL)
usererror(
"CreateDIBSection failed");
1068 _screen.pitch = (bpp == 8) ?
Align(w, 4) : w;
1070 _screen.dst_ptr = _wnd.buffer_bits;
1075 static const Dimension default_resolutions[] = {
1089 static void FindResolutions()
1101 for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) {
1102 if (dm.dmBitsPerPel == bpp &&
1103 dm.dmPelsWidth >= 640 && dm.dmPelsHeight >= 480) {
1106 for (j = 0; j < n; j++) {
1124 memcpy(
_resolutions, default_resolutions,
sizeof(default_resolutions));
1136 memset(&_wnd, 0,
sizeof(_wnd));
1162 DeleteObject(_wnd.gdi_palette);
1163 DeleteObject(_wnd.dib_sect);
1164 DestroyWindow(_wnd.main_wnd);
1166 if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0);
1172 RECT r = { left, top, left + width, top + height };
1174 InvalidateRect(_wnd.main_wnd, &r, FALSE);
1177 static void CheckPaletteAnim()
1182 InvalidateRect(_wnd.main_wnd, NULL, FALSE);
1188 uint32 cur_ticks = GetTickCount();
1189 uint32 last_cur_ticks = cur_ticks;
1210 DEBUG(driver, 1,
"Threaded drawing enabled");
1218 _wnd.running =
true;
1222 uint32 prev_cur_ticks = cur_ticks;
1224 while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) {
1225 InteractiveRandom();
1228 DispatchMessage(&mesg);
1230 if (_exit_game)
return;
1233 if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0 &&
1236 if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0 &&
1240 }
else if (_fast_forward & 2) {
1244 cur_ticks = GetTickCount();
1245 if (cur_ticks >= next_tick || (_fast_forward && !
_pause_mode) || cur_ticks < prev_cur_ticks) {
1247 last_cur_ticks = cur_ticks;
1252 _ctrl_pressed = _wnd.has_focus && GetAsyncKeyState(VK_CONTROL)<0;
1256 if (_wnd.has_focus) {
1258 (GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) +
1259 (GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) +
1260 (GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) +
1261 (GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
1301 _draw_thread->
Join();
1312 if (_window_maximize) ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL);
1314 _wnd.width = _wnd.width_org = w;
1315 _wnd.height = _wnd.height_org = h;
1318 if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
1326 if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
1332 return AllocateDibSection(_screen.width, _screen.height,
true) && this->
MakeWindow(_fullscreen);
1342 if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
1351 if (_draw_mutex != NULL) _draw_mutex->
EndCritical(
true);
static LRESULT HandleCharMsg(uint keycode, WChar charcode)
Forward key presses to the window system.
const char * GetDriverParam(const char *const *parm, const char *name)
Get a string parameter the list of parameters.
void HandleTextInput(const char *str, bool marked=false, const char *caret=NULL, const char *insert_location=NULL, const char *replacement_end=NULL)
Handle text input.
static bool _draw_threaded
Whether the drawing is/may be done in a separate thread.
bool _networking
are we in networking mode?
void MainLoop()
Perform the actual drawing.
uint32 _realtime_tick
The real time in the game.
const NWidgetCore * nested_focus
Currently focused nested widget, or NULL if no nested widget has focus.
Point pos
logical mouse position
const char * FS2OTTD(const TCHAR *name)
Convert to OpenTTD's encoding from that of the local environment.
Information about the currently used palette.
static HANDLE _draw_thread_initialized
Event that is signaled when the drawing thread has finished initializing.
int left
x position of left edge of the window
The factory for Windows' video driver.
bool ChangeResolution(int w, int h)
Change the resolution of the window.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
bool _right_button_down
Is right mouse button pressed?
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
fluid_settings_t * settings
FluidSynth settings handle.
int top
y position of top edge of the window
Dimension _cur_resolution
The current resolution.
int _num_resolutions
The number of resolutions.
static volatile bool _draw_continue
Should we keep continue drawing?
#define lastof(x)
Get the last element of an fixed size array.
How all blitters should look like.
char * convert_from_fs(const TCHAR *name, char *utf8_buf, size_t buflen)
Convert to OpenTTD's encoding from that of the environment in UNICODE.
static T max(const T a, const T b)
Returns the maximum of two values.
virtual void EndCritical(bool allow_recursive=false)=0
End of the critical section.
virtual void PostResize()
Post resize event.
Palette animation should be done by video backend (8bpp only!)
virtual void SendSignal()=0
Send a signal and wake the 'thread' that was waiting for it.
bool _left_button_clicked
Is left mouse button clicked?
bool _ctrl_pressed
Is Ctrl pressed?
bool ToggleFullscreen(bool fullscreen)
Change the full screen setting.
bool _right_button_clicked
Is right mouse button clicked?
static T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
The blitter takes care of the palette animation.
virtual void PaletteAnimate(const Palette &palette)=0
Called when the 8bpp palette is changed; you should redraw all pixels on the screen that are equal to...
bool _left_button_down
Is left mouse button pressed?
void GetKeyboardLayout()
Retrieve keyboard layout from language string or (if set) config file.
static bool DrawIMECompositionString()
Should we draw the composition string ourself, i.e is this a normal IME?
void CDECL usererror(const char *s,...)
Error handling for fatal user errors.
int wheel
mouse wheel movement
bool UpdateCursorPosition(int x, int y, bool queued_warp)
Update cursor position on mouse movement.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
static ThreadMutex * New()
Create a new mutex.
void HandleKeypress(uint keycode, WChar key)
Handle keyboard input.
byte _dirkeys
1 = left, 2 = up, 4 = right, 8 = down
static ThreadObject * _draw_thread
Thread used to 'draw' to the screen, i.e.
bool fix_at
mouse is moving, but cursor is not (used for scrolling)
void HandleMouseEvents()
Handle a mouse event from the video driver.
#define lengthof(x)
Return the length of an fixed size array.
PauseModeByte _pause_mode
The current pause mode.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
int first_dirty
The first dirty element.
bool AfterBlitterChange()
Callback invoked after the blitter was changed.
static WChar Utf16DecodeSurrogate(uint lead, uint trail)
Convert an UTF-16 surrogate pair to the corresponding Unicode character.
Palette _cur_palette
Current palette.
bool _shift_pressed
Is Shift pressed?
#define DEBUG(name, level,...)
Output a line of debugging information.
Dimension _resolutions[32]
List of resolutions.
virtual Blitter::PaletteAnimation UsePaletteAnimation()=0
Check if the blitter uses palette animation at all.
static void PaintWindow(HDC dc)
Do palette animation and blit to the window.
void Stop()
Stop this driver.
The video driver for windows.
const char * Start(const char *const *param)
Start this driver.
static bool Utf16IsTrailSurrogate(uint c)
Is the given character a lead surrogate code point?
void AcquireBlitterLock()
Acquire any lock(s) required to be held when changing blitters.
void HandleCtrlChanged()
State of CONTROL key has changed.
virtual void Join()=0
Join this thread.
void EditBoxLostFocus()
An edit box lost the input focus.
bool EditBoxInGlobalFocus()
Check if an edit box is in global focus.
Base of the Windows video driver.
Speed of painting drawn video buffer.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam)
Handle WM_IME_COMPOSITION messages.
void MakeDirty(int left, int top, int width, int height)
Mark a particular area dirty.
static void SetCandidatePos(HWND hwnd)
Set the position of the candidate window.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
void NetworkDrawChatMessage()
Draw the chat message-box.
static Palette _local_palette
Local copy of the palette for use in the drawing thread.
#define endof(x)
Get the end element of an fixed size array.
bool in_window
mouse inside this window, determines drawing logic
void ReleaseBlitterLock()
Release any lock(s) required to be held when changing blitters.
bool MakeWindow(bool full_screen)
Instantiate a new window.
Coordinates of a point in 2D.
virtual void WaitForSignal()=0
Wait for a signal to be send.
virtual uint8 GetScreenDepth()=0
Get the screen depth this blitter works for.
#define AS(ap_name, size_x, size_y, min_year, max_year, catchment, noise, maint_cost, ttdpatch_type, class_id, name, preview)
AirportSpec definition for airports with at least one depot.
uint GetCPUCoreCount()
Get number of processor cores in the system, including HyperThreading or similar. ...
static bool Utf16IsLeadSurrogate(uint c)
Is the given character a lead surrogate code point?
void GameSizeChanged()
Size of the application screen changed.
int width
width of the window (number of pixels to the right in x direction)
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
WindowClass window_class
Window class.
virtual void BeginCritical(bool allow_recursive=false)=0
Begin the critical section.
virtual bool Exit()=0
Exit this thread.
int count_dirty
The number of dirty elements.
static void CancelIMEComposition(HWND hwnd)
Clear the current composition string.
virtual Point GetCaretPosition() const
Get the current caret position if an edit box has the focus.
uint32 WChar
Type for wide characters, i.e.
static ThreadMutex * _draw_mutex
Mutex to keep the access to the shared memory controlled.
A Thread Object which works on all our supported OSes.
static bool New(OTTDThreadFunc proc, void *param, ThreadObject **thread=NULL, const char *name=NULL)
Create a thread; proc will be called as first function inside the thread, with optional params...
static void SetCompositionPos(HWND hwnd)
Set position of the composition window to the caret position.
Dimensions (a width and height) of a rectangle in 2D.
Full 8bpp support by OS and hardware.
static bool HasModalProgress()
Check if we are currently in a modal progress state.
int height
Height of the window (number of pixels down in y direction)
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
void UpdateWindows()
Update the continuously changing contents of the windows, such as the viewports.