Skip to content

Commit

Permalink
Merge #102, deferred initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
RMichelsen committed Nov 8, 2023
2 parents 7b24b7e + da2a4ba commit c36190e
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 174 deletions.
155 changes: 78 additions & 77 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
#include "renderer/renderer.h"

struct Context {
int start_x, start_y;
GridSize start_grid_size;
bool start_maximized;
bool start_fullscreen;
bool disable_fullscreen;
Expand Down Expand Up @@ -46,19 +44,13 @@ void ToggleFullscreen(HWND hwnd, Context *context) {
void ProcessMPackMessage(Context *context, mpack_tree_t *tree) {
MPackMessageResult result = MPackExtractMessageResult(tree);

if (result.type == MPackMessageType::Response) {
switch (result.type) {
case MPackMessageType::Response: {
assert(result.response.msg_id <= context->nvim->next_msg_id);
switch (context->nvim->msg_id_to_method[result.response.msg_id]) {
case NvimRequest::vim_get_api_info: {
mpack_node_t top_level_map = mpack_node_array_at(result.params, 1);
mpack_node_t version_map = mpack_node_map_value_at(top_level_map, 0);
int64_t api_level = mpack_node_map_cstr(version_map, "api_level").data->value.i;
assert(api_level > 6);
} break;
case NvimRequest::nvim_eval: {
Vec<char> guifont_buffer;
NvimParseConfig(context->nvim, result.params, &guifont_buffer);

if (!guifont_buffer.empty()) {
bool updated = RendererUpdateGuiFont(context->renderer, guifont_buffer.data(), strlen(guifont_buffer.data()));
if(!updated) {
Expand All @@ -72,45 +64,27 @@ void ProcessMPackMessage(Context *context, mpack_tree_t *tree) {
free(command);
}
}

if (context->start_grid_size.rows != 0 &&
context->start_grid_size.cols != 0) {
PixelSize start_size = RendererGridToPixelSize(context->renderer,
context->start_grid_size.rows, context->start_grid_size.cols);
RECT client_rect;
GetClientRect(context->hwnd, &client_rect);
MoveWindow(context->hwnd, client_rect.left, client_rect.top,
start_size.width, start_size.height, false);
}

// Attach the renderer now that the window size is determined
RendererAttach(context->renderer);
auto [rows, cols] = RendererPixelsToGridSize(context->renderer,
context->renderer->pixel_size.width, context->renderer->pixel_size.height);
NvimSendUIAttach(context->nvim, rows, cols);

if (context->start_x != CW_USEDEFAULT ||
context->start_y != CW_USEDEFAULT) {
SetWindowPos(context->hwnd, NULL,
context->start_x, context->start_y,
0, 0,
SWP_NOSIZE | SWP_NOREDRAW | SWP_NOACTIVATE |
SWP_NOOWNERZORDER | SWP_NOZORDER);
}
if (context->start_fullscreen) {
ToggleFullscreen(context->hwnd, context);
}
} break;
case NvimRequest::nvim_input:
case NvimRequest::nvim_input_mouse:
case NvimRequest::nvim_command: {
} break;
case NvimRequest::vim_get_api_info:
case NvimRequest::nvim_input:
case NvimRequest::nvim_input_mouse:
case NvimRequest::nvim_command: {
} break;
}
}
else if (result.type == MPackMessageType::Notification) {
} break;
case MPackMessageType::Notification: {
if (MPackMatchString(result.notification.name, "redraw")) {
RendererRedraw(context->renderer, result.params, context->start_maximized);
}
} break;
case MPackMessageType::Request: {
if (MPackMatchString(result.request.method, "vimenter")) {
// nvim has read user init file, we can now request info if we want
// like additional startup settings or something else
NvimSendResponse(context->nvim, result.request.msg_id);
NvimQueryConfig(context->nvim);
}
} break;
}
}

Expand Down Expand Up @@ -400,7 +374,7 @@ BOOL ShouldUseDarkMode()
return false;
}

int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_line, int n_cmd_show) {
int WINAPI wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR p_cmd_line, _In_ int n_cmd_show) {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);

int n_args;
Expand All @@ -410,16 +384,16 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
bool disable_ligatures = false;
bool disable_fullscreen = false;
float linespace_factor = 1.0f;
int64_t rows = 0;
int64_t cols = 0;
int64_t x = CW_USEDEFAULT;
int64_t y = CW_USEDEFAULT;

constexpr int MAX_NVIM_CMD_LINE_SIZE = 32767;
wchar_t nvim_command_line[MAX_NVIM_CMD_LINE_SIZE] = {};
wcscpy_s(nvim_command_line, MAX_NVIM_CMD_LINE_SIZE, L"nvim --embed");
int cmd_line_size_left = MAX_NVIM_CMD_LINE_SIZE - wcslen(L"nvim --embed");

int64_t start_rows = 0;
int64_t start_cols = 0;
int64_t start_pos_x = CW_USEDEFAULT;
int64_t start_pos_y = CW_USEDEFAULT;

struct WArg {
wchar_t *arg;
size_t len;
};
Vec<WArg> nvim_args;

// Skip argv[0]
for(int i = 1; i < n_args; ++i) {
Expand All @@ -437,13 +411,13 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
}
else if(!wcsncmp(cmd_line_args[i], L"--geometry=", wcslen(L"--geometry="))) {
wchar_t *end_ptr;
cols = wcstol(&cmd_line_args[i][11], &end_ptr, 10);
rows = wcstol(end_ptr + 1, nullptr, 10);
start_cols = wcstol(&cmd_line_args[i][11], &end_ptr, 10);
start_rows = wcstol(end_ptr + 1, nullptr, 10);
}
else if(!wcsncmp(cmd_line_args[i], L"--position=", wcslen(L"--position="))) {
wchar_t *end_ptr;
x = wcstol(&cmd_line_args[i][11], &end_ptr, 10);
y = wcstol(end_ptr + 1, nullptr, 10);
start_pos_x = wcstol(&cmd_line_args[i][11], &end_ptr, 10);
start_pos_y = wcstol(end_ptr + 1, nullptr, 10);
}
else if(!wcsncmp(cmd_line_args[i], L"--linespace-factor=", wcslen(L"--linespace-factor="))) {
wchar_t *end_ptr;
Expand All @@ -454,15 +428,10 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
}
// Otherwise assume the argument is a filename to open
else {
size_t arg_size = wcslen(cmd_line_args[i]);
if(arg_size <= (cmd_line_size_left + 3)) {
wcscat_s(nvim_command_line, cmd_line_size_left, L" \"");
cmd_line_size_left -= 2;
wcscat_s(nvim_command_line, cmd_line_size_left, cmd_line_args[i]);
cmd_line_size_left -= arg_size;
wcscat_s(nvim_command_line, cmd_line_size_left, L"\"");
cmd_line_size_left -= 1;
}
nvim_args.push_back(WArg{
.arg = cmd_line_args[i],
.len = wcslen(cmd_line_args[i])
});
}
}

Expand All @@ -473,10 +442,10 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
.style = CS_HREDRAW | CS_VREDRAW,
.lpfnWndProc = WndProc,
.hInstance = instance,
.hIcon = static_cast<HICON>(LoadImage(GetModuleHandle(NULL), L"NVIM_ICON", IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, 0)),
.hIcon = static_cast<HICON>(LoadImage(GetModuleHandle(NULL), L"NVIM_ICON", IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, 0)),
.hCursor = LoadCursor(NULL, IDC_ARROW),
.lpszClassName = window_class_name,
.hIconSm = static_cast<HICON>(LoadImage(GetModuleHandle(NULL), L"NVIM_ICON", IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, 0))
.hIconSm = static_cast<HICON>(LoadImage(GetModuleHandle(NULL), L"NVIM_ICON", IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, 0))
};

if (!RegisterClassEx(&window_class)) {
Expand All @@ -486,12 +455,6 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
Nvim nvim {};
Renderer renderer {};
Context context {
.start_x = static_cast<int>(x),
.start_y = static_cast<int>(y),
.start_grid_size {
.rows = static_cast<int>(rows),
.cols = static_cast<int>(cols)
},
.start_maximized = start_maximized,
.start_fullscreen = start_fullscreen,
.disable_fullscreen = disable_fullscreen,
Expand Down Expand Up @@ -525,10 +488,47 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
BOOL should_use_dark_mode = ShouldUseDarkMode();
DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &should_use_dark_mode, sizeof(BOOL));
RendererInitialize(&renderer, hwnd, disable_ligatures, linespace_factor, context.saved_dpi_scaling);

// Prepare nvim command line
size_t nvim_command_len = wcslen(L"nvim --embed");
for (const auto& nvim_command_arg : nvim_args) {
nvim_command_len += wcslen(L" \"\"") + nvim_command_arg.len;
}
wchar_t *nvim_command_line = static_cast<wchar_t *>(malloc(sizeof(wchar_t) * (nvim_command_len + 1)));
int cur_len = _snwprintf_s(nvim_command_line, nvim_command_len + 1, nvim_command_len, L"nvim --embed");
for (const auto& [arg, len] : nvim_args) {
cur_len += _snwprintf_s(nvim_command_line + cur_len, nvim_command_len + 1 - cur_len, nvim_command_len - cur_len,
L" \"%s\"", arg, static_cast<uint32_t>(len));
}

NvimInitialize(&nvim, nvim_command_line, hwnd);

// Forceably update the window to prevent any frames where the window is blank. Windows API docs
// specify that SetWindowPos should be called with these arguments after SetWindowLong is called.
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
UINT window_flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED;
int window_w = 0, window_h = 0;

if (start_rows != 0 && start_cols != 0) {
PixelSize start_size = RendererGridToPixelSize(context.renderer,
start_rows, start_cols);
window_w = start_size.width;
window_h = start_size.height;
window_flags = window_flags & ~SWP_NOSIZE;
}
if (start_pos_x != CW_USEDEFAULT || start_pos_y != CW_USEDEFAULT) {
window_flags = window_flags & ~SWP_NOMOVE;
}
SetWindowPos(hwnd, HWND_TOP, start_pos_x, start_pos_y, window_w, window_h, window_flags);

if (start_fullscreen) {
ToggleFullscreen(context.hwnd, &context);
}

// Attach the renderer now that the window size is determined
RendererAttach(context.renderer);
auto [rows, cols] = RendererPixelsToGridSize(context.renderer,
context.renderer->pixel_size.width, context.renderer->pixel_size.height);
NvimSendUIAttach(context.nvim, rows, cols);

MSG msg;
uint32_t previous_width = 0, previous_height = 0;
Expand All @@ -551,6 +551,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, PWSTR p_cmd_lin
NvimShutdown(&nvim);
UnregisterClass(window_class_name, instance);
DestroyWindow(hwnd);
free(nvim_command_line);

return nvim.exit_code;
}
Loading

0 comments on commit c36190e

Please sign in to comment.