* (tried to) implemented RootLayer::ResizeBy() and activated AS_SET_SCREEN_MODE again;

it works in the test environment, but I haven't yet tested it on real hardware.
* moved PrivateScreen.h to src/kits/interface/ - it's not used outside of that one.
* moved reading the color map from the BPrivateScreen constructor to the ColorMap()
  method.
* improved/cleaned server/client communication for the screen stuff a tiny bit.
* fixed the GetBitmap() method I implemented yesterday.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14908 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-11-14 11:01:02 +00:00
parent e84b16339c
commit a817d6ad5a
6 changed files with 438 additions and 429 deletions

View File

@ -1,96 +0,0 @@
//------------------------------------------------------------------------------
// Copyright (c) 2002-2005, Haiku
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: PrivateScreen.h
// Author: Stefano Ceccherini (burton666@libero.it)
// Description: BPrivateScreen is the class which does the real work
// for the proxy class BScreen (it interacts with the app server).
//------------------------------------------------------------------------------
#ifndef __PRIVATESCREEN_H
#define __PRIVATESCREEN_H
#include <Accelerant.h>
#include <GraphicsDefs.h>
struct screen_desc;
class BApplication;
class BWindow;
class BPrivateScreen {
// Constructor and destructor are private. Use the static methods
// CheckOut() and Return() instead.
public:
static BPrivateScreen* CheckOut(BWindow *win);
static BPrivateScreen* CheckOut(screen_id id);
static void Return(BPrivateScreen *screen);
status_t SetToNext();
color_space ColorSpace();
BRect Frame();
screen_id ID();
status_t WaitForRetrace(bigtime_t timeout);
uint8 IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha);
rgb_color ColorForIndex(const uint8 index);
uint8 InvertIndex(uint8 index);
const color_map *ColorMap();
status_t GetBitmap(BBitmap **bitmap, bool drawCursor, BRect *bound);
status_t ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bound);
rgb_color DesktopColor(uint32 index);
void SetDesktopColor(rgb_color, uint32, bool);
status_t ProposeMode(display_mode *target, const display_mode *low, const display_mode *high);
status_t GetModeList(display_mode **mode_list, uint32 *count);
status_t GetMode(uint32 workspace, display_mode *mode);
status_t SetMode(uint32 workspace, display_mode *mode, bool makeDefault);
status_t GetDeviceInfo(accelerant_device_info *info);
status_t GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high);
status_t GetTimingConstraints(display_timing_constraints *dtc);
status_t SetDPMS(uint32 dpmsState);
uint32 DPMSState();
uint32 DPMSCapabilites();
void* BaseAddress();
uint32 BytesPerRow();
status_t get_screen_desc(screen_desc *desc);
private:
color_map *fColorMap;
sem_id fRetraceSem;
bool fOwnsColorMap;
sem_id RetraceSemaphore();
BPrivateScreen();
~BPrivateScreen();
};
#endif // __PRIVATESCREEN_H

View File

@ -1,33 +1,22 @@
//------------------------------------------------------------------------------
// Copyright (c) 2002-2005, Haiku
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: PrivateScreen.cpp
// Author: Stefano Ceccherini (burton666@libero.it)
// Description: BPrivateScreen is the class which does the real work
// for the proxy class BScreen (it interacts with the app server).
//------------------------------------------------------------------------------
/*
* Copyright 2002-2005, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stefano Ceccherini (burton666@libero.it)
* Axel Dörfler, axeld@pinc-software.de
*/
/** BPrivateScreen is the class which does the real work for
* the proxy class BScreen (it interacts with the app server).
*/
#include "AppServerLink.h"
#include "PrivateScreen.h"
#include "ServerProtocol.h"
#include <Autolock.h>
#include <Bitmap.h>
#include <Locker.h>
#include <Window.h>
@ -56,35 +45,24 @@ static BLocker sScreenLock("screen lock");
using namespace BPrivate;
BPrivateScreen *
BPrivateScreen::CheckOut(BWindow *win)
BPrivateScreen::CheckOut(BWindow *window)
{
sScreenLock.Lock();
if (sScreen == NULL) {
// TODO: If we start supporting multiple monitors, we
// should return the right screen for the passed BWindow
sScreen = new BPrivateScreen();
}
sScreenLock.Unlock();
return sScreen;
// TODO: get screen ID from window!
return CheckOut(B_MAIN_SCREEN_ID);
}
BPrivateScreen *
BPrivateScreen::CheckOut(screen_id id)
{
sScreenLock.Lock();
BAutolock locker(sScreenLock);
if (sScreen == NULL) {
// TODO: If we start supporting multiple monitors, we
// should return the right object for the given screen_id
sScreen = new BPrivateScreen();
}
sScreenLock.Unlock();
return sScreen;
}
@ -136,8 +114,8 @@ BPrivateScreen::ID()
// TODO: Change this if we start supporting multiple screens
return B_MAIN_SCREEN_ID;
}
status_t
BPrivateScreen::WaitForRetrace(bigtime_t timeout)
{
@ -145,7 +123,7 @@ BPrivateScreen::WaitForRetrace(bigtime_t timeout)
// we are called. Cache the value then.
status_t status;
if (fRetraceSem < 0)
fRetraceSem = RetraceSemaphore();
fRetraceSem = _RetraceSemaphore();
do {
status = acquire_sem_etc(fRetraceSem, 1, B_RELATIVE_TIMEOUT, timeout);
@ -159,12 +137,14 @@ uint8
BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
{
// Looks like this check is necessary
if (red == B_TRANSPARENT_COLOR.red && green == B_TRANSPARENT_COLOR.green &&
blue == B_TRANSPARENT_COLOR.blue && alpha == B_TRANSPARENT_COLOR.alpha)
if (red == B_TRANSPARENT_COLOR.red
&& green == B_TRANSPARENT_COLOR.green
&& blue == B_TRANSPARENT_COLOR.blue
&& alpha == B_TRANSPARENT_COLOR.alpha)
return B_TRANSPARENT_8_BIT;
uint16 index = ((blue & 0xf8) << 7) | ((green & 0xf8) << 2) | (red >> 3);
if (fColorMap)
if (ColorMap())
return fColorMap->index_map[index];
return 0;
@ -174,7 +154,7 @@ BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
rgb_color
BPrivateScreen::ColorForIndex(const uint8 index)
{
if (fColorMap)
if (ColorMap())
return fColorMap->color_list[index];
return rgb_color();
@ -184,7 +164,7 @@ BPrivateScreen::ColorForIndex(const uint8 index)
uint8
BPrivateScreen::InvertIndex(uint8 index)
{
if (fColorMap)
if (ColorMap())
return fColorMap->inversion_map[index];
return 0;
@ -194,6 +174,29 @@ BPrivateScreen::InvertIndex(uint8 index)
const color_map *
BPrivateScreen::ColorMap()
{
if (fColorMap == NULL) {
BAutolock locker(sScreenLock);
if (fColorMap != NULL) {
// someone could have been faster than us
return fColorMap;
}
// TODO: BeOS R5 here gets the colormap pointer
// (with BApplication::ro_offset_to_ptr() ?)
// which is contained in a shared area created by the server.
BPrivate::AppServerLink link;
link.StartMessage(AS_SCREEN_GET_COLORMAP);
link.Attach<screen_id>(ID());
status_t status;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
fColorMap = (color_map *)malloc(sizeof(color_map));
fOwnsColorMap = true;
link.Read<color_map>(fColorMap);
}
}
return fColorMap;
}
@ -204,13 +207,19 @@ BPrivateScreen::GetBitmap(BBitmap **_bitmap, bool drawCursor, BRect *bounds)
if (_bitmap == NULL)
return B_BAD_VALUE;
BBitmap* bitmap = new (std::nothrow) BBitmap(Frame(), ColorSpace());
BRect rect;
if (bounds != NULL)
rect = *bounds;
else
rect = Frame();
BBitmap* bitmap = new (std::nothrow) BBitmap(rect, ColorSpace());
if (bitmap == NULL)
return B_NO_MEMORY;
status_t status = bitmap->InitCheck();
if (status == B_OK)
status = ReadBitmap(bitmap, drawCursor, bounds);
status = ReadBitmap(bitmap, drawCursor, &rect);
if (status != B_OK) {
delete bitmap;
return status;
@ -222,27 +231,27 @@ BPrivateScreen::GetBitmap(BBitmap **_bitmap, bool drawCursor, BRect *bounds)
status_t
BPrivateScreen::ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bound)
BPrivateScreen::ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bounds)
{
if (bitmap == NULL)
return B_BAD_VALUE;
BRect rect;
if (bound != NULL)
rect = *bound;
if (bounds != NULL)
rect = *bounds;
else
rect = Frame();
BPrivate::AppServerLink link;
link.StartMessage(AS_READ_BITMAP);
link.Attach<int32>(bitmap->get_server_token());
link.Attach<bool>(drawCursor);
link.Attach<BRect>(rect);
int32 code;
if (link.FlushWithReply(code) < B_OK || code != SERVER_TRUE)
return B_ERROR;
status_t status = B_ERROR;
if (link.FlushWithReply(status) < B_OK || status != B_OK)
return status;
return B_OK;
}
@ -258,7 +267,7 @@ BPrivateScreen::DesktopColor(uint32 workspace)
int32 code;
if (link.FlushWithReply(code) == B_OK
&& code == SERVER_TRUE)
&& code == B_OK)
link.Read<rgb_color>(&color);
return color;
@ -266,7 +275,8 @@ BPrivateScreen::DesktopColor(uint32 workspace)
void
BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace, bool makeDefault)
BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace,
bool makeDefault)
{
BPrivate::AppServerLink link;
@ -280,53 +290,57 @@ BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace, bool makeDefa
status_t
BPrivateScreen::ProposeMode(display_mode *target,
const display_mode *low, const display_mode *high)
const display_mode *low, const display_mode *high)
{
// We can't return B_BAD_VALUE here, because it's used to indicate
// that the mode returned is supported, but it doesn't fall
// within the limit (see ProposeMode() documentation)
if (target == NULL || low == NULL || high == NULL)
return B_ERROR;
BPrivate::AppServerLink link;
link.StartMessage(AS_PROPOSE_MODE);
link.Attach<screen_id>(ID());
link.Attach<display_mode>(*target);
link.Attach<display_mode>(*low);
link.Attach<display_mode>(*high);
int32 reply;
status_t status = B_ERROR;
if (link.FlushWithReply(reply) == B_OK && reply == SERVER_TRUE) {
link.Read<display_mode>(target);
// The status is important here. See documentation
link.Read<status_t>(&status);
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<display_mode>(target);
bool withinLimits;
link.Read<bool>(&withinLimits);
if (!withinLimits)
status = B_BAD_VALUE;
}
return status;
}
status_t
BPrivateScreen::GetModeList(display_mode **modeList, uint32 *count)
BPrivateScreen::GetModeList(display_mode **_modeList, uint32 *_count)
{
if (modeList == NULL || count == NULL)
if (_modeList == NULL || _count == NULL)
return B_BAD_VALUE;
status_t status = B_ERROR;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_MODE_LIST);
link.Attach<screen_id>(ID());
int32 reply;
if (link.FlushWithReply(reply) == B_OK && reply == SERVER_TRUE) {
link.Read<uint32>(count);
int32 size = *count * sizeof(display_mode);
*modeList = (display_mode *)malloc(size);
link.Read(*modeList, size);
// TODO: get status from app_server
status = B_OK;
status_t status = B_ERROR;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<uint32>(_count);
// TODO: this could get too big for the link
int32 size = *_count * sizeof(display_mode);
*_modeList = (display_mode *)malloc(size);
if (_modeList == NULL)
return B_NO_MEMORY;
link.Read(*_modeList, size);
}
return status;
}
@ -336,26 +350,19 @@ BPrivateScreen::GetMode(uint32 workspace, display_mode *mode)
{
if (mode == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_SCREEN_GET_MODE);
link.Attach<screen_id>(ID());
link.Attach<uint32>(workspace);
int32 code;
if (link.FlushWithReply(code) != B_OK
|| code != SERVER_TRUE)
return B_ERROR;
display_mode currentMode;
link.Read<display_mode>(&currentMode);
status_t status = B_ERROR;
link.Read<status_t>(&status);
if (status == B_OK && mode)
*mode = currentMode;
return status;
if (link.FlushWithReply(status) != B_OK
|| status != B_OK)
return status;
link.Read<display_mode>(mode);
return B_OK;
}
@ -364,18 +371,16 @@ BPrivateScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
{
if (mode == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_SCREEN_SET_MODE);
link.Attach<screen_id>(ID());
link.Attach<uint32>(workspace);
link.Attach<display_mode>(*mode);
link.Attach<bool>(makeDefault);
status_t status = B_ERROR;
int32 code;
if (link.FlushWithReply(code) == B_OK && code == SERVER_TRUE)
link.Read<status_t>(&status);
link.FlushWithReply(status);
return status;
}
@ -386,17 +391,18 @@ BPrivateScreen::GetDeviceInfo(accelerant_device_info *info)
{
if (info == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_ACCELERANT_INFO);
link.Attach<screen_id>(ID());
int32 code;
if (link.FlushWithReply(code) == B_OK && code == SERVER_TRUE) {
status_t status = B_ERROR;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<accelerant_device_info>(info);
return B_OK;
}
return B_ERROR;
return status;
}
@ -405,41 +411,40 @@ BPrivateScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *hig
{
if (mode == NULL || low == NULL || high == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_PIXEL_CLOCK_LIMITS);
link.Attach<screen_id>(ID());
link.Attach<display_mode>(*mode);
int32 code;
if (link.FlushWithReply(code) == B_OK && code == SERVER_TRUE) {
status_t status;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<uint32>(low);
link.Read<uint32>(high);
return B_OK;
}
return B_ERROR;
return status;
}
status_t
BPrivateScreen::GetTimingConstraints(display_timing_constraints *dtc)
BPrivateScreen::GetTimingConstraints(display_timing_constraints *constraints)
{
if (dtc == NULL)
if (constraints == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_TIMING_CONSTRAINTS);
link.Attach<screen_id>(ID());
int32 code;
if (link.FlushWithReply(code) == B_OK && code == SERVER_TRUE) {
link.Read<display_timing_constraints>(dtc);
status_t status = B_ERROR;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<display_timing_constraints>(constraints);
return B_OK;
}
return B_ERROR;
return status;
}
@ -450,11 +455,11 @@ BPrivateScreen::SetDPMS(uint32 dpmsState)
link.StartMessage(AS_SET_DPMS);
link.Attach<screen_id>(ID());
link.Attach<uint32>(dpmsState);
int32 reply;
if (link.FlushWithReply(reply) == B_OK && reply == SERVER_TRUE)
return B_OK;
return B_ERROR;
status_t status = B_ERROR;
link.FlushWithReply(status);
return status;
}
@ -462,14 +467,15 @@ uint32
BPrivateScreen::DPMSState()
{
uint32 state = 0;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_DPMS_STATE);
link.Attach<screen_id>(ID());
int32 reply;
if (link.FlushWithReply(reply) == B_OK && reply == SERVER_TRUE)
status_t status;
if (link.FlushWithReply(status) == B_OK && status == B_OK)
link.Read<uint32>(&state);
return state;
}
@ -478,14 +484,15 @@ uint32
BPrivateScreen::DPMSCapabilites()
{
uint32 capabilities = 0;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_DPMS_CAPABILITIES);
link.Attach<screen_id>(ID());
int32 reply;
if (link.FlushWithReply(reply) == B_OK && reply == SERVER_TRUE)
status_t status;
if (link.FlushWithReply(status) == B_OK && status == B_OK)
link.Read<uint32>(&capabilities);
return capabilities;
}
@ -496,7 +503,7 @@ BPrivateScreen::BaseAddress()
screen_desc desc;
if (get_screen_desc(&desc) == B_OK)
return desc.base_address;
return NULL;
}
@ -507,6 +514,7 @@ BPrivateScreen::BytesPerRow()
screen_desc desc;
if (get_screen_desc(&desc) == B_OK)
return desc.bytes_per_row;
return 0;
}
@ -528,20 +536,19 @@ BPrivateScreen::get_screen_desc(screen_desc *desc)
}
// private methods
// #pragma mark - private methods
sem_id
BPrivateScreen::RetraceSemaphore()
BPrivateScreen::_RetraceSemaphore()
{
sem_id id = B_BAD_SEM_ID;
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_RETRACE_SEMAPHORE);
link.Attach<screen_id>(ID());
int32 reply;
if (link.FlushWithReply(reply) == B_OK
&& reply == SERVER_TRUE)
link.Read<sem_id>(&id);
sem_id id = B_BAD_SEM_ID;
link.FlushWithReply(id);
return id;
}
@ -552,19 +559,6 @@ BPrivateScreen::BPrivateScreen()
fRetraceSem(-1),
fOwnsColorMap(false)
{
// TODO: BeOS R5 here gets the colormap pointer
// (with BApplication::ro_offset_to_ptr() ?)
// which is contained in a shared area created by the server.
BPrivate::AppServerLink link;
link.StartMessage(AS_SCREEN_GET_COLORMAP);
link.Attach<screen_id>(ID());
int32 reply;
if (link.FlushWithReply(reply) == B_OK && reply == SERVER_TRUE) {
fColorMap = (color_map *)malloc(sizeof(color_map));
fOwnsColorMap = true;
link.Read<color_map>(fColorMap);
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2002-2005, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stefano Ceccherini (burton666@libero.it)
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef _PRIVATE_SCREEN_H_
#define _PRIVATE_SCREEN_H_
#include <Accelerant.h>
#include <GraphicsDefs.h>
struct screen_desc;
struct color_map;
struct display_mode;
struct display_timing_constraints;
class BBitmap;
class BApplication;
class BWindow;
class BPrivateScreen {
// Constructor and destructor are private. Use the static methods
// CheckOut() and Return() instead.
public:
static BPrivateScreen* CheckOut(BWindow *window);
static BPrivateScreen* CheckOut(screen_id id);
static void Return(BPrivateScreen *screen);
status_t SetToNext();
color_space ColorSpace();
BRect Frame();
screen_id ID();
status_t WaitForRetrace(bigtime_t timeout);
uint8 IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha);
rgb_color ColorForIndex(const uint8 index);
uint8 InvertIndex(uint8 index);
const color_map *ColorMap();
status_t GetBitmap(BBitmap **bitmap, bool drawCursor, BRect *bounds);
status_t ReadBitmap(BBitmap *bitmap, bool drawCursor, BRect *bounds);
rgb_color DesktopColor(uint32 index);
void SetDesktopColor(rgb_color, uint32, bool);
status_t ProposeMode(display_mode *target, const display_mode *low,
const display_mode *high);
status_t GetModeList(display_mode **_modeList, uint32 *_count);
status_t GetMode(uint32 workspace, display_mode *mode);
status_t SetMode(uint32 workspace, display_mode *mode, bool makeDefault);
status_t GetDeviceInfo(accelerant_device_info *info);
status_t GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high);
status_t GetTimingConstraints(display_timing_constraints *constraints);
status_t SetDPMS(uint32 dpmsState);
uint32 DPMSState();
uint32 DPMSCapabilites();
void* BaseAddress();
uint32 BytesPerRow();
status_t get_screen_desc(screen_desc *desc);
private:
BPrivateScreen();
~BPrivateScreen();
sem_id _RetraceSemaphore();
private:
color_map *fColorMap;
sem_id fRetraceSem;
bool fOwnsColorMap;
};
#endif // _PRIVATE_SCREEN_H_

View File

@ -1,33 +1,20 @@
//------------------------------------------------------------------------------
// Copyright (c) 2003-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Screen.cpp
// Author: Stefano Ceccherini (burton666@libero.it)
// Description: BScreen lets you retrieve and change the display settings.
//------------------------------------------------------------------------------
/*
* Copyright 2003-2005, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stefano Ceccherini (burton666@libero.it)
* Axel Dörfler, axeld@pinc-software.de
*/
/** BScreen lets you retrieve and change the display settings. */
#include "PrivateScreen.h"
#include <Screen.h>
#include <Window.h>
#include <PrivateScreen.h>
/*! \brief Creates a BScreen object which represents the display with the given screen_id
\param id The screen_id of the screen to get.
@ -37,17 +24,17 @@
*/
BScreen::BScreen(screen_id id)
{
screen = BPrivateScreen::CheckOut(id);
fScreen = BPrivateScreen::CheckOut(id);
}
/*! \brief Creates a BScreen object which represents the display which contains
the given BWindow.
\param win A BWindow.
\param window A BWindow.
*/
BScreen::BScreen(BWindow *win)
BScreen::BScreen(BWindow *window)
{
screen = BPrivateScreen::CheckOut(win);
fScreen = BPrivateScreen::CheckOut(window);
}
@ -55,8 +42,8 @@ BScreen::BScreen(BWindow *win)
*/
BScreen::~BScreen()
{
if (screen != NULL)
BPrivateScreen::Return(screen);
if (fScreen != NULL)
BPrivateScreen::Return(fScreen);
}
@ -66,7 +53,7 @@ BScreen::~BScreen()
bool
BScreen::IsValid()
{
return (screen != NULL);
return fScreen != NULL;
}
@ -76,8 +63,8 @@ BScreen::IsValid()
status_t
BScreen::SetToNext()
{
if (screen != NULL)
return screen->SetToNext();
if (fScreen != NULL)
return fScreen->SetToNext();
return B_ERROR;
}
@ -89,8 +76,8 @@ BScreen::SetToNext()
color_space
BScreen::ColorSpace()
{
if (screen != NULL)
return screen->ColorSpace();
if (fScreen != NULL)
return fScreen->ColorSpace();
return B_NO_COLOR_SPACE;
}
@ -101,8 +88,8 @@ BScreen::ColorSpace()
BRect
BScreen::Frame()
{
if (screen != NULL)
return screen->Frame();
if (fScreen != NULL)
return fScreen->Frame();
return BRect(0, 0, 0, 0);
}
@ -116,8 +103,8 @@ BScreen::Frame()
screen_id
BScreen::ID()
{
if (screen != NULL)
return screen->ID();
if (fScreen != NULL)
return fScreen->ID();
return B_MAIN_SCREEN_ID;
}
@ -128,8 +115,8 @@ BScreen::ID()
status_t
BScreen::WaitForRetrace()
{
if (screen != NULL)
return screen->WaitForRetrace(B_INFINITE_TIMEOUT);
if (fScreen != NULL)
return fScreen->WaitForRetrace(B_INFINITE_TIMEOUT);
return B_ERROR;
}
@ -143,8 +130,8 @@ BScreen::WaitForRetrace()
status_t
BScreen::WaitForRetrace(bigtime_t timeout)
{
if (screen != NULL)
return screen->WaitForRetrace(timeout);
if (fScreen != NULL)
return fScreen->WaitForRetrace(timeout);
return B_ERROR;
}
@ -160,8 +147,8 @@ BScreen::WaitForRetrace(bigtime_t timeout)
uint8
BScreen::IndexForColor(uint8 r, uint8 g, uint8 b, uint8 a)
{
if (screen != NULL)
return screen->IndexForColor(r, g, b, a);
if (fScreen != NULL)
return fScreen->IndexForColor(r, g, b, a);
return 0;
}
@ -173,8 +160,8 @@ BScreen::IndexForColor(uint8 r, uint8 g, uint8 b, uint8 a)
rgb_color
BScreen::ColorForIndex(const uint8 index)
{
if (screen != NULL)
return screen->ColorForIndex(index);
if (fScreen != NULL)
return fScreen->ColorForIndex(index);
return rgb_color();
}
@ -186,8 +173,8 @@ BScreen::ColorForIndex(const uint8 index)
uint8
BScreen::InvertIndex(uint8 index)
{
if (screen != NULL)
return screen->InvertIndex(index);
if (fScreen != NULL)
return fScreen->InvertIndex(index);
return 0;
}
@ -198,8 +185,8 @@ BScreen::InvertIndex(uint8 index)
const color_map*
BScreen::ColorMap()
{
if (screen != NULL)
return screen->ColorMap();
if (fScreen != NULL)
return fScreen->ColorMap();
return NULL;
}
@ -213,8 +200,8 @@ BScreen::ColorMap()
status_t
BScreen::GetBitmap(BBitmap **screen_shot, bool draw_cursor, BRect *bound)
{
if (screen != NULL)
return screen->GetBitmap(screen_shot, draw_cursor, bound);
if (fScreen != NULL)
return fScreen->GetBitmap(screen_shot, draw_cursor, bound);
return B_ERROR;
}
@ -231,8 +218,8 @@ BScreen::GetBitmap(BBitmap **screen_shot, bool draw_cursor, BRect *bound)
status_t
BScreen::ReadBitmap(BBitmap *buffer, bool draw_cursor, BRect *bound)
{
if (screen != NULL)
return screen->ReadBitmap(buffer, draw_cursor, bound);
if (fScreen != NULL)
return fScreen->ReadBitmap(buffer, draw_cursor, bound);
return B_ERROR;
}
@ -243,8 +230,9 @@ BScreen::ReadBitmap(BBitmap *buffer, bool draw_cursor, BRect *bound)
rgb_color
BScreen::DesktopColor()
{
if (screen != NULL)
return screen->DesktopColor(B_ALL_WORKSPACES);
if (fScreen != NULL)
return fScreen->DesktopColor(B_ALL_WORKSPACES);
return rgb_color();
}
@ -256,8 +244,9 @@ BScreen::DesktopColor()
rgb_color
BScreen::DesktopColor(uint32 workspace)
{
if (screen != NULL)
return screen->DesktopColor(workspace);
if (fScreen != NULL)
return fScreen->DesktopColor(workspace);
return rgb_color();
}
@ -269,8 +258,8 @@ BScreen::DesktopColor(uint32 workspace)
void
BScreen::SetDesktopColor(rgb_color rgb, bool stick)
{
if (screen != NULL)
screen->SetDesktopColor(rgb, B_ALL_WORKSPACES, stick);
if (fScreen != NULL)
fScreen->SetDesktopColor(rgb, B_ALL_WORKSPACES, stick);
}
@ -282,8 +271,8 @@ BScreen::SetDesktopColor(rgb_color rgb, bool stick)
void
BScreen::SetDesktopColor(rgb_color rgb, uint32 index, bool stick)
{
if (screen != NULL)
screen->SetDesktopColor(rgb, index, stick);
if (fScreen != NULL)
fScreen->SetDesktopColor(rgb, index, stick);
}
@ -299,8 +288,8 @@ BScreen::SetDesktopColor(rgb_color rgb, uint32 index, bool stick)
status_t
BScreen::ProposeMode(display_mode *target, const display_mode *low, const display_mode *high)
{
if (screen != NULL)
return screen->ProposeMode(target, low, high);
if (fScreen != NULL)
return fScreen->ProposeMode(target, low, high);
return B_ERROR;
}
@ -316,8 +305,8 @@ BScreen::ProposeMode(display_mode *target, const display_mode *low, const displa
status_t
BScreen::GetModeList(display_mode **mode_list, uint32 *count)
{
if (screen != NULL)
return screen->GetModeList(mode_list, count);
if (fScreen != NULL)
return fScreen->GetModeList(mode_list, count);
return B_ERROR;
}
@ -330,8 +319,8 @@ BScreen::GetModeList(display_mode **mode_list, uint32 *count)
status_t
BScreen::GetMode(display_mode *mode)
{
if (screen != NULL)
return screen->GetMode(B_ALL_WORKSPACES, mode);
if (fScreen != NULL)
return fScreen->GetMode(B_ALL_WORKSPACES, mode);
return B_ERROR;
}
@ -344,8 +333,8 @@ BScreen::GetMode(display_mode *mode)
status_t
BScreen::GetMode(uint32 workspace, display_mode *mode)
{
if (screen != NULL)
return screen->GetMode(workspace, mode);
if (fScreen != NULL)
return fScreen->GetMode(workspace, mode);
return B_ERROR;
}
@ -358,8 +347,8 @@ BScreen::GetMode(uint32 workspace, display_mode *mode)
status_t
BScreen::SetMode(display_mode *mode, bool makeDefault)
{
if (screen != NULL)
return screen->SetMode(B_ALL_WORKSPACES, mode, makeDefault);
if (fScreen != NULL)
return fScreen->SetMode(B_ALL_WORKSPACES, mode, makeDefault);
return B_ERROR;
}
@ -373,8 +362,8 @@ BScreen::SetMode(display_mode *mode, bool makeDefault)
status_t
BScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
{
if (screen != NULL)
return screen->SetMode(workspace, mode, makeDefault);
if (fScreen != NULL)
return fScreen->SetMode(workspace, mode, makeDefault);
return B_ERROR;
}
@ -386,8 +375,8 @@ BScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
status_t
BScreen::GetDeviceInfo(accelerant_device_info *info)
{
if (screen != NULL)
return screen->GetDeviceInfo(info);
if (fScreen != NULL)
return fScreen->GetDeviceInfo(info);
return B_ERROR;
}
@ -402,8 +391,8 @@ BScreen::GetDeviceInfo(accelerant_device_info *info)
status_t
BScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
{
if (screen != NULL)
return screen->GetPixelClockLimits(mode, low, high);
if (fScreen != NULL)
return fScreen->GetPixelClockLimits(mode, low, high);
return B_ERROR;
}
@ -416,8 +405,8 @@ BScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
status_t
BScreen::GetTimingConstraints(display_timing_constraints *dtc)
{
if (screen != NULL)
return screen->GetTimingConstraints(dtc);
if (fScreen != NULL)
return fScreen->GetTimingConstraints(dtc);
return B_ERROR;
}
@ -434,8 +423,8 @@ BScreen::GetTimingConstraints(display_timing_constraints *dtc)
status_t
BScreen::SetDPMS(uint32 dpms_state)
{
if (screen != NULL)
return screen->SetDPMS(dpms_state);
if (fScreen != NULL)
return fScreen->SetDPMS(dpms_state);
return B_ERROR;
}
@ -445,8 +434,8 @@ BScreen::SetDPMS(uint32 dpms_state)
uint32
BScreen::DPMSState()
{
if (screen != NULL)
return screen->DPMSState();
if (fScreen != NULL)
return fScreen->DPMSState();
return B_ERROR;
}
@ -456,8 +445,8 @@ BScreen::DPMSState()
uint32
BScreen::DPMSCapabilites()
{
if (screen != NULL)
return screen->DPMSCapabilites();
if (fScreen != NULL)
return fScreen->DPMSCapabilites();
return B_ERROR;
}
@ -468,7 +457,7 @@ BScreen::DPMSCapabilites()
BPrivateScreen*
BScreen::private_screen()
{
return screen;
return fScreen;
}
@ -503,8 +492,8 @@ BScreen::BScreen(const BScreen &screen)
void*
BScreen::BaseAddress()
{
if (screen != NULL)
return screen->BaseAddress();
if (fScreen != NULL)
return fScreen->BaseAddress();
return NULL;
}
@ -514,7 +503,7 @@ BScreen::BaseAddress()
uint32
BScreen::BytesPerRow()
{
if (screen != NULL)
return screen->BytesPerRow();
if (fScreen != NULL)
return fScreen->BytesPerRow();
return 0;
}

View File

@ -295,7 +295,27 @@ RootLayer::MoveBy(float x, float y)
void
RootLayer::ResizeBy(float x, float y)
{
// TODO: implement
if (x == 0 && y == 0)
return;
// TODO: we should be able to update less here
//BRect previous = fFrame;
fFrame.right += x;
fFrame.bottom += y;
fFullVisible2.Set(Bounds());
fVisible2.Set(Bounds());
BRegion region(fFrame);
MarkForRebuild(region);
TriggerRebuild();
//region.Exclude(previous);
MarkForRedraw(region);
TriggerRedraw();
}

View File

@ -2000,9 +2000,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
// actually this isn't still enough as different workspaces can
// have different display_modes
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Attach<display_mode>(mode);
fLink.Attach<status_t>(B_OK);
fLink.Flush();
break;
}
@ -2030,11 +2029,17 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
// TODO: lock RootLayer, set mode and tell it to update it's frame and all clipping
// optionally put this into a message and let the root layer thread handle it.
// status_t ret = fDesktop->ScreenAt(0)->SetMode(mode);
status_t ret = B_ERROR;
RootLayer* rootLayer = fDesktop->ActiveRootLayer();
rootLayer->Lock();
status_t status = fDesktop->ScreenAt(0)->SetMode(mode);
if (status == B_OK) {
BRect bounds = rootLayer->Bounds();
rootLayer->ResizeBy(mode.virtual_width - 1 - bounds.Width(),
mode.virtual_height - 1 - bounds.Height());
}
rootLayer->Unlock();
fLink.StartMessage(SERVER_TRUE);
fLink.Attach<status_t>(ret);
fLink.StartMessage(status);
fLink.Flush();
break;
}
@ -2050,16 +2055,20 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
link.Read<display_mode>(&low);
link.Read<display_mode>(&high);
status_t status = fDesktop->GetHWInterface()->ProposeMode(&target, &low, &high);
// TODO: We always return SERVER_TRUE and put the real
// error code in the message. FIX this.
fLink.StartMessage(SERVER_TRUE);
fLink.Attach<display_mode>(target);
fLink.Attach<status_t>(status);
// ProposeMode() returns B_BAD_VALUE to hint that the candidate is
// not within the given limits (but is supported)
if (status == B_OK || status == B_BAD_VALUE) {
fLink.StartMessage(B_OK);
fLink.Attach<display_mode>(target);
fLink.Attach<bool>(status == B_OK);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_MODE_LIST:
{
screen_id id;
@ -2068,14 +2077,15 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
display_mode* modeList;
uint32 count;
if (fDesktop->GetHWInterface()->GetModeList(&modeList, &count) == B_OK) {
fLink.StartMessage(SERVER_TRUE);
status_t status = fDesktop->GetHWInterface()->GetModeList(&modeList, &count);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(count);
fLink.Attach(modeList, sizeof(display_mode) * count);
delete[] modeList;
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(status);
fLink.Flush();
break;
@ -2087,14 +2097,14 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
screen_id id;
link.Read<screen_id>(&id);
const color_map *colorMap = SystemColorMap();
if (colorMap != NULL) {
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Attach<color_map>(*colorMap);
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
@ -2103,82 +2113,89 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
{
STRACE(("ServerApp %s: get desktop color\n", Signature()));
uint32 workspaceIndex = 0;
uint32 workspaceIndex;
link.Read<uint32>(&workspaceIndex);
// ToDo: for some reason, we currently get "1" as no. of workspace
workspaceIndex = 0;
// ToDo: locking is probably wrong - why the hell is there no (safe)
// way to get to the workspace object directly?
RootLayer *root = fDesktop->ActiveRootLayer();
root->Lock();
Workspace *workspace = root->WorkspaceAt(workspaceIndex);
Workspace *workspace;
// we're nice to our children (and also take the default case
// into account which asks for the current workspace)
if (workspaceIndex > (uint32)root->WorkspaceCount())
workspace = root->ActiveWorkspace();
else
workspace = root->WorkspaceAt(workspaceIndex);
if (workspace != NULL) {
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Attach<rgb_color>(workspace->BGColor().GetColor32());
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(B_ERROR);
fLink.Flush();
root->Unlock();
break;
}
case AS_GET_ACCELERANT_INFO:
{
STRACE(("ServerApp %s: get accelerant info\n", Signature()));
// We aren't using the screen_id for now...
screen_id id;
link.Read<screen_id>(&id);
accelerant_device_info accelerantInfo;
// TODO: I wonder if there should be a "desktop" lock...
if (fDesktop->GetHWInterface()->GetDeviceInfo(&accelerantInfo) == B_OK) {
fLink.StartMessage(SERVER_TRUE);
status_t status = fDesktop->GetHWInterface()->GetDeviceInfo(&accelerantInfo);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<accelerant_device_info>(accelerantInfo);
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_RETRACE_SEMAPHORE:
{
STRACE(("ServerApp %s: get retrace semaphore\n", Signature()));
// We aren't using the screen_id for now...
screen_id id;
link.Read<screen_id>(&id);
sem_id semaphore = fDesktop->GetHWInterface()->RetraceSemaphore();
fLink.StartMessage(SERVER_TRUE);
fLink.Attach<sem_id>(semaphore);
fLink.StartMessage(semaphore);
fLink.Flush();
break;
}
case AS_GET_TIMING_CONSTRAINTS:
{
STRACE(("ServerApp %s: get timing constraints\n", Signature()));
// We aren't using the screen_id for now...
screen_id id;
link.Read<screen_id>(&id);
display_timing_constraints constraints;
if (fDesktop->GetHWInterface()->GetTimingConstraints(&constraints) == B_OK) {
fLink.StartMessage(SERVER_TRUE);
status_t status = fDesktop->GetHWInterface()->GetTimingConstraints(
&constraints);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<display_timing_constraints>(constraints);
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_PIXEL_CLOCK_LIMITS:
{
STRACE(("ServerApp %s: get pixel clock limits\n", Signature()));
@ -2187,87 +2204,87 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
link.Read<screen_id>(&id);
display_mode mode;
link.Read<display_mode>(&mode);
uint32 low, high;
if (fDesktop->GetHWInterface()->GetPixelClockLimits(&mode, &low, &high) == B_OK) {
fLink.StartMessage(SERVER_TRUE);
status_t status = fDesktop->GetHWInterface()->GetPixelClockLimits(&mode,
&low, &high);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(low);
fLink.Attach<uint32>(high);
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SET_DPMS:
{
STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature()));
screen_id id;
link.Read<screen_id>(&id);
uint32 mode;
link.Read<uint32>(&mode);
if (fDesktop->GetHWInterface()->SetDPMSMode(mode) == B_OK)
fLink.StartMessage(SERVER_TRUE);
else
fLink.StartMessage(SERVER_FALSE);
status_t status = fDesktop->GetHWInterface()->SetDPMSMode(mode);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_DPMS_STATE:
{
STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature()));
screen_id id;
link.Read<screen_id>(&id);
uint32 state = fDesktop->GetHWInterface()->DPMSMode();
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(state);
fLink.Flush();
break;
}
case AS_GET_DPMS_CAPABILITIES:
{
STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature()));
screen_id id;
link.Read<screen_id>(&id);
uint32 capabilities = fDesktop->GetHWInterface()->DPMSCapabilities();
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(capabilities);
fLink.Flush();
break;
}
case AS_READ_BITMAP:
{
STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature()));
int32 bitmapToken;
link.Read<int32>(&bitmapToken);
bool drawCursor = true;
link.Read<bool>(&drawCursor);
BRect bounds;
link.Read<BRect>(&bounds);
ServerBitmap *bitmap = FindBitmap(bitmapToken);
if (bitmap != NULL) {
fLink.StartMessage(SERVER_TRUE);
fLink.StartMessage(B_OK);
// TODO: Implement for real
} else
fLink.StartMessage(SERVER_FALSE);
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
default:
printf("ServerApp %s received unhandled message code %ld\n",
Signature(), code);