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
fd1e187a
Commit
fd1e187a
authored
Apr 03, 2013
by
Ken Thomases
Committed by
Alexandre Julliard
Apr 04, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winemac: Handle a Cocoa quit request as a single-process session shutdown.
This lets programs ask the user to save documents, etc., and possibly cancel the quit.
parent
ca2d7140
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
240 additions
and
1 deletion
+240
-1
cocoa_app.m
dlls/winemac.drv/cocoa_app.m
+53
-0
event.c
dlls/winemac.drv/event.c
+7
-1
macdrv.h
dlls/winemac.drv/macdrv.h
+1
-0
macdrv_cocoa.h
dlls/winemac.drv/macdrv_cocoa.h
+12
-0
window.c
dlls/winemac.drv/window.c
+167
-0
No files found.
dlls/winemac.drv/cocoa_app.m
View file @
fd1e187a
...
...
@@ -1206,6 +1206,49 @@ int macdrv_err_on;
macdrv_release_event
(
event
);
}
-
(
NSApplicationTerminateReply
)
applicationShouldTerminate
:
(
NSApplication
*
)
sender
{
NSApplicationTerminateReply
ret
=
NSTerminateNow
;
NSAppleEventManager
*
m
=
[
NSAppleEventManager
sharedAppleEventManager
];
NSAppleEventDescriptor
*
desc
=
[
m
currentAppleEvent
];
macdrv_event
*
event
;
WineEventQueue
*
queue
;
event
=
macdrv_create_event
(
APP_QUIT_REQUESTED
,
nil
);
event
->
deliver
=
1
;
switch
([[
desc
attributeDescriptorForKeyword
:
kAEQuitReason
]
int32Value
])
{
case
kAELogOut
:
case
kAEReallyLogOut
:
event
->
app_quit_requested
.
reason
=
QUIT_REASON_LOGOUT
;
break
;
case
kAEShowRestartDialog
:
event
->
app_quit_requested
.
reason
=
QUIT_REASON_RESTART
;
break
;
case
kAEShowShutdownDialog
:
event
->
app_quit_requested
.
reason
=
QUIT_REASON_SHUTDOWN
;
break
;
default
:
event
->
app_quit_requested
.
reason
=
QUIT_REASON_NONE
;
break
;
}
[
eventQueuesLock
lock
];
if
([
eventQueues
count
])
{
for
(
queue
in
eventQueues
)
[
queue
postEvent
:
event
];
ret
=
NSTerminateLater
;
}
[
eventQueuesLock
unlock
];
macdrv_release_event
(
event
);
return
ret
;
}
-
(
void
)
applicationWillFinishLaunching
:
(
NSNotification
*
)
notification
{
NSNotificationCenter
*
nc
=
[
NSNotificationCenter
defaultCenter
];
...
...
@@ -1541,3 +1584,13 @@ void macdrv_set_application_icon(CFArrayRef images)
[
NSApp
setApplicationIconFromCGImageArray
:
imageArray
];
});
}
/***********************************************************************
* macdrv_quit_reply
*/
void
macdrv_quit_reply
(
int
reply
)
{
OnMainThread
(
^
{
[
NSApp
replyToApplicationShouldTerminate
:
reply
];
});
}
dlls/winemac.drv/event.c
View file @
fd1e187a
...
...
@@ -33,6 +33,7 @@ static const char *dbgstr_event(int type)
{
static
const
char
*
const
event_names
[]
=
{
"APP_DEACTIVATED"
,
"APP_QUIT_REQUESTED"
,
"DISPLAYS_CHANGED"
,
"KEY_PRESS"
,
"KEY_RELEASE"
,
...
...
@@ -87,6 +88,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
if
(
mask
&
QS_POSTMESSAGE
)
{
event_mask
|=
event_mask_for_type
(
APP_DEACTIVATED
);
event_mask
|=
event_mask_for_type
(
APP_QUIT_REQUESTED
);
event_mask
|=
event_mask_for_type
(
DISPLAYS_CHANGED
);
event_mask
|=
event_mask_for_type
(
STATUS_ITEM_CLICKED
);
event_mask
|=
event_mask_for_type
(
WINDOW_CLOSE_REQUESTED
);
...
...
@@ -165,6 +167,9 @@ void macdrv_handle_event(const macdrv_event *event)
case
APP_DEACTIVATED
:
macdrv_app_deactivated
();
break
;
case
APP_QUIT_REQUESTED
:
macdrv_app_quit_requested
(
event
);
break
;
case
DISPLAYS_CHANGED
:
macdrv_displays_changed
(
event
);
break
;
...
...
@@ -257,7 +262,8 @@ DWORD CDECL macdrv_MsgWaitForMultipleObjectsEx(DWORD count, const HANDLE *handle
timeout
,
flags
&
MWMO_ALERTABLE
);
}
if
(
data
->
current_event
&&
data
->
current_event
->
type
!=
QUERY_EVENT
)
if
(
data
->
current_event
&&
data
->
current_event
->
type
!=
QUERY_EVENT
&&
data
->
current_event
->
type
!=
APP_QUIT_REQUESTED
)
event_mask
=
0
;
/* don't process nested events */
if
(
process_events
(
data
->
queue
,
event_mask
))
ret
=
count
-
1
;
...
...
dlls/winemac.drv/macdrv.h
View file @
fd1e187a
...
...
@@ -149,6 +149,7 @@ extern void macdrv_window_frame_changed(HWND hwnd, CGRect frame) DECLSPEC_HIDDEN
extern
void
macdrv_window_got_focus
(
HWND
hwnd
,
const
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_window_lost_focus
(
HWND
hwnd
,
const
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_app_deactivated
(
void
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_app_quit_requested
(
const
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_window_did_minimize
(
HWND
hwnd
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_window_did_unminimize
(
HWND
hwnd
)
DECLSPEC_HIDDEN
;
...
...
dlls/winemac.drv/macdrv_cocoa.h
View file @
fd1e187a
...
...
@@ -134,6 +134,7 @@ extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
extern
void
macdrv_window_rejected_focus
(
const
struct
macdrv_event
*
event
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_beep
(
void
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_set_application_icon
(
CFArrayRef
images
)
DECLSPEC_HIDDEN
;
extern
void
macdrv_quit_reply
(
int
reply
)
DECLSPEC_HIDDEN
;
/* cursor */
...
...
@@ -153,6 +154,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
/* event */
enum
{
APP_DEACTIVATED
,
APP_QUIT_REQUESTED
,
DISPLAYS_CHANGED
,
KEY_PRESS
,
KEY_RELEASE
,
...
...
@@ -172,6 +174,13 @@ enum {
NUM_EVENT_TYPES
};
enum
{
QUIT_REASON_NONE
,
QUIT_REASON_LOGOUT
,
QUIT_REASON_RESTART
,
QUIT_REASON_SHUTDOWN
,
};
typedef
uint32_t
macdrv_event_mask
;
typedef
struct
macdrv_event
{
...
...
@@ -181,6 +190,9 @@ typedef struct macdrv_event {
macdrv_window
window
;
union
{
struct
{
int
reason
;
}
app_quit_requested
;
struct
{
int
activating
;
}
displays_changed
;
struct
{
...
...
dlls/winemac.drv/window.c
View file @
fd1e187a
...
...
@@ -1637,3 +1637,170 @@ void macdrv_window_did_unminimize(HWND hwnd)
done:
release_win_data
(
data
);
}
struct
quit_info
{
HWND
*
wins
;
UINT
capacity
;
UINT
count
;
UINT
done
;
DWORD
flags
;
BOOL
result
;
BOOL
replied
;
};
static
BOOL
CALLBACK
get_process_windows
(
HWND
hwnd
,
LPARAM
lp
)
{
struct
quit_info
*
qi
=
(
struct
quit_info
*
)
lp
;
DWORD
pid
;
GetWindowThreadProcessId
(
hwnd
,
&
pid
);
if
(
pid
==
GetCurrentProcessId
())
{
if
(
qi
->
count
>=
qi
->
capacity
)
{
UINT
new_cap
=
qi
->
capacity
*
2
;
HWND
*
new_wins
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
qi
->
wins
,
new_cap
*
sizeof
(
*
qi
->
wins
));
if
(
!
new_wins
)
return
FALSE
;
qi
->
wins
=
new_wins
;
qi
->
capacity
=
new_cap
;
}
qi
->
wins
[
qi
->
count
++
]
=
hwnd
;
}
return
TRUE
;
}
static
void
CALLBACK
quit_callback
(
HWND
hwnd
,
UINT
msg
,
ULONG_PTR
data
,
LRESULT
result
)
{
struct
quit_info
*
qi
=
(
struct
quit_info
*
)
data
;
qi
->
done
++
;
if
(
msg
==
WM_QUERYENDSESSION
)
{
TRACE
(
"got WM_QUERYENDSESSION result %ld from win %p (%u of %u done)
\n
"
,
result
,
hwnd
,
qi
->
done
,
qi
->
count
);
if
(
!
result
&&
qi
->
result
)
{
qi
->
result
=
FALSE
;
/* On the first FALSE from WM_QUERYENDSESSION, we already know the
ultimate reply. Might as well tell Cocoa now. */
if
(
!
qi
->
replied
)
{
qi
->
replied
=
TRUE
;
TRACE
(
"giving quit reply %d
\n
"
,
qi
->
result
);
macdrv_quit_reply
(
qi
->
result
);
}
}
if
(
qi
->
done
>=
qi
->
count
)
{
UINT
i
;
qi
->
done
=
0
;
for
(
i
=
0
;
i
<
qi
->
count
;
i
++
)
{
TRACE
(
"sending WM_ENDSESSION to win %p result %d flags 0x%08x
\n
"
,
qi
->
wins
[
i
],
qi
->
result
,
qi
->
flags
);
if
(
!
SendMessageCallbackW
(
qi
->
wins
[
i
],
WM_ENDSESSION
,
qi
->
result
,
qi
->
flags
,
quit_callback
,
(
ULONG_PTR
)
qi
))
{
WARN
(
"failed to send WM_ENDSESSION to win %p; error 0x%08x
\n
"
,
qi
->
wins
[
i
],
GetLastError
());
quit_callback
(
qi
->
wins
[
i
],
WM_ENDSESSION
,
(
ULONG_PTR
)
qi
,
0
);
}
}
}
}
else
/* WM_ENDSESSION */
{
TRACE
(
"finished WM_ENDSESSION for win %p (%u of %u done)
\n
"
,
hwnd
,
qi
->
done
,
qi
->
count
);
if
(
qi
->
done
>=
qi
->
count
)
{
if
(
!
qi
->
replied
)
{
TRACE
(
"giving quit reply %d
\n
"
,
qi
->
result
);
macdrv_quit_reply
(
qi
->
result
);
}
TRACE
(
"%sterminating process
\n
"
,
qi
->
result
?
""
:
"not "
);
if
(
qi
->
result
)
TerminateProcess
(
GetCurrentProcess
(),
0
);
HeapFree
(
GetProcessHeap
(),
0
,
qi
->
wins
);
HeapFree
(
GetProcessHeap
(),
0
,
qi
);
}
}
}
/***********************************************************************
* macdrv_app_quit_requested
*
* Handler for APP_QUIT_REQUESTED events.
*/
void
macdrv_app_quit_requested
(
const
macdrv_event
*
event
)
{
struct
quit_info
*
qi
;
UINT
i
;
TRACE
(
"reason %d
\n
"
,
event
->
app_quit_requested
.
reason
);
qi
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
qi
));
if
(
!
qi
)
goto
fail
;
qi
->
capacity
=
32
;
qi
->
wins
=
HeapAlloc
(
GetProcessHeap
(),
0
,
qi
->
capacity
*
sizeof
(
*
qi
->
wins
));
qi
->
count
=
qi
->
done
=
0
;
if
(
!
qi
->
wins
||
!
EnumWindows
(
get_process_windows
,
(
LPARAM
)
qi
))
goto
fail
;
switch
(
event
->
app_quit_requested
.
reason
)
{
case
QUIT_REASON_LOGOUT
:
default:
qi
->
flags
=
ENDSESSION_LOGOFF
;
break
;
case
QUIT_REASON_RESTART
:
case
QUIT_REASON_SHUTDOWN
:
qi
->
flags
=
0
;
break
;
}
qi
->
result
=
TRUE
;
qi
->
replied
=
FALSE
;
for
(
i
=
0
;
i
<
qi
->
count
;
i
++
)
{
TRACE
(
"sending WM_QUERYENDSESSION to win %p
\n
"
,
qi
->
wins
[
i
]);
if
(
!
SendMessageCallbackW
(
qi
->
wins
[
i
],
WM_QUERYENDSESSION
,
0
,
qi
->
flags
,
quit_callback
,
(
ULONG_PTR
)
qi
))
{
WARN
(
"failed to send WM_QUERYENDSESSION to win %p; error 0x%08x; assuming refusal
\n
"
,
qi
->
wins
[
i
],
GetLastError
());
quit_callback
(
qi
->
wins
[
i
],
WM_QUERYENDSESSION
,
(
ULONG_PTR
)
qi
,
FALSE
);
}
}
/* quit_callback() will clean up qi */
return
;
fail:
WARN
(
"failed to allocate window list
\n
"
);
if
(
qi
)
{
HeapFree
(
GetProcessHeap
(),
0
,
qi
->
wins
);
HeapFree
(
GetProcessHeap
(),
0
,
qi
);
}
macdrv_quit_reply
(
FALSE
);
}
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