Skip to main content
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

1

Enable layout on resize

Call pGraphics->SetLayoutOnResize(true) to enable dynamic relayout.
2

Define layout logic

Create a function that calculates control bounds based on current window size.
3

Handle existing controls

Check if controls already exist and update their positions using SetTargetAndDrawRECTs().
4

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