Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | |
3 * Copyright (C) 2006-2015 Eyeo GmbH | |
4 * | |
5 * Adblock Plus is free software: you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License version 3 as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | |
16 */ | |
17 | |
1 #include <cassert> | 18 #include <cassert> |
2 #include "NotificationWindow.h" | 19 #include "NotificationWindow.h" |
3 #include "../shared/Utils.h" | 20 #include "../shared/Utils.h" |
4 #include <algorithm> | 21 #include <algorithm> |
5 #include <fstream> | 22 #include <fstream> |
6 #include "../shared/MsHTMLUtils.h" | 23 #include "../shared/MsHTMLUtils.h" |
7 | 24 |
8 // it is taken from src/plugin/Resource.h | 25 // it is taken from src/plugin/Resource.h |
9 #define IDI_ICON_ENABLED 301 | 26 #define IDI_ICON_ENABLED 301 |
10 | 27 |
11 namespace { | 28 namespace { |
12 // DIP = device independant pixels, as DPI is 96 | 29 // DIP = device independant pixels, as DPI is 96 |
13 const uint32_t kWindowWidth = 400 /*DIP*/; | 30 const uint32_t kWindowWidth = 400 /*DIP*/; |
14 const uint32_t kWindowHeight = 120 /*DIP*/; | 31 const uint32_t kWindowHeight = 120 /*DIP*/; |
15 const uint32_t kIconSize = 64 /*DIP*/; | 32 const uint32_t kIconSize = 64 /*DIP*/; |
33 const uint32_t kIconPadding = 10 /*DIP*/; | |
16 | 34 |
17 // offsets from boundaries of working area of screen | 35 // offsets from boundaries of working area of screen |
18 const uint32_t kWindowMarginRight = 50 /*DIP*/; | 36 const uint32_t kWindowMarginRight = 50 /*DIP*/; |
19 const uint32_t kWindowMarginBottom = 20 /*DIP*/; | 37 const uint32_t kWindowMarginBottom = 20 /*DIP*/; |
20 | 38 |
21 std::vector<uint16_t> iconSizes = []()->std::vector<uint16_t> | 39 std::vector<uint16_t> iconSizes = []()->std::vector<uint16_t> |
22 { | 40 { |
23 std::vector<uint16_t> iconSizes; | 41 std::vector<uint16_t> iconSizes; |
24 iconSizes.emplace_back(16); | 42 iconSizes.emplace_back(16); |
25 iconSizes.emplace_back(19); | 43 iconSizes.emplace_back(19); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
90 std::wstring ReplaceMulti(const std::wstring& workingString, const std::wstrin g& templ, const std::wstring& replacement) | 108 std::wstring ReplaceMulti(const std::wstring& workingString, const std::wstrin g& templ, const std::wstring& replacement) |
91 { | 109 { |
92 return ReplaceMulti(workingString, templ, [&replacement]()->std::wstring | 110 return ReplaceMulti(workingString, templ, [&replacement]()->std::wstring |
93 { | 111 { |
94 return replacement; | 112 return replacement; |
95 }); | 113 }); |
96 } | 114 } |
97 } | 115 } |
98 | 116 |
99 NotificationWindow::NotificationWindow(const AdblockPlus::Notification& notifica tion, const std::wstring& htmlFileDir) | 117 NotificationWindow::NotificationWindow(const AdblockPlus::Notification& notifica tion, const std::wstring& htmlFileDir) |
100 : m_dpi(96) | |
101 { | 118 { |
102 const std::wstring filePath = htmlFileDir + L"NotificationWindow.html"; | 119 const std::wstring filePath = htmlFileDir + L"NotificationWindow.html"; |
103 std::wifstream ifs(filePath); | 120 std::wifstream ifs(filePath); |
104 assert(ifs.good() && "Cannot open NotificationWindow.html file"); | 121 assert(ifs.good() && "Cannot open NotificationWindow.html file"); |
105 if (!ifs.good()) | 122 if (!ifs.good()) |
106 { | 123 { |
107 throw std::runtime_error("Cannot read NotificationWindow.html"); | 124 throw std::runtime_error("Cannot read NotificationWindow.html"); |
108 } | 125 } |
109 m_htmlPage.assign((std::istreambuf_iterator<wchar_t>(ifs)), std::istreambuf_it erator<wchar_t>()); | 126 m_htmlPage.assign((std::istreambuf_iterator<wchar_t>(ifs)), std::istreambuf_it erator<wchar_t>()); |
110 | 127 |
111 m_links = ToUtf16Strings(notification.GetLinks()); | 128 m_links = ToUtf16Strings(notification.GetLinks()); |
112 auto body = ToUtf16String(notification.GetMessageString()); | 129 auto body = ToUtf16String(notification.GetMessageString()); |
113 uint32_t linkIDCounter = 0; | 130 uint32_t linkIDCounter = 0; |
114 body = ReplaceMulti(body, L"<a>", [this, &linkIDCounter]()->std::wstring | 131 body = ReplaceMulti(body, L"<a>", [this, &linkIDCounter]()->std::wstring |
115 { | 132 { |
116 return L"<a href=\"#\" data-linkID=\"" + std::to_wstring(linkIDCounter++) + L"\">"; | 133 return L"<a href=\"#\" data-linkID=\"" + std::to_wstring(linkIDCounter++) + L"\">"; |
117 }); | 134 }); |
118 assert(linkIDCounter == m_links.size() && "The amount of links in the text is different from the amount of provided links"); | 135 assert(linkIDCounter == m_links.size() && "The amount of links in the text is different from the amount of provided links"); |
119 m_htmlPage = ReplaceMulti(m_htmlPage, L"<!--Title-->", ToUtf16String(notificat ion.GetTitle())); | 136 m_htmlPage = ReplaceMulti(m_htmlPage, L"<!--Title-->", ToUtf16String(notificat ion.GetTitle())); |
120 m_htmlPage = ReplaceMulti(m_htmlPage, L"<!--Body-->", body); | 137 m_htmlPage = ReplaceMulti(m_htmlPage, L"<!--Body-->", body); |
121 } | 138 } |
122 | 139 |
123 NotificationWindow::~NotificationWindow() | 140 NotificationWindow::~NotificationWindow() |
124 { | 141 { |
125 } | 142 } |
126 | 143 |
127 LRESULT NotificationWindow::OnCreate(const CREATESTRUCT* /*createStruct*/) { | 144 LRESULT NotificationWindow::OnCreate(const CREATESTRUCT* /*createStruct*/) { |
145 { | |
146 DCHandle hdc(GetDC()); | |
147 m_dpi = hdc.GetDeviceCaps(LOGPIXELSX); | |
148 } | |
128 m_bgColor.CreateSolidBrush(RGB(255, 255, 255)); | 149 m_bgColor.CreateSolidBrush(RGB(255, 255, 255)); |
129 auto windowCoords = GetWindowCoordinates(); | 150 |
130 MoveWindow(windowCoords.x, windowCoords.y, DPIAware(kWindowWidth), DPIAware(kW indowHeight)); | 151 CRect iconRect(CPoint(0, 0), CSize(kIconSize + 2 * kIconPadding, kIconSize + 2 * kIconPadding)); |
131 | 152 m_icon.Create(m_hWnd, DPIAware(iconRect), nullptr, WS_CHILD | WS_VISIBLE | SS_ BITMAP | SS_CENTERIMAGE); |
132 m_icon.Create(m_hWnd, | |
133 DPIAware(CRect(CPoint(0, 0), CSize(kIconSize, kIconSize))), | |
134 nullptr, WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_CENTERIMAGE); | |
135 LoadABPIcon(); | 153 LoadABPIcon(); |
136 | 154 |
137 m_axIE.Create(m_hWnd, DPIAware(CRect(CPoint(kIconSize, 0), CSize(kWindowWidth - kIconSize, kWindowHeight))), | 155 m_axIE.Create(m_hWnd, DPIAware(CRect(CPoint(iconRect.right, 0), CSize(kWindowW idth - iconRect.right, kWindowHeight))), |
138 L"", WS_CHILD | WS_VISIBLE, 0, kHTMLDocumentCtrlID); | 156 L"", WS_CHILD | WS_VISIBLE, 0, kHTMLDocumentCtrlID); |
139 m_axIE.CreateControl((L"mshtml:" + m_htmlPage).c_str()); | 157 m_axIE.CreateControl((L"mshtml:" + m_htmlPage).c_str()); |
140 ATL::CComPtr<IAxWinAmbientDispatch> axWinAmbient; | 158 ATL::CComPtr<IAxWinAmbientDispatch> axWinAmbient; |
141 if (SUCCEEDED(m_axIE.QueryHost(&axWinAmbient))) { | 159 if (SUCCEEDED(m_axIE.QueryHost(&axWinAmbient))) { |
142 // disable web browser context menu | 160 // disable web browser context menu |
143 axWinAmbient->put_AllowContextMenu(VARIANT_FALSE); | 161 axWinAmbient->put_AllowContextMenu(VARIANT_FALSE); |
144 // make web browser DPI aware, so the browser itself sets zoom level and | 162 // make web browser DPI aware, so the browser itself sets zoom level and |
145 // cares about rendering (not zooming) in the proper size. | 163 // cares about rendering (not zooming) in the proper size. |
146 DWORD docFlags; | 164 DWORD docFlags; |
147 axWinAmbient->get_DocHostFlags(&docFlags); | 165 axWinAmbient->get_DocHostFlags(&docFlags); |
(...skipping 13 matching lines...) Expand all Loading... | |
161 { | 179 { |
162 if (reinterpret_cast<HWND>(lParam) != m_icon) | 180 if (reinterpret_cast<HWND>(lParam) != m_icon) |
163 { | 181 { |
164 handled = FALSE; | 182 handled = FALSE; |
165 } | 183 } |
166 return reinterpret_cast<LRESULT>(static_cast<HBRUSH>(m_bgColor)); | 184 return reinterpret_cast<LRESULT>(static_cast<HBRUSH>(m_bgColor)); |
167 } | 185 } |
168 | 186 |
169 LRESULT NotificationWindow::OnClick(UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lP aram*/, BOOL& /*handled*/) | 187 LRESULT NotificationWindow::OnClick(UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lP aram*/, BOOL& /*handled*/) |
170 { | 188 { |
171 DestroyWindow(); | 189 if(m_onClickCallback) |
190 m_onClickCallback(); | |
172 return 0; | 191 return 0; |
173 } | 192 } |
174 | 193 |
175 void NotificationWindow::OnSize(uint32_t wParam, CSize size) | 194 void NotificationWindow::OnSize(uint32_t wParam, CSize size) |
176 { | 195 { |
196 if (m_icon) | |
197 { | |
198 CRect rect(CPoint(0, 0), DPIAware(CSize(kIconSize + 2 * kIconPadding, kIconS ize + 2 * kIconPadding))); | |
199 m_icon.SetWindowPos(0, &rect, SWP_NOMOVE); | |
200 } | |
177 if (m_axIE) | 201 if (m_axIE) |
178 { | 202 { |
179 size.cx -= kIconSize; | 203 size.cx -= DPIAware(kIconSize + 2 * kIconPadding); |
180 CRect rect(CPoint(0, 0), size); | 204 CRect rect(CPoint(0, 0), size); |
181 m_axIE.SetWindowPos(0, &rect, SWP_NOMOVE); | 205 m_axIE.SetWindowPos(0, &rect, SWP_NOMOVE); |
182 } | 206 } |
183 SetMsgHandled(false); | 207 SetMsgHandled(false); |
184 } | 208 } |
185 | 209 |
186 void NotificationWindow::OnDestroy() | 210 void NotificationWindow::OnDestroy() |
187 { | 211 { |
188 AtlAdviseSinkMap(this, false); | 212 AtlAdviseSinkMap(this, false); |
189 // and proceed as usual | 213 // and proceed as usual |
(...skipping 13 matching lines...) Expand all Loading... | |
203 } | 227 } |
204 ATL::CComBSTR tag; | 228 ATL::CComBSTR tag; |
205 htmlElement->get_tagName(&tag); | 229 htmlElement->get_tagName(&tag); |
206 const wchar_t expectedTag[] = { L"a" }; | 230 const wchar_t expectedTag[] = { L"a" }; |
207 if (_wcsnicmp(tag, expectedTag, min(sizeof(expectedTag), tag.Length())) != 0) { | 231 if (_wcsnicmp(tag, expectedTag, min(sizeof(expectedTag), tag.Length())) != 0) { |
208 return; | 232 return; |
209 } | 233 } |
210 auto classAttr = GetHtmlElementAttribute(*htmlElement, ATL::CComBSTR(L"class") ); | 234 auto classAttr = GetHtmlElementAttribute(*htmlElement, ATL::CComBSTR(L"class") ); |
211 if (classAttr.attributeValue == L"closeButton") | 235 if (classAttr.attributeValue == L"closeButton") |
212 { | 236 { |
213 PostMessage(WM_CLOSE); | 237 if (m_onCloseCallback) |
214 return; | 238 m_onCloseCallback(); |
215 } | 239 return; |
216 if (!linkClicked) | 240 } |
241 if (!m_onLinkClickedCallback) | |
217 { | 242 { |
218 return; | 243 return; |
219 } | 244 } |
220 auto linkIDAttr = GetHtmlElementAttribute(*htmlElement, ATL::CComBSTR(L"data-l inkID")); | 245 auto linkIDAttr = GetHtmlElementAttribute(*htmlElement, ATL::CComBSTR(L"data-l inkID")); |
221 uint32_t linkID = 0; | 246 uint32_t linkID = 0; |
222 if (!linkIDAttr.attributeValue.empty() && (linkID = std::stoi(linkIDAttr.attri buteValue)) < m_links.size()) | 247 if (!linkIDAttr.attributeValue.empty() && (linkID = std::stoi(linkIDAttr.attri buteValue)) < m_links.size()) |
223 { | 248 { |
224 linkClicked(m_links[linkID]); | 249 m_onLinkClickedCallback(m_links[linkID]); |
225 PostMessage(WM_CLOSE); | 250 if (m_onCloseCallback) |
251 m_onCloseCallback(); | |
226 } | 252 } |
227 } | 253 } |
228 | 254 |
229 void __stdcall NotificationWindow::OnHTMLDocumentSelectStart(IHTMLEventObj* even tObject) | 255 void __stdcall NotificationWindow::OnHTMLDocumentSelectStart(IHTMLEventObj* even tObject) |
230 { | 256 { |
231 if (!eventObject) | 257 if (!eventObject) |
232 return; | 258 return; |
233 // disable selecting | 259 // disable selecting |
234 eventObject->put_cancelBubble(VARIANT_TRUE); | 260 eventObject->put_cancelBubble(VARIANT_TRUE); |
235 eventObject->put_returnValue(ATL::CComVariant(false)); | 261 eventObject->put_returnValue(ATL::CComVariant(false)); |
236 } | |
237 | |
238 void NotificationWindow::OnFinalMessage(HWND) { | |
239 if (!!destroyed) { | |
240 destroyed(); | |
241 } | |
242 } | 262 } |
243 | 263 |
244 void NotificationWindow::LoadABPIcon() | 264 void NotificationWindow::LoadABPIcon() |
245 { | 265 { |
246 ScopedModule m_adblockPlusDLL; | 266 ScopedModule m_adblockPlusDLL; |
247 if (!(m_adblockPlusDLL.Open(L"AdblockPlus32.dll", LOAD_LIBRARY_AS_DATAFILE) || | 267 if (!(m_adblockPlusDLL.Open(L"AdblockPlus32.dll", LOAD_LIBRARY_AS_DATAFILE) || |
248 m_adblockPlusDLL.Open(L"AdblockPlus64.dll", LOAD_LIBRARY_AS_DATAFILE) || | 268 m_adblockPlusDLL.Open(L"AdblockPlus64.dll", LOAD_LIBRARY_AS_DATAFILE) || |
249 // for debug | 269 // for debug |
250 m_adblockPlusDLL.Open(L"AdblockPlus.dll", LOAD_LIBRARY_AS_DATAFILE))) | 270 m_adblockPlusDLL.Open(L"AdblockPlus.dll", LOAD_LIBRARY_AS_DATAFILE))) |
251 { | 271 { |
(...skipping 10 matching lines...) Expand all Loading... | |
262 if (hIcon == nullptr) | 282 if (hIcon == nullptr) |
263 { | 283 { |
264 return; | 284 return; |
265 } | 285 } |
266 | 286 |
267 HDC screenDC = m_icon.GetDC(); | 287 HDC screenDC = m_icon.GetDC(); |
268 DCHandle tmpDC(::CreateCompatibleDC(screenDC)); | 288 DCHandle tmpDC(::CreateCompatibleDC(screenDC)); |
269 ScopedObjectHandle<HBITMAP> bitmap; | 289 ScopedObjectHandle<HBITMAP> bitmap; |
270 bitmap = CreateCompatibleBitmap(screenDC, DPIAware(kIconSize), DPIAware(kIconS ize)); | 290 bitmap = CreateCompatibleBitmap(screenDC, DPIAware(kIconSize), DPIAware(kIconS ize)); |
271 HBITMAP prevBitmap = tmpDC.SelectBitmap(bitmap); | 291 HBITMAP prevBitmap = tmpDC.SelectBitmap(bitmap); |
272 RECT tmpRect = {0, 0, DPIAware(kIconSize), DPIAware(kIconSize)}; | 292 CRect tmpRect(CPoint(0, 0), DPIAware(CSize(kIconSize, kIconSize))); |
273 FillRect(tmpDC, &tmpRect, m_bgColor); | 293 FillRect(tmpDC, &tmpRect, m_bgColor); |
274 ::DrawIconEx(tmpDC, 0, 0, hIcon, DPIAware(kIconSize), DPIAware(kIconSize), 0, nullptr, DI_NORMAL); | 294 ::DrawIconEx(tmpDC, 0, 0, hIcon, tmpRect.Width(), tmpRect.Height(), 0, nullptr , DI_NORMAL); |
275 m_iconImg.Attach(bitmap.Detach()); | 295 m_iconImg.Attach(bitmap.Detach()); |
276 tmpDC.SelectBitmap(prevBitmap); | 296 tmpDC.SelectBitmap(prevBitmap); |
277 m_icon.SetBitmap(m_iconImg); | 297 m_icon.SetBitmap(m_iconImg); |
278 } | 298 } |
279 | 299 |
280 POINT NotificationWindow::GetWindowCoordinates() { | 300 POINT NotificationBorderWindow::GetWindowCoordinates() { |
281 HMONITOR primaryMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY); | 301 HMONITOR primaryMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY); |
282 { | 302 { |
283 DCHandle hdc(GetDC()); | 303 DCHandle hdc(GetDC()); |
284 m_dpi = hdc.GetDeviceCaps(LOGPIXELSX); | 304 m_dpi = hdc.GetDeviceCaps(LOGPIXELSX); |
Oleksandr
2015/08/18 11:47:40
Is this still needed, seeing that we now get dpi i
sergei
2015/08/18 11:58:40
It's a little bit odd. `GetWindowCoordinates` is a
| |
285 } | 305 } |
286 MONITORINFO monitorInfo = {}; | 306 MONITORINFO monitorInfo = {}; |
287 monitorInfo.cbSize = sizeof(monitorInfo); | 307 monitorInfo.cbSize = sizeof(monitorInfo); |
288 GetMonitorInfo(primaryMonitor, &monitorInfo); | 308 GetMonitorInfo(primaryMonitor, &monitorInfo); |
289 int windowX = monitorInfo.rcWork.right - DPIAware(kWindowWidth + kWindowMargin Right); | 309 int windowX = monitorInfo.rcWork.right - DPIAware(kWindowWidth + kWindowMargin Right); |
290 int windowY = monitorInfo.rcWork.bottom - DPIAware(kWindowHeight + kWindowMarg inBottom); | 310 int windowY = monitorInfo.rcWork.bottom - DPIAware(kWindowHeight + kWindowMarg inBottom); |
291 POINT coords = {windowX, windowY}; | 311 POINT coords = {windowX, windowY}; |
292 return coords; | 312 return coords; |
313 } | |
314 | |
315 NotificationBorderWindow::NotificationBorderWindow(const AdblockPlus::Notificati on& notification, const std::wstring& htmlFileDir) | |
316 : m_content(notification, htmlFileDir) | |
317 { | |
318 m_content.SetOnClick([this] | |
319 { | |
320 PostMessage(WM_CLOSE); | |
321 }); | |
322 m_content.SetOnClose([this] | |
323 { | |
324 PostMessage(WM_CLOSE); | |
325 }); | |
326 } | |
327 | |
328 LRESULT NotificationBorderWindow::OnCreate(const CREATESTRUCT* createStruct) | |
329 { | |
330 auto windowCoords = GetWindowCoordinates(); | |
331 MoveWindow(windowCoords.x, windowCoords.y, DPIAware(kWindowWidth), DPIAware(kW indowHeight)); | |
332 | |
333 RECT clientRect; | |
334 GetClientRect(&clientRect); | |
335 // make one pixel border | |
336 clientRect.top += 1; | |
337 clientRect.left += 1; | |
338 clientRect.bottom -= 1; | |
339 clientRect.right -= 1; | |
340 m_content.Create(m_hWnd, clientRect, nullptr, WS_CHILD | WS_VISIBLE); | |
341 auto err = GetLastError(); | |
342 SetMsgHandled(false); | |
343 return 0; | |
344 } | |
345 | |
346 void NotificationBorderWindow::OnSize(uint32_t wParam, CSize size) | |
347 { | |
348 if (m_content.IsWindow()) | |
349 { | |
350 RECT clientRect; | |
351 GetClientRect(&clientRect); | |
352 clientRect.top += 1; | |
353 clientRect.left += 1; | |
354 clientRect.bottom -= 1; | |
355 clientRect.right -= 1; | |
356 m_content.MoveWindow(&clientRect); | |
357 } | |
358 SetMsgHandled(false); | |
359 } | |
360 | |
361 LRESULT NotificationBorderWindow::OnClick(UINT /*msg*/, WPARAM /*wParam*/, LPARA M /*lParam*/, BOOL& /*handled*/) | |
362 { | |
363 DestroyWindow(); | |
364 return 0; | |
365 } | |
366 | |
367 void NotificationBorderWindow::OnFinalMessage(HWND) { | |
368 if (!!m_onDestroyedCallback) { | |
369 m_onDestroyedCallback(); | |
370 } | |
293 } | 371 } |
LEFT | RIGHT |