VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.cpp@ 79506

Last change on this file since 79506 was 78937, checked in by vboxsync, 6 years ago

VBoxTray: Use RTSystemGetNtVersion() rather than GetVersion or GetVersionEx for determining the actual windows version. Some cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: VBoxHelpers.cpp 78937 2019-06-03 13:52:06Z vboxsync $ */
2/** @file
3 * helpers - Guest Additions Service helper functions
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/win/windows.h>
19
20#include <iprt/string.h>
21#include <iprt/alloca.h>
22#include <iprt/system.h>
23#include <VBox/Log.h>
24#include <VBox/VBoxGuestLib.h>
25
26#include "VBoxHelpers.h"
27#include "resource.h"
28
29
30int hlpReportStatus(VBoxGuestFacilityStatus statusCurrent)
31{
32 int rc = VbglR3ReportAdditionsStatus(VBoxGuestFacilityType_VBoxTrayClient,
33 statusCurrent,
34 0 /* Flags */);
35 if (RT_FAILURE(rc))
36 Log(("VBoxTray: Could not report VBoxTray status \"%ld\", rc=%Rrc\n", statusCurrent, rc));
37 return rc;
38}
39
40/**
41 * Attempt to force Windows to reload the cursor image by attaching to the
42 * thread of the window currently under the mouse, hiding the cursor and
43 * showing it again. This could fail to work in any number of ways (no
44 * window under the cursor, the cursor has moved to a different window while
45 * we are processing), but we just accept this, as the cursor will be reloaded
46 * at some point anyway.
47 */
48void hlpReloadCursor(void)
49{
50 POINT mousePos;
51 GetCursorPos(&mousePos);
52
53 DWORD hThread = 0; /* Shut up MSC */
54 DWORD hCurrentThread = 0; /* Ditto */
55 HWND hWin = WindowFromPoint(mousePos);
56 if (hWin)
57 {
58 hThread = GetWindowThreadProcessId(hWin, NULL);
59 hCurrentThread = GetCurrentThreadId();
60 if (hCurrentThread != hThread)
61 AttachThreadInput(hCurrentThread, hThread, TRUE);
62 }
63
64 ShowCursor(false);
65 ShowCursor(true);
66
67 if (hWin && hCurrentThread != hThread)
68 AttachThreadInput(hCurrentThread, hThread, FALSE);
69}
70
71static unsigned hlpNextAdjacentRectXP(RECTL *paRects, unsigned nRects, unsigned uRect)
72{
73 unsigned i;
74 for (i = 0; i < nRects; i++)
75 {
76 if (paRects[uRect].right == paRects[i].left)
77 return i;
78 }
79 return ~0U;
80}
81
82static unsigned hlpNextAdjacentRectXN(RECTL *paRects, unsigned nRects, unsigned uRect)
83{
84 unsigned i;
85 for (i = 0; i < nRects; i++)
86 {
87 if (paRects[uRect].left == paRects[i].right)
88 return i;
89 }
90 return ~0U;
91}
92
93static unsigned hlpNextAdjacentRectYP(RECTL *paRects, unsigned nRects, unsigned uRect)
94{
95 unsigned i;
96 for (i = 0; i < nRects; i++)
97 {
98 if (paRects[uRect].bottom == paRects[i].top)
99 return i;
100 }
101 return ~0U;
102}
103
104static unsigned hlpNextAdjacentRectYN(RECTL *paRects, unsigned nRects, unsigned uRect)
105{
106 unsigned i;
107 for (i = 0; i < nRects; i++)
108 {
109 if (paRects[uRect].top == paRects[i].bottom)
110 return i;
111 }
112 return ~0U;
113}
114
115void hlpResizeRect(RECTL *paRects, unsigned nRects, unsigned uPrimary,
116 unsigned uResized, int iNewWidth, int iNewHeight,
117 int iNewPosX, int iNewPosY)
118{
119 DDCLOG(("nRects %d, iPrimary %d, iResized %d, NewWidth %d, NewHeight %d\n", nRects, uPrimary, uResized, iNewWidth, iNewHeight));
120
121 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects);
122 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects);
123 paNewRects[uResized].right += iNewWidth - (paNewRects[uResized].right - paNewRects[uResized].left);
124 paNewRects[uResized].bottom += iNewHeight - (paNewRects[uResized].bottom - paNewRects[uResized].top);
125 paNewRects[uResized].right += iNewPosX - paNewRects[uResized].left;
126 paNewRects[uResized].bottom += iNewPosY - paNewRects[uResized].top;
127 paNewRects[uResized].left = iNewPosX;
128 paNewRects[uResized].top = iNewPosY;
129
130 /* Verify all pairs of originally adjacent rectangles for all 4 directions.
131 * If the pair has a "good" delta (that is the first rectangle intersects the second)
132 * at a direction and the second rectangle is not primary one (which can not be moved),
133 * move the second rectangle to make it adjacent to the first one.
134 */
135
136 /* X positive. */
137 unsigned iRect;
138 for (iRect = 0; iRect < nRects; iRect++)
139 {
140 /* Find the next adjacent original rect in x positive direction. */
141 unsigned iNextRect = hlpNextAdjacentRectXP(paRects, nRects, iRect);
142 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
143
144 if (iNextRect == ~0 || iNextRect == uPrimary)
145 {
146 continue;
147 }
148
149 /* Check whether there is an X intersection between these adjacent rects in the new rectangles
150 * and fix the intersection if delta is "good".
151 */
152 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left;
153
154 if (delta != 0)
155 {
156 DDCLOG(("XP intersection right %d left %d, diff %d\n",
157 paNewRects[iRect].right, paNewRects[iNextRect].left,
158 delta));
159
160 paNewRects[iNextRect].left += delta;
161 paNewRects[iNextRect].right += delta;
162 }
163 }
164
165 /* X negative. */
166 for (iRect = 0; iRect < nRects; iRect++)
167 {
168 /* Find the next adjacent original rect in x negative direction. */
169 unsigned iNextRect = hlpNextAdjacentRectXN(paRects, nRects, iRect);
170 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
171
172 if (iNextRect == ~0 || iNextRect == uPrimary)
173 {
174 continue;
175 }
176
177 /* Check whether there is an X intersection between these adjacent rects in the new rectangles
178 * and fix the intersection if delta is "good".
179 */
180 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right;
181
182 if (delta != 0)
183 {
184 DDCLOG(("XN intersection left %d right %d, diff %d\n",
185 paNewRects[iRect].left, paNewRects[iNextRect].right,
186 delta));
187
188 paNewRects[iNextRect].left += delta;
189 paNewRects[iNextRect].right += delta;
190 }
191 }
192
193 /* Y positive (in the computer sense, top->down). */
194 for (iRect = 0; iRect < nRects; iRect++)
195 {
196 /* Find the next adjacent original rect in y positive direction. */
197 unsigned iNextRect = hlpNextAdjacentRectYP(paRects, nRects, iRect);
198 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
199
200 if (iNextRect == ~0 || iNextRect == uPrimary)
201 {
202 continue;
203 }
204
205 /* Check whether there is an Y intersection between these adjacent rects in the new rectangles
206 * and fix the intersection if delta is "good".
207 */
208 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top;
209
210 if (delta != 0)
211 {
212 DDCLOG(("YP intersection bottom %d top %d, diff %d\n",
213 paNewRects[iRect].bottom, paNewRects[iNextRect].top,
214 delta));
215
216 paNewRects[iNextRect].top += delta;
217 paNewRects[iNextRect].bottom += delta;
218 }
219 }
220
221 /* Y negative (in the computer sense, down->top). */
222 for (iRect = 0; iRect < nRects; iRect++)
223 {
224 /* Find the next adjacent original rect in x negative direction. */
225 unsigned iNextRect = hlpNextAdjacentRectYN(paRects, nRects, iRect);
226 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
227
228 if (iNextRect == ~0 || iNextRect == uPrimary)
229 {
230 continue;
231 }
232
233 /* Check whether there is an Y intersection between these adjacent rects in the new rectangles
234 * and fix the intersection if delta is "good".
235 */
236 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom;
237
238 if (delta != 0)
239 {
240 DDCLOG(("YN intersection top %d bottom %d, diff %d\n",
241 paNewRects[iRect].top, paNewRects[iNextRect].bottom,
242 delta));
243
244 paNewRects[iNextRect].top += delta;
245 paNewRects[iNextRect].bottom += delta;
246 }
247 }
248
249 /* Primary rectangle must remain at 0,0. */
250 int32_t iOffsetX = paNewRects[uPrimary].left;
251 int32_t iOffsetY = paNewRects[uPrimary].top;
252 for (iRect = 0; iRect < nRects; iRect++)
253 {
254 paRects[iRect].left = paNewRects[iRect].left - iOffsetX;
255 paRects[iRect].right = paNewRects[iRect].right - iOffsetX;
256 paRects[iRect].top = paNewRects[iRect].top - iOffsetY;
257 paRects[iRect].bottom = paNewRects[iRect].bottom - iOffsetY;
258 DDCLOG((" [%d]: %d,%d %dx%d -> %d,%d %dx%d%s\n",
259 iRect,
260 paRects[iRect].left, paRects[iRect].top,
261 paRects[iRect].right - paRects[iRect].left,
262 paRects[iRect].bottom - paRects[iRect].top,
263 paNewRects[iRect].left, paNewRects[iRect].top,
264 paNewRects[iRect].right - paNewRects[iRect].left,
265 paNewRects[iRect].bottom - paNewRects[iRect].top,
266 iRect == uPrimary? " <- primary": ""));
267 }
268 return;
269}
270
271int hlpShowBalloonTip(HINSTANCE hInst, HWND hWnd, UINT uID,
272 const char *pszMsg, const char *pszTitle,
273 UINT uTimeout, DWORD dwInfoFlags)
274{
275 NOTIFYICONDATA niData;
276 ZeroMemory(&niData, sizeof(NOTIFYICONDATA));
277 niData.cbSize = sizeof(NOTIFYICONDATA);
278 niData.uFlags = NIF_INFO; /* Display a balloon notification. */
279 niData.hWnd = hWnd;
280 niData.uID = uID;
281 /* If not timeout set, set it to 5sec. */
282 if (uTimeout == 0)
283 uTimeout = 5000;
284 niData.uTimeout = uTimeout;
285 /* If no info flag (info, warning, error) set,
286 * set it to info by default. */
287 if (dwInfoFlags == 0)
288 dwInfoFlags = NIIF_INFO;
289 niData.dwInfoFlags = dwInfoFlags;
290
291 /* Do we want to have */
292
293 /* Is the current OS supported (at least WinXP) for displaying
294 * our own icon and do we actually *want* to display our own stuff? */
295 uint64_t const uNtVersion = RTSystemGetNtVersion();
296 if ( uNtVersion >= RTSYSTEM_MAKE_NT_VERSION(5, 0, 0)
297 && (dwInfoFlags & NIIF_INFO))
298 {
299 /* Load (or retrieve handle of) the app's icon. */
300 HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VIRTUALBOX));
301 if (hIcon)
302 niData.dwInfoFlags = NIIF_USER; /* Use an own notification icon. */
303
304 if (uNtVersion >= RTSYSTEM_MAKE_NT_VERSION(5, 1, 0)) /* WinXP. */
305 {
306 /* Use an own icon instead of the default one. */
307 niData.hIcon = hIcon;
308 }
309 else if (uNtVersion >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0)) /* Vista and up. */
310 {
311 /* Use an own icon instead of the default one. */
312 niData.dwInfoFlags |= NIIF_LARGE_ICON; /* Use a large icon if available! */
313 niData.hIcon = hIcon;
314 niData.hBalloonIcon = hIcon;
315 }
316 }
317 else
318 {
319 /* This might be a warning, error message or a to old OS. Use the
320 * standard icons provided by Windows (if any). */
321 }
322
323 strcpy(niData.szInfo, pszMsg ? pszMsg : "-");
324 strcpy(niData.szInfoTitle, pszTitle ? pszTitle : "Information");
325
326 if (!Shell_NotifyIcon(NIM_MODIFY, &niData))
327 {
328 DWORD dwErr = GetLastError();
329 return RTErrConvertFromWin32(dwErr);
330 }
331 return VINF_SUCCESS;
332}
333
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette