1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci* Copyright 2016 Google Inc.
3cb93a386Sopenharmony_ci*
4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci* found in the LICENSE file.
6cb93a386Sopenharmony_ci*/
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include <windows.h>
9cb93a386Sopenharmony_ci#include <tchar.h>
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
12cb93a386Sopenharmony_ci#include "tools/sk_app/Application.h"
13cb93a386Sopenharmony_ci#include "tools/sk_app/win/Window_win.h"
14cb93a386Sopenharmony_ci#include "tools/timer/Timer.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ciusing sk_app::Application;
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cistatic char* tchar_to_utf8(const TCHAR* str) {
19cb93a386Sopenharmony_ci#ifdef _UNICODE
20cb93a386Sopenharmony_ci    int size = WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), NULL, 0, NULL, NULL);
21cb93a386Sopenharmony_ci    char* str8 = (char*)sk_malloc_throw(size + 1);
22cb93a386Sopenharmony_ci    WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), str8, size, NULL, NULL);
23cb93a386Sopenharmony_ci    str8[size] = '\0';
24cb93a386Sopenharmony_ci    return str8;
25cb93a386Sopenharmony_ci#else
26cb93a386Sopenharmony_ci    return _strdup(str);
27cb93a386Sopenharmony_ci#endif
28cb93a386Sopenharmony_ci}
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci// This file can work with GUI or CONSOLE subsystem types since we define _tWinMain and main().
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_cistatic int main_common(HINSTANCE hInstance, int show, int argc, char**argv);
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ciint APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,
35cb93a386Sopenharmony_ci                       int nCmdShow) {
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci    // convert from lpCmdLine to argc, argv.
38cb93a386Sopenharmony_ci    char* argv[4096];
39cb93a386Sopenharmony_ci    int argc = 0;
40cb93a386Sopenharmony_ci    TCHAR exename[1024], *next;
41cb93a386Sopenharmony_ci    int exenameLen = GetModuleFileName(NULL, exename, SK_ARRAY_COUNT(exename));
42cb93a386Sopenharmony_ci    // we're ignoring the possibility that the exe name exceeds the exename buffer
43cb93a386Sopenharmony_ci    (void)exenameLen;
44cb93a386Sopenharmony_ci    argv[argc++] = tchar_to_utf8(exename);
45cb93a386Sopenharmony_ci    TCHAR* arg = _tcstok_s(lpCmdLine, _T(" "), &next);
46cb93a386Sopenharmony_ci    while (arg != NULL) {
47cb93a386Sopenharmony_ci        argv[argc++] = tchar_to_utf8(arg);
48cb93a386Sopenharmony_ci        arg = _tcstok_s(NULL, _T(" "), &next);
49cb93a386Sopenharmony_ci    }
50cb93a386Sopenharmony_ci    int result = main_common(hInstance, nCmdShow, argc, argv);
51cb93a386Sopenharmony_ci    for (int i = 0; i < argc; ++i) {
52cb93a386Sopenharmony_ci        sk_free(argv[i]);
53cb93a386Sopenharmony_ci    }
54cb93a386Sopenharmony_ci    return result;
55cb93a386Sopenharmony_ci}
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ciint main(int argc, char**argv) {
58cb93a386Sopenharmony_ci    return main_common(GetModuleHandle(NULL), SW_SHOW, argc, argv);
59cb93a386Sopenharmony_ci}
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_cistatic int main_common(HINSTANCE hInstance, int show, int argc, char**argv) {
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    Application* app = Application::Create(argc, argv, (void*)hInstance);
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci    MSG msg;
66cb93a386Sopenharmony_ci    memset(&msg, 0, sizeof(msg));
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci    bool idled = false;
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    // Main message loop
71cb93a386Sopenharmony_ci    while (WM_QUIT != msg.message) {
72cb93a386Sopenharmony_ci        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
73cb93a386Sopenharmony_ci            TranslateMessage(&msg);
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci            if (WM_PAINT == msg.message) {
76cb93a386Sopenharmony_ci                // Ensure that call onIdle at least once per WM_PAINT, or mouse events can
77cb93a386Sopenharmony_ci                // overwhelm the message processing loop, and prevent animation from running.
78cb93a386Sopenharmony_ci                if (!idled) {
79cb93a386Sopenharmony_ci                    app->onIdle();
80cb93a386Sopenharmony_ci                }
81cb93a386Sopenharmony_ci                idled = false;
82cb93a386Sopenharmony_ci            }
83cb93a386Sopenharmony_ci            DispatchMessage(&msg);
84cb93a386Sopenharmony_ci        } else {
85cb93a386Sopenharmony_ci            app->onIdle();
86cb93a386Sopenharmony_ci            idled = true;
87cb93a386Sopenharmony_ci        }
88cb93a386Sopenharmony_ci    }
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci    delete app;
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    return (int)msg.wParam;
93cb93a386Sopenharmony_ci}
94