diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index f6808f1981..89ea027788 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -110,6 +110,7 @@ enum { AS_SET_SYSTEM_FONT, AS_GET_SYSTEM_FONTS, AS_GET_SYSTEM_DEFAULT_FONT, + AS_SYSTEM_FONT_CHANGED, AS_GET_FONT_LIST_REVISION, AS_GET_FAMILY_AND_STYLES, diff --git a/src/servers/app/Decorator.cpp b/src/servers/app/Decorator.cpp index 47c6daeb78..e87e74ca45 100644 --- a/src/servers/app/Decorator.cpp +++ b/src/servers/app/Decorator.cpp @@ -21,7 +21,7 @@ /*! \brief Constructor Does general initialization of internal data members and creates a colorset - object. + object. \param rect Size of client area \param wlook style of window look. See Window.h @@ -56,7 +56,7 @@ Decorator::Decorator(DesktopSettings& settings, BRect rect, window_look look, /*! \brief Destructor - + Frees the color set and the title string */ Decorator::~Decorator() @@ -100,14 +100,11 @@ Decorator::SetFlags(uint32 flags, BRegion* updateRegion) } -/*! \brief Sets the decorator's font - \param font The new font object to copy from +/*! \brief Called whenever the system fonts are changed. */ void -Decorator::SetFont(ServerFont *font) +Decorator::FontsChanged(DesktopSettings& settings, BRegion* updateRegion) { - if (font) - fDrawState.SetFont(*font); } @@ -123,7 +120,7 @@ Decorator::SetLook(DesktopSettings& settings, window_look look, /*! \brief Sets the close button's value. - + Note that this does not update the button's look - it just updates the internal button value @@ -139,7 +136,7 @@ Decorator::SetClose(bool pressed) } /*! \brief Sets the minimize button's value. - + Note that this does not update the button's look - it just updates the internal button value @@ -155,7 +152,7 @@ Decorator::SetMinimize(bool pressed) } /*! \brief Sets the zoom button's value. - + Note that this does not update the button's look - it just updates the internal button value @@ -271,7 +268,7 @@ Decorator::GetSizeLimits(int32* minWidth, int32* minHeight, int32* maxWidth, /*! \brief Changes the focus value of the decorator - + While this call will not update the screen, it will affect how future updates work. @@ -343,7 +340,7 @@ Decorator::Clicked(BPoint point, int32 buttons, int32 modifiers) /*! \brief Moves the decorator frame and all default rectangles - + If a subclass implements this method, be sure to call Decorator::MoveBy to ensure that internal members are also updated. All members of the Decorator class are automatically moved in this method @@ -359,7 +356,7 @@ Decorator::MoveBy(float x, float y) /*! \brief Moves the decorator frame and all default rectangles - + If a subclass implements this method, be sure to call Decorator::MoveBy to ensure that internal members are also updated. All members of the Decorator class are automatically moved in this method @@ -381,11 +378,11 @@ Decorator::MoveBy(BPoint offset) /*! \brief Resizes the decorator frame - + This is a required function for subclasses to implement - the default does nothing. Note that window resize flags should be followed and fFrame should be resized accordingly. It would also be a wise idea to ensure that the - window's rectangles are not inverted. + window's rectangles are not inverted. \param x x offset \param y y offset @@ -512,7 +509,7 @@ Decorator::_DrawFrame(BRect rect) /*! \brief Actually draws the tab - + This function is called when the tab itself needs drawn. Other items, like the window title or buttons, should not be drawn here. @@ -553,7 +550,7 @@ Decorator::_DrawTitle(BRect rect) /*! \brief Actually draws the zoom button - + Unless a subclass has a particularly large button, it is probably unnecessary to check the update rectangle. @@ -566,7 +563,7 @@ Decorator::_DrawZoom(BRect rect) /*! \brief Actually draws the minimize button - + Unless a subclass has a particularly large button, it is probably unnecessary to check the update rectangle. diff --git a/src/servers/app/Decorator.h b/src/servers/app/Decorator.h index ea191dca13..1bb978e8b6 100644 --- a/src/servers/app/Decorator.h +++ b/src/servers/app/Decorator.h @@ -32,14 +32,14 @@ enum click_type { DEC_DRAG, DEC_MOVETOBACK, DEC_SLIDETAB, - + DEC_RESIZE, CLICK_RESIZE_L, - CLICK_RESIZE_T, + CLICK_RESIZE_T, CLICK_RESIZE_R, CLICK_RESIZE_B, CLICK_RESIZE_LT, - CLICK_RESIZE_RT, + CLICK_RESIZE_RT, CLICK_RESIZE_LB, CLICK_RESIZE_RB }; @@ -53,8 +53,9 @@ public: void SetDrawingEngine(DrawingEngine *driver); inline DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; } - void SetFont(ServerFont *font); + virtual void FontsChanged(DesktopSettings& settings, + BRegion* updateRegion = NULL); virtual void SetLook(DesktopSettings& settings, window_look look, BRegion* updateRegion = NULL); virtual void SetFlags(uint32 flags, @@ -74,7 +75,7 @@ public: BRect BorderRect() const; BRect TabRect() const; - + bool GetClose(); bool GetMinimize(); bool GetZoom(); @@ -97,7 +98,7 @@ public: virtual void ResizeBy(BPoint offset, BRegion* dirty) = 0; /*! \return true if tab location updated, false if out of bounds - or unsupported + or unsupported */ virtual bool SetTabLocation(float location, BRegion* /*updateRegion*/ = NULL) diff --git a/src/servers/app/DefaultDecorator.cpp b/src/servers/app/DefaultDecorator.cpp index 70cfad13fe..b0bb79095e 100644 --- a/src/servers/app/DefaultDecorator.cpp +++ b/src/servers/app/DefaultDecorator.cpp @@ -90,7 +90,7 @@ DefaultDecorator::DefaultDecorator(DesktopSettings& settings, BRect rect, fTabLocation(0.0), fLastClicked(0) { - DefaultDecorator::SetLook(settings, look); + _UpdateFont(settings); // common colors to both focus and non focus state fFrameColors[0] = (rgb_color){ 152, 152, 152, 255 }; @@ -159,6 +159,27 @@ DefaultDecorator::SetTitle(const char* string, BRegion* updateRegion) } +void +DefaultDecorator::FontsChanged(DesktopSettings& settings, BRegion* updateRegion) +{ + // get previous extent + if (updateRegion != NULL) { + BRegion extent; + GetFootprint(&extent); + updateRegion->Include(&extent); + } + + _UpdateFont(settings); + _DoLayout(); + + if (updateRegion != NULL) { + BRegion extent; + GetFootprint(&extent); + updateRegion->Include(&extent); + } +} + + void DefaultDecorator::SetLook(DesktopSettings& settings, window_look look, BRegion* updateRegion) @@ -172,19 +193,9 @@ DefaultDecorator::SetLook(DesktopSettings& settings, window_look look, updateRegion->Include(&extent); } - ServerFont font; - if (look == B_FLOATING_WINDOW_LOOK || look == kLeftTitledWindowLook) { - settings.GetDefaultPlainFont(font); - if (look == kLeftTitledWindowLook) - font.SetRotation(90.0f); - } else - settings.GetDefaultBoldFont(font); + fLook = look; - font.SetFlags(B_FORCE_ANTIALIASING); - font.SetSpacing(B_STRING_SPACING); - SetFont(&font); - - Decorator::SetLook(settings, look, updateRegion); + _UpdateFont(settings); _DoLayout(); if (updateRegion != NULL) { @@ -435,6 +446,9 @@ DefaultDecorator::GetSettings(BMessage* settings) const if (!fTabRect.IsValid()) return false; + if (settings->AddRect("tab frame", fTabRect) != B_OK) + return false; + return settings->AddFloat("tab location", (float)fTabOffset) == B_OK; } @@ -669,8 +683,8 @@ DefaultDecorator::_DoLayout() fMinTabSize += offset + size; // fMaxTabSize contains fMinWidth + the width required for the title - fMaxTabSize = fDrawingEngine ? - ceilf(fDrawingEngine->StringWidth(Title(), strlen(Title()), + fMaxTabSize = fDrawingEngine + ? ceilf(fDrawingEngine->StringWidth(Title(), strlen(Title()), fDrawState.Font())) : 0.0; if (fMaxTabSize > 0.0) fMaxTabSize += fTextOffset; @@ -1098,6 +1112,23 @@ DefaultDecorator::_SetColors() } +void +DefaultDecorator::_UpdateFont(DesktopSettings& settings) +{ + ServerFont font; + if (fLook == B_FLOATING_WINDOW_LOOK || fLook == kLeftTitledWindowLook) { + settings.GetDefaultPlainFont(font); + if (fLook == kLeftTitledWindowLook) + font.SetRotation(90.0f); + } else + settings.GetDefaultBoldFont(font); + + font.SetFlags(B_FORCE_ANTIALIASING); + font.SetSpacing(B_STRING_SPACING); + fDrawState.SetFont(font); +} + + void DefaultDecorator::_DrawButtonBitmap(ServerBitmap* bitmap, BRect rect) { diff --git a/src/servers/app/DefaultDecorator.h b/src/servers/app/DefaultDecorator.h index 84b43bdbde..1d754964a0 100644 --- a/src/servers/app/DefaultDecorator.h +++ b/src/servers/app/DefaultDecorator.h @@ -25,6 +25,8 @@ public: virtual void SetTitle(const char* string, BRegion* updateRegion = NULL); + virtual void FontsChanged(DesktopSettings& settings, + BRegion* updateRegion); virtual void SetLook(DesktopSettings& settings, window_look look, BRegion* updateRegion = NULL); @@ -68,6 +70,7 @@ protected: virtual void _SetColors(); private: + void _UpdateFont(DesktopSettings& settings); void _DrawButtonBitmap(ServerBitmap* bitmap, BRect rect); void _DrawBlendedRect(DrawingEngine *engine, diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 5f1f36a058..b8de730bff 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -709,8 +709,7 @@ Desktop::_ActivateApp(team_id team) } -/*! - \brief Send a quick (no attachments) message to all applications +/*! \brief Send a quick (no attachments) message to all applications. Quite useful for notification for things like server shutdown, system color changes, etc. @@ -726,6 +725,20 @@ Desktop::BroadcastToAllApps(int32 code) } +/*! \brief Send a quick (no attachments) message to all windows. +*/ +void +Desktop::BroadcastToAllWindows(int32 code) +{ + AutoWriteLocker _(fWindowLock); + + for (Window* window = fAllWindows.FirstWindow(); window != NULL; + window = window->NextWindow(kAllWindowList)) { + window->ServerWindow()->PostMessage(code); + } +} + + // #pragma mark - @@ -1967,22 +1980,12 @@ Desktop::ResizeWindowBy(Window* window, float x, float y) bool Desktop::SetWindowTabLocation(Window* window, float location) { - if (!LockAllWindows()) - return false; + AutoWriteLocker _(fWindowLock); BRegion dirty; bool changed = window->SetTabLocation(location, dirty); - - if (changed && window->IsVisible() && dirty.CountRects() > 0) { - BRegion stillAvailableOnScreen; - _RebuildClippingForAllWindows(stillAvailableOnScreen); - _SetBackground(stillAvailableOnScreen); - - _WindowChanged(window); - _TriggerWindowRedrawing(dirty); - } - - UnlockAllWindows(); + if (changed) + _RebuildAndRedrawAfterWindowChange(window, dirty); return changed; } @@ -1991,23 +1994,12 @@ Desktop::SetWindowTabLocation(Window* window, float location) bool Desktop::SetWindowDecoratorSettings(Window* window, const BMessage& settings) { - // TODO: almost exact code duplication to above function... - - if (!LockAllWindows()) - return false; + AutoWriteLocker _(fWindowLock); BRegion dirty; bool changed = window->SetDecoratorSettings(settings, dirty); - - if (changed && window->IsVisible() && dirty.CountRects() > 0) { - BRegion stillAvailableOnScreen; - _RebuildClippingForAllWindows(stillAvailableOnScreen); - _SetBackground(stillAvailableOnScreen); - - _TriggerWindowRedrawing(dirty); - } - - UnlockAllWindows(); + if (changed) + _RebuildAndRedrawAfterWindowChange(window, dirty); return changed; } @@ -2211,32 +2203,36 @@ Desktop::RemoveWindowFromSubset(Window* subset, Window* window) void -Desktop::SetWindowLook(Window *window, window_look newLook) +Desktop::FontsChanged(Window* window) +{ + AutoWriteLocker _(fWindowLock); + + BRegion dirty; + window->FontsChanged(&dirty); + + _RebuildAndRedrawAfterWindowChange(window, dirty); +} + + +void +Desktop::SetWindowLook(Window* window, window_look newLook) { if (window->Look() == newLook) return; - if (!LockAllWindows()) - return; + AutoWriteLocker _(fWindowLock); BRegion dirty; window->SetLook(newLook, &dirty); // TODO: test what happens when the window // finds out it needs to resize itself... - BRegion stillAvailableOnScreen; - _RebuildClippingForAllWindows(stillAvailableOnScreen); - _SetBackground(stillAvailableOnScreen); - _WindowChanged(window); - - _TriggerWindowRedrawing(dirty); - - UnlockAllWindows(); + _RebuildAndRedrawAfterWindowChange(window, dirty); } void -Desktop::SetWindowFeel(Window *window, window_feel newFeel) +Desktop::SetWindowFeel(Window* window, window_feel newFeel) { if (window->Feel() == newFeel) return; @@ -2340,43 +2336,26 @@ Desktop::SetWindowFlags(Window *window, uint32 newFlags) if (window->Flags() == newFlags) return; - if (!LockAllWindows()) - return; + AutoWriteLocker _(fWindowLock); BRegion dirty; window->SetFlags(newFlags, &dirty); // TODO: test what happens when the window // finds out it needs to resize itself... - BRegion stillAvailableOnScreen; - _RebuildClippingForAllWindows(stillAvailableOnScreen); - _SetBackground(stillAvailableOnScreen); - _WindowChanged(window); - - _TriggerWindowRedrawing(dirty); - - UnlockAllWindows(); + _RebuildAndRedrawAfterWindowChange(window, dirty); } void Desktop::SetWindowTitle(Window *window, const char* title) { - if (!LockAllWindows()) - return; + AutoWriteLocker _(fWindowLock); BRegion dirty; window->SetTitle(title, dirty); - if (window->IsVisible() && dirty.CountRects() > 0) { - BRegion stillAvailableOnScreen; - _RebuildClippingForAllWindows(stillAvailableOnScreen); - _SetBackground(stillAvailableOnScreen); - - _TriggerWindowRedrawing(dirty); - } - - UnlockAllWindows(); + _RebuildAndRedrawAfterWindowChange(window, dirty); } @@ -2755,3 +2734,20 @@ Desktop::_SetBackground(BRegion& background) } } } + + +//! The all window lock must be held when calling this function. +void +Desktop::_RebuildAndRedrawAfterWindowChange(Window* window, BRegion& dirty) +{ + if (!window->IsVisible() || dirty.CountRects() == 0) + return; + + BRegion stillAvailableOnScreen; + _RebuildClippingForAllWindows(stillAvailableOnScreen); + _SetBackground(stillAvailableOnScreen); + _WindowChanged(window); + + _TriggerWindowRedrawing(dirty); +} + diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 9888f862a7..f5165ad53b 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -69,6 +69,7 @@ class Desktop : public MessageLooper, public ScreenOwner { ::EventDispatcher& EventDispatcher() { return fEventDispatcher; } void BroadcastToAllApps(int32 code); + void BroadcastToAllWindows(int32 code); // Screen and drawing related methods @@ -142,6 +143,8 @@ class Desktop : public MessageLooper, public ScreenOwner { void RemoveWindowFromSubset(Window* subset, Window* window); + void FontsChanged(Window* window); + void SetWindowLook(Window* window, window_look look); void SetWindowFeel(Window* window, window_feel feel); void SetWindowFlags(Window* window, uint32 flags); @@ -240,6 +243,8 @@ class Desktop : public MessageLooper, public ScreenOwner { void _TriggerWindowRedrawing( BRegion& newDirtyRegion); void _SetBackground(BRegion& background); + void _RebuildAndRedrawAfterWindowChange( + Window* window, BRegion& dirty); void _UpdateFloating(int32 previousWorkspace = -1, int32 nextWorkspace = -1, diff --git a/src/servers/app/DesktopSettings.cpp b/src/servers/app/DesktopSettings.cpp index 86301472af..57cf7a4fbd 100644 --- a/src/servers/app/DesktopSettings.cpp +++ b/src/servers/app/DesktopSettings.cpp @@ -235,13 +235,13 @@ DesktopSettingsPrivate::_Load() bool subpix; if (settings.FindBool("subpixel antialiasing", &subpix) == B_OK) gSubpixelAntialiasing = subpix; - + int8 averageWeight; if (settings.FindInt8("subpixel average weight", &averageWeight) == B_OK) { gSubpixelAverageWeight = averageWeight; } - + bool subpixelOrdering; if (settings.FindBool("subpixel ordering", &subpixelOrdering) == B_OK) { @@ -778,6 +778,7 @@ void LockedDesktopSettings::SetDefaultBoldFont(const ServerFont &font) { fSettings->SetDefaultBoldFont(font); + fDesktop->BroadcastToAllWindows(AS_SYSTEM_FONT_CHANGED); } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index e03321d24e..04f86cd1be 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1082,6 +1082,13 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) break; } + case AS_SYSTEM_FONT_CHANGED: + { + fDesktop->FontsChanged(fWindow); + // TODO: tell client about this, too, and relayout... + break; + } + case AS_REDRAW: // Nothing to do here - the redraws are actually handled by looking // at the fRedrawRequested member variable in _MessageLooper(). @@ -3692,6 +3699,7 @@ ServerWindow::_MessageNeedsAllWindowsLocked(uint32 code) const case AS_WINDOW_MOVE: case AS_WINDOW_RESIZE: case AS_SET_SIZE_LIMITS: + case AS_SYSTEM_FONT_CHANGED: case AS_SET_DECORATOR_SETTINGS: case AS_GET_MOUSE: case AS_DIRECT_WINDOW_SET_FULLSCREEN: diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp index 90f789984d..42512a28cf 100644 --- a/src/servers/app/Window.cpp +++ b/src/servers/app/Window.cpp @@ -1287,6 +1287,17 @@ Window::GetDecoratorSettings(BMessage* settings) } +void +Window::FontsChanged(BRegion* updateRegion) +{ + if (fDecorator != NULL) { + DesktopSettings settings(fDesktop); + fDecorator->FontsChanged(settings, updateRegion); + fBorderRegionValid = false; + } +} + + void Window::SetLook(window_look look, BRegion* updateRegion) { diff --git a/src/servers/app/Window.h b/src/servers/app/Window.h index a8cfd2b366..6071193480 100644 --- a/src/servers/app/Window.h +++ b/src/servers/app/Window.h @@ -177,6 +177,8 @@ public: void HighlightDecorator(bool active); + void FontsChanged(BRegion* updateRegion); + void SetLook(window_look look, BRegion* updateRegion); void SetFeel(window_feel feel); void SetFlags(uint32 flags, BRegion* updateRegion);