feat: persist floating panel layouts and wrap the compact transport

This commit is contained in:
Johannes Findeisen 2026-11-05 23:57:56 +01:00
commit 73e8bf09dc
9 changed files with 149 additions and 13 deletions

View file

@ -1237,6 +1237,35 @@ int main(int argc, char **argv)
close_result=XTC_OK; window.do_callback();
CHECK(!window.shown() && !window.transport_window()->shown() && !window.mixer_window()->shown());
}
reset();
{
std::string path="/tmp/xtc-panel-layout-"+std::to_string(getpid())+".conf";
{
MainWindow window(false,path.c_str());window.show();
window.detach_transport(true);window.detach_mixer(true);
window.transport_window()->resize(40,40,400,400);window.mixer_window()->resize(80,80,700,460);pump();
auto *group=dynamic_cast<Fl_Group *>(find(window.transport_window(),"Play")->parent());CHECK(group);
for(int i=0;i<group->children();++i) {
auto *widget=group->child(i);CHECK(widget->x()>=0 && widget->x()+widget->w()<=400);
CHECK(widget->y()+widget->h()<=window.transport_window()->h());
}
Fl::add_timeout(.05,[](void *) {auto *d=Fl::first_window();press(find(d,"Apply"));press(find(d,"Close"));});
window.show_preferences();xtc_settings saved{};CHECK(xtc_settings_load(&saved,path.c_str())==XTC_OK);
CHECK(saved.transport_detached && saved.mixer_detached && saved.transport_width==400 && saved.mixer_width==700);
saved.transport_x=30000;saved.transport_y=-30000;CHECK(xtc_settings_save(&saved,path.c_str())==XTC_OK);
window.do_callback();
}
{
MainWindow window(false,path.c_str());window.show();pump();
CHECK(window.transport_window() && window.transport_window()->shown());
CHECK(window.mixer_window() && window.mixer_window()->shown());
int sx,sy,sw,sh;Fl::screen_work_area(sx,sy,sw,sh,0);
CHECK(window.transport_window()->x()>=sx && window.transport_window()->x()+window.transport_window()->w()<=sx+sw);
CHECK(window.transport_window()->y()>=sy && window.transport_window()->y()+window.transport_window()->h()<=sy+sh);
window.detach_transport(false);window.detach_mixer(false);window.do_callback();
}
unlink(path.c_str());
}
if (failures != 0) return 1;
std::printf("GUI controls/errors/views/timers/cleanup passed: %u opens, %u closes.\n", opens, closes);
return 0;

View file

@ -13,13 +13,13 @@ int main(void)
CHECK(fd>=0);close(fd);unlink(path);
xtc_settings_defaults(&a);CHECK(xtc_settings_validate(&a)==XTC_OK);
b=a;CHECK(xtc_settings_load(&b,path)==XTC_ERR_NOT_FOUND);
strcpy(a.clap_paths,"~/space folder:/tmp/quoted\"name\\path");a.loop_enabled=1;a.follow_playhead=1;a.note_velocity=87;
strcpy(a.clap_paths,"~/space folder:/tmp/quoted\"name\\path");a.loop_enabled=1;a.follow_playhead=1;a.transport_detached=1;a.mixer_detached=1;a.transport_x=-30000;a.transport_width=400;a.note_velocity=87;
CHECK(xtc_settings_save(&a,path)==XTC_OK);CHECK(stat(path,&st)==0 && (st.st_mode&0777)==0600);
CHECK(xtc_settings_load(&b,path)==XTC_OK);CHECK(memcmp(&a,&b,sizeof(a))==0);
xtc_settings_schema(&n);
for(i=0;i<n;++i){CHECK(xtc_settings_get(&a,i,value,sizeof(value))==XTC_OK);CHECK(xtc_settings_set(&b,i,value)==XTC_OK);}
CHECK(memcmp(&a,&b,sizeof(a))==0);
{const char *bad[]={"[unknown]\n","[audio]\nchannels=3\n","[audio]\nchannels=1\nchannels=2\n","[audio]\nchannels=9999999999999999999999\n","[plugins]\nclap_paths=\"unterminated\n","[transport]\nloop_start=4000\nloop_end=2\n"};
{const char *bad[]={"[unknown]\n","[interface]\ntransport_width=399\n","[interface]\nmixer_detached=2\n","[audio]\nchannels=3\n","[audio]\nchannels=1\nchannels=2\n","[audio]\nchannels=9999999999999999999999\n","[plugins]\nclap_paths=\"unterminated\n","[transport]\nloop_start=4000\nloop_end=2\n"};
for(i=0;i<sizeof(bad)/sizeof(bad[0]);++i){f=fopen(path,"wb");CHECK(f);CHECK(fputs(bad[i],f)>=0);CHECK(fclose(f)==0);before=b;CHECK(xtc_settings_load(&b,path)==XTC_ERR_FORMAT);CHECK(memcmp(&before,&b,sizeof(b))==0);}}
f=fopen(path,"wb");CHECK(f);CHECK(fwrite(";x\0hidden",1,9,f)==9);fclose(f);CHECK(xtc_settings_load(&b,path)==XTC_ERR_FORMAT);
CHECK(xtc_settings_save(&a,path)==XTC_OK);b=a;b.loop_end=b.loop_start;CHECK(xtc_settings_save(&b,path)==XTC_ERR_INVALID_ARGUMENT);CHECK(xtc_settings_load(&b,path)==XTC_OK && b.loop_end==a.loop_end);