Merge branch 'efroemling:master' into master

This commit is contained in:
Vishal 2023-11-30 23:01:17 +05:30 committed by GitHub
commit f2f13b3cc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 155 additions and 71 deletions

56
.efrocachemap generated
View File

@ -4060,26 +4060,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d1b736e6185c6a77cabad635afe97d1c", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "9fe23e06319e4e256b9fa88814a14afa",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "93c74c5b4f9b7f528b0802aa7a23f677", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "4306acae21ce88235f9d1589086866e7",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "36cba560a8171836dd7c9c6ff0ef9218", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "75e4f7d3a3df67dedd079ec3f4441094",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "6e1d80e717d34d8594588d22a002e8f9", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bd5eda13f239b81886ac80596d6ade73",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "36a88b7c6b86f1acdd32ee4651496297", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "0805235a92dd91f96d43ea54575eecac",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "86399e9fed0bd310390595036e5a2567", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "07589a61b11cbc5fca0bbc8b7fc1c955",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f359b4e02f83e4aa04d7d0165b864de8", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f28629761060c8152168b6792b71adae",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e244e4b6e699ccf65ccde669153290df", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1cfd1a33474cdb31834994f626385ed0",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d31b4e34e21c25455380afa50ecf0fe7", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d50879a92d9d344c376f6f196d78d1be",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "3d1d0b4dd7df23c3c7e9958286211229", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "78cd0edf2698f197f2acd80ca364fae7",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "de5e043bf03efece2aa8a9ab3362749e", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d656f47118ebc3af57c40423cb258bc8",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "3bd9856b27825995919c9d0bbe6809cb", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "75df540b27779342a7c696e1bdbe593f",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4e58688f6d42481fa175d6f0d43f8ab7", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "76f0dfacaa9ea67e45e8ccf3bb3bc1c6",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "a05c25cdef7d3e81067c9645136a7b77", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "2acc754bed825a9265e0621dc09899e0",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5501e98f9cea647b25a3702e26da5b31", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "62c2b6190de8784ea8750ea50e6a2304",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8ef08bf21aeef91beecce31b79661a1a", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "e57358fd9a948a8ce82a54cdd5c766fc",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "51318d5ab8b474a01466eed83b8d9553", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d36e3303e13049eae5e7ec19861d300e",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ea7ab32e245bb804cd09c9d111a7c10b", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "46971a2ca1e3021e52ea5d0f4938d2ff",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "caabdfd17f1df3608a68cc96315ed4d5", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "19ebd36613cf62c4bd50e70b93371368",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "8a9ed3e4672af09f5ea1b81d59dfb84f", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "49ef5905b6e9e1a9caaed3d1c1da4ea5",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "c22901e06e88a55cce0b4e08bbf41a4c", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "c22901e06e88a55cce0b4e08bbf41a4c",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "a27963487e346338e4c216bd4fbb9e2a", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "a27963487e346338e4c216bd4fbb9e2a",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "c22901e06e88a55cce0b4e08bbf41a4c", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "c22901e06e88a55cce0b4e08bbf41a4c",
@ -4096,14 +4096,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "852fe46c736082611a831a618923c241", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "852fe46c736082611a831a618923c241",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "36fbda7829ed5c2862c34feb09b03402", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "36fbda7829ed5c2862c34feb09b03402",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "852fe46c736082611a831a618923c241", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "852fe46c736082611a831a618923c241",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "23dbca6f6f4c8b9061e68af17d79791b", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "38b4b5b85a9bafdb76222d0f0c962b06",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "639bb72656fb6f5b21ac525b9098854a", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "9a8af3d217bcb0bacfaed4c30dd5f42e",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "d0a0820657e11771d1e393d47af23c17", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6d10ca306f60d66efb4942636e4955d6",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "62f9d32dcc6c74421f1a3f88abf07777", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "1c65d36e4420ed79380dc8c041c94a8b",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "2d38cd1723c7b1a9a1b19d206d5a17a5", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "9b1b72f3d41c89a6b06288be63e8f40a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "8e4304d0b16fa16038fc1660eb06c350", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e0f2eb8ea024bc88e999b9dc16317fd4",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "08120b7a6b3845cf729c1defcc6e90ec", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "42be1225757328f432d91de950444ba0",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f5d59b0bce6cb0e43da92a5863bb963c", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "05bc2832cc0c9fba308668fc1a6d3b0f",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -1,4 +1,4 @@
### 1.7.30 (build 21630, api 8, 2023-11-29) ### 1.7.30 (build 21636, api 8, 2023-11-30)
- Continued work on the big 1.7.28 update. - Continued work on the big 1.7.28 update.
- Got the Android version back up and running. There's been lots of cleanup and - Got the Android version back up and running. There's been lots of cleanup and
simplification on the Android layer, cleaning out years of cruft. This should simplification on the Android layer, cleaning out years of cruft. This should
@ -19,6 +19,11 @@
effects such as the app continuing to play audio when it should not be. effects such as the app continuing to play audio when it should not be.
- (build 21626) Fixed a bug where click/tap locations were incorrect on some - (build 21626) Fixed a bug where click/tap locations were incorrect on some
builds when tv-border was on (Thanks for the heads-up Loup(Dliwk's fan)!). builds when tv-border was on (Thanks for the heads-up Loup(Dliwk's fan)!).
- (build 21631) Fixes an issue where '^^^^^^^^^^^^^' lines in stack traces could
get chopped into tiny bits each on their own line in the dev console.
- Fixed a longstanding issue where multiple key presses simultaneously could
cause multiple windows to pop up where only one is expected. Please holler if
you still see this problem happening anywhere.
### 1.7.29 (build 21619, api 8, 2023-11-21) ### 1.7.29 (build 21619, api 8, 2023-11-21)

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21630 TARGET_BALLISTICA_BUILD = 21636
TARGET_BALLISTICA_VERSION = '1.7.30' TARGET_BALLISTICA_VERSION = '1.7.30'

View File

@ -311,8 +311,8 @@ class MainMenuWindow(bui.Window):
else self._confirm_end_game else self._confirm_end_game
), ),
) )
# Assume we're in a client-session.
else: else:
# Assume we're in a client-session.
bui.buttonwidget( bui.buttonwidget(
parent=self._root_widget, parent=self._root_widget,
position=(h - self._button_width * 0.5 * scale, v), position=(h - self._button_width * 0.5 * scale, v),
@ -360,7 +360,6 @@ class MainMenuWindow(bui.Window):
tilt_scale=0.0, tilt_scale=0.0,
draw_controller=store_button, draw_controller=store_button,
) )
self._tdelay += self._t_delay_inc self._tdelay += self._t_delay_inc
else: else:
self._store_button = None self._store_button = None

View File

@ -615,7 +615,7 @@ void Graphics::FadeScreen(bool to, millisecs_t time, PyObject* endcall) {
Log(LogLevel::kWarning, Log(LogLevel::kWarning,
"2 fades overlapping; running first fade-end-call early."); "2 fades overlapping; running first fade-end-call early.");
} }
fade_end_call_->Schedule(); fade_end_call_->ScheduleOnce();
fade_end_call_.Clear(); fade_end_call_.Clear();
} }
set_fade_start_on_next_draw_ = true; set_fade_start_on_next_draw_ = true;
@ -1021,7 +1021,7 @@ void Graphics::DrawFades(FrameDef* frame_def) {
} else { } else {
fade_ = 0; fade_ = 0;
if (!was_done && fade_end_call_.Exists()) { if (!was_done && fade_end_call_.Exists()) {
fade_end_call_->Schedule(); fade_end_call_->ScheduleOnce();
fade_end_call_.Clear(); fade_end_call_.Clear();
} }
} }

View File

@ -279,7 +279,7 @@ static auto PyPushCall(PyObject* self, PyObject* args, PyObject* keywds)
if (!g_base->InLogicThread()) { if (!g_base->InLogicThread()) {
throw Exception("You must use from_other_thread mode."); throw Exception("You must use from_other_thread mode.");
} }
Object::New<PythonContextCall>(call_obj)->Schedule(); Object::New<PythonContextCall>(call_obj)->ScheduleOnce();
} }
Py_RETURN_NONE; Py_RETURN_NONE;
BA_PYTHON_CATCH; BA_PYTHON_CATCH;

View File

@ -125,45 +125,83 @@ void PythonContextCall::Schedule() {
Object::Ref<PythonContextCall> ref(this); Object::Ref<PythonContextCall> ref(this);
assert(base::g_base); assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref] { base::g_base->logic->event_loop()->PushCall([ref] {
assert(ref.Exists()); assert(ref.Exists());
ref->schedule_count_--;
assert(ref->schedule_count_ >= 0);
ref->Run(); ref->Run();
}); });
} }
void PythonContextCall::ScheduleOnce() {
if (schedule_count_ > 0) {
return;
}
Schedule();
}
void PythonContextCall::Schedule(const PythonRef& args) { void PythonContextCall::Schedule(const PythonRef& args) {
// Since we're mucking with Object::Refs, need to limit to logic thread. // Since we're mucking with Object::Refs, need to limit to logic thread.
BA_PRECONDITION(g_base->InLogicThread()); BA_PRECONDITION(g_base->InLogicThread());
Object::Ref<PythonContextCall> ref(this); Object::Ref<PythonContextCall> ref(this);
assert(base::g_base); assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref, args] { base::g_base->logic->event_loop()->PushCall([ref, args] {
assert(ref.Exists()); assert(ref.Exists());
ref->schedule_count_--;
assert(ref->schedule_count_ >= 0);
ref->Run(args); ref->Run(args);
}); });
} }
void PythonContextCall::ScheduleOnce(const PythonRef& args) {
if (schedule_count_ > 0) {
return;
}
Schedule(args);
}
void PythonContextCall::ScheduleWeak() { void PythonContextCall::ScheduleWeak() {
// Since we're mucking with Object::WeakRefs, need to limit to logic thread. // Since we're mucking with Object::WeakRefs, need to limit to logic thread.
BA_PRECONDITION(g_base->InLogicThread()); BA_PRECONDITION(g_base->InLogicThread());
Object::WeakRef<PythonContextCall> ref(this); Object::WeakRef<PythonContextCall> ref(this);
assert(base::g_base); assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref] { base::g_base->logic->event_loop()->PushCall([ref] {
if (auto* call = ref.Get()) { if (auto* call = ref.Get()) {
call->schedule_count_--;
assert(call->schedule_count_ >= 0);
call->Run(); call->Run();
} }
}); });
} }
void PythonContextCall::ScheduleWeakOnce() {
if (schedule_count_ > 0) {
return;
}
ScheduleWeak();
}
void PythonContextCall::ScheduleWeak(const PythonRef& args) { void PythonContextCall::ScheduleWeak(const PythonRef& args) {
// Since we're mucking with Object::WeakRefs, need to limit to logic thread. // Since we're mucking with Object::WeakRefs, need to limit to logic thread.
BA_PRECONDITION(g_base->InLogicThread()); BA_PRECONDITION(g_base->InLogicThread());
Object::WeakRef<PythonContextCall> ref(this); Object::WeakRef<PythonContextCall> ref(this);
assert(base::g_base); assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref, args] { base::g_base->logic->event_loop()->PushCall([ref, args] {
if (auto* call = ref.Get()) { if (auto* call = ref.Get()) {
call->schedule_count_--;
assert(call->schedule_count_ >= 0);
call->Run(args); call->Run(args);
} }
}); });
} }
void PythonContextCall::ScheduleWeakOnce(const PythonRef& args) {
if (schedule_count_ > 0) {
return;
}
ScheduleWeak(args);
}
} // namespace ballistica::base } // namespace ballistica::base

View File

@ -11,10 +11,10 @@
namespace ballistica::base { namespace ballistica::base {
// A callable and ballistica context-state wrapped up in a convenient package. // A callable and ballistica context-state wrapped up in a convenient
// Handy for use with user-submitted callbacks, as it restores context // package. Handy for use with user-submitted callbacks, as it restores
// state from when it was created and prints various useful bits of context // context state from when it was created and prints various useful bits of
// info on exceptions. // context info on exceptions.
class PythonContextCall : public Object { class PythonContextCall : public Object {
public: public:
static auto current_call() -> PythonContextCall* { return current_call_; } static auto current_call() -> PythonContextCall* { return current_call_; }
@ -37,35 +37,65 @@ class PythonContextCall : public Object {
auto file_loc() const -> const std::string& { return file_loc_; } auto file_loc() const -> const std::string& { return file_loc_; }
void PrintContext(); void PrintContext();
/// Run in an upcoming cycle of the logic thread. /// Run in an upcoming cycle of the logic thread. Must be called from the
/// Must be called from the logic thread. /// logic thread. This form creates a strong-reference so the
/// This form creates a strong-reference so the context_ref-call is guaranteed /// context_ref-call is guaranteed to exist until run.
/// to exist until run.
void Schedule(); void Schedule();
/// Run in an upcoming cycle of the logic thread with provided args.
/// Must be called from the logic thread. /// Schedule only if this instance is not already scheduled. Generally a
/// This form creates a strong-reference so the context_ref-call is guaranteed /// good idea unless you know you need multiple runs scheduled. Avoids
/// to exist until run. /// problems such as UIs expecting to be activated only once getting
/// activated twice due to two simultenous key presses.
void ScheduleOnce();
/// Run in an upcoming cycle of the logic thread with provided args. Must
/// be called from the logic thread. This form creates a strong-reference
/// so the context_ref-call is guaranteed to exist until run.
void Schedule(const PythonRef& args); void Schedule(const PythonRef& args);
/// Run in an upcoming cycle of the logic thread.
/// Must be called from the logic thread. /// Schedule only if this instance is not already scheduled. Generally a
/// This form creates a weak-reference and is a no-op if the context_ref-call /// good idea unless you know you need multiple runs scheduled. Avoids
/// is destroyed before its scheduled run. /// problems such as UIs expecting to be activated only once getting
/// activated twice due to two simultenous key presses.
void ScheduleOnce(const PythonRef& args);
/// Run in an upcoming cycle of the logic thread. Must be called from the
/// logic thread. This form creates a weak-reference and is a no-op if the
/// context_ref-call is destroyed before its scheduled run.
void ScheduleWeak(); void ScheduleWeak();
/// Run in an upcoming cycle of the logic thread with provided args.
/// Must be called from the logic thread. /// Schedule weakly only if this instance is not already scheduled.
/// This form creates a weak-reference and is a no-op if the context_ref-call /// Generally a good idea unless you know you need multiple runs
/// is destroyed before its scheduled run. /// scheduled. Avoids problems such as UIs expecting to be activated only
/// once getting activated twice due to two simultenous key presses.
void ScheduleWeakOnce();
/// Run in an upcoming cycle of the logic thread with provided args. Must
/// be called from the logic thread. This form creates a weak-reference
/// and is a no-op if the context_ref-call is destroyed before its
/// scheduled run.
void ScheduleWeak(const PythonRef& args); void ScheduleWeak(const PythonRef& args);
/// Schedule weakly only if this instance is not already scheduled.
/// Generally a good idea unless you know you need multiple runs
/// scheduled. Avoids problems such as UIs expecting to be activated only
/// once getting activated twice due to two simultenous key presses.
void ScheduleWeakOnce(const PythonRef& args);
auto IsScheduled() const {
assert(g_base->InLogicThread());
return schedule_count_ > 0;
}
private: private:
void GetTrace(); // we try to grab basic trace info void GetTrace(); // we try to grab basic trace info
std::string file_loc_;
int line_{}; int line_{};
bool dead_ = false; int schedule_count_{};
bool dead_{};
std::string file_loc_;
PythonRef object_; PythonRef object_;
base::ContextRef context_state_; base::ContextRef context_state_;
// base::Context* context_target_sanity_test_{};
static PythonContextCall* current_call_; static PythonContextCall* current_call_;
}; };

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21630; const int kEngineBuildNumber = 21636;
const char* kEngineVersion = "1.7.30"; const char* kEngineVersion = "1.7.30";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;

View File

@ -115,7 +115,7 @@ void UIV1Python::InvokeStringEditor(PyObject* string_edit_adapter_instance) {
PythonRef::kSteal); PythonRef::kSteal);
Object::New<base::PythonContextCall>( Object::New<base::PythonContextCall>(
objs().Get(ObjID::kOnScreenKeyboardClass)) objs().Get(ObjID::kOnScreenKeyboardClass))
->Schedule(args); ->ScheduleOnce(args);
} }
void UIV1Python::LaunchStringEditOld(TextWidget* w) { void UIV1Python::LaunchStringEditOld(TextWidget* w) {
@ -131,7 +131,7 @@ void UIV1Python::LaunchStringEditOld(TextWidget* w) {
PythonRef::kSteal); PythonRef::kSteal);
Object::New<base::PythonContextCall>( Object::New<base::PythonContextCall>(
objs().Get(ObjID::kOnScreenKeyboardClass)) objs().Get(ObjID::kOnScreenKeyboardClass))
->Schedule(args); ->ScheduleOnce(args);
} }
void UIV1Python::InvokeQuitWindow(QuitType quit_type) { void UIV1Python::InvokeQuitWindow(QuitType quit_type) {

View File

@ -562,7 +562,7 @@ void ButtonWidget::DoActivate(bool is_repeat) {
if (auto* call = on_activate_call_.Get()) { if (auto* call = on_activate_call_.Get()) {
// Call this in the next cycle (don't want to risk mucking with UI from // Call this in the next cycle (don't want to risk mucking with UI from
// within a UI loop.) // within a UI loop.)
call->ScheduleWeak(); call->ScheduleWeakOnce();
return; return;
} }
} }

View File

@ -247,7 +247,7 @@ void CheckBoxWidget::Activate() {
// Call this in the next cycle (don't want to risk mucking with UI from // Call this in the next cycle (don't want to risk mucking with UI from
// within a UI loop) // within a UI loop)
call->ScheduleWeak(args); call->ScheduleWeakOnce(args);
} }
} }

View File

@ -347,7 +347,7 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// Call this in the next cycle (don't wanna risk mucking with UI from // Call this in the next cycle (don't wanna risk mucking with UI from
// within a UI loop). // within a UI loop).
call->ScheduleWeak(); call->ScheduleWeakOnce();
} else { } else {
OnCancelCustom(); OnCancelCustom();
} }
@ -631,7 +631,7 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
if (!claimed && on_outside_click_call_.Exists()) { if (!claimed && on_outside_click_call_.Exists()) {
// Call this in the next cycle (don't wanna risk mucking with UI from // Call this in the next cycle (don't wanna risk mucking with UI from
// within a UI loop). // within a UI loop).
on_outside_click_call_->ScheduleWeak(); on_outside_click_call_->ScheduleWeakOnce();
} }
// Always claim if they want. // Always claim if they want.
@ -1071,7 +1071,7 @@ void ContainerWidget::Activate() {
if (auto* call = on_activate_call_.Get()) { if (auto* call = on_activate_call_.Get()) {
// Call this in the next cycle (don't wanna risk mucking with UI from within // Call this in the next cycle (don't wanna risk mucking with UI from within
// a UI loop). // a UI loop).
call->ScheduleWeak(); call->ScheduleWeakOnce();
} }
} }
@ -1182,6 +1182,7 @@ void ContainerWidget::SetTransition(TransitionType t) {
dynamics_update_time_millisecs_ = display_time_millisecs; dynamics_update_time_millisecs_ = display_time_millisecs;
transitioning_ = true; transitioning_ = true;
transitioning_out_ = true; transitioning_out_ = true;
ignore_input_ = true;
} else { } else {
// Calculate the screen size in our own local space - we'll // Calculate the screen size in our own local space - we'll
// animate an offset to slide on/off screen. // animate an offset to slide on/off screen.

View File

@ -592,7 +592,7 @@ void TextWidget::Activate() {
if (auto* call = on_activate_call_.Get()) { if (auto* call = on_activate_call_.Get()) {
// Call this in the next cycle (don't wanna risk mucking with UI from // Call this in the next cycle (don't wanna risk mucking with UI from
// within a UI loop). // within a UI loop).
call->ScheduleWeak(); call->ScheduleWeakOnce();
} }
// Bring up an editor if applicable. // Bring up an editor if applicable.
@ -720,7 +720,7 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
claimed = true; claimed = true;
// Call this in the next cycle (don't wanna risk mucking with UI // Call this in the next cycle (don't wanna risk mucking with UI
// from within a UI loop) // from within a UI loop)
call->ScheduleWeak(); call->ScheduleWeakOnce();
} }
} }
break; break;

View File

@ -88,7 +88,7 @@ void Widget::SetSelected(bool s, SelectionCause cause) {
if (selected_ && on_select_call_.Exists()) { if (selected_ && on_select_call_.Exists()) {
// Call this in the next cycle (don't wanna risk mucking // Call this in the next cycle (don't wanna risk mucking
// with UI from within a UI loop). // with UI from within a UI loop).
on_select_call_->ScheduleWeak(); on_select_call_->ScheduleWeakOnce();
} }
} }

View File

@ -450,6 +450,11 @@ class LogHandler(logging.Handler):
def file_write(self, name: str, output: str) -> None: def file_write(self, name: str, output: str) -> None:
"""Send raw stdout/stderr output to the logger to be collated.""" """Send raw stdout/stderr output to the logger to be collated."""
# Note to self: it turns out that things like '^^^^^^^^^^^^^^'
# lines in stack traces get written as lots of individual '^'
# writes. It feels a bit dirty to be pushing a deferred call to
# another thread for each character. Perhaps should do some sort
# of basic accumulation here?
self._event_loop.call_soon_threadsafe( self._event_loop.call_soon_threadsafe(
tpartial(self._file_write_in_thread, name, output) tpartial(self._file_write_in_thread, name, output)
) )
@ -509,12 +514,18 @@ class LogHandler(logging.Handler):
traceback.print_exc(file=self._echofile) traceback.print_exc(file=self._echofile)
async def _ship_chunks_task(self, name: str) -> None: async def _ship_chunks_task(self, name: str) -> None:
# Note: it's important we sleep here for a moment. Otherwise,
# things like '^^^^^^^^^^^^' lines in stack traces, which come
# through as lots of individual '^' writes, tend to get broken
# into lots of tiny little lines by us.
await asyncio.sleep(0.01)
self._ship_file_chunks(name, cancel_ship_task=False) self._ship_file_chunks(name, cancel_ship_task=False)
def _ship_file_chunks(self, name: str, cancel_ship_task: bool) -> None: def _ship_file_chunks(self, name: str, cancel_ship_task: bool) -> None:
# Note: Raw print input generally ends in a newline, but that is # Note: Raw print input generally ends in a newline, but that is
# redundant when we break things into log entries and results # redundant when we break things into log entries and results in
# in extra empty lines. So strip off a single trailing newline. # extra empty lines. So strip off a single trailing newline if
# one is present.
text = ''.join(self._file_chunks[name]).removesuffix('\n') text = ''.join(self._file_chunks[name]).removesuffix('\n')
self._emit_entry( self._emit_entry(