Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/MasterpieceApp/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ class MasterpieceApp : public juce::JUCEApplication {
// language comes first.
proc_->applyChosenLanguage();
mp::ui::installTouchLook();
mp::ui::keepFileDialogsWithProgram();
mp::ui::restoreLinkedDocuments();
win_ = std::make_unique<DocWindow>(*proc_, *devices_);
win_->setVisible(true);
Expand Down
3 changes: 3 additions & 0 deletions src/mp_audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ endif()
# iPhone and iPad: picked documents read in place (#197).
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
target_sources(mp_audio PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mp_ui/IosAccess.mm)
elseif(APPLE)
# macOS: the file dialogs stay with the program (#492).
target_sources(mp_audio PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../mp_ui/MacWindows.mm)
endif()
target_include_directories(mp_audio PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..)
target_compile_features(mp_audio PUBLIC cxx_std_20)
Expand Down
33 changes: 33 additions & 0 deletions src/mp_ui/MacWindows.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// macOS: the file dialogs stay with the program (#492).
//
// JUCE raises an open or save panel to the modal-panel level, above every
// normal window, and the panel stayed above other programs' windows once the
// player went to one. Each panel hides when the program leaves the front and
// comes back with it, as the Recorder and Combinations windows do. One
// observer, for the application's lifetime: a panel is seen as it takes the
// keyboard.

#include "Mobile.h"

#if JUCE_MAC
#import <AppKit/AppKit.h>

namespace mp::ui {

void keepFileDialogsWithProgram() {
static bool installed = false;
if (installed) return;
installed = true;
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification
object:nil
queue:nil
usingBlock:^(NSNotification* note) {
id window = note.object;
if ([window isKindOfClass:[NSSavePanel class]])
[(NSSavePanel*)window setHidesOnDeactivate:YES];
}];
}

} // namespace mp::ui

#endif
26 changes: 26 additions & 0 deletions src/mp_ui/Mobile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,31 @@ class SizeKeeper : public juce::ComponentListener {
private:
juce::String kind_;
};

// JUCE makes a new dialog always on top whenever another of the program's
// windows is, and the Recorder and Combinations windows are while the
// program is in front: such a dialog then stayed above every other
// program's windows (#492). It follows the program in and out of the front,
// as those windows do. Owned by nobody but itself: it goes with the dialog.
class FrontFollower : public juce::ComponentListener, private juce::Timer {
public:
explicit FrontFollower(juce::Component& dialog) : dialog_(&dialog) {
dialog.addComponentListener(this);
startTimer(250);
}
void componentBeingDeleted(juce::Component& c) override {
stopTimer();
c.removeComponentListener(this);
delete this;
}

private:
void timerCallback() override {
const bool front = juce::Process::isForegroundProcess();
if (dialog_ != nullptr && dialog_->isAlwaysOnTop() != front) dialog_->setAlwaysOnTop(front);
}
juce::Component::SafePointer<juce::Component> dialog_;
};
} // namespace

juce::DialogWindow* launchDialog(juce::DialogWindow::LaunchOptions& options) {
Expand Down Expand Up @@ -548,6 +573,7 @@ juce::DialogWindow* launchDialog(juce::DialogWindow::LaunchOptions& options) {
}
dialog->addComponentListener(new SizeKeeper(kind));
}
if (kLiveOnTop && !kMobile && dialog->isAlwaysOnTop()) new FrontFollower(*dialog);
return dialog;
}

Expand Down
9 changes: 9 additions & 0 deletions src/mp_ui/Mobile.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ constexpr bool kLiveOnTop = true;
// screen on a phone or tablet. Every dialog opens through here.
juce::DialogWindow* launchDialog(juce::DialogWindow::LaunchOptions& options);

// macOS: an open or save panel hides while another program is in front, and
// comes back with this one (#492; MacWindows.mm). The application calls it
// once at startup; a plug-in leaves the host's panels alone. Nothing elsewhere.
#if JUCE_MAC
void keepFileDialogsWithProgram();
#else
inline void keepFileDialogsWithProgram() {}
#endif

// Closes the front-most window other than `mainWindow`, as its own close
// button would: Android's back button. False when there was none, so the
// system's own back behaviour applies. A window whose properties set
Expand Down
Loading