Author: fireball Date: Sat Oct 31 21:55:25 2009 New Revision: 43887
URL: http://svn.reactos.org/svn/reactos?rev=43887&view=rev Log: - Start working on proper window managing: Implement a very simple window manager, responsible for redrawing top-level windows (Swm* APIs in win32k). - Remove all previous hacks related to window redrawing in events of move or focus change. They couldn't work properly. - Wine's win32 engine really expects mouse events to be tagged by a corresponding window's handle. Make it so using SWM. - All these changes make arwinss usability actually regress (mostly due to removing unnecessary hacks and problems in other components).
Added: branches/arwinss/reactos/subsystems/win32/win32k/include/swm.h (with props) branches/arwinss/reactos/subsystems/win32/win32k/swm/ (with props) branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c (with props) Modified: branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c branches/arwinss/reactos/dll/win32/winent.drv/mouse.c branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c branches/arwinss/reactos/dll/win32/winent.drv/wnd.c branches/arwinss/reactos/include/reactos/win32k/rosuser.h branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h branches/arwinss/reactos/subsystems/win32/win32k/main/init.c branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild branches/arwinss/reactos/subsystems/win32/win32k/wine/window.c
Modified: branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -71,6 +71,9 @@ /* Update brush origin */ GetBrushOrgEx(physDevDst->hUserDC, &ptBrush); RosGdiSetBrushOrg(physDevDst->hKernelDC, ptBrush.x, ptBrush.y); + + //FIXME("xDst %d, yDst %d, widthDst %d, heightDst %d, src x %d y %d\n", + // xDst, yDst, width, height, xSrc, ySrc);
return RosGdiBitBlt(physDevDst->hKernelDC, xDst, yDst, width, height, physDevSrc->hKernelDC, xSrc, ySrc, rop); @@ -669,6 +672,8 @@ HRGN dc_rgn; DWORD size;
+ //FIXME("SetDeviceClipping hdc %x\n", physDev->hUserDC); + /* Create a dummy region (FIXME: create it once!) */ dc_rgn = CreateRectRgn(0,0,0,0); if (!dc_rgn) return;
Modified: branches/arwinss/reactos/dll/win32/winent.drv/mouse.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/mouse.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/mouse.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -188,6 +188,10 @@ { GetCursorPos(&pt); } + + hwnd = SwmGetWindowFromPoint(pt.x, pt.y); + + FIXME("hwnd %x\n", hwnd);
if (flags & MOUSEEVENTF_MOVE) {
Modified: branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -58,9 +58,9 @@ hdc_src = hdc_dst = GetDCEx( data->hwnd, 0, DCX_CACHE ); }
- //ERR( "copying bits for win %p (parent %p)/ %s -> %s\n", - // data->hwnd, parent, - // wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect) ); + FIXME( "copying bits for win %p (parent %p)/ %s -> %s\n", + data->hwnd, parent, + wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect) ); BitBlt( hdc_dst, dst_rect.left, dst_rect.top, dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top, hdc_src, src_rect.left, src_rect.top, SRCCOPY ); @@ -723,10 +723,9 @@
void CDECL RosDrv_SetFocus( HWND hwnd ) { - RECT rc; - //UNIMPLEMENTED; - GetWindowRect(hwnd, &rc); - RosDrv_UpdateZOrder(hwnd, &rc); + TRACE("SetFocus %x, desk %x\n", hwnd, GetDesktopWindow()); + if (GetDesktopWindow() != hwnd) + SwmSetForeground(hwnd); }
void CDECL RosDrv_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ) @@ -765,7 +764,7 @@ !(data = NTDRV_create_win_data( hwnd ))) return;
/* Do some magic... */ - TRACE("Window %x is being made visible\n", hwnd); + FIXME("Window %x is being made visible1\n", hwnd); }
if (offset == GWL_STYLE && (changed & WS_DISABLED)) @@ -787,7 +786,7 @@
UINT CDECL RosDrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) { - TRACE( "win %p cmd %d at %s flags %08x\n", + FIXME( "win %p cmd %d at %s flags %08x\n", hwnd, cmd, wine_dbgstr_rect(rect), swp );
return swp; @@ -819,6 +818,11 @@ if (!(data = NTDRV_create_win_data( hwnd ))) return; }
+ SwmPosChanging(hwnd, window_rect); + + TRACE( "win %x pos is changing. vis rect %s, win rect %s\n", + hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(window_rect) ); + *visible_rect = *window_rect; }
@@ -833,6 +837,9 @@ struct ntdrv_win_data *data = NTDRV_get_win_data(hwnd);
if (!data) return; + + TRACE( "win %x pos changed. new vis rect %s, old whole rect %s\n", + hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect) );
old_whole_rect = data->whole_rect; old_client_rect = data->client_rect; @@ -855,11 +862,12 @@ old_client_rect.bottom - data->client_rect.bottom == y_offset && !memcmp( &valid_rects[0], &data->client_rect, sizeof(RECT) )) { - move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect ); + //move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect ); + SwmPosChanged(hwnd, &data->whole_rect, &old_whole_rect); } else { - move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect ); + //move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect ); } }
Modified: branches/arwinss/reactos/dll/win32/winent.drv/wnd.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/wnd.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/wnd.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -18,6 +18,7 @@ #define NTOS_USER_MODE #include <ndk/ntndk.h> #include "ntrosgdi.h" +#include "win32k/rosuser.h" #include "winent.h" #include "wine/server.h" #include "wine/debug.h" @@ -94,7 +95,15 @@ TRACE( "win %p window %s whole %s client %s\n", hwnd, wine_dbgstr_rect( &data->window_rect ), wine_dbgstr_rect( &data->whole_rect ), wine_dbgstr_rect( &data->client_rect )); + + /* Inform window manager about window rect in screen coords */ + SwmAddWindow(hwnd, &data->window_rect); } + + /* Add desktop window too */ + if (hwnd == GetDesktopWindow()) + SwmAddWindow(hwnd, &data->window_rect); + return data; }
@@ -111,6 +120,9 @@ /* Remove property */ RemovePropA( hwnd, window_data_prop );
+ /* Inform window manager */ + SwmRemoveWindow( hwnd ); + /* Free window data */ HeapFree( GetProcessHeap(), 0, data ); }
Modified: branches/arwinss/reactos/include/reactos/win32k/rosuser.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/include/reactos/... ============================================================================== --- branches/arwinss/reactos/include/reactos/win32k/rosuser.h [iso-8859-1] (original) +++ branches/arwinss/reactos/include/reactos/win32k/rosuser.h [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -136,4 +136,23 @@ VOID NTAPI RosUserConnectCsrss(VOID);
+VOID NTAPI +SwmAddWindow(HWND hWnd, RECT *WindowRect); + +VOID NTAPI +SwmRemoveWindow(HWND hWnd); + +VOID NTAPI +SwmSetForeground(HWND hWnd); + +VOID NTAPI +SwmPosChanging(HWND hWnd, const RECT *WindowRect); + +VOID NTAPI +SwmPosChanged(HWND hWnd, const RECT *WindowRect, const RECT *OldRect); + +HWND NTAPI +SwmGetWindowFromPoint(LONG x, LONG y); + + #endif /* __WIN32K_NTUSER_H */
Added: branches/arwinss/reactos/subsystems/win32/win32k/include/swm.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/swm.h (added) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/swm.h [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -1,0 +1,6 @@ +#ifndef SWM__H +#define SWM__H + +VOID NTAPI SwmInitialize(); + +#endif
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/include/swm.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -53,6 +53,7 @@ #include <xlateobj.h> #include <gre.h> #include <monitor.h> +#include <swm.h>
#include "winesup.h"
Modified: branches/arwinss/reactos/subsystems/win32/win32k/main/init.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -329,6 +329,9 @@ /* Initialize handle-mapping */ GDI_InitHandleMapping();
+ /* Initialize window manager */ + SwmInitialize(); + /* Create stock objects */ CreateStockBitmap(); PALETTE_Init();
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/swm/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Sat Oct 31 21:55:25 2009 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/swm/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/swm/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/swm/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c (added) +++ branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -1,0 +1,719 @@ +/* + * PROJECT: ReactOS Win32K + * LICENSE: LGPL - See COPYING in the top level directory + * FILE: subsystems/win32/win32k/swm/winman.c + * PURPOSE: Simple Window Manager + * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include <win32k.h> + +#include "object.h" +#include "handle.h" +#include "user.h" + +#define NDEBUG +#include <debug.h> + +typedef struct _SWM_WINDOW +{ + HWND hwnd; + rectangle_t Window; + struct region *Visible; + struct region *Invisible; + + LIST_ENTRY Entry; +} SWM_WINDOW, *PSWM_WINDOW; + +/*static*/ inline struct window *get_window( user_handle_t handle ); +void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags ); +void req_update_window_zorder( const struct update_window_zorder_request *req, struct update_window_zorder_reply *reply ); + +VOID NTAPI SwmDumpRegion(struct region *Region); +VOID NTAPI SwmDumpWindows(); +VOID NTAPI SwmDebugDrawWindows(); +VOID NTAPI SwmTest(); + + +/* GLOBALS *******************************************************************/ + +LIST_ENTRY SwmWindows; +ERESOURCE SwmLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +SwmAcquire(VOID) +{ + /* Acquire user resource exclusively */ + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&SwmLock, TRUE); +} + +VOID +NTAPI +SwmRelease(VOID) +{ + /* Release user resource */ + ExReleaseResourceLite(&SwmLock); + KeLeaveCriticalRegion(); +} + +VOID +NTAPI +SwmInvalidateRegion(PSWM_WINDOW Window, struct region *Region, rectangle_t *Rect) +{ + struct window *Win; + struct update_window_zorder_request req; + //struct update_window_zorder_reply reply; + struct region *ClientRegion; + + ClientRegion = create_empty_region(); + copy_region(ClientRegion, Region); + + /* Calculate what areas to paint */ + UserEnterExclusive(); + + DPRINT1("SwmInvalidateRegion hwnd %x, region:\n", Window->hwnd); + SwmDumpRegion(Region); + Win = get_window((UINT_PTR)Window->hwnd); + if (!Win) + { + UserLeave(); + return; + } + + /* Convert region to client coordinates */ + offset_region(ClientRegion, -Window->Window.left, -Window->Window.top); + + //DPRINT1("rect (%d,%d)-(%d,%d)\n", TmpRect.left, TmpRect.top, TmpRect.right, TmpRect.bottom); + + /* Update zorder */ + if (Rect) + { + req.rect = *Rect; + req.rect.left -= Window->Window.left; req.rect.top -= Window->Window.top; + req.rect.right -= Window->Window.left; req.rect.bottom -= Window->Window.left; + req.window = (UINT_PTR)Window->hwnd; + //req_update_window_zorder(&req, &reply); + } + + /* Redraw window */ + redraw_window(Win, ClientRegion, 1, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); + + UserLeave(); + + free_region(ClientRegion); +} + +VOID +NTAPI +SwmMarkInvisible(struct region *Region) +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + struct region *WindowRegion; + struct region *InvisibleRegion; + + /* Make a copy of the invisible region */ + InvisibleRegion = create_empty_region(); + copy_region(InvisibleRegion, Region); + + /* Traverse the list to find our window */ + Current = SwmWindows.Flink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + /* Get window's region */ + WindowRegion = create_empty_region(); + set_region_rect(WindowRegion, &Window->Window); + + //DPRINT1("Window region ext:\n"); + //SwmDumpRegion(WindowRegion); + //DPRINT1("Region to mark invisible ext:\n"); + //SwmDumpRegion(Region); + + /* Region to mark invisible for this window = Update region X Window region */ + intersect_region(WindowRegion, WindowRegion, InvisibleRegion); + + /* Check if it's empty */ + if (!is_region_empty(WindowRegion)) + { + //DPRINT1("Subtracting region\n"); + //SwmDumpRegion(WindowRegion); + //DPRINT1("From visible region\n"); + //SwmDumpRegion(Window->Visible); + + /* If it's not empty, subtract it from visible region */ + subtract_region(Window->Visible, Window->Visible, WindowRegion); + + /* And subtract that part from our invisible region */ + subtract_region(InvisibleRegion, InvisibleRegion, WindowRegion); + } + + free_region(WindowRegion); + + /* Break if our whole invisible region is mapped to underlying windows */ + if (is_region_empty(InvisibleRegion)) break; + + /* Advance to the next window */ + Current = Current->Flink; + } + + free_region(InvisibleRegion); +} + +/* NOTE: It alters the passed region! */ +VOID +NTAPI +SwmMarkVisible(struct region *Region) +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + struct region *WindowRegion; + + /* Go through every window from nearest to farthest */ + Current = SwmWindows.Flink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + /* Get window's region */ + WindowRegion = create_empty_region(); + set_region_rect(WindowRegion, &Window->Window); + + /* Region to mark invisible for this window = Update region X Window region */ + intersect_region(WindowRegion, WindowRegion, Region); + + /* Check if it's empty */ + if (!is_region_empty(WindowRegion)) + { + DPRINT1("Invalidating region\n"); + SwmDumpRegion(WindowRegion); + DPRINT1("of window %x\n", Window->hwnd); + + /* If it's not empty, subtract it from the source region */ + subtract_region(Region, Region, WindowRegion); + + /* And add it to this window's visible region */ + union_region(Window->Visible, Window->Visible, WindowRegion); + + /* Invalidate this region of target window */ + SwmInvalidateRegion(Window, WindowRegion, NULL); + + DPRINT1("Rest of the update region is:\n"); + SwmDumpRegion(Region); + } + + free_region(WindowRegion); + + /* If region to update became empty, quit */ + if (is_region_empty(Region)) break; + + /* Advance to the next window */ + Current = Current->Flink; + } +} + +VOID +NTAPI +SwmRecalculateVisibility(PSWM_WINDOW CalcWindow) +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + struct region *Region = create_empty_region(); + struct region *WindowRegion = create_empty_region(); + + set_region_rect(WindowRegion, &CalcWindow->Window); + + /* Compile a total region of visible regions of "higher" windows */ + Current = &CalcWindow->Entry; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + union_region(Region, Region, Window->Visible); + + /* Advance to the previous window */ + Current = Current->Blink; + } + + /* Crop the region against target window */ + intersect_region(Region, Region, WindowRegion); + + /* Subtract result from target window's visible region */ + subtract_region(CalcWindow->Visible, WindowRegion, Region); + + /* Free allocated temporary regions */ + free_region(Region); + free_region(WindowRegion); +} + +VOID +NTAPI +SwmAddWindow(HWND hWnd, RECT *WindowRect) +{ + PSWM_WINDOW Win; + + DPRINT1("SwmAddWindow %x\n", hWnd); + DPRINT1("rect (%d,%d)-(%d,%d)\n", WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom); + + /* Acquire the lock */ + SwmAcquire(); + + /* Allocate entry */ + Win = ExAllocatePool(PagedPool, sizeof(SWM_WINDOW)); + RtlZeroMemory(Win, sizeof(SWM_WINDOW)); + Win->hwnd = hWnd; + Win->Window.left = WindowRect->left; + Win->Window.top = WindowRect->top; + Win->Window.right = WindowRect->right; + Win->Window.bottom = WindowRect->bottom; + + Win->Visible = create_empty_region(); + set_region_rect(Win->Visible, &Win->Window); + + /* Now go through the list and remove this rect from all underlying windows visible region */ + SwmMarkInvisible(Win->Visible); + + InsertHeadList(&SwmWindows, &Win->Entry); + + /* Now ensure it is visible on screen */ + SwmInvalidateRegion(Win, Win->Visible, &Win->Window); + + //SwmDumpWindows(); + //SwmDebugDrawWindows(); + + /* Release the lock */ + SwmRelease(); +} + +PSWM_WINDOW +NTAPI +SwmFindByHwnd(HWND hWnd) +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + + /* Traverse the list to find our window */ + Current = SwmWindows.Flink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + /* Check if it's our entry */ + if (Window->hwnd == hWnd) + { + /* Found it, save it and break out of the loop */ + return Window; + } + + /* Advance to the next window */ + Current = Current->Flink; + } + + return NULL; +} + +VOID +NTAPI +SwmRemoveWindow(HWND hWnd) +{ + PSWM_WINDOW Win; + + /* Acquire the lock */ + SwmAcquire(); + + DPRINT1("SwmRemoveWindow %x\n", hWnd); + + /* Allocate entry */ + Win = SwmFindByHwnd(hWnd); + //ASSERT(Win != NULL); + if (!Win) + { + /* Release the lock */ + SwmRelease(); + + return; + } + + RemoveEntryList(&Win->Entry); + + /* Mark this region as visible in other window */ + SwmMarkVisible(Win->Visible); + + /* Free the entry */ + free_region(Win->Visible); + ExFreePool(Win); + + /* Release the lock */ + SwmRelease(); +} + +VOID +NTAPI +SwmSetForeground(HWND hWnd) +{ + PSWM_WINDOW SwmWin, Previous; + struct region *OldVisible; + + /* Acquire the lock */ + SwmAcquire(); + + /* Allocate entry */ + SwmWin = SwmFindByHwnd(hWnd); + //ASSERT(SwmWin != NULL); + if (!SwmWin) + { + /* Release the lock */ + SwmRelease(); + return; + } + + /* Save previous focus window */ + Previous = CONTAINING_RECORD(SwmWindows.Flink, SWM_WINDOW, Entry); + + /* It's already on top */ + if (Previous->hwnd == hWnd) + { + DPRINT1("hwnd %x is already on top\n", hWnd); + /* Release the lock */ + SwmRelease(); + return; + } + + DPRINT1("Setting %x as foreground, previous window was %x\n", hWnd, Previous->hwnd); + + /* Remove it from the list */ + RemoveEntryList(&SwmWin->Entry); + + /* Add it to the head of the list */ + InsertHeadList(&SwmWindows, &SwmWin->Entry); + + /* Make it fully visible */ + OldVisible = create_empty_region(); + copy_region(OldVisible, SwmWin->Visible); + + free_region(SwmWin->Visible); + SwmWin->Visible = create_empty_region(); + set_region_rect(SwmWin->Visible, &SwmWin->Window); + + /* Intersect new visible and old visible to find region for updating */ + intersect_region(OldVisible, OldVisible, SwmWin->Visible); + + /* If it's not empty - draw missing parts */ + if (!is_region_empty(OldVisible)) + SwmInvalidateRegion(SwmWin, OldVisible, NULL); + + free_region(OldVisible); + + /* Update previous window's visible region */ + SwmRecalculateVisibility(Previous); + + /* Release the lock */ + SwmRelease(); +} + +VOID +NTAPI +SwmPosChanging(HWND hWnd, const RECT *WindowRect) +{ +} + +VOID +NTAPI +SwmPosChanged(HWND hWnd, const RECT *WindowRect, const RECT *OldRect) +{ + PSWM_WINDOW SwmWin; + struct region *NewRegion; + rectangle_t WinRect; + + /* Acquire the lock */ + SwmAcquire(); + + /* Allocate entry */ + SwmWin = SwmFindByHwnd(hWnd); + if (!SwmWin) + { + /* Release the lock */ + SwmRelease(); + return; + } + + SwmWin->Window.left = WindowRect->left; + SwmWin->Window.top = WindowRect->top; + SwmWin->Window.right = WindowRect->right; + SwmWin->Window.bottom = WindowRect->bottom; + + //SwmDebugDrawWindows(); + + /* Assure the moving window is foreground */ + ASSERT(SwmWindows.Flink == &SwmWin->Entry); + + /* Create a region describing new position */ + NewRegion = create_empty_region(); + WinRect.left = WindowRect->left; WinRect.top = WindowRect->top; + WinRect.right = WindowRect->right; WinRect.bottom = WindowRect->bottom; + set_region_rect(NewRegion, &WinRect); + + /* Intersect it with the old region */ + intersect_region(NewRegion, NewRegion, SwmWin->Visible); + + /* This window's visibility region will just move, because it + really equals window's rect. */ + offset_region(SwmWin->Visible, + WindowRect->left - OldRect->left, + WindowRect->top - OldRect->top); + + /* NewRegion now holds the difference. Mark it visible. */ + SwmMarkVisible(NewRegion); + free_region(NewRegion); + + /* Redraw window itself too */ + //SwmInvalidateRegion(SwmWin, SwmWin->Visible, NULL); + + /* Release the lock */ + SwmRelease(); +} + +HWND +NTAPI +SwmGetWindowFromPoint(LONG x, LONG y) +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + + /* Acquire the lock */ + SwmAcquire(); + + /* Traverse the list to find our window */ + Current = SwmWindows.Flink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + if (point_in_region(Window->Visible, x, y)) + { + /* Release the lock */ + SwmRelease(); + + return Window->hwnd; + } + + /* Advance to the next window */ + Current = Current->Flink; + } + + /* Release the lock */ + SwmRelease(); + + return 0; +} + + +VOID +NTAPI +SwmInitialize() +{ + NTSTATUS Status; + + /* Initialize handles list and a spinlock */ + InitializeListHead(&SwmWindows); + + /* Initialize SWM access resource */ + Status = ExInitializeResourceLite(&SwmLock); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure initializing SWM resource!\n"); + } + + SwmTest(); +} + +// haaaaaaaaaaaaaaaaaaack +struct region +{ + int size; + int num_rects; + rectangle_t *rects; + rectangle_t extents; +}; + +VOID +NTAPI +SwmDumpRegion(struct region *Region) +{ + ULONG i; + + //get_region_extents(Region, &ExtRect); + + for (i=0; i<Region->num_rects; i++) + { + DbgPrint("(%d,%d)-(%d,%d) ", Region->rects[i].left, Region->rects[i].top, + Region->rects[i].right, Region->rects[i].bottom); + } + + DbgPrint("\n"); +} + +VOID +NTAPI +SwmDumpWindows() +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + + DPRINT1("Windows in z order: "); + + /* Traverse the list to find our window */ + Current = SwmWindows.Flink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + DbgPrint("%x regions: \n", Window->hwnd); + SwmDumpRegion(Window->Visible); + + /* Advance to the next window */ + Current = Current->Flink; + } + + DbgPrint("\n"); +} + +VOID +NTAPI +SwmDebugDrawRect(HDC hDC, rectangle_t *Rect, ULONG Color) +{ + PDC pDC; + ULONG Scale = 4; + + /* Get a pointer to the DC */ + pDC = DC_Lock(hDC); + + pDC->pLineBrush->BrushObj.iSolidColor = Color; + + GreRectangle(pDC, Rect->left / Scale, Rect->top / Scale, Rect->right / Scale, Rect->bottom / Scale); + + /* Release the object */ + DC_Unlock(pDC); +} + +VOID +NTAPI +SwmDebugDrawRegion(HDC hDC, struct region *Region, ULONG Color) +{ + PDC pDC; + ULONG Scale = 4, i; + + if (is_region_empty(Region)) return; + + /* Get a pointer to the DC */ + pDC = DC_Lock(hDC); + + pDC->pLineBrush->BrushObj.iSolidColor = Color; + + for (i=0; i<Region->num_rects; i++) + GreRectangle(pDC, Region->rects[i].left / Scale, Region->rects[i].top / Scale, + Region->rects[i].right / Scale, Region->rects[i].bottom / Scale); + + /* Release the object */ + DC_Unlock(pDC); +} + +VOID +NTAPI +SwmDebugDrawWindows() +{ + PLIST_ENTRY Current; + PSWM_WINDOW Window; + HDC ScreenDc = 0; + ROS_DCINFO RosDc = {0}; + PBRUSHGDI Brush, BrushBack; + PDC pDC; + RECTL rcSafeBounds; + + /* Create a dc */ + RosGdiCreateDC(&RosDc, &ScreenDc, L"", L"", L"", NULL); + + /* Create a pen and select it */ + Brush = GreCreateSolidBrush(RGB(0xFF, 0, 0)); + + /* Get a pointer to the DC */ + pDC = DC_Lock(ScreenDc); + GreFreeBrush(pDC->pLineBrush); + pDC->pLineBrush = Brush; + + /* Set the clipping object */ + IntEngDeleteClipRegion(pDC->CombinedClip); + RECTL_vSetRect(&rcSafeBounds, + 0, + 0, + 640, + 480); + + pDC->CombinedClip = IntEngCreateClipRegion(1, &rcSafeBounds, &rcSafeBounds); + + /* Clear the area */ + BrushBack = pDC->pFillBrush; + pDC->pFillBrush = GreCreateSolidBrush(RGB(0,0,0)); + GreRectangle(pDC, 0, 0, 800/4, 600/4); + GreFreeBrush(pDC->pFillBrush); + pDC->pFillBrush = BrushBack; + + DC_Unlock(pDC); + + /* Traverse the list to find our window */ + Current = SwmWindows.Flink; + while(Current != &SwmWindows) + { + Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry); + + SwmDebugDrawRect(ScreenDc, &Window->Window, RGB(0,0,255)); + SwmDebugDrawRegion(ScreenDc, Window->Visible, RGB(255,0,0)); + + /* Advance to the next window */ + Current = Current->Flink; + } + + /* Delete screen dc */ + GreFreeBrush(Brush); + RosGdiDeleteDC(ScreenDc); +} + +VOID +NTAPI +SwmTest() +{ +#if 0 + RECT rect; + HWND hwnd; + + /* "desktop" */ + hwnd = (HWND)1; + rect.left = 0; rect.top = 0; + rect.right = 100; rect.bottom = 100; + SwmAddWindow(hwnd, &rect); + + /* win1 */ + hwnd = (HWND)2; + rect.left = 40; rect.top = 40; + rect.right = 60; rect.bottom = 60; + SwmAddWindow(hwnd, &rect); + + /* win2 */ + hwnd = (HWND)3; + rect.left = 50; rect.top = 50; + rect.right = 70; rect.bottom = 70; + SwmAddWindow(hwnd, &rect); + + SwmDumpWindows(); +#endif +} + +/* EOF */
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -81,4 +81,10 @@ RosUserGetKeyNameText 3 RosUserToUnicodeEx 7 RosUserMapVirtualKeyEx 4 -RosUserGetAsyncKeyState 1 +RosUserGetAsyncKeyState 1 +SwmAddWindow 2 +SwmRemoveWindow 1 +SwmSetForeground 1 +SwmPosChanging 2 +SwmPosChanged 3 +SwmGetWindowFromPoint 2
Modified: branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -116,6 +116,9 @@ <file>kbdlayout.c</file> <file>keyboard.c</file> </directory> + <directory name="swm"> + <file>winman.c</file> + </directory> <directory name="wine"> <file>atom.c</file> <file>class.c</file>
Modified: branches/arwinss/reactos/subsystems/win32/win32k/wine/window.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/wine/window.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/wine/window.c [iso-8859-1] Sat Oct 31 21:55:25 2009 @@ -110,7 +110,7 @@ #define WINPTR_NOTOPMOST ((struct window *)4L)
/* retrieve a pointer to a window from its handle */ -static inline struct window *get_window( user_handle_t handle ) +/*static*/ inline struct window *get_window( user_handle_t handle ) { struct window *ret = get_user_object( handle, USER_WINDOW ); if (!ret) set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); @@ -1231,7 +1231,7 @@
/* add/subtract a region (in client coordinates) to the update region of the window */ -static void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags ) +/*static*/ void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags ) { struct region *tmp; struct window *child;