Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
2fb7c875
Commit
2fb7c875
authored
Mar 25, 2005
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved DCE support to the X11 driver.
parent
dc84b8a4
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
939 additions
and
914 deletions
+939
-914
Makefile.in
dlls/user/Makefile.in
+0
-1
painting.c
dlls/user/painting.c
+106
-1
user16.c
dlls/user/user16.c
+10
-0
user32.spec
dlls/user/user32.spec
+0
-1
user_main.c
dlls/user/user_main.c
+2
-1
user_private.h
dlls/user/user_private.h
+3
-2
Makefile.in
dlls/x11drv/Makefile.in
+1
-0
dce.c
dlls/x11drv/dce.c
+789
-0
window.c
dlls/x11drv/window.c
+6
-1
winpos.c
dlls/x11drv/winpos.c
+3
-166
x11drv.h
dlls/x11drv/x11drv.h
+14
-10
x11drv.spec
dlls/x11drv/x11drv.spec
+2
-1
dce.h
include/dce.h
+0
-46
win.h
include/win.h
+3
-2
class.c
windows/class.c
+0
-5
dce.c
windows/dce.c
+0
-670
nonclient.c
windows/nonclient.c
+0
-1
win.c
windows/win.c
+0
-6
No files found.
dlls/user/Makefile.in
View file @
2fb7c875
...
...
@@ -18,7 +18,6 @@ C_SRCS = \
$(TOPOBJDIR)
/windows/class.c
\
$(TOPOBJDIR)
/windows/clipboard.c
\
$(TOPOBJDIR)
/windows/cursoricon.c
\
$(TOPOBJDIR)
/windows/dce.c
\
$(TOPOBJDIR)
/windows/defdlg.c
\
$(TOPOBJDIR)
/windows/defwnd.c
\
$(TOPOBJDIR)
/windows/dialog.c
\
...
...
dlls/user/painting.c
View file @
2fb7c875
...
...
@@ -32,7 +32,7 @@
#include "winuser.h"
#include "wine/server.h"
#include "win.h"
#include "
dc
e.h"
#include "
user_privat
e.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
win
);
...
...
@@ -417,6 +417,111 @@ BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps )
/***********************************************************************
* GetDCEx (USER32.@)
*/
HDC
WINAPI
GetDCEx
(
HWND
hwnd
,
HRGN
hrgnClip
,
DWORD
flags
)
{
if
(
!
hwnd
)
hwnd
=
GetDesktopWindow
();
else
hwnd
=
WIN_GetFullHandle
(
hwnd
);
if
(
USER_Driver
.
pGetDCEx
)
return
USER_Driver
.
pGetDCEx
(
hwnd
,
hrgnClip
,
flags
);
return
0
;
}
/***********************************************************************
* GetDC (USER32.@)
*
* Get a device context.
*
* RETURNS
* Success: Handle to the device context
* Failure: NULL.
*/
HDC
WINAPI
GetDC
(
HWND
hwnd
)
{
if
(
!
hwnd
)
return
GetDCEx
(
0
,
0
,
DCX_CACHE
|
DCX_WINDOW
);
return
GetDCEx
(
hwnd
,
0
,
DCX_USESTYLE
);
}
/***********************************************************************
* GetWindowDC (USER32.@)
*/
HDC
WINAPI
GetWindowDC
(
HWND
hwnd
)
{
return
GetDCEx
(
hwnd
,
0
,
DCX_USESTYLE
|
DCX_WINDOW
);
}
/***********************************************************************
* ReleaseDC (USER32.@)
*
* Release a device context.
*
* RETURNS
* Success: Non-zero. Resources used by hdc are released.
* Failure: 0.
*/
INT
WINAPI
ReleaseDC
(
HWND
hwnd
,
HDC
hdc
)
{
if
(
USER_Driver
.
pReleaseDC
)
return
USER_Driver
.
pReleaseDC
(
hwnd
,
hdc
);
return
0
;
}
/**********************************************************************
* WindowFromDC (USER32.@)
*/
HWND
WINAPI
WindowFromDC
(
HDC
hDC
)
{
if
(
USER_Driver
.
pWindowFromDC
)
return
USER_Driver
.
pWindowFromDC
(
hDC
);
return
0
;
}
/***********************************************************************
* LockWindowUpdate (USER32.@)
*/
BOOL
WINAPI
LockWindowUpdate
(
HWND
hwnd
)
{
static
HWND
lockedWnd
;
/* This function is fully implemented by the following patch:
*
* http://www.winehq.org/hypermail/wine-patches/2004/01/0142.html
*
* but in order to work properly, it needs the ability to invalidate
* DCEs in other processes when the lock window is changed, which
* isn't possible yet.
* -mike
*/
FIXME
(
"(%p), partial stub!
\n
"
,
hwnd
);
USER_Lock
();
if
(
lockedWnd
)
{
if
(
!
hwnd
)
{
/* Unlock lockedWnd */
/* FIXME: Do something */
}
else
{
/* Attempted to lock a second window */
/* Return FALSE and do nothing */
USER_Unlock
();
return
FALSE
;
}
}
lockedWnd
=
hwnd
;
USER_Unlock
();
return
TRUE
;
}
/***********************************************************************
* RedrawWindow (USER32.@)
*/
BOOL
WINAPI
RedrawWindow
(
HWND
hwnd
,
const
RECT
*
rect
,
HRGN
hrgn
,
UINT
flags
)
...
...
dlls/user/user16.c
View file @
2fb7c875
...
...
@@ -811,6 +811,16 @@ BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
}
/***********************************************************************
* DCHook (USER.362)
*/
BOOL16
WINAPI
DCHook16
(
HDC16
hdc
,
WORD
code
,
DWORD
data
,
LPARAM
lParam
)
{
FIXME
(
"hDC = %x, %i: stub
\n
"
,
hdc
,
code
);
return
FALSE
;
}
/**********************************************************************
* SetMenuContextHelpId (USER.384)
*/
...
...
dlls/user/user32.spec
View file @
2fb7c875
...
...
@@ -725,7 +725,6 @@
################################################################
# Wine dll separation hacks, these will go away, don't use them
#
@ cdecl DCE_InvalidateDCE(long ptr)
@ cdecl HOOK_CallHooks(long long long long long)
@ cdecl USER_Unlock()
@ cdecl WINPOS_ActivateOtherWindow(long)
...
...
dlls/user/user_main.c
View file @
2fb7c875
...
...
@@ -116,7 +116,7 @@ static BOOL load_driver(void)
GET_USER_FUNC
(
EnumDisplaySettingsExW
);
GET_USER_FUNC
(
CreateWindow
);
GET_USER_FUNC
(
DestroyWindow
);
GET_USER_FUNC
(
GetDC
);
GET_USER_FUNC
(
GetDC
Ex
);
GET_USER_FUNC
(
MsgWaitForMultipleObjectsEx
);
GET_USER_FUNC
(
ReleaseDC
);
GET_USER_FUNC
(
ScrollDC
);
...
...
@@ -129,6 +129,7 @@ static BOOL load_driver(void)
GET_USER_FUNC
(
SetWindowText
);
GET_USER_FUNC
(
ShowWindow
);
GET_USER_FUNC
(
SysCommandSizeMove
);
GET_USER_FUNC
(
WindowFromDC
);
GET_USER_FUNC
(
WindowMessage
);
return
TRUE
;
...
...
dlls/user/user_private.h
View file @
2fb7c875
...
...
@@ -100,9 +100,9 @@ typedef struct tagUSER_DRIVER {
/* windowing functions */
BOOL
(
*
pCreateWindow
)(
HWND
,
CREATESTRUCTA
*
,
BOOL
);
BOOL
(
*
pDestroyWindow
)(
HWND
);
BOOL
(
*
pGetDC
)(
HWND
,
HDC
,
HRGN
,
DWORD
);
HDC
(
*
pGetDCEx
)(
HWND
,
HRGN
,
DWORD
);
DWORD
(
*
pMsgWaitForMultipleObjectsEx
)(
DWORD
,
const
HANDLE
*
,
DWORD
,
DWORD
,
DWORD
);
void
(
*
pReleaseDC
)(
HWND
,
HDC
);
BOOL
(
*
pReleaseDC
)(
HWND
,
HDC
);
BOOL
(
*
pScrollDC
)(
HDC
,
INT
,
INT
,
const
RECT
*
,
const
RECT
*
,
HRGN
,
LPRECT
);
void
(
*
pSetFocus
)(
HWND
);
HWND
(
*
pSetParent
)(
HWND
,
HWND
);
...
...
@@ -113,6 +113,7 @@ typedef struct tagUSER_DRIVER {
BOOL
(
*
pSetWindowText
)(
HWND
,
LPCWSTR
);
BOOL
(
*
pShowWindow
)(
HWND
,
INT
);
void
(
*
pSysCommandSizeMove
)(
HWND
,
WPARAM
);
HWND
(
*
pWindowFromDC
)(
HDC
);
LRESULT
(
*
pWindowMessage
)(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
}
USER_DRIVER
;
...
...
dlls/x11drv/Makefile.in
View file @
2fb7c875
...
...
@@ -14,6 +14,7 @@ C_SRCS = \
clipboard.c
\
clipping.c
\
codepage.c
\
dce.c
\
desktop.c
\
dga2.c
\
dib.c
\
...
...
dlls/x11drv/dce.c
0 → 100644
View file @
2fb7c875
/*
* USER DCE functions
*
* Copyright 1993, 2005 Alexandre Julliard
* Copyright 1996, 1997 Alex Korobka
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Note: Visible regions of CS_OWNDC/CS_CLASSDC window DCs
* have to be updated dynamically.
*
* Internal DCX flags:
*
* DCX_WINDOWPAINT - BeginPaint() is in effect
*/
#include "config.h"
#include <assert.h>
#include "win.h"
#include "windef.h"
#include "wingdi.h"
#include "wownt32.h"
#include "ntstatus.h"
#include "x11drv.h"
#include "wine/winbase16.h"
#include "wine/wingdi16.h"
#include "wine/server.h"
#include "wine/list.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dc
);
struct
dce
{
struct
list
entry
;
/* entry in global DCE list */
HDC
hdc
;
HWND
hwnd
;
HRGN
clip_rgn
;
DWORD
flags
;
int
empty
:
1
;
/* DCE is uninitialized */
int
inuse
:
1
;
/* DCE is in use */
int
dirty
:
1
;
/* ReleaseDC should wipe instead of caching */
void
*
class_ptr
;
/* ptr to identify window class for class DCEs */
ULONG
count
;
/* reference count for class DCEs */
};
static
struct
list
dce_list
=
LIST_INIT
(
dce_list
);
static
void
delete_clip_rgn
(
struct
dce
*
);
static
INT
release_dc
(
struct
dce
*
);
static
BOOL16
CALLBACK
dc_hook
(
HDC16
hDC
,
WORD
code
,
DWORD
data
,
LPARAM
lParam
);
static
CRITICAL_SECTION
dce_section
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
0
,
0
,
&
dce_section
,
{
&
critsect_debug
.
ProcessLocksList
,
&
critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
0
,
(
DWORD
)(
__FILE__
": dce_section"
)
}
};
static
CRITICAL_SECTION
dce_section
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
const
WCHAR
displayW
[]
=
{
'D'
,
'I'
,
'S'
,
'P'
,
'L'
,
'A'
,
'Y'
,
0
};
/***********************************************************************
* dump_cache
*/
static
void
dump_cache
(
void
)
{
struct
dce
*
dce
;
EnterCriticalSection
(
&
dce_section
);
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
TRACE
(
"%p: hwnd %p dcx %08lx %s %s
\n
"
,
dce
,
dce
->
hwnd
,
dce
->
flags
,
(
dce
->
flags
&
DCX_CACHE
)
?
"Cache"
:
"Owned"
,
dce
->
inuse
?
"InUse"
:
""
);
}
LeaveCriticalSection
(
&
dce_section
);
}
/***********************************************************************
* get_server_visible_region
*/
static
HRGN
get_server_visible_region
(
HWND
hwnd
,
UINT
flags
)
{
RGNDATA
*
data
;
NTSTATUS
status
;
HRGN
ret
=
0
;
size_t
size
=
256
;
do
{
if
(
!
(
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
data
)
+
size
-
1
)))
return
0
;
SERVER_START_REQ
(
get_visible_region
)
{
req
->
window
=
hwnd
;
req
->
flags
=
flags
;
wine_server_set_reply
(
req
,
data
->
Buffer
,
size
);
if
(
!
(
status
=
wine_server_call
(
req
)))
{
size_t
reply_size
=
wine_server_reply_size
(
reply
);
data
->
rdh
.
dwSize
=
sizeof
(
data
->
rdh
);
data
->
rdh
.
iType
=
RDH_RECTANGLES
;
data
->
rdh
.
nCount
=
reply_size
/
sizeof
(
RECT
);
data
->
rdh
.
nRgnSize
=
reply_size
;
ret
=
ExtCreateRegion
(
NULL
,
size
,
data
);
}
else
size
=
reply
->
total_size
;
}
SERVER_END_REQ
;
HeapFree
(
GetProcessHeap
(),
0
,
data
);
}
while
(
status
==
STATUS_BUFFER_OVERFLOW
);
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
ret
;
}
/***********************************************************************
* get_top_clipping_window
*
* Get the top window to clip against (i.e. the top parent that has
* an associated X window).
*/
static
HWND
get_top_clipping_window
(
HWND
hwnd
)
{
HWND
ret
=
GetAncestor
(
hwnd
,
GA_ROOT
);
if
(
!
ret
)
ret
=
GetDesktopWindow
();
return
ret
;
}
/***********************************************************************
* set_drawable
*
* Set the drawable, origin and dimensions for the DC associated to
* a given window.
*/
static
BOOL
set_drawable
(
HWND
hwnd
,
HDC
hdc
,
HRGN
hrgn
,
DWORD
flags
)
{
HWND
top
=
get_top_clipping_window
(
hwnd
);
struct
x11drv_escape_set_drawable
escape
;
struct
x11drv_win_data
*
data
;
escape
.
mode
=
IncludeInferiors
;
/* don't clip siblings if using parent clip region */
if
(
flags
&
DCX_PARENTCLIP
)
flags
&=
~
DCX_CLIPSIBLINGS
;
if
(
top
!=
hwnd
||
!
(
data
=
X11DRV_get_win_data
(
hwnd
)))
{
POINT
client_offset
;
if
(
flags
&
DCX_WINDOW
)
{
RECT
rect
;
GetWindowRect
(
hwnd
,
&
rect
);
escape
.
org
.
x
=
rect
.
left
;
escape
.
org
.
y
=
rect
.
top
;
MapWindowPoints
(
0
,
top
,
&
escape
.
org
,
1
);
escape
.
drawable_org
.
x
=
rect
.
left
-
escape
.
org
.
x
;
escape
.
drawable_org
.
y
=
rect
.
top
-
escape
.
org
.
y
;
}
else
{
escape
.
org
.
x
=
escape
.
org
.
y
=
0
;
escape
.
drawable_org
.
x
=
escape
.
drawable_org
.
y
=
0
;
MapWindowPoints
(
hwnd
,
top
,
&
escape
.
org
,
1
);
MapWindowPoints
(
top
,
0
,
&
escape
.
drawable_org
,
1
);
}
/* now make origins relative to the X window and not the client area */
client_offset
=
X11DRV_get_client_area_offset
(
top
);
escape
.
org
.
x
+=
client_offset
.
x
;
escape
.
org
.
y
+=
client_offset
.
y
;
escape
.
drawable_org
.
x
-=
client_offset
.
x
;
escape
.
drawable_org
.
y
-=
client_offset
.
y
;
escape
.
drawable
=
X11DRV_get_whole_window
(
top
);
}
else
{
if
(
IsIconic
(
hwnd
))
{
escape
.
drawable
=
data
->
icon_window
?
data
->
icon_window
:
data
->
whole_window
;
escape
.
org
.
x
=
0
;
escape
.
org
.
y
=
0
;
escape
.
drawable_org
=
escape
.
org
;
MapWindowPoints
(
hwnd
,
0
,
&
escape
.
drawable_org
,
1
);
}
else
{
escape
.
drawable
=
data
->
whole_window
;
escape
.
drawable_org
.
x
=
data
->
whole_rect
.
left
;
escape
.
drawable_org
.
y
=
data
->
whole_rect
.
top
;
if
(
flags
&
DCX_WINDOW
)
{
escape
.
org
.
x
=
data
->
window_rect
.
left
-
data
->
whole_rect
.
left
;
escape
.
org
.
y
=
data
->
window_rect
.
top
-
data
->
whole_rect
.
top
;
}
else
{
escape
.
org
.
x
=
data
->
client_rect
.
left
;
escape
.
org
.
y
=
data
->
client_rect
.
top
;
}
}
}
escape
.
code
=
X11DRV_SET_DRAWABLE
;
ExtEscape
(
hdc
,
X11DRV_ESCAPE
,
sizeof
(
escape
),
(
LPSTR
)
&
escape
,
0
,
NULL
);
if
(
flags
&
(
DCX_EXCLUDERGN
|
DCX_INTERSECTRGN
)
||
SetHookFlags16
(
HDC_16
(
hdc
),
DCHF_VALIDATEVISRGN
))
/* DC was dirty */
{
/* need to recompute the visible region */
HRGN
visRgn
=
get_server_visible_region
(
hwnd
,
flags
);
if
(
flags
&
(
DCX_EXCLUDERGN
|
DCX_INTERSECTRGN
))
CombineRgn
(
visRgn
,
visRgn
,
hrgn
,
(
flags
&
DCX_INTERSECTRGN
)
?
RGN_AND
:
RGN_DIFF
);
SelectVisRgn16
(
HDC_16
(
hdc
),
HRGN_16
(
visRgn
)
);
DeleteObject
(
visRgn
);
}
return
TRUE
;
}
/***********************************************************************
* release_drawable
*/
static
void
release_drawable
(
HWND
hwnd
,
HDC
hdc
)
{
struct
x11drv_escape_set_drawable
escape
;
escape
.
code
=
X11DRV_SET_DRAWABLE
;
escape
.
drawable
=
root_window
;
escape
.
mode
=
IncludeInferiors
;
escape
.
org
.
x
=
escape
.
org
.
y
=
0
;
escape
.
drawable_org
.
x
=
escape
.
drawable_org
.
y
=
0
;
ExtEscape
(
hdc
,
X11DRV_ESCAPE
,
sizeof
(
escape
),
(
LPSTR
)
&
escape
,
0
,
NULL
);
}
/***********************************************************************
* alloc_cache_dce
*
* Allocate a new cache DCE.
*/
static
struct
dce
*
alloc_cache_dce
(
void
)
{
struct
dce
*
dce
;
if
(
!
(
dce
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
dce
)
)))
return
NULL
;
if
(
!
(
dce
->
hdc
=
CreateDCW
(
displayW
,
NULL
,
NULL
,
NULL
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
dce
);
return
0
;
}
SaveDC
(
dce
->
hdc
);
/* store DCE handle in DC hook data field */
SetDCHook
(
dce
->
hdc
,
dc_hook
,
(
DWORD
)
dce
);
dce
->
hwnd
=
0
;
dce
->
clip_rgn
=
0
;
dce
->
flags
=
DCX_CACHE
;
dce
->
empty
=
1
;
dce
->
inuse
=
0
;
dce
->
dirty
=
0
;
dce
->
class_ptr
=
NULL
;
dce
->
count
=
0
;
EnterCriticalSection
(
&
dce_section
);
list_add_head
(
&
dce_list
,
&
dce
->
entry
);
LeaveCriticalSection
(
&
dce_section
);
return
dce
;
}
/***********************************************************************
* alloc_window_dce
*
* Allocate a DCE for a newly created window if necessary.
*/
void
alloc_window_dce
(
struct
x11drv_win_data
*
data
)
{
struct
dce
*
dce
;
void
*
class_ptr
=
NULL
;
LONG
style
=
GetClassLongW
(
data
->
hwnd
,
GCL_STYLE
);
if
(
!
(
style
&
(
CS_CLASSDC
|
CS_OWNDC
)))
return
;
/* nothing to do */
if
(
!
(
style
&
CS_OWNDC
))
/* class dc */
{
/* hack: get the class pointer from the window structure */
WND
*
win
=
WIN_GetPtr
(
data
->
hwnd
);
class_ptr
=
win
->
class
;
WIN_ReleasePtr
(
win
);
EnterCriticalSection
(
&
dce_section
);
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
if
(
dce
->
class_ptr
==
class_ptr
)
{
dce
->
count
++
;
data
->
dce
=
dce
;
LeaveCriticalSection
(
&
dce_section
);
return
;
}
}
LeaveCriticalSection
(
&
dce_section
);
}
/* now allocate a new one */
if
(
!
(
dce
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
dce
)
)))
return
;
if
(
!
(
dce
->
hdc
=
CreateDCW
(
displayW
,
NULL
,
NULL
,
NULL
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
dce
);
return
;
}
SaveDC
(
dce
->
hdc
);
/* store DCE handle in DC hook data field */
SetDCHook
(
dce
->
hdc
,
dc_hook
,
(
DWORD
)
dce
);
dce
->
hwnd
=
data
->
hwnd
;
dce
->
clip_rgn
=
0
;
dce
->
flags
=
0
;
dce
->
empty
=
0
;
dce
->
inuse
=
1
;
dce
->
dirty
=
0
;
dce
->
class_ptr
=
class_ptr
;
dce
->
count
=
1
;
if
(
style
&
CS_OWNDC
)
{
LONG
win_style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_STYLE
);
if
(
win_style
&
WS_CLIPCHILDREN
)
dce
->
flags
|=
DCX_CLIPCHILDREN
;
if
(
win_style
&
WS_CLIPSIBLINGS
)
dce
->
flags
|=
DCX_CLIPSIBLINGS
;
}
SetHookFlags16
(
HDC_16
(
dce
->
hdc
),
DCHF_INVALIDATEVISRGN
);
EnterCriticalSection
(
&
dce_section
);
list_add_tail
(
&
dce_list
,
&
dce
->
entry
);
LeaveCriticalSection
(
&
dce_section
);
data
->
dce
=
dce
;
}
/***********************************************************************
* free_window_dce
*
* Free a class or window DCE.
*/
void
free_window_dce
(
struct
x11drv_win_data
*
data
)
{
struct
dce
*
dce
=
data
->
dce
;
if
(
dce
)
{
EnterCriticalSection
(
&
dce_section
);
if
(
!--
dce
->
count
)
{
list_remove
(
&
dce
->
entry
);
SetDCHook
(
dce
->
hdc
,
NULL
,
0L
);
DeleteDC
(
dce
->
hdc
);
if
(
dce
->
clip_rgn
)
DeleteObject
(
dce
->
clip_rgn
);
HeapFree
(
GetProcessHeap
(),
0
,
dce
);
}
else
if
(
dce
->
hwnd
==
data
->
hwnd
)
{
if
(
dce
->
flags
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
))
{
release_drawable
(
dce
->
hwnd
,
dce
->
hdc
);
delete_clip_rgn
(
dce
);
dce
->
hwnd
=
0
;
}
}
LeaveCriticalSection
(
&
dce_section
);
data
->
dce
=
NULL
;
}
/* now check for cache DCEs */
EnterCriticalSection
(
&
dce_section
);
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
if
(
dce
->
hwnd
!=
data
->
hwnd
)
continue
;
if
(
!
(
dce
->
flags
&
DCX_CACHE
))
continue
;
if
(
dce
->
inuse
)
/* shared cache DCE */
{
WARN
(
"GetDC() without ReleaseDC() for window %p
\n
"
,
data
->
hwnd
);
release_dc
(
dce
);
}
if
(
dce
->
hwnd
)
release_drawable
(
dce
->
hwnd
,
dce
->
hdc
);
dce
->
hwnd
=
0
;
dce
->
flags
=
DCX_CACHE
;
dce
->
inuse
=
0
;
dce
->
empty
=
1
;
dce
->
dirty
=
0
;
}
LeaveCriticalSection
(
&
dce_section
);
}
/***********************************************************************
* delete_clip_rgn
*/
static
void
delete_clip_rgn
(
struct
dce
*
dce
)
{
dce
->
flags
&=
~
(
DCX_EXCLUDERGN
|
DCX_INTERSECTRGN
|
DCX_WINDOWPAINT
);
if
(
dce
->
clip_rgn
)
DeleteObject
(
dce
->
clip_rgn
);
dce
->
clip_rgn
=
0
;
/* make it dirty so that the vis rgn gets recomputed next time */
dce
->
dirty
=
1
;
SetHookFlags16
(
HDC_16
(
dce
->
hdc
),
DCHF_INVALIDATEVISRGN
);
}
/***********************************************************************
* release_dc
*/
static
BOOL
release_dc
(
struct
dce
*
dce
)
{
if
(
dce
->
empty
)
return
FALSE
;
if
(
!
dce
->
inuse
)
return
FALSE
;
/* restore previous visible region */
if
((
dce
->
flags
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
))
&&
(
dce
->
flags
&
(
DCX_CACHE
|
DCX_WINDOWPAINT
))
)
delete_clip_rgn
(
dce
);
if
(
dce
->
flags
&
DCX_CACHE
)
{
/* make the DC clean so that RestoreDC doesn't try to update the vis rgn */
SetHookFlags16
(
HDC_16
(
dce
->
hdc
),
DCHF_VALIDATEVISRGN
);
RestoreDC
(
dce
->
hdc
,
1
);
/* initial save level is always 1 */
SaveDC
(
dce
->
hdc
);
/* save the state again for next time */
dce
->
inuse
=
0
;
if
(
dce
->
dirty
)
{
/* don't keep around invalidated entries
* because RestoreDC() disables hVisRgn updates
* by removing dirty bit. */
if
(
dce
->
hwnd
)
release_drawable
(
dce
->
hwnd
,
dce
->
hdc
);
dce
->
hwnd
=
0
;
dce
->
flags
=
DCX_CACHE
;
dce
->
empty
=
1
;
dce
->
dirty
=
0
;
}
}
return
TRUE
;
}
/***********************************************************************
* invalidate_dce
*
* It is called from SetWindowPos() - we have to
* mark as dirty all busy DCEs for windows that have pWnd->parent as
* an ancestor and whose client rect intersects with specified update
* rectangle. In addition, pWnd->parent DCEs may need to be updated if
* DCX_CLIPCHILDREN flag is set.
*/
void
invalidate_dce
(
HWND
hwnd
,
const
RECT
*
rect
)
{
HWND
hwndScope
=
GetAncestor
(
hwnd
,
GA_PARENT
);
if
(
hwndScope
)
{
struct
dce
*
dce
;
TRACE
(
"scope hwnd = %p %s
\n
"
,
hwndScope
,
wine_dbgstr_rect
(
rect
)
);
if
(
TRACE_ON
(
dc
))
dump_cache
();
/* walk all DCEs and fixup non-empty entries */
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
if
(
dce
->
empty
)
continue
;
if
((
dce
->
hwnd
==
hwndScope
)
&&
!
(
dce
->
flags
&
DCX_CLIPCHILDREN
))
continue
;
/* child window positions don't bother us */
/* check if DCE window is within the z-order scope */
if
(
hwndScope
==
dce
->
hwnd
||
IsChild
(
hwndScope
,
dce
->
hwnd
))
{
if
(
hwnd
!=
dce
->
hwnd
)
{
/* check if the window rectangle intersects this DCE window */
RECT
tmp
;
GetWindowRect
(
dce
->
hwnd
,
&
tmp
);
MapWindowPoints
(
0
,
hwndScope
,
(
POINT
*
)
&
tmp
,
2
);
if
(
!
IntersectRect
(
&
tmp
,
&
tmp
,
rect
))
continue
;
}
if
(
!
dce
->
inuse
)
{
/* Don't bother with visible regions of unused DCEs */
TRACE
(
"
\t
purged %p dce [%p]
\n
"
,
dce
,
dce
->
hwnd
);
if
(
dce
->
hwnd
)
release_drawable
(
dce
->
hwnd
,
dce
->
hdc
);
dce
->
hwnd
=
0
;
dce
->
flags
&=
DCX_CACHE
;
dce
->
empty
=
1
;
dce
->
dirty
=
0
;
}
else
{
/* Set dirty bits in the hDC and DCE structs */
TRACE
(
"
\t
fixed up %p dce [%p]
\n
"
,
dce
,
dce
->
hwnd
);
dce
->
dirty
=
1
;
SetHookFlags16
(
HDC_16
(
dce
->
hdc
),
DCHF_INVALIDATEVISRGN
);
}
}
}
/* dce list */
}
}
/***********************************************************************
* X11DRV_GetDCEx (X11DRV.@)
*
* Unimplemented flags: DCX_LOCKWINDOWUPDATE
*/
HDC
X11DRV_GetDCEx
(
HWND
hwnd
,
HRGN
hrgnClip
,
DWORD
flags
)
{
struct
x11drv_win_data
*
data
=
X11DRV_get_win_data
(
hwnd
);
struct
dce
*
dce
;
HDC
hdc
=
0
;
DWORD
dcxFlags
=
0
;
BOOL
bUpdateVisRgn
=
TRUE
;
HWND
parent
;
LONG
window_style
=
GetWindowLongW
(
hwnd
,
GWL_STYLE
);
TRACE
(
"hwnd %p, hrgnClip %p, flags %08lx
\n
"
,
hwnd
,
hrgnClip
,
flags
);
/* fixup flags */
if
(
flags
&
(
DCX_WINDOW
|
DCX_PARENTCLIP
))
flags
|=
DCX_CACHE
;
if
(
flags
&
DCX_USESTYLE
)
{
flags
&=
~
(
DCX_CLIPCHILDREN
|
DCX_CLIPSIBLINGS
|
DCX_PARENTCLIP
);
if
(
window_style
&
WS_CLIPSIBLINGS
)
flags
|=
DCX_CLIPSIBLINGS
;
if
(
!
(
flags
&
DCX_WINDOW
))
{
if
(
GetClassLongW
(
hwnd
,
GCL_STYLE
)
&
CS_PARENTDC
)
flags
|=
DCX_PARENTCLIP
;
if
(
window_style
&
WS_CLIPCHILDREN
&&
!
(
window_style
&
WS_MINIMIZE
))
flags
|=
DCX_CLIPCHILDREN
;
if
(
!
data
||
!
data
->
dce
)
flags
|=
DCX_CACHE
;
}
}
if
(
flags
&
DCX_WINDOW
)
flags
&=
~
DCX_CLIPCHILDREN
;
parent
=
GetAncestor
(
hwnd
,
GA_PARENT
);
if
(
!
parent
||
(
parent
==
GetDesktopWindow
()))
flags
=
(
flags
&
~
DCX_PARENTCLIP
)
|
DCX_CLIPSIBLINGS
;
/* it seems parent clip is ignored when clipping siblings or children */
if
(
flags
&
(
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
))
flags
&=
~
DCX_PARENTCLIP
;
if
(
flags
&
DCX_PARENTCLIP
)
{
LONG
parent_style
=
GetWindowLongW
(
parent
,
GWL_STYLE
);
if
(
(
window_style
&
WS_VISIBLE
)
&&
(
parent_style
&
WS_VISIBLE
)
)
{
flags
&=
~
DCX_CLIPCHILDREN
;
if
(
parent_style
&
WS_CLIPSIBLINGS
)
flags
|=
DCX_CLIPSIBLINGS
;
}
}
if
(
!
(
flags
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
)))
hrgnClip
=
0
;
/* find a suitable DCE */
EnterCriticalSection
(
&
dce_section
);
dcxFlags
=
flags
&
(
DCX_PARENTCLIP
|
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
|
DCX_CACHE
|
DCX_WINDOW
);
if
(
flags
&
DCX_CACHE
)
{
struct
dce
*
dceEmpty
=
NULL
,
*
dceUnused
=
NULL
;
/* Strategy: First, we attempt to find a non-empty but unused DCE with
* compatible flags. Next, we look for an empty entry. If the cache is
* full we have to purge one of the unused entries.
*/
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
if
((
dce
->
flags
&
DCX_CACHE
)
&&
!
dce
->
inuse
)
{
dceUnused
=
dce
;
if
(
dce
->
empty
)
dceEmpty
=
dce
;
else
if
((
dce
->
hwnd
==
hwnd
)
&&
((
dce
->
flags
&
(
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
|
DCX_CACHE
|
DCX_WINDOW
|
DCX_PARENTCLIP
))
==
dcxFlags
))
{
TRACE
(
"
\t
found valid %p dce [%p], flags %08lx
\n
"
,
dce
,
hwnd
,
dcxFlags
);
bUpdateVisRgn
=
FALSE
;
break
;
}
}
}
if
(
&
dce
->
entry
==
&
dce_list
)
/* nothing found */
dce
=
dceEmpty
?
dceEmpty
:
dceUnused
;
/* if there's no dce empty or unused, allocate a new one */
if
(
!
dce
)
dce
=
alloc_cache_dce
();
}
else
{
dce
=
data
->
dce
;
if
(
dce
&&
dce
->
hwnd
==
hwnd
)
{
TRACE
(
"
\t
skipping hVisRgn update
\n
"
);
bUpdateVisRgn
=
FALSE
;
/* updated automatically, via DCHook() */
}
}
if
(
!
dce
)
{
hdc
=
0
;
goto
END
;
}
if
(((
flags
^
dce
->
flags
)
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
))
&&
(
dce
->
clip_rgn
!=
hrgnClip
))
{
/* if the extra clip region has changed, get rid of the old one */
delete_clip_rgn
(
dce
);
}
dce
->
hwnd
=
hwnd
;
dce
->
clip_rgn
=
hrgnClip
;
dce
->
flags
=
flags
&
(
DCX_PARENTCLIP
|
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
|
DCX_CACHE
|
DCX_WINDOW
|
DCX_WINDOWPAINT
|
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
);
dce
->
empty
=
0
;
dce
->
inuse
=
1
;
dce
->
dirty
=
0
;
hdc
=
dce
->
hdc
;
if
(
bUpdateVisRgn
)
SetHookFlags16
(
HDC_16
(
hdc
),
DCHF_INVALIDATEVISRGN
);
/* force update */
if
(
!
set_drawable
(
hwnd
,
hdc
,
hrgnClip
,
flags
))
hdc
=
0
;
TRACE
(
"(%p,%p,0x%lx): returning %p
\n
"
,
hwnd
,
hrgnClip
,
flags
,
hdc
);
END:
LeaveCriticalSection
(
&
dce_section
);
return
hdc
;
}
/***********************************************************************
* X11DRV_ReleaseDC (X11DRV.@)
*/
BOOL
X11DRV_ReleaseDC
(
HWND
hwnd
,
HDC
hdc
)
{
struct
dce
*
dce
;
BOOL
ret
=
FALSE
;
TRACE
(
"%p %p
\n
"
,
hwnd
,
hdc
);
EnterCriticalSection
(
&
dce_section
);
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
if
(
dce
->
hdc
==
hdc
)
{
if
(
dce
->
inuse
)
ret
=
release_dc
(
dce
);
break
;
}
}
LeaveCriticalSection
(
&
dce_section
);
return
ret
;
}
/***********************************************************************
* dc_hook
*
* See "Undoc. Windows" for hints (DC, SetDCHook, SetHookFlags)..
*/
static
BOOL16
CALLBACK
dc_hook
(
HDC16
hDC
,
WORD
code
,
DWORD
data
,
LPARAM
lParam
)
{
BOOL
retv
=
TRUE
;
struct
dce
*
dce
=
(
struct
dce
*
)
data
;
TRACE
(
"hDC = %04x, %i
\n
"
,
hDC
,
code
);
if
(
!
dce
)
return
0
;
assert
(
HDC_16
(
dce
->
hdc
)
==
hDC
);
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
->
inuse
)
{
/* Dirty bit has been cleared by caller, set it again so that
* pGetDC recomputes the visible region. */
SetHookFlags16
(
hDC
,
DCHF_INVALIDATEVISRGN
);
set_drawable
(
dce
->
hwnd
,
dce
->
hdc
,
dce
->
clip_rgn
,
dce
->
flags
);
}
else
/* non-fatal but shouldn't happen */
WARN
(
"DC is not in use!
\n
"
);
break
;
case
DCHC_DELETEDC
:
/*
* Windows will not let you delete a DC that is busy
* (between GetDC and ReleaseDC)
*/
if
(
dce
->
inuse
)
{
WARN
(
"Application trying to delete a busy DC
\n
"
);
retv
=
FALSE
;
}
else
{
EnterCriticalSection
(
&
dce_section
);
list_remove
(
&
dce
->
entry
);
LeaveCriticalSection
(
&
dce_section
);
if
(
dce
->
clip_rgn
)
DeleteObject
(
dce
->
clip_rgn
);
HeapFree
(
GetProcessHeap
(),
0
,
dce
);
}
break
;
}
return
retv
;
}
/**********************************************************************
* WindowFromDC (X11DRV.@)
*/
HWND
X11DRV_WindowFromDC
(
HDC
hDC
)
{
struct
dce
*
dce
;
HWND
hwnd
=
0
;
EnterCriticalSection
(
&
dce_section
);
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
struct
dce
,
entry
)
{
if
(
dce
->
hdc
==
hDC
)
{
hwnd
=
dce
->
hwnd
;
break
;
}
}
LeaveCriticalSection
(
&
dce_section
);
return
hwnd
;
}
dlls/x11drv/window.c
View file @
2fb7c875
...
...
@@ -845,6 +845,7 @@ BOOL X11DRV_DestroyWindow( HWND hwnd )
if
(
!
(
data
=
X11DRV_get_win_data
(
hwnd
)))
return
TRUE
;
free_window_dce
(
data
);
destroy_whole_window
(
display
,
data
);
destroy_icon_window
(
display
,
data
);
...
...
@@ -902,6 +903,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
data
->
icon_window
=
0
;
data
->
xic
=
0
;
data
->
managed
=
FALSE
;
data
->
dce
=
NULL
;
data
->
hWMIconBitmap
=
0
;
data
->
hWMIconMask
=
0
;
...
...
@@ -927,8 +929,11 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
if
(
!
create_whole_window
(
display
,
data
,
cs
->
style
))
goto
failed
;
}
/* get class or window DC if needed */
alloc_window_dce
(
data
);
/* Call the WH_CBT hook */
/* the window style passed to the hook must be the real window style,
* rather than just the window style that the caller to CreateWindowEx
* passed in, so we have to copy the original CREATESTRUCT and get the
...
...
dlls/x11drv/winpos.c
View file @
2fb7c875
...
...
@@ -40,7 +40,6 @@
#include "x11drv.h"
#include "win.h"
#include "winpos.h"
#include "dce.h"
#include "wine/server.h"
#include "wine/debug.h"
...
...
@@ -83,58 +82,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
/***********************************************************************
* get_server_visible_region
*/
static
HRGN
get_server_visible_region
(
HWND
hwnd
,
UINT
flags
)
{
RGNDATA
*
data
;
NTSTATUS
status
;
HRGN
ret
=
0
;
size_t
size
=
256
;
do
{
if
(
!
(
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
data
)
+
size
-
1
)))
return
0
;
SERVER_START_REQ
(
get_visible_region
)
{
req
->
window
=
hwnd
;
req
->
flags
=
flags
;
wine_server_set_reply
(
req
,
data
->
Buffer
,
size
);
if
(
!
(
status
=
wine_server_call
(
req
)))
{
size_t
reply_size
=
wine_server_reply_size
(
reply
);
data
->
rdh
.
dwSize
=
sizeof
(
data
->
rdh
);
data
->
rdh
.
iType
=
RDH_RECTANGLES
;
data
->
rdh
.
nCount
=
reply_size
/
sizeof
(
RECT
);
data
->
rdh
.
nRgnSize
=
reply_size
;
ret
=
ExtCreateRegion
(
NULL
,
size
,
data
);
}
else
size
=
reply
->
total_size
;
}
SERVER_END_REQ
;
HeapFree
(
GetProcessHeap
(),
0
,
data
);
}
while
(
status
==
STATUS_BUFFER_OVERFLOW
);
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
ret
;
}
/***********************************************************************
* get_top_clipping_window
*
* Get the top window to clip against (i.e. the top parent that has
* an associated X window).
*/
static
HWND
get_top_clipping_window
(
HWND
hwnd
)
{
HWND
ret
=
GetAncestor
(
hwnd
,
GA_ROOT
);
if
(
!
ret
)
ret
=
GetDesktopWindow
();
return
ret
;
}
/***********************************************************************
* X11DRV_Expose
*/
void
X11DRV_Expose
(
HWND
hwnd
,
XEvent
*
xev
)
...
...
@@ -177,116 +124,6 @@ void X11DRV_Expose( HWND hwnd, XEvent *xev )
/***********************************************************************
* GetDC (X11DRV.@)
*
* Set the drawable, origin and dimensions for the DC associated to
* a given window.
*/
BOOL
X11DRV_GetDC
(
HWND
hwnd
,
HDC
hdc
,
HRGN
hrgn
,
DWORD
flags
)
{
HWND
top
=
get_top_clipping_window
(
hwnd
);
struct
x11drv_escape_set_drawable
escape
;
struct
x11drv_win_data
*
data
;
escape
.
mode
=
IncludeInferiors
;
/* don't clip siblings if using parent clip region */
if
(
flags
&
DCX_PARENTCLIP
)
flags
&=
~
DCX_CLIPSIBLINGS
;
if
(
top
!=
hwnd
||
!
(
data
=
X11DRV_get_win_data
(
hwnd
)))
{
POINT
client_offset
;
if
(
flags
&
DCX_WINDOW
)
{
RECT
rect
;
GetWindowRect
(
hwnd
,
&
rect
);
escape
.
org
.
x
=
rect
.
left
;
escape
.
org
.
y
=
rect
.
top
;
MapWindowPoints
(
0
,
top
,
&
escape
.
org
,
1
);
escape
.
drawable_org
.
x
=
rect
.
left
-
escape
.
org
.
x
;
escape
.
drawable_org
.
y
=
rect
.
top
-
escape
.
org
.
y
;
}
else
{
escape
.
org
.
x
=
escape
.
org
.
y
=
0
;
escape
.
drawable_org
.
x
=
escape
.
drawable_org
.
y
=
0
;
MapWindowPoints
(
hwnd
,
top
,
&
escape
.
org
,
1
);
MapWindowPoints
(
top
,
0
,
&
escape
.
drawable_org
,
1
);
}
/* now make origins relative to the X window and not the client area */
client_offset
=
X11DRV_get_client_area_offset
(
top
);
escape
.
org
.
x
+=
client_offset
.
x
;
escape
.
org
.
y
+=
client_offset
.
y
;
escape
.
drawable_org
.
x
-=
client_offset
.
x
;
escape
.
drawable_org
.
y
-=
client_offset
.
y
;
escape
.
drawable
=
X11DRV_get_whole_window
(
top
);
}
else
{
if
(
IsIconic
(
hwnd
))
{
escape
.
drawable
=
data
->
icon_window
?
data
->
icon_window
:
data
->
whole_window
;
escape
.
org
.
x
=
0
;
escape
.
org
.
y
=
0
;
escape
.
drawable_org
=
escape
.
org
;
MapWindowPoints
(
hwnd
,
0
,
&
escape
.
drawable_org
,
1
);
}
else
{
escape
.
drawable
=
data
->
whole_window
;
escape
.
drawable_org
.
x
=
data
->
whole_rect
.
left
;
escape
.
drawable_org
.
y
=
data
->
whole_rect
.
top
;
if
(
flags
&
DCX_WINDOW
)
{
escape
.
org
.
x
=
data
->
window_rect
.
left
-
data
->
whole_rect
.
left
;
escape
.
org
.
y
=
data
->
window_rect
.
top
-
data
->
whole_rect
.
top
;
}
else
{
escape
.
org
.
x
=
data
->
client_rect
.
left
;
escape
.
org
.
y
=
data
->
client_rect
.
top
;
}
}
}
escape
.
code
=
X11DRV_SET_DRAWABLE
;
ExtEscape
(
hdc
,
X11DRV_ESCAPE
,
sizeof
(
escape
),
(
LPSTR
)
&
escape
,
0
,
NULL
);
if
(
flags
&
(
DCX_EXCLUDERGN
|
DCX_INTERSECTRGN
)
||
SetHookFlags16
(
HDC_16
(
hdc
),
DCHF_VALIDATEVISRGN
))
/* DC was dirty */
{
/* need to recompute the visible region */
HRGN
visRgn
=
get_server_visible_region
(
hwnd
,
flags
);
if
(
flags
&
(
DCX_EXCLUDERGN
|
DCX_INTERSECTRGN
))
CombineRgn
(
visRgn
,
visRgn
,
hrgn
,
(
flags
&
DCX_INTERSECTRGN
)
?
RGN_AND
:
RGN_DIFF
);
SelectVisRgn16
(
HDC_16
(
hdc
),
HRGN_16
(
visRgn
)
);
DeleteObject
(
visRgn
);
}
return
TRUE
;
}
/***********************************************************************
* ReleaseDC (X11DRV.@)
*/
void
X11DRV_ReleaseDC
(
HWND
hwnd
,
HDC
hdc
)
{
struct
x11drv_escape_set_drawable
escape
;
escape
.
code
=
X11DRV_SET_DRAWABLE
;
escape
.
drawable
=
root_window
;
escape
.
mode
=
IncludeInferiors
;
escape
.
org
.
x
=
escape
.
org
.
y
=
0
;
escape
.
drawable_org
.
x
=
escape
.
drawable_org
.
y
=
0
;
ExtEscape
(
hdc
,
X11DRV_ESCAPE
,
sizeof
(
escape
),
(
LPSTR
)
&
escape
,
0
,
NULL
);
}
/***********************************************************************
* SWP_DoWinPosChanging
*/
static
BOOL
SWP_DoWinPosChanging
(
WINDOWPOS
*
pWinpos
,
RECT
*
pNewWindowRect
,
RECT
*
pNewClientRect
)
...
...
@@ -659,7 +496,7 @@ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style )
}
/* we don't unmap windows, that causes trouble with the window manager */
}
DCE_InvalidateDCE
(
hwnd
,
&
data
->
window_rect
);
invalidate_dce
(
hwnd
,
&
data
->
window_rect
);
}
if
(
changed
&
WS_DISABLED
)
...
...
@@ -764,7 +601,7 @@ BOOL X11DRV_set_window_pos( HWND hwnd, HWND insert_after, const RECT *rectWindow
{
RECT
rect
;
UnionRect
(
&
rect
,
rectWindow
,
&
win
->
rectWindow
);
DCE_InvalidateDCE
(
hwnd
,
&
rect
);
invalidate_dce
(
hwnd
,
&
rect
);
}
win
->
rectWindow
=
*
rectWindow
;
...
...
@@ -1238,7 +1075,7 @@ void X11DRV_MapNotify( HWND hwnd, XEvent *event )
rect
.
bottom
=
y
+
height
;
X11DRV_X_to_window_rect
(
data
,
&
rect
);
DCE_InvalidateDCE
(
hwnd
,
&
data
->
window_rect
);
invalidate_dce
(
hwnd
,
&
data
->
window_rect
);
if
(
win
->
flags
&
WIN_RESTORE_MAX
)
style
|=
WS_MAXIMIZE
;
WIN_SetStyle
(
hwnd
,
style
,
WS_MINIMIZE
);
...
...
dlls/x11drv/x11drv.h
View file @
2fb7c875
...
...
@@ -627,16 +627,17 @@ enum x11drv_window_messages
/* x11drv private window data */
struct
x11drv_win_data
{
HWND
hwnd
;
/* hwnd that this private data belongs to */
Window
whole_window
;
/* X window for the complete window */
Window
icon_window
;
/* X window for the icon */
RECT
window_rect
;
/* USER window rectangle relative to parent */
RECT
whole_rect
;
/* X window rectangle for the whole window relative to parent */
RECT
client_rect
;
/* client area relative to whole window */
XIC
xic
;
/* X input context */
BOOL
managed
;
/* is window managed? */
HBITMAP
hWMIconBitmap
;
HBITMAP
hWMIconMask
;
HWND
hwnd
;
/* hwnd that this private data belongs to */
Window
whole_window
;
/* X window for the complete window */
Window
icon_window
;
/* X window for the icon */
RECT
window_rect
;
/* USER window rectangle relative to parent */
RECT
whole_rect
;
/* X window rectangle for the whole window relative to parent */
RECT
client_rect
;
/* client area relative to whole window */
XIC
xic
;
/* X input context */
BOOL
managed
;
/* is window managed? */
struct
dce
*
dce
;
/* DCE for CS_OWNDC or CS_CLASSDC windows */
HBITMAP
hWMIconBitmap
;
HBITMAP
hWMIconMask
;
};
extern
struct
x11drv_win_data
*
X11DRV_get_win_data
(
HWND
hwnd
);
...
...
@@ -645,6 +646,9 @@ extern Window X11DRV_get_whole_window( HWND hwnd );
extern
BOOL
X11DRV_is_window_rect_mapped
(
const
RECT
*
rect
);
extern
XIC
X11DRV_get_ic
(
HWND
hwnd
);
extern
void
alloc_window_dce
(
struct
x11drv_win_data
*
data
);
extern
void
free_window_dce
(
struct
x11drv_win_data
*
data
);
extern
void
invalidate_dce
(
HWND
hwnd
,
const
RECT
*
rect
);
/* X context to associate a hwnd to an X window */
extern
XContext
winContext
;
...
...
dlls/x11drv/x11drv.spec
View file @
2fb7c875
...
...
@@ -92,7 +92,7 @@
@ cdecl EnumClipboardFormats(long) X11DRV_EnumClipboardFormats
@ cdecl GetClipboardData(long ptr ptr) X11DRV_GetClipboardData
@ cdecl GetClipboardFormatName(long str long) X11DRV_GetClipboardFormatName
@ cdecl GetDC
(long long long long) X11DRV_GetDC
@ cdecl GetDC
Ex(long long long) X11DRV_GetDCEx
@ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
@ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat
...
...
@@ -109,6 +109,7 @@
@ cdecl SetWindowText(long wstr) X11DRV_SetWindowText
@ cdecl ShowWindow(long long) X11DRV_ShowWindow
@ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove
@ cdecl WindowFromDC(long) X11DRV_WindowFromDC
@ cdecl WindowMessage(long long long long) X11DRV_WindowMessage
# WinTab32
...
...
include/dce.h
deleted
100644 → 0
View file @
dc84b8a4
/*
* USER DCE definitions
*
* Copyright 1993 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_DCE_H
#define __WINE_DCE_H
#include <windef.h>
/* internal DCX flags */
#define DCX_DCEEMPTY 0x00000800
#define DCX_DCEBUSY 0x00001000
#define DCX_DCEDIRTY 0x00002000
#define DCX_WINDOWPAINT 0x00020000
typedef
enum
{
DCE_CACHE_DC
,
/* This is a cached DC (allocated by USER) */
DCE_CLASS_DC
,
/* This is a class DC (style CS_CLASSDC) */
DCE_WINDOW_DC
/* This is a window DC (style CS_OWNDC) */
}
DCE_TYPE
;
struct
tagDCE
;
extern
struct
tagDCE
*
DCE_AllocDCE
(
HWND
hWnd
,
DCE_TYPE
type
);
extern
void
DCE_FreeDCE
(
struct
tagDCE
*
dce
);
extern
void
DCE_FreeWindowDCE
(
HWND
);
extern
BOOL
DCE_InvalidateDCE
(
HWND
,
const
RECT
*
);
#endif
/* __WINE_DCE_H */
include/win.h
View file @
2fb7c875
...
...
@@ -31,7 +31,6 @@
#define WND_MAGIC 0x444e4957
/* 'WIND' */
struct
tagCLASS
;
struct
tagDCE
;
typedef
struct
tagWND
{
...
...
@@ -48,7 +47,6 @@ typedef struct tagWND
LPWSTR
text
;
/* Window text */
void
*
pVScroll
;
/* Vertical scroll-bar info */
void
*
pHScroll
;
/* Horizontal scroll-bar info */
struct
tagDCE
*
dce
;
/* Window DCE (if CS_OWNDC or CS_CLASSDC) */
DWORD
dwStyle
;
/* Window style (from CreateWindow) */
DWORD
dwExStyle
;
/* Extended style (from CreateWindowEx) */
DWORD
clsStyle
;
/* Class style at window creation */
...
...
@@ -108,4 +106,7 @@ inline static void WIN_ReleasePtr( WND *ptr )
extern
LRESULT
HOOK_CallHooks
(
INT
id
,
INT
code
,
WPARAM
wparam
,
LPARAM
lparam
,
BOOL
unicode
);
/* internal GetDC flag (FIXME) */
#define DCX_WINDOWPAINT 0x00020000
#endif
/* __WINE_WIN_H */
windows/class.c
View file @
2fb7c875
...
...
@@ -36,7 +36,6 @@
#include "win.h"
#include "user_private.h"
#include "controls.h"
#include "dce.h"
#include "winproc.h"
#include "wine/server.h"
#include "wine/list.h"
...
...
@@ -55,7 +54,6 @@ typedef struct tagCLASS
INT
cbWndExtra
;
/* Window extra bytes */
LPWSTR
menuName
;
/* Default menu name (Unicode followed by ASCII) */
SEGPTR
segMenuName
;
/* Default menu name as SEGPTR */
struct
tagDCE
*
dce
;
/* Class DCE (if CS_CLASSDC) */
HINSTANCE
hInstance
;
/* Module that created the task */
HICON
hIcon
;
/* Default icon */
HICON
hIconSm
;
/* Default small icon */
...
...
@@ -292,7 +290,6 @@ static void CLASS_FreeClass( CLASS *classPtr )
USER_Lock
();
list_remove
(
&
classPtr
->
entry
);
if
(
classPtr
->
dce
)
DCE_FreeDCE
(
classPtr
->
dce
);
if
(
classPtr
->
hbrBackground
>
(
HBRUSH
)(
COLOR_GRADIENTINACTIVECAPTION
+
1
))
DeleteObject
(
classPtr
->
hbrBackground
);
UnMapLS
(
classPtr
->
segMenuName
);
...
...
@@ -421,7 +418,6 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
classPtr
->
cbClsExtra
=
classExtra
;
classPtr
->
hInstance
=
hInstance
;
classPtr
->
atomName
=
atom
;
classPtr
->
dce
=
(
style
&
CS_CLASSDC
)
?
DCE_AllocDCE
(
0
,
DCE_CLASS_DC
)
:
NULL
;
/* Other non-null values must be set by caller */
...
...
@@ -509,7 +505,6 @@ void CLASS_AddWindow( CLASS *class, WND *win, WINDOWPROCTYPE type )
}
win
->
class
=
class
;
win
->
clsStyle
=
class
->
style
;
win
->
dce
=
class
->
dce
;
}
...
...
windows/dce.c
deleted
100644 → 0
View file @
dc84b8a4
/*
* USER DCE functions
*
* Copyright 1993 Alexandre Julliard
* 1996,1997 Alex Korobka
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Note: Visible regions of CS_OWNDC/CS_CLASSDC window DCs
* have to be updated dynamically.
*
* Internal DCX flags:
*
* DCX_DCEEMPTY - dce is uninitialized
* DCX_DCEBUSY - dce is in use
* DCX_DCEDIRTY - ReleaseDC() should wipe instead of caching
* DCX_WINDOWPAINT - BeginPaint() is in effect
*/
#include <assert.h>
#include "dce.h"
#include "win.h"
#include "user_private.h"
#include "windef.h"
#include "wingdi.h"
#include "wownt32.h"
#include "wine/winbase16.h"
#include "wine/winuser16.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dc
);
typedef
struct
tagDCE
{
struct
list
entry
;
HDC
hDC
;
HWND
hwndCurrent
;
HRGN
hClipRgn
;
DCE_TYPE
type
;
DWORD
DCXflags
;
}
DCE
;
static
struct
list
dce_list
=
LIST_INIT
(
dce_list
);
static
void
DCE_DeleteClipRgn
(
DCE
*
);
static
INT
DCE_ReleaseDC
(
DCE
*
);
/***********************************************************************
* DCE_DumpCache
*/
static
void
DCE_DumpCache
(
void
)
{
DCE
*
dce
;
USER_Lock
();
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
DCE
,
entry
)
{
TRACE
(
"
\t
[0x%08x] hWnd %p, dcx %08x, %s %s
\n
"
,
(
unsigned
)
dce
,
dce
->
hwndCurrent
,
(
unsigned
)
dce
->
DCXflags
,
(
dce
->
DCXflags
&
DCX_CACHE
)
?
"Cache"
:
"Owned"
,
(
dce
->
DCXflags
&
DCX_DCEBUSY
)
?
"InUse"
:
""
);
}
USER_Unlock
();
}
/***********************************************************************
* DCE_AllocDCE
*
* Allocate a new DCE.
*/
DCE
*
DCE_AllocDCE
(
HWND
hWnd
,
DCE_TYPE
type
)
{
static
const
WCHAR
szDisplayW
[]
=
{
'D'
,
'I'
,
'S'
,
'P'
,
'L'
,
'A'
,
'Y'
,
'\0'
};
DCE
*
dce
;
TRACE
(
"(%p,%d)
\n
"
,
hWnd
,
type
);
if
(
!
(
dce
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
DCE
)
)))
return
NULL
;
if
(
!
(
dce
->
hDC
=
CreateDCW
(
szDisplayW
,
NULL
,
NULL
,
NULL
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
dce
);
return
0
;
}
SaveDC
(
dce
->
hDC
);
/* store DCE handle in DC hook data field */
SetDCHook
(
dce
->
hDC
,
DCHook16
,
(
DWORD
)
dce
);
dce
->
hwndCurrent
=
hWnd
;
dce
->
hClipRgn
=
0
;
dce
->
type
=
type
;
if
(
type
!=
DCE_CACHE_DC
)
/* owned or class DC */
{
dce
->
DCXflags
=
DCX_DCEBUSY
;
if
(
hWnd
)
{
LONG
style
=
GetWindowLongW
(
hWnd
,
GWL_STYLE
);
if
(
style
&
WS_CLIPCHILDREN
)
dce
->
DCXflags
|=
DCX_CLIPCHILDREN
;
if
(
style
&
WS_CLIPSIBLINGS
)
dce
->
DCXflags
|=
DCX_CLIPSIBLINGS
;
}
SetHookFlags16
(
HDC_16
(
dce
->
hDC
),
DCHF_INVALIDATEVISRGN
);
}
else
dce
->
DCXflags
=
DCX_CACHE
|
DCX_DCEEMPTY
;
USER_Lock
();
list_add_head
(
&
dce_list
,
&
dce
->
entry
);
USER_Unlock
();
return
dce
;
}
/***********************************************************************
* DCE_FreeDCE
*/
void
DCE_FreeDCE
(
DCE
*
dce
)
{
if
(
!
dce
)
return
;
USER_Lock
();
list_remove
(
&
dce
->
entry
);
USER_Unlock
();
SetDCHook
(
dce
->
hDC
,
NULL
,
0L
);
DeleteDC
(
dce
->
hDC
);
if
(
dce
->
hClipRgn
)
DeleteObject
(
dce
->
hClipRgn
);
HeapFree
(
GetProcessHeap
(),
0
,
dce
);
}
/***********************************************************************
* DCE_FreeWindowDCE
*
* Remove owned DCE and reset unreleased cache DCEs.
*/
void
DCE_FreeWindowDCE
(
HWND
hwnd
)
{
struct
list
*
ptr
,
*
next
;
WND
*
pWnd
=
WIN_GetPtr
(
hwnd
);
LIST_FOR_EACH_SAFE
(
ptr
,
next
,
&
dce_list
)
{
DCE
*
pDCE
=
LIST_ENTRY
(
ptr
,
DCE
,
entry
);
if
(
pDCE
->
hwndCurrent
!=
hwnd
)
continue
;
switch
(
pDCE
->
type
)
{
case
DCE_WINDOW_DC
:
DCE_FreeDCE
(
pDCE
);
pWnd
->
dce
=
NULL
;
break
;
case
DCE_CLASS_DC
:
if
(
pDCE
->
DCXflags
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
)
)
{
if
(
USER_Driver
.
pReleaseDC
)
USER_Driver
.
pReleaseDC
(
pDCE
->
hwndCurrent
,
pDCE
->
hDC
);
DCE_DeleteClipRgn
(
pDCE
);
pDCE
->
hwndCurrent
=
0
;
}
break
;
case
DCE_CACHE_DC
:
if
(
pDCE
->
DCXflags
&
DCX_DCEBUSY
)
/* shared cache DCE */
{
WARN
(
"[%p] GetDC() without ReleaseDC()!
\n
"
,
hwnd
);
DCE_ReleaseDC
(
pDCE
);
}
if
(
pDCE
->
hwndCurrent
&&
USER_Driver
.
pReleaseDC
)
USER_Driver
.
pReleaseDC
(
pDCE
->
hwndCurrent
,
pDCE
->
hDC
);
pDCE
->
DCXflags
&=
DCX_CACHE
;
pDCE
->
DCXflags
|=
DCX_DCEEMPTY
;
pDCE
->
hwndCurrent
=
0
;
break
;
}
}
WIN_ReleasePtr
(
pWnd
);
}
/***********************************************************************
* DCE_DeleteClipRgn
*/
static
void
DCE_DeleteClipRgn
(
DCE
*
dce
)
{
dce
->
DCXflags
&=
~
(
DCX_EXCLUDERGN
|
DCX_INTERSECTRGN
|
DCX_WINDOWPAINT
);
if
(
dce
->
hClipRgn
)
DeleteObject
(
dce
->
hClipRgn
);
dce
->
hClipRgn
=
0
;
/* make it dirty so that the vis rgn gets recomputed next time */
dce
->
DCXflags
|=
DCX_DCEDIRTY
;
SetHookFlags16
(
HDC_16
(
dce
->
hDC
),
DCHF_INVALIDATEVISRGN
);
}
/***********************************************************************
* DCE_ReleaseDC
*/
static
INT
DCE_ReleaseDC
(
DCE
*
dce
)
{
if
((
dce
->
DCXflags
&
(
DCX_DCEEMPTY
|
DCX_DCEBUSY
))
!=
DCX_DCEBUSY
)
return
0
;
/* restore previous visible region */
if
((
dce
->
DCXflags
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
))
&&
(
dce
->
DCXflags
&
(
DCX_CACHE
|
DCX_WINDOWPAINT
))
)
DCE_DeleteClipRgn
(
dce
);
if
(
dce
->
DCXflags
&
DCX_CACHE
)
{
/* make the DC clean so that RestoreDC doesn't try to update the vis rgn */
SetHookFlags16
(
HDC_16
(
dce
->
hDC
),
DCHF_VALIDATEVISRGN
);
RestoreDC
(
dce
->
hDC
,
1
);
/* initial save level is always 1 */
SaveDC
(
dce
->
hDC
);
/* save the state again for next time */
dce
->
DCXflags
&=
~
DCX_DCEBUSY
;
if
(
dce
->
DCXflags
&
DCX_DCEDIRTY
)
{
/* don't keep around invalidated entries
* because RestoreDC() disables hVisRgn updates
* by removing dirty bit. */
if
(
dce
->
hwndCurrent
&&
USER_Driver
.
pReleaseDC
)
USER_Driver
.
pReleaseDC
(
dce
->
hwndCurrent
,
dce
->
hDC
);
dce
->
hwndCurrent
=
0
;
dce
->
DCXflags
&=
DCX_CACHE
;
dce
->
DCXflags
|=
DCX_DCEEMPTY
;
}
}
return
1
;
}
/***********************************************************************
* DCE_InvalidateDCE
*
* It is called from SetWindowPos() and EVENT_MapNotify - we have to
* mark as dirty all busy DCEs for windows that have pWnd->parent as
* an ancestor and whose client rect intersects with specified update
* rectangle. In addition, pWnd->parent DCEs may need to be updated if
* DCX_CLIPCHILDREN flag is set. */
BOOL
DCE_InvalidateDCE
(
HWND
hwnd
,
const
RECT
*
pRectUpdate
)
{
HWND
hwndScope
=
GetAncestor
(
hwnd
,
GA_PARENT
);
BOOL
bRet
=
FALSE
;
if
(
hwndScope
)
{
DCE
*
dce
;
TRACE
(
"scope hwnd = %p, (%ld,%ld - %ld,%ld)
\n
"
,
hwndScope
,
pRectUpdate
->
left
,
pRectUpdate
->
top
,
pRectUpdate
->
right
,
pRectUpdate
->
bottom
);
if
(
TRACE_ON
(
dc
))
DCE_DumpCache
();
/* walk all DCEs and fixup non-empty entries */
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
DCE
,
entry
)
{
if
(
dce
->
DCXflags
&
DCX_DCEEMPTY
)
continue
;
if
((
dce
->
hwndCurrent
==
hwndScope
)
&&
!
(
dce
->
DCXflags
&
DCX_CLIPCHILDREN
))
continue
;
/* child window positions don't bother us */
/* check if DCE window is within the z-order scope */
if
(
hwndScope
==
dce
->
hwndCurrent
||
IsChild
(
hwndScope
,
dce
->
hwndCurrent
))
{
if
(
hwnd
!=
dce
->
hwndCurrent
)
{
/* check if the window rectangle intersects this DCE window */
RECT
rect
;
GetWindowRect
(
dce
->
hwndCurrent
,
&
rect
);
MapWindowPoints
(
0
,
hwndScope
,
(
POINT
*
)
&
rect
,
2
);
if
(
!
IntersectRect
(
&
rect
,
&
rect
,
pRectUpdate
))
continue
;
}
if
(
!
(
dce
->
DCXflags
&
DCX_DCEBUSY
)
)
{
/* Don't bother with visible regions of unused DCEs */
TRACE
(
"
\t
purged %p dce [%p]
\n
"
,
dce
,
dce
->
hwndCurrent
);
if
(
dce
->
hwndCurrent
&&
USER_Driver
.
pReleaseDC
)
USER_Driver
.
pReleaseDC
(
dce
->
hwndCurrent
,
dce
->
hDC
);
dce
->
hwndCurrent
=
0
;
dce
->
DCXflags
&=
DCX_CACHE
;
dce
->
DCXflags
|=
DCX_DCEEMPTY
;
}
else
{
/* Set dirty bits in the hDC and DCE structs */
TRACE
(
"
\t
fixed up %p dce [%p]
\n
"
,
dce
,
dce
->
hwndCurrent
);
dce
->
DCXflags
|=
DCX_DCEDIRTY
;
SetHookFlags16
(
HDC_16
(
dce
->
hDC
),
DCHF_INVALIDATEVISRGN
);
bRet
=
TRUE
;
}
}
}
/* dce list */
}
return
bRet
;
}
/***********************************************************************
* GetDCEx (USER32.@)
*
* Unimplemented flags: DCX_LOCKWINDOWUPDATE
*
* FIXME: Full support for hrgnClip == 1 (alias for entire window).
*/
HDC
WINAPI
GetDCEx
(
HWND
hwnd
,
HRGN
hrgnClip
,
DWORD
flags
)
{
HDC
hdc
=
0
;
DCE
*
dce
;
WND
*
wndPtr
;
DWORD
dcxFlags
=
0
;
BOOL
bUpdateVisRgn
=
TRUE
;
BOOL
bUpdateClipOrigin
=
FALSE
;
HWND
parent
;
LONG
window_style
;
TRACE
(
"hwnd %p, hrgnClip %p, flags %08lx
\n
"
,
hwnd
,
hrgnClip
,
flags
);
if
(
flags
&
(
DCX_LOCKWINDOWUPDATE
))
{
FIXME
(
"not yet supported - see source
\n
"
);
/* See the comment in LockWindowUpdate for more explanation. This flag is not implemented
* by that patch, but we need LockWindowUpdate implemented correctly before this can be done.
*/
}
if
(
!
hwnd
)
hwnd
=
GetDesktopWindow
();
else
hwnd
=
WIN_GetFullHandle
(
hwnd
);
if
(
!
(
wndPtr
=
WIN_GetPtr
(
hwnd
)))
return
0
;
if
(
wndPtr
==
WND_OTHER_PROCESS
||
wndPtr
==
WND_DESKTOP
)
{
wndPtr
=
NULL
;
USER_Lock
();
}
window_style
=
GetWindowLongW
(
hwnd
,
GWL_STYLE
);
/* fixup flags */
if
(
flags
&
(
DCX_WINDOW
|
DCX_PARENTCLIP
))
flags
|=
DCX_CACHE
;
if
(
flags
&
DCX_USESTYLE
)
{
flags
&=
~
(
DCX_CLIPCHILDREN
|
DCX_CLIPSIBLINGS
|
DCX_PARENTCLIP
);
if
(
window_style
&
WS_CLIPSIBLINGS
)
flags
|=
DCX_CLIPSIBLINGS
;
if
(
!
(
flags
&
DCX_WINDOW
)
)
{
if
(
GetClassLongW
(
hwnd
,
GCL_STYLE
)
&
CS_PARENTDC
)
flags
|=
DCX_PARENTCLIP
;
if
(
window_style
&
WS_CLIPCHILDREN
&&
!
(
window_style
&
WS_MINIMIZE
))
flags
|=
DCX_CLIPCHILDREN
;
if
(
!
wndPtr
||
!
wndPtr
->
dce
)
flags
|=
DCX_CACHE
;
}
}
if
(
flags
&
DCX_WINDOW
)
flags
&=
~
DCX_CLIPCHILDREN
;
parent
=
GetAncestor
(
hwnd
,
GA_PARENT
);
if
(
!
parent
||
(
parent
==
GetDesktopWindow
()))
flags
=
(
flags
&
~
DCX_PARENTCLIP
)
|
DCX_CLIPSIBLINGS
;
/* it seems parent clip is ignored when clipping siblings or children */
if
(
flags
&
(
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
))
flags
&=
~
DCX_PARENTCLIP
;
if
(
flags
&
DCX_PARENTCLIP
)
{
LONG
parent_style
=
GetWindowLongW
(
parent
,
GWL_STYLE
);
if
(
(
window_style
&
WS_VISIBLE
)
&&
(
parent_style
&
WS_VISIBLE
)
)
{
flags
&=
~
DCX_CLIPCHILDREN
;
if
(
parent_style
&
WS_CLIPSIBLINGS
)
flags
|=
DCX_CLIPSIBLINGS
;
}
}
/* find a suitable DCE */
dcxFlags
=
flags
&
(
DCX_PARENTCLIP
|
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
|
DCX_CACHE
|
DCX_WINDOW
);
if
(
flags
&
DCX_CACHE
)
{
DCE
*
dceEmpty
=
NULL
,
*
dceUnused
=
NULL
;
/* Strategy: First, we attempt to find a non-empty but unused DCE with
* compatible flags. Next, we look for an empty entry. If the cache is
* full we have to purge one of the unused entries.
*/
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
DCE
,
entry
)
{
if
((
dce
->
DCXflags
&
(
DCX_CACHE
|
DCX_DCEBUSY
))
==
DCX_CACHE
)
{
dceUnused
=
dce
;
if
(
dce
->
DCXflags
&
DCX_DCEEMPTY
)
dceEmpty
=
dce
;
else
if
((
dce
->
hwndCurrent
==
hwnd
)
&&
((
dce
->
DCXflags
&
(
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
|
DCX_CACHE
|
DCX_WINDOW
|
DCX_PARENTCLIP
))
==
dcxFlags
))
{
TRACE
(
"
\t
found valid %p dce [%p], flags %08lx
\n
"
,
dce
,
hwnd
,
dcxFlags
);
bUpdateVisRgn
=
FALSE
;
bUpdateClipOrigin
=
TRUE
;
break
;
}
}
}
if
(
&
dce
->
entry
==
&
dce_list
)
/* nothing found */
dce
=
dceEmpty
?
dceEmpty
:
dceUnused
;
/* if there's no dce empty or unused, allocate a new one */
if
(
!
dce
)
{
dce
=
DCE_AllocDCE
(
0
,
DCE_CACHE_DC
);
}
}
else
{
dce
=
wndPtr
->
dce
;
if
(
dce
&&
dce
->
hwndCurrent
==
hwnd
)
{
TRACE
(
"
\t
skipping hVisRgn update
\n
"
);
bUpdateVisRgn
=
FALSE
;
/* updated automatically, via DCHook() */
}
}
if
(
!
dce
)
{
hdc
=
0
;
goto
END
;
}
if
(
!
(
flags
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
)))
hrgnClip
=
0
;
if
(((
flags
^
dce
->
DCXflags
)
&
(
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
))
&&
(
dce
->
hClipRgn
!=
hrgnClip
))
{
/* if the extra clip region has changed, get rid of the old one */
DCE_DeleteClipRgn
(
dce
);
}
dce
->
hwndCurrent
=
hwnd
;
dce
->
hClipRgn
=
hrgnClip
;
dce
->
DCXflags
=
flags
&
(
DCX_PARENTCLIP
|
DCX_CLIPSIBLINGS
|
DCX_CLIPCHILDREN
|
DCX_CACHE
|
DCX_WINDOW
|
DCX_WINDOWPAINT
|
DCX_INTERSECTRGN
|
DCX_EXCLUDERGN
);
dce
->
DCXflags
|=
DCX_DCEBUSY
;
dce
->
DCXflags
&=
~
DCX_DCEDIRTY
;
hdc
=
dce
->
hDC
;
if
(
bUpdateVisRgn
)
SetHookFlags16
(
HDC_16
(
hdc
),
DCHF_INVALIDATEVISRGN
);
/* force update */
if
(
!
USER_Driver
.
pGetDC
||
!
USER_Driver
.
pGetDC
(
hwnd
,
hdc
,
hrgnClip
,
flags
))
hdc
=
0
;
TRACE
(
"(%p,%p,0x%lx): returning %p
\n
"
,
hwnd
,
hrgnClip
,
flags
,
hdc
);
END:
if
(
wndPtr
)
WIN_ReleasePtr
(
wndPtr
);
else
USER_Unlock
();
return
hdc
;
}
/***********************************************************************
* GetDC (USER32.@)
*
* Get a device context.
*
* RETURNS
* Success: Handle to the device context
* Failure: NULL.
*/
HDC
WINAPI
GetDC
(
HWND
hwnd
)
{
if
(
!
hwnd
)
return
GetDCEx
(
0
,
0
,
DCX_CACHE
|
DCX_WINDOW
);
return
GetDCEx
(
hwnd
,
0
,
DCX_USESTYLE
);
}
/***********************************************************************
* GetWindowDC (USER32.@)
*/
HDC
WINAPI
GetWindowDC
(
HWND
hwnd
)
{
return
GetDCEx
(
hwnd
,
0
,
DCX_USESTYLE
|
DCX_WINDOW
);
}
/***********************************************************************
* ReleaseDC (USER32.@)
*
* Release a device context.
*
* RETURNS
* Success: Non-zero. Resources used by hdc are released.
* Failure: 0.
*/
INT
WINAPI
ReleaseDC
(
HWND
hwnd
,
HDC
hdc
)
{
DCE
*
dce
;
INT
nRet
=
0
;
TRACE
(
"%p %p
\n
"
,
hwnd
,
hdc
);
USER_Lock
();
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
DCE
,
entry
)
{
if
(
dce
->
hDC
==
hdc
)
{
if
(
dce
->
DCXflags
&
DCX_DCEBUSY
)
nRet
=
DCE_ReleaseDC
(
dce
);
break
;
}
}
USER_Unlock
();
return
nRet
;
}
/***********************************************************************
* DCHook (USER.362)
*
* See "Undoc. Windows" for hints (DC, SetDCHook, SetHookFlags)..
*/
BOOL16
WINAPI
DCHook16
(
HDC16
hDC
,
WORD
code
,
DWORD
data
,
LPARAM
lParam
)
{
BOOL
retv
=
TRUE
;
DCE
*
dce
=
(
DCE
*
)
data
;
TRACE
(
"hDC = %04x, %i
\n
"
,
hDC
,
code
);
if
(
!
dce
)
return
0
;
assert
(
HDC_16
(
dce
->
hDC
)
==
hDC
);
/* Grab the windows lock before doing anything else */
USER_Lock
();
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
)
{
/* Dirty bit has been cleared by caller, set it again so that
* pGetDC recomputes the visible region. */
SetHookFlags16
(
hDC
,
DCHF_INVALIDATEVISRGN
);
if
(
USER_Driver
.
pGetDC
)
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
;
case
DCHC_DELETEDC
:
/*
* Windows will not let you delete a DC that is busy
* (between GetDC and ReleaseDC)
*/
if
(
dce
->
DCXflags
&
DCX_DCEBUSY
)
{
WARN
(
"Application trying to delete a busy DC
\n
"
);
retv
=
FALSE
;
}
else
DCE_FreeDCE
(
dce
);
break
;
default:
FIXME
(
"unknown code
\n
"
);
}
USER_Unlock
();
/* Release the wnd lock */
return
retv
;
}
/**********************************************************************
* WindowFromDC (USER32.@)
*/
HWND
WINAPI
WindowFromDC
(
HDC
hDC
)
{
DCE
*
dce
;
HWND
hwnd
=
0
;
USER_Lock
();
LIST_FOR_EACH_ENTRY
(
dce
,
&
dce_list
,
DCE
,
entry
)
{
if
(
dce
->
hDC
==
hDC
)
{
hwnd
=
dce
->
hwndCurrent
;
break
;
}
}
USER_Unlock
();
return
hwnd
;
}
/***********************************************************************
* LockWindowUpdate (USER32.@)
*/
BOOL
WINAPI
LockWindowUpdate
(
HWND
hwnd
)
{
static
HWND
lockedWnd
;
/* This function is fully implemented by the following patch:
*
* http://www.winehq.org/hypermail/wine-patches/2004/01/0142.html
*
* but in order to work properly, it needs the ability to invalidate
* DCEs in other processes when the lock window is changed, which
* isn't possible yet.
* -mike
*/
FIXME
(
"(%p), partial stub!
\n
"
,
hwnd
);
USER_Lock
();
if
(
lockedWnd
)
{
if
(
!
hwnd
)
{
/* Unlock lockedWnd */
/* FIXME: Do something */
}
else
{
/* Attempted to lock a second window */
/* Return FALSE and do nothing */
USER_Unlock
();
return
FALSE
;
}
}
lockedWnd
=
hwnd
;
USER_Unlock
();
return
TRUE
;
}
windows/nonclient.c
View file @
2fb7c875
...
...
@@ -29,7 +29,6 @@
#include "wownt32.h"
#include "win.h"
#include "user_private.h"
#include "dce.h"
#include "controls.h"
#include "cursoricon.h"
#include "winpos.h"
...
...
windows/win.c
View file @
2fb7c875
...
...
@@ -34,7 +34,6 @@
#include "wine/unicode.h"
#include "win.h"
#include "user_private.h"
#include "dce.h"
#include "controls.h"
#include "cursoricon.h"
#include "message.h"
...
...
@@ -578,7 +577,6 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
if
(
menu
)
DestroyMenu
(
menu
);
if
(
sys_menu
)
DestroyMenu
(
sys_menu
);
DCE_FreeWindowDCE
(
hwnd
);
/* Always do this to catch orphaned DCs */
if
(
USER_Driver
.
pDestroyWindow
)
USER_Driver
.
pDestroyWindow
(
hwnd
);
free_window_handle
(
hwnd
);
...
...
@@ -1066,10 +1064,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
}
SERVER_END_REQ
;
/* Get class or window DC if needed */
if
(
wndPtr
->
clsStyle
&
CS_OWNDC
)
wndPtr
->
dce
=
DCE_AllocDCE
(
hwnd
,
DCE_WINDOW_DC
);
/* Set the window menu */
if
(((
wndPtr
->
dwStyle
&
(
WS_CAPTION
|
WS_CHILD
))
==
WS_CAPTION
)
||
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment