[iOS] Keyups for non-modifier keys identified as "Dead" when not focused in a content...
[WebKit-https.git] / Source / WebCore / platform / ios / RemoteCommandListenerIOS.mm
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "config.h"
27 #import "RemoteCommandListenerIOS.h"
28
29 #if PLATFORM(IOS_FAMILY) && HAVE(MEDIA_PLAYER)
30
31 #import <MediaPlayer/MPRemoteCommand.h>
32 #import <MediaPlayer/MPRemoteCommandCenter.h>
33 #import <MediaPlayer/MPRemoteCommandEvent.h>
34 #import <wtf/SoftLinking.h>
35
36 SOFT_LINK_FRAMEWORK_OPTIONAL(MediaPlayer)
37 SOFT_LINK_CLASS(MediaPlayer, MPRemoteCommandCenter)
38 SOFT_LINK_CLASS(MediaPlayer, MPSeekCommandEvent)
39 SOFT_LINK_CLASS(MediaPlayer, MPChangePlaybackPositionCommandEvent)
40
41 namespace WebCore {
42
43 std::unique_ptr<RemoteCommandListener> RemoteCommandListener::create(RemoteCommandListenerClient& client)
44 {
45     if (!MediaPlayerLibrary())
46         return nullptr;
47
48     return std::make_unique<RemoteCommandListenerIOS>(client);
49 }
50
51 RemoteCommandListenerIOS::RemoteCommandListenerIOS(RemoteCommandListenerClient& client)
52     : RemoteCommandListener(client)
53 {
54     MPRemoteCommandCenter *center = [getMPRemoteCommandCenterClass() sharedCommandCenter];
55     auto weakThis = makeWeakPtr(*this);
56     
57     m_pauseTarget = [[center pauseCommand] addTargetWithHandler:^(MPRemoteCommandEvent *) {
58         callOnMainThread([weakThis] {
59             if (!weakThis)
60                 return;
61             weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::PauseCommand, nullptr);
62         });
63
64         return MPRemoteCommandHandlerStatusSuccess;
65     }];
66
67     m_playTarget = [[center playCommand] addTargetWithHandler:^(MPRemoteCommandEvent *) {
68         callOnMainThread([weakThis] {
69             if (!weakThis)
70                 return;
71             weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::PlayCommand, nullptr);
72         });
73
74         return MPRemoteCommandHandlerStatusSuccess;
75     }];
76
77     m_togglePlayPauseTarget = [[center togglePlayPauseCommand] addTargetWithHandler:^(MPRemoteCommandEvent *) {
78         callOnMainThread([weakThis] {
79             if (!weakThis)
80                 return;
81             weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::TogglePlayPauseCommand, nullptr);
82         });
83
84         return MPRemoteCommandHandlerStatusSuccess;
85     }];
86
87     m_seekBackwardTarget = [[center seekBackwardCommand] addTargetWithHandler:^(MPRemoteCommandEvent *event) {
88         ASSERT([event isKindOfClass:getMPSeekCommandEventClass()]);
89
90         MPSeekCommandEvent* seekEvent = static_cast<MPSeekCommandEvent *>(event);
91         PlatformMediaSession::RemoteControlCommandType command = [seekEvent type] == MPSeekCommandEventTypeBeginSeeking ? PlatformMediaSession::BeginSeekingBackwardCommand : PlatformMediaSession::EndSeekingBackwardCommand;
92
93         callOnMainThread([weakThis, command] {
94             if (!weakThis)
95                 return;
96             weakThis->m_client.didReceiveRemoteControlCommand(command, nullptr);
97         });
98
99         return MPRemoteCommandHandlerStatusSuccess;
100     }];
101     
102     m_seekForwardTarget = [[center seekForwardCommand] addTargetWithHandler:^(MPRemoteCommandEvent *event) {
103         ASSERT([event isKindOfClass:getMPSeekCommandEventClass()]);
104         MPSeekCommandEvent* seekEvent = static_cast<MPSeekCommandEvent *>(event);
105
106         PlatformMediaSession::RemoteControlCommandType command = [seekEvent type] == MPSeekCommandEventTypeBeginSeeking ? PlatformMediaSession::BeginSeekingForwardCommand : PlatformMediaSession::EndSeekingForwardCommand;
107
108         callOnMainThread([weakThis, command] {
109             if (!weakThis)
110                 return;
111             weakThis->m_client.didReceiveRemoteControlCommand(command, nullptr);
112         });
113
114         return MPRemoteCommandHandlerStatusSuccess;
115     }];
116
117     m_seekToTimeTarget = [[center changePlaybackPositionCommand] addTargetWithHandler:^(MPRemoteCommandEvent *event) {
118         ASSERT([event isKindOfClass:getMPChangePlaybackPositionCommandEventClass()]);
119
120         if (!client.supportsSeeking())
121             return MPRemoteCommandHandlerStatusCommandFailed;
122
123         MPChangePlaybackPositionCommandEvent* seekEvent = static_cast<MPChangePlaybackPositionCommandEvent *>(event);
124         PlatformMediaSession::RemoteCommandArgument argument { [seekEvent positionTime] };
125
126         callOnMainThread([weakThis, argument] {
127             if (!weakThis)
128                 return;
129             weakThis->m_client.didReceiveRemoteControlCommand(PlatformMediaSession::SeekToPlaybackPositionCommand, &argument);
130         });
131
132         return MPRemoteCommandHandlerStatusSuccess;
133     }];
134 }
135
136 RemoteCommandListenerIOS::~RemoteCommandListenerIOS()
137 {
138     MPRemoteCommandCenter *center = [getMPRemoteCommandCenterClass() sharedCommandCenter];
139     [[center pauseCommand] removeTarget:m_pauseTarget.get()];
140     [[center playCommand] removeTarget:m_playTarget.get()];
141     [[center togglePlayPauseCommand] removeTarget:m_togglePlayPauseTarget.get()];
142     [[center seekForwardCommand] removeTarget:m_seekForwardTarget.get()];
143     [[center seekBackwardCommand] removeTarget:m_seekBackwardTarget.get()];
144     [[center changePlaybackPositionCommand] removeTarget:m_seekToTimeTarget.get()];
145 }
146
147 void RemoteCommandListenerIOS::updateSupportedCommands()
148 {
149     [[[getMPRemoteCommandCenterClass() sharedCommandCenter] changePlaybackPositionCommand] setEnabled:!!client().supportsSeeking()];
150 }
151
152 }
153
154 #endif // PLATFORM(IOS_FAMILY) && HAVE(MEDIA_PLAYER)