Compare commits
14 commits
feature/ta
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d8d9166fb | ||
|
|
f0d71308ec | ||
|
|
8f29187a67 | ||
|
|
602ca05732 | ||
|
|
639a82fc0e | ||
|
|
eb9ff6eef2 | ||
|
|
0117fe56a0 | ||
|
|
f59988bb55 | ||
|
|
a9f781b289 | ||
|
|
44b3ffb2b7 | ||
|
|
762d13f4a4 | ||
|
|
a114a41e18 | ||
|
|
1b1ab615e7 | ||
|
|
3e13e29af5 |
18 changed files with 1602 additions and 400 deletions
262
.github/workflows/photino.Native.Development.yml
vendored
Normal file
262
.github/workflows/photino.Native.Development.yml
vendored
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
name: Build Photino.Native
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
buildConfiguration: Release
|
||||
MAJOR: 4
|
||||
MINOR: 0
|
||||
# Note: PATCH below is set per-job in "PublishPackage" using github.run_number
|
||||
|
||||
jobs:
|
||||
Publish_Nuspec:
|
||||
name: Publish .nuspec
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Upload .nuspec artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: .nuspec
|
||||
path: ./Photino.Native/Photino.Native.nuspec
|
||||
|
||||
Build_Win_x64:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup NuGet
|
||||
uses: NuGet/setup-nuget@v2
|
||||
|
||||
- name: Restore (Windows x64)
|
||||
run: nuget restore Photino.Native.sln -NonInteractive
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
- name: Build (Windows x64)
|
||||
run: >
|
||||
msbuild ./Photino.Native/Photino.Native.vcxproj
|
||||
/p:Configuration=${{ env.buildConfiguration }}
|
||||
/p:Platform=x64
|
||||
|
||||
- name: Upload Windows x64 libs
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: photino.Native-Windows-x64
|
||||
path: ./Photino.Native/x64/${{ env.buildConfiguration }}
|
||||
|
||||
Build_Win_Arm64:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup NuGet
|
||||
uses: NuGet/setup-nuget@v2
|
||||
|
||||
- name: Restore (Windows ARM64)
|
||||
run: nuget restore Photino.Native.sln -NonInteractive
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
- name: Build (Windows ARM64)
|
||||
run: >
|
||||
msbuild ./Photino.Native/Photino.Native.vcxproj
|
||||
/p:Configuration=${{ env.buildConfiguration }}
|
||||
/p:Platform=ARM64
|
||||
|
||||
- name: Upload Windows ARM64 libs
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: photino.Native-Windows-arm64
|
||||
path: ./Photino.Native/arm64/${{ env.buildConfiguration }}
|
||||
|
||||
Build_Linux_x64:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build (Linux x64)
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ./Photino.Native/x64/${{ env.buildConfiguration }}
|
||||
make linux-x64
|
||||
mv ./lib/x64/Photino.Native.so ./Photino.Native/x64/${{ env.buildConfiguration }}/Photino.Native.so
|
||||
|
||||
- name: Upload Linux x64 libs
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: photino.Native-Linux-x64
|
||||
path: ./Photino.Native/x64/${{ env.buildConfiguration }}
|
||||
|
||||
# If/when you want to build Linux ARM64 on native hardware or via cross, uncomment and adapt:
|
||||
# Build_Linux_Arm64:
|
||||
# runs-on: ubuntu-24.04
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Build (Linux ARM64)
|
||||
# shell: bash
|
||||
# run: |
|
||||
# mkdir -p ./Photino.Native/arm64/${{ env.buildConfiguration }}
|
||||
# make linux-dev
|
||||
# mv ./lib/dev/Photino.Native.so ./Photino.Native/arm64/${{ env.buildConfiguration }}/Photino.Native.so
|
||||
# - name: Upload Linux ARM64 libs
|
||||
# uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: LinuxArm64Artifact
|
||||
# path: ./Photino.Native/arm64/${{ env.buildConfiguration }}
|
||||
|
||||
Build_Mac_Universal:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build (macOS universal)
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ./Photino.Native/x64/${{ env.buildConfiguration }}
|
||||
mkdir -p ./Photino.Native/arm64/${{ env.buildConfiguration }}
|
||||
make mac-universal
|
||||
cp ./lib/x64/Photino.Native.dylib ./Photino.Native/x64/${{ env.buildConfiguration }}/Photino.Native.dylib
|
||||
cp ./lib/x64/Photino.Native.dylib ./Photino.Native/arm64/${{ env.buildConfiguration }}/Photino.Native.dylib
|
||||
|
||||
- name: Upload macOS x64 dylib
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: photino.Native-macOS-x64
|
||||
path: ./Photino.Native/x64/${{ env.buildConfiguration }}/Photino.Native.dylib
|
||||
|
||||
- name: Upload macOS ARM64 dylib
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: photino.Native-macOS-arm64
|
||||
path: ./Photino.Native/arm64/${{ env.buildConfiguration }}/Photino.Native.dylib
|
||||
|
||||
# Copy_Manual_Arm64_Releases:
|
||||
# runs-on: ubuntu-24.04
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
#
|
||||
# - name: Copy ARM64 native assets
|
||||
# shell: bash
|
||||
# run: |
|
||||
# mkdir -p ./Photino.Native/arm64/${{ env.buildConfiguration }}
|
||||
# mv ./manual-arm-release/linux-arm64/Photino.Native.so ./Photino.Native/arm64/${{ env.buildConfiguration }}/Photino.Native.so
|
||||
#
|
||||
# - name: Upload Linux ARM64 libs
|
||||
# uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: LinuxArm64Artifact
|
||||
# path: ./Photino.Native/arm64/${{ env.buildConfiguration }}
|
||||
|
||||
# PublishPackage:
|
||||
# runs-on: windows-latest
|
||||
# needs:
|
||||
# - Publish_Nuspec
|
||||
# - Build_Win_x64
|
||||
# - Build_Win_Arm64
|
||||
# - Build_Linux_x64
|
||||
# - Build_Mac_Universal
|
||||
# - Copy_Manual_Arm64_Releases
|
||||
# steps:
|
||||
# - name: Prepare workspace directory
|
||||
# run: mkdir $env:GITHUB_WORKSPACE\pkg
|
||||
#
|
||||
# - name: Download NuspecArtifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: NuspecArtifact
|
||||
# path: ${{ github.workspace }}\pkg
|
||||
#
|
||||
# - name: Download WindowsIntelArtifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: WindowsIntelArtifact
|
||||
# path: ${{ github.workspace }}\pkg\x64
|
||||
#
|
||||
# - name: Download WindowsArm64Artifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: WindowsArm64Artifact
|
||||
# path: ${{ github.workspace }}\pkg\arm64
|
||||
#
|
||||
# - name: Download LinuxIntelArtifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: LinuxIntelArtifact
|
||||
# path: ${{ github.workspace }}\pkg\x64
|
||||
#
|
||||
# - name: Download LinuxArm64Artifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: LinuxArm64Artifact
|
||||
# path: ${{ github.workspace }}\pkg\arm64
|
||||
#
|
||||
# - name: Download MacOsIntelArtifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: MacOsIntelArtifact
|
||||
# path: ${{ github.workspace }}\pkg\x64
|
||||
#
|
||||
# - name: Download MacOsArm64Artifact
|
||||
# uses: actions/download-artifact@v4
|
||||
# with:
|
||||
# name: MacOsArm64Artifact
|
||||
# path: ${{ github.workspace }}\pkg\arm64
|
||||
#
|
||||
# - name: List downloaded files (root)
|
||||
# shell: pwsh
|
||||
# run: Get-ChildItem -Recurse $env:GITHUB_WORKSPACE\pkg | Format-Table -AutoSize
|
||||
#
|
||||
# - name: List x64
|
||||
# shell: pwsh
|
||||
# run: Get-ChildItem -Recurse $env:GITHUB_WORKSPACE\pkg\x64 | Format-Table -AutoSize
|
||||
#
|
||||
# - name: List arm64
|
||||
# shell: pwsh
|
||||
# run: Get-ChildItem -Recurse $env:GITHUB_WORKSPACE\pkg\arm64 | Format-Table -AutoSize
|
||||
#
|
||||
# - name: Setup NuGet
|
||||
# uses: NuGet/setup-nuget@v2
|
||||
#
|
||||
# - name: Compute version
|
||||
# id: ver
|
||||
# shell: pwsh
|
||||
# run: |
|
||||
# $patch = "${{ github.run_number }}"
|
||||
# $version = "${{ env.MAJOR }}.${{ env.MINOR }}.$patch"
|
||||
# "patch=$patch" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
||||
# "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
||||
# Write-Host "Version: $version"
|
||||
#
|
||||
# - name: Pack nupkg
|
||||
# shell: pwsh
|
||||
# working-directory: ${{ github.workspace }}\pkg
|
||||
# run: |
|
||||
# nuget pack Photino.Native.nuspec `
|
||||
# -Version "${{ steps.ver.outputs.version }}" `
|
||||
# -NonInteractive `
|
||||
# -Properties "version=${{ steps.ver.outputs.version }}"
|
||||
#
|
||||
# - name: Upload nupkg as artifact (optional)
|
||||
# uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: Photino.Native.nupkg
|
||||
# path: ${{ github.workspace }}\pkg\**\*.nupkg
|
||||
#
|
||||
# - name: Push to nuget.org
|
||||
# if: ${{ github.ref == 'refs/heads/master' }}
|
||||
# shell: pwsh
|
||||
# working-directory: ${{ github.workspace }}\pkg
|
||||
# env:
|
||||
# NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||
# run: |
|
||||
# nuget push **\*.nupkg `
|
||||
# -Source "https://api.nuget.org/v3/index.json" `
|
||||
# -ApiKey "$env:NUGET_API_KEY" `
|
||||
# -NonInteractive
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,7 @@
|
|||
/* * Copyright (C) 2016-2019 Mohammed Boujemaoui <mohabouje@gmail.com>
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2016-2023 WinToast v1.3.0 - Mohammed Boujemaoui <mohabouje@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,6 +23,7 @@
|
|||
|
||||
#ifndef WINTOASTLIB_H
|
||||
#define WINTOASTLIB_H
|
||||
|
||||
#include <Windows.h>
|
||||
#include <sdkddkver.h>
|
||||
#include <WinUser.h>
|
||||
|
|
@ -38,27 +42,32 @@
|
|||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace ABI::Windows::Data::Xml::Dom;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::UI::Notifications;
|
||||
using namespace Windows::Foundation;
|
||||
|
||||
|
||||
namespace WinToastLib {
|
||||
|
||||
void setDebugOutputEnabled(bool enabled);
|
||||
|
||||
class IWinToastHandler {
|
||||
public:
|
||||
enum WinToastDismissalReason {
|
||||
UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled,
|
||||
UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled,
|
||||
ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden,
|
||||
TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut
|
||||
TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut
|
||||
};
|
||||
virtual ~IWinToastHandler() = default;
|
||||
virtual void toastActivated() const = 0;
|
||||
virtual void toastActivated(int actionIndex) const = 0;
|
||||
|
||||
virtual ~IWinToastHandler() = default;
|
||||
virtual void toastActivated() const = 0;
|
||||
virtual void toastActivated(int actionIndex) const = 0;
|
||||
virtual void toastActivated(std::wstring response) const = 0;
|
||||
virtual void toastDismissed(WinToastDismissalReason state) const = 0;
|
||||
virtual void toastFailed() const = 0;
|
||||
virtual void toastFailed() const = 0;
|
||||
};
|
||||
|
||||
class WinToastTemplate {
|
||||
|
|
@ -67,15 +76,16 @@ namespace WinToastLib {
|
|||
enum Duration { System, Short, Long };
|
||||
enum AudioOption { Default = 0, Silent, Loop };
|
||||
enum TextField { FirstLine = 0, SecondLine, ThirdLine };
|
||||
|
||||
enum WinToastTemplateType {
|
||||
ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01,
|
||||
ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02,
|
||||
ImageAndText03 = ToastTemplateType::ToastTemplateType_ToastImageAndText03,
|
||||
ImageAndText04 = ToastTemplateType::ToastTemplateType_ToastImageAndText04,
|
||||
Text01 = ToastTemplateType::ToastTemplateType_ToastText01,
|
||||
Text02 = ToastTemplateType::ToastTemplateType_ToastText02,
|
||||
Text03 = ToastTemplateType::ToastTemplateType_ToastText03,
|
||||
Text04 = ToastTemplateType::ToastTemplateType_ToastText04,
|
||||
Text01 = ToastTemplateType::ToastTemplateType_ToastText01,
|
||||
Text02 = ToastTemplateType::ToastTemplateType_ToastText02,
|
||||
Text03 = ToastTemplateType::ToastTemplateType_ToastText03,
|
||||
Text04 = ToastTemplateType::ToastTemplateType_ToastText04
|
||||
};
|
||||
|
||||
enum AudioSystemFile {
|
||||
|
|
@ -107,49 +117,67 @@ namespace WinToastLib {
|
|||
Call10,
|
||||
};
|
||||
|
||||
enum CropHint {
|
||||
Square,
|
||||
Circle,
|
||||
};
|
||||
|
||||
WinToastTemplate(_In_ WinToastTemplateType type = WinToastTemplateType::ImageAndText02);
|
||||
~WinToastTemplate();
|
||||
|
||||
void setFirstLine(_In_ const std::wstring& text);
|
||||
void setSecondLine(_In_ const std::wstring& text);
|
||||
void setThirdLine(_In_ const std::wstring& text);
|
||||
void setTextField(_In_ const std::wstring& txt, _In_ TextField pos);
|
||||
void setAttributionText(_In_ const std::wstring& attributionText);
|
||||
void setImagePath(_In_ const std::wstring& imgPath);
|
||||
void setFirstLine(_In_ std::wstring const& text);
|
||||
void setSecondLine(_In_ std::wstring const& text);
|
||||
void setThirdLine(_In_ std::wstring const& text);
|
||||
void setTextField(_In_ std::wstring const& txt, _In_ TextField pos);
|
||||
void setAttributionText(_In_ std::wstring const& attributionText);
|
||||
void setImagePath(_In_ std::wstring const& imgPath, _In_ CropHint cropHint = CropHint::Square);
|
||||
void setHeroImagePath(_In_ std::wstring const& imgPath, _In_ bool inlineImage = false);
|
||||
void setAudioPath(_In_ WinToastTemplate::AudioSystemFile audio);
|
||||
void setAudioPath(_In_ const std::wstring& audioPath);
|
||||
void setAudioPath(_In_ std::wstring const& audioPath);
|
||||
void setAudioOption(_In_ WinToastTemplate::AudioOption audioOption);
|
||||
void setDuration(_In_ Duration duration);
|
||||
void setExpiration(_In_ INT64 millisecondsFromNow);
|
||||
void setScenario(_In_ Scenario scenario);
|
||||
void addAction(_In_ const std::wstring& label);
|
||||
void addAction(_In_ std::wstring const& label);
|
||||
void addInput();
|
||||
|
||||
std::size_t textFieldsCount() const;
|
||||
std::size_t actionsCount() const;
|
||||
bool hasImage() const;
|
||||
const std::vector<std::wstring>& textFields() const;
|
||||
const std::wstring& textField(_In_ TextField pos) const;
|
||||
const std::wstring& actionLabel(_In_ std::size_t pos) const;
|
||||
const std::wstring& imagePath() const;
|
||||
const std::wstring& audioPath() const;
|
||||
const std::wstring& attributionText() const;
|
||||
const std::wstring& scenario() const;
|
||||
bool hasHeroImage() const;
|
||||
std::vector<std::wstring> const& textFields() const;
|
||||
std::wstring const& textField(_In_ TextField pos) const;
|
||||
std::wstring const& actionLabel(_In_ std::size_t pos) const;
|
||||
std::wstring const& imagePath() const;
|
||||
std::wstring const& heroImagePath() const;
|
||||
std::wstring const& audioPath() const;
|
||||
std::wstring const& attributionText() const;
|
||||
std::wstring const& scenario() const;
|
||||
INT64 expiration() const;
|
||||
WinToastTemplateType type() const;
|
||||
WinToastTemplate::AudioOption audioOption() const;
|
||||
Duration duration() const;
|
||||
bool isToastGeneric() const;
|
||||
bool isInlineHeroImage() const;
|
||||
bool isCropHintCircle() const;
|
||||
bool isInput() const;
|
||||
|
||||
private:
|
||||
std::vector<std::wstring> _textFields{};
|
||||
std::vector<std::wstring> _actions{};
|
||||
std::wstring _imagePath{};
|
||||
std::wstring _audioPath{};
|
||||
std::wstring _attributionText{};
|
||||
std::wstring _scenario{L"Default"};
|
||||
INT64 _expiration{0};
|
||||
AudioOption _audioOption{WinToastTemplate::AudioOption::Default};
|
||||
WinToastTemplateType _type{WinToastTemplateType::Text01};
|
||||
Duration _duration{Duration::System};
|
||||
bool _hasInput{false};
|
||||
|
||||
std::vector<std::wstring> _textFields{};
|
||||
std::vector<std::wstring> _actions{};
|
||||
std::wstring _imagePath{};
|
||||
std::wstring _heroImagePath{};
|
||||
bool _inlineHeroImage{false};
|
||||
std::wstring _audioPath{};
|
||||
std::wstring _attributionText{};
|
||||
std::wstring _scenario{L"Default"};
|
||||
INT64 _expiration{0};
|
||||
AudioOption _audioOption{WinToastTemplate::AudioOption::Default};
|
||||
WinToastTemplateType _type{WinToastTemplateType::Text01};
|
||||
Duration _duration{Duration::System};
|
||||
CropHint _cropHint{CropHint::Square};
|
||||
};
|
||||
|
||||
class WinToast {
|
||||
|
|
@ -167,14 +195,14 @@ namespace WinToastLib {
|
|||
};
|
||||
|
||||
enum ShortcutResult {
|
||||
SHORTCUT_UNCHANGED = 0,
|
||||
SHORTCUT_UNCHANGED = 0,
|
||||
SHORTCUT_WAS_CHANGED = 1,
|
||||
SHORTCUT_WAS_CREATED = 2,
|
||||
|
||||
SHORTCUT_MISSING_PARAMETERS = -1,
|
||||
SHORTCUT_INCOMPATIBLE_OS = -2,
|
||||
SHORTCUT_COM_INIT_FAILURE = -3,
|
||||
SHORTCUT_CREATE_FAILED = -4
|
||||
SHORTCUT_INCOMPATIBLE_OS = -2,
|
||||
SHORTCUT_COM_INIT_FAILURE = -3,
|
||||
SHORTCUT_CREATE_FAILED = -4
|
||||
};
|
||||
|
||||
enum ShortcutPolicy {
|
||||
|
|
@ -182,8 +210,7 @@ namespace WinToastLib {
|
|||
SHORTCUT_POLICY_IGNORE = 0,
|
||||
/* Require a shortcut with matching AUMI, don't create or modify an existing one. */
|
||||
SHORTCUT_POLICY_REQUIRE_NO_CREATE = 1,
|
||||
/* Require a shortcut with matching AUMI, create if missing, modify if not matching.
|
||||
* This is the default. */
|
||||
/* Require a shortcut with matching AUMI, create if missing, modify if not matching. This is the default. */
|
||||
SHORTCUT_POLICY_REQUIRE_CREATE = 2,
|
||||
};
|
||||
|
||||
|
|
@ -192,43 +219,100 @@ namespace WinToastLib {
|
|||
static WinToast* instance();
|
||||
static bool isCompatible();
|
||||
static bool isSupportingModernFeatures();
|
||||
static std::wstring configureAUMI(_In_ const std::wstring& companyName,
|
||||
_In_ const std::wstring& productName,
|
||||
_In_ const std::wstring& subProduct = std::wstring(),
|
||||
_In_ const std::wstring& versionInformation = std::wstring());
|
||||
static const std::wstring& strerror(_In_ WinToastError error);
|
||||
static bool isWin10AnniversaryOrHigher();
|
||||
static std::wstring configureAUMI(_In_ std::wstring const& companyName, _In_ std::wstring const& productName,
|
||||
_In_ std::wstring const& subProduct = std::wstring(),
|
||||
_In_ std::wstring const& versionInformation = std::wstring());
|
||||
static std::wstring const& strerror(_In_ WinToastError error);
|
||||
virtual bool initialize(_Out_opt_ WinToastError* error = nullptr);
|
||||
virtual bool isInitialized() const;
|
||||
virtual bool hideToast(_In_ INT64 id);
|
||||
virtual INT64 showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler, _Out_opt_ WinToastError* error = nullptr);
|
||||
virtual INT64 showToast(_In_ WinToastTemplate const& toast, _In_ IWinToastHandler* eventHandler,
|
||||
_Out_opt_ WinToastError* error = nullptr);
|
||||
virtual void clear();
|
||||
virtual enum ShortcutResult createShortcut();
|
||||
|
||||
const std::wstring& appName() const;
|
||||
const std::wstring& appUserModelId() const;
|
||||
void setAppUserModelId(_In_ const std::wstring& aumi);
|
||||
void setAppName(_In_ const std::wstring& appName);
|
||||
std::wstring const& appName() const;
|
||||
std::wstring const& appUserModelId() const;
|
||||
void setAppUserModelId(_In_ std::wstring const& aumi);
|
||||
void setAppName(_In_ std::wstring const& appName);
|
||||
void setShortcutPolicy(_In_ ShortcutPolicy policy);
|
||||
|
||||
protected:
|
||||
bool _isInitialized{false};
|
||||
bool _hasCoInitialized{false};
|
||||
ShortcutPolicy _shortcutPolicy{SHORTCUT_POLICY_REQUIRE_CREATE};
|
||||
std::wstring _appName{};
|
||||
std::wstring _aumi{};
|
||||
std::map<INT64, ComPtr<IToastNotification>> _buffer{};
|
||||
struct NotifyData {
|
||||
NotifyData(){};
|
||||
NotifyData(_In_ ComPtr<IToastNotification> notify, _In_ EventRegistrationToken activatedToken,
|
||||
_In_ EventRegistrationToken dismissedToken, _In_ EventRegistrationToken failedToken) :
|
||||
_notify(notify), _activatedToken(activatedToken), _dismissedToken(dismissedToken), _failedToken(failedToken) {}
|
||||
|
||||
~NotifyData() {
|
||||
RemoveTokens();
|
||||
}
|
||||
|
||||
void RemoveTokens() {
|
||||
if (!_readyForDeletion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_previouslyTokenRemoved) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_notify.Get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_notify->remove_Activated(_activatedToken);
|
||||
_notify->remove_Dismissed(_dismissedToken);
|
||||
_notify->remove_Failed(_failedToken);
|
||||
_previouslyTokenRemoved = true;
|
||||
}
|
||||
|
||||
void markAsReadyForDeletion() {
|
||||
_readyForDeletion = true;
|
||||
}
|
||||
|
||||
bool isReadyForDeletion() const {
|
||||
return _readyForDeletion;
|
||||
}
|
||||
|
||||
IToastNotification* notification() {
|
||||
return _notify.Get();
|
||||
}
|
||||
|
||||
private:
|
||||
ComPtr<IToastNotification> _notify{nullptr};
|
||||
EventRegistrationToken _activatedToken{};
|
||||
EventRegistrationToken _dismissedToken{};
|
||||
EventRegistrationToken _failedToken{};
|
||||
bool _readyForDeletion{false};
|
||||
bool _previouslyTokenRemoved{false};
|
||||
};
|
||||
|
||||
bool _isInitialized{false};
|
||||
bool _hasCoInitialized{false};
|
||||
ShortcutPolicy _shortcutPolicy{SHORTCUT_POLICY_REQUIRE_CREATE};
|
||||
std::wstring _appName{};
|
||||
std::wstring _aumi{};
|
||||
std::map<INT64, NotifyData> _buffer{};
|
||||
|
||||
void markAsReadyForDeletion(_In_ INT64 id);
|
||||
HRESULT validateShellLinkHelper(_Out_ bool& wasChanged);
|
||||
HRESULT createShellLinkHelper();
|
||||
HRESULT setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path);
|
||||
HRESULT setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path, _In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default);
|
||||
HRESULT setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text, _In_ UINT32 pos);
|
||||
HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text);
|
||||
HRESULT addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& action, _In_ const std::wstring& arguments);
|
||||
HRESULT addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& duration);
|
||||
HRESULT addScenarioHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& scenario);
|
||||
HRESULT setImageFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& path, _In_ bool isToastGeneric, bool isCropHintCircle);
|
||||
HRESULT setHeroImageHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& path, _In_ bool isInlineImage);
|
||||
HRESULT setBindToastGenericHelper(_In_ IXmlDocument* xml);
|
||||
HRESULT
|
||||
setAudioFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& path,
|
||||
_In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default);
|
||||
HRESULT setTextFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& text, _In_ UINT32 pos);
|
||||
HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& text);
|
||||
HRESULT addActionHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& action, _In_ std::wstring const& arguments);
|
||||
HRESULT addDurationHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& duration);
|
||||
HRESULT addScenarioHelper(_In_ IXmlDocument* xml, _In_ std::wstring const& scenario);
|
||||
HRESULT addInputHelper(_In_ IXmlDocument* xml);
|
||||
ComPtr<IToastNotifier> notifier(_In_ bool* succeded) const;
|
||||
void setError(_Out_opt_ WinToastError* error, _In_ WinToastError value);
|
||||
};
|
||||
}
|
||||
} // namespace WinToastLib
|
||||
#endif // WINTOASTLIB_H
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "Photino.Dialog.h"
|
||||
#include "Photino.Notification.h"
|
||||
#include "Photino.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
@ -56,6 +57,11 @@ extern "C"
|
|||
instance->ClearBrowserAutoFill();
|
||||
}
|
||||
|
||||
EXPORTED void Photino_Focus(Photino* instance)
|
||||
{
|
||||
instance->Focus();
|
||||
}
|
||||
|
||||
EXPORTED void Photino_Close(Photino* instance)
|
||||
{
|
||||
instance->Close();
|
||||
|
|
@ -266,6 +272,16 @@ extern "C"
|
|||
instance->SetZoom(zoom);
|
||||
}
|
||||
|
||||
EXPORTED void Photino_StartDragging(Photino* instance)
|
||||
{
|
||||
instance->StartDragging();
|
||||
}
|
||||
|
||||
EXPORTED void Photino_StartResizing(Photino* instance, PhotinoWindowHitTestCode hitTestCode)
|
||||
{
|
||||
instance->StartResizing(hitTestCode);
|
||||
}
|
||||
|
||||
EXPORTED void Photino_SetFlash(Photino* instance, bool state)
|
||||
{
|
||||
instance->SetFlash(state);
|
||||
|
|
@ -280,11 +296,6 @@ extern "C"
|
|||
{
|
||||
instance->ClearProgress();
|
||||
}
|
||||
|
||||
EXPORTED void Photino_ShowNotification(Photino* instance, AutoString title, AutoString body)
|
||||
{
|
||||
instance->ShowNotification(title, body);
|
||||
}
|
||||
|
||||
EXPORTED void Photino_WaitForExit(Photino* instance)
|
||||
{
|
||||
|
|
@ -349,4 +360,54 @@ extern "C"
|
|||
{
|
||||
instance->Invoke(callback);
|
||||
}
|
||||
|
||||
EXPORTED PhotinoNotification* PhotinoNotification_ctor(Photino* window)
|
||||
{
|
||||
return new PhotinoNotification(window);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_dtor(PhotinoNotification* instance)
|
||||
{
|
||||
delete instance;
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_AddText(PhotinoNotification* instance, AutoString text)
|
||||
{
|
||||
instance->AddText(text);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_AddAction(PhotinoNotification* instance, AutoString action)
|
||||
{
|
||||
instance->AddAction(action);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_SetImagePath(PhotinoNotification* instance, AutoString imagePath)
|
||||
{
|
||||
instance->SetImagePath(imagePath);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_SetType(PhotinoNotification* instance, PhotinoNotificationType type)
|
||||
{
|
||||
instance->SetType(type);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_Show(PhotinoNotification* instance)
|
||||
{
|
||||
instance->Show();
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_SetActionCallback(PhotinoNotification* instance, ActionCallback callback)
|
||||
{
|
||||
instance->SetActionCallback(callback);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_SetActivatedCallback(PhotinoNotification* instance, ActivatedCallback callback)
|
||||
{
|
||||
instance->SetActivatedCallback(callback);
|
||||
}
|
||||
|
||||
EXPORTED void PhotinoNotification_SetDismissedCallback(PhotinoNotification* instance, DismissedCallback callback)
|
||||
{
|
||||
instance->SetDismissedCallback(callback);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,6 +333,11 @@ void Photino::ClearBrowserAutoFill()
|
|||
// TODO
|
||||
}
|
||||
|
||||
void Photino::Focus()
|
||||
{
|
||||
gtk_window_present(GTK_WINDOW(_window));
|
||||
}
|
||||
|
||||
void Photino::Close()
|
||||
{
|
||||
gtk_window_close(GTK_WINDOW(_window));
|
||||
|
|
|
|||
|
|
@ -344,6 +344,12 @@ void Photino::ClearBrowserAutoFill()
|
|||
//TODO
|
||||
}
|
||||
|
||||
void Photino::Focus()
|
||||
{
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[_window makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
void Photino::Close()
|
||||
{
|
||||
if (_chromeless)
|
||||
|
|
|
|||
|
|
@ -172,8 +172,9 @@ COPY .\$(OutDir)WebView2Loader.dll ..\Photino.Test\bin\Debug\net8.0\</Command>
|
|||
<PostBuildEvent>
|
||||
<Message>
|
||||
</Message>
|
||||
<Command>
|
||||
</Command>
|
||||
<Command>COPY .\$(OutDir)Photino.Native.dll ..\Photino.Test\bin\Debug\net8.0\
|
||||
COPY .\$(OutDir)Photino.Native.pdb ..\Photino.Test\bin\Debug\net8.0\
|
||||
COPY .\$(OutDir)WebView2Loader.dll ..\Photino.Test\bin\Debug\net8.0\</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
|
@ -248,6 +249,8 @@ COPY .\$(OutDir)WebView2Loader.dll ..\Photino.Test\bin\ARM64\Debug\net8.0\</Comm
|
|||
<ClCompile Include="Photino.Windows.cpp" />
|
||||
<ClCompile Include="Photino.Windows.DarkMode.cpp" />
|
||||
<ClCompile Include="Photino.Windows.Dialog.cpp" />
|
||||
<ClCompile Include="Photino.Windows.Notification.cpp" />
|
||||
<ClCompile Include="Photino.Windows.ToastHandler.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Dependencies\wintoastlib.h" />
|
||||
|
|
@ -260,6 +263,7 @@ COPY .\$(OutDir)WebView2Loader.dll ..\Photino.Test\bin\ARM64\Debug\net8.0\</Comm
|
|||
<ClInclude Include="Photino.Mac.WindowDelegate.h" />
|
||||
<ClInclude Include="Photino.Mac.UrlSchemeHandler.h" />
|
||||
<ClInclude Include="Photino.Dialog.h" />
|
||||
<ClInclude Include="Photino.Notification.h" />
|
||||
<ClInclude Include="Photino.Windows.ToastHandler.h" />
|
||||
<ClInclude Include="Photino.Windows.DarkMode.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@
|
|||
<ClCompile Include="Photino.Linux.Dialog.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Photino.Windows.Notification.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Photino.Windows.ToastHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
@ -105,6 +111,9 @@
|
|||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Photino.Notification.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
|
|
|
|||
91
Photino.Native/Photino.Notification.h
Normal file
91
Photino.Native/Photino.Notification.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef PHOTINO_NOTIFICATION_H
|
||||
#define PHOTINO_NOTIFICATION_H
|
||||
|
||||
#include "Photino.h"
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
class PhotinoWinToastHandler;
|
||||
#endif
|
||||
|
||||
enum class PhotinoNotificationType {
|
||||
ImageAndText01,
|
||||
ImageAndText02,
|
||||
ImageAndText03,
|
||||
ImageAndText04,
|
||||
Text01,
|
||||
Text02,
|
||||
Text03,
|
||||
Text04,
|
||||
};
|
||||
|
||||
enum class PhotinoNotificationDismissalReason {
|
||||
UserCanceled,
|
||||
ApplicationHidden,
|
||||
TimedOut,
|
||||
};
|
||||
|
||||
typedef void (*ActionCallback)(int actionIndex);
|
||||
typedef void (*ActivatedCallback)();
|
||||
typedef void (*DismissedCallback)(PhotinoNotificationDismissalReason reason);
|
||||
|
||||
class PhotinoNotification
|
||||
{
|
||||
private:
|
||||
PhotinoNotificationType _type;
|
||||
|
||||
ActionCallback _actionCallback;
|
||||
ActivatedCallback _activatedCallback;
|
||||
DismissedCallback _dismissedCallback;
|
||||
|
||||
std::vector<AutoString> _textLines;
|
||||
std::vector<AutoString> _actionNames;
|
||||
AutoString _imagePath;
|
||||
|
||||
public:
|
||||
PhotinoNotification(Photino* window);
|
||||
|
||||
#ifdef _WIN32
|
||||
~PhotinoNotification();
|
||||
#endif
|
||||
|
||||
std::vector<AutoString> GetActions() const;
|
||||
|
||||
void AddText(AutoString text);
|
||||
void AddAction(AutoString action);
|
||||
void SetImagePath(AutoString imagePath);
|
||||
void SetType(PhotinoNotificationType type);
|
||||
void Show();
|
||||
|
||||
void SetActionCallback(ActionCallback callback) { _actionCallback = callback; }
|
||||
void SetActivatedCallback(ActivatedCallback callback) { _activatedCallback = callback; }
|
||||
void SetDismissedCallback(DismissedCallback callback) { _dismissedCallback = callback; }
|
||||
|
||||
void InvokeAction(int actionIndex) const
|
||||
{
|
||||
if (_actionCallback)
|
||||
return _actionCallback(actionIndex);
|
||||
}
|
||||
|
||||
void InvokeActivated() const
|
||||
{
|
||||
if (_activatedCallback)
|
||||
return _activatedCallback();
|
||||
}
|
||||
|
||||
void InvokeDismissed(PhotinoNotificationDismissalReason reason) const
|
||||
{
|
||||
if (_dismissedCallback)
|
||||
return _dismissedCallback(reason);
|
||||
}
|
||||
|
||||
protected:
|
||||
#ifdef _WIN32
|
||||
Photino* _window{};
|
||||
PhotinoWinToastHandler* _handler{};
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
114
Photino.Native/Photino.Windows.Notification.cpp
Normal file
114
Photino.Native/Photino.Windows.Notification.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#include "Photino.Notification.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Photino.Windows.ToastHandler.h"
|
||||
#endif
|
||||
|
||||
WinToastLib::WinToastTemplate _toast;
|
||||
|
||||
PhotinoNotification::PhotinoNotification(Photino* window)
|
||||
{
|
||||
_window = window;
|
||||
_handler = new PhotinoWinToastHandler(_window, this);
|
||||
}
|
||||
|
||||
PhotinoNotification::~PhotinoNotification()
|
||||
{
|
||||
delete _handler;
|
||||
}
|
||||
|
||||
std::vector<AutoString> PhotinoNotification::GetActions() const
|
||||
{
|
||||
return _actionNames;
|
||||
}
|
||||
|
||||
void PhotinoNotification::SetType(PhotinoNotificationType type)
|
||||
{
|
||||
_type = type;
|
||||
|
||||
WinToastLib::WinToastTemplate::WinToastTemplateType winToastType;
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
case PhotinoNotificationType::ImageAndText01:
|
||||
winToastType = WinToastLib::WinToastTemplate::ImageAndText01;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::ImageAndText02:
|
||||
winToastType = WinToastLib::WinToastTemplate::ImageAndText02;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::ImageAndText03:
|
||||
winToastType = WinToastLib::WinToastTemplate::ImageAndText03;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::ImageAndText04:
|
||||
winToastType = WinToastLib::WinToastTemplate::ImageAndText04;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::Text01:
|
||||
winToastType = WinToastLib::WinToastTemplate::Text01;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::Text02:
|
||||
winToastType = WinToastLib::WinToastTemplate::Text02;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::Text03:
|
||||
winToastType = WinToastLib::WinToastTemplate::Text03;
|
||||
break;
|
||||
|
||||
case PhotinoNotificationType::Text04:
|
||||
winToastType = WinToastLib::WinToastTemplate::Text04;
|
||||
break;
|
||||
|
||||
default:
|
||||
winToastType = WinToastLib::WinToastTemplate::Text01;
|
||||
break;
|
||||
}
|
||||
|
||||
_toast = WinToastLib::WinToastTemplate(winToastType);
|
||||
}
|
||||
|
||||
void PhotinoNotification::AddText(AutoString text)
|
||||
{
|
||||
AutoString conv = _window->ToUTF16String(text);
|
||||
|
||||
_textLines.push_back(conv);
|
||||
|
||||
switch (_textLines.size())
|
||||
{
|
||||
case 1:
|
||||
_toast.setTextField(conv, WinToastLib::WinToastTemplate::FirstLine);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_toast.setTextField(conv, WinToastLib::WinToastTemplate::SecondLine);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_toast.setTextField(conv, WinToastLib::WinToastTemplate::ThirdLine);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
_toast.setAttributionText(conv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PhotinoNotification::AddAction(AutoString action)
|
||||
{
|
||||
_actionNames.push_back(action);
|
||||
_toast.addAction(_window->ToUTF16String(action));
|
||||
}
|
||||
|
||||
void PhotinoNotification::SetImagePath(AutoString imagePath)
|
||||
{
|
||||
_imagePath = imagePath;
|
||||
_toast.setImagePath(_window->ToUTF16String(imagePath));
|
||||
}
|
||||
|
||||
void PhotinoNotification::Show()
|
||||
{
|
||||
WinToastLib::WinToast::instance()->showToast(_toast, _handler);
|
||||
}
|
||||
47
Photino.Native/Photino.Windows.ToastHandler.cpp
Normal file
47
Photino.Native/Photino.Windows.ToastHandler.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifdef _WIN32
|
||||
#include "Photino.Windows.ToastHandler.h"
|
||||
#include "Photino.Notification.h"
|
||||
using namespace WinToastLib;
|
||||
|
||||
void PhotinoWinToastHandler::toastActivated() const
|
||||
{
|
||||
ShowWindow(this->_window->getHwnd(), SW_SHOW);
|
||||
ShowWindow(this->_window->getHwnd(), SW_RESTORE);
|
||||
SetForegroundWindow(this->_window->getHwnd());
|
||||
|
||||
_notification->InvokeActivated();
|
||||
}
|
||||
|
||||
void PhotinoWinToastHandler::toastActivated(int actionIndex) const
|
||||
{
|
||||
_notification->InvokeAction(actionIndex);
|
||||
}
|
||||
|
||||
void PhotinoWinToastHandler::toastActivated(std::wstring response) const
|
||||
{
|
||||
// Already implemented above
|
||||
}
|
||||
|
||||
void PhotinoWinToastHandler::toastDismissed(WinToastDismissalReason state) const
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case WinToastDismissalReason::UserCanceled:
|
||||
_notification->InvokeDismissed(PhotinoNotificationDismissalReason::UserCanceled);
|
||||
break;
|
||||
|
||||
case WinToastDismissalReason::ApplicationHidden:
|
||||
_notification->InvokeDismissed(PhotinoNotificationDismissalReason::ApplicationHidden);
|
||||
break;
|
||||
|
||||
case WinToastDismissalReason::TimedOut:
|
||||
_notification->InvokeDismissed(PhotinoNotificationDismissalReason::TimedOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PhotinoWinToastHandler::toastFailed() const
|
||||
{
|
||||
// Not implemented
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,42 +1,34 @@
|
|||
#ifdef _WIN32
|
||||
#ifndef TOASTHANDLER_H
|
||||
#define TOASTHANDLER_H
|
||||
|
||||
#include "Photino.h"
|
||||
#include <vector>
|
||||
#include "Dependencies/wintoastlib.h"
|
||||
#include <WinUser.h>
|
||||
|
||||
using namespace WinToastLib;
|
||||
|
||||
class WinToastHandler : public IWinToastHandler
|
||||
class PhotinoNotification;
|
||||
|
||||
class PhotinoWinToastHandler : public WinToastLib::IWinToastHandler
|
||||
{
|
||||
private:
|
||||
Photino* _window;
|
||||
Photino* _window{};
|
||||
PhotinoNotification* _notification{};
|
||||
|
||||
public:
|
||||
WinToastHandler(Photino* window)
|
||||
explicit PhotinoWinToastHandler(Photino* window, PhotinoNotification* notification)
|
||||
{
|
||||
this->_window = window;
|
||||
_window = window;
|
||||
_notification = notification;
|
||||
}
|
||||
|
||||
void toastActivated() const
|
||||
{
|
||||
ShowWindow(this->_window->getHwnd(), SW_SHOW); // Make the window visible if it was hidden
|
||||
ShowWindow(this->_window->getHwnd(), SW_RESTORE); // Next, restore it if it was minimized
|
||||
SetForegroundWindow(this->_window->getHwnd()); // Finally, activate the window
|
||||
}
|
||||
|
||||
void toastActivated(int actionIndex) const
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void toastDismissed(WinToastDismissalReason state) const
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void toastFailed() const
|
||||
{
|
||||
//
|
||||
}
|
||||
void toastActivated() const override;
|
||||
void toastActivated(int actionIndex) const override;
|
||||
void toastActivated(std::wstring response) const override;
|
||||
void toastDismissed(WinToastDismissalReason state) const override;
|
||||
void toastFailed() const override;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -300,9 +300,7 @@ Photino::Photino(PhotinoInitParams* initParams)
|
|||
if (_notificationRegistrationId != NULL)
|
||||
WinToast::instance()->setAppUserModelId(_notificationRegistrationId);
|
||||
|
||||
this->_toastHandler = new WinToastHandler(this);
|
||||
WinToast::instance()->initialize();
|
||||
|
||||
}
|
||||
|
||||
_dialog = new PhotinoDialog(this);
|
||||
|
|
@ -520,6 +518,13 @@ void Photino::Center()
|
|||
SetPosition(left, top);
|
||||
}
|
||||
|
||||
void Photino::Focus()
|
||||
{
|
||||
ShowWindow(_hWnd, SW_SHOW);
|
||||
ShowWindow(_hWnd, SW_RESTORE);
|
||||
SetForegroundWindow(_hWnd);
|
||||
}
|
||||
|
||||
void Photino::Close()
|
||||
{
|
||||
PostMessage(_hWnd, WM_CLOSE, NULL, NULL);
|
||||
|
|
@ -857,6 +862,59 @@ void Photino::SetZoom(int zoom)
|
|||
//MessageBox(nullptr, msg, L"Setter", MB_OK);
|
||||
}
|
||||
|
||||
|
||||
void Photino::StartDragging()
|
||||
{
|
||||
ReleaseCapture();
|
||||
SendMessage(_hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
}
|
||||
|
||||
void Photino::StartResizing(PhotinoWindowHitTestCode hitTestCode)
|
||||
{
|
||||
int winHitTestCode = 0;
|
||||
|
||||
switch (hitTestCode)
|
||||
{
|
||||
case PhotinoWindowHitTestCode::Left:
|
||||
winHitTestCode = HTLEFT;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::Right:
|
||||
winHitTestCode = HTRIGHT;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::Top:
|
||||
winHitTestCode = HTTOP;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::Bottom:
|
||||
winHitTestCode = HTBOTTOM;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::TopLeft:
|
||||
winHitTestCode = HTTOPLEFT;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::TopRight:
|
||||
winHitTestCode = HTTOPRIGHT;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::BottomLeft:
|
||||
winHitTestCode = HTBOTTOMLEFT;
|
||||
break;
|
||||
|
||||
case PhotinoWindowHitTestCode::BottomRight:
|
||||
winHitTestCode = HTBOTTOMRIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (winHitTestCode != 0)
|
||||
{
|
||||
ReleaseCapture();
|
||||
SendMessage(_hWnd, WM_NCLBUTTONDOWN, winHitTestCode, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Photino::SetFlash(bool state)
|
||||
{
|
||||
FLASHWINFO f = { sizeof(FLASHWINFO) };
|
||||
|
|
@ -921,23 +979,6 @@ void Photino::ClearProgress()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Photino::ShowNotification(AutoString title, AutoString body)
|
||||
{
|
||||
title = ToUTF16String(title);
|
||||
body = ToUTF16String(body);
|
||||
if (_notificationsEnabled && WinToast::isCompatible())
|
||||
{
|
||||
WinToastTemplate toast = WinToastTemplate(WinToastTemplate::ImageAndText02);
|
||||
toast.setTextField(title, WinToastTemplate::FirstLine);
|
||||
toast.setTextField(body, WinToastTemplate::SecondLine);
|
||||
if (this->_iconFileName != NULL)
|
||||
toast.setImagePath(this->_iconFileName);
|
||||
WinToast::instance()->showToast(toast, _toastHandler);
|
||||
}
|
||||
}
|
||||
|
||||
void Photino::WaitForExit()
|
||||
{
|
||||
messageLoopRootWindowHandle = _hWnd;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <WebView2.h>
|
||||
typedef wchar_t *AutoString;
|
||||
class WinToastHandler;
|
||||
class PhotinoNotification;
|
||||
#else
|
||||
// AutoString for macOS/Linux
|
||||
typedef char *AutoString;
|
||||
|
|
@ -40,6 +41,18 @@ struct Monitor
|
|||
double scale;
|
||||
};
|
||||
|
||||
enum class PhotinoWindowHitTestCode
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Top,
|
||||
Bottom,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
};
|
||||
|
||||
enum class PhotinoWindowProgressState
|
||||
{
|
||||
Error,
|
||||
|
|
@ -61,6 +74,7 @@ typedef bool (*ClosingCallback)();
|
|||
typedef void (*FocusInCallback)();
|
||||
typedef void (*FocusOutCallback)();
|
||||
|
||||
class PhotinoNotification;
|
||||
class PhotinoDialog;
|
||||
class Photino;
|
||||
|
||||
|
|
@ -87,7 +101,7 @@ struct PhotinoInitParams
|
|||
MovedCallback *MovedHandler;
|
||||
WebMessageReceivedCallback *WebMessageReceivedHandler;
|
||||
AutoString CustomSchemeNames[16];
|
||||
WebResourceRequestedCallback *CustomSchemeHandler;
|
||||
WebResourceRequestedCallback* CustomSchemeHandler;
|
||||
|
||||
int Left;
|
||||
int Top;
|
||||
|
|
@ -103,6 +117,7 @@ struct PhotinoInitParams
|
|||
bool Chromeless;
|
||||
bool Transparent;
|
||||
bool ContextMenuEnabled;
|
||||
bool ZoomEnabled;
|
||||
bool DevToolsEnabled;
|
||||
bool FullScreen;
|
||||
bool Maximized;
|
||||
|
|
@ -252,6 +267,7 @@ public:
|
|||
|
||||
void Center();
|
||||
void ClearBrowserAutoFill();
|
||||
void Focus();
|
||||
void Close();
|
||||
|
||||
void GetTransparentEnabled(bool *enabled);
|
||||
|
|
@ -302,7 +318,10 @@ public:
|
|||
void SetProgress(ULONGLONG current, ULONGLONG total, PhotinoWindowProgressState state);
|
||||
void ClearProgress();
|
||||
|
||||
void ShowNotification(AutoString title, AutoString message);
|
||||
// Window manipulation
|
||||
void StartDragging();
|
||||
void StartResizing(PhotinoWindowHitTestCode hitTest);
|
||||
|
||||
void WaitForExit();
|
||||
|
||||
// Callbacks
|
||||
|
|
|
|||
|
|
@ -30,16 +30,23 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoDialogEnums.cs" Link="PhotinoDialogEnums.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoDllImports.cs" Link="PhotinoDllImports.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoDllImports.cs" Link="PhotinoDllImports.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNotificationDllImports.cs" Link="PhotinoNotificationDllImports.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoMonitorStruct.cs" Link="PhotinoMonitorStruct.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNativeDelegates.cs" Link="PhotinoNativeDelegates.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNativeParameters.cs" Link="PhotinoNativeParameters.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNetDelegates.cs" Link="PhotinoNetDelegates.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoWindow.NET.cs" Link="PhotinoWindow.NET.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoWindow.NET.cs" Link="PhotinoWindow.NET.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoWindowEnums.cs" Link="PhotinoWindowEnums.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNotification.cs" Link="PhotinoNotification.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNotificationType.cs" Link="PhotinoNotificationType.cs" />
|
||||
<Compile Include="..\..\photino.NET\Photino.NET\PhotinoNotificationDismissalReason.cs" Link="PhotinoNotificationDismissalReason.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="testImage.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="wwwroot\main.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -51,7 +58,7 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyNativeLibs" AfterTargets="Build" Condition="$(Platform) == 'x64'" >
|
||||
<Target Name="CopyNativeLibs" AfterTargets="Build" Condition="$(Platform) == 'x64'">
|
||||
<Copy SourceFiles="..\Photino.Native\x64\Debug\Photino.Native.dll" DestinationFolder="$(TargetDir)" Condition="$(IsWindows) == 'true'" />
|
||||
<Copy SourceFiles="..\Photino.Native\x64\Debug\WebView2Loader.dll" DestinationFolder="$(TargetDir)" Condition="$(IsWindows) == 'true'" />
|
||||
<Copy SourceFiles="../lib/x64/Photino.Native.dylib" DestinationFolder="$(TargetDir)" Condition="$(IsOSX) == 'true'" />
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace Photino.NET
|
|||
//.Offset(new Point(150, 150))
|
||||
//.Offset(250, 250)
|
||||
.SetNotificationRegistrationId("8FDF1B15-3408-47A6-8EF5-2B0676B76277") //Replaces the window title when registering toast notifications
|
||||
.SetNotificationsEnabled(false)
|
||||
.SetNotificationsEnabled(true)
|
||||
|
||||
//Browser settings
|
||||
//.SetContextMenuEnabled(false)
|
||||
|
|
@ -132,6 +132,7 @@ namespace Photino.NET
|
|||
|
||||
.SetLogVerbosity(_logEvents ? 2 : 0);
|
||||
|
||||
|
||||
mainWindow.WaitForClose();
|
||||
|
||||
Console.WriteLine("Done Blocking!");
|
||||
|
|
@ -412,7 +413,21 @@ namespace Photino.NET
|
|||
}
|
||||
else if (string.Compare(message, "toastNotification", true) == 0)
|
||||
{
|
||||
currentWindow.SendNotification("Toast Title", " Toast message! 🤖");
|
||||
currentWindow
|
||||
.CreateNotification(PhotinoNotificationType.ToastImageAndText04)
|
||||
.AddText("Hello World!")
|
||||
.AddText("Lorem ipsum dolor sit amet")
|
||||
.AddText("Some third text!")
|
||||
.SetImagePath($"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\\testImage.jpg")
|
||||
.AddAction("Launch", (notification) =>
|
||||
{
|
||||
Log(notification, "Launch notification action clicked!");
|
||||
})
|
||||
.AddAction("Ignore", (notification) =>
|
||||
{
|
||||
Log(notification, "Ignore notification action clicked!");
|
||||
})
|
||||
.Show();
|
||||
}
|
||||
else if (string.Compare(message, "showOpenFile", true) == 0)
|
||||
{
|
||||
|
|
@ -515,6 +530,42 @@ namespace Photino.NET
|
|||
{
|
||||
currentWindow.ClearProgress();
|
||||
}
|
||||
else if (string.Compare(message, "startDragging", true) == 0)
|
||||
{
|
||||
currentWindow.StartDragging();
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-left", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.Left);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-topLeft", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.TopLeft);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-top", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.Top);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-topRight", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.TopRight);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-right", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.Right);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-bottomRight", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.BottomRight);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-bottom", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.Bottom);
|
||||
}
|
||||
else if (string.Compare(message, "startResizing-bottomLeft", true) == 0)
|
||||
{
|
||||
currentWindow.StartResizing(PhotinoWindowHitTestCode.BottomLeft);
|
||||
}
|
||||
else
|
||||
throw new Exception($"Unknown message '{message}'");
|
||||
}
|
||||
|
|
@ -526,7 +577,23 @@ namespace Photino.NET
|
|||
|
||||
private static void WindowCreated(object sender, EventArgs e)
|
||||
{
|
||||
var window = (PhotinoWindow)sender;
|
||||
Log(sender, "WindowCreated Callback Fired.");
|
||||
|
||||
window
|
||||
.CreateNotification(PhotinoNotificationType.ToastImageAndText04)
|
||||
.AddText("Hello World!")
|
||||
.AddText("Lorem ipsum dolor sit amet")
|
||||
.AddText("Some third text!")
|
||||
.AddAction("Launch", (notification) =>
|
||||
{
|
||||
Log(notification, "Launch notification action clicked!");
|
||||
})
|
||||
.AddAction("Ignore", (notification) =>
|
||||
{
|
||||
Log(notification, "Ignore notification action clicked!");
|
||||
})
|
||||
.Show();
|
||||
}
|
||||
|
||||
private static void WindowLocationChanged(object sender, Point location)
|
||||
|
|
|
|||
BIN
Photino.Test/testImage.jpg
Normal file
BIN
Photino.Test/testImage.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
|
|
@ -144,6 +144,14 @@
|
|||
window.external.sendMessage('setMaxSize');
|
||||
}
|
||||
|
||||
function StartDragging() {
|
||||
window.external.sendMessage('startDragging');
|
||||
}
|
||||
|
||||
function StartResizing(hitTest) {
|
||||
window.external.sendMessage('startResizing-' + hitTest);
|
||||
}
|
||||
|
||||
function SetProgress(state) {
|
||||
window.external.sendMessage('setProgress-' + state + '-' + document.getElementById('progress-range').value);
|
||||
}
|
||||
|
|
@ -300,6 +308,7 @@
|
|||
<button onclick="SetTransparent()">Transparent</button>
|
||||
<button onclick="SetFullScreen()">Kiosk</button>
|
||||
<button onclick="Close()">Close</button>
|
||||
<button onmousedown="StartDragging()">Start Dragging</button>
|
||||
<br>
|
||||
<b>Size</b><br>
|
||||
<button onclick="Minimize()">Minimize</button>
|
||||
|
|
@ -371,5 +380,80 @@
|
|||
</span>
|
||||
|
||||
<canvas id="canvas" style="visibility:hidden">required to render the photo, but not visible</canvas>
|
||||
|
||||
<button class="resize resize-left" onmousedown="StartResizing('left')"></button>
|
||||
<button class="resize resize-top-left" onmousedown="StartResizing('topLeft')"></button>
|
||||
<button class="resize resize-top" onmousedown="StartResizing('top')"></button>
|
||||
<button class="resize resize-top-right" onmousedown="StartResizing('topRight')"></button>
|
||||
<button class="resize resize-right" onmousedown="StartResizing('right')"></button>
|
||||
<button class="resize resize-bottom-right" onmousedown="StartResizing('bottomRight')"></button>
|
||||
<button class="resize resize-bottom" onmousedown="StartResizing('bottom')"></button>
|
||||
<button class="resize resize-bottom-left" onmousedown="StartResizing('bottomLeft')"></button>
|
||||
|
||||
<style>
|
||||
body {
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
.resize {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.resize-left {
|
||||
width: 10px;
|
||||
top: 10px;
|
||||
left: 0px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.resize-top-left {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.resize-top {
|
||||
height: 10px;
|
||||
top: 0;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.resize-top-right {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.resize-right {
|
||||
width: 10px;
|
||||
top: 10px;
|
||||
right: 0px;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.resize-bottom-right {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.resize-bottom {
|
||||
height: 10px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.resize-bottom-left {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue