VirtualBox

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

Last change on this file since 63107 was 63100, checked in by vboxsync, 8 years ago

GA/NT/VBoxTray: warnings

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