source: vendor/synergy/1.3.1/cmd/synergyc/CMSWindowsClientTaskBarReceiver.cpp

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

synergy v1.3.1 sources (zip).

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