-
Notifications
You must be signed in to change notification settings - Fork 1
DevExtensions
Download/Clone this template first then review the details below
ImMobile extension template (Click Here)
void Information() override;
Defines metadata for the extension:
-
name
: The name of the extension (e.g.,"ImmExt"
) -
publisher
: The developer's name (e.g.,"Astifan"
) -
version
: Version string (e.g.,"0.2"
) -
build
: Minimum OS build required (format:major.minor.build.revision
)
There is special variable called
unloadme
, when you set this totrue
the extension will be auto unloaded
To support updating your extension from a remote server:
Imm::App::Extension::Update(url, suggestedName);
- Downloads and schedules the update for next startup
- If the response doesnโt provide a filename, the
suggestedName
will be used - Do not include
.dll
in thesuggestedName
ImMobile provide direct way to grab and download files/extensions
just use
imma:https://.../extName.dll
then a popup will appear to the user
URI call
imma:
can be used in the browser directly
ImMobile will auto start as well if it was closed
Starting from 1.2, ImMobile enabled by default to skip duplicated frames
this may impact your realtime drawing if you're updating image as example
there are many ways to trick the cache and force update like
void ForceImGuiVertexUpdate() {
float t = ImGui::GetTime();
ImU32 color = ImGui::GetColorU32(ImVec4(1, 1, 1, 1));
color ^= (static_cast<int>(t * 1000) & 0xFF);
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec2 p = ImGui::GetCursorScreenPos();
drawList->AddRect(p, ImVec2(p.x + 1, p.y + 1), color);
}
void Initialize(ImmApiProvider* apiProvider) override;
- Called after ImMobile sets up internal fields.
- Use
Imm::
namespace to access ImMobile'sapiProvider
functions.
void Config() override;
- Called after
Initialize()
. - Sets up internal configuration and GUI flags.
- Recommended flags:
flags = ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_SleepFPS | ImGuiWindowFlags_30FPS;
void Register() override;
Use this to register:
-
File types:
Imm::App::Types::RegisterFileType({".xyz"}, "Description", [](std::string path) { Imm::Notify::Success("File received: " + path); });
-
Background intervals:
Imm::Async::RegisterInterval("Label", INTERVAL_ONCE, []() { // Called in background });
This is the most safe in between phase that you can use to initial some stuff you want as well
void Addons() override;
Register UI addon icons with action handlers:
Imm::App::Extension::RegisterAddonItem("ImmExt", ICON_FA_WRENCH, [&]() {
ToggleGUI();
});
void ToggleGUI() override;
Toggles your extension window's visibility using:
Imm::ImGuiEx::Window::FlipState(wd, &visibility);
void Render() override;
This is where your GUI content should be drawn.
Use the recommended window wrapper:
if (Imm::ImGuiEx::Window::Begin(flags)) {
Imm::Debug::DrawTestContent(flags, GetWindowID());
}
Imm::ImGuiEx::Window::End();
you can also register your free draw override
this preffered to be made at Register
not inside render loop
helpful to start draw someting once the extension loaded
apiFunctions.ImDrawOverrideImm(createdExtension, static_cast<int>(ImMobileOverrides::IMM_OVERRIDE_FREEDRAW), [&]() {
// Standalone Preview
if (standalonePreview) {
auto pflags = ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoTitleBar;
if (ImGui::Begin("Lottie Preview###lottie_preview", & standalonePreview, pflags)) {
if (standaloneBringToFront) {
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
}
float size = iconSize * Imm::Screen::Scale();
LottiePreview(size);
ImGui::End();
}
}
});
void Sensors(SensorsDirection direction, bool state) override;
void TouchPad(int port, int code, bool pressed) override;
void TouchPadAnalog(int port, float xAxis, float yAxis) override;
void GamePad(int port, int code, bool pressed) override;
void GamePadAnalog(int port, float xAxisR, float yAxisR, float xAxisL, float yAxisL) override;
void GamePadConnected(int port) override;
void GamePadRemoved(int port) override;
void Rotated(DXGI_MODE_ROTATION orientation) override;
void NetworkChanged(NetworkLevel level, bool wifi) override;
void EnergySaverChanged(SaverStatus status) override;
void BluetoothChanged(BluetoothState state) override;
These are optional unless you're handling custom UI without ImGui:
void PointerPressed(int id, float x, float y, ImPointerType type) override;
void PointerMoved(int id, float x, float y, ImPointerType type) override;
void PointerReleased(int id, float x, float y, ImPointerType type) override;
Input characters don't have custom event in the extension's events
but you can easily capture that via ImGui while rendering
ImGuiIO& io = ImGui::GetIO();
static bool previousKeys[512] = { false };
for (int key = 0; key < IM_ARRAYSIZE(io.KeysDown); ++key) {
// This condition to avoid sending the same key multiple times
if (io.KeysDown[key] != previousKeys[key]) {
}
}
void LaunchURI(std::string uri) override;
Handles custom launch schemes like:
imm:MyValue โ uri = "MyValue"
void Unloading() override;
Called before the extension is unloaded. Clean up your memory, threads, and UI handles here.
~ImmExtension() override;
For practical usage examples and API tests, see the included file:
ImmExtenTemplate.cpp
This template demonstrates how to use the available APIs with real use cases.
You cannot include ImmApiProvider.h
in your .cpp
files directly
as solution I have provided some helpful APIs, storage and log ones specifically at ImmApiProviderBridge.h
the above bridge for CPP
, for C
files use ImmApiProviderBridgeC.h
you can include this file and access to the APIs, if you want more you can simply expose more.
This documentation provides an overview of the available API functions in the Imm
namespace used by ImMobile extensions.
Below you'll find categorized descriptions of function signatures and their expected parameters.
/* CMD */
bool RunCMD(std::string command, bool detached);
std::string RunCMD(std::string command, bool& state, bool detached);
/* INPUT */
bool IsInputPanVisible();
/* HASHING */
std::string Base64Encode(const std::string& in);
std::string Base64Decode(const std::string& in);
std::vector<uint8_t> ComputeSHA256BCrypt(const std::wstring& input);
/* UI */
float GetGlobalProgress();
void ToggleConfigSettingsWindow(const char* windowName, const char* configSection);
bool* GetWindowsVisibiltyPointer(int type); // Related to ImMobileOverrides, nullptr if not supported
/* EXTRA OPTIONS */
void ShowExtraOptions(std::string section);
void AppendExtraOptionsItem(std::string section, std::string item, std::function<void()> onClick);
void AppendExtraOptionsSpr(std::string section);
/* FILES */
void OpenFileWithSupportedApps(std::string file);
void OpenFilesBrowser(); // General use (default files browser behavior)
/* WIN32 / STD */
int fstatUWP(const char* name, struct stat* out); // Resolved internally for UWP access
int removeUWP(const void* name);
int renameUWP(char const* oldFileName, char const* newFileName);
/* IMGUI */
void SaveImGuiConfigs(); // Force direct save, ImMobile only save each 30 second
/* TOUCH */
void KeepInputPaneOpened(); // Use it on demand to keep touch keyboard opened (don't call it constantly)
/* ARCHIVE */
// Helpful when you have object not path (has task by default)
void zipStorageFolder(winrt::Windows::Storage::StorageFolder folder, std::string outputZipPath, std::function<void(bool, std::string)> callback);
Access those directly not through
Imm::
provider.
Imm::Logger::Normal(std::string text);
Imm::Logger::Warn(std::string text);
Imm::Logger::Error(std::string text);
Imm::Logger::Notice(std::string text);
Imm::Logger::Success(std::string text);
Logs messages to the ImMobile extension logger.
It's very important to replace your file stream functions with ImMobile API
ImMobile provide the exact call of the original ones, but they are internally resolved for UWP access
As mentioned you can access them through the bridge file
ImmApiProviderBridge.h
orImmApiProviderBridgeC.h
// Choose file
Imm::Storage::Pickers::ChooseFile(callback, filters = ".*", multiple = false);
// Example
std::string filters = "Image{.jpg,.png,.jpeg},Text{.txt,.ini,.xml},.*";
Imm::Storage::Pickers::ChooseFile([&](const std::vector<PathUWP> files) {
std::string path = files[0].ToString();
Imm::Logger::Normal("Selected file:\n" + path);
}, filters);
// Save file
Imm::Storage::Pickers::SaveFile(callback, suggestedName = "");
// Example
std::string suggestedName = "test.txt";
Imm::Storage::Pickers::SaveFile([&](std::string path) {
Imm::Logger::Normal("File to save:\n" + path);
}, suggestedName);
// Choose folder
Imm::Storage::Pickers::ChooseFolder(callback, multiple = false);
// Example
Imm::Storage::Pickers::ChooseFolder([&](const std::vector<PathUWP> folders) {
std::string path = folders[0].ToString();
Imm::Logger::Normal("Selected folder:\n" + path);
});
File and folder selection dialogs.
Imm::Storage::Locations::InstallationFolder();
Imm::Storage::Locations::InternalIcons(icon);
Imm::Storage::Locations::LocalFolder();
Imm::Storage::Locations::TempFolder();
Imm::Storage::Locations::DataFolder();
Imm::Storage::Locations::MusicFolder();
Imm::Storage::Locations::VideosFolder();
Imm::Storage::Locations::PicturesFolder();
Imm::Storage::Locations::BackupFolder();
Imm::Storage::Locations::ExtensionsFolder();
Imm::Storage::Locations::RuntimesFolder();
Imm::Storage::Locations::DownloadsFolder();
Imm::Storage::Locations::TexturesFolder();
Imm::Storage::Locations::UpdatesFolder();
Imm::Storage::Locations::StartupFolder();
Imm::Storage::Locations::FontsFolder();
Imm::Storage::Locations::TempFilesFolder();
Imm::Storage::Locations::EnvironmentVariables(path);
Imm::Storage::Locations::GetTempFile(name);
Access to system and app-specific folders.
Imm::Storage::Manage::CreateFile(path, accessMode, shareMode, openMode);
Imm::Storage::Manage::CreateFolder(path, replaceExisting = true, skipIfExists = false);
Imm::Storage::Manage::GetFolderContents(path, deepScan = false);
Imm::Storage::Manage::IsExists(path);
Imm::Storage::Manage::IsDirectory(path);
Imm::Storage::Manage::GetSize(path);
Imm::Storage::Manage::Delete(path);
Imm::Storage::Manage::Rename(path, name);
Imm::Storage::Manage::Copy(path, dest, *cancelled = nullptr, *progress = nullptr);
Imm::Storage::Manage::Move(path, dest, *cancelled = nullptr, *progress = nullptr);
Imm::Storage::Manage::CheckPathAccess(path);
Imm::Storage::Manage::CheckDriveAccess(driveName, checkFutureAccess);
Imm::Storage::Manage::GetDriveFreeSpace(path, &space);
Manage files and directories.
for Copy
and Move
(cancelled, progress) can be obtained when you use it inside task
Custom file stream API wrappers:
Imm::Storage::Stream::FileGetStream(path, mode);
Imm::Storage::Stream::FileGetContents(&state, path, mode = "r+", reportIfNotExists = true);
Imm::Storage::Stream::FilePutContents(path, content, backup = false, createnew = false);
Imm::Storage::Stream::FileGetBuffer(path, &outSize);
C-style file operations:
Includes fopen
, fread
, fwrite
, fseek
, fclose
, feof
, ftell
, and moreโall wrapped internally.
It's very important to replace your file stream functions with ImMobile API
ImMobile provide the exact call of the original ones, but they are internally resolved for UWP access
As mentioned you can access them through the bridge file
ImmApiProviderBridge.h
orImmApiProviderBridgeC.h
Imm::Archives::Extract(archive, dest, callback); // Extracts archive to destination
Imm::Archives::Compress(folder, archive, callback); // Compresses folder into archive
Imm::App::Localization::GetLocalString(data);
Imm::App::UI::SetFullModeState(state);
Imm::App::UI::SetGameModeState(state);
Imm::App::UI::ProgressShow(percentage);
Imm::App::UI::ProgressHide();
Imm::App::UI::InvokeGoBack();
Imm::App::UI::CustomBackground(path, scale);
Imm::App::Types::RegisterFileType(extensions, title, onOpen);
Imm::App::Types::GetTypesList(type);
Imm::App::Version::BuildString();
Imm::App::Version::BuildInfo(major, minor, build, revision);
Imm::App::Extension::InvokeCheckUpdates();
Imm::App::Extension::Update(url, suggestedName);
Imm::App::Extension::RegisterAddonItem(label, icon, onClick);
Imm::App::Overrides::TopBarDrawOverride(draw);
Imm::App::Overrides::BottomBarDrawOverride(draw);
Imm::App::Overrides::BackgroundDrawOverride(draw);
Imm::App::Overrides::HomeGridDrawOverride(draw);
Imm::App::Overrides::TouchPadDrawOverride(draw);
Imm::Notify::Info(text, duration);
Imm::Notify::Success(text, duration);
Imm::Notify::Warn(text, duration);
Imm::Notify::Error(text, duration);
Imm::Clipboard::Read();
Imm::Clipboard::Set(data);
Imm::Launch::URI(uri);
Imm::Launch::File(file);
Imm::Launch::Folder(folder);
Imm::DirectX::Texture::RequestCached(path, maxSize, outInfo, preferThumbnail, thumbnailMode);
Imm::DirectX::Texture::RequestCachedByURL(url, maxSize, outInfo, preferThumbnail, thumbnailMode);
Imm::DirectX::Texture::LoadFromFile(filename, maxSize, out_srv, out_width, out_height);
Imm::DirectX::Texture::GetThumbnail(path, outTextureView, out_width, out_height, mode);
Imm::DirectX::Texture::ReleaseTexture(texture);
Imm::DirectX::Texture::ImageSize(path, out_width, out_height);
Imm::DirectX::Texture::LoadDecodedBitmap(path, maxSize, outTextureView, out_width, out_height, format, alpha);
Imm::DirectX::Context::D3DDevice();
Imm::DirectX::Context::D3DContext();
Imm::DirectX::Context::RenderTargetView();
Imm::DirectX::Context::SwapChain();
Imm::DirectX::Context::Texture2D();
Imm::DirectX::Shader::CompileFromFile(szFileName, szEntryPoint, szShaderModel, ppBlobOut);
Imm::DirectX::Shader::LoadCompiledFromFile(filename);
Imm::DirectX::Shader::Level();
Imm::DirectX::Shader::VertexShaderModel();
Imm::DirectX::Shader::PixelShaderModel();
Imm::DirectX::Shader::LevelString();
// ๐ฒ Begin and end ImMobile window container
Imm::ImGuiEx::Window::Begin(flags);
Imm::ImGuiEx::Window::End();
// ๐ File browser state
Imm::ImGuiEx::Window::IsFileBrowserOpened();
// ๐ Toggle or close specific windows by name
Imm::ImGuiEx::Window::FlipState(name, target_state_bool);
Imm::ImGuiEx::Window::CloseByName(name, afterClose);
// ๐ Check if minimized to avoid unwanted toggles
Imm::ImGuiEx::Window::IsMinimized(name);
// ๐ ๏ธ Add layout and flags options to menus
Imm::ImGuiEx::Window::AddLayoutMenuItems(flags);
Imm::ImGuiEx::Window::DrawWindowMenuBar(target_pointer, flags);
// ๐ Close window on back press (mobile UX)
Imm::ImGuiEx::Window::CheckBackPressedAndClose(toggle);
// ๐ค Centered text block, useful for splash messages or UIs
Imm::ImGuiEx::Elements::TextCentered(text, offsetx, offsety);
// ๐ก InputText with edit popup and custom keyboard support
Imm::ImGuiEx::Elements::InputText(label, buffer, size, flags, keyboard);
// ๐ผ๏ธ Load and render cached images with thumbnail fallback
Imm::ImGuiEx::Elements::Image(path, outInfo, renderSize, maxSize, preferThumbnail, thumbnailMode);
// ๐งฟ Render internal ImMobile icon by name
Imm::ImGuiEx::Elements::Icon(icon, outInfo, renderSize, maxSize, preferThumbnail, thumbnailMode);
// โก Simplified Icon overload for quick use
Imm::ImGuiEx::Elements::Icon(icon, renderSize, maxSize, preferThumbnail, thumbnailMode);
// ๐ Auto-download and render image by URL
Imm::ImGuiEx::Elements::ImageByURL(url, outInfo, renderSize, maxSize, preferThumbnail, thumbnailMode);
// ๐ Custom notification bar with icon and optional click
Imm::ImGuiEx::Elements::Notice(text, icon, backColor, padding, onClick);
// ๐ Horizontal, vertical or full centering
Imm::ImGuiEx::Position::CenterItemX(width, offset);
Imm::ImGuiEx::Position::CenterItemY(height, offset);
Imm::ImGuiEx::Position::CenterItem(width, height, offsetx, offsety);
Imm::Pointer::PointerPos(); // Get full pointer/touch position (ImVec2)
Imm::Pointer::PointerX(); // Pointer X coordinate only
Imm::Pointer::PointerY(); // Pointer Y coordinate only
Imm::Pointer::IsPointReleased(); // True if pointer/touch was just released
Imm::Pointer::IsOnePointDetected(); // Single-touch detected (tap/drag)
Imm::Pointer::IsTwoPointsDetected(); // Multi-touch (two fingers) detected
Imm::Pointer::IsZoomBehaviorDetected(); // Zoom gesture behavior detected (pinch)
Imm::Pointer::IsDoubleClickBehaviorDetected(); // Double-tap detected (resets after call)
Imm::Pointer::SetScrollResolverState(state); // Control scroll/touch resolution (e.g., ImPlot zooming)
Imm::Pointer::IgnoreTouchEvent(ignoreReleaseState, ignoreUICheck); // Suppress UI or release-based touch handling
Imm::Pointer::IsPointInButton(point, buttonPos, buttonSize); // Check if point is inside a rectangle (e.g., UI button)
Imm::Pointer::IsPointInCircle(point, center, radius); // Check if point is inside a circle (e.g., joystick/touchpad)
Imm::Packages::Install(package);
Imm::Packages::Register(manifest);
Imm::Packages::Remove(id);
Install, register, and remove Windows App packages.
Imm::Dialogs::Input(title, text, onClose, inputRequired = false);
Imm::Dialogs::Input(title, text, value, onClose, inputRequired = false);
Imm::Dialogs::Notice(title, text, onDontShowAgain, onClose);
Imm::Dialogs::Confirm(title, message, callback);
Imm::Dialogs::Confirm(title, drawFn, callback);
Display confirmation, input, and notice dialogs.
Imm::Device::OS::Notification(title, message);
Imm::Device::OS::BuildString();
Imm::Device::OS::BuildInfo(&major, &minor, &build, &revision);
Imm::Device::Hardware::BatteryLevel();
Imm::Device::Hardware::TotalRAM();
Imm::Device::Hardware::AvailableRAM();
Imm::Device::Hardware::BluetoothState();
Imm::Device::Hardware::BatterySaverState();
Imm::Device::Hardware::WiFiState();
Imm::Device::Hardware::ToggleBluetooth(state);
Imm::Device::Type::IsMobile();
Imm::Device::Type::IsXBox();
Imm::Device::Type::DeviceFamily();
Imm::Online::IsOnline();
Imm::Online::GetFileName(url, defaultName, headers);
Imm::Online::GetResponseHeader(url, defaultName, headers, accept, notifications);
Imm::Online::QuickDownload(url, file, fullPath, httpClient, showNotifications, headers);
Imm::Online::GetResponse(url, accept, headers, notifyError);
Imm::Online::DownloadResponse(url, filePath, accept, headers, notifyError);
Imm::Online::GetDefaultDownloadClient();
Imm::GitHub::GetContents(user, repo, subPath, &output, accept, headers);
Imm::GitHub::GetLatestRelease(user, repo, &output, accept, headers);
Imm::GitHub::ShowReleasesUI(url, token);
Imm::GitHub::ShowContentsUI(url, subPath, token);
Imm::GitHub::ShowReadMeUI(url, token);
Imm::JSRuntime::LoadJSFile(file, callback, window = false, confirmation = false);
Imm::JSRuntime::Execute(jsID, script);
Imm::JSRuntime::Reset(jsID);
Imm::JSRuntime::Reload(jsID);
Imm::JSRuntime::Remove(jsID);
Imm::JSRuntime::IsLoaded(jsID);
Imm::Async::WaitFor(&state);
Imm::Async::AddTask(title, type, callback);
Imm::Async::RegisterInterval(title, type, callback);
Grouped under:
Imm::Utils::String
Imm::Utils::List
Imm::Utils::Colors
Imm::Utils::Time
Each includes common helper functions such as string manipulation, color conversions, formatting utilities, etc.
Imm::Screen::Width(); // Screen width in pixels
Imm::Screen::Height(); // Screen height in pixels
Imm::Screen::Scale(); // UI scaling factor (useful for resolution-independent sizing)
Imm::Screen::FontScale(); // Font scaling based on DPI / user settings
Imm::Screen::DPI(); // Device DPI (dots per inch)
Imm::Screen::BottomBarSize(); // Height of the bottom navigation bar (if any)
Imm::Screen::TopBarSize(); // Height of the top bar (if any)
Imm::Screen::MinButtonWidth(); // Minimum recommended button width (responsive design helper)
Imm::Screen::IsLandScape(); // True if device is in landscape orientation
Imm::Audio::SoundTrack::Play(path); // Play audio file (streamed)
Imm::Audio::SoundTrack::Pause(path); // Pause audio playback
Imm::Audio::SoundTrack::Resume(path); // Resume paused audio
Imm::Audio::SoundTrack::Seek(path, seconds); // Seek to time position
Imm::Audio::SoundTrack::Stop(path); // Stop specific track
Imm::Audio::SoundTrack::StopAll(); // Stop all playing tracks
Imm::Audio::SoundTrack::GetCurrentPosition(path);// Get current playback position
Imm::Audio::SoundTrack::GetTotalDuration(path); // Get total length of the track
Imm::Audio::SoundTrack::GetRemainingTime(path); // Time left in track
Imm::Audio::SoundTrack::ClearCache(path); // Clear cache for a specific track
Imm::Audio::SoundTrack::ClearCacheAll(); // Clear all audio caches
Imm::Audio::SoundEffect::Play(sfx); // Play built-in UI sound effect (default: click)
Imm::Audio::SoundEffect::Play(path); // Play custom SFX by path
Imm::Audio::SoundEffect::Stop(path); // Stop specific SFX
Imm::Audio::SoundEffect::StopAll(); // Stop all sound effects
Imm::Audio::SoundEffect::ClearCache(path); // Clear cache for one SFX
Imm::Audio::SoundEffect::ClearCacheAll(); // Clear all SFX caches
Imm::Config::SaveString(key, value);
Imm::Config::GetString(key, def);
Imm::Config::SaveInt(key, value);
Imm::Config::GetInt(key, def);
Imm::Config::SaveBool(key, value);
Imm::Config::GetBool(key, def);
Imm::Config::SaveFloat(key, value);
Imm::Config::GetFloat(key, def);
Imm::Config::SaveDouble(key, value);
Imm::Config::GetDouble(key, def);
Imm::Config::SaveImVec2(key, value);
Imm::Config::GetImVec2(key, def);
Imm::Config::SaveImVec4(key, value);
Imm::Config::GetImVec4(key, def);
More may avaialble in the official template,
follow the same construct way I used to inspect them,
also more details added to the functions inside the template.