Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/engine/NotificationWindow.h

Issue 6505394822184960: Issue 1109 - Support notifications (Closed)
Patch Set: fix naming Created July 29, 2015, 11:18 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/engine/NotificationWindow.h
diff --git a/src/engine/NotificationWindow.h b/src/engine/NotificationWindow.h
new file mode 100644
index 0000000000000000000000000000000000000000..c05a7e4beac3fb30f555c6e0475d9921308c2ba1
--- /dev/null
+++ b/src/engine/NotificationWindow.h
@@ -0,0 +1,285 @@
+#pragma once
Oleksandr 2015/08/10 09:13:34 Nit: We try to use GNU style guards in the new cod
sergei 2015/08/17 13:12:53 Done.
+#include <atlbase.h>
+#include <atlwin.h>
+#include <atlctl.h>
+#include <atlimage.h>
+#include <AdblockPlus/JsValue.h>
+#include <AdblockPlus/Notification.h>
+#include <functional>
+#include <MsHtmdid.h>
+
+class IconStaticControl : public ATL::CWindow
+{
+public:
+ explicit IconStaticControl(HWND hWnd = nullptr) : ATL::CWindow(hWnd)
+ { }
+
+ IconStaticControl& operator=(HWND hWnd)
+ {
+ m_hWnd = hWnd;
+ return *this;
+ }
+
+ HWND Create(HWND hWndParent, ATL::_U_RECT rect = nullptr, LPCTSTR szWindowName = nullptr,
+ DWORD dwStyle = 0, DWORD dwExStyle = 0,
+ ATL::_U_MENUorID MenuOrID = nullptr, LPVOID lpCreateParam = nullptr)
+ {
+ return ATL::CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
+ }
+
+ static wchar_t* GetWndClassName()
+ {
+ return L"STATIC";
+ }
+
+ void SetBitmap(HBITMAP hBitmap)
+ {
+ ATLASSERT(::IsWindow(m_hWnd));
+ ::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, reinterpret_cast<LPARAM>(hBitmap));
+ }
+};
+
+template<typename T>
+class ScopedObjectHandle
+{
+public:
+ explicit ScopedObjectHandle(T handle = nullptr) : m_handle(handle)
+ { }
+
+ ~ScopedObjectHandle()
+ {
+ if(m_handle != nullptr)
+ {
+ ::DeleteObject(m_handle);
+ m_handle = nullptr;
+ }
+ }
+
+ ScopedObjectHandle& operator=(T handle)
+ {
+ if(m_handle != nullptr && m_handle != handle)
+ ::DeleteObject(m_handle);
+ m_handle = handle;
+ return *this;
+ }
+
+ T Detach()
+ {
+ T retValue = m_handle;
+ m_handle = nullptr;
+ return retValue;
+ }
+
+ operator T()
+ {
+ return m_handle;
+ }
+
+ operator bool() const
+ {
+ return m_handle == nullptr;
+ }
+protected:
+ T m_handle;
+private:
+ ScopedObjectHandle(const ScopedObjectHandle&);
+ ScopedObjectHandle& operator=(const ScopedObjectHandle&);
+};
+
+class CBrush : public ScopedObjectHandle<HBRUSH>
+{
+public:
+ explicit CBrush(HBRUSH brush = nullptr) : ScopedObjectHandle(brush)
+ {
+ }
+
+ void CreateSolidBrush(COLORREF crColor)
+ {
+ ATLASSERT(m_handle == nullptr);
+ m_handle = ::CreateSolidBrush(crColor);
+ }
+};
+
+class ScopedModule
+{
+public:
+ ScopedModule()
+ : m_hModule(nullptr)
+ {
+ }
+
+ bool Open(const wchar_t* fileName, int flags)
+ {
+ m_hModule = LoadLibraryEx(fileName, nullptr, flags);
+ return m_hModule != nullptr;
+ }
+
+ ~ScopedModule()
+ {
+ if (m_hModule != nullptr)
+ {
+ FreeLibrary(m_hModule);
+ m_hModule = nullptr;
+ }
+ }
+ operator HMODULE()
+ {
+ return m_hModule;
+ }
+private:
+ ScopedModule(const ScopedModule&);
+ ScopedModule& operator=(const ScopedModule&);
+private:
+ HMODULE m_hModule;
+};
+
+class DpiAwareness {
+public:
+ DpiAwareness() : m_dpi(96)
+ {
+ }
+protected:
+ uint32_t DPIAware(uint32_t value) const {
+ return MulDiv(value, m_dpi, 96);
+ }
+ SIZE DPIAware(SIZE value) const {
+ return CSize(DPIAware(value.cx), DPIAware(value.cy));
+ }
+ RECT DPIAware(RECT value) const {
+ return CRect(DPIAware(value.left), DPIAware(value.top), DPIAware(value.right), DPIAware(value.bottom));
+ }
+ uint32_t m_dpi;
+};
+
+enum
+{
+ // ID of HTMLDocument ActiveX control, it's used for event binding.
+ kHTMLDocumentCtrlID = 101
+};
+
+class NotificationWindow : public ATL::CWindowImpl<NotificationWindow>
+ , ATL::IDispEventImpl<kHTMLDocumentCtrlID, NotificationWindow, &DIID_HTMLDocumentEvents2, &LIBID_MSHTML, 4, 0>
+ , protected DpiAwareness
+{
+public:
+ explicit NotificationWindow(const AdblockPlus::Notification& notification, const std::wstring& htmlFileDir);
+ ~NotificationWindow();
+ BEGIN_MSG_MAP(NotificationWindow)
+ if (uMsg == WM_CREATE)
+ {
+ SetMsgHandled(TRUE);
+ lResult = OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam));
+ if(IsMsgHandled())
+ return TRUE;
+ }
+ MESSAGE_HANDLER(WM_LBUTTONUP, OnClick)
+ MESSAGE_HANDLER(WM_RBUTTONUP, OnClick)
+ MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtlColor)
+ if (uMsg == WM_SIZE)
+ {
+ SetMsgHandled(TRUE);
+ OnSize(static_cast<uint32_t>(wParam), CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+ lResult = 0;
+ if(IsMsgHandled())
+ return TRUE;
+ }
+ if (uMsg == WM_DESTROY)
+ {
+ SetMsgHandled(TRUE);
+ OnDestroy();
+ lResult = 0;
+ if(IsMsgHandled())
+ return TRUE;
+ }
+ END_MSG_MAP()
+
+ BEGIN_SINK_MAP(NotificationWindow)
+ SINK_ENTRY_EX(kHTMLDocumentCtrlID, DIID_HTMLDocumentEvents2, DISPID_HTMLDOCUMENTEVENTS2_ONCLICK, OnHTMLDocumentClick)
+ SINK_ENTRY_EX(kHTMLDocumentCtrlID, DIID_HTMLDocumentEvents2, DISPID_HTMLDOCUMENTEVENTS2_ONSELECTSTART, OnHTMLDocumentSelectStart)
+ END_SINK_MAP()
+
+ void SetOnClick(const std::function<void()>& callback)
+ {
+ m_onClickCallback = callback;
+ }
+ void SetOnLinkClicked(const std::function<void(const std::wstring& url)>& callback)
+ {
+ m_onLinkClickedCallback = callback;
+ }
+ void SetOnClose(const std::function<void()>& callback)
+ {
+ m_onCloseCallback = callback;
+ }
+private:
+ LRESULT OnCreate(const CREATESTRUCT* createStruct);
+ LRESULT OnCtlColor(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled);
+ LRESULT OnClick(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled);
+ void OnSize(uint32_t wParam, CSize size);
+ void OnDestroy();
+
+ void __stdcall OnHTMLDocumentClick(IHTMLEventObj* pEvtObj);
+ void __stdcall OnHTMLDocumentSelectStart(IHTMLEventObj* pEvtObj);
+
+ void LoadABPIcon();
+private:
+ std::wstring m_htmlPage;
+ CBrush m_bgColor;
+ ATL::CAxWindow m_axIE;
+ ATL::CImage m_iconImg;
+ IconStaticControl m_icon;
+ std::vector<std::wstring> m_links;
+ std::function<void()> m_onClickCallback;
+ std::function<void()> m_onCloseCallback;
+ std::function<void(const std::wstring& url)> m_onLinkClickedCallback;
+};
+
+typedef ATL::CWinTraits<WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_TOOLWINDOW | WS_EX_TOPMOST> NotificationBorderWindowStyles;
+class NotificationBorderWindow : public ATL::CWindowImpl<NotificationBorderWindow, ATL::CWindow, NotificationBorderWindowStyles>
+ , protected DpiAwareness
+{
+public:
+ DECLARE_WND_CLASS_EX(/*generate class name*/nullptr, CS_DROPSHADOW, WHITE_BRUSH);
+ NotificationBorderWindow(const AdblockPlus::Notification& notification, const std::wstring& htmlFileDir);
+ BEGIN_MSG_MAP(NotificationWindow)
+ if (uMsg == WM_CREATE)
+ {
+ SetMsgHandled(TRUE);
+ lResult = OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam));
+ if(IsMsgHandled())
+ return TRUE;
+ }
+ MESSAGE_HANDLER(WM_LBUTTONUP, OnClick)
+ MESSAGE_HANDLER(WM_RBUTTONUP, OnClick)
+ if (uMsg == WM_SIZE)
+ {
+ SetMsgHandled(TRUE);
+ OnSize(static_cast<uint32_t>(wParam), CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
+ lResult = 0;
+ if(IsMsgHandled())
+ return TRUE;
+ }
+ END_MSG_MAP()
+ void SetOnDestroyed(const std::function<void()>& callback)
+ {
+ m_onDestroyedCallback = callback;
+ }
+ void SetOnLinkClicked(const std::function<void(const std::wstring& url)>& callback)
+ {
+ m_content.SetOnLinkClicked(callback);
+ }
+private:
+ LRESULT OnCreate(const CREATESTRUCT* createStruct);
+ void OnSize(uint32_t wParam, CSize size);
+ LRESULT OnClick(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled);
+
+ void OnFinalMessage(HWND) override;
+
+ // returns {windowX, windowY} of top left corner on the monitor
+ POINT GetWindowCoordinates();
+private:
+ // m_content is used as a holder of all children and we need it to have a border.
+ // It seems the most correct way to have a border to set WS_POPUPWINDOW style
+ // and paint the border in WM_NCPAINT but it simply does not work here.
+ NotificationWindow m_content;
+ std::function<void()> m_onDestroyedCallback;
+};

Powered by Google App Engine
This is Rietveld