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);