The IPlugResponsiveUI example demonstrates how to create plugin interfaces that dynamically adapt to different window sizes. This is essential for supporting resizable plugin windows and different screen sizes.
What This Example Demonstrates
Dynamic layout calculation based on window bounds
Runtime control repositioning on resize
Host-requested view configuration support (AUv3)
Using mLayoutFunc for responsive control placement
Key Implementation Details
Layout Function
The layout function recalculates control positions whenever the window is resized:
mLayoutFunc = [ & ]( IGraphics * pGraphics ) {
const IRECT b = pGraphics -> GetBounds ();
auto GetBounds = [ pGraphics ]( int ctrlIdx , const IRECT & b ) {
IRECT main = b . GetPadded ( - 5. f );
IRECT keys = main . FracRectVertical ( 0.25 , false );
IRECT scope = main . FracRectVertical ( 0.75 , true ). GetPadded ( - 10. f );
IRECT gain = scope . ReduceFromRight ( 100. f );
switch (ctrlIdx) {
case 1 : return keys;
case 2 : return gain;
case 3 : return scope;
case 0 : return b;
default : return pGraphics -> GetControl (ctrlIdx)-> GetRECT ();
}
};
// Layout controls on resize
if ( pGraphics -> NControls ()) {
for ( int ctrlIdx = 0 ; ctrlIdx < pGraphics -> NControls (); ctrlIdx ++ ) {
pGraphics -> GetControl (ctrlIdx)-> SetTargetAndDrawRECTs ( GetBounds (ctrlIdx, b));
}
return ;
}
pGraphics -> SetLayoutOnResize ( true );
pGraphics -> LoadFont ( "Roboto-Regular" , ROBOTO_FN);
pGraphics -> AttachPopupMenuControl ();
// Create controls
pGraphics -> AttachPanelBackground (COLOR_GRAY);
pGraphics -> AttachControl ( new IVKeyboardControl ( GetBounds ( 1 , b)));
pGraphics -> AttachControl ( new IVSliderControl ( GetBounds ( 2 , b), kGain));
pGraphics -> AttachControl ( new IVScopeControl <>( GetBounds ( 3 , b), "" ,
DEFAULT_STYLE . WithColor (kBG, COLOR_BLACK). WithColor (kFG, COLOR_WHITE)),
kCtrlTagScope);
};
Rectangle Utilities
FracRectVertical Divides a rectangle vertically into fractional parts
GetPadded Adds padding/margin to a rectangle
ReduceFromRight Carves out space from the right edge
GetBounds Returns the current window bounds
Host View Configuration
Support for host-requested resize (especially important for AUv3):
bool IPlugResponsiveUI :: OnHostRequestingSupportedViewConfiguration ( int width , int height )
{
return ConstrainEditorResize (width, height);
}
void IPlugResponsiveUI :: OnHostSelectedViewConfiguration ( int width , int height )
{
if ( GetUI ())
GetUI ()-> Resize (width, height, 1. f , true );
}
OnHostRequestingSupportedViewConfiguration is primarily used by AUv3 hosts to query if your plugin supports specific window dimensions.
Audio Processing with Visualization
The example includes a scope visualization that displays the audio output:
void IPlugResponsiveUI :: ProcessBlock ( sample ** inputs , sample ** outputs , int nFrames )
{
const double gain = GetParam (kGain)-> DBToAmp ();
for ( int s = 0 ; s < nFrames; s ++ ) {
outputs [ 0 ][s] = mOsc . Process () * gain;
outputs [ 1 ][s] = outputs [ 0 ][s];
}
mScopeSender . ProcessBlock (outputs, nFrames, kCtrlTagScope, 1 );
}
void IPlugResponsiveUI :: OnIdle ()
{
mScopeSender . TransmitData ( * this );
}
The IBufferSender sends audio data from the audio thread to the UI thread safely, where it’s displayed by the IVScopeControl.
Building Responsive Layouts
Enable layout on resize
Call pGraphics->SetLayoutOnResize(true) to enable dynamic relayout.
Define layout logic
Create a function that calculates control bounds based on current window size.
Handle existing controls
Check if controls already exist and update their positions using SetTargetAndDrawRECTs().
Implement view configuration
Override OnHostRequestingSupportedViewConfiguration and OnHostSelectedViewConfiguration for AUv3 support.
Common Layout Patterns
// Vertical split: keyboard at bottom, rest above
IRECT main = b . GetPadded ( - 5. f );
IRECT keys = main . FracRectVertical ( 0.25 , false ); // Bottom 25%
IRECT scope = main . FracRectVertical ( 0.75 , true ); // Top 75%
// Horizontal control on the right
IRECT gain = scope . ReduceFromRight ( 100. f );
// Adding padding
IRECT paddedScope = scope . GetPadded ( - 10. f );
Always check if controls exist before repositioning them. The layout function is called both during initial setup and on resize.
Web UI - Alternative approach using web technologies
SwiftUI - Native macOS/iOS UI with automatic layout