From ff0024fc3938f796e50dd7df240ee3986ff5c962 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 18 Sep 2019 14:09:56 +0300 Subject: more code to detect the problem with #2068 --- plugins/TabSRMM/src/stdafx.h | 1 + plugins/TabSRMM/src/taskbar.cpp | 333 +++++++++++++++++----------------------- plugins/TabSRMM/src/taskbar.h | 26 ++-- 3 files changed, 153 insertions(+), 207 deletions(-) (limited to 'plugins') diff --git a/plugins/TabSRMM/src/stdafx.h b/plugins/TabSRMM/src/stdafx.h index 8aef3fe071..9b451112b5 100644 --- a/plugins/TabSRMM/src/stdafx.h +++ b/plugins/TabSRMM/src/stdafx.h @@ -47,6 +47,7 @@ #include #include +#include #include #include diff --git a/plugins/TabSRMM/src/taskbar.cpp b/plugins/TabSRMM/src/taskbar.cpp index 7e87787958..f4d2935761 100644 --- a/plugins/TabSRMM/src/taskbar.cpp +++ b/plugins/TabSRMM/src/taskbar.cpp @@ -53,22 +53,17 @@ #include "stdafx.h" -/** - * maps MUC event types to icon names for retrieving the "big" icons - * while generating task bar thumbnails. - * used by getMUCBigICon() - */ +///////////////////////////////////////////////////////////////////////////////////////// +// maps MUC event types to icon names for retrieving the "big" icons +// while generating task bar thumbnails. +// used by getMUCBigICon() CTaskbarInteract* Win7Taskbar = nullptr; -/** - * set the overlay icon for a task bar button. Used for typing notifications and incoming - * message indicator. - * - * @param hwndDlg HWND: container window handle - * @param lParam LPARAM: icon handle - * @return true if icon has been set and taskbar will accept it, false otherwise - */ +///////////////////////////////////////////////////////////////////////////////////////// +// sets the overlay icon for a task bar button. Used for typing notifications and incoming +// message indicator. + bool CTaskbarInteract::setOverlayIcon(HWND hwndDlg, LPARAM lParam) const { if (m_pTaskbarInterface && m_isEnabled && m_fHaveLargeicons) { @@ -78,10 +73,10 @@ bool CTaskbarInteract::setOverlayIcon(HWND hwndDlg, LPARAM lParam) const return false; } -/** - * check the task bar status for "large icon mode". - * @return bool: true if large icons are in use, false otherwise - */ +///////////////////////////////////////////////////////////////////////////////////////// +// checks the task bar status for "large icon mode". +// @return bool: true if large icons are in use, false otherwise + bool CTaskbarInteract::haveLargeIcons() { m_fHaveLargeicons = false; @@ -113,10 +108,9 @@ bool CTaskbarInteract::haveLargeIcons() return(m_fHaveLargeicons); } -/** - * removes the overlay icon for the given container window - * @param hwndDlg HWND: window handle - */ +///////////////////////////////////////////////////////////////////////////////////////// +// removes the overlay icon for the given container window + void CTaskbarInteract::clearOverlayIcon(HWND hwndDlg) const { if (m_pTaskbarInterface && m_isEnabled) @@ -130,12 +124,10 @@ LONG CTaskbarInteract::updateMetrics() return(m_IconSize); } -/** - * register a new task bar button ("tab") for the button group hwndContainer - * (one of the top level message windows) - * @param hwndTab proxy window handle - * @param hwndContainer a message container window - */ +///////////////////////////////////////////////////////////////////////////////////////// +// register a new task bar button ("tab") for the button group hwndContainer +// (one of the top level message windows) + void CTaskbarInteract::registerTab(const HWND hwndTab, const HWND hwndContainer) const { if (m_isEnabled) { @@ -144,41 +136,32 @@ void CTaskbarInteract::registerTab(const HWND hwndTab, const HWND hwndContainer) } } -/** - * remove a previously registered proxy window. The destructor of the proxy - * window class is using this before destroying the proxy window itself. - * @param hwndTab proxy window handle - */ +///////////////////////////////////////////////////////////////////////////////////////// +// remove a previously registered proxy window. The destructor of the proxy +// window class is using this before destroying the proxy window itself. +// @param hwndTab proxy window handle + void CTaskbarInteract::unRegisterTab(const HWND hwndTab) const { if (m_isEnabled) m_pTaskbarInterface->UnregisterTab(hwndTab); } -/** - * set a tab as active. The active thumbnail will appear with a slightly - * different background and transparency. - * - * @param hwndTab window handle of the PROXY window to activate - * (don't use the real window handle of the message - * tab, because it is not a toplevel window). - * @param hwndGroup window group to which it belongs (usually, the - * container window handle). - */ +///////////////////////////////////////////////////////////////////////////////////////// +// set a tab as active. The active thumbnail will appear with a slightly +// different background and transparency. + void CTaskbarInteract::SetTabActive(const HWND hwndTab, const HWND hwndGroup) const { if (m_isEnabled) m_pTaskbarInterface->SetTabActive(hwndTab, hwndGroup, 0); } -/** - * This is called from the broadcasted WM_DWMCOMPOSITIONCHANGED event by all messages - * sessions. It checks and, if needed, destroys or creates a proxy object, based on - * the status of the DWM - * @param dat session window data - * - * static member function - */ +///////////////////////////////////////////////////////////////////////////////////////// +// This is called from the broadcasted WM_DWMCOMPOSITIONCHANGED event by all messages +// sessions. It checks and, if needed, destroys or creates a proxy object, based on +// the status of the DWM + void CMsgDialog::VerifyProxy() { if (IsWinVer7Plus() && PluginConfig.m_useAeroPeek) { @@ -200,16 +183,15 @@ void CMsgDialog::VerifyProxy() } } -/** - * create the proxy (toplevel) window required to show per tab thumbnails - * and previews for a message session. - * each tab has one invisible proxy window - */ +///////////////////////////////////////////////////////////////////////////////////////// +// create the proxy (toplevel) window required to show per tab thumbnails +// and previews for a message session. +// each tab has one invisible proxy window + CProxyWindow::CProxyWindow(CMsgDialog *dat) : m_dat(dat) { - if (m_dat == nullptr) - DebugBreak(); + m_hBreakPoint = ::SetHardwareBreakpoint(GetCurrentThread(), HWBRK_TYPE_WRITE, HWBRK_SIZE_4, &m_dat); m_hwndProxy = ::CreateWindowEx(/*WS_EX_TOOLWINDOW | */WS_EX_NOACTIVATE, PROXYCLASSNAME, L"", WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION, -32000, -32000, 10, 10, nullptr, nullptr, g_plugin.getInst(), (LPVOID)this); @@ -228,14 +210,15 @@ CProxyWindow::~CProxyWindow() { Win7Taskbar->unRegisterTab(m_hwndProxy); ::DestroyWindow(m_hwndProxy); + ::RemoveHardwareBreakpoint(m_hBreakPoint); delete m_thumb; } -/** - * verify status of DWM when system broadcasts a WM_DWMCOMPOSITIONCHANGED message - * delete thumbnails, if no longer needed - */ +///////////////////////////////////////////////////////////////////////////////////////// +// verify status of DWM when system broadcasts a WM_DWMCOMPOSITIONCHANGED message +// delete thumbnails, if no longer needed + void CProxyWindow::verifyDwmState() { if (!M.isDwmActive()) { @@ -253,13 +236,10 @@ void CProxyWindow::verifyDwmState() } } -/** - * send a thumbnail to the DWM. If required, refresh it first. - * called by WM_DWMSENDICONICTHUMBNAIL handler. - * - * @param width thumbnail width as requested by DWM via lParam - * @param height thumbnail height as requested by DWM via lParam - */ +///////////////////////////////////////////////////////////////////////////////////////// +// send a thumbnail to the DWM. If required, refresh it first. +// called by WM_DWMSENDICONICTHUMBNAIL handler. + void CProxyWindow::sendThumb(LONG width, LONG height) { if (nullptr == m_thumb) { @@ -276,14 +256,13 @@ void CProxyWindow::sendThumb(LONG width, LONG height) CMimAPI::m_pfnDwmSetIconicThumbnail(m_hwndProxy, m_thumb->getHBM(), DWM_SIT_DISPLAYFRAME); } -/** - * send a live preview image of a given message session to the DWM. - * called by WM_DWMSENDICONICLIVEPREVIEWBITMAP on DWM's request. - * - * The bitmap can be deleted after submitting it, because the DWM - * will cache a copy of it (and re-request it when its own bitmap cache - * was purged). - */ +///////////////////////////////////////////////////////////////////////////////////////// +// send a live preview image of a given message session to the DWM. +// called by WM_DWMSENDICONICLIVEPREVIEWBITMAP on DWM's request. +// +// The bitmap can be deleted after submitting it, because the DWM +// will cache a copy of it (and re-request it when its own bitmap cache was purged). + void CProxyWindow::sendPreview() { if (m_dat->m_pContainer == nullptr) @@ -311,11 +290,9 @@ void CProxyWindow::sendPreview() ::SendMessage(m_dat->GetHwnd(), WM_SIZE, 0, 0); m_dat->DM_ScrollToBottom(0, 1); } - /* - * a minimized container has a null rect as client area, so do not use it - * use the last known client area size instead. - */ - + + // a minimized container has a null rect as client area, so do not use it + // use the last known client area size instead. if (!::IsIconic(m_dat->m_pContainer->m_hwnd)) { ::GetWindowRect(m_dat->m_pContainer->m_hwndActive, &rcLog); ::GetClientRect(m_dat->m_pContainer->m_hwnd, &rcContainer); @@ -353,10 +330,7 @@ void CProxyWindow::sendPreview() LRESULT first = ::SendMessage(hwndRich, EM_CHARFROMPOS, 0, LPARAM(&ptOrigin)); - /* - * paint the content of the message log control into a separate bitmap without - * transparency - */ + // paint the content of the message log control into a separate bitmap without transparency HDC hdcRich = ::CreateCompatibleDC(dc); HBITMAP hbmRich = CSkin::CreateAeroCompatibleBitmap(rcRich, hdcRich); HBITMAP hbmRichOld = reinterpret_cast(::SelectObject(hdcRich, hbmRich)); @@ -407,16 +381,13 @@ void CProxyWindow::sendPreview() ::DeleteObject(hbm); } -/** - * set the large icon for the thumbnail. This is mostly used by group chats - * to indicate last active event in the session. - * - * hIcon may be 0 to remove a custom big icon. In that case, the renderer - * will try to figure out a suitable one, based on session data. - * - * @param hIcon icon handle (should be a 32x32 icon) - * @param fInvalidate invalidate the thumbnail (default value = true) - */ +///////////////////////////////////////////////////////////////////////////////////////// +// set the large icon for the thumbnail. This is mostly used by group chats +// to indicate last active event in the session. +// +// hIcon may be 0 to remove a custom big icon. In that case, the renderer +// will try to figure out a suitable one, based on session data. + void CProxyWindow::setBigIcon(const HICON hIcon, bool fInvalidate) { m_hBigIcon = hIcon; @@ -424,15 +395,12 @@ void CProxyWindow::setBigIcon(const HICON hIcon, bool fInvalidate) Invalidate(); } -/** - * set a overlay icon for the thumbnail. This is mostly used by group chats - * to indicate last active event in the session. - * - * hIcon may be 0 to remove a custom overlay icon. - * - * @param hIcon icon handle (should be a 16x16 icon) - * @param fInvalidate invalidate the thumbnail (default value = true) - */ +///////////////////////////////////////////////////////////////////////////////////////// +// set a overlay icon for the thumbnail. This is mostly used by group chats +// to indicate last active event in the session. +// +// hIcon may be 0 to remove a custom overlay icon. + void CProxyWindow::setOverlayIcon(const HICON hIcon, bool fInvalidate) { m_hOverlayIcon = hIcon; @@ -440,34 +408,32 @@ void CProxyWindow::setOverlayIcon(const HICON hIcon, bool fInvalidate) Invalidate(); } -/** - * update the (small) thumbnail icon in front of the title string - * @param hIcon new icon handle - */ +///////////////////////////////////////////////////////////////////////////////////////// +// update the (small) thumbnail icon in front of the title string + void CProxyWindow::updateIcon(const HICON hIcon) const { if (m_hwndProxy && hIcon) ::SendMessage(m_hwndProxy, WM_SETICON, ICON_SMALL, LPARAM(hIcon)); } -/** - * set the task bar button ("tab") active. This activates the proxy - * window as a sub-window of the (top level) container window. - * This is called whenever the active message tab or window changes - */ +///////////////////////////////////////////////////////////////////////////////////////// +// set the task bar button ("tab") active. This activates the proxy +// window as a sub-window of the (top level) container window. +// This is called whenever the active message tab or window changes + void CProxyWindow::activateTab() const { Win7Taskbar->SetTabActive(m_hwndProxy, m_dat->m_pContainer->m_hwnd); } -/** - * invalidate the thumbnail, it will be recreated at the next request - * by the DWM - * - * this is called from several places whenever a relevant information, - * represented in a thumbnail image, has changed. - * - * also tell the DWM that it must request a new thumb. - */ + +///////////////////////////////////////////////////////////////////////////////////////// +// invalidate the thumbnail, it will be recreated at the next request by the DWM +// +// this is called from several places whenever a relevant information, +// represented in a thumbnail image, has changed. +// also tells the DWM that it must request a new thumb. + void CProxyWindow::Invalidate() const { if (m_thumb) { @@ -512,27 +478,24 @@ LRESULT CALLBACK CProxyWindow::stubWndProc(HWND hWnd, UINT msg, WPARAM wParam, L return ::DefWindowProc(hWnd, msg, wParam, lParam); } -/** - * window procedure for the proxy window - */ +///////////////////////////////////////////////////////////////////////////////////////// +// window procedure for the proxy window + LRESULT CALLBACK CProxyWindow::wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CLOSE: - if (m_dat) { - SendMessage(m_dat->GetHwnd(), WM_CLOSE, 1, 2); - + SendMessage(m_dat->GetHwnd(), WM_CLOSE, 1, 2); + { TContainerData *pC = m_dat->m_pContainer; if (!IsIconic(pC->m_hwnd)) SetForegroundWindow(pC->m_hwnd); } return 0; - /* - * proxy window was activated by clicking on the thumbnail. Send this - * to the real message window. - */ case WM_ACTIVATE: + // proxy window was activated by clicking on the thumbnail. Send this + // to the real message window. if (WA_ACTIVE == wParam) { if (IsWindow(m_dat->GetHwnd())) ::PostMessage(m_dat->GetHwnd(), DM_ACTIVATEME, 0, 0); @@ -555,13 +518,9 @@ LRESULT CALLBACK CProxyWindow::wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARA return ::DefWindowProc(hWnd, msg, wParam, lParam); } -/** - * base thumbnail class. Create the background and common parts for a - * thumbnail - * - * @param _p owner proxy window object - * @return - */ +///////////////////////////////////////////////////////////////////////////////////////// +// base thumbnail class. Create the background and common parts for a thumbnail + CThumbBase::CThumbBase(const CProxyWindow* _p) : m_isValid(false) { @@ -570,11 +529,11 @@ CThumbBase::CThumbBase(const CProxyWindow* _p) : renderBase(); } -/** - * render base for a thumbnail. This creates the background, the large icon - * and the basic status mode text. It also divides the thumbnail rectangle - * into a few content rectangles used later by the content renderer. - */ +///////////////////////////////////////////////////////////////////////////////////////// +// render base for a thumbnail. This creates the background, the large icon +// and the basic status mode text. It also divides the thumbnail rectangle +// into a few content rectangles used later by the content renderer. + void CThumbBase::renderBase() { HICON hIcon = nullptr; @@ -659,9 +618,9 @@ void CThumbBase::renderBase() m_cy = m_rcIcon.bottom - m_rcIcon.top; } -/** - * divide space into content rectangles for normal thumbnails - */ +///////////////////////////////////////////////////////////////////////////////////////// +// divide space into content rectangles for normal thumbnails + void CThumbBase::setupRect() { if (!m_pWnd->getDat()->isChat()) { @@ -684,10 +643,9 @@ void CThumbBase::setupRect() } } -/** - * destroy the thumbnail object. Just delete the bitmap we cached - * @return - */ +///////////////////////////////////////////////////////////////////////////////////////// +// destroy the thumbnail object. Just delete the bitmap we cached + CThumbBase::~CThumbBase() { if (m_hbmThumb) { @@ -697,21 +655,18 @@ CThumbBase::~CThumbBase() } } -/** - * create a IM session thumbnail. base class will create the - * bitmap and render the background. - * - * @param _p our owner (CProxyWindow object) - */ +///////////////////////////////////////////////////////////////////////////////////////// +// create a IM session thumbnail. base class will create the bitmap and render the background. + CThumbIM::CThumbIM(const CProxyWindow* _p) : CThumbBase(_p) { renderContent(); setValid(true); } -/** - * update the thumbnail, render everything and set it valid - */ +///////////////////////////////////////////////////////////////////////////////////////// +// update the thumbnail, render everything and set it valid + void CThumbIM::update() { renderBase(); @@ -719,11 +674,10 @@ void CThumbIM::update() setValid(true); } -/** - * render the content for an IM chat session thumbnail - * m_hdc etc. must already be initialized (done by the constructor) - * background had been already rendered - */ +///////////////////////////////////////////////////////////////////////////////////////// +// render the content for an IM chat session thumbnail m_hdc etc. +// must already be initialized (done by the constructor) background had been already rendered + void CThumbIM::renderContent() { double dNewWidth = 0.0, dNewHeight = 0.0; @@ -754,10 +708,8 @@ void CThumbIM::renderContent() ::DeleteDC(dc); m_rcBottom.bottom -= 16; - /* - * status message and bottom line (either UID or nick name, depending on - * task bar grouping mode). For chat rooms, it is the topic. - */ + // status message and bottom line (either UID or nick name, depending on + // task bar grouping mode). For chat rooms, it is the topic. if ((m_rcBottom.bottom - m_rcBottom.top) < 2 * m_sz.cy) m_dtFlags |= DT_SINGLELINE; @@ -773,12 +725,10 @@ void CThumbIM::renderContent() CSkin::RenderText(m_hdc, m_dat->m_hTheme, Win7Taskbar->haveAlwaysGroupingMode() ? m_dat->m_cache->getUIN() : m_dat->m_cache->getNick(), &m_rcBottom, m_dtFlags | DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS, 10, 0, true); - /* - * finalize it - * do NOT delete the bitmap, the dwm will need the handle - * m_hbm is deleted when a new thumbnail is generated on dwm's request. - * this is not a leak! - */ + // finalize it + // do NOT delete the bitmap, the dwm will need the handle + // m_hbm is deleted when a new thumbnail is generated on dwm's request. + // this is not a leak! if (m_hOldFont) ::SelectObject(m_hdc, m_hOldFont); @@ -786,13 +736,10 @@ void CThumbIM::renderContent() ::DeleteDC(m_hdc); } -/** - * create a MUC session thumbnail. base class will create the - * bitmap and render the background. - * - * @param _p our owner (CProxyWindow object) - * @return - */ +///////////////////////////////////////////////////////////////////////////////////////// +// create a MUC session thumbnail. base class will create the +// bitmap and render the background. + CThumbMUC::CThumbMUC(const CProxyWindow* _p, SESSION_INFO *_si) : CThumbBase(_p), si(_si) @@ -801,9 +748,9 @@ CThumbMUC::CThumbMUC(const CProxyWindow* _p, SESSION_INFO *_si) setValid(true); } -/** - * update an invalidated thumbnail - */ +///////////////////////////////////////////////////////////////////////////////////////// +// update an invalidated thumbnail + void CThumbMUC::update() { renderBase(); @@ -811,9 +758,9 @@ void CThumbMUC::update() setValid(true); } -/** - * render content area for a MUC thumbnail - */ +///////////////////////////////////////////////////////////////////////////////////////// +// render content area for a MUC thumbnail + void CThumbMUC::renderContent() { if (si == nullptr) @@ -870,12 +817,10 @@ void CThumbMUC::renderContent() CSkin::RenderText(m_hdc, m_dat->m_hTheme, szStatusMsg, &m_rcBottom, DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | m_dtFlags, 10, 0, true); - /* - * finalize it - * do NOT delete the bitmap, the dwm will need the handle - * m_hbm is deleted when a new thumbnail is generated on dwm's request. - * this is not a leak! - */ + // finalize it + // do NOT delete the bitmap, the dwm will need the handle + // m_hbm is deleted when a new thumbnail is generated on dwm's request. + // this is not a leak! if (m_hOldFont) ::SelectObject(m_hdc, m_hOldFont); diff --git a/plugins/TabSRMM/src/taskbar.h b/plugins/TabSRMM/src/taskbar.h index 3ee461ff1a..4d8fa4802f 100644 --- a/plugins/TabSRMM/src/taskbar.h +++ b/plugins/TabSRMM/src/taskbar.h @@ -97,6 +97,19 @@ private: class CProxyWindow : public MZeroedObject { + CMsgDialog *m_dat; + + HWND m_hwndProxy; + LONG m_width, m_height; + HICON m_hBigIcon, m_hOverlayIcon; + HANDLE m_hBreakPoint; + + LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + + void sendThumb(LONG width, LONG height); + void sendPreview(); + CThumbBase *m_thumb; + public: CProxyWindow(CMsgDialog *dat); ~CProxyWindow(); @@ -117,19 +130,6 @@ public: __inline const HICON getOverlayIcon() const { return m_hOverlayIcon; } static LRESULT CALLBACK stubWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -private: - CMsgDialog *m_dat; - - HWND m_hwndProxy; - LONG m_width, m_height; - HICON m_hBigIcon, m_hOverlayIcon; - - LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - - void sendThumb(LONG width, LONG height); - void sendPreview(); - CThumbBase *m_thumb; }; class CTaskbarInteract -- cgit v1.2.3