toon-boom-extension-framework/docs/TUWidgetLayoutView_Analysis.md

9.9 KiB

TUWidgetLayoutView Class Analysis

This document contains the reverse engineering analysis of the TUWidgetLayoutView class from ToonBoomLayout.dll used in Toon Boom Harmony Premium and Storyboard Pro.

Overview

TUWidgetLayoutView is a concrete implementation that combines:

  • QWidget - for Qt UI rendering
  • AC_ResponderTemplateWidget - for action/responder chain handling
  • TULayoutView - for the Toon Boom layout system integration

This class serves as the base for most view types in Toon Boom's panel/window system.

Class Hierarchy

QObject
└── QWidget
    └── AC_ResponderTemplateWidget<QWidget>
        └── TUWidgetLayoutView
            └── [TULayoutView embedded at offset +104]

Note: TULayoutView is not a base class in the C++ inheritance sense but is embedded as a sub-object at offset +104. This is a form of composition that allows TULayoutView to have its own vtable and virtual methods.

Memory Layout (x64 MSVC)

Offset (hex) Offset (dec) Size Member
+0x00 +0 8 vptr (QObject)
+0x08 +8 8 QObjectData* d_ptr
+0x10 +16 8 vptr (QPaintDevice)
+0x18 +24 16 QWidget internal data
+0x28 +40 8 vptr (AC_ResponderTemplateWidget)
+0x30 +48 8 AC_Manager* m_actionManager
+0x38 +56 24 QString m_responderIdentity
+0x50 +80 24 QString m_responderDescription
+0x68 +104 8 vptr (TULayoutView) - TULayoutView starts here
+0x70 +112 24 QString m_internalName (TULayoutView)
+0x88 +136 104 LAY_ToolbarInfo m_toolbarInfo (TULayoutView)
+0xF0 +240 16 AC_Menu* m_menuByType[2] (TULayoutView)
+0x100 +256 1+7 bool m_initializedFromCopy + padding (TULayoutView)
+0x108 +264 24 QString m_caption (TULayoutView)

Total size: 0x120 (288 bytes)

VTable Structure

TUWidgetLayoutView has 4 vtables due to multiple inheritance:

vptr[0] at +0x00: QObject vtable

Contains all QObject and QWidget virtual methods including:

  • metaObject(), qt_metacast(), qt_metacall()
  • event(), eventFilter()
  • paintEvent(), mousePressEvent(), etc.

Address in ToonBoomLayout.dll: ??_7TUWidgetLayoutView@@6BQObject@@@

vptr[1] at +0x10: QPaintDevice vtable

Contains QPaintDevice virtuals:

  • devType()
  • paintEngine()
  • metric()

Address in ToonBoomLayout.dll: ??_7TUWidgetLayoutView@@6BQPaintDevice@@@

vptr[2] at +0x28: AC_ResponderTemplateWidget vtable

Contains AC_Responder interface methods:

  • perform(AC_ActionInfo*)
  • performDownToChildren(AC_ActionInfo*)
  • parentResponder()
  • proxyResponder()
  • acceptsFirstResponder()
  • becomeFirstResponder()
  • resignFirstResponder()
  • handleShortcuts()
  • shouldReceiveMessages()
  • responderIdentity()
  • responderDescription()
  • actionManager()
  • handleEvent(QEvent*)

Address in ToonBoomLayout.dll: ??_7TUWidgetLayoutView@@6B?$AC_ResponderTemplateWidget@VQWidget@@@@@

vptr[3] at +0x68: TULayoutView vtable

Contains TULayoutView virtual methods (32 slots total):

Slot Method TUWidgetLayoutView Implementation
0 ~TULayoutView() Thunk to TUWidgetLayoutView dtor
1 widget() _purecall (pure virtual)
2 initiate(QWidget*) TULayoutView::initiate
3 getWidget() const Returns (this - 104)
4 getWidget() Returns (this - 104)
5 getParentHolderWidget() const TULayoutView impl
6 getParentHolderWidget() TULayoutView impl
7 hasMenu() TULayoutView impl
8 setMenu(AC_Manager*, const char*, MenuType) TULayoutView impl
9 setMenu(AC_Menu*, MenuType) TULayoutView impl
10 menu(MenuType) TULayoutView impl
11 toolbar() TULayoutView impl
12 setToolbarInfo(LAY_ToolbarInfo&) TULayoutView impl
13 connectView() Empty
14 disconnectView() Empty
15 initializedFromCopy() TULayoutView impl
16 getCaption(bool) TULayoutView impl
17 getDynamicTextForCaption() TULayoutView impl
18 wantEditionStack() Returns false
19 displayName() TULayoutView impl
20 compositeChanged(QString&) Empty
21 dropOverComposite(QDropEvent*, QString&) Empty
22 wantComposites() Returns false
23 initActionManager(AC_Manager*) Empty
24 wantDisplaySelector() Returns false
25 isUsingDefaultDisplay() Returns false
26 storeViewPreferences(QDomElement&) Returns false
27 loadViewPreferences(QDomElement&) Empty
28 cshHelpId() TULayoutView impl
29 triggerMenuChanged() Emits menuChanged() signal
30 copy(TULayoutView&) TULayoutView impl
31 isTULayoutView() Empty (RTTI marker)

Address in ToonBoomLayout.dll: ??_7TUWidgetLayoutView@@6BTULayoutView@@@

Key Methods

Constructor

TUWidgetLayoutView(
    AC_Manager* manager,         // Action manager (stored at +0x30)
    const QString& objectName,   // Qt object name
    QWidget* parent,             // Parent widget
    const char* className,       // Class name string
    Qt::WindowFlags flags        // Window flags
)

Construction sequence:

  1. Call AC_ResponderTemplateWidget<QWidget> ctor with (parent, flags, objectName)
  2. Call TULayoutView default ctor at this + 104
  3. Install all 4 TUWidgetLayoutView vtables
  4. Set minimum width to 150 pixels
  5. If parent != nullptr && manager != nullptr:
    • Call initActionManager(manager)
  6. Else:
    • Store manager directly at offset +0x30

Destructor

Destruction sequence:

  1. Reset vtables to TUWidgetLayoutView vtables
  2. Destroy TULayoutView::m_caption (QString at +0x108)
  3. Destroy TULayoutView::m_toolbarInfo (LAY_ToolbarInfo at +0x88)
  4. Destroy TULayoutView::m_internalName (QString at +0x70)
  5. Jump to AC_ResponderTemplateWidget<QWidget>::~AC_ResponderTemplateWidget

getWidget()

QWidget* getWidget() {
    return reinterpret_cast<QWidget*>(
        reinterpret_cast<char*>(this) - 104);
}

Called from TULayoutView* context (at +104), returns the containing QWidget* (at +0).

triggerMenuChanged()

void triggerMenuChanged() {
    // 'this' is TULayoutView* at +104
    // Emit signal on containing TUWidgetLayoutView (this - 104)
    TUWidgetLayoutView* widget = (TUWidgetLayoutView*)((char*)this - 104);
    widget->menuChanged();
}

mousePressEvent()

void mousePressEvent(QMouseEvent* event) {
    QWidget::mousePressEvent(event);
    if (!event->isAccepted()) {
        event->accept();
        setFocus(Qt::MouseFocusReason);  // Focus reason = 7
    }
}

Qt Meta-Object System

TUWidgetLayoutView participates in the Qt meta-object system:

  • staticMetaObject - Static meta-object for the class
  • metaObject() - Returns &staticMetaObject (or dynamic for QML)
  • qt_metacast(const char* className):
    • "TUWidgetLayoutView" → returns this
    • "TULayoutView" → returns this + 104
    • Otherwise → delegates to AC_ResponderTemplateWidget::qt_metacast
  • tr() - Static translation method

Signals

  • menuChanged() - Emitted when view menu changes (slot 0 in staticMetaObject signals)

Exported Symbols

From ToonBoomLayout.dll:

Symbol Description
??0TUWidgetLayoutView@@QEAA@...@Z Constructor
??1TUWidgetLayoutView@@UEAA@XZ Destructor
?getWidget@TUWidgetLayoutView@@UEAAPEAVQWidget@@XZ Non-const getWidget
?getWidget@TUWidgetLayoutView@@UEBAPEBVQWidget@@XZ Const getWidget
?mousePressEvent@TUWidgetLayoutView@@MEAAXPEAVQMouseEvent@@@Z Mouse handler
?triggerMenuChanged@TUWidgetLayoutView@@MEAAXXZ Trigger menu signal
?menuChanged@TUWidgetLayoutView@@QEAAXXZ Signal implementation
?metaObject@TUWidgetLayoutView@@UEBAPEBUQMetaObject@@XZ Meta-object
?qt_metacast@TUWidgetLayoutView@@UEAAPEAXPEBD@Z Runtime cast
?qt_metacall@TUWidgetLayoutView@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z Meta-call
?qt_static_metacall@TUWidgetLayoutView@@...@Z Static meta-call
?tr@TUWidgetLayoutView@@SA?AVQString@@PEBD0H@Z Translation

Helper Functions

The header provides inline helper functions for pointer conversion:

// Get TULayoutView* from TUWidgetLayoutView*
TULayoutView* TUWidgetLayoutView_getLayoutView(TUWidgetLayoutView* widget);

// Get TUWidgetLayoutView* from TULayoutView* (must be embedded in TUWidgetLayoutView)
TUWidgetLayoutView* TULayoutView_getWidgetLayoutView(TULayoutView* view);

// Get QWidget* from TUWidgetLayoutView* (same address, different type)
QWidget* TUWidgetLayoutView_getWidget(TUWidgetLayoutView* widget);

// Get AC_Manager* from TULayoutView* embedded in TUWidgetLayoutView
AC_Manager* TULayoutView_getActionManager(TULayoutView* view);

Subclasses

Several classes in ToonBoomLayout.dll inherit from TUWidgetLayoutView:

  • TUCanvasViewLayoutView - Canvas/drawing view
  • TUFrameLayoutView - Frame view
  • TUScrollViewLayoutView - Scrollable view
  • TUTextEditLayoutView - Text editing view
  • TUVBoxLayoutView - Vertical box layout view

These share the same getWidget() implementation (returning this - 104).

Analysis Methodology

This analysis was performed using:

  1. IDA Pro decompilation of constructor (0x7ffa0be600a0) and destructor (0x7ffa0be60480)
  2. Disassembly verification of exact byte offsets
  3. Cross-reference analysis of vtable addresses
  4. Examination of related methods (getWidget, triggerMenuChanged, etc.)
  5. Qt meta-object method analysis (qt_metacast, etc.)

References

  • toon_boom_layout.hpp - Header file with class declarations
  • TULayoutView_Toolbar_Integration.md - Toolbar integration documentation
  • AC_Manager - Action manager class documentation