Skip to content

Commit 4a77492

Browse files
committed
Detect iPadOS multi-window mode and add padding for window control buttons
When running on iPadOS in multi-window mode (Stage Manager, Split View, Slide Over), the window control buttons (red/yellow/green) at the top-left overlap with the hamburger menu button. This adds: - Native iOS detection via UIWindowScene API to check if window is smaller than screen (indicating multi-window mode) - QML-side window width check for reactive updates when user enters/exits multi-window mode - 70px left padding on toolbar when in multi-window mode on iPadOS Fixes #4238 https://claude.ai/code/session_01VPuuPcJnU1GEtGy1vosET9
1 parent 1ac2149 commit 4a77492

4 files changed

Lines changed: 54 additions & 3 deletions

File tree

src/homeform.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class homeform : public QObject {
203203
Q_PROPERTY(QString previewWorkoutDescription READ previewWorkoutDescription NOTIFY previewWorkoutDescriptionChanged)
204204
Q_PROPERTY(QString previewWorkoutTags READ previewWorkoutTags NOTIFY previewWorkoutTagsChanged)
205205
Q_PROPERTY(bool miles_unit READ miles_unit)
206+
Q_PROPERTY(bool iPadMultiWindowMode READ iPadMultiWindowMode)
206207

207208
Q_PROPERTY(bool currentCoordinateValid READ currentCoordinateValid)
208209
Q_PROPERTY(bool trainProgramLoadedWithVideo READ trainProgramLoadedWithVideo)
@@ -705,6 +706,14 @@ class homeform : public QObject {
705706
return settings.value(QZSettings::miles_unit, QZSettings::default_miles_unit).toBool();
706707
}
707708

709+
bool iPadMultiWindowMode() {
710+
#ifdef Q_OS_IOS
711+
return lockscreen::isInMultiWindowMode();
712+
#else
713+
return false;
714+
#endif
715+
}
716+
708717
bool currentCoordinateValid() {
709718
if (bluetoothManager && bluetoothManager->device()) {
710719
return bluetoothManager->device()->currentCordinate().isValid();

src/ios/lockscreen.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class lockscreen {
111111
static void set_action_profile(const char* profile);
112112
static const char* get_action_profile();
113113

114+
// multi-window detection for iPadOS
115+
static bool isInMultiWindowMode();
114116
};
115117

116118
#endif // LOCKSCREEN_H

src/ios/lockscreen.mm

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,13 +616,43 @@
616616

617617
void lockscreen::zwiftClickRemote_WriteCharacteristic(unsigned char* qdata, unsigned char length, void* deviceClass) {
618618
if (ios_zwiftClickRemotes == nil) return;
619-
619+
620620
// Get the specific remote for this device
621621
NSValue *key = [NSValue valueWithPointer:deviceClass];
622622
ios_zwiftclickremote *remote = [ios_zwiftClickRemotes objectForKey:key];
623-
623+
624624
if(remote) {
625625
[remote writeCharacteristic:qdata length:length];
626626
}
627627
}
628+
629+
bool lockscreen::isInMultiWindowMode() {
630+
// Check if we're on iPad and in multi-window mode (Stage Manager, Split View, Slide Over)
631+
if (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPad) {
632+
return false;
633+
}
634+
635+
if (@available(iOS 13.0, *)) {
636+
// Get the foreground active scene
637+
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
638+
if (scene.activationState == UISceneActivationStateForegroundActive &&
639+
[scene isKindOfClass:[UIWindowScene class]]) {
640+
UIWindowScene *windowScene = (UIWindowScene *)scene;
641+
642+
// Get the window bounds and screen bounds
643+
CGRect windowBounds = windowScene.coordinateSpace.bounds;
644+
CGRect screenBounds = windowScene.screen.bounds;
645+
646+
// If window is smaller than screen in either dimension, we're in multi-window mode
647+
// Add a small tolerance for floating point comparison
648+
if (windowBounds.size.width < screenBounds.size.width - 1 ||
649+
windowBounds.size.height < screenBounds.size.height - 1) {
650+
return true;
651+
}
652+
}
653+
}
654+
}
655+
656+
return false;
657+
}
628658
#endif

src/main.qml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,18 @@ ApplicationWindow {
4343
}
4444

4545
function getLeftPadding() {
46+
// Add padding for iPadOS multi-window mode (Stage Manager, Split View, Slide Over)
47+
// to avoid overlap with window control buttons (red/yellow/green)
48+
// Check both the native detection and window size comparison for reactivity
49+
if (Qt.platform.os === "ios") {
50+
var isMultiWindow = (typeof rootItem !== "undefined" && rootItem && rootItem.iPadMultiWindowMode) ||
51+
(window.width < Screen.width - 10); // Window smaller than screen = multi-window
52+
if (isMultiWindow) {
53+
return 70; // Space for window control buttons
54+
}
55+
}
4656
if (Qt.platform.os !== "android" || AndroidStatusBar.apiLevel < 31) return 0;
47-
return (Screen.orientation === Qt.LandscapeOrientation || Screen.orientation === Qt.InvertedLandscapeOrientation) ?
57+
return (Screen.orientation === Qt.LandscapeOrientation || Screen.orientation === Qt.InvertedLandscapeOrientation) ?
4858
AndroidStatusBar.leftInset : 0;
4959
}
5060

0 commit comments

Comments
 (0)