forked from std-microblock/breeze-shell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmenu_render.cc
More file actions
154 lines (134 loc) · 5.1 KB
/
menu_render.cc
File metadata and controls
154 lines (134 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "menu_render.h"
#include "hooks.h"
#include "shell/utils.h"
#define GLFW_EXPOSE_NATIVE_WIN32
#include "GLFW/glfw3native.h"
#include "Windows.h"
#include "menu_widget.h"
#include "breeze_ui/ui.h"
#include "shell/entry.h"
#include "shell/logger.h"
#include "shell/script/binding_types.hpp"
#include <mutex>
#include <thread>
namespace mb_shell {
std::optional<menu_render *> menu_render::current{};
menu_render menu_render::create(int x, int y, menu menu, bool run_js) {
if (auto res = ui::render_target::init_global(); !res) {
MessageBoxW(NULL, L"Failed to initialize global render target",
L"Error", MB_ICONERROR);
return {nullptr, std::nullopt};
}
static auto rt = []() {
static window_proc_hook glfw_proc_hook;
auto rt = std::make_shared<ui::render_target>();
rt->transparent = true;
rt->no_activate = true;
rt->capture_all_input = true;
rt->decorated = false;
rt->topmost = true;
rt->vsync = config::current->context_menu.vsync;
if (config::current->avoid_resize_ui) {
rt->width = 3840;
rt->height = 2159;
}
if (auto res = rt->init(); !res) {
MessageBoxW(NULL, L"Failed to initialize render target", L"Error",
MB_ICONERROR);
return std::shared_ptr<ui::render_target>{nullptr};
}
glfw_proc_hook.install(rt->hwnd());
SetCapture((HWND)rt->hwnd());
glfw_proc_hook.hooks.push_back([](void *hwnd, void *original_proc,
size_t msg, size_t wparam,
size_t lparam) -> std::optional<int> {
if (msg == WM_MOUSEACTIVATE) {
return MA_NOACTIVATE;
}
return std::nullopt;
});
config::current->apply_fonts_to_nvg(rt->nvg);
return rt;
}();
if (!rt) {
return {nullptr, std::nullopt};
}
auto render = menu_render(rt, std::nullopt);
rt->parent = menu.parent_window;
// get the monitor in which the menu is being shown
auto monitor = MonitorFromPoint({x, y}, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info);
// set the position of the window to fullscreen in this monitor + padding
spdlog::info("Monitor: {} {} {} {}", monitor_info.rcMonitor.left,
monitor_info.rcMonitor.top, monitor_info.rcMonitor.right,
monitor_info.rcMonitor.bottom);
rt->set_position(monitor_info.rcMonitor.left + 1,
monitor_info.rcMonitor.top + 1);
if (!config::current->avoid_resize_ui)
rt->resize(
monitor_info.rcMonitor.right - monitor_info.rcMonitor.left - 2,
monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top - 2);
glfwMakeContextCurrent(rt->window);
glfwSwapInterval(config::current->context_menu.vsync ? 1 : 0);
glfwSetWindowAttrib(rt->window, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
rt->show();
SetCapture((HWND)rt->hwnd());
auto menu_wid = std::make_shared<mouse_menu_widget_main>(
menu,
// convert the x and y to the window coordinates
x - monitor_info.rcMonitor.left, y - monitor_info.rcMonitor.top);
context_menu_hooks::set_active_root_menu_widget(menu_wid->menu_wid);
rt->root->children.push_back(menu_wid);
auto current_js_context =
entry::main_window_loop_hook
.add_task([&]() {
return std::make_shared<js::js_menu_context>(
js::js_menu_context::$from_window(menu.parent_window));
})
.get();
js::menu_info_basic_js menu_info{
.menu = std::make_shared<js::menu_controller>(menu_wid->menu_wid),
.context = current_js_context,
.screenside_button =
std::make_shared<js::screenside_button_controller>(menu_wid),
};
if (run_js) {
spdlog::info("[perf] JS plugins start");
auto before_js = rt->clock.now();
for (auto &listener : menu_callbacks_js) {
listener->operator()(menu_info);
}
spdlog::info("[perf] JS plugins costed {}ms",
std::chrono::duration_cast<std::chrono::milliseconds>(
rt->clock.now() - before_js)
.count());
} else {
spdlog::info("Skipped running JS");
}
spdlog::info("Current menu: {}", menu_render::current.has_value());
return render;
}
menu_render::menu_render(std::shared_ptr<ui::render_target> rt,
std::optional<int> selected_menu)
: rt(std::move(rt)), selected_menu(selected_menu) {
current = this;
}
menu_render::~menu_render() {
if (this->rt) {
current = nullptr;
}
}
menu_render::menu_render(menu_render &&t) {
current = this;
rt = std::move(t.rt);
selected_menu = std::move(t.selected_menu);
}
menu_render &menu_render::operator=(menu_render &&t) {
current = this;
rt = std::move(t.rt);
selected_menu = std::move(t.selected_menu);
return *this;
}
}; // namespace mb_shell