Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. | |
3 | * | |
4 | *Permission is hereby granted, free of charge, to any person obtaining | |
5 | * a copy of this software and associated documentation files (the | |
6 | *"Software"), to deal in the Software without restriction, including | |
7 | *without limitation the rights to use, copy, modify, merge, publish, | |
8 | *distribute, sublicense, and/or sell copies of the Software, and to | |
9 | *permit persons to whom the Software is furnished to do so, subject to | |
10 | *the following conditions: | |
11 | * | |
12 | *The above copyright notice and this permission notice shall be | |
13 | *included in all copies or substantial portions of the Software. | |
14 | * | |
15 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
16 | *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 | *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
18 | *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR | |
19 | *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
20 | *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
21 | *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | *Except as contained in this notice, the name of the XFree86 Project | |
24 | *shall not be used in advertising or otherwise to promote the sale, use | |
25 | *or other dealings in this Software without prior written authorization | |
26 | *from the XFree86 Project. | |
27 | * | |
28 | * Authors: Dakshinamurthy Karra | |
29 | * Suhaib M Siddiqi | |
30 | * Peter Busch | |
31 | * Harold L Hunt II | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_XWIN_CONFIG_H | |
35 | #include <xwin-config.h> | |
36 | #endif | |
37 | #include "win.h" | |
38 | ||
39 | /* | |
40 | * Local function prototypes | |
41 | */ | |
42 | ||
43 | static Bool | |
44 | winAllocateFBPrimaryDD(ScreenPtr pScreen); | |
45 | ||
46 | static Bool | |
47 | winCloseScreenPrimaryDD(ScreenPtr pScreen); | |
48 | ||
49 | static Bool | |
50 | winInitVisualsPrimaryDD(ScreenPtr pScreen); | |
51 | ||
52 | static Bool | |
53 | winAdjustVideoModePrimaryDD(ScreenPtr pScreen); | |
54 | ||
55 | static Bool | |
56 | winActivateAppPrimaryDD(ScreenPtr pScreen); | |
57 | ||
58 | static Bool | |
59 | winHotKeyAltTabPrimaryDD(ScreenPtr pScreen); | |
60 | ||
61 | /* | |
62 | * Create a DirectDraw primary surface | |
63 | */ | |
64 | ||
65 | static Bool | |
66 | winAllocateFBPrimaryDD(ScreenPtr pScreen) | |
67 | { | |
68 | winScreenPriv(pScreen); | |
69 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; | |
70 | HRESULT ddrval = DD_OK; | |
71 | DDSURFACEDESC ddsd; | |
72 | DDSURFACEDESC *pddsdPrimary = NULL; | |
73 | DDSURFACEDESC *pddsdOffscreen = NULL; | |
74 | RECT rcClient; | |
75 | ||
76 | ErrorF("winAllocateFBPrimaryDD\n"); | |
77 | ||
78 | /* Get client area location in screen coords */ | |
79 | GetClientRect(pScreenPriv->hwndScreen, &rcClient); | |
80 | MapWindowPoints(pScreenPriv->hwndScreen, | |
81 | HWND_DESKTOP, (LPPOINT) &rcClient, 2); | |
82 | ||
83 | /* Create a DirectDraw object, store the address at lpdd */ | |
84 | ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL); | |
85 | if (ddrval != DD_OK) | |
86 | FatalError("winAllocateFBPrimaryDD - Could not start DirectDraw\n"); | |
87 | ||
88 | /* Get a DirectDraw2 interface pointer */ | |
89 | ddrval = IDirectDraw_QueryInterface(pScreenPriv->pdd, | |
90 | &IID_IDirectDraw2, | |
91 | (LPVOID *) &pScreenPriv->pdd2); | |
92 | if (FAILED(ddrval)) { | |
93 | ErrorF("winAllocateFBShadowDD - Failed DD2 query: %08x\n", | |
94 | (unsigned int) ddrval); | |
95 | return FALSE; | |
96 | } | |
97 | ||
98 | ErrorF("winAllocateFBPrimaryDD - Created and initialized DD\n"); | |
99 | ||
100 | /* Are we windowed or fullscreen? */ | |
101 | if (pScreenInfo->fFullScreen) { | |
102 | /* Full screen mode */ | |
103 | ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2, | |
104 | pScreenPriv->hwndScreen, | |
105 | DDSCL_FULLSCREEN | |
106 | | DDSCL_EXCLUSIVE); | |
107 | if (FAILED(ddrval)) | |
108 | FatalError("winAllocateFBPrimaryDD - Could not set " | |
109 | "cooperative level\n"); | |
110 | ||
111 | /* Change the video mode to the mode requested */ | |
112 | ddrval = IDirectDraw2_SetDisplayMode(pScreenPriv->pdd2, | |
113 | pScreenInfo->dwWidth, | |
114 | pScreenInfo->dwHeight, | |
115 | pScreenInfo->dwBPP, | |
116 | pScreenInfo->dwRefreshRate, 0); | |
117 | if (FAILED(ddrval)) | |
118 | FatalError("winAllocateFBPrimaryDD - Could not set " | |
119 | "full screen display mode\n"); | |
120 | } | |
121 | else { | |
122 | /* Windowed mode */ | |
123 | ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2, | |
124 | pScreenPriv->hwndScreen, | |
125 | DDSCL_NORMAL); | |
126 | if (FAILED(ddrval)) | |
127 | FatalError("winAllocateFBPrimaryDD - Could not set " | |
128 | "cooperative level\n"); | |
129 | } | |
130 | ||
131 | /* Describe the primary surface */ | |
132 | ZeroMemory(&ddsd, sizeof(ddsd)); | |
133 | ddsd.dwSize = sizeof(ddsd); | |
134 | ddsd.dwFlags = DDSD_CAPS; | |
135 | ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; | |
136 | ||
137 | /* Create the primary surface */ | |
138 | ddrval = IDirectDraw2_CreateSurface(pScreenPriv->pdd2, | |
139 | &ddsd, &pScreenPriv->pddsPrimary, NULL); | |
140 | if (FAILED(ddrval)) | |
141 | FatalError("winAllocateFBPrimaryDD - Could not create primary " | |
142 | "surface %08x\n", (unsigned int) ddrval); | |
143 | ||
144 | ErrorF("winAllocateFBPrimaryDD - Created primary\n"); | |
145 | ||
146 | /* Allocate a DD surface description for our screen privates */ | |
147 | pddsdPrimary = pScreenPriv->pddsdPrimary = malloc(sizeof(DDSURFACEDESC)); | |
148 | if (pddsdPrimary == NULL) | |
149 | FatalError("winAllocateFBPrimaryDD - Could not allocate surface " | |
150 | "description memory\n"); | |
151 | ZeroMemory(pddsdPrimary, sizeof(*pddsdPrimary)); | |
152 | pddsdPrimary->dwSize = sizeof(*pddsdPrimary); | |
153 | ||
154 | /* Describe the offscreen surface to be created */ | |
155 | /* | |
156 | * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, | |
157 | * as drawing, locking, and unlocking take forever | |
158 | * with video memory surfaces. In addition, | |
159 | * video memory is a somewhat scarce resource, | |
160 | * so you shouldn't be allocating video memory when | |
161 | * you have the option of using system memory instead. | |
162 | */ | |
163 | ZeroMemory(&ddsd, sizeof(ddsd)); | |
164 | ddsd.dwSize = sizeof(ddsd); | |
165 | ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; | |
166 | ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; | |
167 | ddsd.dwHeight = pScreenInfo->dwHeight; | |
168 | ddsd.dwWidth = pScreenInfo->dwWidth; | |
169 | ||
170 | /* Create the shadow surface */ | |
171 | ddrval = IDirectDraw2_CreateSurface(pScreenPriv->pdd2, | |
172 | &ddsd, | |
173 | &pScreenPriv->pddsOffscreen, NULL); | |
174 | if (ddrval != DD_OK) | |
175 | FatalError("winAllocateFBPrimaryDD - Could not create shadow " | |
176 | "surface\n"); | |
177 | ||
178 | ErrorF("winAllocateFBPrimaryDD - Created offscreen\n"); | |
179 | ||
180 | /* Allocate a DD surface description for our screen privates */ | |
181 | pddsdOffscreen = pScreenPriv->pddsdOffscreen | |
182 | = malloc(sizeof(DDSURFACEDESC)); | |
183 | if (pddsdOffscreen == NULL) | |
184 | FatalError("winAllocateFBPrimaryDD - Could not allocate surface " | |
185 | "description memory\n"); | |
186 | ZeroMemory(pddsdOffscreen, sizeof(*pddsdOffscreen)); | |
187 | pddsdOffscreen->dwSize = sizeof(*pddsdOffscreen); | |
188 | ||
189 | ErrorF("winAllocateFBPrimaryDD - Locking primary\n"); | |
190 | ||
191 | /* Lock the primary surface */ | |
192 | ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsPrimary, | |
193 | pScreenInfo-> | |
194 | fFullScreen ? NULL : &rcClient, | |
195 | pddsdPrimary, DDLOCK_WAIT, NULL); | |
196 | if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL) | |
197 | FatalError("winAllocateFBPrimaryDD - Could not lock " | |
198 | "primary surface\n"); | |
199 | ||
200 | ErrorF("winAllocateFBPrimaryDD - Locked primary\n"); | |
201 | ||
202 | /* We don't know how to deal with anything other than RGB */ | |
203 | if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB)) | |
204 | FatalError("winAllocateFBPrimaryDD - Color format other than RGB\n"); | |
205 | ||
206 | /* Grab the pitch from the surface desc */ | |
207 | pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8) | |
208 | / pScreenInfo->dwBPP; | |
209 | ||
210 | /* Save the pointer to our surface memory */ | |
211 | pScreenInfo->pfb = pddsdPrimary->lpSurface; | |
212 | ||
213 | /* Grab the color depth and masks from the surface description */ | |
214 | pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask; | |
215 | pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask; | |
216 | pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask; | |
217 | ||
218 | ErrorF("winAllocateFBPrimaryDD - Returning\n"); | |
219 | ||
220 | return TRUE; | |
221 | } | |
222 | ||
223 | static void | |
224 | winFreeFBPrimaryDD(ScreenPtr pScreen) | |
225 | { | |
226 | winScreenPriv(pScreen); | |
227 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; | |
228 | ||
229 | /* Free the offscreen surface, if there is one */ | |
230 | if (pScreenPriv->pddsOffscreen) { | |
231 | IDirectDrawSurface2_Unlock(pScreenPriv->pddsOffscreen, NULL); | |
232 | IDirectDrawSurface2_Release(pScreenPriv->pddsOffscreen); | |
233 | pScreenPriv->pddsOffscreen = NULL; | |
234 | } | |
235 | ||
236 | /* Release the primary surface, if there is one */ | |
237 | if (pScreenPriv->pddsPrimary) { | |
238 | IDirectDrawSurface2_Unlock(pScreenPriv->pddsPrimary, NULL); | |
239 | IDirectDrawSurface2_Release(pScreenPriv->pddsPrimary); | |
240 | pScreenPriv->pddsPrimary = NULL; | |
241 | } | |
242 | ||
243 | /* Free the DirectDraw object, if there is one */ | |
244 | if (pScreenPriv->pdd) { | |
245 | IDirectDraw2_RestoreDisplayMode(pScreenPriv->pdd); | |
246 | IDirectDraw2_Release(pScreenPriv->pdd); | |
247 | pScreenPriv->pdd = NULL; | |
248 | } | |
249 | ||
250 | /* Invalidate the ScreenInfo's fb pointer */ | |
251 | pScreenInfo->pfb = NULL; | |
252 | } | |
253 | ||
254 | static Bool | |
255 | winInitScreenPrimaryDD(ScreenPtr pScreen) | |
256 | { | |
257 | return winAllocateFBPrimaryDD(pScreen); | |
258 | } | |
259 | ||
260 | /* | |
261 | * Call the wrapped CloseScreen function. | |
262 | * | |
263 | * Free our resources and private structures. | |
264 | */ | |
265 | ||
266 | static Bool | |
267 | winCloseScreenPrimaryDD(ScreenPtr pScreen) | |
268 | { | |
269 | winScreenPriv(pScreen); | |
270 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; | |
271 | Bool fReturn; | |
272 | ||
273 | ErrorF("winCloseScreenPrimaryDD - Freeing screen resources\n"); | |
274 | ||
275 | /* Flag that the screen is closed */ | |
276 | pScreenPriv->fClosed = TRUE; | |
277 | pScreenPriv->fActive = FALSE; | |
278 | ||
279 | /* Call the wrapped CloseScreen procedure */ | |
280 | WIN_UNWRAP(CloseScreen); | |
281 | if (pScreen->CloseScreen) | |
282 | fReturn = (*pScreen->CloseScreen) (pScreen); | |
283 | ||
284 | /* Delete the window property */ | |
285 | RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP); | |
286 | ||
287 | winFreeFBPrimaryDD(pScreen); | |
288 | ||
289 | /* Delete tray icon, if we have one */ | |
290 | if (!pScreenInfo->fNoTrayIcon) | |
291 | winDeleteNotifyIcon(pScreenPriv); | |
292 | ||
293 | /* Free the exit confirmation dialog box, if it exists */ | |
294 | if (g_hDlgExit != NULL) { | |
295 | DestroyWindow(g_hDlgExit); | |
296 | g_hDlgExit = NULL; | |
297 | } | |
298 | ||
299 | /* Kill our window */ | |
300 | if (pScreenPriv->hwndScreen) { | |
301 | DestroyWindow(pScreenPriv->hwndScreen); | |
302 | pScreenPriv->hwndScreen = NULL; | |
303 | } | |
304 | ||
305 | /* Kill our screeninfo's pointer to the screen */ | |
306 | pScreenInfo->pScreen = NULL; | |
307 | ||
308 | /* Free the screen privates for this screen */ | |
309 | free((pointer) pScreenPriv); | |
310 | ||
311 | return fReturn; | |
312 | } | |
313 | ||
314 | /* | |
315 | * Tell mi what sort of visuals we need. | |
316 | * | |
317 | * Generally we only need one visual, as our screen can only | |
318 | * handle one format at a time, I believe. You may want | |
319 | * to verify that last sentence. | |
320 | */ | |
321 | ||
322 | static Bool | |
323 | winInitVisualsPrimaryDD(ScreenPtr pScreen) | |
324 | { | |
325 | winScreenPriv(pScreen); | |
326 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; | |
327 | DWORD dwRedBits, dwGreenBits, dwBlueBits; | |
328 | ||
329 | /* Count the number of ones in each color mask */ | |
330 | dwRedBits = winCountBits(pScreenPriv->dwRedMask); | |
331 | dwGreenBits = winCountBits(pScreenPriv->dwGreenMask); | |
332 | dwBlueBits = winCountBits(pScreenPriv->dwBlueMask); | |
333 | ||
334 | /* Store the maximum number of ones in a color mask as the bitsPerRGB */ | |
335 | if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) | |
336 | pScreenPriv->dwBitsPerRGB = dwRedBits; | |
337 | else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) | |
338 | pScreenPriv->dwBitsPerRGB = dwGreenBits; | |
339 | else | |
340 | pScreenPriv->dwBitsPerRGB = dwBlueBits; | |
341 | ||
342 | ErrorF("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n", | |
343 | (unsigned int) pScreenPriv->dwRedMask, | |
344 | (unsigned int) pScreenPriv->dwGreenMask, | |
345 | (unsigned int) pScreenPriv->dwBlueMask, | |
346 | (int) pScreenPriv->dwBitsPerRGB); | |
347 | ||
348 | /* Create a single visual according to the Windows screen depth */ | |
349 | switch (pScreenInfo->dwDepth) { | |
350 | case 24: | |
351 | case 16: | |
352 | case 15: | |
353 | if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth, | |
354 | TrueColorMask, | |
355 | pScreenPriv->dwBitsPerRGB, | |
356 | TrueColor, | |
357 | pScreenPriv->dwRedMask, | |
358 | pScreenPriv->dwGreenMask, | |
359 | pScreenPriv->dwBlueMask)) { | |
360 | ErrorF("winInitVisualsPrimaryDD - " | |
361 | "miSetVisualTypesAndMasks failed\n"); | |
362 | return FALSE; | |
363 | } | |
364 | break; | |
365 | ||
366 | case 8: | |
367 | #if CYGDEBUG | |
368 | winDebug("winInitVisuals - Calling miSetVisualTypesAndMasks\n"); | |
369 | #endif /* CYGDEBUG */ | |
370 | if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth, | |
371 | PseudoColorMask, | |
372 | pScreenPriv->dwBitsPerRGB, | |
373 | PseudoColor, | |
374 | pScreenPriv->dwRedMask, | |
375 | pScreenPriv->dwGreenMask, | |
376 | pScreenPriv->dwBlueMask)) { | |
377 | ErrorF("winInitVisualsPrimaryDD - " | |
378 | "miSetVisualTypesAndMasks failed\n"); | |
379 | return FALSE; | |
380 | } | |
381 | #if CYGDEBUG | |
382 | winDebug("winInitVisualsPrimaryDD - Returned from " | |
383 | "miSetVisualTypesAndMasks\n"); | |
384 | #endif /* CYGDEBUG */ | |
385 | break; | |
386 | ||
387 | default: | |
388 | ErrorF("winInitVisualsPrimaryDD - Unknown screen depth\n"); | |
389 | return FALSE; | |
390 | } | |
391 | ||
392 | ErrorF("winInitVisualsPrimaryDD - Returning\n"); | |
393 | ||
394 | return TRUE; | |
395 | } | |
396 | ||
397 | static Bool | |
398 | winAdjustVideoModePrimaryDD(ScreenPtr pScreen) | |
399 | { | |
400 | winScreenPriv(pScreen); | |
401 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; | |
402 | HDC hdc = NULL; | |
403 | DWORD dwBPP; | |
404 | ||
405 | /* We're in serious trouble if we can't get a DC */ | |
406 | hdc = GetDC(NULL); | |
407 | if (hdc == NULL) { | |
408 | ErrorF("winAdjustVideoModePrimaryDD - GetDC failed\n"); | |
409 | return FALSE; | |
410 | } | |
411 | ||
412 | /* Query GDI for current display depth */ | |
413 | dwBPP = GetDeviceCaps(hdc, BITSPIXEL); | |
414 | ||
415 | /* DirectDraw can only change the depth in fullscreen mode */ | |
416 | if (!(pScreenInfo->fFullScreen && (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) { | |
417 | /* Otherwise, We'll use GDI's depth */ | |
418 | pScreenInfo->dwBPP = dwBPP; | |
419 | } | |
420 | ||
421 | /* Release our DC */ | |
422 | ReleaseDC(NULL, hdc); | |
423 | ||
424 | return TRUE; | |
425 | } | |
426 | ||
427 | /* | |
428 | * We need to blit our offscreen fb to | |
429 | * the screen when we are activated, and we need to point | |
430 | * the fb code back to the primary surface memory. | |
431 | */ | |
432 | ||
433 | static Bool | |
434 | winActivateAppPrimaryDD(ScreenPtr pScreen) | |
435 | { | |
436 | winScreenPriv(pScreen); | |
437 | RECT rcSrc, rcClient; | |
438 | HRESULT ddrval = DD_OK; | |
439 | ||
440 | /* Check for errors */ | |
441 | if (pScreenPriv == NULL | |
442 | || pScreenPriv->pScreenInfo == NULL | |
443 | || pScreenPriv->pddsPrimary == NULL | |
444 | || pScreenPriv->pddsOffscreen == NULL) | |
445 | return FALSE; | |
446 | ||
447 | /* Check for do-nothing */ | |
448 | if (!pScreenPriv->fActive) | |
449 | return TRUE; | |
450 | ||
451 | /* We are activating */ | |
452 | ddrval = IDirectDrawSurface2_IsLost(pScreenPriv->pddsOffscreen); | |
453 | if (ddrval == DD_OK) { | |
454 | IDirectDrawSurface2_Unlock(pScreenPriv->pddsOffscreen, NULL); | |
455 | /* | |
456 | * We don't check for an error from Unlock, because it | |
457 | * doesn't matter if the Unlock failed. | |
458 | */ | |
459 | } | |
460 | ||
461 | /* Restore both surfaces, just cause I like it that way */ | |
462 | IDirectDrawSurface2_Restore(pScreenPriv->pddsOffscreen); | |
463 | IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary); | |
464 | ||
465 | /* Get client area in screen coords */ | |
466 | GetClientRect(pScreenPriv->hwndScreen, &rcClient); | |
467 | MapWindowPoints(pScreenPriv->hwndScreen, | |
468 | HWND_DESKTOP, (LPPOINT) &rcClient, 2); | |
469 | ||
470 | /* Setup a source rectangle */ | |
471 | rcSrc.left = 0; | |
472 | rcSrc.top = 0; | |
473 | rcSrc.right = pScreenPriv->pScreenInfo->dwWidth; | |
474 | rcSrc.bottom = pScreenPriv->pScreenInfo->dwHeight; | |
475 | ||
476 | ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsPrimary, | |
477 | &rcClient, | |
478 | pScreenPriv->pddsOffscreen, | |
479 | &rcSrc, DDBLT_WAIT, NULL); | |
480 | if (ddrval != DD_OK) | |
481 | FatalError("winActivateAppPrimaryDD () - Failed blitting offscreen " | |
482 | "surface to primary surface %08x\n", (unsigned int) ddrval); | |
483 | ||
484 | /* Lock the primary surface */ | |
485 | ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsPrimary, | |
486 | &rcClient, | |
487 | pScreenPriv->pddsdPrimary, | |
488 | DDLOCK_WAIT, NULL); | |
489 | if (ddrval != DD_OK || pScreenPriv->pddsdPrimary->lpSurface == NULL) | |
490 | FatalError("winActivateAppPrimaryDD () - Could not lock " | |
491 | "primary surface\n"); | |
492 | ||
493 | /* Notify FB of the new memory pointer */ | |
494 | winUpdateFBPointer(pScreen, pScreenPriv->pddsdPrimary->lpSurface); | |
495 | ||
496 | /* | |
497 | * Register the Alt-Tab combo as a hotkey so we can copy | |
498 | * the primary framebuffer before the display mode changes | |
499 | */ | |
500 | RegisterHotKey(pScreenPriv->hwndScreen, 1, MOD_ALT, 9); | |
501 | ||
502 | return TRUE; | |
503 | } | |
504 | ||
505 | /* | |
506 | * Handle the Alt+Tab hotkey. | |
507 | * | |
508 | * We need to save the primary fb to an offscreen fb when | |
509 | * we get deactivated, and point the fb code at the offscreen | |
510 | * fb for the duration of the deactivation. | |
511 | */ | |
512 | ||
513 | static Bool | |
514 | winHotKeyAltTabPrimaryDD(ScreenPtr pScreen) | |
515 | { | |
516 | winScreenPriv(pScreen); | |
517 | HRESULT ddrval = DD_OK; | |
518 | ||
519 | ErrorF("\nwinHotKeyAltTabPrimaryDD\n\n"); | |
520 | ||
521 | /* Alt+Tab was pressed, we will lose focus very soon */ | |
522 | pScreenPriv->fActive = FALSE; | |
523 | ||
524 | /* Check for error conditions */ | |
525 | if (pScreenPriv->pddsPrimary == NULL || pScreenPriv->pddsOffscreen == NULL) | |
526 | return FALSE; | |
527 | ||
528 | /* Did we loose the primary surface? */ | |
529 | ddrval = IDirectDrawSurface2_IsLost(pScreenPriv->pddsPrimary); | |
530 | if (ddrval == DD_OK) { | |
531 | ddrval = IDirectDrawSurface2_Unlock(pScreenPriv->pddsPrimary, NULL); | |
532 | if (FAILED(ddrval)) | |
533 | FatalError("winHotKeyAltTabPrimaryDD - Failed unlocking primary " | |
534 | "surface\n"); | |
535 | } | |
536 | ||
537 | /* Blit the primary surface to the offscreen surface */ | |
538 | ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsOffscreen, NULL, /* should be rcDest */ | |
539 | pScreenPriv->pddsPrimary, | |
540 | NULL, DDBLT_WAIT, NULL); | |
541 | if (ddrval == DDERR_SURFACELOST) { | |
542 | IDirectDrawSurface2_Restore(pScreenPriv->pddsOffscreen); | |
543 | IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary); | |
544 | ||
545 | /* Blit the primary surface to the offscreen surface */ | |
546 | ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsOffscreen, | |
547 | NULL, | |
548 | pScreenPriv->pddsPrimary, | |
549 | NULL, DDBLT_WAIT, NULL); | |
550 | if (FAILED(ddrval)) | |
551 | FatalError("winHotKeyAltTabPrimaryDD - Failed blitting primary " | |
552 | "surface to offscreen surface: %08x\n", | |
553 | (unsigned int) ddrval); | |
554 | } | |
555 | else { | |
556 | FatalError("winHotKeyAltTabPrimaryDD - Unknown error from " | |
557 | "Blt: %08dx\n", (unsigned int) ddrval); | |
558 | } | |
559 | ||
560 | /* Lock the offscreen surface */ | |
561 | ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsOffscreen, | |
562 | NULL, | |
563 | pScreenPriv->pddsdOffscreen, | |
564 | DDLOCK_WAIT, NULL); | |
565 | if (ddrval != DD_OK || pScreenPriv->pddsdPrimary->lpSurface == NULL) | |
566 | FatalError("winHotKeyAltTabPrimaryDD - Could not lock " | |
567 | "offscreen surface\n"); | |
568 | ||
569 | /* Notify FB of the new memory pointer */ | |
570 | winUpdateFBPointer(pScreen, pScreenPriv->pddsdOffscreen->lpSurface); | |
571 | ||
572 | /* Unregister our hotkey */ | |
573 | UnregisterHotKey(pScreenPriv->hwndScreen, 1); | |
574 | ||
575 | return TRUE; | |
576 | } | |
577 | ||
578 | /* Set engine specific functions */ | |
579 | Bool | |
580 | winSetEngineFunctionsPrimaryDD(ScreenPtr pScreen) | |
581 | { | |
582 | winScreenPriv(pScreen); | |
583 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; | |
584 | ||
585 | /* Set our pointers */ | |
586 | pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD; | |
587 | pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD; | |
588 | pScreenPriv->pwinShadowUpdate = | |
589 | (winShadowUpdateProcPtr) (void (*)(void)) NoopDDA; | |
590 | pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD; | |
591 | pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD; | |
592 | pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD; | |
593 | pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD; | |
594 | if (pScreenInfo->fFullScreen) | |
595 | pScreenPriv->pwinCreateBoundingWindow = | |
596 | winCreateBoundingWindowFullScreen; | |
597 | else | |
598 | pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; | |
599 | pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; | |
600 | pScreenPriv->pwinBltExposedRegions = | |
601 | (winBltExposedRegionsProcPtr) (void (*)(void)) NoopDDA; | |
602 | pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD; | |
603 | pScreenPriv->pwinRedrawScreen = NULL; | |
604 | pScreenPriv->pwinRealizeInstalledPalette = NULL; | |
605 | pScreenPriv->pwinInstallColormap = NULL; | |
606 | pScreenPriv->pwinStoreColors = NULL; | |
607 | pScreenPriv->pwinCreateColormap = NULL; | |
608 | pScreenPriv->pwinDestroyColormap = NULL; | |
609 | pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD; | |
610 | pScreenPriv->pwinCreatePrimarySurface = | |
611 | (winCreatePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA; | |
612 | pScreenPriv->pwinReleasePrimarySurface = | |
613 | (winReleasePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA; | |
614 | #ifdef XWIN_MULTIWINDOW | |
615 | pScreenPriv->pwinFinishCreateWindowsWindow = | |
616 | (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA; | |
617 | #endif | |
618 | ||
619 | return TRUE; | |
620 | } |