Initial code for using winrt headers
This commit is contained in:
parent
915dd4c738
commit
95051d304a
|
@ -1,7 +1,4 @@
|
||||||
set(GETTEXT_PACKAGE "dino-windows-notifications")
|
project(windows-notification)
|
||||||
find_package(Gettext)
|
|
||||||
include(${GETTEXT_USE_FILE})
|
|
||||||
gettext_compile(${GETTEXT_PACKAGE} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../main/po TARGET_NAME ${GETTEXT_PACKAGE}-translations)
|
|
||||||
|
|
||||||
find_packages(WINDOWS_NOTIFICATION_PACKAGES REQUIRED
|
find_packages(WINDOWS_NOTIFICATION_PACKAGES REQUIRED
|
||||||
Gee
|
Gee
|
||||||
|
@ -15,55 +12,54 @@ vala_precompile(WINDOWS_NOTIFICATION_VALA_C
|
||||||
SOURCES
|
SOURCES
|
||||||
src/plugin.vala
|
src/plugin.vala
|
||||||
src/register_plugin.vala
|
src/register_plugin.vala
|
||||||
src/win_notification_provider.vala
|
|
||||||
CUSTOM_VAPIS
|
CUSTOM_VAPIS
|
||||||
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
||||||
${CMAKE_BINARY_DIR}/exports/dino.vapi
|
${CMAKE_BINARY_DIR}/exports/dino.vapi
|
||||||
${CMAKE_BINARY_DIR}/exports/qlite.vapi
|
${CMAKE_BINARY_DIR}/exports/qlite.vapi
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vapi/DinoWinToastLib.vapi
|
${CMAKE_CURRENT_SOURCE_DIR}/vapi/win32.vapi
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vapi/DinoWinToastTemplate.vapi
|
${CMAKE_CURRENT_SOURCE_DIR}/vapi/shortcutcreator.vapi
|
||||||
PACKAGES
|
PACKAGES
|
||||||
${WINDOWS_NOTIFICATION_PACKAGES}
|
${WINDOWS_NOTIFICATION_PACKAGES}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/exports/DinoWinToastLib.h"
|
set(WINDOWS_API_SOURCES
|
||||||
COMMAND
|
${CMAKE_CURRENT_SOURCE_DIR}/api/src/win32.cpp
|
||||||
cp "${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastLib.h" "${CMAKE_BINARY_DIR}/exports/DinoWinToastLib.h"
|
${CMAKE_CURRENT_SOURCE_DIR}/api/src/converter.cpp
|
||||||
DEPENDS
|
${CMAKE_CURRENT_SOURCE_DIR}/api/src/shortcutcreator.cpp
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastLib.h"
|
|
||||||
COMMENT
|
|
||||||
Copy header file DinoWinToastLib.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/exports/DinoWinToastTemplate.h"
|
add_library(windows-notification SHARED ${WINDOWS_NOTIFICATION_VALA_C} ${WINDOWS_API_SOURCES})
|
||||||
COMMAND
|
|
||||||
cp "${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastTemplate.h" "${CMAKE_BINARY_DIR}/exports/DinoWinToastTemplate.h"
|
target_include_directories(windows-notification
|
||||||
DEPENDS
|
PRIVATE
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastTemplate.h"
|
${PROJECT_SOURCE_DIR}/api/include
|
||||||
COMMENT
|
|
||||||
Copy header file DinoWinToastTemplate.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/exports/DinoWinToastDllExport.h"
|
find_library(shlwapi_LIBRARY shlwapi libshlwapi libshlwapi.a HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
|
||||||
COMMAND
|
if(NOT shlwapi_LIBRARY)
|
||||||
cp "${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastDllExport.h" "${CMAKE_BINARY_DIR}/exports/DinoWinToastDllExport.h"
|
message(FATAL_ERROR "shlwapi library not found")
|
||||||
DEPENDS
|
endif(NOT shlwapi_LIBRARY)
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastDllExport.h"
|
|
||||||
COMMENT
|
|
||||||
Copy header file DinoWinToastDllExport.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_definitions(${VALA_CFLAGS} -DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\" -DLOCALE_INSTALL_DIR=\"${LOCALE_INSTALL_DIR}\")
|
find_library(propsys_LIBRARY propsys libpropsys libpropsys.a HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
|
||||||
add_library(windows-notification SHARED ${WINDOWS_NOTIFICATION_VALA_C} ${CMAKE_BINARY_DIR}/exports/DinoWinToastLib.h ${CMAKE_BINARY_DIR}/exports/DinoWinToastTemplate.h ${CMAKE_BINARY_DIR}/exports/DinoWinToastDllExport.h)
|
if(NOT propsys_LIBRARY)
|
||||||
add_dependencies(omemo ${GETTEXT_PACKAGE}-translations)
|
message(FATAL_ERROR "propsys library not found")
|
||||||
|
endif(NOT propsys_LIBRARY)
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
find_library(ntdll_LIBRARY ntdll libntdll libntdll.a HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
|
||||||
set(WINTOASTLIB "${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastLib_AMD64.lib")
|
if(NOT ntdll_LIBRARY)
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
message(FATAL_ERROR "ntdll library not found")
|
||||||
set(WINTOASTLIB "${CMAKE_CURRENT_SOURCE_DIR}/src/DinoWinToastLib_x86.lib")
|
endif(NOT ntdll_LIBRARY)
|
||||||
endif()
|
|
||||||
|
find_library(mincore_LIBRARY mincore libmincore libmincore.a HINTS ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
|
||||||
|
if(NOT mincore_LIBRARY)
|
||||||
|
message(FATAL_ERROR "mincore library not found")
|
||||||
|
endif(NOT mincore_LIBRARY)
|
||||||
|
|
||||||
|
target_link_libraries(windows-notification libdino ${shlwapi_LIBRARY} ${propsys_LIBRARY} ${ntdll_LIBRARY} ${mincore_LIBRARY} ${WINDOWS_NOTIFICATION_PACKAGES})
|
||||||
|
target_compile_features(windows-notification PRIVATE cxx_std_20)
|
||||||
|
# target_compile_options(windows-notification PRIVATE -municode -DUNICODE -fcoroutines -iquote ../../include/winrt/yolort_impl)
|
||||||
|
target_compile_options(windows-notification PRIVATE -municode -DUNICODE -fcoroutines)
|
||||||
|
|
||||||
target_link_libraries(windows-notification libdino ${WINDOWS_NOTIFICATION_PACKAGES} ${WINTOASTLIB})
|
|
||||||
set_target_properties(windows-notification PROPERTIES PREFIX "")
|
set_target_properties(windows-notification PROPERTIES PREFIX "")
|
||||||
set_target_properties(windows-notification PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins/)
|
set_target_properties(windows-notification PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins/)
|
||||||
|
|
||||||
|
|
18
plugins/windows-notification/api/include/ComPtr.hpp
Normal file
18
plugins/windows-notification/api/include/ComPtr.hpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct ComPtr
|
||||||
|
{
|
||||||
|
T *p{};
|
||||||
|
|
||||||
|
~ComPtr() { if (p != nullptr) p->Release(); }
|
||||||
|
|
||||||
|
T &operator*() const { return *p; }
|
||||||
|
T **operator&() const { return &p; }
|
||||||
|
T **operator&() { return &p; }
|
||||||
|
T *operator->() const { return p; }
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
HRESULT As( U **const pp ) const
|
||||||
|
{ return p->QueryInterface(pp); }
|
||||||
|
};
|
7
plugins/windows-notification/api/include/converter.hpp
Normal file
7
plugins/windows-notification/api/include/converter.hpp
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::wstring char_to_wstr(const gchar* str);
|
||||||
|
char* wstr_to_char(const std::wstring& wstr);
|
14
plugins/windows-notification/api/include/shortcutcreator.h
Normal file
14
plugins/windows-notification/api/include/shortcutcreator.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gboolean TryCreateShortcut(gchar* aumid);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
1
plugins/windows-notification/api/include/win32.h
Normal file
1
plugins/windows-notification/api/include/win32.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "win32.hpp"
|
25
plugins/windows-notification/api/include/win32.hpp
Normal file
25
plugins/windows-notification/api/include/win32.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
std::optional<std::wstring> GetCurrentModulePath();
|
||||||
|
std::optional<std::wstring> GetShortcutPath();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
gboolean SupportsModernNotifications();
|
||||||
|
gboolean SetAppModelID(gchar* aumid);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
14
plugins/windows-notification/api/include/winrt.h
Normal file
14
plugins/windows-notification/api/include/winrt.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gboolean Initialize();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
53
plugins/windows-notification/api/src/converter.cpp
Normal file
53
plugins/windows-notification/api/src/converter.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include <stringapiset.h>
|
||||||
|
|
||||||
|
#include "converter.hpp"
|
||||||
|
|
||||||
|
// Convert a wide Unicode string to an UTF8 string
|
||||||
|
std::string wstr_to_str(const std::wstring& wstr)
|
||||||
|
{
|
||||||
|
if(wstr.empty())
|
||||||
|
{
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
int final_size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
|
||||||
|
std::string strTo(final_size, 0);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), strTo.data(), final_size, nullptr, nullptr);
|
||||||
|
return strTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* wstr_to_char(const std::wstring& wstr)
|
||||||
|
{
|
||||||
|
if(wstr.empty())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int final_size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
|
||||||
|
char* strTo = new char[final_size];
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), strTo, final_size, nullptr, nullptr);
|
||||||
|
return strTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert an UTF8 string to a wide Unicode String
|
||||||
|
std::wstring std_to_wstr(const std::string &str)
|
||||||
|
{
|
||||||
|
if(str.empty())
|
||||||
|
{
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
int final_size = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0);
|
||||||
|
std::wstring wstrTo(final_size, 0);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), wstrTo.data(), final_size);
|
||||||
|
return wstrTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring char_to_wstr(const char* str) // TODO: how to be safe from non-null terminated strings?
|
||||||
|
{
|
||||||
|
if(str == nullptr)
|
||||||
|
{
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
int final_size = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), nullptr, 0);
|
||||||
|
std::wstring wstrTo(final_size, 0);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), wstrTo.data(), final_size);
|
||||||
|
return wstrTo;
|
||||||
|
}
|
160
plugins/windows-notification/api/src/shortcutcreator.cpp
Normal file
160
plugins/windows-notification/api/src/shortcutcreator.cpp
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "shortcutcreator.h"
|
||||||
|
#include "win32.hpp"
|
||||||
|
#include "converter.hpp"
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define _UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <tchar.h> // magic
|
||||||
|
#include <objbase.h> // COM stuff
|
||||||
|
#include <shlobj.h> // IShellLink
|
||||||
|
#include <propvarutil.h> // InitPropVariantFromString
|
||||||
|
#include <propkey.h> // PKEY_AppUserModel_ID
|
||||||
|
#include <cstdio> // 'cause iostreams are bloat
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "ComPtr.hpp"
|
||||||
|
|
||||||
|
// Not available in MINGW headers for some reason
|
||||||
|
PSSTDAPI PropVariantToString(_In_ REFPROPVARIANT propvar, _Out_writes_(cch) PWSTR psz, _In_ UINT cch);
|
||||||
|
|
||||||
|
int32_t InstallShortcut(const std::wstring& exe_path, const std::wstring& aumid, const std::wstring& shortcut_path)
|
||||||
|
{
|
||||||
|
ComPtr<IShellLink> shellLink;
|
||||||
|
auto hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = shellLink->SetPath(exe_path.c_str());
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = shellLink->SetArguments(TEXT(""));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = shellLink->SetWorkingDirectory(exe_path.c_str());
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IPropertyStore> propertyStore;
|
||||||
|
hr = shellLink.As(&propertyStore);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PROPVARIANT appIdPropVar;
|
||||||
|
hr = InitPropVariantFromString(aumid.c_str(), &appIdPropVar);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = propertyStore->Commit();
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IPersistFile> persistFile;
|
||||||
|
hr = shellLink.As(&persistFile);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = persistFile->Save(shortcut_path.c_str(), TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropVariantClear(&appIdPropVar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ValidateShortcut(const std::wstring& shortcut_path, const std::wstring& currentAumid)
|
||||||
|
{
|
||||||
|
bool wasChanged = false;
|
||||||
|
|
||||||
|
ComPtr<IShellLink> shellLink;
|
||||||
|
auto hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IPersistFile> persistFile;
|
||||||
|
hr = shellLink.As(&persistFile);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = persistFile->Load(shortcut_path.c_str(), STGM_READWRITE);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IPropertyStore> propertyStore;
|
||||||
|
hr = shellLink.As(&propertyStore);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
PROPVARIANT appIdPropVar;
|
||||||
|
hr = propertyStore->GetValue(PKEY_AppUserModel_ID, &appIdPropVar);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
std::array<wchar_t, MAX_PATH> AUMI;
|
||||||
|
hr = PropVariantToString(appIdPropVar, AUMI.data(), AUMI.size());
|
||||||
|
if (FAILED(hr) || currentAumid != std::wstring(AUMI.data()))
|
||||||
|
{
|
||||||
|
// AUMI Changed for the same app, let's update the current value! =)
|
||||||
|
wasChanged = true;
|
||||||
|
PropVariantClear(&appIdPropVar);
|
||||||
|
hr = InitPropVariantFromString(currentAumid.c_str(), &appIdPropVar);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = propertyStore->Commit();
|
||||||
|
if (SUCCEEDED(hr) && SUCCEEDED(persistFile->IsDirty()))
|
||||||
|
{
|
||||||
|
hr = persistFile->Save(shortcut_path.c_str(), TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropVariantClear(&appIdPropVar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t TryCreateShortcutInternal(const std::wstring& aumid)
|
||||||
|
{
|
||||||
|
auto exePath = GetCurrentModulePath();
|
||||||
|
auto shortcutPath = GetShortcutPath();
|
||||||
|
|
||||||
|
if (shortcutPath && exePath)
|
||||||
|
{
|
||||||
|
auto path = shortcutPath.value() + LR"(\Microsoft\Windows\Start Menu\Programs\Testando.lnk)";
|
||||||
|
if (!std::filesystem::exists(path))
|
||||||
|
{
|
||||||
|
return InstallShortcut(exePath.value(), aumid, path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ValidateShortcut(path, aumid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
gboolean TryCreateShortcut(gchar* aumid)
|
||||||
|
{
|
||||||
|
auto result = char_to_wstr(aumid);
|
||||||
|
if (result.empty())
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return SUCCEEDED(TryCreateShortcutInternal(result));
|
||||||
|
}
|
||||||
|
}
|
60
plugins/windows-notification/api/src/win32.cpp
Normal file
60
plugins/windows-notification/api/src/win32.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
|
#include "win32.hpp"
|
||||||
|
#include "converter.hpp"
|
||||||
|
|
||||||
|
std::optional<std::wstring> GetCurrentModulePath()
|
||||||
|
{
|
||||||
|
std::array<wchar_t, MAX_PATH> exePath;
|
||||||
|
auto charWritten = GetModuleFileName(nullptr, exePath.data(), exePath.size());
|
||||||
|
if (charWritten > 0)
|
||||||
|
{
|
||||||
|
return std::wstring(exePath.data());
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::wstring> GetShortcutPath()
|
||||||
|
{
|
||||||
|
std::array<wchar_t, MAX_PATH> shortcutPath;
|
||||||
|
auto charWritten = GetEnvironmentVariable(L"APPDATA", shortcutPath.data(), shortcutPath.size());
|
||||||
|
if (charWritten > 0)
|
||||||
|
{
|
||||||
|
return std::wstring(shortcutPath.data());
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetAppModelIDInternal(const std::wstring& aumid)
|
||||||
|
{
|
||||||
|
return SUCCEEDED(SetCurrentProcessExplicitAppUserModelID(aumid.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
// Not available in mingw headers, but linking works.
|
||||||
|
NTSTATUS NTAPI RtlGetVersion(PRTL_OSVERSIONINFOW);
|
||||||
|
|
||||||
|
gboolean SupportsModernNotifications()
|
||||||
|
{
|
||||||
|
RTL_OSVERSIONINFOW rovi = { 0 };
|
||||||
|
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
||||||
|
if (S_OK == RtlGetVersion(&rovi))
|
||||||
|
{
|
||||||
|
return rovi.dwMajorVersion > 6;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean SetAppModelID(gchar* aumid)
|
||||||
|
{
|
||||||
|
auto result = char_to_wstr(aumid);
|
||||||
|
if (result.empty())
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return SetAppModelIDInternal(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
plugins/windows-notification/api/src/winrt.cpp
Normal file
2
plugins/windows-notification/api/src/winrt.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#include "winrt.h"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,14 +1,29 @@
|
||||||
using Gee;
|
using Gee;
|
||||||
using Dino.Entities;
|
using Dino.Entities;
|
||||||
|
using Win32Api;
|
||||||
|
using ShortcutCreator;
|
||||||
|
|
||||||
namespace Dino.Plugins.WindowsNotification {
|
namespace Dino.Plugins.WindowsNotification {
|
||||||
public class Plugin : RootInterface, Object {
|
public class Plugin : RootInterface, Object {
|
||||||
|
|
||||||
public void registered(Dino.Application app) {
|
public void registered(Dino.Application app) {
|
||||||
var provider = WindowsNotificationProvider.try_create(app);
|
var created = ShortcutCreator.TryCreateShortcut("org.dino.Dino");
|
||||||
if (provider != null) {
|
if (!created)
|
||||||
app.stream_interactor.get_module(NotificationEvents.IDENTITY).register_notification_provider(provider);
|
{
|
||||||
|
// log somewhere, return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var initialized =
|
||||||
|
|
||||||
|
if (!Win32Api.SupportsModernNotifications())
|
||||||
|
{
|
||||||
|
// limit types of notifications on template builder
|
||||||
|
}
|
||||||
|
|
||||||
|
// var provider = WindowsNotificationProvider.try_create(app);
|
||||||
|
// if (provider != null) {
|
||||||
|
// app.stream_interactor.get_module(NotificationEvents.IDENTITY).register_notification_provider(provider);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
[CCode (cheader_filename = "DinoWinToastLib.h")]
|
|
||||||
namespace DinoWinToast {
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_Notification_Reason", cprefix = "Reason_")]
|
|
||||||
public enum Reason {
|
|
||||||
Activated,
|
|
||||||
ApplicationHidden,
|
|
||||||
TimedOut
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_Notification_Callback_Simple", has_target = true)]
|
|
||||||
public delegate void NotificationCallbackSimple();
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_Notification_Callback_ActivatedWithActionIndex", has_target = true)]
|
|
||||||
public delegate void NotificationCallbackWithActionIndex(int actionId);
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_Notification_Callback_Dismissed", has_target = true)]
|
|
||||||
public delegate void NotificationCallbackDismissed(Reason reason);
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_Notification_Callbacks", free_function = "dinoWinToastLib_DestroyCallbacks")]
|
|
||||||
[Compact]
|
|
||||||
public class Callbacks {
|
|
||||||
[CCode (delegate_target_cname = "activated_context", destroy_notify_cname = "activated_free")]
|
|
||||||
public NotificationCallbackSimple activated;
|
|
||||||
|
|
||||||
[CCode (delegate_target_cname = "activatedWithIndex_context", destroy_notify_cname = "activatedWithIndex_free")]
|
|
||||||
public NotificationCallbackWithActionIndex activatedWithIndex;
|
|
||||||
|
|
||||||
[CCode (delegate_target_cname = "dismissed_context", destroy_notify_cname = "dismissed_free")]
|
|
||||||
public NotificationCallbackDismissed dismissed;
|
|
||||||
|
|
||||||
[CCode (delegate_target_cname = "failed_context", destroy_notify_cname = "failed_free")]
|
|
||||||
public NotificationCallbackSimple failed;
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_NewCallbacks")]
|
|
||||||
public Callbacks();
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_Init")]
|
|
||||||
public int Init();
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_ShowMessage")]
|
|
||||||
public int64 ShowMessage(DinoWinToastTemplate templ, Callbacks callbacks);
|
|
||||||
|
|
||||||
[CCode (cname = "dinoWinToastLib_RemoveNotification")]
|
|
||||||
public bool RemoveNotification(int64 notification_id);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
[CCode (cheader_filename = "DinoWinToastTemplate.h")]
|
|
||||||
namespace DinoWinToast {
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_duration", cprefix = "Duration_")]
|
|
||||||
public enum Duration {
|
|
||||||
System,
|
|
||||||
Short,
|
|
||||||
Long
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_audiooption", cprefix = "AudioOption_")]
|
|
||||||
public enum AudioOption {
|
|
||||||
Default,
|
|
||||||
Silent,
|
|
||||||
Loop
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_textfield", cprefix = "TextField_")]
|
|
||||||
public enum TextField {
|
|
||||||
FirstLine,
|
|
||||||
SecondLine,
|
|
||||||
ThirdLine
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_wintoasttemplatetype", cprefix = "TemplateType_")]
|
|
||||||
public enum TemplateType {
|
|
||||||
ImageAndText01,
|
|
||||||
ImageAndText02,
|
|
||||||
ImageAndText03,
|
|
||||||
ImageAndText04,
|
|
||||||
Text01,
|
|
||||||
Text02,
|
|
||||||
Text03,
|
|
||||||
Text04,
|
|
||||||
WinToastTemplateTypeCount
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname="dino_wintoasttemplate", free_function = "dino_wintoasttemplate_destroy")]
|
|
||||||
[Compact]
|
|
||||||
public class DinoWinToastTemplate {
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_new")]
|
|
||||||
public DinoWinToastTemplate(TemplateType type = TemplateType.ImageAndText02);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_setTextField")]
|
|
||||||
public void setTextField(char* txt, TextField pos);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_setImagePath")]
|
|
||||||
public void setImagePath(char* imgPath);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_setAttributionText")]
|
|
||||||
public void setAttributionText(char* attributionText);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_addAction")]
|
|
||||||
public void addAction(char* label);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_setAudioOption")]
|
|
||||||
public void setAudioOption(AudioOption option);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_setDuration")]
|
|
||||||
public void setDuration(Duration duration);
|
|
||||||
|
|
||||||
[CCode (cname = "dino_wintoasttemplate_setExpiration")]
|
|
||||||
public void setExpiration(int64 millisecondsFromNow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
5
plugins/windows-notification/vapi/shortcutcreator.vapi
Normal file
5
plugins/windows-notification/vapi/shortcutcreator.vapi
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[CCode (cheader_filename = "shortcutcreator.h")]
|
||||||
|
namespace ShortcutCreator {
|
||||||
|
[CCode (cname = "TryCreateShortcut")]
|
||||||
|
public bool TryCreateShortcut(string aumid);
|
||||||
|
}
|
6
plugins/windows-notification/vapi/win32.vapi
Normal file
6
plugins/windows-notification/vapi/win32.vapi
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[CCode (cheader_filename = "win32.h")]
|
||||||
|
namespace Win32Api {
|
||||||
|
[CCode (cname = "SupportsModernNotifications")]
|
||||||
|
public bool SupportsModernNotifications();
|
||||||
|
}
|
||||||
|
|
5
plugins/windows-notification/vapi/winrt.vapi
Normal file
5
plugins/windows-notification/vapi/winrt.vapi
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[CCode (cheader_filename = "winrt.h")]
|
||||||
|
namespace WinRTApi {
|
||||||
|
[CCode (cname = "Initialize")]
|
||||||
|
public bool Initialize();
|
||||||
|
}
|
Loading…
Reference in a new issue