First baby step to a restructured app_server:
- introduced new ScreenManager and VirtualScreen classes - removed screen handling from RootLayer - removed multiple screen/root layer stuff from Desktop, it's now using a VirtualScreen object instead git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13686 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
97021af901
commit
fd5bec1e48
@ -31,6 +31,7 @@
|
||||
#include "RegistrarDefs.h"
|
||||
#include "RGBColor.h"
|
||||
#include "RootLayer.h"
|
||||
#include "ScreenManager.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerCursor.h"
|
||||
#include "ServerProtocol.h"
|
||||
@ -165,6 +166,8 @@ AppServer::AppServer() :
|
||||
if (LoadColorSet(SERVER_SETTINGS_DIR COLOR_SETTINGS_NAME, &gGUIColorSet) != B_OK)
|
||||
gGUIColorSet.SetToDefaults();
|
||||
|
||||
gScreenManager = new ScreenManager();
|
||||
|
||||
// Set up the Desktop
|
||||
gDesktop = new Desktop();
|
||||
gDesktop->Init();
|
||||
|
@ -56,9 +56,6 @@
|
||||
|
||||
Desktop::Desktop()
|
||||
: fWinBorderList(64),
|
||||
fRootLayerList(2),
|
||||
fActiveRootLayer(NULL),
|
||||
fScreenList(2),
|
||||
fActiveScreen(NULL),
|
||||
fMouseMode(B_NORMAL_MOUSE),
|
||||
fFFMouseMode(false)
|
||||
@ -88,104 +85,24 @@ Desktop::~Desktop()
|
||||
for (int32 i = 0; WinBorder *border = (WinBorder *)fWinBorderList.ItemAt(i); i++)
|
||||
delete border;
|
||||
|
||||
for (int32 i = 0; RootLayer *rootLayer = (RootLayer *)fRootLayerList.ItemAt(i); i++)
|
||||
delete rootLayer;
|
||||
|
||||
for (int32 i = 0; Screen *screen = (Screen *)fScreenList.ItemAt(i); i++)
|
||||
delete screen;
|
||||
delete fRootLayer;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::Init()
|
||||
{
|
||||
HWInterface *interface = NULL;
|
||||
fVirtualScreen.RestoreConfiguration(*this);
|
||||
|
||||
// Eventually we will loop through drivers until
|
||||
// one can't initialize in order to support multiple monitors.
|
||||
// For now, we'll just load one and be done with it.
|
||||
|
||||
bool initDrivers = true;
|
||||
while (initDrivers) {
|
||||
// TODO: temporary workaround, fActiveScreen will be removed
|
||||
fActiveScreen = fVirtualScreen.ScreenAt(0);
|
||||
|
||||
#if USE_ACCELERANT
|
||||
interface = new AccelerantHWInterface();
|
||||
#else
|
||||
interface = new ViewHWInterface();
|
||||
#endif
|
||||
// TODO: add user identity to the name
|
||||
char name[32];
|
||||
sprintf(name, "RootLayer %d", 1);
|
||||
|
||||
_AddGraphicsCard(interface);
|
||||
initDrivers = false;
|
||||
}
|
||||
|
||||
if (fScreenList.CountItems() < 1) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
InitMode();
|
||||
|
||||
SetActiveRootLayerByIndex(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::_AddGraphicsCard(HWInterface* interface)
|
||||
{
|
||||
Screen *screen = new Screen(interface, fScreenList.CountItems() + 1);
|
||||
// The interface is now owned by the screen
|
||||
|
||||
if (screen->Initialize() >= B_OK && fScreenList.AddItem((void*)screen)) {
|
||||
// TODO: be careful of screen initialization - monitor may not support 640x480
|
||||
screen->SetMode(800, 600, B_RGB32, 60.f);
|
||||
} else
|
||||
delete screen;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::InitMode()
|
||||
{
|
||||
// this is init mode for n-SS.
|
||||
fActiveScreen = (Screen *)fScreenList.ItemAt(0);
|
||||
|
||||
for (int32 i = 0; i < fScreenList.CountItems(); i++) {
|
||||
Screen *screen = (Screen *)fScreenList.ItemAt(i);
|
||||
|
||||
char name[32];
|
||||
sprintf(name, "RootLayer %ld", i + 1);
|
||||
|
||||
RootLayer *rootLayer = new RootLayer(name, 4, this, GetDisplayDriver());
|
||||
rootLayer->SetScreens(&screen, 1, 1);
|
||||
rootLayer->RunThread();
|
||||
|
||||
fRootLayerList.AddItem(rootLayer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Methods for multiple monitors.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
inline void
|
||||
Desktop::SetActiveRootLayerByIndex(int32 listIndex)
|
||||
{
|
||||
RootLayer *rootLayer = RootLayerAt(listIndex);
|
||||
|
||||
if (rootLayer != NULL)
|
||||
SetActiveRootLayer(rootLayer);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
Desktop::SetActiveRootLayer(RootLayer *rootLayer)
|
||||
{
|
||||
if (fActiveRootLayer == rootLayer)
|
||||
return;
|
||||
|
||||
fActiveRootLayer = rootLayer;
|
||||
fRootLayer = new RootLayer(name, 4, this, GetDisplayDriver());
|
||||
fRootLayer->RunThread();
|
||||
}
|
||||
|
||||
|
||||
@ -541,29 +458,3 @@ Desktop::FFMouseMode(void) const
|
||||
return fMouseMode;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::PrintToStream(void)
|
||||
{
|
||||
printf("RootLayer List:\n=======\n");
|
||||
|
||||
for (int32 i = 0; i < fRootLayerList.CountItems(); i++) {
|
||||
printf("\t%s\n", ((RootLayer*)fRootLayerList.ItemAt(i))->Name());
|
||||
((RootLayer*)fRootLayerList.ItemAt(i))->PrintToStream();
|
||||
printf("-------\n");
|
||||
}
|
||||
|
||||
printf("=======\nActive RootLayer: %s\n",
|
||||
fActiveRootLayer ? fActiveRootLayer->Name() : "NULL");
|
||||
// printf("Active WinBorder: %s\n", fActiveWinBorder? fActiveWinBorder->Name(): "NULL");
|
||||
|
||||
printf("Screen List:\n");
|
||||
for (int32 i = 0; i < fScreenList.CountItems(); i++)
|
||||
printf("\t%ld\n", ((Screen*)fScreenList.ItemAt(i))->ScreenNumber());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::PrintVisibleInRootLayerNo(int32 no)
|
||||
{
|
||||
}
|
||||
|
@ -11,13 +11,16 @@
|
||||
#define _DESKTOP_H_
|
||||
|
||||
|
||||
#include "ScreenManager.h"
|
||||
#include "ServerScreen.h"
|
||||
#include "VirtualScreen.h"
|
||||
|
||||
#include <InterfaceDefs.h>
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
#include <Menu.h>
|
||||
#include <Autolock.h>
|
||||
|
||||
#include "ServerScreen.h"
|
||||
|
||||
class BMessage;
|
||||
|
||||
@ -32,7 +35,7 @@ namespace BPrivate {
|
||||
};
|
||||
|
||||
|
||||
class Desktop : public BLocker {
|
||||
class Desktop : public BLocker, public ScreenOwner {
|
||||
public:
|
||||
// startup methods
|
||||
Desktop();
|
||||
@ -40,41 +43,22 @@ class Desktop : public BLocker {
|
||||
|
||||
void Init();
|
||||
|
||||
// 1-BigScreen or n-SmallScreens
|
||||
void InitMode();
|
||||
|
||||
// Methods for multiple monitors.
|
||||
inline Screen* ScreenAt(int32 index) const
|
||||
{ return static_cast<Screen *>(fScreenList.ItemAt(index)); }
|
||||
inline int32 ScreenCount() const
|
||||
{ return fScreenList.CountItems(); }
|
||||
{ return fActiveScreen; }
|
||||
inline Screen* ActiveScreen() const
|
||||
{ return fActiveScreen; }
|
||||
inline RootLayer* ActiveRootLayer() const { return fRootLayer; }
|
||||
|
||||
void SetActiveRootLayerByIndex(int32 index);
|
||||
void SetActiveRootLayer(RootLayer* layer);
|
||||
inline RootLayer* RootLayerAt(int32 index)
|
||||
{ return static_cast<RootLayer *>(fRootLayerList.ItemAt(index)); }
|
||||
RootLayer* ActiveRootLayer() const
|
||||
{ return fActiveRootLayer;}
|
||||
int32 ActiveRootLayerIndex() const
|
||||
{
|
||||
int32 rootLayerCount = CountRootLayers();
|
||||
|
||||
for (int32 i = 0; i < rootLayerCount; i++) {
|
||||
if (fActiveRootLayer == (RootLayer *)fRootLayerList.ItemAt(i))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline int32 CountRootLayers() const
|
||||
{ return fRootLayerList.CountItems(); }
|
||||
virtual void ScreenRemoved(Screen* screen) {}
|
||||
virtual void ScreenAdded(Screen* screen) {}
|
||||
virtual bool ReleaseScreen(Screen* screen) { return false; }
|
||||
|
||||
const ::VirtualScreen& VirtualScreen() const { return fVirtualScreen; }
|
||||
inline DisplayDriver* GetDisplayDriver() const
|
||||
{ return ScreenAt(0)->GetDisplayDriver(); }
|
||||
{ return fVirtualScreen.DisplayDriver(); }
|
||||
inline HWInterface* GetHWInterface() const
|
||||
{ return ScreenAt(0)->GetHWInterface(); }
|
||||
{ return fVirtualScreen.HWInterface(); }
|
||||
|
||||
// Methods for layer(WinBorder) manipulation.
|
||||
void AddWinBorder(WinBorder *winBorder);
|
||||
@ -112,21 +96,13 @@ class Desktop : public BLocker {
|
||||
void SetFFMouseMode(const mode_mouse &value);
|
||||
mode_mouse FFMouseMode() const;
|
||||
|
||||
// Debugging methods
|
||||
void PrintToStream();
|
||||
void PrintVisibleInRootLayerNo(int32 no);
|
||||
|
||||
private:
|
||||
void _AddGraphicsCard(HWInterface* interface);
|
||||
|
||||
::VirtualScreen fVirtualScreen;
|
||||
BList fWinBorderList;
|
||||
|
||||
BList fRootLayerList;
|
||||
RootLayer* fActiveRootLayer;
|
||||
|
||||
BList fScreenList;
|
||||
|
||||
RootLayer* fRootLayer;
|
||||
Screen* fActiveScreen;
|
||||
|
||||
|
||||
scroll_bar_info fScrollBarInfo;
|
||||
menu_info fMenuInfo;
|
||||
mode_mouse fMouseMode;
|
||||
|
@ -3,7 +3,8 @@ SubDir OBOS_TOP src servers app ;
|
||||
AddResources app_server : app_server.rdef ;
|
||||
|
||||
UseLibraryHeaders agg png zlib ;
|
||||
UsePrivateHeaders app interface [ FDirName servers app ] ;
|
||||
UsePrivateHeaders app interface shared [ FDirName servers app ] ;
|
||||
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing Painter ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing Painter drawing_modes ] ;
|
||||
@ -83,10 +84,12 @@ Server app_server :
|
||||
ServerApp.cpp
|
||||
ServerWindow.cpp
|
||||
DecorManager.cpp
|
||||
ScreenManager.cpp
|
||||
|
||||
# DisplayDriver Classes
|
||||
$(VIEW_DRIVER_SOURCES)
|
||||
|
||||
VirtualScreen.cpp
|
||||
BBitmapBuffer.cpp
|
||||
BitmapHWInterface.cpp
|
||||
DefaultDecorator.cpp
|
||||
|
@ -88,15 +88,6 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
|
||||
fThreadID(B_ERROR),
|
||||
fListenPort(-1),
|
||||
|
||||
fScreenPtrList(32),
|
||||
fRows(0),
|
||||
fColumns(0),
|
||||
|
||||
fScreenWidth(0),
|
||||
fScreenHeight(0),
|
||||
fColorSpace(B_RGB32),
|
||||
fFrequency(60.0),
|
||||
|
||||
fButtons(0),
|
||||
fLastMousePosition(0.0, 0.0),
|
||||
// fMovingWindow(false),
|
||||
@ -172,6 +163,8 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
|
||||
#if ON_SCREEN_DEBUGGING_INFO
|
||||
DebugInfoManager::Default()->SetRootLayer(this);
|
||||
#endif
|
||||
|
||||
fFrame = desktop->VirtualScreen().Frame();
|
||||
}
|
||||
|
||||
|
||||
@ -1026,73 +1019,6 @@ RootLayer::WinBorderAt(const BPoint& pt) const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RootLayer::SetScreens(Screen *screens[], int32 rows, int32 columns)
|
||||
{
|
||||
// NOTE: All screens *must* have the same resolution
|
||||
|
||||
// TODO: This function is badly named. Appearently, it
|
||||
// adjusts the root layers frame rectangle, taking the information
|
||||
// from the first screen in its list. However, a Screen object
|
||||
// has actually now a different meaning. It manages access to
|
||||
// the hardware and *owns* the HWInterface instance.
|
||||
// This means there is going to be one Screen object per physical
|
||||
// screen attached (unless I misunderstood how it was intended).
|
||||
// A workspace needs to be attached to a screen
|
||||
// and then on workspace activation, the appropriate updating
|
||||
// needs to occur. The workspace tells its screen to configure
|
||||
// to the workspaces mode, and then someone takes care of
|
||||
// telling RootLayer to adjust itself and all other layers regions.
|
||||
|
||||
uint16 width, height;
|
||||
uint32 colorSpace;
|
||||
float frequency;
|
||||
screens[0]->GetMode(width, height, colorSpace, frequency);
|
||||
|
||||
fFrame.Set(0, 0, width * columns - 1, height * rows - 1);
|
||||
fRows = rows;
|
||||
fColumns = columns;
|
||||
fScreenWidth = width;
|
||||
fScreenHeight = height;
|
||||
}
|
||||
|
||||
|
||||
Screen **
|
||||
RootLayer::Screens()
|
||||
{
|
||||
return (Screen**)fScreenPtrList.Items();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RootLayer::SetScreenMode(int32 width, int32 height, uint32 colorSpace, float frequency)
|
||||
{
|
||||
if (fScreenWidth == width && fScreenHeight == height
|
||||
&& fColorSpace == colorSpace && frequency == fFrequency)
|
||||
return true;
|
||||
|
||||
// NOTE: Currently, we have only one screen in that list.
|
||||
// Before I changed it, this function would only accept modes
|
||||
// that each of the (potentially multiple) screens can accept.
|
||||
// However, I didn't really know what this gives in practice.
|
||||
// We should re-think this when we really do support multiple monitors.
|
||||
// For now, this function could potentially set the first couple of
|
||||
// screens to the new mode, and fail to do so for the rest of them.
|
||||
|
||||
status_t ret = B_ERROR;
|
||||
for (int i = 0; i < fScreenPtrList.CountItems(); i++) {
|
||||
Screen *screen = static_cast<Screen *>(fScreenPtrList.ItemAt(i));
|
||||
|
||||
ret = screen->SetMode(width, height, colorSpace, frequency);
|
||||
if (ret < B_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
SetScreens(Screens(), fRows, fColumns);
|
||||
|
||||
return ret >= B_OK;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Workspace related methods
|
||||
//---------------------------------------------------------------------------
|
||||
@ -1825,17 +1751,14 @@ RootLayer::SetEventMaskLayer(Layer *lay, uint32 mask, uint32 options)
|
||||
if (!lay)
|
||||
return false;
|
||||
|
||||
bool returnValue = true;
|
||||
bool returnValue = true;
|
||||
|
||||
Lock();
|
||||
|
||||
if (fEventMaskLayer && fEventMaskLayer != lay)
|
||||
{
|
||||
if (fEventMaskLayer && fEventMaskLayer != lay) {
|
||||
fprintf(stderr, "WARNING: fEventMaskLayer already set and different than the required one!\n");
|
||||
returnValue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fEventMaskLayer = lay;
|
||||
// TODO: use this mask and options!
|
||||
}
|
||||
@ -1849,22 +1772,21 @@ RootLayer::SetEventMaskLayer(Layer *lay, uint32 mask, uint32 options)
|
||||
void
|
||||
RootLayer::LayerRemoved(Layer* layer)
|
||||
{
|
||||
if (layer == fEventMaskLayer) {
|
||||
if (layer == fEventMaskLayer)
|
||||
fEventMaskLayer = NULL;
|
||||
}
|
||||
if (layer == fLastMouseMoved) {
|
||||
|
||||
if (layer == fLastMouseMoved)
|
||||
fLastMouseMoved = NULL;
|
||||
}
|
||||
if (layer == fMouseTargetWinBorder) {
|
||||
|
||||
if (layer == fMouseTargetWinBorder)
|
||||
fMouseTargetWinBorder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RootLayer::SetDragMessage(BMessage* msg)
|
||||
{
|
||||
if (fDragMessage)
|
||||
{
|
||||
if (fDragMessage) {
|
||||
delete fDragMessage;
|
||||
fDragMessage = NULL;
|
||||
}
|
||||
@ -1880,26 +1802,6 @@ RootLayer::DragMessage(void) const
|
||||
return fDragMessage;
|
||||
}
|
||||
|
||||
// DEBUG methods
|
||||
|
||||
void
|
||||
RootLayer::PrintToStream()
|
||||
{
|
||||
printf("\nRootLayer '%s' internals:\n", Name());
|
||||
printf("Screen list:\n");
|
||||
for(int32 i=0; i<fScreenPtrList.CountItems(); i++)
|
||||
printf("\t%ld\n", ((Screen*)fScreenPtrList.ItemAt(i))->ScreenNumber());
|
||||
|
||||
printf("Screen rows: %ld\nScreen columns: %ld\n", fRows, fColumns);
|
||||
printf("Resolution for all Screens: %ldx%ldx%ld\n", fScreenWidth, fScreenHeight, fColorSpace);
|
||||
printf("Workspace list:\n");
|
||||
for(int32 i=0; i<fWsCount; i++)
|
||||
{
|
||||
printf("\t~~~Workspace: %ld\n", ((Workspace*)fWorkspace[i])->ID());
|
||||
((Workspace*)fWorkspace[i])->PrintToStream();
|
||||
printf("~~~~~~~~\n");
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE methods
|
||||
|
||||
|
@ -106,12 +106,6 @@ public:
|
||||
void SetWorkspacesLayer(Layer* layer) { fWorkspacesLayer = layer; }
|
||||
Layer* WorkspacesLayer() const { return fWorkspacesLayer; }
|
||||
|
||||
void SetScreens(Screen *screen[], int32 rows, int32 columns);
|
||||
Screen** Screens(void);
|
||||
bool SetScreenMode(int32 width, int32 height, uint32 colorspace, float frequency);
|
||||
int32 ScreenRows(void) const { return fRows; }
|
||||
int32 ScreenColumns(void) const { return fColumns; }
|
||||
|
||||
void SetBGColor(const RGBColor &col);
|
||||
RGBColor BGColor(void) const;
|
||||
|
||||
@ -141,8 +135,6 @@ public:
|
||||
|
||||
virtual void Draw(const BRect &r);
|
||||
|
||||
// Debug methods
|
||||
void PrintToStream(void);
|
||||
thread_id LockingThread() { return fAllRegionsLock.LockingThread(); }
|
||||
|
||||
BRegion fRedrawReg;
|
||||
@ -195,15 +187,6 @@ friend class Desktop;
|
||||
thread_id fThreadID;
|
||||
port_id fListenPort;
|
||||
|
||||
BList fScreenPtrList;
|
||||
int32 fRows;
|
||||
int32 fColumns;
|
||||
|
||||
int32 fScreenWidth;
|
||||
int32 fScreenHeight;
|
||||
uint32 fColorSpace;
|
||||
float fFrequency;
|
||||
|
||||
int32 fButtons;
|
||||
BPoint fLastMousePosition;
|
||||
bool fMovingWindow;
|
||||
|
193
src/servers/app/ScreenManager.cpp
Normal file
193
src/servers/app/ScreenManager.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
|
||||
/** Manages all available physical screens */
|
||||
|
||||
|
||||
#include "ScreenManager.h"
|
||||
#include "ServerScreen.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Entry.h>
|
||||
#include <NodeMonitor.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
#ifdef __HAIKU__
|
||||
# define USE_ACCELERANT 1
|
||||
#else
|
||||
# define USE_ACCELERANT 0
|
||||
#endif
|
||||
|
||||
#if USE_ACCELERANT
|
||||
# include "AccelerantHWInterface.h"
|
||||
#else
|
||||
# include "ViewHWInterface.h"
|
||||
#endif
|
||||
|
||||
|
||||
ScreenManager* gScreenManager;
|
||||
|
||||
|
||||
ScreenManager::ScreenManager()
|
||||
: BLooper("screen manager"),
|
||||
fScreenList(4)
|
||||
{
|
||||
_ScanDrivers();
|
||||
|
||||
// turn on node monitoring the graphics driver directory
|
||||
BEntry entry("/dev/graphics");
|
||||
node_ref nodeRef;
|
||||
if (entry.InitCheck() == B_OK && entry.GetNodeRef(&nodeRef) == B_OK)
|
||||
watch_node(&nodeRef, B_WATCH_DIRECTORY, this);
|
||||
}
|
||||
|
||||
|
||||
ScreenManager::~ScreenManager()
|
||||
{
|
||||
for (int32 i = 0; i < fScreenList.CountItems(); i++) {
|
||||
screen_item* item = fScreenList.ItemAt(i);
|
||||
|
||||
delete item->screen;
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Screen*
|
||||
ScreenManager::ScreenAt(int32 index) const
|
||||
{
|
||||
if (!IsLocked())
|
||||
debugger("Called ScreenManager::ScreenAt() without lock!");
|
||||
|
||||
screen_item* item = fScreenList.ItemAt(index);
|
||||
if (item != NULL)
|
||||
return item->screen;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ScreenManager::CountScreens() const
|
||||
{
|
||||
if (!IsLocked())
|
||||
debugger("Called ScreenManager::CountScreens() without lock!");
|
||||
|
||||
return fScreenList.CountItems();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ScreenManager::AcquireScreens(ScreenOwner* owner, int32* wishList,
|
||||
int32 wishCount, bool force, ScreenList& list)
|
||||
{
|
||||
BAutolock locker(this);
|
||||
int32 added = 0;
|
||||
|
||||
// ToDo: don't ignore the wish list
|
||||
|
||||
for (int32 i = 0; i < fScreenList.CountItems(); i++) {
|
||||
screen_item *item = fScreenList.ItemAt(i);
|
||||
|
||||
if (item->owner == NULL && list.AddItem(item->screen)) {
|
||||
item->owner = owner;
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
return added > 0 ? B_OK : B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScreenManager::ReleaseScreens(ScreenList& list)
|
||||
{
|
||||
BAutolock locker(this);
|
||||
|
||||
for (int32 i = 0; i < fScreenList.CountItems(); i++) {
|
||||
screen_item *item = fScreenList.ItemAt(i);
|
||||
|
||||
for (int32 j = 0; j < list.CountItems(); i++) {
|
||||
Screen* screen = list.ItemAt(j);
|
||||
|
||||
if (item->screen == screen)
|
||||
item->owner = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScreenManager::_ScanDrivers()
|
||||
{
|
||||
HWInterface *interface = NULL;
|
||||
|
||||
// Eventually we will loop through drivers until
|
||||
// one can't initialize in order to support multiple monitors.
|
||||
// For now, we'll just load one and be done with it.
|
||||
|
||||
// ToDo: to make monitoring the driver directory useful, we need more
|
||||
// power and data here, and should do the scanning on our own
|
||||
|
||||
bool initDrivers = true;
|
||||
while (initDrivers) {
|
||||
|
||||
#if USE_ACCELERANT
|
||||
interface = new AccelerantHWInterface();
|
||||
#else
|
||||
interface = new ViewHWInterface();
|
||||
#endif
|
||||
|
||||
_AddHWInterface(interface);
|
||||
initDrivers = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScreenManager::_AddHWInterface(HWInterface* interface)
|
||||
{
|
||||
Screen* screen = new(nothrow) Screen(interface, fScreenList.CountItems() + 1);
|
||||
if (screen == NULL) {
|
||||
delete interface;
|
||||
return;
|
||||
}
|
||||
|
||||
// The interface is now owned by the screen
|
||||
|
||||
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;
|
||||
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
delete screen;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScreenManager::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
// ToDo: handle notification
|
||||
break;
|
||||
|
||||
default:
|
||||
BHandler::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
62
src/servers/app/ScreenManager.h
Normal file
62
src/servers/app/ScreenManager.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
#ifndef SCREEN_MANAGER_H
|
||||
#define SCREEN_MANAGER_H
|
||||
|
||||
|
||||
#include <Looper.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
class BMessage;
|
||||
|
||||
class DisplayDriver;
|
||||
class HWInterface;
|
||||
class Screen;
|
||||
|
||||
|
||||
typedef BObjectList<Screen> ScreenList;
|
||||
|
||||
|
||||
class ScreenOwner {
|
||||
public:
|
||||
virtual void ScreenRemoved(Screen* screen) = 0;
|
||||
virtual void ScreenAdded(Screen* screen) = 0;
|
||||
|
||||
virtual bool ReleaseScreen(Screen* screen) = 0;
|
||||
};
|
||||
|
||||
|
||||
class ScreenManager : public BLooper {
|
||||
public:
|
||||
ScreenManager();
|
||||
virtual ~ScreenManager();
|
||||
|
||||
Screen* ScreenAt(int32 index) const;
|
||||
int32 CountScreens() const;
|
||||
|
||||
status_t AcquireScreens(ScreenOwner* owner, int32* wishList,
|
||||
int32 wishCount, bool force, ScreenList& list);
|
||||
void ReleaseScreens(ScreenList& list);
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
void _ScanDrivers();
|
||||
void _AddHWInterface(HWInterface* interface);
|
||||
|
||||
struct screen_item {
|
||||
Screen* screen;
|
||||
ScreenOwner* owner;
|
||||
};
|
||||
|
||||
BObjectList<screen_item> fScreenList;
|
||||
};
|
||||
|
||||
extern ScreenManager *gScreenManager;
|
||||
|
||||
#endif /* SCREEN_MANAGER_H */
|
@ -130,7 +130,6 @@ Screen::GetMode(uint16 &width, uint16 &height, uint32 &colorspace,
|
||||
float &frequency) const
|
||||
{
|
||||
display_mode mode;
|
||||
|
||||
fHWInterface->GetMode(&mode);
|
||||
|
||||
width = mode.virtual_width;
|
||||
@ -141,6 +140,16 @@ Screen::GetMode(uint16 &width, uint16 &height, uint32 &colorspace,
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
Screen::Frame() const
|
||||
{
|
||||
display_mode mode;
|
||||
fHWInterface->GetMode(&mode);
|
||||
|
||||
return BRect(0, 0, mode.virtual_width - 1, mode.virtual_height - 1);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Screen::_FindMode(uint16 width, uint16 height, uint32 colorspace,
|
||||
float frequency, display_mode* mode) const
|
||||
|
@ -40,7 +40,8 @@ class Screen {
|
||||
uint16 &height,
|
||||
uint32 &colorspace,
|
||||
float &frequency) const;
|
||||
|
||||
BRect Frame() const;
|
||||
|
||||
inline int32 ScreenNumber() const
|
||||
{ return fID; }
|
||||
|
||||
|
146
src/servers/app/VirtualScreen.cpp
Normal file
146
src/servers/app/VirtualScreen.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
|
||||
|
||||
#include "VirtualScreen.h"
|
||||
|
||||
#include <DisplayDriver.h>
|
||||
#include <HWInterface.h>
|
||||
#include <Desktop.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
VirtualScreen::VirtualScreen()
|
||||
:
|
||||
fScreenList(4, true),
|
||||
fDisplayDriver(NULL),
|
||||
fHWInterface(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
VirtualScreen::~VirtualScreen()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VirtualScreen::RestoreConfiguration(Desktop& desktop)
|
||||
{
|
||||
// Copy current Desktop settings
|
||||
//fSettings = desktop.Settings();
|
||||
|
||||
ScreenList list;
|
||||
status_t status = gScreenManager->AcquireScreens(&desktop, NULL, 0, false, list);
|
||||
if (status < B_OK) {
|
||||
// TODO: we would try again here with force == true
|
||||
return status;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < list.CountItems(); i++) {
|
||||
Screen* screen = list.ItemAt(i);
|
||||
|
||||
AddScreen(screen);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VirtualScreen::StoreConfiguration(BMessage& settings)
|
||||
{
|
||||
// TODO: implement me
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VirtualScreen::AddScreen(Screen* screen)
|
||||
{
|
||||
screen_item* item = new(nothrow) screen_item;
|
||||
if (item == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
item->screen = screen;
|
||||
|
||||
BMessage settings;
|
||||
if (_FindConfiguration(screen, settings) == B_OK) {
|
||||
// TODO: read from settings!
|
||||
} else {
|
||||
// TODO: more intelligent standard mode (monitor preference, desktop default, ...)
|
||||
screen->SetMode(800, 600, B_RGB32, 60.f);
|
||||
}
|
||||
|
||||
// TODO: this works only for single screen configurations
|
||||
fDisplayDriver = screen->GetDisplayDriver();
|
||||
fHWInterface = screen->GetHWInterface();
|
||||
fFrame = screen->Frame();
|
||||
|
||||
fScreenList.AddItem(item);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VirtualScreen::RemoveScreen(Screen* screen)
|
||||
{
|
||||
// not implemented yet (config changes when running)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns the smallest frame that spans over all screens
|
||||
*/
|
||||
BRect
|
||||
VirtualScreen::Frame() const
|
||||
{
|
||||
return fFrame;
|
||||
}
|
||||
|
||||
|
||||
Screen*
|
||||
VirtualScreen::ScreenAt(int32 index) const
|
||||
{
|
||||
screen_item* item = fScreenList.ItemAt(index);
|
||||
if (item != NULL)
|
||||
return item->screen;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
VirtualScreen::ScreenFrameAt(int32 index) const
|
||||
{
|
||||
screen_item* item = fScreenList.ItemAt(index);
|
||||
if (item != NULL)
|
||||
return item->frame;
|
||||
|
||||
return BRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
VirtualScreen::CountScreens() const
|
||||
{
|
||||
return fScreenList.CountItems();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VirtualScreen::_FindConfiguration(Screen* screen, BMessage& settings)
|
||||
{
|
||||
// TODO: we probably want to identify the resolution by connected monitor,
|
||||
// and not the display driver used...
|
||||
return B_ERROR;
|
||||
}
|
||||
|
66
src/servers/app/VirtualScreen.h
Normal file
66
src/servers/app/VirtualScreen.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
#ifndef VIRTUAL_SCREEN_H
|
||||
#define VIRTUAL_SCREEN_H
|
||||
|
||||
|
||||
#include "ScreenManager.h"
|
||||
|
||||
#include <Message.h>
|
||||
|
||||
class Desktop;
|
||||
class DisplayDriver;
|
||||
class HWInterface;
|
||||
|
||||
|
||||
class VirtualScreen {
|
||||
public:
|
||||
VirtualScreen();
|
||||
~VirtualScreen();
|
||||
|
||||
::DisplayDriver* DisplayDriver() const
|
||||
{ return fDisplayDriver; }
|
||||
// TODO: can we have a multiplexing HWInterface as well?
|
||||
// If not, this would need to be hidden, and only made
|
||||
// available for the Screen class
|
||||
::HWInterface* HWInterface() const
|
||||
{ return fHWInterface; }
|
||||
|
||||
status_t RestoreConfiguration(Desktop& desktop);
|
||||
status_t StoreConfiguration(BMessage& settings);
|
||||
|
||||
status_t AddScreen(Screen* screen);
|
||||
status_t RemoveScreen(Screen* screen);
|
||||
|
||||
BRect Frame() const;
|
||||
|
||||
// TODO: we need to play with a real multi-screen configuration to
|
||||
// figure out the specifics here - possibly in the test environment?
|
||||
void SetScreenFrame(int32 index, BRect frame);
|
||||
|
||||
Screen* ScreenAt(int32 index) const;
|
||||
BRect ScreenFrameAt(int32 index) const;
|
||||
int32 CountScreens() const;
|
||||
|
||||
private:
|
||||
status_t _FindConfiguration(Screen* screen, BMessage& settings);
|
||||
|
||||
struct screen_item {
|
||||
Screen* screen;
|
||||
BRect frame;
|
||||
// TODO: do we want to have a different color per screen as well?
|
||||
};
|
||||
|
||||
BMessage fSettings;
|
||||
BRect fFrame;
|
||||
BObjectList<screen_item> fScreenList;
|
||||
::DisplayDriver* fDisplayDriver;
|
||||
::HWInterface* fHWInterface;
|
||||
};
|
||||
|
||||
#endif /* VIRTUAL_SCREEN_H */
|
Loading…
Reference in New Issue
Block a user