9 |
10 | Breeze 是专为 Windows 10/11 设计的现代化**次世代右键菜单解决方案**。
11 |
12 | ## 丝滑流畅
13 |
14 | Breeze 以交互动画为核心设计理念。
15 |
16 |
17 |
18 | ## 无限扩展
19 |
20 | 通过嵌入式 JavaScript 脚本 API,您可以用寥寥数行代码为右键菜单增添全新功能。
21 |
22 | ```javascript
23 | shell.menu_controller.add_menu_listener((e) => {
24 | e.menu.add({
25 | type: "button",
26 | name: "Shuffle Buttons",
27 | action: () => {
28 | for (const item of menus) {
29 | item.set_position(Math.floor(menus.length * Math.random()));
30 | }
31 | },
32 | }, 0);
33 | });
34 | ```
35 |
36 | [查看完整 API 文档 →](./src/shell/script/binding_types.d.ts)
37 |
38 | ## 轻量高速
39 |
40 | Breeze 基于自研 breeze_ui 框架实现,这是一个跨平台、简洁优雅、动画友好的现代 C++ UI 库,支持 NanoVG 和 ThorVG 双渲染后端。这使得 Breeze 能在约 2MB 的体积下实现精致的视觉体验。
41 |
42 | # 立即体验
43 |
44 | 从 Releases 下载,然后解压压缩包并运行 `breeze.exe`
45 |
46 | # 构建指南
47 |
48 | 本项目使用 xmake 构建系统。请先安装 xmake,在项目根目录执行 `xmake` 命令并按提示操作。支持 clang-cl 和 MSVC 2019+ 编译器。
49 |
50 | # 开发指南
51 |
52 | 首次构建成功后,可使用 VSCode 打开项目进行开发。建议安装 clangd 插件以获得完整的代码智能提示。
53 |
--------------------------------------------------------------------------------
/src/shell/script/ts/src/config_page/contexts.tsx:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 |
3 | // Context for context menu configuration
4 | export const ContextMenuContext = createContext<{ config: any; update: (c: any) => void } | null>(null);
5 |
6 | // Context for debug console state
7 | export const DebugConsoleContext = createContext<{ value: boolean; update: (v: boolean) => void } | null>(null);
8 |
9 | // Context for plugin load order
10 | export const PluginLoadOrderContext = createContext<{ order: any[]; update: (o: any[]) => void } | null>(null);
11 |
12 | // Context for update data
13 | export const UpdateDataContext = createContext<{ updateData: any; setUpdateData: (d: any) => void } | null>(null);
14 |
15 | // Context for notifications (error and loading messages)
16 | export const NotificationContext = createContext<{
17 | errorMessage: string | null;
18 | setErrorMessage: (msg: string | null) => void;
19 | loadingMessage: string | null;
20 | setLoadingMessage: (msg: string | null) => void;
21 | } | null>(null);
22 |
23 | // Context for plugin source management
24 | export const PluginSourceContext = createContext<{
25 | currentPluginSource: string;
26 | setCurrentPluginSource: (source: string) => void;
27 | cachedPluginIndex: any;
28 | setCachedPluginIndex: (index: any) => void;
29 | } | null>(null);
--------------------------------------------------------------------------------
/src/shell/res_string_loader.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | namespace mb_shell {
8 | struct res_string_loader {
9 | struct res_string_identifier {
10 | size_t id;
11 | size_t module;
12 |
13 | bool operator<=>(const res_string_identifier &other) const {
14 | return std::tie(module, id) < std::tie(other.module, other.id);
15 | }
16 |
17 | bool operator==(const res_string_identifier &other) const {
18 | return module == other.module && id == other.id;
19 | }
20 | };
21 |
22 | using string_id = std::variant;
23 | static string_id string_to_id(std::wstring str);
24 | static std::string string_to_id_string(std::wstring str);
25 | static std::string string_from_id_string(const std::string &str);
26 | static std::vector
27 | get_all_ids_of_string(const std::wstring &str);
28 | static void init_hook();
29 | static void init_known_strings();
30 |
31 | static void init();
32 | };
33 | } // namespace mb_shell
34 |
35 | namespace std {
36 | template <> struct hash {
37 | size_t operator()(const mb_shell::res_string_loader::res_string_identifier
38 | &id) const noexcept {
39 | return std::hash{}(id.id) ^ std::hash{}(id.module);
40 | }
41 | };
42 | } // namespace std
--------------------------------------------------------------------------------
/src/shell/script/ts/src/compats/explorer_compat.ts:
--------------------------------------------------------------------------------
1 | import { menu_controller, value_reset } from "mshell"
2 |
3 | export const doExplorerCompat = () => {
4 | menu_controller.add_menu_listener(ctx => {
5 | for (const items of ctx.menu.items) {
6 | const data = items.data()
7 | if (data.name_resid === '10580@SHELL32.dll' /* 清空回收站 */ || data.name === '清空回收站') {
8 | items.set_data({
9 | disabled: false
10 | })
11 | }
12 |
13 | if (data.name?.startsWith('NVIDIA ')) {
14 | items.set_data({
15 | icon_svg: ``,
16 | icon_bitmap: new value_reset()
17 | })
18 | }
19 | }
20 | })
21 | }
--------------------------------------------------------------------------------
/src/shell/paint_color.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | struct NVGcolor;
6 |
7 | namespace ui {
8 | struct nanovg_context;
9 | }
10 |
11 | namespace mb_shell {
12 |
13 | struct rgba_color {
14 | float r = 0;
15 | float g = 0;
16 | float b = 0;
17 | float a = 1;
18 |
19 | rgba_color() = default;
20 | rgba_color(float r, float g, float b, float a = 1)
21 | : r(r), g(g), b(b), a(a) {}
22 |
23 | static rgba_color from_string(const std::string &str);
24 | std::string to_string() const;
25 |
26 | rgba_color(const NVGcolor &color);
27 | NVGcolor nvg() const;
28 | // we want to pass this directly into fillColor( NVGcolor color)
29 | operator NVGcolor() const;
30 | };
31 |
32 | struct paint_color {
33 | enum class type {
34 | solid,
35 | linear_gradient,
36 | radial_gradient
37 | } type = type::solid;
38 | rgba_color color = {0, 0, 0, 1}; // RGBA
39 | rgba_color color2 = {0, 0, 0, 1}; // RGBA for gradients
40 | float radius = 0;
41 | float radius2 = 0;
42 | float angle = 0;
43 | void apply_to_ctx(ui::nanovg_context &ctx, float x, float y, float width,
44 | float height) const;
45 |
46 | // supported patterns:
47 | // #RRGGBBAA
48 | // #RRGGBB
49 | // #RRGGBB00
50 | // rgba(R, G, B, A)
51 | // rgb(R, G, B)
52 | // linear-gradient(angle, color1, color2)
53 | // radial-gradient(radius, color1, color2)
54 | // solid(color)
55 | static paint_color from_string(const std::string &str);
56 | std::string to_string() const;
57 | };
58 | } // namespace mb_shell
--------------------------------------------------------------------------------
/dependencies/breeze-ui.lua:
--------------------------------------------------------------------------------
1 | package("breeze-glfw")
2 | set_base("glfw")
3 | set_urls("https://github.com/breeze-shell/glfw.git")
4 | add_versions("latest", "master")
5 |
6 | local BREEZE_UI_VER = "2025.12.14"
7 | local BREEZE_UI_HASH = "c197c45a1dc21590abec30e21327b53511c55a41"
8 |
9 | package("breeze-nanosvg")
10 | add_urls("https://github.com/std-microblock/breeze-ui.git")
11 | add_versions(BREEZE_UI_VER, BREEZE_UI_HASH)
12 |
13 | set_kind("library", {headeronly = true})
14 | set_description("The breeze-nanosvg package")
15 |
16 | on_install("windows", function (package)
17 | import("package.tools.xmake").install(package)
18 | end)
19 |
20 | package("breeze-nanovg")
21 | add_urls("https://github.com/std-microblock/breeze-ui.git")
22 | add_versions(BREEZE_UI_VER, BREEZE_UI_HASH)
23 |
24 | set_description("The breeze-nanovg package")
25 |
26 | add_configs("shared", {description = "Build shared library.", default = false, type = "boolean", readonly = true})
27 |
28 | on_install("windows", function (package)
29 | import("package.tools.xmake").install(package)
30 | end)
31 |
32 |
33 | package("breeze-ui")
34 | add_urls("https://github.com/std-microblock/breeze-ui.git")
35 | add_versions(BREEZE_UI_VER, BREEZE_UI_HASH)
36 | add_deps("breeze-glfw", "glad", "nanovg", "breeze-nanosvg", {
37 | public = true
38 | })
39 | add_configs("shared", {description = "Build shared library.", default = false, type = "boolean", readonly = true})
40 |
41 | if is_plat("windows") then
42 | add_syslinks("dwmapi", "shcore")
43 | end
44 |
45 | on_install("windows", function (package)
46 | import("package.tools.xmake").install(package)
47 | end)
48 |
49 |
--------------------------------------------------------------------------------
/src/shell/script/ts/src/menu/constants.ts:
--------------------------------------------------------------------------------
1 | import * as shell from "mshell"
2 |
3 | export const languages = {
4 | 'zh-CN': {
5 | },
6 | 'en-US': {
7 | '管理 Breeze Shell': 'Manage Breeze Shell',
8 | '插件市场 / 更新本体': 'Plugin Market / Update Shell',
9 | '加载中...': 'Loading...',
10 | '更新中...': 'Updating...',
11 | '新版本已下载,将于下次重启资源管理器生效': 'New version downloaded, will take effect next time the file manager is restarted',
12 | '更新失败: ': 'Update failed: ',
13 | '插件安装成功: ': 'Plugin installed: ',
14 | '当前源: ': 'Current source: ',
15 | '删除': 'Delete',
16 | '版本: ': 'Version: ',
17 | '作者: ': 'Author: '
18 | }
19 | }
20 |
21 | export const ICON_EMPTY = new shell.value_reset()
22 | export const ICON_CHECKED = ``
23 | export const ICON_CHANGE = ``
24 | export const ICON_REPAIR = ``
--------------------------------------------------------------------------------
/.github/workflows/xmake.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | permissions: write-all
3 |
4 | on:
5 | push:
6 | branches: [ "master" ]
7 | pull_request:
8 | branches: [ "master" ]
9 | release:
10 | types: [created]
11 |
12 | jobs:
13 | build:
14 | runs-on: windows-2025
15 |
16 | steps:
17 | - uses: actions/checkout@v4
18 | with:
19 | submodules: recursive
20 |
21 | - uses: xmake-io/github-action-setup-xmake@v1
22 | with:
23 | xmake-version: branch@master
24 | actions-cache-folder: '.xmake-cache'
25 | actions-cache-key: 'ci'
26 | package-cache: true
27 | package-cache-key: windows-2025
28 | # build-cache: true
29 | # build-cache-key: ${{ matrix.os }}-${{ matrix.build_type }}
30 |
31 | - name: Xmake configure
32 | run: |
33 | xmake config -v --yes --toolchain=clang-cl --mode=releasedbg
34 |
35 | - name: build-releasedbg
36 | run: |
37 | xmake b --yes --verbose inject
38 | xmake b --yes --verbose shell
39 |
40 | - name: Upload Artifacts
41 | uses: actions/upload-artifact@v4.6.0
42 | with:
43 | path: ./build/windows/x64/
44 | name: windows-build
45 |
46 | - name: Create Archive
47 | if: github.event_name == 'release'
48 | run: |
49 | Compress-Archive -Path ./build/windows/* -DestinationPath windows-build-pdb.zip
50 | Remove-Item -Path ./build/windows/x64/releasedbg/*.pdb -Force
51 | Remove-Item -Path ./build/windows/x64/releasedbg/*.lib -Force
52 | Compress-Archive -Path ./build/windows/* -DestinationPath windows-build.zip
53 |
54 | - name: Upload Release Assets
55 | if: github.event_name == 'release'
56 | uses: softprops/action-gh-release@v1
57 | with:
58 | files: |
59 | windows-build.zip
60 | windows-build-pdb.zip
61 | token: ${{ secrets.GITHUB_TOKEN }}
62 |
--------------------------------------------------------------------------------
/src/shell/window_proc_hook.cc:
--------------------------------------------------------------------------------
1 | #include "window_proc_hook.h"
2 | #include "blook/blook.h"
3 |
4 | #include
5 | #include
6 |
7 | namespace mb_shell {
8 | static std::unordered_set hooked_windows;
9 |
10 | void window_proc_hook::install(void *hwnd) {
11 | if (installed)
12 | uninstall();
13 | this->hwnd = hwnd;
14 | this->original_proc = (void *)GetWindowLongPtrW((HWND)hwnd, GWLP_WNDPROC);
15 |
16 | this->hooked_proc = (void *)blook::Function::into_function_pointer(
17 | [this](HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
18 | SetWindowLongPtrW((HWND)hwnd, GWLP_WNDPROC,
19 | (LONG_PTR)this->original_proc);
20 |
21 | std::optional callOriginal = std::nullopt;
22 | for (auto &f : this->hooks) {
23 | if (!callOriginal)
24 | callOriginal = f(hwnd, this->original_proc, msg, wp, lp);
25 | }
26 |
27 | while (!this->tasks.empty()) {
28 | this->tasks.front()();
29 | this->tasks.pop();
30 | }
31 |
32 | SetWindowLongPtrW((HWND)hwnd, GWLP_WNDPROC,
33 | (LONG_PTR)this->hooked_proc);
34 |
35 | return callOriginal ? *callOriginal
36 | : CallWindowProcW((WNDPROC)this->original_proc,
37 | hwnd, msg, wp, lp);
38 | });
39 |
40 | SetWindowLongPtrW((HWND)hwnd, GWLP_WNDPROC, (LONG_PTR)this->hooked_proc);
41 | installed = true;
42 | }
43 |
44 | void window_proc_hook::uninstall() {
45 | SetWindowLongPtrW((HWND)hwnd, GWLP_WNDPROC, (LONG_PTR)original_proc);
46 | installed = false;
47 | }
48 | window_proc_hook::~window_proc_hook() {
49 | if (installed) {
50 | uninstall();
51 | }
52 | }
53 | void window_proc_hook::send_null() {
54 | if (hwnd) {
55 | PostMessageW((HWND)hwnd, WM_NULL, 0, 0);
56 | }
57 | }
58 | } // namespace mb_shell
--------------------------------------------------------------------------------
/src/shell/contextmenu/contextmenu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "breeze_ui/nanovg_wrapper.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | namespace mb_shell {
13 | struct menu_item;
14 | struct menu_widget;
15 | struct menu_render;
16 | struct menu {
17 | std::vector items;
18 | void *parent_window = nullptr;
19 | bool is_top_level = false;
20 |
21 | static menu
22 | construct_with_hmenu(HMENU hMenu, HWND hWnd, bool is_top = true,
23 | // This is for handling submenus; messages are required
24 | // to be forwarded to IContextMenu2::HandleMenuMsg for
25 | // submenus and owner-draw menus to work properly
26 | std::function
27 | HandleMenuMsg = {});
28 | };
29 |
30 | std::optional
31 | track_popup_menu(menu menu, int x, int y,
32 | std::function on_before_show = {},
33 | bool run_js = true);
34 |
35 | struct owner_draw_menu_info {
36 | HBITMAP bitmap;
37 | int width, height;
38 | };
39 |
40 | struct menu_item {
41 | enum class type {
42 | button,
43 | spacer,
44 | } type = type::button;
45 |
46 | std::optional owner_draw{};
47 | std::optional name;
48 | std::optional> action;
49 | std::optional)>> submenu;
50 | std::optional icon_bitmap;
51 | std::optional icon_svg;
52 | std::optional hotkey;
53 | bool icon_updated = false;
54 | bool disabled = false;
55 |
56 | // the two below are only for information; set them changes nothing
57 | std::optional wID;
58 | std::optional name_resid;
59 | std::optional origin_name;
60 | };
61 | } // namespace mb_shell
--------------------------------------------------------------------------------
/src/shell/script/ts/src/compats/onecommander_compat.ts:
--------------------------------------------------------------------------------
1 | import * as shell from "mshell";
2 | export const doOneCommanderCompat = () => {
3 | shell.menu_controller.add_menu_listener(m => {
4 | const do_action = (keys: string[]) => () => {
5 | m.menu.close();
6 | shell.infra.setTimeout(() => {
7 | shell.win32.simulate_hotkeys(keys);
8 | }, 50);
9 | shell.infra.setTimeout(() => {
10 | shell.win32.simulate_hotkeys(keys);
11 | }, 70);
12 | shell.infra.setTimeout(() => {
13 | shell.win32.simulate_hotkeys(keys);
14 | }, 100);
15 | }
16 |
17 | for (const i of m.menu.items) {
18 | if (i.data().name === "重命名" || i.data().name === "Rename") {
19 | i.set_data({
20 | action: do_action(['f2'])
21 | })
22 | }
23 | }
24 |
25 | const fill = shell.breeze.is_light_theme() ? "fill=\"#000000\"" : "fill=\"#FFFFFF\"";
26 | const zh = shell.breeze.user_language().startsWith('zh');
27 | const NEW_NAME = zh ? "新建" : "New";
28 | const CREATE_FOLDER_NAME = zh ? "文件夹" : "Folder";
29 | const CREATE_FILE_NAME = zh ? "文件" : "File";
30 | m.menu.append_item_after({
31 | name: NEW_NAME,
32 | submenu(m) {
33 | m.append_item({
34 | name: CREATE_FOLDER_NAME,
35 | action: do_action(['ctrl', 'shift', 'n']),
36 | icon_svg: ``
37 | })
38 | m.append_item({
39 | name: CREATE_FILE_NAME,
40 | action: do_action(['ctrl', 'n']),
41 | icon_svg: ``
42 | })
43 | }
44 | }, -2)
45 | })
46 | }
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/shell/script/ts/src/jsx.d.ts:
--------------------------------------------------------------------------------
1 | import { breeze_paint } from "mshell";
2 |
3 | declare module 'react' {
4 | namespace JSX {
5 | interface IntrinsicElements {
6 | flex: {
7 | padding?: number;
8 | paddingTop?: number;
9 | paddingRight?: number;
10 | paddingBottom?: number;
11 | paddingLeft?: number;
12 | backgroundColor?: string;
13 | borderColor?: string;
14 | borderRadius?: number;
15 | borderWidth?: number;
16 | backgroundPaint?: breeze_paint;
17 | borderPaint?: breeze_paint;
18 | onClick?: (key: number) => void;
19 | onMouseEnter?: () => void;
20 | onMouseLeave?: () => void;
21 | onMouseDown?: () => void;
22 | onMouseUp?: () => void;
23 | onMouseMove?: (x: number, y: number) => void;
24 | justifyContent?: 'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly';
25 | alignItems?: 'start' | 'center' | 'end' | 'stretch';
26 | horizontal?: boolean;
27 | children?: React.ReactNode | React.ReactNode[];
28 | key?: string | number;
29 | animatedVars?: string[];
30 | x?: number;
31 | y?: number;
32 | width?: number;
33 | height?: number;
34 | autoSize?: boolean;
35 | gap?: number;
36 | flexGrow?: number;
37 | flexShrink?: number;
38 | maxHeight?: number;
39 | enableScrolling?: boolean;
40 | enableChildClipping?: boolean;
41 | cropOverflow?: boolean;
42 | },
43 | text: {
44 | text?: string[] | string;
45 | fontSize?: number;
46 | color?: string;
47 | key?: string | number;
48 | animatedVars?: string[];
49 | x?: number;
50 | y?: number;
51 | width?: number;
52 | height?: number;
53 | maxWidth?: number;
54 | },
55 | img: {
56 | svg?: string;
57 | key?: string | number;
58 | animatedVars?: string[];
59 | x?: number;
60 | y?: number;
61 | width?: number;
62 | height?: number;
63 | },
64 | spacer: {
65 | size?: number;
66 | key?: string | number;
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/shell/script/ts/src/entry.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | globalThis.h = React.createElement
3 | globalThis.Fragment = React.Fragment
4 |
5 | import * as shell from "mshell"
6 | import { plugin } from "./plugin";
7 |
8 | import { createRenderer } from "./react/renderer";
9 | import { showConfigPage } from "./config_page";
10 | import { doCompats } from "./compats";
11 |
12 | const SVG_CONFIG = ``
13 |
14 | // remove possibly existing shell_old.dll if able to
15 | if (shell.fs.exists(shell.breeze.data_directory() + '/shell_old.dll')) {
16 | try {
17 | shell.fs.remove(shell.breeze.data_directory() + '/shell_old.dll')
18 | } catch (e) {
19 | shell.println('Failed to remove old shell.dll: ', e)
20 | }
21 | }
22 | shell.menu_controller.add_menu_listener(ctx => {
23 | if (ctx.context.folder_view?.current_path.startsWith(shell.breeze.data_directory().replaceAll('/', '\\'))) {
24 | ctx.menu.prepend_menu({
25 | action() {
26 | showConfigPage()
27 | },
28 | name: "Breeze Config",
29 | icon_svg: SVG_CONFIG
30 | })
31 | }
32 |
33 | if (shell.breeze.should_show_settings_button())
34 | ctx.screenside_button.add_button(SVG_CONFIG, () => {
35 | ctx.menu.close()
36 | showConfigPage()
37 | })
38 | })
39 |
40 | doCompats();
41 |
42 | globalThis.plugin = plugin as any
43 | globalThis.React = React
44 | globalThis.createRenderer = createRenderer
45 | globalThis.showConfigPage = showConfigPage
--------------------------------------------------------------------------------
/src/shell/taskbar/taskbar.cc:
--------------------------------------------------------------------------------
1 | #include "taskbar.h"
2 | #include "breeze_ui/widget.h"
3 |
4 | #include "taskbar_widget.h"
5 |
6 | #include
7 |
8 | #include "shell/config.h"
9 |
10 | namespace mb_shell {
11 | std::expected taskbar_render::init() {
12 | rt.transparent = true;
13 | rt.topmost = true;
14 | rt.decorated = false;
15 | rt.title = "Breeze Shell Taskbar";
16 | if (auto res = rt.init(); !res) {
17 | return std::unexpected(res.error());
18 | }
19 |
20 | std::println("Taskbar Monitor: {}, {}, {}, {}", monitor.rcMonitor.left,
21 | monitor.rcMonitor.top, monitor.rcMonitor.right,
22 | monitor.rcMonitor.bottom);
23 |
24 | int height = (monitor.rcMonitor.bottom - monitor.rcMonitor.top) / 20;
25 | rt.show();
26 | config::current->apply_fonts_to_nvg(rt.nvg);
27 |
28 | bool top = position == menu_position::top;
29 |
30 | rt.resize(monitor.rcMonitor.right - monitor.rcMonitor.left, height);
31 | if (top) {
32 | rt.set_position(monitor.rcMonitor.left, monitor.rcMonitor.top);
33 | } else {
34 | rt.set_position(monitor.rcMonitor.left,
35 | monitor.rcMonitor.bottom - height);
36 | }
37 |
38 | APPBARDATA abd = {sizeof(APPBARDATA)};
39 | abd.hWnd = (HWND)rt.hwnd();
40 | abd.uEdge = top ? ABE_TOP : ABE_BOTTOM;
41 | abd.rc =
42 | top ? RECT{monitor.rcMonitor.left, monitor.rcMonitor.top,
43 | monitor.rcMonitor.right, monitor.rcMonitor.top + height}
44 | : RECT{monitor.rcMonitor.left, monitor.rcMonitor.bottom - height,
45 | monitor.rcMonitor.right, monitor.rcMonitor.bottom};
46 |
47 | if (SHAppBarMessage(ABM_NEW, &abd) == 0) {
48 | return std::unexpected("Failed to register taskbar app");
49 | }
50 |
51 | SHAppBarMessage(ABM_QUERYPOS, &abd);
52 | SHAppBarMessage(ABM_SETPOS, &abd);
53 | rt.set_position(abd.rc.left, abd.rc.top);
54 | abd.lParam = TRUE;
55 | SHAppBarMessage(ABM_ACTIVATE, &abd);
56 | SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
57 |
58 | auto taskbar = rt.root->emplace_child();
59 | taskbar->width->reset_to(
60 | (monitor.rcMonitor.right - monitor.rcMonitor.left) / rt.dpi_scale);
61 | taskbar->height->reset_to(height);
62 |
63 | return {};
64 | }
65 | } // namespace mb_shell
--------------------------------------------------------------------------------
/src/shell/script/quickjs/libregexp-opcode.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Regular Expression Engine
3 | *
4 | * Copyright (c) 2017-2018 Fabrice Bellard
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | #ifdef DEF
26 |
27 | DEF(invalid, 1) /* never used */
28 | DEF(char8, 2) /* 7 bits in fact */
29 | DEF(char16, 3)
30 | DEF(char32, 5)
31 | DEF(dot, 1)
32 | DEF(any, 1) /* same as dot but match any character including line terminator */
33 | DEF(line_start, 1)
34 | DEF(line_end, 1)
35 | DEF(goto, 5)
36 | DEF(split_goto_first, 5)
37 | DEF(split_next_first, 5)
38 | DEF(match, 1)
39 | DEF(save_start, 2) /* save start position */
40 | DEF(save_end, 2) /* save end position, must come after saved_start */
41 | DEF(save_reset, 3) /* reset save positions */
42 | DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
43 | DEF(push_i32, 5) /* push integer on the stack */
44 | DEF(drop, 1)
45 | DEF(word_boundary, 1)
46 | DEF(not_word_boundary, 1)
47 | DEF(back_reference, 2)
48 | DEF(backward_back_reference, 2) /* must come after back_reference */
49 | DEF(range, 3) /* variable length */
50 | DEF(range32, 3) /* variable length */
51 | DEF(lookahead, 5)
52 | DEF(negative_lookahead, 5)
53 | DEF(push_char_pos, 1) /* push the character position on the stack */
54 | DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
55 | DEF(prev, 1) /* go to the previous char */
56 | DEF(simple_greedy_quant, 17)
57 |
58 | #endif /* DEF */
59 |
--------------------------------------------------------------------------------
/src/shell/script/quickjs/quickjs-c-atomics.h:
--------------------------------------------------------------------------------
1 | /*
2 | * QuickJS C atomics definitions
3 | *
4 | * Copyright (c) 2023 Marcin Kolny
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | #if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
26 | // Use GCC builtins for version < 4.9
27 | # if((__GNUC__ << 16) + __GNUC_MINOR__ < ((4) << 16) + 9)
28 | # define GCC_BUILTIN_ATOMICS
29 | # endif
30 | #endif
31 |
32 | #ifdef GCC_BUILTIN_ATOMICS
33 | #define atomic_fetch_add(obj, arg) \
34 | __atomic_fetch_add(obj, arg, __ATOMIC_SEQ_CST)
35 | #define atomic_compare_exchange_strong(obj, expected, desired) \
36 | __atomic_compare_exchange_n(obj, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
37 | #define atomic_exchange(obj, desired) \
38 | __atomic_exchange_n (obj, desired, __ATOMIC_SEQ_CST)
39 | #define atomic_load(obj) \
40 | __atomic_load_n(obj, __ATOMIC_SEQ_CST)
41 | #define atomic_store(obj, desired) \
42 | __atomic_store_n(obj, desired, __ATOMIC_SEQ_CST)
43 | #define atomic_fetch_or(obj, arg) \
44 | __atomic_fetch_or(obj, arg, __ATOMIC_SEQ_CST)
45 | #define atomic_fetch_xor(obj, arg) \
46 | __atomic_fetch_xor(obj, arg, __ATOMIC_SEQ_CST)
47 | #define atomic_fetch_and(obj, arg) \
48 | __atomic_fetch_and(obj, arg, __ATOMIC_SEQ_CST)
49 | #define atomic_fetch_sub(obj, arg) \
50 | __atomic_fetch_sub(obj, arg, __ATOMIC_SEQ_CST)
51 | #define _Atomic
52 | #else
53 | #include
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/shell/script/ts/src/config_page/index.ts:
--------------------------------------------------------------------------------
1 | // Export all components and utilities from the config module
2 | export { ConfigApp as default } from './ConfigApp';
3 |
4 | // Export individual components
5 | export { default as Sidebar } from './Sidebar';
6 | export { default as ContextMenuConfig } from './ContextMenuConfig';
7 | export { default as UpdatePage } from './UpdatePage';
8 | export { default as PluginStore } from './PluginStore';
9 | export { default as PluginConfig } from './PluginConfig';
10 |
11 | // Export UI components
12 | export {
13 | Button,
14 | Text,
15 | TextButton,
16 | Toggle,
17 | SidebarItem,
18 | PluginCheckbox,
19 | PluginMoreButton,
20 | PluginItem,
21 | SimpleMarkdownRender,
22 | iconElement
23 | } from './components';
24 |
25 | // Export contexts
26 | export {
27 | ContextMenuContext,
28 | DebugConsoleContext,
29 | PluginLoadOrderContext,
30 | UpdateDataContext,
31 | NotificationContext
32 | } from './contexts';
33 |
34 | // Export utilities
35 | export {
36 | getNestedValue,
37 | setNestedValue,
38 | useTranslation,
39 | getAllSubkeys,
40 | applyPreset,
41 | checkPresetMatch,
42 | getCurrentPreset,
43 | loadConfig,
44 | saveConfig,
45 | loadPlugins as reloadPlugins,
46 | togglePlugin,
47 | deletePlugin,
48 | isPluginInstalled,
49 | getPluginVersion
50 | } from './utils';
51 |
52 | // Export constants
53 | export {
54 | languages,
55 | PLUGIN_SOURCES,
56 | ICON_CONTEXT_MENU,
57 | ICON_UPDATE,
58 | ICON_PLUGIN_STORE,
59 | ICON_PLUGIN_CONFIG,
60 | ICON_MORE_VERT,
61 | ICON_BREEZE,
62 | theme_presets,
63 | animation_presets,
64 | WINDOW_WIDTH,
65 | WINDOW_HEIGHT,
66 | SIDEBAR_WIDTH
67 | } from './constants';
68 |
69 | import * as shell from "mshell";
70 | import ConfigApp from './ConfigApp';
71 |
72 | let existingConfigWindow: shell.breeze_ui.window | null = null;
73 | export const showConfigPage = () => {
74 | shell.breeze.set_can_reload_js(false);
75 | const win = shell.breeze_ui.window.create_ex("Breeze Config", 800, 600, () => {
76 | shell.breeze.set_can_reload_js(true)
77 | if (existingConfigWindow === win)
78 | existingConfigWindow = null;
79 | });
80 | if (existingConfigWindow)
81 | existingConfigWindow.close();
82 | existingConfigWindow = win;
83 |
84 | const widget = shell.breeze_ui.widgets_factory.create_flex_layout_widget();
85 | const renderer = createRenderer(widget);
86 | renderer.render(React.createElement(ConfigApp, null));
87 | win.set_root_widget(widget)
88 | }
--------------------------------------------------------------------------------
/src/shell/script/ts/src/plugin/core.ts:
--------------------------------------------------------------------------------
1 | import * as shell from "mshell"
2 | import { getNestedValue, setNestedValue } from "../utils/object"
3 |
4 | export const config_directory_main = shell.breeze.data_directory() + '/config/';
5 |
6 | export const config_dir_watch_callbacks = new Set<(path: string, type: number) => void>();
7 |
8 | shell.fs.mkdir(config_directory_main)
9 | shell.fs.watch(config_directory_main, (path: string, type: number) => {
10 | for (const callback of config_dir_watch_callbacks) {
11 | callback(path, type)
12 | }
13 | })
14 |
15 | globalThis.on_plugin_menu = {}
16 |
17 | export const plugin = (import_meta, default_config = {}) => {
18 | const CONFIG_FILE = 'config.json'
19 |
20 | const { name, url } = import_meta
21 | const languages = {}
22 |
23 | const nameNoExt = name.endsWith('.js') ? name.slice(0, -3) : name
24 |
25 | let config = default_config
26 |
27 | const on_reload_callbacks = new Set<(config: any) => void>()
28 |
29 | const plugin = {
30 | i18n: {
31 | define: (lang, data) => {
32 | languages[lang] = data
33 | },
34 | t: (key) => {
35 | return languages[shell.breeze.user_language()][key] || key
36 | }
37 | },
38 | set_on_menu: (callback: (m: shell.menu_controller) => void) => {
39 | globalThis.on_plugin_menu[nameNoExt] = callback
40 | },
41 | config_directory: config_directory_main + nameNoExt + '/',
42 | config: {
43 | read_config() {
44 | if (shell.fs.exists(plugin.config_directory + CONFIG_FILE)) {
45 | try {
46 | config = JSON.parse(shell.fs.read(plugin.config_directory + CONFIG_FILE))
47 | } catch (e) {
48 | shell.println(`[${name}] 配置文件解析失败: ${e}`)
49 | }
50 | }
51 | },
52 | write_config() {
53 | shell.fs.write(plugin.config_directory + CONFIG_FILE, JSON.stringify(config, null, 4))
54 | },
55 | get(key) {
56 | return getNestedValue(config, key) || getNestedValue(default_config, key) || null
57 | },
58 | set(key, value) {
59 | setNestedValue(config, key, value)
60 | plugin.config.write_config()
61 | },
62 | all() {
63 | return config
64 | },
65 | on_reload(callback) {
66 | const dispose = () => {
67 | on_reload_callbacks.delete(callback)
68 | }
69 | on_reload_callbacks.add(callback)
70 | return dispose
71 | }
72 | },
73 | log(...args) {
74 | shell.println(`[${name}]`, ...args)
75 | }
76 | }
77 |
78 | shell.fs.mkdir(plugin.config_directory)
79 | plugin.config.read_config()
80 | config_dir_watch_callbacks.add((path, type) => {
81 | const relativePath = path.replace(config_directory_main, '');
82 | if (relativePath === `${nameNoExt}\\${CONFIG_FILE}`) {
83 | shell.println(`[${name}] 配置文件变更: ${path} ${type}`)
84 | plugin.config.read_config()
85 | for (const callback of on_reload_callbacks) {
86 | callback(config)
87 | }
88 | }
89 | })
90 |
91 | return plugin
92 | }
--------------------------------------------------------------------------------
/src/shell/script/quickjs/dtoa.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Tiny float64 printing and parsing library
3 | *
4 | * Copyright (c) 2024 Fabrice Bellard
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | #ifndef DTOA_H
25 | #define DTOA_H
26 |
27 | //#define JS_DTOA_DUMP_STATS
28 |
29 | /* maximum number of digits for fixed and frac formats */
30 | #define JS_DTOA_MAX_DIGITS 101
31 |
32 | /* radix != 10 is only supported with flags = JS_DTOA_FORMAT_FREE */
33 | /* use as many digits as necessary */
34 | #define JS_DTOA_FORMAT_FREE (0 << 0)
35 | /* use n_digits significant digits (1 <= n_digits <= JS_DTOA_MAX_DIGITS) */
36 | #define JS_DTOA_FORMAT_FIXED (1 << 0)
37 | /* force fractional format: [-]dd.dd with n_digits fractional digits.
38 | 0 <= n_digits <= JS_DTOA_MAX_DIGITS */
39 | #define JS_DTOA_FORMAT_FRAC (2 << 0)
40 | #define JS_DTOA_FORMAT_MASK (3 << 0)
41 |
42 | /* select exponential notation either in fixed or free format */
43 | #define JS_DTOA_EXP_AUTO (0 << 2)
44 | #define JS_DTOA_EXP_ENABLED (1 << 2)
45 | #define JS_DTOA_EXP_DISABLED (2 << 2)
46 | #define JS_DTOA_EXP_MASK (3 << 2)
47 |
48 | #define JS_DTOA_MINUS_ZERO (1 << 4) /* show the minus sign for -0 */
49 |
50 | /* only accepts integers (no dot, no exponent) */
51 | #define JS_ATOD_INT_ONLY (1 << 0)
52 | /* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */
53 | #define JS_ATOD_ACCEPT_BIN_OCT (1 << 1)
54 | /* accept O prefix as octal if radix == 0 and properly formed (Annex B) */
55 | #define JS_ATOD_ACCEPT_LEGACY_OCTAL (1 << 2)
56 | /* accept _ between digits as a digit separator */
57 | #define JS_ATOD_ACCEPT_UNDERSCORES (1 << 3)
58 |
59 | typedef struct {
60 | uint64_t mem[37];
61 | } JSDTOATempMem;
62 |
63 | typedef struct {
64 | uint64_t mem[27];
65 | } JSATODTempMem;
66 |
67 | /* return a maximum bound of the string length */
68 | int js_dtoa_max_len(double d, int radix, int n_digits, int flags);
69 | /* return the string length */
70 | int js_dtoa(char *buf, double d, int radix, int n_digits, int flags,
71 | JSDTOATempMem *tmp_mem);
72 | double js_atod(const char *str, const char **pnext, int radix, int flags,
73 | JSATODTempMem *tmp_mem);
74 |
75 | #ifdef JS_DTOA_DUMP_STATS
76 | void js_dtoa_dump_stats(void);
77 | #endif
78 |
79 | /* additional exported functions */
80 | size_t u32toa(char *buf, uint32_t n);
81 | size_t i32toa(char *buf, int32_t n);
82 | size_t u64toa(char *buf, uint64_t n);
83 | size_t i64toa(char *buf, int64_t n);
84 | size_t u64toa_radix(char *buf, uint64_t n, unsigned int radix);
85 | size_t i64toa_radix(char *buf, int64_t n, unsigned int radix);
86 |
87 | #endif /* DTOA_H */
88 |
--------------------------------------------------------------------------------
/src/shell/script/quickjs/list.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Linux klist like system
3 | *
4 | * Copyright (c) 2016-2017 Fabrice Bellard
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | #ifndef LIST_H
25 | #define LIST_H
26 |
27 | #ifndef NULL
28 | #include
29 | #endif
30 |
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 |
35 | struct list_head {
36 | struct list_head *prev;
37 | struct list_head *next;
38 | };
39 |
40 | #define LIST_HEAD_INIT(el) { &(el), &(el) }
41 |
42 | /* return the pointer of type 'type *' containing 'el' as field 'member' */
43 | #define list_entry(el, type, member) container_of(el, type, member)
44 |
45 | static inline void init_list_head(struct list_head *head)
46 | {
47 | head->prev = head;
48 | head->next = head;
49 | }
50 |
51 | /* insert 'el' between 'prev' and 'next' */
52 | static inline void __list_add(struct list_head *el,
53 | struct list_head *prev, struct list_head *next)
54 | {
55 | prev->next = el;
56 | el->prev = prev;
57 | el->next = next;
58 | next->prev = el;
59 | }
60 |
61 | /* add 'el' at the head of the list 'head' (= after element head) */
62 | static inline void list_add(struct list_head *el, struct list_head *head)
63 | {
64 | __list_add(el, head, head->next);
65 | }
66 |
67 | /* add 'el' at the end of the list 'head' (= before element head) */
68 | static inline void list_add_tail(struct list_head *el, struct list_head *head)
69 | {
70 | __list_add(el, head->prev, head);
71 | }
72 |
73 | static inline void list_del(struct list_head *el)
74 | {
75 | struct list_head *prev, *next;
76 | prev = el->prev;
77 | next = el->next;
78 | prev->next = next;
79 | next->prev = prev;
80 | el->prev = NULL; /* fail safe */
81 | el->next = NULL; /* fail safe */
82 | }
83 |
84 | static inline int list_empty(struct list_head *el)
85 | {
86 | return el->next == el;
87 | }
88 |
89 | #define list_for_each(el, head) \
90 | for(el = (head)->next; el != (head); el = el->next)
91 |
92 | #define list_for_each_safe(el, el1, head) \
93 | for(el = (head)->next, el1 = el->next; el != (head); \
94 | el = el1, el1 = el->next)
95 |
96 | #define list_for_each_prev(el, head) \
97 | for(el = (head)->prev; el != (head); el = el->prev)
98 |
99 | #define list_for_each_prev_safe(el, el1, head) \
100 | for(el = (head)->prev, el1 = el->prev; el != (head); \
101 | el = el1, el1 = el->prev)
102 |
103 | #ifdef __cplusplus
104 | } /* extern "C" { */
105 | #endif
106 |
107 | #endif /* LIST_H */
108 |
--------------------------------------------------------------------------------
/src/shell/script/quickjs/libregexp.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Regular Expression Engine
3 | *
4 | * Copyright (c) 2017-2018 Fabrice Bellard
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | #ifndef LIBREGEXP_H
25 | #define LIBREGEXP_H
26 |
27 | #include
28 | #include
29 |
30 | #include "libunicode.h"
31 |
32 | #ifdef __cplusplus
33 | extern "C" {
34 | #endif
35 |
36 | #define LRE_FLAG_GLOBAL (1 << 0)
37 | #define LRE_FLAG_IGNORECASE (1 << 1)
38 | #define LRE_FLAG_MULTILINE (1 << 2)
39 | #define LRE_FLAG_DOTALL (1 << 3)
40 | #define LRE_FLAG_UNICODE (1 << 4)
41 | #define LRE_FLAG_STICKY (1 << 5)
42 | #define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
43 | #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
44 | #define LRE_FLAG_UNICODE_SETS (1 << 8)
45 |
46 | #define LRE_RET_MEMORY_ERROR (-1)
47 | #define LRE_RET_TIMEOUT (-2)
48 |
49 | uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
50 | const char *buf, size_t buf_len, int re_flags,
51 | void *opaque);
52 | int lre_get_capture_count(const uint8_t *bc_buf);
53 | int lre_get_flags(const uint8_t *bc_buf);
54 | const char *lre_get_groupnames(const uint8_t *bc_buf);
55 | int lre_exec(uint8_t **capture,
56 | const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
57 | int cbuf_type, void *opaque);
58 |
59 | int lre_parse_escape(const uint8_t **pp, int allow_utf16);
60 | bool lre_is_space(int c);
61 |
62 | void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped);
63 |
64 | /* must be provided by the user */
65 | bool lre_check_stack_overflow(void *opaque, size_t alloca_size);
66 | /* must be provided by the user, return non zero if time out */
67 | int lre_check_timeout(void *opaque);
68 | void *lre_realloc(void *opaque, void *ptr, size_t size);
69 |
70 | /* JS identifier test */
71 | extern uint32_t const lre_id_start_table_ascii[4];
72 | extern uint32_t const lre_id_continue_table_ascii[4];
73 |
74 | static inline int lre_js_is_ident_first(int c)
75 | {
76 | if ((uint32_t)c < 128) {
77 | return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
78 | } else {
79 | return lre_is_id_start(c);
80 | }
81 | }
82 |
83 | static inline int lre_js_is_ident_next(int c)
84 | {
85 | if ((uint32_t)c < 128) {
86 | return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
87 | } else {
88 | /* ZWNJ and ZWJ are accepted in identifiers */
89 | return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
90 | }
91 | }
92 |
93 | #ifdef __cplusplus
94 | } /* extern "C" { */
95 | #endif
96 |
97 | #endif /* LIBREGEXP_H */
98 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [Join Discord](https://discord.gg/MgpHk8pa3d) [中文简介 →](./README_zh.md)
2 |
3 | > [!WARNING]
4 | > This project is still in active development. File a bug report if you meet any!
5 | > 此项目仍在开发阶段,如果遇到问题请发送 Issue
6 | >
7 | > Both English and Chinese issues are accepted
8 | > Issue 中使用中文或英文均可
9 |
10 |
11 |
12 |
Breeze Shell
13 |
Bring fluency & delication back to Windows
14 |
15 |
16 |
17 |
18 |
19 | Breeze is an **alternative context menu** for Windows 10 and Windows 11.
20 |
21 | ## Fluent
22 | Breeze is designed with animations in mind.
23 |
24 |
25 |
26 | All animations are configurable and can be scaled and disabled as you want.
27 | ## Extensible
28 |
29 | Empowered by the embedded JavaScript script api, Breeze enables you to extend
30 | the functionalities of your context menu in a few lines of code.
31 |
32 | ```javascript
33 | shell.menu_controller.add_menu_listener((e) => {
34 | e.menu.add({
35 | type: "button",
36 | name: "Shuffle Buttons",
37 | action: () => {
38 | for (const item of menus) {
39 | item.set_position(Math.floor(menus.length * Math.random()));
40 | }
41 | },
42 | }, 0);
43 | });
44 | ```
45 |
46 | [See full bindings →](./src/shell/script/binding_types.d.ts)
47 |
48 | Send pull requests to [this repo](https://github.com/breeze-shell/plugins) to add your script to the plugin market!
49 |
50 | ## Configurable
51 | Breeze shell exposed a bunch of configurations ranging from item height to background radius method. Customize them as you need.
52 |
53 | [Configuration Document →](./CONFIG.md)
54 |
55 | The config menu of breeze-shell can be found as you open your `Data Folder` and right-click anywhere inside it.
56 |
57 | ## Lightweight & Fast
58 |
59 | Breeze uses breeze_ui, which is implemented to be a cross-platform, simple,
60 | animation-friendly and fast ui library for modern C++, with the support of both
61 | NanoVG and ThorVG render context. This allowed Breeze to have a delicated user
62 | interface in ~2MiB.
63 |
64 | # Try it out!
65 |
66 | Download and extract the zip, and Run `breeze.exe`.
67 |