From f3e8ed4d4876abc202ca905fa8b88a63771b9003 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 21 Nov 2017 20:59:27 +0100 Subject: [PATCH] app_server: Implement screen changed hooks and notifications. The ScreenOwner interface gets an additional ScreenChanged() hook. It is implemented in the Desktop class to automatically set the preferred screen mode on the changed screen. The HWInterfaceListener, previously only used by the downstream DrawingEngine, gets an additional ScreenChanged() hook as well to inform an upstream client of a changed screen. The ScreenManager ties these two mechanisms together. --- src/servers/app/Desktop.cpp | 13 ++++++ src/servers/app/Desktop.h | 1 + src/servers/app/ScreenManager.cpp | 55 ++++++++++++++++++++++++- src/servers/app/ScreenManager.h | 10 ++++- src/servers/app/drawing/HWInterface.cpp | 13 ++++++ src/servers/app/drawing/HWInterface.h | 7 +++- 6 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 340df6db54..962a6e1647 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -3493,6 +3493,19 @@ Desktop::_ResumeDirectFrameBufferAccess() } +void +Desktop::ScreenChanged(Screen* screen) +{ + AutoWriteLocker windowLocker(fWindowLock); + + AutoWriteLocker screenLocker(fScreenLock); + screen->SetPreferredMode(); + screenLocker.Unlock(); + + _ScreenChanged(screen); +} + + void Desktop::_ScreenChanged(Screen* screen) { diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index f46b4c86a2..dc7b92c53d 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -145,6 +145,7 @@ public: // ScreenOwner implementation virtual void ScreenRemoved(Screen* screen) {} virtual void ScreenAdded(Screen* screen) {} + virtual void ScreenChanged(Screen* screen); virtual bool ReleaseScreen(Screen* screen) { return false; } // Workspace methods diff --git a/src/servers/app/ScreenManager.cpp b/src/servers/app/ScreenManager.cpp index 1bc38c6a99..b70d6e853c 100644 --- a/src/servers/app/ScreenManager.cpp +++ b/src/servers/app/ScreenManager.cpp @@ -37,6 +37,35 @@ using std::nothrow; ScreenManager* gScreenManager; +class ScreenChangeListener : public HWInterfaceListener { +public: + ScreenChangeListener(ScreenManager& manager, + Screen* screen); + +private: +virtual void ScreenChanged(HWInterface* interface); + + ScreenManager& fManager; + Screen* fScreen; +}; + + +ScreenChangeListener::ScreenChangeListener(ScreenManager& manager, + Screen* screen) + : + fManager(manager), + fScreen(screen) +{ +} + + +void +ScreenChangeListener::ScreenChanged(HWInterface* interface) +{ + fManager.ScreenChanged(fScreen); +} + + ScreenManager::ScreenManager() : BLooper("screen manager"), @@ -58,6 +87,7 @@ ScreenManager::~ScreenManager() screen_item* item = fScreenList.ItemAt(i); delete item->screen; + delete item->listener; delete item; } } @@ -151,6 +181,19 @@ ScreenManager::ReleaseScreens(ScreenList& list) } +void +ScreenManager::ScreenChanged(Screen* screen) +{ + BAutolock locker(this); + + for (int32 i = 0; i < fScreenList.CountItems(); i++) { + screen_item* item = fScreenList.ItemAt(i); + if (item->screen == screen) + item->owner->ScreenChanged(screen); + } +} + + void ScreenManager::_ScanDrivers() { @@ -193,12 +236,20 @@ ScreenManager::_AddHWInterface(HWInterface* interface) if (screen->Initialize() >= B_OK) { screen_item* item = new(nothrow) screen_item; + if (item != NULL) { item->screen = screen; item->owner = NULL; - if (fScreenList.AddItem(item)) - return item; + item->listener = new(nothrow) ScreenChangeListener(*this, screen); + if (item->listener != NULL + && interface->AddListener(item->listener)) { + if (fScreenList.AddItem(item)) + return item; + interface->RemoveListener(item->listener); + } + + delete item->listener; delete item; } } diff --git a/src/servers/app/ScreenManager.h b/src/servers/app/ScreenManager.h index 2c81dd1e1f..e4f58c27a0 100644 --- a/src/servers/app/ScreenManager.h +++ b/src/servers/app/ScreenManager.h @@ -12,10 +12,12 @@ #include #include + class BMessage; class DrawingEngine; class HWInterface; +class HWInterfaceListener; class Screen; @@ -27,6 +29,7 @@ class ScreenOwner { virtual ~ScreenOwner() {}; virtual void ScreenRemoved(Screen* screen) = 0; virtual void ScreenAdded(Screen* screen) = 0; + virtual void ScreenChanged(Screen* screen) = 0; virtual bool ReleaseScreen(Screen* screen) = 0; }; @@ -45,12 +48,15 @@ class ScreenManager : public BLooper { ScreenList& list); void ReleaseScreens(ScreenList& list); + void ScreenChanged(Screen* screen); + virtual void MessageReceived(BMessage* message); private: struct screen_item { - Screen* screen; - ScreenOwner* owner; + Screen* screen; + ScreenOwner* owner; + HWInterfaceListener* listener; }; void _ScanDrivers(); diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index bea94cae6a..bfe6a190ea 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -1096,6 +1096,19 @@ HWInterface::_NotifyFrameBufferChanged() } +void +HWInterface::_NotifyScreenChanged() +{ + BList listeners(fListeners); + int32 count = listeners.CountItems(); + for (int32 i = 0; i < count; i++) { + HWInterfaceListener* listener + = (HWInterfaceListener*)listeners.ItemAtFast(i); + listener->ScreenChanged(this); + } +} + + /*static*/ bool HWInterface::_IsValidMode(const display_mode& mode) { diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index 04515a1c3f..aaf79194a0 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -44,7 +44,11 @@ public: HWInterfaceListener(); virtual ~HWInterfaceListener(); - virtual void FrameBufferChanged() = 0; + virtual void FrameBufferChanged() {}; + // Informs a downstream DrawingEngine of a changed framebuffer. + + virtual void ScreenChanged(HWInterface* interface) {}; + // Informs an upstream client of a changed screen configuration. }; @@ -207,6 +211,7 @@ protected: const BPoint& offset); void _NotifyFrameBufferChanged(); + void _NotifyScreenChanged(); static bool _IsValidMode(const display_mode& mode);