source: trunk/synergy/cmd/synergys/CMSWindowsServerTaskBarReceiver.cpp@ 3607

Last change on this file since 3607 was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 8.7 KB
Line 
1/*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2003 Chris Schoeneman
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file COPYING that should have accompanied this file.
8 *
9 * This package 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
15#include "CMSWindowsServerTaskBarReceiver.h"
16#include "CServer.h"
17#include "CMSWindowsClipboard.h"
18#include "IEventQueue.h"
19#include "LogOutputters.h"
20#include "BasicTypes.h"
21#include "CArch.h"
22#include "CArchTaskBarWindows.h"
23#include "resource.h"
24
25extern CEvent::Type getReloadConfigEvent();
26extern CEvent::Type getForceReconnectEvent();
27
28//
29// CMSWindowsServerTaskBarReceiver
30//
31
32const UINT CMSWindowsServerTaskBarReceiver::s_stateToIconID[kMaxState] =
33{
34 IDI_TASKBAR_NOT_RUNNING,
35 IDI_TASKBAR_NOT_WORKING,
36 IDI_TASKBAR_NOT_CONNECTED,
37 IDI_TASKBAR_CONNECTED
38};
39
40CMSWindowsServerTaskBarReceiver::CMSWindowsServerTaskBarReceiver(
41 HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) :
42 CServerTaskBarReceiver(),
43 m_appInstance(appInstance),
44 m_window(NULL),
45 m_logBuffer(logBuffer)
46{
47 for (UInt32 i = 0; i < kMaxState; ++i) {
48 m_icon[i] = loadIcon(s_stateToIconID[i]);
49 }
50 m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR));
51
52 // don't create the window yet. we'll create it on demand. this
53 // has the side benefit of being created in the thread used for
54 // the task bar. that's good because it means the existence of
55 // the window won't prevent changing the main thread's desktop.
56
57 // add ourself to the task bar
58 ARCH->addReceiver(this);
59}
60
61CMSWindowsServerTaskBarReceiver::~CMSWindowsServerTaskBarReceiver()
62{
63 ARCH->removeReceiver(this);
64 for (UInt32 i = 0; i < kMaxState; ++i) {
65 deleteIcon(m_icon[i]);
66 }
67 DestroyMenu(m_menu);
68 destroyWindow();
69}
70
71void
72CMSWindowsServerTaskBarReceiver::showStatus()
73{
74 // create the window
75 createWindow();
76
77 // lock self while getting status
78 lock();
79
80 // get the current status
81 std::string status = getToolTip();
82
83 // get the connect clients, if any
84 const CClients& clients = getClients();
85
86 // done getting status
87 unlock();
88
89 // update dialog
90 HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS);
91 SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str());
92 child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_CLIENTS);
93 SendMessage(child, LB_RESETCONTENT, 0, 0);
94 for (CClients::const_iterator index = clients.begin();
95 index != clients.end(); ) {
96 const char* client = index->c_str();
97 if (++index == clients.end()) {
98 SendMessage(child, LB_ADDSTRING, 0, (LPARAM)client);
99 }
100 else {
101 SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)client);
102 }
103 }
104
105 if (!IsWindowVisible(m_window)) {
106 // position it by the mouse
107 POINT cursorPos;
108 GetCursorPos(&cursorPos);
109 RECT windowRect;
110 GetWindowRect(m_window, &windowRect);
111 int x = cursorPos.x;
112 int y = cursorPos.y;
113 int fw = GetSystemMetrics(SM_CXDLGFRAME);
114 int fh = GetSystemMetrics(SM_CYDLGFRAME);
115 int ww = windowRect.right - windowRect.left;
116 int wh = windowRect.bottom - windowRect.top;
117 int sw = GetSystemMetrics(SM_CXFULLSCREEN);
118 int sh = GetSystemMetrics(SM_CYFULLSCREEN);
119 if (fw < 1) {
120 fw = 1;
121 }
122 if (fh < 1) {
123 fh = 1;
124 }
125 if (x + ww - fw > sw) {
126 x -= ww - fw;
127 }
128 else {
129 x -= fw;
130 }
131 if (x < 0) {
132 x = 0;
133 }
134 if (y + wh - fh > sh) {
135 y -= wh - fh;
136 }
137 else {
138 y -= fh;
139 }
140 if (y < 0) {
141 y = 0;
142 }
143 SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh,
144 SWP_SHOWWINDOW);
145 }
146}
147
148void
149CMSWindowsServerTaskBarReceiver::runMenu(int x, int y)
150{
151 // do popup menu. we need a window to pass to TrackPopupMenu().
152 // the SetForegroundWindow() and SendMessage() calls around
153 // TrackPopupMenu() are to get the menu to be dismissed when
154 // another window gets activated and are just one of those
155 // win32 weirdnesses.
156 createWindow();
157 SetForegroundWindow(m_window);
158 HMENU menu = GetSubMenu(m_menu, 0);
159 SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE);
160 HMENU logLevelMenu = GetSubMenu(menu, 3);
161 CheckMenuRadioItem(logLevelMenu, 0, 6,
162 CLOG->getFilter() - CLog::kERROR, MF_BYPOSITION);
163 int n = TrackPopupMenu(menu,
164 TPM_NONOTIFY |
165 TPM_RETURNCMD |
166 TPM_LEFTBUTTON |
167 TPM_RIGHTBUTTON,
168 x, y, 0, m_window, NULL);
169 SendMessage(m_window, WM_NULL, 0, 0);
170
171 // perform the requested operation
172 switch (n) {
173 case IDC_TASKBAR_STATUS:
174 showStatus();
175 break;
176
177 case IDC_TASKBAR_LOG:
178 copyLog();
179 break;
180
181 case IDC_TASKBAR_SHOW_LOG:
182 ARCH->showConsole(true);
183 break;
184
185 case IDC_RELOAD_CONFIG:
186 EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(),
187 IEventQueue::getSystemTarget()));
188 break;
189
190 case IDC_FORCE_RECONNECT:
191 EVENTQUEUE->addEvent(CEvent(getForceReconnectEvent(),
192 IEventQueue::getSystemTarget()));
193 break;
194
195 case IDC_TASKBAR_LOG_LEVEL_ERROR:
196 CLOG->setFilter(CLog::kERROR);
197 break;
198
199 case IDC_TASKBAR_LOG_LEVEL_WARNING:
200 CLOG->setFilter(CLog::kWARNING);
201 break;
202
203 case IDC_TASKBAR_LOG_LEVEL_NOTE:
204 CLOG->setFilter(CLog::kNOTE);
205 break;
206
207 case IDC_TASKBAR_LOG_LEVEL_INFO:
208 CLOG->setFilter(CLog::kINFO);
209 break;
210
211 case IDC_TASKBAR_LOG_LEVEL_DEBUG:
212 CLOG->setFilter(CLog::kDEBUG);
213 break;
214
215 case IDC_TASKBAR_LOG_LEVEL_DEBUG1:
216 CLOG->setFilter(CLog::kDEBUG1);
217 break;
218
219 case IDC_TASKBAR_LOG_LEVEL_DEBUG2:
220 CLOG->setFilter(CLog::kDEBUG2);
221 break;
222
223 case IDC_TASKBAR_QUIT:
224 quit();
225 break;
226 }
227}
228
229void
230CMSWindowsServerTaskBarReceiver::primaryAction()
231{
232 showStatus();
233}
234
235const IArchTaskBarReceiver::Icon
236CMSWindowsServerTaskBarReceiver::getIcon() const
237{
238 return reinterpret_cast<Icon>(m_icon[getStatus()]);
239}
240
241void
242CMSWindowsServerTaskBarReceiver::copyLog() const
243{
244 if (m_logBuffer != NULL) {
245 // collect log buffer
246 CString data;
247 for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin();
248 index != m_logBuffer->end(); ++index) {
249 data += *index;
250 data += "\n";
251 }
252
253 // copy log to clipboard
254 if (!data.empty()) {
255 CMSWindowsClipboard clipboard(m_window);
256 clipboard.open(0);
257 clipboard.emptyUnowned();
258 clipboard.add(IClipboard::kText, data);
259 clipboard.close();
260 }
261 }
262}
263
264void
265CMSWindowsServerTaskBarReceiver::onStatusChanged()
266{
267 if (IsWindowVisible(m_window)) {
268 showStatus();
269 }
270}
271
272HICON
273CMSWindowsServerTaskBarReceiver::loadIcon(UINT id)
274{
275 HANDLE icon = LoadImage(m_appInstance,
276 MAKEINTRESOURCE(id),
277 IMAGE_ICON,
278 0, 0,
279 LR_DEFAULTCOLOR);
280 return reinterpret_cast<HICON>(icon);
281}
282
283void
284CMSWindowsServerTaskBarReceiver::deleteIcon(HICON icon)
285{
286 if (icon != NULL) {
287 DestroyIcon(icon);
288 }
289}
290
291void
292CMSWindowsServerTaskBarReceiver::createWindow()
293{
294 // ignore if already created
295 if (m_window != NULL) {
296 return;
297 }
298
299 // get the status dialog
300 m_window = CreateDialogParam(m_appInstance,
301 MAKEINTRESOURCE(IDD_TASKBAR_STATUS),
302 NULL,
303 &CMSWindowsServerTaskBarReceiver::staticDlgProc,
304 reinterpret_cast<LPARAM>(
305 reinterpret_cast<void*>(this)));
306
307 // window should appear on top of everything, including (especially)
308 // the task bar.
309 DWORD style = GetWindowLong(m_window, GWL_EXSTYLE);
310 style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
311 SetWindowLong(m_window, GWL_EXSTYLE, style);
312
313 // tell the task bar about this dialog
314 CArchTaskBarWindows::addDialog(m_window);
315}
316
317void
318CMSWindowsServerTaskBarReceiver::destroyWindow()
319{
320 if (m_window != NULL) {
321 CArchTaskBarWindows::removeDialog(m_window);
322 DestroyWindow(m_window);
323 m_window = NULL;
324 }
325}
326
327BOOL
328CMSWindowsServerTaskBarReceiver::dlgProc(HWND hwnd,
329 UINT msg, WPARAM wParam, LPARAM)
330{
331 switch (msg) {
332 case WM_INITDIALOG:
333 // use default focus
334 return TRUE;
335
336 case WM_ACTIVATE:
337 // hide when another window is activated
338 if (LOWORD(wParam) == WA_INACTIVE) {
339 ShowWindow(hwnd, SW_HIDE);
340 }
341 break;
342 }
343 return FALSE;
344}
345
346BOOL CALLBACK
347CMSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd,
348 UINT msg, WPARAM wParam, LPARAM lParam)
349{
350 // if msg is WM_INITDIALOG, extract the CMSWindowsServerTaskBarReceiver*
351 // and put it in the extra window data then forward the call.
352 CMSWindowsServerTaskBarReceiver* self = NULL;
353 if (msg == WM_INITDIALOG) {
354 self = reinterpret_cast<CMSWindowsServerTaskBarReceiver*>(
355 reinterpret_cast<void*>(lParam));
356 SetWindowLong(hwnd, GWL_USERDATA, lParam);
357 }
358 else {
359 // get the extra window data and forward the call
360 LONG data = GetWindowLong(hwnd, GWL_USERDATA);
361 if (data != 0) {
362 self = reinterpret_cast<CMSWindowsServerTaskBarReceiver*>(
363 reinterpret_cast<void*>(data));
364 }
365 }
366
367 // forward the message
368 if (self != NULL) {
369 return self->dlgProc(hwnd, msg, wParam, lParam);
370 }
371 else {
372 return (msg == WM_INITDIALOG) ? TRUE : FALSE;
373 }
374}
Note: See TracBrowser for help on using the repository browser.