Moved most of the implementation of SetWindowPos and SetDrawable into

the user driver, and the corresponding code into the dlls/x11drv
directory. Moved a few functions out of the window driver into the
user driver. Plus a few related cleanups.
This commit is contained in:
Alexandre Julliard 2001-04-24 23:28:52 +00:00
parent 56a45b2049
commit 9ae0fe54b0
29 changed files with 2742 additions and 2474 deletions

View file

@ -239,7 +239,7 @@ BOOL TTYDRV_DC_CreateDC(DC *dc, LPCSTR driver, LPCSTR device,
GDI_ReleaseObj( dc->hBitmap );
} else {
physDev->window = TTYDRV_GetRootWindow();
physDev->window = root_window;
physDev->cellWidth = cell_width;
physDev->cellHeight = cell_height;

View file

@ -29,7 +29,6 @@ struct tagWND;
struct tagCURSORICONINFO;
struct tagCREATESTRUCTA;
struct tagWINDOWPOS;
struct tagKEYBOARD_CONFIG;
struct DIDEVICEOBJECTDATA;
#if defined(HAVE_LIBCURSES) || defined(HAVE_LIBNCURSES)
@ -127,36 +126,17 @@ extern int cell_height;
extern int screen_rows;
extern int screen_cols;
extern WINDOW *root_window;
static inline WINDOW *TTYDRV_GetRootWindow(void) { return root_window; }
/* TTY windows driver */
extern struct tagWND_DRIVER TTYDRV_WND_Driver;
typedef struct tagTTYDRV_WND_DATA {
WINDOW *window;
} TTYDRV_WND_DATA;
WINDOW *TTYDRV_WND_GetCursesWindow(struct tagWND *wndPtr);
extern HANDLE TTYDRV_LoadOEMResource(WORD resid, WORD type);
extern void TTYDRV_WND_Initialize(struct tagWND *wndPtr);
extern void TTYDRV_WND_Finalize(struct tagWND *wndPtr);
extern BOOL TTYDRV_WND_CreateDesktopWindow(struct tagWND *wndPtr);
extern BOOL TTYDRV_WND_CreateWindow(struct tagWND *wndPtr, struct tagCREATESTRUCTA *cs, BOOL bUnicode);
extern BOOL TTYDRV_WND_DestroyWindow(struct tagWND *pWnd);
extern struct tagWND *TTYDRV_WND_SetParent(struct tagWND *wndPtr, struct tagWND *pWndParent);
extern void TTYDRV_WND_ForceWindowRaise(struct tagWND *pWnd);
extern void TTYDRV_WND_SetWindowPos(struct tagWND *wndPtr, const struct tagWINDOWPOS *winpos, BOOL bSMC_SETXPOS);
extern void TTYDRV_WND_SetText(struct tagWND *wndPtr, LPCWSTR text);
extern void TTYDRV_WND_SetFocus(struct tagWND *wndPtr);
extern void TTYDRV_WND_PreSizeMove(struct tagWND *wndPtr);
extern void TTYDRV_WND_PostSizeMove(struct tagWND *wndPtr);
extern void TTYDRV_WND_ScrollWindow(struct tagWND *wndPtr, HDC hdc, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
extern void TTYDRV_WND_SetDrawable(struct tagWND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin);
extern BOOL TTYDRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
extern BOOL TTYDRV_WND_IsSelfClipping(struct tagWND *wndPtr);
extern void TTYDRV_WND_SetWindowRgn(struct tagWND *wndPtr, HRGN hrgnWnd);
#endif /* !defined(__WINE_TTYDRV_H) */

View file

@ -11,8 +11,6 @@ debug_channels (ttydrv)
# USER driver
@ cdecl Synchronize() TTYDRV_Synchronize
@ cdecl CheckFocus() TTYDRV_CheckFocus
@ cdecl UserRepaintDisable(long) TTYDRV_UserRepaintDisable
@ cdecl InitKeyboard() TTYDRV_InitKeyboard
@ cdecl VkKeyScan(long) TTYDRV_VkKeyScan
@ -24,8 +22,6 @@ debug_channels (ttydrv)
@ cdecl Beep() TTYDRV_Beep
@ cdecl GetDIState(long ptr) TTYDRV_GetDIState
@ cdecl GetDIData(ptr long ptr ptr long) TTYDRV_GetDIData
@ cdecl GetKeyboardConfig(ptr) TTYDRV_GetKeyboardConfig
@ cdecl SetKeyboardConfig(ptr long) TTYDRV_SetKeyboardConfig
@ cdecl InitMouse(ptr) TTYDRV_InitMouse
@ cdecl SetCursor(ptr) TTYDRV_SetCursor
@ cdecl MoveCursor(long long) TTYDRV_MoveCursor
@ -34,6 +30,10 @@ debug_channels (ttydrv)
@ cdecl GetScreenSaveTimeout() TTYDRV_GetScreenSaveTimeout
@ cdecl SetScreenSaveTimeout(long) TTYDRV_SetScreenSaveTimeout
@ cdecl LoadOEMResource(long long) TTYDRV_LoadOEMResource
@ cdecl CreateWindow(long) TTYDRV_CreateWindow
@ cdecl DestroyWindow(long) TTYDRV_DestroyWindow
@ cdecl GetDC(long long long long) TTYDRV_GetDC
@ cdecl SetWindowPos(ptr) TTYDRV_SetWindowPos
@ cdecl IsSingleWindow() TTYDRV_IsSingleWindow
@ cdecl AcquireClipboard() TTYDRV_AcquireClipboard
@ cdecl ReleaseClipboard() TTYDRV_ReleaseClipboard

View file

@ -11,21 +11,6 @@
DEFAULT_DEBUG_CHANNEL(ttydrv);
/***********************************************************************
* TTYDRV_Synchronize
*/
void TTYDRV_Synchronize( void )
{
}
/***********************************************************************
* TTYDRV_CheckFocus
*/
BOOL TTYDRV_CheckFocus(void)
{
return TRUE;
}
/***********************************************************************
* TTYDRV_UserRepaintDisable
*/
@ -117,20 +102,6 @@ BOOL TTYDRV_GetDIData( BYTE *keystate, DWORD dodsize, LPDIDEVICEOBJECTDATA dod,
return TRUE;
}
/***********************************************************************
* TTYDRV_GetKeyboardConfig
*/
void TTYDRV_GetKeyboardConfig(KEYBOARD_CONFIG *cfg)
{
}
/***********************************************************************
* TTYDRV_SetKeyboardConfig
*/
extern void TTYDRV_SetKeyboardConfig(KEYBOARD_CONFIG *cfg, DWORD mask)
{
}
/***********************************************************************
* TTYDRV_InitMouse
*/

View file

@ -8,156 +8,88 @@
#include "gdi.h"
#include "ttydrv.h"
#include "region.h"
#include "win.h"
#include "winpos.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ttydrv);
WND_DRIVER TTYDRV_WND_Driver =
{
TTYDRV_WND_Initialize,
TTYDRV_WND_Finalize,
TTYDRV_WND_CreateDesktopWindow,
TTYDRV_WND_CreateWindow,
TTYDRV_WND_DestroyWindow,
TTYDRV_WND_SetParent,
TTYDRV_WND_ForceWindowRaise,
TTYDRV_WND_SetWindowPos,
TTYDRV_WND_SetText,
TTYDRV_WND_SetFocus,
TTYDRV_WND_PreSizeMove,
TTYDRV_WND_PostSizeMove,
TTYDRV_WND_ScrollWindow,
TTYDRV_WND_SetDrawable,
TTYDRV_WND_SetHostAttr,
TTYDRV_WND_IsSelfClipping,
TTYDRV_WND_SetWindowRgn
TTYDRV_WND_SetHostAttr
};
/***********************************************************************
* TTYDRV_WND_GetCursesWindow
*
* Return the Curses window associated to a window.
*/
WINDOW *TTYDRV_WND_GetCursesWindow(WND *wndPtr)
{
return wndPtr && wndPtr->pDriverData ?
((TTYDRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
}
#define SWP_AGG_NOGEOMETRYCHANGE \
(SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
#define SWP_AGG_NOPOSCHANGE \
(SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
#define SWP_AGG_STATUSFLAGS \
(SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
/**********************************************************************
* TTYDRV_WND_Initialize
* CreateWindow (TTYDRV.@)
*/
void TTYDRV_WND_Initialize(WND *wndPtr)
{
TTYDRV_WND_DATA *pWndDriverData = HeapAlloc(GetProcessHeap(), 0, sizeof(TTYDRV_WND_DATA));
TRACE("(%p)\n", wndPtr);
wndPtr->pDriverData = (void *) pWndDriverData;
pWndDriverData->window = NULL;
}
/**********************************************************************
* TTYDRV_WND_Finalize
*/
void TTYDRV_WND_Finalize(WND *wndPtr)
{
TTYDRV_WND_DATA *pWndDriverData =
(TTYDRV_WND_DATA *) wndPtr->pDriverData;
TRACE("(%p)\n", wndPtr);
if(!pWndDriverData) {
ERR("WND already destroyed\n");
return;
}
if(pWndDriverData->window) {
ERR("WND destroyed without destroying the associated Curses Windows");
}
HeapFree(GetProcessHeap(), 0, pWndDriverData);
wndPtr->pDriverData = NULL;
}
/**********************************************************************
* TTYDRV_WND_CreateDesktopWindow
*/
BOOL TTYDRV_WND_CreateDesktopWindow(WND *wndPtr)
{
TTYDRV_WND_DATA *pWndDriverData =
(TTYDRV_WND_DATA *) wndPtr->pDriverData;
TRACE("(%p)\n", wndPtr);
if(!pWndDriverData) { ERR("WND never initialized\n"); return FALSE; }
pWndDriverData->window = TTYDRV_GetRootWindow();
return TRUE;
}
/**********************************************************************
* TTYDRV_WND_CreateWindow
*/
BOOL TTYDRV_WND_CreateWindow(WND *wndPtr, CREATESTRUCTA *cs, BOOL bUnicode)
BOOL TTYDRV_CreateWindow( HWND hwnd )
{
#ifdef WINE_CURSES
WINDOW *window;
INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
WND *wndPtr = WIN_FindWndPtr( hwnd );
WINDOW *window;
INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
TRACE("(%p, %p, %d)\n", wndPtr, cs, bUnicode);
TRACE("(%x)\n", hwnd);
/* Only create top-level windows */
if(cs->style & WS_CHILD)
/* Only create top-level windows */
if (wndPtr->dwStyle & WS_CHILD)
{
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
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;
WIN_ReleaseWndPtr( wndPtr );
#else /* defined(WINE_CURSES) */
FIXME("(%x): stub\n", hwnd);
#endif /* defined(WINE_CURSES) */
return TRUE;
window = subwin(TTYDRV_GetRootWindow(), cs->cy/cellHeight, cs->cx/cellWidth,
cs->y/cellHeight, cs->x/cellWidth);
werase(window);
wrefresh(window);
return TRUE;
#else /* defined(WINE_CURSES) */
FIXME("(%p, %p, %p, %d): stub\n", wndPtr, cs, bUnicode);
return TRUE;
#endif /* defined(WINE_CURSES) */
}
/***********************************************************************
* TTYDRV_WND_DestroyWindow
* DestroyWindow (TTYDRV.@)
*/
BOOL TTYDRV_WND_DestroyWindow(WND *wndPtr)
BOOL TTYDRV_DestroyWindow( HWND hwnd )
{
#ifdef WINE_CURSES
WINDOW *window;
WND *wndPtr = WIN_FindWndPtr( hwnd );
WINDOW *window = wndPtr->pDriverData;
TRACE("(%p)\n", wndPtr);
TRACE("(%x)\n", hwnd);
window = TTYDRV_WND_GetCursesWindow(wndPtr);
if(window && window != TTYDRV_GetRootWindow()) {
delwin(window);
}
return TRUE;
if (window && window != root_window) delwin(window);
wndPtr->pDriverData = NULL;
WIN_ReleaseWndPtr( wndPtr );
#else /* defined(WINE_CURSES) */
FIXME("(%p): stub\n", wndPtr);
return TRUE;
FIXME("(%x): stub\n", hwnd);
#endif /* defined(WINE_CURSES) */
}
/*****************************************************************
* TTYDRV_WND_SetParent
*/
WND *TTYDRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
{
FIXME("(%p, %p): stub\n", wndPtr, pWndParent);
return NULL;
return TRUE;
}
/***********************************************************************
@ -168,30 +100,6 @@ void TTYDRV_WND_ForceWindowRaise(WND *wndPtr)
FIXME("(%p): stub\n", wndPtr);
}
/***********************************************************************
* TTYDRV_WINPOS_SetWindowPos
*/
void TTYDRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bSMC_SETXPOS)
{
FIXME("(%p, %p, %d): stub\n", wndPtr, winpos, bSMC_SETXPOS);
}
/*****************************************************************
* TTYDRV_WND_SetText
*/
void TTYDRV_WND_SetText(WND *wndPtr, LPCWSTR text)
{
FIXME("(%p, %s): stub\n", wndPtr, debugstr_w(text));
}
/*****************************************************************
* TTYDRV_WND_SetFocus
*/
void TTYDRV_WND_SetFocus(WND *wndPtr)
{
FIXME("(%p): stub\n", wndPtr);
}
/*****************************************************************
* TTYDRV_WND_PreSizeMove
*/
@ -218,31 +126,6 @@ void TTYDRV_WND_ScrollWindow( WND *wndPtr, HDC hdc, INT dx, INT dy,
wndPtr, hdc, dx, dy, clipRect, bUpdate);
}
/***********************************************************************
* TTYDRV_WND_SetDrawable
*/
void TTYDRV_WND_SetDrawable(WND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin)
{
DC *dc = DC_GetDCPtr( hdc );
if (!dc) return;
TRACE("(%p, %p, %d, %d)\n", wndPtr, dc, flags, bSetClipOrigin);
/* FIXME: Should be done in the common code instead */
if(!wndPtr) {
dc->DCOrgX = 0;
dc->DCOrgY = 0;
} else {
if(flags & DCX_WINDOW) {
dc->DCOrgX = wndPtr->rectWindow.left;
dc->DCOrgY = wndPtr->rectWindow.top;
} else {
dc->DCOrgX = wndPtr->rectClient.left;
dc->DCOrgY = wndPtr->rectClient.top;
}
}
GDI_ReleaseObj( hdc );
}
/***********************************************************************
* TTYDRV_WND_SetHostAttr
*/
@ -253,20 +136,519 @@ BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
return TRUE;
}
/***********************************************************************
* TTYDRV_WND_IsSelfClipping
*/
BOOL TTYDRV_WND_IsSelfClipping(WND *wndPtr)
{
FIXME("(%p): semistub\n", wndPtr);
return FALSE;
}
/***********************************************************************
* TTYDRV_WND_SetWindowRgn
* DCE_OffsetVisRgn
*
* Change region from DC-origin relative coordinates to screen coords.
*/
void TTYDRV_WND_SetWindowRgn(struct tagWND *wndPtr, HRGN hrgnWnd)
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
*
* 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.
*/
static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
{
*lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
if (wndPtr->dwStyle & WS_VISIBLE)
{
INT xoffset = lprect->left;
INT yoffset = lprect->top;
while ((wndPtr = WIN_LockWndPtr(wndPtr->parent)))
{
if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
{
WIN_ReleaseWndPtr(wndPtr);
goto fail;
}
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;
}
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;
for (WIN_LockWndPtr(pWndStart); (pWndStart && (pWndStart != pWndEnd)); WIN_UpdateWndPtr(&pWndStart,pWndStart->next))
{
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(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break;
}
}
WIN_ReleaseWndPtr(pWndStart);
return (pWndStart == pWndEnd);
}
/***********************************************************************
* DCE_GetVisRgn
*
* 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.
*/
static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
{
HRGN hrgnVis = 0;
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
WND *childWnd = WIN_FindWndPtr( hwndChild );
/* Get visible rectangle and create a region with it. */
if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
{
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;
}
if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
DCE_AddClipRects( wndPtr->parent->child,
wndPtr, hrgnClip, &rect, xoffset, yoffset );
/* Clip siblings of all ancestors that have the
* WS_CLIPSIBLINGS style
*/
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 );
}
}
/* 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;
}
}
}
else
hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
WIN_ReleaseWndPtr(wndPtr);
WIN_ReleaseWndPtr(childWnd);
return hrgnVis;
}
/***********************************************************************
* GetDC (TTYDRV.@)
*
* Set the drawable, origin and dimensions for the DC associated to
* a given window.
*/
BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
{
WND *wndPtr = WIN_FindWndPtr(hwnd);
DC *dc;
BOOL updateVisRgn;
HRGN hrgnVisible = 0;
if (!wndPtr) return FALSE;
if (!(dc = DC_GetDCPtr( hdc )))
{
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
if(flags & DCX_WINDOW)
{
dc->DCOrgX = wndPtr->rectWindow.left;
dc->DCOrgY = wndPtr->rectWindow.top;
}
else
{
dc->DCOrgX = wndPtr->rectClient.left;
dc->DCOrgY = wndPtr->rectClient.top;
}
updateVisRgn = (dc->flags & DC_DIRTY) != 0;
GDI_ReleaseObj( hdc );
if (updateVisRgn)
{
if (flags & DCX_PARENTCLIP)
{
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);
}
else
{
hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
DCE_OffsetVisRgn( hdc, hrgnVisible );
}
SelectVisRgn16( hdc, hrgnVisible );
}
/* apply additional region operation (if any) */
if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
{
if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
TRACE("\tsaved VisRgn, clipRgn = %04x\n", hrgn);
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 );
}
if (hrgnVisible) DeleteObject( hrgnVisible );
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
/***********************************************************************
* SetWindowPos (TTYDRV.@)
*/
BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
{
WND *wndPtr;
RECT newWindowRect, newClientRect;
BOOL retvalue;
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);
/* ------------------------------------------------------------------------ CHECKS */
/* Check window handle */
if (winpos->hwnd == GetDesktopWindow()) return FALSE;
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 );
/* Fix redundant flags */
if(wndPtr->dwStyle & WS_VISIBLE)
winpos->flags &= ~SWP_SHOWWINDOW;
else
{
if (!(winpos->flags & SWP_SHOWWINDOW)) winpos->flags |= SWP_NOREDRAW;
winpos->flags &= ~SWP_HIDEWINDOW;
}
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 )
{
if(!(winpos->flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
{
winpos->flags &= ~SWP_NOZORDER;
winpos->hwndInsertAfter = HWND_TOP;
goto Pos;
}
}
/* 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 )
{
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 */
/* Send WM_WINDOWPOSCHANGING message */
if (!(winpos->flags & SWP_NOSENDCHANGING))
SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)winpos );
/* Calculate new position and size */
newWindowRect = wndPtr->rectWindow;
newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
: wndPtr->rectClient;
if (!(winpos->flags & SWP_NOSIZE))
{
newWindowRect.right = newWindowRect.left + winpos->cx;
newWindowRect.bottom = newWindowRect.top + winpos->cy;
}
if (!(winpos->flags & SWP_NOMOVE))
{
newWindowRect.left = winpos->x;
newWindowRect.top = winpos->y;
newWindowRect.right += winpos->x - wndPtr->rectWindow.left;
newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
OffsetRect( &newClientRect, winpos->x - wndPtr->rectWindow.left,
winpos->y - wndPtr->rectWindow.top );
}
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;
/* Common operations */
/* Send WM_NCCALCSIZE message to get new client area */
if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
{
WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
&wndPtr->rectWindow, &wndPtr->rectClient,
winpos, &newClientRect );
}
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
{
if ( WIN_UnlinkWindow( winpos->hwnd ) )
WIN_LinkWindow( winpos->hwnd, winpos->hwndInsertAfter );
}
/* 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 )
{
wndPtr->dwStyle &= ~WS_VISIBLE;
}
/* ------------------------------------------------------------------------ FINAL */
/* 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.
*/
if( !(winpos->flags & SWP_NOREDRAW) )
{
RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN );
if (wndPtr->parent->hwndSelf == GetDesktopWindow() ||
wndPtr->parent->parent->hwndSelf == GetDesktopWindow())
{
RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
RDW_ERASENOW | RDW_NOCHILDREN );
}
}
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);
if ((((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
!(winpos->flags & SWP_NOSENDCHANGING)) )
SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
retvalue = TRUE;
END:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
}

View file

@ -58,8 +58,6 @@ static BOOL load_driver(void)
return FALSE;
}
GET_USER_FUNC(Synchronize);
GET_USER_FUNC(CheckFocus);
GET_USER_FUNC(UserRepaintDisable);
GET_USER_FUNC(InitKeyboard);
GET_USER_FUNC(VkKeyScan);
@ -71,8 +69,6 @@ static BOOL load_driver(void)
GET_USER_FUNC(Beep);
GET_USER_FUNC(GetDIState);
GET_USER_FUNC(GetDIData);
GET_USER_FUNC(GetKeyboardConfig);
GET_USER_FUNC(SetKeyboardConfig);
GET_USER_FUNC(InitMouse);
GET_USER_FUNC(SetCursor);
GET_USER_FUNC(MoveCursor);
@ -90,6 +86,16 @@ static BOOL load_driver(void)
GET_USER_FUNC(RegisterClipboardFormat);
GET_USER_FUNC(IsSelectionOwner);
GET_USER_FUNC(ResetSelectionOwner);
GET_USER_FUNC(CreateWindow);
GET_USER_FUNC(DestroyWindow);
GET_USER_FUNC(GetDC);
GET_USER_FUNC(EnableWindow);
GET_USER_FUNC(SetFocus);
GET_USER_FUNC(SetParent);
GET_USER_FUNC(SetWindowPos);
GET_USER_FUNC(SetWindowRgn);
GET_USER_FUNC(SetWindowIcon);
GET_USER_FUNC(SetWindowText);
return TRUE;
}

View file

@ -8,6 +8,8 @@ IMPORTS = user32 gdi32 kernel32
C_SRCS = \
dga2.c \
window.c \
winpos.c \
x11ddraw.c \
x11drv_main.c \
xvidmode.c

633
dlls/x11drv/window.c Normal file
View file

@ -0,0 +1,633 @@
/*
* Window related functions
*
* Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
* Copyright 1993 David Metcalfe
* Copyright 1995, 1996 Alex Korobka
*/
#include "config.h"
#include "ts_xlib.h"
#include "ts_xutil.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "debugtools.h"
#include "x11drv.h"
#include "win.h"
#include "options.h"
DEFAULT_DEBUG_CHANNEL(win);
extern Cursor X11DRV_MOUSE_XCursor; /* current X cursor */
extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
#define HAS_DLGFRAME(style,exStyle) \
((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
/* X context to associate a hwnd to an X window */
XContext winContext = 0;
Atom wmProtocols = None;
Atom wmDeleteWindow = None;
Atom dndProtocol = None;
Atom dndSelection = None;
Atom wmChangeState = None;
Atom kwmDockWindow = None;
Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
/***********************************************************************
* register_window
*
* Associate an X window to a HWND.
*/
static void register_window( HWND hwnd, Window win )
{
if (!winContext) winContext = TSXUniqueContext();
TSXSaveContext( display, win, winContext, (char *)hwnd );
TSXSetWMProtocols( display, win, &wmDeleteWindow, 1 );
}
/***********************************************************************
* set_wm_hint
*
* Set a window manager hint.
*/
static void set_wm_hint( Window win, int hint, int val )
{
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;
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, win, wm_hints );
TSXFree(wm_hints);
}
}
/***********************************************************************
* set_icon_hints
*
* Set the icon wm hints
*/
static void set_icon_hints( WND *wndPtr, XWMHints *hints )
{
X11DRV_WND_DATA *data = wndPtr->pDriverData;
HICON hIcon = GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
if (!hIcon)
{
data->hWMIconBitmap = 0;
data->hWMIconMask = 0;
hints->flags &= ~(IconPixmapHint | IconMaskHint);
}
else
{
HBITMAP hbmOrig;
RECT rcMask;
BITMAP bmMask;
ICONINFO ii;
HDC hDC;
GetIconInfo(hIcon, &ii);
X11DRV_CreateBitmap(ii.hbmMask);
X11DRV_CreateBitmap(ii.hbmColor);
GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
rcMask.top = 0;
rcMask.left = 0;
rcMask.right = bmMask.bmWidth;
rcMask.bottom = bmMask.bmHeight;
hDC = CreateCompatibleDC(0);
hbmOrig = SelectObject(hDC, ii.hbmMask);
InvertRect(hDC, &rcMask);
SelectObject(hDC, hbmOrig);
DeleteDC(hDC);
data->hWMIconBitmap = ii.hbmColor;
data->hWMIconMask = ii.hbmMask;
hints->icon_pixmap = X11DRV_BITMAP_Pixmap(data->hWMIconBitmap);
hints->icon_mask = X11DRV_BITMAP_Pixmap(data->hWMIconMask);
hints->flags |= IconPixmapHint | IconMaskHint;
}
}
/***********************************************************************
* dock_window
*
* 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 ;)
*/
inline static void dock_window( Window 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 );
}
/**********************************************************************
* create_desktop
*/
static void create_desktop(WND *wndPtr)
{
X11DRV_WND_DATA *data = wndPtr->pDriverData;
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 );
data->window = root_window;
if (root_window != DefaultRootWindow(display)) wndPtr->flags |= WIN_NATIVE;
register_window( wndPtr->hwndSelf, root_window );
}
/**********************************************************************
* CreateWindow (X11DRV.@)
*/
BOOL X11DRV_CreateWindow( HWND hwnd )
{
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;
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(X11DRV_WND_DATA))))
{
WIN_ReleaseWndPtr( wndPtr );
return FALSE;
}
data->window = 0;
wndPtr->pDriverData = data;
if (!wndPtr->parent)
{
create_desktop( wndPtr );
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
/* Create the X window (only for top-level windows, and then only */
/* when there's no desktop window) */
if ((root_window == DefaultRootWindow(display))
&& (wndPtr->parent->hwndSelf == GetDesktopWindow()))
{
Window wGroupLeader;
XWMHints* wm_hints;
XSetWindowAttributes win_attr;
/* Create "managed" windows only if a title bar or resizable */
/* frame is required. */
if (WIN_WindowNeedsWMBorder(wndPtr->dwStyle, wndPtr->dwExStyle))
{
win_attr.event_mask = ExposureMask | KeyPressMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
FocusChangeMask | StructureNotifyMask;
win_attr.override_redirect = FALSE;
wndPtr->dwExStyle |= WS_EX_MANAGED;
}
else
{
win_attr.event_mask = ExposureMask | KeyPressMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
FocusChangeMask;
win_attr.override_redirect = TRUE;
}
wndPtr->flags |= WIN_NATIVE;
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_MOUSE_XCursor;
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 = TSXCreateWindow( display, root_window,
x, y, cx, cy,
0, screen_depth,
InputOutput, visual,
CWEventMask | CWOverrideRedirect |
CWColormap | CWCursor | CWSaveUnder |
CWBackingStore | CWBitGravity,
&win_attr );
if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
{
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( data->window );
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);
}
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);
}
}
if (wndPtr->owner) /* Get window owner */
{
Window w = X11DRV_WND_FindXWindow( wndPtr->owner );
if (w != None)
{
TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
wGroupLeader = w;
}
}
if ((wm_hints = TSXAllocWMHints()))
{
wm_hints->flags = InputHint | StateHint | WindowGroupHint;
wm_hints->input = True;
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
set_icon_hints( wndPtr, wm_hints );
wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
? IconicState : NormalState;
}
else
wm_hints->initial_state = NormalState;
wm_hints->window_group = wGroupLeader;
TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
TSXFree(wm_hints);
}
register_window( hwnd, data->window );
}
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
/***********************************************************************
* DestroyWindow (X11DRV.@)
*/
BOOL X11DRV_DestroyWindow( HWND hwnd )
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
X11DRV_WND_DATA *data = wndPtr->pDriverData;
Window w;
if (data && (w = data->window))
{
XEvent xe;
TSXDeleteContext( display, w, winContext );
TSXDestroyWindow( display, w );
while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
data->window = None;
if( data->hWMIconBitmap )
{
DeleteObject( data->hWMIconBitmap );
data->hWMIconBitmap = 0;
}
if( data->hWMIconMask )
{
DeleteObject( data->hWMIconMask);
data->hWMIconMask= 0;
}
}
HeapFree( GetProcessHeap(), 0, data );
wndPtr->pDriverData = NULL;
WIN_ReleaseWndPtr( wndPtr );
return TRUE;
}
/*****************************************************************
* SetParent (X11DRV.@)
*/
HWND X11DRV_SetParent( HWND hwnd, HWND parent )
{
WND *wndPtr;
WND *pWndParent;
DWORD dwStyle;
HWND retvalue;
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
dwStyle = wndPtr->dwStyle;
pWndParent = parent ? WIN_FindWndPtr(parent) : WIN_GetDesktop();
if (!pWndParent)
{
WIN_ReleaseWndPtr( wndPtr );
return 0;
}
/* Windows hides the window first, then shows it again
* including the WM_SHOWWINDOW messages and all */
if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
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;
}
WIN_UnlinkWindow(wndPtr->hwndSelf);
wndPtr->parent = pWndParent;
/* 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 */
{
if( !( wndPtr->dwStyle & WS_CHILD ) )
{
if( wndPtr->wIDmenu != 0)
{
DestroyMenu( (HMENU) wndPtr->wIDmenu );
wndPtr->wIDmenu = 0;
}
}
}
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
}
WIN_ReleaseWndPtr( pWndParent );
WIN_ReleaseWndPtr( wndPtr );
/* SetParent additionally needs to make hwnd the topmost window
in the x-order and send the expected WM_WINDOWPOSCHANGING and
WM_WINDOWPOSCHANGED notification messages.
*/
SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
/* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
return retvalue;
}
/*******************************************************************
* EnableWindow (X11DRV.@)
*/
BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
{
WND *wndPtr;
BOOL retvalue;
Window w;
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
if (enable && (wndPtr->dwStyle & WS_DISABLED))
{
/* Enable window */
wndPtr->dwStyle &= ~WS_DISABLED;
if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
set_wm_hint( w, InputHint, TRUE );
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
}
else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
{
SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0 );
/* Disable window */
wndPtr->dwStyle |= WS_DISABLED;
if ((wndPtr->dwExStyle & WS_EX_MANAGED) && (w = X11DRV_WND_GetXWindow( wndPtr )))
set_wm_hint( w, InputHint, FALSE );
if (hwnd == GetFocus())
SetFocus( 0 ); /* A disabled window can't have the focus */
if (hwnd == GetCapture())
ReleaseCapture(); /* A disabled window can't capture the mouse */
SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
}
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
}
/*****************************************************************
* SetFocus (X11DRV.@)
*
* Set the X focus.
* Explicit colormap management seems to work only with OLVWM.
*/
void X11DRV_SetFocus( HWND hwnd )
{
XWindowAttributes win_attr;
Window win;
WND *wndPtr = WIN_FindWndPtr( hwnd );
WND *w = wndPtr;
if (!wndPtr) return;
/* Only mess with the X focus if there's */
/* 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;
if (w->dwExStyle & WS_EX_MANAGED) goto done;
if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
{
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
}
else if ((win = X11DRV_WND_FindXWindow(wndPtr)))
{
/* Set X focus and install colormap */
if (TSXGetWindowAttributes( display, win, &win_attr ) &&
(win_attr.map_state == IsViewable))
{
/* If window is not viewable, don't change anything */
TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
X11DRV_Synchronize();
}
}
done:
WIN_ReleaseWndPtr( wndPtr );
}
/*****************************************************************
* SetWindowText (X11DRV.@)
*/
BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
{
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
*
* hIcon or hIconSm has changed (or is being initialised for the
* first time). Complete the X11 driver-specific initialisation
* and set the window hints.
*
* This is not entirely correct, may need to create
* an icon window and set the pixmap as a background
*/
HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
int index = small ? GCL_HICONSM : GCL_HICON;
HICON old;
if (!wndPtr) return 0;
old = GetClassLongW( hwnd, index );
SetClassLongW( hwnd, index, icon );
SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
Window win = X11DRV_WND_GetXWindow(wndPtr);
XWMHints* wm_hints = TSXGetWMHints( display, win );
if (!wm_hints) wm_hints = TSXAllocWMHints();
if (wm_hints)
{
set_icon_hints( wndPtr, wm_hints );
TSXSetWMHints( display, win, wm_hints );
TSXFree( wm_hints );
}
}
WIN_ReleaseWndPtr( wndPtr );
return old;
}

1324
dlls/x11drv/winpos.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -11,8 +11,6 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
# USER driver
@ cdecl Synchronize() X11DRV_Synchronize
@ cdecl CheckFocus() X11DRV_CheckFocus
@ cdecl UserRepaintDisable(long) X11DRV_UserRepaintDisable
@ cdecl InitKeyboard() X11DRV_InitKeyboard
@ cdecl VkKeyScan(long) X11DRV_VkKeyScan
@ -24,8 +22,6 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
@ cdecl Beep() X11DRV_Beep
@ cdecl GetDIState(long ptr) X11DRV_GetDIState
@ cdecl GetDIData(ptr long ptr ptr long) X11DRV_GetDIData
@ cdecl GetKeyboardConfig(ptr) X11DRV_GetKeyboardConfig
@ cdecl SetKeyboardConfig(ptr long) X11DRV_SetKeyboardConfig
@ cdecl InitMouse(ptr) X11DRV_InitMouse
@ cdecl SetCursor(ptr) X11DRV_SetCursor
@ cdecl MoveCursor(long long) X11DRV_MoveCursor
@ -34,6 +30,16 @@ 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 DestroyWindow(long) X11DRV_DestroyWindow
@ cdecl GetDC(long long long long) X11DRV_GetDC
@ cdecl EnableWindow(long long) X11DRV_EnableWindow
@ cdecl SetFocus(long) X11DRV_SetFocus
@ cdecl SetParent(long long) X11DRV_SetParent
@ cdecl SetWindowPos(ptr) X11DRV_SetWindowPos
@ cdecl SetWindowRgn(long long) X11DRV_SetWindowRgn
@ cdecl SetWindowIcon(long long long) X11DRV_SetWindowIcon
@ cdecl SetWindowText(long wstr) X11DRV_SetWindowText
@ cdecl IsSingleWindow() X11DRV_IsSingleWindow
@ cdecl AcquireClipboard() X11DRV_AcquireClipboard
@ cdecl ReleaseClipboard() X11DRV_ReleaseClipboard

View file

@ -42,7 +42,6 @@ extern DCE* DCE_AllocDCE( HWND hWnd, DCE_TYPE type );
extern DCE* DCE_FreeDCE( DCE *dce );
extern void DCE_FreeWindowDCE( struct tagWND* );
extern INT DCE_ExcludeRgn( HDC, struct tagWND*, HRGN );
extern HRGN DCE_GetVisRgn( HWND, WORD, HWND, WORD );
extern BOOL DCE_InvalidateDCE( struct tagWND*, const RECT* );
#endif /* __WINE_DCE_H */

View file

@ -25,10 +25,6 @@ extern BOOL TIMER_GetTimerMsg( struct tagMSG *msg, HWND hwnd,
HQUEUE16 hQueue, BOOL remove );
extern BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc );
/* event.c */
extern void EVENT_Synchronize( void );
extern BOOL EVENT_CheckFocus( void );
/* input.c */
extern HWND EVENT_Capture( HWND, INT16 );

View file

@ -7,6 +7,10 @@
#ifndef __WINE_USER_H
#define __WINE_USER_H
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "local.h"
extern WORD USER_HeapSel;
@ -29,19 +33,12 @@ extern WORD USER_HeapSel;
struct tagCURSORICONINFO;
struct DIDEVICEOBJECTDATA;
#define WINE_KEYBOARD_CONFIG_AUTO_REPEAT 0x00000001
typedef struct tagKEYBOARD_CONFIG {
BOOL auto_repeat;
} KEYBOARD_CONFIG;
typedef VOID CALLBACK (*LPMOUSE_EVENT_PROC)(DWORD,DWORD,DWORD,DWORD,DWORD);
struct tagWND;
typedef struct tagUSER_DRIVER {
/* event functions */
void (*pSynchronize)(void);
BOOL (*pCheckFocus)(void);
void (*pUserRepaintDisable)(BOOL);
/* keyboard functions */
void (*pInitKeyboard)(void);
@ -54,8 +51,6 @@ typedef struct tagUSER_DRIVER {
void (*pBeep)(void);
BOOL (*pGetDIState)(DWORD, LPVOID);
BOOL (*pGetDIData)(BYTE *, DWORD, struct DIDEVICEOBJECTDATA *, LPDWORD, DWORD);
void (*pGetKeyboardConfig)(KEYBOARD_CONFIG *);
void (*pSetKeyboardConfig)(KEYBOARD_CONFIG *, DWORD);
/* mouse functions */
void (*pInitMouse)(LPMOUSE_EVENT_PROC);
void (*pSetCursor)(struct tagCURSORICONINFO *);
@ -67,8 +62,6 @@ typedef struct tagUSER_DRIVER {
void (*pSetScreenSaveTimeout)(int);
/* resource functions */
HANDLE (*pLoadOEMResource)(WORD,WORD);
/* windowing functions */
BOOL (*pIsSingleWindow)(void);
/* clipboard functions */
void (*pAcquireClipboard)(void); /* Acquire selection */
void (*pReleaseClipboard)(void); /* Release selection */
@ -78,6 +71,19 @@ typedef struct tagUSER_DRIVER {
BOOL (*pRegisterClipboardFormat)(LPCSTR); /* Register a clipboard format */
BOOL (*pIsSelectionOwner)(void); /* Check if we own the selection */
void (*pResetSelectionOwner)(struct tagWND *, BOOL);
/* windowing functions */
BOOL (*pCreateWindow)(HWND);
BOOL (*pDestroyWindow)(HWND);
BOOL (*pGetDC)(HWND,HDC,HRGN,DWORD);
BOOL (*pEnableWindow)(HWND,BOOL);
void (*pSetFocus)(HWND);
HWND (*pSetParent)(HWND,HWND);
BOOL (*pSetWindowPos)(WINDOWPOS *);
BOOL (*pSetWindowRgn)(HWND,HRGN,BOOL);
HICON (*pSetWindowIcon)(HWND,HICON,BOOL);
BOOL (*pSetWindowText)(HWND,LPCWSTR);
BOOL (*pIsSingleWindow)(void);
} USER_DRIVER;
extern USER_DRIVER USER_Driver;

View file

@ -66,45 +66,15 @@ typedef struct tagWND
} WND;
/* Host attributes */
#define HAK_BITGRAVITY 1
#define HAK_ACCEPTFOCUS 2
#define HAK_ICONICSTATE 3
#define HAK_ICONS 4
/* Bit Gravity */
#define BGForget 0
#define BGNorthWest 1
#define BGNorth 2
#define BGNorthEast 3
#define BGWest 4
#define BGCenter 5
#define BGEast 6
#define BGSouthWest 7
#define BGSouth 8
#define BGSouthEast 9
#define BGStatic 10
typedef struct tagWND_DRIVER
{
void (*pInitialize)(WND *);
void (*pFinalize)(WND *);
BOOL (*pCreateDesktopWindow)(WND *);
BOOL (*pCreateWindow)(WND *, CREATESTRUCTA *, BOOL);
BOOL (*pDestroyWindow)(WND *);
WND* (*pSetParent)(WND *, WND *);
void (*pForceWindowRaise)(WND *);
void (*pSetWindowPos)(WND *, const WINDOWPOS *, BOOL);
void (*pSetText)(WND *, LPCWSTR);
void (*pSetFocus)(WND *);
void (*pPreSizeMove)(WND *);
void (*pPostSizeMove)(WND *);
void (*pSurfaceCopy)(WND *, HDC, INT, INT, const RECT *, BOOL);
void (*pSetDrawable)(WND *, HDC, WORD, BOOL);
BOOL (*pSetHostAttr)(WND *, INT haKey, INT value);
BOOL (*pIsSelfClipping)(WND *);
void (*pSetWindowRgn)(WND *, const HRGN);
} WND_DRIVER;
extern WND_DRIVER *WND_Driver;

View file

@ -14,8 +14,6 @@
struct tagWND;
#define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
/* undocumented SWP flags - from SDK 3.1 */
#define SWP_NOCLIENTSIZE 0x0800
#define SWP_NOCLIENTMOVE 0x1000
@ -25,16 +23,6 @@ struct tagWND;
struct tagWINDOWPOS16;
typedef struct
{
INT actualCount;
INT suggestedCount;
BOOL valid;
INT wMagic;
HWND hwndParent;
WINDOWPOS winPos[1];
} DWP;
extern BOOL WINPOS_RedrawIconTitle( HWND hWnd );
extern BOOL WINPOS_ShowIconTitle( struct tagWND* pWnd, BOOL bShow );
extern void WINPOS_GetMinMaxInfo( struct tagWND* pWnd, POINT *maxSize,

View file

@ -31,7 +31,6 @@ struct tagDeviceCaps;
struct tagPALETTEOBJ;
struct tagWND;
struct tagWINDOWPOS;
struct tagKEYBOARD_CONFIG;
struct DIDEVICEOBJECTDATA;
/* X physical pen */
@ -364,8 +363,6 @@ extern UINT16 X11DRV_MapVirtualKey(UINT16 wCode, UINT16 wMapType);
extern INT16 X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT16 nSize);
extern BOOL X11DRV_GetDIState(DWORD len, LPVOID ptr);
extern BOOL X11DRV_GetDIData(BYTE *keystate, DWORD dodsize, struct DIDEVICEOBJECTDATA *dod, LPDWORD entries, DWORD flags);
extern void X11DRV_GetKeyboardConfig(struct tagKEYBOARD_CONFIG *cfg);
extern void X11DRV_SetKeyboardConfig(struct tagKEYBOARD_CONFIG *cfg, DWORD mask);
extern void X11DRV_HandleEvent(struct tagWND *pWnd, XKeyEvent *event);
@ -391,28 +388,20 @@ typedef struct _X11DRV_WND_DATA {
extern Window X11DRV_WND_GetXWindow(struct tagWND *wndPtr);
extern Window X11DRV_WND_FindXWindow(struct tagWND *wndPtr);
extern void X11DRV_WND_Initialize(struct tagWND *wndPtr);
extern void X11DRV_WND_Finalize(struct tagWND *wndPtr);
extern BOOL X11DRV_WND_CreateDesktopWindow(struct tagWND *wndPtr);
extern BOOL X11DRV_WND_CreateWindow(struct tagWND *wndPtr, struct tagCREATESTRUCTA *cs, BOOL bUnicode);
extern BOOL X11DRV_WND_DestroyWindow(struct tagWND *pWnd);
extern struct tagWND *X11DRV_WND_SetParent(struct tagWND *wndPtr, struct tagWND *pWndParent);
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_SetFocus(struct tagWND *wndPtr);
extern void X11DRV_WND_PreSizeMove(struct tagWND *wndPtr);
extern void X11DRV_WND_PostSizeMove(struct tagWND *wndPtr);
extern void X11DRV_WND_SurfaceCopy(struct tagWND *wndPtr, HDC hdc, INT dx, INT dy, const RECT *clipRect, BOOL bUpdate);
extern void X11DRV_WND_SetDrawable(struct tagWND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin);
extern void X11DRV_WND_SetGravity(struct tagWND* wndPtr, int value );
extern BOOL X11DRV_WND_SetHostAttr(struct tagWND *wndPtr, INT haKey, INT value);
extern BOOL X11DRV_WND_IsSelfClipping(struct tagWND *wndPtr);
extern void X11DRV_WND_DockWindow(struct tagWND *wndPtr);
extern void X11DRV_WND_SetWindowRgn(struct tagWND *wndPtr, HRGN hrgnWnd);
extern int X11DRV_EVENT_PrepareShmCompletion( Drawable dw );
extern void X11DRV_EVENT_WaitShmCompletion( int compl );
extern void X11DRV_EVENT_WaitShmCompletions( Drawable dw );
extern void X11DRV_EVENT_WaitReplaceShmCompletion( int *compl, Drawable dw );
extern void X11DRV_SetFocus( HWND hwnd );
#endif /* __WINE_X11DRV_H */

View file

@ -16,7 +16,6 @@ C_SRCS = \
defwnd.c \
dialog.c \
driver.c \
event.c \
focus.c \
hook.c \
input.c \

View file

@ -356,242 +356,6 @@ BOOL DCE_InvalidateDCE(WND* pWnd, const RECT* pRectUpdate)
}
/***********************************************************************
* DCE_GetVisRect
*
* 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.
*/
static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
{
*lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
if (wndPtr->dwStyle & WS_VISIBLE)
{
INT xoffset = lprect->left;
INT yoffset = lprect->top;
while( !(wndPtr->flags & WIN_NATIVE) &&
( wndPtr = WIN_LockWndPtr(wndPtr->parent)) )
{
if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
{
WIN_ReleaseWndPtr(wndPtr);
goto fail;
}
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;
}
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( pWndStart->pDriver->pIsSelfClipping( pWndStart ) )
return TRUE; /* The driver itself will do the clipping */
for (WIN_LockWndPtr(pWndStart); (pWndStart && (pWndStart != pWndEnd)); WIN_UpdateWndPtr(&pWndStart,pWndStart->next))
{
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(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break;
}
}
WIN_ReleaseWndPtr(pWndStart);
return (pWndStart == pWndEnd);
}
/***********************************************************************
* DCE_GetVisRgn
*
* 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.
*/
HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
{
HRGN hrgnVis = 0;
RECT rect;
WND *wndPtr = WIN_FindWndPtr( hwnd );
WND *childWnd = WIN_FindWndPtr( hwndChild );
/* Get visible rectangle and create a region with it. */
if (wndPtr && DCE_GetVisRect(wndPtr, !(flags & DCX_WINDOW), &rect))
{
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;
}
if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
DCE_AddClipRects( wndPtr->parent->child,
wndPtr, hrgnClip, &rect, xoffset, yoffset );
/* Clip siblings of all ancestors that have the
* WS_CLIPSIBLINGS style
*/
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 );
}
}
/* 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;
}
}
}
else
hrgnVis = CreateRectRgn(0, 0, 0, 0); /* empty */
WIN_ReleaseWndPtr(wndPtr);
WIN_ReleaseWndPtr(childWnd);
return hrgnVis;
}
/***********************************************************************
* 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_ExcludeRgn
*
@ -640,10 +404,8 @@ HDC16 WINAPI GetDCEx16( HWND16 hwnd, HRGN16 hrgnClip, DWORD flags )
*/
HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
{
HRGN hrgnVisible = 0;
HDC hdc = 0;
DCE * dce;
DC * dc;
WND * wndPtr;
DWORD dcxFlags = 0;
BOOL bUpdateVisRgn = TRUE;
@ -779,90 +541,21 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
goto END;
}
if (!(flags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN))) hrgnClip = 0;
dce->hwndCurrent = hwnd;
dce->hClipRgn = 0;
dce->DCXflags = dcxFlags | (flags & DCX_WINDOWPAINT) | DCX_DCEBUSY;
dce->hClipRgn = hrgnClip;
dce->DCXflags = flags & (DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN |
DCX_CACHE | DCX_WINDOW | DCX_WINDOWPAINT |
DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_EXCLUDERGN);
dce->DCXflags |= DCX_DCEBUSY;
dce->DCXflags &= ~DCX_DCEDIRTY;
hdc = dce->hDC;
if (!(dc = DC_GetDCPtr( hdc )))
{
hdc = 0;
goto END;
}
bUpdateVisRgn = bUpdateVisRgn || (dc->flags & DC_DIRTY);
/* recompute visible region */
wndPtr->pDriver->pSetDrawable( wndPtr, hdc, flags, bUpdateClipOrigin );
dc->flags &= ~DC_DIRTY;
GDI_ReleaseObj( hdc );
if (bUpdateVisRgn) SetHookFlags16( hdc, DCHF_INVALIDATEVISRGN ); /* force update */
if( bUpdateVisRgn )
{
TRACE("updating visrgn for %08x dce, hwnd [%04x]\n", (unsigned)dce, hwnd);
if (!USER_Driver.pGetDC( hwnd, hdc, hrgnClip, flags )) hdc = 0;
if (flags & DCX_PARENTCLIP)
{
WND *parentPtr = WIN_LockWndPtr(wndPtr->parent);
if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
{
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);
}
else
if ((hwnd == GetDesktopWindow()) && !USER_Driver.pIsSingleWindow())
hrgnVisible = CreateRectRgn( 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) );
else
{
hrgnVisible = DCE_GetVisRgn( hwnd, flags, 0, 0 );
DCE_OffsetVisRgn( hdc, hrgnVisible );
}
dce->DCXflags &= ~DCX_DCEDIRTY;
SelectVisRgn16( hdc, hrgnVisible );
}
else
TRACE("no visrgn update %08x dce, hwnd [%04x]\n", (unsigned)dce, hwnd);
/* apply additional region operation (if any) */
if( flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) )
{
if( !hrgnVisible ) hrgnVisible = CreateRectRgn( 0, 0, 0, 0 );
dce->DCXflags |= flags & (DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_EXCLUDERGN);
dce->hClipRgn = hrgnClip;
TRACE("\tsaved VisRgn, clipRgn = %04x\n", hrgnClip);
SaveVisRgn16( hdc );
CombineRgn( hrgnVisible, hrgnClip, 0, RGN_COPY );
DCE_OffsetVisRgn( hdc, hrgnVisible );
CombineRgn( hrgnVisible, InquireVisRgn16( hdc ), hrgnVisible,
(flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
SelectVisRgn16( hdc, hrgnVisible );
}
if( hrgnVisible ) DeleteObject( hrgnVisible );
TRACE("(%04x,%04x,0x%lx): returning %04x\n",
hwnd, hrgnClip, flags, hdc);
TRACE("(%04x,%04x,0x%lx): returning %04x\n", hwnd, hrgnClip, flags, hdc);
END:
WIN_ReleaseWndPtr(wndPtr);
return hdc;
@ -960,9 +653,7 @@ INT WINAPI ReleaseDC(
BOOL16 WINAPI DCHook16( HDC16 hDC, WORD code, DWORD data, LPARAM lParam )
{
BOOL retv = TRUE;
HRGN hVisRgn;
DCE *dce = (DCE *)data;
WND *wndPtr;
TRACE("hDC = %04x, %i\n", hDC, code);
@ -975,43 +666,12 @@ BOOL16 WINAPI DCHook16( HDC16 hDC, WORD code, DWORD data, LPARAM lParam )
switch( code )
{
case DCHC_INVALIDVISRGN:
/* GDI code calls this when it detects that the
* DC is dirty (usually after SetHookFlags()). This
* means that we have to recompute the visible region.
*/
if( dce->DCXflags & DCX_DCEBUSY )
{
/* Update stale DC in DCX */
wndPtr = WIN_FindWndPtr( dce->hwndCurrent);
if (wndPtr) wndPtr->pDriver->pSetDrawable( wndPtr, dce->hDC, dce->DCXflags, TRUE);
SetHookFlags16(hDC, DCHF_VALIDATEVISRGN);
hVisRgn = DCE_GetVisRgn(dce->hwndCurrent, dce->DCXflags, 0, 0);
TRACE("\tapplying saved clipRgn\n");
/* clip this region with saved clipping region */
if ( (dce->DCXflags & DCX_INTERSECTRGN && dce->hClipRgn != 1) ||
( dce->DCXflags & DCX_EXCLUDERGN && dce->hClipRgn) )
{
if( (!dce->hClipRgn && dce->DCXflags & DCX_INTERSECTRGN) ||
(dce->hClipRgn == 1 && dce->DCXflags & DCX_EXCLUDERGN) )
SetRectRgn(hVisRgn,0,0,0,0);
else
CombineRgn(hVisRgn, hVisRgn, dce->hClipRgn,
(dce->DCXflags & DCX_EXCLUDERGN)? RGN_DIFF:RGN_AND);
}
dce->DCXflags &= ~DCX_DCEDIRTY;
DCE_OffsetVisRgn( hDC, hVisRgn );
SelectVisRgn16(hDC, hVisRgn);
DeleteObject( hVisRgn );
WIN_ReleaseWndPtr( wndPtr ); /* Release WIN_FindWndPtr lock */
}
USER_Driver.pGetDC( dce->hwndCurrent, dce->hDC, dce->hClipRgn, dce->DCXflags );
else /* non-fatal but shouldn't happen */
WARN("DC is not in use!\n");
break;

View file

@ -72,7 +72,8 @@ void DEFWND_SetTextA( WND *wndPtr, LPCSTR text )
else
ERR("Not enough memory for window text");
wndPtr->pDriver->pSetText(wndPtr, wndPtr->text);
if (USER_Driver.pSetWindowText)
USER_Driver.pSetWindowText(wndPtr->hwndSelf, wndPtr->text);
}
/***********************************************************************
@ -94,7 +95,8 @@ void DEFWND_SetTextW( WND *wndPtr, LPCWSTR text )
else
ERR("Not enough memory for window text");
wndPtr->pDriver->pSetText(wndPtr, wndPtr->text);
if (USER_Driver.pSetWindowText)
USER_Driver.pSetWindowText(wndPtr->hwndSelf, wndPtr->text);
}
/***********************************************************************
@ -165,7 +167,7 @@ static void DEFWND_SetRedraw( WND* wndPtr, WPARAM wParam )
if( wndPtr->dwStyle & WS_MINIMIZE ) wParam = RDW_VALIDATE;
else wParam = RDW_ALLCHILDREN | RDW_VALIDATE;
PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, wParam, 0 );
RedrawWindow( wndPtr->hwndSelf, NULL, 0, wParam );
DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
wndPtr->dwStyle &= ~WS_VISIBLE;
}
@ -623,6 +625,9 @@ static LRESULT DEFWND_DefWinProc( WND *wndPtr, UINT msg, WPARAM wParam,
return 1;
case WM_SETICON:
if (USER_Driver.pSetWindowIcon)
return USER_Driver.pSetWindowIcon( wndPtr->hwndSelf, lParam, (wParam != ICON_SMALL) );
else
{
int index = (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM;
HICON hOldIcon = GetClassLongW(wndPtr->hwndSelf, index);
@ -631,10 +636,6 @@ static LRESULT DEFWND_DefWinProc( WND *wndPtr, UINT msg, WPARAM wParam,
SetWindowPos(wndPtr->hwndSelf, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
| SWP_NOZORDER);
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_ICONS, 0);
return hOldIcon;
}

View file

@ -1,36 +0,0 @@
/*
* X events handling functions
*
* Copyright 1993 Alexandre Julliard
*
*/
#include "message.h"
#include "user.h"
#include "win.h"
#include "debugtools.h"
DECLARE_DEBUG_CHANNEL(event);
/***********************************************************************
* EVENT_Synchronize
*
* Synchronize with the X server. Should not be used too often.
*/
void EVENT_Synchronize( void )
{
int iWndsLocks = WIN_SuspendWndsLock();
USER_Driver.pSynchronize();
WIN_RestoreWndsLock(iWndsLocks);
}
/**********************************************************************
* EVENT_CheckFocus
*/
BOOL EVENT_CheckFocus(void)
{
return USER_Driver.pCheckFocus();
}

View file

@ -15,6 +15,7 @@
#include "hook.h"
#include "message.h"
#include "queue.h"
#include "user.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(win);
@ -26,35 +27,20 @@ DEFAULT_DEBUG_CHANNEL(win);
*/
void FOCUS_SwitchFocus( MESSAGEQUEUE *pMsgQ, HWND hFocusFrom, HWND hFocusTo )
{
WND *pFocusTo = WIN_FindWndPtr( hFocusTo );
PERQDATA_SetFocusWnd( pMsgQ->pQData, hFocusTo );
#if 0
if (hFocusFrom) SendMessageA( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
#else
/* FIXME: must be SendMessage16() because 32A doesn't do
* intertask at this time */
if (hFocusFrom) SendMessage16( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
#endif
if( !pFocusTo || hFocusTo != PERQDATA_GetFocusWnd( pMsgQ->pQData ) )
if (hFocusFrom) SendMessageA( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
if( !hFocusTo || hFocusTo != PERQDATA_GetFocusWnd( pMsgQ->pQData ) )
{
WIN_ReleaseWndPtr(pFocusTo);
return;
return;
}
/* According to API docs, the WM_SETFOCUS message is sent AFTER the window
has received the keyboard focus. */
if (USER_Driver.pSetFocus) USER_Driver.pSetFocus(hFocusTo);
pFocusTo->pDriver->pSetFocus(pFocusTo);
WIN_ReleaseWndPtr(pFocusTo);
#if 0
SendMessageA( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
#else
SendMessage16( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
#endif
}

View file

@ -2458,8 +2458,8 @@ LONG WINAPI DispatchMessageA( const MSG* msg )
msg->hwnd);
wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
/* Validate the update region to avoid infinite WM_PAINT loop */
PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0,
RDW_FRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT, 0 );
RedrawWindow( wndPtr->hwndSelf, NULL, 0,
RDW_FRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
}
END:
WIN_ReleaseWndPtr(wndPtr);

View file

@ -988,8 +988,7 @@ BOOL16 WINAPI RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
CONV_RECT16TO32( rectUpdate, &r );
return (BOOL16)RedrawWindow( (HWND)hwnd, &r, hrgnUpdate, flags );
}
return (BOOL16)PAINT_RedrawWindow( (HWND)hwnd, NULL,
(HRGN)hrgnUpdate, flags, 0 );
return RedrawWindow( hwnd, NULL, hrgnUpdate, flags );
}
@ -998,7 +997,7 @@ BOOL16 WINAPI RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
*/
void WINAPI UpdateWindow16( HWND16 hwnd )
{
PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN, 0 );
RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
}
/***********************************************************************
@ -1006,7 +1005,7 @@ void WINAPI UpdateWindow16( HWND16 hwnd )
*/
void WINAPI UpdateWindow( HWND hwnd )
{
PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN, 0 );
RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
}
/***********************************************************************
@ -1014,8 +1013,7 @@ void WINAPI UpdateWindow( HWND hwnd )
*/
void WINAPI InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
{
PAINT_RedrawWindow((HWND)hwnd, NULL, (HRGN)hrgn,
RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
RedrawWindow((HWND)hwnd, NULL, (HRGN)hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
}
@ -1024,7 +1022,7 @@ void WINAPI InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
*/
BOOL WINAPI InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
{
return PAINT_RedrawWindow(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
return RedrawWindow(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
}
@ -1042,8 +1040,7 @@ void WINAPI InvalidateRect16( HWND16 hwnd, const RECT16 *rect, BOOL16 erase )
*/
BOOL WINAPI InvalidateRect( HWND hwnd, const RECT *rect, BOOL erase )
{
return PAINT_RedrawWindow( hwnd, rect, 0,
RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
return RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
}
@ -1052,8 +1049,7 @@ BOOL WINAPI InvalidateRect( HWND hwnd, const RECT *rect, BOOL erase )
*/
void WINAPI ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
{
PAINT_RedrawWindow( (HWND)hwnd, NULL, (HRGN)hrgn,
RDW_VALIDATE | RDW_NOCHILDREN, 0 );
RedrawWindow( (HWND)hwnd, NULL, (HRGN)hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
}
@ -1062,7 +1058,7 @@ void WINAPI ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
*/
void WINAPI ValidateRgn( HWND hwnd, HRGN hrgn )
{
PAINT_RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
}
@ -1080,7 +1076,7 @@ void WINAPI ValidateRect16( HWND16 hwnd, const RECT16 *rect )
*/
void WINAPI ValidateRect( HWND hwnd, const RECT *rect )
{
PAINT_RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
}

View file

@ -336,8 +336,9 @@ rc.left, rc.top, rc.right, rc.bottom, (UINT16)flags );
}
if( flags & (SW_INVALIDATE | SW_ERASE) )
PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) | ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ), 0 );
RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
if( bCaret )
{

View file

@ -455,8 +455,6 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
PROPERTY_RemoveWindowProps( wndPtr );
wndPtr->dwMagic = 0; /* Mark it as invalid */
/* toss stale messages from the queue */
if( wndPtr->hmemTaskQ )
@ -494,16 +492,15 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
DestroyMenu( wndPtr->hSysMenu );
wndPtr->hSysMenu = 0;
}
wndPtr->pDriver->pDestroyWindow( wndPtr );
USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
CLASS_RemoveWindow( wndPtr->class );
wndPtr->class = NULL;
wndPtr->dwMagic = 0; /* Mark it as invalid */
WIN_UpdateWndPtr(&pWnd,wndPtr->next);
wndPtr->pDriver->pFinalize(wndPtr);
return pWnd;
}
@ -590,8 +587,6 @@ BOOL WIN_CreateDesktopWindow(void)
pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
pWndDesktop->pDriver = WND_Driver;
pWndDesktop->pDriver->pInitialize(pWndDesktop);
pWndDesktop->next = NULL;
pWndDesktop->child = NULL;
pWndDesktop->parent = NULL;
@ -626,7 +621,7 @@ BOOL WIN_CreateDesktopWindow(void)
pWndDesktop->cbWndExtra = wndExtra;
pWndDesktop->irefCount = 0;
if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop)) return FALSE;
if (!USER_Driver.pCreateWindow( hwndDesktop )) return FALSE;
SendMessageW( hwndDesktop, WM_NCCREATE, 0, 0 );
pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
@ -789,7 +784,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
wndPtr->pDriver = wndPtr->parent->pDriver;
wndPtr->pDriver->pInitialize(wndPtr);
wndPtr->class = classPtr;
wndPtr->winproc = winproc;
@ -835,7 +829,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
if (ret)
{
TRACE("CBT-hook returned 0\n");
wndPtr->pDriver->pFinalize(wndPtr);
USER_HEAP_FREE( hwnd );
CLASS_RemoveWindow( classPtr );
retvalue = 0;
@ -889,7 +882,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
wndPtr->rectWindow.bottom = cs->y + cs->cy;
wndPtr->rectClient = wndPtr->rectWindow;
if(!wndPtr->pDriver->pCreateWindow(wndPtr, cs, type == WIN_PROC_32W))
if (!USER_Driver.pCreateWindow(wndPtr->hwndSelf))
{
retvalue = FALSE;
goto end;
@ -1374,9 +1367,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
if (wndPtr->dwStyle & WS_VISIBLE)
{
SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
ShowWindow( hwnd, SW_HIDE );
if (!IsWindow(hwnd))
{
retvalue = TRUE;
@ -1413,8 +1404,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
else break;
}
if( !Options.managed || EVENT_CheckFocus() )
WINPOS_ActivateOtherWindow(wndPtr);
WINPOS_ActivateOtherWindow(wndPtr);
if( wndPtr->owner &&
wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
@ -1725,45 +1715,34 @@ BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
WND *wndPtr;
BOOL retvalue;
TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
TRACE("( %x, %d )\n", hwnd, enable);
if (USER_Driver.pEnableWindow)
return USER_Driver.pEnableWindow( hwnd, enable );
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
if (enable && (wndPtr->dwStyle & WS_DISABLED))
{
/* Enable window */
wndPtr->dwStyle &= ~WS_DISABLED;
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
retvalue = TRUE;
goto end;
wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
}
else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
{
SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
/* Disable window */
wndPtr->dwStyle |= WS_DISABLED;
wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
if (hwnd == GetFocus())
SetFocus( 0 ); /* A disabled window can't have the focus */
if (hwnd == GetFocus())
{
SetFocus( 0 ); /* A disabled window can't have the focus */
}
if (hwnd == GetCapture())
{
ReleaseCapture(); /* A disabled window can't capture the mouse */
}
SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
retvalue = FALSE;
goto end;
if (hwnd == GetCapture())
ReleaseCapture(); /* A disabled window can't capture the mouse */
SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
}
retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
end:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
}
@ -2392,48 +2371,72 @@ HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
/*****************************************************************
* SetParent (USER32.@)
*/
HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
HWND WINAPI SetParent( HWND hwnd, HWND parent )
{
WND *wndPtr;
DWORD dwStyle;
WND *pWndNewParent;
WND *pWndOldParent;
HWND retvalue;
WND *wndPtr;
WND *pWndParent;
DWORD dwStyle;
HWND retvalue;
if (hwnd == GetDesktopWindow()) /* sanity check */
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
if (USER_Driver.pSetParent)
return USER_Driver.pSetParent( hwnd, parent );
dwStyle = wndPtr->dwStyle;
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
: WIN_LockWndPtr(pWndDesktop);
dwStyle = wndPtr->dwStyle;
/* Windows hides the window first, then shows it again
* including the WM_SHOWWINDOW messages and all */
if (dwStyle & WS_VISIBLE)
ShowWindow( hwndChild, SW_HIDE );
pWndParent = parent ? WIN_FindWndPtr(parent) : WIN_GetDesktop();
if (!pWndParent)
{
WIN_ReleaseWndPtr( wndPtr );
return 0;
}
pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
/* Windows hides the window first, then shows it again
* including the WM_SHOWWINDOW messages and all */
if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
/* SetParent additionally needs to make hwndChild the topmost window
in the x-order and send the expected WM_WINDOWPOSCHANGING and
WM_WINDOWPOSCHANGED notification messages.
*/
SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
/* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
retvalue = wndPtr->parent->hwndSelf; /* old parent */
if (pWndParent != wndPtr->parent)
{
WIN_UnlinkWindow(wndPtr->hwndSelf);
wndPtr->parent = pWndParent;
retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
if (parent != GetDesktopWindow()) /* a child window */
{
if( !( wndPtr->dwStyle & WS_CHILD ) )
{
if( wndPtr->wIDmenu != 0)
{
DestroyMenu( (HMENU) wndPtr->wIDmenu );
wndPtr->wIDmenu = 0;
}
}
}
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
}
WIN_ReleaseWndPtr( pWndParent );
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleaseWndPtr(pWndOldParent);
WIN_ReleaseWndPtr(pWndNewParent);
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
/* SetParent additionally needs to make hwnd the topmost window
in the x-order and send the expected WM_WINDOWPOSCHANGING and
WM_WINDOWPOSCHANGED notification messages.
*/
SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
/* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
return retvalue;
}
/*******************************************************************
* IsChild (USER.48)
*/
@ -3071,8 +3074,7 @@ BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
}
else
{
PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
RDW_UPDATENOW | RDW_FRAME, 0 );
RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
wndPtr->flags &= ~WIN_NCACTIVATED;
}
WIN_ReleaseWndPtr(wndPtr);

View file

@ -36,25 +36,27 @@ DEFAULT_DEBUG_CHANNEL(win);
(((style) & WS_THICKFRAME) && \
!(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
#define SWP_AGG_NOGEOMETRYCHANGE \
(SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
#define SWP_AGG_NOPOSCHANGE \
(SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
#define SWP_AGG_STATUSFLAGS \
(SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
#define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
#define PLACE_MIN 0x0001
#define PLACE_MAX 0x0002
#define PLACE_RECT 0x0004
#define SWP_EX_NOCOPY 0x0001
#define SWP_EX_PAINTSELF 0x0002
#define SWP_EX_NONCLIENT 0x0004
#define MINMAX_NOSWP 0x00010000
#define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
typedef struct
{
INT actualCount;
INT suggestedCount;
BOOL valid;
INT wMagic;
HWND hwndParent;
WINDOWPOS winPos[1];
} DWP;
/* ----- internal variables ----- */
static HWND hwndPrevActive = 0; /* Previously active window */
@ -288,65 +290,39 @@ int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
*/
int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
{
RECT rect;
WND *wndPtr;
int ret = FALSE;
RECT tempRect;
WND *wndPtr = WIN_FindWndPtr(hwnd);
if (USER_Driver.pSetWindowRgn)
return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
if (!wndPtr) return FALSE;
if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
/* a region exists for this window */
if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
if (wndPtr->hrgnWnd == hrgn)
{
/* can't replace actual region with same region
since we're now owner of that region
*/
SetLastError(ERROR_INVALID_HANDLE);
ret = TRUE;
goto done;
}
/* we'd like to set it back to 0 */
if (hrgn == 0)
if (hrgn) /* verify that region really exists */
{
GetWindowRect(hwnd, &tempRect);
}
else
{
/* verify that region really exists */
if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
}
/* Size the window to the rectangle of the new region
(if it isn't NULL) */
/* James: Added SWP_NOACTIVATE because SetWindowRgn in Windows doesn't activate the
window (and this was REALLY screwing up my app) */
SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
if (wndPtr->hrgnWnd)
{
/* delete previous region */
DeleteObject(wndPtr->hrgnWnd);
wndPtr->hrgnWnd = 0;
}
else if (!hrgn)
{
/* if there was no previous region (stored in wndPtr->hrgnWnd) and
the region to be set is also NULL, there is nothing more to do
*/
ret = TRUE;
goto done;
}
/* valid region handle */
wndPtr->hrgnWnd = hrgn;
wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
/* Size the window to the rectangle of the new region (if it isn't NULL) */
if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
ret = TRUE;
done:
@ -1271,9 +1247,8 @@ UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
wndPtr->flags &= ~WIN_RESTORE_MAX;
wndPtr->dwStyle |= WS_MINIMIZE;
if( wndPtr->flags & WIN_NATIVE )
if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
swpFlags |= MINMAX_NOSWP;
if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
swpFlags |= MINMAX_NOSWP;
lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
@ -1289,8 +1264,7 @@ UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
if( wndPtr->dwStyle & WS_MINIMIZE )
{
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
WINPOS_ShowIconTitle( wndPtr, FALSE );
wndPtr->dwStyle &= ~WS_MINIMIZE;
@ -1304,8 +1278,7 @@ UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
case SW_RESTORE:
if( wndPtr->dwStyle & WS_MINIMIZE )
{
if( wndPtr->flags & WIN_NATIVE )
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
wndPtr->dwStyle &= ~WS_MINIMIZE;
WINPOS_ShowIconTitle( wndPtr, FALSE );
@ -2176,411 +2149,6 @@ LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
return 0;
}
/***********************************************************************
* SWP_DoOwnedPopups
*
* fix Z order taking into account owned popups -
* basically we need to maintain them above the window that owns them
*
* FIXME: hide/show owned popups when owner visibility changes.
*/
static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
{
WND* w = WIN_LockWndPtr(pDesktop->child);
WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
{
/* make sure this popup stays above the owner */
HWND hwndLocalPrev = HWND_TOP;
if( hwndInsertAfter != HWND_TOP )
{
while( w && w != wndPtr->owner )
{
if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
if( hwndLocalPrev == hwndInsertAfter ) break;
WIN_UpdateWndPtr(&w,w->next);
}
hwndInsertAfter = hwndLocalPrev;
}
}
else if( wndPtr->dwStyle & WS_CHILD )
goto END;
WIN_UpdateWndPtr(&w, pDesktop->child);
while( w )
{
if( w == wndPtr ) break;
if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
{
SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
hwndInsertAfter = w->hwndSelf;
}
WIN_UpdateWndPtr(&w, w->next);
}
END:
WIN_ReleaseWndPtr(w);
return hwndInsertAfter;
}
/***********************************************************************
* 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.
*/
static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
LPRECT lpOldWndRect,
LPRECT lpOldClientRect, UINT uFlags )
{
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) )
{
nocopy:
TRACE("\twon't copy anything!\n");
/* 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;
/* check if entire window can be copied */
ow = lpOldWndRect->right - lpOldWndRect->left;
oh = lpOldWndRect->bottom - lpOldWndRect->top;
nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
ocw = lpOldClientRect->right - lpOldClientRect->left;
och = lpOldClientRect->bottom - lpOldClientRect->top;
ncw = Wnd->rectClient.right - Wnd->rectClient.left;
nch = Wnd->rectClient.bottom - Wnd->rectClient.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(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
{
/* movement relative to the parent's client area */
dx = Wnd->rectClient.left - lpOldClientRect->left;
dy = Wnd->rectClient.top - lpOldClientRect->top;
}
/* 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;
}
else
{
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
{
dx = Wnd->rectWindow.left - lpOldWndRect->left;
dy = Wnd->rectWindow.top - lpOldWndRect->top;
OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
}
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");
/* Compute combined dirty region (old + new - valid) */
CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
/* Blt valid bits, r is the rect to copy */
if( dx || dy )
{
RECT rClip;
HDC hDC;
/* get DC and clip rect with drawable rect to avoid superfluous expose events
from copying clipped areas */
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
{
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;
}
rClip.left = rClip.top = 0;
if( oh > nh ) r.bottom = r.top + nh;
if( ow < nw ) r.right = r.left + nw;
if( IntersectRect( &r, &r, &rClip ) )
{
Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
/* 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))
{
OffsetRect(&r, dx, dy);
ValidateRect(Wnd->parent->hwndSelf, &r);
}
}
ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
}
}
/* *pVisRgn now points to the invalidated region */
DeleteObject(newVisRgn);
DeleteObject(dirtyRgn);
return uFlags;
}
/***********************************************************************
* 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 )
{
/* Send WM_WINDOWPOSCHANGING message */
if (!(pWinpos->flags & SWP_NOSENDCHANGING))
SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
/* Calculate new position and size */
*pNewWindowRect = wndPtr->rectWindow;
*pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
: wndPtr->rectClient;
if (!(pWinpos->flags & SWP_NOSIZE))
{
pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
}
if (!(pWinpos->flags & SWP_NOMOVE))
{
pNewWindowRect->left = pWinpos->x;
pNewWindowRect->top = pWinpos->y;
pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
pWinpos->y - wndPtr->rectWindow.top );
}
pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
return TRUE;
}
/***********************************************************************
* SWP_DoNCCalcSize
*/
static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
{
UINT wvrFlags = 0;
/* Send WM_NCCALCSIZE message to get new client area */
if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
{
wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
&wndPtr->rectWindow, &wndPtr->rectClient,
pWinpos, pNewClientRect );
/* FIXME: WVR_ALIGNxxx */
if( pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top )
pWinpos->flags &= ~SWP_NOCLIENTMOVE;
if( (pNewClientRect->right - pNewClientRect->left !=
wndPtr->rectClient.right - wndPtr->rectClient.left) ||
(pNewClientRect->bottom - pNewClientRect->top !=
wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
pWinpos->flags &= ~SWP_NOCLIENTSIZE;
}
else
if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top) )
pWinpos->flags &= ~SWP_NOCLIENTMOVE;
return wvrFlags;
}
/***********************************************************************
* SetWindowPos (USER.232)
*/
@ -2596,104 +2164,7 @@ BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
INT x, INT y, INT cx, INT cy, UINT flags )
{
WINDOWPOS winpos;
WND * wndPtr,*wndTemp;
RECT newWindowRect, newClientRect;
RECT oldWindowRect, oldClientRect;
HRGN visRgn = 0;
UINT wvrFlags = 0, uFlags = 0;
BOOL retvalue, resync = FALSE, bChangePos;
HWND hwndActive = 0;
/* Get current active window from the active queue */
if ( hActiveQueue )
{
MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
if ( pActiveQueue )
{
hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
QUEUE_Unlock( pActiveQueue );
}
}
TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
hwnd, x, y, x+cx, y+cy, flags);
bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
flags &= ~SWP_WINE_NOHOSTMOVE;
/* ------------------------------------------------------------------------ CHECKS */
/* Check window handle */
if (hwnd == GetDesktopWindow()) return FALSE;
if (!(wndPtr = WIN_FindWndPtr( 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 );
/* Fix redundant flags */
if(wndPtr->dwStyle & WS_VISIBLE)
flags &= ~SWP_SHOWWINDOW;
else
{
if (!(flags & SWP_SHOWWINDOW))
flags |= SWP_NOREDRAW;
flags &= ~SWP_HIDEWINDOW;
}
if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
(wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
flags |= SWP_NOSIZE; /* Already the right size */
if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
flags |= SWP_NOMOVE; /* Already the right position */
if (hwnd == hwndActive)
flags |= SWP_NOACTIVATE; /* Already active */
else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
{
if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
{
flags &= ~SWP_NOZORDER;
hwndInsertAfter = HWND_TOP;
goto Pos;
}
}
/* Check hwndInsertAfter */
/* FIXME: TOPMOST not supported yet */
if ((hwndInsertAfter == HWND_TOPMOST) ||
(hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
/* hwndInsertAfter must be a sibling of the window */
if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
{
WND* wnd = WIN_FindWndPtr(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 ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
}
WIN_ReleaseWndPtr(wnd);
}
Pos: /* ------------------------------------------------------------------------ MAIN part */
/* Fill the WINDOWPOS structure */
WINDOWPOS winpos;
winpos.hwnd = hwnd;
winpos.hwndInsertAfter = hwndInsertAfter;
@ -2702,311 +2173,10 @@ Pos: /* -----------------------------------------------------------------------
winpos.cx = cx;
winpos.cy = cy;
winpos.flags = flags;
SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
{
if( wndPtr->parent == WIN_GetDesktop() )
hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
hwndInsertAfter, winpos.flags );
WIN_ReleaseDesktop();
}
if(!(wndPtr->flags & WIN_NATIVE) )
{
if( hwndInsertAfter == HWND_TOP )
winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
else
if( hwndInsertAfter == HWND_BOTTOM )
winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
else
if( !(winpos.flags & SWP_NOZORDER) )
if( GetWindow(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(hwnd, dflags, 0, 0);
}
}
/* Common operations */
wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
{
if ( WIN_UnlinkWindow( winpos.hwnd ) )
WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
}
/* Reset active DCEs */
if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
wndPtr->dwStyle & WS_VISIBLE) ||
(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;
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;
*/
/* FIXME: actually do something with WVR_VALIDRECTS */
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
{
BOOL bCallDriver = TRUE;
HWND tempInsertAfter = winpos.hwndInsertAfter;
winpos.hwndInsertAfter = hwndInsertAfter;
if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
{
/* 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 */
if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
{
cx = newWindowRect.right - newWindowRect.left;
cy = newWindowRect.bottom - newWindowRect.top;
wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
winpos.hwndInsertAfter = tempInsertAfter;
bCallDriver = FALSE;
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, cx, cy );
uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
uFlags | SWP_EX_PAINTSELF );
}
}
}
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.
*/
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;
}
wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
}
}
wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
winpos.hwndInsertAfter = tempInsertAfter;
}
if( winpos.flags & SWP_SHOWWINDOW )
{
HWND focus, curr;
wndPtr->dwStyle |= WS_VISIBLE;
if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
/* focus was set to unmapped window, reset host focus
* since the window is now visible */
focus = curr = GetFocus();
while (curr)
{
if (curr == hwnd)
{
WND *pFocus = WIN_FindWndPtr( focus );
if (pFocus)
pFocus->pDriver->pSetFocus(pFocus);
WIN_ReleaseWndPtr(pFocus);
break;
}
curr = GetParent(curr);
}
}
}
else /* -------------------------------------------- emulated window */
{
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) )
{
if( winpos.flags & SWP_HIDEWINDOW )
{
if( visRgn > 1 ) /* map to parent */
OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
else
visRgn = 0;
}
else
{
if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
&oldClientRect, uFlags);
else
{
/* nothing moved, redraw frame if needed */
if( winpos.flags & SWP_FRAMECHANGED )
SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
if( visRgn )
{
DeleteObject( visRgn );
visRgn = 0;
}
}
}
}
}
if( winpos.flags & SWP_HIDEWINDOW )
{
wndPtr->dwStyle &= ~WS_VISIBLE;
}
if (hwnd == CARET_GetHwnd())
{
if( winpos.flags & SWP_HIDEWINDOW )
HideCaret(hwnd);
else if (winpos.flags & SWP_SHOWWINDOW)
ShowCaret(hwnd);
}
/* ------------------------------------------------------------------------ FINAL */
if (wndPtr->flags & WIN_NATIVE)
EVENT_Synchronize(); /* Synchronize with the host window system */
wndTemp = WIN_GetDesktop();
/* 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.
*/
if( visRgn )
{
if( !(winpos.flags & SWP_NOREDRAW) )
{
/* 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 )
{
PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
RDW_ERASENOW | RDW_NOCHILDREN, 0 );
}
}
if( visRgn != 1 )
DeleteObject( visRgn );
}
WIN_ReleaseDesktop();
if (!(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);
if ( resync ||
(((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
!(winpos.flags & SWP_NOSENDCHANGING)) )
{
SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
if (resync) EVENT_Synchronize();
}
retvalue = TRUE;
END:
WIN_ReleaseWndPtr(wndPtr);
return retvalue;
return USER_Driver.pSetWindowPos( &winpos );
}
/***********************************************************************
* BeginDeferWindowPos (USER.259)
*/
@ -3173,9 +2343,7 @@ BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
if (!pDWP) return FALSE;
for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
{
if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
winpos->x, winpos->y, winpos->cx,
winpos->cy, winpos->flags ))) break;
if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
}
USER_HEAP_FREE( hdwp );
return res;

View file

@ -93,7 +93,7 @@ static const char * const event_names[] =
static void CALLBACK EVENT_Flush( ULONG_PTR arg );
static void CALLBACK EVENT_ProcessAllEvents( ULONG_PTR arg );
static void EVENT_ProcessEvent( XEvent *event );
BOOL X11DRV_CheckFocus(void);
static BOOL X11DRV_CheckFocus(void);
/* Event handlers */
static void EVENT_Key( HWND hWnd, XKeyEvent *event );
@ -401,8 +401,8 @@ static void EVENT_ProcessEvent( XEvent *event )
(win_attr.map_state == IsViewable) )
{
TSXSetInputFocus( xfocChange->display, glastXFocusWin, RevertToParent, CurrentTime );
EVENT_Synchronize();
break;
X11DRV_Synchronize();
break;
}
}
}
@ -877,7 +877,7 @@ static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
/**********************************************************************
* CheckFocus (X11DRV.@)
*/
BOOL X11DRV_CheckFocus(void)
static BOOL X11DRV_CheckFocus(void)
{
HWND hWnd;
Window xW;
@ -1850,7 +1850,7 @@ void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
WIN_ReleaseWndPtr(pWnd);
if (hwndFocus && IsChild( hWnd, hwndFocus ))
X11DRV_WND_SetFocus(wndFocus);
X11DRV_SetFocus(hwndFocus);
WIN_ReleaseWndPtr(wndFocus);

View file

@ -1726,30 +1726,3 @@ BOOL X11DRV_GetDIData(
return TRUE;
}
/***********************************************************************
* GetKeyboardConfig (X11DRV.@)
*/
void X11DRV_GetKeyboardConfig(KEYBOARD_CONFIG *cfg) {
XKeyboardState xks;
/* For the moment, only get the auto-repeat mode */
TSXGetKeyboardControl(display, &xks);
cfg->auto_repeat = xks.global_auto_repeat;
}
/***********************************************************************
* SetKeyboardConfig (X11DRV.@)
*/
void X11DRV_SetKeyboardConfig(KEYBOARD_CONFIG *cfg, DWORD mask) {
XKeyboardControl xkc;
unsigned long X_mask = 0;
if (mask & WINE_KEYBOARD_CONFIG_AUTO_REPEAT) {
X_mask |= KBAutoRepeatMode;
xkc.auto_repeat_mode = cfg->auto_repeat;
}
if (X_mask)
TSXChangeKeyboardControl(display, X_mask, &xkc);
}

View file

@ -31,53 +31,23 @@
DEFAULT_DEBUG_CHANNEL(win);
/* Some useful macros */
extern Atom wmChangeState;
#define HAS_DLGFRAME(style,exStyle) \
((!((style) & WS_THICKFRAME)) && (((style) & WS_DLGFRAME) || ((exStyle) & WS_EX_DLGMODALFRAME)))
/**********************************************************************/
extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
extern BOOL X11DRV_CreateBitmap( HBITMAP );
extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
/**********************************************************************/
WND_DRIVER X11DRV_WND_Driver =
{
X11DRV_WND_Initialize,
X11DRV_WND_Finalize,
X11DRV_WND_CreateDesktopWindow,
X11DRV_WND_CreateWindow,
X11DRV_WND_DestroyWindow,
X11DRV_WND_SetParent,
X11DRV_WND_ForceWindowRaise,
X11DRV_WND_SetWindowPos,
X11DRV_WND_SetText,
X11DRV_WND_SetFocus,
X11DRV_WND_PreSizeMove,
X11DRV_WND_PostSizeMove,
X11DRV_WND_SurfaceCopy,
X11DRV_WND_SetDrawable,
X11DRV_WND_SetHostAttr,
X11DRV_WND_IsSelfClipping,
X11DRV_WND_SetWindowRgn
X11DRV_WND_SetHostAttr
};
/* X context to associate a hwnd to an X window */
XContext winContext = 0;
Atom wmProtocols = None;
Atom wmDeleteWindow = None;
Atom dndProtocol = None;
Atom dndSelection = None;
Atom wmChangeState = None;
Atom kwmDockWindow = None;
Atom _net_kde_system_tray_window_for = None; /* KDE 2 Beta */
Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
/***********************************************************************
* X11DRV_WND_GetXWindow
*
@ -103,20 +73,6 @@ Window X11DRV_WND_FindXWindow(WND *wndPtr)
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
}
/***********************************************************************
* X11DRV_WND_RegisterWindow
*
* Associate an X window to a HWND.
*/
static void X11DRV_WND_RegisterWindow(WND *wndPtr)
{
TSXSetWMProtocols( display, X11DRV_WND_GetXWindow(wndPtr), &wmDeleteWindow, 1 );
if (!winContext) winContext = TSXUniqueContext();
TSXSaveContext( display, X11DRV_WND_GetXWindow(wndPtr),
winContext, (char *) wndPtr->hwndSelf );
}
/***********************************************************************
* X11DRV_WND_IsZeroSizeWnd
*
@ -131,414 +87,6 @@ static BOOL X11DRV_WND_IsZeroSizeWnd(WND *wndPtr)
return FALSE;
}
/**********************************************************************
* X11DRV_WND_Initialize
*/
void X11DRV_WND_Initialize(WND *wndPtr)
{
X11DRV_WND_DATA *pWndDriverData = HeapAlloc(GetProcessHeap(), 0, sizeof(X11DRV_WND_DATA));
wndPtr->pDriverData = (void *) pWndDriverData;
pWndDriverData->window = 0;
}
/**********************************************************************
* X11DRV_WND_Finalize
*/
void X11DRV_WND_Finalize(WND *wndPtr)
{
X11DRV_WND_DATA *pWndDriverData =
(X11DRV_WND_DATA *) wndPtr->pDriverData;
if (!wndPtr->pDriverData) {
ERR("Trying to destroy window again. Not good.\n");
return;
}
if(pWndDriverData->window)
{
ERR(
"WND destroyed without destroying "
"the associated X Window (%ld)\n",
pWndDriverData->window
);
}
HeapFree(GetProcessHeap(), 0, wndPtr->pDriverData);
wndPtr->pDriverData = NULL;
}
/**********************************************************************
* X11DRV_WND_CreateDesktopWindow
*/
BOOL X11DRV_WND_CreateDesktopWindow(WND *wndPtr)
{
if (wmProtocols == None)
wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True );
if (wmDeleteWindow == None)
wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True );
if( dndProtocol == None )
dndProtocol = TSXInternAtom( display, "DndProtocol" , False );
if( dndSelection == None )
dndSelection = TSXInternAtom( display, "DndSelection" , False );
if( wmChangeState == None )
wmChangeState = TSXInternAtom (display, "WM_CHANGE_STATE", False);
if (kwmDockWindow == None)
kwmDockWindow = TSXInternAtom( display, "KWM_DOCKWINDOW", False );
if (_kde_net_wm_system_tray_window_for == None)
_kde_net_wm_system_tray_window_for = TSXInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
if (_net_kde_system_tray_window_for == None)
_net_kde_system_tray_window_for = TSXInternAtom( display, "_NET_KDE_SYSTEM_TRAY_WINDOW_FOR", False );
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = X11DRV_GetXRootWindow();
if (X11DRV_GetXRootWindow() != DefaultRootWindow(display)) wndPtr->flags |= WIN_NATIVE;
X11DRV_WND_RegisterWindow( wndPtr );
return TRUE;
}
/**********************************************************************
* X11DRV_WND_IconChanged
*
* hIcon or hIconSm has changed (or is being initialised for the
* first time). Complete the X11 driver-specific initialisation.
*
* This is not entirely correct, may need to create
* an icon window and set the pixmap as a background
*/
static void X11DRV_WND_IconChanged(WND *wndPtr)
{
HICON16 hIcon = NC_IconForWindow(wndPtr);
if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
if (!hIcon)
{
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap= 0;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
}
else
{
HBITMAP hbmOrig;
RECT rcMask;
BITMAP bmMask;
ICONINFO ii;
HDC hDC;
GetIconInfo(hIcon, &ii);
X11DRV_CreateBitmap(ii.hbmMask);
X11DRV_CreateBitmap(ii.hbmColor);
GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
rcMask.top = 0;
rcMask.left = 0;
rcMask.right = bmMask.bmWidth;
rcMask.bottom = bmMask.bmHeight;
hDC = CreateCompatibleDC(0);
hbmOrig = SelectObject(hDC, ii.hbmMask);
InvertRect(hDC, &rcMask);
SelectObject(hDC, hbmOrig);
DeleteDC(hDC);
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = ii.hbmColor;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= ii.hbmMask;
}
return;
}
static void X11DRV_WND_SetIconHints(WND *wndPtr, XWMHints *hints)
{
if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap)
{
hints->icon_pixmap
= X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap);
hints->flags |= IconPixmapHint;
}
else
hints->flags &= ~IconPixmapHint;
if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask)
{
hints->icon_mask
= X11DRV_BITMAP_Pixmap(((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
hints->flags |= IconMaskHint;
}
else
hints->flags &= ~IconMaskHint;
}
/**********************************************************************
* X11DRV_WND_UpdateIconHints
*
* hIcon or hIconSm has changed (or is being initialised for the
* first time). Complete the X11 driver-specific initialisation
* and set the window hints.
*
* This is not entirely correct, may need to create
* an icon window and set the pixmap as a background
*/
static void X11DRV_WND_UpdateIconHints(WND *wndPtr)
{
XWMHints* wm_hints;
X11DRV_WND_IconChanged(wndPtr);
wm_hints = TSXGetWMHints( display, X11DRV_WND_GetXWindow(wndPtr) );
if (!wm_hints) wm_hints = TSXAllocWMHints();
if (wm_hints)
{
X11DRV_WND_SetIconHints(wndPtr, wm_hints);
TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
TSXFree( wm_hints );
}
}
/**********************************************************************
* X11DRV_WND_CreateWindow
*/
BOOL X11DRV_WND_CreateWindow(WND *wndPtr, CREATESTRUCTA *cs, BOOL bUnicode)
{
/* Create the X window (only for top-level windows, and then only */
/* when there's no desktop window) */
if ((X11DRV_GetXRootWindow() == DefaultRootWindow(display))
&& (wndPtr->parent->hwndSelf == GetDesktopWindow()))
{
Window wGroupLeader;
XWMHints* wm_hints;
XSetWindowAttributes win_attr;
/* Create "managed" windows only if a title bar or resizable */
/* frame is required. */
if (WIN_WindowNeedsWMBorder(cs->style, cs->dwExStyle)) {
win_attr.event_mask = ExposureMask | KeyPressMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
FocusChangeMask | StructureNotifyMask;
win_attr.override_redirect = FALSE;
wndPtr->dwExStyle |= WS_EX_MANAGED;
} else {
win_attr.event_mask = ExposureMask | KeyPressMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
FocusChangeMask;
win_attr.override_redirect = TRUE;
}
wndPtr->flags |= WIN_NATIVE;
win_attr.bit_gravity = (wndPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ? BGForget : BGNorthWest;
win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
win_attr.backing_store = NotUseful;
win_attr.save_under = ((wndPtr->clsStyle & CS_SAVEBITS) != 0);
win_attr.cursor = X11DRV_MOUSE_XCursor;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask = 0;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->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 (cs->cx <= 0) cs->cx = 1;
if (cs->cy <= 0) cs->cy = 1;
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
TSXCreateWindow( display, X11DRV_GetXRootWindow(),
cs->x, cs->y, cs->cx, cs->cy,
0, screen_depth,
InputOutput, visual,
CWEventMask | CWOverrideRedirect |
CWColormap | CWCursor | CWSaveUnder |
CWBackingStore | CWBitGravity,
&win_attr );
if(!(wGroupLeader = X11DRV_WND_GetXWindow(wndPtr)))
return FALSE;
/* If we are the systray, we need to be managed to be noticed by KWM */
if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW)
X11DRV_WND_DockWindow(wndPtr);
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, ((X11DRV_WND_DATA *) wndPtr->pDriverData)->window, class_hints );
TSXFree (class_hints);
}
if (size_hints)
{
size_hints->win_gravity = StaticGravity;
size_hints->x = cs->x;
size_hints->y = cs->y;
size_hints->flags = PWinGravity|PPosition;
if (HAS_DLGFRAME(cs->style,cs->dwExStyle))
{
size_hints->min_width = size_hints->max_width = cs->cx;
size_hints->min_height = size_hints->max_height = cs->cy;
size_hints->flags |= PMinSize | PMaxSize;
}
TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr),
size_hints, XA_WM_NORMAL_HINTS );
TSXFree(size_hints);
}
}
if (cs->hwndParent) /* Get window owner */
{
Window w;
WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
w = X11DRV_WND_FindXWindow( tmpWnd );
if (w != None)
{
TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), w );
wGroupLeader = w;
}
WIN_ReleaseWndPtr(tmpWnd);
}
if ((wm_hints = TSXAllocWMHints()))
{
wm_hints->flags = InputHint | StateHint | WindowGroupHint;
wm_hints->input = True;
if (wndPtr->dwExStyle & WS_EX_MANAGED)
{
X11DRV_WND_IconChanged(wndPtr);
X11DRV_WND_SetIconHints(wndPtr, wm_hints);
wm_hints->initial_state = (wndPtr->dwStyle & WS_MINIMIZE)
? IconicState : NormalState;
}
else
wm_hints->initial_state = NormalState;
wm_hints->window_group = wGroupLeader;
TSXSetWMHints( display, X11DRV_WND_GetXWindow(wndPtr), wm_hints );
TSXFree(wm_hints);
}
X11DRV_WND_RegisterWindow( wndPtr );
}
return TRUE;
}
/***********************************************************************
* X11DRV_WND_DestroyWindow
*/
BOOL X11DRV_WND_DestroyWindow(WND *wndPtr)
{
Window w;
if ((w = X11DRV_WND_GetXWindow(wndPtr)))
{
XEvent xe;
TSXDeleteContext( display, w, winContext );
TSXDestroyWindow( display, w );
while( TSXCheckWindowEvent(display, w, NoEventMask, &xe) );
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap )
{
DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap );
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconBitmap = 0;
}
if( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask )
{
DeleteObject( ((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask);
((X11DRV_WND_DATA *) wndPtr->pDriverData)->hWMIconMask= 0;
}
}
return TRUE;
}
/*****************************************************************
* X11DRV_WND_SetParent
*/
WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
{
WND *pDesktop = WIN_GetDesktop();
if( wndPtr && pWndParent && (wndPtr != pDesktop) )
{
WND* pWndPrev = wndPtr->parent;
if( pWndParent != pWndPrev )
{
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;
}
WIN_UnlinkWindow(wndPtr->hwndSelf);
wndPtr->parent = pWndParent;
/* Create an X counterpart for reparented top-level windows
* when not in the desktop mode. */
if( pWndParent == pDesktop )
{
if( X11DRV_GetXRootWindow() == DefaultRootWindow(display) )
{
CREATESTRUCTA cs;
cs.lpCreateParams = NULL;
cs.hInstance = 0; /* not used in following call */
cs.hMenu = 0; /* not used in following call */
cs.hwndParent = pWndParent->hwndSelf;
cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
if (!cs.cy)
cs.cy = 1;
cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
if (!cs.cx)
cs.cx = 1;
cs.y = wndPtr->rectWindow.top;
cs.x = wndPtr->rectWindow.left;
cs.style = wndPtr->dwStyle;
cs.lpszName = 0; /* not used in following call */
cs.lpszClass = 0; /*not used in following call */
cs.dwExStyle = wndPtr->dwExStyle;
X11DRV_WND_CreateWindow(wndPtr, &cs, FALSE);
}
}
else /* a child window */
{
if( !( wndPtr->dwStyle & WS_CHILD ) )
{
if( wndPtr->wIDmenu != 0)
{
DestroyMenu( (HMENU) wndPtr->wIDmenu );
wndPtr->wIDmenu = 0;
}
}
}
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
}
WIN_ReleaseDesktop();
return pWndPrev;
} /* failure */
WIN_ReleaseDesktop();
return 0;
}
/***********************************************************************
* X11DRV_WND_ForceWindowRaise
*
@ -755,7 +303,7 @@ void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangeP
{
TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
if( winposPtr->clsStyle & (CS_VREDRAW | CS_HREDRAW) )
X11DRV_WND_SetHostAttr( winposPtr, HAK_BITGRAVITY, BGForget );
X11DRV_WND_SetGravity( winposPtr, ForgetGravity );
}
}
@ -768,83 +316,6 @@ void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bChangeP
WIN_ReleaseWndPtr(winposPtr);
}
/*****************************************************************
* X11DRV_WND_SetText
*/
void X11DRV_WND_SetText(WND *wndPtr, LPCWSTR text)
{
UINT count;
char *buffer;
static UINT text_cp = (UINT)-1;
Window win;
if (!(win = X11DRV_WND_GetXWindow(wndPtr))) return;
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");
return;
}
WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
TSXStoreName( display, win, buffer );
TSXSetIconName( display, win, buffer );
HeapFree( GetProcessHeap(), 0, buffer );
}
/*****************************************************************
* X11DRV_WND_SetFocus
*
* Set the X focus.
* Explicit colormap management seems to work only with OLVWM.
*/
void X11DRV_WND_SetFocus(WND *wndPtr)
{
HWND hwnd = wndPtr->hwndSelf;
XWindowAttributes win_attr;
Window win;
WND *w = wndPtr;
if (X11DRV_WND_IsZeroSizeWnd(wndPtr))
return;
/* Only mess with the X focus if there's */
/* no desktop window and if the window is not managed by the WM. */
if ((X11DRV_GetXRootWindow() != DefaultRootWindow(display))) return;
while (w && !((X11DRV_WND_DATA *) w->pDriverData)->window)
w = w->parent;
if (!w) w = wndPtr;
if (w->dwExStyle & WS_EX_MANAGED) return;
if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
{
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
return;
}
/* Set X focus and install colormap */
if (!(win = X11DRV_WND_FindXWindow(wndPtr))) return;
if (!TSXGetWindowAttributes( display, win, &win_attr ) ||
(win_attr.map_state != IsViewable))
return; /* If window is not viewable, don't change anything */
TSXSetInputFocus( display, win, RevertToParent, CurrentTime );
if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
TSXInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
EVENT_Synchronize();
}
/*****************************************************************
* X11DRV_WND_PreSizeMove
*/
@ -896,89 +367,7 @@ void X11DRV_WND_SurfaceCopy(WND* wndPtr, HDC hdc, INT dx, INT dy,
GDI_ReleaseObj( hdc );
if (bUpdate) /* Make sure exposure events have been processed */
EVENT_Synchronize();
}
/***********************************************************************
* X11DRV_WND_SetDrawable
*
* Set the drawable, origin and dimensions for the DC associated to
* a given window.
*/
void X11DRV_WND_SetDrawable(WND *wndPtr, HDC hdc, WORD flags, BOOL bSetClipOrigin)
{
DC *dc = DC_GetDCPtr( hdc );
X11DRV_PDEVICE *physDev;
INT dcOrgXCopy = 0, dcOrgYCopy = 0;
BOOL offsetClipRgn = FALSE;
if (!dc) return;
physDev = (X11DRV_PDEVICE *)dc->physDev;
if (!wndPtr) /* Get a DC for the whole screen */
{
dc->DCOrgX = 0;
dc->DCOrgY = 0;
physDev->drawable = X11DRV_GetXRootWindow();
TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
}
else
{
/*
* 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))
{
dcOrgXCopy = dc->DCOrgX;
dcOrgYCopy = dc->DCOrgY;
offsetClipRgn = TRUE;
}
if (flags & DCX_WINDOW)
{
dc->DCOrgX = wndPtr->rectWindow.left;
dc->DCOrgY = wndPtr->rectWindow.top;
}
else
{
dc->DCOrgX = wndPtr->rectClient.left;
dc->DCOrgY = wndPtr->rectClient.top;
}
while (!X11DRV_WND_GetXWindow(wndPtr))
{
wndPtr = wndPtr->parent;
dc->DCOrgX += wndPtr->rectClient.left;
dc->DCOrgY += wndPtr->rectClient.top;
}
dc->DCOrgX -= wndPtr->rectWindow.left;
dc->DCOrgY -= wndPtr->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(wndPtr);
#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
}
GDI_ReleaseObj( hdc );
X11DRV_Synchronize();
}
/***********************************************************************
@ -1018,6 +407,20 @@ static BOOL X11DRV_SetWMHint(Display* display, WND* wndPtr, int hint, int val)
}
void X11DRV_WND_SetGravity( WND* wnd, int value )
{
X11DRV_WND_DATA *data = wnd->pDriverData;
if (data->window && data->bit_gravity != value )
{
XSetWindowAttributes win_attr;
win_attr.bit_gravity = value;
data->bit_gravity = value;
TSXChangeWindowAttributes( display, data->window, CWBitGravity, &win_attr );
}
}
/***********************************************************************
* X11DRV_WND_SetHostAttr
*
@ -1031,8 +434,6 @@ BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
if( (w = X11DRV_WND_GetXWindow(wnd)) )
{
XSetWindowAttributes win_attr;
switch( ha )
{
case HAK_ICONICSTATE: /* called when a window is minimized/restored */
@ -1086,142 +487,7 @@ BOOL X11DRV_WND_SetHostAttr(WND* wnd, INT ha, INT value)
return TRUE;
}
break;
case HAK_BITGRAVITY: /* called when a window is resized */
if( ((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity != value )
{
win_attr.bit_gravity = value;
((X11DRV_WND_DATA *) wnd->pDriverData)->bit_gravity = value;
TSXChangeWindowAttributes( display, w, CWBitGravity, &win_attr );
}
return TRUE;
case HAK_ICONS: /* called when the icons change */
if ( (wnd->dwExStyle & WS_EX_MANAGED) )
X11DRV_WND_UpdateIconHints(wnd);
return TRUE;
case HAK_ACCEPTFOCUS: /* called when a window is disabled/enabled */
if( (wnd->dwExStyle & WS_EX_MANAGED) )
return X11DRV_SetWMHint( display, wnd, InputHint, value );
}
}
return FALSE;
}
/***********************************************************************
* X11DRV_WND_IsSelfClipping
*/
BOOL X11DRV_WND_IsSelfClipping(WND *wndPtr)
{
return X11DRV_WND_GetXWindow(wndPtr) != None;
}
/***********************************************************************
* X11DRV_WND_DockWindow
*
* 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 ;)
*/
void X11DRV_WND_DockWindow(WND *wndPtr)
{
int data = 1;
Window win = X11DRV_WND_GetXWindow(wndPtr);
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
);
}
if (_net_kde_system_tray_window_for != None) {
TSXChangeProperty(
display,
win,
_net_kde_system_tray_window_for,
XA_WINDOW,
32,
PropModeReplace,
(char*)&win,
1
);
}
}
/***********************************************************************
* X11DRV_WND_SetWindowRgn
*
* Assign specified region to window (for non-rectangular windows)
*/
void X11DRV_WND_SetWindowRgn(WND *wndPtr, HRGN hrgnWnd)
{
#ifdef HAVE_LIBXSHAPE
Window win = X11DRV_WND_GetXWindow(wndPtr);
if (!win) return;
if (!hrgnWnd)
{
TSXShapeCombineMask( display, win, ShapeBounding, 0, 0, None, ShapeSet );
}
else
{
XRectangle *aXRect;
DWORD size;
DWORD dwBufferSize = GetRegionData(hrgnWnd, 0, NULL);
PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
if (!pRegionData) return;
GetRegionData(hrgnWnd, dwBufferSize, pRegionData);
size = pRegionData->rdh.nCount;
/* convert region's "Windows rectangles" to XRectangles */
aXRect = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*aXRect) );
if (aXRect)
{
XRectangle* pCurrRect = aXRect;
RECT *pRect = (RECT*) pRegionData->Buffer;
for (; pRect < ((RECT*) pRegionData->Buffer) + size ; ++pRect, ++pCurrRect)
{
pCurrRect->x = pRect->left;
pCurrRect->y = pRect->top;
pCurrRect->height = pRect->bottom - pRect->top;
pCurrRect->width = pRect->right - pRect->left;
TRACE("Rectangle %04d of %04ld data: X=%04d, Y=%04d, Height=%04d, Width=%04d.\n",
pRect - (RECT*) pRegionData->Buffer,
size,
pCurrRect->x,
pCurrRect->y,
pCurrRect->height,
pCurrRect->width);
}
/* shape = non-rectangular windows (X11/extensions) */
TSXShapeCombineRectangles( display, win, ShapeBounding,
0, 0, aXRect,
pCurrRect - aXRect, ShapeSet, YXBanded );
HeapFree(GetProcessHeap(), 0, aXRect );
}
HeapFree(GetProcessHeap(), 0, pRegionData);
}
#endif /* HAVE_LIBXSHAPE */
}