Reverted task bar code to 1.0.15 version. That used a window in

its own thread for handling messages.  It seems to fix most of
the task bar bugs but there's still an hourglass cursor on NT
when using the popup menu.
This commit is contained in:
crs 2004-03-31 22:15:13 +00:00
parent 4576b30c37
commit d1a60e848e
3 changed files with 160 additions and 40 deletions

View File

@ -41,45 +41,43 @@ CArchTaskBarWindows::CArchTaskBarWindows(void* appInstance) :
// save app instance // save app instance
s_appInstance = reinterpret_cast<HINSTANCE>(appInstance); s_appInstance = reinterpret_cast<HINSTANCE>(appInstance);
// register the task bar restart message // we need a mutex
m_taskBarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); m_mutex = ARCH->newMutex();
// register a window class // and a condition variable which uses the above mutex
WNDCLASSEX classInfo; m_ready = false;
classInfo.cbSize = sizeof(classInfo); m_condVar = ARCH->newCondVar();
classInfo.style = CS_NOCLOSE;
classInfo.lpfnWndProc = &CArchTaskBarWindows::staticWndProc;
classInfo.cbClsExtra = 0;
classInfo.cbWndExtra = sizeof(CArchTaskBarWindows*);
classInfo.hInstance = s_appInstance;
classInfo.hIcon = NULL;
classInfo.hCursor = NULL;
classInfo.hbrBackground = NULL;
classInfo.lpszMenuName = NULL;
classInfo.lpszClassName = TEXT("SynergyTaskBar");
classInfo.hIconSm = NULL;
m_windowClass = RegisterClassEx(&classInfo);
// create window // we're going to want to get a result from the thread we're
m_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, // about to create to know if it initialized successfully.
reinterpret_cast<LPCTSTR>(m_windowClass), // so we lock the condition variable.
TEXT("Synergy Task Bar"), ARCH->lockMutex(m_mutex);
WS_POPUP,
0, 0, 1, 1, // open a window and run an event loop in a separate thread.
NULL, // this has to happen in a separate thread because if we
NULL, // create a window on the current desktop with the current
s_appInstance, // thread then the current thread won't be able to switch
reinterpret_cast<void*>(this)); // desktops if it needs to.
m_thread = ARCH->newThread(&CArchTaskBarWindows::threadEntry, this);
// wait for child thread
while (!m_ready) {
ARCH->waitCondVar(m_condVar, m_mutex, -1.0);
}
// ready
ARCH->unlockMutex(m_mutex);
} }
CArchTaskBarWindows::~CArchTaskBarWindows() CArchTaskBarWindows::~CArchTaskBarWindows()
{ {
if (m_hwnd != NULL) { if (m_thread != NULL) {
removeAllIcons(); PostMessage(m_hwnd, WM_QUIT, 0, 0);
DestroyWindow(m_hwnd); ARCH->wait(m_thread, -1.0);
ARCH->closeThread(m_thread);
} }
UnregisterClass((LPCTSTR)m_windowClass, s_appInstance); ARCH->closeCondVar(m_condVar);
ARCH->closeMutex(m_mutex);
s_instance = NULL; s_instance = NULL;
} }
@ -98,10 +96,6 @@ CArchTaskBarWindows::removeDialog(HWND hwnd)
void void
CArchTaskBarWindows::addReceiver(IArchTaskBarReceiver* receiver) CArchTaskBarWindows::addReceiver(IArchTaskBarReceiver* receiver)
{ {
if (m_hwnd == NULL) {
return;
}
// ignore bogus receiver // ignore bogus receiver
if (receiver == NULL) { if (receiver == NULL) {
return; return;
@ -176,43 +170,53 @@ CArchTaskBarWindows::recycleID(UINT id)
void void
CArchTaskBarWindows::addIcon(UINT id) CArchTaskBarWindows::addIcon(UINT id)
{ {
ARCH->lockMutex(m_mutex);
CIDToReceiverMap::const_iterator index = m_idTable.find(id); CIDToReceiverMap::const_iterator index = m_idTable.find(id);
if (index != m_idTable.end()) { if (index != m_idTable.end()) {
modifyIconNoLock(index->second, NIM_ADD); modifyIconNoLock(index->second, NIM_ADD);
} }
ARCH->unlockMutex(m_mutex);
} }
void void
CArchTaskBarWindows::removeIcon(UINT id) CArchTaskBarWindows::removeIcon(UINT id)
{ {
ARCH->lockMutex(m_mutex);
removeIconNoLock(id); removeIconNoLock(id);
ARCH->unlockMutex(m_mutex);
} }
void void
CArchTaskBarWindows::updateIcon(UINT id) CArchTaskBarWindows::updateIcon(UINT id)
{ {
ARCH->lockMutex(m_mutex);
CIDToReceiverMap::const_iterator index = m_idTable.find(id); CIDToReceiverMap::const_iterator index = m_idTable.find(id);
if (index != m_idTable.end()) { if (index != m_idTable.end()) {
modifyIconNoLock(index->second, NIM_MODIFY); modifyIconNoLock(index->second, NIM_MODIFY);
} }
ARCH->unlockMutex(m_mutex);
} }
void void
CArchTaskBarWindows::addAllIcons() CArchTaskBarWindows::addAllIcons()
{ {
ARCH->lockMutex(m_mutex);
for (CReceiverToInfoMap::const_iterator index = m_receivers.begin(); for (CReceiverToInfoMap::const_iterator index = m_receivers.begin();
index != m_receivers.end(); ++index) { index != m_receivers.end(); ++index) {
modifyIconNoLock(index, NIM_ADD); modifyIconNoLock(index, NIM_ADD);
} }
ARCH->unlockMutex(m_mutex);
} }
void void
CArchTaskBarWindows::removeAllIcons() CArchTaskBarWindows::removeAllIcons()
{ {
ARCH->lockMutex(m_mutex);
for (CReceiverToInfoMap::const_iterator index = m_receivers.begin(); for (CReceiverToInfoMap::const_iterator index = m_receivers.begin();
index != m_receivers.end(); ++index) { index != m_receivers.end(); ++index) {
removeIconNoLock(index->second.m_id); removeIconNoLock(index->second.m_id);
} }
ARCH->unlockMutex(m_mutex);
} }
void void
@ -305,6 +309,49 @@ CArchTaskBarWindows::handleIconMessage(
} }
} }
bool
CArchTaskBarWindows::processDialogs(MSG* msg)
{
// only one thread can be in this method on any particular object
// at any given time. that's not a problem since only our event
// loop calls this method and there's just one of those.
ARCH->lockMutex(m_mutex);
// remove removed dialogs
m_dialogs.erase(false);
// merge added dialogs into the dialog list
for (CDialogs::const_iterator index = m_addedDialogs.begin();
index != m_addedDialogs.end(); ++index) {
m_dialogs.insert(std::make_pair(index->first, index->second));
}
m_addedDialogs.clear();
ARCH->unlockMutex(m_mutex);
// check message against all dialogs until one handles it.
// note that we don't hold a lock while checking because
// the message is processed and may make calls to this
// object. that's okay because addDialog() and
// removeDialog() don't change the map itself (just the
// values of some elements).
ARCH->lockMutex(m_mutex);
for (CDialogs::const_iterator index = m_dialogs.begin();
index != m_dialogs.end(); ++index) {
if (index->second) {
ARCH->unlockMutex(m_mutex);
if (IsDialogMessage(index->first, msg)) {
return true;
}
ARCH->lockMutex(m_mutex);
}
}
ARCH->unlockMutex(m_mutex);
return false;
}
LRESULT LRESULT
CArchTaskBarWindows::wndProc(HWND hwnd, CArchTaskBarWindows::wndProc(HWND hwnd,
UINT msg, WPARAM wParam, LPARAM lParam) UINT msg, WPARAM wParam, LPARAM lParam)
@ -375,3 +422,70 @@ CArchTaskBarWindows::staticWndProc(HWND hwnd, UINT msg,
return DefWindowProc(hwnd, msg, wParam, lParam); return DefWindowProc(hwnd, msg, wParam, lParam);
} }
} }
void
CArchTaskBarWindows::threadMainLoop()
{
// register the task bar restart message
m_taskBarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
// register a window class
WNDCLASSEX classInfo;
classInfo.cbSize = sizeof(classInfo);
classInfo.style = CS_NOCLOSE;
classInfo.lpfnWndProc = &CArchTaskBarWindows::staticWndProc;
classInfo.cbClsExtra = 0;
classInfo.cbWndExtra = sizeof(CArchTaskBarWindows*);
classInfo.hInstance = s_appInstance;
classInfo.hIcon = NULL;
classInfo.hCursor = NULL;
classInfo.hbrBackground = NULL;
classInfo.lpszMenuName = NULL;
classInfo.lpszClassName = TEXT("SynergyTaskBar");
classInfo.hIconSm = NULL;
ATOM windowClass = RegisterClassEx(&classInfo);
// create window
m_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW,
reinterpret_cast<LPCTSTR>(windowClass),
TEXT("Synergy Task Bar"),
WS_POPUP,
0, 0, 1, 1,
NULL,
NULL,
s_appInstance,
reinterpret_cast<void*>(this));
// signal ready
ARCH->lockMutex(m_mutex);
m_ready = true;
ARCH->broadcastCondVar(m_condVar);
ARCH->unlockMutex(m_mutex);
// handle failure
if (m_hwnd == NULL) {
UnregisterClass((LPCTSTR)windowClass, s_appInstance);
return;
}
// main loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!processDialogs(&msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// clean up
removeAllIcons();
DestroyWindow(m_hwnd);
UnregisterClass((LPCTSTR)windowClass, s_appInstance);
}
void*
CArchTaskBarWindows::threadEntry(void* self)
{
reinterpret_cast<CArchTaskBarWindows*>(self)->threadMainLoop();
return NULL;
}

View File

@ -18,6 +18,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include "IArchTaskBar.h" #include "IArchTaskBar.h"
#include "IArchMultithread.h"
#include "stdmap.h" #include "stdmap.h"
#include "stdvector.h" #include "stdvector.h"
#include <windows.h> #include <windows.h>
@ -77,13 +78,21 @@ private:
LRESULT wndProc(HWND, UINT, WPARAM, LPARAM); LRESULT wndProc(HWND, UINT, WPARAM, LPARAM);
static LRESULT CALLBACK static LRESULT CALLBACK
staticWndProc(HWND, UINT, WPARAM, LPARAM); staticWndProc(HWND, UINT, WPARAM, LPARAM);
void threadMainLoop();
static void* threadEntry(void*);
private: private:
static CArchTaskBarWindows* s_instance; static CArchTaskBarWindows* s_instance;
static HINSTANCE s_appInstance; static HINSTANCE s_appInstance;
// multithread data
CArchMutex m_mutex;
CArchCond m_condVar;
bool m_ready;
int m_result;
CArchThread m_thread;
// child thread data // child thread data
ATOM m_windowClass;
HWND m_hwnd; HWND m_hwnd;
UINT m_taskBarRestart; UINT m_taskBarRestart;

View File

@ -27,9 +27,6 @@ though each operation can be a no-op.
*/ */
class IArchTaskBar : public IInterface { class IArchTaskBar : public IInterface {
public: public:
// Event data is architecture dependent
typedef void* Event;
//! @name manipulators //! @name manipulators
//@{ //@{