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
a49df4b3
Commit
a49df4b3
authored
Feb 24, 2013
by
Ken Thomases
Committed by
Alexandre Julliard
Feb 25, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winemac: Implement SetCursor() and DestroyCursorIcon().
parent
1896e557
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
766 additions
and
0 deletions
+766
-0
cocoa_app.h
dlls/winemac.drv/cocoa_app.h
+5
-0
cocoa_app.m
dlls/winemac.drv/cocoa_app.m
+142
-0
macdrv.h
dlls/winemac.drv/macdrv.h
+2
-0
macdrv_cocoa.h
dlls/winemac.drv/macdrv_cocoa.h
+4
-0
macdrv_main.c
dlls/winemac.drv/macdrv_main.c
+34
-0
mouse.c
dlls/winemac.drv/mouse.c
+577
-0
winemac.drv.spec
dlls/winemac.drv/winemac.drv.spec
+2
-0
No files found.
dlls/winemac.drv/cocoa_app.h
View file @
a49df4b3
...
@@ -50,6 +50,11 @@
...
@@ -50,6 +50,11 @@
NSMutableArray
*
orderedWineWindows
;
NSMutableArray
*
orderedWineWindows
;
NSMutableDictionary
*
originalDisplayModes
;
NSMutableDictionary
*
originalDisplayModes
;
NSArray
*
cursorFrames
;
int
cursorFrame
;
NSTimer
*
cursorTimer
;
BOOL
cursorHidden
;
}
}
@property
(
nonatomic
)
CGEventSourceKeyboardType
keyboardType
;
@property
(
nonatomic
)
CGEventSourceKeyboardType
keyboardType
;
...
...
dlls/winemac.drv/cocoa_app.m
View file @
a49df4b3
...
@@ -31,6 +31,8 @@ int macdrv_err_on;
...
@@ -31,6 +31,8 @@ int macdrv_err_on;
@interface
WineApplication
()
@interface
WineApplication
()
@property
(
readwrite
,
copy
,
nonatomic
)
NSEvent
*
lastFlagsChanged
;
@property
(
readwrite
,
copy
,
nonatomic
)
NSEvent
*
lastFlagsChanged
;
@property
(
copy
,
nonatomic
)
NSArray
*
cursorFrames
;
@property
(
retain
,
nonatomic
)
NSTimer
*
cursorTimer
;
@end
@end
...
@@ -39,6 +41,7 @@ int macdrv_err_on;
...
@@ -39,6 +41,7 @@ int macdrv_err_on;
@synthesize
keyboardType
,
lastFlagsChanged
;
@synthesize
keyboardType
,
lastFlagsChanged
;
@synthesize
orderedWineWindows
;
@synthesize
orderedWineWindows
;
@synthesize
cursorFrames
,
cursorTimer
;
-
(
id
)
init
-
(
id
)
init
{
{
...
@@ -65,6 +68,8 @@ int macdrv_err_on;
...
@@ -65,6 +68,8 @@ int macdrv_err_on;
-
(
void
)
dealloc
-
(
void
)
dealloc
{
{
[
cursorTimer
release
];
[
cursorFrames
release
];
[
originalDisplayModes
release
];
[
originalDisplayModes
release
];
[
orderedWineWindows
release
];
[
orderedWineWindows
release
];
[
keyWindows
release
];
[
keyWindows
release
];
...
@@ -460,6 +465,89 @@ int macdrv_err_on;
...
@@ -460,6 +465,89 @@ int macdrv_err_on;
return
([
originalDisplayModes
count
]
>
0
);
return
([
originalDisplayModes
count
]
>
0
);
}
}
-
(
void
)
hideCursor
{
if
(
!
cursorHidden
)
{
[
NSCursor
hide
];
cursorHidden
=
TRUE
;
}
}
-
(
void
)
unhideCursor
{
if
(
cursorHidden
)
{
[
NSCursor
unhide
];
cursorHidden
=
FALSE
;
}
}
-
(
void
)
setCursor
{
NSDictionary
*
frame
=
[
cursorFrames
objectAtIndex
:
cursorFrame
];
CGImageRef
cgimage
=
(
CGImageRef
)[
frame
objectForKey
:
@"image"
];
NSImage
*
image
=
[[
NSImage
alloc
]
initWithCGImage
:
cgimage
size
:
NSZeroSize
];
CFDictionaryRef
hotSpotDict
=
(
CFDictionaryRef
)[
frame
objectForKey
:
@"hotSpot"
];
CGPoint
hotSpot
;
NSCursor
*
cursor
;
if
(
!
CGPointMakeWithDictionaryRepresentation
(
hotSpotDict
,
&
hotSpot
))
hotSpot
=
CGPointZero
;
cursor
=
[[
NSCursor
alloc
]
initWithImage
:
image
hotSpot
:
NSPointFromCGPoint
(
hotSpot
)];
[
image
release
];
[
cursor
set
];
[
self
unhideCursor
];
[
cursor
release
];
}
-
(
void
)
nextCursorFrame
:
(
NSTimer
*
)
theTimer
{
NSDictionary
*
frame
;
NSTimeInterval
duration
;
NSDate
*
date
;
cursorFrame
++
;
if
(
cursorFrame
>=
[
cursorFrames
count
])
cursorFrame
=
0
;
[
self
setCursor
];
frame
=
[
cursorFrames
objectAtIndex
:
cursorFrame
];
duration
=
[[
frame
objectForKey
:
@"duration"
]
doubleValue
];
date
=
[[
theTimer
fireDate
]
dateByAddingTimeInterval
:
duration
];
[
cursorTimer
setFireDate
:
date
];
}
-
(
void
)
setCursorWithFrames
:
(
NSArray
*
)
frames
{
if
(
self
.
cursorFrames
==
frames
)
return
;
self
.
cursorFrames
=
frames
;
cursorFrame
=
0
;
[
cursorTimer
invalidate
];
self
.
cursorTimer
=
nil
;
if
([
frames
count
])
{
if
([
frames
count
]
>
1
)
{
NSDictionary
*
frame
=
[
frames
objectAtIndex
:
0
];
NSTimeInterval
duration
=
[[
frame
objectForKey
:
@"duration"
]
doubleValue
];
NSDate
*
date
=
[
NSDate
dateWithTimeIntervalSinceNow
:
duration
];
self
.
cursorTimer
=
[[[
NSTimer
alloc
]
initWithFireDate
:
date
interval
:
1000000
target
:
self
selector
:
@selector
(
nextCursorFrame
:
)
userInfo
:
nil
repeats
:
YES
]
autorelease
];
[[
NSRunLoop
currentRunLoop
]
addTimer
:
cursorTimer
forMode
:
NSRunLoopCommonModes
];
}
[
self
setCursor
];
}
}
/*
/*
* ---------- NSApplication method overrides ----------
* ---------- NSApplication method overrides ----------
...
@@ -673,3 +761,57 @@ int macdrv_set_display_mode(const struct macdrv_display* display,
...
@@ -673,3 +761,57 @@ int macdrv_set_display_mode(const struct macdrv_display* display,
return
ret
;
return
ret
;
}
}
/***********************************************************************
* macdrv_set_cursor
*
* Set the cursor.
*
* If name is non-NULL, it is a selector for a class method on NSCursor
* identifying the cursor to set. In that case, frames is ignored. If
* name is NULL, then frames is used.
*
* frames is an array of dictionaries. Each dictionary is a frame of
* an animated cursor. Under the key "image" is a CGImage for the
* frame. Under the key "duration" is a CFNumber time interval, in
* seconds, for how long that frame is presented before proceeding to
* the next frame. Under the key "hotSpot" is a CFDictionary encoding a
* CGPoint, to be decoded using CGPointMakeWithDictionaryRepresentation().
* This is the hot spot, measured in pixels down and to the right of the
* top-left corner of the image.
*
* If the array has exactly 1 element, the cursor is static, not
* animated. If frames is NULL or has 0 elements, the cursor is hidden.
*/
void
macdrv_set_cursor
(
CFStringRef
name
,
CFArrayRef
frames
)
{
SEL
sel
;
sel
=
NSSelectorFromString
((
NSString
*
)
name
);
if
(
sel
)
{
OnMainThreadAsync
(
^
{
NSCursor
*
cursor
=
[
NSCursor
performSelector
:
sel
];
[
NSApp
setCursorWithFrames
:
nil
];
[
cursor
set
];
[
NSApp
unhideCursor
];
});
}
else
{
NSArray
*
nsframes
=
(
NSArray
*
)
frames
;
if
([
nsframes
count
])
{
OnMainThreadAsync
(
^
{
[
NSApp
setCursorWithFrames
:
nsframes
];
});
}
else
{
OnMainThreadAsync
(
^
{
[
NSApp
setCursorWithFrames
:
nil
];
[
NSApp
hideCursor
];
});
}
}
}
dlls/winemac.drv/macdrv.h
View file @
a49df4b3
...
@@ -35,6 +35,8 @@
...
@@ -35,6 +35,8 @@
#include "wine/gdi_driver.h"
#include "wine/gdi_driver.h"
extern
const
char
*
debugstr_cf
(
CFTypeRef
t
)
DECLSPEC_HIDDEN
;
static
inline
CGRect
cgrect_from_rect
(
RECT
rect
)
static
inline
CGRect
cgrect_from_rect
(
RECT
rect
)
{
{
if
(
rect
.
left
>=
rect
.
right
||
rect
.
top
>=
rect
.
bottom
)
if
(
rect
.
left
>=
rect
.
right
||
rect
.
top
>=
rect
.
bottom
)
...
...
dlls/winemac.drv/macdrv_cocoa.h
View file @
a49df4b3
...
@@ -118,6 +118,10 @@ extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLS
...
@@ -118,6 +118,10 @@ extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLS
extern
void
macdrv_beep
(
void
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_beep
(
void
)
DECLSPEC_HIDDEN
;
/* cursor */
extern
void
macdrv_set_cursor
(
CFStringRef
name
,
CFArrayRef
frames
)
DECLSPEC_HIDDEN
;
/* display */
/* display */
extern
int
macdrv_get_displays
(
struct
macdrv_display
**
displays
,
int
*
count
)
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
;
extern
void
macdrv_free_displays
(
struct
macdrv_display
*
displays
)
DECLSPEC_HIDDEN
;
...
...
dlls/winemac.drv/macdrv_main.c
View file @
a49df4b3
...
@@ -30,6 +30,40 @@ WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
...
@@ -30,6 +30,40 @@ WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
DWORD
thread_data_tls_index
=
TLS_OUT_OF_INDEXES
;
DWORD
thread_data_tls_index
=
TLS_OUT_OF_INDEXES
;
/**************************************************************************
* debugstr_cf
*/
const
char
*
debugstr_cf
(
CFTypeRef
t
)
{
CFStringRef
s
;
const
char
*
ret
;
if
(
!
t
)
return
"(null)"
;
if
(
CFGetTypeID
(
t
)
==
CFStringGetTypeID
())
s
=
t
;
else
s
=
CFCopyDescription
(
t
);
ret
=
CFStringGetCStringPtr
(
s
,
kCFStringEncodingUTF8
);
if
(
ret
)
ret
=
debugstr_a
(
ret
);
if
(
!
ret
)
{
const
UniChar
*
u
=
CFStringGetCharactersPtr
(
s
);
if
(
u
)
ret
=
debugstr_wn
((
const
WCHAR
*
)
u
,
CFStringGetLength
(
s
));
}
if
(
!
ret
)
{
UniChar
buf
[
200
];
int
len
=
min
(
CFStringGetLength
(
s
),
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]));
CFStringGetCharacters
(
s
,
CFRangeMake
(
0
,
len
),
buf
);
ret
=
debugstr_wn
(
buf
,
len
);
}
if
(
s
!=
t
)
CFRelease
(
s
);
return
ret
;
}
/***********************************************************************
/***********************************************************************
* process_attach
* process_attach
*/
*/
...
...
dlls/winemac.drv/mouse.c
View file @
a49df4b3
...
@@ -23,12 +23,27 @@
...
@@ -23,12 +23,27 @@
#include "config.h"
#include "config.h"
#include "macdrv.h"
#include "macdrv.h"
#define OEMRESOURCE
#include "winuser.h"
#include "winuser.h"
#include "winreg.h"
#include "wine/server.h"
#include "wine/server.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
cursor
);
WINE_DEFAULT_DEBUG_CHANNEL
(
cursor
);
static
CRITICAL_SECTION
cursor_cache_section
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
0
,
0
,
&
cursor_cache_section
,
{
&
critsect_debug
.
ProcessLocksList
,
&
critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": cursor_cache_section"
)
}
};
static
CRITICAL_SECTION
cursor_cache_section
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
CFMutableDictionaryRef
cursor_cache
;
/***********************************************************************
/***********************************************************************
* send_mouse_input
* send_mouse_input
*
*
...
@@ -75,6 +90,568 @@ static void send_mouse_input(HWND hwnd, UINT flags, int x, int y,
...
@@ -75,6 +90,568 @@ static void send_mouse_input(HWND hwnd, UINT flags, int x, int y,
/***********************************************************************
/***********************************************************************
* release_provider_cfdata
*
* Helper for create_monochrome_cursor. A CFData is used by two
* different CGDataProviders, using different offsets. One of them is
* constructed with a pointer to the bytes, not a reference to the
* CFData object (because of the offset). So, the CFData is CFRetain'ed
* on its behalf at creation and released here.
*/
void
release_provider_cfdata
(
void
*
info
,
const
void
*
data
,
size_t
size
)
{
CFRelease
(
info
);
}
/***********************************************************************
* create_monochrome_cursor
*/
CFArrayRef
create_monochrome_cursor
(
HDC
hdc
,
const
ICONINFOEXW
*
icon
,
int
width
,
int
height
)
{
char
buffer
[
FIELD_OFFSET
(
BITMAPINFO
,
bmiColors
[
256
])];
BITMAPINFO
*
info
=
(
BITMAPINFO
*
)
buffer
;
unsigned
int
width_bytes
=
(
width
+
31
)
/
32
*
4
;
CGColorSpaceRef
colorspace
;
CFMutableDataRef
data
;
CGDataProviderRef
provider
;
CGImageRef
cgimage
,
cgmask
,
cgmasked
;
CGPoint
hot_spot
;
CFDictionaryRef
hot_spot_dict
;
const
CFStringRef
keys
[]
=
{
CFSTR
(
"image"
),
CFSTR
(
"hotSpot"
)
};
CFTypeRef
values
[
sizeof
(
keys
)
/
sizeof
(
keys
[
0
])];
CFDictionaryRef
frame
;
CFArrayRef
frames
;
TRACE
(
"hdc %p icon->hbmMask %p icon->xHotspot %d icon->yHotspot %d width %d height %d
\n
"
,
hdc
,
icon
->
hbmMask
,
icon
->
xHotspot
,
icon
->
yHotspot
,
width
,
height
);
info
->
bmiHeader
.
biSize
=
sizeof
(
BITMAPINFOHEADER
);
info
->
bmiHeader
.
biWidth
=
width
;
info
->
bmiHeader
.
biHeight
=
-
height
*
2
;
info
->
bmiHeader
.
biPlanes
=
1
;
info
->
bmiHeader
.
biBitCount
=
1
;
info
->
bmiHeader
.
biCompression
=
BI_RGB
;
info
->
bmiHeader
.
biSizeImage
=
width_bytes
*
height
*
2
;
info
->
bmiHeader
.
biXPelsPerMeter
=
0
;
info
->
bmiHeader
.
biYPelsPerMeter
=
0
;
info
->
bmiHeader
.
biClrUsed
=
0
;
info
->
bmiHeader
.
biClrImportant
=
0
;
/* This will be owned by the data provider for the mask image and released
when it is destroyed. */
data
=
CFDataCreateMutable
(
NULL
,
info
->
bmiHeader
.
biSizeImage
);
if
(
!
data
)
{
WARN
(
"failed to create data
\n
"
);
return
NULL
;
}
CFDataSetLength
(
data
,
info
->
bmiHeader
.
biSizeImage
);
if
(
!
GetDIBits
(
hdc
,
icon
->
hbmMask
,
0
,
height
*
2
,
CFDataGetMutableBytePtr
(
data
),
info
,
DIB_RGB_COLORS
))
{
WARN
(
"GetDIBits failed
\n
"
);
CFRelease
(
data
);
return
NULL
;
}
colorspace
=
CGColorSpaceCreateWithName
(
kCGColorSpaceGenericGray
);
if
(
!
colorspace
)
{
WARN
(
"failed to create colorspace
\n
"
);
CFRelease
(
data
);
return
NULL
;
}
/* The data object needs to live as long as this provider, so retain it an
extra time and have the provider's data-release callback release it. */
provider
=
CGDataProviderCreateWithData
(
data
,
CFDataGetBytePtr
(
data
)
+
width_bytes
*
height
,
width_bytes
*
height
,
release_provider_cfdata
);
if
(
!
provider
)
{
WARN
(
"failed to create data provider
\n
"
);
CGColorSpaceRelease
(
colorspace
);
CFRelease
(
data
);
return
NULL
;
}
CFRetain
(
data
);
cgimage
=
CGImageCreate
(
width
,
height
,
1
,
1
,
width_bytes
,
colorspace
,
kCGImageAlphaNone
|
kCGBitmapByteOrderDefault
,
provider
,
NULL
,
FALSE
,
kCGRenderingIntentDefault
);
CGDataProviderRelease
(
provider
);
CGColorSpaceRelease
(
colorspace
);
if
(
!
cgimage
)
{
WARN
(
"failed to create image
\n
"
);
CFRelease
(
data
);
return
NULL
;
}
provider
=
CGDataProviderCreateWithCFData
(
data
);
CFRelease
(
data
);
if
(
!
provider
)
{
WARN
(
"failed to create data provider
\n
"
);
CGImageRelease
(
cgimage
);
return
NULL
;
}
cgmask
=
CGImageMaskCreate
(
width
,
height
,
1
,
1
,
width_bytes
,
provider
,
NULL
,
FALSE
);
CGDataProviderRelease
(
provider
);
if
(
!
cgmask
)
{
WARN
(
"failed to create mask image
\n
"
);
CGImageRelease
(
cgimage
);
return
NULL
;
}
cgmasked
=
CGImageCreateWithMask
(
cgimage
,
cgmask
);
CGImageRelease
(
cgimage
);
CGImageRelease
(
cgmask
);
if
(
!
cgmasked
)
{
WARN
(
"failed to create masked image
\n
"
);
return
NULL
;
}
hot_spot
=
CGPointMake
(
icon
->
xHotspot
,
icon
->
yHotspot
);
hot_spot_dict
=
CGPointCreateDictionaryRepresentation
(
hot_spot
);
if
(
!
hot_spot_dict
)
{
WARN
(
"failed to create hot spot dictionary
\n
"
);
CGImageRelease
(
cgmasked
);
return
NULL
;
}
values
[
0
]
=
cgmasked
;
values
[
1
]
=
hot_spot_dict
;
frame
=
CFDictionaryCreate
(
NULL
,
(
const
void
**
)
keys
,
values
,
sizeof
(
keys
)
/
sizeof
(
keys
[
0
]),
&
kCFCopyStringDictionaryKeyCallBacks
,
&
kCFTypeDictionaryValueCallBacks
);
CFRelease
(
hot_spot_dict
);
CGImageRelease
(
cgmasked
);
if
(
!
frame
)
{
WARN
(
"failed to create frame dictionary
\n
"
);
return
NULL
;
}
frames
=
CFArrayCreate
(
NULL
,
(
const
void
**
)
&
frame
,
1
,
&
kCFTypeArrayCallBacks
);
CFRelease
(
frame
);
if
(
!
frames
)
{
WARN
(
"failed to create frames array
\n
"
);
return
NULL
;
}
return
frames
;
}
/***********************************************************************
* create_cgimage_from_icon
*/
static
CGImageRef
create_cgimage_from_icon
(
HDC
hdc
,
HANDLE
icon
,
HBITMAP
hbmColor
,
unsigned
char
*
color_bits
,
int
color_size
,
HBITMAP
hbmMask
,
unsigned
char
*
mask_bits
,
int
mask_size
,
int
width
,
int
height
,
int
istep
)
{
int
i
,
has_alpha
=
FALSE
;
DWORD
*
ptr
;
CGBitmapInfo
alpha_format
;
CGColorSpaceRef
colorspace
;
CFDataRef
data
;
CGDataProviderRef
provider
;
CGImageRef
cgimage
;
/* draw the cursor frame to a temporary buffer then create a CGImage from that */
memset
(
color_bits
,
0x00
,
color_size
);
SelectObject
(
hdc
,
hbmColor
);
if
(
!
DrawIconEx
(
hdc
,
0
,
0
,
icon
,
width
,
height
,
istep
,
NULL
,
DI_NORMAL
))
{
WARN
(
"Could not draw frame %d (walk past end of frames).
\n
"
,
istep
);
return
NULL
;
}
/* check if the cursor frame was drawn with an alpha channel */
for
(
i
=
0
,
ptr
=
(
DWORD
*
)
color_bits
;
i
<
width
*
height
;
i
++
,
ptr
++
)
if
((
has_alpha
=
(
*
ptr
&
0xff000000
)
!=
0
))
break
;
if
(
has_alpha
)
alpha_format
=
kCGImageAlphaFirst
;
else
alpha_format
=
kCGImageAlphaNoneSkipFirst
;
colorspace
=
CGColorSpaceCreateWithName
(
kCGColorSpaceGenericRGB
);
if
(
!
colorspace
)
{
WARN
(
"failed to create colorspace
\n
"
);
return
NULL
;
}
data
=
CFDataCreate
(
NULL
,
(
UInt8
*
)
color_bits
,
color_size
);
if
(
!
data
)
{
WARN
(
"failed to create data
\n
"
);
CGColorSpaceRelease
(
colorspace
);
return
NULL
;
}
provider
=
CGDataProviderCreateWithCFData
(
data
);
CFRelease
(
data
);
if
(
!
provider
)
{
WARN
(
"failed to create data provider
\n
"
);
CGColorSpaceRelease
(
colorspace
);
return
NULL
;
}
cgimage
=
CGImageCreate
(
width
,
height
,
8
,
32
,
width
*
4
,
colorspace
,
alpha_format
|
kCGBitmapByteOrder32Little
,
provider
,
NULL
,
FALSE
,
kCGRenderingIntentDefault
);
CGDataProviderRelease
(
provider
);
CGColorSpaceRelease
(
colorspace
);
if
(
!
cgimage
)
{
WARN
(
"failed to create image
\n
"
);
return
NULL
;
}
/* if no alpha channel was drawn then generate it from the mask */
if
(
!
has_alpha
)
{
unsigned
int
width_bytes
=
(
width
+
31
)
/
32
*
4
;
CGImageRef
cgmask
,
temp
;
/* draw the cursor mask to a temporary buffer */
memset
(
mask_bits
,
0xFF
,
mask_size
);
SelectObject
(
hdc
,
hbmMask
);
if
(
!
DrawIconEx
(
hdc
,
0
,
0
,
icon
,
width
,
height
,
istep
,
NULL
,
DI_MASK
))
{
WARN
(
"Failed to draw frame mask %d.
\n
"
,
istep
);
CGImageRelease
(
cgimage
);
return
NULL
;
}
data
=
CFDataCreate
(
NULL
,
(
UInt8
*
)
mask_bits
,
mask_size
);
if
(
!
data
)
{
WARN
(
"failed to create data
\n
"
);
CGImageRelease
(
cgimage
);
return
NULL
;
}
provider
=
CGDataProviderCreateWithCFData
(
data
);
CFRelease
(
data
);
if
(
!
provider
)
{
WARN
(
"failed to create data provider
\n
"
);
CGImageRelease
(
cgimage
);
return
NULL
;
}
cgmask
=
CGImageMaskCreate
(
width
,
height
,
1
,
1
,
width_bytes
,
provider
,
NULL
,
FALSE
);
CGDataProviderRelease
(
provider
);
if
(
!
cgmask
)
{
WARN
(
"failed to create mask
\n
"
);
CGImageRelease
(
cgimage
);
return
NULL
;
}
temp
=
CGImageCreateWithMask
(
cgimage
,
cgmask
);
CGImageRelease
(
cgmask
);
CGImageRelease
(
cgimage
);
if
(
!
temp
)
{
WARN
(
"failed to create masked image
\n
"
);
return
NULL
;
}
cgimage
=
temp
;
}
return
cgimage
;
}
/***********************************************************************
* create_cursor_frame
*
* Create a frame dictionary for a cursor from a Windows icon.
* Keys:
* "image" a CGImage for the frame
* "duration" a CFNumber for the frame duration in seconds
* "hotSpot" a CFDictionary encoding a CGPoint for the hot spot
*/
static
CFDictionaryRef
create_cursor_frame
(
HDC
hdc
,
const
ICONINFOEXW
*
iinfo
,
HANDLE
icon
,
HBITMAP
hbmColor
,
unsigned
char
*
color_bits
,
int
color_size
,
HBITMAP
hbmMask
,
unsigned
char
*
mask_bits
,
int
mask_size
,
int
width
,
int
height
,
int
istep
)
{
DWORD
delay_jiffies
,
num_steps
;
CFMutableDictionaryRef
frame
;
CGPoint
hot_spot
;
CFDictionaryRef
hot_spot_dict
;
double
duration
;
CFNumberRef
duration_number
;
CGImageRef
cgimage
;
TRACE
(
"hdc %p iinfo->xHotspot %d iinfo->yHotspot %d icon %p hbmColor %p color_bits %p color_size %d"
" hbmMask %p mask_bits %p mask_size %d width %d height %d istep %d
\n
"
,
hdc
,
iinfo
->
xHotspot
,
iinfo
->
yHotspot
,
icon
,
hbmColor
,
color_bits
,
color_size
,
hbmMask
,
mask_bits
,
mask_size
,
width
,
height
,
istep
);
frame
=
CFDictionaryCreateMutable
(
NULL
,
0
,
&
kCFCopyStringDictionaryKeyCallBacks
,
&
kCFTypeDictionaryValueCallBacks
);
if
(
!
frame
)
{
WARN
(
"failed to allocate dictionary for frame
\n
"
);
return
NULL
;
}
hot_spot
=
CGPointMake
(
iinfo
->
xHotspot
,
iinfo
->
yHotspot
);
hot_spot_dict
=
CGPointCreateDictionaryRepresentation
(
hot_spot
);
if
(
!
hot_spot_dict
)
{
WARN
(
"failed to create hot spot dictionary
\n
"
);
CFRelease
(
frame
);
return
NULL
;
}
CFDictionarySetValue
(
frame
,
CFSTR
(
"hotSpot"
),
hot_spot_dict
);
CFRelease
(
hot_spot_dict
);
if
(
GetCursorFrameInfo
(
icon
,
0x0
/* unknown parameter */
,
istep
,
&
delay_jiffies
,
&
num_steps
)
!=
0
)
duration
=
delay_jiffies
/
60
.
0
;
/* convert jiffies (1/60s) to seconds */
else
{
WARN
(
"Failed to retrieve animated cursor frame-rate for frame %d.
\n
"
,
istep
);
duration
=
0
.
1
;
/* fallback delay, 100 ms */
}
duration_number
=
CFNumberCreate
(
NULL
,
kCFNumberDoubleType
,
&
duration
);
if
(
!
duration_number
)
{
WARN
(
"failed to create duration number
\n
"
);
CFRelease
(
frame
);
return
NULL
;
}
CFDictionarySetValue
(
frame
,
CFSTR
(
"duration"
),
duration_number
);
CFRelease
(
duration_number
);
cgimage
=
create_cgimage_from_icon
(
hdc
,
icon
,
hbmColor
,
color_bits
,
color_size
,
hbmMask
,
mask_bits
,
mask_size
,
width
,
height
,
istep
);
if
(
!
cgimage
)
{
CFRelease
(
frame
);
return
NULL
;
}
CFDictionarySetValue
(
frame
,
CFSTR
(
"image"
),
cgimage
);
CGImageRelease
(
cgimage
);
return
frame
;
}
/***********************************************************************
* create_color_cursor
*
* Create an array of color cursor frames from a Windows cursor. Each
* frame is represented in the array by a dictionary.
* Frame dictionary keys:
* "image" a CGImage for the frame
* "duration" a CFNumber for the frame duration in seconds
* "hotSpot" a CFDictionary encoding a CGPoint for the hot spot
*/
static
CFArrayRef
create_color_cursor
(
HDC
hdc
,
const
ICONINFOEXW
*
iinfo
,
HANDLE
icon
,
int
width
,
int
height
)
{
unsigned
char
*
color_bits
,
*
mask_bits
;
HBITMAP
hbmColor
=
0
,
hbmMask
=
0
;
DWORD
nFrames
,
delay_jiffies
,
i
;
int
color_size
,
mask_size
;
BITMAPINFO
*
info
=
NULL
;
CFMutableArrayRef
frames
;
TRACE
(
"hdc %p iinfo %p icon %p width %d height %d
\n
"
,
hdc
,
iinfo
,
icon
,
width
,
height
);
/* Retrieve the number of frames to render */
if
(
!
GetCursorFrameInfo
(
icon
,
0x0
/* unknown parameter */
,
0
,
&
delay_jiffies
,
&
nFrames
))
{
WARN
(
"GetCursorFrameInfo failed
\n
"
);
return
NULL
;
}
if
(
!
(
frames
=
CFArrayCreateMutable
(
NULL
,
nFrames
,
&
kCFTypeArrayCallBacks
)))
{
WARN
(
"failed to allocate frames array
\n
"
);
return
NULL
;
}
/* Allocate all of the resources necessary to obtain a cursor frame */
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
FIELD_OFFSET
(
BITMAPINFO
,
bmiColors
[
256
]))))
goto
cleanup
;
info
->
bmiHeader
.
biSize
=
sizeof
(
BITMAPINFOHEADER
);
info
->
bmiHeader
.
biWidth
=
width
;
info
->
bmiHeader
.
biHeight
=
-
height
;
info
->
bmiHeader
.
biPlanes
=
1
;
info
->
bmiHeader
.
biCompression
=
BI_RGB
;
info
->
bmiHeader
.
biXPelsPerMeter
=
0
;
info
->
bmiHeader
.
biYPelsPerMeter
=
0
;
info
->
bmiHeader
.
biClrUsed
=
0
;
info
->
bmiHeader
.
biClrImportant
=
0
;
info
->
bmiHeader
.
biBitCount
=
32
;
color_size
=
width
*
height
*
4
;
info
->
bmiHeader
.
biSizeImage
=
color_size
;
hbmColor
=
CreateDIBSection
(
hdc
,
info
,
DIB_RGB_COLORS
,
(
VOID
**
)
&
color_bits
,
NULL
,
0
);
if
(
!
hbmColor
)
{
WARN
(
"failed to create DIB section for cursor color data
\n
"
);
goto
cleanup
;
}
info
->
bmiHeader
.
biBitCount
=
1
;
info
->
bmiColors
[
0
].
rgbRed
=
0
;
info
->
bmiColors
[
0
].
rgbGreen
=
0
;
info
->
bmiColors
[
0
].
rgbBlue
=
0
;
info
->
bmiColors
[
0
].
rgbReserved
=
0
;
info
->
bmiColors
[
1
].
rgbRed
=
0xff
;
info
->
bmiColors
[
1
].
rgbGreen
=
0xff
;
info
->
bmiColors
[
1
].
rgbBlue
=
0xff
;
info
->
bmiColors
[
1
].
rgbReserved
=
0
;
mask_size
=
((
width
+
31
)
/
32
*
4
)
*
height
;
/* width_bytes * height */
info
->
bmiHeader
.
biSizeImage
=
mask_size
;
hbmMask
=
CreateDIBSection
(
hdc
,
info
,
DIB_RGB_COLORS
,
(
VOID
**
)
&
mask_bits
,
NULL
,
0
);
if
(
!
hbmMask
)
{
WARN
(
"failed to create DIB section for cursor mask data
\n
"
);
goto
cleanup
;
}
/* Create a CFDictionary for each frame of the cursor */
for
(
i
=
0
;
i
<
nFrames
;
i
++
)
{
CFDictionaryRef
frame
=
create_cursor_frame
(
hdc
,
iinfo
,
icon
,
hbmColor
,
color_bits
,
color_size
,
hbmMask
,
mask_bits
,
mask_size
,
width
,
height
,
i
);
if
(
!
frame
)
goto
cleanup
;
CFArrayAppendValue
(
frames
,
frame
);
CFRelease
(
frame
);
}
cleanup:
if
(
CFArrayGetCount
(
frames
)
<
nFrames
)
{
CFRelease
(
frames
);
frames
=
NULL
;
}
else
TRACE
(
"returning cursor with %d frames
\n
"
,
nFrames
);
/* Cleanup all of the resources used to obtain the frame data */
if
(
hbmColor
)
DeleteObject
(
hbmColor
);
if
(
hbmMask
)
DeleteObject
(
hbmMask
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
return
frames
;
}
/***********************************************************************
* DestroyCursorIcon (MACDRV.@)
*/
void
CDECL
macdrv_DestroyCursorIcon
(
HCURSOR
cursor
)
{
TRACE
(
"cursor %p
\n
"
,
cursor
);
EnterCriticalSection
(
&
cursor_cache_section
);
if
(
cursor_cache
)
CFDictionaryRemoveValue
(
cursor_cache
,
cursor
);
LeaveCriticalSection
(
&
cursor_cache_section
);
}
/***********************************************************************
* SetCursor (MACDRV.@)
*/
void
CDECL
macdrv_SetCursor
(
HCURSOR
cursor
)
{
CFStringRef
cursor_name
=
NULL
;
CFArrayRef
cursor_frames
=
NULL
;
TRACE
(
"%p
\n
"
,
cursor
);
if
(
cursor
)
{
ICONINFOEXW
info
;
BITMAP
bm
;
HDC
hdc
;
EnterCriticalSection
(
&
cursor_cache_section
);
if
(
cursor_cache
)
{
CFTypeRef
cached_cursor
=
CFDictionaryGetValue
(
cursor_cache
,
cursor
);
if
(
cached_cursor
)
{
if
(
CFGetTypeID
(
cached_cursor
)
==
CFStringGetTypeID
())
cursor_name
=
CFRetain
(
cached_cursor
);
else
cursor_frames
=
CFRetain
(
cached_cursor
);
}
}
LeaveCriticalSection
(
&
cursor_cache_section
);
if
(
cursor_name
||
cursor_frames
)
goto
done
;
info
.
cbSize
=
sizeof
(
info
);
if
(
!
GetIconInfoExW
(
cursor
,
&
info
))
{
WARN
(
"GetIconInfoExW failed
\n
"
);
return
;
}
GetObjectW
(
info
.
hbmMask
,
sizeof
(
bm
),
&
bm
);
if
(
!
info
.
hbmColor
)
bm
.
bmHeight
=
max
(
1
,
bm
.
bmHeight
/
2
);
/* make sure hotspot is valid */
if
(
info
.
xHotspot
>=
bm
.
bmWidth
||
info
.
yHotspot
>=
bm
.
bmHeight
)
{
info
.
xHotspot
=
bm
.
bmWidth
/
2
;
info
.
yHotspot
=
bm
.
bmHeight
/
2
;
}
hdc
=
CreateCompatibleDC
(
0
);
if
(
info
.
hbmColor
)
{
cursor_frames
=
create_color_cursor
(
hdc
,
&
info
,
cursor
,
bm
.
bmWidth
,
bm
.
bmHeight
);
DeleteObject
(
info
.
hbmColor
);
}
else
cursor_frames
=
create_monochrome_cursor
(
hdc
,
&
info
,
bm
.
bmWidth
,
bm
.
bmHeight
);
DeleteObject
(
info
.
hbmMask
);
DeleteDC
(
hdc
);
if
(
cursor_name
||
cursor_frames
)
{
EnterCriticalSection
(
&
cursor_cache_section
);
if
(
!
cursor_cache
)
cursor_cache
=
CFDictionaryCreateMutable
(
NULL
,
0
,
NULL
,
&
kCFTypeDictionaryValueCallBacks
);
CFDictionarySetValue
(
cursor_cache
,
cursor
,
cursor_name
?
(
CFTypeRef
)
cursor_name
:
(
CFTypeRef
)
cursor_frames
);
LeaveCriticalSection
(
&
cursor_cache_section
);
}
else
cursor_name
=
CFRetain
(
CFSTR
(
"arrowCursor"
));
}
done:
TRACE
(
"setting cursor with cursor_name %s cursor_frames %p
\n
"
,
debugstr_cf
(
cursor_name
),
cursor_frames
);
macdrv_set_cursor
(
cursor_name
,
cursor_frames
);
if
(
cursor_name
)
CFRelease
(
cursor_name
);
if
(
cursor_frames
)
CFRelease
(
cursor_frames
);
}
/***********************************************************************
* macdrv_mouse_button
* macdrv_mouse_button
*
*
* Handler for MOUSE_BUTTON events.
* Handler for MOUSE_BUTTON events.
...
...
dlls/winemac.drv/winemac.drv.spec
View file @
a49df4b3
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
@ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) macdrv_ChangeDisplaySettingsEx
@ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) macdrv_ChangeDisplaySettingsEx
@ cdecl CreateDesktopWindow(long) macdrv_CreateDesktopWindow
@ cdecl CreateDesktopWindow(long) macdrv_CreateDesktopWindow
@ cdecl CreateWindow(long) macdrv_CreateWindow
@ cdecl CreateWindow(long) macdrv_CreateWindow
@ cdecl DestroyCursorIcon(long) macdrv_DestroyCursorIcon
@ cdecl DestroyWindow(long) macdrv_DestroyWindow
@ cdecl DestroyWindow(long) macdrv_DestroyWindow
@ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
@ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
@ cdecl EnumDisplaySettingsEx(ptr long ptr long) macdrv_EnumDisplaySettingsEx
@ cdecl EnumDisplaySettingsEx(ptr long ptr long) macdrv_EnumDisplaySettingsEx
...
@@ -19,6 +20,7 @@
...
@@ -19,6 +20,7 @@
@ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx
@ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx
@ cdecl ScrollDC(long long long ptr ptr long ptr) macdrv_ScrollDC
@ cdecl ScrollDC(long long long ptr ptr long ptr) macdrv_ScrollDC
@ cdecl SetCursor(long) macdrv_SetCursor
@ cdecl SetFocus(long) macdrv_SetFocus
@ cdecl SetFocus(long) macdrv_SetFocus
@ cdecl SetLayeredWindowAttributes(long long long long) macdrv_SetLayeredWindowAttributes
@ cdecl SetLayeredWindowAttributes(long long long long) macdrv_SetLayeredWindowAttributes
@ cdecl SetParent(long long long) macdrv_SetParent
@ cdecl SetParent(long long long) macdrv_SetParent
...
...
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