The last Chapter function of _InitWindowStack()
does a call to gDecorManager.AllocateDecorator(this)
.
Where,
DecorManager gDecorManager;
It is an global variable declared inside the file: src/servers/app/decorator/DecorManager.cpp
So gDecorManager.AllocateDecorator(this)
is calling the function AllocateDecorator
Diagrammatically representation of Decorator classes.
+----------------+
| Decorator |
+----------------+
|
|
V
+----------------+
| TabDecorator |
+----------------+
|
|
V
+----------------+
| DefaultDecorator|
+----------------+
|
|
V
+----------------+
| SATDecorator |
+----------------+
- Each box represents a class.
- Arrows indicate inheritance relationships, with the derived class pointing to its base class.
Decorator
is the base class, and each subsequent class inherits from the class above it.SATDecorator
is the most derived class, inheriting fromDefaultDecorator
, which inherits fromTabDecorator
, which in turn inherits fromDecorator
.
Let's explore this function:
#1 DecorManager :: AllocateDecorator(.)
It is defined in the file: src/servers/app/decorator/DecorManager.cpp
Decorator*
DecorManager::AllocateDecorator(Window* window)
{
// Create a new instance of the current decorator.
// Ownership is that of the caller
if (!fCurrentDecor) {
// We should *never* be here. If we do, it's a bug.
debugger("DecorManager::AllocateDecorator has a NULL decorator");
return NULL;
}
// Are we previewing a specific decorator?
if (window == fPreviewWindow) {
if (fPreviewDecor != NULL) {
return fPreviewDecor->AllocateDecorator(window->Desktop(),
window->GetDrawingEngine(), window->Frame(), window->Title(),
window->Look(), window->Flags());
} else {
fPreviewWindow = NULL;
}
}
return fCurrentDecor->AllocateDecorator(window->Desktop(),
window->GetDrawingEngine(), window->Frame(), window->Title(),
window->Look(), window->Flags());
}
This method is responsible for allocating a new decorator for a given window.
if (!fCurrentDecor) {
debugger("DecorManager::AllocateDecorator has a NULL decorator");
return NULL;
}
It checks if the fCurrentDecor
member variable is NULL
. If it is, it triggers a debugger breakpoint because having a NULL
decorator at this point indicates a bug in the program.
if (window == fPreviewWindow) {
if (fPreviewDecor != NULL) {
return fPreviewDecor->AllocateDecorator(window->Desktop(),
window->GetDrawingEngine(), window->Frame(), window->Title(),
window->Look(), window->Flags());
} else {
fPreviewWindow = NULL;
}
}
It checks if the given window is the same as the window currently being previewed (fPreviewWindow). If it is, and a preview decorator (fPreviewDecor
) is available, it allocates and returns a decorator specific to the preview settings. If fPreviewDecor
is NULL
, it sets fPreviewWindow
to NULL
to indicate that there's no longer a preview in progress.
return fCurrentDecor->AllocateDecorator(window->Desktop(),
window->GetDrawingEngine(), window->Frame(), window->Title(),
window->Look(), window->Flags());
If the window is not being previewed or if there's no specific preview decorator available, it allocates a decorator using the AllocateDecorator()
method of the current decorator (fCurrentDecor
). It passes parameters such as the desktop, drawing engine, frame, title, look, and flags of the window to the decorator for allocation.
#2 DecorAddOn :: AllocateDecorator(. . . . . .)
This function is defined in file: src/servers/app/decorator/DecorManager.cpp
Decorator*
DecorAddOn::AllocateDecorator(Desktop* desktop, DrawingEngine* engine,
BRect rect, const char* title, window_look look, uint32 flags)
{
if (!desktop->LockSingleWindow())
return NULL;
DesktopSettings settings(desktop);
Decorator* decorator;
decorator = _AllocateDecorator(settings, rect, desktop);
desktop->UnlockSingleWindow();
if (!decorator)
return NULL;
decorator->UpdateColors(settings);
if (decorator->AddTab(settings, title, look, flags) == NULL) {
delete decorator;
return NULL;
}
decorator->SetDrawingEngine(engine);
return decorator;
}
This method takes several parameters:
- desktop: A pointer to the desktop where the window is located.
- engine: A pointer to the drawing engine used for rendering graphics.
- rect: The bounding rectangle of the window.
- title: The title of the window.
- look: The appearance style of the window.
- flags: Additional flags specifying window behavior.
if (!desktop->LockSingleWindow())
return NULL;
It locks the desktop to ensure single-window access, preventing race conditions during the allocation process. If it fails to lock the desktop, it returns NULL
.
Race conditions occur when multiple threads or processes access shared resources concurrently without proper synchronization, leading to unpredictable outcomes. In this case, simultaneous attempts to lock or unlock the desktop by multiple threads or processes could result in race conditions.
To mitigate this, proper synchronization mechanisms, such as mutexes or semaphores, should be used to ensure that only one thread or process accesses the desktop at a time. This would prevent race conditions and ensure the correctness of the code.
DesktopSettings settings(desktop);
Decorator* decorator;
decorator = _AllocateDecorator(settings, rect, desktop);
desktop->UnlockSingleWindow();
- It creates a DesktopSettings object to capture the current settings of the desktop.
- It then calls the
_AllocateDecorator()
method to allocate a decorator based on the desktop settings, window dimensions, and the desktop itself. - After allocation, it unlocks the desktop.
if (!decorator)
return NULL;
If the allocation of the decorator fails, it returns NULL
decorator->UpdateColors(settings);
It updates the colors of the decorators based on the desktop settings.
if (decorator->AddTab(settings, title, look, flags) == NULL) {
delete decorator;
return NULL;
}
It attempts to add a tab to the decorator based on the window title, appearance style, and flags. If adding the tab fails, it deletes the decorator and returns NULL.
decorator->SetDrawingEngine(engine);
return decorator;
Finally, it sets the drawing engine for the decorator and returns the allocated decorator.
#3 DecorAddOn :: _AllocateDecorator(. . .)
This function is defined at: src/servers/app/decorator/DecorManager.cpp
Decorator*
DecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
Desktop* desktop)
{
return new (std::nothrow)SATDecorator(settings, rect, desktop);
}
This function creates a new instance of the SATDecorator class,
- settings: A reference to the DesktopSettings object containing the desktop's settings.
- rect: The bounding rectangle of the window.
- desktop: A pointer to the Desktop object representing the desktop where the window is located.
It uses the new (std::nothrow) syntax, which returns a null pointer if memory allocation fails instead of throwing an exception.
Finally, it returns a pointer to the newly created SATDecorator
object.
#4 SATDecorator::SATDecorator(. . .)
This constructor is defined in: src/servers/app/stackandtile/SATDecorator.cpp
SATDecorator::SATDecorator(DesktopSettings& settings, BRect frame,
Desktop* desktop)
:
DefaultDecorator(settings, frame, desktop)
{
}
The constructor initializes the SATDecorator
by calling the constructor of its base class, DefaultDecorator
, passing the provided parameters:
- settings: A reference to the
DesktopSettings
object containing the desktop's settings. - frame: The bounding rectangle of the window.
- desktop: A pointer to the Desktop object representing the desktop where the window is located.
The member initializer list : DefaultDecorator(settings, frame, desktop)
initializes the base class DefaultDecorator
with the provided parameters.
#5 DefaultDecorator::DefaultDecorator(. . .)
This constructor is defined at: src/servers/app/decorator/DefaultDecorator.cpp
DefaultDecorator::DefaultDecorator(DesktopSettings& settings, BRect rect,
Desktop* desktop)
:
TabDecorator(settings, rect, desktop)
{
// TODO: If the decorator was created with a frame too small, it should
// resize itself!
STRACE(("DefaultDecorator:\n"));
STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",
rect.left, rect.top, rect.right, rect.bottom));
}
The constructor initializes the DefaultDecorator by calling the constructor of its base class, TabDecorator, passing the provided parameters:
- settings: A reference to the DesktopSettings object containing the desktop's settings.
- rect: The bounding rectangle of the window.
- desktop: A pointer to the Desktop object representing the desktop where the window is located.
The member initializer list : TabDecorator(settings, rect, desktop)
initializes the base class TabDecorator
with the provided parameters.
#6 TabDecorator::TabDecorator(. . .)
This constructor is defined at: src/servers/app/decorators/TabDecorator.cpp
TabDecorator::TabDecorator(DesktopSettings& settings, BRect frame,
Desktop* desktop)
:
Decorator(settings, frame, desktop),
fOldMovingTab(0, 0, -1, -1)
{
STRACE(("TabDecorator:\n"));
STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",
frame.left, frame.top, frame.right, frame.bottom));
// TODO: If the decorator was created with a frame too small, it should
// resize itself!
}
The constructor initializes the TabDecorator
by calling the constructor of its base class, Decorator, passing the provided parameters:
- settings: A reference to the DesktopSettings object containing the desktop's settings.
- frame: The bounding rectangle of the window.
- desktop: A pointer to the Desktop object representing the desktop where the window is located.
The member initializer list : Decorator(settings, frame, desktop)
initializes the base class Decorator with the provided parameters.
It also initializes the member variable fOldMovingTab
with a BRect object initialized to (0, 0, -1, -1)
. This variable is used to track the previous position of a moving tab within the decorator.
#7 Decorator:: Decorator(. . .)
This constructor is defined in: src/servers/app/decorator/Decorator.cpp
Decorator::Decorator(DesktopSettings& settings, BRect frame,
Desktop* desktop)
:
fLocker("Decorator"),
fDrawingEngine(NULL),
fDrawState(),
fTitleBarRect(),
fFrame(frame),
fResizeRect(),
fBorderRect(),
fOutlineBorderRect(),
fLeftBorder(),
fTopBorder(),
fBottomBorder(),
fRightBorder(),
fLeftOutlineBorder(),
fTopOutlineBorder(),
fBottomOutlineBorder(),
fRightOutlineBorder(),
fBorderWidth(-1),
fOutlineBorderWidth(-1),
fTopTab(NULL),
fDesktop(desktop),
fFootprintValid(false)
{
memset(&fRegionHighlights, HIGHLIGHT_NONE, sizeof(fRegionHighlights));
}
The constructor initializes the Decorator
by initializing its member variables and objects:
- fLocker: Initializes the BLocker object with the name "Decorator", used for thread synchronization.
- fDrawingEngine: Initializes a pointer to the DrawingEngine object as NULL.
- fDrawState: Initializes the DrawState object.
- fTitleBarRect, fFrame, fResizeRect, fBorderRect, fOutlineBorderRect: Initialize BRect objects representing different regions of the decorator.
- fLeftBorder, fTopBorder, fBottomBorder, fRightBorder: Initialize BDimensions objects representing the dimensions of different borders of the decorator.
- fLeftOutlineBorder, fTopOutlineBorder, fBottomOutlineBorder, fRightOutlineBorder: Initialize BOutline objects representing the outline borders of the decorator.
- fBorderWidth, fOutlineBorderWidth: Initialize the widths of the borders.
- fTopTab: Initializes a pointer to the top tab object as NULL.
- fDesktop: Stores a pointer to the desktop where the decorator resides.
- fFootprintValid: Indicates whether the footprint of the decorator is valid or not.
memset(&fRegionHighlights, HIGHLIGHT_NONE, sizeof(fRegionHighlights)): Initializes the fRegionHighlights array with the HIGHLIGHT_NONE value.
#8 Decorator::UpdateColors(settings)
As we know that SATDecorator
is the most derived class. So it's UpdateColors(settings) will be called.
void
SATDecorator::UpdateColors(DesktopSettings& settings)
{
DefaultDecorator::UpdateColors(settings);
// Called during construction, and during any changes
fHighlightTabColor = tint_color(fFocusTabColor, B_DARKEN_2_TINT);
fHighlightTabColorLight = tint_color(fHighlightTabColor,
(B_LIGHTEN_MAX_TINT + B_LIGHTEN_2_TINT) / 2);
fHighlightTabColorBevel = tint_color(fHighlightTabColor, B_LIGHTEN_2_TINT);
fHighlightTabColorShadow= tint_color(fHighlightTabColor,
(B_DARKEN_1_TINT + B_NO_TINT) / 2);
}
The UpdateColors
function in the SATDecorator
class updates colors used within the decorator, leveraging color updates from its base class DefaultDecorator
and then customizing further.
DefaultDecorator::UpdateColors(settings);
: Calls the UpdateColors
function of the DefaultDecorator
class, ensuring that any color updates specific to DefaultDecorator
are applied first.
Then, it customizes some colors further:
fHighlightTabColor
: Calculates a new highlight color for tabs by darkening thefFocusTabColor
.fHighlightTabColorLight
: Adjusts the highlight tab color to be a lighter shade by applying a tint tofHighlightTabColor
.fHighlightTabColorBevel
: Adjusts the highlight tab color to create a bevel effect by applying a lighter tint.fHighlightTabColorShadow
: Adjusts the highlight tab color to create a shadow effect by applying a darker tint.
These color adjustments likely aim to create visual effects, such as shading and highlighting, to enhance the appearance of tabs within the decorator.
#9 DefaultDecorator::UpdateColors(settings)
Defined in: src/servers/app/decorator/DefaultDecorator.cpp
void
DefaultDecorator::UpdateColors(DesktopSettings& settings)
{
TabDecorator::UpdateColors(settings);
}
The UpdateColors
function in the DefaultDecorator
class is calling the UpdateColors
function of its immediate base class TabDecorator
.
#10 TabDecorator::UpdateColors(settings)
Defined in file at: src/servers/app/decorator/TabDecorator.cpp
void
TabDecorator::UpdateColors(DesktopSettings& settings)
{
// Desktop is write locked, so be quick about it.
fFocusFrameColor = settings.UIColor(B_WINDOW_BORDER_COLOR);
fFocusTabColor = settings.UIColor(B_WINDOW_TAB_COLOR);
fFocusTabColorLight = tint_color(fFocusTabColor,
(B_LIGHTEN_MAX_TINT + B_LIGHTEN_2_TINT) / 2);
fFocusTabColorBevel = tint_color(fFocusTabColor, B_LIGHTEN_2_TINT);
fFocusTabColorShadow = tint_color(fFocusTabColor,
(B_DARKEN_1_TINT + B_NO_TINT) / 2);
fFocusTextColor = settings.UIColor(B_WINDOW_TEXT_COLOR);
fNonFocusFrameColor = settings.UIColor(B_WINDOW_INACTIVE_BORDER_COLOR);
fNonFocusTabColor = settings.UIColor(B_WINDOW_INACTIVE_TAB_COLOR);
fNonFocusTabColorLight = tint_color(fNonFocusTabColor,
(B_LIGHTEN_MAX_TINT + B_LIGHTEN_2_TINT) / 2);
fNonFocusTabColorBevel = tint_color(fNonFocusTabColor, B_LIGHTEN_2_TINT);
fNonFocusTabColorShadow = tint_color(fNonFocusTabColor,
(B_DARKEN_1_TINT + B_NO_TINT) / 2);
fNonFocusTextColor = settings.UIColor(B_WINDOW_INACTIVE_TEXT_COLOR);
}
The UpdateColors
function in the TabDecorator
class updates various colors used by the decorator based on the provided DesktopSettings
.
fFocusFrameColor
: Sets the color for the frame of the decorator when it's in focus.
fFocusTabColor
: Sets the color for tabs when the decorator is in focus.
fFocusTabColorLight
: Calculates a lighter shade of the focus tab color.
fFocusTabColorBevel
: Calculates a bevel effect for the focus tab color.
fFocusTabColorShadow
: Calculates a shadow effect for the focus tab color.
fFocusTextColor
: Sets the text color for text within the decorator when it's in focus.
fNonFocusFrameColor
: Sets the color for the frame of the decorator when it's not in focus.
fNonFocusTabColor
: Sets the color for tabs when the decorator is not in focus.
fNonFocusTabColorLight
: Calculates a lighter shade of the non-focus tab color.
fNonFocusTabColorBevel
: Calculates a bevel effect for the non-focus tab color.
fNonFocusTabColorShadow
: Calculates a shadow effect for the non-focus tab color.
fNonFocusTextColor
: Sets the text color for text within the decorator when it's not in focus.