blob: a883cabaa50c7425ee130b476f6645cefe8b052a [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;
171 };
172 };
173 break;
174
175 case WM_CLOSE:
176 PostQuitMessage(0);
177 break;
178
179 case WM_TIMER:
180 if (rfb::win32::desktopChangeRequired()) {
181 SendMessage(getHandle(), WM_CLOSE, 0, 0);
182 return 0;
183 }
184 setIcon(thread.server.isServerInUse() ? thread.activeIcon : thread.inactiveIcon);
Oleg Sheikin641f7e52005-11-22 18:04:10 +0000185
186 thread.server.getClientsInfo(&LCInfo);
187 CPanel->UpdateListView(&LCInfo);
188
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000189 return 0;
190
191 case WM_SET_TOOLTIP:
192 {
193 rfb::Lock l(thread.lock);
194 if (thread.toolTip.buf)
195 setToolTip(thread.toolTip.buf);
196 }
197 return 0;
198
199 }
200
201 return TrayIcon::processMessage(msg, wParam, lParam);
202 }
203
204protected:
205 LaunchProcess vncConfig;
206 LaunchProcess vncConnect;
207 STrayIconThread& thread;
Oleg Sheikinf5049ad2005-07-01 12:41:15 +0000208 ControlPanel * CPanel;
Oleg Sheikin641f7e52005-11-22 18:04:10 +0000209 rfb::ListConnInfo LCInfo;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000210};
211
212
213STrayIconThread::STrayIconThread(VNCServerWin32& sm, UINT inactiveIcon_, UINT activeIcon_, UINT menu_)
214: server(sm), inactiveIcon(inactiveIcon_), activeIcon(activeIcon_), menu(menu_),
215 windowHandle(0), runTrayIcon(true) {
216 start();
217}
218
219
220void STrayIconThread::run() {
221 while (runTrayIcon) {
222 if (rfb::win32::desktopChangeRequired() &&
223 !rfb::win32::changeDesktop())
224 Sleep(2000);
225
226 STrayIcon icon(*this);
227 windowHandle = icon.getHandle();
228
229 MSG msg;
230 while (runTrayIcon && ::GetMessage(&msg, 0, 0, 0) > 0) {
231 TranslateMessage(&msg);
232 DispatchMessage(&msg);
233 }
234
235 windowHandle = 0;
236 }
237}
238
239void STrayIconThread::setToolTip(const TCHAR* text) {
240 if (!windowHandle) return;
241 Lock l(lock);
242 delete [] toolTip.buf;
243 toolTip.buf = tstrDup(text);
244 PostMessage(windowHandle, WM_SET_TOOLTIP, 0, 0);
245}
246
247