VirtualBox

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

Last change on this file since 62556 was 62522, checked in by vboxsync, 8 years ago

(C) 2016

  • 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 62522 2016-07-22 19:17:25Z 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 <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 HWND hWin;
51 DWORD hThread, hCurrentThread;
52
53 GetCursorPos(&mousePos);
54 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 ShowCursor(false);
63 ShowCursor(true);
64 if (hWin && (hCurrentThread != hThread))
65 AttachThreadInput(hCurrentThread, hThread, FALSE);
66}
67
68static unsigned hlpNextAdjacentRectXP(RECTL *paRects, unsigned nRects, unsigned uRect)
69{
70 unsigned i;
71 for (i = 0; i < nRects; i++)
72 {
73 if (paRects[uRect].right == paRects[i].left)
74 return i;
75 }
76 return ~0;
77}
78
79static unsigned hlpNextAdjacentRectXN(RECTL *paRects, unsigned nRects, unsigned uRect)
80{
81 unsigned i;
82 for (i = 0; i < nRects; i++)
83 {
84 if (paRects[uRect].left == paRects[i].right)
85 return i;
86 }
87 return ~0;
88}
89
90static unsigned hlpNextAdjacentRectYP(RECTL *paRects, unsigned nRects, unsigned uRect)
91{
92 unsigned i;
93 for (i = 0; i < nRects; i++)
94 {
95 if (paRects[uRect].bottom == paRects[i].top)
96 return i;
97 }
98 return ~0;
99}
100
101static unsigned hlpNextAdjacentRectYN(RECTL *paRects, unsigned nRects, unsigned uRect)
102{
103 unsigned i;
104 for (i = 0; i < nRects; i++)
105 {
106 if (paRects[uRect].top == paRects[i].bottom)
107 return i;
108 }
109 return ~0;
110}
111
112void hlpResizeRect(RECTL *paRects, unsigned nRects, unsigned uPrimary,
113 unsigned uResized, int iNewWidth, int iNewHeight,
114 int iNewPosX, int iNewPosY)
115{
116 DDCLOG(("nRects %d, iPrimary %d, iResized %d, NewWidth %d, NewHeight %d\n", nRects, uPrimary, uResized, iNewWidth, iNewHeight));
117
118 RECTL *paNewRects = (RECTL *)alloca (sizeof (RECTL) * nRects);
119 memcpy (paNewRects, paRects, sizeof (RECTL) * nRects);
120 paNewRects[uResized].right += iNewWidth - (paNewRects[uResized].right - paNewRects[uResized].left);
121 paNewRects[uResized].bottom += iNewHeight - (paNewRects[uResized].bottom - paNewRects[uResized].top);
122 paNewRects[uResized].right += iNewPosX - paNewRects[uResized].left;
123 paNewRects[uResized].bottom += iNewPosY - paNewRects[uResized].top;
124 paNewRects[uResized].left = iNewPosX;
125 paNewRects[uResized].top = iNewPosY;
126
127 /* Verify all pairs of originally adjacent rectangles for all 4 directions.
128 * If the pair has a "good" delta (that is the first rectangle intersects the second)
129 * at a direction and the second rectangle is not primary one (which can not be moved),
130 * move the second rectangle to make it adjacent to the first one.
131 */
132
133 /* X positive. */
134 unsigned iRect;
135 for (iRect = 0; iRect < nRects; iRect++)
136 {
137 /* Find the next adjacent original rect in x positive direction. */
138 unsigned iNextRect = hlpNextAdjacentRectXP(paRects, nRects, iRect);
139 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
140
141 if (iNextRect == ~0 || iNextRect == uPrimary)
142 {
143 continue;
144 }
145
146 /* Check whether there is an X intersection between these adjacent rects in the new rectangles
147 * and fix the intersection if delta is "good".
148 */
149 int delta = paNewRects[iRect].right - paNewRects[iNextRect].left;
150
151 if (delta != 0)
152 {
153 DDCLOG(("XP intersection right %d left %d, diff %d\n",
154 paNewRects[iRect].right, paNewRects[iNextRect].left,
155 delta));
156
157 paNewRects[iNextRect].left += delta;
158 paNewRects[iNextRect].right += delta;
159 }
160 }
161
162 /* X negative. */
163 for (iRect = 0; iRect < nRects; iRect++)
164 {
165 /* Find the next adjacent original rect in x negative direction. */
166 unsigned iNextRect = hlpNextAdjacentRectXN(paRects, nRects, iRect);
167 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
168
169 if (iNextRect == ~0 || iNextRect == uPrimary)
170 {
171 continue;
172 }
173
174 /* Check whether there is an X intersection between these adjacent rects in the new rectangles
175 * and fix the intersection if delta is "good".
176 */
177 int delta = paNewRects[iRect].left - paNewRects[iNextRect].right;
178
179 if (delta != 0)
180 {
181 DDCLOG(("XN intersection left %d right %d, diff %d\n",
182 paNewRects[iRect].left, paNewRects[iNextRect].right,
183 delta));
184
185 paNewRects[iNextRect].left += delta;
186 paNewRects[iNextRect].right += delta;
187 }
188 }
189
190 /* Y positive (in the computer sense, top->down). */
191 for (iRect = 0; iRect < nRects; iRect++)
192 {
193 /* Find the next adjacent original rect in y positive direction. */
194 unsigned iNextRect = hlpNextAdjacentRectYP(paRects, nRects, iRect);
195 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
196
197 if (iNextRect == ~0 || iNextRect == uPrimary)
198 {
199 continue;
200 }
201
202 /* Check whether there is an Y intersection between these adjacent rects in the new rectangles
203 * and fix the intersection if delta is "good".
204 */
205 int delta = paNewRects[iRect].bottom - paNewRects[iNextRect].top;
206
207 if (delta != 0)
208 {
209 DDCLOG(("YP intersection bottom %d top %d, diff %d\n",
210 paNewRects[iRect].bottom, paNewRects[iNextRect].top,
211 delta));
212
213 paNewRects[iNextRect].top += delta;
214 paNewRects[iNextRect].bottom += delta;
215 }
216 }
217
218 /* Y negative (in the computer sense, down->top). */
219 for (iRect = 0; iRect < nRects; iRect++)
220 {
221 /* Find the next adjacent original rect in x negative direction. */
222 unsigned iNextRect = hlpNextAdjacentRectYN(paRects, nRects, iRect);
223 DDCLOG(("next %d -> %d\n", iRect, iNextRect));
224
225 if (iNextRect == ~0 || iNextRect == uPrimary)
226 {
227 continue;
228 }
229
230 /* Check whether there is an Y intersection between these adjacent rects in the new rectangles
231 * and fix the intersection if delta is "good".
232 */
233 int delta = paNewRects[iRect].top - paNewRects[iNextRect].bottom;
234
235 if (delta != 0)
236 {
237 DDCLOG(("YN intersection top %d bottom %d, diff %d\n",
238 paNewRects[iRect].top, paNewRects[iNextRect].bottom,
239 delta));
240
241 paNewRects[iNextRect].top += delta;
242 paNewRects[iNextRect].bottom += delta;
243 }
244 }
245
246 /* Primary rectangle must remain at 0,0. */
247 int32_t iOffsetX = paNewRects[uPrimary].left;
248 int32_t iOffsetY = paNewRects[uPrimary].top;
249 for (iRect = 0; iRect < nRects; iRect++)
250 {
251 paRects[iRect].left = paNewRects[iRect].left - iOffsetX;
252 paRects[iRect].right = paNewRects[iRect].right - iOffsetX;
253 paRects[iRect].top = paNewRects[iRect].top - iOffsetY;
254 paRects[iRect].bottom = paNewRects[iRect].bottom - iOffsetY;
255 DDCLOG((" [%d]: %d,%d %dx%d -> %d,%d %dx%d%s\n",
256 iRect,
257 paRects[iRect].left, paRects[iRect].top,
258 paRects[iRect].right - paRects[iRect].left,
259 paRects[iRect].bottom - paRects[iRect].top,
260 paNewRects[iRect].left, paNewRects[iRect].top,
261 paNewRects[iRect].right - paNewRects[iRect].left,
262 paNewRects[iRect].bottom - paNewRects[iRect].top,
263 iRect == uPrimary? " <- primary": ""));
264 }
265 return;
266}
267
268int hlpShowBalloonTip(HINSTANCE hInst, HWND hWnd, UINT uID,
269 const char *pszMsg, const char *pszTitle,
270 UINT uTimeout, DWORD dwInfoFlags)
271{
272 NOTIFYICONDATA niData;
273 ZeroMemory(&niData, sizeof(NOTIFYICONDATA));
274 niData.cbSize = sizeof(NOTIFYICONDATA);
275 niData.uFlags = NIF_INFO; /* Display a balloon notification. */
276 niData.hWnd = hWnd;
277 niData.uID = uID;
278 /* If not timeout set, set it to 5sec. */
279 if (uTimeout == 0)
280 uTimeout = 5000;
281 niData.uTimeout = uTimeout;
282 /* If no info flag (info, warning, error) set,
283 * set it to info by default. */
284 if (dwInfoFlags == 0)
285 dwInfoFlags = NIIF_INFO;
286 niData.dwInfoFlags = dwInfoFlags;
287
288 /* Do we want to have */
289
290 /* Get running OS version. */
291 OSVERSIONINFO osInfo;
292 osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
293 if (FALSE == GetVersionEx(&osInfo))
294 return RTErrConvertFromWin32(GetLastError());
295
296 /* Is the current OS supported (at least WinXP) for displaying
297 * our own icon and do we actually *want* to display our own stuff? */
298 if ( osInfo.dwMajorVersion >= 5
299 && (dwInfoFlags & NIIF_INFO))
300 {
301 /* Load (or retrieve handle of) the app's icon. */
302 HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VIRTUALBOX));
303 if (hIcon)
304 niData.dwInfoFlags = NIIF_USER; /* Use an own notification icon. */
305
306 if ( osInfo.dwMajorVersion == 5
307 && osInfo.dwMinorVersion == 1) /* WinXP. */
308 {
309 /* Use an own icon instead of the default one. */
310 niData.hIcon = hIcon;
311 }
312 else if (osInfo.dwMajorVersion == 6) /* Vista and up. */
313 {
314 /* Use an own icon instead of the default one. */
315 niData.dwInfoFlags |= NIIF_LARGE_ICON; /* Use a large icon if available! */
316 niData.hIcon = hIcon;
317 niData.hBalloonIcon = hIcon;
318 }
319 }
320 else
321 {
322 /* This might be a warning, error message or a to old OS. Use the
323 * standard icons provided by Windows (if any). */
324 }
325
326 strcpy(niData.szInfo, pszMsg ? pszMsg : "-");
327 strcpy(niData.szInfoTitle, pszTitle ? pszTitle : "Information");
328
329 if (!Shell_NotifyIcon(NIM_MODIFY, &niData))
330 {
331 DWORD dwErr = GetLastError();
332 return RTErrConvertFromWin32(dwErr);
333 }
334 return VINF_SUCCESS;
335}
336
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