Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
8da2cb16
Commit
8da2cb16
authored
Jan 07, 2013
by
Ken Thomases
Committed by
Alexandre Julliard
Jan 09, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winemac: Implement basic window functionality.
parent
35319684
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1064 additions
and
1 deletion
+1064
-1
Makefile.in
dlls/winemac.drv/Makefile.in
+2
-1
cocoa_app.h
dlls/winemac.drv/cocoa_app.h
+3
-0
cocoa_app.m
dlls/winemac.drv/cocoa_app.m
+20
-0
cocoa_window.h
dlls/winemac.drv/cocoa_window.h
+25
-0
cocoa_window.m
dlls/winemac.drv/cocoa_window.m
+331
-0
macdrv.h
dlls/winemac.drv/macdrv.h
+16
-0
macdrv_cocoa.h
dlls/winemac.drv/macdrv_cocoa.h
+25
-0
window.c
dlls/winemac.drv/window.c
+635
-0
winemac.drv.spec
dlls/winemac.drv/winemac.drv.spec
+7
-0
No files found.
dlls/winemac.drv/Makefile.in
View file @
8da2cb16
...
...
@@ -11,6 +11,7 @@ C_SRCS = \
OBJC_SRCS
=
\
cocoa_app.m
\
cocoa_display.m
\
cocoa_main.m
cocoa_main.m
\
cocoa_window.m
@MAKE_DLL_RULES@
dlls/winemac.drv/cocoa_app.h
View file @
8da2cb16
...
...
@@ -28,3 +28,6 @@
-
(
void
)
transformProcessToForeground
;
@end
void
OnMainThread
(
dispatch_block_t
block
);
void
OnMainThreadAsync
(
dispatch_block_t
block
);
dlls/winemac.drv/cocoa_app.m
View file @
8da2cb16
...
...
@@ -56,3 +56,23 @@
}
@end
/***********************************************************************
* OnMainThread
*
* Run a block on the main thread synchronously.
*/
void
OnMainThread
(
dispatch_block_t
block
)
{
dispatch_sync
(
dispatch_get_main_queue
(),
block
);
}
/***********************************************************************
* OnMainThreadAsync
*
* Run a block on the main thread asynchronously.
*/
void
OnMainThreadAsync
(
dispatch_block_t
block
)
{
dispatch_async
(
dispatch_get_main_queue
(),
block
);
}
dlls/winemac.drv/cocoa_window.h
0 → 100644
View file @
8da2cb16
/*
* MACDRV Cocoa window declarations
*
* Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#import <AppKit/AppKit.h>
@interface
WineWindow
:
NSPanel
<
NSWindowDelegate
>
@end
dlls/winemac.drv/cocoa_window.m
0 → 100644
View file @
8da2cb16
/*
* MACDRV Cocoa window code
*
* Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#import "cocoa_window.h"
#include "macdrv_cocoa.h"
#import "cocoa_app.h"
static
NSUInteger
style_mask_for_features
(
const
struct
macdrv_window_features
*
wf
)
{
NSUInteger
style_mask
;
if
(
wf
->
title_bar
)
{
style_mask
=
NSTitledWindowMask
;
if
(
wf
->
close_button
)
style_mask
|=
NSClosableWindowMask
;
if
(
wf
->
minimize_button
)
style_mask
|=
NSMiniaturizableWindowMask
;
if
(
wf
->
resizable
)
style_mask
|=
NSResizableWindowMask
;
if
(
wf
->
utility
)
style_mask
|=
NSUtilityWindowMask
;
}
else
style_mask
=
NSBorderlessWindowMask
;
return
style_mask
;
}
static
BOOL
frame_intersects_screens
(
NSRect
frame
,
NSArray
*
screens
)
{
NSScreen
*
screen
;
for
(
screen
in
screens
)
{
if
(
NSIntersectsRect
(
frame
,
[
screen
frame
]))
return
TRUE
;
}
return
FALSE
;
}
@interface
WineContentView
:
NSView
@end
@interface
WineWindow
()
+
(
void
)
flipRect
:
(
NSRect
*
)
rect
;
@end
@implementation
WineContentView
-
(
BOOL
)
isFlipped
{
return
YES
;
}
@end
@implementation
WineWindow
+
(
WineWindow
*
)
createWindowWithFeatures
:(
const
struct
macdrv_window_features
*
)
wf
windowFrame
:(
NSRect
)
window_frame
{
WineWindow
*
window
;
WineContentView
*
contentView
;
[
self
flipRect
:
&
window_frame
];
window
=
[[[
self
alloc
]
initWithContentRect
:
window_frame
styleMask
:
style_mask_for_features
(
wf
)
backing
:
NSBackingStoreBuffered
defer
:
YES
]
autorelease
];
/* Standardize windows to eliminate differences between titled and
borderless windows and between NSWindow and NSPanel. */
[
window
setHidesOnDeactivate
:
NO
];
[
window
setReleasedWhenClosed
:
NO
];
[
window
disableCursorRects
];
[
window
setShowsResizeIndicator
:
NO
];
[
window
setHasShadow
:
wf
->
shadow
];
[
window
setDelegate
:
window
];
contentView
=
[[[
WineContentView
alloc
]
initWithFrame
:
NSZeroRect
]
autorelease
];
if
(
!
contentView
)
return
nil
;
[
contentView
setAutoresizesSubviews
:
NO
];
[
window
setContentView
:
contentView
];
return
window
;
}
+
(
void
)
flipRect
:(
NSRect
*
)
rect
{
rect
->
origin
.
y
=
NSMaxY
([[[
NSScreen
screens
]
objectAtIndex
:
0
]
frame
])
-
NSMaxY
(
*
rect
);
}
-
(
void
)
setWindowFeatures
:(
const
struct
macdrv_window_features
*
)
wf
{
[
self
setStyleMask
:
style_mask_for_features
(
wf
)];
[
self
setHasShadow
:
wf
->
shadow
];
}
/* Returns whether or not the window was ordered in, which depends on if
its frame intersects any screen. */
-
(
BOOL
)
orderBelow
:(
WineWindow
*
)
prev
orAbove
:(
WineWindow
*
)
next
{
BOOL
on_screen
=
frame_intersects_screens
([
self
frame
],
[
NSScreen
screens
]);
if
(
on_screen
)
{
[
NSApp
transformProcessToForeground
];
if
(
prev
)
[
self
orderWindow
:
NSWindowBelow
relativeTo
:[
prev
windowNumber
]];
else
[
self
orderWindow
:
NSWindowAbove
relativeTo
:[
next
windowNumber
]];
}
return
on_screen
;
}
-
(
BOOL
)
setFrameIfOnScreen
:(
NSRect
)
contentRect
{
NSArray
*
screens
=
[
NSScreen
screens
];
BOOL
on_screen
=
[
self
isVisible
];
NSRect
frame
,
oldFrame
;
if
(
!
[
screens
count
])
return
on_screen
;
/* Origin is (left, top) in a top-down space. Need to convert it to
(left, bottom) in a bottom-up space. */
[[
self
class
]
flipRect
:
&
contentRect
];
if
(
on_screen
)
{
on_screen
=
frame_intersects_screens
(
contentRect
,
screens
);
if
(
!
on_screen
)
[
self
orderOut
:
nil
];
}
oldFrame
=
[
self
frame
];
frame
=
[
self
frameRectForContentRect
:
contentRect
];
if
(
!
NSEqualRects
(
frame
,
oldFrame
))
{
if
(
NSEqualSizes
(
frame
.
size
,
oldFrame
.
size
))
[
self
setFrameOrigin
:
frame
.
origin
];
else
[
self
setFrame
:
frame
display
:
YES
];
}
return
on_screen
;
}
/*
* ---------- NSWindow method overrides ----------
*/
-
(
BOOL
)
canBecomeKeyWindow
{
return
YES
;
}
-
(
BOOL
)
canBecomeMainWindow
{
return
[
self
canBecomeKeyWindow
];
}
/*
* ---------- NSWindowDelegate methods ----------
*/
-
(
BOOL
)
windowShouldClose
:
(
id
)
sender
{
return
NO
;
}
@end
/***********************************************************************
* macdrv_create_cocoa_window
*
* Create a Cocoa window with the given content frame and features (e.g.
* title bar, close box, etc.).
*/
macdrv_window
macdrv_create_cocoa_window
(
const
struct
macdrv_window_features
*
wf
,
CGRect
frame
)
{
__block
WineWindow
*
window
;
OnMainThread
(
^
{
window
=
[[
WineWindow
createWindowWithFeatures
:
wf
windowFrame
:
NSRectFromCGRect
(
frame
)]
retain
];
});
return
(
macdrv_window
)
window
;
}
/***********************************************************************
* macdrv_destroy_cocoa_window
*
* Destroy a Cocoa window.
*/
void
macdrv_destroy_cocoa_window
(
macdrv_window
w
)
{
NSAutoreleasePool
*
pool
=
[[
NSAutoreleasePool
alloc
]
init
];
WineWindow
*
window
=
(
WineWindow
*
)
w
;
[
window
close
];
[
window
release
];
[
pool
release
];
}
/***********************************************************************
* macdrv_set_cocoa_window_features
*
* Update a Cocoa window's features.
*/
void
macdrv_set_cocoa_window_features
(
macdrv_window
w
,
const
struct
macdrv_window_features
*
wf
)
{
WineWindow
*
window
=
(
WineWindow
*
)
w
;
OnMainThread
(
^
{
[
window
setWindowFeatures
:
wf
];
});
}
/***********************************************************************
* macdrv_set_cocoa_window_title
*
* Set a Cocoa window's title.
*/
void
macdrv_set_cocoa_window_title
(
macdrv_window
w
,
const
unsigned
short
*
title
,
size_t
length
)
{
NSAutoreleasePool
*
pool
=
[[
NSAutoreleasePool
alloc
]
init
];
WineWindow
*
window
=
(
WineWindow
*
)
w
;
NSString
*
titleString
;
if
(
title
)
titleString
=
[
NSString
stringWithCharacters
:
title
length
:
length
];
else
titleString
=
@""
;
OnMainThreadAsync
(
^
{
[
window
setTitle
:
titleString
];
});
[
pool
release
];
}
/***********************************************************************
* macdrv_order_cocoa_window
*
* Reorder a Cocoa window relative to other windows. If prev is
* non-NULL, it is ordered below that window. Else, if next is non-NULL,
* it is ordered above that window. Otherwise, it is ordered to the
* front.
*
* Returns true if the window has actually been ordered onto the screen
* (i.e. if its frame intersects with a screen). Otherwise, false.
*/
int
macdrv_order_cocoa_window
(
macdrv_window
w
,
macdrv_window
prev
,
macdrv_window
next
)
{
WineWindow
*
window
=
(
WineWindow
*
)
w
;
__block
BOOL
on_screen
;
OnMainThread
(
^
{
on_screen
=
[
window
orderBelow
:(
WineWindow
*
)
prev
orAbove
:(
WineWindow
*
)
next
];
});
return
on_screen
;
}
/***********************************************************************
* macdrv_hide_cocoa_window
*
* Hides a Cocoa window.
*/
void
macdrv_hide_cocoa_window
(
macdrv_window
w
)
{
WineWindow
*
window
=
(
WineWindow
*
)
w
;
OnMainThread
(
^
{
[
window
orderOut
:
nil
];
});
}
/***********************************************************************
* macdrv_set_cocoa_window_frame
*
* Move a Cocoa window. If the window has been moved out of the bounds
* of the desktop, it is ordered out. (This routine won't ever order a
* window in, though.)
*
* Returns true if the window is on screen; false otherwise.
*/
int
macdrv_set_cocoa_window_frame
(
macdrv_window
w
,
const
CGRect
*
new_frame
)
{
WineWindow
*
window
=
(
WineWindow
*
)
w
;
__block
BOOL
on_screen
;
OnMainThread
(
^
{
on_screen
=
[
window
setFrameIfOnScreen
:
NSRectFromCGRect
(
*
new_frame
)];
});
return
on_screen
;
}
dlls/winemac.drv/macdrv.h
View file @
8da2cb16
...
...
@@ -70,4 +70,20 @@ static inline const char *wine_dbgstr_cgrect(CGRect cgrect)
extern
CGRect
macdrv_get_desktop_rect
(
void
)
DECLSPEC_HIDDEN
;
/**************************************************************************
* Mac USER driver
*/
/* macdrv private window data */
struct
macdrv_win_data
{
HWND
hwnd
;
/* hwnd that this private data belongs to */
macdrv_window
cocoa_window
;
RECT
window_rect
;
/* USER window rectangle relative to parent */
RECT
whole_rect
;
/* Mac window rectangle for the whole window relative to parent */
RECT
client_rect
;
/* client area relative to parent */
BOOL
on_screen
:
1
;
/* is window ordered in? */
};
#endif
/* __WINE_MACDRV_H */
dlls/winemac.drv/macdrv_cocoa.h
View file @
8da2cb16
...
...
@@ -97,6 +97,8 @@
#endif
typedef
struct
macdrv_opaque_window
*
macdrv_window
;
struct
macdrv_display
{
CGDirectDisplayID
displayID
;
CGRect
frame
;
...
...
@@ -112,4 +114,27 @@ extern int macdrv_start_cocoa_app(void) DECLSPEC_HIDDEN;
extern
int
macdrv_get_displays
(
struct
macdrv_display
**
displays
,
int
*
count
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_free_displays
(
struct
macdrv_display
*
displays
)
DECLSPEC_HIDDEN
;
/* window */
struct
macdrv_window_features
{
unsigned
int
title_bar
:
1
;
unsigned
int
close_button
:
1
;
unsigned
int
minimize_button
:
1
;
unsigned
int
resizable
:
1
;
unsigned
int
utility
:
1
;
unsigned
int
shadow
:
1
;
};
extern
macdrv_window
macdrv_create_cocoa_window
(
const
struct
macdrv_window_features
*
wf
,
CGRect
frame
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_destroy_cocoa_window
(
macdrv_window
w
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_set_cocoa_window_features
(
macdrv_window
w
,
const
struct
macdrv_window_features
*
wf
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_set_cocoa_window_title
(
macdrv_window
w
,
const
UniChar
*
title
,
size_t
length
)
DECLSPEC_HIDDEN
;
extern
int
macdrv_order_cocoa_window
(
macdrv_window
w
,
macdrv_window
prev
,
macdrv_window
next
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_hide_cocoa_window
(
macdrv_window
w
)
DECLSPEC_HIDDEN
;
extern
int
macdrv_set_cocoa_window_frame
(
macdrv_window
w
,
const
CGRect
*
new_frame
)
DECLSPEC_HIDDEN
;
#endif
/* __WINE_MACDRV_COCOA_H */
dlls/winemac.drv/window.c
View file @
8da2cb16
...
...
@@ -25,11 +25,439 @@
#include "macdrv.h"
#include "winuser.h"
#include "wine/unicode.h"
#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
macdrv
);
static
CRITICAL_SECTION
win_data_section
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
0
,
0
,
&
win_data_section
,
{
&
critsect_debug
.
ProcessLocksList
,
&
critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": win_data_section"
)
}
};
static
CRITICAL_SECTION
win_data_section
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
CFMutableDictionaryRef
win_datas
;
/***********************************************************************
* get_cocoa_window_features
*/
static
void
get_cocoa_window_features
(
struct
macdrv_win_data
*
data
,
DWORD
style
,
DWORD
ex_style
,
struct
macdrv_window_features
*
wf
)
{
memset
(
wf
,
0
,
sizeof
(
*
wf
));
if
(
IsRectEmpty
(
&
data
->
window_rect
))
return
;
if
((
style
&
WS_CAPTION
)
==
WS_CAPTION
&&
!
(
ex_style
&
WS_EX_LAYERED
))
{
wf
->
shadow
=
1
;
wf
->
title_bar
=
1
;
if
(
style
&
WS_SYSMENU
)
wf
->
close_button
=
1
;
if
(
style
&
WS_MINIMIZEBOX
)
wf
->
minimize_button
=
1
;
if
(
style
&
WS_MAXIMIZEBOX
)
wf
->
resizable
=
1
;
if
(
ex_style
&
WS_EX_TOOLWINDOW
)
wf
->
utility
=
1
;
}
if
(
ex_style
&
WS_EX_DLGMODALFRAME
)
wf
->
shadow
=
1
;
else
if
(
style
&
WS_THICKFRAME
)
{
wf
->
shadow
=
1
;
wf
->
resizable
=
1
;
}
else
if
((
style
&
(
WS_DLGFRAME
|
WS_BORDER
))
==
WS_DLGFRAME
)
wf
->
shadow
=
1
;
}
/***********************************************************************
* get_mac_rect_offset
*
* Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
*/
static
void
get_mac_rect_offset
(
struct
macdrv_win_data
*
data
,
DWORD
style
,
RECT
*
rect
)
{
DWORD
ex_style
,
style_mask
=
0
,
ex_style_mask
=
0
;
struct
macdrv_window_features
wf
;
rect
->
top
=
rect
->
bottom
=
rect
->
left
=
rect
->
right
=
0
;
ex_style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_EXSTYLE
);
get_cocoa_window_features
(
data
,
style
,
ex_style
,
&
wf
);
if
(
wf
.
title_bar
)
style_mask
|=
WS_CAPTION
;
if
(
wf
.
shadow
)
{
style_mask
|=
WS_DLGFRAME
|
WS_THICKFRAME
;
ex_style_mask
|=
WS_EX_DLGMODALFRAME
;
}
AdjustWindowRectEx
(
rect
,
style
&
style_mask
,
FALSE
,
ex_style
&
ex_style_mask
);
TRACE
(
"%p/%p style %08x ex_style %08x -> %s
\n
"
,
data
->
hwnd
,
data
->
cocoa_window
,
style
,
ex_style
,
wine_dbgstr_rect
(
rect
));
}
/***********************************************************************
* show_window
*/
static
void
show_window
(
struct
macdrv_win_data
*
data
)
{
TRACE
(
"win %p/%p
\n
"
,
data
->
hwnd
,
data
->
cocoa_window
);
data
->
on_screen
=
macdrv_order_cocoa_window
(
data
->
cocoa_window
,
NULL
,
NULL
);
}
/***********************************************************************
* hide_window
*/
static
void
hide_window
(
struct
macdrv_win_data
*
data
)
{
TRACE
(
"win %p/%p
\n
"
,
data
->
hwnd
,
data
->
cocoa_window
);
macdrv_hide_cocoa_window
(
data
->
cocoa_window
);
data
->
on_screen
=
FALSE
;
}
/***********************************************************************
* macdrv_window_to_mac_rect
*
* Convert a rect from client to Mac window coordinates
*/
static
void
macdrv_window_to_mac_rect
(
struct
macdrv_win_data
*
data
,
DWORD
style
,
RECT
*
rect
)
{
RECT
rc
;
if
((
style
&
(
WS_POPUP
|
WS_CHILD
))
==
WS_CHILD
)
return
;
if
(
IsRectEmpty
(
rect
))
return
;
get_mac_rect_offset
(
data
,
style
,
&
rc
);
rect
->
left
-=
rc
.
left
;
rect
->
right
-=
rc
.
right
;
rect
->
top
-=
rc
.
top
;
rect
->
bottom
-=
rc
.
bottom
;
if
(
rect
->
top
>=
rect
->
bottom
)
rect
->
bottom
=
rect
->
top
+
1
;
if
(
rect
->
left
>=
rect
->
right
)
rect
->
right
=
rect
->
left
+
1
;
}
/***********************************************************************
* macdrv_mac_to_window_rect
*
* Opposite of macdrv_window_to_mac_rect
*/
static
void
macdrv_mac_to_window_rect
(
struct
macdrv_win_data
*
data
,
RECT
*
rect
)
{
RECT
rc
;
DWORD
style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_STYLE
);
if
((
style
&
(
WS_POPUP
|
WS_CHILD
))
==
WS_CHILD
)
return
;
if
(
IsRectEmpty
(
rect
))
return
;
get_mac_rect_offset
(
data
,
style
,
&
rc
);
rect
->
left
+=
rc
.
left
;
rect
->
right
+=
rc
.
right
;
rect
->
top
+=
rc
.
top
;
rect
->
bottom
+=
rc
.
bottom
;
if
(
rect
->
top
>=
rect
->
bottom
)
rect
->
bottom
=
rect
->
top
+
1
;
if
(
rect
->
left
>=
rect
->
right
)
rect
->
right
=
rect
->
left
+
1
;
}
/***********************************************************************
* constrain_window_frame
*
* Alter a window frame rectangle to fit within a) Cocoa's documented
* limits, and b) sane sizes, like twice the desktop rect.
*/
static
void
constrain_window_frame
(
CGRect
*
frame
)
{
CGRect
desktop_rect
=
macdrv_get_desktop_rect
();
int
max_width
,
max_height
;
max_width
=
min
(
32000
,
2
*
CGRectGetWidth
(
desktop_rect
));
max_height
=
min
(
32000
,
2
*
CGRectGetHeight
(
desktop_rect
));
if
(
frame
->
origin
.
x
<
-
16000
)
frame
->
origin
.
x
=
-
16000
;
if
(
frame
->
origin
.
y
<
-
16000
)
frame
->
origin
.
y
=
-
16000
;
if
(
frame
->
origin
.
x
>
16000
)
frame
->
origin
.
x
=
16000
;
if
(
frame
->
origin
.
y
>
16000
)
frame
->
origin
.
y
=
16000
;
if
(
frame
->
size
.
width
>
max_width
)
frame
->
size
.
width
=
max_width
;
if
(
frame
->
size
.
height
>
max_height
)
frame
->
size
.
height
=
max_height
;
}
/***********************************************************************
* alloc_win_data
*/
static
struct
macdrv_win_data
*
alloc_win_data
(
HWND
hwnd
)
{
struct
macdrv_win_data
*
data
;
if
((
data
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
data
))))
{
data
->
hwnd
=
hwnd
;
EnterCriticalSection
(
&
win_data_section
);
if
(
!
win_datas
)
win_datas
=
CFDictionaryCreateMutable
(
NULL
,
0
,
NULL
,
NULL
);
CFDictionarySetValue
(
win_datas
,
hwnd
,
data
);
}
return
data
;
}
/***********************************************************************
* get_win_data
*
* Lock and return the data structure associated with a window.
*/
static
struct
macdrv_win_data
*
get_win_data
(
HWND
hwnd
)
{
struct
macdrv_win_data
*
data
;
if
(
!
hwnd
)
return
NULL
;
EnterCriticalSection
(
&
win_data_section
);
if
(
win_datas
&&
(
data
=
(
struct
macdrv_win_data
*
)
CFDictionaryGetValue
(
win_datas
,
hwnd
)))
return
data
;
LeaveCriticalSection
(
&
win_data_section
);
return
NULL
;
}
/***********************************************************************
* release_win_data
*
* Release the data returned by get_win_data.
*/
static
void
release_win_data
(
struct
macdrv_win_data
*
data
)
{
if
(
data
)
LeaveCriticalSection
(
&
win_data_section
);
}
/***********************************************************************
* macdrv_get_cocoa_window
*
* Return the Mac window associated with the full area of a window
*/
static
macdrv_window
macdrv_get_cocoa_window
(
HWND
hwnd
)
{
struct
macdrv_win_data
*
data
=
get_win_data
(
hwnd
);
macdrv_window
ret
=
data
?
data
->
cocoa_window
:
NULL
;
release_win_data
(
data
);
return
ret
;
}
/***********************************************************************
* set_cocoa_window_properties
*
* Set the window properties for a Cocoa window based on its Windows
* properties.
*/
static
void
set_cocoa_window_properties
(
struct
macdrv_win_data
*
data
)
{
DWORD
style
,
ex_style
;
struct
macdrv_window_features
wf
;
style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_STYLE
);
ex_style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_EXSTYLE
);
get_cocoa_window_features
(
data
,
style
,
ex_style
,
&
wf
);
macdrv_set_cocoa_window_features
(
data
->
cocoa_window
,
&
wf
);
}
/**********************************************************************
* create_cocoa_window
*
* Create the whole Mac window for a given window
*/
static
void
create_cocoa_window
(
struct
macdrv_win_data
*
data
)
{
WCHAR
text
[
1024
];
struct
macdrv_window_features
wf
;
CGRect
frame
;
DWORD
style
,
ex_style
;
style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_STYLE
);
ex_style
=
GetWindowLongW
(
data
->
hwnd
,
GWL_EXSTYLE
);
data
->
whole_rect
=
data
->
window_rect
;
macdrv_window_to_mac_rect
(
data
,
style
,
&
data
->
whole_rect
);
memset
(
&
wf
,
0
,
sizeof
(
wf
));
get_cocoa_window_features
(
data
,
style
,
ex_style
,
&
wf
);
frame
=
cgrect_from_rect
(
data
->
whole_rect
);
constrain_window_frame
(
&
frame
);
TRACE
(
"creating %p window %s whole %s client %s
\n
"
,
data
->
hwnd
,
wine_dbgstr_rect
(
&
data
->
window_rect
),
wine_dbgstr_rect
(
&
data
->
whole_rect
),
wine_dbgstr_rect
(
&
data
->
client_rect
));
data
->
cocoa_window
=
macdrv_create_cocoa_window
(
&
wf
,
frame
);
if
(
!
data
->
cocoa_window
)
return
;
set_cocoa_window_properties
(
data
);
/* set the window text */
if
(
!
InternalGetWindowText
(
data
->
hwnd
,
text
,
sizeof
(
text
)
/
sizeof
(
WCHAR
)))
text
[
0
]
=
0
;
macdrv_set_cocoa_window_title
(
data
->
cocoa_window
,
text
,
strlenW
(
text
));
}
/**********************************************************************
* destroy_cocoa_window
*
* Destroy the whole Mac window for a given window.
*/
static
void
destroy_cocoa_window
(
struct
macdrv_win_data
*
data
)
{
if
(
!
data
->
cocoa_window
)
return
;
TRACE
(
"win %p Cocoa win %p
\n
"
,
data
->
hwnd
,
data
->
cocoa_window
);
macdrv_destroy_cocoa_window
(
data
->
cocoa_window
);
data
->
cocoa_window
=
0
;
data
->
on_screen
=
FALSE
;
}
/***********************************************************************
* macdrv_create_win_data
*
* Create a Mac data window structure for an existing window.
*/
static
struct
macdrv_win_data
*
macdrv_create_win_data
(
HWND
hwnd
,
const
RECT
*
window_rect
,
const
RECT
*
client_rect
)
{
struct
macdrv_win_data
*
data
;
HWND
parent
;
if
(
GetWindowThreadProcessId
(
hwnd
,
NULL
)
!=
GetCurrentThreadId
())
return
NULL
;
if
(
!
(
parent
=
GetAncestor
(
hwnd
,
GA_PARENT
)))
/* desktop */
return
NULL
;
/* don't create win data for HWND_MESSAGE windows */
if
(
parent
!=
GetDesktopWindow
()
&&
!
GetAncestor
(
parent
,
GA_PARENT
))
return
NULL
;
if
(
!
(
data
=
alloc_win_data
(
hwnd
)))
return
NULL
;
data
->
whole_rect
=
data
->
window_rect
=
*
window_rect
;
data
->
client_rect
=
*
client_rect
;
if
(
parent
==
GetDesktopWindow
())
{
create_cocoa_window
(
data
);
TRACE
(
"win %p/%p window %s whole %s client %s
\n
"
,
hwnd
,
data
->
cocoa_window
,
wine_dbgstr_rect
(
&
data
->
window_rect
),
wine_dbgstr_rect
(
&
data
->
whole_rect
),
wine_dbgstr_rect
(
&
data
->
client_rect
));
}
return
data
;
}
/***********************************************************************
* sync_window_position
*
* Synchronize the Mac window position with the Windows one
*/
static
void
sync_window_position
(
struct
macdrv_win_data
*
data
,
UINT
swp_flags
)
{
CGRect
frame
=
cgrect_from_rect
(
data
->
whole_rect
);
constrain_window_frame
(
&
frame
);
data
->
on_screen
=
macdrv_set_cocoa_window_frame
(
data
->
cocoa_window
,
&
frame
);
TRACE
(
"win %p/%p pos %s
\n
"
,
data
->
hwnd
,
data
->
cocoa_window
,
wine_dbgstr_rect
(
&
data
->
whole_rect
));
if
(
data
->
on_screen
&&
(
!
(
swp_flags
&
SWP_NOZORDER
)
||
(
swp_flags
&
SWP_SHOWWINDOW
)))
{
HWND
next
=
NULL
;
macdrv_window
prev_window
=
NULL
;
macdrv_window
next_window
=
NULL
;
/* find window that this one must be after */
HWND
prev
=
GetWindow
(
data
->
hwnd
,
GW_HWNDPREV
);
while
(
prev
&&
!
((
GetWindowLongW
(
prev
,
GWL_STYLE
)
&
WS_VISIBLE
)
&&
(
prev_window
=
macdrv_get_cocoa_window
(
prev
))))
prev
=
GetWindow
(
prev
,
GW_HWNDPREV
);
if
(
!
prev_window
)
{
/* find window that this one must be before */
next
=
GetWindow
(
data
->
hwnd
,
GW_HWNDNEXT
);
while
(
next
&&
!
((
GetWindowLongW
(
next
,
GWL_STYLE
)
&
WS_VISIBLE
)
&&
(
next_window
=
macdrv_get_cocoa_window
(
next
))))
next
=
GetWindow
(
next
,
GW_HWNDNEXT
);
}
data
->
on_screen
=
macdrv_order_cocoa_window
(
data
->
cocoa_window
,
prev_window
,
next_window
);
TRACE
(
"win %p/%p below %p/%p above %p/%p
\n
"
,
data
->
hwnd
,
data
->
cocoa_window
,
prev
,
prev_window
,
next
,
next_window
);
}
}
/***********************************************************************
* move_window_bits
*
* Move the window bits when a window is moved.
*/
static
void
move_window_bits
(
HWND
hwnd
,
macdrv_window
window
,
const
RECT
*
old_rect
,
const
RECT
*
new_rect
,
const
RECT
*
old_client_rect
,
const
RECT
*
new_client_rect
,
const
RECT
*
new_window_rect
)
{
RECT
src_rect
=
*
old_rect
;
RECT
dst_rect
=
*
new_rect
;
HDC
hdc_src
,
hdc_dst
;
HRGN
rgn
;
HWND
parent
=
0
;
if
(
!
window
)
{
OffsetRect
(
&
dst_rect
,
-
new_window_rect
->
left
,
-
new_window_rect
->
top
);
parent
=
GetAncestor
(
hwnd
,
GA_PARENT
);
hdc_src
=
GetDCEx
(
parent
,
0
,
DCX_CACHE
);
hdc_dst
=
GetDCEx
(
hwnd
,
0
,
DCX_CACHE
|
DCX_WINDOW
);
}
else
{
OffsetRect
(
&
dst_rect
,
-
new_client_rect
->
left
,
-
new_client_rect
->
top
);
/* make src rect relative to the old position of the window */
OffsetRect
(
&
src_rect
,
-
old_client_rect
->
left
,
-
old_client_rect
->
top
);
if
(
dst_rect
.
left
==
src_rect
.
left
&&
dst_rect
.
top
==
src_rect
.
top
)
return
;
hdc_src
=
hdc_dst
=
GetDCEx
(
hwnd
,
0
,
DCX_CACHE
);
}
rgn
=
CreateRectRgnIndirect
(
&
dst_rect
);
SelectClipRgn
(
hdc_dst
,
rgn
);
DeleteObject
(
rgn
);
ExcludeUpdateRgn
(
hdc_dst
,
hwnd
);
TRACE
(
"copying bits for win %p/%p %s -> %s
\n
"
,
hwnd
,
window
,
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
);
ReleaseDC
(
hwnd
,
hdc_dst
);
if
(
hdc_src
!=
hdc_dst
)
ReleaseDC
(
parent
,
hdc_src
);
}
/**********************************************************************
* CreateDesktopWindow (MACDRV.@)
*/
...
...
@@ -71,3 +499,210 @@ BOOL CDECL macdrv_CreateDesktopWindow(HWND hwnd)
return
TRUE
;
}
/**********************************************************************
* CreateWindow (MACDRV.@)
*/
BOOL
CDECL
macdrv_CreateWindow
(
HWND
hwnd
)
{
return
TRUE
;
}
/***********************************************************************
* DestroyWindow (MACDRV.@)
*/
void
CDECL
macdrv_DestroyWindow
(
HWND
hwnd
)
{
struct
macdrv_win_data
*
data
;
TRACE
(
"%p
\n
"
,
hwnd
);
if
(
!
(
data
=
get_win_data
(
hwnd
)))
return
;
destroy_cocoa_window
(
data
);
CFDictionaryRemoveValue
(
win_datas
,
hwnd
);
release_win_data
(
data
);
HeapFree
(
GetProcessHeap
(),
0
,
data
);
}
/*****************************************************************
* SetParent (MACDRV.@)
*/
void
CDECL
macdrv_SetParent
(
HWND
hwnd
,
HWND
parent
,
HWND
old_parent
)
{
struct
macdrv_win_data
*
data
;
TRACE
(
"%p, %p, %p
\n
"
,
hwnd
,
parent
,
old_parent
);
if
(
parent
==
old_parent
)
return
;
if
(
!
(
data
=
get_win_data
(
hwnd
)))
return
;
if
(
parent
!=
GetDesktopWindow
())
/* a child window */
{
if
(
old_parent
==
GetDesktopWindow
())
{
/* destroy the old Mac window */
destroy_cocoa_window
(
data
);
}
}
else
/* new top level window */
create_cocoa_window
(
data
);
release_win_data
(
data
);
}
/***********************************************************************
* SetWindowStyle (MACDRV.@)
*
* Update the state of the Cocoa window to reflect a style change
*/
void
CDECL
macdrv_SetWindowStyle
(
HWND
hwnd
,
INT
offset
,
STYLESTRUCT
*
style
)
{
struct
macdrv_win_data
*
data
;
TRACE
(
"%p, %d, %p
\n
"
,
hwnd
,
offset
,
style
);
if
(
hwnd
==
GetDesktopWindow
())
return
;
if
(
!
(
data
=
get_win_data
(
hwnd
)))
return
;
if
(
data
->
cocoa_window
)
set_cocoa_window_properties
(
data
);
release_win_data
(
data
);
}
/*****************************************************************
* SetWindowText (MACDRV.@)
*/
void
CDECL
macdrv_SetWindowText
(
HWND
hwnd
,
LPCWSTR
text
)
{
macdrv_window
win
;
TRACE
(
"%p, %s
\n
"
,
hwnd
,
debugstr_w
(
text
));
if
((
win
=
macdrv_get_cocoa_window
(
hwnd
)))
macdrv_set_cocoa_window_title
(
win
,
text
,
strlenW
(
text
));
}
/***********************************************************************
* WindowPosChanging (MACDRV.@)
*/
void
CDECL
macdrv_WindowPosChanging
(
HWND
hwnd
,
HWND
insert_after
,
UINT
swp_flags
,
const
RECT
*
window_rect
,
const
RECT
*
client_rect
,
RECT
*
visible_rect
,
struct
window_surface
**
surface
)
{
struct
macdrv_win_data
*
data
=
get_win_data
(
hwnd
);
DWORD
style
=
GetWindowLongW
(
hwnd
,
GWL_STYLE
);
TRACE
(
"%p after %p swp %04x window %s client %s visible %s surface %p
\n
"
,
hwnd
,
insert_after
,
swp_flags
,
wine_dbgstr_rect
(
window_rect
),
wine_dbgstr_rect
(
client_rect
),
wine_dbgstr_rect
(
visible_rect
),
surface
);
if
(
!
data
&&
!
(
data
=
macdrv_create_win_data
(
hwnd
,
window_rect
,
client_rect
)))
return
;
*
visible_rect
=
*
window_rect
;
macdrv_window_to_mac_rect
(
data
,
style
,
visible_rect
);
TRACE
(
"visible_rect %s -> %s
\n
"
,
wine_dbgstr_rect
(
window_rect
),
wine_dbgstr_rect
(
visible_rect
));
/* release the window surface if necessary */
if
(
!
data
->
cocoa_window
)
goto
done
;
if
(
swp_flags
&
SWP_HIDEWINDOW
)
goto
done
;
if
(
*
surface
)
window_surface_release
(
*
surface
);
*
surface
=
NULL
;
done:
release_win_data
(
data
);
}
/***********************************************************************
* WindowPosChanged (MACDRV.@)
*/
void
CDECL
macdrv_WindowPosChanged
(
HWND
hwnd
,
HWND
insert_after
,
UINT
swp_flags
,
const
RECT
*
window_rect
,
const
RECT
*
client_rect
,
const
RECT
*
visible_rect
,
const
RECT
*
valid_rects
,
struct
window_surface
*
surface
)
{
struct
macdrv_win_data
*
data
;
DWORD
new_style
=
GetWindowLongW
(
hwnd
,
GWL_STYLE
);
RECT
old_window_rect
,
old_whole_rect
,
old_client_rect
;
if
(
!
(
data
=
get_win_data
(
hwnd
)))
return
;
old_window_rect
=
data
->
window_rect
;
old_whole_rect
=
data
->
whole_rect
;
old_client_rect
=
data
->
client_rect
;
data
->
window_rect
=
*
window_rect
;
data
->
whole_rect
=
*
visible_rect
;
data
->
client_rect
=
*
client_rect
;
TRACE
(
"win %p/%p window %s whole %s client %s style %08x flags %08x surface %p
\n
"
,
hwnd
,
data
->
cocoa_window
,
wine_dbgstr_rect
(
window_rect
),
wine_dbgstr_rect
(
visible_rect
),
wine_dbgstr_rect
(
client_rect
),
new_style
,
swp_flags
,
surface
);
if
(
!
IsRectEmpty
(
&
valid_rects
[
0
]))
{
macdrv_window
window
=
data
->
cocoa_window
;
int
x_offset
=
old_whole_rect
.
left
-
data
->
whole_rect
.
left
;
int
y_offset
=
old_whole_rect
.
top
-
data
->
whole_rect
.
top
;
/* if all that happened is that the whole window moved, copy everything */
if
(
!
(
swp_flags
&
SWP_FRAMECHANGED
)
&&
old_whole_rect
.
right
-
data
->
whole_rect
.
right
==
x_offset
&&
old_whole_rect
.
bottom
-
data
->
whole_rect
.
bottom
==
y_offset
&&
old_client_rect
.
left
-
data
->
client_rect
.
left
==
x_offset
&&
old_client_rect
.
right
-
data
->
client_rect
.
right
==
x_offset
&&
old_client_rect
.
top
-
data
->
client_rect
.
top
==
y_offset
&&
old_client_rect
.
bottom
-
data
->
client_rect
.
bottom
==
y_offset
&&
!
memcmp
(
&
valid_rects
[
0
],
&
data
->
client_rect
,
sizeof
(
RECT
)))
{
/* A Cocoa window's bits are moved automatically */
if
(
!
window
&&
(
x_offset
!=
0
||
y_offset
!=
0
))
{
release_win_data
(
data
);
move_window_bits
(
hwnd
,
window
,
&
old_whole_rect
,
visible_rect
,
&
old_client_rect
,
client_rect
,
window_rect
);
if
(
!
(
data
=
get_win_data
(
hwnd
)))
return
;
}
}
else
{
release_win_data
(
data
);
move_window_bits
(
hwnd
,
window
,
&
valid_rects
[
1
],
&
valid_rects
[
0
],
&
old_client_rect
,
client_rect
,
window_rect
);
if
(
!
(
data
=
get_win_data
(
hwnd
)))
return
;
}
}
if
(
!
data
->
cocoa_window
)
goto
done
;
if
(
data
->
on_screen
)
{
if
((
swp_flags
&
SWP_HIDEWINDOW
)
&&
!
(
new_style
&
WS_VISIBLE
))
hide_window
(
data
);
}
if
(
new_style
&
WS_VISIBLE
)
{
if
(
!
data
->
on_screen
||
(
swp_flags
&
(
SWP_FRAMECHANGED
|
SWP_STATECHANGED
)))
set_cocoa_window_properties
(
data
);
if
(
!
data
->
on_screen
)
show_window
(
data
);
}
sync_window_position
(
data
,
swp_flags
);
set_cocoa_window_properties
(
data
);
done:
release_win_data
(
data
);
}
dlls/winemac.drv/winemac.drv.spec
View file @
8da2cb16
...
...
@@ -5,5 +5,12 @@
# USER driver
@ cdecl CreateDesktopWindow(long) macdrv_CreateDesktopWindow
@ cdecl CreateWindow(long) macdrv_CreateWindow
@ cdecl DestroyWindow(long) macdrv_DestroyWindow
@ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
@ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo
@ cdecl SetParent(long long long) macdrv_SetParent
@ cdecl SetWindowStyle(ptr long ptr) macdrv_SetWindowStyle
@ cdecl SetWindowText(long wstr) macdrv_SetWindowText
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) macdrv_WindowPosChanged
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) macdrv_WindowPosChanging
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