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:
parent
4576b30c37
commit
d1a60e848e
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue