Add stamp source hashing and maximize test infrastructure

- Add source hashing to stamp system (functions.sh) for detecting
  when dependencies need rebuild based on source file changes
- Update build-pcbnew.sh to use source stamps for wxWidgets
- Add global-setup.ts to clean logs before test runs
- Add maximize_test standalone test to verify wxFrame::Maximize()
  works correctly in WASM (it does - window is 1280x720)
- Update Makefile.wasm with maximize test build rules

The maximize_test proves wxWidgets display detection works fine.
KiCad's 20x20 window bug is KiCad-specific, not a wxWidgets issue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Viktor Vaczi 2025-12-14 13:28:43 +01:00
commit 8453f9681e
8 changed files with 416 additions and 14 deletions

View file

@ -130,7 +130,8 @@ all: minimal_test.html \
$(S)/fontenum/fontenum_test.html \
$(S)/textdecor/textdecor_test.html \
$(S)/bitmask/bitmask_test.html \
$(S)/regions/regions_test.html
$(S)/regions/regions_test.html \
$(S)/maximize/maximize_test.html
# Main test app (uses GL)
minimal_test.o: minimal_test.cpp
@ -405,6 +406,13 @@ $(S)/regions/regions_test.o: $(S)/regions/regions_test.cpp
$(S)/regions/regions_test.html: $(S)/regions/regions_test.o
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
# Maximize test (no GL) - reproduces KiCad startup maximize issue
$(S)/maximize/maximize_test.o: $(S)/maximize/maximize_test.cpp
$(CXX) -c $(CXXFLAGS) $< -o $@
$(S)/maximize/maximize_test.html: $(S)/maximize/maximize_test.o
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
# Convenience targets
menu: $(S)/menu/menu_test.html
clipboard: $(S)/clipboard/clipboard_test.html
@ -444,9 +452,10 @@ fontenum: $(S)/fontenum/fontenum_test.html
textdecor: $(S)/textdecor/textdecor_test.html
bitmask: $(S)/bitmask/bitmask_test.html
regions: $(S)/regions/regions_test.html
maximize: $(S)/maximize/maximize_test.html
clean:
rm -f minimal_test.o minimal_test.html minimal_test.js minimal_test.wasm
rm -f $(S)/*/*.o $(S)/*/*.html $(S)/*/*.js $(S)/*/*.wasm
.PHONY: all clean menu clipboard filedialog layout aui toolbar grid dialog timer tree dataview htmlwin stc print dnd propgrid pickers collapsible listctrl infobar dataviewvirtual auinotebook wizard gridedit calendar gridrenderers printpreview bitmapbuttons specialized validators ownerdrawn popup xml wasmedge fontenum textdecor bitmask regions
.PHONY: all clean menu clipboard filedialog layout aui toolbar grid dialog timer tree dataview htmlwin stc print dnd propgrid pickers collapsible listctrl infobar dataviewvirtual auinotebook wizard gridedit calendar gridrenderers printpreview bitmapbuttons specialized validators ownerdrawn popup xml wasmedge fontenum textdecor bitmask regions maximize

View file

@ -55,7 +55,7 @@
</style>
</head>
<body style="margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #1a1a2e;">
<div id="main-window"></div>
<div id="main-window" style="width: 100vw; height: 100vh; position: absolute; top: 0; left: 0;"></div>
<div id="status">
<div id="status-text">Initializing...</div>
@ -79,8 +79,13 @@
var canvas = document.createElement('canvas');
canvas.id = 'canvas';
canvas.style.display = 'none';
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
// Set both CSS display size and internal pixel resolution
var width = window.innerWidth;
var height = window.innerHeight;
canvas.width = width;
canvas.height = height;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
canvas.oncontextmenu = function() { event.preventDefault(); };
canvas.addEventListener("webglcontextlost", function(e) {
showError('WebGL context lost. You will need to reload the page.');
@ -90,7 +95,7 @@
mainWindow.appendChild(canvas);
Module.canvas = canvas;
console.log('[KICAD] preRun complete, canvas created');
console.log('[KICAD] preRun complete, canvas created: ' + width + 'x' + height);
};
var onRuntimeInitialized = function() {

View file

@ -0,0 +1,179 @@
// Maximize Test - Tests wxFrame::Maximize() which KiCad uses
// This reproduces the bug where Maximize() returns a tiny window when
// GetScreenSize() returns incorrect values at startup.
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/display.h"
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
class MaximizeTestApp : public wxApp
{
public:
virtual bool OnInit() override;
};
class MaximizeTestFrame : public wxFrame
{
public:
MaximizeTestFrame();
private:
wxStaticText* m_sizeLabel;
wxStaticText* m_displayLabel;
void UpdateSizeDisplay();
void OnSize(wxSizeEvent& evt);
void OnMaximize(wxCommandEvent& evt);
void OnRestore(wxCommandEvent& evt);
wxDECLARE_EVENT_TABLE();
};
enum {
ID_MAXIMIZE = wxID_HIGHEST + 1,
ID_RESTORE
};
wxBEGIN_EVENT_TABLE(MaximizeTestFrame, wxFrame)
EVT_SIZE(MaximizeTestFrame::OnSize)
EVT_BUTTON(ID_MAXIMIZE, MaximizeTestFrame::OnMaximize)
EVT_BUTTON(ID_RESTORE, MaximizeTestFrame::OnRestore)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MaximizeTestApp);
bool MaximizeTestApp::OnInit()
{
if (!wxApp::OnInit())
return false;
// Create frame WITHOUT explicit size - uses wxDefaultSize
// This is what KiCad does
MaximizeTestFrame* frame = new MaximizeTestFrame();
// KiCad calls Maximize() after creation
frame->Maximize(true);
frame->Show(true);
return true;
}
MaximizeTestFrame::MaximizeTestFrame()
: wxFrame(nullptr, wxID_ANY, "Maximize Test",
wxDefaultPosition, wxDefaultSize) // No explicit size!
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
"Maximize Test\n\n"
"This test reproduces the KiCad startup issue.\n"
"The frame is created with wxDefaultSize and Maximize() is called.\n"
"If display size detection works, the window should be fullscreen.");
mainSizer->Add(desc, 0, wxALL, 10);
// Display info
wxStaticBoxSizer* infoBox = new wxStaticBoxSizer(wxVERTICAL, this, "Display Info");
m_displayLabel = new wxStaticText(this, wxID_ANY, "Display: querying...");
infoBox->Add(m_displayLabel, 0, wxALL, 5);
m_sizeLabel = new wxStaticText(this, wxID_ANY, "Window size: querying...");
infoBox->Add(m_sizeLabel, 0, wxALL, 5);
mainSizer->Add(infoBox, 0, wxEXPAND | wxALL, 10);
// Buttons
wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
btnSizer->Add(new wxButton(this, ID_MAXIMIZE, "Maximize"), 0, wxALL, 5);
btnSizer->Add(new wxButton(this, ID_RESTORE, "Restore"), 0, wxALL, 5);
mainSizer->Add(btnSizer, 0, wxALIGN_CENTER | wxALL, 10);
SetSizer(mainSizer);
// Query display info
wxDisplay display(wxDisplay::GetFromWindow(this));
wxRect geom = display.GetGeometry();
wxRect client = display.GetClientArea();
wxString displayInfo = wxString::Format(
"Display geometry: %dx%d, Client area: %dx%d",
geom.GetWidth(), geom.GetHeight(),
client.GetWidth(), client.GetHeight());
m_displayLabel->SetLabel(displayInfo);
#ifdef __EMSCRIPTEN__
EM_ASM({
console.log('[MAXIMIZE_TEST] Display geometry: ' + $0 + 'x' + $1);
console.log('[MAXIMIZE_TEST] Client area: ' + $2 + 'x' + $3);
}, geom.GetWidth(), geom.GetHeight(), client.GetWidth(), client.GetHeight());
#endif
// Update size display after creation
CallAfter(&MaximizeTestFrame::UpdateSizeDisplay);
#ifdef __EMSCRIPTEN__
EM_ASM({
console.log('[MAXIMIZE_TEST] Maximize test app started');
});
#endif
}
void MaximizeTestFrame::UpdateSizeDisplay()
{
wxSize size = GetSize();
wxSize clientSize = GetClientSize();
wxString sizeInfo = wxString::Format(
"Window size: %dx%d, Client: %dx%d, Maximized: %s",
size.GetWidth(), size.GetHeight(),
clientSize.GetWidth(), clientSize.GetHeight(),
IsMaximized() ? "YES" : "NO");
m_sizeLabel->SetLabel(sizeInfo);
#ifdef __EMSCRIPTEN__
EM_ASM({
console.log('[MAXIMIZE_TEST] Window size: ' + $0 + 'x' + $1);
console.log('[MAXIMIZE_TEST] Client size: ' + $2 + 'x' + $3);
console.log('[MAXIMIZE_TEST] Is maximized: ' + ($4 ? 'YES' : 'NO'));
// Test assertion: window should be larger than 100px if maximize worked
if ($0 < 100 || $1 < 100) {
console.error('[MAXIMIZE_TEST] FAIL: Window is too small! Expected fullscreen, got ' + $0 + 'x' + $1);
} else {
console.log('[MAXIMIZE_TEST] PASS: Window size is reasonable');
}
}, size.GetWidth(), size.GetHeight(),
clientSize.GetWidth(), clientSize.GetHeight(),
IsMaximized() ? 1 : 0);
#endif
}
void MaximizeTestFrame::OnSize(wxSizeEvent& evt)
{
evt.Skip();
CallAfter(&MaximizeTestFrame::UpdateSizeDisplay);
}
void MaximizeTestFrame::OnMaximize(wxCommandEvent& WXUNUSED(evt))
{
#ifdef __EMSCRIPTEN__
EM_ASM({ console.log('[MAXIMIZE_TEST] Maximize button clicked'); });
#endif
Maximize(true);
}
void MaximizeTestFrame::OnRestore(wxCommandEvent& WXUNUSED(evt))
{
#ifdef __EMSCRIPTEN__
EM_ASM({ console.log('[MAXIMIZE_TEST] Restore button clicked'); });
#endif
Maximize(false);
}