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:
- Call
AC_ResponderTemplateWidget<QWidget>ctor with (parent, flags, objectName) - Call
TULayoutViewdefault ctor atthis + 104 - Install all 4 TUWidgetLayoutView vtables
- Set minimum width to 150 pixels
- If parent != nullptr && manager != nullptr:
- Call
initActionManager(manager)
- Call
- Else:
- Store manager directly at offset +0x30
Destructor
Destruction sequence:
- Reset vtables to TUWidgetLayoutView vtables
- Destroy
TULayoutView::m_caption(QString at +0x108) - Destroy
TULayoutView::m_toolbarInfo(LAY_ToolbarInfo at +0x88) - Destroy
TULayoutView::m_internalName(QString at +0x70) - 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 classmetaObject()- 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
- "TUWidgetLayoutView" → returns
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 viewTUFrameLayoutView- Frame viewTUScrollViewLayoutView- Scrollable viewTUTextEditLayoutView- Text editing viewTUVBoxLayoutView- Vertical box layout view
These share the same getWidget() implementation (returning this - 104).
Analysis Methodology
This analysis was performed using:
- IDA Pro decompilation of constructor (
0x7ffa0be600a0) and destructor (0x7ffa0be60480) - Disassembly verification of exact byte offsets
- Cross-reference analysis of vtable addresses
- Examination of related methods (getWidget, triggerMenuChanged, etc.)
- Qt meta-object method analysis (qt_metacast, etc.)
References
toon_boom_layout.hpp- Header file with class declarationsTULayoutView_Toolbar_Integration.md- Toolbar integration documentationAC_Manager- Action manager class documentation