diff --git a/bt/CMakeLists.txt b/bt/CMakeLists.txt index 1743f01..620883e 100644 --- a/bt/CMakeLists.txt +++ b/bt/CMakeLists.txt @@ -30,6 +30,9 @@ file(GLOB core_src CONFIGURE_DEPENDS "../common/win32/user.cpp" "../common/win32/window.cpp" "../common/win32/uwp.cpp" + "../common/win32/app.cpp" + "../common/win32/shell_notify_icon.cpp" + "../common/win32/popup_menu.cpp" "../common/config/config.cpp") add_executable (bt WIN32 ${core_src} "bt.cpp" bt.rc) diff --git a/bt/app/systray.cpp b/bt/app/systray.cpp new file mode 100644 index 0000000..7ccae24 --- /dev/null +++ b/bt/app/systray.cpp @@ -0,0 +1,80 @@ +#include "systray.h" +#include "win32/app.h" +#include "win32/shell_notify_icon.h" +#include + +namespace bt { + + using namespace std; + + const string Win32ClassName("BTTrayApp"); + const string AppGuid("026741D2-FF77-462B-AD70-4140697C8AE1"); + #define OWN_WM_NOTIFY_ICON_MESSAGE WM_APP + 1 + // {365F3F68-6330-4D4F-BEF2-999EF15F1BE4} + static const GUID NotifyIconGuid = {0x365f3f68, 0x6330, 0x4d4f, { 0xbe, 0xf2, 0x99, 0x9e, 0xf1, 0x5f, 0x1b, 0xe4 }}; + + void systray::run() { + win32::app app{Win32ClassName, AppGuid}; + win32::shell_notify_icon sni{ + app.get_hwnd(), + NotifyIconGuid, + OWN_WM_NOTIFY_ICON_MESSAGE, + fmt::format("{} {}", APP_LONG_NAME, APP_VERSION)}; + win32::popup_menu m{app.get_hwnd()}; + + app.on_app_window_message = [this, &m, &app](UINT msg, WPARAM wParam, LPARAM lParam) { + switch(msg) { + case OWN_WM_NOTIFY_ICON_MESSAGE: + switch(lParam) { + case WM_LBUTTONUP: + case WM_RBUTTONUP: + // show context menu + build(m); + m.show(); + break; + } + break; + case WM_COMMAND: { + int loword_wparam = LOWORD(wParam); + string id = m.id_from_loword_wparam(loword_wparam); + if(id == "x") { + ::PostQuitMessage(0); + } } + break; + case WM_CLIPBOARDUPDATE: + // get string placed into the clipboard + if (::OpenClipboard(app.get_hwnd())) { + HANDLE hData = ::GetClipboardData(CF_TEXT); + if (hData) { + char* pszText = static_cast(::GlobalLock(hData)); + if (pszText) { + handle_clipboard_text(pszText); + ::GlobalUnlock(hData); + } + } + ::CloseClipboard(); + } + break; + + } + return 0; + }; + + app.add_clipboard_listener(); + + app.run(); + } + + void systray::build(win32::popup_menu& m) { + // this menu can be rebuilt on the fly when needed (clear, add items) + m.clear(); + m.add("o", last_clipboard_url); + m.separator(); + m.add("x", "&Exit"); + } + + void systray::handle_clipboard_text(const std::string& text) { + // todo: check if this is a URL indeed + last_clipboard_url = text; + } +} \ No newline at end of file diff --git a/bt/app/systray.h b/bt/app/systray.h new file mode 100644 index 0000000..63e4637 --- /dev/null +++ b/bt/app/systray.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include "win32/popup_menu.h" + +/** + * @brief Application that runs in system tray notification area. + */ + +namespace bt { + class systray { + public: + void run(); + + private: + std::string last_clipboard_url; + + void build(win32::popup_menu& m); + void handle_clipboard_text(const std::string& text); + }; +} \ No newline at end of file diff --git a/bt/bt.cpp b/bt/bt.cpp index af23971..b043105 100644 --- a/bt/bt.cpp +++ b/bt/bt.cpp @@ -5,10 +5,10 @@ #include "win32/process.h" #include "app/config.h" #include "app/url_pipeline.h" -#include "app/setup.h" #include "win32/window.h" #include "app/rule_hit_log.h" #include "app/url_opener.h" +#include "app/systray.h" //ui #include "app/ui/config_app.h" @@ -91,8 +91,13 @@ void execute(const string& data) { string command_data; string command = get_command(data, command_data); if(!command.empty()) { - // force-invoke the picker - if(command == "pick") { + if(command == "tray") { + // launch "systray" app + bt::systray systray; + systray.run(); + return; + } else if(command == "pick") { + // force-invoke the picker force_picker = true; clean_data = command_data; } diff --git a/bt/globals.h b/bt/globals.h index b857a55..e7268dd 100644 --- a/bt/globals.h +++ b/bt/globals.h @@ -1,14 +1,9 @@ #pragma once #include -#include -#include "app/browser.h" #include "app/url_pipeline.h" #include "app/config.h" #include "../common/ext/alg_tracker.h" -const std::string Win32ClassName("BTWindow"); -const std::string AppGuid("026741D2-FF77-462B-AD70-4140697C8AE1"); - const std::string AppDescription("Redirects open URLs to a browser of your choice."); const std::string ProtoName = "BrowserTamerHTM";