Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / ttydrv / wnd.c
blobf07379734876d7ab8e459afe0d4210171777ed97
1 /*
2 * TTY window driver
4 * Copyright 1998,1999 Patrik Stridvall
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "ttydrv.h"
24 #include "ntstatus.h"
25 #include "win.h"
26 #include "winpos.h"
27 #include "wownt32.h"
28 #include "wine/wingdi16.h"
29 #include "wine/server.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(ttydrv);
34 #define SWP_AGG_NOGEOMETRYCHANGE \
35 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
36 #define SWP_AGG_NOPOSCHANGE \
37 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
38 #define SWP_AGG_STATUSFLAGS \
39 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
41 /***********************************************************************
42 * get_server_visible_region
44 static HRGN get_server_visible_region( HWND hwnd, UINT flags )
46 RGNDATA *data;
47 NTSTATUS status;
48 HRGN ret = 0;
49 size_t size = 256;
53 if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 ))) return 0;
54 SERVER_START_REQ( get_visible_region )
56 req->window = hwnd;
57 req->flags = flags;
58 wine_server_set_reply( req, data->Buffer, size );
59 if (!(status = wine_server_call( req )))
61 size_t reply_size = wine_server_reply_size( reply );
62 data->rdh.dwSize = sizeof(data->rdh);
63 data->rdh.iType = RDH_RECTANGLES;
64 data->rdh.nCount = reply_size / sizeof(RECT);
65 data->rdh.nRgnSize = reply_size;
66 ret = ExtCreateRegion( NULL, size, data );
68 else size = reply->total_size;
70 SERVER_END_REQ;
71 HeapFree( GetProcessHeap(), 0, data );
72 } while (status == STATUS_BUFFER_OVERFLOW);
74 if (status) SetLastError( RtlNtStatusToDosError(status) );
75 return ret;
79 /***********************************************************************
80 * set_window_pos
82 * Set a window position and Z order.
84 static BOOL set_window_pos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
85 const RECT *rectClient, UINT swp_flags )
87 WND *win = WIN_GetPtr( hwnd );
88 BOOL ret;
90 if (!win) return FALSE;
91 if (win == WND_OTHER_PROCESS)
93 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
94 return FALSE;
96 SERVER_START_REQ( set_window_pos )
98 req->handle = hwnd;
99 req->previous = insert_after;
100 req->flags = swp_flags;
101 req->window.left = rectWindow->left;
102 req->window.top = rectWindow->top;
103 req->window.right = rectWindow->right;
104 req->window.bottom = rectWindow->bottom;
105 req->client.left = rectClient->left;
106 req->client.top = rectClient->top;
107 req->client.right = rectClient->right;
108 req->client.bottom = rectClient->bottom;
109 ret = !wine_server_call( req );
111 SERVER_END_REQ;
112 if (win == WND_DESKTOP) return ret;
113 if (ret)
115 win->rectWindow = *rectWindow;
116 win->rectClient = *rectClient;
118 TRACE( "win %p window (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", hwnd,
119 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
120 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
122 WIN_ReleasePtr( win );
123 return ret;
127 /**********************************************************************
128 * CreateWindow (TTYDRV.@)
130 BOOL TTYDRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
132 BOOL ret;
133 RECT rect;
134 HWND parent, hwndLinkAfter;
135 CBT_CREATEWNDA cbtc;
137 TRACE("(%p)\n", hwnd);
139 /* initialize the dimensions before sending WM_GETMINMAXINFO */
140 SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
141 set_window_pos( hwnd, 0, &rect, &rect, SWP_NOZORDER );
143 parent = GetAncestor( hwnd, GA_PARENT );
144 if (!parent) /* desktop window */
146 SetPropA( hwnd, "__wine_ttydrv_window", root_window );
147 return TRUE;
150 #ifdef WINE_CURSES
151 /* Only create top-level windows */
152 if (parent == GetDesktopWindow())
154 WINDOW *window;
155 const INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
157 window = subwin( root_window, cs->cy/cellHeight, cs->cx/cellWidth,
158 cs->y/cellHeight, cs->x/cellWidth);
159 werase(window);
160 wrefresh(window);
161 SetPropA( hwnd, "__wine_ttydrv_window", window );
163 #else /* defined(WINE_CURSES) */
164 FIXME("(%p): stub\n", hwnd);
165 #endif /* defined(WINE_CURSES) */
167 /* Call the WH_CBT hook */
169 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
171 cbtc.lpcs = cs;
172 cbtc.hwndInsertAfter = hwndLinkAfter;
173 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode ))
175 TRACE("CBT-hook returned !0\n");
176 return FALSE;
179 if (unicode)
181 ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
182 if (ret) ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
184 else
186 ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
187 if (ret) ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
189 if (ret) NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
190 return ret;
193 /***********************************************************************
194 * DestroyWindow (TTYDRV.@)
196 BOOL TTYDRV_DestroyWindow( HWND hwnd )
198 #ifdef WINE_CURSES
199 WINDOW *window = GetPropA( hwnd, "__wine_ttydrv_window" );
201 TRACE("(%p)\n", hwnd);
203 if (window && window != root_window) delwin(window);
204 #else /* defined(WINE_CURSES) */
205 FIXME("(%p): stub\n", hwnd);
206 #endif /* defined(WINE_CURSES) */
207 return TRUE;
211 /***********************************************************************
212 * GetDC (TTYDRV.@)
214 * Set the drawable, origin and dimensions for the DC associated to
215 * a given window.
217 BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
219 struct ttydrv_escape_set_drawable escape;
221 if(flags & DCX_WINDOW)
223 RECT rect;
224 GetWindowRect( hwnd, &rect );
225 escape.org.x = rect.left;
226 escape.org.y = rect.top;
228 else
230 escape.org.x = escape.org.y = 0;
231 MapWindowPoints( hwnd, 0, &escape.org, 1 );
234 escape.code = TTYDRV_SET_DRAWABLE;
235 ExtEscape( hdc, TTYDRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
237 if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) ||
238 SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN )) /* DC was dirty */
240 /* need to recompute the visible region */
241 HRGN visRgn = get_server_visible_region( hwnd, flags );
243 if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
244 CombineRgn( visRgn, visRgn, hrgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
246 SelectVisRgn16( HDC_16(hdc), HRGN_16(visRgn) );
247 DeleteObject( visRgn );
249 return TRUE;
253 /* fix redundant flags and values in the WINDOWPOS structure */
254 static BOOL fixup_flags( WINDOWPOS *winpos )
256 HWND parent;
257 WND *wndPtr = WIN_GetPtr( winpos->hwnd );
258 BOOL ret = TRUE;
260 if (!wndPtr || wndPtr == WND_OTHER_PROCESS)
262 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
263 return FALSE;
265 winpos->hwnd = wndPtr->hwndSelf; /* make it a full handle */
267 /* Finally make sure that all coordinates are valid */
268 if (winpos->x < -32768) winpos->x = -32768;
269 else if (winpos->x > 32767) winpos->x = 32767;
270 if (winpos->y < -32768) winpos->y = -32768;
271 else if (winpos->y > 32767) winpos->y = 32767;
273 if (winpos->cx < 0) winpos->cx = 0;
274 else if (winpos->cx > 32767) winpos->cx = 32767;
275 if (winpos->cy < 0) winpos->cy = 0;
276 else if (winpos->cy > 32767) winpos->cy = 32767;
278 parent = GetAncestor( winpos->hwnd, GA_PARENT );
279 if (!IsWindowVisible( parent )) winpos->flags |= SWP_NOREDRAW;
281 if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW;
282 else
284 winpos->flags &= ~SWP_HIDEWINDOW;
285 if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
288 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
289 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
290 winpos->flags |= SWP_NOSIZE; /* Already the right size */
292 if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
293 winpos->flags |= SWP_NOMOVE; /* Already the right position */
295 if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)
297 if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) /* Bring to the top when activating */
299 winpos->flags &= ~SWP_NOZORDER;
300 winpos->hwndInsertAfter = HWND_TOP;
304 /* Check hwndInsertAfter */
305 if (winpos->flags & SWP_NOZORDER) goto done;
307 /* fix sign extension */
308 if (winpos->hwndInsertAfter == (HWND)0xffff) winpos->hwndInsertAfter = HWND_TOPMOST;
309 else if (winpos->hwndInsertAfter == (HWND)0xfffe) winpos->hwndInsertAfter = HWND_NOTOPMOST;
311 /* FIXME: TOPMOST not supported yet */
312 if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
313 (winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
315 /* hwndInsertAfter must be a sibling of the window */
316 if (winpos->hwndInsertAfter == HWND_TOP)
318 if (GetWindow(winpos->hwnd, GW_HWNDFIRST) == winpos->hwnd)
319 winpos->flags |= SWP_NOZORDER;
321 else if (winpos->hwndInsertAfter == HWND_BOTTOM)
323 if (GetWindow(winpos->hwnd, GW_HWNDLAST) == winpos->hwnd)
324 winpos->flags |= SWP_NOZORDER;
326 else
328 if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != parent) ret = FALSE;
329 else
331 /* don't need to change the Zorder of hwnd if it's already inserted
332 * after hwndInsertAfter or when inserting hwnd after itself.
334 if ((winpos->hwnd == winpos->hwndInsertAfter) ||
335 (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
336 winpos->flags |= SWP_NOZORDER;
339 done:
340 WIN_ReleasePtr( wndPtr );
341 return ret;
345 /***********************************************************************
346 * SWP_DoNCCalcSize
348 static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, const RECT* pNewWindowRect, RECT* pNewClientRect )
350 UINT wvrFlags = 0;
351 WND *wndPtr;
353 if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
355 /* Send WM_NCCALCSIZE message to get new client area */
356 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
358 NCCALCSIZE_PARAMS params;
359 WINDOWPOS winposCopy;
361 params.rgrc[0] = *pNewWindowRect;
362 params.rgrc[1] = wndPtr->rectWindow;
363 params.rgrc[2] = wndPtr->rectClient;
364 params.lppos = &winposCopy;
365 winposCopy = *pWinpos;
366 WIN_ReleasePtr( wndPtr );
368 wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
370 *pNewClientRect = params.rgrc[0];
372 if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
374 TRACE( "hwnd %p old win %s old client %s new win %s new client %s\n", pWinpos->hwnd,
375 wine_dbgstr_rect(&wndPtr->rectWindow), wine_dbgstr_rect(&wndPtr->rectClient),
376 wine_dbgstr_rect(pNewWindowRect), wine_dbgstr_rect(pNewClientRect) );
378 if( pNewClientRect->left != wndPtr->rectClient.left ||
379 pNewClientRect->top != wndPtr->rectClient.top )
380 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
382 if( (pNewClientRect->right - pNewClientRect->left !=
383 wndPtr->rectClient.right - wndPtr->rectClient.left))
384 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
385 else
386 wvrFlags &= ~WVR_HREDRAW;
388 if (pNewClientRect->bottom - pNewClientRect->top !=
389 wndPtr->rectClient.bottom - wndPtr->rectClient.top)
390 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
391 else
392 wvrFlags &= ~WVR_VREDRAW;
394 else
396 if (!(pWinpos->flags & SWP_NOMOVE) &&
397 (pNewClientRect->left != wndPtr->rectClient.left ||
398 pNewClientRect->top != wndPtr->rectClient.top))
399 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
402 WIN_ReleasePtr( wndPtr );
403 return wvrFlags;
407 struct move_owned_info
409 HWND owner;
410 HWND insert_after;
413 static BOOL CALLBACK move_owned_popups( HWND hwnd, LPARAM lparam )
415 struct move_owned_info *info = (struct move_owned_info *)lparam;
417 if (hwnd == info->owner) return FALSE;
418 if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) &&
419 GetWindow( hwnd, GW_OWNER ) == info->owner)
421 SetWindowPos( hwnd, info->insert_after, 0, 0, 0, 0,
422 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |
423 SWP_NOSENDCHANGING | SWP_DEFERERASE );
424 info->insert_after = hwnd;
426 return TRUE;
429 /***********************************************************************
430 * SWP_DoOwnedPopups
432 * fix Z order taking into account owned popups -
433 * basically we need to maintain them above the window that owns them
435 * FIXME: hide/show owned popups when owner visibility changes.
437 static HWND SWP_DoOwnedPopups(HWND hwnd, HWND hwndInsertAfter)
439 HWND owner = GetWindow( hwnd, GW_OWNER );
440 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
441 struct move_owned_info info;
443 TRACE("(%p) hInsertAfter = %p\n", hwnd, hwndInsertAfter );
445 if ((style & WS_POPUP) && owner)
447 /* make sure this popup stays above the owner */
449 if( hwndInsertAfter != HWND_TOP )
451 HWND hwndLocalPrev = HWND_TOP;
452 HWND prev = GetWindow( owner, GW_HWNDPREV );
454 while (prev && prev != hwndInsertAfter)
456 if (hwndLocalPrev == HWND_TOP && GetWindowLongW( prev, GWL_STYLE ) & WS_VISIBLE)
457 hwndLocalPrev = prev;
458 prev = GetWindow( prev, GW_HWNDPREV );
460 if (!prev) hwndInsertAfter = hwndLocalPrev;
463 else if (style & WS_CHILD) return hwndInsertAfter;
465 info.owner = hwnd;
466 info.insert_after = hwndInsertAfter;
467 EnumWindows( move_owned_popups, (LPARAM)&info );
468 return info.insert_after;
472 /***********************************************************************
473 * SWP_DoWinPosChanging
475 static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect )
477 WND *wndPtr;
479 /* Send WM_WINDOWPOSCHANGING message */
481 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
482 SendMessageW( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
484 if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return FALSE;
486 /* Calculate new position and size */
488 *pNewWindowRect = wndPtr->rectWindow;
489 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
490 : wndPtr->rectClient;
492 if (!(pWinpos->flags & SWP_NOSIZE))
494 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
495 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
497 if (!(pWinpos->flags & SWP_NOMOVE))
499 pNewWindowRect->left = pWinpos->x;
500 pNewWindowRect->top = pWinpos->y;
501 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
502 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
504 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
505 pWinpos->y - wndPtr->rectWindow.top );
507 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
509 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
510 pWinpos->hwnd, pWinpos->hwndInsertAfter, pWinpos->x, pWinpos->y,
511 pWinpos->cx, pWinpos->cy, pWinpos->flags );
512 TRACE( "current %s style %08lx new %s\n",
513 wine_dbgstr_rect( &wndPtr->rectWindow ), wndPtr->dwStyle,
514 wine_dbgstr_rect( pNewWindowRect ));
516 WIN_ReleasePtr( wndPtr );
517 return TRUE;
521 /***********************************************************************
522 * SetWindowPos (TTYDRV.@)
524 BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
526 RECT newWindowRect, newClientRect;
527 UINT orig_flags;
529 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
530 winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y,
531 winpos->cx, winpos->cy, winpos->flags);
533 orig_flags = winpos->flags;
534 winpos->flags &= ~SWP_WINE_NOHOSTMOVE;
536 /* Check window handle */
537 if (winpos->hwnd == GetDesktopWindow()) return FALSE;
539 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
540 if (!(winpos->flags & SWP_NOMOVE))
542 if (winpos->x < -32768) winpos->x = -32768;
543 else if (winpos->x > 32767) winpos->x = 32767;
544 if (winpos->y < -32768) winpos->y = -32768;
545 else if (winpos->y > 32767) winpos->y = 32767;
547 if (!(winpos->flags & SWP_NOSIZE))
549 if (winpos->cx < 0) winpos->cx = 0;
550 else if (winpos->cx > 32767) winpos->cx = 32767;
551 if (winpos->cy < 0) winpos->cy = 0;
552 else if (winpos->cy > 32767) winpos->cy = 32767;
555 if (!SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect )) return FALSE;
557 /* Fix redundant flags */
558 if (!fixup_flags( winpos )) return FALSE;
560 if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
562 if (GetAncestor( winpos->hwnd, GA_PARENT ) == GetDesktopWindow())
563 winpos->hwndInsertAfter = SWP_DoOwnedPopups( winpos->hwnd, winpos->hwndInsertAfter );
566 /* Common operations */
568 SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect );
570 if (!set_window_pos( winpos->hwnd, winpos->hwndInsertAfter,
571 &newWindowRect, &newClientRect, orig_flags ))
572 return FALSE;
574 if( winpos->flags & SWP_HIDEWINDOW )
575 HideCaret(winpos->hwnd);
576 else if (winpos->flags & SWP_SHOWWINDOW)
577 ShowCaret(winpos->hwnd);
579 if (!(winpos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)))
581 /* child windows get WM_CHILDACTIVATE message */
582 if ((GetWindowLongW( winpos->hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD)
583 SendMessageA( winpos->hwnd, WM_CHILDACTIVATE, 0, 0 );
584 else
585 SetForegroundWindow( winpos->hwnd );
588 /* And last, send the WM_WINDOWPOSCHANGED message */
590 TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
592 if (((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE))
594 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
595 and always contains final window position.
597 winpos->x = newWindowRect.left;
598 winpos->y = newWindowRect.top;
599 winpos->cx = newWindowRect.right - newWindowRect.left;
600 winpos->cy = newWindowRect.bottom - newWindowRect.top;
601 SendMessageW( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
604 return TRUE;
608 /***********************************************************************
609 * WINPOS_MinMaximize (internal)
611 *Lifted from x11 driver
613 static UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
615 UINT swpFlags = 0;
616 WINDOWPLACEMENT wpl;
618 TRACE("%p %u\n", hwnd, cmd );
619 FIXME("(%p): stub\n", hwnd);
621 wpl.length = sizeof(wpl);
622 GetWindowPlacement( hwnd, &wpl );
624 /* If I glark this right, yields an immutable window*/
625 swpFlags = SWP_NOSIZE | SWP_NOMOVE;
627 /*cmd handling goes here. see dlls/x1drv/winpos.c*/
629 return swpFlags;
632 /***********************************************************************
633 * ShowWindow (TTYDRV.@)
635 *Lifted from x11 driver
636 *Sets the specified windows' show state.
638 BOOL TTYDRV_ShowWindow( HWND hwnd, INT cmd )
640 WND *wndPtr;
641 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
642 BOOL wasVisible = (style & WS_VISIBLE) != 0;
643 BOOL showFlag = TRUE;
644 RECT newPos = {0, 0, 0, 0};
645 UINT swp = 0;
648 TRACE("hwnd=%p, cmd=%d, wasVisible %d\n", hwnd, cmd, wasVisible);
650 switch(cmd)
652 case SW_HIDE:
653 if (!wasVisible) return FALSE;
654 showFlag = FALSE;
655 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER;
656 break;
658 case SW_SHOWMINNOACTIVE:
659 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
660 /* fall through */
661 case SW_SHOWMINIMIZED:
662 case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
663 swp |= SWP_SHOWWINDOW;
664 /* fall through */
665 case SW_MINIMIZE:
666 swp |= SWP_FRAMECHANGED;
667 if( !(style & WS_MINIMIZE) )
668 swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
669 else swp |= SWP_NOSIZE | SWP_NOMOVE;
670 break;
672 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
673 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
674 if( !(style & WS_MAXIMIZE) )
675 swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
676 else swp |= SWP_NOSIZE | SWP_NOMOVE;
677 break;
679 case SW_SHOWNA:
680 swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
681 if (style & WS_CHILD) swp |= SWP_NOZORDER;
682 break;
683 case SW_SHOW:
684 if (wasVisible) return TRUE;
685 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
686 break;
688 case SW_RESTORE:
689 swp |= SWP_FRAMECHANGED;
690 /* fall through */
691 case SW_SHOWNOACTIVATE:
692 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
693 /* fall through */
694 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
695 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
696 swp |= SWP_SHOWWINDOW;
698 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
699 swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
700 else swp |= SWP_NOSIZE | SWP_NOMOVE;
701 break;
704 if (showFlag != wasVisible || cmd == SW_SHOWNA)
706 SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 );
707 if (!IsWindow( hwnd )) return wasVisible;
710 /* ShowWindow won't activate a not being maximized child window */
711 if ((style & WS_CHILD) && cmd != SW_MAXIMIZE)
712 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
714 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
715 newPos.right, newPos.bottom, LOWORD(swp) );
716 if (cmd == SW_HIDE)
718 HWND hFocus;
720 /* FIXME: This will cause the window to be activated irrespective
721 * of whether it is owned by the same thread. Has to be done
722 * asynchronously.
725 if (hwnd == GetActiveWindow())
726 WINPOS_ActivateOtherWindow(hwnd);
728 /* Revert focus to parent */
729 hFocus = GetFocus();
730 if (hwnd == hFocus || IsChild(hwnd, hFocus))
732 HWND parent = GetAncestor(hwnd, GA_PARENT);
733 if (parent == GetDesktopWindow()) parent = 0;
734 SetFocus(parent);
738 if (IsIconic(hwnd)) WINPOS_ShowIconTitle( hwnd, TRUE );
740 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return wasVisible;
742 if (wndPtr->flags & WIN_NEED_SIZE)
744 /* should happen only in CreateWindowEx() */
745 int wParam = SIZE_RESTORED;
746 RECT client = wndPtr->rectClient;
748 wndPtr->flags &= ~WIN_NEED_SIZE;
749 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
750 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
751 WIN_ReleasePtr( wndPtr );
753 SendMessageW( hwnd, WM_SIZE, wParam,
754 MAKELONG( client.right - client.left, client.bottom - client.top ));
755 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top ));
757 else WIN_ReleasePtr( wndPtr );
759 return wasVisible;