Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. | |
3 | *Copyright (C) Colin Harrison 2005-2008 | |
4 | * | |
5 | *Permission is hereby granted, free of charge, to any person obtaining | |
6 | * a copy of this software and associated documentation files (the | |
7 | *"Software"), to deal in the Software without restriction, including | |
8 | *without limitation the rights to use, copy, modify, merge, publish, | |
9 | *distribute, sublicense, and/or sell copies of the Software, and to | |
10 | *permit persons to whom the Software is furnished to do so, subject to | |
11 | *the following conditions: | |
12 | * | |
13 | *The above copyright notice and this permission notice shall be | |
14 | *included in all copies or substantial portions of the Software. | |
15 | * | |
16 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 | *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
19 | *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR | |
20 | *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
21 | *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
22 | *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
23 | * | |
24 | *Except as contained in this notice, the name of the XFree86 Project | |
25 | *shall not be used in advertising or otherwise to promote the sale, use | |
26 | *or other dealings in this Software without prior written authorization | |
27 | *from the XFree86 Project. | |
28 | * | |
29 | * Authors: Kensuke Matsuzaki | |
30 | * Earle F. Philhower, III | |
31 | * Harold L Hunt II | |
32 | * Colin Harrison | |
33 | */ | |
34 | ||
35 | #ifdef HAVE_XWIN_CONFIG_H | |
36 | #include <xwin-config.h> | |
37 | #endif | |
38 | #include "win.h" | |
39 | #include "dixevents.h" | |
40 | #include "winmultiwindowclass.h" | |
41 | ||
42 | /* | |
43 | * Prototypes for local functions | |
44 | */ | |
45 | ||
46 | void | |
47 | winCreateWindowsWindow(WindowPtr pWin); | |
48 | ||
49 | static void | |
50 | winDestroyWindowsWindow(WindowPtr pWin); | |
51 | ||
52 | static void | |
53 | winUpdateWindowsWindow(WindowPtr pWin); | |
54 | ||
55 | static void | |
56 | winFindWindow(pointer value, XID id, pointer cdata); | |
57 | ||
58 | static | |
59 | void | |
60 | winInitMultiWindowClass(void) | |
61 | { | |
62 | static wATOM atomXWinClass = 0; | |
63 | WNDCLASSEX wcx; | |
64 | ||
65 | if (atomXWinClass == 0) { | |
66 | HICON hIcon, hIconSmall; | |
67 | ||
68 | /* Load the default icons */ | |
69 | winSelectIcons(&hIcon, &hIconSmall); | |
70 | ||
71 | /* Setup our window class */ | |
72 | wcx.cbSize = sizeof(WNDCLASSEX); | |
73 | wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0); | |
74 | wcx.lpfnWndProc = winTopLevelWindowProc; | |
75 | wcx.cbClsExtra = 0; | |
76 | wcx.cbWndExtra = 0; | |
77 | wcx.hInstance = g_hInstance; | |
78 | wcx.hIcon = hIcon; | |
79 | wcx.hCursor = 0; | |
80 | wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); | |
81 | wcx.lpszMenuName = NULL; | |
82 | wcx.lpszClassName = WINDOW_CLASS_X; | |
83 | wcx.hIconSm = hIconSmall; | |
84 | ||
85 | #if CYGMULTIWINDOW_DEBUG | |
86 | ErrorF("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X); | |
87 | #endif | |
88 | ||
89 | atomXWinClass = RegisterClassEx(&wcx); | |
90 | } | |
91 | } | |
92 | ||
93 | /* | |
94 | * CreateWindow - See Porting Layer Definition - p. 37 | |
95 | */ | |
96 | ||
97 | Bool | |
98 | winCreateWindowMultiWindow(WindowPtr pWin) | |
99 | { | |
100 | Bool fResult = TRUE; | |
101 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
102 | ||
103 | winWindowPriv(pWin); | |
104 | winScreenPriv(pScreen); | |
105 | ||
106 | #if CYGMULTIWINDOW_DEBUG | |
107 | winTrace("winCreateWindowMultiWindow - pWin: %p\n", pWin); | |
108 | #endif | |
109 | ||
110 | WIN_UNWRAP(CreateWindow); | |
111 | fResult = (*pScreen->CreateWindow) (pWin); | |
112 | WIN_WRAP(CreateWindow, winCreateWindowMultiWindow); | |
113 | ||
114 | /* Initialize some privates values */ | |
115 | pWinPriv->hRgn = NULL; | |
116 | pWinPriv->hWnd = NULL; | |
117 | pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen); | |
118 | pWinPriv->fXKilled = FALSE; | |
119 | #ifdef XWIN_GLX_WINDOWS | |
120 | pWinPriv->fWglUsed = FALSE; | |
121 | #endif | |
122 | ||
123 | return fResult; | |
124 | } | |
125 | ||
126 | /* | |
127 | * DestroyWindow - See Porting Layer Definition - p. 37 | |
128 | */ | |
129 | ||
130 | Bool | |
131 | winDestroyWindowMultiWindow(WindowPtr pWin) | |
132 | { | |
133 | Bool fResult = TRUE; | |
134 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
135 | ||
136 | winWindowPriv(pWin); | |
137 | winScreenPriv(pScreen); | |
138 | ||
139 | #if CYGMULTIWINDOW_DEBUG | |
140 | ErrorF("winDestroyWindowMultiWindow - pWin: %p\n", pWin); | |
141 | #endif | |
142 | ||
143 | WIN_UNWRAP(DestroyWindow); | |
144 | fResult = (*pScreen->DestroyWindow) (pWin); | |
145 | WIN_WRAP(DestroyWindow, winDestroyWindowMultiWindow); | |
146 | ||
147 | /* Flag that the window has been destroyed */ | |
148 | pWinPriv->fXKilled = TRUE; | |
149 | ||
150 | /* Kill the MS Windows window associated with this window */ | |
151 | winDestroyWindowsWindow(pWin); | |
152 | ||
153 | return fResult; | |
154 | } | |
155 | ||
156 | /* | |
157 | * PositionWindow - See Porting Layer Definition - p. 37 | |
158 | * | |
159 | * This function adjusts the position and size of Windows window | |
160 | * with respect to the underlying X window. This is the inverse | |
161 | * of winAdjustXWindow, which adjusts X window to Windows window. | |
162 | */ | |
163 | ||
164 | Bool | |
165 | winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) | |
166 | { | |
167 | Bool fResult = TRUE; | |
168 | int iX, iY, iWidth, iHeight; | |
169 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
170 | ||
171 | winWindowPriv(pWin); | |
172 | winScreenPriv(pScreen); | |
173 | ||
174 | HWND hWnd = pWinPriv->hWnd; | |
175 | RECT rcNew; | |
176 | RECT rcOld; | |
177 | ||
178 | #if CYGMULTIWINDOW_DEBUG | |
179 | RECT rcClient; | |
180 | RECT *lpRc; | |
181 | #endif | |
182 | DWORD dwExStyle; | |
183 | DWORD dwStyle; | |
184 | ||
185 | #if CYGMULTIWINDOW_DEBUG | |
186 | winTrace("winPositionWindowMultiWindow - pWin: %p\n", pWin); | |
187 | #endif | |
188 | ||
189 | WIN_UNWRAP(PositionWindow); | |
190 | fResult = (*pScreen->PositionWindow) (pWin, x, y); | |
191 | WIN_WRAP(PositionWindow, winPositionWindowMultiWindow); | |
192 | ||
193 | #if CYGWINDOWING_DEBUG | |
194 | ErrorF("winPositionWindowMultiWindow: (x, y) = (%d, %d)\n", x, y); | |
195 | #endif | |
196 | ||
197 | /* Bail out if the Windows window handle is bad */ | |
198 | if (!hWnd) { | |
199 | #if CYGWINDOWING_DEBUG | |
200 | ErrorF("\timmediately return since hWnd is NULL\n"); | |
201 | #endif | |
202 | return fResult; | |
203 | } | |
204 | ||
205 | /* Get the Windows window style and extended style */ | |
206 | dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); | |
207 | dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); | |
208 | ||
209 | /* Get the X and Y location of the X window */ | |
210 | iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); | |
211 | iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); | |
212 | ||
213 | /* Get the height and width of the X window */ | |
214 | iWidth = pWin->drawable.width; | |
215 | iHeight = pWin->drawable.height; | |
216 | ||
217 | /* Store the origin, height, and width in a rectangle structure */ | |
218 | SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight); | |
219 | ||
220 | #if CYGMULTIWINDOW_DEBUG | |
221 | lpRc = &rcNew; | |
222 | ErrorF("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n", | |
223 | GetTickCount(), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); | |
224 | #endif | |
225 | ||
226 | /* | |
227 | * Calculate the required size of the Windows window rectangle, | |
228 | * given the size of the Windows window client area. | |
229 | */ | |
230 | AdjustWindowRectEx(&rcNew, dwStyle, FALSE, dwExStyle); | |
231 | ||
232 | /* Get a rectangle describing the old Windows window */ | |
233 | GetWindowRect(hWnd, &rcOld); | |
234 | ||
235 | #if CYGMULTIWINDOW_DEBUG | |
236 | /* Get a rectangle describing the Windows window client area */ | |
237 | GetClientRect(hWnd, &rcClient); | |
238 | ||
239 | lpRc = &rcNew; | |
240 | ErrorF("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n", | |
241 | GetTickCount(), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); | |
242 | ||
243 | lpRc = &rcOld; | |
244 | ErrorF("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n", | |
245 | GetTickCount(), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); | |
246 | ||
247 | lpRc = &rcClient; | |
248 | ErrorF("(%d ms)rcClient (%d, %d)-(%d, %d)\n", | |
249 | GetTickCount(), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); | |
250 | #endif | |
251 | ||
252 | /* Check if the old rectangle and new rectangle are the same */ | |
253 | if (!EqualRect(&rcNew, &rcOld)) { | |
254 | #if CYGMULTIWINDOW_DEBUG | |
255 | ErrorF("winPositionWindowMultiWindow - Need to move\n"); | |
256 | #endif | |
257 | ||
258 | #if CYGWINDOWING_DEBUG | |
259 | ErrorF("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top, | |
260 | rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); | |
261 | #endif | |
262 | /* Change the position and dimensions of the Windows window */ | |
263 | MoveWindow(hWnd, | |
264 | rcNew.left, rcNew.top, | |
265 | rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, TRUE); | |
266 | } | |
267 | else { | |
268 | #if CYGMULTIWINDOW_DEBUG | |
269 | ErrorF("winPositionWindowMultiWindow - Not need to move\n"); | |
270 | #endif | |
271 | } | |
272 | ||
273 | return fResult; | |
274 | } | |
275 | ||
276 | /* | |
277 | * ChangeWindowAttributes - See Porting Layer Definition - p. 37 | |
278 | */ | |
279 | ||
280 | Bool | |
281 | winChangeWindowAttributesMultiWindow(WindowPtr pWin, unsigned long mask) | |
282 | { | |
283 | Bool fResult = TRUE; | |
284 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
285 | ||
286 | winScreenPriv(pScreen); | |
287 | ||
288 | #if CYGMULTIWINDOW_DEBUG | |
289 | ErrorF("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin); | |
290 | #endif | |
291 | ||
292 | WIN_UNWRAP(ChangeWindowAttributes); | |
293 | fResult = (*pScreen->ChangeWindowAttributes) (pWin, mask); | |
294 | WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesMultiWindow); | |
295 | ||
296 | /* | |
297 | * NOTE: We do not currently need to do anything here. | |
298 | */ | |
299 | ||
300 | return fResult; | |
301 | } | |
302 | ||
303 | /* | |
304 | * UnmapWindow - See Porting Layer Definition - p. 37 | |
305 | * Also referred to as UnrealizeWindow | |
306 | */ | |
307 | ||
308 | Bool | |
309 | winUnmapWindowMultiWindow(WindowPtr pWin) | |
310 | { | |
311 | Bool fResult = TRUE; | |
312 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
313 | ||
314 | winWindowPriv(pWin); | |
315 | winScreenPriv(pScreen); | |
316 | ||
317 | #if CYGMULTIWINDOW_DEBUG | |
318 | ErrorF("winUnmapWindowMultiWindow - pWin: %08x\n", pWin); | |
319 | #endif | |
320 | ||
321 | WIN_UNWRAP(UnrealizeWindow); | |
322 | fResult = (*pScreen->UnrealizeWindow) (pWin); | |
323 | WIN_WRAP(UnrealizeWindow, winUnmapWindowMultiWindow); | |
324 | ||
325 | /* Flag that the window has been killed */ | |
326 | pWinPriv->fXKilled = TRUE; | |
327 | ||
328 | /* Destroy the Windows window associated with this X window */ | |
329 | winDestroyWindowsWindow(pWin); | |
330 | ||
331 | return fResult; | |
332 | } | |
333 | ||
334 | /* | |
335 | * MapWindow - See Porting Layer Definition - p. 37 | |
336 | * Also referred to as RealizeWindow | |
337 | */ | |
338 | ||
339 | Bool | |
340 | winMapWindowMultiWindow(WindowPtr pWin) | |
341 | { | |
342 | Bool fResult = TRUE; | |
343 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
344 | ||
345 | winWindowPriv(pWin); | |
346 | winScreenPriv(pScreen); | |
347 | ||
348 | #if CYGMULTIWINDOW_DEBUG | |
349 | ErrorF("winMapWindowMultiWindow - pWin: %08x\n", pWin); | |
350 | #endif | |
351 | ||
352 | WIN_UNWRAP(RealizeWindow); | |
353 | fResult = (*pScreen->RealizeWindow) (pWin); | |
354 | WIN_WRAP(RealizeWindow, winMapWindowMultiWindow); | |
355 | ||
356 | /* Flag that this window has not been destroyed */ | |
357 | pWinPriv->fXKilled = FALSE; | |
358 | ||
359 | /* Refresh/redisplay the Windows window associated with this X window */ | |
360 | winUpdateWindowsWindow(pWin); | |
361 | ||
362 | /* Update the Windows window's shape */ | |
363 | winReshapeMultiWindow(pWin); | |
364 | winUpdateRgnMultiWindow(pWin); | |
365 | ||
366 | return fResult; | |
367 | } | |
368 | ||
369 | /* | |
370 | * ReparentWindow - See Porting Layer Definition - p. 42 | |
371 | */ | |
372 | ||
373 | void | |
374 | winReparentWindowMultiWindow(WindowPtr pWin, WindowPtr pPriorParent) | |
375 | { | |
376 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
377 | ||
378 | winScreenPriv(pScreen); | |
379 | ||
380 | winDebug | |
381 | ("winReparentMultiWindow - pWin:%08x XID:0x%x, reparent from pWin:%08x XID:0x%x to pWin:%08x XID:0x%x\n", | |
382 | pWin, pWin->drawable.id, pPriorParent, pPriorParent->drawable.id, | |
383 | pWin->parent, pWin->parent->drawable.id); | |
384 | ||
385 | WIN_UNWRAP(ReparentWindow); | |
386 | if (pScreen->ReparentWindow) | |
387 | (*pScreen->ReparentWindow) (pWin, pPriorParent); | |
388 | WIN_WRAP(ReparentWindow, winReparentWindowMultiWindow); | |
389 | ||
390 | /* Update the Windows window associated with this X window */ | |
391 | winUpdateWindowsWindow(pWin); | |
392 | } | |
393 | ||
394 | /* | |
395 | * RestackWindow - Shuffle the z-order of a window | |
396 | */ | |
397 | ||
398 | void | |
399 | winRestackWindowMultiWindow(WindowPtr pWin, WindowPtr pOldNextSib) | |
400 | { | |
401 | #if 0 | |
402 | WindowPtr pPrevWin; | |
403 | UINT uFlags; | |
404 | HWND hInsertAfter; | |
405 | HWND hWnd = NULL; | |
406 | #endif | |
407 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
408 | ||
409 | winScreenPriv(pScreen); | |
410 | ||
411 | #if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG | |
412 | winTrace("winRestackMultiWindow - %08x\n", pWin); | |
413 | #endif | |
414 | ||
415 | WIN_UNWRAP(RestackWindow); | |
416 | if (pScreen->RestackWindow) | |
417 | (*pScreen->RestackWindow) (pWin, pOldNextSib); | |
418 | WIN_WRAP(RestackWindow, winRestackWindowMultiWindow); | |
419 | ||
420 | #if 1 | |
421 | /* | |
422 | * Calling winReorderWindowsMultiWindow here means our window manager | |
423 | * (i.e. Windows Explorer) has initiative to determine Z order. | |
424 | */ | |
425 | if (pWin->nextSib != pOldNextSib) | |
426 | winReorderWindowsMultiWindow(); | |
427 | #else | |
428 | /* Bail out if no window privates or window handle is invalid */ | |
429 | if (!pWinPriv || !pWinPriv->hWnd) | |
430 | return; | |
431 | ||
432 | /* Get a pointer to our previous sibling window */ | |
433 | pPrevWin = pWin->prevSib; | |
434 | ||
435 | /* | |
436 | * Look for a sibling window with | |
437 | * valid privates and window handle | |
438 | */ | |
439 | while (pPrevWin && !winGetWindowPriv(pPrevWin) | |
440 | && !winGetWindowPriv(pPrevWin)->hWnd) | |
441 | pPrevWin = pPrevWin->prevSib; | |
442 | ||
443 | /* Check if we found a valid sibling */ | |
444 | if (pPrevWin) { | |
445 | /* Valid sibling - get handle to insert window after */ | |
446 | hInsertAfter = winGetWindowPriv(pPrevWin)->hWnd; | |
447 | uFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; | |
448 | ||
449 | hWnd = GetNextWindow(pWinPriv->hWnd, GW_HWNDPREV); | |
450 | ||
451 | do { | |
452 | if (GetProp(hWnd, WIN_WINDOW_PROP)) { | |
453 | if (hWnd == winGetWindowPriv(pPrevWin)->hWnd) { | |
454 | uFlags |= SWP_NOZORDER; | |
455 | } | |
456 | break; | |
457 | } | |
458 | hWnd = GetNextWindow(hWnd, GW_HWNDPREV); | |
459 | } | |
460 | while (hWnd); | |
461 | } | |
462 | else { | |
463 | /* No valid sibling - make this window the top window */ | |
464 | hInsertAfter = HWND_TOP; | |
465 | uFlags = SWP_NOMOVE | SWP_NOSIZE; | |
466 | } | |
467 | ||
468 | /* Perform the restacking operation in Windows */ | |
469 | SetWindowPos(pWinPriv->hWnd, hInsertAfter, 0, 0, 0, 0, uFlags); | |
470 | #endif | |
471 | } | |
472 | ||
473 | /* | |
474 | * winCreateWindowsWindow - Create a Windows window associated with an X window | |
475 | */ | |
476 | ||
477 | void | |
478 | winCreateWindowsWindow(WindowPtr pWin) | |
479 | { | |
480 | int iX, iY; | |
481 | int iWidth; | |
482 | int iHeight; | |
483 | HWND hWnd; | |
484 | HWND hFore = NULL; | |
485 | ||
486 | winWindowPriv(pWin); | |
487 | winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; | |
488 | WinXSizeHints hints; | |
489 | Window daddyId; | |
490 | DWORD dwStyle, dwExStyle; | |
491 | RECT rc; | |
492 | ||
493 | winInitMultiWindowClass(); | |
494 | ||
495 | winDebug("winCreateWindowsTopLevelWindow - pWin:%08x XID:0x%x \n", pWin, | |
496 | pWin->drawable.id); | |
497 | ||
498 | iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); | |
499 | iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); | |
500 | ||
501 | iWidth = pWin->drawable.width; | |
502 | iHeight = pWin->drawable.height; | |
503 | ||
504 | /* If it's an InputOutput window, and so is going to end up being made visible, | |
505 | make sure the window actually ends up somewhere where it will be visible */ | |
506 | if (pWin->drawable.class != InputOnly) { | |
507 | if ((iX < GetSystemMetrics(SM_XVIRTUALSCREEN)) || | |
508 | (iX > GetSystemMetrics(SM_CXVIRTUALSCREEN))) | |
509 | iX = CW_USEDEFAULT; | |
510 | ||
511 | if ((iY < GetSystemMetrics(SM_YVIRTUALSCREEN)) || | |
512 | (iY > GetSystemMetrics(SM_CYVIRTUALSCREEN))) | |
513 | iY = CW_USEDEFAULT; | |
514 | } | |
515 | ||
516 | winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, | |
517 | iY); | |
518 | ||
519 | if (winMultiWindowGetTransientFor(pWin, &daddyId)) { | |
520 | if (daddyId) { | |
521 | hFore = GetForegroundWindow(); | |
522 | if (hFore && (daddyId != (Window) (INT_PTR) GetProp(hFore, WIN_WID_PROP))) | |
523 | hFore = NULL; | |
524 | } | |
525 | } | |
526 | else { | |
527 | /* Default positions if none specified */ | |
528 | if (!winMultiWindowGetWMNormalHints(pWin, &hints)) | |
529 | hints.flags = 0; | |
530 | if (!(hints.flags & (USPosition | PPosition)) && | |
531 | !pWin->overrideRedirect) { | |
532 | iX = CW_USEDEFAULT; | |
533 | iY = CW_USEDEFAULT; | |
534 | } | |
535 | } | |
536 | ||
537 | /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */ | |
538 | /* CW_USEDEFAULT, change back to popup after creation */ | |
539 | dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; | |
540 | dwExStyle = WS_EX_TOOLWINDOW; | |
541 | ||
542 | /* | |
543 | Calculate the window coordinates containing the requested client area, | |
544 | being careful to preseve CW_USEDEFAULT | |
545 | */ | |
546 | rc.top = (iY != CW_USEDEFAULT) ? iY : 0; | |
547 | rc.left = (iX != CW_USEDEFAULT) ? iX : 0; | |
548 | rc.bottom = rc.top + iHeight; | |
549 | rc.right = rc.left + iWidth; | |
550 | AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); | |
551 | if (iY != CW_USEDEFAULT) | |
552 | iY = rc.top; | |
553 | if (iX != CW_USEDEFAULT) | |
554 | iX = rc.left; | |
555 | iHeight = rc.bottom - rc.top; | |
556 | iWidth = rc.right - rc.left; | |
557 | ||
558 | winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, | |
559 | iY); | |
560 | ||
561 | /* Create the window */ | |
562 | hWnd = CreateWindowExA(dwExStyle, /* Extended styles */ | |
563 | WINDOW_CLASS_X, /* Class name */ | |
564 | WINDOW_TITLE_X, /* Window name */ | |
565 | dwStyle, /* Styles */ | |
566 | iX, /* Horizontal position */ | |
567 | iY, /* Vertical position */ | |
568 | iWidth, /* Right edge */ | |
569 | iHeight, /* Bottom edge */ | |
570 | hFore, /* Null or Parent window if transient */ | |
571 | (HMENU) NULL, /* No menu */ | |
572 | GetModuleHandle(NULL), /* Instance handle */ | |
573 | pWin); /* ScreenPrivates */ | |
574 | if (hWnd == NULL) { | |
575 | ErrorF("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", | |
576 | (int) GetLastError()); | |
577 | } | |
578 | pWinPriv->hWnd = hWnd; | |
579 | ||
580 | /* Change style back to popup, already placed... */ | |
581 | SetWindowLongPtr(hWnd, GWL_STYLE, | |
582 | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); | |
583 | SetWindowPos(hWnd, 0, 0, 0, 0, 0, | |
584 | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | | |
585 | SWP_NOACTIVATE); | |
586 | ||
587 | /* Adjust the X window to match the window placement we actually got... */ | |
588 | winAdjustXWindow(pWin, hWnd); | |
589 | ||
590 | /* Make sure it gets the proper system menu for a WS_POPUP, too */ | |
591 | GetSystemMenu(hWnd, TRUE); | |
592 | ||
593 | /* Cause any .XWinrc menus to be added in main WNDPROC */ | |
594 | PostMessage(hWnd, WM_INIT_SYS_MENU, 0, 0); | |
595 | ||
596 | SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(pWin)); | |
597 | ||
598 | /* Flag that this Windows window handles its own activation */ | |
599 | SetProp(hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0); | |
600 | ||
601 | /* Call engine-specific create window procedure */ | |
602 | (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin); | |
603 | } | |
604 | ||
605 | Bool winInDestroyWindowsWindow = FALSE; | |
606 | ||
607 | /* | |
608 | * winDestroyWindowsWindow - Destroy a Windows window associated | |
609 | * with an X window | |
610 | */ | |
611 | static void | |
612 | winDestroyWindowsWindow(WindowPtr pWin) | |
613 | { | |
614 | MSG msg; | |
615 | ||
616 | winWindowPriv(pWin); | |
617 | BOOL oldstate = winInDestroyWindowsWindow; | |
618 | HICON hIcon; | |
619 | HICON hIconSm; | |
620 | ||
621 | winDebug("winDestroyWindowsWindow - pWin:%08x XID:0x%x \n", pWin, | |
622 | pWin->drawable.id); | |
623 | ||
624 | /* Bail out if the Windows window handle is invalid */ | |
625 | if (pWinPriv->hWnd == NULL) | |
626 | return; | |
627 | ||
628 | winInDestroyWindowsWindow = TRUE; | |
629 | ||
630 | /* Store the info we need to destroy after this window is gone */ | |
631 | hIcon = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_BIG, 0); | |
632 | hIconSm = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0); | |
633 | ||
634 | /* Destroy the Windows window */ | |
635 | DestroyWindow(pWinPriv->hWnd); | |
636 | ||
637 | /* Null our handle to the Window so referencing it will cause an error */ | |
638 | pWinPriv->hWnd = NULL; | |
639 | ||
640 | /* Destroy any icons we created for this window */ | |
641 | winDestroyIcon(hIcon); | |
642 | winDestroyIcon(hIconSm); | |
643 | ||
644 | #ifdef XWIN_GLX_WINDOWS | |
645 | /* No longer note WGL used on this window */ | |
646 | pWinPriv->fWglUsed = FALSE; | |
647 | #endif | |
648 | ||
649 | /* Process all messages on our queue */ | |
650 | while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { | |
651 | if (g_hDlgDepthChange == 0 || !IsDialogMessage(g_hDlgDepthChange, &msg)) { | |
652 | DispatchMessage(&msg); | |
653 | } | |
654 | } | |
655 | ||
656 | winInDestroyWindowsWindow = oldstate; | |
657 | ||
658 | winDebug("winDestroyWindowsWindow - done\n"); | |
659 | } | |
660 | ||
661 | /* | |
662 | * winUpdateWindowsWindow - Redisplay/redraw a Windows window | |
663 | * associated with an X window | |
664 | */ | |
665 | ||
666 | static void | |
667 | winUpdateWindowsWindow(WindowPtr pWin) | |
668 | { | |
669 | winWindowPriv(pWin); | |
670 | HWND hWnd = pWinPriv->hWnd; | |
671 | ||
672 | #if CYGMULTIWINDOW_DEBUG | |
673 | ErrorF("winUpdateWindowsWindow\n"); | |
674 | #endif | |
675 | ||
676 | /* Check if the Windows window's parents have been destroyed */ | |
677 | if (pWin->parent != NULL && pWin->parent->parent == NULL && pWin->mapped) { | |
678 | /* Create the Windows window if it has been destroyed */ | |
679 | if (hWnd == NULL) { | |
680 | winCreateWindowsWindow(pWin); | |
681 | assert(pWinPriv->hWnd != NULL); | |
682 | } | |
683 | ||
684 | /* Display the window without activating it */ | |
685 | if (pWin->drawable.class != InputOnly) | |
686 | ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE); | |
687 | ||
688 | /* Send first paint message */ | |
689 | UpdateWindow(pWinPriv->hWnd); | |
690 | } | |
691 | else if (hWnd != NULL) { | |
692 | /* Destroy the Windows window if its parents are destroyed */ | |
693 | winDestroyWindowsWindow(pWin); | |
694 | assert(pWinPriv->hWnd == NULL); | |
695 | } | |
696 | ||
697 | #if CYGMULTIWINDOW_DEBUG | |
698 | ErrorF("-winUpdateWindowsWindow\n"); | |
699 | #endif | |
700 | } | |
701 | ||
702 | /* | |
703 | * winGetWindowID - | |
704 | */ | |
705 | ||
706 | XID | |
707 | winGetWindowID(WindowPtr pWin) | |
708 | { | |
709 | WindowIDPairRec wi = { pWin, 0 }; | |
710 | ClientPtr c = wClient(pWin); | |
711 | ||
712 | /* */ | |
713 | FindClientResourcesByType(c, RT_WINDOW, winFindWindow, &wi); | |
714 | ||
715 | #if CYGMULTIWINDOW_DEBUG | |
716 | ErrorF("winGetWindowID - Window ID: %d\n", wi.id); | |
717 | #endif | |
718 | ||
719 | return wi.id; | |
720 | } | |
721 | ||
722 | /* | |
723 | * winFindWindow - | |
724 | */ | |
725 | ||
726 | static void | |
727 | winFindWindow(pointer value, XID id, pointer cdata) | |
728 | { | |
729 | WindowIDPairPtr wi = (WindowIDPairPtr) cdata; | |
730 | ||
731 | if (value == wi->value) { | |
732 | wi->id = id; | |
733 | } | |
734 | } | |
735 | ||
736 | /* | |
737 | * winReorderWindowsMultiWindow - | |
738 | */ | |
739 | ||
740 | void | |
741 | winReorderWindowsMultiWindow(void) | |
742 | { | |
743 | HWND hwnd = NULL; | |
744 | WindowPtr pWin = NULL; | |
745 | WindowPtr pWinSib = NULL; | |
746 | XID vlist[2]; | |
747 | static Bool fRestacking = FALSE; /* Avoid recusive calls to this function */ | |
748 | DWORD dwCurrentProcessID = GetCurrentProcessId(); | |
749 | DWORD dwWindowProcessID = 0; | |
750 | ||
751 | #if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG | |
752 | winTrace("winReorderWindowsMultiWindow\n"); | |
753 | #endif | |
754 | ||
755 | if (fRestacking) { | |
756 | /* It is a recusive call so immediately exit */ | |
757 | #if CYGWINDOWING_DEBUG | |
758 | ErrorF("winReorderWindowsMultiWindow - " | |
759 | "exit because fRestacking == TRUE\n"); | |
760 | #endif | |
761 | return; | |
762 | } | |
763 | fRestacking = TRUE; | |
764 | ||
765 | /* Loop through top level Window windows, descending in Z order */ | |
766 | for (hwnd = GetTopWindow(NULL); | |
767 | hwnd; hwnd = GetNextWindow(hwnd, GW_HWNDNEXT)) { | |
768 | /* Don't take care of other Cygwin/X process's windows */ | |
769 | GetWindowThreadProcessId(hwnd, &dwWindowProcessID); | |
770 | ||
771 | if (GetProp(hwnd, WIN_WINDOW_PROP) | |
772 | && (dwWindowProcessID == dwCurrentProcessID) | |
773 | && !IsIconic(hwnd)) { /* ignore minimized windows */ | |
774 | pWinSib = pWin; | |
775 | pWin = GetProp(hwnd, WIN_WINDOW_PROP); | |
776 | ||
777 | if (!pWinSib) { /* 1st window - raise to the top */ | |
778 | vlist[0] = Above; | |
779 | ||
780 | ConfigureWindow(pWin, CWStackMode, vlist, wClient(pWin)); | |
781 | } | |
782 | else { /* 2nd or deeper windows - just below the previous one */ | |
783 | vlist[0] = winGetWindowID(pWinSib); | |
784 | vlist[1] = Below; | |
785 | ||
786 | ConfigureWindow(pWin, CWSibling | CWStackMode, | |
787 | vlist, wClient(pWin)); | |
788 | } | |
789 | } | |
790 | } | |
791 | ||
792 | fRestacking = FALSE; | |
793 | } | |
794 | ||
795 | /* | |
796 | * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE | |
797 | */ | |
798 | ||
799 | void | |
800 | winMinimizeWindow(Window id) | |
801 | { | |
802 | WindowPtr pWin; | |
803 | winPrivWinPtr pWinPriv; | |
804 | ||
805 | #ifdef XWIN_MULTIWINDOWEXTWM | |
806 | win32RootlessWindowPtr pRLWinPriv; | |
807 | #endif | |
808 | HWND hWnd; | |
809 | ScreenPtr pScreen = NULL; | |
810 | winPrivScreenPtr pScreenPriv = NULL; | |
811 | ||
812 | #if CYGWINDOWING_DEBUG | |
813 | ErrorF("winMinimizeWindow\n"); | |
814 | #endif | |
815 | ||
816 | dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, | |
817 | DixUnknownAccess); | |
818 | if (!pWin) { | |
819 | ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__); | |
820 | return; | |
821 | } | |
822 | ||
823 | pScreen = pWin->drawable.pScreen; | |
824 | if (pScreen) | |
825 | pScreenPriv = winGetScreenPriv(pScreen); | |
826 | ||
827 | #ifdef XWIN_MULTIWINDOWEXTWM | |
828 | if (pScreenPriv && pScreenPriv->pScreenInfo->fInternalWM) { | |
829 | pRLWinPriv = | |
830 | (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, FALSE); | |
831 | hWnd = pRLWinPriv->hWnd; | |
832 | } | |
833 | else | |
834 | #else | |
835 | if (pScreenPriv) | |
836 | #endif | |
837 | { | |
838 | pWinPriv = winGetWindowPriv(pWin); | |
839 | hWnd = pWinPriv->hWnd; | |
840 | } | |
841 | ||
842 | ShowWindow(hWnd, SW_MINIMIZE); | |
843 | } | |
844 | ||
845 | /* | |
846 | * CopyWindow - See Porting Layer Definition - p. 39 | |
847 | */ | |
848 | void | |
849 | winCopyWindowMultiWindow(WindowPtr pWin, DDXPointRec oldpt, RegionPtr oldRegion) | |
850 | { | |
851 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
852 | ||
853 | winScreenPriv(pScreen); | |
854 | ||
855 | #if CYGWINDOWING_DEBUG | |
856 | ErrorF("CopyWindowMultiWindow\n"); | |
857 | #endif | |
858 | WIN_UNWRAP(CopyWindow); | |
859 | (*pScreen->CopyWindow) (pWin, oldpt, oldRegion); | |
860 | WIN_WRAP(CopyWindow, winCopyWindowMultiWindow); | |
861 | } | |
862 | ||
863 | /* | |
864 | * MoveWindow - See Porting Layer Definition - p. 42 | |
865 | */ | |
866 | void | |
867 | winMoveWindowMultiWindow(WindowPtr pWin, int x, int y, | |
868 | WindowPtr pSib, VTKind kind) | |
869 | { | |
870 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
871 | ||
872 | winScreenPriv(pScreen); | |
873 | ||
874 | #if CYGWINDOWING_DEBUG | |
875 | ErrorF("MoveWindowMultiWindow to (%d, %d)\n", x, y); | |
876 | #endif | |
877 | ||
878 | WIN_UNWRAP(MoveWindow); | |
879 | (*pScreen->MoveWindow) (pWin, x, y, pSib, kind); | |
880 | WIN_WRAP(MoveWindow, winMoveWindowMultiWindow); | |
881 | } | |
882 | ||
883 | /* | |
884 | * ResizeWindow - See Porting Layer Definition - p. 42 | |
885 | */ | |
886 | void | |
887 | winResizeWindowMultiWindow(WindowPtr pWin, int x, int y, unsigned int w, | |
888 | unsigned int h, WindowPtr pSib) | |
889 | { | |
890 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
891 | ||
892 | winScreenPriv(pScreen); | |
893 | ||
894 | #if CYGWINDOWING_DEBUG | |
895 | ErrorF("ResizeWindowMultiWindow to (%d, %d) - %dx%d\n", x, y, w, h); | |
896 | #endif | |
897 | WIN_UNWRAP(ResizeWindow); | |
898 | (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib); | |
899 | WIN_WRAP(ResizeWindow, winResizeWindowMultiWindow); | |
900 | } | |
901 | ||
902 | /* | |
903 | * winAdjustXWindow | |
904 | * | |
905 | * Move and resize X window with respect to corresponding Windows window. | |
906 | * This is called from WM_MOVE/WM_SIZE handlers when the user performs | |
907 | * any windowing operation (move, resize, minimize, maximize, restore). | |
908 | * | |
909 | * The functionality is the inverse of winPositionWindowMultiWindow, which | |
910 | * adjusts Windows window with respect to X window. | |
911 | */ | |
912 | int | |
913 | winAdjustXWindow(WindowPtr pWin, HWND hwnd) | |
914 | { | |
915 | RECT rcDraw; /* Rect made from pWin->drawable to be adjusted */ | |
916 | RECT rcWin; /* The source: WindowRect from hwnd */ | |
917 | DrawablePtr pDraw; | |
918 | XID vlist[4]; | |
919 | LONG dX, dY, dW, dH, x, y; | |
920 | DWORD dwStyle, dwExStyle; | |
921 | ||
922 | #define WIDTH(rc) (rc.right - rc.left) | |
923 | #define HEIGHT(rc) (rc.bottom - rc.top) | |
924 | ||
925 | #if CYGWINDOWING_DEBUG | |
926 | ErrorF("winAdjustXWindow\n"); | |
927 | #endif | |
928 | ||
929 | if (IsIconic(hwnd)) { | |
930 | #if CYGWINDOWING_DEBUG | |
931 | ErrorF("\timmediately return because the window is iconized\n"); | |
932 | #endif | |
933 | /* | |
934 | * If the Windows window is minimized, its WindowRect has | |
935 | * meaningless values so we don't adjust X window to it. | |
936 | */ | |
937 | vlist[0] = 0; | |
938 | vlist[1] = 0; | |
939 | return ConfigureWindow(pWin, CWX | CWY, vlist, wClient(pWin)); | |
940 | } | |
941 | ||
942 | pDraw = &pWin->drawable; | |
943 | ||
944 | /* Calculate the window rect from the drawable */ | |
945 | x = pDraw->x + GetSystemMetrics(SM_XVIRTUALSCREEN); | |
946 | y = pDraw->y + GetSystemMetrics(SM_YVIRTUALSCREEN); | |
947 | SetRect(&rcDraw, x, y, x + pDraw->width, y + pDraw->height); | |
948 | #ifdef CYGMULTIWINDOW_DEBUG | |
949 | winDebug("\tDrawable extend {%d, %d, %d, %d}, {%d, %d}\n", | |
950 | rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom, | |
951 | rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top); | |
952 | #endif | |
953 | dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE); | |
954 | dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); | |
955 | #ifdef CYGMULTIWINDOW_DEBUG | |
956 | winDebug("\tWindowStyle: %08x %08x\n", dwStyle, dwExStyle); | |
957 | #endif | |
958 | AdjustWindowRectEx(&rcDraw, dwStyle, FALSE, dwExStyle); | |
959 | ||
960 | /* The source of adjust */ | |
961 | GetWindowRect(hwnd, &rcWin); | |
962 | #ifdef CYGMULTIWINDOW_DEBUG | |
963 | winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n", | |
964 | rcWin.left, rcWin.top, rcWin.right, rcWin.bottom, | |
965 | rcWin.right - rcWin.left, rcWin.bottom - rcWin.top); | |
966 | winDebug("\tDraw extend {%d, %d, %d, %d}, {%d, %d}\n", | |
967 | rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom, | |
968 | rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top); | |
969 | #endif | |
970 | ||
971 | if (EqualRect(&rcDraw, &rcWin)) { | |
972 | /* Bail if no adjust is needed */ | |
973 | #if CYGWINDOWING_DEBUG | |
974 | ErrorF("\treturn because already adjusted\n"); | |
975 | #endif | |
976 | return 0; | |
977 | } | |
978 | ||
979 | /* Calculate delta values */ | |
980 | dX = rcWin.left - rcDraw.left; | |
981 | dY = rcWin.top - rcDraw.top; | |
982 | dW = WIDTH(rcWin) - WIDTH(rcDraw); | |
983 | dH = HEIGHT(rcWin) - HEIGHT(rcDraw); | |
984 | ||
985 | /* | |
986 | * Adjust. | |
987 | * We may only need to move (vlist[0] and [1]), or only resize | |
988 | * ([2] and [3]) but currently we set all the parameters and leave | |
989 | * the decision to ConfigureWindow. The reason is code simplicity. | |
990 | */ | |
991 | vlist[0] = pDraw->x + dX - wBorderWidth(pWin); | |
992 | vlist[1] = pDraw->y + dY - wBorderWidth(pWin); | |
993 | vlist[2] = pDraw->width + dW; | |
994 | vlist[3] = pDraw->height + dH; | |
995 | #if CYGWINDOWING_DEBUG | |
996 | ErrorF("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1], | |
997 | vlist[2], vlist[3]); | |
998 | #endif | |
999 | return ConfigureWindow(pWin, CWX | CWY | CWWidth | CWHeight, | |
1000 | vlist, wClient(pWin)); | |
1001 | ||
1002 | #undef WIDTH | |
1003 | #undef HEIGHT | |
1004 | } |