Commit dc4fe773 authored by Alexandre Julliard's avatar Alexandre Julliard

Create an X window for every window, including children.

Fixed non-client rectangle calculations in managed mode. Added support for icon window in managed mode.
parent d7c69a5d
......@@ -27,7 +27,7 @@ debug_channels (ttydrv)
@ cdecl GetScreenSaveTimeout() TTYDRV_GetScreenSaveTimeout
@ cdecl SetScreenSaveTimeout(long) TTYDRV_SetScreenSaveTimeout
@ cdecl LoadOEMResource(long long) TTYDRV_LoadOEMResource
@ cdecl CreateWindow(long) TTYDRV_CreateWindow
@ cdecl CreateWindow(long ptr) TTYDRV_CreateWindow
@ cdecl DestroyWindow(long) TTYDRV_DestroyWindow
@ cdecl GetDC(long long long long) TTYDRV_GetDC
@ cdecl SetWindowPos(ptr) TTYDRV_SetWindowPos
......
......@@ -17,8 +17,7 @@ DEFAULT_DEBUG_CHANNEL(ttydrv);
WND_DRIVER TTYDRV_WND_Driver =
{
TTYDRV_WND_ForceWindowRaise,
TTYDRV_WND_SetHostAttr
TTYDRV_WND_ForceWindowRaise
};
#define SWP_AGG_NOGEOMETRYCHANGE \
......@@ -31,8 +30,10 @@ WND_DRIVER TTYDRV_WND_Driver =
/**********************************************************************
* CreateWindow (TTYDRV.@)
*/
BOOL TTYDRV_CreateWindow( HWND hwnd )
BOOL TTYDRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs )
{
BOOL ret;
#ifdef WINE_CURSES
WND *wndPtr = WIN_FindWndPtr( hwnd );
WINDOW *window;
......@@ -41,32 +42,40 @@ BOOL TTYDRV_CreateWindow( HWND hwnd )
TRACE("(%x)\n", hwnd);
/* Only create top-level windows */
if (wndPtr->dwStyle & WS_CHILD)
{
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
if (!wndPtr->parent) /* desktop */
window = root_window;
else
if (!(wndPtr->dwStyle & WS_CHILD))
{
int x = wndPtr->rectWindow.left;
int y = wndPtr->rectWindow.top;
int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
window = subwin( root_window, cy/cellHeight, cx/cellWidth,
y/cellHeight, x/cellWidth);
werase(window);
wrefresh(window);
if (!wndPtr->parent) /* desktop */
window = root_window;
else
{
int x = wndPtr->rectWindow.left;
int y = wndPtr->rectWindow.top;
int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
window = subwin( root_window, cy/cellHeight, cx/cellWidth,
y/cellHeight, x/cellWidth);
werase(window);
wrefresh(window);
}
wndPtr->pDriverData = window;
}
wndPtr->pDriverData = window;
WIN_ReleaseWndPtr( wndPtr );
#else /* defined(WINE_CURSES) */
FIXME("(%x): stub\n", hwnd);
#endif /* defined(WINE_CURSES) */
return TRUE;
if (IsWindowUnicode( hwnd ))
{
ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
if (ret) ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
}
else
{
ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
if (ret) ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
}
return ret;
}
/***********************************************************************
......@@ -97,16 +106,6 @@ void TTYDRV_WND_ForceWindowRaise(WND *wndPtr)
FIXME("(%p): stub\n", wndPtr);
}
/***********************************************************************
* TTYDRV_WND_SetHostAttr
*/
BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
{
FIXME("(%p): stub\n", wndPtr);
return TRUE;
}
/***********************************************************************
* DCE_OffsetVisRgn
......
......@@ -89,6 +89,7 @@ static BOOL load_driver(void)
GET_USER_FUNC(GetDC);
GET_USER_FUNC(EnableWindow);
GET_USER_FUNC(MsgWaitForMultipleObjectsEx);
GET_USER_FUNC(ScrollDC);
GET_USER_FUNC(ScrollWindowEx);
GET_USER_FUNC(SetFocus);
GET_USER_FUNC(SetParent);
......@@ -96,6 +97,7 @@ static BOOL load_driver(void)
GET_USER_FUNC(SetWindowRgn);
GET_USER_FUNC(SetWindowIcon);
GET_USER_FUNC(SetWindowText);
GET_USER_FUNC(ShowWindow);
GET_USER_FUNC(SysCommandSizeMove);
return TRUE;
......
......@@ -9,6 +9,7 @@ IMPORTS = user32 gdi32 kernel32
C_SRCS = \
desktop.c \
dga2.c \
scroll.c \
window.c \
winpos.c \
x11ddraw.c \
......
......@@ -55,11 +55,14 @@ static DWORD CALLBACK desktop_thread( LPVOID driver_data )
/* patch the desktop window queue to point to our queue */
win = WIN_FindWndPtr( hwnd );
win->hmemTaskQ = GetFastQueue16();
X11DRV_register_window( display, hwnd, win->pDriverData );
WIN_ReleaseWndPtr( win );
SetWindowLongW( hwnd, GWL_WNDPROC, (LONG)desktop_winproc );
X11DRV_register_window( display, hwnd, root_window );
TSXMapWindow( display, root_window );
wine_tsx11_lock();
XSetWMProtocols( display, root_window, &wmDeleteWindow, 1 );
XMapWindow( display, root_window );
wine_tsx11_unlock();
while (GetMessageW( &msg, hwnd, 0, 0 )) DispatchMessageW( &msg );
return 0;
......
/*
* Scroll windows and DCs
*
* Copyright 1993 David W. Metcalfe
* Copyright 1995, 1996 Alex Korobka
* Copyright 2001 Alexandre Julliard
*/
#include "config.h"
#include "ts_xlib.h"
#include "ts_xutil.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "x11drv.h"
#include "win.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(x11drv);
/*************************************************************************
* fix_caret
*/
static BOOL fix_caret(HWND hWnd, LPRECT lprc, UINT flags)
{
HWND hCaret = CARET_GetHwnd();
if( hCaret )
{
RECT rc;
CARET_GetRect( &rc );
if( hCaret == hWnd ||
(flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) )
{
POINT pt;
pt.x = rc.left;
pt.y = rc.top;
MapWindowPoints( hCaret, hWnd, (LPPOINT)&rc, 2 );
if( IntersectRect(lprc, lprc, &rc) )
{
HideCaret(0);
lprc->left = pt.x;
lprc->top = pt.y;
return TRUE;
}
}
}
return FALSE;
}
/*************************************************************************
* ScrollDC (X11DRV.@)
*
* Only the hrgnUpdate is returned in device coordinates.
* rcUpdate must be returned in logical coordinates to comply with win API.
* FIXME: the doc explicitly states the opposite, to be checked
*/
BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, const RECT *rc,
const RECT *clipRect, HRGN hrgnUpdate, LPRECT rcUpdate )
{
RECT rect, rClip, rSrc;
TRACE( "%04x %d,%d hrgnUpdate=%04x rcUpdate = %p\n", hdc, dx, dy, hrgnUpdate, rcUpdate );
if (clipRect) TRACE( "cliprc = (%d,%d,%d,%d)\n",
clipRect->left, clipRect->top, clipRect->right, clipRect->bottom );
if (rc) TRACE( "rc = (%d,%d,%d,%d)\n", rc->left, rc->top, rc->right, rc->bottom );
/* compute device clipping region (in device coordinates) */
if (rc) rect = *rc;
else GetClipBox( hdc, &rect );
if (clipRect)
{
rClip = *clipRect;
IntersectRect( &rClip, &rect, &rClip );
}
else rClip = rect;
rSrc = rClip;
OffsetRect( &rSrc, -dx, -dy );
IntersectRect( &rSrc, &rSrc, &rect );
if (!IsRectEmpty(&rSrc))
{
/* copy bits */
if (!BitBlt( hdc, rSrc.left + dx, rSrc.top + dy,
rSrc.right - rSrc.left, rSrc.bottom - rSrc.top,
hdc, rSrc.left, rSrc.top, SRCCOPY))
return FALSE;
}
/* compute update areas */
if (hrgnUpdate || rcUpdate)
{
HRGN hrgn = hrgnUpdate, hrgn2;
POINT pt;
/* map everything to device coordinates */
pt.x = rect.left + dx;
pt.y = rect.top + dy;
LPtoDP( hdc, &pt, 1 );
LPtoDP( hdc, (LPPOINT)&rect, 2 );
LPtoDP( hdc, (LPPOINT)&rClip, 2 );
dx = pt.x - rect.left;
dy = pt.y - rect.top;
hrgn2 = CreateRectRgnIndirect( &rect );
if (hrgn) SetRectRgn( hrgn, rClip.left, rClip.top, rClip.right, rClip.bottom );
else hrgn = CreateRectRgn( rClip.left, rClip.top, rClip.right, rClip.bottom );
CombineRgn( hrgn, hrgn, hrgn2, RGN_AND );
OffsetRgn( hrgn2, dx, dy );
CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
if( rcUpdate )
{
GetRgnBox( hrgn, rcUpdate );
/* Put the rcUpdate in logical coordinate */
DPtoLP( hdc, (LPPOINT)rcUpdate, 2 );
}
if (!hrgnUpdate) DeleteObject( hrgn );
DeleteObject( hrgn2 );
}
return TRUE;
}
/*************************************************************************
* ScrollWindowEx (X11DRV.@)
*/
INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
const RECT *rect, const RECT *clipRect,
HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags )
{
INT retVal = NULLREGION;
BOOL bCaret = FALSE, bOwnRgn = TRUE;
RECT rc, cliprc;
WND* wnd = WIN_FindWndPtr( hwnd );
if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE ))
{
retVal = ERROR;
goto END;
}
GetClientRect(hwnd, &rc);
if (rect) IntersectRect(&rc, &rc, rect);
if (clipRect) IntersectRect(&cliprc,&rc,clipRect);
else cliprc = rc;
if (!IsRectEmpty(&cliprc) && (dx || dy))
{
HDC hDC;
BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
HRGN hrgnClip = CreateRectRgnIndirect(&cliprc);
HRGN hrgnTemp;
RECT caretrc;
TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rc=(%d,%d-%d,%d) %04x\n",
hwnd, dx, dy, hrgnUpdate, rcUpdate,
rc.left, rc.top, rc.right, rc.bottom, flags );
if (clipRect) TRACE( "cliprc = (%d,%d,%d,%d)\n",
clipRect->left, clipRect->top,
clipRect->right, clipRect->bottom );
caretrc = rc;
bCaret = fix_caret(hwnd, &caretrc, flags);
if( hrgnUpdate ) bOwnRgn = FALSE;
else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
hDC = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE );
if (hDC)
{
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
X11DRV_StartGraphicsExposures( hDC );
X11DRV_ScrollDC( hDC, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate );
X11DRV_EndGraphicsExposures( hDC, hrgn );
ReleaseDC( hwnd, hDC );
if (bUpdate) CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_OR );
else RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
}
/* Take into account the fact that some damages may have occured during the scroll */
hrgnTemp = CreateRectRgn( 0, 0, 0, 0 );
if (GetUpdateRgn( hwnd, hrgnTemp, FALSE ) != NULLREGION)
{
OffsetRgn( hrgnTemp, dx, dy );
CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND );
RedrawWindow( hwnd, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE );
}
DeleteObject( hrgnTemp );
if( flags & SW_SCROLLCHILDREN )
{
RECT r;
WND *w;
for( w =WIN_LockWndPtr(wnd->child); w; WIN_UpdateWndPtr(&w, w->next))
{
r = w->rectWindow;
if( !rect || IntersectRect(&r, &r, &rc) )
SetWindowPos(w->hwndSelf, 0, w->rectWindow.left + dx,
w->rectWindow.top + dy, 0,0, SWP_NOZORDER |
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
SWP_DEFERERASE );
}
}
if( flags & (SW_INVALIDATE | SW_ERASE) )
RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
if( bCaret )
{
SetCaretPos( caretrc.left + dx, caretrc.top + dy );
ShowCaret(0);
}
if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
DeleteObject( hrgnClip );
}
END:
WIN_ReleaseWndPtr(wnd);
return retVal;
}
......@@ -21,18 +21,27 @@
#include "dce.h"
#include "options.h"
DEFAULT_DEBUG_CHANNEL(win);
DEFAULT_DEBUG_CHANNEL(x11drv);
extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
#define HAS_DLGFRAME(style,exStyle) \
((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
(((exStyle) & WS_EX_DLGMODALFRAME) || \
(((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
#define HAS_THICKFRAME(style,exStyle) \
(((style) & WS_THICKFRAME) && \
!(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
#define HAS_THINFRAME(style) \
(((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
/* X context to associate a hwnd to an X window */
XContext winContext = 0;
Atom wmProtocols = None;
Atom wmDeleteWindow = None;
Atom wmTakeFocus = None;
Atom dndProtocol = None;
Atom dndSelection = None;
Atom wmChangeState = None;
......@@ -41,51 +50,137 @@ Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
/***********************************************************************
* X11DRV_register_window
* is_window_managed
*
* Associate an X window to a HWND.
* Check if a given window should be managed
*/
void X11DRV_register_window( Display *display, HWND hwnd, Window win )
inline static BOOL is_window_managed( WND *win )
{
if (!winContext) winContext = TSXUniqueContext();
TSXSaveContext( display, win, winContext, (char *)hwnd );
TSXSetWMProtocols( display, win, &wmDeleteWindow, 1 );
if (!Options.managed) return FALSE;
/* tray window is always managed */
if (win->dwExStyle & WS_EX_TRAYWINDOW) return TRUE;
/* child windows are not managed */
if (win->dwStyle & WS_CHILD) return FALSE;
/* tool windows are not managed */
if (win->dwExStyle & WS_EX_TOOLWINDOW) return FALSE;
/* windows with caption or thick frame are managed */
if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) return TRUE;
if (win->dwStyle & WS_THICKFRAME) return TRUE;
/* default: not managed */
return FALSE;
}
/***********************************************************************
* set_wm_hint
* is_window_top_level
*
* Set a window manager hint.
* Check if a given window is a top level X11 window
*/
static void set_wm_hint( Display *display, Window win, int hint, int val )
inline static BOOL is_window_top_level( WND *win )
{
XWMHints* wm_hints = TSXGetWMHints( display, win );
if (!wm_hints) wm_hints = TSXAllocWMHints();
if (wm_hints)
{
wm_hints->flags = hint;
switch( hint )
{
case InputHint:
wm_hints->input = val;
break;
return (root_window == DefaultRootWindow(gdi_display) &&
win->parent->hwndSelf == GetDesktopWindow());
}
case StateHint:
wm_hints->initial_state = val;
break;
case IconPixmapHint:
wm_hints->icon_pixmap = (Pixmap)val;
break;
/***********************************************************************
* get_window_attributes
*
* Fill the window attributes structure for an X window
*/
static int get_window_attributes( WND *win, XSetWindowAttributes *attr )
{
BOOL is_top_level = is_window_top_level( win );
BOOL managed = is_top_level && is_window_managed( win );
if (managed) win->dwExStyle |= WS_EX_MANAGED;
else win->dwExStyle &= ~WS_EX_MANAGED;
attr->override_redirect = !managed;
attr->bit_gravity = ForgetGravity;
attr->win_gravity = NorthWestGravity;
attr->colormap = X11DRV_PALETTE_PaletteXColormap;
attr->backing_store = NotUseful/*WhenMapped*/;
attr->save_under = ((win->clsStyle & CS_SAVEBITS) != 0);
attr->cursor = None;
attr->event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
if (is_window_top_level( win )) attr->event_mask |= StructureNotifyMask | FocusChangeMask;
return (CWBitGravity | CWWinGravity | CWBackingStore | CWOverrideRedirect |
CWSaveUnder | CWEventMask | CWColormap | CWCursor);
}
case IconWindowHint:
wm_hints->icon_window = (Window)val;
break;
}
TSXSetWMHints( display, win, wm_hints );
TSXFree(wm_hints);
/***********************************************************************
* get_window_changes
*
* fill the window changes structure
*/
static int get_window_changes( XWindowChanges *changes, const RECT *old, const RECT *new )
{
int mask = 0;
if (old->right - old->left != new->right - new->left )
{
if (!(changes->width = new->right - new->left)) changes->width = 1;
mask |= CWWidth;
}
if (old->bottom - old->top != new->bottom - new->top)
{
if (!(changes->height = new->bottom - new->top)) changes->height = 1;
mask |= CWHeight;
}
if (old->left != new->left)
{
changes->x = new->left;
mask |= CWX;
}
if (old->top != new->top)
{
changes->y = new->top;
mask |= CWY;
}
return mask;
}
/***********************************************************************
* create_icon_window
*/
static Window create_icon_window( Display *display, WND *win )
{
struct x11drv_win_data *data = win->pDriverData;
XSetWindowAttributes attr;
attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
attr.bit_gravity = NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
data->icon_window = TSXCreateWindow( display, root_window, 0, 0,
GetSystemMetrics( SM_CXICON ),
GetSystemMetrics( SM_CYICON ),
0, screen_depth,
InputOutput, visual,
CWEventMask | CWBitGravity | CWBackingStore, &attr );
XSaveContext( display, data->icon_window, winContext, (char *)win->hwndSelf );
TRACE( "created %lx\n", data->icon_window );
return data->icon_window;
}
/***********************************************************************
* destroy_icon_window
*/
inline static void destroy_icon_window( Display *display, struct x11drv_win_data *data )
{
if (!data->icon_window) return;
XDeleteContext( display, data->icon_window, winContext );
XDestroyWindow( display, data->icon_window );
data->icon_window = 0;
}
......@@ -106,7 +201,9 @@ static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
{
data->hWMIconBitmap = 0;
data->hWMIconMask = 0;
hints->flags &= ~(IconPixmapHint | IconMaskHint);
if (!data->icon_window) create_icon_window( display, wndPtr );
hints->icon_window = data->icon_window;
hints->flags = (hints->flags & ~(IconPixmapHint | IconMaskHint)) | IconWindowHint;
}
else
{
......@@ -138,220 +235,498 @@ static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
hints->icon_pixmap = X11DRV_BITMAP_Pixmap(data->hWMIconBitmap);
hints->icon_mask = X11DRV_BITMAP_Pixmap(data->hWMIconMask);
hints->flags |= IconPixmapHint | IconMaskHint;
destroy_icon_window( display, data );
hints->flags = (hints->flags & ~IconWindowHint) | IconPixmapHint | IconMaskHint;
}
}
/***********************************************************************
* dock_window
* set_size_hints
*
* Set the X Property of the window that tells the windowmanager we really
* want to be in the systray
*
* KDE: set "KWM_DOCKWINDOW", type "KWM_DOCKWINDOW" to 1 before a window is
* mapped.
*
* all others: to be added ;)
* set the window size hints
*/
inline static void dock_window( Display *display, Window win )
static void set_size_hints( Display *display, WND *win )
{
int data = 1;
if (kwmDockWindow != None)
TSXChangeProperty( display, win, kwmDockWindow, kwmDockWindow,
32, PropModeReplace, (char*)&data, 1 );
if (_kde_net_wm_system_tray_window_for != None)
TSXChangeProperty( display, win, _kde_net_wm_system_tray_window_for, XA_WINDOW,
32, PropModeReplace, (char*)&win, 1 );
XSizeHints* size_hints;
struct x11drv_win_data *data = win->pDriverData;
if ((size_hints = XAllocSizeHints()))
{
size_hints->win_gravity = StaticGravity;
size_hints->x = data->whole_rect.left;
size_hints->y = data->whole_rect.top;
size_hints->flags = PWinGravity | PPosition;
if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
{
size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
size_hints->min_width = size_hints->max_width;
size_hints->min_height = size_hints->max_height;
size_hints->flags |= PMinSize | PMaxSize;
}
XSetWMNormalHints( display, data->whole_window, size_hints );
XFree( size_hints );
}
}
/**********************************************************************
* create_desktop
/***********************************************************************
* set_wm_hints
*
* Set the window manager hints for a newly-created window
*/
static void create_desktop( Display *display, WND *wndPtr )
inline static void set_wm_hints( Display *display, WND *win )
{
X11DRV_WND_DATA *data = wndPtr->pDriverData;
struct x11drv_win_data *data = win->pDriverData;
Window group_leader;
XClassHint *class_hints;
XWMHints* wm_hints;
Atom protocols[2];
int i;
wine_tsx11_lock();
/* wm protocols */
i = 0;
protocols[i++] = wmDeleteWindow;
if (wmTakeFocus) protocols[i++] = wmTakeFocus;
XSetWMProtocols( display, data->whole_window, protocols, i );
/* class hints */
if ((class_hints = XAllocClassHint()))
{
class_hints->res_name = "wine";
class_hints->res_class = "Wine";
XSetClassHint( display, data->whole_window, class_hints );
XFree( class_hints );
}
wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
dndSelection = TSXInternAtom( display, "DndSelection" , False );
wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
_kde_net_wm_system_tray_window_for = TSXInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
/* transient for hint */
if (win->owner)
{
struct x11drv_win_data *owner_data = win->owner->pDriverData;
XSetTransientForHint( display, data->whole_window, owner_data->whole_window );
group_leader = owner_data->whole_window;
}
else group_leader = data->whole_window;
data->window = root_window;
if (root_window != DefaultRootWindow(display))
/* wm hints */
if ((wm_hints = XAllocWMHints()))
{
wndPtr->flags |= WIN_NATIVE;
X11DRV_create_desktop_thread();
wm_hints->flags = InputHint | StateHint | WindowGroupHint;
/* use globally active model if take focus is supported,
* passive model otherwise (cf. ICCCM) */
wm_hints->input = !wmTakeFocus;
set_icon_hints( display, win, wm_hints );
wm_hints->initial_state = (win->dwStyle & WS_MINIMIZE) ? IconicState : NormalState;
wm_hints->window_group = group_leader;
XSetWMHints( display, data->whole_window, wm_hints );
XFree(wm_hints);
}
/* size hints */
set_size_hints( display, win );
/* systray properties (KDE only for now) */
if (win->dwExStyle & WS_EX_TRAYWINDOW)
{
int val = 1;
if (kwmDockWindow != None)
TSXChangeProperty( display, data->whole_window, kwmDockWindow, kwmDockWindow,
32, PropModeReplace, (char*)&val, 1 );
if (_kde_net_wm_system_tray_window_for != None)
TSXChangeProperty( display, data->whole_window, _kde_net_wm_system_tray_window_for,
XA_WINDOW, 32, PropModeReplace, (char*)&data->whole_window, 1 );
}
wine_tsx11_unlock();
}
/**********************************************************************
* CreateWindow (X11DRV.@)
/***********************************************************************
* X11DRV_set_iconic_state
*
* Set the X11 iconic state according to the window style.
*/
BOOL X11DRV_CreateWindow( HWND hwnd )
void X11DRV_set_iconic_state( WND *win )
{
Display *display = thread_display();
X11DRV_WND_DATA *data;
WND *wndPtr = WIN_FindWndPtr( hwnd );
int x = wndPtr->rectWindow.left;
int y = wndPtr->rectWindow.top;
int cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
int cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
struct x11drv_win_data *data = win->pDriverData;
XWMHints* wm_hints;
BOOL iconic = IsIconic( win->hwndSelf );
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(X11DRV_WND_DATA))))
if (!(win->dwExStyle & WS_EX_MANAGED))
{
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
if (iconic) TSXUnmapWindow( display, data->client_window );
else TSXMapWindow( display, data->client_window );
}
data->window = 0;
wndPtr->pDriverData = data;
if (!wndPtr->parent)
wine_tsx11_lock();
if (!(wm_hints = XGetWMHints( display, data->whole_window ))) wm_hints = XAllocWMHints();
wm_hints->flags |= StateHint | IconPositionHint;
wm_hints->initial_state = iconic ? IconicState : NormalState;
wm_hints->icon_x = win->rectWindow.left;
wm_hints->icon_y = win->rectWindow.top;
XSetWMHints( display, data->whole_window, wm_hints );
if (win->dwStyle & WS_VISIBLE)
{
create_desktop( display, wndPtr );
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
if (iconic)
XIconifyWindow( display, data->whole_window, DefaultScreen(display) );
else
if (!IsRectEmpty( &win->rectWindow )) XMapWindow( display, data->whole_window );
}
/* Create the X window (only for top-level windows, and then only */
/* when there's no desktop window) */
XFree(wm_hints);
wine_tsx11_unlock();
}
if ((root_window == DefaultRootWindow(display))
&& (wndPtr->parent->hwndSelf == GetDesktopWindow()))
/***********************************************************************
* X11DRV_window_to_X_rect
*
* Convert a rect from client to X window coordinates
*/
void X11DRV_window_to_X_rect( WND *win, RECT *rect )
{
if (!(win->dwExStyle & WS_EX_MANAGED)) return;
if (win->dwStyle & WS_ICONIC) return;
if (IsRectEmpty( rect )) return;
if (HAS_THICKFRAME( win->dwStyle, win->dwExStyle ))
InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
else if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME) );
else if (HAS_THINFRAME( win->dwStyle ))
InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
if ((win->dwStyle & WS_CAPTION) == WS_CAPTION)
{
Window wGroupLeader;
XWMHints* wm_hints;
XSetWindowAttributes win_attr;
if (win->dwExStyle & WS_EX_TOOLWINDOW)
rect->top += GetSystemMetrics(SM_CYSMCAPTION);
else
rect->top += GetSystemMetrics(SM_CYCAPTION);
}
if (win->dwExStyle & WS_EX_CLIENTEDGE)
InflateRect( rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE) );
if (win->dwExStyle & WS_EX_STATICEDGE)
InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
if (rect->left >= rect->right) rect->right = rect->left + 1;
}
/***********************************************************************
* X11DRV_X_to_window_rect
*
* Opposite of X11DRV_window_to_X_rect
*/
void X11DRV_X_to_window_rect( WND *win, RECT *rect )
{
if (!(win->dwExStyle & WS_EX_MANAGED)) return;
if (win->dwStyle & WS_ICONIC) return;
if (IsRectEmpty( rect )) return;
if (HAS_THICKFRAME( win->dwStyle, win->dwExStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
else if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
else if (HAS_THINFRAME( win->dwStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER) );
if ((win->dwStyle & WS_CAPTION) == WS_CAPTION)
{
if (win->dwExStyle & WS_EX_TOOLWINDOW)
rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
else
rect->top -= GetSystemMetrics(SM_CYCAPTION);
}
if (win->dwExStyle & WS_EX_CLIENTEDGE)
InflateRect( rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE) );
if (win->dwExStyle & WS_EX_STATICEDGE)
InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER) );
/* Create "managed" windows only if a title bar or resizable */
/* frame is required. */
if (WIN_WindowNeedsWMBorder(wndPtr->dwStyle, wndPtr->dwExStyle))
if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
if (rect->left >= rect->right) rect->right = rect->left + 1;
}
/***********************************************************************
* X11DRV_sync_whole_window_position
*
* Synchronize the X whole window position with the Windows one
*/
int X11DRV_sync_whole_window_position( Display *display, WND *win, int zorder )
{
XWindowChanges changes;
int mask;
struct x11drv_win_data *data = win->pDriverData;
RECT whole_rect = win->rectWindow;
X11DRV_window_to_X_rect( win, &whole_rect );
mask = get_window_changes( &changes, &data->whole_rect, &whole_rect );
if (zorder)
{
/* find window that this one must be after */
WND *prev = win->parent->child;
if (prev == win) /* top child */
{
win_attr.event_mask = ExposureMask | KeyPressMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
FocusChangeMask | StructureNotifyMask;
win_attr.override_redirect = FALSE;
wndPtr->dwExStyle |= WS_EX_MANAGED;
changes.stack_mode = Above;
mask |= CWStackMode;
}
else
{
win_attr.event_mask = ExposureMask | KeyPressMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
FocusChangeMask;
win_attr.override_redirect = TRUE;
while (prev && prev->next != win) prev = prev->next;
if (prev)
{
changes.stack_mode = Below;
changes.sibling = get_whole_window(prev);
mask |= CWStackMode | CWSibling;
}
else ERR( "previous window not found for %x, list corrupted?\n", win->hwndSelf );
}
wndPtr->flags |= WIN_NATIVE;
}
data->whole_rect = whole_rect;
if (mask)
{
TRACE( "setting win %lx pos %d,%d,%dx%d after %lx changes=%x\n",
data->whole_window, whole_rect.left, whole_rect.top,
whole_rect.right - whole_rect.left, whole_rect.bottom - whole_rect.top,
changes.sibling, mask );
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush graphics operations before moving the window */
if (is_window_top_level( win ))
{
if (mask & (CWWidth|CWHeight)) set_size_hints( display, win );
XReconfigureWMWindow( display, data->whole_window,
DefaultScreen(display), mask, &changes );
}
else XConfigureWindow( display, data->whole_window, mask, &changes );
wine_tsx11_unlock();
}
return mask;
}
win_attr.bit_gravity = (wndPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ? ForgetGravity : NorthWestGravity;
win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
win_attr.backing_store = NotUseful;
win_attr.save_under = ((wndPtr->clsStyle & CS_SAVEBITS) != 0);
win_attr.cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
data->hWMIconBitmap = 0;
data->hWMIconMask = 0;
data->bit_gravity = win_attr.bit_gravity;
/* Zero-size X11 window hack. X doesn't like them, and will crash */
/* with a BadValue unless we do something ugly like this. */
/* Zero size window won't be mapped */
if (cx <= 0) cx = 1;
if (cy <= 0) cy = 1;
data->window = XCreateWindow( display, root_window,
x, y, cx, cy,
0, screen_depth,
InputOutput, visual,
CWEventMask | CWOverrideRedirect |
CWColormap | CWCursor | CWSaveUnder |
CWBackingStore | CWBitGravity,
&win_attr );
if (win_attr.cursor) XFreeCursor( display, win_attr.cursor );
/***********************************************************************
* X11DRV_sync_client_window_position
*
* Synchronize the X client window position with the Windows one
*/
int X11DRV_sync_client_window_position( Display *display, WND *win )
{
XWindowChanges changes;
int mask;
struct x11drv_win_data *data = win->pDriverData;
RECT client_rect = win->rectClient;
OffsetRect( &client_rect, -data->whole_rect.left, -data->whole_rect.top );
/* client rect cannot be empty */
if (client_rect.top >= client_rect.bottom) client_rect.bottom = client_rect.top + 1;
if (client_rect.left >= client_rect.right) client_rect.right = client_rect.left + 1;
if ((mask = get_window_changes( &changes, &data->client_rect, &client_rect )))
{
TRACE( "setting win %lx pos %d,%d,%dx%d (was %d,%d,%dx%d) after %lx changes=%x\n",
data->client_window, client_rect.left, client_rect.top,
client_rect.right - client_rect.left, client_rect.bottom - client_rect.top,
data->client_rect.left, data->client_rect.top,
data->client_rect.right - data->client_rect.left,
data->client_rect.bottom - data->client_rect.top,
changes.sibling, mask );
data->client_rect = client_rect;
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush graphics operations before moving the window */
XConfigureWindow( display, data->client_window, mask, &changes );
wine_tsx11_unlock();
}
return mask;
}
if(!(wGroupLeader = data->window))
{
HeapFree( GetProcessHeap(), 0, data );
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
/* If we are the systray, we need to be managed to be noticed by KWM */
if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW) dock_window( display, data->window );
/***********************************************************************
* X11DRV_register_window
*
* Associate an X window to a HWND.
*/
void X11DRV_register_window( Display *display, HWND hwnd, struct x11drv_win_data *data )
{
wine_tsx11_lock();
XSaveContext( display, data->whole_window, winContext, (char *)hwnd );
XSaveContext( display, data->client_window, winContext, (char *)hwnd );
wine_tsx11_unlock();
}
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
XClassHint *class_hints = TSXAllocClassHint();
XSizeHints* size_hints = TSXAllocSizeHints();
if (class_hints)
{
class_hints->res_name = "wineManaged";
class_hints->res_class = "Wine";
TSXSetClassHint( display, data->window, class_hints );
TSXFree (class_hints);
}
/**********************************************************************
* create_desktop
*/
static void create_desktop( Display *display, WND *wndPtr )
{
X11DRV_WND_DATA *data = wndPtr->pDriverData;
if (size_hints)
{
size_hints->win_gravity = StaticGravity;
size_hints->x = x;
size_hints->y = y;
size_hints->flags = PWinGravity|PPosition;
if (HAS_DLGFRAME(wndPtr->dwStyle,wndPtr->dwExStyle))
{
size_hints->min_width = size_hints->max_width = cx;
size_hints->min_height = size_hints->max_height = cy;
size_hints->flags |= PMinSize | PMaxSize;
}
TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
size_hints, XA_WM_NORMAL_HINTS );
TSXFree(size_hints);
}
}
wine_tsx11_lock();
winContext = XUniqueContext();
wmProtocols = XInternAtom( display, "WM_PROTOCOLS", False );
wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", False );
/* wmTakeFocus = XInternAtom( display, "WM_TAKE_FOCUS", False );*/
wmTakeFocus = 0; /* not yet */
dndProtocol = XInternAtom( display, "DndProtocol" , False );
dndSelection = XInternAtom( display, "DndSelection" , False );
wmChangeState = XInternAtom (display, "WM_CHANGE_STATE", False);
kwmDockWindow = XInternAtom( display, "KWM_DOCKWINDOW", False );
_kde_net_wm_system_tray_window_for = XInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
wine_tsx11_unlock();
data->whole_window = data->client_window = root_window;
if (root_window != DefaultRootWindow(display))
{
wndPtr->flags |= WIN_NATIVE;
X11DRV_create_desktop_thread();
}
}
/**********************************************************************
* create_whole_window
*
* Create the whole X window for a given window
*/
static Window create_whole_window( Display *display, WND *win )
{
struct x11drv_win_data *data = win->pDriverData;
int cx, cy, mask;
XSetWindowAttributes attr;
Window parent;
RECT rect;
BOOL is_top_level = is_window_top_level( win );
mask = get_window_attributes( win, &attr );
rect = win->rectWindow;
X11DRV_window_to_X_rect( win, &rect );
if (!(cx = rect.right - rect.left)) cx = 1;
if (!(cy = rect.bottom - rect.top)) cy = 1;
parent = get_client_window( win->parent );
wine_tsx11_lock();
if (is_top_level) attr.cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
data->whole_rect = rect;
data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
0, screen_depth, InputOutput, visual,
mask, &attr );
if (attr.cursor) XFreeCursor( display, attr.cursor );
if (!data->whole_window) goto done;
/* non-maximized child must be at bottom of Z order */
if ((win->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
{
XWindowChanges changes;
changes.stack_mode = Below;
XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
}
if (is_top_level && !attr.override_redirect) set_wm_hints( display, win );
done:
wine_tsx11_unlock();
return data->whole_window;
}
/**********************************************************************
* create_client_window
*
* Create the client window for a given window
*/
static Window create_client_window( Display *display, WND *win )
{
struct x11drv_win_data *data = win->pDriverData;
RECT rect;
XSetWindowAttributes attr;
rect = win->rectWindow;
SendMessageW( win->hwndSelf, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
if (rect.left > rect.right || rect.top > rect.bottom) rect = win->rectWindow;
if (rect.top >= rect.bottom) rect.bottom = rect.top + 1;
if (rect.left >= rect.right) rect.right = rect.left + 1;
win->rectClient = rect;
OffsetRect( &rect, -data->whole_rect.left, -data->whole_rect.top );
data->client_rect = rect;
attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
attr.bit_gravity = (win->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ?
ForgetGravity : NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
data->client_window = TSXCreateWindow( display, data->whole_window,
rect.left, rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
0, screen_depth,
InputOutput, visual,
CWEventMask | CWBitGravity | CWBackingStore, &attr );
if (data->client_window) TSXMapWindow( display, data->client_window );
return data->client_window;
}
/*****************************************************************
* SetWindowText (X11DRV.@)
*/
BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
{
Display *display = thread_display();
UINT count;
char *buffer;
static UINT text_cp = (UINT)-1;
Window win;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if (wndPtr->owner) /* Get window owner */
if (!wndPtr) return FALSE;
if ((win = get_whole_window(wndPtr)))
{
if (text_cp == (UINT)-1)
{
Window w = X11DRV_WND_FindXWindow( wndPtr->owner );
if (w != None)
{
TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
wGroupLeader = w;
}
text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
TRACE("text_cp = %u\n", text_cp);
}
if ((wm_hints = TSXAllocWMHints()))
/* allocate new buffer for window text */
count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
{
wm_hints->flags = InputHint | StateHint | WindowGroupHint;
wm_hints->input = True;
ERR("Not enough memory for window text\n");
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
set_icon_hints( display, wndPtr, wm_hints );
wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
? IconicState : NormalState;
}
else
wm_hints->initial_state = NormalState;
wm_hints->window_group = wGroupLeader;
wine_tsx11_lock();
XStoreName( display, win, buffer );
XSetIconName( display, win, buffer );
wine_tsx11_unlock();
TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
TSXFree(wm_hints);
}
X11DRV_register_window( display, hwnd, data->window );
TSXFlush( display );
HeapFree( GetProcessHeap(), 0, buffer );
}
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
......@@ -366,37 +741,209 @@ BOOL X11DRV_DestroyWindow( HWND hwnd )
Display *display = thread_display();
WND *wndPtr = WIN_FindWndPtr( hwnd );
X11DRV_WND_DATA *data = wndPtr->pDriverData;
Window w;
if (data && (w = data->window))
if (!data) goto done;
if (data->whole_window)
{
XEvent xe;
TRACE( "win %x xwin %lx/%lx\n", hwnd, data->whole_window, data->client_window );
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush any reference to this drawable in GDI queue */
XDeleteContext( display, w, winContext );
XDestroyWindow( display, w );
while( XCheckWindowEvent(display, w, NoEventMask, &xe) );
XDeleteContext( display, data->whole_window, winContext );
XDeleteContext( display, data->client_window, winContext );
XDestroyWindow( display, data->whole_window ); /* this destroys client too */
destroy_icon_window( display, data );
wine_tsx11_unlock();
data->window = None;
if( data->hWMIconBitmap )
{
DeleteObject( data->hWMIconBitmap );
data->hWMIconBitmap = 0;
}
if( data->hWMIconMask )
{
DeleteObject( data->hWMIconMask);
data->hWMIconMask= 0;
}
}
if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
HeapFree( GetProcessHeap(), 0, data );
wndPtr->pDriverData = NULL;
done:
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
/**********************************************************************
* CreateWindow (X11DRV.@)
*/
BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs )
{
Display *display = thread_display();
WND *wndPtr;
struct x11drv_win_data *data;
BOOL ret = FALSE;
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) return FALSE;
data->whole_window = 0;
data->client_window = 0;
data->icon_window = 0;
data->hWMIconBitmap = 0;
data->hWMIconMask = 0;
wndPtr = WIN_FindWndPtr( hwnd );
wndPtr->pDriverData = data;
wndPtr->flags |= WIN_NATIVE;
WIN_ReleaseWndPtr( wndPtr );
if (IsWindowUnicode( hwnd ))
ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
else
ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
if (!ret) goto failed;
TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
if (!wndPtr->parent)
{
create_desktop( display, wndPtr );
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
if (!create_whole_window( display, wndPtr )) goto failed;
if (!create_client_window( display, wndPtr )) goto failed;
TSXSync( display, False );
TRACE( "win %x window %d,%d,%d,%d client %d,%d,%d,%d whole %d,%d,%d,%d X client %d,%d,%d,%d xwin %x/%x\n",
hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
wndPtr->rectClient.left, wndPtr->rectClient.top,
wndPtr->rectClient.right, wndPtr->rectClient.bottom,
data->whole_rect.left, data->whole_rect.top,
data->whole_rect.right, data->whole_rect.bottom,
data->client_rect.left, data->client_rect.top,
data->client_rect.right, data->client_rect.bottom,
(unsigned int)data->whole_window, (unsigned int)data->client_window );
if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
WIN_LinkWindow( hwnd, HWND_BOTTOM );
else
WIN_LinkWindow( hwnd, HWND_TOP );
if (wndPtr->text) X11DRV_SetWindowText( hwnd, wndPtr->text );
X11DRV_register_window( display, hwnd, data );
WIN_ReleaseWndPtr( wndPtr );
if (IsWindowUnicode( hwnd ))
ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
else
ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
if (!ret)
{
WIN_UnlinkWindow( hwnd );
goto failed;
}
/* Send the size messages */
if (!(wndPtr->flags & WIN_NEED_SIZE))
{
/* send it anyway */
if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
WARN("sending bogus WM_SIZE message 0x%08lx\n",
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
SendMessageW( hwnd, WM_MOVE, 0,
MAKELONG( wndPtr->rectClient.left, wndPtr->rectClient.top ) );
}
/* Show the window, maximizing or minimizing if needed */
if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
{
extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ); /*FIXME*/
RECT newPos;
UINT swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
WINPOS_MinMaximize( hwnd, swFlag, &newPos );
swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
: SWP_NOZORDER | SWP_FRAMECHANGED;
SetWindowPos( hwnd, 0, newPos.left, newPos.top,
newPos.right, newPos.bottom, swFlag );
}
return TRUE;
failed:
X11DRV_DestroyWindow( wndPtr->hwndSelf );
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
/***********************************************************************
* X11DRV_get_client_window
*
* Return the X window associated with the client area of a window
*/
Window X11DRV_get_client_window( HWND hwnd )
{
Window ret = 0;
WND *win = WIN_FindWndPtr( hwnd );
if (win)
{
struct x11drv_win_data *data = win->pDriverData;
ret = data->client_window;
WIN_ReleaseWndPtr( win );
}
return ret;
}
/***********************************************************************
* X11DRV_get_whole_window
*
* Return the X window associated with the full area of a window
*/
Window X11DRV_get_whole_window( HWND hwnd )
{
Window ret = 0;
WND *win = WIN_FindWndPtr( hwnd );
if (win)
{
struct x11drv_win_data *data = win->pDriverData;
ret = data->whole_window;
WIN_ReleaseWndPtr( win );
}
return ret;
}
/***********************************************************************
* X11DRV_get_top_window
*
* Return the X window associated with the top-level parent of a window
*/
Window X11DRV_get_top_window( HWND hwnd )
{
Window ret = 0;
WND *win = WIN_FindWndPtr( hwnd );
while (win && win->parent->hwndSelf != GetDesktopWindow())
WIN_UpdateWndPtr( &win, win->parent );
if (win)
{
struct x11drv_win_data *data = win->pDriverData;
ret = data->whole_window;
WIN_ReleaseWndPtr( win );
}
return ret;
}
/*****************************************************************
* SetParent (X11DRV.@)
*/
......@@ -427,34 +974,32 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
retvalue = wndPtr->parent->hwndSelf; /* old parent */
if (pWndParent != wndPtr->parent)
{
if ( X11DRV_WND_GetXWindow(wndPtr) )
{
/* Toplevel window needs to be reparented. Used by Tk 8.0 */
TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
}
struct x11drv_win_data *data = wndPtr->pDriverData;
int mask;
XSetWindowAttributes attr;
WIN_UnlinkWindow(wndPtr->hwndSelf);
wndPtr->parent = pWndParent;
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
/* Create an X counterpart for reparented top-level windows
* when not in the desktop mode. */
if (parent == GetDesktopWindow())
{
if(root_window == DefaultRootWindow(display))
X11DRV_CreateWindow(wndPtr->hwndSelf);
}
else /* a child window */
mask = get_window_attributes( wndPtr, &attr );
if (is_window_top_level( wndPtr ) && !attr.override_redirect)
set_wm_hints( display, wndPtr );
if (parent != GetDesktopWindow()) /* a child window */
{
if( !( wndPtr->dwStyle & WS_CHILD ) )
if (!(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
{
if( wndPtr->wIDmenu != 0)
{
DestroyMenu( (HMENU) wndPtr->wIDmenu );
wndPtr->wIDmenu = 0;
}
DestroyMenu( (HMENU)wndPtr->wIDmenu );
wndPtr->wIDmenu = 0;
}
}
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
wine_tsx11_lock();
XChangeWindowAttributes( display, data->whole_window, mask, &attr );
XReparentWindow( display, data->whole_window, get_client_window(pWndParent),
data->whole_rect.left, data->whole_rect.top );
wine_tsx11_unlock();
}
WIN_ReleaseWndPtr( pWndParent );
WIN_ReleaseWndPtr( wndPtr );
......@@ -479,9 +1024,9 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
{
Display *display = thread_display();
XWMHints *wm_hints;
WND *wndPtr;
BOOL retvalue;
Window w;
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
......@@ -492,8 +1037,20 @@ BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
/* Enable window */
wndPtr->dwStyle &= ~WS_DISABLED;
if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
set_wm_hint( display, w, InputHint, TRUE );
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
wine_tsx11_lock();
if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
wm_hints = XAllocWMHints();
if (wm_hints)
{
wm_hints->flags |= InputHint;
wm_hints->input = TRUE;
XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
XFree(wm_hints);
}
wine_tsx11_unlock();
}
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
}
......@@ -504,8 +1061,20 @@ BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
/* Disable window */
wndPtr->dwStyle |= WS_DISABLED;
if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
set_wm_hint( display, w, InputHint, FALSE );
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
wine_tsx11_lock();
if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
wm_hints = XAllocWMHints();
if (wm_hints)
{
wm_hints->flags |= InputHint;
wm_hints->input = FALSE;
XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
XFree(wm_hints);
}
wine_tsx11_unlock();
}
if (hwnd == GetFocus())
SetFocus( 0 ); /* A disabled window can't have the focus */
......@@ -540,9 +1109,8 @@ void X11DRV_SetFocus( HWND hwnd )
/* no desktop window and if the window is not managed by the WM. */
if (root_window != DefaultRootWindow(display)) goto done;
while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
w = w->parent;
if (!w) w = wndPtr;
while (w && !get_whole_window(w)) w = w->parent;
if (!w) goto done;
if (w->dwExStyle & WS_EX_MANAGED) goto done;
if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
......@@ -550,18 +1118,23 @@ void X11DRV_SetFocus( HWND hwnd )
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
}
else if ((win = X11DRV_WND_FindXWindow(wndPtr)))
else if ((win = get_whole_window(w)))
{
/* Set X focus and install colormap */
if (TSXGetWindowAttributes( display, win, &win_attr ) &&
wine_tsx11_lock();
if (XGetWindowAttributes( display, win, &win_attr ) &&
(win_attr.map_state == IsViewable))
{
/* If window is not viewable, don't change anything */
TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
/* we must not use CurrentTime (ICCCM), so try to use last message time instead */
/* FIXME: this is not entirely correct */
XSetInputFocus( display, win, RevertToParent,
/*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks );
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
X11DRV_Synchronize();
XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
}
wine_tsx11_unlock();
}
done:
......@@ -569,46 +1142,6 @@ void X11DRV_SetFocus( HWND hwnd )
}
/*****************************************************************
* SetWindowText (X11DRV.@)
*/
BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
{
Display *display = thread_display();
UINT count;
char *buffer;
static UINT text_cp = (UINT)-1;
Window win;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return FALSE;
if ((win = X11DRV_WND_GetXWindow(wndPtr)))
{
if (text_cp == (UINT)-1)
{
text_cp = PROFILE_GetWineIniInt("x11drv", "TextCP", CP_ACP);
TRACE("text_cp = %u\n", text_cp);
}
/* allocate new buffer for window text */
count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
{
ERR("Not enough memory for window text\n");
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
TSXStoreName( display, win, buffer );
TSXSetIconName( display, win, buffer );
HeapFree( GetProcessHeap(), 0, buffer );
}
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
/**********************************************************************
* X11DRV_SetWindowIcon
*
......@@ -636,7 +1169,7 @@ HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
Window win = X11DRV_WND_GetXWindow(wndPtr);
Window win = get_whole_window(wndPtr);
XWMHints* wm_hints = TSXGetWMHints( display, win );
if (!wm_hints) wm_hints = TSXAllocWMHints();
......@@ -651,154 +1184,3 @@ HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
WIN_ReleaseWndPtr( wndPtr );
return old;
}
/*************************************************************************
* fix_caret
*/
static BOOL fix_caret(HWND hWnd, LPRECT lprc, UINT flags)
{
HWND hCaret = CARET_GetHwnd();
if( hCaret )
{
RECT rc;
CARET_GetRect( &rc );
if( hCaret == hWnd ||
(flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) )
{
POINT pt;
pt.x = rc.left;
pt.y = rc.top;
MapWindowPoints( hCaret, hWnd, (LPPOINT)&rc, 2 );
if( IntersectRect(lprc, lprc, &rc) )
{
HideCaret(0);
lprc->left = pt.x;
lprc->top = pt.y;
return TRUE;
}
}
}
return FALSE;
}
/*************************************************************************
* ScrollWindowEx (X11DRV.@)
*/
INT X11DRV_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
const RECT *rect, const RECT *clipRect,
HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags )
{
INT retVal = NULLREGION;
BOOL bCaret = FALSE, bOwnRgn = TRUE;
RECT rc, cliprc;
WND* wnd = WIN_FindWndPtr( hwnd );
if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE ))
{
retVal = ERROR;
goto END;
}
GetClientRect(hwnd, &rc);
if (rect) IntersectRect(&rc, &rc, rect);
if (clipRect) IntersectRect(&cliprc,&rc,clipRect);
else cliprc = rc;
if (!IsRectEmpty(&cliprc) && (dx || dy))
{
HDC hDC;
BOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
HRGN hrgnClip = CreateRectRgnIndirect(&cliprc);
HRGN hrgnTemp = CreateRectRgnIndirect(&rc);
RECT caretrc;
TRACE("%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d) %04x\n",
(HWND16)hwnd, dx, dy, hrgnUpdate, rcUpdate,
clipRect?clipRect->left:0, clipRect?clipRect->top:0,
clipRect?clipRect->right:0, clipRect?clipRect->bottom:0,
rc.left, rc.top, rc.right, rc.bottom, (UINT16)flags );
caretrc = rc;
bCaret = fix_caret(hwnd, &caretrc, flags);
if( hrgnUpdate ) bOwnRgn = FALSE;
else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
hDC = GetDCEx( hwnd, hrgnClip, DCX_CACHE | DCX_USESTYLE |
DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
((flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0) );
if (hDC)
{
X11DRV_WND_SurfaceCopy(wnd,hDC,dx,dy,&rc,bUpdate);
if( bUpdate )
{
DC* dc;
if( (dc = DC_GetDCPtr(hDC)) )
{
OffsetRgn( hrgnTemp, dc->DCOrgX, dc->DCOrgY );
CombineRgn( hrgnTemp, hrgnTemp, dc->hVisRgn,
RGN_AND );
OffsetRgn( hrgnTemp, -dc->DCOrgX, -dc->DCOrgY );
CombineRgn( hrgnUpdate, hrgnTemp, hrgnClip,
RGN_AND );
OffsetRgn( hrgnTemp, dx, dy );
retVal =
CombineRgn( hrgnUpdate, hrgnUpdate, hrgnTemp,
RGN_DIFF );
if( rcUpdate ) GetRgnBox( hrgnUpdate, rcUpdate );
GDI_ReleaseObj( hDC );
}
}
ReleaseDC(hwnd, hDC);
}
if( wnd->hrgnUpdate > 1 )
{
/* Takes into account the fact that some damages may have
occured during the scroll. */
CombineRgn( hrgnTemp, wnd->hrgnUpdate, 0, RGN_COPY );
OffsetRgn( hrgnTemp, dx, dy );
CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND );
CombineRgn( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnTemp, RGN_OR );
}
if( flags & SW_SCROLLCHILDREN )
{
RECT r;
WND *w;
for( w =WIN_LockWndPtr(wnd->child); w; WIN_UpdateWndPtr(&w, w->next))
{
r = w->rectWindow;
if( !rect || IntersectRect(&r, &r, &rc) )
SetWindowPos(w->hwndSelf, 0, w->rectWindow.left + dx,
w->rectWindow.top + dy, 0,0, SWP_NOZORDER |
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
SWP_DEFERERASE );
}
}
if( flags & (SW_INVALIDATE | SW_ERASE) )
RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
if( bCaret )
{
SetCaretPos( caretrc.left + dx, caretrc.top + dy );
ShowCaret(0);
}
if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
DeleteObject( hrgnClip );
DeleteObject( hrgnTemp );
}
END:
WIN_ReleaseWndPtr(wnd);
return retVal;
}
......@@ -8,6 +8,7 @@
#include "config.h"
#include "ts_xlib.h"
#include "ts_xutil.h"
#include "ts_shape.h"
#include "winbase.h"
......@@ -26,8 +27,7 @@
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(win);
DEFAULT_DEBUG_CHANNEL(x11drv);
#define SWP_AGG_NOGEOMETRYCHANGE \
(SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
......@@ -53,480 +53,187 @@ DEFAULT_DEBUG_CHANNEL(win);
#define ON_BOTTOM_BORDER(hit) \
(((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
/***********************************************************************
* DCE_OffsetVisRgn
*
* Change region from DC-origin relative coordinates to screen coords.
*/
static void DCE_OffsetVisRgn( HDC hDC, HRGN hVisRgn )
{
DC *dc;
if (!(dc = DC_GetDCPtr( hDC ))) return;
OffsetRgn( hVisRgn, dc->DCOrgX, dc->DCOrgY );
GDI_ReleaseObj( hDC );
}
/***********************************************************************
* DCE_GetVisRect
* clip_children
*
* Calculate the visible rectangle of a window (i.e. the client or
* window area clipped by the client area of all ancestors) in the
* corresponding coordinates. Return FALSE if the visible region is empty.
* Clip all children of a given window out of the visible region
*/
static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
static void clip_children( WND *win, HRGN hrgn, int whole_window )
{
*lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
if (wndPtr->dwStyle & WS_VISIBLE)
{
INT xoffset = lprect->left;
INT yoffset = lprect->top;
WND *ptr;
HRGN rectRgn;
int x, y;
while( !(wndPtr->flags & WIN_NATIVE) &&
( wndPtr = WIN_LockWndPtr(wndPtr->parent)) )
{
if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
{
WIN_ReleaseWndPtr(wndPtr);
goto fail;
}
/* first check if we have anything to do */
for (ptr = win->child; ptr; ptr = ptr->next)
if (ptr->dwStyle & WS_VISIBLE) break;
if (!ptr) return; /* no children to clip */
xoffset += wndPtr->rectClient.left;
yoffset += wndPtr->rectClient.top;
OffsetRect( lprect, wndPtr->rectClient.left,
wndPtr->rectClient.top );
if( (wndPtr->rectClient.left >= wndPtr->rectClient.right) ||
(wndPtr->rectClient.top >= wndPtr->rectClient.bottom) ||
(lprect->left >= wndPtr->rectClient.right) ||
(lprect->right <= wndPtr->rectClient.left) ||
(lprect->top >= wndPtr->rectClient.bottom) ||
(lprect->bottom <= wndPtr->rectClient.top) )
{
WIN_ReleaseWndPtr(wndPtr);
goto fail;
}
lprect->left = max( lprect->left, wndPtr->rectClient.left );
lprect->right = min( lprect->right, wndPtr->rectClient.right );
lprect->top = max( lprect->top, wndPtr->rectClient.top );
lprect->bottom = min( lprect->bottom, wndPtr->rectClient.bottom );
WIN_ReleaseWndPtr(wndPtr);
}
OffsetRect( lprect, -xoffset, -yoffset );
return TRUE;
if (whole_window)
{
x = win->rectWindow.left - win->rectClient.left;
y = win->rectWindow.top - win->rectClient.top;
}
else x = y = 0;
fail:
SetRectEmpty( lprect );
return FALSE;
}
/***********************************************************************
* DCE_AddClipRects
*
* Go through the linked list of windows from pWndStart to pWndEnd,
* adding to the clip region the intersection of the target rectangle
* with an offset window rectangle.
*/
static BOOL DCE_AddClipRects( WND *pWndStart, WND *pWndEnd,
HRGN hrgnClip, LPRECT lpRect, int x, int y )
{
RECT rect;
if (X11DRV_WND_GetXWindow(pWndStart)) return TRUE; /* X will do the clipping */
for (WIN_LockWndPtr(pWndStart); (pWndStart && (pWndStart != pWndEnd)); WIN_UpdateWndPtr(&pWndStart,pWndStart->next))
rectRgn = CreateRectRgn( 0, 0, 0, 0 );
while (ptr)
{
if( !(pWndStart->dwStyle & WS_VISIBLE) ) continue;
rect.left = pWndStart->rectWindow.left + x;
rect.top = pWndStart->rectWindow.top + y;
rect.right = pWndStart->rectWindow.right + x;
rect.bottom = pWndStart->rectWindow.bottom + y;
if( IntersectRect( &rect, &rect, lpRect ))
if (ptr->dwStyle & WS_VISIBLE)
{
if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break;
SetRectRgn( rectRgn, ptr->rectWindow.left + x, ptr->rectWindow.top + y,
ptr->rectWindow.right + x, ptr->rectWindow.bottom + y );
if (CombineRgn( hrgn, hrgn, rectRgn, RGN_DIFF ) == NULLREGION)
break; /* no need to go on, region is empty */
}
ptr = ptr->next;
}
WIN_ReleaseWndPtr(pWndStart);
return (pWndStart == pWndEnd);
DeleteObject( rectRgn );
}
/***********************************************************************
* DCE_GetVisRgn
* get_visible_region
*
* Return the visible region of a window, i.e. the client or window area
* clipped by the client area of all ancestors, and then optionally
* by siblings and children.
* Compute the visible region of a window
*/
static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
static HRGN get_visible_region( WND *win, UINT flags )
{
HRGN hrgnVis = 0;
HRGN rgn;
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
WND *childWnd = WIN_FindWndPtr( hwndChild );
/* Get visible rectangle and create a region with it. */
int xoffset, yoffset;
X11DRV_WND_DATA *data = win->pDriverData;
if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
if (flags & DCX_WINDOW)
{
if((hrgnVis = CreateRectRgnIndirect( &rect )))
{
HRGN hrgnClip = CreateRectRgn( 0, 0, 0, 0 );
INT xoffset, yoffset;
if( hrgnClip )
{
/* Compute obscured region for the visible rectangle by
* clipping children, siblings, and ancestors. Note that
* DCE_GetVisRect() returns a rectangle either in client
* or in window coordinates (for DCX_WINDOW request). */
if( (flags & DCX_CLIPCHILDREN) && wndPtr->child )
{
if( flags & DCX_WINDOW )
{
/* adjust offsets since child window rectangles are
* in client coordinates */
xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
}
else
xoffset = yoffset = 0;
DCE_AddClipRects( wndPtr->child, NULL, hrgnClip, &rect, xoffset, yoffset );
}
/* We may need to clip children of child window, if a window with PARENTDC
* class style and CLIPCHILDREN window style (like in Free Agent 16
* preference dialogs) gets here, we take the region for the parent window
* but apparently still need to clip the children of the child window... */
if( (cflags & DCX_CLIPCHILDREN) && childWnd && childWnd->child )
{
if( flags & DCX_WINDOW )
{
/* adjust offsets since child window rectangles are
* in client coordinates */
xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left;
yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top;
}
else
xoffset = yoffset = 0;
/* client coordinates of child window */
xoffset += childWnd->rectClient.left;
yoffset += childWnd->rectClient.top;
DCE_AddClipRects( childWnd->child, NULL, hrgnClip,
&rect, xoffset, yoffset );
}
/* sibling window rectangles are in client
* coordinates of the parent window */
if (flags & DCX_WINDOW)
{
xoffset = -wndPtr->rectWindow.left;
yoffset = -wndPtr->rectWindow.top;
}
else
{
xoffset = -wndPtr->rectClient.left;
yoffset = -wndPtr->rectClient.top;
}
xoffset = win->rectWindow.left;
yoffset = win->rectWindow.top;
}
else
{
xoffset = win->rectClient.left;
yoffset = win->rectClient.top;
}
if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
DCE_AddClipRects( wndPtr->parent->child,
wndPtr, hrgnClip, &rect, xoffset, yoffset );
if (flags & DCX_PARENTCLIP)
GetClientRect( win->parent->hwndSelf, &rect );
else if (flags & DCX_WINDOW)
rect = data->whole_rect;
else
rect = win->rectClient;
/* Clip siblings of all ancestors that have the
* WS_CLIPSIBLINGS style
*/
/* vis region is relative to the start of the client/window area */
OffsetRect( &rect, -xoffset, -yoffset );
while (wndPtr->parent)
{
WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
xoffset -= wndPtr->rectClient.left;
yoffset -= wndPtr->rectClient.top;
if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
{
DCE_AddClipRects( wndPtr->parent->child, wndPtr,
hrgnClip, &rect, xoffset, yoffset );
}
}
if (!(rgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) return 0;
/* Now once we've got a jumbo clip region we have
* to substract it from the visible rectangle.
*/
CombineRgn( hrgnVis, hrgnVis, hrgnClip, RGN_DIFF );
DeleteObject( hrgnClip );
}
else
{
DeleteObject( hrgnVis );
hrgnVis = 0;
}
}
if (flags & DCX_CLIPCHILDREN)
{
/* if we are clipping siblings and using the client area,
* X will do the clipping for us; otherwise, we need to
* clip children by hand here
*/
if ((flags & DCX_WINDOW) || !(flags & DCX_CLIPSIBLINGS))
clip_children( win, rgn, (flags & DCX_WINDOW) );
}
else
hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
WIN_ReleaseWndPtr(wndPtr);
WIN_ReleaseWndPtr(childWnd);
return hrgnVis;
return rgn;
}
/***********************************************************************
* GetDC (X11DRV.@)
* X11DRV_GetDC
*
* Set the drawable, origin and dimensions for the DC associated to
* a given window.
*/
BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
{
WND *w, *wndPtr = WIN_FindWndPtr(hwnd);
DC *dc;
X11DRV_PDEVICE *physDev;
INT dcOrgXCopy = 0, dcOrgYCopy = 0;
BOOL offsetClipRgn = FALSE;
BOOL updateVisRgn;
HRGN hrgnVisible = 0;
if (!wndPtr) return FALSE;
WND *win = WIN_FindWndPtr( hwnd );
X11DRV_WND_DATA *data = win->pDriverData;
Drawable drawable;
int org_x, org_y, mode = IncludeInferiors;
if (!(dc = DC_GetDCPtr( hdc )))
{
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
/* don't clip siblings if using parent clip region */
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
physDev = (X11DRV_PDEVICE *)dc->physDev;
/*
* This function change the coordinate system (DCOrgX,DCOrgY)
* values. When it moves the origin, other data like the current clipping
* region will not be moved to that new origin. In the case of DCs that are class
* or window DCs that clipping region might be a valid value from a previous use
* of the DC and changing the origin of the DC without moving the clip region
* results in a clip region that is not placed properly in the DC.
* This code will save the dc origin, let the SetDrawable
* modify the origin and reset the clipping. When the clipping is set,
* it is moved according to the new DC origin.
*/
if ( (wndPtr->clsStyle & (CS_OWNDC | CS_CLASSDC)) && (dc->hClipRgn > 0))
if (flags & DCX_CLIPSIBLINGS)
{
dcOrgXCopy = dc->DCOrgX;
dcOrgYCopy = dc->DCOrgY;
offsetClipRgn = TRUE;
}
if (flags & DCX_WINDOW)
{
dc->DCOrgX = wndPtr->rectWindow.left;
dc->DCOrgY = wndPtr->rectWindow.top;
if (IsIconic( hwnd ))
{
drawable = data->icon_window ? data->icon_window : data->whole_window;
org_x = 0;
org_y = 0;
}
else if (flags & DCX_WINDOW)
{
drawable = data->whole_window;
org_x = win->rectWindow.left - data->whole_rect.left;
org_y = win->rectWindow.top - data->whole_rect.top;
}
else
{
drawable = data->client_window;
org_x = 0;
org_y = 0;
if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren; /* can use X11 clipping */
}
}
else
{
dc->DCOrgX = wndPtr->rectClient.left;
dc->DCOrgY = wndPtr->rectClient.top;
}
w = wndPtr;
while (!X11DRV_WND_GetXWindow(w))
{
w = w->parent;
dc->DCOrgX += w->rectClient.left;
dc->DCOrgY += w->rectClient.top;
}
dc->DCOrgX -= w->rectWindow.left;
dc->DCOrgY -= w->rectWindow.top;
/* reset the clip region, according to the new origin */
if ( offsetClipRgn )
{
OffsetRgn(dc->hClipRgn, dc->DCOrgX - dcOrgXCopy,dc->DCOrgY - dcOrgYCopy);
}
physDev->drawable = X11DRV_WND_GetXWindow(w);
#if 0
/* This is needed when we reuse a cached DC because
* SetDCState() called by ReleaseDC() screws up DC
* origins for child windows.
*/
if( bSetClipOrigin )
TSXSetClipOrigin( display, physDev->gc, dc->DCOrgX, dc->DCOrgY );
#endif
updateVisRgn = (dc->flags & DC_DIRTY) != 0;
GDI_ReleaseObj( hdc );
if (updateVisRgn)
{
if (flags & DCX_PARENTCLIP)
/* not clipping siblings -> have to use parent client drawable */
if (win->parent) drawable = get_client_window( win->parent );
else drawable = root_window;
if (flags & DCX_WINDOW)
{
WND *parentPtr = WIN_LockWndPtr(wndPtr->parent);
if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
{
DWORD dcxFlags;
if( parentPtr->dwStyle & WS_CLIPSIBLINGS )
dcxFlags = DCX_CLIPSIBLINGS | (flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
else
dcxFlags = flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
hrgnVisible = DCE_GetVisRgn( parentPtr->hwndSelf, dcxFlags,
wndPtr->hwndSelf, flags );
if( flags & DCX_WINDOW )
OffsetRgn( hrgnVisible, -wndPtr->rectWindow.left,
-wndPtr->rectWindow.top );
else
OffsetRgn( hrgnVisible, -wndPtr->rectClient.left,
-wndPtr->rectClient.top );
DCE_OffsetVisRgn( hdc, hrgnVisible );
}
else
hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
WIN_ReleaseWndPtr(parentPtr);
org_x = win->rectWindow.left;
org_y = win->rectWindow.top;
}
else
{
if ((hwnd == GetDesktopWindow()) && (root_window != DefaultRootWindow(thread_display())))
hrgnVisible = CreateRectRgn( 0, 0, GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN) );
else
{
hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
DCE_OffsetVisRgn( hdc, hrgnVisible );
}
org_x = win->rectClient.left;
org_y = win->rectClient.top;
}
SelectVisRgn16( hdc, hrgnVisible );
}
/* apply additional region operation (if any) */
X11DRV_SetDrawable( hdc, drawable, mode, org_x, org_y );
if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) ||
SetHookFlags16( hdc, DCHF_VALIDATEVISRGN )) /* DC was dirty */
{
if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
/* need to recompute the visible region */
HRGN visRgn = get_visible_region( win, flags );
TRACE("\tsaved VisRgn, clipRgn = %04x\n", hrgn);
if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
CombineRgn( visRgn, visRgn, hrgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
SaveVisRgn16( hdc );
CombineRgn( hrgnVisible, hrgn, 0, RGN_COPY );
DCE_OffsetVisRgn( hdc, hrgnVisible );
CombineRgn( hrgnVisible, InquireVisRgn16( hdc ), hrgnVisible,
(flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
SelectVisRgn16( hdc, hrgnVisible );
/* make it relative to the drawable origin */
OffsetRgn( visRgn, org_x, org_y );
SelectVisRgn16( hdc, visRgn );
DeleteObject( visRgn );
}
if (hrgnVisible) DeleteObject( hrgnVisible );
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleaseWndPtr( win );
return TRUE;
}
/***********************************************************************
* SWP_DoSimpleFrameChanged
*
* NOTE: old and new client rect origins are identical, only
* extents may have changed. Window extents are the same.
*/
static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect,
WORD swpFlags, UINT uFlags )
{
INT i = 0;
RECT rect;
HRGN hrgn = 0;
if( !(swpFlags & SWP_NOCLIENTSIZE) )
{
/* Client rect changed its position/size, most likely a scrollar
* was added/removed.
*
* FIXME: WVR alignment flags
*/
if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
{
i++;
rect.top = 0;
rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
if(!(uFlags & SWP_EX_NOCOPY))
rect.left = pOldClientRect->right - wndPtr->rectClient.left;
else
{
rect.left = 0;
goto redraw;
}
}
if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
{
if( i )
hrgn = CreateRectRgnIndirect( &rect );
rect.left = 0;
rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
if(!(uFlags & SWP_EX_NOCOPY))
rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
else
rect.top = 0;
if( i++ )
REGION_UnionRectWithRgn( hrgn, &rect );
}
if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
{
rect = wndPtr->rectWindow;
OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
wndPtr->rectWindow.top - wndPtr->rectClient.top );
i++;
}
}
if( i )
{
redraw:
PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
}
else
{
WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
}
if( hrgn > 1 )
DeleteObject( hrgn );
}
/***********************************************************************
* SWP_DoWinPosChanging
*/
static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
RECT* pNewWindowRect, RECT* pNewClientRect )
static BOOL SWP_DoWinPosChanging( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect )
{
/* Send WM_WINDOWPOSCHANGING message */
WND *wndPtr;
/* Send WM_WINDOWPOSCHANGING message */
if (!(pWinpos->flags & SWP_NOSENDCHANGING))
SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
SendMessageA( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
/* Calculate new position and size */
if (!(wndPtr = WIN_FindWndPtr( pWinpos->hwnd ))) return FALSE;
/* Calculate new position and size */
*pNewWindowRect = wndPtr->rectWindow;
*pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
......@@ -547,8 +254,8 @@ static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
pWinpos->y - wndPtr->rectWindow.top );
}
pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
......@@ -556,7 +263,7 @@ static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
* SWP_DoNCCalcSize
*/
static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
RECT* pNewWindowRect, RECT* pNewClientRect )
{
UINT wvrFlags = 0;
......@@ -566,7 +273,6 @@ static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
&wndPtr->rectWindow, &wndPtr->rectClient,
pWinpos, pNewClientRect );
/* FIXME: WVR_ALIGNxxx */
if( pNewClientRect->left != wndPtr->rectClient.left ||
......@@ -580,8 +286,8 @@ static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
pWinpos->flags &= ~SWP_NOCLIENTSIZE;
}
else
if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top) )
if( !(pWinpos->flags & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top) )
pWinpos->flags &= ~SWP_NOCLIENTMOVE;
return wvrFlags;
}
......@@ -640,604 +346,823 @@ END:
return hwndInsertAfter;
}
/* fix redundant flags and values in the WINDOWPOS structure */
static BOOL fixup_flags( WINDOWPOS *winpos )
{
WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
BOOL ret = TRUE;
if (!wndPtr) return FALSE;
if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW;
else
{
winpos->flags &= ~SWP_HIDEWINDOW;
if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
}
if (winpos->cx < 0) winpos->cx = 0;
if (winpos->cy < 0) winpos->cy = 0;
if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
(wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
winpos->flags |= SWP_NOSIZE; /* Already the right size */
if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
winpos->flags |= SWP_NOMOVE; /* Already the right position */
if (winpos->hwnd == GetForegroundWindow())
winpos->flags |= SWP_NOACTIVATE; /* Already active */
else if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)
{
if (!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
{
winpos->flags &= ~SWP_NOZORDER;
winpos->hwndInsertAfter = HWND_TOP;
goto done;
}
}
/* Check hwndInsertAfter */
/* FIXME: TOPMOST not supported yet */
if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
(winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
/* hwndInsertAfter must be a sibling of the window */
if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
{
WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
if (wnd)
{
if (wnd->parent != wndPtr->parent) ret = FALSE;
else
{
/* don't need to change the Zorder of hwnd if it's already inserted
* after hwndInsertAfter or when inserting hwnd after itself.
*/
if ((wnd->next == wndPtr ) || (winpos->hwnd == winpos->hwndInsertAfter))
winpos->flags |= SWP_NOZORDER;
}
WIN_ReleaseWndPtr(wnd);
}
}
done:
WIN_ReleaseWndPtr(wndPtr);
return ret;
}
/***********************************************************************
* SWP_CopyValidBits
*
* Make window look nice without excessive repainting
*
* visible and update regions are in window coordinates
* client and window rectangles are in parent client coordinates
*
* Returns: uFlags and a dirty region in *pVisRgn.
* SetWindowPos (X11DRV.@)
*/
static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
LPRECT lpOldWndRect,
LPRECT lpOldClientRect, UINT uFlags )
BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
{
RECT r;
HRGN newVisRgn, dirtyRgn;
INT my = COMPLEXREGION;
DWORD dflags;
TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
Wnd->rectWindow.left, Wnd->rectWindow.top,
Wnd->rectWindow.right, Wnd->rectWindow.bottom,
lpOldWndRect->left, lpOldWndRect->top,
lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
Wnd->rectClient.left, Wnd->rectClient.top,
Wnd->rectClient.right, Wnd->rectClient.bottom,
lpOldClientRect->left, lpOldClientRect->top,
lpOldClientRect->right,lpOldClientRect->bottom );
if( Wnd->hrgnUpdate == 1 )
uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
dflags = DCX_WINDOW;
if(Wnd->dwStyle & WS_CLIPSIBLINGS)
dflags |= DCX_CLIPSIBLINGS;
newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, dflags, 0, 0);
dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
WND *wndPtr;
RECT newWindowRect, newClientRect;
RECT oldWindowRect, oldClientRect;
UINT wvrFlags = 0;
BOOL bChangePos;
TRACE( "hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
winpos->hwnd, winpos->x, winpos->y,
winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
bChangePos = !(winpos->flags & SWP_WINE_NOHOSTMOVE);
winpos->flags &= ~SWP_WINE_NOHOSTMOVE;
/* Check window handle */
if (winpos->hwnd == GetDesktopWindow()) return FALSE;
/* Fix redundant flags */
if (!fixup_flags( winpos )) return FALSE;
SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect );
if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n",
wndPtr->rectWindow.left, wndPtr->rectWindow.top,
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
{
if( wndPtr->parent->hwndSelf == GetDesktopWindow() )
winpos->hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
winpos->hwndInsertAfter, winpos->flags );
}
/* Common operations */
wvrFlags = SWP_DoNCCalcSize( wndPtr, winpos, &newWindowRect, &newClientRect );
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
{
if ( WIN_UnlinkWindow( winpos->hwnd ) )
WIN_LinkWindow( winpos->hwnd, winpos->hwndInsertAfter );
}
/* Reset active DCEs */
if( (((winpos->flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
wndPtr->dwStyle & WS_VISIBLE) ||
(winpos->flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
{
RECT rect;
UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
DCE_InvalidateDCE(wndPtr, &rect);
}
oldWindowRect = wndPtr->rectWindow;
oldClientRect = wndPtr->rectClient;
/* Find out if we have to redraw the whole client rect */
if( oldClientRect.bottom - oldClientRect.top ==
newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
if( oldClientRect.right - oldClientRect.left ==
newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
/* FIXME: actually do something with WVR_VALIDRECTS */
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
if (winpos->flags & SWP_SHOWWINDOW) wndPtr->dwStyle |= WS_VISIBLE;
else if (winpos->flags & SWP_HIDEWINDOW)
{
/* clear the update region */
RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
RDW_NOINTERNALPAINT | RDW_ALLCHILDREN );
wndPtr->dwStyle &= ~WS_VISIBLE;
}
if (get_whole_window(wndPtr)) /* don't do anything if X window not created yet */
{
Display *display = thread_display();
wine_tsx11_lock();
if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
{
if (!IsRectEmpty( &oldWindowRect ))
{
XUnmapWindow( display, get_whole_window(wndPtr) );
TRACE( "unmapping win %x\n", winpos->hwnd );
}
else TRACE( "not unmapping zero size win %x\n", winpos->hwnd );
}
else if ((wndPtr->dwStyle & WS_VISIBLE) &&
!IsRectEmpty( &oldWindowRect ) && IsRectEmpty( &newWindowRect ))
{
/* resizing to zero size -> unmap */
TRACE( "unmapping zero size win %x\n", winpos->hwnd );
XUnmapWindow( display, get_whole_window(wndPtr) );
}
if (bChangePos)
X11DRV_sync_whole_window_position( display, wndPtr, !(winpos->flags & SWP_NOZORDER) );
else
{
struct x11drv_win_data *data = wndPtr->pDriverData;
data->whole_rect = wndPtr->rectWindow;
X11DRV_window_to_X_rect( wndPtr, &data->whole_rect );
}
if (X11DRV_sync_client_window_position( display, wndPtr ) ||
(winpos->flags & SWP_FRAMECHANGED))
{
/* if we moved the client area, repaint the whole non-client window */
XClearArea( display, get_whole_window(wndPtr), 0, 0, 0, 0, True );
}
if (winpos->flags & SWP_SHOWWINDOW)
{
if (!IsRectEmpty( &newWindowRect ))
{
XMapWindow( display, get_whole_window(wndPtr) );
TRACE( "mapping win %x\n", winpos->hwnd );
}
else TRACE( "not mapping win %x, size is zero\n", winpos->hwnd );
}
else if ((wndPtr->dwStyle & WS_VISIBLE) &&
IsRectEmpty( &oldWindowRect ) && !IsRectEmpty( &newWindowRect ))
{
/* resizing from zero size to non-zero -> map */
TRACE( "mapping non zero size win %x\n", winpos->hwnd );
XMapWindow( display, get_whole_window(wndPtr) );
}
XFlush( display ); /* FIXME: should not be necessary */
wine_tsx11_unlock();
}
WIN_ReleaseWndPtr(wndPtr);
if (wvrFlags & WVR_REDRAW) RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
if (winpos->hwnd == CARET_GetHwnd())
{
nocopy:
if( winpos->flags & SWP_HIDEWINDOW )
HideCaret(winpos->hwnd);
else if (winpos->flags & SWP_SHOWWINDOW)
ShowCaret(winpos->hwnd);
}
if (!(winpos->flags & SWP_NOACTIVATE))
WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
/* And last, send the WM_WINDOWPOSCHANGED message */
TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
TRACE("\twon't copy anything!\n");
if (((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
!(winpos->flags & SWP_NOSENDCHANGING))
SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
return TRUE;
}
/***********************************************************************
* WINPOS_FindIconPos
*
* Find a suitable place for an iconic window.
*/
static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt )
{
RECT rectParent;
short x, y, xspacing, yspacing;
GetClientRect( wndPtr->parent->hwndSelf, &rectParent );
if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
(pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
return pt; /* The icon already has a suitable position */
xspacing = GetSystemMetrics(SM_CXICONSPACING);
yspacing = GetSystemMetrics(SM_CYICONSPACING);
y = rectParent.bottom;
for (;;)
{
x = rectParent.left;
do
{
/* Check if another icon already occupies this spot */
WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
while (childPtr)
{
if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
{
if ((childPtr->rectWindow.left < x + xspacing) &&
(childPtr->rectWindow.right >= x) &&
(childPtr->rectWindow.top <= y) &&
(childPtr->rectWindow.bottom > y - yspacing))
break; /* There's a window in there */
}
WIN_UpdateWndPtr(&childPtr,childPtr->next);
}
WIN_ReleaseWndPtr(childPtr);
if (!childPtr) /* No window was found, so it's OK for us */
{
pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
return pt;
}
x += xspacing;
} while(x <= rectParent.right-xspacing);
y -= yspacing;
}
}
/* set dirtyRgn to the sum of old and new visible regions
* in parent client coordinates */
OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
}
else /* copy valid bits to a new location */
{
INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
/* subtract already invalid region inside Wnd from the dst region */
if( Wnd->hrgnUpdate )
if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
goto nocopy;
UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
UINT swpFlags = 0;
POINT size;
WINDOWPLACEMENT wpl;
/* check if entire window can be copied */
TRACE("0x%04x %u\n", hwnd, cmd );
ow = lpOldWndRect->right - lpOldWndRect->left;
oh = lpOldWndRect->bottom - lpOldWndRect->top;
nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
wpl.length = sizeof(wpl);
GetWindowPlacement( hwnd, &wpl );
ocw = lpOldClientRect->right - lpOldClientRect->left;
och = lpOldClientRect->bottom - lpOldClientRect->top;
ncw = Wnd->rectClient.right - Wnd->rectClient.left;
nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
size.x = wndPtr->rectWindow.left;
size.y = wndPtr->rectWindow.top;
if( (ocw != ncw) || (och != nch) ||
( ow != nw) || ( oh != nh) ||
((lpOldClientRect->top - lpOldWndRect->top) !=
(Wnd->rectClient.top - Wnd->rectWindow.top)) ||
((lpOldClientRect->left - lpOldWndRect->left) !=
(Wnd->rectClient.left - Wnd->rectWindow.left)) )
if (!HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
{
if( wndPtr->dwStyle & WS_MINIMIZE )
{
if(uFlags & SWP_EX_PAINTSELF)
{
/* movement relative to the window itself */
dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
(lpOldClientRect->left - lpOldWndRect->left) ;
dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
(lpOldClientRect->top - lpOldWndRect->top) ;
}
else
if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
{
/* movement relative to the parent's client area */
dx = Wnd->rectClient.left - lpOldClientRect->left;
dy = Wnd->rectClient.top - lpOldClientRect->top;
swpFlags = SWP_NOSIZE | SWP_NOMOVE;
goto done;
}
/* restrict valid bits to the common client rect */
r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
r.right = r.left + min( ocw, ncw );
r.bottom = r.top + min( och, nch );
REGION_CropRgn( hrgnValid, hrgnValid, &r,
(uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
GetRgnBox( hrgnValid, &r );
if( IsRectEmpty( &r ) )
goto nocopy;
r = *lpOldClientRect;
swpFlags |= SWP_NOCOPYBITS;
}
else
switch( cmd )
{
if(uFlags & SWP_EX_PAINTSELF) {
/*
* with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
* relative to itself, only the client area can change.
* if the client rect didn't change, there's nothing to do.
*/
dx = 0;
dy = 0;
}
else
case SW_MINIMIZE:
if( wndPtr->dwStyle & WS_MAXIMIZE)
{
dx = Wnd->rectWindow.left - lpOldWndRect->left;
dy = Wnd->rectWindow.top - lpOldWndRect->top;
OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
wndPtr->flags |= WIN_RESTORE_MAX;
wndPtr->dwStyle &= ~WS_MAXIMIZE;
}
r = *lpOldWndRect;
}
if( !(uFlags & SWP_EX_PAINTSELF) )
{
/* Move remaining regions to parent coordinates */
OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
}
else
OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
TRACE("\tcomputing dirty region!\n");
else
wndPtr->flags &= ~WIN_RESTORE_MAX;
wndPtr->dwStyle |= WS_MINIMIZE;
/* Compute combined dirty region (old + new - valid) */
CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
X11DRV_set_iconic_state( wndPtr );
/* Blt valid bits, r is the rect to copy */
wpl.ptMinPosition = WINPOS_FindIconPos( wndPtr, wpl.ptMinPosition );
if( dx || dy )
{
RECT rClip;
HDC hDC;
SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
swpFlags |= SWP_NOCOPYBITS;
break;
/* get DC and clip rect with drawable rect to avoid superfluous expose events
from copying clipped areas */
case SW_MAXIMIZE:
WINPOS_GetMinMaxInfo( wndPtr, &size, &wpl.ptMaxPosition, NULL, NULL );
if( uFlags & SWP_EX_PAINTSELF )
{
hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
rClip.right = nw; rClip.bottom = nh;
}
else
if( wndPtr->dwStyle & WS_MINIMIZE )
{
hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
wndPtr->dwStyle &= ~WS_MINIMIZE;
WINPOS_ShowIconTitle( wndPtr, FALSE );
X11DRV_set_iconic_state( wndPtr );
}
rClip.left = rClip.top = 0;
wndPtr->dwStyle |= WS_MAXIMIZE;
if( oh > nh ) r.bottom = r.top + nh;
if( ow < nw ) r.right = r.left + nw;
SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
break;
if( IntersectRect( &r, &r, &rClip ) )
case SW_RESTORE:
if( wndPtr->dwStyle & WS_MINIMIZE )
{
X11DRV_WND_SurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
wndPtr->dwStyle &= ~WS_MINIMIZE;
WINPOS_ShowIconTitle( wndPtr, FALSE );
X11DRV_set_iconic_state( wndPtr );
/* When you copy the bits without repainting, parent doesn't
get validated appropriately. Therefore, we have to validate
the parent with the windows' updated region when the
parent's update region is not empty. */
if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
if( wndPtr->flags & WIN_RESTORE_MAX)
{
OffsetRect(&r, dx, dy);
ValidateRect(Wnd->parent->hwndSelf, &r);
/* Restore to maximized position */
WINPOS_GetMinMaxInfo( wndPtr, &size, &wpl.ptMaxPosition, NULL, NULL);
wndPtr->dwStyle |= WS_MAXIMIZE;
SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
break;
}
}
ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
}
}
else
if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
{
swpFlags = (UINT16)(-1);
goto done;
}
else wndPtr->dwStyle &= ~WS_MAXIMIZE;
/* Restore to normal position */
/* *pVisRgn now points to the invalidated region */
*rect = wpl.rcNormalPosition;
rect->right -= rect->left;
rect->bottom -= rect->top;
DeleteObject(newVisRgn);
DeleteObject(dirtyRgn);
return uFlags;
break;
}
} else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
done:
WIN_ReleaseWndPtr( wndPtr );
return swpFlags;
}
/***********************************************************************
* SetWindowPos (X11DRV.@)
* X11DRV_ShowWindow (X11DRV.@)
*/
BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
{
WND *wndPtr,*wndTemp;
RECT newWindowRect, newClientRect;
RECT oldWindowRect, oldClientRect;
HRGN visRgn = 0;
UINT wvrFlags = 0, uFlags = 0;
BOOL retvalue, resync = FALSE, bChangePos;
HWND hwndActive = GetForegroundWindow();
TRACE( "hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
winpos->hwnd, winpos->x, winpos->y,
winpos->x + winpos->cx, winpos->y + winpos->cy, winpos->flags);
WND* wndPtr = WIN_FindWndPtr( hwnd );
BOOL wasVisible, showFlag;
RECT newPos = {0, 0, 0, 0};
UINT swp = 0;
bChangePos = !(winpos->flags & SWP_WINE_NOHOSTMOVE);
winpos->flags &= ~SWP_WINE_NOHOSTMOVE;
/* ------------------------------------------------------------------------ CHECKS */
/* Check window handle */
if (winpos->hwnd == GetDesktopWindow()) return FALSE;
if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
if (!wndPtr) return FALSE;
TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n",
wndPtr->rectWindow.left, wndPtr->rectWindow.top,
wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
/* Fix redundant flags */
wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
if(wndPtr->dwStyle & WS_VISIBLE)
winpos->flags &= ~SWP_SHOWWINDOW;
else
switch(cmd)
{
if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
winpos->flags &= ~SWP_HIDEWINDOW;
case SW_HIDE:
if (!wasVisible) goto END;;
swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER;
break;
case SW_SHOWMINNOACTIVE:
swp |= SWP_NOACTIVATE | SWP_NOZORDER;
/* fall through */
case SW_SHOWMINIMIZED:
swp |= SWP_SHOWWINDOW;
/* fall through */
case SW_MINIMIZE:
swp |= SWP_FRAMECHANGED;
if( !(wndPtr->dwStyle & WS_MINIMIZE) )
swp |= WINPOS_MinMaximize( hwnd, SW_MINIMIZE, &newPos );
else swp |= SWP_NOSIZE | SWP_NOMOVE;
break;
case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
else swp |= SWP_NOSIZE | SWP_NOMOVE;
break;
case SW_SHOWNA:
swp |= SWP_NOACTIVATE | SWP_NOZORDER;
/* fall through */
case SW_SHOW:
swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
/*
* ShowWindow has a little peculiar behavior that if the
* window is already the topmost window, it will not
* activate it.
*/
if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
swp |= SWP_NOACTIVATE;
break;
case SW_SHOWNOACTIVATE:
swp |= SWP_NOZORDER;
if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
/* fall through */
case SW_SHOWNORMAL: /* same as SW_NORMAL: */
case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
case SW_RESTORE:
swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
swp |= WINPOS_MinMaximize( hwnd, SW_RESTORE, &newPos );
else swp |= SWP_NOSIZE | SWP_NOMOVE;
break;
}
if ( winpos->cx < 0 ) winpos->cx = 0;
if ( winpos->cy < 0 ) winpos->cy = 0;
if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == winpos->cx) &&
(wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == winpos->cy))
winpos->flags |= SWP_NOSIZE; /* Already the right size */
if ((wndPtr->rectWindow.left == winpos->x) && (wndPtr->rectWindow.top == winpos->y))
winpos->flags |= SWP_NOMOVE; /* Already the right position */
if (winpos->hwnd == hwndActive)
winpos->flags |= SWP_NOACTIVATE; /* Already active */
else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
showFlag = (cmd != SW_HIDE);
if (showFlag != wasVisible)
{
if(!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
{
winpos->flags &= ~SWP_NOZORDER;
winpos->hwndInsertAfter = HWND_TOP;
goto Pos;
}
SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
if (!IsWindow( hwnd )) goto END;
}
/* Check hwndInsertAfter */
/* FIXME: TOPMOST not supported yet */
if ((winpos->hwndInsertAfter == HWND_TOPMOST) ||
(winpos->hwndInsertAfter == HWND_NOTOPMOST)) winpos->hwndInsertAfter = HWND_TOP;
/* We can't activate a child window */
if ((wndPtr->dwStyle & WS_CHILD) &&
!(wndPtr->dwExStyle & WS_EX_MDICHILD))
swp |= SWP_NOACTIVATE | SWP_NOZORDER;
/* hwndInsertAfter must be a sibling of the window */
if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
newPos.right, newPos.bottom, LOWORD(swp) );
if (cmd == SW_HIDE)
{
WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
if( wnd ) {
if( wnd->parent != wndPtr->parent )
{
retvalue = FALSE;
WIN_ReleaseWndPtr(wnd);
goto END;
}
/* don't need to change the Zorder of hwnd if it's already inserted
* after hwndInsertAfter or when inserting hwnd after itself.
*/
if(( wnd->next == wndPtr ) || (winpos->hwnd == winpos->hwndInsertAfter))
winpos->flags |= SWP_NOZORDER;
}
WIN_ReleaseWndPtr(wnd);
}
Pos: /* ------------------------------------------------------------------------ MAIN part */
/* FIXME: This will cause the window to be activated irrespective
* of whether it is owned by the same thread. Has to be done
* asynchronously.
*/
SWP_DoWinPosChanging( wndPtr, winpos, &newWindowRect, &newClientRect );
if (hwnd == GetActiveWindow())
WINPOS_ActivateOtherWindow(wndPtr);
if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
{
if( wndPtr->parent == WIN_GetDesktop() )
winpos->hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
winpos->hwndInsertAfter, winpos->flags );
WIN_ReleaseDesktop();
/* Revert focus to parent */
if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
SetFocus( GetParent(hwnd) );
}
if (!IsWindow( hwnd )) goto END;
else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
if(!(wndPtr->flags & WIN_NATIVE) )
if (wndPtr->flags & WIN_NEED_SIZE)
{
if( winpos->hwndInsertAfter == HWND_TOP )
winpos->flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
else
if( winpos->hwndInsertAfter == HWND_BOTTOM )
winpos->flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
else
if( !(winpos->flags & SWP_NOZORDER) )
if( GetWindow(winpos->hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
winpos->flags |= SWP_NOZORDER;
if( !(winpos->flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
((winpos->flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
!= (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
{
/* get a previous visible region for SWP_CopyValidBits() */
DWORD dflags = DCX_WINDOW;
if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
dflags |= DCX_CLIPSIBLINGS;
visRgn = DCE_GetVisRgn(winpos->hwnd, dflags, 0, 0);
}
/* should happen only in CreateWindowEx() */
int wParam = SIZE_RESTORED;
wndPtr->flags &= ~WIN_NEED_SIZE;
if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
SendMessageA( hwnd, WM_SIZE, wParam,
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
SendMessageA( hwnd, WM_MOVE, 0,
MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
}
/* Common operations */
END:
WIN_ReleaseWndPtr(wndPtr);
return wasVisible;
}
wvrFlags = SWP_DoNCCalcSize( wndPtr, winpos, &newWindowRect, &newClientRect, winpos->flags );
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
{
if ( WIN_UnlinkWindow( winpos->hwnd ) )
WIN_LinkWindow( winpos->hwnd, winpos->hwndInsertAfter );
}
/**********************************************************************
* X11DRV_MapNotify
*/
void X11DRV_MapNotify( HWND hwnd, XMapEvent *event )
{
HWND hwndFocus = GetFocus();
WND *win;
/* Reset active DCEs */
if (!(win = WIN_FindWndPtr( hwnd ))) return;
if( (((winpos->flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
wndPtr->dwStyle & WS_VISIBLE) ||
(winpos->flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
if ((win->dwStyle & WS_VISIBLE) &&
(win->dwStyle & WS_MINIMIZE) &&
(win->dwExStyle & WS_EX_MANAGED))
{
int x, y;
unsigned int width, height, border, depth;
Window root, top;
RECT rect;
UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
DCE_InvalidateDCE(wndPtr, &rect);
}
oldWindowRect = wndPtr->rectWindow;
oldClientRect = wndPtr->rectClient;
DCE_InvalidateDCE( win, &win->rectWindow );
win->dwStyle &= ~WS_MINIMIZE;
win->dwStyle |= WS_VISIBLE;
WIN_InternalShowOwnedPopups( hwnd, TRUE, TRUE );
/* Find out if we have to redraw the whole client rect */
if (win->flags & WIN_RESTORE_MAX)
win->dwStyle |= WS_MAXIMIZE;
else
win->dwStyle &= ~WS_MAXIMIZE;
if( oldClientRect.bottom - oldClientRect.top ==
newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
/* FIXME: hack */
wine_tsx11_lock();
XGetGeometry( event->display, get_whole_window(win), &root, &x, &y, &width, &height,
&border, &depth );
XTranslateCoordinates( event->display, get_whole_window(win), root, 0, 0, &x, &y, &top );
wine_tsx11_unlock();
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
X11DRV_X_to_window_rect( win, &rect );
SendMessageA( hwnd, WM_SHOWWINDOW, SW_RESTORE, 0 );
SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
SWP_NOZORDER | SWP_WINE_NOHOSTMOVE );
}
if (hwndFocus && IsChild( hwnd, hwndFocus )) X11DRV_SetFocus(hwndFocus); /* FIXME */
WIN_ReleaseWndPtr( win );
}
if( oldClientRect.right - oldClientRect.left ==
newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
if( (winpos->flags & SWP_NOCOPYBITS) ||
(!(winpos->flags & SWP_NOCLIENTSIZE) &&
(wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
{
uFlags |= SWP_EX_NOCOPY;
}
/*
* Use this later in CopyValidBits()
*
else if( 0 )
uFlags |= SWP_EX_NONCLIENT;
/**********************************************************************
* X11DRV_UnmapNotify
*/
void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event )
{
WND *win;
/* FIXME: actually do something with WVR_VALIDRECTS */
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
if (!(win = WIN_FindWndPtr( hwnd ))) return;
if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
if ((win->dwStyle & WS_VISIBLE) && (win->dwExStyle & WS_EX_MANAGED))
{
BOOL bCallDriver = TRUE;
HWND tempInsertAfter = winpos->hwndInsertAfter;
EndMenu();
SendMessageA( hwnd, WM_SHOWWINDOW, SW_MINIMIZE, 0 );
winpos->hwndInsertAfter = winpos->hwndInsertAfter;
win->flags &= ~WIN_RESTORE_MAX;
win->dwStyle |= WS_MINIMIZE;
if( !(winpos->flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
if (win->dwStyle & WS_MAXIMIZE)
{
/* This is the only place where we need to force repainting of the contents
of windows created by the host window system, all other cases go through the
expose event handling */
win->flags |= WIN_RESTORE_MAX;
win->dwStyle &= ~WS_MAXIMIZE;
}
if( (winpos->flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
{
winpos->cx = newWindowRect.right - newWindowRect.left;
winpos->cy = newWindowRect.bottom - newWindowRect.top;
SetWindowPos( hwnd, 0, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_WINE_NOHOSTMOVE );
X11DRV_WND_SetWindowPos(wndPtr, winpos, bChangePos);
winpos->hwndInsertAfter = tempInsertAfter;
bCallDriver = FALSE;
WIN_InternalShowOwnedPopups( hwnd, FALSE, TRUE );
}
WIN_ReleaseWndPtr( win );
}
if( winpos->flags & SWP_NOCLIENTMOVE )
SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos->flags, uFlags );
else
{
/* client area moved but window extents remained the same, copy valid bits */
visRgn = CreateRectRgn( 0, 0, winpos->cx, winpos->cy );
uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
uFlags | SWP_EX_PAINTSELF );
}
}
}
/***********************************************************************
* query_zorder
*
* Synchronize internal z-order with the window manager's.
*/
static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
{
/* return TRUE if we have at least two managed windows */
for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
if( ((*pWndA)->dwExStyle & WS_EX_MANAGED) &&
((*pWndA)->dwStyle & WS_VISIBLE )) break;
if( *pWndA )
for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
if( ((*pWndB)->dwExStyle & WS_EX_MANAGED) &&
((*pWndB)->dwStyle & WS_VISIBLE )) break;
return ((*pWndB) != NULL);
}
if( bCallDriver )
{
if( !(winpos->flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
{
if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
(oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
!(uFlags & SWP_EX_NOCOPY) )
{
/* The origin of the client rect didn't move so we can try to repaint
* only the nonclient area by setting bit gravity hint for the host window system.
*/
static Window __get_common_ancestor( Display *display, Window A, Window B,
Window** children, unsigned* total )
{
/* find the real root window */
if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
{
HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
newWindowRect.bottom - newWindowRect.top);
RECT rcn = newClientRect;
RECT rco = oldClientRect;
OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
IntersectRect( &rcn, &rcn, &rco );
visRgn = CreateRectRgnIndirect( &rcn );
CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
DeleteObject( hrgn );
uFlags = SWP_EX_PAINTSELF;
}
X11DRV_WND_SetGravity(wndPtr, NorthWestGravity );
}
}
Window root, *childrenB;
unsigned totalB;
X11DRV_WND_SetWindowPos(wndPtr, winpos, bChangePos);
X11DRV_WND_SetGravity(wndPtr, ForgetGravity );
winpos->hwndInsertAfter = tempInsertAfter;
}
while( A != B && A && B )
{
TSXQueryTree( display, A, &root, &A, children, total );
TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
if( childrenB ) TSXFree( childrenB );
if( *children ) TSXFree( *children ), *children = NULL;
}
if( winpos->flags & SWP_SHOWWINDOW )
{
HWND focus, curr;
if( A && B )
{
TSXQueryTree( display, A, &root, &B, children, total );
return A;
}
return 0 ;
}
wndPtr->dwStyle |= WS_VISIBLE;
static Window __get_top_decoration( Display *display, Window w, Window ancestor )
{
Window* children, root, prev = w, parent = w;
unsigned total;
if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
do
{
w = parent;
TSXQueryTree( display, w, &root, &parent, &children, &total );
if( children ) TSXFree( children );
} while( parent && parent != ancestor );
TRACE("\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
return ( parent ) ? w : 0 ;
}
/* focus was set to unmapped window, reset host focus
* since the window is now visible */
static unsigned __td_lookup( Window w, Window* list, unsigned max )
{
unsigned i;
for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
return i;
}
focus = curr = GetFocus();
while (curr)
{
if (curr == winpos->hwnd)
{
X11DRV_SetFocus(focus);
break;
}
curr = GetParent(curr);
}
}
static HWND query_zorder( Display *display, HWND hWndCheck)
{
HWND hwndInsertAfter = HWND_TOP;
WND *pWndCheck = WIN_FindWndPtr(hWndCheck);
WND *pDesktop = WIN_GetDesktop();
WND *pWnd, *pWndZ = WIN_LockWndPtr(pDesktop->child);
Window w, parent, *children = NULL;
unsigned total, check, pos, best;
if( !__check_query_condition(&pWndZ, &pWnd) )
{
WIN_ReleaseWndPtr(pWndCheck);
WIN_ReleaseWndPtr(pDesktop->child);
WIN_ReleaseDesktop();
return hwndInsertAfter;
}
else /* -------------------------------------------- emulated window */
WIN_LockWndPtr(pWndZ);
WIN_LockWndPtr(pWnd);
WIN_ReleaseWndPtr(pDesktop->child);
WIN_ReleaseDesktop();
parent = __get_common_ancestor( display, get_whole_window(pWndZ),
get_whole_window(pWnd), &children, &total );
if( parent && children )
{
if( winpos->flags & SWP_SHOWWINDOW )
{
wndPtr->dwStyle |= WS_VISIBLE;
uFlags |= SWP_EX_PAINTSELF;
visRgn = 1; /* redraw the whole window */
}
else if( !(winpos->flags & SWP_NOREDRAW) )
/* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
w = __get_top_decoration( display, get_whole_window(pWndCheck), parent );
if( w != children[total-1] ) /* check if at the top */
{
if( winpos->flags & SWP_HIDEWINDOW )
{
if( visRgn > 1 ) /* map to parent */
OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
else
visRgn = 0;
}
else
/* X child at index 0 is at the bottom, at index total-1 is at the top */
check = __td_lookup( w, children, total );
best = total;
for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
{
if( (winpos->flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
&oldClientRect, uFlags);
else
{
/* nothing moved, redraw frame if needed */
/* go through all windows in Wine z-order... */
if( winpos->flags & SWP_FRAMECHANGED )
SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos->flags, uFlags );
if( visRgn )
if( pWnd != pWndCheck )
{
if( !(pWnd->dwExStyle & WS_EX_MANAGED) ||
!(w = __get_top_decoration( display, get_whole_window(pWnd), parent )) )
continue;
pos = __td_lookup( w, children, total );
if( pos < best && pos > check )
{
DeleteObject( visRgn );
visRgn = 0;
/* find a nearest Wine window precedes
* pWndCheck in the real z-order... */
best = pos;
hwndInsertAfter = pWnd->hwndSelf;
}
if( best - check == 1 ) break;
}
}
}
}
if( children ) TSXFree( children );
WIN_ReleaseWndPtr(pWnd);
WIN_ReleaseWndPtr(pWndZ);
WIN_ReleaseWndPtr(pWndCheck);
return hwndInsertAfter;
}
if( winpos->flags & SWP_HIDEWINDOW )
{
wndPtr->dwStyle &= ~WS_VISIBLE;
}
if (winpos->hwnd == CARET_GetHwnd())
{
if( winpos->flags & SWP_HIDEWINDOW )
HideCaret(winpos->hwnd);
else if (winpos->flags & SWP_SHOWWINDOW)
ShowCaret(winpos->hwnd);
}
/* ------------------------------------------------------------------------ FINAL */
if (wndPtr->flags & WIN_NATIVE)
X11DRV_Synchronize(); /* Synchronize with the host window system */
/***********************************************************************
* X11DRV_ConfigureNotify
*/
void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
{
HWND oldInsertAfter;
struct x11drv_win_data *data;
WND *win;
RECT rect;
WINDOWPOS winpos;
int x = event->x, y = event->y;
wndTemp = WIN_GetDesktop();
if (!(win = WIN_FindWndPtr( hwnd ))) return;
data = win->pDriverData;
/* repaint invalidated region (if any)
*
* FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
* and force update after ChangeActiveWindow() to avoid painting frames twice.
*/
/* Get geometry */
if( visRgn )
if (!event->send_event) /* normal event, need to map coordinates to the root */
{
if( !(winpos->flags & SWP_NOREDRAW) )
Window child;
wine_tsx11_lock();
XTranslateCoordinates( event->display, data->whole_window, root_window,
0, 0, &x, &y, &child );
wine_tsx11_unlock();
}
rect.left = x;
rect.top = y;
rect.right = x + event->width;
rect.bottom = y + event->height;
TRACE( "win %x new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
event->x, event->y, event->width, event->height );
X11DRV_X_to_window_rect( win, &rect );
WIN_ReleaseWndPtr( win );
winpos.hwnd = hwnd;
winpos.x = rect.left;
winpos.y = rect.top;
winpos.cx = rect.right - rect.left;
winpos.cy = rect.bottom - rect.top;
winpos.flags = SWP_NOACTIVATE;
/* Get Z-order (FIXME) */
winpos.hwndInsertAfter = query_zorder( event->display, hwnd );
/* needs to find the first Visible Window above the current one */
oldInsertAfter = hwnd;
for (;;)
{
oldInsertAfter = GetWindow( oldInsertAfter, GW_HWNDPREV );
if (!oldInsertAfter)
{
/* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
its parent and sibling and so on, and then erase the parent window
background if the parent is either a top-level window or its parent's parent
is top-level window. Rely on the system to repaint other affected
windows later on. */
if( uFlags & SWP_EX_PAINTSELF )
{
PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
}
else
{
PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
RDW_EX_USEHRGN );
}
if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
{
RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
RDW_ERASENOW | RDW_NOCHILDREN );
}
oldInsertAfter = HWND_TOP;
break;
}
if( visRgn != 1 )
DeleteObject( visRgn );
if (GetWindowLongA( oldInsertAfter, GWL_STYLE ) & WS_VISIBLE) break;
}
WIN_ReleaseDesktop();
/* Compare what has changed */
if (!(winpos->flags & SWP_NOACTIVATE))
WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
GetWindowRect( hwnd, &rect );
if (rect.left == winpos.x && rect.top == winpos.y) winpos.flags |= SWP_NOMOVE;
else
TRACE( "%04x moving from (%d,%d) to (%d,%d)\n",
hwnd, rect.left, rect.top, winpos.x, winpos.y );
/* And last, send the WM_WINDOWPOSCHANGED message */
if (rect.right - rect.left == winpos.cx &&
rect.bottom - rect.top == winpos.cy) winpos.flags |= SWP_NOSIZE;
else
TRACE( "%04x resizing from (%dx%d) to (%dx%d)\n",
hwnd, rect.right - rect.left, rect.bottom - rect.top,
winpos.cx, winpos.cy );
TRACE("\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
if (winpos.hwndInsertAfter == oldInsertAfter) winpos.flags |= SWP_NOZORDER;
else
TRACE( "%04x restacking from after %04x to after %04x\n",
hwnd, oldInsertAfter, winpos.hwndInsertAfter );
if ( resync ||
(((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
!(winpos->flags & SWP_NOSENDCHANGING)) )
{
SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
if (resync) X11DRV_Synchronize();
}
/* if nothing changed, don't do anything */
if (winpos.flags == (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) return;
retvalue = TRUE;
END:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
SetWindowPos( hwnd, winpos.hwndInsertAfter, winpos.x, winpos.y,
winpos.cx, winpos.cy, winpos.flags | SWP_WINE_NOHOSTMOVE );
}
......@@ -1281,17 +1206,19 @@ BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
#ifdef HAVE_LIBXSHAPE
{
Display *display = thread_display();
Window win = X11DRV_WND_GetXWindow(wndPtr);
X11DRV_WND_DATA *data = wndPtr->pDriverData;
if (win)
if (data->whole_window)
{
if (!hrgn)
{
TSXShapeCombineMask( display, win, ShapeBounding, 0, 0, None, ShapeSet );
TSXShapeCombineMask( display, data->whole_window,
ShapeBounding, 0, 0, None, ShapeSet );
}
else
{
XRectangle *aXRect;
int x_offset, y_offset;
DWORD size;
DWORD dwBufferSize = GetRegionData(hrgn, 0, NULL);
PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
......@@ -1299,6 +1226,8 @@ BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
GetRegionData(hrgn, dwBufferSize, pRegionData);
size = pRegionData->rdh.nCount;
x_offset = wndPtr->rectWindow.left - data->whole_rect.left;
y_offset = wndPtr->rectWindow.top - data->whole_rect.top;
/* convert region's "Windows rectangles" to XRectangles */
aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
if (aXRect)
......@@ -1307,8 +1236,8 @@ BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
RECT *pRect = (RECT*) pRegionData->Buffer;
for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
{
pCurrRect->x = pRect->left;
pCurrRect->y = pRect->top;
pCurrRect->x = pRect->left + x_offset;
pCurrRect->y = pRect->top + y_offset;
pCurrRect->height = pRect->bottom - pRect->top;
pCurrRect->width = pRect->right - pRect->left;
......@@ -1322,7 +1251,7 @@ BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
}
/* shape = non-rectangular windows (X11/extensions) */
TSXShapeCombineRectangles( display, win, ShapeBounding,
TSXShapeCombineRectangles( display, data->whole_window, ShapeBounding,
0, 0, aXRect,
pCurrRect - aXRect, ShapeSet, YXBanded );
HeapFree(GetProcessHeap(), 0, aXRect );
......@@ -1543,17 +1472,9 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
{
MapWindowPoints( wndPtr->parent->hwndSelf, 0, (LPPOINT)&mouseRect, 2 );
}
SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
if (GetCapture() != hwnd) SetCapture( hwnd );
if (wndPtr->parent && (wndPtr->parent->hwndSelf != GetDesktopWindow()))
{
/* Retrieve a default cache DC (without using the window style) */
hdc = GetDCEx( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
}
else
hdc = GetDC( 0 );
/* Retrieve a default cache DC (without using the window style) */
hdc = GetDCEx( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
if( iconic ) /* create a cursor for dragging */
{
......@@ -1566,19 +1487,28 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
/* repaint the window before moving it around */
RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
SetCapture( hwnd );
/* grab the server only when moving top-level windows without desktop */
grab = (!DragFullWindows && (root_window == DefaultRootWindow(gdi_display)) &&
(wndPtr->parent->hwndSelf == GetDesktopWindow()));
wine_tsx11_lock();
if (grab)
{
wine_tsx11_lock();
XSync( gdi_display, False );
XGrabServer( display );
XSync( display, False );
/* switch gdi display to the thread display, since the server is grabbed */
old_gdi_display = gdi_display;
gdi_display = display;
wine_tsx11_unlock();
}
XGrabPointer( display, get_whole_window(wndPtr), False,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, get_client_window(wndPtr->parent),
None, CurrentTime );
wine_tsx11_unlock();
while(1)
{
......@@ -1681,19 +1611,18 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
else if (moved && !DragFullWindows)
draw_moving_frame( hdc, &sizingRect, thickframe );
if (wndPtr->parent && (wndPtr->parent->hwndSelf != GetDesktopWindow()))
ReleaseDC( wndPtr->parent->hwndSelf, hdc );
else
ReleaseDC( 0, hdc );
ReleaseDC( wndPtr->parent->hwndSelf, hdc );
wine_tsx11_lock();
XUngrabPointer( display, CurrentTime );
if (grab)
{
wine_tsx11_lock();
XSync( display, False );
XUngrabServer( display );
XSync( display, False );
gdi_display = old_gdi_display;
wine_tsx11_unlock();
}
wine_tsx11_unlock();
if (HOOK_CallHooksA( WH_CBT, HCBT_MOVESIZE, hwnd, (LPARAM)&sizingRect ))
sizingRect = wndPtr->rectWindow;
......
......@@ -18,7 +18,6 @@
#include "wingdi.h"
#include "ddrawi.h"
#include "bitmap.h"
#include "win.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(x11drv);
......@@ -50,19 +49,12 @@ static void GrabPointer(HWND hWnd)
{
Display *display = thread_display();
if (hWnd) {
WND *tmpWnd;
Window win;
/* find the X11 window that ddraw uses */
tmpWnd = WIN_FindWndPtr(hWnd);
win = X11DRV_WND_GetXWindow(tmpWnd);
TRACE("WND: %p win: %ld\n", tmpWnd, win);
WIN_ReleaseWndPtr(tmpWnd);
Window win = X11DRV_get_whole_window(hWnd);
TRACE("WND: %x win: %ld\n", hWnd, win);
if (!win) {
TRACE("host off desktop\n");
tmpWnd = WIN_FindWndPtr(GetDesktopWindow());
win = X11DRV_WND_GetXWindow(tmpWnd);
TRACE("Owner WND: %p win: %ld\n", tmpWnd, win);
WIN_ReleaseWndPtr(tmpWnd);
win = root_window;
}
TSXGrabPointer(display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
}
......
......@@ -27,11 +27,12 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
@ cdecl GetScreenSaveTimeout() X11DRV_GetScreenSaveTimeout
@ cdecl SetScreenSaveTimeout(long) X11DRV_SetScreenSaveTimeout
@ cdecl LoadOEMResource(long long) X11DRV_LoadOEMResource
@ cdecl CreateWindow(long) X11DRV_CreateWindow
@ cdecl CreateWindow(long ptr) X11DRV_CreateWindow
@ cdecl DestroyWindow(long) X11DRV_DestroyWindow
@ cdecl GetDC(long long long long) X11DRV_GetDC
@ cdecl EnableWindow(long long) X11DRV_EnableWindow
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
@ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC
@ cdecl ScrollWindowEx(long long long ptr ptr long ptr long) X11DRV_ScrollWindowEx
@ cdecl SetFocus(long) X11DRV_SetFocus
@ cdecl SetParent(long long) X11DRV_SetParent
......@@ -39,6 +40,7 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
@ cdecl SetWindowRgn(long long long) X11DRV_SetWindowRgn
@ cdecl SetWindowIcon(long long long) X11DRV_SetWindowIcon
@ cdecl SetWindowText(long wstr) X11DRV_SetWindowText
@ cdecl ShowWindow(long long) X11DRV_ShowWindow
@ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove
@ cdecl AcquireClipboard() X11DRV_AcquireClipboard
@ cdecl ReleaseClipboard() X11DRV_ReleaseClipboard
......
......@@ -1306,28 +1306,22 @@ static BOOL BITBLT_InternalStretchBlt( DC *dcDst, INT xDst, INT yDst,
case SRCCOPY: /* 0xcc */
if (dcSrc->bitsPerPixel == dcDst->bitsPerPixel)
{
BOOL expose = !(dcSrc->flags & DC_MEMORY) && !(dcDst->flags & DC_MEMORY);
if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, True );
XSetFunction( gdi_display, physDevDst->gc, GXcopy );
XCopyArea( gdi_display, physDevSrc->drawable,
physDevDst->drawable, physDevDst->gc,
visRectSrc.left, visRectSrc.top,
width, height, visRectDst.left, visRectDst.top );
if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, False );
return TRUE;
}
if (dcSrc->bitsPerPixel == 1)
{
BOOL expose = !(dcSrc->flags & DC_MEMORY) && !(dcDst->flags & DC_MEMORY);
XSetBackground( gdi_display, physDevDst->gc, physDevDst->textPixel );
XSetForeground( gdi_display, physDevDst->gc, physDevDst->backgroundPixel );
XSetFunction( gdi_display, physDevDst->gc, GXcopy );
if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, True );
XCopyPlane( gdi_display, physDevSrc->drawable,
physDevDst->drawable, physDevDst->gc,
visRectSrc.left, visRectSrc.top,
width, height, visRectDst.left, visRectDst.top, 1 );
if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, False );
return TRUE;
}
break;
......@@ -1355,6 +1349,7 @@ static BOOL BITBLT_InternalStretchBlt( DC *dcDst, INT xDst, INT yDst,
}
tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
XSetGraphicsExposures( gdi_display, tmpGC, False );
pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height,
dcDst->bitsPerPixel );
......
......@@ -41,6 +41,7 @@ BOOL X11DRV_BITMAP_Init(void)
{
BITMAP_monoGC = XCreateGC( gdi_display, tmpPixmap, 0, NULL );
XSetGraphicsExposures( gdi_display, BITMAP_monoGC, False );
XSetSubwindowMode( gdi_display, BITMAP_monoGC, IncludeInferiors );
XFreePixmap( gdi_display, tmpPixmap );
}
......@@ -50,6 +51,7 @@ BOOL X11DRV_BITMAP_Init(void)
{
BITMAP_colorGC = XCreateGC( gdi_display, tmpPixmap, 0, NULL );
XSetGraphicsExposures( gdi_display, BITMAP_colorGC, False );
XSetSubwindowMode( gdi_display, BITMAP_colorGC, IncludeInferiors );
XFreePixmap( gdi_display, tmpPixmap );
}
}
......@@ -101,6 +103,8 @@ HBITMAP X11DRV_BITMAP_SelectObject( DC * dc, HBITMAP hbitmap,
XFreeGC( gdi_display, physDev->gc );
physDev->gc = XCreateGC( gdi_display, physDev->drawable, 0, NULL );
XSetGraphicsExposures( gdi_display, physDev->gc, False );
XSetSubwindowMode( gdi_display, physDev->gc, IncludeInferiors );
XFlush( gdi_display );
wine_tsx11_unlock();
dc->bitsPerPixel = bmp->bitmap.bmBitsPixel;
DC_InitDC( dc );
......
......@@ -72,3 +72,102 @@ void X11DRV_SetDeviceClipping( DC * dc )
GDI_ReleaseObj( dc->hGCClipRgn );
}
/***********************************************************************
* X11DRV_SetDrawable
*
* Set the drawable, clipping mode and origin for a DC.
*/
void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, int org_x, int org_y )
{
DC *dc = DC_GetDCPtr( hdc );
if (dc)
{
X11DRV_PDEVICE *physDev = dc->physDev;
/*
* This function change the coordinate system (DCOrgX,DCOrgY)
* values. When it moves the origin, other data like the current clipping
* region will not be moved to that new origin. In the case of DCs that are class
* or window DCs that clipping region might be a valid value from a previous use
* of the DC and changing the origin of the DC without moving the clip region
* results in a clip region that is not placed properly in the DC.
* This code will save the dc origin, let the SetDrawable
* modify the origin and reset the clipping. When the clipping is set,
* it is moved according to the new DC origin.
*/
if (dc->hClipRgn) OffsetRgn( dc->hClipRgn, org_x - dc->DCOrgX, org_y - dc->DCOrgY );
dc->DCOrgX = org_x;
dc->DCOrgY = org_y;
physDev->drawable = drawable;
TSXSetSubwindowMode( gdi_display, physDev->gc, mode );
GDI_ReleaseObj( hdc );
}
}
/***********************************************************************
* X11DRV_StartGraphicsExposures
*
* Set the DC in graphics exposures mode
*/
void X11DRV_StartGraphicsExposures( HDC hdc )
{
DC *dc = DC_GetDCPtr( hdc );
if (dc)
{
X11DRV_PDEVICE *physDev = dc->physDev;
TSXSetGraphicsExposures( gdi_display, physDev->gc, True );
GDI_ReleaseObj( hdc );
}
}
/***********************************************************************
* X11DRV_EndGraphicsExposures
*
* End the graphics exposures mode and process the events
*/
void X11DRV_EndGraphicsExposures( HDC hdc, HRGN hrgn )
{
HRGN tmp = 0;
DC *dc = DC_GetDCPtr( hdc );
if (dc)
{
XEvent event;
X11DRV_PDEVICE *physDev = dc->physDev;
SetRectRgn( hrgn, 0, 0, 0, 0 );
wine_tsx11_lock();
XSetGraphicsExposures( gdi_display, physDev->gc, False );
XSync( gdi_display, False );
for (;;)
{
XWindowEvent( gdi_display, physDev->drawable, ~0, &event );
if (event.type == NoExpose) break;
if (event.type == GraphicsExpose)
{
TRACE( "got %d,%d %dx%d count %d\n",
event.xgraphicsexpose.x, event.xgraphicsexpose.y,
event.xgraphicsexpose.width, event.xgraphicsexpose.height,
event.xgraphicsexpose.count );
if (!tmp) tmp = CreateRectRgn( 0, 0, 0, 0 );
SetRectRgn( tmp, event.xgraphicsexpose.x, event.xgraphicsexpose.y,
event.xgraphicsexpose.x + event.xgraphicsexpose.width,
event.xgraphicsexpose.y + event.xgraphicsexpose.height );
CombineRgn( hrgn, hrgn, tmp, RGN_OR );
if (!event.xgraphicsexpose.count) break;
}
else
{
ERR( "got unexpected event %d\n", event.type );
break;
}
if (tmp) DeleteObject( tmp );
}
wine_tsx11_unlock();
GDI_ReleaseObj( hdc );
}
}
......@@ -69,11 +69,12 @@ typedef struct tagUSER_DRIVER {
void (*pResetSelectionOwner)(struct tagWND *, BOOL);
/* windowing functions */
BOOL (*pCreateWindow)(HWND);
BOOL (*pCreateWindow)(HWND,CREATESTRUCTA*);
BOOL (*pDestroyWindow)(HWND);
BOOL (*pGetDC)(HWND,HDC,HRGN,DWORD);
BOOL (*pEnableWindow)(HWND,BOOL);
DWORD (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD);
BOOL (*pScrollDC)(HDC,INT,INT,const RECT*,const RECT*,HRGN,LPRECT);
INT (*pScrollWindowEx)(HWND,INT,INT,const RECT*,const RECT*,HRGN,LPRECT,UINT);
void (*pSetFocus)(HWND);
HWND (*pSetParent)(HWND,HWND);
......@@ -81,6 +82,7 @@ typedef struct tagUSER_DRIVER {
BOOL (*pSetWindowRgn)(HWND,HRGN,BOOL);
HICON (*pSetWindowIcon)(HWND,HICON,BOOL);
BOOL (*pSetWindowText)(HWND,LPCWSTR);
BOOL (*pShowWindow)(HWND,INT);
void (*pSysCommandSizeMove)(HWND,WPARAM);
} USER_DRIVER;
......
......@@ -16,13 +16,6 @@
#define WND_MAGIC 0x444e4957 /* 'WIND' */
/* PAINT_RedrawWindow() control flags */
#define RDW_EX_USEHRGN 0x0001
#define RDW_EX_DELETEHRGN 0x0002
#define RDW_EX_XYWINDOW 0x0004
#define RDW_EX_TOPFRAME 0x0010
#define RDW_EX_DELAY_NCPAINT 0x0020
struct tagCLASS;
struct tagDCE;
struct tagMESSAGEQUEUE;
......@@ -65,13 +58,9 @@ typedef struct tagWND
DWORD wExtra[1]; /* Window extra bytes */
} WND;
/* Host attributes */
#define HAK_ICONICSTATE 3
typedef struct tagWND_DRIVER
{
void (*pForceWindowRaise)(WND *);
BOOL (*pSetHostAttr)(WND *, INT haKey, INT value);
} WND_DRIVER;
extern WND_DRIVER *WND_Driver;
......@@ -104,14 +93,6 @@ typedef struct
#define BWA_SKIPOWNED 0x0004
#define BWA_SKIPICONIC 0x0008
/* WIN_UpdateNCRgn() flags */
#define UNC_CHECK 0x0001
#define UNC_ENTIRE 0x0002
#define UNC_REGION 0x0004
#define UNC_UPDATE 0x0008
#define UNC_DELAY_NCPAINT 0x0010
#define UNC_IN_BEGINPAINT 0x0020
/* Window functions */
extern void WIN_LockWnds( void );
extern void WIN_UnlockWnds( void );
......@@ -137,8 +118,6 @@ extern WND** WIN_BuildWinArray( WND *wndPtr, UINT bwa, UINT* pnum );
extern void WIN_ReleaseWinArray(WND **wndArray);
extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
extern HICON16 NC_IconForWindow( WND *wndPtr );
extern HWND CARET_GetHwnd(void);
extern void CARET_GetRect(LPRECT lprc); /* windows/caret.c */
......@@ -149,11 +128,6 @@ extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ); /* windows/defwnd.c
extern void PROPERTY_RemoveWindowProps( WND *pWnd ); /* windows/property.c */
extern BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
HRGN hrgnUpdate, UINT flags,
UINT control ); /* windows/painting.c */
extern HRGN WIN_UpdateNCRgn(WND* wnd, HRGN hRgn, UINT flags); /* windows/painting.c */
/* Classes functions */
struct tagCLASS; /* opaque structure */
struct builtin_class_descr;
......@@ -167,8 +141,4 @@ extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
/* windows/focus.c */
extern void FOCUS_SwitchFocus( struct tagMESSAGEQUEUE *pMsgQ, HWND , HWND );
/* generic method that returns TRUE if the window properties ask for a
window manager type of border */
extern BOOL WIN_WindowNeedsWMBorder( DWORD style, DWORD exStyle );
#endif /* __WINE_WIN_H */
......@@ -28,7 +28,6 @@ extern BOOL WINPOS_ShowIconTitle( struct tagWND* pWnd, BOOL bShow );
extern void WINPOS_GetMinMaxInfo( struct tagWND* pWnd, POINT *maxSize,
POINT *maxPos, POINT *minTrack,
POINT *maxTrack );
extern UINT WINPOS_MinMaximize( struct tagWND* pWnd, UINT16 cmd, LPRECT16 lpPos);
extern BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse,
BOOL fChangeFocus );
extern BOOL WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg );
......
......@@ -19,6 +19,7 @@
#include "winbase.h"
#include "gdi.h"
#include "user.h"
#include "win.h"
#include "thread.h"
#define MAX_PIXELFORMATS 8
......@@ -181,8 +182,11 @@ extern HBITMAP X11DRV_BITMAP_CreateBitmapFromPixmap(Pixmap pixmap, BOOL bDeleteP
extern Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc );
extern Pixmap X11DRV_BITMAP_CreatePixmapFromBitmap( HBITMAP hBmp, HDC hdc );
extern BOOL X11DRV_SetupGCForPatBlt( struct tagDC *dc, GC gc,
BOOL fMapColors );
extern void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, int org_x, int org_y );
extern void X11DRV_StartGraphicsExposures( HDC hdc );
extern void X11DRV_EndGraphicsExposures( HDC hdc, HRGN hrgn );
extern BOOL X11DRV_SetupGCForPatBlt( struct tagDC *dc, GC gc, BOOL fMapColors );
extern BOOL X11DRV_SetupGCForBrush( struct tagDC *dc );
extern BOOL X11DRV_SetupGCForPen( struct tagDC *dc );
extern BOOL X11DRV_SetupGCForText( struct tagDC *dc );
......@@ -307,7 +311,7 @@ struct x11drv_thread_data
{
Display *display;
HANDLE display_fd;
int process_event_count;
int process_event_count; /* recursion count for event processing */
};
extern struct x11drv_thread_data *x11drv_init_thread_data(void);
......@@ -327,6 +331,15 @@ extern unsigned int screen_width;
extern unsigned int screen_height;
extern unsigned int screen_depth;
extern Atom wmProtocols;
extern Atom wmDeleteWindow;
extern Atom wmTakeFocus;
extern Atom dndProtocol;
extern Atom dndSelection;
extern Atom wmChangeState;
extern Atom kwmDockWindow;
extern Atom _kde_net_wm_system_tray_window_for;
static inline Visual *X11DRV_GetVisual(void) { return visual; }
static inline Window X11DRV_GetXRootWindow(void) { return root_window; }
......@@ -345,8 +358,6 @@ extern BOOL X11DRV_GetClipboardData(UINT wFormat);
extern WORD X11DRV_EVENT_XStateToKeyState( int state ) ;
extern void X11DRV_Synchronize( void );
typedef enum {
X11DRV_INPUT_RELATIVE,
X11DRV_INPUT_ABSOLUTE
......@@ -381,28 +392,50 @@ extern void X11DRV_SendEvent( DWORD mouseStatus, DWORD posX, DWORD posY,
extern struct tagWND_DRIVER X11DRV_WND_Driver;
typedef struct _X11DRV_WND_DATA {
Window window;
HBITMAP hWMIconBitmap;
HBITMAP hWMIconMask;
int bit_gravity;
} X11DRV_WND_DATA;
/* x11drv private window data */
struct x11drv_win_data
{
Window whole_window; /* X window for the complete window */
Window client_window; /* X window for the client area */
Window icon_window; /* X window for the icon */
RECT whole_rect; /* X window rectangle for the whole window relative to parent */
RECT client_rect; /* client area relative to whole window */
HBITMAP hWMIconBitmap;
HBITMAP hWMIconMask;
};
typedef struct x11drv_win_data X11DRV_WND_DATA;
extern Window X11DRV_WND_GetXWindow(struct tagWND *wndPtr);
extern Window X11DRV_WND_FindXWindow(struct tagWND *wndPtr);
extern Window X11DRV_get_client_window( HWND hwnd );
extern Window X11DRV_get_whole_window( HWND hwnd );
extern Window X11DRV_get_top_window( HWND hwnd );
inline static Window get_client_window( WND *wnd )
{
struct x11drv_win_data *data = wnd->pDriverData;
return data->client_window;
}
inline static Window get_whole_window( WND *wnd )
{
struct x11drv_win_data *data = wnd->pDriverData;
return data->whole_window;
}
extern void X11DRV_WND_ForceWindowRaise(struct tagWND *pWnd);
extern void X11DRV_WND_SetWindowPos(struct tagWND *wndPtr, const struct tagWINDOWPOS *winpos, BOOL bSMC_SETXPOS);
extern void X11DRV_WND_SetText(struct tagWND *wndPtr, LPCWSTR text);
extern void X11DRV_WND_SurfaceCopy(struct tagWND *wndPtr, HDC hdc, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
extern void X11DRV_WND_SetGravity(struct tagWND* wndPtr, int value );
extern BOOL X11DRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
extern void X11DRV_SetFocus( HWND hwnd );
extern Cursor X11DRV_GetCursor( Display *display, struct tagCURSORICONINFO *ptr );
extern void X11DRV_register_window( Display *display, HWND hwnd, Window win );
extern void X11DRV_expect_error( unsigned char request, unsigned char error, XID id );
extern int X11DRV_check_error(void);
extern void X11DRV_register_window( Display *display, HWND hwnd, struct x11drv_win_data *data );
extern void X11DRV_set_iconic_state( WND *win );
extern void X11DRV_window_to_X_rect( WND *win, RECT *rect );
extern void X11DRV_X_to_window_rect( WND *win, RECT *rect );
extern void X11DRV_create_desktop_thread(void);
extern Window X11DRV_create_desktop( XVisualInfo *desktop_vi, const char *geometry );
extern int X11DRV_sync_whole_window_position( Display *display, WND *win, int zorder );
extern int X11DRV_sync_client_window_position( Display *display, WND *win );
#endif /* __WINE_X11DRV_H */
......@@ -211,9 +211,9 @@ static void DCE_DeleteClipRgn( DCE* dce )
dce->hClipRgn = 0;
TRACE("\trestoring VisRgn\n");
RestoreVisRgn16(dce->hDC);
/* make it dirty so that the vis rgn gets recomputed next time */
dce->DCXflags |= DCX_DCEDIRTY;
SetHookFlags16( dce->hDC, DCHF_INVALIDATEVISRGN );
}
......@@ -412,8 +412,9 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
BOOL bUpdateClipOrigin = FALSE;
TRACE("hwnd %04x, hrgnClip %04x, flags %08x\n",
hwnd, hrgnClip, (unsigned)flags);
hwnd, hrgnClip, (unsigned)flags);
if (!hwnd) hwnd = GetDesktopWindow();
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
/* fixup flags */
......@@ -437,17 +438,11 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
else flags |= DCX_CACHE;
}
if( flags & DCX_NOCLIPCHILDREN )
{
flags |= DCX_CACHE;
flags &= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
}
if (flags & DCX_WINDOW)
flags = (flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
if (!(wndPtr->dwStyle & WS_CHILD) || !wndPtr->parent )
flags &= ~DCX_PARENTCLIP;
if (!wndPtr->parent || (wndPtr->parent->hwndSelf == GetDesktopWindow()))
flags = (flags & ~DCX_PARENTCLIP) | DCX_CLIPSIBLINGS;
else if( flags & DCX_PARENTCLIP )
{
flags |= DCX_CACHE;
......@@ -514,25 +509,6 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
{
TRACE("\tskipping hVisRgn update\n");
bUpdateVisRgn = FALSE; /* updated automatically, via DCHook() */
/* Abey - 16Jul99. to take care of the nested GetDC. first one
with DCX_EXCLUDERGN or DCX_INTERSECTRGN flags and the next
one with or without these flags. */
if(dce->DCXflags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
{
/* This is likely to be a nested BeginPaint().
or a BeginPaint() followed by a GetDC()*/
if( dce->hClipRgn != hrgnClip )
{
FIXME("new hrgnClip[%04x] smashes the previous[%04x]\n",
hrgnClip, dce->hClipRgn );
DCE_DeleteClipRgn( dce );
}
else
RestoreVisRgn16(dce->hDC);
}
}
}
if (!dce)
......@@ -542,6 +518,14 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
}
if (!(flags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN))) hrgnClip = 0;
if (((flags ^ dce->DCXflags) & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
(dce->hClipRgn != hrgnClip))
{
/* if the extra clip region has changed, get rid of the old one */
DCE_DeleteClipRgn( dce );
}
dce->hwndCurrent = hwnd;
dce->hClipRgn = hrgnClip;
dce->DCXflags = flags & (DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN |
......@@ -581,7 +565,7 @@ HDC WINAPI GetDC(
HWND hwnd /* [in] handle of window */
) {
if (!hwnd)
return GetDCEx( GetDesktopWindow(), 0, DCX_CACHE | DCX_WINDOW );
return GetDCEx( 0, 0, DCX_CACHE | DCX_WINDOW );
return GetDCEx( hwnd, 0, DCX_USESTYLE );
}
......@@ -591,7 +575,6 @@ HDC WINAPI GetDC(
*/
HDC16 WINAPI GetWindowDC16( HWND16 hwnd )
{
if (!hwnd) hwnd = GetDesktopWindow16();
return GetDCEx16( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
}
......@@ -601,7 +584,6 @@ HDC16 WINAPI GetWindowDC16( HWND16 hwnd )
*/
HDC WINAPI GetWindowDC( HWND hwnd )
{
if (!hwnd) hwnd = GetDesktopWindow();
return GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW );
}
......
......@@ -415,11 +415,7 @@ static LRESULT DEFWND_DefWinProc( WND *wndPtr, UINT msg, WPARAM wParam,
}
case WM_SYNCPAINT:
if (wndPtr->hrgnUpdate)
{
RedrawWindow ( wndPtr->hwndSelf, 0, wndPtr->hrgnUpdate,
RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
}
RedrawWindow ( wndPtr->hwndSelf, NULL, 0, RDW_ERASENOW | RDW_ERASE | RDW_ALLCHILDREN );
return 0;
case WM_SETREDRAW:
......
......@@ -75,24 +75,6 @@ static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
#define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
/***********************************************************************
* WIN_WindowNeedsWMBorder
*
* This method defines the rules for a window to have a WM border,
* caption... It is used for consistency purposes.
*/
BOOL WIN_WindowNeedsWMBorder( DWORD style, DWORD exStyle )
{
if (!(style & WS_CHILD) &&
Options.managed &&
!(exStyle & WS_EX_TOOLWINDOW) &&
( ((style & WS_CAPTION) == WS_CAPTION) ||
(style & WS_THICKFRAME)))
return TRUE;
if (exStyle & WS_EX_TRAYWINDOW)
return TRUE;
return FALSE;
}
/***********************************************************************
* NC_AdjustRect
......@@ -106,21 +88,17 @@ static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
ERR("Called in Win95 mode. Aiee! Please report this.\n" );
if(style & WS_ICONIC) return;
/* Decide if the window will be managed (see CreateWindowEx) */
if (!WIN_WindowNeedsWMBorder(style, exStyle))
{
if (HAS_THICKFRAME( style, exStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
else
if (HAS_DLGFRAME( style, exStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
else
if (HAS_THINFRAME( style ))
InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
if ((style & WS_CAPTION) == WS_CAPTION)
rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
}
if (HAS_THICKFRAME( style, exStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
else if (HAS_DLGFRAME( style, exStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
else if (HAS_THINFRAME( style ))
InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
if ((style & WS_CAPTION) == WS_CAPTION)
rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
if (style & WS_VSCROLL) {
......@@ -172,29 +150,21 @@ NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
{
if(style & WS_ICONIC) return;
/* Decide if the window will be managed (see CreateWindowEx) */
if (!WIN_WindowNeedsWMBorder(style, exStyle))
if (HAS_THICKFRAME( style, exStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
else if (HAS_DLGFRAME( style, exStyle ))
InflateRect(rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
else if (HAS_THINFRAME( style ))
InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
if ((style & WS_CAPTION) == WS_CAPTION)
{
if (HAS_THICKFRAME( style, exStyle ))
InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
else
if (HAS_DLGFRAME( style, exStyle ))
InflateRect(rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
if (exStyle & WS_EX_TOOLWINDOW)
rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
else
if (HAS_THINFRAME( style ))
InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
if ((style & WS_CAPTION) == WS_CAPTION)
{
if (exStyle & WS_EX_TOOLWINDOW)
rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
else
rect->top -= GetSystemMetrics(SM_CYCAPTION);
}
rect->top -= GetSystemMetrics(SM_CYCAPTION);
}
if (menu)
rect->top -= GetSystemMetrics(SM_CYMENU);
if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
}
......@@ -240,6 +210,20 @@ NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
}
static HICON NC_IconForWindow( HWND hwnd )
{
HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
/* If there is no hIcon specified and this is a modal dialog,
* get the default one.
*/
if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
return hIcon;
}
/***********************************************************************
* DrawCaption (USER.660) Draws a caption bar
*
......@@ -355,18 +339,9 @@ DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
pt.x = rc.left + 2;
pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
if (hIcon) {
DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
}
else {
WND* wndPtr = WIN_FindWndPtr(hwnd);
HICON hAppIcon = (HICON) NC_IconForWindow(wndPtr);
DrawIconEx (hdc, pt.x, pt.y, hAppIcon, GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
WIN_ReleaseWndPtr(wndPtr);
}
if (!hIcon) hIcon = NC_IconForWindow(hwnd);
DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
rc.left += (rc.bottom - rc.top);
}
......@@ -574,7 +549,7 @@ void NC_GetInsideRect( HWND hwnd, RECT *rect )
rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
if ((wndPtr->dwStyle & WS_ICONIC) || (wndPtr->dwExStyle & WS_EX_MANAGED)) goto END;
if (wndPtr->dwStyle & WS_ICONIC) goto END;
/* Remove frame from rectangle */
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
......@@ -630,76 +605,73 @@ static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
/* Check borders */
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
{
/* Check borders */
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
if (!PtInRect( &rect, pt ))
{
InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
if (!PtInRect( &rect, pt ))
/* Check top sizing border */
if (pt.y < rect.top)
{
/* Check top sizing border */
if (pt.y < rect.top)
{
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
return HTTOP;
}
/* Check bottom sizing border */
if (pt.y >= rect.bottom)
{
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
return HTBOTTOM;
}
/* Check left sizing border */
if (pt.x < rect.left)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
return HTLEFT;
}
/* Check right sizing border */
if (pt.x >= rect.right)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
return HTRIGHT;
}
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
return HTTOP;
}
/* Check bottom sizing border */
if (pt.y >= rect.bottom)
{
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
return HTBOTTOM;
}
/* Check left sizing border */
if (pt.x < rect.left)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
return HTLEFT;
}
/* Check right sizing border */
if (pt.x >= rect.right)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
return HTRIGHT;
}
}
else /* No thick frame */
{
if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
else if (HAS_THINFRAME( wndPtr->dwStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
if (!PtInRect( &rect, pt )) return HTBORDER;
}
}
else /* No thick frame */
{
if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
else if (HAS_THINFRAME( wndPtr->dwStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
if (!PtInRect( &rect, pt )) return HTBORDER;
}
/* Check caption */
/* Check caption */
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
{
rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
if (!PtInRect( &rect, pt ))
{
rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
if (!PtInRect( &rect, pt ))
{
/* Check system menu */
if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
rect.left += GetSystemMetrics(SM_CXSIZE);
if (pt.x <= rect.left) return HTSYSMENU;
/* Check maximize box */
if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x >= rect.right) return HTMAXBUTTON;
/* Check minimize box */
if (wndPtr->dwStyle & WS_MINIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x >= rect.right) return HTMINBUTTON;
return HTCAPTION;
}
/* Check system menu */
if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
rect.left += GetSystemMetrics(SM_CXSIZE);
if (pt.x <= rect.left) return HTSYSMENU;
/* Check maximize box */
if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x >= rect.right) return HTMAXBUTTON;
/* Check minimize box */
if (wndPtr->dwStyle & WS_MINIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x >= rect.right) return HTMINBUTTON;
return HTCAPTION;
}
}
......@@ -765,90 +737,87 @@ static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
/* Check borders */
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
{
/* Check borders */
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
if (!PtInRect( &rect, pt ))
{
InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
if (!PtInRect( &rect, pt ))
/* Check top sizing border */
if (pt.y < rect.top)
{
/* Check top sizing border */
if (pt.y < rect.top)
{
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
return HTTOP;
}
/* Check bottom sizing border */
if (pt.y >= rect.bottom)
{
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
return HTBOTTOM;
}
/* Check left sizing border */
if (pt.x < rect.left)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
return HTLEFT;
}
/* Check right sizing border */
if (pt.x >= rect.right)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
return HTRIGHT;
}
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
return HTTOP;
}
/* Check bottom sizing border */
if (pt.y >= rect.bottom)
{
if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
return HTBOTTOM;
}
/* Check left sizing border */
if (pt.x < rect.left)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
return HTLEFT;
}
/* Check right sizing border */
if (pt.x >= rect.right)
{
if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
return HTRIGHT;
}
}
else /* No thick frame */
{
if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
else if (HAS_THINFRAME( wndPtr->dwStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
if (!PtInRect( &rect, pt )) return HTBORDER;
}
}
else /* No thick frame */
{
if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
else if (HAS_THINFRAME( wndPtr->dwStyle ))
InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
if (!PtInRect( &rect, pt )) return HTBORDER;
}
/* Check caption */
/* Check caption */
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
{
if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
else
rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
if (!PtInRect( &rect, pt ))
{
if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
else
rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
if (!PtInRect( &rect, pt ))
/* Check system menu */
if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
{
/* Check system menu */
if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
{
if (NC_IconForWindow(wndPtr))
rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
}
if (pt.x < rect.left) return HTSYSMENU;
/* Check close button */
if (wndPtr->dwStyle & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
if (pt.x > rect.right) return HTCLOSE;
/* Check maximize box */
/* In win95 there is automatically a Maximize button when there is a minimize one*/
if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x > rect.right) return HTMAXBUTTON;
/* Check minimize box */
/* In win95 there is automatically a Maximize button when there is a Maximize one*/
if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x > rect.right) return HTMINBUTTON;
return HTCAPTION;
if (NC_IconForWindow(wndPtr->hwndSelf))
rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
}
if (pt.x < rect.left) return HTSYSMENU;
/* Check close button */
if (wndPtr->dwStyle & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
if (pt.x > rect.right) return HTCLOSE;
/* Check maximize box */
/* In win95 there is automatically a Maximize button when there is a minimize one*/
if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x > rect.right) return HTMAXBUTTON;
/* Check minimize box */
/* In win95 there is automatically a Maximize button when there is a Maximize one*/
if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (pt.x > rect.right) return HTMINBUTTON;
return HTCAPTION;
}
}
......@@ -925,20 +894,15 @@ void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
RECT rect;
HDC hdcMem;
HBITMAP hbitmap;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
{
NC_GetInsideRect( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
hbitmap = SelectObject( hdcMem, hbitmapClose );
BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
hdcMem, (wndPtr->dwStyle & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
down ? NOTSRCCOPY : SRCCOPY );
SelectObject( hdcMem, hbitmap );
DeleteDC( hdcMem );
}
WIN_ReleaseWndPtr(wndPtr);
NC_GetInsideRect( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
hbitmap = SelectObject( hdcMem, hbitmapClose );
BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
down ? NOTSRCCOPY : SRCCOPY );
SelectObject( hdcMem, hbitmap );
DeleteDC( hdcMem );
}
......@@ -948,22 +912,17 @@ void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
{
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
HDC hdcMem;
if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
{
NC_GetInsideRect( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
SelectObject( hdcMem, (IsZoomed(hwnd)
? (down ? hbitmapRestoreD : hbitmapRestore)
: (down ? hbitmapMaximizeD : hbitmapMaximize)) );
BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
SRCCOPY );
DeleteDC( hdcMem );
}
WIN_ReleaseWndPtr(wndPtr);
NC_GetInsideRect( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
SelectObject( hdcMem, (IsZoomed(hwnd)
? (down ? hbitmapRestoreD : hbitmapRestore)
: (down ? hbitmapMaximizeD : hbitmapMaximize)) );
BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
SRCCOPY );
DeleteDC( hdcMem );
}
......@@ -974,21 +933,17 @@ static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
{
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
HDC hdcMem;
if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
{
NC_GetInsideRect( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
SRCCOPY );
DeleteDC( hdcMem );
}
WIN_ReleaseWndPtr(wndPtr);
NC_GetInsideRect( hwnd, &rect );
hdcMem = CreateCompatibleDC( hdc );
SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
if (GetWindowLongA(hwnd,GWL_STYLE) & WS_MAXIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
SRCCOPY );
DeleteDC( hdcMem );
}
......@@ -1012,28 +967,17 @@ static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
BOOL
NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
HICON hIcon = NC_IconForWindow( hwnd );
if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
if (hIcon)
{
HICON hIcon;
RECT rect;
NC_GetInsideRect( hwnd, &rect );
hIcon = NC_IconForWindow( wndPtr );
if (hIcon)
DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
0, 0, DI_NORMAL);
WIN_ReleaseWndPtr(wndPtr);
return (hIcon != 0);
RECT rect;
NC_GetInsideRect( hwnd, &rect );
DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
}
WIN_ReleaseWndPtr(wndPtr);
return FALSE;
return (hIcon != 0);
}
......@@ -1058,37 +1002,32 @@ NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
{
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
NC_GetInsideRect( hwnd, &rect );
/* A tool window has a smaller Close button */
if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
{
NC_GetInsideRect( hwnd, &rect );
INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
/* A tool window has a smaller Close button */
if(wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
{
INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
rect.bottom = rect.top + iBmpHeight;
rect.right = rect.left + iBmpWidth;
}
else
{
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
rect.top += 2;
rect.right -= 2;
}
DrawFrameControl( hdc, &rect, DFC_CAPTION,
(DFCS_CAPTIONCLOSE |
(down ? DFCS_PUSHED : 0) |
(bGrayed ? DFCS_INACTIVE : 0)) );
rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
rect.bottom = rect.top + iBmpHeight;
rect.right = rect.left + iBmpWidth;
}
WIN_ReleaseWndPtr(wndPtr);
else
{
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
rect.top += 2;
rect.right -= 2;
}
DrawFrameControl( hdc, &rect, DFC_CAPTION,
(DFCS_CAPTIONCLOSE |
(down ? DFCS_PUSHED : 0) |
(bGrayed ? DFCS_INACTIVE : 0)) );
}
/******************************************************************************
......@@ -1100,23 +1039,18 @@ static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
{
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
if( !(wndPtr->dwExStyle & WS_EX_MANAGED))
{
UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
NC_GetInsideRect( hwnd, &rect );
if (wndPtr->dwStyle & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
rect.top += 2;
rect.right -= 2;
if (down) flags |= DFCS_PUSHED;
if (bGrayed) flags |= DFCS_INACTIVE;
DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
}
WIN_ReleaseWndPtr(wndPtr);
UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
NC_GetInsideRect( hwnd, &rect );
if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
rect.top += 2;
rect.right -= 2;
if (down) flags |= DFCS_PUSHED;
if (bGrayed) flags |= DFCS_INACTIVE;
DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
}
/******************************************************************************
......@@ -1128,25 +1062,21 @@ static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
static void NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
{
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
UINT flags = DFCS_CAPTIONMIN;
DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
if( !(wndPtr->dwExStyle & WS_EX_MANAGED))
{
UINT flags = DFCS_CAPTIONMIN;
NC_GetInsideRect( hwnd, &rect );
if (wndPtr->dwStyle & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (wndPtr->dwStyle & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
rect.top += 2;
rect.right -= 2;
if (down) flags |= DFCS_PUSHED;
if (bGrayed) flags |= DFCS_INACTIVE;
DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
}
WIN_ReleaseWndPtr(wndPtr);
NC_GetInsideRect( hwnd, &rect );
if (style & WS_SYSMENU)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
rect.top += 2;
rect.right -= 2;
if (down) flags |= DFCS_PUSHED;
if (bGrayed) flags |= DFCS_INACTIVE;
DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
}
/***********************************************************************
......@@ -1306,22 +1236,11 @@ static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
DWORD style, BOOL active )
{
RECT r = *rect;
WND * wndPtr = WIN_FindWndPtr( hwnd );
char buffer[256];
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
WIN_ReleaseWndPtr(wndPtr);
return;
}
if (!hbitmapClose)
{
if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) )))
{
WIN_ReleaseWndPtr(wndPtr);
return;
}
if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) ))) return;
hbitmapMinimize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCE) );
hbitmapMinimizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCED) );
hbitmapMaximize = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOM) );
......@@ -1330,7 +1249,7 @@ static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
hbitmapRestoreD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORED) );
}
if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
{
HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
......@@ -1340,7 +1259,6 @@ static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
r.right--;
SelectObject( hdc, hbrushOld );
}
WIN_ReleaseWndPtr(wndPtr);
MoveToEx( hdc, r.left, r.bottom, NULL );
LineTo( hdc, r.right, r.bottom );
......@@ -1409,18 +1327,10 @@ static void NC_DrawCaption95(
BOOL active )
{
RECT r = *rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
char buffer[256];
HPEN hPrevPen;
HMENU hSysMenu;
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
WIN_ReleaseWndPtr(wndPtr);
return;
}
WIN_ReleaseWndPtr(wndPtr);
hPrevPen = SelectObject( hdc, GetSysColorPen(COLOR_3DFACE) );
MoveToEx( hdc, r.left, r.bottom - 1, NULL );
LineTo( hdc, r.right, r.bottom - 1 );
......@@ -1521,27 +1431,24 @@ static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
{
if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
{
SelectObject( hdc, GetStockObject(NULL_BRUSH) );
Rectangle( hdc, 0, 0, rect.right, rect.bottom );
InflateRect( &rect, -1, -1 );
}
SelectObject( hdc, GetStockObject(NULL_BRUSH) );
Rectangle( hdc, 0, 0, rect.right, rect.bottom );
InflateRect( &rect, -1, -1 );
}
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame(hdc, &rect, FALSE, active );
else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame( hdc, &rect, TRUE, active );
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame(hdc, &rect, FALSE, active );
else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame( hdc, &rect, TRUE, active );
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
{
RECT r = rect;
r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
}
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
{
RECT r = rect;
r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
}
if (HAS_MENU(wndPtr))
......@@ -1652,34 +1559,32 @@ static void NC_DoNCPaint95(
SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
if(!(wndPtr->dwExStyle & WS_EX_MANAGED)) {
if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
}
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame95(hdc, &rect, FALSE, active );
else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame95( hdc, &rect, TRUE, active );
else if (HAS_THINFRAME( wndPtr->dwStyle )) {
SelectObject( hdc, GetStockObject(NULL_BRUSH) );
Rectangle( hdc, 0, 0, rect.right, rect.bottom );
}
if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
}
if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame95(hdc, &rect, FALSE, active );
else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
NC_DrawFrame95( hdc, &rect, TRUE, active );
else if (HAS_THINFRAME( wndPtr->dwStyle )) {
SelectObject( hdc, GetStockObject(NULL_BRUSH) );
Rectangle( hdc, 0, 0, rect.right, rect.bottom );
}
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
{
RECT r = rect;
if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
rect.top += GetSystemMetrics(SM_CYSMCAPTION);
}
else {
r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
rect.top += GetSystemMetrics(SM_CYCAPTION);
}
if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
wndPtr->dwExStyle, active);
if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
{
RECT r = rect;
if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
rect.top += GetSystemMetrics(SM_CYSMCAPTION);
}
else {
r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
rect.top += GetSystemMetrics(SM_CYCAPTION);
}
if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
wndPtr->dwExStyle, active);
}
if (HAS_MENU(wndPtr))
......@@ -2351,16 +2256,3 @@ BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
return TRUE;
}
HICON16 NC_IconForWindow(WND *wndPtr)
{
HICON16 hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICONSM);
if(!hIcon) hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON);
/* If there is no hIcon specified and this is a modal dialog, */
/* get the default one. */
if (!hIcon && (wndPtr->dwStyle & DS_MODALFRAME))
hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
return hIcon;
}
......@@ -28,6 +28,17 @@ DECLARE_DEBUG_CHANNEL(nonclient);
(r).right = (wnd)->rectClient.right - (wnd)->rectWindow.left; \
(r).bottom = (wnd)->rectClient.bottom - (wnd)->rectWindow.top
/* PAINT_RedrawWindow() control flags */
#define RDW_EX_DELAY_NCPAINT 0x0020
/* WIN_UpdateNCRgn() flags */
#define UNC_CHECK 0x0001
#define UNC_ENTIRE 0x0002
#define UNC_REGION 0x0004
#define UNC_UPDATE 0x0008
#define UNC_DELAY_NCPAINT 0x0010
#define UNC_IN_BEGINPAINT 0x0020
/* Last COLOR id */
#define COLOR_MAX COLOR_GRADIENTINACTIVECAPTION
......@@ -127,7 +138,7 @@ static BOOL WIN_HaveToDelayNCPAINT(
* is 1 then the hRgn is preserved and RDW_Paint() will have to get
* a DC without extra clipping region.
*/
HRGN WIN_UpdateNCRgn(WND* wnd, HRGN hRgn, UINT uncFlags )
static HRGN WIN_UpdateNCRgn(WND* wnd, HRGN hRgn, UINT uncFlags )
{
RECT r;
HRGN hClip = 0;
......@@ -323,7 +334,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
TRACE("hrgnUpdate = %04x, \n", hrgnUpdate);
if (GetClassWord16(wndPtr->hwndSelf, GCW_STYLE) & CS_PARENTDC)
if (GetClassLongA(wndPtr->hwndSelf, GCL_STYLE) & CS_PARENTDC)
{
/* Don't clip the output to the update region for CS_PARENTDC window */
if( hrgnUpdate )
......@@ -336,7 +347,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
if( hrgnUpdate ) /* convert to client coordinates */
OffsetRgn( hrgnUpdate, wndPtr->rectWindow.left - wndPtr->rectClient.left,
wndPtr->rectWindow.top - wndPtr->rectClient.top );
lps->hdc = GetDCEx(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
lps->hdc = GetDCEx(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
DCX_WINDOWPAINT | DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) );
/* ReleaseDC() in EndPaint() will delete the region */
}
......@@ -477,7 +488,7 @@ END:
* Validate the portions of parents that are covered by a validated child
* wndPtr = child
*/
void RDW_ValidateParent(WND *wndChild)
static void RDW_ValidateParent(WND *wndChild)
{
WND *wndParent = WIN_LockWndPtr(wndChild->parent);
WND *wndDesktop = WIN_GetDesktop();
......@@ -611,15 +622,14 @@ static void RDW_UpdateRgns( WND* wndPtr, HRGN hRgn, UINT flags, BOOL firstRecurs
if( CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hRgn, RGN_DIFF )
== NULLREGION )
goto EMPTY;
{
DeleteObject( wndPtr->hrgnUpdate );
wndPtr->hrgnUpdate = 0;
}
}
else /* validate everything */
{
if( wndPtr->hrgnUpdate > 1 )
{
EMPTY:
DeleteObject( wndPtr->hrgnUpdate );
}
if( wndPtr->hrgnUpdate > 1 ) DeleteObject( wndPtr->hrgnUpdate );
wndPtr->hrgnUpdate = 0;
}
......@@ -757,7 +767,7 @@ static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex )
if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
SendMessage16( hWnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
}
else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME))
else if (flags & RDW_ERASENOW)
{
UINT dcx = DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN | DCX_WINDOWPAINT | DCX_CACHE;
HRGN hrgnRet;
......@@ -765,7 +775,6 @@ static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex )
hrgnRet = WIN_UpdateNCRgn(wndPtr,
hrgn,
UNC_REGION | UNC_CHECK |
((ex & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) |
((ex & RDW_EX_DELAY_NCPAINT) ? UNC_DELAY_NCPAINT : 0) );
if( hrgnRet )
......@@ -792,7 +801,6 @@ static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex )
}
if( !IsWindow(hWnd) ) return hrgn;
ex &= ~RDW_EX_TOPFRAME;
/* ... and its child windows */
......@@ -820,12 +828,12 @@ static HRGN RDW_Paint( WND* wndPtr, HRGN hrgn, UINT flags, UINT ex )
return hrgn;
}
/***********************************************************************
* PAINT_RedrawWindow
*
* RedrawWindow (USER32.@)
*/
BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
HRGN hrgnUpdate, UINT flags, UINT ex )
BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rectUpdate,
HRGN hrgnUpdate, UINT flags )
{
HRGN hRgn = 0;
RECT r, r2;
......@@ -848,8 +856,8 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
if( hrgnUpdate )
{
GetRgnBox( hrgnUpdate, &r );
TRACE( "%04x (%04x) NULL %04x box (%i,%i-%i,%i) flags=%04x, exflags=%04x\n",
hwnd, wndPtr->hrgnUpdate, hrgnUpdate, r.left, r.top, r.right, r.bottom, flags, ex);
TRACE( "%04x (%04x) NULL %04x box (%i,%i-%i,%i) flags=%04x\n",
hwnd, wndPtr->hrgnUpdate, hrgnUpdate, r.left, r.top, r.right, r.bottom, flags );
}
else
{
......@@ -857,9 +865,9 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
r = *rectUpdate;
else
SetRectEmpty( &r );
TRACE( "%04x (%04x) %s %d,%d-%d,%d %04x flags=%04x, exflags=%04x\n",
TRACE( "%04x (%04x) %s %d,%d-%d,%d %04x flags=%04x\n",
hwnd, wndPtr->hrgnUpdate, rectUpdate ? "rect" : "NULL", r.left,
r.top, r.right, r.bottom, hrgnUpdate, flags, ex );
r.top, r.right, r.bottom, hrgnUpdate, flags );
}
}
......@@ -870,17 +878,9 @@ BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
else
r = wndPtr->rectClient;
if( ex & RDW_EX_XYWINDOW )
{
pt.x = pt.y = 0;
OffsetRect( &r, -wndPtr->rectWindow.left, -wndPtr->rectWindow.top );
}
else
{
pt.x = wndPtr->rectClient.left - wndPtr->rectWindow.left;
pt.y = wndPtr->rectClient.top - wndPtr->rectWindow.top;
OffsetRect( &r, -wndPtr->rectClient.left, -wndPtr->rectClient.top );
}
pt.x = wndPtr->rectClient.left - wndPtr->rectWindow.left;
pt.y = wndPtr->rectClient.top - wndPtr->rectWindow.top;
OffsetRect( &r, -wndPtr->rectClient.left, -wndPtr->rectClient.top );
if (flags & RDW_INVALIDATE) /* ------------------------- Invalidate */
{
......@@ -935,7 +935,6 @@ rect2i:
{
if( !IntersectRect( &r2, &r, rectUpdate ) ) goto END;
OffsetRect( &r2, pt.x, pt.y );
rect2v:
hRgn = CreateRectRgnIndirect( &r2 );
}
else /* entire window or client depending on RDW_FRAME */
......@@ -945,7 +944,7 @@ rect2v:
else
{
GETCLIENTRECTW( wndPtr, r2 );
goto rect2v;
hRgn = CreateRectRgnIndirect( &r2 );
}
}
}
......@@ -956,7 +955,7 @@ rect2v:
/* Erase/update windows, from now on hRgn is a scratch region */
hRgn = RDW_Paint( wndPtr, (hRgn == 1) ? 0 : hRgn, flags, ex );
hRgn = RDW_Paint( wndPtr, (hRgn == 1) ? 0 : hRgn, flags, 0 );
END:
if( hRgn > 1 && (hRgn != hrgnUpdate) )
......@@ -967,16 +966,6 @@ END:
/***********************************************************************
* RedrawWindow (USER32.@)
*/
BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rectUpdate,
HRGN hrgnUpdate, UINT flags )
{
return PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 );
}
/***********************************************************************
* RedrawWindow (USER.290)
*/
BOOL16 WINAPI RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
......
......@@ -13,10 +13,6 @@
#include "wingdi.h"
#include "wine/winuser16.h"
#include "winuser.h"
#include "win.h"
#include "gdi.h"
#include "dce.h"
#include "region.h"
#include "user.h"
#include "debugtools.h"
......@@ -79,109 +75,9 @@ BOOL WINAPI ScrollDC( HDC hdc, INT dx, INT dy, const RECT *rc,
const RECT *prLClip, HRGN hrgnUpdate,
LPRECT rcUpdate )
{
RECT rect, rClip, rSrc;
POINT src, dest;
DC *dc = DC_GetDCUpdate( hdc );
TRACE("%04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n",
(HDC16)hdc, dx, dy, hrgnUpdate, rcUpdate,
prLClip ? prLClip->left : 0, prLClip ? prLClip->top : 0, prLClip ? prLClip->right : 0, prLClip ? prLClip->bottom : 0,
rc ? rc->left : 0, rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 );
if ( !dc || !hdc ) return FALSE;
/*
TRACE(scroll,"\t[wndOrgX=%i, wndExtX=%i, vportOrgX=%i, vportExtX=%i]\n",
dc->wndOrgX, dc->wndExtX, dc->vportOrgX, dc->vportExtX );
TRACE(scroll,"\t[wndOrgY=%i, wndExtY=%i, vportOrgY=%i, vportExtY=%i]\n",
dc->wndOrgY, dc->wndExtY, dc->vportOrgY, dc->vportExtY );
*/
/* compute device clipping region (in device coordinates) */
if ( rc )
rect = *rc;
else /* maybe we should just return FALSE? */
GetClipBox( hdc, &rect );
LPtoDP( hdc, (LPPOINT)&rect, 2 );
if (prLClip)
{
rClip = *prLClip;
LPtoDP( hdc, (LPPOINT)&rClip, 2 );
IntersectRect( &rClip, &rect, &rClip );
}
else
rClip = rect;
dx = XLPTODP ( dc, rect.left + dx ) - XLPTODP ( dc, rect.left );
dy = YLPTODP ( dc, rect.top + dy ) - YLPTODP ( dc, rect.top );
rSrc = rClip;
OffsetRect( &rSrc, -dx, -dy );
IntersectRect( &rSrc, &rSrc, &rect );
if(dc->hVisRgn)
{
if (!IsRectEmpty(&rSrc))
{
dest.x = (src.x = rSrc.left) + dx;
dest.y = (src.y = rSrc.top) + dy;
/* copy bits */
DPtoLP( hdc, (LPPOINT)&rSrc, 2 );
DPtoLP( hdc, &src, 1 );
DPtoLP( hdc, &dest, 1 );
if (!BitBlt( hdc, dest.x, dest.y,
rSrc.right - rSrc.left, rSrc.bottom - rSrc.top,
hdc, src.x, src.y, SRCCOPY))
{
GDI_ReleaseObj( hdc );
return FALSE;
}
}
/* compute update areas */
if (hrgnUpdate || rcUpdate)
{
HRGN hrgn =
(hrgnUpdate) ? hrgnUpdate : CreateRectRgn( 0,0,0,0 );
HRGN hrgn2;
hrgn2 = CreateRectRgnIndirect( &rect );
OffsetRgn( hrgn2, dc->DCOrgX, dc->DCOrgY );
CombineRgn( hrgn2, hrgn2, dc->hVisRgn, RGN_AND );
OffsetRgn( hrgn2, -dc->DCOrgX, -dc->DCOrgY );
SetRectRgn( hrgn, rClip.left, rClip.top,
rClip.right, rClip.bottom );
CombineRgn( hrgn, hrgn, hrgn2, RGN_AND );
OffsetRgn( hrgn2, dx, dy );
CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
if( rcUpdate )
{
GetRgnBox( hrgn, rcUpdate );
/* Put the rcUpdate in logical coordinate */
DPtoLP( hdc, (LPPOINT)rcUpdate, 2 );
}
if (!hrgnUpdate) DeleteObject( hrgn );
DeleteObject( hrgn2 );
}
}
else
{
if (hrgnUpdate) SetRectRgn(hrgnUpdate, 0, 0, 0, 0);
if (rcUpdate) SetRectEmpty(rcUpdate);
}
GDI_ReleaseObj( hdc );
return TRUE;
if (USER_Driver.pScrollDC)
return USER_Driver.pScrollDC( hdc, dx, dy, rc, prLClip, hrgnUpdate, rcUpdate );
return FALSE;
}
......
......@@ -553,6 +553,7 @@ BOOL WIN_CreateDesktopWindow(void)
DWORD clsStyle;
WNDPROC winproc;
DCE *dce;
CREATESTRUCTA cs;
TRACE("Creating desktop window\n");
......@@ -601,9 +602,21 @@ BOOL WIN_CreateDesktopWindow(void)
pWndDesktop->cbWndExtra = wndExtra;
pWndDesktop->irefCount = 0;
if (!USER_Driver.pCreateWindow( hwndDesktop )) return FALSE;
cs.lpCreateParams = NULL;
cs.hInstance = 0;
cs.hMenu = 0;
cs.hwndParent = 0;
cs.x = 0;
cs.y = 0;
cs.cx = pWndDesktop->rectWindow.right;
cs.cy = pWndDesktop->rectWindow.bottom;
cs.style = pWndDesktop->dwStyle;
cs.dwExStyle = pWndDesktop->dwExStyle;
cs.lpszName = NULL;
cs.lpszClass = DESKTOP_CLASS_ATOM;
if (!USER_Driver.pCreateWindow( hwndDesktop, &cs )) return FALSE;
SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
return TRUE;
}
......@@ -685,14 +698,12 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
INT sw = SW_SHOW;
struct tagCLASS *classPtr;
WND *wndPtr;
HWND retvalue;
HWND16 hwnd, hwndLinkAfter;
HWND hwnd, hwndLinkAfter;
POINT maxSize, maxPos, minTrack, maxTrack;
INT wndExtra;
DWORD clsStyle;
WNDPROC winproc;
DCE *dce;
LRESULT CALLBACK (*localSend32)(HWND, UINT, WPARAM, LPARAM);
TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
(type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
......@@ -811,7 +822,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
TRACE("CBT-hook returned 0\n");
USER_HEAP_FREE( hwnd );
CLASS_RemoveWindow( classPtr );
retvalue = 0;
hwnd = 0;
goto end;
}
}
......@@ -862,12 +873,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
wndPtr->rectWindow.bottom = cs->y + cs->cy;
wndPtr->rectClient = wndPtr->rectWindow;
if (!USER_Driver.pCreateWindow(wndPtr->hwndSelf))
{
retvalue = FALSE;
goto end;
}
/* Set the window menu */
if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
......@@ -889,96 +894,44 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
}
else wndPtr->wIDmenu = (UINT)cs->hMenu;
/* Send the WM_CREATE message
* Perhaps we shouldn't allow width/height changes as well.
* See p327 in "Internals".
*/
maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
localSend32 = (type == WIN_PROC_32W) ? SendMessageW : SendMessageA;
if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs ))
{
/* Insert the window in the linked list */
WARN("aborted by WM_xxCREATE!\n");
WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
CLASS_RemoveWindow( classPtr );
WIN_ReleaseWndPtr(wndPtr);
return 0;
}
WIN_LinkWindow( hwnd, hwndLinkAfter );
if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
{
/* Notify the parent window only */
WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
NULL, NULL, 0, &wndPtr->rectClient );
OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
maxPos.y - wndPtr->rectWindow.top);
if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
if( !IsWindow(hwnd) )
{
/* Send the size messages */
if (!(wndPtr->flags & WIN_NEED_SIZE))
{
/* send it anyway */
if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
WARN("sending bogus WM_SIZE message 0x%08lx\n",
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
(*localSend32)( hwnd, WM_SIZE, SIZE_RESTORED,
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
(*localSend32)( hwnd, WM_MOVE, 0,
MAKELONG( wndPtr->rectClient.left,
wndPtr->rectClient.top ) );
}
/* Show the window, maximizing or minimizing if needed */
if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
{
RECT16 newPos;
UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
: SWP_NOZORDER | SWP_FRAMECHANGED;
SetWindowPos( hwnd, 0, newPos.left, newPos.top,
newPos.right, newPos.bottom, swFlag );
}
if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
{
/* Notify the parent window only */
SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
if( !IsWindow(hwnd) )
{
retvalue = 0;
goto end;
}
}
if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
/* Call WH_SHELL hook */
if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
TRACE("created window %04x\n", hwnd);
retvalue = hwnd;
hwnd = 0;
goto end;
}
WIN_UnlinkWindow( hwnd );
}
/* Abort window creation */
if (cs->style & WS_VISIBLE)
{
/* in case WS_VISIBLE got set in the meantime */
wndPtr->dwStyle &= ~WS_VISIBLE;
ShowWindow( hwnd, sw );
}
WARN("aborted by WM_xxCREATE!\n");
WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
CLASS_RemoveWindow( classPtr );
retvalue = 0;
end:
WIN_ReleaseWndPtr(wndPtr);
/* Call WH_SHELL hook */
return retvalue;
if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
TRACE("created window %04x\n", hwnd);
end:
WIN_ReleaseWndPtr(wndPtr);
return hwnd;
}
......@@ -2176,8 +2129,12 @@ INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
*/
INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
{
FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
return GetWindowTextW(hwnd,lpString,nMaxCount);
WND *win = WIN_FindWndPtr( hwnd );
if (!win) return 0;
if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
else lpString[0] = 0;
WIN_ReleaseWndPtr( win );
return strlenW(lpString);
}
......
......@@ -42,8 +42,6 @@ DEFAULT_DEBUG_CHANNEL(win);
#define PLACE_MAX 0x0002
#define PLACE_RECT 0x0004
#define MINMAX_NOSWP 0x00010000
#define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
......@@ -119,58 +117,6 @@ void WINPOS_CheckInternalPos( WND* wndPtr )
}
/***********************************************************************
* WINPOS_FindIconPos
*
* Find a suitable place for an iconic window.
*/
static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
{
RECT16 rectParent;
short x, y, xspacing, yspacing;
GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
(pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
return pt; /* The icon already has a suitable position */
xspacing = GetSystemMetrics(SM_CXICONSPACING);
yspacing = GetSystemMetrics(SM_CYICONSPACING);
y = rectParent.bottom;
for (;;)
{
x = rectParent.left;
do
{
/* Check if another icon already occupies this spot */
WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
while (childPtr)
{
if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
{
if ((childPtr->rectWindow.left < x + xspacing) &&
(childPtr->rectWindow.right >= x) &&
(childPtr->rectWindow.top <= y) &&
(childPtr->rectWindow.bottom > y - yspacing))
break; /* There's a window in there */
}
WIN_UpdateWndPtr(&childPtr,childPtr->next);
}
WIN_ReleaseWndPtr(childPtr);
if (!childPtr) /* No window was found, so it's OK for us */
{
pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
return pt;
}
x += xspacing;
} while(x <= rectParent.right-xspacing);
y -= yspacing;
}
}
/***********************************************************************
* ArrangeIconicWindows (USER.170)
*/
UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
......@@ -440,7 +386,8 @@ INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT pt, WND **ppWnd )
MapWindowPoints( GetDesktopWindow(), wndScope->parent->hwndSelf, &xy, 1 );
if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom)
xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom ||
wndScope->dwStyle & WS_MINIMIZE)
goto hittest;
xy.x -= wndScope->rectClient.left;
......@@ -1154,8 +1101,7 @@ void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
{
xinc = GetSystemMetrics(SM_CXDLGFRAME);
yinc = GetSystemMetrics(SM_CYDLGFRAME);
......@@ -1207,107 +1153,6 @@ void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
}
/***********************************************************************
* WINPOS_MinMaximize
*
* Fill in lpRect and return additional flags to be used with SetWindowPos().
* This function assumes that 'cmd' is different from the current window
* state.
*/
UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
{
UINT swpFlags = 0;
POINT pt, size;
LPINTERNALPOS lpPos;
TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
if (lpPos && !HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
{
if( wndPtr->dwStyle & WS_MINIMIZE )
{
if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
return (SWP_NOSIZE | SWP_NOMOVE);
swpFlags |= SWP_NOCOPYBITS;
}
switch( cmd )
{
case SW_MINIMIZE:
if( wndPtr->dwStyle & WS_MAXIMIZE)
{
wndPtr->flags |= WIN_RESTORE_MAX;
wndPtr->dwStyle &= ~WS_MAXIMIZE;
}
else
wndPtr->flags &= ~WIN_RESTORE_MAX;
wndPtr->dwStyle |= WS_MINIMIZE;
if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
swpFlags |= MINMAX_NOSWP;
lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
swpFlags |= SWP_NOCOPYBITS;
break;
case SW_MAXIMIZE:
CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
if( wndPtr->dwStyle & WS_MINIMIZE )
{
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
WINPOS_ShowIconTitle( wndPtr, FALSE );
wndPtr->dwStyle &= ~WS_MINIMIZE;
}
wndPtr->dwStyle |= WS_MAXIMIZE;
SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
size.x, size.y );
break;
case SW_RESTORE:
if( wndPtr->dwStyle & WS_MINIMIZE )
{
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
wndPtr->dwStyle &= ~WS_MINIMIZE;
WINPOS_ShowIconTitle( wndPtr, FALSE );
if( wndPtr->flags & WIN_RESTORE_MAX)
{
/* Restore to maximized position */
CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
wndPtr->dwStyle |= WS_MAXIMIZE;
SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
break;
}
}
else
if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
else wndPtr->dwStyle &= ~WS_MAXIMIZE;
/* Restore to normal position */
*lpRect = lpPos->rectNormal;
lpRect->right -= lpRect->left;
lpRect->bottom -= lpRect->top;
break;
}
} else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
return swpFlags;
}
/***********************************************************************
* ShowWindowAsync (USER32.@)
*
* doesn't wait; returns immediately.
......@@ -1332,140 +1177,9 @@ BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
/***********************************************************************
* ShowWindow (USER32.@)
*/
BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
{
WND* wndPtr = WIN_FindWndPtr( hwnd );
BOOL wasVisible, showFlag;
RECT16 newPos = {0, 0, 0, 0};
UINT swp = 0;
if (!wndPtr) return FALSE;
TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
switch(cmd)
{
case SW_HIDE:
if (!wasVisible) goto END;;
swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER;
break;
case SW_SHOWMINNOACTIVE:
swp |= SWP_NOACTIVATE | SWP_NOZORDER;
/* fall through */
case SW_SHOWMINIMIZED:
swp |= SWP_SHOWWINDOW;
/* fall through */
case SW_MINIMIZE:
swp |= SWP_FRAMECHANGED;
if( !(wndPtr->dwStyle & WS_MINIMIZE) )
swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
else swp |= SWP_NOSIZE | SWP_NOMOVE;
break;
case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
else swp |= SWP_NOSIZE | SWP_NOMOVE;
break;
case SW_SHOWNA:
swp |= SWP_NOACTIVATE | SWP_NOZORDER;
/* fall through */
case SW_SHOW:
swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
/*
* ShowWindow has a little peculiar behavior that if the
* window is already the topmost window, it will not
* activate it.
*/
if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
swp |= SWP_NOACTIVATE;
break;
case SW_SHOWNOACTIVATE:
swp |= SWP_NOZORDER;
if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
/* fall through */
case SW_SHOWNORMAL: /* same as SW_NORMAL: */
case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
case SW_RESTORE:
swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
else swp |= SWP_NOSIZE | SWP_NOMOVE;
break;
}
showFlag = (cmd != SW_HIDE);
if (showFlag != wasVisible)
{
SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
if (!IsWindow( hwnd )) goto END;
}
if ((wndPtr->dwStyle & WS_CHILD) &&
!IsWindowVisible( wndPtr->parent->hwndSelf ) &&
(swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
{
/* Don't call SetWindowPos() on invisible child windows */
if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
else wndPtr->dwStyle |= WS_VISIBLE;
}
else
{
/* We can't activate a child window */
if ((wndPtr->dwStyle & WS_CHILD) &&
!(wndPtr->dwExStyle & WS_EX_MDICHILD))
swp |= SWP_NOACTIVATE | SWP_NOZORDER;
if (!(swp & MINMAX_NOSWP))
{
SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
newPos.right, newPos.bottom, LOWORD(swp) );
if (cmd == SW_HIDE)
{
/* FIXME: This will cause the window to be activated irrespective
* of whether it is owned by the same thread. Has to be done
* asynchronously.
*/
if (hwnd == GetActiveWindow())
WINPOS_ActivateOtherWindow(wndPtr);
/* Revert focus to parent */
if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
SetFocus( GetParent(hwnd) );
}
}
if (!IsWindow( hwnd )) goto END;
else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
}
if (wndPtr->flags & WIN_NEED_SIZE)
{
/* should happen only in CreateWindowEx() */
int wParam = SIZE_RESTORED;
wndPtr->flags &= ~WIN_NEED_SIZE;
if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
SendMessageA( hwnd, WM_SIZE, wParam,
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
SendMessageA( hwnd, WM_MOVE, 0,
MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
}
END:
WIN_ReleaseWndPtr(wndPtr);
return wasVisible;
BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
{
return USER_Driver.pShowWindow( hwnd, cmd );
}
......
......@@ -315,7 +315,6 @@ int X11DRV_CLIPBOARD_CacheDataFormats( Atom SelectionName )
Display *display = thread_display();
HWND hWnd = 0;
HWND hWndClipWindow = GetOpenClipboardWindow();
WND* wnd = NULL;
XEvent xe;
Atom aTargets;
Atom atype=AnyPropertyType;
......@@ -343,10 +342,7 @@ int X11DRV_CLIPBOARD_CacheDataFormats( Atom SelectionName )
/*
* Query the selection owner for the TARGETS property
*/
wnd = WIN_FindWndPtr(hWnd);
w = X11DRV_WND_FindXWindow(wnd);
WIN_ReleaseWndPtr(wnd);
wnd = NULL;
w = X11DRV_get_top_window(hWnd);
aTargets = TSXInternAtom(display, "TARGETS", False);
......@@ -863,9 +859,7 @@ void X11DRV_AcquireClipboard(void)
if ( !(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)) )
{
Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
WND *tmpWnd = WIN_FindWndPtr( hWndClipWindow ? hWndClipWindow : AnyPopup() );
owner = X11DRV_WND_FindXWindow(tmpWnd );
WIN_ReleaseWndPtr(tmpWnd);
owner = X11DRV_get_top_window( hWndClipWindow ? hWndClipWindow : AnyPopup() );
/* Grab PRIMARY selection if not owned */
if ( !(selectionAcquired & S_PRIMARY) )
......@@ -1012,18 +1006,15 @@ BOOL X11DRV_GetClipboardData(UINT wFormat)
BOOL bRet = selectionAcquired;
HWND hWndClipWindow = GetOpenClipboardWindow();
HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
WND* wnd = NULL;
LPWINE_CLIPFORMAT lpFormat;
TRACE("%d\n", wFormat);
if( !selectionAcquired && (wnd = WIN_FindWndPtr(hWnd)) )
if (!selectionAcquired)
{
XEvent xe;
Atom propRequest;
Window w = X11DRV_WND_FindXWindow(wnd);
WIN_ReleaseWndPtr(wnd);
wnd = NULL;
Window w = X11DRV_get_top_window(hWnd);
/* Map the format ID requested to an X selection property.
* If the format is in the cache, use the atom associated
......@@ -1089,7 +1080,7 @@ void X11DRV_ResetSelectionOwner(WND *pWnd, BOOL bFooBar)
{
Display *display = thread_display();
HWND hWndClipOwner = 0;
Window XWnd = X11DRV_WND_GetXWindow(pWnd);
Window XWnd = get_whole_window(pWnd);
Atom xaClipboard;
BOOL bLostSelection = FALSE;
......@@ -1118,10 +1109,10 @@ void X11DRV_ResetSelectionOwner(WND *pWnd, BOOL bFooBar)
selectionWindow = None;
if( pWnd->next )
selectionWindow = X11DRV_WND_GetXWindow(pWnd->next);
selectionWindow = get_whole_window(pWnd->next);
else if( pWnd->parent )
if( pWnd->parent->child != pWnd )
selectionWindow = X11DRV_WND_GetXWindow(pWnd->parent->child);
selectionWindow = get_whole_window(pWnd->parent->child);
if( selectionWindow != None )
{
......
......@@ -51,7 +51,7 @@ extern Atom dndProtocol;
extern Atom dndSelection;
extern void X11DRV_KEYBOARD_UpdateState(void);
extern void X11DRV_KEYBOARD_HandleEvent(WND *pWnd, XKeyEvent *event);
extern void X11DRV_KEYBOARD_HandleEvent( XKeyEvent *event, int x, int y );
#define NB_BUTTONS 5 /* Windows can handle 3 buttons and the wheel too */
......@@ -97,16 +97,16 @@ static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event );
static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
static void EVENT_Expose( HWND hWnd, XExposeEvent *event );
static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event );
static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event );
static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
static void EVENT_PropertyNotify( XPropertyEvent *event );
static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
static void EVENT_MapNotify( HWND pWnd, XMapEvent *event );
static void EVENT_UnmapNotify( HWND pWnd, XUnmapEvent *event );
static void EVENT_MappingNotify( XMappingEvent *event );
extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
#ifdef HAVE_LIBXXF86DGA2
static int DGAMotionEventType;
static int DGAButtonPressEventType;
......@@ -122,14 +122,6 @@ static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event );
static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event );
#endif
/* Usable only with OLVWM - compile option perhaps?
static void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event );
*/
static void EVENT_GetGeometry( Display *display, Window win, int *px, int *py,
unsigned int *pwidth, unsigned int *pheight );
/* Static used for the current input method */
static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
static BOOL in_transition = FALSE; /* This is not used as for today */
......@@ -138,31 +130,22 @@ static BOOL in_transition = FALSE; /* This is not used as for today */
/***********************************************************************
* process_events
*/
static void process_events( Display *display )
static int process_events( struct x11drv_thread_data *data )
{
XEvent event;
int count = 0;
wine_tsx11_lock();
while ( XPending( display ) )
while ( XPending( data->display ) )
{
XNextEvent( display, &event );
XNextEvent( data->display, &event );
wine_tsx11_unlock();
EVENT_ProcessEvent( &event );
count++;
wine_tsx11_lock();
}
wine_tsx11_unlock();
}
/***********************************************************************
* X11DRV_Synchronize
*
* Synchronize with the X server. Should not be used too often.
*/
void X11DRV_Synchronize( void )
{
Display *display = thread_display();
TSXSync( display, False );
process_events( display );
return count;
}
......@@ -183,14 +166,19 @@ DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
for (i = 0; i < count; i++) new_handles[i] = handles[i];
new_handles[count] = data->display_fd;
data->process_event_count++;
wine_tsx11_lock();
XFlush( gdi_display );
XFlush( data->display );
wine_tsx11_unlock();
ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
timeout, flags & MWMO_ALERTABLE );
if (ret == count) process_events( data->display );
data->process_event_count++;
if (process_events( data )) ret = count;
else
{
ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
timeout, flags & MWMO_ALERTABLE );
if (ret == count) process_events( data );
}
data->process_event_count--;
return ret;
}
......@@ -272,33 +260,20 @@ static void EVENT_ProcessEvent( XEvent *event )
ke.keycode = evt->keycode;
ke.same_screen = TRUE;
X11DRV_KEYBOARD_HandleEvent(NULL, &ke);
X11DRV_KEYBOARD_HandleEvent(&ke,pt.x,pt.y);
return;
}
}
#endif
if ( TSXFindContext( display, event->xany.window, winContext,
(char **)&hWnd ) != 0) {
if ( event->type == ClientMessage) {
/* query window (drag&drop event contains only drag window) */
Window root, child;
int root_x, root_y, child_x, child_y;
unsigned u;
TSXQueryPointer( display, root_window, &root, &child,
&root_x, &root_y, &child_x, &child_y, &u);
if (TSXFindContext( display, child, winContext, (char **)&hWnd ) != 0)
return;
} else {
if (TSXFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
hWnd = 0; /* Not for a registered window */
}
}
if ( !hWnd && event->xany.window != root_window
&& event->type != PropertyNotify
&& event->type != MappingNotify)
ERR("Got event %s for unknown Window %08lx\n",
event_names[event->type], event->xany.window );
WARN( "Got event %s for unknown Window %08lx\n",
event_names[event->type], event->xany.window );
else
TRACE("Got event %s for hwnd %04x\n",
event_names[event->type], hWnd );
......@@ -334,65 +309,22 @@ static void EVENT_ProcessEvent( XEvent *event )
MotionNotify, event));
EVENT_MotionNotify( hWnd, (XMotionEvent*)event );
break;
case FocusIn:
{
WND *pWndLastFocus = 0;
XWindowAttributes win_attr;
BOOL bIsDisabled;
XFocusChangeEvent *xfocChange = (XFocusChangeEvent*)event;
if (!hWnd) return;
bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
/* If the window has been disabled and we are in managed mode,
* revert the X focus back to the last focus window. This is to disallow
* the window manager from switching focus away while the app is
* in a modal state.
*/
if ( Options.managed && bIsDisabled && glastXFocusWin)
{
/* Change focus only if saved focus window is registered and viewable */
if ( TSXFindContext( xfocChange->display, glastXFocusWin, winContext,
(char **)&pWndLastFocus ) == 0 )
{
if ( TSXGetWindowAttributes( display, glastXFocusWin, &win_attr ) &&
(win_attr.map_state == IsViewable) )
{
TSXSetInputFocus( xfocChange->display, glastXFocusWin, RevertToParent, CurrentTime );
X11DRV_Synchronize();
break;
}
}
}
EVENT_FocusIn( hWnd, xfocChange );
case FocusIn:
EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
break;
}
case FocusOut:
{
/* Save the last window which had the focus */
XFocusChangeEvent *xfocChange = (XFocusChangeEvent*)event;
glastXFocusWin = xfocChange->window;
if (!hWnd) return;
if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
break;
}
case Expose:
EVENT_Expose( hWnd, (XExposeEvent *)event );
break;
case GraphicsExpose:
EVENT_GraphicsExpose( hWnd, (XGraphicsExposeEvent *)event );
EVENT_Expose( hWnd, &event->xexpose );
break;
case ConfigureNotify:
if (!hWnd) return;
EVENT_ConfigureNotify( hWnd, (XConfigureEvent*)event );
X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
break;
case SelectionRequest:
......@@ -414,23 +346,15 @@ static void EVENT_ProcessEvent( XEvent *event )
EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
break;
#if 0
case EnterNotify:
EVENT_EnterNotify( hWnd, (XCrossingEvent *) event );
break;
#endif
case NoExpose:
break;
case MapNotify:
if (!hWnd) return;
EVENT_MapNotify( hWnd, (XMapEvent *)event );
X11DRV_MapNotify( hWnd, (XMapEvent *)event );
break;
case UnmapNotify:
if (!hWnd) return;
EVENT_UnmapNotify( hWnd, (XUnmapEvent *)event );
X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
break;
case MappingNotify:
......@@ -446,136 +370,6 @@ static void EVENT_ProcessEvent( XEvent *event )
}
/***********************************************************************
* EVENT_QueryZOrder
*
* Synchronize internal z-order with the window manager's.
*/
static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
{
/* return TRUE if we have at least two managed windows */
for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
if( ((*pWndA)->dwExStyle & WS_EX_MANAGED) &&
((*pWndA)->dwStyle & WS_VISIBLE )) break;
if( *pWndA )
for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
if( ((*pWndB)->dwExStyle & WS_EX_MANAGED) &&
((*pWndB)->dwStyle & WS_VISIBLE )) break;
return ((*pWndB) != NULL);
}
static Window __get_common_ancestor( Display *display, Window A, Window B,
Window** children, unsigned* total )
{
/* find the real root window */
Window root, *childrenB;
unsigned totalB;
while( A != B && A && B )
{
TSXQueryTree( display, A, &root, &A, children, total );
TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
if( childrenB ) TSXFree( childrenB );
if( *children ) TSXFree( *children ), *children = NULL;
}
if( A && B )
{
TSXQueryTree( display, A, &root, &B, children, total );
return A;
}
return 0 ;
}
static Window __get_top_decoration( Display *display, Window w, Window ancestor )
{
Window* children, root, prev = w, parent = w;
unsigned total;
do
{
w = parent;
TSXQueryTree( display, w, &root, &parent, &children, &total );
if( children ) TSXFree( children );
} while( parent && parent != ancestor );
TRACE("\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
return ( parent ) ? w : 0 ;
}
static unsigned __td_lookup( Window w, Window* list, unsigned max )
{
unsigned i;
for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
return i;
}
static HWND EVENT_QueryZOrder( Display *display, HWND hWndCheck)
{
HWND hwndInsertAfter = HWND_TOP;
WND *pWndCheck = WIN_FindWndPtr(hWndCheck);
WND *pDesktop = WIN_GetDesktop();
WND *pWnd, *pWndZ = WIN_LockWndPtr(pDesktop->child);
Window w, parent, *children = NULL;
unsigned total, check, pos, best;
if( !__check_query_condition(&pWndZ, &pWnd) )
{
WIN_ReleaseWndPtr(pWndCheck);
WIN_ReleaseWndPtr(pDesktop->child);
WIN_ReleaseDesktop();
return hwndInsertAfter;
}
WIN_LockWndPtr(pWndZ);
WIN_LockWndPtr(pWnd);
WIN_ReleaseWndPtr(pDesktop->child);
WIN_ReleaseDesktop();
parent = __get_common_ancestor( display, X11DRV_WND_GetXWindow(pWndZ),
X11DRV_WND_GetXWindow(pWnd),
&children, &total );
if( parent && children )
{
/* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
w = __get_top_decoration( display, X11DRV_WND_GetXWindow(pWndCheck), parent );
if( w != children[total-1] ) /* check if at the top */
{
/* X child at index 0 is at the bottom, at index total-1 is at the top */
check = __td_lookup( w, children, total );
best = total;
for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
{
/* go through all windows in Wine z-order... */
if( pWnd != pWndCheck )
{
if( !(pWnd->dwExStyle & WS_EX_MANAGED) ||
!(w = __get_top_decoration( display, X11DRV_WND_GetXWindow(pWnd), parent )) )
continue;
pos = __td_lookup( w, children, total );
if( pos < best && pos > check )
{
/* find a nearest Wine window precedes
* pWndCheck in the real z-order... */
best = pos;
hwndInsertAfter = pWnd->hwndSelf;
}
if( best - check == 1 ) break;
}
}
}
}
if( children ) TSXFree( children );
WIN_ReleaseWndPtr(pWnd);
WIN_ReleaseWndPtr(pWndZ);
WIN_ReleaseWndPtr(pWndCheck);
return hwndInsertAfter;
}
/***********************************************************************
* X11DRV_EVENT_XStateToKeyState
*
* Translate a X event state (Button1Mask, ShiftMask, etc...) to
......@@ -593,62 +387,74 @@ WORD X11DRV_EVENT_XStateToKeyState( int state )
return kstate;
}
/***********************************************************************
* EVENT_Expose
*/
static void EVENT_Expose( HWND hWnd, XExposeEvent *event )
static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
{
RECT rect;
int offx = 0,offy = 0;
RECT rect;
struct x11drv_win_data *data;
int flags = RDW_INVALIDATE | RDW_ERASE;
WND *win;
WND *pWnd = WIN_FindWndPtr(hWnd);
/* Make position relative to client area instead of window */
offx = (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
offy = (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
TRACE( "win %x (%lx) %d,%d %dx%d\n",
hwnd, event->window, event->x, event->y, event->width, event->height );
rect.left = event->x - offx;
rect.top = event->y - offy;
rect.left = event->x;
rect.top = event->y;
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
if (!(win = WIN_FindWndPtr(hwnd))) return;
data = win->pDriverData;
WIN_ReleaseWndPtr(pWnd);
RedrawWindow( hWnd, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
if (event->window != data->client_window) /* whole window or icon window */
{
flags |= RDW_FRAME;
/* make position relative to client area instead of window */
OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
}
if (event->count == 0)
SendNotifyMessageA(hWnd,WM_SYNCPAINT, 0, 0);
/* find the top level parent that doesn't clip children and invalidate the area */
/* on the parent (which will invalidate all the children too) */
while (win->parent && win->parent->hwndSelf != GetDesktopWindow() &&
!(win->parent->dwStyle & WS_CLIPCHILDREN))
{
OffsetRect( &rect, win->rectClient.left, win->rectClient.top );
WIN_UpdateWndPtr( &win, win->parent );
flags &= ~RDW_FRAME; /* parent will invalidate children frame anyway */
}
hwnd = win->hwndSelf;
WIN_ReleaseWndPtr(win);
RedrawWindow( hwnd, &rect, 0, flags );
}
/***********************************************************************
* EVENT_GraphicsExpose
*
* This is needed when scrolling area is partially obscured
* by non-Wine X window.
*/
static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event )
/* get the coordinates of a mouse event */
static void get_coords( HWND *hwnd, Window window, int x, int y, POINT *pt )
{
RECT rect;
int offx = 0,offy = 0;
WND *pWnd = WIN_FindWndPtr(hWnd);
/* Make position relative to client area instead of window */
offx = (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
offy = (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
struct x11drv_win_data *data;
WND *win;
rect.left = event->x - offx;
rect.top = event->y - offy;
if (!(win = WIN_FindWndPtr( *hwnd ))) return;
data = win->pDriverData;
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
WIN_ReleaseWndPtr(pWnd);
RedrawWindow( hWnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
if (event->count == 0)
SendNotifyMessageA(hWnd,WM_SYNCPAINT, 0, 0);
if (window == data->whole_window)
{
x -= data->client_rect.left;
y -= data->client_rect.top;
}
while (win->parent && win->parent->hwndSelf != GetDesktopWindow())
{
x += win->rectClient.left;
y += win->rectClient.top;
WIN_UpdateWndPtr( &win, win->parent );
}
pt->x = x + win->rectClient.left;
pt->y = y + win->rectClient.top;
*hwnd = win->hwndSelf;
WIN_ReleaseWndPtr( win );
}
......@@ -659,10 +465,9 @@ static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event )
*/
static void EVENT_Key( HWND hWnd, XKeyEvent *event )
{
WND *pWnd = WIN_FindWndPtr(hWnd);
X11DRV_KEYBOARD_HandleEvent( pWnd, event );
WIN_ReleaseWndPtr(pWnd);
POINT pt;
get_coords( &hWnd, event->window, event->x, event->y, &pt );
X11DRV_KEYBOARD_HandleEvent( event, pt.x, pt.y );
}
......@@ -671,22 +476,22 @@ static void EVENT_Key( HWND hWnd, XKeyEvent *event )
*/
static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event )
{
if (current_input_type == X11DRV_INPUT_ABSOLUTE) {
WND *pWnd = WIN_FindWndPtr(hWnd);
int xOffset = pWnd? pWnd->rectWindow.left : 0;
int yOffset = pWnd? pWnd->rectWindow.top : 0;
WIN_ReleaseWndPtr(pWnd);
X11DRV_SendEvent( MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
xOffset + event->x, yOffset + event->y,
X11DRV_EVENT_XStateToKeyState( event->state ),
event->time - X11DRV_server_startticks, hWnd);
} else {
X11DRV_SendEvent( MOUSEEVENTF_MOVE,
event->x_root, event->y_root,
X11DRV_EVENT_XStateToKeyState( event->state ),
event->time - X11DRV_server_startticks, hWnd);
}
POINT pt;
if (current_input_type == X11DRV_INPUT_ABSOLUTE)
{
get_coords( &hWnd, event->window, event->x, event->y, &pt );
X11DRV_SendEvent( MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
X11DRV_EVENT_XStateToKeyState( event->state ),
event->time - X11DRV_server_startticks, hWnd);
}
else
{
X11DRV_SendEvent( MOUSEEVENTF_MOVE,
event->x_root, event->y_root,
X11DRV_EVENT_XStateToKeyState( event->state ),
event->time - X11DRV_server_startticks, hWnd);
}
}
......@@ -695,51 +500,46 @@ static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event )
*/
static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event )
{
static WORD statusCodes[NB_BUTTONS] =
{ MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_WHEEL, MOUSEEVENTF_WHEEL};
int buttonNum = event->button - 1;
WND *pWnd = WIN_FindWndPtr(hWnd);
int xOffset = pWnd? pWnd->rectWindow.left : 0;
int yOffset = pWnd? pWnd->rectWindow.top : 0;
WORD keystate,wData = 0;
WIN_ReleaseWndPtr(pWnd);
static const WORD statusCodes[NB_BUTTONS] = { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN,
MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_WHEEL,
MOUSEEVENTF_WHEEL};
int buttonNum = event->button - 1;
WORD keystate, wData = 0;
POINT pt;
if (buttonNum >= NB_BUTTONS) return;
if (buttonNum >= NB_BUTTONS) return;
/*
* Get the compatible keystate
*/
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
/*
* Make sure that the state of the button that was just
* pressed is "down".
*/
switch (buttonNum)
{
get_coords( &hWnd, event->window, event->x, event->y, &pt );
/* Get the compatible keystate */
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
/*
* Make sure that the state of the button that was just
* pressed is "down".
*/
switch (buttonNum)
{
case 0:
keystate |= MK_LBUTTON;
break;
keystate |= MK_LBUTTON;
break;
case 1:
keystate |= MK_MBUTTON;
break;
keystate |= MK_MBUTTON;
break;
case 2:
keystate |= MK_RBUTTON;
break;
keystate |= MK_RBUTTON;
break;
case 3:
wData = WHEEL_DELTA;
break;
case 4:
wData = -WHEEL_DELTA;
break;
}
X11DRV_SendEvent( statusCodes[buttonNum],
xOffset + event->x, yOffset + event->y,
MAKEWPARAM(keystate,wData),
event->time - X11DRV_server_startticks, hWnd);
}
X11DRV_SendEvent( statusCodes[buttonNum], pt.x, pt.y,
MAKEWPARAM(keystate,wData),
event->time - X11DRV_server_startticks, hWnd);
}
......@@ -748,45 +548,39 @@ static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event )
*/
static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event )
{
static WORD statusCodes[NB_BUTTONS] =
{ MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
int buttonNum = event->button - 1;
WND *pWnd = WIN_FindWndPtr(hWnd);
int xOffset = pWnd? pWnd->rectWindow.left : 0;
int yOffset = pWnd? pWnd->rectWindow.top : 0;
WORD keystate;
WIN_ReleaseWndPtr(pWnd);
if (buttonNum >= NB_BUTTONS) return;
/*
* Get the compatible keystate
*/
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
static const WORD statusCodes[NB_BUTTONS] = { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP,
MOUSEEVENTF_RIGHTUP, 0, 0 };
int buttonNum = event->button - 1;
WORD keystate;
POINT pt;
/*
* Make sure that the state of the button that was just
* released is "up".
*/
switch (buttonNum)
{
if (buttonNum >= NB_BUTTONS) return;
get_coords( &hWnd, event->window, event->x, event->y, &pt );
/* Get the compatible keystate */
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
/*
* Make sure that the state of the button that was just
* released is "up".
*/
switch (buttonNum)
{
case 0:
keystate &= ~MK_LBUTTON;
break;
keystate &= ~MK_LBUTTON;
break;
case 1:
keystate &= ~MK_MBUTTON;
break;
keystate &= ~MK_MBUTTON;
break;
case 2:
keystate &= ~MK_RBUTTON;
break;
default:
return;
}
X11DRV_SendEvent( statusCodes[buttonNum],
xOffset + event->x, yOffset + event->y,
keystate, event->time - X11DRV_server_startticks, hWnd);
keystate &= ~MK_RBUTTON;
break;
default:
return;
}
X11DRV_SendEvent( statusCodes[buttonNum], pt.x, pt.y,
keystate, event->time - X11DRV_server_startticks, hWnd);
}
......@@ -795,12 +589,42 @@ static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event )
*/
static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
{
if (event->detail != NotifyPointer)
if (hWnd != GetForegroundWindow())
WND *pWndLastFocus;
XWindowAttributes win_attr;
BOOL bIsDisabled;
if (!hWnd) return;
bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
/* If the window has been disabled and we are in managed mode,
* revert the X focus back to the last focus window. This is to disallow
* the window manager from switching focus away while the app is
* in a modal state.
*/
if ( Options.managed && bIsDisabled && glastXFocusWin)
{
/* Change focus only if saved focus window is registered and viewable */
wine_tsx11_lock();
if (XFindContext( event->display, glastXFocusWin, winContext,
(char **)&pWndLastFocus ) == 0 )
{
SetForegroundWindow( hWnd );
X11DRV_KEYBOARD_UpdateState();
if (XGetWindowAttributes( event->display, glastXFocusWin, &win_attr ) &&
(win_attr.map_state == IsViewable) )
{
XSetInputFocus( event->display, glastXFocusWin, RevertToParent, CurrentTime );
wine_tsx11_unlock();
return;
}
}
wine_tsx11_unlock();
}
if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
{
SetForegroundWindow( hWnd );
X11DRV_KEYBOARD_UpdateState();
}
}
......@@ -811,25 +635,27 @@ static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
*/
static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
{
if (event->detail != NotifyPointer)
if (hWnd == GetForegroundWindow())
{
SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
/* Save the last window which had the focus */
glastXFocusWin = event->window;
if (!hWnd) return;
if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
/* don't reset the foreground window, if the window who's
if (event->detail != NotifyPointer && hWnd == GetForegroundWindow())
{
/* don't reset the foreground window, if the window which is
getting the focus is a Wine window */
if (!X11DRV_CheckFocus())
{
/* Abey : 6-Oct-99. Check again if the focus out window is the
Foreground window, because in most cases the messages sent
above must have already changed the foreground window, in which
case we don't have to change the foreground window to 0 */
if (hWnd == GetForegroundWindow())
SetForegroundWindow( 0 );
}
}
if (!X11DRV_CheckFocus())
{
SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
/* Abey : 6-Oct-99. Check again if the focus out window is the
Foreground window, because in most cases the messages sent
above must have already changed the foreground window, in which
case we don't have to change the foreground window to 0 */
if (hWnd == GetForegroundWindow())
SetForegroundWindow( 0 );
}
}
}
/**********************************************************************
......@@ -849,100 +675,6 @@ static BOOL X11DRV_CheckFocus(void)
return TRUE;
}
/**********************************************************************
* EVENT_GetGeometry
*
* Helper function for ConfigureNotify handling.
* Get the new geometry of a window relative to the root window.
*/
static void EVENT_GetGeometry( Display *display, Window win, int *px, int *py,
unsigned int *pwidth, unsigned int *pheight )
{
Window root, top;
int x, y, width, height, border, depth;
wine_tsx11_lock();
/* Get the geometry of the window */
XGetGeometry( display, win, &root, &x, &y, &width, &height,
&border, &depth );
/* Translate the window origin to root coordinates */
XTranslateCoordinates( display, win, root, 0, 0, &x, &y, &top );
wine_tsx11_unlock();
*px = x;
*py = y;
*pwidth = width;
*pheight = height;
}
/**********************************************************************
* EVENT_ConfigureNotify
*
* The ConfigureNotify event is only selected on top-level windows
* when the -managed flag is used.
*/
static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event )
{
RECT rectWindow;
int x, y, flags = 0;
unsigned int width, height;
HWND newInsertAfter, oldInsertAfter;
/* Get geometry and Z-order according to X */
EVENT_GetGeometry( event->display, event->window, &x, &y, &width, &height );
newInsertAfter = EVENT_QueryZOrder( event->display, hWnd );
/* Get geometry and Z-order according to Wine */
/*
* Needs to find the first Visible Window above the current one
*/
oldInsertAfter = hWnd;
for (;;)
{
oldInsertAfter = GetWindow( oldInsertAfter, GW_HWNDPREV );
if (!oldInsertAfter)
{
oldInsertAfter = HWND_TOP;
break;
}
if (GetWindowLongA( oldInsertAfter, GWL_STYLE ) & WS_VISIBLE) break;
}
/* Compare what has changed */
GetWindowRect( hWnd, &rectWindow );
if ( rectWindow.left == x && rectWindow.top == y )
flags |= SWP_NOMOVE;
else
TRACE_(win)( "%04x moving from (%d,%d) to (%d,%d)\n", hWnd,
rectWindow.left, rectWindow.top, x, y );
if ( rectWindow.right - rectWindow.left == width
&& rectWindow.bottom - rectWindow.top == height )
flags |= SWP_NOSIZE;
else
TRACE_(win)( "%04x resizing from (%d,%d) to (%d,%d)\n", hWnd,
rectWindow.right - rectWindow.left,
rectWindow.bottom - rectWindow.top, width, height );
if ( newInsertAfter == oldInsertAfter )
flags |= SWP_NOZORDER;
else
TRACE_(win)( "%04x restacking from after %04x to after %04x\n", hWnd,
oldInsertAfter, newInsertAfter );
/* If anything changed, call SetWindowPos */
if ( flags != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER) )
SetWindowPos( hWnd, newInsertAfter, x, y, width, height,
flags | SWP_NOACTIVATE | SWP_WINE_NOHOSTMOVE );
}
/***********************************************************************
* EVENT_SelectionRequest_TARGETS
......@@ -1524,7 +1256,7 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
pWnd = WIN_FindWndPtr(hWnd);
TSXQueryPointer( event->display, X11DRV_WND_GetXWindow(pWnd), &w_aux_root, &w_aux_child,
TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
&x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
(unsigned int*)&aux_long);
......@@ -1743,22 +1475,24 @@ static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
if ((event->message_type == wmProtocols) &&
(((Atom) event->data.l[0]) == wmDeleteWindow))
{
/* Ignore the delete window request if the window has been disabled
* and we are in managed mode. This is to disallow applications from
* being closed by the window manager while in a modal state.
*/
BOOL bIsDisabled;
bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
if ( !Options.managed || !bIsDisabled )
PostMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
/* Ignore the delete window request if the window has been disabled */
if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
}
else if (event->message_type == dndProtocol)
{
/* query window (drag&drop event contains only drag window) */
Window root, child;
int root_x, root_y, child_x, child_y;
unsigned int u;
TSXQueryPointer( event->display, root_window, &root, &child,
&root_x, &root_y, &child_x, &child_y, &u);
if (TSXFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) return;
if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
EVENT_DropFromOffiX(hWnd, event);
else if (event->data.l[0] == DndURL)
EVENT_DropURLs(hWnd, event);
}
else if ( event->message_type == dndProtocol &&
(event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
EVENT_DropFromOffiX(hWnd, event);
else if ( event->message_type == dndProtocol &&
event->data.l[0] == DndURL )
EVENT_DropURLs(hWnd, event);
else {
#if 0
/* enable this if you want to see the message */
......@@ -1782,65 +1516,6 @@ static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
}
}
/**********************************************************************
* EVENT_EnterNotify
*
* Install colormap when Wine window is focused in
* self-managed mode with private colormap
*/
#if 0
void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event )
{
if( !Options.managed && root_window == DefaultRootWindow(event->display) &&
(COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus() )
TSXInstallColormap( event->display, X11DRV_PALETTE_GetColormap() );
}
#endif
/**********************************************************************
* EVENT_MapNotify
*/
void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
{
HWND hwndFocus = GetFocus();
WND *wndFocus = WIN_FindWndPtr(hwndFocus);
WND *pWnd = WIN_FindWndPtr(hWnd);
if (pWnd && (pWnd->dwExStyle & WS_EX_MANAGED))
{
DCE_InvalidateDCE( pWnd, &pWnd->rectWindow );
pWnd->dwStyle &= ~WS_MINIMIZE;
pWnd->dwStyle |= WS_VISIBLE;
WIN_InternalShowOwnedPopups(hWnd,TRUE,TRUE);
}
WIN_ReleaseWndPtr(pWnd);
if (hwndFocus && IsChild( hWnd, hwndFocus ))
X11DRV_SetFocus(hwndFocus);
WIN_ReleaseWndPtr(wndFocus);
return;
}
/**********************************************************************
* EVENT_UnmapNotify
*/
void EVENT_UnmapNotify( HWND hWnd, XUnmapEvent *event )
{
WND *pWnd = WIN_FindWndPtr(hWnd);
if (pWnd && (pWnd->dwExStyle & WS_EX_MANAGED))
{
EndMenu();
if( pWnd->dwStyle & WS_VISIBLE )
{
pWnd->dwStyle |= WS_MINIMIZE;
pWnd->dwStyle &= ~WS_VISIBLE;
WIN_InternalShowOwnedPopups(hWnd,FALSE,TRUE);
}
}
WIN_ReleaseWndPtr(pWnd);
}
/***********************************************************************
* EVENT_MappingNotify
......
......@@ -708,7 +708,7 @@ void X11DRV_KEYBOARD_UpdateState ( void )
*
* Handle a X key event
*/
void X11DRV_KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
void X11DRV_KEYBOARD_HandleEvent( XKeyEvent *event, int x, int y )
{
char Str[24];
KeySym keysym;
......@@ -717,8 +717,6 @@ void X11DRV_KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
static BOOL force_extended = FALSE; /* hack for AltGr translation */
int ascii_chars;
INT event_x = (pWnd? pWnd->rectWindow.left : 0) + event->x;
INT event_y = (pWnd? pWnd->rectWindow.top : 0) + event->y;
DWORD event_time = event->time - X11DRV_server_startticks;
/* this allows support for dead keys */
......@@ -745,11 +743,11 @@ void X11DRV_KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
{
TRACE_(key)("Alt Gr key event received\n");
event->keycode = kcControl; /* Simulate Control */
X11DRV_KEYBOARD_HandleEvent( pWnd, event );
X11DRV_KEYBOARD_HandleEvent( event, x, y );
event->keycode = kcAlt; /* Simulate Alt */
force_extended = TRUE;
X11DRV_KEYBOARD_HandleEvent( pWnd, event );
X11DRV_KEYBOARD_HandleEvent( event, x, y );
force_extended = FALSE;
/* Here we save the pressed/released state of the AltGr key, to be able to
......@@ -783,13 +781,11 @@ void X11DRV_KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
switch (vkey & 0xff)
{
case VK_NUMLOCK:
KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_x, event_y,
event_time );
KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, x, y, event_time );
break;
case VK_CAPITAL:
TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_x, event_y,
event_time );
KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, x, y, event_time );
TRACE("State after : %#.2x\n",pKeyStateTable[vkey]);
break;
default:
......@@ -797,19 +793,15 @@ void X11DRV_KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
{
TRACE("Adjusting NumLock state. \n");
KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_x, event_y,
event_time );
KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_x, event_y,
event_time );
KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, x, y, event_time );
KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, x, y, event_time );
}
/* Adjust the CAPSLOCK state if it has been changed outside wine */
if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
{
TRACE("Adjusting Caps Lock state.\n");
KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_x, event_y,
event_time );
KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_x, event_y,
event_time );
KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, x, y, event_time );
KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, x, y, event_time );
}
/* Not Num nor Caps : end of intermediary states for both. */
NumState = FALSE;
......@@ -823,8 +815,7 @@ void X11DRV_KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
if ( vkey & 0x100 ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
if ( force_extended ) dwFlags |= KEYEVENTF_WINE_FORCEEXTENDED;
KEYBOARD_SendEvent( vkey & 0xff, bScan, dwFlags,
event_x, event_y, event_time );
KEYBOARD_SendEvent( vkey & 0xff, bScan, dwFlags, x, y, event_time );
}
}
}
......
......@@ -154,13 +154,8 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
/* set the cursor of a window; helper for X11DRV_SetCursor */
static BOOL CALLBACK set_win_cursor( HWND hwnd, LPARAM cursor )
{
WND *wndPtr = WIN_FindWndPtr(hwnd);
if (wndPtr)
{
Window win = X11DRV_WND_GetXWindow(wndPtr);
if (win) TSXDefineCursor( thread_display(), win, (Cursor)cursor );
}
WIN_ReleaseWndPtr( wndPtr );
Window win = X11DRV_get_whole_window( hwnd );
if (win) TSXDefineCursor( thread_display(), win, (Cursor)cursor );
return TRUE;
}
......
......@@ -40,37 +40,11 @@ extern Atom wmChangeState;
WND_DRIVER X11DRV_WND_Driver =
{
X11DRV_WND_ForceWindowRaise,
X11DRV_WND_SetHostAttr
X11DRV_WND_ForceWindowRaise
};
/***********************************************************************
* X11DRV_WND_GetXWindow
*
* Return the X window associated to a window.
*/
Window X11DRV_WND_GetXWindow(WND *wndPtr)
{
return wndPtr && wndPtr->pDriverData ?
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
}
/***********************************************************************
* X11DRV_WND_FindXWindow
*
* Return the the first X window associated to a window chain.
*/
Window X11DRV_WND_FindXWindow(WND *wndPtr)
{
while (wndPtr &&
!((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
wndPtr = wndPtr->parent;
return wndPtr ?
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
}
/***********************************************************************
* X11DRV_WND_IsZeroSizeWnd
*
* Return TRUE if the window has a height or widht less or equal to 0
......@@ -101,7 +75,7 @@ void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
return;
}
if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->dwExStyle & WS_EX_MANAGED) )
if( !wndPtr || !get_whole_window(wndPtr) || (wndPtr->dwExStyle & WS_EX_MANAGED) )
{
WIN_ReleaseDesktop();
return;
......@@ -114,9 +88,9 @@ void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
winChanges.stack_mode = Above;
while (wndPtr)
{
if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr) && X11DRV_WND_GetXWindow(wndPtr) )
TSXReconfigureWMWindow( thread_display(), X11DRV_WND_GetXWindow(wndPtr), 0,
CWStackMode, &winChanges );
if ( !X11DRV_WND_IsZeroSizeWnd(wndPtr) && get_whole_window(wndPtr) )
TSXReconfigureWMWindow( thread_display(), get_whole_window(wndPtr), 0,
CWStackMode, &winChanges );
wndPrev = pDesktop->child;
if (wndPrev == wndPtr) break;
......@@ -126,345 +100,3 @@ void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
}
WIN_ReleaseDesktop();
}
/***********************************************************************
* X11DRV_WND_FindDesktopXWindow [Internal]
*
* Find the actual X window which needs be restacked.
* Used by X11DRV_WND_SetWindowPos().
*/
static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
{
if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
return X11DRV_WND_GetXWindow(wndPtr);
else
{
Window window, root, parent, *children;
int nchildren;
window = X11DRV_WND_GetXWindow(wndPtr);
for (;;)
{
TSXQueryTree( thread_display(), window, &root, &parent,
&children, &nchildren );
TSXFree( children );
if (parent == root)
return window;
window = parent;
}
}
}
/***********************************************************************
* WINPOS_SetXWindowPos
*
* SetWindowPos() for an X window. Used by the real SetWindowPos().
*/
void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangePos)
{
XWindowChanges winChanges;
Display *display = thread_display();
int changeMask = 0;
BOOL isZeroSizeWnd = FALSE;
BOOL forceMapWindow = FALSE;
WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
if ( !winposPtr ) return;
/* find out if after this function we will end out with a zero-size window */
if (X11DRV_WND_IsZeroSizeWnd(winposPtr))
{
/* if current size is 0, and no resizing */
if (winpos->flags & SWP_NOSIZE)
isZeroSizeWnd = TRUE;
else if ((winpos->cx > 0) && (winpos->cy > 0))
{
/* if this function is setting a new size > 0 for the window, we
should map the window if WS_VISIBLE is set */
if ((winposPtr->dwStyle & WS_VISIBLE) && !(winpos->flags & SWP_HIDEWINDOW))
forceMapWindow = TRUE;
}
}
/* if resizing to 0 */
if ( !(winpos->flags & SWP_NOSIZE) && ((winpos->cx <= 0) || (winpos->cy <= 0)) )
isZeroSizeWnd = TRUE;
if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happen!!! */
if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
{
if(X11DRV_WND_GetXWindow(wndPtr))
TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
}
if(bChangePos)
{
if ( !(winpos->flags & SWP_NOSIZE))
{
winChanges.width = (winpos->cx > 0 ) ? winpos->cx : 1;
winChanges.height = (winpos->cy > 0 ) ? winpos->cy : 1;
changeMask |= CWWidth | CWHeight;
/* Tweak dialog window size hints */
if ((winposPtr->dwExStyle & WS_EX_MANAGED) &&
HAS_DLGFRAME(winposPtr->dwStyle,winposPtr->dwExStyle))
{
XSizeHints *size_hints = TSXAllocSizeHints();
if (size_hints)
{
long supplied_return;
TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
&supplied_return, XA_WM_NORMAL_HINTS);
size_hints->min_width = size_hints->max_width = winpos->cx;
size_hints->min_height = size_hints->max_height = winpos->cy;
TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
XA_WM_NORMAL_HINTS );
TSXFree(size_hints);
}
}
}
if (!(winpos->flags & SWP_NOMOVE))
{
winChanges.x = winpos->x;
winChanges.y = winpos->y;
changeMask |= CWX | CWY;
}
if (!(winpos->flags & SWP_NOZORDER) && !isZeroSizeWnd)
{
winChanges.stack_mode = Below;
changeMask |= CWStackMode;
if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
else if (winpos->hwndInsertAfter != HWND_BOTTOM)
{
WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
Window stack[2];
/* If the window where we should do the insert is zero-sized (not mapped)
don't used this window since it will possibly crash the X server,
use the "non zero-sized" window above */
if (X11DRV_WND_IsZeroSizeWnd(insertPtr))
{
/* find the window on top of the zero sized window */
WND *pDesktop = WIN_GetDesktop();
WND *wndPrev = pDesktop->child;
WND *wndZeroSized = insertPtr;
while (1)
{
if (wndPrev == wndZeroSized)
break; /* zero-sized window is on top */
while (wndPrev && (wndPrev->next != wndZeroSized))
wndPrev = wndPrev->next;
/* check if the window found is not zero-sized */
if (X11DRV_WND_IsZeroSizeWnd(wndPrev))
{
wndZeroSized = wndPrev; /* restart the search */
wndPrev = pDesktop->child;
}
else
break; /* "above" window is found */
}
WIN_ReleaseDesktop();
if (wndPrev == wndZeroSized)
{
/* the zero-sized window is on top */
/* so set the window on top */
winChanges.stack_mode = Above;
}
else
{
stack[0] = X11DRV_WND_FindDesktopXWindow( wndPrev );
stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
TSXRestackWindows(display, stack, 2);
changeMask &= ~CWStackMode;
}
}
else /* Normal behavior, windows are not zero-sized */
{
stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
TSXRestackWindows(display, stack, 2);
changeMask &= ~CWStackMode;
}
WIN_ReleaseWndPtr(insertPtr);
}
}
if (changeMask && X11DRV_WND_GetXWindow(winposPtr))
{
TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
if( winposPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW) )
X11DRV_WND_SetGravity( winposPtr, ForgetGravity );
}
}
/* don't map the window if it's a zero size window */
if ( ((winpos->flags & SWP_SHOWWINDOW) && !isZeroSizeWnd) || forceMapWindow )
{
if(X11DRV_WND_GetXWindow(wndPtr))
TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
}
WIN_ReleaseWndPtr(winposPtr);
}
/*****************************************************************
* X11DRV_WND_SurfaceCopy
*
* Copies rect to (rect.left + dx, rect.top + dy).
*/
void X11DRV_WND_SurfaceCopy(WND* wndPtr, HDC hdc, INT dx, INT dy,
const RECT *rect, BOOL bUpdate)
{
X11DRV_PDEVICE *physDev;
POINT dst, src;
DC *dcPtr = DC_GetDCPtr( hdc );
if (!dcPtr) return;
physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
dst.x = (src.x = dcPtr->DCOrgX + rect->left) + dx;
dst.y = (src.y = dcPtr->DCOrgY + rect->top) + dy;
wine_tsx11_lock();
if (bUpdate) /* handles non-Wine windows hanging over the copied area */
XSetGraphicsExposures( gdi_display, physDev->gc, True );
XSetFunction( gdi_display, physDev->gc, GXcopy );
XCopyArea( gdi_display, physDev->drawable, physDev->drawable, physDev->gc,
src.x, src.y, rect->right - rect->left, rect->bottom - rect->top,
dst.x, dst.y );
if (bUpdate)
XSetGraphicsExposures( gdi_display, physDev->gc, False );
wine_tsx11_unlock();
GDI_ReleaseObj( hdc );
if (bUpdate) /* Make sure exposure events have been processed */
X11DRV_Synchronize();
}
/***********************************************************************
* X11DRV_SetWMHint
*/
static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
{
XWMHints* wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
if (!wm_hints) wm_hints = TSXAllocWMHints();
if (wm_hints)
{
wm_hints->flags = hint;
switch( hint )
{
case InputHint:
wm_hints->input = val;
break;
case StateHint:
wm_hints->initial_state = val;
break;
case IconPixmapHint:
wm_hints->icon_pixmap = (Pixmap)val;
break;
case IconWindowHint:
wm_hints->icon_window = (Window)val;
break;
}
TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
TSXFree(wm_hints);
return TRUE;
}
return FALSE;
}
void X11DRV_WND_SetGravity( WND* wnd, int value )
{
X11DRV_WND_DATA *data = wnd->pDriverData;
if (data && data->window && data->bit_gravity != value )
{
XSetWindowAttributes win_attr;
win_attr.bit_gravity = value;
data->bit_gravity = value;
TSXChangeWindowAttributes( thread_display(), data->window, CWBitGravity, &win_attr );
}
}
/***********************************************************************
* X11DRV_WND_SetHostAttr
*
* This function returns TRUE if the attribute is supported and the
* action was successful. Otherwise it should return FALSE and Wine will try
* to get by without the functionality provided by the host window system.
*/
BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
{
Window w;
if( (w = X11DRV_WND_GetXWindow(wnd)) )
{
Display *display = thread_display();
switch( ha )
{
case HAK_ICONICSTATE: /* called when a window is minimized/restored */
/* don't do anything if it'a zero size window */
if (X11DRV_WND_IsZeroSizeWnd(wnd))
return TRUE;
if( (wnd->dwExStyle & WS_EX_MANAGED) )
{
if( value )
{
if( wnd->dwStyle & WS_VISIBLE )
{
XClientMessageEvent ev;
/* FIXME: set proper icon */
ev.type = ClientMessage;
ev.display = display;
ev.message_type = wmChangeState;
ev.format = 32;
ev.data.l[0] = IconicState;
ev.window = w;
if( TSXSendEvent (display, DefaultRootWindow(display),
True, (SubstructureRedirectMask | SubstructureNotifyMask), (XEvent*)&ev))
{
XEvent xe;
TSXFlush (display);
while( !TSXCheckTypedWindowEvent( display, w, UnmapNotify, &xe) );
}
else
break;
}
else
X11DRV_SetWMHint( display, wnd, StateHint, IconicState );
}
else
{
if( !(wnd->flags & WS_VISIBLE) )
X11DRV_SetWMHint( display, wnd, StateHint, NormalState );
else
{
XEvent xe;
TSXMapWindow(display, w );
while( !TSXCheckTypedWindowEvent( display, w, MapNotify, &xe) );
}
}
return TRUE;
}
break;
}
}
return FALSE;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment