From c339e92a31b063a435d17d63aecf496e939cb9c1 Mon Sep 17 00:00:00 2001 From: p0ryae Date: Thu, 28 May 2026 11:41:04 -0700 Subject: [PATCH 01/17] feat: add shell.nix for dev, bump some versions and fix tomlplusplus fetch --- CMakeLists.txt | 12 +++++------ shell.nix | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 shell.nix diff --git a/CMakeLists.txt b/CMakeLists.txt index d71cbc34..eaa9ee69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # Static linking to avoid runtime dependencies (vcruntime) -if(WIN32 AND MSVC) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +if(WIN32 AND MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() # Strip debug symbols in release @@ -38,13 +38,13 @@ include(FetchContent) FetchContent_Declare(imgui GIT_REPOSITORY https://github.com/ocornut/imgui - GIT_TAG v1.92.5-docking + GIT_TAG v1.92.8-docking GIT_SHALLOW TRUE ) FetchContent_Declare(glaze GIT_REPOSITORY https://github.com/stephenberry/glaze.git - GIT_TAG v5.5.4 + GIT_TAG v7.7.0 GIT_SHALLOW TRUE ) @@ -60,8 +60,8 @@ FetchContent_Declare(lunasvg FetchContent_Declare(tomlplusplus GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git - GIT_TAG 7807a314ad1c0c9c227d9dbd68f23f187163372e - GIT_SHALLOW TRUE + GIT_TAG a43ad3787293f4a46b1d70c0924b5a25d10e79fc + GIT_SHALLOW FALSE ) FetchContent_Declare(cpr diff --git a/shell.nix b/shell.nix new file mode 100644 index 00000000..e0e69d08 --- /dev/null +++ b/shell.nix @@ -0,0 +1,58 @@ +{ + pkgs ? import { }, +}: +let + inherit (pkgs) lib; +in + +pkgs.mkShell { + packages = with pkgs; [ + # Toolchain + gcc14 + cmake + ninja + pkg-config + git + + # OpenGL + libGL + libGLU + mesa + + # X11 (GLFW) + libx11 + libxrandr + libxinerama + libxcursor + libxi + libxext + + # Wayland (GLFW) + wayland + wayland-scanner + wayland-protocols + libxkbcommon + + # CPR / networking + curl.dev + openssl.dev + zlib + ]; + + # Make Nix store .so files visible to the dynamic linker at runtime + LD_LIBRARY_PATH = lib.makeLibraryPath ( + with pkgs; + [ + wayland + libGL + libxkbcommon + ] + ); + + shellHook = '' + echo "Lazap dev shell ready!" + echo "Build with:" + echo " cmake -B build -GNinja -DCMAKE_BUILD_TYPE=Debug -DCPR_USE_SYSTEM_CURL=ON -DCURL_USE_LIBPSL=OFF" + echo " cmake --build build -j\$(nproc)" + ''; +} From 4aca9bda704fc377d6ef14f3832a564e67c6601f Mon Sep 17 00:00:00 2001 From: Data Redacted Date: Tue, 2 Jun 2026 19:30:51 +0530 Subject: [PATCH 02/17] feat(system_tray): Add the minimize to tray feature --- CMakeLists.txt | 10 +- include/utils/tray_manager.h | 12 + src/core/application.cpp | 560 +++++++++++++++++--------------- src/core/utils/tray_manager.cpp | 95 ++++++ src/ui/panels/settings.cpp | 10 +- 5 files changed, 418 insertions(+), 269 deletions(-) create mode 100644 include/utils/tray_manager.h create mode 100644 src/core/utils/tray_manager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index eaa9ee69..2601612f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,12 @@ FetchContent_Declare(stb DOWNLOAD_NO_EXTRACT TRUE ) +FetchContent_Declare(tray + GIT_REPOSITORY https://github.com/LizardByte/tray.git + GIT_TAG df9af119085e2cd3f1a9e88e4cc865963879d468 + GIT_SHALLOW TRUE +) + FetchContent_Declare(lunasvg GIT_REPOSITORY https://github.com/sammycage/lunasvg.git GIT_TAG v3.5.0 @@ -76,7 +82,7 @@ FetchContent_Declare(battery-embed ) FetchContent_MakeAvailable( - imgui glaze stb lunasvg tomlplusplus cpr battery-embed + imgui glaze stb tray lunasvg tomlplusplus cpr battery-embed ) #----------------------------------------------------------------------------------------------------------------------- @@ -148,6 +154,7 @@ target_include_directories(${EXECUTABLE_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/include ${imgui_SOURCE_DIR}/ ${stb_SOURCE_DIR}/ + ${tray_SOURCE_DIR}/src ${tomlplusplus_SOURCE_DIR}/include ) @@ -157,6 +164,7 @@ target_link_libraries(${EXECUTABLE_NAME} PRIVATE glaze::glaze cpr::cpr lunasvg + tray::tray tinyfiledialogs $<$:X11> $<$:dwmapi> diff --git a/include/utils/tray_manager.h b/include/utils/tray_manager.h new file mode 100644 index 00000000..aee11253 --- /dev/null +++ b/include/utils/tray_manager.h @@ -0,0 +1,12 @@ +#pragma once + +#include "GLFW/glfw3.h" + +namespace TrayManager { +void init(GLFWwindow* window); +void update(); +void minimize(); +bool shouldQuit(); +bool isWindowHidden(); +void shutdown(); +} // namespace TrayManager \ No newline at end of file diff --git a/src/core/application.cpp b/src/core/application.cpp index 013ade42..2813c521 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -1,265 +1,295 @@ -#include "application.h" - -#include - -#include "addons/discord_rpc/discord_rpc.h" -#include "clients/custom_games.h" -#include "clients/epic_games.h" -#include "clients/riot_games.h" -#include "clients/rockstar_games.h" -#include "clients/steam/steam.h" -#include "clients/ubisoft_connect.h" -#include "imgui_layer.h" -#include "storage/storage.h" -#include "utils/banner_manager.h" - -#ifdef _WIN32 -#define _WIN32_WINNT 0x0A00 // Windows 10 -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include - -#include -#pragma comment(lib, "dwmapi.lib") -#endif - -double ClockSeconds() { - using Clock = std::chrono::high_resolution_clock; - using second = std::chrono::duration; - static const auto start = Clock::now(); - return std::chrono::duration_cast(Clock::now() - start).count(); -} - -void IdleBySleeping(FpsIdling &ioIdling) { - ioIdling.isIdling = false; - - if ((ioIdling.fpsIdle > 0.f) && ioIdling.enableIdling) { - double beforeWait = ClockSeconds(); - double waitTimeout = 1.0 / static_cast(ioIdling.fpsIdle); - - glfwWaitEventsTimeout(waitTimeout); - - double afterWait = ClockSeconds(); - double waitDuration = afterWait - beforeWait; - double waitIdleExpected = 1.0 / ioIdling.fpsIdle; - - ioIdling.isIdling = (waitDuration > waitIdleExpected * 0.9); - } -} - -#ifdef _WIN32 -void UpdateWindowCorners(GLFWwindow *window) { - HWND hwnd = glfwGetWin32Window(window); - - WINDOWPLACEMENT placement = {}; - placement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(hwnd, &placement); - - bool isMaximized = (placement.showCmd == SW_SHOWMAXIMIZED); - - DWM_WINDOW_CORNER_PREFERENCE cornerPref = - isMaximized ? DWMWCP_DONOTROUND : DWMWCP_ROUND; - DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, - sizeof(cornerPref)); -} -#endif - -void Application::run() { - auto startupBegin = std::chrono::high_resolution_clock::now(); - - glfwSetErrorCallback([](int error, const char *description) { - fprintf(stderr, "Glfw Error %d: %s\n", error, description); - }); - - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - - glfwWindowHint(GLFW_SAMPLES, 4); - - if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) { - glfwWindowHintString(GLFW_WAYLAND_APP_ID, "lazap"); - } - - GLFWmonitor *monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode *mode = glfwGetVideoMode(monitor); - float xscale, yscale; - glfwGetMonitorContentScale(monitor, &xscale, &yscale); - - float sx = 1.0f, sy = 1.0f; - -#ifdef _WIN32 - sx = xscale; - sy = yscale; -#endif - - int windowWidth = WINDOW_SIZE[0] / 1.3 * sx; - int windowHeight = WINDOW_SIZE[1] / 1.3 * sy; - - GLFWwindow *window = - glfwCreateWindow(windowWidth, windowHeight, "Lazap", nullptr, nullptr); - if (!window) { - glfwTerminate(); - return; - } - - glfwSetWindowSizeLimits(window, MIN_WINDOW_SIZE[0], MIN_WINDOW_SIZE[1], - GLFW_DONT_CARE, GLFW_DONT_CARE); - - if (glfwGetPlatform() != GLFW_PLATFORM_WAYLAND) { - int windowX = (mode->width - windowWidth) / 2; - int windowY = (mode->height - windowHeight) / 2; - - glfwSetWindowPos(window, windowX, windowY); - } - - glfwMakeContextCurrent(window); - glfwSetMouseButtonCallback(window, WindowCallbacks::mouseButtonCB); - - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { - fprintf(stderr, "Failed to initialize GLAD\n"); - glfwDestroyWindow(window); - glfwTerminate(); - return; - } - - glEnable(GL_MULTISAMPLE); - - glfwSwapInterval(1); - - Storage storage; - storage.initTOML(); - - bool discordRpc = true; - auto toml = storage.loadTOML(); - auto *settingsTable = toml["settings"].as_table(); - if (settingsTable) { - discordRpc = settingsTable->get("discord_rpc")->value_or(false); - } - - std::vector> clients; - clients.push_back(std::make_unique()); - clients.push_back(std::make_unique()); - clients.push_back(std::make_unique()); - clients.push_back(std::make_unique()); - clients.push_back(std::make_unique()); - clients.push_back(std::make_unique(storage)); - - BannerManager bm; - auto loadAllGames = [&clients, &bm, &storage]() -> std::vector { - std::vector games; - for (const auto &client : clients) { - for (auto &game : client->getInstalledGames()) { - if (game.bannerUrl.empty()) - game.bannerUrl = bm.getBanner(client->getType(), game.name, - std::to_string(game.appId)); - storage.insertGameTOML(game.name); - games.push_back(std::move(game)); - } - } - return games; - }; - - std::vector games = loadAllGames(); - - ImGuiLayer imgui(window, storage); - imgui.setGames(std::move(games)); - - imgui.setOnGamesReload([&imgui, &loadAllGames]() { - std::vector reloadedGames = loadAllGames(); - imgui.setGames(std::move(reloadedGames)); - }); - - if (discordRpc) { - discord::RichPresence::Initialize("932504287337148417"); - discord::RichPresence::UpdatePresence("Lazap", "In Main Menu"); - } - - printf("Startup took: %ld ms\n", - std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - startupBegin) - .count()); - - glfwShowWindow(window); - -#ifdef _WIN32 - // Windows 11 native rounded corners and frame extension - HWND hwnd = glfwGetWin32Window(window); - SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - - DWM_WINDOW_CORNER_PREFERENCE cornerPref = DWMWCP_ROUND; - DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, - sizeof(cornerPref)); -#endif - - RunnerState runner; - while (!glfwWindowShouldClose(window)) { - IdleBySleeping(runner.fpsIdling); - - glfwPollEvents(); - -#ifdef _WIN32 - UpdateWindowCorners(window); -#endif - - int display_w, display_h; - glfwGetFramebufferSize(window, &display_w, &display_h); - glViewport(0, 0, display_w, display_h); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - - imgui.begin(); - imgui.render(); - imgui.end(); - - glfwSwapBuffers(window); - } - - if (discordRpc) { - discord::RichPresence::Shutdown(); - } - imgui.shutdown(); - glfwDestroyWindow(window); - glfwTerminate(); -} - -void WindowCallbacks::mouseButtonCB(GLFWwindow *window, int button, int action, - int mods) { - if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { - double xpos, ypos; - glfwGetCursorPos(window, &xpos, &ypos); - - int width, height; - glfwGetWindowSize(window, &width, &height); - - const int edgeThreshold = 10; - - bool nearLeft = (xpos <= edgeThreshold); - bool nearRight = (xpos >= width - edgeThreshold); - bool nearTop = (ypos <= edgeThreshold); - bool nearBottom = (ypos >= height - edgeThreshold); - - if (nearTop && nearLeft) { - glfwResizeWindow(window, GLFW_WINDOW_TOPLEFT); - } else if (nearTop && nearRight) { - glfwResizeWindow(window, GLFW_WINDOW_TOPRIGHT); - } else if (nearBottom && nearLeft) { - glfwResizeWindow(window, GLFW_WINDOW_BOTTOMLEFT); - } else if (nearBottom && nearRight) { - glfwResizeWindow(window, GLFW_WINDOW_BOTTOMRIGHT); - } - - else if (nearLeft) { - glfwResizeWindow(window, GLFW_WINDOW_LEFT); - } else if (nearRight) { - glfwResizeWindow(window, GLFW_WINDOW_RIGHT); - } else if (nearTop) { - glfwResizeWindow(window, GLFW_WINDOW_TOP); - } else if (nearBottom) { - glfwResizeWindow(window, GLFW_WINDOW_BOTTOM); - } - } -} +// TODO: Stop app from starting multiple instances + +#include "application.h" + +#include + +#include "addons/discord_rpc/discord_rpc.h" +#include "clients/custom_games.h" +#include "clients/epic_games.h" +#include "clients/riot_games.h" +#include "clients/rockstar_games.h" +#include "clients/steam/steam.h" +#include "clients/ubisoft_connect.h" +#include "imgui_layer.h" +#include "storage/storage.h" +#include "utils/banner_manager.h" +#include "utils/tray_manager.h" + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0A00 // Windows 10 +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include + +#include +#pragma comment(lib, "dwmapi.lib") +#endif + +double ClockSeconds() { + using Clock = std::chrono::high_resolution_clock; + using second = std::chrono::duration; + static const auto start = Clock::now(); + return std::chrono::duration_cast(Clock::now() - start).count(); +} + +void IdleBySleeping(FpsIdling &ioIdling) { + ioIdling.isIdling = false; + + if ((ioIdling.fpsIdle > 0.f) && ioIdling.enableIdling) { + double beforeWait = ClockSeconds(); + double waitTimeout = 1.0 / static_cast(ioIdling.fpsIdle); + + glfwWaitEventsTimeout(waitTimeout); + + double afterWait = ClockSeconds(); + double waitDuration = afterWait - beforeWait; + double waitIdleExpected = 1.0 / ioIdling.fpsIdle; + + ioIdling.isIdling = (waitDuration > waitIdleExpected * 0.9); + } +} + +#ifdef _WIN32 +void UpdateWindowCorners(GLFWwindow *window) { + HWND hwnd = glfwGetWin32Window(window); + + WINDOWPLACEMENT placement = {}; + placement.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hwnd, &placement); + + bool isMaximized = (placement.showCmd == SW_SHOWMAXIMIZED); + + DWM_WINDOW_CORNER_PREFERENCE cornerPref = + isMaximized ? DWMWCP_DONOTROUND : DWMWCP_ROUND; + DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, + sizeof(cornerPref)); +} +#endif + +void Application::run() { + auto startupBegin = std::chrono::high_resolution_clock::now(); + + glfwSetErrorCallback([](int error, const char *description) { + fprintf(stderr, "Glfw Error %d: %s\n", error, description); + }); + + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + + glfwWindowHint(GLFW_SAMPLES, 4); + + if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) { + glfwWindowHintString(GLFW_WAYLAND_APP_ID, "lazap"); + } + + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode *mode = glfwGetVideoMode(monitor); + float xscale, yscale; + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + + float sx = 1.0f, sy = 1.0f; + +#ifdef _WIN32 + sx = xscale; + sy = yscale; +#endif + + int windowWidth = WINDOW_SIZE[0] / 1.3 * sx; + int windowHeight = WINDOW_SIZE[1] / 1.3 * sy; + + GLFWwindow *window = + glfwCreateWindow(windowWidth, windowHeight, "Lazap", nullptr, nullptr); + if (!window) { + glfwTerminate(); + return; + } + + glfwSetWindowSizeLimits(window, MIN_WINDOW_SIZE[0], MIN_WINDOW_SIZE[1], + GLFW_DONT_CARE, GLFW_DONT_CARE); + + if (glfwGetPlatform() != GLFW_PLATFORM_WAYLAND) { + int windowX = (mode->width - windowWidth) / 2; + int windowY = (mode->height - windowHeight) / 2; + + glfwSetWindowPos(window, windowX, windowY); + } + + glfwMakeContextCurrent(window); + glfwSetMouseButtonCallback(window, WindowCallbacks::mouseButtonCB); + + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { + fprintf(stderr, "Failed to initialize GLAD\n"); + glfwDestroyWindow(window); + glfwTerminate(); + return; + } + + glEnable(GL_MULTISAMPLE); + + glfwSwapInterval(1); + + Storage storage; + storage.initTOML(); + + bool discordRpc = true; + bool systemTray = false; + auto toml = storage.loadTOML(); + auto *settingsTable = toml["settings"].as_table(); + if (settingsTable) { + discordRpc = settingsTable->get("discord_rpc")->value_or(false); + systemTray = settingsTable->get("quit_tray_min")->value_or(false); + } + + std::vector> clients; + clients.push_back(std::make_unique()); + clients.push_back(std::make_unique()); + clients.push_back(std::make_unique()); + clients.push_back(std::make_unique()); + clients.push_back(std::make_unique()); + clients.push_back(std::make_unique(storage)); + + BannerManager bm; + auto loadAllGames = [&clients, &bm, &storage]() -> std::vector { + std::vector games; + for (const auto &client : clients) { + for (auto &game : client->getInstalledGames()) { + if (game.bannerUrl.empty()) + game.bannerUrl = bm.getBanner(client->getType(), game.name, + std::to_string(game.appId)); + storage.insertGameTOML(game.name); + games.push_back(std::move(game)); + } + } + return games; + }; + + std::vector games = loadAllGames(); + + ImGuiLayer imgui(window, storage); + imgui.setGames(std::move(games)); + + imgui.setOnGamesReload([&imgui, &loadAllGames]() { + std::vector reloadedGames = loadAllGames(); + imgui.setGames(std::move(reloadedGames)); + }); + + if (discordRpc) { + discord::RichPresence::Initialize("932504287337148417"); + discord::RichPresence::UpdatePresence("Lazap", "In Main Menu"); + } + + printf("Startup took: %ld ms\n", + std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - startupBegin) + .count()); + + if (systemTray) { + TrayManager::init(window); + glfwSetWindowCloseCallback(window, [](GLFWwindow* win) { + if (TrayManager::shouldQuit()) { + glfwSetWindowShouldClose(win, GLFW_TRUE); + TrayManager::shutdown(); + } + else { + glfwSetWindowShouldClose(win, GLFW_FALSE); + TrayManager::minimize(); + } + }); + } + + glfwShowWindow(window); + +#ifdef _WIN32 + // Windows 11 native rounded corners and frame extension + HWND hwnd = glfwGetWin32Window(window); + SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + + DWM_WINDOW_CORNER_PREFERENCE cornerPref = DWMWCP_ROUND; + DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, + sizeof(cornerPref)); + glfwIconifyWindow(window); + glfwRestoreWindow(window); +#endif + + RunnerState runner; + while (systemTray ? !TrayManager::shouldQuit() : !glfwWindowShouldClose(window)) { + if (glfwWindowShouldClose(window)) { + glfwSetWindowShouldClose(window, GLFW_FALSE); + TrayManager::minimize(); + } + if (systemTray) TrayManager::update(); + + IdleBySleeping(runner.fpsIdling); + + glfwPollEvents(); + if (TrayManager::isWindowHidden()) { + continue; + } + +#ifdef _WIN32 + UpdateWindowCorners(window); +#endif + + int display_w, display_h; + glfwGetFramebufferSize(window, &display_w, &display_h); + glViewport(0, 0, display_w, display_h); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + + imgui.begin(); + imgui.render(); + imgui.end(); + + glfwSwapBuffers(window); + } + + if (discordRpc) { + discord::RichPresence::Shutdown(); + } + imgui.shutdown(); + glfwDestroyWindow(window); + glfwTerminate(); +} + +void WindowCallbacks::mouseButtonCB(GLFWwindow *window, int button, int action, + int mods) { + if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { + double xpos, ypos; + glfwGetCursorPos(window, &xpos, &ypos); + + int width, height; + glfwGetWindowSize(window, &width, &height); + + const int edgeThreshold = 10; + + bool nearLeft = (xpos <= edgeThreshold); + bool nearRight = (xpos >= width - edgeThreshold); + bool nearTop = (ypos <= edgeThreshold); + bool nearBottom = (ypos >= height - edgeThreshold); + + if (nearTop && nearLeft) { + glfwResizeWindow(window, GLFW_WINDOW_TOPLEFT); + } else if (nearTop && nearRight) { + glfwResizeWindow(window, GLFW_WINDOW_TOPRIGHT); + } else if (nearBottom && nearLeft) { + glfwResizeWindow(window, GLFW_WINDOW_BOTTOMLEFT); + } else if (nearBottom && nearRight) { + glfwResizeWindow(window, GLFW_WINDOW_BOTTOMRIGHT); + } + + else if (nearLeft) { + glfwResizeWindow(window, GLFW_WINDOW_LEFT); + } else if (nearRight) { + glfwResizeWindow(window, GLFW_WINDOW_RIGHT); + } else if (nearTop) { + glfwResizeWindow(window, GLFW_WINDOW_TOP); + } else if (nearBottom) { + glfwResizeWindow(window, GLFW_WINDOW_BOTTOM); + } + } +} diff --git a/src/core/utils/tray_manager.cpp b/src/core/utils/tray_manager.cpp new file mode 100644 index 00000000..349f45be --- /dev/null +++ b/src/core/utils/tray_manager.cpp @@ -0,0 +1,95 @@ +#include +#ifdef _WIN32 +#define TRAY_WINAPI +#elif defined(__APPLE__) +#define TRAY_COCOA +#else +#define TRAY_APPINDICATOR +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +#include "battery/embed.hpp" + +namespace TrayManager { +static GLFWwindow* win = nullptr; +static bool quit = false; +static bool hidden = false; + +static void restore(struct tray_menu* item) { + if (win) { + glfwShowWindow(win); + glfwRestoreWindow(win); + glfwFocusWindow(win); + hidden = false; + } +} + +static void on_quit_clicked(struct tray_menu* item) { + quit = true; + glfwSetWindowShouldClose(win, GLFW_TRUE); + glfwPostEmptyEvent(); + tray_exit(); +} + +static struct tray tray = { + .icon = "/assets/icons/lazap/lazap.ico", + .tooltip = "Lazap", +}; + +void init(GLFWwindow* window) { + win = window; + quit = false; + + std::filesystem::path iconPath = + std::filesystem::temp_directory_path() / "lazap_tray.ico"; + const auto file = b::embed<"assets/icons/lazap/lazap.ico">(); + + std::ofstream out(iconPath, std::ios::binary); + out.write(reinterpret_cast(file.data()), file.size()); + out.close(); + +#ifdef _WIN32 + tray.icon = _strdup(iconPath.string().c_str()); +#else + tray.icon = strdup(iconPath.string().c_str()); +#endif + + static struct tray_menu menu[] = {{.text = "Restore App", .cb = restore}, + {.text = "-"}, + {.text = "Quit", .cb = on_quit_clicked}, + {.text = nullptr}}; + + tray.menu = menu; + + tray_init(&tray); +} + +void update() { + tray_loop(0); + + if (hidden) { + std::this_thread::sleep_for(std::chrono::milliseconds(16)); + } +} + +void minimize() { + if (win) { + glfwHideWindow(win); + hidden = true; + } +} + +bool shouldQuit() { return quit; } +bool isWindowHidden() { return hidden; } + +void shutdown() { tray_exit(); } +} // namespace TrayManager \ No newline at end of file diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index 06cc5896..85e0f8f4 100644 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -105,9 +105,9 @@ void SettingsPanel::render() { ImGui::BeginGroup(); if (addOption("Minimize to Tray on Exit", InputType::Toggle, - &quitTrayMin_, true)) { - // saveSettings(); - ImGui::OpenPopup("Coming Soon"); + &quitTrayMin_)) { + saveSettings(); + ImGui::OpenPopup("Restart"); } if (addOption("Launch at Startup", InputType::Toggle, &autoStart_, true)) { @@ -123,6 +123,10 @@ void SettingsPanel::render() { ImGui::Text("This feature is coming soon!"); ImGui::EndPopup(); } + if (ImGui::BeginPopup("Restart", ImGuiWindowFlags_NoMove)) { + ImGui::Text("Restart the app to apply this change"); + ImGui::EndPopup(); + } ImGui::EndGroup(); ImGui::PopID(); From 4c190c9570cb6638440e5a727c577c042e6e8788 Mon Sep 17 00:00:00 2001 From: Data Redacted Date: Tue, 2 Jun 2026 20:17:47 +0530 Subject: [PATCH 03/17] fix: formatting --- src/core/application.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/application.cpp b/src/core/application.cpp index 2813c521..c59b83c2 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -1,4 +1,4 @@ -// TODO: Stop app from starting multiple instances +// TODO: Stop app from starting multiple instances #include "application.h" @@ -187,15 +187,14 @@ void Application::run() { std::chrono::duration_cast( std::chrono::high_resolution_clock::now() - startupBegin) .count()); - + if (systemTray) { TrayManager::init(window); - glfwSetWindowCloseCallback(window, [](GLFWwindow* win) { + glfwSetWindowCloseCallback(window, [](GLFWwindow *win) { if (TrayManager::shouldQuit()) { glfwSetWindowShouldClose(win, GLFW_TRUE); TrayManager::shutdown(); - } - else { + } else { glfwSetWindowShouldClose(win, GLFW_FALSE); TrayManager::minimize(); } @@ -217,7 +216,8 @@ void Application::run() { #endif RunnerState runner; - while (systemTray ? !TrayManager::shouldQuit() : !glfwWindowShouldClose(window)) { + while (systemTray ? !TrayManager::shouldQuit() + : !glfwWindowShouldClose(window)) { if (glfwWindowShouldClose(window)) { glfwSetWindowShouldClose(window, GLFW_FALSE); TrayManager::minimize(); @@ -225,7 +225,7 @@ void Application::run() { if (systemTray) TrayManager::update(); IdleBySleeping(runner.fpsIdling); - + glfwPollEvents(); if (TrayManager::isWindowHidden()) { continue; @@ -247,7 +247,7 @@ void Application::run() { glfwSwapBuffers(window); } - + if (discordRpc) { discord::RichPresence::Shutdown(); } From 0f587719928ca2d43605dea15b6bd55715fbba51 Mon Sep 17 00:00:00 2001 From: LegIt <77503777+LegItMate@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:36:54 +0530 Subject: [PATCH 04/17] fix: Add libnotify-dev to CD dependencies --- .github/workflows/CD.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/CD.yml b/.github/workflows/CD.yml index 3ea88aa8..3bf5bf1f 100644 --- a/.github/workflows/CD.yml +++ b/.github/workflows/CD.yml @@ -50,6 +50,7 @@ jobs: libpsl-dev \ libidn2-dev \ libnghttp2-dev \ + libnotify-dev \ libunistring-dev \ rpm \ patchelf \ From bc5fe29b1a98d4fd947393aee1abbdb34431d159 Mon Sep 17 00:00:00 2001 From: p0ryae Date: Tue, 2 Jun 2026 10:25:53 -0700 Subject: [PATCH 05/17] fix: update shell.nix to have proper deps for system tray --- shell.nix | 15 + vendor/glfw/deps/mingw/_mingw_dxhelper.h | 117 + vendor/glfw/deps/mingw/dinput.h | 2467 +++++++++++++++++ vendor/glfw/deps/mingw/xinput.h | 239 ++ .../deps/wayland/xdg-toplevel-icon-v1.xml | 205 ++ 5 files changed, 3043 insertions(+) create mode 100644 vendor/glfw/deps/mingw/_mingw_dxhelper.h create mode 100644 vendor/glfw/deps/mingw/dinput.h create mode 100644 vendor/glfw/deps/mingw/xinput.h create mode 100644 vendor/glfw/deps/wayland/xdg-toplevel-icon-v1.xml diff --git a/shell.nix b/shell.nix index e0e69d08..bbc3e134 100644 --- a/shell.nix +++ b/shell.nix @@ -3,6 +3,7 @@ }: let inherit (pkgs) lib; + qt = pkgs.qt5; in pkgs.mkShell { @@ -37,6 +38,16 @@ pkgs.mkShell { curl.dev openssl.dev zlib + + # Desktop notifications + libnotify + glib + sysprof + + # System tray + qt.qtbase + qt.qttools + qt.qtwayland ]; # Make Nix store .so files visible to the dynamic linker at runtime @@ -46,6 +57,10 @@ pkgs.mkShell { wayland libGL libxkbcommon + libnotify + glib + qt.qtbase + qt.qtwayland ] ); diff --git a/vendor/glfw/deps/mingw/_mingw_dxhelper.h b/vendor/glfw/deps/mingw/_mingw_dxhelper.h new file mode 100644 index 00000000..849e2914 --- /dev/null +++ b/vendor/glfw/deps/mingw/_mingw_dxhelper.h @@ -0,0 +1,117 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS) +#define NONAMELESSUNION 1 +#endif +#if defined(NONAMELESSSTRUCT) && \ + !defined(NONAMELESSUNION) +#define NONAMELESSUNION 1 +#endif +#if defined(NONAMELESSUNION) && \ + !defined(NONAMELESSSTRUCT) +#define NONAMELESSSTRUCT 1 +#endif +#if !defined(__GNU_EXTENSION) +#if defined(__GNUC__) || defined(__GNUG__) +#define __GNU_EXTENSION __extension__ +#else +#define __GNU_EXTENSION +#endif +#endif /* __extension__ */ + +#ifndef __ANONYMOUS_DEFINED +#define __ANONYMOUS_DEFINED +#if defined(__GNUC__) || defined(__GNUG__) +#define _ANONYMOUS_UNION __extension__ +#define _ANONYMOUS_STRUCT __extension__ +#else +#define _ANONYMOUS_UNION +#define _ANONYMOUS_STRUCT +#endif +#ifndef NONAMELESSUNION +#define _UNION_NAME(x) +#define _STRUCT_NAME(x) +#else /* NONAMELESSUNION */ +#define _UNION_NAME(x) x +#define _STRUCT_NAME(x) x +#endif +#endif /* __ANONYMOUS_DEFINED */ + +#ifndef DUMMYUNIONNAME +# ifdef NONAMELESSUNION +# define DUMMYUNIONNAME u +# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */ +# define DUMMYUNIONNAME2 u2 +# define DUMMYUNIONNAME3 u3 +# define DUMMYUNIONNAME4 u4 +# define DUMMYUNIONNAME5 u5 +# define DUMMYUNIONNAME6 u6 +# define DUMMYUNIONNAME7 u7 +# define DUMMYUNIONNAME8 u8 +# define DUMMYUNIONNAME9 u9 +# else /* NONAMELESSUNION */ +# define DUMMYUNIONNAME +# define DUMMYUNIONNAME1 /* Wine uses this variant */ +# define DUMMYUNIONNAME2 +# define DUMMYUNIONNAME3 +# define DUMMYUNIONNAME4 +# define DUMMYUNIONNAME5 +# define DUMMYUNIONNAME6 +# define DUMMYUNIONNAME7 +# define DUMMYUNIONNAME8 +# define DUMMYUNIONNAME9 +# endif +#endif /* DUMMYUNIONNAME */ + +#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */ +# ifdef NONAMELESSUNION +# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */ +# else +# define DUMMYUNIONNAME1 /* Wine uses this variant */ +# endif +#endif /* DUMMYUNIONNAME1 */ + +#ifndef DUMMYSTRUCTNAME +# ifdef NONAMELESSUNION +# define DUMMYSTRUCTNAME s +# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */ +# define DUMMYSTRUCTNAME2 s2 +# define DUMMYSTRUCTNAME3 s3 +# define DUMMYSTRUCTNAME4 s4 +# define DUMMYSTRUCTNAME5 s5 +# else +# define DUMMYSTRUCTNAME +# define DUMMYSTRUCTNAME1 /* Wine uses this variant */ +# define DUMMYSTRUCTNAME2 +# define DUMMYSTRUCTNAME3 +# define DUMMYSTRUCTNAME4 +# define DUMMYSTRUCTNAME5 +# endif +#endif /* DUMMYSTRUCTNAME */ + +/* These are for compatibility with the Wine source tree */ + +#ifndef WINELIB_NAME_AW +# ifdef __MINGW_NAME_AW +# define WINELIB_NAME_AW __MINGW_NAME_AW +# else +# ifdef UNICODE +# define WINELIB_NAME_AW(func) func##W +# else +# define WINELIB_NAME_AW(func) func##A +# endif +# endif +#endif /* WINELIB_NAME_AW */ + +#ifndef DECL_WINELIB_TYPE_AW +# ifdef __MINGW_TYPEDEF_AW +# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW +# else +# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type; +# endif +#endif /* DECL_WINELIB_TYPE_AW */ + diff --git a/vendor/glfw/deps/mingw/dinput.h b/vendor/glfw/deps/mingw/dinput.h new file mode 100644 index 00000000..b5754802 --- /dev/null +++ b/vendor/glfw/deps/mingw/dinput.h @@ -0,0 +1,2467 @@ +/* + * Copyright (C) the Wine project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __DINPUT_INCLUDED__ +#define __DINPUT_INCLUDED__ + +#define COM_NO_WINDOWS_H +#include +#include <_mingw_dxhelper.h> + +#ifndef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#endif + +/* Classes */ +DEFINE_GUID(CLSID_DirectInput, 0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice, 0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(CLSID_DirectInput8, 0x25E609E4,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice8, 0x25E609E5,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/* Interfaces */ +DEFINE_GUID(IID_IDirectInputA, 0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputW, 0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2A, 0x5944E662,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2W, 0x5944E663,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput7A, 0x9A4CB684,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput7W, 0x9A4CB685,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput8A, 0xBF798030,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInput8W, 0xBF798031,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInputDeviceA, 0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDeviceW, 0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2A, 0x5944E682,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2W, 0x5944E683,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice7A, 0x57D7C6BC,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice7W, 0x57D7C6BD,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice8A, 0x54D41080,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputDevice8W, 0x54D41081,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputEffect, 0xE7E1F7C0,0x88D2,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +/* Predefined object types */ +DEFINE_GUID(GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RxAxis,0xA36D02F4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RyAxis,0xA36D02F5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RzAxis,0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Slider,0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Button,0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Key, 0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_POV, 0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Unknown,0xA36D02F3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/* Predefined product GUIDs */ +DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboard, 0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Joystick, 0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm, 0x6F1D2B80,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm2, 0x6F1D2B81,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm, 0x6F1D2B82,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm2,0x6F1D2B83,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/* predefined forcefeedback effects */ +DEFINE_GUID(GUID_ConstantForce, 0x13541C20,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_RampForce, 0x13541C21,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Square, 0x13541C22,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Sine, 0x13541C23,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Triangle, 0x13541C24,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothUp, 0x13541C25,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothDown, 0x13541C26,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Spring, 0x13541C27,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Damper, 0x13541C28,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Inertia, 0x13541C29,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Friction, 0x13541C2A,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_CustomForce, 0x13541C2B,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +typedef struct IDirectInputA *LPDIRECTINPUTA; +typedef struct IDirectInputW *LPDIRECTINPUTW; +typedef struct IDirectInput2A *LPDIRECTINPUT2A; +typedef struct IDirectInput2W *LPDIRECTINPUT2W; +typedef struct IDirectInput7A *LPDIRECTINPUT7A; +typedef struct IDirectInput7W *LPDIRECTINPUT7W; +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct IDirectInput8A *LPDIRECTINPUT8A; +typedef struct IDirectInput8W *LPDIRECTINPUT8W; +#endif /* DI8 */ +typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA; +typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW; +#if DIRECTINPUT_VERSION >= 0x0500 +typedef struct IDirectInputDevice2A *LPDIRECTINPUTDEVICE2A; +typedef struct IDirectInputDevice2W *LPDIRECTINPUTDEVICE2W; +#endif /* DI5 */ +#if DIRECTINPUT_VERSION >= 0x0700 +typedef struct IDirectInputDevice7A *LPDIRECTINPUTDEVICE7A; +typedef struct IDirectInputDevice7W *LPDIRECTINPUTDEVICE7W; +#endif /* DI7 */ +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A; +typedef struct IDirectInputDevice8W *LPDIRECTINPUTDEVICE8W; +#endif /* DI8 */ +#if DIRECTINPUT_VERSION >= 0x0500 +typedef struct IDirectInputEffect *LPDIRECTINPUTEFFECT; +#endif /* DI5 */ +typedef struct SysKeyboardA *LPSYSKEYBOARDA; +typedef struct SysMouseA *LPSYSMOUSEA; + +#define IID_IDirectInput WINELIB_NAME_AW(IID_IDirectInput) +#define IDirectInput WINELIB_NAME_AW(IDirectInput) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT) +#define IID_IDirectInput2 WINELIB_NAME_AW(IID_IDirectInput2) +#define IDirectInput2 WINELIB_NAME_AW(IDirectInput2) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT2) +#define IID_IDirectInput7 WINELIB_NAME_AW(IID_IDirectInput7) +#define IDirectInput7 WINELIB_NAME_AW(IDirectInput7) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT7) +#if DIRECTINPUT_VERSION >= 0x0800 +#define IID_IDirectInput8 WINELIB_NAME_AW(IID_IDirectInput8) +#define IDirectInput8 WINELIB_NAME_AW(IDirectInput8) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT8) +#endif /* DI8 */ +#define IID_IDirectInputDevice WINELIB_NAME_AW(IID_IDirectInputDevice) +#define IDirectInputDevice WINELIB_NAME_AW(IDirectInputDevice) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE) +#if DIRECTINPUT_VERSION >= 0x0500 +#define IID_IDirectInputDevice2 WINELIB_NAME_AW(IID_IDirectInputDevice2) +#define IDirectInputDevice2 WINELIB_NAME_AW(IDirectInputDevice2) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE2) +#endif /* DI5 */ +#if DIRECTINPUT_VERSION >= 0x0700 +#define IID_IDirectInputDevice7 WINELIB_NAME_AW(IID_IDirectInputDevice7) +#define IDirectInputDevice7 WINELIB_NAME_AW(IDirectInputDevice7) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE7) +#endif /* DI7 */ +#if DIRECTINPUT_VERSION >= 0x0800 +#define IID_IDirectInputDevice8 WINELIB_NAME_AW(IID_IDirectInputDevice8) +#define IDirectInputDevice8 WINELIB_NAME_AW(IDirectInputDevice8) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE8) +#endif /* DI8 */ + +#define DI_OK S_OK +#define DI_NOTATTACHED S_FALSE +#define DI_BUFFEROVERFLOW S_FALSE +#define DI_PROPNOEFFECT S_FALSE +#define DI_NOEFFECT S_FALSE +#define DI_POLLEDDEVICE ((HRESULT)0x00000002L) +#define DI_DOWNLOADSKIPPED ((HRESULT)0x00000003L) +#define DI_EFFECTRESTARTED ((HRESULT)0x00000004L) +#define DI_TRUNCATED ((HRESULT)0x00000008L) +#define DI_SETTINGSNOTSAVED ((HRESULT)0x0000000BL) +#define DI_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) +#define DI_WRITEPROTECT ((HRESULT)0x00000013L) + +#define DIERR_OLDDIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION) +#define DIERR_BETADIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP) +#define DIERR_BADDRIVERVER \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL) +#define DIERR_DEVICENOTREG REGDB_E_CLASSNOTREG +#define DIERR_NOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) +#define DIERR_OBJECTNOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) +#define DIERR_INVALIDPARAM E_INVALIDARG +#define DIERR_NOINTERFACE E_NOINTERFACE +#define DIERR_GENERIC E_FAIL +#define DIERR_OUTOFMEMORY E_OUTOFMEMORY +#define DIERR_UNSUPPORTED E_NOTIMPL +#define DIERR_NOTINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY) +#define DIERR_ALREADYINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED) +#define DIERR_NOAGGREGATION CLASS_E_NOAGGREGATION +#define DIERR_OTHERAPPHASPRIO E_ACCESSDENIED +#define DIERR_INPUTLOST \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT) +#define DIERR_ACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY) +#define DIERR_NOTACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS) +#define DIERR_READONLY E_ACCESSDENIED +#define DIERR_HANDLEEXISTS E_ACCESSDENIED +#ifndef E_PENDING +#define E_PENDING 0x8000000AL +#endif +#define DIERR_INSUFFICIENTPRIVS 0x80040200L +#define DIERR_DEVICEFULL 0x80040201L +#define DIERR_MOREDATA 0x80040202L +#define DIERR_NOTDOWNLOADED 0x80040203L +#define DIERR_HASEFFECTS 0x80040204L +#define DIERR_NOTEXCLUSIVEACQUIRED 0x80040205L +#define DIERR_INCOMPLETEEFFECT 0x80040206L +#define DIERR_NOTBUFFERED 0x80040207L +#define DIERR_EFFECTPLAYING 0x80040208L +#define DIERR_UNPLUGGED 0x80040209L +#define DIERR_REPORTFULL 0x8004020AL +#define DIERR_MAPFILEFAIL 0x8004020BL + +#define DIENUM_STOP 0 +#define DIENUM_CONTINUE 1 + +#define DIEDFL_ALLDEVICES 0x00000000 +#define DIEDFL_ATTACHEDONLY 0x00000001 +#define DIEDFL_FORCEFEEDBACK 0x00000100 +#define DIEDFL_INCLUDEALIASES 0x00010000 +#define DIEDFL_INCLUDEPHANTOMS 0x00020000 +#define DIEDFL_INCLUDEHIDDEN 0x00040000 + +#define DIDEVTYPE_DEVICE 1 +#define DIDEVTYPE_MOUSE 2 +#define DIDEVTYPE_KEYBOARD 3 +#define DIDEVTYPE_JOYSTICK 4 +#define DIDEVTYPE_HID 0x00010000 + +#define DI8DEVCLASS_ALL 0 +#define DI8DEVCLASS_DEVICE 1 +#define DI8DEVCLASS_POINTER 2 +#define DI8DEVCLASS_KEYBOARD 3 +#define DI8DEVCLASS_GAMECTRL 4 + +#define DI8DEVTYPE_DEVICE 0x11 +#define DI8DEVTYPE_MOUSE 0x12 +#define DI8DEVTYPE_KEYBOARD 0x13 +#define DI8DEVTYPE_JOYSTICK 0x14 +#define DI8DEVTYPE_GAMEPAD 0x15 +#define DI8DEVTYPE_DRIVING 0x16 +#define DI8DEVTYPE_FLIGHT 0x17 +#define DI8DEVTYPE_1STPERSON 0x18 +#define DI8DEVTYPE_DEVICECTRL 0x19 +#define DI8DEVTYPE_SCREENPOINTER 0x1A +#define DI8DEVTYPE_REMOTE 0x1B +#define DI8DEVTYPE_SUPPLEMENTAL 0x1C + +#define DIDEVTYPEMOUSE_UNKNOWN 1 +#define DIDEVTYPEMOUSE_TRADITIONAL 2 +#define DIDEVTYPEMOUSE_FINGERSTICK 3 +#define DIDEVTYPEMOUSE_TOUCHPAD 4 +#define DIDEVTYPEMOUSE_TRACKBALL 5 + +#define DIDEVTYPEKEYBOARD_UNKNOWN 0 +#define DIDEVTYPEKEYBOARD_PCXT 1 +#define DIDEVTYPEKEYBOARD_OLIVETTI 2 +#define DIDEVTYPEKEYBOARD_PCAT 3 +#define DIDEVTYPEKEYBOARD_PCENH 4 +#define DIDEVTYPEKEYBOARD_NOKIA1050 5 +#define DIDEVTYPEKEYBOARD_NOKIA9140 6 +#define DIDEVTYPEKEYBOARD_NEC98 7 +#define DIDEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DIDEVTYPEKEYBOARD_NEC98106 9 +#define DIDEVTYPEKEYBOARD_JAPAN106 10 +#define DIDEVTYPEKEYBOARD_JAPANAX 11 +#define DIDEVTYPEKEYBOARD_J3100 12 + +#define DIDEVTYPEJOYSTICK_UNKNOWN 1 +#define DIDEVTYPEJOYSTICK_TRADITIONAL 2 +#define DIDEVTYPEJOYSTICK_FLIGHTSTICK 3 +#define DIDEVTYPEJOYSTICK_GAMEPAD 4 +#define DIDEVTYPEJOYSTICK_RUDDER 5 +#define DIDEVTYPEJOYSTICK_WHEEL 6 +#define DIDEVTYPEJOYSTICK_HEADTRACKER 7 + +#define DI8DEVTYPEMOUSE_UNKNOWN 1 +#define DI8DEVTYPEMOUSE_TRADITIONAL 2 +#define DI8DEVTYPEMOUSE_FINGERSTICK 3 +#define DI8DEVTYPEMOUSE_TOUCHPAD 4 +#define DI8DEVTYPEMOUSE_TRACKBALL 5 +#define DI8DEVTYPEMOUSE_ABSOLUTE 6 + +#define DI8DEVTYPEKEYBOARD_UNKNOWN 0 +#define DI8DEVTYPEKEYBOARD_PCXT 1 +#define DI8DEVTYPEKEYBOARD_OLIVETTI 2 +#define DI8DEVTYPEKEYBOARD_PCAT 3 +#define DI8DEVTYPEKEYBOARD_PCENH 4 +#define DI8DEVTYPEKEYBOARD_NOKIA1050 5 +#define DI8DEVTYPEKEYBOARD_NOKIA9140 6 +#define DI8DEVTYPEKEYBOARD_NEC98 7 +#define DI8DEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DI8DEVTYPEKEYBOARD_NEC98106 9 +#define DI8DEVTYPEKEYBOARD_JAPAN106 10 +#define DI8DEVTYPEKEYBOARD_JAPANAX 11 +#define DI8DEVTYPEKEYBOARD_J3100 12 + +#define DI8DEVTYPE_LIMITEDGAMESUBTYPE 1 + +#define DI8DEVTYPEJOYSTICK_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEJOYSTICK_STANDARD 2 + +#define DI8DEVTYPEGAMEPAD_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEGAMEPAD_STANDARD 2 +#define DI8DEVTYPEGAMEPAD_TILT 3 + +#define DI8DEVTYPEDRIVING_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEDRIVING_COMBINEDPEDALS 2 +#define DI8DEVTYPEDRIVING_DUALPEDALS 3 +#define DI8DEVTYPEDRIVING_THREEPEDALS 4 +#define DI8DEVTYPEDRIVING_HANDHELD 5 + +#define DI8DEVTYPEFLIGHT_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEFLIGHT_STICK 2 +#define DI8DEVTYPEFLIGHT_YOKE 3 +#define DI8DEVTYPEFLIGHT_RC 4 + +#define DI8DEVTYPE1STPERSON_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPE1STPERSON_UNKNOWN 2 +#define DI8DEVTYPE1STPERSON_SIXDOF 3 +#define DI8DEVTYPE1STPERSON_SHOOTER 4 + +#define DI8DEVTYPESCREENPTR_UNKNOWN 2 +#define DI8DEVTYPESCREENPTR_LIGHTGUN 3 +#define DI8DEVTYPESCREENPTR_LIGHTPEN 4 +#define DI8DEVTYPESCREENPTR_TOUCH 5 + +#define DI8DEVTYPEREMOTE_UNKNOWN 2 + +#define DI8DEVTYPEDEVICECTRL_UNKNOWN 2 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION 3 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION_HARDWIRED 4 + +#define DI8DEVTYPESUPPLEMENTAL_UNKNOWN 2 +#define DI8DEVTYPESUPPLEMENTAL_2NDHANDCONTROLLER 3 +#define DI8DEVTYPESUPPLEMENTAL_HEADTRACKER 4 +#define DI8DEVTYPESUPPLEMENTAL_HANDTRACKER 5 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTSTICKGATE 6 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTER 7 +#define DI8DEVTYPESUPPLEMENTAL_THROTTLE 8 +#define DI8DEVTYPESUPPLEMENTAL_SPLITTHROTTLE 9 +#define DI8DEVTYPESUPPLEMENTAL_COMBINEDPEDALS 10 +#define DI8DEVTYPESUPPLEMENTAL_DUALPEDALS 11 +#define DI8DEVTYPESUPPLEMENTAL_THREEPEDALS 12 +#define DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS 13 + +#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) +#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) + +typedef struct DIDEVICEOBJECTINSTANCE_DX3A { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3A, *LPDIDEVICEOBJECTINSTANCE_DX3A; +typedef const DIDEVICEOBJECTINSTANCE_DX3A *LPCDIDEVICEOBJECTINSTANCE_DX3A; +typedef struct DIDEVICEOBJECTINSTANCE_DX3W { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3W, *LPDIDEVICEOBJECTINSTANCE_DX3W; +typedef const DIDEVICEOBJECTINSTANCE_DX3W *LPCDIDEVICEOBJECTINSTANCE_DX3W; + +DECL_WINELIB_TYPE_AW(DIDEVICEOBJECTINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPDIDEVICEOBJECTINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEOBJECTINSTANCE_DX3) + +typedef struct DIDEVICEOBJECTINSTANCEA { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReserved; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA; +typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA; + +typedef struct DIDEVICEOBJECTINSTANCEW { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReserved; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW; +typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW; + +DECL_WINELIB_TYPE_AW(DIDEVICEOBJECTINSTANCE) +DECL_WINELIB_TYPE_AW(LPDIDEVICEOBJECTINSTANCE) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEOBJECTINSTANCE) + +typedef struct DIDEVICEINSTANCE_DX3A { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3A, *LPDIDEVICEINSTANCE_DX3A; +typedef const DIDEVICEINSTANCE_DX3A *LPCDIDEVICEINSTANCE_DX3A; +typedef struct DIDEVICEINSTANCE_DX3W { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3W, *LPDIDEVICEINSTANCE_DX3W; +typedef const DIDEVICEINSTANCE_DX3W *LPCDIDEVICEINSTANCE_DX3W; + +DECL_WINELIB_TYPE_AW(DIDEVICEINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPDIDEVICEINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEINSTANCE_DX3) + +typedef struct DIDEVICEINSTANCEA { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA; +typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA; + +typedef struct DIDEVICEINSTANCEW { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW; +typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW; + +DECL_WINELIB_TYPE_AW(DIDEVICEINSTANCE) +DECL_WINELIB_TYPE_AW(LPDIDEVICEINSTANCE) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEINSTANCE) + +typedef BOOL (CALLBACK *LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA,LPVOID); +typedef BOOL (CALLBACK *LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW,LPVOID); +DECL_WINELIB_TYPE_AW(LPDIENUMDEVICESCALLBACK) + +#define DIEDBS_MAPPEDPRI1 0x00000001 +#define DIEDBS_MAPPEDPRI2 0x00000002 +#define DIEDBS_RECENTDEVICE 0x00000010 +#define DIEDBS_NEWDEVICE 0x00000020 + +#define DIEDBSFL_ATTACHEDONLY 0x00000000 +#define DIEDBSFL_THISUSER 0x00000010 +#define DIEDBSFL_FORCEFEEDBACK DIEDFL_FORCEFEEDBACK +#define DIEDBSFL_AVAILABLEDEVICES 0x00001000 +#define DIEDBSFL_MULTIMICEKEYBOARDS 0x00002000 +#define DIEDBSFL_NONGAMINGDEVICES 0x00004000 +#define DIEDBSFL_VALID 0x00007110 + +#if DIRECTINPUT_VERSION >= 0x0800 +typedef BOOL (CALLBACK *LPDIENUMDEVICESBYSEMANTICSCBA)(LPCDIDEVICEINSTANCEA,LPDIRECTINPUTDEVICE8A,DWORD,DWORD,LPVOID); +typedef BOOL (CALLBACK *LPDIENUMDEVICESBYSEMANTICSCBW)(LPCDIDEVICEINSTANCEW,LPDIRECTINPUTDEVICE8W,DWORD,DWORD,LPVOID); +DECL_WINELIB_TYPE_AW(LPDIENUMDEVICESBYSEMANTICSCB) +#endif + +typedef BOOL (CALLBACK *LPDICONFIGUREDEVICESCALLBACK)(LPUNKNOWN,LPVOID); + +typedef BOOL (CALLBACK *LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA,LPVOID); +typedef BOOL (CALLBACK *LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW,LPVOID); +DECL_WINELIB_TYPE_AW(LPDIENUMDEVICEOBJECTSCALLBACK) + +#if DIRECTINPUT_VERSION >= 0x0500 +typedef BOOL (CALLBACK *LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID); +#endif + +#define DIK_ESCAPE 0x01 +#define DIK_1 0x02 +#define DIK_2 0x03 +#define DIK_3 0x04 +#define DIK_4 0x05 +#define DIK_5 0x06 +#define DIK_6 0x07 +#define DIK_7 0x08 +#define DIK_8 0x09 +#define DIK_9 0x0A +#define DIK_0 0x0B +#define DIK_MINUS 0x0C /* - on main keyboard */ +#define DIK_EQUALS 0x0D +#define DIK_BACK 0x0E /* backspace */ +#define DIK_TAB 0x0F +#define DIK_Q 0x10 +#define DIK_W 0x11 +#define DIK_E 0x12 +#define DIK_R 0x13 +#define DIK_T 0x14 +#define DIK_Y 0x15 +#define DIK_U 0x16 +#define DIK_I 0x17 +#define DIK_O 0x18 +#define DIK_P 0x19 +#define DIK_LBRACKET 0x1A +#define DIK_RBRACKET 0x1B +#define DIK_RETURN 0x1C /* Enter on main keyboard */ +#define DIK_LCONTROL 0x1D +#define DIK_A 0x1E +#define DIK_S 0x1F +#define DIK_D 0x20 +#define DIK_F 0x21 +#define DIK_G 0x22 +#define DIK_H 0x23 +#define DIK_J 0x24 +#define DIK_K 0x25 +#define DIK_L 0x26 +#define DIK_SEMICOLON 0x27 +#define DIK_APOSTROPHE 0x28 +#define DIK_GRAVE 0x29 /* accent grave */ +#define DIK_LSHIFT 0x2A +#define DIK_BACKSLASH 0x2B +#define DIK_Z 0x2C +#define DIK_X 0x2D +#define DIK_C 0x2E +#define DIK_V 0x2F +#define DIK_B 0x30 +#define DIK_N 0x31 +#define DIK_M 0x32 +#define DIK_COMMA 0x33 +#define DIK_PERIOD 0x34 /* . on main keyboard */ +#define DIK_SLASH 0x35 /* / on main keyboard */ +#define DIK_RSHIFT 0x36 +#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ +#define DIK_LMENU 0x38 /* left Alt */ +#define DIK_SPACE 0x39 +#define DIK_CAPITAL 0x3A +#define DIK_F1 0x3B +#define DIK_F2 0x3C +#define DIK_F3 0x3D +#define DIK_F4 0x3E +#define DIK_F5 0x3F +#define DIK_F6 0x40 +#define DIK_F7 0x41 +#define DIK_F8 0x42 +#define DIK_F9 0x43 +#define DIK_F10 0x44 +#define DIK_NUMLOCK 0x45 +#define DIK_SCROLL 0x46 /* Scroll Lock */ +#define DIK_NUMPAD7 0x47 +#define DIK_NUMPAD8 0x48 +#define DIK_NUMPAD9 0x49 +#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ +#define DIK_NUMPAD4 0x4B +#define DIK_NUMPAD5 0x4C +#define DIK_NUMPAD6 0x4D +#define DIK_ADD 0x4E /* + on numeric keypad */ +#define DIK_NUMPAD1 0x4F +#define DIK_NUMPAD2 0x50 +#define DIK_NUMPAD3 0x51 +#define DIK_NUMPAD0 0x52 +#define DIK_DECIMAL 0x53 /* . on numeric keypad */ +#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */ +#define DIK_F11 0x57 +#define DIK_F12 0x58 +#define DIK_F13 0x64 /* (NEC PC98) */ +#define DIK_F14 0x65 /* (NEC PC98) */ +#define DIK_F15 0x66 /* (NEC PC98) */ +#define DIK_KANA 0x70 /* (Japanese keyboard) */ +#define DIK_ABNT_C1 0x73 /* / ? on Portugese (Brazilian) keyboards */ +#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ +#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ +#define DIK_YEN 0x7D /* (Japanese keyboard) */ +#define DIK_ABNT_C2 0x7E /* Numpad . on Portugese (Brazilian) keyboards */ +#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ +#define DIK_CIRCUMFLEX 0x90 /* (Japanese keyboard) */ +#define DIK_AT 0x91 /* (NEC PC98) */ +#define DIK_COLON 0x92 /* (NEC PC98) */ +#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ +#define DIK_KANJI 0x94 /* (Japanese keyboard) */ +#define DIK_STOP 0x95 /* (NEC PC98) */ +#define DIK_AX 0x96 /* (Japan AX) */ +#define DIK_UNLABELED 0x97 /* (J3100) */ +#define DIK_NEXTTRACK 0x99 /* Next Track */ +#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ +#define DIK_RCONTROL 0x9D +#define DIK_MUTE 0xA0 /* Mute */ +#define DIK_CALCULATOR 0xA1 /* Calculator */ +#define DIK_PLAYPAUSE 0xA2 /* Play / Pause */ +#define DIK_MEDIASTOP 0xA4 /* Media Stop */ +#define DIK_VOLUMEDOWN 0xAE /* Volume - */ +#define DIK_VOLUMEUP 0xB0 /* Volume + */ +#define DIK_WEBHOME 0xB2 /* Web home */ +#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ +#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ +#define DIK_SYSRQ 0xB7 +#define DIK_RMENU 0xB8 /* right Alt */ +#define DIK_PAUSE 0xC5 /* Pause */ +#define DIK_HOME 0xC7 /* Home on arrow keypad */ +#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ +#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ +#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ +#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ +#define DIK_END 0xCF /* End on arrow keypad */ +#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ +#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ +#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ +#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ +#define DIK_LWIN 0xDB /* Left Windows key */ +#define DIK_RWIN 0xDC /* Right Windows key */ +#define DIK_APPS 0xDD /* AppMenu key */ +#define DIK_POWER 0xDE +#define DIK_SLEEP 0xDF +#define DIK_WAKE 0xE3 /* System Wake */ +#define DIK_WEBSEARCH 0xE5 /* Web Search */ +#define DIK_WEBFAVORITES 0xE6 /* Web Favorites */ +#define DIK_WEBREFRESH 0xE7 /* Web Refresh */ +#define DIK_WEBSTOP 0xE8 /* Web Stop */ +#define DIK_WEBFORWARD 0xE9 /* Web Forward */ +#define DIK_WEBBACK 0xEA /* Web Back */ +#define DIK_MYCOMPUTER 0xEB /* My Computer */ +#define DIK_MAIL 0xEC /* Mail */ +#define DIK_MEDIASELECT 0xED /* Media Select */ + +#define DIK_BACKSPACE DIK_BACK /* backspace */ +#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ +#define DIK_LALT DIK_LMENU /* left Alt */ +#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ +#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ +#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ +#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ +#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ +#define DIK_RALT DIK_RMENU /* right Alt */ +#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ +#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ +#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ +#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ +#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ +#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ + +#define DIDFT_ALL 0x00000000 +#define DIDFT_RELAXIS 0x00000001 +#define DIDFT_ABSAXIS 0x00000002 +#define DIDFT_AXIS 0x00000003 +#define DIDFT_PSHBUTTON 0x00000004 +#define DIDFT_TGLBUTTON 0x00000008 +#define DIDFT_BUTTON 0x0000000C +#define DIDFT_POV 0x00000010 +#define DIDFT_COLLECTION 0x00000040 +#define DIDFT_NODATA 0x00000080 +#define DIDFT_ANYINSTANCE 0x00FFFF00 +#define DIDFT_INSTANCEMASK DIDFT_ANYINSTANCE +#define DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8) +#define DIDFT_GETTYPE(n) LOBYTE(n) +#define DIDFT_GETINSTANCE(n) LOWORD((n) >> 8) +#define DIDFT_FFACTUATOR 0x01000000 +#define DIDFT_FFEFFECTTRIGGER 0x02000000 +#if DIRECTINPUT_VERSION >= 0x050a +#define DIDFT_OUTPUT 0x10000000 +#define DIDFT_VENDORDEFINED 0x04000000 +#define DIDFT_ALIAS 0x08000000 +#endif /* DI5a */ +#ifndef DIDFT_OPTIONAL +#define DIDFT_OPTIONAL 0x80000000 +#endif +#define DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8) +#define DIDFT_NOCOLLECTION 0x00FFFF00 + +#define DIDF_ABSAXIS 0x00000001 +#define DIDF_RELAXIS 0x00000002 + +#define DIGDD_PEEK 0x00000001 + +#define DISEQUENCE_COMPARE(dwSq1,cmp,dwSq2) ((int)((dwSq1) - (dwSq2)) cmp 0) + +typedef struct DIDEVICEOBJECTDATA_DX3 { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +} DIDEVICEOBJECTDATA_DX3,*LPDIDEVICEOBJECTDATA_DX3; +typedef const DIDEVICEOBJECTDATA_DX3 *LPCDIDEVICEOBJECTDATA_DX3; + +typedef struct DIDEVICEOBJECTDATA { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +#if(DIRECTINPUT_VERSION >= 0x0800) + UINT_PTR uAppData; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ +} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; +typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA; + +typedef struct _DIOBJECTDATAFORMAT { + const GUID *pguid; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; +} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT; +typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT; + +typedef struct _DIDATAFORMAT { + DWORD dwSize; + DWORD dwObjSize; + DWORD dwFlags; + DWORD dwDataSize; + DWORD dwNumObjs; + LPDIOBJECTDATAFORMAT rgodf; +} DIDATAFORMAT, *LPDIDATAFORMAT; +typedef const DIDATAFORMAT *LPCDIDATAFORMAT; + +#if DIRECTINPUT_VERSION >= 0x0500 +#define DIDOI_FFACTUATOR 0x00000001 +#define DIDOI_FFEFFECTTRIGGER 0x00000002 +#define DIDOI_POLLED 0x00008000 +#define DIDOI_ASPECTPOSITION 0x00000100 +#define DIDOI_ASPECTVELOCITY 0x00000200 +#define DIDOI_ASPECTACCEL 0x00000300 +#define DIDOI_ASPECTFORCE 0x00000400 +#define DIDOI_ASPECTMASK 0x00000F00 +#endif /* DI5 */ +#if DIRECTINPUT_VERSION >= 0x050a +#define DIDOI_GUIDISUSAGE 0x00010000 +#endif /* DI5a */ + +typedef struct DIPROPHEADER { + DWORD dwSize; + DWORD dwHeaderSize; + DWORD dwObj; + DWORD dwHow; +} DIPROPHEADER,*LPDIPROPHEADER; +typedef const DIPROPHEADER *LPCDIPROPHEADER; + +#define DIPH_DEVICE 0 +#define DIPH_BYOFFSET 1 +#define DIPH_BYID 2 +#if DIRECTINPUT_VERSION >= 0x050a +#define DIPH_BYUSAGE 3 + +#define DIMAKEUSAGEDWORD(UsagePage, Usage) (DWORD)MAKELONG(Usage, UsagePage) +#endif /* DI5a */ + +typedef struct DIPROPDWORD { + DIPROPHEADER diph; + DWORD dwData; +} DIPROPDWORD, *LPDIPROPDWORD; +typedef const DIPROPDWORD *LPCDIPROPDWORD; + +typedef struct DIPROPRANGE { + DIPROPHEADER diph; + LONG lMin; + LONG lMax; +} DIPROPRANGE, *LPDIPROPRANGE; +typedef const DIPROPRANGE *LPCDIPROPRANGE; + +#define DIPROPRANGE_NOMIN ((LONG)0x80000000) +#define DIPROPRANGE_NOMAX ((LONG)0x7FFFFFFF) + +#if DIRECTINPUT_VERSION >= 0x050a +typedef struct DIPROPCAL { + DIPROPHEADER diph; + LONG lMin; + LONG lCenter; + LONG lMax; +} DIPROPCAL, *LPDIPROPCAL; +typedef const DIPROPCAL *LPCDIPROPCAL; + +typedef struct DIPROPCALPOV { + DIPROPHEADER diph; + LONG lMin[5]; + LONG lMax[5]; +} DIPROPCALPOV, *LPDIPROPCALPOV; +typedef const DIPROPCALPOV *LPCDIPROPCALPOV; + +typedef struct DIPROPGUIDANDPATH { + DIPROPHEADER diph; + GUID guidClass; + WCHAR wszPath[MAX_PATH]; +} DIPROPGUIDANDPATH, *LPDIPROPGUIDANDPATH; +typedef const DIPROPGUIDANDPATH *LPCDIPROPGUIDANDPATH; + +typedef struct DIPROPSTRING { + DIPROPHEADER diph; + WCHAR wsz[MAX_PATH]; +} DIPROPSTRING, *LPDIPROPSTRING; +typedef const DIPROPSTRING *LPCDIPROPSTRING; +#endif /* DI5a */ + +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct DIPROPPOINTER { + DIPROPHEADER diph; + UINT_PTR uData; +} DIPROPPOINTER, *LPDIPROPPOINTER; +typedef const DIPROPPOINTER *LPCDIPROPPOINTER; +#endif /* DI8 */ + +/* special property GUIDs */ +#ifdef __cplusplus +#define MAKEDIPROP(prop) (*(const GUID *)(prop)) +#else +#define MAKEDIPROP(prop) ((REFGUID)(prop)) +#endif +#define DIPROP_BUFFERSIZE MAKEDIPROP(1) +#define DIPROP_AXISMODE MAKEDIPROP(2) + +#define DIPROPAXISMODE_ABS 0 +#define DIPROPAXISMODE_REL 1 + +#define DIPROP_GRANULARITY MAKEDIPROP(3) +#define DIPROP_RANGE MAKEDIPROP(4) +#define DIPROP_DEADZONE MAKEDIPROP(5) +#define DIPROP_SATURATION MAKEDIPROP(6) +#define DIPROP_FFGAIN MAKEDIPROP(7) +#define DIPROP_FFLOAD MAKEDIPROP(8) +#define DIPROP_AUTOCENTER MAKEDIPROP(9) + +#define DIPROPAUTOCENTER_OFF 0 +#define DIPROPAUTOCENTER_ON 1 + +#define DIPROP_CALIBRATIONMODE MAKEDIPROP(10) + +#define DIPROPCALIBRATIONMODE_COOKED 0 +#define DIPROPCALIBRATIONMODE_RAW 1 + +#if DIRECTINPUT_VERSION >= 0x050a +#define DIPROP_CALIBRATION MAKEDIPROP(11) +#define DIPROP_GUIDANDPATH MAKEDIPROP(12) +#define DIPROP_INSTANCENAME MAKEDIPROP(13) +#define DIPROP_PRODUCTNAME MAKEDIPROP(14) +#endif + +#if DIRECTINPUT_VERSION >= 0x5B2 +#define DIPROP_JOYSTICKID MAKEDIPROP(15) +#define DIPROP_GETPORTDISPLAYNAME MAKEDIPROP(16) +#endif + +#if DIRECTINPUT_VERSION >= 0x0700 +#define DIPROP_PHYSICALRANGE MAKEDIPROP(18) +#define DIPROP_LOGICALRANGE MAKEDIPROP(19) +#endif + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIPROP_KEYNAME MAKEDIPROP(20) +#define DIPROP_CPOINTS MAKEDIPROP(21) +#define DIPROP_APPDATA MAKEDIPROP(22) +#define DIPROP_SCANCODE MAKEDIPROP(23) +#define DIPROP_VIDPID MAKEDIPROP(24) +#define DIPROP_USERNAME MAKEDIPROP(25) +#define DIPROP_TYPENAME MAKEDIPROP(26) + +#define MAXCPOINTSNUM 8 + +typedef struct _CPOINT { + LONG lP; + DWORD dwLog; +} CPOINT, *PCPOINT; + +typedef struct DIPROPCPOINTS { + DIPROPHEADER diph; + DWORD dwCPointsNum; + CPOINT cp[MAXCPOINTSNUM]; +} DIPROPCPOINTS, *LPDIPROPCPOINTS; +typedef const DIPROPCPOINTS *LPCDIPROPCPOINTS; +#endif /* DI8 */ + + +typedef struct DIDEVCAPS_DX3 { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +} DIDEVCAPS_DX3, *LPDIDEVCAPS_DX3; + +typedef struct DIDEVCAPS { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFSamplePeriod; + DWORD dwFFMinTimeResolution; + DWORD dwFirmwareRevision; + DWORD dwHardwareRevision; + DWORD dwFFDriverVersion; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVCAPS,*LPDIDEVCAPS; + +#define DIDC_ATTACHED 0x00000001 +#define DIDC_POLLEDDEVICE 0x00000002 +#define DIDC_EMULATED 0x00000004 +#define DIDC_POLLEDDATAFORMAT 0x00000008 +#define DIDC_FORCEFEEDBACK 0x00000100 +#define DIDC_FFATTACK 0x00000200 +#define DIDC_FFFADE 0x00000400 +#define DIDC_SATURATION 0x00000800 +#define DIDC_POSNEGCOEFFICIENTS 0x00001000 +#define DIDC_POSNEGSATURATION 0x00002000 +#define DIDC_DEADBAND 0x00004000 +#define DIDC_STARTDELAY 0x00008000 +#define DIDC_ALIAS 0x00010000 +#define DIDC_PHANTOM 0x00020000 +#define DIDC_HIDDEN 0x00040000 + + +/* SetCooperativeLevel dwFlags */ +#define DISCL_EXCLUSIVE 0x00000001 +#define DISCL_NONEXCLUSIVE 0x00000002 +#define DISCL_FOREGROUND 0x00000004 +#define DISCL_BACKGROUND 0x00000008 +#define DISCL_NOWINKEY 0x00000010 + +#if (DIRECTINPUT_VERSION >= 0x0500) +/* Device FF flags */ +#define DISFFC_RESET 0x00000001 +#define DISFFC_STOPALL 0x00000002 +#define DISFFC_PAUSE 0x00000004 +#define DISFFC_CONTINUE 0x00000008 +#define DISFFC_SETACTUATORSON 0x00000010 +#define DISFFC_SETACTUATORSOFF 0x00000020 + +#define DIGFFS_EMPTY 0x00000001 +#define DIGFFS_STOPPED 0x00000002 +#define DIGFFS_PAUSED 0x00000004 +#define DIGFFS_ACTUATORSON 0x00000010 +#define DIGFFS_ACTUATORSOFF 0x00000020 +#define DIGFFS_POWERON 0x00000040 +#define DIGFFS_POWEROFF 0x00000080 +#define DIGFFS_SAFETYSWITCHON 0x00000100 +#define DIGFFS_SAFETYSWITCHOFF 0x00000200 +#define DIGFFS_USERFFSWITCHON 0x00000400 +#define DIGFFS_USERFFSWITCHOFF 0x00000800 +#define DIGFFS_DEVICELOST 0x80000000 + +/* Effect flags */ +#define DIEFT_ALL 0x00000000 + +#define DIEFT_CONSTANTFORCE 0x00000001 +#define DIEFT_RAMPFORCE 0x00000002 +#define DIEFT_PERIODIC 0x00000003 +#define DIEFT_CONDITION 0x00000004 +#define DIEFT_CUSTOMFORCE 0x00000005 +#define DIEFT_HARDWARE 0x000000FF +#define DIEFT_FFATTACK 0x00000200 +#define DIEFT_FFFADE 0x00000400 +#define DIEFT_SATURATION 0x00000800 +#define DIEFT_POSNEGCOEFFICIENTS 0x00001000 +#define DIEFT_POSNEGSATURATION 0x00002000 +#define DIEFT_DEADBAND 0x00004000 +#define DIEFT_STARTDELAY 0x00008000 +#define DIEFT_GETTYPE(n) LOBYTE(n) + +#define DIEFF_OBJECTIDS 0x00000001 +#define DIEFF_OBJECTOFFSETS 0x00000002 +#define DIEFF_CARTESIAN 0x00000010 +#define DIEFF_POLAR 0x00000020 +#define DIEFF_SPHERICAL 0x00000040 + +#define DIEP_DURATION 0x00000001 +#define DIEP_SAMPLEPERIOD 0x00000002 +#define DIEP_GAIN 0x00000004 +#define DIEP_TRIGGERBUTTON 0x00000008 +#define DIEP_TRIGGERREPEATINTERVAL 0x00000010 +#define DIEP_AXES 0x00000020 +#define DIEP_DIRECTION 0x00000040 +#define DIEP_ENVELOPE 0x00000080 +#define DIEP_TYPESPECIFICPARAMS 0x00000100 +#if(DIRECTINPUT_VERSION >= 0x0600) +#define DIEP_STARTDELAY 0x00000200 +#define DIEP_ALLPARAMS_DX5 0x000001FF +#define DIEP_ALLPARAMS 0x000003FF +#else +#define DIEP_ALLPARAMS 0x000001FF +#endif /* DIRECTINPUT_VERSION >= 0x0600 */ +#define DIEP_START 0x20000000 +#define DIEP_NORESTART 0x40000000 +#define DIEP_NODOWNLOAD 0x80000000 +#define DIEB_NOTRIGGER 0xFFFFFFFF + +#define DIES_SOLO 0x00000001 +#define DIES_NODOWNLOAD 0x80000000 + +#define DIEGES_PLAYING 0x00000001 +#define DIEGES_EMULATED 0x00000002 + +#define DI_DEGREES 100 +#define DI_FFNOMINALMAX 10000 +#define DI_SECONDS 1000000 + +typedef struct DICONSTANTFORCE { + LONG lMagnitude; +} DICONSTANTFORCE, *LPDICONSTANTFORCE; +typedef const DICONSTANTFORCE *LPCDICONSTANTFORCE; + +typedef struct DIRAMPFORCE { + LONG lStart; + LONG lEnd; +} DIRAMPFORCE, *LPDIRAMPFORCE; +typedef const DIRAMPFORCE *LPCDIRAMPFORCE; + +typedef struct DIPERIODIC { + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; +} DIPERIODIC, *LPDIPERIODIC; +typedef const DIPERIODIC *LPCDIPERIODIC; + +typedef struct DICONDITION { + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; +} DICONDITION, *LPDICONDITION; +typedef const DICONDITION *LPCDICONDITION; + +typedef struct DICUSTOMFORCE { + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; +} DICUSTOMFORCE, *LPDICUSTOMFORCE; +typedef const DICUSTOMFORCE *LPCDICUSTOMFORCE; + +typedef struct DIENVELOPE { + DWORD dwSize; + DWORD dwAttackLevel; + DWORD dwAttackTime; + DWORD dwFadeLevel; + DWORD dwFadeTime; +} DIENVELOPE, *LPDIENVELOPE; +typedef const DIENVELOPE *LPCDIENVELOPE; + +typedef struct DIEFFECT_DX5 { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDuration; + DWORD dwSamplePeriod; + DWORD dwGain; + DWORD dwTriggerButton; + DWORD dwTriggerRepeatInterval; + DWORD cAxes; + LPDWORD rgdwAxes; + LPLONG rglDirection; + LPDIENVELOPE lpEnvelope; + DWORD cbTypeSpecificParams; + LPVOID lpvTypeSpecificParams; +} DIEFFECT_DX5, *LPDIEFFECT_DX5; +typedef const DIEFFECT_DX5 *LPCDIEFFECT_DX5; + +typedef struct DIEFFECT { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDuration; + DWORD dwSamplePeriod; + DWORD dwGain; + DWORD dwTriggerButton; + DWORD dwTriggerRepeatInterval; + DWORD cAxes; + LPDWORD rgdwAxes; + LPLONG rglDirection; + LPDIENVELOPE lpEnvelope; + DWORD cbTypeSpecificParams; + LPVOID lpvTypeSpecificParams; +#if(DIRECTINPUT_VERSION >= 0x0600) + DWORD dwStartDelay; +#endif /* DIRECTINPUT_VERSION >= 0x0600 */ +} DIEFFECT, *LPDIEFFECT; +typedef const DIEFFECT *LPCDIEFFECT; +typedef DIEFFECT DIEFFECT_DX6; +typedef LPDIEFFECT LPDIEFFECT_DX6; + +typedef struct DIEFFECTINFOA { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + CHAR tszName[MAX_PATH]; +} DIEFFECTINFOA, *LPDIEFFECTINFOA; +typedef const DIEFFECTINFOA *LPCDIEFFECTINFOA; + +typedef struct DIEFFECTINFOW { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + WCHAR tszName[MAX_PATH]; +} DIEFFECTINFOW, *LPDIEFFECTINFOW; +typedef const DIEFFECTINFOW *LPCDIEFFECTINFOW; + +DECL_WINELIB_TYPE_AW(DIEFFECTINFO) +DECL_WINELIB_TYPE_AW(LPDIEFFECTINFO) +DECL_WINELIB_TYPE_AW(LPCDIEFFECTINFO) + +typedef BOOL (CALLBACK *LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID); +typedef BOOL (CALLBACK *LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID); + +typedef struct DIEFFESCAPE { + DWORD dwSize; + DWORD dwCommand; + LPVOID lpvInBuffer; + DWORD cbInBuffer; + LPVOID lpvOutBuffer; + DWORD cbOutBuffer; +} DIEFFESCAPE, *LPDIEFFESCAPE; + +typedef struct DIJOYSTATE { + LONG lX; + LONG lY; + LONG lZ; + LONG lRx; + LONG lRy; + LONG lRz; + LONG rglSlider[2]; + DWORD rgdwPOV[4]; + BYTE rgbButtons[32]; +} DIJOYSTATE, *LPDIJOYSTATE; + +typedef struct DIJOYSTATE2 { + LONG lX; + LONG lY; + LONG lZ; + LONG lRx; + LONG lRy; + LONG lRz; + LONG rglSlider[2]; + DWORD rgdwPOV[4]; + BYTE rgbButtons[128]; + LONG lVX; /* 'v' as in velocity */ + LONG lVY; + LONG lVZ; + LONG lVRx; + LONG lVRy; + LONG lVRz; + LONG rglVSlider[2]; + LONG lAX; /* 'a' as in acceleration */ + LONG lAY; + LONG lAZ; + LONG lARx; + LONG lARy; + LONG lARz; + LONG rglASlider[2]; + LONG lFX; /* 'f' as in force */ + LONG lFY; + LONG lFZ; + LONG lFRx; /* 'fr' as in rotational force aka torque */ + LONG lFRy; + LONG lFRz; + LONG rglFSlider[2]; +} DIJOYSTATE2, *LPDIJOYSTATE2; + +#define DIJOFS_X FIELD_OFFSET(DIJOYSTATE, lX) +#define DIJOFS_Y FIELD_OFFSET(DIJOYSTATE, lY) +#define DIJOFS_Z FIELD_OFFSET(DIJOYSTATE, lZ) +#define DIJOFS_RX FIELD_OFFSET(DIJOYSTATE, lRx) +#define DIJOFS_RY FIELD_OFFSET(DIJOYSTATE, lRy) +#define DIJOFS_RZ FIELD_OFFSET(DIJOYSTATE, lRz) +#define DIJOFS_SLIDER(n) (FIELD_OFFSET(DIJOYSTATE, rglSlider) + \ + (n) * sizeof(LONG)) +#define DIJOFS_POV(n) (FIELD_OFFSET(DIJOYSTATE, rgdwPOV) + \ + (n) * sizeof(DWORD)) +#define DIJOFS_BUTTON(n) (FIELD_OFFSET(DIJOYSTATE, rgbButtons) + (n)) +#define DIJOFS_BUTTON0 DIJOFS_BUTTON(0) +#define DIJOFS_BUTTON1 DIJOFS_BUTTON(1) +#define DIJOFS_BUTTON2 DIJOFS_BUTTON(2) +#define DIJOFS_BUTTON3 DIJOFS_BUTTON(3) +#define DIJOFS_BUTTON4 DIJOFS_BUTTON(4) +#define DIJOFS_BUTTON5 DIJOFS_BUTTON(5) +#define DIJOFS_BUTTON6 DIJOFS_BUTTON(6) +#define DIJOFS_BUTTON7 DIJOFS_BUTTON(7) +#define DIJOFS_BUTTON8 DIJOFS_BUTTON(8) +#define DIJOFS_BUTTON9 DIJOFS_BUTTON(9) +#define DIJOFS_BUTTON10 DIJOFS_BUTTON(10) +#define DIJOFS_BUTTON11 DIJOFS_BUTTON(11) +#define DIJOFS_BUTTON12 DIJOFS_BUTTON(12) +#define DIJOFS_BUTTON13 DIJOFS_BUTTON(13) +#define DIJOFS_BUTTON14 DIJOFS_BUTTON(14) +#define DIJOFS_BUTTON15 DIJOFS_BUTTON(15) +#define DIJOFS_BUTTON16 DIJOFS_BUTTON(16) +#define DIJOFS_BUTTON17 DIJOFS_BUTTON(17) +#define DIJOFS_BUTTON18 DIJOFS_BUTTON(18) +#define DIJOFS_BUTTON19 DIJOFS_BUTTON(19) +#define DIJOFS_BUTTON20 DIJOFS_BUTTON(20) +#define DIJOFS_BUTTON21 DIJOFS_BUTTON(21) +#define DIJOFS_BUTTON22 DIJOFS_BUTTON(22) +#define DIJOFS_BUTTON23 DIJOFS_BUTTON(23) +#define DIJOFS_BUTTON24 DIJOFS_BUTTON(24) +#define DIJOFS_BUTTON25 DIJOFS_BUTTON(25) +#define DIJOFS_BUTTON26 DIJOFS_BUTTON(26) +#define DIJOFS_BUTTON27 DIJOFS_BUTTON(27) +#define DIJOFS_BUTTON28 DIJOFS_BUTTON(28) +#define DIJOFS_BUTTON29 DIJOFS_BUTTON(29) +#define DIJOFS_BUTTON30 DIJOFS_BUTTON(30) +#define DIJOFS_BUTTON31 DIJOFS_BUTTON(31) +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +/* DInput 7 structures, types */ +#if(DIRECTINPUT_VERSION >= 0x0700) +typedef struct DIFILEEFFECT { + DWORD dwSize; + GUID GuidEffect; + LPCDIEFFECT lpDiEffect; + CHAR szFriendlyName[MAX_PATH]; +} DIFILEEFFECT, *LPDIFILEEFFECT; + +typedef const DIFILEEFFECT *LPCDIFILEEFFECT; +typedef BOOL (CALLBACK *LPDIENUMEFFECTSINFILECALLBACK)(LPCDIFILEEFFECT , LPVOID); +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +/* DInput 8 structures and types */ +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct _DIACTIONA { + UINT_PTR uAppData; + DWORD dwSemantic; + DWORD dwFlags; + __GNU_EXTENSION union { + LPCSTR lptszActionName; + UINT uResIdString; + } DUMMYUNIONNAME; + GUID guidInstance; + DWORD dwObjID; + DWORD dwHow; +} DIACTIONA, *LPDIACTIONA; +typedef const DIACTIONA *LPCDIACTIONA; + +typedef struct _DIACTIONW { + UINT_PTR uAppData; + DWORD dwSemantic; + DWORD dwFlags; + __GNU_EXTENSION union { + LPCWSTR lptszActionName; + UINT uResIdString; + } DUMMYUNIONNAME; + GUID guidInstance; + DWORD dwObjID; + DWORD dwHow; +} DIACTIONW, *LPDIACTIONW; +typedef const DIACTIONW *LPCDIACTIONW; + +DECL_WINELIB_TYPE_AW(DIACTION) +DECL_WINELIB_TYPE_AW(LPDIACTION) +DECL_WINELIB_TYPE_AW(LPCDIACTION) + +#define DIA_FORCEFEEDBACK 0x00000001 +#define DIA_APPMAPPED 0x00000002 +#define DIA_APPNOMAP 0x00000004 +#define DIA_NORANGE 0x00000008 +#define DIA_APPFIXED 0x00000010 + +#define DIAH_UNMAPPED 0x00000000 +#define DIAH_USERCONFIG 0x00000001 +#define DIAH_APPREQUESTED 0x00000002 +#define DIAH_HWAPP 0x00000004 +#define DIAH_HWDEFAULT 0x00000008 +#define DIAH_DEFAULT 0x00000020 +#define DIAH_ERROR 0x80000000 + +typedef struct _DIACTIONFORMATA { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONA rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + LONG lAxisMin; + LONG lAxisMax; + HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + CHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATA, *LPDIACTIONFORMATA; +typedef const DIACTIONFORMATA *LPCDIACTIONFORMATA; + +typedef struct _DIACTIONFORMATW { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONW rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + LONG lAxisMin; + LONG lAxisMax; + HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + WCHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATW, *LPDIACTIONFORMATW; +typedef const DIACTIONFORMATW *LPCDIACTIONFORMATW; + +DECL_WINELIB_TYPE_AW(DIACTIONFORMAT) +DECL_WINELIB_TYPE_AW(LPDIACTIONFORMAT) +DECL_WINELIB_TYPE_AW(LPCDIACTIONFORMAT) + +#define DIAFTS_NEWDEVICELOW 0xFFFFFFFF +#define DIAFTS_NEWDEVICEHIGH 0xFFFFFFFF +#define DIAFTS_UNUSEDDEVICELOW 0x00000000 +#define DIAFTS_UNUSEDDEVICEHIGH 0x00000000 + +#define DIDBAM_DEFAULT 0x00000000 +#define DIDBAM_PRESERVE 0x00000001 +#define DIDBAM_INITIALIZE 0x00000002 +#define DIDBAM_HWDEFAULTS 0x00000004 + +#define DIDSAM_DEFAULT 0x00000000 +#define DIDSAM_NOUSER 0x00000001 +#define DIDSAM_FORCESAVE 0x00000002 + +#define DICD_DEFAULT 0x00000000 +#define DICD_EDIT 0x00000001 + +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +typedef struct _DICOLORSET { + DWORD dwSize; + D3DCOLOR cTextFore; + D3DCOLOR cTextHighlight; + D3DCOLOR cCalloutLine; + D3DCOLOR cCalloutHighlight; + D3DCOLOR cBorder; + D3DCOLOR cControlFill; + D3DCOLOR cHighlightFill; + D3DCOLOR cAreaFill; +} DICOLORSET, *LPDICOLORSET; +typedef const DICOLORSET *LPCDICOLORSET; + +typedef struct _DICONFIGUREDEVICESPARAMSA { + DWORD dwSize; + DWORD dwcUsers; + LPSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATA lprgFormats; + HWND hwnd; + DICOLORSET dics; + LPUNKNOWN lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSA, *LPDICONFIGUREDEVICESPARAMSA; +typedef const DICONFIGUREDEVICESPARAMSA *LPCDICONFIGUREDEVICESPARAMSA; + +typedef struct _DICONFIGUREDEVICESPARAMSW { + DWORD dwSize; + DWORD dwcUsers; + LPWSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATW lprgFormats; + HWND hwnd; + DICOLORSET dics; + LPUNKNOWN lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSW, *LPDICONFIGUREDEVICESPARAMSW; +typedef const DICONFIGUREDEVICESPARAMSW *LPCDICONFIGUREDEVICESPARAMSW; + +DECL_WINELIB_TYPE_AW(DICONFIGUREDEVICESPARAMS) +DECL_WINELIB_TYPE_AW(LPDICONFIGUREDEVICESPARAMS) +DECL_WINELIB_TYPE_AW(LPCDICONFIGUREDEVICESPARAMS) + +#define DIDIFT_CONFIGURATION 0x00000001 +#define DIDIFT_OVERLAY 0x00000002 + +#define DIDAL_CENTERED 0x00000000 +#define DIDAL_LEFTALIGNED 0x00000001 +#define DIDAL_RIGHTALIGNED 0x00000002 +#define DIDAL_MIDDLE 0x00000000 +#define DIDAL_TOPALIGNED 0x00000004 +#define DIDAL_BOTTOMALIGNED 0x00000008 + +typedef struct _DIDEVICEIMAGEINFOA { + CHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOA, *LPDIDEVICEIMAGEINFOA; +typedef const DIDEVICEIMAGEINFOA *LPCDIDEVICEIMAGEINFOA; + +typedef struct _DIDEVICEIMAGEINFOW { + WCHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOW, *LPDIDEVICEIMAGEINFOW; +typedef const DIDEVICEIMAGEINFOW *LPCDIDEVICEIMAGEINFOW; + +DECL_WINELIB_TYPE_AW(DIDEVICEIMAGEINFO) +DECL_WINELIB_TYPE_AW(LPDIDEVICEIMAGEINFO) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEIMAGEINFO) + +typedef struct _DIDEVICEIMAGEINFOHEADERA { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOA lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERA, *LPDIDEVICEIMAGEINFOHEADERA; +typedef const DIDEVICEIMAGEINFOHEADERA *LPCDIDEVICEIMAGEINFOHEADERA; + +typedef struct _DIDEVICEIMAGEINFOHEADERW { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOW lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERW, *LPDIDEVICEIMAGEINFOHEADERW; +typedef const DIDEVICEIMAGEINFOHEADERW *LPCDIDEVICEIMAGEINFOHEADERW; + +DECL_WINELIB_TYPE_AW(DIDEVICEIMAGEINFOHEADER) +DECL_WINELIB_TYPE_AW(LPDIDEVICEIMAGEINFOHEADER) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEIMAGEINFOHEADER) + +#endif /* DI8 */ + + +/***************************************************************************** + * IDirectInputEffect interface + */ +#if (DIRECTINPUT_VERSION >= 0x0500) +#undef INTERFACE +#define INTERFACE IDirectInputEffect +DECLARE_INTERFACE_(IDirectInputEffect,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputEffect methods ***/ + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID) PURE; + STDMETHOD(GetEffectGuid)(THIS_ LPGUID) PURE; + STDMETHOD(GetParameters)(THIS_ LPDIEFFECT, DWORD) PURE; + STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT, DWORD) PURE; + STDMETHOD(Start)(THIS_ DWORD, DWORD) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(GetEffectStatus)(THIS_ LPDWORD) PURE; + STDMETHOD(Download)(THIS) PURE; + STDMETHOD(Unload)(THIS) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputEffect_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputEffect_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputEffect methods ***/ +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->lpVtbl->GetEffectGuid(p,a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->lpVtbl->GetParameters(p,a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->lpVtbl->SetParameters(p,a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->lpVtbl->Start(p,a,b) +#define IDirectInputEffect_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->lpVtbl->GetEffectStatus(p,a) +#define IDirectInputEffect_Download(p) (p)->lpVtbl->Download(p) +#define IDirectInputEffect_Unload(p) (p)->lpVtbl->Unload(p) +#define IDirectInputEffect_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#else +/*** IUnknown methods ***/ +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputEffect_AddRef(p) (p)->AddRef() +#define IDirectInputEffect_Release(p) (p)->Release() +/*** IDirectInputEffect methods ***/ +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->GetEffectGuid(a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->GetParameters(a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->SetParameters(a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->Start(a,b) +#define IDirectInputEffect_Stop(p) (p)->Stop() +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->GetEffectStatus(a) +#define IDirectInputEffect_Download(p) (p)->Download() +#define IDirectInputEffect_Unload(p) (p)->Unload() +#define IDirectInputEffect_Escape(p,a) (p)->Escape(a) +#endif + +#endif /* DI5 */ + + +/***************************************************************************** + * IDirectInputDeviceA interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDeviceA +DECLARE_INTERFACE_(IDirectInputDeviceA,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; +}; + +/***************************************************************************** + * IDirectInputDeviceW interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDeviceW +DECLARE_INTERFACE_(IDirectInputDeviceW,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice_AddRef(p) (p)->AddRef() +#define IDirectInputDevice_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice_Acquire(p) (p)->Acquire() +#define IDirectInputDevice_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#endif + + +#if (DIRECTINPUT_VERSION >= 0x0500) +/***************************************************************************** + * IDirectInputDevice2A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice2A +DECLARE_INTERFACE_(IDirectInputDevice2A,IDirectInputDeviceA) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; +}; + +/***************************************************************************** + * IDirectInputDevice2W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice2W +DECLARE_INTERFACE_(IDirectInputDevice2W,IDirectInputDeviceW) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice2_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice2_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice2_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice2_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice2_AddRef(p) (p)->AddRef() +#define IDirectInputDevice2_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice2_Acquire(p) (p)->Acquire() +#define IDirectInputDevice2_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice2_Poll(p) (p)->Poll() +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#endif +#endif /* DI5 */ + +#if DIRECTINPUT_VERSION >= 0x0700 +/***************************************************************************** + * IDirectInputDevice7A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice7A +DECLARE_INTERFACE_(IDirectInputDevice7A,IDirectInputDevice2A) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7A methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; +}; + +/***************************************************************************** + * IDirectInputDevice7W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice7W +DECLARE_INTERFACE_(IDirectInputDevice7W,IDirectInputDevice2W) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7W methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice7_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice7_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice7_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice7_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice7_AddRef(p) (p)->AddRef() +#define IDirectInputDevice7_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice7_Acquire(p) (p)->Acquire() +#define IDirectInputDevice7_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice7_Poll(p) (p)->Poll() +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +#endif + +#endif /* DI7 */ + +#if DIRECTINPUT_VERSION >= 0x0800 +/***************************************************************************** + * IDirectInputDevice8A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice8A +DECLARE_INTERFACE_(IDirectInputDevice8A,IDirectInputDevice7A) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7A methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; + /*** IDirectInputDevice8A methods ***/ + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) PURE; +}; + +/***************************************************************************** + * IDirectInputDevice8W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice8W +DECLARE_INTERFACE_(IDirectInputDevice8W,IDirectInputDevice7W) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7W methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; + /*** IDirectInputDevice8W methods ***/ + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice8_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice8_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice8_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice8_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +/*** IDirectInputDevice8 methods ***/ +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->lpVtbl->BuildActionMap(p,a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->lpVtbl->SetActionMap(p,a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->lpVtbl->GetImageInfo(p,a) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice8_AddRef(p) (p)->AddRef() +#define IDirectInputDevice8_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice8_Acquire(p) (p)->Acquire() +#define IDirectInputDevice8_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice8_Poll(p) (p)->Poll() +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +/*** IDirectInputDevice8 methods ***/ +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->BuildActionMap(a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->SetActionMap(a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->GetImageInfo(a) +#endif + +#endif /* DI8 */ + +/* "Standard" Mouse report... */ +typedef struct DIMOUSESTATE { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[4]; +} DIMOUSESTATE; + +#if DIRECTINPUT_VERSION >= 0x0700 +/* "Standard" Mouse report for DInput 7... */ +typedef struct DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2; +#endif /* DI7 */ + +#define DIMOFS_X FIELD_OFFSET(DIMOUSESTATE, lX) +#define DIMOFS_Y FIELD_OFFSET(DIMOUSESTATE, lY) +#define DIMOFS_Z FIELD_OFFSET(DIMOUSESTATE, lZ) +#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0) +#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1) +#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2) +#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3) +#if DIRECTINPUT_VERSION >= 0x0700 +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) +#endif /* DI7 */ + +#ifdef __cplusplus +extern "C" { +#endif +extern const DIDATAFORMAT c_dfDIMouse; +#if DIRECTINPUT_VERSION >= 0x0700 +extern const DIDATAFORMAT c_dfDIMouse2; /* DX 7 */ +#endif /* DI7 */ +extern const DIDATAFORMAT c_dfDIKeyboard; +#if DIRECTINPUT_VERSION >= 0x0500 +extern const DIDATAFORMAT c_dfDIJoystick; +extern const DIDATAFORMAT c_dfDIJoystick2; +#endif /* DI5 */ +#ifdef __cplusplus +}; +#endif + +/***************************************************************************** + * IDirectInputA interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputA +DECLARE_INTERFACE_(IDirectInputA,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; +}; + +/***************************************************************************** + * IDirectInputW interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputW +DECLARE_INTERFACE_(IDirectInputW,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput methods ***/ +#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#else +/*** IUnknown methods ***/ +#define IDirectInput_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput_AddRef(p) (p)->AddRef() +#define IDirectInput_Release(p) (p)->Release() +/*** IDirectInput methods ***/ +#define IDirectInput_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput_Initialize(p,a,b) (p)->Initialize(a,b) +#endif + +/***************************************************************************** + * IDirectInput2A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput2A +DECLARE_INTERFACE_(IDirectInput2A,IDirectInputA) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2A methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) PURE; +}; + +/***************************************************************************** + * IDirectInput2W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput2W +DECLARE_INTERFACE_(IDirectInput2W,IDirectInputW) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2W methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput2_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput methods ***/ +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput2_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#else +/*** IUnknown methods ***/ +#define IDirectInput2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput2_AddRef(p) (p)->AddRef() +#define IDirectInput2_Release(p) (p)->Release() +/*** IDirectInput methods ***/ +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->Initialize(a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput2_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#endif + +/***************************************************************************** + * IDirectInput7A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput7A +DECLARE_INTERFACE_(IDirectInput7A,IDirectInput2A) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2A methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) PURE; + /*** IDirectInput7A methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID rguid, REFIID riid, LPVOID *pvOut, LPUNKNOWN lpUnknownOuter) PURE; +}; + +/***************************************************************************** + * IDirectInput7W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput7W +DECLARE_INTERFACE_(IDirectInput7W,IDirectInput2W) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2W methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance) PURE; + /*** IDirectInput7W methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID rguid, REFIID riid, LPVOID *pvOut, LPUNKNOWN lpUnknownOuter) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput7_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput methods ***/ +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput7_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +/*** IDirectInput7 methods ***/ +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInput7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput7_AddRef(p) (p)->AddRef() +#define IDirectInput7_Release(p) (p)->Release() +/*** IDirectInput methods ***/ +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->Initialize(a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput7_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +/*** IDirectInput7 methods ***/ +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->CreateDeviceEx(a,b,c,d) +#endif + + +#if DIRECTINPUT_VERSION >= 0x0800 +/***************************************************************************** + * IDirectInput8A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput8A +DECLARE_INTERFACE_(IDirectInput8A,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInput8A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICE8A *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) PURE; +}; + +/***************************************************************************** + * IDirectInput8W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput8W +DECLARE_INTERFACE_(IDirectInput8W,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInput8W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICE8W *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput8_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput8 methods ***/ +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->lpVtbl->EnumDevicesBySemantics(p,a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->lpVtbl->ConfigureDevices(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInput8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput8_AddRef(p) (p)->AddRef() +#define IDirectInput8_Release(p) (p)->Release() +/*** IDirectInput8 methods ***/ +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->EnumDevicesBySemantics(a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->ConfigureDevices(a,b,c,d) +#endif + +#endif /* DI8 */ + +/* Export functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if DIRECTINPUT_VERSION >= 0x0800 +HRESULT WINAPI DirectInput8Create(HINSTANCE,DWORD,REFIID,LPVOID *,LPUNKNOWN); +#else /* DI < 8 */ +HRESULT WINAPI DirectInputCreateA(HINSTANCE,DWORD,LPDIRECTINPUTA *,LPUNKNOWN); +HRESULT WINAPI DirectInputCreateW(HINSTANCE,DWORD,LPDIRECTINPUTW *,LPUNKNOWN); +#define DirectInputCreate WINELIB_NAME_AW(DirectInputCreate) + +HRESULT WINAPI DirectInputCreateEx(HINSTANCE,DWORD,REFIID,LPVOID *,LPUNKNOWN); +#endif /* DI8 */ + +#ifdef __cplusplus +}; +#endif + +#endif /* __DINPUT_INCLUDED__ */ diff --git a/vendor/glfw/deps/mingw/xinput.h b/vendor/glfw/deps/mingw/xinput.h new file mode 100644 index 00000000..d3ca726c --- /dev/null +++ b/vendor/glfw/deps/mingw/xinput.h @@ -0,0 +1,239 @@ +/* + * The Wine project - Xinput Joystick Library + * Copyright 2008 Andrew Fenn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_XINPUT_H +#define __WINE_XINPUT_H + +#include + +/* + * Bitmasks for the joysticks buttons, determines what has + * been pressed on the joystick, these need to be mapped + * to whatever device you're using instead of an xbox 360 + * joystick + */ + +#define XINPUT_GAMEPAD_DPAD_UP 0x0001 +#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 +#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 +#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 +#define XINPUT_GAMEPAD_START 0x0010 +#define XINPUT_GAMEPAD_BACK 0x0020 +#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 +#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 +#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 +#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 +#define XINPUT_GAMEPAD_A 0x1000 +#define XINPUT_GAMEPAD_B 0x2000 +#define XINPUT_GAMEPAD_X 0x4000 +#define XINPUT_GAMEPAD_Y 0x8000 + +/* + * Defines the flags used to determine if the user is pushing + * down on a button, not holding a button, etc + */ + +#define XINPUT_KEYSTROKE_KEYDOWN 0x0001 +#define XINPUT_KEYSTROKE_KEYUP 0x0002 +#define XINPUT_KEYSTROKE_REPEAT 0x0004 + +/* + * Defines the codes which are returned by XInputGetKeystroke + */ + +#define VK_PAD_A 0x5800 +#define VK_PAD_B 0x5801 +#define VK_PAD_X 0x5802 +#define VK_PAD_Y 0x5803 +#define VK_PAD_RSHOULDER 0x5804 +#define VK_PAD_LSHOULDER 0x5805 +#define VK_PAD_LTRIGGER 0x5806 +#define VK_PAD_RTRIGGER 0x5807 +#define VK_PAD_DPAD_UP 0x5810 +#define VK_PAD_DPAD_DOWN 0x5811 +#define VK_PAD_DPAD_LEFT 0x5812 +#define VK_PAD_DPAD_RIGHT 0x5813 +#define VK_PAD_START 0x5814 +#define VK_PAD_BACK 0x5815 +#define VK_PAD_LTHUMB_PRESS 0x5816 +#define VK_PAD_RTHUMB_PRESS 0x5817 +#define VK_PAD_LTHUMB_UP 0x5820 +#define VK_PAD_LTHUMB_DOWN 0x5821 +#define VK_PAD_LTHUMB_RIGHT 0x5822 +#define VK_PAD_LTHUMB_LEFT 0x5823 +#define VK_PAD_LTHUMB_UPLEFT 0x5824 +#define VK_PAD_LTHUMB_UPRIGHT 0x5825 +#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826 +#define VK_PAD_LTHUMB_DOWNLEFT 0x5827 +#define VK_PAD_RTHUMB_UP 0x5830 +#define VK_PAD_RTHUMB_DOWN 0x5831 +#define VK_PAD_RTHUMB_RIGHT 0x5832 +#define VK_PAD_RTHUMB_LEFT 0x5833 +#define VK_PAD_RTHUMB_UPLEFT 0x5834 +#define VK_PAD_RTHUMB_UPRIGHT 0x5835 +#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836 +#define VK_PAD_RTHUMB_DOWNLEFT 0x5837 + +/* + * Deadzones are for analogue joystick controls on the joypad + * which determine when input should be assumed to be in the + * middle of the pad. This is a threshold to stop a joypad + * controlling the game when the player isn't touching the + * controls. + */ + +#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849 +#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689 +#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30 + + +/* + * Defines what type of abilities the type of joystick has + * DEVTYPE_GAMEPAD is available for all joysticks, however + * there may be more specific identifiers for other joysticks + * which are being used. + */ + +#define XINPUT_DEVTYPE_GAMEPAD 0x01 +#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01 +#define XINPUT_DEVSUBTYPE_WHEEL 0x02 +#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03 +#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04 +#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05 +#define XINPUT_DEVSUBTYPE_GUITAR 0x06 +#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08 + +/* + * These are used with the XInputGetCapabilities function to + * determine the abilities to the joystick which has been + * plugged in. + */ + +#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004 +#define XINPUT_FLAG_GAMEPAD 0x00000001 + +/* + * Defines the status of the battery if one is used in the + * attached joystick. The first two define if the joystick + * supports a battery. Disconnected means that the joystick + * isn't connected. Wired shows that the joystick is a wired + * joystick. + */ + +#define BATTERY_DEVTYPE_GAMEPAD 0x00 +#define BATTERY_DEVTYPE_HEADSET 0x01 +#define BATTERY_TYPE_DISCONNECTED 0x00 +#define BATTERY_TYPE_WIRED 0x01 +#define BATTERY_TYPE_ALKALINE 0x02 +#define BATTERY_TYPE_NIMH 0x03 +#define BATTERY_TYPE_UNKNOWN 0xFF +#define BATTERY_LEVEL_EMPTY 0x00 +#define BATTERY_LEVEL_LOW 0x01 +#define BATTERY_LEVEL_MEDIUM 0x02 +#define BATTERY_LEVEL_FULL 0x03 + +/* + * How many joysticks can be used with this library. Games that + * use the xinput library will not go over this number. + */ + +#define XUSER_MAX_COUNT 4 +#define XUSER_INDEX_ANY 0x000000FF + +/* + * Defines the structure of an xbox 360 joystick. + */ + +typedef struct _XINPUT_GAMEPAD { + WORD wButtons; + BYTE bLeftTrigger; + BYTE bRightTrigger; + SHORT sThumbLX; + SHORT sThumbLY; + SHORT sThumbRX; + SHORT sThumbRY; +} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD; + +typedef struct _XINPUT_STATE { + DWORD dwPacketNumber; + XINPUT_GAMEPAD Gamepad; +} XINPUT_STATE, *PXINPUT_STATE; + +/* + * Defines the structure of how much vibration is set on both the + * right and left motors in a joystick. If you're not using a 360 + * joystick you will have to map these to your device. + */ + +typedef struct _XINPUT_VIBRATION { + WORD wLeftMotorSpeed; + WORD wRightMotorSpeed; +} XINPUT_VIBRATION, *PXINPUT_VIBRATION; + +/* + * Defines the structure for what kind of abilities the joystick has + * such abilities are things such as if the joystick has the ability + * to send and receive audio, if the joystick is in fact a driving + * wheel or perhaps if the joystick is some kind of dance pad or + * guitar. + */ + +typedef struct _XINPUT_CAPABILITIES { + BYTE Type; + BYTE SubType; + WORD Flags; + XINPUT_GAMEPAD Gamepad; + XINPUT_VIBRATION Vibration; +} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES; + +/* + * Defines the structure for a joystick input event which is + * retrieved using the function XInputGetKeystroke + */ +typedef struct _XINPUT_KEYSTROKE { + WORD VirtualKey; + WCHAR Unicode; + WORD Flags; + BYTE UserIndex; + BYTE HidCode; +} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE; + +typedef struct _XINPUT_BATTERY_INFORMATION +{ + BYTE BatteryType; + BYTE BatteryLevel; +} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION; + +#ifdef __cplusplus +extern "C" { +#endif + +void WINAPI XInputEnable(WINBOOL); +DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*); +DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*); +DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE); +DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*); +DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*); +DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_XINPUT_H */ diff --git a/vendor/glfw/deps/wayland/xdg-toplevel-icon-v1.xml b/vendor/glfw/deps/wayland/xdg-toplevel-icon-v1.xml new file mode 100644 index 00000000..fc409fef --- /dev/null +++ b/vendor/glfw/deps/wayland/xdg-toplevel-icon-v1.xml @@ -0,0 +1,205 @@ + + + + + Copyright © 2023-2024 Matthias Klumpp + Copyright © 2024 David Edmundson + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol allows clients to set icons for their toplevel surfaces + either via the XDG icon stock (using an icon name), or from pixel data. + + A toplevel icon represents the individual toplevel (unlike the application + or launcher icon, which represents the application as a whole), and may be + shown in window switchers, window overviews and taskbars that list + individual windows. + + This document adheres to RFC 2119 when using words like "must", + "should", "may", etc. + + Warning! The protocol described in this file is currently in the testing + phase. Backward compatible changes may be added together with the + corresponding interface version bump. Backward incompatible changes can + only be done by creating a new major version of the extension. + + + + + This interface allows clients to create toplevel window icons and set + them on toplevel windows to be displayed to the user. + + + + + Destroy the toplevel icon manager. + This does not destroy objects created with the manager. + + + + + + Creates a new icon object. This icon can then be attached to a + xdg_toplevel via the 'set_icon' request. + + + + + + + This request assigns the icon 'icon' to 'toplevel', or clears the + toplevel icon if 'icon' was null. + This state is double-buffered and is applied on the next + wl_surface.commit of the toplevel. + + After making this call, the xdg_toplevel_icon_v1 provided as 'icon' + can be destroyed by the client without 'toplevel' losing its icon. + The xdg_toplevel_icon_v1 is immutable from this point, and any + future attempts to change it must raise the + 'xdg_toplevel_icon_v1.immutable' protocol error. + + The compositor must set the toplevel icon from either the pixel data + the icon provides, or by loading a stock icon using the icon name. + See the description of 'xdg_toplevel_icon_v1' for details. + + If 'icon' is set to null, the icon of the respective toplevel is reset + to its default icon (usually the icon of the application, derived from + its desktop-entry file, or a placeholder icon). + If this request is passed an icon with no pixel buffers or icon name + assigned, the icon must be reset just like if 'icon' was null. + + + + + + + + This event indicates an icon size the compositor prefers to be + available if the client has scalable icons and can render to any size. + + When the 'xdg_toplevel_icon_manager_v1' object is created, the + compositor may send one or more 'icon_size' events to describe the list + of preferred icon sizes. If the compositor has no size preference, it + may not send any 'icon_size' event, and it is up to the client to + decide a suitable icon size. + + A sequence of 'icon_size' events must be finished with a 'done' event. + If the compositor has no size preferences, it must still send the + 'done' event, without any preceding 'icon_size' events. + + + + + + + This event is sent after all 'icon_size' events have been sent. + + + + + + + This interface defines a toplevel icon. + An icon can have a name, and multiple buffers. + In order to be applied, the icon must have either a name, or at least + one buffer assigned. Applying an empty icon (with no buffer or name) to + a toplevel should reset its icon to the default icon. + + It is up to compositor policy whether to prefer using a buffer or loading + an icon via its name. See 'set_name' and 'add_buffer' for details. + + + + + + + + + + + Destroys the 'xdg_toplevel_icon_v1' object. + The icon must still remain set on every toplevel it was assigned to, + until the toplevel icon is reset explicitly. + + + + + + This request assigns an icon name to this icon. + Any previously set name is overridden. + + The compositor must resolve 'icon_name' according to the lookup rules + described in the XDG icon theme specification[1] using the + environment's current icon theme. + + If the compositor does not support icon names or cannot resolve + 'icon_name' according to the XDG icon theme specification it must + fall back to using pixel buffer data instead. + + If this request is made after the icon has been assigned to a toplevel + via 'set_icon', a 'immutable' error must be raised. + + [1]: https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html + + + + + + + This request adds pixel data supplied as wl_buffer to the icon. + + The client should add pixel data for all icon sizes and scales that + it can provide, or which are explicitly requested by the compositor + via 'icon_size' events on xdg_toplevel_icon_manager_v1. + + The wl_buffer supplying pixel data as 'buffer' must be backed by wl_shm + and must be a square (width and height being equal). + If any of these buffer requirements are not fulfilled, a 'invalid_buffer' + error must be raised. + + If this icon instance already has a buffer of the same size and scale + from a previous 'add_buffer' request, data from the last request + overrides the preexisting pixel data. + + The wl_buffer must be kept alive for as long as the xdg_toplevel_icon + it is associated with is not destroyed, otherwise a 'no_buffer' error + is raised. The buffer contents must not be modified after it was + assigned to the icon. As a result, the region of the wl_shm_pool's + backing storage used for the wl_buffer must not be modified after this + request is sent. The wl_buffer.release event is unused. + + If this request is made after the icon has been assigned to a toplevel + via 'set_icon', a 'immutable' error must be raised. + + + + + + From a1ca0f6ded02490a0696c9fac8a83caa73d54b76 Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Thu, 4 Jun 2026 00:57:02 +0530 Subject: [PATCH 06/17] feat(autostart): Add the launch on startup option --- include/utils/autostart.h | 20 +++++ src/core/utils/autostart.cpp | 157 +++++++++++++++++++++++++++++++++++ src/ui/panels/settings.cpp | 15 ++-- 3 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 include/utils/autostart.h create mode 100644 src/core/utils/autostart.cpp diff --git a/include/utils/autostart.h b/include/utils/autostart.h new file mode 100644 index 00000000..a9b730be --- /dev/null +++ b/include/utils/autostart.h @@ -0,0 +1,20 @@ +#ifdef _WIN32 +#include +#endif + +#include + +namespace Autostart { +#ifdef _WIN32 +std::wstring getExecutablePath(); +HRESULT createShortcut(); +#endif + +#ifdef __linux__ +std::string getExecutablePath(); +bool createShortcut(); +#endif + +bool deleteShortcut(); +bool shortcutExists(); +} // namespace Autostart \ No newline at end of file diff --git a/src/core/utils/autostart.cpp b/src/core/utils/autostart.cpp new file mode 100644 index 00000000..5539aa94 --- /dev/null +++ b/src/core/utils/autostart.cpp @@ -0,0 +1,157 @@ +#ifdef _WIN32 +#include + +#include +#include + +#include +#include + +#endif + +#ifdef __linux__ +#include +#include + +#include +#include +#endif + +#include +#include + +namespace Autostart { + +#ifdef _WIN32 + +std::wstring getExecutablePath() { + DWORD bufferSize = MAX_PATH; + std::vector buffer(bufferSize); + + DWORD result = GetModuleFileNameW(NULL, buffer.data(), bufferSize); + + while (result == buffer.size()) { + bufferSize *= 2; + buffer.resize(bufferSize); + result = GetModuleFileNameW(NULL, buffer.data(), bufferSize); + } + + if (result == 0) { + return L""; + } + + return std::wstring(buffer.data()); +} + +HRESULT createShortcut() { + HRESULT hres; + IShellLinkW* psl; + std::wstring exePath = getExecutablePath(); + CoInitialize(NULL); + + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLinkW, (LPVOID*)&psl); + if (SUCCEEDED(hres)) { + psl->SetPath(exePath.c_str()); + + IPersistFile* ppf; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); + if (SUCCEEDED(hres)) { + PWSTR startupPath = NULL; + hres = SHGetKnownFolderPath(FOLDERID_Startup, 0, NULL, &startupPath); + + if (SUCCEEDED(hres)) { + std::wstring linkPath = std::wstring(startupPath) + L"\\Lazap.lnk"; + hres = ppf->Save(linkPath.c_str(), TRUE); + CoTaskMemFree(startupPath); + } + ppf->Release(); + } + psl->Release(); + } + CoUninitialize(); + return hres; +} + +#endif + +#ifdef __linux__ + +std::string getExecutablePath() { + char res[PATH_MAX]; + size_t count = readlink("/proc/self/exe", res, PATH_MAX); + return std::string(res, count > 0 ? count : 0); +} + +bool createShortcut() { + const char* home = getenv("HOME"); + if (!home) return false; + + std::filesystem::path dir = + std::filesystem::path(home) / ".config" / "autostart"; + + if (!std::filesystem::exists(dir)) std::filesystem::create_directories(dir); + + std::filesystem::path file = dir / "lazap.desktop"; + std::string execPath = getExecutablePath(); + std::ofstream(file) << ("[Desktop Entry]\nName=Lazap\nExec=" + execPath + + "\nTerminal=false\nType=Application\nIcon=" + "lazap\nCategories=Game;Utility;\n"); + return true; +} +#endif + +bool deleteShortcut() { +#ifdef _WIN32 + PWSTR pszPath = NULL; + std::wstring path; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_Startup, 0, NULL, &pszPath); + + if (SUCCEEDED(hr)) { + path = (pszPath); + + CoTaskMemFree(pszPath); + } + try { + return std::filesystem::remove(std::filesystem::path(path) / "Lazap.lnk"); + } catch (const std::filesystem::filesystem_error& e) { + return false; + } +#endif + +#ifdef __linux__ + const char* home = getenv("HOME"); + if (!home) return false; + + return std::filesystem::remove(std::filesystem::path(home) / ".config" / + "autostart" / "lazap.desktop"); +#endif +} + +bool shortcutExists() { +#ifdef _WIN32 + PWSTR pszPath = NULL; + std::wstring path; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_Startup, 0, NULL, &pszPath); + + if (SUCCEEDED(hr)) { + path = (pszPath); + + CoTaskMemFree(pszPath); + } + try { + return std::filesystem::exists(std::filesystem::path(path) / "Lazap.lnk"); + } catch (const std::filesystem::filesystem_error& e) { + return false; + } +#endif + +#ifdef __linux__ + const char* home = getenv("HOME"); + if (!home) return false; + + return std::filesystem::exists(std::filesystem::path(home) / ".config" / + "autostart" / "lazap.desktop"); +#endif +} +} // namespace Autostart \ No newline at end of file diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index 85e0f8f4..a1305361 100644 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -2,7 +2,10 @@ #include +#include + #include "ui/theme.h" +#include "utils/autostart.h" #include "utils/font_manager.h" #include "utils/image_manager.h" @@ -34,7 +37,7 @@ void SettingsPanel::loadSettings() { if (!settings) return; quitTrayMin_ = settings->get("quit_tray_min")->value_or(false); - autoStart_ = settings->get("auto_start")->value_or(false); + autoStart_ = Autostart::shortcutExists(); checkUpdates_ = settings->get("check_updates")->value_or(true); launcherIcons_ = settings->get("launcher_icons")->value_or(true); discordRpc_ = settings->get("discord_rpc")->value_or(false); @@ -109,10 +112,12 @@ void SettingsPanel::render() { saveSettings(); ImGui::OpenPopup("Restart"); } - if (addOption("Launch at Startup", InputType::Toggle, &autoStart_, - true)) { - // saveSettings(); - ImGui::OpenPopup("Coming Soon"); + if (addOption("Launch at Startup", InputType::Toggle, &autoStart_)) { + saveSettings(); + if (autoStart_) + Autostart::createShortcut(); + else + Autostart::deleteShortcut(); } if (addOption("Check for Updates", InputType::Toggle, &checkUpdates_, true)) { From 45d590302b80ad1f962c2c2e93b08e7a5ed4b6bd Mon Sep 17 00:00:00 2001 From: p0ryae Date: Thu, 4 Jun 2026 10:54:22 -0700 Subject: [PATCH 07/17] fix: improve tray code, use .png for linux platform tray icon --- src/core/utils/tray_manager.cpp | 50 +++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/core/utils/tray_manager.cpp b/src/core/utils/tray_manager.cpp index 349f45be..9944cae6 100644 --- a/src/core/utils/tray_manager.cpp +++ b/src/core/utils/tray_manager.cpp @@ -24,7 +24,7 @@ static GLFWwindow* win = nullptr; static bool quit = false; static bool hidden = false; -static void restore(struct tray_menu* item) { +static void restore(struct tray_menu*) { if (win) { glfwShowWindow(win); glfwRestoreWindow(win); @@ -33,7 +33,7 @@ static void restore(struct tray_menu* item) { } } -static void on_quit_clicked(struct tray_menu* item) { +static void on_quit_clicked(struct tray_menu*) { quit = true; glfwSetWindowShouldClose(win, GLFW_TRUE); glfwPostEmptyEvent(); @@ -41,17 +41,54 @@ static void on_quit_clicked(struct tray_menu* item) { } static struct tray tray = { - .icon = "/assets/icons/lazap/lazap.ico", + .icon = nullptr, .tooltip = "Lazap", + .notification_icon = nullptr, + .notification_text = nullptr, + .notification_title = nullptr, + .notification_cb = nullptr, + .cb = nullptr, + .menu = nullptr, + .iconPathCount = 0, +}; + +static struct tray_menu menu[] = { + {.text = "Restore App", + .disabled = 0, + .checked = 0, + .checkbox = 0, + .cb = restore, + .context = nullptr, + .submenu = nullptr}, + {.text = "-", + .disabled = 0, + .checked = 0, + .checkbox = 0, + .cb = nullptr, + .context = nullptr, + .submenu = nullptr}, + {.text = "Quit", + .disabled = 0, + .checked = 0, + .checkbox = 0, + .cb = on_quit_clicked, + .context = nullptr, + .submenu = nullptr}, }; void init(GLFWwindow* window) { win = window; quit = false; +#ifdef _WIN32 std::filesystem::path iconPath = std::filesystem::temp_directory_path() / "lazap_tray.ico"; const auto file = b::embed<"assets/icons/lazap/lazap.ico">(); +#else + std::filesystem::path iconPath = + std::filesystem::temp_directory_path() / "lazap_tray.png"; + const auto file = b::embed<"assets/icons/lazap/lazap.png">(); +#endif std::ofstream out(iconPath, std::ios::binary); out.write(reinterpret_cast(file.data()), file.size()); @@ -63,11 +100,6 @@ void init(GLFWwindow* window) { tray.icon = strdup(iconPath.string().c_str()); #endif - static struct tray_menu menu[] = {{.text = "Restore App", .cb = restore}, - {.text = "-"}, - {.text = "Quit", .cb = on_quit_clicked}, - {.text = nullptr}}; - tray.menu = menu; tray_init(&tray); @@ -92,4 +124,4 @@ bool shouldQuit() { return quit; } bool isWindowHidden() { return hidden; } void shutdown() { tray_exit(); } -} // namespace TrayManager \ No newline at end of file +} // namespace TrayManager From 61182645287b001e30fa8c696c4caceee6dc955f Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Fri, 5 Jun 2026 00:38:20 +0530 Subject: [PATCH 08/17] feat(custom_bg): Add custom background and opacity features --- include/ui/panels/settings.h | 5 ++-- include/ui/theme.h | 1 + include/utils/image_manager.h | 1 + src/core/storage/storage.cpp | 2 ++ src/core/utils/image_manager.cpp | 9 ++++++ src/ui/imgui_layer.cpp | 17 +++++++++++ src/ui/panel_manager.cpp | 2 +- src/ui/panels/settings.cpp | 51 +++++++++++++++++++++++++------- 8 files changed, 74 insertions(+), 14 deletions(-) diff --git a/include/ui/panels/settings.h b/include/ui/panels/settings.h index 4421800b..274cbc68 100644 --- a/include/ui/panels/settings.h +++ b/include/ui/panels/settings.h @@ -20,8 +20,8 @@ enum class InputType { class SettingsPanel : public Panel { public: - SettingsPanel(Storage* storage, Titlebar* titlebar) - : Panel("Settings", storage), titlebar_(titlebar) {} + SettingsPanel(Storage* storage, Titlebar* titlebar, GLFWwindow* win) + : Panel("Settings", storage), titlebar_(titlebar), window_(win) {} void init() override; void render() override; @@ -36,6 +36,7 @@ class SettingsPanel : public Panel { bool discordRpc_ = false; Titlebar* titlebar_; + GLFWwindow* window_; void loadSettings(); void saveSettings(); diff --git a/include/ui/theme.h b/include/ui/theme.h index 71cfa692..434f82f1 100644 --- a/include/ui/theme.h +++ b/include/ui/theme.h @@ -7,6 +7,7 @@ namespace Themes { inline uint32_t ACCENT_COLOR = 0x7E4CEA; inline ImU32 ACCENT_COLOR_IMGUI = IM_COL32(0x7E, 0x4C, 0xEA, 255); +inline float BG_OPACITY = 0.8; void setDefaultDarkColors(); diff --git a/include/utils/image_manager.h b/include/utils/image_manager.h index 423fddee..0e6007de 100644 --- a/include/utils/image_manager.h +++ b/include/utils/image_manager.h @@ -22,6 +22,7 @@ class ImageManager { static GLuint loadSVG(b::EmbedInternal::EmbeddedFile embed, const std::string& id, uint32_t color); static GLuint get(const std::string& name); + static void remove(const std::string& name); static void clear(); private: diff --git a/src/core/storage/storage.cpp b/src/core/storage/storage.cpp index aac5d3e2..721a43b2 100644 --- a/src/core/storage/storage.cpp +++ b/src/core/storage/storage.cpp @@ -109,6 +109,7 @@ bool Storage::initTOML() { !settingsTable->contains("launcher_icons") || !settingsTable->contains("discord_rpc") || !settingsTable->contains("accent_color") || + !settingsTable->contains("bg_opacity") || !settingsTable->contains("custom_titlebar")) { throw std::runtime_error( "Settings table is missing required fields"); @@ -163,6 +164,7 @@ bool Storage::initTOML() { settings.insert("launcher_icons", false); settings.insert("discord_rpc", true); settings.insert("accent_color", Themes::ACCENT_COLOR); + settings.insert("bg_opacity", Themes::BG_OPACITY); settings.insert("custom_titlebar", true); toml::table games; diff --git a/src/core/utils/image_manager.cpp b/src/core/utils/image_manager.cpp index 25538c86..d8b18d97 100644 --- a/src/core/utils/image_manager.cpp +++ b/src/core/utils/image_manager.cpp @@ -140,6 +140,15 @@ void ImageManager::clear() { cache.clear(); } +void ImageManager::remove(const std::string& name) { + auto it = cache.find(name); + if (it != cache.end()) { + GLuint texture_id = it->second; + glDeleteTextures(1, &texture_id); + cache.erase(it); + } +} + const std::string intToHex(int num) { const std::string hexChars = "0123456789ABCDEF"; std::string result; diff --git a/src/ui/imgui_layer.cpp b/src/ui/imgui_layer.cpp index 7eec7346..e2729b35 100644 --- a/src/ui/imgui_layer.cpp +++ b/src/ui/imgui_layer.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include "backends/imgui_impl_glfw.h" #include "backends/imgui_impl_opengl3.h" #include "imgui.h" @@ -56,6 +58,11 @@ ImGuiLayer::ImGuiLayer(GLFWwindow *window, Storage &storage) FontManager::loadFont("Dialog:Paragraph", b::embed<"assets/fonts/Oxanium-Regular.ttf">(), 15.0f); + if (storage.exists("custom_bg.png")) { + ImageManager::loadPNG( + (std::filesystem::path(storage.getStoragePath()) / "custom_bg.png") + .string()); + } ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 130"); @@ -146,5 +153,15 @@ void ImGuiLayer::renderBackground(const ImGuiViewport *viewport) { bg->AddRectFilledMultiColor(img_pos, img_size, IM_COL32(0, 0, 0, 0), IM_COL32(0, 0, 0, 0), IM_COL32(0, 0, 0, 255), IM_COL32(0, 0, 0, 255)); + } else if (storage_->exists("custom_bg.png")) { + ImDrawList *bg = ImGui::GetWindowDrawList(); + bg->AddImage((ImTextureID)(intptr_t)ImageManager::get("custom_bg"), + ImVec2(0, 0), viewport->Size, ImVec2(0, 0), ImVec2(1, 1), + IM_COL32_WHITE); + bg->AddRectFilledMultiColor(ImVec2(0, 0), viewport->Size, + IM_COL32(0, 0, 0, 255 * Themes::BG_OPACITY), + IM_COL32(0, 0, 0, 255 * Themes::BG_OPACITY), + IM_COL32(0, 0, 0, 255 * Themes::BG_OPACITY), + IM_COL32(0, 0, 0, 255 * Themes::BG_OPACITY)); } } diff --git a/src/ui/panel_manager.cpp b/src/ui/panel_manager.cpp index 2286df8f..247cc30b 100644 --- a/src/ui/panel_manager.cpp +++ b/src/ui/panel_manager.cpp @@ -37,7 +37,7 @@ void PanelManager::initPanels(GLFWwindow *w, Storage &storage) { nullptr)); addPanel(makePanelWithCB(this, "Recently Played", &view_->view, &storage, nullptr)); - addPanel(std::make_unique(&storage, titlebarPtr)); + addPanel(std::make_unique(&storage, titlebarPtr, w)); for (auto &panel : panels_) { panel->init(); diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index a1305361..4cb24bec 100644 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -1,6 +1,7 @@ #include "ui/panels/settings.h" #include +#include #include @@ -45,8 +46,10 @@ void SettingsPanel::loadSettings() { const uint32_t col = settings->get("accent_color")->value_or(Themes::ACCENT_COLOR); + const float bgOpacity = settings->get("bg_opacity")->value_or(0.8); Themes::ACCENT_COLOR = col; + Themes::BG_OPACITY = bgOpacity > 0.8 ? 0.8 : bgOpacity; Themes::ACCENT_COLOR_IMGUI = IM_COL32((col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF, 255); @@ -124,14 +127,6 @@ void SettingsPanel::render() { // saveSettings(); ImGui::OpenPopup("Coming Soon"); } - if (ImGui::BeginPopup("Coming Soon", ImGuiWindowFlags_NoMove)) { - ImGui::Text("This feature is coming soon!"); - ImGui::EndPopup(); - } - if (ImGui::BeginPopup("Restart", ImGuiWindowFlags_NoMove)) { - ImGui::Text("Restart the app to apply this change"); - ImGui::EndPopup(); - } ImGui::EndGroup(); ImGui::PopID(); @@ -164,6 +159,10 @@ void SettingsPanel::render() { ImGui::Text("This feature is coming soon!"); ImGui::EndPopup(); } + if (ImGui::BeginPopup("Restart", ImGuiWindowFlags_NoMove)) { + ImGui::Text("Restart the app to apply this change"); + ImGui::EndPopup(); + } ImGui::PopFont(); ImGui::EndGroup(); @@ -326,7 +325,25 @@ bool SettingsPanel::addOption(const std::string& label, InputType input, (widthAvailable - widthNeeded)); if (FilePickerButton(label.c_str(), ImVec2(110 * scale_.x, 30 * scale_.y))) { - // Open file dialog + glfwIconifyWindow(window_); + const char* filters[] = {"*.png"}; + const char* path = tinyfd_openFileDialog("Select Banner Image", "", 1, + filters, "Image files", 0); + if (path) { + if (storage_->exists("custom_bg.png")) { + ImageManager::remove("custom_bg"); + } + std::filesystem::copy_file( + path, + std::filesystem::path(storage_->getStoragePath()) / + "custom_bg.png", + std::filesystem::copy_options::overwrite_existing); + ImageManager::loadPNG( + (std::filesystem::path(storage_->getStoragePath()) / + "custom_bg.png") + .string()); + } + glfwRestoreWindow(window_); } ImGui::PopFont(); } break; @@ -335,10 +352,18 @@ bool SettingsPanel::addOption(const std::string& label, InputType input, float widthNeeded = 92 * scale_.x; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (widthAvailable - widthNeeded)); - float n = 0.0f; + float n = Themes::BG_OPACITY; ImGui::PushFont(FontManager::getFont("Settings:Option")); - NumberBox(label.c_str(), &n, 92 * scale_.x); + if (NumberBox(label.c_str(), &n, 92 * scale_.x)) { + Themes::BG_OPACITY = n; + } ImGui::PopFont(); + + storage_->updateTOML([](toml::table& config) { + if (auto settings = config["settings"].as_table()) { + settings->insert_or_assign("bg_opacity", Themes::BG_OPACITY); + } + }); } break; case InputType::StringTextbox: { @@ -442,6 +467,10 @@ bool SettingsPanel::NumberBox(const char* id, float* value, float width) { bool changed = ImGui::InputFloat(id, value, 0.0f, 0.0f, "%.2f"); ImGui::PopItemWidth(); + if (changed && *value > 0.8) { + *value = 0.8; + } + ImGui::PopStyleVar(2); return changed; } From 34a5dbeef5f01d4deae0f58d9058dbafa9b62759 Mon Sep 17 00:00:00 2001 From: LegIt <77503777+LegItMate@users.noreply.github.com> Date: Sun, 7 Jun 2026 23:55:25 +0530 Subject: [PATCH 09/17] feat(fonts): Add FreeType font loading --- CMakeLists.txt | 3 +++ src/ui/imgui_layer.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2601612f..da084ae5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ FetchContent_Declare(battery-embed FetchContent_MakeAvailable( imgui glaze stb tray lunasvg tomlplusplus cpr battery-embed ) +find_package(Freetype REQUIRED) #----------------------------------------------------------------------------------------------------------------------- # Target Definition @@ -101,6 +102,7 @@ add_executable(${EXECUTABLE_NAME} ${imgui_SOURCE_DIR}/imgui_draw.cpp ${imgui_SOURCE_DIR}/imgui_tables.cpp ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/misc/freetype/imgui_freetype.cpp ${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp ) @@ -166,6 +168,7 @@ target_link_libraries(${EXECUTABLE_NAME} PRIVATE lunasvg tray::tray tinyfiledialogs + Freetype::Freetype $<$:X11> $<$:dwmapi> $<$,$>:opengl32.a> diff --git a/src/ui/imgui_layer.cpp b/src/ui/imgui_layer.cpp index e2729b35..1d8b9e20 100644 --- a/src/ui/imgui_layer.cpp +++ b/src/ui/imgui_layer.cpp @@ -6,6 +6,7 @@ #include "backends/imgui_impl_glfw.h" #include "backends/imgui_impl_opengl3.h" #include "imgui.h" +#include "misc/freetype/imgui_freetype.h" #include "ui/panel_manager.h" #include "ui/theme.h" #include "utils/font_manager.h" @@ -21,6 +22,7 @@ ImGuiLayer::ImGuiLayer(GLFWwindow *window, Storage &storage) io.ConfigDpiScaleFonts = true; io.ConfigDpiScaleViewports = true; io.IniFilename = nullptr; + io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader()); FontManager::init(); FontManager::loadFont("Titlebar:Title", From bdf777f3ebcac5ca3501518936c634c31466f74b Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Wed, 10 Jun 2026 16:07:37 +0530 Subject: [PATCH 10/17] fix(ui): Fix major UI scaling issues --- include/ui/panel.h | 9 ++++++--- include/ui/panels/left_panel.h | 10 ++++++++++ include/ui/panels/titlebar.h | 10 ++++++++++ src/ui/panel_manager.cpp | 30 +++++++++++++++++++----------- src/ui/panels/left_panel.cpp | 14 ++++++++++---- src/ui/panels/titlebar.cpp | 13 ++++++++++++- 6 files changed, 67 insertions(+), 19 deletions(-) diff --git a/include/ui/panel.h b/include/ui/panel.h index 5f644607..38afeeb3 100644 --- a/include/ui/panel.h +++ b/include/ui/panel.h @@ -27,18 +27,21 @@ class Panel { void setOnRefresh(std::function cb) { onRefresh_ = cb; } - static ImVec2 getScale() { + ImVec2 getScale() { ImGuiIO& io = ImGui::GetIO(); + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(monitor, &xs_, &ys_); if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) { return ImVec2(SCALE_FACTOR, SCALE_FACTOR); } - return ImVec2(io.DisplayFramebufferScale.x * SCALE_FACTOR, - io.DisplayFramebufferScale.y * SCALE_FACTOR); + return ImVec2(io.DisplayFramebufferScale.x * SCALE_FACTOR * xs_, + io.DisplayFramebufferScale.y * SCALE_FACTOR * ys_); } protected: std::string name_; Storage* storage_; + float xs_, ys_; bool visible_ = true; ImVec2 scale_ = ImVec2(0, 0); diff --git a/include/ui/panels/left_panel.h b/include/ui/panels/left_panel.h index 0ee59f07..e6585c09 100644 --- a/include/ui/panels/left_panel.h +++ b/include/ui/panels/left_panel.h @@ -11,9 +11,19 @@ class LeftPanel : public Panel { void init() override; void render() override; void end() override {} + ImVec2 getScale() { + ImGuiIO& io = ImGui::GetIO(); + if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) { + return ImVec2(SCALE_FACTOR, SCALE_FACTOR); + } + return ImVec2(io.DisplayFramebufferScale.x * SCALE_FACTOR * xs_, + io.DisplayFramebufferScale.y * SCALE_FACTOR * ys_); + } + float getWidth() { return size_.x; } private: Views* view_ = nullptr; + ImVec2 size_; }; } // namespace ui diff --git a/include/ui/panels/titlebar.h b/include/ui/panels/titlebar.h index 8cd54796..ee6e31c0 100644 --- a/include/ui/panels/titlebar.h +++ b/include/ui/panels/titlebar.h @@ -17,12 +17,22 @@ class Titlebar : public Panel { void setTitle(const std::string& text) { title_ = text; } void setCustomTitlebar(bool enabled) { customTitlebar_ = enabled; } + ImVec2 getScale() { + ImGuiIO& io = ImGui::GetIO(); + if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) { + return ImVec2(SCALE_FACTOR, SCALE_FACTOR); + } + return ImVec2(io.DisplayFramebufferScale.x * SCALE_FACTOR * xs_, + io.DisplayFramebufferScale.y * SCALE_FACTOR * ys_); + } + float getHeight() { return size_.y; } private: bool customTitlebar_ = true; std::string title_ = "Home"; GLFWwindow* window; + ImVec2 size_; }; } // namespace ui diff --git a/src/ui/panel_manager.cpp b/src/ui/panel_manager.cpp index 247cc30b..f66e36d4 100644 --- a/src/ui/panel_manager.cpp +++ b/src/ui/panel_manager.cpp @@ -45,27 +45,35 @@ void PanelManager::initPanels(GLFWwindow *w, Storage &storage) { } void PanelManager::renderPanels(ImGuiWindowClass *window_class) { - const float fixed_width = 60.0f; - - auto enforceLeftPanelWidth = [fixed_width]() { + auto enforceWidth = [](float w) { ImGuiWindow *left_window = ImGui::FindWindowByName("Left Menu"); if (left_window && left_window->DockNode) { ImGuiDockNode *dock_node = left_window->DockNode; - dock_node->Size.x = fixed_width; - dock_node->SizeRef.x = fixed_width; + dock_node->Size.x = w; + dock_node->SizeRef.x = w; + } + }; + auto enforceHeight = [](float h) { + ImGuiWindow *left_window = ImGui::FindWindowByName("Titlebar"); + if (left_window && left_window->DockNode) { + ImGuiDockNode *dock_node = left_window->DockNode; + dock_node->Size.y = h; + dock_node->SizeRef.y = h; } }; - - enforceLeftPanelWidth(); for (auto &panel : panels_) { if (panel->visible()) { ImGui::SetNextWindowClass(window_class); - panel->render(); - if (panel->getName() == "Left Menu") { - enforceLeftPanelWidth(); + auto *leftMenu = static_cast(panel.get()); + if (leftMenu->getWidth() != 0) enforceWidth(leftMenu->getWidth()); + } else if (panel->getName() == "Titlebar") { + auto *titlebar = static_cast(panel.get()); + enforceHeight(titlebar->getHeight()); } + + panel->render(); } } } @@ -136,7 +144,7 @@ void Views::BuildDockLayout() { ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size); ImGuiID titlebar, left, gamesinfo_id, bottom; - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.0f, &left, + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.0445f, &left, &dockspace_id); ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.07f, &titlebar, &dockspace_id); diff --git a/src/ui/panels/left_panel.cpp b/src/ui/panels/left_panel.cpp index 629c48c1..11a43dd7 100644 --- a/src/ui/panels/left_panel.cpp +++ b/src/ui/panels/left_panel.cpp @@ -36,19 +36,26 @@ void LeftPanel::init() { 0xFFFFFFFF); ImageManager::loadSVG(b::embed<"assets/svg/settings.svg">(), "settings-black", 0xFF000000); + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(monitor, &xs_, &ys_); } void LeftPanel::render() { ImGui::Begin(name_.c_str(), nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar); + if (size_.y == 0) { + size_.y = 1; + } else if (size_.x == 0) { + size_ = ImGui::GetWindowSize(); + } scale_ = getScale(); auto drawIconButton = [&](const char* id, ImTextureID texture, ImTextureID activeTexture, const ImVec2& size, bool isActive) -> bool { - ImVec2 cursorPos = ImGui::GetCursorPos(); + ImVec2 cursorPos = ImGui::GetCursorScreenPos(); if (isActive) { ImDrawList* drawList = ImGui::GetWindowDrawList(); @@ -59,9 +66,8 @@ void LeftPanel::render() { ImVec2(windowPos.x + cursorPos.x + size.x + 38.0f * scale_.x, windowPos.y + cursorPos.y + size.y + 12.5f * scale_.y); - drawList->AddRectFilled( - rectMin, rectMax, Themes::ACCENT_COLOR_IMGUI, - 12.0f * sqrt((pow(scale_.x, 2) + pow(scale_.y, 2)) * 0.5f)); + drawList->AddRectFilled(rectMin, rectMax, Themes::ACCENT_COLOR_IMGUI, + 12.0f * scale_.x); } bool clicked = diff --git a/src/ui/panels/titlebar.cpp b/src/ui/panels/titlebar.cpp index b40df813..61349c96 100644 --- a/src/ui/panels/titlebar.cpp +++ b/src/ui/panels/titlebar.cpp @@ -14,6 +14,8 @@ void Titlebar::init() { 0xFFFFFFFF); ImageManager::loadSVG(b::embed<"assets/svg/maximise.svg">(), "maximise", 0xFFFFFFFF); + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(monitor, &xs_, &ys_); } void Titlebar::render() { @@ -21,9 +23,18 @@ void Titlebar::render() { ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar); + size_ = ImGui::GetWindowSize(); scale_ = getScale(); - ImGui::PushFont(FontManager::getFont("Titlebar:Title")); +#ifdef _WIN32 + float x, y; + GLFWmonitor* m = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(m, &x, &y); + x /= 1.25; +#else + float x = 1; +#endif + ImGui::PushFont(FontManager::getFont("Titlebar:Title"), 16.0f / x); ImGui::SetCursorPos(ImVec2((ImGui::GetCursorPosX() + 35) * scale_.x, (ImGui::GetCursorPosY() + 33) * scale_.y)); ImGui::Text("%s", title_.c_str()); From 041a2123cbb528bf127c5dfbacf56181b7c38c7f Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Wed, 10 Jun 2026 16:58:36 +0530 Subject: [PATCH 11/17] fix(frame): Add resize cursor when hovering over edges of the frame(windows only) --- include/application.h | 32 +++++++++++++++++++++++++++ src/core/application.cpp | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/include/application.h b/include/application.h index 71fdddf7..4f0ab75e 100644 --- a/include/application.h +++ b/include/application.h @@ -20,6 +20,38 @@ struct RunnerState { struct WindowCallbacks { static void mouseButtonCB(GLFWwindow* window, int button, int action, int mods); +#ifdef _WIN32 + static GLFWcursor* cursor_nwse; + static GLFWcursor* cursor_nesw; + static GLFWcursor* cursor_h; + static GLFWcursor* cursor_v; + static bool hovered_; + + static int GetResizeZone(double xpos, double ypos, int w, int h, + int threshold) { + bool l = xpos <= threshold; + bool r = xpos >= w - threshold; + bool t = ypos <= threshold; + bool b = ypos >= h - threshold; + + if (t && l) return 1; // Top-Left + if (t && r) return 2; // Top-Right + if (b && l) return 3; // Bottom-Left + if (b && r) return 4; // Bottom-Right + if (l) return 5; // Left + if (r) return 6; // Right + if (t) return 7; // Top + if (b) return 8; // Bottom + return 0; // None + } + static void cursorPosCB(GLFWwindow* window, double xpos, double ypos); + static void initCursors() { + cursor_nwse = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR); + cursor_nesw = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR); + cursor_h = glfwCreateStandardCursor(GLFW_RESIZE_EW_CURSOR); + cursor_v = glfwCreateStandardCursor(GLFW_RESIZE_NS_CURSOR); + } +#endif }; void IdleBySleeping(FpsIdling& ioIdling); diff --git a/src/core/application.cpp b/src/core/application.cpp index c59b83c2..e2fad968 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -24,6 +24,12 @@ #include #pragma comment(lib, "dwmapi.lib") + +GLFWcursor *WindowCallbacks::cursor_nwse = nullptr; +GLFWcursor *WindowCallbacks::cursor_nesw = nullptr; +GLFWcursor *WindowCallbacks::cursor_h = nullptr; +GLFWcursor *WindowCallbacks::cursor_v = nullptr; +bool WindowCallbacks::hovered_; #endif double ClockSeconds() { @@ -121,6 +127,10 @@ void Application::run() { glfwMakeContextCurrent(window); glfwSetMouseButtonCallback(window, WindowCallbacks::mouseButtonCB); +#ifdef _WIN32 + WindowCallbacks::initCursors(); + glfwSetCursorPosCallback(window, WindowCallbacks::cursorPosCB); +#endif if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { fprintf(stderr, "Failed to initialize GLAD\n"); @@ -293,3 +303,41 @@ void WindowCallbacks::mouseButtonCB(GLFWwindow *window, int button, int action, } } } + +#ifdef _WIN32 +void WindowCallbacks::cursorPosCB(GLFWwindow *window, double xpos, + double ypos) { + int w, h; + glfwGetWindowSize(window, &w, &h); + + int zone = GetResizeZone(xpos, ypos, w, h, 10); + + switch (zone) { + case 1: + case 4: + glfwSetCursor(window, WindowCallbacks::cursor_nwse); + hovered_ = true; + break; + case 2: + case 3: + glfwSetCursor(window, WindowCallbacks::cursor_nesw); + hovered_ = true; + break; + case 5: + case 6: + glfwSetCursor(window, WindowCallbacks::cursor_h); + hovered_ = true; + break; + case 7: + case 8: + glfwSetCursor(window, WindowCallbacks::cursor_v); + hovered_ = true; + break; + default: + if (hovered_ == true) { + glfwSetCursor(window, NULL); + hovered_ = false; + } + } +} +#endif From e3ef72f60d59ae13a1c81f5095ac39a6567625a8 Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Wed, 10 Jun 2026 18:05:35 +0530 Subject: [PATCH 12/17] perf(fonts): Optimize fonts by using dynamic font loading --- include/utils/font_manager.h | 3 ++- src/core/utils/font_manger.cpp | 5 +--- src/ui/cmps/addgame_dialog.cpp | 14 +++++----- src/ui/cmps/game_box.cpp | 2 +- src/ui/imgui_layer.cpp | 49 +++++++++++----------------------- src/ui/panels/game_panel.cpp | 12 +++------ src/ui/panels/settings.cpp | 18 ++++++------- src/ui/panels/titlebar.cpp | 2 +- 8 files changed, 40 insertions(+), 65 deletions(-) diff --git a/include/utils/font_manager.h b/include/utils/font_manager.h index 646ae2cf..a625ac18 100644 --- a/include/utils/font_manager.h +++ b/include/utils/font_manager.h @@ -11,7 +11,8 @@ class FontManager { static void init(); static void shutdown(); static ImFont* loadFont(const std::string& name, - b::EmbedInternal::EmbeddedFile embed, float size); + b::EmbedInternal::EmbeddedFile embed, + float size = 16.0f); static ImFont* getFont(const std::string& name); private: diff --git a/src/core/utils/font_manger.cpp b/src/core/utils/font_manger.cpp index 8135283f..fd938b11 100644 --- a/src/core/utils/font_manger.cpp +++ b/src/core/utils/font_manger.cpp @@ -23,8 +23,6 @@ void FontManager::shutdown() { fonts_.clear(); } -// TODO: Replace current font loading with dynamic font loading system -// introduced in 1.92 using flag ImGuiBackendFlags_HasTextures ImFont* FontManager::loadFont(const std::string& name, b::EmbedInternal::EmbeddedFile embed, float size) { @@ -33,9 +31,8 @@ ImFont* FontManager::loadFont(const std::string& name, ImFontConfig config; config.FontDataOwnedByAtlas = false; - // TODO: if dyanmic font added, get rid of scale factor? ImFont* font = io.Fonts->AddFontFromMemoryTTF( - (void*)embed.data(), static_cast(embed.size()), size * 1.1, &config); + (void*)embed.data(), static_cast(embed.size()), size, &config); if (font) { fonts_[name] = font; diff --git a/src/ui/cmps/addgame_dialog.cpp b/src/ui/cmps/addgame_dialog.cpp index be2da529..e3bc0948 100644 --- a/src/ui/cmps/addgame_dialog.cpp +++ b/src/ui/cmps/addgame_dialog.cpp @@ -50,7 +50,7 @@ void AddGameDialog::render(GLFWwindow* window) { bool open = true; if (ImGui::BeginPopupModal(name_.c_str(), &open, flags)) { - ImGui::PushFont(FontManager::getFont("Dialog:Title")); + ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 27.0f); const char* title = name_.c_str(); float windowWidth = ImGui::GetWindowWidth(); float textWidth = ImGui::CalcTextSize(title).x; @@ -60,7 +60,7 @@ void AddGameDialog::render(GLFWwindow* window) { ImGui::Dummy(ImVec2(0, 50)); - ImGui::PushFont(FontManager::getFont("Dialog:Paragraph")); + ImGui::PushFont(FontManager::getFont("Oxanium-R"), 15.0f); ImGui::Text("Game Name"); ImGui::PopFont(); ImGui::Dummy(ImVec2(0, 5)); @@ -72,7 +72,7 @@ void AddGameDialog::render(GLFWwindow* window) { ImGui::Dummy(ImVec2(0, 15)); - ImGui::PushFont(FontManager::getFont("Dialog:Paragraph")); + ImGui::PushFont(FontManager::getFont("Oxanium-R"), 15.0f); ImGui::Text("Enter Executable Path"); ImGui::PopFont(); ImGui::Dummy(ImVec2(0, 5)); @@ -96,7 +96,7 @@ void AddGameDialog::render(GLFWwindow* window) { if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); ImGui::Dummy(ImVec2(0, 15)); - ImGui::PushFont(FontManager::getFont("Dialog:Paragraph")); + ImGui::PushFont(FontManager::getFont("Oxanium-R"), 15.0f); ImGui::Text("Choose Game Banner (Optional)"); ImGui::PopFont(); ImGui::SameLine(ImGui::GetContentRegionAvail().x - 60); @@ -140,7 +140,7 @@ void AddGameDialog::render(GLFWwindow* window) { ImVec4(0.9f, 0.3f, 0.3f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.7f, 0.1f, 0.1f, 1.0f)); - ImGui::PushFont(FontManager::getFont("Dialog:Button")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 15.0f); if (ImGui::Button("Cancel", ImVec2(btnWidth, 35))) close(); ImGui::PopFont(); if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); @@ -157,7 +157,7 @@ void AddGameDialog::render(GLFWwindow* window) { ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(accentColor.x * 0.85f, accentColor.y * 0.85f, accentColor.z * 0.85f, accentColor.w)); - ImGui::PushFont(FontManager::getFont("Dialog:Button")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 15.0f); if (ImGui::Button("Add Game", ImVec2(btnWidth, 35))) { if (std::strlen(gameName_) > 0 && std::strlen(filePath_) > 0) { CustomGames customGames(*storage_); @@ -225,7 +225,7 @@ bool AddGameDialog::PillButton(const char* label, ImTextureID icon, ImVec2 size, ImVec2 textPos(contentStart.x + iconS.x + spacing, pos.y + (size.y - textSize.y) * 0.5f); - ImGui::PushFont(FontManager::getFont("Settings:Option")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 18.0f); dl->AddText(textPos, text, displayText.c_str()); ImGui::PopFont(); diff --git a/src/ui/cmps/game_box.cpp b/src/ui/cmps/game_box.cpp index 12fd5de7..b4d3cde3 100644 --- a/src/ui/cmps/game_box.cpp +++ b/src/ui/cmps/game_box.cpp @@ -141,7 +141,7 @@ void GameBox::render() { ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); } - ImGui::PushFont(FontManager::getFont("GameBox:Title")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 17.0f); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + padding * scale_.x); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + padding * scale_.y); diff --git a/src/ui/imgui_layer.cpp b/src/ui/imgui_layer.cpp index 1d8b9e20..c7a8c77e 100644 --- a/src/ui/imgui_layer.cpp +++ b/src/ui/imgui_layer.cpp @@ -25,40 +25,21 @@ ImGuiLayer::ImGuiLayer(GLFWwindow *window, Storage &storage) io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader()); FontManager::init(); - FontManager::loadFont("Titlebar:Title", - b::embed<"assets/fonts/Nunito-SemiBold.ttf">(), 16.0f); - - FontManager::loadFont("Username", - b::embed<"assets/fonts/Oxanium-Regular.ttf">(), 15.0f); - - FontManager::loadFont("GameInfo:Title", - b::embed<"assets/fonts/ZenDots-Regular.ttf">(), 64.0f); - FontManager::loadFont("GameInfo:Paragraph", - b::embed<"assets/fonts/Nunito-Medium.ttf">(), 18.0f); - - FontManager::loadFont("Left:Button", - b::embed<"assets/fonts/Oxanium-Regular.ttf">(), 18.0f); - FontManager::loadFont( - "Title", b::embed<"assets/fonts/ArchivoBlack-Regular.ttf">(), 24.0f); - FontManager::loadFont("GameBox:Title", - b::embed<"assets/fonts/Nunito-SemiBold.ttf">(), 17.0f); - FontManager::loadFont( - "GameBox:Time", b::embed<"assets/fonts/RobotoMono-Medium.ttf">(), 10.0f); - - FontManager::loadFont("Settings:Button", - b::embed<"assets/fonts/Nunito-Bold.ttf">(), 13.0f); - FontManager::loadFont("Settings:Setting", - b::embed<"assets/fonts/Nunito-Light.ttf">(), 18.0f); - FontManager::loadFont("Settings:Option", - b::embed<"assets/fonts/Nunito-SemiBold.ttf">(), 13.0f); - - FontManager::loadFont("Dialog:Title", - b::embed<"assets/fonts/ArchivoBlack-Regular.ttf">(), - 27.0f); - FontManager::loadFont("Dialog:Button", - b::embed<"assets/fonts/Nunito-SemiBold.ttf">(), 15.0f); - FontManager::loadFont("Dialog:Paragraph", - b::embed<"assets/fonts/Oxanium-Regular.ttf">(), 15.0f); + FontManager::loadFont("Nunito-SB", + b::embed<"assets/fonts/Nunito-SemiBold.ttf">()); + FontManager::loadFont("ArchivoBlack-R", + b::embed<"assets/fonts/ArchivoBlack-Regular.ttf">()); + // FontManager::loadFont( + // "GameBox:Time", + // b::embed<"assets/fonts/RobotoMono-Medium.ttf">(), 10.0f); + + FontManager::loadFont("Nunito-B", b::embed<"assets/fonts/Nunito-Bold.ttf">()); + FontManager::loadFont("Nunito-L", + b::embed<"assets/fonts/Nunito-Light.ttf">()); + FontManager::loadFont("Oxanium-R", + b::embed<"assets/fonts/Oxanium-Regular.ttf">()); + FontManager::loadFont("Oxanium-EL", + b::embed<"assets/fonts/Oxanium-ExtraLight.ttf">()); if (storage.exists("custom_bg.png")) { ImageManager::loadPNG( diff --git a/src/ui/panels/game_panel.cpp b/src/ui/panels/game_panel.cpp index 8d201b9b..4e67cc75 100644 --- a/src/ui/panels/game_panel.cpp +++ b/src/ui/panels/game_panel.cpp @@ -26,10 +26,6 @@ void GamePanel::init() { Themes::ACCENT_COLOR); ImageManager::loadSVG(b::embed<"assets/svg/play.svg">(), "play", 0xFFFFFFFF); - FontManager::loadFont("CustomGame:Plus", - b::embed<"assets/fonts/Oxanium-ExtraLight.ttf">(), - 64.0f); - addGameDialog_ = std::make_unique(storage_); std::memset(searchBuffer_, 0, sizeof(searchBuffer_)); @@ -74,7 +70,7 @@ void GamePanel::render() { scale_ = getScale(); - ImGui::PushFont(FontManager::getFont("Title")); + ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); if (*view_ == ViewType::MainMenu) { ImGui::Text("%s", name_.c_str()); } @@ -85,7 +81,7 @@ void GamePanel::render() { if (*view_ != ViewType::MainMenu) { ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::PushFont(FontManager::getFont("GameBox:Title")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 17.0f); ImGuiStyle& style = ImGui::GetStyle(); ImVec2 oldPadding = style.FramePadding; @@ -113,7 +109,7 @@ void GamePanel::render() { bool refreshRequested = false; if (!games_) { - ImGui::PushFont(FontManager::getFont("Game:Title")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 17.0f); ImGui::TextDisabled("No games available."); ImGui::PopFont(); } else { @@ -224,7 +220,7 @@ void GamePanel::render() { } } - ImGui::PushFont(FontManager::getFont("CustomGame:Plus")); + ImGui::PushFont(FontManager::getFont("Oxanium-EL"), 64.0f); ImVec2 text_size = ImGui::CalcTextSize("+"); ImVec2 text_pos = ImVec2(pos.x + (size.x - text_size.x) * 0.5f, pos.y + (size.y - text_size.y) * 0.5f); diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index 4cb24bec..28cf42bf 100644 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -106,7 +106,7 @@ void SettingsPanel::render() { switch (view_) { case SettingsView::LauncherConfig: addSection("General", "monitor"); - ImGui::PushFont(FontManager::getFont("Settings:Setting")); + ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); ImGui::PushID("general_settings"); ImGui::BeginGroup(); @@ -135,7 +135,7 @@ void SettingsPanel::render() { ImGui::Dummy(ImVec2(0, 47 * scale_.y)); addSection("Appearance", "appearance"); - ImGui::PushFont(FontManager::getFont("Settings:Setting")); + ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); ImGui::PushID("appearance_settings"); ImGui::BeginGroup(); addOption("Accent Color", InputType::ColorPicker, nullptr); @@ -171,7 +171,7 @@ void SettingsPanel::render() { ImGui::Dummy(ImVec2(0, 47 * scale_.y)); addSection("Integrations", "link"); - ImGui::PushFont(FontManager::getFont("Settings:Setting")); + ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); ImGui::PushID("integration_settings"); ImGui::BeginGroup(); @@ -185,12 +185,12 @@ void SettingsPanel::render() { ImGui::PopID(); break; // case SettingsView::AccountSettings: - // ImGui::PushFont(FontManager::getFont("Title")); + // ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); // ImGui::Image(ImageManager::get("appearance"), // ImVec2(27 * scale_.x, 27 * scale_.x)); // ImGui::Text("Account Settings"); // ImGui::PopFont(); - // ImGui::PushFont(FontManager::getFont("Settings:Setting")); + // ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); // ImGui::Dummy(ImVec2(0, 10)); // ImGui::Text("Username: "); // // ImGui::InputText("##username", &username_buffer_); @@ -221,7 +221,7 @@ bool SettingsPanel::addMenuButton(const std::string& label, ImVec2 size, addIcon(view_ == SettingsView::AccountSettings ? "config:white" : "account:white"); } - ImGui::PushFont(FontManager::getFont("Settings:Button")); + ImGui::PushFont(FontManager::getFont("Nunito-B"), 13.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10 * scale_.x, 0)); bool btn = ImGui::Button(label.c_str()); ImGui::PopStyleVar(); @@ -249,7 +249,7 @@ void SettingsPanel::addIcon(const std::string& icon) { void SettingsPanel::addSection(const std::string& title, const std::string& icon) { - ImGui::PushFont(FontManager::getFont("Title")); + ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); ImGui::Dummy(ImVec2(8 * scale_.x, 0)); ImGui::Image(ImageManager::get(icon), ImVec2(27 * scale_.x, 27 * scale_.x)); ImGui::SameLine(0, 8 * scale_.x); @@ -319,7 +319,7 @@ bool SettingsPanel::addOption(const std::string& label, InputType input, } break; case InputType::ImagePicker: { - ImGui::PushFont(FontManager::getFont("Settings:Option")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13.0f); float widthNeeded = 110 * scale_.x; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (widthAvailable - widthNeeded)); @@ -353,7 +353,7 @@ bool SettingsPanel::addOption(const std::string& label, InputType input, ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (widthAvailable - widthNeeded)); float n = Themes::BG_OPACITY; - ImGui::PushFont(FontManager::getFont("Settings:Option")); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13.0f); if (NumberBox(label.c_str(), &n, 92 * scale_.x)) { Themes::BG_OPACITY = n; } diff --git a/src/ui/panels/titlebar.cpp b/src/ui/panels/titlebar.cpp index 61349c96..687aad5f 100644 --- a/src/ui/panels/titlebar.cpp +++ b/src/ui/panels/titlebar.cpp @@ -34,7 +34,7 @@ void Titlebar::render() { #else float x = 1; #endif - ImGui::PushFont(FontManager::getFont("Titlebar:Title"), 16.0f / x); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 16.0f / x); ImGui::SetCursorPos(ImVec2((ImGui::GetCursorPosX() + 35) * scale_.x, (ImGui::GetCursorPosY() + 33) * scale_.y)); ImGui::Text("%s", title_.c_str()); From 5d60483456020da07875b677d0596c159fec71b7 Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:22:38 +0530 Subject: [PATCH 13/17] fix(scaling): Final fixes for scaling issues --- src/ui/panel_manager.cpp | 11 +++++++---- src/ui/panels/titlebar.cpp | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ui/panel_manager.cpp b/src/ui/panel_manager.cpp index f66e36d4..7a7a3327 100644 --- a/src/ui/panel_manager.cpp +++ b/src/ui/panel_manager.cpp @@ -142,12 +142,15 @@ void Views::BuildDockLayout() { ImGui::DockBuilderRemoveNode(dockspace_id); ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None); ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size); + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + float xs_, ys_; + glfwGetMonitorContentScale(monitor, &xs_, &ys_); ImGuiID titlebar, left, gamesinfo_id, bottom; - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.0445f, &left, - &dockspace_id); - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.07f, &titlebar, - &dockspace_id); + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.0445f * xs_ * 0.8, + &left, &dockspace_id); + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.07f * ys_ * 0.8, + &titlebar, &dockspace_id); ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.426f, &gamesinfo_id, &bottom); diff --git a/src/ui/panels/titlebar.cpp b/src/ui/panels/titlebar.cpp index 687aad5f..71ef657c 100644 --- a/src/ui/panels/titlebar.cpp +++ b/src/ui/panels/titlebar.cpp @@ -30,7 +30,7 @@ void Titlebar::render() { float x, y; GLFWmonitor* m = glfwGetPrimaryMonitor(); glfwGetMonitorContentScale(m, &x, &y); - x /= 1.25; + x /= scale_.x * 1.25; #else float x = 1; #endif From 3f718cbffc2501295a99affdd7707f961524f8ba Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:11:45 +0530 Subject: [PATCH 14/17] fix(ui): Add more detail to settings and other minor fixes --- assets/svg/upload.svg | 2 +- include/ui/panels/settings.h | 115 ++-- src/core/utils/image_manager.cpp | 20 +- src/ui/panel_manager.cpp | 444 ++++++------- src/ui/panels/settings.cpp | 1030 ++++++++++++++++-------------- 5 files changed, 854 insertions(+), 757 deletions(-) mode change 100644 => 100755 include/ui/panels/settings.h mode change 100644 => 100755 src/ui/panel_manager.cpp mode change 100644 => 100755 src/ui/panels/settings.cpp diff --git a/assets/svg/upload.svg b/assets/svg/upload.svg index 1945b140..21f9fbb5 100644 --- a/assets/svg/upload.svg +++ b/assets/svg/upload.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/include/ui/panels/settings.h b/include/ui/panels/settings.h old mode 100644 new mode 100755 index 274cbc68..bcb05c91 --- a/include/ui/panels/settings.h +++ b/include/ui/panels/settings.h @@ -1,56 +1,59 @@ -#pragma once -#include - -#include "ui/panel.h" -#include "ui/panels/titlebar.h" - -namespace ui { -enum class SettingsView { - LauncherConfig, - AccountSettings, -}; - -enum class InputType { - Toggle, - ColorPicker, - ImagePicker, - IntTextbox, - StringTextbox, -}; - -class SettingsPanel : public Panel { - public: - SettingsPanel(Storage* storage, Titlebar* titlebar, GLFWwindow* win) - : Panel("Settings", storage), titlebar_(titlebar), window_(win) {} - - void init() override; - void render() override; - void end() override {}; - - private: - bool quitTrayMin_ = false; - bool autoStart_ = false; - bool checkUpdates_ = true; - bool launcherIcons_ = true; - bool customTitlebar_ = true; - bool discordRpc_ = false; - - Titlebar* titlebar_; - GLFWwindow* window_; - - void loadSettings(); - void saveSettings(); - - bool addMenuButton(const std::string& label, ImVec2 size, bool active); - void addIcon(const std::string& icon); - void addSection(const std::string& title, const std::string& icon); - bool addOption(const std::string& label, InputType input, bool* value, - bool disabled = false); - bool ToggleButton(const char* label, bool* v, bool disabled); - bool ColorBox(const char* id, float color[3], ImVec2 size); - bool FilePickerButton(const char* label, const ImVec2& size); - bool NumberBox(const char* id, float* value, float width); - SettingsView view_ = SettingsView::LauncherConfig; -}; - -} // namespace ui +#pragma once +#include + +#include "ui/panel.h" +#include "ui/panels/titlebar.h" + +namespace ui { +enum class SettingsView { + LauncherConfig, + AccountSettings, +}; + +enum class InputType { + Toggle, + ColorPicker, + ImagePicker, + IntTextbox, + StringTextbox, +}; + +class SettingsPanel : public Panel { + public: + SettingsPanel(Storage* storage, Titlebar* titlebar, GLFWwindow* win) + : Panel("Settings", storage), titlebar_(titlebar), window_(win) {} + + void init() override; + void render() override; + void end() override {}; + + private: + bool quitTrayMin_ = false; + bool autoStart_ = false; + bool checkUpdates_ = true; + bool launcherIcons_ = true; + bool customTitlebar_ = true; + bool discordRpc_ = false; + bool isEditing_ = false; + + Titlebar* titlebar_; + GLFWwindow* window_; + + void loadSettings(); + void saveSettings(); + + bool addMenuButton(const std::string& label, ImVec2 size, bool active); + void addIcon(const std::string& icon); + void addSection(const std::string& title, const std::string& icon); + bool addOption(const std::string& label, InputType input, bool* value, + bool disabled = false); + bool ToggleButton(const char* label, bool* v, bool disabled); + bool ColorBox(const char* id, float color[3], ImVec2 size); + bool FilePickerButton(const char* label, const ImVec2& size); + bool NumberBox(const char* id, float* value, float width); + SettingsView view_ = SettingsView::LauncherConfig; +}; + +} // namespace ui + +std::string rgbToHex(int r, int g, int b); diff --git a/src/core/utils/image_manager.cpp b/src/core/utils/image_manager.cpp index d8b18d97..73df7a8d 100644 --- a/src/core/utils/image_manager.cpp +++ b/src/core/utils/image_manager.cpp @@ -89,15 +89,29 @@ GLuint ImageManager::loadSVG(b::EmbedInternal::EmbeddedFile embed, auto elements = svg->querySelectorAll("path"); for (auto& element : elements) { - std::string hexColor = "#" + intToHex((color >> 16) & 0xFF) + - intToHex((color >> 8) & 0xFF) + - intToHex(color & 0xFF); + int alpha = (color) & 0xFF; + std::string hexColor; + if (alpha != 0) { + hexColor = "#" + intToHex((color >> 24) & 0xFF) + + intToHex((color >> 16) & 0xFF) + intToHex((color >> 8) & 0xFF); + } else { + hexColor = "#" + intToHex((color >> 16) & 0xFF) + + intToHex((color >> 8) & 0xFF) + intToHex((color) & 0xFF); + } + + float opacity = static_cast(alpha) / 255.0f; auto fillAttr = element.getAttribute("fill"); if (!fillAttr.empty() && fillAttr != "none") { element.setAttribute("fill", hexColor); } + auto fillOpaAttr = element.getAttribute("fill-opacity"); + if (!fillOpaAttr.empty() && fillOpaAttr != "none") { + std::string val = std::format("{:.2f}", opacity); + element.setAttribute("fill-opacity", val); + } + auto strokeAttr = element.getAttribute("stroke"); if (!strokeAttr.empty() && strokeAttr != "none") { element.setAttribute("stroke", hexColor); diff --git a/src/ui/panel_manager.cpp b/src/ui/panel_manager.cpp old mode 100644 new mode 100755 index 7a7a3327..0b2a1007 --- a/src/ui/panel_manager.cpp +++ b/src/ui/panel_manager.cpp @@ -1,221 +1,223 @@ -#include "ui/panel_manager.h" - -#include -#include - -#include "addons/discord_rpc/discord_rpc.h" -#include "ui/panels/game_panel.h" -#include "ui/panels/gameinfo_panel.h" -#include "ui/panels/left_panel.h" -#include "ui/panels/settings.h" -#include "ui/panels/titlebar.h" - -using namespace ui; - -template -std::unique_ptr makePanelWithCB(PanelManager *pm, Args &&...args) { - auto panel = std::make_unique(std::forward(args)...); - std::string panelName = panel->getName(); - panel->setOnRefresh([pm, panelName](const bool reloadGames) { - pm->refreshPanel(panelName, reloadGames); - }); - return panel; -} - -void PanelManager::initPanels(GLFWwindow *w, Storage &storage) { - view_ = std::make_unique(this); - - auto titlebar = std::make_unique(w); - Titlebar *titlebarPtr = titlebar.get(); - addPanel(std::move(titlebar)); - addPanel(std::make_unique(view_.get())); - addPanel(std::make_unique()); - - addPanel( - makePanelWithCB(this, "Library", &view_->view, &storage, w)); - addPanel(makePanelWithCB(this, "Favorites", &view_->view, &storage, - nullptr)); - addPanel(makePanelWithCB(this, "Recently Played", &view_->view, - &storage, nullptr)); - addPanel(std::make_unique(&storage, titlebarPtr, w)); - - for (auto &panel : panels_) { - panel->init(); - } -} - -void PanelManager::renderPanels(ImGuiWindowClass *window_class) { - auto enforceWidth = [](float w) { - ImGuiWindow *left_window = ImGui::FindWindowByName("Left Menu"); - if (left_window && left_window->DockNode) { - ImGuiDockNode *dock_node = left_window->DockNode; - dock_node->Size.x = w; - dock_node->SizeRef.x = w; - } - }; - auto enforceHeight = [](float h) { - ImGuiWindow *left_window = ImGui::FindWindowByName("Titlebar"); - if (left_window && left_window->DockNode) { - ImGuiDockNode *dock_node = left_window->DockNode; - dock_node->Size.y = h; - dock_node->SizeRef.y = h; - } - }; - - for (auto &panel : panels_) { - if (panel->visible()) { - ImGui::SetNextWindowClass(window_class); - if (panel->getName() == "Left Menu") { - auto *leftMenu = static_cast(panel.get()); - if (leftMenu->getWidth() != 0) enforceWidth(leftMenu->getWidth()); - } else if (panel->getName() == "Titlebar") { - auto *titlebar = static_cast(panel.get()); - enforceHeight(titlebar->getHeight()); - } - - panel->render(); - } - } -} - -void PanelManager::endPanels() { panels_.clear(); } - -void PanelManager::addPanel(std::unique_ptr panel) { - panels_.push_back(std::move(panel)); -} - -void PanelManager::setPanelVisible(const std::string &name, bool visible) { - for (auto &p : panels_) { - if (p->getName() == name) { - p->setVisible(visible); - if (visible) { - for (auto &q : panels_) { - if (auto *tb = dynamic_cast(q.get())) { - if (name == "Recently Played") - tb->setTitle("Home"); - else - tb->setTitle(name); - } - } - } - return; - } - } -} - -bool PanelManager::isPanelVisible(const std::string &name) const { - for (const auto &p : panels_) { - if (p->getName() == name) { - return p->visible(); - } - } - return false; -} - -void PanelManager::setGames(const std::vector *games) { - for (auto &panel : panels_) { - if (auto *gamePanel = dynamic_cast(panel.get())) { - gamePanel->setGames(games); - } - } -} - -void PanelManager::setOnGamesReload(std::function callback) { - onGamesReload_ = callback; -} - -void PanelManager::refreshPanel(const std::string &name, bool reloadGames) { - if (reloadGames && onGamesReload_) onGamesReload_(); - - for (auto &panel : panels_) { - if (panel->getName() == name) { - if (auto *gp = dynamic_cast(panel.get())) { - gp->refresh(); - } - return; - } - } -} - -void Views::BuildDockLayout() { - ImGuiID dockspace_id = ImGui::GetID("MainDockSpace"); - ImGui::DockBuilderRemoveNode(dockspace_id); - ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None); - ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size); - GLFWmonitor *monitor = glfwGetPrimaryMonitor(); - float xs_, ys_; - glfwGetMonitorContentScale(monitor, &xs_, &ys_); - - ImGuiID titlebar, left, gamesinfo_id, bottom; - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.0445f * xs_ * 0.8, - &left, &dockspace_id); - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.07f * ys_ * 0.8, - &titlebar, &dockspace_id); - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.426f, &gamesinfo_id, - &bottom); - - ImGui::DockBuilderDockWindow("Titlebar", titlebar); - ImGui::DockBuilderDockWindow("Left Menu", left); - ImGui::DockBuilderDockWindow("Games Info", gamesinfo_id); - ImGui::DockBuilderDockWindow("Recently Played", bottom); - ImGui::DockBuilderDockWindow("Library", bottom); - ImGui::DockBuilderDockWindow("Favorites", bottom); - ImGui::DockBuilderDockWindow("Settings", bottom); - - ImGui::DockBuilderFinish(dockspace_id); -} - -void Views::MainMenu() { - if (view == ViewType::MainMenu) return; - - if (!docked_layout_built_) { - BuildDockLayout(); - docked_layout_built_ = true; - } - - panel_manager->setPanelVisible("Games Info", true); - panel_manager->setPanelVisible("Favorites", false); - panel_manager->setPanelVisible("Library", false); - panel_manager->setPanelVisible("Recently Played", true); - panel_manager->setPanelVisible("Settings", false); - view = ViewType::MainMenu; - discord::RichPresence::UpdatePresence("Lazap", "In Main Menu"); -} - -void Views::Library() { - if (view == ViewType::Library) return; - - panel_manager->setPanelVisible("Games Info", false); - panel_manager->setPanelVisible("Favorites", false); - panel_manager->setPanelVisible("Library", true); - panel_manager->setPanelVisible("Recently Played", false); - panel_manager->setPanelVisible("Settings", false); - view = ViewType::Library; - discord::RichPresence::UpdatePresence("Lazap", "In Library"); -} - -void Views::Favorites() { - if (view == ViewType::Favorites) return; - - panel_manager->setPanelVisible("Games Info", false); - panel_manager->setPanelVisible("Favorites", true); - panel_manager->setPanelVisible("Library", false); - panel_manager->setPanelVisible("Recently Played", false); - panel_manager->setPanelVisible("Settings", false); - view = ViewType::Favorites; - discord::RichPresence::UpdatePresence("Lazap", "Browsing Favourites"); - - panel_manager->refreshPanel("Favorites", false); -} - -void Views::Settings() { - if (view == ViewType::Settings) return; - - panel_manager->setPanelVisible("Games Info", false); - panel_manager->setPanelVisible("Favorites", false); - panel_manager->setPanelVisible("Library", false); - panel_manager->setPanelVisible("Recently Played", false); - panel_manager->setPanelVisible("Settings", true); - view = ViewType::Settings; - discord::RichPresence::UpdatePresence("Lazap", "In Settings"); -} +#include "ui/panel_manager.h" + +#include +#include + +#include "addons/discord_rpc/discord_rpc.h" +#include "ui/panels/game_panel.h" +#include "ui/panels/gameinfo_panel.h" +#include "ui/panels/left_panel.h" +#include "ui/panels/settings.h" +#include "ui/panels/titlebar.h" + +using namespace ui; + +template +std::unique_ptr makePanelWithCB(PanelManager *pm, Args &&...args) { + auto panel = std::make_unique(std::forward(args)...); + std::string panelName = panel->getName(); + panel->setOnRefresh([pm, panelName](const bool reloadGames) { + pm->refreshPanel(panelName, reloadGames); + }); + return panel; +} + +void PanelManager::initPanels(GLFWwindow *w, Storage &storage) { + view_ = std::make_unique(this); + + auto titlebar = std::make_unique(w); + Titlebar *titlebarPtr = titlebar.get(); + addPanel(std::move(titlebar)); + addPanel(std::make_unique(view_.get())); + addPanel(std::make_unique()); + + addPanel( + makePanelWithCB(this, "Library", &view_->view, &storage, w)); + addPanel(makePanelWithCB(this, "Favorites", &view_->view, &storage, + nullptr)); + addPanel(makePanelWithCB(this, "Recently Played", &view_->view, + &storage, nullptr)); + addPanel(std::make_unique(&storage, titlebarPtr, w)); + + for (auto &panel : panels_) { + panel->init(); + } +} + +void PanelManager::renderPanels(ImGuiWindowClass *window_class) { + auto enforceWidth = [](float w) { + ImGuiWindow *left_window = ImGui::FindWindowByName("Left Menu"); + if (left_window && left_window->DockNode) { + ImGuiDockNode *dock_node = left_window->DockNode; + dock_node->Size.x = w; + dock_node->SizeRef.x = w; + } + }; + auto enforceHeight = [](float h) { + ImGuiWindow *left_window = ImGui::FindWindowByName("Titlebar"); + if (left_window && left_window->DockNode) { + ImGuiDockNode *dock_node = left_window->DockNode; + dock_node->Size.y = h; + dock_node->SizeRef.y = h; + } + }; + + for (auto &panel : panels_) { + if (panel->visible()) { + ImGui::SetNextWindowClass(window_class); + if (panel->getName() == "Left Menu") { + auto *leftMenu = static_cast(panel.get()); + if (leftMenu->getWidth() != 0) enforceWidth(leftMenu->getWidth()); + } else if (panel->getName() == "Titlebar") { + auto *titlebar = static_cast(panel.get()); + enforceHeight(titlebar->getHeight()); + } + + panel->render(); + } + } +} + +void PanelManager::endPanels() { panels_.clear(); } + +void PanelManager::addPanel(std::unique_ptr panel) { + panels_.push_back(std::move(panel)); +} + +void PanelManager::setPanelVisible(const std::string &name, bool visible) { + for (auto &p : panels_) { + if (p->getName() == name) { + p->setVisible(visible); + if (visible) { + for (auto &q : panels_) { + if (auto *tb = dynamic_cast(q.get())) { + if (name == "Recently Played") + tb->setTitle("Home"); + else + tb->setTitle(name); + } + } + } + return; + } + } +} + +bool PanelManager::isPanelVisible(const std::string &name) const { + for (const auto &p : panels_) { + if (p->getName() == name) { + return p->visible(); + } + } + return false; +} + +void PanelManager::setGames(const std::vector *games) { + for (auto &panel : panels_) { + if (auto *gamePanel = dynamic_cast(panel.get())) { + gamePanel->setGames(games); + } + } +} + +void PanelManager::setOnGamesReload(std::function callback) { + onGamesReload_ = callback; +} + +void PanelManager::refreshPanel(const std::string &name, bool reloadGames) { + if (reloadGames && onGamesReload_) onGamesReload_(); + + for (auto &panel : panels_) { + if (panel->getName() == name) { + if (auto *gp = dynamic_cast(panel.get())) { + gp->refresh(); + } + return; + } + } +} + +void Views::BuildDockLayout() { + ImGuiID dockspace_id = ImGui::GetID("MainDockSpace"); + ImGui::DockBuilderRemoveNode(dockspace_id); + ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None); + ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->Size); + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + float xs_, ys_; + glfwGetMonitorContentScale(monitor, &xs_, &ys_); + + ImGuiID titlebar, left, gamesinfo_id, bottom; + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, + 0.0445f * xs_ * (xs_ > 1 ? 0.75 : 1), &left, + &dockspace_id); + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, + 0.07f * ys_ * (ys_ > 1 ? 0.75 : 1), &titlebar, + &dockspace_id); + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.426f, &gamesinfo_id, + &bottom); + + ImGui::DockBuilderDockWindow("Titlebar", titlebar); + ImGui::DockBuilderDockWindow("Left Menu", left); + ImGui::DockBuilderDockWindow("Games Info", gamesinfo_id); + ImGui::DockBuilderDockWindow("Recently Played", bottom); + ImGui::DockBuilderDockWindow("Library", bottom); + ImGui::DockBuilderDockWindow("Favorites", bottom); + ImGui::DockBuilderDockWindow("Settings", bottom); + + ImGui::DockBuilderFinish(dockspace_id); +} + +void Views::MainMenu() { + if (view == ViewType::MainMenu) return; + + if (!docked_layout_built_) { + BuildDockLayout(); + docked_layout_built_ = true; + } + + panel_manager->setPanelVisible("Games Info", true); + panel_manager->setPanelVisible("Favorites", false); + panel_manager->setPanelVisible("Library", false); + panel_manager->setPanelVisible("Recently Played", true); + panel_manager->setPanelVisible("Settings", false); + view = ViewType::MainMenu; + discord::RichPresence::UpdatePresence("Lazap", "In Main Menu"); +} + +void Views::Library() { + if (view == ViewType::Library) return; + + panel_manager->setPanelVisible("Games Info", false); + panel_manager->setPanelVisible("Favorites", false); + panel_manager->setPanelVisible("Library", true); + panel_manager->setPanelVisible("Recently Played", false); + panel_manager->setPanelVisible("Settings", false); + view = ViewType::Library; + discord::RichPresence::UpdatePresence("Lazap", "In Library"); +} + +void Views::Favorites() { + if (view == ViewType::Favorites) return; + + panel_manager->setPanelVisible("Games Info", false); + panel_manager->setPanelVisible("Favorites", true); + panel_manager->setPanelVisible("Library", false); + panel_manager->setPanelVisible("Recently Played", false); + panel_manager->setPanelVisible("Settings", false); + view = ViewType::Favorites; + discord::RichPresence::UpdatePresence("Lazap", "Browsing Favourites"); + + panel_manager->refreshPanel("Favorites", false); +} + +void Views::Settings() { + if (view == ViewType::Settings) return; + + panel_manager->setPanelVisible("Games Info", false); + panel_manager->setPanelVisible("Favorites", false); + panel_manager->setPanelVisible("Library", false); + panel_manager->setPanelVisible("Recently Played", false); + panel_manager->setPanelVisible("Settings", true); + view = ViewType::Settings; + discord::RichPresence::UpdatePresence("Lazap", "In Settings"); +} diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp old mode 100644 new mode 100755 index 28cf42bf..e486f56f --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -1,476 +1,554 @@ -#include "ui/panels/settings.h" - -#include -#include - -#include - -#include "ui/theme.h" -#include "utils/autostart.h" -#include "utils/font_manager.h" -#include "utils/image_manager.h" - -using namespace ui; - -void SettingsPanel::init() { - ImageManager::loadSVG(b::embed<"assets/svg/config.svg">(), "config:white", - 0xFFFFFFFF); - ImageManager::loadSVG(b::embed<"assets/svg/config.svg">(), "config:dark", - 0x000000); - ImageManager::loadSVG(b::embed<"assets/svg/account.svg">(), "account:white", - 0xFFFFFFFF); - ImageManager::loadSVG(b::embed<"assets/svg/account.svg">(), "account:dark", - 0x000000); - ImageManager::loadSVG(b::embed<"assets/svg/monitor.svg">(), "monitor", - 0xFFFFFFFF); - ImageManager::loadSVG(b::embed<"assets/svg/appearance.svg">(), "appearance", - 0xFFFFFFFF); - ImageManager::loadSVG(b::embed<"assets/svg/link.svg">(), "link", 0xFFFFFFFF); - ImageManager::loadSVG(b::embed<"assets/svg/upload.svg">(), "upload", - 0xA2A2A2); - - loadSettings(); -} - -void SettingsPanel::loadSettings() { - const toml::table toml = storage_->loadTOML(); - const toml::table* settings = toml["settings"].as_table(); - if (!settings) return; - - quitTrayMin_ = settings->get("quit_tray_min")->value_or(false); - autoStart_ = Autostart::shortcutExists(); - checkUpdates_ = settings->get("check_updates")->value_or(true); - launcherIcons_ = settings->get("launcher_icons")->value_or(true); - discordRpc_ = settings->get("discord_rpc")->value_or(false); - customTitlebar_ = settings->get("custom_titlebar")->value_or(true); - - const uint32_t col = - settings->get("accent_color")->value_or(Themes::ACCENT_COLOR); - const float bgOpacity = settings->get("bg_opacity")->value_or(0.8); - - Themes::ACCENT_COLOR = col; - Themes::BG_OPACITY = bgOpacity > 0.8 ? 0.8 : bgOpacity; - - Themes::ACCENT_COLOR_IMGUI = - IM_COL32((col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF, 255); - - titlebar_->setCustomTitlebar(customTitlebar_); - - Themes::setDefaultDarkColors(); -} - -void SettingsPanel::saveSettings() { - storage_->updateTOML([this](toml::table& config) { - if (!config.contains("settings")) { - config.insert("settings", toml::table{}); - } - auto settingsTable = config["settings"].as_table(); - - settingsTable->insert_or_assign("quit_tray_min", quitTrayMin_); - settingsTable->insert_or_assign("auto_start", autoStart_); - settingsTable->insert_or_assign("check_updates", checkUpdates_); - settingsTable->insert_or_assign("launcher_icons", launcherIcons_); - settingsTable->insert_or_assign("discord_rpc", discordRpc_); - settingsTable->insert_or_assign("custom_titlebar", customTitlebar_); - }); -} - -void SettingsPanel::render() { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(35, 50)); - ImGui::Begin(name_.c_str(), nullptr, false); - - scale_ = getScale(); - - // Menu buttons - ImGui::SameLine(); - addMenuButton("Launcher Config", ImVec2(143 * scale_.x, 25 * scale_.y), - view_ == SettingsView::LauncherConfig); - - // ImGui::SameLine(); - // ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (22 * scale_.x)); - // addMenuButton("Account Settings", ImVec2(143 * scale_.x, 25 * scale_.y), - // view_ == SettingsView::AccountSettings); - - // Separator line - ImDrawList* drawlist = ImGui::GetWindowDrawList(); - drawlist->AddLine( - ImVec2(ImGui::GetCursorScreenPos().x - 10 * scale_.x, - ImGui::GetCursorScreenPos().y + 3 * scale_.y), - ImVec2(ImGui::GetCursorScreenPos().x + - (ImGui::GetContentRegionAvail().x - 70 * scale_.x), - ImGui::GetCursorScreenPos().y + (5 * scale_.y)), - IM_COL32(242, 244, 238, 255), 2.0f); - - // Settings - ImGui::Dummy(ImVec2(0, 45 * scale_.y)); - switch (view_) { - case SettingsView::LauncherConfig: - addSection("General", "monitor"); - ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); - ImGui::PushID("general_settings"); - ImGui::BeginGroup(); - - if (addOption("Minimize to Tray on Exit", InputType::Toggle, - &quitTrayMin_)) { - saveSettings(); - ImGui::OpenPopup("Restart"); - } - if (addOption("Launch at Startup", InputType::Toggle, &autoStart_)) { - saveSettings(); - if (autoStart_) - Autostart::createShortcut(); - else - Autostart::deleteShortcut(); - } - if (addOption("Check for Updates", InputType::Toggle, &checkUpdates_, - true)) { - // saveSettings(); - ImGui::OpenPopup("Coming Soon"); - } - - ImGui::EndGroup(); - ImGui::PopID(); - ImGui::PopFont(); - - ImGui::Dummy(ImVec2(0, 47 * scale_.y)); - - addSection("Appearance", "appearance"); - ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); - ImGui::PushID("appearance_settings"); - ImGui::BeginGroup(); - addOption("Accent Color", InputType::ColorPicker, nullptr); - addOption("Background Image", InputType::ImagePicker, nullptr); - addOption("Background Image Opacity", InputType::IntTextbox, nullptr); - - if (addOption("Enable Launcher Icons", InputType::Toggle, &launcherIcons_, - true)) { - // saveSettings(); - ImGui::OpenPopup("Coming Soon"); - } - -#ifdef __linux__ - if (addOption("Custom Titlebar", InputType::Toggle, &customTitlebar_)) { - saveSettings(); - titlebar_->setCustomTitlebar(customTitlebar_); - } -#endif - - if (ImGui::BeginPopup("Coming Soon", ImGuiWindowFlags_NoMove)) { - ImGui::Text("This feature is coming soon!"); - ImGui::EndPopup(); - } - if (ImGui::BeginPopup("Restart", ImGuiWindowFlags_NoMove)) { - ImGui::Text("Restart the app to apply this change"); - ImGui::EndPopup(); - } - - ImGui::PopFont(); - ImGui::EndGroup(); - ImGui::PopID(); - - ImGui::Dummy(ImVec2(0, 47 * scale_.y)); - - addSection("Integrations", "link"); - ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); - ImGui::PushID("integration_settings"); - ImGui::BeginGroup(); - - if (addOption("Discord Rich Presence(RPC)", InputType::Toggle, - &discordRpc_)) { - saveSettings(); - } - - ImGui::PopFont(); - ImGui::EndGroup(); - ImGui::PopID(); - break; - // case SettingsView::AccountSettings: - // ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); - // ImGui::Image(ImageManager::get("appearance"), - // ImVec2(27 * scale_.x, 27 * scale_.x)); - // ImGui::Text("Account Settings"); - // ImGui::PopFont(); - // ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); - // ImGui::Dummy(ImVec2(0, 10)); - // ImGui::Text("Username: "); - // // ImGui::InputText("##username", &username_buffer_); - // ImGui::PopFont(); - // break; - default: - view_ = SettingsView::LauncherConfig; - break; - } - - ImGui::End(); - ImGui::PopStyleVar(); -} - -bool SettingsPanel::addMenuButton(const std::string& label, ImVec2 size, - bool active = false) { - if (active) { - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(8, 8, 8, 255)); - ImDrawList* drawlist = ImGui::GetWindowDrawList(); - ImVec2 p = ImGui::GetCursorScreenPos(); - drawlist->AddRectFilled( - ImVec2(p.x, p.y), ImVec2(p.x + (size.x), p.y + (size.y)), - IM_COL32(242, 244, 238, 255), 3.0f, - ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight); - addIcon(view_ == SettingsView::LauncherConfig ? "config:dark" - : "account:dark"); - } else { - addIcon(view_ == SettingsView::AccountSettings ? "config:white" - : "account:white"); - } - ImGui::PushFont(FontManager::getFont("Nunito-B"), 13.0f); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10 * scale_.x, 0)); - bool btn = ImGui::Button(label.c_str()); - ImGui::PopStyleVar(); - ImGui::PopFont(); - if (active) { - ImGui::PopStyleColor(); - } - if (btn && !active) { - view_ = - view_ == SettingsView::LauncherConfig ? SettingsView::AccountSettings - : view_ == SettingsView::AccountSettings ? SettingsView::LauncherConfig - : SettingsView::LauncherConfig; - } - return btn; -} - -void SettingsPanel::addIcon(const std::string& icon) { - ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (11 * scale_.x), - ImGui::GetCursorPosY() + (5 * scale_.y))); - ImGui::Image(ImageManager::get(icon), ImVec2(13 * scale_.x, 13 * scale_.x)); - ImGui::SameLine(); - ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (4 * scale_.x), - ImGui::GetCursorPosY() + (5 * scale_.y))); -} - -void SettingsPanel::addSection(const std::string& title, - const std::string& icon) { - ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); - ImGui::Dummy(ImVec2(8 * scale_.x, 0)); - ImGui::Image(ImageManager::get(icon), ImVec2(27 * scale_.x, 27 * scale_.x)); - ImGui::SameLine(0, 8 * scale_.x); - ImGui::Text("%s", title.c_str()); - ImGui::PopFont(); - ImGui::Dummy(ImVec2(0, 18.5 * scale_.y)); - ImGui::Dummy(ImVec2(35 * scale_.x, 0)); - ImGui::SameLine(); -} - -bool SettingsPanel::addOption(const std::string& label, InputType input, - bool* value, bool disabled) { - ImGui::PushID(label.c_str()); - ImGui::BeginChild("row", ImVec2(0, 39 * scale_.y), false); - ImGui::Dummy(ImVec2(0, 4.5 * scale_.y)); - - bool changed = false; - - if (ImGui::BeginTable("option_table", 2, ImGuiTableFlags_SizingFixedFit, - ImVec2(590 * scale_.x, 0))) { - ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("Widget", ImGuiTableColumnFlags_WidthFixed, - 110 * scale_.x); - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); - ImGui::Text("%s", label.c_str()); - ImGui::TableSetColumnIndex(1); - - float widthAvailable = ImGui::GetColumnWidth(); - switch (input) { - case InputType::Toggle: { - float widthNeeded = 40 * scale_.x; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + - (widthAvailable - widthNeeded)); - if (value) { - changed = ToggleButton("##toggle", value, disabled); - } - } break; - - case InputType::ColorPicker: { - float widthNeeded = 110.0f * scale_.x; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + - (widthAvailable - widthNeeded)); - - float col[3] = {((Themes::ACCENT_COLOR >> 16) & 0xFF) / 255.0f, - ((Themes::ACCENT_COLOR >> 8) & 0xFF) / 255.0f, - (Themes::ACCENT_COLOR & 0xFF) / 255.0f}; - - if (ColorBox(label.c_str(), col, - ImVec2(widthNeeded, 30.0f * scale_.y))) { - uint8_t r = static_cast(col[0] * 255.0f); - uint8_t g = static_cast(col[1] * 255.0f); - uint8_t b = static_cast(col[2] * 255.0f); - - Themes::ACCENT_COLOR = - (uint32_t(r) << 16) | (uint32_t(g) << 8) | uint32_t(b); - Themes::ACCENT_COLOR_IMGUI = IM_COL32(r, g, b, 255); - - storage_->updateTOML([](toml::table& config) { - if (auto settings = config["settings"].as_table()) { - settings->insert_or_assign("accent_color", Themes::ACCENT_COLOR); - } - }); - } - } break; - - case InputType::ImagePicker: { - ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13.0f); - float widthNeeded = 110 * scale_.x; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + - (widthAvailable - widthNeeded)); - if (FilePickerButton(label.c_str(), - ImVec2(110 * scale_.x, 30 * scale_.y))) { - glfwIconifyWindow(window_); - const char* filters[] = {"*.png"}; - const char* path = tinyfd_openFileDialog("Select Banner Image", "", 1, - filters, "Image files", 0); - if (path) { - if (storage_->exists("custom_bg.png")) { - ImageManager::remove("custom_bg"); - } - std::filesystem::copy_file( - path, - std::filesystem::path(storage_->getStoragePath()) / - "custom_bg.png", - std::filesystem::copy_options::overwrite_existing); - ImageManager::loadPNG( - (std::filesystem::path(storage_->getStoragePath()) / - "custom_bg.png") - .string()); - } - glfwRestoreWindow(window_); - } - ImGui::PopFont(); - } break; - - case InputType::IntTextbox: { - float widthNeeded = 92 * scale_.x; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + - (widthAvailable - widthNeeded)); - float n = Themes::BG_OPACITY; - ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13.0f); - if (NumberBox(label.c_str(), &n, 92 * scale_.x)) { - Themes::BG_OPACITY = n; - } - ImGui::PopFont(); - - storage_->updateTOML([](toml::table& config) { - if (auto settings = config["settings"].as_table()) { - settings->insert_or_assign("bg_opacity", Themes::BG_OPACITY); - } - }); - } break; - - case InputType::StringTextbox: { - float widthNeeded = 490 * scale_.x; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + - (widthAvailable - widthNeeded)); - char s; - ImGui::SetNextItemWidth(250 * scale_.x); - ImGui::InputText("##text", &s, 32); - } break; - } - - ImGui::EndTable(); - } - - ImGui::EndChild(); - ImGui::PopID(); - - return changed; -} - -bool SettingsPanel::ToggleButton(const char* id, bool* v, bool disabled) { - float height = 20 * scale_.y; - float width = 40 * scale_.x; - float radius = 14.67f * scale_.y * 0.5f; - - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImDrawList* draw = ImGui::GetWindowDrawList(); - - ImGui::InvisibleButton(id, ImVec2(width, height)); - bool toggled = ImGui::IsItemClicked(); - - if (toggled && !disabled) *v = !*v; - - float t = *v ? 1.0f : 0.0f; - - ImU32 col_bg = *v ? IM_COL32(20, 174, 92, 255) // ON - : IM_COL32(162, 162, 162, 105); // OFF - - ImU32 col_knob = IM_COL32(242, 244, 238, 255); - - // Draw track - draw->AddRectFilled(pos, ImVec2(pos.x + width, pos.y + height), col_bg, 50); - - // Draw knob - float knob_x = pos.x + t * (width - height) + 2.67f * scale_.x; - draw->AddCircleFilled( - ImVec2(knob_x + radius, pos.y + 2.67 * scale_.y + radius), radius, - col_knob); - - return toggled; -} - -bool SettingsPanel::ColorBox(const char* id, float color[3], ImVec2 size) { - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImDrawList* draw = ImGui::GetWindowDrawList(); - - ImGui::InvisibleButton(id, size); - - draw->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), - ImGui::ColorConvertFloat4ToU32( - ImVec4(color[0], color[1], color[2], 1.0f)), - 4.0f); - - draw->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), - IM_COL32(255, 255, 255, 255), 4.0f, 0, 1.0f); - - if (ImGui::IsItemClicked()) ImGui::OpenPopup(id); - - bool changed = false; - if (ImGui::BeginPopup(id, ImGuiWindowFlags_NoMove)) { - changed = ImGui::ColorPicker3( - "##picker", color, - ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoAlpha | - ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_PickerHueBar | - ImGuiColorEditFlags_NoSmallPreview); - ImGui::EndPopup(); - } - return changed; -} - -bool SettingsPanel::FilePickerButton(const char* label, const ImVec2& size) { - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.20f, 0.22f, 0.27f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, - ImVec4(0.30f, 0.32f, 0.40f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, - ImVec4(0.35f, 0.38f, 0.50f, 1.0f)); - - bool pressed = ImGui::Button(label, size); - - ImGui::PopStyleColor(3); - - return pressed; -} - -bool SettingsPanel::NumberBox(const char* id, float* value, float width) { - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 3.5f)); - - ImGui::PushItemWidth(width); - bool changed = ImGui::InputFloat(id, value, 0.0f, 0.0f, "%.2f"); - ImGui::PopItemWidth(); - - if (changed && *value > 0.8) { - *value = 0.8; - } - - ImGui::PopStyleVar(2); - return changed; -} +#include "ui/panels/settings.h" + +#include +#include + +#include + +#include "ui/theme.h" +#include "utils/autostart.h" +#include "utils/font_manager.h" +#include "utils/image_manager.h" + +using namespace ui; + +void SettingsPanel::init() { + ImageManager::loadSVG(b::embed<"assets/svg/config.svg">(), "config:white", + 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/config.svg">(), "config:dark", + 0x000000); + ImageManager::loadSVG(b::embed<"assets/svg/account.svg">(), "account:white", + 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/account.svg">(), "account:dark", + 0x000000); + ImageManager::loadSVG(b::embed<"assets/svg/monitor.svg">(), "monitor", + 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/appearance.svg">(), "appearance", + 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/link.svg">(), "link", 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/upload.svg">(), "upload", + 0xA2A2A268); + + loadSettings(); +} + +void SettingsPanel::loadSettings() { + const toml::table toml = storage_->loadTOML(); + const toml::table* settings = toml["settings"].as_table(); + if (!settings) return; + + quitTrayMin_ = settings->get("quit_tray_min")->value_or(false); + autoStart_ = Autostart::shortcutExists(); + checkUpdates_ = settings->get("check_updates")->value_or(true); + launcherIcons_ = settings->get("launcher_icons")->value_or(true); + discordRpc_ = settings->get("discord_rpc")->value_or(false); + customTitlebar_ = settings->get("custom_titlebar")->value_or(true); + + const uint32_t col = + settings->get("accent_color")->value_or(Themes::ACCENT_COLOR); + const float bgOpacity = settings->get("bg_opacity")->value_or(0.8); + + Themes::ACCENT_COLOR = col; + Themes::BG_OPACITY = bgOpacity > 0.8 ? 0.8 : bgOpacity; + + Themes::ACCENT_COLOR_IMGUI = + IM_COL32((col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF, 255); + + titlebar_->setCustomTitlebar(customTitlebar_); + + Themes::setDefaultDarkColors(); +} + +void SettingsPanel::saveSettings() { + storage_->updateTOML([this](toml::table& config) { + if (!config.contains("settings")) { + config.insert("settings", toml::table{}); + } + auto settingsTable = config["settings"].as_table(); + + settingsTable->insert_or_assign("quit_tray_min", quitTrayMin_); + settingsTable->insert_or_assign("auto_start", autoStart_); + settingsTable->insert_or_assign("check_updates", checkUpdates_); + settingsTable->insert_or_assign("launcher_icons", launcherIcons_); + settingsTable->insert_or_assign("discord_rpc", discordRpc_); + settingsTable->insert_or_assign("custom_titlebar", customTitlebar_); + }); +} + +void SettingsPanel::render() { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(35, 50)); + ImGui::Begin(name_.c_str(), nullptr, false); + + scale_ = getScale(); + + // Menu buttons + ImGui::SameLine(); + addMenuButton("Launcher Config", ImVec2(143 * scale_.x, 25 * scale_.y), + view_ == SettingsView::LauncherConfig); + + // ImGui::SameLine(); + // ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (22 * scale_.x)); + // addMenuButton("Account Settings", ImVec2(143 * scale_.x, 25 * scale_.y), + // view_ == SettingsView::AccountSettings); + + // Separator line + ImDrawList* drawlist = ImGui::GetWindowDrawList(); + drawlist->AddLine( + ImVec2(ImGui::GetCursorScreenPos().x - 10 * scale_.x, + ImGui::GetCursorScreenPos().y + 3 * scale_.y), + ImVec2(ImGui::GetCursorScreenPos().x + + (ImGui::GetContentRegionAvail().x - 70 * scale_.x), + ImGui::GetCursorScreenPos().y + (5 * scale_.y)), + IM_COL32(242, 244, 238, 255), 2.0f); + + // Settings + ImGui::Dummy(ImVec2(0, 45 * scale_.y)); + switch (view_) { + case SettingsView::LauncherConfig: + addSection("General", "monitor"); + ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); + ImGui::PushID("general_settings"); + ImGui::BeginGroup(); + + if (addOption("Minimize to Tray on Exit", InputType::Toggle, + &quitTrayMin_)) { + saveSettings(); + ImGui::OpenPopup("Restart"); + } + if (addOption("Launch at Startup", InputType::Toggle, &autoStart_)) { + saveSettings(); + if (autoStart_) + Autostart::createShortcut(); + else + Autostart::deleteShortcut(); + } + if (addOption("Check for Updates", InputType::Toggle, &checkUpdates_, + true)) { + // saveSettings(); + ImGui::OpenPopup("Coming Soon"); + } + + ImGui::EndGroup(); + ImGui::PopID(); + ImGui::PopFont(); + + ImGui::Dummy(ImVec2(0, 47 * scale_.y)); + + addSection("Appearance", "appearance"); + ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); + ImGui::PushID("appearance_settings"); + ImGui::BeginGroup(); + addOption("Accent Color", InputType::ColorPicker, nullptr); + addOption("Background Image", InputType::ImagePicker, nullptr); + addOption("Background Image Opacity", InputType::IntTextbox, nullptr); + + if (addOption("Enable Launcher Icons", InputType::Toggle, &launcherIcons_, + true)) { + // saveSettings(); + ImGui::OpenPopup("Coming Soon"); + } + +#ifdef __linux__ + if (addOption("Custom Titlebar", InputType::Toggle, &customTitlebar_)) { + saveSettings(); + titlebar_->setCustomTitlebar(customTitlebar_); + } +#endif + + if (ImGui::BeginPopup("Coming Soon", ImGuiWindowFlags_NoMove)) { + ImGui::Text("This feature is coming soon!"); + ImGui::EndPopup(); + } + if (ImGui::BeginPopup("Restart", ImGuiWindowFlags_NoMove)) { + ImGui::Text("Restart the app to apply this change"); + ImGui::EndPopup(); + } + + ImGui::PopFont(); + ImGui::EndGroup(); + ImGui::PopID(); + + ImGui::Dummy(ImVec2(0, 47 * scale_.y)); + + addSection("Integrations", "link"); + ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); + ImGui::PushID("integration_settings"); + ImGui::BeginGroup(); + + if (addOption("Discord Rich Presence(RPC)", InputType::Toggle, + &discordRpc_)) { + saveSettings(); + } + + ImGui::PopFont(); + ImGui::EndGroup(); + ImGui::PopID(); + break; + // case SettingsView::AccountSettings: + // ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); + // ImGui::Image(ImageManager::get("appearance"), + // ImVec2(27 * scale_.x, 27 * scale_.x)); + // ImGui::Text("Account Settings"); + // ImGui::PopFont(); + // ImGui::PushFont(FontManager::getFont("Nunito-L"), 18.0f); + // ImGui::Dummy(ImVec2(0, 10)); + // ImGui::Text("Username: "); + // // ImGui::InputText("##username", &username_buffer_); + // ImGui::PopFont(); + // break; + default: + view_ = SettingsView::LauncherConfig; + break; + } + + ImGui::End(); + ImGui::PopStyleVar(); +} + +bool SettingsPanel::addMenuButton(const std::string& label, ImVec2 size, + bool active = false) { + if (active) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(8, 8, 8, 255)); + ImDrawList* drawlist = ImGui::GetWindowDrawList(); + ImVec2 p = ImGui::GetCursorScreenPos(); + drawlist->AddRectFilled( + ImVec2(p.x, p.y), ImVec2(p.x + (size.x), p.y + (size.y)), + IM_COL32(242, 244, 238, 255), 3.0f, + ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight); + addIcon(view_ == SettingsView::LauncherConfig ? "config:dark" + : "account:dark"); + } else { + addIcon(view_ == SettingsView::AccountSettings ? "config:white" + : "account:white"); + } + ImGui::PushFont(FontManager::getFont("Nunito-B"), 13.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10 * scale_.x, 0)); + bool btn = ImGui::Button(label.c_str()); + ImGui::PopStyleVar(); + ImGui::PopFont(); + if (active) { + ImGui::PopStyleColor(); + } + if (btn && !active) { + view_ = + view_ == SettingsView::LauncherConfig ? SettingsView::AccountSettings + : view_ == SettingsView::AccountSettings ? SettingsView::LauncherConfig + : SettingsView::LauncherConfig; + } + return btn; +} + +void SettingsPanel::addIcon(const std::string& icon) { + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (11 * scale_.x), + ImGui::GetCursorPosY() + (5 * scale_.y))); + ImGui::Image(ImageManager::get(icon), ImVec2(13 * scale_.x, 13 * scale_.x)); + ImGui::SameLine(); + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (4 * scale_.x), + ImGui::GetCursorPosY() + (5 * scale_.y))); +} + +void SettingsPanel::addSection(const std::string& title, + const std::string& icon) { + ImGui::PushFont(FontManager::getFont("ArchivoBlack-R"), 24.0f); + ImGui::Dummy(ImVec2(8 * scale_.x, 0)); + ImGui::Image(ImageManager::get(icon), ImVec2(27 * scale_.x, 27 * scale_.x)); + ImGui::SameLine(0, 8 * scale_.x); + ImGui::Text("%s", title.c_str()); + ImGui::PopFont(); + ImGui::Dummy(ImVec2(0, 18.5 * scale_.y)); + ImGui::Dummy(ImVec2(35 * scale_.x, 0)); + ImGui::SameLine(); +} + +bool SettingsPanel::addOption(const std::string& label, InputType input, + bool* value, bool disabled) { + ImGui::PushID(label.c_str()); + ImGui::BeginChild("row", ImVec2(0, 39 * scale_.y), false); + ImGui::Dummy(ImVec2(0, 4.5 * scale_.y)); + + bool changed = false; + + if (ImGui::BeginTable("option_table", 2, ImGuiTableFlags_SizingFixedFit, + ImVec2(590 * scale_.x, 0))) { + ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("Widget", ImGuiTableColumnFlags_WidthFixed, + 110 * scale_.x); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::AlignTextToFramePadding(); + ImGui::Text("%s", label.c_str()); + ImGui::TableSetColumnIndex(1); + + float widthAvailable = ImGui::GetColumnWidth(); + switch (input) { + case InputType::Toggle: { + float widthNeeded = 40 * scale_.x; + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + + (widthAvailable - widthNeeded)); + if (value) { + changed = ToggleButton("##toggle", value, disabled); + } + } break; + + case InputType::ColorPicker: { + float widthNeeded = 110.0f * scale_.x; + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + + (widthAvailable - widthNeeded)); + + float col[3] = {((Themes::ACCENT_COLOR >> 16) & 0xFF) / 255.0f, + ((Themes::ACCENT_COLOR >> 8) & 0xFF) / 255.0f, + (Themes::ACCENT_COLOR & 0xFF) / 255.0f}; + + if (ColorBox(label.c_str(), col, + ImVec2(widthNeeded, 30.0f * scale_.y))) { + uint8_t r = static_cast(col[0] * 255.0f); + uint8_t g = static_cast(col[1] * 255.0f); + uint8_t b = static_cast(col[2] * 255.0f); + + Themes::ACCENT_COLOR = + (uint32_t(r) << 16) | (uint32_t(g) << 8) | uint32_t(b); + Themes::ACCENT_COLOR_IMGUI = IM_COL32(r, g, b, 255); + + storage_->updateTOML([](toml::table& config) { + if (auto settings = config["settings"].as_table()) { + settings->insert_or_assign("accent_color", Themes::ACCENT_COLOR); + } + }); + } + } break; + + case InputType::ImagePicker: { + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13.0f); + float widthNeeded = 110 * scale_.x; + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + + (widthAvailable - widthNeeded)); + if (FilePickerButton(label.c_str(), + ImVec2(110 * scale_.x, 30 * scale_.y))) { + glfwIconifyWindow(window_); + const char* filters[] = {"*.png"}; + const char* path = tinyfd_openFileDialog("Select Banner Image", "", 1, + filters, "Image files", 0); + if (path) { + if (storage_->exists("custom_bg.png")) { + ImageManager::remove("custom_bg"); + } + std::filesystem::copy_file( + path, + std::filesystem::path(storage_->getStoragePath()) / + "custom_bg.png", + std::filesystem::copy_options::overwrite_existing); + ImageManager::loadPNG( + (std::filesystem::path(storage_->getStoragePath()) / + "custom_bg.png") + .string()); + } + glfwRestoreWindow(window_); + } + ImGui::PopFont(); + } break; + + case InputType::IntTextbox: { + float widthNeeded = 40 * scale_.x; + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + + (widthAvailable - widthNeeded)); + float n = Themes::BG_OPACITY; + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13.0f); + if (NumberBox(label.c_str(), &n, widthNeeded)) { + Themes::BG_OPACITY = n; + } + ImGui::PopFont(); + + storage_->updateTOML([](toml::table& config) { + if (auto settings = config["settings"].as_table()) { + settings->insert_or_assign("bg_opacity", Themes::BG_OPACITY); + } + }); + } break; + + case InputType::StringTextbox: { + float widthNeeded = 490 * scale_.x; + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + + (widthAvailable - widthNeeded)); + char s; + ImGui::SetNextItemWidth(250 * scale_.x); + ImGui::InputText("##text", &s, 32); + } break; + } + + ImGui::EndTable(); + } + + ImGui::EndChild(); + ImGui::PopID(); + + return changed; +} + +bool SettingsPanel::ToggleButton(const char* id, bool* v, bool disabled) { + float height = 20 * scale_.y; + float width = 40 * scale_.x; + float radius = 14.67f * scale_.y * 0.5f; + + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImDrawList* draw = ImGui::GetWindowDrawList(); + + ImGui::InvisibleButton(id, ImVec2(width, height)); + bool toggled = ImGui::IsItemClicked(); + + if (toggled && !disabled) *v = !*v; + + float t = *v ? 1.0f : 0.0f; + + ImU32 col_bg = *v ? IM_COL32(20, 174, 92, 255) // ON + : IM_COL32(162, 162, 162, 105); // OFF + + ImU32 col_knob = IM_COL32(242, 244, 238, 255); + + // Draw track + draw->AddRectFilled(pos, ImVec2(pos.x + width, pos.y + height), col_bg, 50); + + // Draw knob + float knob_x = pos.x + t * (width - height) + 2.67f * scale_.x; + draw->AddCircleFilled( + ImVec2(knob_x + radius, pos.y + 2.67 * scale_.y + radius), radius, + col_knob); + + return toggled; +} + +bool SettingsPanel::ColorBox(const char* id, float color[3], ImVec2 size) { + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImVec2 p = ImGui::GetCursorPos(); + ImDrawList* draw = ImGui::GetWindowDrawList(); + + ImGui::InvisibleButton(id, size); + + draw->AddRectFilled( + ImVec2(pos.x + 6 * scale_.x, pos.y + 7 * scale_.y), + ImVec2(pos.x + (20 + 6) * scale_.x, pos.y + (15 + 7) * scale_.y), + ImGui::ColorConvertFloat4ToU32( + ImVec4(color[0], color[1], color[2], 1.0f)), + 4.0f); + std::string hexColor = + rgbToHex(color[0] * 255, color[1] * 255, color[2] * 255); + std::transform(hexColor.begin(), hexColor.end(), hexColor.begin(), ::toupper); + ImGui::SetCursorPos(ImVec2(p.x + 36 * scale_.x, p.y + 7 * scale_.y)); + ImGui::PushStyleColor(ImGuiCol_Text, 0xA2A2A268); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13); + ImGui::Text("%s", hexColor.c_str()); + ImGui::PopFont(); + ImGui::PopStyleColor(); + draw->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), + IM_COL32(162, 162, 162, 104), 4.0f, 0, 1.0f); + + if (ImGui::IsItemClicked()) ImGui::OpenPopup(id); + + bool changed = false; + if (ImGui::BeginPopup(id, ImGuiWindowFlags_NoMove)) { + changed = ImGui::ColorPicker3( + "##picker", color, + ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoAlpha | + ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_PickerHueBar | + ImGuiColorEditFlags_NoSmallPreview); + ImGui::EndPopup(); + } + return changed; +} + +bool SettingsPanel::FilePickerButton(const char* label, const ImVec2& size) { + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.20f, 0.22f, 0.27f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + ImVec4(0.30f, 0.32f, 0.40f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + ImVec4(0.35f, 0.38f, 0.50f, 1.0f)); + + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImVec2 p = ImGui::GetCursorPos(); + ImDrawList* draw = ImGui::GetWindowDrawList(); + + bool pressed = ImGui::InvisibleButton(label, size); + + ImGui::SetCursorPos(ImVec2(p.x + 16 * scale_.x, p.y + 7 * scale_.y)); + ImGui::Image(ImageManager::get("upload"), + ImVec2(13 * scale_.x, 13 * scale_.y)); + ImGui::SetCursorPos(ImVec2(p.x + 36 * scale_.x, p.y + 7 * scale_.y)); + ImGui::PushStyleColor(ImGuiCol_Text, 0xA2A2A268); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13); + ImGui::Text("Select File"); + ImGui::PopFont(); + ImGui::PopStyleColor(); + + draw->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), + IM_COL32(162, 162, 162, 104), 4.0f, 0, 1.0f); + + ImGui::PopStyleColor(3); + + return pressed; +} + +bool SettingsPanel::NumberBox(const char* id, float* value, float width) { + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImVec2 p = ImGui::GetCursorPos(); + ImDrawList* draw = ImGui::GetWindowDrawList(); + static char buf[32]; + + isEditing_ = isEditing_ == true + ? true + : ImGui::InvisibleButton(id, ImVec2(width, 30 * scale_.y)); + + std::string display = std::to_string(int(*value * 100)) + "%"; + ImVec2 textSize = ImGui::CalcTextSize(display.c_str()); + + if (!isEditing_) { + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13); + draw->AddText(ImVec2(pos.x + (width - textSize.x) * 0.5f, + pos.y + (30 * scale_.y - textSize.y) * 0.5f), + 0xA2A2A268, display.c_str()); + ImGui::PopFont(); + } else { + sprintf(buf, "%d%%", static_cast(*value * 100.0f)); + ImGui::SetCursorScreenPos( + ImVec2(pos.x + (width - textSize.x) * 0.5f, + pos.y + (30 * scale_.y - textSize.y) * 0.5f)); + ImGui::SetNextItemWidth(width); + + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 13); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(162.0 / 255.0, 162.0 / 255.0, + 162.0 / 255.0, 104.0 / 255.0)); + ImGui::SetKeyboardFocusHere(); + if (ImGui::InputText("##edit", buf, 32, + ImGuiInputTextFlags_EnterReturnsTrue)) { + try { + std::string s = buf; + s.erase(std::remove(s.begin(), s.end(), '%'), s.end()); + float val = std::stof(buf); + *value = std::clamp(val, 0.0f, 80.0f) / 100; + isEditing_ = false; + } catch (std::exception) { + } + } + ImGui::PopStyleColor(2); + ImGui::PopFont(); + + if (ImGui::IsItemDeactivatedAfterEdit()) { + isEditing_ = false; + } + } + + draw->AddRect(pos, ImVec2(pos.x + width, pos.y + 30 * scale_.y), + IM_COL32(162, 162, 162, 104), 4.0f, 0, 1.0f); + + return isEditing_; +} + +std::string rgbToHex(int r, int g, int b) { + std::stringstream ss; + + ss << "#" << std::hex << std::setfill('0') << std::setw(2) << r << std::hex + << std::setfill('0') << std::setw(2) << g << std::hex << std::setfill('0') + << std::setw(2) << b; + + return ss.str(); +} \ No newline at end of file From f5e6c0d0c4e217be4c495d4f84eb030a5a462b16 Mon Sep 17 00:00:00 2001 From: Spoiled Unknown <58999771+SpoiledUnknown@users.noreply.github.com> Date: Thu, 25 Jun 2026 18:20:59 +0530 Subject: [PATCH 15/17] Added the check for update functionality. --- assets/svg/download.svg | 5 ++ include/utils/update_manager.h | 8 ++++ include/version.h | 3 ++ src/core/application.cpp | 6 +++ src/core/utils/image_manager.cpp | 2 + src/core/utils/update_manager.cpp | 79 +++++++++++++++++++++++++++++++ src/ui/panels/left_panel.cpp | 22 +++++++-- src/ui/panels/settings.cpp | 7 ++- 8 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 assets/svg/download.svg create mode 100644 include/utils/update_manager.h create mode 100644 include/version.h create mode 100644 src/core/utils/update_manager.cpp diff --git a/assets/svg/download.svg b/assets/svg/download.svg new file mode 100644 index 00000000..156485c5 --- /dev/null +++ b/assets/svg/download.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/include/utils/update_manager.h b/include/utils/update_manager.h new file mode 100644 index 00000000..4b04944f --- /dev/null +++ b/include/utils/update_manager.h @@ -0,0 +1,8 @@ +#pragma once +#include + +namespace Updater { +void checkForUpdates(); +inline bool hasUpdate; +inline std::string url; +} // namespace Updater \ No newline at end of file diff --git a/include/version.h b/include/version.h new file mode 100644 index 00000000..ff639828 --- /dev/null +++ b/include/version.h @@ -0,0 +1,3 @@ +#pragma once + +#define APP_VERSION "0.1.0" diff --git a/src/core/application.cpp b/src/core/application.cpp index e2fad968..08cdc284 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -15,6 +15,7 @@ #include "storage/storage.h" #include "utils/banner_manager.h" #include "utils/tray_manager.h" +#include "utils/update_manager.h" #ifdef _WIN32 #define _WIN32_WINNT 0x0A00 // Windows 10 @@ -28,6 +29,7 @@ GLFWcursor *WindowCallbacks::cursor_nwse = nullptr; GLFWcursor *WindowCallbacks::cursor_nesw = nullptr; GLFWcursor *WindowCallbacks::cursor_h = nullptr; + GLFWcursor *WindowCallbacks::cursor_v = nullptr; bool WindowCallbacks::hovered_; #endif @@ -147,12 +149,14 @@ void Application::run() { storage.initTOML(); bool discordRpc = true; + bool checkForUpdates = true; bool systemTray = false; auto toml = storage.loadTOML(); auto *settingsTable = toml["settings"].as_table(); if (settingsTable) { discordRpc = settingsTable->get("discord_rpc")->value_or(false); systemTray = settingsTable->get("quit_tray_min")->value_or(false); + checkForUpdates = settingsTable->get("check_updates")->value_or(false); } std::vector> clients; @@ -193,6 +197,8 @@ void Application::run() { discord::RichPresence::UpdatePresence("Lazap", "In Main Menu"); } + if (checkForUpdates) Updater::checkForUpdates(); + printf("Startup took: %ld ms\n", std::chrono::duration_cast( std::chrono::high_resolution_clock::now() - startupBegin) diff --git a/src/core/utils/image_manager.cpp b/src/core/utils/image_manager.cpp index 73df7a8d..0e1730b4 100644 --- a/src/core/utils/image_manager.cpp +++ b/src/core/utils/image_manager.cpp @@ -7,6 +7,8 @@ #include "battery/embed.hpp" #define STB_IMAGE_IMPLEMENTATION +#include + #include "stb_image.h" std::unordered_map ImageManager::cache; diff --git a/src/core/utils/update_manager.cpp b/src/core/utils/update_manager.cpp new file mode 100644 index 00000000..c617f36e --- /dev/null +++ b/src/core/utils/update_manager.cpp @@ -0,0 +1,79 @@ +#include "utils/update_manager.h" + +#include + +#include +#include + +#include "string.h" +#include "version.h" + +struct UpdateRes { + std::string tag_name; + std::string html_url; +}; + +template <> +struct glz::meta { + static constexpr auto value = object("tag_name", &UpdateRes::tag_name, + "html_url", &UpdateRes::html_url); +}; + +struct Version { + int major; + int minor; + int patch; +}; + +Version parseVersion(std::string version) { + Version result{}; + + if (!version.empty() && version[0] == 'v') version.erase(0, 1); + + sscanf(version.data(), "%d.%d.%d", &result.major, &result.minor, + &result.patch); + + return result; +} + +bool isNewer(const Version& remote, const Version& local) { + if (remote.major != local.major) return remote.major > local.major; + + if (remote.minor != local.minor) return remote.minor > local.minor; + + return remote.patch > local.patch; +} + +namespace Updater { +void checkForUpdates() { + cpr::Response res = cpr::Get(cpr::Url{ + "https://api.github.com/repos/Lazap-Development/Lazap/releases/latest"}); + + if (res.status_code != 200) { + std::cerr << "HTTP Error: " << res.status_code << std::endl; + return; + } + + UpdateRes obj; + + if (auto ec = + glz::read(obj, res.text); + ec) { + std::cerr << glz::format_error(ec, res.text) << std::endl; + return; + } + + glz::read_json(obj, res.text); + + auto remoteVersion = parseVersion(obj.tag_name); + auto localVersion = parseVersion(APP_VERSION); + + if (isNewer(remoteVersion, localVersion)) { + std::cout << "Remote Version: " << obj.tag_name << std::endl; + std::cout << "Local Version: " << APP_VERSION << std::endl; + + hasUpdate = true; + url = obj.html_url; + } +} +} // namespace Updater \ No newline at end of file diff --git a/src/ui/panels/left_panel.cpp b/src/ui/panels/left_panel.cpp index 11a43dd7..26afd8e2 100644 --- a/src/ui/panels/left_panel.cpp +++ b/src/ui/panels/left_panel.cpp @@ -6,6 +6,7 @@ #endif #include "ui/theme.h" #include "utils/image_manager.h" +#include "utils/update_manager.h" using namespace ui; @@ -32,6 +33,8 @@ void LeftPanel::init() { 0xFF000000); ImageManager::loadSVG(b::embed<"assets/svg/github.svg">(), "github", 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/download.svg">(), "download", + 0x99FF66B2); ImageManager::loadSVG(b::embed<"assets/svg/settings.svg">(), "settings", 0xFFFFFFFF); ImageManager::loadSVG(b::embed<"assets/svg/settings.svg">(), "settings-black", @@ -112,10 +115,23 @@ void LeftPanel::render() { view_->view == ViewType::Library)) if (view_->view != ViewType::Library) view_->Library(); - ImGui::Dummy( - ImVec2(0, ImGui::GetContentRegionAvail().y - (125.0f * scale_.y))); - // Bottom icons + if (Updater::hasUpdate) { + ImGui::Dummy( + ImVec2(0, ImGui::GetContentRegionAvail().y - (180.0f * scale_.y))); + + if (drawIconButton("Update", ImageManager::get("download"), + ImageManager::get("download"), + ImVec2(30 * scale_.x, 30 * scale_.x), false)) + openURL(Updater::url); + + ImGui::Dummy(ImVec2(0, 30.0f * scale_.y)); + } + else { + ImGui::Dummy( + ImVec2(0, ImGui::GetContentRegionAvail().y - (125.0f * scale_.y))); + } + if (drawIconButton("GitHub", ImageManager::get("github"), ImageManager::get("github"), ImVec2(30 * scale_.x, 30 * scale_.x), false)) diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index e486f56f..8241c48e 100755 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -122,10 +122,9 @@ void SettingsPanel::render() { else Autostart::deleteShortcut(); } - if (addOption("Check for Updates", InputType::Toggle, &checkUpdates_, - true)) { - // saveSettings(); - ImGui::OpenPopup("Coming Soon"); + if (addOption("Check for Updates", InputType::Toggle, &checkUpdates_)) { + saveSettings(); + ImGui::OpenPopup("Restart"); } ImGui::EndGroup(); From dde46752501058511e314d910545da1fc490bc15 Mon Sep 17 00:00:00 2001 From: LegItMate <77503777+LegItMate@users.noreply.github.com> Date: Thu, 25 Jun 2026 20:44:37 +0530 Subject: [PATCH 16/17] fix(misc): Polishing and misc fixes --- include/version.h | 2 +- src/ui/panels/left_panel.cpp | 15 +++++++-------- src/ui/panels/settings.cpp | 3 +-- src/ui/panels/titlebar.cpp | 11 +++++------ 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/include/version.h b/include/version.h index ff639828..68cab6b4 100644 --- a/include/version.h +++ b/include/version.h @@ -1,3 +1,3 @@ #pragma once -#define APP_VERSION "0.1.0" +#define APP_VERSION "0.10.1" diff --git a/src/ui/panels/left_panel.cpp b/src/ui/panels/left_panel.cpp index 26afd8e2..96cccbbe 100644 --- a/src/ui/panels/left_panel.cpp +++ b/src/ui/panels/left_panel.cpp @@ -6,7 +6,7 @@ #endif #include "ui/theme.h" #include "utils/image_manager.h" -#include "utils/update_manager.h" +#include "utils/update_manager.h" using namespace ui; @@ -34,7 +34,7 @@ void LeftPanel::init() { ImageManager::loadSVG(b::embed<"assets/svg/github.svg">(), "github", 0xFFFFFFFF); ImageManager::loadSVG(b::embed<"assets/svg/download.svg">(), "download", - 0x99FF66B2); + 0x99FF66B2); ImageManager::loadSVG(b::embed<"assets/svg/settings.svg">(), "settings", 0xFFFFFFFF); ImageManager::loadSVG(b::embed<"assets/svg/settings.svg">(), "settings-black", @@ -118,18 +118,17 @@ void LeftPanel::render() { // Bottom icons if (Updater::hasUpdate) { ImGui::Dummy( - ImVec2(0, ImGui::GetContentRegionAvail().y - (180.0f * scale_.y))); + ImVec2(0, ImGui::GetContentRegionAvail().y - (180.0f * scale_.y))); if (drawIconButton("Update", ImageManager::get("download"), - ImageManager::get("download"), - ImVec2(30 * scale_.x, 30 * scale_.x), false)) + ImageManager::get("download"), + ImVec2(30 * scale_.x, 30 * scale_.x), false)) openURL(Updater::url); ImGui::Dummy(ImVec2(0, 30.0f * scale_.y)); - } - else { + } else { ImGui::Dummy( - ImVec2(0, ImGui::GetContentRegionAvail().y - (125.0f * scale_.y))); + ImVec2(0, ImGui::GetContentRegionAvail().y - (125.0f * scale_.y))); } if (drawIconButton("GitHub", ImageManager::get("github"), diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index 8241c48e..8977edd8 100755 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -124,7 +124,6 @@ void SettingsPanel::render() { } if (addOption("Check for Updates", InputType::Toggle, &checkUpdates_)) { saveSettings(); - ImGui::OpenPopup("Restart"); } ImGui::EndGroup(); @@ -531,7 +530,7 @@ bool SettingsPanel::NumberBox(const char* id, float* value, float width) { ImGui::PopStyleColor(2); ImGui::PopFont(); - if (ImGui::IsItemDeactivatedAfterEdit()) { + if (ImGui::IsItemDeactivatedAfterEdit() || ImGui::IsItemDeactivated()) { isEditing_ = false; } } diff --git a/src/ui/panels/titlebar.cpp b/src/ui/panels/titlebar.cpp index 71ef657c..118558b0 100644 --- a/src/ui/panels/titlebar.cpp +++ b/src/ui/panels/titlebar.cpp @@ -69,12 +69,11 @@ void Titlebar::render() { glfwSetWindowShouldClose(window, GLFW_TRUE); } ImGui::PopStyleVar(); - } - - if (ImGui::IsWindowHovered() && - ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { - if (!ImGui::IsAnyItemHovered()) { - glfwDragWindow(window); + if (ImGui::IsWindowHovered() && + ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { + if (!ImGui::IsAnyItemHovered()) { + glfwDragWindow(window); + } } } From 96ad93d97ef5210ed064a1fddbe5fba19eb06a29 Mon Sep 17 00:00:00 2001 From: p0ryae Date: Sun, 28 Jun 2026 11:32:34 -0700 Subject: [PATCH 17/17] fix: color picker not showing and improper loadsvg alpha impl --- shell.nix | 3 +++ src/core/utils/image_manager.cpp | 18 ++++++++---------- src/ui/panels/game_panel.cpp | 3 ++- src/ui/panels/settings.cpp | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/shell.nix b/shell.nix index bbc3e134..f7625e4d 100644 --- a/shell.nix +++ b/shell.nix @@ -48,6 +48,9 @@ pkgs.mkShell { qt.qtbase qt.qttools qt.qtwayland + + # GTK Popup + yad ]; # Make Nix store .so files visible to the dynamic linker at runtime diff --git a/src/core/utils/image_manager.cpp b/src/core/utils/image_manager.cpp index 0e1730b4..4699c281 100644 --- a/src/core/utils/image_manager.cpp +++ b/src/core/utils/image_manager.cpp @@ -91,17 +91,15 @@ GLuint ImageManager::loadSVG(b::EmbedInternal::EmbeddedFile embed, auto elements = svg->querySelectorAll("path"); for (auto& element : elements) { - int alpha = (color) & 0xFF; - std::string hexColor; - if (alpha != 0) { - hexColor = "#" + intToHex((color >> 24) & 0xFF) + - intToHex((color >> 16) & 0xFF) + intToHex((color >> 8) & 0xFF); - } else { - hexColor = "#" + intToHex((color >> 16) & 0xFF) + - intToHex((color >> 8) & 0xFF) + intToHex((color) & 0xFF); - } + uint32_t r = (color >> 16) & 0xFF; + uint32_t g = (color >> 8) & 0xFF; + uint32_t b = color & 0xFF; + uint32_t a = (color >> 24) & 0xFF; + + if (a == 0) a = 255; - float opacity = static_cast(alpha) / 255.0f; + std::string hexColor = "#" + intToHex(r) + intToHex(g) + intToHex(b); + float opacity = static_cast(a) / 255.0f; auto fillAttr = element.getAttribute("fill"); if (!fillAttr.empty() && fillAttr != "none") { diff --git a/src/ui/panels/game_panel.cpp b/src/ui/panels/game_panel.cpp index 4e67cc75..8a2a6e66 100644 --- a/src/ui/panels/game_panel.cpp +++ b/src/ui/panels/game_panel.cpp @@ -18,6 +18,7 @@ void GamePanel::init() { ImageManager::loadSVG(b::embed<"assets/svg/heart.svg">(), "heart", 0xFFFFFFFF); + ImageManager::loadSVG(b::embed<"assets/svg/heart2.svg">(), "heart2", Themes::ACCENT_COLOR); ImageManager::loadSVG(b::embed<"assets/svg/heart2-solid.svg">(), @@ -81,7 +82,7 @@ void GamePanel::render() { if (*view_ != ViewType::MainMenu) { ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::PushFont(FontManager::getFont("Nunito-SB"), 17.0f); + ImGui::PushFont(FontManager::getFont("Nunito-SB"), 20.0f); ImGuiStyle& style = ImGui::GetStyle(); ImVec2 oldPadding = style.FramePadding; diff --git a/src/ui/panels/settings.cpp b/src/ui/panels/settings.cpp index 8977edd8..61ac7b3c 100755 --- a/src/ui/panels/settings.cpp +++ b/src/ui/panels/settings.cpp @@ -421,6 +421,7 @@ bool SettingsPanel::ColorBox(const char* id, float color[3], ImVec2 size) { ImDrawList* draw = ImGui::GetWindowDrawList(); ImGui::InvisibleButton(id, size); + bool clicked = ImGui::IsItemClicked(); draw->AddRectFilled( ImVec2(pos.x + 6 * scale_.x, pos.y + 7 * scale_.y), @@ -440,7 +441,7 @@ bool SettingsPanel::ColorBox(const char* id, float color[3], ImVec2 size) { draw->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(162, 162, 162, 104), 4.0f, 0, 1.0f); - if (ImGui::IsItemClicked()) ImGui::OpenPopup(id); + if (clicked) ImGui::OpenPopup(id); bool changed = false; if (ImGui::BeginPopup(id, ImGuiWindowFlags_NoMove)) { @@ -487,7 +488,6 @@ bool SettingsPanel::FilePickerButton(const char* label, const ImVec2& size) { bool SettingsPanel::NumberBox(const char* id, float* value, float width) { ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec2 p = ImGui::GetCursorPos(); ImDrawList* draw = ImGui::GetWindowDrawList(); static char buf[32]; @@ -549,4 +549,4 @@ std::string rgbToHex(int r, int g, int b) { << std::setw(2) << b; return ss.str(); -} \ No newline at end of file +}