650 lines
20 KiB
C
650 lines
20 KiB
C
/*
|
|
* X11 windows driver
|
|
*
|
|
* Copyright 1993, 1994, 1995, 1996 Alexandre Julliard
|
|
* 1993 David Metcalfe
|
|
* 1995, 1996 Alex Korobka
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#ifndef X_DISPLAY_MISSING
|
|
|
|
#include <X11/Xatom.h>
|
|
#include "ts_xlib.h"
|
|
#include "ts_xutil.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "color.h"
|
|
#include "debug.h"
|
|
#include "display.h"
|
|
#include "dce.h"
|
|
#include "options.h"
|
|
#include "message.h"
|
|
#include "heap.h"
|
|
#include "win.h"
|
|
#include "wintypes.h"
|
|
#include "class.h"
|
|
#include "x11drv.h"
|
|
|
|
/**********************************************************************/
|
|
|
|
extern Cursor X11DRV_MOUSE_XCursor; /* Current X cursor */
|
|
|
|
/**********************************************************************/
|
|
|
|
/* 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;
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_GetXWindow
|
|
*
|
|
* Return the X window associated to a window.
|
|
*/
|
|
Window X11DRV_WND_GetXWindow(WND *wndPtr)
|
|
{
|
|
return wndPtr ?
|
|
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_FindXWindow
|
|
*
|
|
* Return the the first X window associated to a window chain.
|
|
*/
|
|
Window X11DRV_WND_FindXWindow(WND *wndPtr)
|
|
{
|
|
while (wndPtr &&
|
|
!((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
|
|
wndPtr = wndPtr->parent;
|
|
return wndPtr ?
|
|
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_GetXScreen
|
|
*
|
|
* Return the X screen associated to the window.
|
|
*/
|
|
Screen *X11DRV_WND_GetXScreen(WND *wndPtr)
|
|
{
|
|
while(wndPtr->parent) wndPtr = wndPtr->parent;
|
|
return X11DRV_DESKTOP_GetXScreen((struct tagDESKTOP *) wndPtr->wExtra);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_GetXRootWindow
|
|
*
|
|
* Return the X display associated to the window.
|
|
*/
|
|
Window X11DRV_WND_GetXRootWindow(WND *wndPtr)
|
|
{
|
|
while(wndPtr->parent) wndPtr = wndPtr->parent;
|
|
return X11DRV_DESKTOP_GetXRootWindow((struct tagDESKTOP *) wndPtr->wExtra);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* 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 );
|
|
}
|
|
|
|
/**********************************************************************
|
|
* X11DRV_WND_Initialize
|
|
*/
|
|
void X11DRV_WND_Initialize(WND *wndPtr)
|
|
{
|
|
X11DRV_WND_DATA *pWndDriverData =
|
|
(X11DRV_WND_DATA *) HeapAlloc(SystemHeap, 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(win,"Trying to destroy window again. Not good.\n");
|
|
return;
|
|
}
|
|
if(pWndDriverData->window)
|
|
{
|
|
ERR(win,
|
|
"WND destroyed without destroying "
|
|
"the associated X Window (%ld)\n",
|
|
pWndDriverData->window
|
|
);
|
|
}
|
|
HeapFree(SystemHeap, 0, wndPtr->pDriverData);
|
|
wndPtr->pDriverData = NULL;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* X11DRV_WND_CreateDesktopWindow
|
|
*/
|
|
BOOL32 X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL32 bUnicode)
|
|
{
|
|
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 );
|
|
|
|
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
|
|
X11DRV_WND_GetXRootWindow( wndPtr );
|
|
X11DRV_WND_RegisterWindow( wndPtr );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* X11DRV_WND_CreateWindow
|
|
*/
|
|
BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode)
|
|
{
|
|
/* Create the X window (only for top-level windows, and then only */
|
|
/* when there's no desktop window) */
|
|
|
|
if (!(cs->style & WS_CHILD) &&
|
|
(X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
|
|
{
|
|
XSetWindowAttributes win_attr;
|
|
|
|
if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
|
|
(cs->dwExStyle & WS_EX_DLGMODALFRAME)))
|
|
{
|
|
win_attr.event_mask = ExposureMask | KeyPressMask |
|
|
KeyReleaseMask | PointerMotionMask |
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
FocusChangeMask | StructureNotifyMask;
|
|
win_attr.override_redirect = FALSE;
|
|
wndPtr->flags |= WIN_MANAGED;
|
|
}
|
|
else
|
|
{
|
|
win_attr.event_mask = ExposureMask | KeyPressMask |
|
|
KeyReleaseMask | PointerMotionMask |
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
FocusChangeMask;
|
|
win_attr.override_redirect = TRUE;
|
|
}
|
|
win_attr.colormap = X11DRV_COLOR_GetColormap();
|
|
win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
|
|
win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
|
|
win_attr.cursor = X11DRV_MOUSE_XCursor;
|
|
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window =
|
|
TSXCreateWindow( display,
|
|
X11DRV_WND_GetXRootWindow(wndPtr),
|
|
cs->x, cs->y, cs->cx, cs->cy,
|
|
0, CopyFromParent,
|
|
InputOutput, CopyFromParent,
|
|
CWEventMask | CWOverrideRedirect |
|
|
CWColormap | CWCursor | CWSaveUnder |
|
|
CWBackingStore, &win_attr );
|
|
|
|
if(!X11DRV_WND_GetXWindow(wndPtr))
|
|
return FALSE;
|
|
|
|
if (wndPtr->flags & WIN_MANAGED) {
|
|
XClassHint *class_hints = TSXAllocClassHint();
|
|
|
|
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 (cs->dwExStyle & WS_EX_DLGMODALFRAME) {
|
|
XSizeHints* size_hints = TSXAllocSizeHints();
|
|
|
|
if (size_hints) {
|
|
size_hints->min_width = size_hints->max_width = cs->cx;
|
|
size_hints->min_height = size_hints->max_height = cs->cy;
|
|
size_hints->flags = (PSize | PMinSize | PMaxSize);
|
|
TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(wndPtr), size_hints,
|
|
XA_WM_NORMAL_HINTS );
|
|
TSXFree(size_hints);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cs->hwndParent) /* Get window owner */
|
|
{
|
|
Window win = X11DRV_WND_FindXWindow( WIN_FindWndPtr( cs->hwndParent ) );
|
|
if (win) TSXSetTransientForHint( display, X11DRV_WND_GetXWindow(wndPtr), win );
|
|
}
|
|
X11DRV_WND_RegisterWindow( wndPtr );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_DestroyWindow
|
|
*/
|
|
BOOL32 X11DRV_WND_DestroyWindow(WND *wndPtr)
|
|
{
|
|
if (X11DRV_WND_GetXWindow(wndPtr))
|
|
{
|
|
XEvent xe;
|
|
TSXDeleteContext( display, X11DRV_WND_GetXWindow(wndPtr), winContext );
|
|
TSXDestroyWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
|
|
while( TSXCheckWindowEvent(display, X11DRV_WND_GetXWindow(wndPtr), NoEventMask, &xe) );
|
|
((X11DRV_WND_DATA *) wndPtr->pDriverData)->window = None;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************
|
|
* X11DRV_WND_SetParent
|
|
*/
|
|
WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
|
|
{
|
|
if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) )
|
|
{
|
|
WND* pWndPrev = wndPtr->parent;
|
|
|
|
if( pWndParent != pWndPrev )
|
|
{
|
|
BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf);
|
|
|
|
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;
|
|
}
|
|
else if( bFixupDCE )
|
|
DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
|
|
|
|
WIN_UnlinkWindow(wndPtr->hwndSelf);
|
|
wndPtr->parent = pWndParent;
|
|
|
|
/* Create an X counterpart for reparented top-level windows
|
|
* when not in the desktop mode. */
|
|
|
|
if( pWndParent == WIN_GetDesktop () )
|
|
{
|
|
wndPtr->dwStyle &= ~WS_CHILD;
|
|
wndPtr->wIDmenu = 0;
|
|
if( X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display) )
|
|
{
|
|
CREATESTRUCT32A cs;
|
|
cs.lpCreateParams = NULL;
|
|
cs.hInstance = 0; /* not used if following call */
|
|
cs.hMenu = 0; /* not used in following call */
|
|
cs.hwndParent = pWndParent->hwndSelf;
|
|
cs.cy = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
|
|
cs.cx = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
|
|
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, wndPtr->class,
|
|
&cs, FALSE);
|
|
}
|
|
}
|
|
else /* a child window */
|
|
{
|
|
if( !( wndPtr->dwStyle & WS_CHILD ) )
|
|
{
|
|
wndPtr->dwStyle |= WS_CHILD;
|
|
if( wndPtr->wIDmenu != 0)
|
|
{
|
|
DestroyMenu32( (HMENU32) wndPtr->wIDmenu );
|
|
wndPtr->wIDmenu = 0;
|
|
}
|
|
}
|
|
}
|
|
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
|
|
|
|
if( bFixupDCE )
|
|
{
|
|
DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
|
|
UpdateWindow32(wndPtr->hwndSelf);
|
|
}
|
|
}
|
|
return pWndPrev;
|
|
} /* failure */
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_ForceWindowRaise
|
|
*
|
|
* Raise a window on top of the X stacking order, while preserving
|
|
* the correct Windows Z order.
|
|
*/
|
|
void X11DRV_WND_ForceWindowRaise(WND *wndPtr)
|
|
{
|
|
XWindowChanges winChanges;
|
|
WND *wndPrev;
|
|
|
|
if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) )
|
|
return;
|
|
|
|
/* Raise all windows up to wndPtr according to their Z order.
|
|
* (it would be easier with sibling-related Below but it doesn't
|
|
* work very well with SGI mwm for instance)
|
|
*/
|
|
winChanges.stack_mode = Above;
|
|
while (wndPtr)
|
|
{
|
|
if (X11DRV_WND_GetXWindow(wndPtr))
|
|
TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(wndPtr), 0,
|
|
CWStackMode, &winChanges );
|
|
wndPrev = WIN_GetDesktop()->child;
|
|
if (wndPrev == wndPtr) break;
|
|
while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
|
|
wndPtr = wndPrev;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_FindDesktopXWindow [Internal]
|
|
*
|
|
* Find the actual X window which needs be restacked.
|
|
* Used by X11DRV_SetWindowPos().
|
|
*/
|
|
static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr )
|
|
{
|
|
if (!(wndPtr->flags & WIN_MANAGED))
|
|
return X11DRV_WND_GetXWindow(wndPtr);
|
|
else
|
|
{
|
|
Window window, root, parent, *children;
|
|
int nchildren;
|
|
window = X11DRV_WND_GetXWindow(wndPtr);
|
|
for (;;)
|
|
{
|
|
TSXQueryTree( display, window, &root, &parent,
|
|
&children, &nchildren );
|
|
TSXFree( children );
|
|
if (parent == root)
|
|
return window;
|
|
window = parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WINPOS_SetXWindowPos
|
|
*
|
|
* SetWindowPos() for an X window. Used by the real SetWindowPos().
|
|
*/
|
|
void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS)
|
|
{
|
|
XWindowChanges winChanges;
|
|
int changeMask = 0;
|
|
WND *winposPtr = WIN_FindWndPtr( winpos->hwnd );
|
|
|
|
if(!wndPtr->hwndSelf) wndPtr = NULL; /* FIXME: WND destroyed, shouldn't happend!!! */
|
|
|
|
if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
|
|
{
|
|
if(X11DRV_WND_GetXWindow(wndPtr))
|
|
TSXUnmapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
|
|
}
|
|
|
|
if(bSMC_SETXPOS)
|
|
{
|
|
if ( !(winpos->flags & SWP_NOSIZE))
|
|
{
|
|
winChanges.width = winpos->cx;
|
|
winChanges.height = winpos->cy;
|
|
changeMask |= CWWidth | CWHeight;
|
|
|
|
/* Tweak dialog window size hints */
|
|
|
|
if ((winposPtr->flags & WIN_MANAGED) &&
|
|
(winposPtr->dwExStyle & WS_EX_DLGMODALFRAME))
|
|
{
|
|
XSizeHints *size_hints = TSXAllocSizeHints();
|
|
|
|
if (size_hints)
|
|
{
|
|
long supplied_return;
|
|
|
|
TSXGetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
|
|
&supplied_return, XA_WM_NORMAL_HINTS);
|
|
size_hints->min_width = size_hints->max_width = winpos->cx;
|
|
size_hints->min_height = size_hints->max_height = winpos->cy;
|
|
TSXSetWMSizeHints( display, X11DRV_WND_GetXWindow(winposPtr), size_hints,
|
|
XA_WM_NORMAL_HINTS );
|
|
TSXFree(size_hints);
|
|
}
|
|
}
|
|
}
|
|
if (!(winpos->flags & SWP_NOMOVE))
|
|
{
|
|
winChanges.x = winpos->x;
|
|
winChanges.y = winpos->y;
|
|
changeMask |= CWX | CWY;
|
|
}
|
|
if (!(winpos->flags & SWP_NOZORDER))
|
|
{
|
|
winChanges.stack_mode = Below;
|
|
changeMask |= CWStackMode;
|
|
|
|
if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
|
|
else if (winpos->hwndInsertAfter != HWND_BOTTOM)
|
|
{
|
|
WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
|
|
Window stack[2];
|
|
|
|
stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr );
|
|
stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr );
|
|
|
|
/* for stupid window managers (i.e. all of them) */
|
|
|
|
TSXRestackWindows(display, stack, 2);
|
|
changeMask &= ~CWStackMode;
|
|
}
|
|
}
|
|
if (changeMask)
|
|
{
|
|
TSXReconfigureWMWindow( display, X11DRV_WND_GetXWindow(winposPtr), 0, changeMask, &winChanges );
|
|
}
|
|
}
|
|
|
|
if ( winpos->flags & SWP_SHOWWINDOW )
|
|
{
|
|
if(X11DRV_WND_GetXWindow(wndPtr)) TSXMapWindow( display, X11DRV_WND_GetXWindow(wndPtr) );
|
|
}
|
|
}
|
|
|
|
/*****************************************************************
|
|
* X11DRV_WND_SetText
|
|
*/
|
|
void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text)
|
|
{
|
|
if (!X11DRV_WND_GetXWindow(wndPtr))
|
|
return;
|
|
|
|
TSXStoreName( display, X11DRV_WND_GetXWindow(wndPtr), text );
|
|
TSXSetIconName( display, X11DRV_WND_GetXWindow(wndPtr), text );
|
|
}
|
|
|
|
/*****************************************************************
|
|
* X11DRV_WND_SetFocus
|
|
*
|
|
* Set the X focus.
|
|
* Explicit colormap management seems to work only with OLVWM.
|
|
*/
|
|
void X11DRV_WND_SetFocus(WND *wndPtr)
|
|
{
|
|
HWND32 hwnd = wndPtr->hwndSelf;
|
|
XWindowAttributes win_attr;
|
|
Window win;
|
|
|
|
/* Only mess with the X focus if there's */
|
|
/* no desktop window and no window manager. */
|
|
if ((X11DRV_WND_GetXRootWindow(wndPtr) != DefaultRootWindow(display))
|
|
|| Options.managed) return;
|
|
|
|
if (!hwnd) /* If setting the focus to 0, uninstall the colormap */
|
|
{
|
|
if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
|
|
TSXUninstallColormap( display, X11DRV_COLOR_GetColormap() );
|
|
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 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE)
|
|
TSXInstallColormap( display, X11DRV_COLOR_GetColormap() );
|
|
|
|
EVENT_Synchronize();
|
|
}
|
|
|
|
/*****************************************************************
|
|
* X11DRV_WND_PreSizeMove
|
|
*/
|
|
void X11DRV_WND_PreSizeMove(WND *wndPtr)
|
|
{
|
|
if (!(wndPtr->dwStyle & WS_CHILD) &&
|
|
(X11DRV_WND_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
|
|
TSXGrabServer( display );
|
|
}
|
|
|
|
/*****************************************************************
|
|
* X11DRV_WND_PostSizeMove
|
|
*/
|
|
void X11DRV_WND_PostSizeMove(WND *wndPtr)
|
|
{
|
|
if (!(wndPtr->dwStyle & WS_CHILD) &&
|
|
(X11DRV_GetXRootWindow(wndPtr) == DefaultRootWindow(display)))
|
|
TSXUngrabServer( display );
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
* X11DRV_WND_ScrollWindow
|
|
*/
|
|
void X11DRV_WND_ScrollWindow(
|
|
WND *wndPtr, DC *dcPtr, INT32 dx, INT32 dy,
|
|
const RECT32 *clipRect, BOOL32 bUpdate)
|
|
{
|
|
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcPtr->physDev;
|
|
POINT32 dst, src;
|
|
|
|
if( dx > 0 ) dst.x = (src.x = dcPtr->w.DCOrgX + clipRect->left) + dx;
|
|
else src.x = (dst.x = dcPtr->w.DCOrgX + clipRect->left) - dx;
|
|
|
|
if( dy > 0 ) dst.y = (src.y = dcPtr->w.DCOrgY + clipRect->top) + dy;
|
|
else src.y = (dst.y = dcPtr->w.DCOrgY + clipRect->top) - dy;
|
|
|
|
|
|
if ((clipRect->right - clipRect->left > abs(dx)) &&
|
|
(clipRect->bottom - clipRect->top > abs(dy)))
|
|
{
|
|
if (bUpdate) /* handles non-Wine windows hanging over the scrolled area */
|
|
TSXSetGraphicsExposures( display, physDev->gc, True );
|
|
TSXSetFunction( display, physDev->gc, GXcopy );
|
|
TSXCopyArea( display, physDev->drawable, physDev->drawable,
|
|
physDev->gc, src.x, src.y,
|
|
clipRect->right - clipRect->left - abs(dx),
|
|
clipRect->bottom - clipRect->top - abs(dy),
|
|
dst.x, dst.y );
|
|
if (bUpdate)
|
|
TSXSetGraphicsExposures( display, physDev->gc, False );
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_SetDrawable
|
|
*
|
|
* Set the drawable, origin and dimensions for the DC associated to
|
|
* a given window.
|
|
*/
|
|
void X11DRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL32 bSetClipOrigin)
|
|
{
|
|
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
|
|
|
|
if (!wndPtr) /* Get a DC for the whole screen */
|
|
{
|
|
dc->w.DCOrgX = 0;
|
|
dc->w.DCOrgY = 0;
|
|
physDev->drawable = X11DRV_WND_GetXRootWindow(wndPtr);
|
|
TSXSetSubwindowMode( display, physDev->gc, IncludeInferiors );
|
|
}
|
|
else
|
|
{
|
|
if (flags & DCX_WINDOW)
|
|
{
|
|
dc->w.DCOrgX = wndPtr->rectWindow.left;
|
|
dc->w.DCOrgY = wndPtr->rectWindow.top;
|
|
}
|
|
else
|
|
{
|
|
dc->w.DCOrgX = wndPtr->rectClient.left;
|
|
dc->w.DCOrgY = wndPtr->rectClient.top;
|
|
}
|
|
while (!X11DRV_WND_GetXWindow(wndPtr))
|
|
{
|
|
wndPtr = wndPtr->parent;
|
|
dc->w.DCOrgX += wndPtr->rectClient.left;
|
|
dc->w.DCOrgY += wndPtr->rectClient.top;
|
|
}
|
|
dc->w.DCOrgX -= wndPtr->rectWindow.left;
|
|
dc->w.DCOrgY -= wndPtr->rectWindow.top;
|
|
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->w.DCOrgX, dc->w.DCOrgY );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* X11DRV_WND_IsSelfClipping
|
|
*/
|
|
BOOL32 X11DRV_WND_IsSelfClipping(WND *wndPtr)
|
|
{
|
|
if( X11DRV_WND_GetXWindow(wndPtr) )
|
|
return TRUE; /* X itself will do the clipping */
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#endif /* !defined(X_DISPLAY_MISSING) */
|