- wasm/kiplatform: add EnableDarkMode, IO::TimestampDir, UI::AllowNetworkFileSystems, UI::CancelPendingScroll, SECRETS::DeleteSecret (new KiCad 10 functions). - wasm/stubs/libgit2_stub.c: ~156 no-op stubs for KiCad 10's restructured git backend + git-backed local history + text_eval VCS. - tests/kicad: bump the demo project dir 9.99 -> 10.0 (KiCad 10 stores projects under /home/kicad/documents/kicad/10.0/) — fixes load-pcb + 3d-viewer e2e. - scripts/common/apply-asyncify.sh: ASYNCIFY_EXTRA_OPTS hook (e.g. -g for symbolizable wasm traces). - kicad submodule -> ef00c2d3 (KiCad 10 link + runtime adaptations). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
211 lines
4.9 KiB
C++
211 lines
4.9 KiB
C++
/*
|
|
* WASM implementation of kiplatform/ui.h
|
|
* Provides UI functions for browser environment
|
|
*/
|
|
|
|
#include <kiplatform/ui.h>
|
|
#include <wx/window.h>
|
|
#include <wx/choice.h>
|
|
#include <wx/toplevel.h>
|
|
#include <wx/nonownedwnd.h>
|
|
#include <wx/colour.h>
|
|
#include <wx/settings.h>
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
#include <emscripten.h>
|
|
#endif
|
|
|
|
namespace KIPLATFORM
|
|
{
|
|
namespace UI
|
|
{
|
|
|
|
bool IsDarkTheme()
|
|
{
|
|
// The wasm/wxUniversal UI renders a fixed theme that does not follow the
|
|
// browser's prefers-color-scheme; report the theme actually rendered so
|
|
// icon variants and widget colours stay consistent with the widget chrome.
|
|
return wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ).GetLuminance() < 0.5;
|
|
}
|
|
|
|
wxColour GetDialogBGColour()
|
|
{
|
|
return wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
|
|
}
|
|
|
|
void ForceFocus( wxWindow* aWindow )
|
|
{
|
|
if( aWindow )
|
|
aWindow->SetFocus();
|
|
}
|
|
|
|
bool IsWindowActive( wxWindow* aWindow )
|
|
{
|
|
if( !aWindow )
|
|
return false;
|
|
|
|
wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>( aWindow );
|
|
if( tlw )
|
|
return tlw->IsActive();
|
|
|
|
// For non-TLW, check if it has focus
|
|
return aWindow->HasFocus();
|
|
}
|
|
|
|
void ReparentModal( wxNonOwnedWindow* aWindow )
|
|
{
|
|
// No-op in browser - modal handling is different
|
|
}
|
|
|
|
void ReparentWindow( wxNonOwnedWindow* aWindow, wxTopLevelWindow* aParent )
|
|
{
|
|
// Reparenting not typically needed in browser
|
|
}
|
|
|
|
void FixupCancelButtonCmdKeyCollision( wxWindow* aWindow )
|
|
{
|
|
// Not needed in browser - no Cmd key
|
|
}
|
|
|
|
bool IsStockCursorOk( wxStockCursor aCursor )
|
|
{
|
|
// All stock cursors should work in browser via CSS
|
|
return true;
|
|
}
|
|
|
|
void LargeChoiceBoxHack( wxChoice* aChoice )
|
|
{
|
|
// Not needed in browser
|
|
}
|
|
|
|
void EllipsizeChoiceBox( wxChoice* aChoice )
|
|
{
|
|
// Browser handles text overflow via CSS
|
|
}
|
|
|
|
double GetPixelScaleFactor( const wxWindow* aWindow )
|
|
{
|
|
// Return actual device pixel ratio for hi-res bitmap loading and bundle
|
|
// selection. KiCad keeps its own logical content scale at 1.0 in WASM, so
|
|
// bitmap selection must stay decoupled from layout sizing.
|
|
#ifdef __EMSCRIPTEN__
|
|
double scale = aWindow ? aWindow->GetDPIScaleFactor() : EM_ASM_DOUBLE({
|
|
return window.devicePixelRatio || 1.0;
|
|
});
|
|
return scale >= 1.5 ? 2.0 : 1.0;
|
|
#else
|
|
if( aWindow )
|
|
return aWindow->GetContentScaleFactor();
|
|
return 1.0;
|
|
#endif
|
|
}
|
|
|
|
double GetContentScaleFactor( const wxWindow* aWindow )
|
|
{
|
|
// KiCad layout uses logical coordinates in WASM. wxWidgets window/content
|
|
// scaling still reports the display scale separately for DIP conversions.
|
|
return aWindow ? aWindow->GetContentScaleFactor() : 1.0;
|
|
}
|
|
|
|
void GetInfoBarColours( wxColour& aFGColour, wxColour& aBGColour )
|
|
{
|
|
// Use standard info bar colors
|
|
if( IsDarkTheme() )
|
|
{
|
|
aFGColour = wxColour( 255, 255, 255 );
|
|
aBGColour = wxColour( 50, 50, 120 ); // Dark blue
|
|
}
|
|
else
|
|
{
|
|
aFGColour = wxColour( 0, 0, 0 );
|
|
aBGColour = wxColour( 200, 220, 255 ); // Light blue
|
|
}
|
|
}
|
|
|
|
wxSize GetUnobscuredSize( const wxWindow* aWindow )
|
|
{
|
|
if( aWindow )
|
|
return aWindow->GetClientSize();
|
|
return wxSize( 0, 0 );
|
|
}
|
|
|
|
void SetOverlayScrolling( const wxWindow* aWindow, bool overlay )
|
|
{
|
|
// Browser handles scrollbar styling via CSS
|
|
}
|
|
|
|
bool AllowIconsInMenus()
|
|
{
|
|
// Icons in menus are fine in browser
|
|
return true;
|
|
}
|
|
|
|
wxPoint GetMousePosition()
|
|
{
|
|
return wxGetMousePosition();
|
|
}
|
|
|
|
bool WarpPointer( wxWindow* aWindow, int aX, int aY )
|
|
{
|
|
// Pointer warping is restricted in browsers for security
|
|
// We can still call WarpPointer but it may not work
|
|
if( aWindow )
|
|
{
|
|
aWindow->WarpPointer( aX, aY );
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ImmControl( wxWindow* aWindow, bool aEnable )
|
|
{
|
|
// IME control not needed in browser - handled natively
|
|
}
|
|
|
|
void ImeNotifyCancelComposition( wxWindow* aWindow )
|
|
{
|
|
// IME control not needed in browser
|
|
}
|
|
|
|
bool InfiniteDragPrepareWindow( wxWindow* aWindow )
|
|
{
|
|
// Pointer lock API could be used for infinite drag
|
|
// but requires user gesture and permission
|
|
return false;
|
|
}
|
|
|
|
void InfiniteDragReleaseWindow()
|
|
{
|
|
// No-op
|
|
}
|
|
|
|
void EnsureVisible( wxWindow* aWindow )
|
|
{
|
|
// In browser, window is always visible (single page)
|
|
if( aWindow )
|
|
aWindow->Raise();
|
|
}
|
|
|
|
void SetFloatLevel( wxWindow* aWindow )
|
|
{
|
|
// No floating window levels in browser
|
|
}
|
|
|
|
void AllowNetworkFileSystems( wxDialog* aDialog )
|
|
{
|
|
// Native platforms use this to let file dialogs browse network mounts.
|
|
// The browser's file dialogs are virtual (MEMFS / JS bridge), so this is
|
|
// a no-op.
|
|
(void) aDialog;
|
|
}
|
|
|
|
void CancelPendingScroll( wxDataViewCtrl* aCtrl )
|
|
{
|
|
// Native (GTK/macOS) platforms cancel an in-flight kinetic/async scroll on
|
|
// the data view. The browser wx port has no such pending-scroll state, so
|
|
// this is a no-op.
|
|
(void) aCtrl;
|
|
}
|
|
|
|
} // namespace UI
|
|
} // namespace KIPLATFORM
|