blob: d3e13dac4a8953c41dc45a9e69f1b9f1008fddc6 [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19// -=- WinVNC Version 4.0 Tray Icon implementation
20
21#include <winvnc/STrayIcon.h>
22#include <winvnc/resource.h>
23
24#include <rfb/LogWriter.h>
25#include <rfb/Configuration.h>
26#include <rfb_win32/LaunchProcess.h>
27#include <rfb_win32/TrayIcon.h>
28#include <rfb_win32/AboutDialog.h>
29#include <rfb_win32/Win32Util.h>
30#include <rfb_win32/Service.h>
31#include <rfb_win32/CurrentUser.h>
Oleg Sheikinf5049ad2005-07-01 12:41:15 +000032#include <winvnc/ControlPanel.h>
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000033
34using namespace rfb;
35using namespace win32;
36using namespace winvnc;
37
38static LogWriter vlog("STrayIcon");
39
40BoolParameter STrayIconThread::disableOptions("DisableOptions", "Disable the Options entry in the VNC Server tray menu.", false);
41
42
43//
44// -=- AboutDialog global values
45//
46
47const WORD rfb::win32::AboutDialog::DialogId = IDD_ABOUT;
48const WORD rfb::win32::AboutDialog::Copyright = IDC_COPYRIGHT;
49const WORD rfb::win32::AboutDialog::Version = IDC_VERSION;
50const WORD rfb::win32::AboutDialog::BuildTime = IDC_BUILDTIME;
51const WORD rfb::win32::AboutDialog::Description = IDC_DESCRIPTION;
52
53
54//
55// -=- Internal tray icon class
56//
57
58const UINT WM_SET_TOOLTIP = WM_USER + 1;
59
60
61class winvnc::STrayIcon : public TrayIcon {
62public:
63 STrayIcon(STrayIconThread& t) : thread(t),
64 vncConfig(_T("vncconfig.exe"), isServiceProcess() ? _T("-noconsole -service") : _T("-noconsole")),
65 vncConnect(_T("winvnc4.exe"), _T("-connect")) {
66
67 // ***
68 SetWindowText(getHandle(), _T("winvnc::IPC_Interface"));
69 // ***
70
71 SetTimer(getHandle(), 1, 3000, 0);
72 PostMessage(getHandle(), WM_TIMER, 1, 0);
73 PostMessage(getHandle(), WM_SET_TOOLTIP, 0, 0);
Oleg Sheikin641f7e52005-11-22 18:04:10 +000074 CPanel = new ControlPanel(getHandle());
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000075 }
76
77 virtual LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
78 switch(msg) {
79
80 case WM_USER:
81 {
82 bool userKnown = CurrentUserToken().isValid();
83 bool allowOptions = !STrayIconThread::disableOptions && userKnown;
84
85 switch (lParam) {
86 case WM_LBUTTONDBLCLK:
Oleg Sheikinf5049ad2005-07-01 12:41:15 +000087 SendMessage(getHandle(), WM_COMMAND, ID_CONTR0L_PANEL, 0);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000088 break;
89 case WM_RBUTTONUP:
90 HMENU menu = LoadMenu(GetModuleHandle(0), MAKEINTRESOURCE(thread.menu));
91 HMENU trayMenu = GetSubMenu(menu, 0);
92
93
94 // Default item is Options, if available, or About if not
Oleg Sheikinf5049ad2005-07-01 12:41:15 +000095 SetMenuDefaultItem(trayMenu, ID_CONTR0L_PANEL, FALSE);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000096
97 // Enable/disable options as required
98 EnableMenuItem(trayMenu, ID_OPTIONS, (!allowOptions ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);
99 EnableMenuItem(trayMenu, ID_CONNECT, (!userKnown ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);
100 EnableMenuItem(trayMenu, ID_CLOSE, (isServiceProcess() ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);
101
102 // SetForegroundWindow is required, otherwise Windows ignores the
103 // TrackPopupMenu because the window isn't the foreground one, on
104 // some older Windows versions...
105 SetForegroundWindow(getHandle());
106
107 // Display the menu
108 POINT pos;
109 GetCursorPos(&pos);
110 TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, getHandle(), 0);
111 break;
112 }
113 return 0;
114 }
115
116 // Handle tray icon menu commands
117 case WM_COMMAND:
118 switch (LOWORD(wParam)) {
Oleg Sheikinf5049ad2005-07-01 12:41:15 +0000119 case ID_CONTR0L_PANEL:
120 {
121 CPanel->showDialog();
122 }
123 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000124 case ID_OPTIONS:
125 {
126 CurrentUserToken token;
127 if (token.isValid())
128 vncConfig.start(isServiceProcess() ? (HANDLE)token : 0);
129 else
130 vlog.error("Options: unknown current user");
131 }
132 break;
133 case ID_CONNECT:
134 {
135 CurrentUserToken token;
136 if (token.isValid())
137 vncConnect.start(isServiceProcess() ? (HANDLE)token : 0);
138 else
139 vlog.error("Options: unknown current user");
140 }
141 break;
142 case ID_DISCONNECT:
143 thread.server.disconnectClients("tray menu disconnect");
144 break;
145 case ID_CLOSE:
146 if (!isServiceProcess())
147 thread.server.stop();
148 break;
149 case ID_ABOUT:
150 AboutDialog::instance.showDialog();
151 break;
152 }
153 return 0;
154
155 // Handle commands send by other processes
156 case WM_COPYDATA:
157 {
158 COPYDATASTRUCT* command = (COPYDATASTRUCT*)lParam;
159 switch (command->dwData) {
160 case 1:
161 {
162 CharArray viewer = new char[command->cbData + 1];
163 memcpy(viewer.buf, command->lpData, command->cbData);
164 viewer.buf[command->cbData] = 0;
165 thread.server.addNewClient(viewer.buf);
166 }
167 break;
168 case 2:
169 thread.server.disconnectClients("IPC disconnect");
170 break;
Oleg Sheikin4b0304f2005-12-09 10:59:12 +0000171 case 3:
172 thread.server.setClientsStatus((rfb::ListConnInfo *)command->cbData);
Constantin Kaplinskyc14a07a2005-12-09 14:54:28 +0000173 thread.server.getClientsInfo(&LCInfo);
174 CPanel->UpdateListView(&LCInfo);
Oleg Sheikin4b0304f2005-12-09 10:59:12 +0000175 break;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000176 };
177 };
178 break;
179
180 case WM_CLOSE:
181 PostQuitMessage(0);
182 break;
183
184 case WM_TIMER:
185 if (rfb::win32::desktopChangeRequired()) {
186 SendMessage(getHandle(), WM_CLOSE, 0, 0);
187 return 0;
188 }
Oleg Sheikin641f7e52005-11-22 18:04:10 +0000189
Oleg Sheikinff43bfd2005-12-07 08:02:52 +0000190 thread.server.getClientsInfo(&LCInfo);
Oleg Sheikin5c642e92005-12-22 20:57:58 +0000191 CPanel->UpdateListView(&LCInfo);
192
193 setIcon(thread.server.isServerInUse() ?
194 (!LCInfo.getDisable() ? thread.activeIcon : thread.dis_activeIcon) :
195 (!LCInfo.getDisable() ? thread.inactiveIcon : thread.dis_inactiveIcon));
Oleg Sheikin641f7e52005-11-22 18:04:10 +0000196
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000197 return 0;
198
199 case WM_SET_TOOLTIP:
200 {
201 rfb::Lock l(thread.lock);
202 if (thread.toolTip.buf)
203 setToolTip(thread.toolTip.buf);
204 }
205 return 0;
206
207 }
208
209 return TrayIcon::processMessage(msg, wParam, lParam);
210 }
211
212protected:
213 LaunchProcess vncConfig;
214 LaunchProcess vncConnect;
215 STrayIconThread& thread;
Oleg Sheikinf5049ad2005-07-01 12:41:15 +0000216 ControlPanel * CPanel;
Oleg Sheikin641f7e52005-11-22 18:04:10 +0000217 rfb::ListConnInfo LCInfo;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000218};
219
220
Oleg Sheikin5c642e92005-12-22 20:57:58 +0000221STrayIconThread::STrayIconThread(VNCServerWin32& sm, UINT inactiveIcon_, UINT activeIcon_,
222 UINT dis_inactiveIcon_, UINT dis_activeIcon_, UINT menu_)
223: server(sm), inactiveIcon(inactiveIcon_), activeIcon(activeIcon_),
224 dis_inactiveIcon(dis_inactiveIcon_), dis_activeIcon(dis_activeIcon_),menu(menu_),
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000225 windowHandle(0), runTrayIcon(true) {
226 start();
227}
228
229
230void STrayIconThread::run() {
231 while (runTrayIcon) {
232 if (rfb::win32::desktopChangeRequired() &&
233 !rfb::win32::changeDesktop())
234 Sleep(2000);
235
236 STrayIcon icon(*this);
237 windowHandle = icon.getHandle();
238
239 MSG msg;
240 while (runTrayIcon && ::GetMessage(&msg, 0, 0, 0) > 0) {
241 TranslateMessage(&msg);
242 DispatchMessage(&msg);
243 }
244
245 windowHandle = 0;
246 }
247}
248
249void STrayIconThread::setToolTip(const TCHAR* text) {
250 if (!windowHandle) return;
251 Lock l(lock);
252 delete [] toolTip.buf;
253 toolTip.buf = tstrDup(text);
254 PostMessage(windowHandle, WM_SET_TOOLTIP, 0, 0);
255}
256
257