-
Notifications
You must be signed in to change notification settings - Fork 447
Take focus from game during calls on iOS #6462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 5 commits
46d6b1a
38c18b0
bd67090
e646976
1b8ec31
03934bc
dd0f362
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using System; | ||
using System.Linq; | ||
using CallKit; | ||
using Foundation; | ||
|
||
namespace osu.Framework.iOS | ||
{ | ||
internal class IOSCallObserver : NSObject, ICXCallObserverDelegate | ||
{ | ||
public event Action? OnCall; | ||
public event Action? OnCallEnded; | ||
|
||
private readonly CXCallController callController; | ||
|
||
public IOSCallObserver() | ||
{ | ||
callController = new CXCallController(); | ||
callController.CallObserver.SetDelegate(this, null); | ||
|
||
if (callController.CallObserver.Calls.Any(c => !c.HasEnded)) | ||
OnCall?.Invoke(); | ||
} | ||
|
||
public void CallChanged(CXCallObserver callObserver, CXCall call) | ||
{ | ||
if (!call.HasEnded) | ||
OnCall?.Invoke(); | ||
else | ||
OnCallEnded?.Invoke(); | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
callController.Dispose(); | ||
base.Dispose(disposing); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -122,22 +122,10 @@ private void initialiseWindowingAfterCreation() | |||||
WindowMode.TriggerChange(); | ||||||
} | ||||||
|
||||||
private bool focused; | ||||||
|
||||||
/// <summary> | ||||||
/// Whether the window currently has focus. | ||||||
/// </summary> | ||||||
public bool Focused | ||||||
{ | ||||||
get => focused; | ||||||
protected set | ||||||
{ | ||||||
if (value == focused) | ||||||
return; | ||||||
|
||||||
isActive.Value = focused = value; | ||||||
} | ||||||
} | ||||||
public bool Focused { get; private set; } | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
To fix Android build. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather fix this by updating android code if we can. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Susko3 can you test the android change i committed? |
||||||
|
||||||
public WindowMode DefaultWindowMode => RuntimeInfo.IsMobile ? Configuration.WindowMode.Fullscreen : Configuration.WindowMode.Windowed; | ||||||
|
||||||
|
@@ -222,9 +210,17 @@ public Size MaxSize | |||||
/// </summary> | ||||||
public Bindable<WindowMode> WindowMode { get; } = new Bindable<WindowMode>(); | ||||||
|
||||||
public IBindable<bool> IsActive => isActive; | ||||||
|
||||||
private readonly BindableBool isActive = new BindableBool(); | ||||||
|
||||||
public IBindable<bool> IsActive => isActive; | ||||||
/// <summary> | ||||||
/// Whether <see cref="IsActive"/> should be <c>true</c>. | ||||||
/// Takes effect on next call to <see cref="UpdateActiveState"/>. | ||||||
/// </summary> | ||||||
protected virtual bool ShouldBeActive => Focused; | ||||||
|
||||||
protected void UpdateActiveState() => isActive.Value = ShouldBeActive; | ||||||
|
||||||
private readonly BindableBool cursorInWindow = new BindableBool(); | ||||||
|
||||||
|
@@ -505,11 +501,13 @@ private unsafe void handleWindowEvent(SDL_WindowEvent evtWindow) | |||||
case SDL_EventType.SDL_EVENT_WINDOW_RESTORED: | ||||||
case SDL_EventType.SDL_EVENT_WINDOW_FOCUS_GAINED: | ||||||
Focused = true; | ||||||
UpdateActiveState(); | ||||||
break; | ||||||
|
||||||
case SDL_EventType.SDL_EVENT_WINDOW_MINIMIZED: | ||||||
case SDL_EventType.SDL_EVENT_WINDOW_FOCUS_LOST: | ||||||
Focused = false; | ||||||
UpdateActiveState(); | ||||||
break; | ||||||
|
||||||
case SDL_EventType.SDL_EVENT_WINDOW_CLOSE_REQUESTED: | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it fixes the issue, I think that forcing the game to be inactive when a call is in progress isn't fully correct.
Image this scenario:
IsActive == false
, leading to weird behaviour (likely: input doesn't work, the game cannot be unpaused)Instead of the game checking if a call is in progress, I think it should check if a call is currently ringing. Looking at the apple docs, I would consider a call to be ringing iff:
!isOutgoing &&
!hasConnected &&
!hasEnded &&
!isOnHold
.I think it's fine to force the game to be inactive when a call is ringing, as the user is focused on answering or declining the call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @frenzibyte, looks better than what you have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be more optimal, but the audio system always remains frozen while a call is active, from the point of ringing until the call is ended. Therefore it doesn't help to make the game focused while a call is active (the user would be faced with a frozen beatmap and they will receive the "audio is not working" message etc.).
If anything, we should prevent the user from trying to unpause the game during a call, but that's pretty much follow-up effort for this PR.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😳 Is this how other games behave? If not, maybe something is wrong with BASS.
Is this documented somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial testing with Arcaea showed much proper handling. When an incoming call is triggered, the level still continues progressing, the audio stops for a short time but returns back, and after accepting a call the audio remains working.
I'll report this to BASS.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly let's just go with what we have for now. The above scenario is an edge case of an edge case. We can iterate.