Release v0.5.0: isolate screenshot editor and support manifest-based updates

This commit is contained in:
2026-10-28 22:52:52 +02:00
parent d1eabfca88
commit ccaa8dad3f
24 changed files with 498 additions and 51 deletions
+69
View File
@@ -0,0 +1,69 @@
#include "screenshot.h"
#include <commctrl.h>
namespace {
constexpr wchar_t ControllerClass[]=L"KSwitcher.Screenshot.Controller";
LRESULT CALLBACK controller(HWND window,UINT message,WPARAM wp,LPARAM lp)
{
auto host=(ks::ScreenshotHost *)GetWindowLongPtrW(window,GWLP_USERDATA);
if(message==WM_NCCREATE) {
host=(ks::ScreenshotHost *)((CREATESTRUCTW *)lp)->lpCreateParams;
SetWindowLongPtrW(window,GWLP_USERDATA,(LONG_PTR)host);
}
if(host && message==ks::ScreenshotRequest) {
try { ks::showScreenshot(*host); }
catch(const std::exception &e) {
MessageBoxW(window,ks::wide(e.what()).c_str(),L"Screen capture",MB_OK|MB_ICONERROR);
PostMessageW(window,ks::ScreenshotIdle,0,0);
}
return TRUE;
}
if(host && message==ks::ScreenshotIdle && !host->windows) {
DestroyWindow(window);
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(window,message,wp,lp);
}
}
int WINAPI wWinMain(HINSTANCE instance,HINSTANCE,PWSTR,int)
{
HANDLE mutex=CreateMutexW(nullptr,FALSE,L"Local\\KSwitcher.Screenshot.Singleton");
if(!mutex) return 1;
// Wait through startup/shutdown races; the controller accepts requests only while alive.
bool acquired=false;
for(int attempt=0;attempt<100;++attempt) {
auto wait=WaitForSingleObject(mutex,0);
if(wait==WAIT_OBJECT_0 || wait==WAIT_ABANDONED) { acquired=true; break; }
if(auto existing=FindWindowW(ControllerClass,nullptr)) {
DWORD pid{}; GetWindowThreadProcessId(existing,&pid);
AllowSetForegroundWindow(pid);
DWORD_PTR accepted{};
if(SendMessageTimeoutW(existing,ks::ScreenshotRequest,0,0,SMTO_ABORTIFHUNG,2000,&accepted) && accepted) {
CloseHandle(mutex); return 0;
}
}
Sleep(50);
}
if(!acquired) { CloseHandle(mutex); return 1; }
CoInitializeEx(nullptr,COINIT_APARTMENTTHREADED);
INITCOMMONCONTROLSEX controls{sizeof(controls),ICC_STANDARD_CLASSES|ICC_BAR_CLASSES};
InitCommonControlsEx(&controls);
ks::ScreenshotHost host{instance};
WNDCLASSW cls{}; cls.hInstance=instance; cls.lpfnWndProc=controller; cls.lpszClassName=ControllerClass;
RegisterClassW(&cls);
host.window=CreateWindowW(ControllerClass,L"KSwitcher Screenshot",0,0,0,0,0,nullptr,nullptr,instance,&host);
int result=1;
if(host.window) {
PostMessageW(host.window,ks::ScreenshotRequest,0,0);
MSG message{};
while((result=GetMessageW(&message,nullptr,0,0))>0) {
TranslateMessage(&message); DispatchMessageW(&message);
}
result=result<0?1:0;
}
CoUninitialize();
ReleaseMutex(mutex); CloseHandle(mutex);
return result;
}